summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md29
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml56
-rw-r--r--.github/workflows/android_builds.yml6
-rw-r--r--.github/workflows/linux_builds.yml2
-rw-r--r--.github/workflows/windows_builds.yml4
-rw-r--r--COPYRIGHT.txt18
-rw-r--r--DONORS.md2
-rw-r--r--SConstruct64
-rw-r--r--core/SCsub1
-rw-r--r--core/config/engine.cpp14
-rw-r--r--core/config/engine.h5
-rw-r--r--core/config/project_settings.cpp11
-rw-r--r--core/core_bind.cpp297
-rw-r--r--core/core_bind.h61
-rw-r--r--core/core_constants.cpp6
-rw-r--r--core/crypto/aes_context.h6
-rw-r--r--core/crypto/crypto.h10
-rw-r--r--core/crypto/crypto_core.h2
-rw-r--r--core/crypto/hashing_context.h6
-rw-r--r--core/debugger/local_debugger.cpp4
-rw-r--r--core/debugger/remote_debugger_peer.h4
-rw-r--r--core/input/input.cpp15
-rw-r--r--core/input/input.h3
-rw-r--r--core/input/input_event.cpp173
-rw-r--r--core/input/input_event.h36
-rw-r--r--core/input/input_map.cpp14
-rw-r--r--core/io/config_file.h8
-rw-r--r--core/io/dir_access.cpp418
-rw-r--r--core/io/dir_access.h147
-rw-r--r--core/io/dtls_server.cpp2
-rw-r--r--core/io/dtls_server.h4
-rw-r--r--core/io/file_access.cpp676
-rw-r--r--core/io/file_access.h198
-rw-r--r--core/io/file_access_compressed.cpp34
-rw-r--r--core/io/file_access_compressed.h30
-rw-r--r--core/io/file_access_encrypted.cpp44
-rw-r--r--core/io/file_access_encrypted.h18
-rw-r--r--core/io/file_access_memory.cpp24
-rw-r--r--core/io/file_access_memory.h18
-rw-r--r--core/io/file_access_network.cpp40
-rw-r--r--core/io/file_access_network.h40
-rw-r--r--core/io/file_access_pack.cpp42
-rw-r--r--core/io/file_access_pack.h32
-rw-r--r--core/io/file_access_zip.cpp28
-rw-r--r--core/io/file_access_zip.h11
-rw-r--r--core/io/http_client.h6
-rw-r--r--core/io/image.cpp44
-rw-r--r--core/io/image.h9
-rw-r--r--core/io/image_loader.h2
-rw-r--r--core/io/ip.cpp91
-rw-r--r--core/io/ip.h6
-rw-r--r--core/io/json.cpp36
-rw-r--r--core/io/json.h10
-rw-r--r--core/io/logger.cpp9
-rw-r--r--core/io/logger.h2
-rw-r--r--core/io/marshalls.cpp24
-rw-r--r--core/io/marshalls.h6
-rw-r--r--core/io/multiplayer_api.cpp314
-rw-r--r--core/io/multiplayer_api.h51
-rw-r--r--core/io/net_socket.h4
-rw-r--r--core/io/packed_data_container.cpp4
-rw-r--r--core/io/packed_data_container.h4
-rw-r--r--core/io/packet_peer.h4
-rw-r--r--core/io/packet_peer_dtls.cpp2
-rw-r--r--core/io/pck_packer.cpp6
-rw-r--r--core/io/pck_packer.h6
-rw-r--r--core/io/resource.cpp2
-rw-r--r--core/io/resource.h6
-rw-r--r--core/io/resource_format_binary.cpp34
-rw-r--r--core/io/resource_format_binary.h2
-rw-r--r--core/io/resource_importer.h4
-rw-r--r--core/io/resource_loader.cpp44
-rw-r--r--core/io/resource_loader.h4
-rw-r--r--core/io/resource_saver.cpp20
-rw-r--r--core/io/resource_saver.h4
-rw-r--r--core/io/stream_peer.cpp4
-rw-r--r--core/io/stream_peer.h8
-rw-r--r--core/io/tcp_server.h4
-rw-r--r--core/io/translation_loader_po.cpp2
-rw-r--r--core/io/translation_loader_po.h2
-rw-r--r--core/io/udp_server.h4
-rw-r--r--core/io/xml_parser.cpp101
-rw-r--r--core/io/xml_parser.h9
-rw-r--r--core/io/zip_io.cpp4
-rw-r--r--core/io/zip_io.h2
-rw-r--r--core/math/a_star.h10
-rw-r--r--core/math/aabb.cpp2
-rw-r--r--core/math/basis.cpp55
-rw-r--r--core/math/basis.h20
-rw-r--r--core/math/bvh_logic.inc14
-rw-r--r--core/math/bvh_public.inc46
-rw-r--r--core/math/bvh_refit.inc4
-rw-r--r--core/math/bvh_structs.inc1
-rw-r--r--core/math/bvh_tree.h15
-rw-r--r--core/math/camera_matrix.cpp14
-rw-r--r--core/math/camera_matrix.h10
-rw-r--r--core/math/color.cpp16
-rw-r--r--core/math/color.h1
-rw-r--r--core/math/convex_hull.cpp2290
-rw-r--r--core/math/convex_hull.h112
-rw-r--r--core/math/delaunay_3d.h2
-rw-r--r--core/math/dynamic_bvh.cpp5
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/expression.h6
-rw-r--r--core/math/face3.cpp6
-rw-r--r--core/math/face3.h6
-rw-r--r--core/math/math_fieldwise.cpp8
-rw-r--r--core/math/math_funcs.h62
-rw-r--r--core/math/plane.cpp2
-rw-r--r--core/math/quat.cpp232
-rw-r--r--core/math/quat.h240
-rw-r--r--core/math/quaternion.cpp232
-rw-r--r--core/math/quaternion.h238
-rw-r--r--core/math/quick_hull.cpp2
-rw-r--r--core/math/random_number_generator.h6
-rw-r--r--core/math/rect2.cpp8
-rw-r--r--core/math/rect2.h4
-rw-r--r--core/math/transform.cpp212
-rw-r--r--core/math/transform.h232
-rw-r--r--core/math/transform_2d.cpp11
-rw-r--r--core/math/transform_2d.h2
-rw-r--r--core/math/transform_3d.cpp215
-rw-r--r--core/math/transform_3d.h232
-rw-r--r--core/math/triangle_mesh.cpp2
-rw-r--r--core/math/triangle_mesh.h6
-rw-r--r--core/math/vector2.cpp26
-rw-r--r--core/math/vector2.h9
-rw-r--r--core/math/vector3.cpp20
-rw-r--r--core/math/vector3.h4
-rw-r--r--core/math/vector3i.cpp9
-rw-r--r--core/math/vector3i.h1
-rw-r--r--core/object/class_db.cpp62
-rw-r--r--core/object/class_db.h9
-rw-r--r--core/object/object.cpp61
-rw-r--r--core/object/object.h84
-rw-r--r--core/object/object_id.h2
-rw-r--r--core/object/ref_counted.cpp138
-rw-r--r--core/object/ref_counted.h297
-rw-r--r--core/object/reference.cpp132
-rw-r--r--core/object/reference.h297
-rw-r--r--core/object/script_language.cpp12
-rw-r--r--core/object/script_language.h53
-rw-r--r--core/object/undo_redo.cpp24
-rw-r--r--core/object/undo_redo.h4
-rw-r--r--core/os/dir_access.cpp416
-rw-r--r--core/os/dir_access.h143
-rw-r--r--core/os/file_access.cpp675
-rw-r--r--core/os/file_access.h198
-rw-r--r--core/os/keyboard.cpp6
-rw-r--r--core/os/keyboard.h2
-rw-r--r--core/os/main_loop.h2
-rw-r--r--core/os/os.cpp42
-rw-r--r--core/os/os.h34
-rw-r--r--core/os/time.cpp433
-rw-r--r--core/os/time.h109
-rw-r--r--core/register_core_types.cpp5
-rw-r--r--core/string/translation_po.cpp2
-rw-r--r--core/string/ustring.cpp67
-rw-r--r--core/string/ustring.h4
-rw-r--r--core/templates/bin_sorted_array.h181
-rw-r--r--core/templates/command_queue_mt.cpp29
-rw-r--r--core/templates/command_queue_mt.h161
-rw-r--r--core/templates/hash_map.h6
-rw-r--r--core/templates/oa_hash_map.h4
-rw-r--r--core/templates/paged_allocator.h8
-rw-r--r--core/variant/array.cpp6
-rw-r--r--core/variant/callable.cpp11
-rw-r--r--core/variant/method_ptrcall.h4
-rw-r--r--core/variant/type_info.h4
-rw-r--r--core/variant/typed_array.h8
-rw-r--r--core/variant/variant.cpp241
-rw-r--r--core/variant/variant.h20
-rw-r--r--core/variant/variant_call.cpp81
-rw-r--r--core/variant/variant_construct.cpp34
-rw-r--r--core/variant/variant_internal.h83
-rw-r--r--core/variant/variant_op.cpp66
-rw-r--r--core/variant/variant_parser.cpp31
-rw-r--r--core/variant/variant_parser.h2
-rw-r--r--core/variant/variant_setget.cpp52
-rw-r--r--core/variant/variant_utility.cpp2
-rw-r--r--doc/classes/@GlobalScope.xml13
-rw-r--r--doc/classes/AABB.xml2
-rw-r--r--doc/classes/AESContext.xml2
-rw-r--r--doc/classes/AStar.xml2
-rw-r--r--doc/classes/AStar2D.xml2
-rw-r--r--doc/classes/AcceptDialog.xml2
-rw-r--r--doc/classes/AnimatedSprite2D.xml4
-rw-r--r--doc/classes/AnimatedSprite3D.xml4
-rw-r--r--doc/classes/Animation.xml8
-rw-r--r--doc/classes/AnimationNode.xml118
-rw-r--r--doc/classes/AnimationNodeAnimation.xml2
-rw-r--r--doc/classes/AnimationNodeStateMachineTransition.xml2
-rw-r--r--doc/classes/AnimationPlayer.xml3
-rw-r--r--doc/classes/AnimationTrackEditPlugin.xml2
-rw-r--r--doc/classes/AnimationTree.xml6
-rw-r--r--doc/classes/Area2D.xml14
-rw-r--r--doc/classes/Area3D.xml14
-rw-r--r--doc/classes/Array.xml10
-rw-r--r--doc/classes/ArrayMesh.xml3
-rw-r--r--doc/classes/AudioEffectCompressor.xml2
-rw-r--r--doc/classes/AudioEffectInstance.xml2
-rw-r--r--doc/classes/AudioEffectSpectrumAnalyzer.xml12
-rw-r--r--doc/classes/AudioStreamGenerator.xml9
-rw-r--r--doc/classes/AudioStreamGeneratorPlayback.xml10
-rw-r--r--doc/classes/AudioStreamPlayback.xml2
-rw-r--r--doc/classes/AudioStreamPlayer.xml2
-rw-r--r--doc/classes/AudioStreamPlayer2D.xml2
-rw-r--r--doc/classes/AudioStreamPlayer3D.xml4
-rw-r--r--doc/classes/AudioStreamSample.xml6
-rw-r--r--doc/classes/BakedLightmap.xml81
-rw-r--r--doc/classes/BakedLightmapData.xml65
-rw-r--r--doc/classes/BaseMaterial3D.xml7
-rw-r--r--doc/classes/Basis.xml12
-rw-r--r--doc/classes/BitMap.xml6
-rw-r--r--doc/classes/Bone2D.xml69
-rw-r--r--doc/classes/CPUParticles2D.xml2
-rw-r--r--doc/classes/Camera3D.xml13
-rw-r--r--doc/classes/CameraFeed.xml2
-rw-r--r--doc/classes/CharFXTransform.xml4
-rw-r--r--doc/classes/CharacterBody2D.xml132
-rw-r--r--doc/classes/CharacterBody3D.xml115
-rw-r--r--doc/classes/CodeEdit.xml327
-rw-r--r--doc/classes/CollisionObject3D.xml20
-rw-r--r--doc/classes/Color.xml11
-rw-r--r--doc/classes/ConcavePolygonShape3D.xml2
-rw-r--r--doc/classes/ConfigFile.xml2
-rw-r--r--doc/classes/Control.xml265
-rw-r--r--doc/classes/Crypto.xml2
-rw-r--r--doc/classes/DTLSServer.xml2
-rw-r--r--doc/classes/Directory.xml10
-rw-r--r--doc/classes/DisplayServer.xml8
-rw-r--r--doc/classes/EditorDebuggerPlugin.xml2
-rw-r--r--doc/classes/EditorExportPlugin.xml2
-rw-r--r--doc/classes/EditorFeatureProfile.xml2
-rw-r--r--doc/classes/EditorImportPlugin.xml52
-rw-r--r--doc/classes/EditorInspectorPlugin.xml94
-rw-r--r--doc/classes/EditorInterface.xml6
-rw-r--r--doc/classes/EditorNode3DGizmo.xml138
-rw-r--r--doc/classes/EditorNode3DGizmoPlugin.xml162
-rw-r--r--doc/classes/EditorPaths.xml43
-rw-r--r--doc/classes/EditorPlugin.xml522
-rw-r--r--doc/classes/EditorProperty.xml20
-rw-r--r--doc/classes/EditorResourceConversionPlugin.xml2
-rw-r--r--doc/classes/EditorResourcePicker.xml81
-rw-r--r--doc/classes/EditorResourcePreview.xml6
-rw-r--r--doc/classes/EditorResourcePreviewGenerator.xml18
-rw-r--r--doc/classes/EditorSceneImporter.xml2
-rw-r--r--doc/classes/EditorScenePostImport.xml22
-rw-r--r--doc/classes/EditorScript.xml2
-rw-r--r--doc/classes/EditorScriptPicker.xml21
-rw-r--r--doc/classes/EditorSettings.xml9
-rw-r--r--doc/classes/EditorSpinSlider.xml2
-rw-r--r--doc/classes/EditorSyntaxHighlighter.xml2
-rw-r--r--doc/classes/EditorTranslationParserPlugin.xml16
-rw-r--r--doc/classes/EncodedObjectAsID.xml2
-rw-r--r--doc/classes/Engine.xml1
-rw-r--r--doc/classes/Environment.xml2
-rw-r--r--doc/classes/Expression.xml2
-rw-r--r--doc/classes/File.xml18
-rw-r--r--doc/classes/FileSystemDock.xml34
-rw-r--r--doc/classes/GIProbe.xml63
-rw-r--r--doc/classes/GIProbeData.xml92
-rw-r--r--doc/classes/GPUParticles2D.xml16
-rw-r--r--doc/classes/GPUParticles3D.xml8
-rw-r--r--doc/classes/GeometryInstance3D.xml26
-rw-r--r--doc/classes/GraphNode.xml83
-rw-r--r--doc/classes/HMACContext.xml2
-rw-r--r--doc/classes/HTTPClient.xml2
-rw-r--r--doc/classes/HashingContext.xml2
-rw-r--r--doc/classes/IP.xml20
-rw-r--r--doc/classes/Input.xml5
-rw-r--r--doc/classes/InputEventAction.xml2
-rw-r--r--doc/classes/InputEventWithModifiers.xml12
-rw-r--r--doc/classes/JSON.xml3
-rw-r--r--doc/classes/JSONParseResult.xml2
-rw-r--r--doc/classes/JSONParser.xml2
-rw-r--r--doc/classes/JavaClass.xml2
-rw-r--r--doc/classes/JavaScript.xml43
-rw-r--r--doc/classes/JavaScriptObject.xml42
-rw-r--r--doc/classes/KinematicBody2D.xml176
-rw-r--r--doc/classes/KinematicBody3D.xml188
-rw-r--r--doc/classes/KinematicCollision2D.xml6
-rw-r--r--doc/classes/KinematicCollision3D.xml6
-rw-r--r--doc/classes/Light3D.xml2
-rw-r--r--doc/classes/LightmapGI.xml81
-rw-r--r--doc/classes/LightmapGIData.xml65
-rw-r--r--doc/classes/Lightmapper.xml2
-rw-r--r--doc/classes/Listener3D.xml4
-rw-r--r--doc/classes/MeshDataTool.xml6
-rw-r--r--doc/classes/MeshLibrary.xml8
-rw-r--r--doc/classes/MultiMesh.xml8
-rw-r--r--doc/classes/MultiplayerAPI.xml10
-rw-r--r--doc/classes/Mutex.xml2
-rw-r--r--doc/classes/NavigationServer3D.xml2
-rw-r--r--doc/classes/Node.xml95
-rw-r--r--doc/classes/Node2D.xml6
-rw-r--r--doc/classes/Node3D.xml23
-rw-r--r--doc/classes/Node3DGizmo.xml2
-rw-r--r--doc/classes/OS.xml85
-rw-r--r--doc/classes/Object.xml4
-rw-r--r--doc/classes/PCKPacker.xml2
-rw-r--r--doc/classes/PackedDataContainerRef.xml4
-rw-r--r--doc/classes/PackedVector3Array.xml2
-rw-r--r--doc/classes/PacketPeer.xml2
-rw-r--r--doc/classes/ParticlesMaterial.xml2
-rw-r--r--doc/classes/PhysicalBone2D.xml49
-rw-r--r--doc/classes/PhysicalBone3D.xml40
-rw-r--r--doc/classes/PhysicsBody2D.xml40
-rw-r--r--doc/classes/PhysicsBody3D.xml80
-rw-r--r--doc/classes/PhysicsDirectBodyState2D.xml2
-rw-r--r--doc/classes/PhysicsDirectBodyState3D.xml4
-rw-r--r--doc/classes/PhysicsServer2D.xml21
-rw-r--r--doc/classes/PhysicsServer3D.xml62
-rw-r--r--doc/classes/PhysicsShapeQueryParameters2D.xml2
-rw-r--r--doc/classes/PhysicsShapeQueryParameters3D.xml4
-rw-r--r--doc/classes/PhysicsShapeQueryResult2D.xml2
-rw-r--r--doc/classes/PhysicsShapeQueryResult3D.xml2
-rw-r--r--doc/classes/PhysicsTestMotionResult2D.xml2
-rw-r--r--doc/classes/PinJoint2D.xml2
-rw-r--r--doc/classes/PinJoint3D.xml2
-rw-r--r--doc/classes/PrimitiveMesh.xml2
-rw-r--r--doc/classes/ProjectSettings.xml70
-rw-r--r--doc/classes/Quat.xml308
-rw-r--r--doc/classes/Quaternion.xml308
-rw-r--r--doc/classes/RDAttachmentFormat.xml2
-rw-r--r--doc/classes/RDPipelineColorBlendState.xml2
-rw-r--r--doc/classes/RDPipelineColorBlendStateAttachment.xml2
-rw-r--r--doc/classes/RDPipelineDepthStencilState.xml2
-rw-r--r--doc/classes/RDPipelineMultisampleState.xml2
-rw-r--r--doc/classes/RDPipelineRasterizationState.xml2
-rw-r--r--doc/classes/RDSamplerState.xml2
-rw-r--r--doc/classes/RDShaderFile.xml4
-rw-r--r--doc/classes/RDShaderSource.xml2
-rw-r--r--doc/classes/RDTextureFormat.xml2
-rw-r--r--doc/classes/RDTextureView.xml2
-rw-r--r--doc/classes/RDUniform.xml2
-rw-r--r--doc/classes/RDVertexAttribute.xml2
-rw-r--r--doc/classes/RandomNumberGenerator.xml2
-rw-r--r--doc/classes/RefCounted.xml43
-rw-r--r--doc/classes/Reference.xml43
-rw-r--r--doc/classes/ReflectionProbe.xml2
-rw-r--r--doc/classes/RemoteTransform3D.xml4
-rw-r--r--doc/classes/RenderingServer.xml100
-rw-r--r--doc/classes/Resource.xml5
-rw-r--r--doc/classes/ResourceFormatLoader.xml14
-rw-r--r--doc/classes/ResourceFormatSaver.xml10
-rw-r--r--doc/classes/ResourceImporter.xml2
-rw-r--r--doc/classes/ResourceSaver.xml2
-rw-r--r--doc/classes/RigidBody2D.xml34
-rw-r--r--doc/classes/RigidBody3D.xml59
-rw-r--r--doc/classes/SceneState.xml2
-rw-r--r--doc/classes/SceneTree.xml1
-rw-r--r--doc/classes/SceneTreeTimer.xml2
-rw-r--r--doc/classes/ScriptEditor.xml34
-rw-r--r--doc/classes/ScriptEditorBase.xml9
-rw-r--r--doc/classes/ScrollContainer.xml9
-rw-r--r--doc/classes/Semaphore.xml2
-rw-r--r--doc/classes/Skeleton2D.xml54
-rw-r--r--doc/classes/Skeleton3D.xml57
-rw-r--r--doc/classes/SkeletonIK3D.xml6
-rw-r--r--doc/classes/SkeletonModification2D.xml104
-rw-r--r--doc/classes/SkeletonModification2DCCDIK.xml170
-rw-r--r--doc/classes/SkeletonModification2DFABRIK.xml108
-rw-r--r--doc/classes/SkeletonModification2DJiggle.xml232
-rw-r--r--doc/classes/SkeletonModification2DLookAt.xml107
-rw-r--r--doc/classes/SkeletonModification2DPhysicalBones.xml68
-rw-r--r--doc/classes/SkeletonModification2DStackHolder.xml32
-rw-r--r--doc/classes/SkeletonModification2DTwoBoneIK.xml94
-rw-r--r--doc/classes/SkeletonModificationStack2D.xml108
-rw-r--r--doc/classes/Skin.xml6
-rw-r--r--doc/classes/SkinReference.xml2
-rw-r--r--doc/classes/Sprite2D.xml2
-rw-r--r--doc/classes/Sprite3D.xml7
-rw-r--r--doc/classes/StaticBody2D.xml15
-rw-r--r--doc/classes/StaticBody3D.xml15
-rw-r--r--doc/classes/StreamPeer.xml4
-rw-r--r--doc/classes/String.xml16
-rw-r--r--doc/classes/StyleBoxTexture.xml7
-rw-r--r--doc/classes/SubViewport.xml2
-rw-r--r--doc/classes/SurfaceTool.xml6
-rw-r--r--doc/classes/TCPServer.xml2
-rw-r--r--doc/classes/TextEdit.xml71
-rw-r--r--doc/classes/TextLine.xml2
-rw-r--r--doc/classes/TextParagraph.xml2
-rw-r--r--doc/classes/TextServer.xml2
-rw-r--r--doc/classes/Theme.xml204
-rw-r--r--doc/classes/Thread.xml2
-rw-r--r--doc/classes/TileData.xml2
-rw-r--r--doc/classes/TileMap.xml10
-rw-r--r--doc/classes/TileSet.xml2
-rw-r--r--doc/classes/TileSetScenesCollectionSource.xml155
-rw-r--r--doc/classes/Time.xml270
-rw-r--r--doc/classes/Transform.xml216
-rw-r--r--doc/classes/Transform2D.xml37
-rw-r--r--doc/classes/Transform3D.xml216
-rw-r--r--doc/classes/Tree.xml24
-rw-r--r--doc/classes/TreeItem.xml84
-rw-r--r--doc/classes/TriangleMesh.xml2
-rw-r--r--doc/classes/UDPServer.xml2
-rw-r--r--doc/classes/Variant.xml32
-rw-r--r--doc/classes/Vector2.xml17
-rw-r--r--doc/classes/Vector2i.xml11
-rw-r--r--doc/classes/Vector3.xml24
-rw-r--r--doc/classes/Vector3i.xml11
-rw-r--r--doc/classes/VelocityTracker3D.xml2
-rw-r--r--doc/classes/VideoPlayer.xml2
-rw-r--r--doc/classes/Viewport.xml24
-rw-r--r--doc/classes/VisualInstance3D.xml2
-rw-r--r--doc/classes/VisualShader.xml12
-rw-r--r--doc/classes/VisualShaderNode.xml16
-rw-r--r--doc/classes/VisualShaderNodeBillboard.xml38
-rw-r--r--doc/classes/VisualShaderNodeDeterminant.xml2
-rw-r--r--doc/classes/VisualShaderNodeParticleAccelerator.xml25
-rw-r--r--doc/classes/VisualShaderNodeParticleBoxEmitter.xml13
-rw-r--r--doc/classes/VisualShaderNodeParticleConeVelocity.xml13
-rw-r--r--doc/classes/VisualShaderNodeParticleEmit.xml27
-rw-r--r--doc/classes/VisualShaderNodeParticleEmitter.xml13
-rw-r--r--doc/classes/VisualShaderNodeParticleMultiplyByAxisAngle.xml17
-rw-r--r--doc/classes/VisualShaderNodeParticleOutput.xml13
-rw-r--r--doc/classes/VisualShaderNodeParticleRandomness.xml23
-rw-r--r--doc/classes/VisualShaderNodeParticleRingEmitter.xml13
-rw-r--r--doc/classes/VisualShaderNodeParticleSphereEmitter.xml13
-rw-r--r--doc/classes/VisualShaderNodeTransformCompose.xml2
-rw-r--r--doc/classes/VisualShaderNodeTransformConstant.xml8
-rw-r--r--doc/classes/VisualShaderNodeTransformDecompose.xml2
-rw-r--r--doc/classes/VisualShaderNodeTransformFunc.xml8
-rw-r--r--doc/classes/VisualShaderNodeTransformMult.xml2
-rw-r--r--doc/classes/VisualShaderNodeTransformUniform.xml4
-rw-r--r--doc/classes/VisualShaderNodeTransformVecMult.xml2
-rw-r--r--doc/classes/VisualShaderNodeUVFunc.xml28
-rw-r--r--doc/classes/VoxelGI.xml63
-rw-r--r--doc/classes/VoxelGIData.xml92
-rw-r--r--doc/classes/WeakRef.xml4
-rw-r--r--doc/classes/Window.xml38
-rw-r--r--doc/classes/XMLParser.xml2
-rw-r--r--doc/classes/XRInterface.xml16
-rw-r--r--doc/classes/XRPositionalTracker.xml4
-rw-r--r--doc/classes/XRServer.xml8
-rw-r--r--doc/classes/YSort.xml21
-rw-r--r--doc/classes/float.xml6
-rw-r--r--doc/classes/int.xml4
-rw-r--r--doc/translations/ar.po26
-rw-r--r--doc/translations/ca.po26
-rw-r--r--doc/translations/classes.pot26
-rw-r--r--doc/translations/cs.po26
-rw-r--r--doc/translations/de.po26
-rw-r--r--doc/translations/es.po28
-rw-r--r--doc/translations/fa.po26
-rw-r--r--doc/translations/fi.po26
-rw-r--r--doc/translations/fr.po26
-rw-r--r--doc/translations/id.po26
-rw-r--r--doc/translations/it.po26
-rw-r--r--doc/translations/ja.po26
-rw-r--r--doc/translations/ko.po26
-rw-r--r--doc/translations/nl.po26
-rw-r--r--doc/translations/pl.po26
-rw-r--r--doc/translations/pt_BR.po26
-rw-r--r--doc/translations/ro.po26
-rw-r--r--doc/translations/ru.po26
-rw-r--r--doc/translations/sr_Cyrl.po26
-rw-r--r--doc/translations/th.po26
-rw-r--r--doc/translations/tr.po26
-rw-r--r--doc/translations/uk.po26
-rw-r--r--doc/translations/zh_Hans.po26
-rw-r--r--doc/translations/zh_Hant.po26
-rw-r--r--drivers/SCsub4
-rw-r--r--drivers/dummy/SCsub5
-rw-r--r--drivers/dummy/rasterizer_dummy.h783
-rw-r--r--drivers/dummy/texture_loader_dummy.cpp109
-rw-r--r--drivers/dummy/texture_loader_dummy.h47
-rw-r--r--drivers/png/image_loader_png.cpp6
-rw-r--r--drivers/png/resource_saver_png.cpp2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp8
-rw-r--r--drivers/unix/dir_access_unix.cpp51
-rw-r--r--drivers/unix/dir_access_unix.h8
-rw-r--r--drivers/unix/file_access_unix.cpp32
-rw-r--r--drivers/unix/file_access_unix.h12
-rw-r--r--drivers/unix/ip_unix.cpp22
-rw-r--r--drivers/unix/ip_unix.h2
-rw-r--r--drivers/unix/net_socket_posix.cpp2
-rw-r--r--drivers/unix/os_unix.cpp4
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp48
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h20
-rw-r--r--drivers/vulkan/vulkan_context.cpp66
-rw-r--r--drivers/vulkan/vulkan_context.h6
-rw-r--r--drivers/windows/dir_access_windows.cpp9
-rw-r--r--drivers/windows/dir_access_windows.h9
-rw-r--r--drivers/windows/file_access_windows.cpp33
-rw-r--r--drivers/windows/file_access_windows.h12
-rw-r--r--editor/action_map_editor.cpp60
-rw-r--r--editor/action_map_editor.h4
-rw-r--r--editor/animation_bezier_editor.cpp12
-rw-r--r--editor/animation_track_editor.cpp96
-rw-r--r--editor/animation_track_editor.h8
-rw-r--r--editor/animation_track_editor_plugins.cpp4
-rw-r--r--editor/array_property_edit.h4
-rw-r--r--editor/audio_stream_preview.h4
-rw-r--r--editor/code_editor.cpp125
-rw-r--r--editor/code_editor.h10
-rw-r--r--editor/connections_dialog.cpp24
-rw-r--r--editor/create_dialog.cpp6
-rw-r--r--editor/debugger/editor_debugger_server.h4
-rw-r--r--editor/debugger/editor_profiler.cpp55
-rw-r--r--editor/debugger/script_editor_debugger.cpp12
-rw-r--r--editor/dependency_editor.cpp6
-rw-r--r--editor/dictionary_property_edit.h4
-rw-r--r--editor/doc_tools.cpp2
-rw-r--r--editor/editor_about.cpp2
-rw-r--r--editor/editor_asset_installer.cpp12
-rw-r--r--editor/editor_audio_buses.cpp51
-rw-r--r--editor/editor_audio_buses.h8
-rw-r--r--editor/editor_autoload_settings.cpp6
-rw-r--r--editor/editor_builders.py2
-rw-r--r--editor/editor_data.cpp6
-rw-r--r--editor/editor_data.h2
-rw-r--r--editor/editor_dir_dialog.h2
-rw-r--r--editor/editor_export.cpp34
-rw-r--r--editor/editor_export.h14
-rw-r--r--editor/editor_feature_profile.cpp169
-rw-r--r--editor/editor_feature_profile.h18
-rw-r--r--editor/editor_file_dialog.cpp5
-rw-r--r--editor/editor_file_dialog.h2
-rw-r--r--editor/editor_file_system.cpp31
-rw-r--r--editor/editor_file_system.h2
-rw-r--r--editor/editor_folding.cpp2
-rw-r--r--editor/editor_fonts.cpp9
-rw-r--r--editor/editor_help.cpp4
-rw-r--r--editor/editor_help_search.cpp2
-rw-r--r--editor/editor_help_search.h2
-rw-r--r--editor/editor_inspector.cpp107
-rw-r--r--editor/editor_inspector.h6
-rw-r--r--editor/editor_log.cpp10
-rw-r--r--editor/editor_node.cpp107
-rw-r--r--editor/editor_node.h3
-rw-r--r--editor/editor_path.cpp100
-rw-r--r--editor/editor_path.h16
-rw-r--r--editor/editor_paths.cpp214
-rw-r--r--editor/editor_paths.h74
-rw-r--r--editor/editor_plugin.cpp169
-rw-r--r--editor/editor_plugin.h4
-rw-r--r--editor/editor_plugin_settings.cpp2
-rw-r--r--editor/editor_properties.cpp872
-rw-r--r--editor/editor_properties.h73
-rw-r--r--editor/editor_properties_array_dict.cpp14
-rw-r--r--editor/editor_properties_array_dict.h8
-rw-r--r--editor/editor_resource_picker.cpp864
-rw-r--r--editor/editor_resource_picker.h141
-rw-r--r--editor/editor_resource_preview.cpp38
-rw-r--r--editor/editor_resource_preview.h7
-rw-r--r--editor/editor_run_script.h6
-rw-r--r--editor/editor_sectioned_inspector.cpp9
-rw-r--r--editor/editor_settings.cpp261
-rw-r--r--editor/editor_settings.h11
-rw-r--r--editor/editor_spin_slider.cpp5
-rw-r--r--editor/editor_themes.cpp213
-rw-r--r--editor/editor_translation_parser.cpp14
-rw-r--r--editor/editor_translation_parser.h6
-rw-r--r--editor/export_template_manager.cpp948
-rw-r--r--editor/export_template_manager.h89
-rw-r--r--editor/fileserver/editor_file_server.cpp5
-rw-r--r--editor/filesystem_dock.cpp69
-rw-r--r--editor/filesystem_dock.h2
-rw-r--r--editor/find_in_files.cpp14
-rw-r--r--editor/groups_editor.cpp8
-rw-r--r--editor/icons/2D.svg2
-rw-r--r--editor/icons/AABB.svg2
-rw-r--r--editor/icons/AddSplit.svg2
-rw-r--r--editor/icons/Anchor.svg2
-rw-r--r--editor/icons/AnimatedSprite2D.svg2
-rw-r--r--editor/icons/AnimatedSprite3D.svg2
-rw-r--r--editor/icons/AnimationPlayer.svg2
-rw-r--r--editor/icons/AnimationTree.svg2
-rw-r--r--editor/icons/Area2D.svg2
-rw-r--r--editor/icons/Area3D.svg2
-rw-r--r--editor/icons/ArrayMesh.svg2
-rw-r--r--editor/icons/AspectRatioContainer.svg2
-rw-r--r--editor/icons/AudioBusLayout.svg2
-rw-r--r--editor/icons/AudioStreamMP3.svg2
-rw-r--r--editor/icons/AudioStreamOGGVorbis.svg2
-rw-r--r--editor/icons/AudioStreamPlayer.svg2
-rw-r--r--editor/icons/AudioStreamPlayer2D.svg2
-rw-r--r--editor/icons/AudioStreamPlayer3D.svg2
-rw-r--r--editor/icons/AudioStreamSample.svg2
-rw-r--r--editor/icons/BackBufferCopy.svg2
-rw-r--r--editor/icons/BakedLightmap.svg1
-rw-r--r--editor/icons/Basis.svg2
-rw-r--r--editor/icons/BezierHandlesBalanced.svg2
-rw-r--r--editor/icons/BezierHandlesFree.svg2
-rw-r--r--editor/icons/BezierHandlesMirror.svg2
-rw-r--r--editor/icons/Bone2D.svg2
-rw-r--r--editor/icons/BoneAttachment3D.svg2
-rw-r--r--editor/icons/BoneTrack.svg2
-rw-r--r--editor/icons/BoxMesh.svg2
-rw-r--r--editor/icons/BusVuEmpty.svg2
-rw-r--r--editor/icons/BusVuFull.svg2
-rw-r--r--editor/icons/Button.svg2
-rw-r--r--editor/icons/CPUParticles3D.svg2
-rw-r--r--editor/icons/Camera2D.svg2
-rw-r--r--editor/icons/Camera3D.svg2
-rw-r--r--editor/icons/CameraEffects.svg2
-rw-r--r--editor/icons/CanvasItemMaterial.svg2
-rw-r--r--editor/icons/CanvasItemShader.svg2
-rw-r--r--editor/icons/CanvasItemShaderGraph.svg2
-rw-r--r--editor/icons/CanvasModulate.svg2
-rw-r--r--editor/icons/CapsuleMesh.svg2
-rw-r--r--editor/icons/CenterContainer.svg2
-rw-r--r--editor/icons/CharacterBody2D.svg1
-rw-r--r--editor/icons/CharacterBody3D.svg1
-rw-r--r--editor/icons/CheckBox.svg2
-rw-r--r--editor/icons/CheckButton.svg2
-rw-r--r--editor/icons/ClippedCamera3D.svg2
-rw-r--r--editor/icons/CodeEdit.svg2
-rw-r--r--editor/icons/CollisionPolygon2D.svg2
-rw-r--r--editor/icons/CollisionPolygon3D.svg2
-rw-r--r--editor/icons/CollisionShape2D.svg2
-rw-r--r--editor/icons/CollisionShape3D.svg2
-rw-r--r--editor/icons/Color.svg2
-rw-r--r--editor/icons/ColorPicker.svg2
-rw-r--r--editor/icons/ColorPickerButton.svg2
-rw-r--r--editor/icons/ColorRect.svg2
-rw-r--r--editor/icons/ConeTwistJoint3D.svg2
-rw-r--r--editor/icons/Container.svg2
-rw-r--r--editor/icons/Control.svg2
-rw-r--r--editor/icons/ControlLayout.svg2
-rw-r--r--editor/icons/CreateNewSceneFrom.svg2
-rw-r--r--editor/icons/Cubemap.svg2
-rw-r--r--editor/icons/CubemapArray.svg2
-rw-r--r--editor/icons/CurveClose.svg2
-rw-r--r--editor/icons/CurveCreate.svg2
-rw-r--r--editor/icons/CurveCurve.svg2
-rw-r--r--editor/icons/CurveDelete.svg2
-rw-r--r--editor/icons/CurveEdit.svg2
-rw-r--r--editor/icons/CylinderMesh.svg2
-rw-r--r--editor/icons/DampedSpringJoint2D.svg2
-rw-r--r--editor/icons/DebugContinue.svg2
-rw-r--r--editor/icons/DebugNext.svg2
-rw-r--r--editor/icons/DebugStep.svg2
-rw-r--r--editor/icons/Decal.svg2
-rw-r--r--editor/icons/Dictionary.svg2
-rw-r--r--editor/icons/DirectionalLight3D.svg2
-rw-r--r--editor/icons/EditBezier.svg2
-rw-r--r--editor/icons/Editor3DHandle.svg2
-rw-r--r--editor/icons/EditorControlAnchor.svg2
-rw-r--r--editor/icons/EditorHandle.svg2
-rw-r--r--editor/icons/EditorHandleAdd.svg2
-rw-r--r--editor/icons/EditorPivot.svg2
-rw-r--r--editor/icons/EditorPosition.svg2
-rw-r--r--editor/icons/FixedSpatialMaterial.svg2
-rw-r--r--editor/icons/FontData.svg2
-rw-r--r--editor/icons/GIProbe.svg1
-rw-r--r--editor/icons/GPUParticles2D.svg2
-rw-r--r--editor/icons/GPUParticles3D.svg2
-rw-r--r--editor/icons/GPUParticlesAttractorBox.svg2
-rw-r--r--editor/icons/GPUParticlesAttractorSphere.svg2
-rw-r--r--editor/icons/GPUParticlesAttractorVectorField.svg2
-rw-r--r--editor/icons/GPUParticlesCollisionBox.svg2
-rw-r--r--editor/icons/GPUParticlesCollisionHeightField.svg2
-rw-r--r--editor/icons/GPUParticlesCollisionSDF.svg2
-rw-r--r--editor/icons/GPUParticlesCollisionSphere.svg2
-rw-r--r--editor/icons/Generic6DOFJoint3D.svg2
-rw-r--r--editor/icons/Gradient.svg2
-rw-r--r--editor/icons/GradientTexture.svg2
-rw-r--r--editor/icons/GraphEdit.svg2
-rw-r--r--editor/icons/GraphNode.svg2
-rw-r--r--editor/icons/Grid.svg2
-rw-r--r--editor/icons/GridContainer.svg2
-rw-r--r--editor/icons/GrooveJoint2D.svg2
-rw-r--r--editor/icons/GuiChecked.svg2
-rw-r--r--editor/icons/GuiRadioChecked.svg2
-rw-r--r--editor/icons/HBoxContainer.svg2
-rw-r--r--editor/icons/HScrollBar.svg2
-rw-r--r--editor/icons/HSeparator.svg2
-rw-r--r--editor/icons/HSlider.svg2
-rw-r--r--editor/icons/HSplitContainer.svg2
-rw-r--r--editor/icons/HingeJoint3D.svg2
-rw-r--r--editor/icons/ImmediateGeometry3D.svg2
-rw-r--r--editor/icons/InsertAfter.svg2
-rw-r--r--editor/icons/InsertBefore.svg2
-rw-r--r--editor/icons/InverseKinematics.svg2
-rw-r--r--editor/icons/ItemList.svg2
-rw-r--r--editor/icons/KeyAnimation.svg2
-rw-r--r--editor/icons/KeyAudio.svg2
-rw-r--r--editor/icons/KeyBezier.svg2
-rw-r--r--editor/icons/KeyBezierSelected.svg2
-rw-r--r--editor/icons/KeyCall.svg2
-rw-r--r--editor/icons/KeyNext.svg2
-rw-r--r--editor/icons/KeySelected.svg2
-rw-r--r--editor/icons/KeyXform.svg2
-rw-r--r--editor/icons/KinematicBody2D.svg1
-rw-r--r--editor/icons/KinematicBody3D.svg1
-rw-r--r--editor/icons/Label.svg2
-rw-r--r--editor/icons/LightOccluder2D.svg2
-rw-r--r--editor/icons/LightmapGI.svg1
-rw-r--r--editor/icons/LightmapGIData.svg (renamed from editor/icons/BakedLightmapData.svg)0
-rw-r--r--editor/icons/LightmapProbe.svg2
-rw-r--r--editor/icons/Line2D.svg2
-rw-r--r--editor/icons/LineEdit.svg2
-rw-r--r--editor/icons/LinkButton.svg2
-rw-r--r--editor/icons/Listener3D.svg2
-rw-r--r--editor/icons/MarginContainer.svg2
-rw-r--r--editor/icons/MenuButton.svg2
-rw-r--r--editor/icons/Mesh.svg2
-rw-r--r--editor/icons/MeshInstance2D.svg2
-rw-r--r--editor/icons/MeshInstance3D.svg2
-rw-r--r--editor/icons/MeshLibrary.svg2
-rw-r--r--editor/icons/MiniObject.svg2
-rw-r--r--editor/icons/MovePoint.svg2
-rw-r--r--editor/icons/MultiMesh.svg2
-rw-r--r--editor/icons/MultiMeshInstance2D.svg2
-rw-r--r--editor/icons/MultiMeshInstance3D.svg2
-rw-r--r--editor/icons/Navigation2D.svg2
-rw-r--r--editor/icons/Navigation3D.svg2
-rw-r--r--editor/icons/NavigationMesh.svg2
-rw-r--r--editor/icons/NavigationRegion2D.svg2
-rw-r--r--editor/icons/NavigationRegion3D.svg2
-rw-r--r--editor/icons/New.svg2
-rw-r--r--editor/icons/NewRoot.svg2
-rw-r--r--editor/icons/NinePatchRect.svg2
-rw-r--r--editor/icons/Node2D.svg2
-rw-r--r--editor/icons/Node3D.svg2
-rw-r--r--editor/icons/NodePath.svg2
-rw-r--r--editor/icons/Occluder3D.svg1
-rw-r--r--editor/icons/OccluderInstance3D.svg1
-rw-r--r--editor/icons/OccluderPolygon2D.svg2
-rw-r--r--editor/icons/OmniLight3D.svg2
-rw-r--r--editor/icons/OptionButton.svg2
-rw-r--r--editor/icons/PackedColorArray.svg2
-rw-r--r--editor/icons/PackedFloat32Array.svg2
-rw-r--r--editor/icons/PackedFloat64Array.svg2
-rw-r--r--editor/icons/PackedInt32Array.svg2
-rw-r--r--editor/icons/PackedInt64Array.svg2
-rw-r--r--editor/icons/PackedStringArray.svg2
-rw-r--r--editor/icons/PackedVector2Array.svg2
-rw-r--r--editor/icons/PackedVector3Array.svg2
-rw-r--r--editor/icons/Panel.svg2
-rw-r--r--editor/icons/PanelContainer.svg2
-rw-r--r--editor/icons/PanoramaSkyMaterial.svg2
-rw-r--r--editor/icons/ParallaxLayer.svg2
-rw-r--r--editor/icons/ParticlesMaterial.svg2
-rw-r--r--editor/icons/Path2D.svg2
-rw-r--r--editor/icons/Path3D.svg2
-rw-r--r--editor/icons/PathFollow2D.svg2
-rw-r--r--editor/icons/PathFollow3D.svg2
-rw-r--r--editor/icons/PhysicalBone3D.svg2
-rw-r--r--editor/icons/PhysicalSkyMaterial.svg2
-rw-r--r--editor/icons/PinJoint2D.svg2
-rw-r--r--editor/icons/PinJoint3D.svg2
-rw-r--r--editor/icons/Plane.svg2
-rw-r--r--editor/icons/PlaneMesh.svg2
-rw-r--r--editor/icons/PointLight2D.svg2
-rw-r--r--editor/icons/PointMesh.svg2
-rw-r--r--editor/icons/Polygon2D.svg2
-rw-r--r--editor/icons/Portal.svg2
-rw-r--r--editor/icons/Position2D.svg2
-rw-r--r--editor/icons/Position3D.svg2
-rw-r--r--editor/icons/PrismMesh.svg2
-rw-r--r--editor/icons/ProceduralSkyMaterial.svg2
-rw-r--r--editor/icons/ProgressBar.svg2
-rw-r--r--editor/icons/ProximityGroup3D.svg2
-rw-r--r--editor/icons/Quad.svg2
-rw-r--r--editor/icons/QuadMesh.svg2
-rw-r--r--editor/icons/Quat.svg1
-rw-r--r--editor/icons/Quaternion.svg1
-rw-r--r--editor/icons/RID.svg2
-rw-r--r--editor/icons/RayCast2D.svg2
-rw-r--r--editor/icons/RayCast3D.svg2
-rw-r--r--editor/icons/Rayito.svg2
-rw-r--r--editor/icons/Rect2.svg2
-rw-r--r--editor/icons/Rect2i.svg2
-rw-r--r--editor/icons/ReferenceRect.svg2
-rw-r--r--editor/icons/ReflectionProbe.svg2
-rw-r--r--editor/icons/RemoteTransform2D.svg2
-rw-r--r--editor/icons/RemoteTransform3D.svg2
-rw-r--r--editor/icons/Reparent.svg2
-rw-r--r--editor/icons/ReparentToNewNode.svg2
-rw-r--r--editor/icons/RibbonTrailMesh.svg1
-rw-r--r--editor/icons/RichTextEffect.svg2
-rw-r--r--editor/icons/RichTextLabel.svg2
-rw-r--r--editor/icons/RigidBody2D.svg2
-rw-r--r--editor/icons/RigidBody3D.svg2
-rw-r--r--editor/icons/Room.svg2
-rw-r--r--editor/icons/RootMotionView.svg2
-rw-r--r--editor/icons/SampleLibrary.svg2
-rw-r--r--editor/icons/ScriptCreate.svg2
-rw-r--r--editor/icons/ScriptRemove.svg2
-rw-r--r--editor/icons/ScrollContainer.svg2
-rw-r--r--editor/icons/Shader.svg2
-rw-r--r--editor/icons/ShaderMaterial.svg2
-rw-r--r--editor/icons/Signal.svg2
-rw-r--r--editor/icons/Skeleton2D.svg2
-rw-r--r--editor/icons/Skeleton3D.svg2
-rw-r--r--editor/icons/SliderJoint3D.svg2
-rw-r--r--editor/icons/Slot.svg2
-rw-r--r--editor/icons/SoftBody3D.svg2
-rw-r--r--editor/icons/SphereMesh.svg2
-rw-r--r--editor/icons/SpinBox.svg2
-rw-r--r--editor/icons/SpotLight3D.svg2
-rw-r--r--editor/icons/SpringArm3D.svg2
-rw-r--r--editor/icons/Sprite2D.svg2
-rw-r--r--editor/icons/Sprite3D.svg2
-rw-r--r--editor/icons/StandardMaterial3D.svg2
-rw-r--r--editor/icons/StaticBody2D.svg2
-rw-r--r--editor/icons/StaticBody3D.svg2
-rw-r--r--editor/icons/String.svg2
-rw-r--r--editor/icons/StringName.svg2
-rw-r--r--editor/icons/StyleBoxEmpty.svg2
-rw-r--r--editor/icons/StyleBoxFlat.svg2
-rw-r--r--editor/icons/StyleBoxLine.svg2
-rw-r--r--editor/icons/StyleBoxTexture.svg2
-rw-r--r--editor/icons/SubViewportContainer.svg2
-rw-r--r--editor/icons/TabContainer.svg2
-rw-r--r--editor/icons/Tabs.svg2
-rw-r--r--editor/icons/TestCube.svg2
-rw-r--r--editor/icons/TextEdit.svg2
-rw-r--r--editor/icons/TextureButton.svg2
-rw-r--r--editor/icons/TextureProgressBar.svg2
-rw-r--r--editor/icons/TextureRect.svg2
-rw-r--r--editor/icons/Theme.svg2
-rw-r--r--editor/icons/ThemeRemoveAllItems.svg2
-rw-r--r--editor/icons/ThemeRemoveCustomItems.svg2
-rw-r--r--editor/icons/TileMap.svg2
-rw-r--r--editor/icons/TouchScreenButton.svg2
-rw-r--r--editor/icons/TrackAddKey.svg2
-rw-r--r--editor/icons/TrackAddKeyHl.svg2
-rw-r--r--editor/icons/Transform.svg1
-rw-r--r--editor/icons/Transform2D.svg2
-rw-r--r--editor/icons/Transform3D.svg1
-rw-r--r--editor/icons/Tree.svg2
-rw-r--r--editor/icons/TubeTrailMesh.svg1
-rw-r--r--editor/icons/Tween.svg2
-rw-r--r--editor/icons/VBoxContainer.svg2
-rw-r--r--editor/icons/VScrollBar.svg2
-rw-r--r--editor/icons/VSeparator.svg2
-rw-r--r--editor/icons/VSlider.svg2
-rw-r--r--editor/icons/VSplitContainer.svg2
-rw-r--r--editor/icons/Variant.svg2
-rw-r--r--editor/icons/Vector2.svg2
-rw-r--r--editor/icons/Vector2i.svg2
-rw-r--r--editor/icons/Vector3.svg2
-rw-r--r--editor/icons/Vector3i.svg2
-rw-r--r--editor/icons/VehicleBody3D.svg2
-rw-r--r--editor/icons/VehicleWheel3D.svg2
-rw-r--r--editor/icons/VideoPlayer.svg2
-rw-r--r--editor/icons/VisibilityEnabler2D.svg2
-rw-r--r--editor/icons/VisibilityEnabler3D.svg2
-rw-r--r--editor/icons/VisibilityNotifier2D.svg2
-rw-r--r--editor/icons/VisibilityNotifier3D.svg2
-rw-r--r--editor/icons/VisualShader.svg2
-rw-r--r--editor/icons/VoxelGI.svg1
-rw-r--r--editor/icons/VoxelGIData.svg (renamed from editor/icons/GIProbeData.svg)0
-rw-r--r--editor/icons/WorldEnvironment.svg2
-rw-r--r--editor/icons/X509Certificate.svg2
-rw-r--r--editor/icons/XRAnchor3D.svg2
-rw-r--r--editor/icons/XRCamera3D.svg2
-rw-r--r--editor/icons/XRController3D.svg2
-rw-r--r--editor/icons/XROrigin3D.svg2
-rw-r--r--editor/icons/YSort.svg2
-rw-r--r--editor/icons/bool.svg2
-rw-r--r--editor/icons/float.svg2
-rw-r--r--editor/icons/int.svg2
-rw-r--r--editor/import/collada.cpp51
-rw-r--r--editor/import/collada.h22
-rw-r--r--editor/import/editor_import_collada.cpp26
-rw-r--r--editor/import/editor_import_plugin.cpp72
-rw-r--r--editor/import/resource_importer_csv_translation.cpp2
-rw-r--r--editor/import/resource_importer_image.cpp4
-rw-r--r--editor/import/resource_importer_obj.cpp8
-rw-r--r--editor/import/resource_importer_scene.cpp30
-rw-r--r--editor/import/resource_importer_scene.h8
-rw-r--r--editor/import/resource_importer_shader_file.cpp2
-rw-r--r--editor/import/resource_importer_texture.cpp32
-rw-r--r--editor/import/resource_importer_texture.h2
-rw-r--r--editor/import/resource_importer_texture_atlas.cpp2
-rw-r--r--editor/import/resource_importer_wav.cpp2
-rw-r--r--editor/import/scene_import_settings.cpp10
-rw-r--r--editor/import/scene_importer_mesh.cpp109
-rw-r--r--editor/import/scene_importer_mesh.h3
-rw-r--r--editor/inspector_dock.cpp105
-rw-r--r--editor/inspector_dock.h4
-rw-r--r--editor/multi_node_edit.h4
-rw-r--r--editor/node_3d_editor_gizmos.cpp336
-rw-r--r--editor/node_3d_editor_gizmos.h42
-rw-r--r--editor/plugin_config_dialog.cpp3
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp4
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp30
-rw-r--r--editor/plugins/animation_player_editor_plugin.h4
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp4
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp8
-rw-r--r--editor/plugins/baked_lightmap_editor_plugin.cpp138
-rw-r--r--editor/plugins/baked_lightmap_editor_plugin.h69
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp716
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h26
-rw-r--r--editor/plugins/collision_polygon_3d_editor_plugin.cpp14
-rw-r--r--editor/plugins/curve_editor_plugin.cpp4
-rw-r--r--editor/plugins/editor_preview_plugins.cpp18
-rw-r--r--editor/plugins/font_editor_plugin.cpp2
-rw-r--r--editor/plugins/gi_probe_editor_plugin.cpp173
-rw-r--r--editor/plugins/gi_probe_editor_plugin.h74
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/lightmap_gi_editor_plugin.cpp138
-rw-r--r--editor/plugins/lightmap_gi_editor_plugin.h69
-rw-r--r--editor/plugins/material_editor_plugin.cpp8
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp10
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp6
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp6
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp240
-rw-r--r--editor/plugins/node_3d_editor_plugin.h23
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp6
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp10
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp10
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp6
-rw-r--r--editor/plugins/script_editor_plugin.cpp45
-rw-r--r--editor/plugins/script_editor_plugin.h4
-rw-r--r--editor/plugins/script_text_editor.cpp117
-rw-r--r--editor/plugins/script_text_editor.h6
-rw-r--r--editor/plugins/shader_editor_plugin.cpp236
-rw-r--r--editor/plugins/shader_editor_plugin.h17
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp36
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.h14
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp86
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h7
-rw-r--r--editor/plugins/text_editor.cpp63
-rw-r--r--editor/plugins/text_editor.h3
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp20
-rw-r--r--editor/plugins/theme_editor_plugin.cpp1515
-rw-r--r--editor/plugins/theme_editor_plugin.h115
-rw-r--r--editor/plugins/theme_editor_preview.cpp464
-rw-r--r--editor/plugins/theme_editor_preview.h118
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp44
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp19
-rw-r--r--editor/plugins/tiles/tile_data_editors.h7
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp466
-rw-r--r--editor/plugins/tiles/tile_map_editor.h41
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp117
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h23
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp122
-rw-r--r--editor/plugins/tiles/tile_set_editor.h8
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp511
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.h139
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp1
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp4
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp649
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h36
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.cpp173
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.h74
-rw-r--r--editor/pot_generator.h2
-rw-r--r--editor/project_export.cpp14
-rw-r--r--editor/project_export.h2
-rw-r--r--editor/project_manager.cpp59
-rw-r--r--editor/property_editor.cpp90
-rw-r--r--editor/property_editor.h4
-rw-r--r--editor/property_selector.cpp25
-rw-r--r--editor/quick_open.cpp4
-rw-r--r--editor/scene_tree_dock.cpp16
-rw-r--r--editor/scene_tree_editor.cpp10
-rw-r--r--editor/script_create_dialog.cpp2
-rw-r--r--editor/settings_config_dialog.cpp14
-rw-r--r--editor/shader_globals_editor.cpp4
-rw-r--r--editor/translations/af.po19
-rw-r--r--editor/translations/ar.po19
-rw-r--r--editor/translations/az.po19
-rw-r--r--editor/translations/bg.po19
-rw-r--r--editor/translations/bn.po19
-rw-r--r--editor/translations/br.po19
-rw-r--r--editor/translations/ca.po19
-rw-r--r--editor/translations/cs.po29
-rw-r--r--editor/translations/da.po19
-rw-r--r--editor/translations/de.po50
-rw-r--r--editor/translations/editor.pot19
-rw-r--r--editor/translations/el.po113
-rw-r--r--editor/translations/eo.po1415
-rw-r--r--editor/translations/es.po29
-rw-r--r--editor/translations/es_AR.po32
-rw-r--r--editor/translations/et.po19
-rw-r--r--editor/translations/eu.po19
-rw-r--r--editor/translations/fa.po19
-rw-r--r--editor/translations/fi.po41
-rw-r--r--editor/translations/fil.po19
-rw-r--r--editor/translations/fr.po34
-rw-r--r--editor/translations/ga.po19
-rw-r--r--editor/translations/gl.po19
-rw-r--r--editor/translations/he.po19
-rw-r--r--editor/translations/hi.po19
-rw-r--r--editor/translations/hr.po19
-rw-r--r--editor/translations/hu.po19
-rw-r--r--editor/translations/id.po19
-rw-r--r--editor/translations/is.po19
-rw-r--r--editor/translations/it.po64
-rw-r--r--editor/translations/ja.po31
-rw-r--r--editor/translations/ka.po19
-rw-r--r--editor/translations/km.po19
-rw-r--r--editor/translations/ko.po45
-rw-r--r--editor/translations/lt.po19
-rw-r--r--editor/translations/lv.po19
-rw-r--r--editor/translations/mi.po19
-rw-r--r--editor/translations/mk.po19
-rw-r--r--editor/translations/ml.po19
-rw-r--r--editor/translations/mr.po19
-rw-r--r--editor/translations/ms.po74
-rw-r--r--editor/translations/nb.po50
-rw-r--r--editor/translations/nl.po190
-rw-r--r--editor/translations/or.po19
-rw-r--r--editor/translations/pl.po40
-rw-r--r--editor/translations/pr.po19
-rw-r--r--editor/translations/pt.po28
-rw-r--r--editor/translations/pt_BR.po43
-rw-r--r--editor/translations/ro.po19
-rw-r--r--editor/translations/ru.po32
-rw-r--r--editor/translations/si.po19
-rw-r--r--editor/translations/sk.po19
-rw-r--r--editor/translations/sl.po19
-rw-r--r--editor/translations/sq.po19
-rw-r--r--editor/translations/sr_Cyrl.po19
-rw-r--r--editor/translations/sr_Latn.po19
-rw-r--r--editor/translations/sv.po19
-rw-r--r--editor/translations/ta.po19
-rw-r--r--editor/translations/te.po19
-rw-r--r--editor/translations/th.po19
-rw-r--r--editor/translations/tr.po54
-rw-r--r--editor/translations/tzm.po19
-rw-r--r--editor/translations/uk.po41
-rw-r--r--editor/translations/ur_PK.po19
-rw-r--r--editor/translations/vi.po19
-rw-r--r--editor/translations/zh_CN.po46
-rw-r--r--editor/translations/zh_HK.po19
-rw-r--r--editor/translations/zh_TW.po31
-rw-r--r--main/main.cpp45
-rw-r--r--methods.py13
-rw-r--r--misc/dist/html/service-worker.js2
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj8
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme10
-rw-r--r--misc/dist/linux/org.godotengine.Godot.xml6
-rw-r--r--misc/dist/osx/editor.entitlements12
-rw-r--r--misc/dist/osx/editor_mono.entitlements18
-rw-r--r--misc/dist/osx_template.app/Contents/Info.plist2
-rw-r--r--misc/dist/osx_tools.app/Contents/Info.plist2
-rwxr-xr-xmisc/hooks/canonicalize_filename.sh2
-rwxr-xr-xmisc/hooks/pre-commit-clang-format7
-rwxr-xr-xmisc/scripts/check_ci_log.py4
-rw-r--r--modules/bmp/image_loader_bmp.cpp2
-rw-r--r--modules/bullet/bullet_physics_server.cpp36
-rw-r--r--modules/bullet/bullet_physics_server.h32
-rw-r--r--modules/bullet/bullet_types_converter.cpp4
-rw-r--r--modules/bullet/bullet_types_converter.h6
-rw-r--r--modules/bullet/collision_object_bullet.cpp16
-rw-r--r--modules/bullet/collision_object_bullet.h16
-rw-r--r--modules/bullet/cone_twist_joint_bullet.cpp6
-rw-r--r--modules/bullet/cone_twist_joint_bullet.h2
-rw-r--r--modules/bullet/config.py1
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.cpp22
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.h10
-rw-r--r--modules/bullet/hinge_joint_bullet.cpp6
-rw-r--r--modules/bullet/hinge_joint_bullet.h2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp20
-rw-r--r--modules/bullet/rigid_body_bullet.h4
-rw-r--r--modules/bullet/slider_joint_bullet.cpp30
-rw-r--r--modules/bullet/slider_joint_bullet.h14
-rw-r--r--modules/bullet/soft_body_bullet.cpp4
-rw-r--r--modules/bullet/soft_body_bullet.h4
-rw-r--r--modules/bullet/space_bullet.cpp14
-rw-r--r--modules/bullet/space_bullet.h12
-rw-r--r--modules/csg/config.py2
-rw-r--r--modules/csg/csg.cpp2
-rw-r--r--modules/csg/csg.h10
-rw-r--r--modules/csg/csg_gizmos.cpp4
-rw-r--r--modules/csg/csg_shape.cpp60
-rw-r--r--modules/csg/doc_classes/CSGShape3D.xml2
-rw-r--r--modules/csg/icons/CSGBox3D.svg2
-rw-r--r--modules/csg/icons/CSGCapsule3D.svg2
-rw-r--r--modules/csg/icons/CSGCombiner3D.svg2
-rw-r--r--modules/csg/icons/CSGCylinder3D.svg2
-rw-r--r--modules/csg/icons/CSGMesh3D.svg2
-rw-r--r--modules/csg/icons/CSGPolygon3D.svg2
-rw-r--r--modules/csg/icons/CSGSphere3D.svg2
-rw-r--r--modules/csg/icons/CSGTorus3D.svg2
-rw-r--r--modules/dds/texture_loader_dds.cpp2
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml2
-rw-r--r--modules/fbx/README.md30
-rw-r--r--modules/fbx/data/fbx_bone.h2
-rw-r--r--modules/fbx/data/fbx_material.h6
-rw-r--r--modules/fbx/data/fbx_mesh_data.cpp6
-rw-r--r--modules/fbx/data/fbx_mesh_data.h4
-rw-r--r--modules/fbx/data/fbx_node.h2
-rw-r--r--modules/fbx/data/fbx_skeleton.h4
-rw-r--r--modules/fbx/data/pivot_transform.cpp90
-rw-r--r--modules/fbx/data/pivot_transform.h30
-rw-r--r--modules/fbx/editor_scene_importer_fbx.cpp64
-rw-r--r--modules/fbx/fbx_parser/FBXDeformer.cpp2
-rw-r--r--modules/fbx/fbx_parser/FBXDocument.cpp2
-rw-r--r--modules/fbx/fbx_parser/FBXDocument.h20
-rw-r--r--modules/fbx/fbx_parser/FBXMeshGeometry.cpp8
-rw-r--r--modules/fbx/fbx_parser/FBXMeshGeometry.h4
-rw-r--r--modules/fbx/fbx_parser/FBXParser.cpp6
-rw-r--r--modules/fbx/fbx_parser/FBXParser.h4
-rw-r--r--modules/fbx/tools/import_utils.cpp12
-rw-r--r--modules/fbx/tools/import_utils.h8
-rw-r--r--modules/fbx/tools/validation_tools.h2
-rw-r--r--modules/gdnative/doc_classes/GDNative.xml2
-rw-r--r--modules/gdnative/gdnative.cpp14
-rw-r--r--modules/gdnative/gdnative.h4
-rw-r--r--modules/gdnative/gdnative/quat.cpp61
-rw-r--r--modules/gdnative/gdnative/quaternion.cpp61
-rw-r--r--modules/gdnative/gdnative/transform.cpp51
-rw-r--r--modules/gdnative/gdnative/transform_3d.cpp51
-rw-r--r--modules/gdnative/gdnative/variant.cpp34
-rw-r--r--modules/gdnative/gdnative_api.json56
-rw-r--r--modules/gdnative/gdnative_library_editor_plugin.cpp9
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h8
-rw-r--r--modules/gdnative/include/gdnative/quat.h60
-rw-r--r--modules/gdnative/include/gdnative/quaternion.h60
-rw-r--r--modules/gdnative/include/gdnative/transform.h58
-rw-r--r--modules/gdnative/include/gdnative/transform_3d.h60
-rw-r--r--modules/gdnative/include/gdnative/variant.h16
-rw-r--r--modules/gdnative/include/pluginscript/godot_pluginscript.h10
-rw-r--r--modules/gdnative/include/xr/godot_xr.h31
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp43
-rw-r--r--modules/gdnative/nativescript/godot_nativescript.cpp24
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp284
-rw-r--r--modules/gdnative/nativescript/nativescript.h29
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.cpp38
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.h12
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.cpp2
-rw-r--r--modules/gdnative/pluginscript/pluginscript_loader.cpp2
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.cpp103
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.h15
-rw-r--r--modules/gdnative/pluginscript/register_types.cpp2
-rw-r--r--modules/gdnative/register_types.cpp2
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.cpp32
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.h2
-rw-r--r--modules/gdnative/xr/xr_interface_gdnative.cpp71
-rw-r--r--modules/gdnative/xr/xr_interface_gdnative.h14
-rw-r--r--modules/gdnavigation/gd_navigation_server.cpp2
-rw-r--r--modules/gdnavigation/gd_navigation_server.h2
-rw-r--r--modules/gdnavigation/nav_map.cpp2
-rw-r--r--modules/gdnavigation/nav_region.cpp2
-rw-r--r--modules/gdnavigation/nav_region.h6
-rw-r--r--modules/gdnavigation/navigation_mesh_generator.cpp16
-rw-r--r--modules/gdnavigation/navigation_mesh_generator.h6
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml4
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp24
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.h2
-rw-r--r--modules/gdscript/gdscript.cpp165
-rw-r--r--modules/gdscript/gdscript.h39
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp41
-rw-r--r--modules/gdscript/gdscript_analyzer.h2
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp170
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h2
-rw-r--r--modules/gdscript/gdscript_cache.cpp6
-rw-r--r--modules/gdscript/gdscript_cache.h4
-rw-r--r--modules/gdscript/gdscript_codegen.h2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp89
-rw-r--r--modules/gdscript/gdscript_disassembler.cpp32
-rw-r--r--modules/gdscript/gdscript_editor.cpp9
-rw-r--r--modules/gdscript/gdscript_function.h15
-rw-r--r--modules/gdscript/gdscript_lambda_callable.h2
-rw-r--r--modules/gdscript/gdscript_parser.cpp8
-rw-r--r--modules/gdscript/gdscript_parser.h4
-rw-r--r--modules/gdscript/gdscript_vm.cpp116
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.h2
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp2
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.h8
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.h4
-rw-r--r--modules/gdscript/language_server/lsp.hpp4
-rw-r--r--modules/gdscript/register_types.cpp4
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp15
-rw-r--r--modules/gdscript/tests/gdscript_test_runner_suite.h21
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/call_self_get_name.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/call_self_get_name.out3
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.gd5
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.out6
-rw-r--r--modules/gdscript/tests/test_gdscript.cpp6
-rw-r--r--modules/glslang/register_types.cpp11
-rw-r--r--modules/gltf/doc_classes/GLTFNode.xml6
-rw-r--r--modules/gltf/editor_scene_importer_gltf.cpp2
-rw-r--r--modules/gltf/gltf_animation.h2
-rw-r--r--modules/gltf/gltf_document.cpp418
-rw-r--r--modules/gltf/gltf_document.h18
-rw-r--r--modules/gltf/gltf_node.cpp23
-rw-r--r--modules/gltf/gltf_node.h16
-rw-r--r--modules/gltf/gltf_skin.cpp2
-rw-r--r--modules/gltf/gltf_skin.h2
-rw-r--r--modules/gridmap/config.py2
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml4
-rw-r--r--modules/gridmap/grid_map.cpp21
-rw-r--r--modules/gridmap/grid_map.h6
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp34
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h6
-rw-r--r--modules/gridmap/icons/GridMap.svg2
-rw-r--r--modules/jpg/image_loader_jpegd.cpp2
-rw-r--r--modules/mbedtls/crypto_mbedtls.cpp6
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.cpp2
-rw-r--r--modules/mbedtls/ssl_context_mbedtls.h8
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.cpp2
-rw-r--r--modules/meshoptimizer/config.py2
-rw-r--r--modules/meshoptimizer/register_types.cpp1
-rw-r--r--modules/minimp3/audio_stream_mp3.cpp2
-rw-r--r--modules/minimp3/resource_importer_mp3.cpp4
-rw-r--r--modules/mobile_vr/config.py2
-rw-r--r--modules/mobile_vr/mobile_vr_interface.cpp95
-rw-r--r--modules/mobile_vr/mobile_vr_interface.h14
-rw-r--r--modules/mono/class_db_api_json.cpp2
-rw-r--r--modules/mono/csharp_script.cpp265
-rw-r--r--modules/mono/csharp_script.h35
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs6
-rw-r--r--modules/mono/editor/bindings_generator.cpp57
-rw-r--r--modules/mono/editor/bindings_generator.h10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs84
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs25
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs541
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs541
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs412
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs18
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs410
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs49
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs23
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs41
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs18
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj4
-rw-r--r--modules/mono/glue/base_object_glue.cpp34
-rw-r--r--modules/mono/glue/glue_header.h2
-rw-r--r--modules/mono/godotsharp_dirs.cpp6
-rw-r--r--modules/mono/mono_gc_handle.h6
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp8
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h4
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp16
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_log.cpp6
-rw-r--r--modules/mono/mono_gd/gd_mono_log.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp44
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h42
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h2
-rw-r--r--modules/mono/signal_awaiter_utils.h2
-rw-r--r--modules/mono/utils/mono_reg_utils.cpp2
-rw-r--r--modules/mono/utils/path_utils.cpp6
-rw-r--r--modules/mono/utils/string_utils.cpp6
-rw-r--r--modules/opensimplex/doc_classes/NoiseTexture.xml3
-rw-r--r--modules/opensimplex/doc_classes/OpenSimplexNoise.xml4
-rw-r--r--modules/opensimplex/noise_texture.cpp18
-rw-r--r--modules/opensimplex/noise_texture.h6
-rw-r--r--modules/opensimplex/open_simplex_noise.cpp6
-rw-r--r--modules/opensimplex/open_simplex_noise.h4
-rw-r--r--modules/pvr/image_compress_pvrtc.cpp2
-rw-r--r--modules/pvr/texture_loader_pvr.cpp2
-rw-r--r--modules/raycast/SCsub18
-rw-r--r--modules/raycast/config.py3
-rw-r--r--modules/raycast/godot_update_embree.py17
-rw-r--r--modules/raycast/raycast_occlusion_cull.cpp10
-rw-r--r--modules/raycast/raycast_occlusion_cull.h18
-rw-r--r--modules/regex/doc_classes/RegEx.xml2
-rw-r--r--modules/regex/doc_classes/RegExMatch.xml2
-rw-r--r--modules/regex/regex.h10
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--modules/stb_vorbis/resource_importer_ogg_vorbis.cpp4
-rw-r--r--modules/svg/image_loader_svg.cpp2
-rw-r--r--modules/text_server_adv/SCsub2
-rw-r--r--modules/text_server_adv/dynamic_font_adv.cpp2
-rw-r--r--modules/text_server_adv/text_server_adv.cpp32
-rw-r--r--modules/text_server_fb/dynamic_font_fb.cpp2
-rw-r--r--modules/text_server_fb/text_server_fb.cpp14
-rw-r--r--modules/tga/image_loader_tga.cpp26
-rw-r--r--modules/tga/image_loader_tga.h4
-rw-r--r--modules/theora/video_stream_theora.cpp16
-rw-r--r--modules/theora/video_stream_theora.h2
-rw-r--r--modules/tinyexr/image_loader_tinyexr.cpp2
-rw-r--r--modules/upnp/doc_classes/UPNP.xml2
-rw-r--r--modules/upnp/doc_classes/UPNPDevice.xml2
-rw-r--r--modules/upnp/upnp.h6
-rw-r--r--modules/upnp/upnp_device.h6
-rw-r--r--modules/vhacd/config.py2
-rw-r--r--modules/visual_script/doc_classes/VisualScript.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptClassConstant.xml4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEmitSignal.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionCall.xml4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionState.xml4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptInputAction.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVar.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertyGet.xml4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertySet.xml4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptTypeCast.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYieldSignal.xml4
-rw-r--r--modules/visual_script/visual_script.cpp100
-rw-r--r--modules/visual_script/visual_script.h31
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp3
-rw-r--r--modules/visual_script/visual_script_editor.cpp79
-rw-r--r--modules/visual_script/visual_script_editor.h3
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp16
-rw-r--r--modules/visual_script/visual_script_nodes.cpp4
-rw-r--r--modules/visual_script/visual_script_property_selector.cpp10
-rw-r--r--modules/webm/libvpx/SCsub9
-rw-r--r--modules/webm/video_stream_webm.cpp8
-rw-r--r--modules/webp/image_loader_webp.cpp77
-rw-r--r--modules/webrtc/doc_classes/WebRTCPeerConnection.xml4
-rw-r--r--modules/webrtc/webrtc_multiplayer.h2
-rw-r--r--modules/webrtc/webrtc_peer_connection.h4
-rw-r--r--modules/websocket/emws_server.h2
-rw-r--r--modules/websocket/websocket_server.h2
-rw-r--r--modules/websocket/wsl_server.h2
-rw-r--r--modules/webxr/config.py2
-rw-r--r--modules/webxr/doc_classes/WebXRInterface.xml2
-rw-r--r--modules/webxr/webxr_interface_js.cpp33
-rw-r--r--modules/webxr/webxr_interface_js.h7
-rw-r--r--platform/android/SCsub1
-rw-r--r--platform/android/android_keys_utils.h4
-rw-r--r--platform/android/api/java_class_wrapper.h10
-rw-r--r--platform/android/audio_driver_jandroid.cpp185
-rw-r--r--platform/android/audio_driver_jandroid.h78
-rw-r--r--platform/android/detect.py5
-rw-r--r--platform/android/dir_access_jandroid.cpp3
-rw-r--r--platform/android/dir_access_jandroid.h9
-rw-r--r--platform/android/display_server_android.cpp51
-rw-r--r--platform/android/display_server_android.h29
-rw-r--r--platform/android/export/export.cpp37
-rw-r--r--platform/android/export/gradle_export_util.h35
-rw-r--r--platform/android/file_access_android.cpp12
-rw-r--r--platform/android/file_access_android.h14
-rw-r--r--platform/android/java/build.gradle4
-rw-r--r--platform/android/java/gradlew.bat4
-rw-r--r--platform/android/java/lib/res/values/strings.xml2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java23
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java93
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java24
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt6
-rw-r--r--platform/android/java_class_wrapper.cpp4
-rw-r--r--platform/android/java_godot_io_wrapper.cpp12
-rw-r--r--platform/android/java_godot_io_wrapper.h2
-rw-r--r--platform/android/java_godot_lib_jni.cpp8
-rw-r--r--platform/android/java_godot_lib_jni.h1
-rw-r--r--platform/android/java_godot_view_wrapper.cpp10
-rw-r--r--platform/android/java_godot_view_wrapper.h2
-rw-r--r--platform/android/os_android.cpp43
-rw-r--r--platform/android/os_android.h3
-rw-r--r--platform/android/plugin/godot_plugin_config.h6
-rw-r--r--platform/iphone/export/export.cpp68
-rw-r--r--platform/iphone/godot_app_delegate.m2
-rw-r--r--platform/iphone/os_iphone.mm4
-rw-r--r--platform/iphone/plugin/godot_plugin_config.h4
-rw-r--r--platform/javascript/SCsub7
-rw-r--r--platform/javascript/api/api.cpp39
-rw-r--r--platform/javascript/api/javascript_eval.h53
-rw-r--r--platform/javascript/api/javascript_singleton.h68
-rw-r--r--platform/javascript/api/javascript_tools_editor_plugin.cpp15
-rw-r--r--platform/javascript/detect.py1
-rw-r--r--platform/javascript/display_server_javascript.cpp25
-rw-r--r--platform/javascript/dom_keys.inc4
-rw-r--r--platform/javascript/export/export.cpp22
-rw-r--r--platform/javascript/godot_js.h2
-rw-r--r--platform/javascript/javascript_eval.cpp79
-rw-r--r--platform/javascript/javascript_singleton.cpp346
-rw-r--r--platform/javascript/js/libs/library_godot_audio.js2
-rw-r--r--platform/javascript/js/libs/library_godot_display.js2
-rw-r--r--platform/javascript/js/libs/library_godot_editor_tools.js57
-rw-r--r--platform/javascript/js/libs/library_godot_eval.js86
-rw-r--r--platform/javascript/js/libs/library_godot_fetch.js8
-rw-r--r--platform/javascript/js/libs/library_godot_javascript_singleton.js333
-rw-r--r--platform/javascript/js/libs/library_godot_os.js17
-rw-r--r--platform/javascript/package-lock.json1002
-rw-r--r--platform/javascript/package.json8
-rw-r--r--platform/linuxbsd/SCsub22
-rw-r--r--platform/linuxbsd/detect.py30
-rw-r--r--platform/linuxbsd/display_server_x11.cpp30
-rw-r--r--platform/linuxbsd/export/export.cpp2
-rw-r--r--platform/linuxbsd/key_mapping_x11.cpp8
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp29
-rw-r--r--platform/osx/dir_access_osx.h2
-rw-r--r--platform/osx/display_server_osx.mm41
-rw-r--r--platform/osx/export/export.cpp86
-rw-r--r--platform/osx/os_osx.mm36
-rw-r--r--platform/server/SCsub16
-rw-r--r--platform/server/detect.py296
-rw-r--r--platform/server/godot_server.cpp49
-rw-r--r--platform/server/logo.pngbin2016 -> 0 bytes
-rw-r--r--platform/server/os_server.cpp267
-rw-r--r--platform/server/os_server.h116
-rw-r--r--platform/server/platform_config.h49
-rw-r--r--platform/uwp/app.cpp12
-rw-r--r--platform/uwp/export/export.cpp16
-rw-r--r--platform/uwp/os_uwp.cpp10
-rw-r--r--platform/windows/context_gl_windows.cpp2
-rw-r--r--platform/windows/display_server_windows.cpp109
-rw-r--r--platform/windows/export/export.cpp2
-rw-r--r--platform/windows/godot.natvis12
-rw-r--r--platform/windows/key_mapping_windows.cpp8
-rw-r--r--platform/windows/os_windows.cpp42
-rw-r--r--scene/2d/area_2d.cpp34
-rw-r--r--scene/2d/area_2d.h2
-rw-r--r--scene/2d/camera_2d.cpp9
-rw-r--r--scene/2d/collision_object_2d.cpp4
-rw-r--r--scene/2d/collision_object_2d.h3
-rw-r--r--scene/2d/collision_polygon_2d.cpp2
-rw-r--r--scene/2d/collision_shape_2d.cpp2
-rw-r--r--scene/2d/cpu_particles_2d.h2
-rw-r--r--scene/2d/gpu_particles_2d.cpp208
-rw-r--r--scene/2d/gpu_particles_2d.h24
-rw-r--r--scene/2d/light_2d.cpp4
-rw-r--r--scene/2d/mesh_instance_2d.cpp3
-rw-r--r--scene/2d/multimesh_instance_2d.cpp3
-rw-r--r--scene/2d/node_2d.cpp15
-rw-r--r--scene/2d/node_2d.h4
-rw-r--r--scene/2d/physical_bone_2d.cpp303
-rw-r--r--scene/2d/physical_bone_2d.h88
-rw-r--r--scene/2d/physics_body_2d.cpp629
-rw-r--r--scene/2d/physics_body_2d.h132
-rw-r--r--scene/2d/position_2d.cpp39
-rw-r--r--scene/2d/skeleton_2d.cpp531
-rw-r--r--scene/2d/skeleton_2d.h53
-rw-r--r--scene/2d/sprite_2d.cpp16
-rw-r--r--scene/2d/sprite_2d.h4
-rw-r--r--scene/2d/tile_map.cpp99
-rw-r--r--scene/2d/tile_map.h60
-rw-r--r--scene/2d/visibility_notifier_2d.cpp2
-rw-r--r--scene/2d/y_sort.cpp52
-rw-r--r--scene/2d/y_sort.h47
-rw-r--r--scene/3d/SCsub1
-rw-r--r--scene/3d/area_3d.cpp32
-rw-r--r--scene/3d/area_3d.h2
-rw-r--r--scene/3d/audio_stream_player_3d.cpp4
-rw-r--r--scene/3d/audio_stream_player_3d.h2
-rw-r--r--scene/3d/baked_lightmap.cpp1466
-rw-r--r--scene/3d/baked_lightmap.h284
-rw-r--r--scene/3d/camera_3d.cpp25
-rw-r--r--scene/3d/camera_3d.h5
-rw-r--r--scene/3d/collision_object_3d.cpp16
-rw-r--r--scene/3d/collision_object_3d.h8
-rw-r--r--scene/3d/collision_polygon_3d.cpp2
-rw-r--r--scene/3d/collision_shape_3d.cpp2
-rw-r--r--scene/3d/cpu_particles_3d.cpp8
-rw-r--r--scene/3d/cpu_particles_3d.h4
-rw-r--r--scene/3d/gi_probe.cpp549
-rw-r--r--scene/3d/gi_probe.h176
-rw-r--r--scene/3d/gpu_particles_3d.cpp17
-rw-r--r--scene/3d/gpu_particles_3d.h7
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp12
-rw-r--r--scene/3d/gpu_particles_collision_3d.h2
-rw-r--r--scene/3d/lightmap_gi.cpp1466
-rw-r--r--scene/3d/lightmap_gi.h284
-rw-r--r--scene/3d/lightmapper.h12
-rw-r--r--scene/3d/listener_3d.cpp2
-rw-r--r--scene/3d/listener_3d.h2
-rw-r--r--scene/3d/mesh_instance_3d.cpp2
-rw-r--r--scene/3d/node_3d.cpp138
-rw-r--r--scene/3d/node_3d.h38
-rw-r--r--scene/3d/occluder_instance_3d.cpp2
-rw-r--r--scene/3d/path_3d.cpp2
-rw-r--r--scene/3d/physics_body_3d.cpp768
-rw-r--r--scene/3d/physics_body_3d.h169
-rw-r--r--scene/3d/physics_joint_3d.cpp40
-rw-r--r--scene/3d/ray_cast_3d.cpp2
-rw-r--r--scene/3d/reflection_probe.cpp4
-rw-r--r--scene/3d/remote_transform_3d.cpp8
-rw-r--r--scene/3d/skeleton_3d.cpp91
-rw-r--r--scene/3d/skeleton_3d.h57
-rw-r--r--scene/3d/skeleton_ik_3d.cpp33
-rw-r--r--scene/3d/skeleton_ik_3d.h26
-rw-r--r--scene/3d/soft_body_3d.cpp6
-rw-r--r--scene/3d/spring_arm_3d.cpp2
-rw-r--r--scene/3d/sprite_3d.cpp16
-rw-r--r--scene/3d/sprite_3d.h4
-rw-r--r--scene/3d/vehicle_body_3d.cpp6
-rw-r--r--scene/3d/vehicle_body_3d.h4
-rw-r--r--scene/3d/velocity_tracker_3d.h4
-rw-r--r--scene/3d/visibility_notifier_3d.cpp2
-rw-r--r--scene/3d/visual_instance_3d.cpp68
-rw-r--r--scene/3d/visual_instance_3d.h30
-rw-r--r--scene/3d/voxel_gi.cpp549
-rw-r--r--scene/3d/voxel_gi.h176
-rw-r--r--scene/3d/voxelizer.cpp24
-rw-r--r--scene/3d/voxelizer.h18
-rw-r--r--scene/3d/xr_nodes.cpp23
-rw-r--r--scene/animation/animation_cache.cpp23
-rw-r--r--scene/animation/animation_cache.h8
-rw-r--r--scene/animation/animation_node_state_machine.cpp2
-rw-r--r--scene/animation/animation_player.cpp38
-rw-r--r--scene/animation/animation_player.h10
-rw-r--r--scene/animation/animation_tree.cpp79
-rw-r--r--scene/animation/animation_tree.h12
-rw-r--r--scene/animation/root_motion_view.cpp4
-rw-r--r--scene/animation/root_motion_view.h2
-rw-r--r--scene/animation/tween.cpp32
-rw-r--r--scene/debugger/scene_debugger.cpp2
-rw-r--r--scene/gui/aspect_ratio_container.cpp2
-rw-r--r--scene/gui/base_button.cpp6
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/code_edit.cpp1435
-rw-r--r--scene/gui/code_edit.h173
-rw-r--r--scene/gui/color_picker.cpp57
-rw-r--r--scene/gui/color_picker.h6
-rw-r--r--scene/gui/control.cpp465
-rw-r--r--scene/gui/control.h51
-rw-r--r--scene/gui/dialogs.cpp2
-rw-r--r--scene/gui/dialogs.h2
-rw-r--r--scene/gui/file_dialog.cpp6
-rw-r--r--scene/gui/file_dialog.h2
-rw-r--r--scene/gui/gradient_edit.cpp8
-rw-r--r--scene/gui/graph_edit.cpp25
-rw-r--r--scene/gui/graph_edit.h2
-rw-r--r--scene/gui/graph_node.cpp78
-rw-r--r--scene/gui/graph_node.h12
-rw-r--r--scene/gui/grid_container.cpp2
-rw-r--r--scene/gui/item_list.cpp8
-rw-r--r--scene/gui/label.cpp3
-rw-r--r--scene/gui/line_edit.cpp12
-rw-r--r--scene/gui/link_button.cpp2
-rw-r--r--scene/gui/nine_patch_rect.cpp3
-rw-r--r--scene/gui/popup_menu.cpp8
-rw-r--r--scene/gui/rich_text_effect.h4
-rw-r--r--scene/gui/rich_text_label.cpp43
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/gui/scroll_container.cpp46
-rw-r--r--scene/gui/scroll_container.h3
-rw-r--r--scene/gui/slider.cpp2
-rw-r--r--scene/gui/split_container.cpp2
-rw-r--r--scene/gui/tabs.cpp5
-rw-r--r--scene/gui/text_edit.cpp953
-rw-r--r--scene/gui/text_edit.h63
-rw-r--r--scene/gui/texture_button.cpp3
-rw-r--r--scene/gui/tree.cpp600
-rw-r--r--scene/gui/tree.h112
-rw-r--r--scene/main/canvas_item.cpp10
-rw-r--r--scene/main/http_request.cpp20
-rw-r--r--scene/main/http_request.h2
-rw-r--r--scene/main/node.cpp287
-rw-r--r--scene/main/node.h49
-rw-r--r--scene/main/scene_tree.cpp4
-rw-r--r--scene/main/scene_tree.h4
-rw-r--r--scene/main/shader_globals_override.cpp2
-rw-r--r--scene/main/viewport.cpp61
-rw-r--r--scene/main/viewport.h18
-rw-r--r--scene/main/window.cpp140
-rw-r--r--scene/main/window.h31
-rw-r--r--scene/register_scene_types.cpp87
-rw-r--r--scene/resources/animation.cpp86
-rw-r--r--scene/resources/animation.h18
-rw-r--r--scene/resources/audio_stream_sample.cpp2
-rw-r--r--scene/resources/bit_map.cpp2
-rw-r--r--scene/resources/convex_polygon_shape_3d.cpp4
-rw-r--r--scene/resources/default_theme/SCsub12
-rw-r--r--scene/resources/default_theme/default_theme.cpp83
-rw-r--r--scene/resources/default_theme/default_theme_builders.py40
-rw-r--r--scene/resources/default_theme/font_hidpi.inc25463
-rw-r--r--scene/resources/default_theme/font_lodpi.inc13117
-rw-r--r--scene/resources/material.cpp19
-rw-r--r--scene/resources/material.h1
-rw-r--r--scene/resources/mesh.cpp11
-rw-r--r--scene/resources/mesh.h6
-rw-r--r--scene/resources/mesh_data_tool.h4
-rw-r--r--scene/resources/mesh_library.cpp10
-rw-r--r--scene/resources/mesh_library.h8
-rw-r--r--scene/resources/multimesh.cpp8
-rw-r--r--scene/resources/multimesh.h4
-rw-r--r--scene/resources/packed_scene.h4
-rw-r--r--scene/resources/particles_material.cpp4
-rw-r--r--scene/resources/primitive_meshes.cpp10
-rw-r--r--scene/resources/primitive_meshes.h4
-rw-r--r--scene/resources/resource_format_text.cpp18
-rw-r--r--scene/resources/resource_format_text.h2
-rw-r--r--scene/resources/shader.cpp8
-rw-r--r--scene/resources/shape_3d.cpp2
-rw-r--r--scene/resources/shape_3d.h2
-rw-r--r--scene/resources/skeleton_modification_2d.cpp253
-rw-r--r--scene/resources/skeleton_modification_2d.h85
-rw-r--r--scene/resources/skeleton_modification_2d_ccdik.cpp545
-rw-r--r--scene/resources/skeleton_modification_2d_ccdik.h116
-rw-r--r--scene/resources/skeleton_modification_2d_fabrik.cpp444
-rw-r--r--scene/resources/skeleton_modification_2d_fabrik.h108
-rw-r--r--scene/resources/skeleton_modification_2d_jiggle.cpp564
-rw-r--r--scene/resources/skeleton_modification_2d_jiggle.h139
-rw-r--r--scene/resources/skeleton_modification_2d_lookat.cpp407
-rw-r--r--scene/resources/skeleton_modification_2d_lookat.h100
-rw-r--r--scene/resources/skeleton_modification_2d_physicalbones.cpp297
-rw-r--r--scene/resources/skeleton_modification_2d_physicalbones.h82
-rw-r--r--scene/resources/skeleton_modification_2d_stackholder.cpp131
-rw-r--r--scene/resources/skeleton_modification_2d_stackholder.h64
-rw-r--r--scene/resources/skeleton_modification_2d_twoboneik.cpp481
-rw-r--r--scene/resources/skeleton_modification_2d_twoboneik.h107
-rw-r--r--scene/resources/skeleton_modification_stack_2d.cpp269
-rw-r--r--scene/resources/skeleton_modification_stack_2d.h99
-rw-r--r--scene/resources/skin.cpp8
-rw-r--r--scene/resources/skin.h12
-rw-r--r--scene/resources/sky_material.cpp2
-rw-r--r--scene/resources/style_box.cpp3
-rw-r--r--scene/resources/surface_tool.cpp11
-rw-r--r--scene/resources/surface_tool.h8
-rw-r--r--scene/resources/text_file.cpp6
-rw-r--r--scene/resources/text_line.cpp2
-rw-r--r--scene/resources/text_line.h4
-rw-r--r--scene/resources/text_paragraph.cpp2
-rw-r--r--scene/resources/text_paragraph.h4
-rw-r--r--scene/resources/texture.cpp28
-rw-r--r--scene/resources/texture.h25
-rw-r--r--scene/resources/theme.cpp723
-rw-r--r--scene/resources/theme.h138
-rw-r--r--scene/resources/tile_set.cpp532
-rw-r--r--scene/resources/tile_set.h98
-rw-r--r--scene/resources/visual_shader.cpp545
-rw-r--r--scene/resources/visual_shader.h30
-rw-r--r--scene/resources/visual_shader_nodes.cpp345
-rw-r--r--scene/resources/visual_shader_nodes.h212
-rw-r--r--scene/resources/visual_shader_particle_nodes.cpp1025
-rw-r--r--scene/resources/visual_shader_particle_nodes.h285
-rw-r--r--scene/resources/world_2d.cpp2
-rw-r--r--scene/scene_string_names.cpp9
-rw-r--r--scene/scene_string_names.h9
-rw-r--r--servers/audio/audio_effect.h4
-rw-r--r--servers/audio/audio_stream.h4
-rw-r--r--servers/audio/effects/audio_effect_capture.h2
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp2
-rw-r--r--servers/audio/effects/audio_effect_record.h2
-rw-r--r--servers/audio/effects/reverb.cpp2
-rw-r--r--servers/audio_server.cpp5
-rw-r--r--servers/camera/camera_feed.h4
-rw-r--r--servers/camera_server.h2
-rw-r--r--servers/display_server.cpp17
-rw-r--r--servers/display_server.h6
-rw-r--r--servers/display_server_headless.h127
-rw-r--r--servers/navigation_server_2d.cpp6
-rw-r--r--servers/navigation_server_3d.h2
-rw-r--r--servers/physics_2d/body_2d_sw.cpp29
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp4
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp4
-rw-r--r--servers/physics_2d/physics_server_2d_sw.h6
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.cpp2
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.h1
-rw-r--r--servers/physics_2d/space_2d_sw.cpp4
-rw-r--r--servers/physics_3d/area_3d_sw.cpp2
-rw-r--r--servers/physics_3d/area_3d_sw.h2
-rw-r--r--servers/physics_3d/body_3d_sw.cpp66
-rw-r--r--servers/physics_3d/body_3d_sw.h12
-rw-r--r--servers/physics_3d/body_pair_3d_sw.cpp24
-rw-r--r--servers/physics_3d/body_pair_3d_sw.h2
-rw-r--r--servers/physics_3d/collision_object_3d_sw.cpp8
-rw-r--r--servers/physics_3d/collision_object_3d_sw.h24
-rw-r--r--servers/physics_3d/collision_solver_3d_sat.cpp56
-rw-r--r--servers/physics_3d/collision_solver_3d_sat.h2
-rw-r--r--servers/physics_3d/collision_solver_3d_sw.cpp32
-rw-r--r--servers/physics_3d/collision_solver_3d_sw.h14
-rw-r--r--servers/physics_3d/gjk_epa.cpp24
-rw-r--r--servers/physics_3d/gjk_epa.h4
-rw-r--r--servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp4
-rw-r--r--servers/physics_3d/joints/cone_twist_joint_3d_sw.h6
-rw-r--r--servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp2
-rw-r--r--servers/physics_3d/joints/generic_6dof_joint_3d_sw.h28
-rw-r--r--servers/physics_3d/joints/hinge_joint_3d_sw.cpp4
-rw-r--r--servers/physics_3d/joints/hinge_joint_3d_sw.h6
-rw-r--r--servers/physics_3d/joints/jacobian_entry_3d_sw.h2
-rw-r--r--servers/physics_3d/joints/slider_joint_3d_sw.cpp2
-rw-r--r--servers/physics_3d/joints/slider_joint_3d_sw.h22
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp52
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h33
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.cpp2
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.h35
-rw-r--r--servers/physics_3d/shape_3d_sw.cpp26
-rw-r--r--servers/physics_3d/shape_3d_sw.h26
-rw-r--r--servers/physics_3d/soft_body_3d_sw.cpp4
-rw-r--r--servers/physics_3d/soft_body_3d_sw.h4
-rw-r--r--servers/physics_3d/space_3d_sw.cpp67
-rw-r--r--servers/physics_3d/space_3d_sw.h12
-rw-r--r--servers/physics_server_2d.cpp12
-rw-r--r--servers/physics_server_2d.h44
-rw-r--r--servers/physics_server_3d.cpp19
-rw-r--r--servers/physics_server_3d.h82
-rw-r--r--servers/rendering/rasterizer_dummy.h787
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp213
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_canvas_render.h1
-rw-r--r--servers/rendering/renderer_compositor.cpp9
-rw-r--r--servers/rendering/renderer_compositor.h47
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h12
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp70
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h33
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp174
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h43
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp37
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h3
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp75
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h31
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp77
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h7
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp57
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h5
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp42
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp308
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h124
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp201
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h93
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp71
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h11
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp563
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h150
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp164
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp290
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h23
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl26
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_sdf.glsl60
-rw-r--r--servers/rendering/renderer_rd/shaders/gi.glsl76
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl238
-rw-r--r--servers/rendering/renderer_rd/shaders/particles_copy.glsl47
-rw-r--r--servers/rendering/renderer_rd/shaders/resolve.glsl22
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl26
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl20
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl32
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl9
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl38
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl12
-rw-r--r--servers/rendering/renderer_rd/shaders/sky.glsl31
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl35
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog.glsl32
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi.glsl (renamed from servers/rendering/renderer_rd/shaders/giprobe.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl (renamed from servers/rendering/renderer_rd/shaders/giprobe_debug.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl (renamed from servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl)0
-rw-r--r--servers/rendering/renderer_scene.h17
-rw-r--r--servers/rendering/renderer_scene_cull.cpp1053
-rw-r--r--servers/rendering/renderer_scene_cull.h141
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h6
-rw-r--r--servers/rendering/renderer_scene_render.cpp150
-rw-r--r--servers/rendering/renderer_scene_render.h52
-rw-r--r--servers/rendering/renderer_storage.h85
-rw-r--r--servers/rendering/renderer_viewport.cpp137
-rw-r--r--servers/rendering/renderer_viewport.h6
-rw-r--r--servers/rendering/rendering_device.cpp12
-rw-r--r--servers/rendering/rendering_device.h10
-rw-r--r--servers/rendering/rendering_device_binds.h48
-rw-r--r--servers/rendering/rendering_server_default.cpp2
-rw-r--r--servers/rendering/rendering_server_default.h82
-rw-r--r--servers/rendering/shader_language.cpp1346
-rw-r--r--servers/rendering/shader_language.h112
-rw-r--r--servers/rendering/shader_types.cpp30
-rw-r--r--servers/rendering/shader_warnings.cpp131
-rw-r--r--servers/rendering/shader_warnings.h83
-rw-r--r--servers/rendering_server.cpp86
-rw-r--r--servers/rendering_server.h99
-rw-r--r--servers/text_server.cpp2
-rw-r--r--servers/text_server.h2
-rw-r--r--servers/xr/xr_interface.cpp3
-rw-r--r--servers/xr/xr_interface.h22
-rw-r--r--servers/xr/xr_positional_tracker.cpp4
-rw-r--r--servers/xr/xr_positional_tracker.h6
-rw-r--r--servers/xr_server.cpp16
-rw-r--r--servers/xr_server.h14
-rw-r--r--tests/test_aabb.h4
-rw-r--r--tests/test_class_db.h18
-rw-r--r--tests/test_color.h8
-rw-r--r--tests/test_command_queue.h60
-rw-r--r--tests/test_curve.h28
-rw-r--r--tests/test_expression.h24
-rw-r--r--tests/test_file_access.h2
-rw-r--r--tests/test_geometry_2d.h8
-rw-r--r--tests/test_image.h20
-rw-r--r--tests/test_json.h4
-rw-r--r--tests/test_macros.h4
-rw-r--r--tests/test_main.cpp36
-rw-r--r--tests/test_math.cpp16
-rw-r--r--tests/test_object.h35
-rw-r--r--tests/test_pck_packer.h8
-rw-r--r--tests/test_physics_2d.cpp2
-rw-r--r--tests/test_physics_3d.cpp38
-rw-r--r--tests/test_rect2.h16
-rw-r--r--tests/test_render.cpp14
-rw-r--r--tests/test_shader_lang.cpp2
-rw-r--r--tests/test_string.h7
-rw-r--r--tests/test_time.h145
-rw-r--r--tests/test_translation.h150
-rw-r--r--tests/test_validate_testing.h4
-rw-r--r--tests/test_vector.h496
-rw-r--r--thirdparty/README.md24
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_any_of.h55
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_filter.cpp56
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_filter.h93
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_for.cpp48
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_for.h229
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_for_for.cpp63
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_for_for.h149
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_for_for_prefix_sum.cpp85
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_for_for_prefix_sum.h112
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_map.cpp47
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_map.h85
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_partition.cpp53
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_partition.h283
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_prefix_sum.cpp48
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_prefix_sum.h85
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_reduce.cpp49
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_reduce.h150
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_set.cpp43
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_set.h52
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_sort.cpp50
-rw-r--r--thirdparty/embree-aarch64/common/algorithms/parallel_sort.h457
-rw-r--r--thirdparty/embree-aarch64/common/lexers/parsestream.h101
-rw-r--r--thirdparty/embree-aarch64/common/lexers/stream.h215
-rw-r--r--thirdparty/embree-aarch64/common/lexers/streamfilters.h39
-rw-r--r--thirdparty/embree-aarch64/common/lexers/stringstream.cpp51
-rw-r--r--thirdparty/embree-aarch64/common/lexers/stringstream.h29
-rw-r--r--thirdparty/embree-aarch64/common/lexers/tokenstream.cpp181
-rw-r--r--thirdparty/embree-aarch64/common/lexers/tokenstream.h164
-rw-r--r--thirdparty/embree-aarch64/common/math/AVX2NEON.h986
-rw-r--r--thirdparty/embree-aarch64/common/math/SSE2NEON.h1753
-rw-r--r--thirdparty/embree-aarch64/common/math/affinespace.h361
-rw-r--r--thirdparty/embree-aarch64/common/math/bbox.h331
-rw-r--r--thirdparty/embree-aarch64/common/math/col3.h47
-rw-r--r--thirdparty/embree-aarch64/common/math/col4.h47
-rw-r--r--thirdparty/embree-aarch64/common/math/color.h257
-rw-r--r--thirdparty/embree-aarch64/common/math/constants.cpp61
-rw-r--r--thirdparty/embree-aarch64/common/math/constants.h239
-rw-r--r--thirdparty/embree-aarch64/common/math/interval.h161
-rw-r--r--thirdparty/embree-aarch64/common/math/lbbox.h289
-rw-r--r--thirdparty/embree-aarch64/common/math/linearspace2.h148
-rw-r--r--thirdparty/embree-aarch64/common/math/linearspace3.h213
-rw-r--r--thirdparty/embree-aarch64/common/math/math.h451
-rw-r--r--thirdparty/embree-aarch64/common/math/obbox.h39
-rw-r--r--thirdparty/embree-aarch64/common/math/quaternion.h254
-rw-r--r--thirdparty/embree-aarch64/common/math/range.h137
-rw-r--r--thirdparty/embree-aarch64/common/math/transcendental.h525
-rw-r--r--thirdparty/embree-aarch64/common/math/vec2.h235
-rw-r--r--thirdparty/embree-aarch64/common/math/vec2fa.h317
-rw-r--r--thirdparty/embree-aarch64/common/math/vec3.h349
-rw-r--r--thirdparty/embree-aarch64/common/math/vec3ba.h120
-rw-r--r--thirdparty/embree-aarch64/common/math/vec3fa.h810
-rw-r--r--thirdparty/embree-aarch64/common/math/vec3ia.h210
-rw-r--r--thirdparty/embree-aarch64/common/math/vec4.h258
-rw-r--r--thirdparty/embree-aarch64/common/simd/avx.h34
-rw-r--r--thirdparty/embree-aarch64/common/simd/avx512.h41
-rw-r--r--thirdparty/embree-aarch64/common/simd/simd.h110
-rw-r--r--thirdparty/embree-aarch64/common/simd/sse.cpp34
-rw-r--r--thirdparty/embree-aarch64/common/simd/sse.h35
-rw-r--r--thirdparty/embree-aarch64/common/simd/varying.h132
-rw-r--r--thirdparty/embree-aarch64/common/simd/vboold4_avx.h160
-rw-r--r--thirdparty/embree-aarch64/common/simd/vboold4_avx512.h140
-rw-r--r--thirdparty/embree-aarch64/common/simd/vboold8_avx512.h148
-rw-r--r--thirdparty/embree-aarch64/common/simd/vboolf16_avx512.h150
-rw-r--r--thirdparty/embree-aarch64/common/simd/vboolf4_avx512.h143
-rw-r--r--thirdparty/embree-aarch64/common/simd/vboolf4_sse2.h198
-rw-r--r--thirdparty/embree-aarch64/common/simd/vboolf8_avx.h189
-rw-r--r--thirdparty/embree-aarch64/common/simd/vboolf8_avx512.h143
-rw-r--r--thirdparty/embree-aarch64/common/simd/vdouble4_avx.h324
-rw-r--r--thirdparty/embree-aarch64/common/simd/vdouble8_avx512.h356
-rw-r--r--thirdparty/embree-aarch64/common/simd/vfloat16_avx512.h771
-rw-r--r--thirdparty/embree-aarch64/common/simd/vfloat4_sse2.h925
-rw-r--r--thirdparty/embree-aarch64/common/simd/vfloat8_avx.h847
-rw-r--r--thirdparty/embree-aarch64/common/simd/vint16_avx512.h490
-rw-r--r--thirdparty/embree-aarch64/common/simd/vint4_sse2.h681
-rw-r--r--thirdparty/embree-aarch64/common/simd/vint8_avx.h464
-rw-r--r--thirdparty/embree-aarch64/common/simd/vint8_avx2.h512
-rw-r--r--thirdparty/embree-aarch64/common/simd/vllong4_avx2.h358
-rw-r--r--thirdparty/embree-aarch64/common/simd/vllong8_avx512.h381
-rw-r--r--thirdparty/embree-aarch64/common/simd/vuint16_avx512.h443
-rw-r--r--thirdparty/embree-aarch64/common/simd/vuint4_sse2.h499
-rw-r--r--thirdparty/embree-aarch64/common/simd/vuint8_avx.h379
-rw-r--r--thirdparty/embree-aarch64/common/simd/vuint8_avx2.h439
-rw-r--r--thirdparty/embree-aarch64/common/sys/alloc.cpp327
-rw-r--r--thirdparty/embree-aarch64/common/sys/alloc.h164
-rw-r--r--thirdparty/embree-aarch64/common/sys/array.h222
-rw-r--r--thirdparty/embree-aarch64/common/sys/atomic.h59
-rw-r--r--thirdparty/embree-aarch64/common/sys/barrier.cpp289
-rw-r--r--thirdparty/embree-aarch64/common/sys/barrier.h112
-rw-r--r--thirdparty/embree-aarch64/common/sys/condition.cpp81
-rw-r--r--thirdparty/embree-aarch64/common/sys/condition.h31
-rw-r--r--thirdparty/embree-aarch64/common/sys/filename.cpp138
-rw-r--r--thirdparty/embree-aarch64/common/sys/filename.h81
-rw-r--r--thirdparty/embree-aarch64/common/sys/intrinsics.h559
-rw-r--r--thirdparty/embree-aarch64/common/sys/library.cpp83
-rw-r--r--thirdparty/embree-aarch64/common/sys/library.h21
-rw-r--r--thirdparty/embree-aarch64/common/sys/mutex.cpp58
-rw-r--r--thirdparty/embree-aarch64/common/sys/mutex.h98
-rw-r--r--thirdparty/embree-aarch64/common/sys/platform.h387
-rw-r--r--thirdparty/embree-aarch64/common/sys/ref.h122
-rw-r--r--thirdparty/embree-aarch64/common/sys/regression.cpp30
-rw-r--r--thirdparty/embree-aarch64/common/sys/regression.h25
-rw-r--r--thirdparty/embree-aarch64/common/sys/string.cpp42
-rw-r--r--thirdparty/embree-aarch64/common/sys/string.h37
-rw-r--r--thirdparty/embree-aarch64/common/sys/sysinfo.cpp676
-rw-r--r--thirdparty/embree-aarch64/common/sys/sysinfo.h192
-rw-r--r--thirdparty/embree-aarch64/common/sys/thread.cpp429
-rw-r--r--thirdparty/embree-aarch64/common/sys/thread.h46
-rw-r--r--thirdparty/embree-aarch64/common/sys/vector.h242
-rw-r--r--thirdparty/embree-aarch64/common/tasking/taskscheduler.h17
-rw-r--r--thirdparty/embree-aarch64/common/tasking/taskschedulergcd.h49
-rw-r--r--thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.cpp426
-rw-r--r--thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h386
-rw-r--r--thirdparty/embree-aarch64/common/tasking/taskschedulerppl.h46
-rw-r--r--thirdparty/embree-aarch64/common/tasking/taskschedulertbb.h67
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore.h14
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_buffer.h51
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_builder.h125
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_common.h326
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_config.h57
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_device.h87
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_geometry.h383
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_quaternion.h101
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_ray.h378
-rw-r--r--thirdparty/embree-aarch64/include/embree3/rtcore_scene.h160
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/bvh_builder_hair.h411
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/bvh_builder_morton.h501
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/bvh_builder_msmblur.h692
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/bvh_builder_msmblur_hair.h526
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/bvh_builder_sah.h669
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/heuristic_binning.h972
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/heuristic_binning_array_aligned.h205
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/heuristic_binning_array_unaligned.h302
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/heuristic_openmerge_array.h443
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/heuristic_spatial.h414
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/heuristic_spatial_array.h552
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/heuristic_strand_array.h188
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/heuristic_timesplit_array.h237
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/priminfo.h362
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/primrefgen.cpp244
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/primrefgen.h28
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/primrefgen_presplit.h371
-rw-r--r--thirdparty/embree-aarch64/kernels/builders/splitter.h169
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh.cpp190
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh.h235
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh4_factory.cpp1325
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh4_factory.h316
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh8_factory.cpp1165
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh8_factory.h280
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder.cpp60
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder.h114
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder_morton.cpp531
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah.cpp640
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah_mb.cpp705
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah_spatial.cpp201
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel.cpp377
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel.h263
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel_internal.h267
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_collider.cpp375
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_collider.h72
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_factory.h21
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1.cpp330
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1.h37
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1_bvh4.cpp61
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_hybrid.h61
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_stream.h295
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_stream_filters.h41
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb.h213
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb_mb.h247
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb_mb4d.h107
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_node_base.h43
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_node_obb.h98
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_node_obb_mb.h90
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_node_qaabb.h265
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_node_ref.h242
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_refit.cpp247
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_refit.h95
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_rotate.cpp127
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_rotate.h37
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.cpp168
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.h285
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_traverser1.h676
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/bvh_traverser_stream.h154
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/node_intersector.h31
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/node_intersector1.h1788
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/node_intersector_frustum.h269
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/node_intersector_packet.h843
-rw-r--r--thirdparty/embree-aarch64/kernels/bvh/node_intersector_packet_stream.h215
-rw-r--r--thirdparty/embree-aarch64/kernels/common/accel.h556
-rw-r--r--thirdparty/embree-aarch64/kernels/common/accelinstance.h41
-rw-r--r--thirdparty/embree-aarch64/kernels/common/acceln.cpp232
-rw-r--r--thirdparty/embree-aarch64/kernels/common/acceln.h49
-rw-r--r--thirdparty/embree-aarch64/kernels/common/accelset.cpp17
-rw-r--r--thirdparty/embree-aarch64/kernels/common/accelset.h248
-rw-r--r--thirdparty/embree-aarch64/kernels/common/alloc.cpp82
-rw-r--r--thirdparty/embree-aarch64/kernels/common/alloc.h1006
-rw-r--r--thirdparty/embree-aarch64/kernels/common/buffer.h263
-rw-r--r--thirdparty/embree-aarch64/kernels/common/builder.h60
-rw-r--r--thirdparty/embree-aarch64/kernels/common/context.h131
-rw-r--r--thirdparty/embree-aarch64/kernels/common/default.h273
-rw-r--r--thirdparty/embree-aarch64/kernels/common/device.cpp567
-rw-r--r--thirdparty/embree-aarch64/kernels/common/device.h85
-rw-r--r--thirdparty/embree-aarch64/kernels/common/geometry.cpp259
-rw-r--r--thirdparty/embree-aarch64/kernels/common/geometry.h582
-rw-r--r--thirdparty/embree-aarch64/kernels/common/hit.h114
-rw-r--r--thirdparty/embree-aarch64/kernels/common/instance_stack.h199
-rw-r--r--thirdparty/embree-aarch64/kernels/common/isa.h271
-rw-r--r--thirdparty/embree-aarch64/kernels/common/motion_derivative.h325
-rw-r--r--thirdparty/embree-aarch64/kernels/common/point_query.h136
-rw-r--r--thirdparty/embree-aarch64/kernels/common/primref.h138
-rw-r--r--thirdparty/embree-aarch64/kernels/common/primref_mb.h262
-rw-r--r--thirdparty/embree-aarch64/kernels/common/profile.h159
-rw-r--r--thirdparty/embree-aarch64/kernels/common/ray.h1517
-rw-r--r--thirdparty/embree-aarch64/kernels/common/rtcore.cpp1799
-rw-r--r--thirdparty/embree-aarch64/kernels/common/rtcore.h142
-rw-r--r--thirdparty/embree-aarch64/kernels/common/rtcore_builder.cpp442
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene.cpp976
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene.h390
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_curves.h341
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_grid_mesh.h215
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_instance.h272
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_line_segments.h307
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_points.h282
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_quad_mesh.h277
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_subdiv_mesh.h326
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_triangle_mesh.cpp243
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_triangle_mesh.h264
-rw-r--r--thirdparty/embree-aarch64/kernels/common/scene_user_geometry.h77
-rw-r--r--thirdparty/embree-aarch64/kernels/common/stack_item.h125
-rw-r--r--thirdparty/embree-aarch64/kernels/common/stat.cpp128
-rw-r--r--thirdparty/embree-aarch64/kernels/common/stat.h116
-rw-r--r--thirdparty/embree-aarch64/kernels/common/state.cpp543
-rw-r--r--thirdparty/embree-aarch64/kernels/common/state.h197
-rw-r--r--thirdparty/embree-aarch64/kernels/common/vector.h76
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/cone.h321
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/coneline_intersector.h209
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/conelinei_intersector.h141
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curveNi.h222
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curveNi_intersector.h569
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curveNi_mb.h278
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curveNi_mb_intersector.h516
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curveNv.h101
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curveNv_intersector.h181
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector.h98
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_distance.h129
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_oriented.h417
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_precalculations.h49
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_ribbon.h214
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_sweep.h362
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual.h671
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_bezier_curve.h21
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_bspline_curve.h21
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_catmullrom_curve.h21
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_hermite_curve.h21
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_linear_curve.h21
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_point.h22
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/cylinder.h223
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/disc_intersector.h216
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/disci_intersector.h277
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/filter.h204
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/grid_intersector.h99
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/grid_soa.h275
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/grid_soa_intersector1.h207
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/grid_soa_intersector_packet.h445
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/instance.h78
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/instance_intersector.h84
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/intersector_epilog.h1074
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/intersector_iterators.h172
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/line_intersector.h141
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/linei.h709
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/linei_intersector.h124
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/object.h84
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/object_intersector.h127
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/plane.h57
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/pointi.h417
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/primitive.h49
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/primitive4.cpp379
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/quad_intersector.h76
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/quad_intersector_moeller.h566
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/quad_intersector_pluecker.h529
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/quadi.h483
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/quadi_intersector.h350
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/quadv.h165
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/quadv_intersector.h181
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/roundline_intersector.h710
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/roundlinei_intersector.h136
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/sphere_intersector.h183
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/spherei_intersector.h156
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/subdivpatch1.h38
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/subdivpatch1_intersector.h237
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/subgrid.h517
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector.h518
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector_moeller.h493
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector_pluecker.h508
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/subgrid_mb_intersector.h236
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/triangle.h162
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/triangle_intersector.h96
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_moeller.h403
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_pluecker.h247
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_woop.h418
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/triangle_triangle_intersector.h132
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/trianglei.h442
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/trianglei_intersector.h336
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/trianglev.h157
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/trianglev_intersector.h206
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/trianglev_mb.h201
-rw-r--r--thirdparty/embree-aarch64/kernels/geometry/trianglev_mb_intersector.h211
-rw-r--r--thirdparty/embree-aarch64/kernels/hash.h5
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/bezier_curve.h669
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/bezier_patch.h372
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/bilinear_patch.h191
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/bspline_curve.h319
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/bspline_patch.h449
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/catmullclark_coefficients.h85
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/catmullclark_patch.h562
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/catmullclark_ring.h826
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/catmullrom_curve.h296
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval.h226
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval_grid.h359
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval_simd.h186
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/gregory_patch.h893
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/gregory_patch_dense.h113
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/gridrange.h96
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/half_edge.h371
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/hermite_curve.h38
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/linear_bezier_patch.h403
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/patch.h371
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/patch_eval.h129
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/patch_eval_grid.h245
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/patch_eval_simd.h127
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/subdivpatch1base.h156
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/tessellation.h161
-rw-r--r--thirdparty/embree-aarch64/kernels/subdiv/tessellation_cache.h325
-rw-r--r--thirdparty/embree-aarch64/patches/godot-changes.patch630
-rw-r--r--thirdparty/embree/common/algorithms/parallel_any_of.h55
-rw-r--r--thirdparty/embree/common/algorithms/parallel_filter.h93
-rw-r--r--thirdparty/embree/common/algorithms/parallel_for.h186
-rw-r--r--thirdparty/embree/common/algorithms/parallel_for_for.h149
-rw-r--r--thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h112
-rw-r--r--thirdparty/embree/common/algorithms/parallel_map.h85
-rw-r--r--thirdparty/embree/common/algorithms/parallel_partition.h283
-rw-r--r--thirdparty/embree/common/algorithms/parallel_prefix_sum.h85
-rw-r--r--thirdparty/embree/common/algorithms/parallel_reduce.h150
-rw-r--r--thirdparty/embree/common/algorithms/parallel_set.h52
-rw-r--r--thirdparty/embree/common/algorithms/parallel_sort.h454
-rw-r--r--thirdparty/embree/common/lexers/parsestream.h101
-rw-r--r--thirdparty/embree/common/lexers/stream.h215
-rw-r--r--thirdparty/embree/common/lexers/streamfilters.h39
-rw-r--r--thirdparty/embree/common/lexers/stringstream.cpp51
-rw-r--r--thirdparty/embree/common/lexers/stringstream.h29
-rw-r--r--thirdparty/embree/common/lexers/tokenstream.cpp181
-rw-r--r--thirdparty/embree/common/lexers/tokenstream.h164
-rw-r--r--thirdparty/embree/common/math/affinespace.h361
-rw-r--r--thirdparty/embree/common/math/bbox.h331
-rw-r--r--thirdparty/embree/common/math/col3.h47
-rw-r--r--thirdparty/embree/common/math/col4.h47
-rw-r--r--thirdparty/embree/common/math/color.h241
-rw-r--r--thirdparty/embree/common/math/constants.cpp27
-rw-r--r--thirdparty/embree/common/math/constants.h197
-rw-r--r--thirdparty/embree/common/math/interval.h161
-rw-r--r--thirdparty/embree/common/math/lbbox.h289
-rw-r--r--thirdparty/embree/common/math/linearspace2.h148
-rw-r--r--thirdparty/embree/common/math/linearspace3.h213
-rw-r--r--thirdparty/embree/common/math/math.h369
-rw-r--r--thirdparty/embree/common/math/obbox.h39
-rw-r--r--thirdparty/embree/common/math/quaternion.h254
-rw-r--r--thirdparty/embree/common/math/range.h137
-rw-r--r--thirdparty/embree/common/math/transcendental.h525
-rw-r--r--thirdparty/embree/common/math/vec2.h235
-rw-r--r--thirdparty/embree/common/math/vec2fa.h301
-rw-r--r--thirdparty/embree/common/math/vec3.h337
-rw-r--r--thirdparty/embree/common/math/vec3ba.h120
-rw-r--r--thirdparty/embree/common/math/vec3fa.h727
-rw-r--r--thirdparty/embree/common/math/vec3ia.h186
-rw-r--r--thirdparty/embree/common/math/vec4.h243
-rw-r--r--thirdparty/embree/common/simd/arm/emulation.h50
-rw-r--r--thirdparty/embree/common/simd/arm/sse2neon.h6996
-rw-r--r--thirdparty/embree/common/simd/avx.h34
-rw-r--r--thirdparty/embree/common/simd/avx512.h41
-rw-r--r--thirdparty/embree/common/simd/simd.h110
-rw-r--r--thirdparty/embree/common/simd/sse.cpp34
-rw-r--r--thirdparty/embree/common/simd/sse.h35
-rw-r--r--thirdparty/embree/common/simd/varying.h145
-rw-r--r--thirdparty/embree/common/simd/vboold4_avx.h169
-rw-r--r--thirdparty/embree/common/simd/vboold4_avx512.h156
-rw-r--r--thirdparty/embree/common/simd/vboold8_avx512.h151
-rw-r--r--thirdparty/embree/common/simd/vboolf16_avx512.h153
-rw-r--r--thirdparty/embree/common/simd/vboolf4_avx512.h159
-rw-r--r--thirdparty/embree/common/simd/vboolf4_sse2.h189
-rw-r--r--thirdparty/embree/common/simd/vboolf8_avx.h202
-rw-r--r--thirdparty/embree/common/simd/vboolf8_avx512.h159
-rw-r--r--thirdparty/embree/common/simd/vdouble4_avx.h321
-rw-r--r--thirdparty/embree/common/simd/vdouble8_avx512.h351
-rw-r--r--thirdparty/embree/common/simd/vfloat16_avx512.h615
-rw-r--r--thirdparty/embree/common/simd/vfloat4_sse2.h722
-rw-r--r--thirdparty/embree/common/simd/vfloat8_avx.h758
-rw-r--r--thirdparty/embree/common/simd/vint16_avx512.h472
-rw-r--r--thirdparty/embree/common/simd/vint4_sse2.h598
-rw-r--r--thirdparty/embree/common/simd/vint8_avx.h470
-rw-r--r--thirdparty/embree/common/simd/vint8_avx2.h518
-rw-r--r--thirdparty/embree/common/simd/vllong4_avx2.h352
-rw-r--r--thirdparty/embree/common/simd/vllong8_avx512.h358
-rw-r--r--thirdparty/embree/common/simd/vuint16_avx512.h424
-rw-r--r--thirdparty/embree/common/simd/vuint4_sse2.h426
-rw-r--r--thirdparty/embree/common/simd/vuint8_avx.h386
-rw-r--r--thirdparty/embree/common/simd/vuint8_avx2.h446
-rw-r--r--thirdparty/embree/common/sys/alloc.cpp327
-rw-r--r--thirdparty/embree/common/sys/alloc.h164
-rw-r--r--thirdparty/embree/common/sys/array.h222
-rw-r--r--thirdparty/embree/common/sys/atomic.h59
-rw-r--r--thirdparty/embree/common/sys/barrier.cpp289
-rw-r--r--thirdparty/embree/common/sys/barrier.h112
-rw-r--r--thirdparty/embree/common/sys/condition.cpp85
-rw-r--r--thirdparty/embree/common/sys/condition.h31
-rw-r--r--thirdparty/embree/common/sys/filename.cpp138
-rw-r--r--thirdparty/embree/common/sys/filename.h81
-rw-r--r--thirdparty/embree/common/sys/intrinsics.h525
-rw-r--r--thirdparty/embree/common/sys/library.cpp83
-rw-r--r--thirdparty/embree/common/sys/library.h21
-rw-r--r--thirdparty/embree/common/sys/mutex.cpp57
-rw-r--r--thirdparty/embree/common/sys/mutex.h98
-rw-r--r--thirdparty/embree/common/sys/platform.h392
-rw-r--r--thirdparty/embree/common/sys/ref.h122
-rw-r--r--thirdparty/embree/common/sys/regression.cpp30
-rw-r--r--thirdparty/embree/common/sys/regression.h25
-rw-r--r--thirdparty/embree/common/sys/string.cpp42
-rw-r--r--thirdparty/embree/common/sys/string.h37
-rw-r--r--thirdparty/embree/common/sys/sysinfo.cpp656
-rw-r--r--thirdparty/embree/common/sys/sysinfo.h178
-rw-r--r--thirdparty/embree/common/sys/thread.cpp474
-rw-r--r--thirdparty/embree/common/sys/thread.h49
-rw-r--r--thirdparty/embree/common/sys/vector.h242
-rw-r--r--thirdparty/embree/common/tasking/taskscheduler.h15
-rw-r--r--thirdparty/embree/common/tasking/taskschedulerinternal.cpp420
-rw-r--r--thirdparty/embree/common/tasking/taskschedulerinternal.h385
-rw-r--r--thirdparty/embree/common/tasking/taskschedulerppl.h46
-rw-r--r--thirdparty/embree/common/tasking/taskschedulertbb.h73
-rw-r--r--thirdparty/embree/include/embree3/rtcore.h14
-rw-r--r--thirdparty/embree/include/embree3/rtcore_buffer.h51
-rw-r--r--thirdparty/embree/include/embree3/rtcore_builder.h125
-rw-r--r--thirdparty/embree/include/embree3/rtcore_common.h328
-rw-r--r--thirdparty/embree/include/embree3/rtcore_config.h57
-rw-r--r--thirdparty/embree/include/embree3/rtcore_device.h87
-rw-r--r--thirdparty/embree/include/embree3/rtcore_geometry.h383
-rw-r--r--thirdparty/embree/include/embree3/rtcore_quaternion.h101
-rw-r--r--thirdparty/embree/include/embree3/rtcore_ray.h378
-rw-r--r--thirdparty/embree/include/embree3/rtcore_scene.h160
-rw-r--r--thirdparty/embree/kernels/builders/bvh_builder_hair.h411
-rw-r--r--thirdparty/embree/kernels/builders/bvh_builder_morton.h501
-rw-r--r--thirdparty/embree/kernels/builders/bvh_builder_msmblur.h692
-rw-r--r--thirdparty/embree/kernels/builders/bvh_builder_msmblur_hair.h526
-rw-r--r--thirdparty/embree/kernels/builders/bvh_builder_sah.h669
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_binning.h496
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_binning_array_aligned.h200
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_binning_array_unaligned.h302
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_openmerge_array.h443
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_spatial.h414
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_spatial_array.h546
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_strand_array.h188
-rw-r--r--thirdparty/embree/kernels/builders/heuristic_timesplit_array.h237
-rw-r--r--thirdparty/embree/kernels/builders/priminfo.h362
-rw-r--r--thirdparty/embree/kernels/builders/primrefgen.cpp312
-rw-r--r--thirdparty/embree/kernels/builders/primrefgen.h34
-rw-r--r--thirdparty/embree/kernels/builders/primrefgen_presplit.h371
-rw-r--r--thirdparty/embree/kernels/builders/splitter.h191
-rw-r--r--thirdparty/embree/kernels/bvh/bvh.cpp190
-rw-r--r--thirdparty/embree/kernels/bvh/bvh.h235
-rw-r--r--thirdparty/embree/kernels/bvh/bvh4_factory.cpp1325
-rw-r--r--thirdparty/embree/kernels/bvh/bvh4_factory.h316
-rw-r--r--thirdparty/embree/kernels/bvh/bvh8_factory.cpp1165
-rw-r--r--thirdparty/embree/kernels/bvh/bvh8_factory.h280
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder.cpp60
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder.h115
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder_morton.cpp531
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder_sah.cpp543
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder_sah_mb.cpp705
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder_sah_spatial.cpp201
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder_twolevel.cpp369
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder_twolevel.h263
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_builder_twolevel_internal.h267
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_collider.cpp375
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_collider.h72
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_factory.h21
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_intersector1.cpp321
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_intersector1.h34
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_intersector1_bvh4.cpp61
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.h58
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_intersector_stream.h270
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_intersector_stream_filters.h41
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_aabb.h213
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h247
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h107
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_base.h43
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_obb.h98
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_obb_mb.h90
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_qaabb.h265
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_node_ref.h242
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_refit.cpp247
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_refit.h95
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_rotate.cpp127
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_rotate.h37
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_statistics.cpp168
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_statistics.h285
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_traverser1.h466
-rw-r--r--thirdparty/embree/kernels/bvh/bvh_traverser_stream.h149
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector.h31
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector1.h1403
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector_frustum.h241
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector_packet.h805
-rw-r--r--thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h189
-rw-r--r--thirdparty/embree/kernels/common/accel.h556
-rw-r--r--thirdparty/embree/kernels/common/accelinstance.h41
-rw-r--r--thirdparty/embree/kernels/common/acceln.cpp232
-rw-r--r--thirdparty/embree/kernels/common/acceln.h49
-rw-r--r--thirdparty/embree/kernels/common/accelset.cpp17
-rw-r--r--thirdparty/embree/kernels/common/accelset.h248
-rw-r--r--thirdparty/embree/kernels/common/alloc.cpp79
-rw-r--r--thirdparty/embree/kernels/common/alloc.h958
-rw-r--r--thirdparty/embree/kernels/common/buffer.h263
-rw-r--r--thirdparty/embree/kernels/common/builder.h60
-rw-r--r--thirdparty/embree/kernels/common/context.h131
-rw-r--r--thirdparty/embree/kernels/common/default.h268
-rw-r--r--thirdparty/embree/kernels/common/device.cpp556
-rw-r--r--thirdparty/embree/kernels/common/device.h85
-rw-r--r--thirdparty/embree/kernels/common/geometry.cpp259
-rw-r--r--thirdparty/embree/kernels/common/geometry.h582
-rw-r--r--thirdparty/embree/kernels/common/hit.h114
-rw-r--r--thirdparty/embree/kernels/common/instance_stack.h179
-rw-r--r--thirdparty/embree/kernels/common/isa.h246
-rw-r--r--thirdparty/embree/kernels/common/motion_derivative.h325
-rw-r--r--thirdparty/embree/kernels/common/point_query.h136
-rw-r--r--thirdparty/embree/kernels/common/primref.h138
-rw-r--r--thirdparty/embree/kernels/common/primref_mb.h262
-rw-r--r--thirdparty/embree/kernels/common/profile.h159
-rw-r--r--thirdparty/embree/kernels/common/ray.h1517
-rw-r--r--thirdparty/embree/kernels/common/rtcore.cpp1766
-rw-r--r--thirdparty/embree/kernels/common/rtcore.h142
-rw-r--r--thirdparty/embree/kernels/common/rtcore_builder.cpp442
-rw-r--r--thirdparty/embree/kernels/common/scene.cpp955
-rw-r--r--thirdparty/embree/kernels/common/scene.h390
-rw-r--r--thirdparty/embree/kernels/common/scene_curves.h688
-rw-r--r--thirdparty/embree/kernels/common/scene_grid_mesh.h294
-rw-r--r--thirdparty/embree/kernels/common/scene_instance.h272
-rw-r--r--thirdparty/embree/kernels/common/scene_line_segments.h345
-rw-r--r--thirdparty/embree/kernels/common/scene_points.h282
-rw-r--r--thirdparty/embree/kernels/common/scene_quad_mesh.h337
-rw-r--r--thirdparty/embree/kernels/common/scene_subdiv_mesh.h326
-rw-r--r--thirdparty/embree/kernels/common/scene_triangle_mesh.cpp194
-rw-r--r--thirdparty/embree/kernels/common/scene_triangle_mesh.h318
-rw-r--r--thirdparty/embree/kernels/common/scene_user_geometry.h77
-rw-r--r--thirdparty/embree/kernels/common/stack_item.h125
-rw-r--r--thirdparty/embree/kernels/common/stat.cpp128
-rw-r--r--thirdparty/embree/kernels/common/stat.h116
-rw-r--r--thirdparty/embree/kernels/common/state.cpp519
-rw-r--r--thirdparty/embree/kernels/common/state.h196
-rw-r--r--thirdparty/embree/kernels/common/vector.h76
-rw-r--r--thirdparty/embree/kernels/config.h (renamed from thirdparty/embree-aarch64/kernels/config.h)0
-rw-r--r--thirdparty/embree/kernels/geometry/cone.h321
-rw-r--r--thirdparty/embree/kernels/geometry/coneline_intersector.h209
-rw-r--r--thirdparty/embree/kernels/geometry/conelinei_intersector.h141
-rw-r--r--thirdparty/embree/kernels/geometry/curveNi.h222
-rw-r--r--thirdparty/embree/kernels/geometry/curveNi_intersector.h569
-rw-r--r--thirdparty/embree/kernels/geometry/curveNi_mb.h278
-rw-r--r--thirdparty/embree/kernels/geometry/curveNi_mb_intersector.h516
-rw-r--r--thirdparty/embree/kernels/geometry/curveNv.h101
-rw-r--r--thirdparty/embree/kernels/geometry/curveNv_intersector.h181
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector.h98
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector_distance.h129
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector_oriented.h417
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector_precalculations.h49
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector_ribbon.h216
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector_sweep.h364
-rw-r--r--thirdparty/embree/kernels/geometry/curve_intersector_virtual.h671
-rw-r--r--thirdparty/embree/kernels/geometry/cylinder.h223
-rw-r--r--thirdparty/embree/kernels/geometry/disc_intersector.h216
-rw-r--r--thirdparty/embree/kernels/geometry/disci_intersector.h277
-rw-r--r--thirdparty/embree/kernels/geometry/filter.h204
-rw-r--r--thirdparty/embree/kernels/geometry/grid_intersector.h99
-rw-r--r--thirdparty/embree/kernels/geometry/grid_soa.h275
-rw-r--r--thirdparty/embree/kernels/geometry/grid_soa_intersector1.h207
-rw-r--r--thirdparty/embree/kernels/geometry/grid_soa_intersector_packet.h445
-rw-r--r--thirdparty/embree/kernels/geometry/instance.h78
-rw-r--r--thirdparty/embree/kernels/geometry/instance_intersector.h84
-rw-r--r--thirdparty/embree/kernels/geometry/intersector_epilog.h979
-rw-r--r--thirdparty/embree/kernels/geometry/intersector_iterators.h172
-rw-r--r--thirdparty/embree/kernels/geometry/line_intersector.h145
-rw-r--r--thirdparty/embree/kernels/geometry/linei.h705
-rw-r--r--thirdparty/embree/kernels/geometry/linei_intersector.h124
-rw-r--r--thirdparty/embree/kernels/geometry/object.h84
-rw-r--r--thirdparty/embree/kernels/geometry/object_intersector.h127
-rw-r--r--thirdparty/embree/kernels/geometry/plane.h57
-rw-r--r--thirdparty/embree/kernels/geometry/pointi.h412
-rw-r--r--thirdparty/embree/kernels/geometry/primitive.h49
-rw-r--r--thirdparty/embree/kernels/geometry/primitive4.cpp379
-rw-r--r--thirdparty/embree/kernels/geometry/quad_intersector.h76
-rw-r--r--thirdparty/embree/kernels/geometry/quad_intersector_moeller.h460
-rw-r--r--thirdparty/embree/kernels/geometry/quad_intersector_pluecker.h438
-rw-r--r--thirdparty/embree/kernels/geometry/quadi.h483
-rw-r--r--thirdparty/embree/kernels/geometry/quadi_intersector.h350
-rw-r--r--thirdparty/embree/kernels/geometry/quadv.h165
-rw-r--r--thirdparty/embree/kernels/geometry/quadv_intersector.h181
-rw-r--r--thirdparty/embree/kernels/geometry/roundline_intersector.h715
-rw-r--r--thirdparty/embree/kernels/geometry/roundlinei_intersector.h123
-rw-r--r--thirdparty/embree/kernels/geometry/sphere_intersector.h183
-rw-r--r--thirdparty/embree/kernels/geometry/spherei_intersector.h156
-rw-r--r--thirdparty/embree/kernels/geometry/subdivpatch1.h38
-rw-r--r--thirdparty/embree/kernels/geometry/subdivpatch1_intersector.h237
-rw-r--r--thirdparty/embree/kernels/geometry/subgrid.h517
-rw-r--r--thirdparty/embree/kernels/geometry/subgrid_intersector.h517
-rw-r--r--thirdparty/embree/kernels/geometry/subgrid_intersector_moeller.h382
-rw-r--r--thirdparty/embree/kernels/geometry/subgrid_intersector_pluecker.h367
-rw-r--r--thirdparty/embree/kernels/geometry/subgrid_mb_intersector.h236
-rw-r--r--thirdparty/embree/kernels/geometry/triangle.h162
-rw-r--r--thirdparty/embree/kernels/geometry/triangle_intersector.h96
-rw-r--r--thirdparty/embree/kernels/geometry/triangle_intersector_moeller.h525
-rw-r--r--thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h407
-rw-r--r--thirdparty/embree/kernels/geometry/triangle_intersector_woop.h418
-rw-r--r--thirdparty/embree/kernels/geometry/triangle_triangle_intersector.h132
-rw-r--r--thirdparty/embree/kernels/geometry/trianglei.h442
-rw-r--r--thirdparty/embree/kernels/geometry/trianglei_intersector.h336
-rw-r--r--thirdparty/embree/kernels/geometry/trianglev.h157
-rw-r--r--thirdparty/embree/kernels/geometry/trianglev_intersector.h206
-rw-r--r--thirdparty/embree/kernels/geometry/trianglev_mb.h201
-rw-r--r--thirdparty/embree/kernels/geometry/trianglev_mb_intersector.h211
-rw-r--r--thirdparty/embree/kernels/hash.h5
-rw-r--r--thirdparty/embree/kernels/subdiv/bezier_curve.h671
-rw-r--r--thirdparty/embree/kernels/subdiv/bezier_patch.h372
-rw-r--r--thirdparty/embree/kernels/subdiv/bilinear_patch.h191
-rw-r--r--thirdparty/embree/kernels/subdiv/bspline_curve.h320
-rw-r--r--thirdparty/embree/kernels/subdiv/bspline_patch.h449
-rw-r--r--thirdparty/embree/kernels/subdiv/catmullclark_coefficients.h85
-rw-r--r--thirdparty/embree/kernels/subdiv/catmullclark_patch.h562
-rw-r--r--thirdparty/embree/kernels/subdiv/catmullclark_ring.h826
-rw-r--r--thirdparty/embree/kernels/subdiv/catmullrom_curve.h297
-rw-r--r--thirdparty/embree/kernels/subdiv/feature_adaptive_eval.h226
-rw-r--r--thirdparty/embree/kernels/subdiv/feature_adaptive_eval_grid.h359
-rw-r--r--thirdparty/embree/kernels/subdiv/feature_adaptive_eval_simd.h186
-rw-r--r--thirdparty/embree/kernels/subdiv/gregory_patch.h893
-rw-r--r--thirdparty/embree/kernels/subdiv/gregory_patch_dense.h113
-rw-r--r--thirdparty/embree/kernels/subdiv/gridrange.h96
-rw-r--r--thirdparty/embree/kernels/subdiv/half_edge.h371
-rw-r--r--thirdparty/embree/kernels/subdiv/hermite_curve.h39
-rw-r--r--thirdparty/embree/kernels/subdiv/linear_bezier_patch.h403
-rw-r--r--thirdparty/embree/kernels/subdiv/patch.h371
-rw-r--r--thirdparty/embree/kernels/subdiv/patch_eval.h129
-rw-r--r--thirdparty/embree/kernels/subdiv/patch_eval_grid.h245
-rw-r--r--thirdparty/embree/kernels/subdiv/patch_eval_simd.h127
-rw-r--r--thirdparty/embree/kernels/subdiv/subdivpatch1base.h156
-rw-r--r--thirdparty/embree/kernels/subdiv/tessellation.h161
-rw-r--r--thirdparty/embree/kernels/subdiv/tessellation_cache.h325
-rw-r--r--thirdparty/embree/patches/godot-changes-android.patch103
-rw-r--r--thirdparty/embree/patches/godot-changes-misc.patch105
-rw-r--r--thirdparty/embree/patches/godot-changes-noexcept.patch630
-rw-r--r--thirdparty/embree/patches/godot-changes-ubsan.patch24
-rw-r--r--thirdparty/fonts/OpenSans_SemiBold.ttfbin0 -> 100820 bytes
-rw-r--r--thirdparty/meshoptimizer/meshoptimizer.h5
-rw-r--r--thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch262
-rw-r--r--thirdparty/meshoptimizer/simplifier.cpp168
-rw-r--r--thirdparty/misc/patches/polypartition-godot-types.patch14
-rw-r--r--thirdparty/misc/polypartition.cpp10
-rw-r--r--thirdparty/misc/smolv.cpp2108
-rw-r--r--thirdparty/misc/smolv.h169
2442 files changed, 150629 insertions, 163213 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index bc56cba21b..0000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-name: Bug report
-about: Report a bug in Godot
-title: ''
-labels: ''
-assignees: ''
-
----
-<!-- Please search existing issues for potential duplicates before filing yours:
-https://github.com/godotengine/godot/issues?q=is%3Aissue
--->
-
-**Godot version:**
-<!-- Specify commit hash if using non-official build. -->
-
-
-**OS/device including version:**
-<!-- Specify GPU model, drivers, and the backend (GLES2, GLES3, Vulkan) if graphics-related. -->
-
-
-**Issue description:**
-<!-- What happened, and what was expected. -->
-
-
-**Steps to reproduce:**
-
-
-**Minimal reproduction project:**
-<!-- A small Godot project which reproduces the issue. Drag and drop a zip archive to upload it. -->
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000000..43ba5ef357
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,56 @@
+name: Bug report
+description: Report a bug in Godot
+body:
+
+- type: markdown
+ attributes:
+ value: |
+ - Read our [CONTRIBUTING.md guide](CONTRIBUTING.md#reporting-bugs) on reporting bugs.
+ - Write a descriptive issue title above.
+ - Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported.
+ - Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/stable/about/release_policy.html).
+
+- type: input
+ attributes:
+ label: Godot version
+ description: >
+ Specify the Git commit hash if using a development or non-official build.
+ If you use a custom build, please test if your issue is reproducible in official builds too.
+ placeholder: 3.3.stable, 4.0.dev (3041becc6)
+ validations:
+ required: true
+
+- type: input
+ attributes:
+ label: System information
+ description: |
+ Specify the OS version, and when relevant hardware information.
+ For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
+ placeholder: Windows 10, GLES3, Intel HD Graphics 620 (27.20.100.9616)
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Issue description
+ description: |
+ Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
+ You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Steps to reproduce
+ description: |
+ List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
+ If you include a minimal reproduction project below, you can detail how to use it here.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Minimal reproduction project
+ description: |
+ A small Godot project which reproduces the issue. Highly recommended to speed up troubleshooting.
+ Drag and drop a ZIP archive to upload it.
diff --git a/.github/workflows/android_builds.yml b/.github/workflows/android_builds.yml
index b24a36beef..63930aa9e2 100644
--- a/.github/workflows/android_builds.yml
+++ b/.github/workflows/android_builds.yml
@@ -6,7 +6,6 @@ env:
GODOT_BASE_BRANCH: master
SCONSFLAGS: platform=android verbose=yes warnings=extra werror=yes debug_symbols=no --jobs=2 module_text_server_fb_enabled=yes
SCONS_CACHE_LIMIT: 4096
- ANDROID_NDK_VERSION: 21.1.6352462
jobs:
android-template:
@@ -29,10 +28,6 @@ jobs:
with:
java-version: 8
- - name: Install Android NDK r21
- run: |
- sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install 'ndk;${{env.ANDROID_NDK_VERSION}}'
-
# Upload cache on completion and check it out now
- name: Load .scons_cache directory
id: android-template-cache
@@ -64,7 +59,6 @@ jobs:
- name: Compilation
env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
- ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/${{env.ANDROID_NDK_VERSION}}/
run: |
scons target=release tools=no android_arch=armv7
scons target=release tools=no android_arch=arm64v8
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 0982d768d6..b4bbaaacb1 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -144,7 +144,7 @@ jobs:
scons --version
# We should always be explicit with our flags usage here since it's gonna be sure to always set those flags
- # [Workaround] SwiftShader doesn't support tesselation, so we skip Godot check about it
+ # [Workaround] SwiftShader doesn't support tessellation, so we skip Godot check about it
- name: Compilation
env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml
index b7cc127226..d1db449ab0 100644
--- a/.github/workflows/windows_builds.yml
+++ b/.github/workflows/windows_builds.yml
@@ -46,7 +46,7 @@ jobs:
- name: Configuring Python packages
run: |
python -c "import sys; print(sys.version)"
- python -m pip install scons pywin32
+ python -m pip install scons
python --version
scons --version
@@ -102,7 +102,7 @@ jobs:
- name: Configuring Python packages
run: |
python -c "import sys; print(sys.version)"
- python -m pip install scons pywin32
+ python -m pip install scons
python --version
scons --version
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index cfd983bb0a..b2a930a4bb 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -55,6 +55,14 @@ Comment: Godot Engine logo
Copyright: 2017, Andrea Calabró
License: CC-BY-4.0
+Files: ./core/math/convex_hull.cpp
+ ./core/math/convex_hull.h
+Comment: Bullet Continuous Collision Detection and Physics Library
+Copyright: 2011, Ole Kniemeyer, MAXON, www.maxon.net
+ 2007-2021, Juan Linietsky, Ariel Manzur.
+ 2014-2021, Godot Engine contributors.
+License: Expat and Zlib
+
Files: ./modules/fbx/fbx_parser/
Comment: Open Asset Import Library (FBX parser)
Copyright: 2006-2020, assimp team
@@ -131,8 +139,8 @@ Comment: doctest
Copyright: 2016-2020, Viktor Kirilov
License: Expat
-Files: ./thirdparty/embree-aarch64/
-Comment: Embree-aarch64
+Files: ./thirdparty/embree/
+Comment: Embree
Copyright: 2009-2021 Intel Corporation
License: Apache-2.0
@@ -352,6 +360,12 @@ Comment: SMAZ
Copyright: 2006-2009, Salvatore Sanfilippo
License: BSD-3-clause
+Files: ./thirdparty/misc/smolv.cpp
+ ./thirdparty/misc/smolv.h
+Comment: SMOL-V
+Copyright: 2016-2020, Aras Pranckevicius
+License: public-domain or Unlicense or Expat
+
Files: ./thirdparty/misc/stb_rect_pack.h
./thirdparty/misc/stb_vorbis.c
Comment: stb libraries
diff --git a/DONORS.md b/DONORS.md
index 70eb8a7e5a..a903a8b38c 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -7,7 +7,7 @@ support of generous donors.
The ways to donate to the project, as well as details on how the funds are
used, are described on [Godot's website](https://godotengine.org/donate).
-The following is a list of the current monthly donors, to be have their
+The following is a list of the current monthly donors, who will have their
generous deed immortalized in the next stable release of Godot Engine.
## Platinum sponsors
diff --git a/SConstruct b/SConstruct
index 6516b42e59..f8e3a68edd 100644
--- a/SConstruct
+++ b/SConstruct
@@ -123,6 +123,7 @@ opts.Add(BoolVariable("use_lto", "Use link-time optimization", False))
opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
+opts.Add(BoolVariable("vulkan", "Enable the vulkan video driver", True))
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
@@ -409,14 +410,27 @@ if selected_platform in platform_list:
env.Prepend(CCFLAGS=["/std:c++17"])
# Enforce our minimal compiler version requirements
- cc_version = methods.get_compiler_version(env) or [-1, -1]
- cc_version_major = cc_version[0]
- cc_version_minor = cc_version[1]
+ cc_version = methods.get_compiler_version(env) or {
+ "major": None,
+ "minor": None,
+ "patch": None,
+ "metadata1": None,
+ "metadata2": None,
+ "date": None,
+ }
+ cc_version_major = int(cc_version["major"] or -1)
+ cc_version_minor = int(cc_version["minor"] or -1)
+ cc_version_metadata1 = cc_version["metadata1"] or ""
if methods.using_gcc(env):
+ if cc_version_major == -1:
+ print(
+ "Couldn't detect compiler version, skipping version checks. "
+ "Build may fail if the compiler doesn't support C++17 fully."
+ )
# GCC 8 before 8.4 has a regression in the support of guaranteed copy elision
# which causes a build failure: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521
- if cc_version_major == 8 and cc_version_minor < 4:
+ elif cc_version_major == 8 and cc_version_minor < 4:
print(
"Detected GCC 8 version < 8.4, which is not supported due to a "
"regression in its C++17 guaranteed copy elision support. Use a "
@@ -432,10 +446,23 @@ if selected_platform in platform_list:
"SCons command line."
)
Exit(255)
+ elif cc_version_metadata1 == "win32":
+ print(
+ "Detected mingw version is not using posix threads. Only posix "
+ "version of mingw is supported. "
+ 'Use "update-alternatives --config <platform>-w64-mingw32-[gcc|g++]" '
+ "to switch to posix threads."
+ )
+ Exit(255)
elif methods.using_clang(env):
+ if cc_version_major == -1:
+ print(
+ "Couldn't detect compiler version, skipping version checks. "
+ "Build may fail if the compiler doesn't support C++17 fully."
+ )
# Apple LLVM versions differ from upstream LLVM version \o/, compare
# in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
- if env["platform"] == "osx" or env["platform"] == "iphone":
+ elif env["platform"] == "osx" or env["platform"] == "iphone":
vanilla = methods.is_vanilla_clang(env)
if vanilla and cc_version_major < 6:
print(
@@ -639,20 +666,19 @@ if selected_platform in platform_list:
if not env["verbose"]:
methods.no_verbose(sys, env)
- if not env["platform"] == "server":
- GLSL_BUILDERS = {
- "RD_GLSL": env.Builder(
- action=env.Run(glsl_builders.build_rd_headers, 'Building RD_GLSL header: "$TARGET"'),
- suffix="glsl.gen.h",
- src_suffix=".glsl",
- ),
- "GLSL_HEADER": env.Builder(
- action=env.Run(glsl_builders.build_raw_headers, 'Building GLSL header: "$TARGET"'),
- suffix="glsl.gen.h",
- src_suffix=".glsl",
- ),
- }
- env.Append(BUILDERS=GLSL_BUILDERS)
+ GLSL_BUILDERS = {
+ "RD_GLSL": env.Builder(
+ action=env.Run(glsl_builders.build_rd_headers, 'Building RD_GLSL header: "$TARGET"'),
+ suffix="glsl.gen.h",
+ src_suffix=".glsl",
+ ),
+ "GLSL_HEADER": env.Builder(
+ action=env.Run(glsl_builders.build_raw_headers, 'Building GLSL header: "$TARGET"'),
+ suffix="glsl.gen.h",
+ src_suffix=".glsl",
+ ),
+ }
+ env.Append(BUILDERS=GLSL_BUILDERS)
scons_cache_path = os.environ.get("SCONS_CACHE")
if scons_cache_path != None:
diff --git a/core/SCsub b/core/SCsub
index bdf8544840..e3ba46be02 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -59,6 +59,7 @@ thirdparty_misc_sources = [
"pcg.cpp",
"polypartition.cpp",
"clipper.cpp",
+ "smolv.cpp",
]
thirdparty_misc_sources = [thirdparty_misc_dir + file for file in thirdparty_misc_sources]
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_misc_sources)
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 2360d66438..99ec1aeb5b 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -31,6 +31,7 @@
#include "engine.h"
#include "core/authors.gen.h"
+#include "core/config/project_settings.h"
#include "core/donors.gen.h"
#include "core/license.gen.h"
#include "core/version.h"
@@ -210,6 +211,13 @@ void Engine::get_singletons(List<Singleton> *p_singletons) {
}
}
+void Engine::set_shader_cache_path(const String &p_path) {
+ shader_cache_path = p_path;
+}
+String Engine::get_shader_cache_path() const {
+ return shader_cache_path;
+}
+
Engine *Engine::singleton = nullptr;
Engine *Engine::get_singleton() {
@@ -224,9 +232,9 @@ Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr) :
name(p_name),
ptr(p_ptr) {
#ifdef DEBUG_ENABLED
- Reference *ref = Object::cast_to<Reference>(p_ptr);
- if (ref && !ref->is_referenced()) {
- WARN_PRINT("You must use Ref<> to ensure the lifetime of a Reference object intended to be used as a singleton.");
+ RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
+ if (rc && !rc->is_referenced()) {
+ WARN_PRINT("You must use Ref<> to ensure the lifetime of a RefCounted object intended to be used as a singleton.");
}
#endif
}
diff --git a/core/config/engine.h b/core/config/engine.h
index a9080e3dfd..276da1c7ea 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -72,6 +72,8 @@ private:
static Engine *singleton;
+ String shader_cache_path;
+
public:
static Engine *get_singleton();
@@ -121,6 +123,9 @@ public:
Dictionary get_license_info() const;
String get_license_text() const;
+ void set_shader_cache_path(const String &p_path);
+ String get_shader_cache_path() const;
+
bool is_abort_on_gpu_errors_enabled() const;
bool is_validation_layers_enabled() const;
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 0d699cdacb..590c3ff50e 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -33,11 +33,11 @@
#include "core/core_bind.h"
#include "core/core_string_names.h"
#include "core/input/input_map.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_network.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
@@ -62,7 +62,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
}
if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
- (p_path.is_abs_path() && !p_path.begins_with(resource_path))) {
+ (p_path.is_absolute_path() && !p_path.begins_with(resource_path))) {
return p_path.simplify_path();
}
@@ -1102,7 +1102,7 @@ ProjectSettings::ProjectSettings() {
if (Engine::get_singleton()->has_singleton("GodotSharp")) {
extensions.push_back("cs");
}
- extensions.push_back("shader");
+ extensions.push_back("gdshader");
GLOBAL_DEF("editor/run/main_run_args", "");
@@ -1114,7 +1114,8 @@ ProjectSettings::ProjectSettings() {
_add_builtin_input_map();
- custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::STRING, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor");
+ // Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum.
+ custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::INT, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor");
custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
GLOBAL_DEF("physics/2d/run_on_thread", false);
GLOBAL_DEF("physics/3d/run_on_thread", false);
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 84d8d0d4d3..60759cd71c 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -42,28 +42,6 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
-/**
- * Time constants borrowed from loc_time.h
- */
-#define EPOCH_YR 1970 /* EPOCH = Jan 1 1970 00:00:00 */
-#define SECS_DAY (24L * 60L * 60L)
-#define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
-#define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
-#define SECOND_KEY "second"
-#define MINUTE_KEY "minute"
-#define HOUR_KEY "hour"
-#define DAY_KEY "day"
-#define MONTH_KEY "month"
-#define YEAR_KEY "year"
-#define WEEKDAY_KEY "weekday"
-#define DST_KEY "dst"
-
-/// Table of number of days in each month (for regular year and leap year)
-static const unsigned int MONTH_DAYS_TABLE[2][12] = {
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
-};
-
////// _ResourceLoader //////
_ResourceLoader *_ResourceLoader::singleton = nullptr;
@@ -322,198 +300,6 @@ uint64_t _OS::get_static_memory_peak_usage() const {
return OS::get_singleton()->get_static_memory_peak_usage();
}
-/**
- * Get current datetime with consideration for utc and
- * dst
- */
-Dictionary _OS::get_datetime(bool utc) const {
- Dictionary dated = get_date(utc);
- Dictionary timed = get_time(utc);
-
- List<Variant> keys;
- timed.get_key_list(&keys);
-
- for (int i = 0; i < keys.size(); i++) {
- dated[keys[i]] = timed[keys[i]];
- }
-
- return dated;
-}
-
-Dictionary _OS::get_date(bool utc) const {
- OS::Date date = OS::get_singleton()->get_date(utc);
- Dictionary dated;
- dated[YEAR_KEY] = date.year;
- dated[MONTH_KEY] = date.month;
- dated[DAY_KEY] = date.day;
- dated[WEEKDAY_KEY] = date.weekday;
- dated[DST_KEY] = date.dst;
- return dated;
-}
-
-Dictionary _OS::get_time(bool utc) const {
- OS::Time time = OS::get_singleton()->get_time(utc);
- Dictionary timed;
- timed[HOUR_KEY] = time.hour;
- timed[MINUTE_KEY] = time.min;
- timed[SECOND_KEY] = time.sec;
- return timed;
-}
-
-/**
- * Get an epoch time value from a dictionary of time values
- * @p datetime must be populated with the following keys:
- * day, hour, minute, month, second, year. (dst is ignored).
- *
- * You can pass the output from
- * get_datetime_from_unix_time directly into this function
- *
- * @param datetime dictionary of date and time values to convert
- *
- * @return epoch calculated
- */
-int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
- // if datetime is an empty Dictionary throws an error
- ERR_FAIL_COND_V_MSG(datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty");
-
- // Bunch of conversion constants
- static const unsigned int SECONDS_PER_MINUTE = 60;
- static const unsigned int MINUTES_PER_HOUR = 60;
- static const unsigned int HOURS_PER_DAY = 24;
- static const unsigned int SECONDS_PER_HOUR = MINUTES_PER_HOUR * SECONDS_PER_MINUTE;
- static const unsigned int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
-
- // Get all time values from the dictionary, set to zero if it doesn't exist.
- // Risk incorrect calculation over throwing errors
- unsigned int second = ((datetime.has(SECOND_KEY)) ? static_cast<unsigned int>(datetime[SECOND_KEY]) : 0);
- unsigned int minute = ((datetime.has(MINUTE_KEY)) ? static_cast<unsigned int>(datetime[MINUTE_KEY]) : 0);
- unsigned int hour = ((datetime.has(HOUR_KEY)) ? static_cast<unsigned int>(datetime[HOUR_KEY]) : 0);
- unsigned int day = ((datetime.has(DAY_KEY)) ? static_cast<unsigned int>(datetime[DAY_KEY]) : 1);
- unsigned int month = ((datetime.has(MONTH_KEY)) ? static_cast<unsigned int>(datetime[MONTH_KEY]) : 1);
- unsigned int year = ((datetime.has(YEAR_KEY)) ? static_cast<unsigned int>(datetime[YEAR_KEY]) : 0);
-
- /// How many days come before each month (0-12)
- static const unsigned short int DAYS_PAST_THIS_YEAR_TABLE[2][13] = {
- /* Normal years. */
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- /* Leap years. */
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
- };
-
- ERR_FAIL_COND_V_MSG(second > 59, 0, "Invalid second value of: " + itos(second) + ".");
-
- ERR_FAIL_COND_V_MSG(minute > 59, 0, "Invalid minute value of: " + itos(minute) + ".");
-
- ERR_FAIL_COND_V_MSG(hour > 23, 0, "Invalid hour value of: " + itos(hour) + ".");
-
- ERR_FAIL_COND_V_MSG(month > 12 || month == 0, 0, "Invalid month value of: " + itos(month) + ".");
-
- // Do this check after month is tested as valid
- ERR_FAIL_COND_V_MSG(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1] || day == 0, 0, "Invalid day value of '" + itos(day) + "' which is larger than '" + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1]) + "' or 0.");
- // Calculate all the seconds from months past in this year
- uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month - 1] * SECONDS_PER_DAY;
-
- int64_t SECONDS_FROM_YEARS_PAST = 0;
- if (year >= EPOCH_YR) {
- for (unsigned int iyear = EPOCH_YR; iyear < year; iyear++) {
- SECONDS_FROM_YEARS_PAST += YEARSIZE(iyear) * SECONDS_PER_DAY;
- }
- } else {
- for (unsigned int iyear = EPOCH_YR - 1; iyear >= year; iyear--) {
- SECONDS_FROM_YEARS_PAST -= YEARSIZE(iyear) * SECONDS_PER_DAY;
- }
- }
-
- int64_t epoch =
- second +
- minute * SECONDS_PER_MINUTE +
- hour * SECONDS_PER_HOUR +
- // Subtract 1 from day, since the current day isn't over yet
- // and we cannot count all 24 hours.
- (day - 1) * SECONDS_PER_DAY +
- SECONDS_FROM_MONTHS_PAST_THIS_YEAR +
- SECONDS_FROM_YEARS_PAST;
- return epoch;
-}
-
-/**
- * Get a dictionary of time values when given epoch time
- *
- * Dictionary Time values will be a union if values from #get_time
- * and #get_date dictionaries (with the exception of dst =
- * day light standard time, as it cannot be determined from epoch)
- *
- * @param unix_time_val epoch time to convert
- *
- * @return dictionary of date and time values
- */
-Dictionary _OS::get_datetime_from_unix_time(int64_t unix_time_val) const {
- OS::Date date;
- OS::Time time;
-
- long dayclock, dayno;
- int year = EPOCH_YR;
-
- if (unix_time_val >= 0) {
- dayno = unix_time_val / SECS_DAY;
- dayclock = unix_time_val % SECS_DAY;
- /* day 0 was a thursday */
- date.weekday = static_cast<OS::Weekday>((dayno + 4) % 7);
- while (dayno >= YEARSIZE(year)) {
- dayno -= YEARSIZE(year);
- year++;
- }
- } else {
- dayno = (unix_time_val - SECS_DAY + 1) / SECS_DAY;
- dayclock = unix_time_val - dayno * SECS_DAY;
- date.weekday = static_cast<OS::Weekday>(((dayno % 7) + 11) % 7);
- do {
- year--;
- dayno += YEARSIZE(year);
- } while (dayno < 0);
- }
-
- time.sec = dayclock % 60;
- time.min = (dayclock % 3600) / 60;
- time.hour = dayclock / 3600;
- date.year = year;
-
- size_t imonth = 0;
-
- while ((unsigned long)dayno >= MONTH_DAYS_TABLE[LEAPYEAR(year)][imonth]) {
- dayno -= MONTH_DAYS_TABLE[LEAPYEAR(year)][imonth];
- imonth++;
- }
-
- /// Add 1 to month to make sure months are indexed starting at 1
- date.month = static_cast<OS::Month>(imonth + 1);
-
- date.day = dayno + 1;
-
- Dictionary timed;
- timed[HOUR_KEY] = time.hour;
- timed[MINUTE_KEY] = time.min;
- timed[SECOND_KEY] = time.sec;
- timed[YEAR_KEY] = date.year;
- timed[MONTH_KEY] = date.month;
- timed[DAY_KEY] = date.day;
- timed[WEEKDAY_KEY] = date.weekday;
-
- return timed;
-}
-
-Dictionary _OS::get_time_zone_info() const {
- OS::TimeZoneInfo info = OS::get_singleton()->get_time_zone_info();
- Dictionary infod;
- infod["bias"] = info.bias;
- infod["name"] = info.name;
- return infod;
-}
-
-double _OS::get_unix_time() const {
- return OS::get_singleton()->get_unix_time();
-}
-
/** This method uses a signed argument for better error reporting as it's used from the scripting API. */
void _OS::delay_usec(int p_usec) const {
ERR_FAIL_COND_MSG(
@@ -530,14 +316,6 @@ void _OS::delay_msec(int p_msec) const {
OS::get_singleton()->delay_usec(int64_t(p_msec) * 1000);
}
-uint32_t _OS::get_ticks_msec() const {
- return OS::get_singleton()->get_ticks_msec();
-}
-
-uint64_t _OS::get_ticks_usec() const {
- return OS::get_singleton()->get_ticks_usec();
-}
-
bool _OS::can_use_threads() const {
return OS::get_singleton()->can_use_threads();
}
@@ -644,6 +422,10 @@ String _OS::get_user_data_dir() const {
return OS::get_singleton()->get_user_data_dir();
}
+String _OS::get_external_data_dir() const {
+ return OS::get_singleton()->get_external_data_dir();
+}
+
bool _OS::is_debug_build() const {
#ifdef DEBUG_ENABLED
return true;
@@ -713,18 +495,8 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_name"), &_OS::get_name);
ClassDB::bind_method(D_METHOD("get_cmdline_args"), &_OS::get_cmdline_args);
- ClassDB::bind_method(D_METHOD("get_datetime", "utc"), &_OS::get_datetime, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_date", "utc"), &_OS::get_date, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_time", "utc"), &_OS::get_time, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_time_zone_info"), &_OS::get_time_zone_info);
- ClassDB::bind_method(D_METHOD("get_unix_time"), &_OS::get_unix_time);
- ClassDB::bind_method(D_METHOD("get_datetime_from_unix_time", "unix_time_val"), &_OS::get_datetime_from_unix_time);
- ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime", "datetime"), &_OS::get_unix_time_from_datetime);
-
ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &_OS::delay_usec);
ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &_OS::delay_msec);
- ClassDB::bind_method(D_METHOD("get_ticks_msec"), &_OS::get_ticks_msec);
- ClassDB::bind_method(D_METHOD("get_ticks_usec"), &_OS::get_ticks_usec);
ClassDB::bind_method(D_METHOD("get_locale"), &_OS::get_locale);
ClassDB::bind_method(D_METHOD("get_model_name"), &_OS::get_model_name);
@@ -744,6 +516,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &_OS::get_static_memory_peak_usage);
ClassDB::bind_method(D_METHOD("get_user_data_dir"), &_OS::get_user_data_dir);
+ ClassDB::bind_method(D_METHOD("get_external_data_dir"), &_OS::get_external_data_dir);
ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir);
ClassDB::bind_method(D_METHOD("get_unique_id"), &_OS::get_unique_id);
@@ -1226,7 +999,7 @@ Error _File::open(const String &p_path, ModeFlags p_mode_flags) {
Error err;
f = FileAccess::open(p_path, p_mode_flags, &err);
if (f) {
- f->set_endian_swap(eswap);
+ f->set_big_endian(big_endian);
}
return err;
}
@@ -1259,6 +1032,7 @@ String _File::get_path_absolute() const {
void _File::seek(int64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(p_position < 0, "Seek position must be a positive integer.");
f->seek(p_position);
}
@@ -1267,14 +1041,14 @@ void _File::seek_end(int64_t p_position) {
f->seek_end(p_position);
}
-int64_t _File::get_position() const {
+uint64_t _File::get_position() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_position();
}
-int64_t _File::get_len() const {
+uint64_t _File::get_length() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
- return f->get_len();
+ return f->get_length();
}
bool _File::eof_reached() const {
@@ -1317,7 +1091,7 @@ real_t _File::get_real() const {
return f->get_real();
}
-Vector<uint8_t> _File::get_buffer(int p_length) const {
+Vector<uint8_t> _File::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use.");
@@ -1330,8 +1104,7 @@ Vector<uint8_t> _File::get_buffer(int p_length) const {
ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");
uint8_t *w = data.ptrw();
- int len = f->get_buffer(&w[0], p_length);
- ERR_FAIL_COND_V(len < 0, Vector<uint8_t>());
+ int64_t len = f->get_buffer(&w[0], p_length);
if (len < p_length) {
data.resize(len);
@@ -1344,7 +1117,7 @@ String _File::get_as_text() const {
ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
String text;
- size_t original_pos = f->get_position();
+ uint64_t original_pos = f->get_position();
f->seek(0);
String l = get_line();
@@ -1382,15 +1155,15 @@ Vector<String> _File::get_csv_line(const String &p_delim) const {
* These flags get reset to false (little endian) on each open
*/
-void _File::set_endian_swap(bool p_swap) {
- eswap = p_swap;
+void _File::set_big_endian(bool p_big_endian) {
+ big_endian = p_big_endian;
if (f) {
- f->set_endian_swap(p_swap);
+ f->set_big_endian(p_big_endian);
}
}
-bool _File::get_endian_swap() {
- return eswap;
+bool _File::is_big_endian() {
+ return big_endian;
}
Error _File::get_error() const {
@@ -1473,7 +1246,7 @@ void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim
void _File::store_buffer(const Vector<uint8_t> &p_buffer) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
- int len = p_buffer.size();
+ uint64_t len = p_buffer.size();
if (len == 0) {
return;
}
@@ -1537,7 +1310,7 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("seek", "position"), &_File::seek);
ClassDB::bind_method(D_METHOD("seek_end", "position"), &_File::seek_end, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_position"), &_File::get_position);
- ClassDB::bind_method(D_METHOD("get_len"), &_File::get_len);
+ ClassDB::bind_method(D_METHOD("get_length"), &_File::get_length);
ClassDB::bind_method(D_METHOD("eof_reached"), &_File::eof_reached);
ClassDB::bind_method(D_METHOD("get_8"), &_File::get_8);
ClassDB::bind_method(D_METHOD("get_16"), &_File::get_16);
@@ -1546,14 +1319,14 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_float"), &_File::get_float);
ClassDB::bind_method(D_METHOD("get_double"), &_File::get_double);
ClassDB::bind_method(D_METHOD("get_real"), &_File::get_real);
- ClassDB::bind_method(D_METHOD("get_buffer", "len"), &_File::get_buffer);
+ ClassDB::bind_method(D_METHOD("get_buffer", "length"), &_File::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &_File::get_line);
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("get_as_text"), &_File::get_as_text);
ClassDB::bind_method(D_METHOD("get_md5", "path"), &_File::get_md5);
ClassDB::bind_method(D_METHOD("get_sha256", "path"), &_File::get_sha256);
- ClassDB::bind_method(D_METHOD("get_endian_swap"), &_File::get_endian_swap);
- ClassDB::bind_method(D_METHOD("set_endian_swap", "enable"), &_File::set_endian_swap);
+ ClassDB::bind_method(D_METHOD("is_big_endian"), &_File::is_big_endian);
+ ClassDB::bind_method(D_METHOD("set_big_endian", "big_endian"), &_File::set_big_endian);
ClassDB::bind_method(D_METHOD("get_error"), &_File::get_error);
ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &_File::get_var, DEFVAL(false));
@@ -1576,7 +1349,7 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("file_exists", "path"), &_File::file_exists);
ClassDB::bind_method(D_METHOD("get_modified_time", "file"), &_File::get_modified_time);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "endian_swap"), "set_endian_swap", "get_endian_swap");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian");
BIND_ENUM_CONSTANT(READ);
BIND_ENUM_CONSTANT(WRITE);
@@ -1617,11 +1390,11 @@ bool _Directory::is_open() const {
return d && dir_open;
}
-Error _Directory::list_dir_begin(bool p_skip_navigational, bool p_skip_hidden) {
+Error _Directory::list_dir_begin(bool p_show_navigational, bool p_show_hidden) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
- _list_skip_navigational = p_skip_navigational;
- _list_skip_hidden = p_skip_hidden;
+ _list_skip_navigational = !p_show_navigational;
+ _list_skip_hidden = !p_show_hidden;
return d->list_dir_begin();
}
@@ -1721,9 +1494,9 @@ bool _Directory::dir_exists(String p_dir) {
return d->dir_exists(p_dir);
}
-int _Directory::get_space_left() {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "Directory must be opened before use.");
- return d->get_space_left() / 1024 * 1024; //return value in megabytes, given binding is int
+uint64_t _Directory::get_space_left() {
+ ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use.");
+ return d->get_space_left() / 1024 * 1024; // Truncate to closest MiB.
}
Error _Directory::copy(String p_from, String p_to) {
@@ -1759,7 +1532,7 @@ Error _Directory::remove(String p_name) {
void _Directory::_bind_methods() {
ClassDB::bind_method(D_METHOD("open", "path"), &_Directory::open);
- ClassDB::bind_method(D_METHOD("list_dir_begin", "skip_navigational", "skip_hidden"), &_Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("list_dir_begin", "show_navigational", "show_hidden"), &_Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_next"), &_Directory::get_next);
ClassDB::bind_method(D_METHOD("current_is_dir"), &_Directory::current_is_dir);
ClassDB::bind_method(D_METHOD("list_dir_end"), &_Directory::list_dir_end);
@@ -2070,7 +1843,7 @@ Variant _ClassDB::instance(const StringName &p_class) const {
return Variant();
}
- Reference *r = Object::cast_to<Reference>(obj);
+ RefCounted *r = Object::cast_to<RefCounted>(obj);
if (r) {
return REF(r);
} else {
@@ -2416,12 +2189,12 @@ Variant JSONParseResult::get_result() const {
}
void _JSON::_bind_methods() {
- ClassDB::bind_method(D_METHOD("print", "value", "indent", "sort_keys"), &_JSON::print, DEFVAL(String()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("print", "value", "indent", "sort_keys", "full_precision"), &_JSON::print, DEFVAL(String()), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("parse", "json"), &_JSON::parse);
}
-String _JSON::print(const Variant &p_value, const String &p_indent, bool p_sort_keys) {
- return JSON::print(p_value, p_indent, p_sort_keys);
+String _JSON::print(const Variant &p_value, const String &p_indent, bool p_sort_keys, bool p_full_precision) {
+ return JSON::print(p_value, p_indent, p_sort_keys, p_full_precision);
}
Ref<JSONParseResult> _JSON::parse(const String &p_json) {
diff --git a/core/core_bind.h b/core/core_bind.h
index 3920116ca4..b161effe95 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -32,11 +32,11 @@
#define CORE_BIND_H
#include "core/io/compression.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/image.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
@@ -199,14 +199,6 @@ public:
void set_use_file_access_save_and_swap(bool p_enable);
- Dictionary get_date(bool utc) const;
- Dictionary get_time(bool utc) const;
- Dictionary get_datetime(bool utc) const;
- Dictionary get_datetime_from_unix_time(int64_t unix_time_val) const;
- int64_t get_unix_time_from_datetime(Dictionary datetime) const;
- Dictionary get_time_zone_info() const;
- double get_unix_time() const;
-
uint64_t get_static_memory_usage() const;
uint64_t get_static_memory_peak_usage() const;
@@ -237,6 +229,7 @@ public:
String get_system_dir(SystemDir p_dir) const;
String get_user_data_dir() const;
+ String get_external_data_dir() const;
Error set_thread_name(const String &p_name);
Thread::ID get_thread_caller_id() const;
@@ -352,11 +345,11 @@ public:
_Geometry3D() { singleton = this; }
};
-class _File : public Reference {
- GDCLASS(_File, Reference);
+class _File : public RefCounted {
+ GDCLASS(_File, RefCounted);
FileAccess *f = nullptr;
- bool eswap = false;
+ bool big_endian = false;
protected:
static void _bind_methods();
@@ -390,8 +383,8 @@ public:
void seek(int64_t p_position); // Seek to a given position.
void seek_end(int64_t p_position = 0); // Seek from the end of file.
- int64_t get_position() const; // Get position in the file.
- int64_t get_len() const; // Get size of the file.
+ uint64_t get_position() const; // Get position in the file.
+ uint64_t get_length() const; // Get size of the file.
bool eof_reached() const; // Reading passed EOF.
@@ -406,20 +399,20 @@ public:
Variant get_var(bool p_allow_objects = false) const;
- Vector<uint8_t> get_buffer(int p_length) const; // Get an array of bytes.
+ Vector<uint8_t> get_buffer(int64_t p_length) const; // Get an array of bytes.
String get_line() const;
Vector<String> get_csv_line(const String &p_delim = ",") const;
String get_as_text() const;
String get_md5(const String &p_path) const;
String get_sha256(const String &p_path) const;
- /* Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac).
+ /*
+ * Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac).
* It's not about the current CPU type but file formats.
- * This flags get reset to false (little endian) on each open.
+ * This flag gets reset to `false` (little endian) on each open.
*/
-
- void set_endian_swap(bool p_swap);
- bool get_endian_swap();
+ void set_big_endian(bool p_big_endian);
+ bool is_big_endian();
Error get_error() const; // Get last error.
@@ -454,8 +447,8 @@ public:
VARIANT_ENUM_CAST(_File::ModeFlags);
VARIANT_ENUM_CAST(_File::CompressionMode);
-class _Directory : public Reference {
- GDCLASS(_Directory, Reference);
+class _Directory : public RefCounted {
+ GDCLASS(_Directory, RefCounted);
DirAccess *d;
bool dir_open = false;
@@ -467,7 +460,7 @@ public:
bool is_open() const;
- Error list_dir_begin(bool p_skip_navigational = false, bool p_skip_hidden = false); // This starts dir listing.
+ Error list_dir_begin(bool p_show_navigational = false, bool p_show_hidden = false); // This starts dir listing.
String get_next();
bool current_is_dir() const;
@@ -486,7 +479,7 @@ public:
bool file_exists(String p_file);
bool dir_exists(String p_dir);
- int get_space_left();
+ uint64_t get_space_left();
Error copy(String p_from, String p_to);
Error rename(String p_from, String p_to);
@@ -524,8 +517,8 @@ public:
~_Marshalls() { singleton = nullptr; }
};
-class _Mutex : public Reference {
- GDCLASS(_Mutex, Reference);
+class _Mutex : public RefCounted {
+ GDCLASS(_Mutex, RefCounted);
Mutex mutex;
static void _bind_methods();
@@ -536,8 +529,8 @@ public:
void unlock();
};
-class _Semaphore : public Reference {
- GDCLASS(_Semaphore, Reference);
+class _Semaphore : public RefCounted {
+ GDCLASS(_Semaphore, RefCounted);
Semaphore semaphore;
static void _bind_methods();
@@ -548,8 +541,8 @@ public:
void post();
};
-class _Thread : public Reference {
- GDCLASS(_Thread, Reference);
+class _Thread : public RefCounted {
+ GDCLASS(_Thread, RefCounted);
protected:
Variant ret;
@@ -665,8 +658,8 @@ public:
class _JSON;
-class JSONParseResult : public Reference {
- GDCLASS(JSONParseResult, Reference);
+class JSONParseResult : public RefCounted {
+ GDCLASS(JSONParseResult, RefCounted);
friend class _JSON;
@@ -705,7 +698,7 @@ protected:
public:
static _JSON *get_singleton() { return singleton; }
- String print(const Variant &p_value, const String &p_indent = "", bool p_sort_keys = false);
+ String print(const Variant &p_value, const String &p_indent = "", bool p_sort_keys = false, bool p_full_precision = false);
Ref<JSONParseResult> parse(const String &p_json);
_JSON() { singleton = this; }
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index f40928350a..7fc09fc3a6 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -161,7 +161,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(KEY_PAGEUP);
BIND_CORE_ENUM_CONSTANT(KEY_PAGEDOWN);
BIND_CORE_ENUM_CONSTANT(KEY_SHIFT);
- BIND_CORE_ENUM_CONSTANT(KEY_CONTROL);
+ BIND_CORE_ENUM_CONSTANT(KEY_CTRL);
BIND_CORE_ENUM_CONSTANT(KEY_META);
BIND_CORE_ENUM_CONSTANT(KEY_ALT);
BIND_CORE_ENUM_CONSTANT(KEY_CAPSLOCK);
@@ -580,10 +580,10 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3I", Variant::VECTOR3I);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM2D", Variant::TRANSFORM2D);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PLANE", Variant::PLANE);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_QUAT", Variant::QUAT);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_QUATERNION", Variant::QUATERNION);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_AABB", Variant::AABB);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BASIS", Variant::BASIS);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM", Variant::TRANSFORM);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM3D", Variant::TRANSFORM3D);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING_NAME", Variant::STRING_NAME);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NODE_PATH", Variant::NODE_PATH);
diff --git a/core/crypto/aes_context.h b/core/crypto/aes_context.h
index cc00b18fd2..2f8422f537 100644
--- a/core/crypto/aes_context.h
+++ b/core/crypto/aes_context.h
@@ -32,10 +32,10 @@
#define AES_CONTEXT_H
#include "core/crypto/crypto_core.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class AESContext : public Reference {
- GDCLASS(AESContext, Reference);
+class AESContext : public RefCounted {
+ GDCLASS(AESContext, RefCounted);
public:
enum Mode {
diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h
index 9438fcfea5..a2ccbba58a 100644
--- a/core/crypto/crypto.h
+++ b/core/crypto/crypto.h
@@ -35,7 +35,7 @@
#include "core/io/resource.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
class CryptoKey : public Resource {
GDCLASS(CryptoKey, Resource);
@@ -67,8 +67,8 @@ public:
virtual Error save(String p_path) = 0;
};
-class HMACContext : public Reference {
- GDCLASS(HMACContext, Reference);
+class HMACContext : public RefCounted {
+ GDCLASS(HMACContext, RefCounted);
protected:
static void _bind_methods();
@@ -84,8 +84,8 @@ public:
HMACContext() {}
};
-class Crypto : public Reference {
- GDCLASS(Crypto, Reference);
+class Crypto : public RefCounted {
+ GDCLASS(Crypto, RefCounted);
protected:
static void _bind_methods();
diff --git a/core/crypto/crypto_core.h b/core/crypto/crypto_core.h
index 27b380e838..7a2f4df589 100644
--- a/core/crypto/crypto_core.h
+++ b/core/crypto/crypto_core.h
@@ -31,7 +31,7 @@
#ifndef CRYPTO_CORE_H
#define CRYPTO_CORE_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
class CryptoCore {
public:
diff --git a/core/crypto/hashing_context.h b/core/crypto/hashing_context.h
index 892a48a4e8..31521a147c 100644
--- a/core/crypto/hashing_context.h
+++ b/core/crypto/hashing_context.h
@@ -31,10 +31,10 @@
#ifndef HASHING_CONTEXT_H
#define HASHING_CONTEXT_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class HashingContext : public Reference {
- GDCLASS(HashingContext, Reference);
+class HashingContext : public RefCounted {
+ GDCLASS(HashingContext, RefCounted);
public:
enum HashType {
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp
index 1dd7e268a5..ab368471e4 100644
--- a/core/debugger/local_debugger.cpp
+++ b/core/debugger/local_debugger.cpp
@@ -183,7 +183,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
print_line("Error: Unknown option " + key);
} else {
// Allow explicit tab character
- String value = key_value.right(value_pos + 1).replace("\\t", "\t");
+ String value = key_value.substr(value_pos + 1).replace("\\t", "\t");
options[key] = value;
}
@@ -348,7 +348,7 @@ Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) {
}
breakpoint.first = script_debugger->breakpoint_find_source(breakpoint_part.left(last_colon).strip_edges());
- breakpoint.second = breakpoint_part.right(last_colon).strip_edges().to_int();
+ breakpoint.second = breakpoint_part.substr(last_colon).strip_edges().to_int();
return breakpoint;
}
diff --git a/core/debugger/remote_debugger_peer.h b/core/debugger/remote_debugger_peer.h
index 652e2d9d20..8cba53a81c 100644
--- a/core/debugger/remote_debugger_peer.h
+++ b/core/debugger/remote_debugger_peer.h
@@ -32,12 +32,12 @@
#define REMOTE_DEBUGGER_PEER_H
#include "core/io/stream_peer_tcp.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/mutex.h"
#include "core/os/thread.h"
#include "core/string/ustring.h"
-class RemoteDebuggerPeer : public Reference {
+class RemoteDebuggerPeer : public RefCounted {
protected:
int max_queued_messages = 4096;
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 2304c05bf8..6e98b596d7 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -85,7 +85,7 @@ Input *Input::get_singleton() {
}
void Input::set_mouse_mode(MouseMode p_mode) {
- ERR_FAIL_INDEX((int)p_mode, 4);
+ ERR_FAIL_INDEX((int)p_mode, 5);
set_mouse_mode_func(p_mode);
}
@@ -138,6 +138,7 @@ void Input::_bind_methods() {
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED);
BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED);
+ BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN);
BIND_ENUM_CONSTANT(CURSOR_ARROW);
BIND_ENUM_CONSTANT(CURSOR_IBEAM);
@@ -1262,16 +1263,16 @@ void Input::parse_mapping(String p_mapping) {
} else if (output[0] == '-') {
output_range = NEGATIVE_HALF_AXIS;
}
- output = output.right(1);
+ output = output.substr(1);
}
JoyAxisRange input_range = FULL_AXIS;
if (input[0] == '+') {
input_range = POSITIVE_HALF_AXIS;
- input = input.right(1);
+ input = input.substr(1);
} else if (input[0] == '-') {
input_range = NEGATIVE_HALF_AXIS;
- input = input.right(1);
+ input = input.substr(1);
}
bool invert_axis = false;
if (input[input.length() - 1] == '~') {
@@ -1299,11 +1300,11 @@ void Input::parse_mapping(String p_mapping) {
switch (input[0]) {
case 'b':
binding.inputType = TYPE_BUTTON;
- binding.input.button = input.right(1).to_int();
+ binding.input.button = input.substr(1).to_int();
break;
case 'a':
binding.inputType = TYPE_AXIS;
- binding.input.axis.axis = input.right(1).to_int();
+ binding.input.axis.axis = input.substr(1).to_int();
binding.input.axis.range = input_range;
binding.input.axis.invert = invert_axis;
break;
@@ -1312,7 +1313,7 @@ void Input::parse_mapping(String p_mapping) {
String(entry[idx] + "\nInvalid hat input: " + input));
binding.inputType = TYPE_HAT;
binding.input.hat.hat = input.substr(1, 1).to_int();
- binding.input.hat.hat_mask = static_cast<HatMask>(input.right(3).to_int());
+ binding.input.hat.hat_mask = static_cast<HatMask>(input.substr(3).to_int());
break;
default:
ERR_CONTINUE_MSG(true, String(entry[idx] + "\nUnrecognised input string: " + input));
diff --git a/core/input/input.h b/core/input/input.h
index 99b45db325..ecb4981b13 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -46,7 +46,8 @@ public:
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
MOUSE_MODE_CAPTURED,
- MOUSE_MODE_CONFINED
+ MOUSE_MODE_CONFINED,
+ MOUSE_MODE_CONFINED_HIDDEN,
};
#undef CursorShape
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 46629d742e..9c1cf15342 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -147,66 +147,66 @@ bool InputEventWithModifiers::is_storing_command() const {
return store_command;
}
-void InputEventWithModifiers::set_shift(bool p_enabled) {
- shift = p_enabled;
+void InputEventWithModifiers::set_shift_pressed(bool p_enabled) {
+ shift_pressed = p_enabled;
}
-bool InputEventWithModifiers::get_shift() const {
- return shift;
+bool InputEventWithModifiers::is_shift_pressed() const {
+ return shift_pressed;
}
-void InputEventWithModifiers::set_alt(bool p_enabled) {
- alt = p_enabled;
+void InputEventWithModifiers::set_alt_pressed(bool p_enabled) {
+ alt_pressed = p_enabled;
}
-bool InputEventWithModifiers::get_alt() const {
- return alt;
+bool InputEventWithModifiers::is_alt_pressed() const {
+ return alt_pressed;
}
-void InputEventWithModifiers::set_control(bool p_enabled) {
- control = p_enabled;
+void InputEventWithModifiers::set_ctrl_pressed(bool p_enabled) {
+ ctrl_pressed = p_enabled;
}
-bool InputEventWithModifiers::get_control() const {
- return control;
+bool InputEventWithModifiers::is_ctrl_pressed() const {
+ return ctrl_pressed;
}
-void InputEventWithModifiers::set_metakey(bool p_enabled) {
- meta = p_enabled;
+void InputEventWithModifiers::set_meta_pressed(bool p_enabled) {
+ meta_pressed = p_enabled;
}
-bool InputEventWithModifiers::get_metakey() const {
- return meta;
+bool InputEventWithModifiers::is_meta_pressed() const {
+ return meta_pressed;
}
-void InputEventWithModifiers::set_command(bool p_enabled) {
- command = p_enabled;
+void InputEventWithModifiers::set_command_pressed(bool p_enabled) {
+ command_pressed = p_enabled;
}
-bool InputEventWithModifiers::get_command() const {
- return command;
+bool InputEventWithModifiers::is_command_pressed() const {
+ return command_pressed;
}
void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModifiers *event) {
- set_alt(event->get_alt());
- set_shift(event->get_shift());
- set_control(event->get_control());
- set_metakey(event->get_metakey());
+ set_alt_pressed(event->is_alt_pressed());
+ set_shift_pressed(event->is_shift_pressed());
+ set_ctrl_pressed(event->is_ctrl_pressed());
+ set_meta_pressed(event->is_meta_pressed());
}
String InputEventWithModifiers::as_text() const {
Vector<String> mod_names;
- if (get_control()) {
- mod_names.push_back(find_keycode_name(KEY_CONTROL));
+ if (is_ctrl_pressed()) {
+ mod_names.push_back(find_keycode_name(KEY_CTRL));
}
- if (get_shift()) {
+ if (is_shift_pressed()) {
mod_names.push_back(find_keycode_name(KEY_SHIFT));
}
- if (get_alt()) {
+ if (is_alt_pressed()) {
mod_names.push_back(find_keycode_name(KEY_ALT));
}
- if (get_metakey()) {
+ if (is_meta_pressed()) {
mod_names.push_back(find_keycode_name(KEY_META));
}
@@ -225,27 +225,27 @@ void InputEventWithModifiers::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_store_command", "enable"), &InputEventWithModifiers::set_store_command);
ClassDB::bind_method(D_METHOD("is_storing_command"), &InputEventWithModifiers::is_storing_command);
- ClassDB::bind_method(D_METHOD("set_alt", "enable"), &InputEventWithModifiers::set_alt);
- ClassDB::bind_method(D_METHOD("get_alt"), &InputEventWithModifiers::get_alt);
+ ClassDB::bind_method(D_METHOD("set_alt_pressed", "pressed"), &InputEventWithModifiers::set_alt_pressed);
+ ClassDB::bind_method(D_METHOD("is_alt_pressed"), &InputEventWithModifiers::is_alt_pressed);
- ClassDB::bind_method(D_METHOD("set_shift", "enable"), &InputEventWithModifiers::set_shift);
- ClassDB::bind_method(D_METHOD("get_shift"), &InputEventWithModifiers::get_shift);
+ ClassDB::bind_method(D_METHOD("set_shift_pressed", "pressed"), &InputEventWithModifiers::set_shift_pressed);
+ ClassDB::bind_method(D_METHOD("is_shift_pressed"), &InputEventWithModifiers::is_shift_pressed);
- ClassDB::bind_method(D_METHOD("set_control", "enable"), &InputEventWithModifiers::set_control);
- ClassDB::bind_method(D_METHOD("get_control"), &InputEventWithModifiers::get_control);
+ ClassDB::bind_method(D_METHOD("set_ctrl_pressed", "pressed"), &InputEventWithModifiers::set_ctrl_pressed);
+ ClassDB::bind_method(D_METHOD("is_ctrl_pressed"), &InputEventWithModifiers::is_ctrl_pressed);
- ClassDB::bind_method(D_METHOD("set_metakey", "enable"), &InputEventWithModifiers::set_metakey);
- ClassDB::bind_method(D_METHOD("get_metakey"), &InputEventWithModifiers::get_metakey);
+ ClassDB::bind_method(D_METHOD("set_meta_pressed", "pressed"), &InputEventWithModifiers::set_meta_pressed);
+ ClassDB::bind_method(D_METHOD("is_meta_pressed"), &InputEventWithModifiers::is_meta_pressed);
- ClassDB::bind_method(D_METHOD("set_command", "enable"), &InputEventWithModifiers::set_command);
- ClassDB::bind_method(D_METHOD("get_command"), &InputEventWithModifiers::get_command);
+ ClassDB::bind_method(D_METHOD("set_command_pressed", "pressed"), &InputEventWithModifiers::set_command_pressed);
+ ClassDB::bind_method(D_METHOD("is_command_pressed"), &InputEventWithModifiers::is_command_pressed);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "store_command"), "set_store_command", "is_storing_command");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alt"), "set_alt", "get_alt");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shift"), "set_shift", "get_shift");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "control"), "set_control", "get_control");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta"), "set_metakey", "get_metakey");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command"), "set_command", "get_command");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alt_pressed"), "set_alt_pressed", "is_alt_pressed");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shift_pressed"), "set_shift_pressed", "is_shift_pressed");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ctrl_pressed"), "set_ctrl_pressed", "is_ctrl_pressed");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_pressed"), "set_meta_pressed", "is_meta_pressed");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command_pressed"), "set_command_pressed", "is_command_pressed");
}
void InputEventWithModifiers::_validate_property(PropertyInfo &property) const {
@@ -253,18 +253,18 @@ void InputEventWithModifiers::_validate_property(PropertyInfo &property) const {
// If we only want to Store "Command".
#ifdef APPLE_STYLE_KEYS
// Don't store "Meta" on Mac.
- if (property.name == "meta") {
+ if (property.name == "meta_pressed") {
property.usage ^= PROPERTY_USAGE_STORAGE;
}
#else
- // Don't store "Control".
- if (property.name == "control") {
+ // Don't store "Ctrl".
+ if (property.name == "ctrl_pressed") {
property.usage ^= PROPERTY_USAGE_STORAGE;
}
#endif
} else {
- // We don't want to store command, only control or meta (on mac).
- if (property.name == "command") {
+ // We don't want to store command, only ctrl or meta (on mac).
+ if (property.name == "command_pressed") {
property.usage ^= PROPERTY_USAGE_STORAGE;
}
}
@@ -314,16 +314,16 @@ bool InputEventKey::is_echo() const {
uint32_t InputEventKey::get_keycode_with_modifiers() const {
uint32_t sc = keycode;
- if (get_control()) {
+ if (is_ctrl_pressed()) {
sc |= KEY_MASK_CTRL;
}
- if (get_alt()) {
+ if (is_alt_pressed()) {
sc |= KEY_MASK_ALT;
}
- if (get_shift()) {
+ if (is_shift_pressed()) {
sc |= KEY_MASK_SHIFT;
}
- if (get_metakey()) {
+ if (is_meta_pressed()) {
sc |= KEY_MASK_META;
}
@@ -332,16 +332,16 @@ uint32_t InputEventKey::get_keycode_with_modifiers() const {
uint32_t InputEventKey::get_physical_keycode_with_modifiers() const {
uint32_t sc = physical_keycode;
- if (get_control()) {
+ if (is_ctrl_pressed()) {
sc |= KEY_MASK_CTRL;
}
- if (get_alt()) {
+ if (is_alt_pressed()) {
sc |= KEY_MASK_ALT;
}
- if (get_shift()) {
+ if (is_shift_pressed()) {
sc |= KEY_MASK_SHIFT;
}
- if (get_metakey()) {
+ if (is_meta_pressed()) {
sc |= KEY_MASK_META;
}
@@ -372,16 +372,16 @@ String InputEventKey::to_string() {
String kc = "";
String physical = "false";
if (keycode == 0) {
- kc = itos(physical_keycode) + " " + keycode_get_string(physical_keycode);
+ kc = itos(physical_keycode) + " (" + keycode_get_string(physical_keycode) + ")";
physical = "true";
} else {
- kc = itos(keycode) + " " + keycode_get_string(keycode);
+ kc = itos(keycode) + " (" + keycode_get_string(keycode) + ")";
}
String mods = InputEventWithModifiers::as_text();
- mods = mods == "" ? TTR("None") : mods;
+ mods = mods == "" ? TTR("none") : mods;
- return vformat("InputEventKey: keycode=%s mods=%s physical=%s pressed=%s echo=%s", kc, mods, physical, p, e);
+ return vformat("InputEventKey: keycode=%s, mods=%s, physical=%s, pressed=%s, echo=%s", kc, mods, physical, p, e);
}
Ref<InputEventKey> InputEventKey::create_reference(uint32_t p_keycode) {
@@ -391,19 +391,19 @@ Ref<InputEventKey> InputEventKey::create_reference(uint32_t p_keycode) {
ie->set_unicode(p_keycode & KEY_CODE_MASK);
if (p_keycode & KEY_MASK_SHIFT) {
- ie->set_shift(true);
+ ie->set_shift_pressed(true);
}
if (p_keycode & KEY_MASK_ALT) {
- ie->set_alt(true);
+ ie->set_alt_pressed(true);
}
if (p_keycode & KEY_MASK_CTRL) {
- ie->set_control(true);
+ ie->set_ctrl_pressed(true);
}
if (p_keycode & KEY_MASK_CMD) {
- ie->set_command(true);
+ ie->set_command_pressed(true);
}
if (p_keycode & KEY_MASK_META) {
- ie->set_metakey(true);
+ ie->set_meta_pressed(true);
}
return ie;
@@ -667,11 +667,11 @@ String InputEventMouseButton::to_string() {
}
String mods = InputEventWithModifiers::as_text();
- mods = mods == "" ? TTR("None") : mods;
+ mods = mods == "" ? TTR("none") : mods;
// Work around the fact vformat can only take 5 substitutions but 6 need to be passed.
- String index_and_mods = vformat("button_index=%s mods=%s", button_index, mods);
- return vformat("InputEventMouseButton: %s pressed=%s position=(%s) button_mask=%s double_click=%s", index_and_mods, p, String(get_position()), itos(get_button_mask()), d);
+ String index_and_mods = vformat("button_index=%s, mods=%s", button_index, mods);
+ return vformat("InputEventMouseButton: %s, pressed=%s, position=(%s), button_mask=%d, double_click=%s", index_and_mods, p, String(get_position()), get_button_mask(), d);
}
void InputEventMouseButton::_bind_methods() {
@@ -780,7 +780,9 @@ String InputEventMouseMotion::to_string() {
break;
}
- return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + "), pressure=(" + rtos(get_pressure()) + "), tilt=(" + String(get_tilt()) + ")";
+ // Work around the fact vformat can only take 5 substitutions but 6 need to be passed.
+ String mask_and_position = vformat("button_mask=%s, position=(%s)", button_mask_string, String(get_position()));
+ return vformat("InputEventMouseMotion: %s, relative=(%s), speed=(%s), pressure=%.2f, tilt=(%s)", mask_and_position, String(get_relative()), String(get_speed()), get_pressure(), String(get_tilt()));
}
bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
@@ -801,19 +803,19 @@ bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
return false;
}
- if (get_shift() != motion->get_shift()) {
+ if (is_shift_pressed() != motion->is_shift_pressed()) {
return false;
}
- if (get_control() != motion->get_control()) {
+ if (is_ctrl_pressed() != motion->is_ctrl_pressed()) {
return false;
}
- if (get_alt() != motion->get_alt()) {
+ if (is_alt_pressed() != motion->is_alt_pressed()) {
return false;
}
- if (get_metakey() != motion->get_metakey()) {
+ if (is_meta_pressed() != motion->is_meta_pressed()) {
return false;
}
@@ -918,11 +920,11 @@ static const char *_joy_axis_descriptions[JOY_AXIS_MAX] = {
String InputEventJoypadMotion::as_text() const {
String desc = axis < JOY_AXIS_MAX ? RTR(_joy_axis_descriptions[axis]) : TTR("Unknown Joypad Axis");
- return vformat(TTR("Joypad Motion on Axis %s (%s) with Value %s"), itos(axis), desc, String(Variant(axis_value)));
+ return vformat(TTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
}
String InputEventJoypadMotion::to_string() {
- return "InputEventJoypadMotion : axis=" + itos(axis) + ", axis_value=" + String(Variant(axis_value));
+ return vformat("InputEventJoypadMotion: axis=%d, axis_value=%.2f", axis, axis_value);
}
void InputEventJoypadMotion::_bind_methods() {
@@ -1021,7 +1023,7 @@ static const char *_joy_button_descriptions[JOY_BUTTON_SDL_MAX] = {
String InputEventJoypadButton::as_text() const {
String text = "Joypad Button " + itos(button_index);
- if (button_index < JOY_BUTTON_SDL_MAX) {
+ if (button_index >= 0 && button_index < JOY_BUTTON_SDL_MAX) {
text += vformat(" (%s)", _joy_button_descriptions[button_index]);
}
@@ -1033,7 +1035,8 @@ String InputEventJoypadButton::as_text() const {
}
String InputEventJoypadButton::to_string() {
- return "InputEventJoypadButton : button_index=" + itos(button_index) + ", pressed=" + (pressed ? "true" : "false") + ", pressure=" + String(Variant(pressure));
+ String p = pressed ? "true" : "false";
+ return vformat("InputEventJoypadButton: button_index=%d, pressed=%s, pressure=%.2f", button_index, p, pressure);
}
Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(int p_btn_index) {
@@ -1104,7 +1107,8 @@ String InputEventScreenTouch::as_text() const {
}
String InputEventScreenTouch::to_string() {
- return "InputEventScreenTouch : index=" + itos(index) + ", pressed=" + (pressed ? "true" : "false") + ", position=(" + String(get_position()) + ")";
+ String p = pressed ? "true" : "false";
+ return vformat("InputEventScreenTouch: index=%d, pressed=%s, position=(%s)", index, p, String(get_position()));
}
void InputEventScreenTouch::_bind_methods() {
@@ -1177,7 +1181,7 @@ String InputEventScreenDrag::as_text() const {
}
String InputEventScreenDrag::to_string() {
- return "InputEventScreenDrag : index=" + itos(index) + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + ")";
+ return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), speed=(%s)", index, String(get_position()), String(get_relative()), String(get_speed()));
}
void InputEventScreenDrag::_bind_methods() {
@@ -1264,7 +1268,8 @@ String InputEventAction::as_text() const {
}
String InputEventAction::to_string() {
- return "InputEventAction : action=" + action + ", pressed=(" + (pressed ? "true" : "false");
+ String p = pressed ? "true" : "false";
+ return vformat("InputEventAction: action=\"%s\", pressed=%s", action, p);
}
void InputEventAction::_bind_methods() {
@@ -1331,7 +1336,7 @@ String InputEventMagnifyGesture::as_text() const {
}
String InputEventMagnifyGesture::to_string() {
- return "InputEventMagnifyGesture : factor=" + rtos(get_factor()) + ", position=(" + String(get_position()) + ")";
+ return vformat("InputEventMagnifyGesture: factor=%.2f, position=(%s)", factor, String(get_position()));
}
void InputEventMagnifyGesture::_bind_methods() {
@@ -1371,7 +1376,7 @@ String InputEventPanGesture::as_text() const {
}
String InputEventPanGesture::to_string() {
- return "InputEventPanGesture : delta=(" + String(get_delta()) + "), position=(" + String(get_position()) + ")";
+ return vformat("InputEventPanGesture: delta=(%s), position=(%s)", String(get_delta()), String(get_position()));
}
void InputEventPanGesture::_bind_methods() {
@@ -1452,7 +1457,7 @@ String InputEventMIDI::as_text() const {
}
String InputEventMIDI::to_string() {
- return vformat("InputEvenMIDI: channel=%s message=%s pitch=%s velocity=%s pressure=%s", itos(channel), itos(message), itos(pitch), itos(velocity), itos(pressure));
+ return vformat("InputEventMIDI: channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d", channel, message, pitch, velocity, pressure);
}
void InputEventMIDI::_bind_methods() {
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 5a33ee7b9c..eed0d79326 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -170,21 +170,21 @@ class InputEventWithModifiers : public InputEventFromWindow {
bool store_command = true;
- bool shift = false;
- bool alt = false;
+ bool shift_pressed = false;
+ bool alt_pressed = false;
#ifdef APPLE_STYLE_KEYS
union {
- bool command;
- bool meta = false; //< windows/mac key
+ bool command_pressed;
+ bool meta_pressed = false; //< windows/mac key
};
- bool control = false;
+ bool ctrl_pressed = false;
#else
union {
- bool command; //< windows/mac key
- bool control = false;
+ bool command_pressed; //< windows/mac key
+ bool ctrl_pressed = false;
};
- bool meta = false; //< windows/mac key
+ bool meta_pressed = false; //< windows/mac key
#endif
protected:
@@ -195,20 +195,20 @@ public:
void set_store_command(bool p_enabled);
bool is_storing_command() const;
- void set_shift(bool p_enabled);
- bool get_shift() const;
+ void set_shift_pressed(bool p_pressed);
+ bool is_shift_pressed() const;
- void set_alt(bool p_enabled);
- bool get_alt() const;
+ void set_alt_pressed(bool p_pressed);
+ bool is_alt_pressed() const;
- void set_control(bool p_enabled);
- bool get_control() const;
+ void set_ctrl_pressed(bool p_pressed);
+ bool is_ctrl_pressed() const;
- void set_metakey(bool p_enabled);
- bool get_metakey() const;
+ void set_meta_pressed(bool p_pressed);
+ bool is_meta_pressed() const;
- void set_command(bool p_enabled);
- bool get_command() const;
+ void set_command_pressed(bool p_pressed);
+ bool is_command_pressed() const;
void set_modifiers_from_event(const InputEventWithModifiers *event);
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index 7421909650..5b96babe44 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -166,7 +166,7 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent
ERR_FAIL_COND_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), _suggest_actions(p_action));
if (_find_event(input_map[p_action], p_event, true)) {
- return; // Already addded.
+ return; // Already added.
}
input_map[p_action].inputs.push_back(p_event);
@@ -353,6 +353,7 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
{ "ui_text_scroll_down", TTRC("Scroll Down") },
{ "ui_text_scroll_down.OSX", TTRC("Scroll Down") },
{ "ui_text_select_all", TTRC("Select All") },
+ { "ui_text_select_word_under_caret", TTRC("Select Word Under Caret") },
{ "ui_text_toggle_insert_mode", TTRC("Toggle Insert Mode") },
{ "ui_graph_duplicate", TTRC("Duplicate Nodes") },
{ "ui_graph_delete", TTRC("Delete Nodes") },
@@ -473,10 +474,14 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
default_builtin_cache.insert("ui_text_completion_query", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_TAB));
inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
+ inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER));
default_builtin_cache.insert("ui_text_completion_accept", inputs);
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_TAB));
+ default_builtin_cache.insert("ui_text_completion_replace", inputs);
+
// Newlines
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
@@ -506,6 +511,7 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
// Text Backspace and Delete
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE));
+ inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_SHIFT));
default_builtin_cache.insert("ui_text_backspace", inputs);
inputs = List<Ref<InputEvent>>();
@@ -651,6 +657,10 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
default_builtin_cache.insert("ui_text_select_all", inputs);
inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_D | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_select_word_under_caret", inputs);
+
+ inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(KEY_INSERT));
default_builtin_cache.insert("ui_text_toggle_insert_mode", inputs);
diff --git a/core/io/config_file.h b/core/io/config_file.h
index 1b28257c60..dbba43ace5 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -31,13 +31,13 @@
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
-#include "core/object/reference.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
+#include "core/object/ref_counted.h"
#include "core/templates/ordered_hash_map.h"
#include "core/variant/variant_parser.h"
-class ConfigFile : public Reference {
- GDCLASS(ConfigFile, Reference);
+class ConfigFile : public RefCounted {
+ GDCLASS(ConfigFile, RefCounted);
OrderedHashMap<String, OrderedHashMap<String, Variant>> values;
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
new file mode 100644
index 0000000000..dfba00067f
--- /dev/null
+++ b/core/io/dir_access.cpp
@@ -0,0 +1,418 @@
+/*************************************************************************/
+/* dir_access.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "dir_access.h"
+
+#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
+#include "core/os/memory.h"
+#include "core/os/os.h"
+
+String DirAccess::_get_root_path() const {
+ switch (_access_type) {
+ case ACCESS_RESOURCES:
+ return ProjectSettings::get_singleton()->get_resource_path();
+ case ACCESS_USERDATA:
+ return OS::get_singleton()->get_user_data_dir();
+ default:
+ return "";
+ }
+}
+
+String DirAccess::_get_root_string() const {
+ switch (_access_type) {
+ case ACCESS_RESOURCES:
+ return "res://";
+ case ACCESS_USERDATA:
+ return "user://";
+ default:
+ return "";
+ }
+}
+
+int DirAccess::get_current_drive() {
+ String path = get_current_dir().to_lower();
+ for (int i = 0; i < get_drive_count(); i++) {
+ String d = get_drive(i).to_lower();
+ if (path.begins_with(d)) {
+ return i;
+ }
+ }
+
+ return 0;
+}
+
+bool DirAccess::drives_are_shortcuts() {
+ return false;
+}
+
+static Error _erase_recursive(DirAccess *da) {
+ List<String> dirs;
+ List<String> files;
+
+ da->list_dir_begin();
+ String n = da->get_next();
+ while (n != String()) {
+ if (n != "." && n != "..") {
+ if (da->current_is_dir()) {
+ dirs.push_back(n);
+ } else {
+ files.push_back(n);
+ }
+ }
+
+ n = da->get_next();
+ }
+
+ da->list_dir_end();
+
+ for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
+ Error err = da->change_dir(E->get());
+ if (err == OK) {
+ err = _erase_recursive(da);
+ if (err) {
+ da->change_dir("..");
+ return err;
+ }
+ err = da->change_dir("..");
+ if (err) {
+ return err;
+ }
+ err = da->remove(da->get_current_dir().plus_file(E->get()));
+ if (err) {
+ return err;
+ }
+ } else {
+ return err;
+ }
+ }
+
+ for (List<String>::Element *E = files.front(); E; E = E->next()) {
+ Error err = da->remove(da->get_current_dir().plus_file(E->get()));
+ if (err) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+Error DirAccess::erase_contents_recursive() {
+ return _erase_recursive(this);
+}
+
+Error DirAccess::make_dir_recursive(String p_dir) {
+ if (p_dir.length() < 1) {
+ return OK;
+ }
+
+ String full_dir;
+
+ if (p_dir.is_rel_path()) {
+ //append current
+ full_dir = get_current_dir().plus_file(p_dir);
+
+ } else {
+ full_dir = p_dir;
+ }
+
+ full_dir = full_dir.replace("\\", "/");
+
+ //int slices = full_dir.get_slice_count("/");
+
+ String base;
+
+ if (full_dir.begins_with("res://")) {
+ base = "res://";
+ } else if (full_dir.begins_with("user://")) {
+ base = "user://";
+ } else if (full_dir.begins_with("/")) {
+ base = "/";
+ } else if (full_dir.find(":/") != -1) {
+ base = full_dir.substr(0, full_dir.find(":/") + 2);
+ } else {
+ ERR_FAIL_V(ERR_INVALID_PARAMETER);
+ }
+
+ full_dir = full_dir.replace_first(base, "").simplify_path();
+
+ Vector<String> subdirs = full_dir.split("/");
+
+ String curpath = base;
+ for (int i = 0; i < subdirs.size(); i++) {
+ curpath = curpath.plus_file(subdirs[i]);
+ Error err = make_dir(curpath);
+ if (err != OK && err != ERR_ALREADY_EXISTS) {
+ ERR_FAIL_V_MSG(err, "Could not create directory: " + curpath);
+ }
+ }
+
+ return OK;
+}
+
+String DirAccess::fix_path(String p_path) const {
+ switch (_access_type) {
+ case ACCESS_RESOURCES: {
+ if (ProjectSettings::get_singleton()) {
+ if (p_path.begins_with("res://")) {
+ String resource_path = ProjectSettings::get_singleton()->get_resource_path();
+ if (resource_path != "") {
+ return p_path.replace_first("res:/", resource_path);
+ }
+ return p_path.replace_first("res://", "");
+ }
+ }
+
+ } break;
+ case ACCESS_USERDATA: {
+ if (p_path.begins_with("user://")) {
+ String data_dir = OS::get_singleton()->get_user_data_dir();
+ if (data_dir != "") {
+ return p_path.replace_first("user:/", data_dir);
+ }
+ return p_path.replace_first("user://", "");
+ }
+
+ } break;
+ case ACCESS_FILESYSTEM: {
+ return p_path;
+ } break;
+ case ACCESS_MAX:
+ break; // Can't happen, but silences warning
+ }
+
+ return p_path;
+}
+
+DirAccess::CreateFunc DirAccess::create_func[ACCESS_MAX] = { nullptr, nullptr, nullptr };
+
+DirAccess *DirAccess::create_for_path(const String &p_path) {
+ DirAccess *da = nullptr;
+ if (p_path.begins_with("res://")) {
+ da = create(ACCESS_RESOURCES);
+ } else if (p_path.begins_with("user://")) {
+ da = create(ACCESS_USERDATA);
+ } else {
+ da = create(ACCESS_FILESYSTEM);
+ }
+
+ return da;
+}
+
+DirAccess *DirAccess::open(const String &p_path, Error *r_error) {
+ DirAccess *da = create_for_path(p_path);
+
+ ERR_FAIL_COND_V_MSG(!da, nullptr, "Cannot create DirAccess for path '" + p_path + "'.");
+ Error err = da->change_dir(p_path);
+ if (r_error) {
+ *r_error = err;
+ }
+ if (err != OK) {
+ memdelete(da);
+ return nullptr;
+ }
+
+ return da;
+}
+
+DirAccess *DirAccess::create(AccessType p_access) {
+ DirAccess *da = create_func[p_access] ? create_func[p_access]() : nullptr;
+ if (da) {
+ da->_access_type = p_access;
+ }
+
+ return da;
+}
+
+String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
+ DirAccess *d = DirAccess::create(p_access);
+ if (!d) {
+ return p_path;
+ }
+
+ d->change_dir(p_path);
+ String full = d->get_current_dir();
+ memdelete(d);
+ return full;
+}
+
+Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
+ //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data());
+ Error err;
+ FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
+
+ if (err) {
+ ERR_PRINT("Failed to open " + p_from);
+ return err;
+ }
+
+ FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
+ if (err) {
+ fsrc->close();
+ memdelete(fsrc);
+ ERR_PRINT("Failed to open " + p_to);
+ return err;
+ }
+
+ fsrc->seek_end(0);
+ int size = fsrc->get_position();
+ fsrc->seek(0);
+ err = OK;
+ while (size--) {
+ if (fsrc->get_error() != OK) {
+ err = fsrc->get_error();
+ break;
+ }
+ if (fdst->get_error() != OK) {
+ err = fdst->get_error();
+ break;
+ }
+
+ fdst->store_8(fsrc->get_8());
+ }
+
+ if (err == OK && p_chmod_flags != -1) {
+ fdst->close();
+ err = FileAccess::set_unix_permissions(p_to, p_chmod_flags);
+ // If running on a platform with no chmod support (i.e., Windows), don't fail
+ if (err == ERR_UNAVAILABLE) {
+ err = OK;
+ }
+ }
+
+ memdelete(fsrc);
+ memdelete(fdst);
+
+ return err;
+}
+
+// Changes dir for the current scope, returning back to the original dir
+// when scope exits
+class DirChanger {
+ DirAccess *da;
+ String original_dir;
+
+public:
+ DirChanger(DirAccess *p_da, String p_dir) :
+ da(p_da),
+ original_dir(p_da->get_current_dir()) {
+ p_da->change_dir(p_dir);
+ }
+
+ ~DirChanger() {
+ da->change_dir(original_dir);
+ }
+};
+
+Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links) {
+ List<String> dirs;
+
+ String curdir = get_current_dir();
+ list_dir_begin();
+ String n = get_next();
+ while (n != String()) {
+ if (n != "." && n != "..") {
+ if (p_copy_links && is_link(get_current_dir().plus_file(n))) {
+ create_link(read_link(get_current_dir().plus_file(n)), p_to + n);
+ } else if (current_is_dir()) {
+ dirs.push_back(n);
+ } else {
+ const String &rel_path = n;
+ if (!n.is_rel_path()) {
+ list_dir_end();
+ return ERR_BUG;
+ }
+ Error err = copy(get_current_dir().plus_file(n), p_to + rel_path, p_chmod_flags);
+ if (err) {
+ list_dir_end();
+ return err;
+ }
+ }
+ }
+
+ n = get_next();
+ }
+
+ list_dir_end();
+
+ for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
+ String rel_path = E->get();
+ String target_dir = p_to + rel_path;
+ if (!p_target_da->dir_exists(target_dir)) {
+ Error err = p_target_da->make_dir(target_dir);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + target_dir + "'.");
+ }
+
+ Error err = change_dir(E->get());
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + E->get() + "'.");
+
+ err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags, p_copy_links);
+ if (err) {
+ change_dir("..");
+ ERR_FAIL_V_MSG(err, "Failed to copy recursively.");
+ }
+ err = change_dir("..");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to go back.");
+ }
+
+ return OK;
+}
+
+Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_copy_links) {
+ ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
+
+ DirAccess *target_da = DirAccess::create_for_path(p_to);
+ ERR_FAIL_COND_V_MSG(!target_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'.");
+
+ if (!target_da->dir_exists(p_to)) {
+ Error err = target_da->make_dir_recursive(p_to);
+ if (err) {
+ memdelete(target_da);
+ }
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + p_to + "'.");
+ }
+
+ if (!p_to.ends_with("/")) {
+ p_to = p_to + "/";
+ }
+
+ DirChanger dir_changer(this, p_from);
+ Error err = _copy_dir(target_da, p_to, p_chmod_flags, p_copy_links);
+ memdelete(target_da);
+
+ return err;
+}
+
+bool DirAccess::exists(String p_dir) {
+ DirAccess *da = DirAccess::create_for_path(p_dir);
+ bool valid = da->change_dir(p_dir) == OK;
+ memdelete(da);
+ return valid;
+}
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
new file mode 100644
index 0000000000..16154a4850
--- /dev/null
+++ b/core/io/dir_access.h
@@ -0,0 +1,147 @@
+/*************************************************************************/
+/* dir_access.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef DIR_ACCESS_H
+#define DIR_ACCESS_H
+
+#include "core/string/ustring.h"
+#include "core/typedefs.h"
+
+//@ TODO, excellent candidate for THREAD_SAFE MACRO, should go through all these and add THREAD_SAFE where it applies
+class DirAccess {
+public:
+ enum AccessType {
+ ACCESS_RESOURCES,
+ ACCESS_USERDATA,
+ ACCESS_FILESYSTEM,
+ ACCESS_MAX
+ };
+
+ typedef DirAccess *(*CreateFunc)();
+
+private:
+ AccessType _access_type = ACCESS_FILESYSTEM;
+ static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
+
+ Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links);
+
+protected:
+ String _get_root_path() const;
+ String _get_root_string() const;
+
+ String fix_path(String p_path) const;
+
+ template <class T>
+ static DirAccess *_create_builtin() {
+ return memnew(T);
+ }
+
+public:
+ virtual Error list_dir_begin() = 0; ///< This starts dir listing
+ virtual String get_next() = 0;
+ virtual bool current_is_dir() const = 0;
+ virtual bool current_is_hidden() const = 0;
+
+ virtual void list_dir_end() = 0; ///<
+
+ virtual int get_drive_count() = 0;
+ virtual String get_drive(int p_drive) = 0;
+ virtual int get_current_drive();
+ virtual bool drives_are_shortcuts();
+
+ virtual Error change_dir(String p_dir) = 0; ///< can be relative or absolute, return false on success
+ virtual String get_current_dir(bool p_include_drive = true) = 0; ///< return current dir location
+ virtual Error make_dir(String p_dir) = 0;
+ virtual Error make_dir_recursive(String p_dir);
+ virtual Error erase_contents_recursive(); //super dangerous, use with care!
+
+ virtual bool file_exists(String p_file) = 0;
+ virtual bool dir_exists(String p_dir) = 0;
+ virtual bool is_readable(String p_dir) { return true; };
+ virtual bool is_writable(String p_dir) { return true; };
+ static bool exists(String p_dir);
+ virtual uint64_t get_space_left() = 0;
+
+ Error copy_dir(String p_from, String p_to, int p_chmod_flags = -1, bool p_copy_links = false);
+ virtual Error copy(String p_from, String p_to, int p_chmod_flags = -1);
+ virtual Error rename(String p_from, String p_to) = 0;
+ virtual Error remove(String p_name) = 0;
+
+ virtual bool is_link(String p_file) = 0;
+ virtual String read_link(String p_file) = 0;
+ virtual Error create_link(String p_source, String p_target) = 0;
+
+ // Meant for editor code when we want to quickly remove a file without custom
+ // handling (e.g. removing a cache file).
+ static void remove_file_or_error(String p_path) {
+ DirAccess *da = create(ACCESS_FILESYSTEM);
+ if (da->file_exists(p_path)) {
+ if (da->remove(p_path) != OK) {
+ ERR_FAIL_MSG("Cannot remove file or directory: " + p_path);
+ }
+ }
+ memdelete(da);
+ }
+
+ virtual String get_filesystem_type() const = 0;
+ static String get_full_path(const String &p_path, AccessType p_access);
+ static DirAccess *create_for_path(const String &p_path);
+
+ static DirAccess *create(AccessType p_access);
+
+ template <class T>
+ static void make_default(AccessType p_access) {
+ create_func[p_access] = _create_builtin<T>;
+ }
+
+ static DirAccess *open(const String &p_path, Error *r_error = nullptr);
+
+ DirAccess() {}
+ virtual ~DirAccess() {}
+};
+
+struct DirAccessRef {
+ _FORCE_INLINE_ DirAccess *operator->() {
+ return f;
+ }
+
+ operator bool() const { return f != nullptr; }
+
+ DirAccess *f;
+
+ DirAccessRef(DirAccess *fa) { f = fa; }
+ ~DirAccessRef() {
+ if (f) {
+ memdelete(f);
+ }
+ }
+};
+
+#endif // DIR_ACCESS_H
diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp
index 288b2efe0e..655fb18535 100644
--- a/core/io/dtls_server.cpp
+++ b/core/io/dtls_server.cpp
@@ -31,7 +31,7 @@
#include "dtls_server.h"
#include "core/config/project_settings.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
DTLSServer *(*DTLSServer::_create)() = nullptr;
bool DTLSServer::available = false;
diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h
index 92b6caf508..02a32533e1 100644
--- a/core/io/dtls_server.h
+++ b/core/io/dtls_server.h
@@ -34,8 +34,8 @@
#include "core/io/net_socket.h"
#include "core/io/packet_peer_dtls.h"
-class DTLSServer : public Reference {
- GDCLASS(DTLSServer, Reference);
+class DTLSServer : public RefCounted {
+ GDCLASS(DTLSServer, RefCounted);
protected:
static DTLSServer *(*_create)();
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
new file mode 100644
index 0000000000..d21c0bd9a2
--- /dev/null
+++ b/core/io/file_access.cpp
@@ -0,0 +1,676 @@
+/*************************************************************************/
+/* file_access.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "file_access.h"
+
+#include "core/config/project_settings.h"
+#include "core/crypto/crypto_core.h"
+#include "core/io/file_access_pack.h"
+#include "core/io/marshalls.h"
+#include "core/os/os.h"
+
+FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = { nullptr, nullptr };
+
+FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr;
+
+bool FileAccess::backup_save = false;
+
+FileAccess *FileAccess::create(AccessType p_access) {
+ ERR_FAIL_INDEX_V(p_access, ACCESS_MAX, nullptr);
+
+ FileAccess *ret = create_func[p_access]();
+ ret->_set_access_type(p_access);
+ return ret;
+}
+
+bool FileAccess::exists(const String &p_name) {
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) {
+ return true;
+ }
+
+ FileAccess *f = open(p_name, READ);
+ if (!f) {
+ return false;
+ }
+ memdelete(f);
+ return true;
+}
+
+void FileAccess::_set_access_type(AccessType p_access) {
+ _access_type = p_access;
+}
+
+FileAccess *FileAccess::create_for_path(const String &p_path) {
+ FileAccess *ret = nullptr;
+ if (p_path.begins_with("res://")) {
+ ret = create(ACCESS_RESOURCES);
+ } else if (p_path.begins_with("user://")) {
+ ret = create(ACCESS_USERDATA);
+
+ } else {
+ ret = create(ACCESS_FILESYSTEM);
+ }
+
+ return ret;
+}
+
+Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
+ return _open(p_path, p_mode_flags);
+}
+
+FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
+ //try packed data first
+
+ FileAccess *ret = nullptr;
+ if (!(p_mode_flags & WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
+ ret = PackedData::get_singleton()->try_open_path(p_path);
+ if (ret) {
+ if (r_error) {
+ *r_error = OK;
+ }
+ return ret;
+ }
+ }
+
+ ret = create_for_path(p_path);
+ Error err = ret->_open(p_path, p_mode_flags);
+
+ if (r_error) {
+ *r_error = err;
+ }
+ if (err != OK) {
+ memdelete(ret);
+ ret = nullptr;
+ }
+
+ return ret;
+}
+
+FileAccess::CreateFunc FileAccess::get_create_func(AccessType p_access) {
+ return create_func[p_access];
+}
+
+String FileAccess::fix_path(const String &p_path) const {
+ //helper used by file accesses that use a single filesystem
+
+ String r_path = p_path.replace("\\", "/");
+
+ switch (_access_type) {
+ case ACCESS_RESOURCES: {
+ if (ProjectSettings::get_singleton()) {
+ if (r_path.begins_with("res://")) {
+ String resource_path = ProjectSettings::get_singleton()->get_resource_path();
+ if (resource_path != "") {
+ return r_path.replace("res:/", resource_path);
+ }
+ return r_path.replace("res://", "");
+ }
+ }
+
+ } break;
+ case ACCESS_USERDATA: {
+ if (r_path.begins_with("user://")) {
+ String data_dir = OS::get_singleton()->get_user_data_dir();
+ if (data_dir != "") {
+ return r_path.replace("user:/", data_dir);
+ }
+ return r_path.replace("user://", "");
+ }
+
+ } break;
+ case ACCESS_FILESYSTEM: {
+ return r_path;
+ } break;
+ case ACCESS_MAX:
+ break; // Can't happen, but silences warning
+ }
+
+ return r_path;
+}
+
+/* these are all implemented for ease of porting, then can later be optimized */
+
+uint16_t FileAccess::get_16() const {
+ uint16_t res;
+ uint8_t a, b;
+
+ a = get_8();
+ b = get_8();
+
+ if (big_endian) {
+ SWAP(a, b);
+ }
+
+ res = b;
+ res <<= 8;
+ res |= a;
+
+ return res;
+}
+
+uint32_t FileAccess::get_32() const {
+ uint32_t res;
+ uint16_t a, b;
+
+ a = get_16();
+ b = get_16();
+
+ if (big_endian) {
+ SWAP(a, b);
+ }
+
+ res = b;
+ res <<= 16;
+ res |= a;
+
+ return res;
+}
+
+uint64_t FileAccess::get_64() const {
+ uint64_t res;
+ uint32_t a, b;
+
+ a = get_32();
+ b = get_32();
+
+ if (big_endian) {
+ SWAP(a, b);
+ }
+
+ res = b;
+ res <<= 32;
+ res |= a;
+
+ return res;
+}
+
+float FileAccess::get_float() const {
+ MarshallFloat m;
+ m.i = get_32();
+ return m.f;
+}
+
+real_t FileAccess::get_real() const {
+ if (real_is_double) {
+ return get_double();
+ } else {
+ return get_float();
+ }
+}
+
+double FileAccess::get_double() const {
+ MarshallDouble m;
+ m.l = get_64();
+ return m.d;
+}
+
+String FileAccess::get_token() const {
+ CharString token;
+
+ char32_t c = get_8();
+
+ while (!eof_reached()) {
+ if (c <= ' ') {
+ if (token.length()) {
+ break;
+ }
+ } else {
+ token += c;
+ }
+ c = get_8();
+ }
+
+ return String::utf8(token.get_data());
+}
+
+class CharBuffer {
+ Vector<char> vector;
+ char stack_buffer[256];
+
+ char *buffer = nullptr;
+ int capacity = 0;
+ int written = 0;
+
+ bool grow() {
+ if (vector.resize(next_power_of_2(1 + written)) != OK) {
+ return false;
+ }
+
+ if (buffer == stack_buffer) { // first chunk?
+
+ for (int i = 0; i < written; i++) {
+ vector.write[i] = stack_buffer[i];
+ }
+ }
+
+ buffer = vector.ptrw();
+ capacity = vector.size();
+ ERR_FAIL_COND_V(written >= capacity, false);
+
+ return true;
+ }
+
+public:
+ _FORCE_INLINE_ CharBuffer() :
+ buffer(stack_buffer),
+ capacity(sizeof(stack_buffer) / sizeof(char)) {
+ }
+
+ _FORCE_INLINE_ void push_back(char c) {
+ if (written >= capacity) {
+ ERR_FAIL_COND(!grow());
+ }
+
+ buffer[written++] = c;
+ }
+
+ _FORCE_INLINE_ const char *get_data() const {
+ return buffer;
+ }
+};
+
+String FileAccess::get_line() const {
+ CharBuffer line;
+
+ char32_t c = get_8();
+
+ while (!eof_reached()) {
+ if (c == '\n' || c == '\0') {
+ line.push_back(0);
+ return String::utf8(line.get_data());
+ } else if (c != '\r') {
+ line.push_back(c);
+ }
+
+ c = get_8();
+ }
+ line.push_back(0);
+ return String::utf8(line.get_data());
+}
+
+Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
+ ERR_FAIL_COND_V(p_delim.length() != 1, Vector<String>());
+
+ String l;
+ int qc = 0;
+ do {
+ if (eof_reached()) {
+ break;
+ }
+
+ l += get_line() + "\n";
+ qc = 0;
+ for (int i = 0; i < l.length(); i++) {
+ if (l[i] == '"') {
+ qc++;
+ }
+ }
+
+ } while (qc % 2);
+
+ l = l.substr(0, l.length() - 1);
+
+ Vector<String> strings;
+
+ bool in_quote = false;
+ String current;
+ for (int i = 0; i < l.length(); i++) {
+ char32_t c = l[i];
+ char32_t s[2] = { 0, 0 };
+
+ if (!in_quote && c == p_delim[0]) {
+ strings.push_back(current);
+ current = String();
+ } else if (c == '"') {
+ if (l[i + 1] == '"' && in_quote) {
+ s[0] = '"';
+ current += s;
+ i++;
+ } else {
+ in_quote = !in_quote;
+ }
+ } else {
+ s[0] = c;
+ current += s;
+ }
+ }
+
+ strings.push_back(current);
+
+ return strings;
+}
+
+uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+
+ uint64_t i = 0;
+ for (i = 0; i < p_length && !eof_reached(); i++) {
+ p_dst[i] = get_8();
+ }
+
+ return i;
+}
+
+String FileAccess::get_as_utf8_string() const {
+ Vector<uint8_t> sourcef;
+ uint64_t len = get_length();
+ sourcef.resize(len + 1);
+
+ uint8_t *w = sourcef.ptrw();
+ uint64_t r = get_buffer(w, len);
+ ERR_FAIL_COND_V(r != len, String());
+ w[len] = 0;
+
+ String s;
+ if (s.parse_utf8((const char *)w)) {
+ return String();
+ }
+ return s;
+}
+
+void FileAccess::store_16(uint16_t p_dest) {
+ uint8_t a, b;
+
+ a = p_dest & 0xFF;
+ b = p_dest >> 8;
+
+ if (big_endian) {
+ SWAP(a, b);
+ }
+
+ store_8(a);
+ store_8(b);
+}
+
+void FileAccess::store_32(uint32_t p_dest) {
+ uint16_t a, b;
+
+ a = p_dest & 0xFFFF;
+ b = p_dest >> 16;
+
+ if (big_endian) {
+ SWAP(a, b);
+ }
+
+ store_16(a);
+ store_16(b);
+}
+
+void FileAccess::store_64(uint64_t p_dest) {
+ uint32_t a, b;
+
+ a = p_dest & 0xFFFFFFFF;
+ b = p_dest >> 32;
+
+ if (big_endian) {
+ SWAP(a, b);
+ }
+
+ store_32(a);
+ store_32(b);
+}
+
+void FileAccess::store_real(real_t p_real) {
+ if (sizeof(real_t) == 4) {
+ store_float(p_real);
+ } else {
+ store_double(p_real);
+ }
+}
+
+void FileAccess::store_float(float p_dest) {
+ MarshallFloat m;
+ m.f = p_dest;
+ store_32(m.i);
+}
+
+void FileAccess::store_double(double p_dest) {
+ MarshallDouble m;
+ m.d = p_dest;
+ store_64(m.l);
+}
+
+uint64_t FileAccess::get_modified_time(const String &p_file) {
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
+ return 0;
+ }
+
+ FileAccess *fa = create_for_path(p_file);
+ ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
+
+ uint64_t mt = fa->_get_modified_time(p_file);
+ memdelete(fa);
+ return mt;
+}
+
+uint32_t FileAccess::get_unix_permissions(const String &p_file) {
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
+ return 0;
+ }
+
+ FileAccess *fa = create_for_path(p_file);
+ ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
+
+ uint32_t mt = fa->_get_unix_permissions(p_file);
+ memdelete(fa);
+ return mt;
+}
+
+Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
+ return ERR_UNAVAILABLE;
+ }
+
+ FileAccess *fa = create_for_path(p_file);
+ ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
+
+ Error err = fa->_set_unix_permissions(p_file, p_permissions);
+ memdelete(fa);
+ return err;
+}
+
+void FileAccess::store_string(const String &p_string) {
+ if (p_string.length() == 0) {
+ return;
+ }
+
+ CharString cs = p_string.utf8();
+ store_buffer((uint8_t *)&cs[0], cs.length());
+}
+
+void FileAccess::store_pascal_string(const String &p_string) {
+ CharString cs = p_string.utf8();
+ store_32(cs.length());
+ store_buffer((uint8_t *)&cs[0], cs.length());
+}
+
+String FileAccess::get_pascal_string() {
+ uint32_t sl = get_32();
+ CharString cs;
+ cs.resize(sl + 1);
+ get_buffer((uint8_t *)cs.ptr(), sl);
+ cs[sl] = 0;
+
+ String ret;
+ ret.parse_utf8(cs.ptr());
+
+ return ret;
+}
+
+void FileAccess::store_line(const String &p_line) {
+ store_string(p_line);
+ store_8('\n');
+}
+
+void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
+ ERR_FAIL_COND(p_delim.length() != 1);
+
+ String line = "";
+ int size = p_values.size();
+ for (int i = 0; i < size; ++i) {
+ String value = p_values[i];
+
+ if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n") != -1) {
+ value = "\"" + value.replace("\"", "\"\"") + "\"";
+ }
+ if (i < size - 1) {
+ value += p_delim;
+ }
+
+ line += value;
+ }
+
+ store_line(line);
+}
+
+void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
+ ERR_FAIL_COND(!p_src && p_length > 0);
+ for (uint64_t i = 0; i < p_length; i++) {
+ store_8(p_src[i]);
+ }
+}
+
+Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) {
+ FileAccess *f = FileAccess::open(p_path, READ, r_error);
+ if (!f) {
+ if (r_error) { // if error requested, do not throw error
+ return Vector<uint8_t>();
+ }
+ ERR_FAIL_V_MSG(Vector<uint8_t>(), "Can't open file from path '" + String(p_path) + "'.");
+ }
+ Vector<uint8_t> data;
+ data.resize(f->get_length());
+ f->get_buffer(data.ptrw(), data.size());
+ memdelete(f);
+ return data;
+}
+
+String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
+ Error err;
+ Vector<uint8_t> array = get_file_as_array(p_path, &err);
+ if (r_error) {
+ *r_error = err;
+ }
+ if (err != OK) {
+ if (r_error) {
+ return String();
+ }
+ ERR_FAIL_V_MSG(String(), "Can't get file as string from path '" + String(p_path) + "'.");
+ }
+
+ String ret;
+ ret.parse_utf8((const char *)array.ptr(), array.size());
+ return ret;
+}
+
+String FileAccess::get_md5(const String &p_file) {
+ FileAccess *f = FileAccess::open(p_file, READ);
+ if (!f) {
+ return String();
+ }
+
+ CryptoCore::MD5Context ctx;
+ ctx.start();
+
+ unsigned char step[32768];
+
+ while (true) {
+ uint64_t br = f->get_buffer(step, 32768);
+ if (br > 0) {
+ ctx.update(step, br);
+ }
+ if (br < 4096) {
+ break;
+ }
+ }
+
+ unsigned char hash[16];
+ ctx.finish(hash);
+
+ memdelete(f);
+
+ return String::md5(hash);
+}
+
+String FileAccess::get_multiple_md5(const Vector<String> &p_file) {
+ CryptoCore::MD5Context ctx;
+ ctx.start();
+
+ for (int i = 0; i < p_file.size(); i++) {
+ FileAccess *f = FileAccess::open(p_file[i], READ);
+ ERR_CONTINUE(!f);
+
+ unsigned char step[32768];
+
+ while (true) {
+ uint64_t br = f->get_buffer(step, 32768);
+ if (br > 0) {
+ ctx.update(step, br);
+ }
+ if (br < 4096) {
+ break;
+ }
+ }
+ memdelete(f);
+ }
+
+ unsigned char hash[16];
+ ctx.finish(hash);
+
+ return String::md5(hash);
+}
+
+String FileAccess::get_sha256(const String &p_file) {
+ FileAccess *f = FileAccess::open(p_file, READ);
+ if (!f) {
+ return String();
+ }
+
+ CryptoCore::SHA256Context ctx;
+ ctx.start();
+
+ unsigned char step[32768];
+
+ while (true) {
+ uint64_t br = f->get_buffer(step, 32768);
+ if (br > 0) {
+ ctx.update(step, br);
+ }
+ if (br < 4096) {
+ break;
+ }
+ }
+
+ unsigned char hash[32];
+ ctx.finish(hash);
+
+ memdelete(f);
+ return String::hex_encode_buffer(hash, 32);
+}
diff --git a/core/io/file_access.h b/core/io/file_access.h
new file mode 100644
index 0000000000..5804aa2c47
--- /dev/null
+++ b/core/io/file_access.h
@@ -0,0 +1,198 @@
+/*************************************************************************/
+/* file_access.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef FILE_ACCESS_H
+#define FILE_ACCESS_H
+
+#include "core/math/math_defs.h"
+#include "core/os/memory.h"
+#include "core/string/ustring.h"
+#include "core/typedefs.h"
+
+/**
+ * Multi-Platform abstraction for accessing to files.
+ */
+
+class FileAccess {
+public:
+ enum AccessType {
+ ACCESS_RESOURCES,
+ ACCESS_USERDATA,
+ ACCESS_FILESYSTEM,
+ ACCESS_MAX
+ };
+
+ typedef void (*FileCloseFailNotify)(const String &);
+
+ typedef FileAccess *(*CreateFunc)();
+ bool big_endian = false;
+ bool real_is_double = false;
+
+ virtual uint32_t _get_unix_permissions(const String &p_file) = 0;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) = 0;
+
+protected:
+ String fix_path(const String &p_path) const;
+ virtual Error _open(const String &p_path, int p_mode_flags) = 0; ///< open a file
+ virtual uint64_t _get_modified_time(const String &p_file) = 0;
+
+ static FileCloseFailNotify close_fail_notify;
+
+private:
+ static bool backup_save;
+
+ AccessType _access_type = ACCESS_FILESYSTEM;
+ static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */
+ template <class T>
+ static FileAccess *_create_builtin() {
+ return memnew(T);
+ }
+
+public:
+ static void set_file_close_fail_notify_callback(FileCloseFailNotify p_cbk) { close_fail_notify = p_cbk; }
+
+ virtual void _set_access_type(AccessType p_access);
+
+ enum ModeFlags {
+ READ = 1,
+ WRITE = 2,
+ READ_WRITE = 3,
+ WRITE_READ = 7,
+ };
+
+ virtual void close() = 0; ///< close a file
+ virtual bool is_open() const = 0; ///< true when file is open
+
+ virtual String get_path() const { return ""; } /// returns the path for the current open file
+ virtual String get_path_absolute() const { return ""; } /// returns the absolute path for the current open file
+
+ virtual void seek(uint64_t p_position) = 0; ///< seek to a given position
+ virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file with negative offset
+ virtual uint64_t get_position() const = 0; ///< get position in the file
+ virtual uint64_t get_length() const = 0; ///< get size of the file
+
+ virtual bool eof_reached() const = 0; ///< reading passed EOF
+
+ virtual uint8_t get_8() const = 0; ///< get a byte
+ virtual uint16_t get_16() const; ///< get 16 bits uint
+ virtual uint32_t get_32() const; ///< get 32 bits uint
+ virtual uint64_t get_64() const; ///< get 64 bits uint
+
+ virtual float get_float() const;
+ virtual double get_double() const;
+ virtual real_t get_real() const;
+
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
+ virtual String get_line() const;
+ virtual String get_token() const;
+ virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
+ virtual String get_as_utf8_string() const;
+
+ /**
+ * Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
+ * It's not about the current CPU type but file formats.
+ * This flag gets reset to `false` (little endian) on each open.
+ */
+ virtual void set_big_endian(bool p_big_endian) { big_endian = p_big_endian; }
+ inline bool is_big_endian() const { return big_endian; }
+
+ virtual Error get_error() const = 0; ///< get last error
+
+ virtual void flush() = 0;
+ virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
+ virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
+ virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
+ virtual void store_64(uint64_t p_dest); ///< store 64 bits uint
+
+ virtual void store_float(float p_dest);
+ virtual void store_double(double p_dest);
+ virtual void store_real(real_t p_real);
+
+ virtual void store_string(const String &p_string);
+ virtual void store_line(const String &p_line);
+ virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
+
+ virtual void store_pascal_string(const String &p_string);
+ virtual String get_pascal_string();
+
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+
+ virtual bool file_exists(const String &p_name) = 0; ///< return true if a file exists
+
+ virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
+
+ static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
+ static FileAccess *create_for_path(const String &p_path);
+ static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files.
+ static CreateFunc get_create_func(AccessType p_access);
+ static bool exists(const String &p_name); ///< return true if a file exists
+ static uint64_t get_modified_time(const String &p_file);
+ static uint32_t get_unix_permissions(const String &p_file);
+ static Error set_unix_permissions(const String &p_file, uint32_t p_permissions);
+
+ static void set_backup_save(bool p_enable) { backup_save = p_enable; };
+ static bool is_backup_save_enabled() { return backup_save; };
+
+ static String get_md5(const String &p_file);
+ static String get_sha256(const String &p_file);
+ static String get_multiple_md5(const Vector<String> &p_file);
+
+ static Vector<uint8_t> get_file_as_array(const String &p_path, Error *r_error = nullptr);
+ static String get_file_as_string(const String &p_path, Error *r_error = nullptr);
+
+ template <class T>
+ static void make_default(AccessType p_access) {
+ create_func[p_access] = _create_builtin<T>;
+ }
+
+ FileAccess() {}
+ virtual ~FileAccess() {}
+};
+
+struct FileAccessRef {
+ _FORCE_INLINE_ FileAccess *operator->() {
+ return f;
+ }
+
+ operator bool() const { return f != nullptr; }
+
+ FileAccess *f;
+
+ operator FileAccess *() { return f; }
+
+ FileAccessRef(FileAccess *fa) { f = fa; }
+ ~FileAccessRef() {
+ if (f) {
+ memdelete(f);
+ }
+ }
+};
+
+#endif // FILE_ACCESS_H
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index b2440629e3..e54c947340 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -32,7 +32,7 @@
#include "core/string/print_string.h"
-void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) {
+void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, uint32_t p_block_size) {
magic = p_magic.ascii().get_data();
if (magic.length() > 4) {
magic = magic.substr(0, 4);
@@ -67,10 +67,10 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted.");
}
read_total = f->get_32();
- int bc = (read_total / block_size) + 1;
- int acc_ofs = f->get_position() + bc * 4;
- int max_bs = 0;
- for (int i = 0; i < bc; i++) {
+ uint32_t bc = (read_total / block_size) + 1;
+ uint64_t acc_ofs = f->get_position() + bc * 4;
+ uint32_t max_bs = 0;
+ for (uint32_t i = 0; i < bc; i++) {
ReadBlock rb;
rb.offset = acc_ofs;
rb.csize = f->get_32();
@@ -148,15 +148,15 @@ void FileAccessCompressed::close() {
f->store_32(cmode); //write compression mode 4
f->store_32(block_size); //write block size 4
f->store_32(write_max); //max amount of data written 4
- int bc = (write_max / block_size) + 1;
+ uint32_t bc = (write_max / block_size) + 1;
- for (int i = 0; i < bc; i++) {
+ for (uint32_t i = 0; i < bc; i++) {
f->store_32(0); //compressed sizes, will update later
}
Vector<int> block_sizes;
- for (int i = 0; i < bc; i++) {
- int bl = i == (bc - 1) ? write_max % block_size : block_size;
+ for (uint32_t i = 0; i < bc; i++) {
+ uint32_t bl = i == (bc - 1) ? write_max % block_size : block_size;
uint8_t *bp = &write_ptr[i * block_size];
Vector<uint8_t> cblock;
@@ -168,7 +168,7 @@ void FileAccessCompressed::close() {
}
f->seek(16); //ok write block sizes
- for (int i = 0; i < bc; i++) {
+ for (uint32_t i = 0; i < bc; i++) {
f->store_32(block_sizes[i]);
}
f->seek_end();
@@ -190,8 +190,9 @@ bool FileAccessCompressed::is_open() const {
return f != nullptr;
}
-void FileAccessCompressed::seek(size_t p_position) {
+void FileAccessCompressed::seek(uint64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+
if (writing) {
ERR_FAIL_COND(p_position > write_max);
@@ -204,7 +205,7 @@ void FileAccessCompressed::seek(size_t p_position) {
} else {
at_end = false;
read_eof = false;
- int block_idx = p_position / block_size;
+ uint32_t block_idx = p_position / block_size;
if (block_idx != read_block) {
read_block = block_idx;
f->seek(read_blocks[read_block].offset);
@@ -227,7 +228,7 @@ void FileAccessCompressed::seek_end(int64_t p_position) {
}
}
-size_t FileAccessCompressed::get_position() const {
+uint64_t FileAccessCompressed::get_position() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
if (writing) {
return write_pos;
@@ -236,7 +237,7 @@ size_t FileAccessCompressed::get_position() const {
}
}
-size_t FileAccessCompressed::get_len() const {
+uint64_t FileAccessCompressed::get_length() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
if (writing) {
return write_max;
@@ -285,9 +286,8 @@ uint8_t FileAccessCompressed::get_8() const {
return ret;
}
-int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
@@ -296,7 +296,7 @@ int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
return 0;
}
- for (int i = 0; i < p_length; i++) {
+ for (uint64_t i = 0; i < p_length; i++) {
p_dst[i] = read_ptr[read_pos];
read_pos++;
if (read_pos >= read_block_size) {
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 118d05ea57..3389e020e3 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -32,39 +32,39 @@
#define FILE_ACCESS_COMPRESSED_H
#include "core/io/compression.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
class FileAccessCompressed : public FileAccess {
Compression::Mode cmode = Compression::MODE_ZSTD;
bool writing = false;
- uint32_t write_pos = 0;
+ uint64_t write_pos = 0;
uint8_t *write_ptr = nullptr;
uint32_t write_buffer_size = 0;
- uint32_t write_max = 0;
+ uint64_t write_max = 0;
uint32_t block_size = 0;
mutable bool read_eof = false;
mutable bool at_end = false;
struct ReadBlock {
- int csize;
- int offset;
+ uint32_t csize;
+ uint64_t offset;
};
mutable Vector<uint8_t> comp_buffer;
uint8_t *read_ptr = nullptr;
- mutable int read_block = 0;
- int read_block_count = 0;
- mutable int read_block_size = 0;
- mutable int read_pos = 0;
+ mutable uint32_t read_block = 0;
+ uint32_t read_block_count = 0;
+ mutable uint32_t read_block_size = 0;
+ mutable uint64_t read_pos = 0;
Vector<ReadBlock> read_blocks;
- uint32_t read_total = 0;
+ uint64_t read_total = 0;
String magic = "GCMP";
mutable Vector<uint8_t> buffer;
FileAccess *f = nullptr;
public:
- void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, int p_block_size = 4096);
+ void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, uint32_t p_block_size = 4096);
Error open_after_magic(FileAccess *p_base);
@@ -72,15 +72,15 @@ public:
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
- virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual uint64_t get_position() const; ///< get position in the file
+ virtual uint64_t get_length() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual Error get_error() const; ///< get last error
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 13377a3a25..9e316291e8 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -69,14 +69,14 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
}
base = p_base->get_position();
- ERR_FAIL_COND_V(p_base->get_len() < base + length, ERR_FILE_CORRUPT);
- uint32_t ds = length;
+ ERR_FAIL_COND_V(p_base->get_length() < base + length, ERR_FILE_CORRUPT);
+ uint64_t ds = length;
if (ds % 16) {
ds += 16 - (ds % 16);
}
data.resize(ds);
- uint32_t blen = p_base->get_buffer(data.ptrw(), ds);
+ uint64_t blen = p_base->get_buffer(data.ptrw(), ds);
ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT);
{
@@ -141,7 +141,7 @@ void FileAccessEncrypted::release() {
void FileAccessEncrypted::_release() {
if (writing) {
Vector<uint8_t> compressed;
- size_t len = data.size();
+ uint64_t len = data.size();
if (len % 16) {
len += 16 - (len % 16);
}
@@ -198,9 +198,9 @@ String FileAccessEncrypted::get_path_absolute() const {
}
}
-void FileAccessEncrypted::seek(size_t p_position) {
- if (p_position > (size_t)data.size()) {
- p_position = data.size();
+void FileAccessEncrypted::seek(uint64_t p_position) {
+ if (p_position > get_length()) {
+ p_position = get_length();
}
pos = p_position;
@@ -208,14 +208,14 @@ void FileAccessEncrypted::seek(size_t p_position) {
}
void FileAccessEncrypted::seek_end(int64_t p_position) {
- seek(data.size() + p_position);
+ seek(get_length() + p_position);
}
-size_t FileAccessEncrypted::get_position() const {
+uint64_t FileAccessEncrypted::get_position() const {
return pos;
}
-size_t FileAccessEncrypted::get_len() const {
+uint64_t FileAccessEncrypted::get_length() const {
return data.size();
}
@@ -225,7 +225,7 @@ bool FileAccessEncrypted::eof_reached() const {
uint8_t FileAccessEncrypted::get_8() const {
ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
- if (pos >= data.size()) {
+ if (pos >= get_length()) {
eofed = true;
return 0;
}
@@ -235,13 +235,12 @@ uint8_t FileAccessEncrypted::get_8() const {
return b;
}
-int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessEncrypted::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
- int to_copy = MIN(p_length, data.size() - pos);
- for (int i = 0; i < to_copy; i++) {
+ uint64_t to_copy = MIN(p_length, get_length() - pos);
+ for (uint64_t i = 0; i < to_copy; i++) {
p_dst[i] = data[pos++];
}
@@ -256,16 +255,17 @@ Error FileAccessEncrypted::get_error() const {
return eofed ? ERR_FILE_EOF : OK;
}
-void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
+void FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
+ ERR_FAIL_COND(!p_src && p_length > 0);
- if (pos < data.size()) {
- for (int i = 0; i < p_length; i++) {
+ if (pos < get_length()) {
+ for (uint64_t i = 0; i < p_length; i++) {
store_8(p_src[i]);
}
- } else if (pos == data.size()) {
+ } else if (pos == get_length()) {
data.resize(pos + p_length);
- for (int i = 0; i < p_length; i++) {
+ for (uint64_t i = 0; i < p_length; i++) {
data.write[pos + i] = p_src[i];
}
pos += p_length;
@@ -281,10 +281,10 @@ void FileAccessEncrypted::flush() {
void FileAccessEncrypted::store_8(uint8_t p_dest) {
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
- if (pos < data.size()) {
+ if (pos < get_length()) {
data.write[pos] = p_dest;
pos++;
- } else if (pos == data.size()) {
+ } else if (pos == get_length()) {
data.push_back(p_dest);
pos++;
}
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index 969052d04f..decffae696 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -31,7 +31,7 @@
#ifndef FILE_ACCESS_ENCRYPTED_H
#define FILE_ACCESS_ENCRYPTED_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#define ENCRYPTED_HEADER_MAGIC 0x43454447
@@ -47,10 +47,10 @@ private:
Vector<uint8_t> key;
bool writing = false;
FileAccess *file = nullptr;
- size_t base = 0;
- size_t length = 0;
+ uint64_t base = 0;
+ uint64_t length = 0;
Vector<uint8_t> data;
- mutable int pos = 0;
+ mutable uint64_t pos = 0;
mutable bool eofed = false;
bool use_magic = true;
@@ -68,21 +68,21 @@ public:
virtual String get_path() const; /// returns the path for the current open file
virtual String get_path_absolute() const; /// returns the absolute path for the current open file
- virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual uint64_t get_position() const; ///< get position in the file
+ virtual uint64_t get_length() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index af155a77a8..627fd2bf9c 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -31,7 +31,7 @@
#include "file_access_memory.h"
#include "core/config/project_settings.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/templates/map.h"
static Map<String, Vector<uint8_t>> *files = nullptr;
@@ -71,7 +71,7 @@ bool FileAccessMemory::file_exists(const String &p_name) {
return files && (files->find(name) != nullptr);
}
-Error FileAccessMemory::open_custom(const uint8_t *p_data, int p_len) {
+Error FileAccessMemory::open_custom(const uint8_t *p_data, uint64_t p_len) {
data = (uint8_t *)p_data;
length = p_len;
pos = 0;
@@ -102,7 +102,7 @@ bool FileAccessMemory::is_open() const {
return data != nullptr;
}
-void FileAccessMemory::seek(size_t p_position) {
+void FileAccessMemory::seek(uint64_t p_position) {
ERR_FAIL_COND(!data);
pos = p_position;
}
@@ -112,12 +112,12 @@ void FileAccessMemory::seek_end(int64_t p_position) {
pos = length + p_position;
}
-size_t FileAccessMemory::get_position() const {
+uint64_t FileAccessMemory::get_position() const {
ERR_FAIL_COND_V(!data, 0);
return pos;
}
-size_t FileAccessMemory::get_len() const {
+uint64_t FileAccessMemory::get_length() const {
ERR_FAIL_COND_V(!data, 0);
return length;
}
@@ -136,13 +136,12 @@ uint8_t FileAccessMemory::get_8() const {
return ret;
}
-int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessMemory::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(!data, -1);
- int left = length - pos;
- int read = MIN(p_length, left);
+ uint64_t left = length - pos;
+ uint64_t read = MIN(p_length, left);
if (read < p_length) {
WARN_PRINT("Reading less data than requested");
@@ -168,9 +167,10 @@ void FileAccessMemory::store_8(uint8_t p_byte) {
data[pos++] = p_byte;
}
-void FileAccessMemory::store_buffer(const uint8_t *p_src, int p_length) {
- int left = length - pos;
- int write = MIN(p_length, left);
+void FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) {
+ ERR_FAIL_COND(!p_src && p_length > 0);
+ uint64_t left = length - pos;
+ uint64_t write = MIN(p_length, left);
if (write < p_length) {
WARN_PRINT("Writing less data than requested");
}
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 0e3b0ad7b1..14135bd68c 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -31,12 +31,12 @@
#ifndef FILE_ACCESS_MEMORY_H
#define FILE_ACCESS_MEMORY_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
class FileAccessMemory : public FileAccess {
uint8_t *data = nullptr;
- int length = 0;
- mutable int pos = 0;
+ uint64_t length = 0;
+ mutable uint64_t pos = 0;
static FileAccess *create();
@@ -44,27 +44,27 @@ public:
static void register_file(String p_name, Vector<uint8_t> p_data);
static void cleanup();
- virtual Error open_custom(const uint8_t *p_data, int p_len); ///< open a file
+ virtual Error open_custom(const uint8_t *p_data, uint64_t p_len); ///< open a file
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
- virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual uint64_t get_position() const; ///< get position in the file
+ virtual uint64_t get_length() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_byte); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 4cc73bcd22..63a8f9c5b6 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -126,7 +126,7 @@ void FileAccessNetworkClient::_thread_func() {
if (status != OK) {
fa->_respond(0, Error(status));
} else {
- uint64_t len = get_64();
+ int64_t len = get_64();
fa->_respond(len, Error(status));
}
@@ -135,7 +135,7 @@ void FileAccessNetworkClient::_thread_func() {
} break;
case FileAccessNetwork::RESPONSE_DATA: {
int64_t offset = get_64();
- uint32_t len = get_32();
+ int32_t len = get_32();
Vector<uint8_t> block;
block.resize(len);
@@ -219,13 +219,13 @@ FileAccessNetworkClient::~FileAccessNetworkClient() {
thread.wait_to_finish();
}
-void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block) {
- int page = p_offset / page_size;
+void FileAccessNetwork::_set_block(uint64_t p_offset, const Vector<uint8_t> &p_block) {
+ int32_t page = p_offset / page_size;
ERR_FAIL_INDEX(page, pages.size());
if (page < pages.size() - 1) {
ERR_FAIL_COND(p_block.size() != page_size);
} else {
- ERR_FAIL_COND((p_block.size() != (int)(total_size % page_size)));
+ ERR_FAIL_COND((uint64_t)p_block.size() != total_size % page_size);
}
{
@@ -240,7 +240,7 @@ void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block)
}
}
-void FileAccessNetwork::_respond(size_t p_len, Error p_status) {
+void FileAccessNetwork::_respond(uint64_t p_len, Error p_status) {
DEBUG_PRINT("GOT RESPONSE - len: " + itos(p_len) + " status: " + itos(p_status));
response = p_status;
if (response != OK) {
@@ -248,7 +248,7 @@ void FileAccessNetwork::_respond(size_t p_len, Error p_status) {
}
opened = true;
total_size = p_len;
- int pc = ((total_size - 1) / page_size) + 1;
+ int32_t pc = ((total_size - 1) / page_size) + 1;
pages.resize(pc);
}
@@ -307,8 +307,9 @@ bool FileAccessNetwork::is_open() const {
return opened;
}
-void FileAccessNetwork::seek(size_t p_position) {
+void FileAccessNetwork::seek(uint64_t p_position) {
ERR_FAIL_COND_MSG(!opened, "File must be opened before use.");
+
eof_flag = p_position > total_size;
if (p_position >= total_size) {
@@ -322,12 +323,12 @@ void FileAccessNetwork::seek_end(int64_t p_position) {
seek(total_size + p_position);
}
-size_t FileAccessNetwork::get_position() const {
+uint64_t FileAccessNetwork::get_position() const {
ERR_FAIL_COND_V_MSG(!opened, 0, "File must be opened before use.");
return pos;
}
-size_t FileAccessNetwork::get_len() const {
+uint64_t FileAccessNetwork::get_length() const {
ERR_FAIL_COND_V_MSG(!opened, 0, "File must be opened before use.");
return total_size;
}
@@ -343,7 +344,7 @@ uint8_t FileAccessNetwork::get_8() const {
return v;
}
-void FileAccessNetwork::_queue_page(int p_page) const {
+void FileAccessNetwork::_queue_page(int32_t p_page) const {
if (p_page >= pages.size()) {
return;
}
@@ -354,7 +355,7 @@ void FileAccessNetwork::_queue_page(int p_page) const {
FileAccessNetworkClient::BlockRequest br;
br.id = id;
- br.offset = size_t(p_page) * page_size;
+ br.offset = (uint64_t)p_page * page_size;
br.size = page_size;
nc->block_requests.push_back(br);
pages.write[p_page].queued = true;
@@ -365,11 +366,9 @@ void FileAccessNetwork::_queue_page(int p_page) const {
}
}
-int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessNetwork::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
- //bool eof=false;
if (pos + p_length > total_size) {
eof_flag = true;
}
@@ -377,18 +376,16 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
p_length = total_size - pos;
}
- //FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
-
uint8_t *buff = last_page_buff;
- for (int i = 0; i < p_length; i++) {
- int page = pos / page_size;
+ for (uint64_t i = 0; i < p_length; i++) {
+ int32_t page = pos / page_size;
if (page != last_page) {
buffer_mutex.lock();
if (pages[page].buffer.is_empty()) {
waiting_on_page = page;
- for (int j = 0; j < read_ahead; j++) {
+ for (int32_t j = 0; j < read_ahead; j++) {
_queue_page(page + j);
}
buffer_mutex.unlock();
@@ -396,10 +393,9 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
page_sem.wait();
DEBUG_PRINT("done");
} else {
- for (int j = 0; j < read_ahead; j++) {
+ for (int32_t j = 0; j < read_ahead; j++) {
_queue_page(page + j);
}
- //queue pages
buffer_mutex.unlock();
}
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 1f5de3e5dd..1d9d761fbb 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -31,8 +31,8 @@
#ifndef FILE_ACCESS_NETWORK_H
#define FILE_ACCESS_NETWORK_H
+#include "core/io/file_access.h"
#include "core/io/stream_peer_tcp.h"
-#include "core/os/file_access.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
@@ -40,9 +40,9 @@ class FileAccessNetwork;
class FileAccessNetworkClient {
struct BlockRequest {
- int id;
+ int32_t id;
uint64_t offset;
- int size;
+ int32_t size;
};
List<BlockRequest> block_requests;
@@ -54,17 +54,17 @@ class FileAccessNetworkClient {
Mutex blockrequest_mutex;
Map<int, FileAccessNetwork *> accesses;
Ref<StreamPeerTCP> client;
- int last_id = 0;
- int lockcount = 0;
+ int32_t last_id = 0;
+ int32_t lockcount = 0;
Vector<uint8_t> block;
void _thread_func();
static void _thread_func(void *s);
- void put_32(int p_32);
+ void put_32(int32_t p_32);
void put_64(int64_t p_64);
- int get_32();
+ int32_t get_32();
int64_t get_64();
void lock_mutex();
void unlock_mutex();
@@ -86,15 +86,15 @@ class FileAccessNetwork : public FileAccess {
Semaphore page_sem;
Mutex buffer_mutex;
bool opened = false;
- size_t total_size;
- mutable size_t pos = 0;
- int id;
+ uint64_t total_size;
+ mutable uint64_t pos = 0;
+ int32_t id;
mutable bool eof_flag = false;
- mutable int last_page = -1;
+ mutable int32_t last_page = -1;
mutable uint8_t *last_page_buff = nullptr;
- int page_size;
- int read_ahead;
+ int32_t page_size;
+ int32_t read_ahead;
mutable int waiting_on_page = -1;
@@ -110,9 +110,9 @@ class FileAccessNetwork : public FileAccess {
uint64_t exists_modtime;
friend class FileAccessNetworkClient;
- void _queue_page(int p_page) const;
- void _respond(size_t p_len, Error p_status);
- void _set_block(int p_offset, const Vector<uint8_t> &p_block);
+ void _queue_page(int32_t p_page) const;
+ void _respond(uint64_t p_len, Error p_status);
+ void _set_block(uint64_t p_offset, const Vector<uint8_t> &p_block);
public:
enum Command {
@@ -134,15 +134,15 @@ public:
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
- virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual uint64_t get_position() const; ///< get position in the file
+ virtual uint64_t get_length() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual Error get_error() const; ///< get last error
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index e24dc40166..7b43daf9c0 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -36,7 +36,7 @@
#include <stdio.h>
-Error PackedData::add_pack(const String &p_path, bool p_replace_files, size_t p_offset) {
+Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
for (int i = 0; i < sources.size(); i++) {
if (sources[i]->try_open_pack(p_path, p_replace_files, p_offset)) {
return OK;
@@ -46,17 +46,16 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, size_t p_
return ERR_FILE_UNRECOGNIZED;
}
-void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) {
- PathMD5 pmd5(path.md5_buffer());
- //printf("adding path %s, %lli, %lli\n", path.utf8().get_data(), pmd5.a, pmd5.b);
+void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) {
+ PathMD5 pmd5(p_path.md5_buffer());
bool exists = files.has(pmd5);
PackedFile pf;
pf.encrypted = p_encrypted;
- pf.pack = pkg_path;
- pf.offset = ofs;
- pf.size = size;
+ pf.pack = p_pkg_path;
+ pf.offset = p_ofs;
+ pf.size = p_size;
for (int i = 0; i < 16; i++) {
pf.md5[i] = p_md5[i];
}
@@ -68,7 +67,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
if (!exists) {
//search for dir
- String p = path.replace_first("res://", "");
+ String p = p_path.replace_first("res://", "");
PackedDir *cd = root;
if (p.find("/") != -1) { //in a subdir
@@ -87,7 +86,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
}
}
}
- String filename = path.get_file();
+ String filename = p_path.get_file();
// Don't add as a file if the path points to a directory
if (!filename.is_empty()) {
cd->files.insert(filename);
@@ -126,7 +125,7 @@ PackedData::~PackedData() {
//////////////////////////////////////////////////////////////////
-bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset) {
+bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
return false;
@@ -261,7 +260,7 @@ bool FileAccessPack::is_open() const {
return f->is_open();
}
-void FileAccessPack::seek(size_t p_position) {
+void FileAccessPack::seek(uint64_t p_position) {
if (p_position > pf.size) {
eof = true;
} else {
@@ -276,11 +275,11 @@ void FileAccessPack::seek_end(int64_t p_position) {
seek(pf.size + p_position);
}
-size_t FileAccessPack::get_position() const {
+uint64_t FileAccessPack::get_position() const {
return pos;
}
-size_t FileAccessPack::get_len() const {
+uint64_t FileAccessPack::get_length() const {
return pf.size;
}
@@ -298,18 +297,17 @@ uint8_t FileAccessPack::get_8() const {
return f->get_8();
}
-int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
if (eof) {
return 0;
}
- uint64_t to_read = p_length;
+ int64_t to_read = p_length;
if (to_read + pos > pf.size) {
eof = true;
- to_read = int64_t(pf.size) - int64_t(pos);
+ to_read = (int64_t)pf.size - (int64_t)pos;
}
pos += p_length;
@@ -322,9 +320,9 @@ int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
return to_read;
}
-void FileAccessPack::set_endian_swap(bool p_swap) {
- FileAccess::set_endian_swap(p_swap);
- f->set_endian_swap(p_swap);
+void FileAccessPack::set_big_endian(bool p_big_endian) {
+ FileAccess::set_big_endian(p_big_endian);
+ f->set_big_endian(p_big_endian);
}
Error FileAccessPack::get_error() const {
@@ -342,7 +340,7 @@ void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL();
}
-void FileAccessPack::store_buffer(const uint8_t *p_src, int p_length) {
+void FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
}
@@ -549,7 +547,7 @@ Error DirAccessPack::remove(String p_name) {
return ERR_UNAVAILABLE;
}
-size_t DirAccessPack::get_space_left() {
+uint64_t DirAccessPack::get_space_left() {
return 0;
}
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 955108f455..2f0ee62723 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -31,8 +31,8 @@
#ifndef FILE_ACCESS_PACK_H
#define FILE_ACCESS_PACK_H
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/string/print_string.h"
#include "core/templates/list.h"
#include "core/templates/map.h"
@@ -112,13 +112,13 @@ private:
public:
void add_pack_source(PackSource *p_source);
- void add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource
+ void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource
void set_disabled(bool p_disabled) { disabled = p_disabled; }
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
static PackedData *get_singleton() { return singleton; }
- Error add_pack(const String &p_path, bool p_replace_files, size_t p_offset);
+ Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
_FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
@@ -132,21 +132,21 @@ public:
class PackSource {
public:
- virtual bool try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset) = 0;
+ virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) = 0;
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
virtual ~PackSource() {}
};
class PackedSourcePCK : public PackSource {
public:
- virtual bool try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset);
+ virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
};
class FileAccessPack : public FileAccess {
PackedData::PackedFile pf;
- mutable size_t pos;
+ mutable uint64_t pos;
mutable bool eof;
uint64_t off;
@@ -160,25 +160,25 @@ public:
virtual void close();
virtual bool is_open() const;
- virtual void seek(size_t p_position);
+ virtual void seek(uint64_t p_position);
virtual void seek_end(int64_t p_position = 0);
- virtual size_t get_position() const;
- virtual size_t get_len() const;
+ virtual uint64_t get_position() const;
+ virtual uint64_t get_length() const;
virtual bool eof_reached() const;
virtual uint8_t get_8() const;
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
- virtual void set_endian_swap(bool p_swap);
+ virtual void set_big_endian(bool p_big_endian);
virtual Error get_error() const;
virtual void flush();
virtual void store_8(uint8_t p_dest);
- virtual void store_buffer(const uint8_t *p_src, int p_length);
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length);
virtual bool file_exists(const String &p_name);
@@ -243,7 +243,11 @@ public:
virtual Error rename(String p_from, String p_to);
virtual Error remove(String p_name);
- size_t get_space_left();
+ uint64_t get_space_left();
+
+ virtual bool is_link(String p_file) { return false; }
+ virtual String read_link(String p_file) { return p_file; }
+ virtual Error create_link(String p_source, String p_target) { return FAILED; }
virtual String get_filesystem_type() const;
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index dbedb5254f..b5c882e9ce 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -32,7 +32,7 @@
#include "file_access_zip.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
ZipArchive *ZipArchive::instance = nullptr;
@@ -67,13 +67,13 @@ static long godot_tell(voidpf opaque, voidpf stream) {
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
FileAccess *f = (FileAccess *)stream;
- int pos = offset;
+ uint64_t pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
pos = f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
- pos = f->get_len() + offset;
+ pos = f->get_length() + offset;
break;
default:
break;
@@ -144,8 +144,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
return pkg;
}
-bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset = 0) {
- //printf("opening zip pack %s, %i, %i\n", p_name.utf8().get_data(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
+bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset = 0) {
// load with offset feature only supported for PCK files
ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Invalid PCK data. Note that loading files with a non-zero offset isn't supported with ZIP archives.");
@@ -227,9 +226,7 @@ ZipArchive::ZipArchive() {
ZipArchive::~ZipArchive() {
for (int i = 0; i < packages.size(); i++) {
- FileAccess *f = (FileAccess *)unzGetOpaque(packages[i].zfile);
unzClose(packages[i].zfile);
- memdelete(f);
}
packages.clear();
@@ -265,22 +262,23 @@ bool FileAccessZip::is_open() const {
return zfile != nullptr;
}
-void FileAccessZip::seek(size_t p_position) {
+void FileAccessZip::seek(uint64_t p_position) {
ERR_FAIL_COND(!zfile);
+
unzSeekCurrentFile(zfile, p_position);
}
void FileAccessZip::seek_end(int64_t p_position) {
ERR_FAIL_COND(!zfile);
- unzSeekCurrentFile(zfile, get_len() + p_position);
+ unzSeekCurrentFile(zfile, get_length() + p_position);
}
-size_t FileAccessZip::get_position() const {
+uint64_t FileAccessZip::get_position() const {
ERR_FAIL_COND_V(!zfile, 0);
return unztell(zfile);
}
-size_t FileAccessZip::get_len() const {
+uint64_t FileAccessZip::get_length() const {
ERR_FAIL_COND_V(!zfile, 0);
return file_info.uncompressed_size;
}
@@ -297,17 +295,17 @@ uint8_t FileAccessZip::get_8() const {
return ret;
}
-int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessZip::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(!zfile, -1);
+
at_eof = unzeof(zfile);
if (at_eof) {
return 0;
}
- int read = unzReadCurrentFile(zfile, p_dst, p_length);
+ int64_t read = unzReadCurrentFile(zfile, p_dst, p_length);
ERR_FAIL_COND_V(read < 0, read);
- if (read < p_length) {
+ if ((uint64_t)read < p_length) {
at_eof = true;
}
return read;
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 8559f871ce..cca14ded62 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -67,7 +67,7 @@ public:
bool file_exists(String p_name) const;
- virtual bool try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset);
+ virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
static ZipArchive *get_singleton();
@@ -87,20 +87,21 @@ public:
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
- virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual uint64_t get_position() const; ///< get position in the file
+ virtual uint64_t get_length() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
+
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
diff --git a/core/io/http_client.h b/core/io/http_client.h
index ec4b86b26f..f70999836f 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -34,10 +34,10 @@
#include "core/io/ip.h"
#include "core/io/stream_peer.h"
#include "core/io/stream_peer_tcp.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class HTTPClient : public Reference {
- GDCLASS(HTTPClient, Reference);
+class HTTPClient : public RefCounted {
+ GDCLASS(HTTPClient, RefCounted);
public:
enum ResponseCode {
diff --git a/core/io/image.cpp b/core/io/image.cpp
index c36fa6e45f..9cd0ea7b5d 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -1428,16 +1428,23 @@ void Image::flip_x() {
}
}
+/// Get mipmap size and offset.
int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps, int *r_mm_width, int *r_mm_height) {
+ // Data offset in mipmaps (including the original texture).
int size = 0;
+
int w = p_width;
int h = p_height;
+
+ // Current mipmap index in the loop below. p_mipmaps is the target mipmap index.
+ // In this function, mipmap 0 represents the first mipmap instead of the original texture.
int mm = 0;
int pixsize = get_format_pixel_size(p_format);
int pixshift = get_format_pixel_rshift(p_format);
int block = get_format_block_size(p_format);
- //technically, you can still compress up to 1 px no matter the format, so commenting this
+
+ // Technically, you can still compress up to 1 px no matter the format, so commenting this.
//int minw, minh;
//get_format_min_pixel_size(p_format, minw, minh);
int minw = 1, minh = 1;
@@ -1453,17 +1460,6 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &
size += s;
- if (r_mm_width) {
- *r_mm_width = bw;
- }
- if (r_mm_height) {
- *r_mm_height = bh;
- }
-
- if (p_mipmaps >= 0 && mm == p_mipmaps) {
- break;
- }
-
if (p_mipmaps >= 0) {
w = MAX(minw, w >> 1);
h = MAX(minh, h >> 1);
@@ -1474,6 +1470,21 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &
w = MAX(minw, w >> 1);
h = MAX(minh, h >> 1);
}
+
+ // Set mipmap size.
+ // It might be necessary to put this after the minimum mipmap size check because of the possible occurrence of "1 >> 1".
+ if (r_mm_width) {
+ *r_mm_width = bw >> 1;
+ }
+ if (r_mm_height) {
+ *r_mm_height = bh >> 1;
+ }
+
+ // Reach target mipmap.
+ if (p_mipmaps >= 0 && mm == p_mipmaps) {
+ break;
+ }
+
mm++;
}
@@ -2718,10 +2729,11 @@ void (*Image::_image_decompress_bptc)(Image *) = nullptr;
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
void (*Image::_image_decompress_etc2)(Image *) = nullptr;
-Vector<uint8_t> (*Image::lossy_packer)(const Ref<Image> &, float) = nullptr;
-Ref<Image> (*Image::lossy_unpacker)(const Vector<uint8_t> &) = nullptr;
-Vector<uint8_t> (*Image::lossless_packer)(const Ref<Image> &) = nullptr;
-Ref<Image> (*Image::lossless_unpacker)(const Vector<uint8_t> &) = nullptr;
+Vector<uint8_t> (*Image::webp_lossy_packer)(const Ref<Image> &, float) = nullptr;
+Vector<uint8_t> (*Image::webp_lossless_packer)(const Ref<Image> &) = nullptr;
+Ref<Image> (*Image::webp_unpacker)(const Vector<uint8_t> &) = nullptr;
+Vector<uint8_t> (*Image::png_packer)(const Ref<Image> &) = nullptr;
+Ref<Image> (*Image::png_unpacker)(const Vector<uint8_t> &) = nullptr;
Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = nullptr;
Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = nullptr;
diff --git a/core/io/image.h b/core/io/image.h
index df8f9b35a1..060e54a308 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -148,10 +148,11 @@ public:
static void (*_image_decompress_etc1)(Image *);
static void (*_image_decompress_etc2)(Image *);
- static Vector<uint8_t> (*lossy_packer)(const Ref<Image> &p_image, float p_quality);
- static Ref<Image> (*lossy_unpacker)(const Vector<uint8_t> &p_buffer);
- static Vector<uint8_t> (*lossless_packer)(const Ref<Image> &p_image);
- static Ref<Image> (*lossless_unpacker)(const Vector<uint8_t> &p_buffer);
+ static Vector<uint8_t> (*webp_lossy_packer)(const Ref<Image> &p_image, float p_quality);
+ static Vector<uint8_t> (*webp_lossless_packer)(const Ref<Image> &p_image);
+ static Ref<Image> (*webp_unpacker)(const Vector<uint8_t> &p_buffer);
+ static Vector<uint8_t> (*png_packer)(const Ref<Image> &p_image);
+ static Ref<Image> (*png_unpacker)(const Vector<uint8_t> &p_buffer);
static Vector<uint8_t> (*basis_universal_packer)(const Ref<Image> &p_image, UsedChannels p_channels);
static Ref<Image> (*basis_universal_unpacker)(const Vector<uint8_t> &p_buffer);
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index a5d588e0b5..6d1b1e3646 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -31,9 +31,9 @@
#ifndef IMAGE_LOADER_H
#define IMAGE_LOADER_H
+#include "core/io/file_access.h"
#include "core/io/image.h"
#include "core/io/resource_loader.h"
-#include "core/os/file_access.h"
#include "core/string/ustring.h"
#include "core/templates/list.h"
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index eb7814054b..001b1c4757 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -41,13 +41,15 @@ VARIANT_ENUM_CAST(IP::ResolverStatus);
struct _IP_ResolverPrivate {
struct QueueItem {
SafeNumeric<IP::ResolverStatus> status;
- IPAddress response;
+
+ List<IPAddress> response;
+
String hostname;
IP::Type type;
void clear() {
status.set(IP::RESOLVER_STATUS_NONE);
- response = IPAddress();
+ response.clear();
type = IP::TYPE_NONE;
hostname = "";
};
@@ -80,13 +82,9 @@ struct _IP_ResolverPrivate {
if (queue[i].status.get() != IP::RESOLVER_STATUS_WAITING) {
continue;
}
- queue[i].response = IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type);
- if (!queue[i].response.is_valid()) {
- queue[i].status.set(IP::RESOLVER_STATUS_ERROR);
- } else {
- queue[i].status.set(IP::RESOLVER_STATUS_DONE);
- }
+ IP::get_singleton()->_resolve_hostname(queue[i].response, queue[i].hostname, queue[i].type);
+ queue[i].status.set(queue[i].response.is_empty() ? IP::RESOLVER_STATUS_ERROR : IP::RESOLVER_STATUS_DONE);
}
}
@@ -101,7 +99,7 @@ struct _IP_ResolverPrivate {
}
}
- HashMap<String, IPAddress> cache;
+ HashMap<String, List<IPAddress>> cache;
static String get_cache_key(String p_hostname, IP::Type p_type) {
return itos(p_type) + p_hostname;
@@ -111,15 +109,41 @@ struct _IP_ResolverPrivate {
IPAddress IP::resolve_hostname(const String &p_hostname, IP::Type p_type) {
MutexLock lock(resolver->mutex);
+ List<IPAddress> res;
+
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
- if (resolver->cache.has(key) && resolver->cache[key].is_valid()) {
- IPAddress res = resolver->cache[key];
- return res;
+ if (resolver->cache.has(key)) {
+ res = resolver->cache[key];
+ } else {
+ _resolve_hostname(res, p_hostname, p_type);
+ resolver->cache[key] = res;
}
- IPAddress res = _resolve_hostname(p_hostname, p_type);
- resolver->cache[key] = res;
- return res;
+ for (int i = 0; i < res.size(); ++i) {
+ if (res[i].is_valid()) {
+ return res[i];
+ }
+ }
+ return IPAddress();
+}
+
+Array IP::resolve_hostname_addresses(const String &p_hostname, Type p_type) {
+ MutexLock lock(resolver->mutex);
+
+ String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
+ if (!resolver->cache.has(key)) {
+ _resolve_hostname(resolver->cache[key], p_hostname, p_type);
+ }
+
+ List<IPAddress> res = resolver->cache[key];
+
+ Array result;
+ for (int i = 0; i < res.size(); ++i) {
+ if (res[i].is_valid()) {
+ result.push_back(String(res[i]));
+ }
+ }
+ return result;
}
IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Type p_type) {
@@ -135,11 +159,11 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
resolver->queue[id].hostname = p_hostname;
resolver->queue[id].type = p_type;
- if (resolver->cache.has(key) && resolver->cache[key].is_valid()) {
+ if (resolver->cache.has(key)) {
resolver->queue[id].response = resolver->cache[key];
resolver->queue[id].status.set(IP::RESOLVER_STATUS_DONE);
} else {
- resolver->queue[id].response = IPAddress();
+ resolver->queue[id].response = List<IPAddress>();
resolver->queue[id].status.set(IP::RESOLVER_STATUS_WAITING);
if (resolver->thread.is_started()) {
resolver->sem.post();
@@ -158,7 +182,6 @@ IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const {
if (resolver->queue[p_id].status.get() == IP::RESOLVER_STATUS_NONE) {
ERR_PRINT("Condition status == IP::RESOLVER_STATUS_NONE");
- resolver->mutex.unlock();
return IP::RESOLVER_STATUS_NONE;
}
return resolver->queue[p_id].status.get();
@@ -171,11 +194,37 @@ IPAddress IP::get_resolve_item_address(ResolverID p_id) const {
if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) {
ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet.");
- resolver->mutex.unlock();
return IPAddress();
}
- return resolver->queue[p_id].response;
+ List<IPAddress> res = resolver->queue[p_id].response;
+
+ for (int i = 0; i < res.size(); ++i) {
+ if (res[i].is_valid()) {
+ return res[i];
+ }
+ }
+ return IPAddress();
+}
+
+Array IP::get_resolve_item_addresses(ResolverID p_id) const {
+ ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, Array());
+ MutexLock lock(resolver->mutex);
+
+ if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) {
+ ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet.");
+ return Array();
+ }
+
+ List<IPAddress> res = resolver->queue[p_id].response;
+
+ Array result;
+ for (int i = 0; i < res.size(); ++i) {
+ if (res[i].is_valid()) {
+ result.push_back(String(res[i]));
+ }
+ }
+ return result;
}
void IP::erase_resolve_item(ResolverID p_id) {
@@ -245,9 +294,11 @@ void IP::get_local_addresses(List<IPAddress> *r_addresses) const {
void IP::_bind_methods() {
ClassDB::bind_method(D_METHOD("resolve_hostname", "host", "ip_type"), &IP::resolve_hostname, DEFVAL(IP::TYPE_ANY));
+ ClassDB::bind_method(D_METHOD("resolve_hostname_addresses", "host", "ip_type"), &IP::resolve_hostname_addresses, DEFVAL(IP::TYPE_ANY));
ClassDB::bind_method(D_METHOD("resolve_hostname_queue_item", "host", "ip_type"), &IP::resolve_hostname_queue_item, DEFVAL(IP::TYPE_ANY));
ClassDB::bind_method(D_METHOD("get_resolve_item_status", "id"), &IP::get_resolve_item_status);
ClassDB::bind_method(D_METHOD("get_resolve_item_address", "id"), &IP::get_resolve_item_address);
+ ClassDB::bind_method(D_METHOD("get_resolve_item_addresses", "id"), &IP::get_resolve_item_addresses);
ClassDB::bind_method(D_METHOD("erase_resolve_item", "id"), &IP::erase_resolve_item);
ClassDB::bind_method(D_METHOD("get_local_addresses"), &IP::_get_local_addresses);
ClassDB::bind_method(D_METHOD("get_local_interfaces"), &IP::_get_local_interfaces);
diff --git a/core/io/ip.h b/core/io/ip.h
index 0c4a83257d..3c6040a1f0 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -69,7 +69,6 @@ protected:
static IP *singleton;
static void _bind_methods();
- virtual IPAddress _resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY) = 0;
Array _get_local_addresses() const;
Array _get_local_interfaces() const;
@@ -84,11 +83,16 @@ public:
};
IPAddress resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY);
+ Array resolve_hostname_addresses(const String &p_hostname, Type p_type = TYPE_ANY);
// async resolver hostname
ResolverID resolve_hostname_queue_item(const String &p_hostname, Type p_type = TYPE_ANY);
ResolverStatus get_resolve_item_status(ResolverID p_id) const;
IPAddress get_resolve_item_address(ResolverID p_id) const;
virtual void get_local_addresses(List<IPAddress> *r_addresses) const;
+
+ virtual void _resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type = TYPE_ANY) const = 0;
+ Array get_resolve_item_addresses(ResolverID p_id) const;
+
virtual void get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const = 0;
void erase_resolve_item(ResolverID p_id);
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 394cf216e8..82ef2a6894 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -55,7 +55,7 @@ static String _make_indent(const String &p_indent, int p_size) {
return indent_text;
}
-String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys) {
+String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers, bool p_full_precision) {
String colon = ":";
String end_statement = "";
@@ -71,8 +71,17 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
return p_var.operator bool() ? "true" : "false";
case Variant::INT:
return itos(p_var);
- case Variant::FLOAT:
- return rtos(p_var);
+ case Variant::FLOAT: {
+ double num = p_var;
+ if (p_full_precision) {
+ // Store unreliable digits (17) instead of just reliable
+ // digits (14) so that the value can be decoded exactly.
+ return String::num(num, 17 - (int)floor(log10(num)));
+ } else {
+ // Store only reliable digits (14) by default.
+ return String::num(num, 14 - (int)floor(log10(num)));
+ }
+ }
case Variant::PACKED_INT32_ARRAY:
case Variant::PACKED_INT64_ARRAY:
case Variant::PACKED_FLOAT32_ARRAY:
@@ -82,20 +91,29 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
String s = "[";
s += end_statement;
Array a = p_var;
+
+ ERR_FAIL_COND_V_MSG(p_markers.has(a.id()), "\"[...]\"", "Converting circular structure to JSON.");
+ p_markers.insert(a.id());
+
for (int i = 0; i < a.size(); i++) {
if (i > 0) {
s += ",";
s += end_statement;
}
- s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(a[i], p_indent, p_cur_indent + 1, p_sort_keys);
+ s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(a[i], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
}
s += end_statement + _make_indent(p_indent, p_cur_indent) + "]";
+ p_markers.erase(a.id());
return s;
}
case Variant::DICTIONARY: {
String s = "{";
s += end_statement;
Dictionary d = p_var;
+
+ ERR_FAIL_COND_V_MSG(p_markers.has(d.id()), "\"{...}\"", "Converting circular structure to JSON.");
+ p_markers.insert(d.id());
+
List<Variant> keys;
d.get_key_list(&keys);
@@ -108,12 +126,13 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
s += ",";
s += end_statement;
}
- s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(String(E->get()), p_indent, p_cur_indent + 1, p_sort_keys);
+ s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(String(E->get()), p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
s += colon;
- s += _print_var(d[E->get()], p_indent, p_cur_indent + 1, p_sort_keys);
+ s += _print_var(d[E->get()], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
}
s += end_statement + _make_indent(p_indent, p_cur_indent) + "}";
+ p_markers.erase(d.id());
return s;
}
default:
@@ -121,8 +140,9 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
}
}
-String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys) {
- return _print_var(p_var, p_indent, 0, p_sort_keys);
+String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys, bool p_full_precision) {
+ Set<const void *> markers;
+ return _print_var(p_var, p_indent, 0, p_sort_keys, markers, p_full_precision);
}
Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) {
diff --git a/core/io/json.h b/core/io/json.h
index 537477666e..5be8cc1e86 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -31,7 +31,7 @@
#ifndef JSON_H
#define JSON_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/variant/variant.h"
class JSON {
enum TokenType {
@@ -62,7 +62,7 @@ class JSON {
static const char *tk_name[TK_MAX];
- static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys);
+ static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers, bool p_full_precision = false);
static Error _get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
@@ -70,12 +70,12 @@ class JSON {
static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
public:
- static String print(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true);
+ static String print(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true, bool p_full_precision = false);
static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
};
-class JSONParser : public Reference {
- GDCLASS(JSONParser, Reference);
+class JSONParser : public RefCounted {
+ GDCLASS(JSONParser, RefCounted);
Variant data;
String string;
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index 8a07459a1d..09539f716c 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -31,8 +31,9 @@
#include "logger.h"
#include "core/config/project_settings.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/os.h"
+#include "core/os/time.h"
#include "core/string/print_string.h"
#if defined(MINGW_ENABLED) || defined(_MSC_VER)
@@ -156,11 +157,7 @@ void RotatedFileLogger::rotate_file() {
if (FileAccess::exists(base_path)) {
if (max_files > 1) {
- char timestamp[21];
- OS::Date date = OS::get_singleton()->get_date();
- OS::Time time = OS::get_singleton()->get_time();
- sprintf(timestamp, "_%04d-%02d-%02d_%02d.%02d.%02d", date.year, date.month, date.day, time.hour, time.min, time.sec);
-
+ String timestamp = Time::get_singleton()->get_datetime_string_from_system().replace(":", ".");
String backup_name = base_path.get_basename() + timestamp;
if (base_path.get_extension() != String()) {
backup_name += "." + base_path.get_extension();
diff --git a/core/io/logger.h b/core/io/logger.h
index a12945911c..ccf68562d6 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -31,7 +31,7 @@
#ifndef LOGGER_H
#define LOGGER_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/string/ustring.h"
#include "core/templates/vector.h"
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 0282609270..4c58c84c14 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -30,7 +30,7 @@
#include "marshalls.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/keyboard.h"
#include "core/string/print_string.h"
@@ -279,9 +279,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
}
} break;
- case Variant::QUAT: {
+ case Variant::QUATERNION: {
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
- Quat val;
+ Quaternion val;
val.x = decode_float(&buf[0]);
val.y = decode_float(&buf[4]);
val.z = decode_float(&buf[8]);
@@ -325,9 +325,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
}
} break;
- case Variant::TRANSFORM: {
+ case Variant::TRANSFORM3D: {
ERR_FAIL_COND_V(len < 4 * 12, ERR_INVALID_DATA);
- Transform val;
+ Transform3D val;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
val.basis.elements[i][j] = decode_float(&buf[(i * 3 + j) * 4]);
@@ -489,8 +489,8 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
obj->set(str, value);
}
- if (Object::cast_to<Reference>(obj)) {
- REF ref = REF(Object::cast_to<Reference>(obj));
+ if (Object::cast_to<RefCounted>(obj)) {
+ REF ref = REF(Object::cast_to<RefCounted>(obj));
r_variant = ref;
} else {
r_variant = obj;
@@ -889,7 +889,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
// Test for potential wrong values sent by the debugger when it breaks.
Object *obj = p_variant.get_validated_object();
if (!obj) {
- // Object is invalid, send a nullptr instead.
+ // Object is invalid, send a nullptr instead.
if (buf) {
encode_uint32(Variant::NIL, buf);
}
@@ -1099,9 +1099,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4 * 4;
} break;
- case Variant::QUAT: {
+ case Variant::QUATERNION: {
if (buf) {
- Quat q = p_variant;
+ Quaternion q = p_variant;
encode_float(q.x, &buf[0]);
encode_float(q.y, &buf[4]);
encode_float(q.z, &buf[8]);
@@ -1138,9 +1138,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 9 * 4;
} break;
- case Variant::TRANSFORM: {
+ case Variant::TRANSFORM3D: {
if (buf) {
- Transform val = p_variant;
+ Transform3D val = p_variant;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
memcpy(&buf[(i * 3 + j) * 4], &val.basis.elements[i][j], sizeof(float));
diff --git a/core/io/marshalls.h b/core/io/marshalls.h
index cc0e9ba301..7fac708f97 100644
--- a/core/io/marshalls.h
+++ b/core/io/marshalls.h
@@ -31,7 +31,7 @@
#ifndef MARSHALLS_H
#define MARSHALLS_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/typedefs.h"
#include "core/variant/variant.h"
@@ -165,8 +165,8 @@ static inline double decode_double(const uint8_t *p_arr) {
return md.d;
}
-class EncodedObjectAsID : public Reference {
- GDCLASS(EncodedObjectAsID, Reference);
+class EncodedObjectAsID : public RefCounted {
+ GDCLASS(EncodedObjectAsID, RefCounted);
ObjectID id;
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 8414ee7c0c..78ec7ea21a 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -44,6 +44,56 @@
#include "core/os/os.h"
#endif
+String _get_rpc_md5(const Node *p_node) {
+ String rpc_list;
+ const Vector<MultiplayerAPI::RPCConfig> node_config = p_node->get_node_rpc_methods();
+ for (int i = 0; i < node_config.size(); i++) {
+ rpc_list += String(node_config[i].name);
+ }
+ if (p_node->get_script_instance()) {
+ const Vector<MultiplayerAPI::RPCConfig> script_config = p_node->get_script_instance()->get_rpc_methods();
+ for (int i = 0; i < script_config.size(); i++) {
+ rpc_list += String(script_config[i].name);
+ }
+ }
+ return rpc_list.md5_text();
+}
+
+const MultiplayerAPI::RPCConfig _get_rpc_config(const Node *p_node, const StringName &p_method, uint16_t &r_id) {
+ const Vector<MultiplayerAPI::RPCConfig> node_config = p_node->get_node_rpc_methods();
+ for (int i = 0; i < node_config.size(); i++) {
+ if (node_config[i].name == p_method) {
+ r_id = ((uint16_t)i) & (1 << 15);
+ return node_config[i];
+ }
+ }
+ if (p_node->get_script_instance()) {
+ const Vector<MultiplayerAPI::RPCConfig> script_config = p_node->get_script_instance()->get_rpc_methods();
+ for (int i = 0; i < script_config.size(); i++) {
+ if (script_config[i].name == p_method) {
+ r_id = (uint16_t)i;
+ return script_config[i];
+ }
+ }
+ }
+ return MultiplayerAPI::RPCConfig();
+}
+
+const MultiplayerAPI::RPCConfig _get_rpc_config_by_id(Node *p_node, uint16_t p_id) {
+ Vector<MultiplayerAPI::RPCConfig> config;
+ uint16_t id = p_id;
+ if (id & (1 << 15)) {
+ id = id & ~(1 << 15);
+ config = p_node->get_node_rpc_methods();
+ } else {
+ config = p_node->get_script_instance()->get_rpc_methods();
+ }
+ if (id < config.size()) {
+ return config[p_id];
+ }
+ return MultiplayerAPI::RPCConfig();
+}
+
_FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_master, bool &r_skip_rpc) {
switch (mode) {
case MultiplayerAPI::RPC_MODE_DISABLED: {
@@ -231,8 +281,7 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
_process_confirm_path(p_from, p_packet, p_packet_len);
} break;
- case NETWORK_COMMAND_REMOTE_CALL:
- case NETWORK_COMMAND_REMOTE_SET: {
+ case NETWORK_COMMAND_REMOTE_CALL: {
// Extract packet meta
int packet_min_size = 1;
int name_id_offset = 1;
@@ -302,13 +351,7 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
}
const int packet_len = get_packet_len(node_target, p_packet_len);
- if (packet_type == NETWORK_COMMAND_REMOTE_CALL) {
- _process_rpc(node, name_id, p_from, p_packet, packet_len, packet_min_size);
-
- } else {
- _process_rset(node, name_id, p_from, p_packet, packet_len, packet_min_size);
- }
-
+ _process_rpc(node, name_id, p_from, p_packet, packet_len, packet_min_size);
} break;
case NETWORK_COMMAND_RAW: {
@@ -362,16 +405,11 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id,
ERR_FAIL_COND_MSG(p_offset > p_packet_len, "Invalid packet received. Size too small.");
// Check that remote can call the RPC on this node.
- StringName name = p_node->get_node_rpc_method(p_rpc_method_id);
- RPCMode rpc_mode = p_node->get_node_rpc_mode_by_id(p_rpc_method_id);
- if (name == StringName() && p_node->get_script_instance()) {
- name = p_node->get_script_instance()->get_rpc_method(p_rpc_method_id);
- rpc_mode = p_node->get_script_instance()->get_rpc_mode_by_id(p_rpc_method_id);
- }
- ERR_FAIL_COND(name == StringName());
+ const RPCConfig config = _get_rpc_config_by_id(p_node, p_rpc_method_id);
+ ERR_FAIL_COND(config.name == StringName());
- bool can_call = _can_call_mode(p_node, rpc_mode, p_from);
- ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
+ bool can_call = _can_call_mode(p_node, config.rpc_mode, p_from);
+ ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(config.name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)config.rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
int argc = 0;
bool byte_only = false;
@@ -424,47 +462,14 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id,
Callable::CallError ce;
- p_node->call(name, (const Variant **)argp.ptr(), argc, ce);
+ p_node->call(config.name, (const Variant **)argp.ptr(), argc, ce);
if (ce.error != Callable::CallError::CALL_OK) {
- String error = Variant::get_call_error_text(p_node, name, (const Variant **)argp.ptr(), argc, ce);
+ String error = Variant::get_call_error_text(p_node, config.name, (const Variant **)argp.ptr(), argc, ce);
error = "RPC - " + error;
ERR_PRINT(error);
}
}
-void MultiplayerAPI::_process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
- ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small.");
-
- // Check that remote can call the RSET on this node.
- StringName name = p_node->get_node_rset_property(p_rpc_property_id);
- RPCMode rset_mode = p_node->get_node_rset_mode_by_id(p_rpc_property_id);
- if (name == StringName() && p_node->get_script_instance()) {
- name = p_node->get_script_instance()->get_rset_property(p_rpc_property_id);
- rset_mode = p_node->get_script_instance()->get_rset_mode_by_id(p_rpc_property_id);
- }
- ERR_FAIL_COND(name == StringName());
-
- bool can_call = _can_call_mode(p_node, rset_mode, p_from);
- ERR_FAIL_COND_MSG(!can_call, "RSET '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
-
-#ifdef DEBUG_ENABLED
- _profile_node_data("in_rset", p_node->get_instance_id());
-#endif
-
- Variant value;
- Error err = _decode_and_decompress_variant(value, &p_packet[p_offset], p_packet_len - p_offset, nullptr);
-
- ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RSET value.");
-
- bool valid;
-
- p_node->set(name, value, &valid);
- if (!valid) {
- String error = "Error setting remote property '" + String(name) + "', not found in object of type " + p_node->get_class() + ".";
- ERR_PRINT(error);
- }
-}
-
void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_FAIL_COND_MSG(p_packet_len < 38, "Invalid packet received. Size too small.");
int ofs = 1;
@@ -487,7 +492,7 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
Node *node = root_node->get_node(path);
ERR_FAIL_COND(node == nullptr);
- const bool valid_rpc_checksum = node->get_rpc_md5() == methods_md5;
+ const bool valid_rpc_checksum = _get_rpc_md5(node) == methods_md5;
if (valid_rpc_checksum == false) {
ERR_PRINT("The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path);
}
@@ -569,7 +574,7 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC
const int path_len = encode_cstring(path.get_data(), nullptr);
// Extract MD5 from rpc methods list.
- const String methods_md5 = p_node->get_rpc_md5();
+ const String methods_md5 = _get_rpc_md5(p_node);
const int methods_md5_len = 33; // 32 + 1 for the `0` that is added by the encoder.
Vector<uint8_t> packet;
@@ -752,7 +757,7 @@ Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const u
return OK;
}
-void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) {
+void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
ERR_FAIL_COND_MSG(network_peer.is_null(), "Attempt to remote call/set when networking is not active in SceneTree.");
ERR_FAIL_COND_MSG(network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING, "Attempt to remote call/set when networking is not connected yet in SceneTree.");
@@ -797,7 +802,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
// - `NetworkNameIdCompression` in the next 1 bit.
// - `byte_only_or_no_args` in the next 1 bit.
// - So we still have the last bit free!
- uint8_t command_type = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL;
+ uint8_t command_type = NETWORK_COMMAND_REMOTE_CALL;
uint8_t node_id_compression = UINT8_MAX;
uint8_t name_id_compression = UINT8_MAX;
bool byte_only_or_no_args = false;
@@ -837,81 +842,42 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
ofs += 4;
}
- if (p_set) {
- // Take the rpc property ID
- uint16_t property_id = p_from->get_node_rset_property_id(p_name);
- if (property_id == UINT16_MAX && p_from->get_script_instance()) {
- property_id = p_from->get_script_instance()->get_rset_property_id(p_name);
- }
- ERR_FAIL_COND_MSG(property_id == UINT16_MAX, "Unable to take the `property_id` for the property:" + p_name + ". this can happen only if this property is not marked as `remote`.");
-
- if (property_id <= UINT8_MAX) {
- // The ID fits in 1 byte
- name_id_compression = NETWORK_NAME_ID_COMPRESSION_8;
- MAKE_ROOM(ofs + 1);
- packet_cache.write[ofs] = static_cast<uint8_t>(property_id);
- ofs += 1;
- } else {
- // The ID is larger, let's use 2 bytes
- name_id_compression = NETWORK_NAME_ID_COMPRESSION_16;
- MAKE_ROOM(ofs + 2);
- encode_uint16(property_id, &(packet_cache.write[ofs]));
- ofs += 2;
- }
-
- // Set argument.
- int len(0);
- Error err = _encode_and_compress_variant(*p_arg[0], nullptr, len);
- ERR_FAIL_COND_MSG(err != OK, "Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!");
- MAKE_ROOM(ofs + len);
- _encode_and_compress_variant(*p_arg[0], &(packet_cache.write[ofs]), len);
- ofs += len;
-
+ // Encode method ID
+ if (p_rpc_id <= UINT8_MAX) {
+ // The ID fits in 1 byte
+ name_id_compression = NETWORK_NAME_ID_COMPRESSION_8;
+ MAKE_ROOM(ofs + 1);
+ packet_cache.write[ofs] = static_cast<uint8_t>(p_rpc_id);
+ ofs += 1;
} else {
- // Take the rpc method ID
- uint16_t method_id = p_from->get_node_rpc_method_id(p_name);
- if (method_id == UINT16_MAX && p_from->get_script_instance()) {
- method_id = p_from->get_script_instance()->get_rpc_method_id(p_name);
- }
- ERR_FAIL_COND_MSG(method_id == UINT16_MAX,
- vformat("Unable to take the `method_id` for the function \"%s\" at path: \"%s\". This happens when the method is not marked as `remote`.", p_name, p_from->get_path()));
-
- if (method_id <= UINT8_MAX) {
- // The ID fits in 1 byte
- name_id_compression = NETWORK_NAME_ID_COMPRESSION_8;
- MAKE_ROOM(ofs + 1);
- packet_cache.write[ofs] = static_cast<uint8_t>(method_id);
- ofs += 1;
- } else {
- // The ID is larger, let's use 2 bytes
- name_id_compression = NETWORK_NAME_ID_COMPRESSION_16;
- MAKE_ROOM(ofs + 2);
- encode_uint16(method_id, &(packet_cache.write[ofs]));
- ofs += 2;
- }
+ // The ID is larger, let's use 2 bytes
+ name_id_compression = NETWORK_NAME_ID_COMPRESSION_16;
+ MAKE_ROOM(ofs + 2);
+ encode_uint16(p_rpc_id, &(packet_cache.write[ofs]));
+ ofs += 2;
+ }
- if (p_argcount == 0) {
- byte_only_or_no_args = true;
- } else if (p_argcount == 1 && p_arg[0]->get_type() == Variant::PACKED_BYTE_ARRAY) {
- byte_only_or_no_args = true;
- // Special optimization when only the byte vector is sent.
- const Vector<uint8_t> data = *p_arg[0];
- MAKE_ROOM(ofs + data.size());
- memcpy(&(packet_cache.write[ofs]), data.ptr(), sizeof(uint8_t) * data.size());
- ofs += data.size();
- } else {
- // Arguments
- MAKE_ROOM(ofs + 1);
- packet_cache.write[ofs] = p_argcount;
- ofs += 1;
- for (int i = 0; i < p_argcount; i++) {
- int len(0);
- Error err = _encode_and_compress_variant(*p_arg[i], nullptr, len);
- ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
- MAKE_ROOM(ofs + len);
- _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len);
- ofs += len;
- }
+ if (p_argcount == 0) {
+ byte_only_or_no_args = true;
+ } else if (p_argcount == 1 && p_arg[0]->get_type() == Variant::PACKED_BYTE_ARRAY) {
+ byte_only_or_no_args = true;
+ // Special optimization when only the byte vector is sent.
+ const Vector<uint8_t> data = *p_arg[0];
+ MAKE_ROOM(ofs + data.size());
+ memcpy(&(packet_cache.write[ofs]), data.ptr(), sizeof(uint8_t) * data.size());
+ ofs += data.size();
+ } else {
+ // Arguments
+ MAKE_ROOM(ofs + 1);
+ packet_cache.write[ofs] = p_argcount;
+ ofs += 1;
+ for (int i = 0; i < p_argcount; i++) {
+ int len(0);
+ Error err = _encode_and_compress_variant(*p_arg[i], nullptr, len);
+ ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
+ MAKE_ROOM(ofs + len);
+ _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len);
+ ofs += len;
}
}
@@ -927,7 +893,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
#endif
// Take chance and set transfer mode, since all send methods will use it.
- network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
+ network_peer->set_transfer_mode(p_config.transfer_mode);
if (has_all_peers) {
// They all have verified paths, so send fast.
@@ -1015,19 +981,15 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
bool call_local_native = false;
bool call_local_script = false;
bool is_master = p_node->is_network_master();
-
+ uint16_t rpc_id = UINT16_MAX;
+ const RPCConfig config = _get_rpc_config(p_node, p_method, rpc_id);
+ ERR_FAIL_COND_MSG(config.name == StringName(),
+ vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is not marked for RPCs.", p_method, p_node->get_path()));
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
- // Check that send mode can use local call.
-
- RPCMode rpc_mode = p_node->get_node_rpc_mode(p_method);
- call_local_native = _should_call_local(rpc_mode, is_master, skip_rpc);
-
- if (call_local_native) {
- // Done below.
- } else if (p_node->get_script_instance()) {
- // Attempt with script.
- rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method);
- call_local_script = _should_call_local(rpc_mode, is_master, skip_rpc);
+ if (rpc_id & (1 << 15)) {
+ call_local_native = _should_call_local(config.rpc_mode, is_master, skip_rpc);
+ } else {
+ call_local_script = _should_call_local(config.rpc_mode, is_master, skip_rpc);
}
}
@@ -1036,7 +998,7 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
_profile_node_data("out_rpc", p_node->get_instance_id());
#endif
- _send_rpc(p_node, p_peer_id, p_unreliable, false, p_method, p_arg, p_argcount);
+ _send_rpc(p_node, p_peer_id, rpc_id, config, p_method, p_arg, p_argcount);
}
if (call_local_native) {
@@ -1071,70 +1033,6 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
ERR_FAIL_COND_MSG(skip_rpc && !(call_local_native || call_local_script), "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
}
-void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
- ERR_FAIL_COND_MSG(!network_peer.is_valid(), "Trying to RSET while no network peer is active.");
- ERR_FAIL_COND_MSG(!p_node->is_inside_tree(), "Trying to RSET on a node which is not inside SceneTree.");
- ERR_FAIL_COND_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, "Trying to send an RSET via a network peer which is not connected.");
-
- int node_id = network_peer->get_unique_id();
- bool is_master = p_node->is_network_master();
- bool skip_rset = node_id == p_peer_id;
- bool set_local = false;
-
- if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
- // Check that send mode can use local call.
- RPCMode rpc_mode = p_node->get_node_rset_mode(p_property);
- set_local = _should_call_local(rpc_mode, is_master, skip_rset);
-
- if (set_local) {
- bool valid;
- int temp_id = rpc_sender_id;
-
- rpc_sender_id = get_network_unique_id();
- p_node->set(p_property, p_value, &valid);
- rpc_sender_id = temp_id;
-
- if (!valid) {
- String error = "rset() aborted in local set, property not found: - " + String(p_property) + ".";
- ERR_PRINT(error);
- return;
- }
- } else if (p_node->get_script_instance()) {
- // Attempt with script.
- rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property);
-
- set_local = _should_call_local(rpc_mode, is_master, skip_rset);
-
- if (set_local) {
- int temp_id = rpc_sender_id;
-
- rpc_sender_id = get_network_unique_id();
- bool valid = p_node->get_script_instance()->set(p_property, p_value);
- rpc_sender_id = temp_id;
-
- if (!valid) {
- String error = "rset() aborted in local script set, property not found: - " + String(p_property) + ".";
- ERR_PRINT(error);
- return;
- }
- }
- }
- }
-
- if (skip_rset) {
- ERR_FAIL_COND_MSG(!set_local, "RSET for '" + p_property + "' on yourself is not allowed by selected mode.");
- return;
- }
-
-#ifdef DEBUG_ENABLED
- _profile_node_data("out_rset", p_node->get_instance_id());
-#endif
-
- const Variant *vptr = &p_value;
-
- _send_rpc(p_node, p_peer_id, p_unreliable, true, p_property, &vptr, 1);
-}
-
Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) {
ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet.");
ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no network peer is active.");
diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h
index 7f88b53a27..43804a20ec 100644
--- a/core/io/multiplayer_api.h
+++ b/core/io/multiplayer_api.h
@@ -32,10 +32,39 @@
#define MULTIPLAYER_API_H
#include "core/io/networked_multiplayer_peer.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class MultiplayerAPI : public Reference {
- GDCLASS(MultiplayerAPI, Reference);
+class MultiplayerAPI : public RefCounted {
+ GDCLASS(MultiplayerAPI, RefCounted);
+
+public:
+ enum RPCMode {
+ RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
+ RPC_MODE_REMOTE, // Using rpc() on it will call method in all remote peers
+ RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote
+ RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
+ RPC_MODE_REMOTESYNC, // Using rpc() on it will call method in all remote peers and locally
+ RPC_MODE_MASTERSYNC, // Using rpc() on it will call method in the master peer and locally
+ RPC_MODE_PUPPETSYNC, // Using rpc() on it will call method in all puppets peers and locally
+ };
+
+ struct RPCConfig {
+ StringName name;
+ RPCMode rpc_mode = RPC_MODE_DISABLED;
+ NetworkedMultiplayerPeer::TransferMode transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ int channel = 0;
+
+ bool operator==(RPCConfig const &p_other) const {
+ return name == p_other.name;
+ }
+ };
+
+ struct SortRPCConfig {
+ StringName::AlphCompare compare;
+ bool operator()(const RPCConfig &p_a, const RPCConfig &p_b) const {
+ return compare(p_a.name, p_b.name);
+ }
+ };
private:
//path sent caches
@@ -72,10 +101,9 @@ protected:
void _process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len);
Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len);
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
- void _process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
- void _send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount);
+ void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
bool _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target);
Error _encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len);
@@ -84,7 +112,6 @@ protected:
public:
enum NetworkCommands {
NETWORK_COMMAND_REMOTE_CALL = 0,
- NETWORK_COMMAND_REMOTE_SET,
NETWORK_COMMAND_SIMPLIFY_PATH,
NETWORK_COMMAND_CONFIRM_PATH,
NETWORK_COMMAND_RAW,
@@ -101,16 +128,6 @@ public:
NETWORK_NAME_ID_COMPRESSION_16,
};
- enum RPCMode {
- RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
- RPC_MODE_REMOTE, // Using rpc() on it will call method / set property in all remote peers
- RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote
- RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
- RPC_MODE_REMOTESYNC, // Using rpc() on it will call method / set property in all remote peers and locally
- RPC_MODE_MASTERSYNC, // Using rpc() on it will call method / set property in the master peer and locally
- RPC_MODE_PUPPETSYNC, // Using rpc() on it will call method / set property in all puppets peers and locally
- };
-
void poll();
void clear();
void set_root_node(Node *p_node);
@@ -121,8 +138,6 @@ public:
// Called by Node.rpc
void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);
- // Called by Node.rset
- void rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value);
void _add_peer(int p_id);
void _del_peer(int p_id);
diff --git a/core/io/net_socket.h b/core/io/net_socket.h
index 98ff9562d9..fd7d50c704 100644
--- a/core/io/net_socket.h
+++ b/core/io/net_socket.h
@@ -32,9 +32,9 @@
#define NET_SOCKET_H
#include "core/io/ip.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class NetSocket : public Reference {
+class NetSocket : public RefCounted {
protected:
static NetSocket *(*_create)();
diff --git a/core/io/packed_data_container.cpp b/core/io/packed_data_container.cpp
index 52169987fd..cf6a0b6027 100644
--- a/core/io/packed_data_container.cpp
+++ b/core/io/packed_data_container.cpp
@@ -227,10 +227,10 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
case Variant::VECTOR3:
case Variant::TRANSFORM2D:
case Variant::PLANE:
- case Variant::QUAT:
+ case Variant::QUATERNION:
case Variant::AABB:
case Variant::BASIS:
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
case Variant::PACKED_BYTE_ARRAY:
case Variant::PACKED_INT32_ARRAY:
case Variant::PACKED_INT64_ARRAY:
diff --git a/core/io/packed_data_container.h b/core/io/packed_data_container.h
index 7791e21bb3..40772bb2bf 100644
--- a/core/io/packed_data_container.h
+++ b/core/io/packed_data_container.h
@@ -80,8 +80,8 @@ public:
PackedDataContainer() {}
};
-class PackedDataContainerRef : public Reference {
- GDCLASS(PackedDataContainerRef, Reference);
+class PackedDataContainerRef : public RefCounted {
+ GDCLASS(PackedDataContainerRef, RefCounted);
friend class PackedDataContainer;
uint32_t offset = 0;
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index 9e03c44750..9a345af3d0 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -35,8 +35,8 @@
#include "core/object/class_db.h"
#include "core/templates/ring_buffer.h"
-class PacketPeer : public Reference {
- GDCLASS(PacketPeer, Reference);
+class PacketPeer : public RefCounted {
+ GDCLASS(PacketPeer, RefCounted);
Variant _bnd_get_var(bool p_allow_objects = false);
diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp
index bac98e20e7..a6d220622b 100644
--- a/core/io/packet_peer_dtls.cpp
+++ b/core/io/packet_peer_dtls.cpp
@@ -30,7 +30,7 @@
#include "packet_peer_dtls.h"
#include "core/config/project_settings.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
PacketPeerDTLS *(*PacketPeerDTLS::_create)() = nullptr;
bool PacketPeerDTLS::available = false;
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index a0697ca18b..806a95398f 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -31,9 +31,9 @@
#include "pck_packer.h"
#include "core/crypto/crypto_core.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_encrypted.h"
#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
-#include "core/os/file_access.h"
#include "core/version.h"
static int _get_pad(int p_alignment, int p_n) {
@@ -120,7 +120,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr
pf.path = p_file;
pf.src_path = p_src;
pf.ofs = ofs;
- pf.size = f->get_len();
+ pf.size = f->get_length();
Vector<uint8_t> data = FileAccess::get_file_as_array(p_src);
{
@@ -236,7 +236,7 @@ Error PCKPacker::flush(bool p_verbose) {
}
while (to_write > 0) {
- int read = src->get_buffer(buf, MIN(to_write, buf_max));
+ uint64_t read = src->get_buffer(buf, MIN(to_write, buf_max));
ftmp->store_buffer(buf, read);
to_write -= read;
}
diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h
index dec8f8748d..3d2ce8f240 100644
--- a/core/io/pck_packer.h
+++ b/core/io/pck_packer.h
@@ -31,12 +31,12 @@
#ifndef PCK_PACKER_H
#define PCK_PACKER_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
class FileAccess;
-class PCKPacker : public Reference {
- GDCLASS(PCKPacker, Reference);
+class PCKPacker : public RefCounted {
+ GDCLASS(PCKPacker, RefCounted);
FileAccess *file = nullptr;
int alignment = 0;
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index d46e9edafa..b970e85c99 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -31,9 +31,9 @@
#include "resource.h"
#include "core/core_string_names.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/object/script_language.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "scene/main/node.h" //only so casting works
diff --git a/core/io/resource.h b/core/io/resource.h
index 75a9f928f8..028fed1c6e 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -32,7 +32,7 @@
#define RESOURCE_H
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/templates/safe_refcount.h"
#include "core/templates/self_list.h"
@@ -43,8 +43,8 @@ public:
\
private:
-class Resource : public Reference {
- GDCLASS(Resource, Reference);
+class Resource : public RefCounted {
+ GDCLASS(Resource, RefCounted);
OBJ_CATEGORY("Resources");
public:
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index c4eb2a20bb..f83ba30514 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -31,10 +31,10 @@
#include "resource_format_binary.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
#include "core/io/file_access_compressed.h"
#include "core/io/image.h"
#include "core/io/marshalls.h"
-#include "core/os/dir_access.h"
#include "core/version.h"
//#define print_bl(m_what) print_line(m_what)
@@ -51,7 +51,7 @@ enum {
VARIANT_RECT2 = 11,
VARIANT_VECTOR3 = 12,
VARIANT_PLANE = 13,
- VARIANT_QUAT = 14,
+ VARIANT_QUATERNION = 14,
VARIANT_AABB = 15,
VARIANT_MATRIX3 = 16,
VARIANT_TRANSFORM = 17,
@@ -199,8 +199,8 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
v.d = f->get_real();
r_v = v;
} break;
- case VARIANT_QUAT: {
- Quat v;
+ case VARIANT_QUATERNION: {
+ Quaternion v;
v.x = f->get_real();
v.y = f->get_real();
v.z = f->get_real();
@@ -245,7 +245,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
} break;
case VARIANT_TRANSFORM: {
- Transform v;
+ Transform3D v;
v.basis.elements[0].x = f->get_real();
v.basis.elements[0].y = f->get_real();
v.basis.elements[0].z = f->get_real();
@@ -851,7 +851,7 @@ void ResourceLoaderBinary::open(FileAccess *p_f) {
bool big_endian = f->get_32();
bool use_real64 = f->get_32();
- f->set_endian_swap(big_endian != 0); //read big endian if saved as big endian
+ f->set_big_endian(big_endian != 0); //read big endian if saved as big endian
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
@@ -948,7 +948,7 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
bool big_endian = f->get_32();
f->get_32(); // use_real64
- f->set_endian_swap(big_endian != 0); //read big endian if saved as big endian
+ f->set_big_endian(big_endian != 0); //read big endian if saved as big endian
uint32_t ver_major = f->get_32();
f->get_32(); // ver_minor
@@ -1097,13 +1097,13 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
bool big_endian = f->get_32();
bool use_real64 = f->get_32();
- f->set_endian_swap(big_endian != 0); //read big endian if saved as big endian
+ f->set_big_endian(big_endian != 0); //read big endian if saved as big endian
#ifdef BIG_ENDIAN_ENABLED
fw->store_32(!big_endian);
#else
fw->store_32(big_endian);
#endif
- fw->set_endian_swap(big_endian != 0);
+ fw->set_big_endian(big_endian != 0);
fw->store_32(use_real64); //use real64
uint32_t ver_major = f->get_32();
@@ -1157,8 +1157,8 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
save_ustring(fw, get_ustring(f)); //type
- size_t md_ofs = f->get_position();
- size_t importmd_ofs = f->get_64();
+ uint64_t md_ofs = f->get_position();
+ uint64_t importmd_ofs = f->get_64();
fw->store_64(0); //metadata offset
for (int i = 0; i < 14; i++) {
@@ -1371,9 +1371,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
f->store_real(val.d);
} break;
- case Variant::QUAT: {
- f->store_32(VARIANT_QUAT);
- Quat val = p_property;
+ case Variant::QUATERNION: {
+ f->store_32(VARIANT_QUATERNION);
+ Quaternion val = p_property;
f->store_real(val.x);
f->store_real(val.y);
f->store_real(val.z);
@@ -1416,9 +1416,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
f->store_real(val.elements[2].z);
} break;
- case Variant::TRANSFORM: {
+ case Variant::TRANSFORM3D: {
f->store_32(VARIANT_TRANSFORM);
- Transform val = p_property;
+ Transform3D val = p_property;
f->store_real(val.basis.elements[0].x);
f->store_real(val.basis.elements[0].y);
f->store_real(val.basis.elements[0].z);
@@ -1798,7 +1798,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
if (big_endian) {
f->store_32(1);
- f->set_endian_swap(true);
+ f->set_big_endian(true);
} else {
f->store_32(0);
}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 3592bbdbc4..abc7403935 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -31,9 +31,9 @@
#ifndef RESOURCE_FORMAT_BINARY_H
#define RESOURCE_FORMAT_BINARY_H
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
class ResourceLoaderBinary {
bool translation_remapped = false;
diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h
index a14d6ba52c..2ceeb176e5 100644
--- a/core/io/resource_importer.h
+++ b/core/io/resource_importer.h
@@ -93,8 +93,8 @@ public:
ResourceFormatImporter();
};
-class ResourceImporter : public Reference {
- GDCLASS(ResourceImporter, Reference);
+class ResourceImporter : public RefCounted {
+ GDCLASS(ResourceImporter, RefCounted);
public:
virtual String get_importer_name() const = 0;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 040e55b9db..1700766cbf 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -31,8 +31,8 @@
#include "resource_loader.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/resource_importer.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "core/string/translation.h"
@@ -68,17 +68,17 @@ bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_
}
bool ResourceFormatLoader::handles_type(const String &p_type) const {
- if (get_script_instance() && get_script_instance()->has_method("handles_type")) {
+ if (get_script_instance() && get_script_instance()->has_method("_handles_type")) {
// I guess custom loaders for custom resources should use "Resource"
- return get_script_instance()->call("handles_type", p_type);
+ return get_script_instance()->call("_handles_type", p_type);
}
return false;
}
String ResourceFormatLoader::get_resource_type(const String &p_path) const {
- if (get_script_instance() && get_script_instance()->has_method("get_resource_type")) {
- return get_script_instance()->call("get_resource_type", p_path);
+ if (get_script_instance() && get_script_instance()->has_method("_get_resource_type")) {
+ return get_script_instance()->call("_get_resource_type", p_path);
}
return "";
@@ -101,8 +101,8 @@ bool ResourceFormatLoader::exists(const String &p_path) const {
}
void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) const {
- if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) {
- PackedStringArray exts = get_script_instance()->call("get_recognized_extensions");
+ if (get_script_instance() && get_script_instance()->has_method("_get_recognized_extensions")) {
+ PackedStringArray exts = get_script_instance()->call("_get_recognized_extensions");
{
const String *r = exts.ptr();
@@ -115,8 +115,8 @@ void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions)
RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
// Check user-defined loader if there's any. Hard fail if it returns an error.
- if (get_script_instance() && get_script_instance()->has_method("load")) {
- Variant res = get_script_instance()->call("load", p_path, p_original_path, p_use_sub_threads, p_cache_mode);
+ if (get_script_instance() && get_script_instance()->has_method("_load")) {
+ Variant res = get_script_instance()->call("_load", p_path, p_original_path, p_use_sub_threads, p_cache_mode);
if (res.get_type() == Variant::INT) { // Error code, abort.
if (r_error) {
@@ -135,8 +135,8 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa
}
void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
- if (get_script_instance() && get_script_instance()->has_method("get_dependencies")) {
- PackedStringArray deps = get_script_instance()->call("get_dependencies", p_path, p_add_types);
+ if (get_script_instance() && get_script_instance()->has_method("_get_dependencies")) {
+ PackedStringArray deps = get_script_instance()->call("_get_dependencies", p_path, p_add_types);
{
const String *r = deps.ptr();
@@ -148,13 +148,13 @@ void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *
}
Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
- if (get_script_instance() && get_script_instance()->has_method("rename_dependencies")) {
+ if (get_script_instance() && get_script_instance()->has_method("_rename_dependencies")) {
Dictionary deps_dict;
for (Map<String, String>::Element *E = p_map.front(); E; E = E->next()) {
deps_dict[E->key()] = E->value();
}
- int64_t res = get_script_instance()->call("rename_dependencies", deps_dict);
+ int64_t res = get_script_instance()->call("_rename_dependencies", deps_dict);
return (Error)res;
}
@@ -163,16 +163,16 @@ Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<
void ResourceFormatLoader::_bind_methods() {
{
- MethodInfo info = MethodInfo(Variant::NIL, "load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path"), PropertyInfo(Variant::BOOL, "use_sub_threads"), PropertyInfo(Variant::INT, "cache_mode"));
+ MethodInfo info = MethodInfo(Variant::NIL, "_load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path"), PropertyInfo(Variant::BOOL, "use_sub_threads"), PropertyInfo(Variant::INT, "cache_mode"));
info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- ClassDB::add_virtual_method(get_class_static(), info);
+ BIND_VMETHOD(info);
}
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::PACKED_STRING_ARRAY, "get_recognized_extensions"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles_type", PropertyInfo(Variant::STRING_NAME, "typename")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type", PropertyInfo(Variant::STRING, "path")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "add_types")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "rename_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "renames")));
+ BIND_VMETHOD(MethodInfo(Variant::PACKED_STRING_ARRAY, "_get_recognized_extensions"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_handles_type", PropertyInfo(Variant::STRING_NAME, "typename")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_resource_type", PropertyInfo(Variant::STRING, "path")));
+ BIND_VMETHOD(MethodInfo("_get_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "add_types")));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_rename_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "renames")));
BIND_ENUM_CONSTANT(CACHE_MODE_IGNORE);
BIND_ENUM_CONSTANT(CACHE_MODE_REUSE);
@@ -354,7 +354,7 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
ThreadLoadTask &load_task = thread_load_tasks[local_path];
- if (load_task.resource.is_null()) { //needs to be loaded in thread
+ if (load_task.resource.is_null()) { //needs to be loaded in thread
load_task.semaphore = memnew(Semaphore);
if (thread_loading_count < thread_load_max) {
@@ -867,7 +867,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
continue;
}
- String l = res_remaps[i].right(split + 1).strip_edges();
+ String l = res_remaps[i].substr(split + 1).strip_edges();
if (l == locale) { // Exact match.
new_path = res_remaps[i].left(split);
break;
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 914d988caa..c656b9a69c 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -35,8 +35,8 @@
#include "core/os/semaphore.h"
#include "core/os/thread.h"
-class ResourceFormatLoader : public Reference {
- GDCLASS(ResourceFormatLoader, Reference);
+class ResourceFormatLoader : public RefCounted {
+ GDCLASS(ResourceFormatLoader, RefCounted);
public:
enum CacheMode {
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index 7ebc7f34b3..389a4fdbbd 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -30,9 +30,9 @@
#include "resource_saver.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/object/script_language.h"
-#include "core/os/file_access.h"
Ref<ResourceFormatSaver> ResourceSaver::saver[MAX_SAVERS];
@@ -41,24 +41,24 @@ bool ResourceSaver::timestamp_on_save = false;
ResourceSavedCallback ResourceSaver::save_callback = nullptr;
Error ResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
- if (get_script_instance() && get_script_instance()->has_method("save")) {
- return (Error)get_script_instance()->call("save", p_path, p_resource, p_flags).operator int64_t();
+ if (get_script_instance() && get_script_instance()->has_method("_save")) {
+ return (Error)get_script_instance()->call("_save", p_path, p_resource, p_flags).operator int64_t();
}
return ERR_METHOD_NOT_FOUND;
}
bool ResourceFormatSaver::recognize(const RES &p_resource) const {
- if (get_script_instance() && get_script_instance()->has_method("recognize")) {
- return get_script_instance()->call("recognize", p_resource);
+ if (get_script_instance() && get_script_instance()->has_method("_recognize")) {
+ return get_script_instance()->call("_recognize", p_resource);
}
return false;
}
void ResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
- if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) {
- PackedStringArray exts = get_script_instance()->call("get_recognized_extensions", p_resource);
+ if (get_script_instance() && get_script_instance()->has_method("_get_recognized_extensions")) {
+ PackedStringArray exts = get_script_instance()->call("_get_recognized_extensions", p_resource);
{
const String *r = exts.ptr();
@@ -74,11 +74,11 @@ void ResourceFormatSaver::_bind_methods() {
PropertyInfo arg0 = PropertyInfo(Variant::STRING, "path");
PropertyInfo arg1 = PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource");
PropertyInfo arg2 = PropertyInfo(Variant::INT, "flags");
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "save", arg0, arg1, arg2));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_save", arg0, arg1, arg2));
}
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::PACKED_STRING_ARRAY, "get_recognized_extensions", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "recognize", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
+ BIND_VMETHOD(MethodInfo(Variant::PACKED_STRING_ARRAY, "_get_recognized_extensions", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_recognize", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
}
Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 2c9e8f1aa3..07154aac4d 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -33,8 +33,8 @@
#include "core/io/resource.h"
-class ResourceFormatSaver : public Reference {
- GDCLASS(ResourceFormatSaver, Reference);
+class ResourceFormatSaver : public RefCounted {
+ GDCLASS(ResourceFormatSaver, RefCounted);
protected:
static void _bind_methods();
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index 74154321b3..ee5e9eca0c 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -108,8 +108,8 @@ Array StreamPeer::_get_partial_data(int p_bytes) {
return ret;
}
-void StreamPeer::set_big_endian(bool p_enable) {
- big_endian = p_enable;
+void StreamPeer::set_big_endian(bool p_big_endian) {
+ big_endian = p_big_endian;
}
bool StreamPeer::is_big_endian_enabled() const {
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index dadedbd2dc..effc3850af 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -31,10 +31,10 @@
#ifndef STREAM_PEER_H
#define STREAM_PEER_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class StreamPeer : public Reference {
- GDCLASS(StreamPeer, Reference);
+class StreamPeer : public RefCounted {
+ GDCLASS(StreamPeer, RefCounted);
OBJ_CATEGORY("Networking");
protected:
@@ -58,7 +58,7 @@ public:
virtual int get_available_bytes() const = 0;
- void set_big_endian(bool p_enable);
+ void set_big_endian(bool p_big_endian);
bool is_big_endian_enabled() const;
void put_8(int8_t p_val);
diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h
index abefa53c6f..10985a04d5 100644
--- a/core/io/tcp_server.h
+++ b/core/io/tcp_server.h
@@ -36,8 +36,8 @@
#include "core/io/stream_peer.h"
#include "core/io/stream_peer_tcp.h"
-class TCPServer : public Reference {
- GDCLASS(TCPServer, Reference);
+class TCPServer : public RefCounted {
+ GDCLASS(TCPServer, RefCounted);
protected:
enum {
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 9adf912224..83d575cee8 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -30,7 +30,7 @@
#include "translation_loader_po.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/string/translation.h"
#include "core/string/translation_po.h"
diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h
index 36d33fcac3..c52820e60d 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -31,8 +31,8 @@
#ifndef TRANSLATION_LOADER_PO_H
#define TRANSLATION_LOADER_PO_H
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
-#include "core/os/file_access.h"
#include "core/string/translation.h"
class TranslationLoaderPO : public ResourceFormatLoader {
diff --git a/core/io/udp_server.h b/core/io/udp_server.h
index 60d03f37f0..e49a559c51 100644
--- a/core/io/udp_server.h
+++ b/core/io/udp_server.h
@@ -34,8 +34,8 @@
#include "core/io/net_socket.h"
#include "core/io/packet_peer_udp.h"
-class UDPServer : public Reference {
- GDCLASS(UDPServer, Reference);
+class UDPServer : public RefCounted {
+ GDCLASS(UDPServer, RefCounted);
protected:
enum {
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index a1f8e79adc..938d93a01b 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -75,7 +75,7 @@ void XMLParser::_parse_closing_xml_element() {
++P;
const char *pBeginClose = P;
- while (*P != '>') {
+ while (*P && *P != '>') {
++P;
}
@@ -83,7 +83,10 @@ void XMLParser::_parse_closing_xml_element() {
#ifdef DEBUG_XML
print_line("XML CLOSE: " + node_name);
#endif
- ++P;
+
+ if (*P) {
+ ++P;
+ }
}
void XMLParser::_ignore_definition() {
@@ -91,11 +94,14 @@ void XMLParser::_ignore_definition() {
char *F = P;
// move until end marked with '>' reached
- while (*P != '>') {
+ while (*P && *P != '>') {
++P;
}
node_name.parse_utf8(F, P - F);
- ++P;
+
+ if (*P) {
+ ++P;
+ }
}
bool XMLParser::_parse_cdata() {
@@ -113,6 +119,7 @@ bool XMLParser::_parse_cdata() {
}
if (!*P) {
+ node_name = "";
return true;
}
@@ -131,10 +138,9 @@ bool XMLParser::_parse_cdata() {
}
if (cDataEnd) {
- node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin));
- } else {
- node_name = "";
+ cDataEnd = P;
}
+ node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin));
#ifdef DEBUG_XML
print_line("XML CDATA: " + node_name);
#endif
@@ -146,24 +152,45 @@ void XMLParser::_parse_comment() {
node_type = NODE_COMMENT;
P += 1;
- char *pCommentBegin = P;
+ char *pEndOfInput = data + length;
+ char *pCommentBegin;
+ char *pCommentEnd;
- int count = 1;
-
- // move until end of comment reached
- while (count) {
- if (*P == '>') {
- --count;
- } else if (*P == '<') {
- ++count;
+ if (P + 1 < pEndOfInput && P[0] == '-' && P[1] == '-') {
+ // Comment, use '-->' as end.
+ pCommentBegin = P + 2;
+ for (pCommentEnd = pCommentBegin; pCommentEnd + 2 < pEndOfInput; pCommentEnd++) {
+ if (pCommentEnd[0] == '-' && pCommentEnd[1] == '-' && pCommentEnd[2] == '>') {
+ break;
+ }
+ }
+ if (pCommentEnd + 2 < pEndOfInput) {
+ P = pCommentEnd + 3;
+ } else {
+ P = pCommentEnd = pEndOfInput;
+ }
+ } else {
+ // Like document type definition, match angle brackets.
+ pCommentBegin = P;
+
+ int count = 1;
+ while (*P && count) {
+ if (*P == '>') {
+ --count;
+ } else if (*P == '<') {
+ ++count;
+ }
+ ++P;
}
- ++P;
+ if (count) {
+ pCommentEnd = P;
+ } else {
+ pCommentEnd = P - 1;
+ }
}
- P -= 3;
- node_name = String::utf8(pCommentBegin + 2, (int)(P - pCommentBegin - 2));
- P += 3;
+ node_name = String::utf8(pCommentBegin, (int)(pCommentEnd - pCommentBegin));
#ifdef DEBUG_XML
print_line("XML COMMENT: " + node_name);
#endif
@@ -178,14 +205,14 @@ void XMLParser::_parse_opening_xml_element() {
const char *startName = P;
// find end of element
- while (*P != '>' && !_is_white_space(*P)) {
+ while (*P && *P != '>' && !_is_white_space(*P)) {
++P;
}
const char *endName = P;
// find attributes
- while (*P != '>') {
+ while (*P && *P != '>') {
if (_is_white_space(*P)) {
++P;
} else {
@@ -195,10 +222,14 @@ void XMLParser::_parse_opening_xml_element() {
// read the attribute names
const char *attributeNameBegin = P;
- while (!_is_white_space(*P) && *P != '=') {
+ while (*P && !_is_white_space(*P) && *P != '=') {
++P;
}
+ if (!*P) {
+ break;
+ }
+
const char *attributeNameEnd = P;
++P;
@@ -209,7 +240,7 @@ void XMLParser::_parse_opening_xml_element() {
}
if (!*P) { // malformatted xml file
- return;
+ break;
}
const char attributeQuoteChar = *P;
@@ -221,12 +252,10 @@ void XMLParser::_parse_opening_xml_element() {
++P;
}
- if (!*P) { // malformatted xml file
- return;
- }
-
const char *attributeValueEnd = P;
- ++P;
+ if (*P) {
+ ++P;
+ }
Attribute attr;
attr.name = String::utf8(attributeNameBegin,
@@ -258,7 +287,9 @@ void XMLParser::_parse_opening_xml_element() {
print_line("XML OPEN: " + node_name);
#endif
- ++P;
+ if (*P) {
+ ++P;
+ }
}
void XMLParser::_parse_current_node() {
@@ -270,10 +301,6 @@ void XMLParser::_parse_current_node() {
++P;
}
- if (!*P) {
- return;
- }
-
if (P - start > 0) {
// we found some text, store it
if (_set_text(start, P)) {
@@ -281,6 +308,10 @@ void XMLParser::_parse_current_node() {
}
}
+ if (!*P) {
+ return;
+ }
+
++P;
// based on current token, parse and report next element
@@ -445,7 +476,7 @@ Error XMLParser::open(const String &p_path) {
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
- length = file->get_len();
+ length = file->get_length();
ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT);
if (data) {
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index 847edf958d..1113cce715 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -31,8 +31,8 @@
#ifndef XML_PARSER_H
#define XML_PARSER_H
-#include "core/object/reference.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
+#include "core/object/ref_counted.h"
#include "core/string/ustring.h"
#include "core/templates/vector.h"
@@ -40,8 +40,8 @@
Based on irrXML (see their zlib license). Added mainly for compatibility with their Collada loader.
*/
-class XMLParser : public Reference {
- GDCLASS(XMLParser, Reference);
+class XMLParser : public RefCounted {
+ GDCLASS(XMLParser, RefCounted);
public:
//! Enumeration of all supported source text file formats
@@ -80,7 +80,6 @@ private:
Vector<Attribute> attributes;
- String _replace_special_characters(const String &origstr);
bool _set_text(char *start, char *end);
void _parse_closing_xml_element();
void _ignore_definition();
diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp
index fe46868dd0..fb4c76aa7a 100644
--- a/core/io/zip_io.cpp
+++ b/core/io/zip_io.cpp
@@ -68,13 +68,13 @@ long zipio_tell(voidpf opaque, voidpf stream) {
long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
FileAccess *f = *(FileAccess **)opaque;
- int pos = offset;
+ uint64_t pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
pos = f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
- pos = f->get_len() + offset;
+ pos = f->get_length() + offset;
break;
default:
break;
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index 52691c65e9..776473bfa1 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -31,7 +31,7 @@
#ifndef ZIP_IO_H
#define ZIP_IO_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
// Not directly used in this header, but assumed available in downstream users
// like platform/*/export/export.cpp. Could be fixed, but probably better to have
diff --git a/core/math/a_star.h b/core/math/a_star.h
index 4c61abd91c..44758cb046 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -31,7 +31,7 @@
#ifndef A_STAR_H
#define A_STAR_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/templates/oa_hash_map.h"
/**
@@ -40,8 +40,8 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
-class AStar : public Reference {
- GDCLASS(AStar, Reference);
+class AStar : public RefCounted {
+ GDCLASS(AStar, RefCounted);
friend class AStar2D;
struct Point {
@@ -157,8 +157,8 @@ public:
~AStar();
};
-class AStar2D : public Reference {
- GDCLASS(AStar2D, Reference);
+class AStar2D : public RefCounted {
+ GDCLASS(AStar2D, RefCounted);
AStar astar;
bool _solve(AStar::Point *begin_point, AStar::Point *end_point);
diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp
index 2c721997d8..33aa65f15d 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -392,5 +392,5 @@ Variant AABB::intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) c
}
AABB::operator String() const {
- return String() + position + " - " + size;
+ return "[P: " + position.operator String() + ", S: " + size + "]";
}
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 50299902eb..aa3831d4cf 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -109,7 +109,7 @@ bool Basis::is_diagonal() const {
}
bool Basis::is_rotation() const {
- return Math::is_equal_approx(determinant(), 1, UNIT_EPSILON) && is_orthogonal();
+ return Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON) && is_orthogonal();
}
#ifdef MATH_CHECKS
@@ -345,12 +345,12 @@ void Basis::rotate(const Vector3 &p_euler) {
*this = rotated(p_euler);
}
-Basis Basis::rotated(const Quat &p_quat) const {
- return Basis(p_quat) * (*this);
+Basis Basis::rotated(const Quaternion &p_quaternion) const {
+ return Basis(p_quaternion) * (*this);
}
-void Basis::rotate(const Quat &p_quat) {
- *this = rotated(p_quat);
+void Basis::rotate(const Quaternion &p_quaternion) {
+ *this = rotated(p_quaternion);
}
Vector3 Basis::get_rotation_euler() const {
@@ -367,7 +367,7 @@ Vector3 Basis::get_rotation_euler() const {
return m.get_euler();
}
-Quat Basis::get_rotation_quat() const {
+Quaternion Basis::get_rotation_quaternion() const {
// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
// See the comment in get_scale() for further information.
@@ -378,7 +378,7 @@ Quat Basis::get_rotation_quat() const {
m.scale(Vector3(-1, -1, -1));
}
- return m.get_quat();
+ return m.get_quaternion();
}
void Basis::get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const {
@@ -756,23 +756,14 @@ bool Basis::operator!=(const Basis &p_matrix) const {
}
Basis::operator String() const {
- String mtx;
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- if (i != 0 || j != 0) {
- mtx += ", ";
- }
-
- mtx += rtos(elements[j][i]); //matrix is stored transposed for performance, so print it transposed
- }
- }
-
- return mtx;
+ return "[X: " + get_axis(0).operator String() +
+ ", Y: " + get_axis(1).operator String() +
+ ", Z: " + get_axis(2).operator String() + "]";
}
-Quat Basis::get_quat() const {
+Quaternion Basis::get_quaternion() const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_rotation(), Quat(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quat() or call orthonormalized() instead.");
+ ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() instead.");
#endif
/* Allow getting a quaternion from an unnormalized transform */
Basis m = *this;
@@ -803,7 +794,7 @@ Quat Basis::get_quat() const {
temp[k] = (m.elements[k][i] + m.elements[i][k]) * s;
}
- return Quat(temp[0], temp[1], temp[2], temp[3]);
+ return Quaternion(temp[0], temp[1], temp[2], temp[3]);
}
static const Basis _ortho_bases[24] = {
@@ -945,13 +936,13 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = angle;
}
-void Basis::set_quat(const Quat &p_quat) {
- real_t d = p_quat.length_squared();
+void Basis::set_quaternion(const Quaternion &p_quaternion) {
+ real_t d = p_quaternion.length_squared();
real_t s = 2.0 / d;
- real_t xs = p_quat.x * s, ys = p_quat.y * s, zs = p_quat.z * s;
- real_t wx = p_quat.w * xs, wy = p_quat.w * ys, wz = p_quat.w * zs;
- real_t xx = p_quat.x * xs, xy = p_quat.x * ys, xz = p_quat.x * zs;
- real_t yy = p_quat.y * ys, yz = p_quat.y * zs, zz = p_quat.z * zs;
+ real_t xs = p_quaternion.x * s, ys = p_quaternion.y * s, zs = p_quaternion.z * s;
+ real_t wx = p_quaternion.w * xs, wy = p_quaternion.w * ys, wz = p_quaternion.w * zs;
+ real_t xx = p_quaternion.x * xs, xy = p_quaternion.x * ys, xz = p_quaternion.x * zs;
+ real_t yy = p_quaternion.y * ys, yz = p_quaternion.y * zs, zz = p_quaternion.z * zs;
set(1.0 - (yy + zz), xy - wz, xz + wy,
xy + wz, 1.0 - (xx + zz), yz - wx,
xz - wy, yz + wx, 1.0 - (xx + yy));
@@ -997,9 +988,9 @@ void Basis::set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale) {
rotate(p_euler);
}
-void Basis::set_quat_scale(const Quat &p_quat, const Vector3 &p_scale) {
+void Basis::set_quaternion_scale(const Quaternion &p_quaternion, const Vector3 &p_scale) {
set_diagonal(p_scale);
- rotate(p_quat);
+ rotate(p_quaternion);
}
void Basis::set_diagonal(const Vector3 &p_diag) {
@@ -1018,8 +1009,8 @@ void Basis::set_diagonal(const Vector3 &p_diag) {
Basis Basis::slerp(const Basis &p_to, const real_t &p_weight) const {
//consider scale
- Quat from(*this);
- Quat to(p_to);
+ Quaternion from(*this);
+ Quaternion to(p_to);
Basis b(from.slerp(to, p_weight));
b.elements[0] *= Math::lerp(elements[0].length(), p_to.elements[0].length(), p_weight);
diff --git a/core/math/basis.h b/core/math/basis.h
index 56f6227313..3736047dd3 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -31,7 +31,7 @@
#ifndef BASIS_H
#define BASIS_H
-#include "core/math/quat.h"
+#include "core/math/quaternion.h"
#include "core/math/vector3.h"
class Basis {
@@ -79,13 +79,13 @@ public:
void rotate(const Vector3 &p_euler);
Basis rotated(const Vector3 &p_euler) const;
- void rotate(const Quat &p_quat);
- Basis rotated(const Quat &p_quat) const;
+ void rotate(const Quaternion &p_quaternion);
+ Basis rotated(const Quaternion &p_quaternion) const;
Vector3 get_rotation_euler() const;
void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const;
void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const;
- Quat get_rotation_quat() const;
+ Quaternion get_rotation_quaternion() const;
Vector3 get_rotation() const { return get_rotation_euler(); };
Vector3 rotref_posscale_decomposition(Basis &rotref) const;
@@ -108,8 +108,8 @@ public:
Vector3 get_euler_zyx() const;
void set_euler_zyx(const Vector3 &p_euler);
- Quat get_quat() const;
- void set_quat(const Quat &p_quat);
+ Quaternion get_quaternion() const;
+ void set_quaternion(const Quaternion &p_quaternion);
Vector3 get_euler() const { return get_euler_yxz(); }
void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
@@ -132,7 +132,7 @@ public:
void set_axis_angle_scale(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale);
void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale);
- void set_quat_scale(const Quat &p_quat, const Vector3 &p_scale);
+ void set_quaternion_scale(const Quaternion &p_quaternion, const Vector3 &p_scale);
// transposed dot products
_FORCE_INLINE_ real_t tdotx(const Vector3 &v) const {
@@ -240,10 +240,10 @@ public:
#endif
Basis diagonalize();
- operator Quat() const { return get_quat(); }
+ operator Quaternion() const { return get_quaternion(); }
- Basis(const Quat &p_quat) { set_quat(p_quat); };
- Basis(const Quat &p_quat, const Vector3 &p_scale) { set_quat_scale(p_quat, p_scale); }
+ Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); };
+ Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
Basis(const Vector3 &p_euler) { set_euler(p_euler); }
Basis(const Vector3 &p_euler, const Vector3 &p_scale) { set_euler_scale(p_euler, p_scale); }
diff --git a/core/math/bvh_logic.inc b/core/math/bvh_logic.inc
index d84c3f7830..afab08f151 100644
--- a/core/math/bvh_logic.inc
+++ b/core/math/bvh_logic.inc
@@ -20,17 +20,17 @@ void _logic_item_remove_and_reinsert(uint32_t p_ref_id) {
// some overlay elaborate way to find out which tree the node is in!
BVHHandle temp_handle;
temp_handle.set_id(p_ref_id);
- _current_tree = _handle_get_tree_id(temp_handle);
+ uint32_t tree_id = _handle_get_tree_id(temp_handle);
// remove and reinsert
BVHABB_CLASS abb;
- node_remove_item(p_ref_id, &abb);
+ node_remove_item(p_ref_id, tree_id, &abb);
// we must choose where to add to tree
- ref.tnode_id = _logic_choose_item_add_node(_root_node_id[_current_tree], abb);
+ ref.tnode_id = _logic_choose_item_add_node(_root_node_id[tree_id], abb);
_node_add_item(ref.tnode_id, p_ref_id, abb);
- refit_upward_and_balance(ref.tnode_id);
+ refit_upward_and_balance(ref.tnode_id, tree_id);
}
// from randy gaul balance function
@@ -66,7 +66,7 @@ BVHABB_CLASS _logic_abb_merge(const BVHABB_CLASS &a, const BVHABB_CLASS &b) {
// https://github.com/RandyGaul/qu3e
// It is MODIFIED from qu3e version.
// This is the only function used (and _logic_abb_merge helper function).
-int32_t _logic_balance(int32_t iA) {
+int32_t _logic_balance(int32_t iA, uint32_t p_tree_id) {
// return iA; // uncomment this to bypass balance
TNode *A = &_nodes[iA];
@@ -107,7 +107,7 @@ int32_t _logic_balance(int32_t iA) {
}
} else {
// check this .. seems dodgy
- change_root_node(iC);
+ change_root_node(iC, p_tree_id);
}
// Swap A and C
@@ -159,7 +159,7 @@ int32_t _logic_balance(int32_t iA) {
else {
// check this .. seems dodgy
- change_root_node(iB);
+ change_root_node(iB, p_tree_id);
}
// Swap A and B
diff --git a/core/math/bvh_public.inc b/core/math/bvh_public.inc
index f1b6d6b1bf..2c1e406712 100644
--- a/core/math/bvh_public.inc
+++ b/core/math/bvh_public.inc
@@ -53,16 +53,16 @@ BVHHandle item_add(T *p_userdata, bool p_active, const Bounds &p_aabb, int32_t p
// assign to handle to return
handle.set_id(ref_id);
- _current_tree = 0;
+ uint32_t tree_id = 0;
if (p_pairable) {
- _current_tree = 1;
+ tree_id = 1;
}
- create_root_node(_current_tree);
+ create_root_node(tree_id);
// we must choose where to add to tree
if (p_active) {
- ref->tnode_id = _logic_choose_item_add_node(_root_node_id[_current_tree], abb);
+ ref->tnode_id = _logic_choose_item_add_node(_root_node_id[tree_id], abb);
bool refit = _node_add_item(ref->tnode_id, ref_id, abb);
@@ -70,7 +70,7 @@ BVHHandle item_add(T *p_userdata, bool p_active, const Bounds &p_aabb, int32_t p
// only need to refit from the parent
const TNode &add_node = _nodes[ref->tnode_id];
if (add_node.parent_id != BVHCommon::INVALID) {
- refit_upward_and_balance(add_node.parent_id);
+ refit_upward_and_balance(add_node.parent_id, tree_id);
}
}
} else {
@@ -139,13 +139,13 @@ bool item_move(BVHHandle p_handle, const Bounds &p_aabb) {
return true;
}
- _current_tree = _handle_get_tree_id(p_handle);
+ uint32_t tree_id = _handle_get_tree_id(p_handle);
// remove and reinsert
- node_remove_item(ref_id);
+ node_remove_item(ref_id, tree_id);
// we must choose where to add to tree
- ref.tnode_id = _logic_choose_item_add_node(_root_node_id[_current_tree], abb);
+ ref.tnode_id = _logic_choose_item_add_node(_root_node_id[tree_id], abb);
// add to the tree
bool needs_refit = _node_add_item(ref.tnode_id, ref_id, abb);
@@ -167,7 +167,7 @@ bool item_move(BVHHandle p_handle, const Bounds &p_aabb) {
void item_remove(BVHHandle p_handle) {
uint32_t ref_id = p_handle.id();
- _current_tree = _handle_get_tree_id(p_handle);
+ uint32_t tree_id = _handle_get_tree_id(p_handle);
VERBOSE_PRINT("item_remove [" + itos(ref_id) + "] ");
@@ -187,7 +187,7 @@ void item_remove(BVHHandle p_handle) {
// remove the item from the node (only if active)
if (_refs[ref_id].is_active()) {
- node_remove_item(ref_id);
+ node_remove_item(ref_id, tree_id);
}
// remove the item reference
@@ -198,10 +198,10 @@ void item_remove(BVHHandle p_handle) {
}
// don't think refit_all is necessary?
- //refit_all(_current_tree);
+ //refit_all(_tree_id);
#ifdef BVH_VERBOSE_TREE
- _debug_recursive_print_tree(_current_tree);
+ _debug_recursive_print_tree(tree_id);
#endif
}
@@ -218,13 +218,13 @@ bool item_activate(BVHHandle p_handle, const Bounds &p_aabb) {
BVHABB_CLASS abb;
abb.from(p_aabb);
- _current_tree = _handle_get_tree_id(p_handle);
+ uint32_t tree_id = _handle_get_tree_id(p_handle);
// we must choose where to add to tree
- ref.tnode_id = _logic_choose_item_add_node(_root_node_id[_current_tree], abb);
+ ref.tnode_id = _logic_choose_item_add_node(_root_node_id[tree_id], abb);
_node_add_item(ref.tnode_id, ref_id, abb);
- refit_upward_and_balance(ref.tnode_id);
+ refit_upward_and_balance(ref.tnode_id, tree_id);
return true;
}
@@ -238,9 +238,11 @@ bool item_deactivate(BVHHandle p_handle) {
return false;
}
+ uint32_t tree_id = _handle_get_tree_id(p_handle);
+
// remove from tree
BVHABB_CLASS abb;
- node_remove_item(ref_id, &abb);
+ node_remove_item(ref_id, tree_id, &abb);
// mark as inactive
ref.set_inactive();
@@ -304,21 +306,21 @@ bool item_set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pa
BVHABB_CLASS abb = leaf.get_aabb(ref.item_id);
// make sure current tree is correct prior to changing
- _current_tree = _handle_get_tree_id(p_handle);
+ uint32_t tree_id = _handle_get_tree_id(p_handle);
// remove from old tree
- node_remove_item(ref_id);
+ node_remove_item(ref_id, tree_id);
// we must set the pairable AFTER getting the current tree
// because the pairable status determines which tree
ex.pairable = p_pairable;
// add to new tree
- _current_tree = _handle_get_tree_id(p_handle);
- create_root_node(_current_tree);
+ tree_id = _handle_get_tree_id(p_handle);
+ create_root_node(tree_id);
// we must choose where to add to tree
- ref.tnode_id = _logic_choose_item_add_node(_root_node_id[_current_tree], abb);
+ ref.tnode_id = _logic_choose_item_add_node(_root_node_id[tree_id], abb);
bool needs_refit = _node_add_item(ref.tnode_id, ref_id, abb);
// only need to refit from the PARENT
@@ -326,7 +328,7 @@ bool item_set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pa
// only need to refit from the parent
const TNode &add_node = _nodes[ref.tnode_id];
if (add_node.parent_id != BVHCommon::INVALID) {
- refit_upward_and_balance(add_node.parent_id);
+ refit_upward_and_balance(add_node.parent_id, tree_id);
}
}
} else {
diff --git a/core/math/bvh_refit.inc b/core/math/bvh_refit.inc
index 514c853ac5..717a3438c7 100644
--- a/core/math/bvh_refit.inc
+++ b/core/math/bvh_refit.inc
@@ -66,10 +66,10 @@ void refit_upward(uint32_t p_node_id) {
}
}
-void refit_upward_and_balance(uint32_t p_node_id) {
+void refit_upward_and_balance(uint32_t p_node_id, uint32_t p_tree_id) {
while (p_node_id != BVHCommon::INVALID) {
uint32_t before = p_node_id;
- p_node_id = _logic_balance(p_node_id);
+ p_node_id = _logic_balance(p_node_id, p_tree_id);
if (before != p_node_id) {
VERBOSE_PRINT("REBALANCED!");
diff --git a/core/math/bvh_structs.inc b/core/math/bvh_structs.inc
index 4133ba6c10..1d1e0e6468 100644
--- a/core/math/bvh_structs.inc
+++ b/core/math/bvh_structs.inc
@@ -162,7 +162,6 @@ enum { NUM_TREES = 2,
// Tree 1 - Pairable
// This is more efficient because in physics we only need check non pairable against the pairable tree.
uint32_t _root_node_id[NUM_TREES];
-int _current_tree = 0;
// these values may need tweaking according to the project
// the bound of the world, and the average velocities of the objects
diff --git a/core/math/bvh_tree.h b/core/math/bvh_tree.h
index 64c5f6e254..3169d31ec7 100644
--- a/core/math/bvh_tree.h
+++ b/core/math/bvh_tree.h
@@ -196,7 +196,7 @@ private:
new_child.parent_id = p_parent_id;
}
- void node_remove_child(uint32_t p_parent_id, uint32_t p_child_id, bool p_prevent_sibling = false) {
+ void node_remove_child(uint32_t p_parent_id, uint32_t p_child_id, uint32_t p_tree_id, bool p_prevent_sibling = false) {
TNode &parent = _nodes[p_parent_id];
BVH_ASSERT(!parent.is_leaf());
@@ -231,7 +231,7 @@ private:
if (grandparent_id == BVHCommon::INVALID) {
if (sibling_present) {
// change the root node
- change_root_node(sibling_id);
+ change_root_node(sibling_id, p_tree_id);
// delete the old root node as no longer needed
_nodes.free(p_parent_id);
@@ -243,16 +243,15 @@ private:
if (sibling_present) {
node_replace_child(grandparent_id, p_parent_id, sibling_id);
} else {
- node_remove_child(grandparent_id, p_parent_id, true);
+ node_remove_child(grandparent_id, p_parent_id, p_tree_id, true);
}
// put the node on the free list to recycle
_nodes.free(p_parent_id);
}
- // this relies on _current_tree being accurate
- void change_root_node(uint32_t p_new_root_id) {
- _root_node_id[_current_tree] = p_new_root_id;
+ void change_root_node(uint32_t p_new_root_id, uint32_t p_tree_id) {
+ _root_node_id[p_tree_id] = p_new_root_id;
TNode &root = _nodes[p_new_root_id];
// mark no parent
@@ -272,7 +271,7 @@ private:
node.neg_leaf_id = -(int)child_leaf_id;
}
- void node_remove_item(uint32_t p_ref_id, BVHABB_CLASS *r_old_aabb = nullptr) {
+ void node_remove_item(uint32_t p_ref_id, uint32_t p_tree_id, BVHABB_CLASS *r_old_aabb = nullptr) {
// get the reference
ItemRef &ref = _refs[p_ref_id];
uint32_t owner_node_id = ref.tnode_id;
@@ -336,7 +335,7 @@ private:
uint32_t parent_id = tnode.parent_id;
- node_remove_child(parent_id, owner_node_id);
+ node_remove_child(parent_id, owner_node_id, p_tree_id);
refit_upward(parent_id);
// put the node on the free list to recycle
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index 1066cf5e30..66c18f7b3c 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -315,8 +315,8 @@ Vector2 CameraMatrix::get_far_plane_half_extents() const {
return Vector2(res.x, res.y);
}
-bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
- Vector<Plane> planes = get_projection_planes(Transform());
+bool CameraMatrix::get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const {
+ Vector<Plane> planes = get_projection_planes(Transform3D());
const Planes intersections[8][3] = {
{ PLANE_FAR, PLANE_LEFT, PLANE_TOP },
{ PLANE_FAR, PLANE_LEFT, PLANE_BOTTOM },
@@ -338,7 +338,7 @@ bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8point
return true;
}
-Vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) const {
+Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform) const {
/** Fast Plane Extraction from combined modelview/projection matrices.
* References:
* https://web.archive.org/web/20011221205252/http://www.markmorley.com/opengl/frustumculling.html
@@ -707,8 +707,8 @@ void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) {
matrix[3][3] = 1;
}
-CameraMatrix::operator Transform() const {
- Transform tr;
+CameraMatrix::operator Transform3D() const {
+ Transform3D tr;
const real_t *m = &matrix[0][0];
tr.basis.elements[0][0] = m[0];
@@ -730,8 +730,8 @@ CameraMatrix::operator Transform() const {
return tr;
}
-CameraMatrix::CameraMatrix(const Transform &p_transform) {
- const Transform &tr = p_transform;
+CameraMatrix::CameraMatrix(const Transform3D &p_transform) {
+ const Transform3D &tr = p_transform;
real_t *m = &matrix[0][0];
m[0] = tr.basis.elements[0][0];
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 3f327d3bc4..786d46055a 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -32,7 +32,7 @@
#define CAMERA_MATRIX_H
#include "core/math/rect2.h"
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
struct CameraMatrix {
enum Planes {
@@ -71,9 +71,9 @@ struct CameraMatrix {
real_t get_fov() const;
bool is_orthogonal() const;
- Vector<Plane> get_projection_planes(const Transform &p_transform) const;
+ Vector<Plane> get_projection_planes(const Transform3D &p_transform) const;
- bool get_endpoints(const Transform &p_transform, Vector3 *p_8points) const;
+ bool get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const;
Vector2 get_viewport_half_extents() const;
Vector2 get_far_plane_half_extents() const;
@@ -90,7 +90,7 @@ struct CameraMatrix {
void scale_translate_to_fit(const AABB &p_aabb);
void make_scale(const Vector3 &p_scale);
int get_pixels_per_meter(int p_for_pixel_width) const;
- operator Transform() const;
+ operator Transform3D() const;
void flip_y();
@@ -112,7 +112,7 @@ struct CameraMatrix {
float get_lod_multiplier() const;
CameraMatrix();
- CameraMatrix(const Transform &p_transform);
+ CameraMatrix(const Transform3D &p_transform);
~CameraMatrix();
};
diff --git a/core/math/color.cpp b/core/math/color.cpp
index 64abd6dd08..dc86cacf8f 100644
--- a/core/math/color.cpp
+++ b/core/math/color.cpp
@@ -211,6 +211,14 @@ bool Color::is_equal_approx(const Color &p_color) const {
return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a);
}
+Color Color::clamp(const Color &p_min, const Color &p_max) const {
+ return Color(
+ CLAMP(r, p_min.r, p_max.r),
+ CLAMP(g, p_min.g, p_max.g),
+ CLAMP(b, p_min.b, p_max.b),
+ CLAMP(a, p_min.a, p_max.a));
+}
+
void Color::invert() {
r = 1.0 - r;
g = 1.0 - g;
@@ -360,7 +368,7 @@ Color Color::named(const String &p_name) {
ERR_FAIL_V_MSG(Color(), "Invalid color name: " + p_name + ".");
return Color();
}
- return get_named_color(idx);
+ return named_colors[idx].color;
}
Color Color::named(const String &p_name, const Color &p_default) {
@@ -368,7 +376,7 @@ Color Color::named(const String &p_name, const Color &p_default) {
if (idx == -1) {
return p_default;
}
- return get_named_color(idx);
+ return named_colors[idx].color;
}
int Color::find_named_color(const String &p_name) {
@@ -401,10 +409,12 @@ int Color::get_named_color_count() {
}
String Color::get_named_color_name(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, get_named_color_count(), "");
return named_colors[p_idx].name;
}
Color Color::get_named_color(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, get_named_color_count(), Color());
return named_colors[p_idx].color;
}
@@ -458,7 +468,7 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
}
Color::operator String() const {
- return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a);
+ return "(" + String::num(r, 4) + ", " + String::num(g, 4) + ", " + String::num(b, 4) + ", " + String::num(a, 4) + ")";
}
Color Color::operator+(const Color &p_color) const {
diff --git a/core/math/color.h b/core/math/color.h
index e404d80c8a..a95dbf4f60 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -89,6 +89,7 @@ struct Color {
bool is_equal_approx(const Color &p_color) const;
+ Color clamp(const Color &p_min = Color(0, 0, 0, 0), const Color &p_max = Color(1, 1, 1, 1)) const;
void invert();
Color inverted() const;
diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp
new file mode 100644
index 0000000000..682a7ea39e
--- /dev/null
+++ b/core/math/convex_hull.cpp
@@ -0,0 +1,2290 @@
+/*************************************************************************/
+/* convex_hull.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+/*
+ * Based on Godot's patched VHACD-version of Bullet's btConvexHullComputer.
+ * See /thirdparty/vhacd/btConvexHullComputer.cpp at 64403ddcab9f1dca2408f0a412a22d899708bbb1
+ * In turn, based on /src/LinearMath/btConvexHullComputer.cpp in <https://github.com/bulletphysics/bullet3>
+ * at 73b217fb07e7e3ce126caeb28ab3c9ddd0718467
+ *
+ * Changes:
+ * - int32_t is consistently used instead of int in some cases
+ * - integrated patch db0d6c92927f5a1358b887f2645c11f3014f0e8a from Bullet (CWE-190 integer overflow in btConvexHullComputer)
+ * - adapted to Godot's code style
+ * - replaced Bullet's types (e.g. vectors) with Godot's
+ * - replaced custom Pool implementation with PagedAllocator
+ */
+
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+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.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "convex_hull.h"
+
+#include "core/error/error_macros.h"
+#include "core/math/aabb.h"
+#include "core/math/math_defs.h"
+#include "core/os/memory.h"
+#include "core/templates/paged_allocator.h"
+
+#include <string.h>
+
+//#define DEBUG_CONVEX_HULL
+//#define SHOW_ITERATIONS
+
+// -- GODOT start --
+// Assembly optimizations are not used at the moment.
+//#define USE_X86_64_ASM
+// -- GODOT end --
+
+#ifdef DEBUG_ENABLED
+#define CHULL_ASSERT(m_cond) \
+ do { \
+ if (unlikely(!(m_cond))) { \
+ ERR_PRINT("Assertion \"" _STR(m_cond) "\" failed."); \
+ } \
+ } while (0)
+#else
+#define CHULL_ASSERT(m_cond) \
+ do { \
+ } while (0)
+#endif
+
+#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
+#include <stdio.h>
+#endif
+
+// Convex hull implementation based on Preparata and Hong
+// Ole Kniemeyer, MAXON Computer GmbH
+class ConvexHullInternal {
+public:
+ class Point64 {
+ public:
+ int64_t x;
+ int64_t y;
+ int64_t z;
+
+ Point64(int64_t p_x, int64_t p_y, int64_t p_z) {
+ x = p_x;
+ y = p_y;
+ z = p_z;
+ }
+
+ bool is_zero() {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
+
+ int64_t dot(const Point64 &b) const {
+ return x * b.x + y * b.y + z * b.z;
+ }
+ };
+
+ class Point32 {
+ public:
+ int32_t x = 0;
+ int32_t y = 0;
+ int32_t z = 0;
+ int32_t index = -1;
+
+ Point32() {
+ }
+
+ Point32(int32_t p_x, int32_t p_y, int32_t p_z) {
+ x = p_x;
+ y = p_y;
+ z = p_z;
+ }
+
+ bool operator==(const Point32 &b) const {
+ return (x == b.x) && (y == b.y) && (z == b.z);
+ }
+
+ bool operator!=(const Point32 &b) const {
+ return (x != b.x) || (y != b.y) || (z != b.z);
+ }
+
+ bool is_zero() {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
+
+ Point64 cross(const Point32 &b) const {
+ return Point64((int64_t)y * b.z - (int64_t)z * b.y, (int64_t)z * b.x - (int64_t)x * b.z, (int64_t)x * b.y - (int64_t)y * b.x);
+ }
+
+ Point64 cross(const Point64 &b) const {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
+
+ int64_t dot(const Point32 &b) const {
+ return (int64_t)x * b.x + (int64_t)y * b.y + (int64_t)z * b.z;
+ }
+
+ int64_t dot(const Point64 &b) const {
+ return x * b.x + y * b.y + z * b.z;
+ }
+
+ Point32 operator+(const Point32 &b) const {
+ return Point32(x + b.x, y + b.y, z + b.z);
+ }
+
+ Point32 operator-(const Point32 &b) const {
+ return Point32(x - b.x, y - b.y, z - b.z);
+ }
+ };
+
+ class Int128 {
+ public:
+ uint64_t low = 0;
+ uint64_t high = 0;
+
+ Int128() {
+ }
+
+ Int128(uint64_t p_low, uint64_t p_high) {
+ low = p_low;
+ high = p_high;
+ }
+
+ Int128(uint64_t p_low) {
+ low = p_low;
+ high = 0;
+ }
+
+ Int128(int64_t p_value) {
+ low = p_value;
+ if (p_value >= 0) {
+ high = 0;
+ } else {
+ high = (uint64_t)-1LL;
+ }
+ }
+
+ static Int128 mul(int64_t a, int64_t b);
+
+ static Int128 mul(uint64_t a, uint64_t b);
+
+ Int128 operator-() const {
+ return Int128((uint64_t) - (int64_t)low, ~high + (low == 0));
+ }
+
+ Int128 operator+(const Int128 &b) const {
+#ifdef USE_X86_64_ASM
+ Int128 result;
+ __asm__("addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r"(result.low), [rh] "=r"(result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+ return result;
+#else
+ uint64_t lo = low + b.low;
+ return Int128(lo, high + b.high + (lo < low));
+#endif
+ }
+
+ Int128 operator-(const Int128 &b) const {
+#ifdef USE_X86_64_ASM
+ Int128 result;
+ __asm__("subq %[bl], %[rl]\n\t"
+ "sbbq %[bh], %[rh]\n\t"
+ : [rl] "=r"(result.low), [rh] "=r"(result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+ return result;
+#else
+ return *this + -b;
+#endif
+ }
+
+ Int128 &operator+=(const Int128 &b) {
+#ifdef USE_X86_64_ASM
+ __asm__("addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r"(low), [rh] "=r"(high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+#else
+ uint64_t lo = low + b.low;
+ if (lo < low) {
+ ++high;
+ }
+ low = lo;
+ high += b.high;
+#endif
+ return *this;
+ }
+
+ Int128 &operator++() {
+ if (++low == 0) {
+ ++high;
+ }
+ return *this;
+ }
+
+ Int128 operator*(int64_t b) const;
+
+ real_t to_scalar() const {
+ return ((int64_t)high >= 0) ? real_t(high) * (real_t(0x100000000LL) * real_t(0x100000000LL)) + real_t(low) : -(-*this).to_scalar();
+ }
+
+ int32_t get_sign() const {
+ return ((int64_t)high < 0) ? -1 : (high || low) ? 1 :
+ 0;
+ }
+
+ bool operator<(const Int128 &b) const {
+ return (high < b.high) || ((high == b.high) && (low < b.low));
+ }
+
+ int32_t ucmp(const Int128 &b) const {
+ if (high < b.high) {
+ return -1;
+ }
+ if (high > b.high) {
+ return 1;
+ }
+ if (low < b.low) {
+ return -1;
+ }
+ if (low > b.low) {
+ return 1;
+ }
+ return 0;
+ }
+ };
+
+ class Rational64 {
+ private:
+ uint64_t numerator;
+ uint64_t denominator;
+ int32_t sign;
+
+ public:
+ Rational64(int64_t p_numerator, int64_t p_denominator) {
+ if (p_numerator > 0) {
+ sign = 1;
+ numerator = (uint64_t)p_numerator;
+ } else if (p_numerator < 0) {
+ sign = -1;
+ numerator = (uint64_t)-p_numerator;
+ } else {
+ sign = 0;
+ numerator = 0;
+ }
+ if (p_denominator > 0) {
+ denominator = (uint64_t)p_denominator;
+ } else if (p_denominator < 0) {
+ sign = -sign;
+ denominator = (uint64_t)-p_denominator;
+ } else {
+ denominator = 0;
+ }
+ }
+
+ bool is_negative_infinity() const {
+ return (sign < 0) && (denominator == 0);
+ }
+
+ bool is_nan() const {
+ return (sign == 0) && (denominator == 0);
+ }
+
+ int32_t compare(const Rational64 &b) const;
+
+ real_t to_scalar() const {
+ return sign * ((denominator == 0) ? FLT_MAX : (real_t)numerator / denominator);
+ }
+ };
+
+ class Rational128 {
+ private:
+ Int128 numerator;
+ Int128 denominator;
+ int32_t sign;
+ bool is_int_64;
+
+ public:
+ Rational128(int64_t p_value) {
+ if (p_value > 0) {
+ sign = 1;
+ this->numerator = p_value;
+ } else if (p_value < 0) {
+ sign = -1;
+ this->numerator = -p_value;
+ } else {
+ sign = 0;
+ this->numerator = (uint64_t)0;
+ }
+ this->denominator = (uint64_t)1;
+ is_int_64 = true;
+ }
+
+ Rational128(const Int128 &p_numerator, const Int128 &p_denominator) {
+ sign = p_numerator.get_sign();
+ if (sign >= 0) {
+ this->numerator = p_numerator;
+ } else {
+ this->numerator = -p_numerator;
+ }
+ int32_t dsign = p_denominator.get_sign();
+ if (dsign >= 0) {
+ this->denominator = p_denominator;
+ } else {
+ sign = -sign;
+ this->denominator = -p_denominator;
+ }
+ is_int_64 = false;
+ }
+
+ int32_t compare(const Rational128 &b) const;
+
+ int32_t compare(int64_t b) const;
+
+ real_t to_scalar() const {
+ return sign * ((denominator.get_sign() == 0) ? FLT_MAX : numerator.to_scalar() / denominator.to_scalar());
+ }
+ };
+
+ class PointR128 {
+ public:
+ Int128 x;
+ Int128 y;
+ Int128 z;
+ Int128 denominator;
+
+ PointR128() {
+ }
+
+ PointR128(Int128 p_x, Int128 p_y, Int128 p_z, Int128 p_denominator) {
+ x = p_x;
+ y = p_y;
+ z = p_z;
+ denominator = p_denominator;
+ }
+
+ real_t xvalue() const {
+ return x.to_scalar() / denominator.to_scalar();
+ }
+
+ real_t yvalue() const {
+ return y.to_scalar() / denominator.to_scalar();
+ }
+
+ real_t zvalue() const {
+ return z.to_scalar() / denominator.to_scalar();
+ }
+ };
+
+ class Edge;
+ class Face;
+
+ class Vertex {
+ public:
+ Vertex *next = nullptr;
+ Vertex *prev = nullptr;
+ Edge *edges = nullptr;
+ Face *first_nearby_face = nullptr;
+ Face *last_nearby_face = nullptr;
+ PointR128 point128;
+ Point32 point;
+ int32_t copy = -1;
+
+ Vertex() {
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ void print() {
+ printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+ }
+
+ void print_graph();
+#endif
+
+ Point32 operator-(const Vertex &b) const {
+ return point - b.point;
+ }
+
+ Rational128 dot(const Point64 &b) const {
+ return (point.index >= 0) ? Rational128(point.dot(b)) : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+ }
+
+ real_t xvalue() const {
+ return (point.index >= 0) ? real_t(point.x) : point128.xvalue();
+ }
+
+ real_t yvalue() const {
+ return (point.index >= 0) ? real_t(point.y) : point128.yvalue();
+ }
+
+ real_t zvalue() const {
+ return (point.index >= 0) ? real_t(point.z) : point128.zvalue();
+ }
+
+ void receive_nearby_faces(Vertex *p_src) {
+ if (last_nearby_face) {
+ last_nearby_face->next_with_same_nearby_vertex = p_src->first_nearby_face;
+ } else {
+ first_nearby_face = p_src->first_nearby_face;
+ }
+ if (p_src->last_nearby_face) {
+ last_nearby_face = p_src->last_nearby_face;
+ }
+ for (Face *f = p_src->first_nearby_face; f; f = f->next_with_same_nearby_vertex) {
+ CHULL_ASSERT(f->nearby_vertex == p_src);
+ f->nearby_vertex = this;
+ }
+ p_src->first_nearby_face = nullptr;
+ p_src->last_nearby_face = nullptr;
+ }
+ };
+
+ class Edge {
+ public:
+ Edge *next = nullptr;
+ Edge *prev = nullptr;
+ Edge *reverse = nullptr;
+ Vertex *target = nullptr;
+ Face *face = nullptr;
+ int32_t copy = -1;
+
+ void link(Edge *n) {
+ CHULL_ASSERT(reverse->target == n->reverse->target);
+ next = n;
+ n->prev = this;
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ void print() {
+ printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+ reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+ }
+#endif
+ };
+
+ class Face {
+ public:
+ Face *next = nullptr;
+ Vertex *nearby_vertex = nullptr;
+ Face *next_with_same_nearby_vertex = nullptr;
+ Point32 origin;
+ Point32 dir0;
+ Point32 dir1;
+
+ Face() {
+ }
+
+ void init(Vertex *p_a, Vertex *p_b, Vertex *p_c) {
+ nearby_vertex = p_a;
+ origin = p_a->point;
+ dir0 = *p_b - *p_a;
+ dir1 = *p_c - *p_a;
+ if (p_a->last_nearby_face) {
+ p_a->last_nearby_face->next_with_same_nearby_vertex = this;
+ } else {
+ p_a->first_nearby_face = this;
+ }
+ p_a->last_nearby_face = this;
+ }
+
+ Point64 get_normal() {
+ return dir0.cross(dir1);
+ }
+ };
+
+ template <typename UWord, typename UHWord>
+ class DMul {
+ private:
+ static uint32_t high(uint64_t p_value) {
+ return (uint32_t)(p_value >> 32);
+ }
+
+ static uint32_t low(uint64_t p_value) {
+ return (uint32_t)p_value;
+ }
+
+ static uint64_t mul(uint32_t a, uint32_t b) {
+ return (uint64_t)a * (uint64_t)b;
+ }
+
+ static void shl_half(uint64_t &p_value) {
+ p_value <<= 32;
+ }
+
+ static uint64_t high(Int128 p_value) {
+ return p_value.high;
+ }
+
+ static uint64_t low(Int128 p_value) {
+ return p_value.low;
+ }
+
+ static Int128 mul(uint64_t a, uint64_t b) {
+ return Int128::mul(a, b);
+ }
+
+ static void shl_half(Int128 &p_value) {
+ p_value.high = p_value.low;
+ p_value.low = 0;
+ }
+
+ public:
+ static void mul(UWord p_a, UWord p_b, UWord &r_low, UWord &r_high) {
+ UWord p00 = mul(low(p_a), low(p_b));
+ UWord p01 = mul(low(p_a), high(p_b));
+ UWord p10 = mul(high(p_a), low(p_b));
+ UWord p11 = mul(high(p_a), high(p_b));
+ UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+ p11 += high(p01);
+ p11 += high(p10);
+ p11 += high(p0110);
+ shl_half(p0110);
+ p00 += p0110;
+ if (p00 < p0110) {
+ ++p11;
+ }
+ r_low = p00;
+ r_high = p11;
+ }
+ };
+
+private:
+ class IntermediateHull {
+ public:
+ Vertex *min_xy = nullptr;
+ Vertex *max_xy = nullptr;
+ Vertex *min_yx = nullptr;
+ Vertex *max_yx = nullptr;
+
+ IntermediateHull() {
+ }
+
+ void print();
+ };
+
+ enum Orientation { NONE,
+ CLOCKWISE,
+ COUNTER_CLOCKWISE };
+
+ Vector3 scaling;
+ Vector3 center;
+ PagedAllocator<Vertex> vertex_pool;
+ PagedAllocator<Edge> edge_pool;
+ PagedAllocator<Face> face_pool;
+ LocalVector<Vertex *> original_vertices;
+ int32_t merge_stamp = 0;
+ int32_t min_axis = 0;
+ int32_t med_axis = 0;
+ int32_t max_axis = 0;
+ int32_t used_edge_pairs = 0;
+ int32_t max_used_edge_pairs = 0;
+
+ static Orientation get_orientation(const Edge *p_prev, const Edge *p_next, const Point32 &p_s, const Point32 &p_t);
+ Edge *find_max_angle(bool p_ccw, const Vertex *p_start, const Point32 &p_s, const Point64 &p_rxs, const Point64 &p_ssxrxs, Rational64 &p_min_cot);
+ void find_edge_for_coplanar_faces(Vertex *p_c0, Vertex *p_c1, Edge *&p_e0, Edge *&p_e1, Vertex *p_stop0, Vertex *p_stop1);
+
+ Edge *new_edge_pair(Vertex *p_from, Vertex *p_to);
+
+ void remove_edge_pair(Edge *p_edge) {
+ Edge *n = p_edge->next;
+ Edge *r = p_edge->reverse;
+
+ CHULL_ASSERT(p_edge->target && r->target);
+
+ if (n != p_edge) {
+ n->prev = p_edge->prev;
+ p_edge->prev->next = n;
+ r->target->edges = n;
+ } else {
+ r->target->edges = nullptr;
+ }
+
+ n = r->next;
+
+ if (n != r) {
+ n->prev = r->prev;
+ r->prev->next = n;
+ p_edge->target->edges = n;
+ } else {
+ p_edge->target->edges = nullptr;
+ }
+
+ edge_pool.free(p_edge);
+ edge_pool.free(r);
+ used_edge_pairs--;
+ }
+
+ void compute_internal(int32_t p_start, int32_t p_end, IntermediateHull &r_result);
+
+ bool merge_projection(IntermediateHull &p_h0, IntermediateHull &p_h1, Vertex *&r_c0, Vertex *&r_c1);
+
+ void merge(IntermediateHull &p_h0, IntermediateHull &p_h1);
+
+ Vector3 to_gd_vector(const Point32 &p_v);
+
+ Vector3 get_gd_normal(Face *p_face);
+
+ bool shift_face(Face *p_face, real_t p_amount, LocalVector<Vertex *> p_stack);
+
+public:
+ ~ConvexHullInternal() {
+ vertex_pool.reset(true);
+ edge_pool.reset(true);
+ face_pool.reset(true);
+ }
+
+ Vertex *vertex_list;
+
+ void compute(const Vector3 *p_coords, int32_t p_count);
+
+ Vector3 get_coordinates(const Vertex *p_v);
+
+ real_t shrink(real_t amount, real_t p_clamp_amount);
+};
+
+ConvexHullInternal::Int128 ConvexHullInternal::Int128::operator*(int64_t b) const {
+ bool negative = (int64_t)high < 0;
+ Int128 a = negative ? -*this : *this;
+ if (b < 0) {
+ negative = !negative;
+ b = -b;
+ }
+ Int128 result = mul(a.low, (uint64_t)b);
+ result.high += a.high * (uint64_t)b;
+ return negative ? -result : result;
+}
+
+ConvexHullInternal::Int128 ConvexHullInternal::Int128::mul(int64_t a, int64_t b) {
+ Int128 result;
+
+#ifdef USE_X86_64_ASM
+ __asm__("imulq %[b]"
+ : "=a"(result.low), "=d"(result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc");
+ return result;
+
+#else
+ bool negative = a < 0;
+ if (negative) {
+ a = -a;
+ }
+ if (b < 0) {
+ negative = !negative;
+ b = -b;
+ }
+ DMul<uint64_t, uint32_t>::mul((uint64_t)a, (uint64_t)b, result.low, result.high);
+ return negative ? -result : result;
+#endif
+}
+
+ConvexHullInternal::Int128 ConvexHullInternal::Int128::mul(uint64_t a, uint64_t b) {
+ Int128 result;
+
+#ifdef USE_X86_64_ASM
+ __asm__("mulq %[b]"
+ : "=a"(result.low), "=d"(result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc");
+
+#else
+ DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high);
+#endif
+
+ return result;
+}
+
+int32_t ConvexHullInternal::Rational64::compare(const Rational64 &b) const {
+ if (sign != b.sign) {
+ return sign - b.sign;
+ } else if (sign == 0) {
+ return 0;
+ }
+
+ // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
+
+#ifdef USE_X86_64_ASM
+
+ int32_t result;
+ int64_t tmp;
+ int64_t dummy;
+ __asm__("mulq %[bn]\n\t"
+ "movq %%rax, %[tmp]\n\t"
+ "movq %%rdx, %%rbx\n\t"
+ "movq %[tn], %%rax\n\t"
+ "mulq %[bd]\n\t"
+ "subq %[tmp], %%rax\n\t"
+ "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+ "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
+ "orq %%rdx, %%rax\n\t"
+ "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
+ "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+ "shll $16, %%ebx\n\t" // ebx has same sign as difference
+ : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+ : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
+ : "%rdx", "cc");
+ return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+ // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+ :
+ 0;
+
+#else
+
+ return sign * Int128::mul(numerator, b.denominator).ucmp(Int128::mul(denominator, b.numerator));
+
+#endif
+}
+
+int32_t ConvexHullInternal::Rational128::compare(const Rational128 &b) const {
+ if (sign != b.sign) {
+ return sign - b.sign;
+ } else if (sign == 0) {
+ return 0;
+ }
+ if (is_int_64) {
+ return -b.compare(sign * (int64_t)numerator.low);
+ }
+
+ Int128 nbd_low, nbd_high, dbn_low, dbn_high;
+ DMul<Int128, uint64_t>::mul(numerator, b.denominator, nbd_low, nbd_high);
+ DMul<Int128, uint64_t>::mul(denominator, b.numerator, dbn_low, dbn_high);
+
+ int32_t cmp = nbd_high.ucmp(dbn_high);
+ if (cmp) {
+ return cmp * sign;
+ }
+ return nbd_low.ucmp(dbn_low) * sign;
+}
+
+int32_t ConvexHullInternal::Rational128::compare(int64_t b) const {
+ if (is_int_64) {
+ int64_t a = sign * (int64_t)numerator.low;
+ return (a > b) ? 1 : (a < b) ? -1 :
+ 0;
+ }
+ if (b > 0) {
+ if (sign <= 0) {
+ return -1;
+ }
+ } else if (b < 0) {
+ if (sign >= 0) {
+ return 1;
+ }
+ b = -b;
+ } else {
+ return sign;
+ }
+
+ return numerator.ucmp(denominator * b) * sign;
+}
+
+ConvexHullInternal::Edge *ConvexHullInternal::new_edge_pair(Vertex *p_from, Vertex *p_to) {
+ CHULL_ASSERT(p_from && p_to);
+ Edge *e = edge_pool.alloc();
+ Edge *r = edge_pool.alloc();
+ e->reverse = r;
+ r->reverse = e;
+ e->copy = merge_stamp;
+ r->copy = merge_stamp;
+ e->target = p_to;
+ r->target = p_from;
+ e->face = nullptr;
+ r->face = nullptr;
+ used_edge_pairs++;
+ if (used_edge_pairs > max_used_edge_pairs) {
+ max_used_edge_pairs = used_edge_pairs;
+ }
+ return e;
+}
+
+bool ConvexHullInternal::merge_projection(IntermediateHull &r_h0, IntermediateHull &r_h1, Vertex *&r_c0, Vertex *&r_c1) {
+ Vertex *v0 = r_h0.max_yx;
+ Vertex *v1 = r_h1.min_yx;
+ if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y)) {
+ CHULL_ASSERT(v0->point.z < v1->point.z);
+ Vertex *v1p = v1->prev;
+ if (v1p == v1) {
+ r_c0 = v0;
+ if (v1->edges) {
+ CHULL_ASSERT(v1->edges->next == v1->edges);
+ v1 = v1->edges->target;
+ CHULL_ASSERT(v1->edges->next == v1->edges);
+ }
+ r_c1 = v1;
+ return false;
+ }
+ Vertex *v1n = v1->next;
+ v1p->next = v1n;
+ v1n->prev = v1p;
+ if (v1 == r_h1.min_xy) {
+ if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y))) {
+ r_h1.min_xy = v1n;
+ } else {
+ r_h1.min_xy = v1p;
+ }
+ }
+ if (v1 == r_h1.max_xy) {
+ if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y))) {
+ r_h1.max_xy = v1n;
+ } else {
+ r_h1.max_xy = v1p;
+ }
+ }
+ }
+
+ v0 = r_h0.max_xy;
+ v1 = r_h1.max_xy;
+ Vertex *v00 = nullptr;
+ Vertex *v10 = nullptr;
+ int32_t sign = 1;
+
+ for (int32_t side = 0; side <= 1; side++) {
+ int32_t dx = (v1->point.x - v0->point.x) * sign;
+ if (dx > 0) {
+ while (true) {
+ int32_t dy = v1->point.y - v0->point.y;
+
+ Vertex *w0 = side ? v0->next : v0->prev;
+ if (w0 != v0) {
+ int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+ int32_t dy0 = w0->point.y - v0->point.y;
+ if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0)))) {
+ v0 = w0;
+ dx = (v1->point.x - v0->point.x) * sign;
+ continue;
+ }
+ }
+
+ Vertex *w1 = side ? v1->next : v1->prev;
+ if (w1 != v1) {
+ int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+ int32_t dy1 = w1->point.y - v1->point.y;
+ int32_t dxn = (w1->point.x - v0->point.x) * sign;
+ if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1)))) {
+ v1 = w1;
+ dx = dxn;
+ continue;
+ }
+ }
+
+ break;
+ }
+ } else if (dx < 0) {
+ while (true) {
+ int32_t dy = v1->point.y - v0->point.y;
+
+ Vertex *w1 = side ? v1->prev : v1->next;
+ if (w1 != v1) {
+ int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+ int32_t dy1 = w1->point.y - v1->point.y;
+ if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1)))) {
+ v1 = w1;
+ dx = (v1->point.x - v0->point.x) * sign;
+ continue;
+ }
+ }
+
+ Vertex *w0 = side ? v0->prev : v0->next;
+ if (w0 != v0) {
+ int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+ int32_t dy0 = w0->point.y - v0->point.y;
+ int32_t dxn = (v1->point.x - w0->point.x) * sign;
+ if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0)))) {
+ v0 = w0;
+ dx = dxn;
+ continue;
+ }
+ }
+
+ break;
+ }
+ } else {
+ int32_t x = v0->point.x;
+ int32_t y0 = v0->point.y;
+ Vertex *w0 = v0;
+ Vertex *t;
+ while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0)) {
+ w0 = t;
+ y0 = t->point.y;
+ }
+ v0 = w0;
+
+ int32_t y1 = v1->point.y;
+ Vertex *w1 = v1;
+ while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1)) {
+ w1 = t;
+ y1 = t->point.y;
+ }
+ v1 = w1;
+ }
+
+ if (side == 0) {
+ v00 = v0;
+ v10 = v1;
+
+ v0 = r_h0.min_xy;
+ v1 = r_h1.min_xy;
+ sign = -1;
+ }
+ }
+
+ v0->prev = v1;
+ v1->next = v0;
+
+ v00->next = v10;
+ v10->prev = v00;
+
+ if (r_h1.min_xy->point.x < r_h0.min_xy->point.x) {
+ r_h0.min_xy = r_h1.min_xy;
+ }
+ if (r_h1.max_xy->point.x >= r_h0.max_xy->point.x) {
+ r_h0.max_xy = r_h1.max_xy;
+ }
+
+ r_h0.max_yx = r_h1.max_yx;
+
+ r_c0 = v00;
+ r_c1 = v10;
+
+ return true;
+}
+
+void ConvexHullInternal::compute_internal(int32_t p_start, int32_t p_end, IntermediateHull &r_result) {
+ int32_t n = p_end - p_start;
+ switch (n) {
+ case 0:
+ r_result.min_xy = nullptr;
+ r_result.max_xy = nullptr;
+ r_result.min_yx = nullptr;
+ r_result.max_yx = nullptr;
+ return;
+ case 2: {
+ Vertex *v = original_vertices[p_start];
+ Vertex *w = original_vertices[p_start + 1];
+ if (v->point != w->point) {
+ int32_t dx = v->point.x - w->point.x;
+ int32_t dy = v->point.y - w->point.y;
+
+ if ((dx == 0) && (dy == 0)) {
+ if (v->point.z > w->point.z) {
+ Vertex *t = w;
+ w = v;
+ v = t;
+ }
+ CHULL_ASSERT(v->point.z < w->point.z);
+ v->next = v;
+ v->prev = v;
+ r_result.min_xy = v;
+ r_result.max_xy = v;
+ r_result.min_yx = v;
+ r_result.max_yx = v;
+ } else {
+ v->next = w;
+ v->prev = w;
+ w->next = v;
+ w->prev = v;
+
+ if ((dx < 0) || ((dx == 0) && (dy < 0))) {
+ r_result.min_xy = v;
+ r_result.max_xy = w;
+ } else {
+ r_result.min_xy = w;
+ r_result.max_xy = v;
+ }
+
+ if ((dy < 0) || ((dy == 0) && (dx < 0))) {
+ r_result.min_yx = v;
+ r_result.max_yx = w;
+ } else {
+ r_result.min_yx = w;
+ r_result.max_yx = v;
+ }
+ }
+
+ Edge *e = new_edge_pair(v, w);
+ e->link(e);
+ v->edges = e;
+
+ e = e->reverse;
+ e->link(e);
+ w->edges = e;
+
+ return;
+ }
+ [[fallthrough]];
+ }
+ case 1: {
+ Vertex *v = original_vertices[p_start];
+ v->edges = nullptr;
+ v->next = v;
+ v->prev = v;
+
+ r_result.min_xy = v;
+ r_result.max_xy = v;
+ r_result.min_yx = v;
+ r_result.max_yx = v;
+
+ return;
+ }
+ }
+
+ int32_t split0 = p_start + n / 2;
+ Point32 p = original_vertices[split0 - 1]->point;
+ int32_t split1 = split0;
+ while ((split1 < p_end) && (original_vertices[split1]->point == p)) {
+ split1++;
+ }
+ compute_internal(p_start, split0, r_result);
+ IntermediateHull hull1;
+ compute_internal(split1, p_end, hull1);
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n\nMerge\n");
+ r_result.print();
+ hull1.print();
+#endif
+ merge(r_result, hull1);
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n Result\n");
+ r_result.print();
+#endif
+}
+
+#ifdef DEBUG_CONVEX_HULL
+void ConvexHullInternal::IntermediateHull::print() {
+ printf(" Hull\n");
+ for (Vertex *v = min_xy; v;) {
+ printf(" ");
+ v->print();
+ if (v == max_xy) {
+ printf(" max_xy");
+ }
+ if (v == min_yx) {
+ printf(" min_yx");
+ }
+ if (v == max_yx) {
+ printf(" max_yx");
+ }
+ if (v->next->prev != v) {
+ printf(" Inconsistency");
+ }
+ printf("\n");
+ v = v->next;
+ if (v == min_xy) {
+ break;
+ }
+ }
+ if (min_xy) {
+ min_xy->copy = (min_xy->copy == -1) ? -2 : -1;
+ min_xy->print_graph();
+ }
+}
+
+void ConvexHullInternal::Vertex::print_graph() {
+ print();
+ printf("\nEdges\n");
+ Edge *e = edges;
+ if (e) {
+ do {
+ e->print();
+ printf("\n");
+ e = e->next;
+ } while (e != edges);
+ do {
+ Vertex *v = e->target;
+ if (v->copy != copy) {
+ v->copy = copy;
+ v->print_graph();
+ }
+ e = e->next;
+ } while (e != edges);
+ }
+}
+#endif
+
+ConvexHullInternal::Orientation ConvexHullInternal::get_orientation(const Edge *p_prev, const Edge *p_next, const Point32 &p_s, const Point32 &p_t) {
+ CHULL_ASSERT(p_prev->reverse->target == p_next->reverse->target);
+ if (p_prev->next == p_next) {
+ if (p_prev->prev == p_next) {
+ Point64 n = p_t.cross(p_s);
+ Point64 m = (*p_prev->target - *p_next->reverse->target).cross(*p_next->target - *p_next->reverse->target);
+ CHULL_ASSERT(!m.is_zero());
+ int64_t dot = n.dot(m);
+ CHULL_ASSERT(dot != 0);
+ return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
+ }
+ return COUNTER_CLOCKWISE;
+ } else if (p_prev->prev == p_next) {
+ return CLOCKWISE;
+ } else {
+ return NONE;
+ }
+}
+
+ConvexHullInternal::Edge *ConvexHullInternal::find_max_angle(bool p_ccw, const Vertex *p_start, const Point32 &p_s, const Point64 &p_rxs, const Point64 &p_sxrxs, Rational64 &p_min_cot) {
+ Edge *min_edge = nullptr;
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("find max edge for %d\n", p_start->point.index);
+#endif
+ Edge *e = p_start->edges;
+ if (e) {
+ do {
+ if (e->copy > merge_stamp) {
+ Point32 t = *e->target - *p_start;
+ Rational64 cot(t.dot(p_sxrxs), t.dot(p_rxs));
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Angle is %f (%d) for ", Math::atan(cot.to_scalar()), (int32_t)cot.is_nan());
+ e->print();
+#endif
+ if (cot.is_nan()) {
+ CHULL_ASSERT(p_ccw ? (t.dot(p_s) < 0) : (t.dot(p_s) > 0));
+ } else {
+ int32_t cmp;
+ if (min_edge == nullptr) {
+ p_min_cot = cot;
+ min_edge = e;
+ } else if ((cmp = cot.compare(p_min_cot)) < 0) {
+ p_min_cot = cot;
+ min_edge = e;
+ } else if ((cmp == 0) && (p_ccw == (get_orientation(min_edge, e, p_s, t) == COUNTER_CLOCKWISE))) {
+ min_edge = e;
+ }
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n");
+#endif
+ }
+ e = e->next;
+ } while (e != p_start->edges);
+ }
+ return min_edge;
+}
+
+void ConvexHullInternal::find_edge_for_coplanar_faces(Vertex *p_c0, Vertex *p_c1, Edge *&p_e0, Edge *&p_e1, Vertex *p_stop0, Vertex *p_stop1) {
+ Edge *start0 = p_e0;
+ Edge *start1 = p_e1;
+ Point32 et0 = start0 ? start0->target->point : p_c0->point;
+ Point32 et1 = start1 ? start1->target->point : p_c1->point;
+ Point32 s = p_c1->point - p_c0->point;
+ Point64 normal = ((start0 ? start0 : start1)->target->point - p_c0->point).cross(s);
+ int64_t dist = p_c0->point.dot(normal);
+ CHULL_ASSERT(!start1 || (start1->target->point.dot(normal) == dist));
+ Point64 perp = s.cross(normal);
+ CHULL_ASSERT(!perp.is_zero());
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Advancing %d %d (%p %p, %d %d)\n", p_c0->point.index, p_c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
+#endif
+
+ int64_t max_dot0 = et0.dot(perp);
+ if (p_e0) {
+ while (p_e0->target != p_stop0) {
+ Edge *e = p_e0->reverse->prev;
+ if (e->target->point.dot(normal) < dist) {
+ break;
+ }
+ CHULL_ASSERT(e->target->point.dot(normal) == dist);
+ if (e->copy == merge_stamp) {
+ break;
+ }
+ int64_t dot = e->target->point.dot(perp);
+ if (dot <= max_dot0) {
+ break;
+ }
+ max_dot0 = dot;
+ p_e0 = e;
+ et0 = e->target->point;
+ }
+ }
+
+ int64_t max_dot1 = et1.dot(perp);
+ if (p_e1) {
+ while (p_e1->target != p_stop1) {
+ Edge *e = p_e1->reverse->next;
+ if (e->target->point.dot(normal) < dist) {
+ break;
+ }
+ CHULL_ASSERT(e->target->point.dot(normal) == dist);
+ if (e->copy == merge_stamp) {
+ break;
+ }
+ int64_t dot = e->target->point.dot(perp);
+ if (dot <= max_dot1) {
+ break;
+ }
+ max_dot1 = dot;
+ p_e1 = e;
+ et1 = e->target->point;
+ }
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Starting at %d %d\n", et0.index, et1.index);
+#endif
+
+ int64_t dx = max_dot1 - max_dot0;
+ if (dx > 0) {
+ while (true) {
+ int64_t dy = (et1 - et0).dot(s);
+
+ if (p_e0 && (p_e0->target != p_stop0)) {
+ Edge *f0 = p_e0->next->reverse;
+ if (f0->copy > merge_stamp) {
+ int64_t dx0 = (f0->target->point - et0).dot(perp);
+ int64_t dy0 = (f0->target->point - et0).dot(s);
+ if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0))) {
+ et0 = f0->target->point;
+ dx = (et1 - et0).dot(perp);
+ p_e0 = (p_e0 == start0) ? nullptr : f0;
+ continue;
+ }
+ }
+ }
+
+ if (p_e1 && (p_e1->target != p_stop1)) {
+ Edge *f1 = p_e1->reverse->next;
+ if (f1->copy > merge_stamp) {
+ Point32 d1 = f1->target->point - et1;
+ if (d1.dot(normal) == 0) {
+ int64_t dx1 = d1.dot(perp);
+ int64_t dy1 = d1.dot(s);
+ int64_t dxn = (f1->target->point - et0).dot(perp);
+ if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0)))) {
+ p_e1 = f1;
+ et1 = p_e1->target->point;
+ dx = dxn;
+ continue;
+ }
+ } else {
+ CHULL_ASSERT((p_e1 == start1) && (d1.dot(normal) < 0));
+ }
+ }
+ }
+
+ break;
+ }
+ } else if (dx < 0) {
+ while (true) {
+ int64_t dy = (et1 - et0).dot(s);
+
+ if (p_e1 && (p_e1->target != p_stop1)) {
+ Edge *f1 = p_e1->prev->reverse;
+ if (f1->copy > merge_stamp) {
+ int64_t dx1 = (f1->target->point - et1).dot(perp);
+ int64_t dy1 = (f1->target->point - et1).dot(s);
+ if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0))) {
+ et1 = f1->target->point;
+ dx = (et1 - et0).dot(perp);
+ p_e1 = (p_e1 == start1) ? nullptr : f1;
+ continue;
+ }
+ }
+ }
+
+ if (p_e0 && (p_e0->target != p_stop0)) {
+ Edge *f0 = p_e0->reverse->prev;
+ if (f0->copy > merge_stamp) {
+ Point32 d0 = f0->target->point - et0;
+ if (d0.dot(normal) == 0) {
+ int64_t dx0 = d0.dot(perp);
+ int64_t dy0 = d0.dot(s);
+ int64_t dxn = (et1 - f0->target->point).dot(perp);
+ if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0)))) {
+ p_e0 = f0;
+ et0 = p_e0->target->point;
+ dx = dxn;
+ continue;
+ }
+ } else {
+ CHULL_ASSERT((p_e0 == start0) && (d0.dot(normal) < 0));
+ }
+ }
+ }
+
+ break;
+ }
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Advanced edges to %d %d\n", et0.index, et1.index);
+#endif
+}
+
+void ConvexHullInternal::merge(IntermediateHull &p_h0, IntermediateHull &p_h1) {
+ if (!p_h1.max_xy) {
+ return;
+ }
+ if (!p_h0.max_xy) {
+ p_h0 = p_h1;
+ return;
+ }
+
+ merge_stamp--;
+
+ Vertex *c0 = nullptr;
+ Edge *to_prev0 = nullptr;
+ Edge *first_new0 = nullptr;
+ Edge *pending_head0 = nullptr;
+ Edge *pending_tail0 = nullptr;
+ Vertex *c1 = nullptr;
+ Edge *to_prev1 = nullptr;
+ Edge *first_new1 = nullptr;
+ Edge *pending_head1 = nullptr;
+ Edge *pending_tail1 = nullptr;
+ Point32 prev_point;
+
+ if (merge_projection(p_h0, p_h1, c0, c1)) {
+ Point32 s = *c1 - *c0;
+ Point64 normal = Point32(0, 0, -1).cross(s);
+ Point64 t = s.cross(normal);
+ CHULL_ASSERT(!t.is_zero());
+
+ Edge *e = c0->edges;
+ Edge *start0 = nullptr;
+ if (e) {
+ do {
+ int64_t dot = (*e->target - *c0).dot(normal);
+ CHULL_ASSERT(dot <= 0);
+ if ((dot == 0) && ((*e->target - *c0).dot(t) > 0)) {
+ if (!start0 || (get_orientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE)) {
+ start0 = e;
+ }
+ }
+ e = e->next;
+ } while (e != c0->edges);
+ }
+
+ e = c1->edges;
+ Edge *start1 = nullptr;
+ if (e) {
+ do {
+ int64_t dot = (*e->target - *c1).dot(normal);
+ CHULL_ASSERT(dot <= 0);
+ if ((dot == 0) && ((*e->target - *c1).dot(t) > 0)) {
+ if (!start1 || (get_orientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE)) {
+ start1 = e;
+ }
+ }
+ e = e->next;
+ } while (e != c1->edges);
+ }
+
+ if (start0 || start1) {
+ find_edge_for_coplanar_faces(c0, c1, start0, start1, nullptr, nullptr);
+ if (start0) {
+ c0 = start0->target;
+ }
+ if (start1) {
+ c1 = start1->target;
+ }
+ }
+
+ prev_point = c1->point;
+ prev_point.z++;
+ } else {
+ prev_point = c1->point;
+ prev_point.x++;
+ }
+
+ Vertex *first0 = c0;
+ Vertex *first1 = c1;
+ bool first_run = true;
+
+ while (true) {
+ Point32 s = *c1 - *c0;
+ Point32 r = prev_point - c0->point;
+ Point64 rxs = r.cross(s);
+ Point64 sxrxs = s.cross(rxs);
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
+#endif
+ Rational64 min_cot0(0, 0);
+ Edge *min0 = find_max_angle(false, c0, s, rxs, sxrxs, min_cot0);
+ Rational64 min_cot1(0, 0);
+ Edge *min1 = find_max_angle(true, c1, s, rxs, sxrxs, min_cot1);
+ if (!min0 && !min1) {
+ Edge *e = new_edge_pair(c0, c1);
+ e->link(e);
+ c0->edges = e;
+
+ e = e->reverse;
+ e->link(e);
+ c1->edges = e;
+ return;
+ } else {
+ int32_t cmp = !min0 ? 1 : !min1 ? -1 :
+ min_cot0.compare(min_cot1);
+#ifdef DEBUG_CONVEX_HULL
+ printf(" -> Result %d\n", cmp);
+#endif
+ if (first_run || ((cmp >= 0) ? !min_cot1.is_negative_infinity() : !min_cot0.is_negative_infinity())) {
+ Edge *e = new_edge_pair(c0, c1);
+ if (pending_tail0) {
+ pending_tail0->prev = e;
+ } else {
+ pending_head0 = e;
+ }
+ e->next = pending_tail0;
+ pending_tail0 = e;
+
+ e = e->reverse;
+ if (pending_tail1) {
+ pending_tail1->next = e;
+ } else {
+ pending_head1 = e;
+ }
+ e->prev = pending_tail1;
+ pending_tail1 = e;
+ }
+
+ Edge *e0 = min0;
+ Edge *e1 = min1;
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
+#endif
+
+ if (cmp == 0) {
+ find_edge_for_coplanar_faces(c0, c1, e0, e1, nullptr, nullptr);
+ }
+
+ if ((cmp >= 0) && e1) {
+ if (to_prev1) {
+ for (Edge *e = to_prev1->next, *n = nullptr; e != min1; e = n) {
+ n = e->next;
+ remove_edge_pair(e);
+ }
+ }
+
+ if (pending_tail1) {
+ if (to_prev1) {
+ to_prev1->link(pending_head1);
+ } else {
+ min1->prev->link(pending_head1);
+ first_new1 = pending_head1;
+ }
+ pending_tail1->link(min1);
+ pending_head1 = nullptr;
+ pending_tail1 = nullptr;
+ } else if (!to_prev1) {
+ first_new1 = min1;
+ }
+
+ prev_point = c1->point;
+ c1 = e1->target;
+ to_prev1 = e1->reverse;
+ }
+
+ if ((cmp <= 0) && e0) {
+ if (to_prev0) {
+ for (Edge *e = to_prev0->prev, *n = nullptr; e != min0; e = n) {
+ n = e->prev;
+ remove_edge_pair(e);
+ }
+ }
+
+ if (pending_tail0) {
+ if (to_prev0) {
+ pending_head0->link(to_prev0);
+ } else {
+ pending_head0->link(min0->next);
+ first_new0 = pending_head0;
+ }
+ min0->link(pending_tail0);
+ pending_head0 = nullptr;
+ pending_tail0 = nullptr;
+ } else if (!to_prev0) {
+ first_new0 = min0;
+ }
+
+ prev_point = c0->point;
+ c0 = e0->target;
+ to_prev0 = e0->reverse;
+ }
+ }
+
+ if ((c0 == first0) && (c1 == first1)) {
+ if (to_prev0 == nullptr) {
+ pending_head0->link(pending_tail0);
+ c0->edges = pending_tail0;
+ } else {
+ for (Edge *e = to_prev0->prev, *n = nullptr; e != first_new0; e = n) {
+ n = e->prev;
+ remove_edge_pair(e);
+ }
+ if (pending_tail0) {
+ pending_head0->link(to_prev0);
+ first_new0->link(pending_tail0);
+ }
+ }
+
+ if (to_prev1 == nullptr) {
+ pending_tail1->link(pending_head1);
+ c1->edges = pending_tail1;
+ } else {
+ for (Edge *e = to_prev1->next, *n = nullptr; e != first_new1; e = n) {
+ n = e->next;
+ remove_edge_pair(e);
+ }
+ if (pending_tail1) {
+ to_prev1->link(pending_head1);
+ pending_tail1->link(first_new1);
+ }
+ }
+
+ return;
+ }
+
+ first_run = false;
+ }
+}
+
+struct PointComparator {
+ _FORCE_INLINE_ bool operator()(const ConvexHullInternal::Point32 &p, const ConvexHullInternal::Point32 &q) const {
+ return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+ }
+};
+
+void ConvexHullInternal::compute(const Vector3 *p_coords, int32_t p_count) {
+ AABB aabb;
+ for (int32_t i = 0; i < p_count; i++) {
+ Vector3 p = p_coords[i];
+ if (i == 0) {
+ aabb.position = p;
+ } else {
+ aabb.expand_to(p);
+ }
+ }
+
+ Vector3 s = aabb.size;
+ max_axis = s.max_axis();
+ min_axis = s.min_axis();
+ if (min_axis == max_axis) {
+ min_axis = (max_axis + 1) % 3;
+ }
+ med_axis = 3 - max_axis - min_axis;
+
+ s /= real_t(10216);
+ if (((med_axis + 1) % 3) != max_axis) {
+ s *= -1;
+ }
+ scaling = s;
+
+ if (s[0] != 0) {
+ s[0] = real_t(1) / s[0];
+ }
+ if (s[1] != 0) {
+ s[1] = real_t(1) / s[1];
+ }
+ if (s[2] != 0) {
+ s[2] = real_t(1) / s[2];
+ }
+
+ center = aabb.position;
+
+ LocalVector<Point32> points;
+ points.resize(p_count);
+ for (int32_t i = 0; i < p_count; i++) {
+ Vector3 p = p_coords[i];
+ p = (p - center) * s;
+ points[i].x = (int32_t)p[med_axis];
+ points[i].y = (int32_t)p[max_axis];
+ points[i].z = (int32_t)p[min_axis];
+ points[i].index = i;
+ }
+
+ points.sort_custom<PointComparator>();
+
+ vertex_pool.reset(true);
+ original_vertices.resize(p_count);
+ for (int32_t i = 0; i < p_count; i++) {
+ Vertex *v = vertex_pool.alloc();
+ v->edges = nullptr;
+ v->point = points[i];
+ v->copy = -1;
+ original_vertices[i] = v;
+ }
+
+ points.clear();
+
+ edge_pool.reset(true);
+
+ used_edge_pairs = 0;
+ max_used_edge_pairs = 0;
+
+ merge_stamp = -3;
+
+ IntermediateHull hull;
+ compute_internal(0, p_count, hull);
+ vertex_list = hull.min_xy;
+#ifdef DEBUG_CONVEX_HULL
+ printf("max. edges %d (3v = %d)", max_used_edge_pairs, 3 * p_count);
+#endif
+}
+
+Vector3 ConvexHullInternal::to_gd_vector(const Point32 &p_v) {
+ Vector3 p;
+ p[med_axis] = real_t(p_v.x);
+ p[max_axis] = real_t(p_v.y);
+ p[min_axis] = real_t(p_v.z);
+ return p * scaling;
+}
+
+Vector3 ConvexHullInternal::get_gd_normal(Face *p_face) {
+ return to_gd_vector(p_face->dir0).cross(to_gd_vector(p_face->dir1)).normalized();
+}
+
+Vector3 ConvexHullInternal::get_coordinates(const Vertex *p_v) {
+ Vector3 p;
+ p[med_axis] = p_v->xvalue();
+ p[max_axis] = p_v->yvalue();
+ p[min_axis] = p_v->zvalue();
+ return p * scaling + center;
+}
+
+real_t ConvexHullInternal::shrink(real_t p_amount, real_t p_clamp_amount) {
+ if (!vertex_list) {
+ return 0;
+ }
+ int32_t stamp = --merge_stamp;
+ LocalVector<Vertex *> stack;
+ vertex_list->copy = stamp;
+ stack.push_back(vertex_list);
+ LocalVector<Face *> faces;
+
+ Point32 ref = vertex_list->point;
+ Int128 hull_center_x(0, 0);
+ Int128 hull_center_y(0, 0);
+ Int128 hull_center_z(0, 0);
+ Int128 volume(0, 0);
+
+ while (stack.size() > 0) {
+ Vertex *v = stack[stack.size() - 1];
+ stack.remove(stack.size() - 1);
+ Edge *e = v->edges;
+ if (e) {
+ do {
+ if (e->target->copy != stamp) {
+ e->target->copy = stamp;
+ stack.push_back(e->target);
+ }
+ if (e->copy != stamp) {
+ Face *face = face_pool.alloc();
+ face->init(e->target, e->reverse->prev->target, v);
+ faces.push_back(face);
+ Edge *f = e;
+
+ Vertex *a = nullptr;
+ Vertex *b = nullptr;
+ do {
+ if (a && b) {
+ int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
+ CHULL_ASSERT(vol >= 0);
+ Point32 c = v->point + a->point + b->point + ref;
+ hull_center_x += vol * c.x;
+ hull_center_y += vol * c.y;
+ hull_center_z += vol * c.z;
+ volume += vol;
+ }
+
+ CHULL_ASSERT(f->copy != stamp);
+ f->copy = stamp;
+ f->face = face;
+
+ a = b;
+ b = f->target;
+
+ f = f->reverse->prev;
+ } while (f != e);
+ }
+ e = e->next;
+ } while (e != v->edges);
+ }
+ }
+
+ if (volume.get_sign() <= 0) {
+ return 0;
+ }
+
+ Vector3 hull_center;
+ hull_center[med_axis] = hull_center_x.to_scalar();
+ hull_center[max_axis] = hull_center_y.to_scalar();
+ hull_center[min_axis] = hull_center_z.to_scalar();
+ hull_center /= 4 * volume.to_scalar();
+ hull_center *= scaling;
+
+ int32_t face_count = faces.size();
+
+ if (p_clamp_amount > 0) {
+ real_t min_dist = FLT_MAX;
+ for (int32_t i = 0; i < face_count; i++) {
+ Vector3 normal = get_gd_normal(faces[i]);
+ real_t dist = normal.dot(to_gd_vector(faces[i]->origin) - hull_center);
+ if (dist < min_dist) {
+ min_dist = dist;
+ }
+ }
+
+ if (min_dist <= 0) {
+ return 0;
+ }
+
+ p_amount = MIN(p_amount, min_dist * p_clamp_amount);
+ }
+
+ uint32_t seed = 243703;
+ for (int32_t i = 0; i < face_count; i++, seed = 1664525 * seed + 1013904223) {
+ SWAP(faces[i], faces[seed % face_count]);
+ }
+
+ for (int32_t i = 0; i < face_count; i++) {
+ if (!shift_face(faces[i], p_amount, stack)) {
+ return -p_amount;
+ }
+ }
+
+ return p_amount;
+}
+
+bool ConvexHullInternal::shift_face(Face *p_face, real_t p_amount, LocalVector<Vertex *> p_stack) {
+ Vector3 orig_shift = get_gd_normal(p_face) * -p_amount;
+ if (scaling[0] != 0) {
+ orig_shift[0] /= scaling[0];
+ }
+ if (scaling[1] != 0) {
+ orig_shift[1] /= scaling[1];
+ }
+ if (scaling[2] != 0) {
+ orig_shift[2] /= scaling[2];
+ }
+ Point32 shift((int32_t)orig_shift[med_axis], (int32_t)orig_shift[max_axis], (int32_t)orig_shift[min_axis]);
+ if (shift.is_zero()) {
+ return true;
+ }
+ Point64 normal = p_face->get_normal();
+#ifdef DEBUG_CONVEX_HULL
+ printf("\nShrinking p_face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
+ p_face->origin.x, p_face->origin.y, p_face->origin.z, p_face->dir0.x, p_face->dir0.y, p_face->dir0.z, p_face->dir1.x, p_face->dir1.y, p_face->dir1.z, shift.x, shift.y, shift.z);
+#endif
+ int64_t orig_dot = p_face->origin.dot(normal);
+ Point32 shifted_origin = p_face->origin + shift;
+ int64_t shifted_dot = shifted_origin.dot(normal);
+ CHULL_ASSERT(shifted_dot <= orig_dot);
+ if (shifted_dot >= orig_dot) {
+ return false;
+ }
+
+ Edge *intersection = nullptr;
+
+ Edge *start_edge = p_face->nearby_vertex->edges;
+#ifdef DEBUG_CONVEX_HULL
+ printf("Start edge is ");
+ start_edge->print();
+ printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shifted_dot);
+#endif
+ Rational128 opt_dot = p_face->nearby_vertex->dot(normal);
+ int32_t cmp = opt_dot.compare(shifted_dot);
+#ifdef SHOW_ITERATIONS
+ int32_t n = 0;
+#endif
+ if (cmp >= 0) {
+ Edge *e = start_edge;
+ do {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ Rational128 dot = e->target->dot(normal);
+ CHULL_ASSERT(dot.compare(orig_dot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Moving downwards, edge is ");
+ e->print();
+ printf(", dot is %f (%f %lld)\n", (float)dot.to_scalar(), (float)opt_dot.to_scalar(), shifted_dot);
+#endif
+ if (dot.compare(opt_dot) < 0) {
+ int32_t c = dot.compare(shifted_dot);
+ opt_dot = dot;
+ e = e->reverse;
+ start_edge = e;
+ if (c < 0) {
+ intersection = e;
+ break;
+ }
+ cmp = c;
+ }
+ e = e->prev;
+ } while (e != start_edge);
+
+ if (!intersection) {
+ return false;
+ }
+ } else {
+ Edge *e = start_edge;
+ do {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ Rational128 dot = e->target->dot(normal);
+ CHULL_ASSERT(dot.compare(orig_dot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Moving upwards, edge is ");
+ e->print();
+ printf(", dot is %f (%f %lld)\n", (float)dot.to_scalar(), (float)opt_dot.to_scalar(), shifted_dot);
+#endif
+ if (dot.compare(opt_dot) > 0) {
+ cmp = dot.compare(shifted_dot);
+ if (cmp >= 0) {
+ intersection = e;
+ break;
+ }
+ opt_dot = dot;
+ e = e->reverse;
+ start_edge = e;
+ }
+ e = e->prev;
+ } while (e != start_edge);
+
+ if (!intersection) {
+ return true;
+ }
+ }
+
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to find initial intersection\n", n);
+#endif
+
+ if (cmp == 0) {
+ Edge *e = intersection->reverse->next;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (e->target->dot(normal).compare(shifted_dot) <= 0) {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ e = e->next;
+ if (e == intersection->reverse) {
+ return true;
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("Checking for outwards edge, current edge is ");
+ e->print();
+ printf("\n");
+#endif
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to check for complete containment\n", n);
+#endif
+ }
+
+ Edge *first_intersection = nullptr;
+ Edge *face_edge = nullptr;
+ Edge *first_face_edge = nullptr;
+
+#ifdef SHOW_ITERATIONS
+ int32_t m = 0;
+#endif
+ while (true) {
+#ifdef SHOW_ITERATIONS
+ m++;
+#endif
+#ifdef DEBUG_CONVEX_HULL
+ printf("Intersecting edge is ");
+ intersection->print();
+ printf("\n");
+#endif
+ if (cmp == 0) {
+ Edge *e = intersection->reverse->next;
+ start_edge = e;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (true) {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ if (e->target->dot(normal).compare(shifted_dot) >= 0) {
+ break;
+ }
+ intersection = e->reverse;
+ e = e->next;
+ if (e == start_edge) {
+ return true;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to advance intersection\n", n);
+#endif
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("Advanced intersecting edge to ");
+ intersection->print();
+ printf(", cmp = %d\n", cmp);
+#endif
+
+ if (!first_intersection) {
+ first_intersection = intersection;
+ } else if (intersection == first_intersection) {
+ break;
+ }
+
+ int32_t prev_cmp = cmp;
+ Edge *prev_intersection = intersection;
+ Edge *prev_face_edge = face_edge;
+
+ Edge *e = intersection->reverse;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (true) {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ e = e->reverse->prev;
+ CHULL_ASSERT(e != intersection->reverse);
+ cmp = e->target->dot(normal).compare(shifted_dot);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Testing edge ");
+ e->print();
+ printf(" -> cmp = %d\n", cmp);
+#endif
+ if (cmp >= 0) {
+ intersection = e;
+ break;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to find other intersection of p_face\n", n);
+#endif
+
+ if (cmp > 0) {
+ Vertex *removed = intersection->target;
+ e = intersection->reverse;
+ if (e->prev == e) {
+ removed->edges = nullptr;
+ } else {
+ removed->edges = e->prev;
+ e->prev->link(e->next);
+ e->link(e);
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+
+ Point64 n0 = intersection->face->get_normal();
+ Point64 n1 = intersection->reverse->face->get_normal();
+ int64_t m00 = p_face->dir0.dot(n0);
+ int64_t m01 = p_face->dir1.dot(n0);
+ int64_t m10 = p_face->dir0.dot(n1);
+ int64_t m11 = p_face->dir1.dot(n1);
+ int64_t r0 = (intersection->face->origin - shifted_origin).dot(n0);
+ int64_t r1 = (intersection->reverse->face->origin - shifted_origin).dot(n1);
+ Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
+ CHULL_ASSERT(det.get_sign() != 0);
+ Vertex *v = vertex_pool.alloc();
+ v->point.index = -1;
+ v->copy = -1;
+ v->point128 = PointR128(Int128::mul(p_face->dir0.x * r0, m11) - Int128::mul(p_face->dir0.x * r1, m01) + Int128::mul(p_face->dir1.x * r1, m00) - Int128::mul(p_face->dir1.x * r0, m10) + det * shifted_origin.x,
+ Int128::mul(p_face->dir0.y * r0, m11) - Int128::mul(p_face->dir0.y * r1, m01) + Int128::mul(p_face->dir1.y * r1, m00) - Int128::mul(p_face->dir1.y * r0, m10) + det * shifted_origin.y,
+ Int128::mul(p_face->dir0.z * r0, m11) - Int128::mul(p_face->dir0.z * r1, m01) + Int128::mul(p_face->dir1.z * r1, m00) - Int128::mul(p_face->dir1.z * r0, m10) + det * shifted_origin.z,
+ det);
+ v->point.x = (int32_t)v->point128.xvalue();
+ v->point.y = (int32_t)v->point128.yvalue();
+ v->point.z = (int32_t)v->point128.zvalue();
+ intersection->target = v;
+ v->edges = e;
+
+ p_stack.push_back(v);
+ p_stack.push_back(removed);
+ p_stack.push_back(nullptr);
+ }
+
+ if (cmp || prev_cmp || (prev_intersection->reverse->next->target != intersection->target)) {
+ face_edge = new_edge_pair(prev_intersection->target, intersection->target);
+ if (prev_cmp == 0) {
+ face_edge->link(prev_intersection->reverse->next);
+ }
+ if ((prev_cmp == 0) || prev_face_edge) {
+ prev_intersection->reverse->link(face_edge);
+ }
+ if (cmp == 0) {
+ intersection->reverse->prev->link(face_edge->reverse);
+ }
+ face_edge->reverse->link(intersection->reverse);
+ } else {
+ face_edge = prev_intersection->reverse->next;
+ }
+
+ if (prev_face_edge) {
+ if (prev_cmp > 0) {
+ face_edge->link(prev_face_edge->reverse);
+ } else if (face_edge != prev_face_edge->reverse) {
+ p_stack.push_back(prev_face_edge->target);
+ while (face_edge->next != prev_face_edge->reverse) {
+ Vertex *removed = face_edge->next->target;
+ remove_edge_pair(face_edge->next);
+ p_stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+ printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+ }
+ p_stack.push_back(nullptr);
+ }
+ }
+ face_edge->face = p_face;
+ face_edge->reverse->face = intersection->face;
+
+ if (!first_face_edge) {
+ first_face_edge = face_edge;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to process all intersections\n", m);
+#endif
+
+ if (cmp > 0) {
+ first_face_edge->reverse->target = face_edge->target;
+ first_intersection->reverse->link(first_face_edge);
+ first_face_edge->link(face_edge->reverse);
+ } else if (first_face_edge != face_edge->reverse) {
+ p_stack.push_back(face_edge->target);
+ while (first_face_edge->next != face_edge->reverse) {
+ Vertex *removed = first_face_edge->next->target;
+ remove_edge_pair(first_face_edge->next);
+ p_stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+ printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+ }
+ p_stack.push_back(nullptr);
+ }
+
+ CHULL_ASSERT(p_stack.size() > 0);
+ vertex_list = p_stack[0];
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("Removing part\n");
+#endif
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ uint32_t pos = 0;
+ while (pos < p_stack.size()) {
+ uint32_t end = p_stack.size();
+ while (pos < end) {
+ Vertex *kept = p_stack[pos++];
+#ifdef DEBUG_CONVEX_HULL
+ kept->print();
+#endif
+ bool deeper = false;
+ Vertex *removed;
+ while ((removed = p_stack[pos++]) != nullptr) {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ kept->receive_nearby_faces(removed);
+ while (removed->edges) {
+ if (!deeper) {
+ deeper = true;
+ p_stack.push_back(kept);
+ }
+ p_stack.push_back(removed->edges->target);
+ remove_edge_pair(removed->edges);
+ }
+ }
+ if (deeper) {
+ p_stack.push_back(nullptr);
+ }
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to remove part\n", n);
+#endif
+
+ p_stack.resize(0);
+ p_face->origin = shifted_origin;
+
+ return true;
+}
+
+static int32_t get_vertex_copy(ConvexHullInternal::Vertex *p_vertex, LocalVector<ConvexHullInternal::Vertex *> &p_vertices) {
+ int32_t index = p_vertex->copy;
+ if (index < 0) {
+ index = p_vertices.size();
+ p_vertex->copy = index;
+ p_vertices.push_back(p_vertex);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Vertex %d gets index *%d\n", p_vertex->point.index, index);
+#endif
+ }
+ return index;
+}
+
+real_t ConvexHullComputer::compute(const Vector3 *p_coords, int32_t p_count, real_t p_shrink, real_t p_shrink_clamp) {
+ if (p_count <= 0) {
+ vertices.clear();
+ edges.clear();
+ faces.clear();
+ return 0;
+ }
+
+ ConvexHullInternal hull;
+ hull.compute(p_coords, p_count);
+
+ real_t shift = 0;
+ if ((p_shrink > 0) && ((shift = hull.shrink(p_shrink, p_shrink_clamp)) < 0)) {
+ vertices.clear();
+ edges.clear();
+ faces.clear();
+ return shift;
+ }
+
+ vertices.resize(0);
+ edges.resize(0);
+ faces.resize(0);
+
+ LocalVector<ConvexHullInternal::Vertex *> old_vertices;
+ get_vertex_copy(hull.vertex_list, old_vertices);
+ int32_t copied = 0;
+ while (copied < (int32_t)old_vertices.size()) {
+ ConvexHullInternal::Vertex *v = old_vertices[copied];
+ vertices.push_back(hull.get_coordinates(v));
+ ConvexHullInternal::Edge *first_edge = v->edges;
+ if (first_edge) {
+ int32_t first_copy = -1;
+ int32_t prev_copy = -1;
+ ConvexHullInternal::Edge *e = first_edge;
+ do {
+ if (e->copy < 0) {
+ int32_t s = edges.size();
+ edges.push_back(Edge());
+ edges.push_back(Edge());
+ Edge *c = &edges[s];
+ Edge *r = &edges[s + 1];
+ e->copy = s;
+ e->reverse->copy = s + 1;
+ c->reverse = 1;
+ r->reverse = -1;
+ c->target_vertex = get_vertex_copy(e->target, old_vertices);
+ r->target_vertex = copied;
+#ifdef DEBUG_CONVEX_HULL
+ printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->get_target_vertex());
+#endif
+ }
+ if (prev_copy >= 0) {
+ edges[e->copy].next = prev_copy - e->copy;
+ } else {
+ first_copy = e->copy;
+ }
+ prev_copy = e->copy;
+ e = e->next;
+ } while (e != first_edge);
+ edges[first_copy].next = prev_copy - first_copy;
+ }
+ copied++;
+ }
+
+ for (int32_t i = 0; i < copied; i++) {
+ ConvexHullInternal::Vertex *v = old_vertices[i];
+ ConvexHullInternal::Edge *first_edge = v->edges;
+ if (first_edge) {
+ ConvexHullInternal::Edge *e = first_edge;
+ do {
+ if (e->copy >= 0) {
+#ifdef DEBUG_CONVEX_HULL
+ printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].get_target_vertex());
+#endif
+ faces.push_back(e->copy);
+ ConvexHullInternal::Edge *f = e;
+ do {
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Face *%d\n", edges[f->copy].get_target_vertex());
+#endif
+ f->copy = -1;
+ f = f->reverse->prev;
+ } while (f != e);
+ }
+ e = e->next;
+ } while (e != first_edge);
+ }
+ }
+
+ return shift;
+}
+
+Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_mesh) {
+ r_mesh = Geometry3D::MeshData(); // clear
+
+ if (p_points.size() == 0) {
+ return FAILED; // matches QuickHull
+ }
+
+ ConvexHullComputer ch;
+ ch.compute(p_points.ptr(), p_points.size(), -1.0, -1.0);
+
+ r_mesh.vertices = ch.vertices;
+
+ r_mesh.edges.resize(ch.edges.size());
+ for (uint32_t i = 0; i < ch.edges.size(); i++) {
+ r_mesh.edges.write[i].a = (&ch.edges[i])->get_source_vertex();
+ r_mesh.edges.write[i].b = (&ch.edges[i])->get_target_vertex();
+ }
+
+ r_mesh.faces.resize(ch.faces.size());
+ for (uint32_t i = 0; i < ch.faces.size(); i++) {
+ const Edge *e_start = &ch.edges[ch.faces[i]];
+ const Edge *e = e_start;
+ Geometry3D::MeshData::Face &face = r_mesh.faces.write[i];
+
+ do {
+ face.indices.push_back(e->get_target_vertex());
+
+ e = e->get_next_edge_of_face();
+ } while (e != e_start);
+
+ // compute normal
+ if (face.indices.size() >= 3) {
+ face.plane = Plane(r_mesh.vertices[face.indices[0]], r_mesh.vertices[face.indices[2]], r_mesh.vertices[face.indices[1]]);
+ } else {
+ WARN_PRINT("Too few vertices per face.");
+ }
+ }
+
+ return OK;
+}
diff --git a/core/math/convex_hull.h b/core/math/convex_hull.h
new file mode 100644
index 0000000000..ba7be9c5e8
--- /dev/null
+++ b/core/math/convex_hull.h
@@ -0,0 +1,112 @@
+/*************************************************************************/
+/* convex_hull.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+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.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONVEX_HULL_H
+#define CONVEX_HULL_H
+
+#include "core/math/geometry_3d.h"
+#include "core/math/vector3.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/vector.h"
+
+/// Convex hull implementation based on Preparata and Hong
+/// See http://code.google.com/p/bullet/issues/detail?id=275
+/// Ole Kniemeyer, MAXON Computer GmbH
+class ConvexHullComputer {
+public:
+ class Edge {
+ private:
+ int32_t next = 0;
+ int32_t reverse = 0;
+ int32_t target_vertex = 0;
+
+ friend class ConvexHullComputer;
+
+ public:
+ int32_t get_source_vertex() const {
+ return (this + reverse)->target_vertex;
+ }
+
+ int32_t get_target_vertex() const {
+ return target_vertex;
+ }
+
+ const Edge *get_next_edge_of_vertex() const // clockwise list of all edges of a vertex
+ {
+ return this + next;
+ }
+
+ const Edge *get_next_edge_of_face() const // counter-clockwise list of all edges of a face
+ {
+ return (this + reverse)->get_next_edge_of_vertex();
+ }
+
+ const Edge *get_reverse_edge() const {
+ return this + reverse;
+ }
+ };
+
+ // Vertices of the output hull
+ Vector<Vector3> vertices;
+
+ // Edges of the output hull
+ LocalVector<Edge> edges;
+
+ // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+ LocalVector<int32_t> faces;
+
+ /*
+ Compute convex hull of "count" vertices stored in "coords".
+ If "shrink" is positive, the convex hull is shrunken by that amount (each face is moved by "shrink" length units
+ towards the center along its normal).
+ If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
+ is the minimum distance of a face to the center of the convex hull.
+ The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
+ that the resulting convex hull is empty.
+ The output convex hull can be found in the member variables "vertices", "edges", "faces".
+ */
+ real_t compute(const Vector3 *p_coords, int32_t p_count, real_t p_shrink, real_t p_shrink_clamp);
+
+ static Error convex_hull(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_mesh);
+};
+
+#endif // CONVEX_HULL_H
diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h
index 25cc1125db..6f7209556e 100644
--- a/core/math/delaunay_3d.h
+++ b/core/math/delaunay_3d.h
@@ -31,10 +31,10 @@
#ifndef DELAUNAY_3D_H
#define DELAUNAY_3D_H
+#include "core/io/file_access.h"
#include "core/math/aabb.h"
#include "core/math/camera_matrix.h"
#include "core/math/vector3.h"
-#include "core/os/file_access.h"
#include "core/string/print_string.h"
#include "core/templates/local_vector.h"
#include "core/templates/oa_hash_map.h"
diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp
index 200095d8cb..8e596f0f9d 100644
--- a/core/math/dynamic_bvh.cpp
+++ b/core/math/dynamic_bvh.cpp
@@ -312,8 +312,11 @@ void DynamicBVH::optimize_incremental(int passes) {
if (passes < 0) {
passes = total_leaves;
}
- if (bvh_root && (passes > 0)) {
+ if (passes > 0) {
do {
+ if (!bvh_root) {
+ break;
+ }
Node *node = bvh_root;
unsigned bit = 0;
while (node->is_internal()) {
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index f7ac44d321..0146c345f0 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -33,7 +33,7 @@
#include "core/io/marshalls.h"
#include "core/math/math_funcs.h"
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
diff --git a/core/math/expression.h b/core/math/expression.h
index a6b288ed6e..aecf662d0a 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -31,10 +31,10 @@
#ifndef EXPRESSION_H
#define EXPRESSION_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class Expression : public Reference {
- GDCLASS(Expression, Reference);
+class Expression : public RefCounted {
+ GDCLASS(Expression, RefCounted);
private:
struct Input {
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index 20c316c322..9af3f868d2 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -230,7 +230,7 @@ bool Face3::intersects_aabb(const AABB &p_aabb) const {
real_t minA, maxA, minB, maxB;
p_aabb.project_range_in_plane(Plane(axis, 0), minA, maxA);
- project_range(axis, Transform(), minB, maxB);
+ project_range(axis, Transform3D(), minB, maxB);
if (maxA < minB || maxB < minA) {
return false;
@@ -244,7 +244,7 @@ Face3::operator String() const {
return String() + vertex[0] + ", " + vertex[1] + ", " + vertex[2];
}
-void Face3::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void Face3::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
for (int i = 0; i < 3; i++) {
Vector3 v = p_transform.xform(vertex[i]);
real_t d = p_normal.dot(v);
@@ -259,7 +259,7 @@ void Face3::project_range(const Vector3 &p_normal, const Transform &p_transform,
}
}
-void Face3::get_support(const Vector3 &p_normal, const Transform &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const {
+void Face3::get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const {
#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.98
#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.05
diff --git a/core/math/face3.h b/core/math/face3.h
index 2e86b0a904..5091b338ef 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -33,7 +33,7 @@
#include "core/math/aabb.h"
#include "core/math/plane.h"
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include "core/math/vector3.h"
class Face3 {
@@ -74,8 +74,8 @@ public:
ClockDirection get_clock_dir() const; ///< todo, test if this is returning the proper clockwisity
- void get_support(const Vector3 &p_normal, const Transform &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const;
- void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ void get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const;
+ void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
AABB get_aabb() const {
AABB aabb(vertex[0], Vector3());
diff --git a/core/math/math_fieldwise.cpp b/core/math/math_fieldwise.cpp
index 0985a727f2..570c57e254 100644
--- a/core/math/math_fieldwise.cpp
+++ b/core/math/math_fieldwise.cpp
@@ -88,8 +88,8 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
- case Variant::QUAT: {
- SETUP_TYPE(Quat)
+ case Variant::QUATERNION: {
+ SETUP_TYPE(Quaternion)
/**/ TRY_TRANSFER_FIELD("x", x)
else TRY_TRANSFER_FIELD("y", y)
@@ -141,8 +141,8 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
- case Variant::TRANSFORM: {
- SETUP_TYPE(Transform)
+ case Variant::TRANSFORM3D: {
+ SETUP_TYPE(Transform3D)
/**/ TRY_TRANSFER_FIELD("xx", basis.elements[0][0])
else TRY_TRANSFER_FIELD("xy", basis.elements[0][1])
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index c0d7649b65..3389407e72 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -275,8 +275,8 @@ public:
static _ALWAYS_INLINE_ double db2linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); }
static _ALWAYS_INLINE_ float db2linear(float p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); }
- static _ALWAYS_INLINE_ double round(double p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
- static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
+ static _ALWAYS_INLINE_ double round(double p_val) { return ::round(p_val); }
+ static _ALWAYS_INLINE_ float round(float p_val) { return ::roundf(p_val); }
static _ALWAYS_INLINE_ int64_t wrapi(int64_t value, int64_t min, int64_t max) {
int64_t range = max - min;
@@ -311,20 +311,20 @@ public:
static float random(float from, float to);
static int random(int from, int to);
- static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) {
+ static _ALWAYS_INLINE_ bool is_equal_approx(float a, float b) {
// Check for exact equality first, required to handle "infinity" values.
if (a == b) {
return true;
}
// Then check for approximate equality.
- real_t tolerance = CMP_EPSILON * abs(a);
+ float tolerance = CMP_EPSILON * abs(a);
if (tolerance < CMP_EPSILON) {
tolerance = CMP_EPSILON;
}
return abs(a - b) < tolerance;
}
- static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b, real_t tolerance) {
+ static _ALWAYS_INLINE_ bool is_equal_approx(float a, float b, float tolerance) {
// Check for exact equality first, required to handle "infinity" values.
if (a == b) {
return true;
@@ -333,7 +333,33 @@ public:
return abs(a - b) < tolerance;
}
- static _ALWAYS_INLINE_ bool is_zero_approx(real_t s) {
+ static _ALWAYS_INLINE_ bool is_zero_approx(float s) {
+ return abs(s) < CMP_EPSILON;
+ }
+
+ static _ALWAYS_INLINE_ bool is_equal_approx(double a, double b) {
+ // Check for exact equality first, required to handle "infinity" values.
+ if (a == b) {
+ return true;
+ }
+ // Then check for approximate equality.
+ double tolerance = CMP_EPSILON * abs(a);
+ if (tolerance < CMP_EPSILON) {
+ tolerance = CMP_EPSILON;
+ }
+ return abs(a - b) < tolerance;
+ }
+
+ static _ALWAYS_INLINE_ bool is_equal_approx(double a, double b, double tolerance) {
+ // Check for exact equality first, required to handle "infinity" values.
+ if (a == b) {
+ return true;
+ }
+ // Then check for approximate equality.
+ return abs(a - b) < tolerance;
+ }
+
+ static _ALWAYS_INLINE_ bool is_zero_approx(double s) {
return abs(s) < CMP_EPSILON;
}
@@ -358,28 +384,10 @@ public:
return u.d;
}
- //this function should be as fast as possible and rounding mode should not matter
+ // This function should be as fast as possible and rounding mode should not matter.
static _ALWAYS_INLINE_ int fast_ftoi(float a) {
- static int b;
-
-#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone?
- b = (int)((a > 0.0) ? (a + 0.5) : (a - 0.5));
-
-#elif defined(_MSC_VER) && _MSC_VER < 1800
- __asm fld a __asm fistp b
- /*#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
- // use AT&T inline assembly style, document that
- // we use memory as output (=m) and input (m)
- __asm__ __volatile__ (
- "flds %1 \n\t"
- "fistpl %0 \n\t"
- : "=m" (b)
- : "m" (a));*/
-
-#else
- b = lrintf(a); //assuming everything but msvc 2012 or earlier has lrint
-#endif
- return b;
+ // Assuming every supported compiler has `lrint()`.
+ return lrintf(a);
}
static _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h) {
diff --git a/core/math/plane.cpp b/core/math/plane.cpp
index f1d3bbbd54..3c78b55b90 100644
--- a/core/math/plane.cpp
+++ b/core/math/plane.cpp
@@ -175,5 +175,5 @@ bool Plane::is_equal_approx(const Plane &p_plane) const {
}
Plane::operator String() const {
- return normal.operator String() + ", " + rtos(d);
+ return "[N: " + normal.operator String() + ", D: " + String::num_real(d, false) + "]";
}
diff --git a/core/math/quat.cpp b/core/math/quat.cpp
deleted file mode 100644
index 6f13e04027..0000000000
--- a/core/math/quat.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-/*************************************************************************/
-/* quat.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "quat.h"
-
-#include "core/math/basis.h"
-#include "core/string/print_string.h"
-
-// get_euler_xyz returns a vector containing the Euler angles in the format
-// (ax,ay,az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// This implementation uses XYZ convention (Z is the first rotation).
-Vector3 Quat::get_euler_xyz() const {
- Basis m(*this);
- return m.get_euler_xyz();
-}
-
-// get_euler_yxz returns a vector containing the Euler angles in the format
-// (ax,ay,az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// This implementation uses YXZ convention (Z is the first rotation).
-Vector3 Quat::get_euler_yxz() const {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
-#endif
- Basis m(*this);
- return m.get_euler_yxz();
-}
-
-void Quat::operator*=(const Quat &p_q) {
- real_t xx = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y;
- real_t yy = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z;
- real_t zz = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x;
- w = w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z;
- x = xx;
- y = yy;
- z = zz;
-}
-
-Quat Quat::operator*(const Quat &p_q) const {
- Quat r = *this;
- r *= p_q;
- return r;
-}
-
-bool Quat::is_equal_approx(const Quat &p_quat) const {
- return Math::is_equal_approx(x, p_quat.x) && Math::is_equal_approx(y, p_quat.y) && Math::is_equal_approx(z, p_quat.z) && Math::is_equal_approx(w, p_quat.w);
-}
-
-real_t Quat::length() const {
- return Math::sqrt(length_squared());
-}
-
-void Quat::normalize() {
- *this /= length();
-}
-
-Quat Quat::normalized() const {
- return *this / length();
-}
-
-bool Quat::is_normalized() const {
- return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); //use less epsilon
-}
-
-Quat Quat::inverse() const {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quat(), "The quaternion must be normalized.");
-#endif
- return Quat(-x, -y, -z, w);
-}
-
-Quat Quat::slerp(const Quat &p_to, const real_t &p_weight) const {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quat(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quat(), "The end quaternion must be normalized.");
-#endif
- Quat to1;
- real_t omega, cosom, sinom, scale0, scale1;
-
- // calc cosine
- cosom = dot(p_to);
-
- // adjust signs (if necessary)
- if (cosom < 0.0) {
- cosom = -cosom;
- to1.x = -p_to.x;
- to1.y = -p_to.y;
- to1.z = -p_to.z;
- to1.w = -p_to.w;
- } else {
- to1.x = p_to.x;
- to1.y = p_to.y;
- to1.z = p_to.z;
- to1.w = p_to.w;
- }
-
- // calculate coefficients
-
- if ((1.0 - cosom) > CMP_EPSILON) {
- // standard case (slerp)
- omega = Math::acos(cosom);
- sinom = Math::sin(omega);
- scale0 = Math::sin((1.0 - p_weight) * omega) / sinom;
- scale1 = Math::sin(p_weight * omega) / sinom;
- } else {
- // "from" and "to" quaternions are very close
- // ... so we can do a linear interpolation
- scale0 = 1.0 - p_weight;
- scale1 = p_weight;
- }
- // calculate final values
- return Quat(
- scale0 * x + scale1 * to1.x,
- scale0 * y + scale1 * to1.y,
- scale0 * z + scale1 * to1.z,
- scale0 * w + scale1 * to1.w);
-}
-
-Quat Quat::slerpni(const Quat &p_to, const real_t &p_weight) const {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quat(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quat(), "The end quaternion must be normalized.");
-#endif
- const Quat &from = *this;
-
- real_t dot = from.dot(p_to);
-
- if (Math::absf(dot) > 0.9999) {
- return from;
- }
-
- real_t theta = Math::acos(dot),
- sinT = 1.0 / Math::sin(theta),
- newFactor = Math::sin(p_weight * theta) * sinT,
- invFactor = Math::sin((1.0 - p_weight) * theta) * sinT;
-
- return Quat(invFactor * from.x + newFactor * p_to.x,
- invFactor * from.y + newFactor * p_to.y,
- invFactor * from.z + newFactor * p_to.z,
- invFactor * from.w + newFactor * p_to.w);
-}
-
-Quat Quat::cubic_slerp(const Quat &p_b, const Quat &p_pre_a, const Quat &p_post_b, const real_t &p_weight) const {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quat(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quat(), "The end quaternion must be normalized.");
-#endif
- //the only way to do slerp :|
- real_t t2 = (1.0 - p_weight) * p_weight * 2;
- Quat sp = this->slerp(p_b, p_weight);
- Quat sq = p_pre_a.slerpni(p_post_b, p_weight);
- return sp.slerpni(sq, t2);
-}
-
-Quat::operator String() const {
- return String::num(x) + ", " + String::num(y) + ", " + String::num(z) + ", " + String::num(w);
-}
-
-Quat::Quat(const Vector3 &p_axis, real_t p_angle) {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
-#endif
- real_t d = p_axis.length();
- if (d == 0) {
- x = 0;
- y = 0;
- z = 0;
- w = 0;
- } else {
- real_t sin_angle = Math::sin(p_angle * 0.5);
- real_t cos_angle = Math::cos(p_angle * 0.5);
- real_t s = sin_angle / d;
- x = p_axis.x * s;
- y = p_axis.y * s;
- z = p_axis.z * s;
- w = cos_angle;
- }
-}
-
-// Euler constructor expects a vector containing the Euler angles in the format
-// (ax, ay, az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// This implementation uses YXZ convention (Z is the first rotation).
-Quat::Quat(const Vector3 &p_euler) {
- real_t half_a1 = p_euler.y * 0.5;
- real_t half_a2 = p_euler.x * 0.5;
- real_t half_a3 = p_euler.z * 0.5;
-
- // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
- // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
- // a3 is the angle of the first rotation, following the notation in this reference.
-
- real_t cos_a1 = Math::cos(half_a1);
- real_t sin_a1 = Math::sin(half_a1);
- real_t cos_a2 = Math::cos(half_a2);
- real_t sin_a2 = Math::sin(half_a2);
- real_t cos_a3 = Math::cos(half_a3);
- real_t sin_a3 = Math::sin(half_a3);
-
- x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
- y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
- z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
- w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
-}
diff --git a/core/math/quat.h b/core/math/quat.h
deleted file mode 100644
index 9db914fe52..0000000000
--- a/core/math/quat.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*************************************************************************/
-/* quat.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-// Circular dependency between Vector3 and Basis :/
-#include "core/math/vector3.h"
-
-#ifndef QUAT_H
-#define QUAT_H
-
-#include "core/math/math_defs.h"
-#include "core/math/math_funcs.h"
-#include "core/string/ustring.h"
-
-class Quat {
-public:
- union {
- struct {
- real_t x;
- real_t y;
- real_t z;
- real_t w;
- };
- real_t components[4] = { 0, 0, 0, 1.0 };
- };
-
- _FORCE_INLINE_ real_t &operator[](int idx) {
- return components[idx];
- }
- _FORCE_INLINE_ const real_t &operator[](int idx) const {
- return components[idx];
- }
- _FORCE_INLINE_ real_t length_squared() const;
- bool is_equal_approx(const Quat &p_quat) const;
- real_t length() const;
- void normalize();
- Quat normalized() const;
- bool is_normalized() const;
- Quat inverse() const;
- _FORCE_INLINE_ real_t dot(const Quat &p_q) const;
-
- Vector3 get_euler_xyz() const;
- Vector3 get_euler_yxz() const;
- Vector3 get_euler() const { return get_euler_yxz(); };
-
- Quat slerp(const Quat &p_to, const real_t &p_weight) const;
- Quat slerpni(const Quat &p_to, const real_t &p_weight) const;
- Quat cubic_slerp(const Quat &p_b, const Quat &p_pre_a, const Quat &p_post_b, const real_t &p_weight) const;
-
- _FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
- r_angle = 2 * Math::acos(w);
- real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
- r_axis.x = x * r;
- r_axis.y = y * r;
- r_axis.z = z * r;
- }
-
- void operator*=(const Quat &p_q);
- Quat operator*(const Quat &p_q) const;
-
- Quat operator*(const Vector3 &v) const {
- return Quat(w * v.x + y * v.z - z * v.y,
- w * v.y + z * v.x - x * v.z,
- w * v.z + x * v.y - y * v.x,
- -x * v.x - y * v.y - z * v.z);
- }
-
- _FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
-#endif
- Vector3 u(x, y, z);
- Vector3 uv = u.cross(v);
- return v + ((uv * w) + u.cross(uv)) * ((real_t)2);
- }
-
- _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &v) const {
- return inverse().xform(v);
- }
-
- _FORCE_INLINE_ void operator+=(const Quat &p_q);
- _FORCE_INLINE_ void operator-=(const Quat &p_q);
- _FORCE_INLINE_ void operator*=(const real_t &s);
- _FORCE_INLINE_ void operator/=(const real_t &s);
- _FORCE_INLINE_ Quat operator+(const Quat &q2) const;
- _FORCE_INLINE_ Quat operator-(const Quat &q2) const;
- _FORCE_INLINE_ Quat operator-() const;
- _FORCE_INLINE_ Quat operator*(const real_t &s) const;
- _FORCE_INLINE_ Quat operator/(const real_t &s) const;
-
- _FORCE_INLINE_ bool operator==(const Quat &p_quat) const;
- _FORCE_INLINE_ bool operator!=(const Quat &p_quat) const;
-
- operator String() const;
-
- _FORCE_INLINE_ Quat() {}
-
- _FORCE_INLINE_ Quat(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
- x(p_x),
- y(p_y),
- z(p_z),
- w(p_w) {
- }
-
- Quat(const Vector3 &p_axis, real_t p_angle);
-
- Quat(const Vector3 &p_euler);
-
- Quat(const Quat &p_q) :
- x(p_q.x),
- y(p_q.y),
- z(p_q.z),
- w(p_q.w) {
- }
-
- Quat &operator=(const Quat &p_q) {
- x = p_q.x;
- y = p_q.y;
- z = p_q.z;
- w = p_q.w;
- return *this;
- }
-
- Quat(const Vector3 &v0, const Vector3 &v1) // shortest arc
- {
- Vector3 c = v0.cross(v1);
- real_t d = v0.dot(v1);
-
- if (d < -1.0 + CMP_EPSILON) {
- x = 0;
- y = 1;
- z = 0;
- w = 0;
- } else {
- real_t s = Math::sqrt((1.0 + d) * 2.0);
- real_t rs = 1.0 / s;
-
- x = c.x * rs;
- y = c.y * rs;
- z = c.z * rs;
- w = s * 0.5;
- }
- }
-};
-
-real_t Quat::dot(const Quat &p_q) const {
- return x * p_q.x + y * p_q.y + z * p_q.z + w * p_q.w;
-}
-
-real_t Quat::length_squared() const {
- return dot(*this);
-}
-
-void Quat::operator+=(const Quat &p_q) {
- x += p_q.x;
- y += p_q.y;
- z += p_q.z;
- w += p_q.w;
-}
-
-void Quat::operator-=(const Quat &p_q) {
- x -= p_q.x;
- y -= p_q.y;
- z -= p_q.z;
- w -= p_q.w;
-}
-
-void Quat::operator*=(const real_t &s) {
- x *= s;
- y *= s;
- z *= s;
- w *= s;
-}
-
-void Quat::operator/=(const real_t &s) {
- *this *= 1.0 / s;
-}
-
-Quat Quat::operator+(const Quat &q2) const {
- const Quat &q1 = *this;
- return Quat(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
-}
-
-Quat Quat::operator-(const Quat &q2) const {
- const Quat &q1 = *this;
- return Quat(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
-}
-
-Quat Quat::operator-() const {
- const Quat &q2 = *this;
- return Quat(-q2.x, -q2.y, -q2.z, -q2.w);
-}
-
-Quat Quat::operator*(const real_t &s) const {
- return Quat(x * s, y * s, z * s, w * s);
-}
-
-Quat Quat::operator/(const real_t &s) const {
- return *this * (1.0 / s);
-}
-
-bool Quat::operator==(const Quat &p_quat) const {
- return x == p_quat.x && y == p_quat.y && z == p_quat.z && w == p_quat.w;
-}
-
-bool Quat::operator!=(const Quat &p_quat) const {
- return x != p_quat.x || y != p_quat.y || z != p_quat.z || w != p_quat.w;
-}
-
-_FORCE_INLINE_ Quat operator*(const real_t &p_real, const Quat &p_quat) {
- return p_quat * p_real;
-}
-
-#endif // QUAT_H
diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp
new file mode 100644
index 0000000000..7037db7112
--- /dev/null
+++ b/core/math/quaternion.cpp
@@ -0,0 +1,232 @@
+/*************************************************************************/
+/* quaternion.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "quaternion.h"
+
+#include "core/math/basis.h"
+#include "core/string/print_string.h"
+
+// get_euler_xyz returns a vector containing the Euler angles in the format
+// (ax,ay,az), where ax is the angle of rotation around x axis,
+// and similar for other axes.
+// This implementation uses XYZ convention (Z is the first rotation).
+Vector3 Quaternion::get_euler_xyz() const {
+ Basis m(*this);
+ return m.get_euler_xyz();
+}
+
+// get_euler_yxz returns a vector containing the Euler angles in the format
+// (ax,ay,az), where ax is the angle of rotation around x axis,
+// and similar for other axes.
+// This implementation uses YXZ convention (Z is the first rotation).
+Vector3 Quaternion::get_euler_yxz() const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
+#endif
+ Basis m(*this);
+ return m.get_euler_yxz();
+}
+
+void Quaternion::operator*=(const Quaternion &p_q) {
+ real_t xx = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y;
+ real_t yy = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z;
+ real_t zz = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x;
+ w = w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z;
+ x = xx;
+ y = yy;
+ z = zz;
+}
+
+Quaternion Quaternion::operator*(const Quaternion &p_q) const {
+ Quaternion r = *this;
+ r *= p_q;
+ return r;
+}
+
+bool Quaternion::is_equal_approx(const Quaternion &p_quaternion) const {
+ return Math::is_equal_approx(x, p_quaternion.x) && Math::is_equal_approx(y, p_quaternion.y) && Math::is_equal_approx(z, p_quaternion.z) && Math::is_equal_approx(w, p_quaternion.w);
+}
+
+real_t Quaternion::length() const {
+ return Math::sqrt(length_squared());
+}
+
+void Quaternion::normalize() {
+ *this /= length();
+}
+
+Quaternion Quaternion::normalized() const {
+ return *this / length();
+}
+
+bool Quaternion::is_normalized() const {
+ return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); //use less epsilon
+}
+
+Quaternion Quaternion::inverse() const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized.");
+#endif
+ return Quaternion(-x, -y, -z, w);
+}
+
+Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+#endif
+ Quaternion to1;
+ real_t omega, cosom, sinom, scale0, scale1;
+
+ // calc cosine
+ cosom = dot(p_to);
+
+ // adjust signs (if necessary)
+ if (cosom < 0.0) {
+ cosom = -cosom;
+ to1.x = -p_to.x;
+ to1.y = -p_to.y;
+ to1.z = -p_to.z;
+ to1.w = -p_to.w;
+ } else {
+ to1.x = p_to.x;
+ to1.y = p_to.y;
+ to1.z = p_to.z;
+ to1.w = p_to.w;
+ }
+
+ // calculate coefficients
+
+ if ((1.0 - cosom) > CMP_EPSILON) {
+ // standard case (slerp)
+ omega = Math::acos(cosom);
+ sinom = Math::sin(omega);
+ scale0 = Math::sin((1.0 - p_weight) * omega) / sinom;
+ scale1 = Math::sin(p_weight * omega) / sinom;
+ } else {
+ // "from" and "to" quaternions are very close
+ // ... so we can do a linear interpolation
+ scale0 = 1.0 - p_weight;
+ scale1 = p_weight;
+ }
+ // calculate final values
+ return Quaternion(
+ scale0 * x + scale1 * to1.x,
+ scale0 * y + scale1 * to1.y,
+ scale0 * z + scale1 * to1.z,
+ scale0 * w + scale1 * to1.w);
+}
+
+Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+#endif
+ const Quaternion &from = *this;
+
+ real_t dot = from.dot(p_to);
+
+ if (Math::absf(dot) > 0.9999) {
+ return from;
+ }
+
+ real_t theta = Math::acos(dot),
+ sinT = 1.0 / Math::sin(theta),
+ newFactor = Math::sin(p_weight * theta) * sinT,
+ invFactor = Math::sin((1.0 - p_weight) * theta) * sinT;
+
+ return Quaternion(invFactor * from.x + newFactor * p_to.x,
+ invFactor * from.y + newFactor * p_to.y,
+ invFactor * from.z + newFactor * p_to.z,
+ invFactor * from.w + newFactor * p_to.w);
+}
+
+Quaternion Quaternion::cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+#endif
+ //the only way to do slerp :|
+ real_t t2 = (1.0 - p_weight) * p_weight * 2;
+ Quaternion sp = this->slerp(p_b, p_weight);
+ Quaternion sq = p_pre_a.slerpni(p_post_b, p_weight);
+ return sp.slerpni(sq, t2);
+}
+
+Quaternion::operator String() const {
+ return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")";
+}
+
+Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
+#endif
+ real_t d = p_axis.length();
+ if (d == 0) {
+ x = 0;
+ y = 0;
+ z = 0;
+ w = 0;
+ } else {
+ real_t sin_angle = Math::sin(p_angle * 0.5);
+ real_t cos_angle = Math::cos(p_angle * 0.5);
+ real_t s = sin_angle / d;
+ x = p_axis.x * s;
+ y = p_axis.y * s;
+ z = p_axis.z * s;
+ w = cos_angle;
+ }
+}
+
+// Euler constructor expects a vector containing the Euler angles in the format
+// (ax, ay, az), where ax is the angle of rotation around x axis,
+// and similar for other axes.
+// This implementation uses YXZ convention (Z is the first rotation).
+Quaternion::Quaternion(const Vector3 &p_euler) {
+ real_t half_a1 = p_euler.y * 0.5;
+ real_t half_a2 = p_euler.x * 0.5;
+ real_t half_a3 = p_euler.z * 0.5;
+
+ // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
+ // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
+ // a3 is the angle of the first rotation, following the notation in this reference.
+
+ real_t cos_a1 = Math::cos(half_a1);
+ real_t sin_a1 = Math::sin(half_a1);
+ real_t cos_a2 = Math::cos(half_a2);
+ real_t sin_a2 = Math::sin(half_a2);
+ real_t cos_a3 = Math::cos(half_a3);
+ real_t sin_a3 = Math::sin(half_a3);
+
+ x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
+ y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
+ z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
+ w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
+}
diff --git a/core/math/quaternion.h b/core/math/quaternion.h
new file mode 100644
index 0000000000..796214b79e
--- /dev/null
+++ b/core/math/quaternion.h
@@ -0,0 +1,238 @@
+/*************************************************************************/
+/* quaternion.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef QUAT_H
+#define QUAT_H
+
+#include "core/math/math_defs.h"
+#include "core/math/math_funcs.h"
+#include "core/math/vector3.h"
+#include "core/string/ustring.h"
+
+class Quaternion {
+public:
+ union {
+ struct {
+ real_t x;
+ real_t y;
+ real_t z;
+ real_t w;
+ };
+ real_t components[4] = { 0, 0, 0, 1.0 };
+ };
+
+ _FORCE_INLINE_ real_t &operator[](int idx) {
+ return components[idx];
+ }
+ _FORCE_INLINE_ const real_t &operator[](int idx) const {
+ return components[idx];
+ }
+ _FORCE_INLINE_ real_t length_squared() const;
+ bool is_equal_approx(const Quaternion &p_quaternion) const;
+ real_t length() const;
+ void normalize();
+ Quaternion normalized() const;
+ bool is_normalized() const;
+ Quaternion inverse() const;
+ _FORCE_INLINE_ real_t dot(const Quaternion &p_q) const;
+
+ Vector3 get_euler_xyz() const;
+ Vector3 get_euler_yxz() const;
+ Vector3 get_euler() const { return get_euler_yxz(); };
+
+ Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const;
+ Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const;
+ Quaternion cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
+
+ _FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
+ r_angle = 2 * Math::acos(w);
+ real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
+ r_axis.x = x * r;
+ r_axis.y = y * r;
+ r_axis.z = z * r;
+ }
+
+ void operator*=(const Quaternion &p_q);
+ Quaternion operator*(const Quaternion &p_q) const;
+
+ Quaternion operator*(const Vector3 &v) const {
+ return Quaternion(w * v.x + y * v.z - z * v.y,
+ w * v.y + z * v.x - x * v.z,
+ w * v.z + x * v.y - y * v.x,
+ -x * v.x - y * v.y - z * v.z);
+ }
+
+ _FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
+#endif
+ Vector3 u(x, y, z);
+ Vector3 uv = u.cross(v);
+ return v + ((uv * w) + u.cross(uv)) * ((real_t)2);
+ }
+
+ _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &v) const {
+ return inverse().xform(v);
+ }
+
+ _FORCE_INLINE_ void operator+=(const Quaternion &p_q);
+ _FORCE_INLINE_ void operator-=(const Quaternion &p_q);
+ _FORCE_INLINE_ void operator*=(const real_t &s);
+ _FORCE_INLINE_ void operator/=(const real_t &s);
+ _FORCE_INLINE_ Quaternion operator+(const Quaternion &q2) const;
+ _FORCE_INLINE_ Quaternion operator-(const Quaternion &q2) const;
+ _FORCE_INLINE_ Quaternion operator-() const;
+ _FORCE_INLINE_ Quaternion operator*(const real_t &s) const;
+ _FORCE_INLINE_ Quaternion operator/(const real_t &s) const;
+
+ _FORCE_INLINE_ bool operator==(const Quaternion &p_quaternion) const;
+ _FORCE_INLINE_ bool operator!=(const Quaternion &p_quaternion) const;
+
+ operator String() const;
+
+ _FORCE_INLINE_ Quaternion() {}
+
+ _FORCE_INLINE_ Quaternion(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
+ x(p_x),
+ y(p_y),
+ z(p_z),
+ w(p_w) {
+ }
+
+ Quaternion(const Vector3 &p_axis, real_t p_angle);
+
+ Quaternion(const Vector3 &p_euler);
+
+ Quaternion(const Quaternion &p_q) :
+ x(p_q.x),
+ y(p_q.y),
+ z(p_q.z),
+ w(p_q.w) {
+ }
+
+ Quaternion &operator=(const Quaternion &p_q) {
+ x = p_q.x;
+ y = p_q.y;
+ z = p_q.z;
+ w = p_q.w;
+ return *this;
+ }
+
+ Quaternion(const Vector3 &v0, const Vector3 &v1) // shortest arc
+ {
+ Vector3 c = v0.cross(v1);
+ real_t d = v0.dot(v1);
+
+ if (d < -1.0 + CMP_EPSILON) {
+ x = 0;
+ y = 1;
+ z = 0;
+ w = 0;
+ } else {
+ real_t s = Math::sqrt((1.0 + d) * 2.0);
+ real_t rs = 1.0 / s;
+
+ x = c.x * rs;
+ y = c.y * rs;
+ z = c.z * rs;
+ w = s * 0.5;
+ }
+ }
+};
+
+real_t Quaternion::dot(const Quaternion &p_q) const {
+ return x * p_q.x + y * p_q.y + z * p_q.z + w * p_q.w;
+}
+
+real_t Quaternion::length_squared() const {
+ return dot(*this);
+}
+
+void Quaternion::operator+=(const Quaternion &p_q) {
+ x += p_q.x;
+ y += p_q.y;
+ z += p_q.z;
+ w += p_q.w;
+}
+
+void Quaternion::operator-=(const Quaternion &p_q) {
+ x -= p_q.x;
+ y -= p_q.y;
+ z -= p_q.z;
+ w -= p_q.w;
+}
+
+void Quaternion::operator*=(const real_t &s) {
+ x *= s;
+ y *= s;
+ z *= s;
+ w *= s;
+}
+
+void Quaternion::operator/=(const real_t &s) {
+ *this *= 1.0 / s;
+}
+
+Quaternion Quaternion::operator+(const Quaternion &q2) const {
+ const Quaternion &q1 = *this;
+ return Quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
+}
+
+Quaternion Quaternion::operator-(const Quaternion &q2) const {
+ const Quaternion &q1 = *this;
+ return Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
+}
+
+Quaternion Quaternion::operator-() const {
+ const Quaternion &q2 = *this;
+ return Quaternion(-q2.x, -q2.y, -q2.z, -q2.w);
+}
+
+Quaternion Quaternion::operator*(const real_t &s) const {
+ return Quaternion(x * s, y * s, z * s, w * s);
+}
+
+Quaternion Quaternion::operator/(const real_t &s) const {
+ return *this * (1.0 / s);
+}
+
+bool Quaternion::operator==(const Quaternion &p_quaternion) const {
+ return x == p_quaternion.x && y == p_quaternion.y && z == p_quaternion.z && w == p_quaternion.w;
+}
+
+bool Quaternion::operator!=(const Quaternion &p_quaternion) const {
+ return x != p_quaternion.x || y != p_quaternion.y || z != p_quaternion.z || w != p_quaternion.w;
+}
+
+_FORCE_INLINE_ Quaternion operator*(const real_t &p_real, const Quaternion &p_quaternion) {
+ return p_quaternion * p_real;
+}
+
+#endif // QUAT_H
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index fe18cc3d41..0d77bfe933 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -112,7 +112,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
}
}
- //fourth vertex is the one most further away from the plane
+ //fourth vertex is the one most further away from the plane
{
real_t maxd = 0;
diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h
index a396c2b7d7..06cd3999f3 100644
--- a/core/math/random_number_generator.h
+++ b/core/math/random_number_generator.h
@@ -32,10 +32,10 @@
#define RANDOM_NUMBER_GENERATOR_H
#include "core/math/random_pcg.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class RandomNumberGenerator : public Reference {
- GDCLASS(RandomNumberGenerator, Reference);
+class RandomNumberGenerator : public RefCounted {
+ GDCLASS(RandomNumberGenerator, RefCounted);
protected:
RandomPCG randbase;
diff --git a/core/math/rect2.cpp b/core/math/rect2.cpp
index 60c44999f7..f64bf560c8 100644
--- a/core/math/rect2.cpp
+++ b/core/math/rect2.cpp
@@ -263,3 +263,11 @@ next4:
return true;
}
+
+Rect2::operator String() const {
+ return "[P: " + position.operator String() + ", S: " + size + "]";
+}
+
+Rect2i::operator String() const {
+ return "[P: " + position.operator String() + ", S: " + size + "]";
+}
diff --git a/core/math/rect2.h b/core/math/rect2.h
index 1dc027cf72..ab0b489b4a 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -320,7 +320,7 @@ struct Rect2 {
return position + size;
}
- operator String() const { return String(position) + ", " + String(size); }
+ operator String() const;
Rect2() {}
Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
@@ -498,7 +498,7 @@ struct Rect2i {
return position + size;
}
- operator String() const { return String(position) + ", " + String(size); }
+ operator String() const;
operator Rect2() const { return Rect2(position, size); }
diff --git a/core/math/transform.cpp b/core/math/transform.cpp
deleted file mode 100644
index d4d7ff6d28..0000000000
--- a/core/math/transform.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/*************************************************************************/
-/* transform.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "transform.h"
-
-#include "core/math/math_funcs.h"
-#include "core/string/print_string.h"
-
-void Transform::affine_invert() {
- basis.invert();
- origin = basis.xform(-origin);
-}
-
-Transform Transform::affine_inverse() const {
- Transform ret = *this;
- ret.affine_invert();
- return ret;
-}
-
-void Transform::invert() {
- basis.transpose();
- origin = basis.xform(-origin);
-}
-
-Transform Transform::inverse() const {
- // FIXME: this function assumes the basis is a rotation matrix, with no scaling.
- // Transform::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
- Transform ret = *this;
- ret.invert();
- return ret;
-}
-
-void Transform::rotate(const Vector3 &p_axis, real_t p_phi) {
- *this = rotated(p_axis, p_phi);
-}
-
-Transform Transform::rotated(const Vector3 &p_axis, real_t p_phi) const {
- return Transform(Basis(p_axis, p_phi), Vector3()) * (*this);
-}
-
-void Transform::rotate_basis(const Vector3 &p_axis, real_t p_phi) {
- basis.rotate(p_axis, p_phi);
-}
-
-Transform Transform::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
- Transform t = *this;
- t.set_look_at(origin, p_target, p_up);
- return t;
-}
-
-void Transform::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND(p_eye == p_target);
- ERR_FAIL_COND(p_up.length() == 0);
-#endif
- // Reference: MESA source code
- Vector3 v_x, v_y, v_z;
-
- /* Make rotation matrix */
-
- /* Z vector */
- v_z = p_eye - p_target;
-
- v_z.normalize();
-
- v_y = p_up;
-
- v_x = v_y.cross(v_z);
-#ifdef MATH_CHECKS
- ERR_FAIL_COND(v_x.length() == 0);
-#endif
-
- /* Recompute Y = Z cross X */
- v_y = v_z.cross(v_x);
-
- v_x.normalize();
- v_y.normalize();
-
- basis.set(v_x, v_y, v_z);
-
- origin = p_eye;
-}
-
-Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) const {
- /* not sure if very "efficient" but good enough? */
-
- Vector3 src_scale = basis.get_scale();
- Quat src_rot = basis.get_rotation_quat();
- Vector3 src_loc = origin;
-
- Vector3 dst_scale = p_transform.basis.get_scale();
- Quat dst_rot = p_transform.basis.get_rotation_quat();
- Vector3 dst_loc = p_transform.origin;
-
- Transform interp;
- interp.basis.set_quat_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c));
- interp.origin = src_loc.lerp(dst_loc, p_c);
-
- return interp;
-}
-
-void Transform::scale(const Vector3 &p_scale) {
- basis.scale(p_scale);
- origin *= p_scale;
-}
-
-Transform Transform::scaled(const Vector3 &p_scale) const {
- Transform t = *this;
- t.scale(p_scale);
- return t;
-}
-
-void Transform::scale_basis(const Vector3 &p_scale) {
- basis.scale(p_scale);
-}
-
-void Transform::translate(real_t p_tx, real_t p_ty, real_t p_tz) {
- translate(Vector3(p_tx, p_ty, p_tz));
-}
-
-void Transform::translate(const Vector3 &p_translation) {
- for (int i = 0; i < 3; i++) {
- origin[i] += basis[i].dot(p_translation);
- }
-}
-
-Transform Transform::translated(const Vector3 &p_translation) const {
- Transform t = *this;
- t.translate(p_translation);
- return t;
-}
-
-void Transform::orthonormalize() {
- basis.orthonormalize();
-}
-
-Transform Transform::orthonormalized() const {
- Transform _copy = *this;
- _copy.orthonormalize();
- return _copy;
-}
-
-bool Transform::is_equal_approx(const Transform &p_transform) const {
- return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
-}
-
-bool Transform::operator==(const Transform &p_transform) const {
- return (basis == p_transform.basis && origin == p_transform.origin);
-}
-
-bool Transform::operator!=(const Transform &p_transform) const {
- return (basis != p_transform.basis || origin != p_transform.origin);
-}
-
-void Transform::operator*=(const Transform &p_transform) {
- origin = xform(p_transform.origin);
- basis *= p_transform.basis;
-}
-
-Transform Transform::operator*(const Transform &p_transform) const {
- Transform t = *this;
- t *= p_transform;
- return t;
-}
-
-Transform::operator String() const {
- return basis.operator String() + " - " + origin.operator String();
-}
-
-Transform::Transform(const Basis &p_basis, const Vector3 &p_origin) :
- basis(p_basis),
- origin(p_origin) {
-}
-
-Transform::Transform(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) :
- origin(p_origin) {
- basis.set_axis(0, p_x);
- basis.set_axis(1, p_y);
- basis.set_axis(2, p_z);
-}
-
-Transform::Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) {
- basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz);
- origin = Vector3(ox, oy, oz);
-}
diff --git a/core/math/transform.h b/core/math/transform.h
deleted file mode 100644
index 1c05dbe554..0000000000
--- a/core/math/transform.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/*************************************************************************/
-/* transform.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef TRANSFORM_H
-#define TRANSFORM_H
-
-#include "core/math/aabb.h"
-#include "core/math/basis.h"
-#include "core/math/plane.h"
-
-class Transform {
-public:
- Basis basis;
- Vector3 origin;
-
- void invert();
- Transform inverse() const;
-
- void affine_invert();
- Transform affine_inverse() const;
-
- Transform rotated(const Vector3 &p_axis, real_t p_phi) const;
-
- void rotate(const Vector3 &p_axis, real_t p_phi);
- void rotate_basis(const Vector3 &p_axis, real_t p_phi);
-
- void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
- Transform looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const;
-
- void scale(const Vector3 &p_scale);
- Transform scaled(const Vector3 &p_scale) const;
- void scale_basis(const Vector3 &p_scale);
- void translate(real_t p_tx, real_t p_ty, real_t p_tz);
- void translate(const Vector3 &p_translation);
- Transform translated(const Vector3 &p_translation) const;
-
- const Basis &get_basis() const { return basis; }
- void set_basis(const Basis &p_basis) { basis = p_basis; }
-
- const Vector3 &get_origin() const { return origin; }
- void set_origin(const Vector3 &p_origin) { origin = p_origin; }
-
- void orthonormalize();
- Transform orthonormalized() const;
- bool is_equal_approx(const Transform &p_transform) const;
-
- bool operator==(const Transform &p_transform) const;
- bool operator!=(const Transform &p_transform) const;
-
- _FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
- _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const;
-
- _FORCE_INLINE_ Plane xform(const Plane &p_plane) const;
- _FORCE_INLINE_ Plane xform_inv(const Plane &p_plane) const;
-
- _FORCE_INLINE_ AABB xform(const AABB &p_aabb) const;
- _FORCE_INLINE_ AABB xform_inv(const AABB &p_aabb) const;
-
- _FORCE_INLINE_ Vector<Vector3> xform(const Vector<Vector3> &p_array) const;
- _FORCE_INLINE_ Vector<Vector3> xform_inv(const Vector<Vector3> &p_array) const;
-
- void operator*=(const Transform &p_transform);
- Transform operator*(const Transform &p_transform) const;
-
- Transform interpolate_with(const Transform &p_transform, real_t p_c) const;
-
- _FORCE_INLINE_ Transform inverse_xform(const Transform &t) const {
- Vector3 v = t.origin - origin;
- return Transform(basis.transpose_xform(t.basis),
- basis.xform(v));
- }
-
- void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) {
- basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
- origin.x = tx;
- origin.y = ty;
- origin.z = tz;
- }
-
- operator String() const;
-
- Transform() {}
- Transform(const Basis &p_basis, const Vector3 &p_origin = Vector3());
- Transform(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin);
- Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz);
-};
-
-_FORCE_INLINE_ Vector3 Transform::xform(const Vector3 &p_vector) const {
- return Vector3(
- basis[0].dot(p_vector) + origin.x,
- basis[1].dot(p_vector) + origin.y,
- basis[2].dot(p_vector) + origin.z);
-}
-
-_FORCE_INLINE_ Vector3 Transform::xform_inv(const Vector3 &p_vector) const {
- Vector3 v = p_vector - origin;
-
- return Vector3(
- (basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z),
- (basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z),
- (basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z));
-}
-
-_FORCE_INLINE_ Plane Transform::xform(const Plane &p_plane) const {
- Vector3 point = p_plane.normal * p_plane.d;
- Vector3 point_dir = point + p_plane.normal;
- point = xform(point);
- point_dir = xform(point_dir);
-
- Vector3 normal = point_dir - point;
- normal.normalize();
- real_t d = normal.dot(point);
-
- return Plane(normal, d);
-}
-
-_FORCE_INLINE_ Plane Transform::xform_inv(const Plane &p_plane) const {
- Vector3 point = p_plane.normal * p_plane.d;
- Vector3 point_dir = point + p_plane.normal;
- point = xform_inv(point);
- point_dir = xform_inv(point_dir);
-
- Vector3 normal = point_dir - point;
- normal.normalize();
- real_t d = normal.dot(point);
-
- return Plane(normal, d);
-}
-
-_FORCE_INLINE_ AABB Transform::xform(const AABB &p_aabb) const {
- /* http://dev.theomader.com/transform-bounding-boxes/ */
- Vector3 min = p_aabb.position;
- Vector3 max = p_aabb.position + p_aabb.size;
- Vector3 tmin, tmax;
- for (int i = 0; i < 3; i++) {
- tmin[i] = tmax[i] = origin[i];
- for (int j = 0; j < 3; j++) {
- real_t e = basis[i][j] * min[j];
- real_t f = basis[i][j] * max[j];
- if (e < f) {
- tmin[i] += e;
- tmax[i] += f;
- } else {
- tmin[i] += f;
- tmax[i] += e;
- }
- }
- }
- AABB r_aabb;
- r_aabb.position = tmin;
- r_aabb.size = tmax - tmin;
- return r_aabb;
-}
-
-_FORCE_INLINE_ AABB Transform::xform_inv(const AABB &p_aabb) const {
- /* define vertices */
- Vector3 vertices[8] = {
- Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
- Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
- Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
- Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z),
- Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
- Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
- Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
- Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z)
- };
-
- AABB ret;
-
- ret.position = xform_inv(vertices[0]);
-
- for (int i = 1; i < 8; i++) {
- ret.expand_to(xform_inv(vertices[i]));
- }
-
- return ret;
-}
-
-Vector<Vector3> Transform::xform(const Vector<Vector3> &p_array) const {
- Vector<Vector3> array;
- array.resize(p_array.size());
-
- const Vector3 *r = p_array.ptr();
- Vector3 *w = array.ptrw();
-
- for (int i = 0; i < p_array.size(); ++i) {
- w[i] = xform(r[i]);
- }
- return array;
-}
-
-Vector<Vector3> Transform::xform_inv(const Vector<Vector3> &p_array) const {
- Vector<Vector3> array;
- array.resize(p_array.size());
-
- const Vector3 *r = p_array.ptr();
- Vector3 *w = array.ptrw();
-
- for (int i = 0; i < p_array.size(); ++i) {
- w[i] = xform_inv(r[i]);
- }
- return array;
-}
-
-#endif // TRANSFORM_H
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index 4a521b96ae..0140f31b8a 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -158,6 +158,13 @@ bool Transform2D::is_equal_approx(const Transform2D &p_transform) const {
return elements[0].is_equal_approx(p_transform.elements[0]) && elements[1].is_equal_approx(p_transform.elements[1]) && elements[2].is_equal_approx(p_transform.elements[2]);
}
+Transform2D Transform2D::looking_at(const Vector2 &p_target) const {
+ Transform2D return_trans = Transform2D(get_rotation(), get_origin());
+ Vector2 target_position = affine_inverse().xform(p_target);
+ return_trans.set_rotation(return_trans.get_rotation() + (target_position * get_scale()).angle());
+ return return_trans;
+}
+
bool Transform2D::operator==(const Transform2D &p_transform) const {
for (int i = 0; i < 3; i++) {
if (elements[i] != p_transform.elements[i]) {
@@ -270,5 +277,7 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t
}
Transform2D::operator String() const {
- return String(String() + elements[0] + ", " + elements[1] + ", " + elements[2]);
+ return "[X: " + elements[0].operator String() +
+ ", Y: " + elements[1].operator String() +
+ ", O: " + elements[2].operator String() + "]";
}
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index 327d0f244f..715f013701 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -100,6 +100,8 @@ struct Transform2D {
Transform2D orthonormalized() const;
bool is_equal_approx(const Transform2D &p_transform) const;
+ Transform2D looking_at(const Vector2 &p_target) const;
+
bool operator==(const Transform2D &p_transform) const;
bool operator!=(const Transform2D &p_transform) const;
diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp
new file mode 100644
index 0000000000..a34d998dde
--- /dev/null
+++ b/core/math/transform_3d.cpp
@@ -0,0 +1,215 @@
+/*************************************************************************/
+/* transform_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "transform_3d.h"
+
+#include "core/math/math_funcs.h"
+#include "core/string/print_string.h"
+
+void Transform3D::affine_invert() {
+ basis.invert();
+ origin = basis.xform(-origin);
+}
+
+Transform3D Transform3D::affine_inverse() const {
+ Transform3D ret = *this;
+ ret.affine_invert();
+ return ret;
+}
+
+void Transform3D::invert() {
+ basis.transpose();
+ origin = basis.xform(-origin);
+}
+
+Transform3D Transform3D::inverse() const {
+ // FIXME: this function assumes the basis is a rotation matrix, with no scaling.
+ // Transform3D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
+ Transform3D ret = *this;
+ ret.invert();
+ return ret;
+}
+
+void Transform3D::rotate(const Vector3 &p_axis, real_t p_phi) {
+ *this = rotated(p_axis, p_phi);
+}
+
+Transform3D Transform3D::rotated(const Vector3 &p_axis, real_t p_phi) const {
+ return Transform3D(Basis(p_axis, p_phi), Vector3()) * (*this);
+}
+
+void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_phi) {
+ basis.rotate(p_axis, p_phi);
+}
+
+Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
+ Transform3D t = *this;
+ t.set_look_at(origin, p_target, p_up);
+ return t;
+}
+
+void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND(p_eye == p_target);
+ ERR_FAIL_COND(p_up.length() == 0);
+#endif
+ // Reference: MESA source code
+ Vector3 v_x, v_y, v_z;
+
+ /* Make rotation matrix */
+
+ /* Z vector */
+ v_z = p_eye - p_target;
+
+ v_z.normalize();
+
+ v_y = p_up;
+
+ v_x = v_y.cross(v_z);
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND(v_x.length() == 0);
+#endif
+
+ /* Recompute Y = Z cross X */
+ v_y = v_z.cross(v_x);
+
+ v_x.normalize();
+ v_y.normalize();
+
+ basis.set(v_x, v_y, v_z);
+
+ origin = p_eye;
+}
+
+Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const {
+ /* not sure if very "efficient" but good enough? */
+
+ Vector3 src_scale = basis.get_scale();
+ Quaternion src_rot = basis.get_rotation_quaternion();
+ Vector3 src_loc = origin;
+
+ Vector3 dst_scale = p_transform.basis.get_scale();
+ Quaternion dst_rot = p_transform.basis.get_rotation_quaternion();
+ Vector3 dst_loc = p_transform.origin;
+
+ Transform3D interp;
+ interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c));
+ interp.origin = src_loc.lerp(dst_loc, p_c);
+
+ return interp;
+}
+
+void Transform3D::scale(const Vector3 &p_scale) {
+ basis.scale(p_scale);
+ origin *= p_scale;
+}
+
+Transform3D Transform3D::scaled(const Vector3 &p_scale) const {
+ Transform3D t = *this;
+ t.scale(p_scale);
+ return t;
+}
+
+void Transform3D::scale_basis(const Vector3 &p_scale) {
+ basis.scale(p_scale);
+}
+
+void Transform3D::translate(real_t p_tx, real_t p_ty, real_t p_tz) {
+ translate(Vector3(p_tx, p_ty, p_tz));
+}
+
+void Transform3D::translate(const Vector3 &p_translation) {
+ for (int i = 0; i < 3; i++) {
+ origin[i] += basis[i].dot(p_translation);
+ }
+}
+
+Transform3D Transform3D::translated(const Vector3 &p_translation) const {
+ Transform3D t = *this;
+ t.translate(p_translation);
+ return t;
+}
+
+void Transform3D::orthonormalize() {
+ basis.orthonormalize();
+}
+
+Transform3D Transform3D::orthonormalized() const {
+ Transform3D _copy = *this;
+ _copy.orthonormalize();
+ return _copy;
+}
+
+bool Transform3D::is_equal_approx(const Transform3D &p_transform) const {
+ return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
+}
+
+bool Transform3D::operator==(const Transform3D &p_transform) const {
+ return (basis == p_transform.basis && origin == p_transform.origin);
+}
+
+bool Transform3D::operator!=(const Transform3D &p_transform) const {
+ return (basis != p_transform.basis || origin != p_transform.origin);
+}
+
+void Transform3D::operator*=(const Transform3D &p_transform) {
+ origin = xform(p_transform.origin);
+ basis *= p_transform.basis;
+}
+
+Transform3D Transform3D::operator*(const Transform3D &p_transform) const {
+ Transform3D t = *this;
+ t *= p_transform;
+ return t;
+}
+
+Transform3D::operator String() const {
+ return "[X: " + basis.get_axis(0).operator String() +
+ ", Y: " + basis.get_axis(1).operator String() +
+ ", Z: " + basis.get_axis(2).operator String() +
+ ", O: " + origin.operator String() + "]";
+}
+
+Transform3D::Transform3D(const Basis &p_basis, const Vector3 &p_origin) :
+ basis(p_basis),
+ origin(p_origin) {
+}
+
+Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) :
+ origin(p_origin) {
+ basis.set_axis(0, p_x);
+ basis.set_axis(1, p_y);
+ basis.set_axis(2, p_z);
+}
+
+Transform3D::Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) {
+ basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz);
+ origin = Vector3(ox, oy, oz);
+}
diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h
new file mode 100644
index 0000000000..078a2ca11a
--- /dev/null
+++ b/core/math/transform_3d.h
@@ -0,0 +1,232 @@
+/*************************************************************************/
+/* transform_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TRANSFORM_H
+#define TRANSFORM_H
+
+#include "core/math/aabb.h"
+#include "core/math/basis.h"
+#include "core/math/plane.h"
+
+class Transform3D {
+public:
+ Basis basis;
+ Vector3 origin;
+
+ void invert();
+ Transform3D inverse() const;
+
+ void affine_invert();
+ Transform3D affine_inverse() const;
+
+ Transform3D rotated(const Vector3 &p_axis, real_t p_phi) const;
+
+ void rotate(const Vector3 &p_axis, real_t p_phi);
+ void rotate_basis(const Vector3 &p_axis, real_t p_phi);
+
+ void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
+ Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const;
+
+ void scale(const Vector3 &p_scale);
+ Transform3D scaled(const Vector3 &p_scale) const;
+ void scale_basis(const Vector3 &p_scale);
+ void translate(real_t p_tx, real_t p_ty, real_t p_tz);
+ void translate(const Vector3 &p_translation);
+ Transform3D translated(const Vector3 &p_translation) const;
+
+ const Basis &get_basis() const { return basis; }
+ void set_basis(const Basis &p_basis) { basis = p_basis; }
+
+ const Vector3 &get_origin() const { return origin; }
+ void set_origin(const Vector3 &p_origin) { origin = p_origin; }
+
+ void orthonormalize();
+ Transform3D orthonormalized() const;
+ bool is_equal_approx(const Transform3D &p_transform) const;
+
+ bool operator==(const Transform3D &p_transform) const;
+ bool operator!=(const Transform3D &p_transform) const;
+
+ _FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
+ _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const;
+
+ _FORCE_INLINE_ Plane xform(const Plane &p_plane) const;
+ _FORCE_INLINE_ Plane xform_inv(const Plane &p_plane) const;
+
+ _FORCE_INLINE_ AABB xform(const AABB &p_aabb) const;
+ _FORCE_INLINE_ AABB xform_inv(const AABB &p_aabb) const;
+
+ _FORCE_INLINE_ Vector<Vector3> xform(const Vector<Vector3> &p_array) const;
+ _FORCE_INLINE_ Vector<Vector3> xform_inv(const Vector<Vector3> &p_array) const;
+
+ void operator*=(const Transform3D &p_transform);
+ Transform3D operator*(const Transform3D &p_transform) const;
+
+ Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const;
+
+ _FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const {
+ Vector3 v = t.origin - origin;
+ return Transform3D(basis.transpose_xform(t.basis),
+ basis.xform(v));
+ }
+
+ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) {
+ basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
+ origin.x = tx;
+ origin.y = ty;
+ origin.z = tz;
+ }
+
+ operator String() const;
+
+ Transform3D() {}
+ Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3());
+ Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin);
+ Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz);
+};
+
+_FORCE_INLINE_ Vector3 Transform3D::xform(const Vector3 &p_vector) const {
+ return Vector3(
+ basis[0].dot(p_vector) + origin.x,
+ basis[1].dot(p_vector) + origin.y,
+ basis[2].dot(p_vector) + origin.z);
+}
+
+_FORCE_INLINE_ Vector3 Transform3D::xform_inv(const Vector3 &p_vector) const {
+ Vector3 v = p_vector - origin;
+
+ return Vector3(
+ (basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z),
+ (basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z),
+ (basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z));
+}
+
+_FORCE_INLINE_ Plane Transform3D::xform(const Plane &p_plane) const {
+ Vector3 point = p_plane.normal * p_plane.d;
+ Vector3 point_dir = point + p_plane.normal;
+ point = xform(point);
+ point_dir = xform(point_dir);
+
+ Vector3 normal = point_dir - point;
+ normal.normalize();
+ real_t d = normal.dot(point);
+
+ return Plane(normal, d);
+}
+
+_FORCE_INLINE_ Plane Transform3D::xform_inv(const Plane &p_plane) const {
+ Vector3 point = p_plane.normal * p_plane.d;
+ Vector3 point_dir = point + p_plane.normal;
+ point = xform_inv(point);
+ point_dir = xform_inv(point_dir);
+
+ Vector3 normal = point_dir - point;
+ normal.normalize();
+ real_t d = normal.dot(point);
+
+ return Plane(normal, d);
+}
+
+_FORCE_INLINE_ AABB Transform3D::xform(const AABB &p_aabb) const {
+ /* http://dev.theomader.com/transform-bounding-boxes/ */
+ Vector3 min = p_aabb.position;
+ Vector3 max = p_aabb.position + p_aabb.size;
+ Vector3 tmin, tmax;
+ for (int i = 0; i < 3; i++) {
+ tmin[i] = tmax[i] = origin[i];
+ for (int j = 0; j < 3; j++) {
+ real_t e = basis[i][j] * min[j];
+ real_t f = basis[i][j] * max[j];
+ if (e < f) {
+ tmin[i] += e;
+ tmax[i] += f;
+ } else {
+ tmin[i] += f;
+ tmax[i] += e;
+ }
+ }
+ }
+ AABB r_aabb;
+ r_aabb.position = tmin;
+ r_aabb.size = tmax - tmin;
+ return r_aabb;
+}
+
+_FORCE_INLINE_ AABB Transform3D::xform_inv(const AABB &p_aabb) const {
+ /* define vertices */
+ Vector3 vertices[8] = {
+ Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
+ Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
+ Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
+ Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z),
+ Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
+ Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
+ Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
+ Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z)
+ };
+
+ AABB ret;
+
+ ret.position = xform_inv(vertices[0]);
+
+ for (int i = 1; i < 8; i++) {
+ ret.expand_to(xform_inv(vertices[i]));
+ }
+
+ return ret;
+}
+
+Vector<Vector3> Transform3D::xform(const Vector<Vector3> &p_array) const {
+ Vector<Vector3> array;
+ array.resize(p_array.size());
+
+ const Vector3 *r = p_array.ptr();
+ Vector3 *w = array.ptrw();
+
+ for (int i = 0; i < p_array.size(); ++i) {
+ w[i] = xform(r[i]);
+ }
+ return array;
+}
+
+Vector<Vector3> Transform3D::xform_inv(const Vector<Vector3> &p_array) const {
+ Vector<Vector3> array;
+ array.resize(p_array.size());
+
+ const Vector3 *r = p_array.ptr();
+ Vector3 *w = array.ptrw();
+
+ for (int i = 0; i < p_array.size(); ++i) {
+ w[i] = xform_inv(r[i]);
+ }
+ return array;
+}
+
+#endif // TRANSFORM_H
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 23c0c686a2..903d5951a8 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -600,7 +600,7 @@ bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count,
const Vector3 *vertexptr = vertices.ptr();
const BVH *bvhptr = bvh.ptr();
- Transform scale(Basis().scaled(p_scale));
+ Transform3D scale(Basis().scaled(p_scale));
int pos = bvh.size() - 1;
diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h
index 1d1dbc114b..463b0dd5c8 100644
--- a/core/math/triangle_mesh.h
+++ b/core/math/triangle_mesh.h
@@ -32,10 +32,10 @@
#define TRIANGLE_MESH_H
#include "core/math/face3.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class TriangleMesh : public Reference {
- GDCLASS(TriangleMesh, Reference);
+class TriangleMesh : public RefCounted {
+ GDCLASS(TriangleMesh, RefCounted);
struct Triangle {
Vector3 normal;
diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp
index 5129ed336e..eb3301f5d0 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -59,7 +59,7 @@ Vector2 Vector2::normalized() const {
bool Vector2::is_normalized() const {
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
- return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
+ return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON);
}
real_t Vector2::distance_to(const Vector2 &p_vector2) const {
@@ -122,14 +122,20 @@ Vector2 Vector2::project(const Vector2 &p_to) const {
return p_to * (dot(p_to) / p_to.length_squared());
}
+Vector2 Vector2::clamp(const Vector2 &p_min, const Vector2 &p_max) const {
+ return Vector2(
+ CLAMP(x, p_min.x, p_max.x),
+ CLAMP(y, p_min.y, p_max.y));
+}
+
Vector2 Vector2::snapped(const Vector2 &p_step) const {
return Vector2(
Math::snapped(x, p_step.x),
Math::snapped(y, p_step.y));
}
-Vector2 Vector2::clamped(real_t p_len) const {
- real_t l = length();
+Vector2 Vector2::limit_length(const real_t p_len) const {
+ const real_t l = length();
Vector2 v = *this;
if (l > 0 && p_len < l) {
v /= l;
@@ -187,8 +193,18 @@ bool Vector2::is_equal_approx(const Vector2 &p_v) const {
return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y);
}
+Vector2::operator String() const {
+ return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")";
+}
+
/* Vector2i */
+Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const {
+ return Vector2i(
+ CLAMP(x, p_min.x, p_max.x),
+ CLAMP(y, p_min.y, p_max.y));
+}
+
Vector2i Vector2i::operator+(const Vector2i &p_v) const {
return Vector2i(x + p_v.x, y + p_v.y);
}
@@ -257,3 +273,7 @@ bool Vector2i::operator==(const Vector2i &p_vec2) const {
bool Vector2i::operator!=(const Vector2i &p_vec2) const {
return x != p_vec2.x || y != p_vec2.y;
}
+
+Vector2i::operator String() const {
+ return "(" + itos(x) + ", " + itos(y) + ")";
+}
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 6abe0f5ea9..78deb473b4 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -84,6 +84,7 @@ struct Vector2 {
real_t length() const;
real_t length_squared() const;
+ Vector2 limit_length(const real_t p_len = 1.0) const;
Vector2 min(const Vector2 &p_vector2) const {
return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y));
@@ -107,8 +108,6 @@ struct Vector2 {
Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const;
- Vector2 clamped(real_t p_len) const;
-
_FORCE_INLINE_ Vector2 lerp(const Vector2 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector2 slerp(const Vector2 &p_to, real_t p_weight) const;
Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const;
@@ -163,9 +162,10 @@ struct Vector2 {
Vector2 ceil() const;
Vector2 round() const;
Vector2 snapped(const Vector2 &p_by) const;
+ Vector2 clamp(const Vector2 &p_min, const Vector2 &p_max) const;
real_t aspect() const { return width / height; }
- operator String() const { return String::num(x) + ", " + String::num(y); }
+ operator String() const;
_FORCE_INLINE_ Vector2() {}
_FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) {
@@ -338,8 +338,9 @@ struct Vector2i {
real_t aspect() const { return width / (real_t)height; }
Vector2i sign() const { return Vector2i(SGN(x), SGN(y)); }
Vector2i abs() const { return Vector2i(ABS(x), ABS(y)); }
+ Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
- operator String() const { return String::num(x) + ", " + String::num(y); }
+ operator String() const;
operator Vector2() const { return Vector2(x, y); }
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index d4317d506c..3d59064af6 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -52,6 +52,13 @@ real_t Vector3::get_axis(int p_axis) const {
return operator[](p_axis);
}
+Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const {
+ return Vector3(
+ CLAMP(x, p_min.x, p_max.x),
+ CLAMP(y, p_min.y, p_max.y),
+ CLAMP(z, p_min.z, p_max.z));
+}
+
void Vector3::snap(Vector3 p_step) {
x = Math::snapped(x, p_step.x);
y = Math::snapped(y, p_step.y);
@@ -64,6 +71,17 @@ Vector3 Vector3::snapped(Vector3 p_step) const {
return v;
}
+Vector3 Vector3::limit_length(const real_t p_len) const {
+ const real_t l = length();
+ Vector3 v = *this;
+ if (l > 0 && p_len < l) {
+ v /= l;
+ v *= p_len;
+ }
+
+ return v;
+}
+
Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const {
Vector3 p0 = p_pre_a;
Vector3 p1 = *this;
@@ -108,5 +126,5 @@ bool Vector3::is_equal_approx(const Vector3 &p_v) const {
}
Vector3::operator String() const {
- return (rtos(x) + ", " + rtos(y) + ", " + rtos(z));
+ return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")";
}
diff --git a/core/math/vector3.h b/core/math/vector3.h
index b47c3cc916..d8d3cd3cc0 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -86,6 +86,7 @@ struct Vector3 {
_FORCE_INLINE_ Vector3 normalized() const;
_FORCE_INLINE_ bool is_normalized() const;
_FORCE_INLINE_ Vector3 inverse() const;
+ Vector3 limit_length(const real_t p_len = 1.0) const;
_FORCE_INLINE_ void zero();
@@ -112,6 +113,7 @@ struct Vector3 {
_FORCE_INLINE_ Vector3 sign() const;
_FORCE_INLINE_ Vector3 ceil() const;
_FORCE_INLINE_ Vector3 round() const;
+ Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
@@ -423,7 +425,7 @@ Vector3 Vector3::normalized() const {
bool Vector3::is_normalized() const {
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
- return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
+ return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON);
}
Vector3 Vector3::inverse() const {
diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp
index 167fa3221d..2de1e4e331 100644
--- a/core/math/vector3i.cpp
+++ b/core/math/vector3i.cpp
@@ -48,6 +48,13 @@ int Vector3i::max_axis() const {
return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
}
+Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const {
+ return Vector3i(
+ CLAMP(x, p_min.x, p_max.x),
+ CLAMP(y, p_min.y, p_max.y),
+ CLAMP(z, p_min.z, p_max.z));
+}
+
Vector3i::operator String() const {
- return (itos(x) + ", " + itos(y) + ", " + itos(z));
+ return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")";
}
diff --git a/core/math/vector3i.h b/core/math/vector3i.h
index b0411fb62e..37c7c1c368 100644
--- a/core/math/vector3i.h
+++ b/core/math/vector3i.h
@@ -69,6 +69,7 @@ struct Vector3i {
_FORCE_INLINE_ Vector3i abs() const;
_FORCE_INLINE_ Vector3i sign() const;
+ Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
/* Operators */
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index fb7eb42738..5bf874ccae 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -501,12 +501,27 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam
compat_classes[p_class] = p_fallback;
}
+thread_local bool initializing_with_extension = false;
+thread_local ObjectNativeExtension *initializing_extension = nullptr;
+thread_local void *initializing_extension_instance = nullptr;
+
+void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance) {
+ if (initializing_with_extension) {
+ *r_extension = initializing_extension;
+ *r_extension_instance = initializing_extension_instance;
+ initializing_with_extension = false;
+ } else {
+ *r_extension = nullptr;
+ *r_extension_instance = nullptr;
+ }
+}
+
Object *ClassDB::instance(const StringName &p_class) {
ClassInfo *ti;
{
OBJTYPE_RLOCK;
ti = classes.getptr(p_class);
- if (!ti || ti->disabled || !ti->creation_func) {
+ if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) {
if (compat_classes.has(p_class)) {
ti = classes.getptr(compat_classes[p_class]);
}
@@ -521,6 +536,11 @@ Object *ClassDB::instance(const StringName &p_class) {
return nullptr;
}
#endif
+ if (ti->native_extension) {
+ initializing_with_extension = true;
+ initializing_extension = ti->native_extension;
+ initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->create_instance_userdata);
+ }
return ti->creation_func();
}
@@ -534,7 +554,7 @@ bool ClassDB::can_instance(const StringName &p_class) {
return false;
}
#endif
- return (!ti->disabled && ti->creation_func != nullptr);
+ return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance));
}
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
@@ -1310,6 +1330,24 @@ bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inhe
return false;
}
+void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method) {
+ ClassInfo *type = classes.getptr(p_class);
+ if (!type) {
+ ERR_FAIL_MSG("Couldn't bind custom method '" + p_method->get_name() + "' for instance '" + p_class + "'.");
+ }
+
+ if (type->method_map.has(p_method->get_name())) {
+ // overloading not supported
+ ERR_FAIL_MSG("Method already bound '" + p_class + "::" + p_method->get_name() + "'.");
+ }
+
+#ifdef DEBUG_METHODS_ENABLED
+ type->method_order.push_back(p_method->get_name());
+#endif
+
+ type->method_map[p_method->get_name()] = p_method;
+}
+
#ifdef DEBUG_METHODS_ENABLED
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
StringName mdname = method_name.name;
@@ -1545,6 +1583,26 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
return var;
}
+void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
+ GLOBAL_LOCK_FUNCTION;
+
+ ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name));
+ ERR_FAIL_COND_MSG(classes.has(p_extension->parent_class_name), "Parent class name for extension class not found: " + String(p_extension->parent_class_name));
+
+ ClassInfo *parent = classes.getptr(p_extension->parent_class_name);
+
+ ClassInfo c;
+ c.api = p_extension->editor_class ? API_EDITOR_EXTENSION : API_EXTENSION;
+ c.native_extension = p_extension;
+ c.name = p_extension->class_name;
+ c.creation_func = parent->creation_func;
+ c.inherits = parent->name;
+ c.class_ptr = parent->class_ptr;
+ c.inherits_ptr = parent;
+
+ classes[p_extension->class_name] = c;
+}
+
RWLock ClassDB::lock;
void ClassDB::cleanup_defaults() {
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 6fd5748dbb..4355c9b0ea 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -97,6 +97,8 @@ public:
enum APIType {
API_CORE,
API_EDITOR,
+ API_EXTENSION,
+ API_EDITOR_EXTENSION,
API_NONE
};
@@ -115,6 +117,8 @@ public:
ClassInfo *inherits_ptr = nullptr;
void *class_ptr = nullptr;
+ ObjectNativeExtension *native_extension = nullptr;
+
HashMap<StringName, MethodBind *> method_map;
HashMap<StringName, int> constant_map;
HashMap<StringName, List<StringName>> enum_map;
@@ -199,6 +203,8 @@ public:
//nothing
}
+ static void register_extension_class(ObjectNativeExtension *p_extension);
+
template <class T>
static Object *_create_ptr_func() {
return T::create();
@@ -226,6 +232,7 @@ public:
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instance(const StringName &p_class);
static Object *instance(const StringName &p_class);
+ static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance);
static APIType get_api_type(const StringName &p_class);
static uint64_t get_api_hash(APIType p_api);
@@ -334,6 +341,8 @@ public:
return bind;
}
+ static void bind_method_custom(const StringName &p_class, MethodBind *p_method);
+
static void add_signal(StringName p_class, const MethodInfo &p_signal);
static bool has_signal(StringName p_class, StringName p_signal, bool p_no_inheritance = false);
static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal);
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 413f917518..799e63a512 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -385,6 +385,15 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
}
}
+ if (_extension && _extension->set) {
+ if (_extension->set(_extension_instance, &p_name, &p_value)) {
+ if (r_valid) {
+ *r_valid = true;
+ }
+ return;
+ }
+ }
+
//try built-in setgetter
{
if (ClassDB::set_property(this, p_name, p_value, r_valid)) {
@@ -451,6 +460,15 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
}
}
+ if (_extension && _extension->get) {
+ if (_extension->get(_extension_instance, &p_name, &ret)) {
+ if (r_valid) {
+ *r_valid = true;
+ }
+ return ret;
+ }
+ }
+
//try built-in setgetter
{
if (ClassDB::get_property(const_cast<Object *>(this), p_name, ret)) {
@@ -596,6 +614,17 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
_get_property_listv(p_list, p_reversed);
+ if (_extension && _extension->get_property_list) {
+ uint32_t pcount;
+ const ObjectNativeExtension::PInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
+ for (uint32_t i = 0; i < pcount; i++) {
+ p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name));
+ }
+ if (_extension->free_property_list) {
+ _extension->free_property_list(_extension_instance, pinfo);
+ }
+ }
+
if (!is_class("Script")) { // can still be set, but this is for user-friendliness
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
}
@@ -740,7 +769,7 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a
r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
return Variant();
}
- if (Object::cast_to<Reference>(this)) {
+ if (Object::cast_to<RefCounted>(this)) {
r_error.argument = 0;
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
ERR_FAIL_V_MSG(Variant(), "Can't 'free' a reference.");
@@ -761,6 +790,7 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a
Variant ret;
OBJ_DEBUG_LOCK
+
if (script_instance) {
ret = script_instance->call(p_method, p_args, p_argcount, r_error);
//force jumptable
@@ -778,6 +808,8 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a
}
}
+ //extension does not need this, because all methods are registered in MethodBind
+
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
if (method) {
@@ -795,6 +827,10 @@ void Object::notification(int p_notification, bool p_reversed) {
if (script_instance) {
script_instance->notification(p_notification);
}
+
+ if (_extension && _extension->notification) {
+ _extension->notification(_extension_instance, p_notification);
+ }
}
String Object::to_string() {
@@ -805,6 +841,9 @@ String Object::to_string() {
return ret;
}
}
+ if (_extension && _extension->to_string) {
+ return _extension->to_string(_extension_instance);
+ }
return "[" + get_class() + ":" + itos(get_instance_id()) + "]";
}
@@ -1345,7 +1384,7 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable,
if (!s) {
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal) ||
(!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal));
- ERR_FAIL_COND_MSG(signal_is_valid, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. signal: '" + p_signal + "', callable: '" + p_callable + "'.");
+ ERR_FAIL_COND_MSG(signal_is_valid, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. Signal: '" + p_signal + "', callable: '" + p_callable + "'.");
}
ERR_FAIL_COND_MSG(!s, vformat("Disconnecting nonexistent signal '%s' in %s.", p_signal, to_string()));
@@ -1751,6 +1790,8 @@ void Object::_construct_object(bool p_reference) {
_instance_id = ObjectDB::add_instance(this);
memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS);
+ ClassDB::instance_get_native_extension_data(&_extension, &_extension_instance);
+
#ifdef DEBUG_ENABLED
_lock_index.init(1);
#endif
@@ -1770,6 +1811,12 @@ Object::~Object() {
}
script_instance = nullptr;
+ if (_extension && _extension->free_instance) {
+ _extension->free_instance(_extension->create_instance_userdata, _extension_instance);
+ _extension = nullptr;
+ _extension_instance = nullptr;
+ }
+
const StringName *S = nullptr;
if (_emitting) {
@@ -1853,7 +1900,7 @@ ObjectID ObjectDB::add_instance(Object *p_object) {
object_slots = (ObjectSlot *)memrealloc(object_slots, sizeof(ObjectSlot) * new_slot_max);
for (uint32_t i = slot_max; i < new_slot_max; i++) {
object_slots[i].object = nullptr;
- object_slots[i].is_reference = false;
+ object_slots[i].is_ref_counted = false;
object_slots[i].next_free = i;
object_slots[i].validator = 0;
}
@@ -1866,7 +1913,7 @@ ObjectID ObjectDB::add_instance(Object *p_object) {
ERR_FAIL_COND_V(object_slots[slot].object != nullptr, ObjectID());
}
object_slots[slot].object = p_object;
- object_slots[slot].is_reference = p_object->is_reference();
+ object_slots[slot].is_ref_counted = p_object->is_ref_counted();
validator_counter = (validator_counter + 1) & OBJECTDB_VALIDATOR_MASK;
if (unlikely(validator_counter == 0)) {
validator_counter = 1;
@@ -1877,7 +1924,7 @@ ObjectID ObjectDB::add_instance(Object *p_object) {
id <<= OBJECTDB_SLOT_MAX_COUNT_BITS;
id |= uint64_t(slot);
- if (p_object->is_reference()) {
+ if (p_object->is_ref_counted()) {
id |= OBJECTDB_REFERENCE_BIT;
}
@@ -1915,7 +1962,7 @@ void ObjectDB::remove_instance(Object *p_object) {
object_slots[slot_count].next_free = slot;
//invalidate, so checks against it fail
object_slots[slot].validator = 0;
- object_slots[slot].is_reference = false;
+ object_slots[slot].is_ref_counted = false;
object_slots[slot].object = nullptr;
spin_lock.unlock();
@@ -1950,7 +1997,7 @@ void ObjectDB::cleanup() {
extra_info = " - Resource path: " + String(resource_get_path->call(obj, nullptr, 0, call_error));
}
- uint64_t id = uint64_t(i) | (uint64_t(object_slots[i].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[i].is_reference ? OBJECTDB_REFERENCE_BIT : 0);
+ uint64_t id = uint64_t(i) | (uint64_t(object_slots[i].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[i].is_ref_counted ? OBJECTDB_REFERENCE_BIT : 0);
print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + extra_info);
count--;
diff --git a/core/object/object.h b/core/object/object.h
index 448a33d3bc..37b2e61dfe 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -238,6 +238,50 @@ struct MethodInfo {
////else
//return nullptr;
+// API used to extend in GDNative and other C compatible compiled languages
+class MethodBind;
+
+struct ObjectNativeExtension {
+ ObjectNativeExtension *parent = nullptr;
+ StringName parent_class_name;
+ StringName class_name;
+ bool editor_class = false;
+ bool (*set)(void *instance, const void *name, const void *value) = nullptr;
+ bool (*get)(void *instance, const void *name, void *ret_variant) = nullptr;
+ struct PInfo {
+ uint32_t type;
+ const char *name;
+ const char *class_name;
+ uint32_t hint;
+ const char *hint_string;
+ uint32_t usage;
+ };
+ const PInfo *(*get_property_list)(void *instance, uint32_t *count) = nullptr;
+ void (*free_property_list)(void *instance, const PInfo *) = nullptr;
+
+ //call is not used, as all methods registered in ClassDB
+
+ void (*notification)(void *instance, int32_t what) = nullptr;
+ const char *(*to_string)(void *instance) = nullptr;
+
+ void (*reference)(void *instance) = nullptr;
+ void (*unreference)(void *instance) = nullptr;
+
+ _FORCE_INLINE_ bool is_class(const String &p_class) const {
+ const ObjectNativeExtension *e = this;
+ while (e) {
+ if (p_class == e->class_name.operator String()) {
+ return true;
+ }
+ e = e->parent;
+ }
+ return false;
+ }
+ void *create_instance_userdata = nullptr;
+ void *(*create_instance)(void *create_instance_userdata) = nullptr;
+ void (*free_instance)(void *create_instance_userdata, void *instance) = nullptr;
+};
+
/*
the following is an incomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
*/
@@ -262,9 +306,15 @@ private:
\
public: \
virtual String get_class() const override { \
+ if (_get_extension()) { \
+ return _get_extension()->class_name.operator String(); \
+ } \
return String(#m_class); \
} \
virtual const StringName *_get_class_namev() const override { \
+ if (_get_extension()) { \
+ return &_get_extension()->class_name; \
+ } \
if (!_class_name) { \
_class_name = get_class_static(); \
} \
@@ -297,7 +347,12 @@ public:
static String inherits_static() { \
return String(#m_inherits); \
} \
- virtual bool is_class(const String &p_class) const override { return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); } \
+ virtual bool is_class(const String &p_class) const override { \
+ if (_get_extension() && _get_extension()->is_class(p_class)) { \
+ return true; \
+ } \
+ return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); \
+ } \
virtual bool is_class_ptr(void *p_ptr) const override { return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); } \
\
static void get_valid_parents_static(List<String> *p_parents) { \
@@ -440,6 +495,9 @@ private:
friend bool predelete_handler(Object *);
friend void postinitialize_handler(Object *);
+ ObjectNativeExtension *_extension = nullptr;
+ void *_extension_instance = nullptr;
+
struct SignalData {
struct Slot {
int reference_count = 0;
@@ -487,7 +545,7 @@ private:
_FORCE_INLINE_ void _construct_object(bool p_reference);
- friend class Reference;
+ friend class RefCounted;
bool type_is_reference = false;
SafeNumeric<uint32_t> instance_binding_count;
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
@@ -495,6 +553,8 @@ private:
Object(bool p_reference);
protected:
+ _ALWAYS_INLINE_ const ObjectNativeExtension *_get_extension() const { return _extension; }
+ _ALWAYS_INLINE_ void *_get_extension_instance() const { return _extension_instance; }
virtual void _initialize_classv() { initialize_class(); }
virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; };
virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; };
@@ -610,13 +670,25 @@ public:
static String get_parent_class_static() { return String(); }
static String get_category_static() { return String(); }
- virtual String get_class() const { return "Object"; }
+ virtual String get_class() const {
+ if (_extension)
+ return _extension->class_name.operator String();
+ return "Object";
+ }
virtual String get_save_class() const { return get_class(); } //class stored when saving
- virtual bool is_class(const String &p_class) const { return (p_class == "Object"); }
+ virtual bool is_class(const String &p_class) const {
+ if (_extension && _extension->is_class(p_class)) {
+ return true;
+ }
+ return (p_class == "Object");
+ }
virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
_FORCE_INLINE_ const StringName &get_class_name() const {
+ if (_extension) {
+ return _extension->class_name;
+ }
if (!_class_ptr) {
return *_get_class_namev();
} else {
@@ -723,7 +795,7 @@ public:
void clear_internal_resource_paths();
- _ALWAYS_INLINE_ bool is_reference() const { return type_is_reference; }
+ _ALWAYS_INLINE_ bool is_ref_counted() const { return type_is_reference; }
Object();
virtual ~Object();
@@ -743,7 +815,7 @@ class ObjectDB {
struct ObjectSlot { //128 bits per slot
uint64_t validator : OBJECTDB_VALIDATOR_BITS;
uint64_t next_free : OBJECTDB_SLOT_MAX_COUNT_BITS;
- uint64_t is_reference : 1;
+ uint64_t is_ref_counted : 1;
Object *object;
};
diff --git a/core/object/object_id.h b/core/object/object_id.h
index 7f2496ad48..0666ec0855 100644
--- a/core/object/object_id.h
+++ b/core/object/object_id.h
@@ -42,7 +42,7 @@ class ObjectID {
uint64_t id = 0;
public:
- _ALWAYS_INLINE_ bool is_reference() const { return (id & (uint64_t(1) << 63)) != 0; }
+ _ALWAYS_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
_ALWAYS_INLINE_ bool is_valid() const { return id != 0; }
_ALWAYS_INLINE_ bool is_null() const { return id == 0; }
_ALWAYS_INLINE_ operator uint64_t() const { return id; }
diff --git a/core/object/ref_counted.cpp b/core/object/ref_counted.cpp
new file mode 100644
index 0000000000..9862624972
--- /dev/null
+++ b/core/object/ref_counted.cpp
@@ -0,0 +1,138 @@
+/*************************************************************************/
+/* ref_counted.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "ref_counted.h"
+
+#include "core/object/script_language.h"
+
+bool RefCounted::init_ref() {
+ if (reference()) {
+ if (!is_referenced() && refcount_init.unref()) {
+ unreference(); // first referencing is already 1, so compensate for the ref above
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void RefCounted::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("init_ref"), &RefCounted::init_ref);
+ ClassDB::bind_method(D_METHOD("reference"), &RefCounted::reference);
+ ClassDB::bind_method(D_METHOD("unreference"), &RefCounted::unreference);
+}
+
+int RefCounted::reference_get_count() const {
+ return refcount.get();
+}
+
+bool RefCounted::reference() {
+ uint32_t rc_val = refcount.refval();
+ bool success = rc_val != 0;
+
+ if (success && rc_val <= 2 /* higher is not relevant */) {
+ if (get_script_instance()) {
+ get_script_instance()->refcount_incremented();
+ }
+ if (_get_extension() && _get_extension()->reference) {
+ _get_extension()->reference(_get_extension_instance());
+ }
+ if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
+ for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
+ if (_script_instance_bindings[i]) {
+ ScriptServer::get_language(i)->refcount_incremented_instance_binding(this);
+ }
+ }
+ }
+ }
+
+ return success;
+}
+
+bool RefCounted::unreference() {
+ uint32_t rc_val = refcount.unrefval();
+ bool die = rc_val == 0;
+
+ if (rc_val <= 1 /* higher is not relevant */) {
+ if (get_script_instance()) {
+ bool script_ret = get_script_instance()->refcount_decremented();
+ die = die && script_ret;
+ }
+ if (_get_extension() && _get_extension()->unreference) {
+ _get_extension()->unreference(_get_extension_instance());
+ }
+ if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
+ for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
+ if (_script_instance_bindings[i]) {
+ bool script_ret = ScriptServer::get_language(i)->refcount_decremented_instance_binding(this);
+ die = die && script_ret;
+ }
+ }
+ }
+ }
+
+ return die;
+}
+
+RefCounted::RefCounted() :
+ Object(true) {
+ refcount.init();
+ refcount_init.init();
+}
+
+Variant WeakRef::get_ref() const {
+ if (ref.is_null()) {
+ return Variant();
+ }
+
+ Object *obj = ObjectDB::get_instance(ref);
+ if (!obj) {
+ return Variant();
+ }
+ RefCounted *r = cast_to<RefCounted>(obj);
+ if (r) {
+ return REF(r);
+ }
+
+ return obj;
+}
+
+void WeakRef::set_obj(Object *p_object) {
+ ref = p_object ? p_object->get_instance_id() : ObjectID();
+}
+
+void WeakRef::set_ref(const REF &p_ref) {
+ ref = p_ref.is_valid() ? p_ref->get_instance_id() : ObjectID();
+}
+
+void WeakRef::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_ref"), &WeakRef::get_ref);
+}
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
new file mode 100644
index 0000000000..3dd7cc456b
--- /dev/null
+++ b/core/object/ref_counted.h
@@ -0,0 +1,297 @@
+/*************************************************************************/
+/* ref_counted.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef REF_COUNTED_H
+#define REF_COUNTED_H
+
+#include "core/object/class_db.h"
+#include "core/templates/safe_refcount.h"
+
+class RefCounted : public Object {
+ GDCLASS(RefCounted, Object);
+ SafeRefCount refcount;
+ SafeRefCount refcount_init;
+
+protected:
+ static void _bind_methods();
+
+public:
+ _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() != 1; }
+ bool init_ref();
+ bool reference(); // returns false if refcount is at zero and didn't get increased
+ bool unreference();
+ int reference_get_count() const;
+
+ RefCounted();
+ ~RefCounted() {}
+};
+
+template <class T>
+class Ref {
+ T *reference = nullptr;
+
+ void ref(const Ref &p_from) {
+ if (p_from.reference == reference) {
+ return;
+ }
+
+ unref();
+
+ reference = p_from.reference;
+ if (reference) {
+ reference->reference();
+ }
+ }
+
+ void ref_pointer(T *p_ref) {
+ ERR_FAIL_COND(!p_ref);
+
+ if (p_ref->init_ref()) {
+ reference = p_ref;
+ }
+ }
+
+ //virtual RefCounted * get_reference() const { return reference; }
+public:
+ _FORCE_INLINE_ bool operator==(const T *p_ptr) const {
+ return reference == p_ptr;
+ }
+ _FORCE_INLINE_ bool operator!=(const T *p_ptr) const {
+ return reference != p_ptr;
+ }
+
+ _FORCE_INLINE_ bool operator<(const Ref<T> &p_r) const {
+ return reference < p_r.reference;
+ }
+ _FORCE_INLINE_ bool operator==(const Ref<T> &p_r) const {
+ return reference == p_r.reference;
+ }
+ _FORCE_INLINE_ bool operator!=(const Ref<T> &p_r) const {
+ return reference != p_r.reference;
+ }
+
+ _FORCE_INLINE_ T *operator->() {
+ return reference;
+ }
+
+ _FORCE_INLINE_ T *operator*() {
+ return reference;
+ }
+
+ _FORCE_INLINE_ const T *operator->() const {
+ return reference;
+ }
+
+ _FORCE_INLINE_ const T *ptr() const {
+ return reference;
+ }
+ _FORCE_INLINE_ T *ptr() {
+ return reference;
+ }
+
+ _FORCE_INLINE_ const T *operator*() const {
+ return reference;
+ }
+
+ operator Variant() const {
+ return Variant(reference);
+ }
+
+ void operator=(const Ref &p_from) {
+ ref(p_from);
+ }
+
+ template <class T_Other>
+ void operator=(const Ref<T_Other> &p_from) {
+ RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
+ if (!refb) {
+ unref();
+ return;
+ }
+ Ref r;
+ r.reference = Object::cast_to<T>(refb);
+ ref(r);
+ r.reference = nullptr;
+ }
+
+ void operator=(const Variant &p_variant) {
+ Object *object = p_variant.get_validated_object();
+
+ if (object == reference) {
+ return;
+ }
+
+ unref();
+
+ if (!object) {
+ return;
+ }
+
+ T *r = Object::cast_to<T>(object);
+ if (r && r->reference()) {
+ reference = r;
+ }
+ }
+
+ template <class T_Other>
+ void reference_ptr(T_Other *p_ptr) {
+ if (reference == p_ptr) {
+ return;
+ }
+ unref();
+
+ T *r = Object::cast_to<T>(p_ptr);
+ if (r) {
+ ref_pointer(r);
+ }
+ }
+
+ Ref(const Ref &p_from) {
+ ref(p_from);
+ }
+
+ template <class T_Other>
+ Ref(const Ref<T_Other> &p_from) {
+ RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
+ if (!refb) {
+ unref();
+ return;
+ }
+ Ref r;
+ r.reference = Object::cast_to<T>(refb);
+ ref(r);
+ r.reference = nullptr;
+ }
+
+ Ref(T *p_reference) {
+ if (p_reference) {
+ ref_pointer(p_reference);
+ }
+ }
+
+ Ref(const Variant &p_variant) {
+ Object *object = p_variant.get_validated_object();
+
+ if (!object) {
+ return;
+ }
+
+ T *r = Object::cast_to<T>(object);
+ if (r && r->reference()) {
+ reference = r;
+ }
+ }
+
+ inline bool is_valid() const { return reference != nullptr; }
+ inline bool is_null() const { return reference == nullptr; }
+
+ void unref() {
+ //TODO this should be moved to mutexes, since this engine does not really
+ // do a lot of referencing on references and stuff
+ // mutexes will avoid more crashes?
+
+ if (reference && reference->unreference()) {
+ memdelete(reference);
+ }
+ reference = nullptr;
+ }
+
+ void instance() {
+ ref(memnew(T));
+ }
+
+ Ref() {}
+
+ ~Ref() {
+ unref();
+ }
+};
+
+typedef Ref<RefCounted> REF;
+
+class WeakRef : public RefCounted {
+ GDCLASS(WeakRef, RefCounted);
+
+ ObjectID ref;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Variant get_ref() const;
+ void set_obj(Object *p_object);
+ void set_ref(const REF &p_ref);
+
+ WeakRef() {}
+};
+
+template <class T>
+struct PtrToArg<Ref<T>> {
+ _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
+ return Ref<T>(const_cast<T *>(reinterpret_cast<const T *>(p_ptr)));
+ }
+
+ _FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) {
+ *(Ref<RefCounted> *)p_ptr = p_val;
+ }
+};
+
+template <class T>
+struct PtrToArg<const Ref<T> &> {
+ _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
+ return Ref<T>((T *)p_ptr);
+ }
+};
+
+#ifdef DEBUG_METHODS_ENABLED
+
+template <class T>
+struct GetTypeInfo<Ref<T>> {
+ static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
+
+ static inline PropertyInfo get_class_info() {
+ return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
+ }
+};
+
+template <class T>
+struct GetTypeInfo<const Ref<T> &> {
+ static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
+
+ static inline PropertyInfo get_class_info() {
+ return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
+ }
+};
+
+#endif // DEBUG_METHODS_ENABLED
+
+#endif // REF_COUNTED_H
diff --git a/core/object/reference.cpp b/core/object/reference.cpp
deleted file mode 100644
index 22e4e8a336..0000000000
--- a/core/object/reference.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*************************************************************************/
-/* reference.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "reference.h"
-
-#include "core/object/script_language.h"
-
-bool Reference::init_ref() {
- if (reference()) {
- if (!is_referenced() && refcount_init.unref()) {
- unreference(); // first referencing is already 1, so compensate for the ref above
- }
-
- return true;
- } else {
- return false;
- }
-}
-
-void Reference::_bind_methods() {
- ClassDB::bind_method(D_METHOD("init_ref"), &Reference::init_ref);
- ClassDB::bind_method(D_METHOD("reference"), &Reference::reference);
- ClassDB::bind_method(D_METHOD("unreference"), &Reference::unreference);
-}
-
-int Reference::reference_get_count() const {
- return refcount.get();
-}
-
-bool Reference::reference() {
- uint32_t rc_val = refcount.refval();
- bool success = rc_val != 0;
-
- if (success && rc_val <= 2 /* higher is not relevant */) {
- if (get_script_instance()) {
- get_script_instance()->refcount_incremented();
- }
- if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
- for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
- if (_script_instance_bindings[i]) {
- ScriptServer::get_language(i)->refcount_incremented_instance_binding(this);
- }
- }
- }
- }
-
- return success;
-}
-
-bool Reference::unreference() {
- uint32_t rc_val = refcount.unrefval();
- bool die = rc_val == 0;
-
- if (rc_val <= 1 /* higher is not relevant */) {
- if (get_script_instance()) {
- bool script_ret = get_script_instance()->refcount_decremented();
- die = die && script_ret;
- }
- if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
- for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
- if (_script_instance_bindings[i]) {
- bool script_ret = ScriptServer::get_language(i)->refcount_decremented_instance_binding(this);
- die = die && script_ret;
- }
- }
- }
- }
-
- return die;
-}
-
-Reference::Reference() :
- Object(true) {
- refcount.init();
- refcount_init.init();
-}
-
-Variant WeakRef::get_ref() const {
- if (ref.is_null()) {
- return Variant();
- }
-
- Object *obj = ObjectDB::get_instance(ref);
- if (!obj) {
- return Variant();
- }
- Reference *r = cast_to<Reference>(obj);
- if (r) {
- return REF(r);
- }
-
- return obj;
-}
-
-void WeakRef::set_obj(Object *p_object) {
- ref = p_object ? p_object->get_instance_id() : ObjectID();
-}
-
-void WeakRef::set_ref(const REF &p_ref) {
- ref = p_ref.is_valid() ? p_ref->get_instance_id() : ObjectID();
-}
-
-void WeakRef::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_ref"), &WeakRef::get_ref);
-}
diff --git a/core/object/reference.h b/core/object/reference.h
deleted file mode 100644
index d02cb12069..0000000000
--- a/core/object/reference.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*************************************************************************/
-/* reference.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef REFERENCE_H
-#define REFERENCE_H
-
-#include "core/object/class_db.h"
-#include "core/templates/safe_refcount.h"
-
-class Reference : public Object {
- GDCLASS(Reference, Object);
- SafeRefCount refcount;
- SafeRefCount refcount_init;
-
-protected:
- static void _bind_methods();
-
-public:
- _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() != 1; }
- bool init_ref();
- bool reference(); // returns false if refcount is at zero and didn't get increased
- bool unreference();
- int reference_get_count() const;
-
- Reference();
- ~Reference() {}
-};
-
-template <class T>
-class Ref {
- T *reference = nullptr;
-
- void ref(const Ref &p_from) {
- if (p_from.reference == reference) {
- return;
- }
-
- unref();
-
- reference = p_from.reference;
- if (reference) {
- reference->reference();
- }
- }
-
- void ref_pointer(T *p_ref) {
- ERR_FAIL_COND(!p_ref);
-
- if (p_ref->init_ref()) {
- reference = p_ref;
- }
- }
-
- //virtual Reference * get_reference() const { return reference; }
-public:
- _FORCE_INLINE_ bool operator==(const T *p_ptr) const {
- return reference == p_ptr;
- }
- _FORCE_INLINE_ bool operator!=(const T *p_ptr) const {
- return reference != p_ptr;
- }
-
- _FORCE_INLINE_ bool operator<(const Ref<T> &p_r) const {
- return reference < p_r.reference;
- }
- _FORCE_INLINE_ bool operator==(const Ref<T> &p_r) const {
- return reference == p_r.reference;
- }
- _FORCE_INLINE_ bool operator!=(const Ref<T> &p_r) const {
- return reference != p_r.reference;
- }
-
- _FORCE_INLINE_ T *operator->() {
- return reference;
- }
-
- _FORCE_INLINE_ T *operator*() {
- return reference;
- }
-
- _FORCE_INLINE_ const T *operator->() const {
- return reference;
- }
-
- _FORCE_INLINE_ const T *ptr() const {
- return reference;
- }
- _FORCE_INLINE_ T *ptr() {
- return reference;
- }
-
- _FORCE_INLINE_ const T *operator*() const {
- return reference;
- }
-
- operator Variant() const {
- return Variant(reference);
- }
-
- void operator=(const Ref &p_from) {
- ref(p_from);
- }
-
- template <class T_Other>
- void operator=(const Ref<T_Other> &p_from) {
- Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
- if (!refb) {
- unref();
- return;
- }
- Ref r;
- r.reference = Object::cast_to<T>(refb);
- ref(r);
- r.reference = nullptr;
- }
-
- void operator=(const Variant &p_variant) {
- Object *object = p_variant.get_validated_object();
-
- if (object == reference) {
- return;
- }
-
- unref();
-
- if (!object) {
- return;
- }
-
- T *r = Object::cast_to<T>(object);
- if (r && r->reference()) {
- reference = r;
- }
- }
-
- template <class T_Other>
- void reference_ptr(T_Other *p_ptr) {
- if (reference == p_ptr) {
- return;
- }
- unref();
-
- T *r = Object::cast_to<T>(p_ptr);
- if (r) {
- ref_pointer(r);
- }
- }
-
- Ref(const Ref &p_from) {
- ref(p_from);
- }
-
- template <class T_Other>
- Ref(const Ref<T_Other> &p_from) {
- Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
- if (!refb) {
- unref();
- return;
- }
- Ref r;
- r.reference = Object::cast_to<T>(refb);
- ref(r);
- r.reference = nullptr;
- }
-
- Ref(T *p_reference) {
- if (p_reference) {
- ref_pointer(p_reference);
- }
- }
-
- Ref(const Variant &p_variant) {
- Object *object = p_variant.get_validated_object();
-
- if (!object) {
- return;
- }
-
- T *r = Object::cast_to<T>(object);
- if (r && r->reference()) {
- reference = r;
- }
- }
-
- inline bool is_valid() const { return reference != nullptr; }
- inline bool is_null() const { return reference == nullptr; }
-
- void unref() {
- //TODO this should be moved to mutexes, since this engine does not really
- // do a lot of referencing on references and stuff
- // mutexes will avoid more crashes?
-
- if (reference && reference->unreference()) {
- memdelete(reference);
- }
- reference = nullptr;
- }
-
- void instance() {
- ref(memnew(T));
- }
-
- Ref() {}
-
- ~Ref() {
- unref();
- }
-};
-
-typedef Ref<Reference> REF;
-
-class WeakRef : public Reference {
- GDCLASS(WeakRef, Reference);
-
- ObjectID ref;
-
-protected:
- static void _bind_methods();
-
-public:
- Variant get_ref() const;
- void set_obj(Object *p_object);
- void set_ref(const REF &p_ref);
-
- WeakRef() {}
-};
-
-template <class T>
-struct PtrToArg<Ref<T>> {
- _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
- return Ref<T>(const_cast<T *>(reinterpret_cast<const T *>(p_ptr)));
- }
-
- _FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) {
- *(Ref<Reference> *)p_ptr = p_val;
- }
-};
-
-template <class T>
-struct PtrToArg<const Ref<T> &> {
- _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
- return Ref<T>((T *)p_ptr);
- }
-};
-
-#ifdef DEBUG_METHODS_ENABLED
-
-template <class T>
-struct GetTypeInfo<Ref<T>> {
- static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
- static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
-
- static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
- }
-};
-
-template <class T>
-struct GetTypeInfo<const Ref<T> &> {
- static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
- static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
-
- static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
- }
-};
-
-#endif // DEBUG_METHODS_ENABLED
-
-#endif // REFERENCE_H
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 42fb0a0caf..196f7a1876 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -353,10 +353,10 @@ void ScriptLanguage::get_core_type_words(List<String> *p_core_type_words) const
p_core_type_words->push_back("Vector3i");
p_core_type_words->push_back("Transform2D");
p_core_type_words->push_back("Plane");
- p_core_type_words->push_back("Quat");
+ p_core_type_words->push_back("Quaternion");
p_core_type_words->push_back("AABB");
p_core_type_words->push_back("Basis");
- p_core_type_words->push_back("Transform");
+ p_core_type_words->push_back("Transform3D");
p_core_type_words->push_back("Color");
p_core_type_words->push_back("StringName");
p_core_type_words->push_back("NodePath");
@@ -585,14 +585,6 @@ Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_nam
return Variant();
}
-uint16_t PlaceHolderScriptInstance::get_rpc_method_id(const StringName &p_method) const {
- return UINT16_MAX;
-}
-
-uint16_t PlaceHolderScriptInstance::get_rset_property_id(const StringName &p_method) const {
- return UINT16_MAX;
-}
-
PlaceHolderScriptInstance::PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner) :
owner(p_owner),
language(p_language),
diff --git a/core/object/script_language.h b/core/object/script_language.h
index bb46c718b2..a22e91870e 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -41,21 +41,6 @@ class ScriptLanguage;
typedef void (*ScriptEditRequestFunction)(const String &p_path);
-struct ScriptNetData {
- StringName name;
- MultiplayerAPI::RPCMode mode;
- bool operator==(ScriptNetData const &p_other) const {
- return name == p_other.name;
- }
-};
-
-struct SortNetData {
- StringName::AlphCompare compare;
- bool operator()(const ScriptNetData &p_a, const ScriptNetData &p_b) const {
- return compare(p_a.name, p_b.name);
- }
-};
-
class ScriptServer {
enum {
MAX_LANGUAGES = 16
@@ -174,17 +159,7 @@ public:
virtual bool is_placeholder_fallback_enabled() const { return false; }
- virtual Vector<ScriptNetData> get_rpc_methods() const = 0;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const = 0;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const = 0;
-
- virtual Vector<ScriptNetData> get_rset_properties() const = 0;
- virtual uint16_t get_rset_property_id(const StringName &p_property) const = 0;
- virtual StringName get_rset_property(const uint16_t p_rset_property_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const = 0;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const = 0;
Script() {}
};
@@ -225,23 +200,15 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid);
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid);
- virtual Vector<ScriptNetData> get_rpc_methods() const = 0;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const = 0;
- virtual StringName get_rpc_method(uint16_t p_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const = 0;
-
- virtual Vector<ScriptNetData> get_rset_properties() const = 0;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const = 0;
- virtual StringName get_rset_property(uint16_t p_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const = 0;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const = 0;
virtual ScriptLanguage *get_language() = 0;
virtual ~ScriptInstance();
};
struct ScriptCodeCompletionOption {
+ /* Keep enum in Sync with: */
+ /* /scene/gui/code_edit.h - CodeEdit::CodeCompletionKind */
enum Kind {
KIND_CLASS,
KIND_FUNCTION,
@@ -445,17 +412,7 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = nullptr);
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = nullptr);
- virtual Vector<ScriptNetData> get_rpc_methods() const { return Vector<ScriptNetData>(); }
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(uint16_t p_id) const { return StringName(); }
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const { return MultiplayerAPI::RPC_MODE_DISABLED; }
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const { return MultiplayerAPI::RPC_MODE_DISABLED; }
-
- virtual Vector<ScriptNetData> get_rset_properties() const { return Vector<ScriptNetData>(); }
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
- virtual StringName get_rset_property(uint16_t p_id) const { return StringName(); }
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const { return MultiplayerAPI::RPC_MODE_DISABLED; }
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const { return MultiplayerAPI::RPC_MODE_DISABLED; }
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const { return Vector<MultiplayerAPI::RPCConfig>(); }
PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner);
~PlaceHolderScriptInstance();
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index e8735e335c..96c96c1efb 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -122,8 +122,8 @@ void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIA
ERR_FAIL_COND((current_action + 1) >= actions.size());
Operation do_op;
do_op.object = p_object->get_instance_id();
- if (Object::cast_to<Reference>(p_object)) {
- do_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object));
+ if (Object::cast_to<RefCounted>(p_object)) {
+ do_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(p_object));
}
do_op.type = Operation::TYPE_METHOD;
@@ -148,8 +148,8 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR
Operation undo_op;
undo_op.object = p_object->get_instance_id();
- if (Object::cast_to<Reference>(p_object)) {
- undo_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object));
+ if (Object::cast_to<RefCounted>(p_object)) {
+ undo_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(p_object));
}
undo_op.type = Operation::TYPE_METHOD;
@@ -167,8 +167,8 @@ void UndoRedo::add_do_property(Object *p_object, const StringName &p_property, c
ERR_FAIL_COND((current_action + 1) >= actions.size());
Operation do_op;
do_op.object = p_object->get_instance_id();
- if (Object::cast_to<Reference>(p_object)) {
- do_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object));
+ if (Object::cast_to<RefCounted>(p_object)) {
+ do_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(p_object));
}
do_op.type = Operation::TYPE_PROPERTY;
@@ -189,8 +189,8 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property,
Operation undo_op;
undo_op.object = p_object->get_instance_id();
- if (Object::cast_to<Reference>(p_object)) {
- undo_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object));
+ if (Object::cast_to<RefCounted>(p_object)) {
+ undo_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(p_object));
}
undo_op.type = Operation::TYPE_PROPERTY;
@@ -205,8 +205,8 @@ void UndoRedo::add_do_reference(Object *p_object) {
ERR_FAIL_COND((current_action + 1) >= actions.size());
Operation do_op;
do_op.object = p_object->get_instance_id();
- if (Object::cast_to<Reference>(p_object)) {
- do_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object));
+ if (Object::cast_to<RefCounted>(p_object)) {
+ do_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(p_object));
}
do_op.type = Operation::TYPE_REFERENCE;
@@ -225,8 +225,8 @@ void UndoRedo::add_undo_reference(Object *p_object) {
Operation undo_op;
undo_op.object = p_object->get_instance_id();
- if (Object::cast_to<Reference>(p_object)) {
- undo_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object));
+ if (Object::cast_to<RefCounted>(p_object)) {
+ undo_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(p_object));
}
undo_op.type = Operation::TYPE_REFERENCE;
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index a08ca7792f..8f009830e3 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -32,7 +32,7 @@
#define UNDO_REDO_H
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
class UndoRedo : public Object {
GDCLASS(UndoRedo, Object);
@@ -61,7 +61,7 @@ private:
};
Type type;
- Ref<Reference> ref;
+ Ref<RefCounted> ref;
ObjectID object;
StringName name;
Variant args[VARIANT_ARG_MAX];
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
deleted file mode 100644
index b7c3a17ba9..0000000000
--- a/core/os/dir_access.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-/*************************************************************************/
-/* dir_access.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "dir_access.h"
-
-#include "core/config/project_settings.h"
-#include "core/os/file_access.h"
-#include "core/os/memory.h"
-#include "core/os/os.h"
-
-String DirAccess::_get_root_path() const {
- switch (_access_type) {
- case ACCESS_RESOURCES:
- return ProjectSettings::get_singleton()->get_resource_path();
- case ACCESS_USERDATA:
- return OS::get_singleton()->get_user_data_dir();
- default:
- return "";
- }
-}
-
-String DirAccess::_get_root_string() const {
- switch (_access_type) {
- case ACCESS_RESOURCES:
- return "res://";
- case ACCESS_USERDATA:
- return "user://";
- default:
- return "";
- }
-}
-
-int DirAccess::get_current_drive() {
- String path = get_current_dir().to_lower();
- for (int i = 0; i < get_drive_count(); i++) {
- String d = get_drive(i).to_lower();
- if (path.begins_with(d)) {
- return i;
- }
- }
-
- return 0;
-}
-
-bool DirAccess::drives_are_shortcuts() {
- return false;
-}
-
-static Error _erase_recursive(DirAccess *da) {
- List<String> dirs;
- List<String> files;
-
- da->list_dir_begin();
- String n = da->get_next();
- while (n != String()) {
- if (n != "." && n != "..") {
- if (da->current_is_dir()) {
- dirs.push_back(n);
- } else {
- files.push_back(n);
- }
- }
-
- n = da->get_next();
- }
-
- da->list_dir_end();
-
- for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
- Error err = da->change_dir(E->get());
- if (err == OK) {
- err = _erase_recursive(da);
- if (err) {
- da->change_dir("..");
- return err;
- }
- err = da->change_dir("..");
- if (err) {
- return err;
- }
- err = da->remove(da->get_current_dir().plus_file(E->get()));
- if (err) {
- return err;
- }
- } else {
- return err;
- }
- }
-
- for (List<String>::Element *E = files.front(); E; E = E->next()) {
- Error err = da->remove(da->get_current_dir().plus_file(E->get()));
- if (err) {
- return err;
- }
- }
-
- return OK;
-}
-
-Error DirAccess::erase_contents_recursive() {
- return _erase_recursive(this);
-}
-
-Error DirAccess::make_dir_recursive(String p_dir) {
- if (p_dir.length() < 1) {
- return OK;
- }
-
- String full_dir;
-
- if (p_dir.is_rel_path()) {
- //append current
- full_dir = get_current_dir().plus_file(p_dir);
-
- } else {
- full_dir = p_dir;
- }
-
- full_dir = full_dir.replace("\\", "/");
-
- //int slices = full_dir.get_slice_count("/");
-
- String base;
-
- if (full_dir.begins_with("res://")) {
- base = "res://";
- } else if (full_dir.begins_with("user://")) {
- base = "user://";
- } else if (full_dir.begins_with("/")) {
- base = "/";
- } else if (full_dir.find(":/") != -1) {
- base = full_dir.substr(0, full_dir.find(":/") + 2);
- } else {
- ERR_FAIL_V(ERR_INVALID_PARAMETER);
- }
-
- full_dir = full_dir.replace_first(base, "").simplify_path();
-
- Vector<String> subdirs = full_dir.split("/");
-
- String curpath = base;
- for (int i = 0; i < subdirs.size(); i++) {
- curpath = curpath.plus_file(subdirs[i]);
- Error err = make_dir(curpath);
- if (err != OK && err != ERR_ALREADY_EXISTS) {
- ERR_FAIL_V_MSG(err, "Could not create directory: " + curpath);
- }
- }
-
- return OK;
-}
-
-String DirAccess::fix_path(String p_path) const {
- switch (_access_type) {
- case ACCESS_RESOURCES: {
- if (ProjectSettings::get_singleton()) {
- if (p_path.begins_with("res://")) {
- String resource_path = ProjectSettings::get_singleton()->get_resource_path();
- if (resource_path != "") {
- return p_path.replace_first("res:/", resource_path);
- }
- return p_path.replace_first("res://", "");
- }
- }
-
- } break;
- case ACCESS_USERDATA: {
- if (p_path.begins_with("user://")) {
- String data_dir = OS::get_singleton()->get_user_data_dir();
- if (data_dir != "") {
- return p_path.replace_first("user:/", data_dir);
- }
- return p_path.replace_first("user://", "");
- }
-
- } break;
- case ACCESS_FILESYSTEM: {
- return p_path;
- } break;
- case ACCESS_MAX:
- break; // Can't happen, but silences warning
- }
-
- return p_path;
-}
-
-DirAccess::CreateFunc DirAccess::create_func[ACCESS_MAX] = { nullptr, nullptr, nullptr };
-
-DirAccess *DirAccess::create_for_path(const String &p_path) {
- DirAccess *da = nullptr;
- if (p_path.begins_with("res://")) {
- da = create(ACCESS_RESOURCES);
- } else if (p_path.begins_with("user://")) {
- da = create(ACCESS_USERDATA);
- } else {
- da = create(ACCESS_FILESYSTEM);
- }
-
- return da;
-}
-
-DirAccess *DirAccess::open(const String &p_path, Error *r_error) {
- DirAccess *da = create_for_path(p_path);
-
- ERR_FAIL_COND_V_MSG(!da, nullptr, "Cannot create DirAccess for path '" + p_path + "'.");
- Error err = da->change_dir(p_path);
- if (r_error) {
- *r_error = err;
- }
- if (err != OK) {
- memdelete(da);
- return nullptr;
- }
-
- return da;
-}
-
-DirAccess *DirAccess::create(AccessType p_access) {
- DirAccess *da = create_func[p_access] ? create_func[p_access]() : nullptr;
- if (da) {
- da->_access_type = p_access;
- }
-
- return da;
-}
-
-String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
- DirAccess *d = DirAccess::create(p_access);
- if (!d) {
- return p_path;
- }
-
- d->change_dir(p_path);
- String full = d->get_current_dir();
- memdelete(d);
- return full;
-}
-
-Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
- //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data());
- Error err;
- FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
-
- if (err) {
- ERR_PRINT("Failed to open " + p_from);
- return err;
- }
-
- FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
- if (err) {
- fsrc->close();
- memdelete(fsrc);
- ERR_PRINT("Failed to open " + p_to);
- return err;
- }
-
- fsrc->seek_end(0);
- int size = fsrc->get_position();
- fsrc->seek(0);
- err = OK;
- while (size--) {
- if (fsrc->get_error() != OK) {
- err = fsrc->get_error();
- break;
- }
- if (fdst->get_error() != OK) {
- err = fdst->get_error();
- break;
- }
-
- fdst->store_8(fsrc->get_8());
- }
-
- if (err == OK && p_chmod_flags != -1) {
- fdst->close();
- err = FileAccess::set_unix_permissions(p_to, p_chmod_flags);
- // If running on a platform with no chmod support (i.e., Windows), don't fail
- if (err == ERR_UNAVAILABLE) {
- err = OK;
- }
- }
-
- memdelete(fsrc);
- memdelete(fdst);
-
- return err;
-}
-
-// Changes dir for the current scope, returning back to the original dir
-// when scope exits
-class DirChanger {
- DirAccess *da;
- String original_dir;
-
-public:
- DirChanger(DirAccess *p_da, String p_dir) :
- da(p_da),
- original_dir(p_da->get_current_dir()) {
- p_da->change_dir(p_dir);
- }
-
- ~DirChanger() {
- da->change_dir(original_dir);
- }
-};
-
-Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) {
- List<String> dirs;
-
- String curdir = get_current_dir();
- list_dir_begin();
- String n = get_next();
- while (n != String()) {
- if (n != "." && n != "..") {
- if (current_is_dir()) {
- dirs.push_back(n);
- } else {
- const String &rel_path = n;
- if (!n.is_rel_path()) {
- list_dir_end();
- return ERR_BUG;
- }
- Error err = copy(get_current_dir().plus_file(n), p_to + rel_path, p_chmod_flags);
- if (err) {
- list_dir_end();
- return err;
- }
- }
- }
-
- n = get_next();
- }
-
- list_dir_end();
-
- for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
- String rel_path = E->get();
- String target_dir = p_to + rel_path;
- if (!p_target_da->dir_exists(target_dir)) {
- Error err = p_target_da->make_dir(target_dir);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + target_dir + "'.");
- }
-
- Error err = change_dir(E->get());
- ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + E->get() + "'.");
-
- err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags);
- if (err) {
- change_dir("..");
- ERR_FAIL_V_MSG(err, "Failed to copy recursively.");
- }
- err = change_dir("..");
- ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to go back.");
- }
-
- return OK;
-}
-
-Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
- ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
-
- DirAccess *target_da = DirAccess::create_for_path(p_to);
- ERR_FAIL_COND_V_MSG(!target_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'.");
-
- if (!target_da->dir_exists(p_to)) {
- Error err = target_da->make_dir_recursive(p_to);
- if (err) {
- memdelete(target_da);
- }
- ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + p_to + "'.");
- }
-
- if (!p_to.ends_with("/")) {
- p_to = p_to + "/";
- }
-
- DirChanger dir_changer(this, p_from);
- Error err = _copy_dir(target_da, p_to, p_chmod_flags);
- memdelete(target_da);
-
- return err;
-}
-
-bool DirAccess::exists(String p_dir) {
- DirAccess *da = DirAccess::create_for_path(p_dir);
- bool valid = da->change_dir(p_dir) == OK;
- memdelete(da);
- return valid;
-}
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
deleted file mode 100644
index 7f0bcd372d..0000000000
--- a/core/os/dir_access.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*************************************************************************/
-/* dir_access.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef DIR_ACCESS_H
-#define DIR_ACCESS_H
-
-#include "core/string/ustring.h"
-#include "core/typedefs.h"
-
-//@ TODO, excellent candidate for THREAD_SAFE MACRO, should go through all these and add THREAD_SAFE where it applies
-class DirAccess {
-public:
- enum AccessType {
- ACCESS_RESOURCES,
- ACCESS_USERDATA,
- ACCESS_FILESYSTEM,
- ACCESS_MAX
- };
-
- typedef DirAccess *(*CreateFunc)();
-
-private:
- AccessType _access_type = ACCESS_FILESYSTEM;
- static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
-
- Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags);
-
-protected:
- String _get_root_path() const;
- String _get_root_string() const;
-
- String fix_path(String p_path) const;
-
- template <class T>
- static DirAccess *_create_builtin() {
- return memnew(T);
- }
-
-public:
- virtual Error list_dir_begin() = 0; ///< This starts dir listing
- virtual String get_next() = 0;
- virtual bool current_is_dir() const = 0;
- virtual bool current_is_hidden() const = 0;
-
- virtual void list_dir_end() = 0; ///<
-
- virtual int get_drive_count() = 0;
- virtual String get_drive(int p_drive) = 0;
- virtual int get_current_drive();
- virtual bool drives_are_shortcuts();
-
- virtual Error change_dir(String p_dir) = 0; ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true) = 0; ///< return current dir location
- virtual Error make_dir(String p_dir) = 0;
- virtual Error make_dir_recursive(String p_dir);
- virtual Error erase_contents_recursive(); //super dangerous, use with care!
-
- virtual bool file_exists(String p_file) = 0;
- virtual bool dir_exists(String p_dir) = 0;
- virtual bool is_readable(String p_dir) { return true; };
- virtual bool is_writable(String p_dir) { return true; };
- static bool exists(String p_dir);
- virtual size_t get_space_left() = 0;
-
- Error copy_dir(String p_from, String p_to, int p_chmod_flags = -1);
- virtual Error copy(String p_from, String p_to, int p_chmod_flags = -1);
- virtual Error rename(String p_from, String p_to) = 0;
- virtual Error remove(String p_name) = 0;
-
- // Meant for editor code when we want to quickly remove a file without custom
- // handling (e.g. removing a cache file).
- static void remove_file_or_error(String p_path) {
- DirAccess *da = create(ACCESS_FILESYSTEM);
- if (da->file_exists(p_path)) {
- if (da->remove(p_path) != OK) {
- ERR_FAIL_MSG("Cannot remove file or directory: " + p_path);
- }
- }
- memdelete(da);
- }
-
- virtual String get_filesystem_type() const = 0;
- static String get_full_path(const String &p_path, AccessType p_access);
- static DirAccess *create_for_path(const String &p_path);
-
- static DirAccess *create(AccessType p_access);
-
- template <class T>
- static void make_default(AccessType p_access) {
- create_func[p_access] = _create_builtin<T>;
- }
-
- static DirAccess *open(const String &p_path, Error *r_error = nullptr);
-
- DirAccess() {}
- virtual ~DirAccess() {}
-};
-
-struct DirAccessRef {
- _FORCE_INLINE_ DirAccess *operator->() {
- return f;
- }
-
- operator bool() const { return f != nullptr; }
-
- DirAccess *f;
-
- DirAccessRef(DirAccess *fa) { f = fa; }
- ~DirAccessRef() {
- if (f) {
- memdelete(f);
- }
- }
-};
-
-#endif // DIR_ACCESS_H
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
deleted file mode 100644
index ad234c2d49..0000000000
--- a/core/os/file_access.cpp
+++ /dev/null
@@ -1,675 +0,0 @@
-/*************************************************************************/
-/* file_access.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "file_access.h"
-
-#include "core/config/project_settings.h"
-#include "core/crypto/crypto_core.h"
-#include "core/io/file_access_pack.h"
-#include "core/io/marshalls.h"
-#include "core/os/os.h"
-
-FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = { nullptr, nullptr };
-
-FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr;
-
-bool FileAccess::backup_save = false;
-
-FileAccess *FileAccess::create(AccessType p_access) {
- ERR_FAIL_INDEX_V(p_access, ACCESS_MAX, nullptr);
-
- FileAccess *ret = create_func[p_access]();
- ret->_set_access_type(p_access);
- return ret;
-}
-
-bool FileAccess::exists(const String &p_name) {
- if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) {
- return true;
- }
-
- FileAccess *f = open(p_name, READ);
- if (!f) {
- return false;
- }
- memdelete(f);
- return true;
-}
-
-void FileAccess::_set_access_type(AccessType p_access) {
- _access_type = p_access;
-}
-
-FileAccess *FileAccess::create_for_path(const String &p_path) {
- FileAccess *ret = nullptr;
- if (p_path.begins_with("res://")) {
- ret = create(ACCESS_RESOURCES);
- } else if (p_path.begins_with("user://")) {
- ret = create(ACCESS_USERDATA);
-
- } else {
- ret = create(ACCESS_FILESYSTEM);
- }
-
- return ret;
-}
-
-Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
- return _open(p_path, p_mode_flags);
-}
-
-FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
- //try packed data first
-
- FileAccess *ret = nullptr;
- if (!(p_mode_flags & WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
- ret = PackedData::get_singleton()->try_open_path(p_path);
- if (ret) {
- if (r_error) {
- *r_error = OK;
- }
- return ret;
- }
- }
-
- ret = create_for_path(p_path);
- Error err = ret->_open(p_path, p_mode_flags);
-
- if (r_error) {
- *r_error = err;
- }
- if (err != OK) {
- memdelete(ret);
- ret = nullptr;
- }
-
- return ret;
-}
-
-FileAccess::CreateFunc FileAccess::get_create_func(AccessType p_access) {
- return create_func[p_access];
-}
-
-String FileAccess::fix_path(const String &p_path) const {
- //helper used by file accesses that use a single filesystem
-
- String r_path = p_path.replace("\\", "/");
-
- switch (_access_type) {
- case ACCESS_RESOURCES: {
- if (ProjectSettings::get_singleton()) {
- if (r_path.begins_with("res://")) {
- String resource_path = ProjectSettings::get_singleton()->get_resource_path();
- if (resource_path != "") {
- return r_path.replace("res:/", resource_path);
- }
- return r_path.replace("res://", "");
- }
- }
-
- } break;
- case ACCESS_USERDATA: {
- if (r_path.begins_with("user://")) {
- String data_dir = OS::get_singleton()->get_user_data_dir();
- if (data_dir != "") {
- return r_path.replace("user:/", data_dir);
- }
- return r_path.replace("user://", "");
- }
-
- } break;
- case ACCESS_FILESYSTEM: {
- return r_path;
- } break;
- case ACCESS_MAX:
- break; // Can't happen, but silences warning
- }
-
- return r_path;
-}
-
-/* these are all implemented for ease of porting, then can later be optimized */
-
-uint16_t FileAccess::get_16() const {
- uint16_t res;
- uint8_t a, b;
-
- a = get_8();
- b = get_8();
-
- if (endian_swap) {
- SWAP(a, b);
- }
-
- res = b;
- res <<= 8;
- res |= a;
-
- return res;
-}
-
-uint32_t FileAccess::get_32() const {
- uint32_t res;
- uint16_t a, b;
-
- a = get_16();
- b = get_16();
-
- if (endian_swap) {
- SWAP(a, b);
- }
-
- res = b;
- res <<= 16;
- res |= a;
-
- return res;
-}
-
-uint64_t FileAccess::get_64() const {
- uint64_t res;
- uint32_t a, b;
-
- a = get_32();
- b = get_32();
-
- if (endian_swap) {
- SWAP(a, b);
- }
-
- res = b;
- res <<= 32;
- res |= a;
-
- return res;
-}
-
-float FileAccess::get_float() const {
- MarshallFloat m;
- m.i = get_32();
- return m.f;
-}
-
-real_t FileAccess::get_real() const {
- if (real_is_double) {
- return get_double();
- } else {
- return get_float();
- }
-}
-
-double FileAccess::get_double() const {
- MarshallDouble m;
- m.l = get_64();
- return m.d;
-}
-
-String FileAccess::get_token() const {
- CharString token;
-
- char32_t c = get_8();
-
- while (!eof_reached()) {
- if (c <= ' ') {
- if (token.length()) {
- break;
- }
- } else {
- token += c;
- }
- c = get_8();
- }
-
- return String::utf8(token.get_data());
-}
-
-class CharBuffer {
- Vector<char> vector;
- char stack_buffer[256];
-
- char *buffer = nullptr;
- int capacity = 0;
- int written = 0;
-
- bool grow() {
- if (vector.resize(next_power_of_2(1 + written)) != OK) {
- return false;
- }
-
- if (buffer == stack_buffer) { // first chunk?
-
- for (int i = 0; i < written; i++) {
- vector.write[i] = stack_buffer[i];
- }
- }
-
- buffer = vector.ptrw();
- capacity = vector.size();
- ERR_FAIL_COND_V(written >= capacity, false);
-
- return true;
- }
-
-public:
- _FORCE_INLINE_ CharBuffer() :
- buffer(stack_buffer),
- capacity(sizeof(stack_buffer) / sizeof(char)) {
- }
-
- _FORCE_INLINE_ void push_back(char c) {
- if (written >= capacity) {
- ERR_FAIL_COND(!grow());
- }
-
- buffer[written++] = c;
- }
-
- _FORCE_INLINE_ const char *get_data() const {
- return buffer;
- }
-};
-
-String FileAccess::get_line() const {
- CharBuffer line;
-
- char32_t c = get_8();
-
- while (!eof_reached()) {
- if (c == '\n' || c == '\0') {
- line.push_back(0);
- return String::utf8(line.get_data());
- } else if (c != '\r') {
- line.push_back(c);
- }
-
- c = get_8();
- }
- line.push_back(0);
- return String::utf8(line.get_data());
-}
-
-Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
- ERR_FAIL_COND_V(p_delim.length() != 1, Vector<String>());
-
- String l;
- int qc = 0;
- do {
- if (eof_reached()) {
- break;
- }
-
- l += get_line() + "\n";
- qc = 0;
- for (int i = 0; i < l.length(); i++) {
- if (l[i] == '"') {
- qc++;
- }
- }
-
- } while (qc % 2);
-
- l = l.substr(0, l.length() - 1);
-
- Vector<String> strings;
-
- bool in_quote = false;
- String current;
- for (int i = 0; i < l.length(); i++) {
- char32_t c = l[i];
- char32_t s[2] = { 0, 0 };
-
- if (!in_quote && c == p_delim[0]) {
- strings.push_back(current);
- current = String();
- } else if (c == '"') {
- if (l[i + 1] == '"' && in_quote) {
- s[0] = '"';
- current += s;
- i++;
- } else {
- in_quote = !in_quote;
- }
- } else {
- s[0] = c;
- current += s;
- }
- }
-
- strings.push_back(current);
-
- return strings;
-}
-
-int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const {
- ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
- int i = 0;
- for (i = 0; i < p_length && !eof_reached(); i++) {
- p_dst[i] = get_8();
- }
-
- return i;
-}
-
-String FileAccess::get_as_utf8_string() const {
- Vector<uint8_t> sourcef;
- int len = get_len();
- sourcef.resize(len + 1);
-
- uint8_t *w = sourcef.ptrw();
- int r = get_buffer(w, len);
- ERR_FAIL_COND_V(r != len, String());
- w[len] = 0;
-
- String s;
- if (s.parse_utf8((const char *)w)) {
- return String();
- }
- return s;
-}
-
-void FileAccess::store_16(uint16_t p_dest) {
- uint8_t a, b;
-
- a = p_dest & 0xFF;
- b = p_dest >> 8;
-
- if (endian_swap) {
- SWAP(a, b);
- }
-
- store_8(a);
- store_8(b);
-}
-
-void FileAccess::store_32(uint32_t p_dest) {
- uint16_t a, b;
-
- a = p_dest & 0xFFFF;
- b = p_dest >> 16;
-
- if (endian_swap) {
- SWAP(a, b);
- }
-
- store_16(a);
- store_16(b);
-}
-
-void FileAccess::store_64(uint64_t p_dest) {
- uint32_t a, b;
-
- a = p_dest & 0xFFFFFFFF;
- b = p_dest >> 32;
-
- if (endian_swap) {
- SWAP(a, b);
- }
-
- store_32(a);
- store_32(b);
-}
-
-void FileAccess::store_real(real_t p_real) {
- if (sizeof(real_t) == 4) {
- store_float(p_real);
- } else {
- store_double(p_real);
- }
-}
-
-void FileAccess::store_float(float p_dest) {
- MarshallFloat m;
- m.f = p_dest;
- store_32(m.i);
-}
-
-void FileAccess::store_double(double p_dest) {
- MarshallDouble m;
- m.d = p_dest;
- store_64(m.l);
-}
-
-uint64_t FileAccess::get_modified_time(const String &p_file) {
- if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
- return 0;
- }
-
- FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
-
- uint64_t mt = fa->_get_modified_time(p_file);
- memdelete(fa);
- return mt;
-}
-
-uint32_t FileAccess::get_unix_permissions(const String &p_file) {
- if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
- return 0;
- }
-
- FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
-
- uint32_t mt = fa->_get_unix_permissions(p_file);
- memdelete(fa);
- return mt;
-}
-
-Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
- if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
- return ERR_UNAVAILABLE;
- }
-
- FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
-
- Error err = fa->_set_unix_permissions(p_file, p_permissions);
- memdelete(fa);
- return err;
-}
-
-void FileAccess::store_string(const String &p_string) {
- if (p_string.length() == 0) {
- return;
- }
-
- CharString cs = p_string.utf8();
- store_buffer((uint8_t *)&cs[0], cs.length());
-}
-
-void FileAccess::store_pascal_string(const String &p_string) {
- CharString cs = p_string.utf8();
- store_32(cs.length());
- store_buffer((uint8_t *)&cs[0], cs.length());
-}
-
-String FileAccess::get_pascal_string() {
- uint32_t sl = get_32();
- CharString cs;
- cs.resize(sl + 1);
- get_buffer((uint8_t *)cs.ptr(), sl);
- cs[sl] = 0;
-
- String ret;
- ret.parse_utf8(cs.ptr());
-
- return ret;
-}
-
-void FileAccess::store_line(const String &p_line) {
- store_string(p_line);
- store_8('\n');
-}
-
-void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
- ERR_FAIL_COND(p_delim.length() != 1);
-
- String line = "";
- int size = p_values.size();
- for (int i = 0; i < size; ++i) {
- String value = p_values[i];
-
- if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n") != -1) {
- value = "\"" + value.replace("\"", "\"\"") + "\"";
- }
- if (i < size - 1) {
- value += p_delim;
- }
-
- line += value;
- }
-
- store_line(line);
-}
-
-void FileAccess::store_buffer(const uint8_t *p_src, int p_length) {
- for (int i = 0; i < p_length; i++) {
- store_8(p_src[i]);
- }
-}
-
-Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) {
- FileAccess *f = FileAccess::open(p_path, READ, r_error);
- if (!f) {
- if (r_error) { // if error requested, do not throw error
- return Vector<uint8_t>();
- }
- ERR_FAIL_V_MSG(Vector<uint8_t>(), "Can't open file from path '" + String(p_path) + "'.");
- }
- Vector<uint8_t> data;
- data.resize(f->get_len());
- f->get_buffer(data.ptrw(), data.size());
- memdelete(f);
- return data;
-}
-
-String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
- Error err;
- Vector<uint8_t> array = get_file_as_array(p_path, &err);
- if (r_error) {
- *r_error = err;
- }
- if (err != OK) {
- if (r_error) {
- return String();
- }
- ERR_FAIL_V_MSG(String(), "Can't get file as string from path '" + String(p_path) + "'.");
- }
-
- String ret;
- ret.parse_utf8((const char *)array.ptr(), array.size());
- return ret;
-}
-
-String FileAccess::get_md5(const String &p_file) {
- FileAccess *f = FileAccess::open(p_file, READ);
- if (!f) {
- return String();
- }
-
- CryptoCore::MD5Context ctx;
- ctx.start();
-
- unsigned char step[32768];
-
- while (true) {
- int br = f->get_buffer(step, 32768);
- if (br > 0) {
- ctx.update(step, br);
- }
- if (br < 4096) {
- break;
- }
- }
-
- unsigned char hash[16];
- ctx.finish(hash);
-
- memdelete(f);
-
- return String::md5(hash);
-}
-
-String FileAccess::get_multiple_md5(const Vector<String> &p_file) {
- CryptoCore::MD5Context ctx;
- ctx.start();
-
- for (int i = 0; i < p_file.size(); i++) {
- FileAccess *f = FileAccess::open(p_file[i], READ);
- ERR_CONTINUE(!f);
-
- unsigned char step[32768];
-
- while (true) {
- int br = f->get_buffer(step, 32768);
- if (br > 0) {
- ctx.update(step, br);
- }
- if (br < 4096) {
- break;
- }
- }
- memdelete(f);
- }
-
- unsigned char hash[16];
- ctx.finish(hash);
-
- return String::md5(hash);
-}
-
-String FileAccess::get_sha256(const String &p_file) {
- FileAccess *f = FileAccess::open(p_file, READ);
- if (!f) {
- return String();
- }
-
- CryptoCore::SHA256Context ctx;
- ctx.start();
-
- unsigned char step[32768];
-
- while (true) {
- int br = f->get_buffer(step, 32768);
- if (br > 0) {
- ctx.update(step, br);
- }
- if (br < 4096) {
- break;
- }
- }
-
- unsigned char hash[32];
- ctx.finish(hash);
-
- memdelete(f);
- return String::hex_encode_buffer(hash, 32);
-}
diff --git a/core/os/file_access.h b/core/os/file_access.h
deleted file mode 100644
index 1c78204c1d..0000000000
--- a/core/os/file_access.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*************************************************************************/
-/* file_access.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef FILE_ACCESS_H
-#define FILE_ACCESS_H
-
-#include "core/math/math_defs.h"
-#include "core/os/memory.h"
-#include "core/string/ustring.h"
-#include "core/typedefs.h"
-
-/**
- * Multi-Platform abstraction for accessing to files.
- */
-
-class FileAccess {
-public:
- enum AccessType {
- ACCESS_RESOURCES,
- ACCESS_USERDATA,
- ACCESS_FILESYSTEM,
- ACCESS_MAX
- };
-
- typedef void (*FileCloseFailNotify)(const String &);
-
- typedef FileAccess *(*CreateFunc)();
- bool endian_swap = false;
- bool real_is_double = false;
-
- virtual uint32_t _get_unix_permissions(const String &p_file) = 0;
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) = 0;
-
-protected:
- String fix_path(const String &p_path) const;
- virtual Error _open(const String &p_path, int p_mode_flags) = 0; ///< open a file
- virtual uint64_t _get_modified_time(const String &p_file) = 0;
-
- static FileCloseFailNotify close_fail_notify;
-
-private:
- static bool backup_save;
-
- AccessType _access_type = ACCESS_FILESYSTEM;
- static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */
- template <class T>
- static FileAccess *_create_builtin() {
- return memnew(T);
- }
-
-public:
- static void set_file_close_fail_notify_callback(FileCloseFailNotify p_cbk) { close_fail_notify = p_cbk; }
-
- virtual void _set_access_type(AccessType p_access);
-
- enum ModeFlags {
- READ = 1,
- WRITE = 2,
- READ_WRITE = 3,
- WRITE_READ = 7,
- };
-
- virtual void close() = 0; ///< close a file
- virtual bool is_open() const = 0; ///< true when file is open
-
- virtual String get_path() const { return ""; } /// returns the path for the current open file
- virtual String get_path_absolute() const { return ""; } /// returns the absolute path for the current open file
-
- virtual void seek(size_t p_position) = 0; ///< seek to a given position
- virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file
- virtual size_t get_position() const = 0; ///< get position in the file
- virtual size_t get_len() const = 0; ///< get size of the file
-
- virtual bool eof_reached() const = 0; ///< reading passed EOF
-
- virtual uint8_t get_8() const = 0; ///< get a byte
- virtual uint16_t get_16() const; ///< get 16 bits uint
- virtual uint32_t get_32() const; ///< get 32 bits uint
- virtual uint64_t get_64() const; ///< get 64 bits uint
-
- virtual float get_float() const;
- virtual double get_double() const;
- virtual real_t get_real() const;
-
- virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes
- virtual String get_line() const;
- virtual String get_token() const;
- virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
- virtual String get_as_utf8_string() const;
-
- /**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
- * It's not about the current CPU type but file formats.
- * this flags get reset to false (little endian) on each open
- */
-
- virtual void set_endian_swap(bool p_swap) { endian_swap = p_swap; }
- inline bool get_endian_swap() const { return endian_swap; }
-
- virtual Error get_error() const = 0; ///< get last error
-
- virtual void flush() = 0;
- virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
- virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
- virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
- virtual void store_64(uint64_t p_dest); ///< store 64 bits uint
-
- virtual void store_float(float p_dest);
- virtual void store_double(double p_dest);
- virtual void store_real(real_t p_real);
-
- virtual void store_string(const String &p_string);
- virtual void store_line(const String &p_line);
- virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
-
- virtual void store_pascal_string(const String &p_string);
- virtual String get_pascal_string();
-
- virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
-
- virtual bool file_exists(const String &p_name) = 0; ///< return true if a file exists
-
- virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
-
- static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
- static FileAccess *create_for_path(const String &p_path);
- static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files.
- static CreateFunc get_create_func(AccessType p_access);
- static bool exists(const String &p_name); ///< return true if a file exists
- static uint64_t get_modified_time(const String &p_file);
- static uint32_t get_unix_permissions(const String &p_file);
- static Error set_unix_permissions(const String &p_file, uint32_t p_permissions);
-
- static void set_backup_save(bool p_enable) { backup_save = p_enable; };
- static bool is_backup_save_enabled() { return backup_save; };
-
- static String get_md5(const String &p_file);
- static String get_sha256(const String &p_file);
- static String get_multiple_md5(const Vector<String> &p_file);
-
- static Vector<uint8_t> get_file_as_array(const String &p_path, Error *r_error = nullptr);
- static String get_file_as_string(const String &p_path, Error *r_error = nullptr);
-
- template <class T>
- static void make_default(AccessType p_access) {
- create_func[p_access] = _create_builtin<T>;
- }
-
- FileAccess() {}
- virtual ~FileAccess() {}
-};
-
-struct FileAccessRef {
- _FORCE_INLINE_ FileAccess *operator->() {
- return f;
- }
-
- operator bool() const { return f != nullptr; }
-
- FileAccess *f;
-
- operator FileAccess *() { return f; }
-
- FileAccessRef(FileAccess *fa) { f = fa; }
- ~FileAccessRef() {
- if (f) {
- memdelete(f);
- }
- }
-};
-
-#endif // FILE_ACCESS_H
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index 4b2cafd8fe..4c5f0b5220 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -60,7 +60,7 @@ static const _KeyCodeText _keycodes[] = {
{KEY_PAGEUP ,"PageUp"},
{KEY_PAGEDOWN ,"PageDown"},
{KEY_SHIFT ,"Shift"},
- {KEY_CONTROL ,"Control"},
+ {KEY_CTRL ,"Ctrl"},
#ifdef OSX_ENABLED
{KEY_META ,"Command"},
#else
@@ -314,7 +314,7 @@ bool keycode_has_unicode(uint32_t p_keycode) {
case KEY_PAGEUP:
case KEY_PAGEDOWN:
case KEY_SHIFT:
- case KEY_CONTROL:
+ case KEY_CTRL:
case KEY_META:
case KEY_ALT:
case KEY_CAPSLOCK:
@@ -401,7 +401,7 @@ String keycode_get_string(uint32_t p_code) {
codestr += "+";
}
if (p_code & KEY_MASK_CTRL) {
- codestr += find_keycode_name(KEY_CONTROL);
+ codestr += find_keycode_name(KEY_CTRL);
codestr += "+";
}
if (p_code & KEY_MASK_META) {
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index f6fe5fc070..33f9213c4e 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -68,7 +68,7 @@ enum Key {
KEY_PAGEUP = SPKEY | 0x13,
KEY_PAGEDOWN = SPKEY | 0x14,
KEY_SHIFT = SPKEY | 0x15,
- KEY_CONTROL = SPKEY | 0x16,
+ KEY_CTRL = SPKEY | 0x16,
KEY_META = SPKEY | 0x17,
KEY_ALT = SPKEY | 0x18,
KEY_CAPSLOCK = SPKEY | 0x19,
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index 25a09fe98f..34e944709b 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -32,7 +32,7 @@
#define MAIN_LOOP_H
#include "core/input/input_event.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
class MainLoop : public Object {
diff --git a/core/os/os.cpp b/core/os/os.cpp
index ca1b798e11..535eee4797 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -32,8 +32,8 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/os/midi_driver.h"
#include "core/version_generated.gen.h"
#include "servers/audio_server.h"
@@ -47,37 +47,8 @@ OS *OS::get_singleton() {
return singleton;
}
-uint32_t OS::get_ticks_msec() const {
- return get_ticks_usec() / 1000;
-}
-
-String OS::get_iso_date_time(bool local) const {
- OS::Date date = get_date(local);
- OS::Time time = get_time(local);
-
- String timezone;
- if (!local) {
- TimeZoneInfo zone = get_time_zone_info();
- if (zone.bias >= 0) {
- timezone = "+";
- }
- timezone = timezone + itos(zone.bias / 60).pad_zeros(2) + itos(zone.bias % 60).pad_zeros(2);
- } else {
- timezone = "Z";
- }
-
- return itos(date.year).pad_zeros(2) +
- "-" +
- itos(date.month).pad_zeros(2) +
- "-" +
- itos(date.day).pad_zeros(2) +
- "T" +
- itos(time.hour).pad_zeros(2) +
- ":" +
- itos(time.min).pad_zeros(2) +
- ":" +
- itos(time.sec).pad_zeros(2) +
- timezone;
+uint64_t OS::get_ticks_msec() const {
+ return get_ticks_usec() / 1000ULL;
}
double OS::get_unix_time() const {
@@ -310,6 +281,11 @@ String OS::get_user_data_dir() const {
return ".";
}
+// Android OS path to app's external data storage
+String OS::get_external_data_dir() const {
+ return get_user_data_dir();
+};
+
// Absolute path to res://
String OS::get_resource_dir() const {
return ProjectSettings::get_singleton()->get_resource_path();
diff --git a/core/os/os.h b/core/os/os.h
index 7198607237..444f67431f 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -158,17 +158,17 @@ public:
virtual void yield();
- enum Weekday {
- DAY_SUNDAY,
- DAY_MONDAY,
- DAY_TUESDAY,
- DAY_WEDNESDAY,
- DAY_THURSDAY,
- DAY_FRIDAY,
- DAY_SATURDAY
+ enum Weekday : uint8_t {
+ WEEKDAY_SUNDAY,
+ WEEKDAY_MONDAY,
+ WEEKDAY_TUESDAY,
+ WEEKDAY_WEDNESDAY,
+ WEEKDAY_THURSDAY,
+ WEEKDAY_FRIDAY,
+ WEEKDAY_SATURDAY,
};
- enum Month {
+ enum Month : uint8_t {
/// Start at 1 to follow Windows SYSTEMTIME structure
/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx
MONTH_JANUARY = 1,
@@ -182,21 +182,21 @@ public:
MONTH_SEPTEMBER,
MONTH_OCTOBER,
MONTH_NOVEMBER,
- MONTH_DECEMBER
+ MONTH_DECEMBER,
};
struct Date {
- int year;
+ int64_t year;
Month month;
- int day;
+ uint8_t day;
Weekday weekday;
bool dst;
};
struct Time {
- int hour;
- int min;
- int sec;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
};
struct TimeZoneInfo {
@@ -207,14 +207,13 @@ public:
virtual Date get_date(bool local = false) const = 0;
virtual Time get_time(bool local = false) const = 0;
virtual TimeZoneInfo get_time_zone_info() const = 0;
- virtual String get_iso_date_time(bool local = false) const;
virtual double get_unix_time() const;
virtual void delay_usec(uint32_t p_usec) const = 0;
virtual void add_frame_delay(bool p_can_draw);
virtual uint64_t get_ticks_usec() const = 0;
- uint32_t get_ticks_msec() const;
+ uint64_t get_ticks_msec() const;
virtual bool is_userfs_persistent() const { return true; }
@@ -252,6 +251,7 @@ public:
virtual String get_bundle_resource_dir() const;
virtual String get_user_data_dir() const;
+ virtual String get_external_data_dir() const;
virtual String get_resource_dir() const;
enum SystemDir {
diff --git a/core/os/time.cpp b/core/os/time.cpp
new file mode 100644
index 0000000000..a185029969
--- /dev/null
+++ b/core/os/time.cpp
@@ -0,0 +1,433 @@
+/*************************************************************************/
+/* time.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "time.h"
+
+#include "core/os/os.h"
+
+#define UNIX_EPOCH_YEAR_AD 1970 // 1970
+#define SECONDS_PER_DAY (24 * 60 * 60) // 86400
+#define IS_LEAP_YEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
+#define YEAR_SIZE(year) (IS_LEAP_YEAR(year) ? 366 : 365)
+
+#define YEAR_KEY "year"
+#define MONTH_KEY "month"
+#define DAY_KEY "day"
+#define WEEKDAY_KEY "weekday"
+#define HOUR_KEY "hour"
+#define MINUTE_KEY "minute"
+#define SECOND_KEY "second"
+#define DST_KEY "dst"
+
+// Table of number of days in each month (for regular year and leap year).
+static const uint8_t MONTH_DAYS_TABLE[2][12] = {
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+VARIANT_ENUM_CAST(Time::Month);
+VARIANT_ENUM_CAST(Time::Weekday);
+
+#define UNIX_TIME_TO_HMS \
+ uint8_t hour, minute, second; \
+ { \
+ /* The time of the day (in seconds since start of day). */ \
+ uint32_t day_clock = Math::posmod(p_unix_time_val, SECONDS_PER_DAY); \
+ /* On x86 these 4 lines can be optimized to only 2 divisions. */ \
+ second = day_clock % 60; \
+ day_clock /= 60; \
+ minute = day_clock % 60; \
+ hour = day_clock / 60; \
+ }
+
+#define UNIX_TIME_TO_YMD \
+ int64_t year; \
+ Month month; \
+ uint8_t day; \
+ /* The day number since Unix epoch (0-index). Days before 1970 are negative. */ \
+ int64_t day_number = Math::floor(p_unix_time_val / (double)SECONDS_PER_DAY); \
+ { \
+ int64_t day_number_copy = day_number; \
+ year = UNIX_EPOCH_YEAR_AD; \
+ uint8_t month_zero_index = 0; \
+ while (day_number_copy >= YEAR_SIZE(year)) { \
+ day_number_copy -= YEAR_SIZE(year); \
+ year++; \
+ } \
+ while (day_number_copy < 0) { \
+ year--; \
+ day_number_copy += YEAR_SIZE(year); \
+ } \
+ /* After the above, day_number now represents the day of the year (0-index). */ \
+ while (day_number_copy >= MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month_zero_index]) { \
+ day_number_copy -= MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month_zero_index]; \
+ month_zero_index++; \
+ } \
+ /* After the above, day_number now represents the day of the month (0-index). */ \
+ month = (Month)(month_zero_index + 1); \
+ day = day_number_copy + 1; \
+ }
+
+#define VALIDATE_YMDHMS \
+ ERR_FAIL_COND_V_MSG(month == 0, 0, "Invalid month value of: " + itos(month) + ", months are 1-indexed and cannot be 0. See the Time.Month enum for valid values."); \
+ ERR_FAIL_COND_V_MSG(month > 12, 0, "Invalid month value of: " + itos(month) + ". See the Time.Month enum for valid values."); \
+ ERR_FAIL_COND_V_MSG(hour > 23, 0, "Invalid hour value of: " + itos(hour) + "."); \
+ ERR_FAIL_COND_V_MSG(minute > 59, 0, "Invalid minute value of: " + itos(minute) + "."); \
+ ERR_FAIL_COND_V_MSG(second > 59, 0, "Invalid second value of: " + itos(second) + " (leap seconds are not supported)."); \
+ /* Do this check after month is tested as valid. */ \
+ ERR_FAIL_COND_V_MSG(day == 0, 0, "Invalid day value of: " + itos(month) + ", days are 1-indexed and cannot be 0."); \
+ uint8_t days_in_this_month = MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month - 1]; \
+ ERR_FAIL_COND_V_MSG(day > days_in_this_month, 0, "Invalid day value of: " + itos(day) + " which is larger than the maximum for this month, " + itos(days_in_this_month) + ".");
+
+#define YMD_TO_DAY_NUMBER \
+ /* The day number since Unix epoch (0-index). Days before 1970 are negative. */ \
+ int64_t day_number = day - 1; \
+ /* Add the days in the months to day_number. */ \
+ for (int i = 0; i < month - 1; i++) { \
+ day_number += MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][i]; \
+ } \
+ /* Add the days in the years to day_number. */ \
+ if (year >= UNIX_EPOCH_YEAR_AD) { \
+ for (int64_t iyear = UNIX_EPOCH_YEAR_AD; iyear < year; iyear++) { \
+ day_number += YEAR_SIZE(iyear); \
+ } \
+ } else { \
+ for (int64_t iyear = UNIX_EPOCH_YEAR_AD - 1; iyear >= year; iyear--) { \
+ day_number -= YEAR_SIZE(iyear); \
+ } \
+ }
+
+#define PARSE_ISO8601_STRING \
+ int64_t year = UNIX_EPOCH_YEAR_AD; \
+ Month month = MONTH_JANUARY; \
+ uint8_t day = 1; \
+ uint8_t hour = 0; \
+ uint8_t minute = 0; \
+ uint8_t second = 0; \
+ { \
+ bool has_date = false, has_time = false; \
+ String date, time; \
+ if (p_datetime.find_char('T') > 0) { \
+ has_date = has_time = true; \
+ PackedStringArray array = p_datetime.split("T"); \
+ date = array[0]; \
+ time = array[1]; \
+ } else if (p_datetime.find_char(' ') > 0) { \
+ has_date = has_time = true; \
+ PackedStringArray array = p_datetime.split(" "); \
+ date = array[0]; \
+ time = array[1]; \
+ } else if (p_datetime.find_char('-', 1) > 0) { \
+ has_date = true; \
+ date = p_datetime; \
+ } else if (p_datetime.find_char(':') > 0) { \
+ has_time = true; \
+ time = p_datetime; \
+ } \
+ /* Set the variables from the contents of the string. */ \
+ if (has_date) { \
+ PackedInt32Array array = date.split_ints("-", false); \
+ year = array[0]; \
+ month = (Month)array[1]; \
+ day = array[2]; \
+ /* Handle negative years. */ \
+ if (p_datetime.find_char('-') == 0) { \
+ year *= -1; \
+ } \
+ } \
+ if (has_time) { \
+ PackedInt32Array array = time.split_ints(":", false); \
+ hour = array[0]; \
+ minute = array[1]; \
+ second = array[2]; \
+ } \
+ }
+
+#define EXTRACT_FROM_DICTIONARY \
+ /* Get all time values from the dictionary. If it doesn't exist, set the */ \
+ /* values to the default values for Unix epoch (1970-01-01 00:00:00). */ \
+ int64_t year = p_datetime.has(YEAR_KEY) ? int64_t(p_datetime[YEAR_KEY]) : UNIX_EPOCH_YEAR_AD; \
+ Month month = Month((p_datetime.has(MONTH_KEY)) ? uint8_t(p_datetime[MONTH_KEY]) : 1); \
+ uint8_t day = p_datetime.has(DAY_KEY) ? uint8_t(p_datetime[DAY_KEY]) : 1; \
+ uint8_t hour = p_datetime.has(HOUR_KEY) ? uint8_t(p_datetime[HOUR_KEY]) : 0; \
+ uint8_t minute = p_datetime.has(MINUTE_KEY) ? uint8_t(p_datetime[MINUTE_KEY]) : 0; \
+ uint8_t second = p_datetime.has(SECOND_KEY) ? uint8_t(p_datetime[SECOND_KEY]) : 0;
+
+Time *Time::singleton = nullptr;
+
+Time *Time::get_singleton() {
+ if (!singleton) {
+ memnew(Time);
+ }
+ return singleton;
+}
+
+Dictionary Time::get_datetime_dict_from_unix_time(int64_t p_unix_time_val) const {
+ UNIX_TIME_TO_HMS
+ UNIX_TIME_TO_YMD
+ Dictionary datetime;
+ datetime[YEAR_KEY] = year;
+ datetime[MONTH_KEY] = (uint8_t)month;
+ datetime[DAY_KEY] = day;
+ // Unix epoch was a Thursday (day 0 aka 1970-01-01).
+ datetime[WEEKDAY_KEY] = Math::posmod(day_number + WEEKDAY_THURSDAY, 7);
+ datetime[HOUR_KEY] = hour;
+ datetime[MINUTE_KEY] = minute;
+ datetime[SECOND_KEY] = second;
+
+ return datetime;
+}
+
+Dictionary Time::get_date_dict_from_unix_time(int64_t p_unix_time_val) const {
+ UNIX_TIME_TO_YMD
+ Dictionary datetime;
+ datetime[YEAR_KEY] = year;
+ datetime[MONTH_KEY] = (uint8_t)month;
+ datetime[DAY_KEY] = day;
+ // Unix epoch was a Thursday (day 0 aka 1970-01-01).
+ datetime[WEEKDAY_KEY] = Math::posmod(day_number + WEEKDAY_THURSDAY, 7);
+
+ return datetime;
+}
+
+Dictionary Time::get_time_dict_from_unix_time(int64_t p_unix_time_val) const {
+ UNIX_TIME_TO_HMS
+ Dictionary datetime;
+ datetime[HOUR_KEY] = hour;
+ datetime[MINUTE_KEY] = minute;
+ datetime[SECOND_KEY] = second;
+
+ return datetime;
+}
+
+String Time::get_datetime_string_from_unix_time(int64_t p_unix_time_val, bool p_use_space) const {
+ UNIX_TIME_TO_HMS
+ UNIX_TIME_TO_YMD
+ // vformat only supports up to 6 arguments, so we need to split this up into 2 parts.
+ String timestamp = vformat("%04d-%02d-%02d", year, (uint8_t)month, day);
+ if (p_use_space) {
+ timestamp = vformat("%s %02d:%02d:%02d", timestamp, hour, minute, second);
+ } else {
+ timestamp = vformat("%sT%02d:%02d:%02d", timestamp, hour, minute, second);
+ }
+
+ return timestamp;
+}
+
+String Time::get_date_string_from_unix_time(int64_t p_unix_time_val) const {
+ UNIX_TIME_TO_YMD
+ // Android is picky about the types passed to make Variant, so we need a cast.
+ return vformat("%04d-%02d-%02d", year, (uint8_t)month, day);
+}
+
+String Time::get_time_string_from_unix_time(int64_t p_unix_time_val) const {
+ UNIX_TIME_TO_HMS
+ return vformat("%02d:%02d:%02d", hour, minute, second);
+}
+
+Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday) const {
+ PARSE_ISO8601_STRING
+ Dictionary dict;
+ dict[YEAR_KEY] = year;
+ dict[MONTH_KEY] = (uint8_t)month;
+ dict[DAY_KEY] = day;
+ if (p_weekday) {
+ YMD_TO_DAY_NUMBER
+ // Unix epoch was a Thursday (day 0 aka 1970-01-01).
+ dict[WEEKDAY_KEY] = Math::posmod(day_number + WEEKDAY_THURSDAY, 7);
+ }
+ dict[HOUR_KEY] = hour;
+ dict[MINUTE_KEY] = minute;
+ dict[SECOND_KEY] = second;
+
+ return dict;
+}
+
+String Time::get_datetime_string_from_dict(Dictionary p_datetime, bool p_use_space) const {
+ ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), "", "Invalid datetime Dictionary: Dictionary is empty.");
+ EXTRACT_FROM_DICTIONARY
+ // vformat only supports up to 6 arguments, so we need to split this up into 2 parts.
+ String timestamp = vformat("%04d-%02d-%02d", year, (uint8_t)month, day);
+ if (p_use_space) {
+ timestamp = vformat("%s %02d:%02d:%02d", timestamp, hour, minute, second);
+ } else {
+ timestamp = vformat("%sT%02d:%02d:%02d", timestamp, hour, minute, second);
+ }
+ return timestamp;
+}
+
+int64_t Time::get_unix_time_from_datetime_dict(Dictionary p_datetime) const {
+ ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty");
+ EXTRACT_FROM_DICTIONARY
+ VALIDATE_YMDHMS
+ YMD_TO_DAY_NUMBER
+ return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second;
+}
+
+int64_t Time::get_unix_time_from_datetime_string(String p_datetime) const {
+ PARSE_ISO8601_STRING
+ VALIDATE_YMDHMS
+ YMD_TO_DAY_NUMBER
+ return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second;
+}
+
+Dictionary Time::get_datetime_dict_from_system(bool p_utc) const {
+ OS::Date date = OS::get_singleton()->get_date(p_utc);
+ OS::Time time = OS::get_singleton()->get_time(p_utc);
+ Dictionary datetime;
+ datetime[YEAR_KEY] = date.year;
+ datetime[MONTH_KEY] = (uint8_t)date.month;
+ datetime[DAY_KEY] = date.day;
+ datetime[WEEKDAY_KEY] = (uint8_t)date.weekday;
+ datetime[DST_KEY] = date.dst;
+ datetime[HOUR_KEY] = time.hour;
+ datetime[MINUTE_KEY] = time.minute;
+ datetime[SECOND_KEY] = time.second;
+ return datetime;
+}
+
+Dictionary Time::get_date_dict_from_system(bool p_utc) const {
+ OS::Date date = OS::get_singleton()->get_date(p_utc);
+ Dictionary date_dictionary;
+ date_dictionary[YEAR_KEY] = date.year;
+ date_dictionary[MONTH_KEY] = (uint8_t)date.month;
+ date_dictionary[DAY_KEY] = date.day;
+ date_dictionary[WEEKDAY_KEY] = (uint8_t)date.weekday;
+ date_dictionary[DST_KEY] = date.dst;
+ return date_dictionary;
+}
+
+Dictionary Time::get_time_dict_from_system(bool p_utc) const {
+ OS::Time time = OS::get_singleton()->get_time(p_utc);
+ Dictionary time_dictionary;
+ time_dictionary[HOUR_KEY] = time.hour;
+ time_dictionary[MINUTE_KEY] = time.minute;
+ time_dictionary[SECOND_KEY] = time.second;
+ return time_dictionary;
+}
+
+String Time::get_datetime_string_from_system(bool p_utc, bool p_use_space) const {
+ OS::Date date = OS::get_singleton()->get_date(p_utc);
+ OS::Time time = OS::get_singleton()->get_time(p_utc);
+ // vformat only supports up to 6 arguments, so we need to split this up into 2 parts.
+ String timestamp = vformat("%04d-%02d-%02d", date.year, (uint8_t)date.month, date.day);
+ if (p_use_space) {
+ timestamp = vformat("%s %02d:%02d:%02d", timestamp, time.hour, time.minute, time.second);
+ } else {
+ timestamp = vformat("%sT%02d:%02d:%02d", timestamp, time.hour, time.minute, time.second);
+ }
+
+ return timestamp;
+}
+
+String Time::get_date_string_from_system(bool p_utc) const {
+ OS::Date date = OS::get_singleton()->get_date(p_utc);
+ // Android is picky about the types passed to make Variant, so we need a cast.
+ return vformat("%04d-%02d-%02d", date.year, (uint8_t)date.month, date.day);
+}
+
+String Time::get_time_string_from_system(bool p_utc) const {
+ OS::Time time = OS::get_singleton()->get_time(p_utc);
+ return vformat("%02d:%02d:%02d", time.hour, time.minute, time.second);
+}
+
+Dictionary Time::get_time_zone_from_system() const {
+ OS::TimeZoneInfo info = OS::get_singleton()->get_time_zone_info();
+ Dictionary timezone;
+ timezone["bias"] = info.bias;
+ timezone["name"] = info.name;
+ return timezone;
+}
+
+double Time::get_unix_time_from_system() const {
+ return OS::get_singleton()->get_unix_time();
+}
+
+uint64_t Time::get_ticks_msec() const {
+ return OS::get_singleton()->get_ticks_msec();
+}
+
+uint64_t Time::get_ticks_usec() const {
+ return OS::get_singleton()->get_ticks_usec();
+}
+
+void Time::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_datetime_dict_from_unix_time", "unix_time_val"), &Time::get_datetime_dict_from_unix_time);
+ ClassDB::bind_method(D_METHOD("get_date_dict_from_unix_time", "unix_time_val"), &Time::get_date_dict_from_unix_time);
+ ClassDB::bind_method(D_METHOD("get_time_dict_from_unix_time", "unix_time_val"), &Time::get_time_dict_from_unix_time);
+ ClassDB::bind_method(D_METHOD("get_datetime_string_from_unix_time", "unix_time_val", "use_space"), &Time::get_datetime_string_from_unix_time, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_date_string_from_unix_time", "unix_time_val"), &Time::get_date_string_from_unix_time);
+ ClassDB::bind_method(D_METHOD("get_time_string_from_unix_time", "unix_time_val"), &Time::get_time_string_from_unix_time);
+ ClassDB::bind_method(D_METHOD("get_datetime_dict_from_string", "datetime", "weekday"), &Time::get_datetime_dict_from_string);
+ ClassDB::bind_method(D_METHOD("get_datetime_string_from_dict", "datetime", "use_space"), &Time::get_datetime_string_from_dict);
+ ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime_dict", "datetime"), &Time::get_unix_time_from_datetime_dict);
+ ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime_string", "datetime"), &Time::get_unix_time_from_datetime_string);
+
+ ClassDB::bind_method(D_METHOD("get_datetime_dict_from_system", "utc"), &Time::get_datetime_dict_from_system, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_date_dict_from_system", "utc"), &Time::get_date_dict_from_system, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_time_dict_from_system", "utc"), &Time::get_time_dict_from_system, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_datetime_string_from_system", "utc", "use_space"), &Time::get_datetime_string_from_system, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_date_string_from_system", "utc"), &Time::get_date_string_from_system, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_time_string_from_system", "utc"), &Time::get_time_string_from_system, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_time_zone_from_system"), &Time::get_time_zone_from_system);
+ ClassDB::bind_method(D_METHOD("get_unix_time_from_system"), &Time::get_unix_time_from_system);
+ ClassDB::bind_method(D_METHOD("get_ticks_msec"), &Time::get_ticks_msec);
+ ClassDB::bind_method(D_METHOD("get_ticks_usec"), &Time::get_ticks_usec);
+
+ BIND_ENUM_CONSTANT(MONTH_JANUARY);
+ BIND_ENUM_CONSTANT(MONTH_FEBRUARY);
+ BIND_ENUM_CONSTANT(MONTH_MARCH);
+ BIND_ENUM_CONSTANT(MONTH_APRIL);
+ BIND_ENUM_CONSTANT(MONTH_MAY);
+ BIND_ENUM_CONSTANT(MONTH_JUNE);
+ BIND_ENUM_CONSTANT(MONTH_JULY);
+ BIND_ENUM_CONSTANT(MONTH_AUGUST);
+ BIND_ENUM_CONSTANT(MONTH_SEPTEMBER);
+ BIND_ENUM_CONSTANT(MONTH_OCTOBER);
+ BIND_ENUM_CONSTANT(MONTH_NOVEMBER);
+ BIND_ENUM_CONSTANT(MONTH_DECEMBER);
+
+ BIND_ENUM_CONSTANT(WEEKDAY_SUNDAY);
+ BIND_ENUM_CONSTANT(WEEKDAY_MONDAY);
+ BIND_ENUM_CONSTANT(WEEKDAY_TUESDAY);
+ BIND_ENUM_CONSTANT(WEEKDAY_WEDNESDAY);
+ BIND_ENUM_CONSTANT(WEEKDAY_THURSDAY);
+ BIND_ENUM_CONSTANT(WEEKDAY_FRIDAY);
+ BIND_ENUM_CONSTANT(WEEKDAY_SATURDAY);
+}
+
+Time::Time() {
+ ERR_FAIL_COND_MSG(singleton, "Singleton for Time already exists.");
+ singleton = this;
+}
+
+Time::~Time() {
+ singleton = nullptr;
+}
diff --git a/core/os/time.h b/core/os/time.h
new file mode 100644
index 0000000000..4325f93d56
--- /dev/null
+++ b/core/os/time.h
@@ -0,0 +1,109 @@
+/*************************************************************************/
+/* time.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TIME_H
+#define TIME_H
+
+#include "core/object/class_db.h"
+
+// This Time class conforms with as many of the ISO 8601 standards as possible.
+// * As per ISO 8601:2004 4.3.2.1, all dates follow the Proleptic Gregorian
+// calendar. As such, the day before 1582-10-15 is 1582-10-14, not 1582-10-04.
+// See: https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar
+// * As per ISO 8601:2004 3.4.2 and 4.1.2.4, the year before 1 AD (aka 1 BC)
+// is number "0", with the year before that (2 BC) being "-1", etc.
+// Conversion methods assume "the same timezone", and do not handle DST.
+// Leap seconds are not handled, they must be done manually if desired.
+// Suffixes such as "Z" are not handled, you need to strip them away manually.
+
+class Time : public Object {
+ GDCLASS(Time, Object);
+ static void _bind_methods();
+ static Time *singleton;
+
+public:
+ static Time *get_singleton();
+
+ enum Month : uint8_t {
+ /// Start at 1 to follow Windows SYSTEMTIME structure
+ /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx
+ MONTH_JANUARY = 1,
+ MONTH_FEBRUARY,
+ MONTH_MARCH,
+ MONTH_APRIL,
+ MONTH_MAY,
+ MONTH_JUNE,
+ MONTH_JULY,
+ MONTH_AUGUST,
+ MONTH_SEPTEMBER,
+ MONTH_OCTOBER,
+ MONTH_NOVEMBER,
+ MONTH_DECEMBER,
+ };
+
+ enum Weekday : uint8_t {
+ WEEKDAY_SUNDAY,
+ WEEKDAY_MONDAY,
+ WEEKDAY_TUESDAY,
+ WEEKDAY_WEDNESDAY,
+ WEEKDAY_THURSDAY,
+ WEEKDAY_FRIDAY,
+ WEEKDAY_SATURDAY,
+ };
+
+ // Methods that convert times.
+ Dictionary get_datetime_dict_from_unix_time(int64_t p_unix_time_val) const;
+ Dictionary get_date_dict_from_unix_time(int64_t p_unix_time_val) const;
+ Dictionary get_time_dict_from_unix_time(int64_t p_unix_time_val) const;
+ String get_datetime_string_from_unix_time(int64_t p_unix_time_val, bool p_use_space = false) const;
+ String get_date_string_from_unix_time(int64_t p_unix_time_val) const;
+ String get_time_string_from_unix_time(int64_t p_unix_time_val) const;
+ Dictionary get_datetime_dict_from_string(String p_datetime, bool p_weekday = true) const;
+ String get_datetime_string_from_dict(Dictionary p_datetime, bool p_use_space = false) const;
+ int64_t get_unix_time_from_datetime_dict(Dictionary p_datetime) const;
+ int64_t get_unix_time_from_datetime_string(String p_datetime) const;
+
+ // Methods that get information from OS.
+ Dictionary get_datetime_dict_from_system(bool p_utc = false) const;
+ Dictionary get_date_dict_from_system(bool p_utc = false) const;
+ Dictionary get_time_dict_from_system(bool p_utc = false) const;
+ String get_datetime_string_from_system(bool p_utc = false, bool p_use_space = false) const;
+ String get_date_string_from_system(bool p_utc = false) const;
+ String get_time_string_from_system(bool p_utc = false) const;
+ Dictionary get_time_zone_from_system() const;
+ double get_unix_time_from_system() const;
+ uint64_t get_ticks_msec() const;
+ uint64_t get_ticks_usec() const;
+
+ Time();
+ virtual ~Time();
+};
+
+#endif // TIME_H
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index f1b1b98bea..f67d615418 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -68,6 +68,7 @@
#include "core/object/class_db.h"
#include "core/object/undo_redo.h"
#include "core/os/main_loop.h"
+#include "core/os/time.h"
#include "core/string/optimized_translation.h"
#include "core/string/translation.h"
@@ -131,7 +132,7 @@ void register_core_types() {
ClassDB::register_virtual_class<Script>();
- ClassDB::register_class<Reference>();
+ ClassDB::register_class<RefCounted>();
ClassDB::register_class<WeakRef>();
ClassDB::register_class<Resource>();
ClassDB::register_class<Image>();
@@ -258,6 +259,7 @@ void register_core_singletons() {
ClassDB::register_class<_JSON>();
ClassDB::register_class<Expression>();
ClassDB::register_class<_EngineDebugger>();
+ ClassDB::register_class<Time>();
Engine::get_singleton()->add_singleton(Engine::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton()));
@@ -274,6 +276,7 @@ void register_core_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("JSON", _JSON::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", _EngineDebugger::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton()));
}
void unregister_core_types() {
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index ad768f7140..d6b84cabc9 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -30,7 +30,7 @@
#include "translation_po.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#ifdef DEBUG_TRANSLATION_PO
void TranslationPO::print_translation_map() {
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index bdb66526a4..83ede0b11b 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -54,7 +54,7 @@
#define snprintf _snprintf_s
#endif
-#define MAX_DIGITS 6
+#define MAX_DECIMALS 32
#define UPPERCASE(m_c) (((m_c) >= 'a' && (m_c) <= 'z') ? ((m_c) - ('a' - 'A')) : (m_c))
#define LOWERCASE(m_c) (((m_c) >= 'A' && (m_c) <= 'Z') ? ((m_c) + ('a' - 'A')) : (m_c))
#define IS_DIGIT(m_d) ((m_d) >= '0' && (m_d) <= '9')
@@ -939,7 +939,7 @@ const char32_t *String::get_data() const {
}
void String::erase(int p_pos, int p_chars) {
- *this = left(p_pos) + substr(p_pos + p_chars, length() - ((p_pos + p_chars)));
+ *this = left(MAX(p_pos, 0)) + substr(p_pos + p_chars, length() - ((p_pos + p_chars)));
}
String String::capitalize() const {
@@ -1379,8 +1379,11 @@ String String::num(double p_num, int p_decimals) {
}
#ifndef NO_USE_STDLIB
- if (p_decimals > 16) {
- p_decimals = 16;
+ if (p_decimals < 0) {
+ p_decimals = 14 - (int)floor(log10(p_num));
+ }
+ if (p_decimals > MAX_DECIMALS) {
+ p_decimals = MAX_DECIMALS;
}
char fmt[7];
@@ -1391,7 +1394,6 @@ String String::num(double p_num, int p_decimals) {
fmt[1] = 'l';
fmt[2] = 'f';
fmt[3] = 0;
-
} else if (p_decimals < 10) {
fmt[2] = '0' + p_decimals;
fmt[3] = 'l';
@@ -1458,8 +1460,9 @@ String String::num(double p_num, int p_decimals) {
double dec = p_num - (double)((int)p_num);
int digit = 0;
- if (p_decimals > MAX_DIGITS)
- p_decimals = MAX_DIGITS;
+ if (p_decimals > MAX_DECIMALS) {
+ p_decimals = MAX_DECIMALS;
+ }
int dec_int = 0;
int dec_max = 0;
@@ -1471,16 +1474,18 @@ String String::num(double p_num, int p_decimals) {
digit++;
if (p_decimals == -1) {
- if (digit == MAX_DIGITS) //no point in going to infinite
+ if (digit == MAX_DECIMALS) { //no point in going to infinite
break;
+ }
if (dec - (double)((int)dec) < 1e-6) {
break;
}
}
- if (digit == p_decimals)
+ if (digit == p_decimals) {
break;
+ }
}
dec *= 10;
int last = (int)dec % 10;
@@ -1589,7 +1594,7 @@ String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) {
return s;
}
-String String::num_real(double p_num) {
+String String::num_real(double p_num, bool p_trailing) {
if (Math::is_nan(p_num)) {
return "nan";
}
@@ -1616,7 +1621,15 @@ String String::num_real(double p_num) {
double dec = p_num - (double)((int)p_num);
int digit = 0;
- int decimals = MAX_DIGITS;
+
+#if REAL_T_IS_DOUBLE
+ int decimals = 14 - (int)floor(log10(p_num));
+#else
+ int decimals = 6 - (int)floor(log10(p_num));
+#endif
+ if (decimals > MAX_DECIMALS) {
+ decimals = MAX_DECIMALS;
+ }
int dec_int = 0;
int dec_max = 0;
@@ -1656,8 +1669,10 @@ String String::num_real(double p_num) {
dec_int /= 10;
}
sd = '.' + decimal;
- } else {
+ } else if (p_trailing) {
sd = ".0";
+ } else {
+ sd = "";
}
if (intn == 0) {
@@ -3382,14 +3397,14 @@ String String::format(const Variant &values, String placeholder) const {
if (value_arr.size() == 2) {
Variant v_key = value_arr[0];
String key = v_key;
- if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") {
+ if (key.left(1) == "\"" && key.right(1) == "\"") {
key = key.substr(1, key.length() - 2);
}
Variant v_val = value_arr[1];
String val = v_val;
- if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+ if (val.left(1) == "\"" && val.right(1) == "\"") {
val = val.substr(1, val.length() - 2);
}
@@ -3401,7 +3416,7 @@ String String::format(const Variant &values, String placeholder) const {
Variant v_val = values_arr[i];
String val = v_val;
- if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+ if (val.left(1) == "\"" && val.right(1) == "\"") {
val = val.substr(1, val.length() - 2);
}
@@ -3421,11 +3436,11 @@ String String::format(const Variant &values, String placeholder) const {
String key = E->get();
String val = d[E->get()];
- if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") {
+ if (key.left(1) == "\"" && key.right(1) == "\"") {
key = key.substr(1, key.length() - 2);
}
- if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+ if (val.left(1) == "\"" && val.right(1) == "\"") {
val = val.substr(1, val.length() - 2);
}
@@ -3529,6 +3544,10 @@ String String::repeat(int p_count) const {
}
String String::left(int p_pos) const {
+ if (p_pos < 0) {
+ p_pos = length() + p_pos;
+ }
+
if (p_pos <= 0) {
return "";
}
@@ -3541,15 +3560,19 @@ String String::left(int p_pos) const {
}
String String::right(int p_pos) const {
- if (p_pos >= length()) {
- return "";
+ if (p_pos < 0) {
+ p_pos = length() + p_pos;
}
if (p_pos <= 0) {
+ return "";
+ }
+
+ if (p_pos >= length()) {
return *this;
}
- return substr(p_pos, (length() - p_pos));
+ return substr(length() - p_pos);
}
char32_t String::unicode_at(int p_idx) const {
@@ -3778,7 +3801,7 @@ String String::humanize_size(uint64_t p_size) {
return String::num(p_size / divisor).pad_decimals(digits) + " " + prefixes[prefix_idx];
}
-bool String::is_abs_path() const {
+bool String::is_absolute_path() const {
if (length() > 1) {
return (operator[](0) == '/' || operator[](0) == '\\' || find(":/") != -1 || find(":\\") != -1);
} else if ((length()) == 1) {
@@ -4388,7 +4411,7 @@ bool String::is_resource_file() const {
}
bool String::is_rel_path() const {
- return !is_abs_path();
+ return !is_absolute_path();
}
String String::get_base_dir() const {
diff --git a/core/string/ustring.h b/core/string/ustring.h
index a56845deff..82cd3e1667 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -309,7 +309,7 @@ public:
String unquote() const;
static String num(double p_num, int p_decimals = -1);
static String num_scientific(double p_num);
- static String num_real(double p_num);
+ static String num_real(double p_num, bool p_trailing = true);
static String num_int64(int64_t p_num, int base = 10, bool capitalize_hex = false);
static String num_uint64(uint64_t p_num, int base = 10, bool capitalize_hex = false);
static String chr(char32_t p_char);
@@ -397,7 +397,7 @@ public:
_FORCE_INLINE_ bool is_empty() const { return length() == 0; }
// path functions
- bool is_abs_path() const;
+ bool is_absolute_path() const;
bool is_rel_path() const;
bool is_resource_file() const;
String path_to(const String &p_path) const;
diff --git a/core/templates/bin_sorted_array.h b/core/templates/bin_sorted_array.h
new file mode 100644
index 0000000000..be9d0b5475
--- /dev/null
+++ b/core/templates/bin_sorted_array.h
@@ -0,0 +1,181 @@
+/*************************************************************************/
+/* bin_sorted_array.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BIN_SORTED_ARRAY_H
+#define BIN_SORTED_ARRAY_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/paged_array.h"
+
+template <class T>
+class BinSortedArray {
+ PagedArray<T> array;
+ LocalVector<uint64_t> bin_limits;
+
+ // Implement if elements need to keep track of their own index in the array.
+ _FORCE_INLINE_ virtual void _update_idx(T &r_element, uint64_t p_idx) {}
+
+ _FORCE_INLINE_ void _swap(uint64_t p_a, uint64_t p_b) {
+ SWAP(array[p_a], array[p_b]);
+ _update_idx(array[p_a], p_a);
+ _update_idx(array[p_b], p_b);
+ }
+
+public:
+ uint64_t insert(T &p_element, uint64_t p_bin) {
+ array.push_back(p_element);
+ uint64_t new_idx = array.size() - 1;
+ _update_idx(p_element, new_idx);
+ bin_limits[0] = new_idx;
+ if (p_bin != 0) {
+ new_idx = move(new_idx, p_bin);
+ }
+ return new_idx;
+ }
+
+ uint64_t move(uint64_t p_idx, uint64_t p_bin) {
+ ERR_FAIL_COND_V(p_idx >= array.size(), -1);
+
+ uint64_t current_bin = bin_limits.size() - 1;
+ while (p_idx > bin_limits[current_bin]) {
+ current_bin--;
+ }
+
+ if (p_bin == current_bin) {
+ return p_idx;
+ }
+
+ uint64_t current_idx = p_idx;
+ if (p_bin > current_bin) {
+ while (p_bin > current_bin) {
+ uint64_t swap_idx = 0;
+
+ if (current_bin == bin_limits.size() - 1) {
+ bin_limits.push_back(0);
+ } else {
+ bin_limits[current_bin + 1]++;
+ swap_idx = bin_limits[current_bin + 1];
+ }
+
+ if (current_idx != swap_idx) {
+ _swap(current_idx, swap_idx);
+ current_idx = swap_idx;
+ }
+
+ current_bin++;
+ }
+ } else {
+ while (p_bin < current_bin) {
+ uint64_t swap_idx = bin_limits[current_bin];
+
+ if (current_idx != swap_idx) {
+ _swap(current_idx, swap_idx);
+ }
+
+ if (current_bin == bin_limits.size() - 1 && bin_limits[current_bin] == 0) {
+ bin_limits.resize(bin_limits.size() - 1);
+ } else {
+ bin_limits[current_bin]--;
+ }
+ current_idx = swap_idx;
+ current_bin--;
+ }
+ }
+
+ return current_idx;
+ }
+
+ void remove(uint64_t p_idx) {
+ ERR_FAIL_COND(p_idx >= array.size());
+ uint64_t new_idx = move(p_idx, 0);
+ uint64_t swap_idx = array.size() - 1;
+
+ if (new_idx != swap_idx) {
+ _swap(new_idx, swap_idx);
+ }
+
+ if (bin_limits[0] > 0) {
+ bin_limits[0]--;
+ }
+
+ array.pop_back();
+ }
+
+ void set_page_pool(PagedArrayPool<T> *p_page_pool) {
+ array.set_page_pool(p_page_pool);
+ }
+
+ _FORCE_INLINE_ const T &operator[](uint64_t p_index) const {
+ return array[p_index];
+ }
+
+ _FORCE_INLINE_ T &operator[](uint64_t p_index) {
+ return array[p_index];
+ }
+
+ int get_bin_count() {
+ if (array.size() == 0) {
+ return 0;
+ }
+ return bin_limits.size();
+ }
+
+ int get_bin_start(int p_bin) {
+ ERR_FAIL_COND_V(p_bin >= get_bin_count(), ~0U);
+ if ((unsigned int)p_bin == bin_limits.size() - 1) {
+ return 0;
+ }
+ return bin_limits[p_bin + 1] + 1;
+ }
+
+ int get_bin_size(int p_bin) {
+ ERR_FAIL_COND_V(p_bin >= get_bin_count(), 0);
+ if ((unsigned int)p_bin == bin_limits.size() - 1) {
+ return bin_limits[p_bin] + 1;
+ }
+ return bin_limits[p_bin] - bin_limits[p_bin + 1];
+ }
+
+ void reset() {
+ array.reset();
+ bin_limits.clear();
+ bin_limits.push_back(0);
+ }
+
+ BinSortedArray() {
+ bin_limits.push_back(0);
+ }
+
+ virtual ~BinSortedArray() {
+ reset();
+ }
+};
+
+#endif //BIN_SORTED_ARRAY_H
diff --git a/core/templates/command_queue_mt.cpp b/core/templates/command_queue_mt.cpp
index 238bf3975c..04a8095f0b 100644
--- a/core/templates/command_queue_mt.cpp
+++ b/core/templates/command_queue_mt.cpp
@@ -70,35 +70,7 @@ CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
return &sync_sems[idx];
}
-bool CommandQueueMT::dealloc_one() {
-tryagain:
- if (dealloc_ptr == (write_ptr_and_epoch >> 1)) {
- // The queue is empty
- return false;
- }
-
- uint32_t size = *(uint32_t *)&command_mem[dealloc_ptr];
-
- if (size == 0) {
- // End of command buffer wrap down
- dealloc_ptr = 0;
- goto tryagain;
- }
-
- if (size & 1) {
- // Still used, nothing can be deallocated
- return false;
- }
-
- dealloc_ptr += (size >> 1) + 8;
- return true;
-}
-
CommandQueueMT::CommandQueueMT(bool p_sync) {
- command_mem_size = GLOBAL_DEF_RST("memory/limits/command_queue/multithreading_queue_size_kb", DEFAULT_COMMAND_MEM_SIZE_KB);
- ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/command_queue/multithreading_queue_size_kb", PropertyInfo(Variant::INT, "memory/limits/command_queue/multithreading_queue_size_kb", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"));
- command_mem_size *= 1024;
- command_mem = (uint8_t *)memalloc(command_mem_size);
if (p_sync) {
sync = memnew(Semaphore);
}
@@ -108,5 +80,4 @@ CommandQueueMT::~CommandQueueMT() {
if (sync) {
memdelete(sync);
}
- memfree(command_mem);
}
diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h
index 0012cea72d..acc46da0d5 100644
--- a/core/templates/command_queue_mt.h
+++ b/core/templates/command_queue_mt.h
@@ -34,6 +34,8 @@
#include "core/os/memory.h"
#include "core/os/mutex.h"
#include "core/os/semaphore.h"
+#include "core/string/print_string.h"
+#include "core/templates/local_vector.h"
#include "core/templates/simple_type.h"
#include "core/typedefs.h"
@@ -334,11 +336,7 @@ class CommandQueueMT {
SYNC_SEMAPHORES = 8
};
- uint8_t *command_mem = nullptr;
- uint32_t read_ptr_and_epoch = 0;
- uint32_t write_ptr_and_epoch = 0;
- uint32_t dealloc_ptr = 0;
- uint32_t command_mem_size = 0;
+ LocalVector<uint8_t> command_mem;
SyncSemaphore sync_sems[SYNC_SEMAPHORES];
Mutex mutex;
Semaphore *sync = nullptr;
@@ -346,138 +344,47 @@ class CommandQueueMT {
template <class T>
T *allocate() {
// alloc size is size+T+safeguard
- uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1)) + 8;
-
- // Assert that the buffer is big enough to hold at least two messages.
- ERR_FAIL_COND_V(alloc_size * 2 + sizeof(uint32_t) > command_mem_size, nullptr);
-
- tryagain:
- uint32_t write_ptr = write_ptr_and_epoch >> 1;
-
- if (write_ptr < dealloc_ptr) {
- // behind dealloc_ptr, check that there is room
- if ((dealloc_ptr - write_ptr) <= alloc_size) {
- // There is no more room, try to deallocate something
- if (dealloc_one()) {
- goto tryagain;
- }
- return nullptr;
- }
- } else {
- // ahead of dealloc_ptr, check that there is room
-
- if ((command_mem_size - write_ptr) < alloc_size + sizeof(uint32_t)) {
- // no room at the end, wrap down;
-
- if (dealloc_ptr == 0) { // don't want write_ptr to become dealloc_ptr
-
- // There is no more room, try to deallocate something
- if (dealloc_one()) {
- goto tryagain;
- }
- return nullptr;
- }
-
- // if this happens, it's a bug
- ERR_FAIL_COND_V((command_mem_size - write_ptr) < 8, nullptr);
- // zero means, wrap to beginning
-
- uint32_t *p = (uint32_t *)&command_mem[write_ptr];
- *p = 1;
- write_ptr_and_epoch = 0 | (1 & ~write_ptr_and_epoch); // Invert epoch.
- // See if we can get the thread to run and clear up some more space while we wait.
- // This is required if alloc_size * 2 + 4 > COMMAND_MEM_SIZE
- if (sync) {
- sync->post();
- }
- goto tryagain;
- }
- }
- // Allocate the size and the 'in use' bit.
- // First bit used to mark if command is still in use (1)
- // or if it has been destroyed and can be deallocated (0).
- uint32_t size = (sizeof(T) + 8 - 1) & ~(8 - 1);
- uint32_t *p = (uint32_t *)&command_mem[write_ptr];
- *p = (size << 1) | 1;
- write_ptr += 8;
- // allocate the command
- T *cmd = memnew_placement(&command_mem[write_ptr], T);
- write_ptr += size;
- write_ptr_and_epoch = (write_ptr << 1) | (write_ptr_and_epoch & 1);
+ uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1));
+ uint64_t size = command_mem.size();
+ command_mem.resize(size + alloc_size + 8);
+ *(uint64_t *)&command_mem[size] = alloc_size;
+ T *cmd = memnew_placement(&command_mem[size + 8], T);
return cmd;
}
template <class T>
T *allocate_and_lock() {
lock();
- T *ret;
-
- while ((ret = allocate<T>()) == nullptr) {
- unlock();
- // sleep a little until fetch happened and some room is made
- wait_for_flush();
- lock();
- }
-
+ T *ret = allocate<T>();
return ret;
}
- bool flush_one(bool p_lock = true) {
- if (p_lock) {
- lock();
- }
- tryagain:
-
- // tried to read an empty queue
- if (read_ptr_and_epoch == write_ptr_and_epoch) {
- if (p_lock) {
- unlock();
- }
- return false;
- }
-
- uint32_t read_ptr = read_ptr_and_epoch >> 1;
- uint32_t size_ptr = read_ptr;
- uint32_t size = *(uint32_t *)&command_mem[read_ptr] >> 1;
-
- if (size == 0) {
- *(uint32_t *)&command_mem[read_ptr] = 0; // clear in-use bit.
- //end of ringbuffer, wrap
- read_ptr_and_epoch = 0 | (1 & ~read_ptr_and_epoch); // Invert epoch.
- goto tryagain;
- }
-
- read_ptr += 8;
+ void _flush() {
+ lock();
- CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[read_ptr]);
+ uint64_t read_ptr = 0;
+ uint64_t limit = command_mem.size();
- read_ptr += size;
+ while (read_ptr < limit) {
+ uint64_t size = *(uint64_t *)&command_mem[read_ptr];
+ read_ptr += 8;
+ CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[read_ptr]);
- read_ptr_and_epoch = (read_ptr << 1) | (read_ptr_and_epoch & 1);
+ cmd->call(); //execute the function
+ cmd->post(); //release in case it needs sync/ret
+ cmd->~CommandBase(); //should be done, so erase the command
- if (p_lock) {
- unlock();
- }
- cmd->call();
- if (p_lock) {
- lock();
+ read_ptr += size;
}
- cmd->post();
- cmd->~CommandBase();
- *(uint32_t *)&command_mem[size_ptr] &= ~1;
-
- if (p_lock) {
- unlock();
- }
- return true;
+ command_mem.clear();
+ unlock();
}
void lock();
void unlock();
void wait_for_flush();
SyncSemaphore *_alloc_sync_sem();
- bool dealloc_one();
public:
/* NORMAL PUSH COMMANDS */
@@ -492,23 +399,19 @@ public:
DECL_PUSH_AND_SYNC(0)
SPACE_SEP_LIST(DECL_PUSH_AND_SYNC, 15)
- void wait_and_flush_one() {
- ERR_FAIL_COND(!sync);
- sync->wait();
- flush_one();
- }
-
_FORCE_INLINE_ void flush_if_pending() {
- if (unlikely(read_ptr_and_epoch != write_ptr_and_epoch)) {
- flush_all();
+ if (unlikely(command_mem.size() > 0)) {
+ _flush();
}
}
void flush_all() {
- //ERR_FAIL_COND(sync);
- lock();
- while (flush_one(false)) {
- }
- unlock();
+ _flush();
+ }
+
+ void wait_and_flush() {
+ ERR_FAIL_COND(!sync);
+ sync->wait();
+ _flush();
}
CommandQueueMT(bool p_sync);
diff --git a/core/templates/hash_map.h b/core/templates/hash_map.h
index dc378aed69..1257b54449 100644
--- a/core/templates/hash_map.h
+++ b/core/templates/hash_map.h
@@ -291,7 +291,7 @@ public:
}
/**
- * Same as get, except it can return nullptr when item was not found.
+ * Same as get, except it can return nullptr when item was not found.
* This is mainly used for speed purposes.
*/
@@ -324,7 +324,7 @@ public:
}
/**
- * Same as get, except it can return nullptr when item was not found.
+ * Same as get, except it can return nullptr when item was not found.
* This version is custom, will take a hash and a custom key (that should support operator==()
*/
@@ -443,7 +443,7 @@ public:
/**
* Get the next key to p_key, and the first key if p_key is null.
- * Returns a pointer to the next key if found, nullptr otherwise.
+ * Returns a pointer to the next key if found, nullptr otherwise.
* Adding/Removing elements while iterating will, of course, have unexpected results, don't do it.
*
* Example:
diff --git a/core/templates/oa_hash_map.h b/core/templates/oa_hash_map.h
index 2c7c64cd78..025cc30db4 100644
--- a/core/templates/oa_hash_map.h
+++ b/core/templates/oa_hash_map.h
@@ -231,7 +231,7 @@ public:
/**
* returns true if the value was found, false otherwise.
*
- * if r_data is not nullptr then the value will be written to the object
+ * if r_data is not nullptr then the value will be written to the object
* it points to.
*/
bool lookup(const TKey &p_key, TValue &r_data) const {
@@ -249,7 +249,7 @@ public:
/**
* returns true if the value was found, false otherwise.
*
- * if r_data is not nullptr then the value will be written to the object
+ * if r_data is not nullptr then the value will be written to the object
* it points to.
*/
TValue *lookup_ptr(const TKey &p_key) const {
diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h
index 7002034710..481289309f 100644
--- a/core/templates/paged_allocator.h
+++ b/core/templates/paged_allocator.h
@@ -35,6 +35,8 @@
#include "core/os/spin_lock.h"
#include "core/typedefs.h"
+#include <type_traits>
+
template <class T, bool thread_safe = false>
class PagedAllocator {
T **page_pool = nullptr;
@@ -89,8 +91,10 @@ public:
allocs_available++;
}
- void reset() {
- ERR_FAIL_COND(allocs_available < pages_allocated * page_size);
+ void reset(bool p_allow_unfreed = false) {
+ if (!p_allow_unfreed || !std::is_trivially_destructible<T>::value) {
+ ERR_FAIL_COND(allocs_available < pages_allocated * page_size);
+ }
if (pages_allocated) {
for (uint32_t i = 0; i < pages_allocated; i++) {
memfree(page_pool[i]);
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 3c7e2a0719..09cf785390 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -366,8 +366,8 @@ Array Array::filter(const Callable &p_callable) const {
new_arr.resize(size());
int accepted_count = 0;
+ const Variant *argptrs[1];
for (int i = 0; i < size(); i++) {
- const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *));
argptrs[0] = &get(i);
Variant result;
@@ -392,8 +392,8 @@ Array Array::map(const Callable &p_callable) const {
Array new_arr;
new_arr.resize(size());
+ const Variant *argptrs[1];
for (int i = 0; i < size(); i++) {
- const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *));
argptrs[0] = &get(i);
Variant result;
@@ -417,8 +417,8 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const
start = 1;
}
+ const Variant *argptrs[2];
for (int i = start; i < size(); i++) {
- const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * 2);
argptrs[0] = &ret;
argptrs[1] = &get(i);
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index e06b3e07ef..34b3e3ea35 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -33,7 +33,7 @@
#include "callable_bind.h"
#include "core/object/message_queue.h"
#include "core/object/object.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
void Callable::call_deferred(const Variant **p_arguments, int p_argcount) const {
@@ -50,6 +50,15 @@ void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_retu
custom->call(p_arguments, p_argcount, r_return_value, r_call_error);
} else {
Object *obj = ObjectDB::get_instance(ObjectID(object));
+#ifdef DEBUG_ENABLED
+ if (!obj) {
+ r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ r_call_error.argument = 0;
+ r_call_error.expected = 0;
+ r_return_value = Variant();
+ return;
+ }
+#endif
r_return_value = obj->call(method, p_arguments, p_argcount, r_call_error);
}
}
diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h
index e91029f330..d4ec5e570c 100644
--- a/core/variant/method_ptrcall.h
+++ b/core/variant/method_ptrcall.h
@@ -122,10 +122,10 @@ MAKE_PTRARG_BY_REFERENCE(Vector3);
MAKE_PTRARG_BY_REFERENCE(Vector3i);
MAKE_PTRARG(Transform2D);
MAKE_PTRARG_BY_REFERENCE(Plane);
-MAKE_PTRARG(Quat);
+MAKE_PTRARG(Quaternion);
MAKE_PTRARG_BY_REFERENCE(AABB);
MAKE_PTRARG_BY_REFERENCE(Basis);
-MAKE_PTRARG_BY_REFERENCE(Transform);
+MAKE_PTRARG_BY_REFERENCE(Transform3D);
MAKE_PTRARG_BY_REFERENCE(Color);
MAKE_PTRARG(StringName);
MAKE_PTRARG(NodePath);
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index d5b6d85dfb..76cb065d10 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -146,10 +146,10 @@ MAKE_TYPE_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPE_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPE_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPE_INFO(Plane, Variant::PLANE)
-MAKE_TYPE_INFO(Quat, Variant::QUAT)
+MAKE_TYPE_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPE_INFO(AABB, Variant::AABB)
MAKE_TYPE_INFO(Basis, Variant::BASIS)
-MAKE_TYPE_INFO(Transform, Variant::TRANSFORM)
+MAKE_TYPE_INFO(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPE_INFO(Color, Variant::COLOR)
MAKE_TYPE_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH)
diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h
index e0309aa3fe..900dcf7689 100644
--- a/core/variant/typed_array.h
+++ b/core/variant/typed_array.h
@@ -98,10 +98,10 @@ MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY(Plane, Variant::PLANE)
-MAKE_TYPED_ARRAY(Quat, Variant::QUAT)
+MAKE_TYPED_ARRAY(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY(AABB, Variant::AABB)
MAKE_TYPED_ARRAY(Basis, Variant::BASIS)
-MAKE_TYPED_ARRAY(Transform, Variant::TRANSFORM)
+MAKE_TYPED_ARRAY(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY(Color, Variant::COLOR)
MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH)
@@ -196,10 +196,10 @@ MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE)
-MAKE_TYPED_ARRAY_INFO(Quat, Variant::QUAT)
+MAKE_TYPED_ARRAY_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB)
MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS)
-MAKE_TYPED_ARRAY_INFO(Transform, Variant::TRANSFORM)
+MAKE_TYPED_ARRAY_INFO(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR)
MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH)
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 333dd8e8d1..4e45862fd3 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -91,16 +91,16 @@ String Variant::get_type_name(Variant::Type p_type) {
case AABB: {
return "AABB";
} break;
- case QUAT: {
- return "Quat";
+ case QUATERNION: {
+ return "Quaternion";
} break;
case BASIS: {
return "Basis";
} break;
- case TRANSFORM: {
- return "Transform";
+ case TRANSFORM3D: {
+ return "Transform3D";
} break;
@@ -275,7 +275,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
} break;
case TRANSFORM2D: {
static const Type valid[] = {
- TRANSFORM,
+ TRANSFORM3D,
NIL
};
@@ -300,7 +300,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
} break;
- case QUAT: {
+ case QUATERNION: {
static const Type valid[] = {
BASIS,
NIL
@@ -311,7 +311,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
} break;
case BASIS: {
static const Type valid[] = {
- QUAT,
+ QUATERNION,
VECTOR3,
NIL
};
@@ -319,10 +319,10 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
valid_types = valid;
} break;
- case TRANSFORM: {
+ case TRANSFORM3D: {
static const Type valid[] = {
TRANSFORM2D,
- QUAT,
+ QUATERNION,
BASIS,
NIL
};
@@ -582,7 +582,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
} break;
case TRANSFORM2D: {
static const Type valid[] = {
- TRANSFORM,
+ TRANSFORM3D,
NIL
};
@@ -607,7 +607,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
} break;
- case QUAT: {
+ case QUATERNION: {
static const Type valid[] = {
BASIS,
NIL
@@ -618,7 +618,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
} break;
case BASIS: {
static const Type valid[] = {
- QUAT,
+ QUATERNION,
VECTOR3,
NIL
};
@@ -626,10 +626,10 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
valid_types = valid;
} break;
- case TRANSFORM: {
+ case TRANSFORM3D: {
static const Type valid[] = {
TRANSFORM2D,
- QUAT,
+ QUATERNION,
BASIS,
NIL
};
@@ -873,16 +873,16 @@ bool Variant::is_zero() const {
case AABB: {
return *_data._aabb == ::AABB();
} break;
- case QUAT: {
- return *reinterpret_cast<const Quat *>(_data._mem) == Quat();
+ case QUATERNION: {
+ return *reinterpret_cast<const Quaternion *>(_data._mem) == Quaternion();
} break;
case BASIS: {
return *_data._basis == Basis();
} break;
- case TRANSFORM: {
- return *_data._transform == Transform();
+ case TRANSFORM3D: {
+ return *_data._transform3d == Transform3D();
} break;
@@ -1092,16 +1092,16 @@ void Variant::reference(const Variant &p_variant) {
case AABB: {
_data._aabb = memnew(::AABB(*p_variant._data._aabb));
} break;
- case QUAT: {
- memnew_placement(_data._mem, Quat(*reinterpret_cast<const Quat *>(p_variant._data._mem)));
+ case QUATERNION: {
+ memnew_placement(_data._mem, Quaternion(*reinterpret_cast<const Quaternion *>(p_variant._data._mem)));
} break;
case BASIS: {
_data._basis = memnew(Basis(*p_variant._data._basis));
} break;
- case TRANSFORM: {
- _data._transform = memnew(Transform(*p_variant._data._transform));
+ case TRANSFORM3D: {
+ _data._transform3d = memnew(Transform3D(*p_variant._data._transform3d));
} break;
// misc types
@@ -1115,9 +1115,9 @@ void Variant::reference(const Variant &p_variant) {
case OBJECT: {
memnew_placement(_data._mem, ObjData);
- if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) {
- Reference *reference = static_cast<Reference *>(p_variant._get_obj().obj);
- if (!reference->reference()) {
+ if (p_variant._get_obj().obj && p_variant._get_obj().id.is_ref_counted()) {
+ RefCounted *ref_counted = static_cast<RefCounted *>(p_variant._get_obj().obj);
+ if (!ref_counted->reference()) {
_get_obj().obj = nullptr;
_get_obj().id = ObjectID();
break;
@@ -1254,8 +1254,8 @@ void Variant::zero() {
case PLANE:
*reinterpret_cast<Plane *>(this->_data._mem) = Plane();
break;
- case QUAT:
- *reinterpret_cast<Quat *>(this->_data._mem) = Quat();
+ case QUATERNION:
+ *reinterpret_cast<Quaternion *>(this->_data._mem) = Quaternion();
break;
case COLOR:
*reinterpret_cast<Color *>(this->_data._mem) = Color();
@@ -1275,7 +1275,7 @@ void Variant::_clear_internal() {
// no point, they don't allocate memory
VECTOR3,
PLANE,
- QUAT,
+ QUATERNION,
COLOR,
VECTOR2,
RECT2
@@ -1289,8 +1289,8 @@ void Variant::_clear_internal() {
case BASIS: {
memdelete(_data._basis);
} break;
- case TRANSFORM: {
- memdelete(_data._transform);
+ case TRANSFORM3D: {
+ memdelete(_data._transform3d);
} break;
// misc types
@@ -1301,11 +1301,11 @@ void Variant::_clear_internal() {
reinterpret_cast<NodePath *>(_data._mem)->~NodePath();
} break;
case OBJECT: {
- if (_get_obj().id.is_reference()) {
+ if (_get_obj().id.is_ref_counted()) {
//we are safe that there is a reference here
- Reference *reference = static_cast<Reference *>(_get_obj().obj);
- if (reference->unreference()) {
- memdelete(reference);
+ RefCounted *ref_counted = static_cast<RefCounted *>(_get_obj().obj);
+ if (ref_counted->unreference()) {
+ memdelete(ref_counted);
}
}
_get_obj().obj = nullptr;
@@ -1636,60 +1636,35 @@ String Variant::stringify(List<const void *> &stack) const {
case STRING:
return *reinterpret_cast<const String *>(_data._mem);
case VECTOR2:
- return "(" + operator Vector2() + ")";
+ return operator Vector2();
case VECTOR2I:
- return "(" + operator Vector2i() + ")";
+ return operator Vector2i();
case RECT2:
- return "(" + operator Rect2() + ")";
+ return operator Rect2();
case RECT2I:
- return "(" + operator Rect2i() + ")";
- case TRANSFORM2D: {
- Transform2D mat32 = operator Transform2D();
- return "(" + Variant(mat32.elements[0]).operator String() + ", " + Variant(mat32.elements[1]).operator String() + ", " + Variant(mat32.elements[2]).operator String() + ")";
- } break;
+ return operator Rect2i();
+ case TRANSFORM2D:
+ return operator Transform2D();
case VECTOR3:
- return "(" + operator Vector3() + ")";
+ return operator Vector3();
case VECTOR3I:
- return "(" + operator Vector3i() + ")";
+ return operator Vector3i();
case PLANE:
return operator Plane();
- //case QUAT:
case AABB:
return operator ::AABB();
- case QUAT:
- return "(" + operator Quat() + ")";
- case BASIS: {
- Basis mat3 = operator Basis();
-
- String mtx("(");
- for (int i = 0; i < 3; i++) {
- if (i != 0) {
- mtx += ", ";
- }
-
- mtx += "(";
-
- for (int j = 0; j < 3; j++) {
- if (j != 0) {
- mtx += ", ";
- }
-
- mtx += Variant(mat3.elements[i][j]).operator String();
- }
-
- mtx += ")";
- }
-
- return mtx + ")";
- } break;
- case TRANSFORM:
- return operator Transform();
+ case QUATERNION:
+ return operator Quaternion();
+ case BASIS:
+ return operator Basis();
+ case TRANSFORM3D:
+ return operator Transform3D();
case STRING_NAME:
return operator StringName();
case NODE_PATH:
return operator NodePath();
case COLOR:
- return String::num(operator Color().r) + "," + String::num(operator Color().g) + "," + String::num(operator Color().b) + "," + String::num(operator Color().a);
+ return operator Color();
case DICTIONARY: {
const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem);
if (stack.find(d.id())) {
@@ -1723,6 +1698,7 @@ String Variant::stringify(List<const void *> &stack) const {
}
str += "}";
+ stack.erase(d.id());
return str;
} break;
case PACKED_VECTOR2_ARRAY: {
@@ -1826,12 +1802,13 @@ String Variant::stringify(List<const void *> &stack) const {
}
str += "]";
+ stack.erase(arr.id());
return str;
} break;
case OBJECT: {
if (_get_obj().obj) {
- if (!_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ if (!_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
return "[Freed Object]";
}
@@ -1956,39 +1933,39 @@ Variant::operator ::AABB() const {
Variant::operator Basis() const {
if (type == BASIS) {
return *_data._basis;
- } else if (type == QUAT) {
- return *reinterpret_cast<const Quat *>(_data._mem);
+ } else if (type == QUATERNION) {
+ return *reinterpret_cast<const Quaternion *>(_data._mem);
} else if (type == VECTOR3) {
return Basis(*reinterpret_cast<const Vector3 *>(_data._mem));
- } else if (type == TRANSFORM) { // unexposed in Variant::can_convert?
- return _data._transform->basis;
+ } else if (type == TRANSFORM3D) { // unexposed in Variant::can_convert?
+ return _data._transform3d->basis;
} else {
return Basis();
}
}
-Variant::operator Quat() const {
- if (type == QUAT) {
- return *reinterpret_cast<const Quat *>(_data._mem);
+Variant::operator Quaternion() const {
+ if (type == QUATERNION) {
+ return *reinterpret_cast<const Quaternion *>(_data._mem);
} else if (type == BASIS) {
return *_data._basis;
- } else if (type == TRANSFORM) {
- return _data._transform->basis;
+ } else if (type == TRANSFORM3D) {
+ return _data._transform3d->basis;
} else {
- return Quat();
+ return Quaternion();
}
}
-Variant::operator Transform() const {
- if (type == TRANSFORM) {
- return *_data._transform;
+Variant::operator Transform3D() const {
+ if (type == TRANSFORM3D) {
+ return *_data._transform3d;
} else if (type == BASIS) {
- return Transform(*_data._basis, Vector3());
- } else if (type == QUAT) {
- return Transform(Basis(*reinterpret_cast<const Quat *>(_data._mem)), Vector3());
+ return Transform3D(*_data._basis, Vector3());
+ } else if (type == QUATERNION) {
+ return Transform3D(Basis(*reinterpret_cast<const Quaternion *>(_data._mem)), Vector3());
} else if (type == TRANSFORM2D) {
const Transform2D &t = *_data._transform2d;
- Transform m;
+ Transform3D m;
m.basis.elements[0][0] = t.elements[0][0];
m.basis.elements[1][0] = t.elements[0][1];
m.basis.elements[0][1] = t.elements[1][0];
@@ -1997,15 +1974,15 @@ Variant::operator Transform() const {
m.origin[1] = t.elements[2][1];
return m;
} else {
- return Transform();
+ return Transform3D();
}
}
Variant::operator Transform2D() const {
if (type == TRANSFORM2D) {
return *_data._transform2d;
- } else if (type == TRANSFORM) {
- const Transform &t = *_data._transform;
+ } else if (type == TRANSFORM3D) {
+ const Transform3D &t = *_data._transform3d;
Transform2D m;
m.elements[0][0] = t.basis.elements[0][0];
m.elements[0][1] = t.basis.elements[1][0];
@@ -2495,14 +2472,14 @@ Variant::Variant(const Basis &p_matrix) {
_data._basis = memnew(Basis(p_matrix));
}
-Variant::Variant(const Quat &p_quat) {
- type = QUAT;
- memnew_placement(_data._mem, Quat(p_quat));
+Variant::Variant(const Quaternion &p_quaternion) {
+ type = QUATERNION;
+ memnew_placement(_data._mem, Quaternion(p_quaternion));
}
-Variant::Variant(const Transform &p_transform) {
- type = TRANSFORM;
- _data._transform = memnew(Transform(p_transform));
+Variant::Variant(const Transform3D &p_transform) {
+ type = TRANSFORM3D;
+ _data._transform3d = memnew(Transform3D(p_transform));
}
Variant::Variant(const Transform2D &p_transform) {
@@ -2531,9 +2508,9 @@ Variant::Variant(const Object *p_object) {
memnew_placement(_data._mem, ObjData);
if (p_object) {
- if (p_object->is_reference()) {
- Reference *reference = const_cast<Reference *>(static_cast<const Reference *>(p_object));
- if (!reference->init_ref()) {
+ if (p_object->is_ref_counted()) {
+ RefCounted *ref_counted = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_object));
+ if (!ref_counted->init_ref()) {
_get_obj().obj = nullptr;
_get_obj().id = ObjectID();
return;
@@ -2739,14 +2716,14 @@ void Variant::operator=(const Variant &p_variant) {
case AABB: {
*_data._aabb = *(p_variant._data._aabb);
} break;
- case QUAT: {
- *reinterpret_cast<Quat *>(_data._mem) = *reinterpret_cast<const Quat *>(p_variant._data._mem);
+ case QUATERNION: {
+ *reinterpret_cast<Quaternion *>(_data._mem) = *reinterpret_cast<const Quaternion *>(p_variant._data._mem);
} break;
case BASIS: {
*_data._basis = *(p_variant._data._basis);
} break;
- case TRANSFORM: {
- *_data._transform = *(p_variant._data._transform);
+ case TRANSFORM3D: {
+ *_data._transform3d = *(p_variant._data._transform3d);
} break;
// misc types
@@ -2757,17 +2734,17 @@ void Variant::operator=(const Variant &p_variant) {
*reinterpret_cast<::RID *>(_data._mem) = *reinterpret_cast<const ::RID *>(p_variant._data._mem);
} break;
case OBJECT: {
- if (_get_obj().id.is_reference()) {
+ if (_get_obj().id.is_ref_counted()) {
//we are safe that there is a reference here
- Reference *reference = static_cast<Reference *>(_get_obj().obj);
- if (reference->unreference()) {
- memdelete(reference);
+ RefCounted *ref_counted = static_cast<RefCounted *>(_get_obj().obj);
+ if (ref_counted->unreference()) {
+ memdelete(ref_counted);
}
}
- if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) {
- Reference *reference = static_cast<Reference *>(p_variant._get_obj().obj);
- if (!reference->reference()) {
+ if (p_variant._get_obj().obj && p_variant._get_obj().id.is_ref_counted()) {
+ RefCounted *ref_counted = static_cast<RefCounted *>(p_variant._get_obj().obj);
+ if (!ref_counted->reference()) {
_get_obj().obj = nullptr;
_get_obj().id = ObjectID();
break;
@@ -2916,11 +2893,11 @@ uint32_t Variant::hash() const {
return hash;
} break;
- case QUAT: {
- uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Quat *>(_data._mem)->x);
- hash = hash_djb2_one_float(reinterpret_cast<const Quat *>(_data._mem)->y, hash);
- hash = hash_djb2_one_float(reinterpret_cast<const Quat *>(_data._mem)->z, hash);
- return hash_djb2_one_float(reinterpret_cast<const Quat *>(_data._mem)->w, hash);
+ case QUATERNION: {
+ uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->x);
+ hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->y, hash);
+ hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->z, hash);
+ return hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->w, hash);
} break;
case BASIS: {
@@ -2934,13 +2911,13 @@ uint32_t Variant::hash() const {
return hash;
} break;
- case TRANSFORM: {
+ case TRANSFORM3D: {
uint32_t hash = 5831;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- hash = hash_djb2_one_float(_data._transform->basis.elements[i][j], hash);
+ hash = hash_djb2_one_float(_data._transform3d->basis.elements[i][j], hash);
}
- hash = hash_djb2_one_float(_data._transform->origin[i], hash);
+ hash = hash_djb2_one_float(_data._transform3d->origin[i], hash);
}
return hash;
@@ -3127,7 +3104,7 @@ uint32_t Variant::hash() const {
(hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
(hash_compare_scalar((p_lhs).z, (p_rhs).z))
-#define hash_compare_quat(p_lhs, p_rhs) \
+#define hash_compare_quaternion(p_lhs, p_rhs) \
(hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
(hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
(hash_compare_scalar((p_lhs).z, (p_rhs).z)) && \
@@ -3235,11 +3212,11 @@ bool Variant::hash_compare(const Variant &p_variant) const {
} break;
- case QUAT: {
- const Quat *l = reinterpret_cast<const Quat *>(_data._mem);
- const Quat *r = reinterpret_cast<const Quat *>(p_variant._data._mem);
+ case QUATERNION: {
+ const Quaternion *l = reinterpret_cast<const Quaternion *>(_data._mem);
+ const Quaternion *r = reinterpret_cast<const Quaternion *>(p_variant._data._mem);
- return hash_compare_quat(*l, *r);
+ return hash_compare_quaternion(*l, *r);
} break;
case BASIS: {
@@ -3255,9 +3232,9 @@ bool Variant::hash_compare(const Variant &p_variant) const {
return true;
} break;
- case TRANSFORM: {
- const Transform *l = _data._transform;
- const Transform *r = p_variant._data._transform;
+ case TRANSFORM3D: {
+ const Transform3D *l = _data._transform3d;
+ const Transform3D *r = p_variant._data._transform3d;
for (int i = 0; i < 3; i++) {
if (!(hash_compare_vector3(l->basis.elements[i], r->basis.elements[i]))) {
@@ -3324,7 +3301,7 @@ bool Variant::hash_compare(const Variant &p_variant) const {
}
bool Variant::is_ref() const {
- return type == OBJECT && _get_obj().id.is_reference();
+ return type == OBJECT && _get_obj().id.is_ref_counted();
}
Vector<Variant> varray() {
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 7f3c3477fc..75316da63f 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -37,9 +37,9 @@
#include "core/math/color.h"
#include "core/math/face3.h"
#include "core/math/plane.h"
-#include "core/math/quat.h"
-#include "core/math/transform.h"
+#include "core/math/quaternion.h"
#include "core/math/transform_2d.h"
+#include "core/math/transform_3d.h"
#include "core/math/vector3.h"
#include "core/math/vector3i.h"
#include "core/object/object_id.h"
@@ -88,10 +88,10 @@ public:
VECTOR3I,
TRANSFORM2D,
PLANE,
- QUAT,
+ QUATERNION,
AABB,
BASIS,
- TRANSFORM,
+ TRANSFORM3D,
// misc types
COLOR,
@@ -200,7 +200,7 @@ private:
Transform2D *_transform2d;
::AABB *_aabb;
Basis *_basis;
- Transform *_transform;
+ Transform3D *_transform3d;
PackedArrayRefBase *packed_array;
void *_ptr; //generic pointer
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)];
@@ -225,7 +225,7 @@ private:
false, //VECTOR3I,
true, //TRANSFORM2D,
false, //PLANE,
- false, //QUAT,
+ false, //QUATERNION,
true, //AABB,
true, //BASIS,
true, //TRANSFORM,
@@ -320,10 +320,10 @@ public:
operator Vector3i() const;
operator Plane() const;
operator ::AABB() const;
- operator Quat() const;
+ operator Quaternion() const;
operator Basis() const;
- operator Transform() const;
operator Transform2D() const;
+ operator Transform3D() const;
operator Color() const;
operator NodePath() const;
@@ -392,10 +392,10 @@ public:
Variant(const Vector3i &p_vector3i);
Variant(const Plane &p_plane);
Variant(const ::AABB &p_aabb);
- Variant(const Quat &p_quat);
+ Variant(const Quaternion &p_quat);
Variant(const Basis &p_matrix);
Variant(const Transform2D &p_transform);
- Variant(const Transform &p_transform);
+ Variant(const Transform3D &p_transform);
Variant(const Color &p_color);
Variant(const NodePath &p_node_path);
Variant(const ::RID &p_rid);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index efaaa8cd19..05ed35c760 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -611,6 +611,9 @@ struct _VariantCall {
if (buffer_size <= 0) {
ERR_FAIL_V_MSG(decompressed, "Decompression buffer size must be greater than zero.");
}
+ if (p_instance->size() == 0) {
+ ERR_FAIL_V_MSG(decompressed, "Compressed buffer size must be greater than zero.");
+ }
decompressed.resize(buffer_size);
int result = Compression::decompress(decompressed.ptrw(), buffer_size, p_instance->ptr(), p_instance->size(), mode);
@@ -969,7 +972,7 @@ void Variant::call(const StringName &p_method, const Variant **p_args, int p_arg
return;
}
#ifdef DEBUG_ENABLED
- if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ if (EngineDebugger::is_active() && !_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
return;
}
@@ -1362,7 +1365,7 @@ static void _register_variant_builtin_methods() {
// FIXME: Static function, not sure how to bind
//bind_method(String, humanize_size, sarray("size"), varray());
- bind_method(String, is_abs_path, sarray(), varray());
+ bind_method(String, is_absolute_path, sarray(), varray());
bind_method(String, is_rel_path, sarray(), varray());
bind_method(String, get_base_dir, sarray(), varray());
bind_method(String, get_file, sarray(), varray());
@@ -1416,6 +1419,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector2, distance_squared_to, sarray("to"), varray());
bind_method(Vector2, length, sarray(), varray());
bind_method(Vector2, length_squared, sarray(), varray());
+ bind_method(Vector2, limit_length, sarray("length"), varray(1.0));
bind_method(Vector2, normalized, sarray(), varray());
bind_method(Vector2, is_normalized, sarray(), varray());
bind_method(Vector2, is_equal_approx, sarray("to"), varray());
@@ -1439,14 +1443,15 @@ static void _register_variant_builtin_methods() {
bind_method(Vector2, cross, sarray("with"), varray());
bind_method(Vector2, abs, sarray(), varray());
bind_method(Vector2, sign, sarray(), varray());
+ bind_method(Vector2, clamp, sarray("min", "max"), varray());
bind_method(Vector2, snapped, sarray("step"), varray());
- bind_method(Vector2, clamped, sarray("length"), varray());
/* Vector2i */
bind_method(Vector2i, aspect, sarray(), varray());
bind_method(Vector2i, sign, sarray(), varray());
bind_method(Vector2i, abs, sarray(), varray());
+ bind_method(Vector2i, clamp, sarray("min", "max"), varray());
/* Rect2 */
@@ -1490,10 +1495,12 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3, distance_squared_to, sarray("b"), varray());
bind_method(Vector3, length, sarray(), varray());
bind_method(Vector3, length_squared, sarray(), varray());
+ bind_method(Vector3, limit_length, sarray("length"), varray(1.0));
bind_method(Vector3, normalized, sarray(), varray());
bind_method(Vector3, is_normalized, sarray(), varray());
bind_method(Vector3, is_equal_approx, sarray("to"), varray());
bind_method(Vector3, inverse, sarray(), varray());
+ bind_method(Vector3, clamp, sarray("min", "max"), varray());
bind_method(Vector3, snapped, sarray("step"), varray());
bind_method(Vector3, rotated, sarray("by_axis", "phi"), varray());
bind_method(Vector3, lerp, sarray("to", "weight"), varray());
@@ -1522,6 +1529,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3i, max_axis, sarray(), varray());
bind_method(Vector3i, sign, sarray(), varray());
bind_method(Vector3i, abs, sarray(), varray());
+ bind_method(Vector3i, clamp, sarray("min", "max"), varray());
/* Plane */
@@ -1536,19 +1544,19 @@ static void _register_variant_builtin_methods() {
bind_methodv(Plane, intersects_ray, &Plane::intersects_ray_bind, sarray("from", "dir"), varray());
bind_methodv(Plane, intersects_segment, &Plane::intersects_segment_bind, sarray("from", "to"), varray());
- /* Quat */
+ /* Quaternion */
- bind_method(Quat, length, sarray(), varray());
- bind_method(Quat, length_squared, sarray(), varray());
- bind_method(Quat, normalized, sarray(), varray());
- bind_method(Quat, is_normalized, sarray(), varray());
- bind_method(Quat, is_equal_approx, sarray("to"), varray());
- bind_method(Quat, inverse, sarray(), varray());
- bind_method(Quat, dot, sarray("with"), varray());
- bind_method(Quat, slerp, sarray("to", "weight"), varray());
- bind_method(Quat, slerpni, sarray("to", "weight"), varray());
- bind_method(Quat, cubic_slerp, sarray("b", "pre_a", "post_b", "weight"), varray());
- bind_method(Quat, get_euler, sarray(), varray());
+ bind_method(Quaternion, length, sarray(), varray());
+ bind_method(Quaternion, length_squared, sarray(), varray());
+ bind_method(Quaternion, normalized, sarray(), varray());
+ bind_method(Quaternion, is_normalized, sarray(), varray());
+ bind_method(Quaternion, is_equal_approx, sarray("to"), varray());
+ bind_method(Quaternion, inverse, sarray(), varray());
+ bind_method(Quaternion, dot, sarray("with"), varray());
+ bind_method(Quaternion, slerp, sarray("to", "weight"), varray());
+ bind_method(Quaternion, slerpni, sarray("to", "weight"), varray());
+ bind_method(Quaternion, cubic_slerp, sarray("b", "pre_a", "post_b", "weight"), varray());
+ bind_method(Quaternion, get_euler, sarray(), varray());
/* Color */
@@ -1559,6 +1567,7 @@ static void _register_variant_builtin_methods() {
bind_method(Color, to_abgr64, sarray(), varray());
bind_method(Color, to_rgba64, sarray(), varray());
+ bind_method(Color, clamp, sarray("min", "max"), varray(Color(0, 0, 0, 0), Color(1, 1, 1, 1)));
bind_method(Color, inverted, sarray(), varray());
bind_method(Color, lerp, sarray("to", "weight"), varray());
bind_method(Color, lightened, sarray("amount"), varray());
@@ -1642,6 +1651,8 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, basis_xform_inv, sarray("v"), varray());
bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform2D, is_equal_approx, sarray("xform"), varray());
+ bind_method(Transform2D, set_rotation, sarray("rotation"), varray());
+ bind_method(Transform2D, looking_at, sarray("target"), varray(Transform2D()));
/* Basis */
@@ -1659,7 +1670,7 @@ static void _register_variant_builtin_methods() {
bind_method(Basis, get_orthogonal_index, sarray(), varray());
bind_method(Basis, slerp, sarray("to", "weight"), varray());
bind_method(Basis, is_equal_approx, sarray("b"), varray());
- bind_method(Basis, get_rotation_quat, sarray(), varray());
+ bind_method(Basis, get_rotation_quaternion, sarray(), varray());
/* AABB */
@@ -1687,17 +1698,17 @@ static void _register_variant_builtin_methods() {
bind_methodv(AABB, intersects_segment, &AABB::intersects_segment_bind, sarray("from", "to"), varray());
bind_methodv(AABB, intersects_ray, &AABB::intersects_ray_bind, sarray("from", "dir"), varray());
- /* Transform */
+ /* Transform3D */
- bind_method(Transform, inverse, sarray(), varray());
- bind_method(Transform, affine_inverse, sarray(), varray());
- bind_method(Transform, orthonormalized, sarray(), varray());
- bind_method(Transform, rotated, sarray("axis", "phi"), varray());
- bind_method(Transform, scaled, sarray("scale"), varray());
- bind_method(Transform, translated, sarray("offset"), varray());
- bind_method(Transform, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
- bind_method(Transform, interpolate_with, sarray("xform", "weight"), varray());
- bind_method(Transform, is_equal_approx, sarray("xform"), varray());
+ bind_method(Transform3D, inverse, sarray(), varray());
+ bind_method(Transform3D, affine_inverse, sarray(), varray());
+ bind_method(Transform3D, orthonormalized, sarray(), varray());
+ bind_method(Transform3D, rotated, sarray("axis", "phi"), varray());
+ bind_method(Transform3D, scaled, sarray("scale"), varray());
+ bind_method(Transform3D, translated, sarray("offset"), varray());
+ bind_method(Transform3D, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
+ bind_method(Transform3D, interpolate_with, sarray("xform", "weight"), varray());
+ bind_method(Transform3D, is_equal_approx, sarray("xform"), varray());
/* Dictionary */
@@ -2016,14 +2027,14 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));
- Transform identity_transform = Transform();
- Transform flip_x_transform = Transform(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
- Transform flip_y_transform = Transform(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0);
- Transform flip_z_transform = Transform(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
- _VariantCall::add_variant_constant(Variant::TRANSFORM, "IDENTITY", identity_transform);
- _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_X", flip_x_transform);
- _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Y", flip_y_transform);
- _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Z", flip_z_transform);
+ Transform3D identity_transform = Transform3D();
+ Transform3D flip_x_transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
+ Transform3D flip_y_transform = Transform3D(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0);
+ Transform3D flip_z_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
+ _VariantCall::add_variant_constant(Variant::TRANSFORM3D, "IDENTITY", identity_transform);
+ _VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_X", flip_x_transform);
+ _VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_Y", flip_y_transform);
+ _VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_Z", flip_z_transform);
Basis identity_basis = Basis();
Basis flip_x_basis = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1);
@@ -2038,7 +2049,7 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XZ", Plane(Vector3(0, 1, 0), 0));
_VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XY", Plane(Vector3(0, 0, 1), 0));
- _VariantCall::add_variant_constant(Variant::QUAT, "IDENTITY", Quat(0, 0, 0, 1));
+ _VariantCall::add_variant_constant(Variant::QUATERNION, "IDENTITY", Quaternion(0, 0, 0, 1));
}
void Variant::_register_variant_methods() {
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index f0c9e52b46..9e3ab5897b 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -62,10 +62,10 @@ MAKE_PTRCONSTRUCT(Vector3);
MAKE_PTRCONSTRUCT(Vector3i);
MAKE_PTRCONSTRUCT(Transform2D);
MAKE_PTRCONSTRUCT(Plane);
-MAKE_PTRCONSTRUCT(Quat);
+MAKE_PTRCONSTRUCT(Quaternion);
MAKE_PTRCONSTRUCT(AABB);
MAKE_PTRCONSTRUCT(Basis);
-MAKE_PTRCONSTRUCT(Transform);
+MAKE_PTRCONSTRUCT(Transform3D);
MAKE_PTRCONSTRUCT(Color);
MAKE_PTRCONSTRUCT(StringName);
MAKE_PTRCONSTRUCT(NodePath);
@@ -659,13 +659,13 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructor<Plane, Vector3, Vector3, Vector3>>(sarray("point1", "point2", "point3"));
add_constructor<VariantConstructor<Plane, double, double, double, double>>(sarray("a", "b", "c", "d"));
- add_constructor<VariantConstructNoArgs<Quat>>(sarray());
- add_constructor<VariantConstructor<Quat, Quat>>(sarray("from"));
- add_constructor<VariantConstructor<Quat, Basis>>(sarray("from"));
- add_constructor<VariantConstructor<Quat, Vector3>>(sarray("euler"));
- add_constructor<VariantConstructor<Quat, Vector3, double>>(sarray("axis", "angle"));
- add_constructor<VariantConstructor<Quat, Vector3, Vector3>>(sarray("arc_from", "arc_to"));
- add_constructor<VariantConstructor<Quat, double, double, double, double>>(sarray("x", "y", "z", "w"));
+ add_constructor<VariantConstructNoArgs<Quaternion>>(sarray());
+ add_constructor<VariantConstructor<Quaternion, Quaternion>>(sarray("from"));
+ add_constructor<VariantConstructor<Quaternion, Basis>>(sarray("from"));
+ add_constructor<VariantConstructor<Quaternion, Vector3>>(sarray("euler"));
+ add_constructor<VariantConstructor<Quaternion, Vector3, double>>(sarray("axis", "angle"));
+ add_constructor<VariantConstructor<Quaternion, Vector3, Vector3>>(sarray("arc_from", "arc_to"));
+ add_constructor<VariantConstructor<Quaternion, double, double, double, double>>(sarray("x", "y", "z", "w"));
add_constructor<VariantConstructNoArgs<::AABB>>(sarray());
add_constructor<VariantConstructor<::AABB, ::AABB>>(sarray("from"));
@@ -673,15 +673,15 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Basis>>(sarray());
add_constructor<VariantConstructor<Basis, Basis>>(sarray("from"));
- add_constructor<VariantConstructor<Basis, Quat>>(sarray("from"));
+ add_constructor<VariantConstructor<Basis, Quaternion>>(sarray("from"));
add_constructor<VariantConstructor<Basis, Vector3>>(sarray("euler"));
add_constructor<VariantConstructor<Basis, Vector3, double>>(sarray("axis", "phi"));
add_constructor<VariantConstructor<Basis, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis"));
- add_constructor<VariantConstructNoArgs<Transform>>(sarray());
- add_constructor<VariantConstructor<Transform, Transform>>(sarray("from"));
- add_constructor<VariantConstructor<Transform, Basis, Vector3>>(sarray("basis", "origin"));
- add_constructor<VariantConstructor<Transform, Vector3, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis", "origin"));
+ add_constructor<VariantConstructNoArgs<Transform3D>>(sarray());
+ add_constructor<VariantConstructor<Transform3D, Transform3D>>(sarray("from"));
+ add_constructor<VariantConstructor<Transform3D, Basis, Vector3>>(sarray("basis", "origin"));
+ add_constructor<VariantConstructor<Transform3D, Vector3, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis", "origin"));
add_constructor<VariantConstructNoArgs<Color>>(sarray());
add_constructor<VariantConstructor<Color, Color>>(sarray("from"));
@@ -836,9 +836,9 @@ String Variant::get_constructor_argument_name(Variant::Type p_type, int p_constr
void VariantInternal::object_assign(Variant *v, const Object *o) {
if (o) {
- if (o->is_reference()) {
- Reference *reference = const_cast<Reference *>(static_cast<const Reference *>(o));
- if (!reference->init_ref()) {
+ if (o->is_ref_counted()) {
+ RefCounted *ref_counted = const_cast<RefCounted *>(static_cast<const RefCounted *>(o));
+ if (!ref_counted->init_ref()) {
v->_get_obj().obj = nullptr;
v->_get_obj().id = ObjectID();
return;
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 7d33d85cd6..78e1ad06ae 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -43,17 +43,20 @@ public:
v->type = p_type;
switch (p_type) {
- case Variant::AABB:
- init_aabb(v);
+ case Variant::STRING:
+ init_string(v);
break;
case Variant::TRANSFORM2D:
init_transform2d(v);
break;
- case Variant::TRANSFORM:
- init_transform(v);
+ case Variant::AABB:
+ init_aabb(v);
break;
- case Variant::STRING:
- init_string(v);
+ case Variant::BASIS:
+ init_basis(v);
+ break;
+ case Variant::TRANSFORM3D:
+ init_transform(v);
break;
case Variant::STRING_NAME:
init_string_name(v);
@@ -135,14 +138,14 @@ public:
_FORCE_INLINE_ static const Transform2D *get_transform2d(const Variant *v) { return v->_data._transform2d; }
_FORCE_INLINE_ static Plane *get_plane(Variant *v) { return reinterpret_cast<Plane *>(v->_data._mem); }
_FORCE_INLINE_ static const Plane *get_plane(const Variant *v) { return reinterpret_cast<const Plane *>(v->_data._mem); }
- _FORCE_INLINE_ static Quat *get_quat(Variant *v) { return reinterpret_cast<Quat *>(v->_data._mem); }
- _FORCE_INLINE_ static const Quat *get_quat(const Variant *v) { return reinterpret_cast<const Quat *>(v->_data._mem); }
+ _FORCE_INLINE_ static Quaternion *get_quaternion(Variant *v) { return reinterpret_cast<Quaternion *>(v->_data._mem); }
+ _FORCE_INLINE_ static const Quaternion *get_quaternion(const Variant *v) { return reinterpret_cast<const Quaternion *>(v->_data._mem); }
_FORCE_INLINE_ static ::AABB *get_aabb(Variant *v) { return v->_data._aabb; }
_FORCE_INLINE_ static const ::AABB *get_aabb(const Variant *v) { return v->_data._aabb; }
_FORCE_INLINE_ static Basis *get_basis(Variant *v) { return v->_data._basis; }
_FORCE_INLINE_ static const Basis *get_basis(const Variant *v) { return v->_data._basis; }
- _FORCE_INLINE_ static Transform *get_transform(Variant *v) { return v->_data._transform; }
- _FORCE_INLINE_ static const Transform *get_transform(const Variant *v) { return v->_data._transform; }
+ _FORCE_INLINE_ static Transform3D *get_transform(Variant *v) { return v->_data._transform3d; }
+ _FORCE_INLINE_ static const Transform3D *get_transform(const Variant *v) { return v->_data._transform3d; }
// Misc types.
_FORCE_INLINE_ static Color *get_color(Variant *v) { return reinterpret_cast<Color *>(v->_data._mem); }
@@ -192,6 +195,10 @@ public:
v->type = GetTypeInfo<T>::VARIANT_TYPE;
}
+ // Should be in the same order as Variant::Type for consistency.
+ // Those primitive and vector types don't need an `init_` method:
+ // Nil, bool, float, Vector2/i, Rect2/i, Vector3/i, Plane, Quat, Color, RID.
+ // Object is a special case, handled via `object_assign_null`.
_FORCE_INLINE_ static void init_string(Variant *v) {
memnew_placement(v->_data._mem, String);
v->type = Variant::STRING;
@@ -210,8 +217,8 @@ public:
v->type = Variant::BASIS;
}
_FORCE_INLINE_ static void init_transform(Variant *v) {
- v->_data._transform = memnew(Transform);
- v->type = Variant::TRANSFORM;
+ v->_data._transform3d = memnew(Transform3D);
+ v->type = Variant::TRANSFORM3D;
}
_FORCE_INLINE_ static void init_string_name(Variant *v) {
memnew_placement(v->_data._mem, StringName);
@@ -278,7 +285,7 @@ public:
v->clear();
}
- static void object_assign(Variant *v, const Object *o); // Needs Reference, so it's implemented elsewhere.
+ static void object_assign(Variant *v, const Object *o); // Needs RefCounted, so it's implemented elsewhere.
_FORCE_INLINE_ static void object_assign(Variant *v, const Variant *o) {
object_assign(v, o->_get_obj().obj);
@@ -313,12 +320,12 @@ public:
return get_rect2(v);
case Variant::RECT2I:
return get_rect2i(v);
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
return get_transform(v);
case Variant::TRANSFORM2D:
return get_transform2d(v);
- case Variant::QUAT:
- return get_quat(v);
+ case Variant::QUATERNION:
+ return get_quaternion(v);
case Variant::PLANE:
return get_plane(v);
case Variant::BASIS:
@@ -391,12 +398,12 @@ public:
return get_rect2(v);
case Variant::RECT2I:
return get_rect2i(v);
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
return get_transform(v);
case Variant::TRANSFORM2D:
return get_transform2d(v);
- case Variant::QUAT:
- return get_quat(v);
+ case Variant::QUATERNION:
+ return get_quaternion(v);
case Variant::PLANE:
return get_plane(v);
case Variant::BASIS:
@@ -583,9 +590,9 @@ struct VariantGetInternalPtr<Transform2D> {
};
template <>
-struct VariantGetInternalPtr<Transform> {
- static Transform *get_ptr(Variant *v) { return VariantInternal::get_transform(v); }
- static const Transform *get_ptr(const Variant *v) { return VariantInternal::get_transform(v); }
+struct VariantGetInternalPtr<Transform3D> {
+ static Transform3D *get_ptr(Variant *v) { return VariantInternal::get_transform(v); }
+ static const Transform3D *get_ptr(const Variant *v) { return VariantInternal::get_transform(v); }
};
template <>
@@ -595,9 +602,9 @@ struct VariantGetInternalPtr<Plane> {
};
template <>
-struct VariantGetInternalPtr<Quat> {
- static Quat *get_ptr(Variant *v) { return VariantInternal::get_quat(v); }
- static const Quat *get_ptr(const Variant *v) { return VariantInternal::get_quat(v); }
+struct VariantGetInternalPtr<Quaternion> {
+ static Quaternion *get_ptr(Variant *v) { return VariantInternal::get_quaternion(v); }
+ static const Quaternion *get_ptr(const Variant *v) { return VariantInternal::get_quaternion(v); }
};
template <>
@@ -812,9 +819,9 @@ struct VariantInternalAccessor<Transform2D> {
};
template <>
-struct VariantInternalAccessor<Transform> {
- static _FORCE_INLINE_ const Transform &get(const Variant *v) { return *VariantInternal::get_transform(v); }
- static _FORCE_INLINE_ void set(Variant *v, const Transform &p_value) { *VariantInternal::get_transform(v) = p_value; }
+struct VariantInternalAccessor<Transform3D> {
+ static _FORCE_INLINE_ const Transform3D &get(const Variant *v) { return *VariantInternal::get_transform(v); }
+ static _FORCE_INLINE_ void set(Variant *v, const Transform3D &p_value) { *VariantInternal::get_transform(v) = p_value; }
};
template <>
@@ -824,9 +831,9 @@ struct VariantInternalAccessor<Plane> {
};
template <>
-struct VariantInternalAccessor<Quat> {
- static _FORCE_INLINE_ const Quat &get(const Variant *v) { return *VariantInternal::get_quat(v); }
- static _FORCE_INLINE_ void set(Variant *v, const Quat &p_value) { *VariantInternal::get_quat(v) = p_value; }
+struct VariantInternalAccessor<Quaternion> {
+ static _FORCE_INLINE_ const Quaternion &get(const Variant *v) { return *VariantInternal::get_quaternion(v); }
+ static _FORCE_INLINE_ void set(Variant *v, const Quaternion &p_value) { *VariantInternal::get_quaternion(v) = p_value; }
};
template <>
@@ -1060,8 +1067,8 @@ struct VariantInitializer<Plane> {
};
template <>
-struct VariantInitializer<Quat> {
- static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Quat>(v); }
+struct VariantInitializer<Quaternion> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Quaternion>(v); }
};
template <>
@@ -1075,7 +1082,7 @@ struct VariantInitializer<Basis> {
};
template <>
-struct VariantInitializer<Transform> {
+struct VariantInitializer<Transform3D> {
static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform(v); }
};
@@ -1234,8 +1241,8 @@ struct VariantZeroAssigner<Plane> {
};
template <>
-struct VariantZeroAssigner<Quat> {
- static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_quat(v) = Quat(); }
+struct VariantZeroAssigner<Quaternion> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_quaternion(v) = Quaternion(); }
};
template <>
@@ -1249,8 +1256,8 @@ struct VariantZeroAssigner<Basis> {
};
template <>
-struct VariantZeroAssigner<Transform> {
- static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_transform(v) = Transform(); }
+struct VariantZeroAssigner<Transform3D> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_transform(v) = Transform3D(); }
};
template <>
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index 8cfa793c0e..10d0a83014 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -1395,7 +1395,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorAdd<Vector2i, Vector2i, Vector2i>>(Variant::OP_ADD, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorAdd<Vector3, Vector3, Vector3>>(Variant::OP_ADD, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorAdd<Vector3i, Vector3i, Vector3i>>(Variant::OP_ADD, Variant::VECTOR3I, Variant::VECTOR3I);
- register_op<OperatorEvaluatorAdd<Quat, Quat, Quat>>(Variant::OP_ADD, Variant::QUAT, Variant::QUAT);
+ register_op<OperatorEvaluatorAdd<Quaternion, Quaternion, Quaternion>>(Variant::OP_ADD, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorAdd<Color, Color, Color>>(Variant::OP_ADD, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorAddArray>(Variant::OP_ADD, Variant::ARRAY, Variant::ARRAY);
register_op<OperatorEvaluatorAppendArray<uint8_t>>(Variant::OP_ADD, Variant::PACKED_BYTE_ARRAY, Variant::PACKED_BYTE_ARRAY);
@@ -1416,7 +1416,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorSub<Vector2i, Vector2i, Vector2i>>(Variant::OP_SUBTRACT, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorSub<Vector3, Vector3, Vector3>>(Variant::OP_SUBTRACT, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorSub<Vector3i, Vector3i, Vector3i>>(Variant::OP_SUBTRACT, Variant::VECTOR3I, Variant::VECTOR3I);
- register_op<OperatorEvaluatorSub<Quat, Quat, Quat>>(Variant::OP_SUBTRACT, Variant::QUAT, Variant::QUAT);
+ register_op<OperatorEvaluatorSub<Quaternion, Quaternion, Quaternion>>(Variant::OP_SUBTRACT, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorSub<Color, Color, Color>>(Variant::OP_SUBTRACT, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorMul<int64_t, int64_t, int64_t>>(Variant::OP_MULTIPLY, Variant::INT, Variant::INT);
@@ -1449,9 +1449,9 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorMul<Vector3i, Vector3i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::INT);
register_op<OperatorEvaluatorMul<Vector3i, Vector3i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::FLOAT);
- register_op<OperatorEvaluatorMul<Quat, Quat, Quat>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::QUAT);
- register_op<OperatorEvaluatorMul<Quat, Quat, int64_t>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::INT);
- register_op<OperatorEvaluatorMul<Quat, Quat, double>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::FLOAT);
+ register_op<OperatorEvaluatorMul<Quaternion, Quaternion, Quaternion>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::QUATERNION);
+ register_op<OperatorEvaluatorMul<Quaternion, Quaternion, int64_t>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::INT);
+ register_op<OperatorEvaluatorMul<Quaternion, Quaternion, double>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::FLOAT);
register_op<OperatorEvaluatorMul<Color, Color, Color>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorMul<Color, Color, int64_t>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::INT);
@@ -1465,25 +1465,25 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorXForm<Vector<Vector2>, Transform2D, Vector<Vector2>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM2D, Variant::PACKED_VECTOR2_ARRAY);
register_op<OperatorEvaluatorXFormInv<Vector<Vector2>, Vector<Vector2>, Transform2D>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR2_ARRAY, Variant::TRANSFORM2D);
- register_op<OperatorEvaluatorMul<Transform, Transform, Transform>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::TRANSFORM);
- register_op<OperatorEvaluatorXForm<Vector3, Transform, Vector3>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::VECTOR3);
- register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Transform>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::TRANSFORM);
- register_op<OperatorEvaluatorXForm<::AABB, Transform, ::AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::AABB);
- register_op<OperatorEvaluatorXFormInv<::AABB, ::AABB, Transform>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM);
- register_op<OperatorEvaluatorXForm<Vector<Vector3>, Transform, Vector<Vector3>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::PACKED_VECTOR3_ARRAY);
- register_op<OperatorEvaluatorXFormInv<Vector<Vector3>, Vector<Vector3>, Transform>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR3_ARRAY, Variant::TRANSFORM);
+ register_op<OperatorEvaluatorMul<Transform3D, Transform3D, Transform3D>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorXForm<Vector3, Transform3D, Vector3>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::VECTOR3);
+ register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Transform3D>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorXForm<::AABB, Transform3D, ::AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::AABB);
+ register_op<OperatorEvaluatorXFormInv<::AABB, ::AABB, Transform3D>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorXForm<Vector<Vector3>, Transform3D, Vector<Vector3>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::PACKED_VECTOR3_ARRAY);
+ register_op<OperatorEvaluatorXFormInv<Vector<Vector3>, Vector<Vector3>, Transform3D>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR3_ARRAY, Variant::TRANSFORM3D);
register_op<OperatorEvaluatorMul<Basis, Basis, Basis>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::BASIS);
register_op<OperatorEvaluatorXForm<Vector3, Basis, Vector3>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::VECTOR3);
register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Basis>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::BASIS);
- register_op<OperatorEvaluatorMul<Quat, Quat, Quat>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::QUAT);
- register_op<OperatorEvaluatorMul<Quat, Quat, int64_t>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::INT);
- register_op<OperatorEvaluatorMul<Quat, int64_t, Quat>>(Variant::OP_MULTIPLY, Variant::INT, Variant::QUAT);
- register_op<OperatorEvaluatorMul<Quat, Quat, double>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::FLOAT);
- register_op<OperatorEvaluatorMul<Quat, double, Quat>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::QUAT);
- register_op<OperatorEvaluatorXForm<Vector3, Quat, Vector3>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::VECTOR3);
- register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Quat>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::QUAT);
+ register_op<OperatorEvaluatorMul<Quaternion, Quaternion, Quaternion>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::QUATERNION);
+ register_op<OperatorEvaluatorMul<Quaternion, Quaternion, int64_t>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::INT);
+ register_op<OperatorEvaluatorMul<Quaternion, int64_t, Quaternion>>(Variant::OP_MULTIPLY, Variant::INT, Variant::QUATERNION);
+ register_op<OperatorEvaluatorMul<Quaternion, Quaternion, double>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::FLOAT);
+ register_op<OperatorEvaluatorMul<Quaternion, double, Quaternion>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::QUATERNION);
+ register_op<OperatorEvaluatorXForm<Vector3, Quaternion, Vector3>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::VECTOR3);
+ register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Quaternion>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::QUATERNION);
register_op<OperatorEvaluatorMul<Color, Color, Color>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorMul<Color, Color, int64_t>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::INT);
@@ -1516,8 +1516,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, double>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT);
register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::INT);
- register_op<OperatorEvaluatorDiv<Quat, Quat, double>>(Variant::OP_DIVIDE, Variant::QUAT, Variant::FLOAT);
- register_op<OperatorEvaluatorDiv<Quat, Quat, int64_t>>(Variant::OP_DIVIDE, Variant::QUAT, Variant::INT);
+ register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, double>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::FLOAT);
+ register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, int64_t>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::INT);
register_op<OperatorEvaluatorDiv<Color, Color, Color>>(Variant::OP_DIVIDE, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorDiv<Color, Color, double>>(Variant::OP_DIVIDE, Variant::COLOR, Variant::FLOAT);
@@ -1544,10 +1544,10 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorStringModT<Vector3i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3I);
register_op<OperatorEvaluatorStringModT<Transform2D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorStringModT<Plane>>(Variant::OP_MODULE, Variant::STRING, Variant::PLANE);
- register_op<OperatorEvaluatorStringModT<Quat>>(Variant::OP_MODULE, Variant::STRING, Variant::QUAT);
+ register_op<OperatorEvaluatorStringModT<Quaternion>>(Variant::OP_MODULE, Variant::STRING, Variant::QUATERNION);
register_op<OperatorEvaluatorStringModT<::AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB);
register_op<OperatorEvaluatorStringModT<Basis>>(Variant::OP_MODULE, Variant::STRING, Variant::BASIS);
- register_op<OperatorEvaluatorStringModT<Transform>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM);
+ register_op<OperatorEvaluatorStringModT<Transform3D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM3D);
register_op<OperatorEvaluatorStringModT<Color>>(Variant::OP_MODULE, Variant::STRING, Variant::COLOR);
register_op<OperatorEvaluatorStringModT<StringName>>(Variant::OP_MODULE, Variant::STRING, Variant::STRING_NAME);
@@ -1574,7 +1574,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNeg<Vector2i, Vector2i>>(Variant::OP_NEGATE, Variant::VECTOR2I, Variant::NIL);
register_op<OperatorEvaluatorNeg<Vector3, Vector3>>(Variant::OP_NEGATE, Variant::VECTOR3, Variant::NIL);
register_op<OperatorEvaluatorNeg<Vector3i, Vector3i>>(Variant::OP_NEGATE, Variant::VECTOR3I, Variant::NIL);
- register_op<OperatorEvaluatorNeg<Quat, Quat>>(Variant::OP_NEGATE, Variant::QUAT, Variant::NIL);
+ register_op<OperatorEvaluatorNeg<Quaternion, Quaternion>>(Variant::OP_NEGATE, Variant::QUATERNION, Variant::NIL);
register_op<OperatorEvaluatorNeg<Plane, Plane>>(Variant::OP_NEGATE, Variant::PLANE, Variant::NIL);
register_op<OperatorEvaluatorNeg<Color, Color>>(Variant::OP_NEGATE, Variant::COLOR, Variant::NIL);
@@ -1584,7 +1584,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorPos<Vector2i, Vector2i>>(Variant::OP_POSITIVE, Variant::VECTOR2I, Variant::NIL);
register_op<OperatorEvaluatorPos<Vector3, Vector3>>(Variant::OP_POSITIVE, Variant::VECTOR3, Variant::NIL);
register_op<OperatorEvaluatorPos<Vector3i, Vector3i>>(Variant::OP_POSITIVE, Variant::VECTOR3I, Variant::NIL);
- register_op<OperatorEvaluatorPos<Quat, Quat>>(Variant::OP_POSITIVE, Variant::QUAT, Variant::NIL);
+ register_op<OperatorEvaluatorPos<Quaternion, Quaternion>>(Variant::OP_POSITIVE, Variant::QUATERNION, Variant::NIL);
register_op<OperatorEvaluatorPos<Plane, Plane>>(Variant::OP_POSITIVE, Variant::PLANE, Variant::NIL);
register_op<OperatorEvaluatorPos<Color, Color>>(Variant::OP_POSITIVE, Variant::COLOR, Variant::NIL);
@@ -1612,10 +1612,10 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorEqual<Vector3i, Vector3i>>(Variant::OP_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I);
register_op<OperatorEvaluatorEqual<Transform2D, Transform2D>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorEqual<Plane, Plane>>(Variant::OP_EQUAL, Variant::PLANE, Variant::PLANE);
- register_op<OperatorEvaluatorEqual<Quat, Quat>>(Variant::OP_EQUAL, Variant::QUAT, Variant::QUAT);
+ register_op<OperatorEvaluatorEqual<Quaternion, Quaternion>>(Variant::OP_EQUAL, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorEqual<::AABB, ::AABB>>(Variant::OP_EQUAL, Variant::AABB, Variant::AABB);
register_op<OperatorEvaluatorEqual<Basis, Basis>>(Variant::OP_EQUAL, Variant::BASIS, Variant::BASIS);
- register_op<OperatorEvaluatorEqual<Transform, Transform>>(Variant::OP_EQUAL, Variant::TRANSFORM, Variant::TRANSFORM);
+ register_op<OperatorEvaluatorEqual<Transform3D, Transform3D>>(Variant::OP_EQUAL, Variant::TRANSFORM3D, Variant::TRANSFORM3D);
register_op<OperatorEvaluatorEqual<Color, Color>>(Variant::OP_EQUAL, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorEqual<StringName, String>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING);
@@ -1658,10 +1658,10 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNotEqual<Vector3i, Vector3i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I);
register_op<OperatorEvaluatorNotEqual<Transform2D, Transform2D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorNotEqual<Plane, Plane>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::PLANE);
- register_op<OperatorEvaluatorNotEqual<Quat, Quat>>(Variant::OP_NOT_EQUAL, Variant::QUAT, Variant::QUAT);
+ register_op<OperatorEvaluatorNotEqual<Quaternion, Quaternion>>(Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorNotEqual<::AABB, ::AABB>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::AABB);
register_op<OperatorEvaluatorNotEqual<Basis, Basis>>(Variant::OP_NOT_EQUAL, Variant::BASIS, Variant::BASIS);
- register_op<OperatorEvaluatorNotEqual<Transform, Transform>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM, Variant::TRANSFORM);
+ register_op<OperatorEvaluatorNotEqual<Transform3D, Transform3D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM3D, Variant::TRANSFORM3D);
register_op<OperatorEvaluatorNotEqual<Color, Color>>(Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorNotEqual<StringName, String>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING);
@@ -1849,10 +1849,10 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorInDictionaryHas<Vector3i>>(Variant::OP_IN, Variant::VECTOR3I, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Transform2D>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Plane>>(Variant::OP_IN, Variant::PLANE, Variant::DICTIONARY);
- register_op<OperatorEvaluatorInDictionaryHas<Quat>>(Variant::OP_IN, Variant::QUAT, Variant::DICTIONARY);
+ register_op<OperatorEvaluatorInDictionaryHas<Quaternion>>(Variant::OP_IN, Variant::QUATERNION, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<::AABB>>(Variant::OP_IN, Variant::AABB, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Basis>>(Variant::OP_IN, Variant::BASIS, Variant::DICTIONARY);
- register_op<OperatorEvaluatorInDictionaryHas<Transform>>(Variant::OP_IN, Variant::TRANSFORM, Variant::DICTIONARY);
+ register_op<OperatorEvaluatorInDictionaryHas<Transform3D>>(Variant::OP_IN, Variant::TRANSFORM3D, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Color>>(Variant::OP_IN, Variant::COLOR, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::DICTIONARY);
@@ -1886,10 +1886,10 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorInArrayFind<Vector3i, Array>>(Variant::OP_IN, Variant::VECTOR3I, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Transform2D, Array>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Plane, Array>>(Variant::OP_IN, Variant::PLANE, Variant::ARRAY);
- register_op<OperatorEvaluatorInArrayFind<Quat, Array>>(Variant::OP_IN, Variant::QUAT, Variant::ARRAY);
+ register_op<OperatorEvaluatorInArrayFind<Quaternion, Array>>(Variant::OP_IN, Variant::QUATERNION, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<::AABB, Array>>(Variant::OP_IN, Variant::AABB, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Basis, Array>>(Variant::OP_IN, Variant::BASIS, Variant::ARRAY);
- register_op<OperatorEvaluatorInArrayFind<Transform, Array>>(Variant::OP_IN, Variant::TRANSFORM, Variant::ARRAY);
+ register_op<OperatorEvaluatorInArrayFind<Transform3D, Array>>(Variant::OP_IN, Variant::TRANSFORM3D, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Color, Array>>(Variant::OP_IN, Variant::COLOR, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<StringName, Array>>(Variant::OP_IN, Variant::STRING_NAME, Variant::ARRAY);
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index edaeddbf27..751cb64c62 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -190,10 +190,13 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
r_token.type = TK_COLOR;
return OK;
}
- case '@': {
+#ifndef DISABLE_DEPRECATED
+ case '@': // Compatibility with 3.x StringNames.
+#endif
+ case '&': { // StringName.
cchar = p_stream->get_char();
if (cchar != '"') {
- r_err_str = "Expected '\"' after '@'";
+ r_err_str = "Expected '\"' after '&'";
r_token.type = TK_ERROR;
return ERR_PARSE_ERROR;
}
@@ -614,7 +617,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = Plane(args[0], args[1], args[2], args[3]);
- } else if (id == "Quat") {
+ } else if (id == "Quaternion" || id == "Quat") { // "Quat" kept for compatibility
Vector<real_t> args;
Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
@@ -626,7 +629,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
return ERR_PARSE_ERROR;
}
- value = Quat(args[0], args[1], args[2], args[3]);
+ value = Quaternion(args[0], args[1], args[2], args[3]);
} else if (id == "AABB" || id == "Rect3") {
Vector<real_t> args;
Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
@@ -653,7 +656,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
- } else if (id == "Transform") {
+ } else if (id == "Transform3D" || id == "Transform") { // "Transform" kept for compatibility with Godot <4.
Vector<real_t> args;
Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
@@ -665,7 +668,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
return ERR_PARSE_ERROR;
}
- value = Transform(Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]), Vector3(args[9], args[10], args[11]));
+ value = Transform3D(Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]), Vector3(args[9], args[10], args[11]));
} else if (id == "Color") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -742,7 +745,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
return ERR_PARSE_ERROR;
}
- REF ref = REF(Object::cast_to<Reference>(obj));
+ REF ref = REF(Object::cast_to<RefCounted>(obj));
get_token(p_stream, token, line, r_err_str);
if (token.type != TK_COMMA) {
@@ -1454,9 +1457,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, "AABB( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.position.z) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ", " + rtosfix(aabb.size.z) + " )");
} break;
- case Variant::QUAT: {
- Quat quat = p_variant;
- p_store_string_func(p_store_string_ud, "Quat( " + rtosfix(quat.x) + ", " + rtosfix(quat.y) + ", " + rtosfix(quat.z) + ", " + rtosfix(quat.w) + " )");
+ case Variant::QUATERNION: {
+ Quaternion quaternion = p_variant;
+ p_store_string_func(p_store_string_ud, "Quaternion( " + rtosfix(quaternion.x) + ", " + rtosfix(quaternion.y) + ", " + rtosfix(quaternion.z) + ", " + rtosfix(quaternion.w) + " )");
} break;
case Variant::TRANSFORM2D: {
@@ -1489,9 +1492,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, s + " )");
} break;
- case Variant::TRANSFORM: {
- String s = "Transform( ";
- Transform t = p_variant;
+ case Variant::TRANSFORM3D: {
+ String s = "Transform3D( ";
+ Transform3D t = p_variant;
Basis &m3 = t.basis;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
@@ -1516,7 +1519,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
case Variant::STRING_NAME: {
String str = p_variant;
- str = "@\"" + str.c_escape() + "\"";
+ str = "&\"" + str.c_escape() + "\"";
p_store_string_func(p_store_string_ud, str);
} break;
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index 5703f0200c..05fc29b5e0 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -31,8 +31,8 @@
#ifndef VARIANT_PARSER_H
#define VARIANT_PARSER_H
+#include "core/io/file_access.h"
#include "core/io/resource.h"
-#include "core/os/file_access.h"
#include "core/variant/variant.h"
class VariantParser {
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 9ab8602782..ae2795f2fd 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -279,17 +279,17 @@ SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, z, normal.z)
SETGET_STRUCT(Plane, Vector3, normal)
SETGET_NUMBER_STRUCT(Plane, double, d)
-SETGET_NUMBER_STRUCT(Quat, double, x)
-SETGET_NUMBER_STRUCT(Quat, double, y)
-SETGET_NUMBER_STRUCT(Quat, double, z)
-SETGET_NUMBER_STRUCT(Quat, double, w)
+SETGET_NUMBER_STRUCT(Quaternion, double, x)
+SETGET_NUMBER_STRUCT(Quaternion, double, y)
+SETGET_NUMBER_STRUCT(Quaternion, double, z)
+SETGET_NUMBER_STRUCT(Quaternion, double, w)
SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, x, set_axis, get_axis, 0)
SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, y, set_axis, get_axis, 1)
SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_axis, get_axis, 2)
-SETGET_STRUCT(Transform, Basis, basis)
-SETGET_STRUCT(Transform, Vector3, origin)
+SETGET_STRUCT(Transform3D, Basis, basis)
+SETGET_STRUCT(Transform3D, Vector3, origin)
SETGET_NUMBER_STRUCT(Color, double, r)
SETGET_NUMBER_STRUCT(Color, double, g)
@@ -374,17 +374,17 @@ void register_named_setters_getters() {
REGISTER_MEMBER(Plane, d);
REGISTER_MEMBER(Plane, normal);
- REGISTER_MEMBER(Quat, x);
- REGISTER_MEMBER(Quat, y);
- REGISTER_MEMBER(Quat, z);
- REGISTER_MEMBER(Quat, w);
+ REGISTER_MEMBER(Quaternion, x);
+ REGISTER_MEMBER(Quaternion, y);
+ REGISTER_MEMBER(Quaternion, z);
+ REGISTER_MEMBER(Quaternion, w);
REGISTER_MEMBER(Basis, x);
REGISTER_MEMBER(Basis, y);
REGISTER_MEMBER(Basis, z);
- REGISTER_MEMBER(Transform, basis);
- REGISTER_MEMBER(Transform, origin);
+ REGISTER_MEMBER(Transform3D, basis);
+ REGISTER_MEMBER(Transform3D, origin);
REGISTER_MEMBER(Color, r);
REGISTER_MEMBER(Color, g);
@@ -975,7 +975,7 @@ INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2, double, real_t, 2)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2i, int64_t, int32_t, 2)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3, double, real_t, 3)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3i, int64_t, int32_t, 3)
-INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Quat, double, real_t, 4)
+INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Quaternion, double, real_t, 4)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Color, double, float, 4)
INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Transform2D, Vector2, .elements, 3)
@@ -1037,7 +1037,7 @@ void register_indexed_setters_getters() {
REGISTER_INDEXED_MEMBER(Vector2i);
REGISTER_INDEXED_MEMBER(Vector3);
REGISTER_INDEXED_MEMBER(Vector3i);
- REGISTER_INDEXED_MEMBER(Quat);
+ REGISTER_INDEXED_MEMBER(Quaternion);
REGISTER_INDEXED_MEMBER(Color);
REGISTER_INDEXED_MEMBER(Transform2D);
REGISTER_INDEXED_MEMBER(Basis);
@@ -1453,7 +1453,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
#ifdef DEBUG_ENABLED
- if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ if (EngineDebugger::is_active() && !_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
valid = false;
return false;
}
@@ -1680,7 +1680,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
#ifdef DEBUG_ENABLED
- if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ if (EngineDebugger::is_active() && !_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
valid = false;
return false;
}
@@ -1865,7 +1865,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
return Variant();
}
#ifdef DEBUG_ENABLED
- if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ if (EngineDebugger::is_active() && !_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
r_valid = false;
return Variant();
}
@@ -2135,10 +2135,10 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst)
r_dst = ::AABB(ra->position + rb->position * c, ra->size + rb->size * c);
}
return;
- case QUAT: {
- Quat empty_rot;
- const Quat *qa = reinterpret_cast<const Quat *>(a._data._mem);
- const Quat *qb = reinterpret_cast<const Quat *>(b._data._mem);
+ case QUATERNION: {
+ Quaternion empty_rot;
+ const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem);
+ const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem);
r_dst = *qa * empty_rot.slerp(*qb, c);
}
return;
@@ -2295,8 +2295,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
r_dst = a;
}
return;
- case QUAT: {
- r_dst = reinterpret_cast<const Quat *>(a._data._mem)->slerp(*reinterpret_cast<const Quat *>(b._data._mem), c);
+ case QUATERNION: {
+ r_dst = reinterpret_cast<const Quaternion *>(a._data._mem)->slerp(*reinterpret_cast<const Quaternion *>(b._data._mem), c);
}
return;
case AABB: {
@@ -2304,11 +2304,11 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case BASIS: {
- r_dst = Transform(*a._data._basis).interpolate_with(Transform(*b._data._basis), c).basis;
+ r_dst = Transform3D(*a._data._basis).interpolate_with(Transform3D(*b._data._basis), c).basis;
}
return;
- case TRANSFORM: {
- r_dst = a._data._transform->interpolate_with(*b._data._transform, c);
+ case TRANSFORM3D: {
+ r_dst = a._data._transform3d->interpolate_with(*b._data._transform3d, c);
}
return;
case COLOR: {
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 553f2b23a2..5d1efb4166 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -32,7 +32,7 @@
#include "core/core_string_names.h"
#include "core/io/marshalls.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/os.h"
#include "core/templates/oa_hash_map.h"
#include "core/variant/binder_common.h"
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index af66a11fe5..552fc41318 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -1261,6 +1261,9 @@
<member name="TextServerManager" type="TextServerManager" setter="" getter="">
The [TextServerManager] singleton.
</member>
+ <member name="Time" type="Time" setter="" getter="">
+ The [Time] singleton.
+ </member>
<member name="TranslationServer" type="TranslationServer" setter="" getter="">
The [TranslationServer] singleton.
</member>
@@ -1393,7 +1396,7 @@
<constant name="KEY_SHIFT" value="16777237" enum="Key">
Shift key.
</constant>
- <constant name="KEY_CONTROL" value="16777238" enum="Key">
+ <constant name="KEY_CTRL" value="16777238" enum="Key">
Control key.
</constant>
<constant name="KEY_META" value="16777239" enum="Key">
@@ -2596,8 +2599,8 @@
<constant name="TYPE_PLANE" value="12" enum="Variant.Type">
Variable is of type [Plane].
</constant>
- <constant name="TYPE_QUAT" value="13" enum="Variant.Type">
- Variable is of type [Quat].
+ <constant name="TYPE_QUATERNION" value="13" enum="Variant.Type">
+ Variable is of type [Quaternion].
</constant>
<constant name="TYPE_AABB" value="14" enum="Variant.Type">
Variable is of type [AABB].
@@ -2605,8 +2608,8 @@
<constant name="TYPE_BASIS" value="15" enum="Variant.Type">
Variable is of type [Basis].
</constant>
- <constant name="TYPE_TRANSFORM" value="16" enum="Variant.Type">
- Variable is of type [Transform].
+ <constant name="TYPE_TRANSFORM3D" value="16" enum="Variant.Type">
+ Variable is of type [Transform3D].
</constant>
<constant name="TYPE_COLOR" value="17" enum="Variant.Type">
Variable is of type [Color].
diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml
index a28bde9946..af34a948f5 100644
--- a/doc/classes/AABB.xml
+++ b/doc/classes/AABB.xml
@@ -242,7 +242,7 @@
<method name="operator *" qualifiers="operator">
<return type="AABB">
</return>
- <argument index="0" name="right" type="Transform">
+ <argument index="0" name="right" type="Transform3D">
</argument>
<description>
</description>
diff --git a/doc/classes/AESContext.xml b/doc/classes/AESContext.xml
index f577bab992..9dde25028e 100644
--- a/doc/classes/AESContext.xml
+++ b/doc/classes/AESContext.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AESContext" inherits="Reference" version="4.0">
+<class name="AESContext" inherits="RefCounted" version="4.0">
<brief_description>
Interface to low level AES encryption features.
</brief_description>
diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml
index fce2b90197..cc7f7072b9 100644
--- a/doc/classes/AStar.xml
+++ b/doc/classes/AStar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AStar" inherits="Reference" version="4.0">
+<class name="AStar" inherits="RefCounted" version="4.0">
<brief_description>
An implementation of A* to find the shortest paths among connected points in space.
</brief_description>
diff --git a/doc/classes/AStar2D.xml b/doc/classes/AStar2D.xml
index 3efd2f604c..9edc300169 100644
--- a/doc/classes/AStar2D.xml
+++ b/doc/classes/AStar2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AStar2D" inherits="Reference" version="4.0">
+<class name="AStar2D" inherits="RefCounted" version="4.0">
<brief_description>
AStar class representation that uses 2D vectors as edges.
</brief_description>
diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml
index f4cf246713..f644606040 100644
--- a/doc/classes/AcceptDialog.xml
+++ b/doc/classes/AcceptDialog.xml
@@ -49,7 +49,7 @@
<method name="register_text_enter">
<return type="void">
</return>
- <argument index="0" name="line_edit" type="Node">
+ <argument index="0" name="line_edit" type="Control">
</argument>
<description>
Registers a [LineEdit] in the dialog. When the enter key is pressed, the dialog will be accepted.
diff --git a/doc/classes/AnimatedSprite2D.xml b/doc/classes/AnimatedSprite2D.xml
index 969e9cc85b..d18419f163 100644
--- a/doc/classes/AnimatedSprite2D.xml
+++ b/doc/classes/AnimatedSprite2D.xml
@@ -22,7 +22,7 @@
<method name="play">
<return type="void">
</return>
- <argument index="0" name="anim" type="StringName" default="@&quot;&quot;">
+ <argument index="0" name="anim" type="StringName" default="&amp;&quot;&quot;">
</argument>
<argument index="1" name="backwards" type="bool" default="false">
</argument>
@@ -39,7 +39,7 @@
</method>
</methods>
<members>
- <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="@&quot;default&quot;">
+ <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="&amp;&quot;default&quot;">
The current animation from the [code]frames[/code] resource. If this value changes, the [code]frame[/code] counter is reset.
</member>
<member name="centered" type="bool" setter="set_centered" getter="is_centered" default="true">
diff --git a/doc/classes/AnimatedSprite3D.xml b/doc/classes/AnimatedSprite3D.xml
index 02ccab4e05..39ab317b79 100644
--- a/doc/classes/AnimatedSprite3D.xml
+++ b/doc/classes/AnimatedSprite3D.xml
@@ -20,7 +20,7 @@
<method name="play">
<return type="void">
</return>
- <argument index="0" name="anim" type="StringName" default="@&quot;&quot;">
+ <argument index="0" name="anim" type="StringName" default="&amp;&quot;&quot;">
</argument>
<description>
Plays the animation named [code]anim[/code]. If no [code]anim[/code] is provided, the current animation is played.
@@ -35,7 +35,7 @@
</method>
</methods>
<members>
- <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="@&quot;default&quot;">
+ <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="&amp;&quot;default&quot;">
The current animation from the [code]frames[/code] resource. If this value changes, the [code]frame[/code] counter is reset.
</member>
<member name="frame" type="int" setter="set_frame" getter="get_frame" default="0">
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 7ceb21d22e..02203a3725 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -640,7 +640,7 @@
</argument>
<argument index="2" name="location" type="Vector3">
</argument>
- <argument index="3" name="rotation" type="Quat">
+ <argument index="3" name="rotation" type="Quaternion">
</argument>
<argument index="4" name="scale" type="Vector3">
</argument>
@@ -656,7 +656,7 @@
<argument index="1" name="time_sec" type="float">
</argument>
<description>
- Returns the interpolated value of a transform track at a given time (in seconds). An array consisting of 3 elements: position ([Vector3]), rotation ([Quat]) and scale ([Vector3]).
+ Returns the interpolated value of a transform track at a given time (in seconds). An array consisting of 3 elements: position ([Vector3]), rotation ([Quaternion]) and scale ([Vector3]).
</description>
</method>
<method name="value_track_get_key_indices" qualifiers="const">
@@ -727,8 +727,8 @@
<constant name="TYPE_VALUE" value="0" enum="TrackType">
Value tracks set values in node properties, but only those which can be Interpolated.
</constant>
- <constant name="TYPE_TRANSFORM" value="1" enum="TrackType">
- Transform tracks are used to change node local transforms or skeleton pose bones. Transitions are interpolated.
+ <constant name="TYPE_TRANSFORM3D" value="1" enum="TrackType">
+ Transform3D tracks are used to change node local transforms or skeleton pose bones of 3D nodes. Transitions are interpolated.
</constant>
<constant name="TYPE_METHOD" value="2" enum="TrackType">
Method tracks call functions with given arguments per key.
diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml
index 8204b456d9..fddd8989ab 100644
--- a/doc/classes/AnimationNode.xml
+++ b/doc/classes/AnimationNode.xml
@@ -11,6 +11,65 @@
<link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link>
</tutorials>
<methods>
+ <method name="_get_caption" qualifiers="virtual">
+ <return type="String">
+ </return>
+ <description>
+ Gets the text caption for this node (used by some editors).
+ </description>
+ </method>
+ <method name="_get_child_by_name" qualifiers="virtual">
+ <return type="Object">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ Gets a child node by index (used by editors inheriting from [AnimationRootNode]).
+ </description>
+ </method>
+ <method name="_get_child_nodes" qualifiers="virtual">
+ <return type="Dictionary">
+ </return>
+ <description>
+ Gets all children nodes in order as a [code]name: node[/code] dictionary. Only useful when inheriting [AnimationRootNode].
+ </description>
+ </method>
+ <method name="_get_parameter_default_value" qualifiers="virtual">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="name" type="StringName">
+ </argument>
+ <description>
+ Gets the default value of a parameter. Parameters are custom local memory used for your nodes, given a resource can be reused in multiple trees.
+ </description>
+ </method>
+ <method name="_get_parameter_list" qualifiers="virtual">
+ <return type="Array">
+ </return>
+ <description>
+ Gets the property information for parameter. Parameters are custom local memory used for your nodes, given a resource can be reused in multiple trees. Format is similar to [method Object.get_property_list].
+ </description>
+ </method>
+ <method name="_has_filter" qualifiers="virtual">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] whether you want the blend tree editor to display filter editing on this node.
+ </description>
+ </method>
+ <method name="_process" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="time" type="float">
+ </argument>
+ <argument index="1" name="seek" type="bool">
+ </argument>
+ <description>
+ User-defined callback called when a custom node is processed. The [code]time[/code] parameter is a relative delta, unless [code]seek[/code] is [code]true[/code], in which case it is absolute.
+ Here, call the [method blend_input], [method blend_node] or [method blend_animation] functions. You can also use [method get_parameter] and [method set_parameter] to modify local memory.
+ This function should return the time left for the current animation to finish (if unsure, pass the value from the main blend being called).
+ </description>
+ </method>
<method name="add_input">
<return type="void">
</return>
@@ -77,29 +136,6 @@
Blend another animation node (in case this node contains children animation nodes). This function is only useful if you inherit from [AnimationRootNode] instead, else editors will not display your node for addition.
</description>
</method>
- <method name="get_caption" qualifiers="virtual">
- <return type="String">
- </return>
- <description>
- Gets the text caption for this node (used by some editors).
- </description>
- </method>
- <method name="get_child_by_name" qualifiers="virtual">
- <return type="Object">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- Gets a child node by index (used by editors inheriting from [AnimationRootNode]).
- </description>
- </method>
- <method name="get_child_nodes" qualifiers="virtual">
- <return type="Dictionary">
- </return>
- <description>
- Gets all children nodes in order as a [code]name: node[/code] dictionary. Only useful when inheriting [AnimationRootNode].
- </description>
- </method>
<method name="get_input_count" qualifiers="const">
<return type="int">
</return>
@@ -125,29 +161,6 @@
Gets the value of a parameter. Parameters are custom local memory used for your nodes, given a resource can be reused in multiple trees.
</description>
</method>
- <method name="get_parameter_default_value" qualifiers="virtual">
- <return type="Variant">
- </return>
- <argument index="0" name="name" type="StringName">
- </argument>
- <description>
- Gets the default value of a parameter. Parameters are custom local memory used for your nodes, given a resource can be reused in multiple trees.
- </description>
- </method>
- <method name="get_parameter_list" qualifiers="virtual">
- <return type="Array">
- </return>
- <description>
- Gets the property information for parameter. Parameters are custom local memory used for your nodes, given a resource can be reused in multiple trees. Format is similar to [method Object.get_property_list].
- </description>
- </method>
- <method name="has_filter" qualifiers="virtual">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] whether you want the blend tree editor to display filter editing on this node.
- </description>
- </method>
<method name="is_path_filtered" qualifiers="const">
<return type="bool">
</return>
@@ -157,19 +170,6 @@
Returns [code]true[/code] whether a given path is filtered.
</description>
</method>
- <method name="process" qualifiers="virtual">
- <return type="void">
- </return>
- <argument index="0" name="time" type="float">
- </argument>
- <argument index="1" name="seek" type="bool">
- </argument>
- <description>
- User-defined callback called when a custom node is processed. The [code]time[/code] parameter is a relative delta, unless [code]seek[/code] is [code]true[/code], in which case it is absolute.
- Here, call the [method blend_input], [method blend_node] or [method blend_animation] functions. You can also use [method get_parameter] and [method set_parameter] to modify local memory.
- This function should return the time left for the current animation to finish (if unsure, pass the value from the main blend being called).
- </description>
- </method>
<method name="remove_input">
<return type="void">
</return>
diff --git a/doc/classes/AnimationNodeAnimation.xml b/doc/classes/AnimationNodeAnimation.xml
index 3f0843c112..75dae6a48e 100644
--- a/doc/classes/AnimationNodeAnimation.xml
+++ b/doc/classes/AnimationNodeAnimation.xml
@@ -14,7 +14,7 @@
<methods>
</methods>
<members>
- <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="@&quot;&quot;">
+ <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="&amp;&quot;&quot;">
Animation to use as an output. It is one of the animations provided by [member AnimationTree.anim_player].
</member>
</members>
diff --git a/doc/classes/AnimationNodeStateMachineTransition.xml b/doc/classes/AnimationNodeStateMachineTransition.xml
index 2f0ebd7de6..7f07afecee 100644
--- a/doc/classes/AnimationNodeStateMachineTransition.xml
+++ b/doc/classes/AnimationNodeStateMachineTransition.xml
@@ -10,7 +10,7 @@
<methods>
</methods>
<members>
- <member name="advance_condition" type="StringName" setter="set_advance_condition" getter="get_advance_condition" default="@&quot;&quot;">
+ <member name="advance_condition" type="StringName" setter="set_advance_condition" getter="get_advance_condition" default="&amp;&quot;&quot;">
Turn on auto advance when this condition is set. The provided name will become a boolean parameter on the [AnimationTree] that can be controlled from code (see [url=https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html#controlling-from-code][/url]). For example, if [member AnimationTree.tree_root] is an [AnimationNodeStateMachine] and [member advance_condition] is set to [code]"idle"[/code]:
[codeblocks]
[gdscript]
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index 7696f36009..8a94eee54c 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -275,7 +275,8 @@
<argument index="1" name="new_name" type="StringName">
</argument>
<description>
- If the currently being played animation changes, this signal will notify of such change.
+ Emitted when a queued animation plays after the previous animation was finished. See [method queue].
+ [b]Note:[/b] The signal is not emitted when the animation is changed via [method play] or from [AnimationTree].
</description>
</signal>
<signal name="animation_finished">
diff --git a/doc/classes/AnimationTrackEditPlugin.xml b/doc/classes/AnimationTrackEditPlugin.xml
index 8490d48718..7b96808581 100644
--- a/doc/classes/AnimationTrackEditPlugin.xml
+++ b/doc/classes/AnimationTrackEditPlugin.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationTrackEditPlugin" inherits="Reference" version="4.0">
+<class name="AnimationTrackEditPlugin" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml
index 2517941133..af7d8d73e8 100644
--- a/doc/classes/AnimationTree.xml
+++ b/doc/classes/AnimationTree.xml
@@ -21,10 +21,10 @@
</description>
</method>
<method name="get_root_motion_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<description>
- Retrieve the motion of the [member root_motion_track] as a [Transform] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_TRANSFORM], returns an identity transformation.
+ Retrieve the motion of the [member root_motion_track] as a [Transform3D] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_TRANSFORM3D], returns an identity transformation.
</description>
</method>
<method name="rename_parameter">
@@ -50,7 +50,7 @@
</member>
<member name="root_motion_track" type="NodePath" setter="set_root_motion_track" getter="get_root_motion_track" default="NodePath(&quot;&quot;)">
The path to the Animation track used for root motion. Paths must be valid scene-tree paths to a node, and must be specified starting from the parent node of the node that will reproduce the animation. To specify a track that controls properties or bones, append its name after the path, separated by [code]":"[/code]. For example, [code]"character/skeleton:ankle"[/code] or [code]"character/mesh:transform/local"[/code].
- If the track has type [constant Animation.TYPE_TRANSFORM], the transformation will be cancelled visually, and the animation will appear to stay in place.
+ If the track has type [constant Animation.TYPE_TRANSFORM3D], the transformation will be cancelled visually, and the animation will appear to stay in place.
</member>
<member name="tree_root" type="AnimationNode" setter="set_tree_root" getter="get_tree_root">
The root animation node of this [AnimationTree]. See [AnimationNode].
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index a1e522d146..96333988f8 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -54,14 +54,14 @@
The rate at which objects stop spinning in this area. Represents the angular velocity lost per second.
See [member ProjectSettings.physics/2d/default_angular_damp] for more details about damping.
</member>
- <member name="audio_bus_name" type="StringName" setter="set_audio_bus_name" getter="get_audio_bus_name" default="@&quot;Master&quot;">
+ <member name="audio_bus_name" type="StringName" setter="set_audio_bus_name" getter="get_audio_bus_name" default="&amp;&quot;Master&quot;">
The name of the area's audio bus.
</member>
<member name="audio_bus_override" type="bool" setter="set_audio_bus_override" getter="is_overriding_audio_bus" default="false">
If [code]true[/code], the area's audio bus overrides the default audio bus.
</member>
- <member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="98.0">
- The area's gravity intensity (ranges from -1024 to 1024). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction.
+ <member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="980.0">
+ The area's gravity intensity (in pixels per second squared). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction.
</member>
<member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale" default="0.0">
The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance.
@@ -107,7 +107,7 @@
</description>
</signal>
<signal name="area_shape_entered">
- <argument index="0" name="area_id" type="int">
+ <argument index="0" name="area_rid" type="RID">
</argument>
<argument index="1" name="area" type="Area2D">
</argument>
@@ -124,7 +124,7 @@
</description>
</signal>
<signal name="area_shape_exited">
- <argument index="0" name="area_id" type="int">
+ <argument index="0" name="area_rid" type="RID">
</argument>
<argument index="1" name="area" type="Area2D">
</argument>
@@ -157,7 +157,7 @@
</description>
</signal>
<signal name="body_shape_entered">
- <argument index="0" name="body_id" type="int">
+ <argument index="0" name="body_rid" type="RID">
</argument>
<argument index="1" name="body" type="Node2D">
</argument>
@@ -174,7 +174,7 @@
</description>
</signal>
<signal name="body_shape_exited">
- <argument index="0" name="body_id" type="int">
+ <argument index="0" name="body_rid" type="RID">
</argument>
<argument index="1" name="body" type="Node2D">
</argument>
diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml
index e69a89a836..a2724f3f23 100644
--- a/doc/classes/Area3D.xml
+++ b/doc/classes/Area3D.xml
@@ -52,14 +52,14 @@
The rate at which objects stop spinning in this area. Represents the angular velocity lost per second.
See [member ProjectSettings.physics/3d/default_angular_damp] for more details about damping.
</member>
- <member name="audio_bus_name" type="StringName" setter="set_audio_bus_name" getter="get_audio_bus_name" default="@&quot;Master&quot;">
+ <member name="audio_bus_name" type="StringName" setter="set_audio_bus_name" getter="get_audio_bus_name" default="&amp;&quot;Master&quot;">
The name of the area's audio bus.
</member>
<member name="audio_bus_override" type="bool" setter="set_audio_bus_override" getter="is_overriding_audio_bus" default="false">
If [code]true[/code], the area's audio bus overrides the default audio bus.
</member>
<member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="9.8">
- The area's gravity intensity (ranges from -1024 to 1024). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction.
+ The area's gravity intensity (in meters per second squared). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction.
</member>
<member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale" default="0.0">
The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance.
@@ -89,7 +89,7 @@
<member name="reverb_bus_enable" type="bool" setter="set_use_reverb_bus" getter="is_using_reverb_bus" default="false">
If [code]true[/code], the area applies reverb to its associated audio.
</member>
- <member name="reverb_bus_name" type="StringName" setter="set_reverb_bus" getter="get_reverb_bus" default="@&quot;Master&quot;">
+ <member name="reverb_bus_name" type="StringName" setter="set_reverb_bus" getter="get_reverb_bus" default="&amp;&quot;Master&quot;">
The reverb bus name to use for this area's associated audio.
</member>
<member name="reverb_bus_uniformity" type="float" setter="set_reverb_uniformity" getter="get_reverb_uniformity" default="0.0">
@@ -117,7 +117,7 @@
</description>
</signal>
<signal name="area_shape_entered">
- <argument index="0" name="area_id" type="int">
+ <argument index="0" name="area_rid" type="RID">
</argument>
<argument index="1" name="area" type="Area3D">
</argument>
@@ -134,7 +134,7 @@
</description>
</signal>
<signal name="area_shape_exited">
- <argument index="0" name="area_id" type="int">
+ <argument index="0" name="area_rid" type="RID">
</argument>
<argument index="1" name="area" type="Area3D">
</argument>
@@ -167,7 +167,7 @@
</description>
</signal>
<signal name="body_shape_entered">
- <argument index="0" name="body_id" type="int">
+ <argument index="0" name="body_rid" type="RID">
</argument>
<argument index="1" name="body" type="Node3D">
</argument>
@@ -184,7 +184,7 @@
</description>
</signal>
<signal name="body_shape_exited">
- <argument index="0" name="body_id" type="int">
+ <argument index="0" name="body_rid" type="RID">
</argument>
<argument index="1" name="body" type="Node3D">
</argument>
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 624b51e463..543ec096c7 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -33,8 +33,8 @@
[/gdscript]
[csharp]
// Array concatenation is not possible with C# arrays, but is with Godot.Collections.Array.
- var array1 = new Godot.Collections.Array("One", 2);
- var array2 = new Godot.Collections.Array(3, "Four");
+ var array1 = new Godot.Collections.Array{"One", 2};
+ var array2 = new Godot.Collections.Array{3, "Four"};
GD.Print(array1 + array2); // Prints [One, 2, 3, Four]
[/csharp]
[/codeblocks]
@@ -333,14 +333,14 @@
[gdscript]
# Will evaluate to `true`.
if 2 in [2, 4, 6, 8]:
- print("Containes!")
+ print("Contains!")
[/gdscript]
[csharp]
// As there is no "in" keyword in C#, you have to use Contains
var array = new Godot.Collections.Array{2, 4, 6, 8};
if (array.Contains(2))
{
- GD.Print("Containes!");
+ GD.Print("Contains!");
}
[/csharp]
[/codeblocks]
@@ -615,7 +615,7 @@
<argument index="0" name="func" type="Callable">
</argument>
<description>
- Sorts the array using a custom method. The custom method receives two arguments (a pair of elements from the array) and must return either [code]true[/code] or [code]false[/code].
+ Sorts the array using a custom method. The custom method receives two arguments (a pair of elements from the array) and must return either [code]true[/code] or [code]false[/code]. For two elements [code]a[/code] and [code]b[/code], if the given method returns [code]true[/code], element [code]b[/code] will be after element [code]a[/code] in the array.
[b]Note:[/b] you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
[codeblocks]
[gdscript]
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index 7c1c4656f8..f8cbc942e6 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -77,7 +77,6 @@
Creates a new surface.
Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface.
The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used.
- Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data, and the index array defines the order of the vertices.
</description>
</method>
<method name="clear_blend_shapes">
@@ -113,7 +112,7 @@
<method name="lightmap_unwrap">
<return type="int" enum="Error">
</return>
- <argument index="0" name="transform" type="Transform">
+ <argument index="0" name="transform" type="Transform3D">
</argument>
<argument index="1" name="texel_size" type="float">
</argument>
diff --git a/doc/classes/AudioEffectCompressor.xml b/doc/classes/AudioEffectCompressor.xml
index 3117978d8a..4e924bcb65 100644
--- a/doc/classes/AudioEffectCompressor.xml
+++ b/doc/classes/AudioEffectCompressor.xml
@@ -32,7 +32,7 @@
<member name="release_ms" type="float" setter="set_release_ms" getter="get_release_ms" default="250.0">
Compressor's delay time to stop reducing the signal after the signal level falls below the threshold, in milliseconds. Value can range from 20 to 2000.
</member>
- <member name="sidechain" type="StringName" setter="set_sidechain" getter="get_sidechain" default="@&quot;&quot;">
+ <member name="sidechain" type="StringName" setter="set_sidechain" getter="get_sidechain" default="&amp;&quot;&quot;">
Reduce the sound level using another audio bus for threshold detection.
</member>
<member name="threshold" type="float" setter="set_threshold" getter="get_threshold" default="0.0">
diff --git a/doc/classes/AudioEffectInstance.xml b/doc/classes/AudioEffectInstance.xml
index dc76880a36..9ab6028901 100644
--- a/doc/classes/AudioEffectInstance.xml
+++ b/doc/classes/AudioEffectInstance.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectInstance" inherits="Reference" version="4.0">
+<class name="AudioEffectInstance" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/AudioEffectSpectrumAnalyzer.xml b/doc/classes/AudioEffectSpectrumAnalyzer.xml
index 79a8932e25..10d29ff8ab 100644
--- a/doc/classes/AudioEffectSpectrumAnalyzer.xml
+++ b/doc/classes/AudioEffectSpectrumAnalyzer.xml
@@ -1,31 +1,43 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectSpectrumAnalyzer" inherits="AudioEffect" version="4.0">
<brief_description>
+ Audio effect that can be used for real-time audio visualizations.
</brief_description>
<description>
+ This audio effect does not affect sound output, but can be used for real-time audio visualizations.
+ See also [AudioStreamGenerator] for procedurally generating sounds.
</description>
<tutorials>
+ <link title="https://godotengine.org/asset-library/asset/528">Audio Spectrum Demo</link>
+ <link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
</tutorials>
<methods>
</methods>
<members>
<member name="buffer_length" type="float" setter="set_buffer_length" getter="get_buffer_length" default="2.0">
+ The length of the buffer to keep (in seconds). Higher values keep data around for longer, but require more memory.
</member>
<member name="fft_size" type="int" setter="set_fft_size" getter="get_fft_size" enum="AudioEffectSpectrumAnalyzer.FFTSize" default="2">
+ The size of the [url=https://en.wikipedia.org/wiki/Fast_Fourier_transform]Fast Fourier transform[/url] buffer. Higher values smooth out the spectrum analysis over time, but have greater latency. The effects of this higher latency are especially noticeable with sudden amplitude changes.
</member>
<member name="tap_back_pos" type="float" setter="set_tap_back_pos" getter="get_tap_back_pos" default="0.01">
</member>
</members>
<constants>
<constant name="FFT_SIZE_256" value="0" enum="FFTSize">
+ Use a buffer of 256 samples for the Fast Fourier transform. Lowest latency, but least stable over time.
</constant>
<constant name="FFT_SIZE_512" value="1" enum="FFTSize">
+ Use a buffer of 512 samples for the Fast Fourier transform. Low latency, but less stable over time.
</constant>
<constant name="FFT_SIZE_1024" value="2" enum="FFTSize">
+ Use a buffer of 1024 samples for the Fast Fourier transform. This is a compromise between latency and stability over time.
</constant>
<constant name="FFT_SIZE_2048" value="3" enum="FFTSize">
+ Use a buffer of 2048 samples for the Fast Fourier transform. High latency, but stable over time.
</constant>
<constant name="FFT_SIZE_4096" value="4" enum="FFTSize">
+ Use a buffer of 4096 samples for the Fast Fourier transform. Highest latency, but most stable over time.
</constant>
<constant name="FFT_SIZE_MAX" value="5" enum="FFTSize">
Represents the size of the [enum FFTSize] enum.
diff --git a/doc/classes/AudioStreamGenerator.xml b/doc/classes/AudioStreamGenerator.xml
index a273beb5af..8464bc8a85 100644
--- a/doc/classes/AudioStreamGenerator.xml
+++ b/doc/classes/AudioStreamGenerator.xml
@@ -1,18 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamGenerator" inherits="AudioStream" version="4.0">
<brief_description>
+ Audio stream that generates sounds procedurally.
</brief_description>
<description>
+ This audio stream does not play back sounds, but expects a script to generate audio data for it instead. See also [AudioStreamGeneratorPlayback].
+ See also [AudioEffectSpectrumAnalyzer] for performing real-time audio spectrum analysis.
+ [b]Note:[/b] Due to performance constraints, this class is best used from C# or from a compiled language via GDNative. If you still want to use this class from GDScript, consider using a lower [member mix_rate] such as 11,025 Hz or 22,050 Hz.
</description>
<tutorials>
<link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
+ <link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
</tutorials>
<methods>
</methods>
<members>
<member name="buffer_length" type="float" setter="set_buffer_length" getter="get_buffer_length" default="0.5">
+ The length of the buffer to generate (in seconds). Lower values result in less latency, but require the script to generate audio data faster, resulting in increased CPU usage and more risk for audio cracking if the CPU can't keep up.
</member>
<member name="mix_rate" type="float" setter="set_mix_rate" getter="get_mix_rate" default="44100.0">
+ The sample rate to use (in Hz). Higher values are more demanding for the CPU to generate, but result in better quality.
+ In games, common sample rates in use are [code]11025[/code], [code]16000[/code], [code]22050[/code], [code]32000[/code], [code]44100[/code], and [code]48000[/code].
+ According to the [url=https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem]Nyquist-Shannon sampling theorem[/url], there is no quality difference to human hearing when going past 40,000 Hz (since most humans can only hear up to ~20,000 Hz, often less). If you are generating lower-pitched sounds such as voices, lower sample rates such as [code]32000[/code] or [code]22050[/code] may be usable with no loss in quality.
</member>
</members>
<constants>
diff --git a/doc/classes/AudioStreamGeneratorPlayback.xml b/doc/classes/AudioStreamGeneratorPlayback.xml
index cd8e8735b6..503f72a048 100644
--- a/doc/classes/AudioStreamGeneratorPlayback.xml
+++ b/doc/classes/AudioStreamGeneratorPlayback.xml
@@ -1,11 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamGeneratorPlayback" inherits="AudioStreamPlaybackResampled" version="4.0">
<brief_description>
+ Plays back audio generated using [AudioStreamGenerator].
</brief_description>
<description>
+ This class is meant to be used with [AudioStreamGenerator] to play back the generated audio in real-time.
</description>
<tutorials>
- <link title="Audio generator demo project">https://github.com/godotengine/godot-demo-projects/tree/master/audio/generator</link>
+ <link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
+ <link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
</tutorials>
<methods>
<method name="can_push_buffer" qualifiers="const">
@@ -14,18 +17,21 @@
<argument index="0" name="amount" type="int">
</argument>
<description>
+ Returns [code]true[/code] if a buffer of the size [code]amount[/code] can be pushed to the audio sample data buffer without overflowing it, [code]false[/code] otherwise.
</description>
</method>
<method name="clear_buffer">
<return type="void">
</return>
<description>
+ Clears the audio sample data buffer.
</description>
</method>
<method name="get_frames_available" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the number of audio data frames left to play. If this returned number reaches [code]0[/code], the audio will stop playing until frames are added again. Therefore, make sure your script can always generate and push new audio frames fast enough to avoid audio cracking.
</description>
</method>
<method name="get_skips" qualifiers="const">
@@ -40,6 +46,7 @@
<argument index="0" name="frames" type="PackedVector2Array">
</argument>
<description>
+ Pushes several audio data frames to the buffer. This is usually more efficient than [method push_frame] in C# and compiled languages via GDNative, but [method push_buffer] may be [i]less[/i] efficient in GDScript.
</description>
</method>
<method name="push_frame">
@@ -48,6 +55,7 @@
<argument index="0" name="frame" type="Vector2">
</argument>
<description>
+ Pushes a single audio data frame to the buffer. This is usually less efficient than [method push_buffer] in C# and compiled languages via GDNative, but [method push_frame] may be [i]more[/i] efficient in GDScript.
</description>
</method>
</methods>
diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml
index da75ff206c..cb01aa75e8 100644
--- a/doc/classes/AudioStreamPlayback.xml
+++ b/doc/classes/AudioStreamPlayback.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamPlayback" inherits="Reference" version="4.0">
+<class name="AudioStreamPlayback" inherits="RefCounted" version="4.0">
<brief_description>
Meta class for playing back audio.
</brief_description>
diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml
index 113cc64b9d..7c7f7e0cea 100644
--- a/doc/classes/AudioStreamPlayer.xml
+++ b/doc/classes/AudioStreamPlayer.xml
@@ -60,7 +60,7 @@
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled" default="false">
If [code]true[/code], audio plays when added to scene tree.
</member>
- <member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="@&quot;Master&quot;">
+ <member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="&amp;&quot;Master&quot;">
Bus on which this audio is playing.
</member>
<member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioStreamPlayer.MixTarget" default="0">
diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml
index e7c276f463..b1e18ab550 100644
--- a/doc/classes/AudioStreamPlayer2D.xml
+++ b/doc/classes/AudioStreamPlayer2D.xml
@@ -62,7 +62,7 @@
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled" default="false">
If [code]true[/code], audio plays when added to scene tree.
</member>
- <member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="@&quot;Master&quot;">
+ <member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="&amp;&quot;Master&quot;">
Bus on which this audio is playing.
</member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="2000.0">
diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml
index db46ed2778..3bd20b4b9b 100644
--- a/doc/classes/AudioStreamPlayer3D.xml
+++ b/doc/classes/AudioStreamPlayer3D.xml
@@ -69,7 +69,7 @@
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled" default="false">
If [code]true[/code], audio plays when the AudioStreamPlayer3D node is added to scene tree.
</member>
- <member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="@&quot;Master&quot;">
+ <member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="&amp;&quot;Master&quot;">
The bus on which this audio is playing.
</member>
<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="AudioStreamPlayer3D.DopplerTracking" default="0">
@@ -108,7 +108,7 @@
<member name="unit_db" type="float" setter="set_unit_db" getter="get_unit_db" default="0.0">
The base sound level unaffected by dampening, in decibels.
</member>
- <member name="unit_size" type="float" setter="set_unit_size" getter="get_unit_size" default="1.0">
+ <member name="unit_size" type="float" setter="set_unit_size" getter="get_unit_size" default="10.0">
The factor for the attenuation effect. Higher values make the sound audible over a larger distance.
</member>
</members>
diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamSample.xml
index c12e1bd05c..d07b1ac66d 100644
--- a/doc/classes/AudioStreamSample.xml
+++ b/doc/classes/AudioStreamSample.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
AudioStreamSample stores sound samples loaded from WAV files. To play the stored sound, use an [AudioStreamPlayer] (for non-positional audio) or [AudioStreamPlayer2D]/[AudioStreamPlayer3D] (for positional audio). The sound can be looped.
- This class can also be used to store dynamically-generated PCM audio data.
+ This class can also be used to store dynamically-generated PCM audio data. See also [AudioStreamGenerator] for procedural audio generation.
</description>
<tutorials>
</tutorials>
@@ -39,7 +39,9 @@
The loop mode. This information will be imported automatically from the WAV file if present. See [enum LoopMode] constants for values.
</member>
<member name="mix_rate" type="int" setter="set_mix_rate" getter="get_mix_rate" default="44100">
- The sample rate for mixing this audio.
+ The sample rate for mixing this audio. Higher values require more storage space, but result in better quality.
+ In games, common sample rates in use are [code]11025[/code], [code]16000[/code], [code]22050[/code], [code]32000[/code], [code]44100[/code], and [code]48000[/code].
+ According to the [url=https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem]Nyquist-Shannon sampling theorem[/url], there is no quality difference to human hearing when going past 40,000 Hz (since most humans can only hear up to ~20,000 Hz, often less). If you are using lower-pitched sounds such as voices, lower sample rates such as [code]32000[/code] or [code]22050[/code] may be usable with no loss in quality.
</member>
<member name="stereo" type="bool" setter="set_stereo" getter="is_stereo" default="false">
If [code]true[/code], audio is stereo.
diff --git a/doc/classes/BakedLightmap.xml b/doc/classes/BakedLightmap.xml
deleted file mode 100644
index 6fd08fc4e4..0000000000
--- a/doc/classes/BakedLightmap.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BakedLightmap" inherits="VisualInstance3D" version="4.0">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <methods>
- </methods>
- <members>
- <member name="bias" type="float" setter="set_bias" getter="get_bias" default="0.0005">
- </member>
- <member name="bounces" type="int" setter="set_bounces" getter="get_bounces" default="1">
- </member>
- <member name="directional" type="bool" setter="set_directional" getter="is_directional" default="false">
- </member>
- <member name="environment_custom_color" type="Color" setter="set_environment_custom_color" getter="get_environment_custom_color">
- </member>
- <member name="environment_custom_energy" type="float" setter="set_environment_custom_energy" getter="get_environment_custom_energy">
- </member>
- <member name="environment_custom_sky" type="Sky" setter="set_environment_custom_sky" getter="get_environment_custom_sky">
- </member>
- <member name="environment_mode" type="int" setter="set_environment_mode" getter="get_environment_mode" enum="BakedLightmap.EnvironmentMode" default="0">
- </member>
- <member name="generate_probes_subdiv" type="int" setter="set_generate_probes" getter="get_generate_probes" enum="BakedLightmap.GenerateProbes" default="0">
- </member>
- <member name="interior" type="bool" setter="set_interior" getter="is_interior" default="false">
- </member>
- <member name="light_data" type="BakedLightmapData" setter="set_light_data" getter="get_light_data">
- </member>
- <member name="max_texture_size" type="int" setter="set_max_texture_size" getter="get_max_texture_size" default="16384">
- </member>
- <member name="quality" type="int" setter="set_bake_quality" getter="get_bake_quality" enum="BakedLightmap.BakeQuality" default="1">
- </member>
- <member name="use_denoiser" type="bool" setter="set_use_denoiser" getter="is_using_denoiser" default="true">
- </member>
- </members>
- <constants>
- <constant name="BAKE_QUALITY_LOW" value="0" enum="BakeQuality">
- </constant>
- <constant name="BAKE_QUALITY_MEDIUM" value="1" enum="BakeQuality">
- </constant>
- <constant name="BAKE_QUALITY_HIGH" value="2" enum="BakeQuality">
- </constant>
- <constant name="BAKE_QUALITY_ULTRA" value="3" enum="BakeQuality">
- </constant>
- <constant name="GENERATE_PROBES_DISABLED" value="0" enum="GenerateProbes">
- </constant>
- <constant name="GENERATE_PROBES_SUBDIV_4" value="1" enum="GenerateProbes">
- </constant>
- <constant name="GENERATE_PROBES_SUBDIV_8" value="2" enum="GenerateProbes">
- </constant>
- <constant name="GENERATE_PROBES_SUBDIV_16" value="3" enum="GenerateProbes">
- </constant>
- <constant name="GENERATE_PROBES_SUBDIV_32" value="4" enum="GenerateProbes">
- </constant>
- <constant name="BAKE_ERROR_OK" value="0" enum="BakeError">
- </constant>
- <constant name="BAKE_ERROR_NO_LIGHTMAPPER" value="1" enum="BakeError">
- </constant>
- <constant name="BAKE_ERROR_NO_SAVE_PATH" value="2" enum="BakeError">
- </constant>
- <constant name="BAKE_ERROR_NO_MESHES" value="3" enum="BakeError">
- </constant>
- <constant name="BAKE_ERROR_MESHES_INVALID" value="4" enum="BakeError">
- </constant>
- <constant name="BAKE_ERROR_CANT_CREATE_IMAGE" value="5" enum="BakeError">
- </constant>
- <constant name="BAKE_ERROR_USER_ABORTED" value="6" enum="BakeError">
- </constant>
- <constant name="ENVIRONMENT_MODE_DISABLED" value="0" enum="EnvironmentMode">
- </constant>
- <constant name="ENVIRONMENT_MODE_SCENE" value="1" enum="EnvironmentMode">
- </constant>
- <constant name="ENVIRONMENT_MODE_CUSTOM_SKY" value="2" enum="EnvironmentMode">
- </constant>
- <constant name="ENVIRONMENT_MODE_CUSTOM_COLOR" value="3" enum="EnvironmentMode">
- </constant>
- </constants>
-</class>
diff --git a/doc/classes/BakedLightmapData.xml b/doc/classes/BakedLightmapData.xml
deleted file mode 100644
index 904555c48e..0000000000
--- a/doc/classes/BakedLightmapData.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BakedLightmapData" inherits="Resource" version="4.0">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <methods>
- <method name="add_user">
- <return type="void">
- </return>
- <argument index="0" name="path" type="NodePath">
- </argument>
- <argument index="1" name="uv_scale" type="Rect2">
- </argument>
- <argument index="2" name="slice_index" type="int">
- </argument>
- <argument index="3" name="sub_instance" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_users">
- <return type="void">
- </return>
- <description>
- </description>
- </method>
- <method name="get_user_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_user_path" qualifiers="const">
- <return type="NodePath">
- </return>
- <argument index="0" name="user_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_using_spherical_harmonics" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_uses_spherical_harmonics">
- <return type="void">
- </return>
- <argument index="0" name="uses_spherical_harmonics" type="bool">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <members>
- <member name="light_texture" type="TextureLayered" setter="set_light_texture" getter="get_light_texture">
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index 0a7b4c5dab..49edb4c691 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -199,7 +199,7 @@
The emitted light's color. See [member emission_enabled].
</member>
<member name="emission_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
- If [code]true[/code], the body emits light. Emitting light makes the object appear brighter. The object can also cast light on other objects if a [GIProbe] is used and this object is used in baked lighting.
+ If [code]true[/code], the body emits light. Emitting light makes the object appear brighter. The object can also cast light on other objects if a [VoxelGI] is used and this object is used in baked lighting.
</member>
<member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy" default="1.0">
The emitted light's strength. See [member emission_enabled].
@@ -671,10 +671,7 @@
<constant name="DIFFUSE_LAMBERT_WRAP" value="2" enum="DiffuseMode">
Extends Lambert to cover more than 90 degrees when roughness increases.
</constant>
- <constant name="DIFFUSE_OREN_NAYAR" value="3" enum="DiffuseMode">
- Attempts to use roughness to emulate microsurfacing.
- </constant>
- <constant name="DIFFUSE_TOON" value="4" enum="DiffuseMode">
+ <constant name="DIFFUSE_TOON" value="3" enum="DiffuseMode">
Uses a hard cut for lighting, with smoothing affected by roughness.
</constant>
<constant name="SPECULAR_SCHLICK_GGX" value="0" enum="SpecularMode">
diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml
index 55ae58ee3a..14fca04672 100644
--- a/doc/classes/Basis.xml
+++ b/doc/classes/Basis.xml
@@ -4,7 +4,7 @@
3×3 matrix datatype.
</brief_description>
<description>
- 3×3 matrix used for 3D rotation and scale. Almost always used as an orthogonal basis for a Transform.
+ 3×3 matrix used for 3D rotation and scale. Almost always used as an orthogonal basis for a [Transform3D].
Contains 3 vector fields X, Y and Z as its columns, which are typically interpreted as the local basis vectors of a transformation. For such use, it is composed of a scaling and a rotation matrix, in that order (M = R.S).
Can also be accessed as array of 3D vectors. These vectors are normally orthogonal to each other, but are not necessarily normalized (due to scaling).
For more information, read the "Matrices and transforms" documentation article.
@@ -53,13 +53,13 @@
</argument>
<description>
Constructs a pure rotation basis matrix from the given Euler angles (in the YXZ convention: when *composing*, first Y, then X, and Z last), given in the vector format as (X angle, Y angle, Z angle).
- Consider using the [Quat] constructor instead, which uses a quaternion instead of Euler angles.
+ Consider using the [Quaternion] constructor instead, which uses a quaternion instead of Euler angles.
</description>
</method>
<method name="Basis" qualifiers="constructor">
<return type="Basis">
</return>
- <argument index="0" name="from" type="Quat">
+ <argument index="0" name="from" type="Quaternion">
</argument>
<description>
Constructs a pure rotation basis matrix from the given quaternion.
@@ -91,7 +91,7 @@
</return>
<description>
Returns the basis's rotation in the form of Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last). The returned vector contains the rotation angles in the format (X angle, Y angle, Z angle).
- Consider using the [method get_rotation_quat] method instead, which returns a [Quat] quaternion instead of Euler angles.
+ Consider using the [method get_rotation_quaternion] method instead, which returns a [Quaternion] quaternion instead of Euler angles.
</description>
</method>
<method name="get_orthogonal_index" qualifiers="const">
@@ -101,8 +101,8 @@
This function considers a discretization of rotations into 24 points on unit sphere, lying along the vectors (x,y,z) with each component being either -1, 0, or 1, and returns the index of the point best representing the orientation of the object. It is mainly used by the [GridMap] editor. For further details, refer to the Godot source code.
</description>
</method>
- <method name="get_rotation_quat" qualifiers="const">
- <return type="Quat">
+ <method name="get_rotation_quaternion" qualifiers="const">
+ <return type="Quaternion">
</return>
<description>
Returns the basis's rotation in the form of a quaternion. See [method get_euler] if you need Euler angles, but keep in mind quaternions should generally be preferred to Euler angles.
diff --git a/doc/classes/BitMap.xml b/doc/classes/BitMap.xml
index 27ead07e6f..83e598d2ba 100644
--- a/doc/classes/BitMap.xml
+++ b/doc/classes/BitMap.xml
@@ -71,6 +71,12 @@
<argument index="1" name="epsilon" type="float" default="2.0">
</argument>
<description>
+ Creates an [Array] of polygons covering a rectangular portion of the bitmap. It uses a marching squares algorithm, followed by Ramer-Douglas-Peucker (RDP) reduction of the number of vertices. Each polygon is described as a [PackedVector2Array] of its vertices.
+ To get polygons covering the whole bitmap, pass:
+ [codeblock]
+ Rect2(Vector2(), get_size())
+ [/codeblock]
+ [code]epsilon[/code] is passed to RDP to control how accurately the polygons cover the bitmap: a lower [code]epsilon[/code] corresponds to more points in the polygons.
</description>
</method>
<method name="set_bit">
diff --git a/doc/classes/Bone2D.xml b/doc/classes/Bone2D.xml
index 910d488dfd..93744ddad7 100644
--- a/doc/classes/Bone2D.xml
+++ b/doc/classes/Bone2D.xml
@@ -19,6 +19,28 @@
Stores the node's current transforms in [member rest].
</description>
</method>
+ <method name="get_autocalculate_length_and_angle" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether this [code]Bone2D[/code] node is going to autocalculate its length and bone angle using its first [code]Bone2D[/code] child node, if one exists. If there are no [code]Bone2D[/code] children, then it cannot autocalculate these values and will print a warning.
+ </description>
+ </method>
+ <method name="get_bone_angle" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Returns the angle of the bone in the [code]Bone2D[/code] node.
+ [b]Note:[/b] This is different from the [code]Bone2D[/code]'s rotation. The bone angle is the rotation of the bone shown by the [code]Bone2D[/code] gizmo, and because [code]Bone2D[/code] bones are based on positions, this can vary from the actual rotation of the [code]Bone2D[/code] node.
+ </description>
+ </method>
+ <method name="get_default_length" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Deprecated. Please use [code]get_length[/code] instead.
+ </description>
+ </method>
<method name="get_index_in_skeleton" qualifiers="const">
<return type="int">
</return>
@@ -26,6 +48,13 @@
Returns the node's index as part of the entire skeleton. See [Skeleton2D].
</description>
</method>
+ <method name="get_length" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Returns the length of the bone in the [code]Bone2D[/code] node.
+ </description>
+ </method>
<method name="get_skeleton_rest" qualifiers="const">
<return type="Transform2D">
</return>
@@ -33,11 +62,45 @@
Returns the node's [member rest] [code]Transform2D[/code] if it doesn't have a parent, or its rest pose relative to its parent.
</description>
</method>
+ <method name="set_autocalculate_length_and_angle">
+ <return type="void">
+ </return>
+ <argument index="0" name="auto_calculate" type="bool">
+ </argument>
+ <description>
+ When set to [code]true[/code], the [code]Bone2D[/code] node will attempt to automatically calculate the bone angle and length using the first child [code]Bone2D[/code] node, if one exists. If none exist, the [code]Bone2D[/code] cannot automatically calculate these values and will print a warning.
+ </description>
+ </method>
+ <method name="set_bone_angle">
+ <return type="void">
+ </return>
+ <argument index="0" name="angle" type="float">
+ </argument>
+ <description>
+ Sets the bone angle for the [code]Bone2D[/code] node. This is typically set to the rotation from the [code]Bone2D[/code] node to a child [code]Bone2D[/code] node.
+ [b]Note:[/b] This is different from the [code]Bone2D[/code]'s rotation. The bone angle is the rotation of the bone shown by the [code]Bone2D[/code] gizmo, and because [code]Bone2D[/code] bones are based on positions, this can vary from the actual rotation of the [code]Bone2D[/code] node.
+ </description>
+ </method>
+ <method name="set_default_length">
+ <return type="void">
+ </return>
+ <argument index="0" name="default_length" type="float">
+ </argument>
+ <description>
+ Deprecated. Please use [code]set_length[/code] instead.
+ </description>
+ </method>
+ <method name="set_length">
+ <return type="void">
+ </return>
+ <argument index="0" name="length" type="float">
+ </argument>
+ <description>
+ Sets the length of the bone in the [code]Bone2D[/code] node.
+ </description>
+ </method>
</methods>
<members>
- <member name="default_length" type="float" setter="set_default_length" getter="get_default_length" default="16.0">
- Length of the bone's representation drawn in the editor's viewport in pixels.
- </member>
<member name="rest" type="Transform2D" setter="set_rest" getter="get_rest" default="Transform2D( 0, 0, 0, 0, 0, 0 )">
Rest transform of the bone. You can reset the node's transforms to this value using [method apply_rest].
</member>
diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml
index aa9f99a31e..9e70978db8 100644
--- a/doc/classes/CPUParticles2D.xml
+++ b/doc/classes/CPUParticles2D.xml
@@ -199,7 +199,7 @@
<member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true">
If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect.
</member>
- <member name="gravity" type="Vector2" setter="set_gravity" getter="get_gravity" default="Vector2( 0, 98 )">
+ <member name="gravity" type="Vector2" setter="set_gravity" getter="get_gravity" default="Vector2( 0, 980 )">
Gravity applied to every particle.
</member>
<member name="hue_variation" type="float" setter="set_param" getter="get_param" default="0.0">
diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml
index 9f1d6d8e31..016eb05308 100644
--- a/doc/classes/Camera3D.xml
+++ b/doc/classes/Camera3D.xml
@@ -27,7 +27,7 @@
</description>
</method>
<method name="get_camera_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<description>
Gets the camera transform. Subclassed cameras such as [ClippedCamera3D] may provide different transforms than the [Node] transform.
@@ -55,10 +55,19 @@
<argument index="0" name="world_point" type="Vector3">
</argument>
<description>
- Returns [code]true[/code] if the given position is behind the camera.
+ Returns [code]true[/code] if the given position is behind the camera (the blue part of the linked diagram). [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/camera3d_position_frustum.png]See this diagram[/url] for an overview of position query methods.
[b]Note:[/b] A position which returns [code]false[/code] may still be outside the camera's field of view.
</description>
</method>
+ <method name="is_position_in_frustum" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="world_point" type="Vector3">
+ </argument>
+ <description>
+ Returns [code]true[/code] if the given position is inside the camera's frustum (the green part of the linked diagram). [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/camera3d_position_frustum.png]See this diagram[/url] for an overview of position query methods.
+ </description>
+ </method>
<method name="make_current">
<return type="void">
</return>
diff --git a/doc/classes/CameraFeed.xml b/doc/classes/CameraFeed.xml
index 4fc124592f..fc7dcd3772 100644
--- a/doc/classes/CameraFeed.xml
+++ b/doc/classes/CameraFeed.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CameraFeed" inherits="Reference" version="4.0">
+<class name="CameraFeed" inherits="RefCounted" version="4.0">
<brief_description>
A camera feed gives you access to a single physical camera attached to your device.
</brief_description>
diff --git a/doc/classes/CharFXTransform.xml b/doc/classes/CharFXTransform.xml
index 850098f741..7a6a18f532 100644
--- a/doc/classes/CharFXTransform.xml
+++ b/doc/classes/CharFXTransform.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CharFXTransform" inherits="Reference" version="4.0">
+<class name="CharFXTransform" inherits="RefCounted" version="4.0">
<brief_description>
Controls how an individual character will be displayed in a [RichTextEffect].
</brief_description>
@@ -37,7 +37,7 @@
The position offset the character will be drawn with (in pixels).
</member>
<member name="outline" type="bool" setter="set_outline" getter="is_outline" default="false">
- If [code]ture[/code], FX transform is called for outline drawing. Setting this property won't affect drawing.
+ If [code]true[/code], FX transform is called for outline drawing. Setting this property won't affect drawing.
</member>
<member name="range" type="Vector2i" setter="set_range" getter="get_range" default="Vector2i( 0, 0 )">
Absolute character range in the string, corresponding to the glyph. Setting this property won't affect drawing.
diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml
new file mode 100644
index 0000000000..0e6ca073a7
--- /dev/null
+++ b/doc/classes/CharacterBody2D.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="CharacterBody2D" inherits="PhysicsBody2D" version="4.0">
+ <brief_description>
+ Character body 2D node.
+ </brief_description>
+ <description>
+ Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a static body. However, they have two main uses:
+ [b]Kinematic characters:[/b] Character bodies have an API for moving objects with walls and slopes detection ([method move_and_slide] method), in addition to collision detection (also done with [method PhysicsBody3D.move_and_collide]). This makes them really useful to implement characters that move in specific ways and collide with the world, but don't require advanced physics.
+ [b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [member StaticBody3D.kinematic_motion] when enabled), which allows them to be moved by code and push other bodies on their path.
+ </description>
+ <tutorials>
+ <link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link>
+ <link title="Using KinematicBody2D">https://docs.godotengine.org/en/latest/tutorials/physics/using_kinematic_body_2d.html</link>
+ <link title="2D Kinematic Character Demo">https://godotengine.org/asset-library/asset/113</link>
+ <link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/120</link>
+ </tutorials>
+ <methods>
+ <method name="get_floor_normal" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ Returns the surface normal of the floor at the last collision point. Only valid after calling [method move_and_slide] and when [method is_on_floor] returns [code]true[/code].
+ </description>
+ </method>
+ <method name="get_floor_velocity" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] and when [method is_on_floor] returns [code]true[/code].
+ </description>
+ </method>
+ <method name="get_slide_collision">
+ <return type="KinematicCollision2D">
+ </return>
+ <argument index="0" name="slide_idx" type="int">
+ </argument>
+ <description>
+ Returns a [KinematicCollision2D], which contains information about a collision that occurred during the last call to [method move_and_slide]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
+ [b]Example usage:[/b]
+ [codeblocks]
+ [gdscript]
+ for i in get_slide_count():
+ var collision = get_slide_collision(i)
+ print("Collided with: ", collision.collider.name)
+ [/gdscript]
+ [csharp]
+ for (int i = 0; i &lt; GetSlideCount(); i++)
+ {
+ KinematicCollision2D collision = GetSlideCollision(i);
+ GD.Print("Collided with: ", (collision.Collider as Node).Name);
+ }
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="get_slide_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the number of times the body collided and changed direction during the last call to [method move_and_slide].
+ </description>
+ </method>
+ <method name="is_on_ceiling" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the body collided with the ceiling on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
+ <method name="is_on_floor" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the body collided with the floor on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
+ <method name="is_on_wall" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the body collided with a wall on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
+ <method name="move_and_slide">
+ <return type="void">
+ </return>
+ <description>
+ Moves the body based on [member linear_velocity]. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [CharacterBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes.
+ This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed.
+ Modifies [member linear_velocity] if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.08">
+ Extra margin used for collision recovery when calling [method move_and_slide].
+ If the body is at least this close to another body, it will consider them to be colliding and will be pushed away before performing the actual motion.
+ A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors.
+ A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of character bodies.
+ </member>
+ <member name="floor_max_angle" type="float" setter="set_floor_max_angle" getter="get_floor_max_angle" default="0.785398">
+ Maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. The default value equals 45 degrees.
+ </member>
+ <member name="floor_max_angle_degrees" type="float" setter="set_floor_max_angle_degrees" getter="get_floor_max_angle_degrees" default="45.0">
+ Maximum angle (in degrees) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide].
+ </member>
+ <member name="infinite_inertia" type="bool" setter="set_infinite_inertia_enabled" getter="is_infinite_inertia_enabled" default="true">
+ If [code]true[/code], the body will be able to push [RigidBody2D] nodes when calling [method move_and_slide], but it also won't detect any collisions with them. If [code]false[/code], it will interact with [RigidBody2D] nodes like with [StaticBody2D].
+ </member>
+ <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector2( 0, 0 )">
+ Current velocity vector in pixels per second, used and modified during calls to [method move_and_slide].
+ </member>
+ <member name="max_slides" type="int" setter="set_max_slides" getter="get_max_slides" default="4">
+ Maximum number of times the body can change direction before it stops when calling [method move_and_slide].
+ </member>
+ <member name="motion/sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
+ If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method move_and_slide] or [method PhysicsBody2D.move_and_collide] functions.
+ </member>
+ <member name="snap" type="Vector2" setter="set_snap" getter="get_snap" default="Vector2( 0, 0 )">
+ When set to a value different from [code]Vector2(0, 0)[/code], the body is kept attached to slopes when calling [method move_and_slide].
+ As long as the [code]snap[/code] vector is in contact with the ground, the body will remain attached to the surface. This means you must disable snap in order to jump, for example. You can do this by setting [code]snap[/code] to [code]Vector2(0, 0)[/code].
+ </member>
+ <member name="stop_on_slope" type="bool" setter="set_stop_on_slope_enabled" getter="is_stop_on_slope_enabled" default="false">
+ If [code]true[/code], the body will not slide on slopes when you include gravity in [code]linear_velocity[/code] when calling [method move_and_slide] and the body is standing still.
+ </member>
+ <member name="up_direction" type="Vector2" setter="set_up_direction" getter="get_up_direction" default="Vector2( 0, -1 )">
+ Direction vector used to determine what is a wall and what is a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. Defaults to [code]Vector2.UP[/code]. If set to [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml
new file mode 100644
index 0000000000..790edfcad1
--- /dev/null
+++ b/doc/classes/CharacterBody3D.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="CharacterBody3D" inherits="PhysicsBody3D" version="4.0">
+ <brief_description>
+ Character body 3D node.
+ </brief_description>
+ <description>
+ Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a static body. However, they have two main uses:
+ [b]Kinematic characters:[/b] Character bodies have an API for moving objects with walls and slopes detection ([method move_and_slide] method), in addition to collision detection (also done with [method PhysicsBody3D.move_and_collide]). This makes them really useful to implement characters that move in specific ways and collide with the world, but don't require advanced physics.
+ [b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [member StaticBody3D.kinematic_motion] when enabled), which allows them to be moved by code and push other bodies on their path.
+ </description>
+ <tutorials>
+ <link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link>
+ <link title="3D Kinematic Character Demo">https://godotengine.org/asset-library/asset/126</link>
+ <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link>
+ <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link>
+ <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
+ </tutorials>
+ <methods>
+ <method name="get_floor_normal" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ Returns the surface normal of the floor at the last collision point. Only valid after calling [method move_and_slide] and when [method is_on_floor] returns [code]true[/code].
+ </description>
+ </method>
+ <method name="get_floor_velocity" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] and when [method is_on_floor] returns [code]true[/code].
+ </description>
+ </method>
+ <method name="get_slide_collision">
+ <return type="KinematicCollision3D">
+ </return>
+ <argument index="0" name="slide_idx" type="int">
+ </argument>
+ <description>
+ Returns a [KinematicCollision3D], which contains information about a collision that occurred during the last call to [method move_and_slide]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
+ </description>
+ </method>
+ <method name="get_slide_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the number of times the body collided and changed direction during the last call to [method move_and_slide].
+ </description>
+ </method>
+ <method name="is_on_ceiling" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the body collided with the ceiling on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
+ <method name="is_on_floor" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the body collided with the floor on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
+ <method name="is_on_wall" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the body collided with a wall on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
+ <method name="move_and_slide">
+ <return type="void">
+ </return>
+ <description>
+ Moves the body based on [member linear_velocity]. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [CharacterBody3D] or [RigidBody3D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes.
+ This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed.
+ Modifies [member linear_velocity] if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.001">
+ Extra margin used for collision recovery when calling [method move_and_slide].
+ If the body is at least this close to another body, it will consider them to be colliding and will be pushed away before performing the actual motion.
+ A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors.
+ A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of character bodies.
+ </member>
+ <member name="floor_max_angle" type="float" setter="set_floor_max_angle" getter="get_floor_max_angle" default="0.785398">
+ Maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. The default value equals 45 degrees.
+ </member>
+ <member name="floor_max_angle_degrees" type="float" setter="set_floor_max_angle_degrees" getter="get_floor_max_angle_degrees" default="45.0">
+ Maximum angle (in degrees) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide].
+ </member>
+ <member name="infinite_inertia" type="bool" setter="set_infinite_inertia_enabled" getter="is_infinite_inertia_enabled" default="true">
+ If [code]true[/code], the body will be able to push [RigidBody3D] nodes when calling [method move_and_slide], but it also won't detect any collisions with them. If [code]false[/code], it will interact with [RigidBody3D] nodes like with [StaticBody3D].
+ </member>
+ <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector3( 0, 0, 0 )">
+ Current velocity vector (typically meters per second), used and modified during calls to [method move_and_slide].
+ </member>
+ <member name="max_slides" type="int" setter="set_max_slides" getter="get_max_slides" default="4">
+ Maximum number of times the body can change direction before it stops when calling [method move_and_slide].
+ </member>
+ <member name="snap" type="Vector3" setter="set_snap" getter="get_snap" default="Vector3( 0, 0, 0 )">
+ When set to a value different from [code]Vector3(0, 0, 0)[/code], the body is kept attached to slopes when calling [method move_and_slide].
+ As long as the [code]snap[/code] vector is in contact with the ground, the body will remain attached to the surface. This means you must disable snap in order to jump, for example. You can do this by setting [code]snap[/code] to [code]Vector3(0, 0, 0)[/code].
+ </member>
+ <member name="stop_on_slope" type="bool" setter="set_stop_on_slope_enabled" getter="is_stop_on_slope_enabled" default="false">
+ If [code]true[/code], the body will not slide on slopes when you include gravity in [code]linear_velocity[/code] when calling [method move_and_slide] and the body is standing still.
+ </member>
+ <member name="up_direction" type="Vector3" setter="set_up_direction" getter="get_up_direction" default="Vector3( 0, 1, 0 )">
+ Direction vector used to determine what is a wall and what is a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. Defaults to [code]Vector3.UP[/code]. If set to [code]Vector3(0, 0, 0)[/code], everything is considered a wall. This is useful for topdown games.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml
index 81795abcdd..4076198df6 100644
--- a/doc/classes/CodeEdit.xml
+++ b/doc/classes/CodeEdit.xml
@@ -8,6 +8,91 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_confirm_code_completion" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="replace" type="bool">
+ </argument>
+ <description>
+ Override this method to define how the selected entry should be inserted. If [code]replace[/code] is true, any existing text should be replaced.
+ </description>
+ </method>
+ <method name="_filter_code_completion_candidates" qualifiers="virtual">
+ <return type="Array">
+ </return>
+ <argument index="0" name="candidates" type="Array">
+ </argument>
+ <description>
+ Override this method to define what items in [code]candidates[/code] should be displayed.
+ Both [code]candidates[/code] and the return is a [Array] of [Dictionary], see [method get_code_completion_option] for [Dictionary] content.
+ </description>
+ </method>
+ <method name="_request_code_completion" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="force" type="bool">
+ </argument>
+ <description>
+ Override this method to define what happens when the user requests code completion. If [code]force[/code] is true, any checks should be bypassed.
+ </description>
+ </method>
+ <method name="add_code_completion_option">
+ <return type="void">
+ </return>
+ <argument index="0" name="type" type="int" enum="CodeEdit.CodeCompletionKind">
+ </argument>
+ <argument index="1" name="display_text" type="String">
+ </argument>
+ <argument index="2" name="insert_text" type="String">
+ </argument>
+ <argument index="3" name="text_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ </argument>
+ <argument index="4" name="icon" type="Resource" default="null">
+ </argument>
+ <argument index="5" name="value" type="Variant" default="0">
+ </argument>
+ <description>
+ Submits an item to the queue of potential candidates for the autocomplete menu. Call [method update_code_completion_options] to update the list.
+ [b]Note[/b]: This list will replace all current candidates.
+ </description>
+ </method>
+ <method name="add_comment_delimiter">
+ <return type="void">
+ </return>
+ <argument index="0" name="start_key" type="String">
+ </argument>
+ <argument index="1" name="end_key" type="String">
+ </argument>
+ <argument index="2" name="line_only" type="bool" default="false">
+ </argument>
+ <description>
+ Adds a comment delimiter.
+ Both the start and end keys must be symbols. Only the start key has to be unique.
+ Line only denotes if the region should continue until the end of the line or carry over on to the next line. If the end key is blank this is automatically set to [code]true[/code].
+ </description>
+ </method>
+ <method name="add_string_delimiter">
+ <return type="void">
+ </return>
+ <argument index="0" name="start_key" type="String">
+ </argument>
+ <argument index="1" name="end_key" type="String">
+ </argument>
+ <argument index="2" name="line_only" type="bool" default="false">
+ </argument>
+ <description>
+ Adds a string delimiter.
+ Both the start and end keys must be symbols. Only the start key has to be unique.
+ Line only denotes if the region should continue until the end of the line or carry over on to the next line. If the end key is blank this is automatically set to [code]true[/code].
+ </description>
+ </method>
+ <method name="cancel_code_completion">
+ <return type="void">
+ </return>
+ <description>
+ Cancels the autocomplete menu.
+ </description>
+ </method>
<method name="clear_bookmarked_lines">
<return type="void">
</return>
@@ -20,12 +105,35 @@
<description>
</description>
</method>
+ <method name="clear_comment_delimiters">
+ <return type="void">
+ </return>
+ <description>
+ Removes all comment delimiters.
+ </description>
+ </method>
<method name="clear_executing_lines">
<return type="void">
</return>
<description>
</description>
</method>
+ <method name="clear_string_delimiters">
+ <return type="void">
+ </return>
+ <description>
+ Removes all string delimiters.
+ </description>
+ </method>
+ <method name="confirm_code_completion">
+ <return type="void">
+ </return>
+ <argument index="0" name="replace" type="bool" default="false">
+ </argument>
+ <description>
+ Inserts the selected entry into the text. If [code]replace[/code] is true, any existing text is replaced rather then merged.
+ </description>
+ </method>
<method name="get_bookmarked_lines" qualifiers="const">
<return type="Array">
</return>
@@ -38,12 +146,128 @@
<description>
</description>
</method>
+ <method name="get_code_completion_option" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ Gets the completion option at [code]index[/code]. The return [Dictionary] has the following key-values:
+ [code]kind[/code]: [enum CodeCompletionKind]
+ [code]display_text[/code]: Text that is shown on the autocomplete menu.
+ [code]insert_text[/code]: Text that is to be inserted when this item is selected.
+ [code]font_color[/code]: Color of the text on the autocomplete menu.
+ [code]icon[/code]: Icon to draw on the autocomplete menu.
+ [code]default_value[/code]: Value of the symbol.
+ </description>
+ </method>
+ <method name="get_code_completion_options" qualifiers="const">
+ <return type="Dictionary[]">
+ </return>
+ <description>
+ Gets all completion options, see [method get_code_completion_option] for return content.
+ </description>
+ </method>
+ <method name="get_code_completion_selected_index" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Gets the index of the current selected completion option.
+ </description>
+ </method>
+ <method name="get_delimiter_end_key" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="delimiter_index" type="int">
+ </argument>
+ <description>
+ Gets the end key for a string or comment region index.
+ </description>
+ </method>
+ <method name="get_delimiter_end_postion" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <argument index="1" name="column" type="int">
+ </argument>
+ <description>
+ If [code]line[/code] [code]column[/code] is in a string or comment, returns the end position of the region. If not or no end could be found, both [Vector2] values will be [code]-1[/code].
+ </description>
+ </method>
+ <method name="get_delimiter_start_key" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="delimiter_index" type="int">
+ </argument>
+ <description>
+ Gets the start key for a string or comment region index.
+ </description>
+ </method>
+ <method name="get_delimiter_start_postion" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <argument index="1" name="column" type="int">
+ </argument>
+ <description>
+ If [code]line[/code] [code]column[/code] is in a string or comment, returns the start position of the region. If not or no start could be found, both [Vector2] values will be [code]-1[/code].
+ </description>
+ </method>
<method name="get_executing_lines" qualifiers="const">
<return type="Array">
</return>
<description>
</description>
</method>
+ <method name="get_text_for_code_completion" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns the full text with char [code]0xFFFF[/code] at the caret location.
+ </description>
+ </method>
+ <method name="has_comment_delimiter" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="start_key" type="String">
+ </argument>
+ <description>
+ Returns [code]true[/code] if comment [code]start_key[/code] exists.
+ </description>
+ </method>
+ <method name="has_string_delimiter" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="start_key" type="String">
+ </argument>
+ <description>
+ Returns [code]true[/code] if string [code]start_key[/code] exists.
+ </description>
+ </method>
+ <method name="is_in_comment" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <argument index="1" name="column" type="int" default="-1">
+ </argument>
+ <description>
+ Return delimiter index if [code]line[/code] [code]column[/code] is in a comment. If [code]column[/code] is not provided, will return delimiter index if the entire [code]line[/code] is a comment. Otherwise [code]-1[/code].
+ </description>
+ </method>
+ <method name="is_in_string" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <argument index="1" name="column" type="int" default="-1">
+ </argument>
+ <description>
+ Return the delimiter index if [code]line[/code] [code]column[/code] is in a string. If [code]column[/code] is not provided, will return the delimiter index if the entire [code]line[/code] is a string. Otherwise [code]-1[/code].
+ </description>
+ </method>
<method name="is_line_bookmarked" qualifiers="const">
<return type="bool">
</return>
@@ -68,6 +292,60 @@
<description>
</description>
</method>
+ <method name="remove_comment_delimiter">
+ <return type="void">
+ </return>
+ <argument index="0" name="start_key" type="String">
+ </argument>
+ <description>
+ Removes the comment delimiter with [code]start_key[/code].
+ </description>
+ </method>
+ <method name="remove_string_delimiter">
+ <return type="void">
+ </return>
+ <argument index="0" name="start_key" type="String">
+ </argument>
+ <description>
+ Removes the string delimiter with [code]start_key[/code].
+ </description>
+ </method>
+ <method name="request_code_completion">
+ <return type="void">
+ </return>
+ <argument index="0" name="force" type="bool" default="false">
+ </argument>
+ <description>
+ Emits [signal request_code_completion], if [code]force[/code] is true will bypass all checks. Otherwise will check that the caret is in a word or in front of a prefix. Will ignore the request if all current options are of type file path, node path or signal.
+ </description>
+ </method>
+ <method name="set_code_completion_selected_index">
+ <return type="void">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ Sets the current selected completion option.
+ </description>
+ </method>
+ <method name="set_code_hint">
+ <return type="void">
+ </return>
+ <argument index="0" name="code_hint" type="String">
+ </argument>
+ <description>
+ Sets the code hint text. Pass an empty string to clear.
+ </description>
+ </method>
+ <method name="set_code_hint_draw_below">
+ <return type="void">
+ </return>
+ <argument index="0" name="draw_below" type="bool">
+ </argument>
+ <description>
+ Sets if the code hint should draw below the text.
+ </description>
+ </method>
<method name="set_line_as_bookmarked">
<return type="void">
</return>
@@ -98,8 +376,30 @@
<description>
</description>
</method>
+ <method name="update_code_completion_options">
+ <return type="void">
+ </return>
+ <argument index="0" name="force" type="bool">
+ </argument>
+ <description>
+ Submits all completion options added with [method add_code_completion_option]. Will try to force the autoccomplete menu to popup, if [code]force[/code] is [code]true[/code].
+ [b]Note[/b]: This will replace all current candidates.
+ </description>
+ </method>
</methods>
<members>
+ <member name="code_completion_enabled" type="bool" setter="set_code_completion_enabled" getter="is_code_completion_enabled" default="false">
+ Sets whether code completion is allowed.
+ </member>
+ <member name="code_completion_prefixes" type="String[]" setter="set_code_completion_prefixes" getter="get_code_comletion_prefixes" default="[ ]">
+ Sets prefixes that will trigger code completion.
+ </member>
+ <member name="delimiter_comments" type="String[]" setter="set_comment_delimiters" getter="get_comment_delimiters" default="[ ]">
+ Sets the comment delimiters. All existing comment delimiters will be removed.
+ </member>
+ <member name="delimiter_strings" type="String[]" setter="set_string_delimiters" getter="get_string_delimiters" default="[ ]">
+ Sets the string delimiters. All existing string delimiters will be removed.
+ </member>
<member name="draw_bookmarks" type="bool" setter="set_draw_bookmarks_gutter" getter="is_drawing_bookmarks_gutter" default="false">
</member>
<member name="draw_breakpoints_gutter" type="bool" setter="set_draw_breakpoints_gutter" getter="is_drawing_breakpoints_gutter" default="false">
@@ -123,8 +423,33 @@
<description>
</description>
</signal>
+ <signal name="request_code_completion">
+ <description>
+ Emitted when the user requests code completion.
+ </description>
+ </signal>
</signals>
<constants>
+ <constant name="KIND_CLASS" value="0" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_FUNCTION" value="1" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_SIGNAL" value="2" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_VARIABLE" value="3" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_MEMBER" value="4" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_ENUM" value="5" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_CONSTANT" value="6" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_NODE_PATH" value="7" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_FILE_PATH" value="8" enum="CodeCompletionKind">
+ </constant>
+ <constant name="KIND_PLAIN_TEXT" value="9" enum="CodeCompletionKind">
+ </constant>
</constants>
<theme_items>
<theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 0 )">
@@ -193,8 +518,6 @@
</theme_item>
<theme_item name="line_spacing" type="int" default="4">
</theme_item>
- <theme_item name="mark_color" type="Color" default="Color( 1, 0.4, 0.4, 0.4 )">
- </theme_item>
<theme_item name="normal" type="StyleBox">
</theme_item>
<theme_item name="outline_size" type="int" default="0">
diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml
index 522eec5cbe..4ab37f5c7b 100644
--- a/doc/classes/CollisionObject3D.xml
+++ b/doc/classes/CollisionObject3D.xml
@@ -16,14 +16,14 @@
</argument>
<argument index="1" name="event" type="InputEvent">
</argument>
- <argument index="2" name="click_position" type="Vector3">
+ <argument index="2" name="position" type="Vector3">
</argument>
- <argument index="3" name="click_normal" type="Vector3">
+ <argument index="3" name="normal" type="Vector3">
</argument>
<argument index="4" name="shape_idx" type="int">
</argument>
<description>
- Accepts unhandled [InputEvent]s. [code]click_position[/code] is the clicked location in world space and [code]click_normal[/code] is the normal vector extending from the clicked surface of the [Shape3D] at [code]shape_idx[/code]. Connect to the [code]input_event[/code] signal to easily pick up these events.
+ Receives unhandled [InputEvent]s. [code]position[/code] is the location in world space of the mouse pointer on the surface of the shape with index [code]shape_idx[/code] and [code]normal[/code] is the normal vector of the surface at that point. Connect to the [signal input_event] signal to easily pick up these events.
</description>
</method>
<method name="create_shape_owner">
@@ -179,12 +179,12 @@
</description>
</method>
<method name="shape_owner_get_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="owner_id" type="int">
</argument>
<description>
- Returns the shape owner's [Transform].
+ Returns the shape owner's [Transform3D].
</description>
</method>
<method name="shape_owner_remove_shape">
@@ -214,10 +214,10 @@
</return>
<argument index="0" name="owner_id" type="int">
</argument>
- <argument index="1" name="transform" type="Transform">
+ <argument index="1" name="transform" type="Transform3D">
</argument>
<description>
- Sets the [Transform] of the given shape owner.
+ Sets the [Transform3D] of the given shape owner.
</description>
</method>
</methods>
@@ -243,14 +243,14 @@
</argument>
<argument index="1" name="event" type="InputEvent">
</argument>
- <argument index="2" name="click_position" type="Vector3">
+ <argument index="2" name="position" type="Vector3">
</argument>
- <argument index="3" name="click_normal" type="Vector3">
+ <argument index="3" name="normal" type="Vector3">
</argument>
<argument index="4" name="shape_idx" type="int">
</argument>
<description>
- Emitted when [method _input_event] receives an event. See its description for details.
+ Emitted when the object receives an unhandled [InputEvent]. [code]position[/code] is the location in world space of the mouse pointer on the surface of the shape with index [code]shape_idx[/code] and [code]normal[/code] is the normal vector of the surface at that point.
</description>
</signal>
<signal name="mouse_entered">
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 6133bb8d8c..ddff92e6fc 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -136,6 +136,17 @@
[/codeblocks]
</description>
</method>
+ <method name="clamp" qualifiers="const">
+ <return type="Color">
+ </return>
+ <argument index="0" name="min" type="Color" default="Color( 0, 0, 0, 0 )">
+ </argument>
+ <argument index="1" name="max" type="Color" default="Color( 1, 1, 1, 1 )">
+ </argument>
+ <description>
+ Returns a new color with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component.
+ </description>
+ </method>
<method name="darkened" qualifiers="const">
<return type="Color">
</return>
diff --git a/doc/classes/ConcavePolygonShape3D.xml b/doc/classes/ConcavePolygonShape3D.xml
index a9687abedc..b510905d1f 100644
--- a/doc/classes/ConcavePolygonShape3D.xml
+++ b/doc/classes/ConcavePolygonShape3D.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Concave polygon shape resource, which can be set into a [PhysicsBody3D] or area. This shape is created by feeding a list of triangles.
- Note: when used for collision, [ConcavePolygonShape3D] is intended to work with static [PhysicsBody3D] nodes like [StaticBody3D] and will not work with [KinematicBody3D] or [RigidBody3D] with a mode other than Static.
+ Note: when used for collision, [ConcavePolygonShape3D] is intended to work with static [PhysicsBody3D] nodes like [StaticBody3D] and will not work with [CharacterBody3D] or [RigidBody3D] with a mode other than Static.
</description>
<tutorials>
<link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link>
diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml
index 38948a2d6e..8b903d8dbc 100644
--- a/doc/classes/ConfigFile.xml
+++ b/doc/classes/ConfigFile.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ConfigFile" inherits="Reference" version="4.0">
+<class name="ConfigFile" inherits="RefCounted" version="4.0">
<brief_description>
Helper class to handle INI-style files.
</brief_description>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index c0f918a01f..33969cf4c3 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -22,6 +22,34 @@
<link title="All GUI Demos">https://github.com/godotengine/godot-demo-projects/tree/master/gui</link>
</tutorials>
<methods>
+ <method name="_can_drop_data" qualifiers="virtual">
+ <return type="bool">
+ </return>
+ <argument index="0" name="position" type="Vector2">
+ </argument>
+ <argument index="1" name="data" type="Variant">
+ </argument>
+ <description>
+ Godot calls this method to test if [code]data[/code] from a control's [method _get_drag_data] can be dropped at [code]position[/code]. [code]position[/code] is local to this control.
+ This method should only be used to test the data. Process the data in [method _drop_data].
+ [codeblocks]
+ [gdscript]
+ func _can_drop_data(position, data):
+ # Check position if it is relevant to you
+ # Otherwise, just check data
+ return typeof(data) == TYPE_DICTIONARY and data.has("expected")
+ [/gdscript]
+ [csharp]
+ public override bool CanDropData(Vector2 position, object data)
+ {
+ // Check position if it is relevant to you
+ // Otherwise, just check data
+ return data is Godot.Collections.Dictionary &amp;&amp; (data as Godot.Collections.Dictionary).Contains("expected");
+ }
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
<method name="_clips_input" qualifiers="virtual">
<return type="bool">
</return>
@@ -30,6 +58,61 @@
If not overridden, defaults to [code]false[/code].
</description>
</method>
+ <method name="_drop_data" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="position" type="Vector2">
+ </argument>
+ <argument index="1" name="data" type="Variant">
+ </argument>
+ <description>
+ Godot calls this method to pass you the [code]data[/code] from a control's [method _get_drag_data] result. Godot first calls [method _can_drop_data] to test if [code]data[/code] is allowed to drop at [code]position[/code] where [code]position[/code] is local to this control.
+ [codeblocks]
+ [gdscript]
+ func _can_drop_data(position, data):
+ return typeof(data) == TYPE_DICTIONARY and data.has("color")
+ func _drop_data(position, data):
+ var color = data["color"]
+ [/gdscript]
+ [csharp]
+ public override bool CanDropData(Vector2 position, object data)
+ {
+ return data is Godot.Collections.Dictionary &amp;&amp; (data as Godot.Collections.Dictionary).Contains("color");
+ }
+ public override void DropData(Vector2 position, object data)
+ {
+ Color color = (Color)(data as Godot.Collections.Dictionary)["color"];
+ }
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="_get_drag_data" qualifiers="virtual">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="position" type="Vector2">
+ </argument>
+ <description>
+ Godot calls this method to get data that can be dragged and dropped onto controls that expect drop data. Returns [code]null[/code] if there is no data to drag. Controls that want to receive drop data should implement [method _can_drop_data] and [method _drop_data]. [code]position[/code] is local to this control. Drag may be forced with [method force_drag].
+ A preview that will follow the mouse that should represent the data can be set with [method set_drag_preview]. A good time to set the preview is in this method.
+ [codeblocks]
+ [gdscript]
+ func _get_drag_data(position):
+ var mydata = make_data() # This is your custom method generating the drag data.
+ set_drag_preview(make_preview(mydata)) # This is your custom method generating the preview of the drag data.
+ return mydata
+ [/gdscript]
+ [csharp]
+ public override object GetDragData(Vector2 position)
+ {
+ object mydata = MakeData(); // This is your custom method generating the drag data.
+ SetDragPreview(MakePreview(mydata)); // This is your custom method generating the preview of the drag data.
+ return mydata;
+ }
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
<method name="_get_minimum_size" qualifiers="virtual">
<return type="Vector2">
</return>
@@ -68,13 +151,24 @@
[/csharp]
[/codeblocks]
The event won't trigger if:
- * clicking outside the control (see [method has_point]);
+ * clicking outside the control (see [method _has_point]);
* control has [member mouse_filter] set to [constant MOUSE_FILTER_IGNORE];
* control is obstructed by another [Control] on top of it, which doesn't have [member mouse_filter] set to [constant MOUSE_FILTER_IGNORE];
* control's parent has [member mouse_filter] set to [constant MOUSE_FILTER_STOP] or has accepted the event;
* it happens outside parent's rectangle and the parent has either [member rect_clip_content] or [method _clips_input] enabled.
</description>
</method>
+ <method name="_has_point" qualifiers="virtual">
+ <return type="bool">
+ </return>
+ <argument index="0" name="point" type="Vector2">
+ </argument>
+ <description>
+ Virtual method to be implemented by the user. Returns whether the given [code]point[/code] is inside this control.
+ If not overridden, default behavior is checking if the point is within control's Rect.
+ [b]Note:[/b] If you want to check if a point is inside the control, you can use [code]get_rect().has_point(point)[/code].
+ </description>
+ </method>
<method name="_make_custom_tooltip" qualifiers="virtual">
<return type="Control">
</return>
@@ -249,63 +343,6 @@
[/codeblocks]
</description>
</method>
- <method name="can_drop_data" qualifiers="virtual">
- <return type="bool">
- </return>
- <argument index="0" name="position" type="Vector2">
- </argument>
- <argument index="1" name="data" type="Variant">
- </argument>
- <description>
- Godot calls this method to test if [code]data[/code] from a control's [method get_drag_data] can be dropped at [code]position[/code]. [code]position[/code] is local to this control.
- This method should only be used to test the data. Process the data in [method drop_data].
- [codeblocks]
- [gdscript]
- func can_drop_data(position, data):
- # Check position if it is relevant to you
- # Otherwise, just check data
- return typeof(data) == TYPE_DICTIONARY and data.has("expected")
- [/gdscript]
- [csharp]
- public override bool CanDropData(Vector2 position, object data)
- {
- // Check position if it is relevant to you
- // Otherwise, just check data
- return data is Godot.Collections.Dictionary &amp;&amp; (data as Godot.Collections.Dictionary).Contains("expected");
- }
- [/csharp]
- [/codeblocks]
- </description>
- </method>
- <method name="drop_data" qualifiers="virtual">
- <return type="void">
- </return>
- <argument index="0" name="position" type="Vector2">
- </argument>
- <argument index="1" name="data" type="Variant">
- </argument>
- <description>
- Godot calls this method to pass you the [code]data[/code] from a control's [method get_drag_data] result. Godot first calls [method can_drop_data] to test if [code]data[/code] is allowed to drop at [code]position[/code] where [code]position[/code] is local to this control.
- [codeblocks]
- [gdscript]
- func can_drop_data(position, data):
- return typeof(data) == TYPE_DICTIONARY and data.has("color")
- func drop_data(position, data):
- var color = data["color"]
- [/gdscript]
- [csharp]
- public override bool CanDropData(Vector2 position, object data)
- {
- return data is Godot.Collections.Dictionary &amp;&amp; (data as Godot.Collections.Dictionary).Contains("color");
- }
- public override void DropData(Vector2 position, object data)
- {
- Color color = (Color)(data as Godot.Collections.Dictionary)["color"];
- }
- [/csharp]
- [/codeblocks]
- </description>
- </method>
<method name="find_next_valid_focus" qualifiers="const">
<return type="Control">
</return>
@@ -328,8 +365,8 @@
<argument index="1" name="preview" type="Control">
</argument>
<description>
- Forces drag and bypasses [method get_drag_data] and [method set_drag_preview] by passing [code]data[/code] and [code]preview[/code]. Drag will start even if the mouse is neither over nor pressed on this control.
- The methods [method can_drop_data] and [method drop_data] must be implemented on controls that want to receive drop data.
+ Forces drag and bypasses [method _get_drag_data] and [method set_drag_preview] by passing [code]data[/code] and [code]preview[/code]. Drag will start even if the mouse is neither over nor pressed on this control.
+ The methods [method _can_drop_data] and [method _drop_data] must be implemented on controls that want to receive drop data.
</description>
</method>
<method name="get_anchor" qualifiers="const">
@@ -364,32 +401,6 @@
Returns the mouse cursor shape the control displays on mouse hover. See [enum CursorShape].
</description>
</method>
- <method name="get_drag_data" qualifiers="virtual">
- <return type="Variant">
- </return>
- <argument index="0" name="position" type="Vector2">
- </argument>
- <description>
- Godot calls this method to get data that can be dragged and dropped onto controls that expect drop data. Returns [code]null[/code] if there is no data to drag. Controls that want to receive drop data should implement [method can_drop_data] and [method drop_data]. [code]position[/code] is local to this control. Drag may be forced with [method force_drag].
- A preview that will follow the mouse that should represent the data can be set with [method set_drag_preview]. A good time to set the preview is in this method.
- [codeblocks]
- [gdscript]
- func get_drag_data(position):
- var mydata = make_data() # This is your custom method generating the drag data.
- set_drag_preview(make_preview(mydata)) # This is your custom method generating the preview of the drag data.
- return mydata
- [/gdscript]
- [csharp]
- public override object GetDragData(Vector2 position)
- {
- object mydata = MakeData(); // This is your custom method generating the drag data.
- SetDragPreview(MakePreview(mydata)); // This is your custom method generating the preview of the drag data.
- return mydata;
- }
- [/csharp]
- [/codeblocks]
- </description>
- </method>
<method name="get_end" qualifiers="const">
<return type="Vector2">
</return>
@@ -462,10 +473,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a color from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code].
+ Returns a color from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
[codeblocks]
[gdscript]
func _ready():
@@ -485,10 +496,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a constant from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code].
+ Returns a constant from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
</description>
</method>
<method name="get_theme_font" qualifiers="const">
@@ -496,10 +507,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a font from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code].
+ Returns a font from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
</description>
</method>
<method name="get_theme_font_size" qualifiers="const">
@@ -507,10 +518,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a font size from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]type[/code].
+ Returns a font size from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
</description>
</method>
<method name="get_theme_icon" qualifiers="const">
@@ -518,10 +529,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns an icon from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code].
+ Returns an icon from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
</description>
</method>
<method name="get_theme_stylebox" qualifiers="const">
@@ -529,10 +540,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a [StyleBox] from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code].
+ Returns a [StyleBox] from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
</description>
</method>
<method name="get_tooltip" qualifiers="const">
@@ -577,26 +588,15 @@
Returns [code]true[/code] if this is the current focused control. See [member focus_mode].
</description>
</method>
- <method name="has_point" qualifiers="virtual">
- <return type="bool">
- </return>
- <argument index="0" name="point" type="Vector2">
- </argument>
- <description>
- Virtual method to be implemented by the user. Returns whether the given [code]point[/code] is inside this control.
- If not overridden, default behavior is checking if the point is within control's Rect.
- [b]Note:[/b] If you want to check if a point is inside the control, you can use [code]get_rect().has_point(point)[/code].
- </description>
- </method>
<method name="has_theme_color" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if [Color] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if [Color] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
</description>
</method>
<method name="has_theme_color_override" qualifiers="const">
@@ -613,10 +613,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if constant with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if constant with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
</description>
</method>
<method name="has_theme_constant_override" qualifiers="const">
@@ -633,10 +633,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if font with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if font with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
</description>
</method>
<method name="has_theme_font_override" qualifiers="const">
@@ -653,10 +653,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if font size with given [code]name[/code] and associated with [Control] of given [code]type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if font size with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
</description>
</method>
<method name="has_theme_font_size_override" qualifiers="const">
@@ -673,10 +673,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if icon with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if icon with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
</description>
</method>
<method name="has_theme_icon_override" qualifiers="const">
@@ -693,10 +693,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if [StyleBox] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if [StyleBox] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
</description>
</method>
<method name="has_theme_stylebox_override" qualifiers="const">
@@ -856,7 +856,7 @@
</argument>
<description>
Forwards the handling of this control's drag and drop to [code]target[/code] control.
- Forwarding can be implemented in the target control similar to the methods [method get_drag_data], [method can_drop_data], and [method drop_data] but with two differences:
+ Forwarding can be implemented in the target control similar to the methods [method _get_drag_data], [method _can_drop_data], and [method _drop_data] but with two differences:
1. The function name must be suffixed with [b]_fw[/b]
2. The function must take an extra argument that is the control doing the forwarding
[codeblocks]
@@ -871,13 +871,13 @@
# TargetControl.gd
extends Control
- func can_drop_data_fw(position, data, from_control):
+ func _can_drop_data_fw(position, data, from_control):
return true
- func drop_data_fw(position, data, from_control):
+ func _drop_data_fw(position, data, from_control):
my_handle_data(data) # Your handler method.
- func get_drag_data_fw(position, from_control):
+ func _get_drag_data_fw(position, from_control):
set_drag_preview(my_preview)
return my_data()
[/gdscript]
@@ -922,12 +922,12 @@
<argument index="0" name="control" type="Control">
</argument>
<description>
- Shows the given control at the mouse pointer. A good time to call this method is in [method get_drag_data]. The control must not be in the scene tree. You should not free the control, and you should not keep a reference to the control beyond the duration of the drag. It will be deleted automatically after the drag has ended.
+ Shows the given control at the mouse pointer. A good time to call this method is in [method _get_drag_data]. The control must not be in the scene tree. You should not free the control, and you should not keep a reference to the control beyond the duration of the drag. It will be deleted automatically after the drag has ended.
[codeblocks]
[gdscript]
export (Color, RGBA) var color = Color(1, 0, 0, 1)
- func get_drag_data(position):
+ func _get_drag_data(position):
# Use a control that is not in the tree
var cpb = ColorPickerButton.new()
cpb.color = color
@@ -1055,7 +1055,7 @@
Anchors the right edge of the node to the origin, the center or the end of its parent control. It changes how the right offset updates when the node moves or changes size. You can use one of the [enum Anchor] constants for convenience.
</member>
<member name="anchor_top" type="float" setter="_set_anchor" getter="get_anchor" default="0.0">
- Anchors the top edge of the node to the origin, the center or the end of its parent control. It changes how the top offset updates when the node moves or changes size. You can use one of the [enum Anchor] constants for convenience.
+ Anchors the top edge of the node to the origin, the center or the end of its parent control. It changes how the top offset updates when the node moves or changes size. You can use one of the [enum Anchor] constants for convenience.
</member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" enum="Control.FocusMode" default="0">
The focus access mode for the control (None, Click or All). Only one Control can be focused at the same time, and it will receive keyboard signals.
@@ -1067,7 +1067,7 @@
Tells Godot which node it should give keyboard focus to if the user presses the left arrow on the keyboard or left on a gamepad by default. You can change the key by editing the [code]ui_left[/code] input action. The node must be a [Control]. If this property is not set, Godot will give focus to the closest [Control] to the left of this one.
</member>
<member name="focus_neighbor_right" type="NodePath" setter="set_focus_neighbor" getter="get_focus_neighbor" default="NodePath(&quot;&quot;)">
- Tells Godot which node it should give keyboard focus to if the user presses the right arrow on the keyboard or right on a gamepad by default. You can change the key by editing the [code]ui_right[/code] input action. The node must be a [Control]. If this property is not set, Godot will give focus to the closest [Control] to the bottom of this one.
+ Tells Godot which node it should give keyboard focus to if the user presses the right arrow on the keyboard or right on a gamepad by default. You can change the key by editing the [code]ui_right[/code] input action. The node must be a [Control]. If this property is not set, Godot will give focus to the closest [Control] to the bottom of this one.
</member>
<member name="focus_neighbor_top" type="NodePath" setter="set_focus_neighbor" getter="get_focus_neighbor" default="NodePath(&quot;&quot;)">
Tells Godot which node it should give keyboard focus to if the user presses the top arrow on the keyboard or top on a gamepad by default. You can change the key by editing the [code]ui_top[/code] input action. The node must be a [Control]. If this property is not set, Godot will give focus to the closest [Control] to the bottom of this one.
@@ -1173,7 +1173,12 @@
Tells the parent [Container] nodes how they should resize and place the node on the Y axis. Use one of the [enum SizeFlags] constants to change the flags. See the constants to learn what each does.
</member>
<member name="theme" type="Theme" setter="set_theme" getter="get_theme">
- Changing this property replaces the current [Theme] resource this node and all its [Control] children use.
+ The [Theme] resource this node and all its [Control] children use. If a child node has its own [Theme] resource set, theme items are merged with child's definitions having higher priority.
+ </member>
+ <member name="theme_custom_type" type="StringName" setter="set_theme_custom_type" getter="get_theme_custom_type" default="&amp;&quot;&quot;">
+ The type name used by this [Control] to look up its own theme items. By default, the class name of the node is used (e.g. [code]Button[/code] for the [Button] control), as well as the class names of all parent classes (in order of inheritance). Setting this property gives the highest priority to the type of the specified name, then falls back on the class names.
+ [b]Note:[/b] To look up [Control]'s own items use various [code]get_theme_*[/code] methods without specifying [code]theme_type[/code].
+ [b]Note:[/b] Theme items are looked for in the tree order, from branch to root, where each [Control] node is checked for its [member theme] property. The earliest match against any type/class name is returned. The project-level Theme and the default Theme are checked last.
</member>
</members>
<signals>
diff --git a/doc/classes/Crypto.xml b/doc/classes/Crypto.xml
index 1f6cb40cde..deda6116f4 100644
--- a/doc/classes/Crypto.xml
+++ b/doc/classes/Crypto.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Crypto" inherits="Reference" version="4.0">
+<class name="Crypto" inherits="RefCounted" version="4.0">
<brief_description>
Access to advanced cryptographic functionalities.
</brief_description>
diff --git a/doc/classes/DTLSServer.xml b/doc/classes/DTLSServer.xml
index 91a04b1f28..28d68d309f 100644
--- a/doc/classes/DTLSServer.xml
+++ b/doc/classes/DTLSServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="DTLSServer" inherits="Reference" version="4.0">
+<class name="DTLSServer" inherits="RefCounted" version="4.0">
<brief_description>
Helper class to implement a DTLS server.
</brief_description>
diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml
index a9d7960501..dae8d83f0c 100644
--- a/doc/classes/Directory.xml
+++ b/doc/classes/Directory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Directory" inherits="Reference" version="4.0">
+<class name="Directory" inherits="RefCounted" version="4.0">
<brief_description>
Type used to handle the filesystem.
</brief_description>
@@ -154,14 +154,14 @@
<method name="list_dir_begin">
<return type="int" enum="Error">
</return>
- <argument index="0" name="skip_navigational" type="bool" default="false">
+ <argument index="0" name="show_navigational" type="bool" default="false">
</argument>
- <argument index="1" name="skip_hidden" type="bool" default="false">
+ <argument index="1" name="show_hidden" type="bool" default="false">
</argument>
<description>
Initializes the stream used to list all files and directories using the [method get_next] function, closing the current opened stream if needed. Once the stream has been processed, it should typically be closed with [method list_dir_end].
- If [code]skip_navigational[/code] is [code]true[/code], [code].[/code] and [code]..[/code] are filtered out.
- If [code]skip_hidden[/code] is [code]true[/code], hidden files are filtered out.
+ If [code]show_navigational[/code] is [code]true[/code], [code].[/code] and [code]..[/code] are included too.
+ If [code]show_hidden[/code] is [code]true[/code], hidden files are included too.
</description>
</method>
<method name="list_dir_end">
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 0c9df071a7..6c1cd37beb 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -1044,12 +1044,20 @@
<constant name="FEATURE_SWAP_BUFFERS" value="17" enum="Feature">
</constant>
<constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode">
+ Makes the mouse cursor visible if it is hidden.
</constant>
<constant name="MOUSE_MODE_HIDDEN" value="1" enum="MouseMode">
+ Makes the mouse cursor hidden if it is visible.
</constant>
<constant name="MOUSE_MODE_CAPTURED" value="2" enum="MouseMode">
+ Captures the mouse. The mouse will be hidden and its position locked at the center of the screen.
+ [b]Note:[/b] If you want to process the mouse's movement in this mode, you need to use [member InputEventMouseMotion.relative].
</constant>
<constant name="MOUSE_MODE_CONFINED" value="3" enum="MouseMode">
+ Confines the mouse cursor to the game window, and make it visible.
+ </constant>
+ <constant name="MOUSE_MODE_CONFINED_HIDDEN" value="4" enum="MouseMode">
+ Confines the mouse cursor to the game window, and make it hidden.
</constant>
<constant name="SCREEN_OF_MAIN_WINDOW" value="-1">
</constant>
diff --git a/doc/classes/EditorDebuggerPlugin.xml b/doc/classes/EditorDebuggerPlugin.xml
index b97933e582..9484d33252 100644
--- a/doc/classes/EditorDebuggerPlugin.xml
+++ b/doc/classes/EditorDebuggerPlugin.xml
@@ -38,7 +38,7 @@
<return type="bool">
</return>
<description>
- Returns [code]true[/code] if there is an instance of the game running with the attached debugger otherwise [code]false[/code].
+ Returns [code]true[/code] if there is an instance of the game running with the attached debugger otherwise [code]false[/code].
</description>
</method>
<method name="register_message_capture">
diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml
index b29734de1c..d9e3003fbb 100644
--- a/doc/classes/EditorExportPlugin.xml
+++ b/doc/classes/EditorExportPlugin.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorExportPlugin" inherits="Reference" version="4.0">
+<class name="EditorExportPlugin" inherits="RefCounted" version="4.0">
<brief_description>
A script that is executed when exporting the project.
</brief_description>
diff --git a/doc/classes/EditorFeatureProfile.xml b/doc/classes/EditorFeatureProfile.xml
index e05a685dd7..0cd839f370 100644
--- a/doc/classes/EditorFeatureProfile.xml
+++ b/doc/classes/EditorFeatureProfile.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorFeatureProfile" inherits="Reference" version="4.0">
+<class name="EditorFeatureProfile" inherits="RefCounted" version="4.0">
<brief_description>
An editor feature profile which can be used to disable specific features.
</brief_description>
diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml
index aa64ab4043..a532e9bc2b 100644
--- a/doc/classes/EditorImportPlugin.xml
+++ b/doc/classes/EditorImportPlugin.xml
@@ -5,45 +5,45 @@
</brief_description>
<description>
EditorImportPlugins provide a way to extend the editor's resource import functionality. Use them to import resources from custom files or to provide alternatives to the editor's existing importers. Register your [EditorPlugin] with [method EditorPlugin.add_import_plugin].
- EditorImportPlugins work by associating with specific file extensions and a resource type. See [method get_recognized_extensions] and [method get_resource_type]. They may optionally specify some import presets that affect the import process. EditorImportPlugins are responsible for creating the resources and saving them in the [code].godot/imported[/code] directory.
+ EditorImportPlugins work by associating with specific file extensions and a resource type. See [method _get_recognized_extensions] and [method _get_resource_type]. They may optionally specify some import presets that affect the import process. EditorImportPlugins are responsible for creating the resources and saving them in the [code].godot/imported[/code] directory.
Below is an example EditorImportPlugin that imports a [Mesh] from a file with the extension ".special" or ".spec":
[codeblocks]
[gdscript]
tool
extends EditorImportPlugin
- func get_importer_name():
+ func _get_importer_name():
return "my.special.plugin"
- func get_visible_name():
+ func _get_visible_name():
return "Special Mesh"
- func get_recognized_extensions():
+ func _get_recognized_extensions():
return ["special", "spec"]
- func get_save_extension():
+ func _get_save_extension():
return "mesh"
- func get_resource_type():
+ func _get_resource_type():
return "Mesh"
- func get_preset_count():
+ func _get_preset_count():
return 1
- func get_preset_name(i):
+ func _get_preset_name(i):
return "Default"
- func get_import_options(i):
+ func _get_import_options(i):
return [{"name": "my_option", "default_value": false}]
- func import(source_file, save_path, options, platform_variants, gen_files):
+ func _import(source_file, save_path, options, platform_variants, gen_files):
var file = File.new()
if file.open(source_file, File.READ) != OK:
return FAILED
var mesh = ArrayMesh.new()
# Fill the Mesh with data read in "file", left as an exercise to the reader.
- var filename = save_path + "." + get_save_extension()
+ var filename = save_path + "." + _get_save_extension()
return ResourceSaver.save(filename, mesh)
[/gdscript]
[csharp]
@@ -92,7 +92,7 @@
return new Godot.Collections.Array{new Godot.Collections.Dictionary{{"name", "myOption"}, {"defaultValue", false}}};
}
- public override int Import(String sourceFile, String savePath, Godot.Collections.Dictionary options, Godot.Collections.Array platformVariants, Godot.Collections.Array genFiles)
+ public override int Import(String sourceFile, String savePath, Godot.Collections.Dictionary options, Godot.Collections.Array platformVariants, Godot.Collections.Array genFiles)
{
var file = new File();
if (file.Open(sourceFile, File.ModeFlags.Read) != Error.Ok)
@@ -113,7 +113,7 @@
<link title="Import plugins">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/import_plugins.html</link>
</tutorials>
<methods>
- <method name="get_import_options" qualifiers="virtual">
+ <method name="_get_import_options" qualifiers="virtual">
<return type="Array">
</return>
<argument index="0" name="preset" type="int">
@@ -122,21 +122,21 @@
Gets the options and default values for the preset at this index. Returns an Array of Dictionaries with the following keys: [code]name[/code], [code]default_value[/code], [code]property_hint[/code] (optional), [code]hint_string[/code] (optional), [code]usage[/code] (optional).
</description>
</method>
- <method name="get_import_order" qualifiers="virtual">
+ <method name="_get_import_order" qualifiers="virtual">
<return type="int">
</return>
<description>
Gets the order of this importer to be run when importing resources. Higher values will be called later. Use this to ensure the importer runs after the dependencies are already imported.
</description>
</method>
- <method name="get_importer_name" qualifiers="virtual">
+ <method name="_get_importer_name" qualifiers="virtual">
<return type="String">
</return>
<description>
Gets the unique name of the importer.
</description>
</method>
- <method name="get_option_visibility" qualifiers="virtual">
+ <method name="_get_option_visibility" qualifiers="virtual">
<return type="bool">
</return>
<argument index="0" name="option" type="String">
@@ -147,7 +147,7 @@
This method can be overridden to hide specific import options if conditions are met. This is mainly useful for hiding options that depend on others if one of them is disabled. For example:
[codeblocks]
[gdscript]
- func get_option_visibility(option, options):
+ func _get_option_visibility(option, options):
# Only show the lossy quality setting if the compression mode is set to "Lossy".
if option == "compress/lossy_quality" and options.has("compress/mode"):
return int(options["compress/mode"]) == COMPRESS_LOSSY # This is a constant that you set
@@ -170,14 +170,14 @@
Return [code]true[/code] to make all options always visible.
</description>
</method>
- <method name="get_preset_count" qualifiers="virtual">
+ <method name="_get_preset_count" qualifiers="virtual">
<return type="int">
</return>
<description>
- Gets the number of initial presets defined by the plugin. Use [method get_import_options] to get the default options for the preset and [method get_preset_name] to get the name of the preset.
+ Gets the number of initial presets defined by the plugin. Use [method _get_import_options] to get the default options for the preset and [method _get_preset_name] to get the name of the preset.
</description>
</method>
- <method name="get_preset_name" qualifiers="virtual">
+ <method name="_get_preset_name" qualifiers="virtual">
<return type="String">
</return>
<argument index="0" name="preset" type="int">
@@ -186,42 +186,42 @@
Gets the name of the options preset at this index.
</description>
</method>
- <method name="get_priority" qualifiers="virtual">
+ <method name="_get_priority" qualifiers="virtual">
<return type="float">
</return>
<description>
Gets the priority of this plugin for the recognized extension. Higher priority plugins will be preferred. The default priority is [code]1.0[/code].
</description>
</method>
- <method name="get_recognized_extensions" qualifiers="virtual">
+ <method name="_get_recognized_extensions" qualifiers="virtual">
<return type="Array">
</return>
<description>
Gets the list of file extensions to associate with this loader (case-insensitive). e.g. [code]["obj"][/code].
</description>
</method>
- <method name="get_resource_type" qualifiers="virtual">
+ <method name="_get_resource_type" qualifiers="virtual">
<return type="String">
</return>
<description>
Gets the Godot resource type associated with this loader. e.g. [code]"Mesh"[/code] or [code]"Animation"[/code].
</description>
</method>
- <method name="get_save_extension" qualifiers="virtual">
+ <method name="_get_save_extension" qualifiers="virtual">
<return type="String">
</return>
<description>
Gets the extension used to save this resource in the [code].godot/imported[/code] directory.
</description>
</method>
- <method name="get_visible_name" qualifiers="virtual">
+ <method name="_get_visible_name" qualifiers="virtual">
<return type="String">
</return>
<description>
Gets the name to display in the import window. You should choose this name as a continuation to "Import as", e.g. "Import as Special Mesh".
</description>
</method>
- <method name="import" qualifiers="virtual">
+ <method name="_import" qualifiers="virtual">
<return type="int">
</return>
<argument index="0" name="source_file" type="String">
diff --git a/doc/classes/EditorInspectorPlugin.xml b/doc/classes/EditorInspectorPlugin.xml
index 8204dc931e..c992d0fbb4 100644
--- a/doc/classes/EditorInspectorPlugin.xml
+++ b/doc/classes/EditorInspectorPlugin.xml
@@ -1,106 +1,100 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorInspectorPlugin" inherits="Reference" version="4.0">
+<class name="EditorInspectorPlugin" inherits="RefCounted" version="4.0">
<brief_description>
Plugin for adding custom property editors on inspector.
</brief_description>
<description>
These plugins allow adding custom property editors to [EditorInspector].
Plugins are registered via [method EditorPlugin.add_inspector_plugin].
- When an object is edited, the [method can_handle] function is called and must return [code]true[/code] if the object type is supported.
- If supported, the function [method parse_begin] will be called, allowing to place custom controls at the beginning of the class.
- Subsequently, the [method parse_category] and [method parse_property] are called for every category and property. They offer the ability to add custom controls to the inspector too.
- Finally, [method parse_end] will be called.
+ When an object is edited, the [method _can_handle] function is called and must return [code]true[/code] if the object type is supported.
+ If supported, the function [method _parse_begin] will be called, allowing to place custom controls at the beginning of the class.
+ Subsequently, the [method _parse_category] and [method _parse_property] are called for every category and property. They offer the ability to add custom controls to the inspector too.
+ Finally, [method _parse_end] will be called.
On each of these calls, the "add" functions can be called.
</description>
<tutorials>
</tutorials>
<methods>
- <method name="add_custom_control">
- <return type="void">
+ <method name="_can_handle" qualifiers="virtual">
+ <return type="bool">
</return>
- <argument index="0" name="control" type="Control">
+ <argument index="0" name="object" type="Object">
</argument>
<description>
- Adds a custom control, not necessarily a property editor.
+ Returns [code]true[/code] if this object can be handled by this plugin.
</description>
</method>
- <method name="add_property_editor">
+ <method name="_parse_begin" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="property" type="String">
- </argument>
- <argument index="1" name="editor" type="Control">
- </argument>
<description>
- Adds a property editor, this must inherit [EditorProperty].
+ Called to allow adding controls at the beginning of the list.
</description>
</method>
- <method name="add_property_editor_for_multiple_properties">
+ <method name="_parse_category" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="label" type="String">
- </argument>
- <argument index="1" name="properties" type="PackedStringArray">
- </argument>
- <argument index="2" name="editor" type="Control">
+ <argument index="0" name="category" type="String">
</argument>
<description>
- Adds an editor that allows modifying multiple properties, this must inherit [EditorProperty].
+ Called to allow adding controls at the beginning of the category.
</description>
</method>
- <method name="can_handle" qualifiers="virtual">
- <return type="bool">
+ <method name="_parse_end" qualifiers="virtual">
+ <return type="void">
</return>
- <argument index="0" name="object" type="Object">
- </argument>
<description>
- Returns [code]true[/code] if this object can be handled by this plugin.
+ Called to allow adding controls at the end of the list.
</description>
</method>
- <method name="parse_begin" qualifiers="virtual">
- <return type="void">
+ <method name="_parse_property" qualifiers="virtual">
+ <return type="bool">
</return>
- <argument index="0" name="object" type="Object">
+ <argument index="0" name="type" type="int">
+ </argument>
+ <argument index="1" name="path" type="String">
+ </argument>
+ <argument index="2" name="hint" type="int">
+ </argument>
+ <argument index="3" name="hint_text" type="String">
+ </argument>
+ <argument index="4" name="usage" type="int">
</argument>
<description>
- Called to allow adding controls at the beginning of the list.
+ Called to allow adding property specific editors to the inspector. Usually these inherit [EditorProperty]. Returning [code]true[/code] removes the built-in editor for this property, otherwise allows to insert a custom editor before the built-in one.
</description>
</method>
- <method name="parse_category" qualifiers="virtual">
+ <method name="add_custom_control">
<return type="void">
</return>
- <argument index="0" name="object" type="Object">
- </argument>
- <argument index="1" name="category" type="String">
+ <argument index="0" name="control" type="Control">
</argument>
<description>
- Called to allow adding controls at the beginning of the category.
+ Adds a custom control, not necessarily a property editor.
</description>
</method>
- <method name="parse_end" qualifiers="virtual">
+ <method name="add_property_editor">
<return type="void">
</return>
+ <argument index="0" name="property" type="String">
+ </argument>
+ <argument index="1" name="editor" type="Control">
+ </argument>
<description>
- Called to allow adding controls at the end of the list.
+ Adds a property editor, this must inherit [EditorProperty].
</description>
</method>
- <method name="parse_property" qualifiers="virtual">
- <return type="bool">
+ <method name="add_property_editor_for_multiple_properties">
+ <return type="void">
</return>
- <argument index="0" name="object" type="Object">
- </argument>
- <argument index="1" name="type" type="int">
- </argument>
- <argument index="2" name="path" type="String">
- </argument>
- <argument index="3" name="hint" type="int">
+ <argument index="0" name="label" type="String">
</argument>
- <argument index="4" name="hint_text" type="String">
+ <argument index="1" name="properties" type="PackedStringArray">
</argument>
- <argument index="5" name="usage" type="int">
+ <argument index="2" name="editor" type="Control">
</argument>
<description>
- Called to allow adding property specific editors to the inspector. Usually these inherit [EditorProperty]. Returning [code]true[/code] removes the built-in editor for this property, otherwise allows to insert a custom editor before the built-in one.
+ Adds an editor that allows modifying multiple properties, this must inherit [EditorProperty].
</description>
</method>
</methods>
diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml
index a5328ce382..3f324bf1a0 100644
--- a/doc/classes/EditorInterface.xml
+++ b/doc/classes/EditorInterface.xml
@@ -57,6 +57,12 @@
[b]Note:[/b] This returns the main editor control containing the whole editor, not the 2D or 3D viewports specifically.
</description>
</method>
+ <method name="get_editor_paths">
+ <return type="EditorPaths">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_editor_scale" qualifiers="const">
<return type="float">
</return>
diff --git a/doc/classes/EditorNode3DGizmo.xml b/doc/classes/EditorNode3DGizmo.xml
index 45541b9263..dcc6d6ef12 100644
--- a/doc/classes/EditorNode3DGizmo.xml
+++ b/doc/classes/EditorNode3DGizmo.xml
@@ -9,13 +9,76 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_commit_handle" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <argument index="1" name="restore" type="Variant">
+ </argument>
+ <argument index="2" name="cancel" type="bool" default="false">
+ </argument>
+ <description>
+ Commit a handle being edited (handles must have been previously added by [method add_handles]).
+ If the [code]cancel[/code] parameter is [code]true[/code], an option to restore the edited value to the original is provided.
+ </description>
+ </method>
+ <method name="_get_handle_name" qualifiers="virtual">
+ <return type="String">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ Gets the name of an edited handle (handles must have been previously added by [method add_handles]).
+ Handles can be named for reference to the user when editing.
+ </description>
+ </method>
+ <method name="_get_handle_value" qualifiers="virtual">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ Gets actual value of a handle. This value can be anything and used for eventually undoing the motion when calling [method _commit_handle].
+ </description>
+ </method>
+ <method name="_is_handle_highlighted" qualifiers="virtual">
+ <return type="bool">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ Returns [code]true[/code] if the handle at index [code]index[/code] is highlighted by being hovered with the mouse.
+ </description>
+ </method>
+ <method name="_redraw" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <description>
+ This function is called when the [Node3D] this gizmo refers to changes (the [method Node3D.update_gizmo] is called).
+ </description>
+ </method>
+ <method name="_set_handle" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <argument index="1" name="camera" type="Camera3D">
+ </argument>
+ <argument index="2" name="point" type="Vector2">
+ </argument>
+ <description>
+ This function is used when the user drags a gizmo handle (previously added with [method add_handles]) in screen coordinates.
+ The [Camera3D] is also provided so screen coordinates can be converted to raycasts.
+ </description>
+ </method>
<method name="add_collision_segments">
<return type="void">
</return>
<argument index="0" name="segments" type="PackedVector3Array">
</argument>
<description>
- Adds the specified [code]segments[/code] to the gizmo's collision shape for picking. Call this function during [method redraw].
+ Adds the specified [code]segments[/code] to the gizmo's collision shape for picking. Call this function during [method _redraw].
</description>
</method>
<method name="add_collision_triangles">
@@ -24,7 +87,7 @@
<argument index="0" name="triangles" type="TriangleMesh">
</argument>
<description>
- Adds collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this function during [method redraw].
+ Adds collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this function during [method _redraw].
</description>
</method>
<method name="add_handles">
@@ -40,7 +103,7 @@
</argument>
<description>
Adds a list of handles (points) which can be used to deform the object being edited.
- There are virtual functions which will be called upon editing of these handles. Call this function during [method redraw].
+ There are virtual functions which will be called upon editing of these handles. Call this function during [method _redraw].
</description>
</method>
<method name="add_lines">
@@ -55,7 +118,7 @@
<argument index="3" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
<description>
- Adds lines to the gizmo (as sets of 2 points), with a given material. The lines are used for visualizing the gizmo. Call this function during [method redraw].
+ Adds lines to the gizmo (as sets of 2 points), with a given material. The lines are used for visualizing the gizmo. Call this function during [method _redraw].
</description>
</method>
<method name="add_mesh">
@@ -70,7 +133,7 @@
<argument index="3" name="material" type="Material" default="null">
</argument>
<description>
- Adds a mesh to the gizmo with the specified [code]billboard[/code] state, [code]skeleton[/code] and [code]material[/code]. If [code]billboard[/code] is [code]true[/code], the mesh will rotate to always face the camera. Call this function during [method redraw].
+ Adds a mesh to the gizmo with the specified [code]billboard[/code] state, [code]skeleton[/code] and [code]material[/code]. If [code]billboard[/code] is [code]true[/code], the mesh will rotate to always face the camera. Call this function during [method _redraw].
</description>
</method>
<method name="add_unscaled_billboard">
@@ -83,7 +146,7 @@
<argument index="2" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
<description>
- Adds an unscaled billboard for visualization. Call this function during [method redraw].
+ Adds an unscaled billboard for visualization. Call this function during [method _redraw].
</description>
</method>
<method name="clear">
@@ -93,39 +156,6 @@
Removes everything in the gizmo including meshes, collisions and handles.
</description>
</method>
- <method name="commit_handle" qualifiers="virtual">
- <return type="void">
- </return>
- <argument index="0" name="index" type="int">
- </argument>
- <argument index="1" name="restore" type="Variant">
- </argument>
- <argument index="2" name="cancel" type="bool" default="false">
- </argument>
- <description>
- Commit a handle being edited (handles must have been previously added by [method add_handles]).
- If the [code]cancel[/code] parameter is [code]true[/code], an option to restore the edited value to the original is provided.
- </description>
- </method>
- <method name="get_handle_name" qualifiers="virtual">
- <return type="String">
- </return>
- <argument index="0" name="index" type="int">
- </argument>
- <description>
- Gets the name of an edited handle (handles must have been previously added by [method add_handles]).
- Handles can be named for reference to the user when editing.
- </description>
- </method>
- <method name="get_handle_value" qualifiers="virtual">
- <return type="Variant">
- </return>
- <argument index="0" name="index" type="int">
- </argument>
- <description>
- Gets actual value of a handle. This value can be anything and used for eventually undoing the motion when calling [method commit_handle].
- </description>
- </method>
<method name="get_plugin" qualifiers="const">
<return type="EditorNode3DGizmoPlugin">
</return>
@@ -140,36 +170,6 @@
Returns the Node3D node associated with this gizmo.
</description>
</method>
- <method name="is_handle_highlighted" qualifiers="virtual">
- <return type="bool">
- </return>
- <argument index="0" name="index" type="int">
- </argument>
- <description>
- Returns [code]true[/code] if the handle at index [code]index[/code] is highlighted by being hovered with the mouse.
- </description>
- </method>
- <method name="redraw" qualifiers="virtual">
- <return type="void">
- </return>
- <description>
- This function is called when the [Node3D] this gizmo refers to changes (the [method Node3D.update_gizmo] is called).
- </description>
- </method>
- <method name="set_handle" qualifiers="virtual">
- <return type="void">
- </return>
- <argument index="0" name="index" type="int">
- </argument>
- <argument index="1" name="camera" type="Camera3D">
- </argument>
- <argument index="2" name="point" type="Vector2">
- </argument>
- <description>
- This function is used when the user drags a gizmo handle (previously added with [method add_handles]) in screen coordinates.
- The [Camera3D] is also provided so screen coordinates can be converted to raycasts.
- </description>
- </method>
<method name="set_hidden">
<return type="void">
</return>
diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml
index 34657a1c08..5551326533 100644
--- a/doc/classes/EditorNode3DGizmoPlugin.xml
+++ b/doc/classes/EditorNode3DGizmoPlugin.xml
@@ -10,25 +10,14 @@
<link title="Spatial gizmo plugins">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/spatial_gizmos.html</link>
</tutorials>
<methods>
- <method name="add_material">
- <return type="void">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="material" type="StandardMaterial3D">
- </argument>
- <description>
- Adds a new material to the internal material list for the plugin. It can then be accessed with [method get_material]. Should not be overridden.
- </description>
- </method>
- <method name="can_be_hidden" qualifiers="virtual">
+ <method name="_can_be_hidden" qualifiers="virtual">
<return type="bool">
</return>
<description>
Override this method to define whether the gizmo can be hidden or not. Returns [code]true[/code] if not overridden.
</description>
</method>
- <method name="commit_handle" qualifiers="virtual">
+ <method name="_commit_handle" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
@@ -43,69 +32,23 @@
Override this method to commit gizmo handles. Called for this plugin's active gizmos.
</description>
</method>
- <method name="create_gizmo" qualifiers="virtual">
+ <method name="_create_gizmo" qualifiers="virtual">
<return type="EditorNode3DGizmo">
</return>
<argument index="0" name="spatial" type="Node3D">
</argument>
<description>
- Override this method to return a custom [EditorNode3DGizmo] for the spatial nodes of your choice, return [code]null[/code] for the rest of nodes. See also [method has_gizmo].
- </description>
- </method>
- <method name="create_handle_material">
- <return type="void">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="billboard" type="bool" default="false">
- </argument>
- <argument index="2" name="texture" type="Texture2D" default="null">
- </argument>
- <description>
- Creates a handle material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorNode3DGizmo.add_handles]. Should not be overridden.
- You can optionally provide a texture to use instead of the default icon.
- </description>
- </method>
- <method name="create_icon_material">
- <return type="void">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="texture" type="Texture2D">
- </argument>
- <argument index="2" name="on_top" type="bool" default="false">
- </argument>
- <argument index="3" name="color" type="Color" default="Color( 1, 1, 1, 1 )">
- </argument>
- <description>
- Creates an icon material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorNode3DGizmo.add_unscaled_billboard]. Should not be overridden.
- </description>
- </method>
- <method name="create_material">
- <return type="void">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <argument index="2" name="billboard" type="bool" default="false">
- </argument>
- <argument index="3" name="on_top" type="bool" default="false">
- </argument>
- <argument index="4" name="use_vertex_color" type="bool" default="false">
- </argument>
- <description>
- Creates an unshaded material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorNode3DGizmo.add_mesh] and [method EditorNode3DGizmo.add_lines]. Should not be overridden.
+ Override this method to return a custom [EditorNode3DGizmo] for the spatial nodes of your choice, return [code]null[/code] for the rest of nodes. See also [method _has_gizmo].
</description>
</method>
- <method name="get_gizmo_name" qualifiers="virtual">
+ <method name="_get_gizmo_name" qualifiers="virtual">
<return type="String">
</return>
<description>
Override this method to provide the name that will appear in the gizmo visibility menu.
</description>
</method>
- <method name="get_handle_name" qualifiers="virtual">
+ <method name="_get_handle_name" qualifiers="virtual">
<return type="String">
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
@@ -116,7 +59,7 @@
Override this method to provide gizmo's handle names. Called for this plugin's active gizmos.
</description>
</method>
- <method name="get_handle_value" qualifiers="virtual">
+ <method name="_get_handle_value" qualifiers="virtual">
<return type="Variant">
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
@@ -127,18 +70,7 @@
Gets actual value of a handle from gizmo. Called for this plugin's active gizmos.
</description>
</method>
- <method name="get_material">
- <return type="StandardMaterial3D">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="gizmo" type="EditorNode3DGizmo" default="null">
- </argument>
- <description>
- Gets material from the internal list of materials. If an [EditorNode3DGizmo] is provided, it will try to get the corresponding variant (selected and/or editable).
- </description>
- </method>
- <method name="get_priority" qualifiers="virtual">
+ <method name="_get_priority" qualifiers="virtual">
<return type="int">
</return>
<description>
@@ -146,7 +78,7 @@
All built-in editor gizmos return a priority of [code]-1[/code]. If not overridden, this method will return [code]0[/code], which means custom gizmos will automatically override built-in gizmos.
</description>
</method>
- <method name="has_gizmo" qualifiers="virtual">
+ <method name="_has_gizmo" qualifiers="virtual">
<return type="bool">
</return>
<argument index="0" name="spatial" type="Node3D">
@@ -155,7 +87,7 @@
Override this method to define which Node3D nodes have a gizmo from this plugin. Whenever a [Node3D] node is added to a scene this method is called, if it returns [code]true[/code] the node gets a generic [EditorNode3DGizmo] assigned and is added to this plugin's list of active gizmos.
</description>
</method>
- <method name="is_handle_highlighted" qualifiers="virtual">
+ <method name="_is_handle_highlighted" qualifiers="virtual">
<return type="bool">
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
@@ -166,14 +98,14 @@
Gets whether a handle is highlighted or not. Called for this plugin's active gizmos.
</description>
</method>
- <method name="is_selectable_when_hidden" qualifiers="virtual">
+ <method name="_is_selectable_when_hidden" qualifiers="virtual">
<return type="bool">
</return>
<description>
Override this method to define whether Node3D with this gizmo should be selectable even when the gizmo is hidden.
</description>
</method>
- <method name="redraw" qualifiers="virtual">
+ <method name="_redraw" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
@@ -182,7 +114,7 @@
Callback to redraw the provided gizmo. Called for this plugin's active gizmos.
</description>
</method>
- <method name="set_handle" qualifiers="virtual">
+ <method name="_set_handle" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
@@ -197,6 +129,74 @@
Update the value of a handle after it has been updated. Called for this plugin's active gizmos.
</description>
</method>
+ <method name="add_material">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="material" type="StandardMaterial3D">
+ </argument>
+ <description>
+ Adds a new material to the internal material list for the plugin. It can then be accessed with [method get_material]. Should not be overridden.
+ </description>
+ </method>
+ <method name="create_handle_material">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="billboard" type="bool" default="false">
+ </argument>
+ <argument index="2" name="texture" type="Texture2D" default="null">
+ </argument>
+ <description>
+ Creates a handle material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorNode3DGizmo.add_handles]. Should not be overridden.
+ You can optionally provide a texture to use instead of the default icon.
+ </description>
+ </method>
+ <method name="create_icon_material">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="texture" type="Texture2D">
+ </argument>
+ <argument index="2" name="on_top" type="bool" default="false">
+ </argument>
+ <argument index="3" name="color" type="Color" default="Color( 1, 1, 1, 1 )">
+ </argument>
+ <description>
+ Creates an icon material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorNode3DGizmo.add_unscaled_billboard]. Should not be overridden.
+ </description>
+ </method>
+ <method name="create_material">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <argument index="2" name="billboard" type="bool" default="false">
+ </argument>
+ <argument index="3" name="on_top" type="bool" default="false">
+ </argument>
+ <argument index="4" name="use_vertex_color" type="bool" default="false">
+ </argument>
+ <description>
+ Creates an unshaded material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorNode3DGizmo.add_mesh] and [method EditorNode3DGizmo.add_lines]. Should not be overridden.
+ </description>
+ </method>
+ <method name="get_material">
+ <return type="StandardMaterial3D">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="gizmo" type="EditorNode3DGizmo" default="null">
+ </argument>
+ <description>
+ Gets material from the internal list of materials. If an [EditorNode3DGizmo] is provided, it will try to get the corresponding variant (selected and/or editable).
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/EditorPaths.xml b/doc/classes/EditorPaths.xml
new file mode 100644
index 0000000000..d0d785dbb8
--- /dev/null
+++ b/doc/classes/EditorPaths.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorPaths" inherits="Object" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_cache_dir" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_config_dir" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_data_dir" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_self_contained_file" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="is_self_contained" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index f6f51df7c0..0c0439e9d3 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -10,164 +10,7 @@
<link title="Editor plugins tutorial index">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/index.html</link>
</tutorials>
<methods>
- <method name="add_autoload_singleton">
- <return type="void">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="path" type="String">
- </argument>
- <description>
- Adds a script at [code]path[/code] to the Autoload list as [code]name[/code].
- </description>
- </method>
- <method name="add_control_to_bottom_panel">
- <return type="Button">
- </return>
- <argument index="0" name="control" type="Control">
- </argument>
- <argument index="1" name="title" type="String">
- </argument>
- <description>
- Adds a control to the bottom panel (together with Output, Debug, Animation, etc). Returns a reference to the button added. It's up to you to hide/show the button when needed. When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_bottom_panel] and free it with [method Node.queue_free].
- </description>
- </method>
- <method name="add_control_to_container">
- <return type="void">
- </return>
- <argument index="0" name="container" type="int" enum="EditorPlugin.CustomControlContainer">
- </argument>
- <argument index="1" name="control" type="Control">
- </argument>
- <description>
- Adds a custom control to a container (see [enum CustomControlContainer]). There are many locations where custom controls can be added in the editor UI.
- Please remember that you have to manage the visibility of your custom controls yourself (and likely hide it after adding it).
- When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_container] and free it with [method Node.queue_free].
- </description>
- </method>
- <method name="add_control_to_dock">
- <return type="void">
- </return>
- <argument index="0" name="slot" type="int" enum="EditorPlugin.DockSlot">
- </argument>
- <argument index="1" name="control" type="Control">
- </argument>
- <description>
- Adds the control to a specific dock slot (see [enum DockSlot] for options).
- If the dock is repositioned and as long as the plugin is active, the editor will save the dock position on further sessions.
- When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_docks] and free it with [method Node.queue_free].
- </description>
- </method>
- <method name="add_custom_type">
- <return type="void">
- </return>
- <argument index="0" name="type" type="String">
- </argument>
- <argument index="1" name="base" type="String">
- </argument>
- <argument index="2" name="script" type="Script">
- </argument>
- <argument index="3" name="icon" type="Texture2D">
- </argument>
- <description>
- Adds a custom type, which will appear in the list of nodes or resources. An icon can be optionally passed.
- When given node or resource is selected, the base type will be instanced (e.g. "Node3D", "Control", "Resource"), then the script will be loaded and set to this object.
- You can use the virtual method [method handles] to check if your custom object is being edited by checking the script or using the [code]is[/code] keyword.
- During run-time, this will be a simple object with a script so this function does not need to be called then.
- </description>
- </method>
- <method name="add_debugger_plugin">
- <return type="void">
- </return>
- <argument index="0" name="script" type="Script">
- </argument>
- <description>
- Adds a [Script] as debugger plugin to the Debugger. The script must extend [EditorDebuggerPlugin].
- </description>
- </method>
- <method name="add_export_plugin">
- <return type="void">
- </return>
- <argument index="0" name="plugin" type="EditorExportPlugin">
- </argument>
- <description>
- Registers a new export plugin. Export plugins are used when the project is being exported. See [EditorExportPlugin] for more information.
- </description>
- </method>
- <method name="add_import_plugin">
- <return type="void">
- </return>
- <argument index="0" name="importer" type="EditorImportPlugin">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_inspector_plugin">
- <return type="void">
- </return>
- <argument index="0" name="plugin" type="EditorInspectorPlugin">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_scene_import_plugin">
- <return type="void">
- </return>
- <argument index="0" name="scene_importer" type="EditorSceneImporter">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_spatial_gizmo_plugin">
- <return type="void">
- </return>
- <argument index="0" name="plugin" type="EditorNode3DGizmoPlugin">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_tool_menu_item">
- <return type="void">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="callable" type="Callable">
- </argument>
- <description>
- Adds a custom menu item to [b]Project &gt; Tools[/b] named [code]name[/code]. When clicked, the provided [code]callable[/code] will be called.
- </description>
- </method>
- <method name="add_tool_submenu_item">
- <return type="void">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="submenu" type="Object">
- </argument>
- <description>
- Adds a custom submenu under [b]Project &gt; Tools &gt;[/b] [code]name[/code]. [code]submenu[/code] should be an object of class [PopupMenu]. Use [code]remove_tool_menu_item(name)[/code] on plugin clean up to remove the menu.
- </description>
- </method>
- <method name="add_translation_parser_plugin">
- <return type="void">
- </return>
- <argument index="0" name="parser" type="EditorTranslationParserPlugin">
- </argument>
- <description>
- Registers a custom translation parser plugin for extracting translatable strings from custom files.
- </description>
- </method>
- <method name="add_undo_redo_inspector_hook_callback">
- <return type="void">
- </return>
- <argument index="0" name="callable" type="Callable">
- </argument>
- <description>
- Hooks a callback into the undo/redo action creation when a property is modified in the inspector. This allows, for example, to save other properties that may be lost when a given property is modified.
- The callback should have 4 arguments: [Object] [code]undo_redo[/code], [Object] [code]modified_object[/code], [String] [code]property[/code] and [Variant] [code]new_value[/code]. They are, respectively, the [UndoRedo] object used by the inspector, the currently modified object, the name of the modified property and the new value the property is about to take.
- </description>
- </method>
- <method name="apply_changes" qualifiers="virtual">
+ <method name="_apply_changes" qualifiers="virtual">
<return type="void">
</return>
<description>
@@ -175,29 +18,29 @@
This is used, for example, in shader editors to let the plugin know that it must apply the shader code being written by the user to the object.
</description>
</method>
- <method name="build" qualifiers="virtual">
+ <method name="_build" qualifiers="virtual">
<return type="bool">
</return>
<description>
This method is called when the editor is about to run the project. The plugin can then perform required operations before the project runs.
- This method must return a boolean. If this method returns [code]false[/code], the project will not run. The run is aborted immediately, so this also prevents all other plugins' [method build] methods from running.
+ This method must return a boolean. If this method returns [code]false[/code], the project will not run. The run is aborted immediately, so this also prevents all other plugins' [method _build] methods from running.
</description>
</method>
- <method name="clear" qualifiers="virtual">
+ <method name="_clear" qualifiers="virtual">
<return type="void">
</return>
<description>
Clear all the state and reset the object being edited to zero. This ensures your plugin does not keep editing a currently existing node, or a node from the wrong scene.
</description>
</method>
- <method name="disable_plugin" qualifiers="virtual">
+ <method name="_disable_plugin" qualifiers="virtual">
<return type="void">
</return>
<description>
Called by the engine when the user disables the [EditorPlugin] in the Plugin tab of the project settings window.
</description>
</method>
- <method name="edit" qualifiers="virtual">
+ <method name="_edit" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="object" type="Object">
@@ -206,14 +49,14 @@
This function is used for plugins that edit specific object types (nodes or resources). It requests the editor to edit the given object.
</description>
</method>
- <method name="enable_plugin" qualifiers="virtual">
+ <method name="_enable_plugin" qualifiers="virtual">
<return type="void">
</return>
<description>
Called by the engine when the user enables the [EditorPlugin] in the Plugin tab of the project settings window.
</description>
</method>
- <method name="forward_canvas_draw_over_viewport" qualifiers="virtual">
+ <method name="_forward_canvas_draw_over_viewport" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="overlay" type="Control">
@@ -222,11 +65,11 @@
Called by the engine when the 2D editor's viewport is updated. Use the [code]overlay[/code] [Control] for drawing. You can update the viewport manually by calling [method update_overlays].
[codeblocks]
[gdscript]
- func forward_canvas_draw_over_viewport(overlay):
+ func _forward_canvas_draw_over_viewport(overlay):
# Draw a circle at cursor position.
overlay.draw_circle(overlay.get_local_mouse_position(), 64, Color.white)
- func forward_canvas_gui_input(event):
+ func _forward_canvas_gui_input(event):
if event is InputEventMouseMotion:
# Redraw viewport when cursor is moved.
update_overlays()
@@ -253,27 +96,27 @@
[/codeblocks]
</description>
</method>
- <method name="forward_canvas_force_draw_over_viewport" qualifiers="virtual">
+ <method name="_forward_canvas_force_draw_over_viewport" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="overlay" type="Control">
</argument>
<description>
- This method is the same as [method forward_canvas_draw_over_viewport], except it draws on top of everything. Useful when you need an extra layer that shows over anything else.
+ This method is the same as [method _forward_canvas_draw_over_viewport], except it draws on top of everything. Useful when you need an extra layer that shows over anything else.
You need to enable calling of this method by using [method set_force_draw_over_forwarding_enabled].
</description>
</method>
- <method name="forward_canvas_gui_input" qualifiers="virtual">
+ <method name="_forward_canvas_gui_input" qualifiers="virtual">
<return type="bool">
</return>
<argument index="0" name="event" type="InputEvent">
</argument>
<description>
- Called when there is a root node in the current edited scene, [method handles] is implemented and an [InputEvent] happens in the 2D viewport. Intercepts the [InputEvent], if [code]return true[/code] [EditorPlugin] consumes the [code]event[/code], otherwise forwards [code]event[/code] to other Editor classes. Example:
+ Called when there is a root node in the current edited scene, [method _handles] is implemented and an [InputEvent] happens in the 2D viewport. Intercepts the [InputEvent], if [code]return true[/code] [EditorPlugin] consumes the [code]event[/code], otherwise forwards [code]event[/code] to other Editor classes. Example:
[codeblocks]
[gdscript]
# Prevents the InputEvent to reach other Editor classes
- func forward_canvas_gui_input(event):
+ func _forward_canvas_gui_input(event):
return true
[/gdscript]
[csharp]
@@ -288,7 +131,7 @@
[codeblocks]
[gdscript]
# Consumes InputEventMouseMotion and forwards other InputEvent types.
- func forward_canvas_gui_input(event):
+ func _forward_canvas_gui_input(event):
return event is InputEventMouseMotion
[/gdscript]
[csharp]
@@ -301,7 +144,7 @@
[/codeblocks]
</description>
</method>
- <method name="forward_spatial_draw_over_viewport" qualifiers="virtual">
+ <method name="_forward_spatial_draw_over_viewport" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="overlay" type="Control">
@@ -310,11 +153,11 @@
Called by the engine when the 3D editor's viewport is updated. Use the [code]overlay[/code] [Control] for drawing. You can update the viewport manually by calling [method update_overlays].
[codeblocks]
[gdscript]
- func forward_spatial_draw_over_viewport(overlay):
+ func _forward_spatial_draw_over_viewport(overlay):
# Draw a circle at cursor position.
overlay.draw_circle(overlay.get_local_mouse_position(), 64)
- func forward_spatial_gui_input(camera, event):
+ func _forward_spatial_gui_input(camera, event):
if event is InputEventMouseMotion:
# Redraw viewport when cursor is moved.
update_overlays()
@@ -341,17 +184,17 @@
[/codeblocks]
</description>
</method>
- <method name="forward_spatial_force_draw_over_viewport" qualifiers="virtual">
+ <method name="_forward_spatial_force_draw_over_viewport" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="overlay" type="Control">
</argument>
<description>
- This method is the same as [method forward_spatial_draw_over_viewport], except it draws on top of everything. Useful when you need an extra layer that shows over anything else.
+ This method is the same as [method _forward_spatial_draw_over_viewport], except it draws on top of everything. Useful when you need an extra layer that shows over anything else.
You need to enable calling of this method by using [method set_force_draw_over_forwarding_enabled].
</description>
</method>
- <method name="forward_spatial_gui_input" qualifiers="virtual">
+ <method name="_forward_spatial_gui_input" qualifiers="virtual">
<return type="bool">
</return>
<argument index="0" name="camera" type="Camera3D">
@@ -359,11 +202,11 @@
<argument index="1" name="event" type="InputEvent">
</argument>
<description>
- Called when there is a root node in the current edited scene, [method handles] is implemented and an [InputEvent] happens in the 3D viewport. Intercepts the [InputEvent], if [code]return true[/code] [EditorPlugin] consumes the [code]event[/code], otherwise forwards [code]event[/code] to other Editor classes. Example:
+ Called when there is a root node in the current edited scene, [method _handles] is implemented and an [InputEvent] happens in the 3D viewport. Intercepts the [InputEvent], if [code]return true[/code] [EditorPlugin] consumes the [code]event[/code], otherwise forwards [code]event[/code] to other Editor classes. Example:
[codeblocks]
[gdscript]
# Prevents the InputEvent to reach other Editor classes.
- func forward_spatial_gui_input(camera, event):
+ func _forward_spatial_gui_input(camera, event):
return true
[/gdscript]
[csharp]
@@ -378,7 +221,7 @@
[codeblocks]
[gdscript]
# Consumes InputEventMouseMotion and forwards other InputEvent types.
- func forward_spatial_gui_input(camera, event):
+ func _forward_spatial_gui_input(camera, event):
return event is InputEventMouseMotion
[/gdscript]
[csharp]
@@ -391,21 +234,14 @@
[/codeblocks]
</description>
</method>
- <method name="get_breakpoints" qualifiers="virtual">
+ <method name="_get_breakpoints" qualifiers="virtual">
<return type="PackedStringArray">
</return>
<description>
This is for editors that edit script-based objects. You can return a list of breakpoints in the format ([code]script:line[/code]), for example: [code]res://path_to_script.gd:25[/code].
</description>
</method>
- <method name="get_editor_interface">
- <return type="EditorInterface">
- </return>
- <description>
- Returns the [EditorInterface] object that gives you control over Godot editor's window and its functionalities.
- </description>
- </method>
- <method name="get_plugin_icon" qualifiers="virtual">
+ <method name="_get_plugin_icon" qualifiers="virtual">
<return type="Texture2D">
</return>
<description>
@@ -414,7 +250,7 @@
Ideally, the plugin icon should be white with a transparent background and 16x16 pixels in size.
[codeblocks]
[gdscript]
- func get_plugin_icon():
+ func _get_plugin_icon():
# You can use a custom icon:
return preload("res://addons/my_plugin/my_plugin_icon.svg")
# Or use a built-in icon:
@@ -432,7 +268,7 @@
[/codeblocks]
</description>
</method>
- <method name="get_plugin_name" qualifiers="virtual">
+ <method name="_get_plugin_name" qualifiers="virtual">
<return type="String">
</return>
<description>
@@ -440,75 +276,285 @@
For main screen plugins, this appears at the top of the screen, to the right of the "2D", "3D", "Script", and "AssetLib" buttons.
</description>
</method>
- <method name="get_script_create_dialog">
- <return type="ScriptCreateDialog">
+ <method name="_get_state" qualifiers="virtual">
+ <return type="Dictionary">
</return>
<description>
- Gets the Editor's dialogue used for making scripts.
- [b]Note:[/b] Users can configure it before use.
+ Gets the state of your plugin editor. This is used when saving the scene (so state is kept when opening it again) and for switching tabs (so state can be restored when the tab returns).
</description>
</method>
- <method name="get_state" qualifiers="virtual">
- <return type="Dictionary">
+ <method name="_get_window_layout" qualifiers="virtual">
+ <return type="void">
</return>
+ <argument index="0" name="layout" type="ConfigFile">
+ </argument>
<description>
- Gets the state of your plugin editor. This is used when saving the scene (so state is kept when opening it again) and for switching tabs (so state can be restored when the tab returns).
+ Gets the GUI layout of the plugin. This is used to save the project's editor layout when [method queue_save_layout] is called or the editor layout was changed(For example changing the position of a dock).
</description>
</method>
- <method name="get_undo_redo">
- <return type="UndoRedo">
+ <method name="_handles" qualifiers="virtual">
+ <return type="bool">
</return>
+ <argument index="0" name="object" type="Object">
+ </argument>
<description>
- Gets the undo/redo object. Most actions in the editor can be undoable, so use this object to make sure this happens when it's worth it.
+ Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method _edit] and [method _make_visible] called when the editor requests them. If you have declared the methods [method _forward_canvas_gui_input] and [method _forward_spatial_gui_input] these will be called too.
+ </description>
+ </method>
+ <method name="_has_main_screen" qualifiers="virtual">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if this is a main screen editor plugin (it goes in the workspace selector together with [b]2D[/b], [b]3D[/b], [b]Script[/b] and [b]AssetLib[/b]).
+ </description>
+ </method>
+ <method name="_make_visible" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="visible" type="bool">
+ </argument>
+ <description>
+ This function will be called when the editor is requested to become visible. It is used for plugins that edit a specific object type.
+ Remember that you have to manage the visibility of all your editor controls manually.
+ </description>
+ </method>
+ <method name="_save_external_data" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <description>
+ This method is called after the editor saves the project or when it's closed. It asks the plugin to save edited external scenes/resources.
+ </description>
+ </method>
+ <method name="_set_state" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="state" type="Dictionary">
+ </argument>
+ <description>
+ Restore the state saved by [method _get_state].
</description>
</method>
- <method name="get_window_layout" qualifiers="virtual">
+ <method name="_set_window_layout" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="layout" type="ConfigFile">
</argument>
<description>
- Gets the GUI layout of the plugin. This is used to save the project's editor layout when [method queue_save_layout] is called or the editor layout was changed(For example changing the position of a dock).
+ Restore the plugin GUI layout saved by [method _get_window_layout].
</description>
</method>
- <method name="handles" qualifiers="virtual">
- <return type="bool">
+ <method name="add_autoload_singleton">
+ <return type="void">
</return>
- <argument index="0" name="object" type="Object">
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="path" type="String">
</argument>
<description>
- Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method edit] and [method make_visible] called when the editor requests them. If you have declared the methods [method forward_canvas_gui_input] and [method forward_spatial_gui_input] these will be called too.
+ Adds a script at [code]path[/code] to the Autoload list as [code]name[/code].
</description>
</method>
- <method name="has_main_screen" qualifiers="virtual">
- <return type="bool">
+ <method name="add_control_to_bottom_panel">
+ <return type="Button">
</return>
+ <argument index="0" name="control" type="Control">
+ </argument>
+ <argument index="1" name="title" type="String">
+ </argument>
<description>
- Returns [code]true[/code] if this is a main screen editor plugin (it goes in the workspace selector together with [b]2D[/b], [b]3D[/b], [b]Script[/b] and [b]AssetLib[/b]).
+ Adds a control to the bottom panel (together with Output, Debug, Animation, etc). Returns a reference to the button added. It's up to you to hide/show the button when needed. When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_bottom_panel] and free it with [method Node.queue_free].
</description>
</method>
- <method name="hide_bottom_panel">
+ <method name="add_control_to_container">
<return type="void">
</return>
+ <argument index="0" name="container" type="int" enum="EditorPlugin.CustomControlContainer">
+ </argument>
+ <argument index="1" name="control" type="Control">
+ </argument>
<description>
+ Adds a custom control to a container (see [enum CustomControlContainer]). There are many locations where custom controls can be added in the editor UI.
+ Please remember that you have to manage the visibility of your custom controls yourself (and likely hide it after adding it).
+ When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_container] and free it with [method Node.queue_free].
</description>
</method>
- <method name="make_bottom_panel_item_visible">
+ <method name="add_control_to_dock">
<return type="void">
</return>
- <argument index="0" name="item" type="Control">
+ <argument index="0" name="slot" type="int" enum="EditorPlugin.DockSlot">
+ </argument>
+ <argument index="1" name="control" type="Control">
</argument>
<description>
+ Adds the control to a specific dock slot (see [enum DockSlot] for options).
+ If the dock is repositioned and as long as the plugin is active, the editor will save the dock position on further sessions.
+ When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_docks] and free it with [method Node.queue_free].
</description>
</method>
- <method name="make_visible" qualifiers="virtual">
+ <method name="add_custom_type">
<return type="void">
</return>
- <argument index="0" name="visible" type="bool">
+ <argument index="0" name="type" type="String">
+ </argument>
+ <argument index="1" name="base" type="String">
+ </argument>
+ <argument index="2" name="script" type="Script">
+ </argument>
+ <argument index="3" name="icon" type="Texture2D">
+ </argument>
+ <description>
+ Adds a custom type, which will appear in the list of nodes or resources. An icon can be optionally passed.
+ When given node or resource is selected, the base type will be instanced (e.g. "Node3D", "Control", "Resource"), then the script will be loaded and set to this object.
+ You can use the virtual method [method _handles] to check if your custom object is being edited by checking the script or using the [code]is[/code] keyword.
+ During run-time, this will be a simple object with a script so this function does not need to be called then.
+ </description>
+ </method>
+ <method name="add_debugger_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="script" type="Script">
+ </argument>
+ <description>
+ Adds a [Script] as debugger plugin to the Debugger. The script must extend [EditorDebuggerPlugin].
+ </description>
+ </method>
+ <method name="add_export_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="plugin" type="EditorExportPlugin">
+ </argument>
+ <description>
+ Registers a new [EditorExportPlugin]. Export plugins are used to perform tasks when the project is being exported.
+ See [method add_inspector_plugin] for an example of how to register a plugin.
+ </description>
+ </method>
+ <method name="add_import_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="importer" type="EditorImportPlugin">
+ </argument>
+ <description>
+ Registers a new [EditorImportPlugin]. Import plugins are used to import custom and unsupported assets as a custom [Resource] type.
+ [b]Note:[/b] If you want to import custom 3D asset formats use [method add_scene_import_plugin] instead.
+ See [method add_inspector_plugin] for an example of how to register a plugin.
+ </description>
+ </method>
+ <method name="add_inspector_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="plugin" type="EditorInspectorPlugin">
+ </argument>
+ <description>
+ Registers a new [EditorInspectorPlugin]. Inspector plugins are used to extend [EditorInspector] and provide custom configuration tools for your object's properties.
+ [b]Note:[/b] Always use [method remove_inspector_plugin] to remove the registered [EditorInspectorPlugin] when your [EditorPlugin] is disabled to prevent leaks and an unexpected behavior.
+ [codeblocks]
+ [gdscript]
+ const MyInspectorPlugin = preload("res://addons/your_addon/path/to/your/script.gd")
+ var inspector_plugin = MyInspectorPlugin.new()
+
+ func _enter_tree():
+ add_inspector_plugin(inspector_plugin)
+
+ func _exit_tree():
+ remove_inspector_plugin(inspector_plugin)
+ [/gdscript]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="add_scene_import_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="scene_importer" type="EditorSceneImporter">
+ </argument>
+ <description>
+ Registers a new [EditorSceneImporter]. Scene importers are used to import custom 3D asset formats as scenes.
+ </description>
+ </method>
+ <method name="add_spatial_gizmo_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="plugin" type="EditorNode3DGizmoPlugin">
+ </argument>
+ <description>
+ Registers a new [EditorNode3DGizmoPlugin]. Gizmo plugins are used to add custom gizmos to the 3D preview viewport for a [Node3D].
+ See [method add_inspector_plugin] for an example of how to register a plugin.
+ </description>
+ </method>
+ <method name="add_tool_menu_item">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="callable" type="Callable">
+ </argument>
+ <description>
+ Adds a custom menu item to [b]Project &gt; Tools[/b] named [code]name[/code]. When clicked, the provided [code]callable[/code] will be called.
+ </description>
+ </method>
+ <method name="add_tool_submenu_item">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="submenu" type="Object">
+ </argument>
+ <description>
+ Adds a custom submenu under [b]Project &gt; Tools &gt;[/b] [code]name[/code]. [code]submenu[/code] should be an object of class [PopupMenu]. Use [code]remove_tool_menu_item(name)[/code] on plugin clean up to remove the menu.
+ </description>
+ </method>
+ <method name="add_translation_parser_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="parser" type="EditorTranslationParserPlugin">
+ </argument>
+ <description>
+ Registers a custom translation parser plugin for extracting translatable strings from custom files.
+ </description>
+ </method>
+ <method name="add_undo_redo_inspector_hook_callback">
+ <return type="void">
+ </return>
+ <argument index="0" name="callable" type="Callable">
+ </argument>
+ <description>
+ Hooks a callback into the undo/redo action creation when a property is modified in the inspector. This allows, for example, to save other properties that may be lost when a given property is modified.
+ The callback should have 4 arguments: [Object] [code]undo_redo[/code], [Object] [code]modified_object[/code], [String] [code]property[/code] and [Variant] [code]new_value[/code]. They are, respectively, the [UndoRedo] object used by the inspector, the currently modified object, the name of the modified property and the new value the property is about to take.
+ </description>
+ </method>
+ <method name="get_editor_interface">
+ <return type="EditorInterface">
+ </return>
+ <description>
+ Returns the [EditorInterface] object that gives you control over Godot editor's window and its functionalities.
+ </description>
+ </method>
+ <method name="get_script_create_dialog">
+ <return type="ScriptCreateDialog">
+ </return>
+ <description>
+ Gets the Editor's dialogue used for making scripts.
+ [b]Note:[/b] Users can configure it before use.
+ </description>
+ </method>
+ <method name="get_undo_redo">
+ <return type="UndoRedo">
+ </return>
+ <description>
+ Gets the undo/redo object. Most actions in the editor can be undoable, so use this object to make sure this happens when it's worth it.
+ </description>
+ </method>
+ <method name="hide_bottom_panel">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="make_bottom_panel_item_visible">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="Control">
</argument>
<description>
- This function will be called when the editor is requested to become visible. It is used for plugins that edit a specific object type.
- Remember that you have to manage the visibility of all your editor controls manually.
</description>
</method>
<method name="queue_save_layout">
@@ -580,6 +626,7 @@
<argument index="0" name="plugin" type="EditorExportPlugin">
</argument>
<description>
+ Removes an export plugin registered by [method add_export_plugin].
</description>
</method>
<method name="remove_import_plugin">
@@ -588,6 +635,7 @@
<argument index="0" name="importer" type="EditorImportPlugin">
</argument>
<description>
+ Removes an import plugin registered by [method add_import_plugin].
</description>
</method>
<method name="remove_inspector_plugin">
@@ -596,6 +644,7 @@
<argument index="0" name="plugin" type="EditorInspectorPlugin">
</argument>
<description>
+ Removes an inspector plugin registered by [method add_import_plugin]
</description>
</method>
<method name="remove_scene_import_plugin">
@@ -604,6 +653,7 @@
<argument index="0" name="scene_importer" type="EditorSceneImporter">
</argument>
<description>
+ Removes a scene importer registered by [method add_scene_import_plugin].
</description>
</method>
<method name="remove_spatial_gizmo_plugin">
@@ -612,6 +662,7 @@
<argument index="0" name="plugin" type="EditorNode3DGizmoPlugin">
</argument>
<description>
+ Removes a gizmo plugin registered by [method add_spatial_gizmo_plugin].
</description>
</method>
<method name="remove_tool_menu_item">
@@ -629,7 +680,7 @@
<argument index="0" name="parser" type="EditorTranslationParserPlugin">
</argument>
<description>
- Removes a registered custom translation parser plugin.
+ Removes a custom translation parser plugin registered by [method add_translation_parser_plugin].
</description>
</method>
<method name="remove_undo_redo_inspector_hook_callback">
@@ -641,50 +692,25 @@
Removes a callback previsously added by [method add_undo_redo_inspector_hook_callback].
</description>
</method>
- <method name="save_external_data" qualifiers="virtual">
- <return type="void">
- </return>
- <description>
- This method is called after the editor saves the project or when it's closed. It asks the plugin to save edited external scenes/resources.
- </description>
- </method>
<method name="set_force_draw_over_forwarding_enabled">
<return type="void">
</return>
<description>
- Enables calling of [method forward_canvas_force_draw_over_viewport] for the 2D editor and [method forward_spatial_force_draw_over_viewport] for the 3D editor when their viewports are updated. You need to call this method only once and it will work permanently for this plugin.
+ Enables calling of [method _forward_canvas_force_draw_over_viewport] for the 2D editor and [method _forward_spatial_force_draw_over_viewport] for the 3D editor when their viewports are updated. You need to call this method only once and it will work permanently for this plugin.
</description>
</method>
<method name="set_input_event_forwarding_always_enabled">
<return type="void">
</return>
<description>
- Use this method if you always want to receive inputs from 3D view screen inside [method forward_spatial_gui_input]. It might be especially usable if your plugin will want to use raycast in the scene.
- </description>
- </method>
- <method name="set_state" qualifiers="virtual">
- <return type="void">
- </return>
- <argument index="0" name="state" type="Dictionary">
- </argument>
- <description>
- Restore the state saved by [method get_state].
- </description>
- </method>
- <method name="set_window_layout" qualifiers="virtual">
- <return type="void">
- </return>
- <argument index="0" name="layout" type="ConfigFile">
- </argument>
- <description>
- Restore the plugin GUI layout saved by [method get_window_layout].
+ Use this method if you always want to receive inputs from 3D view screen inside [method _forward_spatial_gui_input]. It might be especially usable if your plugin will want to use raycast in the scene.
</description>
</method>
<method name="update_overlays" qualifiers="const">
<return type="int">
</return>
<description>
- Updates the overlays of the 2D and 3D editor viewport. Causes methods [method forward_canvas_draw_over_viewport], [method forward_canvas_force_draw_over_viewport], [method forward_spatial_draw_over_viewport] and [method forward_spatial_force_draw_over_viewport] to be called.
+ Updates the overlays of the 2D and 3D editor viewport. Causes methods [method _forward_canvas_draw_over_viewport], [method _forward_canvas_force_draw_over_viewport], [method _forward_spatial_draw_over_viewport] and [method _forward_spatial_force_draw_over_viewport] to be called.
</description>
</method>
</methods>
diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml
index f568263ff8..549d2c1628 100644
--- a/doc/classes/EditorProperty.xml
+++ b/doc/classes/EditorProperty.xml
@@ -9,6 +9,13 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_update_property" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <description>
+ When this virtual function is called, you must update your editor.
+ </description>
+ </method>
<method name="add_focusable">
<return type="void">
</return>
@@ -25,7 +32,7 @@
</argument>
<argument index="1" name="value" type="Variant">
</argument>
- <argument index="2" name="field" type="StringName" default="@&quot;&quot;">
+ <argument index="2" name="field" type="StringName" default="&amp;&quot;&quot;">
</argument>
<argument index="3" name="changing" type="bool" default="false">
</argument>
@@ -44,7 +51,7 @@
<return type="StringName">
</return>
<description>
- Gets the edited property. If your editor is for a single property (added via [method EditorInspectorPlugin.parse_property]), then this will return the property.
+ Gets the edited property. If your editor is for a single property (added via [method EditorInspectorPlugin._parse_property]), then this will return the property.
</description>
</method>
<method name="get_tooltip_text" qualifiers="const">
@@ -63,13 +70,6 @@
Adds controls with this function if you want them on the bottom (below the label).
</description>
</method>
- <method name="update_property" qualifiers="virtual">
- <return type="void">
- </return>
- <description>
- When this virtual function is called, you must update your editor.
- </description>
- </method>
</methods>
<members>
<member name="checkable" type="bool" setter="set_checkable" getter="is_checkable" default="false">
@@ -101,7 +101,7 @@
<argument index="1" name="value" type="Array">
</argument>
<description>
- Emit it if you want multiple properties modified at the same time. Do not use if added via [method EditorInspectorPlugin.parse_property].
+ Emit it if you want multiple properties modified at the same time. Do not use if added via [method EditorInspectorPlugin._parse_property].
</description>
</signal>
<signal name="object_id_selected">
diff --git a/doc/classes/EditorResourceConversionPlugin.xml b/doc/classes/EditorResourceConversionPlugin.xml
index 1976eb802c..1d7e98c99d 100644
--- a/doc/classes/EditorResourceConversionPlugin.xml
+++ b/doc/classes/EditorResourceConversionPlugin.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorResourceConversionPlugin" inherits="Reference" version="4.0">
+<class name="EditorResourceConversionPlugin" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/EditorResourcePicker.xml b/doc/classes/EditorResourcePicker.xml
new file mode 100644
index 0000000000..0029955819
--- /dev/null
+++ b/doc/classes/EditorResourcePicker.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorResourcePicker" inherits="HBoxContainer" version="4.0">
+ <brief_description>
+ Godot editor's control for selecting [Resource] type properties.
+ </brief_description>
+ <description>
+ This [Control] node is used in the editor's Inspector dock to allow editing of [Resource] type properties. It provides options for creating, loading, saving and converting resources. Can be used with [EditorInspectorPlugin] to recreate the same behavior.
+ [b]Note:[/b] This [Control] does not include any editor for the resource, as editing is controlled by the Inspector dock itself or sub-Inspectors.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="_handle_menu_selected" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ This virtual method can be implemented to handle context menu items not handled by default. See [method _set_create_options].
+ </description>
+ </method>
+ <method name="_set_create_options" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="menu_node" type="Object">
+ </argument>
+ <description>
+ This virtual method is called when updating the context menu of [EditorResourcePicker]. Implement this method to override the "New ..." items with your own options. [code]menu_node[/code] is a reference to the [PopupMenu] node.
+ [b]Note:[/b] Implement [method _handle_menu_selected] to handle these custom items.
+ </description>
+ </method>
+ <method name="get_allowed_types" qualifiers="const">
+ <return type="PackedStringArray">
+ </return>
+ <description>
+ Returns a list of all allowed types and subtypes corresponding to the [member base_type]. If the [member base_type] is empty, an empty list is returned.
+ </description>
+ </method>
+ <method name="set_toggle_pressed">
+ <return type="void">
+ </return>
+ <argument index="0" name="pressed" type="bool">
+ </argument>
+ <description>
+ Sets the toggle mode state for the main button. Works only if [member toggle_mode] is set to [code]true[/code].
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default="&quot;&quot;">
+ The base type of allowed resource types. Can be a comma-separated list of several options.
+ </member>
+ <member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true">
+ If [code]true[/code], the value can be selected and edited.
+ </member>
+ <member name="edited_resource" type="Resource" setter="set_edited_resource" getter="get_edited_resource">
+ The edited resource value.
+ </member>
+ <member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode" default="false">
+ If [code]true[/code], the main button with the resource preview works in the toggle mode. Use [method set_toggle_pressed] to manually set the state.
+ </member>
+ </members>
+ <signals>
+ <signal name="resource_changed">
+ <argument index="0" name="resource" type="Resource">
+ </argument>
+ <description>
+ Emitted when the value of the edited resource was changed.
+ </description>
+ </signal>
+ <signal name="resource_selected">
+ <argument index="0" name="resource" type="Resource">
+ </argument>
+ <description>
+ Emitted when the resource value was set and user clicked to edit it.
+ </description>
+ </signal>
+ </signals>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/EditorResourcePreview.xml b/doc/classes/EditorResourcePreview.xml
index 0c1d969518..3239a75ada 100644
--- a/doc/classes/EditorResourcePreview.xml
+++ b/doc/classes/EditorResourcePreview.xml
@@ -40,7 +40,8 @@
<argument index="3" name="userdata" type="Variant">
</argument>
<description>
- Queue a resource being edited for preview (using an instance). Once the preview is ready, your receiver.receiver_func will be called either containing the preview texture or an empty texture (if no preview was possible). Callback must have the format: (path,texture,userdata). Userdata can be anything.
+ Queue the [code]resource[/code] being edited for preview. Once the preview is ready, the [code]receiver[/code]'s [code]receiver_func[/code] will be called. The [code]receiver_func[/code] must take the following four arguments: [String] path, [Texture2D] preview, [Texture2D] thumbnail_preview, [Variant] userdata. [code]userdata[/code] can be anything, and will be returned when [code]receiver_func[/code] is called.
+ [b]Note[/b]: If it was not possible to create the preview the [code]receiver_func[/code] will still be called, but the preview will be null.
</description>
</method>
<method name="queue_resource_preview">
@@ -55,7 +56,8 @@
<argument index="3" name="userdata" type="Variant">
</argument>
<description>
- Queue a resource file for preview (using a path). Once the preview is ready, your receiver.receiver_func will be called either containing the preview texture or an empty texture (if no preview was possible). Callback must have the format: (path,texture,userdata). Userdata can be anything.
+ Queue a resource file located at [code]path[/code] for preview. Once the preview is ready, the [code]receiver[/code]'s [code]receiver_func[/code] will be called. The [code]receiver_func[/code] must take the following four arguments: [String] path, [Texture2D] preview, [Texture2D] thumbnail_preview, [Variant] userdata. [code]userdata[/code] can be anything, and will be returned when [code]receiver_func[/code] is called.
+ [b]Note[/b]: If it was not possible to create the preview the [code]receiver_func[/code] will still be called, but the preview will be null.
</description>
</method>
<method name="remove_preview_generator">
diff --git a/doc/classes/EditorResourcePreviewGenerator.xml b/doc/classes/EditorResourcePreviewGenerator.xml
index e935bf19fc..3594474e36 100644
--- a/doc/classes/EditorResourcePreviewGenerator.xml
+++ b/doc/classes/EditorResourcePreviewGenerator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorResourcePreviewGenerator" inherits="Reference" version="4.0">
+<class name="EditorResourcePreviewGenerator" inherits="RefCounted" version="4.0">
<brief_description>
Custom generator of previews.
</brief_description>
@@ -9,15 +9,15 @@
<tutorials>
</tutorials>
<methods>
- <method name="can_generate_small_preview" qualifiers="virtual">
+ <method name="_can_generate_small_preview" qualifiers="virtual">
<return type="bool">
</return>
<description>
- If this function returns [code]true[/code], the generator will call [method generate] or [method generate_from_path] for small previews as well.
+ If this function returns [code]true[/code], the generator will call [method _generate] or [method _generate_from_path] for small previews as well.
By default, it returns [code]false[/code].
</description>
</method>
- <method name="generate" qualifiers="virtual">
+ <method name="_generate" qualifiers="virtual">
<return type="Texture2D">
</return>
<argument index="0" name="from" type="Resource">
@@ -30,7 +30,7 @@
Care must be taken because this function is always called from a thread (not the main thread).
</description>
</method>
- <method name="generate_from_path" qualifiers="virtual">
+ <method name="_generate_from_path" qualifiers="virtual">
<return type="Texture2D">
</return>
<argument index="0" name="path" type="String">
@@ -38,20 +38,20 @@
<argument index="1" name="size" type="Vector2">
</argument>
<description>
- Generate a preview directly from a path with the specified size. Implementing this is optional, as default code will load and call [method generate].
+ Generate a preview directly from a path with the specified size. Implementing this is optional, as default code will load and call [method _generate].
Returning an empty texture is an OK way to fail and let another generator take care.
Care must be taken because this function is always called from a thread (not the main thread).
</description>
</method>
- <method name="generate_small_preview_automatically" qualifiers="virtual">
+ <method name="_generate_small_preview_automatically" qualifiers="virtual">
<return type="bool">
</return>
<description>
- If this function returns [code]true[/code], the generator will automatically generate the small previews from the normal preview texture generated by the methods [method generate] or [method generate_from_path].
+ If this function returns [code]true[/code], the generator will automatically generate the small previews from the normal preview texture generated by the methods [method _generate] or [method _generate_from_path].
By default, it returns [code]false[/code].
</description>
</method>
- <method name="handles" qualifiers="virtual">
+ <method name="_handles" qualifiers="virtual">
<return type="bool">
</return>
<argument index="0" name="type" type="String">
diff --git a/doc/classes/EditorSceneImporter.xml b/doc/classes/EditorSceneImporter.xml
index aa55a1653d..8df3091057 100644
--- a/doc/classes/EditorSceneImporter.xml
+++ b/doc/classes/EditorSceneImporter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorSceneImporter" inherits="Reference" version="4.0">
+<class name="EditorSceneImporter" inherits="RefCounted" version="4.0">
<brief_description>
Imports scenes from third-parties' 3D files.
</brief_description>
diff --git a/doc/classes/EditorScenePostImport.xml b/doc/classes/EditorScenePostImport.xml
index d1cdc4e43e..d2b5e84ff7 100644
--- a/doc/classes/EditorScenePostImport.xml
+++ b/doc/classes/EditorScenePostImport.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorScenePostImport" inherits="Reference" version="4.0">
+<class name="EditorScenePostImport" inherits="RefCounted" version="4.0">
<brief_description>
Post-processes scenes after import.
</brief_description>
<description>
Imported scenes can be automatically modified right after import by setting their [b]Custom Script[/b] Import property to a [code]tool[/code] script that inherits from this class.
- The [method post_import] callback receives the imported scene's root node and returns the modified version of the scene. Usage example:
+ The [method _post_import] callback receives the imported scene's root node and returns the modified version of the scene. Usage example:
[codeblocks]
[gdscript]
tool # Needed so it runs in editor.
extends EditorScenePostImport
# This sample changes all node names.
# Called right after the scene is imported and gets the root node.
- func post_import(scene):
+ func _post_import(scene):
# Change all node names to "modified_[oldnodename]"
iterate(scene)
return scene # Remember to return the imported scene
@@ -55,14 +55,7 @@
<link title="Importing 3D scenes: Custom script">https://docs.godotengine.org/en/latest/getting_started/workflow/assets/importing_scenes.html#custom-script</link>
</tutorials>
<methods>
- <method name="get_source_file" qualifiers="const">
- <return type="String">
- </return>
- <description>
- Returns the source file path which got imported (e.g. [code]res://scene.dae[/code]).
- </description>
- </method>
- <method name="post_import" qualifiers="virtual">
+ <method name="_post_import" qualifiers="virtual">
<return type="Object">
</return>
<argument index="0" name="scene" type="Object">
@@ -71,6 +64,13 @@
Called after the scene was imported. This method must return the modified version of the scene.
</description>
</method>
+ <method name="get_source_file" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns the source file path which got imported (e.g. [code]res://scene.dae[/code]).
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml
index 60ccf451b8..a91ea0eb14 100644
--- a/doc/classes/EditorScript.xml
+++ b/doc/classes/EditorScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorScript" inherits="Reference" version="4.0">
+<class name="EditorScript" inherits="RefCounted" version="4.0">
<brief_description>
Base script that can be used to add extension functions to the editor.
</brief_description>
diff --git a/doc/classes/EditorScriptPicker.xml b/doc/classes/EditorScriptPicker.xml
new file mode 100644
index 0000000000..8334676d92
--- /dev/null
+++ b/doc/classes/EditorScriptPicker.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorScriptPicker" inherits="EditorResourcePicker" version="4.0">
+ <brief_description>
+ Godot editor's control for selecting the [code]script[/code] property of a [Node].
+ </brief_description>
+ <description>
+ Similar to [EditorResourcePicker] this [Control] node is used in the editor's Inspector dock, but only to edit the [code]script[/code] property of a [Node]. Default options for creating new resources of all possible subtypes are replaced with dedicated buttons that open the "Attach Node Script" dialog. Can be used with [EditorInspectorPlugin] to recreate the same behavior.
+ [b]Note:[/b] You must set the [member script_owner] for the custom context menu items to work.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="script_owner" type="Node" setter="set_script_owner" getter="get_script_owner">
+ The owner [Node] of the script property that holds the edited resource.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 016d0128eb..e732223516 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -124,15 +124,6 @@
Returns the value of the setting specified by [code]name[/code]. This is equivalent to using [method Object.get] on the EditorSettings instance.
</description>
</method>
- <method name="get_settings_dir" qualifiers="const">
- <return type="String">
- </return>
- <description>
- Gets the global settings path for the engine. Inside this path, you can find some standard paths such as:
- [code]settings/tmp[/code] - Used for temporary storage of files
- [code]settings/templates[/code] - Where export templates are located
- </description>
- </method>
<method name="has_setting" qualifiers="const">
<return type="bool">
</return>
diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml
index 381f4fae04..935335943f 100644
--- a/doc/classes/EditorSpinSlider.xml
+++ b/doc/classes/EditorSpinSlider.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorSpinSlider" inherits="Range" version="4.0">
<brief_description>
+ Godot editor's control for editing numeric values.
</brief_description>
<description>
+ This [Control] node is used in the editor's Inspector dock to allow editing of numeric values. Can be used with [EditorInspectorPlugin] to recreate the same behavior.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/EditorSyntaxHighlighter.xml b/doc/classes/EditorSyntaxHighlighter.xml
index b80e81928f..d81b25345f 100644
--- a/doc/classes/EditorSyntaxHighlighter.xml
+++ b/doc/classes/EditorSyntaxHighlighter.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Base syntax highlighter resource all editor syntax highlighters extend from, it is used in the [ScriptEditor].
- Add a syntax highlighter to an individual script by calling [method ScriptEditorBase.add_syntax_highlighter]. To apply to all scripts on open, call [method ScriptEditor.register_syntax_highlighter]
+ Add a syntax highlighter to an individual script by calling [method ScriptEditorBase._add_syntax_highlighter]. To apply to all scripts on open, call [method ScriptEditor.register_syntax_highlighter]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/EditorTranslationParserPlugin.xml b/doc/classes/EditorTranslationParserPlugin.xml
index c97459d9dc..a9f4e90e72 100644
--- a/doc/classes/EditorTranslationParserPlugin.xml
+++ b/doc/classes/EditorTranslationParserPlugin.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorTranslationParserPlugin" inherits="Reference" version="4.0">
+<class name="EditorTranslationParserPlugin" inherits="RefCounted" version="4.0">
<brief_description>
Plugin for adding custom parsers to extract strings that are to be translated from custom files (.csv, .json etc.).
</brief_description>
<description>
- Plugins are registered via [method EditorPlugin.add_translation_parser_plugin] method. To define the parsing and string extraction logic, override the [method parse_file] method in script.
+ Plugins are registered via [method EditorPlugin.add_translation_parser_plugin] method. To define the parsing and string extraction logic, override the [method _parse_file] method in script.
Add the extracted strings to argument [code]msgids[/code] or [code]msgids_context_plural[/code] if context or plural is used.
When adding to [code]msgids_context_plural[/code], you must add the data using the format [code]["A", "B", "C"][/code], where [code]A[/code] represents the extracted string, [code]B[/code] represents the context, and [code]C[/code] represents the plural version of the extracted string. If you want to add only context but not plural, put [code]""[/code] for the plural slot. The idea is the same if you only want to add plural but not context. See the code below for concrete examples.
The extracted strings will be written into a POT file selected by user under "POT Generation" in "Localization" tab in "Project Settings" menu.
@@ -14,7 +14,7 @@
tool
extends EditorTranslationParserPlugin
- func parse_file(path, msgids, msgids_context_plural):
+ func _parse_file(path, msgids, msgids_context_plural):
var file = File.new()
file.open(path, File.READ)
var text = file.get_as_text()
@@ -23,7 +23,7 @@
msgids.append(s)
#print("Extracted string: " + s)
- func get_recognized_extensions():
+ func _get_recognized_extensions():
return ["csv"]
[/gdscript]
[csharp]
@@ -76,12 +76,12 @@
For example:
[codeblocks]
[gdscript]
- func parse_file(path, msgids, msgids_context_plural):
+ func _parse_file(path, msgids, msgids_context_plural):
var res = ResourceLoader.load(path, "Script")
var text = res.source_code
# Parsing logic.
- func get_recognized_extensions():
+ func _get_recognized_extensions():
return ["gd"]
[/gdscript]
[csharp]
@@ -102,14 +102,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="get_recognized_extensions" qualifiers="virtual">
+ <method name="_get_recognized_extensions" qualifiers="virtual">
<return type="Array">
</return>
<description>
Gets the list of file extensions to associate with this parser, e.g. [code]["csv"][/code].
</description>
</method>
- <method name="parse_file" qualifiers="virtual">
+ <method name="_parse_file" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="path" type="String">
diff --git a/doc/classes/EncodedObjectAsID.xml b/doc/classes/EncodedObjectAsID.xml
index 1e4fde453b..e3e36590a3 100644
--- a/doc/classes/EncodedObjectAsID.xml
+++ b/doc/classes/EncodedObjectAsID.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EncodedObjectAsID" inherits="Reference" version="4.0">
+<class name="EncodedObjectAsID" inherits="RefCounted" version="4.0">
<brief_description>
Holds a reference to an [Object]'s instance ID.
</brief_description>
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index 1147b52102..ab480c50ab 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -171,6 +171,7 @@
</member>
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
+ [b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics_jitter_fix] to [code]0[/code].
</member>
<member name="target_fps" type="int" setter="set_target_fps" getter="get_target_fps" default="0">
The desired frames per second. If the hardware cannot keep up, this setting may not be respected. A value of 0 means no limit.
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 6909fac2b7..878535a08d 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -206,7 +206,7 @@
The depth tolerance for screen-space reflections.
</member>
<member name="ss_reflections_enabled" type="bool" setter="set_ssr_enabled" getter="is_ssr_enabled" default="false">
- If [code]true[/code], screen-space reflections are enabled. Screen-space reflections are more accurate than reflections from [GIProbe]s or [ReflectionProbe]s, but are slower and can't reflect surfaces occluded by others.
+ If [code]true[/code], screen-space reflections are enabled. Screen-space reflections are more accurate than reflections from [VoxelGI]s or [ReflectionProbe]s, but are slower and can't reflect surfaces occluded by others.
</member>
<member name="ss_reflections_fade_in" type="float" setter="set_ssr_fade_in" getter="get_ssr_fade_in" default="0.15">
The fade-in distance for screen-space reflections. Affects the area from the reflected material to the screen-space reflection).
diff --git a/doc/classes/Expression.xml b/doc/classes/Expression.xml
index d777c6fd9d..e41de4c4ed 100644
--- a/doc/classes/Expression.xml
+++ b/doc/classes/Expression.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Expression" inherits="Reference" version="4.0">
+<class name="Expression" inherits="RefCounted" version="4.0">
<brief_description>
A class that stores an expression you can execute.
</brief_description>
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index f0b9156b89..7feaaa2040 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="File" inherits="Reference" version="4.0">
+<class name="File" inherits="RefCounted" version="4.0">
<brief_description>
Type to handle file reading and writing operations.
</brief_description>
@@ -61,7 +61,7 @@
</return>
<description>
Returns [code]true[/code] if the file cursor has read past the end of the file.
- [b]Note:[/b] This function will still return [code]false[/code] while at the end of the file and only activates when reading past it. This can be confusing but it conforms to how low-level file access works in all operating systems. There is always [method get_len] and [method get_position] to implement a custom logic.
+ [b]Note:[/b] This function will still return [code]false[/code] while at the end of the file and only activates when reading past it. This can be confusing but it conforms to how low-level file access works in all operating systems. There is always [method get_length] and [method get_position] to implement a custom logic.
</description>
</method>
<method name="file_exists" qualifiers="const">
@@ -121,10 +121,10 @@
<method name="get_buffer" qualifiers="const">
<return type="PackedByteArray">
</return>
- <argument index="0" name="len" type="int">
+ <argument index="0" name="length" type="int">
</argument>
<description>
- Returns next [code]len[/code] bytes of the file as a [PackedByteArray].
+ Returns next [code]length[/code] bytes of the file as a [PackedByteArray].
</description>
</method>
<method name="get_csv_line" qualifiers="const">
@@ -158,7 +158,7 @@
Returns the next 32 bits from the file as a floating-point number.
</description>
</method>
- <method name="get_len" qualifiers="const">
+ <method name="get_length" qualifiers="const">
<return type="int">
</return>
<description>
@@ -188,7 +188,7 @@
<argument index="0" name="file" type="String">
</argument>
<description>
- Returns the last time the [code]file[/code] was modified in unix timestamp format or returns a [String] "ERROR IN [code]file[/code]". This unix timestamp can be converted to datetime by using [method OS.get_datetime_from_unix_time].
+ Returns the last time the [code]file[/code] was modified in Unix timestamp format or returns a [String] "ERROR IN [code]file[/code]". This Unix timestamp can be converted to another format using the [Time] singleton.
</description>
</method>
<method name="get_pascal_string">
@@ -490,10 +490,10 @@
</method>
</methods>
<members>
- <member name="endian_swap" type="bool" setter="set_endian_swap" getter="get_endian_swap" default="false">
+ <member name="big_endian" type="bool" setter="set_big_endian" getter="is_big_endian" default="false">
If [code]true[/code], the file is read with big-endian [url=https://en.wikipedia.org/wiki/Endianness]endianness[/url]. If [code]false[/code], the file is read with little-endian endianness. If in doubt, leave this to [code]false[/code] as most files are written with little-endian endianness.
- [b]Note:[/b] [member endian_swap] is only about the file format, not the CPU type. The CPU endianness doesn't affect the default endianness for files written.
- [b]Note:[/b] This is always reset to [code]false[/code] whenever you open the file. Therefore, you must set [member endian_swap] [i]after[/i] opening the file, not before.
+ [b]Note:[/b] [member big_endian] is only about the file format, not the CPU type. The CPU endianness doesn't affect the default endianness for files written.
+ [b]Note:[/b] This is always reset to [code]false[/code] whenever you open the file. Therefore, you must set [member big_endian] [i]after[/i] opening the file, not before.
</member>
</members>
<constants>
diff --git a/doc/classes/FileSystemDock.xml b/doc/classes/FileSystemDock.xml
index c553f90e37..15f92e90e3 100644
--- a/doc/classes/FileSystemDock.xml
+++ b/doc/classes/FileSystemDock.xml
@@ -7,40 +7,6 @@
<tutorials>
</tutorials>
<methods>
- <method name="can_drop_data_fw" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="position" type="Vector2">
- </argument>
- <argument index="1" name="data" type="Variant">
- </argument>
- <argument index="2" name="from" type="Control">
- </argument>
- <description>
- </description>
- </method>
- <method name="drop_data_fw">
- <return type="void">
- </return>
- <argument index="0" name="position" type="Vector2">
- </argument>
- <argument index="1" name="data" type="Variant">
- </argument>
- <argument index="2" name="from" type="Control">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_drag_data_fw">
- <return type="Variant">
- </return>
- <argument index="0" name="position" type="Vector2">
- </argument>
- <argument index="1" name="from" type="Control">
- </argument>
- <description>
- </description>
- </method>
<method name="navigate_to_path">
<return type="void">
</return>
diff --git a/doc/classes/GIProbe.xml b/doc/classes/GIProbe.xml
deleted file mode 100644
index 4f56d1ad3e..0000000000
--- a/doc/classes/GIProbe.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GIProbe" inherits="VisualInstance3D" version="4.0">
- <brief_description>
- Real-time global illumination (GI) probe.
- </brief_description>
- <description>
- [GIProbe]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [GIProbe]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked.
- Having [GIProbe]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/global_illumination/gi_probes/quality].
- [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh.
- </description>
- <tutorials>
- <link title="GI probes">https://docs.godotengine.org/en/latest/tutorials/3d/gi_probes.html</link>
- <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
- </tutorials>
- <methods>
- <method name="bake">
- <return type="void">
- </return>
- <argument index="0" name="from_node" type="Node" default="null">
- </argument>
- <argument index="1" name="create_visual_debug" type="bool" default="false">
- </argument>
- <description>
- Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_BAKED] and [Light3D]s marked with either [constant Light3D.BAKE_DYNAMIC] or [constant Light3D.BAKE_STATIC]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [GIProbe]'s data and debug any issues that may be occurring.
- </description>
- </method>
- <method name="debug_bake">
- <return type="void">
- </return>
- <description>
- Calls [method bake] with [code]create_visual_debug[/code] enabled.
- </description>
- </method>
- </methods>
- <members>
- <member name="data" type="GIProbeData" setter="set_probe_data" getter="get_probe_data">
- The [GIProbeData] resource that holds the data for this [GIProbe].
- </member>
- <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3( 10, 10, 10 )">
- The size of the area covered by the [GIProbe]. If you make the extents larger without increasing the subdivisions with [member subdiv], the size of each cell will increase and result in lower detailed lighting.
- </member>
- <member name="subdiv" type="int" setter="set_subdiv" getter="get_subdiv" enum="GIProbe.Subdiv" default="1">
- Number of times to subdivide the grid that the [GIProbe] operates on. A higher number results in finer detail and thus higher visual quality, while lower numbers result in better performance.
- </member>
- </members>
- <constants>
- <constant name="SUBDIV_64" value="0" enum="Subdiv">
- Use 64 subdivisions. This is the lowest quality setting, but the fastest. Use it if you can, but especially use it on lower-end hardware.
- </constant>
- <constant name="SUBDIV_128" value="1" enum="Subdiv">
- Use 128 subdivisions. This is the default quality setting.
- </constant>
- <constant name="SUBDIV_256" value="2" enum="Subdiv">
- Use 256 subdivisions.
- </constant>
- <constant name="SUBDIV_512" value="3" enum="Subdiv">
- Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware this could cause the GPU to stall.
- </constant>
- <constant name="SUBDIV_MAX" value="4" enum="Subdiv">
- Represents the size of the [enum Subdiv] enum.
- </constant>
- </constants>
-</class>
diff --git a/doc/classes/GIProbeData.xml b/doc/classes/GIProbeData.xml
deleted file mode 100644
index 693df8f819..0000000000
--- a/doc/classes/GIProbeData.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GIProbeData" inherits="Resource" version="4.0">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
- </tutorials>
- <methods>
- <method name="allocate">
- <return type="void">
- </return>
- <argument index="0" name="to_cell_xform" type="Transform">
- </argument>
- <argument index="1" name="aabb" type="AABB">
- </argument>
- <argument index="2" name="octree_size" type="Vector3">
- </argument>
- <argument index="3" name="octree_cells" type="PackedByteArray">
- </argument>
- <argument index="4" name="data_cells" type="PackedByteArray">
- </argument>
- <argument index="5" name="distance_field" type="PackedByteArray">
- </argument>
- <argument index="6" name="level_counts" type="PackedInt32Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bounds" qualifiers="const">
- <return type="AABB">
- </return>
- <description>
- </description>
- </method>
- <method name="get_data_cells" qualifiers="const">
- <return type="PackedByteArray">
- </return>
- <description>
- </description>
- </method>
- <method name="get_level_counts" qualifiers="const">
- <return type="PackedInt32Array">
- </return>
- <description>
- </description>
- </method>
- <method name="get_octree_cells" qualifiers="const">
- <return type="PackedByteArray">
- </return>
- <description>
- </description>
- </method>
- <method name="get_octree_size" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="get_to_cell_xform" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <members>
- <member name="anisotropy_strength" type="float" setter="set_anisotropy_strength" getter="get_anisotropy_strength" default="0.5">
- </member>
- <member name="ao" type="float" setter="set_ao" getter="get_ao" default="0.0">
- </member>
- <member name="ao_size" type="float" setter="set_ao_size" getter="get_ao_size" default="0.5">
- </member>
- <member name="bias" type="float" setter="set_bias" getter="get_bias" default="1.5">
- </member>
- <member name="dynamic_range" type="float" setter="set_dynamic_range" getter="get_dynamic_range" default="4.0">
- </member>
- <member name="energy" type="float" setter="set_energy" getter="get_energy" default="1.0">
- </member>
- <member name="interior" type="bool" setter="set_interior" getter="is_interior" default="false">
- </member>
- <member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" default="0.0">
- </member>
- <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.7">
- </member>
- <member name="use_two_bounces" type="bool" setter="set_use_two_bounces" getter="is_using_two_bounces" default="false">
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml
index ebe4e3b00d..ebd6d2b92c 100644
--- a/doc/classes/GPUParticles2D.xml
+++ b/doc/classes/GPUParticles2D.xml
@@ -31,7 +31,9 @@
<member name="amount" type="int" setter="set_amount" getter="get_amount" default="8">
Number of particles emitted in one emission cycle.
</member>
- <member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="GPUParticles2D.DrawOrder" default="0">
+ <member name="collision_base_size" type="float" setter="set_collision_base_size" getter="get_collision_base_size" default="1.0">
+ </member>
+ <member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="GPUParticles2D.DrawOrder" default="1">
Particle draw order. Uses [enum DrawOrder] values.
</member>
<member name="emitting" type="bool" setter="set_emitting" getter="is_emitting" default="true">
@@ -40,7 +42,7 @@
<member name="explosiveness" type="float" setter="set_explosiveness_ratio" getter="get_explosiveness_ratio" default="0.0">
How rapidly particles in an emission cycle are emitted. If greater than [code]0[/code], there will be a gap in emissions before the next cycle begins.
</member>
- <member name="fixed_fps" type="int" setter="set_fixed_fps" getter="get_fixed_fps" default="0">
+ <member name="fixed_fps" type="int" setter="set_fixed_fps" getter="get_fixed_fps" default="30">
The particle system's frame rate is fixed to a value. For instance, changing the value to 2 will make the particles render at 2 frames per second. Note this does not slow down the simulation of the particle system itself.
</member>
<member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true">
@@ -70,6 +72,14 @@
<member name="texture" type="Texture2D" setter="set_texture" getter="get_texture">
Particle texture. If [code]null[/code], particles will be squares.
</member>
+ <member name="trail_enabled" type="bool" setter="set_trail_enabled" getter="is_trail_enabled" default="false">
+ </member>
+ <member name="trail_length_secs" type="float" setter="set_trail_length" getter="get_trail_length" default="0.3">
+ </member>
+ <member name="trail_section_subdivisions" type="int" setter="set_trail_section_subdivisions" getter="get_trail_section_subdivisions" default="4">
+ </member>
+ <member name="trail_sections" type="int" setter="set_trail_sections" getter="get_trail_sections" default="8">
+ </member>
<member name="visibility_rect" type="Rect2" setter="set_visibility_rect" getter="get_visibility_rect" default="Rect2( -100, -100, 200, 200 )">
The [Rect2] that determines the node's region which needs to be visible on screen for the particle system to be active.
Grow the rect if particles suddenly appear/disappear when the node enters/exits the screen. The [Rect2] can be grown via code or with the [b]Particles → Generate Visibility Rect[/b] editor tool.
@@ -82,5 +92,7 @@
<constant name="DRAW_ORDER_LIFETIME" value="1" enum="DrawOrder">
Particles are drawn in order of remaining lifetime.
</constant>
+ <constant name="DRAW_ORDER_REVERSE_LIFETIME" value="2" enum="DrawOrder">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml
index e5d6581ddc..47bdd9d745 100644
--- a/doc/classes/GPUParticles3D.xml
+++ b/doc/classes/GPUParticles3D.xml
@@ -22,7 +22,7 @@
<method name="emit_particle">
<return type="void">
</return>
- <argument index="0" name="xform" type="Transform">
+ <argument index="0" name="xform" type="Transform3D">
</argument>
<argument index="1" name="velocity" type="Vector3">
</argument>
@@ -126,7 +126,7 @@
</member>
<member name="sub_emitter" type="NodePath" setter="set_sub_emitter" getter="get_sub_emitter" default="NodePath(&quot;&quot;)">
</member>
- <member name="trail_enabled" type="bool" setter="set_enable_trail" getter="is_trail_enabled" default="false">
+ <member name="trail_enabled" type="bool" setter="set_trail_enabled" getter="is_trail_enabled" default="false">
</member>
<member name="trail_length_secs" type="float" setter="set_trail_length" getter="get_trail_length" default="0.3">
</member>
@@ -144,7 +144,9 @@
<constant name="DRAW_ORDER_LIFETIME" value="1" enum="DrawOrder">
Particles are drawn in order of remaining lifetime.
</constant>
- <constant name="DRAW_ORDER_VIEW_DEPTH" value="2" enum="DrawOrder">
+ <constant name="DRAW_ORDER_REVERSE_LIFETIME" value="2" enum="DrawOrder">
+ </constant>
+ <constant name="DRAW_ORDER_VIEW_DEPTH" value="3" enum="DrawOrder">
Particles are drawn in order of depth.
</constant>
<constant name="EMIT_FLAG_POSITION" value="1" enum="EmitFlags">
diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml
index b2c3bfc3ed..667ca2dacf 100644
--- a/doc/classes/GeometryInstance3D.xml
+++ b/doc/classes/GeometryInstance3D.xml
@@ -52,25 +52,21 @@
</member>
<member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias" default="1.0">
</member>
- <member name="lod_max_distance" type="float" setter="set_lod_max_distance" getter="get_lod_max_distance" default="0.0">
- The GeometryInstance3D's max LOD distance.
- [b]Note:[/b] This property currently has no effect.
+ <member name="material_override" type="Material" setter="set_material_override" getter="get_material_override">
+ The material override for the whole geometry.
+ If a material is assigned to this property, it will be used instead of any material set in any material slot of the mesh.
</member>
- <member name="lod_max_hysteresis" type="float" setter="set_lod_max_hysteresis" getter="get_lod_max_hysteresis" default="0.0">
- The GeometryInstance3D's max LOD margin.
- [b]Note:[/b] This property currently has no effect.
+ <member name="visibility_range_begin" type="float" setter="set_visibility_range_begin" getter="get_visibility_range_begin" default="0.0">
+ Starting distance from which the GeometryInstance3D will be visible, taking [member visibility_range_begin_margin] into account as well. The default value of 0 is used to disable the range check.
</member>
- <member name="lod_min_distance" type="float" setter="set_lod_min_distance" getter="get_lod_min_distance" default="0.0">
- The GeometryInstance3D's min LOD distance.
- [b]Note:[/b] This property currently has no effect.
+ <member name="visibility_range_begin_margin" type="float" setter="set_visibility_range_begin_margin" getter="get_visibility_range_begin_margin" default="0.0">
+ Margin for the [member visibility_range_begin] threshold. The GeometryInstance3D will only change its visibility state when it goes over or under the [member visibility_range_begin] threshold by this amount.
</member>
- <member name="lod_min_hysteresis" type="float" setter="set_lod_min_hysteresis" getter="get_lod_min_hysteresis" default="0.0">
- The GeometryInstance3D's min LOD margin.
- [b]Note:[/b] This property currently has no effect.
+ <member name="visibility_range_end" type="float" setter="set_visibility_range_end" getter="get_visibility_range_end" default="0.0">
+ Distance from which the GeometryInstance3D will be hidden, taking [member visibility_range_end_margin] into account as well. The default value of 0 is used to disable the range check..
</member>
- <member name="material_override" type="Material" setter="set_material_override" getter="get_material_override">
- The material override for the whole geometry.
- If a material is assigned to this property, it will be used instead of any material set in any material slot of the mesh.
+ <member name="visibility_range_end_margin" type="float" setter="set_visibility_range_end_margin" getter="get_visibility_range_end_margin" default="0.0">
+ Margin for the [member visibility_range_end] threshold. The GeometryInstance3D will only change its visibility state when it goes over or under the [member visibility_range_end] threshold by this amount.
</member>
</members>
<constants>
diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml
index aae3126c0f..82ba45f11a 100644
--- a/doc/classes/GraphNode.xml
+++ b/doc/classes/GraphNode.xml
@@ -40,7 +40,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns the color of the input connection [code]idx[/code].
+ Returns the [Color] of the input connection [code]idx[/code].
</description>
</method>
<method name="get_connection_input_count">
@@ -74,7 +74,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns the color of the output connection [code]idx[/code].
+ Returns the [Color] of the output connection [code]idx[/code].
</description>
</method>
<method name="get_connection_output_count">
@@ -117,7 +117,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns the color set to [code]idx[/code] left (input) slot.
+ Returns the left (input) [Color] of the slot [code]idx[/code].
</description>
</method>
<method name="get_slot_color_right" qualifiers="const">
@@ -126,7 +126,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns the color set to [code]idx[/code] right (output) slot.
+ Returns the right (output) [Color] of the slot [code]idx[/code].
</description>
</method>
<method name="get_slot_type_left" qualifiers="const">
@@ -135,7 +135,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns the (integer) type of left (input) [code]idx[/code] slot.
+ Returns the left (input) type of the slot [code]idx[/code].
</description>
</method>
<method name="get_slot_type_right" qualifiers="const">
@@ -144,7 +144,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns the (integer) type of right (output) [code]idx[/code] slot.
+ Returns the right (output) type of the slot [code]idx[/code].
</description>
</method>
<method name="is_slot_enabled_left" qualifiers="const">
@@ -153,7 +153,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns [code]true[/code] if left (input) slot [code]idx[/code] is enabled, [code]false[/code] otherwise.
+ Returns [code]true[/code] if left (input) side of the slot [code]idx[/code] is enabled.
</description>
</method>
<method name="is_slot_enabled_right" qualifiers="const">
@@ -162,7 +162,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns [code]true[/code] if right (output) slot [code]idx[/code] is enabled, [code]false[/code] otherwise.
+ Returns [code]true[/code] if right (output) side of the slot [code]idx[/code] is enabled.
</description>
</method>
<method name="set_opentype_feature">
@@ -204,6 +204,73 @@
[code]color_left[/code]/[code]right[/code] is the tint of the port's icon on this side.
[code]custom_left[/code]/[code]right[/code] is a custom texture for this side's port.
[b]Note:[/b] This method only sets properties of the slot. To create the slot, add a [Control]-derived child to the GraphNode.
+ Individual properties can be set using one of the [code]set_slot_*[/code] methods. You must enable at least one side of the slot to do so.
+ </description>
+ </method>
+ <method name="set_slot_color_left">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="color_left" type="Color">
+ </argument>
+ <description>
+ Sets the [Color] of the left (input) side of the slot [code]idx[/code] to [code]color_left[/code].
+ </description>
+ </method>
+ <method name="set_slot_color_right">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="color_right" type="Color">
+ </argument>
+ <description>
+ Sets the [Color] of the right (output) side of the slot [code]idx[/code] to [code]color_right[/code].
+ </description>
+ </method>
+ <method name="set_slot_enabled_left">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="enable_left" type="bool">
+ </argument>
+ <description>
+ Toggles the left (input) side of the slot [code]idx[/code]. If [code]enable_left[/code] is [code]true[/code], a port will appear on the left side and the slot will be able to be connected from this side.
+ </description>
+ </method>
+ <method name="set_slot_enabled_right">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="enable_right" type="bool">
+ </argument>
+ <description>
+ Toggles the right (output) side of the slot [code]idx[/code]. If [code]enable_right[/code] is [code]true[/code], a port will appear on the right side and the slot will be able to be connected from this side.
+ </description>
+ </method>
+ <method name="set_slot_type_left">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="type_left" type="int">
+ </argument>
+ <description>
+ Sets the left (input) type of the slot [code]idx[/code] to [code]type_left[/code].
+ </description>
+ </method>
+ <method name="set_slot_type_right">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="type_right" type="int">
+ </argument>
+ <description>
+ Sets the right (output) type of the slot [code]idx[/code] to [code]type_right[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/HMACContext.xml b/doc/classes/HMACContext.xml
index 00d528ef8f..9fa96e5ddf 100644
--- a/doc/classes/HMACContext.xml
+++ b/doc/classes/HMACContext.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HMACContext" inherits="Reference" version="4.0">
+<class name="HMACContext" inherits="RefCounted" version="4.0">
<brief_description>
Used to create an HMAC for a message using a key.
</brief_description>
diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml
index ddfcdf7724..a549994a69 100644
--- a/doc/classes/HTTPClient.xml
+++ b/doc/classes/HTTPClient.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HTTPClient" inherits="Reference" version="4.0">
+<class name="HTTPClient" inherits="RefCounted" version="4.0">
<brief_description>
Low-level hyper-text transfer protocol client.
</brief_description>
diff --git a/doc/classes/HashingContext.xml b/doc/classes/HashingContext.xml
index e020293d76..1c7b7ca937 100644
--- a/doc/classes/HashingContext.xml
+++ b/doc/classes/HashingContext.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HashingContext" inherits="Reference" version="4.0">
+<class name="HashingContext" inherits="RefCounted" version="4.0">
<brief_description>
Context to compute cryptographic hashes over multiple iterations.
</brief_description>
diff --git a/doc/classes/IP.xml b/doc/classes/IP.xml
index 44da913492..b3ce1abaeb 100644
--- a/doc/classes/IP.xml
+++ b/doc/classes/IP.xml
@@ -59,6 +59,15 @@
Returns a queued hostname's IP address, given its queue [code]id[/code]. Returns an empty string on error or if resolution hasn't happened yet (see [method get_resolve_item_status]).
</description>
</method>
+ <method name="get_resolve_item_addresses" qualifiers="const">
+ <return type="Array">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ Returns resolved addresses, or an empty array if an error happened or resolution didn't happen yet (see [method get_resolve_item_status]).
+ </description>
+ </method>
<method name="get_resolve_item_status" qualifiers="const">
<return type="int" enum="IP.ResolverStatus">
</return>
@@ -79,6 +88,17 @@
Returns a given hostname's IPv4 or IPv6 address when resolved (blocking-type method). The address type returned depends on the [enum Type] constant given as [code]ip_type[/code].
</description>
</method>
+ <method name="resolve_hostname_addresses">
+ <return type="Array">
+ </return>
+ <argument index="0" name="host" type="String">
+ </argument>
+ <argument index="1" name="ip_type" type="int" enum="IP.Type" default="3">
+ </argument>
+ <description>
+ Resolves a given hostname in a blocking way. Addresses are returned as an [Array] of IPv4 or IPv6 addresses depending on [code]ip_type[/code].
+ </description>
+ </method>
<method name="resolve_hostname_queue_item">
<return type="int">
</return>
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index d7408cd0ff..ebfd32c5fb 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -449,7 +449,10 @@
[b]Note:[/b] If you want to process the mouse's movement in this mode, you need to use [member InputEventMouseMotion.relative].
</constant>
<constant name="MOUSE_MODE_CONFINED" value="3" enum="MouseMode">
- Makes the mouse cursor visible but confines it to the game window.
+ Confines the mouse cursor to the game window, and make it visible.
+ </constant>
+ <constant name="MOUSE_MODE_CONFINED_HIDDEN" value="4" enum="MouseMode">
+ Confines the mouse cursor to the game window, and make it hidden.
</constant>
<constant name="CURSOR_ARROW" value="0" enum="CursorShape">
Arrow cursor. Standard, default pointing cursor.
diff --git a/doc/classes/InputEventAction.xml b/doc/classes/InputEventAction.xml
index ed290fc7e2..42326f344f 100644
--- a/doc/classes/InputEventAction.xml
+++ b/doc/classes/InputEventAction.xml
@@ -14,7 +14,7 @@
<methods>
</methods>
<members>
- <member name="action" type="StringName" setter="set_action" getter="get_action" default="@&quot;&quot;">
+ <member name="action" type="StringName" setter="set_action" getter="get_action" default="&amp;&quot;&quot;">
The action's name. Actions are accessed via this [String].
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false">
diff --git a/doc/classes/InputEventWithModifiers.xml b/doc/classes/InputEventWithModifiers.xml
index dd782209e5..3beea7f9a0 100644
--- a/doc/classes/InputEventWithModifiers.xml
+++ b/doc/classes/InputEventWithModifiers.xml
@@ -12,23 +12,23 @@
<methods>
</methods>
<members>
- <member name="alt" type="bool" setter="set_alt" getter="get_alt" default="false">
+ <member name="alt_pressed" type="bool" setter="set_alt_pressed" getter="is_alt_pressed" default="false">
State of the [kbd]Alt[/kbd] modifier.
</member>
- <member name="command" type="bool" setter="set_command" getter="get_command" default="false">
+ <member name="command_pressed" type="bool" setter="set_command_pressed" getter="is_command_pressed" default="false">
State of the [kbd]Cmd[/kbd] modifier.
</member>
- <member name="control" type="bool" setter="set_control" getter="get_control" default="false">
+ <member name="ctrl_pressed" type="bool" setter="set_ctrl_pressed" getter="is_ctrl_pressed" default="false">
State of the [kbd]Ctrl[/kbd] modifier.
</member>
- <member name="meta" type="bool" setter="set_metakey" getter="get_metakey" default="false">
+ <member name="meta_pressed" type="bool" setter="set_meta_pressed" getter="is_meta_pressed" default="false">
State of the [kbd]Meta[/kbd] modifier.
</member>
- <member name="shift" type="bool" setter="set_shift" getter="get_shift" default="false">
+ <member name="shift_pressed" type="bool" setter="set_shift_pressed" getter="is_shift_pressed" default="false">
State of the [kbd]Shift[/kbd] modifier.
</member>
<member name="store_command" type="bool" setter="set_store_command" getter="is_storing_command" default="true">
- If [code]true[/code], pressing [kbd]Cmd[/kbd] on macOS or [kbd]Ctrl[/kbd] on all other platforms will both be serialized as [member command]. If [code]false[/code], those same keys will be serialized as [member meta] on macOS and [member control] on all other platforms.
+ If [code]true[/code], pressing [kbd]Cmd[/kbd] on macOS or [kbd]Ctrl[/kbd] on all other platforms will both be serialized as [member command_pressed]. If [code]false[/code], those same keys will be serialized as [member meta_pressed] on macOS and [member ctrl_pressed] on all other platforms.
This aids with cross-platform compatibility when developing e.g. on Windows for macOS, or vice-versa.
</member>
</members>
diff --git a/doc/classes/JSON.xml b/doc/classes/JSON.xml
index a9fb50c262..7baff7aa39 100644
--- a/doc/classes/JSON.xml
+++ b/doc/classes/JSON.xml
@@ -27,9 +27,12 @@
</argument>
<argument index="2" name="sort_keys" type="bool" default="false">
</argument>
+ <argument index="3" name="full_precision" type="bool" default="false">
+ </argument>
<description>
Converts a [Variant] var to JSON text and returns the result. Useful for serializing data to store or send over the network.
[b]Note:[/b] The JSON specification does not define integer or float types, but only a [i]number[/i] type. Therefore, converting a Variant to JSON text will convert all numerical values to [float] types.
+ [b]Note:[/b] If [code]full_precision[/code] is true, when printing floats, the unreliable digits are printed in addition to the reliable digits to guarantee exact decoding.
Use [code]indent[/code] parameter to pretty print the output.
[b]Example output:[/b]
[codeblock]
diff --git a/doc/classes/JSONParseResult.xml b/doc/classes/JSONParseResult.xml
index bc94f74b07..7311343b68 100644
--- a/doc/classes/JSONParseResult.xml
+++ b/doc/classes/JSONParseResult.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="JSONParseResult" inherits="Reference" version="4.0">
+<class name="JSONParseResult" inherits="RefCounted" version="4.0">
<brief_description>
Data class wrapper for decoded JSON.
</brief_description>
diff --git a/doc/classes/JSONParser.xml b/doc/classes/JSONParser.xml
index 31ba295418..991629f255 100644
--- a/doc/classes/JSONParser.xml
+++ b/doc/classes/JSONParser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="JSONParser" inherits="Reference" version="4.0">
+<class name="JSONParser" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/JavaClass.xml b/doc/classes/JavaClass.xml
index 69b7a9b718..0b6a44fe14 100644
--- a/doc/classes/JavaClass.xml
+++ b/doc/classes/JavaClass.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="JavaClass" inherits="Reference" version="4.0">
+<class name="JavaClass" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/JavaScript.xml b/doc/classes/JavaScript.xml
index c707a72ee8..c87e637ff5 100644
--- a/doc/classes/JavaScript.xml
+++ b/doc/classes/JavaScript.xml
@@ -11,6 +11,40 @@
<link title="Exporting for the Web: Calling JavaScript from script">https://docs.godotengine.org/en/latest/getting_started/workflow/export/exporting_for_web.html#calling-javascript-from-script</link>
</tutorials>
<methods>
+ <method name="create_callback">
+ <return type="JavaScriptObject">
+ </return>
+ <argument index="0" name="callable" type="Callable">
+ </argument>
+ <description>
+ Creates a reference to a [Callable] that can be used as a callback by JavaScript. The reference must be kept until the callback happens, or it won't be called at all. See [JavaScriptObject] for usage.
+ </description>
+ </method>
+ <method name="create_object" qualifiers="vararg">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="object" type="String">
+ </argument>
+ <description>
+ Creates a new JavaScript object using the [code]new[/code] constructor. The [code]object[/code] must a valid property of the JavaScript [code]window[/code]. See [JavaScriptObject] for usage.
+ </description>
+ </method>
+ <method name="download_buffer">
+ <return type="void">
+ </return>
+ <argument index="0" name="buffer" type="PackedByteArray">
+ </argument>
+ <argument index="1" name="name" type="String">
+ </argument>
+ <argument index="2" name="mime" type="String" default="&quot;application/octet-stream&quot;">
+ </argument>
+ <description>
+ Prompts the user to download a file containing the specified [code]buffer[/code]. The file will have the given [code]name[/code] and [code]mime[/code] type.
+ [b]Note:[/b] The browser may override the [url=https://en.wikipedia.org/wiki/Media_type]MIME type[/url] provided based on the file [code]name[/code]'s extension.
+ [b]Note:[/b] Browsers might block the download if [method download_buffer] is not being called from a user interaction (e.g. button click).
+ [b]Note:[/b] Browsers might ask the user for permission or block the download if multiple download requests are made in a quick succession.
+ </description>
+ </method>
<method name="eval">
<return type="Variant">
</return>
@@ -23,6 +57,15 @@
If [code]use_global_execution_context[/code] is [code]true[/code], the code will be evaluated in the global execution context. Otherwise, it is evaluated in the execution context of a function within the engine's runtime environment.
</description>
</method>
+ <method name="get_interface">
+ <return type="JavaScriptObject">
+ </return>
+ <argument index="0" name="interface" type="String">
+ </argument>
+ <description>
+ Returns an interface to a JavaScript object that can be used by scripts. The [code]interface[/code] must be a valid property of the JavaScript [code]window[/code]. The callback must accept a single [Array] argument, which will contain the JavaScript [code]arguments[/code]. See [JavaScriptObject] for usage.
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/JavaScriptObject.xml b/doc/classes/JavaScriptObject.xml
new file mode 100644
index 0000000000..087fe163b4
--- /dev/null
+++ b/doc/classes/JavaScriptObject.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="JavaScriptObject" inherits="RefCounted" version="4.0">
+ <brief_description>
+ A wrapper class for native JavaScript objects.
+ </brief_description>
+ <description>
+ JavaScriptObject is used to interact with JavaScript objects retrieved or created via [method JavaScript.get_interface], [method JavaScript.create_object], or [method JavaScript.create_callback].
+ Example:
+ [codeblock]
+ extends Node
+
+ var _my_js_callback = JavaScript.create_callback(self, "myCallback") # This reference must be kept
+ var console = JavaScript.get_interface("console")
+
+ func _init():
+ var buf = JavaScript.create_object("ArrayBuffer", 10) # new ArrayBuffer(10)
+ print(buf) # prints [JavaScriptObject:OBJECT_ID]
+ var uint8arr = JavaScript.create_object("Uint8Array", buf) # new Uint8Array(buf)
+ uint8arr[1] = 255
+ prints(uint8arr[1], uint8arr.byteLength) # prints 255 10
+ console.log(uint8arr) # prints in browser console "Uint8Array(10) [ 0, 255, 0, 0, 0, 0, 0, 0, 0, 0 ]"
+
+ # Equivalent of JavaScript: Array.from(uint8arr).forEach(myCallback)
+ JavaScript.get_interface("Array").from(uint8arr).forEach(_my_js_callback)
+
+ func myCallback(args):
+ # Will be called with the parameters passed to the "forEach" callback
+ # [0, 0, [JavaScriptObject:1173]]
+ # [255, 1, [JavaScriptObject:1173]]
+ # ...
+ # [0, 9, [JavaScriptObject:1180]]
+ print(args)
+ [/codeblock]
+ Note: Only available in the "HTML5" platform.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml
deleted file mode 100644
index fdd4db6115..0000000000
--- a/doc/classes/KinematicBody2D.xml
+++ /dev/null
@@ -1,176 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="KinematicBody2D" inherits="PhysicsBody2D" version="4.0">
- <brief_description>
- Kinematic body 2D node.
- </brief_description>
- <description>
- Kinematic bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a character or a rigid body, these are the same as a static body. However, they have two main uses:
- [b]Simulated motion:[/b] When these bodies are moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to "physics"), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
- [b]Kinematic characters:[/b] KinematicBody2D also has an API for moving objects (the [method move_and_collide] and [method move_and_slide] methods) while performing collision tests. This makes them really useful to implement characters that collide against a world, but don't require advanced physics.
- </description>
- <tutorials>
- <link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link>
- <link title="Using KinematicBody2D">https://docs.godotengine.org/en/latest/tutorials/physics/using_kinematic_body_2d.html</link>
- <link title="2D Kinematic Character Demo">https://godotengine.org/asset-library/asset/113</link>
- <link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/120</link>
- </tutorials>
- <methods>
- <method name="get_floor_normal" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- Returns the surface normal of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code].
- </description>
- </method>
- <method name="get_floor_velocity" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code].
- </description>
- </method>
- <method name="get_slide_collision">
- <return type="KinematicCollision2D">
- </return>
- <argument index="0" name="slide_idx" type="int">
- </argument>
- <description>
- Returns a [KinematicCollision2D], which contains information about a collision that occurred during the last call to [method move_and_slide] or [method move_and_slide_with_snap]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
- [b]Example usage:[/b]
- [codeblocks]
- [gdscript]
- for i in get_slide_count():
- var collision = get_slide_collision(i)
- print("Collided with: ", collision.collider.name)
- [/gdscript]
- [csharp]
- for (int i = 0; i &lt; GetSlideCount(); i++)
- {
- KinematicCollision2D collision = GetSlideCollision(i);
- GD.Print("Collided with: ", (collision.Collider as Node).Name);
- }
- [/csharp]
- [/codeblocks]
- </description>
- </method>
- <method name="get_slide_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the number of times the body collided and changed direction during the last call to [method move_and_slide] or [method move_and_slide_with_snap].
- </description>
- </method>
- <method name="is_on_ceiling" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if the body collided with the ceiling on the last call of [method move_and_slide] or [method move_and_slide_with_snap]. Otherwise, returns [code]false[/code].
- </description>
- </method>
- <method name="is_on_floor" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if the body collided with the floor on the last call of [method move_and_slide] or [method move_and_slide_with_snap]. Otherwise, returns [code]false[/code].
- </description>
- </method>
- <method name="is_on_wall" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if the body collided with a wall on the last call of [method move_and_slide] or [method move_and_slide_with_snap]. Otherwise, returns [code]false[/code].
- </description>
- </method>
- <method name="move_and_collide">
- <return type="KinematicCollision2D">
- </return>
- <argument index="0" name="rel_vec" type="Vector2">
- </argument>
- <argument index="1" name="infinite_inertia" type="bool" default="true">
- </argument>
- <argument index="2" name="exclude_raycast_shapes" type="bool" default="true">
- </argument>
- <argument index="3" name="test_only" type="bool" default="false">
- </argument>
- <description>
- Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision.
- If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given.
- </description>
- </method>
- <method name="move_and_slide">
- <return type="Vector2">
- </return>
- <argument index="0" name="linear_velocity" type="Vector2">
- </argument>
- <argument index="1" name="up_direction" type="Vector2" default="Vector2( 0, 0 )">
- </argument>
- <argument index="2" name="stop_on_slope" type="bool" default="false">
- </argument>
- <argument index="3" name="max_slides" type="int" default="4">
- </argument>
- <argument index="4" name="floor_max_angle" type="float" default="0.785398">
- </argument>
- <argument index="5" name="infinite_inertia" type="bool" default="true">
- </argument>
- <description>
- Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes.
- This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed.
- [code]linear_velocity[/code] is the velocity vector in pixels per second. Unlike in [method move_and_collide], you should [i]not[/i] multiply it by [code]delta[/code] — the physics engine handles applying the velocity.
- [code]up_direction[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games.
- If [code]stop_on_slope[/code] is [code]true[/code], body will not slide on slopes when you include gravity in [code]linear_velocity[/code] and the body is standing still.
- If the body collides, it will change direction a maximum of [code]max_slides[/code] times before it stops.
- [code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
- If [code]infinite_inertia[/code] is [code]true[/code], body will be able to push [RigidBody2D] nodes, but it won't also detect any collisions with them. If [code]false[/code], it will interact with [RigidBody2D] nodes like with [StaticBody2D].
- Returns the [code]linear_velocity[/code] vector, rotated and/or scaled if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
- </description>
- </method>
- <method name="move_and_slide_with_snap">
- <return type="Vector2">
- </return>
- <argument index="0" name="linear_velocity" type="Vector2">
- </argument>
- <argument index="1" name="snap" type="Vector2">
- </argument>
- <argument index="2" name="up_direction" type="Vector2" default="Vector2( 0, 0 )">
- </argument>
- <argument index="3" name="stop_on_slope" type="bool" default="false">
- </argument>
- <argument index="4" name="max_slides" type="int" default="4">
- </argument>
- <argument index="5" name="floor_max_angle" type="float" default="0.785398">
- </argument>
- <argument index="6" name="infinite_inertia" type="bool" default="true">
- </argument>
- <description>
- Moves the body while keeping it attached to slopes. Similar to [method move_and_slide].
- As long as the [code]snap[/code] vector is in contact with the ground, the body will remain attached to the surface. This means you must disable snap in order to jump, for example. You can do this by setting [code]snap[/code] to [code](0, 0)[/code] or by using [method move_and_slide] instead.
- </description>
- </method>
- <method name="test_move">
- <return type="bool">
- </return>
- <argument index="0" name="from" type="Transform2D">
- </argument>
- <argument index="1" name="rel_vec" type="Vector2">
- </argument>
- <argument index="2" name="infinite_inertia" type="bool" default="true">
- </argument>
- <description>
- Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur.
- </description>
- </method>
- </methods>
- <members>
- <member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.08">
- Extra margin used for collision recovery in motion functions (see [method move_and_collide], [method move_and_slide], [method move_and_slide_with_snap]).
- If the body is at least this close to another body, it will consider them to be colliding and will be pushed away before performing the actual motion.
- A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors.
- A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of kinematic bodies.
- </member>
- <member name="motion/sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
- If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method move_and_slide] or [method move_and_collide] functions.
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/KinematicBody3D.xml b/doc/classes/KinematicBody3D.xml
deleted file mode 100644
index efd3f58f88..0000000000
--- a/doc/classes/KinematicBody3D.xml
+++ /dev/null
@@ -1,188 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="KinematicBody3D" inherits="PhysicsBody3D" version="4.0">
- <brief_description>
- Kinematic body 3D node.
- </brief_description>
- <description>
- Kinematic bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a character or a rigid body, these are the same as a static body. However, they have two main uses:
- [b]Simulated motion:[/b] When these bodies are moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to "physics"), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
- [b]Kinematic characters:[/b] KinematicBody3D also has an API for moving objects (the [method move_and_collide] and [method move_and_slide] methods) while performing collision tests. This makes them really useful to implement characters that collide against a world, but don't require advanced physics.
- </description>
- <tutorials>
- <link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link>
- <link title="3D Kinematic Character Demo">https://godotengine.org/asset-library/asset/126</link>
- <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link>
- <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link>
- <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
- </tutorials>
- <methods>
- <method name="get_axis_lock" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
- </argument>
- <description>
- Returns [code]true[/code] if the specified [code]axis[/code] is locked. See also [member axis_lock_motion_x], [member axis_lock_motion_y] and [member axis_lock_motion_z].
- </description>
- </method>
- <method name="get_floor_normal" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- Returns the surface normal of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code].
- </description>
- </method>
- <method name="get_floor_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code].
- </description>
- </method>
- <method name="get_slide_collision">
- <return type="KinematicCollision3D">
- </return>
- <argument index="0" name="slide_idx" type="int">
- </argument>
- <description>
- Returns a [KinematicCollision3D], which contains information about a collision that occurred during the last call to [method move_and_slide] or [method move_and_slide_with_snap]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
- </description>
- </method>
- <method name="get_slide_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the number of times the body collided and changed direction during the last call to [method move_and_slide] or [method move_and_slide_with_snap].
- </description>
- </method>
- <method name="is_on_ceiling" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if the body collided with the ceiling on the last call of [method move_and_slide] or [method move_and_slide_with_snap]. Otherwise, returns [code]false[/code].
- </description>
- </method>
- <method name="is_on_floor" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if the body collided with the floor on the last call of [method move_and_slide] or [method move_and_slide_with_snap]. Otherwise, returns [code]false[/code].
- </description>
- </method>
- <method name="is_on_wall" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if the body collided with a wall on the last call of [method move_and_slide] or [method move_and_slide_with_snap]. Otherwise, returns [code]false[/code].
- </description>
- </method>
- <method name="move_and_collide">
- <return type="KinematicCollision3D">
- </return>
- <argument index="0" name="rel_vec" type="Vector3">
- </argument>
- <argument index="1" name="infinite_inertia" type="bool" default="true">
- </argument>
- <argument index="2" name="exclude_raycast_shapes" type="bool" default="true">
- </argument>
- <argument index="3" name="test_only" type="bool" default="false">
- </argument>
- <description>
- Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision3D], which contains information about the collision.
- If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given.
- </description>
- </method>
- <method name="move_and_slide">
- <return type="Vector3">
- </return>
- <argument index="0" name="linear_velocity" type="Vector3">
- </argument>
- <argument index="1" name="up_direction" type="Vector3" default="Vector3( 0, 0, 0 )">
- </argument>
- <argument index="2" name="stop_on_slope" type="bool" default="false">
- </argument>
- <argument index="3" name="max_slides" type="int" default="4">
- </argument>
- <argument index="4" name="floor_max_angle" type="float" default="0.785398">
- </argument>
- <argument index="5" name="infinite_inertia" type="bool" default="true">
- </argument>
- <description>
- Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody3D] or [RigidBody3D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes.
- This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed.
- [code]linear_velocity[/code] is the velocity vector (typically meters per second). Unlike in [method move_and_collide], you should [i]not[/i] multiply it by [code]delta[/code] — the physics engine handles applying the velocity.
- [code]up_direction[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector3(0, 0, 0)[/code], everything is considered a wall.
- If [code]stop_on_slope[/code] is [code]true[/code], body will not slide on slopes when you include gravity in [code]linear_velocity[/code] and the body is standing still.
- If the body collides, it will change direction a maximum of [code]max_slides[/code] times before it stops.
- [code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
- If [code]infinite_inertia[/code] is [code]true[/code], body will be able to push [RigidBody3D] nodes, but it won't also detect any collisions with them. If [code]false[/code], it will interact with [RigidBody3D] nodes like with [StaticBody3D].
- Returns the [code]linear_velocity[/code] vector, rotated and/or scaled if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
- </description>
- </method>
- <method name="move_and_slide_with_snap">
- <return type="Vector3">
- </return>
- <argument index="0" name="linear_velocity" type="Vector3">
- </argument>
- <argument index="1" name="snap" type="Vector3">
- </argument>
- <argument index="2" name="up_direction" type="Vector3" default="Vector3( 0, 0, 0 )">
- </argument>
- <argument index="3" name="stop_on_slope" type="bool" default="false">
- </argument>
- <argument index="4" name="max_slides" type="int" default="4">
- </argument>
- <argument index="5" name="floor_max_angle" type="float" default="0.785398">
- </argument>
- <argument index="6" name="infinite_inertia" type="bool" default="true">
- </argument>
- <description>
- Moves the body while keeping it attached to slopes. Similar to [method move_and_slide].
- As long as the [code]snap[/code] vector is in contact with the ground, the body will remain attached to the surface. This means you must disable snap in order to jump, for example. You can do this by setting [code]snap[/code] to [code](0, 0, 0)[/code] or by using [method move_and_slide] instead.
- </description>
- </method>
- <method name="set_axis_lock">
- <return type="void">
- </return>
- <argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
- </argument>
- <argument index="1" name="lock" type="bool">
- </argument>
- <description>
- Locks or unlocks the specified [code]axis[/code] depending on the value of [code]lock[/code]. See also [member axis_lock_motion_x], [member axis_lock_motion_y] and [member axis_lock_motion_z].
- </description>
- </method>
- <method name="test_move">
- <return type="bool">
- </return>
- <argument index="0" name="from" type="Transform">
- </argument>
- <argument index="1" name="rel_vec" type="Vector3">
- </argument>
- <argument index="2" name="infinite_inertia" type="bool" default="true">
- </argument>
- <description>
- Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur.
- </description>
- </method>
- </methods>
- <members>
- <member name="axis_lock_motion_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's X axis movement.
- </member>
- <member name="axis_lock_motion_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's Y axis movement.
- </member>
- <member name="axis_lock_motion_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's Z axis movement.
- </member>
- <member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.001">
- Extra margin used for collision recovery in motion functions (see [method move_and_collide], [method move_and_slide], [method move_and_slide_with_snap]).
- If the body is at least this close to another body, it will consider them to be colliding and will be pushed away before performing the actual motion.
- A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors.
- A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of kinematic bodies.
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/KinematicCollision2D.xml b/doc/classes/KinematicCollision2D.xml
index ec6e16e25a..5480d7d55f 100644
--- a/doc/classes/KinematicCollision2D.xml
+++ b/doc/classes/KinematicCollision2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="KinematicCollision2D" inherits="Reference" version="4.0">
+<class name="KinematicCollision2D" inherits="RefCounted" version="4.0">
<brief_description>
- Collision data for [KinematicBody2D] collisions.
+ Collision data for [method PhysicsBody2D.move_and_collide] collisions.
</brief_description>
<description>
- Contains collision data for [KinematicBody2D] collisions. When a [KinematicBody2D] is moved using [method KinematicBody2D.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a KinematicCollision2D object is returned.
+ Contains collision data for [method PhysicsBody2D.move_and_collide] collisions. When a [PhysicsBody2D] is moved using [method PhysicsBody2D.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a [KinematicCollision2D] object is returned.
This object contains information about the collision, including the colliding object, the remaining motion, and the collision position. This information can be used to calculate a collision response.
</description>
<tutorials>
diff --git a/doc/classes/KinematicCollision3D.xml b/doc/classes/KinematicCollision3D.xml
index f3248a9ca1..329efab474 100644
--- a/doc/classes/KinematicCollision3D.xml
+++ b/doc/classes/KinematicCollision3D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="KinematicCollision3D" inherits="Reference" version="4.0">
+<class name="KinematicCollision3D" inherits="RefCounted" version="4.0">
<brief_description>
- Collision data for [KinematicBody3D] collisions.
+ Collision data for [method PhysicsBody3D.move_and_collide] collisions.
</brief_description>
<description>
- Contains collision data for [KinematicBody3D] collisions. When a [KinematicBody3D] is moved using [method KinematicBody3D.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a KinematicCollision3D object is returned.
+ Contains collision data for [method PhysicsBody3D.move_and_collide] collisions. When a [PhysicsBody3D] is moved using [method PhysicsBody3D.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a [KinematicCollision3D] object is returned.
This object contains information about the collision, including the colliding object, the remaining motion, and the collision position. This information can be used to calculate a collision response.
</description>
<tutorials>
diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml
index 6bae612c9f..42b9ed8ab4 100644
--- a/doc/classes/Light3D.xml
+++ b/doc/classes/Light3D.xml
@@ -52,7 +52,7 @@
The light's strength multiplier (this is not a physical unit). For [OmniLight3D] and [SpotLight3D], changing this value will only change the light color's intensity, not the light's radius.
</member>
<member name="light_indirect_energy" type="float" setter="set_param" getter="get_param" default="1.0">
- Secondary multiplier used with indirect light (light bounces). Used with [GIProbe].
+ Secondary multiplier used with indirect light (light bounces). Used with [VoxelGI].
</member>
<member name="light_negative" type="bool" setter="set_negative" getter="is_negative" default="false">
If [code]true[/code], the light's effect is reversed, darkening areas and casting bright shadows.
diff --git a/doc/classes/LightmapGI.xml b/doc/classes/LightmapGI.xml
new file mode 100644
index 0000000000..d7722a83b0
--- /dev/null
+++ b/doc/classes/LightmapGI.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="LightmapGI" inherits="VisualInstance3D" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="bias" type="float" setter="set_bias" getter="get_bias" default="0.0005">
+ </member>
+ <member name="bounces" type="int" setter="set_bounces" getter="get_bounces" default="1">
+ </member>
+ <member name="directional" type="bool" setter="set_directional" getter="is_directional" default="false">
+ </member>
+ <member name="environment_custom_color" type="Color" setter="set_environment_custom_color" getter="get_environment_custom_color">
+ </member>
+ <member name="environment_custom_energy" type="float" setter="set_environment_custom_energy" getter="get_environment_custom_energy">
+ </member>
+ <member name="environment_custom_sky" type="Sky" setter="set_environment_custom_sky" getter="get_environment_custom_sky">
+ </member>
+ <member name="environment_mode" type="int" setter="set_environment_mode" getter="get_environment_mode" enum="LightmapGI.EnvironmentMode" default="0">
+ </member>
+ <member name="generate_probes_subdiv" type="int" setter="set_generate_probes" getter="get_generate_probes" enum="LightmapGI.GenerateProbes" default="0">
+ </member>
+ <member name="interior" type="bool" setter="set_interior" getter="is_interior" default="false">
+ </member>
+ <member name="light_data" type="LightmapGIData" setter="set_light_data" getter="get_light_data">
+ </member>
+ <member name="max_texture_size" type="int" setter="set_max_texture_size" getter="get_max_texture_size" default="16384">
+ </member>
+ <member name="quality" type="int" setter="set_bake_quality" getter="get_bake_quality" enum="LightmapGI.BakeQuality" default="1">
+ </member>
+ <member name="use_denoiser" type="bool" setter="set_use_denoiser" getter="is_using_denoiser" default="true">
+ </member>
+ </members>
+ <constants>
+ <constant name="BAKE_QUALITY_LOW" value="0" enum="BakeQuality">
+ </constant>
+ <constant name="BAKE_QUALITY_MEDIUM" value="1" enum="BakeQuality">
+ </constant>
+ <constant name="BAKE_QUALITY_HIGH" value="2" enum="BakeQuality">
+ </constant>
+ <constant name="BAKE_QUALITY_ULTRA" value="3" enum="BakeQuality">
+ </constant>
+ <constant name="GENERATE_PROBES_DISABLED" value="0" enum="GenerateProbes">
+ </constant>
+ <constant name="GENERATE_PROBES_SUBDIV_4" value="1" enum="GenerateProbes">
+ </constant>
+ <constant name="GENERATE_PROBES_SUBDIV_8" value="2" enum="GenerateProbes">
+ </constant>
+ <constant name="GENERATE_PROBES_SUBDIV_16" value="3" enum="GenerateProbes">
+ </constant>
+ <constant name="GENERATE_PROBES_SUBDIV_32" value="4" enum="GenerateProbes">
+ </constant>
+ <constant name="BAKE_ERROR_OK" value="0" enum="BakeError">
+ </constant>
+ <constant name="BAKE_ERROR_NO_LIGHTMAPPER" value="1" enum="BakeError">
+ </constant>
+ <constant name="BAKE_ERROR_NO_SAVE_PATH" value="2" enum="BakeError">
+ </constant>
+ <constant name="BAKE_ERROR_NO_MESHES" value="3" enum="BakeError">
+ </constant>
+ <constant name="BAKE_ERROR_MESHES_INVALID" value="4" enum="BakeError">
+ </constant>
+ <constant name="BAKE_ERROR_CANT_CREATE_IMAGE" value="5" enum="BakeError">
+ </constant>
+ <constant name="BAKE_ERROR_USER_ABORTED" value="6" enum="BakeError">
+ </constant>
+ <constant name="ENVIRONMENT_MODE_DISABLED" value="0" enum="EnvironmentMode">
+ </constant>
+ <constant name="ENVIRONMENT_MODE_SCENE" value="1" enum="EnvironmentMode">
+ </constant>
+ <constant name="ENVIRONMENT_MODE_CUSTOM_SKY" value="2" enum="EnvironmentMode">
+ </constant>
+ <constant name="ENVIRONMENT_MODE_CUSTOM_COLOR" value="3" enum="EnvironmentMode">
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/LightmapGIData.xml b/doc/classes/LightmapGIData.xml
new file mode 100644
index 0000000000..3a37c6dcb7
--- /dev/null
+++ b/doc/classes/LightmapGIData.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="LightmapGIData" inherits="Resource" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_user">
+ <return type="void">
+ </return>
+ <argument index="0" name="path" type="NodePath">
+ </argument>
+ <argument index="1" name="uv_scale" type="Rect2">
+ </argument>
+ <argument index="2" name="slice_index" type="int">
+ </argument>
+ <argument index="3" name="sub_instance" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="clear_users">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_user_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_user_path" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <argument index="0" name="user_idx" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="is_using_spherical_harmonics" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_uses_spherical_harmonics">
+ <return type="void">
+ </return>
+ <argument index="0" name="uses_spherical_harmonics" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="light_texture" type="TextureLayered" setter="set_light_texture" getter="get_light_texture">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/Lightmapper.xml b/doc/classes/Lightmapper.xml
index e80194858a..79fae42d68 100644
--- a/doc/classes/Lightmapper.xml
+++ b/doc/classes/Lightmapper.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Lightmapper" inherits="Reference" version="4.0">
+<class name="Lightmapper" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Listener3D.xml b/doc/classes/Listener3D.xml
index 998ea757ff..b2fcbe534d 100644
--- a/doc/classes/Listener3D.xml
+++ b/doc/classes/Listener3D.xml
@@ -18,10 +18,10 @@
</description>
</method>
<method name="get_listener_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<description>
- Returns the listener's global orthonormalized [Transform].
+ Returns the listener's global orthonormalized [Transform3D].
</description>
</method>
<method name="is_current" qualifiers="const">
diff --git a/doc/classes/MeshDataTool.xml b/doc/classes/MeshDataTool.xml
index db7a3187f0..da02511dc0 100644
--- a/doc/classes/MeshDataTool.xml
+++ b/doc/classes/MeshDataTool.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MeshDataTool" inherits="Reference" version="4.0">
+<class name="MeshDataTool" inherits="RefCounted" version="4.0">
<brief_description>
Helper tool to access and edit [Mesh] data.
</brief_description>
@@ -15,7 +15,7 @@
mdt.create_from_surface(mesh, 0)
for i in range(mdt.get_vertex_count()):
var vertex = mdt.get_vertex(i)
- # In this example we extend the mesh by one unit, which results in seperated faces as it is flat shaded.
+ # In this example we extend the mesh by one unit, which results in separated faces as it is flat shaded.
vertex += mdt.get_vertex_normal(i)
# Save your change.
mdt.set_vertex(i, vertex)
@@ -33,7 +33,7 @@
for (var i = 0; i &lt; mdt.GetVertexCount(); i++)
{
Vector3 vertex = mdt.GetVertex(i);
- // In this example we extend the mesh by one unit, which results in seperated faces as it is flat shaded.
+ // In this example we extend the mesh by one unit, which results in separated faces as it is flat shaded.
vertex += mdt.GetVertexNormal(i);
// Save your change.
mdt.SetVertex(i, vertex);
diff --git a/doc/classes/MeshLibrary.xml b/doc/classes/MeshLibrary.xml
index ad8bd6991d..b33bcc89e3 100644
--- a/doc/classes/MeshLibrary.xml
+++ b/doc/classes/MeshLibrary.xml
@@ -72,7 +72,7 @@
</description>
</method>
<method name="get_item_navmesh_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="id" type="int">
</argument>
@@ -96,7 +96,7 @@
</argument>
<description>
Returns an item's collision shapes.
- The array consists of each [Shape3D] followed by its [Transform].
+ The array consists of each [Shape3D] followed by its [Transform3D].
</description>
</method>
<method name="get_last_unused_item_id" qualifiers="const">
@@ -154,7 +154,7 @@
</return>
<argument index="0" name="id" type="int">
</argument>
- <argument index="1" name="navmesh" type="Transform">
+ <argument index="1" name="navmesh" type="Transform3D">
</argument>
<description>
Sets the transform to apply to the item's navigation mesh.
@@ -180,7 +180,7 @@
</argument>
<description>
Sets an item's collision shapes.
- The array should consist of [Shape3D] objects, each followed by a [Transform] that will be applied to it. For shapes that should not have a transform, use [constant Transform.IDENTITY].
+ The array should consist of [Shape3D] objects, each followed by a [Transform3D] that will be applied to it. For shapes that should not have a transform, use [constant Transform3D.IDENTITY].
</description>
</method>
</methods>
diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml
index 2adebdb306..02628f4960 100644
--- a/doc/classes/MultiMesh.xml
+++ b/doc/classes/MultiMesh.xml
@@ -40,12 +40,12 @@
</description>
</method>
<method name="get_instance_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="instance" type="int">
</argument>
<description>
- Returns the [Transform] of a specific instance.
+ Returns the [Transform3D] of a specific instance.
</description>
</method>
<method name="get_instance_transform_2d" qualifiers="const">
@@ -86,10 +86,10 @@
</return>
<argument index="0" name="instance" type="int">
</argument>
- <argument index="1" name="transform" type="Transform">
+ <argument index="1" name="transform" type="Transform3D">
</argument>
<description>
- Sets the [Transform] for a specific instance.
+ Sets the [Transform3D] for a specific instance.
</description>
</method>
<method name="set_instance_transform_2d">
diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml
index c168695d61..5de5703d95 100644
--- a/doc/classes/MultiplayerAPI.xml
+++ b/doc/classes/MultiplayerAPI.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiplayerAPI" inherits="Reference" version="4.0">
+<class name="MultiplayerAPI" inherits="RefCounted" version="4.0">
<brief_description>
High-level multiplayer API.
</brief_description>
@@ -135,16 +135,16 @@
</signals>
<constants>
<constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode">
- Used with [method Node.rpc_config] or [method Node.rset_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods.
+ Used with [method Node.rpc_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods.
</constant>
<constant name="RPC_MODE_REMOTE" value="1" enum="RPCMode">
- Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on the remote end, not locally. Analogous to the [code]remote[/code] keyword. Calls and property changes are accepted from all remote peers, no matter if they are node's master or puppets.
+ Used with [method Node.rpc_config] to set a method to be called or a property to be changed only on the remote end, not locally. Analogous to the [code]remote[/code] keyword. Calls and property changes are accepted from all remote peers, no matter if they are node's master or puppets.
</constant>
<constant name="RPC_MODE_MASTER" value="2" enum="RPCMode">
- Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on the network master for this node. Analogous to the [code]master[/code] keyword. Only accepts calls or property changes from the node's network puppets, see [method Node.set_network_master].
+ Used with [method Node.rpc_config] to set a method to be called or a property to be changed only on the network master for this node. Analogous to the [code]master[/code] keyword. Only accepts calls or property changes from the node's network puppets, see [method Node.set_network_master].
</constant>
<constant name="RPC_MODE_PUPPET" value="3" enum="RPCMode">
- Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on puppets for this node. Analogous to the [code]puppet[/code] keyword. Only accepts calls or property changes from the node's network master, see [method Node.set_network_master].
+ Used with [method Node.rpc_config] to set a method to be called or a property to be changed only on puppets for this node. Analogous to the [code]puppet[/code] keyword. Only accepts calls or property changes from the node's network master, see [method Node.set_network_master].
</constant>
<constant name="RPC_MODE_REMOTESYNC" value="4" enum="RPCMode">
Behave like [constant RPC_MODE_REMOTE] but also make the call or property change locally. Analogous to the [code]remotesync[/code] keyword.
diff --git a/doc/classes/Mutex.xml b/doc/classes/Mutex.xml
index f5f6308401..dfda614f8e 100644
--- a/doc/classes/Mutex.xml
+++ b/doc/classes/Mutex.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Mutex" inherits="Reference" version="4.0">
+<class name="Mutex" inherits="RefCounted" version="4.0">
<brief_description>
A synchronization mutex (mutual exclusion).
</brief_description>
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index b098a7fc20..ef9efcb99c 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -413,7 +413,7 @@
</return>
<argument index="0" name="region" type="RID">
</argument>
- <argument index="1" name="transform" type="Transform">
+ <argument index="1" name="transform" type="Transform3D">
</argument>
<description>
Sets the global transformation for the region.
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 523f3a0c17..1300351e47 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -649,7 +649,7 @@
<argument index="0" name="method" type="StringName">
</argument>
<description>
- Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. See also [method rset] and [method rset_config] for properties. Returns an empty [Variant].
+ Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. Returns an empty [Variant].
[b]Note:[/b] You can only safely use RPCs on clients after you received the [code]connected_to_server[/code] signal from the [SceneTree]. You also need to keep track of the connection state, either by the [SceneTree] signals like [code]server_disconnected[/code] or by checking [code]SceneTree.network_peer.get_connection_status() == CONNECTION_CONNECTED[/code].
</description>
</method>
@@ -658,33 +658,17 @@
</return>
<argument index="0" name="method" type="StringName">
</argument>
- <argument index="1" name="mode" type="int" enum="MultiplayerAPI.RPCMode">
+ <argument index="1" name="rpc_mode" type="int" enum="MultiplayerAPI.RPCMode">
</argument>
- <description>
- Changes the RPC mode for the given [code]method[/code] to the given [code]mode[/code]. See [enum MultiplayerAPI.RPCMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]master[/code], [code]puppet[/code], [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code]). By default, methods are not exposed to networking (and RPCs). See also [method rset] and [method rset_config] for properties.
- </description>
- </method>
- <method name="rpc_id" qualifiers="vararg">
- <return type="Variant">
- </return>
- <argument index="0" name="peer_id" type="int">
+ <argument index="2" name="transfer_mode" type="int" enum="NetworkedMultiplayerPeer.TransferMode" default="2">
</argument>
- <argument index="1" name="method" type="StringName">
- </argument>
- <description>
- Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
- </description>
- </method>
- <method name="rpc_unreliable" qualifiers="vararg">
- <return type="Variant">
- </return>
- <argument index="0" name="method" type="StringName">
+ <argument index="3" name="channel" type="int" default="0">
</argument>
<description>
- Sends a [method rpc] using an unreliable protocol. Returns an empty [Variant].
+ Changes the RPC mode for the given [code]method[/code] to the given [code]rpc_mode[/code], optionally specifying the [code]transfer_mode[/code] and [code]channel[/code] (on supported peers). See [enum MultiplayerAPI.RPCMode] and [enum NetworkedMultiplayerPeer.TransferMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]master[/code], [code]puppet[/code], [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code]). By default, methods are not exposed to networking (and RPCs).
</description>
</method>
- <method name="rpc_unreliable_id" qualifiers="vararg">
+ <method name="rpc_id" qualifiers="vararg">
<return type="Variant">
</return>
<argument index="0" name="peer_id" type="int">
@@ -692,66 +676,7 @@
<argument index="1" name="method" type="StringName">
</argument>
<description>
- Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] using an unreliable protocol (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
- </description>
- </method>
- <method name="rset">
- <return type="void">
- </return>
- <argument index="0" name="property" type="StringName">
- </argument>
- <argument index="1" name="value" type="Variant">
- </argument>
- <description>
- Remotely changes a property's value on other peers (and locally). Behaviour depends on the RPC configuration for the given property, see [method rset_config]. See also [method rpc] for RPCs for methods, most information applies to this method as well.
- </description>
- </method>
- <method name="rset_config">
- <return type="int">
- </return>
- <argument index="0" name="property" type="StringName">
- </argument>
- <argument index="1" name="mode" type="int" enum="MultiplayerAPI.RPCMode">
- </argument>
- <description>
- Changes the RPC mode for the given [code]property[/code] to the given [code]mode[/code]. See [enum MultiplayerAPI.RPCMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]master[/code], [code]puppet[/code], [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code]). By default, properties are not exposed to networking (and RPCs). See also [method rpc] and [method rpc_config] for methods.
- </description>
- </method>
- <method name="rset_id">
- <return type="void">
- </return>
- <argument index="0" name="peer_id" type="int">
- </argument>
- <argument index="1" name="property" type="StringName">
- </argument>
- <argument index="2" name="value" type="Variant">
- </argument>
- <description>
- Remotely changes the property's value on a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]).
- </description>
- </method>
- <method name="rset_unreliable">
- <return type="void">
- </return>
- <argument index="0" name="property" type="StringName">
- </argument>
- <argument index="1" name="value" type="Variant">
- </argument>
- <description>
- Remotely changes the property's value on other peers (and locally) using an unreliable protocol.
- </description>
- </method>
- <method name="rset_unreliable_id">
- <return type="void">
- </return>
- <argument index="0" name="peer_id" type="int">
- </argument>
- <argument index="1" name="property" type="StringName">
- </argument>
- <argument index="2" name="value" type="Variant">
- </argument>
- <description>
- Remotely changes property's value on a specific peer identified by [code]peer_id[/code] using an unreliable protocol (see [method NetworkedMultiplayerPeer.set_target_peer]).
+ Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
</description>
</method>
<method name="set_display_folded">
@@ -969,6 +894,12 @@
<constant name="NOTIFICATION_POST_ENTER_TREE" value="27">
Notification received when the node is ready, just before [constant NOTIFICATION_READY] is received. Unlike the latter, it's sent every time the node enters tree, instead of only once.
</constant>
+ <constant name="NOTIFICATION_EDITOR_PRE_SAVE" value="9001">
+ Notification received right before the scene with the node is saved in the editor. This notification is only sent in the Godot editor and will not occur in exported projects.
+ </constant>
+ <constant name="NOTIFICATION_EDITOR_POST_SAVE" value="9002">
+ Notification received right after the scene with the node is saved in the editor. This notification is only sent in the Godot editor and will not occur in exported projects.
+ </constant>
<constant name="NOTIFICATION_WM_MOUSE_ENTER" value="1002">
Notification received from the OS when the mouse enters the game window.
Implemented on desktop and web platforms.
diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml
index eed0ec8d7e..8ca945418c 100644
--- a/doc/classes/Node2D.xml
+++ b/doc/classes/Node2D.xml
@@ -150,11 +150,15 @@
<member name="transform" type="Transform2D" setter="set_transform" getter="get_transform">
Local [Transform2D].
</member>
+ <member name="y_sort_enabled" type="bool" setter="set_y_sort_enabled" getter="is_y_sort_enabled" default="false">
+ If [code]true[/code], child nodes with the lowest Y position are drawn before those with a higher Y position. If [code]false[/code], Y-sorting is disabled. Y-sorting only affects children that inherit from [CanvasItem].
+ You can nest nodes with Y-sorting. Child Y-sorted nodes are sorted in the same space as the parent Y-sort. This feature allows you to organize a scene better or divide it into multiple ones without changing your scene tree.
+ </member>
<member name="z_as_relative" type="bool" setter="set_z_as_relative" getter="is_z_relative" default="true">
If [code]true[/code], the node's Z index is relative to its parent's Z index. If this node's Z index is 2 and its parent's effective Z index is 3, then this node's effective Z index will be 2 + 3 = 5.
</member>
<member name="z_index" type="int" setter="set_z_index" getter="get_z_index" default="0">
- Z index. Controls the order in which the nodes render. A node with a higher Z index will display in front of others.
+ Z index. Controls the order in which the nodes render. A node with a higher Z index will display in front of others. Must be between [constant RenderingServer.CANVAS_ITEM_Z_MIN] and [constant RenderingServer.CANVAS_ITEM_Z_MAX] (inclusive).
</member>
</members>
<constants>
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index 5c29c0d48f..1c161803db 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -4,7 +4,7 @@
Most basic 3D game object, parent of all 3D-related nodes.
</brief_description>
<description>
- Most basic 3D game object, with a 3D [Transform] and visibility settings. All other 3D game objects inherit from Node3D. Use [Node3D] as a parent node to move, scale, rotate and show/hide children in a 3D project.
+ Most basic 3D game object, with a 3D [Transform3D] and visibility settings. All other 3D game objects inherit from Node3D. Use [Node3D] as a parent node to move, scale, rotate and show/hide children in a 3D project.
Affine operations (rotate, scale, translate) happen in parent's local coordinate system, unless the [Node3D] object is set as top-level. Affine operations in this coordinate system correspond to direct affine operations on the [Node3D]'s transform. The word local below refers to this coordinate system. The coordinate system that is attached to the [Node3D] object itself is referred to as object-local coordinate system.
[b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg2rad].
</description>
@@ -20,7 +20,7 @@
Forces the transform to update. Transform changes in physics are not instant for performance reasons. Transforms are accumulated and then set. Use this if you need an up-to-date transform when doing physics operations.
</description>
</method>
- <method name="get_parent_spatial" qualifiers="const">
+ <method name="get_parent_node_3d" qualifiers="const">
<return type="Node3D">
</return>
<description>
@@ -128,7 +128,7 @@
<return type="void">
</return>
<description>
- Resets this node's transformations (like scale, skew and taper) preserving its rotation and translation by performing Gram-Schmidt orthonormalization on this node's [Transform].
+ Resets this node's transformations (like scale, skew and taper) preserving its rotation and translation by performing Gram-Schmidt orthonormalization on this node's [Transform3D].
</description>
</method>
<method name="rotate">
@@ -202,7 +202,7 @@
<return type="void">
</return>
<description>
- Reset all transformations for this node (sets its [Transform] to the identity matrix).
+ Reset all transformations for this node (sets its [Transform3D] to the identity matrix).
</description>
</method>
<method name="set_ignore_transform_notification">
@@ -288,8 +288,11 @@
<member name="gizmo" type="Node3DGizmo" setter="set_gizmo" getter="get_gizmo">
The [Node3DGizmo] for this node. Used for example in [EditorNode3DGizmo] as custom visualization and editing handles in Editor.
</member>
- <member name="global_transform" type="Transform" setter="set_global_transform" getter="get_global_transform">
- World3D space (global) [Transform] of this node.
+ <member name="global_transform" type="Transform3D" setter="set_global_transform" getter="get_global_transform">
+ World3D space (global) [Transform3D] of this node.
+ </member>
+ <member name="position" type="Vector3" setter="set_position" getter="get_position" default="Vector3( 0, 0, 0 )">
+ Local position or translation of this node relative to the parent. This is equivalent to [code]transform.origin[/code].
</member>
<member name="rotation" type="Vector3" setter="set_rotation" getter="get_rotation">
Rotation part of the local transformation in radians, specified in terms of YXZ-Euler angles in the format (X angle, Y angle, Z angle).
@@ -304,11 +307,11 @@
<member name="top_level" type="bool" setter="set_as_top_level" getter="is_set_as_top_level" default="false">
If [code]true[/code], the node will not inherit its transformations from its parent. Node transformations are only in global space.
</member>
- <member name="transform" type="Transform" setter="set_transform" getter="get_transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
- Local space [Transform] of this node, with respect to the parent node.
+ <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ Local space [Transform3D] of this node, with respect to the parent node.
</member>
- <member name="translation" type="Vector3" setter="set_translation" getter="get_translation" default="Vector3( 0, 0, 0 )">
- Local translation of this node.
+ <member name="visibility_parent" type="NodePath" setter="set_visibility_parent" getter="get_visibility_parent" default="NodePath(&quot;&quot;)">
+ Defines the visibility range parent for this node and its subtree. The visibility parent must be a GeometryInstance3D. Any visual instance will only be visible if the visibility parent (and all of its visibility ancestors) is hidden by being closer to the camera than its own [member GeometryInstance3D.visibility_range_begin]. Nodes hidden via the [member Node3D.visible] property are essentially removed from the visibility dependency tree, so dependant instances will not take the hidden node or its ancestors into account.
</member>
<member name="visible" type="bool" setter="set_visible" getter="is_visible" default="true">
If [code]true[/code], this node is drawn. The node is only visible if all of its antecedents are visible as well (in other words, [method is_visible_in_tree] must return [code]true[/code]).
diff --git a/doc/classes/Node3DGizmo.xml b/doc/classes/Node3DGizmo.xml
index 55080614fc..c561047332 100644
--- a/doc/classes/Node3DGizmo.xml
+++ b/doc/classes/Node3DGizmo.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Node3DGizmo" inherits="Reference" version="4.0">
+<class name="Node3DGizmo" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index cb95deb9a0..bfcd5b1beb 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -176,34 +176,6 @@
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
</description>
</method>
- <method name="get_date" qualifiers="const">
- <return type="Dictionary">
- </return>
- <argument index="0" name="utc" type="bool" default="false">
- </argument>
- <description>
- Returns current date as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], [code]dst[/code] (Daylight Savings Time).
- </description>
- </method>
- <method name="get_datetime" qualifiers="const">
- <return type="Dictionary">
- </return>
- <argument index="0" name="utc" type="bool" default="false">
- </argument>
- <description>
- Returns current datetime as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], [code]dst[/code] (Daylight Savings Time), [code]hour[/code], [code]minute[/code], [code]second[/code].
- </description>
- </method>
- <method name="get_datetime_from_unix_time" qualifiers="const">
- <return type="Dictionary">
- </return>
- <argument index="0" name="unix_time_val" type="int">
- </argument>
- <description>
- Gets a dictionary of time values corresponding to the given UNIX epoch time (in seconds).
- The returned Dictionary's values will be the same as [method get_datetime], with the exception of Daylight Savings Time as it cannot be determined from the epoch.
- </description>
- </method>
<method name="get_environment" qualifiers="const">
<return type="String">
</return>
@@ -221,6 +193,13 @@
Returns the path to the current engine executable.
</description>
</method>
+ <method name="get_external_data_dir" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ On Android, returns the absolute directory path where user data can be written to external storage if available. On all other platforms, this will return the same location as [method get_user_data_dir].
+ </description>
+ </method>
<method name="get_granted_permissions" qualifiers="const">
<return type="PackedStringArray">
</return>
@@ -313,36 +292,6 @@
[b]Note:[/b] Thread IDs are not deterministic and may be reused across application restarts.
</description>
</method>
- <method name="get_ticks_msec" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the amount of time passed in milliseconds since the engine started.
- </description>
- </method>
- <method name="get_ticks_usec" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the amount of time passed in microseconds since the engine started.
- </description>
- </method>
- <method name="get_time" qualifiers="const">
- <return type="Dictionary">
- </return>
- <argument index="0" name="utc" type="bool" default="false">
- </argument>
- <description>
- Returns current time as a dictionary of keys: hour, minute, second.
- </description>
- </method>
- <method name="get_time_zone_info" qualifiers="const">
- <return type="Dictionary">
- </return>
- <description>
- Returns the current time zone as a dictionary with the keys: bias and name.
- </description>
- </method>
<method name="get_unique_id" qualifiers="const">
<return type="String">
</return>
@@ -352,26 +301,6 @@
[b]Note:[/b] Returns an empty string on HTML5 and UWP, as this method isn't implemented on those platforms yet.
</description>
</method>
- <method name="get_unix_time" qualifiers="const">
- <return type="float">
- </return>
- <description>
- Returns the current UNIX epoch timestamp in seconds.
- [b]Important:[/b] This is the system clock that the user can manully set. [b]Never use[/b] this method for precise time calculation since its results are also subject to automatic adjustments by the operating system. [b]Always use[/b] [method get_ticks_usec] or [method get_ticks_msec] for precise time calculation instead, since they are guaranteed to be monotonic (i.e. never decrease).
- </description>
- </method>
- <method name="get_unix_time_from_datetime" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="datetime" type="Dictionary">
- </argument>
- <description>
- Gets an epoch time value from a dictionary of time values.
- [code]datetime[/code] must be populated with the following keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]hour[/code], [code]minute[/code], [code]second[/code].
- If the dictionary is empty [code]0[/code] is returned.
- You can pass the output from [method get_datetime_from_unix_time] directly into this function. Daylight Savings Time ([code]dst[/code]), if present, is ignored.
- </description>
- </method>
<method name="get_user_data_dir" qualifiers="const">
<return type="String">
</return>
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 7da9c1ac38..f5dcd6bcdc 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -7,7 +7,7 @@
Every class which is not a built-in type inherits from this class.
You can construct Objects from scripting languages, using [code]Object.new()[/code] in GDScript, [code]new Object[/code] in C#, or the "Construct Object" node in VisualScript.
Objects do not manage memory. If a class inherits from Object, you will have to delete instances of it manually. To do so, call the [method free] method from your script or delete the instance from C++.
- Some classes that extend Object add memory management. This is the case of [Reference], which counts references and deletes itself automatically when no longer referenced. [Node], another fundamental type, deletes all its children when freed from memory.
+ Some classes that extend Object add memory management. This is the case of [RefCounted], which counts references and deletes itself automatically when no longer referenced. [Node], another fundamental type, deletes all its children when freed from memory.
Objects export properties, which are mainly useful for storage and editing, but not really so much in programming. Properties are exported in [method _get_property_list] and handled in [method _get] and [method _set]. However, scripting languages and C++ have simpler means to export them.
Property membership can be tested directly in GDScript using [code]in[/code]:
[codeblocks]
@@ -26,7 +26,7 @@
[/codeblocks]
The [code]in[/code] operator will evaluate to [code]true[/code] as long as the key exists, even if the value is [code]null[/code].
Objects also receive notifications. Notifications are a simple way to notify the object about different events, so they can all be handled together. See [method _notification].
- [b]Note:[/b] Unlike references to a [Reference], references to an Object stored in a variable can become invalid without warning. Therefore, it's recommended to use [Reference] for data classes instead of [Object].
+ [b]Note:[/b] Unlike references to a [RefCounted], references to an Object stored in a variable can become invalid without warning. Therefore, it's recommended to use [RefCounted] for data classes instead of [Object].
</description>
<tutorials>
<link title="When and how to avoid using nodes for everything">https://docs.godotengine.org/en/latest/getting_started/workflow/best_practices/node_alternatives.html</link>
diff --git a/doc/classes/PCKPacker.xml b/doc/classes/PCKPacker.xml
index e3c78e08f1..40e8683c93 100644
--- a/doc/classes/PCKPacker.xml
+++ b/doc/classes/PCKPacker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PCKPacker" inherits="Reference" version="4.0">
+<class name="PCKPacker" inherits="RefCounted" version="4.0">
<brief_description>
Creates packages that can be loaded into a running project.
</brief_description>
diff --git a/doc/classes/PackedDataContainerRef.xml b/doc/classes/PackedDataContainerRef.xml
index f0f59675de..bfd5a6f1c1 100644
--- a/doc/classes/PackedDataContainerRef.xml
+++ b/doc/classes/PackedDataContainerRef.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PackedDataContainerRef" inherits="Reference" version="4.0">
+<class name="PackedDataContainerRef" inherits="RefCounted" version="4.0">
<brief_description>
- Reference version of [PackedDataContainer].
+ Reference-counted version of [PackedDataContainer].
</brief_description>
<description>
</description>
diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml
index 85d41d7519..00ded39082 100644
--- a/doc/classes/PackedVector3Array.xml
+++ b/doc/classes/PackedVector3Array.xml
@@ -106,7 +106,7 @@
<method name="operator *" qualifiers="operator">
<return type="PackedVector3Array">
</return>
- <argument index="0" name="right" type="Transform">
+ <argument index="0" name="right" type="Transform3D">
</argument>
<description>
</description>
diff --git a/doc/classes/PacketPeer.xml b/doc/classes/PacketPeer.xml
index e3e2f63e14..0a758c2cd6 100644
--- a/doc/classes/PacketPeer.xml
+++ b/doc/classes/PacketPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PacketPeer" inherits="Reference" version="4.0">
+<class name="PacketPeer" inherits="RefCounted" version="4.0">
<brief_description>
Abstraction and base class for packet-based protocols.
</brief_description>
diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml
index 6d7f99a55b..3c364b621a 100644
--- a/doc/classes/ParticlesMaterial.xml
+++ b/doc/classes/ParticlesMaterial.xml
@@ -135,7 +135,7 @@
</member>
<member name="collision_bounce" type="float" setter="set_collision_bounce" getter="get_collision_bounce" default="0.0">
</member>
- <member name="collision_enabled" type="bool" setter="set_collision_enabled" getter="is_collision_enabled" default="true">
+ <member name="collision_enabled" type="bool" setter="set_collision_enabled" getter="is_collision_enabled" default="false">
</member>
<member name="collision_friction" type="float" setter="set_collision_friction" getter="get_collision_friction" default="0.0">
</member>
diff --git a/doc/classes/PhysicalBone2D.xml b/doc/classes/PhysicalBone2D.xml
new file mode 100644
index 0000000000..cea75bad52
--- /dev/null
+++ b/doc/classes/PhysicalBone2D.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="PhysicalBone2D" inherits="RigidBody2D" version="4.0">
+ <brief_description>
+ A 2D node that can be used for physically aware bones in 2D.
+ </brief_description>
+ <description>
+ The [code]PhysicalBone2D[/code] node is a [RigidBody2D]-based node that can be used to make [Bone2D] nodes in a [Skeleton2D] react to physics. This node is very similar to the [PhysicalBone3D] node, just for 2D instead of 3D.
+ [b]Note:[/b] To have the Bone2D nodes visually follow the [code]PhysicalBone2D[/code] node, use a [SkeletonModification2DPhysicalBones] modification on the [Skeleton2D] node with the [Bone2D] nodes.
+ [b]Note:[/b] The PhysicalBone2D node does not automatically create a [Joint2D] node to keep [code]PhysicalBone2D[/code] nodes together. You will need to create these manually. For most cases, you want to use a [PinJoint2D] node. The [code]PhysicalBone2D[/code] node can automatically configure the [Joint2D] node once it's been created as a child node.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_joint" qualifiers="const">
+ <return type="Joint2D">
+ </return>
+ <description>
+ Returns the first [Joint2D] child node, if one exists. This is mainly a helper function to make it easier to get the [Joint2D] that the [code]PhysicalBone2D[/code] is autoconfiguring.
+ </description>
+ </method>
+ <method name="is_simulating_physics" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns a boolean that indicates whether the [code]PhysicalBone2D[/code] node is running and simulating using the Godot 2D physics engine. When [code]true[/code], the PhysicalBone2D node is using physics.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="auto_configure_joint" type="bool" setter="set_auto_configure_joint" getter="get_auto_configure_joint" default="true">
+ If [code]true[/code], the [code]PhysicalBone2D[/code] node will automatically configure the first [Joint2D] child node. The automatic configuration is limited to setting up the node properties and positioning the [Joint2D].
+ </member>
+ <member name="bone2d_index" type="int" setter="set_bone2d_index" getter="get_bone2d_index" default="-1">
+ The index of the [Bone2D] node that this [code]PhysicalBone2D[/code] node is supposed to be simulating.
+ </member>
+ <member name="bone2d_nodepath" type="NodePath" setter="set_bone2d_nodepath" getter="get_bone2d_nodepath" default="NodePath(&quot;&quot;)">
+ The [NodePath] to the [Bone2D] node that this [code]PhysicalBone2D[/code] node is supposed to be simulating.
+ </member>
+ <member name="follow_bone_when_simulating" type="bool" setter="set_follow_bone_when_simulating" getter="get_follow_bone_when_simulating" default="false">
+ If [code]true[/code], the [code]PhysicalBone2D[/code] will keep the transform of the bone it is bound to when simulating physics.
+ </member>
+ <member name="simulate_physics" type="bool" setter="set_simulate_physics" getter="get_simulate_physics" default="false">
+ If [code]true[/code], the [code]PhysicalBone2D[/code] will start simulating using physics. If [code]false[/code], the [code]PhysicalBone2D[/code] will follow the transform of the [Bone2D] node.
+ [b]Note:[/b] To have the Bone2D nodes visually follow the [code]PhysicalBone2D[/code] node, use a [SkeletonModification2DPhysicalBones] modification on the [Skeleton2D] node with the [Bone2D] nodes.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/PhysicalBone3D.xml b/doc/classes/PhysicalBone3D.xml
index 38d9f722b1..5d15590a3f 100644
--- a/doc/classes/PhysicalBone3D.xml
+++ b/doc/classes/PhysicalBone3D.xml
@@ -25,14 +25,6 @@
<description>
</description>
</method>
- <method name="get_axis_lock" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
- </argument>
- <description>
- </description>
- </method>
<method name="get_bone_id" qualifiers="const">
<return type="int">
</return>
@@ -51,40 +43,12 @@
<description>
</description>
</method>
- <method name="set_axis_lock">
- <return type="void">
- </return>
- <argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
- </argument>
- <argument index="1" name="lock" type="bool">
- </argument>
- <description>
- </description>
- </method>
</methods>
<members>
<member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp" default="-1.0">
Damps the body's rotation if greater than [code]0[/code].
</member>
- <member name="axis_lock_angular_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's rotation in the X axis.
- </member>
- <member name="axis_lock_angular_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's rotation in the Y axis.
- </member>
- <member name="axis_lock_angular_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's rotation in the Z axis.
- </member>
- <member name="axis_lock_linear_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's movement in the X axis.
- </member>
- <member name="axis_lock_linear_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's movement in the Y axis.
- </member>
- <member name="axis_lock_linear_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's movement in the Z axis.
- </member>
- <member name="body_offset" type="Transform" setter="set_body_offset" getter="get_body_offset" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ <member name="body_offset" type="Transform3D" setter="set_body_offset" getter="get_body_offset" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
Sets the body's transform.
</member>
<member name="bounce" type="float" setter="set_bounce" getter="get_bounce" default="0.0">
@@ -99,7 +63,7 @@
<member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale" default="1.0">
This is multiplied by the global 3D gravity setting found in [b]Project &gt; Project Settings &gt; Physics &gt; 3d[/b] to produce the body's gravity. For example, a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object.
</member>
- <member name="joint_offset" type="Transform" setter="set_joint_offset" getter="get_joint_offset" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ <member name="joint_offset" type="Transform3D" setter="set_joint_offset" getter="get_joint_offset" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
Sets the joint's transform.
</member>
<member name="joint_rotation" type="Vector3" setter="set_joint_rotation" getter="get_joint_rotation">
diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml
index e43d3bb762..654b0fb668 100644
--- a/doc/classes/PhysicsBody2D.xml
+++ b/doc/classes/PhysicsBody2D.xml
@@ -26,6 +26,25 @@
Returns an array of nodes that were added as collision exceptions for this body.
</description>
</method>
+ <method name="move_and_collide">
+ <return type="KinematicCollision2D">
+ </return>
+ <argument index="0" name="rel_vec" type="Vector2">
+ </argument>
+ <argument index="1" name="infinite_inertia" type="bool" default="true">
+ </argument>
+ <argument index="2" name="exclude_raycast_shapes" type="bool" default="true">
+ </argument>
+ <argument index="3" name="test_only" type="bool" default="false">
+ </argument>
+ <argument index="4" name="safe_margin" type="float" default="0.08">
+ </argument>
+ <description>
+ Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision.
+ If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given.
+ [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody2D.collision/safe_margin] for more details).
+ </description>
+ </method>
<method name="remove_collision_exception_with">
<return type="void">
</return>
@@ -35,6 +54,27 @@
Removes a body from the list of bodies that this body can't collide with.
</description>
</method>
+ <method name="test_move">
+ <return type="bool">
+ </return>
+ <argument index="0" name="from" type="Transform2D">
+ </argument>
+ <argument index="1" name="rel_vec" type="Vector2">
+ </argument>
+ <argument index="2" name="infinite_inertia" type="bool" default="true">
+ </argument>
+ <argument index="3" name="exclude_raycast_shapes" type="bool" default="true">
+ </argument>
+ <argument index="4" name="collision" type="KinematicCollision2D" default="null">
+ </argument>
+ <argument index="5" name="safe_margin" type="float" default="0.08">
+ </argument>
+ <description>
+ Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur.
+ [code]collision[/code] is an optional object of type [KinematicCollision2D], which contains additional information about the collision (should there be one).
+ [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody2D.collision/safe_margin] for more details).
+ </description>
+ </method>
</methods>
<members>
<member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable" override="true" default="false" />
diff --git a/doc/classes/PhysicsBody3D.xml b/doc/classes/PhysicsBody3D.xml
index b320d37d23..1ec38000be 100644
--- a/doc/classes/PhysicsBody3D.xml
+++ b/doc/classes/PhysicsBody3D.xml
@@ -19,6 +19,15 @@
Adds a body to the list of bodies that this body can't collide with.
</description>
</method>
+ <method name="get_axis_lock" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
+ </argument>
+ <description>
+ Returns [code]true[/code] if the specified linear or rotational [code]axis[/code] is locked.
+ </description>
+ </method>
<method name="get_collision_exceptions">
<return type="PhysicsBody3D[]">
</return>
@@ -26,6 +35,25 @@
Returns an array of nodes that were added as collision exceptions for this body.
</description>
</method>
+ <method name="move_and_collide">
+ <return type="KinematicCollision3D">
+ </return>
+ <argument index="0" name="rel_vec" type="Vector3">
+ </argument>
+ <argument index="1" name="infinite_inertia" type="bool" default="true">
+ </argument>
+ <argument index="2" name="exclude_raycast_shapes" type="bool" default="true">
+ </argument>
+ <argument index="3" name="test_only" type="bool" default="false">
+ </argument>
+ <argument index="4" name="safe_margin" type="float" default="0.001">
+ </argument>
+ <description>
+ Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision3D], which contains information about the collision.
+ If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given.
+ [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody3D.collision/safe_margin] for more details).
+ </description>
+ </method>
<method name="remove_collision_exception_with">
<return type="void">
</return>
@@ -35,7 +63,59 @@
Removes a body from the list of bodies that this body can't collide with.
</description>
</method>
+ <method name="set_axis_lock">
+ <return type="void">
+ </return>
+ <argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
+ </argument>
+ <argument index="1" name="lock" type="bool">
+ </argument>
+ <description>
+ Locks or unlocks the specified linear or rotational [code]axis[/code] depending on the value of [code]lock[/code].
+ </description>
+ </method>
+ <method name="test_move">
+ <return type="bool">
+ </return>
+ <argument index="0" name="from" type="Transform3D">
+ </argument>
+ <argument index="1" name="rel_vec" type="Vector3">
+ </argument>
+ <argument index="2" name="infinite_inertia" type="bool" default="true">
+ </argument>
+ <argument index="3" name="exclude_raycast_shapes" type="bool" default="true">
+ </argument>
+ <argument index="4" name="collision" type="KinematicCollision3D" default="null">
+ </argument>
+ <argument index="5" name="safe_margin" type="float" default="0.001">
+ </argument>
+ <description>
+ Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur.
+ [code]collision[/code] is an optional object of type [KinematicCollision3D], which contains additional information about the collision (should there be one).
+ [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody3D.collision/safe_margin] for more details).
+ </description>
+ </method>
</methods>
+ <members>
+ <member name="axis_lock_angular_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ Lock the body's rotation in the X axis.
+ </member>
+ <member name="axis_lock_angular_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ Lock the body's rotation in the Y axis.
+ </member>
+ <member name="axis_lock_angular_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ Lock the body's rotation in the Z axis.
+ </member>
+ <member name="axis_lock_linear_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ Lock the body's linear movement in the X axis.
+ </member>
+ <member name="axis_lock_linear_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ Lock the body's linear movement in the Y axis.
+ </member>
+ <member name="axis_lock_linear_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ Lock the body's linear movement in the Z axis.
+ </member>
+ </members>
<constants>
</constants>
</class>
diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml
index dfc0ab909a..66ff16a3ce 100644
--- a/doc/classes/PhysicsDirectBodyState2D.xml
+++ b/doc/classes/PhysicsDirectBodyState2D.xml
@@ -4,7 +4,7 @@
Direct access object to a physics body in the [PhysicsServer2D].
</brief_description>
<description>
- Provides direct access to a physics body in the [PhysicsServer2D], allowing safe changes to physics properties. This object is passed via the direct state callback of rigid/character bodies, and is intended for changing the direct state of that body. See [method RigidBody2D._integrate_forces].
+ Provides direct access to a physics body in the [PhysicsServer2D], allowing safe changes to physics properties. This object is passed via the direct state callback of dynamic bodies, and is intended for changing the direct state of that body. See [method RigidBody2D._integrate_forces].
</description>
<tutorials>
<link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link>
diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml
index eea681e696..7cb3a56338 100644
--- a/doc/classes/PhysicsDirectBodyState3D.xml
+++ b/doc/classes/PhysicsDirectBodyState3D.xml
@@ -4,7 +4,7 @@
Direct access object to a physics body in the [PhysicsServer3D].
</brief_description>
<description>
- Provides direct access to a physics body in the [PhysicsServer3D], allowing safe changes to physics properties. This object is passed via the direct state callback of rigid/character bodies, and is intended for changing the direct state of that body. See [method RigidBody3D._integrate_forces].
+ Provides direct access to a physics body in the [PhysicsServer3D], allowing safe changes to physics properties. This object is passed via the direct state callback of dynamic bodies, and is intended for changing the direct state of that body. See [method RigidBody3D._integrate_forces].
</description>
<tutorials>
</tutorials>
@@ -214,7 +214,7 @@
<member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp">
The rate at which the body stops moving, if there are not any other forces moving it.
</member>
- <member name="transform" type="Transform" setter="set_transform" getter="get_transform">
+ <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform">
The body's transformation matrix.
</member>
</members>
diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml
index 229facd08b..4c2abcb087 100644
--- a/doc/classes/PhysicsServer2D.xml
+++ b/doc/classes/PhysicsServer2D.xml
@@ -1018,6 +1018,15 @@
Activates or deactivates the 2D physics engine.
</description>
</method>
+ <method name="set_collision_iterations">
+ <return type="void">
+ </return>
+ <argument index="0" name="iterations" type="int">
+ </argument>
+ <description>
+ Sets the amount of iterations for calculating velocities of colliding bodies. The greater the amount, the more accurate the collisions, but with a performance loss.
+ </description>
+ </method>
<method name="shape_get_data" qualifiers="const">
<return type="Variant">
</return>
@@ -1198,16 +1207,16 @@
This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="BODY_MODE_STATIC" value="0" enum="BodyMode">
- Constant for static bodies.
+ Constant for static bodies. In this mode, a body can be only moved by user code.
</constant>
<constant name="BODY_MODE_KINEMATIC" value="1" enum="BodyMode">
- Constant for kinematic bodies.
+ Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path.
</constant>
- <constant name="BODY_MODE_RIGID" value="2" enum="BodyMode">
- Constant for rigid bodies.
+ <constant name="BODY_MODE_DYNAMIC" value="2" enum="BodyMode">
+ Constant for dynamic bodies. In this mode, a body can be pushed by other bodies and has forces applied.
</constant>
- <constant name="BODY_MODE_CHARACTER" value="3" enum="BodyMode">
- Constant for rigid bodies in character mode. In this mode, a body can not rotate, and only its linear velocity is affected by physics.
+ <constant name="BODY_MODE_DYNAMIC_LOCKED" value="3" enum="BodyMode">
+ Constant for locked dynamic bodies. In this mode, a body is dynamic but can not rotate, and only its linear velocity is affected by external forces.
</constant>
<constant name="BODY_PARAM_BOUNCE" value="0" enum="BodyParameter">
Constant to set/get a body's bounce factor.
diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml
index 46de9e5282..2972d5155c 100644
--- a/doc/classes/PhysicsServer3D.xml
+++ b/doc/classes/PhysicsServer3D.xml
@@ -16,7 +16,7 @@
</argument>
<argument index="1" name="shape" type="RID">
</argument>
- <argument index="2" name="transform" type="Transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ <argument index="2" name="transform" type="Transform3D" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
</argument>
<argument index="3" name="disabled" type="bool" default="false">
</argument>
@@ -92,7 +92,7 @@
</description>
</method>
<method name="area_get_shape_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="area" type="RID">
</argument>
@@ -121,7 +121,7 @@
</description>
</method>
<method name="area_get_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="area" type="RID">
</argument>
@@ -258,7 +258,7 @@
</argument>
<argument index="1" name="shape_idx" type="int">
</argument>
- <argument index="2" name="transform" type="Transform">
+ <argument index="2" name="transform" type="Transform3D">
</argument>
<description>
Sets the transform matrix for an area shape.
@@ -291,7 +291,7 @@
</return>
<argument index="0" name="area" type="RID">
</argument>
- <argument index="1" name="transform" type="Transform">
+ <argument index="1" name="transform" type="Transform3D">
</argument>
<description>
Sets the transform matrix for an area.
@@ -337,7 +337,7 @@
</argument>
<argument index="1" name="shape" type="RID">
</argument>
- <argument index="2" name="transform" type="Transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ <argument index="2" name="transform" type="Transform3D" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
</argument>
<argument index="3" name="disabled" type="bool" default="false">
</argument>
@@ -443,14 +443,6 @@
Returns the [PhysicsDirectBodyState3D] of the body.
</description>
</method>
- <method name="body_get_kinematic_safe_margin" qualifiers="const">
- <return type="float">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
<method name="body_get_max_contacts_reported" qualifiers="const">
<return type="int">
</return>
@@ -510,7 +502,7 @@
</description>
</method>
<method name="body_get_shape_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="body" type="RID">
</argument>
@@ -661,16 +653,6 @@
Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]).
</description>
</method>
- <method name="body_set_kinematic_safe_margin">
- <return type="void">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="margin" type="float">
- </argument>
- <description>
- </description>
- </method>
<method name="body_set_max_contacts_reported">
<return type="void">
</return>
@@ -760,7 +742,7 @@
</argument>
<argument index="1" name="shape_idx" type="int">
</argument>
- <argument index="2" name="transform" type="Transform">
+ <argument index="2" name="transform" type="Transform3D">
</argument>
<description>
Sets the transform matrix for a body shape.
@@ -1017,11 +999,11 @@
</argument>
<argument index="1" name="body_A" type="RID">
</argument>
- <argument index="2" name="local_ref_A" type="Transform">
+ <argument index="2" name="local_ref_A" type="Transform3D">
</argument>
<argument index="3" name="body_B" type="RID">
</argument>
- <argument index="4" name="local_ref_B" type="Transform">
+ <argument index="4" name="local_ref_B" type="Transform3D">
</argument>
<description>
</description>
@@ -1033,11 +1015,11 @@
</argument>
<argument index="1" name="body_A" type="RID">
</argument>
- <argument index="2" name="local_ref_A" type="Transform">
+ <argument index="2" name="local_ref_A" type="Transform3D">
</argument>
<argument index="3" name="body_B" type="RID">
</argument>
- <argument index="4" name="local_ref_B" type="Transform">
+ <argument index="4" name="local_ref_B" type="Transform3D">
</argument>
<description>
</description>
@@ -1049,11 +1031,11 @@
</argument>
<argument index="1" name="body_A" type="RID">
</argument>
- <argument index="2" name="hinge_A" type="Transform">
+ <argument index="2" name="hinge_A" type="Transform3D">
</argument>
<argument index="3" name="body_B" type="RID">
</argument>
- <argument index="4" name="hinge_B" type="Transform">
+ <argument index="4" name="hinge_B" type="Transform3D">
</argument>
<description>
</description>
@@ -1081,11 +1063,11 @@
</argument>
<argument index="1" name="body_A" type="RID">
</argument>
- <argument index="2" name="local_ref_A" type="Transform">
+ <argument index="2" name="local_ref_A" type="Transform3D">
</argument>
<argument index="3" name="body_B" type="RID">
</argument>
- <argument index="4" name="local_ref_B" type="Transform">
+ <argument index="4" name="local_ref_B" type="Transform3D">
</argument>
<description>
</description>
@@ -1595,16 +1577,16 @@
This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="BODY_MODE_STATIC" value="0" enum="BodyMode">
- Constant for static bodies.
+ Constant for static bodies. In this mode, a body can be only moved by user code.
</constant>
<constant name="BODY_MODE_KINEMATIC" value="1" enum="BodyMode">
- Constant for kinematic bodies.
+ Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path.
</constant>
- <constant name="BODY_MODE_RIGID" value="2" enum="BodyMode">
- Constant for rigid bodies.
+ <constant name="BODY_MODE_DYNAMIC" value="2" enum="BodyMode">
+ Constant for dynamic bodies. In this mode, a body can be pushed by other bodies and has forces applied.
</constant>
- <constant name="BODY_MODE_CHARACTER" value="3" enum="BodyMode">
- Constant for rigid bodies in character mode. In this mode, a body can not rotate, and only its linear velocity is affected by physics.
+ <constant name="BODY_MODE_DYNAMIC_LOCKED" value="3" enum="BodyMode">
+ Constant for locked dynamic bodies. In this mode, a body is dynamic but can not rotate, and only its linear velocity is affected by external forces.
</constant>
<constant name="BODY_PARAM_BOUNCE" value="0" enum="BodyParameter">
Constant to set/get a body's bounce factor.
diff --git a/doc/classes/PhysicsShapeQueryParameters2D.xml b/doc/classes/PhysicsShapeQueryParameters2D.xml
index 4d7fc61517..92bd9b136a 100644
--- a/doc/classes/PhysicsShapeQueryParameters2D.xml
+++ b/doc/classes/PhysicsShapeQueryParameters2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsShapeQueryParameters2D" inherits="Reference" version="4.0">
+<class name="PhysicsShapeQueryParameters2D" inherits="RefCounted" version="4.0">
<brief_description>
Parameters to be sent to a 2D shape physics query.
</brief_description>
diff --git a/doc/classes/PhysicsShapeQueryParameters3D.xml b/doc/classes/PhysicsShapeQueryParameters3D.xml
index 4b43ea66fc..087c52a650 100644
--- a/doc/classes/PhysicsShapeQueryParameters3D.xml
+++ b/doc/classes/PhysicsShapeQueryParameters3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsShapeQueryParameters3D" inherits="Reference" version="4.0">
+<class name="PhysicsShapeQueryParameters3D" inherits="RefCounted" version="4.0">
<brief_description>
Parameters to be sent to a 3D shape physics query.
</brief_description>
@@ -60,7 +60,7 @@
[/csharp]
[/codeblocks]
</member>
- <member name="transform" type="Transform" setter="set_transform" getter="get_transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
The queried shape's transform matrix.
</member>
</members>
diff --git a/doc/classes/PhysicsShapeQueryResult2D.xml b/doc/classes/PhysicsShapeQueryResult2D.xml
index 227683cc33..07b7bc90e2 100644
--- a/doc/classes/PhysicsShapeQueryResult2D.xml
+++ b/doc/classes/PhysicsShapeQueryResult2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsShapeQueryResult2D" inherits="Reference" version="4.0">
+<class name="PhysicsShapeQueryResult2D" inherits="RefCounted" version="4.0">
<brief_description>
Result of a 2D shape query in [PhysicsServer2D].
</brief_description>
diff --git a/doc/classes/PhysicsShapeQueryResult3D.xml b/doc/classes/PhysicsShapeQueryResult3D.xml
index 4555c4e242..d0ca227a68 100644
--- a/doc/classes/PhysicsShapeQueryResult3D.xml
+++ b/doc/classes/PhysicsShapeQueryResult3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsShapeQueryResult3D" inherits="Reference" version="4.0">
+<class name="PhysicsShapeQueryResult3D" inherits="RefCounted" version="4.0">
<brief_description>
Result of a 3D shape query in [PhysicsServer3D].
</brief_description>
diff --git a/doc/classes/PhysicsTestMotionResult2D.xml b/doc/classes/PhysicsTestMotionResult2D.xml
index 301cff2885..2744aa17a1 100644
--- a/doc/classes/PhysicsTestMotionResult2D.xml
+++ b/doc/classes/PhysicsTestMotionResult2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsTestMotionResult2D" inherits="Reference" version="4.0">
+<class name="PhysicsTestMotionResult2D" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PinJoint2D.xml b/doc/classes/PinJoint2D.xml
index 42155a7f25..ed45149cdf 100644
--- a/doc/classes/PinJoint2D.xml
+++ b/doc/classes/PinJoint2D.xml
@@ -4,7 +4,7 @@
Pin joint for 2D shapes.
</brief_description>
<description>
- Pin joint for 2D rigid bodies. It pins two bodies (rigid or static) together.
+ Pin joint for 2D rigid bodies. It pins two bodies (dynamic or static) together.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PinJoint3D.xml b/doc/classes/PinJoint3D.xml
index 267ea38873..37a85e497f 100644
--- a/doc/classes/PinJoint3D.xml
+++ b/doc/classes/PinJoint3D.xml
@@ -4,7 +4,7 @@
Pin joint for 3D PhysicsBodies.
</brief_description>
<description>
- Pin joint for 3D rigid bodies. It pins 2 bodies (rigid or static) together. See also [Generic6DOFJoint3D].
+ Pin joint for 3D rigid bodies. It pins 2 bodies (dynamic or static) together. See also [Generic6DOFJoint3D].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml
index 8b73bcb9c1..3892633654 100644
--- a/doc/classes/PrimitiveMesh.xml
+++ b/doc/classes/PrimitiveMesh.xml
@@ -31,7 +31,7 @@
</methods>
<members>
<member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB( 0, 0, 0, 0, 0, 0 )">
- Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices.
+ Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices.
</member>
<member name="flip_faces" type="bool" setter="set_flip_faces" getter="get_flip_faces" default="false">
If set, the order of the vertices in each triangle are reversed resulting in the backside of the mesh being drawn.
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index d38c3fc0d8..25df918522 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -6,7 +6,7 @@
<description>
Contains global variables accessible from everywhere. Use [method get_setting], [method set_setting] or [method has_setting] to access them. Variables stored in [code]project.godot[/code] are also loaded into ProjectSettings, making this object very useful for reading custom game configuration options.
When naming a Project Settings property, use the full path to the setting including the category. For example, [code]"application/config/name"[/code] for the project name. Category and property names can be viewed in the Project Settings dialog.
- [b]Feature tags:[/b] Project settings can be overriden for specific platforms and configurations (debug, release, ...) using [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url].
+ [b]Feature tags:[/b] Project settings can be overridden for specific platforms and configurations (debug, release, ...) using [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url].
[b]Overriding:[/b] Any project setting can be overridden by creating a file named [code]override.cfg[/code] in the project's root directory. This can also be used in exported projects by placing this file in the same directory as the project binary. Overriding will still take the base project settings' [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url] in account. Therefore, make sure to [i]also[/i] override the setting with the desired feature tags if you want them to override base project settings on all platforms and configurations.
</description>
<tutorials>
@@ -309,7 +309,7 @@
If [code]true[/code], microphone input will be allowed. This requires appropriate permissions to be set when exporting to Android or iOS.
</member>
<member name="audio/driver/mix_rate" type="int" setter="" getter="" default="44100">
- Mixing rate used for audio. In general, it's better to not touch this and leave it to the host operating system.
+ The mixing rate used for audio (in Hz). In general, it's better to not touch this and leave it to the host operating system.
</member>
<member name="audio/driver/output_latency" type="int" setter="" getter="" default="15">
Output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware.
@@ -494,8 +494,9 @@
<member name="display/window/energy_saving/keep_screen_on" type="bool" setter="" getter="" default="true">
If [code]true[/code], keeps the screen on (even in case of inactivity), so the screensaver does not take over. Works on desktop and mobile platforms.
</member>
- <member name="display/window/handheld/orientation" type="String" setter="" getter="" default="&quot;landscape&quot;">
- Default orientation on mobile devices.
+ <member name="display/window/handheld/orientation" type="int" setter="" getter="" default="0">
+ The default screen orientation to use on mobile devices. See [enum DisplayServer.ScreenOrientation] for possible values.
+ [b]Note:[/b] When set to a portrait orientation, this project setting does not flip the project resolution's width and height automatically. Instead, you have to set [member display/window/size/width] and [member display/window/size/height] accordingly.
</member>
<member name="display/window/ios/hide_home_indicator" type="bool" setter="" getter="" default="true">
If [code]true[/code], the home indicator is hidden automatically. This only affects iOS devices without a physical home button.
@@ -550,7 +551,7 @@
prime-run %command%
[/codeblock]
</member>
- <member name="editor/script/search_in_file_extensions" type="PackedStringArray" setter="" getter="" default="PackedStringArray( &quot;gd&quot;, &quot;shader&quot; )">
+ <member name="editor/script/search_in_file_extensions" type="PackedStringArray" setter="" getter="" default="PackedStringArray( &quot;gd&quot;, &quot;gdshader&quot; )">
Text-based file extensions to include in the script editor's "Find in Files" feature. You can add e.g. [code]tscn[/code] if you wish to also parse your scene files, especially if you use built-in scripts which are serialized in the scene files.
</member>
<member name="editor/script/templates_search_path" type="String" setter="" getter="" default="&quot;res://script_templates&quot;">
@@ -702,6 +703,8 @@
</member>
<member name="input/ui_text_completion_query" type="Dictionary" setter="" getter="">
</member>
+ <member name="input/ui_text_completion_replace" type="Dictionary" setter="" getter="">
+ </member>
<member name="input/ui_text_dedent" type="Dictionary" setter="" getter="">
</member>
<member name="input/ui_text_delete" type="Dictionary" setter="" getter="">
@@ -732,6 +735,10 @@
</member>
<member name="input/ui_text_select_all" type="Dictionary" setter="" getter="">
</member>
+ <member name="input/ui_text_select_word_under_caret" type="Dictionary" setter="" getter="">
+ If no selection is currently active, selects the word currently under the caret in text fields. If a selection is currently active, deselects the current selection.
+ [b]Note:[/b] Currently, this is only implemented in [TextEdit], not [LineEdit].
+ </member>
<member name="input/ui_text_toggle_insert_mode" type="Dictionary" setter="" getter="">
</member>
<member name="input/ui_undo" type="Dictionary" setter="" getter="">
@@ -1132,8 +1139,6 @@
<member name="layer_names/3d_render/layer_9" type="String" setter="" getter="" default="&quot;&quot;">
Optional name for the 3D render layer 9. If left empty, the layer will display as "Layer 9".
</member>
- <member name="memory/limits/command_queue/multithreading_queue_size_kb" type="int" setter="" getter="" default="256">
- </member>
<member name="memory/limits/message_queue/max_size_kb" type="int" setter="" getter="" default="4096">
Godot uses a message queue to defer some function calls. If you run out of space on it (you will see an error), you can increase the size here.
</member>
@@ -1201,17 +1206,17 @@
The default angular damp in 2D.
[b]Note:[/b] Good values are in the range [code]0[/code] to [code]1[/code]. At value [code]0[/code] objects will keep moving with the same velocity. Values greater than [code]1[/code] will aim to reduce the velocity to [code]0[/code] in less than a second e.g. a value of [code]2[/code] will aim to reduce the velocity to [code]0[/code] in half a second. A value equal to or greater than the physics frame rate ([member ProjectSettings.physics/common/physics_fps], [code]60[/code] by default) will bring the object to a stop in one iteration.
</member>
- <member name="physics/2d/default_gravity" type="int" setter="" getter="" default="98">
- The default gravity strength in 2D.
+ <member name="physics/2d/default_gravity" type="float" setter="" getter="" default="980.0">
+ The default gravity strength in 2D (in pixels per second squared).
[b]Note:[/b] This property is only read when the project starts. To change the default gravity at runtime, use the following code sample:
[codeblocks]
[gdscript]
- # Set the default gravity strength to 98.
- PhysicsServer2D.area_set_param(get_viewport().find_world_2d().space, PhysicsServer2D.AREA_PARAM_GRAVITY, 98)
+ # Set the default gravity strength to 980.
+ PhysicsServer2D.area_set_param(get_viewport().find_world_2d().space, PhysicsServer2D.AREA_PARAM_GRAVITY, 980)
[/gdscript]
[csharp]
- // Set the default gravity strength to 98.
- PhysicsServer2D.AreaSetParam(GetViewport().FindWorld2d().Space, PhysicsServer2D.AreaParameter.Gravity, 98);
+ // Set the default gravity strength to 980.
+ PhysicsServer2D.AreaSetParam(GetViewport().FindWorld2d().Space, PhysicsServer2D.AreaParameter.Gravity, 980);
[/csharp]
[/codeblocks]
</member>
@@ -1254,7 +1259,7 @@
[b]Note:[/b] Good values are in the range [code]0[/code] to [code]1[/code]. At value [code]0[/code] objects will keep moving with the same velocity. Values greater than [code]1[/code] will aim to reduce the velocity to [code]0[/code] in less than a second e.g. a value of [code]2[/code] will aim to reduce the velocity to [code]0[/code] in half a second. A value equal to or greater than the physics frame rate ([member ProjectSettings.physics/common/physics_fps], [code]60[/code] by default) will bring the object to a stop in one iteration.
</member>
<member name="physics/3d/default_gravity" type="float" setter="" getter="" default="9.8">
- The default gravity strength in 3D.
+ The default gravity strength in 3D (in meters per second squared).
[b]Note:[/b] This property is only read when the project starts. To change the default gravity at runtime, use the following code sample:
[codeblocks]
[gdscript]
@@ -1306,7 +1311,8 @@
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.iterations_per_second] instead.
</member>
<member name="physics/common/physics_jitter_fix" type="float" setter="" getter="" default="0.5">
- Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
+ Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
+ [b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics/common/physics_jitter_fix] to [code]0[/code].
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_jitter_fix] instead.
</member>
<member name="rendering/2d/sdf/oversize" type="int" setter="" getter="" default="1">
@@ -1414,18 +1420,16 @@
</member>
<member name="rendering/global_illumination/gi/use_half_resolution" type="bool" setter="" getter="" default="false">
</member>
- <member name="rendering/global_illumination/gi_probes/anisotropic" type="bool" setter="" getter="" default="false">
- If [code]true[/code], take additional samples when rendering objects affected by a [GIProbe] to reduce artifacts from only sampling in one direction.
- </member>
- <member name="rendering/global_illumination/gi_probes/quality" type="int" setter="" getter="" default="1">
- Sets the number of cone samples taken when rendering objects affected by [GIProbe]s.
- </member>
<member name="rendering/global_illumination/sdfgi/frames_to_converge" type="int" setter="" getter="" default="4">
</member>
<member name="rendering/global_illumination/sdfgi/frames_to_update_lights" type="int" setter="" getter="" default="2">
</member>
<member name="rendering/global_illumination/sdfgi/probe_ray_count" type="int" setter="" getter="" default="1">
</member>
+ <member name="rendering/global_illumination/voxel_gi/anisotropic" type="bool" setter="" getter="" default="false">
+ </member>
+ <member name="rendering/global_illumination/voxel_gi/quality" type="int" setter="" getter="" default="1">
+ </member>
<member name="rendering/lightmapping/bake_performance/max_rays_per_pass" type="int" setter="" getter="" default="32">
</member>
<member name="rendering/lightmapping/bake_performance/max_rays_per_probe_pass" type="int" setter="" getter="" default="64">
@@ -1497,6 +1501,16 @@
<member name="rendering/reflections/sky_reflections/texture_array_reflections.mobile" type="bool" setter="" getter="" default="false">
Lower-end override for [member rendering/reflections/sky_reflections/texture_array_reflections] on mobile devices, due to performance concerns or driver support.
</member>
+ <member name="rendering/shader_compiler/shader_cache/compress" type="bool" setter="" getter="" default="true">
+ </member>
+ <member name="rendering/shader_compiler/shader_cache/enabled" type="bool" setter="" getter="" default="true">
+ </member>
+ <member name="rendering/shader_compiler/shader_cache/strip_debug" type="bool" setter="" getter="" default="false">
+ </member>
+ <member name="rendering/shader_compiler/shader_cache/strip_debug.release" type="bool" setter="" getter="" default="true">
+ </member>
+ <member name="rendering/shader_compiler/shader_cache/use_zstd_compression" type="bool" setter="" getter="" default="true">
+ </member>
<member name="rendering/shading/overrides/force_blinn_over_ggx" type="bool" setter="" getter="" default="false">
If [code]true[/code], uses faster but lower-quality Blinn model to generate blurred reflections instead of the GGX model.
</member>
@@ -1561,20 +1575,31 @@
<member name="rendering/textures/default_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false">
If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
</member>
+ <member name="rendering/textures/lossless_compression/force_png" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
+ </member>
+ <member name="rendering/textures/lossless_compression/webp_compression_level" type="int" setter="" getter="" default="2">
+ The default compression level for lossless WebP. Higher levels result in smaller files at the cost of compression speed. Decompression speed is mostly unaffected by the compression level. Supported values are 0 to 9. Note that compression levels above 6 are very slow and offer very little savings.
+ </member>
<member name="rendering/textures/vram_compression/import_bptc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the BPTC algorithm. This texture compression algorithm is only supported on desktop platforms, and only when using the Vulkan renderer.
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor.
</member>
<member name="rendering/textures/vram_compression/import_etc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression algorithm. This algorithm doesn't support alpha channels in textures.
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor.
</member>
<member name="rendering/textures/vram_compression/import_etc2" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm. This texture compression algorithm is only supported when using the Vulkan renderer.
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor.
</member>
<member name="rendering/textures/vram_compression/import_pvrtc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the PowerVR Texture Compression algorithm. This texture compression algorithm is only supported on iOS.
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor.
</member>
<member name="rendering/textures/vram_compression/import_s3tc" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor.
</member>
<member name="rendering/vulkan/descriptor_pools/max_descriptors_per_pool" type="int" setter="" getter="" default="64">
</member>
@@ -1588,6 +1613,9 @@
</member>
<member name="rendering/vulkan/staging_buffer/texture_upload_region_size_px" type="int" setter="" getter="" default="64">
</member>
+ <member name="rendering/xr/enabled" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], XR support is enabled in Godot, this ensures required shaders are compiled.
+ </member>
<member name="world/2d/cell_size" type="int" setter="" getter="" default="100">
Cell size used for the 2D hash grid that [VisibilityNotifier2D] uses (in pixels).
</member>
diff --git a/doc/classes/Quat.xml b/doc/classes/Quat.xml
deleted file mode 100644
index 1c0a3e37c0..0000000000
--- a/doc/classes/Quat.xml
+++ /dev/null
@@ -1,308 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Quat" version="4.0">
- <brief_description>
- Quaternion.
- </brief_description>
- <description>
- A unit quaternion used for representing 3D rotations. Quaternions need to be normalized to be used for rotation.
- It is similar to Basis, which implements matrix representation of rotations, and can be parametrized using both an axis-angle pair or Euler angles. Basis stores rotation, scale, and shearing, while Quat only stores rotation.
- Due to its compactness and the way it is stored in memory, certain operations (obtaining axis-angle and performing SLERP, in particular) are more efficient and robust against floating-point errors.
- </description>
- <tutorials>
- <link title="Using 3D transforms">https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html#interpolating-with-quaternions</link>
- <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
- </tutorials>
- <methods>
- <method name="Quat" qualifiers="constructor">
- <return type="Quat">
- </return>
- <description>
- Constructs a default-initialized quaternion with all components set to [code]0[/code].
- </description>
- </method>
- <method name="Quat" qualifiers="constructor">
- <return type="Quat">
- </return>
- <argument index="0" name="from" type="Quat">
- </argument>
- <description>
- Constructs a [Quat] as a copy of the given [Quat].
- </description>
- </method>
- <method name="Quat" qualifiers="constructor">
- <return type="Quat">
- </return>
- <argument index="0" name="arc_from" type="Vector3">
- </argument>
- <argument index="1" name="arc_to" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="Quat" qualifiers="constructor">
- <return type="Quat">
- </return>
- <argument index="0" name="axis" type="Vector3">
- </argument>
- <argument index="1" name="angle" type="float">
- </argument>
- <description>
- Constructs a quaternion that will rotate around the given axis by the specified angle. The axis must be a normalized vector.
- </description>
- </method>
- <method name="Quat" qualifiers="constructor">
- <return type="Quat">
- </return>
- <argument index="0" name="euler" type="Vector3">
- </argument>
- <description>
- Constructs a quaternion that will perform a rotation specified by Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last), given in the vector format as (X angle, Y angle, Z angle).
- </description>
- </method>
- <method name="Quat" qualifiers="constructor">
- <return type="Quat">
- </return>
- <argument index="0" name="from" type="Basis">
- </argument>
- <description>
- Constructs a quaternion from the given [Basis].
- </description>
- </method>
- <method name="Quat" qualifiers="constructor">
- <return type="Quat">
- </return>
- <argument index="0" name="x" type="float">
- </argument>
- <argument index="1" name="y" type="float">
- </argument>
- <argument index="2" name="z" type="float">
- </argument>
- <argument index="3" name="w" type="float">
- </argument>
- <description>
- Constructs a quaternion defined by the given values.
- </description>
- </method>
- <method name="cubic_slerp" qualifiers="const">
- <return type="Quat">
- </return>
- <argument index="0" name="b" type="Quat">
- </argument>
- <argument index="1" name="pre_a" type="Quat">
- </argument>
- <argument index="2" name="post_b" type="Quat">
- </argument>
- <argument index="3" name="weight" type="float">
- </argument>
- <description>
- Performs a cubic spherical interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code].
- </description>
- </method>
- <method name="dot" qualifiers="const">
- <return type="float">
- </return>
- <argument index="0" name="with" type="Quat">
- </argument>
- <description>
- Returns the dot product of two quaternions.
- </description>
- </method>
- <method name="get_euler" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- Returns Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last) corresponding to the rotation represented by the unit quaternion. Returned vector contains the rotation angles in the format (X angle, Y angle, Z angle).
- </description>
- </method>
- <method name="inverse" qualifiers="const">
- <return type="Quat">
- </return>
- <description>
- Returns the inverse of the quaternion.
- </description>
- </method>
- <method name="is_equal_approx" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="to" type="Quat">
- </argument>
- <description>
- Returns [code]true[/code] if this quaternion and [code]quat[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
- </description>
- </method>
- <method name="is_normalized" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns whether the quaternion is normalized or not.
- </description>
- </method>
- <method name="length" qualifiers="const">
- <return type="float">
- </return>
- <description>
- Returns the length of the quaternion.
- </description>
- </method>
- <method name="length_squared" qualifiers="const">
- <return type="float">
- </return>
- <description>
- Returns the length of the quaternion, squared.
- </description>
- </method>
- <method name="normalized" qualifiers="const">
- <return type="Quat">
- </return>
- <description>
- Returns a copy of the quaternion, normalized to unit length.
- </description>
- </method>
- <method name="operator !=" qualifiers="operator">
- <return type="bool">
- </return>
- <argument index="0" name="right" type="Quat">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator *" qualifiers="operator">
- <return type="Quat">
- </return>
- <argument index="0" name="right" type="Quat">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator *" qualifiers="operator">
- <return type="Vector3">
- </return>
- <argument index="0" name="right" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator *" qualifiers="operator">
- <return type="Quat">
- </return>
- <argument index="0" name="right" type="float">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator *" qualifiers="operator">
- <return type="Quat">
- </return>
- <argument index="0" name="right" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="Quat">
- </return>
- <description>
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="Quat">
- </return>
- <argument index="0" name="right" type="Quat">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="Quat">
- </return>
- <description>
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="Quat">
- </return>
- <argument index="0" name="right" type="Quat">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator /" qualifiers="operator">
- <return type="Quat">
- </return>
- <argument index="0" name="right" type="float">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator /" qualifiers="operator">
- <return type="Quat">
- </return>
- <argument index="0" name="right" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator ==" qualifiers="operator">
- <return type="bool">
- </return>
- <argument index="0" name="right" type="Quat">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator []" qualifiers="operator">
- <return type="float">
- </return>
- <argument index="0" name="index" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="slerp" qualifiers="const">
- <return type="Quat">
- </return>
- <argument index="0" name="to" type="Quat">
- </argument>
- <argument index="1" name="weight" type="float">
- </argument>
- <description>
- Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code].
- [b]Note:[/b] Both quaternions must be normalized.
- </description>
- </method>
- <method name="slerpni" qualifiers="const">
- <return type="Quat">
- </return>
- <argument index="0" name="to" type="Quat">
- </argument>
- <argument index="1" name="weight" type="float">
- </argument>
- <description>
- Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code], but without checking if the rotation path is not bigger than 90 degrees.
- </description>
- </method>
- </methods>
- <members>
- <member name="w" type="float" setter="" getter="" default="1.0">
- W component of the quaternion (real part).
- Quaternion components should usually not be manipulated directly.
- </member>
- <member name="x" type="float" setter="" getter="" default="0.0">
- X component of the quaternion (imaginary [code]i[/code] axis part).
- Quaternion components should usually not be manipulated directly.
- </member>
- <member name="y" type="float" setter="" getter="" default="0.0">
- Y component of the quaternion (imaginary [code]j[/code] axis part).
- Quaternion components should usually not be manipulated directly.
- </member>
- <member name="z" type="float" setter="" getter="" default="0.0">
- Z component of the quaternion (imaginary [code]k[/code] axis part).
- Quaternion components should usually not be manipulated directly.
- </member>
- </members>
- <constants>
- <constant name="IDENTITY" value="Quat( 0, 0, 0, 1 )">
- The identity quaternion, representing no rotation. Equivalent to an identity [Basis] matrix. If a vector is transformed by an identity quaternion, it will not change.
- </constant>
- </constants>
-</class>
diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml
new file mode 100644
index 0000000000..678fb0d44d
--- /dev/null
+++ b/doc/classes/Quaternion.xml
@@ -0,0 +1,308 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Quaternion" version="4.0">
+ <brief_description>
+ Quaternion.
+ </brief_description>
+ <description>
+ A unit quaternion used for representing 3D rotations. Quaternions need to be normalized to be used for rotation.
+ It is similar to Basis, which implements matrix representation of rotations, and can be parametrized using both an axis-angle pair or Euler angles. Basis stores rotation, scale, and shearing, while Quaternion only stores rotation.
+ Due to its compactness and the way it is stored in memory, certain operations (obtaining axis-angle and performing SLERP, in particular) are more efficient and robust against floating-point errors.
+ </description>
+ <tutorials>
+ <link title="Using 3D transforms">https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html#interpolating-with-quaternions</link>
+ <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
+ </tutorials>
+ <methods>
+ <method name="Quaternion" qualifiers="constructor">
+ <return type="Quaternion">
+ </return>
+ <description>
+ Constructs a default-initialized quaternion with all components set to [code]0[/code].
+ </description>
+ </method>
+ <method name="Quaternion" qualifiers="constructor">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="from" type="Quaternion">
+ </argument>
+ <description>
+ Constructs a [Quaternion] as a copy of the given [Quaternion].
+ </description>
+ </method>
+ <method name="Quaternion" qualifiers="constructor">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="arc_from" type="Vector3">
+ </argument>
+ <argument index="1" name="arc_to" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="Quaternion" qualifiers="constructor">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="axis" type="Vector3">
+ </argument>
+ <argument index="1" name="angle" type="float">
+ </argument>
+ <description>
+ Constructs a quaternion that will rotate around the given axis by the specified angle. The axis must be a normalized vector.
+ </description>
+ </method>
+ <method name="Quaternion" qualifiers="constructor">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="euler" type="Vector3">
+ </argument>
+ <description>
+ Constructs a quaternion that will perform a rotation specified by Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last), given in the vector format as (X angle, Y angle, Z angle).
+ </description>
+ </method>
+ <method name="Quaternion" qualifiers="constructor">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="from" type="Basis">
+ </argument>
+ <description>
+ Constructs a quaternion from the given [Basis].
+ </description>
+ </method>
+ <method name="Quaternion" qualifiers="constructor">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="x" type="float">
+ </argument>
+ <argument index="1" name="y" type="float">
+ </argument>
+ <argument index="2" name="z" type="float">
+ </argument>
+ <argument index="3" name="w" type="float">
+ </argument>
+ <description>
+ Constructs a quaternion defined by the given values.
+ </description>
+ </method>
+ <method name="cubic_slerp" qualifiers="const">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="b" type="Quaternion">
+ </argument>
+ <argument index="1" name="pre_a" type="Quaternion">
+ </argument>
+ <argument index="2" name="post_b" type="Quaternion">
+ </argument>
+ <argument index="3" name="weight" type="float">
+ </argument>
+ <description>
+ Performs a cubic spherical interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code].
+ </description>
+ </method>
+ <method name="dot" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="with" type="Quaternion">
+ </argument>
+ <description>
+ Returns the dot product of two quaternions.
+ </description>
+ </method>
+ <method name="get_euler" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ Returns Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last) corresponding to the rotation represented by the unit quaternion. Returned vector contains the rotation angles in the format (X angle, Y angle, Z angle).
+ </description>
+ </method>
+ <method name="inverse" qualifiers="const">
+ <return type="Quaternion">
+ </return>
+ <description>
+ Returns the inverse of the quaternion.
+ </description>
+ </method>
+ <method name="is_equal_approx" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="to" type="Quaternion">
+ </argument>
+ <description>
+ Returns [code]true[/code] if this quaternion and [code]quat[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
+ </description>
+ </method>
+ <method name="is_normalized" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether the quaternion is normalized or not.
+ </description>
+ </method>
+ <method name="length" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Returns the length of the quaternion.
+ </description>
+ </method>
+ <method name="length_squared" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Returns the length of the quaternion, squared.
+ </description>
+ </method>
+ <method name="normalized" qualifiers="const">
+ <return type="Quaternion">
+ </return>
+ <description>
+ Returns a copy of the quaternion, normalized to unit length.
+ </description>
+ </method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Quaternion">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="right" type="Quaternion">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="right" type="Quaternion">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="right" type="Quaternion">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Quaternion">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="slerp" qualifiers="const">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="to" type="Quaternion">
+ </argument>
+ <argument index="1" name="weight" type="float">
+ </argument>
+ <description>
+ Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code].
+ [b]Note:[/b] Both quaternions must be normalized.
+ </description>
+ </method>
+ <method name="slerpni" qualifiers="const">
+ <return type="Quaternion">
+ </return>
+ <argument index="0" name="to" type="Quaternion">
+ </argument>
+ <argument index="1" name="weight" type="float">
+ </argument>
+ <description>
+ Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code], but without checking if the rotation path is not bigger than 90 degrees.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="w" type="float" setter="" getter="" default="1.0">
+ W component of the quaternion (real part).
+ Quaternion components should usually not be manipulated directly.
+ </member>
+ <member name="x" type="float" setter="" getter="" default="0.0">
+ X component of the quaternion (imaginary [code]i[/code] axis part).
+ Quaternion components should usually not be manipulated directly.
+ </member>
+ <member name="y" type="float" setter="" getter="" default="0.0">
+ Y component of the quaternion (imaginary [code]j[/code] axis part).
+ Quaternion components should usually not be manipulated directly.
+ </member>
+ <member name="z" type="float" setter="" getter="" default="0.0">
+ Z component of the quaternion (imaginary [code]k[/code] axis part).
+ Quaternion components should usually not be manipulated directly.
+ </member>
+ </members>
+ <constants>
+ <constant name="IDENTITY" value="Quaternion( 0, 0, 0, 1 )">
+ The identity quaternion, representing no rotation. Equivalent to an identity [Basis] matrix. If a vector is transformed by an identity quaternion, it will not change.
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/RDAttachmentFormat.xml b/doc/classes/RDAttachmentFormat.xml
index 4ee7b9b28e..b73377bf77 100644
--- a/doc/classes/RDAttachmentFormat.xml
+++ b/doc/classes/RDAttachmentFormat.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDAttachmentFormat" inherits="Reference" version="4.0">
+<class name="RDAttachmentFormat" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDPipelineColorBlendState.xml b/doc/classes/RDPipelineColorBlendState.xml
index adc6f1f6a3..1424a0d653 100644
--- a/doc/classes/RDPipelineColorBlendState.xml
+++ b/doc/classes/RDPipelineColorBlendState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDPipelineColorBlendState" inherits="Reference" version="4.0">
+<class name="RDPipelineColorBlendState" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDPipelineColorBlendStateAttachment.xml b/doc/classes/RDPipelineColorBlendStateAttachment.xml
index 7f118b5f0b..a6a1900cb5 100644
--- a/doc/classes/RDPipelineColorBlendStateAttachment.xml
+++ b/doc/classes/RDPipelineColorBlendStateAttachment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDPipelineColorBlendStateAttachment" inherits="Reference" version="4.0">
+<class name="RDPipelineColorBlendStateAttachment" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDPipelineDepthStencilState.xml b/doc/classes/RDPipelineDepthStencilState.xml
index 562ff52819..76e0506bca 100644
--- a/doc/classes/RDPipelineDepthStencilState.xml
+++ b/doc/classes/RDPipelineDepthStencilState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDPipelineDepthStencilState" inherits="Reference" version="4.0">
+<class name="RDPipelineDepthStencilState" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDPipelineMultisampleState.xml b/doc/classes/RDPipelineMultisampleState.xml
index 4658c7d9ba..8c90f02301 100644
--- a/doc/classes/RDPipelineMultisampleState.xml
+++ b/doc/classes/RDPipelineMultisampleState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDPipelineMultisampleState" inherits="Reference" version="4.0">
+<class name="RDPipelineMultisampleState" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDPipelineRasterizationState.xml b/doc/classes/RDPipelineRasterizationState.xml
index 5064dd6deb..3f8c50cf42 100644
--- a/doc/classes/RDPipelineRasterizationState.xml
+++ b/doc/classes/RDPipelineRasterizationState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDPipelineRasterizationState" inherits="Reference" version="4.0">
+<class name="RDPipelineRasterizationState" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDSamplerState.xml b/doc/classes/RDSamplerState.xml
index ab31960b7c..9a9d55948c 100644
--- a/doc/classes/RDSamplerState.xml
+++ b/doc/classes/RDSamplerState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDSamplerState" inherits="Reference" version="4.0">
+<class name="RDSamplerState" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDShaderFile.xml b/doc/classes/RDShaderFile.xml
index 14e70d53ea..346a97a1c0 100644
--- a/doc/classes/RDShaderFile.xml
+++ b/doc/classes/RDShaderFile.xml
@@ -10,7 +10,7 @@
<method name="get_bytecode" qualifiers="const">
<return type="RDShaderBytecode">
</return>
- <argument index="0" name="version" type="StringName" default="@&quot;&quot;">
+ <argument index="0" name="version" type="StringName" default="&amp;&quot;&quot;">
</argument>
<description>
</description>
@@ -26,7 +26,7 @@
</return>
<argument index="0" name="bytecode" type="RDShaderBytecode">
</argument>
- <argument index="1" name="version" type="StringName" default="@&quot;&quot;">
+ <argument index="1" name="version" type="StringName" default="&amp;&quot;&quot;">
</argument>
<description>
</description>
diff --git a/doc/classes/RDShaderSource.xml b/doc/classes/RDShaderSource.xml
index c1cfd34bb7..68fc43d8ef 100644
--- a/doc/classes/RDShaderSource.xml
+++ b/doc/classes/RDShaderSource.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDShaderSource" inherits="Reference" version="4.0">
+<class name="RDShaderSource" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDTextureFormat.xml b/doc/classes/RDTextureFormat.xml
index e41ddff368..ccfa6d1b95 100644
--- a/doc/classes/RDTextureFormat.xml
+++ b/doc/classes/RDTextureFormat.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDTextureFormat" inherits="Reference" version="4.0">
+<class name="RDTextureFormat" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDTextureView.xml b/doc/classes/RDTextureView.xml
index 73b2a7ae4a..db140ae775 100644
--- a/doc/classes/RDTextureView.xml
+++ b/doc/classes/RDTextureView.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDTextureView" inherits="Reference" version="4.0">
+<class name="RDTextureView" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDUniform.xml b/doc/classes/RDUniform.xml
index bc8a21e985..666935d663 100644
--- a/doc/classes/RDUniform.xml
+++ b/doc/classes/RDUniform.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDUniform" inherits="Reference" version="4.0">
+<class name="RDUniform" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RDVertexAttribute.xml b/doc/classes/RDVertexAttribute.xml
index 56fe40b51d..3499918cc8 100644
--- a/doc/classes/RDVertexAttribute.xml
+++ b/doc/classes/RDVertexAttribute.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDVertexAttribute" inherits="Reference" version="4.0">
+<class name="RDVertexAttribute" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml
index 6312cd18aa..6fcb79b5fe 100644
--- a/doc/classes/RandomNumberGenerator.xml
+++ b/doc/classes/RandomNumberGenerator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RandomNumberGenerator" inherits="Reference" version="4.0">
+<class name="RandomNumberGenerator" inherits="RefCounted" version="4.0">
<brief_description>
A class for generating pseudo-random numbers.
</brief_description>
diff --git a/doc/classes/RefCounted.xml b/doc/classes/RefCounted.xml
new file mode 100644
index 0000000000..cf96514203
--- /dev/null
+++ b/doc/classes/RefCounted.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="RefCounted" inherits="Object" version="4.0">
+ <brief_description>
+ Base class for reference-counted objects.
+ </brief_description>
+ <description>
+ Base class for any object that keeps a reference count. [Resource] and many other helper objects inherit this class.
+ Unlike other [Object] types, References keep an internal reference counter so that they are automatically released when no longer in use, and only then. References therefore do not need to be freed manually with [method Object.free].
+ In the vast majority of use cases, instantiating and using [RefCounted]-derived types is all you need to do. The methods provided in this class are only for advanced users, and can cause issues if misused.
+ [b]Note:[/b] In C#, references will not be freed instantly after they are no longer in use. Instead, garbage collection will run periodically and will free references that are no longer in use. This means that unused references will linger on for a while before being removed.
+ </description>
+ <tutorials>
+ <link title="When and how to avoid using nodes for everything">https://docs.godotengine.org/en/latest/getting_started/workflow/best_practices/node_alternatives.html</link>
+ </tutorials>
+ <methods>
+ <method name="init_ref">
+ <return type="bool">
+ </return>
+ <description>
+ Initializes the internal reference counter. Use this only if you really know what you are doing.
+ Returns whether the initialization was successful.
+ </description>
+ </method>
+ <method name="reference">
+ <return type="bool">
+ </return>
+ <description>
+ Increments the internal reference counter. Use this only if you really know what you are doing.
+ Returns [code]true[/code] if the increment was successful, [code]false[/code] otherwise.
+ </description>
+ </method>
+ <method name="unreference">
+ <return type="bool">
+ </return>
+ <description>
+ Decrements the internal reference counter. Use this only if you really know what you are doing.
+ Returns [code]true[/code] if the decrement was successful, [code]false[/code] otherwise.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/Reference.xml b/doc/classes/Reference.xml
deleted file mode 100644
index 724d2db924..0000000000
--- a/doc/classes/Reference.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Reference" inherits="Object" version="4.0">
- <brief_description>
- Base class for reference-counted objects.
- </brief_description>
- <description>
- Base class for any object that keeps a reference count. [Resource] and many other helper objects inherit this class.
- Unlike other [Object] types, References keep an internal reference counter so that they are automatically released when no longer in use, and only then. References therefore do not need to be freed manually with [method Object.free].
- In the vast majority of use cases, instantiating and using [Reference]-derived types is all you need to do. The methods provided in this class are only for advanced users, and can cause issues if misused.
- [b]Note:[/b] In C#, references will not be freed instantly after they are no longer in use. Instead, garbage collection will run periodically and will free references that are no longer in use. This means that unused references will linger on for a while before being removed.
- </description>
- <tutorials>
- <link title="When and how to avoid using nodes for everything">https://docs.godotengine.org/en/latest/getting_started/workflow/best_practices/node_alternatives.html</link>
- </tutorials>
- <methods>
- <method name="init_ref">
- <return type="bool">
- </return>
- <description>
- Initializes the internal reference counter. Use this only if you really know what you are doing.
- Returns whether the initialization was successful.
- </description>
- </method>
- <method name="reference">
- <return type="bool">
- </return>
- <description>
- Increments the internal reference counter. Use this only if you really know what you are doing.
- Returns [code]true[/code] if the increment was successful, [code]false[/code] otherwise.
- </description>
- </method>
- <method name="unreference">
- <return type="bool">
- </return>
- <description>
- Decrements the internal reference counter. Use this only if you really know what you are doing.
- Returns [code]true[/code] if the decrement was successful, [code]false[/code] otherwise.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml
index cd08778c89..13df17cd22 100644
--- a/doc/classes/ReflectionProbe.xml
+++ b/doc/classes/ReflectionProbe.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Captures its surroundings as a cubemap, and stores versions of it with increasing levels of blur to simulate different material roughnesses.
- The [ReflectionProbe] is used to create high-quality reflections at the cost of performance. It can be combined with [GIProbe]s and Screen Space Reflections to achieve high quality reflections. [ReflectionProbe]s render all objects within their [member cull_mask], so updating them can be quite expensive. It is best to update them once with the important static objects and then leave them.
+ The [ReflectionProbe] is used to create high-quality reflections at the cost of performance. It can be combined with [VoxelGI]s and Screen Space Reflections to achieve high quality reflections. [ReflectionProbe]s render all objects within their [member cull_mask], so updating them can be quite expensive. It is best to update them once with the important static objects and then leave them.
</description>
<tutorials>
<link title="Reflection probes">https://docs.godotengine.org/en/latest/tutorials/3d/reflection_probes.html</link>
diff --git a/doc/classes/RemoteTransform3D.xml b/doc/classes/RemoteTransform3D.xml
index bd3da2aea9..453177496f 100644
--- a/doc/classes/RemoteTransform3D.xml
+++ b/doc/classes/RemoteTransform3D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RemoteTransform3D" inherits="Node3D" version="4.0">
<brief_description>
- RemoteTransform3D pushes its own [Transform] to another [Node3D] derived Node in the scene.
+ RemoteTransform3D pushes its own [Transform3D] to another [Node3D] derived Node in the scene.
</brief_description>
<description>
- RemoteTransform3D pushes its own [Transform] to another [Node3D] derived Node (called the remote node) in the scene.
+ RemoteTransform3D pushes its own [Transform3D] to another [Node3D] derived Node (called the remote node) in the scene.
It can be set to update another Node's position, rotation and/or scale. It can use either global or local coordinates.
</description>
<tutorials>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 638b0bb297..9b9644093f 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -130,10 +130,10 @@
</return>
<argument index="0" name="camera" type="RID">
</argument>
- <argument index="1" name="transform" type="Transform">
+ <argument index="1" name="transform" type="Transform3D">
</argument>
<description>
- Sets [Transform] of camera.
+ Sets [Transform3D] of camera.
</description>
</method>
<method name="camera_set_use_vertical_aspect">
@@ -1175,17 +1175,6 @@
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
- <method name="instance_geometry_set_as_instance_lod">
- <return type="void">
- </return>
- <argument index="0" name="instance" type="RID">
- </argument>
- <argument index="1" name="as_lod_of_instance" type="RID">
- </argument>
- <description>
- Not implemented in Godot 3.x.
- </description>
- </method>
<method name="instance_geometry_set_cast_shadows_setting">
<return type="void">
</return>
@@ -1197,45 +1186,45 @@
Sets the shadow casting setting to one of [enum ShadowCastingSetting]. Equivalent to [member GeometryInstance3D.cast_shadow].
</description>
</method>
- <method name="instance_geometry_set_draw_range">
+ <method name="instance_geometry_set_flag">
<return type="void">
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="min" type="float">
- </argument>
- <argument index="2" name="max" type="float">
- </argument>
- <argument index="3" name="min_margin" type="float">
+ <argument index="1" name="flag" type="int" enum="RenderingServer.InstanceFlags">
</argument>
- <argument index="4" name="max_margin" type="float">
+ <argument index="2" name="enabled" type="bool">
</argument>
<description>
- Not implemented in Godot 3.x.
+ Sets the flag for a given [enum InstanceFlags]. See [enum InstanceFlags] for more details.
</description>
</method>
- <method name="instance_geometry_set_flag">
+ <method name="instance_geometry_set_material_override">
<return type="void">
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="flag" type="int" enum="RenderingServer.InstanceFlags">
- </argument>
- <argument index="2" name="enabled" type="bool">
+ <argument index="1" name="material" type="RID">
</argument>
<description>
- Sets the flag for a given [enum InstanceFlags]. See [enum InstanceFlags] for more details.
+ Sets a material that will override the material for all surfaces on the mesh associated with this instance. Equivalent to [member GeometryInstance3D.material_override].
</description>
</method>
- <method name="instance_geometry_set_material_override">
+ <method name="instance_geometry_set_visibility_range">
<return type="void">
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="material" type="RID">
+ <argument index="1" name="min" type="float">
+ </argument>
+ <argument index="2" name="max" type="float">
+ </argument>
+ <argument index="3" name="min_margin" type="float">
+ </argument>
+ <argument index="4" name="max_margin" type="float">
</argument>
<description>
- Sets a material that will override the material for all surfaces on the mesh associated with this instance. Equivalent to [member GeometryInstance3D.material_override].
+ Sets the visibility range values for the given geometry instance. Equivalent to [member GeometryInstance3D.visibility_range_begin] and related properties.
</description>
</method>
<method name="instance_set_base">
@@ -1335,12 +1324,23 @@
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="transform" type="Transform">
+ <argument index="1" name="transform" type="Transform3D">
</argument>
<description>
Sets the world space transform of the instance. Equivalent to [member Node3D.transform].
</description>
</method>
+ <method name="instance_set_visibility_parent">
+ <return type="void">
+ </return>
+ <argument index="0" name="instance" type="RID">
+ </argument>
+ <argument index="1" name="parent" type="RID">
+ </argument>
+ <description>
+ Sets the visibility parent for the given instance. Equivalent to [member Node3D.visibility_parent].
+ </description>
+ </method>
<method name="instance_set_visible">
<return type="void">
</return>
@@ -1894,14 +1894,14 @@
</description>
</method>
<method name="multimesh_instance_get_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="multimesh" type="RID">
</argument>
<argument index="1" name="index" type="int">
</argument>
<description>
- Returns the [Transform] of the specified instance.
+ Returns the [Transform3D] of the specified instance.
</description>
</method>
<method name="multimesh_instance_get_transform_2d" qualifiers="const">
@@ -1948,10 +1948,10 @@
</argument>
<argument index="1" name="index" type="int">
</argument>
- <argument index="2" name="transform" type="Transform">
+ <argument index="2" name="transform" type="Transform3D">
</argument>
<description>
- Sets the [Transform] for this instance. Equivalent to [method MultiMesh.set_instance_transform].
+ Sets the [Transform3D] for this instance. Equivalent to [method MultiMesh.set_instance_transform].
</description>
</method>
<method name="multimesh_instance_set_transform_2d">
@@ -2142,10 +2142,10 @@
</return>
<argument index="0" name="particles" type="RID">
</argument>
- <argument index="1" name="transform" type="Transform">
+ <argument index="1" name="transform" type="Transform3D">
</argument>
<description>
- Sets the [Transform] that will be used by the particles when they first emit.
+ Sets the [Transform3D] that will be used by the particles when they first emit.
</description>
</method>
<method name="particles_set_emitting">
@@ -2590,14 +2590,14 @@
</description>
</method>
<method name="skeleton_bone_get_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="skeleton" type="RID">
</argument>
<argument index="1" name="bone" type="int">
</argument>
<description>
- Returns the [Transform] set for a specific bone of this skeleton.
+ Returns the [Transform3D] set for a specific bone of this skeleton.
</description>
</method>
<method name="skeleton_bone_get_transform_2d" qualifiers="const">
@@ -2618,10 +2618,10 @@
</argument>
<argument index="1" name="bone" type="int">
</argument>
- <argument index="2" name="transform" type="Transform">
+ <argument index="2" name="transform" type="Transform3D">
</argument>
<description>
- Sets the [Transform] for a specific bone of this skeleton.
+ Sets the [Transform3D] for a specific bone of this skeleton.
</description>
</method>
<method name="skeleton_bone_set_transform_2d">
@@ -3267,7 +3267,7 @@
Use [Transform2D] to store MultiMesh transform.
</constant>
<constant name="MULTIMESH_TRANSFORM_3D" value="1" enum="MultimeshTransformFormat">
- Use [Transform] to store MultiMesh transform.
+ Use [Transform3D] to store MultiMesh transform.
</constant>
<constant name="LIGHT_DIRECTIONAL" value="0" enum="LightType">
Is a directional (sun) light.
@@ -3388,7 +3388,7 @@
<constant name="PARTICLES_DRAW_ORDER_LIFETIME" value="1" enum="ParticlesDrawOrder">
Sort particles based on their lifetime.
</constant>
- <constant name="PARTICLES_DRAW_ORDER_VIEW_DEPTH" value="2" enum="ParticlesDrawOrder">
+ <constant name="PARTICLES_DRAW_ORDER_VIEW_DEPTH" value="3" enum="ParticlesDrawOrder">
Sort particles based on their distance to the camera.
</constant>
<constant name="VIEWPORT_UPDATE_DISABLED" value="0" enum="ViewportUpdateMode">
@@ -3477,14 +3477,14 @@
<constant name="VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER" value="5" enum="ViewportDebugDraw">
Normal buffer is drawn instead of regular scene so you can see the per-pixel normals that will be used by post-processing effects.
</constant>
- <constant name="VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO" value="6" enum="ViewportDebugDraw">
- Objects are displayed with only the albedo value from [GIProbe]s.
+ <constant name="VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO" value="6" enum="ViewportDebugDraw">
+ Objects are displayed with only the albedo value from [VoxelGI]s.
</constant>
- <constant name="VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING" value="7" enum="ViewportDebugDraw">
- Objects are displayed with only the lighting value from [GIProbe]s.
+ <constant name="VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING" value="7" enum="ViewportDebugDraw">
+ Objects are displayed with only the lighting value from [VoxelGI]s.
</constant>
- <constant name="VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION" value="8" enum="ViewportDebugDraw">
- Objects are displayed with only the emission color from [GIProbe]s.
+ <constant name="VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION" value="8" enum="ViewportDebugDraw">
+ Objects are displayed with only the emission color from [VoxelGI]s.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS" value="9" enum="ViewportDebugDraw">
Draws the shadow atlas that stores shadows from [OmniLight3D]s and [SpotLight3D]s in the upper left quadrant of the [Viewport].
@@ -3694,8 +3694,8 @@
<constant name="INSTANCE_DECAL" value="8" enum="InstanceType">
The instance is a decal.
</constant>
- <constant name="INSTANCE_GI_PROBE" value="9" enum="InstanceType">
- The instance is a GI probe.
+ <constant name="INSTANCE_VOXEL_GI" value="9" enum="InstanceType">
+ The instance is a VoxelGI.
</constant>
<constant name="INSTANCE_LIGHTMAP" value="10" enum="InstanceType">
The instance is a lightmap.
diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml
index 2548f8d911..6edb3b1a11 100644
--- a/doc/classes/Resource.xml
+++ b/doc/classes/Resource.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Resource" inherits="Reference" version="4.0">
+<class name="Resource" inherits="RefCounted" version="4.0">
<brief_description>
Base class for all resources.
</brief_description>
<description>
- Resource is the base class for all Godot-specific resource types, serving primarily as data containers. Since they inherit from [Reference], resources are reference-counted and freed when no longer in use. They are also cached once loaded from disk, so that any further attempts to load a resource from a given path will return the same reference (all this in contrast to a [Node], which is not reference-counted and can be instanced from disk as many times as desired). Resources can be saved externally on disk or bundled into another object, such as a [Node] or another resource.
+ Resource is the base class for all Godot-specific resource types, serving primarily as data containers. Since they inherit from [RefCounted], resources are reference-counted and freed when no longer in use. They are also cached once loaded from disk, so that any further attempts to load a resource from a given path will return the same reference (all this in contrast to a [Node], which is not reference-counted and can be instanced from disk as many times as desired). Resources can be saved externally on disk or bundled into another object, such as a [Node] or another resource.
[b]Note:[/b] In C#, resources will not be freed instantly after they are no longer in use. Instead, garbage collection will run periodically and will free resources that are no longer in use. This means that unused resources will linger on for a while before being removed.
</description>
<tutorials>
@@ -27,6 +27,7 @@
<description>
Duplicates the resource, returning a new resource. By default, sub-resources are shared between resource copies for efficiency. This can be changed by passing [code]true[/code] to the [code]subresources[/code] argument which will copy the subresources.
[b]Note:[/b] If [code]subresources[/code] is [code]true[/code], this method will only perform a shallow copy. Nested resources within subresources will not be duplicated and will still be shared.
+ [b]Note:[/b] When duplicating a resource, only [code]export[/code]ed properties are copied. Other properties will be set to their default value in the new resource.
</description>
</method>
<method name="emit_changed">
diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml
index 9943f644cf..6abe5c813b 100644
--- a/doc/classes/ResourceFormatLoader.xml
+++ b/doc/classes/ResourceFormatLoader.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceFormatLoader" inherits="Reference" version="4.0">
+<class name="ResourceFormatLoader" inherits="RefCounted" version="4.0">
<brief_description>
Loads a specific resource type from a file.
</brief_description>
@@ -11,7 +11,7 @@
<tutorials>
</tutorials>
<methods>
- <method name="get_dependencies" qualifiers="virtual">
+ <method name="_get_dependencies" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="path" type="String">
@@ -23,14 +23,14 @@
[b]Note:[/b] Custom resource types defined by scripts aren't known by the [ClassDB], so you might just return [code]"Resource"[/code] for them.
</description>
</method>
- <method name="get_recognized_extensions" qualifiers="virtual">
+ <method name="_get_recognized_extensions" qualifiers="virtual">
<return type="PackedStringArray">
</return>
<description>
Gets the list of extensions for files this loader is able to read.
</description>
</method>
- <method name="get_resource_type" qualifiers="virtual">
+ <method name="_get_resource_type" qualifiers="virtual">
<return type="String">
</return>
<argument index="0" name="path" type="String">
@@ -40,7 +40,7 @@
[b]Note:[/b] Custom resource types defined by scripts aren't known by the [ClassDB], so you might just return [code]"Resource"[/code] for them.
</description>
</method>
- <method name="handles_type" qualifiers="virtual">
+ <method name="_handles_type" qualifiers="virtual">
<return type="bool">
</return>
<argument index="0" name="typename" type="StringName">
@@ -50,7 +50,7 @@
[b]Note:[/b] Custom resource types defined by scripts aren't known by the [ClassDB], so you might just handle [code]"Resource"[/code] for them.
</description>
</method>
- <method name="load" qualifiers="virtual">
+ <method name="_load" qualifiers="virtual">
<return type="Variant">
</return>
<argument index="0" name="path" type="String">
@@ -66,7 +66,7 @@
The [code]cache_mode[/code] property defines whether and how the cache should be used or updated when loading the resource. See [enum CacheMode] for details.
</description>
</method>
- <method name="rename_dependencies" qualifiers="virtual">
+ <method name="_rename_dependencies" qualifiers="virtual">
<return type="int">
</return>
<argument index="0" name="path" type="String">
diff --git a/doc/classes/ResourceFormatSaver.xml b/doc/classes/ResourceFormatSaver.xml
index 69f8b43898..df71e05d02 100644
--- a/doc/classes/ResourceFormatSaver.xml
+++ b/doc/classes/ResourceFormatSaver.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceFormatSaver" inherits="Reference" version="4.0">
+<class name="ResourceFormatSaver" inherits="RefCounted" version="4.0">
<brief_description>
Saves a specific resource type to a file.
</brief_description>
@@ -10,16 +10,16 @@
<tutorials>
</tutorials>
<methods>
- <method name="get_recognized_extensions" qualifiers="virtual">
+ <method name="_get_recognized_extensions" qualifiers="virtual">
<return type="PackedStringArray">
</return>
<argument index="0" name="resource" type="Resource">
</argument>
<description>
- Returns the list of extensions available for saving the resource object, provided it is recognized (see [method recognize]).
+ Returns the list of extensions available for saving the resource object, provided it is recognized (see [method _recognize]).
</description>
</method>
- <method name="recognize" qualifiers="virtual">
+ <method name="_recognize" qualifiers="virtual">
<return type="bool">
</return>
<argument index="0" name="resource" type="Resource">
@@ -28,7 +28,7 @@
Returns whether the given resource object can be saved by this saver.
</description>
</method>
- <method name="save" qualifiers="virtual">
+ <method name="_save" qualifiers="virtual">
<return type="int">
</return>
<argument index="0" name="path" type="String">
diff --git a/doc/classes/ResourceImporter.xml b/doc/classes/ResourceImporter.xml
index 0475d2c94d..59900b1b73 100644
--- a/doc/classes/ResourceImporter.xml
+++ b/doc/classes/ResourceImporter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceImporter" inherits="Reference" version="4.0">
+<class name="ResourceImporter" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml
index ecde5754f9..437b0ce730 100644
--- a/doc/classes/ResourceSaver.xml
+++ b/doc/classes/ResourceSaver.xml
@@ -49,7 +49,7 @@
Do not save editor-specific metadata (identified by their [code]__editor[/code] prefix).
</constant>
<constant name="FLAG_SAVE_BIG_ENDIAN" value="16" enum="SaverFlags">
- Save as big endian (see [member File.endian_swap]).
+ Save as big endian (see [member File.big_endian]).
</constant>
<constant name="FLAG_COMPRESS" value="32" enum="SaverFlags">
Compress the resource on save using [constant File.COMPRESSION_ZSTD]. Only available for binary resource types.
diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml
index ed375a8b1e..237317daf1 100644
--- a/doc/classes/RigidBody2D.xml
+++ b/doc/classes/RigidBody2D.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties.
- A RigidBody2D has 4 behavior [member mode]s: Rigid, Static, Character, and Kinematic.
+ A RigidBody2D has 4 behavior [member mode]s: Dynamic, Static, DynamicLocked, and Kinematic.
[b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state.
Please also keep in mind that physics bodies manage their own transform which overwrites the ones you set. So any direct or indirect transformation (including scaling of the node or its parent) will be visible in the editor only, and immediately reset at runtime.
If you need to override the default physics behavior or add a transformation at runtime, you can write a custom force integration. See [member custom_integrator].
@@ -100,21 +100,6 @@
Sets the body's velocity on the given axis. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior.
</description>
</method>
- <method name="test_motion">
- <return type="bool">
- </return>
- <argument index="0" name="motion" type="Vector2">
- </argument>
- <argument index="1" name="infinite_inertia" type="bool" default="true">
- </argument>
- <argument index="2" name="margin" type="float" default="0.08">
- </argument>
- <argument index="3" name="result" type="PhysicsTestMotionResult2D" default="null">
- </argument>
- <description>
- Returns [code]true[/code] if a collision would result from moving in the given vector. [code]margin[/code] increases the size of the shapes involved in the collision detection, and [code]result[/code] is an object of type [PhysicsTestMotionResult2D], which contains additional information about the collision (should there be one).
- </description>
- </method>
</methods>
<members>
<member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp" default="-1.0">
@@ -132,7 +117,6 @@
</member>
<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true">
If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping].
- [b]Note:[/b] A RigidBody2D will never enter sleep mode automatically if its [member mode] is [constant MODE_CHARACTER]. It can still be put to sleep manually by setting its [member sleeping] property to [code]true[/code].
</member>
<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false">
If [code]true[/code], the body will emit signals when it collides with another RigidBody2D. See also [member contacts_reported].
@@ -193,7 +177,7 @@
</description>
</signal>
<signal name="body_shape_entered">
- <argument index="0" name="body_id" type="int">
+ <argument index="0" name="body_rid" type="RID">
</argument>
<argument index="1" name="body" type="Node">
</argument>
@@ -210,7 +194,7 @@
</description>
</signal>
<signal name="body_shape_exited">
- <argument index="0" name="body_id" type="int">
+ <argument index="0" name="body_rid" type="RID">
</argument>
<argument index="1" name="body" type="Node">
</argument>
@@ -234,17 +218,17 @@
</signal>
</signals>
<constants>
- <constant name="MODE_RIGID" value="0" enum="Mode">
- Rigid mode. The body behaves as a physical object. It collides with other bodies and responds to forces applied to it. This is the default mode.
+ <constant name="MODE_DYNAMIC" value="0" enum="Mode">
+ Dynamic body mode. This is the default mode of a rigid body. It is affected by forces, and can move, rotate, and be affected by user code.
</constant>
<constant name="MODE_STATIC" value="1" enum="Mode">
- Static mode. The body behaves like a [StaticBody2D] and does not move.
+ Static body mode. The body behaves like a [StaticBody2D], and must be moved by code.
</constant>
- <constant name="MODE_CHARACTER" value="2" enum="Mode">
- Character mode. Similar to [constant MODE_RIGID], but the body can not rotate.
+ <constant name="MODE_DYNAMIC_LOCKED" value="2" enum="Mode">
+ Locked dynamic body mode. Similar to [constant MODE_DYNAMIC], but the body can not rotate.
</constant>
<constant name="MODE_KINEMATIC" value="3" enum="Mode">
- Kinematic mode. The body behaves like a [KinematicBody2D], and must be moved by code.
+ Kinematic body mode. The body behaves like a [StaticBody2D] with [member StaticBody2D.kinematic_motion] enabled, and must be moved by user code.
</constant>
<constant name="CCD_MODE_DISABLED" value="0" enum="CCDMode">
Continuous collision detection disabled. This is the fastest way to detect body collisions, but can miss small, fast-moving objects.
diff --git a/doc/classes/RigidBody3D.xml b/doc/classes/RigidBody3D.xml
index 1c6c8852a9..e3349169ff 100644
--- a/doc/classes/RigidBody3D.xml
+++ b/doc/classes/RigidBody3D.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
This is the node that implements full 3D physics. This means that you do not control a RigidBody3D directly. Instead, you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc.
- A RigidBody3D has 4 behavior [member mode]s: Rigid, Static, Character, and Kinematic.
+ A RigidBody3D has 4 behavior [member mode]s: Dynamic, Static, DynamicLocked, and Kinematic.
[b]Note:[/b] Don't change a RigidBody3D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed Hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop may result in strange behavior. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state.
If you need to override the default physics behavior, you can write a custom force integration function. See [member custom_integrator].
With Bullet physics (the default), the center of mass is the RigidBody3D center. With GodotPhysics, the center of mass is the average of the [CollisionShape3D] centers.
@@ -86,15 +86,6 @@
Applies a torque impulse which will be affected by the body mass and shape. This will rotate the body around the [code]impulse[/code] vector passed.
</description>
</method>
- <method name="get_axis_lock" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
- </argument>
- <description>
- Returns [code]true[/code] if the specified linear or rotational axis is locked.
- </description>
- </method>
<method name="get_colliding_bodies" qualifiers="const">
<return type="Array">
</return>
@@ -103,24 +94,13 @@
[b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of collisions is updated once per frame and before the physics step. Consider using signals instead.
</description>
</method>
- <method name="get_inverse_inertia_tensor">
+ <method name="get_inverse_inertia_tensor" qualifiers="const">
<return type="Basis">
</return>
<description>
Returns the inverse inertia tensor basis. This is used to calculate the angular acceleration resulting from a torque applied to the [RigidBody3D].
</description>
</method>
- <method name="set_axis_lock">
- <return type="void">
- </return>
- <argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
- </argument>
- <argument index="1" name="lock" type="bool">
- </argument>
- <description>
- Locks the specified linear or rotational axis.
- </description>
- </method>
<method name="set_axis_velocity">
<return type="void">
</return>
@@ -139,27 +119,8 @@
<member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity" default="Vector3( 0, 0, 0 )">
RigidBody3D's rotational velocity.
</member>
- <member name="axis_lock_angular_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's rotation in the X axis.
- </member>
- <member name="axis_lock_angular_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's rotation in the Y axis.
- </member>
- <member name="axis_lock_angular_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's rotation in the Z axis.
- </member>
- <member name="axis_lock_linear_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's movement in the X axis.
- </member>
- <member name="axis_lock_linear_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's movement in the Y axis.
- </member>
- <member name="axis_lock_linear_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
- Lock the body's movement in the Z axis.
- </member>
<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true">
If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping].
- [b]Note:[/b] A RigidBody3D will never enter sleep mode automatically if its [member mode] is [constant MODE_CHARACTER]. It can still be put to sleep manually by setting its [member sleeping] property to [code]true[/code].
</member>
<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false">
If [code]true[/code], the RigidBody3D will emit signals when it collides with another RigidBody3D. See also [member contacts_reported].
@@ -217,7 +178,7 @@
</description>
</signal>
<signal name="body_shape_entered">
- <argument index="0" name="body_id" type="int">
+ <argument index="0" name="body_rid" type="RID">
</argument>
<argument index="1" name="body" type="Node">
</argument>
@@ -235,7 +196,7 @@
</description>
</signal>
<signal name="body_shape_exited">
- <argument index="0" name="body_id" type="int">
+ <argument index="0" name="body_rid" type="RID">
</argument>
<argument index="1" name="body" type="Node">
</argument>
@@ -260,17 +221,17 @@
</signal>
</signals>
<constants>
- <constant name="MODE_RIGID" value="0" enum="Mode">
- Rigid body mode. This is the "natural" state of a rigid body. It is affected by forces, and can move, rotate, and be affected by user code.
+ <constant name="MODE_DYNAMIC" value="0" enum="Mode">
+ Dynamic body mode. This is the default mode of a rigid body. It is affected by forces, and can move, rotate, and be affected by user code.
</constant>
<constant name="MODE_STATIC" value="1" enum="Mode">
- Static mode. The body behaves like a [StaticBody3D], and can only move by user code.
+ Static body mode. The body behaves like a [StaticBody3D], and can only move by user code.
</constant>
- <constant name="MODE_CHARACTER" value="2" enum="Mode">
- Character body mode. This behaves like a rigid body, but can not rotate.
+ <constant name="MODE_DYNAMIC_LOCKED" value="2" enum="Mode">
+ Locked dynamic body mode. Similar to [constant MODE_DYNAMIC], but the body can not rotate.
</constant>
<constant name="MODE_KINEMATIC" value="3" enum="Mode">
- Kinematic body mode. The body behaves like a [KinematicBody3D], and can only move by user code.
+ Kinematic body mode. The body behaves like a [StaticBody3D] with [member StaticBody3D.kinematic_motion] enabled, and can only move by user code.
</constant>
</constants>
</class>
diff --git a/doc/classes/SceneState.xml b/doc/classes/SceneState.xml
index abc429d5fe..f9e0ef76b9 100644
--- a/doc/classes/SceneState.xml
+++ b/doc/classes/SceneState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SceneState" inherits="Reference" version="4.0">
+<class name="SceneState" inherits="RefCounted" version="4.0">
<brief_description>
A script interface to a scene file's data.
</brief_description>
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index 06800082cb..7a15153fc2 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -207,6 +207,7 @@
Quits the application at the end of the current iteration. Argument [code]exit_code[/code] can optionally be given (defaulting to 0) to customize the exit status code.
By convention, an exit code of [code]0[/code] indicates success whereas a non-zero exit code indicates an error.
For portability reasons, the exit code should be set between 0 and 125 (inclusive).
+ [b]Note:[/b] On iOS this method doesn't work. Instead, as recommended by the iOS Human Interface Guidelines, the user is expected to close apps via the Home button.
</description>
</method>
<method name="reload_current_scene">
diff --git a/doc/classes/SceneTreeTimer.xml b/doc/classes/SceneTreeTimer.xml
index b223bf6821..4eef754345 100644
--- a/doc/classes/SceneTreeTimer.xml
+++ b/doc/classes/SceneTreeTimer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SceneTreeTimer" inherits="Reference" version="4.0">
+<class name="SceneTreeTimer" inherits="RefCounted" version="4.0">
<brief_description>
One-shot timer.
</brief_description>
diff --git a/doc/classes/ScriptEditor.xml b/doc/classes/ScriptEditor.xml
index 28620bd29b..31dbf7453f 100644
--- a/doc/classes/ScriptEditor.xml
+++ b/doc/classes/ScriptEditor.xml
@@ -9,30 +9,6 @@
<tutorials>
</tutorials>
<methods>
- <method name="can_drop_data_fw" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="point" type="Vector2">
- </argument>
- <argument index="1" name="data" type="Variant">
- </argument>
- <argument index="2" name="from" type="Control">
- </argument>
- <description>
- </description>
- </method>
- <method name="drop_data_fw">
- <return type="void">
- </return>
- <argument index="0" name="point" type="Vector2">
- </argument>
- <argument index="1" name="data" type="Variant">
- </argument>
- <argument index="2" name="from" type="Control">
- </argument>
- <description>
- </description>
- </method>
<method name="get_current_editor" qualifiers="const">
<return type="ScriptEditorBase">
</return>
@@ -47,16 +23,6 @@
Returns a [Script] that is currently active in editor.
</description>
</method>
- <method name="get_drag_data_fw">
- <return type="Variant">
- </return>
- <argument index="0" name="point" type="Vector2">
- </argument>
- <argument index="1" name="from" type="Control">
- </argument>
- <description>
- </description>
- </method>
<method name="get_open_script_editors" qualifiers="const">
<return type="Array">
</return>
diff --git a/doc/classes/ScriptEditorBase.xml b/doc/classes/ScriptEditorBase.xml
index ee498de302..a135062bd8 100644
--- a/doc/classes/ScriptEditorBase.xml
+++ b/doc/classes/ScriptEditorBase.xml
@@ -9,7 +9,7 @@
<tutorials>
</tutorials>
<methods>
- <method name="add_syntax_highlighter" qualifiers="virtual">
+ <method name="_add_syntax_highlighter" qualifiers="virtual">
<return type="void">
</return>
<argument index="0" name="highlighter" type="Object">
@@ -18,6 +18,13 @@
Adds a [EditorSyntaxHighlighter] to the open script.
</description>
</method>
+ <method name="get_base_editor" qualifiers="const">
+ <return type="Control">
+ </return>
+ <description>
+ Returns the underlying [Control] used for editing scripts. This can be either [CodeEdit] (for text scripts) or [GraphEdit] (for visual scripts).
+ </description>
+ </method>
</methods>
<signals>
<signal name="edited_script_changed">
diff --git a/doc/classes/ScrollContainer.xml b/doc/classes/ScrollContainer.xml
index 40e29ac74b..60f3106b4b 100644
--- a/doc/classes/ScrollContainer.xml
+++ b/doc/classes/ScrollContainer.xml
@@ -11,6 +11,15 @@
<tutorials>
</tutorials>
<methods>
+ <method name="ensure_control_visible">
+ <return type="void">
+ </return>
+ <argument index="0" name="control" type="Control">
+ </argument>
+ <description>
+ Ensures the given [code]control[/code] is visible (must be a direct or indirect child of the ScrollContainer). Used by [member follow_focus].
+ </description>
+ </method>
<method name="get_h_scrollbar">
<return type="HScrollBar">
</return>
diff --git a/doc/classes/Semaphore.xml b/doc/classes/Semaphore.xml
index f311e1c72f..e8b405e52a 100644
--- a/doc/classes/Semaphore.xml
+++ b/doc/classes/Semaphore.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Semaphore" inherits="Reference" version="4.0">
+<class name="Semaphore" inherits="RefCounted" version="4.0">
<brief_description>
A synchronization semaphore.
</brief_description>
diff --git a/doc/classes/Skeleton2D.xml b/doc/classes/Skeleton2D.xml
index 0ddbac9ba4..6665a4a9f6 100644
--- a/doc/classes/Skeleton2D.xml
+++ b/doc/classes/Skeleton2D.xml
@@ -10,6 +10,17 @@
<link title="2D skeletons">https://docs.godotengine.org/en/latest/tutorials/animation/2d_skeletons.html</link>
</tutorials>
<methods>
+ <method name="execute_modifications">
+ <return type="void">
+ </return>
+ <argument index="0" name="delta" type="float">
+ </argument>
+ <argument index="1" name="execution_mode" type="int">
+ </argument>
+ <description>
+ Executes all the modifications on the [SkeletonModificationStack2D], if the Skeleton3D has one assigned.
+ </description>
+ </method>
<method name="get_bone">
<return type="Bone2D">
</return>
@@ -26,6 +37,22 @@
Returns the number of [Bone2D] nodes in the node hierarchy parented by Skeleton2D.
</description>
</method>
+ <method name="get_bone_local_pose_override">
+ <return type="Transform2D">
+ </return>
+ <argument index="0" name="bone_idx" type="int">
+ </argument>
+ <description>
+ Returns the local pose override transform for [code]bone_idx[/code].
+ </description>
+ </method>
+ <method name="get_modification_stack" qualifiers="const">
+ <return type="SkeletonModificationStack2D">
+ </return>
+ <description>
+ Returns the [SkeletonModificationStack2D] attached to this skeleton, if one exists.
+ </description>
+ </method>
<method name="get_skeleton" qualifiers="const">
<return type="RID">
</return>
@@ -33,10 +60,37 @@
Returns the [RID] of a Skeleton2D instance.
</description>
</method>
+ <method name="set_bone_local_pose_override">
+ <return type="void">
+ </return>
+ <argument index="0" name="bone_idx" type="int">
+ </argument>
+ <argument index="1" name="override_pose" type="Transform2D">
+ </argument>
+ <argument index="2" name="strength" type="float">
+ </argument>
+ <argument index="3" name="persistent" type="bool">
+ </argument>
+ <description>
+ Sets the local pose transform, [code]pose[/code], for the bone at [code]bone_idx[/code].
+ [code]amount[/code] is the interpolation strengh that will be used when applying the pose, and [code]persistent[/code] determines if the applied pose will remain.
+ [b]Note:[/b] The pose transform needs to be a local transform relative to the [Bone2D] node at [code]bone_idx[/code]!
+ </description>
+ </method>
+ <method name="set_modification_stack">
+ <return type="void">
+ </return>
+ <argument index="0" name="modification_stack" type="SkeletonModificationStack2D">
+ </argument>
+ <description>
+ Sets the [SkeletonModificationStack2D] attached to this skeleton.
+ </description>
+ </method>
</methods>
<signals>
<signal name="bone_setup_changed">
<description>
+ Emitted when the [Bone2D] setup attached to this skeletons changes. This is primarily used internally within the skeleton.
</description>
</signal>
</signals>
diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml
index 0b278d7d25..d8b35ad272 100644
--- a/doc/classes/Skeleton3D.xml
+++ b/doc/classes/Skeleton3D.xml
@@ -22,21 +22,10 @@
Adds a bone, with name [code]name[/code]. [method get_bone_count] will become the bone index.
</description>
</method>
- <method name="bind_child_node_to_bone">
- <return type="void">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="node" type="Node">
- </argument>
- <description>
- [i]Deprecated soon.[/i]
- </description>
- </method>
<method name="bone_transform_to_world_transform">
- <return type="Transform">
+ <return type="Transform3D">
</return>
- <argument index="0" name="bone_transform" type="Transform">
+ <argument index="0" name="bone_transform" type="Transform3D">
</argument>
<description>
Takes the given bone pose/transform and converts it to a world transform, relative to the [Skeleton3D] node.
@@ -74,7 +63,7 @@
</description>
</method>
<method name="get_bone_custom_pose" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
@@ -83,7 +72,7 @@
</description>
</method>
<method name="get_bone_global_pose" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
@@ -92,7 +81,7 @@
</description>
</method>
<method name="get_bone_global_pose_no_override" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
@@ -120,7 +109,7 @@
</description>
</method>
<method name="get_bone_pose" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
@@ -135,7 +124,7 @@
</description>
</method>
<method name="get_bone_rest" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
@@ -143,15 +132,6 @@
Returns the rest transform for a bone [code]bone_idx[/code].
</description>
</method>
- <method name="get_bound_child_nodes_to_bone" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- [i]Deprecated soon.[/i]
- </description>
- </method>
<method name="is_bone_rest_disabled" qualifiers="const">
<return type="bool">
</return>
@@ -219,7 +199,7 @@
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
- <argument index="1" name="custom_pose" type="Transform">
+ <argument index="1" name="custom_pose" type="Transform3D">
</argument>
<description>
Sets the custom pose transform, [code]custom_pose[/code], for the bone at [code]bone_idx[/code]. This pose is an addition to the bone rest pose.
@@ -242,7 +222,7 @@
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
- <argument index="1" name="pose" type="Transform">
+ <argument index="1" name="pose" type="Transform3D">
</argument>
<argument index="2" name="amount" type="float">
</argument>
@@ -281,7 +261,7 @@
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
- <argument index="1" name="pose" type="Transform">
+ <argument index="1" name="pose" type="Transform3D">
</argument>
<description>
Sets the pose transform for bone [code]bone_idx[/code].
@@ -293,23 +273,12 @@
</return>
<argument index="0" name="bone_idx" type="int">
</argument>
- <argument index="1" name="rest" type="Transform">
+ <argument index="1" name="rest" type="Transform3D">
</argument>
<description>
Sets the rest transform for bone [code]bone_idx[/code].
</description>
</method>
- <method name="unbind_child_node_from_bone">
- <return type="void">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="node" type="Node">
- </argument>
- <description>
- [i]Deprecated soon.[/i]
- </description>
- </method>
<method name="unparent_bone_and_rest">
<return type="void">
</return>
@@ -320,9 +289,9 @@
</description>
</method>
<method name="world_transform_to_bone_transform">
- <return type="Transform">
+ <return type="Transform3D">
</return>
- <argument index="0" name="world_transform" type="Transform">
+ <argument index="0" name="world_transform" type="Transform3D">
</argument>
<description>
Takes the given world transform, relative to the [Skeleton3D], and converts it to a bone pose/transform.
diff --git a/doc/classes/SkeletonIK3D.xml b/doc/classes/SkeletonIK3D.xml
index 5193109447..dccc45d0ec 100644
--- a/doc/classes/SkeletonIK3D.xml
+++ b/doc/classes/SkeletonIK3D.xml
@@ -46,13 +46,13 @@
</member>
<member name="override_tip_basis" type="bool" setter="set_override_tip_basis" getter="is_override_tip_basis" default="true">
</member>
- <member name="root_bone" type="StringName" setter="set_root_bone" getter="get_root_bone" default="@&quot;&quot;">
+ <member name="root_bone" type="StringName" setter="set_root_bone" getter="get_root_bone" default="&amp;&quot;&quot;">
</member>
- <member name="target" type="Transform" setter="set_target_transform" getter="get_target_transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ <member name="target" type="Transform3D" setter="set_target_transform" getter="get_target_transform" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
</member>
<member name="target_node" type="NodePath" setter="set_target_node" getter="get_target_node" default="NodePath(&quot;&quot;)">
</member>
- <member name="tip_bone" type="StringName" setter="set_tip_bone" getter="get_tip_bone" default="@&quot;&quot;">
+ <member name="tip_bone" type="StringName" setter="set_tip_bone" getter="get_tip_bone" default="&amp;&quot;&quot;">
</member>
<member name="use_magnet" type="bool" setter="set_use_magnet" getter="is_using_magnet" default="false">
</member>
diff --git a/doc/classes/SkeletonModification2D.xml b/doc/classes/SkeletonModification2D.xml
new file mode 100644
index 0000000000..8596dac76e
--- /dev/null
+++ b/doc/classes/SkeletonModification2D.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModification2D" inherits="Resource" version="4.0">
+ <brief_description>
+ A resource that operates on [Bone2D] nodes in a [Skeleton2D].
+ </brief_description>
+ <description>
+ This resource provides an interface that can be expanded so code that operates on [Bone2D] nodes in a [Skeleton2D] can be mixed and matched together to create complex interactions.
+ This is used to provide Godot with a flexible and powerful Inverse Kinematics solution that can be adapted for many different uses.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="_draw_editor_gizmo" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <description>
+ Used for drawing [b]editor-only[/b] modification gizmos. This function will only be called in the Godot editor and can be overriden to draw custom gizmos.
+ [b]Note:[/b] You will need to use the Skeleton2D from [method SkeletonModificationStack2D.get_skeleton] and it's draw functions, as the [SkeletonModification2D] resource cannot draw on its own.
+ </description>
+ </method>
+ <method name="_execute" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="delta" type="float">
+ </argument>
+ <description>
+ Executes the given modification. This is where the modification performs whatever function it is designed to do.
+ </description>
+ </method>
+ <method name="_setup_modification" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="modification_stack" type="SkeletonModificationStack2D">
+ </argument>
+ <description>
+ Called when the modification is setup. This is where the modification performs initialization.
+ </description>
+ </method>
+ <method name="clamp_angle">
+ <return type="float">
+ </return>
+ <argument index="0" name="angle" type="float">
+ </argument>
+ <argument index="1" name="min" type="float">
+ </argument>
+ <argument index="2" name="max" type="float">
+ </argument>
+ <argument index="3" name="invert" type="bool">
+ </argument>
+ <description>
+ Takes a angle and clamps it so it is within the passed-in [code]min[/code] and [code]max[/code] range. [code]invert[/code] will inversely clamp the angle, clamping it to the range outside of the given bounds.
+ </description>
+ </method>
+ <method name="get_editor_draw_gizmo" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether this modification will call [method _draw_editor_gizmo] in the Godot editor to draw modification-specific gizmos.
+ </description>
+ </method>
+ <method name="get_is_setup" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether this modification has been successfully setup or not.
+ </description>
+ </method>
+ <method name="get_modification_stack">
+ <return type="SkeletonModificationStack2D">
+ </return>
+ <description>
+ Returns the [SkeletonModificationStack2D] that this modification is bound to. Through the modification stack, you can access the Skeleton3D the modification is operating on.
+ </description>
+ </method>
+ <method name="set_editor_draw_gizmo">
+ <return type="void">
+ </return>
+ <argument index="0" name="draw_gizmo" type="bool">
+ </argument>
+ <description>
+ Sets whether this modification will call [method _draw_editor_gizmo] in the Godot editor to draw modification-specific gizmos.
+ </description>
+ </method>
+ <method name="set_is_setup">
+ <return type="void">
+ </return>
+ <argument index="0" name="is_setup" type="bool">
+ </argument>
+ <description>
+ Manually allows you to set the setup state of the modification. This function should only rarely be used, as the [SkeletonModificationStack2D] the modification is bound to should handle setting the modification up.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="enabled" type="bool" setter="set_enabled" getter="get_enabled" default="true">
+ If [code]true[/code], the modification's [method _execute] function will be called by the [SkeletonModificationStack2D].
+ </member>
+ <member name="execution_mode" type="int" setter="set_execution_mode" getter="get_execution_mode" default="0">
+ The execution mode for the modification. This tells the modification stack when to execute the modification. Some modifications have settings that are only availible in certain execution modes.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonModification2DCCDIK.xml b/doc/classes/SkeletonModification2DCCDIK.xml
new file mode 100644
index 0000000000..014d366a42
--- /dev/null
+++ b/doc/classes/SkeletonModification2DCCDIK.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModification2DCCDIK" inherits="SkeletonModification2D" version="4.0">
+ <brief_description>
+ A modification that uses CCDIK to manipulate a series of bones to reach a target in 2D.
+ </brief_description>
+ <description>
+ This [SkeletonModification2D] uses an algorithm called [b]C[/b]yclic [b]C[/b]oordinate [b]D[/b]escent [b]I[/b]nverse [b]K[/b]inematics, or CCDIK, to maniuplate a chain of bones in a [Skeleton2D] so it reaches a defined target.
+ CCDIK works by rotating a set of bones, typically called a "bone chain", on a single axis. Each bone is rotated to face the target from the tip (by default), which over a chain of bones allow it to rotate properly to reach the target. Because the bones only rotate on a single axis, CCDIK [i]can[/i] look more robotic than other IK solvers.
+ [b]Note:[/b] The CCDIK modifier has [code]ccdik_joints[/code], which are the data objects that hold the data for each joint in the CCDIK chain. This is different from a bone! CCDIK joints hold the data needed for each bone in the bone chain used by CCDIK.
+ CCDIK also fully supports angle constraints, allowing for more control over how a solution is met.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_ccdik_joint_bone2d_node" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the [Bone2D] node assigned to the CCDIK joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_ccdik_joint_bone_index" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the index of the [Bone2D] node assigned to the CCDIK joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_ccdik_joint_constraint_angle_invert" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns whether the CCDIK joint at [code]joint_idx[/code] uses an inverted joint constraint. See [method set_ccdik_joint_constraint_angle_invert] for details.
+ </description>
+ </method>
+ <method name="get_ccdik_joint_constraint_angle_max" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the maximum angle constraint for the joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_ccdik_joint_constraint_angle_min" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the minimum angle constraint for the joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_ccdik_joint_enable_constraint" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns whether angle constraints on the CCDIK joint at [code]joint_idx[/code] are enabled.
+ </description>
+ </method>
+ <method name="get_ccdik_joint_rotate_from_joint" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns whether the joint at [code]joint_idx[/code] is set to rotate from the joint, [code]true[/code], or to rotate from the tip, [code]false[/code]. The default is to rotate from the tip.
+ </description>
+ </method>
+ <method name="set_ccdik_joint_bone2d_node">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="bone2d_nodepath" type="NodePath">
+ </argument>
+ <description>
+ Sets the [Bone2D] node assigned to the CCDIK joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_ccdik_joint_bone_index">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="bone_idx" type="int">
+ </argument>
+ <description>
+ Sets the bone index, [code]bone_index[/code], of the CCDIK joint at [code]joint_idx[/code]. When possible, this will also update the [code]bone2d_node[/code] of the CCDIK joint based on data provided by the linked skeleton.
+ </description>
+ </method>
+ <method name="set_ccdik_joint_constraint_angle_invert">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="invert" type="bool">
+ </argument>
+ <description>
+ Sets whether the CCDIK joint at [code]joint_idx[/code] uses an inverted joint constraint.
+ An inverted joint constraint only constraints the CCDIK joint to the angles [i]outside of[/i] the inputted minimum and maximum angles. For this reason, it is referred to as an inverted joint constraint, as it constraints the joint to the outside of the inputted values.
+ </description>
+ </method>
+ <method name="set_ccdik_joint_constraint_angle_max">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="angle_max" type="float">
+ </argument>
+ <description>
+ Sets the maximum angle constraint for the joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_ccdik_joint_constraint_angle_min">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="angle_min" type="float">
+ </argument>
+ <description>
+ Sets the minimum angle constraint for the joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_ccdik_joint_enable_constraint">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="enable_constraint" type="bool">
+ </argument>
+ <description>
+ Determines whether angle constraints on the CCDIK joint at [code]joint_idx[/code] are enabled. When [code]true[/code], constraints will be enabled and taken into account when solving.
+ </description>
+ </method>
+ <method name="set_ccdik_joint_rotate_from_joint">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="rotate_from_joint" type="bool">
+ </argument>
+ <description>
+ Sets whether the joint at [code]joint_idx[/code] is set to rotate from the joint, [code]true[/code], or to rotate from the tip, [code]false[/code].
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="ccdik_data_chain_length" type="int" setter="set_ccdik_data_chain_length" getter="get_ccdik_data_chain_length" default="0">
+ The amount of CCDIK joints in the CCDIK modification.
+ </member>
+ <member name="target_nodepath" type="NodePath" setter="set_target_node" getter="get_target_node" default="NodePath(&quot;&quot;)">
+ The NodePath to the node that is the target for the CCDIK modification. This node is what the CCDIK chain will attempt to rotate the bone chain to.
+ </member>
+ <member name="tip_nodepath" type="NodePath" setter="set_tip_node" getter="get_tip_node" default="NodePath(&quot;&quot;)">
+ The end position of the CCDIK chain. Typically, this should be a child of a [Bone2D] node attached to the final [Bone2D] in the CCDIK chain.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonModification2DFABRIK.xml b/doc/classes/SkeletonModification2DFABRIK.xml
new file mode 100644
index 0000000000..62ab34b06f
--- /dev/null
+++ b/doc/classes/SkeletonModification2DFABRIK.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModification2DFABRIK" inherits="SkeletonModification2D" version="4.0">
+ <brief_description>
+ A modification that uses FABRIK to manipulate a series of [Bone2D] nodes to reach a target.
+ </brief_description>
+ <description>
+ This [SkeletonModification2D] uses an algorithm called [b]F[/b]orward [b]A[/b]nd [b]B[/b]ackward [b]R[/b]eaching [b]I[/b]nverse [b]K[/b]inematics, or FABRIK, to rotate a bone chain so that it reaches a target.
+ FABRIK works by knowing the positions and lengths of a series of bones, typically called a "bone chain". It first starts by running a forward pass, which places the final bone at the target's position. Then all other bones are moved towards the tip bone, so they stay at the defined bone length away. Then a backwards pass is performed, where the root/first bone in the FABRIK chain is placed back at the origin. then all other bones are moved so they stay at the defined bone length away. This positions the bone chain so that it reaches the target when possible, but all of the bones stay the correct length away from each other.
+ Because of how FABRIK works, it often gives more natural results than those seen in [SkeletonModification2DCCDIK]. FABRIK also supports angle constraints, which are fully taken into account when solving.
+ [b]Note:[/b] The FABRIK modifier has [code]fabrik_joints[/code], which are the data objects that hold the data for each joint in the FABRIK chain. This is different from [Bone2D] nodes! FABRIK joints hold the data needed for each [Bone2D] in the bone chain used by FABRIK.
+ To help control how the FABRIK joints move, a magnet vector can be passed, which can nudge the bones in a certain direction prior to solving, giving a level of control over the final result.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_fabrik_joint_bone2d_node" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the [Bone2D] node assigned to the FABRIK joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_fabrik_joint_bone_index" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the index of the [Bone2D] node assigned to the FABRIK joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_fabrik_joint_magnet_position" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the magnet position vector for the joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_fabrik_joint_use_target_rotation" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns whether the joint is using the target's rotation rather than allowing FABRIK to rotate the joint. This option only applies to the tip/final joint in the chain.
+ </description>
+ </method>
+ <method name="set_fabrik_joint_bone2d_node">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="bone2d_nodepath" type="NodePath">
+ </argument>
+ <description>
+ Sets the [Bone2D] node assigned to the FABRIK joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_fabrik_joint_bone_index">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="bone_idx" type="int">
+ </argument>
+ <description>
+ Sets the bone index, [code]bone_index[/code], of the FABRIK joint at [code]joint_idx[/code]. When possible, this will also update the [code]bone2d_node[/code] of the FABRIK joint based on data provided by the linked skeleton.
+ </description>
+ </method>
+ <method name="set_fabrik_joint_magnet_position">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="magnet_position" type="Vector2">
+ </argument>
+ <description>
+ Sets the magnet position vector for the joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_fabrik_joint_use_target_rotation">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="use_target_rotation" type="bool">
+ </argument>
+ <description>
+ Sets whether the joint at [code]joint_idx[/code] will use the target node's rotation rather than letting FABRIK rotate the node.
+ [b]Note:[/b] This option only works for the tip/final joint in the chain. For all other nodes, this option will be ignored.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="fabrik_data_chain_length" type="int" setter="set_fabrik_data_chain_length" getter="get_fabrik_data_chain_length" default="0">
+ The amount of FABRIK joints in the FABRIK modification.
+ </member>
+ <member name="target_nodepath" type="NodePath" setter="set_target_node" getter="get_target_node" default="NodePath(&quot;&quot;)">
+ The NodePath to the node that is the target for the FABRIK modification. This node is what the FABRIK chain will attempt to rotate the bone chain to.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonModification2DJiggle.xml b/doc/classes/SkeletonModification2DJiggle.xml
new file mode 100644
index 0000000000..7f8cf2d4d9
--- /dev/null
+++ b/doc/classes/SkeletonModification2DJiggle.xml
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModification2DJiggle" inherits="SkeletonModification2D" version="4.0">
+ <brief_description>
+ A modification that jiggles [Bone2D] nodes as they move towards a target.
+ </brief_description>
+ <description>
+ This modification moves a series of bones, typically called a bone chain, towards a target. What makes this modification special is that it calculates the velocity and acceleration for each bone in the bone chain, and runs a very light physics-like calculation using the inputted values. This allows the bones to overshoot the target and "jiggle" around. It can be configured to act more like a spring, or sway around like cloth might.
+ This modification is useful for adding additional motion to things like hair, the edges of clothing, and more. It has several settings to that allow control over how the joint moves when the target moves.
+ [b]Note:[/b] The Jiggle modifier has [code]jiggle_joints[/code], which are the data objects that hold the data for each joint in the Jiggle chain. This is different from than [Bone2D] nodes! Jiggle joints hold the data needed for each [Bone2D] in the bone chain used by the Jiggle modification.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_collision_mask" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the collision mask used by the Jiggle modifier when collisions are enabled.
+ </description>
+ </method>
+ <method name="get_jiggle_joint_bone2d_node" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the [Bone2D] node assigned to the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_jiggle_joint_bone_index" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the index of the [Bone2D] node assigned to the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_jiggle_joint_damping" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the amount of damping of the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_jiggle_joint_gravity" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns a [Vector2] representing the amount of gravity the Jiggle joint at [code]joint_idx[/code] is influenced by.
+ </description>
+ </method>
+ <method name="get_jiggle_joint_mass" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the amount of mass of the jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_jiggle_joint_override" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns a boolean that indiciates whether the joint at [code]joint_idx[/code] is overriding the default Jiggle joint data defined in the modification.
+ </description>
+ </method>
+ <method name="get_jiggle_joint_stiffness" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the stiffness of the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="get_jiggle_joint_use_gravity" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns a boolean that indiciates whether the joint at [code]joint_idx[/code] is using gravity or not.
+ </description>
+ </method>
+ <method name="get_use_colliders" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether the jiggle modifier is taking physics colliders into account when solving.
+ </description>
+ </method>
+ <method name="set_collision_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="collision_mask" type="int">
+ </argument>
+ <description>
+ Sets the collision mask that the Jiggle modifier will use when reacting to colliders, if the Jiggle modifier is set to take colliders into account.
+ </description>
+ </method>
+ <method name="set_jiggle_joint_bone2d_node">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="bone2d_node" type="NodePath">
+ </argument>
+ <description>
+ Sets the [Bone2D] node assigned to the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_jiggle_joint_bone_index">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="bone_idx" type="int">
+ </argument>
+ <description>
+ Sets the bone index, [code]bone_index[/code], of the Jiggle joint at [code]joint_idx[/code]. When possible, this will also update the [code]bone2d_node[/code] of the Jiggle joint based on data provided by the linked skeleton.
+ </description>
+ </method>
+ <method name="set_jiggle_joint_damping">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="damping" type="float">
+ </argument>
+ <description>
+ Sets the amount of dampening of the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_jiggle_joint_gravity">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="gravity" type="Vector2">
+ </argument>
+ <description>
+ Sets the gravity vector of the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_jiggle_joint_mass">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="mass" type="float">
+ </argument>
+ <description>
+ Sets the of mass of the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_jiggle_joint_override">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="override" type="bool">
+ </argument>
+ <description>
+ Sets whether the Jiggle joint at [code]joint_idx[/code] should override the default Jiggle joint settings. Setting this to [code]true[/code] will make the joint use its own settings rather than the default ones attached to the modification.
+ </description>
+ </method>
+ <method name="set_jiggle_joint_stiffness">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="stiffness" type="float">
+ </argument>
+ <description>
+ Sets the of stiffness of the Jiggle joint at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_jiggle_joint_use_gravity">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="use_gravity" type="bool">
+ </argument>
+ <description>
+ Sets whether the Jiggle joint at [code]joint_idx[/code] should use gravity.
+ </description>
+ </method>
+ <method name="set_use_colliders">
+ <return type="void">
+ </return>
+ <argument index="0" name="use_colliders" type="bool">
+ </argument>
+ <description>
+ If [code]true[/code], the Jiggle modifier will take colliders into account, keeping them from entering into these collision objects.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="damping" type="float" setter="set_damping" getter="get_damping" default="0.75">
+ The default amount of dampening applied to the Jiggle joints, if they are not overriden. Higher values lead to more of the calculated velocity being applied.
+ </member>
+ <member name="gravity" type="Vector2" setter="set_gravity" getter="get_gravity" default="Vector2( 0, 6 )">
+ The default amount of gravity applied to the Jiggle joints, if they are not overriden.
+ </member>
+ <member name="jiggle_data_chain_length" type="int" setter="set_jiggle_data_chain_length" getter="get_jiggle_data_chain_length" default="0">
+ The amount of Jiggle joints in the Jiggle modification.
+ </member>
+ <member name="mass" type="float" setter="set_mass" getter="get_mass" default="0.75">
+ The default amount of mass assigned to the Jiggle joints, if they are not overriden. Higher values lead to faster movements and more overshooting.
+ </member>
+ <member name="stiffness" type="float" setter="set_stiffness" getter="get_stiffness" default="3.0">
+ The default amount of stiffness assigned to the Jiggle joints, if they are not overriden. Higher values act more like springs, quickly moving into the correct position.
+ </member>
+ <member name="target_nodepath" type="NodePath" setter="set_target_node" getter="get_target_node" default="NodePath(&quot;&quot;)">
+ The NodePath to the node that is the target for the Jiggle modification. This node is what the Jiggle chain will attempt to rotate the bone chain to.
+ </member>
+ <member name="use_gravity" type="bool" setter="set_use_gravity" getter="get_use_gravity" default="false">
+ Whether the gravity vector, [member gravity], should be applied to the Jiggle joints, assuming they are not overriding the default settings.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonModification2DLookAt.xml b/doc/classes/SkeletonModification2DLookAt.xml
new file mode 100644
index 0000000000..b0fa0e5a01
--- /dev/null
+++ b/doc/classes/SkeletonModification2DLookAt.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModification2DLookAt" inherits="SkeletonModification2D" version="4.0">
+ <brief_description>
+ A modification that rotates a [Bone2D] node to look at a target.
+ </brief_description>
+ <description>
+ This [SkeletonModification2D] rotates a bone to look a target. This is extremely helpful for moving character's head to look at the player, rotating a turret to look at a target, or any other case where you want to make a bone rotate towards something quickly and easily.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_additional_rotation" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Returns the amount of additional rotation that is applied after the LookAt modification executes.
+ </description>
+ </method>
+ <method name="get_constraint_angle_invert" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether the constraints to this modification are inverted or not.
+ </description>
+ </method>
+ <method name="get_constraint_angle_max" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Returns the constraint's maximum allowed angle.
+ </description>
+ </method>
+ <method name="get_constraint_angle_min" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Returns the constraint's minimum allowed angle.
+ </description>
+ </method>
+ <method name="get_enable_constraint" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the LookAt modification is using constraints.
+ </description>
+ </method>
+ <method name="set_additional_rotation">
+ <return type="void">
+ </return>
+ <argument index="0" name="rotation" type="float">
+ </argument>
+ <description>
+ Sets the amount of additional rotation that is to be applied after executing the modification. This allows for offsetting the results by the inputted rotation amount.
+ </description>
+ </method>
+ <method name="set_constraint_angle_invert">
+ <return type="void">
+ </return>
+ <argument index="0" name="invert" type="bool">
+ </argument>
+ <description>
+ When [code]true[/code], the modification will use an inverted joint constraint.
+ An inverted joint constraint only constraints the [Bone2D] to the angles [i]outside of[/i] the inputted minimum and maximum angles. For this reason, it is referred to as an inverted joint constraint, as it constraints the joint to the outside of the inputted values.
+ </description>
+ </method>
+ <method name="set_constraint_angle_max">
+ <return type="void">
+ </return>
+ <argument index="0" name="angle_max" type="float">
+ </argument>
+ <description>
+ Sets the constraint's maximum allowed angle.
+ </description>
+ </method>
+ <method name="set_constraint_angle_min">
+ <return type="void">
+ </return>
+ <argument index="0" name="angle_min" type="float">
+ </argument>
+ <description>
+ Sets the constraint's minimum allowed angle.
+ </description>
+ </method>
+ <method name="set_enable_constraint">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable_constraint" type="bool">
+ </argument>
+ <description>
+ Sets whether this modification will use constraints or not. When [code]true[/code], constraints will be applied when solving the LookAt modification.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="bone2d_node" type="NodePath" setter="set_bone2d_node" getter="get_bone2d_node" default="NodePath(&quot;&quot;)">
+ The [Bone2D] node that the modification will operate on.
+ </member>
+ <member name="bone_index" type="int" setter="set_bone_index" getter="get_bone_index" default="-1">
+ The index of the [Bone2D] node that the modification will oeprate on.
+ </member>
+ <member name="target_nodepath" type="NodePath" setter="set_target_node" getter="get_target_node" default="NodePath(&quot;&quot;)">
+ The NodePath to the node that is the target for the LookAt modification. This node is what the modification will rotate the [Bone2D] to.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonModification2DPhysicalBones.xml b/doc/classes/SkeletonModification2DPhysicalBones.xml
new file mode 100644
index 0000000000..d8aaf09a8e
--- /dev/null
+++ b/doc/classes/SkeletonModification2DPhysicalBones.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModification2DPhysicalBones" inherits="SkeletonModification2D" version="4.0">
+ <brief_description>
+ A modification that applies the transforms of [PhysicalBone2D] nodes to [Bone2D] nodes.
+ </brief_description>
+ <description>
+ This modification takes the transforms of [PhysicalBone2D] nodes and applies them to [Bone2D] nodes. This allows the [Bone2D] nodes to react to physics thanks to the linked [PhysicalBone2D] nodes.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="fetch_physical_bones">
+ <return type="void">
+ </return>
+ <description>
+ Empties the list of [PhysicalBone2D] nodes and populates it will all [PhysicalBone2D] nodes that are children of the [Skeleton2D].
+ </description>
+ </method>
+ <method name="get_physical_bone_node" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <description>
+ Returns the [PhysicalBone2D] node at [code]joint_idx[/code].
+ </description>
+ </method>
+ <method name="set_physical_bone_node">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint_idx" type="int">
+ </argument>
+ <argument index="1" name="physicalbone2d_node" type="NodePath">
+ </argument>
+ <description>
+ Sets the [PhysicalBone2D] node at [code]joint_idx[/code].
+ [b]Note:[/b] This is just the index used for this modification, not the bone index used in the [Skeleton2D].
+ </description>
+ </method>
+ <method name="start_simulation">
+ <return type="void">
+ </return>
+ <argument index="0" name="bones" type="StringName[]" default="[ ]">
+ </argument>
+ <description>
+ Tell the [PhysicalBone2D] nodes to start simulating and interacting with the physics world.
+ Optionally, an array of bone names can be passed to this function, and that will cause only [PhysicalBone2D] nodes with those names to start simulating.
+ </description>
+ </method>
+ <method name="stop_simulation">
+ <return type="void">
+ </return>
+ <argument index="0" name="bones" type="StringName[]" default="[ ]">
+ </argument>
+ <description>
+ Tell the [PhysicalBone2D] nodes to stop simulating and interacting with the physics world.
+ Optionally, an array of bone names can be passed to this function, and that will cause only [PhysicalBone2D] nodes with those names to stop simulating.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="physical_bone_chain_length" type="int" setter="set_physical_bone_chain_length" getter="get_physical_bone_chain_length" default="0">
+ The amount of [PhysicalBone2D] nodes linked in this modification.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonModification2DStackHolder.xml b/doc/classes/SkeletonModification2DStackHolder.xml
new file mode 100644
index 0000000000..313cf81482
--- /dev/null
+++ b/doc/classes/SkeletonModification2DStackHolder.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModification2DStackHolder" inherits="SkeletonModification2D" version="4.0">
+ <brief_description>
+ A modification that holds and executes a [SkeletonModificationStack2D].
+ </brief_description>
+ <description>
+ This [SkeletonModification2D] holds a reference to a [SkeletonModificationStack2D], allowing you to use multiple modification stacks on a single [Skeleton2D].
+ [b]Note:[/b] The modifications in the held [SkeletonModificationStack2D] will only be executed if their execution mode matches the execution mode of the SkeletonModification2DStackHolder.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_held_modification_stack" qualifiers="const">
+ <return type="SkeletonModificationStack2D">
+ </return>
+ <description>
+ Returns the [SkeletonModificationStack2D] that this modification is holding.
+ </description>
+ </method>
+ <method name="set_held_modification_stack">
+ <return type="void">
+ </return>
+ <argument index="0" name="held_modification_stack" type="SkeletonModificationStack2D">
+ </argument>
+ <description>
+ Sets the [SkeletonModificationStack2D] that this modification is holding. This modification stack will then be executed when this modification is executed.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonModification2DTwoBoneIK.xml b/doc/classes/SkeletonModification2DTwoBoneIK.xml
new file mode 100644
index 0000000000..554515556b
--- /dev/null
+++ b/doc/classes/SkeletonModification2DTwoBoneIK.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModification2DTwoBoneIK" inherits="SkeletonModification2D" version="4.0">
+ <brief_description>
+ A modification that rotates two bones using the law of cosigns to reach the target.
+ </brief_description>
+ <description>
+ This [SkeletonModification2D] uses an algorithm typically called TwoBoneIK. This algorithm works by leveraging the law of cosigns and the lengths of the bones to figure out what rotation the bones currently have, and what rotation they need to make a complete triangle, where the first bone, the second bone, and the target form the three verticies of the triangle. Because the algorithm works by making a triangle, it can only opperate on two bones.
+ TwoBoneIK is great for arms, legs, and really any joints that can be represented by just two bones that bend to reach a target. This solver is more lightweight than [SkeletonModification2DFABRIK], but gives similar, natural looking results.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_joint_one_bone2d_node" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <description>
+ Returns the [Bone2D] node that is being used as the first bone in the TwoBoneIK modification.
+ </description>
+ </method>
+ <method name="get_joint_one_bone_idx" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the index of the [Bone2D] node that is being used as the first bone in the TwoBoneIK modification.
+ </description>
+ </method>
+ <method name="get_joint_two_bone2d_node" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <description>
+ Returns the [Bone2D] node that is being used as the second bone in the TwoBoneIK modification.
+ </description>
+ </method>
+ <method name="get_joint_two_bone_idx" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the index of the [Bone2D] node that is being used as the second bone in the TwoBoneIK modification.
+ </description>
+ </method>
+ <method name="set_joint_one_bone2d_node">
+ <return type="void">
+ </return>
+ <argument index="0" name="bone2d_node" type="NodePath">
+ </argument>
+ <description>
+ Sets the [Bone2D] node that is being used as the first bone in the TwoBoneIK modification.
+ </description>
+ </method>
+ <method name="set_joint_one_bone_idx">
+ <return type="void">
+ </return>
+ <argument index="0" name="bone_idx" type="int">
+ </argument>
+ <description>
+ Sets the index of the [Bone2D] node that is being used as the first bone in the TwoBoneIK modification.
+ </description>
+ </method>
+ <method name="set_joint_two_bone2d_node">
+ <return type="void">
+ </return>
+ <argument index="0" name="bone2d_node" type="NodePath">
+ </argument>
+ <description>
+ Sets the [Bone2D] node that is being used as the second bone in the TwoBoneIK modification.
+ </description>
+ </method>
+ <method name="set_joint_two_bone_idx">
+ <return type="void">
+ </return>
+ <argument index="0" name="bone_idx" type="int">
+ </argument>
+ <description>
+ Sets the index of the [Bone2D] node that is being used as the second bone in the TwoBoneIK modification.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="flip_bend_direction" type="bool" setter="set_flip_bend_direction" getter="get_flip_bend_direction" default="false">
+ If [code]true[/code], the bones in the modification will blend outward as opposed to inwards when contracting. If [code]false[/code], the bones will bend inwards when contracting.
+ </member>
+ <member name="target_maximum_distance" type="float" setter="set_target_maximum_distance" getter="get_target_maximum_distance" default="0.0">
+ The maximum distance the target can be at. If the target is farther than this distance, the modification will solve as if it's at this maximum distance. When set to [code]0[/code], the modification will solve without distance constraints.
+ </member>
+ <member name="target_minimum_distance" type="float" setter="set_target_minimum_distance" getter="get_target_minimum_distance" default="0.0">
+ The minimum distance the target can be at. If the target is closer than this distance, the modification will solve as if it's at this minimum distance. When set to [code]0[/code], the modification will solve without distance constraints.
+ </member>
+ <member name="target_nodepath" type="NodePath" setter="set_target_node" getter="get_target_node" default="NodePath(&quot;&quot;)">
+ The NodePath to the node that is the target for the TwoBoneIK modification. This node is what the modification will use when bending the [Bone2D] nodes.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonModificationStack2D.xml b/doc/classes/SkeletonModificationStack2D.xml
new file mode 100644
index 0000000000..35b899fe08
--- /dev/null
+++ b/doc/classes/SkeletonModificationStack2D.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonModificationStack2D" inherits="Resource" version="4.0">
+ <brief_description>
+ A resource that holds a stack of [SkeletonModification2D]s.
+ </brief_description>
+ <description>
+ This resource is used by the Skeleton and holds a stack of [SkeletonModification2D]s.
+ This controls the order of the modifications and how they are applied. Modification order is especially important for full-body IK setups, as you need to execute the modifications in the correct order to get the desired results. For example, you want to execute a modification on the spine [i]before[/i] the arms on a humanoid skeleton.
+ This resource also controls how strongly all of the modifications are applied to the [Skeleton2D].
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_modification">
+ <return type="void">
+ </return>
+ <argument index="0" name="modification" type="SkeletonModification2D">
+ </argument>
+ <description>
+ Adds the passed-in [SkeletonModification2D] to the stack.
+ </description>
+ </method>
+ <method name="delete_modification">
+ <return type="void">
+ </return>
+ <argument index="0" name="mod_idx" type="int">
+ </argument>
+ <description>
+ Deletes the [SkeletonModification2D] at the index position [code]mod_idx[/code], if it exists.
+ </description>
+ </method>
+ <method name="enable_all_modifications">
+ <return type="void">
+ </return>
+ <argument index="0" name="enabled" type="bool">
+ </argument>
+ <description>
+ Enables all [SkeletonModification2D]s in the stack.
+ </description>
+ </method>
+ <method name="execute">
+ <return type="void">
+ </return>
+ <argument index="0" name="delta" type="float">
+ </argument>
+ <argument index="1" name="execution_mode" type="int">
+ </argument>
+ <description>
+ Executes all of the [SkeletonModification2D]s in the stack that use the same execution mode as the passed-in [code]execution_mode[/code], starting from index [code]0[/code] to [member modification_count].
+ [b]Note:[/b] The order of the modifications can matter depending on the modifications. For example, modifications on a spine should operate before modifications on the arms in order to get proper results.
+ </description>
+ </method>
+ <method name="get_is_setup" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns a boolean that indiciates whether the modification stack is setup and can execute.
+ </description>
+ </method>
+ <method name="get_modification" qualifiers="const">
+ <return type="SkeletonModification2D">
+ </return>
+ <argument index="0" name="mod_idx" type="int">
+ </argument>
+ <description>
+ Returns the [SkeletonModification2D] at the passed-in index, [code]mod_idx[/code].
+ </description>
+ </method>
+ <method name="get_skeleton" qualifiers="const">
+ <return type="Skeleton2D">
+ </return>
+ <description>
+ Returns the [Skeleton2D] node that the SkeletonModificationStack2D is bound to.
+ </description>
+ </method>
+ <method name="set_modification">
+ <return type="void">
+ </return>
+ <argument index="0" name="mod_idx" type="int">
+ </argument>
+ <argument index="1" name="modification" type="SkeletonModification2D">
+ </argument>
+ <description>
+ Sets the modification at [code]mod_idx[/code] to the passed-in modification, [code]modification[/code].
+ </description>
+ </method>
+ <method name="setup">
+ <return type="void">
+ </return>
+ <description>
+ Sets up the modification stack so it can execute. This function should be called by [Skeleton2D] and shouldn't be manually called unless you know what you are doing.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="enabled" type="bool" setter="set_enabled" getter="get_enabled" default="false">
+ If [code]true[/code], the modification's in the stack will be called. This is handled automatically through the [Skeleton2D] node.
+ </member>
+ <member name="modification_count" type="int" setter="set_modification_count" getter="get_modification_count" default="0">
+ The number of modifications in the stack.
+ </member>
+ <member name="strength" type="float" setter="set_strength" getter="get_strength" default="1.0">
+ The interpolation strength of the modifications in stack. A value of [code]0[/code] will make it where the modifications are not applied, a strength of [code]0.5[/code] will be half applied, and a strength of [code]1[/code] will allow the modifications to be fully applied and override the [Skeleton2D] [Bone2D] poses.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/Skin.xml b/doc/classes/Skin.xml
index e22feb42f0..f409b6c80c 100644
--- a/doc/classes/Skin.xml
+++ b/doc/classes/Skin.xml
@@ -12,7 +12,7 @@
</return>
<argument index="0" name="bone" type="int">
</argument>
- <argument index="1" name="pose" type="Transform">
+ <argument index="1" name="pose" type="Transform3D">
</argument>
<description>
</description>
@@ -46,7 +46,7 @@
</description>
</method>
<method name="get_bind_pose" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="bind_index" type="int">
</argument>
@@ -86,7 +86,7 @@
</return>
<argument index="0" name="bind_index" type="int">
</argument>
- <argument index="1" name="pose" type="Transform">
+ <argument index="1" name="pose" type="Transform3D">
</argument>
<description>
</description>
diff --git a/doc/classes/SkinReference.xml b/doc/classes/SkinReference.xml
index 8fc163f88d..3f8bc3be82 100644
--- a/doc/classes/SkinReference.xml
+++ b/doc/classes/SkinReference.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SkinReference" inherits="Reference" version="4.0">
+<class name="SkinReference" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Sprite2D.xml b/doc/classes/Sprite2D.xml
index 617ad3a371..c320adb1be 100644
--- a/doc/classes/Sprite2D.xml
+++ b/doc/classes/Sprite2D.xml
@@ -64,7 +64,7 @@
<member name="frame" type="int" setter="set_frame" getter="get_frame" default="0">
Current frame to display from sprite sheet. [member hframes] or [member vframes] must be greater than 1.
</member>
- <member name="frame_coords" type="Vector2" setter="set_frame_coords" getter="get_frame_coords" default="Vector2( 0, 0 )">
+ <member name="frame_coords" type="Vector2i" setter="set_frame_coords" getter="get_frame_coords" default="Vector2i( 0, 0 )">
Coordinates of the frame to display from sprite sheet. This is as an alias for the [member frame] property. [member hframes] or [member vframes] must be greater than 1.
</member>
<member name="hframes" type="int" setter="set_hframes" getter="get_hframes" default="1">
diff --git a/doc/classes/Sprite3D.xml b/doc/classes/Sprite3D.xml
index 658fd1a4f2..8c4b9e7d10 100644
--- a/doc/classes/Sprite3D.xml
+++ b/doc/classes/Sprite3D.xml
@@ -14,7 +14,7 @@
<member name="frame" type="int" setter="set_frame" getter="get_frame" default="0">
Current frame to display from sprite sheet. [member hframes] or [member vframes] must be greater than 1.
</member>
- <member name="frame_coords" type="Vector2" setter="set_frame_coords" getter="get_frame_coords" default="Vector2( 0, 0 )">
+ <member name="frame_coords" type="Vector2i" setter="set_frame_coords" getter="get_frame_coords" default="Vector2i( 0, 0 )">
Coordinates of the frame to display from sprite sheet. This is as an alias for the [member frame] property. [member hframes] or [member vframes] must be greater than 1.
</member>
<member name="hframes" type="int" setter="set_hframes" getter="get_hframes" default="1">
@@ -39,6 +39,11 @@
Emitted when the [member frame] changes.
</description>
</signal>
+ <signal name="texture_changed">
+ <description>
+ Emitted when the [member texture] changes.
+ </description>
+ </signal>
</signals>
<constants>
</constants>
diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml
index 2a5c1ea6f4..298339d5fc 100644
--- a/doc/classes/StaticBody2D.xml
+++ b/doc/classes/StaticBody2D.xml
@@ -4,8 +4,11 @@
Static body for 2D physics.
</brief_description>
<description>
- Static body for 2D physics. A StaticBody2D is a body that is not intended to move. It is ideal for implementing objects in the environment, such as walls or platforms.
- Additionally, a constant linear or angular velocity can be set for the static body, which will affect colliding bodies as if it were moving (for example, a conveyor belt).
+ Static body for 2D physics. A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody2D], they don't consume any CPU resources as long as they don't move.
+ They however have extra functionalities to move and affect other bodies:
+ [b]Constant velocity:[/b] [member constant_linear_velocity] and [member constant_angular_velocity] can be set for the static body, so even if it doesn't move, it affects other bodies as if it was moving (this is useful for simulating conveyor belts or conveyor wheels).
+ [b]Transform change:[/b] Static bodies can be also moved by code. Unless [member kinematic_motion] is enabled, they are just teleported in this case and don't affect other bodies on their path.
+ [b]Kinematic motion:[/b] Static bodies can have [member kinematic_motion] enabled to make them kinematic bodies that can be moved by code and push other bodies on their path.
</description>
<tutorials>
</tutorials>
@@ -13,10 +16,14 @@
</methods>
<members>
<member name="constant_angular_velocity" type="float" setter="set_constant_angular_velocity" getter="get_constant_angular_velocity" default="0.0">
- The body's constant angular velocity. This does not rotate the body, but affects colliding bodies, as if it were rotating.
+ The body's constant angular velocity. This does not rotate the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were rotating.
</member>
<member name="constant_linear_velocity" type="Vector2" setter="set_constant_linear_velocity" getter="get_constant_linear_velocity" default="Vector2( 0, 0 )">
- The body's constant linear velocity. This does not move the body, but affects colliding bodies, as if it were moving.
+ The body's constant linear velocity. This does not move the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were moving.
+ </member>
+ <member name="kinematic_motion" type="bool" setter="set_kinematic_motion_enabled" getter="is_kinematic_motion_enabled" default="false">
+ If [code]true[/code], the body will act the same as a [RigidBody2D] in [constant RigidBody2D.MODE_KINEMATIC] mode.
+ When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
The physics material override for the body.
diff --git a/doc/classes/StaticBody3D.xml b/doc/classes/StaticBody3D.xml
index 63a15cbe1d..5ffbb71522 100644
--- a/doc/classes/StaticBody3D.xml
+++ b/doc/classes/StaticBody3D.xml
@@ -4,8 +4,11 @@
Static body for 3D physics.
</brief_description>
<description>
- Static body for 3D physics. A static body is a simple body that is not intended to move. In contrast to [RigidBody3D], they don't consume any CPU resources as long as they don't move.
- Additionally, a constant linear or angular velocity can be set for the static body, so even if it doesn't move, it affects other bodies as if it was moving (this is useful for simulating conveyor belts or conveyor wheels).
+ Static body for 3D physics. A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody3D], they don't consume any CPU resources as long as they don't move.
+ They however have extra functionalities to move and affect other bodies:
+ [b]Constant velocity:[/b] [member constant_linear_velocity] and [member constant_angular_velocity] can be set for the static body, so even if it doesn't move, it affects other bodies as if it was moving (this is useful for simulating conveyor belts or conveyor wheels).
+ [b]Transform change:[/b] Static bodies can be also moved by code. Unless [member kinematic_motion] is enabled, they are just teleported in this case and don't affect other bodies on their path.
+ [b]Kinematic motion:[/b] Static bodies can have [member kinematic_motion] enabled to make them kinematic bodies that can be moved by code and push other bodies on their path.
</description>
<tutorials>
<link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link>
@@ -16,10 +19,14 @@
</methods>
<members>
<member name="constant_angular_velocity" type="Vector3" setter="set_constant_angular_velocity" getter="get_constant_angular_velocity" default="Vector3( 0, 0, 0 )">
- The body's constant angular velocity. This does not rotate the body, but affects other bodies that touch it, as if it was in a state of rotation.
+ The body's constant angular velocity. This does not rotate the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were rotating.
</member>
<member name="constant_linear_velocity" type="Vector3" setter="set_constant_linear_velocity" getter="get_constant_linear_velocity" default="Vector3( 0, 0, 0 )">
- The body's constant linear velocity. This does not move the body, but affects other bodies that touch it, as if it was in a state of movement.
+ The body's constant linear velocity. This does not move the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were moving.
+ </member>
+ <member name="kinematic_motion" type="bool" setter="set_kinematic_motion_enabled" getter="is_kinematic_motion_enabled" default="false">
+ If [code]true[/code], the body will act the same as a [RigidBody3D] in [constant RigidBody3D.MODE_KINEMATIC] mode.
+ When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
The physics material override for the body.
diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml
index a1b858acf6..5367a572f1 100644
--- a/doc/classes/StreamPeer.xml
+++ b/doc/classes/StreamPeer.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StreamPeer" inherits="Reference" version="4.0">
+<class name="StreamPeer" inherits="RefCounted" version="4.0">
<brief_description>
Abstraction and base class for stream-based protocols.
</brief_description>
<description>
- StreamPeer is an abstraction and base class for stream-based protocols (such as TCP or UNIX sockets). It provides an API for sending and receiving data through streams as raw data or strings.
+ StreamPeer is an abstraction and base class for stream-based protocols (such as TCP). It provides an API for sending and receiving data through streams as raw data or strings.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index 416438e648..d0c5f0ea86 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -275,7 +275,7 @@
Returns a copy of the string with the substring [code]what[/code] inserted at the given position.
</description>
</method>
- <method name="is_abs_path" qualifiers="const">
+ <method name="is_absolute_path" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -397,7 +397,12 @@
<argument index="0" name="position" type="int">
</argument>
<description>
- Returns a number of characters from the left of the string.
+ Returns a number of characters from the left of the string. If negative [code]position[/code] is used, the characters are counted downwards from [String]'s length.
+ Examples:
+ [codeblock]
+ print("sample text".left(3)) #prints "sam"
+ print("sample text".left(-3)) #prints "sample t"
+ [/codeblock]
</description>
</method>
<method name="length" qualifiers="const">
@@ -669,7 +674,12 @@
<argument index="0" name="position" type="int">
</argument>
<description>
- Returns the right side of the string from a given position.
+ Returns a number of characters from the right of the string. If negative [code]position[/code] is used, the characters are counted downwards from [String]'s length.
+ Examples:
+ [codeblock]
+ print("sample text".right(3)) #prints "ext"
+ print("sample text".right(-3)) #prints "ple text"
+ [/codeblock]
</description>
</method>
<method name="rpad" qualifiers="const">
diff --git a/doc/classes/StyleBoxTexture.xml b/doc/classes/StyleBoxTexture.xml
index 895d0c357d..f4a1f1f01d 100644
--- a/doc/classes/StyleBoxTexture.xml
+++ b/doc/classes/StyleBoxTexture.xml
@@ -127,13 +127,6 @@
The texture to use when drawing this style box.
</member>
</members>
- <signals>
- <signal name="texture_changed">
- <description>
- Emitted when the stylebox's texture is changed.
- </description>
- </signal>
- </signals>
<constants>
<constant name="AXIS_STRETCH_MODE_STRETCH" value="0" enum="AxisStretchMode">
Stretch the stylebox's texture. This results in visible distortion unless the texture size matches the stylebox's size perfectly.
diff --git a/doc/classes/SubViewport.xml b/doc/classes/SubViewport.xml
index b6e9eda1d1..f54f22d6fa 100644
--- a/doc/classes/SubViewport.xml
+++ b/doc/classes/SubViewport.xml
@@ -25,7 +25,7 @@
<member name="render_target_update_mode" type="int" setter="set_update_mode" getter="get_update_mode" enum="SubViewport.UpdateMode" default="2">
The update mode when the sub-viewport is used as a render target.
</member>
- <member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i( 0, 0 )">
+ <member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i( 512, 512 )">
The width and height of the sub-viewport.
</member>
<member name="size_2d_override" type="Vector2i" setter="set_size_2d_override" getter="get_size_2d_override" default="Vector2i( 0, 0 )">
diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml
index 1195e4aa2b..56b47f4a24 100644
--- a/doc/classes/SurfaceTool.xml
+++ b/doc/classes/SurfaceTool.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SurfaceTool" inherits="Reference" version="4.0">
+<class name="SurfaceTool" inherits="RefCounted" version="4.0">
<brief_description>
Helper tool to create geometry.
</brief_description>
@@ -76,10 +76,10 @@
</argument>
<argument index="1" name="surface" type="int">
</argument>
- <argument index="2" name="transform" type="Transform">
+ <argument index="2" name="transform" type="Transform3D">
</argument>
<description>
- Append vertices from a given [Mesh] surface onto the current vertex array with specified [Transform].
+ Append vertices from a given [Mesh] surface onto the current vertex array with specified [Transform3D].
</description>
</method>
<method name="begin">
diff --git a/doc/classes/TCPServer.xml b/doc/classes/TCPServer.xml
index 28f06ad3ae..7160055c6d 100644
--- a/doc/classes/TCPServer.xml
+++ b/doc/classes/TCPServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TCPServer" inherits="Reference" version="4.0">
+<class name="TCPServer" inherits="RefCounted" version="4.0">
<brief_description>
A TCP server.
</brief_description>
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 088bcd1c3c..74811318dc 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -5,6 +5,7 @@
</brief_description>
<description>
TextEdit is meant for editing large, multiline text. It also has facilities for editing code, such as syntax highlighting support and multiple levels of undo/redo.
+ [b]Note:[/b] When holding down [kbd]Alt[/kbd], the vertical scroll wheel will scroll 5 times as fast as it would normally do. This also works in the Godot script editor.
</description>
<tutorials>
</tutorials>
@@ -127,6 +128,13 @@
Folds the given line, if possible (see [method can_fold]).
</description>
</method>
+ <method name="get_caret_draw_pos" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ Gets the caret pixel draw poistion.
+ </description>
+ </method>
<method name="get_gutter_count" qualifiers="const">
<return type="int">
</return>
@@ -166,6 +174,15 @@
Returns the text of a specific line.
</description>
</method>
+ <method name="get_line_background_color">
+ <return type="Color">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <description>
+ Returns the current background color of the line. [code]Color(0, 0, 0, 0)[/code] is returned if no color is set.
+ </description>
+ </method>
<method name="get_line_count" qualifiers="const">
<return type="int">
</return>
@@ -282,6 +299,13 @@
Returns the selection end line.
</description>
</method>
+ <method name="get_visible_line_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the number of visible lines, including wrapped text.
+ </description>
+ </method>
<method name="get_word_under_cursor" qualifiers="const">
<return type="String">
</return>
@@ -298,6 +322,13 @@
Insert the specified text at the cursor position.
</description>
</method>
+ <method name="is_caret_visible" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the caret is visible on the screen.
+ </description>
+ </method>
<method name="is_folded" qualifiers="const">
<return type="bool">
</return>
@@ -540,6 +571,17 @@
If [code]true[/code], hides the line of the specified index.
</description>
</method>
+ <method name="set_line_background_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ Sets the current background color of the line. Set to [code]Color(0, 0, 0, 0)[/code] for no color.
+ </description>
+ </method>
<method name="set_line_gutter_clickable">
<return type="void">
</return>
@@ -714,10 +756,10 @@
If [code]true[/code], read-only mode is enabled. Existing text cannot be modified and new text cannot be added.
</member>
<member name="scroll_horizontal" type="int" setter="set_h_scroll" getter="get_h_scroll" default="0">
- If there is a horizontal scrollbar this determines the current horizontal scroll value in pixels.
+ If there is a horizontal scrollbar, this determines the current horizontal scroll value in pixels.
</member>
<member name="scroll_vertical" type="float" setter="set_v_scroll" getter="get_v_scroll" default="0.0">
- If there is a vertical scrollbar this determines the current vertical scroll value in line numbers, starting at 0 for the top line.
+ If there is a vertical scrollbar, this determines the current vertical scroll value in line numbers, starting at 0 for the top line.
</member>
<member name="selecting_enabled" type="bool" setter="set_selecting_enabled" getter="is_selecting_enabled" default="true">
If [code]true[/code], text can be selected.
@@ -784,10 +826,6 @@
<description>
</description>
</signal>
- <signal name="request_completion">
- <description>
- </description>
- </signal>
<signal name="symbol_lookup">
<argument index="0" name="symbol" type="String">
</argument>
@@ -936,24 +974,6 @@
</theme_item>
<theme_item name="code_folding_color" type="Color" default="Color( 0.8, 0.8, 0.8, 0.8 )">
</theme_item>
- <theme_item name="completion" type="StyleBox">
- </theme_item>
- <theme_item name="completion_background_color" type="Color" default="Color( 0.17, 0.16, 0.2, 1 )">
- </theme_item>
- <theme_item name="completion_existing_color" type="Color" default="Color( 0.87, 0.87, 0.87, 0.13 )">
- </theme_item>
- <theme_item name="completion_font_color" type="Color" default="Color( 0.67, 0.67, 0.67, 1 )">
- </theme_item>
- <theme_item name="completion_lines" type="int" default="7">
- </theme_item>
- <theme_item name="completion_max_width" type="int" default="50">
- </theme_item>
- <theme_item name="completion_scroll_color" type="Color" default="Color( 1, 1, 1, 1 )">
- </theme_item>
- <theme_item name="completion_scroll_width" type="int" default="3">
- </theme_item>
- <theme_item name="completion_selected_color" type="Color" default="Color( 0.26, 0.26, 0.27, 1 )">
- </theme_item>
<theme_item name="current_line_color" type="Color" default="Color( 0.25, 0.25, 0.26, 0.8 )">
Sets the [Color] of the breakpoints. [member breakpoint_gutter] has to be enabled.
</theme_item>
@@ -979,9 +999,6 @@
<theme_item name="line_spacing" type="int" default="4">
Sets the spacing between the lines.
</theme_item>
- <theme_item name="mark_color" type="Color" default="Color( 1, 0.4, 0.4, 0.4 )">
- Sets the [Color] of marked text.
- </theme_item>
<theme_item name="normal" type="StyleBox">
Sets the [StyleBox] of this [TextEdit].
</theme_item>
diff --git a/doc/classes/TextLine.xml b/doc/classes/TextLine.xml
index c21da09edb..ddbae0e977 100644
--- a/doc/classes/TextLine.xml
+++ b/doc/classes/TextLine.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TextLine" inherits="Reference" version="4.0">
+<class name="TextLine" inherits="RefCounted" version="4.0">
<brief_description>
Holds a line of text.
</brief_description>
diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml
index 8df53b8423..e9afe47ee8 100644
--- a/doc/classes/TextParagraph.xml
+++ b/doc/classes/TextParagraph.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TextParagraph" inherits="Reference" version="4.0">
+<class name="TextParagraph" inherits="RefCounted" version="4.0">
<brief_description>
Holds a paragraph of text.
</brief_description>
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index fe63e434c9..9a96d8699c 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -976,7 +976,7 @@
</argument>
<description>
Returns [code]true[/code] if text buffer is configured to display hexadecimal codes in place of invalid characters.
- Note: If set to [code]false[/code], nothing is displayed in place of invalid characters.
+ Note: If set to [code]false[/code], nothing is displayed in place of invalid characters.
</description>
</method>
<method name="shaped_text_get_range" qualifiers="const">
diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml
index 3173dddb42..7448697df3 100644
--- a/doc/classes/Theme.xml
+++ b/doc/classes/Theme.xml
@@ -23,10 +23,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Clears the [Color] at [code]name[/code] if the theme has [code]node_type[/code].
+ Clears the [Color] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="clear_constant">
@@ -34,10 +34,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Clears the constant at [code]name[/code] if the theme has [code]node_type[/code].
+ Clears the constant at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="clear_font">
@@ -45,10 +45,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Clears the [Font] at [code]name[/code] if the theme has [code]node_type[/code].
+ Clears the [Font] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="clear_font_size">
@@ -56,10 +56,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Clears the font size [code]name[/code] if the theme has [code]node_type[/code].
+ Clears the font size [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="clear_icon">
@@ -67,10 +67,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Clears the icon at [code]name[/code] if the theme has [code]node_type[/code].
+ Clears the icon at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="clear_stylebox">
@@ -78,10 +78,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Clears [StyleBox] at [code]name[/code] if the theme has [code]node_type[/code].
+ Clears [StyleBox] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="clear_theme_item">
@@ -91,10 +91,10 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Clears the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]node_type[/code].
+ Clears the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="copy_default_theme">
@@ -118,19 +118,19 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns the [Color] at [code]name[/code] if the theme has [code]node_type[/code].
+ Returns the [Color] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_color_list" qualifiers="const">
<return type="PackedStringArray">
</return>
- <argument index="0" name="node_type" type="String">
+ <argument index="0" name="theme_type" type="String">
</argument>
<description>
- Returns all the [Color]s as a [PackedStringArray] filled with each [Color]'s name, for use in [method get_color], if the theme has [code]node_type[/code].
+ Returns all the [Color]s as a [PackedStringArray] filled with each [Color]'s name, for use in [method get_color], if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_color_type_list" qualifiers="const">
@@ -145,19 +145,19 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns the constant at [code]name[/code] if the theme has [code]node_type[/code].
+ Returns the constant at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_constant_list" qualifiers="const">
<return type="PackedStringArray">
</return>
- <argument index="0" name="node_type" type="String">
+ <argument index="0" name="theme_type" type="String">
</argument>
<description>
- Returns all the constants as a [PackedStringArray] filled with each constant's name, for use in [method get_constant], if the theme has [code]node_type[/code].
+ Returns all the constants as a [PackedStringArray] filled with each constant's name, for use in [method get_constant], if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_constant_type_list" qualifiers="const">
@@ -172,19 +172,19 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns the [Font] at [code]name[/code] if the theme has [code]node_type[/code].
+ Returns the [Font] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_font_list" qualifiers="const">
<return type="PackedStringArray">
</return>
- <argument index="0" name="node_type" type="String">
+ <argument index="0" name="theme_type" type="String">
</argument>
<description>
- Returns all the [Font]s as a [PackedStringArray] filled with each [Font]'s name, for use in [method get_font], if the theme has [code]node_type[/code].
+ Returns all the [Font]s as a [PackedStringArray] filled with each [Font]'s name, for use in [method get_font], if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_font_size" qualifiers="const">
@@ -192,19 +192,19 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns the font size at [code]name[/code] if the theme has [code]node_type[/code].
+ Returns the font size at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_font_size_list" qualifiers="const">
<return type="PackedStringArray">
</return>
- <argument index="0" name="node_type" type="String">
+ <argument index="0" name="theme_type" type="String">
</argument>
<description>
- Returns all the font sizes as a [PackedStringArray] filled with each font size name, for use in [method get_font_size], if the theme has [code]node_type[/code].
+ Returns all the font sizes as a [PackedStringArray] filled with each font size name, for use in [method get_font_size], if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_font_size_type_list" qualifiers="const">
@@ -226,19 +226,19 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns the icon [Texture2D] at [code]name[/code] if the theme has [code]node_type[/code].
+ Returns the icon [Texture2D] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_icon_list" qualifiers="const">
<return type="PackedStringArray">
</return>
- <argument index="0" name="node_type" type="String">
+ <argument index="0" name="theme_type" type="String">
</argument>
<description>
- Returns all the icons as a [PackedStringArray] filled with each [Texture2D]'s name, for use in [method get_icon], if the theme has [code]node_type[/code].
+ Returns all the icons as a [PackedStringArray] filled with each [Texture2D]'s name, for use in [method get_icon], if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_icon_type_list" qualifiers="const">
@@ -253,21 +253,21 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns the [StyleBox] at [code]name[/code] if the theme has [code]node_type[/code].
- Valid [code]name[/code]s may be found using [method get_stylebox_list]. Valid [code]node_type[/code]s may be found using [method get_stylebox_type_list].
+ Returns the [StyleBox] at [code]name[/code] if the theme has [code]theme_type[/code].
+ Valid [code]name[/code]s may be found using [method get_stylebox_list]. Valid [code]theme_type[/code]s may be found using [method get_stylebox_type_list].
</description>
</method>
<method name="get_stylebox_list" qualifiers="const">
<return type="PackedStringArray">
</return>
- <argument index="0" name="node_type" type="String">
+ <argument index="0" name="theme_type" type="String">
</argument>
<description>
- Returns all the [StyleBox]s as a [PackedStringArray] filled with each [StyleBox]'s name, for use in [method get_stylebox], if the theme has [code]node_type[/code].
- Valid [code]node_type[/code]s may be found using [method get_stylebox_type_list].
+ Returns all the [StyleBox]s as a [PackedStringArray] filled with each [StyleBox]'s name, for use in [method get_stylebox], if the theme has [code]theme_type[/code].
+ Valid [code]theme_type[/code]s may be found using [method get_stylebox_type_list].
</description>
</method>
<method name="get_stylebox_type_list" qualifiers="const">
@@ -284,11 +284,11 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Returns the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]node_type[/code].
- Valid [code]name[/code]s may be found using [method get_theme_item_list] or a data type specific method. Valid [code]node_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method.
+ Returns the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]theme_type[/code].
+ Valid [code]name[/code]s may be found using [method get_theme_item_list] or a data type specific method. Valid [code]theme_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method.
</description>
</method>
<method name="get_theme_item_list" qualifiers="const">
@@ -296,11 +296,11 @@
</return>
<argument index="0" name="data_type" type="int" enum="Theme.DataType">
</argument>
- <argument index="1" name="node_type" type="String">
+ <argument index="1" name="theme_type" type="String">
</argument>
<description>
- Returns all the theme items of [code]data_type[/code] as a [PackedStringArray] filled with each theme items's name, for use in [method get_theme_item] or a data type specific method, if the theme has [code]node_type[/code].
- Valid [code]node_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method.
+ Returns all the theme items of [code]data_type[/code] as a [PackedStringArray] filled with each theme items's name, for use in [method get_theme_item] or a data type specific method, if the theme has [code]theme_type[/code].
+ Valid [code]theme_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method.
</description>
</method>
<method name="get_theme_item_type_list" qualifiers="const">
@@ -324,11 +324,11 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if [Color] with [code]name[/code] is in [code]node_type[/code].
- Returns [code]false[/code] if the theme does not have [code]node_type[/code].
+ Returns [code]true[/code] if [Color] with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="has_constant" qualifiers="const">
@@ -336,11 +336,11 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if constant with [code]name[/code] is in [code]node_type[/code].
- Returns [code]false[/code] if the theme does not have [code]node_type[/code].
+ Returns [code]true[/code] if constant with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="has_font" qualifiers="const">
@@ -348,11 +348,11 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if [Font] with [code]name[/code] is in [code]node_type[/code].
- Returns [code]false[/code] if the theme does not have [code]node_type[/code].
+ Returns [code]true[/code] if [Font] with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="has_font_size" qualifiers="const">
@@ -360,11 +360,11 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if font size with [code]name[/code] is in [code]node_type[/code].
- Returns [code]false[/code] if the theme does not have [code]node_type[/code].
+ Returns [code]true[/code] if font size with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="has_icon" qualifiers="const">
@@ -372,11 +372,11 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if icon [Texture2D] with [code]name[/code] is in [code]node_type[/code].
- Returns [code]false[/code] if the theme does not have [code]node_type[/code].
+ Returns [code]true[/code] if icon [Texture2D] with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="has_stylebox" qualifiers="const">
@@ -384,11 +384,11 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if [StyleBox] with [code]name[/code] is in [code]node_type[/code].
- Returns [code]false[/code] if the theme does not have [code]node_type[/code].
+ Returns [code]true[/code] if [StyleBox] with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="has_theme_item" qualifiers="const">
@@ -398,11 +398,11 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if a theme item of [code]data_type[/code] with [code]name[/code] is in [code]node_type[/code].
- Returns [code]false[/code] if the theme does not have [code]node_type[/code].
+ Returns [code]true[/code] if a theme item of [code]data_type[/code] with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="rename_color">
@@ -412,10 +412,10 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Renames the [Color] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails.
+ Renames the [Color] at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails.
</description>
</method>
<method name="rename_constant">
@@ -425,10 +425,10 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Renames the constant at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails.
+ Renames the constant at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails.
</description>
</method>
<method name="rename_font">
@@ -438,10 +438,10 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Renames the [Font] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails.
+ Renames the [Font] at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails.
</description>
</method>
<method name="rename_font_size">
@@ -451,10 +451,10 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Renames the font size [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails.
+ Renames the font size [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails.
</description>
</method>
<method name="rename_icon">
@@ -464,10 +464,10 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Renames the icon at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails.
+ Renames the icon at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails.
</description>
</method>
<method name="rename_stylebox">
@@ -477,10 +477,10 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<description>
- Renames [StyleBox] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails.
+ Renames [StyleBox] at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails.
</description>
</method>
<method name="rename_theme_item">
@@ -492,10 +492,10 @@
</argument>
<argument index="2" name="name" type="StringName">
</argument>
- <argument index="3" name="node_type" type="StringName">
+ <argument index="3" name="theme_type" type="StringName">
</argument>
<description>
- Renames the theme item of [code]data_type[/code] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails.
+ Renames the theme item of [code]data_type[/code] at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails.
</description>
</method>
<method name="set_color">
@@ -503,13 +503,13 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<argument index="2" name="color" type="Color">
</argument>
<description>
- Sets the theme's [Color] to [code]color[/code] at [code]name[/code] in [code]node_type[/code].
- Creates [code]node_type[/code] if the theme does not have it.
+ Sets the theme's [Color] to [code]color[/code] at [code]name[/code] in [code]theme_type[/code].
+ Creates [code]theme_type[/code] if the theme does not have it.
</description>
</method>
<method name="set_constant">
@@ -517,13 +517,13 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<argument index="2" name="constant" type="int">
</argument>
<description>
- Sets the theme's constant to [code]constant[/code] at [code]name[/code] in [code]node_type[/code].
- Creates [code]node_type[/code] if the theme does not have it.
+ Sets the theme's constant to [code]constant[/code] at [code]name[/code] in [code]theme_type[/code].
+ Creates [code]theme_type[/code] if the theme does not have it.
</description>
</method>
<method name="set_font">
@@ -531,13 +531,13 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<argument index="2" name="font" type="Font">
</argument>
<description>
- Sets the theme's [Font] to [code]font[/code] at [code]name[/code] in [code]node_type[/code].
- Creates [code]node_type[/code] if the theme does not have it.
+ Sets the theme's [Font] to [code]font[/code] at [code]name[/code] in [code]theme_type[/code].
+ Creates [code]theme_type[/code] if the theme does not have it.
</description>
</method>
<method name="set_font_size">
@@ -545,13 +545,13 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<argument index="2" name="font_size" type="int">
</argument>
<description>
- Sets the theme's font size to [code]font_size[/code] at [code]name[/code] in [code]node_type[/code].
- Creates [code]node_type[/code] if the theme does not have it.
+ Sets the theme's font size to [code]font_size[/code] at [code]name[/code] in [code]theme_type[/code].
+ Creates [code]theme_type[/code] if the theme does not have it.
</description>
</method>
<method name="set_icon">
@@ -559,13 +559,13 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<argument index="2" name="texture" type="Texture2D">
</argument>
<description>
- Sets the theme's icon [Texture2D] to [code]texture[/code] at [code]name[/code] in [code]node_type[/code].
- Creates [code]node_type[/code] if the theme does not have it.
+ Sets the theme's icon [Texture2D] to [code]texture[/code] at [code]name[/code] in [code]theme_type[/code].
+ Creates [code]theme_type[/code] if the theme does not have it.
</description>
</method>
<method name="set_stylebox">
@@ -573,13 +573,13 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="node_type" type="StringName">
+ <argument index="1" name="theme_type" type="StringName">
</argument>
<argument index="2" name="texture" type="StyleBox">
</argument>
<description>
- Sets theme's [StyleBox] to [code]stylebox[/code] at [code]name[/code] in [code]node_type[/code].
- Creates [code]node_type[/code] if the theme does not have it.
+ Sets theme's [StyleBox] to [code]stylebox[/code] at [code]name[/code] in [code]theme_type[/code].
+ Creates [code]theme_type[/code] if the theme does not have it.
</description>
</method>
<method name="set_theme_item">
@@ -589,14 +589,14 @@
</argument>
<argument index="1" name="name" type="StringName">
</argument>
- <argument index="2" name="node_type" type="StringName">
+ <argument index="2" name="theme_type" type="StringName">
</argument>
<argument index="3" name="value" type="Variant">
</argument>
<description>
- Sets the theme item of [code]data_type[/code] to [code]value[/code] at [code]name[/code] in [code]node_type[/code].
+ Sets the theme item of [code]data_type[/code] to [code]value[/code] at [code]name[/code] in [code]theme_type[/code].
Does nothing if the [code]value[/code] type does not match [code]data_type[/code].
- Creates [code]node_type[/code] if the theme does not have it.
+ Creates [code]theme_type[/code] if the theme does not have it.
</description>
</method>
</methods>
diff --git a/doc/classes/Thread.xml b/doc/classes/Thread.xml
index 88f46e3937..5ac9416b72 100644
--- a/doc/classes/Thread.xml
+++ b/doc/classes/Thread.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Thread" inherits="Reference" version="4.0">
+<class name="Thread" inherits="RefCounted" version="4.0">
<brief_description>
A unit of execution in a process.
</brief_description>
diff --git a/doc/classes/TileData.xml b/doc/classes/TileData.xml
index e3bc910ab6..efcbdf2e95 100644
--- a/doc/classes/TileData.xml
+++ b/doc/classes/TileData.xml
@@ -229,7 +229,7 @@
</member>
<member name="transpose" type="bool" setter="set_transpose" getter="get_transpose" default="false">
</member>
- <member name="y_sort_origin" type="Vector2i" setter="set_y_sort_origin" getter="get_y_sort_origin" default="Vector2i( 0, 0 )">
+ <member name="y_sort_origin" type="int" setter="set_y_sort_origin" getter="get_y_sort_origin" default="0">
</member>
<member name="z_index" type="int" setter="set_z_index" getter="get_z_index" default="0">
</member>
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index fd52a28486..93d5dd8037 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -132,6 +132,10 @@
<member name="cell_quadrant_size" type="int" setter="set_quadrant_size" getter="get_quadrant_size" default="16">
The TileMap's quadrant size. Optimizes drawing by batching, using chunks of this size.
</member>
+ <member name="show_collision" type="int" setter="set_collision_visibility_mode" getter="get_collision_visibility_mode" enum="TileMap.VisibilityMode" default="0">
+ </member>
+ <member name="show_navigation" type="int" setter="set_navigation_visibility_mode" getter="get_navigation_visibility_mode" enum="TileMap.VisibilityMode" default="0">
+ </member>
<member name="tile_set" type="TileSet" setter="set_tileset" getter="get_tileset">
The assigned [TileSet].
</member>
@@ -144,5 +148,11 @@
</signal>
</signals>
<constants>
+ <constant name="VISIBILITY_MODE_DEFAULT" value="0" enum="VisibilityMode">
+ </constant>
+ <constant name="VISIBILITY_MODE_FORCE_HIDE" value="2" enum="VisibilityMode">
+ </constant>
+ <constant name="VISIBILITY_MODE_FORCE_SHOW" value="1" enum="VisibilityMode">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml
index ff68a017a1..2015b1f1cd 100644
--- a/doc/classes/TileSet.xml
+++ b/doc/classes/TileSet.xml
@@ -20,7 +20,7 @@
<method name="add_source">
<return type="int">
</return>
- <argument index="0" name="atlas_source_id_override" type="TileSetAtlasSource">
+ <argument index="0" name="atlas_source_id_override" type="TileSetSource">
</argument>
<argument index="1" name="arg1" type="int" default="-1">
</argument>
diff --git a/doc/classes/TileSetScenesCollectionSource.xml b/doc/classes/TileSetScenesCollectionSource.xml
new file mode 100644
index 0000000000..1a00eb51c0
--- /dev/null
+++ b/doc/classes/TileSetScenesCollectionSource.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="TileSetScenesCollectionSource" inherits="TileSetSource" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="create_scene_tile">
+ <return type="int">
+ </return>
+ <argument index="0" name="packed_scene" type="PackedScene">
+ </argument>
+ <argument index="1" name="id_override" type="int" default="-1">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_alternative_tile_id" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="atlas_coords" type="Vector2i">
+ </argument>
+ <argument index="1" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_alternative_tiles_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="atlas_coords" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_next_scene_tile_id" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_scene_tile_display_placeholder" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_scene_tile_id">
+ <return type="int">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_scene_tile_scene" qualifiers="const">
+ <return type="PackedScene">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_scene_tiles_count">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_tile_id" qualifiers="const">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_tiles_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="has_alternative_tile" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="atlas_coords" type="Vector2i">
+ </argument>
+ <argument index="1" name="alternative_tile" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="has_scene_tile_id">
+ <return type="bool">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="has_tile" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="atlas_coords" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="remove_scene_tile">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_scene_tile_display_placeholder">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="display_placeholder" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_scene_tile_id">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="new_id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_scene_tile_scene">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="packed_scene" type="PackedScene">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/Time.xml b/doc/classes/Time.xml
new file mode 100644
index 0000000000..0c7c090e97
--- /dev/null
+++ b/doc/classes/Time.xml
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Time" inherits="Object" version="4.0">
+ <brief_description>
+ Time singleton for working with time.
+ </brief_description>
+ <description>
+ The Time singleton allows converting time between various formats and also getting time information from the system.
+ This class conforms with as many of the ISO 8601 standards as possible. All dates follow the Proleptic Gregorian calendar. As such, the day before [code]1582-10-15[/code] is [code]1582-10-14[/code], not [code]1582-10-04[/code]. The year before 1 AD (aka 1 BC) is number [code]0[/code], with the year before that (2 BC) being [code]-1[/code], etc.
+ Conversion methods assume "the same timezone", and do not handle timezone conversions or DST automatically. Leap seconds are also not handled, they must be done manually if desired. Suffixes such as "Z" are not handled, you need to strip them away manually.
+ [b]Important:[/b] The [code]_from_system[/code] methods use the system clock that the user can manually set. [b]Never use[/b] this method for precise time calculation since its results are subject to automatic adjustments by the user or the operating system. [b]Always use[/b] [method get_ticks_usec] or [method get_ticks_msec] for precise time calculation instead, since they are guaranteed to be monotonic (i.e. never decrease).
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_date_dict_from_system" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="utc" type="bool" default="false">
+ </argument>
+ <description>
+ Returns the current date as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], and [code]dst[/code] (Daylight Savings Time).
+ The returned values are in the system's local time when [code]utc[/code] is false, otherwise they are in UTC.
+ </description>
+ </method>
+ <method name="get_date_dict_from_unix_time" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="unix_time_val" type="int">
+ </argument>
+ <description>
+ Converts the given Unix timestamp to a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], and [code]weekday[/code].
+ </description>
+ </method>
+ <method name="get_date_string_from_system" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="utc" type="bool" default="false">
+ </argument>
+ <description>
+ Returns the current date as an ISO 8601 date string (YYYY-MM-DD).
+ The returned values are in the system's local time when [code]utc[/code] is false, otherwise they are in UTC.
+ </description>
+ </method>
+ <method name="get_date_string_from_unix_time" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="unix_time_val" type="int">
+ </argument>
+ <description>
+ Converts the given Unix timestamp to an ISO 8601 date string (YYYY-MM-DD).
+ </description>
+ </method>
+ <method name="get_datetime_dict_from_string" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="datetime" type="String">
+ </argument>
+ <argument index="1" name="weekday" type="bool">
+ </argument>
+ <description>
+ Converts the given ISO 8601 date and time string (YYYY-MM-DDTHH:MM:SS) to a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], [code]hour[/code], [code]minute[/code], and [code]second[/code].
+ If [code]weekday[/code] is false, then the [code]weekday[/code] entry is excluded (the calculation is relatively expensive).
+ </description>
+ </method>
+ <method name="get_datetime_dict_from_system" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="utc" type="bool" default="false">
+ </argument>
+ <description>
+ Returns the current date as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], [code]hour[/code], [code]minute[/code], and [code]second[/code].
+ </description>
+ </method>
+ <method name="get_datetime_dict_from_unix_time" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="unix_time_val" type="int">
+ </argument>
+ <description>
+ Converts the given Unix timestamp to a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], and [code]weekday[/code].
+ The returned Dictionary's values will be the same as the [method get_datetime_dict_from_system] if the Unix timestamp is the current time, with the exception of Daylight Savings Time as it cannot be determined from the epoch.
+ </description>
+ </method>
+ <method name="get_datetime_string_from_dict" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="datetime" type="Dictionary">
+ </argument>
+ <argument index="1" name="use_space" type="bool">
+ </argument>
+ <description>
+ Converts the given dictionary of keys to an ISO 8601 date and time string (YYYY-MM-DDTHH:MM:SS).
+ The given dictionary can be populated with the following keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]hour[/code], [code]minute[/code], and [code]second[/code]. Any other entries (including [code]dst[/code]) are ignored.
+ If the dictionary is empty, [code]0[/code] is returned. If some keys are omitted, they default to the equivalent values for the Unix epoch timestamp 0 (1970-01-01 at 00:00:00).
+ If [code]use_space[/code] is true, use a space instead of the letter T in the middle.
+ </description>
+ </method>
+ <method name="get_datetime_string_from_system" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="utc" type="bool" default="false">
+ </argument>
+ <argument index="1" name="use_space" type="bool" default="false">
+ </argument>
+ <description>
+ Returns the current date and time as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], [code]dst[/code] (Daylight Savings Time), [code]hour[/code], [code]minute[/code], and [code]second[/code].
+ The returned values are in the system's local time when [code]utc[/code] is false, otherwise they are in UTC.
+ If [code]use_space[/code] is true, use a space instead of the letter T in the middle.
+ </description>
+ </method>
+ <method name="get_datetime_string_from_unix_time" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="unix_time_val" type="int">
+ </argument>
+ <argument index="1" name="use_space" type="bool" default="false">
+ </argument>
+ <description>
+ Converts the given Unix timestamp to an ISO 8601 date and time string (YYYY-MM-DDTHH:MM:SS).
+ If [code]use_space[/code] is true, use a space instead of the letter T in the middle.
+ </description>
+ </method>
+ <method name="get_ticks_msec" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the amount of time passed in milliseconds since the engine started.
+ </description>
+ </method>
+ <method name="get_ticks_usec" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the amount of time passed in microseconds since the engine started.
+ </description>
+ </method>
+ <method name="get_time_dict_from_system" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="utc" type="bool" default="false">
+ </argument>
+ <description>
+ Returns the current time as a dictionary of keys: [code]hour[/code], [code]minute[/code], and [code]second[/code].
+ The returned values are in the system's local time when [code]utc[/code] is false, otherwise they are in UTC.
+ </description>
+ </method>
+ <method name="get_time_dict_from_unix_time" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="unix_time_val" type="int">
+ </argument>
+ <description>
+ Converts the given time to a dictionary of keys: [code]hour[/code], [code]minute[/code], and [code]second[/code].
+ </description>
+ </method>
+ <method name="get_time_string_from_system" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="utc" type="bool" default="false">
+ </argument>
+ <description>
+ Returns the current time as an ISO 8601 time string (HH:MM:SS).
+ The returned values are in the system's local time when [code]utc[/code] is false, otherwise they are in UTC.
+ </description>
+ </method>
+ <method name="get_time_string_from_unix_time" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="unix_time_val" type="int">
+ </argument>
+ <description>
+ Converts the given Unix timestamp to an ISO 8601 time string (HH:MM:SS).
+ </description>
+ </method>
+ <method name="get_time_zone_from_system" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <description>
+ Returns the current time zone as a dictionary of keys: [code]bias[/code] and [code]name[/code]. The [code]bias[/code] value is the offset from UTC in minutes, since not all time zones are multiples of an hour from UTC.
+ </description>
+ </method>
+ <method name="get_unix_time_from_datetime_dict" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="datetime" type="Dictionary">
+ </argument>
+ <description>
+ Converts a dictionary of time values to a Unix timestamp.
+ The given dictionary can be populated with the following keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]hour[/code], [code]minute[/code], and [code]second[/code]. Any other entries (including [code]dst[/code]) are ignored.
+ If the dictionary is empty, [code]0[/code] is returned. If some keys are omitted, they default to the equivalent values for the Unix epoch timestamp 0 (1970-01-01 at 00:00:00).
+ You can pass the output from [method get_datetime_dict_from_unix_time] directly into this function and get the same as what was put in.
+ </description>
+ </method>
+ <method name="get_unix_time_from_datetime_string" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="datetime" type="String">
+ </argument>
+ <description>
+ Converts the given ISO 8601 date and/or time string to a Unix timestamp. The string can contain a date only, a time only, or both.
+ </description>
+ </method>
+ <method name="get_unix_time_from_system" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Returns the current Unix timestamp in seconds based on the system time.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ <constant name="MONTH_JANUARY" value="1" enum="Month">
+ The month of January, represented numerically as [code]01[/code].
+ </constant>
+ <constant name="MONTH_FEBRUARY" value="2" enum="Month">
+ The month of February, represented numerically as [code]02[/code].
+ </constant>
+ <constant name="MONTH_MARCH" value="3" enum="Month">
+ The month of March, represented numerically as [code]03[/code].
+ </constant>
+ <constant name="MONTH_APRIL" value="4" enum="Month">
+ The month of April, represented numerically as [code]04[/code].
+ </constant>
+ <constant name="MONTH_MAY" value="5" enum="Month">
+ The month of May, represented numerically as [code]05[/code].
+ </constant>
+ <constant name="MONTH_JUNE" value="6" enum="Month">
+ The month of June, represented numerically as [code]06[/code].
+ </constant>
+ <constant name="MONTH_JULY" value="7" enum="Month">
+ The month of July, represented numerically as [code]07[/code].
+ </constant>
+ <constant name="MONTH_AUGUST" value="8" enum="Month">
+ The month of August, represented numerically as [code]08[/code].
+ </constant>
+ <constant name="MONTH_SEPTEMBER" value="9" enum="Month">
+ The month of September, represented numerically as [code]09[/code].
+ </constant>
+ <constant name="MONTH_OCTOBER" value="10" enum="Month">
+ The month of October, represented numerically as [code]10[/code].
+ </constant>
+ <constant name="MONTH_NOVEMBER" value="11" enum="Month">
+ The month of November, represented numerically as [code]11[/code].
+ </constant>
+ <constant name="MONTH_DECEMBER" value="12" enum="Month">
+ The month of December, represented numerically as [code]12[/code].
+ </constant>
+ <constant name="WEEKDAY_SUNDAY" value="0" enum="Weekday">
+ The day of the week Sunday, represented numerically as [code]0[/code].
+ </constant>
+ <constant name="WEEKDAY_MONDAY" value="1" enum="Weekday">
+ The day of the week Monday, represented numerically as [code]1[/code].
+ </constant>
+ <constant name="WEEKDAY_TUESDAY" value="2" enum="Weekday">
+ The day of the week Tuesday, represented numerically as [code]2[/code].
+ </constant>
+ <constant name="WEEKDAY_WEDNESDAY" value="3" enum="Weekday">
+ The day of the week Wednesday, represented numerically as [code]3[/code].
+ </constant>
+ <constant name="WEEKDAY_THURSDAY" value="4" enum="Weekday">
+ The day of the week Thursday, represented numerically as [code]4[/code].
+ </constant>
+ <constant name="WEEKDAY_FRIDAY" value="5" enum="Weekday">
+ The day of the week Friday, represented numerically as [code]5[/code].
+ </constant>
+ <constant name="WEEKDAY_SATURDAY" value="6" enum="Weekday">
+ The day of the week Saturday, represented numerically as [code]6[/code].
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml
deleted file mode 100644
index 9d8721e2de..0000000000
--- a/doc/classes/Transform.xml
+++ /dev/null
@@ -1,216 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Transform" version="4.0">
- <brief_description>
- 3D transformation (3×4 matrix).
- </brief_description>
- <description>
- 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations. It can represent transformations such as translation, rotation, or scaling. It consists of a [member basis] (first 3 columns) and a [Vector3] for the [member origin] (last column).
- For more information, read the "Matrices and transforms" documentation article.
- </description>
- <tutorials>
- <link title="Math tutorial index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link>
- <link title="Matrices and transforms">https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html</link>
- <link title="Using 3D transforms">https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html</link>
- <link title="Matrix Transform Demo">https://godotengine.org/asset-library/asset/584</link>
- <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link>
- <link title="2.5D Demo">https://godotengine.org/asset-library/asset/583</link>
- </tutorials>
- <methods>
- <method name="Transform" qualifiers="constructor">
- <return type="Transform">
- </return>
- <description>
- Constructs a default-initialized [Transform] set to [constant IDENTITY].
- </description>
- </method>
- <method name="Transform" qualifiers="constructor">
- <return type="Transform">
- </return>
- <argument index="0" name="from" type="Transform">
- </argument>
- <description>
- Constructs a [Transform] as a copy of the given [Transform].
- </description>
- </method>
- <method name="Transform" qualifiers="constructor">
- <return type="Transform">
- </return>
- <argument index="0" name="basis" type="Basis">
- </argument>
- <argument index="1" name="origin" type="Vector3">
- </argument>
- <description>
- Constructs a Transform from a [Basis] and [Vector3].
- </description>
- </method>
- <method name="Transform" qualifiers="constructor">
- <return type="Transform">
- </return>
- <argument index="0" name="x_axis" type="Vector3">
- </argument>
- <argument index="1" name="y_axis" type="Vector3">
- </argument>
- <argument index="2" name="z_axis" type="Vector3">
- </argument>
- <argument index="3" name="origin" type="Vector3">
- </argument>
- <description>
- Constructs a Transform from four [Vector3] values (matrix columns). Each axis corresponds to local basis vectors (some of which may be scaled).
- </description>
- </method>
- <method name="affine_inverse" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- Returns the inverse of the transform, under the assumption that the transformation is composed of rotation, scaling and translation.
- </description>
- </method>
- <method name="interpolate_with" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="xform" type="Transform">
- </argument>
- <argument index="1" name="weight" type="float">
- </argument>
- <description>
- Interpolates the transform to other Transform by weight amount (on the range of 0.0 to 1.0).
- </description>
- </method>
- <method name="inverse" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- Returns the inverse of the transform, under the assumption that the transformation is composed of rotation and translation (no scaling, use affine_inverse for transforms with scaling).
- </description>
- </method>
- <method name="is_equal_approx" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="xform" type="Transform">
- </argument>
- <description>
- Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
- </description>
- </method>
- <method name="looking_at" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="target" type="Vector3">
- </argument>
- <argument index="1" name="up" type="Vector3" default="Vector3( 0, 1, 0 )">
- </argument>
- <description>
- Returns a copy of the transform rotated such that its -Z axis points towards the [code]target[/code] position.
- The transform will first be rotated around the given [code]up[/code] vector, and then fully aligned to the target by a further rotation around an axis perpendicular to both the [code]target[/code] and [code]up[/code] vectors.
- Operations take place in global space.
- </description>
- </method>
- <method name="operator !=" qualifiers="operator">
- <return type="bool">
- </return>
- <argument index="0" name="right" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator *" qualifiers="operator">
- <return type="PackedVector3Array">
- </return>
- <argument index="0" name="right" type="PackedVector3Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator *" qualifiers="operator">
- <return type="Transform">
- </return>
- <argument index="0" name="right" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator *" qualifiers="operator">
- <return type="AABB">
- </return>
- <argument index="0" name="right" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator *" qualifiers="operator">
- <return type="Vector3">
- </return>
- <argument index="0" name="right" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="operator ==" qualifiers="operator">
- <return type="bool">
- </return>
- <argument index="0" name="right" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="orthonormalized" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- Returns the transform with the basis orthogonal (90 degrees), and normalized axis vectors.
- </description>
- </method>
- <method name="rotated" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="axis" type="Vector3">
- </argument>
- <argument index="1" name="phi" type="float">
- </argument>
- <description>
- Rotates the transform around the given axis by the given angle (in radians), using matrix multiplication. The axis must be a normalized vector.
- </description>
- </method>
- <method name="scaled" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="scale" type="Vector3">
- </argument>
- <description>
- Scales basis and origin of the transform by the given scale factor, using matrix multiplication.
- </description>
- </method>
- <method name="translated" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="offset" type="Vector3">
- </argument>
- <description>
- Translates the transform by the given offset, relative to the transform's basis vectors.
- Unlike [method rotated] and [method scaled], this does not use matrix multiplication.
- </description>
- </method>
- </methods>
- <members>
- <member name="basis" type="Basis" setter="" getter="" default="Basis( 1, 0, 0, 0, 1, 0, 0, 0, 1 )">
- The basis is a matrix containing 3 [Vector3] as its columns: X axis, Y axis, and Z axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object.
- </member>
- <member name="origin" type="Vector3" setter="" getter="" default="Vector3( 0, 0, 0 )">
- The translation offset of the transform (column 3, the fourth column). Equivalent to array index [code]3[/code].
- </member>
- </members>
- <constants>
- <constant name="IDENTITY" value="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
- [Transform] with no translation, rotation or scaling applied. When applied to other data structures, [constant IDENTITY] performs no transformation.
- </constant>
- <constant name="FLIP_X" value="Transform( -1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
- [Transform] with mirroring applied perpendicular to the YZ plane.
- </constant>
- <constant name="FLIP_Y" value="Transform( 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0 )">
- [Transform] with mirroring applied perpendicular to the XZ plane.
- </constant>
- <constant name="FLIP_Z" value="Transform( 1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0 )">
- [Transform] with mirroring applied perpendicular to the XY plane.
- </constant>
- </constants>
-</class>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index 6ae7fbcf79..0dbf95376a 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -18,7 +18,7 @@
<return type="Transform2D">
</return>
<description>
- Constructs a default-initialized [Transform] set to [constant IDENTITY].
+ Constructs a default-initialized [Transform2D] set to [constant IDENTITY].
</description>
</method>
<method name="Transform2D" qualifiers="constructor">
@@ -129,6 +129,16 @@
Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
</description>
</method>
+ <method name="looking_at" qualifiers="const">
+ <return type="Transform2D">
+ </return>
+ <argument index="0" name="target" type="Vector2" default="Transform2D( 1, 0, 0, 1, 0, 0 )">
+ </argument>
+ <description>
+ Returns a copy of the transform rotated such that it's rotation on the X-axis points towards the [code]target[/code] position.
+ Operations take place in global space.
+ </description>
+ </method>
<method name="operator !=" qualifiers="operator">
<return type="bool">
</return>
@@ -138,33 +148,33 @@
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="Vector2">
+ <return type="PackedVector2Array">
</return>
- <argument index="0" name="right" type="Vector2">
+ <argument index="0" name="right" type="PackedVector2Array">
</argument>
<description>
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="Rect2">
+ <return type="Transform2D">
</return>
- <argument index="0" name="right" type="Rect2">
+ <argument index="0" name="right" type="Transform2D">
</argument>
<description>
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="Transform2D">
+ <return type="Rect2">
</return>
- <argument index="0" name="right" type="Transform2D">
+ <argument index="0" name="right" type="Rect2">
</argument>
<description>
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="PackedVector2Array">
+ <return type="Vector2">
</return>
- <argument index="0" name="right" type="PackedVector2Array">
+ <argument index="0" name="right" type="Vector2">
</argument>
<description>
</description>
@@ -210,6 +220,15 @@
Scales the transform by the given scale factor, using matrix multiplication.
</description>
</method>
+ <method name="set_rotation">
+ <return type="void">
+ </return>
+ <argument index="0" name="rotation" type="float">
+ </argument>
+ <description>
+ Sets the transform's rotation (in radians).
+ </description>
+ </method>
<method name="translated" qualifiers="const">
<return type="Transform2D">
</return>
diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml
new file mode 100644
index 0000000000..0d49255523
--- /dev/null
+++ b/doc/classes/Transform3D.xml
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Transform3D" version="4.0">
+ <brief_description>
+ 3D transformation (3×4 matrix).
+ </brief_description>
+ <description>
+ 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations. It can represent transformations such as translation, rotation, or scaling. It consists of a [member basis] (first 3 columns) and a [Vector3] for the [member origin] (last column).
+ For more information, read the "Matrices and transforms" documentation article.
+ </description>
+ <tutorials>
+ <link title="Math tutorial index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link>
+ <link title="Matrices and transforms">https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html</link>
+ <link title="Using 3D transforms">https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html</link>
+ <link title="Matrix Transform Demo">https://godotengine.org/asset-library/asset/584</link>
+ <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link>
+ <link title="2.5D Demo">https://godotengine.org/asset-library/asset/583</link>
+ </tutorials>
+ <methods>
+ <method name="Transform3D" qualifiers="constructor">
+ <return type="Transform3D">
+ </return>
+ <description>
+ Constructs a default-initialized [Transform3D] set to [constant IDENTITY].
+ </description>
+ </method>
+ <method name="Transform3D" qualifiers="constructor">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="from" type="Transform3D">
+ </argument>
+ <description>
+ Constructs a [Transform3D] as a copy of the given [Transform3D].
+ </description>
+ </method>
+ <method name="Transform3D" qualifiers="constructor">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="basis" type="Basis">
+ </argument>
+ <argument index="1" name="origin" type="Vector3">
+ </argument>
+ <description>
+ Constructs a Transform3D from a [Basis] and [Vector3].
+ </description>
+ </method>
+ <method name="Transform3D" qualifiers="constructor">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="x_axis" type="Vector3">
+ </argument>
+ <argument index="1" name="y_axis" type="Vector3">
+ </argument>
+ <argument index="2" name="z_axis" type="Vector3">
+ </argument>
+ <argument index="3" name="origin" type="Vector3">
+ </argument>
+ <description>
+ Constructs a Transform3D from four [Vector3] values (matrix columns). Each axis corresponds to local basis vectors (some of which may be scaled).
+ </description>
+ </method>
+ <method name="affine_inverse" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <description>
+ Returns the inverse of the transform, under the assumption that the transformation is composed of rotation, scaling and translation.
+ </description>
+ </method>
+ <method name="interpolate_with" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="xform" type="Transform3D">
+ </argument>
+ <argument index="1" name="weight" type="float">
+ </argument>
+ <description>
+ Interpolates the transform to other Transform3D by weight amount (on the range of 0.0 to 1.0).
+ </description>
+ </method>
+ <method name="inverse" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <description>
+ Returns the inverse of the transform, under the assumption that the transformation is composed of rotation and translation (no scaling, use affine_inverse for transforms with scaling).
+ </description>
+ </method>
+ <method name="is_equal_approx" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="xform" type="Transform3D">
+ </argument>
+ <description>
+ Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
+ </description>
+ </method>
+ <method name="looking_at" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="target" type="Vector3">
+ </argument>
+ <argument index="1" name="up" type="Vector3" default="Vector3( 0, 1, 0 )">
+ </argument>
+ <description>
+ Returns a copy of the transform rotated such that its -Z axis points towards the [code]target[/code] position.
+ The transform will first be rotated around the given [code]up[/code] vector, and then fully aligned to the target by a further rotation around an axis perpendicular to both the [code]target[/code] and [code]up[/code] vectors.
+ Operations take place in global space.
+ </description>
+ </method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Transform3D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="PackedVector3Array">
+ </return>
+ <argument index="0" name="right" type="PackedVector3Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="right" type="Transform3D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="AABB">
+ </return>
+ <argument index="0" name="right" type="AABB">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Transform3D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="orthonormalized" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <description>
+ Returns the transform with the basis orthogonal (90 degrees), and normalized axis vectors.
+ </description>
+ </method>
+ <method name="rotated" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="axis" type="Vector3">
+ </argument>
+ <argument index="1" name="phi" type="float">
+ </argument>
+ <description>
+ Rotates the transform around the given axis by the given angle (in radians), using matrix multiplication. The axis must be a normalized vector.
+ </description>
+ </method>
+ <method name="scaled" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="scale" type="Vector3">
+ </argument>
+ <description>
+ Scales basis and origin of the transform by the given scale factor, using matrix multiplication.
+ </description>
+ </method>
+ <method name="translated" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="offset" type="Vector3">
+ </argument>
+ <description>
+ Translates the transform by the given offset, relative to the transform's basis vectors.
+ Unlike [method rotated] and [method scaled], this does not use matrix multiplication.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="basis" type="Basis" setter="" getter="" default="Basis( 1, 0, 0, 0, 1, 0, 0, 0, 1 )">
+ The basis is a matrix containing 3 [Vector3] as its columns: X axis, Y axis, and Z axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object.
+ </member>
+ <member name="origin" type="Vector3" setter="" getter="" default="Vector3( 0, 0, 0 )">
+ The translation offset of the transform (column 3, the fourth column). Equivalent to array index [code]3[/code].
+ </member>
+ </members>
+ <constants>
+ <constant name="IDENTITY" value="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ [Transform3D] with no translation, rotation or scaling applied. When applied to other data structures, [constant IDENTITY] performs no transformation.
+ </constant>
+ <constant name="FLIP_X" value="Transform3D( -1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ [Transform3D] with mirroring applied perpendicular to the YZ plane.
+ </constant>
+ <constant name="FLIP_Y" value="Transform3D( 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0 )">
+ [Transform3D] with mirroring applied perpendicular to the XZ plane.
+ </constant>
+ <constant name="FLIP_Z" value="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0 )">
+ [Transform3D] with mirroring applied perpendicular to the XY plane.
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index a09f1bf470..fe83bf9c2d 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -30,7 +30,7 @@
}
[/csharp]
[/codeblocks]
- To iterate over all the [TreeItem] objects in a [Tree] object, use [method TreeItem.get_next] and [method TreeItem.get_children] after getting the root through [method get_root]. You can use [method Object.free] on a [TreeItem] to remove it from the [Tree].
+ To iterate over all the [TreeItem] objects in a [Tree] object, use [method TreeItem.get_next] and [method TreeItem.get_first_child] after getting the root through [method get_root]. You can use [method Object.free] on a [TreeItem] to remove it from the [Tree].
</description>
<tutorials>
</tutorials>
@@ -361,7 +361,7 @@
The number of columns.
</member>
<member name="drop_mode_flags" type="int" setter="set_drop_mode_flags" getter="get_drop_mode_flags" default="0">
- The drop mode as an OR combination of flags. See [enum DropModeFlags] constants. Once dropping is done, reverts to [constant DROP_MODE_DISABLED]. Setting this during [method Control.can_drop_data] is recommended.
+ The drop mode as an OR combination of flags. See [enum DropModeFlags] constants. Once dropping is done, reverts to [constant DROP_MODE_DISABLED]. Setting this during [method Control._can_drop_data] is recommended.
This controls the drop sections, i.e. the decision and drawing of possible drop locations based on the mouse position.
</member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" />
@@ -533,6 +533,12 @@
<theme_item name="checked" type="Texture2D">
The check icon to display when the [constant TreeItem.CELL_MODE_CHECK] mode cell is checked.
</theme_item>
+ <theme_item name="children_hl_line_color" type="Color" default="Color( 0.27, 0.27, 0.27, 1 )">
+ The [Color] of the relationship lines between the selected [TreeItem] and its children.
+ </theme_item>
+ <theme_item name="children_hl_line_width" type="int" default="1">
+ The width of the relationship lines between the selected [TreeItem] and its children.
+ </theme_item>
<theme_item name="cursor" type="StyleBox">
[StyleBox] used for the cursor, when the [Tree] is being focused.
</theme_item>
@@ -587,8 +593,20 @@
<theme_item name="outline_size" type="int" default="0">
The size of the text outline.
</theme_item>
+ <theme_item name="parent_hl_line_color" type="Color" default="Color( 0.27, 0.27, 0.27, 1 )">
+ The [Color] of the relationship lines between the selected [TreeItem] and its parents.
+ </theme_item>
+ <theme_item name="parent_hl_line_margin" type="int" default="0">
+ The space between the parent relationship lines for the selected [TreeItem] and the relationship lines to its siblings that are not selected.
+ </theme_item>
+ <theme_item name="parent_hl_line_width" type="int" default="1">
+ The width of the relationship lines between the selected [TreeItem] and its parents.
+ </theme_item>
<theme_item name="relationship_line_color" type="Color" default="Color( 0.27, 0.27, 0.27, 1 )">
- [Color] of the relationship lines.
+ The default [Color] of the relationship lines.
+ </theme_item>
+ <theme_item name="relationship_line_width" type="int" default="1">
+ The default width of the relationship lines.
</theme_item>
<theme_item name="scroll_border" type="int" default="4">
The maximum distance between the mouse cursor and the control's border to trigger border scrolling when dragging.
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index add23c2ce6..0256d83fea 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -63,6 +63,16 @@
Removes all OpenType features.
</description>
</method>
+ <method name="create_child">
+ <return type="TreeItem">
+ </return>
+ <argument index="0" name="idx" type="int" default="-1">
+ </argument>
+ <description>
+ Creates an item and adds it as a child.
+ The new item will be inserted as position [code]idx[/code] (the default value [code]-1[/code] means the last position), or it will be the last child if [code]idx[/code] is higher than the child count.
+ </description>
+ </method>
<method name="deselect">
<return type="void">
</return>
@@ -123,11 +133,28 @@
Returns the column's cell mode.
</description>
</method>
- <method name="get_children">
+ <method name="get_child">
<return type="TreeItem">
</return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ Returns a child item by its index (see [method get_child_count]). This method is often used for iterating all children of an item.
+ Negative indices access the children from the last one.
+ </description>
+ </method>
+ <method name="get_child_count">
+ <return type="int">
+ </return>
<description>
- Returns the TreeItem's first child item or a null object if there is none.
+ Returns the number of child items.
+ </description>
+ </method>
+ <method name="get_children">
+ <return type="Array">
+ </return>
+ <description>
+ Returns an array of references to the item's children.
</description>
</method>
<method name="get_custom_bg_color" qualifiers="const">
@@ -148,6 +175,14 @@
Returns the custom color of column [code]column[/code].
</description>
</method>
+ <method name="get_custom_font" qualifiers="const">
+ <return type="Font">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_expand_right" qualifiers="const">
<return type="bool">
</return>
@@ -157,6 +192,13 @@
Returns [code]true[/code] if [code]expand_right[/code] is set.
</description>
</method>
+ <method name="get_first_child">
+ <return type="TreeItem">
+ </return>
+ <description>
+ Returns the TreeItem's first child.
+ </description>
+ </method>
<method name="get_icon" qualifiers="const">
<return type="Texture2D">
</return>
@@ -193,6 +235,13 @@
Returns the icon [Texture2D] region as [Rect2].
</description>
</method>
+ <method name="get_index">
+ <return type="int">
+ </return>
+ <description>
+ Returns the node's order in the tree. For example, if called on the first child item the position is [code]0[/code].
+ </description>
+ </method>
<method name="get_language" qualifiers="const">
<return type="String">
</return>
@@ -342,6 +391,13 @@
Returns the given column's tooltip.
</description>
</method>
+ <method name="get_tree">
+ <return type="Tree">
+ </return>
+ <description>
+ Returns the [Tree] that owns this TreeItem.
+ </description>
+ </method>
<method name="is_button_disabled" qualifiers="const">
<return type="bool">
</return>
@@ -397,18 +453,24 @@
Returns [code]true[/code] if column [code]column[/code] is selected.
</description>
</method>
- <method name="move_to_bottom">
+ <method name="move_after">
<return type="void">
</return>
+ <argument index="0" name="item" type="Object">
+ </argument>
<description>
- Moves this TreeItem to the bottom in the [Tree] hierarchy.
+ Moves this TreeItem right after the given [code]item[/code].
+ [b]Note:[/b] You can't move to the root or move the root.
</description>
</method>
- <method name="move_to_top">
+ <method name="move_before">
<return type="void">
</return>
+ <argument index="0" name="item" type="Object">
+ </argument>
<description>
- Moves this TreeItem to the top in the [Tree] hierarchy.
+ Moves this TreeItem right before the given [code]item[/code].
+ [b]Note:[/b] You can't move to the root or move the root.
</description>
</method>
<method name="remove_child">
@@ -525,6 +587,16 @@
The [code]callback[/code] should accept two arguments: the [TreeItem] that is drawn and its position and size as a [Rect2].
</description>
</method>
+ <method name="set_custom_font">
+ <return type="void">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <argument index="1" name="font" type="Font">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_editable">
<return type="void">
</return>
diff --git a/doc/classes/TriangleMesh.xml b/doc/classes/TriangleMesh.xml
index 39bee0c2b3..cfdb6fe33e 100644
--- a/doc/classes/TriangleMesh.xml
+++ b/doc/classes/TriangleMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TriangleMesh" inherits="Reference" version="4.0">
+<class name="TriangleMesh" inherits="RefCounted" version="4.0">
<brief_description>
Internal mesh type.
</brief_description>
diff --git a/doc/classes/UDPServer.xml b/doc/classes/UDPServer.xml
index 6f3ccb8a17..5e2906450c 100644
--- a/doc/classes/UDPServer.xml
+++ b/doc/classes/UDPServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="UDPServer" inherits="Reference" version="4.0">
+<class name="UDPServer" inherits="RefCounted" version="4.0">
<brief_description>
Helper class to implement a UDP server.
</brief_description>
diff --git a/doc/classes/Variant.xml b/doc/classes/Variant.xml
index 775bd58bcf..240c1c909f 100644
--- a/doc/classes/Variant.xml
+++ b/doc/classes/Variant.xml
@@ -5,20 +5,30 @@
</brief_description>
<description>
In computer programming, a Variant class is a class that is designed to store a variety of other types. Dynamic programming languages like PHP, Lua, JavaScript and GDScript like to use them to store variables' data on the backend. With these Variants, properties are able to change value types freely.
- [codeblock]
+ [codeblocks]
+ [gdscript]
var foo = 2 # foo is dynamically an integer
foo = "Now foo is a string!"
- foo = Reference.new() # foo is an Object
+ foo = RefCounted.new() # foo is an Object
var bar: int = 2 # bar is a statically typed integer.
# bar = "Uh oh! I can't make static variables become a different type!"
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ // ... but C# is statically typed. Once a variable has a type it cannot be changed. However you can use the var keyword in methods to let the compiler decide the type automatically.
+ var foo = 2; // Foo is a 32-bit integer (int). Be cautious, integers in GDScript are 64-bit and the direct C# equivalent is "long".
+ // foo = "foo was and will always be an integer. It cannot be turned into a string!";
+ var boo = "Boo is a string!";
+ var ref = new Reference(); // var is especially useful when used together with a constructor.
+ [/csharp]
+ [/codeblocks]
Godot tracks all scripting API variables within Variants. Without even realizing it, you use Variants all the time. When a particular language enforces its own rules for keeping data typed, then that language is applying its own custom logic over the base Variant scripting API.
- GDScript automatically wrap values in them. It keeps all data in plain Variants by default and then optionally enforces custom static typing rules on variable types.
- VisualScript tracks properties inside Variants as well, but it also uses static typing. The GUI interface enforces that properties have a particular type that doesn't change over time.
- C# is statically typed, but uses the Mono [code]object[/code] type in place of Godot's Variant class when it needs to represent a dynamic value. [code]object[/code] is the Mono runtime's equivalent of the same concept.
- The statically-typed language NativeScript C++ does not define a built-in Variant-like class. Godot's GDNative bindings provide their own godot::Variant class for users; Any point at which the C++ code starts interacting with the Godot runtime is a place where you might have to start wrapping data inside Variant objects.
The global [method @GlobalScope.typeof] function returns the enumerated value of the Variant type stored in the current variable (see [enum Variant.Type]).
- [codeblock]
+ [codeblocks]
+ [gdscript]
var foo = 2
match typeof(foo):
TYPE_NIL:
@@ -32,7 +42,19 @@
# Note also that there is not yet any way to get a script's `class_name` string easily.
# To fetch that value, you need to dig deeply into a hidden ProjectSettings setting: an Array of Dictionaries called "_global_script_classes".
# Open your project.godot file to see it up close.
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ int foo = 2;
+ if (foo == null)
+ {
+ GD.Print("foo is null");
+ }
+ if (foo is int)
+ {
+ GD.Print("foo is an integer");
+ }
+ [/csharp]
+ [/codeblocks]
A Variant takes up only 20 bytes and can store almost any engine datatype inside of it. Variants are rarely used to hold information for long periods of time. Instead, they are used mainly for communication, editing, serialization and moving data around.
Godot has specifically invested in making its Variant class as flexible as possible; so much so that it is used for a multitude of operations to facilitate communication between all of Godot's systems.
A Variant:
diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml
index 94d4b1a903..1390a5e45b 100644
--- a/doc/classes/Vector2.xml
+++ b/doc/classes/Vector2.xml
@@ -110,13 +110,15 @@
Returns the vector with all components rounded up (towards positive infinity).
</description>
</method>
- <method name="clamped" qualifiers="const">
+ <method name="clamp" qualifiers="const">
<return type="Vector2">
</return>
- <argument index="0" name="length" type="float">
+ <argument index="0" name="min" type="Vector2">
+ </argument>
+ <argument index="1" name="max" type="Vector2">
</argument>
<description>
- Returns the vector with a maximum length by limiting its length to [code]length[/code].
+ Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component.
</description>
</method>
<method name="cross" qualifiers="const">
@@ -232,6 +234,15 @@
Returns the result of the linear interpolation between this vector and [code]to[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation.
</description>
</method>
+ <method name="limit_length" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="length" type="float" default="1.0">
+ </argument>
+ <description>
+ Returns the vector with a maximum length by limiting its length to [code]length[/code].
+ </description>
+ </method>
<method name="move_toward" qualifiers="const">
<return type="Vector2">
</return>
diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml
index b38b968ba3..6efb52b712 100644
--- a/doc/classes/Vector2i.xml
+++ b/doc/classes/Vector2i.xml
@@ -64,6 +64,17 @@
Returns the ratio of [member x] to [member y].
</description>
</method>
+ <method name="clamp" qualifiers="const">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="min" type="Vector2i">
+ </argument>
+ <argument index="1" name="max" type="Vector2i">
+ </argument>
+ <description>
+ Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component.
+ </description>
+ </method>
<method name="operator !=" qualifiers="operator">
<return type="bool">
</return>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index 0a86369506..b6effd441b 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -87,6 +87,17 @@
Returns a new vector with all components rounded up (towards positive infinity).
</description>
</method>
+ <method name="clamp" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="min" type="Vector3">
+ </argument>
+ <argument index="1" name="max" type="Vector3">
+ </argument>
+ <description>
+ Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component.
+ </description>
+ </method>
<method name="cross" qualifiers="const">
<return type="Vector3">
</return>
@@ -207,6 +218,15 @@
Returns the result of the linear interpolation between this vector and [code]to[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation.
</description>
</method>
+ <method name="limit_length" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="length" type="float" default="1.0">
+ </argument>
+ <description>
+ Returns the vector with a maximum length by limiting its length to [code]length[/code].
+ </description>
+ </method>
<method name="max_axis" qualifiers="const">
<return type="int">
</return>
@@ -266,7 +286,7 @@
<method name="operator *" qualifiers="operator">
<return type="Vector3">
</return>
- <argument index="0" name="right" type="Quat">
+ <argument index="0" name="right" type="Quaternion">
</argument>
<description>
</description>
@@ -274,7 +294,7 @@
<method name="operator *" qualifiers="operator">
<return type="Vector3">
</return>
- <argument index="0" name="right" type="Transform">
+ <argument index="0" name="right" type="Transform3D">
</argument>
<description>
</description>
diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml
index ea5945f5b7..6e8a34b692 100644
--- a/doc/classes/Vector3i.xml
+++ b/doc/classes/Vector3i.xml
@@ -58,6 +58,17 @@
<description>
</description>
</method>
+ <method name="clamp" qualifiers="const">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="min" type="Vector3i">
+ </argument>
+ <argument index="1" name="max" type="Vector3i">
+ </argument>
+ <description>
+ Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component.
+ </description>
+ </method>
<method name="max_axis" qualifiers="const">
<return type="int">
</return>
diff --git a/doc/classes/VelocityTracker3D.xml b/doc/classes/VelocityTracker3D.xml
index 98f7533c76..2d5e3a4d30 100644
--- a/doc/classes/VelocityTracker3D.xml
+++ b/doc/classes/VelocityTracker3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VelocityTracker3D" inherits="Reference" version="4.0">
+<class name="VelocityTracker3D" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml
index d905ce4054..12558ebbbc 100644
--- a/doc/classes/VideoPlayer.xml
+++ b/doc/classes/VideoPlayer.xml
@@ -60,7 +60,7 @@
<member name="buffering_msec" type="int" setter="set_buffering_msec" getter="get_buffering_msec" default="500">
Amount of time in milliseconds to store in buffer while playing.
</member>
- <member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="@&quot;Master&quot;">
+ <member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="&amp;&quot;Master&quot;">
Audio bus to use for sound playback.
</member>
<member name="expand" type="bool" setter="set_expand" getter="has_expand" default="true">
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index 1c33274cb0..96d63b27ad 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -81,10 +81,16 @@
<description>
Returns the viewport's texture.
[b]Note:[/b] Due to the way OpenGL works, the resulting [ViewportTexture] is flipped vertically. You can use [method Image.flip_y] on the result of [method Texture2D.get_image] to flip it back, for example:
- [codeblock]
+ [codeblocks]
+ [gdscript]
var img = get_viewport().get_texture().get_image()
img.flip_y()
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ Image img = GetViewport().GetTexture().GetImage();
+ img.FlipY();
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="get_viewport_rid" qualifiers="const">
@@ -105,7 +111,7 @@
<return type="Variant">
</return>
<description>
- Returns the drag data from the GUI, that was previously returned by [method Control.get_drag_data].
+ Returns the drag data from the GUI, that was previously returned by [method Control._get_drag_data].
</description>
</method>
<method name="gui_is_dragging" qualifiers="const">
@@ -382,14 +388,14 @@
</constant>
<constant name="DEBUG_DRAW_NORMAL_BUFFER" value="5" enum="DebugDraw">
</constant>
- <constant name="DEBUG_DRAW_GI_PROBE_ALBEDO" value="6" enum="DebugDraw">
- Objects are displayed with only the albedo value from [GIProbe]s.
+ <constant name="DEBUG_DRAW_VOXEL_GI_ALBEDO" value="6" enum="DebugDraw">
+ Objects are displayed with only the albedo value from [VoxelGI]s.
</constant>
- <constant name="DEBUG_DRAW_GI_PROBE_LIGHTING" value="7" enum="DebugDraw">
- Objects are displayed with only the lighting value from [GIProbe]s.
+ <constant name="DEBUG_DRAW_VOXEL_GI_LIGHTING" value="7" enum="DebugDraw">
+ Objects are displayed with only the lighting value from [VoxelGI]s.
</constant>
- <constant name="DEBUG_DRAW_GI_PROBE_EMISSION" value="8" enum="DebugDraw">
- Objects are displayed with only the emission color from [GIProbe]s.
+ <constant name="DEBUG_DRAW_VOXEL_GI_EMISSION" value="8" enum="DebugDraw">
+ Objects are displayed with only the emission color from [VoxelGI]s.
</constant>
<constant name="DEBUG_DRAW_SHADOW_ATLAS" value="9" enum="DebugDraw">
Draws the shadow atlas that stores shadows from [OmniLight3D]s and [SpotLight3D]s in the upper left quadrant of the [Viewport].
diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml
index 01d569d9c8..2a12254b71 100644
--- a/doc/classes/VisualInstance3D.xml
+++ b/doc/classes/VisualInstance3D.xml
@@ -44,7 +44,7 @@
</return>
<description>
Returns the transformed [AABB] (also known as the bounding box) for this [VisualInstance3D].
- Transformed in this case means the [AABB] plus the position, rotation, and scale of the [Node3D]'s [Transform]. See also [method get_aabb].
+ Transformed in this case means the [AABB] plus the position, rotation, and scale of the [Node3D]'s [Transform3D]. See also [method get_aabb].
</description>
</method>
<method name="set_base">
diff --git a/doc/classes/VisualShader.xml b/doc/classes/VisualShader.xml
index ff00a848b9..775ac88eff 100644
--- a/doc/classes/VisualShader.xml
+++ b/doc/classes/VisualShader.xml
@@ -222,15 +222,19 @@
<constant name="TYPE_LIGHT" value="2" enum="Type">
A shader for light calculations.
</constant>
- <constant name="TYPE_EMIT" value="3" enum="Type">
+ <constant name="TYPE_START" value="3" enum="Type">
</constant>
<constant name="TYPE_PROCESS" value="4" enum="Type">
</constant>
- <constant name="TYPE_END" value="5" enum="Type">
+ <constant name="TYPE_COLLIDE" value="5" enum="Type">
</constant>
- <constant name="TYPE_SKY" value="6" enum="Type">
+ <constant name="TYPE_START_CUSTOM" value="6" enum="Type">
</constant>
- <constant name="TYPE_MAX" value="7" enum="Type">
+ <constant name="TYPE_PROCESS_CUSTOM" value="7" enum="Type">
+ </constant>
+ <constant name="TYPE_SKY" value="8" enum="Type">
+ </constant>
+ <constant name="TYPE_MAX" value="9" enum="Type">
Represents the size of the [enum Type] enum.
</constant>
<constant name="NODE_ID_INVALID" value="-1">
diff --git a/doc/classes/VisualShaderNode.xml b/doc/classes/VisualShaderNode.xml
index 6327ab534f..9a74f2322e 100644
--- a/doc/classes/VisualShaderNode.xml
+++ b/doc/classes/VisualShaderNode.xml
@@ -9,6 +9,13 @@
<link title="VisualShaders">https://docs.godotengine.org/en/latest/tutorials/shading/visual_shaders.html</link>
</tutorials>
<methods>
+ <method name="clear_default_input_values">
+ <return type="void">
+ </return>
+ <description>
+ Clears the default input ports value.
+ </description>
+ </method>
<method name="get_default_input_values" qualifiers="const">
<return type="Array">
</return>
@@ -25,6 +32,15 @@
Returns the default value of the input [code]port[/code].
</description>
</method>
+ <method name="remove_input_port_default_value">
+ <return type="void">
+ </return>
+ <argument index="0" name="port" type="int">
+ </argument>
+ <description>
+ Removes the default value of the input [code]port[/code].
+ </description>
+ </method>
<method name="set_default_input_values">
<return type="void">
</return>
diff --git a/doc/classes/VisualShaderNodeBillboard.xml b/doc/classes/VisualShaderNodeBillboard.xml
new file mode 100644
index 0000000000..53bcfa7b5c
--- /dev/null
+++ b/doc/classes/VisualShaderNodeBillboard.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeBillboard" inherits="VisualShaderNode" version="4.0">
+ <brief_description>
+ A node that controls how the object faces the camera to be used within the visual shader graph.
+ </brief_description>
+ <description>
+ The output port of this node needs to be connected to [code]Model View Matrix[/code] port of [VisualShaderNodeOutput].
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="billboard_type" type="int" setter="set_billboard_type" getter="get_billboard_type" enum="VisualShaderNodeBillboard.BillboardType" default="1">
+ Controls how the object faces the camera. See [enum BillboardType].
+ </member>
+ <member name="keep_scale" type="bool" setter="set_keep_scale_enabled" getter="is_keep_scale_enabled" default="false">
+ If [code]true[/code], the shader will keep the scale set for the mesh. Otherwise, the scale is lost when billboarding.
+ </member>
+ </members>
+ <constants>
+ <constant name="BILLBOARD_TYPE_DISABLED" value="0" enum="BillboardType">
+ Billboarding is disabled and the node does nothing.
+ </constant>
+ <constant name="BILLBOARD_TYPE_ENABLED" value="1" enum="BillboardType">
+ A standard billboarding algorithm is enabled.
+ </constant>
+ <constant name="BILLBOARD_TYPE_FIXED_Y" value="2" enum="BillboardType">
+ A billboarding algorithm to rotate around Y-axis is enabled.
+ </constant>
+ <constant name="BILLBOARD_TYPE_PARTICLES" value="3" enum="BillboardType">
+ A billboarding algorithm designed to use on particles is enabled.
+ </constant>
+ <constant name="BILLBOARD_TYPE_MAX" value="4" enum="BillboardType">
+ Represents the size of the [enum BillboardType] enum.
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeDeterminant.xml b/doc/classes/VisualShaderNodeDeterminant.xml
index 6b042f6172..06b05addfa 100644
--- a/doc/classes/VisualShaderNodeDeterminant.xml
+++ b/doc/classes/VisualShaderNodeDeterminant.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeDeterminant" inherits="VisualShaderNode" version="4.0">
<brief_description>
- Calculates the determinant of a [Transform] within the visual shader graph.
+ Calculates the determinant of a [Transform3D] within the visual shader graph.
</brief_description>
<description>
Translates to [code]determinant(x)[/code] in the shader language.
diff --git a/doc/classes/VisualShaderNodeParticleAccelerator.xml b/doc/classes/VisualShaderNodeParticleAccelerator.xml
new file mode 100644
index 0000000000..82aae1df63
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleAccelerator.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleAccelerator" inherits="VisualShaderNodeOutput" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="VisualShaderNodeParticleAccelerator.Mode" default="0">
+ </member>
+ </members>
+ <constants>
+ <constant name="MODE_LINEAR" value="0" enum="Mode">
+ </constant>
+ <constant name="MODE_RADIAL" value="1" enum="Mode">
+ </constant>
+ <constant name="MODE_TANGENTIAL" value="2" enum="Mode">
+ </constant>
+ <constant name="MODE_MAX" value="3" enum="Mode">
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleBoxEmitter.xml b/doc/classes/VisualShaderNodeParticleBoxEmitter.xml
new file mode 100644
index 0000000000..af33b285d2
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleBoxEmitter.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleBoxEmitter" inherits="VisualShaderNodeParticleEmitter" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleConeVelocity.xml b/doc/classes/VisualShaderNodeParticleConeVelocity.xml
new file mode 100644
index 0000000000..7a40c2a7d0
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleConeVelocity.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleConeVelocity" inherits="VisualShaderNode" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleEmit.xml b/doc/classes/VisualShaderNodeParticleEmit.xml
new file mode 100644
index 0000000000..120b12d643
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleEmit.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleEmit" inherits="VisualShaderNode" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="flags" type="int" setter="set_flags" getter="get_flags" enum="VisualShaderNodeParticleEmit.EmitFlags" default="31">
+ </member>
+ </members>
+ <constants>
+ <constant name="EMIT_FLAG_POSITION" value="1" enum="EmitFlags">
+ </constant>
+ <constant name="EMIT_FLAG_ROT_SCALE" value="2" enum="EmitFlags">
+ </constant>
+ <constant name="EMIT_FLAG_VELOCITY" value="4" enum="EmitFlags">
+ </constant>
+ <constant name="EMIT_FLAG_COLOR" value="8" enum="EmitFlags">
+ </constant>
+ <constant name="EMIT_FLAG_CUSTOM" value="16" enum="EmitFlags">
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleEmitter.xml b/doc/classes/VisualShaderNodeParticleEmitter.xml
new file mode 100644
index 0000000000..3a25fc1c7f
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleEmitter.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleEmitter" inherits="VisualShaderNode" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleMultiplyByAxisAngle.xml b/doc/classes/VisualShaderNodeParticleMultiplyByAxisAngle.xml
new file mode 100644
index 0000000000..89a53699c9
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleMultiplyByAxisAngle.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleMultiplyByAxisAngle" inherits="VisualShaderNode" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="degrees_mode" type="bool" setter="set_degrees_mode" getter="is_degrees_mode" default="true">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleOutput.xml b/doc/classes/VisualShaderNodeParticleOutput.xml
new file mode 100644
index 0000000000..c8fc66f2ff
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleOutput.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleOutput" inherits="VisualShaderNodeOutput" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleRandomness.xml b/doc/classes/VisualShaderNodeParticleRandomness.xml
new file mode 100644
index 0000000000..f19723a663
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleRandomness.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleRandomness" inherits="VisualShaderNode" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="op_type" type="int" setter="set_op_type" getter="get_op_type" enum="VisualShaderNodeParticleRandomness.OpType" default="0">
+ </member>
+ </members>
+ <constants>
+ <constant name="OP_TYPE_SCALAR" value="0" enum="OpType">
+ </constant>
+ <constant name="OP_TYPE_VECTOR" value="1" enum="OpType">
+ </constant>
+ <constant name="OP_TYPE_MAX" value="2" enum="OpType">
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleRingEmitter.xml b/doc/classes/VisualShaderNodeParticleRingEmitter.xml
new file mode 100644
index 0000000000..ee3fbe7faf
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleRingEmitter.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleRingEmitter" inherits="VisualShaderNodeParticleEmitter" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeParticleSphereEmitter.xml b/doc/classes/VisualShaderNodeParticleSphereEmitter.xml
new file mode 100644
index 0000000000..d43ac518cf
--- /dev/null
+++ b/doc/classes/VisualShaderNodeParticleSphereEmitter.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeParticleSphereEmitter" inherits="VisualShaderNodeParticleEmitter" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeTransformCompose.xml b/doc/classes/VisualShaderNodeTransformCompose.xml
index 41762b0099..b82ce9bdd8 100644
--- a/doc/classes/VisualShaderNodeTransformCompose.xml
+++ b/doc/classes/VisualShaderNodeTransformCompose.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTransformCompose" inherits="VisualShaderNode" version="4.0">
<brief_description>
- Composes a [Transform] from four [Vector3]s within the visual shader graph.
+ Composes a [Transform3D] from four [Vector3]s within the visual shader graph.
</brief_description>
<description>
Creates a 4x4 transform matrix using four vectors of type [code]vec3[/code]. Each vector is one row in the matrix and the last column is a [code]vec4(0, 0, 0, 1)[/code].
diff --git a/doc/classes/VisualShaderNodeTransformConstant.xml b/doc/classes/VisualShaderNodeTransformConstant.xml
index b8f054e914..550ed829c9 100644
--- a/doc/classes/VisualShaderNodeTransformConstant.xml
+++ b/doc/classes/VisualShaderNodeTransformConstant.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTransformConstant" inherits="VisualShaderNodeConstant" version="4.0">
<brief_description>
- A [Transform] constant for use within the visual shader graph.
+ A [Transform3D] constant for use within the visual shader graph.
</brief_description>
<description>
- A constant [Transform], which can be used as an input node.
+ A constant [Transform3D], which can be used as an input node.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
- <member name="constant" type="Transform" setter="set_constant" getter="get_constant" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
- A [Transform] constant which represents the state of this node.
+ <member name="constant" type="Transform3D" setter="set_constant" getter="get_constant" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ A [Transform3D] constant which represents the state of this node.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualShaderNodeTransformDecompose.xml b/doc/classes/VisualShaderNodeTransformDecompose.xml
index c8d893db00..b815efc67a 100644
--- a/doc/classes/VisualShaderNodeTransformDecompose.xml
+++ b/doc/classes/VisualShaderNodeTransformDecompose.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTransformDecompose" inherits="VisualShaderNode" version="4.0">
<brief_description>
- Decomposes a [Transform] into four [Vector3]s within the visual shader graph.
+ Decomposes a [Transform3D] into four [Vector3]s within the visual shader graph.
</brief_description>
<description>
Takes a 4x4 transform matrix and decomposes it into four [code]vec3[/code] values, one from each row of the matrix.
diff --git a/doc/classes/VisualShaderNodeTransformFunc.xml b/doc/classes/VisualShaderNodeTransformFunc.xml
index d0b5c5129d..41a58e1458 100644
--- a/doc/classes/VisualShaderNodeTransformFunc.xml
+++ b/doc/classes/VisualShaderNodeTransformFunc.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTransformFunc" inherits="VisualShaderNode" version="4.0">
<brief_description>
- Computes a [Transform] function within the visual shader graph.
+ Computes a [Transform3D] function within the visual shader graph.
</brief_description>
<description>
- Computes an inverse or transpose function on the provided [Transform].
+ Computes an inverse or transpose function on the provided [Transform3D].
</description>
<tutorials>
</tutorials>
@@ -17,10 +17,10 @@
</members>
<constants>
<constant name="FUNC_INVERSE" value="0" enum="Function">
- Perform the inverse operation on the [Transform] matrix.
+ Perform the inverse operation on the [Transform3D] matrix.
</constant>
<constant name="FUNC_TRANSPOSE" value="1" enum="Function">
- Perform the transpose operation on the [Transform] matrix.
+ Perform the transpose operation on the [Transform3D] matrix.
</constant>
</constants>
</class>
diff --git a/doc/classes/VisualShaderNodeTransformMult.xml b/doc/classes/VisualShaderNodeTransformMult.xml
index 02b6e0cd1c..f26f60a1f3 100644
--- a/doc/classes/VisualShaderNodeTransformMult.xml
+++ b/doc/classes/VisualShaderNodeTransformMult.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTransformMult" inherits="VisualShaderNode" version="4.0">
<brief_description>
- Multiplies [Transform] by [Transform] within the visual shader graph.
+ Multiplies [Transform3D] by [Transform3D] within the visual shader graph.
</brief_description>
<description>
A multiplication operation on two transforms (4x4 matrices), with support for different multiplication operators.
diff --git a/doc/classes/VisualShaderNodeTransformUniform.xml b/doc/classes/VisualShaderNodeTransformUniform.xml
index ff6246618d..1f1cc4b630 100644
--- a/doc/classes/VisualShaderNodeTransformUniform.xml
+++ b/doc/classes/VisualShaderNodeTransformUniform.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTransformUniform" inherits="VisualShaderNodeUniform" version="4.0">
<brief_description>
- A [Transform] uniform for use within the visual shader graph.
+ A [Transform3D] uniform for use within the visual shader graph.
</brief_description>
<description>
Translated to [code]uniform mat4[/code] in the shader language.
@@ -11,7 +11,7 @@
<methods>
</methods>
<members>
- <member name="default_value" type="Transform" setter="set_default_value" getter="get_default_value" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ <member name="default_value" type="Transform3D" setter="set_default_value" getter="get_default_value" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
A default value to be assigned within the shader.
</member>
<member name="default_value_enabled" type="bool" setter="set_default_value_enabled" getter="is_default_value_enabled" default="false">
diff --git a/doc/classes/VisualShaderNodeTransformVecMult.xml b/doc/classes/VisualShaderNodeTransformVecMult.xml
index 3d5f87f727..2c9c115d9c 100644
--- a/doc/classes/VisualShaderNodeTransformVecMult.xml
+++ b/doc/classes/VisualShaderNodeTransformVecMult.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTransformVecMult" inherits="VisualShaderNode" version="4.0">
<brief_description>
- Multiplies a [Transform] and a [Vector3] within the visual shader graph.
+ Multiplies a [Transform3D] and a [Vector3] within the visual shader graph.
</brief_description>
<description>
A multiplication operation on a transform (4x4 matrix) and a vector, with support for different multiplication operators.
diff --git a/doc/classes/VisualShaderNodeUVFunc.xml b/doc/classes/VisualShaderNodeUVFunc.xml
new file mode 100644
index 0000000000..042644feb0
--- /dev/null
+++ b/doc/classes/VisualShaderNodeUVFunc.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeUVFunc" inherits="VisualShaderNode" version="4.0">
+ <brief_description>
+ Contains functions to modify texture coordinates ([code]uv[/code]) to be used within the visual shader graph.
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="function" type="int" setter="set_function" getter="get_function" enum="VisualShaderNodeUVFunc.Function" default="0">
+ A function to be applied to the texture coordinates. See [enum Function] for options.
+ </member>
+ </members>
+ <constants>
+ <constant name="FUNC_PANNING" value="0" enum="Function">
+ Translates [code]uv[/code] by using [code]scale[/code] and [code]offset[/code] values using the following formula: [code]uv = uv + offset * scale[/code]. [code]uv[/code] port is connected to [code]UV[/code] built-in by default.
+ </constant>
+ <constant name="FUNC_SCALING" value="1" enum="Function">
+ Scales [code]uv[/uv] by using [code]scale[/code] and [code]pivot[/code] values using the following formula: [code]uv = (uv - pivot) * scale + pivot[/code]. [code]uv[/code] port is connected to [code]UV[/code] built-in by default.
+ </constant>
+ <constant name="FUNC_MAX" value="2" enum="Function">
+ Represents the size of the [enum Function] enum.
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/VoxelGI.xml b/doc/classes/VoxelGI.xml
new file mode 100644
index 0000000000..fa5035349e
--- /dev/null
+++ b/doc/classes/VoxelGI.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VoxelGI" inherits="VisualInstance3D" version="4.0">
+ <brief_description>
+ Real-time global illumination (GI) probe.
+ </brief_description>
+ <description>
+ [VoxelGI]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [VoxelGI]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked.
+ Having [VoxelGI]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/global_illumination/voxel_gi/quality].
+ [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh.
+ </description>
+ <tutorials>
+ <link title="GI probes">https://docs.godotengine.org/en/latest/tutorials/3d/voxel_gi.html</link>
+ <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
+ </tutorials>
+ <methods>
+ <method name="bake">
+ <return type="void">
+ </return>
+ <argument index="0" name="from_node" type="Node" default="null">
+ </argument>
+ <argument index="1" name="create_visual_debug" type="bool" default="false">
+ </argument>
+ <description>
+ Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_BAKED] and [Light3D]s marked with either [constant Light3D.BAKE_DYNAMIC] or [constant Light3D.BAKE_STATIC]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [VoxelGI]'s data and debug any issues that may be occurring.
+ </description>
+ </method>
+ <method name="debug_bake">
+ <return type="void">
+ </return>
+ <description>
+ Calls [method bake] with [code]create_visual_debug[/code] enabled.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="data" type="VoxelGIData" setter="set_probe_data" getter="get_probe_data">
+ The [VoxelGIData] resource that holds the data for this [VoxelGI].
+ </member>
+ <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3( 10, 10, 10 )">
+ The size of the area covered by the [VoxelGI]. If you make the extents larger without increasing the subdivisions with [member subdiv], the size of each cell will increase and result in lower detailed lighting.
+ </member>
+ <member name="subdiv" type="int" setter="set_subdiv" getter="get_subdiv" enum="VoxelGI.Subdiv" default="1">
+ Number of times to subdivide the grid that the [VoxelGI] operates on. A higher number results in finer detail and thus higher visual quality, while lower numbers result in better performance.
+ </member>
+ </members>
+ <constants>
+ <constant name="SUBDIV_64" value="0" enum="Subdiv">
+ Use 64 subdivisions. This is the lowest quality setting, but the fastest. Use it if you can, but especially use it on lower-end hardware.
+ </constant>
+ <constant name="SUBDIV_128" value="1" enum="Subdiv">
+ Use 128 subdivisions. This is the default quality setting.
+ </constant>
+ <constant name="SUBDIV_256" value="2" enum="Subdiv">
+ Use 256 subdivisions.
+ </constant>
+ <constant name="SUBDIV_512" value="3" enum="Subdiv">
+ Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware this could cause the GPU to stall.
+ </constant>
+ <constant name="SUBDIV_MAX" value="4" enum="Subdiv">
+ Represents the size of the [enum Subdiv] enum.
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/VoxelGIData.xml b/doc/classes/VoxelGIData.xml
new file mode 100644
index 0000000000..88a0411e2b
--- /dev/null
+++ b/doc/classes/VoxelGIData.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VoxelGIData" inherits="Resource" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
+ </tutorials>
+ <methods>
+ <method name="allocate">
+ <return type="void">
+ </return>
+ <argument index="0" name="to_cell_xform" type="Transform3D">
+ </argument>
+ <argument index="1" name="aabb" type="AABB">
+ </argument>
+ <argument index="2" name="octree_size" type="Vector3">
+ </argument>
+ <argument index="3" name="octree_cells" type="PackedByteArray">
+ </argument>
+ <argument index="4" name="data_cells" type="PackedByteArray">
+ </argument>
+ <argument index="5" name="distance_field" type="PackedByteArray">
+ </argument>
+ <argument index="6" name="level_counts" type="PackedInt32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_bounds" qualifiers="const">
+ <return type="AABB">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_data_cells" qualifiers="const">
+ <return type="PackedByteArray">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_level_counts" qualifiers="const">
+ <return type="PackedInt32Array">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_octree_cells" qualifiers="const">
+ <return type="PackedByteArray">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_octree_size" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_to_cell_xform" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="anisotropy_strength" type="float" setter="set_anisotropy_strength" getter="get_anisotropy_strength" default="0.5">
+ </member>
+ <member name="ao" type="float" setter="set_ao" getter="get_ao" default="0.0">
+ </member>
+ <member name="ao_size" type="float" setter="set_ao_size" getter="get_ao_size" default="0.5">
+ </member>
+ <member name="bias" type="float" setter="set_bias" getter="get_bias" default="1.5">
+ </member>
+ <member name="dynamic_range" type="float" setter="set_dynamic_range" getter="get_dynamic_range" default="4.0">
+ </member>
+ <member name="energy" type="float" setter="set_energy" getter="get_energy" default="1.0">
+ </member>
+ <member name="interior" type="bool" setter="set_interior" getter="is_interior" default="false">
+ </member>
+ <member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" default="0.0">
+ </member>
+ <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.7">
+ </member>
+ <member name="use_two_bounces" type="bool" setter="set_use_two_bounces" getter="is_using_two_bounces" default="false">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/WeakRef.xml b/doc/classes/WeakRef.xml
index 4140df5828..6c9a7de67f 100644
--- a/doc/classes/WeakRef.xml
+++ b/doc/classes/WeakRef.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WeakRef" inherits="Reference" version="4.0">
+<class name="WeakRef" inherits="RefCounted" version="4.0">
<brief_description>
Holds an [Object], but does not contribute to the reference count if the object is a reference.
</brief_description>
<description>
- A weakref can hold a [Reference], without contributing to the reference counter. A weakref can be created from an [Object] using [method @GlobalScope.weakref]. If this object is not a reference, weakref still works, however, it does not have any effect on the object. Weakrefs are useful in cases where multiple classes have variables that refer to each other. Without weakrefs, using these classes could lead to memory leaks, since both references keep each other from being released. Making part of the variables a weakref can prevent this cyclic dependency, and allows the references to be released.
+ A weakref can hold a [RefCounted], without contributing to the reference counter. A weakref can be created from an [Object] using [method @GlobalScope.weakref]. If this object is not a reference, weakref still works, however, it does not have any effect on the object. Weakrefs are useful in cases where multiple classes have variables that refer to each other. Without weakrefs, using these classes could lead to memory leaks, since both references keep each other from being released. Making part of the variables a weakref can prevent this cyclic dependency, and allows the references to be released.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml
index b99a251a11..9c320747d1 100644
--- a/doc/classes/Window.xml
+++ b/doc/classes/Window.xml
@@ -45,7 +45,7 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
</description>
@@ -55,7 +55,7 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
</description>
@@ -65,10 +65,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns the [Font] at [code]name[/code] if the theme has [code]type[/code].
+ Returns the [Font] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_theme_font_size" qualifiers="const">
@@ -76,10 +76,10 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns the font size at [code]name[/code] if the theme has [code]type[/code].
+ Returns the font size at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
<method name="get_theme_icon" qualifiers="const">
@@ -87,7 +87,7 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
</description>
@@ -97,7 +97,7 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
</description>
@@ -119,7 +119,7 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
</description>
@@ -129,7 +129,7 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
</description>
@@ -139,11 +139,11 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if [Font] with [code]name[/code] is in [code]type[/code].
- Returns [code]false[/code] if the theme does not have [code]type[/code].
+ Returns [code]true[/code] if [Font] with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="has_theme_font_size" qualifiers="const">
@@ -151,11 +151,11 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if font size with [code]name[/code] is in [code]type[/code].
- Returns [code]false[/code] if the theme does not have [code]type[/code].
+ Returns [code]true[/code] if font size with [code]name[/code] is in [code]theme_type[/code].
+ Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
<method name="has_theme_icon" qualifiers="const">
@@ -163,7 +163,7 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
</description>
@@ -173,7 +173,7 @@
</return>
<argument index="0" name="name" type="StringName">
</argument>
- <argument index="1" name="type" type="StringName" default="&quot;&quot;">
+ <argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
</description>
@@ -340,6 +340,8 @@
</member>
<member name="theme" type="Theme" setter="set_theme" getter="get_theme">
</member>
+ <member name="theme_custom_type" type="StringName" setter="set_theme_custom_type" getter="get_theme_custom_type" default="&amp;&quot;&quot;">
+ </member>
<member name="title" type="String" setter="set_title" getter="get_title" default="&quot;&quot;">
</member>
<member name="transient" type="bool" setter="set_transient" getter="is_transient" default="false">
diff --git a/doc/classes/XMLParser.xml b/doc/classes/XMLParser.xml
index 2849ea62ab..ab5c58c51c 100644
--- a/doc/classes/XMLParser.xml
+++ b/doc/classes/XMLParser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="XMLParser" inherits="Reference" version="4.0">
+<class name="XMLParser" inherits="RefCounted" version="4.0">
<brief_description>
Low-level class for creating parsers for [url=https://en.wikipedia.org/wiki/XML]XML[/url] files.
</brief_description>
diff --git a/doc/classes/XRInterface.xml b/doc/classes/XRInterface.xml
index 034cb51be3..fec98007c3 100644
--- a/doc/classes/XRInterface.xml
+++ b/doc/classes/XRInterface.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="XRInterface" inherits="Reference" version="4.0">
+<class name="XRInterface" inherits="RefCounted" version="4.0">
<brief_description>
Base class for an AR/VR interface implementation.
</brief_description>
@@ -46,6 +46,13 @@
If supported, returns the status of our tracking. This will allow you to provide feedback to the user whether there are issues with positional tracking.
</description>
</method>
+ <method name="get_view_count">
+ <return type="int">
+ </return>
+ <description>
+ Returns the number of views that need to be rendered for this device. 1 for Monoscopic, 2 for Stereoscopic.
+ </description>
+ </method>
<method name="initialize">
<return type="bool">
</return>
@@ -57,13 +64,6 @@
While currently not used, you can activate additional interfaces. You may wish to do this if you want to track controllers from other platforms. However, at this point in time only one interface can render to an HMD.
</description>
</method>
- <method name="is_stereo">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if the current output of this interface is in stereo.
- </description>
- </method>
<method name="uninitialize">
<return type="void">
</return>
diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml
index 5274d952fd..cd8cb71cd9 100644
--- a/doc/classes/XRPositionalTracker.xml
+++ b/doc/classes/XRPositionalTracker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="XRPositionalTracker" inherits="Reference" version="4.0">
+<class name="XRPositionalTracker" inherits="RefCounted" version="4.0">
<brief_description>
A tracked object.
</brief_description>
@@ -69,7 +69,7 @@
</description>
</method>
<method name="get_transform" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<argument index="0" name="adjust_by_reference_frame" type="bool">
</argument>
diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml
index d0edf91fed..149e177700 100644
--- a/doc/classes/XRServer.xml
+++ b/doc/classes/XRServer.xml
@@ -63,7 +63,7 @@
</description>
</method>
<method name="get_hmd_transform">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<description>
Returns the primary interface's transformation.
@@ -96,7 +96,7 @@
<return type="int">
</return>
<description>
- Returns the absolute timestamp (in μs) of the last [XRServer] commit of the AR/VR eyes to [RenderingServer]. The value comes from an internal call to [method OS.get_ticks_usec].
+ Returns the absolute timestamp (in μs) of the last [XRServer] commit of the AR/VR eyes to [RenderingServer]. The value comes from an internal call to [method Time.get_ticks_usec].
</description>
</method>
<method name="get_last_frame_usec">
@@ -110,11 +110,11 @@
<return type="int">
</return>
<description>
- Returns the absolute timestamp (in μs) of the last [XRServer] process callback. The value comes from an internal call to [method OS.get_ticks_usec].
+ Returns the absolute timestamp (in μs) of the last [XRServer] process callback. The value comes from an internal call to [method Time.get_ticks_usec].
</description>
</method>
<method name="get_reference_frame" qualifiers="const">
- <return type="Transform">
+ <return type="Transform3D">
</return>
<description>
Returns the reference frame transform. Mostly used internally and exposed for GDNative build interfaces.
diff --git a/doc/classes/YSort.xml b/doc/classes/YSort.xml
deleted file mode 100644
index 4ef6a4b4ec..0000000000
--- a/doc/classes/YSort.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="YSort" inherits="Node2D" version="4.0">
- <brief_description>
- Sort all child nodes based on their Y positions.
- </brief_description>
- <description>
- Sort all child nodes based on their Y positions. The child node must inherit from [CanvasItem] for it to be sorted. Nodes that have a higher Y position will be drawn later, so they will appear on top of nodes that have a lower Y position.
- Nesting of YSort nodes is possible. Children YSort nodes will be sorted in the same space as the parent YSort, allowing to better organize a scene or divide it in multiple ones, yet keep the unique sorting.
- </description>
- <tutorials>
- </tutorials>
- <methods>
- </methods>
- <members>
- <member name="sort_enabled" type="bool" setter="set_sort_enabled" getter="is_sort_enabled" default="true">
- If [code]true[/code], child nodes are sorted, otherwise sorting is disabled.
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index 11f6d91b05..f75c130039 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -113,12 +113,12 @@
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="Quat">
+ <return type="Quaternion">
</return>
- <argument index="0" name="right" type="Quat">
+ <argument index="0" name="right" type="Quaternion">
</argument>
<description>
- Multiplies each component of the [Quat] by the given [float].
+ Multiplies each component of the [Quaternion] by the given [float].
</description>
</method>
<method name="operator *" qualifiers="operator">
diff --git a/doc/classes/int.xml b/doc/classes/int.xml
index 119cdf8eeb..b0ad963998 100644
--- a/doc/classes/int.xml
+++ b/doc/classes/int.xml
@@ -183,9 +183,9 @@
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="Quat">
+ <return type="Quaternion">
</return>
- <argument index="0" name="right" type="Quat">
+ <argument index="0" name="right" type="Quaternion">
</argument>
<description>
Multiplies each component of the quaternion by the given integer.
diff --git a/doc/translations/ar.po b/doc/translations/ar.po
index b4ae664714..77a3d39f27 100644
--- a/doc/translations/ar.po
+++ b/doc/translations/ar.po
@@ -33036,7 +33036,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33055,12 +33055,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34557,7 +34557,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41765,30 +41765,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41796,7 +41796,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54060,7 +54060,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59139,7 +59139,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/ca.po b/doc/translations/ca.po
index 6485111b20..8ea801181d 100644
--- a/doc/translations/ca.po
+++ b/doc/translations/ca.po
@@ -33067,7 +33067,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33086,12 +33086,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34588,7 +34588,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41796,30 +41796,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41827,7 +41827,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54091,7 +54091,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59170,7 +59170,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/classes.pot b/doc/translations/classes.pot
index d14b0d9b1f..d12fa78b0e 100644
--- a/doc/translations/classes.pot
+++ b/doc/translations/classes.pot
@@ -33037,7 +33037,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33056,12 +33056,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34558,7 +34558,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41766,30 +41766,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41797,7 +41797,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54061,7 +54061,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59140,7 +59140,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/cs.po b/doc/translations/cs.po
index 7b958a5049..a267656497 100644
--- a/doc/translations/cs.po
+++ b/doc/translations/cs.po
@@ -33536,7 +33536,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33555,12 +33555,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -35058,7 +35058,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -42266,30 +42266,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -42297,7 +42297,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54562,7 +54562,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59645,7 +59645,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/de.po b/doc/translations/de.po
index 2e3e219ba6..181d64d525 100644
--- a/doc/translations/de.po
+++ b/doc/translations/de.po
@@ -33453,7 +33453,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33472,12 +33472,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
#, fuzzy
msgid ""
@@ -34984,7 +34984,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -42226,30 +42226,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -42257,7 +42257,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54558,7 +54558,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59796,7 +59796,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/es.po b/doc/translations/es.po
index 3078c1bf90..7df36316b7 100644
--- a/doc/translations/es.po
+++ b/doc/translations/es.po
@@ -44834,7 +44834,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -44853,9 +44853,9 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
"Toda clase que no es un tipo integrado hereda de esta clase.\n"
"Puedes construir Objetos desde lenguajes de scripting, usando [code]Object."
@@ -44866,7 +44866,7 @@ msgstr ""
"llama al método [method free] desde tu script o elimina la instancia desde C+"
"+.\n"
"Algunas clases que extienden a Object añaden gestión de memoria. Este es el "
-"caso de [Reference], que cuenta las referencias y se borra a sí misma "
+"caso de [RefCounted], que cuenta las referencias y se borra a sí misma "
"automáticamente cuando deja de estar referenciada. [Node], otro tipo "
"fundamental, borra todos sus hijos cuando se libera de la memoria.\n"
"Los objetos exportan propiedades, que son principalmente útiles para el "
@@ -44887,7 +44887,7 @@ msgstr ""
"sencilla de notificar al objeto sobre diferentes eventos, de modo que todos "
"ellos pueden ser manejados juntos. Véase [method _notification]."
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
#, fuzzy
msgid ""
@@ -46525,7 +46525,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -53779,30 +53779,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -53810,7 +53810,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -66189,7 +66189,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -71348,7 +71348,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/fa.po b/doc/translations/fa.po
index 733d3bb969..e440146dd3 100644
--- a/doc/translations/fa.po
+++ b/doc/translations/fa.po
@@ -33042,7 +33042,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33061,12 +33061,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34563,7 +34563,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41771,30 +41771,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41802,7 +41802,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54066,7 +54066,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59145,7 +59145,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/fi.po b/doc/translations/fi.po
index 0a40863a52..92ec4f29dd 100644
--- a/doc/translations/fi.po
+++ b/doc/translations/fi.po
@@ -33055,7 +33055,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33074,12 +33074,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34576,7 +34576,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41784,30 +41784,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41815,7 +41815,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54080,7 +54080,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59168,7 +59168,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/fr.po b/doc/translations/fr.po
index f3e26ebc61..7717474c0f 100644
--- a/doc/translations/fr.po
+++ b/doc/translations/fr.po
@@ -33403,7 +33403,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33422,12 +33422,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34927,7 +34927,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -42142,30 +42142,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -42173,7 +42173,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54519,7 +54519,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59618,7 +59618,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/id.po b/doc/translations/id.po
index 1bce3d6b50..edfd392f4f 100644
--- a/doc/translations/id.po
+++ b/doc/translations/id.po
@@ -33068,7 +33068,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33087,12 +33087,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34589,7 +34589,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41797,30 +41797,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41828,7 +41828,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54092,7 +54092,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59171,7 +59171,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/it.po b/doc/translations/it.po
index 18e162476c..353eae4116 100644
--- a/doc/translations/it.po
+++ b/doc/translations/it.po
@@ -33334,7 +33334,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33353,12 +33353,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34856,7 +34856,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -42067,30 +42067,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -42098,7 +42098,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54365,7 +54365,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59459,7 +59459,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/ja.po b/doc/translations/ja.po
index ede80a35ef..1424b24153 100644
--- a/doc/translations/ja.po
+++ b/doc/translations/ja.po
@@ -34306,7 +34306,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -34325,12 +34325,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
#, fuzzy
msgid ""
@@ -35830,7 +35830,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -43046,30 +43046,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -43077,7 +43077,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -55349,7 +55349,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -60446,7 +60446,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/ko.po b/doc/translations/ko.po
index e71cd06ba7..8e8aef2eaf 100644
--- a/doc/translations/ko.po
+++ b/doc/translations/ko.po
@@ -33044,7 +33044,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33063,12 +33063,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34565,7 +34565,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41773,30 +41773,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41804,7 +41804,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54068,7 +54068,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59149,7 +59149,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/nl.po b/doc/translations/nl.po
index 032ff95bdb..096e59f497 100644
--- a/doc/translations/nl.po
+++ b/doc/translations/nl.po
@@ -33070,7 +33070,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33089,12 +33089,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34591,7 +34591,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41799,30 +41799,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41830,7 +41830,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54094,7 +54094,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59173,7 +59173,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/pl.po b/doc/translations/pl.po
index b0c94b55be..5ef41b155a 100644
--- a/doc/translations/pl.po
+++ b/doc/translations/pl.po
@@ -33089,7 +33089,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33108,12 +33108,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34610,7 +34610,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41818,30 +41818,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41849,7 +41849,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54117,7 +54117,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59203,7 +59203,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/pt_BR.po b/doc/translations/pt_BR.po
index a508d38859..ef62950d51 100644
--- a/doc/translations/pt_BR.po
+++ b/doc/translations/pt_BR.po
@@ -33083,7 +33083,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33102,12 +33102,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34604,7 +34604,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41812,30 +41812,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41843,7 +41843,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54108,7 +54108,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59194,7 +59194,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/ro.po b/doc/translations/ro.po
index 96c0161312..5f018aa497 100644
--- a/doc/translations/ro.po
+++ b/doc/translations/ro.po
@@ -33044,7 +33044,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33063,12 +33063,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34565,7 +34565,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41773,30 +41773,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41804,7 +41804,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54068,7 +54068,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59147,7 +59147,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/ru.po b/doc/translations/ru.po
index 1108967bc9..0d227beff7 100644
--- a/doc/translations/ru.po
+++ b/doc/translations/ru.po
@@ -33581,7 +33581,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33600,12 +33600,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -35104,7 +35104,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -42362,30 +42362,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -42393,7 +42393,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54666,7 +54666,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59891,7 +59891,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/sr_Cyrl.po b/doc/translations/sr_Cyrl.po
index d7d2911b97..d53711d996 100644
--- a/doc/translations/sr_Cyrl.po
+++ b/doc/translations/sr_Cyrl.po
@@ -33054,7 +33054,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33073,12 +33073,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34575,7 +34575,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41783,30 +41783,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41814,7 +41814,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54078,7 +54078,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59157,7 +59157,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/th.po b/doc/translations/th.po
index 5031ecfb0e..7686e22f19 100644
--- a/doc/translations/th.po
+++ b/doc/translations/th.po
@@ -33060,7 +33060,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33079,12 +33079,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34581,7 +34581,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41789,30 +41789,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41820,7 +41820,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54084,7 +54084,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59163,7 +59163,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/tr.po b/doc/translations/tr.po
index a317f4ee83..df9897f1d6 100644
--- a/doc/translations/tr.po
+++ b/doc/translations/tr.po
@@ -33036,7 +33036,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33055,12 +33055,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34557,7 +34557,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41765,30 +41765,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41796,7 +41796,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54060,7 +54060,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59139,7 +59139,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/uk.po b/doc/translations/uk.po
index 8ca75e8b19..d1296da87a 100644
--- a/doc/translations/uk.po
+++ b/doc/translations/uk.po
@@ -33122,7 +33122,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33141,12 +33141,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34643,7 +34643,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41851,30 +41851,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41882,7 +41882,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54147,7 +54147,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59237,7 +59237,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/zh_Hans.po b/doc/translations/zh_Hans.po
index aee852699c..edfb11dec1 100644
--- a/doc/translations/zh_Hans.po
+++ b/doc/translations/zh_Hans.po
@@ -33272,7 +33272,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33291,12 +33291,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34794,7 +34794,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -42002,30 +42002,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -42033,7 +42033,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54298,7 +54298,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59381,7 +59381,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/doc/translations/zh_Hant.po b/doc/translations/zh_Hant.po
index 242c8cc086..3afec7ead8 100644
--- a/doc/translations/zh_Hant.po
+++ b/doc/translations/zh_Hant.po
@@ -33073,7 +33073,7 @@ msgid ""
"to delete instances of it manually. To do so, call the [method free] method "
"from your script or delete the instance from C++.\n"
"Some classes that extend Object add memory management. This is the case of "
-"[Reference], which counts references and deletes itself automatically when "
+"[RefCounted], which counts references and deletes itself automatically when "
"no longer referenced. [Node], another fundamental type, deletes all its "
"children when freed from memory.\n"
"Objects export properties, which are mainly useful for storage and editing, "
@@ -33092,12 +33092,12 @@ msgid ""
"Objects also receive notifications. Notifications are a simple way to notify "
"the object about different events, so they can all be handled together. See "
"[method _notification].\n"
-"[b]Note:[/b] Unlike references to a [Reference], references to an Object "
+"[b]Note:[/b] Unlike references to a [RefCounted], references to an Object "
"stored in a variable can become invalid without warning. Therefore, it's "
-"recommended to use [Reference] for data classes instead of [Object]."
+"recommended to use [RefCounted] for data classes instead of [Object]."
msgstr ""
-#: doc/classes/Object.xml:23 doc/classes/Reference.xml:12
+#: doc/classes/Object.xml:23 doc/classes/RefCounted.xml:12
#: doc/classes/Resource.xml:11
msgid ""
"https://docs.godotengine.org/en/latest/getting_started/workflow/"
@@ -34594,7 +34594,7 @@ msgid "Changes the [Color] at the given index."
msgstr ""
#: doc/classes/PackedDataContainerRef.xml:4
-msgid "Reference version of [PackedDataContainer]."
+msgid "RefCounted version of [PackedDataContainer]."
msgstr ""
#: doc/classes/PackedFloat32Array.xml:4
@@ -41802,30 +41802,30 @@ msgid ""
"the half extents."
msgstr ""
-#: doc/classes/Reference.xml:4
+#: doc/classes/RefCounted.xml:4
msgid "Base class for reference-counted objects."
msgstr ""
-#: doc/classes/Reference.xml:7
+#: doc/classes/RefCounted.xml:7
msgid ""
"Base class for any object that keeps a reference count. [Resource] and many "
"other helper objects inherit this class.\n"
"Unlike [Object]s, References keep an internal reference counter so that they "
"are automatically released when no longer in use, and only then. References "
"therefore do not need to be freed manually with [method Object.free].\n"
-"In the vast majority of use cases, instantiating and using [Reference]-"
+"In the vast majority of use cases, instantiating and using [RefCounted]-"
"derived types is all you need to do. The methods provided in this class are "
"only for advanced users, and can cause issues if misused."
msgstr ""
-#: doc/classes/Reference.xml:19
+#: doc/classes/RefCounted.xml:19
msgid ""
"Initializes the internal reference counter. Use this only if you really know "
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
-#: doc/classes/Reference.xml:27
+#: doc/classes/RefCounted.xml:27
msgid ""
"Increments the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -41833,7 +41833,7 @@ msgid ""
"code] otherwise."
msgstr ""
-#: doc/classes/Reference.xml:35
+#: doc/classes/RefCounted.xml:35
msgid ""
"Decrements the internal reference counter. Use this only if you really know "
"what you are doing.\n"
@@ -54098,7 +54098,7 @@ msgid ""
"[codeblock]\n"
"var foo = 2 # foo is dynamically an integer\n"
"foo = \"Now foo is a string!\"\n"
-"foo = Reference.new() # foo is an Object\n"
+"foo = RefCounted.new() # foo is an Object\n"
"var bar: int = 2 # bar is a statically typed integer.\n"
"# bar = \"Uh oh! I can't make static variables become a different type!\"\n"
"[/codeblock]\n"
@@ -59181,7 +59181,7 @@ msgstr ""
#: doc/classes/WeakRef.xml:7
msgid ""
-"A weakref can hold a [Reference], without contributing to the reference "
+"A weakref can hold a [RefCounted], without contributing to the reference "
"counter. A weakref can be created from an [Object] using [method @GDScript."
"weakref]. If this object is not a reference, weakref still works, however, "
"it does not have any effect on the object. Weakrefs are useful in cases "
diff --git a/drivers/SCsub b/drivers/SCsub
index e2ac9ee01e..a7b21b855f 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -23,10 +23,8 @@ SConscript("coremidi/SCsub")
SConscript("winmidi/SCsub")
# Graphics drivers
-if env["platform"] != "server" and env["platform"] != "javascript":
+if env["vulkan"]:
SConscript("vulkan/SCsub")
-else:
- SConscript("dummy/SCsub")
# Core dependencies
SConscript("png/SCsub")
diff --git a/drivers/dummy/SCsub b/drivers/dummy/SCsub
deleted file mode 100644
index 91e1140b75..0000000000
--- a/drivers/dummy/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-env.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
deleted file mode 100644
index 1a27c54757..0000000000
--- a/drivers/dummy/rasterizer_dummy.h
+++ /dev/null
@@ -1,783 +0,0 @@
-/*************************************************************************/
-/* rasterizer_dummy.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef RASTERIZER_DUMMY_H
-#define RASTERIZER_DUMMY_H
-
-#include "core/math/camera_matrix.h"
-#include "core/templates/rid_owner.h"
-#include "core/templates/self_list.h"
-#include "scene/resources/mesh.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering_server.h"
-
-class RasterizerSceneDummy : public RendererSceneRender {
-public:
- GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
- void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
- void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
- void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
- void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
- void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
- void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
- void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
- void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
- void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
- void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
-
- uint32_t geometry_instance_get_pair_mask() override { return 0; }
- void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
- void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
- void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
- void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) override {}
-
- void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
-
- /* SHADOW ATLAS API */
-
- RID shadow_atlas_create() override { return RID(); }
- void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) override {}
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {}
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; }
-
- void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) override {}
- int get_directional_light_shadow_size(RID p_light_intance) override { return 0; }
- void set_directional_shadow_count(int p_count) override {}
-
- /* SDFGI UPDATE */
-
- void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
- int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
- AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
- uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
-
- /* SKY API */
-
- RID sky_allocate() override { return RID(); }
- void sky_initialize(RID p_rid) override {}
- void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {}
- void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {}
- void sky_set_material(RID p_sky, RID p_material) override {}
- Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
-
- /* ENVIRONMENT API */
-
- RID environment_allocate() override { return RID(); }
- void environment_initialize(RID p_rid) override {}
- void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
- void environment_set_sky(RID p_env, RID p_sky) override {}
- void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
- void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {}
- void environment_set_bg_color(RID p_env, const Color &p_color) override {}
- void environment_set_bg_energy(RID p_env, float p_energy) override {}
- void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
- void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) override {}
-
- void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override {}
- void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
- void environment_glow_set_use_high_quality(bool p_enable) override {}
-
- void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {}
- void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
- void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {}
- void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
-
- void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
-
- void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
- void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
- void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {}
-
- void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {}
-
- void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
-
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override {}
- void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
- void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
-
- Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
-
- bool is_environment(RID p_env) const override { return false; }
- RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
- int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
-
- RID camera_effects_allocate() override { return RID(); }
- void camera_effects_initialize(RID p_rid) override {}
- void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
- void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {}
-
- void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {}
- void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {}
-
- void shadows_quality_set(RS::ShadowQuality p_quality) override {}
- void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {}
-
- RID light_instance_create(RID p_light) override { return RID(); }
- void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) override {}
- void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
- void light_instance_mark_visible(RID p_light_instance) override {}
-
- RID reflection_atlas_create() override { return RID(); }
- int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
- void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
-
- RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
- void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) override {}
- void reflection_probe_release_atlas_index(RID p_instance) override {}
- bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
- bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
- bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
- bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
-
- RID decal_instance_create(RID p_decal) override { return RID(); }
- void decal_instance_set_transform(RID p_decal, const Transform &p_transform) override {}
-
- RID lightmap_instance_create(RID p_lightmap) override { return RID(); }
- void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) override {}
-
- RID gi_probe_instance_create(RID p_gi_probe) override { return RID(); }
- void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) override {}
- bool gi_probe_needs_update(RID p_probe) const override { return false; }
- void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
-
- void gi_probe_set_quality(RS::GIProbeQuality) override {}
-
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) override {}
- void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
- void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
-
- void set_scene_pass(uint64_t p_pass) override {}
- void set_time(double p_time, double p_step) override {}
- void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
-
- RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) override {}
- void gi_set_use_half_resolution(bool p_enable) override {}
-
- void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
- bool screen_space_roughness_limiter_is_active() const override { return false; }
-
- void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
- void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
-
- TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
-
- bool free(RID p_rid) override { return true; }
- void update() override {}
- void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
-
- RasterizerSceneDummy() {}
- ~RasterizerSceneDummy() {}
-};
-
-class RasterizerStorageDummy : public RendererStorage {
-public:
- bool can_create_resources_async() const override { return false; }
-
- /* TEXTURE API */
- struct DummyTexture {
- Ref<Image> image;
- };
- mutable RID_PtrOwner<DummyTexture> texture_owner;
-
- RID texture_allocate() override {
- DummyTexture *texture = memnew(DummyTexture);
- ERR_FAIL_COND_V(!texture, RID());
- return texture_owner.make_rid(texture);
- }
- void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!t);
- t->image = p_image->duplicate();
- }
-
- void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {}
- void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
- void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
- void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
- void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
- void texture_proxy_initialize(RID p_texture, RID p_base) override {}
- void texture_proxy_update(RID p_proxy, RID p_base) override {}
-
- void texture_2d_placeholder_initialize(RID p_texture) override {}
- void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {}
- void texture_3d_placeholder_initialize(RID p_texture) override {}
-
- Ref<Image> texture_2d_get(RID p_texture) const override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND_V(!t, Ref<Image>());
- return t->image;
- }
-
- Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
- Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
-
- void texture_replace(RID p_texture, RID p_by_texture) override {}
- void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
-
- void texture_set_path(RID p_texture, const String &p_path) override {}
- String texture_get_path(RID p_texture) const override { return String(); }
-
- void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {}
- void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {}
- void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {}
-
- void texture_debug_usage(List<RS::TextureInfo> *r_info) override {}
- void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {}
- Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }
-
- void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
- void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-
- /* CANVAS TEXTURE API */
-
- RID canvas_texture_allocate() override { return RID(); }
- void canvas_texture_initialize(RID p_rid) override {}
- void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {}
- void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {}
-
- void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {}
- void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {}
-
- /* SHADER API */
-
- RID shader_allocate() override { return RID(); }
- void shader_initialize(RID p_rid) override {}
- void shader_set_code(RID p_shader, const String &p_code) override {}
- String shader_get_code(RID p_shader) const override { return ""; }
- void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
-
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override {}
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override { return RID(); }
- Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
-
- RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
-
- /* COMMON MATERIAL API */
-
- RID material_allocate() override { return RID(); }
- void material_initialize(RID p_rid) override {}
- void material_set_render_priority(RID p_material, int priority) override {}
- void material_set_shader(RID p_shader_material, RID p_shader) override {}
-
- void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {}
- Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); }
-
- void material_set_next_pass(RID p_material, RID p_next_material) override {}
-
- bool material_is_animated(RID p_material) override { return false; }
- bool material_casts_shadows(RID p_material) override { return false; }
- void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
- void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
-
- /* MESH API */
-
- RID mesh_allocate() override { return RID(); }
- void mesh_initialize(RID p_rid) override {}
- void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
- bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
- RID mesh_instance_create(RID p_base) override { return RID(); }
- void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
- void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
- void mesh_instance_check_for_update(RID p_mesh_instance) override {}
- void update_mesh_instances() override {}
- void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) override {}
- float reflection_probe_get_lod_threshold(RID p_probe) const override { return 0.0; }
-
- void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
-
- int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
-
- void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
- RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
-
- void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
-
- void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
- RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
-
- RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
- int mesh_get_surface_count(RID p_mesh) const override { return 0; }
-
- void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
- AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
-
- AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
- void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
- void mesh_clear(RID p_mesh) override {}
-
- /* MULTIMESH API */
-
- RID multimesh_allocate() override { return RID(); }
- void multimesh_initialize(RID p_rid) override {}
- void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
- int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
-
- void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) override {}
- void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {}
- void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {}
- void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {}
-
- RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); }
- AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); }
-
- Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform(); }
- Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); }
- Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
- Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
- void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {}
- Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); }
-
- void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
- int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
-
- /* IMMEDIATE API */
-
- RID immediate_allocate() override { return RID(); }
- void immediate_initialize(RID p_rid) override {}
- void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) override {}
- void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) override {}
- void immediate_normal(RID p_immediate, const Vector3 &p_normal) override {}
- void immediate_tangent(RID p_immediate, const Plane &p_tangent) override {}
- void immediate_color(RID p_immediate, const Color &p_color) override {}
- void immediate_uv(RID p_immediate, const Vector2 &tex_uv) override {}
- void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) override {}
- void immediate_end(RID p_immediate) override {}
- void immediate_clear(RID p_immediate) override {}
- void immediate_set_material(RID p_immediate, RID p_material) override {}
- RID immediate_get_material(RID p_immediate) const override { return RID(); }
- AABB immediate_get_aabb(RID p_immediate) const override { return AABB(); }
-
- /* SKELETON API */
-
- RID skeleton_allocate() override { return RID(); }
- void skeleton_initialize(RID p_rid) override {}
- void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
- void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
- int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) override {}
- Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform(); }
- void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
- Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
-
- /* Light API */
-
- RID directional_light_allocate() override { return RID(); }
- void directional_light_initialize(RID p_rid) override {}
- RID omni_light_allocate() override { return RID(); }
- void omni_light_initialize(RID p_rid) override {}
- RID spot_light_allocate() override { return RID(); }
- void spot_light_initialize(RID p_rid) override {}
- RID reflection_probe_allocate() override { return RID(); }
- void reflection_probe_initialize(RID p_rid) override {}
-
- void light_set_color(RID p_light, const Color &p_color) override {}
- void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
- void light_set_shadow(RID p_light, bool p_enabled) override {}
- void light_set_shadow_color(RID p_light, const Color &p_color) override {}
- void light_set_projector(RID p_light, RID p_texture) override {}
- void light_set_negative(RID p_light, bool p_enable) override {}
- void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
- void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
- void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
- void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
-
- void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {}
-
- void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
- void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
- bool light_directional_get_blend_splits(RID p_light) const override { return false; }
- void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) override {}
- void light_directional_set_sky_only(RID p_light, bool p_sky_only) override {}
- bool light_directional_is_sky_only(RID p_light) const override { return false; }
- RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; }
-
- RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
- RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
-
- bool light_has_shadow(RID p_light) const override { return false; }
-
- RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
- AABB light_get_aabb(RID p_light) const override { return AABB(); }
- float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; }
- Color light_get_color(RID p_light) override { return Color(); }
- RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; }
- uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
- uint64_t light_get_version(RID p_light) const override { return 0; }
-
- /* PROBE API */
-
- void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
- void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
- void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
- void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {}
- void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {}
- void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {}
- void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {}
- void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {}
- void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {}
- void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {}
- void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
- void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
- void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
-
- AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
- RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
- uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
- Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); }
- Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); }
- float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
- bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
-
- void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
- void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
-
- /* DECAL API */
-
- RID decal_allocate() override { return RID(); }
- void decal_initialize(RID p_rid) override {}
- void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
- void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
- void decal_set_emission_energy(RID p_decal, float p_energy) override {}
- void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
- void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
- void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
- void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
- void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
- void decal_set_normal_fade(RID p_decal, float p_fade) override {}
-
- AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
-
- /* GI PROBE API */
-
- RID gi_probe_allocate() override { return RID(); }
- void gi_probe_initialize(RID p_rid) override {}
- void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override {}
-
- AABB gi_probe_get_bounds(RID p_gi_probe) const override { return AABB(); }
- Vector3i gi_probe_get_octree_size(RID p_gi_probe) const override { return Vector3i(); }
- Vector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const override { return Vector<uint8_t>(); }
- Vector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const override { return Vector<uint8_t>(); }
- Vector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const override { return Vector<uint8_t>(); }
-
- Vector<int> gi_probe_get_level_counts(RID p_gi_probe) const override { return Vector<int>(); }
- Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const override { return Transform(); }
-
- void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) override {}
- float gi_probe_get_dynamic_range(RID p_gi_probe) const override { return 0; }
-
- void gi_probe_set_propagation(RID p_gi_probe, float p_range) override {}
- float gi_probe_get_propagation(RID p_gi_probe) const override { return 0; }
-
- void gi_probe_set_energy(RID p_gi_probe, float p_range) override {}
- float gi_probe_get_energy(RID p_gi_probe) const override { return 0.0; }
-
- void gi_probe_set_ao(RID p_gi_probe, float p_ao) override {}
- float gi_probe_get_ao(RID p_gi_probe) const override { return 0; }
-
- void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) override {}
- float gi_probe_get_ao_size(RID p_gi_probe) const override { return 0; }
-
- void gi_probe_set_bias(RID p_gi_probe, float p_range) override {}
- float gi_probe_get_bias(RID p_gi_probe) const override { return 0.0; }
-
- void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) override {}
- float gi_probe_get_normal_bias(RID p_gi_probe) const override { return 0.0; }
-
- void gi_probe_set_interior(RID p_gi_probe, bool p_enable) override {}
- bool gi_probe_is_interior(RID p_gi_probe) const override { return false; }
-
- void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) override {}
- bool gi_probe_is_using_two_bounces(RID p_gi_probe) const override { return false; }
-
- void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) override {}
- float gi_probe_get_anisotropy_strength(RID p_gi_probe) const override { return 0; }
-
- uint32_t gi_probe_get_version(RID p_gi_probe) override { return 0; }
-
- /* LIGHTMAP CAPTURE */
- RID lightmap_allocate() override { return RID(); }
- void lightmap_initialize(RID p_rid) override {}
- void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
- void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
- void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
- void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {}
- PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
- PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
- PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
- PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); }
- AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); }
- void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {}
- bool lightmap_is_interior(RID p_lightmap) const override { return false; }
- void lightmap_set_probe_capture_update_speed(float p_speed) override {}
- float lightmap_get_probe_capture_update_speed() const override { return 0; }
-
- /* OCCLUDER */
-
- void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
-
- /* PARTICLES */
-
- RID particles_allocate() override { return RID(); }
- void particles_initialize(RID p_rid) override {}
- void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
- void particles_set_emitting(RID p_particles, bool p_emitting) override {}
- void particles_set_amount(RID p_particles, int p_amount) override {}
- void particles_set_lifetime(RID p_particles, float p_lifetime) override {}
- void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
- void particles_set_pre_process_time(RID p_particles, float p_time) override {}
- void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) override {}
- void particles_set_randomness_ratio(RID p_particles, float p_ratio) override {}
- void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
- void particles_set_speed_scale(RID p_particles, float p_scale) override {}
- void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
- void particles_set_process_material(RID p_particles, RID p_material) override {}
- void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
- void particles_set_interpolate(RID p_particles, bool p_enable) override {}
- void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
- void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
- void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
- void particles_set_collision_base_size(RID p_particles, float p_size) override {}
-
- void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
-
- void particles_set_trails(RID p_particles, bool p_enable, float p_length) override {}
- void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform> &p_bind_poses) override {}
-
- void particles_restart(RID p_particles) override {}
-
- void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {}
-
- void particles_set_draw_passes(RID p_particles, int p_count) override {}
- void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {}
-
- void particles_request_process(RID p_particles) override {}
- AABB particles_get_current_aabb(RID p_particles) override { return AABB(); }
- AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
-
- void particles_set_emission_transform(RID p_particles, const Transform &p_transform) override {}
-
- bool particles_get_emitting(RID p_particles) override { return false; }
- int particles_get_draw_passes(RID p_particles) const override { return 0; }
- RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); }
-
- void particles_add_collision(RID p_particles, RID p_instance) override {}
- void particles_remove_collision(RID p_particles, RID p_instance) override {}
-
- void update_particles() override {}
-
- /* PARTICLES COLLISION */
-
- RID particles_collision_allocate() override { return RID(); }
- void particles_collision_initialize(RID p_rid) override {}
- void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
- void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
- void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) override {}
- void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
- void particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) override {}
- void particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) override {}
- void particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) override {}
- void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
- void particles_collision_height_field_update(RID p_particles_collision) override {}
- void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
- AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
- bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
- RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
-
- RID particles_collision_instance_create(RID p_collision) override { return RID(); };
- void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) override{};
- void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override{};
-
- /* GLOBAL VARIABLES */
-
- void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
- void global_variable_remove(const StringName &p_name) override {}
- Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
-
- void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
- void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
- Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
- RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
-
- void global_variables_load_settings(bool p_load_textures = true) override {}
- void global_variables_clear() override {}
-
- int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
- void global_variables_instance_free(RID p_instance) override {}
- void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
-
- bool particles_is_inactive(RID p_particles) const override { return false; }
-
- /* RENDER TARGET */
-
- RID render_target_create() override { return RID(); }
- void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
- void render_target_set_size(RID p_render_target, int p_width, int p_height) override {}
- RID render_target_get_texture(RID p_render_target) override { return RID(); }
- void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
- void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
- bool render_target_was_used(RID p_render_target) override { return false; }
- void render_target_set_as_unused(RID p_render_target) override {}
-
- void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
- bool render_target_is_clear_requested(RID p_render_target) override { return false; }
- Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); }
- void render_target_disable_clear_request(RID p_render_target) override {}
- void render_target_do_clear_request(RID p_render_target) override {}
-
- void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
- Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
-
- RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
- bool free(RID p_rid) override {
- if (texture_owner.owns(p_rid)) {
- // delete the texture
- DummyTexture *texture = texture_owner.getornull(p_rid);
- texture_owner.free(p_rid);
- memdelete(texture);
- }
- return true;
- }
-
- bool has_os_feature(const String &p_feature) const override { return false; }
-
- void update_dirty_resources() override {}
-
- void set_debug_generate_wireframes(bool p_generate) override {}
-
- void render_info_begin_capture() override {}
- void render_info_end_capture() override {}
- int get_captured_render_info(RS::RenderInfo p_info) override { return 0; }
-
- uint64_t get_render_info(RS::RenderInfo p_info) override { return 0; }
- String get_video_adapter_name() const override { return String(); }
- String get_video_adapter_vendor() const override { return String(); }
-
- static RendererStorage *base_singleton;
-
- void capture_timestamps_begin() override {}
- void capture_timestamp(const String &p_name) override {}
- uint32_t get_captured_timestamps_count() const override { return 0; }
- uint64_t get_captured_timestamps_frame() const override { return 0; }
- uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; }
- uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; }
- String get_captured_timestamp_name(uint32_t p_index) const override { return String(); }
-
- RasterizerStorageDummy() {}
- ~RasterizerStorageDummy() {}
-};
-
-class RasterizerCanvasDummy : public RendererCanvasRender {
-public:
- PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; }
- void free_polygon(PolygonID p_polygon) override {}
-
- void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {}
- void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {}
-
- RID light_create() override { return RID(); }
- void light_set_texture(RID p_rid, RID p_texture) override {}
- void light_set_use_shadow(RID p_rid, bool p_enable) override {}
- void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {}
- void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {}
-
- void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {}
- RID occluder_polygon_create() override { return RID(); }
- void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {}
- void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {}
- void set_shadow_texture_size(int p_size) override {}
-
- void draw_window_margins(int *p_margins, RID *p_margin_textures) override {}
-
- bool free(RID p_rid) override { return true; }
- void update() override {}
-
- RasterizerCanvasDummy() {}
- ~RasterizerCanvasDummy() {}
-};
-
-class RasterizerDummy : public RendererCompositor {
-private:
- uint64_t frame = 1;
- float delta = 0;
-
-protected:
- RasterizerCanvasDummy canvas;
- RasterizerStorageDummy storage;
- RasterizerSceneDummy scene;
-
-public:
- RendererStorage *get_storage() override { return &storage; }
- RendererCanvasRender *get_canvas() override { return &canvas; }
- RendererSceneRender *get_scene() override { return &scene; }
-
- void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {}
-
- void initialize() override {}
- void begin_frame(double frame_step) override {
- frame++;
- delta = frame_step;
- }
-
- void prepare_for_blitting_render_targets() override {}
- void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {}
-
- void end_frame(bool p_swap_buffers) override {
- if (p_swap_buffers) {
- DisplayServer::get_singleton()->swap_buffers();
- }
- }
-
- void finalize() override {}
-
- static RendererCompositor *_create_current() {
- return memnew(RasterizerDummy);
- }
-
- static void make_current() {
- _create_func = _create_current;
- }
-
- bool is_low_end() const override { return true; }
- uint64_t get_frame_number() const override { return frame; }
- float get_frame_delta_time() const override { return delta; }
-
- RasterizerDummy() {}
- ~RasterizerDummy() {}
-};
-
-#endif // RASTERIZER_DUMMY_H
diff --git a/drivers/dummy/texture_loader_dummy.cpp b/drivers/dummy/texture_loader_dummy.cpp
deleted file mode 100644
index f148e42845..0000000000
--- a/drivers/dummy/texture_loader_dummy.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/*************************************************************************/
-/* texture_loader_dummy.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "texture_loader_dummy.h"
-
-#include "core/os/file_access.h"
-#include "core/string/print_string.h"
-
-#include <string.h>
-
-RES ResourceFormatDummyTexture::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
- unsigned int width = 8;
- unsigned int height = 8;
-
- //We just use some format
- Image::Format fmt = Image::FORMAT_RGB8;
- int rowsize = 3 * width;
-
- Vector<uint8_t> dstbuff;
-
- dstbuff.resize(rowsize * height);
-
- uint8_t **row_p = memnew_arr(uint8_t *, height);
-
- for (unsigned int i = 0; i < height; i++) {
- row_p[i] = 0; //No colors any more, I want them to turn black
- }
-
- memdelete_arr(row_p);
-
- Ref<Image> img = memnew(Image(width, height, 0, fmt, dstbuff));
-
- Ref<ImageTexture> texture = memnew(ImageTexture);
- texture->create_from_image(img);
-
- if (r_error)
- *r_error = OK;
-
- return texture;
-}
-
-void ResourceFormatDummyTexture::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("bmp");
- p_extensions->push_back("dds");
- p_extensions->push_back("exr");
- p_extensions->push_back("jpeg");
- p_extensions->push_back("jpg");
- p_extensions->push_back("hdr");
- p_extensions->push_back("pkm");
- p_extensions->push_back("png");
- p_extensions->push_back("pvr");
- p_extensions->push_back("svg");
- p_extensions->push_back("svgz");
- p_extensions->push_back("tga");
- p_extensions->push_back("webp");
-}
-
-bool ResourceFormatDummyTexture::handles_type(const String &p_type) const {
- return ClassDB::is_parent_class(p_type, "Texture2D");
-}
-
-String ResourceFormatDummyTexture::get_resource_type(const String &p_path) const {
- String extension = p_path.get_extension().to_lower();
- if (
- extension == "bmp" ||
- extension == "dds" ||
- extension == "exr" ||
- extension == "jpeg" ||
- extension == "jpg" ||
- extension == "hdr" ||
- extension == "pkm" ||
- extension == "png" ||
- extension == "pvr" ||
- extension == "svg" ||
- extension == "svgz" ||
- extension == "tga" ||
- extension == "webp") {
- return "ImageTexture";
- }
-
- return "";
-}
diff --git a/drivers/dummy/texture_loader_dummy.h b/drivers/dummy/texture_loader_dummy.h
deleted file mode 100644
index 00e6b9cc53..0000000000
--- a/drivers/dummy/texture_loader_dummy.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*************************************************************************/
-/* texture_loader_dummy.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef TEXTURE_LOADER_DUMMY_H
-#define TEXTURE_LOADER_DUMMY_H
-
-#include "core/io/resource_loader.h"
-#include "scene/resources/texture.h"
-
-class ResourceFormatDummyTexture : public ResourceFormatLoader {
-public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual bool handles_type(const String &p_type) const;
- virtual String get_resource_type(const String &p_path) const;
-
- virtual ~ResourceFormatDummyTexture() {}
-};
-
-#endif // TEXTURE_LOADER_DUMMY_H
diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp
index ded6bbc53e..8cc76b01e1 100644
--- a/drivers/png/image_loader_png.cpp
+++ b/drivers/png/image_loader_png.cpp
@@ -37,7 +37,7 @@
#include <string.h>
Error ImageLoaderPNG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
- const size_t buffer_size = f->get_len();
+ const uint64_t buffer_size = f->get_length();
Vector<uint8_t> file_buffer;
Error err = file_buffer.resize(buffer_size);
if (err) {
@@ -101,6 +101,6 @@ Vector<uint8_t> ImageLoaderPNG::lossless_pack_png(const Ref<Image> &p_image) {
ImageLoaderPNG::ImageLoaderPNG() {
Image::_png_mem_loader_func = load_mem_png;
- Image::lossless_unpacker = lossless_unpack_png;
- Image::lossless_packer = lossless_pack_png;
+ Image::png_unpacker = lossless_unpack_png;
+ Image::png_packer = lossless_pack_png;
}
diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp
index b737a287d1..2971880985 100644
--- a/drivers/png/resource_saver_png.cpp
+++ b/drivers/png/resource_saver_png.cpp
@@ -30,8 +30,8 @@
#include "resource_saver_png.h"
+#include "core/io/file_access.h"
#include "core/io/image.h"
-#include "core/os/file_access.h"
#include "drivers/png/png_driver_common.h"
#include "scene/resources/texture.h"
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 0f8f2260f2..5e2431d44e 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -35,6 +35,10 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
+#ifdef ALSAMIDI_ENABLED
+#include "drivers/alsa/asound-so_wrap.h"
+#endif
+
void AudioDriverPulseAudio::pa_state_cb(pa_context *c, void *userdata) {
AudioDriverPulseAudio *ad = (AudioDriverPulseAudio *)userdata;
@@ -272,6 +276,10 @@ Error AudioDriverPulseAudio::init() {
#else
int dylibloader_verbose = 0;
#endif
+#ifdef ALSAMIDI_ENABLED
+ // If using PulseAudio with ALSA MIDI, we need to initialize ALSA as well
+ initialize_asound(dylibloader_verbose);
+#endif
if (initialize_pulse(dylibloader_verbose)) {
return ERR_CANT_OPEN;
}
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 22151b60c1..a2c9bae852 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -406,14 +406,61 @@ Error DirAccessUnix::remove(String p_path) {
}
}
-size_t DirAccessUnix::get_space_left() {
+bool DirAccessUnix::is_link(String p_file) {
+ if (p_file.is_rel_path()) {
+ p_file = get_current_dir().plus_file(p_file);
+ }
+
+ p_file = fix_path(p_file);
+
+ struct stat flags;
+ if ((lstat(p_file.utf8().get_data(), &flags) != 0)) {
+ return FAILED;
+ }
+
+ return S_ISLNK(flags.st_mode);
+}
+
+String DirAccessUnix::read_link(String p_file) {
+ if (p_file.is_rel_path()) {
+ p_file = get_current_dir().plus_file(p_file);
+ }
+
+ p_file = fix_path(p_file);
+
+ char buf[256];
+ memset(buf, 0, 256);
+ ssize_t len = readlink(p_file.utf8().get_data(), buf, sizeof(buf));
+ String link;
+ if (len > 0) {
+ link.parse_utf8(buf, len);
+ }
+ return link;
+}
+
+Error DirAccessUnix::create_link(String p_source, String p_target) {
+ if (p_target.is_rel_path()) {
+ p_target = get_current_dir().plus_file(p_target);
+ }
+
+ p_source = fix_path(p_source);
+ p_target = fix_path(p_target);
+
+ if (symlink(p_source.utf8().get_data(), p_target.utf8().get_data()) == 0) {
+ return OK;
+ } else {
+ return FAILED;
+ }
+}
+
+uint64_t DirAccessUnix::get_space_left() {
#ifndef NO_STATVFS
struct statvfs vfs;
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
return 0;
};
- return vfs.f_bfree * vfs.f_bsize;
+ return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize;
#else
// FIXME: Implement this.
return 0;
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 54f4a5c312..8b19308967 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -33,7 +33,7 @@
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include <dirent.h>
#include <sys/stat.h>
@@ -79,7 +79,11 @@ public:
virtual Error rename(String p_path, String p_new_path);
virtual Error remove(String p_path);
- virtual size_t get_space_left();
+ virtual bool is_link(String p_file);
+ virtual String read_link(String p_file);
+ virtual Error create_link(String p_source, String p_target);
+
+ virtual uint64_t get_space_left();
virtual String get_filesystem_type() const;
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 4c08380dd0..6ea55219bb 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -184,11 +184,11 @@ String FileAccessUnix::get_path_absolute() const {
return path;
}
-void FileAccessUnix::seek(size_t p_position) {
+void FileAccessUnix::seek(uint64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
last_error = OK;
- if (fseek(f, p_position, SEEK_SET)) {
+ if (fseeko(f, p_position, SEEK_SET)) {
check_errors();
}
}
@@ -196,15 +196,15 @@ void FileAccessUnix::seek(size_t p_position) {
void FileAccessUnix::seek_end(int64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
- if (fseek(f, p_position, SEEK_END)) {
+ if (fseeko(f, p_position, SEEK_END)) {
check_errors();
}
}
-size_t FileAccessUnix::get_position() const {
+uint64_t FileAccessUnix::get_position() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
- long pos = ftell(f);
+ int64_t pos = ftello(f);
if (pos < 0) {
check_errors();
ERR_FAIL_V(0);
@@ -212,15 +212,15 @@ size_t FileAccessUnix::get_position() const {
return pos;
}
-size_t FileAccessUnix::get_len() const {
+uint64_t FileAccessUnix::get_length() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
- long pos = ftell(f);
+ int64_t pos = ftello(f);
ERR_FAIL_COND_V(pos < 0, 0);
- ERR_FAIL_COND_V(fseek(f, 0, SEEK_END), 0);
- long size = ftell(f);
+ ERR_FAIL_COND_V(fseeko(f, 0, SEEK_END), 0);
+ int64_t size = ftello(f);
ERR_FAIL_COND_V(size < 0, 0);
- ERR_FAIL_COND_V(fseek(f, pos, SEEK_SET), 0);
+ ERR_FAIL_COND_V(fseeko(f, pos, SEEK_SET), 0);
return size;
}
@@ -239,11 +239,11 @@ uint8_t FileAccessUnix::get_8() const {
return b;
}
-int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessUnix::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
- int read = fread(p_dst, 1, p_length, f);
+
+ uint64_t read = fread(p_dst, 1, p_length, f);
check_errors();
return read;
};
@@ -262,10 +262,10 @@ void FileAccessUnix::store_8(uint8_t p_dest) {
ERR_FAIL_COND(fwrite(&p_dest, 1, 1, f) != 1);
}
-void FileAccessUnix::store_buffer(const uint8_t *p_src, int p_length) {
+void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
- ERR_FAIL_COND(!p_src);
- ERR_FAIL_COND((int)fwrite(p_src, 1, p_length, f) != p_length);
+ ERR_FAIL_COND(!p_src && p_length > 0);
+ ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length);
}
bool FileAccessUnix::file_exists(const String &p_path) {
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 998fad7909..8b27c308e1 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -31,7 +31,7 @@
#ifndef FILE_ACCESS_UNIX_H
#define FILE_ACCESS_UNIX_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/memory.h"
#include <stdio.h>
@@ -61,21 +61,21 @@ public:
virtual String get_path() const; /// returns the path for the current open file
virtual String get_path_absolute() const; /// returns the absolute path for the current open file
- virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual uint64_t get_position() const; ///< get position in the file
+ virtual uint64_t get_length() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
virtual bool file_exists(const String &p_path); ///< return true if a file exists
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index 053e3fd9d6..e8f8ae4717 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -89,7 +89,7 @@ static IPAddress _sockaddr2ip(struct sockaddr *p_addr) {
return ip;
};
-IPAddress IPUnix::_resolve_hostname(const String &p_hostname, Type p_type) {
+void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type) const {
struct addrinfo hints;
struct addrinfo *result = nullptr;
@@ -108,7 +108,7 @@ IPAddress IPUnix::_resolve_hostname(const String &p_hostname, Type p_type) {
int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result);
if (s != 0) {
ERR_PRINT("getaddrinfo failed! Cannot resolve hostname.");
- return IPAddress();
+ return;
};
if (result == nullptr || result->ai_addr == nullptr) {
@@ -116,14 +116,24 @@ IPAddress IPUnix::_resolve_hostname(const String &p_hostname, Type p_type) {
if (result) {
freeaddrinfo(result);
}
- return IPAddress();
+ return;
};
- IPAddress ip = _sockaddr2ip(result->ai_addr);
+ struct addrinfo *next = result;
- freeaddrinfo(result);
+ do {
+ if (next->ai_addr == NULL) {
+ next = next->ai_next;
+ continue;
+ }
+ IPAddress ip = _sockaddr2ip(next->ai_addr);
+ if (!r_addresses.find(ip)) {
+ r_addresses.push_back(ip);
+ }
+ next = next->ai_next;
+ } while (next);
- return ip;
+ freeaddrinfo(result);
}
#if defined(WINDOWS_ENABLED)
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
index e6479be6e5..0d64648b39 100644
--- a/drivers/unix/ip_unix.h
+++ b/drivers/unix/ip_unix.h
@@ -38,7 +38,7 @@
class IPUnix : public IP {
GDCLASS(IPUnix, IP);
- virtual IPAddress _resolve_hostname(const String &p_hostname, IP::Type p_type) override;
+ virtual void _resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type = TYPE_ANY) const override;
static IP *_create_unix();
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index 222aef998c..efeaf32ff7 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -466,7 +466,7 @@ Error NetSocketPosix::poll(PollType p_type, int p_timeout) const {
FD_ZERO(&ex);
FD_SET(_sock, &ex);
struct timeval timeout = { p_timeout / 1000, (p_timeout % 1000) * 1000 };
- // For blocking operation, pass nullptr timeout pointer to select.
+ // For blocking operation, pass nullptr timeout pointer to select.
struct timeval *tp = nullptr;
if (p_timeout >= 0) {
// If timeout is non-negative, we want to specify the timeout instead.
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 15cd7bee92..a5c61bbea5 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -195,8 +195,8 @@ OS::Time OS_Unix::get_time(bool utc) const {
}
Time ret;
ret.hour = lt.tm_hour;
- ret.min = lt.tm_min;
- ret.sec = lt.tm_sec;
+ ret.minute = lt.tm_min;
+ ret.second = lt.tm_sec;
get_time_zone_info();
return ret;
}
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 43b2a24172..c69b516f37 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -31,7 +31,7 @@
#include "rendering_device_vulkan.h"
#include "core/config/project_settings.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#include "core/templates/hashfuncs.h"
#include "drivers/vulkan/vulkan_context.h"
@@ -3244,7 +3244,7 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f
/**** ATTACHMENT ****/
/********************/
-VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, int *r_color_attachment_count) {
+VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, int *r_color_attachment_count, uint32_t p_view_count) {
Vector<VkAttachmentDescription> attachments;
Vector<VkAttachmentReference> color_references;
Vector<VkAttachmentReference> depth_stencil_references;
@@ -3280,7 +3280,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
// For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write
// Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs.
- // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that
+ // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that
// stage
switch (is_depth_stencil ? p_initial_depth_action : p_initial_color_action) {
case INITIAL_ACTION_CLEAR_REGION:
@@ -3469,6 +3469,31 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
render_pass_create_info.dependencyCount = 0;
render_pass_create_info.pDependencies = nullptr;
+ const uint32_t view_mask = (1 << p_view_count) - 1;
+ const uint32_t correlation_mask = (1 << p_view_count) - 1;
+ VkRenderPassMultiviewCreateInfo render_pass_multiview_create_info;
+
+ if (p_view_count > 1) {
+ const VulkanContext::MultiviewCapabilities capabilities = context->get_multiview_capabilities();
+
+ // For now this only works with multiview!
+ ERR_FAIL_COND_V_MSG(!capabilities.is_supported, VK_NULL_HANDLE, "Multiview not supported");
+
+ // Make sure we limit this to the number of views we support.
+ ERR_FAIL_COND_V_MSG(p_view_count > capabilities.max_view_count, VK_NULL_HANDLE, "Hardware does not support requested number of views for Multiview render pass");
+
+ render_pass_multiview_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
+ render_pass_multiview_create_info.pNext = nullptr;
+ render_pass_multiview_create_info.subpassCount = 1;
+ render_pass_multiview_create_info.pViewMasks = &view_mask;
+ render_pass_multiview_create_info.dependencyCount = 0;
+ render_pass_multiview_create_info.pViewOffsets = nullptr;
+ render_pass_multiview_create_info.correlationMaskCount = 1;
+ render_pass_multiview_create_info.pCorrelationMasks = &correlation_mask;
+
+ render_pass_create_info.pNext = &render_pass_multiview_create_info;
+ }
+
VkRenderPass render_pass;
VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass);
ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass failed with error " + itos(res) + ".");
@@ -3479,11 +3504,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
return render_pass;
}
-RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create(const Vector<AttachmentFormat> &p_format) {
+RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count) {
_THREAD_SAFE_METHOD_
FramebufferFormatKey key;
key.attachments = p_format;
+ key.view_count = p_view_count;
const Map<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key);
if (E) {
@@ -3492,7 +3518,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
}
int color_references;
- VkRenderPass render_pass = _render_pass_create(p_format, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, &color_references); //actions don't matter for this use case
+ VkRenderPass render_pass = _render_pass_create(p_format, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, &color_references, p_view_count); //actions don't matter for this use case
if (render_pass == VK_NULL_HANDLE) { //was likely invalid
return INVALID_ID;
@@ -3505,6 +3531,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
fb_format.color_attachments = color_references;
fb_format.render_pass = render_pass;
fb_format.samples = p_format[0].samples;
+ fb_format.view_count = p_view_count;
framebuffer_formats[id] = fb_format;
return id;
}
@@ -3580,11 +3607,12 @@ RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, Textur
framebuffer.format_id = framebuffer_format_create_empty(p_samples);
ERR_FAIL_COND_V(p_format_check != INVALID_FORMAT_ID && framebuffer.format_id != p_format_check, RID());
framebuffer.size = p_size;
+ framebuffer.view_count = 1;
return framebuffer_owner.make_rid(framebuffer);
}
-RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check) {
+RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check, uint32_t p_view_count) {
_THREAD_SAFE_METHOD_
Vector<AttachmentFormat> attachments;
@@ -3594,6 +3622,8 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac
Texture *texture = texture_owner.getornull(p_texture_attachments[i]);
ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture index supplied for framebuffer (" + itos(i) + ") is not a valid texture.");
+ ERR_FAIL_COND_V_MSG(texture->layers != p_view_count, RID(), "Layers of our texture doesn't match view count for this framebuffer");
+
if (i == 0) {
size.width = texture->width;
size.height = texture->height;
@@ -3609,7 +3639,7 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac
attachments.push_back(af);
}
- FramebufferFormatID format_id = framebuffer_format_create(attachments);
+ FramebufferFormatID format_id = framebuffer_format_create(attachments, p_view_count);
if (format_id == INVALID_ID) {
return RID();
}
@@ -3621,6 +3651,7 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac
framebuffer.format_id = format_id;
framebuffer.texture_ids = p_texture_attachments;
framebuffer.size = size;
+ framebuffer.view_count = p_view_count;
RID id = framebuffer_owner.make_rid(framebuffer);
@@ -5904,12 +5935,13 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
vk.final_color_action = p_final_color_action;
vk.initial_depth_action = p_initial_depth_action;
vk.final_depth_action = p_final_depth_action;
+ vk.view_count = p_framebuffer->view_count;
if (!p_framebuffer->framebuffers.has(vk)) {
//need to create this version
Framebuffer::Version version;
- version.render_pass = _render_pass_create(framebuffer_formats[p_framebuffer->format_id].E->key().attachments, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action);
+ version.render_pass = _render_pass_create(framebuffer_formats[p_framebuffer->format_id].E->key().attachments, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, nullptr, p_framebuffer->view_count);
VkFramebufferCreateInfo framebuffer_create_info;
framebuffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index a2527d5c33..f4fe9cf956 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -234,7 +234,12 @@ class RenderingDeviceVulkan : public RenderingDevice {
struct FramebufferFormatKey {
Vector<AttachmentFormat> attachments;
+ uint32_t view_count = 1;
bool operator<(const FramebufferFormatKey &p_key) const {
+ if (view_count != p_key.view_count) {
+ return view_count < p_key.view_count;
+ }
+
int as = attachments.size();
int bs = p_key.attachments.size();
if (as != bs) {
@@ -261,7 +266,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
}
};
- VkRenderPass _render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depthcolor_action, int *r_color_attachment_count = nullptr);
+ VkRenderPass _render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depthcolor_action, int *r_color_attachment_count = nullptr, uint32_t p_view_count = 1);
// This is a cache and it's never freed, it ensures
// IDs for a given format are always unique.
@@ -271,6 +276,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkRenderPass render_pass = VK_NULL_HANDLE; //here for constructing shaders, never used, see section (7.2. Render Pass Compatibility from Vulkan spec)
int color_attachments = 0; //used for pipeline validation
TextureSamples samples;
+ uint32_t view_count = 1; // number of views
};
Map<FramebufferFormatID, FramebufferFormat> framebuffer_formats;
@@ -282,11 +288,16 @@ class RenderingDeviceVulkan : public RenderingDevice {
FinalAction final_color_action;
InitialAction initial_depth_action;
FinalAction final_depth_action;
+ uint32_t view_count;
bool operator<(const VersionKey &p_key) const {
if (initial_color_action == p_key.initial_color_action) {
if (final_color_action == p_key.final_color_action) {
if (initial_depth_action == p_key.initial_depth_action) {
- return final_depth_action < p_key.final_depth_action;
+ if (final_depth_action == p_key.final_depth_action) {
+ return view_count < p_key.view_count;
+ } else {
+ return final_depth_action < p_key.final_depth_action;
+ }
} else {
return initial_depth_action < p_key.initial_depth_action;
}
@@ -309,6 +320,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
Map<VersionKey, Version> framebuffers;
Size2 size;
+ uint32_t view_count;
};
RID_Owner<Framebuffer, true> framebuffer_owner;
@@ -938,11 +950,11 @@ public:
/**** FRAMEBUFFER ****/
/*********************/
- virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format);
+ virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1);
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1);
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format);
- virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID);
+ virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID);
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer);
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 4649cee17f..6ed43b5d31 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -337,6 +337,9 @@ Error VulkanContext::_initialize_extensions() {
extension_names[enabled_extension_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
enabled_debug_utils = true;
}
+ if (!strcmp(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, instance_extensions[i].extensionName)) {
+ extension_names[enabled_extension_count++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
+ }
if (enabled_extension_count >= MAX_EXTENSIONS) {
free(instance_extensions);
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
@@ -504,6 +507,8 @@ Error VulkanContext::_check_capabilities() {
// assume not supported until proven otherwise
multiview_capabilities.is_supported = false;
+ multiview_capabilities.geometry_shader_is_supported = false;
+ multiview_capabilities.tessellation_shader_is_supported = false;
multiview_capabilities.max_view_count = 0;
multiview_capabilities.max_instance_count = 0;
subgroup_capabilities.size = 0;
@@ -529,7 +534,8 @@ Error VulkanContext::_check_capabilities() {
device_features_func(gpu, &device_features);
multiview_capabilities.is_supported = multiview_features.multiview;
- // For now we ignore if multiview is available in geometry and tesselation as we do not currently support those
+ multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader;
+ multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader;
}
// check extended properties
@@ -573,7 +579,7 @@ Error VulkanContext::_check_capabilities() {
#ifdef DEBUG_ENABLED
print_line("- Vulkan multiview supported:");
- print_line(" max views: " + itos(multiview_capabilities.max_view_count));
+ print_line(" max view count: " + itos(multiview_capabilities.max_view_count));
print_line(" max instances: " + itos(multiview_capabilities.max_instance_count));
} else {
print_line("- Vulkan multiview not supported");
@@ -694,8 +700,25 @@ Error VulkanContext::_create_physical_device() {
free(physical_devices);
ERR_FAIL_V(ERR_CANT_CREATE);
}
- /* for now, just grab the first physical device */
+
+ // TODO: At least on Linux Laptops integrated GPUs fail with Vulkan in many instances.
+ // The device should really be a preference, but for now choosing a discrete GPU over the
+ // integrated one is better than the default.
+
+ // Default to first device
uint32_t device_index = 0;
+
+ for (uint32_t i = 0; i < gpu_count; ++i) {
+ VkPhysicalDeviceProperties props;
+ vkGetPhysicalDeviceProperties(physical_devices[i], &props);
+
+ if (props.deviceType == VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
+ // Prefer discrete GPU.
+ device_index = i;
+ break;
+ }
+ }
+
gpu = physical_devices[device_index];
free(physical_devices);
@@ -755,6 +778,10 @@ Error VulkanContext::_create_physical_device() {
swapchainExtFound = 1;
extension_names[enabled_extension_count++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
}
+ if (!strcmp(VK_KHR_MULTIVIEW_EXTENSION_NAME, device_extensions[i].extensionName)) {
+ // if multiview is supported, enable it
+ extension_names[enabled_extension_count++] = VK_KHR_MULTIVIEW_EXTENSION_NAME;
+ }
if (enabled_extension_count >= MAX_EXTENSIONS) {
free(device_extensions);
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
@@ -947,6 +974,39 @@ Error VulkanContext::_create_device() {
queues[1].flags = 0;
sdevice.queueCreateInfoCount = 2;
}
+
+#ifdef VK_VERSION_1_2
+ VkPhysicalDeviceVulkan11Features vulkan11features;
+
+ vulkan11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
+ vulkan11features.pNext = nullptr;
+ // !BAS! Need to figure out which ones of these we want enabled...
+ vulkan11features.storageBuffer16BitAccess = 0;
+ vulkan11features.uniformAndStorageBuffer16BitAccess = 0;
+ vulkan11features.storagePushConstant16 = 0;
+ vulkan11features.storageInputOutput16 = 0;
+ vulkan11features.multiview = multiview_capabilities.is_supported;
+ vulkan11features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
+ vulkan11features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
+ vulkan11features.variablePointersStorageBuffer = 0;
+ vulkan11features.variablePointers = 0;
+ vulkan11features.protectedMemory = 0;
+ vulkan11features.samplerYcbcrConversion = 0;
+ vulkan11features.shaderDrawParameters = 0;
+
+ sdevice.pNext = &vulkan11features;
+#elif VK_VERSION_1_1
+ VkPhysicalDeviceMultiviewFeatures multiview_features;
+
+ multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
+ multiview_features.pNext = nullptr;
+ multiview_features.multiview = multiview_capabilities.is_supported;
+ multiview_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
+ multiview_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
+
+ sdevice.pNext = &multiview_features;
+#endif
+
err = vkCreateDevice(gpu, &sdevice, nullptr, &device);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index 3d9b295c5a..738ead4f96 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -56,8 +56,10 @@ public:
struct MultiviewCapabilities {
bool is_supported;
- int32_t max_view_count;
- int32_t max_instance_count;
+ bool geometry_shader_is_supported;
+ bool tessellation_shader_is_supported;
+ uint32_t max_view_count;
+ uint32_t max_instance_count;
};
private:
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 2c9f28717d..325bae5b56 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -198,7 +198,7 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) {
if (_get_root_string() == "") {
int p = current_dir.find(":");
if (p != -1) {
- return current_dir.right(p + 1);
+ return current_dir.substr(p + 1);
}
}
return current_dir;
@@ -208,7 +208,7 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) {
bool DirAccessWindows::file_exists(String p_file) {
GLOBAL_LOCK_FUNCTION
- if (!p_file.is_abs_path()) {
+ if (!p_file.is_absolute_path()) {
p_file = get_current_dir().plus_file(p_file);
}
@@ -325,14 +325,15 @@ FileType DirAccessWindows::get_file_type(const String& p_file) const {
}
*/
-size_t DirAccessWindows::get_space_left() {
+
+uint64_t DirAccessWindows::get_space_left() {
uint64_t bytes = 0;
if (!GetDiskFreeSpaceEx(nullptr, (PULARGE_INTEGER)&bytes, nullptr, nullptr)) {
return 0;
}
//this is either 0 or a value in bytes.
- return (size_t)bytes;
+ return bytes;
}
String DirAccessWindows::get_filesystem_type() const {
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index 7f10023470..1ba4e70e42 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -33,7 +33,7 @@
#ifdef WINDOWS_ENABLED
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
/**
@author Juan Linietsky <reduz@gmail.com>
@@ -78,8 +78,11 @@ public:
virtual Error rename(String p_path, String p_new_path);
virtual Error remove(String p_path);
- //virtual FileType get_file_type() const;
- size_t get_space_left();
+ virtual bool is_link(String p_file) { return false; };
+ virtual String read_link(String p_file) { return p_file; };
+ virtual Error create_link(String p_source, String p_target) { return FAILED; };
+
+ uint64_t get_space_left();
virtual String get_filesystem_type() const;
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index b1b3fc9092..d6deda7b5d 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -193,10 +193,11 @@ bool FileAccessWindows::is_open() const {
return (f != nullptr);
}
-void FileAccessWindows::seek(size_t p_position) {
+void FileAccessWindows::seek(uint64_t p_position) {
ERR_FAIL_COND(!f);
+
last_error = OK;
- if (fseek(f, p_position, SEEK_SET)) {
+ if (_fseeki64(f, p_position, SEEK_SET)) {
check_errors();
}
prev_op = 0;
@@ -204,28 +205,27 @@ void FileAccessWindows::seek(size_t p_position) {
void FileAccessWindows::seek_end(int64_t p_position) {
ERR_FAIL_COND(!f);
- if (fseek(f, p_position, SEEK_END)) {
+ if (_fseeki64(f, p_position, SEEK_END)) {
check_errors();
}
prev_op = 0;
}
-size_t FileAccessWindows::get_position() const {
- size_t aux_position = 0;
- aux_position = ftell(f);
- if (!aux_position) {
+uint64_t FileAccessWindows::get_position() const {
+ int64_t aux_position = _ftelli64(f);
+ if (aux_position < 0) {
check_errors();
}
return aux_position;
}
-size_t FileAccessWindows::get_len() const {
+uint64_t FileAccessWindows::get_length() const {
ERR_FAIL_COND_V(!f, 0);
- size_t pos = get_position();
- fseek(f, 0, SEEK_END);
- int size = get_position();
- fseek(f, pos, SEEK_SET);
+ uint64_t pos = get_position();
+ _fseeki64(f, 0, SEEK_END);
+ uint64_t size = get_position();
+ _fseeki64(f, pos, SEEK_SET);
return size;
}
@@ -252,17 +252,17 @@ uint8_t FileAccessWindows::get_8() const {
return b;
}
-int FileAccessWindows::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessWindows::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(!f, -1);
+
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == WRITE) {
fflush(f);
}
prev_op = READ;
}
- int read = fread(p_dst, 1, p_length, f);
+ uint64_t read = fread(p_dst, 1, p_length, f);
check_errors();
return read;
};
@@ -292,8 +292,9 @@ void FileAccessWindows::store_8(uint8_t p_dest) {
fwrite(&p_dest, 1, 1, f);
}
-void FileAccessWindows::store_buffer(const uint8_t *p_src, int p_length) {
+void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND(!f);
+ ERR_FAIL_COND(!p_src && p_length > 0);
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == READ) {
if (last_error != ERR_FILE_EOF) {
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index 507e0b2c20..7280fc3237 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -33,7 +33,7 @@
#ifdef WINDOWS_ENABLED
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/memory.h"
#include <stdio.h>
@@ -56,21 +56,21 @@ public:
virtual String get_path() const; /// returns the path for the current open file
virtual String get_path_absolute() const; /// returns the absolute path for the current open file
- virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual uint64_t get_position() const; ///< get position in the file
+ virtual uint64_t get_length() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index c0d5716c4e..cc07d589c5 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -63,7 +63,7 @@ static const char *_joy_axis_descriptions[JOY_AXIS_MAX * 2] = {
String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent");
- // Joypad motion events will display slighlty differently than what the event->as_text() provides. See #43660.
+ // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
Ref<InputEventJoypadMotion> jpmotion = p_event;
if (jpmotion.is_valid()) {
String desc = TTR("Unknown Joypad Axis");
@@ -97,11 +97,11 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) {
if (mod.is_valid()) {
show_mods = true;
- mod_checkboxes[MOD_ALT]->set_pressed(mod->get_alt());
- mod_checkboxes[MOD_SHIFT]->set_pressed(mod->get_shift());
- mod_checkboxes[MOD_COMMAND]->set_pressed(mod->get_command());
- mod_checkboxes[MOD_CONTROL]->set_pressed(mod->get_control());
- mod_checkboxes[MOD_META]->set_pressed(mod->get_metakey());
+ mod_checkboxes[MOD_ALT]->set_pressed(mod->is_alt_pressed());
+ mod_checkboxes[MOD_SHIFT]->set_pressed(mod->is_shift_pressed());
+ mod_checkboxes[MOD_COMMAND]->set_pressed(mod->is_command_pressed());
+ mod_checkboxes[MOD_CTRL]->set_pressed(mod->is_ctrl_pressed());
+ mod_checkboxes[MOD_META]->set_pressed(mod->is_meta_pressed());
store_command_checkbox->set_pressed(mod->is_storing_command());
}
@@ -122,9 +122,9 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) {
// Update selected item in input list for keys, joybuttons and joyaxis only (since the mouse cannot be "listened" for).
if (k.is_valid() || joyb.is_valid() || joym.is_valid()) {
- TreeItem *category = input_list_tree->get_root()->get_children();
+ TreeItem *category = input_list_tree->get_root()->get_first_child();
while (category) {
- TreeItem *input_item = category->get_children();
+ TreeItem *input_item = category->get_first_child();
// has_type this should be always true, unless the tree structure has been misconfigured.
bool has_type = input_item->get_parent()->has_meta("__type");
@@ -384,15 +384,15 @@ void InputEventConfigurationDialog::_mod_toggled(bool p_checked, int p_index) {
}
if (p_index == 0) {
- ie->set_alt(p_checked);
+ ie->set_alt_pressed(p_checked);
} else if (p_index == 1) {
- ie->set_shift(p_checked);
+ ie->set_shift_pressed(p_checked);
} else if (p_index == 2) {
- ie->set_command(p_checked);
+ ie->set_command_pressed(p_checked);
} else if (p_index == 3) {
- ie->set_control(p_checked);
+ ie->set_ctrl_pressed(p_checked);
} else if (p_index == 4) {
- ie->set_metakey(p_checked);
+ ie->set_meta_pressed(p_checked);
}
_set_event(ie);
@@ -413,7 +413,7 @@ void InputEventConfigurationDialog::_store_command_toggled(bool p_checked) {
mod_checkboxes[MOD_COMMAND]->show();
mod_checkboxes[MOD_COMMAND]->set_text("Meta (Command)");
#else
- mod_checkboxes[MOD_CONTROL]->hide();
+ mod_checkboxes[MOD_CTRL]->hide();
mod_checkboxes[MOD_COMMAND]->show();
mod_checkboxes[MOD_COMMAND]->set_text("Control (Command)");
@@ -421,7 +421,7 @@ void InputEventConfigurationDialog::_store_command_toggled(bool p_checked) {
} else {
// If not, hide Command, show Control and Meta.
mod_checkboxes[MOD_COMMAND]->hide();
- mod_checkboxes[MOD_CONTROL]->show();
+ mod_checkboxes[MOD_CTRL]->show();
mod_checkboxes[MOD_META]->show();
}
}
@@ -469,11 +469,11 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
}
// Maintain modifier state from checkboxes
- k->set_alt(mod_checkboxes[MOD_ALT]->is_pressed());
- k->set_shift(mod_checkboxes[MOD_SHIFT]->is_pressed());
- k->set_command(mod_checkboxes[MOD_COMMAND]->is_pressed());
- k->set_control(mod_checkboxes[MOD_CONTROL]->is_pressed());
- k->set_metakey(mod_checkboxes[MOD_META]->is_pressed());
+ k->set_alt_pressed(mod_checkboxes[MOD_ALT]->is_pressed());
+ k->set_shift_pressed(mod_checkboxes[MOD_SHIFT]->is_pressed());
+ k->set_command_pressed(mod_checkboxes[MOD_COMMAND]->is_pressed());
+ k->set_ctrl_pressed(mod_checkboxes[MOD_CTRL]->is_pressed());
+ k->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed());
k->set_store_command(store_command_checkbox->is_pressed());
_set_event(k);
@@ -484,11 +484,11 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
mb.instance();
mb->set_button_index(idx);
// Maintain modifier state from checkboxes
- mb->set_alt(mod_checkboxes[MOD_ALT]->is_pressed());
- mb->set_shift(mod_checkboxes[MOD_SHIFT]->is_pressed());
- mb->set_command(mod_checkboxes[MOD_COMMAND]->is_pressed());
- mb->set_control(mod_checkboxes[MOD_CONTROL]->is_pressed());
- mb->set_metakey(mod_checkboxes[MOD_META]->is_pressed());
+ mb->set_alt_pressed(mod_checkboxes[MOD_ALT]->is_pressed());
+ mb->set_shift_pressed(mod_checkboxes[MOD_SHIFT]->is_pressed());
+ mb->set_command_pressed(mod_checkboxes[MOD_COMMAND]->is_pressed());
+ mb->set_ctrl_pressed(mod_checkboxes[MOD_CTRL]->is_pressed());
+ mb->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed());
mb->set_store_command(store_command_checkbox->is_pressed());
_set_event(mb);
@@ -731,7 +731,7 @@ void ActionMapEditor::_add_action_pressed() {
void ActionMapEditor::_add_action(const String &p_name) {
if (p_name == "" || !_is_action_name_valid(p_name)) {
- show_message(TTR("Invalid action name. it cannot be.is_empty()() nor contain '/', ':', '=', '\\' or '\"'"));
+ show_message(TTR("Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or '\"'"));
return;
}
@@ -756,7 +756,7 @@ void ActionMapEditor::_action_edited() {
if (new_name == "" || !_is_action_name_valid(new_name)) {
ti->set_text(0, old_name);
- show_message(TTR("Invalid action name. it cannot be.is_empty()() nor contain '/', ':', '=', '\\' or '\"'"));
+ show_message(TTR("Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or '\"'"));
return;
}
@@ -969,9 +969,9 @@ void ActionMapEditor::_notification(int p_what) {
}
void ActionMapEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ActionMapEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ActionMapEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &ActionMapEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &ActionMapEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &ActionMapEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &ActionMapEditor::drop_data_fw);
ADD_SIGNAL(MethodInfo("action_added", PropertyInfo(Variant::STRING, "name")));
ADD_SIGNAL(MethodInfo("action_edited", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::DICTIONARY, "new_action")));
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index fb097ddfdd..aff3e6e957 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -78,11 +78,11 @@ private:
MOD_ALT,
MOD_SHIFT,
MOD_COMMAND,
- MOD_CONTROL,
+ MOD_CTRL,
MOD_META,
MOD_MAX
};
- String mods[MOD_MAX] = { "Alt", "Shift", "Command", "Control", "Meta" };
+ String mods[MOD_MAX] = { "Alt", "Shift", "Command", "Ctrl", "Metakey" };
CheckBox *mod_checkboxes[MOD_MAX];
CheckBox *store_command_checkbox;
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 67b52bf0ca..63ffab6727 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -619,7 +619,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
float v_zoom_orig = v_zoom;
- if (mb->get_command()) {
+ if (mb->is_command_pressed()) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
} else {
if (v_zoom < 100000) {
@@ -632,7 +632,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
float v_zoom_orig = v_zoom;
- if (mb->get_command()) {
+ if (mb->is_command_pressed()) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
} else {
if (v_zoom > 0.000001) {
@@ -691,9 +691,9 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
//first check point
//command makes it ignore the main point, so control point editors can be force-edited
//path 2D editing in the 3D and 2D editors works the same way
- if (!mb->get_command()) {
+ if (!mb->is_command_pressed()) {
if (edit_points[i].point_rect.has_point(mb->get_position())) {
- if (mb->get_shift()) {
+ if (mb->is_shift_pressed()) {
//add to selection
if (selection.has(i)) {
selection.erase(i);
@@ -743,7 +743,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
//insert new point
- if (mb->get_command() && mb->get_position().x >= timeline->get_name_limit() && mb->get_position().x < get_size().width - timeline->get_buttons_width()) {
+ if (mb->is_command_pressed() && mb->get_position().x >= timeline->get_name_limit() && mb->get_position().x < get_size().width - timeline->get_buttons_width()) {
Array new_point;
new_point.resize(5);
@@ -961,7 +961,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (box_selecting_attempt && mm.is_valid()) {
if (!box_selecting) {
box_selecting = true;
- box_selecting_add = mm->get_shift();
+ box_selecting_add = mm->is_shift_pressed();
}
box_selection_to = mm->get_position();
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 89f77f3c77..fde75e0f0c 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -165,7 +165,7 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
Dictionary d_old = animation->track_get_key_value(track, key);
Dictionary d_new = d_old.duplicate();
d_new[p_name] = p_value;
@@ -412,7 +412,7 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
Dictionary d = animation->track_get_key_value(track, key);
ERR_FAIL_COND_V(!d.has(name), false);
r_ret = d[p_name];
@@ -523,9 +523,9 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "location"));
- p_list->push_back(PropertyInfo(Variant::QUAT, "rotation"));
+ p_list->push_back(PropertyInfo(Variant::QUATERNION, "rotation"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
@@ -781,7 +781,7 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
Dictionary d_old = animation->track_get_key_value(track, key);
Dictionary d_new = d_old.duplicate();
d_new[p_name] = p_value;
@@ -1012,7 +1012,7 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
Dictionary d = animation->track_get_key_value(track, key);
ERR_FAIL_COND_V(!d.has(name), false);
r_ret = d[p_name];
@@ -1162,9 +1162,9 @@ public:
if (same_track_type) {
switch (animation->track_get_type(first_track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "location"));
- p_list->push_back(PropertyInfo(Variant::QUAT, "rotation"));
+ p_list->push_back(PropertyInfo(Variant::QUATERNION, "rotation"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
case Animation::TYPE_VALUE: {
@@ -1659,7 +1659,7 @@ void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
int x = mb->get_position().x - get_name_limit();
float ofs = x / get_zoom_scale() + get_value();
- emit_signal("timeline_changed", ofs, false);
+ emit_signal("timeline_changed", ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT));
dragging_timeline = true;
}
if (!dragging_timeline && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) {
@@ -1698,7 +1698,7 @@ void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (dragging_timeline) {
int x = mm->get_position().x - get_name_limit();
float ofs = x / get_zoom_scale() + get_value();
- emit_signal("timeline_changed", ofs, false);
+ emit_signal("timeline_changed", ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT));
}
if (panning_timeline) {
int x = mm->get_position().x - get_name_limit();
@@ -2007,7 +2007,7 @@ void AnimationTrackEdit::_notification(int p_what) {
interp_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
interp_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
draw_texture(icon, interp_mode_rect.position);
}
//make it easier to click
@@ -2017,7 +2017,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
interp_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
interp_mode_rect.size.x += down_icon->get_width();
} else {
@@ -2040,7 +2040,7 @@ void AnimationTrackEdit::_notification(int p_what) {
loop_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
loop_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
draw_texture(icon, loop_mode_rect.position);
}
@@ -2050,7 +2050,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
loop_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
loop_mode_rect.size.x += down_icon->get_width();
} else {
@@ -2441,7 +2441,7 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
if (key_idx != -1) {
String text = TTR("Time (s): ") + rtos(animation->track_get_key_time(track, key_idx)) + "\n";
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
Dictionary d = animation->track_get_key_value(track, key_idx);
if (d.has("location")) {
text += "Pos: " + String(d["location"]) + "\n";
@@ -2662,7 +2662,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
if (key_idx != -1) {
- if (mb->get_command() || mb->get_shift()) {
+ if (mb->is_command_pressed() || mb->is_shift_pressed()) {
if (editor->is_key_selected(track, key_idx)) {
emit_signal("deselect_key", key_idx);
} else {
@@ -3254,8 +3254,8 @@ void AnimationTrackEditor::_name_limit_changed() {
}
}
-void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag) {
- emit_signal("timeline_changed", p_new_pos, p_drag);
+void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only) {
+ emit_signal("timeline_changed", p_new_pos, p_drag, p_timeline_only);
}
void AnimationTrackEditor::_track_remove_request(int p_track) {
@@ -3310,7 +3310,7 @@ static bool track_type_is_resettable(Animation::TrackType p_type) {
[[fallthrough]];
case Animation::TYPE_BEZIER:
[[fallthrough]];
- case Animation::TYPE_TRANSFORM:
+ case Animation::TYPE_TRANSFORM3D:
return true;
default:
return false;
@@ -3376,7 +3376,7 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
case Variant::FLOAT:
case Variant::VECTOR2:
case Variant::VECTOR3:
- case Variant::QUAT:
+ case Variant::QUATERNION:
case Variant::PLANE:
case Variant::COLOR: {
// Valid.
@@ -3459,7 +3459,7 @@ void AnimationTrackEditor::_insert_delay(bool p_create_reset, bool p_create_bezi
insert_queue = false;
}
-void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Transform &p_xform) {
+void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform) {
if (!keying) {
return;
}
@@ -3479,7 +3479,7 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
int track_idx = -1;
for (int i = 0; i < animation->get_track_count(); i++) {
- if (animation->track_get_type(i) != Animation::TYPE_TRANSFORM) {
+ if (animation->track_get_type(i) != Animation::TYPE_TRANSFORM3D) {
continue;
}
if (animation->track_get_path(i) != np) {
@@ -3496,7 +3496,7 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
id.path = np;
id.track_idx = track_idx;
id.value = p_xform;
- id.type = Animation::TYPE_TRANSFORM;
+ id.type = Animation::TYPE_TRANSFORM3D;
id.query = "node '" + p_node->get_name() + "'";
id.advance = false;
@@ -3845,7 +3845,7 @@ static Vector<String> _get_bezier_subindices_for_type(Variant::Type p_type, bool
subindices.push_back(":y");
subindices.push_back(":z");
} break;
- case Variant::QUAT: {
+ case Variant::QUATERNION: {
subindices.push_back(":x");
subindices.push_back(":y");
subindices.push_back(":z");
@@ -3911,11 +3911,11 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
h.type == Variant::RECT2 ||
h.type == Variant::VECTOR3 ||
h.type == Variant::AABB ||
- h.type == Variant::QUAT ||
+ h.type == Variant::QUATERNION ||
h.type == Variant::COLOR ||
h.type == Variant::PLANE ||
h.type == Variant::TRANSFORM2D ||
- h.type == Variant::TRANSFORM) {
+ h.type == Variant::TRANSFORM3D) {
update_mode = Animation::UPDATE_CONTINUOUS;
}
@@ -3945,12 +3945,12 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
value = p_id.value;
} break;
- case Animation::TYPE_TRANSFORM: {
- Transform tr = p_id.value;
+ case Animation::TYPE_TRANSFORM3D: {
+ Transform3D tr = p_id.value;
Dictionary d;
d["location"] = tr.origin;
d["scale"] = tr.basis.get_scale();
- d["rotation"] = Quat(tr.basis);
+ d["rotation"] = Quaternion(tr.basis);
value = d;
} break;
case Animation::TYPE_BEZIER: {
@@ -4028,7 +4028,7 @@ bool AnimationTrackEditor::is_selection_active() const {
}
bool AnimationTrackEditor::is_snap_enabled() const {
- return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CTRL);
}
void AnimationTrackEditor::_update_tracks() {
@@ -4368,8 +4368,8 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
ERR_FAIL_COND(!node);
NodePath path_to = root->get_path_to(node);
- if (adding_track_type == Animation::TYPE_TRANSFORM && !node->is_class("Node3D")) {
- EditorNode::get_singleton()->show_warning(TTR("Transform tracks only apply to 3D-based nodes."));
+ if (adding_track_type == Animation::TYPE_TRANSFORM3D && !node->is_class("Node3D")) {
+ EditorNode::get_singleton()->show_warning(TTR("Transform3D tracks only apply to 3D-based nodes."));
return;
}
@@ -4379,7 +4379,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
prop_selector->set_type_filter(Vector<Variant::Type>());
prop_selector->select_property_from_instance(node);
} break;
- case Animation::TYPE_TRANSFORM:
+ case Animation::TYPE_TRANSFORM3D:
case Animation::TYPE_METHOD: {
undo_redo->create_action(TTR("Add Track"));
undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
@@ -4394,7 +4394,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
filter.push_back(Variant::FLOAT);
filter.push_back(Variant::VECTOR2);
filter.push_back(Variant::VECTOR3);
- filter.push_back(Variant::QUAT);
+ filter.push_back(Variant::QUATERNION);
filter.push_back(Variant::PLANE);
filter.push_back(Variant::COLOR);
@@ -4464,11 +4464,11 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
h.type == Variant::RECT2 ||
h.type == Variant::VECTOR3 ||
h.type == Variant::AABB ||
- h.type == Variant::QUAT ||
+ h.type == Variant::QUATERNION ||
h.type == Variant::COLOR ||
h.type == Variant::PLANE ||
h.type == Variant::TRANSFORM2D ||
- h.type == Variant::TRANSFORM) {
+ h.type == Variant::TRANSFORM3D) {
update_mode = Animation::UPDATE_CONTINUOUS;
}
@@ -4548,7 +4548,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
}
switch (animation->track_get_type(p_track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
if (!root->has_node(animation->track_get_path(p_track))) {
EditorNode::get_singleton()->show_warning(TTR("Track path is invalid, so can't add a key."));
return;
@@ -4560,11 +4560,11 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
return;
}
- Transform xf = base->get_transform();
+ Transform3D xf = base->get_transform();
Vector3 loc = xf.get_origin();
Vector3 scale = xf.basis.get_scale_local();
- Quat rot = xf.basis;
+ Quaternion rot = xf.basis;
undo_redo->create_action(TTR("Add Transform Track Key"));
undo_redo->add_do_method(animation.ptr(), "transform_track_insert_key", p_track, p_ofs, loc, rot, scale);
@@ -4959,12 +4959,12 @@ void AnimationTrackEditor::_box_selection_draw() {
void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
scroll->accept_event();
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
scroll->accept_event();
}
@@ -4980,7 +4980,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
for (int i = 0; i < track_edits.size(); i++) {
Rect2 local_rect = box_select_rect;
local_rect.position -= track_edits[i]->get_global_position();
- track_edits[i]->append_to_selection(local_rect, mb->get_command());
+ track_edits[i]->append_to_selection(local_rect, mb->is_command_pressed());
}
if (_get_track_selected() == -1 && track_edits.size() > 0) { //minimal hack to make shortcuts work
@@ -5010,7 +5010,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
}
if (!box_selection->is_visible_in_tree()) {
- if (!mm->get_command() && !mm->get_shift()) {
+ if (!mm->is_command_pressed() && !mm->is_shift_pressed()) {
_clear_selection();
}
box_selection->show();
@@ -5182,7 +5182,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
switch (animation->track_get_type(i)) {
- case Animation::TYPE_TRANSFORM:
+ case Animation::TYPE_TRANSFORM3D:
text += " (Transform)";
break;
case Animation::TYPE_METHOD:
@@ -5216,7 +5216,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
track_clipboard.clear();
TreeItem *root = track_copy_select->get_root();
if (root) {
- TreeItem *it = root->get_children();
+ TreeItem *it = root->get_first_child();
while (it) {
Dictionary md = it->get_metadata(0);
int idx = md["track_idx"];
@@ -5602,7 +5602,7 @@ void AnimationTrackEditor::_show_imported_anim_warning() {
}
void AnimationTrackEditor::_select_all_tracks_for_copy() {
- TreeItem *track = track_copy_select->get_root()->get_children();
+ TreeItem *track = track_copy_select->get_root()->get_first_child();
if (!track) {
return;
}
@@ -5616,7 +5616,7 @@ void AnimationTrackEditor::_select_all_tracks_for_copy() {
track = track->get_next();
}
- track = track_copy_select->get_root()->get_children();
+ track = track_copy_select->get_root()->get_first_child();
while (track) {
track->set_checked(0, !all_selected);
track = track->get_next();
@@ -5681,7 +5681,7 @@ void AnimationTrackEditor::_pick_track_select_recursive(TreeItem *p_item, const
p_select_candidates.push_back(node);
}
- TreeItem *c = p_item->get_children();
+ TreeItem *c = p_item->get_first_child();
while (c) {
_pick_track_select_recursive(c, p_filter, p_select_candidates);
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index c25865effb..f1d8139511 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -236,8 +236,8 @@ public:
AnimationTrackEdit();
};
-class AnimationTrackEditPlugin : public Reference {
- GDCLASS(AnimationTrackEditPlugin, Reference);
+class AnimationTrackEditPlugin : public RefCounted {
+ GDCLASS(AnimationTrackEditPlugin, RefCounted);
public:
virtual AnimationTrackEdit *create_value_track_edit(Object *p_object, Variant::Type p_type, const String &p_property, PropertyHint p_hint, const String &p_hint_string, int p_usage);
@@ -328,7 +328,7 @@ class AnimationTrackEditor : public VBoxContainer {
void _update_tracks();
void _name_limit_changed();
- void _timeline_changed(float p_new_pos, bool p_drag);
+ void _timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only = false);
void _track_remove_request(int p_track);
void _track_grab_focus(int p_track);
@@ -526,7 +526,7 @@ public:
void set_anim_pos(float p_pos);
void insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists = false);
void insert_value_key(const String &p_property, const Variant &p_value, bool p_advance);
- void insert_transform_key(Node3D *p_node, const String &p_sub, const Transform &p_xform);
+ void insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform);
void show_select_node_warning(bool p_show);
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index ae79299331..54c1e89d1e 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -1091,7 +1091,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) {
if (len_resizing && mm.is_valid()) {
len_resizing_rel += mm->get_relative().x;
- len_resizing_start = mm->get_shift();
+ len_resizing_start = mm->is_shift_pressed();
update();
accept_event();
return;
@@ -1100,7 +1100,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && get_default_cursor_shape() == CURSOR_HSIZE) {
len_resizing = true;
- len_resizing_start = mb->get_shift();
+ len_resizing_start = mb->is_shift_pressed();
len_resizing_from_px = mb->get_position().x;
len_resizing_rel = 0;
update();
diff --git a/editor/array_property_edit.h b/editor/array_property_edit.h
index fa3dcbe038..d7e11936a3 100644
--- a/editor/array_property_edit.h
+++ b/editor/array_property_edit.h
@@ -33,8 +33,8 @@
#include "scene/main/node.h"
-class ArrayPropertyEdit : public Reference {
- GDCLASS(ArrayPropertyEdit, Reference);
+class ArrayPropertyEdit : public RefCounted {
+ GDCLASS(ArrayPropertyEdit, RefCounted);
int page;
ObjectID obj;
diff --git a/editor/audio_stream_preview.h b/editor/audio_stream_preview.h
index accc7275c0..61567598ed 100644
--- a/editor/audio_stream_preview.h
+++ b/editor/audio_stream_preview.h
@@ -36,8 +36,8 @@
#include "scene/main/node.h"
#include "servers/audio/audio_stream.h"
-class AudioStreamPreview : public Reference {
- GDCLASS(AudioStreamPreview, Reference);
+class AudioStreamPreview : public RefCounted {
+ GDCLASS(AudioStreamPreview, RefCounted);
friend class AudioStream;
Vector<uint8_t> preview;
float length;
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 1c62c3d3e1..7b96858ec7 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -302,7 +302,7 @@ void FindReplaceBar::_replace_all() {
matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor"));
matches_label->set_text(vformat(TTR("%d replaced."), rc));
- text_editor->call_deferred("connect", "text_changed", Callable(this, "_editor_text_changed"));
+ text_editor->call_deferred("connect", "text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
results_count = -1;
}
@@ -583,15 +583,29 @@ void FindReplaceBar::set_error(const String &p_label) {
emit_signal("error", p_label);
}
-void FindReplaceBar::set_text_edit(CodeEdit *p_text_edit) {
+void FindReplaceBar::set_text_edit(CodeTextEditor *p_text_editor) {
+ if (p_text_editor == base_text_editor) {
+ return;
+ }
+
+ if (base_text_editor) {
+ base_text_editor->remove_find_replace_bar();
+ base_text_editor = nullptr;
+ text_editor->disconnect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
+ text_editor = nullptr;
+ }
+
results_count = -1;
- text_editor = p_text_edit;
+ base_text_editor = p_text_editor;
+ text_editor = base_text_editor->get_text_editor();
text_editor->connect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
+
+ _update_results_count();
+ _update_matches_label();
}
void FindReplaceBar::_bind_methods() {
ClassDB::bind_method("_unhandled_input", &FindReplaceBar::_unhandled_input);
-
ClassDB::bind_method("_search_current", &FindReplaceBar::search_current);
ADD_SIGNAL(MethodInfo("search"));
@@ -726,7 +740,7 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_command()) {
+ if (mb->is_pressed() && mb->is_command_pressed()) {
if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
_zoom_in();
} else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
@@ -816,12 +830,12 @@ void CodeTextEditor::_code_complete_timer_timeout() {
if (!is_visible_in_tree()) {
return;
}
- text_editor->query_code_comple();
+ text_editor->request_code_completion();
}
void CodeTextEditor::_complete_request() {
List<ScriptCodeCompletionOption> entries;
- String ctext = text_editor->get_text_for_completion();
+ String ctext = text_editor->get_text_for_code_completion();
_code_complete_script(ctext, &entries);
bool forced = false;
if (code_complete_func) {
@@ -832,16 +846,17 @@ void CodeTextEditor::_complete_request() {
}
for (List<ScriptCodeCompletionOption>::Element *E = entries.front(); E; E = E->next()) {
- ScriptCodeCompletionOption *e = &E->get();
- e->icon = _get_completion_icon(*e);
- e->font_color = completion_font_color;
- if (e->insert_text.begins_with("\"") || e->insert_text.begins_with("\'")) {
- e->font_color = completion_string_color;
- } else if (e->insert_text.begins_with("#") || e->insert_text.begins_with("//")) {
- e->font_color = completion_comment_color;
+ ScriptCodeCompletionOption &e = E->get();
+
+ Color font_color = completion_font_color;
+ if (e.insert_text.begins_with("\"") || e.insert_text.begins_with("\'")) {
+ font_color = completion_string_color;
+ } else if (e.insert_text.begins_with("#") || e.insert_text.begins_with("//")) {
+ font_color = completion_comment_color;
}
+ text_editor->add_code_completion_option((CodeEdit::CodeCompletionKind)e.kind, e.display, e.insert_text, font_color, _get_completion_icon(e), e.default_value);
}
- text_editor->code_complete(entries, forced);
+ text_editor->update_code_completion_options(forced);
}
Ref<Texture2D> CodeTextEditor::_get_completion_icon(const ScriptCodeCompletionOption &p_option) {
@@ -938,6 +953,25 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
}
+void CodeTextEditor::set_find_replace_bar(FindReplaceBar *p_bar) {
+ if (find_replace_bar) {
+ return;
+ }
+
+ find_replace_bar = p_bar;
+ find_replace_bar->set_text_edit(this);
+ find_replace_bar->connect("error", callable_mp(error, &Label::set_text));
+}
+
+void CodeTextEditor::remove_find_replace_bar() {
+ if (!find_replace_bar) {
+ return;
+ }
+
+ find_replace_bar->disconnect("error", callable_mp(error, &Label::set_text));
+ find_replace_bar = nullptr;
+}
+
void CodeTextEditor::trim_trailing_whitespace() {
bool trimed_whitespace = false;
for (int i = 0; i < text_editor->get_line_count(); i++) {
@@ -1012,7 +1046,7 @@ void CodeTextEditor::convert_indent_to_spaces() {
if (cursor_line == i && cursor_column > j) {
cursor_column += indent_size - 1;
}
- line = line.left(j) + indent + line.right(j + 1);
+ line = line.left(j) + indent + line.substr(j + 1);
}
j++;
}
@@ -1056,7 +1090,7 @@ void CodeTextEditor::convert_indent_to_tabs() {
if (cursor_line == i && cursor_column > j) {
cursor_column -= indent_size;
}
- line = line.left(j - indent_size) + "\t" + line.right(j + 1);
+ line = line.left(j - indent_size) + "\t" + line.substr(j + 1);
j = 0;
space_count = -1;
}
@@ -1114,7 +1148,7 @@ void CodeTextEditor::convert_case(CaseStyle p_case) {
new_line = text_editor->get_line(i).left(begin_col) + new_line;
}
if (i == end) {
- new_line = new_line + text_editor->get_line(i).right(end_col);
+ new_line = new_line + text_editor->get_line(i).substr(end_col);
}
text_editor->set_line(i, new_line);
}
@@ -1474,6 +1508,34 @@ void CodeTextEditor::goto_error() {
}
}
+void CodeTextEditor::_update_text_editor_theme() {
+ text_editor->add_theme_color_override("background_color", EDITOR_GET("text_editor/highlighting/background_color"));
+ text_editor->add_theme_color_override("completion_background_color", EDITOR_GET("text_editor/highlighting/completion_background_color"));
+ text_editor->add_theme_color_override("completion_selected_color", EDITOR_GET("text_editor/highlighting/completion_selected_color"));
+ text_editor->add_theme_color_override("completion_existing_color", EDITOR_GET("text_editor/highlighting/completion_existing_color"));
+ text_editor->add_theme_color_override("completion_scroll_color", EDITOR_GET("text_editor/highlighting/completion_scroll_color"));
+ text_editor->add_theme_color_override("completion_font_color", EDITOR_GET("text_editor/highlighting/completion_font_color"));
+ text_editor->add_theme_color_override("font_color", EDITOR_GET("text_editor/highlighting/text_color"));
+ text_editor->add_theme_color_override("line_number_color", EDITOR_GET("text_editor/highlighting/line_number_color"));
+ text_editor->add_theme_color_override("caret_color", EDITOR_GET("text_editor/highlighting/caret_color"));
+ text_editor->add_theme_color_override("caret_background_color", EDITOR_GET("text_editor/highlighting/caret_background_color"));
+ text_editor->add_theme_color_override("font_selected_color", EDITOR_GET("text_editor/highlighting/text_selected_color"));
+ text_editor->add_theme_color_override("selection_color", EDITOR_GET("text_editor/highlighting/selection_color"));
+ text_editor->add_theme_color_override("brace_mismatch_color", EDITOR_GET("text_editor/highlighting/brace_mismatch_color"));
+ text_editor->add_theme_color_override("current_line_color", EDITOR_GET("text_editor/highlighting/current_line_color"));
+ text_editor->add_theme_color_override("line_length_guideline_color", EDITOR_GET("text_editor/highlighting/line_length_guideline_color"));
+ text_editor->add_theme_color_override("word_highlighted_color", EDITOR_GET("text_editor/highlighting/word_highlighted_color"));
+ text_editor->add_theme_color_override("bookmark_color", EDITOR_GET("text_editor/highlighting/bookmark_color"));
+ text_editor->add_theme_color_override("breakpoint_color", EDITOR_GET("text_editor/highlighting/breakpoint_color"));
+ text_editor->add_theme_color_override("executing_line_color", EDITOR_GET("text_editor/highlighting/executing_line_color"));
+ text_editor->add_theme_color_override("code_folding_color", EDITOR_GET("text_editor/highlighting/code_folding_color"));
+ text_editor->add_theme_color_override("search_result_color", EDITOR_GET("text_editor/highlighting/search_result_color"));
+ text_editor->add_theme_color_override("search_result_border_color", EDITOR_GET("text_editor/highlighting/search_result_border_color"));
+ text_editor->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
+ emit_signal("load_theme_settings");
+ _load_theme_settings();
+}
+
void CodeTextEditor::_update_font() {
text_editor->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
text_editor->add_theme_font_size_override("font_size", get_theme_font_size("source_size", "EditorFonts"));
@@ -1497,6 +1559,7 @@ void CodeTextEditor::_update_font() {
}
void CodeTextEditor::_on_settings_change() {
+ _update_text_editor_theme();
_update_font();
font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size");
@@ -1534,9 +1597,7 @@ void CodeTextEditor::_on_settings_change() {
EDITOR_GET("text_editor/completion/code_complete_delay"));
// Call hint settings.
- text_editor->set_callhint_settings(
- EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"),
- EDITOR_GET("text_editor/completion/callhint_tooltip_offset"));
+ text_editor->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
idle->set_wait_time(EDITOR_GET("text_editor/completion/idle_parse_delay"));
}
@@ -1583,14 +1644,11 @@ void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) {
void CodeTextEditor::_notification(int p_what) {
switch (p_what) {
- case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- _load_theme_settings();
- emit_signal("load_theme_settings");
- } break;
case NOTIFICATION_THEME_CHANGED: {
if (toggle_scripts_button->is_visible()) {
update_toggle_scripts_button();
}
+ _update_text_editor_theme();
_update_font();
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -1735,14 +1793,6 @@ CodeTextEditor::CodeTextEditor() {
} break;
}
- // Added second so it opens at the bottom, so it won't shift the entire text editor when opening.
- find_replace_bar = memnew(FindReplaceBar);
- add_child(find_replace_bar);
- find_replace_bar->set_h_size_flags(SIZE_EXPAND_FILL);
- find_replace_bar->hide();
-
- find_replace_bar->set_text_edit(text_editor);
-
text_editor->set_draw_line_numbers(true);
text_editor->set_brace_matching(true);
text_editor->set_auto_indent(true);
@@ -1783,7 +1833,6 @@ CodeTextEditor::CodeTextEditor() {
error->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
error->set_mouse_filter(MOUSE_FILTER_STOP);
error->connect("gui_input", callable_mp(this, &CodeTextEditor::_error_pressed));
- find_replace_bar->connect("error", callable_mp(error, &Label::set_text));
// Warnings
warning_button = memnew(Button);
@@ -1821,15 +1870,17 @@ CodeTextEditor::CodeTextEditor() {
text_editor->connect("gui_input", callable_mp(this, &CodeTextEditor::_text_editor_gui_input));
text_editor->connect("cursor_changed", callable_mp(this, &CodeTextEditor::_line_col_changed));
text_editor->connect("text_changed", callable_mp(this, &CodeTextEditor::_text_changed));
- text_editor->connect("request_completion", callable_mp(this, &CodeTextEditor::_complete_request));
- Vector<String> cs;
+ text_editor->connect("request_code_completion", callable_mp(this, &CodeTextEditor::_complete_request));
+ TypedArray<String> cs;
cs.push_back(".");
cs.push_back(",");
cs.push_back("(");
cs.push_back("=");
cs.push_back("$");
cs.push_back("@");
- text_editor->set_completion(true, cs);
+ cs.push_back("\"");
+ cs.push_back("\'");
+ text_editor->set_code_completion_prefixes(cs);
idle->connect("timeout", callable_mp(this, &CodeTextEditor::_text_changed_idle_timeout));
code_complete_timer->connect("timeout", callable_mp(this, &CodeTextEditor::_code_complete_timer_timeout));
diff --git a/editor/code_editor.h b/editor/code_editor.h
index e201da446e..9fc659b611 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -57,6 +57,8 @@ public:
GotoLineDialog();
};
+class CodeTextEditor;
+
class FindReplaceBar : public HBoxContainer {
GDCLASS(FindReplaceBar, HBoxContainer);
@@ -77,6 +79,7 @@ class FindReplaceBar : public HBoxContainer {
HBoxContainer *hbc_button_replace;
HBoxContainer *hbc_option_replace;
+ CodeTextEditor *base_text_editor = nullptr;
CodeEdit *text_editor;
int result_line;
@@ -120,7 +123,7 @@ public:
bool is_selection_only() const;
void set_error(const String &p_label);
- void set_text_edit(CodeEdit *p_text_edit);
+ void set_text_edit(CodeTextEditor *p_text_editor);
void popup_search(bool p_show_only = false);
void popup_replace();
@@ -138,7 +141,7 @@ class CodeTextEditor : public VBoxContainer {
GDCLASS(CodeTextEditor, VBoxContainer);
CodeEdit *text_editor;
- FindReplaceBar *find_replace_bar;
+ FindReplaceBar *find_replace_bar = nullptr;
HBoxContainer *status_bar;
Button *toggle_scripts_button;
@@ -161,6 +164,7 @@ class CodeTextEditor : public VBoxContainer {
void _on_settings_change();
+ void _update_text_editor_theme();
void _update_font();
void _complete_request();
Ref<Texture2D> _get_completion_icon(const ScriptCodeCompletionOption &p_option);
@@ -242,6 +246,8 @@ public:
void update_line_and_column() { _line_col_changed(); }
CodeEdit *get_text_editor() { return text_editor; }
FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
+ void set_find_replace_bar(FindReplaceBar *p_bar);
+ void remove_find_replace_bar();
virtual void apply_code() {}
void goto_error();
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 0c1fb6fe4d..a17b1aec10 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -66,8 +66,8 @@ public:
bool _set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
- if (name.begins_with("bind/")) {
- int which = name.get_slice("/", 1).to_int() - 1;
+ if (name.begins_with("bind/argument_")) {
+ int which = name.get_slice("_", 1).to_int() - 1;
ERR_FAIL_INDEX_V(which, params.size(), false);
params.write[which] = p_value;
} else {
@@ -80,8 +80,8 @@ public:
bool _get(const StringName &p_name, Variant &r_ret) const {
String name = p_name;
- if (name.begins_with("bind/")) {
- int which = name.get_slice("/", 1).to_int() - 1;
+ if (name.begins_with("bind/argument_")) {
+ int which = name.get_slice("_", 1).to_int() - 1;
ERR_FAIL_INDEX_V(which, params.size(), false);
r_ret = params[which];
} else {
@@ -93,7 +93,7 @@ public:
void _get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < params.size(); i++) {
- p_list->push_back(PropertyInfo(params[i].get_type(), "bind/" + itos(i + 1)));
+ p_list->push_back(PropertyInfo(params[i].get_type(), "bind/argument_" + itos(i + 1)));
}
}
@@ -203,8 +203,8 @@ void ConnectDialog::_add_bind() {
case Variant::PLANE:
value = Plane();
break;
- case Variant::QUAT:
- value = Quat();
+ case Variant::QUATERNION:
+ value = Quaternion();
break;
case Variant::AABB:
value = AABB();
@@ -212,8 +212,8 @@ void ConnectDialog::_add_bind() {
case Variant::BASIS:
value = Basis();
break;
- case Variant::TRANSFORM:
- value = Transform();
+ case Variant::TRANSFORM3D:
+ value = Transform3D();
break;
case Variant::COLOR:
value = Color();
@@ -443,10 +443,10 @@ ConnectDialog::ConnectDialog() {
type_list->add_item("Rect2", Variant::RECT2);
type_list->add_item("Vector3", Variant::VECTOR3);
type_list->add_item("Plane", Variant::PLANE);
- type_list->add_item("Quat", Variant::QUAT);
+ type_list->add_item("Quaternion", Variant::QUATERNION);
type_list->add_item("AABB", Variant::AABB);
type_list->add_item("Basis", Variant::BASIS);
- type_list->add_item("Transform", Variant::TRANSFORM);
+ type_list->add_item("Transform3D", Variant::TRANSFORM3D);
type_list->add_item("Color", Variant::COLOR);
type_list->select(0);
@@ -655,7 +655,7 @@ void ConnectionsDock::_disconnect_all() {
return;
}
- TreeItem *child = item->get_children();
+ TreeItem *child = item->get_first_child();
String signalName = item->get_metadata(0).operator Dictionary()["name"];
undo_redo->create_action(vformat(TTR("Disconnect all from signal: '%s'"), signalName));
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 1c0a55e4ec..968b24893c 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -643,9 +643,9 @@ void CreateDialog::_load_favorites_and_history() {
void CreateDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_save_and_update_favorite_list"), &CreateDialog::_save_and_update_favorite_list);
- ClassDB::bind_method("get_drag_data_fw", &CreateDialog::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw", &CreateDialog::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw", &CreateDialog::drop_data_fw);
+ ClassDB::bind_method("_get_drag_data_fw", &CreateDialog::get_drag_data_fw);
+ ClassDB::bind_method("_can_drop_data_fw", &CreateDialog::can_drop_data_fw);
+ ClassDB::bind_method("_drop_data_fw", &CreateDialog::drop_data_fw);
ADD_SIGNAL(MethodInfo("create"));
ADD_SIGNAL(MethodInfo("favorites_updated"));
diff --git a/editor/debugger/editor_debugger_server.h b/editor/debugger/editor_debugger_server.h
index 6458421e7a..6216d0df3d 100644
--- a/editor/debugger/editor_debugger_server.h
+++ b/editor/debugger/editor_debugger_server.h
@@ -32,9 +32,9 @@
#define EDITOR_DEBUGGER_CONNECTION_H
#include "core/debugger/remote_debugger_peer.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class EditorDebuggerServer : public Reference {
+class EditorDebuggerServer : public RefCounted {
public:
typedef EditorDebuggerServer *(*CreateServerFunc)(const String &p_uri);
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 6befee090b..d60e2783ec 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -508,23 +508,35 @@ Vector<Vector<String>> EditorProfiler::get_data_as_csv() const {
return res;
}
- // signatures
- Vector<String> signatures;
- const Vector<EditorProfiler::Metric::Category> &categories = frame_metrics[0].categories;
-
- for (int j = 0; j < categories.size(); j++) {
- const EditorProfiler::Metric::Category &c = categories[j];
- signatures.push_back(c.signature);
-
- for (int k = 0; k < c.items.size(); k++) {
- signatures.push_back(c.items[k].signature);
+ // Different metrics may contain different number of categories.
+ Set<StringName> possible_signatures;
+ for (int i = 0; i < frame_metrics.size(); i++) {
+ const Metric &m = frame_metrics[i];
+ if (!m.valid) {
+ continue;
+ }
+ for (Map<StringName, Metric::Category *>::Element *E = m.category_ptrs.front(); E; E = E->next()) {
+ possible_signatures.insert(E->key());
+ }
+ for (Map<StringName, Metric::Category::Item *>::Element *E = m.item_ptrs.front(); E; E = E->next()) {
+ possible_signatures.insert(E->key());
}
}
+
+ // Generate CSV header and cache indices.
+ Map<StringName, int> sig_map;
+ Vector<String> signatures;
+ signatures.resize(possible_signatures.size());
+ int sig_index = 0;
+ for (const Set<StringName>::Element *E = possible_signatures.front(); E; E = E->next()) {
+ signatures.write[sig_index] = E->get();
+ sig_map[E->get()] = sig_index;
+ sig_index++;
+ }
res.push_back(signatures);
// values
Vector<String> values;
- values.resize(signatures.size());
int index = last_metric;
@@ -535,20 +547,23 @@ Vector<Vector<String>> EditorProfiler::get_data_as_csv() const {
index = 0;
}
- if (!frame_metrics[index].valid) {
+ const Metric &m = frame_metrics[index];
+
+ if (!m.valid) {
continue;
}
- int it = 0;
- const Vector<EditorProfiler::Metric::Category> &frame_cat = frame_metrics[index].categories;
- for (int j = 0; j < frame_cat.size(); j++) {
- const EditorProfiler::Metric::Category &c = frame_cat[j];
- values.write[it++] = String::num_real(c.total_time);
+ // Don't keep old values since there may be empty cells.
+ values.clear();
+ values.resize(possible_signatures.size());
- for (int k = 0; k < c.items.size(); k++) {
- values.write[it++] = String::num_real(c.items[k].total);
- }
+ for (Map<StringName, Metric::Category *>::Element *E = m.category_ptrs.front(); E; E = E->next()) {
+ values.write[sig_map[E->key()]] = String::num_real(E->value()->total_time);
+ }
+ for (Map<StringName, Metric::Category::Item *>::Element *E = m.item_ptrs.front(); E; E = E->next()) {
+ values.write[sig_map[E->key()]] = String::num_real(E->value()->total);
}
+
res.push_back(values);
}
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 1d95161e6c..7493cc2a8d 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -220,7 +220,7 @@ void ScriptEditorDebugger::_file_selected(const String &p_file) {
file->store_csv_line(headers);
if (vmem_tree->get_root()) {
- TreeItem *ti = vmem_tree->get_root()->get_children();
+ TreeItem *ti = vmem_tree->get_root()->get_first_child();
while (ti) {
Vector<String> values;
values.resize(vmem_tree->get_columns());
@@ -1319,7 +1319,7 @@ bool ScriptEditorDebugger::is_skip_breakpoints() {
void ScriptEditorDebugger::_error_activated() {
TreeItem *selected = error_tree->get_selected();
- TreeItem *ci = selected->get_children();
+ TreeItem *ci = selected->get_first_child();
if (ci) {
selected->set_collapsed(!selected->is_collapsed());
}
@@ -1341,7 +1341,7 @@ void ScriptEditorDebugger::_expand_errors_list() {
return;
}
- TreeItem *item = root->get_children();
+ TreeItem *item = root->get_first_child();
while (item) {
item->set_collapsed(false);
item = item->get_next();
@@ -1354,7 +1354,7 @@ void ScriptEditorDebugger::_collapse_errors_list() {
return;
}
- TreeItem *item = root->get_children();
+ TreeItem *item = root->get_first_child();
while (item) {
item->set_collapsed(true);
item = item->get_next();
@@ -1403,7 +1403,7 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) {
int rpad_len = text.length();
text = type + text + ti->get_text(1) + "\n";
- TreeItem *ci = ti->get_children();
+ TreeItem *ci = ti->get_first_child();
while (ci) {
text += " " + ci->get_text(0).rpad(rpad_len) + ci->get_text(1) + "\n";
ci = ci->get_next();
@@ -1419,7 +1419,7 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) {
}
// We only need the first child here (C++ source stack trace).
- TreeItem *ci = ti->get_children();
+ TreeItem *ci = ti->get_first_child();
// Parse back the `file:line @ method()` string.
const Vector<String> file_line_number = ci->get_text(1).split("@")[0].strip_edges().split(":");
ERR_FAIL_COND_MSG(file_line_number.size() < 2, "Incorrect C++ source stack trace file:line format (please report).");
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 57d44ca56c..7534b419fe 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -30,8 +30,8 @@
#include "dependency_editor.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
-#include "core/os/file_access.h"
#include "editor_node.h"
#include "editor_scale.h"
#include "scene/gui/margin_container.h"
@@ -725,8 +725,8 @@ void OrphanResourcesDialog::_find_to_delete(TreeItem *p_item, List<String> &path
paths.push_back(p_item->get_metadata(0));
}
- if (p_item->get_children()) {
- _find_to_delete(p_item->get_children(), paths);
+ if (p_item->get_first_child()) {
+ _find_to_delete(p_item->get_first_child(), paths);
}
p_item = p_item->get_next();
diff --git a/editor/dictionary_property_edit.h b/editor/dictionary_property_edit.h
index e0fd945491..d1401c5e5f 100644
--- a/editor/dictionary_property_edit.h
+++ b/editor/dictionary_property_edit.h
@@ -33,8 +33,8 @@
#include "scene/main/node.h"
-class DictionaryPropertyEdit : public Reference {
- GDCLASS(DictionaryPropertyEdit, Reference);
+class DictionaryPropertyEdit : public RefCounted {
+ GDCLASS(DictionaryPropertyEdit, RefCounted);
ObjectID obj;
StringName property;
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index e29c9593c3..d3df4d91a6 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -34,9 +34,9 @@
#include "core/config/project_settings.h"
#include "core/core_constants.h"
#include "core/io/compression.h"
+#include "core/io/dir_access.h"
#include "core/io/marshalls.h"
#include "core/object/script_language.h"
-#include "core/os/dir_access.h"
#include "core/version.h"
#include "scene/resources/theme.h"
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index 7527514dca..b8504ad02a 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -141,7 +141,7 @@ EditorAbout::EditorAbout() {
version_btn = memnew(LinkButton);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
- hash = "." + hash.left(9);
+ hash = " " + vformat("[%s]", hash.left(9));
}
version_btn->set_text(VERSION_FULL_NAME + hash);
// Set the text to copy in metadata as it slightly differs from the button's text.
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 2d29076476..38f417a8ce 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -30,9 +30,9 @@
#include "editor_asset_installer.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/zip_io.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "editor_node.h"
#include "progress_dialog.h"
@@ -45,8 +45,8 @@ void EditorAssetInstaller::_update_subitems(TreeItem *p_item, bool p_check, bool
p_item->set_checked(0, false);
}
- if (p_item->get_children()) {
- _update_subitems(p_item->get_children(), p_check);
+ if (p_item->get_first_child()) {
+ _update_subitems(p_item->get_first_child(), p_check);
}
if (!p_first && p_item->get_next()) {
@@ -60,7 +60,7 @@ void EditorAssetInstaller::_uncheck_parent(TreeItem *p_item) {
}
bool any_checked = false;
- TreeItem *item = p_item->get_children();
+ TreeItem *item = p_item->get_first_child();
while (item) {
if (item->is_checked(0)) {
any_checked = true;
@@ -137,7 +137,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
extension_guess["atlastex"] = tree->get_theme_icon("AtlasTexture", "EditorIcons");
extension_guess["scn"] = tree->get_theme_icon("PackedScene", "EditorIcons");
extension_guess["tscn"] = tree->get_theme_icon("PackedScene", "EditorIcons");
- extension_guess["shader"] = tree->get_theme_icon("Shader", "EditorIcons");
+ extension_guess["gdshader"] = tree->get_theme_icon("Shader", "EditorIcons");
extension_guess["gd"] = tree->get_theme_icon("GDScript", "EditorIcons");
extension_guess["vs"] = tree->get_theme_icon("VisualScript", "EditorIcons");
}
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index e7934bed0a..13296e2f23 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -173,6 +173,9 @@ void EditorAudioBus::_notification(int p_what) {
bypass->set_icon(get_theme_icon("AudioBusBypass", "EditorIcons"));
bus_options->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
+
+ audio_value_preview_box->add_theme_color_override("font_color", get_theme_color("font_color", "TooltipLabel"));
+ audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel"));
} break;
case NOTIFICATION_MOUSE_EXIT:
case NOTIFICATION_DRAG_END: {
@@ -312,7 +315,7 @@ void EditorAudioBus::_volume_changed(float p_normalized) {
const float p_db = this->_normalized_volume_to_scaled_db(p_normalized);
- if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
// Snap the value when holding Ctrl for easier editing.
// To do so, it needs to be converted back to normalized volume (as the slider uses that unit).
slider->set_value(_scaled_db_to_normalized_volume(Math::round(p_db)));
@@ -372,22 +375,31 @@ float EditorAudioBus::_scaled_db_to_normalized_volume(float db) {
void EditorAudioBus::_show_value(float slider_value) {
float db;
- if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
// Display the correct (snapped) value when holding Ctrl
db = Math::round(_normalized_volume_to_scaled_db(slider_value));
} else {
db = _normalized_volume_to_scaled_db(slider_value);
}
- String text = vformat("%10.1f dB", db);
+ String text;
+ if (Math::is_zero_approx(Math::snapped(db, 0.1))) {
+ // Prevent displaying `-0.0 dB` and show ` 0.0 dB` instead.
+ // The leading space makes the text visually line up with its positive/negative counterparts.
+ text = " 0.0 dB";
+ } else {
+ // Show an explicit `+` sign if positive.
+ text = vformat("%+.1f dB", db);
+ }
+ // Also set the preview text as a standard Control tooltip.
+ // This way, it can be seen when the slider is merely hovered (instead of dragged).
slider->set_tooltip(text);
audio_value_preview_label->set_text(text);
- Vector2 slider_size = slider->get_size();
- Vector2 slider_position = slider->get_global_position();
- float left_padding = 5.0f;
- float vert_padding = 10.0f;
- Vector2 box_position = Vector2(slider_size.x + left_padding, (slider_size.y - vert_padding) * (1.0f - slider->get_value()) - vert_padding);
+ const Vector2 slider_size = slider->get_size();
+ const Vector2 slider_position = slider->get_global_position();
+ const float vert_padding = 10.0f;
+ const Vector2 box_position = Vector2(slider_size.x, (slider_size.y - vert_padding) * (1.0f - slider->get_value()) - vert_padding);
audio_value_preview_box->set_position(slider_position + box_position);
audio_value_preview_box->set_size(audio_value_preview_label->get_size());
if (slider->has_focus() && !audio_value_preview_box->is_visible()) {
@@ -745,9 +757,9 @@ void EditorAudioBus::_bind_methods() {
ClassDB::bind_method("update_bus", &EditorAudioBus::update_bus);
ClassDB::bind_method("update_send", &EditorAudioBus::update_send);
ClassDB::bind_method("_gui_input", &EditorAudioBus::_gui_input);
- ClassDB::bind_method("get_drag_data_fw", &EditorAudioBus::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw", &EditorAudioBus::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw", &EditorAudioBus::drop_data_fw);
+ ClassDB::bind_method("_get_drag_data_fw", &EditorAudioBus::get_drag_data_fw);
+ ClassDB::bind_method("_can_drop_data_fw", &EditorAudioBus::can_drop_data_fw);
+ ClassDB::bind_method("_drop_data_fw", &EditorAudioBus::drop_data_fw);
ADD_SIGNAL(MethodInfo("duplicate_request"));
ADD_SIGNAL(MethodInfo("delete_request"));
@@ -830,14 +842,13 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
audio_value_preview_label->set_v_size_flags(SIZE_EXPAND_FILL);
audio_value_preview_label->set_h_size_flags(SIZE_EXPAND_FILL);
audio_value_preview_label->set_mouse_filter(MOUSE_FILTER_PASS);
+ audio_value_preview_box->add_theme_color_override("font_color", get_theme_color("font_color", "TooltipLabel"));
audioprev_hbc->add_child(audio_value_preview_label);
slider->add_child(audio_value_preview_box);
audio_value_preview_box->set_as_top_level(true);
- Ref<StyleBoxFlat> panel_style = memnew(StyleBoxFlat);
- panel_style->set_bg_color(Color(0.0f, 0.0f, 0.0f, 0.8f));
- audio_value_preview_box->add_theme_style_override("panel", panel_style);
+ audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel"));
audio_value_preview_box->set_mouse_filter(MOUSE_FILTER_PASS);
audio_value_preview_box->hide();
@@ -925,7 +936,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
bus_options->set_shortcut_context(this);
bus_options->set_h_size_flags(SIZE_SHRINK_END);
bus_options->set_anchor(SIDE_RIGHT, 0.0);
- bus_options->set_tooltip(TTR("Bus options"));
+ bus_options->set_tooltip(TTR("Bus Options"));
hbc->add_child(bus_options);
bus_popup = bus_options->get_popup();
@@ -1400,7 +1411,7 @@ void EditorAudioMeterNotches::_bind_methods() {
void EditorAudioMeterNotches::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- notch_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(0, 0, 0);
+ notch_color = get_theme_color("font_color", "Editor");
} break;
case NOTIFICATION_DRAW: {
_draw_audio_notches();
@@ -1416,13 +1427,13 @@ void EditorAudioMeterNotches::_draw_audio_notches() {
for (int i = 0; i < notches.size(); i++) {
AudioNotch n = notches[i];
draw_line(Vector2(0, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
- Vector2(line_length, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
+ Vector2(line_length * EDSCALE, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
notch_color,
- 1);
+ Math::round(EDSCALE));
if (n.render_db_value) {
draw_string(font,
- Vector2(line_length + label_space,
+ Vector2((line_length + label_space) * EDSCALE,
(1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + (font_height / 4) + top_padding),
String::num(Math::abs(n.db_value)) + "dB",
HALIGN_LEFT, -1, font_size,
@@ -1432,5 +1443,5 @@ void EditorAudioMeterNotches::_draw_audio_notches() {
}
EditorAudioMeterNotches::EditorAudioMeterNotches() {
- notch_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(0, 0, 0);
+ notch_color = get_theme_color("font_color", "Editor");
}
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
index 8dfc2137ef..0fbda8ece9 100644
--- a/editor/editor_audio_buses.h
+++ b/editor/editor_audio_buses.h
@@ -243,10 +243,10 @@ private:
List<AudioNotch> notches;
public:
- float line_length = 5.0f;
- float label_space = 2.0f;
- float btm_padding = 9.0f;
- float top_padding = 5.0f;
+ const float line_length = 5.0f;
+ const float label_space = 2.0f;
+ const float btm_padding = 9.0f;
+ const float top_padding = 5.0f;
Color notch_color;
void add_notch(float p_normalized_offset, float p_db_value, bool p_render_value = false);
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index d46df05f6e..a39e693912 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -749,9 +749,9 @@ void EditorAutoloadSettings::autoload_remove(const String &p_name) {
void EditorAutoloadSettings::_bind_methods() {
ClassDB::bind_method("_autoload_open", &EditorAutoloadSettings::_autoload_open);
- ClassDB::bind_method("get_drag_data_fw", &EditorAutoloadSettings::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw", &EditorAutoloadSettings::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw", &EditorAutoloadSettings::drop_data_fw);
+ ClassDB::bind_method("_get_drag_data_fw", &EditorAutoloadSettings::get_drag_data_fw);
+ ClassDB::bind_method("_can_drop_data_fw", &EditorAutoloadSettings::can_drop_data_fw);
+ ClassDB::bind_method("_drop_data_fw", &EditorAutoloadSettings::drop_data_fw);
ClassDB::bind_method("update_autoload", &EditorAutoloadSettings::update_autoload);
ClassDB::bind_method("autoload_add", &EditorAutoloadSettings::autoload_add);
diff --git a/editor/editor_builders.py b/editor/editor_builders.py
index 86c5c87a68..ff0daa86ff 100644
--- a/editor/editor_builders.py
+++ b/editor/editor_builders.py
@@ -53,7 +53,7 @@ def make_fonts_header(target, source, env):
g.write("#ifndef _EDITOR_FONTS_H\n")
g.write("#define _EDITOR_FONTS_H\n")
- # saving uncompressed, since freetype will reference from memory pointer
+ # Saving uncompressed, since FreeType will reference from memory pointer.
for i in range(len(source)):
with open(source[i], "rb") as f:
buf = f.read()
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 6405af3876..56c6a416af 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -31,9 +31,9 @@
#include "editor_data.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "editor_node.h"
#include "editor_settings.h"
#include "scene/resources/packed_scene.h"
@@ -83,7 +83,7 @@ void EditorHistory::cleanup_history() {
void EditorHistory::_add_object(ObjectID p_object, const String &p_property, int p_level_change, bool p_inspector_only) {
Object *obj = ObjectDB::get_instance(p_object);
ERR_FAIL_COND(!obj);
- Reference *r = Object::cast_to<Reference>(obj);
+ RefCounted *r = Object::cast_to<RefCounted>(obj);
Obj o;
if (r) {
o.ref = REF(r);
diff --git a/editor/editor_data.h b/editor/editor_data.h
index 2ece94d6a3..df6ba9d0c9 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -167,7 +167,7 @@ public:
EditorPlugin *get_editor_plugin(int p_idx);
UndoRedo &get_undo_redo();
- void add_undo_redo_inspector_hook_callback(Callable p_callable); // Callbacks shoud have 4 args: (Object* undo_redo, Object *modified_object, String property, Varian new_value)
+ void add_undo_redo_inspector_hook_callback(Callable p_callable); // Callbacks should have 4 args: (Object* undo_redo, Object *modified_object, String property, Variant new_value)
void remove_undo_redo_inspector_hook_callback(Callable p_callable);
const Vector<Callable> get_undo_redo_inspector_hook_callback();
diff --git a/editor/editor_dir_dialog.h b/editor/editor_dir_dialog.h
index 05451b7bda..ef473b0779 100644
--- a/editor/editor_dir_dialog.h
+++ b/editor/editor_dir_dialog.h
@@ -31,7 +31,7 @@
#ifndef EDITOR_DIR_DIALOG_H
#define EDITOR_DIR_DIALOG_H
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "editor/editor_file_system.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/tree.h"
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index a368a9618e..7c5a06107d 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -33,14 +33,14 @@
#include "core/config/project_settings.h"
#include "core/crypto/crypto_core.h"
#include "core/io/config_file.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_encrypted.h"
#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/io/zip_io.h"
#include "core/object/script_language.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/version.h"
#include "editor/editor_file_system.h"
#include "editor/plugins/script_editor_plugin.h"
@@ -151,7 +151,7 @@ void EditorExportPreset::set_export_path(const String &p_path) {
export_path = p_path;
/* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path,
* this should be removed. */
- if (export_path.is_abs_path()) {
+ if (export_path.is_absolute_path()) {
String res_path = OS::get_singleton()->get_resource_dir();
export_path = res_path.path_to_file(export_path);
}
@@ -1065,7 +1065,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
}
} else {
// Use default text server data.
- String icu_data_file = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_icu_data");
+ String icu_data_file = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmp_icu_data");
TS->save_support_data(icu_data_file);
Vector<uint8_t> array = FileAccess::get_file_as_array(icu_data_file);
err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key);
@@ -1078,7 +1078,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
}
String config_file = "project.binary";
- String engine_cfb = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp" + config_file);
+ String engine_cfb = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmp" + config_file);
ProjectSettings::get_singleton()->save_custom(engine_cfb, custom_map, custom_list);
Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
DirAccess::remove_file_or_error(engine_cfb);
@@ -1100,9 +1100,9 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
// Create the temporary export directory if it doesn't exist.
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->make_dir_recursive(EditorSettings::get_singleton()->get_cache_dir());
+ da->make_dir_recursive(EditorPaths::get_singleton()->get_cache_dir());
- String tmppath = EditorSettings::get_singleton()->get_cache_dir().plus_file("packtmp");
+ String tmppath = EditorPaths::get_singleton()->get_cache_dir().plus_file("packtmp");
FileAccess *ftmp = FileAccess::open(tmppath, FileAccess::WRITE);
ERR_FAIL_COND_V_MSG(!ftmp, ERR_CANT_CREATE, "Cannot create file '" + tmppath + "'.");
@@ -1222,12 +1222,12 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
}
for (int i = 0; i < pd.file_ofs.size(); i++) {
- int string_len = pd.file_ofs[i].path_utf8.length();
- int pad = _get_pad(4, string_len);
+ uint32_t string_len = pd.file_ofs[i].path_utf8.length();
+ uint32_t pad = _get_pad(4, string_len);
fhead->store_32(string_len + pad);
fhead->store_buffer((const uint8_t *)pd.file_ofs[i].path_utf8.get_data(), string_len);
- for (int j = 0; j < pad; j++) {
+ for (uint32_t j = 0; j < pad; j++) {
fhead->store_8(0);
}
@@ -1269,8 +1269,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
uint8_t buf[bufsize];
while (true) {
- int got = ftmp->get_buffer(buf, bufsize);
- if (got <= 0) {
+ uint64_t got = ftmp->get_buffer(buf, bufsize);
+ if (got == 0) {
break;
}
f->store_buffer(buf, got);
@@ -1280,13 +1280,13 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
if (p_embed) {
// Ensure embedded data ends at a 64-bit multiple
- int64_t embed_end = f->get_position() - embed_pos + 12;
- int pad = embed_end % 8;
- for (int i = 0; i < pad; i++) {
+ uint64_t embed_end = f->get_position() - embed_pos + 12;
+ uint64_t pad = embed_end % 8;
+ for (uint64_t i = 0; i < pad; i++) {
f->store_8(0);
}
- int64_t pck_size = f->get_position() - pck_start_pos;
+ uint64_t pck_size = f->get_position() - pck_start_pos;
f->store_64(pck_size);
f->store_32(PACK_HEADER_MAGIC);
@@ -1984,7 +1984,7 @@ void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, con
if (!convert) {
return;
}
- String tmp_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpfile.res");
+ String tmp_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpfile.res");
Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path);
if (err != OK) {
DirAccess::remove_file_or_error(tmp_path);
diff --git a/editor/editor_export.h b/editor/editor_export.h
index c96c8fdbce..c9401df9c2 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -31,8 +31,8 @@
#ifndef EDITOR_EXPORT_H
#define EDITOR_EXPORT_H
+#include "core/io/dir_access.h"
#include "core/io/resource.h"
-#include "core/os/dir_access.h"
#include "scene/main/node.h"
#include "scene/main/timer.h"
#include "scene/resources/texture.h"
@@ -42,8 +42,8 @@ class EditorExportPlatform;
class EditorFileSystemDirectory;
struct EditorProgress;
-class EditorExportPreset : public Reference {
- GDCLASS(EditorExportPreset, Reference);
+class EditorExportPreset : public RefCounted {
+ GDCLASS(EditorExportPreset, RefCounted);
public:
enum ExportFilter {
@@ -161,8 +161,8 @@ struct SharedObject {
SharedObject() {}
};
-class EditorExportPlatform : public Reference {
- GDCLASS(EditorExportPlatform, Reference);
+class EditorExportPlatform : public RefCounted {
+ GDCLASS(EditorExportPlatform, RefCounted);
public:
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
@@ -284,8 +284,8 @@ public:
EditorExportPlatform();
};
-class EditorExportPlugin : public Reference {
- GDCLASS(EditorExportPlugin, Reference);
+class EditorExportPlugin : public RefCounted {
+ GDCLASS(EditorExportPlugin, RefCounted);
friend class EditorExportPlatform;
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index bd00d86ec8..51c6b473ad 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -30,8 +30,8 @@
#include "editor_feature_profile.h"
+#include "core/io/dir_access.h"
#include "core/io/json.h"
-#include "core/os/dir_access.h"
#include "editor/editor_settings.h"
#include "editor_node.h"
#include "editor_scale.h"
@@ -46,6 +46,16 @@ const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = {
TTRC("Import Dock"),
};
+const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = {
+ TTRC("Allows to view and edit 3D scenes."),
+ TTRC("Allows to edit scripts using the integrated script editor."),
+ TTRC("Provides built-in access to the Asset Library."),
+ TTRC("Allows editing the node hierarchy in the Scene dock."),
+ TTRC("Allows to work with signals and groups of the node selected in the Scene dock."),
+ TTRC("Allows to browse the local file system via a dedicated dock."),
+ TTRC("Allows to configure import settings for individual assets. Requires the FileSystem dock to function."),
+};
+
const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = {
"3d",
"script",
@@ -118,6 +128,18 @@ bool EditorFeatureProfile::has_class_properties_disabled(const StringName &p_cla
return disabled_properties.has(p_class);
}
+void EditorFeatureProfile::set_item_collapsed(const StringName &p_class, bool p_collapsed) {
+ if (p_collapsed) {
+ collapsed_classes.insert(p_class);
+ } else {
+ collapsed_classes.erase(p_class);
+ }
+}
+
+bool EditorFeatureProfile::is_item_collapsed(const StringName &p_class) const {
+ return collapsed_classes.has(p_class);
+}
+
void EditorFeatureProfile::set_disable_feature(Feature p_feature, bool p_disable) {
ERR_FAIL_INDEX(p_feature, FEATURE_MAX);
features_disabled[p_feature] = p_disable;
@@ -133,6 +155,11 @@ String EditorFeatureProfile::get_feature_name(Feature p_feature) {
return feature_names[p_feature];
}
+String EditorFeatureProfile::get_feature_description(Feature p_feature) {
+ ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, String());
+ return feature_descriptions[p_feature];
+}
+
Error EditorFeatureProfile::save_to_file(const String &p_path) {
Dictionary json;
json["type"] = "feature_profile";
@@ -406,7 +433,7 @@ void EditorFeatureProfileManager::_profile_action(int p_action) {
export_profile->set_current_file(_get_selected_profile() + ".profile");
} break;
case PROFILE_NEW: {
- new_profile_dialog->popup_centered();
+ new_profile_dialog->popup_centered(Size2(240, 60) * EDSCALE);
new_profile_name->clear();
new_profile_name->grab_focus();
} break;
@@ -414,8 +441,8 @@ void EditorFeatureProfileManager::_profile_action(int p_action) {
String selected = _get_selected_profile();
ERR_FAIL_COND(selected == String());
- erase_profile_dialog->set_text(vformat(TTR("Erase profile '%s'? (no undo)"), selected));
- erase_profile_dialog->popup_centered();
+ erase_profile_dialog->set_text(vformat(TTR("Remove currently selected profile, '%s'? Cannot be undone."), selected));
+ erase_profile_dialog->popup_centered(Size2(240, 60) * EDSCALE);
} break;
}
}
@@ -484,6 +511,9 @@ void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const S
class_item->set_selectable(0, true);
class_item->set_metadata(0, p_class);
+ bool collapsed = edited->is_item_collapsed(p_class);
+ class_item->set_collapsed(collapsed);
+
if (p_class == p_selected) {
class_item->select(0);
}
@@ -520,12 +550,28 @@ void EditorFeatureProfileManager::_class_list_item_selected() {
}
Variant md = item->get_metadata(0);
- if (md.get_type() != Variant::STRING && md.get_type() != Variant::STRING_NAME) {
+ if (md.get_type() == Variant::STRING || md.get_type() == Variant::STRING_NAME) {
+ String class_name = md;
+ String class_description;
+
+ DocTools *dd = EditorHelp::get_doc_data();
+ Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(class_name);
+ if (E) {
+ class_description = DTR(E->get().brief_description);
+ }
+
+ description_bit->set_text(class_description);
+ } else if (md.get_type() == Variant::INT) {
+ int feature_id = md;
+ String feature_description = EditorFeatureProfile::get_feature_description(EditorFeatureProfile::Feature(feature_id));
+
+ description_bit->set_text(feature_description);
+ return;
+ } else {
return;
}
String class_name = md;
-
if (edited->is_class_disabled(class_name)) {
return;
}
@@ -545,27 +591,28 @@ void EditorFeatureProfileManager::_class_list_item_selected() {
option->set_metadata(0, CLASS_OPTION_DISABLE_EDITOR);
}
- TreeItem *properties = property_list->create_item(root);
- properties->set_text(0, TTR("Enabled Properties:"));
-
List<PropertyInfo> props;
-
ClassDB::get_property_list(class_name, &props, true);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- String name = E->get().name;
- if (!(E->get().usage & PROPERTY_USAGE_EDITOR)) {
- continue;
+ if (props.size() > 0) {
+ TreeItem *properties = property_list->create_item(root);
+ properties->set_text(0, TTR("Class Properties:"));
+
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ String name = E->get().name;
+ if (!(E->get().usage & PROPERTY_USAGE_EDITOR)) {
+ continue;
+ }
+ TreeItem *property = property_list->create_item(properties);
+ property->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ property->set_editable(0, true);
+ property->set_selectable(0, true);
+ property->set_checked(0, !edited->is_class_property_disabled(class_name, name));
+ property->set_text(0, name.capitalize());
+ property->set_metadata(0, name);
+ String icon_type = Variant::get_type_name(E->get().type);
+ property->set_icon(0, EditorNode::get_singleton()->get_class_icon(icon_type));
}
- TreeItem *property = property_list->create_item(properties);
- property->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- property->set_editable(0, true);
- property->set_selectable(0, true);
- property->set_checked(0, !edited->is_class_property_disabled(class_name, name));
- property->set_text(0, name.capitalize());
- property->set_metadata(0, name);
- String icon_type = Variant::get_type_name(E->get().type);
- property->set_icon(0, EditorNode::get_singleton()->get_class_icon(icon_type));
}
updating_features = false;
@@ -596,6 +643,26 @@ void EditorFeatureProfileManager::_class_list_item_edited() {
}
}
+void EditorFeatureProfileManager::_class_list_item_collapsed(Object *p_item) {
+ if (updating_features) {
+ return;
+ }
+
+ TreeItem *item = Object::cast_to<TreeItem>(p_item);
+ if (!item) {
+ return;
+ }
+
+ Variant md = item->get_metadata(0);
+ if (md.get_type() != Variant::STRING && md.get_type() != Variant::STRING_NAME) {
+ return;
+ }
+
+ String class_name = md;
+ bool collapsed = item->is_collapsed();
+ edited->set_item_collapsed(class_name, collapsed);
+}
+
void EditorFeatureProfileManager::_property_item_edited() {
if (updating_features) {
return;
@@ -675,7 +742,7 @@ void EditorFeatureProfileManager::_update_selected_profile() {
TreeItem *features = class_list->create_item(root);
TreeItem *last_feature;
- features->set_text(0, TTR("Enabled Features:"));
+ features->set_text(0, TTR("Main Features") + ":");
for (int i = 0; i < EditorFeatureProfile::FEATURE_MAX; i++) {
TreeItem *feature;
if (i == EditorFeatureProfile::FEATURE_IMPORT_DOCK) {
@@ -699,7 +766,7 @@ void EditorFeatureProfileManager::_update_selected_profile() {
}
TreeItem *classes = class_list->create_item(root);
- classes->set_text(0, TTR("Enabled Classes:"));
+ classes->set_text(0, TTR("Nodes and Classes") + ":");
_fill_classes_from(classes, "Node", class_selected);
_fill_classes_from(classes, "Resource", class_selected);
@@ -797,47 +864,51 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
current_profile_name->set_text(TTR("(none)"));
current_profile_name->set_editable(false);
current_profile_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- profile_actions[PROFILE_CLEAR] = memnew(Button(TTR("Unset")));
+ profile_actions[PROFILE_CLEAR] = memnew(Button(TTR("Reset to Default")));
name_hbc->add_child(profile_actions[PROFILE_CLEAR]);
profile_actions[PROFILE_CLEAR]->set_disabled(true);
profile_actions[PROFILE_CLEAR]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_CLEAR));
main_vbc->add_margin_child(TTR("Current Profile:"), name_hbc);
+ main_vbc->add_child(memnew(HSeparator));
+
HBoxContainer *profiles_hbc = memnew(HBoxContainer);
profile_list = memnew(OptionButton);
profile_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
profiles_hbc->add_child(profile_list);
profile_list->connect("item_selected", callable_mp(this, &EditorFeatureProfileManager::_profile_selected));
- profile_actions[PROFILE_SET] = memnew(Button(TTR("Make Current")));
- profiles_hbc->add_child(profile_actions[PROFILE_SET]);
- profile_actions[PROFILE_SET]->set_disabled(true);
- profile_actions[PROFILE_SET]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_SET));
+ profile_actions[PROFILE_NEW] = memnew(Button(TTR("Create Profile")));
+ profiles_hbc->add_child(profile_actions[PROFILE_NEW]);
+ profile_actions[PROFILE_NEW]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_NEW));
- profile_actions[PROFILE_ERASE] = memnew(Button(TTR("Remove")));
+ profile_actions[PROFILE_ERASE] = memnew(Button(TTR("Remove Profile")));
profiles_hbc->add_child(profile_actions[PROFILE_ERASE]);
profile_actions[PROFILE_ERASE]->set_disabled(true);
profile_actions[PROFILE_ERASE]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_ERASE));
- profiles_hbc->add_child(memnew(VSeparator));
+ main_vbc->add_margin_child(TTR("Available Profiles:"), profiles_hbc);
- profile_actions[PROFILE_NEW] = memnew(Button(TTR("New")));
- profiles_hbc->add_child(profile_actions[PROFILE_NEW]);
- profile_actions[PROFILE_NEW]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_NEW));
+ HBoxContainer *current_profile_hbc = memnew(HBoxContainer);
- profiles_hbc->add_child(memnew(VSeparator));
+ profile_actions[PROFILE_SET] = memnew(Button(TTR("Make Current")));
+ current_profile_hbc->add_child(profile_actions[PROFILE_SET]);
+ profile_actions[PROFILE_SET]->set_disabled(true);
+ profile_actions[PROFILE_SET]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_SET));
+
+ current_profile_hbc->add_child(memnew(VSeparator));
profile_actions[PROFILE_IMPORT] = memnew(Button(TTR("Import")));
- profiles_hbc->add_child(profile_actions[PROFILE_IMPORT]);
+ current_profile_hbc->add_child(profile_actions[PROFILE_IMPORT]);
profile_actions[PROFILE_IMPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_IMPORT));
profile_actions[PROFILE_EXPORT] = memnew(Button(TTR("Export")));
- profiles_hbc->add_child(profile_actions[PROFILE_EXPORT]);
+ current_profile_hbc->add_child(profile_actions[PROFILE_EXPORT]);
profile_actions[PROFILE_EXPORT]->set_disabled(true);
profile_actions[PROFILE_EXPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_EXPORT));
- main_vbc->add_margin_child(TTR("Available Profiles:"), profiles_hbc);
+ main_vbc->add_child(current_profile_hbc);
h_split = memnew(HSplitContainer);
h_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@@ -848,11 +919,12 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
class_list_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
class_list = memnew(Tree);
- class_list_vbc->add_margin_child(TTR("Enabled Classes:"), class_list, true);
+ class_list_vbc->add_margin_child(TTR("Configure Selected Profile") + ":", class_list, true);
class_list->set_hide_root(true);
class_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
class_list->connect("cell_selected", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_selected));
class_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_edited), varray(), CONNECT_DEFERRED);
+ class_list->connect("item_collapsed", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_collapsed));
// It will be displayed once the user creates or chooses a profile.
class_list_vbc->hide();
@@ -860,8 +932,12 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
h_split->add_child(property_list_vbc);
property_list_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ description_bit = memnew(EditorHelpBit);
+ property_list_vbc->add_margin_child(TTR("Description") + ":", description_bit, false);
+ description_bit->set_custom_minimum_size(Size2(0, 80) * EDSCALE);
+
property_list = memnew(Tree);
- property_list_vbc->add_margin_child(TTR("Class Options:"), property_list, true);
+ property_list_vbc->add_margin_child(TTR("Extra Options") + ":", property_list, true);
property_list->set_hide_root(true);
property_list->set_hide_folding(true);
property_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
@@ -879,9 +955,14 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
h_split->add_child(no_profile_selected_help);
new_profile_dialog = memnew(ConfirmationDialog);
- new_profile_dialog->set_title(TTR("New profile name:"));
+ new_profile_dialog->set_title(TTR("Create Profile"));
+ VBoxContainer *new_profile_vb = memnew(VBoxContainer);
+ new_profile_dialog->add_child(new_profile_vb);
+ Label *new_profile_label = memnew(Label);
+ new_profile_label->set_text(TTR("New profile name") + ":");
+ new_profile_vb->add_child(new_profile_label);
new_profile_name = memnew(LineEdit);
- new_profile_dialog->add_child(new_profile_name);
+ new_profile_vb->add_child(new_profile_name);
new_profile_name->set_custom_minimum_size(Size2(300 * EDSCALE, 1));
add_child(new_profile_dialog);
new_profile_dialog->connect("confirmed", callable_mp(this, &EditorFeatureProfileManager::_create_new_profile));
@@ -890,7 +971,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
erase_profile_dialog = memnew(ConfirmationDialog);
add_child(erase_profile_dialog);
- erase_profile_dialog->set_title(TTR("Erase Profile"));
+ erase_profile_dialog->set_title(TTR("Remove Profile"));
erase_profile_dialog->connect("confirmed", callable_mp(this, &EditorFeatureProfileManager::_erase_selected_profile));
import_profiles = memnew(EditorFileDialog);
diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h
index 01e6a6a142..d31498bfc6 100644
--- a/editor/editor_feature_profile.h
+++ b/editor/editor_feature_profile.h
@@ -31,17 +31,18 @@
#ifndef EDITOR_FEATURE_PROFILE_H
#define EDITOR_FEATURE_PROFILE_H
-#include "core/object/reference.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
+#include "core/object/ref_counted.h"
#include "editor/editor_file_dialog.h"
+#include "editor_help.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/option_button.h"
#include "scene/gui/separator.h"
#include "scene/gui/split_container.h"
#include "scene/gui/tree.h"
-class EditorFeatureProfile : public Reference {
- GDCLASS(EditorFeatureProfile, Reference);
+class EditorFeatureProfile : public RefCounted {
+ GDCLASS(EditorFeatureProfile, RefCounted);
public:
enum Feature {
@@ -60,8 +61,11 @@ private:
Set<StringName> disabled_editors;
Map<StringName, Set<StringName>> disabled_properties;
+ Set<StringName> collapsed_classes;
+
bool features_disabled[FEATURE_MAX];
static const char *feature_names[FEATURE_MAX];
+ static const char *feature_descriptions[FEATURE_MAX];
static const char *feature_identifiers[FEATURE_MAX];
String _get_feature_name(Feature p_feature) { return get_feature_name(p_feature); }
@@ -80,6 +84,9 @@ public:
bool is_class_property_disabled(const StringName &p_class, const StringName &p_property) const;
bool has_class_properties_disabled(const StringName &p_class) const;
+ void set_item_collapsed(const StringName &p_class, bool p_collapsed);
+ bool is_item_collapsed(const StringName &p_class) const;
+
void set_disable_feature(Feature p_feature, bool p_disable);
bool is_feature_disabled(Feature p_feature) const;
@@ -87,6 +94,7 @@ public:
Error load_from_file(const String &p_path);
static String get_feature_name(Feature p_feature);
+ static String get_feature_description(Feature p_feature);
EditorFeatureProfile();
};
@@ -124,6 +132,7 @@ class EditorFeatureProfileManager : public AcceptDialog {
Tree *class_list;
VBoxContainer *property_list_vbc;
Tree *property_list;
+ EditorHelpBit *description_bit;
Label *no_profile_selected_help;
EditorFileDialog *import_profiles;
@@ -151,6 +160,7 @@ class EditorFeatureProfileManager : public AcceptDialog {
void _class_list_item_selected();
void _class_list_item_edited();
+ void _class_list_item_collapsed(Object *p_item);
void _property_item_edited();
void _save_and_update();
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 75815fa750..991d76ce72 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -30,7 +30,7 @@
#include "editor_file_dialog.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -294,6 +294,9 @@ void EditorFileDialog::_post_popup() {
if (res && name == "res://") {
name = "/";
} else {
+ if (name.ends_with("/")) {
+ name = name.substr(0, name.length() - 1);
+ }
name = name.get_file() + "/";
}
bool exists = dir_access->dir_exists(recentd[i]);
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 5a5e3a8807..f7879838d4 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -31,7 +31,7 @@
#ifndef EDITORFILEDIALOG_H
#define EDITORFILEDIALOG_H
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "scene/gui/box_container.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/item_list.h"
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 495bdd42f7..c61b097ccd 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -31,10 +31,10 @@
#include "editor_file_system.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/resource_importer.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
#include "editor_node.h"
@@ -506,7 +506,7 @@ bool EditorFileSystem::_update_scan_actions() {
case ItemAction::ACTION_DIR_ADD: {
int idx = 0;
for (int i = 0; i < ia.dir->subdirs.size(); i++) {
- if (ia.new_dir->name < ia.dir->subdirs[i]->name) {
+ if (ia.new_dir->name.naturalnocasecmp_to(ia.dir->subdirs[i]->name) < 0) {
break;
}
idx++;
@@ -528,7 +528,7 @@ bool EditorFileSystem::_update_scan_actions() {
case ItemAction::ACTION_FILE_ADD: {
int idx = 0;
for (int i = 0; i < ia.dir->files.size(); i++) {
- if (ia.new_file->file < ia.dir->files[i]->file) {
+ if (ia.new_file->file.naturalnocasecmp_to(ia.dir->files[i]->file) < 0) {
break;
}
idx++;
@@ -713,7 +713,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
int idx2 = 0;
for (int i = 0; i < p_dir->subdirs.size(); i++) {
- if (efd->name < p_dir->subdirs[i]->name) {
+ if (efd->name.naturalnocasecmp_to(p_dir->subdirs[i]->name) < 0) {
break;
}
idx2++;
@@ -1245,7 +1245,7 @@ bool EditorFileSystem::_find_file(const String &p_file, EditorFileSystemDirector
int idx2 = 0;
for (int j = 0; j < fs->get_subdir_count(); j++) {
- if (efsd->name < fs->get_subdir(j)->get_name()) {
+ if (efsd->name.naturalnocasecmp_to(fs->get_subdir(j)->get_name()) < 0) {
break;
}
idx2++;
@@ -1481,7 +1481,7 @@ void EditorFileSystem::update_file(const String &p_file) {
String file_name = p_file.get_file();
for (int i = 0; i < fs->files.size(); i++) {
- if (file_name < fs->files[i]->file) {
+ if (p_file.naturalnocasecmp_to(fs->files[i]->file) < 0) {
break;
}
idx++;
@@ -1934,19 +1934,6 @@ void EditorFileSystem::_reimport_thread(uint32_t p_index, ImportThreadData *p_im
}
void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
- {
- // Ensure that ProjectSettings::IMPORTED_FILES_PATH exists.
- DirAccess *da = DirAccess::open("res://");
- if (da->change_dir(ProjectSettings::IMPORTED_FILES_PATH) != OK) {
- Error err = da->make_dir_recursive(ProjectSettings::IMPORTED_FILES_PATH);
- if (err || da->change_dir(ProjectSettings::IMPORTED_FILES_PATH) != OK) {
- memdelete(da);
- ERR_FAIL_MSG("Failed to create '" + ProjectSettings::IMPORTED_FILES_PATH + "' folder.");
- }
- }
- memdelete(da);
- }
-
importing = true;
EditorProgress pr("reimport", TTR("(Re)Importing Assets"), p_files.size());
@@ -2177,13 +2164,9 @@ EditorFileSystem::EditorFileSystem() {
scanning_changes = false;
scanning_changes_done = false;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (da->change_dir(ProjectSettings::IMPORTED_FILES_PATH) != OK) {
- da->make_dir(ProjectSettings::IMPORTED_FILES_PATH);
- }
// This should probably also work on Unix and use the string it returns for FAT32 or exFAT
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT");
- memdelete(da);
scan_total = 0;
update_script_classes_queued.clear();
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index 855c320856..04879bad6d 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -31,7 +31,7 @@
#ifndef EDITOR_FILE_SYSTEM_H
#define EDITOR_FILE_SYSTEM_H
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/thread.h"
#include "core/os/thread_safe.h"
#include "core/templates/safe_refcount.h"
diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp
index 97a2c67c26..4030aecbf5 100644
--- a/editor/editor_folding.cpp
+++ b/editor/editor_folding.cpp
@@ -30,7 +30,7 @@
#include "editor_folding.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "editor_inspector.h"
#include "editor_settings.h"
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 96869ae6fd..2f5451fba3 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -31,7 +31,7 @@
#include "editor_fonts.h"
#include "builtin_fonts.gen.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "editor_scale.h"
#include "editor_settings.h"
#include "scene/resources/default_theme/default_theme.h"
@@ -313,9 +313,14 @@ void editor_register_fonts(Ref<Theme> p_theme) {
p_theme->set_font("bold", "EditorFonts", df_bold);
// Title font
- p_theme->set_font_size("title_size", "EditorFonts", default_font_size + 2 * EDSCALE);
+ p_theme->set_font_size("title_size", "EditorFonts", default_font_size + 1 * EDSCALE);
p_theme->set_font("title", "EditorFonts", df_bold);
+ p_theme->set_font_size("main_button_font_size", "EditorFonts", default_font_size + 1 * EDSCALE);
+ p_theme->set_font("main_button_font", "EditorFonts", df_bold);
+
+ p_theme->set_font("font", "Label", df_bold);
+
// Documentation fonts
MAKE_SOURCE_FONT(df_code);
p_theme->set_font_size("doc_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 6039f64b7c..9361981db6 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -475,7 +475,7 @@ void EditorHelp::_update_doc() {
String linktxt = (cd.tutorials[i].title.is_empty()) ? link : DTR(cd.tutorials[i].title);
const int seppos = linktxt.find("//");
if (seppos != -1) {
- linktxt = link.right(seppos + 2);
+ linktxt = link.substr(seppos + 2);
}
class_desc->push_color(symbol_color);
@@ -1593,7 +1593,7 @@ void EditorHelp::_notification(int p_what) {
_update_doc();
} break;
case NOTIFICATION_THEME_CHANGED: {
- if (is_visible_in_tree()) {
+ if (is_inside_tree()) {
_class_desc_resized();
}
} break;
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index 23226ffa9b..b93ffa9321 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -334,7 +334,7 @@ bool EditorHelpSearch::Runner::_phase_match_classes() {
for (int i = 0; i < class_doc.methods.size(); i++) {
String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower();
if (method_name.find(term) > -1 ||
- (term.begins_with(".") && method_name.begins_with(term.right(1))) ||
+ (term.begins_with(".") && method_name.begins_with(term.substr(1))) ||
(term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) ||
(term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) {
match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i]));
diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h
index 350a02315f..75da2d5aba 100644
--- a/editor/editor_help_search.h
+++ b/editor/editor_help_search.h
@@ -83,7 +83,7 @@ public:
EditorHelpSearch();
};
-class EditorHelpSearch::Runner : public Reference {
+class EditorHelpSearch::Runner : public RefCounted {
enum Phase {
PHASE_MATCH_CLASSES_INIT,
PHASE_MATCH_CLASSES,
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 5bb3c8b4d0..69709315ff 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -380,7 +380,7 @@ StringName EditorProperty::get_edited_property() {
void EditorProperty::update_property() {
if (get_script_instance()) {
- get_script_instance()->call("update_property");
+ get_script_instance()->call("_update_property");
}
}
@@ -741,7 +741,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
if (use_keying_next()) {
if (property == "frame_coords" && (object->is_class("Sprite2D") || object->is_class("Sprite3D"))) {
- Vector2 new_coords = object->get(property);
+ Vector2i new_coords = object->get(property);
new_coords.x++;
if (new_coords.x >= object->get("hframes").operator int64_t()) {
new_coords.x = 0;
@@ -753,7 +753,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
call_deferred("emit_changed", property, object->get(property).operator int64_t() + 1, "", false);
}
- call_deferred("update_property");
+ call_deferred("_update_property");
}
}
if (delete_rect.has_point(mpos)) {
@@ -965,9 +965,7 @@ void EditorProperty::_bind_methods() {
ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "focusable_idx")));
- MethodInfo vm;
- vm.name = "update_property";
- BIND_VMETHOD(vm);
+ BIND_VMETHOD(MethodInfo("_update_property"));
}
EditorProperty::EditorProperty() {
@@ -1023,20 +1021,20 @@ void EditorInspectorPlugin::add_property_editor_for_multiple_properties(const St
bool EditorInspectorPlugin::can_handle(Object *p_object) {
if (get_script_instance()) {
- return get_script_instance()->call("can_handle", p_object);
+ return get_script_instance()->call("_can_handle", p_object);
}
return false;
}
void EditorInspectorPlugin::parse_begin(Object *p_object) {
if (get_script_instance()) {
- get_script_instance()->call("parse_begin", p_object);
+ get_script_instance()->call("_parse_begin", p_object);
}
}
void EditorInspectorPlugin::parse_category(Object *p_object, const String &p_parse_category) {
if (get_script_instance()) {
- get_script_instance()->call("parse_category", p_object, p_parse_category);
+ get_script_instance()->call("_parse_category", p_object, p_parse_category);
}
}
@@ -1050,14 +1048,14 @@ bool EditorInspectorPlugin::parse_property(Object *p_object, Variant::Type p_typ
};
Callable::CallError err;
- return get_script_instance()->call("parse_property", (const Variant **)&argptr, 6, err);
+ return get_script_instance()->call("_parse_property", (const Variant **)&argptr, 6, err);
}
return false;
}
void EditorInspectorPlugin::parse_end() {
if (get_script_instance()) {
- get_script_instance()->call("parse_end");
+ get_script_instance()->call("_parse_end");
}
}
@@ -1066,30 +1064,11 @@ void EditorInspectorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_property_editor", "property", "editor"), &EditorInspectorPlugin::add_property_editor);
ClassDB::bind_method(D_METHOD("add_property_editor_for_multiple_properties", "label", "properties", "editor"), &EditorInspectorPlugin::add_property_editor_for_multiple_properties);
- MethodInfo vm;
- vm.name = "can_handle";
- vm.return_val.type = Variant::BOOL;
- vm.arguments.push_back(PropertyInfo(Variant::OBJECT, "object"));
- BIND_VMETHOD(vm);
- vm.name = "parse_begin";
- vm.return_val.type = Variant::NIL;
- BIND_VMETHOD(vm);
- vm.name = "parse_category";
- vm.arguments.push_back(PropertyInfo(Variant::STRING, "category"));
- BIND_VMETHOD(vm);
- vm.arguments.pop_back();
- vm.name = "parse_property";
- vm.return_val.type = Variant::BOOL;
- vm.arguments.push_back(PropertyInfo(Variant::INT, "type"));
- vm.arguments.push_back(PropertyInfo(Variant::STRING, "path"));
- vm.arguments.push_back(PropertyInfo(Variant::INT, "hint"));
- vm.arguments.push_back(PropertyInfo(Variant::STRING, "hint_text"));
- vm.arguments.push_back(PropertyInfo(Variant::INT, "usage"));
- BIND_VMETHOD(vm);
- vm.arguments.clear();
- vm.name = "parse_end";
- vm.return_val.type = Variant::NIL;
- BIND_VMETHOD(vm);
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_can_handle", PropertyInfo(Variant::OBJECT, "object")));
+ BIND_VMETHOD(MethodInfo(Variant::NIL, "_parse_begin"));
+ BIND_VMETHOD(MethodInfo(Variant::NIL, "_parse_category", PropertyInfo(Variant::STRING, "category")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_parse_property", PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "hint"), PropertyInfo(Variant::STRING, "hint_text"), PropertyInfo(Variant::INT, "usage")));
+ BIND_VMETHOD(MethodInfo(Variant::NIL, "_parse_end"));
}
////////////////////////////////////////////////
@@ -1097,9 +1076,12 @@ void EditorInspectorPlugin::_bind_methods() {
void EditorInspectorCategory::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- draw_rect(Rect2(Vector2(), get_size()), bg_color);
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
+ Ref<StyleBox> sb = get_theme_stylebox("prop_category_style", "Editor");
+
+ draw_style_box(sb, Rect2(Vector2(), get_size()));
+
+ Ref<Font> font = get_theme_font("bold", "EditorFonts");
+ int font_size = get_theme_font_size("bold_size", "EditorFonts");
int hs = get_theme_constant("hseparation", "Tree");
@@ -1181,8 +1163,9 @@ void EditorInspectorSection::_test_unfold() {
void EditorInspectorSection::_notification(int p_what) {
if (p_what == NOTIFICATION_SORT_CHILDREN) {
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
+ Ref<Font> font = get_theme_font("bold", "EditorFonts");
+ int font_size = get_theme_font_size("bold_size", "EditorFonts");
+
Ref<Texture2D> arrow;
if (foldable) {
@@ -1233,15 +1216,19 @@ void EditorInspectorSection::_notification(int p_what) {
bool rtl = is_layout_rtl();
if (foldable) {
- if (rtl) {
- arrow = get_theme_icon("arrow_collapsed_mirrored", "Tree");
+ if (object->editor_is_section_unfolded(section)) {
+ arrow = get_theme_icon("arrow", "Tree");
} else {
- arrow = get_theme_icon("arrow_collapsed", "Tree");
+ if (is_layout_rtl()) {
+ arrow = get_theme_icon("arrow_collapsed_mirrored", "Tree");
+ } else {
+ arrow = get_theme_icon("arrow_collapsed", "Tree");
+ }
}
}
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
+ Ref<Font> font = get_theme_font("bold", "EditorFonts");
+ int font_size = get_theme_font_size("bold_size", "EditorFonts");
int h = font->get_height(font_size);
if (arrow.is_valid()) {
@@ -1249,12 +1236,15 @@ void EditorInspectorSection::_notification(int p_what) {
}
h += get_theme_constant("vseparation", "Tree");
- draw_rect(Rect2(Vector2(), Vector2(get_size().width, h)), bg_color);
+ Color c = bg_color;
+ c.a *= 0.4;
+ draw_rect(Rect2(Vector2(), Vector2(get_size().width, h)), c);
- const int arrow_margin = 3;
- Color color = get_theme_color("font_color", "Tree");
- float text_width = get_size().width - Math::round((16 + arrow_margin) * EDSCALE);
- draw_string(font, Point2(rtl ? 0 : Math::round((16 + arrow_margin) * EDSCALE), font->get_ascent(font_size) + (h - font->get_height(font_size)) / 2).floor(), label, rtl ? HALIGN_RIGHT : HALIGN_LEFT, text_width, font_size, color);
+ const int arrow_margin = 2;
+ const int arrow_width = arrow.is_valid() ? arrow->get_width() : 0;
+ Color color = get_theme_color("font_color");
+ float text_width = get_size().width - Math::round(arrow_width + arrow_margin * EDSCALE);
+ draw_string(font, Point2(rtl ? 0 : Math::round(arrow_width + arrow_margin * EDSCALE), font->get_ascent(font_size) + (h - font->get_height(font_size)) / 2).floor(), label, rtl ? HALIGN_RIGHT : HALIGN_LEFT, text_width, font_size, color);
if (arrow.is_valid()) {
if (rtl) {
@@ -1279,7 +1269,7 @@ void EditorInspectorSection::_notification(int p_what) {
Control *editor_property = Object::cast_to<Control>(vbox->get_child(child_idx));
// Test can_drop_data and can_drop_data_fw, since can_drop_data only works if set up with forwarding or if script attached.
- if (editor_property && (editor_property->can_drop_data(Point2(), dd) || editor_property->call("can_drop_data_fw", Point2(), dd, this))) {
+ if (editor_property && (editor_property->can_drop_data(Point2(), dd) || editor_property->call("_can_drop_data_fw", Point2(), dd, this))) {
children_can_drop = true;
break;
}
@@ -1626,7 +1616,7 @@ void EditorInspector::update_tree() {
bool draw_red = false;
- {
+ if (is_inside_tree()) {
Node *nod = Object::cast_to<Node>(object);
Node *es = EditorNode::get_singleton()->get_edited_scene();
if (nod && es != nod && nod->get_owner() != es) {
@@ -1737,7 +1727,6 @@ void EditorInspector::update_tree() {
}
category->label = type;
- category->bg_color = get_theme_color("prop_category", "Editor");
if (use_doc_hints) {
StringName type2 = p.name;
if (!class_descr_cache.has(type2)) {
@@ -1809,12 +1798,12 @@ void EditorInspector::update_tree() {
basename = group + "/" + basename;
}
- String name = (basename.find("/") != -1) ? basename.right(basename.rfind("/") + 1) : basename;
+ String name = (basename.find("/") != -1) ? basename.substr(basename.rfind("/") + 1) : basename;
if (capitalize_paths) {
int dot = name.find(".");
if (dot != -1) {
- String ov = name.right(dot);
+ String ov = name.substr(dot);
name = name.substr(0, dot);
name = name.capitalize();
name += ov;
@@ -1824,7 +1813,13 @@ void EditorInspector::update_tree() {
}
}
- String path = basename.left(basename.rfind("/"));
+ String path;
+ {
+ int idx = basename.rfind("/");
+ if (idx > -1) {
+ path = basename.left(idx);
+ }
+ }
if (use_filter && filter != "") {
String cat = path;
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 18250780be..e4bcab3e3f 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -175,8 +175,8 @@ public:
EditorProperty();
};
-class EditorInspectorPlugin : public Reference {
- GDCLASS(EditorInspectorPlugin, Reference);
+class EditorInspectorPlugin : public RefCounted {
+ GDCLASS(EditorInspectorPlugin, RefCounted);
friend class EditorInspector;
struct AddedEditor {
@@ -208,7 +208,7 @@ class EditorInspectorCategory : public Control {
friend class EditorInspector;
Ref<Texture2D> icon;
String label;
- Color bg_color;
+
mutable String tooltip_text;
protected:
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 7c485d53c5..35d8021394 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -234,8 +234,9 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) {
if (p_replace_previous) {
// Remove last line if replacing, as it will be replace by the next added line.
- log->remove_line(log->get_line_count() - 1);
- log->increment_line_count();
+ // Why "- 2"? RichTextLabel is weird. When you add a line with add_newline(), it also adds an element to the list of lines which is null/blank,
+ // but it still counts as a line. So if you remove the last line (count - 1) you are actually removing nothing...
+ log->remove_line(log->get_paragraph_count() - 2);
}
switch (p_message.type) {
@@ -269,13 +270,14 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) {
}
log->add_text(p_message.text);
- log->add_newline();
// Need to use pop() to exit out of the RichTextLabels current "push" stack.
// We only "push" in the above switch when message type != STD, so only pop when that is the case.
if (p_message.type != MSG_TYPE_STD) {
log->pop();
}
+
+ log->add_newline();
}
void EditorLog::_set_filter_active(bool p_active, MessageType p_message_type) {
@@ -376,7 +378,7 @@ EditorLog::EditorLog() {
collapse_button = memnew(Button);
collapse_button->set_flat(true);
collapse_button->set_focus_mode(FOCUS_NONE);
- collapse_button->set_tooltip(TTR("Collapse duplicate messages into one log entry. Shows number of occurences."));
+ collapse_button->set_tooltip(TTR("Collapse duplicate messages into one log entry. Shows number of occurrences."));
collapse_button->set_toggle_mode(true);
collapse_button->set_pressed(false);
collapse_button->connect("toggled", callable_mp(this, &EditorLog::_set_collapse));
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 61b17a7247..4f874687b4 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -34,15 +34,16 @@
#include "core/core_bind.h"
#include "core/input/input.h"
#include "core/io/config_file.h"
+#include "core/io/file_access.h"
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/io/stream_peer_ssl.h"
#include "core/object/class_db.h"
#include "core/object/message_queue.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
+#include "core/os/time.h"
#include "core/string/print_string.h"
#include "core/string/translation.h"
#include "core/version.h"
@@ -80,8 +81,10 @@
#include "editor/editor_inspector.h"
#include "editor/editor_layouts_dialog.h"
#include "editor/editor_log.h"
+#include "editor/editor_paths.h"
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
+#include "editor/editor_resource_picker.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_run_native.h"
#include "editor/editor_run_script.h"
@@ -117,7 +120,6 @@
#include "editor/plugins/animation_tree_editor_plugin.h"
#include "editor/plugins/asset_library_editor_plugin.h"
#include "editor/plugins/audio_stream_editor_plugin.h"
-#include "editor/plugins/baked_lightmap_editor_plugin.h"
#include "editor/plugins/camera_3d_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
@@ -130,13 +132,13 @@
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/editor_preview_plugins.h"
#include "editor/plugins/font_editor_plugin.h"
-#include "editor/plugins/gi_probe_editor_plugin.h"
#include "editor/plugins/gpu_particles_2d_editor_plugin.h"
#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
#include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h"
#include "editor/plugins/gradient_editor_plugin.h"
#include "editor/plugins/item_list_editor_plugin.h"
#include "editor/plugins/light_occluder_2d_editor_plugin.h"
+#include "editor/plugins/lightmap_gi_editor_plugin.h"
#include "editor/plugins/line_2d_editor_plugin.h"
#include "editor/plugins/material_editor_plugin.h"
#include "editor/plugins/mesh_editor_plugin.h"
@@ -173,6 +175,7 @@
#include "editor/plugins/tiles/tiles_editor_plugin.h"
#include "editor/plugins/version_control_editor_plugin.h"
#include "editor/plugins/visual_shader_editor_plugin.h"
+#include "editor/plugins/voxel_gi_editor_plugin.h"
#include "editor/progress_dialog.h"
#include "editor/project_export.h"
#include "editor/project_settings_editor.h"
@@ -482,8 +485,8 @@ void EditorNode::_update_from_settings() {
RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge);
RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/global_illumination/sdfgi/probe_ray_count")));
RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count);
- RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/global_illumination/gi_probes/quality")));
- RS::get_singleton()->gi_probe_set_quality(gi_probe_quality);
+ RS::VoxelGIQuality voxel_gi_quality = RS::VoxelGIQuality(int(GLOBAL_GET("rendering/global_illumination/voxel_gi/quality")));
+ RS::get_singleton()->voxel_gi_set_quality(voxel_gi_quality);
RS::get_singleton()->environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
RS::get_singleton()->environment_set_volumetric_fog_filter_active(bool(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter")));
RS::get_singleton()->canvas_set_shadow_texture_size(GLOBAL_GET("rendering/2d/shadow_atlas/size"));
@@ -705,6 +708,11 @@ void EditorNode::_notification(int p_what) {
p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_theme_icon("Godot", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), gui_base->get_theme_icon("Heart", "EditorIcons"));
+ for (int i = 0; i < main_editor_buttons.size(); i++) {
+ main_editor_buttons.write[i]->add_theme_font_override("font", gui_base->get_theme_font("main_button_font", "EditorFonts"));
+ main_editor_buttons.write[i]->add_theme_font_size_override("font_size", gui_base->get_theme_font_size("main_button_font_size", "EditorFonts"));
+ }
+
_update_update_spinner();
} break;
@@ -763,7 +771,7 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) {
if (!res->editor_can_reload_from_file()) {
continue;
}
- if (!res->get_path().is_resource_file() && !res->get_path().is_abs_path()) {
+ if (!res->get_path().is_resource_file() && !res->get_path().is_absolute_path()) {
continue;
}
if (!FileAccess::exists(res->get_path())) {
@@ -1456,7 +1464,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
img->convert(Image::FORMAT_RGB8);
//save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5
- String temp_path = EditorSettings::get_singleton()->get_cache_dir();
+ String temp_path = EditorPaths::get_singleton()->get_cache_dir();
String cache_base = ProjectSettings::get_singleton()->globalize_path(p_file).md5_text();
cache_base = temp_path.plus_file("resthumb-" + cache_base);
@@ -1580,6 +1588,8 @@ void EditorNode::_save_scene(String p_file, int idx) {
return;
}
+ scene->propagate_notification(NOTIFICATION_EDITOR_PRE_SAVE);
+
editor_data.apply_changes_in_editors();
List<Ref<AnimatedValuesBackup>> anim_backups;
_reset_animation_players(scene, &anim_backups);
@@ -1651,6 +1661,8 @@ void EditorNode::_save_scene(String p_file, int idx) {
} else {
_dialog_display_save_error(p_file, err);
}
+
+ scene->propagate_notification(NOTIFICATION_EDITOR_POST_SAVE);
}
void EditorNode::save_all_scenes() {
@@ -2150,9 +2162,14 @@ void EditorNode::_edit_current() {
if (!inspector_only) {
EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
- for (int i = 0; i < editor_table.size(); i++) {
- if (editor_table[i] == main_plugin && !main_editor_buttons[i]->is_visible()) {
- main_plugin = nullptr; //if button is not visible, then no plugin active
+ int plugin_index = 0;
+ for (; plugin_index < editor_table.size(); plugin_index++) {
+ if (editor_table[plugin_index] == main_plugin) {
+ if (!main_editor_buttons[plugin_index]->is_visible()) {
+ main_plugin = nullptr; //if button is not visible, then no plugin active
+ }
+
+ break;
}
}
@@ -2166,26 +2183,8 @@ void EditorNode::_edit_current() {
else if (main_plugin != editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) {
// update screen main_plugin
-
- if (!changing_scene) {
- if (editor_plugin_screen) {
- editor_plugin_screen->make_visible(false);
- }
- editor_plugin_screen = main_plugin;
- editor_plugin_screen->edit(current_obj);
-
- editor_plugin_screen->make_visible(true);
-
- int plugin_count = editor_data.get_editor_plugin_count();
- for (int i = 0; i < plugin_count; i++) {
- editor_data.get_editor_plugin(i)->notify_main_screen_changed(editor_plugin_screen->get_name());
- }
-
- for (int i = 0; i < editor_table.size(); i++) {
- main_editor_buttons[i]->set_pressed(editor_table[i] == main_plugin);
- }
- }
-
+ _editor_select(plugin_index);
+ main_plugin->edit(current_obj);
} else {
editor_plugin_screen->edit(current_obj);
}
@@ -2694,6 +2693,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: {
OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().plus_file("android"));
} break;
+ case RUN_RELOAD_CURRENT_PROJECT: {
+ restart_editor();
+ } break;
case FILE_QUIT:
case RUN_PROJECT_MANAGER: {
if (!p_confirmed) {
@@ -2744,10 +2746,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
settings_config_dialog->popup_edit_settings();
} break;
case SETTINGS_EDITOR_DATA_FOLDER: {
- OS::get_singleton()->shell_open(String("file://") + EditorSettings::get_singleton()->get_data_dir());
+ OS::get_singleton()->shell_open(String("file://") + EditorPaths::get_singleton()->get_data_dir());
} break;
case SETTINGS_EDITOR_CONFIG_FOLDER: {
- OS::get_singleton()->shell_open(String("file://") + EditorSettings::get_singleton()->get_settings_dir());
+ OS::get_singleton()->shell_open(String("file://") + EditorPaths::get_singleton()->get_config_dir());
} break;
case SETTINGS_MANAGE_EXPORT_TEMPLATES: {
export_template_manager->popup_manager();
@@ -2825,7 +2827,7 @@ void EditorNode::_request_screenshot() {
}
void EditorNode::_screenshot(bool p_use_utc) {
- String name = "editor_screenshot_" + OS::get_singleton()->get_iso_date_time(p_use_utc).replace(":", "") + ".png";
+ String name = "editor_screenshot_" + Time::get_singleton()->get_datetime_string_from_system(p_use_utc).replace(":", "") + ".png";
NodePath path = String("user://") + name;
_save_screenshot(path);
if (EditorSettings::get_singleton()->get("interface/editor/automatically_open_screenshots")) {
@@ -2891,7 +2893,7 @@ void EditorNode::_exit_editor() {
_save_docks();
// Dim the editor window while it's quitting to make it clearer that it's busy
- dim_editor(true, true);
+ dim_editor(true);
get_tree()->quit();
}
@@ -3057,6 +3059,9 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed
tb->set_icon(singleton->gui_base->get_theme_icon(p_editor->get_name(), "EditorIcons"));
}
+ tb->add_theme_font_override("font", singleton->gui_base->get_theme_font("main_button_font", "EditorFonts"));
+ tb->add_theme_font_size_override("font_size", singleton->gui_base->get_theme_font_size("main_button_font_size", "EditorFonts"));
+
tb->set_name(p_editor->get_name());
singleton->main_editor_buttons.push_back(tb);
singleton->main_editor_button_vb->add_child(tb);
@@ -3093,10 +3098,11 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor, bool p_config_chan
if (p_config_changed) {
p_editor->disable_plugin();
}
- singleton->editor_plugins_over->get_plugins_list().erase(p_editor);
+ singleton->editor_plugins_over->remove_plugin(p_editor);
+ singleton->editor_plugins_force_over->remove_plugin(p_editor);
+ singleton->editor_plugins_force_input_forwarding->remove_plugin(p_editor);
singleton->remove_child(p_editor);
singleton->editor_data.remove_editor_plugin(p_editor);
- singleton->get_editor_plugins_force_input_forwarding()->remove_plugin(p_editor);
}
void EditorNode::_update_addon_config() {
@@ -3165,7 +3171,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
// Errors in the script cause the base_type to be an empty string.
if (String(script->get_instance_base_type()) == "") {
- show_warning(vformat(TTR("Unable to load addon script from path: '%s'. This might be due to a code error in that script. \nDisabling the addon at '%s' to prevent further errors."), script_path, p_addon));
+ show_warning(vformat(TTR("Unable to load addon script from path: '%s'. This might be due to a code error in that script.\nDisabling the addon at '%s' to prevent further errors."), script_path, p_addon));
_remove_plugin_from_enabled(p_addon);
return;
}
@@ -3729,6 +3735,7 @@ void EditorNode::register_editor_types() {
ResourceLoader::set_timestamp_on_load(true);
ResourceSaver::set_timestamp_on_save(true);
+ ClassDB::register_class<EditorPaths>();
ClassDB::register_class<EditorPlugin>();
ClassDB::register_class<EditorTranslationParserPlugin>();
ClassDB::register_class<EditorImportPlugin>();
@@ -3757,6 +3764,8 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<ScriptCreateDialog>();
ClassDB::register_class<EditorFeatureProfile>();
ClassDB::register_class<EditorSpinSlider>();
+ ClassDB::register_class<EditorResourcePicker>();
+ ClassDB::register_class<EditorScriptPicker>();
ClassDB::register_class<EditorSceneImporterMesh>();
ClassDB::register_class<EditorSceneImporterMeshNode3D>();
@@ -3770,6 +3779,9 @@ void EditorNode::register_editor_types() {
void EditorNode::unregister_editor_types() {
_init_callbacks.clear();
+ if (EditorPaths::get_singleton()) {
+ EditorPaths::free();
+ }
}
void EditorNode::stop_child_process(OS::ProcessID p_pid) {
@@ -5288,7 +5300,7 @@ void EditorNode::_file_access_close_error_notify(const String &p_str) {
void EditorNode::reload_scene(const String &p_path) {
/*
- * No longer necesary since scenes now reset and reload their internal resource if needed.
+ * No longer necessary since scenes now reset and reload their internal resource if needed.
//first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk
List<Ref<Resource>> cached;
@@ -5392,15 +5404,9 @@ void EditorNode::_open_imported() {
load_scene(open_import_request, true, false, true, true);
}
-void EditorNode::dim_editor(bool p_dimming, bool p_force_dim) {
- // Dimming can be forced regardless of the editor setting, which is useful when quitting the editor.
- if ((p_force_dim || EditorSettings::get_singleton()->get("interface/editor/dim_editor_on_dialog_popup")) && p_dimming) {
- dimmed = true;
- gui_base->set_modulate(Color(0.5, 0.5, 0.5));
- } else {
- dimmed = false;
- gui_base->set_modulate(Color(1, 1, 1));
- }
+void EditorNode::dim_editor(bool p_dimming) {
+ dimmed = p_dimming;
+ gui_base->set_modulate(p_dimming ? Color(0.5, 0.5, 0.5) : Color(1, 1, 1));
}
bool EditorNode::is_editor_dimmed() const {
@@ -6285,6 +6291,7 @@ EditorNode::EditorNode() {
tool_menu->add_item(TTR("Orphan Resource Explorer..."), TOOLS_ORPHAN_RESOURCES);
p->add_separator();
+ p->add_item(TTR("Reload Current Project"), RUN_RELOAD_CURRENT_PROJECT);
#ifdef OSX_ENABLED
p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q), RUN_PROJECT_MANAGER, true);
#else
@@ -6613,7 +6620,7 @@ EditorNode::EditorNode() {
version_btn->set_text(VERSION_FULL_CONFIG);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
- hash = "." + hash.left(9);
+ hash = " " + vformat("[%s]", hash.left(9));
}
// Set the text to copy in metadata as it slightly differs from the button's text.
version_btn->set_meta(META_TEXT_TO_COPY, "v" VERSION_FULL_BUILD + hash);
@@ -6803,8 +6810,8 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(TilesEditorPlugin(this)));
add_editor_plugin(memnew(SpriteFramesEditorPlugin(this)));
add_editor_plugin(memnew(TextureRegionEditorPlugin(this)));
- add_editor_plugin(memnew(GIProbeEditorPlugin(this)));
- add_editor_plugin(memnew(BakedLightmapEditorPlugin(this)));
+ add_editor_plugin(memnew(VoxelGIEditorPlugin(this)));
+ add_editor_plugin(memnew(LightmapGIEditorPlugin(this)));
add_editor_plugin(memnew(OccluderInstance3DEditorPlugin(this)));
add_editor_plugin(memnew(Path2DEditorPlugin(this)));
add_editor_plugin(memnew(Path3DEditorPlugin(this)));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 9824702d7b..037ed263c5 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -164,6 +164,7 @@ private:
RUN_PLAY_CUSTOM_SCENE,
RUN_SETTINGS,
RUN_PROJECT_DATA_FOLDER,
+ RUN_RELOAD_CURRENT_PROJECT,
RUN_PROJECT_MANAGER,
RUN_VCS_SETTINGS,
RUN_VCS_SHUT_DOWN,
@@ -855,7 +856,7 @@ public:
void notify_settings_changed();
- void dim_editor(bool p_dimming, bool p_force_dim = false);
+ void dim_editor(bool p_dimming);
bool is_editor_dimmed() const;
void edit_current() { _edit_current(); };
diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp
index d1c52b4310..63281ae1aa 100644
--- a/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
@@ -59,15 +59,40 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) {
Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj);
- int index = get_popup()->get_item_count();
- get_popup()->add_icon_item(icon, E->get().name.capitalize(), objects.size());
- get_popup()->set_item_h_offset(index, p_depth * 10 * EDSCALE);
+ String proper_name = "";
+ Vector<String> name_parts = E->get().name.split("/");
+
+ for (int i = 0; i < name_parts.size(); i++) {
+ if (i > 0) {
+ proper_name += " > ";
+ }
+ proper_name += name_parts[i].capitalize();
+ }
+
+ int index = sub_objects_menu->get_item_count();
+ sub_objects_menu->add_icon_item(icon, proper_name, objects.size());
+ sub_objects_menu->set_item_h_offset(index, p_depth * 10 * EDSCALE);
objects.push_back(obj->get_instance_id());
_add_children_to_popup(obj, p_depth + 1);
}
}
+void EditorPath::_show_popup() {
+ sub_objects_menu->clear();
+
+ Size2 size = get_size();
+ Point2 gp = get_screen_position();
+ gp.y += size.y;
+
+ sub_objects_menu->set_position(gp);
+ sub_objects_menu->set_size(Size2(size.width, 1));
+ sub_objects_menu->set_parent_rect(Rect2(Point2(gp - sub_objects_menu->get_position()), size));
+
+ sub_objects_menu->take_mouse_focus();
+ sub_objects_menu->popup();
+}
+
void EditorPath::_about_to_show() {
Object *obj = ObjectDB::get_instance(history->get_path_object(history->get_path_size() - 1));
if (!obj) {
@@ -75,13 +100,11 @@ void EditorPath::_about_to_show() {
}
objects.clear();
- get_popup()->clear();
- get_popup()->set_size(Size2(get_size().width, 1));
_add_children_to_popup(obj);
- if (get_popup()->get_item_count() == 0) {
- get_popup()->add_item(TTR("No sub-resources found."));
- get_popup()->set_item_disabled(0, true);
+ if (sub_objects_menu->get_item_count() == 0) {
+ sub_objects_menu->add_item(TTR("No sub-resources found."));
+ sub_objects_menu->set_item_disabled(0, true);
}
}
@@ -94,7 +117,7 @@ void EditorPath::update_path() {
Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj);
if (icon.is_valid()) {
- set_icon(icon);
+ current_object_icon->set_texture(icon);
}
if (i == history->get_path_size() - 1) {
@@ -120,12 +143,26 @@ void EditorPath::update_path() {
name = obj->get_class();
}
- set_text(" " + name); // An extra space so the text is not too close of the icon.
+ current_object_label->set_text(" " + name); // An extra space so the text is not too close of the icon.
set_tooltip(obj->get_class());
}
}
}
+void EditorPath::clear_path() {
+ set_disabled(true);
+ set_tooltip("");
+
+ current_object_label->set_text("");
+ current_object_icon->set_texture(nullptr);
+ sub_objects_icon->set_visible(false);
+}
+
+void EditorPath::enable_path() {
+ set_disabled(false);
+ sub_objects_icon->set_visible(true);
+}
+
void EditorPath::_id_pressed(int p_idx) {
ERR_FAIL_INDEX(p_idx, objects.size());
@@ -139,8 +176,16 @@ void EditorPath::_id_pressed(int p_idx) {
void EditorPath::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
update_path();
+
+ sub_objects_icon->set_texture(get_theme_icon("select_arrow", "Tree"));
+ current_object_label->add_theme_font_override("font", get_theme_font("main", "EditorFonts"));
+ } break;
+
+ case NOTIFICATION_READY: {
+ connect("pressed", callable_mp(this, &EditorPath::_show_popup));
} break;
}
}
@@ -150,8 +195,35 @@ void EditorPath::_bind_methods() {
EditorPath::EditorPath(EditorHistory *p_history) {
history = p_history;
- set_clip_text(true);
- set_text_align(ALIGN_LEFT);
- get_popup()->connect("about_to_popup", callable_mp(this, &EditorPath::_about_to_show));
- get_popup()->connect("id_pressed", callable_mp(this, &EditorPath::_id_pressed));
+
+ MarginContainer *main_mc = memnew(MarginContainer);
+ main_mc->set_anchors_and_offsets_preset(PRESET_WIDE);
+ main_mc->add_theme_constant_override("margin_left", 4 * EDSCALE);
+ main_mc->add_theme_constant_override("margin_right", 6 * EDSCALE);
+ add_child(main_mc);
+
+ HBoxContainer *main_hb = memnew(HBoxContainer);
+ main_mc->add_child(main_hb);
+
+ current_object_icon = memnew(TextureRect);
+ current_object_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ main_hb->add_child(current_object_icon);
+
+ current_object_label = memnew(Label);
+ current_object_label->set_clip_text(true);
+ current_object_label->set_align(Label::ALIGN_LEFT);
+ current_object_label->set_h_size_flags(SIZE_EXPAND_FILL);
+ main_hb->add_child(current_object_label);
+
+ sub_objects_icon = memnew(TextureRect);
+ sub_objects_icon->set_visible(false);
+ sub_objects_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ main_hb->add_child(sub_objects_icon);
+
+ sub_objects_menu = memnew(PopupMenu);
+ add_child(sub_objects_menu);
+ sub_objects_menu->connect("about_to_popup", callable_mp(this, &EditorPath::_about_to_show));
+ sub_objects_menu->connect("id_pressed", callable_mp(this, &EditorPath::_id_pressed));
+
+ set_tooltip(TTR("Open a list of sub-resources."));
}
diff --git a/editor/editor_path.h b/editor/editor_path.h
index d1090947f9..cabfa931d6 100644
--- a/editor/editor_path.h
+++ b/editor/editor_path.h
@@ -32,16 +32,24 @@
#define EDITOR_PATH_H
#include "editor_data.h"
-#include "scene/gui/menu_button.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/popup_menu.h"
-class EditorPath : public MenuButton {
- GDCLASS(EditorPath, MenuButton);
+class EditorPath : public Button {
+ GDCLASS(EditorPath, Button);
EditorHistory *history;
+ TextureRect *current_object_icon;
+ Label *current_object_label;
+ TextureRect *sub_objects_icon;
+ PopupMenu *sub_objects_menu;
+
Vector<ObjectID> objects;
EditorPath();
+ void _show_popup();
void _id_pressed(int p_idx);
void _about_to_show();
void _add_children_to_popup(Object *p_obj, int p_depth = 0);
@@ -52,6 +60,8 @@ protected:
public:
void update_path();
+ void clear_path();
+ void enable_path();
EditorPath(EditorHistory *p_history);
};
diff --git a/editor/editor_paths.cpp b/editor/editor_paths.cpp
new file mode 100644
index 0000000000..323707ec6c
--- /dev/null
+++ b/editor/editor_paths.cpp
@@ -0,0 +1,214 @@
+/*************************************************************************/
+/* editor_paths.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "editor_paths.h"
+
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/os/os.h"
+#include "main/main.h" // For `is_project_manager`.
+
+EditorPaths *EditorPaths::singleton = nullptr;
+
+bool EditorPaths::are_paths_valid() const {
+ return paths_valid;
+}
+
+String EditorPaths::get_data_dir() const {
+ return data_dir;
+}
+
+String EditorPaths::get_config_dir() const {
+ return config_dir;
+}
+
+String EditorPaths::get_cache_dir() const {
+ return cache_dir;
+}
+
+String EditorPaths::get_project_data_dir() const {
+ return project_data_dir;
+}
+
+bool EditorPaths::is_self_contained() const {
+ return self_contained;
+}
+
+String EditorPaths::get_self_contained_file() const {
+ return self_contained_file;
+}
+
+void EditorPaths::create() {
+ ERR_FAIL_COND(singleton != nullptr);
+ memnew(EditorPaths());
+}
+
+void EditorPaths::free() {
+ ERR_FAIL_COND(singleton == nullptr);
+ memdelete(singleton);
+}
+
+void EditorPaths::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_data_dir"), &EditorPaths::get_data_dir);
+ ClassDB::bind_method(D_METHOD("get_config_dir"), &EditorPaths::get_config_dir);
+ ClassDB::bind_method(D_METHOD("get_cache_dir"), &EditorPaths::get_cache_dir);
+ ClassDB::bind_method(D_METHOD("is_self_contained"), &EditorPaths::is_self_contained);
+ ClassDB::bind_method(D_METHOD("get_self_contained_file"), &EditorPaths::get_self_contained_file);
+}
+
+EditorPaths::EditorPaths() {
+ singleton = this;
+
+ // Self-contained mode if a `._sc_` or `_sc_` file is present in executable dir.
+ String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
+ {
+ DirAccessRef d = DirAccess::create_for_path(exe_path);
+
+ if (d->file_exists(exe_path + "/._sc_")) {
+ self_contained = true;
+ self_contained_file = exe_path + "/._sc_";
+ } else if (d->file_exists(exe_path + "/_sc_")) {
+ self_contained = true;
+ self_contained_file = exe_path + "/_sc_";
+ }
+ }
+
+ String data_path;
+ String config_path;
+ String cache_path;
+
+ if (self_contained) {
+ // editor is self contained, all in same folder
+ data_path = exe_path;
+ data_dir = data_path.plus_file("editor_data");
+ config_path = exe_path;
+ config_dir = data_dir;
+ cache_path = exe_path;
+ cache_dir = data_dir.plus_file("cache");
+ } else {
+ // Typically XDG_DATA_HOME or %APPDATA%.
+ data_path = OS::get_singleton()->get_data_path();
+ data_dir = data_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+ // Can be different from data_path e.g. on Linux or macOS.
+ config_path = OS::get_singleton()->get_config_path();
+ config_dir = config_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+ // Can be different from above paths, otherwise a subfolder of data_dir.
+ cache_path = OS::get_singleton()->get_cache_path();
+ if (cache_path == data_path) {
+ cache_dir = data_dir.plus_file("cache");
+ } else {
+ cache_dir = cache_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+ }
+ }
+
+ paths_valid = (data_path != "" && config_path != "" && cache_path != "");
+ ERR_FAIL_COND_MSG(!paths_valid, "Editor data, config, or cache paths are invalid.");
+
+ // Validate or create each dir and its relevant subdirectories.
+
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ // Data dir.
+ {
+ if (dir->change_dir(data_dir) != OK) {
+ dir->make_dir_recursive(data_dir);
+ if (dir->change_dir(data_dir) != OK) {
+ ERR_PRINT("Could not create editor data directory: " + data_dir);
+ paths_valid = false;
+ }
+ }
+
+ if (!dir->dir_exists("templates")) {
+ dir->make_dir("templates");
+ }
+ }
+
+ // Config dir.
+ {
+ if (dir->change_dir(config_dir) != OK) {
+ dir->make_dir_recursive(config_dir);
+ if (dir->change_dir(config_dir) != OK) {
+ ERR_PRINT("Could not create editor config directory: " + config_dir);
+ paths_valid = false;
+ }
+ }
+
+ if (!dir->dir_exists("text_editor_themes")) {
+ dir->make_dir("text_editor_themes");
+ }
+ if (!dir->dir_exists("script_templates")) {
+ dir->make_dir("script_templates");
+ }
+ if (!dir->dir_exists("feature_profiles")) {
+ dir->make_dir("feature_profiles");
+ }
+ }
+
+ // Cache dir.
+ {
+ if (dir->change_dir(cache_dir) != OK) {
+ dir->make_dir_recursive(cache_dir);
+ if (dir->change_dir(cache_dir) != OK) {
+ ERR_PRINT("Could not create editor cache directory: " + cache_dir);
+ paths_valid = false;
+ }
+ }
+ }
+
+ // Validate or create project-specific editor data dir (`res://.godot`),
+ // including shader cache subdir.
+
+ if (Main::is_project_manager()) {
+ // Nothing to create, use shared editor data dir for shader cache.
+ Engine::get_singleton()->set_shader_cache_path(data_dir);
+ } else {
+ DirAccessRef dir_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (dir_res->change_dir(project_data_dir) != OK) {
+ dir_res->make_dir_recursive(project_data_dir);
+ if (dir_res->change_dir(project_data_dir) != OK) {
+ ERR_PRINT("Could not create project data directory (" + project_data_dir + ") in: " + dir_res->get_current_dir());
+ paths_valid = false;
+ }
+ }
+ Engine::get_singleton()->set_shader_cache_path(project_data_dir);
+
+ // Editor metadata dir.
+ if (!dir_res->dir_exists("editor")) {
+ dir_res->make_dir("editor");
+ }
+ // Imported assets dir.
+ if (!dir_res->dir_exists(ProjectSettings::IMPORTED_FILES_PATH)) {
+ dir_res->make_dir(ProjectSettings::IMPORTED_FILES_PATH);
+ }
+ }
+
+ print_line("paths valid: " + itos((int)paths_valid));
+}
diff --git a/editor/editor_paths.h b/editor/editor_paths.h
new file mode 100644
index 0000000000..2c156b7c96
--- /dev/null
+++ b/editor/editor_paths.h
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* editor_paths.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef EDITOR_PATHS_H
+#define EDITOR_PATHS_H
+
+#include "core/object/class_db.h"
+#include "core/string/ustring.h"
+
+class EditorPaths : public Object {
+ GDCLASS(EditorPaths, Object)
+
+ bool paths_valid = false; // If any of the paths can't be created, this is false.
+ String data_dir; // Editor data (templates, shader cache, etc.).
+ String config_dir; // Editor config (settings, profiles, themes, etc.).
+ String cache_dir; // Editor cache (thumbnails, tmp generated files).
+ String project_data_dir = "res://.godot"; // Project-specific data (metadata, shader cache, etc.).
+ bool self_contained = false; // Self-contained means everything goes to `editor_data` dir.
+ String self_contained_file; // Self-contained file with configuration.
+
+ static EditorPaths *singleton;
+
+protected:
+ static void _bind_methods();
+
+public:
+ bool are_paths_valid() const;
+
+ String get_data_dir() const;
+ String get_config_dir() const;
+ String get_cache_dir() const;
+ String get_project_data_dir() const;
+
+ bool is_self_contained() const;
+ String get_self_contained_file() const;
+
+ static EditorPaths *get_singleton() {
+ return singleton;
+ }
+
+ static void create();
+ static void free();
+
+ EditorPaths();
+};
+
+#endif // EDITOR_PATHS_H
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 6b96cb0f5c..63de06d5e2 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_export.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_settings.h"
#include "editor/filesystem_dock.h"
#include "editor/project_settings_editor.h"
@@ -59,7 +60,7 @@ Array EditorInterface::_make_mesh_previews(const Array &p_meshes, int p_preview_
return ret;
}
-Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform> *p_transforms, int p_preview_size) {
+Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size) {
int size = p_preview_size;
RID scenario = RS::get_singleton()->scenario_create();
@@ -93,7 +94,7 @@ Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh
continue;
}
- Transform mesh_xform;
+ Transform3D mesh_xform;
if (p_transforms != nullptr) {
mesh_xform = (*p_transforms)[i];
}
@@ -104,7 +105,7 @@ Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh
AABB aabb = mesh->get_aabb();
Vector3 ofs = aabb.position + aabb.size * 0.5;
aabb.position -= ofs;
- Transform xform;
+ Transform3D xform;
xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI / 6);
xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI / 6) * xform.basis;
AABB rot_aabb = xform.xform(aabb);
@@ -118,11 +119,11 @@ Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh
xform.invert();
xform = mesh_xform * xform;
- RS::get_singleton()->camera_set_transform(camera, xform * Transform(Basis(), Vector3(0, 0, 3)));
+ RS::get_singleton()->camera_set_transform(camera, xform * Transform3D(Basis(), Vector3(0, 0, 3)));
RS::get_singleton()->camera_set_orthogonal(camera, m * 2, 0.01, 1000.0);
- RS::get_singleton()->instance_set_transform(light_instance, xform * Transform().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0)));
- RS::get_singleton()->instance_set_transform(light_instance2, xform * Transform().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0)));
+ RS::get_singleton()->instance_set_transform(light_instance, xform * Transform3D().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0)));
+ RS::get_singleton()->instance_set_transform(light_instance2, xform * Transform3D().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0)));
ep.step(TTR("Thumbnail..."), i);
Main::iteration();
@@ -257,6 +258,9 @@ EditorSelection *EditorInterface::get_selection() {
Ref<EditorSettings> EditorInterface::get_editor_settings() {
return EditorSettings::get_singleton();
}
+EditorPaths *EditorInterface::get_editor_paths() {
+ return EditorPaths::get_singleton();
+}
EditorResourcePreview *EditorInterface::get_resource_previewer() {
return EditorResourcePreview::get_singleton();
@@ -335,6 +339,7 @@ void EditorInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path);
ClassDB::bind_method(D_METHOD("get_current_path"), &EditorInterface::get_current_path);
ClassDB::bind_method(D_METHOD("get_file_system_dock"), &EditorInterface::get_file_system_dock);
+ ClassDB::bind_method(D_METHOD("get_editor_paths"), &EditorInterface::get_editor_paths);
ClassDB::bind_method(D_METHOD("set_plugin_enabled", "plugin", "enabled"), &EditorInterface::set_plugin_enabled);
ClassDB::bind_method(D_METHOD("is_plugin_enabled", "plugin"), &EditorInterface::is_plugin_enabled);
@@ -548,21 +553,21 @@ void EditorPlugin::notify_resource_saved(const Ref<Resource> &p_resource) {
}
bool EditorPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
- if (get_script_instance() && get_script_instance()->has_method("forward_canvas_gui_input")) {
- return get_script_instance()->call("forward_canvas_gui_input", p_event);
+ if (get_script_instance() && get_script_instance()->has_method("_forward_canvas_gui_input")) {
+ return get_script_instance()->call("_forward_canvas_gui_input", p_event);
}
return false;
}
void EditorPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
- if (get_script_instance() && get_script_instance()->has_method("forward_canvas_draw_over_viewport")) {
- get_script_instance()->call("forward_canvas_draw_over_viewport", p_overlay);
+ if (get_script_instance() && get_script_instance()->has_method("_forward_canvas_draw_over_viewport")) {
+ get_script_instance()->call("_forward_canvas_draw_over_viewport", p_overlay);
}
}
void EditorPlugin::forward_canvas_force_draw_over_viewport(Control *p_overlay) {
- if (get_script_instance() && get_script_instance()->has_method("forward_canvas_force_draw_over_viewport")) {
- get_script_instance()->call("forward_canvas_force_draw_over_viewport", p_overlay);
+ if (get_script_instance() && get_script_instance()->has_method("_forward_canvas_force_draw_over_viewport")) {
+ get_script_instance()->call("_forward_canvas_force_draw_over_viewport", p_overlay);
}
}
@@ -586,110 +591,110 @@ int EditorPlugin::update_overlays() const {
}
bool EditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) {
- if (get_script_instance() && get_script_instance()->has_method("forward_spatial_gui_input")) {
- return get_script_instance()->call("forward_spatial_gui_input", p_camera, p_event);
+ if (get_script_instance() && get_script_instance()->has_method("_forward_spatial_gui_input")) {
+ return get_script_instance()->call("_forward_spatial_gui_input", p_camera, p_event);
}
return false;
}
void EditorPlugin::forward_spatial_draw_over_viewport(Control *p_overlay) {
- if (get_script_instance() && get_script_instance()->has_method("forward_spatial_draw_over_viewport")) {
- get_script_instance()->call("forward_spatial_draw_over_viewport", p_overlay);
+ if (get_script_instance() && get_script_instance()->has_method("_forward_spatial_draw_over_viewport")) {
+ get_script_instance()->call("_forward_spatial_draw_over_viewport", p_overlay);
}
}
void EditorPlugin::forward_spatial_force_draw_over_viewport(Control *p_overlay) {
- if (get_script_instance() && get_script_instance()->has_method("forward_spatial_force_draw_over_viewport")) {
- get_script_instance()->call("forward_spatial_force_draw_over_viewport", p_overlay);
+ if (get_script_instance() && get_script_instance()->has_method("_forward_spatial_force_draw_over_viewport")) {
+ get_script_instance()->call("_forward_spatial_force_draw_over_viewport", p_overlay);
}
}
String EditorPlugin::get_name() const {
- if (get_script_instance() && get_script_instance()->has_method("get_plugin_name")) {
- return get_script_instance()->call("get_plugin_name");
+ if (get_script_instance() && get_script_instance()->has_method("_get_plugin_name")) {
+ return get_script_instance()->call("_get_plugin_name");
}
return String();
}
const Ref<Texture2D> EditorPlugin::get_icon() const {
- if (get_script_instance() && get_script_instance()->has_method("get_plugin_icon")) {
- return get_script_instance()->call("get_plugin_icon");
+ if (get_script_instance() && get_script_instance()->has_method("_get_plugin_icon")) {
+ return get_script_instance()->call("_get_plugin_icon");
}
return Ref<Texture2D>();
}
bool EditorPlugin::has_main_screen() const {
- if (get_script_instance() && get_script_instance()->has_method("has_main_screen")) {
- return get_script_instance()->call("has_main_screen");
+ if (get_script_instance() && get_script_instance()->has_method("_has_main_screen")) {
+ return get_script_instance()->call("_has_main_screen");
}
return false;
}
void EditorPlugin::make_visible(bool p_visible) {
- if (get_script_instance() && get_script_instance()->has_method("make_visible")) {
- get_script_instance()->call("make_visible", p_visible);
+ if (get_script_instance() && get_script_instance()->has_method("_make_visible")) {
+ get_script_instance()->call("_make_visible", p_visible);
}
}
void EditorPlugin::edit(Object *p_object) {
- if (get_script_instance() && get_script_instance()->has_method("edit")) {
+ if (get_script_instance() && get_script_instance()->has_method("_edit")) {
if (p_object->is_class("Resource")) {
- get_script_instance()->call("edit", Ref<Resource>(Object::cast_to<Resource>(p_object)));
+ get_script_instance()->call("_edit", Ref<Resource>(Object::cast_to<Resource>(p_object)));
} else {
- get_script_instance()->call("edit", p_object);
+ get_script_instance()->call("_edit", p_object);
}
}
}
bool EditorPlugin::handles(Object *p_object) const {
- if (get_script_instance() && get_script_instance()->has_method("handles")) {
- return get_script_instance()->call("handles", p_object);
+ if (get_script_instance() && get_script_instance()->has_method("_handles")) {
+ return get_script_instance()->call("_handles", p_object);
}
return false;
}
Dictionary EditorPlugin::get_state() const {
- if (get_script_instance() && get_script_instance()->has_method("get_state")) {
- return get_script_instance()->call("get_state");
+ if (get_script_instance() && get_script_instance()->has_method("_get_state")) {
+ return get_script_instance()->call("_get_state");
}
return Dictionary();
}
void EditorPlugin::set_state(const Dictionary &p_state) {
- if (get_script_instance() && get_script_instance()->has_method("set_state")) {
- get_script_instance()->call("set_state", p_state);
+ if (get_script_instance() && get_script_instance()->has_method("_set_state")) {
+ get_script_instance()->call("_set_state", p_state);
}
}
void EditorPlugin::clear() {
- if (get_script_instance() && get_script_instance()->has_method("clear")) {
- get_script_instance()->call("clear");
+ if (get_script_instance() && get_script_instance()->has_method("_clear")) {
+ get_script_instance()->call("_clear");
}
}
// if editor references external resources/scenes, save them
void EditorPlugin::save_external_data() {
- if (get_script_instance() && get_script_instance()->has_method("save_external_data")) {
- get_script_instance()->call("save_external_data");
+ if (get_script_instance() && get_script_instance()->has_method("_save_external_data")) {
+ get_script_instance()->call("_save_external_data");
}
}
// if changes are pending in editor, apply them
void EditorPlugin::apply_changes() {
- if (get_script_instance() && get_script_instance()->has_method("apply_changes")) {
- get_script_instance()->call("apply_changes");
+ if (get_script_instance() && get_script_instance()->has_method("_apply_changes")) {
+ get_script_instance()->call("_apply_changes");
}
}
void EditorPlugin::get_breakpoints(List<String> *p_breakpoints) {
- if (get_script_instance() && get_script_instance()->has_method("get_breakpoints")) {
- PackedStringArray arr = get_script_instance()->call("get_breakpoints");
+ if (get_script_instance() && get_script_instance()->has_method("_get_breakpoints")) {
+ PackedStringArray arr = get_script_instance()->call("_get_breakpoints");
for (int i = 0; i < arr.size(); i++) {
p_breakpoints->push_back(arr[i]);
}
@@ -712,52 +717,64 @@ void EditorPlugin::remove_undo_redo_inspector_hook_callback(Callable p_callable)
}
void EditorPlugin::add_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser) {
+ ERR_FAIL_COND(!p_parser.is_valid());
EditorTranslationParser::get_singleton()->add_parser(p_parser, EditorTranslationParser::CUSTOM);
}
void EditorPlugin::remove_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser) {
+ ERR_FAIL_COND(!p_parser.is_valid());
EditorTranslationParser::get_singleton()->remove_parser(p_parser, EditorTranslationParser::CUSTOM);
}
void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer) {
+ ERR_FAIL_COND(!p_importer.is_valid());
ResourceFormatImporter::get_singleton()->add_importer(p_importer);
EditorFileSystem::get_singleton()->call_deferred("scan");
}
void EditorPlugin::remove_import_plugin(const Ref<EditorImportPlugin> &p_importer) {
+ ERR_FAIL_COND(!p_importer.is_valid());
ResourceFormatImporter::get_singleton()->remove_importer(p_importer);
EditorFileSystem::get_singleton()->call_deferred("scan");
}
void EditorPlugin::add_export_plugin(const Ref<EditorExportPlugin> &p_exporter) {
+ ERR_FAIL_COND(!p_exporter.is_valid());
EditorExport::get_singleton()->add_export_plugin(p_exporter);
}
void EditorPlugin::remove_export_plugin(const Ref<EditorExportPlugin> &p_exporter) {
+ ERR_FAIL_COND(!p_exporter.is_valid());
EditorExport::get_singleton()->remove_export_plugin(p_exporter);
}
void EditorPlugin::add_spatial_gizmo_plugin(const Ref<EditorNode3DGizmoPlugin> &p_gizmo_plugin) {
+ ERR_FAIL_COND(!p_gizmo_plugin.is_valid());
Node3DEditor::get_singleton()->add_gizmo_plugin(p_gizmo_plugin);
}
void EditorPlugin::remove_spatial_gizmo_plugin(const Ref<EditorNode3DGizmoPlugin> &p_gizmo_plugin) {
+ ERR_FAIL_COND(!p_gizmo_plugin.is_valid());
Node3DEditor::get_singleton()->remove_gizmo_plugin(p_gizmo_plugin);
}
void EditorPlugin::add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) {
+ ERR_FAIL_COND(!p_plugin.is_valid());
EditorInspector::add_inspector_plugin(p_plugin);
}
void EditorPlugin::remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) {
+ ERR_FAIL_COND(!p_plugin.is_valid());
EditorInspector::remove_inspector_plugin(p_plugin);
}
void EditorPlugin::add_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) {
+ ERR_FAIL_COND(!p_importer.is_valid());
ResourceImporterScene::get_singleton()->add_importer(p_importer);
}
void EditorPlugin::remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) {
+ ERR_FAIL_COND(!p_importer.is_valid());
ResourceImporterScene::get_singleton()->remove_importer(p_importer);
}
@@ -774,8 +791,8 @@ int find(const PackedStringArray &a, const String &v) {
void EditorPlugin::enable_plugin() {
// Called when the plugin gets enabled in project settings, after it's added to the tree.
// You can implement it to register autoloads.
- if (get_script_instance() && get_script_instance()->has_method("enable_plugin")) {
- get_script_instance()->call("enable_plugin");
+ if (get_script_instance() && get_script_instance()->has_method("_enable_plugin")) {
+ get_script_instance()->call("_enable_plugin");
}
}
@@ -783,26 +800,26 @@ void EditorPlugin::disable_plugin() {
// Last function called when the plugin gets disabled in project settings.
// Implement it to cleanup things from the project, such as unregister autoloads.
- if (get_script_instance() && get_script_instance()->has_method("disable_plugin")) {
- get_script_instance()->call("disable_plugin");
+ if (get_script_instance() && get_script_instance()->has_method("_disable_plugin")) {
+ get_script_instance()->call("_disable_plugin");
}
}
void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
- if (get_script_instance() && get_script_instance()->has_method("set_window_layout")) {
- get_script_instance()->call("set_window_layout", p_layout);
+ if (get_script_instance() && get_script_instance()->has_method("_set_window_layout")) {
+ get_script_instance()->call("_set_window_layout", p_layout);
}
}
void EditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) {
- if (get_script_instance() && get_script_instance()->has_method("get_window_layout")) {
- get_script_instance()->call("get_window_layout", p_layout);
+ if (get_script_instance() && get_script_instance()->has_method("_get_window_layout")) {
+ get_script_instance()->call("_get_window_layout", p_layout);
}
}
bool EditorPlugin::build() {
- if (get_script_instance() && get_script_instance()->has_method("build")) {
- return get_script_instance()->call("build");
+ if (get_script_instance() && get_script_instance()->has_method("_build")) {
+ return get_script_instance()->call("_build");
}
return true;
@@ -893,29 +910,29 @@ void EditorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_debugger_plugin", "script"), &EditorPlugin::add_debugger_plugin);
ClassDB::bind_method(D_METHOD("remove_debugger_plugin", "script"), &EditorPlugin::remove_debugger_plugin);
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_canvas_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_spatial_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_spatial_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_plugin_name"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "get_plugin_icon"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "has_main_screen"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("make_visible", PropertyInfo(Variant::BOOL, "visible")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("edit", PropertyInfo(Variant::OBJECT, "object")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles", PropertyInfo(Variant::OBJECT, "object")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::DICTIONARY, "get_state"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("set_state", PropertyInfo(Variant::DICTIONARY, "state")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("clear"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("save_external_data"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("apply_changes"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::PACKED_STRING_ARRAY, "get_breakpoints"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("set_window_layout", PropertyInfo(Variant::OBJECT, "layout", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_window_layout", PropertyInfo(Variant::OBJECT, "layout", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "build"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("enable_plugin"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("disable_plugin"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_forward_canvas_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
+ BIND_VMETHOD(MethodInfo("_forward_canvas_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
+ BIND_VMETHOD(MethodInfo("_forward_canvas_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
+ BIND_VMETHOD(MethodInfo("_forward_spatial_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
+ BIND_VMETHOD(MethodInfo("_forward_spatial_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_plugin_name"));
+ BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "_get_plugin_icon"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_main_screen"));
+ BIND_VMETHOD(MethodInfo("_make_visible", PropertyInfo(Variant::BOOL, "visible")));
+ BIND_VMETHOD(MethodInfo("_edit", PropertyInfo(Variant::OBJECT, "object")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_handles", PropertyInfo(Variant::OBJECT, "object")));
+ BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "_get_state"));
+ BIND_VMETHOD(MethodInfo("_set_state", PropertyInfo(Variant::DICTIONARY, "state")));
+ BIND_VMETHOD(MethodInfo("_clear"));
+ BIND_VMETHOD(MethodInfo("_save_external_data"));
+ BIND_VMETHOD(MethodInfo("_apply_changes"));
+ BIND_VMETHOD(MethodInfo(Variant::PACKED_STRING_ARRAY, "_get_breakpoints"));
+ BIND_VMETHOD(MethodInfo("_set_window_layout", PropertyInfo(Variant::OBJECT, "layout", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile")));
+ BIND_VMETHOD(MethodInfo("_get_window_layout", PropertyInfo(Variant::OBJECT, "layout", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_build"));
+ BIND_VMETHOD(MethodInfo("_enable_plugin"));
+ BIND_VMETHOD(MethodInfo("_disable_plugin"));
ADD_SIGNAL(MethodInfo("scene_changed", PropertyInfo(Variant::OBJECT, "scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("scene_closed", PropertyInfo(Variant::STRING, "filepath")));
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 37412e5ebe..2e1dd0a0c1 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -54,6 +54,7 @@ class EditorNode3DGizmoPlugin;
class EditorResourcePreview;
class EditorFileSystem;
class EditorToolAddons;
+class EditorPaths;
class FileSystemDock;
class ScriptEditor;
@@ -95,6 +96,7 @@ public:
EditorSelection *get_selection();
//EditorImportExport *get_import_export();
Ref<EditorSettings> get_editor_settings();
+ EditorPaths *get_editor_paths();
EditorResourcePreview *get_resource_previewer();
EditorFileSystem *get_resource_file_system();
@@ -111,7 +113,7 @@ public:
Error save_scene();
void save_scene_as(const String &p_scene, bool p_with_preview = true);
- Vector<Ref<Texture2D>> make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform> *p_transforms, int p_preview_size);
+ Vector<Ref<Texture2D>> make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size);
void set_main_screen_editor(const String &p_name);
void set_distraction_free_mode(bool p_enter);
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index e5b62513ff..1db24bb908 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -32,7 +32,7 @@
#include "core/config/project_settings.h"
#include "core/io/config_file.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/main_loop.h"
#include "editor_node.h"
#include "editor_scale.h"
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index ee55ec4c0b..fd3cf662a9 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -994,9 +994,8 @@ void EditorPropertyEasing::_draw_easing() {
Size2 s = easing_draw->get_size();
- const int points = 48;
+ const int point_count = 48;
- float prev = 1.0;
const float exp = get_edited_object()->get(get_edited_property());
const Ref<Font> f = get_theme_font("font", "Label");
@@ -1009,24 +1008,20 @@ void EditorPropertyEasing::_draw_easing() {
line_color = get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.9);
}
- Vector<Point2> lines;
- for (int i = 1; i <= points; i++) {
- float ifl = i / float(points);
- float iflp = (i - 1) / float(points);
+ Vector<Point2> points;
+ for (int i = 0; i <= point_count; i++) {
+ float ifl = i / float(point_count);
const float h = 1.0 - Math::ease(ifl, exp);
if (flip) {
ifl = 1.0 - ifl;
- iflp = 1.0 - iflp;
}
- lines.push_back(Point2(ifl * s.width, h * s.height));
- lines.push_back(Point2(iflp * s.width, prev * s.height));
- prev = h;
+ points.push_back(Point2(ifl * s.width, h * s.height));
}
- easing_draw->draw_multiline(lines, line_color, 1.0);
+ easing_draw->draw_polyline(points, line_color, 1.0, true);
// Draw more decimals for small numbers since higher precision is usually required for fine adjustments.
int decimals;
if (Math::abs(exp) < 0.1 - CMP_EPSILON) {
@@ -1761,14 +1756,14 @@ EditorPropertyPlane::EditorPropertyPlane(bool p_force_wide) {
setting = false;
}
-///////////////////// QUAT /////////////////////////
+///////////////////// QUATERNION /////////////////////////
-void EditorPropertyQuat::_value_changed(double val, const String &p_name) {
+void EditorPropertyQuaternion::_value_changed(double val, const String &p_name) {
if (setting) {
return;
}
- Quat p;
+ Quaternion p;
p.x = spin[0]->get_value();
p.y = spin[1]->get_value();
p.z = spin[2]->get_value();
@@ -1776,8 +1771,8 @@ void EditorPropertyQuat::_value_changed(double val, const String &p_name) {
emit_changed(get_edited_property(), p, p_name);
}
-void EditorPropertyQuat::update_property() {
- Quat val = get_edited_object()->get(get_edited_property());
+void EditorPropertyQuaternion::update_property() {
+ Quaternion val = get_edited_object()->get(get_edited_property());
setting = true;
spin[0]->set_value(val.x);
spin[1]->set_value(val.y);
@@ -1786,7 +1781,7 @@ void EditorPropertyQuat::update_property() {
setting = false;
}
-void EditorPropertyQuat::_notification(int p_what) {
+void EditorPropertyQuaternion::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
Color base = get_theme_color("accent_color", "Editor");
for (int i = 0; i < 3; i++) {
@@ -1797,10 +1792,10 @@ void EditorPropertyQuat::_notification(int p_what) {
}
}
-void EditorPropertyQuat::_bind_methods() {
+void EditorPropertyQuaternion::_bind_methods() {
}
-void EditorPropertyQuat::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyQuaternion::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
for (int i = 0; i < 4; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1811,7 +1806,7 @@ void EditorPropertyQuat::setup(double p_min, double p_max, double p_step, bool p
}
}
-EditorPropertyQuat::EditorPropertyQuat() {
+EditorPropertyQuaternion::EditorPropertyQuaternion() {
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
BoxContainer *bc;
@@ -1832,7 +1827,7 @@ EditorPropertyQuat::EditorPropertyQuat() {
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyQuat::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyQuaternion::_value_changed), varray(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -2078,12 +2073,12 @@ EditorPropertyBasis::EditorPropertyBasis() {
///////////////////// TRANSFORM /////////////////////////
-void EditorPropertyTransform::_value_changed(double val, const String &p_name) {
+void EditorPropertyTransform3D::_value_changed(double val, const String &p_name) {
if (setting) {
return;
}
- Transform p;
+ Transform3D p;
p.basis[0][0] = spin[0]->get_value();
p.basis[1][0] = spin[1]->get_value();
p.basis[2][0] = spin[2]->get_value();
@@ -2100,11 +2095,11 @@ void EditorPropertyTransform::_value_changed(double val, const String &p_name) {
emit_changed(get_edited_property(), p, p_name);
}
-void EditorPropertyTransform::update_property() {
+void EditorPropertyTransform3D::update_property() {
update_using_transform(get_edited_object()->get(get_edited_property()));
}
-void EditorPropertyTransform::update_using_transform(Transform p_transform) {
+void EditorPropertyTransform3D::update_using_transform(Transform3D p_transform) {
setting = true;
spin[0]->set_value(p_transform.basis[0][0]);
spin[1]->set_value(p_transform.basis[1][0]);
@@ -2121,7 +2116,7 @@ void EditorPropertyTransform::update_using_transform(Transform p_transform) {
setting = false;
}
-void EditorPropertyTransform::_notification(int p_what) {
+void EditorPropertyTransform3D::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
Color base = get_theme_color("accent_color", "Editor");
for (int i = 0; i < 12; i++) {
@@ -2132,10 +2127,10 @@ void EditorPropertyTransform::_notification(int p_what) {
}
}
-void EditorPropertyTransform::_bind_methods() {
+void EditorPropertyTransform3D::_bind_methods() {
}
-void EditorPropertyTransform::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyTransform3D::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
for (int i = 0; i < 12; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -2146,7 +2141,7 @@ void EditorPropertyTransform::setup(double p_min, double p_max, double p_step, b
}
}
-EditorPropertyTransform::EditorPropertyTransform() {
+EditorPropertyTransform3D::EditorPropertyTransform3D() {
GridContainer *g = memnew(GridContainer);
g->set_columns(3);
add_child(g);
@@ -2159,7 +2154,7 @@ EditorPropertyTransform::EditorPropertyTransform() {
g->add_child(spin[i]);
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform3D::_value_changed), varray(desc[i]));
}
set_bottom_editor(g);
setting = false;
@@ -2261,7 +2256,7 @@ void EditorPropertyNodePath::_node_selected(const NodePath &p_path) {
base_node = get_edited_object()->call("get_root_path");
}
- if (!base_node && Object::cast_to<Reference>(get_edited_object())) {
+ if (!base_node && Object::cast_to<RefCounted>(get_edited_object())) {
Node *to_node = get_node(p_path);
ERR_FAIL_COND(!to_node);
path = get_tree()->get_edited_scene_root()->get_path_to(to_node);
@@ -2384,426 +2379,64 @@ EditorPropertyRID::EditorPropertyRID() {
////////////// RESOURCE //////////////////////
-void EditorPropertyResource::_file_selected(const String &p_path) {
- RES res = ResourceLoader::load(p_path);
-
- ERR_FAIL_COND_MSG(res.is_null(), "Cannot load resource from path '" + p_path + "'.");
-
- List<PropertyInfo> prop_list;
- get_edited_object()->get_property_list(&prop_list);
- String property_types;
-
- for (List<PropertyInfo>::Element *E = prop_list.front(); E; E = E->next()) {
- if (E->get().name == get_edited_property() && (E->get().hint & PROPERTY_HINT_RESOURCE_TYPE)) {
- property_types = E->get().hint_string;
- }
- }
- if (!property_types.is_empty()) {
- bool any_type_matches = false;
- const Vector<String> split_property_types = property_types.split(",");
- for (int i = 0; i < split_property_types.size(); ++i) {
- if (res->is_class(split_property_types[i])) {
- any_type_matches = true;
- break;
- }
- }
-
- if (!any_type_matches) {
- EditorNode::get_singleton()->show_warning(vformat(TTR("The selected resource (%s) does not match any type expected for this property (%s)."), res->get_class(), property_types));
- }
+void EditorPropertyResource::_resource_selected(const RES &p_resource) {
+ if (use_sub_inspector) {
+ bool unfold = !get_edited_object()->editor_is_section_unfolded(get_edited_property());
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), unfold);
+ update_property();
+ } else {
+ emit_signal("resource_selected", get_edited_property(), p_resource);
}
-
- emit_changed(get_edited_property(), res);
- update_property();
}
-void EditorPropertyResource::_menu_option(int p_which) {
- //scene_tree->popup_scenetree_dialog();
- switch (p_which) {
- case OBJ_MENU_LOAD: {
- if (!file) {
- file = memnew(EditorFileDialog);
- file->connect("file_selected", callable_mp(this, &EditorPropertyResource::_file_selected));
- add_child(file);
- }
- file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
- String type = base_type;
-
- List<String> extensions;
- for (int i = 0; i < type.get_slice_count(","); i++) {
- ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",", i), &extensions);
- }
-
- Set<String> valid_extensions;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- valid_extensions.insert(E->get());
- }
-
- file->clear_filters();
- for (Set<String>::Element *E = valid_extensions.front(); E; E = E->next()) {
- file->add_filter("*." + E->get() + " ; " + E->get().to_upper());
- }
-
- file->popup_file_dialog();
- } break;
-
- case OBJ_MENU_EDIT: {
- RES res = get_edited_object()->get(get_edited_property());
+void EditorPropertyResource::_resource_changed(const RES &p_resource) {
+ // Make visual script the correct type.
+ Ref<Script> s = p_resource;
+ if (get_edited_object() && s.is_valid()) {
+ s->call("set_instance_base_type", get_edited_object()->get_class());
+ }
- if (!res.is_null()) {
- emit_signal("resource_selected", get_edited_property(), res);
- }
- } break;
- case OBJ_MENU_CLEAR: {
+ // Prevent the creation of invalid ViewportTextures when possible.
+ Ref<ViewportTexture> vpt = p_resource;
+ if (vpt.is_valid()) {
+ Resource *r = Object::cast_to<Resource>(get_edited_object());
+ if (r && r->get_path().is_resource_file()) {
+ EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on resources saved as a file.\nResource needs to belong to a scene."));
emit_changed(get_edited_property(), RES());
update_property();
-
- } break;
-
- case OBJ_MENU_MAKE_UNIQUE: {
- RES res_orig = get_edited_object()->get(get_edited_property());
- if (res_orig.is_null()) {
- return;
- }
-
- List<PropertyInfo> property_list;
- res_orig->get_property_list(&property_list);
- List<Pair<String, Variant>> propvalues;
-
- for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
- Pair<String, Variant> p;
- PropertyInfo &pi = E->get();
- if (pi.usage & PROPERTY_USAGE_STORAGE) {
- p.first = pi.name;
- p.second = res_orig->get(pi.name);
- }
-
- propvalues.push_back(p);
- }
-
- String orig_type = res_orig->get_class();
-
- Object *inst = ClassDB::instance(orig_type);
-
- Ref<Resource> res = Ref<Resource>(Object::cast_to<Resource>(inst));
-
- ERR_FAIL_COND(res.is_null());
-
- for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) {
- Pair<String, Variant> &p = E->get();
- res->set(p.first, p.second);
- }
-
- emit_changed(get_edited_property(), res);
- update_property();
-
- } break;
-
- case OBJ_MENU_SAVE: {
- RES res = get_edited_object()->get(get_edited_property());
- if (res.is_null()) {
- return;
- }
- EditorNode::get_singleton()->save_resource(res);
- } break;
-
- case OBJ_MENU_COPY: {
- RES res = get_edited_object()->get(get_edited_property());
-
- EditorSettings::get_singleton()->set_resource_clipboard(res);
-
- } break;
- case OBJ_MENU_PASTE: {
- RES res = EditorSettings::get_singleton()->get_resource_clipboard();
- emit_changed(get_edited_property(), res);
- update_property();
-
- } break;
- case OBJ_MENU_NEW_SCRIPT: {
- if (Object::cast_to<Node>(get_edited_object())) {
- EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object()), false);
- }
-
- } break;
- case OBJ_MENU_EXTEND_SCRIPT: {
- if (Object::cast_to<Node>(get_edited_object())) {
- EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object()), true);
- }
-
- } break;
- case OBJ_MENU_SHOW_IN_FILE_SYSTEM: {
- RES res = get_edited_object()->get(get_edited_property());
-
- FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock();
- file_system_dock->navigate_to_path(res->get_path());
- // Ensure that the FileSystem dock is visible.
- TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control();
- tab_container->set_current_tab(file_system_dock->get_index());
- } break;
- default: {
- RES res = get_edited_object()->get(get_edited_property());
-
- if (p_which >= CONVERT_BASE_ID) {
- int to_type = p_which - CONVERT_BASE_ID;
-
- Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(res);
-
- ERR_FAIL_INDEX(to_type, conversions.size());
-
- Ref<Resource> new_res = conversions[to_type]->convert(res);
-
- emit_changed(get_edited_property(), new_res);
- update_property();
- break;
- }
- ERR_FAIL_COND(inheritors_array.is_empty());
-
- String intype = inheritors_array[p_which - TYPE_BASE_ID];
-
- if (intype == "ViewportTexture") {
- Resource *r = Object::cast_to<Resource>(get_edited_object());
- if (r && r->get_path().is_resource_file()) {
- EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on resources saved as a file.\nResource needs to belong to a scene."));
- return;
- }
-
- if (r && !r->is_local_to_scene()) {
- EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on this resource because it's not set as local to scene.\nPlease switch on the 'local to scene' property on it (and all resources containing it up to a node)."));
- return;
- }
-
- if (!scene_tree) {
- scene_tree = memnew(SceneTreeDialog);
- Vector<StringName> valid_types;
- valid_types.push_back("Viewport");
- scene_tree->get_scene_tree()->set_valid_types(valid_types);
- scene_tree->get_scene_tree()->set_show_enabled_subscene(true);
- add_child(scene_tree);
- scene_tree->connect("selected", callable_mp(this, &EditorPropertyResource::_viewport_selected));
- scene_tree->set_title(TTR("Pick a Viewport"));
- }
- scene_tree->popup_scenetree_dialog();
-
- return;
- }
-
- Variant obj;
-
- if (ScriptServer::is_global_class(intype)) {
- obj = ClassDB::instance(ScriptServer::get_global_class_native_base(intype));
- if (obj) {
- Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(intype));
- if (script.is_valid()) {
- ((Object *)obj)->set_script(script);
- }
- }
- } else {
- obj = ClassDB::instance(intype);
- }
-
- if (!obj) {
- obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
- }
-
- Resource *resp = Object::cast_to<Resource>(obj);
- ERR_BREAK(!resp);
- if (get_edited_object() && base_type != String() && base_type == "Script") {
- //make visual script the right type
- resp->call("set_instance_base_type", get_edited_object()->get_class());
- }
-
- res = RES(resp);
- emit_changed(get_edited_property(), res);
- update_property();
-
- } break;
- }
-}
-
-void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj) {
- RES p = get_edited_object()->get(get_edited_property());
- if (p.is_valid() && p->get_instance_id() == p_obj) {
- String type = p->get_class_name();
-
- if (ClassDB::is_parent_class(type, "Script")) {
- assign->set_text(p->get_path().get_file());
return;
}
- if (p_preview.is_valid()) {
- preview->set_offset(SIDE_LEFT, assign->get_icon()->get_width() + assign->get_theme_stylebox("normal")->get_default_margin(SIDE_LEFT) + get_theme_constant("hseparation", "Button"));
- if (type == "GradientTexture") {
- preview->set_stretch_mode(TextureRect::STRETCH_SCALE);
- assign->set_custom_minimum_size(Size2(1, 1));
- } else {
- preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
- assign->set_custom_minimum_size(Size2(1, thumbnail_size));
- }
- preview->set_texture(p_preview);
- assign->set_text("");
- }
- }
-}
-
-void EditorPropertyResource::_update_menu_items() {
- //////////////////// UPDATE MENU //////////////////////////
- RES res = get_edited_object()->get(get_edited_property());
-
- menu->clear();
-
- if (get_edited_property() == "script" && base_type == "Script" && Object::cast_to<Node>(get_edited_object())) {
- menu->add_icon_item(get_theme_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT);
- menu->add_icon_item(get_theme_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT);
- menu->add_separator();
- } else if (base_type != "") {
- int idx = 0;
-
- Vector<EditorData::CustomType> custom_resources;
-
- if (EditorNode::get_editor_data().get_custom_types().has("Resource")) {
- custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"];
- }
-
- for (int i = 0; i < base_type.get_slice_count(","); i++) {
- String base = base_type.get_slice(",", i);
-
- Set<String> valid_inheritors;
- valid_inheritors.insert(base);
- List<StringName> inheritors;
- ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors);
-
- for (int j = 0; j < custom_resources.size(); j++) {
- inheritors.push_back(custom_resources[j].name);
- }
-
- List<StringName>::Element *E = inheritors.front();
- while (E) {
- valid_inheritors.insert(E->get());
- E = E->next();
- }
-
- List<StringName> global_classes;
- ScriptServer::get_global_class_list(&global_classes);
- E = global_classes.front();
- while (E) {
- if (EditorNode::get_editor_data().script_class_is_parent(E->get(), base_type)) {
- valid_inheritors.insert(E->get());
- }
- E = E->next();
- }
-
- for (Set<String>::Element *F = valid_inheritors.front(); F; F = F->next()) {
- const String &t = F->get();
-
- bool is_custom_resource = false;
- Ref<Texture2D> icon;
- if (!custom_resources.is_empty()) {
- for (int j = 0; j < custom_resources.size(); j++) {
- if (custom_resources[j].name == t) {
- is_custom_resource = true;
- if (custom_resources[j].icon.is_valid()) {
- icon = custom_resources[j].icon;
- }
- break;
- }
- }
- }
-
- if (!is_custom_resource && !(ScriptServer::is_global_class(t) || ClassDB::can_instance(t))) {
- continue;
- }
-
- inheritors_array.push_back(t);
-
- if (!icon.is_valid()) {
- icon = get_theme_icon(has_theme_icon(t, "EditorIcons") ? t : "Object", "EditorIcons");
- }
-
- int id = TYPE_BASE_ID + idx;
- menu->add_icon_item(icon, vformat(TTR("New %s"), t), id);
-
- idx++;
- }
- }
-
- if (menu->get_item_count()) {
- menu->add_separator();
- }
- }
-
- menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD);
-
- if (!res.is_null()) {
- menu->add_icon_item(get_theme_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT);
- menu->add_icon_item(get_theme_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR);
- menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
- menu->add_icon_item(get_theme_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE);
- RES r = res;
- if (r.is_valid() && r->get_path().is_resource_file()) {
- menu->add_separator();
- menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM);
- }
- }
-
- RES cb = EditorSettings::get_singleton()->get_resource_clipboard();
- bool paste_valid = false;
- if (cb.is_valid()) {
- if (base_type == "") {
- paste_valid = true;
- } else {
- for (int i = 0; i < base_type.get_slice_count(","); i++) {
- if (ClassDB::is_parent_class(cb->get_class(), base_type.get_slice(",", i))) {
- paste_valid = true;
- break;
- }
- }
+ if (r && !r->is_local_to_scene()) {
+ EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on this resource because it's not set as local to scene.\nPlease switch on the 'local to scene' property on it (and all resources containing it up to a node)."));
+ emit_changed(get_edited_property(), RES());
+ update_property();
+ return;
}
}
- if (!res.is_null() || paste_valid) {
- menu->add_separator();
+ emit_changed(get_edited_property(), p_resource);
+ update_property();
- if (!res.is_null()) {
- menu->add_item(TTR("Copy"), OBJ_MENU_COPY);
- }
+ // Automatically suggest setting up the path for a ViewportTexture.
+ if (vpt.is_valid() && vpt->get_viewport_path_in_scene().is_empty()) {
+ if (!scene_tree) {
+ scene_tree = memnew(SceneTreeDialog);
+ scene_tree->set_title(TTR("Pick a Viewport"));
- if (paste_valid) {
- menu->add_item(TTR("Paste"), OBJ_MENU_PASTE);
- }
- }
+ Vector<StringName> valid_types;
+ valid_types.push_back("Viewport");
+ scene_tree->get_scene_tree()->set_valid_types(valid_types);
+ scene_tree->get_scene_tree()->set_show_enabled_subscene(true);
- if (!res.is_null()) {
- Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(res);
- if (conversions.size()) {
- menu->add_separator();
+ add_child(scene_tree);
+ scene_tree->connect("selected", callable_mp(this, &EditorPropertyResource::_viewport_selected));
}
- for (int i = 0; i < conversions.size(); i++) {
- String what = conversions[i]->converts_to();
- Ref<Texture2D> icon;
- if (has_theme_icon(what, "EditorIcons")) {
- icon = get_theme_icon(what, "EditorIcons");
- } else {
- icon = get_theme_icon(what, "Resource");
- }
- menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i);
- }
+ scene_tree->popup_scenetree_dialog();
}
}
-void EditorPropertyResource::_update_menu() {
- _update_menu_items();
-
- Rect2 gt = edit->get_screen_rect();
- menu->set_as_minsize();
- int ms = menu->get_contents_minimum_size().width;
- Vector2 popup_pos = gt.position + gt.size - Vector2(ms, 0);
- menu->set_position(popup_pos);
- menu->popup();
-}
-
void EditorPropertyResource::_sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool) {
emit_signal("property_keyed_with_value", String(get_edited_property()) + ":" + p_property, p_value, false);
}
@@ -2816,24 +2449,11 @@ void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) {
emit_signal("object_id_selected", get_edited_property(), p_id);
}
-void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) {
- Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
- _update_menu_items();
- Vector2 pos = get_screen_position() + mb->get_position();
- //pos = assign->get_global_transform().xform(pos);
- menu->set_as_minsize();
- menu->set_position(pos);
- menu->popup();
- }
- }
-}
-
void EditorPropertyResource::_open_editor_pressed() {
RES res = get_edited_object()->get(get_edited_property());
if (res.is_valid()) {
- EditorNode::get_singleton()->call_deferred("edit_item_resource", res); //may clear the editor so do it deferred
+ // May clear the editor so do it deferred.
+ EditorNode::get_singleton()->call_deferred("edit_item_resource", res);
}
}
@@ -2843,28 +2463,28 @@ void EditorPropertyResource::_fold_other_editors(Object *p_self) {
}
RES res = get_edited_object()->get(get_edited_property());
-
if (!res.is_valid()) {
return;
}
+
bool use_editor = false;
for (int i = 0; i < EditorNode::get_editor_data().get_editor_plugin_count(); i++) {
EditorPlugin *ep = EditorNode::get_editor_data().get_editor_plugin(i);
if (ep->handles(res.ptr())) {
use_editor = true;
+ break;
}
}
-
if (!use_editor) {
return;
}
- bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
opened_editor = false;
+ bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
if (unfolded) {
- //refold
- assign->set_pressed(false);
+ // Refold.
+ resource_picker->set_toggle_pressed(false);
get_edited_object()->editor_set_section_unfold(get_edited_property(), false);
update_property();
}
@@ -2876,6 +2496,7 @@ void EditorPropertyResource::_update_property_bg() {
}
updating_theme = true;
+
if (sub_inspector != nullptr) {
int count_subinspectors = 0;
Node *n = get_parent();
@@ -2905,12 +2526,60 @@ void EditorPropertyResource::_update_property_bg() {
updating_theme = false;
update();
}
+
+void EditorPropertyResource::_viewport_selected(const NodePath &p_path) {
+ Node *to_node = get_node(p_path);
+ if (!Object::cast_to<Viewport>(to_node)) {
+ EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!"));
+ return;
+ }
+
+ Ref<ViewportTexture> vt;
+ vt.instance();
+ vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node));
+ vt->setup_local_to_scene();
+
+ emit_changed(get_edited_property(), vt);
+ update_property();
+}
+
+void EditorPropertyResource::setup(Object *p_object, const String &p_path, const String &p_base_type) {
+ if (resource_picker) {
+ resource_picker->disconnect("resource_selected", callable_mp(this, &EditorPropertyResource::_resource_selected));
+ resource_picker->disconnect("resource_changed", callable_mp(this, &EditorPropertyResource::_resource_changed));
+ memdelete(resource_picker);
+ }
+
+ if (p_path == "script" && p_base_type == "Script" && Object::cast_to<Node>(p_object)) {
+ EditorScriptPicker *script_picker = memnew(EditorScriptPicker);
+ script_picker->set_script_owner(Object::cast_to<Node>(p_object));
+ resource_picker = script_picker;
+ } else {
+ resource_picker = memnew(EditorResourcePicker);
+ }
+
+ resource_picker->set_base_type(p_base_type);
+ resource_picker->set_editable(true);
+ resource_picker->set_h_size_flags(SIZE_EXPAND_FILL);
+ add_child(resource_picker);
+
+ resource_picker->connect("resource_selected", callable_mp(this, &EditorPropertyResource::_resource_selected));
+ resource_picker->connect("resource_changed", callable_mp(this, &EditorPropertyResource::_resource_changed));
+
+ for (int i = 0; i < resource_picker->get_child_count(); i++) {
+ Button *b = Object::cast_to<Button>(resource_picker->get_child(i));
+ if (b) {
+ add_focusable(b);
+ }
+ }
+}
+
void EditorPropertyResource::update_property() {
RES res = get_edited_object()->get(get_edited_property());
if (use_sub_inspector) {
- if (res.is_valid() != assign->is_toggle_mode()) {
- assign->set_toggle_mode(res.is_valid());
+ if (res.is_valid() != resource_picker->is_toggle_mode()) {
+ resource_picker->set_toggle_mode(res.is_valid());
}
if (res.is_valid() && get_edited_object()->editor_is_section_unfolded(get_edited_property())) {
@@ -2935,7 +2604,7 @@ void EditorPropertyResource::update_property() {
set_bottom_editor(sub_inspector_vbox);
sub_inspector_vbox->add_child(sub_inspector);
- assign->set_pressed(true);
+ resource_picker->set_toggle_pressed(true);
bool use_editor = false;
for (int i = 0; i < EditorNode::get_editor_data().get_editor_plugin_count(); i++) {
@@ -2946,7 +2615,7 @@ void EditorPropertyResource::update_property() {
}
if (use_editor) {
- //open editor directly and hide other open of these
+ // Open editor directly and hide other such editors which are currently open.
_open_editor_pressed();
if (is_inside_tree()) {
get_tree()->call_deferred("call_group", "_editor_resource_properties", "_fold_other_editors", this);
@@ -2967,102 +2636,18 @@ void EditorPropertyResource::update_property() {
memdelete(sub_inspector_vbox);
sub_inspector = nullptr;
sub_inspector_vbox = nullptr;
+
if (opened_editor) {
EditorNode::get_singleton()->hide_top_editors();
opened_editor = false;
}
+
_update_property_bg();
}
}
}
- preview->set_texture(Ref<Texture2D>());
- if (res == RES()) {
- assign->set_icon(Ref<Texture2D>());
- assign->set_text(TTR("[empty]"));
- assign->set_custom_minimum_size(Size2(1, 1));
- } else {
- assign->set_icon(EditorNode::get_singleton()->get_object_icon(res.operator->(), "Object"));
-
- if (res->get_name() != String()) {
- assign->set_text(res->get_name());
- } else if (res->get_path().is_resource_file()) {
- assign->set_text(res->get_path().get_file());
- assign->set_tooltip(res->get_path());
- } else {
- assign->set_text(res->get_class());
- }
-
- if (res->get_path().is_resource_file()) {
- assign->set_tooltip(res->get_path());
- }
-
- //preview will override the above, so called at the end
- EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_resource_preview", res->get_instance_id());
- }
-}
-
-void EditorPropertyResource::_resource_selected() {
- RES res = get_edited_object()->get(get_edited_property());
-
- if (res.is_null()) {
- edit->set_pressed(true);
- _update_menu();
- return;
- }
-
- if (use_sub_inspector) {
- bool unfold = !get_edited_object()->editor_is_section_unfolded(get_edited_property());
- get_edited_object()->editor_set_section_unfold(get_edited_property(), unfold);
- update_property();
- } else {
- emit_signal("resource_selected", get_edited_property(), res);
- }
-}
-
-void EditorPropertyResource::setup(const String &p_base_type) {
- base_type = p_base_type;
-}
-
-void EditorPropertyResource::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- if (updating_theme) {
- return;
- }
- Ref<Texture2D> t = get_theme_icon("select_arrow", "Tree");
- edit->set_icon(t);
- _update_property_bg();
- }
-
- if (p_what == NOTIFICATION_DRAG_BEGIN) {
- if (_is_drop_valid(get_viewport()->gui_get_drag_data())) {
- dropping = true;
- assign->update();
- }
- }
-
- if (p_what == NOTIFICATION_DRAG_END) {
- if (dropping) {
- dropping = false;
- assign->update();
- }
- }
-}
-
-void EditorPropertyResource::_viewport_selected(const NodePath &p_path) {
- Node *to_node = get_node(p_path);
- if (!Object::cast_to<Viewport>(to_node)) {
- EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!"));
- return;
- }
-
- Ref<ViewportTexture> vt;
- vt.instance();
- vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node));
- vt->setup_local_to_scene();
-
- emit_changed(get_edited_property(), vt);
- update_property();
+ resource_picker->set_edited_resource(res);
}
void EditorPropertyResource::collapse_all_folding() {
@@ -3077,204 +2662,29 @@ void EditorPropertyResource::expand_all_folding() {
}
}
-void EditorPropertyResource::_button_draw() {
- if (dropping) {
- Color color = get_theme_color("accent_color", "Editor");
- assign->draw_rect(Rect2(Point2(), assign->get_size()), color, false);
- }
-}
-
-Variant EditorPropertyResource::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
- RES res = get_edited_object()->get(get_edited_property());
- if (res.is_valid()) {
- return EditorNode::get_singleton()->drag_resource(res, p_from);
- }
-
- return Variant();
-}
-
-bool EditorPropertyResource::_is_drop_valid(const Dictionary &p_drag_data) const {
- Vector<String> allowed_types = base_type.split(",");
- int size = allowed_types.size();
- for (int i = 0; i < size; i++) {
- String at = allowed_types[i].strip_edges();
- if (at == "StandardMaterial3D") {
- allowed_types.append("Texture2D");
- } else if (at == "ShaderMaterial") {
- allowed_types.append("Shader");
- } else if (at == "Font") {
- allowed_types.append("FontData");
- }
- }
-
- Dictionary drag_data = p_drag_data;
-
- Ref<Resource> res;
- if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") {
- ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]);
- res = se->get_edited_resource();
- } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
- res = drag_data["resource"];
- }
-
- if (res.is_valid()) {
- for (int i = 0; i < allowed_types.size(); i++) {
- String at = allowed_types[i].strip_edges();
- if (ClassDB::is_parent_class(res->get_class(), at)) {
- return true;
- }
- }
- }
-
- if (drag_data.has("type") && String(drag_data["type"]) == "files") {
- Vector<String> files = drag_data["files"];
-
- if (files.size() == 1) {
- String file = files[0];
- String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
-
- if (ftype != "") {
- for (int i = 0; i < allowed_types.size(); i++) {
- String at = allowed_types[i].strip_edges();
- if (ClassDB::is_parent_class(ftype, at)) {
- return true;
- }
- }
- }
- }
- }
-
- return false;
-}
-
-bool EditorPropertyResource::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
- return _is_drop_valid(p_data);
+void EditorPropertyResource::set_use_sub_inspector(bool p_enable) {
+ use_sub_inspector = p_enable;
}
-void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
- ERR_FAIL_COND(!_is_drop_valid(p_data));
-
- Dictionary drag_data = p_data;
-
- Ref<Resource> res;
- if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") {
- ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]);
- res = se->get_edited_resource();
- } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
- res = drag_data["resource"];
- }
-
- if (!res.is_valid() && drag_data.has("type") && String(drag_data["type"]) == "files") {
- Vector<String> files = drag_data["files"];
-
- if (files.size() == 1) {
- String file = files[0];
- res = ResourceLoader::load(file);
- }
- }
-
- if (res.is_valid()) {
- bool need_convert = true;
-
- Vector<String> allowed_types = base_type.split(",");
- for (int i = 0; i < allowed_types.size(); i++) {
- String at = allowed_types[i].strip_edges();
- if (ClassDB::is_parent_class(res->get_class(), at)) {
- need_convert = false;
- break;
- }
- }
-
- if (need_convert) {
- for (int i = 0; i < allowed_types.size(); i++) {
- String at = allowed_types[i].strip_edges();
- if (at == "StandardMaterial3D" && ClassDB::is_parent_class(res->get_class(), "Texture2D")) {
- Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D);
- mat->set_texture(StandardMaterial3D::TextureParam::TEXTURE_ALBEDO, res);
- res = mat;
- break;
- }
-
- if (at == "ShaderMaterial" && ClassDB::is_parent_class(res->get_class(), "Shader")) {
- Ref<ShaderMaterial> mat = memnew(ShaderMaterial);
- mat->set_shader(res);
- res = mat;
- break;
- }
-
- if (at == "Font" && ClassDB::is_parent_class(res->get_class(), "FontData")) {
- Ref<Font> font = memnew(Font);
- font->add_data(res);
- res = font;
- break;
- }
+void EditorPropertyResource::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ if (!updating_theme) {
+ _update_property_bg();
}
- }
-
- emit_changed(get_edited_property(), res);
- update_property();
- return;
+ } break;
}
}
-void EditorPropertyResource::set_use_sub_inspector(bool p_enable) {
- use_sub_inspector = p_enable;
-}
-
void EditorPropertyResource::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_resource_preview"), &EditorPropertyResource::_resource_preview);
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &EditorPropertyResource::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &EditorPropertyResource::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyResource::drop_data_fw);
ClassDB::bind_method(D_METHOD("_open_editor_pressed"), &EditorPropertyResource::_open_editor_pressed);
ClassDB::bind_method(D_METHOD("_fold_other_editors"), &EditorPropertyResource::_fold_other_editors);
}
EditorPropertyResource::EditorPropertyResource() {
- opened_editor = false;
- sub_inspector = nullptr;
- sub_inspector_vbox = nullptr;
use_sub_inspector = bool(EDITOR_GET("interface/inspector/open_resources_in_current_inspector"));
- HBoxContainer *hbc = memnew(HBoxContainer);
- add_child(hbc);
- assign = memnew(Button);
- assign->set_flat(true);
- assign->set_h_size_flags(SIZE_EXPAND_FILL);
- assign->set_clip_text(true);
- assign->connect("pressed", callable_mp(this, &EditorPropertyResource::_resource_selected));
- assign->set_drag_forwarding(this);
- assign->connect("draw", callable_mp(this, &EditorPropertyResource::_button_draw));
- hbc->add_child(assign);
- add_focusable(assign);
-
- preview = memnew(TextureRect);
- preview->set_expand(true);
- preview->set_anchors_and_offsets_preset(PRESET_WIDE);
- preview->set_offset(SIDE_TOP, 1);
- preview->set_offset(SIDE_BOTTOM, -1);
- preview->set_offset(SIDE_RIGHT, -1);
- // This is required to draw the focus outline in front of the preview, rather than behind.
- preview->set_draw_behind_parent(true);
- assign->add_child(preview);
- assign->connect("gui_input", callable_mp(this, &EditorPropertyResource::_button_input));
-
- menu = memnew(PopupMenu);
- add_child(menu);
- edit = memnew(Button);
- edit->set_flat(true);
- edit->set_toggle_mode(true);
- menu->connect("id_pressed", callable_mp(this, &EditorPropertyResource::_menu_option));
- menu->connect("popup_hide", callable_mp((BaseButton *)edit, &BaseButton::set_pressed), varray(false));
- edit->connect("pressed", callable_mp(this, &EditorPropertyResource::_update_menu));
- hbc->add_child(edit);
- edit->connect("gui_input", callable_mp(this, &EditorPropertyResource::_button_input));
- add_focusable(edit);
-
- file = nullptr;
- scene_tree = nullptr;
- dropping = false;
-
add_to_group("_editor_resource_properties");
}
@@ -3641,8 +3051,8 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
editor->setup(min, max, step, hide_slider);
add_property_editor(p_path, editor);
} break;
- case Variant::QUAT: {
- EditorPropertyQuat *editor = memnew(EditorPropertyQuat);
+ case Variant::QUATERNION: {
+ EditorPropertyQuaternion *editor = memnew(EditorPropertyQuaternion);
double min = -65535, max = 65535, step = default_float_step;
bool hide_slider = true;
@@ -3692,8 +3102,8 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
editor->setup(min, max, step, hide_slider);
add_property_editor(p_path, editor);
} break;
- case Variant::TRANSFORM: {
- EditorPropertyTransform *editor = memnew(EditorPropertyTransform);
+ case Variant::TRANSFORM3D: {
+ EditorPropertyTransform3D *editor = memnew(EditorPropertyTransform3D);
double min = -65535, max = 65535, step = default_float_step;
bool hide_slider = true;
@@ -3751,7 +3161,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
} break;
case Variant::OBJECT: {
EditorPropertyResource *editor = memnew(EditorPropertyResource);
- editor->setup(p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource");
+ editor->setup(p_object, p_path, p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource");
if (p_hint == PROPERTY_HINT_RESOURCE_TYPE) {
String open_in_new = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector");
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 07a1e72319..121848d936 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -33,6 +33,7 @@
#include "editor/create_dialog.h"
#include "editor/editor_inspector.h"
+#include "editor/editor_resource_picker.h"
#include "editor/editor_spin_slider.h"
#include "editor/property_selector.h"
#include "editor/scene_tree_editor.h"
@@ -464,8 +465,8 @@ public:
EditorPropertyPlane(bool p_force_wide = false);
};
-class EditorPropertyQuat : public EditorProperty {
- GDCLASS(EditorPropertyQuat, EditorProperty);
+class EditorPropertyQuaternion : public EditorProperty {
+ GDCLASS(EditorPropertyQuaternion, EditorProperty);
EditorSpinSlider *spin[4];
bool setting;
void _value_changed(double p_val, const String &p_name);
@@ -477,7 +478,7 @@ protected:
public:
virtual void update_property() override;
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
- EditorPropertyQuat();
+ EditorPropertyQuaternion();
};
class EditorPropertyAABB : public EditorProperty {
@@ -528,8 +529,8 @@ public:
EditorPropertyBasis();
};
-class EditorPropertyTransform : public EditorProperty {
- GDCLASS(EditorPropertyTransform, EditorProperty);
+class EditorPropertyTransform3D : public EditorProperty {
+ GDCLASS(EditorPropertyTransform3D, EditorProperty);
EditorSpinSlider *spin[12];
bool setting;
void _value_changed(double p_val, const String &p_name);
@@ -540,9 +541,9 @@ protected:
public:
virtual void update_property() override;
- virtual void update_using_transform(Transform p_transform);
+ virtual void update_using_transform(Transform3D p_transform);
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
- EditorPropertyTransform();
+ EditorPropertyTransform3D();
};
class EditorPropertyColor : public EditorProperty {
@@ -599,64 +600,26 @@ public:
class EditorPropertyResource : public EditorProperty {
GDCLASS(EditorPropertyResource, EditorProperty);
- enum MenuOption {
- OBJ_MENU_LOAD = 0,
- OBJ_MENU_EDIT = 1,
- OBJ_MENU_CLEAR = 2,
- OBJ_MENU_MAKE_UNIQUE = 3,
- OBJ_MENU_SAVE = 4,
- OBJ_MENU_COPY = 5,
- OBJ_MENU_PASTE = 6,
- OBJ_MENU_NEW_SCRIPT = 7,
- OBJ_MENU_EXTEND_SCRIPT = 8,
- OBJ_MENU_SHOW_IN_FILE_SYSTEM = 9,
- TYPE_BASE_ID = 100,
- CONVERT_BASE_ID = 1000
+ EditorResourcePicker *resource_picker = nullptr;
+ SceneTreeDialog *scene_tree = nullptr;
- };
-
- Button *assign;
- TextureRect *preview;
- Button *edit;
- PopupMenu *menu;
- EditorFileDialog *file;
- Vector<String> inheritors_array;
- EditorInspector *sub_inspector;
- VBoxContainer *sub_inspector_vbox;
-
- bool use_sub_inspector;
- bool dropping;
- String base_type;
+ bool use_sub_inspector = false;
+ EditorInspector *sub_inspector = nullptr;
+ VBoxContainer *sub_inspector_vbox = nullptr;
+ bool updating_theme = false;
+ bool opened_editor = false;
- SceneTreeDialog *scene_tree;
+ void _resource_selected(const RES &p_resource);
+ void _resource_changed(const RES &p_resource);
- void _file_selected(const String &p_path);
- void _menu_option(int p_which);
- void _resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj);
- void _resource_selected();
void _viewport_selected(const NodePath &p_path);
- void _update_menu_items();
-
- void _update_menu();
-
void _sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool);
void _sub_inspector_resource_selected(const RES &p_resource, const String &p_property);
void _sub_inspector_object_id_selected(int p_id);
- void _button_draw();
- Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
- bool _is_drop_valid(const Dictionary &p_drag_data) const;
- bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
- void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
-
- void _button_input(const Ref<InputEvent> &p_event);
void _open_editor_pressed();
void _fold_other_editors(Object *p_self);
-
- bool opened_editor;
-
- bool updating_theme = false;
void _update_property_bg();
protected:
@@ -665,7 +628,7 @@ protected:
public:
virtual void update_property() override;
- void setup(const String &p_base_type);
+ void setup(Object *p_object, const String &p_path, const String &p_base_type);
void collapse_all_folding() override;
void expand_all_folding() override;
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index fb2980c948..66fabcd940 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -567,8 +567,8 @@ void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint
}
void EditorPropertyArray::_bind_methods() {
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &EditorPropertyArray::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyArray::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &EditorPropertyArray::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &EditorPropertyArray::drop_data_fw);
}
EditorPropertyArray::EditorPropertyArray() {
@@ -850,8 +850,8 @@ void EditorPropertyDictionary::update_property() {
prop = editor;
} break;
- case Variant::QUAT: {
- EditorPropertyQuat *editor = memnew(EditorPropertyQuat);
+ case Variant::QUATERNION: {
+ EditorPropertyQuaternion *editor = memnew(EditorPropertyQuaternion);
editor->setup(-100000, 100000, 0.001, true);
prop = editor;
@@ -868,8 +868,8 @@ void EditorPropertyDictionary::update_property() {
prop = editor;
} break;
- case Variant::TRANSFORM: {
- EditorPropertyTransform *editor = memnew(EditorPropertyTransform);
+ case Variant::TRANSFORM3D: {
+ EditorPropertyTransform3D *editor = memnew(EditorPropertyTransform3D);
editor->setup(-100000, 100000, 0.001, true);
prop = editor;
@@ -902,7 +902,7 @@ void EditorPropertyDictionary::update_property() {
} else {
EditorPropertyResource *editor = memnew(EditorPropertyResource);
- editor->setup("Resource");
+ editor->setup(object.ptr(), prop_name, "Resource");
prop = editor;
}
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index fa5adc788d..aa2d8744b1 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -36,8 +36,8 @@
#include "editor/filesystem_dock.h"
#include "scene/gui/button.h"
-class EditorPropertyArrayObject : public Reference {
- GDCLASS(EditorPropertyArrayObject, Reference);
+class EditorPropertyArrayObject : public RefCounted {
+ GDCLASS(EditorPropertyArrayObject, RefCounted);
Variant array;
@@ -52,8 +52,8 @@ public:
EditorPropertyArrayObject();
};
-class EditorPropertyDictionaryObject : public Reference {
- GDCLASS(EditorPropertyDictionaryObject, Reference);
+class EditorPropertyDictionaryObject : public RefCounted {
+ GDCLASS(EditorPropertyDictionaryObject, RefCounted);
Variant new_item_key;
Variant new_item_value;
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
new file mode 100644
index 0000000000..1ea8c71f85
--- /dev/null
+++ b/editor/editor_resource_picker.cpp
@@ -0,0 +1,864 @@
+/*************************************************************************/
+/* editor_resource_picker.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "editor_resource_picker.h"
+
+#include "editor/editor_resource_preview.h"
+#include "editor_node.h"
+#include "editor_scale.h"
+#include "editor_settings.h"
+#include "filesystem_dock.h"
+
+void EditorResourcePicker::_update_resource() {
+ preview_rect->set_texture(Ref<Texture2D>());
+ assign_button->set_custom_minimum_size(Size2(1, 1));
+
+ if (edited_resource == RES()) {
+ assign_button->set_icon(Ref<Texture2D>());
+ assign_button->set_text(TTR("[empty]"));
+ } else {
+ assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object"));
+
+ if (edited_resource->get_name() != String()) {
+ assign_button->set_text(edited_resource->get_name());
+ } else if (edited_resource->get_path().is_resource_file()) {
+ assign_button->set_text(edited_resource->get_path().get_file());
+ assign_button->set_tooltip(edited_resource->get_path());
+ } else {
+ assign_button->set_text(edited_resource->get_class());
+ }
+
+ if (edited_resource->get_path().is_resource_file()) {
+ assign_button->set_tooltip(edited_resource->get_path());
+ }
+
+ // Preview will override the above, so called at the end.
+ EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id());
+ }
+}
+
+void EditorResourcePicker::_update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj) {
+ if (!edited_resource.is_valid() || edited_resource->get_instance_id() != p_obj) {
+ return;
+ }
+
+ String type = edited_resource->get_class_name();
+ if (ClassDB::is_parent_class(type, "Script")) {
+ assign_button->set_text(edited_resource->get_path().get_file());
+ return;
+ }
+
+ if (p_preview.is_valid()) {
+ preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox("normal")->get_default_margin(SIDE_LEFT) + get_theme_constant("hseparation", "Button"));
+
+ if (type == "GradientTexture") {
+ preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE);
+ assign_button->set_custom_minimum_size(Size2(1, 1));
+ } else {
+ preview_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size *= EDSCALE;
+ assign_button->set_custom_minimum_size(Size2(1, thumbnail_size));
+ }
+
+ preview_rect->set_texture(p_preview);
+ assign_button->set_text("");
+ }
+}
+
+void EditorResourcePicker::_resource_selected() {
+ if (edited_resource.is_null()) {
+ edit_button->set_pressed(true);
+ _update_menu();
+ return;
+ }
+
+ emit_signal("resource_selected", edited_resource);
+}
+
+void EditorResourcePicker::_file_selected(const String &p_path) {
+ RES loaded_resource = ResourceLoader::load(p_path);
+ ERR_FAIL_COND_MSG(loaded_resource.is_null(), "Cannot load resource from path '" + p_path + "'.");
+
+ if (base_type != "") {
+ bool any_type_matches = false;
+
+ for (int i = 0; i < base_type.get_slice_count(","); i++) {
+ String base = base_type.get_slice(",", i);
+ if (loaded_resource->is_class(base)) {
+ any_type_matches = true;
+ break;
+ }
+ }
+
+ if (!any_type_matches) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("The selected resource (%s) does not match any type expected for this property (%s)."), loaded_resource->get_class(), base_type));
+ return;
+ }
+ }
+
+ edited_resource = loaded_resource;
+ emit_signal("resource_changed", edited_resource);
+ _update_resource();
+}
+
+void EditorResourcePicker::_update_menu() {
+ _update_menu_items();
+
+ Rect2 gt = edit_button->get_screen_rect();
+ edit_menu->set_as_minsize();
+ int ms = edit_menu->get_contents_minimum_size().width;
+ Vector2 popup_pos = gt.position + gt.size - Vector2(ms, 0);
+ edit_menu->set_position(popup_pos);
+ edit_menu->popup();
+}
+
+void EditorResourcePicker::_update_menu_items() {
+ edit_menu->clear();
+
+ // Add options for creating specific subtypes of the base resource type.
+ set_create_options(edit_menu);
+
+ // Add an option to load a resource from a file.
+ edit_menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD);
+
+ // Add options for changing existing value of the resource.
+ if (edited_resource.is_valid()) {
+ edit_menu->add_icon_item(get_theme_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT);
+ edit_menu->add_icon_item(get_theme_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR);
+ edit_menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
+ edit_menu->add_icon_item(get_theme_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE);
+
+ if (edited_resource->get_path().is_resource_file()) {
+ edit_menu->add_separator();
+ edit_menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM);
+ }
+ }
+
+ // Add options to copy/paste resource.
+ RES cb = EditorSettings::get_singleton()->get_resource_clipboard();
+ bool paste_valid = false;
+ if (cb.is_valid()) {
+ if (base_type == "") {
+ paste_valid = true;
+ } else {
+ for (int i = 0; i < base_type.get_slice_count(","); i++) {
+ if (ClassDB::is_parent_class(cb->get_class(), base_type.get_slice(",", i))) {
+ paste_valid = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (edited_resource.is_valid() || paste_valid) {
+ edit_menu->add_separator();
+
+ if (edited_resource.is_valid()) {
+ edit_menu->add_item(TTR("Copy"), OBJ_MENU_COPY);
+ }
+
+ if (paste_valid) {
+ edit_menu->add_item(TTR("Paste"), OBJ_MENU_PASTE);
+ }
+ }
+
+ // Add options to convert existing resource to another type of resource.
+ if (edited_resource.is_valid()) {
+ Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(edited_resource);
+ if (conversions.size()) {
+ edit_menu->add_separator();
+ }
+ for (int i = 0; i < conversions.size(); i++) {
+ String what = conversions[i]->converts_to();
+ Ref<Texture2D> icon;
+ if (has_theme_icon(what, "EditorIcons")) {
+ icon = get_theme_icon(what, "EditorIcons");
+ } else {
+ icon = get_theme_icon(what, "Resource");
+ }
+
+ edit_menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i);
+ }
+ }
+}
+
+void EditorResourcePicker::_edit_menu_cbk(int p_which) {
+ switch (p_which) {
+ case OBJ_MENU_LOAD: {
+ List<String> extensions;
+ for (int i = 0; i < base_type.get_slice_count(","); i++) {
+ String base = base_type.get_slice(",", i);
+ ResourceLoader::get_recognized_extensions_for_type(base, &extensions);
+ }
+
+ Set<String> valid_extensions;
+ for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
+ valid_extensions.insert(E->get());
+ }
+
+ if (!file_dialog) {
+ file_dialog = memnew(EditorFileDialog);
+ file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ add_child(file_dialog);
+ file_dialog->connect("file_selected", callable_mp(this, &EditorResourcePicker::_file_selected));
+ }
+
+ file_dialog->clear_filters();
+ for (Set<String>::Element *E = valid_extensions.front(); E; E = E->next()) {
+ file_dialog->add_filter("*." + E->get() + " ; " + E->get().to_upper());
+ }
+
+ file_dialog->popup_file_dialog();
+ } break;
+
+ case OBJ_MENU_EDIT: {
+ if (edited_resource.is_valid()) {
+ emit_signal("resource_selected", edited_resource);
+ }
+ } break;
+
+ case OBJ_MENU_CLEAR: {
+ edited_resource = RES();
+ emit_signal("resource_changed", edited_resource);
+ _update_resource();
+ } break;
+
+ case OBJ_MENU_MAKE_UNIQUE: {
+ if (edited_resource.is_null()) {
+ return;
+ }
+
+ List<PropertyInfo> property_list;
+ edited_resource->get_property_list(&property_list);
+ List<Pair<String, Variant>> propvalues;
+ for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
+ Pair<String, Variant> p;
+ PropertyInfo &pi = E->get();
+ if (pi.usage & PROPERTY_USAGE_STORAGE) {
+ p.first = pi.name;
+ p.second = edited_resource->get(pi.name);
+ }
+
+ propvalues.push_back(p);
+ }
+
+ String orig_type = edited_resource->get_class();
+ Object *inst = ClassDB::instance(orig_type);
+ Ref<Resource> unique_resource = Ref<Resource>(Object::cast_to<Resource>(inst));
+ ERR_FAIL_COND(unique_resource.is_null());
+
+ for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) {
+ Pair<String, Variant> &p = E->get();
+ unique_resource->set(p.first, p.second);
+ }
+
+ edited_resource = unique_resource;
+ emit_signal("resource_changed", edited_resource);
+ _update_resource();
+ } break;
+
+ case OBJ_MENU_SAVE: {
+ if (edited_resource.is_null()) {
+ return;
+ }
+ EditorNode::get_singleton()->save_resource(edited_resource);
+ } break;
+
+ case OBJ_MENU_COPY: {
+ EditorSettings::get_singleton()->set_resource_clipboard(edited_resource);
+ } break;
+
+ case OBJ_MENU_PASTE: {
+ edited_resource = EditorSettings::get_singleton()->get_resource_clipboard();
+ emit_signal("resource_changed", edited_resource);
+ _update_resource();
+ } break;
+
+ case OBJ_MENU_SHOW_IN_FILE_SYSTEM: {
+ FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock();
+ file_system_dock->navigate_to_path(edited_resource->get_path());
+
+ // Ensure that the FileSystem dock is visible.
+ TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control();
+ tab_container->set_current_tab(file_system_dock->get_index());
+ } break;
+
+ default: {
+ // Allow subclasses to handle their own options first, only then fallback on the default branch logic.
+ if (handle_menu_selected(p_which)) {
+ break;
+ }
+
+ if (p_which >= CONVERT_BASE_ID) {
+ int to_type = p_which - CONVERT_BASE_ID;
+ Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(edited_resource);
+ ERR_FAIL_INDEX(to_type, conversions.size());
+
+ edited_resource = conversions[to_type]->convert(edited_resource);
+ emit_signal("resource_changed", edited_resource);
+ _update_resource();
+ break;
+ }
+
+ ERR_FAIL_COND(inheritors_array.is_empty());
+
+ String intype = inheritors_array[p_which - TYPE_BASE_ID];
+ Variant obj;
+
+ if (ScriptServer::is_global_class(intype)) {
+ obj = ClassDB::instance(ScriptServer::get_global_class_native_base(intype));
+ if (obj) {
+ Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(intype));
+ if (script.is_valid()) {
+ ((Object *)obj)->set_script(script);
+ }
+ }
+ } else {
+ obj = ClassDB::instance(intype);
+ }
+
+ if (!obj) {
+ obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
+ }
+
+ Resource *resp = Object::cast_to<Resource>(obj);
+ ERR_BREAK(!resp);
+
+ edited_resource = RES(resp);
+ emit_signal("resource_changed", edited_resource);
+ _update_resource();
+ } break;
+ }
+}
+
+void EditorResourcePicker::set_create_options(Object *p_menu_node) {
+ // If a subclass implements this method, use it to replace all create items.
+ if (get_script_instance() && get_script_instance()->has_method("_set_create_options")) {
+ get_script_instance()->call("_set_create_options", p_menu_node);
+ return;
+ }
+
+ // By default provide generic "New ..." options.
+ if (base_type != "") {
+ int idx = 0;
+
+ Set<String> allowed_types;
+ _get_allowed_types(false, &allowed_types);
+
+ Vector<EditorData::CustomType> custom_resources;
+ if (EditorNode::get_editor_data().get_custom_types().has("Resource")) {
+ custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"];
+ }
+
+ for (Set<String>::Element *E = allowed_types.front(); E; E = E->next()) {
+ const String &t = E->get();
+
+ bool is_custom_resource = false;
+ Ref<Texture2D> icon;
+ if (!custom_resources.is_empty()) {
+ for (int j = 0; j < custom_resources.size(); j++) {
+ if (custom_resources[j].name == t) {
+ is_custom_resource = true;
+ if (custom_resources[j].icon.is_valid()) {
+ icon = custom_resources[j].icon;
+ }
+ break;
+ }
+ }
+ }
+
+ if (!is_custom_resource && !(ScriptServer::is_global_class(t) || ClassDB::can_instance(t))) {
+ continue;
+ }
+
+ inheritors_array.push_back(t);
+
+ if (!icon.is_valid()) {
+ icon = get_theme_icon(has_theme_icon(t, "EditorIcons") ? t : "Object", "EditorIcons");
+ }
+
+ int id = TYPE_BASE_ID + idx;
+ edit_menu->add_icon_item(icon, vformat(TTR("New %s"), t), id);
+
+ idx++;
+ }
+
+ if (edit_menu->get_item_count()) {
+ edit_menu->add_separator();
+ }
+ }
+}
+
+bool EditorResourcePicker::handle_menu_selected(int p_which) {
+ if (get_script_instance() && get_script_instance()->has_method("_handle_menu_selected")) {
+ return get_script_instance()->call("_handle_menu_selected", p_which);
+ }
+
+ return false;
+}
+
+void EditorResourcePicker::_button_draw() {
+ if (dropping) {
+ Color color = get_theme_color("accent_color", "Editor");
+ assign_button->draw_rect(Rect2(Point2(), assign_button->get_size()), color, false);
+ }
+}
+
+void EditorResourcePicker::_button_input(const Ref<InputEvent> &p_event) {
+ if (!editable) {
+ return;
+ }
+
+ Ref<InputEventMouseButton> mb = p_event;
+
+ if (mb.is_valid()) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
+ _update_menu_items();
+
+ Vector2 pos = get_screen_position() + mb->get_position();
+ edit_menu->set_as_minsize();
+ edit_menu->set_position(pos);
+ edit_menu->popup();
+ }
+ }
+}
+
+void EditorResourcePicker::_get_allowed_types(bool p_with_convert, Set<String> *p_vector) const {
+ Vector<String> allowed_types = base_type.split(",");
+ int size = allowed_types.size();
+
+ List<StringName> global_classes;
+ ScriptServer::get_global_class_list(&global_classes);
+
+ for (int i = 0; i < size; i++) {
+ String base = allowed_types[i].strip_edges();
+ p_vector->insert(base);
+
+ List<StringName> inheriters;
+
+ ClassDB::get_inheriters_from_class(base, &inheriters);
+ for (List<StringName>::Element *E = inheriters.front(); E; E = E->next()) {
+ p_vector->insert(E->get());
+ }
+
+ for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
+ if (EditorNode::get_editor_data().script_class_is_parent(E->get(), base)) {
+ p_vector->insert(E->get());
+ }
+ }
+
+ if (p_with_convert) {
+ if (base == "StandardMaterial3D") {
+ p_vector->insert("Texture2D");
+ } else if (base == "ShaderMaterial") {
+ p_vector->insert("Shader");
+ } else if (base == "Font") {
+ p_vector->insert("FontData");
+ }
+ }
+ }
+
+ if (EditorNode::get_editor_data().get_custom_types().has("Resource")) {
+ Vector<EditorData::CustomType> custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"];
+
+ for (int i = 0; i < custom_resources.size(); i++) {
+ p_vector->insert(custom_resources[i].name);
+ }
+ }
+}
+
+bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const {
+ if (base_type.is_empty()) {
+ return true;
+ }
+
+ Dictionary drag_data = p_drag_data;
+
+ Ref<Resource> res;
+ if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") {
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]);
+ res = se->get_edited_resource();
+ } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
+ res = drag_data["resource"];
+ }
+
+ Set<String> allowed_types;
+ _get_allowed_types(true, &allowed_types);
+
+ if (res.is_valid() && _is_type_valid(res->get_class(), allowed_types)) {
+ return true;
+ }
+
+ if (res.is_valid() && res->get_script()) {
+ StringName custom_class = EditorNode::get_singleton()->get_object_custom_type_name(res->get_script());
+ if (_is_type_valid(custom_class, allowed_types)) {
+ return true;
+ }
+ }
+
+ if (drag_data.has("type") && String(drag_data["type"]) == "files") {
+ Vector<String> files = drag_data["files"];
+
+ if (files.size() == 1) {
+ String file = files[0];
+
+ String file_type = EditorFileSystem::get_singleton()->get_file_type(file);
+ if (file_type != "" && _is_type_valid(file_type, allowed_types)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool EditorResourcePicker::_is_type_valid(const String p_type_name, Set<String> p_allowed_types) const {
+ for (Set<String>::Element *E = p_allowed_types.front(); E; E = E->next()) {
+ String at = E->get().strip_edges();
+ if (p_type_name == at || ClassDB::is_parent_class(p_type_name, at) || EditorNode::get_editor_data().script_class_is_parent(p_type_name, at)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Variant EditorResourcePicker::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+ if (edited_resource.is_valid()) {
+ return EditorNode::get_singleton()->drag_resource(edited_resource, p_from);
+ }
+
+ return Variant();
+}
+
+bool EditorResourcePicker::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+ return editable && _is_drop_valid(p_data);
+}
+
+void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+ ERR_FAIL_COND(!_is_drop_valid(p_data));
+
+ Dictionary drag_data = p_data;
+
+ Ref<Resource> dropped_resource;
+ if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") {
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]);
+ dropped_resource = se->get_edited_resource();
+ } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
+ dropped_resource = drag_data["resource"];
+ }
+
+ if (!dropped_resource.is_valid() && drag_data.has("type") && String(drag_data["type"]) == "files") {
+ Vector<String> files = drag_data["files"];
+
+ if (files.size() == 1) {
+ String file = files[0];
+ dropped_resource = ResourceLoader::load(file);
+ }
+ }
+
+ if (dropped_resource.is_valid()) {
+ Set<String> allowed_types;
+ _get_allowed_types(false, &allowed_types);
+
+ // If the accepted dropped resource is from the extended list, it requires conversion.
+ if (!_is_type_valid(dropped_resource->get_class(), allowed_types)) {
+ for (Set<String>::Element *E = allowed_types.front(); E; E = E->next()) {
+ String at = E->get().strip_edges();
+
+ if (at == "StandardMaterial3D" && ClassDB::is_parent_class(dropped_resource->get_class(), "Texture2D")) {
+ Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D);
+ mat->set_texture(StandardMaterial3D::TextureParam::TEXTURE_ALBEDO, dropped_resource);
+ dropped_resource = mat;
+ break;
+ }
+
+ if (at == "ShaderMaterial" && ClassDB::is_parent_class(dropped_resource->get_class(), "Shader")) {
+ Ref<ShaderMaterial> mat = memnew(ShaderMaterial);
+ mat->set_shader(dropped_resource);
+ dropped_resource = mat;
+ break;
+ }
+
+ if (at == "Font" && ClassDB::is_parent_class(dropped_resource->get_class(), "FontData")) {
+ Ref<Font> font = memnew(Font);
+ font->add_data(dropped_resource);
+ dropped_resource = font;
+ break;
+ }
+ }
+ }
+
+ edited_resource = dropped_resource;
+ emit_signal("resource_changed", edited_resource);
+ _update_resource();
+ }
+}
+
+void EditorResourcePicker::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_update_resource_preview"), &EditorResourcePicker::_update_resource_preview);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw", "position", "from"), &EditorResourcePicker::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw", "position", "data", "from"), &EditorResourcePicker::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw", "position", "data", "from"), &EditorResourcePicker::drop_data_fw);
+
+ ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &EditorResourcePicker::set_base_type);
+ ClassDB::bind_method(D_METHOD("get_base_type"), &EditorResourcePicker::get_base_type);
+ ClassDB::bind_method(D_METHOD("get_allowed_types"), &EditorResourcePicker::get_allowed_types);
+ ClassDB::bind_method(D_METHOD("set_edited_resource", "resource"), &EditorResourcePicker::set_edited_resource);
+ ClassDB::bind_method(D_METHOD("get_edited_resource"), &EditorResourcePicker::get_edited_resource);
+ ClassDB::bind_method(D_METHOD("set_toggle_mode", "enable"), &EditorResourcePicker::set_toggle_mode);
+ ClassDB::bind_method(D_METHOD("is_toggle_mode"), &EditorResourcePicker::is_toggle_mode);
+ ClassDB::bind_method(D_METHOD("set_toggle_pressed", "pressed"), &EditorResourcePicker::set_toggle_pressed);
+ ClassDB::bind_method(D_METHOD("set_editable", "enable"), &EditorResourcePicker::set_editable);
+ ClassDB::bind_method(D_METHOD("is_editable"), &EditorResourcePicker::is_editable);
+
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo("_set_create_options", PropertyInfo(Variant::OBJECT, "menu_node")));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo("_handle_menu_selected", PropertyInfo(Variant::INT, "id")));
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type"), "set_base_type", "get_base_type");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource", 0), "set_edited_resource", "get_edited_resource");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode");
+
+ ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
+ ADD_SIGNAL(MethodInfo("resource_changed", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
+}
+
+void EditorResourcePicker::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ _update_resource();
+ [[fallthrough]];
+ }
+ case NOTIFICATION_THEME_CHANGED: {
+ edit_button->set_icon(get_theme_icon("select_arrow", "Tree"));
+ } break;
+
+ case NOTIFICATION_DRAW: {
+ draw_style_box(get_theme_stylebox("bg", "Tree"), Rect2(Point2(), get_size()));
+ } break;
+
+ case NOTIFICATION_DRAG_BEGIN: {
+ if (editable && _is_drop_valid(get_viewport()->gui_get_drag_data())) {
+ dropping = true;
+ assign_button->update();
+ }
+ } break;
+
+ case NOTIFICATION_DRAG_END: {
+ if (dropping) {
+ dropping = false;
+ assign_button->update();
+ }
+ } break;
+ }
+}
+
+void EditorResourcePicker::set_base_type(const String &p_base_type) {
+ base_type = p_base_type;
+
+ // There is a possibility that the new base type is conflicting with the existing value.
+ // Keep the value, but warn the user that there is a potential mistake.
+ if (!base_type.is_empty() && edited_resource.is_valid()) {
+ Set<String> allowed_types;
+ _get_allowed_types(true, &allowed_types);
+
+ StringName custom_class;
+ bool is_custom = false;
+ if (edited_resource->get_script()) {
+ custom_class = EditorNode::get_singleton()->get_object_custom_type_name(edited_resource->get_script());
+ is_custom = _is_type_valid(custom_class, allowed_types);
+ }
+
+ if (!is_custom && !_is_type_valid(edited_resource->get_class(), allowed_types)) {
+ String class_str = (custom_class == StringName() ? edited_resource->get_class() : vformat("%s (%s)", custom_class, edited_resource->get_class()));
+ WARN_PRINT(vformat("Value mismatch between the new base type of this EditorResourcePicker, '%s', and the type of the value it already has, '%s'.", base_type, class_str));
+ }
+ }
+}
+
+String EditorResourcePicker::get_base_type() const {
+ return base_type;
+}
+
+Vector<String> EditorResourcePicker::get_allowed_types() const {
+ Set<String> allowed_types;
+ _get_allowed_types(false, &allowed_types);
+
+ Vector<String> types;
+ types.resize(allowed_types.size());
+
+ int i = 0;
+ String *w = types.ptrw();
+ for (Set<String>::Element *E = allowed_types.front(); E; E = E->next(), i++) {
+ w[i] = E->get();
+ }
+
+ return types;
+}
+
+void EditorResourcePicker::set_edited_resource(RES p_resource) {
+ if (!p_resource.is_valid()) {
+ edited_resource = RES();
+ _update_resource();
+ return;
+ }
+
+ if (!base_type.is_empty()) {
+ Set<String> allowed_types;
+ _get_allowed_types(true, &allowed_types);
+
+ StringName custom_class;
+ bool is_custom = false;
+ if (p_resource->get_script()) {
+ custom_class = EditorNode::get_singleton()->get_object_custom_type_name(p_resource->get_script());
+ is_custom = _is_type_valid(custom_class, allowed_types);
+ }
+
+ if (!is_custom && !_is_type_valid(p_resource->get_class(), allowed_types)) {
+ String class_str = (custom_class == StringName() ? p_resource->get_class() : vformat("%s (%s)", custom_class, p_resource->get_class()));
+ ERR_FAIL_MSG(vformat("Failed to set a resource of the type '%s' because this EditorResourcePicker only accepts '%s' and its derivatives.", class_str, base_type));
+ }
+ }
+
+ edited_resource = p_resource;
+ _update_resource();
+}
+
+RES EditorResourcePicker::get_edited_resource() {
+ return edited_resource;
+}
+
+void EditorResourcePicker::set_toggle_mode(bool p_enable) {
+ assign_button->set_toggle_mode(p_enable);
+}
+
+bool EditorResourcePicker::is_toggle_mode() const {
+ return assign_button->is_toggle_mode();
+}
+
+void EditorResourcePicker::set_toggle_pressed(bool p_pressed) {
+ if (!is_toggle_mode()) {
+ return;
+ }
+
+ assign_button->set_pressed(p_pressed);
+}
+
+void EditorResourcePicker::set_editable(bool p_editable) {
+ editable = p_editable;
+ assign_button->set_disabled(!editable);
+ edit_button->set_visible(editable);
+}
+
+bool EditorResourcePicker::is_editable() const {
+ return editable;
+}
+
+EditorResourcePicker::EditorResourcePicker() {
+ assign_button = memnew(Button);
+ assign_button->set_flat(true);
+ assign_button->set_h_size_flags(SIZE_EXPAND_FILL);
+ assign_button->set_clip_text(true);
+ assign_button->set_drag_forwarding(this);
+ add_child(assign_button);
+ assign_button->connect("pressed", callable_mp(this, &EditorResourcePicker::_resource_selected));
+ assign_button->connect("draw", callable_mp(this, &EditorResourcePicker::_button_draw));
+ assign_button->connect("gui_input", callable_mp(this, &EditorResourcePicker::_button_input));
+
+ preview_rect = memnew(TextureRect);
+ preview_rect->set_expand(true);
+ preview_rect->set_anchors_and_offsets_preset(PRESET_WIDE);
+ preview_rect->set_offset(SIDE_TOP, 1);
+ preview_rect->set_offset(SIDE_BOTTOM, -1);
+ preview_rect->set_offset(SIDE_RIGHT, -1);
+ assign_button->add_child(preview_rect);
+
+ edit_button = memnew(Button);
+ edit_button->set_flat(true);
+ edit_button->set_toggle_mode(true);
+ edit_button->connect("pressed", callable_mp(this, &EditorResourcePicker::_update_menu));
+ add_child(edit_button);
+ edit_button->connect("gui_input", callable_mp(this, &EditorResourcePicker::_button_input));
+ edit_menu = memnew(PopupMenu);
+ add_child(edit_menu);
+ edit_menu->connect("id_pressed", callable_mp(this, &EditorResourcePicker::_edit_menu_cbk));
+ edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed), varray(false));
+}
+
+void EditorScriptPicker::set_create_options(Object *p_menu_node) {
+ PopupMenu *menu_node = Object::cast_to<PopupMenu>(p_menu_node);
+ if (!menu_node) {
+ return;
+ }
+
+ menu_node->add_icon_item(get_theme_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT);
+ menu_node->add_icon_item(get_theme_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT);
+ menu_node->add_separator();
+}
+
+bool EditorScriptPicker::handle_menu_selected(int p_which) {
+ switch (p_which) {
+ case OBJ_MENU_NEW_SCRIPT: {
+ if (script_owner) {
+ EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(script_owner, false);
+ }
+ return true;
+ }
+
+ case OBJ_MENU_EXTEND_SCRIPT: {
+ if (script_owner) {
+ EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(script_owner, true);
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void EditorScriptPicker::set_script_owner(Node *p_owner) {
+ script_owner = p_owner;
+}
+
+Node *EditorScriptPicker::get_script_owner() const {
+ return script_owner;
+}
+
+void EditorScriptPicker::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_script_owner", "owner_node"), &EditorScriptPicker::set_script_owner);
+ ClassDB::bind_method(D_METHOD("get_script_owner"), &EditorScriptPicker::get_script_owner);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "script_owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_script_owner", "get_script_owner");
+}
+
+EditorScriptPicker::EditorScriptPicker() {
+}
diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h
new file mode 100644
index 0000000000..9a4b945bc7
--- /dev/null
+++ b/editor/editor_resource_picker.h
@@ -0,0 +1,141 @@
+/*************************************************************************/
+/* editor_resource_picker.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef EDITOR_RESOURCE_PICKER_H
+#define EDITOR_RESOURCE_PICKER_H
+
+#include "editor_file_dialog.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/popup_menu.h"
+#include "scene/gui/texture_rect.h"
+
+class EditorResourcePicker : public HBoxContainer {
+ GDCLASS(EditorResourcePicker, HBoxContainer);
+
+ String base_type;
+ RES edited_resource;
+
+ bool editable = true;
+ bool dropping = false;
+
+ Vector<String> inheritors_array;
+
+ Button *assign_button;
+ TextureRect *preview_rect;
+ Button *edit_button;
+ EditorFileDialog *file_dialog = nullptr;
+
+ enum MenuOption {
+ OBJ_MENU_LOAD,
+ OBJ_MENU_EDIT,
+ OBJ_MENU_CLEAR,
+ OBJ_MENU_MAKE_UNIQUE,
+ OBJ_MENU_SAVE,
+ OBJ_MENU_COPY,
+ OBJ_MENU_PASTE,
+ OBJ_MENU_SHOW_IN_FILE_SYSTEM,
+
+ TYPE_BASE_ID = 100,
+ CONVERT_BASE_ID = 1000,
+ };
+
+ PopupMenu *edit_menu;
+
+ void _update_resource();
+ void _update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj);
+
+ void _resource_selected();
+ void _file_selected(const String &p_path);
+
+ void _update_menu();
+ void _update_menu_items();
+ void _edit_menu_cbk(int p_which);
+
+ void _button_draw();
+ void _button_input(const Ref<InputEvent> &p_event);
+
+ void _get_allowed_types(bool p_with_convert, Set<String> *p_vector) const;
+ bool _is_drop_valid(const Dictionary &p_drag_data) const;
+ bool _is_type_valid(const String p_type_name, Set<String> p_allowed_types) const;
+
+ Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ void set_base_type(const String &p_base_type);
+ String get_base_type() const;
+ Vector<String> get_allowed_types() const;
+
+ void set_edited_resource(RES p_resource);
+ RES get_edited_resource();
+
+ void set_toggle_mode(bool p_enable);
+ bool is_toggle_mode() const;
+ void set_toggle_pressed(bool p_pressed);
+
+ void set_editable(bool p_editable);
+ bool is_editable() const;
+
+ virtual void set_create_options(Object *p_menu_node);
+ virtual bool handle_menu_selected(int p_which);
+
+ EditorResourcePicker();
+};
+
+class EditorScriptPicker : public EditorResourcePicker {
+ GDCLASS(EditorScriptPicker, EditorResourcePicker);
+
+ enum ExtraMenuOption {
+ OBJ_MENU_NEW_SCRIPT = 10,
+ OBJ_MENU_EXTEND_SCRIPT = 11
+ };
+
+ Node *script_owner = nullptr;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual void set_create_options(Object *p_menu_node) override;
+ virtual bool handle_menu_selected(int p_which) override;
+
+ void set_script_owner(Node *p_owner);
+ Node *get_script_owner() const;
+
+ EditorScriptPicker();
+};
+
+#endif // EDITOR_RESOURCE_PICKER_H
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 138830cdc6..0f1b70936a 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -31,31 +31,31 @@
#include "editor_resource_preview.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/object/message_queue.h"
-#include "core/os/file_access.h"
#include "editor_node.h"
#include "editor_scale.h"
#include "editor_settings.h"
bool EditorResourcePreviewGenerator::handles(const String &p_type) const {
- if (get_script_instance() && get_script_instance()->has_method("handles")) {
- return get_script_instance()->call("handles", p_type);
+ if (get_script_instance() && get_script_instance()->has_method("_handles")) {
+ return get_script_instance()->call("_handles", p_type);
}
- ERR_FAIL_V_MSG(false, "EditorResourcePreviewGenerator::handles needs to be overridden.");
+ ERR_FAIL_V_MSG(false, "EditorResourcePreviewGenerator::_handles needs to be overridden.");
}
Ref<Texture2D> EditorResourcePreviewGenerator::generate(const RES &p_from, const Size2 &p_size) const {
- if (get_script_instance() && get_script_instance()->has_method("generate")) {
- return get_script_instance()->call("generate", p_from, p_size);
+ if (get_script_instance() && get_script_instance()->has_method("_generate")) {
+ return get_script_instance()->call("_generate", p_from, p_size);
}
- ERR_FAIL_V_MSG(Ref<Texture2D>(), "EditorResourcePreviewGenerator::generate needs to be overridden.");
+ ERR_FAIL_V_MSG(Ref<Texture2D>(), "EditorResourcePreviewGenerator::_generate needs to be overridden.");
}
Ref<Texture2D> EditorResourcePreviewGenerator::generate_from_path(const String &p_path, const Size2 &p_size) const {
- if (get_script_instance() && get_script_instance()->has_method("generate_from_path")) {
- return get_script_instance()->call("generate_from_path", p_path, p_size);
+ if (get_script_instance() && get_script_instance()->has_method("_generate_from_path")) {
+ return get_script_instance()->call("_generate_from_path", p_path, p_size);
}
RES res = ResourceLoader::load(p_path);
@@ -66,27 +66,27 @@ Ref<Texture2D> EditorResourcePreviewGenerator::generate_from_path(const String &
}
bool EditorResourcePreviewGenerator::generate_small_preview_automatically() const {
- if (get_script_instance() && get_script_instance()->has_method("generate_small_preview_automatically")) {
- return get_script_instance()->call("generate_small_preview_automatically");
+ if (get_script_instance() && get_script_instance()->has_method("_generate_small_preview_automatically")) {
+ return get_script_instance()->call("_generate_small_preview_automatically");
}
return false;
}
bool EditorResourcePreviewGenerator::can_generate_small_preview() const {
- if (get_script_instance() && get_script_instance()->has_method("can_generate_small_preview")) {
- return get_script_instance()->call("can_generate_small_preview");
+ if (get_script_instance() && get_script_instance()->has_method("_can_generate_small_preview")) {
+ return get_script_instance()->call("_can_generate_small_preview");
}
return false;
}
void EditorResourcePreviewGenerator::_bind_methods() {
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles", PropertyInfo(Variant::STRING, "type")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture2D), "generate", PropertyInfo(Variant::OBJECT, "from", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::VECTOR2, "size")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture2D), "generate_from_path", PropertyInfo(Variant::STRING, "path", PROPERTY_HINT_FILE), PropertyInfo(Variant::VECTOR2, "size")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "generate_small_preview_automatically"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "can_generate_small_preview"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_handles", PropertyInfo(Variant::STRING, "type")));
+ BIND_VMETHOD(MethodInfo(CLASS_INFO(Texture2D), "_generate", PropertyInfo(Variant::OBJECT, "from", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::VECTOR2, "size")));
+ BIND_VMETHOD(MethodInfo(CLASS_INFO(Texture2D), "_generate_from_path", PropertyInfo(Variant::STRING, "path", PROPERTY_HINT_FILE), PropertyInfo(Variant::VECTOR2, "size")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_generate_small_preview_automatically"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_can_generate_small_preview"));
}
EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() {
@@ -241,7 +241,7 @@ void EditorResourcePreview::_thread() {
_preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, small_texture, item.id, item.function, item.userdata);
} else {
- String temp_path = EditorSettings::get_singleton()->get_cache_dir();
+ String temp_path = EditorPaths::get_singleton()->get_cache_dir();
String cache_base = ProjectSettings::get_singleton()->globalize_path(item.path).md5_text();
cache_base = temp_path.plus_file("resthumb-" + cache_base);
diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index c4e796dcf1..67f83220d0 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -37,8 +37,8 @@
#include "scene/main/node.h"
#include "scene/resources/texture.h"
-class EditorResourcePreviewGenerator : public Reference {
- GDCLASS(EditorResourcePreviewGenerator, Reference);
+class EditorResourcePreviewGenerator : public RefCounted {
+ GDCLASS(EditorResourcePreviewGenerator, RefCounted);
protected:
static void _bind_methods();
@@ -101,7 +101,8 @@ protected:
public:
static EditorResourcePreview *get_singleton();
- //callback function is callback(String p_path,Ref<Texture2D> preview,Variant udata) preview null if could not load
+ // p_receiver_func callback has signature (String p_path, Ref<Texture2D> p_preview, Ref<Texture2D> p_preview_small, Variant p_userdata)
+ // p_preview will be null if there was an error
void queue_resource_preview(const String &p_path, Object *p_receiver, const StringName &p_receiver_func, const Variant &p_userdata);
void queue_edited_resource_preview(const Ref<Resource> &p_res, Object *p_receiver, const StringName &p_receiver_func, const Variant &p_userdata);
diff --git a/editor/editor_run_script.h b/editor/editor_run_script.h
index 83987ecba1..c8412c3c92 100644
--- a/editor/editor_run_script.h
+++ b/editor/editor_run_script.h
@@ -31,11 +31,11 @@
#ifndef EDITOR_RUN_SCRIPT_H
#define EDITOR_RUN_SCRIPT_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "editor_plugin.h"
class EditorNode;
-class EditorScript : public Reference {
- GDCLASS(EditorScript, Reference);
+class EditorScript : public RefCounted {
+ GDCLASS(EditorScript, RefCounted);
EditorNode *editor;
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index f81c87be9e..6bfb17f9c2 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -135,7 +135,7 @@ void SectionedInspector::_section_selected() {
}
selected_category = sections->get_selected()->get_metadata(0);
- filter->set_section(selected_category, sections->get_selected()->get_children() == nullptr);
+ filter->set_section(selected_category, sections->get_selected()->get_first_child() == nullptr);
inspector->set_property_prefix(selected_category + "/");
}
@@ -187,8 +187,8 @@ void SectionedInspector::edit(Object *p_object) {
TreeItem *first_item = sections->get_root();
if (first_item) {
- while (first_item->get_children()) {
- first_item = first_item->get_children();
+ while (first_item->get_first_child()) {
+ first_item = first_item->get_first_child();
}
first_item->select(0);
@@ -250,7 +250,8 @@ void SectionedInspector::update_category_list() {
for (int i = 0; i < sc; i++) {
TreeItem *parent = section_map[metasection];
- parent->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor"));
+ //parent->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor"));
+ parent->set_custom_font(0, get_theme_font("bold", "EditorFonts"));
if (i > 0) {
metasection += "/" + sectionarr[i];
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index aba14df812..fa7980b95f 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -35,13 +35,13 @@
#include "core/io/certs_compressed.gen.h"
#include "core/io/compression.h"
#include "core/io/config_file.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_memory.h"
#include "core/io/ip.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/io/translation_loader_po.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/version.h"
@@ -419,7 +419,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/editor/main_font_bold"] = PropertyInfo(Variant::STRING, "interface/editor/main_font_bold", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/editor/code_font", "");
hints["interface/editor/code_font"] = PropertyInfo(Variant::STRING, "interface/editor/code_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT);
- _initial_set("interface/editor/dim_editor_on_dialog_popup", true);
_initial_set("interface/editor/low_processor_mode_sleep_usec", 6900); // ~144 FPS
hints["interface/editor/low_processor_mode_sleep_usec"] = PropertyInfo(Variant::FLOAT, "interface/editor/low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,100000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/unfocused_low_processor_mode_sleep_usec", 50000); // 20 FPS
@@ -503,12 +502,12 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
/* Text editor */
// Theme
- _initial_set("text_editor/theme/color_theme", "Adaptive");
- hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Adaptive,Default,Custom");
+ _initial_set("text_editor/theme/color_theme", "Default");
+ hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Default,Godot 2,Custom");
_initial_set("text_editor/theme/line_spacing", 6);
hints["text_editor/theme/line_spacing"] = PropertyInfo(Variant::INT, "text_editor/theme/line_spacing", PROPERTY_HINT_RANGE, "0,50,1");
- _load_default_text_editor_theme();
+ _load_godot2_text_editor_theme();
// Highlighting
_initial_set("text_editor/highlighting/highlight_all_occurrences", true);
@@ -572,7 +571,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/completion/code_complete_delay", 0.3);
hints["text_editor/completion/code_complete_delay"] = PropertyInfo(Variant::FLOAT, "text_editor/completion/code_complete_delay", PROPERTY_HINT_RANGE, "0.01, 5, 0.01");
_initial_set("text_editor/completion/put_callhint_tooltip_below_current_line", true);
- _initial_set("text_editor/completion/callhint_tooltip_offset", Vector2());
_initial_set("text_editor/completion/complete_file_paths", true);
_initial_set("text_editor/completion/add_type_hints", false);
_initial_set("text_editor/completion/use_single_quotes", false);
@@ -691,11 +689,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/guides_color", Color(0.6, 0.0, 0.8));
_initial_set("editors/2d/smart_snapping_line_color", Color(0.9, 0.1, 0.1));
_initial_set("editors/2d/bone_width", 5);
- _initial_set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.9));
- _initial_set("editors/2d/bone_color2", Color(0.6, 0.6, 0.6, 0.9));
- _initial_set("editors/2d/bone_selected_color", Color(0.9, 0.45, 0.45, 0.9));
- _initial_set("editors/2d/bone_ik_color", Color(0.9, 0.9, 0.45, 0.9));
- _initial_set("editors/2d/bone_outline_color", Color(0.35, 0.35, 0.35));
+ _initial_set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.7));
+ _initial_set("editors/2d/bone_color2", Color(0.6, 0.6, 0.6, 0.7));
+ _initial_set("editors/2d/bone_selected_color", Color(0.9, 0.45, 0.45, 0.7));
+ _initial_set("editors/2d/bone_ik_color", Color(0.9, 0.9, 0.45, 0.7));
+ _initial_set("editors/2d/bone_outline_color", Color(0.35, 0.35, 0.35, 0.5));
_initial_set("editors/2d/bone_outline_size", 2);
_initial_set("editors/2d/viewport_border_color", Color(0.4, 0.4, 1.0, 0.4));
_initial_set("editors/2d/constrain_editor_view", true);
@@ -704,6 +702,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/scroll_to_pan", false);
_initial_set("editors/2d/pan_speed", 20);
+ // Tiles editor
+ _initial_set("editors/tiles_editor/display_grid", true);
+ _initial_set("editors/tiles_editor/grid_color", Color(1.0, 0.5, 0.2, 0.5));
+
// Polygon editor
_initial_set("editors/poly_editor/point_grab_radius", 8);
_initial_set("editors/poly_editor/show_previous_outline", true);
@@ -766,8 +768,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
for (int i = 0; i < list.size(); i++) {
String name = list[i].replace("/", "::");
set("projects/" + name, list[i]);
- };
- };
+ }
+ }
if (p_extra_config->has_section("presets")) {
List<String> keys;
@@ -777,14 +779,13 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
String key = E->get();
Variant val = p_extra_config->get_value("presets", key);
set(key, val);
- };
- };
- };
+ }
+ }
+ }
}
-void EditorSettings::_load_default_text_editor_theme() {
- bool dark_theme = is_dark_theme();
-
+void EditorSettings::_load_godot2_text_editor_theme() {
+ // Godot 2 is only a dark theme; it doesn't have a light theme counterpart.
_initial_set("text_editor/highlighting/symbol_color", Color(0.73, 0.87, 1.0));
_initial_set("text_editor/highlighting/keyword_color", Color(1.0, 1.0, 0.7));
_initial_set("text_editor/highlighting/control_flow_keyword_color", Color(1.0, 0.85, 0.7));
@@ -793,7 +794,7 @@ void EditorSettings::_load_default_text_editor_theme() {
_initial_set("text_editor/highlighting/user_type_color", Color(0.42, 0.67, 0.93));
_initial_set("text_editor/highlighting/comment_color", Color(0.4, 0.4, 0.4));
_initial_set("text_editor/highlighting/string_color", Color(0.94, 0.43, 0.75));
- _initial_set("text_editor/highlighting/background_color", dark_theme ? Color(0.0, 0.0, 0.0, 0.23) : Color(0.2, 0.23, 0.31));
+ _initial_set("text_editor/highlighting/background_color", Color(0.13, 0.12, 0.15));
_initial_set("text_editor/highlighting/completion_background_color", Color(0.17, 0.16, 0.2));
_initial_set("text_editor/highlighting/completion_selected_color", Color(0.26, 0.26, 0.27));
_initial_set("text_editor/highlighting/completion_existing_color", Color(0.13, 0.87, 0.87, 0.87));
@@ -843,7 +844,7 @@ bool EditorSettings::_save_text_editor_theme(String p_file) {
}
bool EditorSettings::_is_default_text_editor_theme(String p_theme_name) {
- return p_theme_name == "default" || p_theme_name == "adaptive" || p_theme_name == "custom";
+ return p_theme_name == "default" || p_theme_name == "godot 2" || p_theme_name == "custom";
}
static Dictionary _get_builtin_script_templates() {
@@ -870,9 +871,8 @@ static void _create_script_templates(const String &p_path) {
Dictionary templates = _get_builtin_script_templates();
List<Variant> keys;
templates.get_key_list(&keys);
- FileAccess *file = FileAccess::create(FileAccess::ACCESS_FILESYSTEM);
-
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ FileAccessRef file = FileAccess::create(FileAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
dir->change_dir(p_path);
for (int i = 0; i < keys.size(); i++) {
if (!dir->file_exists(keys[i])) {
@@ -882,9 +882,6 @@ static void _create_script_templates(const String &p_path) {
file->close();
}
}
-
- memdelete(dir);
- memdelete(file);
}
// PUBLIC METHODS
@@ -894,163 +891,53 @@ EditorSettings *EditorSettings::get_singleton() {
}
void EditorSettings::create() {
+ // IMPORTANT: create() *must* create a valid EditorSettings singleton,
+ // as the rest of the engine code will assume it. As such, it should never
+ // return (incl. via ERR_FAIL) without initializing the singleton member.
+
if (singleton.ptr()) {
- return; //pointless
+ ERR_PRINT("Can't recreate EditorSettings as it already exists.");
+ return;
}
- DirAccess *dir = nullptr;
-
- String data_path;
- String data_dir;
- String config_path;
- String config_dir;
- String cache_path;
- String cache_dir;
+ ClassDB::register_class<EditorSettings>(); // Otherwise it can't be unserialized.
+ String config_file_path;
Ref<ConfigFile> extra_config = memnew(ConfigFile);
- String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
- DirAccess *d = DirAccess::create_for_path(exe_path);
- bool self_contained = false;
-
- if (d->file_exists(exe_path + "/._sc_")) {
- self_contained = true;
- Error err = extra_config->load(exe_path + "/._sc_");
- if (err != OK) {
- ERR_PRINT("Can't load config from path '" + exe_path + "/._sc_'.");
- }
- } else if (d->file_exists(exe_path + "/_sc_")) {
- self_contained = true;
- Error err = extra_config->load(exe_path + "/_sc_");
- if (err != OK) {
- ERR_PRINT("Can't load config from path '" + exe_path + "/_sc_'.");
- }
+ if (!EditorPaths::get_singleton()) {
+ ERR_PRINT("Bug (please report): EditorPaths haven't been initialized, EditorSettings cannot be created properly.");
+ goto fail;
}
- memdelete(d);
- if (self_contained) {
- // editor is self contained, all in same folder
- data_path = exe_path;
- data_dir = data_path.plus_file("editor_data");
- config_path = exe_path;
- config_dir = data_dir;
- cache_path = exe_path;
- cache_dir = data_dir.plus_file("cache");
- } else {
- // Typically XDG_DATA_HOME or %APPDATA%
- data_path = OS::get_singleton()->get_data_path();
- data_dir = data_path.plus_file(OS::get_singleton()->get_godot_dir_name());
- // Can be different from data_path e.g. on Linux or macOS
- config_path = OS::get_singleton()->get_config_path();
- config_dir = config_path.plus_file(OS::get_singleton()->get_godot_dir_name());
- // Can be different from above paths, otherwise a subfolder of data_dir
- cache_path = OS::get_singleton()->get_cache_path();
- if (cache_path == data_path) {
- cache_dir = data_dir.plus_file("cache");
- } else {
- cache_dir = cache_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+ if (EditorPaths::get_singleton()->is_self_contained()) {
+ Error err = extra_config->load(EditorPaths::get_singleton()->get_self_contained_file());
+ if (err != OK) {
+ ERR_PRINT("Can't load extra config from path: " + EditorPaths::get_singleton()->get_self_contained_file());
}
}
- ClassDB::register_class<EditorSettings>(); //otherwise it can't be unserialized
+ if (EditorPaths::get_singleton()->are_paths_valid()) {
+ _create_script_templates(EditorPaths::get_singleton()->get_config_dir().plus_file("script_templates"));
- String config_file_path;
-
- if (data_path != "" && config_path != "" && cache_path != "") {
- // Validate/create data dir and subdirectories
-
- dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (dir->change_dir(data_dir) != OK) {
- dir->make_dir_recursive(data_dir);
- if (dir->change_dir(data_dir) != OK) {
- ERR_PRINT("Cannot create data directory!");
- memdelete(dir);
- goto fail;
- }
- }
-
- if (dir->change_dir("templates") != OK) {
- dir->make_dir("templates");
- } else {
- dir->change_dir("..");
- }
-
- // Validate/create cache dir
-
- if (dir->change_dir(cache_dir) != OK) {
- dir->make_dir_recursive(cache_dir);
- if (dir->change_dir(cache_dir) != OK) {
- ERR_PRINT("Cannot create cache directory!");
- memdelete(dir);
- goto fail;
- }
- }
-
- // Validate/create config dir and subdirectories
-
- if (dir->change_dir(config_dir) != OK) {
- dir->make_dir_recursive(config_dir);
- if (dir->change_dir(config_dir) != OK) {
- ERR_PRINT("Cannot create config directory!");
- memdelete(dir);
- goto fail;
- }
- }
-
- if (dir->change_dir("text_editor_themes") != OK) {
- dir->make_dir("text_editor_themes");
- } else {
- dir->change_dir("..");
- }
-
- if (dir->change_dir("script_templates") != OK) {
- dir->make_dir("script_templates");
- } else {
- dir->change_dir("..");
- }
-
- if (dir->change_dir("feature_profiles") != OK) {
- dir->make_dir("feature_profiles");
- } else {
- dir->change_dir("..");
- }
-
- _create_script_templates(dir->get_current_dir().plus_file("script_templates"));
-
- {
- // Validate/create project-specific editor settings dir.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (da->change_dir(EditorSettings::PROJECT_EDITOR_SETTINGS_PATH) != OK) {
- Error err = da->make_dir_recursive(EditorSettings::PROJECT_EDITOR_SETTINGS_PATH);
- if (err || da->change_dir(EditorSettings::PROJECT_EDITOR_SETTINGS_PATH) != OK) {
- ERR_FAIL_MSG("Failed to create '" + EditorSettings::PROJECT_EDITOR_SETTINGS_PATH + "' folder.");
- }
- }
- }
-
- // Validate editor config file
+ // Validate editor config file.
+ DirAccessRef dir = DirAccess::open(EditorPaths::get_singleton()->get_config_dir());
String config_file_name = "editor_settings-" + itos(VERSION_MAJOR) + ".tres";
- config_file_path = config_dir.plus_file(config_file_name);
+ config_file_path = EditorPaths::get_singleton()->get_config_dir().plus_file(config_file_name);
if (!dir->file_exists(config_file_name)) {
- memdelete(dir);
goto fail;
}
- memdelete(dir);
-
singleton = ResourceLoader::load(config_file_path, "EditorSettings");
if (singleton.is_null()) {
- WARN_PRINT("Could not open config file.");
+ ERR_PRINT("Could not load editor settings from path: " + config_file_path);
goto fail;
}
singleton->save_changed_setting = true;
singleton->config_file_path = config_file_path;
- singleton->settings_dir = config_dir;
- singleton->data_dir = data_dir;
- singleton->cache_dir = cache_dir;
print_verbose("EditorSettings: Load OK!");
@@ -1063,22 +950,20 @@ void EditorSettings::create() {
}
fail:
-
// patch init projects
+ String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
+
if (extra_config->has_section("init_projects")) {
Vector<String> list = extra_config->get_value("init_projects", "list");
for (int i = 0; i < list.size(); i++) {
list.write[i] = exe_path.plus_file(list[i]);
- };
+ }
extra_config->set_value("init_projects", "list", list);
- };
+ }
singleton = Ref<EditorSettings>(memnew(EditorSettings));
singleton->save_changed_setting = true;
singleton->config_file_path = config_file_path;
- singleton->settings_dir = config_dir;
- singleton->data_dir = data_dir;
- singleton->cache_dir = cache_dir;
singleton->_load_defaults(extra_config);
singleton->setup_language();
singleton->setup_network();
@@ -1306,46 +1191,31 @@ void EditorSettings::add_property_hint(const PropertyInfo &p_hint) {
hints[p_hint.name] = p_hint;
}
-// Data directories
-
-String EditorSettings::get_data_dir() const {
- return data_dir;
-}
+// Editor data and config directories
+// EditorPaths::create() is responsible for the creation of these directories.
String EditorSettings::get_templates_dir() const {
- return get_data_dir().plus_file("templates");
-}
-
-// Config directories
-
-String EditorSettings::get_settings_dir() const {
- return settings_dir;
+ return EditorPaths::get_singleton()->get_data_dir().plus_file("templates");
}
String EditorSettings::get_project_settings_dir() const {
- return EditorSettings::PROJECT_EDITOR_SETTINGS_PATH;
+ return EditorPaths::get_singleton()->get_project_data_dir().plus_file("editor");
}
String EditorSettings::get_text_editor_themes_dir() const {
- return get_settings_dir().plus_file("text_editor_themes");
+ return EditorPaths::get_singleton()->get_config_dir().plus_file("text_editor_themes");
}
String EditorSettings::get_script_templates_dir() const {
- return get_settings_dir().plus_file("script_templates");
+ return EditorPaths::get_singleton()->get_config_dir().plus_file("script_templates");
}
String EditorSettings::get_project_script_templates_dir() const {
return ProjectSettings::get_singleton()->get("editor/script/templates_search_path");
}
-// Cache directory
-
-String EditorSettings::get_cache_dir() const {
- return cache_dir;
-}
-
String EditorSettings::get_feature_profiles_dir() const {
- return get_settings_dir().plus_file("feature_profiles");
+ return EditorPaths::get_singleton()->get_config_dir().plus_file("feature_profiles");
}
// Metadata
@@ -1432,7 +1302,7 @@ bool EditorSettings::is_dark_theme() {
}
void EditorSettings::list_text_editor_themes() {
- String themes = "Adaptive,Default,Custom";
+ String themes = "Default,Godot 2,Custom";
DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
if (d) {
@@ -1460,8 +1330,8 @@ void EditorSettings::load_text_editor_theme() {
String p_file = get("text_editor/theme/color_theme");
if (_is_default_text_editor_theme(p_file.get_file().to_lower())) {
- if (p_file == "Default") {
- _load_default_text_editor_theme();
+ if (p_file == "Godot 2") {
+ _load_godot2_text_editor_theme();
}
return; // sorry for "Settings changed" console spam
}
@@ -1572,7 +1442,7 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c
}
String EditorSettings::get_editor_layouts_config() const {
- return get_settings_dir().plus_file("editor_layouts.cfg");
+ return EditorPaths::get_singleton()->get_config_dir().plus_file("editor_layouts.cfg");
}
// Shortcuts
@@ -1656,10 +1526,10 @@ Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p
ie->set_unicode(p_keycode & KEY_CODE_MASK);
ie->set_keycode(p_keycode & KEY_CODE_MASK);
- ie->set_shift(bool(p_keycode & KEY_MASK_SHIFT));
- ie->set_alt(bool(p_keycode & KEY_MASK_ALT));
- ie->set_control(bool(p_keycode & KEY_MASK_CTRL));
- ie->set_metakey(bool(p_keycode & KEY_MASK_META));
+ ie->set_shift_pressed(bool(p_keycode & KEY_MASK_SHIFT));
+ ie->set_alt_pressed(bool(p_keycode & KEY_MASK_ALT));
+ ie->set_ctrl_pressed(bool(p_keycode & KEY_MASK_CTRL));
+ ie->set_meta_pressed(bool(p_keycode & KEY_MASK_META));
}
if (!EditorSettings::get_singleton()) {
@@ -1774,7 +1644,6 @@ void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert);
ClassDB::bind_method(D_METHOD("add_property_info", "info"), &EditorSettings::_add_property_info_bind);
- ClassDB::bind_method(D_METHOD("get_settings_dir"), &EditorSettings::get_settings_dir);
ClassDB::bind_method(D_METHOD("get_project_settings_dir"), &EditorSettings::get_project_settings_dir);
ClassDB::bind_method(D_METHOD("set_project_metadata", "section", "key", "data"), &EditorSettings::set_project_metadata);
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index e5f8527faf..d6a9a9d1b9 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -36,6 +36,7 @@
#include "core/object/class_db.h"
#include "core/os/thread_safe.h"
#include "core/string/translation.h"
+#include "editor/editor_paths.h"
#include "scene/gui/shortcut.h"
class EditorPlugin;
@@ -46,7 +47,6 @@ class EditorSettings : public Resource {
_THREAD_SAFE_CLASS_
public:
- inline static const String PROJECT_EDITOR_SETTINGS_PATH = "res://.godot/editor";
struct Plugin {
EditorPlugin *instance = nullptr;
String path;
@@ -87,12 +87,7 @@ private:
mutable Map<String, Ref<Shortcut>> shortcuts;
Map<String, List<Ref<InputEvent>>> builtin_action_overrides;
- String resource_path;
- String settings_dir;
- String data_dir;
- String cache_dir;
String config_file_path;
- String project_config_dir;
Vector<String> favorites;
Vector<String> recent_dirs;
@@ -108,7 +103,7 @@ private:
void _add_property_info_bind(const Dictionary &p_info);
void _load_defaults(Ref<ConfigFile> p_extra_config = Ref<ConfigFile>());
- void _load_default_text_editor_theme();
+ void _load_godot2_text_editor_theme();
bool _save_text_editor_theme(String p_file);
bool _is_default_text_editor_theme(String p_theme_name);
@@ -153,12 +148,10 @@ public:
String get_data_dir() const;
String get_templates_dir() const;
- String get_settings_dir() const;
String get_project_settings_dir() const;
String get_text_editor_themes_dir() const;
String get_script_templates_dir() const;
String get_project_script_templates_dir() const;
- String get_cache_dir() const;
String get_feature_profiles_dir() const;
void set_project_metadata(const String &p_section, const String &p_key, Variant p_data);
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index dba53a9708..657dcfa760 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -70,6 +70,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
grabbing_spinner_dist_cache = 0;
pre_grab_value = get_value();
grabbing_spinner = false;
+ grabbing_spinner_mouse_pos = get_global_mouse_position();
}
} else {
if (grabbing_spinner_attempt) {
@@ -96,7 +97,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid()) {
if (grabbing_spinner_attempt) {
double diff_x = mm->get_relative().x;
- if (mm->get_shift() && grabbing_spinner) {
+ if (mm->is_shift_pressed() && grabbing_spinner) {
diff_x *= 0.1;
}
grabbing_spinner_dist_cache += diff_x;
@@ -115,7 +116,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
pre_grab_value = get_max();
}
- if (mm->get_control()) {
+ if (mm->is_ctrl_pressed()) {
// If control was just pressed, don't make the value do a huge jump in magnitude.
if (grabbing_spinner_dist_cache != 0) {
pre_grab_value += grabbing_spinner_dist_cache * get_step();
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 2c4f4e2973..fa543b7455 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -144,70 +144,70 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
Set<StringName> exceptions;
if (!p_dark_theme) {
- // convert color: FROM TO
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#5a5a5a"); // common icon color
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#414141"); // white
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#363636"); // script darker color
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f9f9f9", "#606060"); // scrollbar grabber highlight color
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#cea4f1", "#a85de9"); // animation
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc9c9c", "#cd3838"); // spatial
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5b7f3", "#3d64dd"); // 2d
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#708cea", "#1a3eac"); // 2d dark
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#2fa139"); // control
-
- // rainbow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff7070", "#ff2929"); // red
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffeb70", "#ffe337"); // yellow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9dff70", "#74ff34"); // green
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70ffb9", "#2cff98"); // aqua
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70deff", "#22ccff"); // blue
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9f70ff", "#702aff"); // purple
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff70ac", "#ff2781"); // pink
-
- // audio gradient
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff4040"); // red
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1dc7a", "#d6cf4b"); // yellow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00f010"); // green
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#fea900"); // mesh (orange)
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#40a2ff", "#68b6ff"); // shape (blue)
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff3333"); // remove (red)
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00db50"); // add (green)
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84c2ff", "#5caeff"); // selection (blue)
+ // Convert color: FROM TO
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#5a5a5a"); // Common icon color
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#414141"); // White
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#363636"); // Script darker color
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f9f9f9", "#606060"); // Scrollbar grabber highlight color
+
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#c38ef1", "#a85de9"); // Animation
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc7f7f", "#cd3838"); // Spatial
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#8da5f3", "#3d64dd"); // 2D
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#4b70ea", "#1a3eac"); // 2D Dark
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#8eef97", "#2fa139"); // Control
+
+ // Rainbow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff4545", "#ff2929"); // Red
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffe345", "#ffe337"); // Yellow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#80ff45", "#74ff34"); // Green
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#45ffa2", "#2cff98"); // Aqua
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#45d7ff", "#22ccff"); // Blue
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#8045ff", "#702aff"); // Purple
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff4596", "#ff2781"); // Pink
+
+ // Audio gradient
+ // Red is defined further below.
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1da5b", "#d6cf4b"); // Yellow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#5fff97", "#00f010"); // Green
+
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffca5f", "#fea900"); // Mesh resource (orange)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#0787ff", "#68b6ff"); // Shape resource (blue)
+
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff5f5f", "#ff3333"); // Red audio gradient + remove (red)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#5fff97", "#00db50"); // Add (green)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#5fb2ff", "#5caeff"); // Selection (blue)
// Animation editor tracks
- // The property track icon color is set by the common icon color
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea9568", "#bd5e2c"); // 3D Transform track
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#66f376", "#16a827"); // Call Method track
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#5792f6", "#236be6"); // Bezier Curve track
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#eae668", "#9f9722"); // Audio Playback track
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b76ef0", "#9853ce"); // Animation Playback track
+ // The property track icon color is set by the common icon color.
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea7940", "#bd5e2c"); // 3D Transform track
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#3cf34e", "#16a827"); // Call Method track
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#2877f6", "#236be6"); // Bezier Curve track
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#eae440", "#9f9722"); // Audio Playback track
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a448f0", "#9853ce"); // Animation Playback track
// TileSet editor icons
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fce844", "#aa8d24"); // New Single Tile
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#4490fc", "#0350bd"); // New Autotile
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#c9cfd4", "#828f9b"); // New Atlas
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#69ecbd", "#25e3a0"); // VS variant
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#8da6f0", "#6d8eeb"); // VS bool
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#7dc6ef", "#4fb2e9"); // VS int
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#61daf4", "#27ccf0"); // VS float
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#6ba7ec", "#4690e7"); // VS string
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#bd91f1", "#ad76ee"); // VS vector2
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f191a5", "#ee758e"); // VS rect
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e286f0", "#dc6aed"); // VS vector3
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#c4ec69", "#96ce1a"); // VS transform2D
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f77070", "#f77070"); // VS plane
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ec69a3", "#ec69a3"); // VS quat
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ee7991", "#ee7991"); // VS aabb
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e3ec69", "#b2bb19"); // VS basis
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f6a86e", "#f49047"); // VS transform
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#6993ec", "#6993ec"); // VS path
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#69ec9a", "#2ce573"); // VS rid
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#79f3e8", "#12d5c3"); // VS object
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#77edb1", "#57e99f"); // VS dict
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fce00e", "#aa8d24"); // New Single Tile
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#0e71fc", "#0350bd"); // New Autotile
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#c6ced4", "#828f9b"); // New Atlas
+
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#41ecad", "#25e3a0"); // VisualScript variant
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#6f91f0", "#6d8eeb"); // VisualScript bool
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#5abbef", "#4fb2e9"); // VisualScript int
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#35d4f4", "#27ccf0"); // VisualScript float
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#4593ec", "#4690e7"); // VisualScript String
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ac73f1", "#ad76ee"); // VisualScript Vector2
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f1738f", "#ee758e"); // VisualScript Rect2
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#de66f0", "#dc6aed"); // VisualScript Vector3
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b9ec41", "#96ce1a"); // VisualScript Transform2D
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f74949", "#f77070"); // VisualScript Plane
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ec418e", "#ec69a3"); // VisualScript Quat
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ee5677", "#ee7991"); // VisualScript AABB
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1ec41", "#b2bb19"); // VisualScript Basis
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f68f45", "#f49047"); // VisualScript Transform
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#417aec", "#6993ec"); // VisualScript NodePath
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#41ec80", "#2ce573"); // VisualScript RID
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#55f3e3", "#12d5c3"); // VisualScript Object
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#54ed9e", "#57e99f"); // VisualScript Dictionary
exceptions.insert("EditorPivot");
exceptions.insert("EditorHandle");
@@ -216,6 +216,8 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
exceptions.insert("Sky");
exceptions.insert("EditorControlAnchor");
exceptions.insert("DefaultProjectIcon");
+ exceptions.insert("GuiChecked");
+ exceptions.insert("GuiRadioChecked");
exceptions.insert("GuiCloseCustomizable");
exceptions.insert("GuiGraphNodePort");
exceptions.insert("GuiResizer");
@@ -328,16 +330,18 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
preset_contrast = default_contrast;
} else if (preset == "Light") {
preset_accent_color = Color(0.18, 0.50, 1.00);
- preset_base_color = Color(1.00, 1.00, 1.00);
- preset_contrast = 0.08;
+ preset_base_color = Color(0.9, 0.9, 0.9);
+ // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
+ preset_contrast = -0.08;
} else if (preset == "Solarized (Dark)") {
preset_accent_color = Color(0.15, 0.55, 0.82);
preset_base_color = Color(0.04, 0.23, 0.27);
preset_contrast = default_contrast;
} else if (preset == "Solarized (Light)") {
preset_accent_color = Color(0.15, 0.55, 0.82);
- preset_base_color = Color(0.99, 0.96, 0.89);
- preset_contrast = 0.08;
+ preset_base_color = Color(0.89, 0.86, 0.79);
+ // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
+ preset_contrast = -0.08;
} else { // Default
preset_accent_color = Color(0.44, 0.73, 0.98);
preset_base_color = Color(0.21, 0.24, 0.29);
@@ -461,7 +465,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Ensure borders are visible when using an editor scale below 100%.
const int border_width = CLAMP(border_size, 0, 2) * MAX(1, EDSCALE);
- const int corner_width = CLAMP(corner_radius, 0, 6) * EDSCALE;
+ const int corner_width = CLAMP(corner_radius, 0, 6);
const int default_margin_size = 4;
const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 2);
@@ -782,14 +786,17 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_property_bg->set_bg_color(highlight_color);
style_property_bg->set_border_width_all(0);
- theme->set_constant("font_offset", "EditorProperty", 1 * EDSCALE);
+ theme->set_constant("font_offset", "EditorProperty", 8 * EDSCALE);
theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg);
theme->set_stylebox("bg", "EditorProperty", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
theme->set_constant("vseparation", "EditorProperty", (extra_spacing + default_margin_size) * EDSCALE);
theme->set_color("error_color", "EditorProperty", error_color);
theme->set_color("property_color", "EditorProperty", property_color);
- theme->set_constant("inspector_margin", "Editor", 8 * EDSCALE);
+ Color inspector_section_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.35);
+ theme->set_color("font_color", "EditorInspectorSection", inspector_section_color);
+
+ theme->set_constant("inspector_margin", "Editor", 12 * EDSCALE);
// Tree & ItemList background
Ref<StyleBoxFlat> style_tree_bg = style_default->duplicate();
@@ -798,8 +805,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_tree_bg->set_border_color(dark_color_3);
theme->set_stylebox("bg", "Tree", style_tree_bg);
- const Color guide_color = mono_color * Color(1, 1, 1, 0.05);
- Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity);
// Tree
theme->set_icon("checked", "Tree", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons"));
@@ -816,19 +821,33 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_color", "Tree", font_color);
theme->set_color("font_selected_color", "Tree", mono_color);
theme->set_color("title_button_color", "Tree", font_color);
- theme->set_color("guide_color", "Tree", guide_color);
- theme->set_color("relationship_line_color", "Tree", relationship_line_color);
theme->set_color("drop_position_color", "Tree", accent_color);
theme->set_constant("vseparation", "Tree", widget_default_margin.y - EDSCALE);
theme->set_constant("hseparation", "Tree", 6 * EDSCALE);
theme->set_constant("guide_width", "Tree", border_width);
theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE);
theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE);
- theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01);
- theme->set_constant("draw_guides", "Tree", relationship_line_opacity < 0.01);
theme->set_constant("scroll_border", "Tree", 40 * EDSCALE);
theme->set_constant("scroll_speed", "Tree", 12);
+ const Color guide_color = mono_color * Color(1, 1, 1, 0.05);
+ Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity);
+
+ theme->set_constant("draw_guides", "Tree", relationship_line_opacity < 0.01);
+ theme->set_color("guide_color", "Tree", guide_color);
+
+ int relationship_line_width = 1;
+ Color parent_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.45, 0.0, 1.0));
+ Color children_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.25, 0.0, 1.0));
+ theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01);
+ theme->set_constant("relationship_line_width", "Tree", relationship_line_width);
+ theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2);
+ theme->set_constant("children_hl_line_width", "Tree", relationship_line_width);
+ theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3);
+ theme->set_color("relationship_line_color", "Tree", relationship_line_color);
+ theme->set_color("parent_hl_line_color", "Tree", parent_line_color);
+ theme->set_color("children_hl_line_color", "Tree", children_line_color);
+
Ref<StyleBoxFlat> style_tree_btn = style_default->duplicate();
style_tree_btn->set_bg_color(highlight_color);
style_tree_btn->set_border_width_all(0);
@@ -869,6 +888,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("prop_subsection", "Editor", prop_subsection_color);
theme->set_color("drop_position_color", "Tree", accent_color);
+ Ref<StyleBoxFlat> category_bg = style_default->duplicate();
+ // Make Trees easier to distinguish from other controls by using a darker background color.
+ category_bg->set_bg_color(prop_category_color);
+ category_bg->set_border_color(prop_category_color);
+ theme->set_stylebox("prop_category_style", "Editor", category_bg);
+
// ItemList
Ref<StyleBoxFlat> style_itemlist_bg = style_default->duplicate();
style_itemlist_bg->set_bg_color(dark_color_1);
@@ -926,7 +951,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_content_panel->set_border_color(dark_color_3);
style_content_panel->set_border_width_all(border_width);
// compensate the border
- style_content_panel->set_default_margin(SIDE_TOP, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(SIDE_TOP, (2 + margin_size_extra) * EDSCALE);
style_content_panel->set_default_margin(SIDE_RIGHT, margin_size_extra * EDSCALE);
style_content_panel->set_default_margin(SIDE_BOTTOM, margin_size_extra * EDSCALE);
style_content_panel->set_default_margin(SIDE_LEFT, margin_size_extra * EDSCALE);
@@ -935,14 +960,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_content_panel->set_border_color(dark_color_2);
theme->set_stylebox("panel", "TabContainer", style_content_panel);
- // this is the stylebox used in 3d and 2d viewports (no borders)
- Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
- style_content_panel_vp->set_default_margin(SIDE_LEFT, border_width * 2);
- style_content_panel_vp->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE);
- style_content_panel_vp->set_default_margin(SIDE_RIGHT, border_width * 2);
- style_content_panel_vp->set_default_margin(SIDE_BOTTOM, border_width * 2);
- theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp);
-
// These styleboxes can be used on tabs against the base color background (e.g. nested tabs).
Ref<StyleBoxFlat> style_tab_selected_odd = style_tab_selected->duplicate();
style_tab_selected_odd->set_bg_color(disabled_bg_color);
@@ -952,6 +969,22 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_content_panel_odd->set_bg_color(disabled_bg_color);
theme->set_stylebox("panel_odd", "TabContainer", style_content_panel_odd);
+ // This stylebox is used in 3d and 2d viewports (no borders).
+ Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
+ style_content_panel_vp->set_default_margin(SIDE_LEFT, border_width * 2);
+ style_content_panel_vp->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE);
+ style_content_panel_vp->set_default_margin(SIDE_RIGHT, border_width * 2);
+ style_content_panel_vp->set_default_margin(SIDE_BOTTOM, border_width * 2);
+ theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp);
+
+ // This stylebox is used by preview tabs in the Theme Editor.
+ Ref<StyleBoxFlat> style_theme_preview_tab = style_tab_selected_odd->duplicate();
+ style_theme_preview_tab->set_expand_margin_size(SIDE_BOTTOM, 5 * EDSCALE);
+ theme->set_stylebox("ThemeEditorPreviewFG", "EditorStyles", style_theme_preview_tab);
+ Ref<StyleBoxFlat> style_theme_preview_bg_tab = style_tab_unselected->duplicate();
+ style_theme_preview_bg_tab->set_expand_margin_size(SIDE_BOTTOM, 2 * EDSCALE);
+ theme->set_stylebox("ThemeEditorPreviewBG", "EditorStyles", style_theme_preview_bg_tab);
+
// Separators
theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width)));
theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width), 0, 0, true));
@@ -1321,6 +1354,15 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_info_3d_viewport->set_border_width_all(0);
theme->set_stylebox("Information3dViewport", "EditorStyles", style_info_3d_viewport);
+ // Theme editor.
+ theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25));
+ Color theme_preview_picker_bg_color = accent_color;
+ theme_preview_picker_bg_color.a = 0.2;
+ Ref<StyleBoxFlat> theme_preview_picker_sb = make_flat_stylebox(theme_preview_picker_bg_color, 0, 0, 0, 0);
+ theme_preview_picker_sb->set_border_color(accent_color);
+ theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE);
+ theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb);
+
// adaptive script theme constants
// for comments and elements with lower relevance
const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5);
@@ -1342,7 +1384,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color comment_color = dim_color;
const Color string_color = (dark_theme ? Color(1.0, 0.85, 0.26) : Color(1.0, 0.82, 0.09)).lerp(mono_color, dark_theme ? 0.5 : 0.3);
- const Color te_background_color = dark_theme ? background_color : base_color;
+ // Use the brightest background color on a light theme (which generally uses a negative contrast rate).
+ const Color te_background_color = dark_theme ? background_color : dark_color_3;
const Color completion_background_color = dark_theme ? base_color : background_color;
const Color completion_selected_color = alpha1;
const Color completion_existing_color = alpha2;
@@ -1371,7 +1414,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
EditorSettings *setting = EditorSettings::get_singleton();
String text_editor_color_theme = setting->get("text_editor/theme/color_theme");
- if (text_editor_color_theme == "Adaptive") {
+ if (text_editor_color_theme == "Default") {
setting->set_initial_value("text_editor/highlighting/symbol_color", symbol_color, true);
setting->set_initial_value("text_editor/highlighting/keyword_color", keyword_color, true);
setting->set_initial_value("text_editor/highlighting/control_flow_keyword_color", control_flow_keyword_color, true);
@@ -1407,7 +1450,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
setting->set_initial_value("text_editor/highlighting/code_folding_color", code_folding_color, true);
setting->set_initial_value("text_editor/highlighting/search_result_color", search_result_color, true);
setting->set_initial_value("text_editor/highlighting/search_result_border_color", search_result_border_color, true);
- } else if (text_editor_color_theme == "Default") {
+ } else if (text_editor_color_theme == "Godot 2") {
setting->load_text_editor_theme();
}
diff --git a/editor/editor_translation_parser.cpp b/editor/editor_translation_parser.cpp
index 49d5cf1fd3..27d428e682 100644
--- a/editor/editor_translation_parser.cpp
+++ b/editor/editor_translation_parser.cpp
@@ -31,8 +31,8 @@
#include "editor_translation_parser.h"
#include "core/error/error_macros.h"
+#include "core/io/file_access.h"
#include "core/object/script_language.h"
-#include "core/os/file_access.h"
#include "core/templates/set.h"
EditorTranslationParser *EditorTranslationParser::singleton = nullptr;
@@ -42,10 +42,10 @@ Error EditorTranslationParserPlugin::parse_file(const String &p_path, Vector<Str
return ERR_UNAVAILABLE;
}
- if (get_script_instance()->has_method("parse_file")) {
+ if (get_script_instance()->has_method("_parse_file")) {
Array ids;
Array ids_ctx_plural;
- get_script_instance()->call("parse_file", p_path, ids, ids_ctx_plural);
+ get_script_instance()->call("_parse_file", p_path, ids, ids_ctx_plural);
// Add user's extracted translatable messages.
for (int i = 0; i < ids.size(); i++) {
@@ -75,8 +75,8 @@ void EditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_ex
return;
}
- if (get_script_instance()->has_method("get_recognized_extensions")) {
- Array extensions = get_script_instance()->call("get_recognized_extensions");
+ if (get_script_instance()->has_method("_get_recognized_extensions")) {
+ Array extensions = get_script_instance()->call("_get_recognized_extensions");
for (int i = 0; i < extensions.size(); i++) {
r_extensions->push_back(extensions[i]);
}
@@ -86,8 +86,8 @@ void EditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_ex
}
void EditorTranslationParserPlugin::_bind_methods() {
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::NIL, "parse_file", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::ARRAY, "msgids"), PropertyInfo(Variant::ARRAY, "msgids_context_plural")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::ARRAY, "get_recognized_extensions"));
+ BIND_VMETHOD(MethodInfo(Variant::NIL, "_parse_file", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::ARRAY, "msgids"), PropertyInfo(Variant::ARRAY, "msgids_context_plural")));
+ BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_recognized_extensions"));
}
/////////////////////////
diff --git a/editor/editor_translation_parser.h b/editor/editor_translation_parser.h
index 4f8f3537f2..7013bbb8c4 100644
--- a/editor/editor_translation_parser.h
+++ b/editor/editor_translation_parser.h
@@ -32,10 +32,10 @@
#define EDITOR_TRANSLATION_PARSER_H
#include "core/error/error_list.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class EditorTranslationParserPlugin : public Reference {
- GDCLASS(EditorTranslationParserPlugin, Reference);
+class EditorTranslationParserPlugin : public RefCounted {
+ GDCLASS(EditorTranslationParserPlugin, RefCounted);
protected:
static void _bind_methods();
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 0f5c01be0e..76c6fcc3d3 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -31,9 +31,9 @@
#include "export_template_manager.h"
#include "core/input/input.h"
+#include "core/io/dir_access.h"
#include "core/io/json.h"
#include "core/io/zip_io.h"
-#include "core/os/dir_access.h"
#include "core/os/keyboard.h"
#include "core/version.h"
#include "editor_node.h"
@@ -41,141 +41,336 @@
#include "progress_dialog.h"
#include "scene/gui/link_button.h"
-void ExportTemplateManager::_update_template_list() {
- while (current_hb->get_child_count()) {
- memdelete(current_hb->get_child(0));
- }
-
- while (installed_vb->get_child_count()) {
- memdelete(installed_vb->get_child(0));
- }
+void ExportTemplateManager::_update_template_status() {
+ // Fetch installed templates from the file system.
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- Error err = d->change_dir(EditorSettings::get_singleton()->get_templates_dir());
+ Error err = da->change_dir(templates_dir);
+ ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir + "'.");
Set<String> templates;
- d->list_dir_begin();
+ da->list_dir_begin();
if (err == OK) {
- String c = d->get_next();
+ String c = da->get_next();
while (c != String()) {
- if (d->current_is_dir() && !c.begins_with(".")) {
+ if (da->current_is_dir() && !c.begins_with(".")) {
templates.insert(c);
}
- c = d->get_next();
+ c = da->get_next();
}
}
- d->list_dir_end();
-
- memdelete(d);
+ da->list_dir_end();
+ memdelete(da);
+ // Update the state of the current version.
String current_version = VERSION_FULL_CONFIG;
- // Downloadable export templates are only available for stable and official alpha/beta/RC builds
- // (which always have a number following their status, e.g. "alpha1").
- // Therefore, don't display download-related features when using a development version
- // (whose builds aren't numbered).
- const bool downloads_available =
- String(VERSION_STATUS) != String("dev") &&
- String(VERSION_STATUS) != String("alpha") &&
- String(VERSION_STATUS) != String("beta") &&
- String(VERSION_STATUS) != String("rc");
-
- Label *current = memnew(Label);
- current->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- current_hb->add_child(current);
+ current_value->set_text(current_version);
if (templates.has(current_version)) {
- current->add_theme_color_override("font_color", current->get_theme_color("success_color", "Editor"));
-
- // Only display a redownload button if it can be downloaded in the first place
- if (downloads_available) {
- Button *redownload = memnew(Button);
- redownload->set_text(TTR("Redownload"));
- current_hb->add_child(redownload);
- redownload->connect("pressed", callable_mp(this, &ExportTemplateManager::_download_template), varray(current_version));
- }
+ current_missing_label->hide();
+ current_installed_label->show();
+
+ current_installed_hb->show();
+ current_version_exists = true;
+ } else {
+ current_installed_label->hide();
+ current_missing_label->show();
- Button *uninstall = memnew(Button);
- uninstall->set_text(TTR("Uninstall"));
- current_hb->add_child(uninstall);
- current->set_text(current_version + " " + TTR("(Installed)"));
- uninstall->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template), varray(current_version));
+ current_installed_hb->hide();
+ current_version_exists = false;
+ }
+ if (is_downloading_templates) {
+ install_options_vb->hide();
+ download_progress_hb->show();
} else {
- current->add_theme_color_override("font_color", current->get_theme_color("error_color", "Editor"));
- Button *redownload = memnew(Button);
- redownload->set_text(TTR("Download"));
+ download_progress_hb->hide();
+ install_options_vb->show();
- if (!downloads_available) {
- redownload->set_disabled(true);
- redownload->set_tooltip(TTR("Official export templates aren't available for development builds."));
+ if (templates.has(current_version)) {
+ current_installed_path->set_text(templates_dir.plus_file(current_version));
}
-
- redownload->connect("pressed", callable_mp(this, &ExportTemplateManager::_download_template), varray(current_version));
- current_hb->add_child(redownload);
- current->set_text(current_version + " " + TTR("(Missing)"));
}
+ // Update the list of other installed versions.
+ installed_table->clear();
+ TreeItem *installed_root = installed_table->create_item();
+
for (Set<String>::Element *E = templates.back(); E; E = E->prev()) {
- String text = E->get();
- if (text == current_version) {
+ String version_string = E->get();
+ if (version_string == current_version) {
continue;
}
- HBoxContainer *hbc = memnew(HBoxContainer);
- Label *version = memnew(Label);
- version->set_modulate(current->get_theme_color("disabled_font_color", "Editor"));
- version->set_text(text);
- version->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- hbc->add_child(version);
+ TreeItem *ti = installed_table->create_item(installed_root);
+ ti->set_text(0, version_string);
+
+ ti->add_button(0, get_theme_icon("Folder", "EditorIcons"), OPEN_TEMPLATE_FOLDER, false, TTR("Open the folder containing these templates."));
+ ti->add_button(0, get_theme_icon("Remove", "EditorIcons"), UNINSTALL_TEMPLATE, false, TTR("Uninstall these templates."));
+ }
+}
+
+void ExportTemplateManager::_download_current() {
+ if (is_downloading_templates) {
+ return;
+ }
+ is_downloading_templates = true;
- Button *uninstall = memnew(Button);
+ install_options_vb->hide();
+ download_progress_hb->show();
- uninstall->set_text(TTR("Uninstall"));
- hbc->add_child(uninstall);
- uninstall->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template), varray(E->get()));
+ if (mirrors_available) {
+ String mirror_url = _get_selected_mirror();
+ if (mirror_url.is_empty()) {
+ _set_current_progress_status(TTR("There are no mirrors available."), true);
+ return;
+ }
- installed_vb->add_child(hbc);
+ _download_template(mirror_url, true);
+ } else if (!mirrors_available && !is_refreshing_mirrors) {
+ _set_current_progress_status(TTR("Retrieving the mirror list..."));
+ _refresh_mirrors();
}
}
-void ExportTemplateManager::_download_template(const String &p_version) {
- while (template_list->get_child_count()) {
- memdelete(template_list->get_child(0));
- }
- template_downloader->popup_centered();
- template_list_state->set_text(TTR("Retrieving mirrors, please wait..."));
- template_download_progress->set_max(100);
- template_download_progress->set_value(0);
- request_mirror->request("https://godotengine.org/mirrorlist/" + p_version + ".json");
- template_list_state->show();
- template_download_progress->show();
+void ExportTemplateManager::_download_template(const String &p_url, bool p_skip_check) {
+ if (!p_skip_check && is_downloading_templates) {
+ return;
+ }
+ is_downloading_templates = true;
+
+ install_options_vb->hide();
+ download_progress_hb->show();
+ _set_current_progress_status(TTR("Starting the download..."));
+
+ download_templates->set_download_file(EditorPaths::get_singleton()->get_cache_dir().plus_file("tmp_templates.tpz"));
+ download_templates->set_use_threads(true);
+
+ Error err = download_templates->request(p_url);
+ if (err != OK) {
+ _set_current_progress_status(TTR("Error requesting URL:") + " " + p_url, true);
+ return;
+ }
+
+ set_process(true);
+ _set_current_progress_status(TTR("Connecting to the mirror..."));
}
-void ExportTemplateManager::_uninstall_template(const String &p_version) {
- remove_confirm->set_text(vformat(TTR("Remove template version '%s'?"), p_version));
- remove_confirm->popup_centered();
- to_remove = p_version;
+void ExportTemplateManager::_download_template_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data) {
+ switch (p_status) {
+ case HTTPRequest::RESULT_CANT_RESOLVE: {
+ _set_current_progress_status(TTR("Can't resolve the requested address."), true);
+ } break;
+ case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED:
+ case HTTPRequest::RESULT_CONNECTION_ERROR:
+ case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH:
+ case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR:
+ case HTTPRequest::RESULT_CANT_CONNECT: {
+ _set_current_progress_status(TTR("Can't connect to the mirror."), true);
+ } break;
+ case HTTPRequest::RESULT_NO_RESPONSE: {
+ _set_current_progress_status(TTR("No response from the mirror."), true);
+ } break;
+ case HTTPRequest::RESULT_REQUEST_FAILED: {
+ _set_current_progress_status(TTR("Request failed."), true);
+ } break;
+ case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: {
+ _set_current_progress_status(TTR("Request ended up in a redirect loop."), true);
+ } break;
+ default: {
+ if (p_code != 200) {
+ _set_current_progress_status(TTR("Request failed:") + " " + itos(p_code), true);
+ } else {
+ _set_current_progress_status(TTR("Download complete; extracting templates..."));
+ String path = download_templates->get_download_file();
+
+ is_downloading_templates = false;
+ bool ret = _install_file_selected(path, true);
+ if (ret) {
+ // Clean up downloaded file.
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Error err = da->remove(path);
+ if (err != OK) {
+ EditorNode::get_singleton()->add_io_error(TTR("Cannot remove temporary file:") + "\n" + path + "\n");
+ }
+ } else {
+ EditorNode::get_singleton()->add_io_error(vformat(TTR("Templates installation failed.\nThe problematic templates archives can be found at '%s'."), path));
+ }
+ }
+ } break;
+ }
+
+ set_process(false);
}
-void ExportTemplateManager::_uninstall_template_confirm() {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
- Error err = da->change_dir(templates_dir);
- ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir + "'.");
- err = da->change_dir(to_remove);
- ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir.plus_file(to_remove) + "'.");
+void ExportTemplateManager::_cancel_template_download() {
+ if (!is_downloading_templates) {
+ return;
+ }
- err = da->erase_contents_recursive();
- ERR_FAIL_COND_MSG(err != OK, "Could not remove all templates in '" + templates_dir.plus_file(to_remove) + "'.");
+ download_templates->cancel_request();
+ download_progress_hb->hide();
+ install_options_vb->show();
+ is_downloading_templates = false;
+}
- da->change_dir("..");
- err = da->remove(to_remove);
- ERR_FAIL_COND_MSG(err != OK, "Could not remove templates directory at '" + templates_dir.plus_file(to_remove) + "'.");
+void ExportTemplateManager::_refresh_mirrors() {
+ if (is_refreshing_mirrors) {
+ return;
+ }
+ is_refreshing_mirrors = true;
+
+ String current_version = VERSION_FULL_CONFIG;
+ const String mirrors_metadata_url = "https://godotengine.org/mirrorlist/" + current_version + ".json";
+ request_mirrors->request(mirrors_metadata_url);
+}
+
+void ExportTemplateManager::_refresh_mirrors_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data) {
+ if (p_status != HTTPRequest::RESULT_SUCCESS || p_code != 200) {
+ EditorNode::get_singleton()->show_warning(TTR("Error getting the list of mirrors."));
+ is_refreshing_mirrors = false;
+ if (is_downloading_templates) {
+ _cancel_template_download();
+ }
+ return;
+ }
+
+ String response_json;
+ {
+ const uint8_t *r = p_data.ptr();
+ response_json.parse_utf8((const char *)r, p_data.size());
+ }
+
+ Variant response;
+ String errs;
+ int errline;
+ Error err = JSON::parse(response_json, response, errs, errline);
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(TTR("Error parsing JSON with the list of mirrors. Please report this issue!"));
+ is_refreshing_mirrors = false;
+ if (is_downloading_templates) {
+ _cancel_template_download();
+ }
+ return;
+ }
+
+ mirrors_list->clear();
+ mirrors_list->add_item(TTR("Best available mirror"), 0);
+
+ mirrors_available = false;
+
+ Dictionary data = response;
+ if (data.has("mirrors")) {
+ Array mirrors = data["mirrors"];
+
+ for (int i = 0; i < mirrors.size(); i++) {
+ Dictionary m = mirrors[i];
+ ERR_CONTINUE(!m.has("url") || !m.has("name"));
+
+ mirrors_list->add_item(m["name"]);
+ mirrors_list->set_item_metadata(i + 1, m["url"]);
+
+ mirrors_available = true;
+ }
+ }
+ if (!mirrors_available) {
+ EditorNode::get_singleton()->show_warning(TTR("No download links found for this version. Direct download is only available for official releases."));
+ if (is_downloading_templates) {
+ _cancel_template_download();
+ }
+ }
+
+ is_refreshing_mirrors = false;
+
+ if (is_downloading_templates) {
+ String mirror_url = _get_selected_mirror();
+ if (mirror_url.is_empty()) {
+ _set_current_progress_status(TTR("There are no mirrors available."), true);
+ return;
+ }
+
+ _download_template(mirror_url, true);
+ }
+}
+
+bool ExportTemplateManager::_humanize_http_status(HTTPRequest *p_request, String *r_status, int *r_downloaded_bytes, int *r_total_bytes) {
+ *r_status = "";
+ *r_downloaded_bytes = -1;
+ *r_total_bytes = -1;
+ bool success = true;
+
+ switch (p_request->get_http_client_status()) {
+ case HTTPClient::STATUS_DISCONNECTED:
+ *r_status = TTR("Disconnected");
+ success = false;
+ break;
+ case HTTPClient::STATUS_RESOLVING:
+ *r_status = TTR("Resolving");
+ break;
+ case HTTPClient::STATUS_CANT_RESOLVE:
+ *r_status = TTR("Can't Resolve");
+ success = false;
+ break;
+ case HTTPClient::STATUS_CONNECTING:
+ *r_status = TTR("Connecting...");
+ break;
+ case HTTPClient::STATUS_CANT_CONNECT:
+ *r_status = TTR("Can't Connect");
+ success = false;
+ break;
+ case HTTPClient::STATUS_CONNECTED:
+ *r_status = TTR("Connected");
+ break;
+ case HTTPClient::STATUS_REQUESTING:
+ *r_status = TTR("Requesting...");
+ break;
+ case HTTPClient::STATUS_BODY:
+ *r_status = TTR("Downloading");
+ *r_downloaded_bytes = p_request->get_downloaded_bytes();
+ *r_total_bytes = p_request->get_body_size();
+
+ if (p_request->get_body_size() > 0) {
+ *r_status += " " + String::humanize_size(p_request->get_downloaded_bytes()) + "/" + String::humanize_size(p_request->get_body_size());
+ } else {
+ *r_status += " " + String::humanize_size(p_request->get_downloaded_bytes());
+ }
+ break;
+ case HTTPClient::STATUS_CONNECTION_ERROR:
+ *r_status = TTR("Connection Error");
+ success = false;
+ break;
+ case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR:
+ *r_status = TTR("SSL Handshake Error");
+ success = false;
+ break;
+ }
+
+ return success;
+}
+
+void ExportTemplateManager::_set_current_progress_status(const String &p_status, bool p_error) {
+ download_progress_bar->hide();
+ download_progress_label->set_text(p_status);
+
+ if (p_error) {
+ download_progress_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ } else {
+ download_progress_label->add_theme_color_override("font_color", get_theme_color("font_color", "Label"));
+ }
+}
+
+void ExportTemplateManager::_set_current_progress_value(float p_value, const String &p_status) {
+ download_progress_bar->show();
+ download_progress_bar->set_value(p_value);
+ download_progress_label->set_text(p_status);
+}
- _update_template_list();
+void ExportTemplateManager::_install_file() {
+ install_file_dialog->popup_file_dialog();
}
-bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_progress) {
+bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_skip_progress) {
// unzClose() will take care of closing the file stored in the unzFile,
// so we don't need to `memdelete(fa)` in this method.
FileAccess *fa = nullptr;
@@ -183,12 +378,13 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io);
if (!pkg) {
- EditorNode::get_singleton()->show_warning(TTR("Can't open export templates zip."));
+ EditorNode::get_singleton()->show_warning(TTR("Can't open the export templates file."));
return false;
}
int ret = unzGoToFirstFile(pkg);
- int fc = 0; //count them and find version
+ // Count them and find version.
+ int fc = 0;
String version;
String contents_dir;
@@ -198,12 +394,11 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
String file = fname;
-
if (file.ends_with("version.txt")) {
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
- //read
+ // Read.
unzOpenCurrentFile(pkg);
ret = unzReadCurrentFile(pkg, data.ptrw(), data.size());
unzCloseCurrentFile(pkg);
@@ -215,7 +410,7 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
// Version number should be of the form major.minor[.patch].status[.module_config]
// so it can in theory have 3 or more slices.
if (data_str.get_slice_count(".") < 3) {
- EditorNode::get_singleton()->show_warning(vformat(TTR("Invalid version.txt format inside templates: %s."), data_str));
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Invalid version.txt format inside the export templates file: %s."), data_str));
unzClose(pkg);
return false;
}
@@ -232,32 +427,29 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
}
if (version == String()) {
- EditorNode::get_singleton()->show_warning(TTR("No version.txt found inside templates."));
+ EditorNode::get_singleton()->show_warning(TTR("No version.txt found inside the export templates file."));
unzClose(pkg);
return false;
}
- String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version);
-
DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version);
Error err = d->make_dir_recursive(template_path);
if (err != OK) {
- EditorNode::get_singleton()->show_warning(TTR("Error creating path for templates:") + "\n" + template_path);
+ EditorNode::get_singleton()->show_warning(TTR("Error creating path for extracting templates:") + "\n" + template_path);
unzClose(pkg);
return false;
}
- ret = unzGoToFirstFile(pkg);
-
EditorProgress *p = nullptr;
- if (p_use_progress) {
+ if (!p_skip_progress) {
p = memnew(EditorProgress("ltask", TTR("Extracting Export Templates"), fc));
}
fc = 0;
-
+ ret = unzGoToFirstFile(pkg);
while (ret == UNZ_OK) {
- //get filename
+ // Get filename.
unz_file_info info;
char fname[16384];
unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
@@ -274,7 +466,7 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
- //read
+ // Read
unzOpenCurrentFile(pkg);
unzReadCurrentFile(pkg, data.ptrw(), data.size());
unzCloseCurrentFile(pkg);
@@ -322,216 +514,116 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
if (p) {
memdelete(p);
}
-
unzClose(pkg);
- _update_template_list();
+ _update_template_status();
return true;
}
-void ExportTemplateManager::popup_manager() {
- _update_template_list();
- popup_centered(Size2(400, 400) * EDSCALE);
-}
-
-void ExportTemplateManager::ok_pressed() {
- template_open->popup_file_dialog();
+void ExportTemplateManager::_uninstall_template(const String &p_version) {
+ uninstall_confirm->set_text(vformat(TTR("Remove templates for the version '%s'?"), p_version));
+ uninstall_confirm->popup_centered();
+ uninstall_version = p_version;
}
-void ExportTemplateManager::_http_download_mirror_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data) {
- if (p_status != HTTPRequest::RESULT_SUCCESS || p_code != 200) {
- EditorNode::get_singleton()->show_warning(TTR("Error getting the list of mirrors."));
- return;
- }
+void ExportTemplateManager::_uninstall_template_confirmed() {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
- String mirror_str;
- {
- const uint8_t *r = p_data.ptr();
- mirror_str.parse_utf8((const char *)r, p_data.size());
- }
+ Error err = da->change_dir(templates_dir);
+ ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir + "'.");
+ err = da->change_dir(uninstall_version);
+ ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir.plus_file(uninstall_version) + "'.");
- template_list_state->hide();
- template_download_progress->hide();
+ err = da->erase_contents_recursive();
+ ERR_FAIL_COND_MSG(err != OK, "Could not remove all templates in '" + templates_dir.plus_file(uninstall_version) + "'.");
- Variant r;
- String errs;
- int errline;
- Error err = JSON::parse(mirror_str, r, errs, errline);
- if (err != OK) {
- EditorNode::get_singleton()->show_warning(TTR("Error parsing JSON of mirror list. Please report this issue!"));
- return;
- }
+ da->change_dir("..");
+ err = da->remove(uninstall_version);
+ ERR_FAIL_COND_MSG(err != OK, "Could not remove templates directory at '" + templates_dir.plus_file(uninstall_version) + "'.");
- bool mirrors_found = false;
+ _update_template_status();
+}
- Dictionary d = r;
- if (d.has("mirrors")) {
- Array mirrors = d["mirrors"];
- for (int i = 0; i < mirrors.size(); i++) {
- Dictionary m = mirrors[i];
- ERR_CONTINUE(!m.has("url") || !m.has("name"));
- LinkButton *lb = memnew(LinkButton);
- lb->set_text(m["name"]);
- lb->connect("pressed", callable_mp(this, &ExportTemplateManager::_begin_template_download), varray(m["url"]));
- template_list->add_child(lb);
- mirrors_found = true;
- }
+String ExportTemplateManager::_get_selected_mirror() const {
+ if (mirrors_list->get_item_count() == 1) {
+ return "";
}
- if (!mirrors_found) {
- EditorNode::get_singleton()->show_warning(TTR("No download links found for this version. Direct download is only available for official releases."));
- return;
+ int selected = mirrors_list->get_selected_id();
+ if (selected == 0) {
+ // This is a special "best available" value; so pick the first available mirror from the rest of the list.
+ selected = 1;
}
+
+ return mirrors_list->get_item_metadata(selected);
}
-void ExportTemplateManager::_http_download_templates_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data) {
- switch (p_status) {
- case HTTPRequest::RESULT_CANT_RESOLVE: {
- template_list_state->set_text(TTR("Can't resolve."));
- } break;
- case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED:
- case HTTPRequest::RESULT_CONNECTION_ERROR:
- case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH:
- case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR:
- case HTTPRequest::RESULT_CANT_CONNECT: {
- template_list_state->set_text(TTR("Can't connect."));
- } break;
- case HTTPRequest::RESULT_NO_RESPONSE: {
- template_list_state->set_text(TTR("No response."));
- } break;
- case HTTPRequest::RESULT_REQUEST_FAILED: {
- template_list_state->set_text(TTR("Request Failed."));
- } break;
- case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: {
- template_list_state->set_text(TTR("Redirect Loop."));
+void ExportTemplateManager::_mirror_options_button_cbk(int p_id) {
+ switch (p_id) {
+ case VISIT_WEB_MIRROR: {
+ String mirror_url = _get_selected_mirror();
+ if (mirror_url.is_empty()) {
+ EditorNode::get_singleton()->show_warning(TTR("There are no mirrors available."));
+ return;
+ }
+
+ OS::get_singleton()->shell_open(mirror_url);
} break;
- default: {
- if (p_code != 200) {
- template_list_state->set_text(TTR("Failed:") + " " + itos(p_code));
- } else {
- String path = download_templates->get_download_file();
- template_list_state->set_text(TTR("Download Complete."));
- template_downloader->hide();
- bool ret = _install_from_file(path, false);
- if (ret) {
- // Clean up downloaded file.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- Error err = da->remove(path);
- if (err != OK) {
- EditorNode::get_singleton()->add_io_error(TTR("Cannot remove temporary file:") + "\n" + path + "\n");
- }
- } else {
- EditorNode::get_singleton()->add_io_error(vformat(TTR("Templates installation failed.\nThe problematic templates archives can be found at '%s'."), path));
- }
+
+ case COPY_MIRROR_URL: {
+ String mirror_url = _get_selected_mirror();
+ if (mirror_url.is_empty()) {
+ EditorNode::get_singleton()->show_warning(TTR("There are no mirrors available."));
+ return;
}
+
+ DisplayServer::get_singleton()->clipboard_set(mirror_url);
} break;
}
-
- set_process(false);
}
-void ExportTemplateManager::_begin_template_download(const String &p_url) {
- if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
- OS::get_singleton()->shell_open(p_url);
+void ExportTemplateManager::_installed_table_button_cbk(Object *p_item, int p_column, int p_id) {
+ TreeItem *ti = Object::cast_to<TreeItem>(p_item);
+ if (!ti) {
return;
}
- for (int i = 0; i < template_list->get_child_count(); i++) {
- BaseButton *b = Object::cast_to<BaseButton>(template_list->get_child(0));
- if (b) {
- b->set_disabled(true);
- }
- }
-
- download_data.clear();
- download_templates->set_download_file(EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_templates.tpz"));
- download_templates->set_use_threads(true);
+ switch (p_id) {
+ case OPEN_TEMPLATE_FOLDER: {
+ String version_string = ti->get_text(0);
+ _open_template_folder(version_string);
+ } break;
- Error err = download_templates->request(p_url);
- if (err != OK) {
- EditorNode::get_singleton()->show_warning(TTR("Error requesting URL:") + " " + p_url);
- return;
+ case UNINSTALL_TEMPLATE: {
+ String version_string = ti->get_text(0);
+ _uninstall_template(version_string);
+ } break;
}
+}
- set_process(true);
-
- template_list_state->show();
- template_download_progress->set_max(100);
- template_download_progress->set_value(0);
- template_download_progress->show();
- template_list_state->set_text(TTR("Connecting to Mirror..."));
+void ExportTemplateManager::_open_template_folder(const String &p_version) {
+ const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
+ OS::get_singleton()->shell_open("file://" + templates_dir.plus_file(p_version));
}
-void ExportTemplateManager::_window_template_downloader_closed() {
- download_templates->cancel_request();
+void ExportTemplateManager::popup_manager() {
+ _update_template_status();
+ _refresh_mirrors();
+ popup_centered(Size2(720, 280) * EDSCALE);
}
-void ExportTemplateManager::_notification(int p_what) {
- if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
- if (!is_visible()) {
- set_process(false);
- }
+void ExportTemplateManager::ok_pressed() {
+ if (!is_downloading_templates) {
+ hide();
+ return;
}
- if (p_what == NOTIFICATION_PROCESS) {
- update_countdown -= get_process_delta_time();
- if (update_countdown > 0) {
- return;
- }
- update_countdown = 0.5;
- String status;
- bool errored = false;
-
- switch (download_templates->get_http_client_status()) {
- case HTTPClient::STATUS_DISCONNECTED:
- status = TTR("Disconnected");
- errored = true;
- break;
- case HTTPClient::STATUS_RESOLVING:
- status = TTR("Resolving");
- break;
- case HTTPClient::STATUS_CANT_RESOLVE:
- status = TTR("Can't Resolve");
- errored = true;
- break;
- case HTTPClient::STATUS_CONNECTING:
- status = TTR("Connecting...");
- break;
- case HTTPClient::STATUS_CANT_CONNECT:
- status = TTR("Can't Connect");
- errored = true;
- break;
- case HTTPClient::STATUS_CONNECTED:
- status = TTR("Connected");
- break;
- case HTTPClient::STATUS_REQUESTING:
- status = TTR("Requesting...");
- break;
- case HTTPClient::STATUS_BODY:
- status = TTR("Downloading");
- if (download_templates->get_body_size() > 0) {
- status += " " + String::humanize_size(download_templates->get_downloaded_bytes()) + "/" + String::humanize_size(download_templates->get_body_size());
- template_download_progress->set_max(download_templates->get_body_size());
- template_download_progress->set_value(download_templates->get_downloaded_bytes());
- } else {
- status += " " + String::humanize_size(download_templates->get_downloaded_bytes());
- }
- break;
- case HTTPClient::STATUS_CONNECTION_ERROR:
- status = TTR("Connection Error");
- errored = true;
- break;
- case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR:
- status = TTR("SSL Handshake Error");
- errored = true;
- break;
- }
+ hide_dialog_accept->popup_centered();
+}
- template_list_state->set_text(status);
- if (errored) {
- set_process(false);
- }
- }
+void ExportTemplateManager::_hide_dialog() {
+ hide();
}
bool ExportTemplateManager::can_install_android_template() {
@@ -643,72 +735,246 @@ Error ExportTemplateManager::install_android_template() {
return OK;
}
-void ExportTemplateManager::_bind_methods() {
-}
+void ExportTemplateManager::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ current_value->add_theme_font_override("font", get_theme_font("main", "EditorFonts"));
+ current_missing_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ current_installed_label->add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor"));
+
+ mirror_options_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+ } break;
-ExportTemplateManager::ExportTemplateManager() {
- VBoxContainer *main_vb = memnew(VBoxContainer);
- add_child(main_vb);
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible()) {
+ set_process(false);
+ } else if (is_visible() && is_downloading_templates) {
+ set_process(true);
+ }
+ } break;
- current_hb = memnew(HBoxContainer);
- main_vb->add_margin_child(TTR("Current Version:"), current_hb, false);
+ case NOTIFICATION_PROCESS: {
+ update_countdown -= get_process_delta_time();
+ if (update_countdown > 0) {
+ return;
+ }
+ update_countdown = 0.5;
- installed_scroll = memnew(ScrollContainer);
- main_vb->add_margin_child(TTR("Other Installed Versions:"), installed_scroll, true);
+ String status;
+ int downloaded_bytes;
+ int total_bytes;
+ bool success = _humanize_http_status(download_templates, &status, &downloaded_bytes, &total_bytes);
- installed_vb = memnew(VBoxContainer);
- installed_scroll->add_child(installed_vb);
- installed_scroll->set_enable_v_scroll(true);
- installed_scroll->set_enable_h_scroll(false);
- installed_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (downloaded_bytes >= 0) {
+ if (total_bytes > 0) {
+ _set_current_progress_value(float(downloaded_bytes) / total_bytes, status);
+ } else {
+ _set_current_progress_value(0, status);
+ }
+ } else {
+ _set_current_progress_status(status);
+ }
- get_cancel_button()->set_text(TTR("Close"));
- get_ok_button()->set_text(TTR("Install From File"));
+ if (!success) {
+ set_process(false);
+ }
+ } break;
- remove_confirm = memnew(ConfirmationDialog);
- remove_confirm->set_title(TTR("Remove Template"));
- add_child(remove_confirm);
- remove_confirm->connect("confirmed", callable_mp(this, &ExportTemplateManager::_uninstall_template_confirm));
+ case NOTIFICATION_WM_CLOSE_REQUEST: {
+ // This won't stop the window from closing, but will show the alert if the download is active.
+ ok_pressed();
+ } break;
+ }
+}
- template_open = memnew(FileDialog);
- template_open->set_title(TTR("Select Template File"));
- template_open->add_filter("*.tpz ; " + TTR("Godot Export Templates"));
- template_open->set_access(FileDialog::ACCESS_FILESYSTEM);
- template_open->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE);
- template_open->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_from_file), varray(true));
- add_child(template_open);
+void ExportTemplateManager::_bind_methods() {
+}
+ExportTemplateManager::ExportTemplateManager() {
set_title(TTR("Export Template Manager"));
set_hide_on_ok(false);
+ get_ok_button()->set_text(TTR("Close"));
+
+ // Downloadable export templates are only available for stable and official alpha/beta/RC builds
+ // (which always have a number following their status, e.g. "alpha1").
+ // Therefore, don't display download-related features when using a development version
+ // (whose builds aren't numbered).
+ downloads_available =
+ String(VERSION_STATUS) != String("dev") &&
+ String(VERSION_STATUS) != String("alpha") &&
+ String(VERSION_STATUS) != String("beta") &&
+ String(VERSION_STATUS) != String("rc");
+
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
+
+ // Current version controls.
+ HBoxContainer *current_hb = memnew(HBoxContainer);
+ main_vb->add_child(current_hb);
+
+ Label *current_label = memnew(Label);
+ current_label->set_text(TTR("Current Version:"));
+ current_hb->add_child(current_label);
+
+ current_value = memnew(Label);
+ current_hb->add_child(current_value);
+
+ // Current version statuses.
+ // Status: Current version is missing.
+ current_missing_label = memnew(Label);
+ current_missing_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ current_missing_label->set_align(Label::ALIGN_RIGHT);
+ current_missing_label->set_text(TTR("Export templates are missing. Download them or install from a file."));
+ current_hb->add_child(current_missing_label);
+
+ // Status: Current version is installed.
+ current_installed_label = memnew(Label);
+ current_installed_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ current_installed_label->set_align(Label::ALIGN_RIGHT);
+ current_installed_label->set_text(TTR("Export templates are installed and ready to be used."));
+ current_hb->add_child(current_installed_label);
+ current_installed_label->hide();
+
+ // Currently installed template.
+ current_installed_hb = memnew(HBoxContainer);
+ main_vb->add_child(current_installed_hb);
+
+ current_installed_path = memnew(LineEdit);
+ current_installed_path->set_editable(false);
+ current_installed_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ current_installed_hb->add_child(current_installed_path);
+
+ current_open_button = memnew(Button);
+ current_open_button->set_text(TTR("Open Folder"));
+ current_open_button->set_tooltip(TTR("Open the folder containing installed templates for the current version."));
+ current_installed_hb->add_child(current_open_button);
+ current_open_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_open_template_folder), varray(VERSION_FULL_CONFIG));
+
+ current_uninstall_button = memnew(Button);
+ current_uninstall_button->set_text(TTR("Uninstall"));
+ current_uninstall_button->set_tooltip(TTR("Uninstall templates for the current version."));
+ current_installed_hb->add_child(current_uninstall_button);
+ current_uninstall_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template), varray(VERSION_FULL_CONFIG));
+
+ main_vb->add_child(memnew(HSeparator));
+
+ // Download and install section.
+ HBoxContainer *install_templates_hb = memnew(HBoxContainer);
+ main_vb->add_child(install_templates_hb);
+
+ // Download and install buttons are available.
+ install_options_vb = memnew(VBoxContainer);
+ install_options_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ install_templates_hb->add_child(install_options_vb);
+
+ HBoxContainer *download_install_hb = memnew(HBoxContainer);
+ install_options_vb->add_child(download_install_hb);
+
+ Label *mirrors_label = memnew(Label);
+ mirrors_label->set_text(TTR("Download from:"));
+ download_install_hb->add_child(mirrors_label);
+
+ mirrors_list = memnew(OptionButton);
+ mirrors_list->set_custom_minimum_size(Size2(280, 0) * EDSCALE);
+ download_install_hb->add_child(mirrors_list);
+ mirrors_list->add_item(TTR("Best available mirror"), 0);
+
+ request_mirrors = memnew(HTTPRequest);
+ mirrors_list->add_child(request_mirrors);
+ request_mirrors->connect("request_completed", callable_mp(this, &ExportTemplateManager::_refresh_mirrors_completed));
+
+ mirror_options_button = memnew(MenuButton);
+ mirror_options_button->get_popup()->add_item("Open in Web Browser", VISIT_WEB_MIRROR);
+ mirror_options_button->get_popup()->add_item("Copy Mirror URL", COPY_MIRROR_URL);
+ download_install_hb->add_child(mirror_options_button);
+ mirror_options_button->get_popup()->connect("id_pressed", callable_mp(this, &ExportTemplateManager::_mirror_options_button_cbk));
+
+ download_install_hb->add_spacer();
+
+ Button *download_current_button = memnew(Button);
+ download_current_button->set_text(TTR("Download and Install"));
+ download_current_button->set_tooltip(TTR("Download and install templates for the current version from the best possible mirror."));
+ download_install_hb->add_child(download_current_button);
+ download_current_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_download_current));
+
+ // Update downloads buttons to prevent unsupported downloads.
+ if (!downloads_available) {
+ download_current_button->set_disabled(true);
+ download_current_button->set_tooltip(TTR("Official export templates aren't available for development builds."));
+ }
- request_mirror = memnew(HTTPRequest);
- add_child(request_mirror);
- request_mirror->connect("request_completed", callable_mp(this, &ExportTemplateManager::_http_download_mirror_completed));
+ HBoxContainer *install_file_hb = memnew(HBoxContainer);
+ install_file_hb->set_alignment(BoxContainer::ALIGN_END);
+ install_options_vb->add_child(install_file_hb);
+
+ install_file_button = memnew(Button);
+ install_file_button->set_text(TTR("Install from File"));
+ install_file_button->set_tooltip(TTR("Install templates from a local file."));
+ install_file_hb->add_child(install_file_button);
+ install_file_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_install_file));
+
+ // Templates are being downloaded; buttons unavailable.
+ download_progress_hb = memnew(HBoxContainer);
+ download_progress_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ install_templates_hb->add_child(download_progress_hb);
+ download_progress_hb->hide();
+
+ download_progress_bar = memnew(ProgressBar);
+ download_progress_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ download_progress_bar->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ download_progress_bar->set_min(0);
+ download_progress_bar->set_max(1);
+ download_progress_bar->set_value(0);
+ download_progress_bar->set_step(0.01);
+ download_progress_hb->add_child(download_progress_bar);
+
+ download_progress_label = memnew(Label);
+ download_progress_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ download_progress_hb->add_child(download_progress_label);
+
+ Button *download_cancel_button = memnew(Button);
+ download_cancel_button->set_text(TTR("Cancel"));
+ download_cancel_button->set_tooltip(TTR("Cancel the download of the templates."));
+ download_progress_hb->add_child(download_cancel_button);
+ download_cancel_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_cancel_template_download));
download_templates = memnew(HTTPRequest);
- add_child(download_templates);
- download_templates->connect("request_completed", callable_mp(this, &ExportTemplateManager::_http_download_templates_completed));
-
- template_downloader = memnew(AcceptDialog);
- template_downloader->set_title(TTR("Download Templates"));
- template_downloader->get_ok_button()->set_text(TTR("Close"));
- template_downloader->set_exclusive(true);
- add_child(template_downloader);
- template_downloader->connect("cancelled", callable_mp(this, &ExportTemplateManager::_window_template_downloader_closed));
-
- VBoxContainer *vbc = memnew(VBoxContainer);
- template_downloader->add_child(vbc);
- ScrollContainer *sc = memnew(ScrollContainer);
- sc->set_custom_minimum_size(Size2(400, 200) * EDSCALE);
- vbc->add_margin_child(TTR("Select mirror from list: (Shift+Click: Open in Browser)"), sc);
- template_list = memnew(VBoxContainer);
- sc->add_child(template_list);
- sc->set_enable_v_scroll(true);
- sc->set_enable_h_scroll(false);
- template_list_state = memnew(Label);
- vbc->add_child(template_list_state);
- template_download_progress = memnew(ProgressBar);
- vbc->add_child(template_download_progress);
-
- update_countdown = 0;
+ install_templates_hb->add_child(download_templates);
+ download_templates->connect("request_completed", callable_mp(this, &ExportTemplateManager::_download_template_completed));
+
+ main_vb->add_child(memnew(HSeparator));
+
+ // Other installed templates table.
+ HBoxContainer *installed_versions_hb = memnew(HBoxContainer);
+ main_vb->add_child(installed_versions_hb);
+ Label *installed_label = memnew(Label);
+ installed_label->set_text(TTR("Other Installed Versions:"));
+ installed_versions_hb->add_child(installed_label);
+
+ installed_table = memnew(Tree);
+ installed_table->set_hide_root(true);
+ installed_table->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
+ installed_table->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ main_vb->add_child(installed_table);
+ installed_table->connect("button_pressed", callable_mp(this, &ExportTemplateManager::_installed_table_button_cbk));
+
+ // Dialogs.
+ uninstall_confirm = memnew(ConfirmationDialog);
+ uninstall_confirm->set_title(TTR("Uninstall Template"));
+ add_child(uninstall_confirm);
+ uninstall_confirm->connect("confirmed", callable_mp(this, &ExportTemplateManager::_uninstall_template_confirmed));
+
+ install_file_dialog = memnew(FileDialog);
+ install_file_dialog->set_title(TTR("Select Template File"));
+ install_file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM);
+ install_file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE);
+ install_file_dialog->add_filter("*.tpz ; " + TTR("Godot Export Templates"));
+ install_file_dialog->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_file_selected), varray(false));
+ add_child(install_file_dialog);
+
+ hide_dialog_accept = memnew(AcceptDialog);
+ hide_dialog_accept->set_text(TTR("The templates will continue to download.\nYou may experience a short editor freeze when they finish."));
+ add_child(hide_dialog_accept);
+ hide_dialog_accept->connect("confirmed", callable_mp(this, &ExportTemplateManager::_hide_dialog));
}
diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h
index 3de74e17d8..f145c6c0f5 100644
--- a/editor/export_template_manager.h
+++ b/editor/export_template_manager.h
@@ -34,50 +34,87 @@
#include "editor/editor_settings.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/file_dialog.h"
+#include "scene/gui/menu_button.h"
#include "scene/gui/progress_bar.h"
#include "scene/gui/scroll_container.h"
#include "scene/main/http_request.h"
class ExportTemplateVersion;
-class ExportTemplateManager : public ConfirmationDialog {
- GDCLASS(ExportTemplateManager, ConfirmationDialog);
+class ExportTemplateManager : public AcceptDialog {
+ GDCLASS(ExportTemplateManager, AcceptDialog);
+
+ bool current_version_exists = false;
+ bool downloads_available = true;
+ bool mirrors_available = false;
+ bool is_refreshing_mirrors = false;
+ bool is_downloading_templates = false;
+ float update_countdown = 0;
+
+ Label *current_value;
+ Label *current_missing_label;
+ Label *current_installed_label;
+
+ HBoxContainer *current_installed_hb;
+ LineEdit *current_installed_path;
+ Button *current_open_button;
+ Button *current_uninstall_button;
+
+ VBoxContainer *install_options_vb;
+ OptionButton *mirrors_list;
+
+ enum MirrorAction {
+ VISIT_WEB_MIRROR,
+ COPY_MIRROR_URL,
+ };
+
+ MenuButton *mirror_options_button;
+ HBoxContainer *download_progress_hb;
+ ProgressBar *download_progress_bar;
+ Label *download_progress_label;
+ HTTPRequest *download_templates;
+ Button *install_file_button;
+ HTTPRequest *request_mirrors;
- AcceptDialog *template_downloader;
- VBoxContainer *template_list;
- Label *template_list_state;
- ProgressBar *template_download_progress;
+ enum TemplatesAction {
+ OPEN_TEMPLATE_FOLDER,
+ UNINSTALL_TEMPLATE,
+ };
- ScrollContainer *installed_scroll;
- VBoxContainer *installed_vb;
- HBoxContainer *current_hb;
- FileDialog *template_open;
+ Tree *installed_table;
- ConfirmationDialog *remove_confirm;
- String to_remove;
+ ConfirmationDialog *uninstall_confirm;
+ String uninstall_version;
+ FileDialog *install_file_dialog;
+ AcceptDialog *hide_dialog_accept;
- HTTPRequest *request_mirror;
- HTTPRequest *download_templates;
+ void _update_template_status();
- Vector<uint8_t> download_data;
+ void _download_current();
+ void _download_template(const String &p_url, bool p_skip_check = false);
+ void _download_template_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data);
+ void _cancel_template_download();
+ void _refresh_mirrors();
+ void _refresh_mirrors_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data);
- float update_countdown;
+ bool _humanize_http_status(HTTPRequest *p_request, String *r_status, int *r_downloaded_bytes, int *r_total_bytes);
+ void _set_current_progress_status(const String &p_status, bool p_error = false);
+ void _set_current_progress_value(float p_value, const String &p_status);
- void _update_template_list();
+ void _install_file();
+ bool _install_file_selected(const String &p_file, bool p_skip_progress = false);
- void _download_template(const String &p_version);
void _uninstall_template(const String &p_version);
- void _uninstall_template_confirm();
+ void _uninstall_template_confirmed();
- virtual void ok_pressed() override;
- bool _install_from_file(const String &p_file, bool p_use_progress = true);
+ String _get_selected_mirror() const;
+ void _mirror_options_button_cbk(int p_id);
+ void _installed_table_button_cbk(Object *p_item, int p_column, int p_id);
- void _http_download_mirror_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data);
- void _http_download_templates_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data);
+ void _open_template_folder(const String &p_version);
- void _begin_template_download(const String &p_url);
-
- void _window_template_downloader_closed();
+ virtual void ok_pressed() override;
+ void _hide_dialog();
protected:
void _notification(int p_what);
diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp
index d80003a12a..654915e3e5 100644
--- a/editor/fileserver/editor_file_server.cpp
+++ b/editor/fileserver/editor_file_server.cpp
@@ -200,7 +200,7 @@ void EditorFileServer::_subthread_start(void *s) {
cd->connection->put_data(buf4, 4);
encode_uint32(OK, buf4);
cd->connection->put_data(buf4, 4);
- encode_uint64(fa->get_len(), buf4);
+ encode_uint64(fa->get_length(), buf4);
cd->connection->put_data(buf4, 8);
cd->files[id] = fa;
@@ -230,8 +230,7 @@ void EditorFileServer::_subthread_start(void *s) {
cd->files[id]->seek(offset);
Vector<uint8_t> buf;
buf.resize(blocklen);
- int read = cd->files[id]->get_buffer(buf.ptrw(), blocklen);
- ERR_CONTINUE(read < 0);
+ uint32_t read = cd->files[id]->get_buffer(buf.ptrw(), blocklen);
print_verbose("GET BLOCK - offset: " + itos(offset) + ", blocklen: " + itos(blocklen));
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 7ecfc5d520..46bb6a1632 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -31,9 +31,9 @@
#include "filesystem_dock.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/templates/list.h"
@@ -180,12 +180,12 @@ Vector<String> FileSystemDock::_compute_uncollapsed_paths() {
Vector<String> uncollapsed_paths;
TreeItem *root = tree->get_root();
if (root) {
- TreeItem *favorites_item = root->get_children();
+ TreeItem *favorites_item = root->get_first_child();
if (!favorites_item->is_collapsed()) {
uncollapsed_paths.push_back(favorites_item->get_metadata(0));
}
- TreeItem *resTree = root->get_children()->get_next();
+ TreeItem *resTree = root->get_first_child()->get_next();
if (resTree) {
Vector<TreeItem *> needs_check;
needs_check.push_back(resTree);
@@ -193,7 +193,7 @@ Vector<String> FileSystemDock::_compute_uncollapsed_paths() {
while (needs_check.size()) {
if (!needs_check[0]->is_collapsed()) {
uncollapsed_paths.push_back(needs_check[0]->get_metadata(0));
- TreeItem *child = needs_check[0]->get_children();
+ TreeItem *child = needs_check[0]->get_first_child();
while (child) {
needs_check.push_back(child);
child = child->get_next();
@@ -464,7 +464,7 @@ void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_s
return;
}
- TreeItem *favorites_item = tree->get_root()->get_children();
+ TreeItem *favorites_item = tree->get_root()->get_first_child();
if (selected->get_parent() == favorites_item && !String(selected->get_metadata(0)).ends_with("/")) {
// Go to the favorites if we click in the favorites and the path has changed.
path = "Favorites";
@@ -860,7 +860,6 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
file_list.push_back(fi);
}
}
- file_list.sort();
}
// Sort the file list if needed.
@@ -1644,7 +1643,7 @@ Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) {
// Build a list of selected items with the active one at the first position.
Vector<String> selected_strings;
- TreeItem *favorites_item = tree->get_root()->get_children();
+ TreeItem *favorites_item = tree->get_root()->get_first_child();
TreeItem *active_selected = tree->get_selected();
if (active_selected && active_selected != favorites_item) {
selected_strings.push_back(active_selected->get_metadata(0));
@@ -1700,7 +1699,7 @@ void FileSystemDock::_tree_rmb_option(int p_option) {
while (needs_check.size()) {
needs_check[0]->set_collapsed(is_collapsed);
- TreeItem *child = needs_check[0]->get_children();
+ TreeItem *child = needs_check[0]->get_first_child();
while (child) {
needs_check.push_back(child);
child = child->get_next();
@@ -2062,13 +2061,13 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from)
// Check if the first selected is in favorite.
TreeItem *selected = tree->get_next_selected(tree->get_root());
while (selected) {
- TreeItem *favorites_item = tree->get_root()->get_children();
+ TreeItem *favorites_item = tree->get_root()->get_first_child();
if (selected == favorites_item) {
// The "Favorites" item is not draggable.
return Variant();
}
- bool is_favorite = selected->get_parent() != nullptr && tree->get_root()->get_children() == selected->get_parent();
+ bool is_favorite = selected->get_parent() != nullptr && tree->get_root()->get_first_child() == selected->get_parent();
all_favorites &= is_favorite;
all_not_favorites &= !is_favorite;
selected = tree->get_next_selected(selected);
@@ -2114,7 +2113,7 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
}
int drop_section = tree->get_drop_section_at_position(p_point);
- TreeItem *favorites_item = tree->get_root()->get_children();
+ TreeItem *favorites_item = tree->get_root()->get_first_child();
TreeItem *resources_item = favorites_item->get_next();
@@ -2190,7 +2189,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
int drop_position;
Vector<String> files = drag_data["files"];
- TreeItem *favorites_item = tree->get_root()->get_children();
+ TreeItem *favorites_item = tree->get_root()->get_first_child();
TreeItem *resources_item = favorites_item->get_next();
if (ti == favorites_item) {
@@ -2264,7 +2263,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
}
if (!to_move.is_empty()) {
- if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
for (int i = 0; i < to_move.size(); i++) {
String new_path;
String new_path_base;
@@ -2328,10 +2327,10 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
int section = tree->get_drop_section_at_position(p_point);
if (ti) {
// Check the favorites first.
- if (ti == tree->get_root()->get_children() && section >= 0) {
+ if (ti == tree->get_root()->get_first_child() && section >= 0) {
target_favorites = true;
return;
- } else if (ti->get_parent() == tree->get_root()->get_children()) {
+ } else if (ti->get_parent() == tree->get_root()->get_first_child()) {
target_favorites = true;
return;
} else {
@@ -2347,7 +2346,7 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
return;
}
} else {
- if (ti->get_parent() != tree->get_root()->get_children()) {
+ if (ti->get_parent() != tree->get_root()->get_first_child()) {
// Not in the favorite section.
if (fpath != "res://") {
// We drop between two files
@@ -2735,12 +2734,12 @@ MenuButton *FileSystemDock::_create_file_menu_button() {
PopupMenu *p = button->get_popup();
p->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_sort_popup));
- p->add_radio_check_item("Sort by Name (Ascending)", FILE_SORT_NAME);
- p->add_radio_check_item("Sort by Name (Descending)", FILE_SORT_NAME_REVERSE);
- p->add_radio_check_item("Sort by Type (Ascending)", FILE_SORT_TYPE);
- p->add_radio_check_item("Sort by Type (Descending)", FILE_SORT_TYPE_REVERSE);
- p->add_radio_check_item("Sort by Last Modified", FILE_SORT_MODIFIED_TIME);
- p->add_radio_check_item("Sort by First Modified", FILE_SORT_MODIFIED_TIME_REVERSE);
+ p->add_radio_check_item(TTR("Sort by Name (Ascending)"), FILE_SORT_NAME);
+ p->add_radio_check_item(TTR("Sort by Name (Descending)"), FILE_SORT_NAME_REVERSE);
+ p->add_radio_check_item(TTR("Sort by Type (Ascending)"), FILE_SORT_TYPE);
+ p->add_radio_check_item(TTR("Sort by Type (Descending)"), FILE_SORT_TYPE_REVERSE);
+ p->add_radio_check_item(TTR("Sort by Last Modified"), FILE_SORT_MODIFIED_TIME);
+ p->add_radio_check_item(TTR("Sort by First Modified"), FILE_SORT_MODIFIED_TIME_REVERSE);
p->set_item_checked(file_sort, true);
return button;
}
@@ -2752,9 +2751,9 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_tree_thumbnail_done"), &FileSystemDock::_tree_thumbnail_done);
ClassDB::bind_method(D_METHOD("_select_file"), &FileSystemDock::_select_file);
- ClassDB::bind_method(D_METHOD("get_drag_data_fw", "position", "from"), &FileSystemDock::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw", "position", "data", "from"), &FileSystemDock::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw", "position", "data", "from"), &FileSystemDock::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw", "position", "from"), &FileSystemDock::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw", "position", "data", "from"), &FileSystemDock::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw", "position", "data", "from"), &FileSystemDock::drop_data_fw);
ClassDB::bind_method(D_METHOD("navigate_to_path", "path"), &FileSystemDock::navigate_to_path);
ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock);
@@ -2778,22 +2777,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
// `KEY_MASK_CMD | KEY_C` conflicts with other editor shortcuts.
ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_C);
ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KEY_MASK_CMD | KEY_D);
-
-#if defined(WINDOWS_ENABLED)
- // TRANSLATORS: This string is only used on Windows, as it refers to the system trash
- // as "Recycle Bin" instead of "Trash". Make sure to use the translation of "Recycle Bin"
- // recommended by Microsoft for the target language.
- ED_SHORTCUT("filesystem_dock/delete", TTR("Move to Recycle Bin"), KEY_DELETE);
-#elif defined(OSX_ENABLED)
- // TRANSLATORS: This string is only used on macOS, as it refers to the system trash
- // as "Bin" instead of "Trash". Make sure to use the translation of "Bin"
- // recommended by Apple for the target language.
- ED_SHORTCUT("filesystem_dock/delete", TTR("Move to Bin"), KEY_DELETE);
-#else
- // TRANSLATORS: This string is only used on platforms other than Windows and macOS.
- ED_SHORTCUT("filesystem_dock/delete", TTR("Move to Trash"), KEY_DELETE);
-#endif
-
+ ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), KEY_DELETE);
ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), KEY_F2);
VBoxContainer *top_vbc = memnew(VBoxContainer);
@@ -2835,6 +2819,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
button_toggle_display_mode->connect("toggled", callable_mp(this, &FileSystemDock::_toggle_split_mode));
button_toggle_display_mode->set_focus_mode(FOCUS_NONE);
button_toggle_display_mode->set_tooltip(TTR("Toggle Split Mode"));
+ button_toggle_display_mode->set_flat(true);
toolbar_hbc->add_child(button_toggle_display_mode);
toolbar2_hbc = memnew(HBoxContainer);
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 8783c402cd..12c567fb69 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -43,7 +43,7 @@
#include "scene/gui/tree.h"
#include "scene/main/timer.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/thread.h"
#include "create_dialog.h"
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index 47079a92b7..17d24a295c 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -30,7 +30,7 @@
#include "find_in_files.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/os.h"
#include "editor_node.h"
#include "editor_scale.h"
@@ -530,7 +530,7 @@ void FindInFilesDialog::_on_replace_text_entered(String text) {
void FindInFilesDialog::_on_folder_selected(String path) {
int i = path.find("://");
if (i != -1) {
- path = path.right(i + 3);
+ path = path.substr(i + 3);
}
_folder_line_edit->set_text(path);
}
@@ -763,8 +763,10 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) {
match_rect.position.y += 1 * EDSCALE;
match_rect.size.y -= 2 * EDSCALE;
- _results_display->draw_rect(match_rect, Color(0, 0, 0, 0.5));
- // Text is drawn by Tree already
+ // Use the inverted accent color to help match rectangles stand out even on the currently selected line.
+ _results_display->draw_rect(match_rect, get_theme_color("accent_color", "Editor").inverted() * Color(1, 1, 1, 0.5));
+
+ // Text is drawn by Tree already.
}
void FindInFilesPanel::_on_item_edited() {
@@ -838,7 +840,7 @@ void FindInFilesPanel::_on_replace_all_clicked() {
String fpath = file_item->get_metadata(0);
Vector<Result> locations;
- for (TreeItem *item = file_item->get_children(); item; item = item->get_next()) {
+ for (TreeItem *item = file_item->get_first_child(); item; item = item->get_next()) {
if (!item->is_checked(0)) {
continue;
}
@@ -932,7 +934,7 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result>
continue;
}
- line = line.left(repl_begin) + new_text + line.right(repl_end);
+ line = line.left(repl_begin) + new_text + line.substr(repl_end);
// keep an offset in case there are successive replaces in the same line
offset += new_text.length() - (repl_end - repl_begin);
}
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index f2a110ca03..d8e5a05c5d 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -52,7 +52,7 @@ void GroupDialog::_group_selected() {
selected_group = groups->get_selected()->get_text(0);
_load_nodes(scene_tree->get_edited_scene_root());
- group_empty->set_visible(!remove_node_root->get_children());
+ group_empty->set_visible(!remove_node_root->get_first_child());
}
void GroupDialog::_load_nodes(Node *p_current) {
@@ -217,7 +217,7 @@ void GroupDialog::_group_renamed() {
}
const String name = renamed_group->get_text(0).strip_edges();
- for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) {
+ for (TreeItem *E = groups_root->get_first_child(); E; E = E->get_next()) {
if (E != renamed_group && E->get_text(0) == name) {
renamed_group->set_text(0, selected_group);
error->set_text(TTR("Group name already exists."));
@@ -274,7 +274,7 @@ void GroupDialog::_rename_group_item(const String &p_old_name, const String &p_n
selected_group = p_new_name;
- for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) {
+ for (TreeItem *E = groups_root->get_first_child(); E; E = E->get_next()) {
if (E->get_text(0) == p_old_name) {
E->set_text(0, p_new_name);
return;
@@ -351,7 +351,7 @@ void GroupDialog::_delete_group_item(const String &p_name) {
selected_group = "";
}
- for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) {
+ for (TreeItem *E = groups_root->get_first_child(); E; E = E->get_next()) {
if (E->get_text(0) == p_name) {
groups_root->remove_child(E);
return;
diff --git a/editor/icons/2D.svg b/editor/icons/2D.svg
index afb9f4b45f..fdd2e473e3 100644
--- a/editor/icons/2D.svg
+++ b/editor/icons/2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.9844 1.002a1.0001 1.0001 0 0 0 -.69141.29102l-2 2a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l.29297-.29297v8.5859h8.5859l-.29297.29297a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 0-1.4141l-2-2a1 1 0 0 0 -.7207-.29102 1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l.29297.29297h-6.5859v-6.5859l.29297.29297a1 1 0 0 0 1.4141 0 1 1 0 0 0 0-1.4141l-2-2a1.0001 1.0001 0 0 0 -.72266-.29102z" fill="#e0e0e0"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.984375 15a1 1 0 0 1 -.6914062-.291316l-2-2a1 1 0 0 1 0-1.414062 1 1 0 0 1 1.4140624 0l.2929688.292968v-8.5859371h8.585938l-.292969-.292969a1 1 0 0 1 0-1.414062 1 1 0 0 1 1.414062 0l2 2a1 1 0 0 1 0 1.414062l-2 2.0000002a1 1 0 0 1 -.720703.2910157 1 1 0 0 1 -.693359-.2910157 1 1 0 0 1 0-1.4140622l.292969-.292969h-6.585938v6.5859371l.2929688-.292968a1 1 0 0 1 1.4140624 0 1 1 0 0 1 0 1.414062l-2 2a1 1 0 0 1 -.7226562.291316z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/AABB.svg b/editor/icons/AABB.svg
index 03ec25caf2..7db093cc0d 100644
--- a/editor/icons/AABB.svg
+++ b/editor/icons/AABB.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1a3 3 0 0 0 -3 3 3 3 0 0 0 .77734 2.0117 3 3 0 0 0 -2.7773 2.9883 3 3 0 0 0 3 3h2v-5h2v-6h-2zm6 0v5.1738a3 3 0 0 0 -1-.17383v-2h-2v8h2a3 3 0 0 0 3-3 3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2h-2zm-6 2v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm8 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1zm-10 3v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm7 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#ee7991"/><path d="m8 4v8h2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2zm-5 2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6zm0 2v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm7 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#fff" fill-opacity=".23529"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1a3 3 0 0 0 -3 3 3 3 0 0 0 .77734 2.0117 3 3 0 0 0 -2.7773 2.9883 3 3 0 0 0 3 3h2v-5h2v-6h-2zm6 0v5.1738a3 3 0 0 0 -1-.17383v-2h-2v8h2a3 3 0 0 0 3-3 3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2h-2zm-6 2v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm8 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1zm-10 3v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm7 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#ee5677"/><path d="m8 4v8h2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2zm-5 2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6zm0 2v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm7 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#fff" fill-opacity=".23529"/></svg>
diff --git a/editor/icons/AddSplit.svg b/editor/icons/AddSplit.svg
index 5c034d8d12..e46949182c 100644
--- a/editor/icons/AddSplit.svg
+++ b/editor/icons/AddSplit.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 13 10-10" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#84ffb1"/><circle cx="4" cy="12" fill="none" r="2"/><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-10 10a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#e0e0e0"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 13 10-10" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/><circle cx="4" cy="12" fill="none" r="2"/><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-10 10a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Anchor.svg b/editor/icons/Anchor.svg
index cb40970ba3..37bad8bec6 100644
--- a/editor/icons/Anchor.svg
+++ b/editor/icons/Anchor.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8262v.17383h-2v2h2v3.8984a5 5 0 0 1 -3.8281-3.6035l-1.9336.51758a7 7 0 0 0 6.7617 5.1875 7 7 0 0 0 6.7617-5.1875l-1.9375-.51953a5 5 0 0 1 -3.8242 3.6035v-3.8965h2v-2h-2v-.17578a3 3 0 0 0 2-2.8242 3 3 0 0 0 -3-3zm0 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8262v.17383h-2v2h2v3.8984a5 5 0 0 1 -3.8281-3.6035l-1.9336.51758a7 7 0 0 0 6.7617 5.1875 7 7 0 0 0 6.7617-5.1875l-1.9375-.51953a5 5 0 0 1 -3.8242 3.6035v-3.8965h2v-2h-2v-.17578a3 3 0 0 0 2-2.8242 3 3 0 0 0 -3-3zm0 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#8eef97"/></svg>
diff --git a/editor/icons/AnimatedSprite2D.svg b/editor/icons/AnimatedSprite2D.svg
index 0c9d2933ee..b22aeadeb6 100644
--- a/editor/icons/AnimatedSprite2D.svg
+++ b/editor/icons/AnimatedSprite2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#a5b7f3"><path d="m7 0c-1.108 0-2 .89199-2 2h7c1.108 0 2 .89199 2 2v6c1.108 0 2-.89199 2-2v-6c0-1.108-.89199-2-2-2z" fill-opacity=".39216"/><path d="m5 2c-1.108 0-2 .89199-2 2h7c1.108 0 2 .89199 2 2v7c1.108 0 2-.89199 2-2v-7c0-1.108-.89199-2-2-2z" fill-opacity=".58824"/><path d="m3 4c-1.108 0-2 .89199-2 2v7c0 1.108.89199 2 2 2h7c1.108 0 2-.89199 2-2v-7c0-1.108-.89199-2-2-2zm0 4c.554 0 1 .446 1 1v1c0 .554-.446 1-1 1s-1-.446-1-1v-1c0-.554.446-1 1-1zm7 0c.554 0 1 .446 1 1v1c0 .554-.446 1-1 1s-1-.446-1-1v-1c0-.554.446-1 1-1zm-6 4h5a2.5 2 0 0 1 -1.25 1.7324 2.5 2 0 0 1 -2.5 0 2.5 2 0 0 1 -1.25-1.7324z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#8da5f3"><path d="m7 0c-1.108 0-2 .89199-2 2h7c1.108 0 2 .89199 2 2v6c1.108 0 2-.89199 2-2v-6c0-1.108-.89199-2-2-2z" fill-opacity=".39216"/><path d="m5 2c-1.108 0-2 .89199-2 2h7c1.108 0 2 .89199 2 2v7c1.108 0 2-.89199 2-2v-7c0-1.108-.89199-2-2-2z" fill-opacity=".58824"/><path d="m3 4c-1.108 0-2 .89199-2 2v7c0 1.108.89199 2 2 2h7c1.108 0 2-.89199 2-2v-7c0-1.108-.89199-2-2-2zm0 4c.554 0 1 .446 1 1v1c0 .554-.446 1-1 1s-1-.446-1-1v-1c0-.554.446-1 1-1zm7 0c.554 0 1 .446 1 1v1c0 .554-.446 1-1 1s-1-.446-1-1v-1c0-.554.446-1 1-1zm-6 4h5a2.5 2 0 0 1 -1.25 1.7324 2.5 2 0 0 1 -2.5 0 2.5 2 0 0 1 -1.25-1.7324z"/></g></svg>
diff --git a/editor/icons/AnimatedSprite3D.svg b/editor/icons/AnimatedSprite3D.svg
index b25ebae683..99520a3bc2 100644
--- a/editor/icons/AnimatedSprite3D.svg
+++ b/editor/icons/AnimatedSprite3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc9c9c"><path d="m7 0c-1.108 0-2 .89199-2 2h7c1.108 0 2 .89199 2 2v6c1.108 0 2-.89199 2-2v-6c0-1.108-.89199-2-2-2z" fill-opacity=".39216"/><path d="m5 2c-1.108 0-2 .89199-2 2h7c1.108 0 2 .89199 2 2v7c1.108 0 2-.89199 2-2v-7c0-1.108-.89199-2-2-2z" fill-opacity=".58824"/><path d="m3 4c-1.108 0-2 .89199-2 2v7c0 1.108.89199 2 2 2h7c1.108 0 2-.89199 2-2v-7c0-1.108-.89199-2-2-2zm0 4c.554 0 1 .446 1 1v1c0 .554-.446 1-1 1s-1-.446-1-1v-1c0-.554.446-1 1-1zm7 0c.554 0 1 .446 1 1v1c0 .554-.446 1-1 1s-1-.446-1-1v-1c0-.554.446-1 1-1zm-6 4h5a2.5 2 0 0 1 -1.25 1.7324 2.5 2 0 0 1 -2.5 0 2.5 2 0 0 1 -1.25-1.7324z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><path d="m7 0c-1.108 0-2 .89199-2 2h7c1.108 0 2 .89199 2 2v6c1.108 0 2-.89199 2-2v-6c0-1.108-.89199-2-2-2z" fill-opacity=".39216"/><path d="m5 2c-1.108 0-2 .89199-2 2h7c1.108 0 2 .89199 2 2v7c1.108 0 2-.89199 2-2v-7c0-1.108-.89199-2-2-2z" fill-opacity=".58824"/><path d="m3 4c-1.108 0-2 .89199-2 2v7c0 1.108.89199 2 2 2h7c1.108 0 2-.89199 2-2v-7c0-1.108-.89199-2-2-2zm0 4c.554 0 1 .446 1 1v1c0 .554-.446 1-1 1s-1-.446-1-1v-1c0-.554.446-1 1-1zm7 0c.554 0 1 .446 1 1v1c0 .554-.446 1-1 1s-1-.446-1-1v-1c0-.554.446-1 1-1zm-6 4h5a2.5 2 0 0 1 -1.25 1.7324 2.5 2 0 0 1 -2.5 0 2.5 2 0 0 1 -1.25-1.7324z"/></g></svg>
diff --git a/editor/icons/AnimationPlayer.svg b/editor/icons/AnimationPlayer.svg
index 52b6b02c15..68a2c82dd0 100644
--- a/editor/icons/AnimationPlayer.svg
+++ b/editor/icons/AnimationPlayer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1037.4v14h1.1667v-2h1.8333v2h8v-2h2v2h1v-14h-1v2h-2v-2h-8v2h-1.8333v-2zm1.1667 4h1.8333v2h-1.8333zm9.8333 0h2v2h-2zm-9.8333 4h1.8333v2h-1.8333zm9.8333 0h2v2h-2z" fill="#cea4f1" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1037.4v14h1.1667v-2h1.8333v2h8v-2h2v2h1v-14h-1v2h-2v-2h-8v2h-1.8333v-2zm1.1667 4h1.8333v2h-1.8333zm9.8333 0h2v2h-2zm-9.8333 4h1.8333v2h-1.8333zm9.8333 0h2v2h-2z" fill="#c38ef1" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/AnimationTree.svg b/editor/icons/AnimationTree.svg
index d6484097c9..04c4d60402 100644
--- a/editor/icons/AnimationTree.svg
+++ b/editor/icons/AnimationTree.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h1.166v-2h1.834v2h8v-2h2v2h1v-14h-1v2h-2v-2h-8v2h-1.834v-2zm4 3h2v1 1h1 3v2h-2v1 1h1 1v2h-1-2a1.0001 1.0001 0 0 1 -1-1v-1-2h-1a1.0001 1.0001 0 0 1 -1-1v-1-1zm-2.834 1h1.834v2h-1.834zm9.834 0h2v2h-2zm-9.834 4h1.834v2h-1.834zm9.834 0h2v2h-2z" fill="#cea4f1"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h1.166v-2h1.834v2h8v-2h2v2h1v-14h-1v2h-2v-2h-8v2h-1.834v-2zm4 3h2v1 1h1 3v2h-2v1 1h1 1v2h-1-2a1.0001 1.0001 0 0 1 -1-1v-1-2h-1a1.0001 1.0001 0 0 1 -1-1v-1-1zm-2.834 1h1.834v2h-1.834zm9.834 0h2v2h-2zm-9.834 4h1.834v2h-1.834zm9.834 0h2v2h-2z" fill="#c38ef1"/></svg>
diff --git a/editor/icons/Area2D.svg b/editor/icons/Area2D.svg
index 005f70ed48..2150a582d2 100644
--- a/editor/icons/Area2D.svg
+++ b/editor/icons/Area2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 2h2v-2h2v-2zm10 0v2h2v2h2v-4zm-7 3v2 4 2h8v-2-6zm2 2h4v4h-4zm-5 5v2 2h2 2v-2h-2v-2zm12 0v2h-2v2h4v-2-2z" fill="#a5b7f3"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 2h2v-2h2v-2zm10 0v2h2v2h2v-4zm-7 3v2 4 2h8v-2-6zm2 2h4v4h-4zm-5 5v2 2h2 2v-2h-2v-2zm12 0v2h-2v2h4v-2-2z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/Area3D.svg b/editor/icons/Area3D.svg
index 4be8a2cced..88b6a42b23 100644
--- a/editor/icons/Area3D.svg
+++ b/editor/icons/Area3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 2h2v-2h2v-2zm10 0v2h2v2h2v-4zm-7 3v2 4 2h8v-2-6zm2 2h4v4h-4zm-5 5v2 2h2 2v-2h-2v-2zm12 0v2h-2v2h4v-2-2z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 2h2v-2h2v-2zm10 0v2h2v2h2v-4zm-7 3v2 4 2h8v-2-6zm2 2h4v4h-4zm-5 5v2 2h2 2v-2h-2v-2zm12 0v2h-2v2h4v-2-2z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/ArrayMesh.svg b/editor/icons/ArrayMesh.svg
index 3a33a966aa..2494a519fb 100644
--- a/editor/icons/ArrayMesh.svg
+++ b/editor/icons/ArrayMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm10 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-2 7v3h-3v2h3v3h2v-3h3v-2h-3v-3zm-8 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm10 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-2 7v3h-3v2h3v3h2v-3h3v-2h-3v-3zm-8 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/AspectRatioContainer.svg b/editor/icons/AspectRatioContainer.svg
index a7aef8e028..d28bcc7193 100644
--- a/editor/icons/AspectRatioContainer.svg
+++ b/editor/icons/AspectRatioContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-1.1046 0-2 .89543-2 2h2zm2 0v2h2v-2zm4 0v2h2c0-1.1046-.89543-2-2-2zm-8 4v2h2v-2zm8 0v2h2v-2zm-8 4v2h2v-2zm8 0v2h2v-2zm-8 4c0 1.1046.89543 2 2 2v-2zm4 0v2h2v-2zm4 0v2c1.1046 0 2-.89543 2-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-1.1046 0-2 .89543-2 2h2zm2 0v2h2v-2zm4 0v2h2c0-1.1046-.89543-2-2-2zm-8 4v2h2v-2zm8 0v2h2v-2zm-8 4v2h2v-2zm8 0v2h2v-2zm-8 4c0 1.1046.89543 2 2 2v-2zm4 0v2h2v-2zm4 0v2c1.1046 0 2-.89543 2-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/AudioBusLayout.svg b/editor/icons/AudioBusLayout.svg
index 3b1f3e7a0d..9928f369e7 100644
--- a/editor/icons/AudioBusLayout.svg
+++ b/editor/icons/AudioBusLayout.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m3 1c-1.108 0-2 .89199-2 2v10c0 1.108.89199 2 2 2h2c1.108 0 2-.89199 2-2v-10c0-1.108-.89199-2-2-2zm8 0c-1.108 0-2 .89199-2 2v10c0 1.108.89199 2 2 2h2c1.108 0 2-.89199 2-2v-10c0-1.108-.89199-2-2-2zm-8 1h2c.55401 0 1 .44599 1 1v10c0 .55401-.44599 1-1 1h-2c-.55401 0-1-.44599-1-1v-10c0-.55401.44599-1 1-1z" fill="url(#a)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m3 1c-1.108 0-2 .89199-2 2v10c0 1.108.89199 2 2 2h2c1.108 0 2-.89199 2-2v-10c0-1.108-.89199-2-2-2zm8 0c-1.108 0-2 .89199-2 2v10c0 1.108.89199 2 2 2h2c1.108 0 2-.89199 2-2v-10c0-1.108-.89199-2-2-2zm-8 1h2c.55401 0 1 .44599 1 1v10c0 .55401-.44599 1-1 1h-2c-.55401 0-1-.44599-1-1v-10c0-.55401.44599-1 1-1z" fill="url(#a)"/></svg>
diff --git a/editor/icons/AudioStreamMP3.svg b/editor/icons/AudioStreamMP3.svg
index 900d5873fe..dc034c90de 100644
--- a/editor/icons/AudioStreamMP3.svg
+++ b/editor/icons/AudioStreamMP3.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m11.971 1.002c-.08326.00207-.16593.014541-.24609.037109l-7 2c-.42881.12287-.7244.51487-.72461.96094v5.5508c-.16454-.033679-.33205-.050692-.5-.050781-1.3807 0-2.5 1.1193-2.5 2.5-.00000475 1.3807 1.1193 2.5 2.5 2.5 1.3456-.0013 2.4488-1.0674 2.4961-2.4121.0025906-.029226.003894-.058551.0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5c-.000916-.56314-.4664-1.0145-1.0293-.99805zm-1.4707 6.998c-.277 0-.5.223-.5.5v5c0 .277.223.5.5.5s.5-.223.5-.5v-5c0-.277-.223-.5-.5-.5zm2 1c-.277 0-.5.223-.5.5v3c0 .277.223.5.5.5s.5-.223.5-.5v-3c0-.277-.223-.5-.5-.5zm-4 1c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5zm6 0c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5z" fill="url(#a)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m11.971 1.002c-.08326.00207-.16593.014541-.24609.037109l-7 2c-.42881.12287-.7244.51487-.72461.96094v5.5508c-.16454-.033679-.33205-.050692-.5-.050781-1.3807 0-2.5 1.1193-2.5 2.5-.00000475 1.3807 1.1193 2.5 2.5 2.5 1.3456-.0013 2.4488-1.0674 2.4961-2.4121.0025906-.029226.003894-.058551.0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5c-.000916-.56314-.4664-1.0145-1.0293-.99805zm-1.4707 6.998c-.277 0-.5.223-.5.5v5c0 .277.223.5.5.5s.5-.223.5-.5v-5c0-.277-.223-.5-.5-.5zm2 1c-.277 0-.5.223-.5.5v3c0 .277.223.5.5.5s.5-.223.5-.5v-3c0-.277-.223-.5-.5-.5zm-4 1c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5zm6 0c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5z" fill="url(#a)"/></svg>
diff --git a/editor/icons/AudioStreamOGGVorbis.svg b/editor/icons/AudioStreamOGGVorbis.svg
index 900d5873fe..dc034c90de 100644
--- a/editor/icons/AudioStreamOGGVorbis.svg
+++ b/editor/icons/AudioStreamOGGVorbis.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m11.971 1.002c-.08326.00207-.16593.014541-.24609.037109l-7 2c-.42881.12287-.7244.51487-.72461.96094v5.5508c-.16454-.033679-.33205-.050692-.5-.050781-1.3807 0-2.5 1.1193-2.5 2.5-.00000475 1.3807 1.1193 2.5 2.5 2.5 1.3456-.0013 2.4488-1.0674 2.4961-2.4121.0025906-.029226.003894-.058551.0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5c-.000916-.56314-.4664-1.0145-1.0293-.99805zm-1.4707 6.998c-.277 0-.5.223-.5.5v5c0 .277.223.5.5.5s.5-.223.5-.5v-5c0-.277-.223-.5-.5-.5zm2 1c-.277 0-.5.223-.5.5v3c0 .277.223.5.5.5s.5-.223.5-.5v-3c0-.277-.223-.5-.5-.5zm-4 1c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5zm6 0c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5z" fill="url(#a)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m11.971 1.002c-.08326.00207-.16593.014541-.24609.037109l-7 2c-.42881.12287-.7244.51487-.72461.96094v5.5508c-.16454-.033679-.33205-.050692-.5-.050781-1.3807 0-2.5 1.1193-2.5 2.5-.00000475 1.3807 1.1193 2.5 2.5 2.5 1.3456-.0013 2.4488-1.0674 2.4961-2.4121.0025906-.029226.003894-.058551.0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5c-.000916-.56314-.4664-1.0145-1.0293-.99805zm-1.4707 6.998c-.277 0-.5.223-.5.5v5c0 .277.223.5.5.5s.5-.223.5-.5v-5c0-.277-.223-.5-.5-.5zm2 1c-.277 0-.5.223-.5.5v3c0 .277.223.5.5.5s.5-.223.5-.5v-3c0-.277-.223-.5-.5-.5zm-4 1c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5zm6 0c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5z" fill="url(#a)"/></svg>
diff --git a/editor/icons/AudioStreamPlayer.svg b/editor/icons/AudioStreamPlayer.svg
index 48aa7c2904..6d074c0744 100644
--- a/editor/icons/AudioStreamPlayer.svg
+++ b/editor/icons/AudioStreamPlayer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><g transform="translate(0 -1036.4)"><path d="m10.023 1044.4c-.56139-.013-1.0235.4264-1.0234.9724v5.0542c.0006911.7482.83361 1.2154 1.5.8414l4-2.5262c.66694-.3743.66694-1.3104 0-1.6847l-4-2.5261c-.14505-.082-.30893-.1269-.47656-.131z" fill="#e0e0e0"/><path d="m11.971 1.002a1.0001 1.0001 0 0 0 -.24609.037109l-7 2a1.0001 1.0001 0 0 0 -.72461.96094v5.5508a2.5 2.5 0 0 0 -.5-.050781 2.5 2.5 0 0 0 -2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.4961-2.4121 1.0001 1.0001 0 0 0 .0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5a1.0001 1.0001 0 0 0 -1.0293-.99805z" fill="url(#a)" transform="translate(0 1036.4)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><g transform="translate(0 -1036.4)"><path d="m10.023 1044.4c-.56139-.013-1.0235.4264-1.0234.9724v5.0542c.0006911.7482.83361 1.2154 1.5.8414l4-2.5262c.66694-.3743.66694-1.3104 0-1.6847l-4-2.5261c-.14505-.082-.30893-.1269-.47656-.131z" fill="#e0e0e0"/><path d="m11.971 1.002a1.0001 1.0001 0 0 0 -.24609.037109l-7 2a1.0001 1.0001 0 0 0 -.72461.96094v5.5508a2.5 2.5 0 0 0 -.5-.050781 2.5 2.5 0 0 0 -2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.4961-2.4121 1.0001 1.0001 0 0 0 .0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5a1.0001 1.0001 0 0 0 -1.0293-.99805z" fill="url(#a)" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/AudioStreamPlayer2D.svg b/editor/icons/AudioStreamPlayer2D.svg
index 21cf751c92..0bf091de29 100644
--- a/editor/icons/AudioStreamPlayer2D.svg
+++ b/editor/icons/AudioStreamPlayer2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><g transform="translate(0 -1036.4)"><path d="m10.023 1044.4c-.56139-.013-1.0235.4264-1.0234.9724v5.0542c.0006911.7482.83361 1.2154 1.5.8414l4-2.5262c.66694-.3743.66694-1.3104 0-1.6847l-4-2.5261c-.14505-.082-.30893-.1269-.47656-.131z" fill="#a5b7f3"/><path d="m11.971 1.002a1.0001 1.0001 0 0 0 -.24609.037109l-7 2a1.0001 1.0001 0 0 0 -.72461.96094v5.5508a2.5 2.5 0 0 0 -.5-.050781 2.5 2.5 0 0 0 -2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.4961-2.4121 1.0001 1.0001 0 0 0 .0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5a1.0001 1.0001 0 0 0 -1.0293-.99805z" fill="url(#a)" transform="translate(0 1036.4)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><g transform="translate(0 -1036.4)"><path d="m10.023 1044.4c-.56139-.013-1.0235.4264-1.0234.9724v5.0542c.0006911.7482.83361 1.2154 1.5.8414l4-2.5262c.66694-.3743.66694-1.3104 0-1.6847l-4-2.5261c-.14505-.082-.30893-.1269-.47656-.131z" fill="#8da5f3"/><path d="m11.971 1.002a1.0001 1.0001 0 0 0 -.24609.037109l-7 2a1.0001 1.0001 0 0 0 -.72461.96094v5.5508a2.5 2.5 0 0 0 -.5-.050781 2.5 2.5 0 0 0 -2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.4961-2.4121 1.0001 1.0001 0 0 0 .0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5a1.0001 1.0001 0 0 0 -1.0293-.99805z" fill="url(#a)" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/AudioStreamPlayer3D.svg b/editor/icons/AudioStreamPlayer3D.svg
index d1e39e62f3..ebe3128a21 100644
--- a/editor/icons/AudioStreamPlayer3D.svg
+++ b/editor/icons/AudioStreamPlayer3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><g transform="translate(0 -1036.4)"><path d="m10.023 1044.4c-.56139-.013-1.0235.4264-1.0234.9724v5.0542c.0006911.7482.83361 1.2154 1.5.8414l4-2.5262c.66694-.3743.66694-1.3104 0-1.6847l-4-2.5261c-.14505-.082-.30893-.1269-.47656-.131z" fill="#fc9c9c"/><path d="m11.971 1.002a1.0001 1.0001 0 0 0 -.24609.037109l-7 2a1.0001 1.0001 0 0 0 -.72461.96094v5.5508a2.5 2.5 0 0 0 -.5-.050781 2.5 2.5 0 0 0 -2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.4961-2.4121 1.0001 1.0001 0 0 0 .0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5a1.0001 1.0001 0 0 0 -1.0293-.99805z" fill="url(#a)" transform="translate(0 1036.4)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><g transform="translate(0 -1036.4)"><path d="m10.023 1044.4c-.56139-.013-1.0235.4264-1.0234.9724v5.0542c.0006911.7482.83361 1.2154 1.5.8414l4-2.5262c.66694-.3743.66694-1.3104 0-1.6847l-4-2.5261c-.14505-.082-.30893-.1269-.47656-.131z" fill="#fc7f7f"/><path d="m11.971 1.002a1.0001 1.0001 0 0 0 -.24609.037109l-7 2a1.0001 1.0001 0 0 0 -.72461.96094v5.5508a2.5 2.5 0 0 0 -.5-.050781 2.5 2.5 0 0 0 -2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.4961-2.4121 1.0001 1.0001 0 0 0 .0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5a1.0001 1.0001 0 0 0 -1.0293-.99805z" fill="url(#a)" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/AudioStreamSample.svg b/editor/icons/AudioStreamSample.svg
index 900d5873fe..dc034c90de 100644
--- a/editor/icons/AudioStreamSample.svg
+++ b/editor/icons/AudioStreamSample.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m11.971 1.002c-.08326.00207-.16593.014541-.24609.037109l-7 2c-.42881.12287-.7244.51487-.72461.96094v5.5508c-.16454-.033679-.33205-.050692-.5-.050781-1.3807 0-2.5 1.1193-2.5 2.5-.00000475 1.3807 1.1193 2.5 2.5 2.5 1.3456-.0013 2.4488-1.0674 2.4961-2.4121.0025906-.029226.003894-.058551.0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5c-.000916-.56314-.4664-1.0145-1.0293-.99805zm-1.4707 6.998c-.277 0-.5.223-.5.5v5c0 .277.223.5.5.5s.5-.223.5-.5v-5c0-.277-.223-.5-.5-.5zm2 1c-.277 0-.5.223-.5.5v3c0 .277.223.5.5.5s.5-.223.5-.5v-3c0-.277-.223-.5-.5-.5zm-4 1c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5zm6 0c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5z" fill="url(#a)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m11.971 1.002c-.08326.00207-.16593.014541-.24609.037109l-7 2c-.42881.12287-.7244.51487-.72461.96094v5.5508c-.16454-.033679-.33205-.050692-.5-.050781-1.3807 0-2.5 1.1193-2.5 2.5-.00000475 1.3807 1.1193 2.5 2.5 2.5 1.3456-.0013 2.4488-1.0674 2.4961-2.4121.0025906-.029226.003894-.058551.0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5c-.000916-.56314-.4664-1.0145-1.0293-.99805zm-1.4707 6.998c-.277 0-.5.223-.5.5v5c0 .277.223.5.5.5s.5-.223.5-.5v-5c0-.277-.223-.5-.5-.5zm2 1c-.277 0-.5.223-.5.5v3c0 .277.223.5.5.5s.5-.223.5-.5v-3c0-.277-.223-.5-.5-.5zm-4 1c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5zm6 0c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5z" fill="url(#a)"/></svg>
diff --git a/editor/icons/BackBufferCopy.svg b/editor/icons/BackBufferCopy.svg
index 9bd40395c0..c85a35a410 100644
--- a/editor/icons/BackBufferCopy.svg
+++ b/editor/icons/BackBufferCopy.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v11h5v-2h-3v-7h6v-2zm6 3v11h8v-11zm2 2h4v7h-4z" fill="#a5b7f3"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v11h5v-2h-3v-7h6v-2zm6 3v11h8v-11zm2 2h4v7h-4z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/BakedLightmap.svg b/editor/icons/BakedLightmap.svg
deleted file mode 100644
index ea9efa55ba..0000000000
--- a/editor/icons/BakedLightmap.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1v2h12v-2zm-1 3v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-9zm2 1h1v1h-1zm3 0h1v1h-1zm3 0h1v1h-1zm3 0h1v1h-1zm-9 2h10v6h-10zm3 1v1h4v-1z" fill="#fc9c9c"/></svg>
diff --git a/editor/icons/Basis.svg b/editor/icons/Basis.svg
index 5ff892888a..e425cf3bcd 100644
--- a/editor/icons/Basis.svg
+++ b/editor/icons/Basis.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2v8h2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2zm10 0v2h2v-2zm-3 2a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2zm7 0a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v-2h-2v4h4a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2zm-12 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#e3ec69"/><path d="m10 2v2h2v-2zm0 4v4h2v-4z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2v8h2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2zm10 0v2h2v-2zm-3 2a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2zm7 0a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v-2h-2v4h4a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2zm-12 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#e1ec41"/><path d="m10 2v2h2v-2zm0 4v4h2v-4z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/BezierHandlesBalanced.svg b/editor/icons/BezierHandlesBalanced.svg
index e4b8ae12e3..911029e431 100644
--- a/editor/icons/BezierHandlesBalanced.svg
+++ b/editor/icons/BezierHandlesBalanced.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.7627119 13.627119s1.2881355-6.847458 6.5762712-8.1355935c5.0847459.9491522 5.9661009 8.1355925 5.9661009 8.1355925" fill="none" stroke="#84c2ff" stroke-miterlimit="4.9" stroke-width="1.7"/><ellipse cx="1.898304" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><ellipse cx="14.237288" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><path d="m7.4559186 5.1473018-4.7355323 1.5541798" fill="none" stroke="#84c2ff" stroke-width=".618"/><path d="m10.790357 4.2063094-2.5009748.9433136" fill="none" stroke="#84c2ff" stroke-width=".614897"/><g fill="#e0e0e0"><ellipse cx="8.271187" cy="4.779661" rx="1.267586" ry="1.199789"/><path d="m1.7157324 5.8754878a1.2675855 1.1997888 0 0 0 -1.26757806 1.1992188 1.2675855 1.1997888 0 0 0 1.26757806 1.1992187 1.2675855 1.1997888 0 0 0 1.2675781-1.1992187 1.2675855 1.1997888 0 0 0 -1.2675781-1.1992188zm.00195.4238282a.84677333.80148375 0 0 1 .8476593.8007812.84677333.80148375 0 0 1 -.8476562.8007812.84677333.80148375 0 0 1 -.84765616-.8007812.84677333.80148375 0 0 1 .84765616-.8007812z"/><path d="m11.909414 2.4642073a1.2836218 1.231838 0 0 0 -1.283614 1.2312528 1.2836218 1.231838 0 0 0 1.283614 1.2312527 1.2836218 1.231838 0 0 0 1.283614-1.2312527 1.2836218 1.231838 0 0 0 -1.283614-1.2312528zm.002.4351497a.85748593.82289328 0 0 1 .858383.8221719.85748593.82289328 0 0 1 -.85838.822172.85748593.82289328 0 0 1 -.858379-.822172.85748593.82289328 0 0 1 .858379-.8221719z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.7627119 13.627119s1.2881355-6.847458 6.5762712-8.1355935c5.0847459.9491522 5.9661009 8.1355925 5.9661009 8.1355925" fill="none" stroke="#5fb2ff" stroke-miterlimit="4.9" stroke-width="1.7"/><ellipse cx="1.898304" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><ellipse cx="14.237288" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><path d="m7.4559186 5.1473018-4.7355323 1.5541798" fill="none" stroke="#5fb2ff" stroke-width=".618"/><path d="m10.790357 4.2063094-2.5009748.9433136" fill="none" stroke="#5fb2ff" stroke-width=".614897"/><g fill="#e0e0e0"><ellipse cx="8.271187" cy="4.779661" rx="1.267586" ry="1.199789"/><path d="m1.7157324 5.8754878a1.2675855 1.1997888 0 0 0 -1.26757806 1.1992188 1.2675855 1.1997888 0 0 0 1.26757806 1.1992187 1.2675855 1.1997888 0 0 0 1.2675781-1.1992187 1.2675855 1.1997888 0 0 0 -1.2675781-1.1992188zm.00195.4238282a.84677333.80148375 0 0 1 .8476593.8007812.84677333.80148375 0 0 1 -.8476562.8007812.84677333.80148375 0 0 1 -.84765616-.8007812.84677333.80148375 0 0 1 .84765616-.8007812z"/><path d="m11.909414 2.4642073a1.2836218 1.231838 0 0 0 -1.283614 1.2312528 1.2836218 1.231838 0 0 0 1.283614 1.2312527 1.2836218 1.231838 0 0 0 1.283614-1.2312527 1.2836218 1.231838 0 0 0 -1.283614-1.2312528zm.002.4351497a.85748593.82289328 0 0 1 .858383.8221719.85748593.82289328 0 0 1 -.85838.822172.85748593.82289328 0 0 1 -.858379-.822172.85748593.82289328 0 0 1 .858379-.8221719z"/></g></svg>
diff --git a/editor/icons/BezierHandlesFree.svg b/editor/icons/BezierHandlesFree.svg
index 88f8146871..6e91288c79 100644
--- a/editor/icons/BezierHandlesFree.svg
+++ b/editor/icons/BezierHandlesFree.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.7627119 13.627119s1.2881355-6.847458 6.5762712-8.1355935c5.0847459.9491522 5.9661009 8.1355925 5.9661009 8.1355925" fill="none" stroke="#84c2ff" stroke-miterlimit="4.9" stroke-width="1.7"/><ellipse cx="1.898304" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><ellipse cx="14.237288" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><path d="m7.6850253 4.7560401-3.776127.6607599" fill="none" stroke="#84c2ff" stroke-width=".805138"/><path d="m11.695505 2.3941651-2.999121 2.2935078" fill="none" stroke="#84c2ff" stroke-width=".730798"/><g fill="#e0e0e0"><ellipse cx="8.271187" cy="4.779661" rx="1.267586" ry="1.199789"/><path d="m2.4961199 4.3976698a1.1997888 1.2675855 80.074672 0 0 -1.0419038 1.3997559 1.1997888 1.2675855 80.074672 0 0 1.4553094.9627848 1.1997888 1.2675855 80.074672 0 0 1.0419037-1.3997558 1.1997888 1.2675855 80.074672 0 0 -1.4553093-.9627849zm.074974.4171488a.80148375.84677333 80.074672 0 1 .9729986.6426896.80148375.84677333 80.074672 0 1 -.6969432.934902.80148375.84677333 80.074672 0 1 -.9729958-.6426902.80148375.84677333 80.074672 0 1 .6969432-.934902z"/><path d="m11.838896.64428913a1.231838 1.2836218 52.593897 0 0 -.271701 1.75779027 1.231838 1.2836218 52.593897 0 0 1.767576.1983008 1.231838 1.2836218 52.593897 0 0 .271701-1.75779027 1.231838 1.2836218 52.593897 0 0 -1.767576-.1983008zm.265925.3444462a.82289328.85748593 52.593897 0 1 1.181294.13165847.82289328.85748593 52.593897 0 1 -.182417 1.1745241.82289328.85748593 52.593897 0 1 -1.181291-.1316609.82289328.85748593 52.593897 0 1 .182417-1.17452347z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.7627119 13.627119s1.2881355-6.847458 6.5762712-8.1355935c5.0847459.9491522 5.9661009 8.1355925 5.9661009 8.1355925" fill="none" stroke="#5fb2ff" stroke-miterlimit="4.9" stroke-width="1.7"/><ellipse cx="1.898304" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><ellipse cx="14.237288" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><path d="m7.6850253 4.7560401-3.776127.6607599" fill="none" stroke="#5fb2ff" stroke-width=".805138"/><path d="m11.695505 2.3941651-2.999121 2.2935078" fill="none" stroke="#5fb2ff" stroke-width=".730798"/><g fill="#e0e0e0"><ellipse cx="8.271187" cy="4.779661" rx="1.267586" ry="1.199789"/><path d="m2.4961199 4.3976698a1.1997888 1.2675855 80.074672 0 0 -1.0419038 1.3997559 1.1997888 1.2675855 80.074672 0 0 1.4553094.9627848 1.1997888 1.2675855 80.074672 0 0 1.0419037-1.3997558 1.1997888 1.2675855 80.074672 0 0 -1.4553093-.9627849zm.074974.4171488a.80148375.84677333 80.074672 0 1 .9729986.6426896.80148375.84677333 80.074672 0 1 -.6969432.934902.80148375.84677333 80.074672 0 1 -.9729958-.6426902.80148375.84677333 80.074672 0 1 .6969432-.934902z"/><path d="m11.838896.64428913a1.231838 1.2836218 52.593897 0 0 -.271701 1.75779027 1.231838 1.2836218 52.593897 0 0 1.767576.1983008 1.231838 1.2836218 52.593897 0 0 .271701-1.75779027 1.231838 1.2836218 52.593897 0 0 -1.767576-.1983008zm.265925.3444462a.82289328.85748593 52.593897 0 1 1.181294.13165847.82289328.85748593 52.593897 0 1 -.182417 1.1745241.82289328.85748593 52.593897 0 1 -1.181291-.1316609.82289328.85748593 52.593897 0 1 .182417-1.17452347z"/></g></svg>
diff --git a/editor/icons/BezierHandlesMirror.svg b/editor/icons/BezierHandlesMirror.svg
index 3a4b75ee96..9180e31921 100644
--- a/editor/icons/BezierHandlesMirror.svg
+++ b/editor/icons/BezierHandlesMirror.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.7627119 13.627119s1.2881355-6.847458 6.5762712-8.1355935c5.0847459.9491522 5.9661009 8.1355925 5.9661009 8.1355925" fill="none" stroke="#84c2ff" stroke-miterlimit="4.9" stroke-width="1.7"/><ellipse cx="1.898304" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><ellipse cx="14.237288" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><path d="m8.2033896 4.6779662h-3.8335021" fill="none" stroke="#84c2ff" stroke-width=".805138"/><path d="m11.931789 4.6440679h-3.7283994" fill="none" stroke="#84c2ff" stroke-width=".716709"/><g fill="#e0e0e0"><ellipse cx="8.271187" cy="4.779661" rx="1.267586" ry="1.199789"/><path d="m3.1539157 3.4305762a1.2675855 1.1997888 0 0 0 -1.2675781 1.1992188 1.2675855 1.1997888 0 0 0 1.2675781 1.1992187 1.2675855 1.1997888 0 0 0 1.2675781-1.1992187 1.2675855 1.1997888 0 0 0 -1.2675781-1.1992188zm.00195.4238282a.84677333.80148375 0 0 1 .8476593.8007812.84677333.80148375 0 0 1 -.8476562.8007812.84677333.80148375 0 0 1 -.8476562-.8007812.84677333.80148375 0 0 1 .8476562-.8007812z"/><path d="m13.093969 3.3750567a1.2675855 1.1997888 0 0 0 -1.267578 1.1992188 1.2675855 1.1997888 0 0 0 1.267578 1.1992187 1.2675855 1.1997888 0 0 0 1.267578-1.1992187 1.2675855 1.1997888 0 0 0 -1.267578-1.1992188zm.002.4238282a.84677333.80148375 0 0 1 .847659.8007812.84677333.80148375 0 0 1 -.847656.8007812.84677333.80148375 0 0 1 -.847656-.8007812.84677333.80148375 0 0 1 .847656-.8007812z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.7627119 13.627119s1.2881355-6.847458 6.5762712-8.1355935c5.0847459.9491522 5.9661009 8.1355925 5.9661009 8.1355925" fill="none" stroke="#5fb2ff" stroke-miterlimit="4.9" stroke-width="1.7"/><ellipse cx="1.898304" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><ellipse cx="14.237288" cy="13.491526" fill="#e0e0e0" rx="1.267586" ry="1.199789"/><path d="m8.2033896 4.6779662h-3.8335021" fill="none" stroke="#5fb2ff" stroke-width=".805138"/><path d="m11.931789 4.6440679h-3.7283994" fill="none" stroke="#5fb2ff" stroke-width=".716709"/><g fill="#e0e0e0"><ellipse cx="8.271187" cy="4.779661" rx="1.267586" ry="1.199789"/><path d="m3.1539157 3.4305762a1.2675855 1.1997888 0 0 0 -1.2675781 1.1992188 1.2675855 1.1997888 0 0 0 1.2675781 1.1992187 1.2675855 1.1997888 0 0 0 1.2675781-1.1992187 1.2675855 1.1997888 0 0 0 -1.2675781-1.1992188zm.00195.4238282a.84677333.80148375 0 0 1 .8476593.8007812.84677333.80148375 0 0 1 -.8476562.8007812.84677333.80148375 0 0 1 -.8476562-.8007812.84677333.80148375 0 0 1 .8476562-.8007812z"/><path d="m13.093969 3.3750567a1.2675855 1.1997888 0 0 0 -1.267578 1.1992188 1.2675855 1.1997888 0 0 0 1.267578 1.1992187 1.2675855 1.1997888 0 0 0 1.267578-1.1992187 1.2675855 1.1997888 0 0 0 -1.267578-1.1992188zm.002.4238282a.84677333.80148375 0 0 1 .847659.8007812.84677333.80148375 0 0 1 -.847656.8007812.84677333.80148375 0 0 1 -.847656-.8007812.84677333.80148375 0 0 1 .847656-.8007812z"/></g></svg>
diff --git a/editor/icons/Bone2D.svg b/editor/icons/Bone2D.svg
index 2298022d6a..efbe9ca5b0 100644
--- a/editor/icons/Bone2D.svg
+++ b/editor/icons/Bone2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#a5b7f3" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#8da5f3" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/BoneAttachment3D.svg b/editor/icons/BoneAttachment3D.svg
index 2f2a9cdae5..be15631b5e 100644
--- a/editor/icons/BoneAttachment3D.svg
+++ b/editor/icons/BoneAttachment3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#fc9c9c" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#fc7f7f" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/BoneTrack.svg b/editor/icons/BoneTrack.svg
index 34fb76e696..69a32f3595 100644
--- a/editor/icons/BoneTrack.svg
+++ b/editor/icons/BoneTrack.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#cea4f1" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#c38ef1" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/BoxMesh.svg b/editor/icons/BoxMesh.svg
index d540858248..6809b989cc 100644
--- a/editor/icons/BoxMesh.svg
+++ b/editor/icons/BoxMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 .88867-7 3.5v7.2227l7 3.5 7-3.5v-7.2227zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002zm10 0v3.9395l-4 2.002v-3.9414z" fill="#ffd684" stroke-width="1.0667" transform="scale(.9375)"/></svg>
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 .88867-7 3.5v7.2227l7 3.5 7-3.5v-7.2227zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002zm10 0v3.9395l-4 2.002v-3.9414z" fill="#ffca5f" stroke-width="1.0667" transform="scale(.9375)"/></svg>
diff --git a/editor/icons/BusVuEmpty.svg b/editor/icons/BusVuEmpty.svg
index 32a27e26b5..cc72e7cd36 100644
--- a/editor/icons/BusVuEmpty.svg
+++ b/editor/icons/BusVuEmpty.svg
@@ -1 +1 @@
-<svg height="128" viewBox="0 0 16 128" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="926.36" y2="1050.36"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><g transform="translate(0 -924.36)"><path d="m3 926.36c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 5c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1z" fill="url(#a)"/><path d="m3 2c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 5c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1z" fill-opacity=".19608" transform="translate(0 924.36)"/></g></svg>
+<svg height="128" viewBox="0 0 16 128" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="926.36" y2="1050.36"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><g transform="translate(0 -924.36)"><path d="m3 926.36c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 5c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1z" fill="url(#a)"/><path d="m3 2c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 5c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1z" fill-opacity=".19608" transform="translate(0 924.36)"/></g></svg>
diff --git a/editor/icons/BusVuFull.svg b/editor/icons/BusVuFull.svg
index acfa742d18..34396c3c18 100644
--- a/editor/icons/BusVuFull.svg
+++ b/editor/icons/BusVuFull.svg
@@ -1 +1 @@
-<svg height="128" viewBox="0 0 16 128" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="2" y2="126"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m3 2c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 5c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1z" fill="url(#a)"/></svg>
+<svg height="128" viewBox="0 0 16 128" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="2" y2="126"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m3 2c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 5c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1z" fill="url(#a)"/></svg>
diff --git a/editor/icons/Button.svg b/editor/icons/Button.svg
index 6046038289..a856b29a02 100644
--- a/editor/icons/Button.svg
+++ b/editor/icons/Button.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3.1328l-1.4453-.96484-1.1094 1.6641 3 2a1.0001 1.0001 0 0 0 1.1094 0l3-2-1.1094-1.6641-1.4453.96484v-3.1328zm-1.5 8c-.831 0-1.5.669-1.5 1.5v1.5h-2v2h12v-2h-2v-1.5c0-.831-.669-1.5-1.5-1.5z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3.1328l-1.4453-.96484-1.1094 1.6641 3 2a1.0001 1.0001 0 0 0 1.1094 0l3-2-1.1094-1.6641-1.4453.96484v-3.1328zm-1.5 8c-.831 0-1.5.669-1.5 1.5v1.5h-2v2h12v-2h-2v-1.5c0-.831-.669-1.5-1.5-1.5z" fill="#8eef97"/></svg>
diff --git a/editor/icons/CPUParticles3D.svg b/editor/icons/CPUParticles3D.svg
index 072703cfa9..d7ced5fc6b 100644
--- a/editor/icons/CPUParticles3D.svg
+++ b/editor/icons/CPUParticles3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4.5587261.60940813c-.4226244 0-.7617187.3410473-.7617187.76367177v.5078126c0 .1028478.020058.199689.056641.2890624h-1.1933597c-.4226245 0-.7617188.3390944-.7617188.7617188v.921875c-.040428-.00657-.0767989-.0234375-.1191406-.0234375h-.5078125c-.42262448 0-.76367188.3410475-.76367188.7636719v.3730468c0 .4226245.3410474.7617188.76367188.7617188h.5078125c.042396 0 .078663-.016851.1191406-.023437v4.4531248c-.040428-.0066-.076799-.02344-.1191406-.02344h-.5078125c-.42262448 0-.76367188.341047-.76367188.763672v.373047c0 .422625.3410474.761718.76367188.761718h.5078125c.042396 0 .078663-.01685.1191406-.02344v1.125c0 .422624.3390944.763672.7617188.763672h1.1367187v.457031c0 .422624.3390943.763672.7617187.763672h.3730469c.4226244 0 .7636719-.341048.7636719-.763672v-.457031h4.4062501v.457031c0 .422624.339094.763672.761719.763672h.373047c.422624 0 .763671-.341048.763671-.763672v-.457031h1.269532c.422625 0 .763672-.341048.763672-.763672v-1.111328c.01774.0012.03272.0098.05078.0098h.507812c.422624 0 .763672-.339093.763672-.761718v-.373047c0-.422624-.341048-.763672-.763672-.763672h-.507812c-.01803 0-.03307.0085-.05078.0098v-4.4258454c.01774.00122.03272.00977.05078.00977h.507812c.422624 0 .763672-.3390943.763672-.7617188v-.3730512c0-.4226244-.341048-.7636719-.763672-.7636719h-.507812c-.01803 0-.03307.00855-.05078.00977v-.9082075c0-.4226244-.341047-.7617187-.763672-.7617188h-1.328125c.03658-.089375.05859-.1862118.05859-.2890624v-.5078126c0-.42262437-.341047-.76367177-.763671-.76367177h-.373047c-.422625 0-.761719.3410474-.761719.76367177v.5078126c0 .1028478.02006.1996891.05664.2890624h-4.5214809c.036585-.0893749.0585938-.1862118.0585938-.2890624v-.5078126c0-.42262437-.3410475-.76367177-.7636719-.76367177zm3.2382813 2.35742177a3.279661 3.6440678 0 0 1 3.2128906 2.9394532 2.1864407 2.1864407 0 0 1 1.888672 2.1621094 2.1864407 2.1864407 0 0 1 -2.1875 2.1855475h-5.8300782a2.1864407 2.1864407 0 0 1 -2.1855469-2.1855475 2.1864407 2.1864407 0 0 1 1.8847656-2.1640626 3.279661 3.6440678 0 0 1 3.2167969-2.9375zm-2.9160156 8.0156251a.72881355.72881355 0 0 1 .7285156.728516.72881355.72881355 0 0 1 -.7285156.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm5.8300782 0a.72881355.72881355 0 0 1 .730469.728516.72881355.72881355 0 0 1 -.730469.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm-2.9140626.728516a.72881355.72881355 0 0 1 .7285156.730469.72881355.72881355 0 0 1 -.7285156.728515.72881355.72881355 0 0 1 -.7285156-.728515.72881355.72881355 0 0 1 .7285156-.730469z" fill="#fc9c9c" fill-opacity=".996078"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4.5587261.60940813c-.4226244 0-.7617187.3410473-.7617187.76367177v.5078126c0 .1028478.020058.199689.056641.2890624h-1.1933597c-.4226245 0-.7617188.3390944-.7617188.7617188v.921875c-.040428-.00657-.0767989-.0234375-.1191406-.0234375h-.5078125c-.42262448 0-.76367188.3410475-.76367188.7636719v.3730468c0 .4226245.3410474.7617188.76367188.7617188h.5078125c.042396 0 .078663-.016851.1191406-.023437v4.4531248c-.040428-.0066-.076799-.02344-.1191406-.02344h-.5078125c-.42262448 0-.76367188.341047-.76367188.763672v.373047c0 .422625.3410474.761718.76367188.761718h.5078125c.042396 0 .078663-.01685.1191406-.02344v1.125c0 .422624.3390944.763672.7617188.763672h1.1367187v.457031c0 .422624.3390943.763672.7617187.763672h.3730469c.4226244 0 .7636719-.341048.7636719-.763672v-.457031h4.4062501v.457031c0 .422624.339094.763672.761719.763672h.373047c.422624 0 .763671-.341048.763671-.763672v-.457031h1.269532c.422625 0 .763672-.341048.763672-.763672v-1.111328c.01774.0012.03272.0098.05078.0098h.507812c.422624 0 .763672-.339093.763672-.761718v-.373047c0-.422624-.341048-.763672-.763672-.763672h-.507812c-.01803 0-.03307.0085-.05078.0098v-4.4258454c.01774.00122.03272.00977.05078.00977h.507812c.422624 0 .763672-.3390943.763672-.7617188v-.3730512c0-.4226244-.341048-.7636719-.763672-.7636719h-.507812c-.01803 0-.03307.00855-.05078.00977v-.9082075c0-.4226244-.341047-.7617187-.763672-.7617188h-1.328125c.03658-.089375.05859-.1862118.05859-.2890624v-.5078126c0-.42262437-.341047-.76367177-.763671-.76367177h-.373047c-.422625 0-.761719.3410474-.761719.76367177v.5078126c0 .1028478.02006.1996891.05664.2890624h-4.5214809c.036585-.0893749.0585938-.1862118.0585938-.2890624v-.5078126c0-.42262437-.3410475-.76367177-.7636719-.76367177zm3.2382813 2.35742177a3.279661 3.6440678 0 0 1 3.2128906 2.9394532 2.1864407 2.1864407 0 0 1 1.888672 2.1621094 2.1864407 2.1864407 0 0 1 -2.1875 2.1855475h-5.8300782a2.1864407 2.1864407 0 0 1 -2.1855469-2.1855475 2.1864407 2.1864407 0 0 1 1.8847656-2.1640626 3.279661 3.6440678 0 0 1 3.2167969-2.9375zm-2.9160156 8.0156251a.72881355.72881355 0 0 1 .7285156.728516.72881355.72881355 0 0 1 -.7285156.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm5.8300782 0a.72881355.72881355 0 0 1 .730469.728516.72881355.72881355 0 0 1 -.730469.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm-2.9140626.728516a.72881355.72881355 0 0 1 .7285156.730469.72881355.72881355 0 0 1 -.7285156.728515.72881355.72881355 0 0 1 -.7285156-.728515.72881355.72881355 0 0 1 .7285156-.730469z" fill="#fc7f7f" fill-opacity=".996078"/></svg>
diff --git a/editor/icons/Camera2D.svg b/editor/icons/Camera2D.svg
index b6aa869be3..6b0f8e603f 100644
--- a/editor/icons/Camera2D.svg
+++ b/editor/icons/Camera2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1038.4a3 3 0 0 0 -2.9883 2.7774 3 3 0 0 0 -2.0117-.7774 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8243v2.1757c0 .554.44599 1 1 1h6c.55401 0 1-.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1-2.2305 3 3 0 0 0 -3-3z" fill="#a5b7f3" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1038.4a3 3 0 0 0 -2.9883 2.7774 3 3 0 0 0 -2.0117-.7774 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8243v2.1757c0 .554.44599 1 1 1h6c.55401 0 1-.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1-2.2305 3 3 0 0 0 -3-3z" fill="#8da5f3" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/Camera3D.svg b/editor/icons/Camera3D.svg
index f6e99cb56e..a8dee93de2 100644
--- a/editor/icons/Camera3D.svg
+++ b/editor/icons/Camera3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1038.4a3 3 0 0 0 -2.9883 2.7774 3 3 0 0 0 -2.0117-.7774 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8243v2.1757c0 .554.44599 1 1 1h6c.55401 0 1-.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1-2.2305 3 3 0 0 0 -3-3z" fill="#fc9c9c" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1038.4a3 3 0 0 0 -2.9883 2.7774 3 3 0 0 0 -2.0117-.7774 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8243v2.1757c0 .554.44599 1 1 1h6c.55401 0 1-.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1-2.2305 3 3 0 0 0 -3-3z" fill="#fc7f7f" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/CameraEffects.svg b/editor/icons/CameraEffects.svg
index de1d55e1a9..1ee7e15c87 100644
--- a/editor/icons/CameraEffects.svg
+++ b/editor/icons/CameraEffects.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5.9492188 2a3 3 0 0 0 -2.9492188 3 3 3 0 0 0 1 2.2304688v1.7695312l-3-2v6l3-2v1c0 .554.44599 1 1 1h3c.0076117-.045309.0115938-.096059.0214844-.134766.0773621-.302758.1860981-.478282.2832031-.625.1397097-.211089.2814954-.338835.4257813-.480468-.1445165-.141692-.2879205-.269839-.4277344-.480469-.0971224-.146315-.2052562-.321748-.2832032-.623047-.0777157-.300405-.1044198-.8152648.1640626-1.2910156.2700589-.4775976.7340166-.7239536 1.0371093-.8105469.3037241-.0867737.5108695-.0808838.6875-.0703125.2608449.0156115.4500479.0763383.6503909.1328125.049596-.1859081.086921-.3641449.195312-.5800781.078477-.1563394.174637-.3364783.396485-.5527344.221847-.2162561.652628-.4930277 1.195312-.4980469a1.6124973 1.6124973 0 0 1 .033203 0c.542861.0056205.97185.2837448 1.19336.5.146452.1429781.230167.265896.298828.3808594a3 3 0 0 0 .128906-.8671875 3 3 0 0 0 -3-3 3 3 0 0 0 -2.0117188.7773438 3 3 0 0 0 -2.9882812-2.7773438 3 3 0 0 0 -.0507812 0z" fill="#e0e0e0"/><path d="m12.36062 8.59795a.53334 3.2001 0 0 0 -.50976 2.2754 3.2001.53334 30 0 0 -2.2656-.71484 3.2001.53334 30 0 0 1.75 1.6016.53334 3.2001 60 0 0 -1.7461 1.5996.53334 3.2001 60 0 0 2.2578-.71094.53334 3.2001 0 0 0 .51367 2.3496.53334 3.2001 0 0 0 .51367-2.3516 3.2001.53334 30 0 0 2.2539.71094 3.2001.53334 30 0 0 -1.7441-1.5977.53334 3.2001 60 0 0 1.748-1.5996.53334 3.2001 60 0 0 -2.2617.71484.53334 3.2001 0 0 0 -.50977-2.2773z" fill="#cea4f1" stroke-width="1.0667"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5.9492188 2a3 3 0 0 0 -2.9492188 3 3 3 0 0 0 1 2.2304688v1.7695312l-3-2v6l3-2v1c0 .554.44599 1 1 1h3c.0076117-.045309.0115938-.096059.0214844-.134766.0773621-.302758.1860981-.478282.2832031-.625.1397097-.211089.2814954-.338835.4257813-.480468-.1445165-.141692-.2879205-.269839-.4277344-.480469-.0971224-.146315-.2052562-.321748-.2832032-.623047-.0777157-.300405-.1044198-.8152648.1640626-1.2910156.2700589-.4775976.7340166-.7239536 1.0371093-.8105469.3037241-.0867737.5108695-.0808838.6875-.0703125.2608449.0156115.4500479.0763383.6503909.1328125.049596-.1859081.086921-.3641449.195312-.5800781.078477-.1563394.174637-.3364783.396485-.5527344.221847-.2162561.652628-.4930277 1.195312-.4980469a1.6124973 1.6124973 0 0 1 .033203 0c.542861.0056205.97185.2837448 1.19336.5.146452.1429781.230167.265896.298828.3808594a3 3 0 0 0 .128906-.8671875 3 3 0 0 0 -3-3 3 3 0 0 0 -2.0117188.7773438 3 3 0 0 0 -2.9882812-2.7773438 3 3 0 0 0 -.0507812 0z" fill="#e0e0e0"/><path d="m12.36062 8.59795a.53334 3.2001 0 0 0 -.50976 2.2754 3.2001.53334 30 0 0 -2.2656-.71484 3.2001.53334 30 0 0 1.75 1.6016.53334 3.2001 60 0 0 -1.7461 1.5996.53334 3.2001 60 0 0 2.2578-.71094.53334 3.2001 0 0 0 .51367 2.3496.53334 3.2001 0 0 0 .51367-2.3516 3.2001.53334 30 0 0 2.2539.71094 3.2001.53334 30 0 0 -1.7441-1.5977.53334 3.2001 60 0 0 1.748-1.5996.53334 3.2001 60 0 0 -2.2617.71484.53334 3.2001 0 0 0 -.50977-2.2773z" fill="#c38ef1" stroke-width="1.0667"/></svg>
diff --git a/editor/icons/CanvasItemMaterial.svg b/editor/icons/CanvasItemMaterial.svg
index 241184f8b9..9a7a89431c 100644
--- a/editor/icons/CanvasItemMaterial.svg
+++ b/editor/icons/CanvasItemMaterial.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.1035 3a7 7 0 0 0 -1.418 2h12.631a7 7 0 0 0 -1.4277-2h-9.7852z" fill="#ffeb70"/><path d="m1.6855 5a7 7 0 0 0 -.60547 2h13.842a7 7 0 0 0 -.60547-2h-12.631z" fill="#9dff70"/><path d="m1.0801 7a7 7 0 0 0 -.080078 1 7 7 0 0 0 .078125 1h13.842a7 7 0 0 0 .080078-1 7 7 0 0 0 -.078125-1z" fill="#70ffb9"/><path d="m1.0781 9a7 7 0 0 0 .60547 2h12.631a7 7 0 0 0 .60547-2h-13.842z" fill="#70deff"/><path d="m3.1113 13a7 7 0 0 0 4.8887 2 7 7 0 0 0 4.8965-2z" fill="#ff70ac"/><path d="m1.6836 11a7 7 0 0 0 1.4277 2h9.7852a7 7 0 0 0 1.418-2h-12.631z" fill="#9f70ff"/><path d="m8 1a7 7 0 0 0 -4.8965 2h9.7852a7 7 0 0 0 -4.8887-2z" fill="#ff7070"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.1035 3a7 7 0 0 0 -1.418 2h12.631a7 7 0 0 0 -1.4277-2h-9.7852z" fill="#ffe345"/><path d="m1.6855 5a7 7 0 0 0 -.60547 2h13.842a7 7 0 0 0 -.60547-2h-12.631z" fill="#80ff45"/><path d="m1.0801 7a7 7 0 0 0 -.080078 1 7 7 0 0 0 .078125 1h13.842a7 7 0 0 0 .080078-1 7 7 0 0 0 -.078125-1z" fill="#45ffa2"/><path d="m1.0781 9a7 7 0 0 0 .60547 2h12.631a7 7 0 0 0 .60547-2h-13.842z" fill="#45d7ff"/><path d="m3.1113 13a7 7 0 0 0 4.8887 2 7 7 0 0 0 4.8965-2z" fill="#ff4596"/><path d="m1.6836 11a7 7 0 0 0 1.4277 2h9.7852a7 7 0 0 0 1.418-2h-12.631z" fill="#8045ff"/><path d="m8 1a7 7 0 0 0 -4.8965 2h9.7852a7 7 0 0 0 -4.8887-2z" fill="#ff4545"/></svg>
diff --git a/editor/icons/CanvasItemShader.svg b/editor/icons/CanvasItemShader.svg
index b8b1588843..9aeb2f0fdc 100644
--- a/editor/icons/CanvasItemShader.svg
+++ b/editor/icons/CanvasItemShader.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.303 1c-.4344 0-.86973.16881-1.2012.50586l-1.4688 1.4941h4.3418c.082839-.52789-.072596-1.0872-.47266-1.4941-.33144-.33705-.76482-.50586-1.1992-.50586z" fill="#ff7070"/><path d="m10.633 3-1.9668 2h4.8008l1.0352-1.0527c.2628-.2673.41824-.60049.47266-.94727h-4.3418z" fill="#ffeb70"/><path d="m8.666 5-1.9648 2h4.7988l1.9668-2z" fill="#9dff70"/><path d="m6.7012 7-1.4004 1.4238.56641.57617h3.668l1.9648-2h-4.7988z" fill="#70ffb9"/><path d="m5.8672 9 1.834 1.8652 1.834-1.8652zm-1.752.57812c-.48501-.048725-.90521.12503-1.1953.45508-.21472.24426-.35243.57797-.39844.9668h3.5625c-.10223-.1935-.22224-.37965-.38281-.54297-.55011-.55955-1.1009-.83018-1.5859-.87891z" fill="#70deff"/><path d="m1.3242 13c.18414.24071.43707.53374.83789.94141.88382.899 2.6552.67038 3.5391-.22852.20747-.21103.36064-.45476.4707-.71289h-4.8477z" fill="#ff70ac"/><path d="m2.5215 11c-.0105.088737-.021484.17696-.021484.27148 0 1.3947-2.2782.28739-1.1758 1.7285h4.8477c.27363-.64173.24047-1.3785-.087891-2h-3.5625z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.303 1c-.4344 0-.86973.16881-1.2012.50586l-1.4688 1.4941h4.3418c.082839-.52789-.072596-1.0872-.47266-1.4941-.33144-.33705-.76482-.50586-1.1992-.50586z" fill="#ff4545"/><path d="m10.633 3-1.9668 2h4.8008l1.0352-1.0527c.2628-.2673.41824-.60049.47266-.94727h-4.3418z" fill="#ffe345"/><path d="m8.666 5-1.9648 2h4.7988l1.9668-2z" fill="#80ff45"/><path d="m6.7012 7-1.4004 1.4238.56641.57617h3.668l1.9648-2h-4.7988z" fill="#45ffa2"/><path d="m5.8672 9 1.834 1.8652 1.834-1.8652zm-1.752.57812c-.48501-.048725-.90521.12503-1.1953.45508-.21472.24426-.35243.57797-.39844.9668h3.5625c-.10223-.1935-.22224-.37965-.38281-.54297-.55011-.55955-1.1009-.83018-1.5859-.87891z" fill="#45d7ff"/><path d="m1.3242 13c.18414.24071.43707.53374.83789.94141.88382.899 2.6552.67038 3.5391-.22852.20747-.21103.36064-.45476.4707-.71289h-4.8477z" fill="#ff4596"/><path d="m2.5215 11c-.0105.088737-.021484.17696-.021484.27148 0 1.3947-2.2782.28739-1.1758 1.7285h4.8477c.27363-.64173.24047-1.3785-.087891-2h-3.5625z" fill="#8045ff"/></svg>
diff --git a/editor/icons/CanvasItemShaderGraph.svg b/editor/icons/CanvasItemShaderGraph.svg
index 838ca45178..70db53a4ba 100644
--- a/editor/icons/CanvasItemShaderGraph.svg
+++ b/editor/icons/CanvasItemShaderGraph.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m8.0625 1025.9a3.375 3 0 0 0 -3.375 3 3.375 3 0 0 0 1.6875 2.5957v9.8115a3.375 3 0 0 0 -1.6875 2.5928 3.375 3 0 0 0 3.375 3 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -1.6875-2.5957v-8.7832l11.931 10.605a3.375 3 0 0 0 -.11865.7735 3.375 3 0 0 0 3.375 3 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -3.375-3 3.375 3 0 0 0 -.87341.1025l-11.928-10.602h9.8844a3.375 3 0 0 0 2.9169 1.5 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -3.375-3 3.375 3 0 0 0 -2.9202 1.5h-11.038a3.375 3 0 0 0 -2.9169-1.5z"/></clipPath><g transform="translate(0 -1036.4)"><g clip-path="url(#a)" transform="matrix(.59259 0 0 .66667 -1.7778 353.45)"><path d="m3 1025.9h27v3h-27z" fill="#ff7070"/><path d="m3 1028.9h27v3h-27z" fill="#ffeb70"/><path d="m3 1031.9h27v3h-27z" fill="#9dff70"/><path d="m3 1034.9h27v3h-27z" fill="#70ffb9"/><path d="m3 1037.9h27v3h-27z" fill="#70deff"/><path d="m3 1043.9h27v3h-27z" fill="#ff70ac"/><path d="m3 1040.9h27v3h-27z" fill="#9f70ff"/></g><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m8.0625 1025.9a3.375 3 0 0 0 -3.375 3 3.375 3 0 0 0 1.6875 2.5957v9.8115a3.375 3 0 0 0 -1.6875 2.5928 3.375 3 0 0 0 3.375 3 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -1.6875-2.5957v-8.7832l11.931 10.605a3.375 3 0 0 0 -.11865.7735 3.375 3 0 0 0 3.375 3 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -3.375-3 3.375 3 0 0 0 -.87341.1025l-11.928-10.602h9.8844a3.375 3 0 0 0 2.9169 1.5 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -3.375-3 3.375 3 0 0 0 -2.9202 1.5h-11.038a3.375 3 0 0 0 -2.9169-1.5z"/></clipPath><g transform="translate(0 -1036.4)"><g clip-path="url(#a)" transform="matrix(.59259 0 0 .66667 -1.7778 353.45)"><path d="m3 1025.9h27v3h-27z" fill="#ff4545"/><path d="m3 1028.9h27v3h-27z" fill="#ffe345"/><path d="m3 1031.9h27v3h-27z" fill="#80ff45"/><path d="m3 1034.9h27v3h-27z" fill="#45ffa2"/><path d="m3 1037.9h27v3h-27z" fill="#45d7ff"/><path d="m3 1043.9h27v3h-27z" fill="#ff4596"/><path d="m3 1040.9h27v3h-27z" fill="#8045ff"/></g><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/></g></svg>
diff --git a/editor/icons/CanvasModulate.svg b/editor/icons/CanvasModulate.svg
index 6096beb732..a96fb75643 100644
--- a/editor/icons/CanvasModulate.svg
+++ b/editor/icons/CanvasModulate.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1 1037.4v14h14v-14zm2 2h10v10h-10z" fill="#a5b7f3"/><g fill-rule="evenodd"><path d="m12 1048.4h-5l5-5z" fill="#70bfff"/><path d="m4 1040.4h5l-5 5z" fill="#ff7070"/><path d="m4 1048.4v-3l5-5h3v3l-5 5z" fill="#7aff70"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1 1037.4v14h14v-14zm2 2h10v10h-10z" fill="#8da5f3"/><g fill-rule="evenodd"><path d="m12 1048.4h-5l5-5z" fill="#70bfff"/><path d="m4 1040.4h5l-5 5z" fill="#ff4545"/><path d="m4 1048.4v-3l5-5h3v3l-5 5z" fill="#7aff70"/></g></g></svg>
diff --git a/editor/icons/CapsuleMesh.svg b/editor/icons/CapsuleMesh.svg
index f7424310aa..0bc7814bea 100644
--- a/editor/icons/CapsuleMesh.svg
+++ b/editor/icons/CapsuleMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.7527 0-5 2.2419-5 4.9903v4.0175c0 2.7484 2.2473 4.9922 5 4.9922s5-2.2438 5-4.9922v-4.0175c0-2.7484-2.2473-4.9903-5-4.9903zm-1.0059 2.1264v4.8576c-.66556-.1047-1.2973-.372-1.9941-.6618v-1.3222c0-1.3474.79838-2.4648 1.9941-2.8736zm2.0118 0c1.1957.4088 1.9941 1.5262 1.9941 2.8736v1.3451c-.68406.3054-1.3142.5732-1.9941.6663zm-4.0059 6.334c.67836.2231 1.3126.447 1.9941.5264v2.8848c-1.1957-.4092-1.9941-1.5242-1.9941-2.8716zm6 .03v.5094c0 1.3474-.79838 2.4619-1.9941 2.8711v-2.8711c.68606-.068 1.3207-.2828 1.9941-.5094z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.7527 0-5 2.2419-5 4.9903v4.0175c0 2.7484 2.2473 4.9922 5 4.9922s5-2.2438 5-4.9922v-4.0175c0-2.7484-2.2473-4.9903-5-4.9903zm-1.0059 2.1264v4.8576c-.66556-.1047-1.2973-.372-1.9941-.6618v-1.3222c0-1.3474.79838-2.4648 1.9941-2.8736zm2.0118 0c1.1957.4088 1.9941 1.5262 1.9941 2.8736v1.3451c-.68406.3054-1.3142.5732-1.9941.6663zm-4.0059 6.334c.67836.2231 1.3126.447 1.9941.5264v2.8848c-1.1957-.4092-1.9941-1.5242-1.9941-2.8716zm6 .03v.5094c0 1.3474-.79838 2.4619-1.9941 2.8711v-2.8711c.68606-.068 1.3207-.2828 1.9941-.5094z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/CenterContainer.svg b/editor/icons/CenterContainer.svg
index af1958c2d8..990f63b6c2 100644
--- a/editor/icons/CenterContainer.svg
+++ b/editor/icons/CenterContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm3 1 2 2 2-2zm-2 2v4l2-2zm8 0-2 2 2 2zm-4 4-2 2h4z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm3 1 2 2 2-2zm-2 2v4l2-2zm8 0-2 2 2 2zm-4 4-2 2h4z" fill="#8eef97"/></svg>
diff --git a/editor/icons/CharacterBody2D.svg b/editor/icons/CharacterBody2D.svg
new file mode 100644
index 0000000000..b71fda9650
--- /dev/null
+++ b/editor/icons/CharacterBody2D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6.4921 1c-.55401 0-1 .446-1 1v3c0 .554.44599 1 1 1h1v.9902a1.0001 1.0001 0 0 0 -.31641.062l-2.0508.6836-.68359-2.0508a1.0001 1.0001 0 0 0 -.99023-.6972 1.0001 1.0001 0 0 0 -.9082 1.3281l1 3a1.0001 1.0001 0 0 0 1.2656.6328l1.6836-.5605v.6113c0 .041.018715.076.023437.1152l-4.5781 3.0528a1.0001 1.0001 0 1 0 1.1094 1.664l5.0566-3.3711 1.4941 2.9864a1.0001 1.0001 0 0 0 1.2109.5019l3-1a1.0001 1.0001 0 1 0 -.63281-1.8965l-2.1777.7246-.97461-1.9511c.2759-.1777.46875-.4723.46875-.8262v-1h1.3828l.72266 1.4473a1.0001 1.0001 0 1 0 1.7891-.8946l-1-2a1.0001 1.0001 0 0 0 -.89453-.5527h-3v-1h1c.55401 0 1-.446 1-1v-3c0-.554-.44599-1-1-1zm0 2h1v2h-1z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/CharacterBody3D.svg b/editor/icons/CharacterBody3D.svg
new file mode 100644
index 0000000000..d0def4f14a
--- /dev/null
+++ b/editor/icons/CharacterBody3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1c-.55401 0-1 .44599-1 1v3c0 .55401.44599 1 1 1h1v.99023a1.0001 1.0001 0 0 0 -.31641.0625l-2.0508.68359-.68359-2.0508a1.0001 1.0001 0 0 0 -.99023-.69727 1.0001 1.0001 0 0 0 -.9082 1.3281l1 3a1.0001 1.0001 0 0 0 1.2656.63281l1.6836-.56055v.61133c0 .04088.018715.07566.023437.11523l-4.5781 3.0527a1.0001 1.0001 0 1 0 1.1094 1.6641l5.0566-3.3711 1.4941 2.9863a1.0001 1.0001 0 0 0 1.2109.50195l3-1a1.0001 1.0001 0 1 0 -.63281-1.8965l-2.1777.72461-.97461-1.9512c.2759-.17764.46875-.47227.46875-.82617v-1h1.3828l.72266 1.4473a1.0001 1.0001 0 1 0 1.7891-.89453l-1-2a1.0001 1.0001 0 0 0 -.89453-.55273h-3v-1h1c.55401 0 1-.44599 1-1v-3c0-.55401-.44599-1-1-1zm0 2h1v2h-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/CheckBox.svg b/editor/icons/CheckBox.svg
index 8707dfce0c..32eaf2d212 100644
--- a/editor/icons/CheckBox.svg
+++ b/editor/icons/CheckBox.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2c-1.1046 0-2 .89543-2 2v9c0 1.1046.89543 2 2 2h9c1.1046 0 2-.89543 2-2v-4.9277l-2 2v2.9277h-9v-9h6.5859l2-2zm9.3633 2.0508-4.9492 4.9492-1.4141-1.4141-1.4141 1.4141 2.8281 2.8281 6.3633-6.3633z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2c-1.1046 0-2 .89543-2 2v9c0 1.1046.89543 2 2 2h9c1.1046 0 2-.89543 2-2v-4.9277l-2 2v2.9277h-9v-9h6.5859l2-2zm9.3633 2.0508-4.9492 4.9492-1.4141-1.4141-1.4141 1.4141 2.8281 2.8281 6.3633-6.3633z" fill="#8eef97"/></svg>
diff --git a/editor/icons/CheckButton.svg b/editor/icons/CheckButton.svg
index 4b8106ecc0..91367e2a2a 100644
--- a/editor/icons/CheckButton.svg
+++ b/editor/icons/CheckButton.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 4a4 4 0 0 0 -4 4 4 4 0 0 0 4 4h6a4 4 0 0 0 4-4 4 4 0 0 0 -4-4zm0 2h2.541a4 4 0 0 0 -.54102 2 4 4 0 0 0 .54102 2h-2.541a2 2 0 0 1 -2-2 2 2 0 0 1 2-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 4a4 4 0 0 0 -4 4 4 4 0 0 0 4 4h6a4 4 0 0 0 4-4 4 4 0 0 0 -4-4zm0 2h2.541a4 4 0 0 0 -.54102 2 4 4 0 0 0 .54102 2h-2.541a2 2 0 0 1 -2-2 2 2 0 0 1 2-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/ClippedCamera3D.svg b/editor/icons/ClippedCamera3D.svg
index a66f7844a9..44d656e8ba 100644
--- a/editor/icons/ClippedCamera3D.svg
+++ b/editor/icons/ClippedCamera3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6.5 12v4h3v-1h-2v-3zm-1 0h-2c-.5 0-1 .5-1 1v2c-.01829.53653.5 1 1 1h2v-1h-2v-2h2zm4-12c-1.5691.0017903-2.8718 1.2125-2.9883 2.7773-.55103-.49952-1.268-.77655-2.0117-.77734-1.6569 0-3 1.3431-3 3 .00179 1.2698.80282 2.4009 2 2.8242v2.1758c0 .554.44599 1 1 1h6c.55401 0 1-.446 1-1v-1l3 2v-6l-3 2v-1.7695c.63486-.56783.99842-1.3788 1-2.2305 0-1.6569-1.3431-3-3-3zm1 12v4h1v-1h1c.55228 0 1-.44772 1-1v-1c0-.55228-.44775-.99374-1-1h-1zm1 1h1v1h-1z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6.5 12v4h3v-1h-2v-3zm-1 0h-2c-.5 0-1 .5-1 1v2c-.01829.53653.5 1 1 1h2v-1h-2v-2h2zm4-12c-1.5691.0017903-2.8718 1.2125-2.9883 2.7773-.55103-.49952-1.268-.77655-2.0117-.77734-1.6569 0-3 1.3431-3 3 .00179 1.2698.80282 2.4009 2 2.8242v2.1758c0 .554.44599 1 1 1h6c.55401 0 1-.446 1-1v-1l3 2v-6l-3 2v-1.7695c.63486-.56783.99842-1.3788 1-2.2305 0-1.6569-1.3431-3-3-3zm1 12v4h1v-1h1c.55228 0 1-.44772 1-1v-1c0-.55228-.44775-.99374-1-1h-1zm1 1h1v1h-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/CodeEdit.svg b/editor/icons/CodeEdit.svg
index 0750b072e7..7f08340ffb 100644
--- a/editor/icons/CodeEdit.svg
+++ b/editor/icons/CodeEdit.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m29 1042.4h1v1h-1z" fill="#fefeff"/><path d="m3 1c-1.1046 0-2 .8954-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.8954 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm2 1-1 1 1 1-1 1 1 1 2-2zm2 3v1h2v-1z" fill="#a5efac" transform="translate(0 1036.4)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m29 1042.4h1v1h-1z" fill="#fefeff"/><path d="m3 1c-1.1046 0-2 .8954-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.8954 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm2 1-1 1 1 1-1 1 1 1 2-2zm2 3v1h2v-1z" fill="#8eef97" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/CollisionPolygon2D.svg b/editor/icons/CollisionPolygon2D.svg
index 524efd1e65..a882943847 100644
--- a/editor/icons/CollisionPolygon2D.svg
+++ b/editor/icons/CollisionPolygon2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="none" stroke="#a5b7f3" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="none" stroke="#8da5f3" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/CollisionPolygon3D.svg b/editor/icons/CollisionPolygon3D.svg
index 9b8b13c514..57531fa9f4 100644
--- a/editor/icons/CollisionPolygon3D.svg
+++ b/editor/icons/CollisionPolygon3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="none" stroke="#fc9c9c" stroke-linejoin="round" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/CollisionShape2D.svg b/editor/icons/CollisionShape2D.svg
index d366ddb630..0acad74379 100644
--- a/editor/icons/CollisionShape2D.svg
+++ b/editor/icons/CollisionShape2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12z" fill="none" stroke="#a5b7f3" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12z" fill="none" stroke="#8da5f3" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/CollisionShape3D.svg b/editor/icons/CollisionShape3D.svg
index cf5925ce79..7a8bbf8050 100644
--- a/editor/icons/CollisionShape3D.svg
+++ b/editor/icons/CollisionShape3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1050.4-6-3v-6l6-3 6 3v6z" fill="none" stroke="#fc9c9c" stroke-linejoin="round" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.399988)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1050.4-6-3v-6l6-3 6 3v6z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.399988)"/></svg>
diff --git a/editor/icons/Color.svg b/editor/icons/Color.svg
index 91bc0d1d2d..5c6fca1876 100644
--- a/editor/icons/Color.svg
+++ b/editor/icons/Color.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2z" fill="#ff8484"/><path d="m14 4a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1h1v-2z" fill="#84c2ff"/><path d="m6 2v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-5z" fill="#84ffb1"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2z" fill="#ff5f5f"/><path d="m14 4a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1h1v-2z" fill="#5fb2ff"/><path d="m6 2v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-5z" fill="#5fff97"/></svg>
diff --git a/editor/icons/ColorPicker.svg b/editor/icons/ColorPicker.svg
index c4f48cd347..ce1f4fef96 100644
--- a/editor/icons/ColorPicker.svg
+++ b/editor/icons/ColorPicker.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-1.108 0-2 .892-2 2v2h-1v2h1v5a2 2 0 0 0 1 1.7285v1.2715h2v-1.2695a2 2 0 0 0 1-1.7305v-5h1v-2h-1v-2c0-1.108-.892-2-2-2zm-1 6h2v5a1 1 0 0 1 -1 1 1 1 0 0 1 -1-1z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-1.108 0-2 .892-2 2v2h-1v2h1v5a2 2 0 0 0 1 1.7285v1.2715h2v-1.2695a2 2 0 0 0 1-1.7305v-5h1v-2h-1v-2c0-1.108-.892-2-2-2zm-1 6h2v5a1 1 0 0 1 -1 1 1 1 0 0 1 -1-1z" fill="#8eef97"/></svg>
diff --git a/editor/icons/ColorPickerButton.svg b/editor/icons/ColorPickerButton.svg
index fa2a615428..ced130b1ce 100644
--- a/editor/icons/ColorPickerButton.svg
+++ b/editor/icons/ColorPickerButton.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1c-1.108 0-2 .892-2 2v2h-1v2h1v5a2 2 0 0 0 1 1.7285v1.2715h2v-1.2695a2 2 0 0 0 1-1.7305v-5h1v-2h-1v-2c0-1.108-.892-2-2-2zm-9 1v3.1328l-1.4453-.96484-1.1094 1.6641 3 2c.3359.2239.77347.2239 1.1094 0l3-2-1.1094-1.6641-1.4453.96484v-3.1328zm8 5h2v5a1 1 0 0 1 -1 1 1 1 0 0 1 -1-1zm-8.5 3c-.831 0-1.5.669-1.5 1.5v.5 1h-1v2h8v-2h-1v-1-.5c0-.831-.669-1.5-1.5-1.5z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1c-1.108 0-2 .892-2 2v2h-1v2h1v5a2 2 0 0 0 1 1.7285v1.2715h2v-1.2695a2 2 0 0 0 1-1.7305v-5h1v-2h-1v-2c0-1.108-.892-2-2-2zm-9 1v3.1328l-1.4453-.96484-1.1094 1.6641 3 2c.3359.2239.77347.2239 1.1094 0l3-2-1.1094-1.6641-1.4453.96484v-3.1328zm8 5h2v5a1 1 0 0 1 -1 1 1 1 0 0 1 -1-1zm-8.5 3c-.831 0-1.5.669-1.5 1.5v.5 1h-1v2h8v-2h-1v-1-.5c0-.831-.669-1.5-1.5-1.5z" fill="#8eef97"/></svg>
diff --git a/editor/icons/ColorRect.svg b/editor/icons/ColorRect.svg
index 306401191a..f08b17ed1f 100644
--- a/editor/icons/ColorRect.svg
+++ b/editor/icons/ColorRect.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1 1v14h14v-14zm2 2h10v10h-10z" fill="#a5efac" transform="translate(0 1036.4)"/><g fill-rule="evenodd"><path d="m12 1048.4h-4.8l4.8-4.8z" fill="#70bfff"/><path d="m4 1040.4h4.8l-4.8 4.8z" fill="#ff7070"/><path d="m4 1048.4v-3.2l4.8-4.8h3.2v3.2l-4.8 4.8z" fill="#7aff70"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1 1v14h14v-14zm2 2h10v10h-10z" fill="#8eef97" transform="translate(0 1036.4)"/><g fill-rule="evenodd"><path d="m12 1048.4h-4.8l4.8-4.8z" fill="#70bfff"/><path d="m4 1040.4h4.8l-4.8 4.8z" fill="#ff4545"/><path d="m4 1048.4v-3.2l4.8-4.8h3.2v3.2l-4.8 4.8z" fill="#7aff70"/></g></g></svg>
diff --git a/editor/icons/ConeTwistJoint3D.svg b/editor/icons/ConeTwistJoint3D.svg
index 9eff38d0dc..300cc7ecc1 100644
--- a/editor/icons/ConeTwistJoint3D.svg
+++ b/editor/icons/ConeTwistJoint3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9824 1a1.0001 1.0001 0 0 0 -.81445.44531l-4.7012 7.0527c-.80117.58197-1.3801 1.3563-1.4492 2.3145a1.0001 1.0001 0 0 0 -.017578.1875c0 .21449.033976.41628.082031.61328.0071983.028314.015306.055972.023438.083985.053631.19149.1274.37452.2207.54883.19678.36764.47105.69651.80273.98633.007988.007025.013442.016473.021484.023437.016953.014679.03747.026532.054688.041016.10299.086112.21259.16531.32422.24414.23883.16992.49083.33075.76953.4707.0025295.00127.0052799.002638.0078125.003906.001313.000658.0025928.001296.0039063.001953.0085785.00429.018732.007456.027344.011719.26499.13103.55174.24596.84961.35156.10487.037634.21202.071147.32031.10547.072945.022902.1402.050715.21484.072266.16777.04843.34161.086385.51367.12695.093562.021905.18185.048745.27734.068359.010733.002205.022447.003684.033203.00586.34623.071177.69974.12196 1.0566.16211.057889.006228.11544.01213.17383.017578.81052.079498 1.6348.079498 2.4453 0 .058387-.005448.11594-.01135.17383-.017578.3569-.040146.71041-.090932 1.0566-.16211.010948-.002251.022269-.003578.033203-.00586.095491-.019614.18378-.046454.27734-.068359.17206-.040568.3459-.078523.51367-.12695.074642-.021551.1419-.049364.21484-.072266.10829-.034322.21544-.067835.32031-.10547.29787-.1056.58462-.22053.84961-.35156.009951-.00492.021348-.008715.03125-.013672.002626-.001315.005189-.002588.007813-.003906.2787-.13995.5307-.30078.76953-.4707.11163-.07883.22123-.15803.32422-.24414.017218-.014484.037734-.026337.054687-.041016.008042-.006964.013497-.016412.021485-.023437.33169-.28982.60596-.61869.80273-.98633.093299-.17431.16707-.35733.2207-.54883.008132-.028013.016239-.055671.023438-.083985.048055-.197.082031-.39879.082031-.61328a1.0001 1.0001 0 0 0 -.017578-.18164 1.0001 1.0001 0 0 0 -.001953-.017578c-.073081-.95265-.64941-1.7232-1.4473-2.3027l-4.7012-7.0527a1.0001 1.0001 0 0 0 -.84961-.44531zm-.98242 4.3027v1.7461c-.43911.033461-.86366.087835-1.2734.16406l1.2734-1.9102zm2 0 1.2734 1.9102c-.40978-.076228-.83432-.1306-1.2734-.16406v-1.7461zm-2 3.748v1.9492a1.0001 1.0001 0 1 0 2 0v-1.9492c1.1126.10487 2.0951.37277 2.7949.72266.12146.060728.20622.12218.30664.18359l.80078 1.2012c-.032965.14677-.089654.30658-.30469.51758-.051464.049149-.10034.098137-.16406.14844-.045193.035312-.091373.070148-.14258.10547-.11245.07827-.24511.15838-.39062.23633-.075428.040204-.1553.078371-.23828.11719-.16195.075482-.33452.14662-.52148.21289-.070588.025324-.14454.048409-.21875.072265-.23425.074473-.48077.14392-.74414.20117-.021343.004579-.041038.011189-.0625.015625-.2559.05368-.53101.090517-.80859.125-.856.10229-1.7573.10229-2.6133 0-.27759-.034483-.5527-.07132-.80859-.125-.021462-.004436-.041156-.011046-.0625-.015625-.26337-.057254-.50989-.1267-.74414-.20117-.074211-.023856-.14816-.046941-.21875-.072265-.18697-.066266-.35954-.13741-.52148-.21289-.082979-.038816-.16285-.076983-.23828-.11719-.14552-.077951-.27818-.15806-.39062-.23633-.051205-.035321-.097386-.070157-.14258-.10547-.06372-.050301-.1126-.099289-.16406-.14844-.21503-.21099-.27173-.37081-.30469-.51758l.80078-1.2012c.10043-.061415.18518-.12287.30664-.18359.69978-.34989 1.6823-.61778 2.7949-.72266z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9824 1a1.0001 1.0001 0 0 0 -.81445.44531l-4.7012 7.0527c-.80117.58197-1.3801 1.3563-1.4492 2.3145a1.0001 1.0001 0 0 0 -.017578.1875c0 .21449.033976.41628.082031.61328.0071983.028314.015306.055972.023438.083985.053631.19149.1274.37452.2207.54883.19678.36764.47105.69651.80273.98633.007988.007025.013442.016473.021484.023437.016953.014679.03747.026532.054688.041016.10299.086112.21259.16531.32422.24414.23883.16992.49083.33075.76953.4707.0025295.00127.0052799.002638.0078125.003906.001313.000658.0025928.001296.0039063.001953.0085785.00429.018732.007456.027344.011719.26499.13103.55174.24596.84961.35156.10487.037634.21202.071147.32031.10547.072945.022902.1402.050715.21484.072266.16777.04843.34161.086385.51367.12695.093562.021905.18185.048745.27734.068359.010733.002205.022447.003684.033203.00586.34623.071177.69974.12196 1.0566.16211.057889.006228.11544.01213.17383.017578.81052.079498 1.6348.079498 2.4453 0 .058387-.005448.11594-.01135.17383-.017578.3569-.040146.71041-.090932 1.0566-.16211.010948-.002251.022269-.003578.033203-.00586.095491-.019614.18378-.046454.27734-.068359.17206-.040568.3459-.078523.51367-.12695.074642-.021551.1419-.049364.21484-.072266.10829-.034322.21544-.067835.32031-.10547.29787-.1056.58462-.22053.84961-.35156.009951-.00492.021348-.008715.03125-.013672.002626-.001315.005189-.002588.007813-.003906.2787-.13995.5307-.30078.76953-.4707.11163-.07883.22123-.15803.32422-.24414.017218-.014484.037734-.026337.054687-.041016.008042-.006964.013497-.016412.021485-.023437.33169-.28982.60596-.61869.80273-.98633.093299-.17431.16707-.35733.2207-.54883.008132-.028013.016239-.055671.023438-.083985.048055-.197.082031-.39879.082031-.61328a1.0001 1.0001 0 0 0 -.017578-.18164 1.0001 1.0001 0 0 0 -.001953-.017578c-.073081-.95265-.64941-1.7232-1.4473-2.3027l-4.7012-7.0527a1.0001 1.0001 0 0 0 -.84961-.44531zm-.98242 4.3027v1.7461c-.43911.033461-.86366.087835-1.2734.16406l1.2734-1.9102zm2 0 1.2734 1.9102c-.40978-.076228-.83432-.1306-1.2734-.16406v-1.7461zm-2 3.748v1.9492a1.0001 1.0001 0 1 0 2 0v-1.9492c1.1126.10487 2.0951.37277 2.7949.72266.12146.060728.20622.12218.30664.18359l.80078 1.2012c-.032965.14677-.089654.30658-.30469.51758-.051464.049149-.10034.098137-.16406.14844-.045193.035312-.091373.070148-.14258.10547-.11245.07827-.24511.15838-.39062.23633-.075428.040204-.1553.078371-.23828.11719-.16195.075482-.33452.14662-.52148.21289-.070588.025324-.14454.048409-.21875.072265-.23425.074473-.48077.14392-.74414.20117-.021343.004579-.041038.011189-.0625.015625-.2559.05368-.53101.090517-.80859.125-.856.10229-1.7573.10229-2.6133 0-.27759-.034483-.5527-.07132-.80859-.125-.021462-.004436-.041156-.011046-.0625-.015625-.26337-.057254-.50989-.1267-.74414-.20117-.074211-.023856-.14816-.046941-.21875-.072265-.18697-.066266-.35954-.13741-.52148-.21289-.082979-.038816-.16285-.076983-.23828-.11719-.14552-.077951-.27818-.15806-.39062-.23633-.051205-.035321-.097386-.070157-.14258-.10547-.06372-.050301-.1126-.099289-.16406-.14844-.21503-.21099-.27173-.37081-.30469-.51758l.80078-1.2012c.10043-.061415.18518-.12287.30664-.18359.69978-.34989 1.6823-.61778 2.7949-.72266z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/Container.svg b/editor/icons/Container.svg
index a7be880268..efe1966ad4 100644
--- a/editor/icons/Container.svg
+++ b/editor/icons/Container.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2h2zm2 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2c0-1.1046-.89543-2-2-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4c0 1.1046.89543 2 2 2v-2zm4 0v2h2v-2zm4 0v2h2v-2zm4 0v2c1.1046 0 2-.89543 2-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2h2zm2 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2c0-1.1046-.89543-2-2-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4c0 1.1046.89543 2 2 2v-2zm4 0v2h2v-2zm4 0v2h2v-2zm4 0v2c1.1046 0 2-.89543 2-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/Control.svg b/editor/icons/Control.svg
index 0ec9c4c6fe..3f3530de61 100644
--- a/editor/icons/Control.svg
+++ b/editor/icons/Control.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#8eef97"/></svg>
diff --git a/editor/icons/ControlLayout.svg b/editor/icons/ControlLayout.svg
index c4aa64113d..11dd2554be 100644
--- a/editor/icons/ControlLayout.svg
+++ b/editor/icons/ControlLayout.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h14v-14zm2 2h3v3h-3zm5 0h5v3h-5zm-5 5h3v5h-3zm5 0h5v5h-5z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h14v-14zm2 2h3v3h-3zm5 0h5v3h-5zm-5 5h3v5h-3zm5 0h5v5h-5z" fill="#8eef97"/></svg>
diff --git a/editor/icons/CreateNewSceneFrom.svg b/editor/icons/CreateNewSceneFrom.svg
index 094a0aae39..3ec6140515 100644
--- a/editor/icons/CreateNewSceneFrom.svg
+++ b/editor/icons/CreateNewSceneFrom.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m14.564 2-2.2441.32812.81836 1.9004 1.7148-.25-.28906-1.9785zm-4.2227.61523-1.9785.28906.81836 1.9023 1.9785-.28906zm-3.959.57812-1.9785.28906.81836 1.9023 1.9785-.28906zm-3.957.57812-1.7148.25.28906 1.9785 2.2441-.32812-.81836-1.9004zm-1.4258 3.2285v6c0 1.1046.89543 2 2 2h7v-1h-2v-4h2v-2h4v2h1v-3z" fill="#e0e0e0" transform="translate(0 1036.4)"/><circle cx="-14" cy="1047.4" fill="#e0e0e0" r="0"/><path d="m13 1049.4h2v-2h-2v-2h-2v2h-2v2h2v2h2z" fill="#84ffb1" fill-rule="evenodd"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m14.564 2-2.2441.32812.81836 1.9004 1.7148-.25-.28906-1.9785zm-4.2227.61523-1.9785.28906.81836 1.9023 1.9785-.28906zm-3.959.57812-1.9785.28906.81836 1.9023 1.9785-.28906zm-3.957.57812-1.7148.25.28906 1.9785 2.2441-.32812-.81836-1.9004zm-1.4258 3.2285v6c0 1.1046.89543 2 2 2h7v-1h-2v-4h2v-2h4v2h1v-3z" fill="#e0e0e0" transform="translate(0 1036.4)"/><circle cx="-14" cy="1047.4" fill="#e0e0e0" r="0"/><path d="m13 1049.4h2v-2h-2v-2h-2v2h-2v2h2v2h2z" fill="#5fff97" fill-rule="evenodd"/></g></svg>
diff --git a/editor/icons/Cubemap.svg b/editor/icons/Cubemap.svg
index b3ec2bd3e7..81965f7a09 100644
--- a/editor/icons/Cubemap.svg
+++ b/editor/icons/Cubemap.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 6v4h4v-4zm8 0v4h4v-4z" fill="#84ffb1"/><path d="m4 6v4h4v-4zm8 0v4h4v-4z" fill="#ff8484"/><path d="m4 2v4h4v-4zm0 8v4h4v-4z" fill="#84c2ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 6v4h4v-4zm8 0v4h4v-4z" fill="#5fff97"/><path d="m4 6v4h4v-4zm8 0v4h4v-4z" fill="#ff5f5f"/><path d="m4 2v4h4v-4zm0 8v4h4v-4z" fill="#5fb2ff"/></svg>
diff --git a/editor/icons/CubemapArray.svg b/editor/icons/CubemapArray.svg
index c9d722dc52..847fc7f70a 100644
--- a/editor/icons/CubemapArray.svg
+++ b/editor/icons/CubemapArray.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 6v4h2v-4zm6 0v4h4v-4z" fill="#84ffb1"/><path d="m4 6v4h4v-4zm8 0v4h2v-4z" fill="#ff8484"/><path d="m4 2v4h4v-4zm0 8v4h4v-4z" fill="#84c2ff"/><path d="m-.00000002 2v12h4.00000002v-2h-2v-8h2v-2h-2zm12.00000002 0v2h2.000001v8h-2.000001v2h4.000001v-12h-2z" fill="#e0e0e0"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 6v4h2v-4zm6 0v4h4v-4z" fill="#5fff97"/><path d="m4 6v4h4v-4zm8 0v4h2v-4z" fill="#ff5f5f"/><path d="m4 2v4h4v-4zm0 8v4h4v-4z" fill="#5fb2ff"/><path d="m-.00000002 2v12h4.00000002v-2h-2v-8h2v-2h-2zm12.00000002 0v2h2.000001v8h-2.000001v2h4.000001v-12h-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/CurveClose.svg b/editor/icons/CurveClose.svg
index 26e30cdb1c..5cb8ab890e 100644
--- a/editor/icons/CurveClose.svg
+++ b/editor/icons/CurveClose.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><g transform="translate(0 1036.4)"><path d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm8 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/><path d="m10 6v2h2v-2zm0 2h-2v2h2zm-2 2h-2v2h2z" fill="#84c2ff"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><g transform="translate(0 1036.4)"><path d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm8 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/><path d="m10 6v2h2v-2zm0 2h-2v2h2zm-2 2h-2v2h2z" fill="#5fb2ff"/></g></g></svg>
diff --git a/editor/icons/CurveCreate.svg b/editor/icons/CurveCreate.svg
index 962abd0b3f..1e80817a34 100644
--- a/editor/icons/CurveCreate.svg
+++ b/editor/icons/CurveCreate.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><g transform="translate(0 1036.4)"><path d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm6 5v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#84ffb1"/><path d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><g transform="translate(0 1036.4)"><path d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm6 5v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#5fff97"/><path d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/></g></g></svg>
diff --git a/editor/icons/CurveCurve.svg b/editor/icons/CurveCurve.svg
index 35770543af..e43e7ccd8a 100644
--- a/editor/icons/CurveCurve.svg
+++ b/editor/icons/CurveCurve.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><g transform="translate(0 1036.4)"><path d="m8.4688.4707-2.6875 2.6875h-.0019531a2 2 0 0 0 -.7793-.1582 2 2 0 0 0 -2 2 2 2 0 0 0 .16016.7793l-2.6914 2.6914 1.0625 1.0605 2.6895-2.6895a2 2 0 0 0 .7793.1582 2 2 0 0 0 2-2 2 2 0 0 0 -.16016-.77734l2.6914-2.6914-1.0625-1.0605z" fill="#84c2ff"/><path d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><g transform="translate(0 1036.4)"><path d="m8.4688.4707-2.6875 2.6875h-.0019531a2 2 0 0 0 -.7793-.1582 2 2 0 0 0 -2 2 2 2 0 0 0 .16016.7793l-2.6914 2.6914 1.0625 1.0605 2.6895-2.6895a2 2 0 0 0 .7793.1582 2 2 0 0 0 2-2 2 2 0 0 0 -.16016-.77734l2.6914-2.6914-1.0625-1.0605z" fill="#5fb2ff"/><path d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/></g></g></svg>
diff --git a/editor/icons/CurveDelete.svg b/editor/icons/CurveDelete.svg
index 5bce6d0c1c..cf15d75bc1 100644
--- a/editor/icons/CurveDelete.svg
+++ b/editor/icons/CurveDelete.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><path d="m5 1039.4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm4.8789 5.4648-1.4141 1.4141 2.1211 2.1211-2.1211 2.1211 1.4141 1.4141 2.1211-2.1211 2.1211 2.1211 1.4141-1.4141-2.1211-2.1211 2.1211-2.1211-1.4141-1.4141-2.1211 2.1211z" fill="#ff8484"/><path d="m13 1039.4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><path d="m5 1039.4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm4.8789 5.4648-1.4141 1.4141 2.1211 2.1211-2.1211 2.1211 1.4141 1.4141 2.1211-2.1211 2.1211 2.1211 1.4141-1.4141-2.1211-2.1211 2.1211-2.1211-1.4141-1.4141-2.1211 2.1211z" fill="#ff5f5f"/><path d="m13 1039.4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/></g></svg>
diff --git a/editor/icons/CurveEdit.svg b/editor/icons/CurveEdit.svg
index 84b56fbccb..57e365f3cd 100644
--- a/editor/icons/CurveEdit.svg
+++ b/editor/icons/CurveEdit.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><g transform="translate(0 1036.4)"><path d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm3 5 3.291 8 .94726-2.8203 1.8828 1.8828.94336-.94141-1.8848-1.8828 2.8203-.94726-8-3.291z" fill="#84c2ff"/><path d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><g transform="translate(0 1036.4)"><path d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm3 5 3.291 8 .94726-2.8203 1.8828 1.8828.94336-.94141-1.8848-1.8828 2.8203-.94726-8-3.291z" fill="#5fb2ff"/><path d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#f5f5f5"/></g></g></svg>
diff --git a/editor/icons/CylinderMesh.svg b/editor/icons/CylinderMesh.svg
index 85483aeeca..f6315c253c 100644
--- a/editor/icons/CylinderMesh.svg
+++ b/editor/icons/CylinderMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.5.9375c-1.6377 0-3.12.2123-4.2737.5969-.57682.1923-1.0754.4237-1.4905.7508-.41505.3271-.79834.8259-.79834 1.4648v7.5c0 .6389.38329 1.1396.79834 1.4667s.91366.5585 1.4905.7507c1.1536.3846 2.6359.5951 4.2737.5951s3.12-.2105 4.2737-.5951c.57682-.1922 1.0754-.4236 1.4905-.7507.41505-.3271.79834-.8278.79834-1.4667v-7.5c0-.6389-.38329-1.1377-.79834-1.4648s-.91366-.5585-1.4905-.7508c-1.1536-.3846-2.6359-.5969-4.2737-.5969zm0 1.875c1.4689 0 2.8.2076 3.6823.5017.4347.1449.7513.3163.9082.4376-.15705.1212-.47387.2911-.9082.4358-.88221.2941-2.2134.4999-3.6823.4999s-2.8-.2058-3.6823-.4999c-.43433-.1447-.75115-.3146-.9082-.4358.15691-.1213.47351-.2927.9082-.4376.88221-.2941 2.2134-.5017 3.6823-.5017zm-4.6875 2.9883c.13762.055.26578.1173.41382.1666 1.1536.3846 2.6359.5951 4.2737.5951s3.12-.2105 4.2737-.5951c.14804-.049.2762-.1112.41382-.1666v5.4492c-.15705.1212-.57092.2929-1.0052.4376-.88221.2941-2.2134.4999-3.6823.4999s-2.8-.2058-3.6823-.4999c-.43433-.1447-.8482-.3164-1.0052-.4376z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.5.9375c-1.6377 0-3.12.2123-4.2737.5969-.57682.1923-1.0754.4237-1.4905.7508-.41505.3271-.79834.8259-.79834 1.4648v7.5c0 .6389.38329 1.1396.79834 1.4667s.91366.5585 1.4905.7507c1.1536.3846 2.6359.5951 4.2737.5951s3.12-.2105 4.2737-.5951c.57682-.1922 1.0754-.4236 1.4905-.7507.41505-.3271.79834-.8278.79834-1.4667v-7.5c0-.6389-.38329-1.1377-.79834-1.4648s-.91366-.5585-1.4905-.7508c-1.1536-.3846-2.6359-.5969-4.2737-.5969zm0 1.875c1.4689 0 2.8.2076 3.6823.5017.4347.1449.7513.3163.9082.4376-.15705.1212-.47387.2911-.9082.4358-.88221.2941-2.2134.4999-3.6823.4999s-2.8-.2058-3.6823-.4999c-.43433-.1447-.75115-.3146-.9082-.4358.15691-.1213.47351-.2927.9082-.4376.88221-.2941 2.2134-.5017 3.6823-.5017zm-4.6875 2.9883c.13762.055.26578.1173.41382.1666 1.1536.3846 2.6359.5951 4.2737.5951s3.12-.2105 4.2737-.5951c.14804-.049.2762-.1112.41382-.1666v5.4492c-.15705.1212-.57092.2929-1.0052.4376-.88221.2941-2.2134.4999-3.6823.4999s-2.8-.2058-3.6823-.4999c-.43433-.1447-.8482-.3164-1.0052-.4376z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/DampedSpringJoint2D.svg b/editor/icons/DampedSpringJoint2D.svg
index 02a7033106..99e1a1f1e1 100644
--- a/editor/icons/DampedSpringJoint2D.svg
+++ b/editor/icons/DampedSpringJoint2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".98824"><path d="m4 3v2l8 3v-2zm0 5v2l8 3v-2z" fill="#708cea"/><path d="m4 3v2l8-2v-2zm0 5v2l8-2v-2zm0 5v2l8-2v-2z" fill="#a5b7f3"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".98824"><path d="m4 3v2l8 3v-2zm0 5v2l8 3v-2z" fill="#4b70ea"/><path d="m4 3v2l8-2v-2zm0 5v2l8-2v-2zm0 5v2l8-2v-2z" fill="#8da5f3"/></g></svg>
diff --git a/editor/icons/DebugContinue.svg b/editor/icons/DebugContinue.svg
index cf9e0724c2..8625626ab2 100644
--- a/editor/icons/DebugContinue.svg
+++ b/editor/icons/DebugContinue.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m10 4v3h-5v2h5v3l2.5-2 2.5-2-2.5-2z" fill="#ff8484" transform="translate(0 1036.4)"/><circle cx="4" cy="1044.4" fill="#e0e0e0" r="3"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m10 4v3h-5v2h5v3l2.5-2 2.5-2-2.5-2z" fill="#ff5f5f" transform="translate(0 1036.4)"/><circle cx="4" cy="1044.4" fill="#e0e0e0" r="3"/></g></svg>
diff --git a/editor/icons/DebugNext.svg b/editor/icons/DebugNext.svg
index d510aff828..50532d6e77 100644
--- a/editor/icons/DebugNext.svg
+++ b/editor/icons/DebugNext.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1v10h-2l1.5 2 1.5 2 1.5-2 1.5-2h-2v-10z" fill="#ff8484"/><path d="m7 1v2h8v-2zm2 4v2h6v-2zm0 4v2h6v-2zm-2 4v2h8v-2z" fill="#e0e0e0"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1v10h-2l1.5 2 1.5 2 1.5-2 1.5-2h-2v-10z" fill="#ff5f5f"/><path d="m7 1v2h8v-2zm2 4v2h6v-2zm0 4v2h6v-2zm-2 4v2h8v-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/DebugStep.svg b/editor/icons/DebugStep.svg
index b26e9b7b25..f8d57ef693 100644
--- a/editor/icons/DebugStep.svg
+++ b/editor/icons/DebugStep.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v8 2h2 1v2l2-1.5 2-1.5-2-1.5-2-1.5v2h-1v-8z" fill="#ff8484"/><path d="m7 1v2h8v-2zm2 4v2h6v-2zm0 4v2h6v-2zm-2 4v2h8v-2z" fill="#e0e0e0"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v8 2h2 1v2l2-1.5 2-1.5-2-1.5-2-1.5v2h-1v-8z" fill="#ff5f5f"/><path d="m7 1v2h8v-2zm2 4v2h6v-2zm0 4v2h6v-2zm-2 4v2h8v-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/Decal.svg b/editor/icons/Decal.svg
index 2a61ceb0a0..8c33f44360 100644
--- a/editor/icons/Decal.svg
+++ b/editor/icons/Decal.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2c-3.3137085 0-6 2.6862915-6 6 0 2.220299 1.2092804 4.153789 3.0019531 5.191406l8.9082029-6.1894529c-.476307-2.8374399-2.937354-5.0019531-5.910156-5.0019531z" fill="#fc9c9c"/><path d="m5.001954 13.191406 8.908202-6.1894529c-.882819-.510985-1.904638-.808594-2.998046-.808594-3.3137079 0-6 2.686292-6 5.9999999 0 .340906.03522.672663.08984.998047z" fill="#ff5d5d"/><path d="m13.910156 7.0019531-8.908202 6.1894529c.882819.510985 1.904638.808594 2.998046.808594 3.313708 0 6-2.686292 6-5.9999999 0-.340906-.03522-.672663-.08984-.998047z" fill="#fc9c9c" fill-opacity=".392157"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2c-3.3137085 0-6 2.6862915-6 6 0 2.220299 1.2092804 4.153789 3.0019531 5.191406l8.9082029-6.1894529c-.476307-2.8374399-2.937354-5.0019531-5.910156-5.0019531z" fill="#fc7f7f"/><path d="m5.001954 13.191406 8.908202-6.1894529c-.882819-.510985-1.904638-.808594-2.998046-.808594-3.3137079 0-6 2.686292-6 5.9999999 0 .340906.03522.672663.08984.998047z" fill="#ff5d5d"/><path d="m13.910156 7.0019531-8.908202 6.1894529c.882819.510985 1.904638.808594 2.998046.808594 3.313708 0 6-2.686292 6-5.9999999 0-.340906-.03522-.672663-.08984-.998047z" fill="#fc7f7f" fill-opacity=".392157"/></svg>
diff --git a/editor/icons/Dictionary.svg b/editor/icons/Dictionary.svg
index c835398836..0284e847d9 100644
--- a/editor/icons/Dictionary.svg
+++ b/editor/icons/Dictionary.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2v2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-8zm3 0v2h2v-2zm7 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2zm-2 2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2zm-3 3v-1h-2v4h2zm-5-1v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#77edb1"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2v2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-8zm3 0v2h2v-2zm7 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2zm-2 2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2zm-3 3v-1h-2v4h2zm-5-1v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#54ed9e"/></svg>
diff --git a/editor/icons/DirectionalLight3D.svg b/editor/icons/DirectionalLight3D.svg
index ff033636be..ef25fd473a 100644
--- a/editor/icons/DirectionalLight3D.svg
+++ b/editor/icons/DirectionalLight3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3h2v-3zm-2.5352 2.0508-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-3.5352 1.9492c-1.6569 0-3 1.3432-3 3s1.3431 3 3 3 3-1.3432 3-3-1.3431-3-3-3zm-7 2v2h3v-2zm11 0v2h3v-2zm-7.5352 3.1211-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-4.5352 1.8789v3h2v-3z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3h2v-3zm-2.5352 2.0508-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-3.5352 1.9492c-1.6569 0-3 1.3432-3 3s1.3431 3 3 3 3-1.3432 3-3-1.3431-3-3-3zm-7 2v2h3v-2zm11 0v2h3v-2zm-7.5352 3.1211-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-4.5352 1.8789v3h2v-3z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/EditBezier.svg b/editor/icons/EditBezier.svg
index 3feff790dc..82667d0bed 100644
--- a/editor/icons/EditBezier.svg
+++ b/editor/icons/EditBezier.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1.4758015 1050.3064c11.6492855.7191 3.1098343-11.4976 12.2331255-11.3475" fill="none" stroke="#84c2ff" stroke-miterlimit="4.9" stroke-width="2.2"/><g fill="#e0e0e0"><circle cx="13.470984" cy="1038.7133" r="1.823002"/><circle cx="2.444912" cy="1050.1708" r="1.823002"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1.4758015 1050.3064c11.6492855.7191 3.1098343-11.4976 12.2331255-11.3475" fill="none" stroke="#5fb2ff" stroke-miterlimit="4.9" stroke-width="2.2"/><g fill="#e0e0e0"><circle cx="13.470984" cy="1038.7133" r="1.823002"/><circle cx="2.444912" cy="1050.1708" r="1.823002"/></g></g></svg>
diff --git a/editor/icons/Editor3DHandle.svg b/editor/icons/Editor3DHandle.svg
index f63234f410..00e0d865af 100644
--- a/editor/icons/Editor3DHandle.svg
+++ b/editor/icons/Editor3DHandle.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill-opacity=".29412" r="8"/><circle cx="8" cy="8" fill="#fff" r="7"/><circle cx="8" cy="8" fill="#ff8484" r="5"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill-opacity=".29412" r="8"/><circle cx="8" cy="8" fill="#fff" r="7"/><circle cx="8" cy="8" fill="#ff5f5f" r="5"/></svg>
diff --git a/editor/icons/EditorControlAnchor.svg b/editor/icons/EditorControlAnchor.svg
index 4574f5d7be..3383ea121f 100644
--- a/editor/icons/EditorControlAnchor.svg
+++ b/editor/icons/EditorControlAnchor.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 0a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 1.0566-.11914l9.9434 6.1191-6.1172-9.9395a5 5 0 0 0 .11719-1.0605 5 5 0 0 0 -5-5z" fill-opacity=".39216" transform="translate(0 1036.4)"/><path d="m5 1a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 1.1406-.16992l9.8594 7.1699-7.168-9.8555a4 4 0 0 0 .16797-1.1445 4 4 0 0 0 -4-4z" fill="#a5efac" fill-rule="evenodd" transform="translate(0 1036.4)"/><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/><circle cx="5" cy="1041.4" fill="#a5efac" r="0"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m5 0a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 1.0566-.11914l9.9434 6.1191-6.1172-9.9395a5 5 0 0 0 .11719-1.0605 5 5 0 0 0 -5-5z" fill-opacity=".39216" transform="translate(0 1036.4)"/><path d="m5 1a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 1.1406-.16992l9.8594 7.1699-7.168-9.8555a4 4 0 0 0 .16797-1.1445 4 4 0 0 0 -4-4z" fill="#8eef97" fill-rule="evenodd" transform="translate(0 1036.4)"/><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/><circle cx="5" cy="1041.4" fill="#8eef97" r="0"/></g></svg>
diff --git a/editor/icons/EditorHandle.svg b/editor/icons/EditorHandle.svg
index a56e64bde3..8f78189798 100644
--- a/editor/icons/EditorHandle.svg
+++ b/editor/icons/EditorHandle.svg
@@ -1 +1 @@
-<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><circle cx="5" cy="5" fill-opacity=".29412" r="5"/><circle cx="5" cy="5" fill="#fff" r="4"/><circle cx="5" cy="5" fill="#ff8484" r="3"/></svg>
+<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><circle cx="5" cy="5" fill-opacity=".29412" r="5"/><circle cx="5" cy="5" fill="#fff" r="4"/><circle cx="5" cy="5" fill="#ff5f5f" r="3"/></svg>
diff --git a/editor/icons/EditorHandleAdd.svg b/editor/icons/EditorHandleAdd.svg
index 82d3730d3c..aca6b61df1 100644
--- a/editor/icons/EditorHandleAdd.svg
+++ b/editor/icons/EditorHandleAdd.svg
@@ -1 +1 @@
-<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><circle cx="5" cy="5" fill-opacity=".29412" r="5"/><circle cx="5" cy="5" fill="#474747" r="4"/><path d="m4 2v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#84ffb1"/></svg>
+<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><circle cx="5" cy="5" fill-opacity=".29412" r="5"/><circle cx="5" cy="5" fill="#474747" r="4"/><path d="m4 2v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/></svg>
diff --git a/editor/icons/EditorPivot.svg b/editor/icons/EditorPivot.svg
index ecb5dd95b7..cd7f5779c5 100644
--- a/editor/icons/EditorPivot.svg
+++ b/editor/icons/EditorPivot.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 0v6h-6v4h6v6h4v-6h6v-4h-6v-6zm1 7h2v2h-2z" fill="#fff" fill-opacity=".70588"/><path d="m7 1v5h2v-5zm-6 6v2h5v-2zm9 0v2h5v-2zm-3 3v5h2v-5z" fill="#ff8484"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 0v6h-6v4h6v6h4v-6h6v-4h-6v-6zm1 7h2v2h-2z" fill="#fff" fill-opacity=".70588"/><path d="m7 1v5h2v-5zm-6 6v2h5v-2zm9 0v2h5v-2zm-3 3v5h2v-5z" fill="#ff5f5f"/></svg>
diff --git a/editor/icons/EditorPosition.svg b/editor/icons/EditorPosition.svg
index 09f09feffc..10d0f5629d 100644
--- a/editor/icons/EditorPosition.svg
+++ b/editor/icons/EditorPosition.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 0v4.4199a4.2662 4.0576 0 0 0 -1.709 1.5801h-4.291v4h4.2949a4.2662 4.0576 0 0 0 1.7051 1.582v4.418h4v-4.4199a4.2662 4.0576 0 0 0 1.709-1.5801h4.291v-4h-4.2949a4.2662 4.0576 0 0 0 -1.7051-1.582v-4.418z" fill="#fff" fill-opacity=".70588"/><path d="m7 1v3.0605a4.2662 4.0576 0 0 1 1-.11914 4.2662 4.0576 0 0 1 1 .11914v-3.0605zm1 4.0801a2.9201 2.9201 0 0 0 -2.9199 2.9199 2.9201 2.9201 0 0 0 2.9199 2.9199 2.9201 2.9201 0 0 0 2.9199-2.9199 2.9201 2.9201 0 0 0 -2.9199-2.9199zm-7 1.9199v2h2.8691a4.2662 4.0576 0 0 1 -.13477-1 4.2662 4.0576 0 0 1 .13672-1h-2.8711zm11.131 0a4.2662 4.0576 0 0 1 .13477 1 4.2662 4.0576 0 0 1 -.13672 1h2.8711v-2h-2.8691zm-5.1309 4.9395v3.0605h2v-3.0605a4.2662 4.0576 0 0 1 -1 .11914 4.2662 4.0576 0 0 1 -1-.11914z" fill="#ff8484"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 0v4.4199a4.2662 4.0576 0 0 0 -1.709 1.5801h-4.291v4h4.2949a4.2662 4.0576 0 0 0 1.7051 1.582v4.418h4v-4.4199a4.2662 4.0576 0 0 0 1.709-1.5801h4.291v-4h-4.2949a4.2662 4.0576 0 0 0 -1.7051-1.582v-4.418z" fill="#fff" fill-opacity=".70588"/><path d="m7 1v3.0605a4.2662 4.0576 0 0 1 1-.11914 4.2662 4.0576 0 0 1 1 .11914v-3.0605zm1 4.0801a2.9201 2.9201 0 0 0 -2.9199 2.9199 2.9201 2.9201 0 0 0 2.9199 2.9199 2.9201 2.9201 0 0 0 2.9199-2.9199 2.9201 2.9201 0 0 0 -2.9199-2.9199zm-7 1.9199v2h2.8691a4.2662 4.0576 0 0 1 -.13477-1 4.2662 4.0576 0 0 1 .13672-1h-2.8711zm11.131 0a4.2662 4.0576 0 0 1 .13477 1 4.2662 4.0576 0 0 1 -.13672 1h2.8711v-2h-2.8691zm-5.1309 4.9395v3.0605h2v-3.0605a4.2662 4.0576 0 0 1 -1 .11914 4.2662 4.0576 0 0 1 -1-.11914z" fill="#ff5f5f"/></svg>
diff --git a/editor/icons/FixedSpatialMaterial.svg b/editor/icons/FixedSpatialMaterial.svg
index 6701208560..322465a0c7 100644
--- a/editor/icons/FixedSpatialMaterial.svg
+++ b/editor/icons/FixedSpatialMaterial.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -4.8887 2h2.8887 6.8965a7 7 0 0 0 -4.8965-2z" fill="#ff7070"/><path d="m3.1113 3a7 7 0 0 0 -1.4277 2h2.3164a2 2 0 0 1 2-2zm2.8887 0a2 2 0 0 1 2 2h6.3145a7 7 0 0 0 -1.418-2z" fill="#ffeb70"/><path d="m1.6836 5a7 7 0 0 0 -.60547 2h4.9219a2 2 0 0 1 -2-2h-2.3164zm4.3164 2h8.9199a7 7 0 0 0 -.60547-2h-6.3145a2 2 0 0 1 -2 2z" fill="#9dff70"/><path d="m1.0781 7a7 7 0 0 0 -.078125 1 7 7 0 0 0 .080078 1h13.842a7 7 0 0 0 .078125-1 7 7 0 0 0 -.080078-1h-8.9199-4.9219z" fill="#70ffb9"/><path d="m1.0801 9a7 7 0 0 0 .60547 2h12.631a7 7 0 0 0 .60547-2h-13.842z" fill="#70deff"/><path d="m3.1035 13a7 7 0 0 0 4.8965 2 7 7 0 0 0 4.8887-2z" fill="#ff70ac"/><path d="m1.6855 11a7 7 0 0 0 1.418 2h9.7852a7 7 0 0 0 1.4277-2h-12.631z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -4.8887 2h2.8887 6.8965a7 7 0 0 0 -4.8965-2z" fill="#ff4545"/><path d="m3.1113 3a7 7 0 0 0 -1.4277 2h2.3164a2 2 0 0 1 2-2zm2.8887 0a2 2 0 0 1 2 2h6.3145a7 7 0 0 0 -1.418-2z" fill="#ffe345"/><path d="m1.6836 5a7 7 0 0 0 -.60547 2h4.9219a2 2 0 0 1 -2-2h-2.3164zm4.3164 2h8.9199a7 7 0 0 0 -.60547-2h-6.3145a2 2 0 0 1 -2 2z" fill="#80ff45"/><path d="m1.0781 7a7 7 0 0 0 -.078125 1 7 7 0 0 0 .080078 1h13.842a7 7 0 0 0 .078125-1 7 7 0 0 0 -.080078-1h-8.9199-4.9219z" fill="#45ffa2"/><path d="m1.0801 9a7 7 0 0 0 .60547 2h12.631a7 7 0 0 0 .60547-2h-13.842z" fill="#45d7ff"/><path d="m3.1035 13a7 7 0 0 0 4.8965 2 7 7 0 0 0 4.8887-2z" fill="#ff4596"/><path d="m1.6855 11a7 7 0 0 0 1.418 2h9.7852a7 7 0 0 0 1.4277-2h-12.631z" fill="#8045ff"/></svg>
diff --git a/editor/icons/FontData.svg b/editor/icons/FontData.svg
index 7ee88582a5..4cb6412081 100644
--- a/editor/icons/FontData.svg
+++ b/editor/icons/FontData.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2zm0 5v2h2v-2zm0 3v2h2v-2zm0 3v2h2v-2zm3 0v2h2v-2z" fill="#e0e0e0"/><path d="m4 5v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2z" fill="#ff8484"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2zm0 5v2h2v-2zm0 3v2h2v-2zm0 3v2h2v-2zm3 0v2h2v-2z" fill="#e0e0e0"/><path d="m4 5v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2z" fill="#ff5f5f"/></svg>
diff --git a/editor/icons/GIProbe.svg b/editor/icons/GIProbe.svg
deleted file mode 100644
index b66c937317..0000000000
--- a/editor/icons/GIProbe.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1.0001 1.0001 0 0 0 -1 1v12a1.0001 1.0001 0 0 0 1 1h4v-2h-3v-10h9v-2zm9 3a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.459v.54102c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1v-.54102a4 4 0 0 0 2-3.459 4 4 0 0 0 -4-4zm0 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2zm-1 8v1h2v-1z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/GPUParticles2D.svg b/editor/icons/GPUParticles2D.svg
index b291bcda95..a693e554b2 100644
--- a/editor/icons/GPUParticles2D.svg
+++ b/editor/icons/GPUParticles2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a4.5 5 0 0 0 -4.4141 4.0312 3 3 0 0 0 -2.5859 2.9688 3 3 0 0 0 3 3h8a3 3 0 0 0 3-3 3 3 0 0 0 -2.5898-2.9668 4.5 5 0 0 0 -4.4102-4.0332zm-4 11a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm8 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-4 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#a5b7f3"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a4.5 5 0 0 0 -4.4141 4.0312 3 3 0 0 0 -2.5859 2.9688 3 3 0 0 0 3 3h8a3 3 0 0 0 3-3 3 3 0 0 0 -2.5898-2.9668 4.5 5 0 0 0 -4.4102-4.0332zm-4 11a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm8 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-4 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/GPUParticles3D.svg b/editor/icons/GPUParticles3D.svg
index 25377f9f5f..bbc90ec35f 100644
--- a/editor/icons/GPUParticles3D.svg
+++ b/editor/icons/GPUParticles3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a4.5 5 0 0 0 -4.4141 4.0312 3 3 0 0 0 -2.5859 2.9688 3 3 0 0 0 3 3h8a3 3 0 0 0 3-3 3 3 0 0 0 -2.5898-2.9668 4.5 5 0 0 0 -4.4102-4.0332zm-4 11a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm8 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-4 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a4.5 5 0 0 0 -4.4141 4.0312 3 3 0 0 0 -2.5859 2.9688 3 3 0 0 0 3 3h8a3 3 0 0 0 3-3 3 3 0 0 0 -2.5898-2.9668 4.5 5 0 0 0 -4.4102-4.0332zm-4 11a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm8 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-4 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/GPUParticlesAttractorBox.svg b/editor/icons/GPUParticlesAttractorBox.svg
index 3c27b2d3cb..7a2ee7a6b9 100644
--- a/editor/icons/GPUParticlesAttractorBox.svg
+++ b/editor/icons/GPUParticlesAttractorBox.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fc9c9c" fill-opacity=".996078" r="1"/><g fill="none" stroke="#fc9c9c" stroke-opacity=".996078"><ellipse cx="8" cy="-8" rx="2.339226" ry="4.949748" transform="rotate(90)"/><ellipse cx="8" cy="8" rx="2.339226" ry="4.949748"/><path d="m1.498906 1.498906h13.002189v13.002188h-13.002189z" stroke-width=".997813"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fc7f7f" fill-opacity=".996078" r="1"/><g fill="none" stroke="#fc7f7f" stroke-opacity=".996078"><ellipse cx="8" cy="-8" rx="2.339226" ry="4.949748" transform="rotate(90)"/><ellipse cx="8" cy="8" rx="2.339226" ry="4.949748"/><path d="m1.498906 1.498906h13.002189v13.002188h-13.002189z" stroke-width=".997813"/></g></svg>
diff --git a/editor/icons/GPUParticlesAttractorSphere.svg b/editor/icons/GPUParticlesAttractorSphere.svg
index 5473a23854..2215331a18 100644
--- a/editor/icons/GPUParticlesAttractorSphere.svg
+++ b/editor/icons/GPUParticlesAttractorSphere.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="-8" cy="-7.999999" fill="none" rx="6.499003" ry="6.499001" stroke="#fc9c9c" stroke-opacity=".996078" stroke-width="1.002" transform="scale(-1)"/><circle cx="8" cy="8" fill="#fc9c9c" fill-opacity=".996078" r="1"/><g fill="none" stroke="#fc9c9c" stroke-opacity=".996078"><ellipse cx="11.313708" rx="2.339226" ry="4.949748" transform="matrix(.70710678 .70710678 -.70710678 .70710678 0 0)"/><ellipse cy="11.313708" rx="2.339226" ry="4.949748" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 0)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="-8" cy="-7.999999" fill="none" rx="6.499003" ry="6.499001" stroke="#fc7f7f" stroke-opacity=".996078" stroke-width="1.002" transform="scale(-1)"/><circle cx="8" cy="8" fill="#fc7f7f" fill-opacity=".996078" r="1"/><g fill="none" stroke="#fc7f7f" stroke-opacity=".996078"><ellipse cx="11.313708" rx="2.339226" ry="4.949748" transform="matrix(.70710678 .70710678 -.70710678 .70710678 0 0)"/><ellipse cy="11.313708" rx="2.339226" ry="4.949748" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 0)"/></g></svg>
diff --git a/editor/icons/GPUParticlesAttractorVectorField.svg b/editor/icons/GPUParticlesAttractorVectorField.svg
index 93a29789e3..87b2b21804 100644
--- a/editor/icons/GPUParticlesAttractorVectorField.svg
+++ b/editor/icons/GPUParticlesAttractorVectorField.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="6.663637" cy="9.245457" fill="#fc9c9c" fill-opacity=".996078" rx="1.030661" ry=".998146"/><ellipse cx="-6.672815" cy="-9.387111" fill="none" rx="2.408711" ry="5.096776" stroke="#fc9c9c" stroke-opacity=".996078" stroke-width="1.0297" transform="matrix(-.99999945 .00104887 .00104887 -.99999945 0 0)"/><ellipse cx="9.387111" cy="-6.672815" fill="none" rx="2.408711" ry="5.096776" stroke="#fc9c9c" stroke-opacity=".996078" stroke-width="1.0297" transform="matrix(-.00104887 .99999945 -.99999945 .00104887 0 0)"/><g fill="#fc9c9c" fill-opacity=".996078"><path d="m11.8 15 2.4-2.4.8.8v-2.4h-2.4l.8.8-2.4 2.4z"/><path d="m11 6 3-3 1 1v-3h-3l1 1-3 3z"/><path d="m1.8 5 2.4-2.4.8.8v-2.4h-2.4l.8.8-2.4 2.4z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="6.663637" cy="9.245457" fill="#fc7f7f" fill-opacity=".996078" rx="1.030661" ry=".998146"/><ellipse cx="-6.672815" cy="-9.387111" fill="none" rx="2.408711" ry="5.096776" stroke="#fc7f7f" stroke-opacity=".996078" stroke-width="1.0297" transform="matrix(-.99999945 .00104887 .00104887 -.99999945 0 0)"/><ellipse cx="9.387111" cy="-6.672815" fill="none" rx="2.408711" ry="5.096776" stroke="#fc7f7f" stroke-opacity=".996078" stroke-width="1.0297" transform="matrix(-.00104887 .99999945 -.99999945 .00104887 0 0)"/><g fill="#fc7f7f" fill-opacity=".996078"><path d="m11.8 15 2.4-2.4.8.8v-2.4h-2.4l.8.8-2.4 2.4z"/><path d="m11 6 3-3 1 1v-3h-3l1 1-3 3z"/><path d="m1.8 5 2.4-2.4.8.8v-2.4h-2.4l.8.8-2.4 2.4z"/></g></svg>
diff --git a/editor/icons/GPUParticlesCollisionBox.svg b/editor/icons/GPUParticlesCollisionBox.svg
index f7296b34c3..4f7325d086 100644
--- a/editor/icons/GPUParticlesCollisionBox.svg
+++ b/editor/icons/GPUParticlesCollisionBox.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc9c9c" fill-opacity=".996078"><path d="m7.5 2.8124998-5.5883107 2.7941554v5.7660988l5.5883107 2.794155 5.588311-2.794155v-5.7660988zm0 1.6886278 3.145021 1.5732692-3.145021 1.5717523-3.1450214-1.5717523zm-3.9916505 2.8362274 3.1933204 1.5966602v3.1465378l-3.1933204-1.598256zm7.9833015 0v3.145021l-3.1933209 1.598257v-3.146538z" stroke-width=".851579"/><circle cx="1.875" cy="3.75" r=".9375"/><circle cx="13.124999" cy="3.75" r=".9375"/><circle cx="9.374999" cy="1.875" r=".9375"/><circle cx="5.625" cy="1.875" r=".9375"/></g></svg>
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f" fill-opacity=".996078"><path d="m7.5 2.8124998-5.5883107 2.7941554v5.7660988l5.5883107 2.794155 5.588311-2.794155v-5.7660988zm0 1.6886278 3.145021 1.5732692-3.145021 1.5717523-3.1450214-1.5717523zm-3.9916505 2.8362274 3.1933204 1.5966602v3.1465378l-3.1933204-1.598256zm7.9833015 0v3.145021l-3.1933209 1.598257v-3.146538z" stroke-width=".851579"/><circle cx="1.875" cy="3.75" r=".9375"/><circle cx="13.124999" cy="3.75" r=".9375"/><circle cx="9.374999" cy="1.875" r=".9375"/><circle cx="5.625" cy="1.875" r=".9375"/></g></svg>
diff --git a/editor/icons/GPUParticlesCollisionHeightField.svg b/editor/icons/GPUParticlesCollisionHeightField.svg
index b483f299e9..8bdc98a84b 100644
--- a/editor/icons/GPUParticlesCollisionHeightField.svg
+++ b/editor/icons/GPUParticlesCollisionHeightField.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc9c9c"><path d="m1 10c1-1 3-2 3-4s2-4 4-4 4 2 4 4 2 3 3 4l-7 5z"/><circle cx="2" cy="6" r="1"/><circle cx="14" cy="6" r="1"/><circle cx="12" cy="2" r="1"/><circle cx="4" cy="2" r="1"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><path d="m1 10c1-1 3-2 3-4s2-4 4-4 4 2 4 4 2 3 3 4l-7 5z"/><circle cx="2" cy="6" r="1"/><circle cx="14" cy="6" r="1"/><circle cx="12" cy="2" r="1"/><circle cx="4" cy="2" r="1"/></g></svg>
diff --git a/editor/icons/GPUParticlesCollisionSDF.svg b/editor/icons/GPUParticlesCollisionSDF.svg
index 6279990f3a..00eca8295d 100644
--- a/editor/icons/GPUParticlesCollisionSDF.svg
+++ b/editor/icons/GPUParticlesCollisionSDF.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 14h-12v-9s3 4 5.9999999 3.9999999c3.0000001-.0000001 6.0000001-3.9999999 6.0000001-3.9999999z" fill="none" stroke="#fc9c9c" stroke-linejoin="round" stroke-opacity=".996078" stroke-width="2"/><g fill="#fc9c9c" fill-opacity=".996078"><circle cx="2" cy="2" r="1"/><circle cx="14" cy="2" r="1"/><circle cx="10" cy="5" r="1"/><circle cx="6" cy="5" r="1"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 14h-12v-9s3 4 5.9999999 3.9999999c3.0000001-.0000001 6.0000001-3.9999999 6.0000001-3.9999999z" fill="none" stroke="#fc7f7f" stroke-linejoin="round" stroke-opacity=".996078" stroke-width="2"/><g fill="#fc7f7f" fill-opacity=".996078"><circle cx="2" cy="2" r="1"/><circle cx="14" cy="2" r="1"/><circle cx="10" cy="5" r="1"/><circle cx="6" cy="5" r="1"/></g></svg>
diff --git a/editor/icons/GPUParticlesCollisionSphere.svg b/editor/icons/GPUParticlesCollisionSphere.svg
index fc7715445c..cd188ddacc 100644
--- a/editor/icons/GPUParticlesCollisionSphere.svg
+++ b/editor/icons/GPUParticlesCollisionSphere.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc9c9c" fill-opacity=".996078"><path d="m8 3.0532484c-3.2888554 0-5.9733758 2.6845204-5.9733758 5.9733758 0 3.2889408 2.6845204 5.9733758 5.9733758 5.9733758 3.288855 0 5.973376-2.684435 5.973376-5.9733758 0-3.2888554-2.684521-5.9733758-5.973376-5.9733758zm-.8533394 1.79005v4.1567016c-1.1034532-.0608789-2.2238878-.2544573-3.3650586-.5900074.256693-1.7901354 1.6087154-3.2141029 3.3650586-3.5667027zm1.7066788 0c1.7535276.3520281 3.1035956 1.77213 3.3633516 3.55834-1.113266.3129793-2.2321649.5142138-3.3633516.5866709zm3.2300606 5.3599956c-.434043 1.51792-1.663927 2.690664-3.2300606 3.005035v-2.518376c1.0915918-.0617 2.1691036-.227875 3.2300606-.486668zm-8.161765.015c1.0865571.272147 2.162106.428504 3.2250256.480003v2.510013c-1.5608431-.313338-2.7870065-1.479605-3.2250256-2.990016z" stroke-width=".853339"/><circle cx="2" cy="5" r="1"/><circle cx="14" cy="5" r="1"/><circle cx="10" cy="2" r="1"/><circle cx="6" cy="2" r="1"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f" fill-opacity=".996078"><path d="m8 3.0532484c-3.2888554 0-5.9733758 2.6845204-5.9733758 5.9733758 0 3.2889408 2.6845204 5.9733758 5.9733758 5.9733758 3.288855 0 5.973376-2.684435 5.973376-5.9733758 0-3.2888554-2.684521-5.9733758-5.973376-5.9733758zm-.8533394 1.79005v4.1567016c-1.1034532-.0608789-2.2238878-.2544573-3.3650586-.5900074.256693-1.7901354 1.6087154-3.2141029 3.3650586-3.5667027zm1.7066788 0c1.7535276.3520281 3.1035956 1.77213 3.3633516 3.55834-1.113266.3129793-2.2321649.5142138-3.3633516.5866709zm3.2300606 5.3599956c-.434043 1.51792-1.663927 2.690664-3.2300606 3.005035v-2.518376c1.0915918-.0617 2.1691036-.227875 3.2300606-.486668zm-8.161765.015c1.0865571.272147 2.162106.428504 3.2250256.480003v2.510013c-1.5608431-.313338-2.7870065-1.479605-3.2250256-2.990016z" stroke-width=".853339"/><circle cx="2" cy="5" r="1"/><circle cx="14" cy="5" r="1"/><circle cx="10" cy="2" r="1"/><circle cx="6" cy="2" r="1"/></g></svg>
diff --git a/editor/icons/Generic6DOFJoint3D.svg b/editor/icons/Generic6DOFJoint3D.svg
index 63df5fc507..07918748e5 100644
--- a/editor/icons/Generic6DOFJoint3D.svg
+++ b/editor/icons/Generic6DOFJoint3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a1 1 0 0 0 -1 1v4.8828l-3.5527-1.7773a1 1 0 0 0 -.48438-.10352 1 1 0 0 0 -.85742.55078 1 1 0 0 0 .44727 1.3418l3.2109 1.6055-3.2109 1.6055a1 1 0 0 0 -.44727 1.3418 1 1 0 0 0 1.3418.44726l3.5527-1.7773v3.8828a1 1 0 0 0 1 1 1 1 0 0 0 1-1v-3.8828l3.5527 1.7773a1 1 0 0 0 1.3418-.44726 1 1 0 0 0 -.44726-1.3418l-3.2109-1.6055 3.2109-1.6055a1 1 0 0 0 .44726-1.3418 1 1 0 0 0 -.88672-.55273 1 1 0 0 0 -.45508.10547l-3.5527 1.7773v-4.8828a1 1 0 0 0 -1-1z" fill="#fc9c9c" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a1 1 0 0 0 -1 1v4.8828l-3.5527-1.7773a1 1 0 0 0 -.48438-.10352 1 1 0 0 0 -.85742.55078 1 1 0 0 0 .44727 1.3418l3.2109 1.6055-3.2109 1.6055a1 1 0 0 0 -.44727 1.3418 1 1 0 0 0 1.3418.44726l3.5527-1.7773v3.8828a1 1 0 0 0 1 1 1 1 0 0 0 1-1v-3.8828l3.5527 1.7773a1 1 0 0 0 1.3418-.44726 1 1 0 0 0 -.44726-1.3418l-3.2109-1.6055 3.2109-1.6055a1 1 0 0 0 .44726-1.3418 1 1 0 0 0 -.88672-.55273 1 1 0 0 0 -.45508.10547l-3.5527 1.7773v-4.8828a1 1 0 0 0 -1-1z" fill="#fc7f7f" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/Gradient.svg b/editor/icons/Gradient.svg
index 47dde294fc..99d3a871a6 100644
--- a/editor/icons/Gradient.svg
+++ b/editor/icons/Gradient.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="10" x2="10" y1="1" y2="15"><stop offset="0" stop-color="#e0e0e0"/><stop offset="1" stop-color="#e0e0e0" stop-opacity="0"/></linearGradient><path d="m2 1c-.55228 0-1 .44772-1 1v12c0 .55228.44772 1 1 1h12c.55228 0 1-.44772 1-1v-12c0-.55228-.44772-1-1-1z" fill="url(#a)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m3 1c-1.1046 0-2 .8954299-2 1.9999999v10.0000001c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10.0000001c0-1.1046-.89543-1.9999999-2-1.9999999zm0 1.9999999h10v10.0000001h-10z"/><path d="m7.5 5.500001h1v1h-1z" stroke-width=".787342"/><path d="m3.5 3.5v9h3v-1h1v-1h-1v-1h1v-1h-1v-1h1v-1h-1v-1h1v-1h-1v-1z" stroke-width="4.09116"/><g stroke-width=".787342"><path d="m7.5 3.5h1v1h-1z"/><path d="m7.5 9.500001h1v1h-1z"/><path d="m7.5 7.500001h1v1h-1z"/><path d="m7.5 11.5h1v1h-1z"/><path d="m8.5 4.500001h1v1h-1z"/><path d="m8.5 6.500001h1v1h-1z"/><path d="m8.5 8.500002h1v1h-1z"/><path d="m8.5 10.500002h1v1h-1z"/></g></g></svg>
diff --git a/editor/icons/GradientTexture.svg b/editor/icons/GradientTexture.svg
index ec4c4546e1..fa03e69805 100644
--- a/editor/icons/GradientTexture.svg
+++ b/editor/icons/GradientTexture.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="10" x2="10" y1="1" y2="15"><stop offset="0" stop-color="#e0e0e0"/><stop offset="1" stop-color="#e0e0e0" stop-opacity="0"/></linearGradient><g transform="translate(0 -1036.4)"><path d="m2 1a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-12a1 1 0 0 0 -1-1zm1 2h10v8h-10z" fill="url(#a)" transform="translate(0 1036.4)"/><g fill="#e0e0e0"><path d="m6 1043.4h2v1h-2z"/><path d="m6 1044.4h2v2h-2z"/><path d="m4 1045.4h2v1h-2z"/><path d="m8 1044.4h2v2h-2z"/><path d="m10 1044.4h2v2h-2z"/><path d="m8 1042.4h3v2h-3z"/><path d="m9 1041.4h1v1h-1z"/><path d="m5 1044.4h1v1h-1z"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m12.5 10.5v-7h-3v1h-1v1h1v1h-1v1h1v1h-1v1h1v1zm-4-1h-1v1h1zm-1 0v-1h-1v1zm0-1h1v-1h-1zm0-1v-1h-1v1zm0-1h1v-1h-1zm0-1v-1h-1v1zm0-1h1v-1h-1z" stroke-width=".787342"/><path d="m2 1c-.552285 0-1 .4477153-1 1v12.000001c0 .552285.447715 1 1 1h11.999999c.552285 0 1-.447715 1-1v-12.000001c0-.5522847-.447715-1-1-1zm1 2.0000001h9.999999v8.0000009h-9.999999z" fill-opacity=".99608"/></g></svg>
diff --git a/editor/icons/GraphEdit.svg b/editor/icons/GraphEdit.svg
index b879259ffc..fbe7422f98 100644
--- a/editor/icons/GraphEdit.svg
+++ b/editor/icons/GraphEdit.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -1-1.7305v-5.8555l4.793 4.793 1.4141-1.4141-4.793-4.793h5.8574a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm10.656 6.9297-.70703.70703 1.4141 1.4141.70703-.70703zm-1.4141 1.4141-3.8887 3.8887-.35352 1.7676 1.7676-.35352 3.8887-3.8887-1.4141-1.4141z" fill="#a5efac" transform="translate(0 1036.4)"/><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -1-1.7305v-5.8555l4.793 4.793 1.4141-1.4141-4.793-4.793h5.8574a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm10.656 6.9297-.70703.70703 1.4141 1.4141.70703-.70703zm-1.4141 1.4141-3.8887 3.8887-.35352 1.7676 1.7676-.35352 3.8887-3.8887-1.4141-1.4141z" fill="#8eef97" transform="translate(0 1036.4)"/><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/></g></svg>
diff --git a/editor/icons/GraphNode.svg b/editor/icons/GraphNode.svg
index bcd7bfc1c1..061a81d951 100644
--- a/editor/icons/GraphNode.svg
+++ b/editor/icons/GraphNode.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -1-1.7305v-5.8555l4.0859 4.0859 1.4141-1.4141-4.0859-4.0859h5.8574a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm9.5 9a2.5 2.5 0 0 0 -2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5 2.5 2.5 0 0 0 -2.5-2.5z" fill="#a5efac" transform="translate(0 1036.4)"/><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -1-1.7305v-5.8555l4.0859 4.0859 1.4141-1.4141-4.0859-4.0859h5.8574a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm9.5 9a2.5 2.5 0 0 0 -2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5 2.5 2.5 0 0 0 -2.5-2.5z" fill="#8eef97" transform="translate(0 1036.4)"/><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/></g></svg>
diff --git a/editor/icons/Grid.svg b/editor/icons/Grid.svg
index 8353ad7d19..3b63bfb051 100644
--- a/editor/icons/Grid.svg
+++ b/editor/icons/Grid.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 10 2h2 12v-2-12h-12zm2 2h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm-8 4h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm-8 4h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h14v-14zm1.9999999 2h2v2h-2zm4 0h2v2h-2zm4.0000001 0h2v2h-2zm-8.0000001 4.0000004h2v2h-2zm4 0h2v2h-2zm4.0000001 0h2v2h-2zm-8.0000001 3.9999996h2v2h-2zm4 0h2v2h-2zm4.0000001 0h2v2h-2z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/GridContainer.svg b/editor/icons/GridContainer.svg
index fb6207d94b..94a312bc36 100644
--- a/editor/icons/GridContainer.svg
+++ b/editor/icons/GridContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm-8 4h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm-8 4h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm-8 4h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm-8 4h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/GrooveJoint2D.svg b/editor/icons/GrooveJoint2D.svg
index 41cf64ad66..0f7b84096c 100644
--- a/editor/icons/GrooveJoint2D.svg
+++ b/editor/icons/GrooveJoint2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1037.4h-5v6h-5v2h5v6h5zm-7 0h-7v14h7v-4h-5v-6h5z" fill="#a5b7f3" fill-opacity=".98824" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1037.4h-5v6h-5v2h5v6h5zm-7 0h-7v14h7v-4h-5v-6h5z" fill="#8da5f3" fill-opacity=".98824" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/GuiChecked.svg b/editor/icons/GuiChecked.svg
index 9bdf5dcb19..31b2995939 100644
--- a/editor/icons/GuiChecked.svg
+++ b/editor/icons/GuiChecked.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill-opacity=".188235" stroke-width="1.166667"/><path d="m11.500773 3.7343508-5.6117507 5.6117502-1.7045017-1.6814543-1.4992276 1.4992276 3.2037293 3.1806817 7.1109777-7.1109775z" stroke-width="1.060227"/></g></svg>
+<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#699ce8" stroke-width="1.16667"/><path d="m11.500773 3.7343508-5.6117507 5.6117502-1.7045017-1.6814543-1.4992276 1.4992276 3.2037293 3.1806817 7.1109777-7.1109775z" fill="#fff" stroke-width="1.06023"/></svg>
diff --git a/editor/icons/GuiRadioChecked.svg b/editor/icons/GuiRadioChecked.svg
index 771337116d..65ef086c9a 100644
--- a/editor/icons/GuiRadioChecked.svg
+++ b/editor/icons/GuiRadioChecked.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill-opacity=".188235" stroke-width="2.333333"/><path d="m12 8a4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" stroke-width="1.333333"/></g></svg>
+<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#699ce8" stroke-width="2.33333"/><path d="m12 8a4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" fill="#fff" stroke-width="1.33333"/></svg>
diff --git a/editor/icons/HBoxContainer.svg b/editor/icons/HBoxContainer.svg
index 791fca0ebc..8fbeef525c 100644
--- a/editor/icons/HBoxContainer.svg
+++ b/editor/icons/HBoxContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h2v10h-2zm4 0h2v10h-2zm4 0h2v10h-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h2v10h-2zm4 0h2v10h-2zm4 0h2v10h-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/HScrollBar.svg b/editor/icons/HScrollBar.svg
index 5828ccb388..3b42eb94c9 100644
--- a/editor/icons/HScrollBar.svg
+++ b/editor/icons/HScrollBar.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1041.4c0-1.108-.892-2-2-2h-10c-1.108 0-2 .892-2 2v6c0 1.108.892 2 2 2h10c1.108 0 2-.892 2-2zm-1 2.9883a1.0001 1.0001 0 0 1 -.168.5664l-2 3a1.0001 1.0001 0 1 1 -1.664-1.1094l1.6289-2.4453-1.6289-2.4453a1.0001 1.0001 0 1 1 1.664-1.1094l2 3a1.0001 1.0001 0 0 1 .168.543zm-7.9922-2.9981a1.0001 1.0001 0 0 1 -.1758.5645l-1.6308 2.4453 1.6308 2.4453a1.0001 1.0001 0 1 1 -1.664 1.1094l-2-3a1.0001 1.0001 0 0 1 0-1.1094l2-3a1.0001 1.0001 0 0 1 1.8398.5449z" fill="#a5efac" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1041.4c0-1.108-.892-2-2-2h-10c-1.108 0-2 .892-2 2v6c0 1.108.892 2 2 2h10c1.108 0 2-.892 2-2zm-1 2.9883a1.0001 1.0001 0 0 1 -.168.5664l-2 3a1.0001 1.0001 0 1 1 -1.664-1.1094l1.6289-2.4453-1.6289-2.4453a1.0001 1.0001 0 1 1 1.664-1.1094l2 3a1.0001 1.0001 0 0 1 .168.543zm-7.9922-2.9981a1.0001 1.0001 0 0 1 -.1758.5645l-1.6308 2.4453 1.6308 2.4453a1.0001 1.0001 0 1 1 -1.664 1.1094l-2-3a1.0001 1.0001 0 0 1 0-1.1094l2-3a1.0001 1.0001 0 0 1 1.8398.5449z" fill="#8eef97" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/HSeparator.svg b/editor/icons/HSeparator.svg
index d786767be8..c47b126778 100644
--- a/editor/icons/HSeparator.svg
+++ b/editor/icons/HSeparator.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 2v3h6v-3zm-4 5v2h14v-2zm4 4v3h6v-3z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 2v3h6v-3zm-4 5v2h14v-2zm4 4v3h6v-3z" fill="#8eef97"/></svg>
diff --git a/editor/icons/HSlider.svg b/editor/icons/HSlider.svg
index 0ab453bbce..c876afa843 100644
--- a/editor/icons/HSlider.svg
+++ b/editor/icons/HSlider.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 3c-.55228 0-1 .44772-1 1v2c0 .55228.44772 1 1 1s1-.44772 1-1v-2c0-.55228-.44772-1-1-1zm12 0c-.55228 0-1 .44772-1 1v2c0 .55228.44772 1 1 1s1-.44772 1-1v-2c0-.55228-.44772-1-1-1zm-6 1c-.55228 0-1 .44772-1 1s.44772 1 1 1 1-.44772 1-1-.44772-1-1-1zm5 5c-1.1046 0-2 .89543-2 2 0 1.1046.89543 2 2 2 1.0099-.000337 1.8611-.75351 1.9844-1.7559.04003-.16104.03936-.32952-.002-.49024-.12404-1.0008-.97388-1.7527-1.9824-1.7539zm-11 1c-1.3523-.019125-1.3523 2.0191 0 2h7.1309c-.085635-.32648-.1296-.66248-.13086-1 .00189-.3376.046518-.67361.13281-1z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 3c-.55228 0-1 .44772-1 1v2c0 .55228.44772 1 1 1s1-.44772 1-1v-2c0-.55228-.44772-1-1-1zm12 0c-.55228 0-1 .44772-1 1v2c0 .55228.44772 1 1 1s1-.44772 1-1v-2c0-.55228-.44772-1-1-1zm-6 1c-.55228 0-1 .44772-1 1s.44772 1 1 1 1-.44772 1-1-.44772-1-1-1zm5 5c-1.1046 0-2 .89543-2 2 0 1.1046.89543 2 2 2 1.0099-.000337 1.8611-.75351 1.9844-1.7559.04003-.16104.03936-.32952-.002-.49024-.12404-1.0008-.97388-1.7527-1.9824-1.7539zm-11 1c-1.3523-.019125-1.3523 2.0191 0 2h7.1309c-.085635-.32648-.1296-.66248-.13086-1 .00189-.3376.046518-.67361.13281-1z" fill="#8eef97"/></svg>
diff --git a/editor/icons/HSplitContainer.svg b/editor/icons/HSplitContainer.svg
index 796e331ef5..4cf32d00ff 100644
--- a/editor/icons/HSplitContainer.svg
+++ b/editor/icons/HSplitContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h4v3l-2 2 2 2v3h-4zm6 0h4v10h-4v-3l2-2-2-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h4v3l-2 2 2 2v3h-4zm6 0h4v10h-4v-3l2-2-2-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/HingeJoint3D.svg b/editor/icons/HingeJoint3D.svg
index ca97169d82..a37377905d 100644
--- a/editor/icons/HingeJoint3D.svg
+++ b/editor/icons/HingeJoint3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.2832 1.3281a1.0001 1.0001 0 0 0 -.88086.51172l-3.6895 6.3906c.40599-.13877.83411-.23047 1.2871-.23047.37043 0 .72206.067873 1.0625.16211l3.0723-5.3223a1.0001 1.0001 0 0 0 -.85156-1.5117zm-3.2832 7.6719a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h10a1 1 0 0 0 1-1 1 1 0 0 0 -1-1h-7.1738a3 3 0 0 0 .17383-1 3 3 0 0 0 -3-3zm0 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.2832 1.3281a1.0001 1.0001 0 0 0 -.88086.51172l-3.6895 6.3906c.40599-.13877.83411-.23047 1.2871-.23047.37043 0 .72206.067873 1.0625.16211l3.0723-5.3223a1.0001 1.0001 0 0 0 -.85156-1.5117zm-3.2832 7.6719a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h10a1 1 0 0 0 1-1 1 1 0 0 0 -1-1h-7.1738a3 3 0 0 0 .17383-1 3 3 0 0 0 -3-3zm0 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/ImmediateGeometry3D.svg b/editor/icons/ImmediateGeometry3D.svg
index 876d752ced..ec5a392a68 100644
--- a/editor/icons/ImmediateGeometry3D.svg
+++ b/editor/icons/ImmediateGeometry3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2.9208 1046.4c-.26373.3-.4204.7296-.4204 1.2383 0 1.6277-3.1381-.1781-.33757 2.6703.88382.899 2.6544.6701 3.5382-.2288.88384-.899.88382-2.3565 0-3.2554-1.1002-1.1191-2.2001-1.0845-2.7803-.4244zm2.3802-1.6103 2.4005 2.4416 6.8014-6.9177c.66286-.6742.66286-1.7673 0-2.4415-.66288-.6741-1.7376-.6741-2.4005 0z" fill="#fc9c9c" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2.9208 1046.4c-.26373.3-.4204.7296-.4204 1.2383 0 1.6277-3.1381-.1781-.33757 2.6703.88382.899 2.6544.6701 3.5382-.2288.88384-.899.88382-2.3565 0-3.2554-1.1002-1.1191-2.2001-1.0845-2.7803-.4244zm2.3802-1.6103 2.4005 2.4416 6.8014-6.9177c.66286-.6742.66286-1.7673 0-2.4415-.66288-.6741-1.7376-.6741-2.4005 0z" fill="#fc7f7f" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/InsertAfter.svg b/editor/icons/InsertAfter.svg
index b75df837bd..d7fc9c67c0 100644
--- a/editor/icons/InsertAfter.svg
+++ b/editor/icons/InsertAfter.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" fill="none" r="2"/><path d="m11.99.99023a1.0001 1.0001 0 0 0 -.69726 1.7168l.29297.29297h-2.5859v2h2.5859l-.29297.29297a1.0001 1.0001 0 1 0 1.4141 1.4141l2-2a1.0001 1.0001 0 0 0 0-1.4141l-2-2a1.0001 1.0001 0 0 0 -.7168-.30273zm-8.9902.0097656c-1.108 0-2 .892-2 2v2c0 1.108.892 2 2 2h2c1.108 0 2-.892 2-2v-2c0-1.108-.892-2-2-2z" fill="#e0e0e0"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#84ffb1"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" fill="none" r="2"/><path d="m11.99.99023a1.0001 1.0001 0 0 0 -.69726 1.7168l.29297.29297h-2.5859v2h2.5859l-.29297.29297a1.0001 1.0001 0 1 0 1.4141 1.4141l2-2a1.0001 1.0001 0 0 0 0-1.4141l-2-2a1.0001 1.0001 0 0 0 -.7168-.30273zm-8.9902.0097656c-1.108 0-2 .892-2 2v2c0 1.108.892 2 2 2h2c1.108 0 2-.892 2-2v-2c0-1.108-.892-2-2-2z" fill="#e0e0e0"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/></svg>
diff --git a/editor/icons/InsertBefore.svg b/editor/icons/InsertBefore.svg
index 44c876fc76..ee62b28380 100644
--- a/editor/icons/InsertBefore.svg
+++ b/editor/icons/InsertBefore.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" fill="none" r="2"/><path d="m4.0096.99023a1.0001 1.0001 0 0 1 .69726 1.7168l-.29297.29297h2.5859v2h-2.5859l.29297.29297a1.0001 1.0001 0 1 1 -1.4141 1.4141l-2-2a1.0001 1.0001 0 0 1 0-1.4141l2-2a1.0001 1.0001 0 0 1 .7168-.30273zm8.9902.0097656c1.108 0 2 .892 2 2v2c0 1.108-.892 2-2 2h-2c-1.108 0-2-.892-2-2v-2c0-1.108.892-2 2-2z" fill="#e0e0e0"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#84ffb1"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" fill="none" r="2"/><path d="m4.0096.99023a1.0001 1.0001 0 0 1 .69726 1.7168l-.29297.29297h2.5859v2h-2.5859l.29297.29297a1.0001 1.0001 0 1 1 -1.4141 1.4141l-2-2a1.0001 1.0001 0 0 1 0-1.4141l2-2a1.0001 1.0001 0 0 1 .7168-.30273zm8.9902.0097656c1.108 0 2 .892 2 2v2c0 1.108-.892 2-2 2h-2c-1.108 0-2-.892-2-2v-2c0-1.108.892-2 2-2z" fill="#e0e0e0"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/></svg>
diff --git a/editor/icons/InverseKinematics.svg b/editor/icons/InverseKinematics.svg
index e4a076fbbd..4c6dbd4546 100644
--- a/editor/icons/InverseKinematics.svg
+++ b/editor/icons/InverseKinematics.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v10.27h2v-10.271a2 2 0 0 0 .73047-.72852h4.541a2 2 0 0 0 .72852.73047v3.2695h-2v2l-1 2 3 2v-4h2v4l3-2-1-2v-2h-2v-3.2715a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-4.541a2 2 0 0 0 -1.7285-1z" fill="#fc9c9c" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v10.27h2v-10.271a2 2 0 0 0 .73047-.72852h4.541a2 2 0 0 0 .72852.73047v3.2695h-2v2l-1 2 3 2v-4h2v4l3-2-1-2v-2h-2v-3.2715a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-4.541a2 2 0 0 0 -1.7285-1z" fill="#fc7f7f" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/ItemList.svg b/editor/icons/ItemList.svg
index fb98a706a9..efa753fdb6 100644
--- a/editor/icons/ItemList.svg
+++ b/editor/icons/ItemList.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm1 1v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-6 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-6 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm1 1v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-6 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-6 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/KeyAnimation.svg b/editor/icons/KeyAnimation.svg
index 5afd5bdb70..24a1e84da2 100644
--- a/editor/icons/KeyAnimation.svg
+++ b/editor/icons/KeyAnimation.svg
@@ -1 +1 @@
-<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#b76ef0" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
+<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#a448f0" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
diff --git a/editor/icons/KeyAudio.svg b/editor/icons/KeyAudio.svg
index e1a93529a6..18caa7afe2 100644
--- a/editor/icons/KeyAudio.svg
+++ b/editor/icons/KeyAudio.svg
@@ -1 +1 @@
-<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#eae668" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
+<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#eae440" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
diff --git a/editor/icons/KeyBezier.svg b/editor/icons/KeyBezier.svg
index cd41f953b1..7bbdd8dbab 100644
--- a/editor/icons/KeyBezier.svg
+++ b/editor/icons/KeyBezier.svg
@@ -1 +1 @@
-<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#5792f6" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
+<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#2877f6" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
diff --git a/editor/icons/KeyBezierSelected.svg b/editor/icons/KeyBezierSelected.svg
index e8536e97b4..741f9bea60 100644
--- a/editor/icons/KeyBezierSelected.svg
+++ b/editor/icons/KeyBezierSelected.svg
@@ -1 +1 @@
-<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><rect fill="#84c2ff" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1044.4)" width="6.1027" x="-741.53" y="741.08"/></svg>
+<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><rect fill="#5fb2ff" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1044.4)" width="6.1027" x="-741.53" y="741.08"/></svg>
diff --git a/editor/icons/KeyCall.svg b/editor/icons/KeyCall.svg
index dd47272d4f..5ffbceeb09 100644
--- a/editor/icons/KeyCall.svg
+++ b/editor/icons/KeyCall.svg
@@ -1 +1 @@
-<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#66f376" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
+<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#3cf34e" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
diff --git a/editor/icons/KeyNext.svg b/editor/icons/KeyNext.svg
index a2b616072b..83a8329494 100644
--- a/editor/icons/KeyNext.svg
+++ b/editor/icons/KeyNext.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#84ffb1"/><path d="m11 1a4 4 0 0 0 -3.8691 3h-6.1309v2h1v2h3v-2h2.1328a4 4 0 0 0 2.8672 2.8691v-.86914h3.6387a4 4 0 0 0 1.3613-3 4 4 0 0 0 -4-4zm0 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/><path d="m11 1a4 4 0 0 0 -3.8691 3h-6.1309v2h1v2h3v-2h2.1328a4 4 0 0 0 2.8672 2.8691v-.86914h3.6387a4 4 0 0 0 1.3613-3 4 4 0 0 0 -4-4zm0 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/KeySelected.svg b/editor/icons/KeySelected.svg
index 32f900bdd6..aff66b9a27 100644
--- a/editor/icons/KeySelected.svg
+++ b/editor/icons/KeySelected.svg
@@ -1 +1 @@
-<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#84c2ff" height="6.1027" ry=".76286" transform="matrix(.87871827 -.87871827 .87871827 .87871827 .03288 -1297.7965)" width="6.1027" x="-741.53003" y="741.08002"/><rect fill="#003e7a" height="3.434683" ry=".429348" stroke-width=".562814" transform="matrix(.89137101 -.86588067 .89137101 .86588067 -.038545 -1297.8361)" width="3.434683" x="-751.20953" y="753.42743"/></svg>
+<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#5fb2ff" height="6.1027" ry=".76286" transform="matrix(.87871827 -.87871827 .87871827 .87871827 .03288 -1297.7965)" width="6.1027" x="-741.53003" y="741.08002"/><rect fill="#003e7a" height="3.434683" ry=".429348" stroke-width=".562814" transform="matrix(.89137101 -.86588067 .89137101 .86588067 -.038545 -1297.8361)" width="3.434683" x="-751.20953" y="753.42743"/></svg>
diff --git a/editor/icons/KeyXform.svg b/editor/icons/KeyXform.svg
index 12f27d32a9..59c14cd820 100644
--- a/editor/icons/KeyXform.svg
+++ b/editor/icons/KeyXform.svg
@@ -1 +1 @@
-<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#ea9568" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
+<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#ea7940" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)" width="6.1027" x="-740.13947" y="741.10779"/></svg>
diff --git a/editor/icons/KinematicBody2D.svg b/editor/icons/KinematicBody2D.svg
deleted file mode 100644
index 70faad6a49..0000000000
--- a/editor/icons/KinematicBody2D.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6.4921 1c-.55401 0-1 .446-1 1v3c0 .554.44599 1 1 1h1v.9902a1.0001 1.0001 0 0 0 -.31641.062l-2.0508.6836-.68359-2.0508a1.0001 1.0001 0 0 0 -.99023-.6972 1.0001 1.0001 0 0 0 -.9082 1.3281l1 3a1.0001 1.0001 0 0 0 1.2656.6328l1.6836-.5605v.6113c0 .041.018715.076.023437.1152l-4.5781 3.0528a1.0001 1.0001 0 1 0 1.1094 1.664l5.0566-3.3711 1.4941 2.9864a1.0001 1.0001 0 0 0 1.2109.5019l3-1a1.0001 1.0001 0 1 0 -.63281-1.8965l-2.1777.7246-.97461-1.9511c.2759-.1777.46875-.4723.46875-.8262v-1h1.3828l.72266 1.4473a1.0001 1.0001 0 1 0 1.7891-.8946l-1-2a1.0001 1.0001 0 0 0 -.89453-.5527h-3v-1h1c.55401 0 1-.446 1-1v-3c0-.554-.44599-1-1-1zm0 2h1v2h-1z" fill="#a5b7f3"/></svg>
diff --git a/editor/icons/KinematicBody3D.svg b/editor/icons/KinematicBody3D.svg
deleted file mode 100644
index 06e9275ec1..0000000000
--- a/editor/icons/KinematicBody3D.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1c-.55401 0-1 .44599-1 1v3c0 .55401.44599 1 1 1h1v.99023a1.0001 1.0001 0 0 0 -.31641.0625l-2.0508.68359-.68359-2.0508a1.0001 1.0001 0 0 0 -.99023-.69727 1.0001 1.0001 0 0 0 -.9082 1.3281l1 3a1.0001 1.0001 0 0 0 1.2656.63281l1.6836-.56055v.61133c0 .04088.018715.07566.023437.11523l-4.5781 3.0527a1.0001 1.0001 0 1 0 1.1094 1.6641l5.0566-3.3711 1.4941 2.9863a1.0001 1.0001 0 0 0 1.2109.50195l3-1a1.0001 1.0001 0 1 0 -.63281-1.8965l-2.1777.72461-.97461-1.9512c.2759-.17764.46875-.47227.46875-.82617v-1h1.3828l.72266 1.4473a1.0001 1.0001 0 1 0 1.7891-.89453l-1-2a1.0001 1.0001 0 0 0 -.89453-.55273h-3v-1h1c.55401 0 1-.44599 1-1v-3c0-.55401-.44599-1-1-1zm0 2h1v2h-1z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/Label.svg b/editor/icons/Label.svg
index bfb1c903f3..f7a6fb3a9e 100644
--- a/editor/icons/Label.svg
+++ b/editor/icons/Label.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 3a1.0001 1.0001 0 0 0 -.70703.29297l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1.0001 1.0001 0 0 0 .70703.29297h8a1.0001 1.0001 0 0 0 1-1v-8a1.0001 1.0001 0 0 0 -1-1h-8zm-1 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#a5efac" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 3a1.0001 1.0001 0 0 0 -.70703.29297l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1.0001 1.0001 0 0 0 .70703.29297h8a1.0001 1.0001 0 0 0 1-1v-8a1.0001 1.0001 0 0 0 -1-1h-8zm-1 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#8eef97" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/LightOccluder2D.svg b/editor/icons/LightOccluder2D.svg
index 8c5bb89218..ff2c4d4561 100644
--- a/editor/icons/LightOccluder2D.svg
+++ b/editor/icons/LightOccluder2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1037.4c-2.7614 0-5 2.2386-5 5 .00253 1.9858 1.18 3.7819 3 4.5762v2.4238h4v-2.4199c1.8213-.7949 2.999-2.5929 3-4.5801 0-2.7614-2.2386-5-5-5zm0 2v6c-1.6569 0-3-1.3431-3-3s1.3431-3 3-3zm-1 11v1h2v-1z" fill="#a5b7f3" fill-opacity=".98824" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1037.4c-2.7614 0-5 2.2386-5 5 .00253 1.9858 1.18 3.7819 3 4.5762v2.4238h4v-2.4199c1.8213-.7949 2.999-2.5929 3-4.5801 0-2.7614-2.2386-5-5-5zm0 2v6c-1.6569 0-3-1.3431-3-3s1.3431-3 3-3zm-1 11v1h2v-1z" fill="#8da5f3" fill-opacity=".98824" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/LightmapGI.svg b/editor/icons/LightmapGI.svg
new file mode 100644
index 0000000000..78f0a64a7b
--- /dev/null
+++ b/editor/icons/LightmapGI.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1v2h12v-2zm-1 3v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-9zm2 1h1v1h-1zm3 0h1v1h-1zm3 0h1v1h-1zm3 0h1v1h-1zm-9 2h10v6h-10zm3 1v1h4v-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/BakedLightmapData.svg b/editor/icons/LightmapGIData.svg
index f5dcfb618b..f5dcfb618b 100644
--- a/editor/icons/BakedLightmapData.svg
+++ b/editor/icons/LightmapGIData.svg
diff --git a/editor/icons/LightmapProbe.svg b/editor/icons/LightmapProbe.svg
index bc790d50c1..07f2b41a7c 100644
--- a/editor/icons/LightmapProbe.svg
+++ b/editor/icons/LightmapProbe.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 9h3v-2h-3zm2.050781 2.535156 1.414063 1.414063 1.414062-1.414063-1.414062-1.414062zm0-7.070312 1.414063 1.414062 1.414062-1.414062-1.414062-1.414063zm1.949219 3.535156c0 1.6569 1.3432 3 3 3s3-1.3431 3-3-1.3432-3-3-3-3 1.3431-3 3zm3 7c3.865993 0 7-3.134007 7-7s-3.134007-7-7-7v2.333984c2.577329 0 4.666016 2.088687 4.666016 4.666016s-2.088687 4.666016-4.666016 4.666016z" fill="#fc9c9c" fill-opacity=".996078" stroke-width="1.16667"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 9h3v-2h-3zm2.050781 2.535156 1.414063 1.414063 1.414062-1.414063-1.414062-1.414062zm0-7.070312 1.414063 1.414062 1.414062-1.414062-1.414062-1.414063zm1.949219 3.535156c0 1.6569 1.3432 3 3 3s3-1.3431 3-3-1.3432-3-3-3-3 1.3431-3 3zm3 7c3.865993 0 7-3.134007 7-7s-3.134007-7-7-7v2.333984c2.577329 0 4.666016 2.088687 4.666016 4.666016s-2.088687 4.666016-4.666016 4.666016z" fill="#fc7f7f" fill-opacity=".996078" stroke-width="1.16667"/></svg>
diff --git a/editor/icons/Line2D.svg b/editor/icons/Line2D.svg
index a0f9d1e33c..e9e70af5c7 100644
--- a/editor/icons/Line2D.svg
+++ b/editor/icons/Line2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1045.4 3 4 3-10 3 6 3-2" fill="none" stroke="#a5b7f3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1045.4 3 4 3-10 3 6 3-2" fill="none" stroke="#8da5f3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/LineEdit.svg b/editor/icons/LineEdit.svg
index 54e3190259..168836a432 100644
--- a/editor/icons/LineEdit.svg
+++ b/editor/icons/LineEdit.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 4v5h2v-5zm-1 7c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2h-2-10z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 4v5h2v-5zm-1 7c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2h-2-10z" fill="#8eef97"/></svg>
diff --git a/editor/icons/LinkButton.svg b/editor/icons/LinkButton.svg
index 3a99d241c3..a3d29e82e8 100644
--- a/editor/icons/LinkButton.svg
+++ b/editor/icons/LinkButton.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 3a5 5 0 0 0 -4.3301 2.5 5 5 0 0 0 0 5 5 5 0 0 0 4.3301 2.5h1v-2h-1a3 3 0 0 1 -3-3 3 3 0 0 1 3-3h1v-2zm3 0v2h1a3 3 0 0 1 3 3 3 3 0 0 1 -3 3h-1v2h1a5 5 0 0 0 4.3301-2.5 5 5 0 0 0 0-5 5 5 0 0 0 -4.3301-2.5zm-3 4a.99998.99998 0 0 0 -1 1 .99998.99998 0 0 0 1 1h4a.99998.99998 0 0 0 1-1 .99998.99998 0 0 0 -1-1z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 3a5 5 0 0 0 -4.3301 2.5 5 5 0 0 0 0 5 5 5 0 0 0 4.3301 2.5h1v-2h-1a3 3 0 0 1 -3-3 3 3 0 0 1 3-3h1v-2zm3 0v2h1a3 3 0 0 1 3 3 3 3 0 0 1 -3 3h-1v2h1a5 5 0 0 0 4.3301-2.5 5 5 0 0 0 0-5 5 5 0 0 0 -4.3301-2.5zm-3 4a.99998.99998 0 0 0 -1 1 .99998.99998 0 0 0 1 1h4a.99998.99998 0 0 0 1-1 .99998.99998 0 0 0 -1-1z" fill="#8eef97"/></svg>
diff --git a/editor/icons/Listener3D.svg b/editor/icons/Listener3D.svg
index 7afbdccd43..c068474d17 100644
--- a/editor/icons/Listener3D.svg
+++ b/editor/icons/Listener3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a5 5 0 0 0 -5 5h2a3 3 0 0 1 3-3 3 3 0 0 1 3 3c0 1.75-.54175 2.3583-1.1406 2.8574-.29944.2495-.62954.44071-.97656.69141-.17351.1253-.35729.26529-.53711.49219-.17982.227-.3457.58398-.3457.95898 0 1.2778-.31632 1.5742-.63867 1.7676-.32236.1934-.86133.23242-1.3613.23242h-1v2h1c.5 0 1.461.038922 2.3887-.51758.87316-.5239 1.4826-1.6633 1.5566-3.2266.011365-.0098.027247-.024684.10938-.083984.21547-.1556.63537-.40194 1.0859-.77734.90112-.751 1.8594-2.1445 1.8594-4.3945a5 5 0 0 0 -5-5zm7.9277 1-1.7383 1.0039a6 6 0 0 1 .81055 2.9961 6 6 0 0 1 -.80859 2.998l1.7363 1.002a8 8 0 0 0 0-8z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a5 5 0 0 0 -5 5h2a3 3 0 0 1 3-3 3 3 0 0 1 3 3c0 1.75-.54175 2.3583-1.1406 2.8574-.29944.2495-.62954.44071-.97656.69141-.17351.1253-.35729.26529-.53711.49219-.17982.227-.3457.58398-.3457.95898 0 1.2778-.31632 1.5742-.63867 1.7676-.32236.1934-.86133.23242-1.3613.23242h-1v2h1c.5 0 1.461.038922 2.3887-.51758.87316-.5239 1.4826-1.6633 1.5566-3.2266.011365-.0098.027247-.024684.10938-.083984.21547-.1556.63537-.40194 1.0859-.77734.90112-.751 1.8594-2.1445 1.8594-4.3945a5 5 0 0 0 -5-5zm7.9277 1-1.7383 1.0039a6 6 0 0 1 .81055 2.9961 6 6 0 0 1 -.80859 2.998l1.7363 1.002a8 8 0 0 0 0-8z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/MarginContainer.svg b/editor/icons/MarginContainer.svg
index 82e72c0da9..6c6f1271d1 100644
--- a/editor/icons/MarginContainer.svg
+++ b/editor/icons/MarginContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#a5efac" transform="translate(0 -1036.4)"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10z" transform="translate(0 1036.4)"/><path d="m4 1042.4v4l2-2z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#8eef97" transform="translate(0 -1036.4)"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10z" transform="translate(0 1036.4)"/><path d="m4 1042.4v4l2-2z"/></g></svg>
diff --git a/editor/icons/MenuButton.svg b/editor/icons/MenuButton.svg
index ca129baced..cb1d9e8382 100644
--- a/editor/icons/MenuButton.svg
+++ b/editor/icons/MenuButton.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v4h14v-4zm5 1h4l-2 2zm-4 4a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-7a1 1 0 0 0 -1-1zm1 2h10v2h-10zm0 3h10v2h-10z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v4h14v-4zm5 1h4l-2 2zm-4 4a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-7a1 1 0 0 0 -1-1zm1 2h10v2h-10zm0 3h10v2h-10z" fill="#8eef97"/></svg>
diff --git a/editor/icons/Mesh.svg b/editor/icons/Mesh.svg
index c02d5d0613..a1743e4c58 100644
--- a/editor/icons/Mesh.svg
+++ b/editor/icons/Mesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.0312-1.75h.03125v-6.5215a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm2.4141 3h5.8574a2 2 0 0 0 .72852.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141 6.5859 6.5859h-5.8574a2 2 0 0 0 -.72852-.73047v-5.8555z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.0312-1.75h.03125v-6.5215a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm2.4141 3h5.8574a2 2 0 0 0 .72852.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141 6.5859 6.5859h-5.8574a2 2 0 0 0 -.72852-.73047v-5.8555z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/MeshInstance2D.svg b/editor/icons/MeshInstance2D.svg
index b8df0768d2..8f6de06252 100644
--- a/editor/icons/MeshInstance2D.svg
+++ b/editor/icons/MeshInstance2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.0312-1.75h.03125v-6.5215a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm2.4141 3h5.8574a2 2 0 0 0 .72852.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141 6.5859 6.5859h-5.8574a2 2 0 0 0 -.72852-.73047v-5.8555z" fill="#a5b7f3"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.0312-1.75h.03125v-6.5215a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm2.4141 3h5.8574a2 2 0 0 0 .72852.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141 6.5859 6.5859h-5.8574a2 2 0 0 0 -.72852-.73047v-5.8555z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/MeshInstance3D.svg b/editor/icons/MeshInstance3D.svg
index aa0cf7740b..a9258505f8 100644
--- a/editor/icons/MeshInstance3D.svg
+++ b/editor/icons/MeshInstance3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.0312-1.75h.03125v-6.5215a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm2.4141 3h5.8574a2 2 0 0 0 .72852.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141 6.5859 6.5859h-5.8574a2 2 0 0 0 -.72852-.73047v-5.8555z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.0312-1.75h.03125v-6.5215a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm2.4141 3h5.8574a2 2 0 0 0 .72852.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141 6.5859 6.5859h-5.8574a2 2 0 0 0 -.72852-.73047v-5.8555z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/MeshLibrary.svg b/editor/icons/MeshLibrary.svg
index 6e824af177..5d64acd97e 100644
--- a/editor/icons/MeshLibrary.svg
+++ b/editor/icons/MeshLibrary.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h2.2695v-2h-2.2715a2 2 0 0 0 -.72852-.73047v-5.8555l3 3v-.41406a2.0002 2.0002 0 0 1 .80859-1.6055l-2.3945-2.3945h5.8574a2 2 0 0 0 .72852.73047v1.2695a2.0002 2.0002 0 0 1 .99805.27148 2.0002 2.0002 0 0 1 1.002-.27148v-1.2715a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm6 7v1 5 1h5c.55228 0 1-.4477 1-1v-5c0-.5523-.44772-1-1-1v4l-1-1-1 1v-4z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h2.2695v-2h-2.2715a2 2 0 0 0 -.72852-.73047v-5.8555l3 3v-.41406a2.0002 2.0002 0 0 1 .80859-1.6055l-2.3945-2.3945h5.8574a2 2 0 0 0 .72852.73047v1.2695a2.0002 2.0002 0 0 1 .99805.27148 2.0002 2.0002 0 0 1 1.002-.27148v-1.2715a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm6 7v1 5 1h5c.55228 0 1-.4477 1-1v-5c0-.5523-.44772-1-1-1v4l-1-1-1 1v-4z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/MiniObject.svg b/editor/icons/MiniObject.svg
index b4a336923d..7fe3b773d6 100644
--- a/editor/icons/MiniObject.svg
+++ b/editor/icons/MiniObject.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2v8h2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2zm0 5a3 3 0 0 0 -3-3 3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3zm7-3v5a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3-3v-5zm-10 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#79f3e8"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2v8h2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2zm0 5a3 3 0 0 0 -3-3 3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3zm7-3v5a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3-3v-5zm-10 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#55f3e3"/></svg>
diff --git a/editor/icons/MovePoint.svg b/editor/icons/MovePoint.svg
index 03b15e47b5..a5d728e6dd 100644
--- a/editor/icons/MovePoint.svg
+++ b/editor/icons/MovePoint.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 1.2129-.10742l-2.5996-6.3203a1.5002 1.5002 0 0 1 1.3711-2.0703v-.0019531a1.5002 1.5002 0 0 1 .58594.11133l6.3184 2.5996a7 7 0 0 0 .11133-1.2109 7 7 0 0 0 -7-7zm2.7559 9.7559.52344 1.2734a1.5002 1.5002 0 0 1 .48047-.26953 1.5002 1.5002 0 0 1 .26953-.47852l-1.2734-.52539z" fill="#fff" transform="translate(0 1036.4)"/><path d="m8 3a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 .42578-.021484l-1.8125-4.4063a1.5002 1.5002 0 0 1 1.3711-2.0703v-.0019531a1.5002 1.5002 0 0 1 .58594.11133l4.4082 1.8125a5 5 0 0 0 .021484-.42383 5 5 0 0 0 -5-5zm2.7559 7.7559.44336 1.0801a5 5 0 0 0 .63867-.63281l-1.082-.44727z" fill="#ff8484" transform="translate(0 1036.4)"/><path d="m16 1047.7-8-3.291 3.291 8 .9471-2.8201 1.8836 1.8835.9418-.9418-1.8836-1.8835z" fill="#e0e0e0"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 1.2129-.10742l-2.5996-6.3203a1.5002 1.5002 0 0 1 1.3711-2.0703v-.0019531a1.5002 1.5002 0 0 1 .58594.11133l6.3184 2.5996a7 7 0 0 0 .11133-1.2109 7 7 0 0 0 -7-7zm2.7559 9.7559.52344 1.2734a1.5002 1.5002 0 0 1 .48047-.26953 1.5002 1.5002 0 0 1 .26953-.47852l-1.2734-.52539z" fill="#fff" transform="translate(0 1036.4)"/><path d="m8 3a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 .42578-.021484l-1.8125-4.4063a1.5002 1.5002 0 0 1 1.3711-2.0703v-.0019531a1.5002 1.5002 0 0 1 .58594.11133l4.4082 1.8125a5 5 0 0 0 .021484-.42383 5 5 0 0 0 -5-5zm2.7559 7.7559.44336 1.0801a5 5 0 0 0 .63867-.63281l-1.082-.44727z" fill="#ff5f5f" transform="translate(0 1036.4)"/><path d="m16 1047.7-8-3.291 3.291 8 .9471-2.8201 1.8836 1.8835.9418-.9418-1.8836-1.8835z" fill="#e0e0e0"/></g></svg>
diff --git a/editor/icons/MultiMesh.svg b/editor/icons/MultiMesh.svg
index 6ee638db4c..5b4900841f 100644
--- a/editor/icons/MultiMesh.svg
+++ b/editor/icons/MultiMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h1.2695v-2h-1.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c.17532.30158.42647.55205.72852.72656v1.2734h2v-1.2695c.61831-.35698.99944-1.0165 1-1.7305 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h1.2695v-2h-1.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c.17532.30158.42647.55205.72852.72656v1.2734h2v-1.2695c.61831-.35698.99944-1.0165 1-1.7305 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/MultiMeshInstance2D.svg b/editor/icons/MultiMeshInstance2D.svg
index 07c72aeed1..253a43bf55 100644
--- a/editor/icons/MultiMeshInstance2D.svg
+++ b/editor/icons/MultiMeshInstance2D.svg
@@ -1 +1 @@
-<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m-1-1h582v402h-582z" fill="none"/><path d="m3 1c-1.1046 0-2 .89543-2 2 .00056.71397.38169 1.3735 1 1.7305v6.541c-.61771.35664-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.00056 1.3735-.38169 1.7305-1h1.2695v-2h-1.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c.17532.30158.42647.55205.72852.72656v1.2734h2v-1.2695c.61831-.35698.99944-1.0165 1-1.7305 0-1.1046-.89543-2-2-2-.71397.00056-1.3735.38169-1.7305 1h-6.541c-.35664-.61771-1.0152-.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#a5b7f3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></svg>
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m-1-1h582v402h-582z" fill="none"/><path d="m3 1c-1.1046 0-2 .89543-2 2 .00056.71397.38169 1.3735 1 1.7305v6.541c-.61771.35664-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.00056 1.3735-.38169 1.7305-1h1.2695v-2h-1.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c.17532.30158.42647.55205.72852.72656v1.2734h2v-1.2695c.61831-.35698.99944-1.0165 1-1.7305 0-1.1046-.89543-2-2-2-.71397.00056-1.3735.38169-1.7305 1h-6.541c-.35664-.61771-1.0152-.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#8da5f3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></svg>
diff --git a/editor/icons/MultiMeshInstance3D.svg b/editor/icons/MultiMeshInstance3D.svg
index 61d728c4be..3ccd2c9cbe 100644
--- a/editor/icons/MultiMeshInstance3D.svg
+++ b/editor/icons/MultiMeshInstance3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h1.2695v-2h-1.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c.17532.30158.42647.55205.72852.72656v1.2734h2v-1.2695c.61831-.35698.99944-1.0165 1-1.7305 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h1.2695v-2h-1.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c.17532.30158.42647.55205.72852.72656v1.2734h2v-1.2695c.61831-.35698.99944-1.0165 1-1.7305 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/Navigation2D.svg b/editor/icons/Navigation2D.svg
index 6725400e92..aa3e258eae 100644
--- a/editor/icons/Navigation2D.svg
+++ b/editor/icons/Navigation2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1050.4 5-2 5 2-5-12z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1050.4 5-2 5 2-5-12z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/Navigation3D.svg b/editor/icons/Navigation3D.svg
index 74c8e204a3..646500d9ed 100644
--- a/editor/icons/Navigation3D.svg
+++ b/editor/icons/Navigation3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1050.4 5-2 5 2-5-12z" fill="#fc9c9c" fill-opacity=".99608" fill-rule="evenodd" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1050.4 5-2 5 2-5-12z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/NavigationMesh.svg b/editor/icons/NavigationMesh.svg
index 45bc51ac31..c5f16596a6 100644
--- a/editor/icons/NavigationMesh.svg
+++ b/editor/icons/NavigationMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h2.5078l.75-2h-3.2598a2 2 0 0 0 -.72852-.73047v-5.8555l4.6973 4.6973.77148-2.0566-4.0547-4.0547h5.8574a2 2 0 0 0 .72852.73047v.27148a2.0002 2.0002 0 0 1 .023438 0 2.0002 2.0002 0 0 1 1.8496 1.2969l.12695.33789v-1.9082a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm9 6-3 8 3-2 3 2z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h2.5078l.75-2h-3.2598a2 2 0 0 0 -.72852-.73047v-5.8555l4.6973 4.6973.77148-2.0566-4.0547-4.0547h5.8574a2 2 0 0 0 .72852.73047v.27148a2.0002 2.0002 0 0 1 .023438 0 2.0002 2.0002 0 0 1 1.8496 1.2969l.12695.33789v-1.9082a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285-1zm9 6-3 8 3-2 3 2z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/NavigationRegion2D.svg b/editor/icons/NavigationRegion2D.svg
index 3ec0938417..8efd836075 100644
--- a/editor/icons/NavigationRegion2D.svg
+++ b/editor/icons/NavigationRegion2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.1339223.0000569-.2535666.0306675-.3652344.0742188-.022275.0088111-.0410424.0209185-.0625.03125-.0889622.0424668-.1681009.0954994-.2382812.1601562-.0215322.0195204-.0427394.0372854-.0625.0585938-.0741112.0810923-.13722.1698052-.1816406.2695312-.0034324.0076504-.0084746.0137334-.0117188.0214844l-.0019531.0019531c-.0452252.1091882-.0629923.2268973-.0683594.3457031-.0005086.0130821-.0078112.023903-.0078125.0371094v12c.0000552.552262.4477381.999945 1 1h4.8847656a2.1184381 2.1184381 0 0 1 .1328125-.744141l2.9999999-7.9999996a2.1184381 2.1184381 0 0 1 2.007813-1.3730469 2.1184381 2.1184381 0 0 1 1.957031 1.3730469l1.017578 2.7128906v-6.96875c-.000001-.0132064-.007305-.0240273-.007812-.0371094-.005369-.1188058-.023135-.2365149-.06836-.3457031l-.001953-.0019531c-.003155-.0075626-.008384-.0139987-.011719-.0214844-.044421-.099726-.107529-.188439-.18164-.2695312-.019761-.0213083-.040968-.0390734-.0625-.0585938-.070181-.0646568-.149319-.1176895-.238282-.1601562-.021457-.0103315-.040225-.022439-.0625-.03125-.111667-.0435511-.231312-.0741619-.365234-.0742188zm10 6-3 8 3-2 3 2z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.1339223.0000569-.2535666.0306675-.3652344.0742188-.022275.0088111-.0410424.0209185-.0625.03125-.0889622.0424668-.1681009.0954994-.2382812.1601562-.0215322.0195204-.0427394.0372854-.0625.0585938-.0741112.0810923-.13722.1698052-.1816406.2695312-.0034324.0076504-.0084746.0137334-.0117188.0214844l-.0019531.0019531c-.0452252.1091882-.0629923.2268973-.0683594.3457031-.0005086.0130821-.0078112.023903-.0078125.0371094v12c.0000552.552262.4477381.999945 1 1h4.8847656a2.1184381 2.1184381 0 0 1 .1328125-.744141l2.9999999-7.9999996a2.1184381 2.1184381 0 0 1 2.007813-1.3730469 2.1184381 2.1184381 0 0 1 1.957031 1.3730469l1.017578 2.7128906v-6.96875c-.000001-.0132064-.007305-.0240273-.007812-.0371094-.005369-.1188058-.023135-.2365149-.06836-.3457031l-.001953-.0019531c-.003155-.0075626-.008384-.0139987-.011719-.0214844-.044421-.099726-.107529-.188439-.18164-.2695312-.019761-.0213083-.040968-.0390734-.0625-.0585938-.070181-.0646568-.149319-.1176895-.238282-.1601562-.021457-.0103315-.040225-.022439-.0625-.03125-.111667-.0435511-.231312-.0741619-.365234-.0742188zm10 6-3 8 3-2 3 2z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/NavigationRegion3D.svg b/editor/icons/NavigationRegion3D.svg
index 7a899dbc80..39b6d0ca13 100644
--- a/editor/icons/NavigationRegion3D.svg
+++ b/editor/icons/NavigationRegion3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.1339223.0000569-.2535666.030668-.3652344.074219-.022275.00881-.041042.020919-.0625.03125-.088962.042467-.1681009.095499-.2382812.1601562-.021532.01952-.042739.037285-.0625.058594-.074111.081092-.13722.1698052-.1816406.2695312-.00343.00765-.00847.013733-.011719.021484l-.00195.00195c-.0452281.1091913-.0629952.2269004-.0683623.3457062-.0005086.0130821-.0078112.023903-.0078125.0371094v12c.0000552.552262.4477381.999945 1 1h4.8847656a2.1184381 2.1184381 0 0 1 .1328125-.744141l2.9999999-7.9999996a2.1184381 2.1184381 0 0 1 2.007813-1.3730469 2.1184381 2.1184381 0 0 1 1.957031 1.3730469l1.017578 2.7128906v-6.96875c-.000001-.013206-.0073-.024027-.0078-.037109-.0054-.1188058-.02313-.2365149-.06836-.3457031l-.002-.00195c-.0032-.00756-.0084-.013999-.01172-.021484-.04442-.099726-.107529-.188439-.18164-.2695312-.01976-.021308-.04097-.039073-.0625-.058594-.07018-.064657-.149319-.1176895-.238282-.1601562-.02146-.010331-.04022-.022439-.0625-.03125-.111631-.0435548-.231276-.0741656-.365198-.0742225zm10 6-3 8 3-2 3 2z" fill="#fc9c9c" fill-opacity=".996078" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.1339223.0000569-.2535666.030668-.3652344.074219-.022275.00881-.041042.020919-.0625.03125-.088962.042467-.1681009.095499-.2382812.1601562-.021532.01952-.042739.037285-.0625.058594-.074111.081092-.13722.1698052-.1816406.2695312-.00343.00765-.00847.013733-.011719.021484l-.00195.00195c-.0452281.1091913-.0629952.2269004-.0683623.3457062-.0005086.0130821-.0078112.023903-.0078125.0371094v12c.0000552.552262.4477381.999945 1 1h4.8847656a2.1184381 2.1184381 0 0 1 .1328125-.744141l2.9999999-7.9999996a2.1184381 2.1184381 0 0 1 2.007813-1.3730469 2.1184381 2.1184381 0 0 1 1.957031 1.3730469l1.017578 2.7128906v-6.96875c-.000001-.013206-.0073-.024027-.0078-.037109-.0054-.1188058-.02313-.2365149-.06836-.3457031l-.002-.00195c-.0032-.00756-.0084-.013999-.01172-.021484-.04442-.099726-.107529-.188439-.18164-.2695312-.01976-.021308-.04097-.039073-.0625-.058594-.07018-.064657-.149319-.1176895-.238282-.1601562-.02146-.010331-.04022-.022439-.0625-.03125-.111631-.0435548-.231276-.0741656-.365198-.0742225zm10 6-3 8 3-2 3 2z" fill="#fc7f7f" fill-opacity=".996078" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/New.svg b/editor/icons/New.svg
index efc897cb4f..1667f46075 100644
--- a/editor/icons/New.svg
+++ b/editor/icons/New.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.400017)"><path d="m2 1v14h8v-1h-2v-4h2v-2h4v-2h-5v-5zm8 0v4h4z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m11 1045.4v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#84ffb1"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.400017)"><path d="m2 1v14h8v-1h-2v-4h2v-2h4v-2h-5v-5zm8 0v4h4z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m11 1045.4v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/></g></svg>
diff --git a/editor/icons/NewRoot.svg b/editor/icons/NewRoot.svg
index 061ff6043a..df3d590d01 100644
--- a/editor/icons/NewRoot.svg
+++ b/editor/icons/NewRoot.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 4.7813475v2.0494746c-.6177049.3566305-.998733 1.0152377-1 1.7285 0 1.1045694.8954305 1.9999999 2 1.9999999.7139771-.000554 1.3735116-.381678 1.7305-.9999995h1.3545593c.3566306.6177035 1.0152377.9987325 1.7285.9999995 1.1045696 0 1.9999996-.8954305 1.9999996-1.9999999 0-1.1045695-.89543-2-1.9999996-2-.7139771.0005537-1.3735116.3816774-1.7305 1h-1.3545593c-.1747809-.3030102-.4259781-.5548798-.72852-.73047v-2.0494746c-.5384713.0290292-1.2982621.0368063-1.99998.00197z" fill="#e0e0e0"/><path d="m6.8474576 9.6288045v1.2020165c-.617705.35663-.998733 1.015237-1 1.7285 0 1.104569.89543 2 2 2 .713977-.000554 1.373512-.381678 1.7305-1h1.2867634c.35663.617704 1.015237.998733 1.7285 1 1.104569 0 1.999999-.895431 1.999999-2 0-1.10457-.89543-2-1.999999-2-.713977.000553-1.373512.381677-1.7305 1h-1.2867634c-.174781-.303011-.425978-.55488-.72852-.73047v-1.2020165s-1.264363.03681-1.99998.002z" fill="#e0e0e0"/><path d="m2.7966098 1.3559322c-1.104569 0-2.00000003.8954305-2.00000003 2 .000554.7139771.38167803 1.3735116 1.00000003 1.7305.757716.266212.949133.2840609 1.99998-.00197.617705-.3566306.998733-1.0152377 1-1.7285 0-1.1045695-.89543-2-2-2z" fill="#84ffb1"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 4.7813475v2.0494746c-.6177049.3566305-.998733 1.0152377-1 1.7285 0 1.1045694.8954305 1.9999999 2 1.9999999.7139771-.000554 1.3735116-.381678 1.7305-.9999995h1.3545593c.3566306.6177035 1.0152377.9987325 1.7285.9999995 1.1045696 0 1.9999996-.8954305 1.9999996-1.9999999 0-1.1045695-.89543-2-1.9999996-2-.7139771.0005537-1.3735116.3816774-1.7305 1h-1.3545593c-.1747809-.3030102-.4259781-.5548798-.72852-.73047v-2.0494746c-.5384713.0290292-1.2982621.0368063-1.99998.00197z" fill="#e0e0e0"/><path d="m6.8474576 9.6288045v1.2020165c-.617705.35663-.998733 1.015237-1 1.7285 0 1.104569.89543 2 2 2 .713977-.000554 1.373512-.381678 1.7305-1h1.2867634c.35663.617704 1.015237.998733 1.7285 1 1.104569 0 1.999999-.895431 1.999999-2 0-1.10457-.89543-2-1.999999-2-.713977.000553-1.373512.381677-1.7305 1h-1.2867634c-.174781-.303011-.425978-.55488-.72852-.73047v-1.2020165s-1.264363.03681-1.99998.002z" fill="#e0e0e0"/><path d="m2.7966098 1.3559322c-1.104569 0-2.00000003.8954305-2.00000003 2 .000554.7139771.38167803 1.3735116 1.00000003 1.7305.757716.266212.949133.2840609 1.99998-.00197.617705-.3566306.998733-1.0152377 1-1.7285 0-1.1045695-.89543-2-2-2z" fill="#5fff97"/></svg>
diff --git a/editor/icons/NinePatchRect.svg b/editor/icons/NinePatchRect.svg
index d857b71a46..56ed224f98 100644
--- a/editor/icons/NinePatchRect.svg
+++ b/editor/icons/NinePatchRect.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#a5efac" transform="translate(0 -1036.4)"><path d="m1 1037.4h2v14h-2z"/><path d="m1 1049.4h14v2h-14z"/><path d="m1 1037.4h14v2h-14z"/><path d="m13 1037.4h2v14h-2z"/><path d="m1 1041.4h14v.99998h-14z"/><path d="m1 1046.4h14v.99998h-14z"/><g transform="rotate(90)"><path d="m1037.4-6h14v.99998h-14z"/><path d="m1037.4-11h14v.99998h-14z"/></g></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#8eef97" transform="translate(0 -1036.4)"><path d="m1 1037.4h2v14h-2z"/><path d="m1 1049.4h14v2h-14z"/><path d="m1 1037.4h14v2h-14z"/><path d="m13 1037.4h2v14h-2z"/><path d="m1 1041.4h14v.99998h-14z"/><path d="m1 1046.4h14v.99998h-14z"/><g transform="rotate(90)"><path d="m1037.4-6h14v.99998h-14z"/><path d="m1037.4-11h14v.99998h-14z"/></g></g></svg>
diff --git a/editor/icons/Node2D.svg b/editor/icons/Node2D.svg
index 7f27e0695f..a47399df92 100644
--- a/editor/icons/Node2D.svg
+++ b/editor/icons/Node2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#a5b7f3"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/Node3D.svg b/editor/icons/Node3D.svg
index 56f6ed5542..c8a3163e51 100644
--- a/editor/icons/Node3D.svg
+++ b/editor/icons/Node3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/NodePath.svg b/editor/icons/NodePath.svg
index 3ecb830bec..14c753a136 100644
--- a/editor/icons/NodePath.svg
+++ b/editor/icons/NodePath.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2v8h2v-2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3zm6 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-1h2v-2h-2v-2zm5 0v8h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3v-2zm-9 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#6993ec"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2v8h2v-2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3zm6 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-1h2v-2h-2v-2zm5 0v8h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3v-2zm-9 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z" fill="#417aec"/></svg>
diff --git a/editor/icons/Occluder3D.svg b/editor/icons/Occluder3D.svg
new file mode 100644
index 0000000000..850e2651af
--- /dev/null
+++ b/editor/icons/Occluder3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.90625 1a7 7 0 0 0 -1.2988281.1386719 4.5 4.5 0 0 1 3.3925781 4.3613281 4.5 4.5 0 0 1 -4.5 4.5 4.5 4.5 0 0 1 -4.359375-3.3886719 7 7 0 0 0 -.140625 1.3886719 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7 7 7 0 0 0 -.09375 0z" fill="#ffca5f" stroke-width=".365215"/></svg>
diff --git a/editor/icons/OccluderInstance3D.svg b/editor/icons/OccluderInstance3D.svg
new file mode 100644
index 0000000000..cc7ccc410f
--- /dev/null
+++ b/editor/icons/OccluderInstance3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.90625 1a7 7 0 0 0 -1.2988281.1386719 4.5 4.5 0 0 1 3.3925781 4.3613281 4.5 4.5 0 0 1 -4.5 4.5 4.5 4.5 0 0 1 -4.359375-3.3886719 7 7 0 0 0 -.140625 1.3886719 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7 7 7 0 0 0 -.09375 0z" fill="#fc7f7f" fill-opacity=".996078" stroke-width=".365215"/></svg>
diff --git a/editor/icons/OccluderPolygon2D.svg b/editor/icons/OccluderPolygon2D.svg
index cdceb16441..ae5d2f4a1d 100644
--- a/editor/icons/OccluderPolygon2D.svg
+++ b/editor/icons/OccluderPolygon2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd" transform="translate(0 -1036.4)"><path d="m1 1045.4 6 6h8v-8l-6-6h-8z" fill="#3552b1"/><path d="m1 1037.4h8l-3 4 3 4h-8z" fill="#a5b7f3" fill-opacity=".98824"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd" transform="translate(0 -1036.4)"><path d="m1 1045.4 6 6h8v-8l-6-6h-8z" fill="#3552b1"/><path d="m1 1037.4h8l-3 4 3 4h-8z" fill="#8da5f3" fill-opacity=".98824"/></g></svg>
diff --git a/editor/icons/OmniLight3D.svg b/editor/icons/OmniLight3D.svg
index 06b3786ebe..391e9104a1 100644
--- a/editor/icons/OmniLight3D.svg
+++ b/editor/icons/OmniLight3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 5 0 0 0 -5 5 5 5 0 0 0 3 4.5762v2.4238h4v-2.4199a5 5 0 0 0 3-4.5801 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3zm-1 11v1h2v-1z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 5 0 0 0 -5 5 5 5 0 0 0 3 4.5762v2.4238h4v-2.4199a5 5 0 0 0 3-4.5801 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3zm-1 11v1h2v-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/OptionButton.svg b/editor/icons/OptionButton.svg
index 50e6fae218..0a07470618 100644
--- a/editor/icons/OptionButton.svg
+++ b/editor/icons/OptionButton.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 3c-1.1046 0-2 .89543-2 2v6c0 1.1046.89543 2 2 2h5 1 1 2 1c1.1046 0 2-.89543 2-2v-6c0-1.1046-.89543-2-2-2h-1-2-1-1zm8 2.9863a1.0001 1.0001 0 0 1 .7168 1.7207l-3 3a1.0001 1.0001 0 0 1 -1.4141 0l-3-3a1.0001 1.0001 0 0 1 .69727-1.7168 1.0001 1.0001 0 0 1 .7168.30273l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 .69727-.30664z" fill="#a5efac" transform="translate(0 1036.4)"/><path d="m4 1042.4h4v4h-4z" fill="none"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 3c-1.1046 0-2 .89543-2 2v6c0 1.1046.89543 2 2 2h5 1 1 2 1c1.1046 0 2-.89543 2-2v-6c0-1.1046-.89543-2-2-2h-1-2-1-1zm8 2.9863a1.0001 1.0001 0 0 1 .7168 1.7207l-3 3a1.0001 1.0001 0 0 1 -1.4141 0l-3-3a1.0001 1.0001 0 0 1 .69727-1.7168 1.0001 1.0001 0 0 1 .7168.30273l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 .69727-.30664z" fill="#8eef97" transform="translate(0 1036.4)"/><path d="m4 1042.4h4v4h-4z" fill="none"/></g></svg>
diff --git a/editor/icons/PackedColorArray.svg b/editor/icons/PackedColorArray.svg
index 206819ffb6..588002f188 100644
--- a/editor/icons/PackedColorArray.svg
+++ b/editor/icons/PackedColorArray.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m6 3.5a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2z" fill="#ff7070"/><path d="m13 3.5a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1z" fill="#70bfff"/><path d="m7 1.5v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5z" fill="#7aff70"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m6 3.5a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2z" fill="#ff4545"/><path d="m13 3.5a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1z" fill="#70bfff"/><path d="m7 1.5v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5z" fill="#7aff70"/></svg>
diff --git a/editor/icons/PackedFloat32Array.svg b/editor/icons/PackedFloat32Array.svg
index 503b0e7b6f..ccfbb748b7 100644
--- a/editor/icons/PackedFloat32Array.svg
+++ b/editor/icons/PackedFloat32Array.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m6 2a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1-1zm1 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5zm3 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2z" fill="#61daf4"/><path d="m7 2v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m6 2a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1-1zm1 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5zm3 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2z" fill="#35d4f4"/><path d="m7 2v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/PackedFloat64Array.svg b/editor/icons/PackedFloat64Array.svg
index 503b0e7b6f..ccfbb748b7 100644
--- a/editor/icons/PackedFloat64Array.svg
+++ b/editor/icons/PackedFloat64Array.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m6 2a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1-1zm1 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5zm3 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2z" fill="#61daf4"/><path d="m7 2v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m6 2a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1-1zm1 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5zm3 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2z" fill="#35d4f4"/><path d="m7 2v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/PackedInt32Array.svg b/editor/icons/PackedInt32Array.svg
index a1dc417c11..973e4b9ab2 100644
--- a/editor/icons/PackedInt32Array.svg
+++ b/editor/icons/PackedInt32Array.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m3 2v2h2v-2zm2 2v2h-2v4h4v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3zm5 3a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2h-2z" fill="#7dc6ef"/><path d="m5 4v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m3 2v2h2v-2zm2 2v2h-2v4h4v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3zm5 3a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2h-2z" fill="#5abbef"/><path d="m5 4v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/PackedInt64Array.svg b/editor/icons/PackedInt64Array.svg
index a1dc417c11..973e4b9ab2 100644
--- a/editor/icons/PackedInt64Array.svg
+++ b/editor/icons/PackedInt64Array.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m3 2v2h2v-2zm2 2v2h-2v4h4v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3zm5 3a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2h-2z" fill="#7dc6ef"/><path d="m5 4v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m3 2v2h2v-2zm2 2v2h-2v4h4v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3zm5 3a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2h-2z" fill="#5abbef"/><path d="m5 4v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/PackedStringArray.svg b/editor/icons/PackedStringArray.svg
index e9285e2192..5273d6bc56 100644
--- a/editor/icons/PackedStringArray.svg
+++ b/editor/icons/PackedStringArray.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m7 2a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3-3v-2a1 1 0 0 1 1-1h1v3a3 3 0 0 0 3 3h2v-3a1 1 0 0 1 1-1v-2a3 3 0 0 0 -3 3v1a1 1 0 0 1 -1-1v-1h1v-2h-1v-2h-2z" fill="#6ba7ec"/><path d="m8 2v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m7 2a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3-3v-2a1 1 0 0 1 1-1h1v3a3 3 0 0 0 3 3h2v-3a1 1 0 0 1 1-1v-2a3 3 0 0 0 -3 3v1a1 1 0 0 1 -1-1v-1h1v-2h-1v-2h-2z" fill="#4593ec"/><path d="m8 2v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/PackedVector2Array.svg b/editor/icons/PackedVector2Array.svg
index a5c8921045..f7e23b800f 100644
--- a/editor/icons/PackedVector2Array.svg
+++ b/editor/icons/PackedVector2Array.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m9 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.0019531v2h5v-2h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5zm-6 1v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4z" fill="#bd91f1"/><path d="m9 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.00195v2.0001h5v-2h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5001z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m9 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.0019531v2h5v-2h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5zm-6 1v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4z" fill="#ac73f1"/><path d="m9 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.00195v2.0001h5v-2h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5001z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/PackedVector3Array.svg b/editor/icons/PackedVector3Array.svg
index e1de83908d..e78be63df2 100644
--- a/editor/icons/PackedVector3Array.svg
+++ b/editor/icons/PackedVector3Array.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m8 1v2h2c0 .55228-.44772 1-1 1v2c.55228 0 1 .44772 1 1s-.44772 1-1 1h-1v2h1c1.0716-.0001501 2.0618-.57193 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.10406-.1795-.22646-.34772-.36523-.50195.13856-.15301.26095-.31991.36523-.49805.26209-.45639.3995-.97371.39844-1.5h.003906v-2zm0 2h-2v3c-.0000096.55228-.44772.99999-1 1v-4h-2v6h2c1.6569 0 3-1.3431 3-3z" fill="#e286f0"/><path d="m8 1v2h2c0 .55228-.44772 1-1 1v2c.55228 0 1 .44772 1 1s-.44772 1-1 1h-1v2h1c1.0716-.0001501 2.0618-.57193 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.10406-.1795-.22646-.34772-.36523-.50195.13856-.15301.26095-.31991.36523-.49805.26209-.45639.3995-.97371.39844-1.5h.003906v-2z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v12h4v-2h-2v-8h2v-2zm12 0v2h2v8h-2v2h4v-12z" fill="#e0e0e0"/><path d="m8 1v2h2c0 .55228-.44772 1-1 1v2c.55228 0 1 .44772 1 1s-.44772 1-1 1h-1v2h1c1.0716-.0001501 2.0618-.57193 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.10406-.1795-.22646-.34772-.36523-.50195.13856-.15301.26095-.31991.36523-.49805.26209-.45639.3995-.97371.39844-1.5h.003906v-2zm0 2h-2v3c-.0000096.55228-.44772.99999-1 1v-4h-2v6h2c1.6569 0 3-1.3431 3-3z" fill="#de66f0"/><path d="m8 1v2h2c0 .55228-.44772 1-1 1v2c.55228 0 1 .44772 1 1s-.44772 1-1 1h-1v2h1c1.0716-.0001501 2.0618-.57193 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.10406-.1795-.22646-.34772-.36523-.50195.13856-.15301.26095-.31991.36523-.49805.26209-.45639.3995-.97371.39844-1.5h.003906v-2z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/Panel.svg b/editor/icons/Panel.svg
index f82822c5a1..7a36a35048 100644
--- a/editor/icons/Panel.svg
+++ b/editor/icons/Panel.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/PanelContainer.svg b/editor/icons/PanelContainer.svg
index 017941ba36..2f783d6e49 100644
--- a/editor/icons/PanelContainer.svg
+++ b/editor/icons/PanelContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10z" fill="#8eef97"/></svg>
diff --git a/editor/icons/PanoramaSkyMaterial.svg b/editor/icons/PanoramaSkyMaterial.svg
index 33ffc20351..eddcbfd871 100644
--- a/editor/icons/PanoramaSkyMaterial.svg
+++ b/editor/icons/PanoramaSkyMaterial.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 5v2h8 1c0-.554.446-1 1-1h2c.554 0 1 .446 1 1h1v-2z" fill="#9dff70"/><path d="m1 3v2h14v-2h-1.589844c-2.86436 1.357608-6.9481434 1.30996-10.347656 0z" fill="#ffeb70"/><path d="m1 2v1h2.0625c-.7241713-.2790504-1.419865-.6077805-2.0625-1zm14 0c-.465784.3952185-1.005424.7230054-1.589844 1h1.589844z" fill="#ff7070"/><path d="m1 7v2h2 1 5c-.554 0-1-.446-1-1s.446-1 1-1zm13 0c0 .554-.446 1-1 1h-1c0 .554-.446 1-1 1h4v-2z" fill="#70ffb9"/><path d="m1 9v2h2c-.554 0-1-.446-1-1s.446-1 1-1zm3 0c.554 0 1 .446 1 1s-.446 1-1 1h11v-2h-4-2z" fill="#70deff"/><path d="m1 13v-2h14v2h-1.589844c-2.86436-1.357608-6.9481434-1.30996-10.347656 0z" fill="#9f70ff"/><path d="m1 14v-1h2.0625c-.7241713.27905-1.419865.60778-2.0625 1zm14 0c-.465784-.395219-1.005424-.723005-1.589844-1h1.589844z" fill="#ff70ac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 5v2h8 1c0-.554.446-1 1-1h2c.554 0 1 .446 1 1h1v-2z" fill="#80ff45"/><path d="m1 3v2h14v-2h-1.589844c-2.86436 1.357608-6.9481434 1.30996-10.347656 0z" fill="#ffe345"/><path d="m1 2v1h2.0625c-.7241713-.2790504-1.419865-.6077805-2.0625-1zm14 0c-.465784.3952185-1.005424.7230054-1.589844 1h1.589844z" fill="#ff4545"/><path d="m1 7v2h2 1 5c-.554 0-1-.446-1-1s.446-1 1-1zm13 0c0 .554-.446 1-1 1h-1c0 .554-.446 1-1 1h4v-2z" fill="#45ffa2"/><path d="m1 9v2h2c-.554 0-1-.446-1-1s.446-1 1-1zm3 0c.554 0 1 .446 1 1s-.446 1-1 1h11v-2h-4-2z" fill="#45d7ff"/><path d="m1 13v-2h14v2h-1.589844c-2.86436-1.357608-6.9481434-1.30996-10.347656 0z" fill="#8045ff"/><path d="m1 14v-1h2.0625c-.7241713.27905-1.419865.60778-2.0625 1zm14 0c-.465784-.395219-1.005424-.723005-1.589844-1h1.589844z" fill="#ff4596"/></svg>
diff --git a/editor/icons/ParallaxLayer.svg b/editor/icons/ParallaxLayer.svg
index 64bf68f604..0768e941ad 100644
--- a/editor/icons/ParallaxLayer.svg
+++ b/editor/icons/ParallaxLayer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 1h10c.55228.0000096.99999.44772 1 1v10c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-10c.0000096-.55228.44772-.99999 1-1zm4 3-3 3 3 3zm2 0v6l3-3z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd" transform="translate(0 1036.4)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 1h10c.55228.0000096.99999.44772 1 1v10c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-10c.0000096-.55228.44772-.99999 1-1zm4 3-3 3 3 3zm2 0v6l3-3z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/ParticlesMaterial.svg b/editor/icons/ParticlesMaterial.svg
index f9a25530ef..33598980a5 100644
--- a/editor/icons/ParticlesMaterial.svg
+++ b/editor/icons/ParticlesMaterial.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a4.5 5 0 0 0 -3.5938 2h7.1816a4.5 5 0 0 0 -3.5879-2z" fill="#ff7070"/><path d="m4.4062 3a4.5 5 0 0 0 -.81445 2h8.8105a4.5 5 0 0 0 -.81445-2z" fill="#ffeb70"/><path d="m3.5918 5a4.5 5 0 0 0 -.0058594.03125 3 3 0 0 0 -2.4121 1.9688h13.65a3 3 0 0 0 -2.4141-1.9668 4.5 5 0 0 0 -.007812-.033203h-8.8105z" fill="#9dff70"/><path d="m1.1738 7a3 3 0 0 0 -.17383 1 3 3 0 0 0 .17578 1h13.65a3 3 0 0 0 .17383-1 3 3 0 0 0 -.17578-1z" fill="#70ffb9"/><path d="m1.1758 9a3 3 0 0 0 2.8242 2h8a3 3 0 0 0 2.8262-2h-13.65z" fill="#70deff"/><path d="m3 13a1 1 0 0 0 1 1 1 1 0 0 0 1-1zm5 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm3 0a1 1 0 0 0 1 1 1 1 0 0 0 1-1z" fill="#ff70ac"/><path d="m4 12a1 1 0 0 0 -1 1h2a1 1 0 0 0 -1-1zm8 0a1 1 0 0 0 -1 1h2a1 1 0 0 0 -1-1z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a4.5 5 0 0 0 -3.5938 2h7.1816a4.5 5 0 0 0 -3.5879-2z" fill="#ff4545"/><path d="m4.4062 3a4.5 5 0 0 0 -.81445 2h8.8105a4.5 5 0 0 0 -.81445-2z" fill="#ffe345"/><path d="m3.5918 5a4.5 5 0 0 0 -.0058594.03125 3 3 0 0 0 -2.4121 1.9688h13.65a3 3 0 0 0 -2.4141-1.9668 4.5 5 0 0 0 -.007812-.033203h-8.8105z" fill="#80ff45"/><path d="m1.1738 7a3 3 0 0 0 -.17383 1 3 3 0 0 0 .17578 1h13.65a3 3 0 0 0 .17383-1 3 3 0 0 0 -.17578-1z" fill="#45ffa2"/><path d="m1.1758 9a3 3 0 0 0 2.8242 2h8a3 3 0 0 0 2.8262-2h-13.65z" fill="#45d7ff"/><path d="m3 13a1 1 0 0 0 1 1 1 1 0 0 0 1-1zm5 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm3 0a1 1 0 0 0 1 1 1 1 0 0 0 1-1z" fill="#ff4596"/><path d="m4 12a1 1 0 0 0 -1 1h2a1 1 0 0 0 -1-1zm8 0a1 1 0 0 0 -1 1h2a1 1 0 0 0 -1-1z" fill="#8045ff"/></svg>
diff --git a/editor/icons/Path2D.svg b/editor/icons/Path2D.svg
index 5633dcf923..494ca344be 100644
--- a/editor/icons/Path2D.svg
+++ b/editor/icons/Path2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 .84961 1.6328c-.19239.88508-.55317 1.3394-.98633 1.6426-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c.8927-.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699-1.8164 2 2 0 0 0 -2-2z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 .84961 1.6328c-.19239.88508-.55317 1.3394-.98633 1.6426-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c.8927-.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699-1.8164 2 2 0 0 0 -2-2z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/Path3D.svg b/editor/icons/Path3D.svg
index 913fe8abf6..076ce9acd2 100644
--- a/editor/icons/Path3D.svg
+++ b/editor/icons/Path3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 .84961 1.6328c-.19239.88508-.55317 1.3394-.98633 1.6426-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c.8927-.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699-1.8164 2 2 0 0 0 -2-2z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 .84961 1.6328c-.19239.88508-.55317 1.3394-.98633 1.6426-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c.8927-.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699-1.8164 2 2 0 0 0 -2-2z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/PathFollow2D.svg b/editor/icons/PathFollow2D.svg
index ac0f17240e..a1fb97cf34 100644
--- a/editor/icons/PathFollow2D.svg
+++ b/editor/icons/PathFollow2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 0-3 4h1.9473c-.1385 1.3203-.5583 1.9074-1.084 2.2754-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c1.0528-.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 0-3 4h1.9473c-.1385 1.3203-.5583 1.9074-1.084 2.2754-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c1.0528-.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/PathFollow3D.svg b/editor/icons/PathFollow3D.svg
index c9bd7009dc..f9bb38939e 100644
--- a/editor/icons/PathFollow3D.svg
+++ b/editor/icons/PathFollow3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 0-3 4h1.9473c-.1385 1.3203-.5583 1.9074-1.084 2.2754-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c1.0528-.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 0-3 4h1.9473c-.1385 1.3203-.5583 1.9074-1.084 2.2754-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c1.0528-.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/PhysicalBone3D.svg b/editor/icons/PhysicalBone3D.svg
index 55df1f1e19..29f0611b9e 100644
--- a/editor/icons/PhysicalBone3D.svg
+++ b/editor/icons/PhysicalBone3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc9c9c" transform="translate(-2.5625 -18.4375)"><path d="m13.107422 19.382812a2.4664 2.4663 0 0 0 -1.78125.720704 2.4664 2.4663 0 0 0 -.185547.21289l1.332031 2.433594-1.605469.603516-3.414062 3.414062a2.4664 2.4663 0 0 0 -3.1015625.3125 2.4664 2.4663 0 0 0 0 3.488281 2.4664 2.4663 0 0 0 1.3964844.695313 2.4664 2.4663 0 0 0 .6953125 1.396484 2.4664 2.4663 0 0 0 3.4882812 0 2.4664 2.4663 0 0 0 .3144534-3.103515l3.560547-3.560547a2.4664 2.4663 0 0 0 3.099609-.310547 2.4664 2.4663 0 0 0 0-3.488281 2.4664 2.4663 0 0 0 -1.396484-.697266 2.4664 2.4663 0 0 0 -.695313-1.396484 2.4664 2.4663 0 0 0 -1.707031-.720704z"/><path d="m3.7211033 21.208326.9608286 4.82644 1.3962404-.524494z"/><path d="m6.4843278 19.465234.9608285 4.82644 1.3962404-.524494z"/><path d="m9.6964655 19.33678.7108285 3.51394 1.39624-.524494z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f" transform="translate(-2.5625 -18.4375)"><path d="m13.107422 19.382812a2.4664 2.4663 0 0 0 -1.78125.720704 2.4664 2.4663 0 0 0 -.185547.21289l1.332031 2.433594-1.605469.603516-3.414062 3.414062a2.4664 2.4663 0 0 0 -3.1015625.3125 2.4664 2.4663 0 0 0 0 3.488281 2.4664 2.4663 0 0 0 1.3964844.695313 2.4664 2.4663 0 0 0 .6953125 1.396484 2.4664 2.4663 0 0 0 3.4882812 0 2.4664 2.4663 0 0 0 .3144534-3.103515l3.560547-3.560547a2.4664 2.4663 0 0 0 3.099609-.310547 2.4664 2.4663 0 0 0 0-3.488281 2.4664 2.4663 0 0 0 -1.396484-.697266 2.4664 2.4663 0 0 0 -.695313-1.396484 2.4664 2.4663 0 0 0 -1.707031-.720704z"/><path d="m3.7211033 21.208326.9608286 4.82644 1.3962404-.524494z"/><path d="m6.4843278 19.465234.9608285 4.82644 1.3962404-.524494z"/><path d="m9.6964655 19.33678.7108285 3.51394 1.39624-.524494z"/></g></svg>
diff --git a/editor/icons/PhysicalSkyMaterial.svg b/editor/icons/PhysicalSkyMaterial.svg
index 68bf2785a4..a32b451c53 100644
--- a/editor/icons/PhysicalSkyMaterial.svg
+++ b/editor/icons/PhysicalSkyMaterial.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 5v2h8 1c0-.554.446-1 1-1h2c.554 0 1 .446 1 1h1v-2z" fill="#9dff70"/><path d="m1 7v2h2 1 5c-.554 0-1-.446-1-1s.446-1 1-1zm13 0c0 .554-.446 1-1 1h-1c0 .554-.446 1-1 1h4v-2z" fill="#70ffb9"/><path d="m1 9v2h2c-.554 0-1-.446-1-1s.446-1 1-1zm3 0c.554 0 1 .446 1 1s-.446 1-1 1h11v-2h-4-2z" fill="#70deff"/><path d="m1 3v2h14v-2z" fill="#ffeb70"/><path d="m1 11v2h14v-2z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 5v2h8 1c0-.554.446-1 1-1h2c.554 0 1 .446 1 1h1v-2z" fill="#80ff45"/><path d="m1 7v2h2 1 5c-.554 0-1-.446-1-1s.446-1 1-1zm13 0c0 .554-.446 1-1 1h-1c0 .554-.446 1-1 1h4v-2z" fill="#45ffa2"/><path d="m1 9v2h2c-.554 0-1-.446-1-1s.446-1 1-1zm3 0c.554 0 1 .446 1 1s-.446 1-1 1h11v-2h-4-2z" fill="#45d7ff"/><path d="m1 3v2h14v-2z" fill="#ffe345"/><path d="m1 11v2h14v-2z" fill="#8045ff"/></svg>
diff --git a/editor/icons/PinJoint2D.svg b/editor/icons/PinJoint2D.svg
index 4e701df7fb..fc7329e4f3 100644
--- a/editor/icons/PinJoint2D.svg
+++ b/editor/icons/PinJoint2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1.2715-.70703.70703v1.4141l-2.1211 2.123 4.2422 4.2422 2.1211-2.1211h1.4141l.70703-.70703-5.6562-5.6582zm-3.5352 4.9512-3.5352.70703 7.0703 7.0703.70703-3.5352-4.2422-4.2422zm-1.4141 4.2422-1.4141 1.4141-.70703 2.1211 2.1211-.70703 1.4141-1.4141-1.4141-1.4141z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1.2715-.70703.70703v1.4141l-2.1211 2.123 4.2422 4.2422 2.1211-2.1211h1.4141l.70703-.70703-5.6562-5.6582zm-3.5352 4.9512-3.5352.70703 7.0703 7.0703.70703-3.5352-4.2422-4.2422zm-1.4141 4.2422-1.4141 1.4141-.70703 2.1211 2.1211-.70703 1.4141-1.4141-1.4141-1.4141z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/PinJoint3D.svg b/editor/icons/PinJoint3D.svg
index 12f388b2f7..8cba452163 100644
--- a/editor/icons/PinJoint3D.svg
+++ b/editor/icons/PinJoint3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1.2715-.70703.70703v1.4141l-2.1211 2.123 4.2422 4.2422 2.1211-2.1211h1.4141l.70703-.70703-5.6562-5.6582zm-3.5352 4.9512-3.5352.70703 7.0703 7.0703.70703-3.5352-4.2422-4.2422zm-1.4141 4.2422-1.4141 1.4141-.70703 2.1211 2.1211-.70703 1.4141-1.4141-1.4141-1.4141z" fill="#fc9c9c" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1.2715-.70703.70703v1.4141l-2.1211 2.123 4.2422 4.2422 2.1211-2.1211h1.4141l.70703-.70703-5.6562-5.6582zm-3.5352 4.9512-3.5352.70703 7.0703 7.0703.70703-3.5352-4.2422-4.2422zm-1.4141 4.2422-1.4141 1.4141-.70703 2.1211 2.1211-.70703 1.4141-1.4141-1.4141-1.4141z" fill="#fc7f7f" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/Plane.svg b/editor/icons/Plane.svg
index edaa86e772..5857ac56f7 100644
--- a/editor/icons/Plane.svg
+++ b/editor/icons/Plane.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 2v8h2v-2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3zm6 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5zm-4 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1zm8 0v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3z" fill="#f77070"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 2v8h2v-2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3zm6 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-5zm-4 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1zm8 0v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3z" fill="#f74949"/></svg>
diff --git a/editor/icons/PlaneMesh.svg b/editor/icons/PlaneMesh.svg
index 3514c1e3e3..54b33616ba 100644
--- a/editor/icons/PlaneMesh.svg
+++ b/editor/icons/PlaneMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 4-7 4 7 4 7-4zm0 2 3.5 2-3.5 2-3.5-2z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 4-7 4 7 4 7-4zm0 2 3.5 2-3.5 2-3.5-2z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/PointLight2D.svg b/editor/icons/PointLight2D.svg
index d660b82c34..1a3222c79e 100644
--- a/editor/icons/PointLight2D.svg
+++ b/editor/icons/PointLight2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 5 0 0 0 -5 5 5 5 0 0 0 3 4.5762v2.4238h4v-2.4199a5 5 0 0 0 3-4.5801 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3zm-1 11v1h2v-1z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 5 0 0 0 -5 5 5 5 0 0 0 3 4.5762v2.4238h4v-2.4199a5 5 0 0 0 3-4.5801 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3zm-1 11v1h2v-1z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/PointMesh.svg b/editor/icons/PointMesh.svg
index 184200c528..ec04989e02 100644
--- a/editor/icons/PointMesh.svg
+++ b/editor/icons/PointMesh.svg
@@ -1 +1 @@
-<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#ffd684"><ellipse cx="3.7237" cy="3.0268" rx="2.0114" ry="1.9956"/><ellipse cx="11.717" cy="6.1734" rx="2.0114" ry="1.9956"/><ellipse cx="6.5219" cy="12.477" rx="2.0114" ry="1.9956"/></g></svg>
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#ffca5f"><ellipse cx="3.7237" cy="3.0268" rx="2.0114" ry="1.9956"/><ellipse cx="11.717" cy="6.1734" rx="2.0114" ry="1.9956"/><ellipse cx="6.5219" cy="12.477" rx="2.0114" ry="1.9956"/></g></svg>
diff --git a/editor/icons/Polygon2D.svg b/editor/icons/Polygon2D.svg
index b74ba3e342..9d7ad5d1cf 100644
--- a/editor/icons/Polygon2D.svg
+++ b/editor/icons/Polygon2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="#a5b7f3" stroke="#a5b7f3" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="#8da5f3" stroke="#8da5f3" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/Portal.svg b/editor/icons/Portal.svg
index e52e0473a6..9365c450da 100644
--- a/editor/icons/Portal.svg
+++ b/editor/icons/Portal.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 7 0 0 0 -5 7 5 7 0 0 0 5 7 5 7 0 0 0 5-7 5 7 0 0 0 -5-7zm0 2a3 5 0 0 1 3 5 3 5 0 0 1 -3 5 3 5 0 0 1 -3-5 3 5 0 0 1 3-5z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 7 0 0 0 -5 7 5 7 0 0 0 5 7 5 7 0 0 0 5-7 5 7 0 0 0 -5-7zm0 2a3 5 0 0 1 3 5 3 5 0 0 1 -3 5 3 5 0 0 1 -3-5 3 5 0 0 1 3-5z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/Position2D.svg b/editor/icons/Position2D.svg
index d5e7ff9621..191f0b2a03 100644
--- a/editor/icons/Position2D.svg
+++ b/editor/icons/Position2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v4h2v-4zm-6 6v2h4v-2zm10 0v2h4v-2zm-4 4v4h2v-4z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v4h2v-4zm-6 6v2h4v-2zm10 0v2h4v-2zm-4 4v4h2v-4z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/Position3D.svg b/editor/icons/Position3D.svg
index da7dfb010a..894b195589 100644
--- a/editor/icons/Position3D.svg
+++ b/editor/icons/Position3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v4h2v-4zm-6 6v2h4v-2zm10 0v2h4v-2zm-4 4v4h2v-4z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v4h2v-4zm-6 6v2h4v-2zm10 0v2h4v-2zm-4 4v4h2v-4z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/PrismMesh.svg b/editor/icons/PrismMesh.svg
index bc5f4fb0b1..cca52bb7b0 100644
--- a/editor/icons/PrismMesh.svg
+++ b/editor/icons/PrismMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9824 1.002a1.0001 1.0001 0 0 0 -.81445.44336l-5.9727 8.9609-.027344.03906a1 1 0 0 0 -.0625.10742 1 1 0 0 0 .44727 1.3418l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1 1 0 0 0 .44726-1.3418 1 1 0 0 0 -.0625-.10742l-6-9a1.0001 1.0001 0 0 0 -.84961-.44336zm-.98242 4.3008v7.0801l-3.5391-1.7715zm2 0 3.5391 5.3086-3.5391 1.7715z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9824 1.002a1.0001 1.0001 0 0 0 -.81445.44336l-5.9727 8.9609-.027344.03906a1 1 0 0 0 -.0625.10742 1 1 0 0 0 .44727 1.3418l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1 1 0 0 0 .44726-1.3418 1 1 0 0 0 -.0625-.10742l-6-9a1.0001 1.0001 0 0 0 -.84961-.44336zm-.98242 4.3008v7.0801l-3.5391-1.7715zm2 0 3.5391 5.3086-3.5391 1.7715z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/ProceduralSkyMaterial.svg b/editor/icons/ProceduralSkyMaterial.svg
index 9aa362d8da..ceaf56dbce 100644
--- a/editor/icons/ProceduralSkyMaterial.svg
+++ b/editor/icons/ProceduralSkyMaterial.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.0761719 11a7 7 0 0 0 .609375 2h12.6308591a7 7 0 0 0 .609375-2h-9.925781c0 .554-.446 1-1 1h-1c-.554 0-1-.446-1-1z" fill="#9f70ff"/><path d="m1.0722656 9a7 7 0 0 0 -.0722656 1 7 7 0 0 0 .0761719 1h.9238281c0-.554.446-1 1-1h1c.554 0 1 .446 1 1h9.925781a7 7 0 0 0 .074219-1 7 7 0 0 0 -.072266-1h-2.927734-1c0 .554-.446 1-1 1h-2c-.554 0-1-.446-1-1z" fill="#70deff"/><path d="m1.6757812 7a7 7 0 0 0 -.6035156 2h5.9277344c0-.554.446-1 1-1h1c0-.554.446-1 1-1zm10.3242188 0c.554 0 1 .446 1 1s-.446 1-1 1h2.927734a7 7 0 0 0 -.603515-2z" fill="#70ffb9"/><path d="m3.1035156 5a7 7 0 0 0 -1.4277344 2h12.6484378a7 7 0 0 0 -1.425781-2z" fill="#9dff70"/><path d="m8 3a7 7 0 0 0 -4.8964844 2h9.7949224a7 7 0 0 0 -4.898438-2z" fill="#ffeb70"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.0761719 11a7 7 0 0 0 .609375 2h12.6308591a7 7 0 0 0 .609375-2h-9.925781c0 .554-.446 1-1 1h-1c-.554 0-1-.446-1-1z" fill="#8045ff"/><path d="m1.0722656 9a7 7 0 0 0 -.0722656 1 7 7 0 0 0 .0761719 1h.9238281c0-.554.446-1 1-1h1c.554 0 1 .446 1 1h9.925781a7 7 0 0 0 .074219-1 7 7 0 0 0 -.072266-1h-2.927734-1c0 .554-.446 1-1 1h-2c-.554 0-1-.446-1-1z" fill="#45d7ff"/><path d="m1.6757812 7a7 7 0 0 0 -.6035156 2h5.9277344c0-.554.446-1 1-1h1c0-.554.446-1 1-1zm10.3242188 0c.554 0 1 .446 1 1s-.446 1-1 1h2.927734a7 7 0 0 0 -.603515-2z" fill="#45ffa2"/><path d="m3.1035156 5a7 7 0 0 0 -1.4277344 2h12.6484378a7 7 0 0 0 -1.425781-2z" fill="#80ff45"/><path d="m8 3a7 7 0 0 0 -4.8964844 2h9.7949224a7 7 0 0 0 -4.898438-2z" fill="#ffe345"/></svg>
diff --git a/editor/icons/ProgressBar.svg b/editor/icons/ProgressBar.svg
index 2200cb8ea7..5c49563f23 100644
--- a/editor/icons/ProgressBar.svg
+++ b/editor/icons/ProgressBar.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 3c-1.1046 0-2 .89543-2 2v6c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-6c0-1.1046-.89543-2-2-2zm0 2h10v6h-10zm1 1v4h1v-4zm2 0v4h1v-4zm2 0v4h1v-4z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 3c-1.1046 0-2 .89543-2 2v6c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-6c0-1.1046-.89543-2-2-2zm0 2h10v6h-10zm1 1v4h1v-4zm2 0v4h1v-4zm2 0v4h1v-4z" fill="#8eef97"/></svg>
diff --git a/editor/icons/ProximityGroup3D.svg b/editor/icons/ProximityGroup3D.svg
index 703abc6486..5cbf8add7b 100644
--- a/editor/icons/ProximityGroup3D.svg
+++ b/editor/icons/ProximityGroup3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h14v-14zm2 2h10v10h-10zm7.5 1c-.82843.0000048-1.5.67157-1.5 1.5.0000048.82843.67157 1.5 1.5 1.5.82842-.0000048 1.5-.67157 1.5-1.5-.000005-.82843-.67158-1.5-1.5-1.5zm-5 5c-.82843-.0000048-1.5.67157-1.5 1.5-.0000048.82843.67157 1.5 1.5 1.5.82843.000005 1.5-.67157 1.5-1.5.0000048-.82843-.67157-1.5-1.5-1.5zm5 0c-.82843.0000048-1.5.67157-1.5 1.5.0000048.82842.67157 1.5 1.5 1.5.82842-.000005 1.5-.67158 1.5-1.5-.000005-.82843-.67158-1.5-1.5-1.5z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h14v-14zm2 2h10v10h-10zm7.5 1c-.82843.0000048-1.5.67157-1.5 1.5.0000048.82843.67157 1.5 1.5 1.5.82842-.0000048 1.5-.67157 1.5-1.5-.000005-.82843-.67158-1.5-1.5-1.5zm-5 5c-.82843-.0000048-1.5.67157-1.5 1.5-.0000048.82843.67157 1.5 1.5 1.5.82843.000005 1.5-.67157 1.5-1.5.0000048-.82843-.67157-1.5-1.5-1.5zm5 0c-.82843.0000048-1.5.67157-1.5 1.5.0000048.82842.67157 1.5 1.5 1.5.82842-.000005 1.5-.67158 1.5-1.5-.000005-.82843-.67158-1.5-1.5-1.5z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/Quad.svg b/editor/icons/Quad.svg
index cf07be1d2f..70ef6b7227 100644
--- a/editor/icons/Quad.svg
+++ b/editor/icons/Quad.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 10 2h2 12v-2-12h-12zm3.4141 2h8.5859v8.5859zm-1.4141 1.4141 8.5859 8.5859h-8.5859z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 10 2h2 12v-2-12h-12zm3.4141 2h8.5859v8.5859zm-1.4141 1.4141 8.5859 8.5859h-8.5859z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/QuadMesh.svg b/editor/icons/QuadMesh.svg
index bee0b2853f..86cc1bc233 100644
--- a/editor/icons/QuadMesh.svg
+++ b/editor/icons/QuadMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1v14h-14v-14zm-2 2h-8.5859l8.5859 8.5859zm-10 1.4141v8.5859h8.5859z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1v14h-14v-14zm-2 2h-8.5859l8.5859 8.5859zm-10 1.4141v8.5859h8.5859z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/Quat.svg b/editor/icons/Quat.svg
deleted file mode 100644
index 66020e5243..0000000000
--- a/editor/icons/Quat.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 3a3 3 0 0 0 -3 3 3 3 0 0 0 3 3v2h2v-2.7695a3 3 0 0 0 2 .76953h2v-6h-2v4a1 1 0 0 1 -1-1v-3h-2zm0 2v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#ec69a3"/><path d="m4 3v3a3 3 0 0 0 3 3h2v-6h-2v4a1 1 0 0 1 -1-1v-3z" fill="#fff" fill-opacity=".39216"/><path d="m13 1v2h-2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-3a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2zm-2 4v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#ec69a3"/></svg>
diff --git a/editor/icons/Quaternion.svg b/editor/icons/Quaternion.svg
new file mode 100644
index 0000000000..cf29160ff4
--- /dev/null
+++ b/editor/icons/Quaternion.svg
@@ -0,0 +1 @@
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 3a3 3 0 0 0 -3 3 3 3 0 0 0 3 3v2h2v-2.7695a3 3 0 0 0 2 .76953h2v-6h-2v4a1 1 0 0 1 -1-1v-3h-2zm0 2v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#ec418e"/><path d="m4 3v3a3 3 0 0 0 3 3h2v-6h-2v4a1 1 0 0 1 -1-1v-3z" fill="#fff" fill-opacity=".39216"/><path d="m13 1v2h-2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-3a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2zm-2 4v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#ec418e"/></svg>
diff --git a/editor/icons/RID.svg b/editor/icons/RID.svg
index 9198e421b1..40764867ba 100644
--- a/editor/icons/RID.svg
+++ b/editor/icons/RID.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 2v2h2v-2zm7 0v2h-1a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1 2v-8zm-10 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1h1v-2zm3 2v4h2v-4zm6 0h1v2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#69ec9a"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 2v2h2v-2zm7 0v2h-1a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1 2v-8zm-10 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1h1v-2zm3 2v4h2v-4zm6 0h1v2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#41ec80"/></svg>
diff --git a/editor/icons/RayCast2D.svg b/editor/icons/RayCast2D.svg
index 645da1e2da..07c8d45239 100644
--- a/editor/icons/RayCast2D.svg
+++ b/editor/icons/RayCast2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v9h-3l4 5 4-5h-3v-9z" fill="#a5b7f3"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v9h-3l4 5 4-5h-3v-9z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/RayCast3D.svg b/editor/icons/RayCast3D.svg
index 4500551463..9670e63022 100644
--- a/editor/icons/RayCast3D.svg
+++ b/editor/icons/RayCast3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v9h-3l4 5 4-5h-3v-9z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v9h-3l4 5 4-5h-3v-9z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/Rayito.svg b/editor/icons/Rayito.svg
index 1db71c2231..1d4f9ca458 100644
--- a/editor/icons/Rayito.svg
+++ b/editor/icons/Rayito.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-1 7h2.875l-.875 7 9-8h-3.8574l.85742-6h-7z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-1 7h2.875l-.875 7 9-8h-3.8574l.85742-6h-7z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/Rect2.svg b/editor/icons/Rect2.svg
index 18dbdf3a12..5b069bd3c1 100644
--- a/editor/icons/Rect2.svg
+++ b/editor/icons/Rect2.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 2v2h-1a3 3 0 0 0 -2.5 1.3457 3 3 0 0 0 -2.5-1.3457 3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1h3a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v1a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2zm-10 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1h1v-2z" fill="#f191a5"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 2v2h-1a3 3 0 0 0 -2.5 1.3457 3 3 0 0 0 -2.5-1.3457 3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1h3a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v1a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1-1v-1h1v-2h-1v-2zm-10 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1h1v-2z" fill="#f1738f"/></svg>
diff --git a/editor/icons/Rect2i.svg b/editor/icons/Rect2i.svg
index 142ad88515..76f4fededf 100644
--- a/editor/icons/Rect2i.svg
+++ b/editor/icons/Rect2i.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 2v2h-1c-1.7267 0-3 1.3359-3 3 0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228 0-1-.44772-1-1s.44772-1 1-1h1v1c0 1.6569 1.3431 3 3 3v-2c-.55228 0-.93526-.45152-1-1v-1h1v-2h-1v-2zm-5 2c-1.6569 0-2.9547 1.3438-3 3v3h2v-3c0-.55228.44772-1 1-1h1v-2z" fill="#f191a5"/><path d="m13 2v2h2v-2zm0 4v4h2v-4z" fill="#7dc6ef"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 2v2h-1c-1.7267 0-3 1.3359-3 3 0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228 0-1-.44772-1-1s.44772-1 1-1h1v1c0 1.6569 1.3431 3 3 3v-2c-.55228 0-.93526-.45152-1-1v-1h1v-2h-1v-2zm-5 2c-1.6569 0-2.9547 1.3438-3 3v3h2v-3c0-.55228.44772-1 1-1h1v-2z" fill="#f1738f"/><path d="m13 2v2h2v-2zm0 4v4h2v-4z" fill="#5abbef"/></svg>
diff --git a/editor/icons/ReferenceRect.svg b/editor/icons/ReferenceRect.svg
index 449ca250e3..4ba50b2af2 100644
--- a/editor/icons/ReferenceRect.svg
+++ b/editor/icons/ReferenceRect.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v-2zm3 0v2h8v-2zm9 0v2h2v-2zm-12 3v8h2v-8zm12 0v8h2v-8zm-12 9v2h2v-2zm3 0v2h8v-2zm9 0v2h2v-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v-2zm3 0v2h8v-2zm9 0v2h2v-2zm-12 3v8h2v-8zm12 0v8h2v-8zm-12 9v2h2v-2zm3 0v2h8v-2zm9 0v2h2v-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/ReflectionProbe.svg b/editor/icons/ReflectionProbe.svg
index ff9263d798..a88a3524be 100644
--- a/editor/icons/ReflectionProbe.svg
+++ b/editor/icons/ReflectionProbe.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10 2a1.0001 1.0001 0 1 0 0 2h1.5859l-4.5195 4.5195-4.2988-5.1582-1.5352 1.2793 5 6a1.0001 1.0001 0 0 0 1.4746.064453l5.293-5.293v1.5879a1.0001 1.0001 0 1 0 2 0v-4a1.0001 1.0001 0 0 0 -1-1h-4zm-9 7v5a1.0001 1.0001 0 0 0 1 1h12a1.0001 1.0001 0 0 0 1-1v-4h-2v3h-10v-4z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10 2a1.0001 1.0001 0 1 0 0 2h1.5859l-4.5195 4.5195-4.2988-5.1582-1.5352 1.2793 5 6a1.0001 1.0001 0 0 0 1.4746.064453l5.293-5.293v1.5879a1.0001 1.0001 0 1 0 2 0v-4a1.0001 1.0001 0 0 0 -1-1h-4zm-9 7v5a1.0001 1.0001 0 0 0 1 1h12a1.0001 1.0001 0 0 0 1-1v-4h-2v3h-10v-4z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/RemoteTransform2D.svg b/editor/icons/RemoteTransform2D.svg
index 81a3946d9f..9d03db5c3b 100644
--- a/editor/icons/RemoteTransform2D.svg
+++ b/editor/icons/RemoteTransform2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.8565 0-5.4995 1.5262-6.9277 4a1 1 0 0 0 .36523 1.3672 1 1 0 0 0 1.3672-.36719c1.0726-1.8578 3.0501-3 5.1953-3s4.1227 1.1422 5.1953 3a1 1 0 0 0 1.3672.36719 1 1 0 0 0 .36523-1.3672c-1.4283-2.4738-4.0712-4-6.9277-4zm0 4c-1.8056 0-3.396 1.2207-3.8633 2.9648a1 1 0 0 0 .70703 1.2246 1 1 0 0 0 1.2246-.70703c.23553-.8791 1.0216-1.4824 1.9316-1.4824s1.6961.60332 1.9316 1.4824a1 1 0 0 0 1.2246.70703 1 1 0 0 0 .70703-1.2246c-.46732-1.7441-2.0577-2.9648-3.8633-2.9648zm0 4c-.554 0-1 .446-1 1v1h-3a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2-3.4648h-3v-1c0-.554-.446-1-1-1z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.8565 0-5.4995 1.5262-6.9277 4a1 1 0 0 0 .36523 1.3672 1 1 0 0 0 1.3672-.36719c1.0726-1.8578 3.0501-3 5.1953-3s4.1227 1.1422 5.1953 3a1 1 0 0 0 1.3672.36719 1 1 0 0 0 .36523-1.3672c-1.4283-2.4738-4.0712-4-6.9277-4zm0 4c-1.8056 0-3.396 1.2207-3.8633 2.9648a1 1 0 0 0 .70703 1.2246 1 1 0 0 0 1.2246-.70703c.23553-.8791 1.0216-1.4824 1.9316-1.4824s1.6961.60332 1.9316 1.4824a1 1 0 0 0 1.2246.70703 1 1 0 0 0 .70703-1.2246c-.46732-1.7441-2.0577-2.9648-3.8633-2.9648zm0 4c-.554 0-1 .446-1 1v1h-3a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2-3.4648h-3v-1c0-.554-.446-1-1-1z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/RemoteTransform3D.svg b/editor/icons/RemoteTransform3D.svg
index d55e4e4224..96cd31a2df 100644
--- a/editor/icons/RemoteTransform3D.svg
+++ b/editor/icons/RemoteTransform3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.8565 0-5.4995 1.5262-6.9277 4a1 1 0 0 0 .36523 1.3672 1 1 0 0 0 1.3672-.36719c1.0726-1.8578 3.0501-3 5.1953-3s4.1227 1.1422 5.1953 3a1 1 0 0 0 1.3672.36719 1 1 0 0 0 .36523-1.3672c-1.4283-2.4738-4.0712-4-6.9277-4zm0 4c-1.8056 0-3.396 1.2207-3.8633 2.9648a1 1 0 0 0 .70703 1.2246 1 1 0 0 0 1.2246-.70703c.23553-.8791 1.0216-1.4824 1.9316-1.4824s1.6961.60332 1.9316 1.4824a1 1 0 0 0 1.2246.70703 1 1 0 0 0 .70703-1.2246c-.46732-1.7441-2.0577-2.9648-3.8633-2.9648zm0 4c-.554 0-1 .446-1 1v1h-3a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2-3.4648h-3v-1c0-.554-.446-1-1-1z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.8565 0-5.4995 1.5262-6.9277 4a1 1 0 0 0 .36523 1.3672 1 1 0 0 0 1.3672-.36719c1.0726-1.8578 3.0501-3 5.1953-3s4.1227 1.1422 5.1953 3a1 1 0 0 0 1.3672.36719 1 1 0 0 0 .36523-1.3672c-1.4283-2.4738-4.0712-4-6.9277-4zm0 4c-1.8056 0-3.396 1.2207-3.8633 2.9648a1 1 0 0 0 .70703 1.2246 1 1 0 0 0 1.2246-.70703c.23553-.8791 1.0216-1.4824 1.9316-1.4824s1.6961.60332 1.9316 1.4824a1 1 0 0 0 1.2246.70703 1 1 0 0 0 .70703-1.2246c-.46732-1.7441-2.0577-2.9648-3.8633-2.9648zm0 4c-.554 0-1 .446-1 1v1h-3a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2-3.4648h-3v-1c0-.554-.446-1-1-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/Reparent.svg b/editor/icons/Reparent.svg
index 04efb08b99..e95eb742db 100644
--- a/editor/icons/Reparent.svg
+++ b/editor/icons/Reparent.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v5.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -.72852-.73047v-5.541a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2z" fill="#e0e0e0"/><path d="m9 1-4 3 4 3v-2a3 3 0 0 1 3 3v2h2v-2a5 5 0 0 0 -5-5z" fill="#84ffb1"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v5.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305-1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2-2 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -.72852-.73047v-5.541a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2z" fill="#e0e0e0"/><path d="m9 1-4 3 4 3v-2a3 3 0 0 1 3 3v2h2v-2a5 5 0 0 0 -5-5z" fill="#5fff97"/></svg>
diff --git a/editor/icons/ReparentToNewNode.svg b/editor/icons/ReparentToNewNode.svg
index cca610d2b1..f28a04a19e 100644
--- a/editor/icons/ReparentToNewNode.svg
+++ b/editor/icons/ReparentToNewNode.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1.4915254 13c0 1.104569.8954305 2 2 2 .7139771-.000554 1.3735116-.381677 1.7305-1h6.0494746c.356631.617705 1.015238.998733 1.7285 1 1.104569 0 2-.895431 2-2s-.895431-2-2-2c-.713977.000554-1.373512.381677-1.7305 1h-6.0494746c-.1747809-.30301-.8483719-1-1.7285-1-.9027301 0-2 .891221-2 2z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m10.421845 1038.2814-2.7947264 2.096 2.7947264 2.0961v-1.3974c2.716918 0 2.180792 1.4469 2.180792 3.9265v1.3974h1.397363v-1.3974c0-3.863.13086-5.3239-3.578155-5.3239z" fill="#84ffb1" stroke-width=".698682"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#84ffb1" transform="translate(-8.5 1028.4)"/><path d="m4.5 1047.7968v-3.1171h-2.0000005v3.1171z" fill="#e0e0e0" stroke-width=".717839"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1.4915254 13c0 1.104569.8954305 2 2 2 .7139771-.000554 1.3735116-.381677 1.7305-1h6.0494746c.356631.617705 1.015238.998733 1.7285 1 1.104569 0 2-.895431 2-2s-.895431-2-2-2c-.713977.000554-1.373512.381677-1.7305 1h-6.0494746c-.1747809-.30301-.8483719-1-1.7285-1-.9027301 0-2 .891221-2 2z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m10.421845 1038.2814-2.7947264 2.096 2.7947264 2.0961v-1.3974c2.716918 0 2.180792 1.4469 2.180792 3.9265v1.3974h1.397363v-1.3974c0-3.863.13086-5.3239-3.578155-5.3239z" fill="#5fff97" stroke-width=".698682"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97" transform="translate(-8.5 1028.4)"/><path d="m4.5 1047.7968v-3.1171h-2.0000005v3.1171z" fill="#e0e0e0" stroke-width=".717839"/></g></svg>
diff --git a/editor/icons/RibbonTrailMesh.svg b/editor/icons/RibbonTrailMesh.svg
new file mode 100644
index 0000000000..3f6cf0bfef
--- /dev/null
+++ b/editor/icons/RibbonTrailMesh.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#ffca5f" stroke-width=".25" transform="rotate(90)"><path d="m6.5625-14.062499h1.875v13.124999h-1.875z"/><path d="m.9375-11.249999h1.875v7.499999h-1.875z"/><path d="m12.187499-11.249999h1.875v7.5h-1.875z"/></g></svg>
diff --git a/editor/icons/RichTextEffect.svg b/editor/icons/RichTextEffect.svg
index f1d3f168ff..3745219934 100644
--- a/editor/icons/RichTextEffect.svg
+++ b/editor/icons/RichTextEffect.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h7v-2zm9 0v2h5v-2zm-9 4v2h11v-2zm0 4v2h4v-2zm6 0v2h1c-.044949-.094701-.088906-.20229-.125-.3418-.077717-.30039-.10439-.81722.16406-1.293.081489-.1441.18202-.26127.28906-.36523zm-6 4v2h8.2812c-.066517-.011548-.1231-.014758-.20117-.037109-.30195-.08645-.76491-.33245-1.0352-.80664-.23366-.4121-.24101-.84933-.18945-1.1562z" fill="#e0e0e0"/><path d="m12.216 8.598a.53334 3.2001 0 0 0 -.50976 2.2754 3.2001.53334 30 0 0 -2.2656-.71484 3.2001.53334 30 0 0 1.75 1.6016.53334 3.2001 60 0 0 -1.7461 1.5996.53334 3.2001 60 0 0 2.2578-.71094.53334 3.2001 0 0 0 .51367 2.3496.53334 3.2001 0 0 0 .51367-2.3516 3.2001.53334 30 0 0 2.2539.71094 3.2001.53334 30 0 0 -1.7441-1.5977.53334 3.2001 60 0 0 1.748-1.5996.53334 3.2001 60 0 0 -2.2617.71484.53334 3.2001 0 0 0 -.50977-2.2773z" fill="#cea4f1" stroke-width="1.0667"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h7v-2zm9 0v2h5v-2zm-9 4v2h11v-2zm0 4v2h4v-2zm6 0v2h1c-.044949-.094701-.088906-.20229-.125-.3418-.077717-.30039-.10439-.81722.16406-1.293.081489-.1441.18202-.26127.28906-.36523zm-6 4v2h8.2812c-.066517-.011548-.1231-.014758-.20117-.037109-.30195-.08645-.76491-.33245-1.0352-.80664-.23366-.4121-.24101-.84933-.18945-1.1562z" fill="#e0e0e0"/><path d="m12.216 8.598a.53334 3.2001 0 0 0 -.50976 2.2754 3.2001.53334 30 0 0 -2.2656-.71484 3.2001.53334 30 0 0 1.75 1.6016.53334 3.2001 60 0 0 -1.7461 1.5996.53334 3.2001 60 0 0 2.2578-.71094.53334 3.2001 0 0 0 .51367 2.3496.53334 3.2001 0 0 0 .51367-2.3516 3.2001.53334 30 0 0 2.2539.71094 3.2001.53334 30 0 0 -1.7441-1.5977.53334 3.2001 60 0 0 1.748-1.5996.53334 3.2001 60 0 0 -2.2617.71484.53334 3.2001 0 0 0 -.50977-2.2773z" fill="#c38ef1" stroke-width="1.0667"/></svg>
diff --git a/editor/icons/RichTextLabel.svg b/editor/icons/RichTextLabel.svg
index 7283d3dd62..14c1af3ea3 100644
--- a/editor/icons/RichTextLabel.svg
+++ b/editor/icons/RichTextLabel.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h8v-2zm12 0-3 3h2v8h-2l3 3 3-3h-2v-8h2zm-12 4v2h2v-2zm4 0v2h4v-2zm-4 4v2h8v-2zm0 4v2h4v-2zm6 0v2h2v-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h8v-2zm12 0-3 3h2v8h-2l3 3 3-3h-2v-8h2zm-12 4v2h2v-2zm4 0v2h4v-2zm-4 4v2h8v-2zm0 4v2h4v-2zm6 0v2h2v-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/RigidBody2D.svg b/editor/icons/RigidBody2D.svg
index 9dc626b94e..5d08e991ae 100644
--- a/editor/icons/RigidBody2D.svg
+++ b/editor/icons/RigidBody2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 1.2227 3.9531 7 7 0 0 0 .30273.4082c.000785-.00256.0011667-.005252.0019532-.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422-.80273c.001375.000393.002531.00156.003906.001953a7 7 0 0 0 .035156-.021485 7 7 0 0 0 .42578-.25 7 7 0 0 0 .16992-.10352 7 7 0 0 0 .36914-.26953 7 7 0 0 0 .20508-.15625 7 7 0 0 0 .3418-.30859 7 7 0 0 0 .16406-.1543 7 7 0 0 0 .33008-.36133 7 7 0 0 0 .14062-.16016 7 7 0 0 0 .27734-.37305 7 7 0 0 0 .13867-.19531 7 7 0 0 0 .21875-.36133 7 7 0 0 0 .14258-.25 7 7 0 0 0 .15625-.33398 7 7 0 0 0 .13867-.31055 7 7 0 0 0 .10742-.30859 7 7 0 0 0 .11914-.35352 7 7 0 0 0 .087891-.36914 7 7 0 0 0 .066406-.29297 7 7 0 0 0 .056641-.40039 7 7 0 0 0 .037109-.3125 7 7 0 0 0 .025391-.55273 7 7 0 0 0 -4.3926-6.4922 7 7 0 0 0 -.001953 0 7 7 0 0 0 -.66016-.22852 7 7 0 0 0 -.0058594-.0019531 7 7 0 0 0 -.55078-.13086 7 7 0 0 0 -.14062-.03125 7 7 0 0 0 -.55078-.072266 7 7 0 0 0 -.14258-.017578 7 7 0 0 0 -.55469-.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -.94922-1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c.14632.65093.35776 1.2833.68359 1.8848a2 2 0 0 0 -.80664 1.6016h-1a6 6 0 0 1 1.123-3.4863zm1.877 1.4863a2 2 0 0 0 -.10938.0039062 2 2 0 0 1 .10938-.0039062zm-.18945.011719a2 2 0 0 0 -.12109.013672 2 2 0 0 1 .12109-.013672zm-.44141.09375a2 2 0 0 0 -.056641.019531 2 2 0 0 1 .056641-.019531zm-1.3594 2.0605a2 2 0 0 0 .013672.11914 2 2 0 0 1 -.013672-.11914zm.027344.20898a2 2 0 0 0 .017578.080078 2 2 0 0 1 -.017578-.080078zm.73438 1.1992a2 2 0 0 0 1.2285.42578 2 2 0 0 0 1.0508-.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473.33203 6 6 0 0 1 -5.0547-2.7695c.23771-.5785.50336-1.1403.82617-1.6563z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 1.2227 3.9531 7 7 0 0 0 .30273.4082c.000785-.00256.0011667-.005252.0019532-.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422-.80273c.001375.000393.002531.00156.003906.001953a7 7 0 0 0 .035156-.021485 7 7 0 0 0 .42578-.25 7 7 0 0 0 .16992-.10352 7 7 0 0 0 .36914-.26953 7 7 0 0 0 .20508-.15625 7 7 0 0 0 .3418-.30859 7 7 0 0 0 .16406-.1543 7 7 0 0 0 .33008-.36133 7 7 0 0 0 .14062-.16016 7 7 0 0 0 .27734-.37305 7 7 0 0 0 .13867-.19531 7 7 0 0 0 .21875-.36133 7 7 0 0 0 .14258-.25 7 7 0 0 0 .15625-.33398 7 7 0 0 0 .13867-.31055 7 7 0 0 0 .10742-.30859 7 7 0 0 0 .11914-.35352 7 7 0 0 0 .087891-.36914 7 7 0 0 0 .066406-.29297 7 7 0 0 0 .056641-.40039 7 7 0 0 0 .037109-.3125 7 7 0 0 0 .025391-.55273 7 7 0 0 0 -4.3926-6.4922 7 7 0 0 0 -.001953 0 7 7 0 0 0 -.66016-.22852 7 7 0 0 0 -.0058594-.0019531 7 7 0 0 0 -.55078-.13086 7 7 0 0 0 -.14062-.03125 7 7 0 0 0 -.55078-.072266 7 7 0 0 0 -.14258-.017578 7 7 0 0 0 -.55469-.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -.94922-1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c.14632.65093.35776 1.2833.68359 1.8848a2 2 0 0 0 -.80664 1.6016h-1a6 6 0 0 1 1.123-3.4863zm1.877 1.4863a2 2 0 0 0 -.10938.0039062 2 2 0 0 1 .10938-.0039062zm-.18945.011719a2 2 0 0 0 -.12109.013672 2 2 0 0 1 .12109-.013672zm-.44141.09375a2 2 0 0 0 -.056641.019531 2 2 0 0 1 .056641-.019531zm-1.3594 2.0605a2 2 0 0 0 .013672.11914 2 2 0 0 1 -.013672-.11914zm.027344.20898a2 2 0 0 0 .017578.080078 2 2 0 0 1 -.017578-.080078zm.73438 1.1992a2 2 0 0 0 1.2285.42578 2 2 0 0 0 1.0508-.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473.33203 6 6 0 0 1 -5.0547-2.7695c.23771-.5785.50336-1.1403.82617-1.6563z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/RigidBody3D.svg b/editor/icons/RigidBody3D.svg
index 476bf3966a..7f5db4ce88 100644
--- a/editor/icons/RigidBody3D.svg
+++ b/editor/icons/RigidBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 .035156.69922 7 7 0 0 0 .27734 1.3691 7 7 0 0 0 .91016 1.8848 7 7 0 0 0 .30273.4082c.000785-.00256.0011667-.005252.0019532-.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422-.80273c.001374.000393.002531.00156.003906.001953a7 7 0 0 0 .035156-.021485 7 7 0 0 0 .42578-.25 7 7 0 0 0 .16992-.10352 7 7 0 0 0 .36914-.26953 7 7 0 0 0 .20508-.15625 7 7 0 0 0 .3418-.30859 7 7 0 0 0 .16406-.1543 7 7 0 0 0 .33008-.36133 7 7 0 0 0 .14062-.16016 7 7 0 0 0 .27734-.37305 7 7 0 0 0 .13867-.19531 7 7 0 0 0 .21875-.36133 7 7 0 0 0 .14258-.25 7 7 0 0 0 .15625-.33398 7 7 0 0 0 .13867-.31055 7 7 0 0 0 .10742-.30859 7 7 0 0 0 .11914-.35352 7 7 0 0 0 .087891-.36914 7 7 0 0 0 .066406-.29297 7 7 0 0 0 .056641-.40039 7 7 0 0 0 .037109-.3125 7 7 0 0 0 .025391-.55273 7 7 0 0 0 -4.3848-6.4883 7 7 0 0 0 -.007812-.0039063 7 7 0 0 0 -.001953 0 7 7 0 0 0 -.61523-.21289 7 7 0 0 0 -.044922-.015625 7 7 0 0 0 -.0058594-.0019531 7 7 0 0 0 -.55078-.13086 7 7 0 0 0 -.14062-.03125 7 7 0 0 0 -.55078-.072266 7 7 0 0 0 -.14258-.017578 7 7 0 0 0 -.55469-.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -.94922-1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c.14632.65093.35776 1.2833.68359 1.8848a2 2 0 0 0 -.80664 1.6016h-1a6 6 0 0 1 1.123-3.4863zm1.877 1.4863a2 2 0 0 0 -.10938.0039062 2 2 0 0 1 .10938-.0039062zm-.18945.011719a2 2 0 0 0 -.12109.013672 2 2 0 0 1 .12109-.013672zm-.44141.09375a2 2 0 0 0 -.056641.019531 2 2 0 0 1 .056641-.019531zm-1.3594 2.0605a2 2 0 0 0 .013672.11914 2 2 0 0 1 -.013672-.11914zm.027344.20898a2 2 0 0 0 .017578.080078 2 2 0 0 1 -.017578-.080078zm.73438 1.1992a2 2 0 0 0 1.2285.42578 2 2 0 0 0 1.0508-.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473.33203 6 6 0 0 1 -5.0547-2.7695c.23771-.5785.50336-1.1403.82617-1.6563z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 .035156.69922 7 7 0 0 0 .27734 1.3691 7 7 0 0 0 .91016 1.8848 7 7 0 0 0 .30273.4082c.000785-.00256.0011667-.005252.0019532-.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422-.80273c.001374.000393.002531.00156.003906.001953a7 7 0 0 0 .035156-.021485 7 7 0 0 0 .42578-.25 7 7 0 0 0 .16992-.10352 7 7 0 0 0 .36914-.26953 7 7 0 0 0 .20508-.15625 7 7 0 0 0 .3418-.30859 7 7 0 0 0 .16406-.1543 7 7 0 0 0 .33008-.36133 7 7 0 0 0 .14062-.16016 7 7 0 0 0 .27734-.37305 7 7 0 0 0 .13867-.19531 7 7 0 0 0 .21875-.36133 7 7 0 0 0 .14258-.25 7 7 0 0 0 .15625-.33398 7 7 0 0 0 .13867-.31055 7 7 0 0 0 .10742-.30859 7 7 0 0 0 .11914-.35352 7 7 0 0 0 .087891-.36914 7 7 0 0 0 .066406-.29297 7 7 0 0 0 .056641-.40039 7 7 0 0 0 .037109-.3125 7 7 0 0 0 .025391-.55273 7 7 0 0 0 -4.3848-6.4883 7 7 0 0 0 -.007812-.0039063 7 7 0 0 0 -.001953 0 7 7 0 0 0 -.61523-.21289 7 7 0 0 0 -.044922-.015625 7 7 0 0 0 -.0058594-.0019531 7 7 0 0 0 -.55078-.13086 7 7 0 0 0 -.14062-.03125 7 7 0 0 0 -.55078-.072266 7 7 0 0 0 -.14258-.017578 7 7 0 0 0 -.55469-.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -.94922-1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c.14632.65093.35776 1.2833.68359 1.8848a2 2 0 0 0 -.80664 1.6016h-1a6 6 0 0 1 1.123-3.4863zm1.877 1.4863a2 2 0 0 0 -.10938.0039062 2 2 0 0 1 .10938-.0039062zm-.18945.011719a2 2 0 0 0 -.12109.013672 2 2 0 0 1 .12109-.013672zm-.44141.09375a2 2 0 0 0 -.056641.019531 2 2 0 0 1 .056641-.019531zm-1.3594 2.0605a2 2 0 0 0 .013672.11914 2 2 0 0 1 -.013672-.11914zm.027344.20898a2 2 0 0 0 .017578.080078 2 2 0 0 1 -.017578-.080078zm.73438 1.1992a2 2 0 0 0 1.2285.42578 2 2 0 0 0 1.0508-.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473.33203 6 6 0 0 1 -5.0547-2.7695c.23771-.5785.50336-1.1403.82617-1.6563z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/Room.svg b/editor/icons/Room.svg
index 6491d0409c..2bc165e736 100644
--- a/editor/icons/Room.svg
+++ b/editor/icons/Room.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002a1.0001 1.0001 0 0 0 -.41016.10352l-6 3a1.0001 1.0001 0 0 0 -.55273.89453v6a1.0001 1.0001 0 0 0 .55273.89453l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1.0001 1.0001 0 0 0 .55273-.89453v-6a1.0001 1.0001 0 0 0 -.55273-.89453l-6-3a1.0001 1.0001 0 0 0 -.48438-.10352zm1.0371 2.6172 4 2v3.7637l-4-2zm-1 5.5 3.7637 1.8809-3.7637 1.8828-3.7637-1.8828z" fill="#fc9c9c" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002a1.0001 1.0001 0 0 0 -.41016.10352l-6 3a1.0001 1.0001 0 0 0 -.55273.89453v6a1.0001 1.0001 0 0 0 .55273.89453l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1.0001 1.0001 0 0 0 .55273-.89453v-6a1.0001 1.0001 0 0 0 -.55273-.89453l-6-3a1.0001 1.0001 0 0 0 -.48438-.10352zm1.0371 2.6172 4 2v3.7637l-4-2zm-1 5.5 3.7637 1.8809-3.7637 1.8828-3.7637-1.8828z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/RootMotionView.svg b/editor/icons/RootMotionView.svg
index f2d23e5b9f..051b95543c 100644
--- a/editor/icons/RootMotionView.svg
+++ b/editor/icons/RootMotionView.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="8" cy="8" gradientTransform="matrix(.85714281 -.00000007 .00000004 .85714284 1.142858 1.142858)" gradientUnits="userSpaceOnUse" r="7"><stop offset="0" stop-color="#fc9c9c"/><stop offset=".83333331" stop-color="#fc9c9c" stop-opacity=".701961"/><stop offset="1" stop-color="#fc9c9c" stop-opacity="0"/></radialGradient><path d="m5 2v3h-3v2h3v2h-3v2h3v3h2v-3h2v3h2v-3h3v-2h-3v-2h3v-2h-3v-3h-2v3h-2v-3zm2 5h2v2h-2z" fill="url(#a)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="8" cy="8" gradientTransform="matrix(.85714281 -.00000007 .00000004 .85714284 1.142858 1.142858)" gradientUnits="userSpaceOnUse" r="7"><stop offset="0" stop-color="#fc7f7f"/><stop offset=".83333331" stop-color="#fc7f7f" stop-opacity=".701961"/><stop offset="1" stop-color="#fc7f7f" stop-opacity="0"/></radialGradient><path d="m5 2v3h-3v2h3v2h-3v2h3v3h2v-3h2v3h2v-3h3v-2h-3v-2h3v-2h-3v-3h-2v3h-2v-3zm2 5h2v2h-2z" fill="url(#a)"/></svg>
diff --git a/editor/icons/SampleLibrary.svg b/editor/icons/SampleLibrary.svg
index 962f7b9413..a5f86d7f3c 100644
--- a/editor/icons/SampleLibrary.svg
+++ b/editor/icons/SampleLibrary.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.0215 1.002a1.0001 1.0001 0 0 0 -1 .875l-.58984 4.7227-.52344-1.0469a1.0001 1.0001 0 0 0 -.89453-.55273h-2a1.0001 1.0001 0 1 0 0 2h1.3828l1.7227 3.4473a1.0001 1.0001 0 0 0 1.8867-.32227l.58984-4.7227.52344 1.0449a1.0001 1.0001 0 0 0 .89453.55273h3a1.0001 1.0001 0 1 0 0-2h-2.3809l-1.7246-3.4473a1.0001 1.0001 0 0 0 -.88672-.55078zm1.9785 6.998v1 5 1h5c.55228 0 1-.44772 1-1v-5c0-.55228-.44772-1-1-1v4l-1-1-1 1v-4z" fill="#ff8484"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.0215 1.002a1.0001 1.0001 0 0 0 -1 .875l-.58984 4.7227-.52344-1.0469a1.0001 1.0001 0 0 0 -.89453-.55273h-2a1.0001 1.0001 0 1 0 0 2h1.3828l1.7227 3.4473a1.0001 1.0001 0 0 0 1.8867-.32227l.58984-4.7227.52344 1.0449a1.0001 1.0001 0 0 0 .89453.55273h3a1.0001 1.0001 0 1 0 0-2h-2.3809l-1.7246-3.4473a1.0001 1.0001 0 0 0 -.88672-.55078zm1.9785 6.998v1 5 1h5c.55228 0 1-.44772 1-1v-5c0-.55228-.44772-1-1-1v4l-1-1-1 1v-4z" fill="#ff5f5f"/></svg>
diff --git a/editor/icons/ScriptCreate.svg b/editor/icons/ScriptCreate.svg
index 91e95eb8c7..564dcddc2e 100644
--- a/editor/icons/ScriptCreate.svg
+++ b/editor/icons/ScriptCreate.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m6 1v1c-.55228 0-1 .44772-1 1v10h-1v-2h-2v2c.0002826.35698.19084.68674.5.86523.15194.088045.32439.13452.5.13477v1h5 1v-1h-1v-4h2v-2h2v-3h3v-2c0-1.1046-.89543-2-2-2z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m6 1c-1.1046 0-2 .89543-2 2v7h-2-1v1 2c0 1.1046.89543 2 2 2s2-.89543 2-2v-10c0-.55228.44772-1 1-1s1 .44772 1 1v1 1 1h1 4v-1h-4v-1-1c0-1.1046-.89543-2-2-2zm-4 10h2v2c0 .55228-.44772 1-1 1s-1-.44772-1-1z" fill="#b4b4b4" transform="translate(0 1036.4)"/><circle cx="3" cy="1048.4" fill="#e0e0e0"/><path d="m13 1049.4h2v-2h-2v-2h-2v2h-2v2h2v2h2z" fill="#84ffb1" fill-rule="evenodd"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m6 1v1c-.55228 0-1 .44772-1 1v10h-1v-2h-2v2c.0002826.35698.19084.68674.5.86523.15194.088045.32439.13452.5.13477v1h5 1v-1h-1v-4h2v-2h2v-3h3v-2c0-1.1046-.89543-2-2-2z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m6 1c-1.1046 0-2 .89543-2 2v7h-2-1v1 2c0 1.1046.89543 2 2 2s2-.89543 2-2v-10c0-.55228.44772-1 1-1s1 .44772 1 1v1 1 1h1 4v-1h-4v-1-1c0-1.1046-.89543-2-2-2zm-4 10h2v2c0 .55228-.44772 1-1 1s-1-.44772-1-1z" fill="#b4b4b4" transform="translate(0 1036.4)"/><circle cx="3" cy="1048.4" fill="#e0e0e0"/><path d="m13 1049.4h2v-2h-2v-2h-2v2h-2v2h2v2h2z" fill="#5fff97" fill-rule="evenodd"/></g></svg>
diff --git a/editor/icons/ScriptRemove.svg b/editor/icons/ScriptRemove.svg
index b455583a6c..9af184c946 100644
--- a/editor/icons/ScriptRemove.svg
+++ b/editor/icons/ScriptRemove.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m6 1v1c-.55228 0-1 .44772-1 1v10h-1v-2h-2v2c.0002826.35698.19084.68674.5.86523.15194.088045.32439.13452.5.13477v1h5.6348l-1.584-1.584 1.4141-1.4141-1.4141-1.416 3.5352-3.5352 1.4141 1.4141v-.46484-3h3v-2c0-1.1046-.89543-2-2-2h-7z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m6 1c-1.1046 0-2 .89543-2 2v7h-2-1v1 2c0 1.1046.89543 2 2 2s2-.89543 2-2v-10c0-.55228.44772-1 1-1s1 .44772 1 1v1 1 1h1 4v-1h-4v-1-1c0-1.1046-.89543-2-2-2zm-4 10h2v2c0 .55228-.44772 1-1 1s-1-.44772-1-1z" fill="#b4b4b4" transform="translate(0 1036.4)"/><circle cx="3" cy="1048.4" fill="#e0e0e0"/><path d="m13.414 1048.4 1.4142-1.4142-1.4142-1.4142-1.4142 1.4142-1.4142-1.4142-1.4142 1.4142 1.4142 1.4142-1.4142 1.4142 1.4142 1.4142 1.4142-1.4142 1.4142 1.4142 1.4142-1.4142z" fill="#ff8484" fill-rule="evenodd"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m6 1v1c-.55228 0-1 .44772-1 1v10h-1v-2h-2v2c.0002826.35698.19084.68674.5.86523.15194.088045.32439.13452.5.13477v1h5.6348l-1.584-1.584 1.4141-1.4141-1.4141-1.416 3.5352-3.5352 1.4141 1.4141v-.46484-3h3v-2c0-1.1046-.89543-2-2-2h-7z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m6 1c-1.1046 0-2 .89543-2 2v7h-2-1v1 2c0 1.1046.89543 2 2 2s2-.89543 2-2v-10c0-.55228.44772-1 1-1s1 .44772 1 1v1 1 1h1 4v-1h-4v-1-1c0-1.1046-.89543-2-2-2zm-4 10h2v2c0 .55228-.44772 1-1 1s-1-.44772-1-1z" fill="#b4b4b4" transform="translate(0 1036.4)"/><circle cx="3" cy="1048.4" fill="#e0e0e0"/><path d="m13.414 1048.4 1.4142-1.4142-1.4142-1.4142-1.4142 1.4142-1.4142-1.4142-1.4142 1.4142 1.4142 1.4142-1.4142 1.4142 1.4142 1.4142 1.4142-1.4142 1.4142 1.4142 1.4142-1.4142z" fill="#ff5f5f" fill-rule="evenodd"/></g></svg>
diff --git a/editor/icons/ScrollContainer.svg b/editor/icons/ScrollContainer.svg
index 600590684d..de631a525e 100644
--- a/editor/icons/ScrollContainer.svg
+++ b/editor/icons/ScrollContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm5 1-2 2h4zm2 2v4l2-2zm0 4h-4l2 2zm-4 0v-4l-2 2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm5 1-2 2h4zm2 2v4l2-2zm0 4h-4l2 2zm-4 0v-4l-2 2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/Shader.svg b/editor/icons/Shader.svg
index 33479326d4..5a7e51191f 100644
--- a/editor/icons/Shader.svg
+++ b/editor/icons/Shader.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10z" fill="#e0e0e0"/><path d="m10 11h2v1h-2z" fill="#9f70ff"/><path d="m4 6h2v1h-2z" fill="#ffeb70"/><path d="m8 8h4v1h-4z" fill="#9dff70"/><path d="m7 6h1v1h-1z" fill="#70deff"/><path d="m4 11h5v1h-5z" fill="#ff70ac"/><path d="m4 4h3v1h-3z" fill="#ff7070"/><path d="m4 8h3v1h-3z" fill="#70ffb9"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10z" fill="#e0e0e0"/><path d="m10 11h2v1h-2z" fill="#8045ff"/><path d="m4 6h2v1h-2z" fill="#ffe345"/><path d="m8 8h4v1h-4z" fill="#80ff45"/><path d="m7 6h1v1h-1z" fill="#45d7ff"/><path d="m4 11h5v1h-5z" fill="#ff4596"/><path d="m4 4h3v1h-3z" fill="#ff4545"/><path d="m4 8h3v1h-3z" fill="#45ffa2"/></svg>
diff --git a/editor/icons/ShaderMaterial.svg b/editor/icons/ShaderMaterial.svg
index ff92f0c376..80a1d0a24d 100644
--- a/editor/icons/ShaderMaterial.svg
+++ b/editor/icons/ShaderMaterial.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v1h2 6 3l-2-2z" fill="#ff7070"/><path d="m1 3v2h2v-2zm8 0v2h5l-2-2z" fill="#ffeb70"/><path d="m1 5v2h2v-2zm8 0v1c0 .554.44599 1 1 1h3 2v-1l-1-1z" fill="#9dff70"/><path d="m1 7v2h2v-2zm12 0v2h2v-2z" fill="#70ffb9"/><path d="m1 9v2h2v-2zm12 0v2h2v-2z" fill="#70deff"/><path d="m1 13v1c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-1h-2-10z" fill="#ff70ac"/><path d="m1 11v2h2v-2zm12 0v2h2v-2z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v1h2 6 3l-2-2z" fill="#ff4545"/><path d="m1 3v2h2v-2zm8 0v2h5l-2-2z" fill="#ffe345"/><path d="m1 5v2h2v-2zm8 0v1c0 .554.44599 1 1 1h3 2v-1l-1-1z" fill="#80ff45"/><path d="m1 7v2h2v-2zm12 0v2h2v-2z" fill="#45ffa2"/><path d="m1 9v2h2v-2zm12 0v2h2v-2z" fill="#45d7ff"/><path d="m1 13v1c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-1h-2-10z" fill="#ff4596"/><path d="m1 11v2h2v-2zm12 0v2h2v-2z" fill="#8045ff"/></svg>
diff --git a/editor/icons/Signal.svg b/editor/icons/Signal.svg
index 91599ffd65..ad5b5e5b06 100644
--- a/editor/icons/Signal.svg
+++ b/editor/icons/Signal.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 3v10h2 4v-2h-4v-6h4v-2h-4zm9 1v3h-5v2h5v3l2.5-2 2.5-2-2.5-2z" fill="#ff8484"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 3v10h2 4v-2h-4v-6h4v-2h-4zm9 1v3h-5v2h5v3l2.5-2 2.5-2-2.5-2z" fill="#ff5f5f"/></svg>
diff --git a/editor/icons/Skeleton2D.svg b/editor/icons/Skeleton2D.svg
index b34a2a9dca..fc2555fb8a 100644
--- a/editor/icons/Skeleton2D.svg
+++ b/editor/icons/Skeleton2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 .26562v.001953h4v-.001953a2 2 0 0 0 1-.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0 -4-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-4 2h2v1h-2zm-2 2h1v1h1v-1h1 1v1h1v-1h1v.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-.86914z" fill="#a5b7f3"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 .26562v.001953h4v-.001953a2 2 0 0 0 1-.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0 -4-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-4 2h2v1h-2zm-2 2h1v1h1v-1h1 1v1h1v-1h1v.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-.86914z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/Skeleton3D.svg b/editor/icons/Skeleton3D.svg
index e0780dedd6..f1a1db86a9 100644
--- a/editor/icons/Skeleton3D.svg
+++ b/editor/icons/Skeleton3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 .26562v.001953h4v-.001953a2 2 0 0 0 1-.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0 -4-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-4 2h2v1h-2zm-2 2h1v1h1v-1h1 1v1h1v-1h1v.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-.86914z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 .26562v.001953h4v-.001953a2 2 0 0 0 1-.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0 -4-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-4 2h2v1h-2zm-2 2h1v1h1v-1h1 1v1h1v-1h1v.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-.86914z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/SliderJoint3D.svg b/editor/icons/SliderJoint3D.svg
index 57d22dff6a..20b265b766 100644
--- a/editor/icons/SliderJoint3D.svg
+++ b/editor/icons/SliderJoint3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-.55228 0-1 .44772-1 1s.44772 1 1 1h3l-7 7v3l12-12zm10 2-12 12h8c.55228 0 1-.44772 1-1s-.44772-1-1-1h-3l7-7z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-.55228 0-1 .44772-1 1s.44772 1 1 1h3l-7 7v3l12-12zm10 2-12 12h8c.55228 0 1-.44772 1-1s-.44772-1-1-1h-3l7-7z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/Slot.svg b/editor/icons/Slot.svg
index ec35be6b51..93c125a801 100644
--- a/editor/icons/Slot.svg
+++ b/editor/icons/Slot.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 3v2h4v6h-4v2h4 2v-10h-2zm-3 1v3h-5v2h5v3l2.5-2 2.5-2-2.5-2z" fill="#84ffb1"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 3v2h4v6h-4v2h4 2v-10h-2zm-3 1v3h-5v2h5v3l2.5-2 2.5-2-2.5-2z" fill="#5fff97"/></svg>
diff --git a/editor/icons/SoftBody3D.svg b/editor/icons/SoftBody3D.svg
index e46691d6a2..7bc9a22c22 100644
--- a/editor/icons/SoftBody3D.svg
+++ b/editor/icons/SoftBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1s-3 5 0 7-1 7-1 7h13s3-6 0-8 1-6 1-6zm2 2h7s-2 3 1 5 0 5 0 5h-7s2-4-1-6 0-4 0-4z" fill="#fc9c9c" fill-opacity=".996078"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1s-3 5 0 7-1 7-1 7h13s3-6 0-8 1-6 1-6zm2 2h7s-2 3 1 5 0 5 0 5h-7s2-4-1-6 0-4 0-4z" fill="#fc7f7f" fill-opacity=".996078"/></svg>
diff --git a/editor/icons/SphereMesh.svg b/editor/icons/SphereMesh.svg
index 66cc8e3cc4..be2dd44a34 100644
--- a/editor/icons/SphereMesh.svg
+++ b/editor/icons/SphereMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7s7-3.1458 7-7c0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-.071342-2.6061-.29819-3.9434-.69141.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549.41253 3.637 2.0767 3.9414 4.1699-1.3046.36677-2.6158.60259-3.9414.6875zm3.7852 6.2812c-.50864 1.7788-1.9499 3.1531-3.7852 3.5215v-2.9512c1.2792-.072301 2.5419-.26704 3.7852-.57031zm-9.5645.017578c1.2733.31892 2.5337.50215 3.7793.5625v2.9414c-1.8291-.36719-3.266-1.7339-3.7793-3.5039z" fill="#ffd684"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7s7-3.1458 7-7c0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-.071342-2.6061-.29819-3.9434-.69141.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549.41253 3.637 2.0767 3.9414 4.1699-1.3046.36677-2.6158.60259-3.9414.6875zm3.7852 6.2812c-.50864 1.7788-1.9499 3.1531-3.7852 3.5215v-2.9512c1.2792-.072301 2.5419-.26704 3.7852-.57031zm-9.5645.017578c1.2733.31892 2.5337.50215 3.7793.5625v2.9414c-1.8291-.36719-3.266-1.7339-3.7793-3.5039z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/SpinBox.svg b/editor/icons/SpinBox.svg
index a8dc55d8db..1206ada6bd 100644
--- a/editor/icons/SpinBox.svg
+++ b/editor/icons/SpinBox.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 3c-1.1046 0-2 .89543-2 2v6c0 1.1046.89543 2 2 2h7v-2-6-2zm10 1-2 3h4zm-10 1h5v6h-5zm8 4 2 3 2-3z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 3c-1.1046 0-2 .89543-2 2v6c0 1.1046.89543 2 2 2h7v-2-6-2zm10 1-2 3h4zm-10 1h5v6h-5zm8 4 2 3 2-3z" fill="#8eef97"/></svg>
diff --git a/editor/icons/SpotLight3D.svg b/editor/icons/SpotLight3D.svg
index a1dea938a3..73b738efcf 100644
--- a/editor/icons/SpotLight3D.svg
+++ b/editor/icons/SpotLight3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a1 1 0 0 0 -1 1v3.6934c-1.7861.86608-3 2.4605-3 4.3066h4a2 2 0 0 0 2 2 2 2 0 0 0 2-2h4c0-1.8462-1.2139-3.4406-3-4.3066v-3.6934a1 1 0 0 0 -1-1zm-1.0977 9.6348-1.7324 1 1 1.7305 1.7324-1zm6.1953 0-1 1.7305 1.7324 1 1-1.7305zm-4.0977 2.3652v2h2v-2z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a1 1 0 0 0 -1 1v3.6934c-1.7861.86608-3 2.4605-3 4.3066h4a2 2 0 0 0 2 2 2 2 0 0 0 2-2h4c0-1.8462-1.2139-3.4406-3-4.3066v-3.6934a1 1 0 0 0 -1-1zm-1.0977 9.6348-1.7324 1 1 1.7305 1.7324-1zm6.1953 0-1 1.7305 1.7324 1 1-1.7305zm-4.0977 2.3652v2h2v-2z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/SpringArm3D.svg b/editor/icons/SpringArm3D.svg
index 707e408dd9..e2c607c7bd 100644
--- a/editor/icons/SpringArm3D.svg
+++ b/editor/icons/SpringArm3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fc9c9c" stroke-width="2"><path d="m8 14 6-6"/><path d="m2 2 7 7"/><path d="m10 9h-6"/><path d="m9 9v-5"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fc7f7f" stroke-width="2"><path d="m8 14 6-6"/><path d="m2 2 7 7"/><path d="m10 9h-6"/><path d="m9 9v-5"/></g></svg>
diff --git a/editor/icons/Sprite2D.svg b/editor/icons/Sprite2D.svg
index faae0e444f..0d3ec05a30 100644
--- a/editor/icons/Sprite2D.svg
+++ b/editor/icons/Sprite2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-2.216 0-4 1.784-4 4v6c0 2.216 1.784 4 4 4h6c2.216 0 4-1.784 4-4v-6c0-2.216-1.784-4-4-4zm-1 5c.554 0 1 .446 1 1v2c0 .554-.446 1-1 1s-1-.446-1-1v-2c0-.554.446-1 1-1zm8 0c.554 0 1 .446 1 1v2c0 .554-.446 1-1 1s-1-.446-1-1v-2c0-.554.446-1 1-1zm-1.8887 5.1074a1.0001 1.0001 0 0 1 .7168 1.7207c-.74987.74987-1.7676 1.1719-2.8281 1.1719s-2.0783-.422-2.8281-1.1719a1.0001 1.0001 0 0 1 .69727-1.7168 1.0001 1.0001 0 0 1 .7168.30273c.37534.37535.88325.58594 1.4141.58594s1.0387-.21059 1.4141-.58594a1.0001 1.0001 0 0 1 .69727-.30664z" fill="#a5b7f3"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-2.216 0-4 1.784-4 4v6c0 2.216 1.784 4 4 4h6c2.216 0 4-1.784 4-4v-6c0-2.216-1.784-4-4-4zm-1 5c.554 0 1 .446 1 1v2c0 .554-.446 1-1 1s-1-.446-1-1v-2c0-.554.446-1 1-1zm8 0c.554 0 1 .446 1 1v2c0 .554-.446 1-1 1s-1-.446-1-1v-2c0-.554.446-1 1-1zm-1.8887 5.1074a1.0001 1.0001 0 0 1 .7168 1.7207c-.74987.74987-1.7676 1.1719-2.8281 1.1719s-2.0783-.422-2.8281-1.1719a1.0001 1.0001 0 0 1 .69727-1.7168 1.0001 1.0001 0 0 1 .7168.30273c.37534.37535.88325.58594 1.4141.58594s1.0387-.21059 1.4141-.58594a1.0001 1.0001 0 0 1 .69727-.30664z" fill="#8da5f3"/></svg>
diff --git a/editor/icons/Sprite3D.svg b/editor/icons/Sprite3D.svg
index 4ccd8f9c48..b002249ed7 100644
--- a/editor/icons/Sprite3D.svg
+++ b/editor/icons/Sprite3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-2.216 0-4 1.784-4 4v6c0 2.216 1.784 4 4 4h6c2.216 0 4-1.784 4-4v-6c0-2.216-1.784-4-4-4zm-1 5c.554 0 1 .446 1 1v2c0 .554-.446 1-1 1s-1-.446-1-1v-2c0-.554.446-1 1-1zm8 0c.554 0 1 .446 1 1v2c0 .554-.446 1-1 1s-1-.446-1-1v-2c0-.554.446-1 1-1zm-1.8887 5.1074a1.0001 1.0001 0 0 1 .7168 1.7207c-.74987.74987-1.7676 1.1719-2.8281 1.1719s-2.0783-.422-2.8281-1.1719a1.0001 1.0001 0 0 1 .69727-1.7168 1.0001 1.0001 0 0 1 .7168.30273c.37534.37535.88325.58594 1.4141.58594s1.0387-.21059 1.4141-.58594a1.0001 1.0001 0 0 1 .69727-.30664z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-2.216 0-4 1.784-4 4v6c0 2.216 1.784 4 4 4h6c2.216 0 4-1.784 4-4v-6c0-2.216-1.784-4-4-4zm-1 5c.554 0 1 .446 1 1v2c0 .554-.446 1-1 1s-1-.446-1-1v-2c0-.554.446-1 1-1zm8 0c.554 0 1 .446 1 1v2c0 .554-.446 1-1 1s-1-.446-1-1v-2c0-.554.446-1 1-1zm-1.8887 5.1074a1.0001 1.0001 0 0 1 .7168 1.7207c-.74987.74987-1.7676 1.1719-2.8281 1.1719s-2.0783-.422-2.8281-1.1719a1.0001 1.0001 0 0 1 .69727-1.7168 1.0001 1.0001 0 0 1 .7168.30273c.37534.37535.88325.58594 1.4141.58594s1.0387-.21059 1.4141-.58594a1.0001 1.0001 0 0 1 .69727-.30664z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/StandardMaterial3D.svg b/editor/icons/StandardMaterial3D.svg
index 7c52665a89..717ba5d239 100644
--- a/editor/icons/StandardMaterial3D.svg
+++ b/editor/icons/StandardMaterial3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002a1.0001 1.0001 0 0 0 -.41016.10352l-3.7891 1.8945h8.4727l-3.7891-1.8945a1.0001 1.0001 0 0 0 -.48438-.10352z" fill="#ff7070"/><path d="m3.7637 3-2.2109 1.1055a1.0001 1.0001 0 0 0 -.55273.89453h3.2363l3.7637-1.8809 3.7637 1.8809h3.2363a1.0001 1.0001 0 0 0 -.55273-.89453l-2.2109-1.1055h-8.4727z" fill="#ffeb70"/><path d="m1 5v2h2v-.38086l.76172.38086h8.4766l.76172-.38086v.38086h2v-2h-3.2363l-3.7637 1.8828-3.7637-1.8828h-3.2363z" fill="#9dff70"/><path d="m1 7v2h2v-2zm2.7617 0 3.2383 1.6191v.38086h2v-.38086l3.2383-1.6191zm9.2383 0v2h2v-2z" fill="#70ffb9"/><path d="m1 9v2h3.2344l-1.2344-.61719v-1.3828h-2zm6 0v2h2v-2zm6 0v1.3828l-1.2344.61719h3.2344v-2h-2z" fill="#70deff"/><path d="m3.7637 13 3.7891 1.8945a1.0001 1.0001 0 0 0 .48438.10547 1.0001 1.0001 0 0 0 .41016-.10547l3.7891-1.8945h-8.4727z" fill="#ff70ac"/><path d="m1 11a1.0001 1.0001 0 0 0 .55273.89453l2.2109 1.1055h8.4727l2.2109-1.1055a1.0001 1.0001 0 0 0 .55273-.89453h-3.2344l-2.7656 1.3828v-1.3828h-2v1.3828l-2.7656-1.3828h-3.2344z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002a1.0001 1.0001 0 0 0 -.41016.10352l-3.7891 1.8945h8.4727l-3.7891-1.8945a1.0001 1.0001 0 0 0 -.48438-.10352z" fill="#ff4545"/><path d="m3.7637 3-2.2109 1.1055a1.0001 1.0001 0 0 0 -.55273.89453h3.2363l3.7637-1.8809 3.7637 1.8809h3.2363a1.0001 1.0001 0 0 0 -.55273-.89453l-2.2109-1.1055h-8.4727z" fill="#ffe345"/><path d="m1 5v2h2v-.38086l.76172.38086h8.4766l.76172-.38086v.38086h2v-2h-3.2363l-3.7637 1.8828-3.7637-1.8828h-3.2363z" fill="#80ff45"/><path d="m1 7v2h2v-2zm2.7617 0 3.2383 1.6191v.38086h2v-.38086l3.2383-1.6191zm9.2383 0v2h2v-2z" fill="#45ffa2"/><path d="m1 9v2h3.2344l-1.2344-.61719v-1.3828h-2zm6 0v2h2v-2zm6 0v1.3828l-1.2344.61719h3.2344v-2h-2z" fill="#45d7ff"/><path d="m3.7637 13 3.7891 1.8945a1.0001 1.0001 0 0 0 .48438.10547 1.0001 1.0001 0 0 0 .41016-.10547l3.7891-1.8945h-8.4727z" fill="#ff4596"/><path d="m1 11a1.0001 1.0001 0 0 0 .55273.89453l2.2109 1.1055h8.4727l2.2109-1.1055a1.0001 1.0001 0 0 0 .55273-.89453h-3.2344l-2.7656 1.3828v-1.3828h-2v1.3828l-2.7656-1.3828h-3.2344z" fill="#8045ff"/></svg>
diff --git a/editor/icons/StaticBody2D.svg b/editor/icons/StaticBody2D.svg
index 66940ad415..ba61605522 100644
--- a/editor/icons/StaticBody2D.svg
+++ b/editor/icons/StaticBody2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m29 1042.4h1v1h-1z" fill="#fefeff"/><path d="m3 1a2 2 0 0 0 -1.4141.58594 2 2 0 0 0 -.58594 1.4141v10a2 2 0 0 0 .58594 1.4141 2 2 0 0 0 1.4141.58594h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2h-10zm0 1h10a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-10a1 1 0 0 1 1-1zm0 1v2h2v-2zm8 0v2h2v-2zm-8 8v2h2v-2zm8 0v2h2v-2z" fill="#a5b7f3" fill-opacity=".98824" transform="translate(0 1036.4)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m29 1042.4h1v1h-1z" fill="#fefeff"/><path d="m3 1a2 2 0 0 0 -1.4141.58594 2 2 0 0 0 -.58594 1.4141v10a2 2 0 0 0 .58594 1.4141 2 2 0 0 0 1.4141.58594h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2h-10zm0 1h10a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-10a1 1 0 0 1 1-1zm0 1v2h2v-2zm8 0v2h2v-2zm-8 8v2h2v-2zm8 0v2h2v-2z" fill="#8da5f3" fill-opacity=".98824" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/StaticBody3D.svg b/editor/icons/StaticBody3D.svg
index a4a641f28c..55b061571f 100644
--- a/editor/icons/StaticBody3D.svg
+++ b/editor/icons/StaticBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -1.4141.58594 2 2 0 0 0 -.58594 1.4141v10a2 2 0 0 0 .58594 1.4141 2 2 0 0 0 1.4141.58594h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2h-10zm0 1h10a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-10a1 1 0 0 1 1-1zm0 1v2h2v-2zm8 0v2h2v-2zm-8 8v2h2v-2zm8 0v2h2v-2z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -1.4141.58594 2 2 0 0 0 -.58594 1.4141v10a2 2 0 0 0 .58594 1.4141 2 2 0 0 0 1.4141.58594h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2h-10zm0 1h10a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-10a1 1 0 0 1 1-1zm0 1v2h2v-2zm8 0v2h2v-2zm-8 8v2h2v-2zm8 0v2h2v-2z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/String.svg b/editor/icons/String.svg
index 5b7ade8b1e..abcb92d4b2 100644
--- a/editor/icons/String.svg
+++ b/editor/icons/String.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 2a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3-3v-2a1 1 0 0 1 1-1h1v-2zm2 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-1h2v-2h-2v-2zm8 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1h1v-2z" fill="#6ba7ec"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 2a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3-3v-2a1 1 0 0 1 1-1h1v-2zm2 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-1h2v-2h-2v-2zm8 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1-1h1v-2z" fill="#4593ec"/></svg>
diff --git a/editor/icons/StringName.svg b/editor/icons/StringName.svg
index 8f2ef13a37..3b67f2accd 100644
--- a/editor/icons/StringName.svg
+++ b/editor/icons/StringName.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 2c-1.6569 0-3 1.3431-3 3v2c0 .55228-.44772 1-1 1h-1v2h1c1.6569 0 3-1.3431 3-3v-2c0-.55228.44772-1 1-1h1v3c0 1.6569 1.3431 3 3 3h3v-4h1c.55228 0 1 .44772 1 1v3h2v-3c0-1.6569-1.3431-3-3-3h-5v-2zm3 4h2v2h-1c-.55228 0-1-.44772-1-1z" fill="#6ba7ec"/><path d="m10 4v6h2v-4h1c.55228 0 1 .44772 1 1v3h2v-3c0-1.6569-1.3431-3-3-3h-1z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 2c-1.6569 0-3 1.3431-3 3v2c0 .55228-.44772 1-1 1h-1v2h1c1.6569 0 3-1.3431 3-3v-2c0-.55228.44772-1 1-1h1v3c0 1.6569 1.3431 3 3 3h3v-4h1c.55228 0 1 .44772 1 1v3h2v-3c0-1.6569-1.3431-3-3-3h-5v-2zm3 4h2v2h-1c-.55228 0-1-.44772-1-1z" fill="#4593ec"/><path d="m10 4v6h2v-4h1c.55228 0 1 .44772 1 1v3h2v-3c0-1.6569-1.3431-3-3-3h-1z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/StyleBoxEmpty.svg b/editor/icons/StyleBoxEmpty.svg
index e1a2bc6888..3c4546dff5 100644
--- a/editor/icons/StyleBoxEmpty.svg
+++ b/editor/icons/StyleBoxEmpty.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v1h2v-2zm3 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2v-1c-.000055-.5523-.44774-.9999-1-1z" fill="#ff7070"/><path d="m1 5v2h2v-2zm12 0v.23242c.31584.1783.57817.43795.75977.75195.19142.33153.43699.67036.69922 1.0156h.54102v-2h-2z" fill="#9dff70"/><path d="m12 7c-.43047.7456-.94451 1.3867-1.4355 2h2.8711c-.49104-.6133-1.0051-1.2544-1.4355-2zm2.459 0c.17438.2296.352.46082.54102.69922v-.69922z" fill="#70ffb9"/><path d="m1 9v2h2v-2zm9.5645 0c-.55248.69003-1.0583 1.3421-1.334 2h5.5391c-.2757-.65786-.78151-1.31-1.334-2z" fill="#70deff"/><path d="m1 13v1c.0000552.5523.44774.9999 1 1h1v-2zm4 0v2h2v-2zm4.1836 0c.41312 1.1628 1.5119 2 2.8164 2s2.4033-.83718 2.8164-2z" fill="#ff70ac"/><path d="m9.2305 11c-.13656.32585-.23047.65576-.23047 1 0 .35235.07201.68593.18359 1h5.6328c.11158-.31407.18359-.64765.18359-1 0-.34424-.093909-.67415-.23047-1h-5.5391z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v1h2v-2zm3 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2v-1c-.000055-.5523-.44774-.9999-1-1z" fill="#ff4545"/><path d="m1 5v2h2v-2zm12 0v.23242c.31584.1783.57817.43795.75977.75195.19142.33153.43699.67036.69922 1.0156h.54102v-2h-2z" fill="#80ff45"/><path d="m12 7c-.43047.7456-.94451 1.3867-1.4355 2h2.8711c-.49104-.6133-1.0051-1.2544-1.4355-2zm2.459 0c.17438.2296.352.46082.54102.69922v-.69922z" fill="#45ffa2"/><path d="m1 9v2h2v-2zm9.5645 0c-.55248.69003-1.0583 1.3421-1.334 2h5.5391c-.2757-.65786-.78151-1.31-1.334-2z" fill="#45d7ff"/><path d="m1 13v1c.0000552.5523.44774.9999 1 1h1v-2zm4 0v2h2v-2zm4.1836 0c.41312 1.1628 1.5119 2 2.8164 2s2.4033-.83718 2.8164-2z" fill="#ff4596"/><path d="m9.2305 11c-.13656.32585-.23047.65576-.23047 1 0 .35235.07201.68593.18359 1h5.6328c.11158-.31407.18359-.64765.18359-1 0-.34424-.093909-.67415-.23047-1h-5.5391z" fill="#8045ff"/></svg>
diff --git a/editor/icons/StyleBoxFlat.svg b/editor/icons/StyleBoxFlat.svg
index b24c453f6b..5bf01f5e66 100644
--- a/editor/icons/StyleBoxFlat.svg
+++ b/editor/icons/StyleBoxFlat.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v1h14v-1c-.000055-.5523-.44774-.9999-1-1z" fill="#ff7070"/><path d="m1 3v2h14v-2z" fill="#ffeb70"/><path d="m1 5v2h8.582c.25686-.33847.49465-.66934.68555-1 .33885-.5859.95103-.96109 1.627-.99609.7512-.04 1.4613.34489 1.8379.99609.18899.32737.42831.66049.68555 1h.58203v-2h-14z" fill="#9dff70"/><path d="m1 7v2h7.0547c.14116-.20345.28508-.40233.42383-.58398.38601-.5053.76348-.96794 1.1035-1.416h-8.582zm11 0c-.43047.7456-.94451 1.3867-1.4355 2h2.8711c-.49104-.6133-1.0051-1.2544-1.4355-2zm2.418 0c.18626.24583.37928.49419.58203.75v-.75z" fill="#70ffb9"/><path d="m1 9v2h6.1172c.17955-.78395.54577-1.4354.9375-2zm9.5645 0c-.55248.69003-1.0583 1.3421-1.334 2h5.5391c-.2757-.65786-.78151-1.31-1.334-2z" fill="#70deff"/><path d="m1 13v1c.0000552.5523.44774.9999 1 1h6.0371c-.44511-.58388-.76161-1.2639-.91992-2h-6.1172zm8.1836 0c.41312 1.1628 1.5119 2 2.8164 2s2.4033-.83718 2.8164-2z" fill="#ff70ac"/><path d="m1 11v2h6.1172c-.06966-.3239-.11719-.65596-.11719-1 0-.35655.045474-.68688.11719-1zm8.2305 0c-.13656.32585-.23047.65576-.23047 1 0 .35235.07201.68593.18359 1h5.6328c.11158-.31407.18359-.64765.18359-1 0-.34424-.093909-.67415-.23047-1h-5.5391z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v1h14v-1c-.000055-.5523-.44774-.9999-1-1z" fill="#ff4545"/><path d="m1 3v2h14v-2z" fill="#ffe345"/><path d="m1 5v2h8.582c.25686-.33847.49465-.66934.68555-1 .33885-.5859.95103-.96109 1.627-.99609.7512-.04 1.4613.34489 1.8379.99609.18899.32737.42831.66049.68555 1h.58203v-2h-14z" fill="#80ff45"/><path d="m1 7v2h7.0547c.14116-.20345.28508-.40233.42383-.58398.38601-.5053.76348-.96794 1.1035-1.416h-8.582zm11 0c-.43047.7456-.94451 1.3867-1.4355 2h2.8711c-.49104-.6133-1.0051-1.2544-1.4355-2zm2.418 0c.18626.24583.37928.49419.58203.75v-.75z" fill="#45ffa2"/><path d="m1 9v2h6.1172c.17955-.78395.54577-1.4354.9375-2zm9.5645 0c-.55248.69003-1.0583 1.3421-1.334 2h5.5391c-.2757-.65786-.78151-1.31-1.334-2z" fill="#45d7ff"/><path d="m1 13v1c.0000552.5523.44774.9999 1 1h6.0371c-.44511-.58388-.76161-1.2639-.91992-2h-6.1172zm8.1836 0c.41312 1.1628 1.5119 2 2.8164 2s2.4033-.83718 2.8164-2z" fill="#ff4596"/><path d="m1 11v2h6.1172c-.06966-.3239-.11719-.65596-.11719-1 0-.35655.045474-.68688.11719-1zm8.2305 0c-.13656.32585-.23047.65576-.23047 1 0 .35235.07201.68593.18359 1h5.6328c.11158-.31407.18359-.64765.18359-1 0-.34424-.093909-.67415-.23047-1h-5.5391z" fill="#8045ff"/></svg>
diff --git a/editor/icons/StyleBoxLine.svg b/editor/icons/StyleBoxLine.svg
index e92f33b7b0..995f56f726 100644
--- a/editor/icons/StyleBoxLine.svg
+++ b/editor/icons/StyleBoxLine.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.303 1c-.4344 0-.86973.16881-1.2012.50586l-1.4688 1.4941h4.3418c.082839-.52789-.072596-1.0872-.47266-1.4941-.33144-.33705-.76482-.50586-1.1992-.50586z" fill="#ff7070"/><path d="m10.633 3-1.9668 2h4.8008l1.0352-1.0527c.2628-.2673.41824-.60049.47266-.94727h-4.3418z" fill="#ffeb70"/><path d="m8.666 5-1.9648 2h2.8809c.25686-.33847.49465-.66934.68555-1 .33885-.5859.95098-.96109 1.627-.99609.44399-.023642.86385.115 1.2188.35547l.35352-.35938h-4.8008z" fill="#9dff70"/><path d="m1.2617 13c-.08284.52789.072596 1.0872.47266 1.4941.33144.33705.76484.50586 1.1992.50586.4344 0 .8697-.16881 1.2012-.50586l1.4688-1.4941h-4.3418zm7.9219 0c.41312 1.1628 1.5119 2 2.8164 2s2.4033-.83718 2.8164-2z" fill="#ff70ac"/><path d="m2.7695 11-1.0352 1.0527c-.2628.2673-.41824.60049-.47266.94727h4.3418l1.4238-1.4473c.020288-.18998.04923-.37542.089844-.55273h-4.3477zm6.4609 0c-.13656.32585-.23047.65576-.23047 1 0 .35235.072014.68593.18359 1h5.6328c.11158-.31407.18359-.64765.18359-1 0-.34424-.093909-.67415-.23047-1h-5.5391z" fill="#9f70ff"/><path d="m4.7363 9-1.9668 2h4.3477c.17955-.78395.54577-1.4354.9375-2zm5.8281 0c-.55248.69003-1.0583 1.3421-1.334 2h5.5391c-.2757-.65786-.78149-1.31-1.334-2z" fill="#70deff"/><path d="m6.7012 7-1.9648 2h3.3184c.14116-.20345.28508-.40233.42383-.58398.38601-.5053.7635-.96796 1.1035-1.416h-2.8809zm5.2988 0c-.43047.7456-.94456 1.3867-1.4355 2h2.8711c-.49104-.6133-1.0051-1.2544-1.4355-2z" fill="#70ffb9"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.303 1c-.4344 0-.86973.16881-1.2012.50586l-1.4688 1.4941h4.3418c.082839-.52789-.072596-1.0872-.47266-1.4941-.33144-.33705-.76482-.50586-1.1992-.50586z" fill="#ff4545"/><path d="m10.633 3-1.9668 2h4.8008l1.0352-1.0527c.2628-.2673.41824-.60049.47266-.94727h-4.3418z" fill="#ffe345"/><path d="m8.666 5-1.9648 2h2.8809c.25686-.33847.49465-.66934.68555-1 .33885-.5859.95098-.96109 1.627-.99609.44399-.023642.86385.115 1.2188.35547l.35352-.35938h-4.8008z" fill="#80ff45"/><path d="m1.2617 13c-.08284.52789.072596 1.0872.47266 1.4941.33144.33705.76484.50586 1.1992.50586.4344 0 .8697-.16881 1.2012-.50586l1.4688-1.4941h-4.3418zm7.9219 0c.41312 1.1628 1.5119 2 2.8164 2s2.4033-.83718 2.8164-2z" fill="#ff4596"/><path d="m2.7695 11-1.0352 1.0527c-.2628.2673-.41824.60049-.47266.94727h4.3418l1.4238-1.4473c.020288-.18998.04923-.37542.089844-.55273h-4.3477zm6.4609 0c-.13656.32585-.23047.65576-.23047 1 0 .35235.072014.68593.18359 1h5.6328c.11158-.31407.18359-.64765.18359-1 0-.34424-.093909-.67415-.23047-1h-5.5391z" fill="#8045ff"/><path d="m4.7363 9-1.9668 2h4.3477c.17955-.78395.54577-1.4354.9375-2zm5.8281 0c-.55248.69003-1.0583 1.3421-1.334 2h5.5391c-.2757-.65786-.78149-1.31-1.334-2z" fill="#45d7ff"/><path d="m6.7012 7-1.9648 2h3.3184c.14116-.20345.28508-.40233.42383-.58398.38601-.5053.7635-.96796 1.1035-1.416h-2.8809zm5.2988 0c-.43047.7456-.94456 1.3867-1.4355 2h2.8711c-.49104-.6133-1.0051-1.2544-1.4355-2z" fill="#45ffa2"/></svg>
diff --git a/editor/icons/StyleBoxTexture.svg b/editor/icons/StyleBoxTexture.svg
index 89bbc41ef8..a356d11885 100644
--- a/editor/icons/StyleBoxTexture.svg
+++ b/editor/icons/StyleBoxTexture.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1.0001 1.0001 0 0 0 -1 1v1h2 10 2v-1a1.0001 1.0001 0 0 0 -1-1z" fill="#ff7070"/><path d="m1 3v2h2v-2zm12 0v2h2v-2zm-4 1v1h1v-1z" fill="#ffeb70"/><path d="m1 5v2h2v-2zm7 0v1h-2v1h3.543c.26215-.34438.50373-.68039.69727-1.0156a2.0315 2.0315 0 0 1 .75977-.75195v-.23242h-1-1-1zm5 0v.23242a2.0315 2.0315 0 0 1 .75977.75195c.19142.33153.43699.67033.69922 1.0156h.54102v-2h-2z" fill="#9dff70"/><path d="m1 7v2h2v-2zm4 0v1h-1v1h4.0156c.14585-.2113.29419-.41592.4375-.60352.38121-.49904.75394-.95521 1.0898-1.3965h-3.543-1zm7 0c-.43047.7456-.94451 1.3867-1.4355 2h2.8711c-.49104-.6133-1.0051-1.2544-1.4355-2zm2.459 0c.17438.22962.352.46082.54102.69922v-.69922z" fill="#70ffb9"/><path d="m1 9v2h2v-2zm9.5645 0c-.55248.69003-1.0583 1.3421-1.334 2h5.5391c-.2757-.65786-.78151-1.31-1.334-2z" fill="#70deff"/><path d="m1 13v1a1.0001 1.0001 0 0 0 1 1h5.998c-.4429-.5864-.77294-1.2592-.92578-2h-4.0723-2zm8.1836 0c.41312 1.1628 1.5119 2 2.8164 2s2.4033-.83718 2.8164-2z" fill="#ff70ac"/><path d="m1 11v2h2v-2zm8.2305 0c-.13656.32585-.23047.65576-.23047 1 0 .35235.07201.68593.18359 1h5.6328c.11158-.31407.18359-.64765.18359-1 0-.34424-.093909-.67415-.23047-1h-5.5391z" fill="#9f70ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1.0001 1.0001 0 0 0 -1 1v1h2 10 2v-1a1.0001 1.0001 0 0 0 -1-1z" fill="#ff4545"/><path d="m1 3v2h2v-2zm12 0v2h2v-2zm-4 1v1h1v-1z" fill="#ffe345"/><path d="m1 5v2h2v-2zm7 0v1h-2v1h3.543c.26215-.34438.50373-.68039.69727-1.0156a2.0315 2.0315 0 0 1 .75977-.75195v-.23242h-1-1-1zm5 0v.23242a2.0315 2.0315 0 0 1 .75977.75195c.19142.33153.43699.67033.69922 1.0156h.54102v-2h-2z" fill="#80ff45"/><path d="m1 7v2h2v-2zm4 0v1h-1v1h4.0156c.14585-.2113.29419-.41592.4375-.60352.38121-.49904.75394-.95521 1.0898-1.3965h-3.543-1zm7 0c-.43047.7456-.94451 1.3867-1.4355 2h2.8711c-.49104-.6133-1.0051-1.2544-1.4355-2zm2.459 0c.17438.22962.352.46082.54102.69922v-.69922z" fill="#45ffa2"/><path d="m1 9v2h2v-2zm9.5645 0c-.55248.69003-1.0583 1.3421-1.334 2h5.5391c-.2757-.65786-.78151-1.31-1.334-2z" fill="#45d7ff"/><path d="m1 13v1a1.0001 1.0001 0 0 0 1 1h5.998c-.4429-.5864-.77294-1.2592-.92578-2h-4.0723-2zm8.1836 0c.41312 1.1628 1.5119 2 2.8164 2s2.4033-.83718 2.8164-2z" fill="#ff4596"/><path d="m1 11v2h2v-2zm8.2305 0c-.13656.32585-.23047.65576-.23047 1 0 .35235.07201.68593.18359 1h5.6328c.11158-.31407.18359-.64765.18359-1 0-.34424-.093909-.67415-.23047-1h-5.5391z" fill="#8045ff"/></svg>
diff --git a/editor/icons/SubViewportContainer.svg b/editor/icons/SubViewportContainer.svg
index baf80e5086..e4584c3b9a 100644
--- a/editor/icons/SubViewportContainer.svg
+++ b/editor/icons/SubViewportContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm3 1c-.5304.0001-1.0391.21084-1.4141.58594-.37509.375-.58586.88366-.58594 1.4141v4c.00008.5304.21085 1.0391.58594 1.4141.37501.3751.88366.58584 1.4141.58594h4c1.1046 0 2-.8954 2-2v-4c0-1.1046-.89543-2-2-2zm0 1h4c.55228 0 .99999.4477 1 1v4c-.00001.5523-.44772 1-1 1h-4c-.55228 0-.99999-.4477-1-1v-4c.00001-.5523.44772-1 1-1z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm3 1c-.5304.0001-1.0391.21084-1.4141.58594-.37509.375-.58586.88366-.58594 1.4141v4c.00008.5304.21085 1.0391.58594 1.4141.37501.3751.88366.58584 1.4141.58594h4c1.1046 0 2-.8954 2-2v-4c0-1.1046-.89543-2-2-2zm0 1h4c.55228 0 .99999.4477 1 1v4c-.00001.5523-.44772 1-1 1h-4c-.55228 0-.99999-.4477-1-1v-4c.00001-.5523.44772-1 1-1z" fill="#8eef97"/></svg>
diff --git a/editor/icons/TabContainer.svg b/editor/icons/TabContainer.svg
index aeb5507279..92ca60911a 100644
--- a/editor/icons/TabContainer.svg
+++ b/editor/icons/TabContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h5v2 2h5v6h-10zm7 0h3v2h-3z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h5v2 2h5v6h-10zm7 0h3v2h-3z" fill="#8eef97"/></svg>
diff --git a/editor/icons/Tabs.svg b/editor/icons/Tabs.svg
index 4fd4a5cd80..e20a1a0131 100644
--- a/editor/icons/Tabs.svg
+++ b/editor/icons/Tabs.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 4c-1.108 0-1.8178.9071-2 2l-1 6h-1v2h4 6 4v-2h-2l-1-6c-.18216-1.0929-.89199-2-2-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 4c-1.108 0-1.8178.9071-2 2l-1 6h-1v2h4 6 4v-2h-2l-1-6c-.18216-1.0929-.89199-2-2-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/TestCube.svg b/editor/icons/TestCube.svg
index bdfb3c893b..9995f5b5f4 100644
--- a/editor/icons/TestCube.svg
+++ b/editor/icons/TestCube.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002a1.0001 1.0001 0 0 0 -.41016.10352l-6 3a1.0001 1.0001 0 0 0 -.55273.89453v6a1.0001 1.0001 0 0 0 .55273.89453l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1.0001 1.0001 0 0 0 .55273-.89453v-6a1.0001 1.0001 0 0 0 -.55273-.89453l-6-3a1.0001 1.0001 0 0 0 -.48438-.10352zm.037109 2.1172 3.7637 1.8809-3.7637 1.8828-3.7637-1.8828zm-5 3.5 4 2v3.7637l-4-2zm10 0v3.7637l-4 2v-3.7637z" fill="#fc9c9c" fill-opacity=".99608" fill-rule="evenodd" transform="translate(0 .000012)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002a1.0001 1.0001 0 0 0 -.41016.10352l-6 3a1.0001 1.0001 0 0 0 -.55273.89453v6a1.0001 1.0001 0 0 0 .55273.89453l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1.0001 1.0001 0 0 0 .55273-.89453v-6a1.0001 1.0001 0 0 0 -.55273-.89453l-6-3a1.0001 1.0001 0 0 0 -.48438-.10352zm.037109 2.1172 3.7637 1.8809-3.7637 1.8828-3.7637-1.8828zm-5 3.5 4 2v3.7637l-4-2zm10 0v3.7637l-4 2v-3.7637z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd" transform="translate(0 .000012)"/></svg>
diff --git a/editor/icons/TextEdit.svg b/editor/icons/TextEdit.svg
index 366cf6596d..67a5145373 100644
--- a/editor/icons/TextEdit.svg
+++ b/editor/icons/TextEdit.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m29 1042.4h1v1h-1z" fill="#fefeff"/><path d="m3 1c-1.1046 0-2 .8954-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.8954 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm1 1v4h1v-4z" fill="#a5efac" transform="translate(0 1036.4)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m29 1042.4h1v1h-1z" fill="#fefeff"/><path d="m3 1c-1.1046 0-2 .8954-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.8954 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v10h-10zm1 1v4h1v-4z" fill="#8eef97" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/icons/TextureButton.svg b/editor/icons/TextureButton.svg
index 497386945e..8d3d1c52ce 100644
--- a/editor/icons/TextureButton.svg
+++ b/editor/icons/TextureButton.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1v2h6v10h-4v2h6v-14zm-5 1v3.1328l-1.4453-.96484-1.1094 1.6641 3 2c.3359.2239.77347.2239 1.1094 0l3-2-1.1094-1.6641-1.4453.96484v-3.1328zm7 4v1h-1v1h-1v1h1v2h2 2v-2h-1v-2h-1v-1zm-7.5 4c-.831 0-1.5.669-1.5 1.5v.5 1h-1v2h8v-2h-1v-1-.5c0-.831-.669-1.5-1.5-1.5z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1v2h6v10h-4v2h6v-14zm-5 1v3.1328l-1.4453-.96484-1.1094 1.6641 3 2c.3359.2239.77347.2239 1.1094 0l3-2-1.1094-1.6641-1.4453.96484v-3.1328zm7 4v1h-1v1h-1v1h1v2h2 2v-2h-1v-2h-1v-1zm-7.5 4c-.831 0-1.5.669-1.5 1.5v.5 1h-1v2h8v-2h-1v-1-.5c0-.831-.669-1.5-1.5-1.5z" fill="#8eef97"/></svg>
diff --git a/editor/icons/TextureProgressBar.svg b/editor/icons/TextureProgressBar.svg
index 30d76e33b8..a72f0e5754 100644
--- a/editor/icons/TextureProgressBar.svg
+++ b/editor/icons/TextureProgressBar.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#a5efac" transform="translate(0 -1036.4)"><path d="m3 3c-1.1046 0-2 .89543-2 2v6c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-6c0-1.1046-.89543-2-2-2zm0 2h10v6h-10z" transform="translate(0 1036.4)"/><path d="m4 1042.4h1v2h-1z"/><path d="m6 1043.4h1v3h-1z"/><path d="m8 1042.4h1v4h-1z"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#8eef97" transform="translate(0 -1036.4)"><path d="m3 3c-1.1046 0-2 .89543-2 2v6c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-6c0-1.1046-.89543-2-2-2zm0 2h10v6h-10z" transform="translate(0 1036.4)"/><path d="m4 1042.4h1v2h-1z"/><path d="m6 1043.4h1v3h-1z"/><path d="m8 1042.4h1v4h-1z"/></g></svg>
diff --git a/editor/icons/TextureRect.svg b/editor/icons/TextureRect.svg
index 605afbb7ca..5f55c06bce 100644
--- a/editor/icons/TextureRect.svg
+++ b/editor/icons/TextureRect.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h14v-14zm2 2h10v10h-10zm6 3v1h-1v1h-2v1h-1v1h-1v1h2 2 2 2v-2h-1v-2h-1v-1z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v14h14v-14zm2 2h10v10h-10zm6 3v1h-1v1h-2v1h-1v1h-1v1h2 2 2 2v-2h-1v-2h-1v-1z" fill="#8eef97"/></svg>
diff --git a/editor/icons/Theme.svg b/editor/icons/Theme.svg
index 00e1716dad..401d884022 100644
--- a/editor/icons/Theme.svg
+++ b/editor/icons/Theme.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width="0"><path d="m6.7246 3c-.52985.78935-.96267 1.4021-1.3945 2h5.3398c-.43187-.59786-.86468-1.2107-1.3945-2z" fill="#ffeb70"/><path d="m5.3301 5c-.52617.72841-1.0198 1.4208-1.375 2h8.0898c-.35516-.57924-.84883-1.2716-1.375-2z" fill="#9dff70"/><path d="m3.9551 7c-.41451.67603-.71534 1.3082-.85547 2h9.8008c-.14013-.69181-.44096-1.324-.85547-2h-8.0898z" fill="#70ffb9"/><path d="m3.0996 9c-.063989.3159-.099609.64498-.099609 1 0 .34242.034776.67693.10156 1h9.7969c.066786-.32307.10156-.65758.10156-1 0-.35502-.03562-.6841-.099609-1h-9.8008z" fill="#70deff"/><path d="m3.1016 11c.15381.74405.48967 1.4159.93555 2h7.9258c.44588-.5841.78173-1.2559.93555-2h-9.7969z" fill="#9f70ff"/><path d="m4.0371 13c.9218 1.2076 2.3612 2 3.9629 2s3.0411-.79243 3.9629-2z" fill="#ff70ac"/><path d="m8 1c-.45196.75327-.87224 1.3994-1.2754 2h2.5508c-.40315-.6006-.82343-1.2467-1.2754-2z" fill="#ff7070"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width="0"><path d="m6.7246 3c-.52985.78935-.96267 1.4021-1.3945 2h5.3398c-.43187-.59786-.86468-1.2107-1.3945-2z" fill="#ffe345"/><path d="m5.3301 5c-.52617.72841-1.0198 1.4208-1.375 2h8.0898c-.35516-.57924-.84883-1.2716-1.375-2z" fill="#80ff45"/><path d="m3.9551 7c-.41451.67603-.71534 1.3082-.85547 2h9.8008c-.14013-.69181-.44096-1.324-.85547-2h-8.0898z" fill="#45ffa2"/><path d="m3.0996 9c-.063989.3159-.099609.64498-.099609 1 0 .34242.034776.67693.10156 1h9.7969c.066786-.32307.10156-.65758.10156-1 0-.35502-.03562-.6841-.099609-1h-9.8008z" fill="#45d7ff"/><path d="m3.1016 11c.15381.74405.48967 1.4159.93555 2h7.9258c.44588-.5841.78173-1.2559.93555-2h-9.7969z" fill="#8045ff"/><path d="m4.0371 13c.9218 1.2076 2.3612 2 3.9629 2s3.0411-.79243 3.9629-2z" fill="#ff4596"/><path d="m8 1c-.45196.75327-.87224 1.3994-1.2754 2h2.5508c-.40315-.6006-.82343-1.2467-1.2754-2z" fill="#ff4545"/></g></svg>
diff --git a/editor/icons/ThemeRemoveAllItems.svg b/editor/icons/ThemeRemoveAllItems.svg
index 652274a0e7..c04254ea8d 100644
--- a/editor/icons/ThemeRemoveAllItems.svg
+++ b/editor/icons/ThemeRemoveAllItems.svg
@@ -1 +1 @@
-<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1.745c-.595 0-1.084.489-1.084 1.084v3.699l-3.851-1.927c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.076.151-.115.317-.115.485 0 .41.233.786.599.97l3.481 1.74-3.481 1.74c-.366.184-.599.56-.599.97 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114l3.851-1.927v3.111c0 .594.489 1.084 1.084 1.084s1.084-.49 1.084-1.084v-3.111l3.851 1.927c.151.075.317.114.485.114.41 0 .786-.232.969-.599.076-.151.115-.317.115-.485 0-.41-.233-.786-.599-.97l-3.481-1.74 3.481-1.74c.366-.184.599-.56.599-.97 0-.168-.039-.334-.115-.485-.182-.364-.554-.596-.961-.599-.171-.001-.34.038-.493.114l-3.851 1.927v-3.699c0-.595-.489-1.084-1.084-1.084z" fill="#a5efac"/><g fill-rule="nonzero"><path d="m8 1.745v1.783h-1.084v-.699c0-.595.489-1.084 1.084-1.084z" fill="#ff7070"/><path d="m1.528 5.312h2.957l-1.42-.711c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.036.072-.064.148-.083.226zm5.388-1.784h1.084v1.784h-1.084z" fill="#ffeb70"/><path d="m6.916 5.312h1.084v1.783h-4.796l-1.109-.554c-.366-.184-.599-.56-.599-.97 0-.088.011-.175.032-.259h2.957l2.431 1.216z" fill="#9dff70"/><path d="m3.204 7.095h4.796v1.783h-3.619l1.195-.597z" fill="#70ffb9"/><path d="m4.381 8.878h3.619v1.784h-1.084v-.628l-1.255.628h-4.114c.088-.274.283-.508.548-.641z" fill="#70deff"/><path d="m6.916 12.445h1.084v1.784c-.595-.001-1.084-.49-1.084-1.084z" fill="#ff70ac"/><path d="m6.916 10.662h1.084v1.783h-1.084zm-1.255 0h-4.114c-.033.105-.051.216-.051.329 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114z" fill="#9f70ff"/></g></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1.745c-.595 0-1.084.489-1.084 1.084v3.699l-3.851-1.927c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.076.151-.115.317-.115.485 0 .41.233.786.599.97l3.481 1.74-3.481 1.74c-.366.184-.599.56-.599.97 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114l3.851-1.927v3.111c0 .594.489 1.084 1.084 1.084s1.084-.49 1.084-1.084v-3.111l3.851 1.927c.151.075.317.114.485.114.41 0 .786-.232.969-.599.076-.151.115-.317.115-.485 0-.41-.233-.786-.599-.97l-3.481-1.74 3.481-1.74c.366-.184.599-.56.599-.97 0-.168-.039-.334-.115-.485-.182-.364-.554-.596-.961-.599-.171-.001-.34.038-.493.114l-3.851 1.927v-3.699c0-.595-.489-1.084-1.084-1.084z" fill="#8eef97"/><g fill-rule="nonzero"><path d="m8 1.745v1.783h-1.084v-.699c0-.595.489-1.084 1.084-1.084z" fill="#ff4545"/><path d="m1.528 5.312h2.957l-1.42-.711c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.036.072-.064.148-.083.226zm5.388-1.784h1.084v1.784h-1.084z" fill="#ffe345"/><path d="m6.916 5.312h1.084v1.783h-4.796l-1.109-.554c-.366-.184-.599-.56-.599-.97 0-.088.011-.175.032-.259h2.957l2.431 1.216z" fill="#80ff45"/><path d="m3.204 7.095h4.796v1.783h-3.619l1.195-.597z" fill="#45ffa2"/><path d="m4.381 8.878h3.619v1.784h-1.084v-.628l-1.255.628h-4.114c.088-.274.283-.508.548-.641z" fill="#45d7ff"/><path d="m6.916 12.445h1.084v1.784c-.595-.001-1.084-.49-1.084-1.084z" fill="#ff4596"/><path d="m6.916 10.662h1.084v1.783h-1.084zm-1.255 0h-4.114c-.033.105-.051.216-.051.329 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114z" fill="#8045ff"/></g></svg>
diff --git a/editor/icons/ThemeRemoveCustomItems.svg b/editor/icons/ThemeRemoveCustomItems.svg
index 839f584fce..5ecde9ff55 100644
--- a/editor/icons/ThemeRemoveCustomItems.svg
+++ b/editor/icons/ThemeRemoveCustomItems.svg
@@ -1 +1 @@
-<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m11.299 3c.772.513 1.42 1.199 1.888 2h-2.553c-.706-.621-1.629-1-2.634-1s-1.928.379-2.634 1h-2.553c.468-.801 1.116-1.487 1.888-2z" fill="#ffeb70"/><path d="m5.366 5c-.593.522-1.033 1.216-1.238 2h-2.043c.122-.717.373-1.392.728-2zm7.821 0c.355.608.606 1.283.728 2h-2.043c-.205-.784-.645-1.478-1.238-2z" fill="#9dff70"/><path d="m13.915 7c.056.326.085.66.085 1s-.029.674-.085 1h-2.043c.083-.32.128-.655.128-1s-.045-.68-.128-1zm-9.787 0c-.083.32-.128.655-.128 1s.045.68.128 1h-2.043c-.056-.326-.085-.66-.085-1s.029-.674.085-1z" fill="#70ffb9"/><path d="m4.128 9c.205.784.645 1.478 1.238 2h-2.553c-.355-.608-.606-1.283-.728-2zm9.787 0c-.122.717-.373 1.392-.728 2h-2.553c.593-.522 1.033-1.216 1.238-2z" fill="#70deff"/><path d="m11.299 13h-6.598c.949.631 2.084 1 3.299 1s2.35-.369 3.299-1z" fill="#ff70ac"/><path d="m13.187 11c-.468.801-1.116 1.487-1.888 2h-6.598c-.772-.513-1.42-1.199-1.888-2h2.553c.706.621 1.629 1 2.634 1s1.928-.379 2.634-1z" fill="#9f70ff"/><path d="m4.701 3h6.598c-.949-.631-2.084-1-3.299-1s-2.35.369-3.299 1z" fill="#ff7070"/></g></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m11.299 3c.772.513 1.42 1.199 1.888 2h-2.553c-.706-.621-1.629-1-2.634-1s-1.928.379-2.634 1h-2.553c.468-.801 1.116-1.487 1.888-2z" fill="#ffe345"/><path d="m5.366 5c-.593.522-1.033 1.216-1.238 2h-2.043c.122-.717.373-1.392.728-2zm7.821 0c.355.608.606 1.283.728 2h-2.043c-.205-.784-.645-1.478-1.238-2z" fill="#80ff45"/><path d="m13.915 7c.056.326.085.66.085 1s-.029.674-.085 1h-2.043c.083-.32.128-.655.128-1s-.045-.68-.128-1zm-9.787 0c-.083.32-.128.655-.128 1s.045.68.128 1h-2.043c-.056-.326-.085-.66-.085-1s.029-.674.085-1z" fill="#45ffa2"/><path d="m4.128 9c.205.784.645 1.478 1.238 2h-2.553c-.355-.608-.606-1.283-.728-2zm9.787 0c-.122.717-.373 1.392-.728 2h-2.553c.593-.522 1.033-1.216 1.238-2z" fill="#45d7ff"/><path d="m11.299 13h-6.598c.949.631 2.084 1 3.299 1s2.35-.369 3.299-1z" fill="#ff4596"/><path d="m13.187 11c-.468.801-1.116 1.487-1.888 2h-6.598c-.772-.513-1.42-1.199-1.888-2h2.553c.706.621 1.629 1 2.634 1s1.928-.379 2.634-1z" fill="#8045ff"/><path d="m4.701 3h6.598c-.949-.631-2.084-1-3.299-1s-2.35.369-3.299 1z" fill="#ff4545"/></g></svg>
diff --git a/editor/icons/TileMap.svg b/editor/icons/TileMap.svg
index d1904338a8..291d02b858 100644
--- a/editor/icons/TileMap.svg
+++ b/editor/icons/TileMap.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/TouchScreenButton.svg b/editor/icons/TouchScreenButton.svg
index aec0951d59..7e3e232867 100644
--- a/editor/icons/TouchScreenButton.svg
+++ b/editor/icons/TouchScreenButton.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a1 1 0 0 0 -1 1v2a1 1 0 0 0 1 1h2v-1h-1-1v-2h8v2h-2v1h2a1 1 0 0 0 1-1v-2a1 1 0 0 0 -1-1zm4 2a1 1 0 0 0 -1 1v7 .033203l-2.4746-1.8086c-.52015-.3803-1.1948-.4556-1.6504 0-.45566.4556-.45561 1.1948 0 1.6504l4.125 4.125h6c1.1046 0 2-.8954 2-2v-5h-6v-4a1 1 0 0 0 -1-1z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a1 1 0 0 0 -1 1v2a1 1 0 0 0 1 1h2v-1h-1-1v-2h8v2h-2v1h2a1 1 0 0 0 1-1v-2a1 1 0 0 0 -1-1zm4 2a1 1 0 0 0 -1 1v7 .033203l-2.4746-1.8086c-.52015-.3803-1.1948-.4556-1.6504 0-.45566.4556-.45561 1.1948 0 1.6504l4.125 4.125h6c1.1046 0 2-.8954 2-2v-5h-6v-4a1 1 0 0 0 -1-1z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/TrackAddKey.svg b/editor/icons/TrackAddKey.svg
index 5d2b4ebaf9..82eff5d2bf 100644
--- a/editor/icons/TrackAddKey.svg
+++ b/editor/icons/TrackAddKey.svg
@@ -1 +1 @@
-<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#84ffb1"/></svg>
+<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#5fff97"/></svg>
diff --git a/editor/icons/TrackAddKeyHl.svg b/editor/icons/TrackAddKeyHl.svg
index 0a0cdea48c..03fb90f1e9 100644
--- a/editor/icons/TrackAddKeyHl.svg
+++ b/editor/icons/TrackAddKeyHl.svg
@@ -1 +1 @@
-<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#84ffb1"/><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fff" fill-opacity=".42424"/></svg>
+<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#5fff97"/><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fff" fill-opacity=".42424"/></svg>
diff --git a/editor/icons/Transform.svg b/editor/icons/Transform.svg
deleted file mode 100644
index 4d9bb829cd..0000000000
--- a/editor/icons/Transform.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2 2 4-2 4h2l.9082-2.1816 1.0918 2.1816h2l-2-4 2-4h-2l-.9082 2.1816-1.0918-2.1816zm6 8h2v-2h1v-2h-1v-1c.0000096-.55228.44772-.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3zm4-6v6h2v-2l1 1 1-1v2h2v-6h-2l-1 2-1-2z" fill="#f6a86e"/><path d="m9 2a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1-1h1v-2z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/Transform2D.svg b/editor/icons/Transform2D.svg
index a0b5430298..75be0b73e1 100644
--- a/editor/icons/Transform2D.svg
+++ b/editor/icons/Transform2D.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2v2h2v6h2v-6h2v-2zm7 0v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.0019531v2h7a4 4 0 0 0 3.4648-2 4 4 0 0 0 0-4 4 4 0 0 0 -3.4648-2h-2v6h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5zm5 2a2 2 0 0 1 1.7324 1 2 2 0 0 1 0 2 2 2 0 0 1 -1.7324 1z" fill="#c4ec69"/><path d="m7 2v2c.55228 0 1 .44772 1 1s-.44772 1-1 1c-.71466-.0001326-1.3751.38108-1.7324 1-.17472.30426-.26633.64914-.26562 1h-.0019531v2h5v-2h-3c1.0716-.00015 2.0618-.57193 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.53582-.92807-1.526-1.4998-2.5977-1.5z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2v2h2v6h2v-6h2v-2zm7 0v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.0019531v2h7a4 4 0 0 0 3.4648-2 4 4 0 0 0 0-4 4 4 0 0 0 -3.4648-2h-2v6h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5zm5 2a2 2 0 0 1 1.7324 1 2 2 0 0 1 0 2 2 2 0 0 1 -1.7324 1z" fill="#b9ec41"/><path d="m7 2v2c.55228 0 1 .44772 1 1s-.44772 1-1 1c-.71466-.0001326-1.3751.38108-1.7324 1-.17472.30426-.26633.64914-.26562 1h-.0019531v2h5v-2h-3c1.0716-.00015 2.0618-.57193 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.53582-.92807-1.526-1.4998-2.5977-1.5z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/Transform3D.svg b/editor/icons/Transform3D.svg
new file mode 100644
index 0000000000..a940120702
--- /dev/null
+++ b/editor/icons/Transform3D.svg
@@ -0,0 +1 @@
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2 2 4-2 4h2l.9082-2.1816 1.0918 2.1816h2l-2-4 2-4h-2l-.9082 2.1816-1.0918-2.1816zm6 8h2v-2h1v-2h-1v-1c.0000096-.55228.44772-.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3zm4-6v6h2v-2l1 1 1-1v2h2v-6h-2l-1 2-1-2z" fill="#f68f45"/><path d="m9 2a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1-1h1v-2z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/Tree.svg b/editor/icons/Tree.svg
index 9476f40db3..a6c8ace55f 100644
--- a/editor/icons/Tree.svg
+++ b/editor/icons/Tree.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v13c.0000552.55226.44774.99994 1 1h13v-2h-12v-6h2v3c.0000552.55226.44774.99994 1 1h9v-2h-8v-2h8v-2h-12v-2h12v-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v13c.0000552.55226.44774.99994 1 1h13v-2h-12v-6h2v3c.0000552.55226.44774.99994 1 1h9v-2h-8v-2h8v-2h-12v-2h12v-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/TubeTrailMesh.svg b/editor/icons/TubeTrailMesh.svg
new file mode 100644
index 0000000000..3ca524226f
--- /dev/null
+++ b/editor/icons/TubeTrailMesh.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#ffca5f"><path d="m14.0625 7.5c0-1.6377-.2123-3.12-.5969-4.2737-.1923-.57682-.4237-1.0754-.7508-1.4905-.3271-.41505-.8259-.79834-1.4648-.79834h-7.5c-.6389 0-1.1396.38329-1.4667.79834s-.5585.91366-.7507 1.4905c-.3846 1.1536-.5951 2.6359-.5951 4.2737s.2105 3.12.5951 4.2737c.1922.57682.4236 1.0754.7507 1.4905.3271.41505.8278.79834 1.4667.79834h7.5c.6389 0 1.1377-.38329 1.4648-.79834s.5585-.91366.7508-1.4905c.3846-1.1536.5969-2.6359.5969-4.2737zm-2.8125-4.6875002c.4358 1.0052002 0 0 .4358 1.0052002.2941.88221.5017 2.2134.5017 3.6823s-.2076 2.8-.5017 3.6823c-.1449.4347 0 0-.4358 1.005199l-7.5.000041c-.1212-.15705-.2929-.57092-.4376-1.0052-.2941-.88221-.4999-2.2134-.4999-3.6823s.2058-2.8.4999-3.6823c.1447-.43433.3164-.8482.4376-1.0052"/><path d="m6.5625-11.25h1.875v7.5h-1.875z" stroke-width=".25" transform="rotate(90)"/></g></svg>
diff --git a/editor/icons/Tween.svg b/editor/icons/Tween.svg
index d5cfbbcd88..388aaaf66a 100644
--- a/editor/icons/Tween.svg
+++ b/editor/icons/Tween.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v2h6v6h2v-8zm-1 4 1.793 1.793-4.793 4.793v-4.5859h-2v8h8v-2h-4.5859l4.793-4.793 1.793 1.793v-5h-5z" fill="#cea4f1" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v2h6v6h2v-8zm-1 4 1.793 1.793-4.793 4.793v-4.5859h-2v8h8v-2h-4.5859l4.793-4.793 1.793 1.793v-5h-5z" fill="#c38ef1" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VBoxContainer.svg b/editor/icons/VBoxContainer.svg
index 9a68df4f6a..c515d61d83 100644
--- a/editor/icons/VBoxContainer.svg
+++ b/editor/icons/VBoxContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1039.4c0-1.1046-.89543-2-2-2h-10c-1.1046 0-2 .8954-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.8954 2-2zm-2 0v2h-10v-2zm0 4v2h-10v-2zm0 4v2h-10v-2z" fill="#a5efac" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1039.4c0-1.1046-.89543-2-2-2h-10c-1.1046 0-2 .8954-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.8954 2-2zm-2 0v2h-10v-2zm0 4v2h-10v-2zm0 4v2h-10v-2z" fill="#8eef97" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/VScrollBar.svg b/editor/icons/VScrollBar.svg
index e0fc575860..65f068f8da 100644
--- a/editor/icons/VScrollBar.svg
+++ b/editor/icons/VScrollBar.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-1.108 0-2 .89199-2 2v10c0 1.108.89199 2 2 2h6c1.108 0 2-.89199 2-2v-10c0-1.108-.89199-2-2-2zm2.9883 1a1.0001 1.0001 0 0 1 .56641.16797l3 2a1.0001 1.0001 0 1 1 -1.1094 1.6641l-2.4453-1.6289-2.4453 1.6289a1.0001 1.0001 0 1 1 -1.1094-1.6641l3-2a1.0001 1.0001 0 0 1 .54297-.16797zm-2.998 7.9922a1.0001 1.0001 0 0 1 .56445.17578l2.4453 1.6309 2.4453-1.6309a1.0001 1.0001 0 1 1 1.1094 1.6641l-3 2a1.0001 1.0001 0 0 1 -1.1094 0l-3-2a1.0001 1.0001 0 0 1 .54492-1.8398z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1c-1.108 0-2 .89199-2 2v10c0 1.108.89199 2 2 2h6c1.108 0 2-.89199 2-2v-10c0-1.108-.89199-2-2-2zm2.9883 1a1.0001 1.0001 0 0 1 .56641.16797l3 2a1.0001 1.0001 0 1 1 -1.1094 1.6641l-2.4453-1.6289-2.4453 1.6289a1.0001 1.0001 0 1 1 -1.1094-1.6641l3-2a1.0001 1.0001 0 0 1 .54297-.16797zm-2.998 7.9922a1.0001 1.0001 0 0 1 .56445.17578l2.4453 1.6309 2.4453-1.6309a1.0001 1.0001 0 1 1 1.1094 1.6641l-3 2a1.0001 1.0001 0 0 1 -1.1094 0l-3-2a1.0001 1.0001 0 0 1 .54492-1.8398z" fill="#8eef97"/></svg>
diff --git a/editor/icons/VSeparator.svg b/editor/icons/VSeparator.svg
index 11038b7542..1fd31d89d1 100644
--- a/editor/icons/VSeparator.svg
+++ b/editor/icons/VSeparator.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1047.4h3v-6h-3zm5 4h2v-14h-2zm4-4h3v-6h-3z" fill="#a5efac" transform="translate(0 -1036.4)"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1047.4h3v-6h-3zm5 4h2v-14h-2zm4-4h3v-6h-3z" fill="#8eef97" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/VSlider.svg b/editor/icons/VSlider.svg
index 0ecb1e9aa3..16fafe1162 100644
--- a/editor/icons/VSlider.svg
+++ b/editor/icons/VSlider.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm5 0c-.55228 0-1 .44772-1 1s.44772 1 1 1h2c.55228 0 1-.44772 1-1s-.44772-1-1-1zm-4 5.8672c-.32639.086294-.6624.13092-1 .13281-.33752-.0012549-.67352-.045224-1-.13086v5 1.1309 1c-.019125 1.3523 2.0191 1.3523 2 0v-1-1.1328-5zm5 .13281c-.55228 0-1 .44772-1 1s.44772 1 1 1 1-.44772 1-1-.44772-1-1-1zm-1 6c-.55228 0-1 .44772-1 1s.44772 1 1 1h2c.55228 0 1-.44772 1-1s-.44772-1-1-1z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm5 0c-.55228 0-1 .44772-1 1s.44772 1 1 1h2c.55228 0 1-.44772 1-1s-.44772-1-1-1zm-4 5.8672c-.32639.086294-.6624.13092-1 .13281-.33752-.0012549-.67352-.045224-1-.13086v5 1.1309 1c-.019125 1.3523 2.0191 1.3523 2 0v-1-1.1328-5zm5 .13281c-.55228 0-1 .44772-1 1s.44772 1 1 1 1-.44772 1-1-.44772-1-1-1zm-1 6c-.55228 0-1 .44772-1 1s.44772 1 1 1h2c.55228 0 1-.44772 1-1s-.44772-1-1-1z" fill="#8eef97"/></svg>
diff --git a/editor/icons/VSplitContainer.svg b/editor/icons/VSplitContainer.svg
index 21d45bd5e7..785b1b1880 100644
--- a/editor/icons/VSplitContainer.svg
+++ b/editor/icons/VSplitContainer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v4h-3l-2-2-2 2h-3zm0 6h3l2 2 2-2h3v4h-10z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 2h10v4h-3l-2-2-2 2h-3zm0 6h3l2 2 2-2h3v4h-10z" fill="#8eef97"/></svg>
diff --git a/editor/icons/Variant.svg b/editor/icons/Variant.svg
index 71ebd060ae..dff2c67ebc 100644
--- a/editor/icons/Variant.svg
+++ b/editor/icons/Variant.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6zm3 0v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3zm5 3a3 3 0 0 0 3 3v2h2v-8h-2v4a1 1 0 0 1 -1-1v-3h-2zm-8-1v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#69ecbd"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6zm3 0v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3zm5 3a3 3 0 0 0 3 3v2h2v-8h-2v4a1 1 0 0 1 -1-1v-3h-2zm-8-1v2a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#41ecad"/></svg>
diff --git a/editor/icons/Vector2.svg b/editor/icons/Vector2.svg
index 43a93df83f..2bab922ca9 100644
--- a/editor/icons/Vector2.svg
+++ b/editor/icons/Vector2.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.001953v2h5v-2h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5zm-11 2v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4zm5 3a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2h-1a3 3 0 0 0 -3 3z" fill="#bd91f1"/><path d="m12 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.001953v2h5v-2h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.001953v2h5v-2h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5zm-11 2v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4zm5 3a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2h-1a3 3 0 0 0 -3 3z" fill="#ac73f1"/><path d="m12 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.001953v2h5v-2h-3a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -2.5977-1.5z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/Vector2i.svg b/editor/icons/Vector2i.svg
index 39803fd6a4..f2923542e8 100644
--- a/editor/icons/Vector2i.svg
+++ b/editor/icons/Vector2i.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2v2h1c.55228 0 1 .44772 1 1s-.44772 1-1 1c-.71466-.0001248-1.3751.38109-1.7324 1-.17472.30426-.26633.64914-.26562 1h-.002v2h5v-2h-3c1.0717-.0001344 2.0619-.57191 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.53578-.92809-1.526-1.4999-2.5977-1.5zm-7 2v6h2c1.6569 0 3-1.3431 3-3v-3h-2v3c0 .55228-.44772 1-1 1v-4z" fill="#bd91f1"/><path d="m8 2v2h1c.55228 0 1 .44772 1 1s-.44772 1-1 1c-.71466-.0001248-1.3751.38109-1.7324 1-.17472.30426-.26633.64914-.26562 1h-.001953v2h5v-2h-3c1.0717-.0001344 2.0619-.57191 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.53583-.92809-1.526-1.4999-2.5977-1.5z" fill="#fff" fill-opacity=".39216"/><path d="m13 2v2h2v-2zm0 4v4h2v-4z" fill="#7dc6ef"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2v2h1c.55228 0 1 .44772 1 1s-.44772 1-1 1c-.71466-.0001248-1.3751.38109-1.7324 1-.17472.30426-.26633.64914-.26562 1h-.002v2h5v-2h-3c1.0717-.0001344 2.0619-.57191 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.53578-.92809-1.526-1.4999-2.5977-1.5zm-7 2v6h2c1.6569 0 3-1.3431 3-3v-3h-2v3c0 .55228-.44772 1-1 1v-4z" fill="#ac73f1"/><path d="m8 2v2h1c.55228 0 1 .44772 1 1s-.44772 1-1 1c-.71466-.0001248-1.3751.38109-1.7324 1-.17472.30426-.26633.64914-.26562 1h-.001953v2h5v-2h-3c1.0717-.0001344 2.0619-.57191 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.53583-.92809-1.526-1.4999-2.5977-1.5z" fill="#fff" fill-opacity=".39216"/><path d="m13 2v2h2v-2zm0 4v4h2v-4z" fill="#5abbef"/></svg>
diff --git a/editor/icons/Vector3.svg b/editor/icons/Vector3.svg
index 2606f6e22b..85cac571cf 100644
--- a/editor/icons/Vector3.svg
+++ b/editor/icons/Vector3.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 2v2h2a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -.36523-.50195 3 3 0 0 0 .36523-.49805 3 3 0 0 0 .39844-1.5h.003906v-2zm-11 2v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4zm5 3a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2h-1a3 3 0 0 0 -3 3z" fill="#e286f0"/><path d="m12 2v2h2a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -.36523-.50195 3 3 0 0 0 .36523-.49805 3 3 0 0 0 .39844-1.5h.003906v-2z" fill="#fff" fill-opacity=".39216"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 2v2h2a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -.36523-.50195 3 3 0 0 0 .36523-.49805 3 3 0 0 0 .39844-1.5h.003906v-2zm-11 2v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4zm5 3a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1 1 1 0 0 1 1-1h1v-2h-1a3 3 0 0 0 -3 3z" fill="#de66f0"/><path d="m12 2v2h2a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977-1.5 3 3 0 0 0 0-3 3 3 0 0 0 -.36523-.50195 3 3 0 0 0 .36523-.49805 3 3 0 0 0 .39844-1.5h.003906v-2z" fill="#fff" fill-opacity=".39216"/></svg>
diff --git a/editor/icons/Vector3i.svg b/editor/icons/Vector3i.svg
index 09651193a5..26e9c1b3ef 100644
--- a/editor/icons/Vector3i.svg
+++ b/editor/icons/Vector3i.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2v2h2c0 .55228-.44772 1-1 1v2c.55228 0 1 .44772 1 1s-.45296.92408-1 1h-1v2h1c1.0717-.000134 2.0619-.57191 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.10406-.1795-.22646-.34771-.36523-.50195.13855-.15301.26094-.31991.36523-.49805.26209-.45639.3995-.97371.39844-1.5h.0039v-2zm-7 2v6h2c1.6569 0 3-1.3431 3-3v-3h-2v3c0 .55228-.44772 1-1 1v-4z" fill="#e286f0"/><path d="m8 2v2h2c0 .55228-.44772 1-1 1v2c.55228 0 1 .44772 1 1s-.44948.95585-1 1h-1v2h1c1.0717-.000134 2.0619-.57191 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.10406-.1795-.22646-.34771-.36523-.50195.13855-.15301.26094-.31991.36523-.49805.26209-.45639.3995-.97371.39844-1.5h.0039v-2z" fill="#fff" fill-opacity=".39216"/><path d="m13 2v2h2v-2zm0 4v4h2v-4z" fill="#7dc6ef"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2v2h2c0 .55228-.44772 1-1 1v2c.55228 0 1 .44772 1 1s-.45296.92408-1 1h-1v2h1c1.0717-.000134 2.0619-.57191 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.10406-.1795-.22646-.34771-.36523-.50195.13855-.15301.26094-.31991.36523-.49805.26209-.45639.3995-.97371.39844-1.5h.0039v-2zm-7 2v6h2c1.6569 0 3-1.3431 3-3v-3h-2v3c0 .55228-.44772 1-1 1v-4z" fill="#de66f0"/><path d="m8 2v2h2c0 .55228-.44772 1-1 1v2c.55228 0 1 .44772 1 1s-.44948.95585-1 1h-1v2h1c1.0717-.000134 2.0619-.57191 2.5977-1.5.5359-.9282.5359-2.0718 0-3-.10406-.1795-.22646-.34771-.36523-.50195.13855-.15301.26094-.31991.36523-.49805.26209-.45639.3995-.97371.39844-1.5h.0039v-2z" fill="#fff" fill-opacity=".39216"/><path d="m13 2v2h2v-2zm0 4v4h2v-4z" fill="#5abbef"/></svg>
diff --git a/editor/icons/VehicleBody3D.svg b/editor/icons/VehicleBody3D.svg
index 0cfbad371c..00e4696a17 100644
--- a/editor/icons/VehicleBody3D.svg
+++ b/editor/icons/VehicleBody3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 3a1 1 0 0 0 -1 1l-1 3h-2v4h1.0508c.23167-1.1411 1.2398-2 2.4492-2s2.2175.85893 2.4492 2h2.1016c.23167-1.1411 1.2398-2 2.4492-2s2.2175.85893 2.4492 2h1.0508v-4h-4v-4zm1 1h4v3h-4zm-1.5 6a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0 -1.5-1.5zm7 0a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0 -1.5-1.5z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 3a1 1 0 0 0 -1 1l-1 3h-2v4h1.0508c.23167-1.1411 1.2398-2 2.4492-2s2.2175.85893 2.4492 2h2.1016c.23167-1.1411 1.2398-2 2.4492-2s2.2175.85893 2.4492 2h1.0508v-4h-4v-4zm1 1h4v3h-4zm-1.5 6a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0 -1.5-1.5zm7 0a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0 -1.5-1.5z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/VehicleWheel3D.svg b/editor/icons/VehicleWheel3D.svg
index 0391eac4cf..4c825d6e34 100644
--- a/editor/icons/VehicleWheel3D.svg
+++ b/editor/icons/VehicleWheel3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5-5 5 5 0 0 1 5-5zm0 1a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0 -4-4zm0 1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-2 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-2 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5-5 5 5 0 0 1 5-5zm0 1a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0 -4-4zm0 1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-2 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm-2 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/VideoPlayer.svg b/editor/icons/VideoPlayer.svg
index c5433e0131..092a26b955 100644
--- a/editor/icons/VideoPlayer.svg
+++ b/editor/icons/VideoPlayer.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.0907 0-2 .9093-2 2v10c0 1.0907.90929 2 2 2h10c1.0907 0 2-.9093 2-2v-10c0-1.0907-.90929-2-2-2zm0 2h10v8h-10zm3 2v4l4-2z" fill="#a5efac"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.0907 0-2 .9093-2 2v10c0 1.0907.90929 2 2 2h10c1.0907 0 2-.9093 2-2v-10c0-1.0907-.90929-2-2-2zm0 2h10v8h-10zm3 2v4l4-2z" fill="#8eef97"/></svg>
diff --git a/editor/icons/VisibilityEnabler2D.svg b/editor/icons/VisibilityEnabler2D.svg
index e603936d83..989675f44f 100644
--- a/editor/icons/VisibilityEnabler2D.svg
+++ b/editor/icons/VisibilityEnabler2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v3h1v-2h2v-1zm11 0v1h2v2h1v-3zm-4 1c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-7 6v3h3v-1h-2v-2zm13 0v2h-2v1h3v-3z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v3h1v-2h2v-1zm11 0v1h2v2h1v-3zm-4 1c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-7 6v3h3v-1h-2v-2zm13 0v2h-2v1h3v-3z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VisibilityEnabler3D.svg b/editor/icons/VisibilityEnabler3D.svg
index 07ba8b88df..6923bcb46b 100644
--- a/editor/icons/VisibilityEnabler3D.svg
+++ b/editor/icons/VisibilityEnabler3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v3h1v-2h2v-1zm11 0v1h2v2h1v-3zm-4 1c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-7 6v3h3v-1h-2v-2zm13 0v2h-2v1h3v-3z" fill="#fc9c9c" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v3h1v-2h2v-1zm11 0v1h2v2h1v-3zm-4 1c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-7 6v3h3v-1h-2v-2zm13 0v2h-2v1h3v-3z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VisibilityNotifier2D.svg b/editor/icons/VisibilityNotifier2D.svg
index 8eaf8334ac..13df19be56 100644
--- a/editor/icons/VisibilityNotifier2D.svg
+++ b/editor/icons/VisibilityNotifier2D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 1v6h2v-6zm-4 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246 1.4907 0 3.2717-.65207 4.7109-2h-.71094-2v-.54102a4 4 0 0 1 -2 .54102 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 2 .54102v-2.1816c-.68312-.23834-1.3644-.35938-2-.35938zm0 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm4 2v2h2v-2z" fill="#a5b7f3" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 1v6h2v-6zm-4 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246 1.4907 0 3.2717-.65207 4.7109-2h-.71094-2v-.54102a4 4 0 0 1 -2 .54102 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 2 .54102v-2.1816c-.68312-.23834-1.3644-.35938-2-.35938zm0 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm4 2v2h2v-2z" fill="#8da5f3" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VisibilityNotifier3D.svg b/editor/icons/VisibilityNotifier3D.svg
index afb433c9ed..2fdf784701 100644
--- a/editor/icons/VisibilityNotifier3D.svg
+++ b/editor/icons/VisibilityNotifier3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 1v6h2v-6zm-4 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246 1.4907 0 3.2717-.65207 4.7109-2h-.71094-2v-.54102a4 4 0 0 1 -2 .54102 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 2 .54102v-2.1816c-.68312-.23834-1.3644-.35938-2-.35938zm0 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm4 2v2h2v-2z" fill="#fc9c9c" fill-opacity=".99608" fill-rule="evenodd"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 1v6h2v-6zm-4 2c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246 1.4907 0 3.2717-.65207 4.7109-2h-.71094-2v-.54102a4 4 0 0 1 -2 .54102 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 2 .54102v-2.1816c-.68312-.23834-1.3644-.35938-2-.35938zm0 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm4 2v2h2v-2z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VisualShader.svg b/editor/icons/VisualShader.svg
index 7006066592..92b4737cbe 100644
--- a/editor/icons/VisualShader.svg
+++ b/editor/icons/VisualShader.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m2.8642 9.9954v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4z"/><path d="m10.864 9.9954a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2z"/><path d="m2 1c-.55226.0001-.99994.4477-1 1v7h2v-6h6v3c0 .554.44599 1 1 1h3v2h2v-3l-5-5z"/></g><path d="m4 6h2v1h-2z" fill="#ffeb70"/><path d="m8 8h4v1h-4z" fill="#9dff70"/><path d="m7 6h1v1h-1z" fill="#70deff"/><path d="m4 4h3v1h-3z" fill="#ff7070"/><path d="m4 8h3v1h-3z" fill="#70ffb9"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m2.8642 9.9954v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4z"/><path d="m10.864 9.9954a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2z"/><path d="m2 1c-.55226.0001-.99994.4477-1 1v7h2v-6h6v3c0 .554.44599 1 1 1h3v2h2v-3l-5-5z"/></g><path d="m4 6h2v1h-2z" fill="#ffe345"/><path d="m8 8h4v1h-4z" fill="#80ff45"/><path d="m7 6h1v1h-1z" fill="#45d7ff"/><path d="m4 4h3v1h-3z" fill="#ff4545"/><path d="m4 8h3v1h-3z" fill="#45ffa2"/></svg>
diff --git a/editor/icons/VoxelGI.svg b/editor/icons/VoxelGI.svg
new file mode 100644
index 0000000000..f5e1025260
--- /dev/null
+++ b/editor/icons/VoxelGI.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1a1.0001 1.0001 0 0 0 -1 1v12a1.0001 1.0001 0 0 0 1 1h4v-2h-3v-10h9v-2zm9 3a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.459v.54102c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1v-.54102a4 4 0 0 0 2-3.459 4 4 0 0 0 -4-4zm0 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2zm-1 8v1h2v-1z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/editor/icons/GIProbeData.svg b/editor/icons/VoxelGIData.svg
index 5975115f4c..5975115f4c 100644
--- a/editor/icons/GIProbeData.svg
+++ b/editor/icons/VoxelGIData.svg
diff --git a/editor/icons/WorldEnvironment.svg b/editor/icons/WorldEnvironment.svg
index 314639a576..d26ec52034 100644
--- a/editor/icons/WorldEnvironment.svg
+++ b/editor/icons/WorldEnvironment.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-1.7305 2.3125c-.83125 1.5372-1.2685 3.1037-1.2695 4.6816-.64057-.11251-1.3005-.27158-1.9766-.47266a5 5 0 0 1 3.2461-4.209zm3.4629.0039062a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm-1.7324.0078126c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.0066161.10803-.0078125.16211-.96392.096801-1.9566.1103-2.9844.027344-.0016335-.063192-.0078125-.12632-.0078125-.18945 0-1.5333.48744-3.0828 1.5-4.6758zm4.8789 5.7578a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039zm-9.7461.033203c.68377.18153 1.3555.33345 2.0098.43164.18781 1.0551.56647 2.1026 1.125 3.1367a5 5 0 0 1 -3.1348-3.5684zm6.168.55469c-.22615.98866-.65424 1.9884-1.3008 3.0059-.63811-1.0042-1.0645-1.9908-1.293-2.9668.89027.054126 1.7517.029377 2.5938-.039062z" fill="#fc9c9c" fill-opacity=".99608"/><path d="m8 1v2.3242c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.0066161.10803-.0078125.16211-.4894.049148-.98713.077552-1.4922.082031v1.4922c.43915-.0075968.87287-.031628 1.3008-.066406-.22615.98866-.65424 1.9884-1.3008 3.0059v2.3242a7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm1.7324 2.3164a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm3.1465 5.7656a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039z" fill="#a5b7f3"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-1.7305 2.3125c-.83125 1.5372-1.2685 3.1037-1.2695 4.6816-.64057-.11251-1.3005-.27158-1.9766-.47266a5 5 0 0 1 3.2461-4.209zm3.4629.0039062a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm-1.7324.0078126c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.0066161.10803-.0078125.16211-.96392.096801-1.9566.1103-2.9844.027344-.0016335-.063192-.0078125-.12632-.0078125-.18945 0-1.5333.48744-3.0828 1.5-4.6758zm4.8789 5.7578a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039zm-9.7461.033203c.68377.18153 1.3555.33345 2.0098.43164.18781 1.0551.56647 2.1026 1.125 3.1367a5 5 0 0 1 -3.1348-3.5684zm6.168.55469c-.22615.98866-.65424 1.9884-1.3008 3.0059-.63811-1.0042-1.0645-1.9908-1.293-2.9668.89027.054126 1.7517.029377 2.5938-.039062z" fill="#fc7f7f" fill-opacity=".99608"/><path d="m8 1v2.3242c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.0066161.10803-.0078125.16211-.4894.049148-.98713.077552-1.4922.082031v1.4922c.43915-.0075968.87287-.031628 1.3008-.066406-.22615.98866-.65424 1.9884-1.3008 3.0059v2.3242a7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm1.7324 2.3164a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm3.1465 5.7656a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039z" fill="#8da5f3"/></g></svg>
diff --git a/editor/icons/X509Certificate.svg b/editor/icons/X509Certificate.svg
index b56268f281..718b0ee6a1 100644
--- a/editor/icons/X509Certificate.svg
+++ b/editor/icons/X509Certificate.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 4.233 4.233" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.967.263-3.704.001v2.646h1.427a.993.993 0 0 1 -.022-.096.993.993 0 0 1 -.012-.099.993.993 0 0 1 -.002-.07.993.993 0 0 1 .005-.1.993.993 0 0 1 .014-.097.993.993 0 0 1 .025-.096.993.993 0 0 1 .034-.093.993.993 0 0 1 .043-.09.993.993 0 0 1 .052-.085.993.993 0 0 1 .06-.079.993.993 0 0 1 .068-.072.993.993 0 0 1 .074-.066.993.993 0 0 1 .08-.057.993.993 0 0 1 .087-.05.993.993 0 0 1 .09-.04.993.993 0 0 1 .095-.031.993.993 0 0 1 .096-.022.993.993 0 0 1 .099-.012.993.993 0 0 1 .07-.003.993.993 0 0 1 .099.006.993.993 0 0 1 .098.014.993.993 0 0 1 .096.025.993.993 0 0 1 .094.034.993.993 0 0 1 .089.043.993.993 0 0 1 .084.052.993.993 0 0 1 .08.06.993.993 0 0 1 .072.068.993.993 0 0 1 .065.074.993.993 0 0 1 .058.08.993.993 0 0 1 .05.087.993.993 0 0 1 .04.09.993.993 0 0 1 .031.095.993.993 0 0 1 .022.096.993.993 0 0 1 .012.099.993.993 0 0 1 .002.07.993.993 0 0 1 -.004.1.993.993 0 0 1 -.015.097.993.993 0 0 1 -.017.068h.365z" fill="#e0e0e0"/><g fill="#ff8484"><path d="m2.116 3.175v.793l.53-.253.529.253v-.793z"/><circle cx="2.646" cy="2.645" r=".794"/></g></svg>
+<svg height="16" viewBox="0 0 4.233 4.233" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.967.263-3.704.001v2.646h1.427a.993.993 0 0 1 -.022-.096.993.993 0 0 1 -.012-.099.993.993 0 0 1 -.002-.07.993.993 0 0 1 .005-.1.993.993 0 0 1 .014-.097.993.993 0 0 1 .025-.096.993.993 0 0 1 .034-.093.993.993 0 0 1 .043-.09.993.993 0 0 1 .052-.085.993.993 0 0 1 .06-.079.993.993 0 0 1 .068-.072.993.993 0 0 1 .074-.066.993.993 0 0 1 .08-.057.993.993 0 0 1 .087-.05.993.993 0 0 1 .09-.04.993.993 0 0 1 .095-.031.993.993 0 0 1 .096-.022.993.993 0 0 1 .099-.012.993.993 0 0 1 .07-.003.993.993 0 0 1 .099.006.993.993 0 0 1 .098.014.993.993 0 0 1 .096.025.993.993 0 0 1 .094.034.993.993 0 0 1 .089.043.993.993 0 0 1 .084.052.993.993 0 0 1 .08.06.993.993 0 0 1 .072.068.993.993 0 0 1 .065.074.993.993 0 0 1 .058.08.993.993 0 0 1 .05.087.993.993 0 0 1 .04.09.993.993 0 0 1 .031.095.993.993 0 0 1 .022.096.993.993 0 0 1 .012.099.993.993 0 0 1 .002.07.993.993 0 0 1 -.004.1.993.993 0 0 1 -.015.097.993.993 0 0 1 -.017.068h.365z" fill="#e0e0e0"/><g fill="#ff5f5f"><path d="m2.116 3.175v.793l.53-.253.529.253v-.793z"/><circle cx="2.646" cy="2.645" r=".794"/></g></svg>
diff --git a/editor/icons/XRAnchor3D.svg b/editor/icons/XRAnchor3D.svg
index 0f6282a085..2d8e543f85 100644
--- a/editor/icons/XRAnchor3D.svg
+++ b/editor/icons/XRAnchor3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v2h-2v2h2v3.2656l-2.5527-1.2773c-.15005-.075253-.31662-.11152-.48438-.10547-.36536.013648-.69415.2256-.85742.55273-.24709.49403-.046823 1.0948.44727 1.3418l4.4473 2.2227 4.4473-2.2227c.49409-.24697.69435-.84777.44726-1.3418-.24697-.49409-.84777-.69435-1.3418-.44727l-2.5527 1.2773v-3.2656h2v-2h-2v-2zm-3 11v1c0 .55228.44772 1 1 1-.55228 0-1 .44772-1 1v1h1v-1h1v1h1v-1c0-.55228-.44772-1-1-1 .55228 0 1-.44772 1-1v-1h-1v1h-1v-1zm5 0v4h1v-1h1v1h1v-1c-.000834-.17579-.047991-.34825-.13672-.5.088728-.15175.13588-.32421.13672-.5v-1c0-.55228-.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v2h-2v2h2v3.2656l-2.5527-1.2773c-.15005-.075253-.31662-.11152-.48438-.10547-.36536.013648-.69415.2256-.85742.55273-.24709.49403-.046823 1.0948.44727 1.3418l4.4473 2.2227 4.4473-2.2227c.49409-.24697.69435-.84777.44726-1.3418-.24697-.49409-.84777-.69435-1.3418-.44727l-2.5527 1.2773v-3.2656h2v-2h-2v-2zm-3 11v1c0 .55228.44772 1 1 1-.55228 0-1 .44772-1 1v1h1v-1h1v1h1v-1c0-.55228-.44772-1-1-1 .55228 0 1-.44772 1-1v-1h-1v1h-1v-1zm5 0v4h1v-1h1v1h1v-1c-.000834-.17579-.047991-.34825-.13672-.5.088728-.15175.13588-.32421.13672-.5v-1c0-.55228-.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/XRCamera3D.svg b/editor/icons/XRCamera3D.svg
index 9f9072fc1e..b4657c9f2c 100644
--- a/editor/icons/XRCamera3D.svg
+++ b/editor/icons/XRCamera3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9.5 0a3 3 0 0 0 -2.9883 2.7773 3 3 0 0 0 -2.0117-.77734 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8242v2.1758c0 .554.44599 1 1 1h6c.55401 0 1-.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1-2.2305 3 3 0 0 0 -3-3zm-5.5 12v1c0 .55228.44772 1 1 1-.55228 0-1 .44772-1 1v1h1v-1h1v1h1v-1c0-.55228-.44772-1-1-1 .55228 0 1-.44772 1-1v-1h-1v1h-1v-1zm5 0v1 3h1v-1h1v1h1v-1c-.000834-.17579-.047991-.34825-.13672-.5.088728-.15175.13588-.32421.13672-.5v-1c0-.55228-.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9.5 0a3 3 0 0 0 -2.9883 2.7773 3 3 0 0 0 -2.0117-.77734 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8242v2.1758c0 .554.44599 1 1 1h6c.55401 0 1-.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1-2.2305 3 3 0 0 0 -3-3zm-5.5 12v1c0 .55228.44772 1 1 1-.55228 0-1 .44772-1 1v1h1v-1h1v1h1v-1c0-.55228-.44772-1-1-1 .55228 0 1-.44772 1-1v-1h-1v1h-1v-1zm5 0v1 3h1v-1h1v1h1v-1c-.000834-.17579-.047991-.34825-.13672-.5.088728-.15175.13588-.32421.13672-.5v-1c0-.55228-.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/XRController3D.svg b/editor/icons/XRController3D.svg
index 9296b11c8e..cfde6691df 100644
--- a/editor/icons/XRController3D.svg
+++ b/editor/icons/XRController3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.554 0-1 .446-1 1v6c0 .554.446 1 1 1h12c.554 0 1-.446 1-1v-6c0-.554-.446-1-1-1zm2 1h2v2h2v2h-2v2h-2v-2h-2v-2h2zm9 1c.55228 0 1 .44772 1 1s-.44772 1-1 1-1-.44772-1-1 .44772-1 1-1zm-2 2c.55228 0 1 .44772 1 1s-.44772 1-1 1-1-.44772-1-1 .44772-1 1-1zm-7 7v1c0 .55228.44772 1 1 1-.55228 0-1 .44772-1 1v1h1v-1h1v1h1v-1c0-.55228-.44772-1-1-1 .55228 0 1-.44772 1-1v-1h-1v1h-1v-1zm5 0v1 3h1v-1h1v1h1v-1c-.000834-.17579-.047991-.34825-.13672-.5.088728-.15175.13588-.32421.13672-.5v-1c0-.55228-.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.554 0-1 .446-1 1v6c0 .554.446 1 1 1h12c.554 0 1-.446 1-1v-6c0-.554-.446-1-1-1zm2 1h2v2h2v2h-2v2h-2v-2h-2v-2h2zm9 1c.55228 0 1 .44772 1 1s-.44772 1-1 1-1-.44772-1-1 .44772-1 1-1zm-2 2c.55228 0 1 .44772 1 1s-.44772 1-1 1-1-.44772-1-1 .44772-1 1-1zm-7 7v1c0 .55228.44772 1 1 1-.55228 0-1 .44772-1 1v1h1v-1h1v1h1v-1c0-.55228-.44772-1-1-1 .55228 0 1-.44772 1-1v-1h-1v1h-1v-1zm5 0v1 3h1v-1h1v1h1v-1c-.000834-.17579-.047991-.34825-.13672-.5.088728-.15175.13588-.32421.13672-.5v-1c0-.55228-.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/XROrigin3D.svg b/editor/icons/XROrigin3D.svg
index dda24e7530..03d6e67500 100644
--- a/editor/icons/XROrigin3D.svg
+++ b/editor/icons/XROrigin3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3h2v-3zm-4 4v2h3v-2zm5 0c-.55228 0-1 .44772-1 1s.44772 1 1 1 1-.44772 1-1-.44772-1-1-1zm2 0v2h3v-2zm-3 3v3h2v-3zm-3 4v1c0 .55228.44772 1 1 1-.55228 0-1 .44772-1 1v1h1v-1h1v1h1v-1c0-.55228-.44772-1-1-1 .55228 0 1-.44772 1-1v-1h-1v1h-1v-1zm5 0v1 3h1v-1h1v1h1v-1c-.000834-.17579-.047991-.34825-.13672-.5.088728-.15175.13588-.32421.13672-.5v-1c0-.55228-.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3h2v-3zm-4 4v2h3v-2zm5 0c-.55228 0-1 .44772-1 1s.44772 1 1 1 1-.44772 1-1-.44772-1-1-1zm2 0v2h3v-2zm-3 3v3h2v-3zm-3 4v1c0 .55228.44772 1 1 1-.55228 0-1 .44772-1 1v1h1v-1h1v1h1v-1c0-.55228-.44772-1-1-1 .55228 0 1-.44772 1-1v-1h-1v1h-1v-1zm5 0v1 3h1v-1h1v1h1v-1c-.000834-.17579-.047991-.34825-.13672-.5.088728-.15175.13588-.32421.13672-.5v-1c0-.55228-.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc7f7f"/></svg>
diff --git a/editor/icons/YSort.svg b/editor/icons/YSort.svg
index 40367bd2b2..31e5d9a67e 100644
--- a/editor/icons/YSort.svg
+++ b/editor/icons/YSort.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-3 3h2v8h-2l3 3 3-3h-2v-8h2zm5 1v2h6v-2zm0 5v2h4v-2zm0 5v2h2v-2z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-3 3h2v8h-2l3 3 3-3h-2v-8h2zm5 1v2h6v-2zm0 5v2h4v-2zm0 5v2h2v-2z" fill="#8da5f3" fill-opacity=".98824"/></svg>
diff --git a/editor/icons/bool.svg b/editor/icons/bool.svg
index e6e32001ef..674cbc9e6c 100644
--- a/editor/icons/bool.svg
+++ b/editor/icons/bool.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2v8h2a3 3 0 0 0 2.5-1.3457 3 3 0 0 0 2.5 1.3457 3 3 0 0 0 2-.76758 3 3 0 0 0 2 .76758 3 3 0 0 0 2.5-1.3457 3 3 0 0 0 2.5 1.3457v-2a1 1 0 0 1 -1-1v-5h-2v2.7695a3 3 0 0 0 -2-.76953 3 3 0 0 0 -2 .76758 3 3 0 0 0 -2-.76758 3 3 0 0 0 -2.5 1.3457 3 3 0 0 0 -2.5-1.3457v-2zm2 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#8da6f0"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 2v8h2a3 3 0 0 0 2.5-1.3457 3 3 0 0 0 2.5 1.3457 3 3 0 0 0 2-.76758 3 3 0 0 0 2 .76758 3 3 0 0 0 2.5-1.3457 3 3 0 0 0 2.5 1.3457v-2a1 1 0 0 1 -1-1v-5h-2v2.7695a3 3 0 0 0 -2-.76953 3 3 0 0 0 -2 .76758 3 3 0 0 0 -2-.76758 3 3 0 0 0 -2.5 1.3457 3 3 0 0 0 -2.5-1.3457v-2zm2 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#6f91f0"/></svg>
diff --git a/editor/icons/float.svg b/editor/icons/float.svg
index 1e931ad930..b941332e6c 100644
--- a/editor/icons/float.svg
+++ b/editor/icons/float.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2a3 3 0 0 0 -3 3v5h2v-2h2v-2h-2v-1a1 1 0 0 1 1-1h1v-2zm3 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-5zm6 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-1h2v-2h-2v-2z" fill="#61daf4"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 2a3 3 0 0 0 -3 3v5h2v-2h2v-2h-2v-1a1 1 0 0 1 1-1h1v-2zm3 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-5zm6 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-1h2v-2h-2v-2z" fill="#35d4f4"/></svg>
diff --git a/editor/icons/int.svg b/editor/icons/int.svg
index f8c88300f7..b943822c23 100644
--- a/editor/icons/int.svg
+++ b/editor/icons/int.svg
@@ -1 +1 @@
-<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 2v2h2v-2zm11 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-1h2v-2h-2v-2zm-8 2v6h2v-4h1a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3h-1zm-3 2v4h2v-4z" fill="#7dc6ef"/></svg>
+<svg height="12" viewBox="0 0 16 12" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 2v2h2v-2zm11 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1-1v-1h2v-2h-2v-2zm-8 2v6h2v-4h1a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3h-1zm-3 2v4h2v-4z" fill="#5abbef"/></svg>
diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp
index e38034dd8c..aa9700716d 100644
--- a/editor/import/collada.cpp
+++ b/editor/import/collada.cpp
@@ -50,8 +50,8 @@ String Collada::Effect::get_texture_path(const String &p_source, Collada &state)
return state.state.image_map[image].path;
}
-Transform Collada::get_root_transform() const {
- Transform unit_scale_transform;
+Transform3D Collada::get_root_transform() const {
+ Transform3D unit_scale_transform;
#ifndef COLLADA_IMPORT_SCALE_SCENE
unit_scale_transform.scale(Vector3(state.unit_scale, state.unit_scale, state.unit_scale));
#endif
@@ -74,8 +74,8 @@ static String _uri_to_id(const String &p_uri) {
/** HELPER FUNCTIONS **/
-Transform Collada::fix_transform(const Transform &p_transform) {
- Transform tr = p_transform;
+Transform3D Collada::fix_transform(const Transform3D &p_transform) {
+ Transform3D tr = p_transform;
#ifndef NO_UP_AXIS_SWAP
@@ -102,8 +102,8 @@ Transform Collada::fix_transform(const Transform &p_transform) {
//return state.matrix_fix * p_transform;
}
-static Transform _read_transform_from_array(const Vector<float> &array, int ofs = 0) {
- Transform tr;
+static Transform3D _read_transform_from_array(const Vector<float> &array, int ofs = 0) {
+ Transform3D tr;
// i wonder why collada matrices are transposed, given that's opposed to opengl..
tr.basis.elements[0][0] = array[0 + ofs];
tr.basis.elements[0][1] = array[1 + ofs];
@@ -122,11 +122,11 @@ static Transform _read_transform_from_array(const Vector<float> &array, int ofs
/* STRUCTURES */
-Transform Collada::Node::compute_transform(Collada &state) const {
- Transform xform;
+Transform3D Collada::Node::compute_transform(Collada &state) const {
+ Transform3D xform;
for (int i = 0; i < xform_list.size(); i++) {
- Transform xform_step;
+ Transform3D xform_step;
const XForm &xf = xform_list[i];
switch (xf.op) {
case XForm::OP_ROTATE: {
@@ -165,11 +165,11 @@ Transform Collada::Node::compute_transform(Collada &state) const {
return xform;
}
-Transform Collada::Node::get_transform() const {
+Transform3D Collada::Node::get_transform() const {
return default_transform;
}
-Transform Collada::Node::get_global_transform() const {
+Transform3D Collada::Node::get_global_transform() const {
if (parent) {
return parent->get_global_transform() * default_transform;
} else {
@@ -201,14 +201,14 @@ Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) const {
if (keys[i].data.size() == 16) {
//interpolate a matrix
- Transform src = _read_transform_from_array(keys[i - 1].data);
- Transform dst = _read_transform_from_array(keys[i].data);
+ Transform3D src = _read_transform_from_array(keys[i - 1].data);
+ Transform3D dst = _read_transform_from_array(keys[i].data);
- Transform interp = c < 0.001 ? src : src.interpolate_with(dst, c);
+ Transform3D interp = c < 0.001 ? src : src.interpolate_with(dst, c);
Vector<float> ret;
ret.resize(16);
- Transform tr;
+ Transform3D tr;
// i wonder why collada matrices are transposed, given that's opposed to opengl..
ret.write[0] = interp.basis.elements[0][0];
ret.write[1] = interp.basis.elements[0][1];
@@ -410,10 +410,9 @@ Vector<String> Collada::_read_string_array(XMLParser &parser) {
return array;
}
-Transform Collada::_read_transform(XMLParser &parser) {
- if (parser.is_empty()) {
- return Transform();
- }
+Transform3D Collada::_read_transform(XMLParser &parser) {
+ if (parser.is_empty())
+ return Transform3D();
Vector<String> array;
while (parser.read() == OK) {
@@ -429,7 +428,7 @@ Transform Collada::_read_transform(XMLParser &parser) {
}
}
- ERR_FAIL_COND_V(array.size() != 16, Transform());
+ ERR_FAIL_COND_V(array.size() != 16, Transform3D());
Vector<float> farr;
farr.resize(16);
for (int i = 0; i < 16; i++) {
@@ -1197,7 +1196,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
/* STORE REST MATRICES */
- Vector<Transform> rests;
+ Vector<Transform3D> rests;
ERR_FAIL_COND(!skindata.joints.sources.has("JOINT"));
ERR_FAIL_COND(!skindata.joints.sources.has("INV_BIND_MATRIX"));
@@ -1214,7 +1213,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
for (int i = 0; i < joint_source.sarray.size(); i++) {
String name = joint_source.sarray[i];
- Transform xform = _read_transform_from_array(ibm_source.array, i * 16); //<- this is a mistake, it must be applied to vertices
+ Transform3D xform = _read_transform_from_array(ibm_source.array, i * 16); //<- this is a mistake, it must be applied to vertices
xform.affine_invert(); // inverse for rest, because it's an inverse
#ifdef COLLADA_IMPORT_SCALE_SCENE
xform.origin *= state.unit_scale;
@@ -2096,7 +2095,7 @@ void Collada::_merge_skeletons2(VisualScene *p_vscene) {
NodeSkeleton *skeleton = nullptr;
- for (Map<String, Transform>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) {
+ for (Map<String, Transform3D>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) {
String name;
if (!state.sid_to_node_map.has(F->key())) {
@@ -2240,11 +2239,11 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L
//this should be correct
ERR_FAIL_COND_V(!state.skin_controller_data_map.has(ng->source), false);
SkinControllerData &skin = state.skin_controller_data_map[ng->source];
- Transform skel_inv = sk->get_global_transform().affine_inverse();
+ Transform3D skel_inv = sk->get_global_transform().affine_inverse();
p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it
//make rests relative to the skeleton (they seem to be always relative to world)
- for (Map<String, Transform>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) {
+ for (Map<String, Transform3D>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) {
E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton
state.bone_rest_map[E->key()] = E->get(); // make it remember where the bone is globally, now that it's relative
}
@@ -2252,7 +2251,7 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L
//but most exporters seem to work only if i do this..
//p_node->default_transform = p_node->get_global_transform();
- //p_node->default_transform=Transform(); //this seems to be correct, because bind shape makes the object local to the skeleton
+ //p_node->default_transform=Transform3D(); //this seems to be correct, because bind shape makes the object local to the skeleton
p_node->ignore_anim = true; // collada may animate this later, if it does, then this is not supported (redo your original asset and don't animate the base mesh)
p_node->parent = sk;
//sk->children.push_back(0,p_node); //avoid INFINITE loop
diff --git a/editor/import/collada.h b/editor/import/collada.h
index 2c3f0a3006..5e38637504 100644
--- a/editor/import/collada.h
+++ b/editor/import/collada.h
@@ -182,7 +182,7 @@ public:
String base;
bool use_idrefs = false;
- Transform bind_shape;
+ Transform3D bind_shape;
struct Source {
Vector<String> sarray; //maybe for names
@@ -210,7 +210,7 @@ public:
int count = 0;
} weights;
- Map<String, Transform> bone_rest_map;
+ Map<String, Transform3D> bone_rest_map;
SkinControllerData() {}
};
@@ -342,15 +342,15 @@ public:
String empty_draw_type;
bool noname = false;
Vector<XForm> xform_list;
- Transform default_transform;
- Transform post_transform;
+ Transform3D default_transform;
+ Transform3D post_transform;
Vector<Node *> children;
Node *parent = nullptr;
- Transform compute_transform(Collada &state) const;
- Transform get_global_transform() const;
- Transform get_transform() const;
+ Transform3D compute_transform(Collada &state) const;
+ Transform3D get_global_transform() const;
+ Transform3D get_transform() const;
bool ignore_anim = false;
@@ -497,7 +497,7 @@ public:
Map<String, String> sid_to_node_map;
//Map<String,NodeJoint*> bone_map;
- Map<String, Transform> bone_rest_map;
+ Map<String, Transform3D> bone_rest_map;
String local_path;
String root_visual_scene;
@@ -517,9 +517,9 @@ public:
Collada();
- Transform fix_transform(const Transform &p_transform);
+ Transform3D fix_transform(const Transform3D &p_transform);
- Transform get_root_transform() const;
+ Transform3D get_root_transform() const;
int get_uv_channel(String p_name);
@@ -557,7 +557,7 @@ private: // private stuff
Variant _parse_param(XMLParser &parser);
Vector<float> _read_float_array(XMLParser &parser);
Vector<String> _read_string_array(XMLParser &parser);
- Transform _read_transform(XMLParser &parser);
+ Transform3D _read_transform(XMLParser &parser);
String _read_empty_draw_type(XMLParser &parser);
void _joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner);
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index d3183e5a8d..dc1bd38a99 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -87,7 +87,7 @@ struct ColladaImport {
Error _create_scene(Collada::Node *p_node, Node3D *p_parent);
Error _create_resources(Collada::Node *p_node, bool p_use_compression);
Error _create_material(const String &p_target);
- Error _create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes = Vector<Ref<EditorSceneImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false);
+ Error _create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes = Vector<Ref<EditorSceneImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false);
Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false, bool p_use_compression = false);
void _fix_param_animation_tracks();
void create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
@@ -300,7 +300,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) {
nm.node = node;
node_map[p_node->id] = nm;
node_name_map[node->get_name()] = p_node->id;
- Transform xf = p_node->default_transform;
+ Transform3D xf = p_node->default_transform;
xf = collada.fix_transform(xf) * p_node->post_transform;
node->set_transform(xf);
@@ -457,7 +457,7 @@ Error ColladaImport::_create_material(const String &p_target) {
return OK;
}
-Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) {
+Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) {
bool local_xform_mirror = p_local_xform.basis.determinant() < 0;
if (p_morph_data) {
@@ -811,7 +811,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor
if (has_weights) {
//if skeleton, localize
- Transform local_xform = p_local_xform;
+ Transform3D local_xform = p_local_xform;
for (int i = 0; i < vertex_array.size(); i++) {
vertex_array.write[i].vertex = local_xform.xform(vertex_array[i].vertex);
vertex_array.write[i].normal = local_xform.basis.xform(vertex_array[i].normal).normalized();
@@ -1037,7 +1037,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
Collada::SkinControllerData *skin = nullptr;
Collada::MorphControllerData *morph = nullptr;
String meshid;
- Transform apply_xform;
+ Transform3D apply_xform;
Vector<int> bone_remap;
Vector<Ref<EditorSceneImporterMesh>> morphs;
@@ -1073,9 +1073,9 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
if (apply_mesh_xform_to_vertices) {
apply_xform = collada.fix_transform(p_node->default_transform);
- node->set_transform(Transform());
+ node->set_transform(Transform3D());
} else {
- apply_xform = Transform();
+ apply_xform = Transform3D();
}
ERR_FAIL_COND_V(!skin->weights.sources.has("JOINT"), ERR_INVALID_DATA);
@@ -1461,7 +1461,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
continue;
}
- animation->add_track(Animation::TYPE_TRANSFORM);
+ animation->add_track(Animation::TYPE_TRANSFORM3D);
int track = animation->get_track_count() - 1;
animation->track_set_path(track, path);
animation->track_set_imported(track, true); //helps merging later
@@ -1530,7 +1530,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
}
}
- Transform xform = cn->compute_transform(collada);
+ Transform3D xform = cn->compute_transform(collada);
xform = collada.fix_transform(xform) * cn->post_transform;
if (nm.bone >= 0) {
@@ -1545,7 +1545,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
Vector3 s = xform.basis.get_scale();
bool singular_matrix = Math::is_equal_approx(s.x, 0.0f) || Math::is_equal_approx(s.y, 0.0f) || Math::is_equal_approx(s.z, 0.0f);
- Quat q = singular_matrix ? Quat() : xform.basis.get_rotation_quat();
+ Quaternion q = singular_matrix ? Quaternion() : xform.basis.get_rotation_quaternion();
Vector3 l = xform.origin;
animation->transform_track_insert_key(track, snapshots[i], l, q, s);
@@ -1584,19 +1584,19 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
continue;
}
- animation->add_track(Animation::TYPE_TRANSFORM);
+ animation->add_track(Animation::TYPE_TRANSFORM3D);
int track = animation->get_track_count() - 1;
animation->track_set_path(track, path);
animation->track_set_imported(track, true); //helps merging later
- Transform xform = cn->compute_transform(collada);
+ Transform3D xform = cn->compute_transform(collada);
xform = collada.fix_transform(xform) * cn->post_transform;
xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform;
Vector3 s = xform.basis.get_scale();
bool singular_matrix = Math::is_equal_approx(s.x, 0.0f) || Math::is_equal_approx(s.y, 0.0f) || Math::is_equal_approx(s.z, 0.0f);
- Quat q = singular_matrix ? Quat() : xform.basis.get_rotation_quat();
+ Quaternion q = singular_matrix ? Quaternion() : xform.basis.get_rotation_quaternion();
Vector3 l = xform.origin;
animation->transform_track_insert_key(track, 0, l, q, s);
diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp
index 44aff874eb..8660289c40 100644
--- a/editor/import/editor_import_plugin.cpp
+++ b/editor/import/editor_import_plugin.cpp
@@ -35,63 +35,63 @@ EditorImportPlugin::EditorImportPlugin() {
}
String EditorImportPlugin::get_importer_name() const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_importer_name")), "");
- return get_script_instance()->call("get_importer_name");
+ ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_importer_name")), "");
+ return get_script_instance()->call("_get_importer_name");
}
String EditorImportPlugin::get_visible_name() const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_visible_name")), "");
- return get_script_instance()->call("get_visible_name");
+ ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_visible_name")), "");
+ return get_script_instance()->call("_get_visible_name");
}
void EditorImportPlugin::get_recognized_extensions(List<String> *p_extensions) const {
- ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")));
- Array extensions = get_script_instance()->call("get_recognized_extensions");
+ ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("_get_recognized_extensions")));
+ Array extensions = get_script_instance()->call("_get_recognized_extensions");
for (int i = 0; i < extensions.size(); i++) {
p_extensions->push_back(extensions[i]);
}
}
String EditorImportPlugin::get_preset_name(int p_idx) const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_preset_name")), "");
- return get_script_instance()->call("get_preset_name", p_idx);
+ ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_preset_name")), "");
+ return get_script_instance()->call("_get_preset_name", p_idx);
}
int EditorImportPlugin::get_preset_count() const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_preset_count")), 0);
- return get_script_instance()->call("get_preset_count");
+ ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_preset_count")), 0);
+ return get_script_instance()->call("_get_preset_count");
}
String EditorImportPlugin::get_save_extension() const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_save_extension")), "");
- return get_script_instance()->call("get_save_extension");
+ ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_save_extension")), "");
+ return get_script_instance()->call("_get_save_extension");
}
String EditorImportPlugin::get_resource_type() const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_resource_type")), "");
- return get_script_instance()->call("get_resource_type");
+ ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_resource_type")), "");
+ return get_script_instance()->call("_get_resource_type");
}
float EditorImportPlugin::get_priority() const {
- if (!(get_script_instance() && get_script_instance()->has_method("get_priority"))) {
+ if (!(get_script_instance() && get_script_instance()->has_method("_get_priority"))) {
return ResourceImporter::get_priority();
}
- return get_script_instance()->call("get_priority");
+ return get_script_instance()->call("_get_priority");
}
int EditorImportPlugin::get_import_order() const {
- if (!(get_script_instance() && get_script_instance()->has_method("get_import_order"))) {
+ if (!(get_script_instance() && get_script_instance()->has_method("_get_import_order"))) {
return ResourceImporter::get_import_order();
}
- return get_script_instance()->call("get_import_order");
+ return get_script_instance()->call("_get_import_order");
}
void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption> *r_options, int p_preset) const {
- ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("get_import_options")));
+ ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("_get_import_options")));
Array needed;
needed.push_back("name");
needed.push_back("default_value");
- Array options = get_script_instance()->call("get_import_options", p_preset);
+ Array options = get_script_instance()->call("_get_import_options", p_preset);
for (int i = 0; i < options.size(); i++) {
Dictionary d = options[i];
ERR_FAIL_COND(!d.has_all(needed));
@@ -119,18 +119,18 @@ void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption>
}
bool EditorImportPlugin::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_option_visibility")), true);
+ ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_option_visibility")), true);
Dictionary d;
Map<StringName, Variant>::Element *E = p_options.front();
while (E) {
d[E->key()] = E->get();
E = E->next();
}
- return get_script_instance()->call("get_option_visibility", p_option, d);
+ return get_script_instance()->call("_get_option_visibility", p_option, d);
}
Error EditorImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("import")), ERR_UNAVAILABLE);
+ ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_import")), ERR_UNAVAILABLE);
Dictionary options;
Array platform_variants, gen_files;
@@ -139,7 +139,7 @@ Error EditorImportPlugin::import(const String &p_source_file, const String &p_sa
options[E->key()] = E->get();
E = E->next();
}
- Error err = (Error)get_script_instance()->call("import", p_source_file, p_save_path, options, platform_variants, gen_files).operator int64_t();
+ Error err = (Error)get_script_instance()->call("_import", p_source_file, p_save_path, options, platform_variants, gen_files).operator int64_t();
for (int i = 0; i < platform_variants.size(); i++) {
r_platform_variants->push_back(platform_variants[i]);
@@ -151,16 +151,16 @@ Error EditorImportPlugin::import(const String &p_source_file, const String &p_sa
}
void EditorImportPlugin::_bind_methods() {
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_importer_name"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_visible_name"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "get_preset_count"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_preset_name", PropertyInfo(Variant::INT, "preset")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::ARRAY, "get_recognized_extensions"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::ARRAY, "get_import_options", PropertyInfo(Variant::INT, "preset")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_save_extension"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::FLOAT, "get_priority"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "get_import_order"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "get_option_visibility", PropertyInfo(Variant::STRING, "option"), PropertyInfo(Variant::DICTIONARY, "options")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "import", PropertyInfo(Variant::STRING, "source_file"), PropertyInfo(Variant::STRING, "save_path"), PropertyInfo(Variant::DICTIONARY, "options"), PropertyInfo(Variant::ARRAY, "platform_variants"), PropertyInfo(Variant::ARRAY, "gen_files")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_importer_name"));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_visible_name"));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_get_preset_count"));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_preset_name", PropertyInfo(Variant::INT, "preset")));
+ BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_recognized_extensions"));
+ BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_import_options", PropertyInfo(Variant::INT, "preset")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_save_extension"));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_resource_type"));
+ BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_get_priority"));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_get_import_order"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_get_option_visibility", PropertyInfo(Variant::STRING, "option"), PropertyInfo(Variant::DICTIONARY, "options")));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_import", PropertyInfo(Variant::STRING, "source_file"), PropertyInfo(Variant::STRING, "save_path"), PropertyInfo(Variant::DICTIONARY, "options"), PropertyInfo(Variant::ARRAY, "platform_variants"), PropertyInfo(Variant::ARRAY, "gen_files")));
}
diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp
index 4a4d9d8f06..c9e446a1a2 100644
--- a/editor/import/resource_importer_csv_translation.cpp
+++ b/editor/import/resource_importer_csv_translation.cpp
@@ -30,8 +30,8 @@
#include "resource_importer_csv_translation.h"
+#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "core/string/optimized_translation.h"
#include "core/string/translation.h"
diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp
index 26c6a8462b..2dea359188 100644
--- a/editor/import/resource_importer_image.cpp
+++ b/editor/import/resource_importer_image.cpp
@@ -30,9 +30,9 @@
#include "resource_importer_image.h"
+#include "core/io/file_access.h"
#include "core/io/image_loader.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "scene/resources/texture.h"
String ResourceImporterImage::get_importer_name() const {
@@ -75,7 +75,7 @@ Error ResourceImporterImage::import(const String &p_source_file, const String &p
ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'.");
- size_t len = f->get_len();
+ uint64_t len = f->get_length();
Vector<uint8_t> data;
data.resize(len);
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index dd62c72d8a..3aa17ee581 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -30,8 +30,8 @@
#include "resource_importer_obj.h"
+#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "editor/import/scene_importer_mesh.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/mesh_instance_3d.h"
@@ -126,7 +126,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand
String p = l.replace("map_Kd", "").replace("\\", "/").strip_edges();
String path;
- if (p.is_abs_path()) {
+ if (p.is_absolute_path()) {
path = p;
} else {
path = base_path.plus_file(p);
@@ -146,7 +146,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand
String p = l.replace("map_Ks", "").replace("\\", "/").strip_edges();
String path;
- if (p.is_abs_path()) {
+ if (p.is_absolute_path()) {
path = p;
} else {
path = base_path.plus_file(p);
@@ -166,7 +166,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand
String p = l.replace("map_Ns", "").replace("\\", "/").strip_edges();
String path;
- if (p.is_abs_path()) {
+ if (p.is_absolute_path()) {
path = p;
} else {
path = base_path.plus_file(p);
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 96002400f3..08aa2fecbb 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -120,13 +120,13 @@ void EditorSceneImporter::_bind_methods() {
/////////////////////////////////
void EditorScenePostImport::_bind_methods() {
- BIND_VMETHOD(MethodInfo(Variant::OBJECT, "post_import", PropertyInfo(Variant::OBJECT, "scene")));
+ BIND_VMETHOD(MethodInfo(Variant::OBJECT, "_post_import", PropertyInfo(Variant::OBJECT, "scene")));
ClassDB::bind_method(D_METHOD("get_source_file"), &EditorScenePostImport::get_source_file);
}
Node *EditorScenePostImport::post_import(Node *p_scene) {
if (get_script_instance()) {
- return get_script_instance()->call("post_import", p_scene);
+ return get_script_instance()->call("_post_import", p_scene);
}
return p_scene;
@@ -433,7 +433,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
p_node->replace_by(rigid_body);
rigid_body->set_transform(mi->get_transform());
p_node = rigid_body;
- mi->set_transform(Transform());
+ mi->set_transform(Transform3D());
rigid_body->add_child(mi);
mi->set_owner(rigid_body->get_owner());
@@ -632,7 +632,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
p_node->replace_by(rigid_body);
rigid_body->set_transform(mi->get_transform());
p_node = rigid_body;
- mi->set_transform(Transform());
+ mi->set_transform(Transform3D());
rigid_body->add_child(mi);
mi->set_owner(rigid_body->get_owner());
base = rigid_body;
@@ -856,8 +856,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
new_anim->track_set_path(dtrack, default_anim->track_get_path(j));
if (kt > (from + 0.01) && k > 0) {
- if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) {
- Quat q;
+ if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) {
+ Quaternion q;
Vector3 p;
Vector3 s;
default_anim->transform_track_interpolate(j, from, &p, &q, &s);
@@ -870,8 +870,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
}
}
- if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) {
- Quat q;
+ if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) {
+ Quaternion q;
Vector3 p;
Vector3 s;
default_anim->transform_track_get_key(j, k, &p, &q, &s);
@@ -884,8 +884,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
}
if (dtrack != -1 && kt >= to) {
- if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) {
- Quat q;
+ if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) {
+ Quaternion q;
Vector3 p;
Vector3 s;
default_anim->transform_track_interpolate(j, to, &p, &q, &s);
@@ -902,8 +902,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
new_anim->add_track(default_anim->track_get_type(j));
dtrack = new_anim->get_track_count() - 1;
new_anim->track_set_path(dtrack, default_anim->track_get_path(j));
- if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) {
- Quat q;
+ if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) {
+ Quaternion q;
Vector3 p;
Vector3 s;
default_anim->transform_track_interpolate(j, from, &p, &q, &s);
@@ -1209,11 +1209,11 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m
}
if (bake_lightmaps) {
- Transform xf;
+ Transform3D xf;
Node3D *n = src_mesh_node;
while (n) {
xf = n->get_transform() * xf;
- n = n->get_parent_spatial();
+ n = n->get_parent_node_3d();
}
Vector<uint8_t> lightmap_cache;
@@ -1508,7 +1508,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
if (!scene) {
EditorNode::add_io_error(
TTR("Error running post-import script:") + " " + post_import_script_path + "\n" +
- TTR("Did you return a Node-derived object in the `post_import()` method?"));
+ TTR("Did you return a Node-derived object in the `_post_import()` method?"));
return err;
}
}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 8cb84abce2..c6e5836a23 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -42,8 +42,8 @@ class Material;
class AnimationPlayer;
class EditorSceneImporterMesh;
-class EditorSceneImporter : public Reference {
- GDCLASS(EditorSceneImporter, Reference);
+class EditorSceneImporter : public RefCounted {
+ GDCLASS(EditorSceneImporter, RefCounted);
protected:
static void _bind_methods();
@@ -69,8 +69,8 @@ public:
EditorSceneImporter() {}
};
-class EditorScenePostImport : public Reference {
- GDCLASS(EditorScenePostImport, Reference);
+class EditorScenePostImport : public RefCounted {
+ GDCLASS(EditorScenePostImport, RefCounted);
String source_file;
diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp
index f4d20a6296..70119bfd1c 100644
--- a/editor/import/resource_importer_shader_file.cpp
+++ b/editor/import/resource_importer_shader_file.cpp
@@ -30,9 +30,9 @@
#include "resource_importer_shader_file.h"
+#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "editor/editor_node.h"
#include "editor/plugins/shader_file_editor_plugin.h"
#include "servers/rendering/rendering_device_binds.h"
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index de8031af35..809f47bad9 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -208,7 +208,7 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "roughness/src_normal", PROPERTY_HINT_FILE, "*.bmp,*.dds,*.exr,*.jpeg,*.jpg,*.hdr,*.png,*.svg,*.svgz,*.tga,*.webp"), ""));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/fix_alpha_border"), p_preset != PRESET_3D));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/invert_color"), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/normal_map_invert_y"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/HDR_as_SRGB"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "detect_3d/compress_to", PROPERTY_HINT_ENUM, "Disabled,VRAM Compressed,Basis Universal"), (p_preset == PRESET_DETECT) ? 1 : 0));
@@ -218,14 +218,21 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,
void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
switch (p_compress_mode) {
case COMPRESS_LOSSLESS: {
- f->store_32(StreamTexture2D::DATA_FORMAT_LOSSLESS);
+ bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png");
+ bool use_webp = !lossless_force_png && p_image->get_width() <= 16383 && p_image->get_height() <= 16383; // WebP has a size limit
+ f->store_32(use_webp ? StreamTexture2D::DATA_FORMAT_WEBP : StreamTexture2D::DATA_FORMAT_PNG);
f->store_16(p_image->get_width());
f->store_16(p_image->get_height());
f->store_32(p_image->get_mipmap_count());
f->store_32(p_image->get_format());
for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) {
- Vector<uint8_t> data = Image::lossless_packer(p_image->get_image_from_mipmap(i));
+ Vector<uint8_t> data;
+ if (use_webp) {
+ data = Image::webp_lossless_packer(p_image->get_image_from_mipmap(i));
+ } else {
+ data = Image::png_packer(p_image->get_image_from_mipmap(i));
+ }
int data_len = data.size();
f->store_32(data_len);
@@ -235,14 +242,14 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image
} break;
case COMPRESS_LOSSY: {
- f->store_32(StreamTexture2D::DATA_FORMAT_LOSSY);
+ f->store_32(StreamTexture2D::DATA_FORMAT_WEBP);
f->store_16(p_image->get_width());
f->store_16(p_image->get_height());
f->store_32(p_image->get_mipmap_count());
f->store_32(p_image->get_format());
for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) {
- Vector<uint8_t> data = Image::lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality);
+ Vector<uint8_t> data = Image::webp_lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality);
int data_len = data.size();
f->store_32(data_len);
@@ -388,7 +395,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
uint32_t mipmap_limit = int(mipmaps ? int(p_options["mipmaps/limit"]) : int(-1));
bool fix_alpha_border = p_options["process/fix_alpha_border"];
bool premult_alpha = p_options["process/premult_alpha"];
- bool invert_color = p_options["process/invert_color"];
+ bool normal_map_invert_y = p_options["process/normal_map_invert_y"];
bool stream = p_options["compress/streamed"];
int size_limit = p_options["process/size_limit"];
bool hdr_as_srgb = p_options["process/HDR_as_SRGB"];
@@ -444,13 +451,18 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
image->premultiply_alpha();
}
- if (invert_color) {
- int height = image->get_height();
- int width = image->get_width();
+ if (normal_map_invert_y) {
+ // Inverting the green channel can be used to flip a normal map's direction.
+ // There's no standard when it comes to normal map Y direction, so this is
+ // sometimes needed when using a normal map exported from another program.
+ // See <http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates>.
+ const int height = image->get_height();
+ const int width = image->get_width();
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
- image->set_pixel(i, j, image->get_pixel(i, j).inverted());
+ const Color color = image->get_pixel(i, j);
+ image->set_pixel(i, j, Color(color.r, 1 - color.g, color.b));
}
}
}
diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h
index 0d551a965c..41220009cd 100644
--- a/editor/import/resource_importer_texture.h
+++ b/editor/import/resource_importer_texture.h
@@ -31,9 +31,9 @@
#ifndef RESOURCEIMPORTTEXTURE_H
#define RESOURCEIMPORTTEXTURE_H
+#include "core/io/file_access.h"
#include "core/io/image.h"
#include "core/io/resource_importer.h"
-#include "core/os/file_access.h"
#include "scene/resources/texture.h"
#include "servers/rendering_server.h"
diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp
index 4c3ae59951..d5d1a14be3 100644
--- a/editor/import/resource_importer_texture_atlas.cpp
+++ b/editor/import/resource_importer_texture_atlas.cpp
@@ -31,10 +31,10 @@
#include "resource_importer_texture_atlas.h"
#include "atlas_import_failed.xpm"
+#include "core/io/file_access.h"
#include "core/io/image_loader.h"
#include "core/io/resource_saver.h"
#include "core/math/geometry_2d.h"
-#include "core/os/file_access.h"
#include "editor/editor_atlas_packer.h"
#include "scene/resources/mesh.h"
#include "scene/resources/texture.h"
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index bcc55b330b..e615212569 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -30,9 +30,9 @@
#include "resource_importer_wav.h"
+#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "scene/resources/audio_stream_sample.h"
const float TRIM_DB_LIMIT = -50;
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 48340ac242..600f3fe2f0 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -317,7 +317,7 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) {
if (mesh_node && mesh_node->get_mesh().is_valid()) {
_fill_mesh(scene_tree, mesh_node->get_mesh(), item);
- Transform accum_xform;
+ Transform3D accum_xform;
Node3D *base = mesh_node;
while (base) {
accum_xform = base->get_transform() * accum_xform;
@@ -339,7 +339,7 @@ void SceneImportSettings::_update_scene() {
material_tree->clear();
mesh_tree->clear();
- //hiden roots
+ //hidden roots
material_tree->create_item();
mesh_tree->create_item();
@@ -379,7 +379,7 @@ void SceneImportSettings::_update_camera() {
camera->set_orthogonal(camera_size * zoom, 0.0001, camera_size * 2);
- Transform xf;
+ Transform3D xf;
xf.basis = Basis(Vector3(0, 1, 0), rot_y) * Basis(Vector3(1, 0, 0), rot_x);
xf.origin = center;
xf.translate(0, 0, camera_size);
@@ -493,7 +493,7 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) {
Ref<Mesh> base_mesh = mi->get_mesh();
if (base_mesh.is_valid()) {
AABB aabb = base_mesh->get_aabb();
- Transform aabb_xf;
+ Transform3D aabb_xf;
aabb_xf.basis.scale(aabb.size);
aabb_xf.origin = aabb.position;
@@ -1099,7 +1099,7 @@ SceneImportSettings::SceneImportSettings() {
camera->make_current();
light = memnew(DirectionalLight3D);
- light->set_transform(Transform().looking_at(Vector3(-1, -2, -0.6), Vector3(0, 1, 0)));
+ light->set_transform(Transform3D().looking_at(Vector3(-1, -2, -0.6), Vector3(0, 1, 0)));
base_viewport->add_child(light);
light->set_shadow(true);
diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp
index bc7e8a1626..bf17ea7bca 100644
--- a/editor/import/scene_importer_mesh.cpp
+++ b/editor/import/scene_importer_mesh.cpp
@@ -30,6 +30,7 @@
#include "scene_importer_mesh.h"
+#include "core/math/math_defs.h"
#include "scene/resources/surface_tool.h"
void EditorSceneImporterMesh::add_blend_shape(const String &p_name) {
@@ -141,6 +142,18 @@ void EditorSceneImporterMesh::set_surface_material(int p_surface, const Ref<Mate
surfaces.write[p_surface].material = p_material;
}
+Basis EditorSceneImporterMesh::compute_rotation_matrix_from_ortho_6d(Vector3 p_x_raw, Vector3 p_y_raw) {
+ Vector3 x = p_x_raw.normalized();
+ Vector3 z = x.cross(p_y_raw);
+ z = z.normalized();
+ Vector3 y = z.cross(x);
+ Basis basis;
+ basis.set_axis(Vector3::AXIS_X, x);
+ basis.set_axis(Vector3::AXIS_Y, y);
+ basis.set_axis(Vector3::AXIS_Z, z);
+ return basis;
+}
+
void EditorSceneImporterMesh::generate_lods() {
if (!SurfaceTool::simplify_func) {
return;
@@ -151,6 +164,9 @@ void EditorSceneImporterMesh::generate_lods() {
if (!SurfaceTool::simplify_sloppy_func) {
return;
}
+ if (!SurfaceTool::simplify_with_attrib_func) {
+ return;
+ }
for (int i = 0; i < surfaces.size(); i++) {
if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) {
@@ -163,59 +179,62 @@ void EditorSceneImporterMesh::generate_lods() {
if (indices.size() == 0) {
continue; //no lods if no indices
}
+ Vector<Vector3> normals = surfaces[i].arrays[RS::ARRAY_NORMAL];
uint32_t vertex_count = vertices.size();
const Vector3 *vertices_ptr = vertices.ptr();
-
- int min_indices = 10;
- int index_target = indices.size() / 2;
- print_line("Total indices: " + itos(indices.size()));
- float mesh_scale = SurfaceTool::simplify_scale_func((const float *)vertices_ptr, vertex_count, sizeof(Vector3));
- const float target_error = 1e-3f;
- float abs_target_error = target_error / mesh_scale;
+ Vector<float> attributes;
+ Vector<float> normal_weights;
+ int32_t attribute_count = 6;
+ if (normals.size()) {
+ attributes.resize(normals.size() * attribute_count);
+ for (int32_t normal_i = 0; normal_i < normals.size(); normal_i++) {
+ Basis basis;
+ basis.set_euler(normals[normal_i]);
+ Vector3 basis_x = basis.get_axis(0);
+ Vector3 basis_y = basis.get_axis(1);
+ basis = compute_rotation_matrix_from_ortho_6d(basis_x, basis_y);
+ basis_x = basis.get_axis(0);
+ basis_y = basis.get_axis(1);
+ attributes.write[normal_i * attribute_count + 0] = basis_x.x;
+ attributes.write[normal_i * attribute_count + 1] = basis_x.y;
+ attributes.write[normal_i * attribute_count + 2] = basis_x.z;
+ attributes.write[normal_i * attribute_count + 3] = basis_y.x;
+ attributes.write[normal_i * attribute_count + 4] = basis_y.y;
+ attributes.write[normal_i * attribute_count + 5] = basis_y.z;
+ }
+ normal_weights.resize(vertex_count);
+ for (int32_t weight_i = 0; weight_i < normal_weights.size(); weight_i++) {
+ normal_weights.write[weight_i] = 1.0;
+ }
+ } else {
+ attribute_count = 0;
+ }
+ const int min_indices = 10;
+ const float error_tolerance = 1.44224'95703; // Cube root of 3
+ const float threshold = 1.0 / error_tolerance;
+ int index_target = indices.size() * threshold;
+ float max_mesh_error_percentage = 1e0f;
+ float mesh_error = 0.0f;
while (index_target > min_indices) {
- float error;
Vector<int> new_indices;
new_indices.resize(indices.size());
- size_t new_len = SurfaceTool::simplify_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, abs_target_error, &error);
- if ((int)new_len > (index_target * 120 / 100)) {
- // Attribute discontinuities break normals.
- bool is_sloppy = false;
- if (is_sloppy) {
- abs_target_error = target_error / mesh_scale;
- index_target = new_len;
- while (index_target > min_indices) {
- Vector<int> sloppy_new_indices;
- sloppy_new_indices.resize(indices.size());
- new_len = SurfaceTool::simplify_sloppy_func((unsigned int *)sloppy_new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, abs_target_error, &error);
- if ((int)new_len > (index_target * 120 / 100)) {
- break; // 20 percent tolerance
- }
- sloppy_new_indices.resize(new_len);
- Surface::LOD lod;
- lod.distance = error * mesh_scale;
- abs_target_error = lod.distance;
- if (Math::is_equal_approx(abs_target_error, 0.0f)) {
- return;
- }
- lod.indices = sloppy_new_indices;
- print_line("Lod " + itos(surfaces.write[i].lods.size()) + " shoot for " + itos(index_target / 3) + " triangles, got " + itos(new_len / 3) + " triangles. Distance " + rtos(lod.distance) + ". Use simplify sloppy.");
- surfaces.write[i].lods.push_back(lod);
- index_target /= 2;
- }
- }
- break; // 20 percent tolerance
+ size_t new_len = SurfaceTool::simplify_with_attrib_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, max_mesh_error_percentage, &mesh_error, (float *)attributes.ptrw(), normal_weights.ptrw(), attribute_count);
+ if ((int)new_len > (index_target * error_tolerance)) {
+ break;
}
- new_indices.resize(new_len);
Surface::LOD lod;
- lod.distance = error * mesh_scale;
- abs_target_error = lod.distance;
- if (Math::is_equal_approx(abs_target_error, 0.0f)) {
- return;
+ lod.distance = mesh_error;
+ if (Math::is_equal_approx(mesh_error, 0.0f)) {
+ break;
+ }
+ if (new_len <= 0) {
+ break;
}
+ new_indices.resize(new_len);
lod.indices = new_indices;
- print_line("Lod " + itos(surfaces.write[i].lods.size()) + " shoot for " + itos(index_target / 3) + " triangles, got " + itos(new_len / 3) + " triangles. Distance " + rtos(lod.distance));
+ print_line("Lod " + itos(surfaces.write[i].lods.size()) + " begin with " + itos(indices.size() / 3) + " triangles and shoot for " + itos(index_target / 3) + " triangles. Got " + itos(new_len / 3) + " triangles. Lod screen ratio " + rtos(lod.distance));
surfaces.write[i].lods.push_back(lod);
- index_target /= 2;
+ index_target *= threshold;
}
}
}
@@ -593,7 +612,7 @@ struct EditorSceneImporterMeshLightmapSurface {
String name;
};
-Error EditorSceneImporterMesh::lightmap_unwrap_cached(const Transform &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache) {
+Error EditorSceneImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache) {
ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes.");
@@ -609,7 +628,7 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(const Transform &p_base_tr
Basis basis = p_base_transform.get_basis();
Vector3 scale = Vector3(basis.get_axis(0).length(), basis.get_axis(1).length(), basis.get_axis(2).length());
- Transform transform;
+ Transform3D transform;
transform.scale(scale);
Basis normal_basis = transform.basis.inverse().transposed();
diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h
index b3e8137e0a..2488de7ed0 100644
--- a/editor/import/scene_importer_mesh.h
+++ b/editor/import/scene_importer_mesh.h
@@ -67,6 +67,7 @@ class EditorSceneImporterMesh : public Resource {
Ref<EditorSceneImporterMesh> shadow_mesh;
Size2i lightmap_size_hint;
+ Basis compute_rotation_matrix_from_ortho_6d(Vector3 p_x_raw, Vector3 y_raw);
protected:
void _set_data(const Dictionary &p_data);
@@ -105,7 +106,7 @@ public:
Vector<Ref<Shape3D>> convex_decompose() const;
Ref<Shape3D> create_trimesh_shape() const;
Ref<NavigationMesh> create_navigation_mesh();
- Error lightmap_unwrap_cached(const Transform &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache);
+ Error lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache);
void set_lightmap_size_hint(const Size2i &p_size);
Size2i get_lightmap_size_hint() const;
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index 6265dfc2e4..e8c01d0e0c 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -42,6 +42,14 @@ void InspectorDock::_menu_option(int p_option) {
case COLLAPSE_ALL: {
_menu_collapseall();
} break;
+
+ case RESOURCE_SAVE: {
+ _save_resource(false);
+ } break;
+ case RESOURCE_SAVE_AS: {
+ _save_resource(true);
+ } break;
+
case RESOURCE_MAKE_BUILT_IN: {
_unref_resource();
} break;
@@ -52,13 +60,6 @@ void InspectorDock::_menu_option(int p_option) {
_paste_resource();
} break;
- case RESOURCE_SAVE: {
- _save_resource(false);
- } break;
- case RESOURCE_SAVE_AS: {
- _save_resource(true);
- } break;
-
case OBJECT_REQUEST_HELP: {
if (current) {
editor->set_visible_editor(EditorNode::EDITOR_SCRIPT);
@@ -313,7 +314,7 @@ void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_valu
AnimationPlayerEditor::singleton->get_track_editor()->insert_value_key(p_keyed, p_value, p_advance);
}
-void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) {
+void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform3D &p_key) {
Node3D *s = Object::cast_to<Node3D>(sp);
if (!s) {
return;
@@ -335,9 +336,16 @@ void InspectorDock::_notification(int p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
set_theme(editor->get_gui_base()->get_theme());
+
resource_new_button->set_icon(get_theme_icon("New", "EditorIcons"));
resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons"));
resource_save_button->set_icon(get_theme_icon("Save", "EditorIcons"));
+ resource_extra_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+
+ PopupMenu *resource_extra_popup = resource_extra_button->get_popup();
+ resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_EDIT_CLIPBOARD), get_theme_icon("ActionPaste", "EditorIcons"));
+ resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_COPY), get_theme_icon("ActionCopy", "EditorIcons"));
+
if (is_layout_rtl()) {
backward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
forward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
@@ -345,6 +353,7 @@ void InspectorDock::_notification(int p_what) {
backward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
forward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
}
+
history_menu->set_icon(get_theme_icon("History", "EditorIcons"));
object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
@@ -403,12 +412,7 @@ void InspectorDock::update(Object *p_object) {
object_menu->set_disabled(true);
warning->hide();
search->set_editable(false);
-
- editor_path->set_disabled(true);
- editor_path->set_text("");
- editor_path->set_tooltip("");
- editor_path->set_icon(nullptr);
-
+ editor_path->clear_path();
return;
}
@@ -417,35 +421,28 @@ void InspectorDock::update(Object *p_object) {
object_menu->set_disabled(false);
search->set_editable(true);
- editor_path->set_disabled(false);
+ editor_path->enable_path();
+
resource_save_button->set_disabled(!is_resource);
+ open_docs_button->set_visible(is_resource || is_node);
+
+ PopupMenu *resource_extra_popup = resource_extra_button->get_popup();
+ resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_COPY), !is_resource);
+ resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_MAKE_BUILT_IN), !is_resource);
PopupMenu *p = object_menu->get_popup();
p->clear();
- p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand All Properties")), EXPAND_ALL);
- p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All Properties")), COLLAPSE_ALL);
- p->add_separator();
- if (is_resource) {
- p->add_item(TTR("Save"), RESOURCE_SAVE);
- p->add_item(TTR("Save As..."), RESOURCE_SAVE_AS);
- p->add_separator();
- }
- p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS);
- p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS);
+ p->add_icon_shortcut(get_theme_icon("GuiTreeArrowDown", "EditorIcons"), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL);
+ p->add_icon_shortcut(get_theme_icon("GuiTreeArrowRight", "EditorIcons"), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL);
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource Clipboard")), RESOURCE_EDIT_CLIPBOARD);
- if (is_resource) {
- p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
- p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_MAKE_BUILT_IN);
- }
+ p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Properties")), OBJECT_COPY_PARAMS);
+ p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Properties")), OBJECT_PASTE_PARAMS);
if (is_resource || is_node) {
p->add_separator();
p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES);
- p->add_separator();
- p->add_icon_shortcut(get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP);
}
List<MethodInfo> methods;
@@ -525,6 +522,17 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
resource_save_button->set_focus_mode(Control::FOCUS_NONE);
resource_save_button->set_disabled(true);
+ resource_extra_button = memnew(MenuButton);
+ resource_extra_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+ general_options_hb->add_child(resource_extra_button);
+ resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon("ActionPaste", "EditorIcons"), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD);
+ resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon("ActionCopy", "EditorIcons"), ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
+ resource_extra_button->get_popup()->set_item_disabled(1, true);
+ resource_extra_button->get_popup()->add_separator();
+ resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Resource Built-In")), RESOURCE_MAKE_BUILT_IN);
+ resource_extra_button->get_popup()->set_item_disabled(3, true);
+ resource_extra_button->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option));
+
general_options_hb->add_spacer();
backward_button = memnew(Button);
@@ -558,31 +566,42 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
history_menu->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_history));
history_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_select_history));
- HBoxContainer *node_info_hb = memnew(HBoxContainer);
- add_child(node_info_hb);
-
+ HBoxContainer *subresource_hb = memnew(HBoxContainer);
+ add_child(subresource_hb);
editor_path = memnew(EditorPath(editor->get_editor_history()));
editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- node_info_hb->add_child(editor_path);
+ subresource_hb->add_child(editor_path);
- object_menu = memnew(MenuButton);
- object_menu->set_shortcut_context(this);
- object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
- node_info_hb->add_child(object_menu);
- object_menu->set_tooltip(TTR("Object properties."));
- object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option));
+ open_docs_button = memnew(Button);
+ open_docs_button->set_flat(true);
+ open_docs_button->set_visible(false);
+ open_docs_button->set_tooltip(TTR("Open documentation for this object."));
+ open_docs_button->set_icon(get_theme_icon("HelpSearch", "EditorIcons"));
+ open_docs_button->set_shortcut(ED_SHORTCUT("property_editor/open_help", TTR("Open Documentation")));
+ subresource_hb->add_child(open_docs_button);
+ open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option), varray(OBJECT_REQUEST_HELP));
new_resource_dialog = memnew(CreateDialog);
editor->get_gui_base()->add_child(new_resource_dialog);
new_resource_dialog->set_base_type("Resource");
new_resource_dialog->connect("create", callable_mp(this, &InspectorDock::_resource_created));
+ HBoxContainer *property_tools_hb = memnew(HBoxContainer);
+ add_child(property_tools_hb);
+
search = memnew(LineEdit);
search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search->set_placeholder(TTR("Filter properties"));
search->set_right_icon(get_theme_icon("Search", "EditorIcons"));
search->set_clear_button_enabled(true);
- add_child(search);
+ property_tools_hb->add_child(search);
+
+ object_menu = memnew(MenuButton);
+ object_menu->set_shortcut_context(this);
+ object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
+ property_tools_hb->add_child(object_menu);
+ object_menu->set_tooltip(TTR("Manage object properties."));
+ object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option));
warning = memnew(Button);
add_child(warning);
diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h
index 6a3f8c679c..d50785d95c 100644
--- a/editor/inspector_dock.h
+++ b/editor/inspector_dock.h
@@ -81,9 +81,11 @@ class InspectorDock : public VBoxContainer {
Button *resource_new_button;
Button *resource_load_button;
MenuButton *resource_save_button;
+ MenuButton *resource_extra_button;
MenuButton *history_menu;
LineEdit *search;
+ Button *open_docs_button;
MenuButton *object_menu;
EditorPath *editor_path;
@@ -112,7 +114,7 @@ class InspectorDock : public VBoxContainer {
void _prepare_history();
void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance);
- void _transform_keyed(Object *sp, const String &p_sub, const Transform &p_key);
+ void _transform_keyed(Object *sp, const String &p_sub, const Transform3D &p_key);
protected:
static void _bind_methods();
diff --git a/editor/multi_node_edit.h b/editor/multi_node_edit.h
index 0544eb2d50..2efecb9f65 100644
--- a/editor/multi_node_edit.h
+++ b/editor/multi_node_edit.h
@@ -33,8 +33,8 @@
#include "scene/main/node.h"
-class MultiNodeEdit : public Reference {
- GDCLASS(MultiNodeEdit, Reference);
+class MultiNodeEdit : public RefCounted {
+ GDCLASS(MultiNodeEdit, RefCounted);
List<NodePath> nodes;
struct PLData {
diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp
index afafd7d195..5c69a1e975 100644
--- a/editor/node_3d_editor_gizmos.cpp
+++ b/editor/node_3d_editor_gizmos.cpp
@@ -30,19 +30,18 @@
#include "node_3d_editor_gizmos.h"
+#include "core/math/convex_hull.h"
#include "core/math/geometry_2d.h"
#include "core/math/geometry_3d.h"
-#include "core/math/quick_hull.h"
#include "scene/3d/audio_stream_player_3d.h"
-#include "scene/3d/baked_lightmap.h"
#include "scene/3d/collision_polygon_3d.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/cpu_particles_3d.h"
#include "scene/3d/decal.h"
-#include "scene/3d/gi_probe.h"
#include "scene/3d/gpu_particles_3d.h"
#include "scene/3d/gpu_particles_collision_3d.h"
#include "scene/3d/light_3d.h"
+#include "scene/3d/lightmap_gi.h"
#include "scene/3d/lightmap_probe.h"
#include "scene/3d/listener_3d.h"
#include "scene/3d/mesh_instance_3d.h"
@@ -57,6 +56,7 @@
#include "scene/3d/sprite_3d.h"
#include "scene/3d/vehicle_body_3d.h"
#include "scene/3d/visibility_notifier_3d.h"
+#include "scene/3d/voxel_gi.h"
#include "scene/resources/box_shape_3d.h"
#include "scene/resources/capsule_shape_3d.h"
#include "scene/resources/concave_polygon_shape_3d.h"
@@ -104,8 +104,8 @@ void EditorNode3DGizmo::clear() {
}
void EditorNode3DGizmo::redraw() {
- if (get_script_instance() && get_script_instance()->has_method("redraw")) {
- get_script_instance()->call("redraw");
+ if (get_script_instance() && get_script_instance()->has_method("_redraw")) {
+ get_script_instance()->call("_redraw");
return;
}
@@ -114,8 +114,8 @@ void EditorNode3DGizmo::redraw() {
}
String EditorNode3DGizmo::get_handle_name(int p_idx) const {
- if (get_script_instance() && get_script_instance()->has_method("get_handle_name")) {
- return get_script_instance()->call("get_handle_name", p_idx);
+ if (get_script_instance() && get_script_instance()->has_method("_get_handle_name")) {
+ return get_script_instance()->call("_get_handle_name", p_idx);
}
ERR_FAIL_COND_V(!gizmo_plugin, "");
@@ -123,8 +123,8 @@ String EditorNode3DGizmo::get_handle_name(int p_idx) const {
}
bool EditorNode3DGizmo::is_handle_highlighted(int p_idx) const {
- if (get_script_instance() && get_script_instance()->has_method("is_handle_highlighted")) {
- return get_script_instance()->call("is_handle_highlighted", p_idx);
+ if (get_script_instance() && get_script_instance()->has_method("_is_handle_highlighted")) {
+ return get_script_instance()->call("_is_handle_highlighted", p_idx);
}
ERR_FAIL_COND_V(!gizmo_plugin, false);
@@ -132,8 +132,8 @@ bool EditorNode3DGizmo::is_handle_highlighted(int p_idx) const {
}
Variant EditorNode3DGizmo::get_handle_value(int p_idx) {
- if (get_script_instance() && get_script_instance()->has_method("get_handle_value")) {
- return get_script_instance()->call("get_handle_value", p_idx);
+ if (get_script_instance() && get_script_instance()->has_method("_get_handle_value")) {
+ return get_script_instance()->call("_get_handle_value", p_idx);
}
ERR_FAIL_COND_V(!gizmo_plugin, Variant());
@@ -141,8 +141,8 @@ Variant EditorNode3DGizmo::get_handle_value(int p_idx) {
}
void EditorNode3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) {
- if (get_script_instance() && get_script_instance()->has_method("set_handle")) {
- get_script_instance()->call("set_handle", p_idx, p_camera, p_point);
+ if (get_script_instance() && get_script_instance()->has_method("_set_handle")) {
+ get_script_instance()->call("_set_handle", p_idx, p_camera, p_point);
return;
}
@@ -151,8 +151,8 @@ void EditorNode3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &
}
void EditorNode3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
- if (get_script_instance() && get_script_instance()->has_method("commit_handle")) {
- get_script_instance()->call("commit_handle", p_idx, p_restore, p_cancel);
+ if (get_script_instance() && get_script_instance()->has_method("_commit_handle")) {
+ get_script_instance()->call("_commit_handle", p_idx, p_restore, p_cancel);
return;
}
@@ -455,7 +455,7 @@ bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector
int vc = collision_segments.size();
const Vector3 *vptr = collision_segments.ptr();
- Transform t = spatial_node->get_global_transform();
+ Transform3D t = spatial_node->get_global_transform();
bool any_out = false;
for (int j = 0; j < fc; j++) {
@@ -477,12 +477,12 @@ bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector
}
if (collision_mesh.is_valid()) {
- Transform t = spatial_node->get_global_transform();
+ Transform3D t = spatial_node->get_global_transform();
Vector3 mesh_scale = t.get_basis().get_scale();
t.orthonormalize();
- Transform it = t.affine_inverse();
+ Transform3D it = t.affine_inverse();
Vector<Plane> transformed_frustum;
@@ -508,7 +508,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
}
if (r_gizmo_handle && !hidden) {
- Transform t = spatial_node->get_global_transform();
+ Transform3D t = spatial_node->get_global_transform();
if (billboard_handle) {
t.set_look_at(t.origin, t.origin - p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1));
}
@@ -560,7 +560,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
}
if (selectable_icon_size > 0.0f) {
- Transform t = spatial_node->get_global_transform();
+ Transform3D t = spatial_node->get_global_transform();
Vector3 camera_position = p_camera->get_camera_transform().origin;
if (camera_position.distance_squared_to(t.origin) > 0.01) {
t.set_look_at(t.origin, camera_position);
@@ -576,7 +576,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
Point2 center = p_camera->unproject_position(t.origin);
- Transform orig_camera_transform = p_camera->get_camera_transform();
+ Transform3D orig_camera_transform = p_camera->get_camera_transform();
if (orig_camera_transform.origin.distance_squared_to(t.origin) > 0.01 &&
ABS(orig_camera_transform.basis.get_axis(Vector3::AXIS_Z).dot(Vector3(0, 1, 0))) < 0.99) {
@@ -609,7 +609,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
int vc = collision_segments.size();
const Vector3 *vptr = collision_segments.ptr();
- Transform t = spatial_node->get_global_transform();
+ Transform3D t = spatial_node->get_global_transform();
if (billboard_handle) {
t.set_look_at(t.origin, t.origin - p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1));
}
@@ -657,13 +657,13 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
}
if (collision_mesh.is_valid()) {
- Transform gt = spatial_node->get_global_transform();
+ Transform3D gt = spatial_node->get_global_transform();
if (billboard_handle) {
gt.set_look_at(gt.origin, gt.origin - p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1));
}
- Transform ai = gt.affine_inverse();
+ Transform3D ai = gt.affine_inverse();
Vector3 ray_from = ai.xform(p_camera->project_ray_origin(p_point));
Vector3 ray_dir = ai.basis.xform(p_camera->project_ray_normal(p_point)).normalized();
Vector3 rpos, rnorm;
@@ -739,16 +739,16 @@ void EditorNode3DGizmo::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &EditorNode3DGizmo::clear);
ClassDB::bind_method(D_METHOD("set_hidden", "hidden"), &EditorNode3DGizmo::set_hidden);
- BIND_VMETHOD(MethodInfo("redraw"));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", PropertyInfo(Variant::INT, "index")));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_handle_highlighted", PropertyInfo(Variant::INT, "index")));
+ BIND_VMETHOD(MethodInfo("_redraw"));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_handle_name", PropertyInfo(Variant::INT, "index")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_handle_highlighted", PropertyInfo(Variant::INT, "index")));
- MethodInfo hvget(Variant::NIL, "get_handle_value", PropertyInfo(Variant::INT, "index"));
+ MethodInfo hvget(Variant::NIL, "_get_handle_value", PropertyInfo(Variant::INT, "index"));
hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
BIND_VMETHOD(hvget);
- BIND_VMETHOD(MethodInfo("set_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
- MethodInfo cm = MethodInfo("commit_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
+ BIND_VMETHOD(MethodInfo("_set_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
+ MethodInfo cm = MethodInfo("_commit_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
cm.default_arguments.push_back(false);
BIND_VMETHOD(cm);
}
@@ -826,7 +826,7 @@ Variant Light3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_i
return Variant();
}
-static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vector3 &p_to, float p_arc_radius, const Transform &p_arc_xform) {
+static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vector3 &p_to, float p_arc_radius, const Transform3D &p_arc_xform) {
//bleh, discrete is simpler
static const int arc_test_points = 64;
float min_d = 1e20;
@@ -855,8 +855,8 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec
void Light3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
Light3D *light = Object::cast_to<Light3D>(p_gizmo->get_spatial_node());
- Transform gt = light->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = light->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -1084,8 +1084,8 @@ Variant AudioStreamPlayer3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gi
void AudioStreamPlayer3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node());
- Transform gt = player->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = player->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -1230,8 +1230,8 @@ Variant Camera3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_
void Camera3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
- Transform gt = camera->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = camera->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -1239,7 +1239,7 @@ void Camera3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Came
Vector3 s[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) {
- Transform gt2 = camera->get_global_transform();
+ Transform3D gt2 = camera->get_global_transform();
float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], 1.0, gt2);
camera->set("fov", CLAMP(a * 2.0, 1, 179));
} else {
@@ -1418,7 +1418,7 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
lines.push_back(cam_pos);
}
- Transform local = camera->get_global_transform().affine_inverse();
+ Transform3D local = camera->get_global_transform().affine_inverse();
for (int i = 0; i < lines.size(); i++) {
lines.write[i] = local.xform(lines[i]);
}
@@ -1541,19 +1541,46 @@ Position3DGizmoPlugin::Position3DGizmoPlugin() {
cursor_points = Vector<Vector3>();
Vector<Color> cursor_colors;
- float cs = 0.25;
+ const float cs = 0.25;
+ // Add more points to create a "hard stop" in the color gradient.
cursor_points.push_back(Vector3(+cs, 0, 0));
+ cursor_points.push_back(Vector3());
+ cursor_points.push_back(Vector3());
cursor_points.push_back(Vector3(-cs, 0, 0));
+
cursor_points.push_back(Vector3(0, +cs, 0));
+ cursor_points.push_back(Vector3());
+ cursor_points.push_back(Vector3());
cursor_points.push_back(Vector3(0, -cs, 0));
+
cursor_points.push_back(Vector3(0, 0, +cs));
+ cursor_points.push_back(Vector3());
+ cursor_points.push_back(Vector3());
cursor_points.push_back(Vector3(0, 0, -cs));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor"));
+
+ // Use the axis color which is brighter for the positive axis.
+ // Use a darkened axis color for the negative axis.
+ // This makes it possible to see in which direction the Position3D node is rotated
+ // (which can be important depending on how it's used).
+ const Color color_x = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor");
+ cursor_colors.push_back(color_x);
+ cursor_colors.push_back(color_x);
+ // FIXME: Use less strong darkening factor once GH-48573 is fixed.
+ // The current darkening factor compensates for lines being too bright in the 3D editor.
+ cursor_colors.push_back(color_x.lerp(Color(0, 0, 0), 0.75));
+ cursor_colors.push_back(color_x.lerp(Color(0, 0, 0), 0.75));
+
+ const Color color_y = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor");
+ cursor_colors.push_back(color_y);
+ cursor_colors.push_back(color_y);
+ cursor_colors.push_back(color_y.lerp(Color(0, 0, 0), 0.75));
+ cursor_colors.push_back(color_y.lerp(Color(0, 0, 0), 0.75));
+
+ const Color color_z = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor");
+ cursor_colors.push_back(color_z);
+ cursor_colors.push_back(color_z);
+ cursor_colors.push_back(color_z.lerp(Color(0, 0, 0), 0.75));
+ cursor_colors.push_back(color_z.lerp(Color(0, 0, 0), 0.75));
Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D);
mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
@@ -1617,7 +1644,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
surface_tool->begin(Mesh::PRIMITIVE_LINES);
surface_tool->set_material(material);
- Vector<Transform> grests;
+ Vector<Transform3D> grests;
grests.resize(skel->get_bone_count());
Vector<int> bones;
@@ -1731,59 +1758,10 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(points[(j + 1) % 4]);
}
-
- /*
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(0.4,1,0.4,0.4));
- surface_tool->add_vertex(v0);
- bones[0]=i;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(0.4,1,0.4,0.4));
- surface_tool->add_vertex(v1);
-*/
} else {
grests.write[i] = skel->get_bone_rest(i);
bones.write[0] = i;
}
- /*
- Transform t = grests[i];
- t.orthonormalize();
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
-
- for (int j=0;j<4;j++) {
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- }
-
- for(int j=0;j<4;j++) {
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
- surface_tool->add_vertex(t.xform(face_points[j]*0.04));
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
- surface_tool->add_vertex(t.xform(face_points[(j+1)%4]*0.04));
- }
-
- }
- */
}
Ref<ArrayMesh> m = surface_tool->commit();
@@ -2196,9 +2174,9 @@ Variant VisibilityNotifier3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_g
void VisibilityNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
VisibilityNotifier3D *notifier = Object::cast_to<VisibilityNotifier3D>(p_gizmo->get_spatial_node());
- Transform gt = notifier->get_global_transform();
+ Transform3D gt = notifier->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gi = gt.affine_inverse();
bool move = p_idx >= 3;
p_idx = p_idx % 3;
@@ -2388,8 +2366,8 @@ Variant GPUParticles3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo,
void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_spatial_node());
- Transform gt = particles->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = particles->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
bool move = p_idx >= 3;
p_idx = p_idx % 3;
@@ -2555,8 +2533,8 @@ Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *
void GPUParticlesCollision3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
Node3D *sn = p_gizmo->get_spatial_node();
- Transform gt = sn->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = sn->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -2814,9 +2792,9 @@ Variant ReflectionProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo,
void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node());
- Transform gt = probe->get_global_transform();
+ Transform3D gt = probe->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gi = gt.affine_inverse();
if (p_idx < 3) {
Vector3 extents = probe->get_extents();
@@ -2993,9 +2971,9 @@ Variant DecalGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx
void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
- Transform gt = decal->get_global_transform();
+ Transform3D gt = decal->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gi = gt.affine_inverse();
Vector3 extents = decal->get_extents();
@@ -3086,35 +3064,35 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
///////////////////////////////
-GIProbeGizmoPlugin::GIProbeGizmoPlugin() {
- Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/gi_probe", Color(0.5, 1, 0.6));
+VoxelGIGizmoPlugin::VoxelGIGizmoPlugin() {
+ Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/voxel_gi", Color(0.5, 1, 0.6));
- create_material("gi_probe_material", gizmo_color);
+ create_material("voxel_gi_material", gizmo_color);
// This gizmo draws a lot of lines. Use a low opacity to make it not too intrusive.
gizmo_color.a = 0.1;
- create_material("gi_probe_internal_material", gizmo_color);
+ create_material("voxel_gi_internal_material", gizmo_color);
gizmo_color.a = 0.05;
- create_material("gi_probe_solid_material", gizmo_color);
+ create_material("voxel_gi_solid_material", gizmo_color);
- create_icon_material("gi_probe_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoGIProbe", "EditorIcons"));
+ create_icon_material("voxel_gi_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoVoxelGI", "EditorIcons"));
create_handle_material("handles");
}
-bool GIProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) {
- return Object::cast_to<GIProbe>(p_spatial) != nullptr;
+bool VoxelGIGizmoPlugin::has_gizmo(Node3D *p_spatial) {
+ return Object::cast_to<VoxelGI>(p_spatial) != nullptr;
}
-String GIProbeGizmoPlugin::get_gizmo_name() const {
- return "GIProbe";
+String VoxelGIGizmoPlugin::get_gizmo_name() const {
+ return "VoxelGI";
}
-int GIProbeGizmoPlugin::get_priority() const {
+int VoxelGIGizmoPlugin::get_priority() const {
return -1;
}
-String GIProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
switch (p_idx) {
case 0:
return "Extents X";
@@ -3127,16 +3105,16 @@ String GIProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int
return "";
}
-Variant GIProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
- GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
+Variant VoxelGIGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+ VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
return probe->get_extents();
}
-void GIProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
- GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
+void VoxelGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+ VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
- Transform gt = probe->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = probe->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
Vector3 extents = probe->get_extents();
@@ -3163,8 +3141,8 @@ void GIProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
probe->set_extents(extents);
}
-void GIProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
- GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
+void VoxelGIGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+ VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
Vector3 restore = p_restore;
@@ -3180,19 +3158,19 @@ void GIProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, co
ur->commit_action();
}
-void GIProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
- GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
+void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+ VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
- Ref<Material> material = get_material("gi_probe_material", p_gizmo);
- Ref<Material> icon = get_material("gi_probe_icon", p_gizmo);
- Ref<Material> material_internal = get_material("gi_probe_internal_material", p_gizmo);
+ Ref<Material> material = get_material("voxel_gi_material", p_gizmo);
+ Ref<Material> icon = get_material("voxel_gi_icon", p_gizmo);
+ Ref<Material> material_internal = get_material("voxel_gi_internal_material", p_gizmo);
p_gizmo->clear();
Vector<Vector3> lines;
Vector3 extents = probe->get_extents();
- static const int subdivs[GIProbe::SUBDIV_MAX] = { 64, 128, 256, 512 };
+ static const int subdivs[VoxelGI::SUBDIV_MAX] = { 64, 128, 256, 512 };
AABB aabb = AABB(-extents, extents * 2);
int subdiv = subdivs[probe->get_subdiv()];
@@ -3256,7 +3234,7 @@ void GIProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
if (p_gizmo->is_selected()) {
- Ref<Material> solid_material = get_material("gi_probe_solid_material", p_gizmo);
+ Ref<Material> solid_material = get_material("voxel_gi_solid_material", p_gizmo);
p_gizmo->add_solid_box(solid_material, aabb.get_size());
}
@@ -3266,7 +3244,7 @@ void GIProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
-BakedLightmapGizmoPlugin::BakedLightmapGizmoPlugin() {
+LightmapGIGizmoPlugin::LightmapGIGizmoPlugin() {
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/lightmap_lines", Color(0.5, 0.6, 1));
gizmo_color.a = 0.1;
@@ -3280,39 +3258,39 @@ BakedLightmapGizmoPlugin::BakedLightmapGizmoPlugin() {
add_material("lightmap_probe_material", mat);
- create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoBakedLightmap", "EditorIcons"));
+ create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoLightmapGI", "EditorIcons"));
}
-String BakedLightmapGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String LightmapGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
return "";
}
-Variant BakedLightmapGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant LightmapGIGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
return Variant();
}
-void BakedLightmapGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void LightmapGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
}
-void BakedLightmapGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void LightmapGIGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
}
-bool BakedLightmapGizmoPlugin::has_gizmo(Node3D *p_spatial) {
- return Object::cast_to<BakedLightmap>(p_spatial) != nullptr;
+bool LightmapGIGizmoPlugin::has_gizmo(Node3D *p_spatial) {
+ return Object::cast_to<LightmapGI>(p_spatial) != nullptr;
}
-String BakedLightmapGizmoPlugin::get_gizmo_name() const {
- return "BakedLightmap";
+String LightmapGIGizmoPlugin::get_gizmo_name() const {
+ return "LightmapGI";
}
-int BakedLightmapGizmoPlugin::get_priority() const {
+int LightmapGIGizmoPlugin::get_priority() const {
return -1;
}
-void BakedLightmapGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+void LightmapGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<Material> icon = get_material("baked_indirect_light_icon", p_gizmo);
- BakedLightmap *baker = Object::cast_to<BakedLightmap>(p_gizmo->get_spatial_node());
- Ref<BakedLightmapData> data = baker->get_light_data();
+ LightmapGI *baker = Object::cast_to<LightmapGI>(p_gizmo->get_spatial_node());
+ Ref<LightmapGIData> data = baker->get_light_data();
p_gizmo->add_unscaled_billboard(icon, 0.05);
@@ -3583,7 +3561,7 @@ void CollisionObject3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
co->get_shape_owners(&owners);
for (List<uint32_t>::Element *E = owners.front(); E; E = E->next()) {
uint32_t owner_id = E->get();
- Transform xform = co->shape_owner_get_transform(owner_id);
+ Transform3D xform = co->shape_owner_get_transform(owner_id);
Object *owner = co->shape_owner_get_owner(owner_id);
// Exclude CollisionShape3D and CollisionPolygon3D as they have their gizmo.
if (!Object::cast_to<CollisionShape3D>(owner) && !Object::cast_to<CollisionPolygon3D>(owner)) {
@@ -3701,8 +3679,8 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
return;
}
- Transform gt = cs->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = cs->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -4161,7 +4139,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
if (points.size() > 3) {
Vector<Vector3> varr = Variant(points);
Geometry3D::MeshData md;
- Error err = QuickHull::build(varr, md);
+ Error err = ConvexHullComputer::convex_hull(varr, md);
if (err == OK) {
Vector<Vector3> points2;
points2.resize(md.edges.size() * 2);
@@ -4369,7 +4347,7 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
#define BODY_A_RADIUS 0.25
#define BODY_B_RADIUS 0.27
-Basis JointGizmosDrawer::look_body(const Transform &p_joint_transform, const Transform &p_body_transform) {
+Basis JointGizmosDrawer::look_body(const Transform3D &p_joint_transform, const Transform3D &p_body_transform) {
const Vector3 &p_eye(p_joint_transform.origin);
const Vector3 &p_target(p_body_transform.origin);
@@ -4394,7 +4372,7 @@ Basis JointGizmosDrawer::look_body(const Transform &p_joint_transform, const Tra
return base;
}
-Basis JointGizmosDrawer::look_body_toward(Vector3::Axis p_axis, const Transform &joint_transform, const Transform &body_transform) {
+Basis JointGizmosDrawer::look_body_toward(Vector3::Axis p_axis, const Transform3D &joint_transform, const Transform3D &body_transform) {
switch (p_axis) {
case Vector3::AXIS_X:
return look_body_toward_x(joint_transform, body_transform);
@@ -4407,7 +4385,7 @@ Basis JointGizmosDrawer::look_body_toward(Vector3::Axis p_axis, const Transform
}
}
-Basis JointGizmosDrawer::look_body_toward_x(const Transform &p_joint_transform, const Transform &p_body_transform) {
+Basis JointGizmosDrawer::look_body_toward_x(const Transform3D &p_joint_transform, const Transform3D &p_body_transform) {
const Vector3 &p_eye(p_joint_transform.origin);
const Vector3 &p_target(p_body_transform.origin);
@@ -4438,7 +4416,7 @@ Basis JointGizmosDrawer::look_body_toward_x(const Transform &p_joint_transform,
return base;
}
-Basis JointGizmosDrawer::look_body_toward_y(const Transform &p_joint_transform, const Transform &p_body_transform) {
+Basis JointGizmosDrawer::look_body_toward_y(const Transform3D &p_joint_transform, const Transform3D &p_body_transform) {
const Vector3 &p_eye(p_joint_transform.origin);
const Vector3 &p_target(p_body_transform.origin);
@@ -4469,7 +4447,7 @@ Basis JointGizmosDrawer::look_body_toward_y(const Transform &p_joint_transform,
return base;
}
-Basis JointGizmosDrawer::look_body_toward_z(const Transform &p_joint_transform, const Transform &p_body_transform) {
+Basis JointGizmosDrawer::look_body_toward_z(const Transform3D &p_joint_transform, const Transform3D &p_body_transform) {
const Vector3 &p_eye(p_joint_transform.origin);
const Vector3 &p_target(p_body_transform.origin);
@@ -4500,7 +4478,7 @@ Basis JointGizmosDrawer::look_body_toward_z(const Transform &p_joint_transform,
return base;
}
-void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse) {
+void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform3D &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse) {
if (p_limit_lower == p_limit_upper) {
r_points.push_back(p_offset.translated(Vector3()).origin);
r_points.push_back(p_offset.translated(p_base.xform(Vector3(0.5, 0, 0))).origin);
@@ -4562,7 +4540,7 @@ void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const
}
}
-void JointGizmosDrawer::draw_cone(const Transform &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points) {
+void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points) {
float r = 1.0;
float w = r * Math::sin(p_swing);
float d = r * Math::cos(p_swing);
@@ -4666,7 +4644,7 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector<Vector3> body_b_points;
if (Object::cast_to<PinJoint3D>(joint)) {
- CreatePinJointGizmo(Transform(), points);
+ CreatePinJointGizmo(Transform3D(), points);
p_gizmo->add_collision_segments(points);
p_gizmo->add_lines(points, common_material);
}
@@ -4674,10 +4652,10 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
HingeJoint3D *hinge = Object::cast_to<HingeJoint3D>(joint);
if (hinge) {
CreateHingeJointGizmo(
- Transform(),
+ Transform3D(),
hinge->get_global_transform(),
- node_body_a ? node_body_a->get_global_transform() : Transform(),
- node_body_b ? node_body_b->get_global_transform() : Transform(),
+ node_body_a ? node_body_a->get_global_transform() : Transform3D(),
+ node_body_b ? node_body_b->get_global_transform() : Transform3D(),
hinge->get_param(HingeJoint3D::PARAM_LIMIT_LOWER),
hinge->get_param(HingeJoint3D::PARAM_LIMIT_UPPER),
hinge->get_flag(HingeJoint3D::FLAG_USE_LIMIT),
@@ -4697,10 +4675,10 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
SliderJoint3D *slider = Object::cast_to<SliderJoint3D>(joint);
if (slider) {
CreateSliderJointGizmo(
- Transform(),
+ Transform3D(),
slider->get_global_transform(),
- node_body_a ? node_body_a->get_global_transform() : Transform(),
- node_body_b ? node_body_b->get_global_transform() : Transform(),
+ node_body_a ? node_body_a->get_global_transform() : Transform3D(),
+ node_body_b ? node_body_b->get_global_transform() : Transform3D(),
slider->get_param(SliderJoint3D::PARAM_ANGULAR_LIMIT_LOWER),
slider->get_param(SliderJoint3D::PARAM_ANGULAR_LIMIT_UPPER),
slider->get_param(SliderJoint3D::PARAM_LINEAR_LIMIT_LOWER),
@@ -4721,10 +4699,10 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
ConeTwistJoint3D *cone = Object::cast_to<ConeTwistJoint3D>(joint);
if (cone) {
CreateConeTwistJointGizmo(
- Transform(),
+ Transform3D(),
cone->get_global_transform(),
- node_body_a ? node_body_a->get_global_transform() : Transform(),
- node_body_b ? node_body_b->get_global_transform() : Transform(),
+ node_body_a ? node_body_a->get_global_transform() : Transform3D(),
+ node_body_b ? node_body_b->get_global_transform() : Transform3D(),
cone->get_param(ConeTwistJoint3D::PARAM_SWING_SPAN),
cone->get_param(ConeTwistJoint3D::PARAM_TWIST_SPAN),
node_body_a ? &body_a_points : nullptr,
@@ -4740,10 +4718,10 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Generic6DOFJoint3D *gen = Object::cast_to<Generic6DOFJoint3D>(joint);
if (gen) {
CreateGeneric6DOFJointGizmo(
- Transform(),
+ Transform3D(),
gen->get_global_transform(),
- node_body_a ? node_body_a->get_global_transform() : Transform(),
- node_body_b ? node_body_b->get_global_transform() : Transform(),
+ node_body_a ? node_body_a->get_global_transform() : Transform3D(),
+ node_body_b ? node_body_b->get_global_transform() : Transform3D(),
gen->get_param_x(Generic6DOFJoint3D::PARAM_ANGULAR_LOWER_LIMIT),
gen->get_param_x(Generic6DOFJoint3D::PARAM_ANGULAR_UPPER_LIMIT),
@@ -4780,7 +4758,7 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
}
-void Joint3DGizmoPlugin::CreatePinJointGizmo(const Transform &p_offset, Vector<Vector3> &r_cursor_points) {
+void Joint3DGizmoPlugin::CreatePinJointGizmo(const Transform3D &p_offset, Vector<Vector3> &r_cursor_points) {
float cs = 0.25;
r_cursor_points.push_back(p_offset.translated(Vector3(+cs, 0, 0)).origin);
@@ -4791,7 +4769,7 @@ void Joint3DGizmoPlugin::CreatePinJointGizmo(const Transform &p_offset, Vector<V
r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, -cs)).origin);
}
-void Joint3DGizmoPlugin::CreateHingeJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
+void Joint3DGizmoPlugin::CreateHingeJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
r_common_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin);
r_common_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin);
@@ -4821,7 +4799,7 @@ void Joint3DGizmoPlugin::CreateHingeJointGizmo(const Transform &p_offset, const
}
}
-void Joint3DGizmoPlugin::CreateSliderJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
+void Joint3DGizmoPlugin::CreateSliderJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
p_linear_limit_lower = -p_linear_limit_lower;
p_linear_limit_upper = -p_linear_limit_upper;
@@ -4880,7 +4858,7 @@ void Joint3DGizmoPlugin::CreateSliderJointGizmo(const Transform &p_offset, const
}
}
-void Joint3DGizmoPlugin::CreateConeTwistJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
+void Joint3DGizmoPlugin::CreateConeTwistJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
if (r_body_a_points) {
JointGizmosDrawer::draw_cone(
p_offset,
@@ -4901,10 +4879,10 @@ void Joint3DGizmoPlugin::CreateConeTwistJointGizmo(const Transform &p_offset, co
}
void Joint3DGizmoPlugin::CreateGeneric6DOFJointGizmo(
- const Transform &p_offset,
- const Transform &p_trs_joint,
- const Transform &p_trs_body_a,
- const Transform &p_trs_body_b,
+ const Transform3D &p_offset,
+ const Transform3D &p_trs_joint,
+ const Transform3D &p_trs_body_a,
+ const Transform3D &p_trs_body_b,
real_t p_angular_limit_lower_x,
real_t p_angular_limit_upper_x,
real_t p_linear_limit_lower_x,
diff --git a/editor/node_3d_editor_gizmos.h b/editor/node_3d_editor_gizmos.h
index 95344176ad..8a0e10241a 100644
--- a/editor/node_3d_editor_gizmos.h
+++ b/editor/node_3d_editor_gizmos.h
@@ -316,8 +316,8 @@ public:
DecalGizmoPlugin();
};
-class GIProbeGizmoPlugin : public EditorNode3DGizmoPlugin {
- GDCLASS(GIProbeGizmoPlugin, EditorNode3DGizmoPlugin);
+class VoxelGIGizmoPlugin : public EditorNode3DGizmoPlugin {
+ GDCLASS(VoxelGIGizmoPlugin, EditorNode3DGizmoPlugin);
public:
bool has_gizmo(Node3D *p_spatial) override;
@@ -330,11 +330,11 @@ public:
void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
- GIProbeGizmoPlugin();
+ VoxelGIGizmoPlugin();
};
-class BakedLightmapGizmoPlugin : public EditorNode3DGizmoPlugin {
- GDCLASS(BakedLightmapGizmoPlugin, EditorNode3DGizmoPlugin);
+class LightmapGIGizmoPlugin : public EditorNode3DGizmoPlugin {
+ GDCLASS(LightmapGIGizmoPlugin, EditorNode3DGizmoPlugin);
public:
bool has_gizmo(Node3D *p_spatial) override;
@@ -347,7 +347,7 @@ public:
void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
- BakedLightmapGizmoPlugin();
+ LightmapGIGizmoPlugin();
};
class LightmapProbeGizmoPlugin : public EditorNode3DGizmoPlugin {
@@ -428,17 +428,17 @@ public:
class JointGizmosDrawer {
public:
- static Basis look_body(const Transform &p_joint_transform, const Transform &p_body_transform);
- static Basis look_body_toward(Vector3::Axis p_axis, const Transform &joint_transform, const Transform &body_transform);
- static Basis look_body_toward_x(const Transform &p_joint_transform, const Transform &p_body_transform);
- static Basis look_body_toward_y(const Transform &p_joint_transform, const Transform &p_body_transform);
+ static Basis look_body(const Transform3D &p_joint_transform, const Transform3D &p_body_transform);
+ static Basis look_body_toward(Vector3::Axis p_axis, const Transform3D &joint_transform, const Transform3D &body_transform);
+ static Basis look_body_toward_x(const Transform3D &p_joint_transform, const Transform3D &p_body_transform);
+ static Basis look_body_toward_y(const Transform3D &p_joint_transform, const Transform3D &p_body_transform);
/// Special function just used for physics joints, it returns a basis constrained toward Joint Z axis
/// with axis X and Y that are looking toward the body and oriented toward up
- static Basis look_body_toward_z(const Transform &p_joint_transform, const Transform &p_body_transform);
+ static Basis look_body_toward_z(const Transform3D &p_joint_transform, const Transform3D &p_body_transform);
// Draw circle around p_axis
- static void draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse = false);
- static void draw_cone(const Transform &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points);
+ static void draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform3D &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse = false);
+ static void draw_cone(const Transform3D &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points);
};
class Joint3DGizmoPlugin : public EditorNode3DGizmoPlugin {
@@ -455,15 +455,15 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- static void CreatePinJointGizmo(const Transform &p_offset, Vector<Vector3> &r_cursor_points);
- static void CreateHingeJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
- static void CreateSliderJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
- static void CreateConeTwistJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
+ static void CreatePinJointGizmo(const Transform3D &p_offset, Vector<Vector3> &r_cursor_points);
+ static void CreateHingeJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
+ static void CreateSliderJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
+ static void CreateConeTwistJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
static void CreateGeneric6DOFJointGizmo(
- const Transform &p_offset,
- const Transform &p_trs_joint,
- const Transform &p_trs_body_a,
- const Transform &p_trs_body_b,
+ const Transform3D &p_offset,
+ const Transform3D &p_trs_joint,
+ const Transform3D &p_trs_body_a,
+ const Transform3D &p_trs_body_b,
real_t p_angular_limit_lower_x,
real_t p_angular_limit_upper_x,
real_t p_linear_limit_lower_x,
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index f496811e0a..f55d77d782 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -30,7 +30,7 @@
#include "plugin_config_dialog.h"
#include "core/io/config_file.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "editor/editor_scale.h"
@@ -214,6 +214,7 @@ PluginConfigDialog::PluginConfigDialog() {
desc_edit = memnew(TextEdit);
desc_edit->set_custom_minimum_size(Size2(400, 80) * EDSCALE);
+ desc_edit->set_wrap_enabled(true);
grid->add_child(desc_edit);
Label *author_lb = memnew(Label);
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index 80d0a7db60..e6f7ec1fbf 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -266,7 +266,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) {
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
- if (mb->get_control() || mb->get_shift() || mb->get_alt()) {
+ if (mb->is_ctrl_pressed() || mb->is_shift_pressed() || mb->is_alt_pressed()) {
return false;
}
@@ -399,7 +399,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
//Move the point in a single axis. Should only work when editing a polygon and while holding shift.
- if (mode == MODE_EDIT && mm->get_shift()) {
+ if (mode == MODE_EDIT && mm->is_shift_pressed()) {
Vector2 old_point = pre_move_edit.get(selected_point.vertex);
if (ABS(cpoint.x - old_point.x) > ABS(cpoint.y - old_point.y)) {
cpoint.y = old_point.y;
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 612a8f30a4..bd88d96a66 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -994,7 +994,7 @@ void AnimationPlayerEditor::_animation_duplicate() {
}
}
-void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set) {
+void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set, bool p_timeline_only) {
if (updating || !player || player->is_playing()) {
return;
};
@@ -1015,18 +1015,18 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set) {
pos = Math::snapped(pos, _get_editor_step());
}
- if (player->is_valid() && !p_set) {
- float cpos = player->get_current_animation_position();
+ if (!p_timeline_only) {
+ if (player->is_valid() && !p_set) {
+ float cpos = player->get_current_animation_position();
- player->seek_delta(pos, pos - cpos);
- } else {
- player->stop(true);
- player->seek(pos, true);
+ player->seek_delta(pos, pos - cpos);
+ } else {
+ player->stop(true);
+ player->seek(pos, true);
+ }
}
track_editor->set_anim_pos(pos);
-
- updating = true;
};
void AnimationPlayerEditor::_animation_player_changed(Object *p_pl) {
@@ -1048,7 +1048,7 @@ void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float p_len)
frame->set_max(p_len);
}
-void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag) {
+void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag, bool p_timeline_only) {
timeline_position = p_pos;
if (!is_visible_in_tree()) {
@@ -1070,7 +1070,7 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag)
updating = true;
frame->set_value(Math::snapped(p_pos, _get_editor_step()));
updating = false;
- _seek_value_changed(p_pos, !p_drag);
+ _seek_value_changed(p_pos, !p_drag, p_timeline_only);
}
void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
@@ -1222,10 +1222,10 @@ void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
Ref<InputEventKey> k = p_ev;
- if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->get_alt() && !k->get_control() && !k->get_metakey()) {
+ if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->is_alt_pressed() && !k->is_ctrl_pressed() && !k->is_meta_pressed()) {
switch (k->get_keycode()) {
case KEY_A: {
- if (!k->get_shift()) {
+ if (!k->is_shift_pressed()) {
_play_bw_from_pressed();
} else {
_play_bw_pressed();
@@ -1237,7 +1237,7 @@ void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
accept_event();
} break;
case KEY_D: {
- if (!k->get_shift()) {
+ if (!k->is_shift_pressed()) {
_play_from_pressed();
} else {
_play_pressed();
@@ -1693,7 +1693,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
animation->connect("item_selected", callable_mp(this, &AnimationPlayerEditor::_animation_selected));
file->connect("file_selected", callable_mp(this, &AnimationPlayerEditor::_dialog_action));
- frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed), make_binds(true));
+ frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed), make_binds(true, false));
scale->connect("text_entered", callable_mp(this, &AnimationPlayerEditor::_scale_changed));
renaming = false;
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 2f6bf55e4c..5c2348f86b 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -187,7 +187,7 @@ class AnimationPlayerEditor : public VBoxContainer {
void _scale_changed(const String &p_scale);
void _dialog_action(String p_file);
void _seek_frame_changed(const String &p_frame);
- void _seek_value_changed(float p_value, bool p_set = false);
+ void _seek_value_changed(float p_value, bool p_set = false, bool p_timeline_only = false);
void _blend_editor_next_changed(const int p_idx);
void _list_changed();
@@ -197,7 +197,7 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_player_changed(Object *p_pl);
- void _animation_key_editor_seek(float p_pos, bool p_drag);
+ void _animation_key_editor_seek(float p_pos, bool p_drag, bool p_timeline_only = false);
void _animation_key_editor_anim_len_changed(float p_len);
void _unhandled_key_input(const Ref<InputEvent> &p_ev);
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index a9709bbb16..c915276d3a 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -124,7 +124,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
}
// select node or push a field inside
- if (mb.is_valid() && !mb->get_shift() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->is_shift_pressed() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
selected_transition_from = StringName();
selected_transition_to = StringName();
selected_node = StringName();
@@ -237,7 +237,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
}
//connect nodes
- if (mb.is_valid() && ((tool_select->is_pressed() && mb->get_shift()) || tool_connect->is_pressed()) && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) {
+ if (mb.is_valid() && ((tool_select->is_pressed() && mb->is_shift_pressed()) || tool_connect->is_pressed()) && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) {
for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order
if (node_rects[i].node.has_point(mb->get_position())) { //select node since nothing else was selected
connecting = true;
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index a0d9afee74..93bb170128 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -464,7 +464,7 @@ void EditorAssetLibraryItemDownload::_make_request() {
retry->hide();
download->cancel_request();
- download->set_download_file(EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_asset_" + itos(asset_id)) + ".zip");
+ download->set_download_file(EditorPaths::get_singleton()->get_cache_dir().plus_file("tmp_asset_" + itos(asset_id)) + ".zip");
Error err = download->request(host);
if (err != OK) {
@@ -702,7 +702,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
PackedByteArray image_data = p_data;
if (use_cache) {
- String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
+ String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
FileAccess *file = FileAccess::open(cache_filename_base + ".data", FileAccess::READ);
@@ -781,7 +781,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
if (p_code != HTTPClient::RESPONSE_NOT_MODIFIED) {
for (int i = 0; i < headers.size(); i++) {
if (headers[i].findn("ETag:") == 0) { // Save etag
- String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
+ String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
String new_etag = headers[i].substr(headers[i].find(":") + 1, headers[i].length()).strip_edges();
FileAccess *file;
@@ -829,7 +829,7 @@ void EditorAssetLibrary::_update_image_queue() {
List<int> to_delete;
for (Map<int, ImageQueue>::Element *E = image_queue.front(); E; E = E->next()) {
if (!E->get().active && current_images < max_images) {
- String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + E->get().image_url.md5_text());
+ String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + E->get().image_url.md5_text());
Vector<String> headers;
if (FileAccess::exists(cache_filename_base + ".etag") && FileAccess::exists(cache_filename_base + ".data")) {
diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp
deleted file mode 100644
index 470b61bf40..0000000000
--- a/editor/plugins/baked_lightmap_editor_plugin.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*************************************************************************/
-/* baked_lightmap_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "baked_lightmap_editor_plugin.h"
-
-void BakedLightmapEditorPlugin::_bake_select_file(const String &p_file) {
- if (lightmap) {
- BakedLightmap::BakeError err;
- if (get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root() == lightmap) {
- err = lightmap->bake(lightmap, p_file, bake_func_step);
- } else {
- err = lightmap->bake(lightmap->get_parent(), p_file, bake_func_step);
- }
-
- bake_func_end();
-
- switch (err) {
- case BakedLightmap::BAKE_ERROR_NO_SAVE_PATH: {
- String scene_path = lightmap->get_filename();
- if (scene_path == String()) {
- scene_path = lightmap->get_owner()->get_filename();
- }
- if (scene_path == String()) {
- EditorNode::get_singleton()->show_warning(TTR("Can't determine a save path for lightmap images.\nSave your scene and try again."));
- break;
- }
- scene_path = scene_path.get_basename() + ".lmbake";
-
- file_dialog->set_current_path(scene_path);
- file_dialog->popup_file_dialog();
-
- } break;
- case BakedLightmap::BAKE_ERROR_NO_MESHES:
- EditorNode::get_singleton()->show_warning(TTR("No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake Light' flag is on."));
- break;
- case BakedLightmap::BAKE_ERROR_CANT_CREATE_IMAGE:
- EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable."));
- break;
- default: {
- }
- }
- }
-}
-
-void BakedLightmapEditorPlugin::_bake() {
- _bake_select_file("");
-}
-
-void BakedLightmapEditorPlugin::edit(Object *p_object) {
- BakedLightmap *s = Object::cast_to<BakedLightmap>(p_object);
- if (!s) {
- return;
- }
-
- lightmap = s;
-}
-
-bool BakedLightmapEditorPlugin::handles(Object *p_object) const {
- return p_object->is_class("BakedLightmap");
-}
-
-void BakedLightmapEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
- bake->show();
- } else {
- bake->hide();
- }
-}
-
-EditorProgress *BakedLightmapEditorPlugin::tmp_progress = nullptr;
-
-bool BakedLightmapEditorPlugin::bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh) {
- if (!tmp_progress) {
- tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, false));
- ERR_FAIL_COND_V(tmp_progress == nullptr, false);
- }
- return tmp_progress->step(p_description, p_progress * 1000, p_refresh);
-}
-
-void BakedLightmapEditorPlugin::bake_func_end() {
- if (tmp_progress != nullptr) {
- memdelete(tmp_progress);
- tmp_progress = nullptr;
- }
-}
-
-void BakedLightmapEditorPlugin::_bind_methods() {
- ClassDB::bind_method("_bake", &BakedLightmapEditorPlugin::_bake);
-}
-
-BakedLightmapEditorPlugin::BakedLightmapEditorPlugin(EditorNode *p_node) {
- editor = p_node;
- bake = memnew(Button);
- bake->set_flat(true);
- bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
- bake->set_text(TTR("Bake Lightmaps"));
- bake->hide();
- bake->connect("pressed", Callable(this, "_bake"));
- add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake);
- lightmap = nullptr;
-
- file_dialog = memnew(EditorFileDialog);
- file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- file_dialog->add_filter("*.lmbake ; LightMap Bake");
- file_dialog->set_title(TTR("Select lightmap bake file:"));
- file_dialog->connect("file_selected", callable_mp(this, &BakedLightmapEditorPlugin::_bake_select_file));
- bake->add_child(file_dialog);
-}
-
-BakedLightmapEditorPlugin::~BakedLightmapEditorPlugin() {
-}
diff --git a/editor/plugins/baked_lightmap_editor_plugin.h b/editor/plugins/baked_lightmap_editor_plugin.h
deleted file mode 100644
index d291c377d9..0000000000
--- a/editor/plugins/baked_lightmap_editor_plugin.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*************************************************************************/
-/* baked_lightmap_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef BAKED_LIGHTMAP_EDITOR_PLUGIN_H
-#define BAKED_LIGHTMAP_EDITOR_PLUGIN_H
-
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
-#include "scene/3d/baked_lightmap.h"
-#include "scene/resources/material.h"
-
-class BakedLightmapEditorPlugin : public EditorPlugin {
- GDCLASS(BakedLightmapEditorPlugin, EditorPlugin);
-
- BakedLightmap *lightmap;
-
- Button *bake;
- EditorNode *editor;
-
- EditorFileDialog *file_dialog;
- static EditorProgress *tmp_progress;
- static bool bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh);
- static void bake_func_end();
-
- void _bake_select_file(const String &p_file);
- void _bake();
-
-protected:
- static void _bind_methods();
-
-public:
- virtual String get_name() const override { return "BakedLightmap"; }
- bool has_main_screen() const override { return false; }
- virtual void edit(Object *p_object) override;
- virtual bool handles(Object *p_object) const override;
- virtual void make_visible(bool p_visible) override;
-
- BakedLightmapEditorPlugin(EditorNode *p_node);
- ~BakedLightmapEditorPlugin();
-};
-
-#endif
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 91022ccb2c..5d248176c1 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -332,7 +332,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
- bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CTRL);
// Smart snap using the canvas position
Vector2 output = p_target;
@@ -460,7 +460,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
}
float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
- if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) {
+ if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CTRL)) && snap_rotation_step != 0) {
if (snap_relative) {
return Math::snapped(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset + (p_start - (int)(p_start / snap_rotation_step) * snap_rotation_step);
} else {
@@ -481,11 +481,11 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
}
if (k.is_valid()) {
- if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) {
+ if (k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) {
viewport->update();
}
- if (k->is_pressed() && !k->get_control() && !k->is_echo()) {
+ if (k->is_pressed() && !k->is_ctrl_pressed() && !k->is_echo()) {
if ((grid_snap_active || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) {
// Multiply the grid size
grid_step_multiplier = MIN(grid_step_multiplier + 1, 12);
@@ -666,93 +666,6 @@ void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_Sel
}
}
-void CanvasItemEditor::_get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items) {
- Point2 screen_pos = transform.xform(p_pos);
-
- for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
- Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
-
- Vector<Vector2> bone_shape;
- if (!_get_bone_shape(&bone_shape, nullptr, E)) {
- continue;
- }
-
- // Check if the point is inside the Polygon2D
- if (Geometry2D::is_point_in_polygon(screen_pos, bone_shape)) {
- // Check if the item is already in the list
- bool duplicate = false;
- for (int i = 0; i < r_items.size(); i++) {
- if (r_items[i].item == from_node) {
- duplicate = true;
- break;
- }
- }
- if (duplicate) {
- continue;
- }
-
- // Else, add it
- _SelectResult res;
- res.item = from_node;
- res.z_index = from_node ? from_node->get_z_index() : 0;
- res.has_z = from_node;
- r_items.push_back(res);
- }
- }
-}
-
-bool CanvasItemEditor::_get_bone_shape(Vector<Vector2> *shape, Vector<Vector2> *outline_shape, Map<BoneKey, BoneList>::Element *bone) {
- int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
- int bone_outline_width = EditorSettings::get_singleton()->get("editors/2d/bone_outline_size");
-
- Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().from));
- Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().to));
-
- if (!from_node) {
- return false;
- }
- if (!from_node->is_inside_tree()) {
- return false; //may have been removed
- }
-
- if (!to_node && bone->get().length == 0) {
- return false;
- }
-
- Vector2 from = transform.xform(from_node->get_global_position());
- Vector2 to;
-
- if (to_node) {
- to = transform.xform(to_node->get_global_position());
- } else {
- to = transform.xform(from_node->get_global_transform().xform(Vector2(bone->get().length, 0)));
- }
-
- Vector2 rel = to - from;
- Vector2 relt = rel.orthogonal().normalized() * bone_width;
- Vector2 reln = rel.normalized();
- Vector2 reltn = relt.normalized();
-
- if (shape) {
- shape->clear();
- shape->push_back(from);
- shape->push_back(from + rel * 0.2 + relt);
- shape->push_back(to);
- shape->push_back(from + rel * 0.2 - relt);
- }
-
- if (outline_shape) {
- outline_shape->clear();
- outline_shape->push_back(from + (-reln - reltn) * bone_outline_width);
- outline_shape->push_back(from + (-reln + reltn) * bone_outline_width);
- outline_shape->push_back(from + rel * 0.2 + relt + reltn * bone_outline_width);
- outline_shape->push_back(to + (reln + reltn) * bone_outline_width);
- outline_shape->push_back(to + (reln - reltn) * bone_outline_width);
- outline_shape->push_back(from + rel * 0.2 - relt - reltn * bone_outline_width);
- }
- return true;
-}
-
void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
if (!p_node) {
return;
@@ -886,50 +799,6 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2
return output;
}
-void CanvasItemEditor::_save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state) {
- if (p_bones_length) {
- *p_bones_length = List<float>();
- }
- if (p_bones_state) {
- *p_bones_state = List<Dictionary>();
- }
-
- const Node2D *bone = Object::cast_to<Node2D>(p_canvas_item);
- if (bone && bone->has_meta("_edit_bone_")) {
- // Check if we have an IK chain
- List<const Node2D *> bone_ik_list;
- bool ik_found = false;
- bone = Object::cast_to<Node2D>(bone->get_parent());
- while (bone) {
- bone_ik_list.push_back(bone);
- if (bone->has_meta("_edit_ik_")) {
- ik_found = true;
- break;
- } else if (!bone->has_meta("_edit_bone_")) {
- break;
- }
- bone = Object::cast_to<Node2D>(bone->get_parent());
- }
-
- //Save the bone state and length if we have an IK chain
- if (ik_found) {
- bone = Object::cast_to<Node2D>(p_canvas_item);
- Transform2D bone_xform = bone->get_global_transform();
- for (List<const Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) {
- bone_xform = bone_xform * bone->get_transform().affine_inverse();
- const Node2D *parent_bone = bone_E->get();
- if (p_bones_length) {
- p_bones_length->push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position()));
- }
- if (p_bones_state) {
- p_bones_state->push_back(parent_bone->_edit_get_state());
- }
- bone = parent_bone;
- }
- }
- }
-}
-
void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) {
for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
@@ -942,31 +811,15 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items
} else {
se->pre_drag_rect = Rect2();
}
-
- // If we have a bone, save the state of all nodes in the IK chain
- _save_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_length), &(se->pre_drag_bones_undo_state));
}
}
}
-void CanvasItemEditor::_restore_canvas_item_ik_chain(CanvasItem *p_canvas_item, const List<Dictionary> *p_bones_state) {
- CanvasItem *canvas_item = p_canvas_item;
- for (const List<Dictionary>::Element *E = p_bones_state->front(); E; E = E->next()) {
- canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
- canvas_item->_edit_set_state(E->get());
- }
-}
-
void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) {
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (se) {
- canvas_item->_edit_set_state(se->undo_state);
- if (restore_bones) {
- _restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state));
- }
- }
+ canvas_item->_edit_set_state(se->undo_state);
}
}
@@ -1269,12 +1122,12 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid() && !p_already_accepted) {
- const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->get_control();
+ const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->is_ctrl_pressed();
if (pan_on_scroll) {
// Perform horizontal scrolling first so we can check for Shift being held.
if (b->is_pressed() &&
- (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP))) {
+ (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->is_shift_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP))) {
// Pan left
view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
update_viewport();
@@ -1282,7 +1135,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
}
if (b->is_pressed() &&
- (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN))) {
+ (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->is_shift_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN))) {
// Pan right
view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
update_viewport();
@@ -1389,7 +1242,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid() && !p_already_accepted) {
// If control key pressed, then zoom instead of pan
- if (pan_gesture->get_control()) {
+ if (pan_gesture->is_ctrl_pressed()) {
const float factor = pan_gesture->get_delta().y;
zoom_widget->set_zoom_by_increments(1);
@@ -1497,76 +1350,6 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
return false;
}
-void CanvasItemEditor::_solve_IK(Node2D *leaf_node, Point2 target_position) {
- CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(leaf_node);
- if (se) {
- int nb_bones = se->pre_drag_bones_undo_state.size();
- if (nb_bones > 0) {
- // Build the node list
- Point2 leaf_pos = target_position;
-
- List<Node2D *> joints_list;
- List<Point2> joints_pos;
- Node2D *joint = leaf_node;
- Transform2D joint_transform = leaf_node->get_global_transform_with_canvas();
- for (int i = 0; i < nb_bones + 1; i++) {
- joints_list.push_back(joint);
- joints_pos.push_back(joint_transform.get_origin());
- joint_transform = joint_transform * joint->get_transform().affine_inverse();
- joint = Object::cast_to<Node2D>(joint->get_parent());
- }
- Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin();
-
- // Restraints the node to a maximum distance is necessary
- float total_len = 0;
- for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) {
- total_len += E->get();
- }
- if ((root_pos.distance_to(leaf_pos)) > total_len) {
- Vector2 rel = leaf_pos - root_pos;
- rel = rel.normalized() * total_len;
- leaf_pos = root_pos + rel;
- }
- joints_pos[0] = leaf_pos;
-
- // Run the solver
- int solver_iterations = 64;
- float solver_k = 0.3;
-
- // Build the position list
- for (int i = 0; i < solver_iterations; i++) {
- // Handle the leaf joint
- int node_id = 0;
- for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) {
- Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized();
- int len = E->get();
- if (E == se->pre_drag_bones_length.front()) {
- joints_pos[1] = joints_pos[1].lerp(joints_pos[0] + len * direction, solver_k);
- } else if (E == se->pre_drag_bones_length.back()) {
- joints_pos[node_id] = joints_pos[node_id].lerp(joints_pos[node_id + 1] - len * direction, solver_k);
- } else {
- Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0;
- joints_pos[node_id] = joints_pos[node_id].lerp(center - (direction * len) / 2.0, solver_k);
- joints_pos[node_id + 1] = joints_pos[node_id + 1].lerp(center + (direction * len) / 2.0, solver_k);
- }
- node_id++;
- }
- }
-
- // Set the position
- for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) {
- Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized();
- Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized();
- float rot = current.angle_to(target);
- if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) {
- rot = -rot;
- }
- joints_list[node_id]->rotate(rot);
- }
- }
- }
-}
-
bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
Ref<InputEventMouseMotion> m = p_event;
@@ -1574,7 +1357,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
// Start rotation
if (drag_type == DRAG_NONE) {
if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) {
- if ((b->get_command() && !b->get_alt() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
+ if ((b->is_command_pressed() && !b->is_alt_pressed() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
List<CanvasItem *> selection = _get_edited_canvas_items();
// Remove not movable nodes
@@ -1740,7 +1523,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
Vector2 new_anchor = xform.xform(snap_point(previous_anchor + (drag_to - drag_from), SNAP_GRID | SNAP_OTHER_NODES, SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER, control));
new_anchor = _position_to_anchor(control, new_anchor).snapped(Vector2(0.001, 0.001));
- bool use_single_axis = m->get_shift();
+ bool use_single_axis = m->is_shift_pressed();
Vector2 drag_vector = xform.xform(drag_to) - xform.xform(drag_from);
bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x);
@@ -1888,8 +1671,8 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
//Reset state
canvas_item->_edit_set_state(se->undo_state);
- bool uniform = m->get_shift();
- bool symmetric = m->get_alt();
+ bool uniform = m->is_shift_pressed();
+ bool symmetric = m->is_alt_pressed();
Rect2 local_rect = canvas_item->_edit_get_rect();
float aspect = local_rect.get_size().y / local_rect.get_size().x;
@@ -2028,7 +1811,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
// Drag resize handles
if (drag_type == DRAG_NONE) {
- if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && ((b->is_alt_pressed() && b->is_ctrl_pressed()) || tool == TOOL_SCALE)) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (selection.size() == 1) {
CanvasItem *canvas_item = selection[0];
@@ -2074,8 +1857,8 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
Transform2D unscaled_transform = (transform * parent_xform * canvas_item->_edit_get_transform()).orthonormalized();
Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform;
- bool uniform = m->get_shift();
- bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool uniform = m->is_shift_pressed();
+ bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL);
Point2 drag_from_local = simple_xform.xform(drag_from);
Point2 drag_to_local = simple_xform.xform(drag_to);
@@ -2167,7 +1950,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
if (drag_type == DRAG_NONE) {
//Start moving the nodes
if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) {
- if ((b->get_alt() && !b->get_control()) || tool == TOOL_MOVE) {
+ if ((b->is_alt_pressed() && !b->is_ctrl_pressed()) || tool == TOOL_MOVE) {
List<CanvasItem *> selection = _get_edited_canvas_items();
drag_selection.clear();
@@ -2208,14 +1991,6 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
if (drag_type == DRAG_MOVE || drag_type == DRAG_MOVE_X || drag_type == DRAG_MOVE_Y) {
// Move the nodes
if (m.is_valid()) {
- // Save the ik chain for reapplying before IK solve
- Vector<List<Dictionary>> all_bones_ik_states;
- for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
- List<Dictionary> bones_ik_states;
- _save_canvas_item_ik_chain(E->get(), nullptr, &bones_ik_states);
- all_bones_ik_states.push_back(bones_ik_states);
- }
-
_restore_canvas_item_state(drag_selection, true);
drag_to = transform.affine_inverse().xform(m->get_position());
@@ -2235,7 +2010,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
new_pos.x = previous_pos.x;
}
- bool single_axis = m->get_shift();
+ bool single_axis = m->is_shift_pressed();
if (single_axis) {
if (ABS(new_pos.x - previous_pos.x) > ABS(new_pos.y - previous_pos.y)) {
new_pos.y = previous_pos.y;
@@ -2244,25 +2019,12 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
}
}
- bool force_no_IK = m->get_alt();
int index = 0;
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
- CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (se) {
- Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
-
- Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
- if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) {
- real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
- _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
- real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
- node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
- _solve_IK(node2d, new_pos);
- } else {
- canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
- }
- }
+ Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
+
+ canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
index++;
}
return true;
@@ -2325,18 +2087,10 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
}
if (drag_selection.size() > 0) {
- // Save the ik chain for reapplying before IK solve
- Vector<List<Dictionary>> all_bones_ik_states;
- for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
- List<Dictionary> bones_ik_states;
- _save_canvas_item_ik_chain(E->get(), nullptr, &bones_ik_states);
- all_bones_ik_states.push_back(bones_ik_states);
- }
-
_restore_canvas_item_state(drag_selection, true);
- bool move_local_base = k->get_alt();
- bool move_local_base_rotated = k->get_control() || k->get_metakey();
+ bool move_local_base = k->is_alt_pressed();
+ bool move_local_base_rotated = k->is_ctrl_pressed() || k->is_meta_pressed();
Vector2 dir;
if (k->get_keycode() == KEY_UP) {
@@ -2348,12 +2102,12 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
} else if (k->get_keycode() == KEY_RIGHT) {
dir += Vector2(1, 0);
}
- if (k->get_shift()) {
+ if (k->is_shift_pressed()) {
dir *= grid_step * Math::pow(2.0, grid_step_multiplier);
}
drag_to += dir;
- if (k->get_shift()) {
+ if (k->is_shift_pressed()) {
drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier));
}
@@ -2384,21 +2138,9 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
int index = 0;
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
- CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (se) {
- Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
-
- Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
- if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
- real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
- _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
- real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
- node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
- _solve_IK(node2d, new_pos);
- } else {
- canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
- }
- }
+ Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
+
+ canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
index++;
}
}
@@ -2442,18 +2184,18 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
if (drag_type == DRAG_NONE) {
if (b.is_valid() &&
- ((b->get_button_index() == MOUSE_BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) ||
+ ((b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_alt_pressed() && tool == TOOL_SELECT) ||
(b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_LIST_SELECT))) {
// Popup the selection menu list
Point2 click = transform.affine_inverse().xform(b->get_position());
- _get_canvas_items_at_pos(click, selection_results, b->get_alt() && tool != TOOL_LIST_SELECT);
+ _get_canvas_items_at_pos(click, selection_results, b->is_alt_pressed() && tool != TOOL_LIST_SELECT);
if (selection_results.size() == 1) {
CanvasItem *item = selection_results[0].item;
selection_results.clear();
- _select_click_on_item(item, click, b->get_shift());
+ _select_click_on_item(item, click, b->is_shift_pressed());
return true;
} else if (!selection_results.is_empty()) {
@@ -2497,14 +2239,14 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path);
}
- selection_menu_additive_selection = b->get_shift();
+ selection_menu_additive_selection = b->is_shift_pressed();
selection_menu->set_position(get_screen_transform().xform(b->get_position()));
selection_menu->popup();
return true;
}
}
- if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->get_control()) {
+ if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_ctrl_pressed()) {
add_node_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
add_node_menu->set_size(Vector2(1, 1));
add_node_menu->popup();
@@ -2524,23 +2266,17 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
// Find the item to select
CanvasItem *canvas_item = nullptr;
- // Retrieve the bones
Vector<_SelectResult> selection = Vector<_SelectResult>();
- _get_bones_at_pos(click, selection);
+ // Retrieve the canvas items
+ selection = Vector<_SelectResult>();
+ _get_canvas_items_at_pos(click, selection);
if (!selection.is_empty()) {
canvas_item = selection[0].item;
- } else {
- // Retrieve the canvas items
- selection = Vector<_SelectResult>();
- _get_canvas_items_at_pos(click, selection);
- if (!selection.is_empty()) {
- canvas_item = selection[0].item;
- }
}
if (!canvas_item) {
// Start a box selection
- if (!b->get_shift()) {
+ if (!b->is_shift_pressed()) {
// Clear the selection if not additive
editor_selection->clear();
viewport->update();
@@ -2552,26 +2288,42 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
box_selecting_to = drag_from;
return true;
} else {
- bool still_selected = _select_click_on_item(canvas_item, click, b->get_shift());
+ bool still_selected = _select_click_on_item(canvas_item, click, b->is_shift_pressed());
// Start dragging
if (still_selected) {
// Drag the node(s) if requested
- List<CanvasItem *> selection2 = _get_edited_canvas_items();
+ drag_start_origin = click;
+ drag_type = DRAG_QUEUED;
+ }
+ // Select the item
+ return true;
+ }
+ }
+ }
- drag_selection.clear();
- for (int i = 0; i < selection2.size(); i++) {
- if (_is_node_movable(selection2[i], true)) {
- drag_selection.push_back(selection2[i]);
- }
- }
+ if (drag_type == DRAG_QUEUED) {
+ if (b.is_valid() && !b->is_pressed()) {
+ drag_type = DRAG_NONE;
+ return true;
+ }
+ if (m.is_valid()) {
+ Point2 click = transform.affine_inverse().xform(m->get_position());
+ bool movement_threshold_passed = drag_start_origin.distance_to(click) > 10 * EDSCALE;
+ if (m.is_valid() && movement_threshold_passed) {
+ List<CanvasItem *> selection2 = _get_edited_canvas_items();
- if (selection2.size() > 0) {
- drag_type = DRAG_MOVE;
- drag_from = click;
- _save_canvas_item_state(drag_selection);
+ drag_selection.clear();
+ for (int i = 0; i < selection2.size(); i++) {
+ if (_is_node_movable(selection2[i], true)) {
+ drag_selection.push_back(selection2[i]);
}
}
- // Select the item
+
+ if (selection2.size() > 0) {
+ drag_type = DRAG_MOVE;
+ drag_from = click;
+ _save_canvas_item_state(drag_selection);
+ }
return true;
}
}
@@ -3574,7 +3326,7 @@ void CanvasItemEditor::_draw_selection() {
}
// Draw the move handles
- bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL);
bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
if (tool == TOOL_MOVE && show_transformation_gizmos) {
if (_is_node_movable(canvas_item)) {
@@ -3734,65 +3486,6 @@ void CanvasItemEditor::_draw_axis() {
}
}
-void CanvasItemEditor::_draw_bones() {
- RID ci = viewport->get_canvas_item();
-
- if (skeleton_show_bones) {
- Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1");
- Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2");
- Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
- Color bone_outline_color = EditorSettings::get_singleton()->get("editors/2d/bone_outline_color");
- Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
-
- for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
- Vector<Vector2> bone_shape;
- Vector<Vector2> bone_shape_outline;
- if (!_get_bone_shape(&bone_shape, &bone_shape_outline, E)) {
- continue;
- }
-
- Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
- if (!from_node->is_visible_in_tree()) {
- continue;
- }
-
- Vector<Color> colors;
- if (from_node->has_meta("_edit_ik_")) {
- colors.push_back(bone_ik_color);
- colors.push_back(bone_ik_color);
- colors.push_back(bone_ik_color);
- colors.push_back(bone_ik_color);
- } else {
- colors.push_back(bone_color1);
- colors.push_back(bone_color2);
- colors.push_back(bone_color1);
- colors.push_back(bone_color2);
- }
-
- Vector<Color> outline_colors;
-
- if (editor_selection->is_selected(from_node)) {
- outline_colors.push_back(bone_selected_color);
- outline_colors.push_back(bone_selected_color);
- outline_colors.push_back(bone_selected_color);
- outline_colors.push_back(bone_selected_color);
- outline_colors.push_back(bone_selected_color);
- outline_colors.push_back(bone_selected_color);
- } else {
- outline_colors.push_back(bone_outline_color);
- outline_colors.push_back(bone_outline_color);
- outline_colors.push_back(bone_outline_color);
- outline_colors.push_back(bone_outline_color);
- outline_colors.push_back(bone_outline_color);
- outline_colors.push_back(bone_outline_color);
- }
-
- RenderingServer::get_singleton()->canvas_item_add_polygon(ci, bone_shape_outline, outline_colors);
- RenderingServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector<Vector2>(), RID());
- }
- }
-}
-
void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
ERR_FAIL_COND(!p_node);
@@ -3908,72 +3601,6 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p
}
}
-bool CanvasItemEditor::_build_bones_list(Node *p_node) {
- ERR_FAIL_COND_V(!p_node, false);
-
- bool has_child_bones = false;
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- if (_build_bones_list(p_node->get_child(i))) {
- has_child_bones = true;
- }
- }
-
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
- Node *scene = editor->get_edited_scene();
- if (!canvas_item || !canvas_item->is_visible() || (canvas_item != scene && canvas_item->get_owner() != scene && canvas_item != scene->get_deepest_editable_node(canvas_item))) {
- return false;
- }
-
- Node *parent = canvas_item->get_parent();
-
- if (Object::cast_to<Bone2D>(canvas_item)) {
- if (Object::cast_to<Bone2D>(parent)) {
- // Add as bone->parent relationship
- BoneKey bk;
- bk.from = parent->get_instance_id();
- bk.to = canvas_item->get_instance_id();
- if (!bone_list.has(bk)) {
- BoneList b;
- b.length = 0;
- bone_list[bk] = b;
- }
-
- bone_list[bk].last_pass = bone_last_frame;
- }
-
- if (!has_child_bones) {
- // Add a last bone if the Bone2D has no Bone2D child
- BoneKey bk;
- bk.from = canvas_item->get_instance_id();
- bk.to = ObjectID();
- if (!bone_list.has(bk)) {
- BoneList b;
- b.length = 0;
- bone_list[bk] = b;
- }
- bone_list[bk].last_pass = bone_last_frame;
- }
-
- return true;
- }
-
- if (canvas_item->has_meta("_edit_bone_")) {
- // Add a "custom bone"
- BoneKey bk;
- bk.from = parent->get_instance_id();
- bk.to = canvas_item->get_instance_id();
- if (!bone_list.has(bk)) {
- BoneList b;
- b.length = 0;
- bone_list[bk] = b;
- }
- bone_list[bk].last_pass = bone_last_frame;
- }
-
- return false;
-}
-
void CanvasItemEditor::_draw_viewport() {
// Update the transform
transform = Transform2D();
@@ -4033,7 +3660,6 @@ void CanvasItemEditor::_draw_viewport() {
force_over_plugin_list->forward_canvas_force_draw_over_viewport(viewport);
}
- _draw_bones();
if (show_rulers) {
_draw_rulers();
}
@@ -4159,8 +3785,8 @@ void CanvasItemEditor::_notification(int p_what) {
}
Bone2D *bone = Object::cast_to<Bone2D>(b);
- if (bone && bone->get_default_length() != E->get().length) {
- E->get().length = bone->get_default_length();
+ if (bone && bone->get_length() != E->get().length) {
+ E->get().length = bone->get_length();
viewport->update();
}
}
@@ -4175,18 +3801,11 @@ void CanvasItemEditor::_notification(int p_what) {
AnimationPlayerEditor::singleton->get_track_editor()->connect("visibility_changed", callable_mp(this, &CanvasItemEditor::_keying_changed));
_keying_changed();
- get_tree()->connect("node_added", callable_mp(this, &CanvasItemEditor::_tree_changed), varray());
- get_tree()->connect("node_removed", callable_mp(this, &CanvasItemEditor::_tree_changed), varray());
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
select_sb->set_texture(get_theme_icon("EditorRect2D", "EditorIcons"));
}
- if (p_what == NOTIFICATION_EXIT_TREE) {
- get_tree()->disconnect("node_added", callable_mp(this, &CanvasItemEditor::_tree_changed));
- get_tree()->disconnect("node_removed", callable_mp(this, &CanvasItemEditor::_tree_changed));
- }
-
if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
select_button->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
list_select_button->set_icon(get_theme_icon("ListSelect", "EditorIcons"));
@@ -4321,46 +3940,6 @@ void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
}
}
-void CanvasItemEditor::_queue_update_bone_list() {
- if (bone_list_dirty) {
- return;
- }
-
- call_deferred("_update_bone_list");
- bone_list_dirty = true;
-}
-
-void CanvasItemEditor::_update_bone_list() {
- bone_last_frame++;
-
- if (editor->get_edited_scene()) {
- _build_bones_list(editor->get_edited_scene());
- }
-
- List<Map<BoneKey, BoneList>::Element *> bone_to_erase;
- for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
- if (E->get().last_pass != bone_last_frame) {
- bone_to_erase.push_back(E);
- continue;
- }
-
- Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E->key().from));
- if (!node || !node->is_inside_tree() || (node != get_tree()->get_edited_scene_root() && !get_tree()->get_edited_scene_root()->is_a_parent_of(node))) {
- bone_to_erase.push_back(E);
- continue;
- }
- }
- while (bone_to_erase.size()) {
- bone_list.erase(bone_to_erase.front()->get());
- bone_to_erase.pop_front();
- }
- bone_list_dirty = false;
-}
-
-void CanvasItemEditor::_tree_changed(Node *) {
- _queue_update_bone_list();
-}
-
void CanvasItemEditor::_update_scrollbars() {
updating_scroll = true;
@@ -4376,11 +3955,9 @@ void CanvasItemEditor::_update_scrollbars() {
Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height));
- _queue_update_bone_list();
-
// Calculate scrollable area.
Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
- if (editor->get_edited_scene()) {
+ if (editor->is_inside_tree() && editor->get_edited_scene()) {
Rect2 content_rect = _get_encompassing_rect(editor->get_edited_scene());
canvas_item_rect.expand_to(content_rect.position);
canvas_item_rect.expand_to(content_rect.position + content_rect.size);
@@ -4837,10 +4414,19 @@ void CanvasItemEditor::_popup_callback(int p_op) {
snap_dialog->popup_centered(Size2(220, 160) * EDSCALE);
} break;
case SKELETON_SHOW_BONES: {
- skeleton_show_bones = !skeleton_show_bones;
- int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
- skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
- viewport->update();
+ List<Node *> selection = editor_selection->get_selected_node_list();
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ // Add children nodes so they are processed
+ for (int child = 0; child < E->get()->get_child_count(); child++) {
+ selection.push_back(E->get()->get_child(child));
+ }
+
+ Bone2D *bone_2d = Object::cast_to<Bone2D>(E->get());
+ if (!bone_2d || !bone_2d->is_inside_tree()) {
+ continue;
+ }
+ bone_2d->_editor_set_show_bone_gizmo(!bone_2d->_editor_get_show_bone_gizmo());
+ }
} break;
case SHOW_HELPERS: {
show_helpers = !show_helpers;
@@ -5189,107 +4775,45 @@ void CanvasItemEditor::_popup_callback(int p_op) {
} break;
case SKELETON_MAKE_BONES: {
Map<Node *, Object *> &selection = editor_selection->get_selection();
+ Node *editor_root = EditorNode::get_singleton()->get_edited_scene()->get_tree()->get_edited_scene_root();
- undo_redo->create_action(TTR("Create Custom Bone(s) from Node(s)"));
+ undo_redo->create_action(TTR("Create Custom Bone2D(s) from Node(s)"));
for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
Node2D *n2d = Object::cast_to<Node2D>(E->key());
- if (!n2d) {
- continue;
- }
- if (!n2d->is_visible_in_tree()) {
- continue;
- }
- if (!n2d->get_parent_item()) {
- continue;
- }
- if (n2d->has_meta("_edit_bone_") && n2d->get_meta("_edit_bone_")) {
- continue;
- }
-
- undo_redo->add_do_method(n2d, "set_meta", "_edit_bone_", true);
- undo_redo->add_undo_method(n2d, "remove_meta", "_edit_bone_");
- }
- undo_redo->add_do_method(this, "_queue_update_bone_list");
- undo_redo->add_undo_method(this, "_queue_update_bone_list");
- undo_redo->add_do_method(viewport, "update");
- undo_redo->add_undo_method(viewport, "update");
- undo_redo->commit_action();
- } break;
- case SKELETON_CLEAR_BONES: {
- Map<Node *, Object *> &selection = editor_selection->get_selection();
+ Bone2D *new_bone = memnew(Bone2D);
+ String new_bone_name = n2d->get_name();
+ new_bone_name += "Bone2D";
+ new_bone->set_name(new_bone_name);
+ new_bone->set_transform(n2d->get_transform());
- undo_redo->create_action(TTR("Clear Bones"));
- for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
- Node2D *n2d = Object::cast_to<Node2D>(E->key());
- if (!n2d) {
- continue;
- }
- if (!n2d->is_visible_in_tree()) {
- continue;
- }
- if (!n2d->has_meta("_edit_bone_")) {
+ Node *n2d_parent = n2d->get_parent();
+ if (!n2d_parent) {
continue;
}
- undo_redo->add_do_method(n2d, "remove_meta", "_edit_bone_");
- undo_redo->add_undo_method(n2d, "set_meta", "_edit_bone_", n2d->get_meta("_edit_bone_"));
- }
- undo_redo->add_do_method(this, "_queue_update_bone_list");
- undo_redo->add_undo_method(this, "_queue_update_bone_list");
- undo_redo->add_do_method(viewport, "update");
- undo_redo->add_undo_method(viewport, "update");
- undo_redo->commit_action();
-
- } break;
- case SKELETON_SET_IK_CHAIN: {
- List<Node *> selection = editor_selection->get_selected_node_list();
+ undo_redo->add_do_method(n2d_parent, "add_child", new_bone);
+ undo_redo->add_do_method(n2d_parent, "remove_child", n2d);
+ undo_redo->add_do_method(new_bone, "add_child", n2d);
+ undo_redo->add_do_method(n2d, "set_transform", Transform2D());
+ undo_redo->add_do_method(this, "_set_owner_for_node_and_children", new_bone, editor_root);
- undo_redo->create_action(TTR("Make IK Chain"));
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
- if (!canvas_item || !canvas_item->is_visible_in_tree()) {
- continue;
- }
- if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
- continue;
- }
- if (canvas_item->has_meta("_edit_ik_") && canvas_item->get_meta("_edit_ik_")) {
- continue;
- }
-
- undo_redo->add_do_method(canvas_item, "set_meta", "_edit_ik_", true);
- undo_redo->add_undo_method(canvas_item, "remove_meta", "_edit_ik_");
+ undo_redo->add_undo_method(new_bone, "remove_child", n2d);
+ undo_redo->add_undo_method(n2d_parent, "add_child", n2d);
+ undo_redo->add_undo_method(n2d, "set_transform", new_bone->get_transform());
+ undo_redo->add_undo_method(new_bone, "queue_free");
+ undo_redo->add_undo_method(this, "_set_owner_for_node_and_children", n2d, editor_root);
}
- undo_redo->add_do_method(viewport, "update");
- undo_redo->add_undo_method(viewport, "update");
undo_redo->commit_action();
} break;
- case SKELETON_CLEAR_IK_CHAIN: {
- Map<Node *, Object *> &selection = editor_selection->get_selection();
-
- undo_redo->create_action(TTR("Clear IK Chain"));
- for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *n2d = Object::cast_to<CanvasItem>(E->key());
- if (!n2d) {
- continue;
- }
- if (!n2d->is_visible_in_tree()) {
- continue;
- }
- if (!n2d->has_meta("_edit_ik_")) {
- continue;
- }
-
- undo_redo->add_do_method(n2d, "remove_meta", "_edit_ik_");
- undo_redo->add_undo_method(n2d, "set_meta", "_edit_ik_", n2d->get_meta("_edit_ik_"));
- }
- undo_redo->add_do_method(viewport, "update");
- undo_redo->add_undo_method(viewport, "update");
- undo_redo->commit_action();
+ }
+}
- } break;
+void CanvasItemEditor::_set_owner_for_node_and_children(Node *p_node, Node *p_owner) {
+ p_node->set_owner(p_owner);
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _set_owner_for_node_and_children(p_node->get_child(i), p_owner);
}
}
@@ -5358,11 +4882,11 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button);
ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data);
ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input);
- ClassDB::bind_method("_queue_update_bone_list", &CanvasItemEditor::_update_bone_list);
- ClassDB::bind_method("_update_bone_list", &CanvasItemEditor::_update_bone_list);
- ClassDB::bind_method("_reset_create_position", &CanvasItemEditor::_reset_create_position);
ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state);
ClassDB::bind_method(D_METHOD("update_viewport"), &CanvasItemEditor::update_viewport);
+ ClassDB::bind_method(D_METHOD("_zoom_on_position"), &CanvasItemEditor::_zoom_on_position);
+
+ ClassDB::bind_method("_set_owner_for_node_and_children", &CanvasItemEditor::_set_owner_for_node_and_children);
ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
ADD_SIGNAL(MethodInfo("item_group_status_changed"));
@@ -5400,7 +4924,6 @@ Dictionary CanvasItemEditor::get_state() const {
state["snap_scale"] = snap_scale;
state["snap_relative"] = snap_relative;
state["snap_pixel"] = snap_pixel;
- state["skeleton_show_bones"] = skeleton_show_bones;
return state;
}
@@ -5568,12 +5091,6 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel);
}
- if (state.has("skeleton_show_bones")) {
- skeleton_show_bones = state["skeleton_show_bones"];
- int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
- skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
- }
-
if (update_scrollbars) {
_update_scrollbars();
}
@@ -5656,8 +5173,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
selected_from_canvas = false;
anchors_mode = false;
- skeleton_show_bones = true;
-
drag_type = DRAG_NONE;
drag_from = Vector2();
drag_to = Vector2();
@@ -5673,7 +5188,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
bone_last_frame = 0;
- bone_list_dirty = false;
tool = TOOL_SELECT;
undo_redo = p_editor->get_undo_redo();
editor = p_editor;
@@ -5938,13 +5452,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p = skeleton_menu->get_popup();
p->set_hide_on_checkable_item_selection(false);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Custom Bone(s) from Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Custom Bones")), SKELETON_CLEAR_BONES);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bone2D Node(s) from Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
p->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback));
hb->add_child(memnew(VSeparator));
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 21ef3f88df..7b64d0cb5d 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -187,10 +187,7 @@ private:
VIEW_FRAME_TO_SELECTION,
PREVIEW_CANVAS_SCALE,
SKELETON_MAKE_BONES,
- SKELETON_CLEAR_BONES,
- SKELETON_SHOW_BONES,
- SKELETON_SET_IK_CHAIN,
- SKELETON_CLEAR_IK_CHAIN
+ SKELETON_SHOW_BONES
};
enum DragType {
@@ -209,6 +206,7 @@ private:
DRAG_ANCHOR_BOTTOM_RIGHT,
DRAG_ANCHOR_BOTTOM_LEFT,
DRAG_ANCHOR_ALL,
+ DRAG_QUEUED,
DRAG_MOVE,
DRAG_MOVE_X,
DRAG_MOVE_Y,
@@ -223,7 +221,6 @@ private:
DRAG_KEY_MOVE
};
- EditorSelection *editor_selection;
bool selection_menu_additive_selection;
Tool tool;
@@ -277,7 +274,6 @@ private:
bool snap_scale;
bool snap_relative;
bool snap_pixel;
- bool skeleton_show_bones;
bool key_pos;
bool key_rot;
bool key_scale;
@@ -384,6 +380,7 @@ private:
Control *top_ruler;
Control *left_ruler;
+ Point2 drag_start_origin;
DragType drag_type;
Point2 drag_from;
Point2 drag_to;
@@ -412,7 +409,6 @@ private:
bool _is_node_movable(const Node *p_node, bool p_popup_warning = false);
void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
void _get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items, bool p_allow_locked = false);
- void _get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items);
void _find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append);
@@ -423,9 +419,7 @@ private:
void _add_canvas_item(CanvasItem *p_canvas_item);
- void _save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state);
void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false);
- void _restore_canvas_item_ik_chain(CanvasItem *p_canvas_item, const List<Dictionary> *p_bones_state);
void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false);
void _commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones = false);
@@ -445,8 +439,6 @@ private:
void _reset_create_position();
UndoRedo *undo_redo;
- bool _build_bones_list(Node *p_node);
- bool _get_bone_shape(Vector<Vector2> *shape, Vector<Vector2> *outline_shape, Map<BoneKey, BoneList>::Element *bone);
List<CanvasItem *> _get_edited_canvas_items(bool retreive_locked = false, bool remove_canvas_item_if_parent_in_selection = true);
Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list);
@@ -476,7 +468,6 @@ private:
void _draw_control_helpers(Control *control);
void _draw_selection();
void _draw_axis();
- void _draw_bones();
void _draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
void _draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
void _draw_hover();
@@ -503,8 +494,6 @@ private:
void _focus_selection(int p_op);
- void _solve_IK(Node2D *leaf_node, Point2 target_position);
-
SnapTarget snap_target[2];
Transform2D snap_transform;
void _snap_if_closer_float(
@@ -546,14 +535,11 @@ private:
HSplitContainer *palette_split;
VSplitContainer *bottom_split;
- bool bone_list_dirty;
- void _queue_update_bone_list();
- void _update_bone_list();
- void _tree_changed(Node *);
-
void _popup_warning_temporarily(Control *p_control, const float p_duration);
void _popup_warning_depop(Control *p_control);
+ void _set_owner_for_node_and_children(Node *p_node, Node *p_owner);
+
friend class CanvasItemEditorPlugin;
protected:
@@ -641,6 +627,8 @@ public:
bool is_anchors_mode_enabled() { return anchors_mode; };
+ EditorSelection *editor_selection;
+
CanvasItemEditor(EditorNode *p_editor);
};
diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp
index b50a497ccf..a0df7e289e 100644
--- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp
@@ -32,8 +32,8 @@
#include "canvas_item_editor_plugin.h"
#include "core/input/input.h"
+#include "core/io/file_access.h"
#include "core/math/geometry_2d.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "editor/editor_settings.h"
#include "node_3d_editor_plugin.h"
@@ -108,8 +108,8 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con
return false;
}
- Transform gt = node->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = node->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
float depth = _get_depth() * 0.5;
Vector3 n = gt.basis.get_axis(2).normalized();
Plane p(gt.origin + n * depth, n);
@@ -175,7 +175,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con
case MODE_EDIT: {
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
- if (mb->get_control()) {
+ if (mb->is_ctrl_pressed()) {
if (poly.size() < 3) {
undo_redo->create_action(TTR("Edit Poly"));
undo_redo->add_undo_method(node, "set_polygon", poly);
@@ -317,7 +317,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con
Vector2 cpoint(spoint.x, spoint.y);
- if (snap_ignore && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (snap_ignore && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
snap_ignore = false;
}
@@ -516,7 +516,7 @@ CollisionPolygon3DEditor::CollisionPolygon3DEditor(EditorNode *p_editor) {
mode = MODE_EDIT;
wip_active = false;
imgeom = memnew(ImmediateGeometry3D);
- imgeom->set_transform(Transform(Basis(), Vector3(0, 0, 0.00001)));
+ imgeom->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
@@ -539,7 +539,7 @@ CollisionPolygon3DEditor::CollisionPolygon3DEditor(EditorNode *p_editor) {
imgeom->add_child(pointsm);
m.instance();
pointsm->set_mesh(m);
- pointsm->set_transform(Transform(Basis(), Vector3(0, 0, 0.00001)));
+ pointsm->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
snap_ignore = false;
}
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index db999f50ab..7a38fd2bd5 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -168,8 +168,8 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) {
// Snap to "round" coordinates when holding Ctrl.
// Be more precise when holding Shift as well.
float snap_threshold;
- if (mm.get_control()) {
- snap_threshold = mm.get_shift() ? 0.025 : 0.1;
+ if (mm.is_ctrl_pressed()) {
+ snap_threshold = mm.is_shift_pressed() ? 0.025 : 0.1;
} else {
snap_threshold = 0.0;
}
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 18cc5d43fb..235ccb18cb 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -265,7 +265,7 @@ Ref<Texture2D> EditorPackedScenePreviewPlugin::generate(const RES &p_from, const
}
Ref<Texture2D> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path, const Size2 &p_size) const {
- String temp_path = EditorSettings::get_singleton()->get_cache_dir();
+ String temp_path = EditorPaths::get_singleton()->get_cache_dir();
String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text();
cache_base = temp_path.plus_file("resthumb-" + cache_base);
@@ -359,12 +359,12 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
camera = RS::get_singleton()->camera_create();
RS::get_singleton()->viewport_attach_camera(viewport, camera);
- RS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3)));
+ RS::get_singleton()->camera_set_transform(camera, Transform3D(Basis(), Vector3(0, 0, 3)));
RS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10);
light = RS::get_singleton()->directional_light_create();
light_instance = RS::get_singleton()->instance_create2(light, scenario);
- RS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
+ RS::get_singleton()->instance_set_transform(light_instance, Transform3D().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
light2 = RS::get_singleton()->directional_light_create();
RS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
@@ -372,7 +372,7 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
light_instance2 = RS::get_singleton()->instance_create2(light2, scenario);
- RS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
+ RS::get_singleton()->instance_set_transform(light_instance2, Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
sphere = RS::get_singleton()->mesh_create();
sphere_instance = RS::get_singleton()->instance_create2(sphere, scenario);
@@ -720,7 +720,7 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2
AABB aabb = mesh->get_aabb();
Vector3 ofs = aabb.position + aabb.size * 0.5;
aabb.position -= ofs;
- Transform xform;
+ Transform3D xform;
xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI * 0.125);
xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI * 0.125) * xform.basis;
AABB rot_aabb = xform.xform(aabb);
@@ -780,20 +780,20 @@ EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
camera = RS::get_singleton()->camera_create();
RS::get_singleton()->viewport_attach_camera(viewport, camera);
- RS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3)));
+ RS::get_singleton()->camera_set_transform(camera, Transform3D(Basis(), Vector3(0, 0, 3)));
//RS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
RS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
light = RS::get_singleton()->directional_light_create();
light_instance = RS::get_singleton()->instance_create2(light, scenario);
- RS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
+ RS::get_singleton()->instance_set_transform(light_instance, Transform3D().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
light2 = RS::get_singleton()->directional_light_create();
RS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
//RS::get_singleton()->light_set_color(light2, RS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
light_instance2 = RS::get_singleton()->instance_create2(light2, scenario);
- RS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
+ RS::get_singleton()->instance_set_transform(light_instance2, Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
//sphere = RS::get_singleton()->mesh_create();
mesh_instance = RS::get_singleton()->instance_create();
@@ -832,7 +832,7 @@ struct FSample {
};
static FSample _samples[] = {
- { "hani", U"漢語" },
+ { "hani", U"漢字" },
{ "armn", U"Ô±Õ¢" },
{ "copt", U"Αα" },
{ "cyrl", U"Ðб" },
diff --git a/editor/plugins/font_editor_plugin.cpp b/editor/plugins/font_editor_plugin.cpp
index fa58eb5480..8de7dc2447 100644
--- a/editor/plugins/font_editor_plugin.cpp
+++ b/editor/plugins/font_editor_plugin.cpp
@@ -56,7 +56,7 @@ struct FSample {
};
static FSample _samples[] = {
- { "hani", U"漢語" },
+ { "hani", U"漢字" },
{ "armn", U"Ô±Õ¢" },
{ "copt", U"Αα" },
{ "cyrl", U"Ðб" },
diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp
deleted file mode 100644
index f309c5da01..0000000000
--- a/editor/plugins/gi_probe_editor_plugin.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*************************************************************************/
-/* gi_probe_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "gi_probe_editor_plugin.h"
-
-void GIProbeEditorPlugin::_bake() {
- if (gi_probe) {
- if (gi_probe->get_probe_data().is_null()) {
- String path = get_tree()->get_edited_scene_root()->get_filename();
- if (path == String()) {
- path = "res://" + gi_probe->get_name() + "_data.res";
- } else {
- String ext = path.get_extension();
- path = path.get_basename() + "." + gi_probe->get_name() + "_data.res";
- }
- probe_file->set_current_path(path);
- probe_file->popup_file_dialog();
- return;
- }
- gi_probe->bake();
- }
-}
-
-void GIProbeEditorPlugin::edit(Object *p_object) {
- GIProbe *s = Object::cast_to<GIProbe>(p_object);
- if (!s) {
- return;
- }
-
- gi_probe = s;
-}
-
-bool GIProbeEditorPlugin::handles(Object *p_object) const {
- return p_object->is_class("GIProbe");
-}
-
-void GIProbeEditorPlugin::_notification(int p_what) {
- if (p_what == NOTIFICATION_PROCESS) {
- if (!gi_probe) {
- return;
- }
-
- const Vector3i size = gi_probe->get_estimated_cell_size();
- String text = vformat(String::utf8("%d × %d × %d"), size.x, size.y, size.z);
- int data_size = 4;
- if (GLOBAL_GET("rendering/quality/gi_probes/anisotropic")) {
- data_size += 4;
- }
- const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0);
- text += " - " + vformat(TTR("VRAM Size: %s MB"), String::num(size_mb, 2));
-
- if (bake_info->get_text() == text) {
- return;
- }
-
- // Color the label depending on the estimated performance level.
- Color color;
- if (size_mb <= 16.0 + CMP_EPSILON) {
- // Fast.
- color = bake_info->get_theme_color("success_color", "Editor");
- } else if (size_mb <= 64.0 + CMP_EPSILON) {
- // Medium.
- color = bake_info->get_theme_color("warning_color", "Editor");
- } else {
- // Slow.
- color = bake_info->get_theme_color("error_color", "Editor");
- }
- bake_info->add_theme_color_override("font_color", color);
-
- bake_info->set_text(text);
- }
-}
-
-void GIProbeEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
- bake_hb->show();
- set_process(true);
- } else {
- bake_hb->hide();
- set_process(false);
- }
-}
-
-EditorProgress *GIProbeEditorPlugin::tmp_progress = nullptr;
-
-void GIProbeEditorPlugin::bake_func_begin(int p_steps) {
- ERR_FAIL_COND(tmp_progress != nullptr);
-
- tmp_progress = memnew(EditorProgress("bake_gi", TTR("Bake GI Probe"), p_steps));
-}
-
-void GIProbeEditorPlugin::bake_func_step(int p_step, const String &p_description) {
- ERR_FAIL_COND(tmp_progress == nullptr);
- tmp_progress->step(p_description, p_step, false);
-}
-
-void GIProbeEditorPlugin::bake_func_end() {
- ERR_FAIL_COND(tmp_progress == nullptr);
- memdelete(tmp_progress);
- tmp_progress = nullptr;
-}
-
-void GIProbeEditorPlugin::_giprobe_save_path_and_bake(const String &p_path) {
- probe_file->hide();
- if (gi_probe) {
- gi_probe->bake();
- ERR_FAIL_COND(gi_probe->get_probe_data().is_null());
- ResourceSaver::save(p_path, gi_probe->get_probe_data(), ResourceSaver::FLAG_CHANGE_PATH);
- }
-}
-
-void GIProbeEditorPlugin::_bind_methods() {
-}
-
-GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) {
- editor = p_node;
- bake_hb = memnew(HBoxContainer);
- bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- bake_hb->hide();
- bake = memnew(Button);
- bake->set_flat(true);
- bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
- bake->set_text(TTR("Bake GI Probe"));
- bake->connect("pressed", callable_mp(this, &GIProbeEditorPlugin::_bake));
- bake_hb->add_child(bake);
- bake_info = memnew(Label);
- bake_info->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- bake_info->set_clip_text(true);
- bake_hb->add_child(bake_info);
-
- add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake_hb);
- gi_probe = nullptr;
- probe_file = memnew(EditorFileDialog);
- probe_file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- probe_file->add_filter("*.res");
- probe_file->connect("file_selected", callable_mp(this, &GIProbeEditorPlugin::_giprobe_save_path_and_bake));
- get_editor_interface()->get_base_control()->add_child(probe_file);
- probe_file->set_title(TTR("Select path for GIProbe Data File"));
-
- GIProbe::bake_begin_function = bake_func_begin;
- GIProbe::bake_step_function = bake_func_step;
- GIProbe::bake_end_function = bake_func_end;
-}
-
-GIProbeEditorPlugin::~GIProbeEditorPlugin() {
-}
diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h
deleted file mode 100644
index fdf0623561..0000000000
--- a/editor/plugins/gi_probe_editor_plugin.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*************************************************************************/
-/* gi_probe_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef GIPROBEEDITORPLUGIN_H
-#define GIPROBEEDITORPLUGIN_H
-
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
-#include "scene/3d/gi_probe.h"
-#include "scene/resources/material.h"
-
-class GIProbeEditorPlugin : public EditorPlugin {
- GDCLASS(GIProbeEditorPlugin, EditorPlugin);
-
- GIProbe *gi_probe;
-
- HBoxContainer *bake_hb;
- Label *bake_info;
- Button *bake;
- EditorNode *editor;
-
- EditorFileDialog *probe_file;
-
- static EditorProgress *tmp_progress;
- static void bake_func_begin(int p_steps);
- static void bake_func_step(int p_step, const String &p_description);
- static void bake_func_end();
-
- void _bake();
- void _giprobe_save_path_and_bake(const String &p_path);
-
-protected:
- static void _bind_methods();
- void _notification(int p_what);
-
-public:
- virtual String get_name() const override { return "GIProbe"; }
- bool has_main_screen() const override { return false; }
- virtual void edit(Object *p_object) override;
- virtual bool handles(Object *p_object) const override;
- virtual void make_visible(bool p_visible) override;
-
- GIProbeEditorPlugin(EditorNode *p_node);
- ~GIProbeEditorPlugin();
-};
-
-#endif // GIPROBEEDITORPLUGIN_H
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 89d6aaa5f9..17c7397729 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -177,7 +177,7 @@ void GPUParticles3DEditorBase::_node_selected(const NodePath &p_path) {
return;
}
- Transform geom_xform = base_node->get_global_transform().affine_inverse() * vi->get_global_transform();
+ Transform3D geom_xform = base_node->get_global_transform().affine_inverse() * vi->get_global_transform();
int gc = geometry.size();
Face3 *w = geometry.ptrw();
diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp
new file mode 100644
index 0000000000..484fdabfe1
--- /dev/null
+++ b/editor/plugins/lightmap_gi_editor_plugin.cpp
@@ -0,0 +1,138 @@
+/*************************************************************************/
+/* lightmap_gi_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "lightmap_gi_editor_plugin.h"
+
+void LightmapGIEditorPlugin::_bake_select_file(const String &p_file) {
+ if (lightmap) {
+ LightmapGI::BakeError err;
+ if (get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root() == lightmap) {
+ err = lightmap->bake(lightmap, p_file, bake_func_step);
+ } else {
+ err = lightmap->bake(lightmap->get_parent(), p_file, bake_func_step);
+ }
+
+ bake_func_end();
+
+ switch (err) {
+ case LightmapGI::BAKE_ERROR_NO_SAVE_PATH: {
+ String scene_path = lightmap->get_filename();
+ if (scene_path == String()) {
+ scene_path = lightmap->get_owner()->get_filename();
+ }
+ if (scene_path == String()) {
+ EditorNode::get_singleton()->show_warning(TTR("Can't determine a save path for lightmap images.\nSave your scene and try again."));
+ break;
+ }
+ scene_path = scene_path.get_basename() + ".lmbake";
+
+ file_dialog->set_current_path(scene_path);
+ file_dialog->popup_file_dialog();
+
+ } break;
+ case LightmapGI::BAKE_ERROR_NO_MESHES:
+ EditorNode::get_singleton()->show_warning(TTR("No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake Light' flag is on."));
+ break;
+ case LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE:
+ EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable."));
+ break;
+ default: {
+ }
+ }
+ }
+}
+
+void LightmapGIEditorPlugin::_bake() {
+ _bake_select_file("");
+}
+
+void LightmapGIEditorPlugin::edit(Object *p_object) {
+ LightmapGI *s = Object::cast_to<LightmapGI>(p_object);
+ if (!s) {
+ return;
+ }
+
+ lightmap = s;
+}
+
+bool LightmapGIEditorPlugin::handles(Object *p_object) const {
+ return p_object->is_class("LightmapGI");
+}
+
+void LightmapGIEditorPlugin::make_visible(bool p_visible) {
+ if (p_visible) {
+ bake->show();
+ } else {
+ bake->hide();
+ }
+}
+
+EditorProgress *LightmapGIEditorPlugin::tmp_progress = nullptr;
+
+bool LightmapGIEditorPlugin::bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh) {
+ if (!tmp_progress) {
+ tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, false));
+ ERR_FAIL_COND_V(tmp_progress == nullptr, false);
+ }
+ return tmp_progress->step(p_description, p_progress * 1000, p_refresh);
+}
+
+void LightmapGIEditorPlugin::bake_func_end() {
+ if (tmp_progress != nullptr) {
+ memdelete(tmp_progress);
+ tmp_progress = nullptr;
+ }
+}
+
+void LightmapGIEditorPlugin::_bind_methods() {
+ ClassDB::bind_method("_bake", &LightmapGIEditorPlugin::_bake);
+}
+
+LightmapGIEditorPlugin::LightmapGIEditorPlugin(EditorNode *p_node) {
+ editor = p_node;
+ bake = memnew(Button);
+ bake->set_flat(true);
+ bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
+ bake->set_text(TTR("Bake Lightmaps"));
+ bake->hide();
+ bake->connect("pressed", Callable(this, "_bake"));
+ add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake);
+ lightmap = nullptr;
+
+ file_dialog = memnew(EditorFileDialog);
+ file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ file_dialog->add_filter("*.lmbake ; LightMap Bake");
+ file_dialog->set_title(TTR("Select lightmap bake file:"));
+ file_dialog->connect("file_selected", callable_mp(this, &LightmapGIEditorPlugin::_bake_select_file));
+ bake->add_child(file_dialog);
+}
+
+LightmapGIEditorPlugin::~LightmapGIEditorPlugin() {
+}
diff --git a/editor/plugins/lightmap_gi_editor_plugin.h b/editor/plugins/lightmap_gi_editor_plugin.h
new file mode 100644
index 0000000000..12d080d6be
--- /dev/null
+++ b/editor/plugins/lightmap_gi_editor_plugin.h
@@ -0,0 +1,69 @@
+/*************************************************************************/
+/* lightmap_gi_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BAKED_LIGHTMAP_EDITOR_PLUGIN_H
+#define BAKED_LIGHTMAP_EDITOR_PLUGIN_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "scene/3d/lightmap_gi.h"
+#include "scene/resources/material.h"
+
+class LightmapGIEditorPlugin : public EditorPlugin {
+ GDCLASS(LightmapGIEditorPlugin, EditorPlugin);
+
+ LightmapGI *lightmap;
+
+ Button *bake;
+ EditorNode *editor;
+
+ EditorFileDialog *file_dialog;
+ static EditorProgress *tmp_progress;
+ static bool bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh);
+ static void bake_func_end();
+
+ void _bake_select_file(const String &p_file);
+ void _bake();
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_name() const override { return "LightmapGI"; }
+ bool has_main_screen() const override { return false; }
+ virtual void edit(Object *p_object) override;
+ virtual bool handles(Object *p_object) const override;
+ virtual void make_visible(bool p_visible) override;
+
+ LightmapGIEditorPlugin(EditorNode *p_node);
+ ~LightmapGIEditorPlugin();
+};
+
+#endif
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index ad99ad7808..81f0ecacf2 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -119,17 +119,17 @@ MaterialEditor::MaterialEditor() {
viewport->set_msaa(Viewport::MSAA_4X);
camera = memnew(Camera3D);
- camera->set_transform(Transform(Basis(), Vector3(0, 0, 3)));
+ camera->set_transform(Transform3D(Basis(), Vector3(0, 0, 3)));
camera->set_perspective(45, 0.1, 10);
camera->make_current();
viewport->add_child(camera);
light1 = memnew(DirectionalLight3D);
- light1->set_transform(Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
+ light1->set_transform(Transform3D().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
viewport->add_child(light1);
light2 = memnew(DirectionalLight3D);
- light2->set_transform(Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
+ light2->set_transform(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
light2->set_color(Color(0.7, 0.7, 0.7));
viewport->add_child(light2);
@@ -139,7 +139,7 @@ MaterialEditor::MaterialEditor() {
box_instance = memnew(MeshInstance3D);
viewport->add_child(box_instance);
- Transform box_xform;
+ Transform3D box_xform;
box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg2rad(25.0));
box_xform.basis = box_xform.basis * Basis().rotated(Vector3(0, 1, 0), Math::deg2rad(-25.0));
box_xform.basis.scale(Vector3(0.8, 0.8, 0.8));
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index 9d29c31522..8d488dce20 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -65,7 +65,7 @@ void MeshEditor::_notification(int p_what) {
}
void MeshEditor::_update_rotation() {
- Transform t;
+ Transform3D t;
t.basis.rotate(Vector3(0, 1, 0), -rot_y);
t.basis.rotate(Vector3(1, 0, 0), -rot_x);
rotation->set_transform(t);
@@ -85,7 +85,7 @@ void MeshEditor::edit(Ref<Mesh> p_mesh) {
if (m != 0) {
m = 1.0 / m;
m *= 0.5;
- Transform xform;
+ Transform3D xform;
xform.basis.scale(Vector3(m, m, m));
xform.origin = -xform.basis.xform(ofs); //-ofs*m;
//xform.origin.z -= aabb.get_longest_axis_size() * 2;
@@ -117,16 +117,16 @@ MeshEditor::MeshEditor() {
viewport->set_msaa(Viewport::MSAA_2X);
set_stretch(true);
camera = memnew(Camera3D);
- camera->set_transform(Transform(Basis(), Vector3(0, 0, 1.1)));
+ camera->set_transform(Transform3D(Basis(), Vector3(0, 0, 1.1)));
camera->set_perspective(45, 0.1, 10);
viewport->add_child(camera);
light1 = memnew(DirectionalLight3D);
- light1->set_transform(Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
+ light1->set_transform(Transform3D().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
viewport->add_child(light1);
light2 = memnew(DirectionalLight3D);
- light2->set_transform(Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
+ light2->set_transform(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
light2->set_color(Color(0.7, 0.7, 0.7));
viewport->add_child(light2);
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 6f1f243444..e64992759d 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -127,7 +127,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
continue;
}
- //Transform shape_transform = sb->shape_owner_get_transform(E->get());
+ //Transform3D shape_transform = sb->shape_owner_get_transform(E->get());
//shape_transform.set_origin(shape_transform.get_origin() - phys_offset);
@@ -147,7 +147,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
p_library->set_item_shapes(id, collisions);
Ref<NavigationMesh> navmesh;
- Transform navmesh_transform;
+ Transform3D navmesh_transform;
for (int j = 0; j < mi->get_child_count(); j++) {
Node *child2 = mi->get_child(j);
if (!Object::cast_to<NavigationRegion3D>(child2)) {
@@ -170,7 +170,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
if (true) {
Vector<Ref<Mesh>> meshes;
- Vector<Transform> transforms;
+ Vector<Transform3D> transforms;
Vector<int> ids = p_library->get_item_list();
for (int i = 0; i < ids.size(); i++) {
if (mesh_instances.find(ids[i])) {
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index 19c6dcf402..48b885930f 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -111,7 +111,7 @@ void MultiMeshEditor::_populate() {
return;
}
- Transform geom_xform = node->get_global_transform().affine_inverse() * ss_instance->get_global_transform();
+ Transform3D geom_xform = node->get_global_transform().affine_inverse() * ss_instance->get_global_transform();
Vector<Face3> geometry = ss_instance->get_faces(VisualInstance3D::FACES_SOLID);
@@ -167,7 +167,7 @@ void MultiMeshEditor::_populate() {
float _scale = populate_scale->get_value();
int axis = populate_axis->get_selected();
- Transform axis_xform;
+ Transform3D axis_xform;
if (axis == Vector3::AXIS_Z) {
axis_xform.rotate(Vector3(1, 0, 0), -Math_PI * 0.5);
}
@@ -191,7 +191,7 @@ void MultiMeshEditor::_populate() {
Vector3 normal = face.get_plane().normal;
Vector3 op_axis = (face.vertex[0] - face.vertex[1]).normalized();
- Transform xform;
+ Transform3D xform;
xform.set_look_at(pos, pos + op_axis, normal);
xform = xform * axis_xform;
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 81f1852fba..fdb6e27367 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -85,10 +85,10 @@ void ViewportRotationControl::_notification(int p_what) {
axis_menu_options.clear();
axis_menu_options.push_back(Node3DEditorViewport::VIEW_RIGHT);
axis_menu_options.push_back(Node3DEditorViewport::VIEW_TOP);
- axis_menu_options.push_back(Node3DEditorViewport::VIEW_FRONT);
+ axis_menu_options.push_back(Node3DEditorViewport::VIEW_REAR);
axis_menu_options.push_back(Node3DEditorViewport::VIEW_LEFT);
axis_menu_options.push_back(Node3DEditorViewport::VIEW_BOTTOM);
- axis_menu_options.push_back(Node3DEditorViewport::VIEW_REAR);
+ axis_menu_options.push_back(Node3DEditorViewport::VIEW_FRONT);
axis_colors.clear();
axis_colors.push_back(get_theme_color("axis_x_color", "Editor"));
@@ -309,7 +309,7 @@ void Node3DEditorViewport::_update_camera(float p_interp_delta) {
bool manipulated = Input::get_singleton()->get_mouse_button_mask() & (2 | 4);
manipulated |= Input::get_singleton()->is_key_pressed(KEY_SHIFT);
manipulated |= Input::get_singleton()->is_key_pressed(KEY_ALT);
- manipulated |= Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ manipulated |= Input::get_singleton()->is_key_pressed(KEY_CTRL);
float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia);
float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia);
@@ -344,7 +344,7 @@ void Node3DEditorViewport::_update_camera(float p_interp_delta) {
equal = false;
}
- if (!equal || p_interp_delta == 0 || is_freelook_active() || is_orthogonal != orthogonal) {
+ if (!equal || p_interp_delta == 0 || is_orthogonal != orthogonal) {
camera->set_global_transform(to_camera_transform(camera_cursor));
if (orthogonal) {
@@ -361,8 +361,8 @@ void Node3DEditorViewport::_update_camera(float p_interp_delta) {
}
}
-Transform Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) const {
- Transform camera_transform;
+Transform3D Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) const {
+ Transform3D camera_transform;
camera_transform.translate(p_cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -p_cursor.x_rot);
camera_transform.basis.rotate(Vector3(0, 1, 0), -p_cursor.y_rot);
@@ -410,7 +410,7 @@ float Node3DEditorViewport::get_fov() const {
return CLAMP(spatial_editor->get_fov(), MIN_FOV, MAX_FOV);
}
-Transform Node3DEditorViewport::_get_camera_transform() const {
+Transform3D Node3DEditorViewport::_get_camera_transform() const {
return camera->get_global_transform();
}
@@ -631,7 +631,7 @@ Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
}
Vector2 screen_he = cm.get_viewport_half_extents();
- Transform camera_transform;
+ Transform3D camera_transform;
camera_transform.translate(cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
@@ -794,22 +794,22 @@ static int _get_key_modifier_setting(const String &p_property) {
case 3:
return KEY_META;
case 4:
- return KEY_CONTROL;
+ return KEY_CTRL;
}
return 0;
}
static int _get_key_modifier(Ref<InputEventWithModifiers> e) {
- if (e->get_shift()) {
+ if (e->is_shift_pressed()) {
return KEY_SHIFT;
}
- if (e->get_alt()) {
+ if (e->is_alt_pressed()) {
return KEY_ALT;
}
- if (e->get_control()) {
- return KEY_CONTROL;
+ if (e->is_ctrl_pressed()) {
+ return KEY_CTRL;
}
- if (e->get_metakey()) {
+ if (e->is_meta_pressed()) {
return KEY_META;
}
return 0;
@@ -829,7 +829,7 @@ bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_high
Vector3 ray_pos = _get_ray_pos(Vector2(p_screenpos.x, p_screenpos.y));
Vector3 ray = _get_ray(Vector2(p_screenpos.x, p_screenpos.y));
- Transform gt = spatial_editor->get_gizmo_transform();
+ Transform3D gt = spatial_editor->get_gizmo_transform();
float gs = gizmo_scale;
if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
@@ -1024,7 +1024,7 @@ bool Node3DEditorViewport ::_is_node_locked(const Node *p_node) {
}
void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
- _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->get_shift());
+ _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->is_shift_pressed());
Node *scene = editor->get_edited_scene();
@@ -1037,7 +1037,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
}
}
- clicked_wants_append = b->get_shift();
+ clicked_wants_append = b->is_shift_pressed();
if (selection_results.size() == 1) {
clicked = selection_results[0].item->get_instance_id();
@@ -1149,7 +1149,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
if (_edit.mode == TRANSFORM_NONE && b->is_pressed()) {
- if (b->get_alt()) {
+ if (b->is_alt_pressed()) {
if (nav_scheme == NAVIGATION_MAYA) {
break;
}
@@ -1234,7 +1234,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
case MOUSE_BUTTON_LEFT: {
if (b->is_pressed()) {
NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
- if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->get_alt()) {
+ if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->is_alt_pressed()) {
break;
}
@@ -1244,6 +1244,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
_edit.mouse_pos = b->get_position();
+ _edit.original_mouse_pos = b->get_position();
_edit.snap = spatial_editor->is_snap_enabled();
_edit.mode = TRANSFORM_NONE;
@@ -1262,7 +1263,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
int handle = -1;
Vector3 point;
Vector3 normal;
- bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, b->get_shift());
+ bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, b->is_shift_pressed());
if (inters && handle != -1) {
_edit.gizmo = seg;
_edit.gizmo_handle = handle;
@@ -1279,7 +1280,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
clicked = ObjectID();
clicked_includes_current = false;
- if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->get_command()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
+ if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
/* HANDLE ROTATION */
if (get_selected_count() == 0) {
break; //bye
@@ -1314,11 +1315,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
int gizmo_handle = -1;
- clicked = _select_ray(b->get_position(), b->get_shift(), clicked_includes_current, &gizmo_handle, b->get_shift());
+ clicked = _select_ray(b->get_position(), b->is_shift_pressed(), clicked_includes_current, &gizmo_handle, b->is_shift_pressed());
//clicking is always deferred to either move or release
- clicked_wants_append = b->get_shift();
+ clicked_wants_append = b->is_shift_pressed();
if (clicked.is_null()) {
if (!clicked_wants_append) {
@@ -1441,16 +1442,17 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
set_message(n + ": " + String(v));
} else if (m->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
- if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) {
+ if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) {
nav_mode = NAVIGATION_ORBIT;
- } else if (nav_scheme == NAVIGATION_MODO && m->get_alt() && m->get_shift()) {
+ } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed() && m->is_shift_pressed()) {
nav_mode = NAVIGATION_PAN;
- } else if (nav_scheme == NAVIGATION_MODO && m->get_alt() && m->get_control()) {
+ } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed() && m->is_ctrl_pressed()) {
nav_mode = NAVIGATION_ZOOM;
- } else if (nav_scheme == NAVIGATION_MODO && m->get_alt()) {
+ } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed()) {
nav_mode = NAVIGATION_ORBIT;
} else {
- if (clicked.is_valid()) {
+ bool movement_threshold_passed = _edit.original_mouse_pos.distance_to(_edit.mouse_pos) > 10 * EDSCALE;
+ if (clicked.is_valid() && movement_threshold_passed) {
if (!clicked_includes_current) {
_select_clicked(clicked_wants_append, true);
// Processing was deferred.
@@ -1579,10 +1581,10 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform original = se->original;
- Transform original_local = se->original_local;
- Transform base = Transform(Basis(), _edit.center);
- Transform t;
+ Transform3D original = se->original;
+ Transform3D original_local = se->original_local;
+ Transform3D base = Transform3D(Basis(), _edit.center);
+ Transform3D t;
Vector3 local_scale;
if (local_coords) {
@@ -1608,7 +1610,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
motion.snap(Vector3(snap, snap, snap));
}
- Transform r;
+ Transform3D r;
r.basis.scale(motion + Vector3(1, 1, 1));
t = base * (r * (base.inverse() * original));
@@ -1701,8 +1703,8 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform original = se->original;
- Transform t;
+ Transform3D original = se->original;
+ Transform3D t;
if (local_coords) {
if (_edit.snap || spatial_editor->is_snap_enabled()) {
@@ -1797,10 +1799,10 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform t;
+ Transform3D t;
if (local_coords) {
- Transform original_local = se->original_local;
+ Transform3D original_local = se->original_local;
Basis rot = Basis(axis, angle);
t.basis = original_local.get_basis().orthonormalized() * rot;
@@ -1811,9 +1813,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
sp->set_scale(original_local.basis.get_scale()); // re-apply original scale
} else {
- Transform original = se->original;
- Transform r;
- Transform base = Transform(Basis(), _edit.center);
+ Transform3D original = se->original;
+ Transform3D r;
+ Transform3D base = Transform3D(Basis(), _edit.center);
r.basis.rotate(plane.normal, angle);
t = base * r * base.inverse() * original;
@@ -1831,7 +1833,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
}
} else if ((m->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) || freelook_active) {
- if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) {
+ if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) {
nav_mode = NAVIGATION_ZOOM;
} else if (freelook_active) {
nav_mode = NAVIGATION_LOOK;
@@ -1924,7 +1926,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
} else if (nav_scheme == NAVIGATION_MAYA) {
- if (pan_gesture->get_alt()) {
+ if (pan_gesture->is_alt_pressed()) {
nav_mode = NAVIGATION_PAN;
}
}
@@ -2053,11 +2055,11 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const
real_t pan_speed = 1 / 150.0;
int pan_speed_modifier = 10;
- if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift()) {
+ if (nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) {
pan_speed *= pan_speed_modifier;
}
- Transform camera_transform;
+ Transform3D camera_transform;
camera_transform.translate(cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
@@ -2078,7 +2080,7 @@ void Node3DEditorViewport::_nav_zoom(Ref<InputEventWithModifiers> p_event, const
real_t zoom_speed = 1 / 80.0;
int zoom_speed_modifier = 10;
- if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift()) {
+ if (nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) {
zoom_speed *= zoom_speed_modifier;
}
@@ -2145,7 +2147,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const
const bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis");
// Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag".
- const Transform prev_camera_transform = to_camera_transform(cursor);
+ const Transform3D prev_camera_transform = to_camera_transform(cursor);
if (invert_y_axis) {
cursor.x_rot -= p_relative.y * radians_per_pixel;
@@ -2158,7 +2160,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const
cursor.y_rot += p_relative.x * radians_per_pixel;
// Look is like the opposite of Orbit: the focus point rotates around the camera
- Transform camera_transform = to_camera_transform(cursor);
+ Transform3D camera_transform = to_camera_transform(cursor);
Vector3 pos = camera_transform.xform(Vector3(0, 0, 0));
Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0));
Vector3 diff = prev_pos - pos;
@@ -2444,7 +2446,7 @@ void Node3DEditorViewport::_notification(int p_what) {
continue;
}
- Transform t = sp->get_global_gizmo_transform();
+ Transform3D t = sp->get_global_gizmo_transform();
VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(sp);
AABB new_aabb = vi ? vi->get_aabb() : _calculate_spatial_bounds(sp);
@@ -2500,9 +2502,9 @@ void Node3DEditorViewport::_notification(int p_what) {
if (show_info) {
String text;
- text += "X: " + rtos(current_camera->get_translation().x).pad_decimals(1) + "\n";
- text += "Y: " + rtos(current_camera->get_translation().y).pad_decimals(1) + "\n";
- text += "Z: " + rtos(current_camera->get_translation().z).pad_decimals(1) + "\n";
+ text += "X: " + rtos(current_camera->get_position().x).pad_decimals(1) + "\n";
+ text += "Y: " + rtos(current_camera->get_position().y).pad_decimals(1) + "\n";
+ text += "Z: " + rtos(current_camera->get_position().z).pad_decimals(1) + "\n";
text += TTR("Pitch") + ": " + itos(Math::round(current_camera->get_rotation_degrees().x)) + "\n";
text += TTR("Yaw") + ": " + itos(Math::round(current_camera->get_rotation_degrees().y)) + "\n\n";
@@ -2878,7 +2880,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
break;
}
- Transform camera_transform = camera->get_global_transform();
+ Transform3D camera_transform = camera->get_global_transform();
List<Node *> &selection = editor_selection->get_selected_node_list();
@@ -2895,7 +2897,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
continue;
}
- Transform xform;
+ Transform3D xform;
if (orthogonal) {
xform = sp->get_global_transform();
xform.basis.set_euler(camera_transform.basis.get_euler());
@@ -2915,7 +2917,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
break;
}
- Transform camera_transform = camera->get_global_transform();
+ Transform3D camera_transform = camera->get_global_transform();
List<Node *> &selection = editor_selection->get_selected_node_list();
@@ -3060,9 +3062,9 @@ void Node3DEditorViewport::_menu_option(int p_option) {
case VIEW_DISPLAY_NORMAL_BUFFER:
case VIEW_DISPLAY_DEBUG_SHADOW_ATLAS:
case VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS:
- case VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO:
- case VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING:
- case VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION:
+ case VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO:
+ case VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING:
+ case VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION:
case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE:
case VIEW_DISPLAY_DEBUG_SSAO:
case VIEW_DISPLAY_DEBUG_PSSM_SPLITS:
@@ -3086,9 +3088,9 @@ void Node3DEditorViewport::_menu_option(int p_option) {
VIEW_DISPLAY_WIREFRAME,
VIEW_DISPLAY_DEBUG_SHADOW_ATLAS,
VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS,
- VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO,
- VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING,
- VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION,
+ VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO,
+ VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING,
+ VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION,
VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
VIEW_DISPLAY_DEBUG_SSAO,
VIEW_DISPLAY_DEBUG_GI_BUFFER,
@@ -3114,9 +3116,9 @@ void Node3DEditorViewport::_menu_option(int p_option) {
Viewport::DEBUG_DRAW_WIREFRAME,
Viewport::DEBUG_DRAW_SHADOW_ATLAS,
Viewport::DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
- Viewport::DEBUG_DRAW_GI_PROBE_ALBEDO,
- Viewport::DEBUG_DRAW_GI_PROBE_LIGHTING,
- Viewport::DEBUG_DRAW_GI_PROBE_EMISSION,
+ Viewport::DEBUG_DRAW_VOXEL_GI_ALBEDO,
+ Viewport::DEBUG_DRAW_VOXEL_GI_LIGHTING,
+ Viewport::DEBUG_DRAW_VOXEL_GI_EMISSION,
Viewport::DEBUG_DRAW_SCENE_LUMINANCE,
Viewport::DEBUG_DRAW_SSAO,
Viewport::DEBUG_DRAW_GI_BUFFER,
@@ -3315,9 +3317,9 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
return;
}
- Transform xform = spatial_editor->get_gizmo_transform();
+ Transform3D xform = spatial_editor->get_gizmo_transform();
- Transform camera_xform = camera->get_transform();
+ Transform3D camera_xform = camera->get_transform();
if (xform.origin.distance_squared_to(camera_xform.origin) < 0.01) {
for (int i = 0; i < 3; i++) {
@@ -3551,8 +3553,8 @@ Dictionary Node3DEditorViewport::get_state() const {
void Node3DEditorViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"), &Node3DEditorViewport::update_transform_gizmo_view); // Used by call_deferred.
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &Node3DEditorViewport::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &Node3DEditorViewport::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &Node3DEditorViewport::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &Node3DEditorViewport::drop_data_fw);
ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")));
ADD_SIGNAL(MethodInfo("clicked", PropertyInfo(Variant::OBJECT, "viewport")));
@@ -3800,7 +3802,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
Node3D *node3d = Object::cast_to<Node3D>(instanced_scene);
if (node3d) {
- Transform global_transform;
+ Transform3D global_transform;
Node3D *parent_node3d = Object::cast_to<Node3D>(parent);
if (parent_node3d) {
global_transform = parent_node3d->get_global_gizmo_transform();
@@ -3900,7 +3902,7 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant
}
if (can_instance) {
- Transform global_transform = Transform(Basis(), _get_instance_position(p_point));
+ Transform3D global_transform = Transform3D(Basis(), _get_instance_position(p_point));
preview_node->set_global_transform(global_transform);
}
@@ -4036,9 +4038,9 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
display_submenu->add_separator();
display_submenu->add_radio_check_item(TTR("Decal Atlas"), VIEW_DISPLAY_DEBUG_DECAL_ATLAS);
display_submenu->add_separator();
- display_submenu->add_radio_check_item(TTR("GIProbe Lighting"), VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING);
- display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO);
- display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION);
+ display_submenu->add_radio_check_item(TTR("VoxelGI Lighting"), VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING);
+ display_submenu->add_radio_check_item(TTR("VoxelGI Albedo"), VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO);
+ display_submenu->add_radio_check_item(TTR("VoxelGI Emission"), VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION);
display_submenu->add_separator();
display_submenu->add_radio_check_item(TTR("SDFGI Cascades"), VIEW_DISPLAY_DEBUG_SDFGI);
display_submenu->add_radio_check_item(TTR("SDFGI Probes"), VIEW_DISPLAY_DEBUG_SDFGI_PROBES);
@@ -4574,7 +4576,7 @@ void Node3DEditor::update_transform_gizmo() {
continue;
}
- Transform xf = se->sp->get_global_gizmo_transform();
+ Transform3D xf = se->sp->get_global_gizmo_transform();
if (first) {
center.position = xf.origin;
@@ -4955,7 +4957,7 @@ void Node3DEditor::_snap_update() {
}
void Node3DEditor::_xform_dialog_action() {
- Transform t;
+ Transform3D t;
//translation
Vector3 scale;
Vector3 rotate;
@@ -4988,7 +4990,7 @@ void Node3DEditor::_xform_dialog_action() {
bool post = xform_type->get_selected() > 0;
- Transform tr = sp->get_global_gizmo_transform();
+ Transform3D tr = sp->get_global_gizmo_transform();
if (post) {
tr = tr * t;
} else {
@@ -5056,11 +5058,11 @@ void Node3DEditor::_update_camera_override_button(bool p_game_running) {
if (p_game_running) {
button->set_disabled(false);
- button->set_tooltip(TTR("Game Camera Override\nNo game instance running."));
+ button->set_tooltip(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera."));
} else {
button->set_disabled(true);
button->set_pressed(false);
- button->set_tooltip(TTR("Game Camera Override\nOverrides game camera with editor viewport camera."));
+ button->set_tooltip(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature."));
}
}
@@ -5834,7 +5836,7 @@ void Node3DEditor::_init_grid() {
return;
}
Camera3D *camera = get_editor_viewport(0)->camera;
- Vector3 camera_position = camera->get_translation();
+ Vector3 camera_position = camera->get_position();
if (camera_position == Vector3()) {
return; // Camera3D is invalid, don't draw the grid.
}
@@ -6180,7 +6182,7 @@ void Node3DEditor::snap_selected_nodes_to_floor() {
if (ss->intersect_ray(from, to, result, excluded)) {
Vector3 position_offset = d["position_offset"];
- Transform new_transform = sp->get_global_transform();
+ Transform3D new_transform = sp->get_global_transform();
new_transform.origin.y = result.position.y;
new_transform.origin = new_transform.origin - position_offset;
@@ -6204,7 +6206,7 @@ void Node3DEditor::_unhandled_key_input(Ref<InputEvent> p_event) {
return;
}
- snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CTRL);
}
void Node3DEditor::_sun_environ_settings_pressed() {
@@ -6496,8 +6498,8 @@ void Node3DEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<CPUParticles3DGizmoPlugin>(memnew(CPUParticles3DGizmoPlugin)));
add_gizmo_plugin(Ref<ReflectionProbeGizmoPlugin>(memnew(ReflectionProbeGizmoPlugin)));
add_gizmo_plugin(Ref<DecalGizmoPlugin>(memnew(DecalGizmoPlugin)));
- add_gizmo_plugin(Ref<GIProbeGizmoPlugin>(memnew(GIProbeGizmoPlugin)));
- add_gizmo_plugin(Ref<BakedLightmapGizmoPlugin>(memnew(BakedLightmapGizmoPlugin)));
+ add_gizmo_plugin(Ref<VoxelGIGizmoPlugin>(memnew(VoxelGIGizmoPlugin)));
+ add_gizmo_plugin(Ref<LightmapGIGizmoPlugin>(memnew(LightmapGIGizmoPlugin)));
add_gizmo_plugin(Ref<LightmapProbeGizmoPlugin>(memnew(LightmapProbeGizmoPlugin)));
add_gizmo_plugin(Ref<CollisionObject3DGizmoPlugin>(memnew(CollisionObject3DGizmoPlugin)));
add_gizmo_plugin(Ref<CollisionShape3DGizmoPlugin>(memnew(CollisionShape3DGizmoPlugin)));
@@ -6556,7 +6558,7 @@ void Node3DEditor::_preview_settings_changed() {
}
{ // preview sun
- Transform t;
+ Transform3D t;
t.basis = sun_rotation;
preview_sun->set_transform(t);
sun_direction->update();
@@ -7475,15 +7477,15 @@ Ref<StandardMaterial3D> EditorNode3DGizmoPlugin::get_material(const String &p_na
}
String EditorNode3DGizmoPlugin::get_gizmo_name() const {
- if (get_script_instance() && get_script_instance()->has_method("get_gizmo_name")) {
- return get_script_instance()->call("get_gizmo_name");
+ if (get_script_instance() && get_script_instance()->has_method("_get_gizmo_name")) {
+ return get_script_instance()->call("_get_gizmo_name");
}
return TTR("Nameless gizmo");
}
int EditorNode3DGizmoPlugin::get_priority() const {
- if (get_script_instance() && get_script_instance()->has_method("get_priority")) {
- return get_script_instance()->call("get_priority");
+ if (get_script_instance() && get_script_instance()->has_method("_get_priority")) {
+ return get_script_instance()->call("_get_priority");
}
return 0;
}
@@ -7510,8 +7512,8 @@ Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::get_gizmo(Node3D *p_spatial) {
void EditorNode3DGizmoPlugin::_bind_methods() {
#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorNode3DGizmo")
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
- BIND_VMETHOD(MethodInfo(GIZMO_REF, "create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
+ BIND_VMETHOD(MethodInfo(GIZMO_REF, "_create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorNode3DGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorNode3DGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1)));
@@ -7520,38 +7522,38 @@ void EditorNode3DGizmoPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material, DEFVAL(Ref<EditorNode3DGizmo>()));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "get_gizmo_name"));
- BIND_VMETHOD(MethodInfo(Variant::INT, "get_priority"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_be_hidden"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_selectable_when_hidden"));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_gizmo_name"));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_get_priority"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_can_be_hidden"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_selectable_when_hidden"));
- BIND_VMETHOD(MethodInfo("redraw", GIZMO_REF));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", GIZMO_REF, PropertyInfo(Variant::INT, "index")));
+ BIND_VMETHOD(MethodInfo("_redraw", GIZMO_REF));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_handle_name", GIZMO_REF, PropertyInfo(Variant::INT, "index")));
- MethodInfo hvget(Variant::NIL, "get_handle_value", GIZMO_REF, PropertyInfo(Variant::INT, "index"));
+ MethodInfo hvget(Variant::NIL, "_get_handle_value", GIZMO_REF, PropertyInfo(Variant::INT, "index"));
hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
BIND_VMETHOD(hvget);
- BIND_VMETHOD(MethodInfo("set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
- MethodInfo cm = MethodInfo("commit_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
+ BIND_VMETHOD(MethodInfo("_set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
+ MethodInfo cm = MethodInfo("_commit_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
cm.default_arguments.push_back(false);
BIND_VMETHOD(cm);
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_handle_highlighted", GIZMO_REF, PropertyInfo(Variant::INT, "index")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_handle_highlighted", GIZMO_REF, PropertyInfo(Variant::INT, "index")));
#undef GIZMO_REF
}
bool EditorNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
- if (get_script_instance() && get_script_instance()->has_method("has_gizmo")) {
- return get_script_instance()->call("has_gizmo", p_spatial);
+ if (get_script_instance() && get_script_instance()->has_method("_has_gizmo")) {
+ return get_script_instance()->call("_has_gizmo", p_spatial);
}
return false;
}
Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) {
- if (get_script_instance() && get_script_instance()->has_method("create_gizmo")) {
- return get_script_instance()->call("create_gizmo", p_spatial);
+ if (get_script_instance() && get_script_instance()->has_method("_create_gizmo")) {
+ return get_script_instance()->call("_create_gizmo", p_spatial);
}
Ref<EditorNode3DGizmo> ref;
@@ -7562,55 +7564,55 @@ Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial)
}
bool EditorNode3DGizmoPlugin::can_be_hidden() const {
- if (get_script_instance() && get_script_instance()->has_method("can_be_hidden")) {
- return get_script_instance()->call("can_be_hidden");
+ if (get_script_instance() && get_script_instance()->has_method("_can_be_hidden")) {
+ return get_script_instance()->call("_can_be_hidden");
}
return true;
}
bool EditorNode3DGizmoPlugin::is_selectable_when_hidden() const {
- if (get_script_instance() && get_script_instance()->has_method("is_selectable_when_hidden")) {
- return get_script_instance()->call("is_selectable_when_hidden");
+ if (get_script_instance() && get_script_instance()->has_method("_is_selectable_when_hidden")) {
+ return get_script_instance()->call("_is_selectable_when_hidden");
}
return false;
}
void EditorNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
- if (get_script_instance() && get_script_instance()->has_method("redraw")) {
+ if (get_script_instance() && get_script_instance()->has_method("_redraw")) {
Ref<EditorNode3DGizmo> ref(p_gizmo);
- get_script_instance()->call("redraw", ref);
+ get_script_instance()->call("_redraw", ref);
}
}
String EditorNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- if (get_script_instance() && get_script_instance()->has_method("get_handle_name")) {
- return get_script_instance()->call("get_handle_name", p_gizmo, p_idx);
+ if (get_script_instance() && get_script_instance()->has_method("_get_handle_name")) {
+ return get_script_instance()->call("_get_handle_name", p_gizmo, p_idx);
}
return "";
}
Variant EditorNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
- if (get_script_instance() && get_script_instance()->has_method("get_handle_value")) {
- return get_script_instance()->call("get_handle_value", p_gizmo, p_idx);
+ if (get_script_instance() && get_script_instance()->has_method("_get_handle_value")) {
+ return get_script_instance()->call("_get_handle_value", p_gizmo, p_idx);
}
return Variant();
}
void EditorNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
- if (get_script_instance() && get_script_instance()->has_method("set_handle")) {
- get_script_instance()->call("set_handle", p_gizmo, p_idx, p_camera, p_point);
+ if (get_script_instance() && get_script_instance()->has_method("_set_handle")) {
+ get_script_instance()->call("_set_handle", p_gizmo, p_idx, p_camera, p_point);
}
}
void EditorNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
- if (get_script_instance() && get_script_instance()->has_method("commit_handle")) {
- get_script_instance()->call("commit_handle", p_gizmo, p_idx, p_restore, p_cancel);
+ if (get_script_instance() && get_script_instance()->has_method("_commit_handle")) {
+ get_script_instance()->call("_commit_handle", p_gizmo, p_idx, p_restore, p_cancel);
}
}
bool EditorNode3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- if (get_script_instance() && get_script_instance()->has_method("is_handle_highlighted")) {
- return get_script_instance()->call("is_handle_highlighted", p_gizmo, p_idx);
+ if (get_script_instance() && get_script_instance()->has_method("_is_handle_highlighted")) {
+ return get_script_instance()->call("_is_handle_highlighted", p_gizmo, p_idx);
}
return false;
}
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 33f4c32471..161d6a38a9 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -206,9 +206,9 @@ class Node3DEditorViewport : public Control {
VIEW_DISPLAY_NORMAL_BUFFER,
VIEW_DISPLAY_DEBUG_SHADOW_ATLAS,
VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS,
- VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO,
- VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING,
- VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION,
+ VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO,
+ VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING,
+ VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION,
VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
VIEW_DISPLAY_DEBUG_SSAO,
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
@@ -322,7 +322,7 @@ private:
Vector3 _get_ray_pos(const Vector2 &p_pos) const;
Vector3 _get_ray(const Vector2 &p_pos) const;
Point2 _point_to_screen(const Vector3 &p_point);
- Transform _get_camera_transform() const;
+ Transform3D _get_camera_transform() const;
int get_selected_count() const;
Vector3 _get_camera_position() const;
@@ -380,13 +380,14 @@ private:
struct EditData {
TransformMode mode;
TransformPlane plane;
- Transform original;
+ Transform3D original;
Vector3 click_ray;
Vector3 click_ray_pos;
Vector3 center;
Vector3 orig_gizmo_pos;
int edited_gizmo = 0;
Point2 mouse_pos;
+ Point2 original_mouse_pos;
bool snap = false;
Ref<EditorNode3DGizmo> gizmo;
int gizmo_handle = 0;
@@ -432,7 +433,7 @@ private:
//
void _update_camera(float p_interp_delta);
- Transform to_camera_transform(const Cursor &p_cursor) const;
+ Transform3D to_camera_transform(const Cursor &p_cursor) const;
void _draw();
void _surface_mouse_enter();
@@ -505,9 +506,9 @@ class Node3DEditorSelectedItem : public Object {
public:
AABB aabb;
- Transform original; // original location when moving
- Transform original_local;
- Transform last_xform; // last transform
+ Transform3D original; // original location when moving
+ Transform3D original_local;
+ Transform3D last_xform; // last transform
bool last_xform_dirty;
Node3D *sp;
RID sbox_instance;
@@ -641,7 +642,7 @@ private:
struct Gizmo {
bool visible = false;
float scale = 0;
- Transform transform;
+ Transform3D transform;
} gizmo;
enum MenuOption {
@@ -824,7 +825,7 @@ public:
float get_zfar() const { return settings_zfar->get_value(); }
float get_fov() const { return settings_fov->get_value(); }
- Transform get_gizmo_transform() const { return gizmo.transform; }
+ Transform3D get_gizmo_transform() const { return gizmo.transform; }
bool is_gizmo_visible() const { return gizmo.visible; }
ToolMode get_tool_mode() const { return tool_mode; }
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index 84b4516452..838e67b5e7 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -31,7 +31,7 @@
#include "path_2d_editor_plugin.h"
#include "canvas_item_editor_plugin.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/keyboard.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -89,7 +89,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
// Check for point movement start (for point + in/out controls).
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (mode == MODE_EDIT && !mb->get_shift() && dist_to_p < grab_threshold) {
+ if (mode == MODE_EDIT && !mb->is_shift_pressed() && dist_to_p < grab_threshold) {
// Points can only be moved in edit mode.
action = ACTION_MOVING_POINT;
@@ -149,7 +149,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
// Check for point creation.
- if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && ((mb->is_command_pressed() && mode == MODE_EDIT) || mode == MODE_CREATE)) {
Ref<Curve2D> curve = node->get_curve();
undo_redo->create_action(TTR("Add Point to Curve"));
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index 47bd1114d2..b0eb13c3c6 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -94,8 +94,8 @@ void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_poin
return;
}
- Transform gt = path->get_global_transform();
- Transform gi = gt.affine_inverse();
+ Transform3D gt = path->get_global_transform();
+ Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -302,8 +302,8 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref
if (c.is_null()) {
return false;
}
- Transform gt = path->get_global_transform();
- Transform it = gt.affine_inverse();
+ Transform3D gt = path->get_global_transform();
+ Transform3D it = gt.affine_inverse();
static const int click_dist = 10; //should make global
@@ -316,7 +316,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref
set_handle_clicked(false);
}
- if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->is_ctrl_pressed()))) {
//click into curve, break it down
Vector<Vector3> v3a = c->tessellate();
int idx = 0;
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 470d897dcc..8a14db0cfd 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -32,8 +32,8 @@
#include "canvas_item_editor_plugin.h"
#include "core/input/input.h"
+#include "core/io/file_access.h"
#include "core/math/geometry_2d.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -613,11 +613,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
}
if (uv_move_current == UV_MODE_EDIT_POINT) {
- if (mb->get_shift() && mb->get_command()) {
+ if (mb->is_shift_pressed() && mb->is_command_pressed()) {
uv_move_current = UV_MODE_SCALE;
- } else if (mb->get_shift()) {
+ } else if (mb->is_shift_pressed()) {
uv_move_current = UV_MODE_MOVE;
- } else if (mb->get_command()) {
+ } else if (mb->is_command_pressed()) {
uv_move_current = UV_MODE_ROTATE;
}
}
@@ -1144,7 +1144,7 @@ void Polygon2DEditor::_uv_draw() {
if (!found_child) {
//draw normally
Transform2D bone_xform = node->get_global_transform().affine_inverse() * (skeleton->get_global_transform() * bone->get_skeleton_rest());
- Transform2D endpoint_xform = bone_xform * Transform2D(0, Vector2(bone->get_default_length(), 0));
+ Transform2D endpoint_xform = bone_xform * Transform2D(0, Vector2(bone->get_length(), 0));
Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5);
uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE));
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index b4b8e82124..b8b2c6d343 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -339,9 +339,9 @@ void ResourcePreloaderEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_library"), &ResourcePreloaderEditor::_update_library);
ClassDB::bind_method(D_METHOD("_remove_resource", "to_remove"), &ResourcePreloaderEditor::_remove_resource);
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ResourcePreloaderEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ResourcePreloaderEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &ResourcePreloaderEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &ResourcePreloaderEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &ResourcePreloaderEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &ResourcePreloaderEditor::drop_data_fw);
}
ResourcePreloaderEditor::ResourcePreloaderEditor() {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 8c4c5a3461..0410ab3a45 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -32,8 +32,8 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "editor/debugger/editor_debugger_node.h"
@@ -218,6 +218,8 @@ Ref<EditorSyntaxHighlighter> EditorPlainTextSyntaxHighlighter::_create() const {
/*** SCRIPT EDITOR ****/
void ScriptEditorBase::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_base_editor"), &ScriptEditorBase::get_base_editor);
+
ADD_SIGNAL(MethodInfo("name_changed"));
ADD_SIGNAL(MethodInfo("edited_script_changed"));
ADD_SIGNAL(MethodInfo("request_help", PropertyInfo(Variant::STRING, "topic")));
@@ -228,7 +230,7 @@ void ScriptEditorBase::_bind_methods() {
ADD_SIGNAL(MethodInfo("search_in_files_requested", PropertyInfo(Variant::STRING, "text")));
ADD_SIGNAL(MethodInfo("replace_in_files_requested", PropertyInfo(Variant::STRING, "text")));
- BIND_VMETHOD(MethodInfo("add_syntax_highlighter", PropertyInfo(Variant::OBJECT, "highlighter")));
+ BIND_VMETHOD(MethodInfo("_add_syntax_highlighter", PropertyInfo(Variant::OBJECT, "highlighter")));
}
static bool _is_built_in_script(Script *p_script) {
@@ -337,13 +339,13 @@ void ScriptEditorQuickOpen::_update_search() {
if ((search_box->get_text() == "" || file.findn(search_box->get_text()) != -1)) {
TreeItem *ti = search_options->create_item(root);
ti->set_text(0, file);
- if (root->get_children() == ti) {
+ if (root->get_first_child() == ti) {
ti->select(0);
}
}
}
- get_ok_button()->set_disabled(root->get_children() == nullptr);
+ get_ok_button()->set_disabled(root->get_first_child() == nullptr);
}
void ScriptEditorQuickOpen::_confirmed() {
@@ -1501,6 +1503,11 @@ void ScriptEditor::_notification(int p_what) {
filename->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("normal", "LineEdit"));
recent_scripts->set_as_minsize();
+
+ if (is_inside_tree()) {
+ _update_script_colors();
+ _update_script_names();
+ }
} break;
case NOTIFICATION_READY: {
@@ -1633,10 +1640,13 @@ void ScriptEditor::ensure_select_current() {
ScriptEditorBase *se = _get_current_editor();
if (se) {
se->enable_editor();
+ se->set_find_replace_bar(find_replace_bar);
if (!grab_focus_block && is_visible_in_tree()) {
se->ensure_focus();
}
+ } else {
+ find_replace_bar->hide();
}
}
@@ -1675,7 +1685,7 @@ struct _ScriptEditorItemData {
if (sort_key == id.sort_key) {
return index < id.index;
} else {
- return sort_key < id.sort_key;
+ return sort_key.naturalnocasecmp_to(id.sort_key) < 0;
}
} else {
return category < id.category;
@@ -2279,8 +2289,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
void ScriptEditor::save_current_script() {
ScriptEditorBase *current = _get_current_editor();
-
- if (_test_script_times_on_disk()) {
+ if (!current || _test_script_times_on_disk()) {
return;
}
@@ -2445,7 +2454,9 @@ void ScriptEditor::_add_callback(Object *p_obj, const String &p_function, const
script_list->select(script_list->find_metadata(i));
// Save the current script so the changes can be picked up by an external editor.
- save_current_script();
+ if (!_is_built_in_script(script.ptr())) { // But only if it's not built-in script.
+ save_current_script();
+ }
break;
}
@@ -3182,7 +3193,7 @@ void ScriptEditor::_on_find_in_files_result_selected(String fpath, int line_numb
if (ResourceLoader::exists(fpath)) {
RES res = ResourceLoader::load(fpath);
- if (fpath.get_extension() == "shader") {
+ if (fpath.get_extension() == "gdshader") {
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_singleton()->get_editor_data().get_editor("Shader"));
shader_editor->edit(res.ptr());
shader_editor->make_visible(true);
@@ -3265,9 +3276,9 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("register_syntax_highlighter", "syntax_highlighter"), &ScriptEditor::register_syntax_highlighter);
ClassDB::bind_method(D_METHOD("unregister_syntax_highlighter", "syntax_highlighter"), &ScriptEditor::unregister_syntax_highlighter);
- ClassDB::bind_method(D_METHOD("get_drag_data_fw", "point", "from"), &ScriptEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw", "point", "data", "from"), &ScriptEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw", "point", "data", "from"), &ScriptEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw", "point", "from"), &ScriptEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw", "point", "data", "from"), &ScriptEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw", "point", "data", "from"), &ScriptEditor::drop_data_fw);
ClassDB::bind_method(D_METHOD("goto_line", "line_number"), &ScriptEditor::_goto_script_line2);
ClassDB::bind_method(D_METHOD("get_current_script"), &ScriptEditor::_get_current_script);
@@ -3371,11 +3382,19 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
help_overview->set_custom_minimum_size(Size2(0, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
help_overview->set_v_size_flags(SIZE_EXPAND_FILL);
+ VBoxContainer *code_editor_container = memnew(VBoxContainer);
+ script_split->add_child(code_editor_container);
+
tab_container = memnew(TabContainer);
tab_container->set_tabs_visible(false);
tab_container->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
- script_split->add_child(tab_container);
+ code_editor_container->add_child(tab_container);
tab_container->set_h_size_flags(SIZE_EXPAND_FILL);
+ tab_container->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ find_replace_bar = memnew(FindReplaceBar);
+ code_editor_container->add_child(find_replace_bar);
+ find_replace_bar->hide();
ED_SHORTCUT("script_editor/window_sort", TTR("Sort"));
ED_SHORTCUT("script_editor/window_move_up", TTR("Move Up"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_UP);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 570ebfba4e..1d379059d4 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -162,6 +162,9 @@ public:
virtual void set_tooltip_request_func(String p_method, Object *p_obj) = 0;
virtual Control *get_edit_menu() = 0;
virtual void clear_edit_menu() = 0;
+ virtual void set_find_replace_bar(FindReplaceBar *p_bar) = 0;
+
+ virtual Control *get_base_editor() const = 0;
virtual void validate() = 0;
@@ -268,6 +271,7 @@ class ScriptEditor : public PanelContainer {
ConfirmationDialog *erase_tab_confirm;
ScriptCreateDialog *script_create_dialog;
Button *scripts_visible;
+ FindReplaceBar *find_replace_bar;
String current_theme;
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index edf540bf48..1f6da30547 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -170,66 +170,25 @@ void ScriptTextEditor::_load_theme_settings() {
CodeEdit *text_edit = code_editor->get_text_editor();
text_edit->clear_keywords();
+ Color updated_marked_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
Color updated_safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color");
- if (updated_safe_line_number_color != safe_line_number_color) {
+
+ bool safe_line_number_color_updated = updated_safe_line_number_color != safe_line_number_color;
+ bool marked_line_color_updated = updated_marked_line_color != marked_line_color;
+ if (safe_line_number_color_updated || marked_line_color_updated) {
safe_line_number_color = updated_safe_line_number_color;
for (int i = 0; i < text_edit->get_line_count(); i++) {
- if (text_edit->get_line_gutter_item_color(i, line_number_gutter) != default_line_number_color) {
+ if (marked_line_color_updated && text_edit->get_line_background_color(i) == marked_line_color) {
+ text_edit->set_line_background_color(i, updated_marked_line_color);
+ }
+
+ if (safe_line_number_color_updated && text_edit->get_line_gutter_item_color(i, line_number_gutter) != default_line_number_color) {
text_edit->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
}
}
+ marked_line_color = updated_marked_line_color;
}
- Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
- Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
- Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
- Color completion_existing_color = EDITOR_GET("text_editor/highlighting/completion_existing_color");
- Color completion_scroll_color = EDITOR_GET("text_editor/highlighting/completion_scroll_color");
- Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
- Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
- Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
- Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
- Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
- Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
- Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
- Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
- Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
- Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
- Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
- Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
- Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
- Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
- Color executing_line_color = EDITOR_GET("text_editor/highlighting/executing_line_color");
- Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
- Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
- Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
-
- text_edit->add_theme_color_override("background_color", background_color);
- text_edit->add_theme_color_override("completion_background_color", completion_background_color);
- text_edit->add_theme_color_override("completion_selected_color", completion_selected_color);
- text_edit->add_theme_color_override("completion_existing_color", completion_existing_color);
- text_edit->add_theme_color_override("completion_scroll_color", completion_scroll_color);
- text_edit->add_theme_color_override("completion_font_color", completion_font_color);
- text_edit->add_theme_color_override("font_color", text_color);
- text_edit->add_theme_color_override("line_number_color", line_number_color);
- text_edit->add_theme_color_override("caret_color", caret_color);
- text_edit->add_theme_color_override("caret_background_color", caret_background_color);
- text_edit->add_theme_color_override("font_selected_color", text_selected_color);
- text_edit->add_theme_color_override("selection_color", selection_color);
- text_edit->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
- text_edit->add_theme_color_override("current_line_color", current_line_color);
- text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
- text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
- text_edit->add_theme_color_override("bookmark_color", bookmark_color);
- text_edit->add_theme_color_override("breakpoint_color", breakpoint_color);
- text_edit->add_theme_color_override("executing_line_color", executing_line_color);
- text_edit->add_theme_color_override("mark_color", mark_color);
- text_edit->add_theme_color_override("code_folding_color", code_folding_color);
- text_edit->add_theme_color_override("search_result_color", search_result_color);
- text_edit->add_theme_color_override("search_result_border_color", search_result_border_color);
-
- text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
-
theme_loaded = true;
if (!script.is_null()) {
_set_theme_for_script();
@@ -244,6 +203,26 @@ void ScriptTextEditor::_set_theme_for_script() {
CodeEdit *text_edit = code_editor->get_text_editor();
text_edit->get_syntax_highlighter()->update_cache();
+ List<String> strings;
+ script->get_language()->get_string_delimiters(&strings);
+ text_edit->clear_string_delimiters();
+ for (List<String>::Element *E = strings.front(); E; E = E->next()) {
+ String string = E->get();
+ String beg = string.get_slice(" ", 0);
+ String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
+ text_edit->add_string_delimiter(beg, end, end == "");
+ }
+
+ List<String> comments;
+ script->get_language()->get_comment_delimiters(&comments);
+ text_edit->clear_comment_delimiters();
+ for (List<String>::Element *E = comments.front(); E; E = E->next()) {
+ String comment = E->get();
+ String beg = comment.get_slice(" ", 0);
+ String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
+ text_edit->add_comment_delimiter(beg, end, end == "");
+ }
+
/* add keywords for auto completion */
// singleton autoloads (as types, just as engine singletons are)
Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
@@ -546,7 +525,7 @@ void ScriptTextEditor::_validate_script() {
bool highlight_safe = EDITOR_DEF("text_editor/highlighting/highlight_type_safe_lines", true);
bool last_is_safe = false;
for (int i = 0; i < te->get_line_count(); i++) {
- te->set_line_as_marked(i, line == i);
+ te->set_line_background_color(i, (line == i) ? marked_line_color : Color(0, 0, 0, 0));
if (highlight_safe) {
if (safe_lines.has(i + 1)) {
te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
@@ -1097,7 +1076,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
_edit_option_toggle_inline_comment();
} break;
case EDIT_COMPLETE: {
- tx->query_code_comple();
+ tx->request_code_completion(true);
} break;
case EDIT_AUTO_INDENT: {
String text = tx->get_text();
@@ -1364,9 +1343,9 @@ void ScriptTextEditor::_notification(int p_what) {
void ScriptTextEditor::_bind_methods() {
ClassDB::bind_method("_update_connected_methods", &ScriptTextEditor::_update_connected_methods);
- ClassDB::bind_method("get_drag_data_fw", &ScriptTextEditor::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw", &ScriptTextEditor::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw", &ScriptTextEditor::drop_data_fw);
+ ClassDB::bind_method("_get_drag_data_fw", &ScriptTextEditor::get_drag_data_fw);
+ ClassDB::bind_method("_can_drop_data_fw", &ScriptTextEditor::can_drop_data_fw);
+ ClassDB::bind_method("_drop_data_fw", &ScriptTextEditor::drop_data_fw);
ClassDB::bind_method(D_METHOD("add_syntax_highlighter", "highlighter"), &ScriptTextEditor::add_syntax_highlighter);
}
@@ -1379,6 +1358,10 @@ void ScriptTextEditor::clear_edit_menu() {
memdelete(edit_hb);
}
+void ScriptTextEditor::set_find_replace_bar(FindReplaceBar *p_bar) {
+ code_editor->set_find_replace_bar(p_bar);
+}
+
void ScriptTextEditor::reload(bool p_soft) {
CodeEdit *te = code_editor->get_text_editor();
Ref<Script> scr = script;
@@ -1402,6 +1385,10 @@ void ScriptTextEditor::set_tooltip_request_func(String p_method, Object *p_obj)
void ScriptTextEditor::set_debugger_active(bool p_active) {
}
+Control *ScriptTextEditor::get_base_editor() const {
+ return code_editor->get_text_editor();
+}
+
Variant ScriptTextEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
return Variant();
}
@@ -1466,11 +1453,17 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
Array files = d["files"];
String text_to_drop;
+ bool preload = Input::get_singleton()->is_key_pressed(KEY_CTRL);
for (int i = 0; i < files.size(); i++) {
if (i > 0) {
- text_to_drop += ",";
+ text_to_drop += ", ";
+ }
+
+ if (preload) {
+ text_to_drop += "preload(\"" + String(files[i]).c_escape() + "\")";
+ } else {
+ text_to_drop += "\"" + String(files[i]).c_escape() + "\"";
}
- text_to_drop += "\"" + String(files[i]).c_escape() + "\"";
}
te->cursor_set_line(row);
@@ -1835,9 +1828,7 @@ ScriptTextEditor::ScriptTextEditor() {
update_settings();
- code_editor->get_text_editor()->set_callhint_settings(
- EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
- EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
+ code_editor->get_text_editor()->set_code_hint_draw_below(EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"));
code_editor->get_text_editor()->set_select_identifiers_on_hover(true);
code_editor->get_text_editor()->set_context_menu_enabled(false);
@@ -1933,7 +1924,7 @@ void ScriptTextEditor::register_editor() {
#ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C);
#else
- ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_D);
+ ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D);
#endif
ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_E);
ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T);
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 17abfcf4cc..7bb961bf19 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -89,6 +89,8 @@ class ScriptTextEditor : public ScriptEditorBase {
Color default_line_number_color = Color(1, 1, 1);
Color safe_line_number_color = Color(1, 1, 1);
+ Color marked_line_color = Color(1, 1, 1);
+
PopupPanel *color_panel = nullptr;
ColorPicker *color_picker = nullptr;
Vector2 color_position;
@@ -231,8 +233,12 @@ public:
Control *get_edit_menu() override;
virtual void clear_edit_menu() override;
+ virtual void set_find_replace_bar(FindReplaceBar *p_bar) override;
+
static void register_editor();
+ virtual Control *get_base_editor() const override;
+
virtual void validate() override;
ScriptTextEditor();
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 3cdba9cf16..e4a5a3796e 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -37,12 +37,18 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/project_settings_editor.h"
#include "editor/property_editor.h"
#include "servers/display_server.h"
#include "servers/rendering/shader_types.h"
/*** SHADER SCRIPT EDITOR ****/
+static bool saved_warnings_enabled = false;
+static bool saved_treat_warning_as_errors = false;
+static Map<ShaderWarning::Code, bool> saved_warnings;
+static uint32_t saved_warning_flags = 0U;
+
Ref<Shader> ShaderTextEditor::get_edited_shader() const {
return shader;
}
@@ -57,6 +63,8 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) {
get_text_editor()->set_text(p_shader->get_code());
get_text_editor()->clear_undo_history();
+ get_text_editor()->call_deferred("set_h_scroll", 0);
+ get_text_editor()->call_deferred("set_v_scroll", 0);
_validate_script();
_line_col_changed();
@@ -82,54 +90,21 @@ void ShaderTextEditor::reload_text() {
update_line_and_column();
}
+void ShaderTextEditor::set_warnings_panel(RichTextLabel *p_warnings_panel) {
+ warnings_panel = p_warnings_panel;
+}
+
void ShaderTextEditor::_load_theme_settings() {
- Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
- Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
- Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
- Color completion_existing_color = EDITOR_GET("text_editor/highlighting/completion_existing_color");
- Color completion_scroll_color = EDITOR_GET("text_editor/highlighting/completion_scroll_color");
- Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
- Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
- Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
- Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
- Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
- Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
- Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
- Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
- Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
- Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
- Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
- Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
- Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
- Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
- Color executing_line_color = EDITOR_GET("text_editor/highlighting/executing_line_color");
- Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
- Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
- Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
-
- get_text_editor()->add_theme_color_override("background_color", background_color);
- get_text_editor()->add_theme_color_override("completion_background_color", completion_background_color);
- get_text_editor()->add_theme_color_override("completion_selected_color", completion_selected_color);
- get_text_editor()->add_theme_color_override("completion_existing_color", completion_existing_color);
- get_text_editor()->add_theme_color_override("completion_scroll_color", completion_scroll_color);
- get_text_editor()->add_theme_color_override("completion_font_color", completion_font_color);
- get_text_editor()->add_theme_color_override("font_color", text_color);
- get_text_editor()->add_theme_color_override("line_number_color", line_number_color);
- get_text_editor()->add_theme_color_override("caret_color", caret_color);
- get_text_editor()->add_theme_color_override("caret_background_color", caret_background_color);
- get_text_editor()->add_theme_color_override("font_selected_color", text_selected_color);
- get_text_editor()->add_theme_color_override("selection_color", selection_color);
- get_text_editor()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
- get_text_editor()->add_theme_color_override("current_line_color", current_line_color);
- get_text_editor()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
- get_text_editor()->add_theme_color_override("word_highlighted_color", word_highlighted_color);
- get_text_editor()->add_theme_color_override("mark_color", mark_color);
- get_text_editor()->add_theme_color_override("bookmark_color", bookmark_color);
- get_text_editor()->add_theme_color_override("breakpoint_color", breakpoint_color);
- get_text_editor()->add_theme_color_override("executing_line_color", executing_line_color);
- get_text_editor()->add_theme_color_override("code_folding_color", code_folding_color);
- get_text_editor()->add_theme_color_override("search_result_color", search_result_color);
- get_text_editor()->add_theme_color_override("search_result_border_color", search_result_border_color);
+ CodeEdit *text_editor = get_text_editor();
+ Color updated_marked_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
+ if (updated_marked_line_color != marked_line_color) {
+ for (int i = 0; i < text_editor->get_line_count(); i++) {
+ if (text_editor->get_line_background_color(i) == marked_line_color) {
+ text_editor->set_line_background_color(i, updated_marked_line_color);
+ }
+ }
+ marked_line_color = updated_marked_line_color;
+ }
syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color"));
syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color"));
@@ -178,6 +153,16 @@ void ShaderTextEditor::_load_theme_settings() {
syntax_highlighter->clear_color_regions();
syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
syntax_highlighter->add_color_region("//", "", comment_color, true);
+
+ text_editor->clear_comment_delimiters();
+ text_editor->add_comment_delimiter("/*", "*/", false);
+ text_editor->add_comment_delimiter("//", "", true);
+
+ if (warnings_panel) {
+ // Warnings panel
+ warnings_panel->add_theme_font_override("normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
+ warnings_panel->add_theme_font_size_override("normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("main_size", "EditorFonts"));
+ }
}
void ShaderTextEditor::_check_shader_mode() {
@@ -224,6 +209,9 @@ void ShaderTextEditor::_validate_script() {
ShaderLanguage sl;
+ sl.enable_warning_checking(saved_warnings_enabled);
+ sl.set_warning_flags(saved_warning_flags);
+
Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type);
if (err != OK) {
@@ -231,20 +219,70 @@ void ShaderTextEditor::_validate_script() {
set_error(error_text);
set_error_pos(sl.get_error_line() - 1, 0);
for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
- get_text_editor()->set_line_as_marked(i, false);
+ get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0));
}
- get_text_editor()->set_line_as_marked(sl.get_error_line() - 1, true);
-
+ get_text_editor()->set_line_background_color(sl.get_error_line() - 1, marked_line_color);
} else {
for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
- get_text_editor()->set_line_as_marked(i, false);
+ get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0));
}
set_error("");
}
+ if (warnings.size() > 0 || err != OK) {
+ warnings_panel->clear();
+ }
+ warnings.clear();
+ for (List<ShaderWarning>::Element *E = sl.get_warnings_ptr(); E; E = E->next()) {
+ warnings.push_back(E->get());
+ }
+ if (warnings.size() > 0 && err == OK) {
+ warnings.sort_custom<WarningsComparator>();
+ _update_warning_panel();
+ } else {
+ set_warning_nb(0);
+ }
emit_signal("script_changed");
}
+void ShaderTextEditor::_update_warning_panel() {
+ int warning_count = 0;
+
+ warnings_panel->push_table(2);
+ for (int i = 0; i < warnings.size(); i++) {
+ ShaderWarning &w = warnings[i];
+
+ if (warning_count == 0) {
+ if (saved_treat_warning_as_errors) {
+ String error_text = "error(" + itos(w.get_line()) + "): " + w.get_message() + " " + TTR("Warnings should be fixed to prevent errors.");
+ set_error_pos(w.get_line() - 1, 0);
+ set_error(error_text);
+ get_text_editor()->set_line_background_color(w.get_line() - 1, marked_line_color);
+ }
+ }
+
+ warning_count++;
+
+ // First cell.
+ warnings_panel->push_cell();
+ warnings_panel->push_meta(w.get_line() - 1);
+ warnings_panel->push_color(warnings_panel->get_theme_color("warning_color", "Editor"));
+ warnings_panel->add_text(TTR("Line") + " " + itos(w.get_line()));
+ warnings_panel->add_text(" (" + w.get_name() + "):");
+ warnings_panel->pop(); // Color.
+ warnings_panel->pop(); // Meta goto.
+ warnings_panel->pop(); // Cell.
+
+ // Second cell.
+ warnings_panel->push_cell();
+ warnings_panel->add_text(w.get_message());
+ warnings_panel->pop(); // Cell.
+ }
+ warnings_panel->pop(); // Table.
+
+ set_warning_nb(warning_count);
+}
+
void ShaderTextEditor::_bind_methods() {
}
@@ -314,7 +352,7 @@ void ShaderEditor::_menu_option(int p_option) {
} break;
case EDIT_COMPLETE: {
- shader_editor->get_text_editor()->query_code_comple();
+ shader_editor->get_text_editor()->request_code_completion();
} break;
case SEARCH_FIND: {
shader_editor->get_find_replace_bar()->popup_search();
@@ -358,10 +396,6 @@ void ShaderEditor::_notification(int p_what) {
}
}
-void ShaderEditor::_params_changed() {
- shader_editor->_validate_script();
-}
-
void ShaderEditor::_editor_settings_changed() {
shader_editor->update_editor_settings();
@@ -370,8 +404,19 @@ void ShaderEditor::_editor_settings_changed() {
shader_editor->get_text_editor()->set_draw_executing_lines_gutter(false);
}
+void ShaderEditor::_show_warnings_panel(bool p_show) {
+ warnings_panel->set_visible(p_show);
+}
+
+void ShaderEditor::_warning_clicked(Variant p_line) {
+ if (p_line.get_type() == Variant::INT) {
+ shader_editor->get_text_editor()->cursor_set_line(p_line.operator int64_t());
+ }
+}
+
void ShaderEditor::_bind_methods() {
- ClassDB::bind_method("_params_changed", &ShaderEditor::_params_changed);
+ ClassDB::bind_method("_show_warnings_panel", &ShaderEditor::_show_warnings_panel);
+ ClassDB::bind_method("_warning_clicked", &ShaderEditor::_warning_clicked);
}
void ShaderEditor::ensure_select_current() {
@@ -389,6 +434,47 @@ void ShaderEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
shader_editor->goto_line_selection(p_line, p_begin, p_end);
}
+void ShaderEditor::_project_settings_changed() {
+ _update_warnings(true);
+}
+
+void ShaderEditor::_update_warnings(bool p_validate) {
+ bool changed = false;
+
+ bool warnings_enabled = GLOBAL_GET("debug/shader_language/warnings/enable").booleanize();
+ if (warnings_enabled != saved_warnings_enabled) {
+ saved_warnings_enabled = warnings_enabled;
+ changed = true;
+ }
+
+ bool treat_warning_as_errors = GLOBAL_GET("debug/shader_language/warnings/treat_warnings_as_errors").booleanize();
+ if (treat_warning_as_errors != saved_treat_warning_as_errors) {
+ saved_treat_warning_as_errors = treat_warning_as_errors;
+ changed = true;
+ }
+
+ bool update_flags = false;
+
+ for (int i = 0; i < ShaderWarning::WARNING_MAX; i++) {
+ ShaderWarning::Code code = (ShaderWarning::Code)i;
+ bool value = GLOBAL_GET("debug/shader_language/warnings/" + ShaderWarning::get_name_from_code(code).to_lower());
+
+ if (saved_warnings[code] != value) {
+ saved_warnings[code] = value;
+ update_flags = true;
+ changed = true;
+ }
+ }
+
+ if (update_flags) {
+ saved_warning_flags = (uint32_t)ShaderWarning::get_flags_from_codemap(saved_warnings);
+ }
+
+ if (p_validate && changed && shader_editor && shader_editor->get_edited_shader().is_valid()) {
+ shader_editor->validate_script();
+ }
+}
+
void ShaderEditor::_check_for_external_edit() {
if (shader.is_null() || !shader.is_valid()) {
return;
@@ -560,17 +646,24 @@ void ShaderEditor::_make_context_menu(bool p_selection, Vector2 p_position) {
}
ShaderEditor::ShaderEditor(EditorNode *p_node) {
+ GLOBAL_DEF("debug/shader_language/warnings/enable", true);
+ GLOBAL_DEF("debug/shader_language/warnings/treat_warnings_as_errors", false);
+ for (int i = 0; i < (int)ShaderWarning::WARNING_MAX; i++) {
+ GLOBAL_DEF("debug/shader_language/warnings/" + ShaderWarning::get_name_from_code((ShaderWarning::Code)i).to_lower(), true);
+ }
+ _update_warnings(false);
+
shader_editor = memnew(ShaderTextEditor);
shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
shader_editor->add_theme_constant_override("separation", 0);
shader_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ shader_editor->connect("show_warnings_panel", callable_mp(this, &ShaderEditor::_show_warnings_panel));
shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders));
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &ShaderEditor::_editor_settings_changed));
+ ProjectSettingsEditor::get_singleton()->connect("confirmed", callable_mp(this, &ShaderEditor::_project_settings_changed));
- shader_editor->get_text_editor()->set_callhint_settings(
- EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
- EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
+ shader_editor->get_text_editor()->set_code_hint_draw_below(EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"));
shader_editor->get_text_editor()->set_select_identifiers_on_hover(true);
shader_editor->get_text_editor()->set_context_menu_enabled(false);
@@ -651,7 +744,28 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
hbc->add_child(goto_menu);
hbc->add_child(help_menu);
hbc->add_theme_style_override("panel", p_node->get_gui_base()->get_theme_stylebox("ScriptEditorPanel", "EditorStyles"));
- main_container->add_child(shader_editor);
+
+ VSplitContainer *editor_box = memnew(VSplitContainer);
+ main_container->add_child(editor_box);
+ editor_box->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ editor_box->set_v_size_flags(SIZE_EXPAND_FILL);
+ editor_box->add_child(shader_editor);
+
+ FindReplaceBar *bar = memnew(FindReplaceBar);
+ main_container->add_child(bar);
+ bar->hide();
+ shader_editor->set_find_replace_bar(bar);
+
+ warnings_panel = memnew(RichTextLabel);
+ warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE));
+ warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL);
+ warnings_panel->set_meta_underline(true);
+ warnings_panel->set_selection_enabled(true);
+ warnings_panel->set_focus_mode(FOCUS_CLICK);
+ warnings_panel->hide();
+ warnings_panel->connect("meta_clicked", callable_mp(this, &ShaderEditor::_warning_clicked));
+ editor_box->add_child(warnings_panel);
+ shader_editor->set_warnings_panel(warnings_panel);
goto_line_dialog = memnew(GotoLineDialog);
add_child(goto_line_dialog);
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index 731c0a5b7e..d7da73f2ae 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -35,6 +35,7 @@
#include "editor/editor_plugin.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/panel_container.h"
+#include "scene/gui/rich_text_label.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/text_edit.h"
#include "scene/main/timer.h"
@@ -44,10 +45,19 @@
class ShaderTextEditor : public CodeTextEditor {
GDCLASS(ShaderTextEditor, CodeTextEditor);
+ Color marked_line_color = Color(1, 1, 1);
+
+ struct WarningsComparator {
+ _ALWAYS_INLINE_ bool operator()(const ShaderWarning &p_a, const ShaderWarning &p_b) const { return (p_a.get_line() < p_b.get_line()); }
+ };
+
Ref<CodeHighlighter> syntax_highlighter;
+ RichTextLabel *warnings_panel = nullptr;
Ref<Shader> shader;
+ List<ShaderWarning> warnings;
void _check_shader_mode();
+ void _update_warning_panel();
protected:
static void _bind_methods();
@@ -59,6 +69,7 @@ public:
virtual void _validate_script() override;
void reload_text();
+ void set_warnings_panel(RichTextLabel *p_warnings_panel);
Ref<Shader> get_edited_shader() const;
void set_edited_shader(const Ref<Shader> &p_shader);
@@ -100,6 +111,7 @@ class ShaderEditor : public PanelContainer {
PopupMenu *bookmarks_menu;
MenuButton *help_menu;
PopupMenu *context_menu;
+ RichTextLabel *warnings_panel = nullptr;
uint64_t idle;
GotoLineDialog *goto_line_dialog;
@@ -109,13 +121,16 @@ class ShaderEditor : public PanelContainer {
ShaderTextEditor *shader_editor;
void _menu_option(int p_option);
- void _params_changed();
mutable Ref<Shader> shader;
void _editor_settings_changed();
+ void _project_settings_changed();
void _check_for_external_edit();
void _reload_shader_from_disk();
+ void _show_warnings_panel(bool p_show);
+ void _warning_clicked(Variant p_line);
+ void _update_warnings(bool p_validate);
protected:
void _notification(int p_what);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 404ef62eca..a97584ebce 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -95,7 +95,7 @@ void BoneTransformEditor::create_editors() {
section->get_vbox()->add_child(transform_section);
// Transform/Matrix property
- transform_property = memnew(EditorPropertyTransform());
+ transform_property = memnew(EditorPropertyTransform3D());
transform_property->setup(-10000, 10000, 0.001f, true);
transform_property->set_label("Transform");
transform_property->set_use_folding(true);
@@ -171,7 +171,7 @@ void BoneTransformEditor::_value_changed(const double p_value) {
return;
}
- Transform tform = compute_transform_from_vector3s();
+ Transform3D tform = compute_transform_from_vector3s();
_change_transform(tform);
}
@@ -179,30 +179,30 @@ void BoneTransformEditor::_value_changed_vector3(const String p_property_name, c
if (updating) {
return;
}
- Transform tform = compute_transform_from_vector3s();
+ Transform3D tform = compute_transform_from_vector3s();
_change_transform(tform);
}
-Transform BoneTransformEditor::compute_transform_from_vector3s() const {
+Transform3D BoneTransformEditor::compute_transform_from_vector3s() const {
// Convert rotation from degrees to radians.
Vector3 prop_rotation = rotation_property->get_vector();
prop_rotation.x = Math::deg2rad(prop_rotation.x);
prop_rotation.y = Math::deg2rad(prop_rotation.y);
prop_rotation.z = Math::deg2rad(prop_rotation.z);
- return Transform(
+ return Transform3D(
Basis(prop_rotation, scale_property->get_vector()),
translation_property->get_vector());
}
-void BoneTransformEditor::_value_changed_transform(const String p_property_name, const Transform p_transform, const StringName p_edited_property_name, const bool p_boolean) {
+void BoneTransformEditor::_value_changed_transform(const String p_property_name, const Transform3D p_transform, const StringName p_edited_property_name, const bool p_boolean) {
if (updating) {
return;
}
_change_transform(p_transform);
}
-void BoneTransformEditor::_change_transform(Transform p_new_transform) {
+void BoneTransformEditor::_change_transform(Transform3D p_new_transform) {
if (property.get_slicec('/', 0) == "bones" && property.get_slicec('/', 2) == "custom_pose") {
undo_redo->create_action(TTR("Set Custom Bone Pose Transform"), UndoRedo::MERGE_ENDS);
undo_redo->add_undo_method(skeleton, "set_bone_custom_pose", property.get_slicec('/', 1).to_int(), skeleton->get_bone_custom_pose(property.get_slicec('/', 1).to_int()));
@@ -235,7 +235,7 @@ void BoneTransformEditor::_update_properties() {
updating = true;
- Transform tform = skeleton->get(property);
+ Transform3D tform = skeleton->get(property);
_update_transform_properties(tform);
}
@@ -250,11 +250,11 @@ void BoneTransformEditor::_update_custom_pose_properties() {
updating = true;
- Transform tform = skeleton->get_bone_custom_pose(property.to_int());
+ Transform3D tform = skeleton->get_bone_custom_pose(property.to_int());
_update_transform_properties(tform);
}
-void BoneTransformEditor::_update_transform_properties(Transform tform) {
+void BoneTransformEditor::_update_transform_properties(Transform3D tform) {
Basis rotation_basis = tform.get_basis();
Vector3 rotation_radians = rotation_basis.get_rotation_euler();
Vector3 rotation_degrees = Vector3(Math::rad2deg(rotation_radians.x), Math::rad2deg(rotation_radians.y), Math::rad2deg(rotation_radians.z));
@@ -306,7 +306,7 @@ void BoneTransformEditor::_key_button_pressed() {
}
// Need to normalize the basis before you key it
- Transform tform = compute_transform_from_vector3s();
+ Transform3D tform = compute_transform_from_vector3s();
tform.orthonormalize();
AnimationPlayerEditor::singleton->get_track_editor()->insert_transform_key(skeleton, name, tform);
}
@@ -380,7 +380,7 @@ void Skeleton3DEditor::create_physical_skeleton() {
}
PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos) {
- const Transform child_rest = skeleton->get_bone_rest(bone_child_id);
+ const Transform3D child_rest = skeleton->get_bone_rest(bone_child_id);
const real_t half_height(child_rest.origin.length() * 0.5);
const real_t radius(half_height * 0.2);
@@ -392,15 +392,15 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi
CollisionShape3D *bone_shape = memnew(CollisionShape3D);
bone_shape->set_shape(bone_shape_capsule);
- Transform capsule_transform;
+ Transform3D capsule_transform;
capsule_transform.basis = Basis(Vector3(1, 0, 0), Vector3(0, 0, 1), Vector3(0, -1, 0));
bone_shape->set_transform(capsule_transform);
- Transform body_transform;
+ Transform3D body_transform;
body_transform.set_look_at(Vector3(0, 0, 0), child_rest.origin);
body_transform.origin = body_transform.basis.xform(Vector3(0, 0, -half_height));
- Transform joint_transform;
+ Transform3D joint_transform;
joint_transform.origin = Vector3(0, 0, half_height);
PhysicalBone3D *physical_bone = memnew(PhysicalBone3D);
@@ -666,9 +666,9 @@ void Skeleton3DEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_properties"), &Skeleton3DEditor::_update_properties);
ClassDB::bind_method(D_METHOD("_on_click_option"), &Skeleton3DEditor::_on_click_option);
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &Skeleton3DEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &Skeleton3DEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &Skeleton3DEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &Skeleton3DEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &Skeleton3DEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &Skeleton3DEditor::drop_data_fw);
ClassDB::bind_method(D_METHOD("move_skeleton_bone"), &Skeleton3DEditor::move_skeleton_bone);
}
diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h
index 14c213f7b2..9de52c6fa8 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.h
+++ b/editor/plugins/skeleton_3d_editor_plugin.h
@@ -41,7 +41,7 @@ class PhysicalBone3D;
class Skeleton3DEditorPlugin;
class Button;
class CheckBox;
-class EditorPropertyTransform;
+class EditorPropertyTransform3D;
class EditorPropertyVector3;
class BoneTransformEditor : public VBoxContainer {
@@ -53,7 +53,7 @@ class BoneTransformEditor : public VBoxContainer {
EditorPropertyVector3 *rotation_property = nullptr;
EditorPropertyVector3 *scale_property = nullptr;
EditorInspectorSection *transform_section = nullptr;
- EditorPropertyTransform *transform_property = nullptr;
+ EditorPropertyTransform3D *transform_property = nullptr;
Rect2 background_rects[5];
@@ -78,11 +78,11 @@ class BoneTransformEditor : public VBoxContainer {
// Called when the one of the EditorPropertyVector3 are updated.
void _value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean);
// Called when the transform_property is updated.
- void _value_changed_transform(const String p_property_name, const Transform p_transform, const StringName p_edited_property_name, const bool p_boolean);
+ void _value_changed_transform(const String p_property_name, const Transform3D p_transform, const StringName p_edited_property_name, const bool p_boolean);
// Changes the transform to the given transform and updates the UI accordingly.
- void _change_transform(Transform p_new_transform);
+ void _change_transform(Transform3D p_new_transform);
// Creates a Transform using the EditorPropertyVector3 properties.
- Transform compute_transform_from_vector3s() const;
+ Transform3D compute_transform_from_vector3s() const;
void update_enabled_checkbox();
@@ -98,7 +98,7 @@ public:
void _update_properties();
void _update_custom_pose_properties();
- void _update_transform_properties(Transform p_transform);
+ void _update_transform_properties(Transform3D p_transform);
// Can/cannot modify the spinner values for the Transform
void set_read_only(const bool p_read_only);
@@ -127,7 +127,7 @@ class Skeleton3DEditor : public VBoxContainer {
struct BoneInfo {
PhysicalBone3D *physical_bone = nullptr;
- Transform relative_rest; // Relative to skeleton node
+ Transform3D relative_rest; // Relative to skeleton node
};
EditorNode *editor;
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index bd6dac7490..a5a3d624ec 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -115,7 +115,7 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
int idx = h * y + x;
- if (mb->get_shift() && last_frame_selected >= 0) {
+ if (mb->is_shift_pressed() && last_frame_selected >= 0) {
//select multiple
int from = idx;
int to = last_frame_selected;
@@ -124,7 +124,7 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
}
for (int i = from; i <= to; i++) {
- if (mb->get_control()) {
+ if (mb->is_ctrl_pressed()) {
frames_selected.erase(i);
} else {
frames_selected.insert(i);
@@ -150,11 +150,11 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {
// Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer
// to allow performing this action anywhere, even if the cursor isn't
// hovering the texture in the workspace.
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) {
_sheet_zoom_in();
// Don't scroll up after zooming in.
accept_event();
- } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) {
_sheet_zoom_out();
// Don't scroll down after zooming out.
accept_event();
@@ -220,7 +220,7 @@ void SpriteFramesEditor::_sheet_zoom_out() {
void SpriteFramesEditor::_sheet_zoom_reset() {
// Default the zoom to match the editor scale, but don't dezoom on editor scales below 100% to prevent pixel art from looking bad.
- sheet_zoom = MAX(1.0, EDSCALE);
+ sheet_zoom = MAX(1.0f, EDSCALE);
Size2 texture_size = split_sheet_preview->get_texture()->get_size();
split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom);
}
@@ -252,10 +252,10 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
EditorNode::get_singleton()->show_warning(TTR("Unable to load images"));
ERR_FAIL_COND(!texture.is_valid());
}
- bool new_texture = texture != split_sheet_preview->get_texture();
frames_selected.clear();
last_frame_selected = -1;
+ bool new_texture = texture != split_sheet_preview->get_texture();
split_sheet_preview->set_texture(texture);
if (new_texture) {
//different texture, reset to 4x4
@@ -280,17 +280,17 @@ void SpriteFramesEditor::_notification(int p_what) {
move_down->set_icon(get_theme_icon("MoveRight", "EditorIcons"));
_delete->set_icon(get_theme_icon("Remove", "EditorIcons"));
zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
- zoom_1->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
+ zoom_reset->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
new_anim->set_icon(get_theme_icon("New", "EditorIcons"));
remove_anim->set_icon(get_theme_icon("Remove", "EditorIcons"));
split_sheet_zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
- split_sheet_zoom_1->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
+ split_sheet_zoom_reset->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
split_sheet_zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
- splite_sheet_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
+ split_sheet_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
} break;
case NOTIFICATION_READY: {
add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up.
@@ -513,7 +513,7 @@ void SpriteFramesEditor::_animation_select() {
if (frames->has_animation(edited_anim)) {
double value = anim_speed->get_line_edit()->get_text().to_float();
- if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim))) {
+ if (!Math::is_equal_approx(value, (double)frames->get_animation_speed(edited_anim))) {
_animation_fps_changed(value);
}
}
@@ -694,11 +694,11 @@ void SpriteFramesEditor::_tree_input(const Ref<InputEvent> &p_event) {
const Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) {
_zoom_in();
// Don't scroll up after zooming in.
accept_event();
- } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) {
_zoom_out();
// Don't scroll down after zooming out.
accept_event();
@@ -733,7 +733,7 @@ void SpriteFramesEditor::_zoom_out() {
}
void SpriteFramesEditor::_zoom_reset() {
- thumbnail_zoom = MAX(1.0, EDSCALE);
+ thumbnail_zoom = MAX(1.0f, EDSCALE);
tree->set_fixed_column_width(thumbnail_default_size * 3 / 2);
tree->set_fixed_icon_size(Size2(thumbnail_default_size, thumbnail_default_size));
}
@@ -954,7 +954,7 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
if (String(d["type"]) == "files") {
Vector<String> files = d["files"];
- if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
_prepare_sprite_sheet(files[0]);
} else {
_file_load_request(files, at_pos);
@@ -964,9 +964,9 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
void SpriteFramesEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_library", "skipsel"), &SpriteFramesEditor::_update_library, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SpriteFramesEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpriteFramesEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &SpriteFramesEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &SpriteFramesEditor::drop_data_fw);
}
SpriteFramesEditor::SpriteFramesEditor() {
@@ -1086,11 +1086,13 @@ SpriteFramesEditor::SpriteFramesEditor() {
zoom_out->set_flat(true);
zoom_out->set_tooltip(TTR("Zoom Out"));
hbc->add_child(zoom_out);
- zoom_1 = memnew(Button);
- zoom_1->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_reset));
- zoom_1->set_flat(true);
- zoom_1->set_tooltip(TTR("Zoom Reset"));
- hbc->add_child(zoom_1);
+
+ zoom_reset = memnew(Button);
+ zoom_reset->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_reset));
+ zoom_reset->set_flat(true);
+ zoom_reset->set_tooltip(TTR("Zoom Reset"));
+ hbc->add_child(zoom_reset);
+
zoom_in = memnew(Button);
zoom_in->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_in));
zoom_in->set_flat(true);
@@ -1183,16 +1185,16 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_preview->connect("draw", callable_mp(this, &SpriteFramesEditor::_sheet_preview_draw));
split_sheet_preview->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_preview_input));
- splite_sheet_scroll = memnew(ScrollContainer);
- splite_sheet_scroll->set_enable_h_scroll(true);
- splite_sheet_scroll->set_enable_v_scroll(true);
- splite_sheet_scroll->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_scroll_input));
- split_sheet_panel->add_child(splite_sheet_scroll);
+ split_sheet_scroll = memnew(ScrollContainer);
+ split_sheet_scroll->set_enable_h_scroll(true);
+ split_sheet_scroll->set_enable_v_scroll(true);
+ split_sheet_scroll->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_scroll_input));
+ split_sheet_panel->add_child(split_sheet_scroll);
CenterContainer *cc = memnew(CenterContainer);
cc->add_child(split_sheet_preview);
cc->set_h_size_flags(SIZE_EXPAND_FILL);
cc->set_v_size_flags(SIZE_EXPAND_FILL);
- splite_sheet_scroll->add_child(cc);
+ split_sheet_scroll->add_child(cc);
MarginContainer *split_sheet_zoom_margin = memnew(MarginContainer);
split_sheet_panel->add_child(split_sheet_zoom_margin);
@@ -1209,12 +1211,14 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_zoom_out->set_tooltip(TTR("Zoom Out"));
split_sheet_zoom_out->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_out));
split_sheet_zoom_hb->add_child(split_sheet_zoom_out);
- split_sheet_zoom_1 = memnew(Button);
- split_sheet_zoom_1->set_flat(true);
- split_sheet_zoom_1->set_focus_mode(FOCUS_NONE);
- split_sheet_zoom_1->set_tooltip(TTR("Zoom Reset"));
- split_sheet_zoom_1->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_reset));
- split_sheet_zoom_hb->add_child(split_sheet_zoom_1);
+
+ split_sheet_zoom_reset = memnew(Button);
+ split_sheet_zoom_reset->set_flat(true);
+ split_sheet_zoom_reset->set_focus_mode(FOCUS_NONE);
+ split_sheet_zoom_reset->set_tooltip(TTR("Zoom Reset"));
+ split_sheet_zoom_reset->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_reset));
+ split_sheet_zoom_hb->add_child(split_sheet_zoom_reset);
+
split_sheet_zoom_in = memnew(Button);
split_sheet_zoom_in->set_flat(true);
split_sheet_zoom_in->set_focus_mode(FOCUS_NONE);
@@ -1230,14 +1234,14 @@ SpriteFramesEditor::SpriteFramesEditor() {
// Config scale.
scale_ratio = 1.2f;
- thumbnail_default_size = 96 * MAX(1.0, EDSCALE);
- thumbnail_zoom = MAX(1.0, EDSCALE);
- max_thumbnail_zoom = 8.0f * MAX(1.0, EDSCALE);
- min_thumbnail_zoom = 0.1f * MAX(1.0, EDSCALE);
+ thumbnail_default_size = 96 * MAX(1, EDSCALE);
+ thumbnail_zoom = MAX(1.0f, EDSCALE);
+ max_thumbnail_zoom = 8.0f * MAX(1.0f, EDSCALE);
+ min_thumbnail_zoom = 0.1f * MAX(1.0f, EDSCALE);
// Default the zoom to match the editor scale, but don't dezoom on editor scales below 100% to prevent pixel art from looking bad.
- sheet_zoom = MAX(1.0, EDSCALE);
- max_sheet_zoom = 16.0f * MAX(1.0, EDSCALE);
- min_sheet_zoom = 0.01f * MAX(1.0, EDSCALE);
+ sheet_zoom = MAX(1.0f, EDSCALE);
+ max_sheet_zoom = 16.0f * MAX(1.0f, EDSCALE);
+ min_sheet_zoom = 0.01f * MAX(1.0f, EDSCALE);
_zoom_reset();
}
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index bbc26ca726..77cdbb4af6 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -54,13 +54,12 @@ class SpriteFramesEditor : public HSplitContainer {
Button *move_up;
Button *move_down;
Button *zoom_out;
- Button *zoom_1;
+ Button *zoom_reset;
Button *zoom_in;
ItemList *tree;
bool loading_scene;
int sel;
- HSplitContainer *split;
Button *new_anim;
Button *remove_anim;
@@ -79,12 +78,12 @@ class SpriteFramesEditor : public HSplitContainer {
ConfirmationDialog *delete_dialog;
ConfirmationDialog *split_sheet_dialog;
- ScrollContainer *splite_sheet_scroll;
+ ScrollContainer *split_sheet_scroll;
TextureRect *split_sheet_preview;
SpinBox *split_sheet_h;
SpinBox *split_sheet_v;
Button *split_sheet_zoom_out;
- Button *split_sheet_zoom_1;
+ Button *split_sheet_zoom_reset;
Button *split_sheet_zoom_in;
EditorFileDialog *file_split_sheet;
Set<int> frames_selected;
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 2b8bfe067d..dc7f85a790 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -59,58 +59,7 @@ void TextEditor::_change_syntax_highlighter(int p_idx) {
}
void TextEditor::_load_theme_settings() {
- CodeEdit *text_edit = code_editor->get_text_editor();
- text_edit->get_syntax_highlighter()->update_cache();
-
- Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
- Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
- Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
- Color completion_existing_color = EDITOR_GET("text_editor/highlighting/completion_existing_color");
- Color completion_scroll_color = EDITOR_GET("text_editor/highlighting/completion_scroll_color");
- Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
- Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
- Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
- Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
- Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
- Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
- Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
- Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
- Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
- Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
- Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
- Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
- Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
- Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
- Color executing_line_color = EDITOR_GET("text_editor/highlighting/executing_line_color");
- Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
- Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
- Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
-
- text_edit->add_theme_color_override("background_color", background_color);
- text_edit->add_theme_color_override("completion_background_color", completion_background_color);
- text_edit->add_theme_color_override("completion_selected_color", completion_selected_color);
- text_edit->add_theme_color_override("completion_existing_color", completion_existing_color);
- text_edit->add_theme_color_override("completion_scroll_color", completion_scroll_color);
- text_edit->add_theme_color_override("completion_font_color", completion_font_color);
- text_edit->add_theme_color_override("font_color", text_color);
- text_edit->add_theme_color_override("line_number_color", line_number_color);
- text_edit->add_theme_color_override("caret_color", caret_color);
- text_edit->add_theme_color_override("caret_background_color", caret_background_color);
- text_edit->add_theme_color_override("font_selected_color", text_selected_color);
- text_edit->add_theme_color_override("selection_color", selection_color);
- text_edit->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
- text_edit->add_theme_color_override("current_line_color", current_line_color);
- text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
- text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
- text_edit->add_theme_color_override("breakpoint_color", breakpoint_color);
- text_edit->add_theme_color_override("executing_line_color", executing_line_color);
- text_edit->add_theme_color_override("mark_color", mark_color);
- text_edit->add_theme_color_override("bookmark_color", bookmark_color);
- text_edit->add_theme_color_override("code_folding_color", code_folding_color);
- text_edit->add_theme_color_override("search_result_color", search_result_color);
- text_edit->add_theme_color_override("search_result_border_color", search_result_border_color);
-
- text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
+ code_editor->get_text_editor()->get_syntax_highlighter()->update_cache();
}
String TextEditor::get_name() {
@@ -171,6 +120,10 @@ void TextEditor::add_callback(const String &p_function, PackedStringArray p_args
void TextEditor::set_debugger_active(bool p_active) {
}
+Control *TextEditor::get_base_editor() const {
+ return code_editor->get_text_editor();
+}
+
Array TextEditor::get_breakpoints() {
return Array();
}
@@ -328,6 +281,10 @@ void TextEditor::clear_edit_menu() {
memdelete(edit_hb);
}
+void TextEditor::set_find_replace_bar(FindReplaceBar *p_bar) {
+ code_editor->set_find_replace_bar(p_bar);
+}
+
void TextEditor::_edit_option(int p_op) {
CodeEdit *tx = code_editor->get_text_editor();
@@ -585,7 +542,7 @@ TextEditor::TextEditor() {
edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &TextEditor::_edit_option));
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("un_redo"), EDIT_REDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY);
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index c066d51b18..4e667dc676 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -139,9 +139,12 @@ public:
virtual Control *get_edit_menu() override;
virtual void clear_edit_menu() override;
+ virtual void set_find_replace_bar(FindReplaceBar *p_bar) override;
virtual void validate() override;
+ virtual Control *get_base_editor() const override;
+
static void register_editor();
TextEditor();
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 7b927ad98b..686ff0f9ef 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -331,7 +331,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
if (E->get().has_point(point)) {
rect = E->get();
- if (Input::get_singleton()->is_key_pressed(KEY_CONTROL) && !(Input::get_singleton()->is_key_pressed(KEY_SHIFT | KEY_ALT))) {
+ if (Input::get_singleton()->is_key_pressed(KEY_CTRL) && !(Input::get_singleton()->is_key_pressed(KEY_SHIFT | KEY_ALT))) {
Rect2 r;
if (node_sprite) {
r = node_sprite->get_region_rect();
@@ -863,13 +863,13 @@ Sprite2D *TextureRegionEditor::get_sprite() {
void TextureRegionEditor::edit(Object *p_obj) {
if (node_sprite) {
- node_sprite->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
+ node_sprite->disconnect("texture_changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
if (node_sprite_3d) {
- node_sprite_3d->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
+ node_sprite_3d->disconnect("texture_changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
if (node_ninepatch) {
- node_ninepatch->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
+ node_ninepatch->disconnect("texture_changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
if (obj_styleBox.is_valid()) {
obj_styleBox->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
@@ -881,13 +881,22 @@ void TextureRegionEditor::edit(Object *p_obj) {
node_sprite = Object::cast_to<Sprite2D>(p_obj);
node_sprite_3d = Object::cast_to<Sprite3D>(p_obj);
node_ninepatch = Object::cast_to<NinePatchRect>(p_obj);
+
+ bool is_resource = false;
if (Object::cast_to<StyleBoxTexture>(p_obj)) {
obj_styleBox = Ref<StyleBoxTexture>(Object::cast_to<StyleBoxTexture>(p_obj));
+ is_resource = true;
}
if (Object::cast_to<AtlasTexture>(p_obj)) {
atlas_tex = Ref<AtlasTexture>(Object::cast_to<AtlasTexture>(p_obj));
+ is_resource = true;
+ }
+
+ if (is_resource) {
+ p_obj->connect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
+ } else {
+ p_obj->connect("texture_changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
- p_obj->connect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
_edit_region();
} else {
node_sprite = nullptr;
@@ -937,7 +946,6 @@ void TextureRegionEditor::_edit_region() {
if (cache_map.has(texture->get_rid())) {
autoslice_cache = cache_map[texture->get_rid()];
autoslice_is_dirty = false;
- return;
} else {
if (is_visible() && snap_mode == SNAP_AUTOSLICE) {
_update_autoslice();
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 0f7468bead..6607bf6cad 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -30,12 +30,10 @@
#include "theme_editor_plugin.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
-#include "core/version.h"
+#include "editor/editor_resource_picker.h"
#include "editor/editor_scale.h"
#include "editor/progress_dialog.h"
-#include "scene/gui/progress_bar.h"
void ThemeItemImportTree::_update_items_tree() {
import_items_tree->clear();
@@ -321,7 +319,7 @@ void ThemeItemImportTree::_toggle_type_items(bool p_collapse) {
return;
}
- TreeItem *type_node = root->get_children();
+ TreeItem *type_node = root->get_first_child();
while (type_node) {
type_node->set_collapsed(p_collapse);
type_node = type_node->get_next();
@@ -491,7 +489,7 @@ void ThemeItemImportTree::_tree_item_edited() {
}
void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) {
- TreeItem *child_item = p_root_item->get_children();
+ TreeItem *child_item = p_root_item->get_first_child();
while (child_item) {
child_item->set_checked(IMPORT_ITEM, true);
if (p_select_with_data) {
@@ -505,7 +503,7 @@ void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_sel
}
void ThemeItemImportTree::_deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely) {
- TreeItem *child_item = p_root_item->get_children();
+ TreeItem *child_item = p_root_item->get_first_child();
while (child_item) {
child_item->set_checked(IMPORT_ITEM_DATA, false);
if (p_deselect_completely) {
@@ -527,7 +525,7 @@ void ThemeItemImportTree::_update_parent_items(TreeItem *p_root_item) {
bool any_checked = false;
bool any_checked_with_data = false;
- TreeItem *child_item = parent_item->get_children();
+ TreeItem *child_item = parent_item->get_first_child();
while (child_item) {
if (child_item->is_checked(IMPORT_ITEM)) {
any_checked = true;
@@ -756,7 +754,9 @@ void ThemeItemImportTree::_import_selected() {
return;
}
- ProgressDialog::get_singleton()->add_task("import_theme_items", TTR("Importing Theme Items"), selected_items.size());
+ // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ edited_theme->_freeze_change_propagation();
+ ProgressDialog::get_singleton()->add_task("import_theme_items", TTR("Importing Theme Items"), selected_items.size() + 2);
int idx = 0;
for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) {
@@ -814,6 +814,12 @@ void ThemeItemImportTree::_import_selected() {
idx++;
}
+ // Allow changes to be reported now that the operation is finished.
+ ProgressDialog::get_singleton()->task_step("import_theme_items", TTR("Updating the editor"), idx++);
+ edited_theme->_unfreeze_and_propagate_changes();
+ // Make sure the task is not ended before the editor freezes to update the Inspector.
+ ProgressDialog::get_singleton()->task_step("import_theme_items", TTR("Finalizing"), idx++);
+
ProgressDialog::get_singleton()->end_task("import_theme_items");
emit_signal("items_imported");
}
@@ -1201,7 +1207,7 @@ void ThemeItemEditorDialog::_close_dialog() {
}
void ThemeItemEditorDialog::_dialog_about_to_show() {
- ERR_FAIL_COND(edited_theme.is_null());
+ ERR_FAIL_COND_MSG(edited_theme.is_null(), "Invalid state of the Theme Editor; the Theme resource is missing.");
_update_edit_types();
@@ -1458,6 +1464,9 @@ void ThemeItemEditorDialog::_add_theme_type() {
edited_theme->add_color_type(edit_add_type_value->get_text());
edited_theme->add_constant_type(edit_add_type_value->get_text());
_update_edit_types();
+
+ // Force emit a change so that other parts of the editor can update.
+ edited_theme->emit_changed();
}
void ThemeItemEditorDialog::_add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type) {
@@ -1488,15 +1497,24 @@ void ThemeItemEditorDialog::_add_theme_item(Theme::DataType p_data_type, String
void ThemeItemEditorDialog::_remove_data_type_items(Theme::DataType p_data_type, String p_item_type) {
List<StringName> names;
+ // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ edited_theme->_freeze_change_propagation();
+
edited_theme->get_theme_item_list(p_data_type, p_item_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
edited_theme->clear_theme_item(p_data_type, E->get(), p_item_type);
}
+
+ // Allow changes to be reported now that the operation is finished.
+ edited_theme->_unfreeze_and_propagate_changes();
}
void ThemeItemEditorDialog::_remove_class_items() {
List<StringName> names;
+ // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ edited_theme->_freeze_change_propagation();
+
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
Theme::DataType data_type = (Theme::DataType)dt;
@@ -1509,12 +1527,18 @@ void ThemeItemEditorDialog::_remove_class_items() {
}
}
+ // Allow changes to be reported now that the operation is finished.
+ edited_theme->_unfreeze_and_propagate_changes();
+
_update_edit_item_tree(edited_item_type);
}
void ThemeItemEditorDialog::_remove_custom_items() {
List<StringName> names;
+ // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ edited_theme->_freeze_change_propagation();
+
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
Theme::DataType data_type = (Theme::DataType)dt;
@@ -1527,12 +1551,18 @@ void ThemeItemEditorDialog::_remove_custom_items() {
}
}
+ // Allow changes to be reported now that the operation is finished.
+ edited_theme->_unfreeze_and_propagate_changes();
+
_update_edit_item_tree(edited_item_type);
}
void ThemeItemEditorDialog::_remove_all_items() {
List<StringName> names;
+ // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ edited_theme->_freeze_change_propagation();
+
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
Theme::DataType data_type = (Theme::DataType)dt;
@@ -1543,6 +1573,9 @@ void ThemeItemEditorDialog::_remove_all_items() {
}
}
+ // Allow changes to be reported now that the operation is finished.
+ edited_theme->_unfreeze_and_propagate_changes();
+
_update_edit_item_tree(edited_item_type);
}
@@ -1907,268 +1940,1310 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog));
}
+VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
+ VBoxContainer *items_tab = memnew(VBoxContainer);
+ items_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
+ data_type_tabs->add_child(items_tab);
+ data_type_tabs->set_tab_title(data_type_tabs->get_tab_count() - 1, "");
+
+ ScrollContainer *items_sc = memnew(ScrollContainer);
+ items_sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ items_sc->set_enable_h_scroll(false);
+ items_tab->add_child(items_sc);
+ VBoxContainer *items_list = memnew(VBoxContainer);
+ items_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ items_sc->add_child(items_list);
+
+ HBoxContainer *item_add_hb = memnew(HBoxContainer);
+ items_tab->add_child(item_add_hb);
+ LineEdit *item_add_edit = memnew(LineEdit);
+ item_add_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_add_hb->add_child(item_add_edit);
+ item_add_edit->connect("text_entered", callable_mp(this, &ThemeTypeEditor::_item_add_lineedit_cbk), varray(p_data_type, item_add_edit));
+ Button *item_add_button = memnew(Button);
+ item_add_button->set_text(TTR("Add"));
+ item_add_hb->add_child(item_add_button);
+ item_add_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_add_cbk), varray(p_data_type, item_add_edit));
+
+ return items_list;
+}
+
+void ThemeTypeEditor::_update_type_list() {
+ ERR_FAIL_COND(edited_theme.is_null());
+
+ if (updating) {
+ return;
+ }
+ updating = true;
+
+ Control *focused = get_focus_owner();
+ if (focused) {
+ if (focusables.has(focused)) {
+ // If focus is currently on one of the internal property editors, don't update.
+ updating = false;
+ return;
+ }
+
+ Node *focus_parent = focused->get_parent();
+ while (focus_parent) {
+ Control *c = Object::cast_to<Control>(focus_parent);
+ if (c && focusables.has(c)) {
+ // If focus is currently on one of the internal property editors, don't update.
+ updating = false;
+ return;
+ }
+
+ focus_parent = focus_parent->get_parent();
+ }
+ }
+
+ List<StringName> theme_types;
+ edited_theme->get_type_list(&theme_types);
+ theme_types.sort_custom<StringName::AlphCompare>();
+
+ theme_type_list->clear();
+
+ if (theme_types.size() > 0) {
+ theme_type_list->set_disabled(false);
+
+ bool item_reselected = false;
+ int e_idx = 0;
+ for (List<StringName>::Element *E = theme_types.front(); E; E = E->next()) {
+ Ref<Texture2D> item_icon;
+ if (E->get() == "") {
+ item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
+ } else {
+ item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
+ }
+ theme_type_list->add_icon_item(item_icon, E->get());
+
+ if (E->get() == edited_type) {
+ theme_type_list->select(e_idx);
+ item_reselected = true;
+ }
+ e_idx++;
+ }
+
+ if (!item_reselected) {
+ theme_type_list->select(0);
+ _list_type_selected(0);
+ } else {
+ _update_type_items();
+ }
+ } else {
+ theme_type_list->set_disabled(true);
+ theme_type_list->add_item(TTR("None"));
+
+ edited_type = "";
+ _update_type_items();
+ }
+
+ updating = false;
+}
+
+void ThemeTypeEditor::_update_type_list_debounced() {
+ update_debounce_timer->start();
+}
+
+void ThemeTypeEditor::_update_add_type_options(const String &p_filter) {
+ add_type_options->clear();
+
+ List<StringName> names;
+ Theme::get_default()->get_type_list(&names);
+ names.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ if (!p_filter.is_subsequence_ofi(String(E->get()))) {
+ continue;
+ }
+
+ Ref<Texture2D> item_icon;
+ if (E->get() == "") {
+ item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
+ } else {
+ item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
+ }
+
+ add_type_options->add_item(E->get(), item_icon);
+ }
+}
+
+OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) {
+ OrderedHashMap<StringName, bool> items;
+ List<StringName> names;
+
+ if (include_default) {
+ names.clear();
+ (Theme::get_default().operator->()->*get_list_func)(p_type_name, &names);
+ names.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ items[E->get()] = false;
+ }
+ }
+
+ {
+ names.clear();
+ (edited_theme.operator->()->*get_list_func)(p_type_name, &names);
+ names.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ items[E->get()] = true;
+ }
+ }
+
+ List<StringName> keys;
+ for (OrderedHashMap<StringName, bool>::Element E = items.front(); E; E = E.next()) {
+ keys.push_back(E.key());
+ }
+ keys.sort_custom<StringName::AlphCompare>();
+
+ OrderedHashMap<StringName, bool> ordered_items;
+ for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
+ ordered_items[E->get()] = items[E->get()];
+ }
+
+ return ordered_items;
+}
+
+HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable) {
+ HBoxContainer *item_control = memnew(HBoxContainer);
+
+ HBoxContainer *item_name_container = memnew(HBoxContainer);
+ item_name_container->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_name_container->set_stretch_ratio(2.0);
+ item_control->add_child(item_name_container);
+
+ Label *item_name = memnew(Label);
+ item_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_name->set_clip_text(true);
+ item_name->set_text(p_item_name);
+ item_name->set_tooltip(p_item_name);
+ item_name_container->add_child(item_name);
+
+ if (p_editable) {
+ LineEdit *item_name_edit = memnew(LineEdit);
+ item_name_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_name_edit->set_text(p_item_name);
+ item_name_container->add_child(item_name_edit);
+ item_name_edit->connect("text_entered", callable_mp(this, &ThemeTypeEditor::_item_rename_entered), varray(p_data_type, p_item_name, item_name_container));
+ item_name_edit->hide();
+
+ Button *item_rename_button = memnew(Button);
+ item_rename_button->set_icon(get_theme_icon("Edit", "EditorIcons"));
+ item_rename_button->set_tooltip(TTR("Rename Item"));
+ item_rename_button->set_flat(true);
+ item_name_container->add_child(item_rename_button);
+ item_rename_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_cbk), varray(p_data_type, p_item_name, item_name_container));
+
+ Button *item_remove_button = memnew(Button);
+ item_remove_button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ item_remove_button->set_tooltip(TTR("Remove Item"));
+ item_remove_button->set_flat(true);
+ item_name_container->add_child(item_remove_button);
+ item_remove_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_remove_cbk), varray(p_data_type, p_item_name));
+
+ Button *item_rename_confirm_button = memnew(Button);
+ item_rename_confirm_button->set_icon(get_theme_icon("ImportCheck", "EditorIcons"));
+ item_rename_confirm_button->set_tooltip(TTR("Confirm Item Rename"));
+ item_rename_confirm_button->set_flat(true);
+ item_name_container->add_child(item_rename_confirm_button);
+ item_rename_confirm_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_confirmed), varray(p_data_type, p_item_name, item_name_container));
+ item_rename_confirm_button->hide();
+
+ Button *item_rename_cancel_button = memnew(Button);
+ item_rename_cancel_button->set_icon(get_theme_icon("ImportFail", "EditorIcons"));
+ item_rename_cancel_button->set_tooltip(TTR("Cancel Item Rename"));
+ item_rename_cancel_button->set_flat(true);
+ item_name_container->add_child(item_rename_cancel_button);
+ item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled), varray(p_data_type, p_item_name, item_name_container));
+ item_rename_cancel_button->hide();
+ } else {
+ item_name->add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor"));
+
+ Button *item_override_button = memnew(Button);
+ item_override_button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ item_override_button->set_tooltip(TTR("Override Item"));
+ item_override_button->set_flat(true);
+ item_name_container->add_child(item_override_button);
+ item_override_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_override_cbk), varray(p_data_type, p_item_name));
+ }
+
+ return item_control;
+}
+
+void ThemeTypeEditor::_add_focusable(Control *p_control) {
+ focusables.append(p_control);
+}
+
+void ThemeTypeEditor::_update_type_items() {
+ bool show_default = show_default_items_button->is_pressed();
+ List<StringName> names;
+
+ focusables.clear();
+
+ // Colors.
+ {
+ for (int i = color_items_list->get_child_count() - 1; i >= 0; i--) {
+ Node *node = color_items_list->get_child(i);
+ node->queue_delete();
+ color_items_list->remove_child(node);
+ }
+
+ OrderedHashMap<StringName, bool> color_items = _get_type_items(edited_type, &Theme::get_color_list, show_default);
+ for (OrderedHashMap<StringName, bool>::Element E = color_items.front(); E; E = E.next()) {
+ HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_COLOR, E.key(), E.get());
+ ColorPickerButton *item_editor = memnew(ColorPickerButton);
+ item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_control->add_child(item_editor);
+
+ if (E.get()) {
+ item_editor->set_pick_color(edited_theme->get_color(E.key(), edited_type));
+ item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed), varray(E.key()));
+ } else {
+ item_editor->set_pick_color(Theme::get_default()->get_color(E.key(), edited_type));
+ item_editor->set_disabled(true);
+ }
+
+ _add_focusable(item_editor);
+ color_items_list->add_child(item_control);
+ }
+ }
+
+ // Constants.
+ {
+ for (int i = constant_items_list->get_child_count() - 1; i >= 0; i--) {
+ Node *node = constant_items_list->get_child(i);
+ node->queue_delete();
+ constant_items_list->remove_child(node);
+ }
+
+ OrderedHashMap<StringName, bool> constant_items = _get_type_items(edited_type, &Theme::get_constant_list, show_default);
+ for (OrderedHashMap<StringName, bool>::Element E = constant_items.front(); E; E = E.next()) {
+ HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_CONSTANT, E.key(), E.get());
+ SpinBox *item_editor = memnew(SpinBox);
+ item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_editor->set_min(-100000);
+ item_editor->set_max(100000);
+ item_editor->set_step(1);
+ item_editor->set_allow_lesser(true);
+ item_editor->set_allow_greater(true);
+ item_control->add_child(item_editor);
+
+ if (E.get()) {
+ item_editor->set_value(edited_theme->get_constant(E.key(), edited_type));
+ item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed), varray(E.key()));
+ } else {
+ item_editor->set_value(Theme::get_default()->get_constant(E.key(), edited_type));
+ item_editor->set_editable(false);
+ }
+
+ _add_focusable(item_editor);
+ constant_items_list->add_child(item_control);
+ }
+ }
+
+ // Fonts.
+ {
+ for (int i = font_items_list->get_child_count() - 1; i >= 0; i--) {
+ Node *node = font_items_list->get_child(i);
+ node->queue_delete();
+ font_items_list->remove_child(node);
+ }
+
+ OrderedHashMap<StringName, bool> font_items = _get_type_items(edited_type, &Theme::get_font_list, show_default);
+ for (OrderedHashMap<StringName, bool>::Element E = font_items.front(); E; E = E.next()) {
+ HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT, E.key(), E.get());
+ EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
+ item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_editor->set_base_type("Font");
+ item_control->add_child(item_editor);
+
+ if (E.get()) {
+ if (edited_theme->has_font(E.key(), edited_type)) {
+ item_editor->set_edited_resource(edited_theme->get_font(E.key(), edited_type));
+ } else {
+ item_editor->set_edited_resource(RES());
+ }
+ item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item), varray(item_control));
+ item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed), varray(E.key()));
+ } else {
+ if (Theme::get_default()->has_font(E.key(), edited_type)) {
+ item_editor->set_edited_resource(Theme::get_default()->get_font(E.key(), edited_type));
+ } else {
+ item_editor->set_edited_resource(RES());
+ }
+ item_editor->set_editable(false);
+ }
+
+ _add_focusable(item_editor);
+ font_items_list->add_child(item_control);
+ }
+ }
+
+ // Fonts sizes.
+ {
+ for (int i = font_size_items_list->get_child_count() - 1; i >= 0; i--) {
+ Node *node = font_size_items_list->get_child(i);
+ node->queue_delete();
+ font_size_items_list->remove_child(node);
+ }
+
+ OrderedHashMap<StringName, bool> font_size_items = _get_type_items(edited_type, &Theme::get_font_size_list, show_default);
+ for (OrderedHashMap<StringName, bool>::Element E = font_size_items.front(); E; E = E.next()) {
+ HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT_SIZE, E.key(), E.get());
+ SpinBox *item_editor = memnew(SpinBox);
+ item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_editor->set_min(-100000);
+ item_editor->set_max(100000);
+ item_editor->set_step(1);
+ item_editor->set_allow_lesser(true);
+ item_editor->set_allow_greater(true);
+ item_control->add_child(item_editor);
+
+ if (E.get()) {
+ item_editor->set_value(edited_theme->get_font_size(E.key(), edited_type));
+ item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed), varray(E.key()));
+ } else {
+ item_editor->set_value(Theme::get_default()->get_font_size(E.key(), edited_type));
+ item_editor->set_editable(false);
+ }
+
+ _add_focusable(item_editor);
+ font_size_items_list->add_child(item_control);
+ }
+ }
+
+ // Icons.
+ {
+ for (int i = icon_items_list->get_child_count() - 1; i >= 0; i--) {
+ Node *node = icon_items_list->get_child(i);
+ node->queue_delete();
+ icon_items_list->remove_child(node);
+ }
+
+ OrderedHashMap<StringName, bool> icon_items = _get_type_items(edited_type, &Theme::get_icon_list, show_default);
+ for (OrderedHashMap<StringName, bool>::Element E = icon_items.front(); E; E = E.next()) {
+ HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_ICON, E.key(), E.get());
+ EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
+ item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_editor->set_base_type("Texture2D");
+ item_control->add_child(item_editor);
+
+ if (E.get()) {
+ if (edited_theme->has_icon(E.key(), edited_type)) {
+ item_editor->set_edited_resource(edited_theme->get_icon(E.key(), edited_type));
+ } else {
+ item_editor->set_edited_resource(RES());
+ }
+ item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item), varray(item_control));
+ item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed), varray(E.key()));
+ } else {
+ if (Theme::get_default()->has_icon(E.key(), edited_type)) {
+ item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key(), edited_type));
+ } else {
+ item_editor->set_edited_resource(RES());
+ }
+ item_editor->set_editable(false);
+ }
+
+ _add_focusable(item_editor);
+ icon_items_list->add_child(item_control);
+ }
+ }
+
+ // Styleboxes.
+ {
+ for (int i = stylebox_items_list->get_child_count() - 1; i >= 0; i--) {
+ Node *node = stylebox_items_list->get_child(i);
+ node->queue_delete();
+ stylebox_items_list->remove_child(node);
+ }
+
+ if (leading_stylebox.pinned) {
+ HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_STYLEBOX, leading_stylebox.item_name, true);
+ EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
+ item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_editor->set_stretch_ratio(1.5);
+ item_editor->set_base_type("StyleBox");
+
+ Button *pin_leader_button = memnew(Button);
+ pin_leader_button->set_flat(true);
+ pin_leader_button->set_toggle_mode(true);
+ pin_leader_button->set_pressed(true);
+ pin_leader_button->set_icon(get_theme_icon("Pin", "EditorIcons"));
+ pin_leader_button->set_tooltip(TTR("Unpin this StyleBox as a main style."));
+ item_control->add_child(pin_leader_button);
+ pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_unpin_leading_stylebox));
+
+ item_control->add_child(item_editor);
+
+ if (leading_stylebox.stylebox.is_valid()) {
+ item_editor->set_edited_resource(leading_stylebox.stylebox);
+ } else {
+ item_editor->set_edited_resource(RES());
+ }
+ item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item), varray(item_control));
+ item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(leading_stylebox.item_name));
+
+ stylebox_items_list->add_child(item_control);
+ stylebox_items_list->add_child(memnew(HSeparator));
+ }
+
+ OrderedHashMap<StringName, bool> stylebox_items = _get_type_items(edited_type, &Theme::get_stylebox_list, show_default);
+ for (OrderedHashMap<StringName, bool>::Element E = stylebox_items.front(); E; E = E.next()) {
+ if (leading_stylebox.pinned && leading_stylebox.item_name == E.key()) {
+ continue;
+ }
+
+ HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_STYLEBOX, E.key(), E.get());
+ EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
+ item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_editor->set_stretch_ratio(1.5);
+ item_editor->set_base_type("StyleBox");
+
+ if (E.get()) {
+ Ref<StyleBox> stylebox_value;
+ if (edited_theme->has_stylebox(E.key(), edited_type)) {
+ stylebox_value = edited_theme->get_stylebox(E.key(), edited_type);
+ item_editor->set_edited_resource(stylebox_value);
+ } else {
+ item_editor->set_edited_resource(RES());
+ }
+ item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item), varray(item_control));
+ item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(E.key()));
+
+ Button *pin_leader_button = memnew(Button);
+ pin_leader_button->set_flat(true);
+ pin_leader_button->set_toggle_mode(true);
+ pin_leader_button->set_icon(get_theme_icon("Pin", "EditorIcons"));
+ pin_leader_button->set_tooltip(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type."));
+ item_control->add_child(pin_leader_button);
+ pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_pin_leading_stylebox), varray(stylebox_value, E.key()));
+ } else {
+ if (Theme::get_default()->has_stylebox(E.key(), edited_type)) {
+ item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key(), edited_type));
+ } else {
+ item_editor->set_edited_resource(RES());
+ }
+ item_editor->set_editable(false);
+ }
+
+ item_control->add_child(item_editor);
+ _add_focusable(item_editor);
+ stylebox_items_list->add_child(item_control);
+ }
+ }
+}
+
+void ThemeTypeEditor::_list_type_selected(int p_index) {
+ edited_type = theme_type_list->get_item_text(p_index);
+ _update_type_items();
+}
+
+void ThemeTypeEditor::_add_type_button_cbk() {
+ add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
+ add_type_filter->grab_focus();
+}
+
+void ThemeTypeEditor::_add_type_filter_cbk(const String &p_value) {
+ _update_add_type_options(p_value);
+}
+
+void ThemeTypeEditor::_add_type_options_cbk(int p_index) {
+ add_type_filter->set_text(add_type_options->get_item_text(p_index));
+}
+
+void ThemeTypeEditor::_add_type_dialog_confirmed() {
+ select_type(add_type_filter->get_text().strip_edges());
+}
+
+void ThemeTypeEditor::_add_type_dialog_entered(const String &p_value) {
+ select_type(p_value.strip_edges());
+ add_type_dialog->hide();
+}
+
+void ThemeTypeEditor::_add_type_dialog_activated(int p_index) {
+ select_type(add_type_options->get_item_text(p_index));
+ add_type_dialog->hide();
+}
+
+void ThemeTypeEditor::_add_default_type_items() {
+ List<StringName> names;
+
+ updating = true;
+ // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ edited_theme->_freeze_change_propagation();
+
+ {
+ names.clear();
+ Theme::get_default()->get_icon_list(edited_type, &names);
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ if (!edited_theme->has_icon(E->get(), edited_type)) {
+ edited_theme->set_icon(E->get(), edited_type, Ref<Texture2D>());
+ }
+ }
+ }
+ {
+ names.clear();
+ Theme::get_default()->get_stylebox_list(edited_type, &names);
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ if (!edited_theme->has_stylebox(E->get(), edited_type)) {
+ edited_theme->set_stylebox(E->get(), edited_type, Ref<StyleBox>());
+ }
+ }
+ }
+ {
+ names.clear();
+ Theme::get_default()->get_font_list(edited_type, &names);
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ if (!edited_theme->has_font(E->get(), edited_type)) {
+ edited_theme->set_font(E->get(), edited_type, Ref<Font>());
+ }
+ }
+ }
+ {
+ names.clear();
+ Theme::get_default()->get_font_size_list(edited_type, &names);
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ if (!edited_theme->has_font_size(E->get(), edited_type)) {
+ edited_theme->set_font_size(E->get(), edited_type, Theme::get_default()->get_font_size(E->get(), edited_type));
+ }
+ }
+ }
+ {
+ names.clear();
+ Theme::get_default()->get_color_list(edited_type, &names);
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ if (!edited_theme->has_color(E->get(), edited_type)) {
+ edited_theme->set_color(E->get(), edited_type, Theme::get_default()->get_color(E->get(), edited_type));
+ }
+ }
+ }
+ {
+ names.clear();
+ Theme::get_default()->get_constant_list(edited_type, &names);
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ if (!edited_theme->has_constant(E->get(), edited_type)) {
+ edited_theme->set_constant(E->get(), edited_type, Theme::get_default()->get_constant(E->get(), edited_type));
+ }
+ }
+ }
+
+ // Allow changes to be reported now that the operation is finished.
+ edited_theme->_unfreeze_and_propagate_changes();
+ updating = false;
+
+ _update_type_items();
+}
+
+void ThemeTypeEditor::_item_add_cbk(int p_data_type, Control *p_control) {
+ LineEdit *le = Object::cast_to<LineEdit>(p_control);
+ if (le->get_text().strip_edges().is_empty()) {
+ return;
+ }
+
+ String item_name = le->get_text().strip_edges();
+ switch (p_data_type) {
+ case Theme::DATA_TYPE_COLOR: {
+ edited_theme->set_color(item_name, edited_type, Color());
+ } break;
+ case Theme::DATA_TYPE_CONSTANT: {
+ edited_theme->set_constant(item_name, edited_type, 0);
+ } break;
+ case Theme::DATA_TYPE_FONT: {
+ edited_theme->set_font(item_name, edited_type, Ref<Font>());
+ } break;
+ case Theme::DATA_TYPE_FONT_SIZE: {
+ edited_theme->set_font_size(item_name, edited_type, -1);
+ } break;
+ case Theme::DATA_TYPE_ICON: {
+ edited_theme->set_icon(item_name, edited_type, Ref<Texture2D>());
+ } break;
+ case Theme::DATA_TYPE_STYLEBOX: {
+ edited_theme->set_stylebox(item_name, edited_type, Ref<StyleBox>());
+ } break;
+ }
+
+ le->set_text("");
+}
+
+void ThemeTypeEditor::_item_add_lineedit_cbk(String p_value, int p_data_type, Control *p_control) {
+ _item_add_cbk(p_data_type, p_control);
+}
+
+void ThemeTypeEditor::_item_override_cbk(int p_data_type, String p_item_name) {
+ switch (p_data_type) {
+ case Theme::DATA_TYPE_COLOR: {
+ edited_theme->set_color(p_item_name, edited_type, Theme::get_default()->get_color(p_item_name, edited_type));
+ } break;
+ case Theme::DATA_TYPE_CONSTANT: {
+ edited_theme->set_constant(p_item_name, edited_type, Theme::get_default()->get_constant(p_item_name, edited_type));
+ } break;
+ case Theme::DATA_TYPE_FONT: {
+ edited_theme->set_font(p_item_name, edited_type, Ref<Font>());
+ } break;
+ case Theme::DATA_TYPE_FONT_SIZE: {
+ edited_theme->set_font_size(p_item_name, edited_type, Theme::get_default()->get_font_size(p_item_name, edited_type));
+ } break;
+ case Theme::DATA_TYPE_ICON: {
+ edited_theme->set_icon(p_item_name, edited_type, Ref<Texture2D>());
+ } break;
+ case Theme::DATA_TYPE_STYLEBOX: {
+ edited_theme->set_stylebox(p_item_name, edited_type, Ref<StyleBox>());
+ } break;
+ }
+}
+
+void ThemeTypeEditor::_item_remove_cbk(int p_data_type, String p_item_name) {
+ switch (p_data_type) {
+ case Theme::DATA_TYPE_COLOR: {
+ edited_theme->clear_color(p_item_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_CONSTANT: {
+ edited_theme->clear_constant(p_item_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_FONT: {
+ edited_theme->clear_font(p_item_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_FONT_SIZE: {
+ edited_theme->clear_font_size(p_item_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_ICON: {
+ edited_theme->clear_icon(p_item_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_STYLEBOX: {
+ edited_theme->clear_stylebox(p_item_name, edited_type);
+ } break;
+ }
+}
+
+void ThemeTypeEditor::_item_rename_cbk(int p_data_type, String p_item_name, Control *p_control) {
+ // Label
+ Object::cast_to<Label>(p_control->get_child(0))->hide();
+ // Label buttons
+ Object::cast_to<Button>(p_control->get_child(2))->hide();
+ Object::cast_to<Button>(p_control->get_child(3))->hide();
+
+ // LineEdit
+ Object::cast_to<LineEdit>(p_control->get_child(1))->set_text(p_item_name);
+ Object::cast_to<LineEdit>(p_control->get_child(1))->show();
+ // LineEdit buttons
+ Object::cast_to<Button>(p_control->get_child(4))->show();
+ Object::cast_to<Button>(p_control->get_child(5))->show();
+}
+
+void ThemeTypeEditor::_item_rename_confirmed(int p_data_type, String p_item_name, Control *p_control) {
+ LineEdit *le = Object::cast_to<LineEdit>(p_control->get_child(1));
+ if (le->get_text().strip_edges().is_empty()) {
+ return;
+ }
+
+ String new_name = le->get_text().strip_edges();
+ if (new_name == p_item_name) {
+ _item_rename_canceled(p_data_type, p_item_name, p_control);
+ return;
+ }
+
+ switch (p_data_type) {
+ case Theme::DATA_TYPE_COLOR: {
+ edited_theme->rename_color(p_item_name, new_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_CONSTANT: {
+ edited_theme->rename_constant(p_item_name, new_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_FONT: {
+ edited_theme->rename_font(p_item_name, new_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_FONT_SIZE: {
+ edited_theme->rename_font_size(p_item_name, new_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_ICON: {
+ edited_theme->rename_icon(p_item_name, new_name, edited_type);
+ } break;
+ case Theme::DATA_TYPE_STYLEBOX: {
+ edited_theme->rename_stylebox(p_item_name, new_name, edited_type);
+ } break;
+ }
+}
+
+void ThemeTypeEditor::_item_rename_entered(String p_value, int p_data_type, String p_item_name, Control *p_control) {
+ _item_rename_confirmed(p_data_type, p_item_name, p_control);
+}
+
+void ThemeTypeEditor::_item_rename_canceled(int p_data_type, String p_item_name, Control *p_control) {
+ // LineEdit
+ Object::cast_to<LineEdit>(p_control->get_child(1))->hide();
+ // LineEdit buttons
+ Object::cast_to<Button>(p_control->get_child(4))->hide();
+ Object::cast_to<Button>(p_control->get_child(5))->hide();
+
+ // Label
+ Object::cast_to<Label>(p_control->get_child(0))->show();
+ // Label buttons
+ Object::cast_to<Button>(p_control->get_child(2))->show();
+ Object::cast_to<Button>(p_control->get_child(3))->show();
+}
+
+void ThemeTypeEditor::_color_item_changed(Color p_value, String p_item_name) {
+ edited_theme->set_color(p_item_name, edited_type, p_value);
+}
+
+void ThemeTypeEditor::_constant_item_changed(float p_value, String p_item_name) {
+ edited_theme->set_constant(p_item_name, edited_type, int(p_value));
+}
+
+void ThemeTypeEditor::_font_size_item_changed(float p_value, String p_item_name) {
+ edited_theme->set_font_size(p_item_name, edited_type, int(p_value));
+}
+
+void ThemeTypeEditor::_edit_resource_item(RES p_resource, Control *p_editor) {
+ EditorNode::get_singleton()->edit_resource(p_resource);
+}
+
+void ThemeTypeEditor::_font_item_changed(Ref<Font> p_value, String p_item_name) {
+ edited_theme->set_font(p_item_name, edited_type, p_value);
+}
+
+void ThemeTypeEditor::_icon_item_changed(Ref<Texture2D> p_value, String p_item_name) {
+ edited_theme->set_icon(p_item_name, edited_type, p_value);
+}
+
+void ThemeTypeEditor::_stylebox_item_changed(Ref<StyleBox> p_value, String p_item_name) {
+ edited_theme->set_stylebox(p_item_name, edited_type, p_value);
+
+ if (leading_stylebox.pinned && leading_stylebox.item_name == p_item_name) {
+ if (leading_stylebox.stylebox.is_valid()) {
+ leading_stylebox.stylebox->disconnect("changed", callable_mp(this, &ThemeTypeEditor::_update_stylebox_from_leading));
+ }
+
+ leading_stylebox.stylebox = p_value;
+ leading_stylebox.ref_stylebox = (p_value.is_valid() ? p_value->duplicate() : RES());
+ if (p_value.is_valid()) {
+ leading_stylebox.stylebox->connect("changed", callable_mp(this, &ThemeTypeEditor::_update_stylebox_from_leading));
+ }
+ }
+}
+
+void ThemeTypeEditor::_pin_leading_stylebox(Ref<StyleBox> p_stylebox, String p_item_name) {
+ if (leading_stylebox.stylebox.is_valid()) {
+ leading_stylebox.stylebox->disconnect("changed", callable_mp(this, &ThemeTypeEditor::_update_stylebox_from_leading));
+ }
+
+ LeadingStylebox leader;
+ leader.pinned = true;
+ leader.item_name = p_item_name;
+ leader.stylebox = p_stylebox;
+ leader.ref_stylebox = (p_stylebox.is_valid() ? p_stylebox->duplicate() : RES());
+
+ leading_stylebox = leader;
+ if (leading_stylebox.stylebox.is_valid()) {
+ leading_stylebox.stylebox->connect("changed", callable_mp(this, &ThemeTypeEditor::_update_stylebox_from_leading));
+ }
+
+ _update_type_items();
+}
+
+void ThemeTypeEditor::_unpin_leading_stylebox() {
+ if (leading_stylebox.stylebox.is_valid()) {
+ leading_stylebox.stylebox->disconnect("changed", callable_mp(this, &ThemeTypeEditor::_update_stylebox_from_leading));
+ }
+
+ LeadingStylebox leader;
+ leader.pinned = false;
+ leading_stylebox = leader;
+
+ _update_type_items();
+}
+
+void ThemeTypeEditor::_update_stylebox_from_leading() {
+ if (!leading_stylebox.pinned || leading_stylebox.stylebox.is_null()) {
+ return;
+ }
+
+ // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ edited_theme->_freeze_change_propagation();
+
+ List<StringName> names;
+ edited_theme->get_stylebox_list(edited_type, &names);
+ List<Ref<StyleBox>> styleboxes;
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ if (E->get() == leading_stylebox.item_name) {
+ continue;
+ }
+
+ Ref<StyleBox> sb = edited_theme->get_stylebox(E->get(), edited_type);
+ if (sb->get_class() == leading_stylebox.stylebox->get_class()) {
+ styleboxes.push_back(sb);
+ }
+ }
+
+ List<PropertyInfo> props;
+ leading_stylebox.stylebox->get_property_list(&props);
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ continue;
+ }
+
+ Variant value = leading_stylebox.stylebox->get(E->get().name);
+ Variant ref_value = leading_stylebox.ref_stylebox->get(E->get().name);
+ if (value == ref_value) {
+ continue;
+ }
+
+ for (List<Ref<StyleBox>>::Element *F = styleboxes.front(); F; F = F->next()) {
+ Ref<StyleBox> sb = F->get();
+ sb->set(E->get().name, value);
+ }
+ }
+
+ leading_stylebox.ref_stylebox = leading_stylebox.stylebox->duplicate();
+
+ // Allow changes to be reported now that the operation is finished.
+ edited_theme->_unfreeze_and_propagate_changes();
+}
+
+void ThemeTypeEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ add_type_button->set_icon(get_theme_icon("Add", "EditorIcons"));
+
+ data_type_tabs->set_tab_icon(0, get_theme_icon("Color", "EditorIcons"));
+ data_type_tabs->set_tab_icon(1, get_theme_icon("MemberConstant", "EditorIcons"));
+ data_type_tabs->set_tab_icon(2, get_theme_icon("Font", "EditorIcons"));
+ data_type_tabs->set_tab_icon(3, get_theme_icon("FontSize", "EditorIcons"));
+ data_type_tabs->set_tab_icon(4, get_theme_icon("ImageTexture", "EditorIcons"));
+ data_type_tabs->set_tab_icon(5, get_theme_icon("StyleBoxFlat", "EditorIcons"));
+
+ data_type_tabs->add_theme_style_override("tab_selected", get_theme_stylebox("tab_selected_odd", "TabContainer"));
+ data_type_tabs->add_theme_style_override("panel", get_theme_stylebox("panel_odd", "TabContainer"));
+
+ _update_add_type_options();
+ } break;
+ }
+}
+
+void ThemeTypeEditor::set_edited_theme(const Ref<Theme> &p_theme) {
+ if (edited_theme.is_valid()) {
+ edited_theme->disconnect("changed", callable_mp(this, &ThemeTypeEditor::_update_type_list_debounced));
+ }
+
+ edited_theme = p_theme;
+ edited_theme->connect("changed", callable_mp(this, &ThemeTypeEditor::_update_type_list_debounced));
+ _update_type_list();
+}
+
+void ThemeTypeEditor::select_type(String p_type_name) {
+ edited_type = p_type_name;
+ bool type_exists = false;
+
+ for (int i = 0; i < theme_type_list->get_item_count(); i++) {
+ String type_name = theme_type_list->get_item_text(i);
+ if (type_name == edited_type) {
+ theme_type_list->select(i);
+ type_exists = true;
+ break;
+ }
+ }
+
+ if (type_exists) {
+ _update_type_items();
+ } else {
+ edited_theme->add_icon_type(edited_type);
+ edited_theme->add_stylebox_type(edited_type);
+ edited_theme->add_font_type(edited_type);
+ edited_theme->add_font_size_type(edited_type);
+ edited_theme->add_color_type(edited_type);
+ edited_theme->add_constant_type(edited_type);
+
+ _update_type_list();
+ }
+}
+
+ThemeTypeEditor::ThemeTypeEditor() {
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
+
+ HBoxContainer *type_list_hb = memnew(HBoxContainer);
+ main_vb->add_child(type_list_hb);
+
+ Label *type_list_label = memnew(Label);
+ type_list_label->set_text(TTR("Type:"));
+ type_list_hb->add_child(type_list_label);
+
+ theme_type_list = memnew(OptionButton);
+ theme_type_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ type_list_hb->add_child(theme_type_list);
+ theme_type_list->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_list_type_selected));
+
+ add_type_button = memnew(Button);
+ add_type_button->set_tooltip(TTR("Add Type"));
+ type_list_hb->add_child(add_type_button);
+ add_type_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_button_cbk));
+
+ add_type_dialog = memnew(ConfirmationDialog);
+ add_type_dialog->set_title(TTR("Add Item Type"));
+ type_list_hb->add_child(add_type_dialog);
+ add_type_dialog->connect("confirmed", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_confirmed));
+
+ VBoxContainer *add_type_vb = memnew(VBoxContainer);
+ add_type_dialog->add_child(add_type_vb);
+
+ Label *add_type_filter_label = memnew(Label);
+ add_type_filter_label->set_text(TTR("Name:"));
+ add_type_vb->add_child(add_type_filter_label);
+ add_type_filter = memnew(LineEdit);
+ add_type_vb->add_child(add_type_filter);
+ add_type_filter->connect("text_changed", callable_mp(this, &ThemeTypeEditor::_add_type_filter_cbk));
+ add_type_filter->connect("text_entered", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_entered));
+ Label *add_type_options_label = memnew(Label);
+ add_type_options_label->set_text(TTR("Node Types:"));
+ add_type_vb->add_child(add_type_options_label);
+ add_type_options = memnew(ItemList);
+ add_type_options->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_type_vb->add_child(add_type_options);
+ add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_add_type_options_cbk));
+ add_type_options->connect("item_activated", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_activated));
+
+ HBoxContainer *type_controls = memnew(HBoxContainer);
+ main_vb->add_child(type_controls);
+
+ show_default_items_button = memnew(CheckButton);
+ show_default_items_button->set_h_size_flags(SIZE_EXPAND_FILL);
+ show_default_items_button->set_text(TTR("Show Default"));
+ show_default_items_button->set_tooltip(TTR("Show default type items alongside items that have been overridden."));
+ show_default_items_button->set_pressed(true);
+ type_controls->add_child(show_default_items_button);
+ show_default_items_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_update_type_items));
+
+ Button *add_default_items_button = memnew(Button);
+ add_default_items_button->set_h_size_flags(SIZE_EXPAND_FILL);
+ add_default_items_button->set_text(TTR("Override All"));
+ add_default_items_button->set_tooltip(TTR("Override all default type items."));
+ type_controls->add_child(add_default_items_button);
+ add_default_items_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_default_type_items));
+
+ data_type_tabs = memnew(TabContainer);
+ main_vb->add_child(data_type_tabs);
+ data_type_tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ data_type_tabs->set_use_hidden_tabs_for_min_size(true);
+
+ color_items_list = _create_item_list(Theme::DATA_TYPE_COLOR);
+ constant_items_list = _create_item_list(Theme::DATA_TYPE_CONSTANT);
+ font_items_list = _create_item_list(Theme::DATA_TYPE_FONT);
+ font_size_items_list = _create_item_list(Theme::DATA_TYPE_FONT_SIZE);
+ icon_items_list = _create_item_list(Theme::DATA_TYPE_ICON);
+ stylebox_items_list = _create_item_list(Theme::DATA_TYPE_STYLEBOX);
+
+ update_debounce_timer = memnew(Timer);
+ update_debounce_timer->set_one_shot(true);
+ update_debounce_timer->set_wait_time(0.5);
+ update_debounce_timer->connect("timeout", callable_mp(this, &ThemeTypeEditor::_update_type_list));
+ add_child(update_debounce_timer);
+}
+
void ThemeEditor::edit(const Ref<Theme> &p_theme) {
+ if (theme == p_theme) {
+ return;
+ }
+
theme = p_theme;
+ theme_type_editor->set_edited_theme(p_theme);
theme_edit_dialog->set_edited_theme(p_theme);
- main_panel->set_theme(p_theme);
- main_container->set_theme(p_theme);
-}
-void ThemeEditor::_propagate_redraw(Control *p_at) {
- p_at->notification(NOTIFICATION_THEME_CHANGED);
- p_at->minimum_size_changed();
- p_at->update();
- for (int i = 0; i < p_at->get_child_count(); i++) {
- Control *a = Object::cast_to<Control>(p_at->get_child(i));
- if (a) {
- _propagate_redraw(a);
+ for (int i = 0; i < preview_tabs_content->get_child_count(); i++) {
+ ThemeEditorPreview *preview_tab = Object::cast_to<ThemeEditorPreview>(preview_tabs_content->get_child(i));
+ if (!preview_tab) {
+ continue;
}
+
+ preview_tab->set_preview_theme(p_theme);
}
+
+ theme_name->set_text(TTR("Theme") + ": " + theme->get_path().get_file());
+}
+
+Ref<Theme> ThemeEditor::get_edited_theme() {
+ return theme;
}
-void ThemeEditor::_refresh_interval() {
- _propagate_redraw(main_panel);
- _propagate_redraw(main_container);
+void ThemeEditor::_theme_save_button_cbk(bool p_save_as) {
+ ERR_FAIL_COND_MSG(theme.is_null(), "Invalid state of the Theme Editor; the Theme resource is missing.");
+
+ if (p_save_as) {
+ EditorNode::get_singleton()->save_resource_as(theme);
+ } else {
+ EditorNode::get_singleton()->save_resource(theme);
+ }
}
void ThemeEditor::_theme_edit_button_cbk() {
theme_edit_dialog->popup_centered(Size2(850, 760) * EDSCALE);
}
+void ThemeEditor::_add_preview_button_cbk() {
+ preview_scene_dialog->popup_file_dialog();
+}
+
+void ThemeEditor::_preview_scene_dialog_cbk(const String &p_path) {
+ SceneThemeEditorPreview *preview_tab = memnew(SceneThemeEditorPreview);
+ if (!preview_tab->set_preview_scene(p_path)) {
+ return;
+ }
+
+ _add_preview_tab(preview_tab, p_path.get_file(), get_theme_icon("PackedScene", "EditorIcons"));
+ preview_tab->connect("scene_invalidated", callable_mp(this, &ThemeEditor::_remove_preview_tab_invalid), varray(preview_tab));
+ preview_tab->connect("scene_reloaded", callable_mp(this, &ThemeEditor::_update_preview_tab), varray(preview_tab));
+}
+
+void ThemeEditor::_add_preview_tab(ThemeEditorPreview *p_preview_tab, const String &p_preview_name, const Ref<Texture2D> &p_icon) {
+ p_preview_tab->set_preview_theme(theme);
+
+ preview_tabs->add_tab(p_preview_name, p_icon);
+ preview_tabs_content->add_child(p_preview_tab);
+ preview_tabs->set_tab_right_button(preview_tabs->get_tab_count() - 1, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("close", "Tabs"));
+ p_preview_tab->connect("control_picked", callable_mp(this, &ThemeEditor::_preview_control_picked));
+
+ preview_tabs->set_current_tab(preview_tabs->get_tab_count() - 1);
+}
+
+void ThemeEditor::_change_preview_tab(int p_tab) {
+ ERR_FAIL_INDEX_MSG(p_tab, preview_tabs_content->get_child_count(), "Attempting to open a preview tab that doesn't exist.");
+
+ for (int i = 0; i < preview_tabs_content->get_child_count(); i++) {
+ Control *c = Object::cast_to<Control>(preview_tabs_content->get_child(i));
+ if (!c) {
+ continue;
+ }
+
+ c->set_visible(i == p_tab);
+ }
+}
+
+void ThemeEditor::_remove_preview_tab(int p_tab) {
+ ERR_FAIL_INDEX_MSG(p_tab, preview_tabs_content->get_child_count(), "Attempting to remove a preview tab that doesn't exist.");
+
+ ThemeEditorPreview *preview_tab = Object::cast_to<ThemeEditorPreview>(preview_tabs_content->get_child(p_tab));
+ ERR_FAIL_COND_MSG(Object::cast_to<DefaultThemeEditorPreview>(preview_tab), "Attemptying to remove the default preview tab.");
+
+ if (preview_tab) {
+ preview_tab->disconnect("control_picked", callable_mp(this, &ThemeEditor::_preview_control_picked));
+ if (preview_tab->is_connected("scene_invalidated", callable_mp(this, &ThemeEditor::_remove_preview_tab_invalid))) {
+ preview_tab->disconnect("scene_invalidated", callable_mp(this, &ThemeEditor::_remove_preview_tab_invalid));
+ }
+ if (preview_tab->is_connected("scene_reloaded", callable_mp(this, &ThemeEditor::_update_preview_tab))) {
+ preview_tab->disconnect("scene_reloaded", callable_mp(this, &ThemeEditor::_update_preview_tab));
+ }
+
+ preview_tabs_content->remove_child(preview_tab);
+ preview_tabs->remove_tab(p_tab);
+ _change_preview_tab(preview_tabs->get_current_tab());
+ }
+}
+
+void ThemeEditor::_remove_preview_tab_invalid(Node *p_tab_control) {
+ int tab_index = p_tab_control->get_index();
+ _remove_preview_tab(tab_index);
+}
+
+void ThemeEditor::_update_preview_tab(Node *p_tab_control) {
+ if (!Object::cast_to<SceneThemeEditorPreview>(p_tab_control)) {
+ return;
+ }
+
+ int tab_index = p_tab_control->get_index();
+ SceneThemeEditorPreview *scene_preview = Object::cast_to<SceneThemeEditorPreview>(p_tab_control);
+ preview_tabs->set_tab_title(tab_index, scene_preview->get_preview_scene_path().get_file());
+}
+
+void ThemeEditor::_preview_control_picked(String p_class_name) {
+ theme_type_editor->select_type(p_class_name);
+}
+
void ThemeEditor::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_PROCESS: {
- time_left -= get_process_delta_time();
- if (time_left < 0) {
- time_left = 1.5;
- _refresh_interval();
- }
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ preview_tabs->add_theme_style_override("tab_selected", get_theme_stylebox("ThemeEditorPreviewFG", "EditorStyles"));
+ preview_tabs->add_theme_style_override("tab_unselected", get_theme_stylebox("ThemeEditorPreviewBG", "EditorStyles"));
+ preview_tabs_content->add_theme_style_override("panel", get_theme_stylebox("panel_odd", "TabContainer"));
+
+ add_preview_button->set_icon(get_theme_icon("Add", "EditorIcons"));
} break;
}
}
-void ThemeEditor::_bind_methods() {
-}
-
ThemeEditor::ThemeEditor() {
HBoxContainer *top_menu = memnew(HBoxContainer);
add_child(top_menu);
- top_menu->add_child(memnew(Label(TTR("Preview:"))));
+ theme_name = memnew(Label);
+ theme_name->set_text(TTR("Theme") + ": ");
+ top_menu->add_child(theme_name);
+
top_menu->add_spacer(false);
- theme_edit_button = memnew(Button);
- theme_edit_button->set_text(TTR("Manage Items"));
+ Button *theme_save_button = memnew(Button);
+ theme_save_button->set_text(TTR("Save"));
+ theme_save_button->set_flat(true);
+ theme_save_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk), varray(false));
+ top_menu->add_child(theme_save_button);
+
+ Button *theme_save_as_button = memnew(Button);
+ theme_save_as_button->set_text(TTR("Save As..."));
+ theme_save_as_button->set_flat(true);
+ theme_save_as_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk), varray(true));
+ top_menu->add_child(theme_save_as_button);
+
+ top_menu->add_child(memnew(VSeparator));
+
+ Button *theme_edit_button = memnew(Button);
+ theme_edit_button->set_text(TTR("Manage Items..."));
theme_edit_button->set_tooltip(TTR("Add, remove, organize and import Theme items."));
theme_edit_button->set_flat(true);
theme_edit_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_edit_button_cbk));
top_menu->add_child(theme_edit_button);
- ScrollContainer *scroll = memnew(ScrollContainer);
- add_child(scroll);
- scroll->set_enable_v_scroll(true);
- scroll->set_enable_h_scroll(true);
- scroll->set_v_size_flags(SIZE_EXPAND_FILL);
-
- MarginContainer *root_container = memnew(MarginContainer);
- scroll->add_child(root_container);
- root_container->set_theme(Theme::get_default());
- root_container->set_clip_contents(true);
- root_container->set_custom_minimum_size(Size2(700, 0) * EDSCALE);
- root_container->set_v_size_flags(SIZE_EXPAND_FILL);
- root_container->set_h_size_flags(SIZE_EXPAND_FILL);
-
- //// Preview Controls ////
-
- main_panel = memnew(Panel);
- root_container->add_child(main_panel);
-
- main_container = memnew(MarginContainer);
- root_container->add_child(main_container);
- main_container->add_theme_constant_override("margin_right", 4 * EDSCALE);
- main_container->add_theme_constant_override("margin_top", 4 * EDSCALE);
- main_container->add_theme_constant_override("margin_left", 4 * EDSCALE);
- main_container->add_theme_constant_override("margin_bottom", 4 * EDSCALE);
-
- HBoxContainer *main_hb = memnew(HBoxContainer);
- main_container->add_child(main_hb);
-
- VBoxContainer *first_vb = memnew(VBoxContainer);
- main_hb->add_child(first_vb);
- first_vb->set_h_size_flags(SIZE_EXPAND_FILL);
- first_vb->add_theme_constant_override("separation", 10 * EDSCALE);
-
- first_vb->add_child(memnew(Label("Label")));
-
- first_vb->add_child(memnew(Button("Button")));
- Button *bt = memnew(Button);
- bt->set_text(TTR("Toggle Button"));
- bt->set_toggle_mode(true);
- bt->set_pressed(true);
- first_vb->add_child(bt);
- bt = memnew(Button);
- bt->set_text(TTR("Disabled Button"));
- bt->set_disabled(true);
- first_vb->add_child(bt);
- Button *tb = memnew(Button);
- tb->set_flat(true);
- tb->set_text("Button");
- first_vb->add_child(tb);
-
- CheckButton *cb = memnew(CheckButton);
- cb->set_text("CheckButton");
- first_vb->add_child(cb);
- CheckBox *cbx = memnew(CheckBox);
- cbx->set_text("CheckBox");
- first_vb->add_child(cbx);
-
- MenuButton *test_menu_button = memnew(MenuButton);
- test_menu_button->set_text("MenuButton");
- test_menu_button->get_popup()->add_item(TTR("Item"));
- test_menu_button->get_popup()->add_item(TTR("Disabled Item"));
- test_menu_button->get_popup()->set_item_disabled(1, true);
- test_menu_button->get_popup()->add_separator();
- test_menu_button->get_popup()->add_check_item(TTR("Check Item"));
- test_menu_button->get_popup()->add_check_item(TTR("Checked Item"));
- test_menu_button->get_popup()->set_item_checked(4, true);
- test_menu_button->get_popup()->add_separator();
- test_menu_button->get_popup()->add_radio_check_item(TTR("Radio Item"));
- test_menu_button->get_popup()->add_radio_check_item(TTR("Checked Radio Item"));
- test_menu_button->get_popup()->set_item_checked(7, true);
- test_menu_button->get_popup()->add_separator(TTR("Named Sep."));
-
- PopupMenu *test_submenu = memnew(PopupMenu);
- test_menu_button->get_popup()->add_child(test_submenu);
- test_submenu->set_name("submenu");
- test_menu_button->get_popup()->add_submenu_item(TTR("Submenu"), "submenu");
- test_submenu->add_item(TTR("Subitem 1"));
- test_submenu->add_item(TTR("Subitem 2"));
- first_vb->add_child(test_menu_button);
-
- OptionButton *test_option_button = memnew(OptionButton);
- test_option_button->add_item("OptionButton");
- test_option_button->add_separator();
- test_option_button->add_item(TTR("Has"));
- test_option_button->add_item(TTR("Many"));
- test_option_button->add_item(TTR("Options"));
- first_vb->add_child(test_option_button);
- first_vb->add_child(memnew(ColorPickerButton));
-
- VBoxContainer *second_vb = memnew(VBoxContainer);
- second_vb->set_h_size_flags(SIZE_EXPAND_FILL);
- main_hb->add_child(second_vb);
- second_vb->add_theme_constant_override("separation", 10 * EDSCALE);
- LineEdit *le = memnew(LineEdit);
- le->set_text("LineEdit");
- second_vb->add_child(le);
- le = memnew(LineEdit);
- le->set_text(TTR("Disabled LineEdit"));
- le->set_editable(false);
- second_vb->add_child(le);
- TextEdit *te = memnew(TextEdit);
- te->set_text("TextEdit");
- te->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
- second_vb->add_child(te);
- second_vb->add_child(memnew(SpinBox));
-
- HBoxContainer *vhb = memnew(HBoxContainer);
- second_vb->add_child(vhb);
- vhb->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
- vhb->add_child(memnew(VSlider));
- VScrollBar *vsb = memnew(VScrollBar);
- vsb->set_page(25);
- vhb->add_child(vsb);
- vhb->add_child(memnew(VSeparator));
- VBoxContainer *hvb = memnew(VBoxContainer);
- vhb->add_child(hvb);
- hvb->set_alignment(ALIGN_CENTER);
- hvb->set_h_size_flags(SIZE_EXPAND_FILL);
- hvb->add_child(memnew(HSlider));
- HScrollBar *hsb = memnew(HScrollBar);
- hsb->set_page(25);
- hvb->add_child(hsb);
- HSlider *hs = memnew(HSlider);
- hs->set_editable(false);
- hvb->add_child(hs);
- hvb->add_child(memnew(HSeparator));
- ProgressBar *pb = memnew(ProgressBar);
- pb->set_value(50);
- hvb->add_child(pb);
-
- VBoxContainer *third_vb = memnew(VBoxContainer);
- third_vb->set_h_size_flags(SIZE_EXPAND_FILL);
- third_vb->add_theme_constant_override("separation", 10 * EDSCALE);
- main_hb->add_child(third_vb);
-
- TabContainer *tc = memnew(TabContainer);
- third_vb->add_child(tc);
- tc->set_custom_minimum_size(Size2(0, 135) * EDSCALE);
- Control *tcc = memnew(Control);
- tcc->set_name(TTR("Tab 1"));
- tc->add_child(tcc);
- tcc = memnew(Control);
- tcc->set_name(TTR("Tab 2"));
- tc->add_child(tcc);
- tcc = memnew(Control);
- tcc->set_name(TTR("Tab 3"));
- tc->add_child(tcc);
- tc->set_tab_disabled(2, true);
-
- Tree *test_tree = memnew(Tree);
- third_vb->add_child(test_tree);
- test_tree->set_custom_minimum_size(Size2(0, 175) * EDSCALE);
- test_tree->add_theme_constant_override("draw_relationship_lines", 1);
-
- TreeItem *item = test_tree->create_item();
- item->set_text(0, "Tree");
- item = test_tree->create_item(test_tree->get_root());
- item->set_text(0, "Item");
- item = test_tree->create_item(test_tree->get_root());
- item->set_editable(0, true);
- item->set_text(0, TTR("Editable Item"));
- TreeItem *sub_tree = test_tree->create_item(test_tree->get_root());
- sub_tree->set_text(0, TTR("Subtree"));
- item = test_tree->create_item(sub_tree);
- item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- item->set_editable(0, true);
- item->set_text(0, "Check Item");
- item = test_tree->create_item(sub_tree);
- item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
- item->set_editable(0, true);
- item->set_range_config(0, 0, 20, 0.1);
- item->set_range(0, 2);
- item = test_tree->create_item(sub_tree);
- item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
- item->set_editable(0, true);
- item->set_text(0, TTR("Has,Many,Options"));
- item->set_range(0, 2);
-
- main_hb->add_theme_constant_override("separation", 20 * EDSCALE);
-
theme_edit_dialog = memnew(ThemeItemEditorDialog);
theme_edit_dialog->hide();
- add_child(theme_edit_dialog);
+ top_menu->add_child(theme_edit_dialog);
+
+ HSplitContainer *main_hs = memnew(HSplitContainer);
+ main_hs->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(main_hs);
+
+ VBoxContainer *preview_tabs_vb = memnew(VBoxContainer);
+ preview_tabs_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ preview_tabs_vb->set_custom_minimum_size(Size2(520, 0) * EDSCALE);
+ preview_tabs_vb->add_theme_constant_override("separation", 2 * EDSCALE);
+ main_hs->add_child(preview_tabs_vb);
+ HBoxContainer *preview_tabbar_hb = memnew(HBoxContainer);
+ preview_tabs_vb->add_child(preview_tabbar_hb);
+ preview_tabs_content = memnew(PanelContainer);
+ preview_tabs_content->set_v_size_flags(SIZE_EXPAND_FILL);
+ preview_tabs_content->set_draw_behind_parent(true);
+ preview_tabs_vb->add_child(preview_tabs_content);
+
+ preview_tabs = memnew(Tabs);
+ preview_tabs->set_tab_align(Tabs::ALIGN_LEFT);
+ preview_tabs->set_h_size_flags(SIZE_EXPAND_FILL);
+ preview_tabbar_hb->add_child(preview_tabs);
+ preview_tabs->connect("tab_changed", callable_mp(this, &ThemeEditor::_change_preview_tab));
+ preview_tabs->connect("right_button_pressed", callable_mp(this, &ThemeEditor::_remove_preview_tab));
+
+ HBoxContainer *add_preview_button_hb = memnew(HBoxContainer);
+ preview_tabbar_hb->add_child(add_preview_button_hb);
+ add_preview_button = memnew(Button);
+ add_preview_button->set_text(TTR("Add Preview"));
+ add_preview_button_hb->add_child(add_preview_button);
+ add_preview_button->connect("pressed", callable_mp(this, &ThemeEditor::_add_preview_button_cbk));
+
+ DefaultThemeEditorPreview *default_preview_tab = memnew(DefaultThemeEditorPreview);
+ preview_tabs_content->add_child(default_preview_tab);
+ default_preview_tab->connect("control_picked", callable_mp(this, &ThemeEditor::_preview_control_picked));
+ preview_tabs->add_tab(TTR("Default Preview"));
+
+ preview_scene_dialog = memnew(EditorFileDialog);
+ preview_scene_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ preview_scene_dialog->set_title(TTR("Select UI Scene:"));
+ List<String> ext;
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene", &ext);
+ for (List<String>::Element *E = ext.front(); E; E = E->next()) {
+ preview_scene_dialog->add_filter("*." + E->get() + "; Scene");
+ }
+ main_hs->add_child(preview_scene_dialog);
+ preview_scene_dialog->connect("file_selected", callable_mp(this, &ThemeEditor::_preview_scene_dialog_cbk));
+
+ theme_type_editor = memnew(ThemeTypeEditor);
+ main_hs->add_child(theme_type_editor);
+ theme_type_editor->set_custom_minimum_size(Size2(360, 0) * EDSCALE);
}
void ThemeEditorPlugin::edit(Object *p_node) {
if (Object::cast_to<Theme>(p_node)) {
theme_editor->edit(Object::cast_to<Theme>(p_node));
+ } else if (Object::cast_to<Font>(p_node) || Object::cast_to<StyleBox>(p_node) || Object::cast_to<Texture2D>(p_node)) {
+ // Do nothing, keep editing the existing theme.
} else {
theme_editor->edit(Ref<Theme>());
}
}
bool ThemeEditorPlugin::handles(Object *p_node) const {
- return p_node->is_class("Theme");
+ if (Object::cast_to<Theme>(p_node)) {
+ return true;
+ }
+
+ Ref<Theme> edited_theme = theme_editor->get_edited_theme();
+ if (edited_theme.is_null()) {
+ return false;
+ }
+
+ // If we are editing a theme already and this particular resource happens to belong to it,
+ // then we just keep editing it, despite not being able to directly handle it.
+ // This only goes one layer deep, but if required this can be extended to support, say, FontData inside of Font.
+ bool belongs_to_theme = false;
+
+ if (Object::cast_to<Font>(p_node)) {
+ Ref<Font> font_item = Object::cast_to<Font>(p_node);
+ List<StringName> types;
+ List<StringName> names;
+
+ edited_theme->get_font_type_list(&types);
+ for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
+ names.clear();
+ edited_theme->get_font_list(E->get(), &names);
+
+ for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
+ if (font_item == edited_theme->get_font(F->get(), E->get())) {
+ belongs_to_theme = true;
+ break;
+ }
+ }
+ }
+ } else if (Object::cast_to<StyleBox>(p_node)) {
+ Ref<StyleBox> stylebox_item = Object::cast_to<StyleBox>(p_node);
+ List<StringName> types;
+ List<StringName> names;
+
+ edited_theme->get_stylebox_type_list(&types);
+ for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
+ names.clear();
+ edited_theme->get_stylebox_list(E->get(), &names);
+
+ for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
+ if (stylebox_item == edited_theme->get_stylebox(F->get(), E->get())) {
+ belongs_to_theme = true;
+ break;
+ }
+ }
+ }
+ } else if (Object::cast_to<Texture2D>(p_node)) {
+ Ref<Texture2D> icon_item = Object::cast_to<Texture2D>(p_node);
+ List<StringName> types;
+ List<StringName> names;
+
+ edited_theme->get_icon_type_list(&types);
+ for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
+ names.clear();
+ edited_theme->get_icon_list(E->get(), &names);
+
+ for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
+ if (icon_item == edited_theme->get_icon(F->get(), E->get())) {
+ belongs_to_theme = true;
+ break;
+ }
+ }
+ }
+ }
+
+ return belongs_to_theme;
}
void ThemeEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- theme_editor->set_process(true);
button->show();
editor->make_bottom_panel_item_visible(theme_editor);
} else {
- theme_editor->set_process(false);
if (theme_editor->is_visible_in_tree()) {
editor->hide_bottom_panel();
}
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index c42ebf1a19..77baf46395 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -31,13 +31,13 @@
#ifndef THEME_EDITOR_PLUGIN_H
#define THEME_EDITOR_PLUGIN_H
-#include "scene/gui/check_box.h"
-#include "scene/gui/file_dialog.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/option_button.h"
#include "scene/gui/scroll_container.h"
+#include "scene/gui/tabs.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/theme.h"
+#include "theme_editor_preview.h"
#include "editor/editor_node.h"
@@ -263,30 +263,123 @@ public:
ThemeItemEditorDialog();
};
+class ThemeTypeEditor : public MarginContainer {
+ GDCLASS(ThemeTypeEditor, MarginContainer);
+
+ Ref<Theme> edited_theme;
+ String edited_type;
+ bool updating = false;
+
+ struct LeadingStylebox {
+ bool pinned = false;
+ StringName item_name;
+ Ref<StyleBox> stylebox;
+ Ref<StyleBox> ref_stylebox;
+ };
+
+ LeadingStylebox leading_stylebox;
+
+ OptionButton *theme_type_list;
+ Button *add_type_button;
+ ConfirmationDialog *add_type_dialog;
+ LineEdit *add_type_filter;
+ ItemList *add_type_options;
+
+ CheckButton *show_default_items_button;
+
+ TabContainer *data_type_tabs;
+ VBoxContainer *color_items_list;
+ VBoxContainer *constant_items_list;
+ VBoxContainer *font_items_list;
+ VBoxContainer *font_size_items_list;
+ VBoxContainer *icon_items_list;
+ VBoxContainer *stylebox_items_list;
+
+ Vector<Control *> focusables;
+ Timer *update_debounce_timer;
+
+ VBoxContainer *_create_item_list(Theme::DataType p_data_type);
+ void _update_type_list();
+ void _update_type_list_debounced();
+ void _update_add_type_options(const String &p_filter = "");
+ OrderedHashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default);
+ HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable);
+ void _add_focusable(Control *p_control);
+ void _update_type_items();
+
+ void _list_type_selected(int p_index);
+ void _select_type(String p_type_name);
+ void _add_type_button_cbk();
+ void _add_type_filter_cbk(const String &p_value);
+ void _add_type_options_cbk(int p_index);
+ void _add_type_dialog_confirmed();
+ void _add_type_dialog_entered(const String &p_value);
+ void _add_type_dialog_activated(int p_index);
+ void _add_default_type_items();
+
+ void _item_add_cbk(int p_data_type, Control *p_control);
+ void _item_add_lineedit_cbk(String p_value, int p_data_type, Control *p_control);
+ void _item_override_cbk(int p_data_type, String p_item_name);
+ void _item_remove_cbk(int p_data_type, String p_item_name);
+ void _item_rename_cbk(int p_data_type, String p_item_name, Control *p_control);
+ void _item_rename_confirmed(int p_data_type, String p_item_name, Control *p_control);
+ void _item_rename_entered(String p_value, int p_data_type, String p_item_name, Control *p_control);
+ void _item_rename_canceled(int p_data_type, String p_item_name, Control *p_control);
+
+ void _color_item_changed(Color p_value, String p_item_name);
+ void _constant_item_changed(float p_value, String p_item_name);
+ void _font_size_item_changed(float p_value, String p_item_name);
+ void _edit_resource_item(RES p_resource, Control *p_editor);
+ void _font_item_changed(Ref<Font> p_value, String p_item_name);
+ void _icon_item_changed(Ref<Texture2D> p_value, String p_item_name);
+ void _stylebox_item_changed(Ref<StyleBox> p_value, String p_item_name);
+ void _pin_leading_stylebox(Ref<StyleBox> p_stylebox, String p_item_name);
+ void _unpin_leading_stylebox();
+ void _update_stylebox_from_leading();
+
+protected:
+ void _notification(int p_what);
+
+public:
+ void set_edited_theme(const Ref<Theme> &p_theme);
+ void select_type(String p_type_name);
+
+ ThemeTypeEditor();
+};
+
class ThemeEditor : public VBoxContainer {
GDCLASS(ThemeEditor, VBoxContainer);
Ref<Theme> theme;
- double time_left = 0;
+ Tabs *preview_tabs;
+ PanelContainer *preview_tabs_content;
+ Button *add_preview_button;
+ EditorFileDialog *preview_scene_dialog;
- Button *theme_edit_button;
- ThemeItemEditorDialog *theme_edit_dialog;
+ ThemeTypeEditor *theme_type_editor;
- Panel *main_panel;
- MarginContainer *main_container;
- Tree *test_tree;
+ Label *theme_name;
+ ThemeItemEditorDialog *theme_edit_dialog;
+ void _theme_save_button_cbk(bool p_save_as);
void _theme_edit_button_cbk();
- void _propagate_redraw(Control *p_at);
- void _refresh_interval();
+
+ void _add_preview_button_cbk();
+ void _preview_scene_dialog_cbk(const String &p_path);
+ void _add_preview_tab(ThemeEditorPreview *p_preview_tab, const String &p_preview_name, const Ref<Texture2D> &p_icon);
+ void _change_preview_tab(int p_tab);
+ void _remove_preview_tab(int p_tab);
+ void _remove_preview_tab_invalid(Node *p_tab_control);
+ void _update_preview_tab(Node *p_tab_control);
+ void _preview_control_picked(String p_class_name);
protected:
void _notification(int p_what);
- static void _bind_methods();
public:
void edit(const Ref<Theme> &p_theme);
+ Ref<Theme> get_edited_theme();
ThemeEditor();
};
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
new file mode 100644
index 0000000000..766f8508c1
--- /dev/null
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -0,0 +1,464 @@
+/*************************************************************************/
+/* theme_editor_preview.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "theme_editor_preview.h"
+
+#include "core/input/input.h"
+#include "core/math/math_funcs.h"
+#include "scene/resources/packed_scene.h"
+
+#include "editor/editor_scale.h"
+
+void ThemeEditorPreview::set_preview_theme(const Ref<Theme> &p_theme) {
+ preview_content->set_theme(p_theme);
+}
+
+void ThemeEditorPreview::add_preview_overlay(Control *p_overlay) {
+ preview_overlay->add_child(p_overlay);
+ p_overlay->hide();
+}
+
+void ThemeEditorPreview::_propagate_redraw(Control *p_at) {
+ p_at->notification(NOTIFICATION_THEME_CHANGED);
+ p_at->minimum_size_changed();
+ p_at->update();
+ for (int i = 0; i < p_at->get_child_count(); i++) {
+ Control *a = Object::cast_to<Control>(p_at->get_child(i));
+ if (a) {
+ _propagate_redraw(a);
+ }
+ }
+}
+
+void ThemeEditorPreview::_refresh_interval() {
+ // In case the project settings have changed.
+ preview_bg->set_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
+
+ _propagate_redraw(preview_bg);
+ _propagate_redraw(preview_content);
+}
+
+void ThemeEditorPreview::_preview_visibility_changed() {
+ set_process(is_visible());
+}
+
+void ThemeEditorPreview::_picker_button_cbk() {
+ picker_overlay->set_visible(picker_button->is_pressed());
+}
+
+Control *ThemeEditorPreview::_find_hovered_control(Control *p_parent, Vector2 p_mouse_position) {
+ Control *found = nullptr;
+
+ for (int i = 0; i < p_parent->get_child_count(); i++) {
+ Control *cc = Object::cast_to<Control>(p_parent->get_child(i));
+ if (!cc || !cc->is_visible()) {
+ continue;
+ }
+
+ Rect2 crect = cc->get_rect();
+ if (crect.has_point(p_mouse_position)) {
+ // Check if there is a child control under mouse.
+ if (cc->get_child_count() > 0) {
+ found = _find_hovered_control(cc, p_mouse_position - cc->get_position());
+ }
+
+ // If there are no applicable children, use the control itself.
+ if (!found) {
+ found = cc;
+ }
+ break;
+ }
+ }
+
+ return found;
+}
+
+void ThemeEditorPreview::_draw_picker_overlay() {
+ if (!picker_button->is_pressed()) {
+ return;
+ }
+
+ picker_overlay->draw_rect(Rect2(Vector2(0.0, 0.0), picker_overlay->get_size()), get_theme_color("preview_picker_overlay_color", "ThemeEditor"));
+ if (hovered_control) {
+ Rect2 highlight_rect = hovered_control->get_global_rect();
+ highlight_rect.position = picker_overlay->get_global_transform().affine_inverse().xform(highlight_rect.position);
+
+ picker_overlay->draw_style_box(get_theme_stylebox("preview_picker_overlay", "ThemeEditor"), highlight_rect);
+ }
+}
+
+void ThemeEditorPreview::_gui_input_picker_overlay(const Ref<InputEvent> &p_event) {
+ if (!picker_button->is_pressed()) {
+ return;
+ }
+
+ Ref<InputEventMouseButton> mb = p_event;
+
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (hovered_control) {
+ StringName theme_type = hovered_control->get_theme_custom_type();
+ if (theme_type == StringName()) {
+ theme_type = hovered_control->get_class_name();
+ }
+
+ emit_signal("control_picked", theme_type);
+ picker_button->set_pressed(false);
+ picker_overlay->set_visible(false);
+ }
+ }
+
+ Ref<InputEventMouseMotion> mm = p_event;
+
+ if (mm.is_valid()) {
+ Vector2 mp = preview_content->get_local_mouse_position();
+ hovered_control = _find_hovered_control(preview_content, mp);
+ picker_overlay->update();
+ }
+}
+
+void ThemeEditorPreview::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (is_visible_in_tree()) {
+ set_process(true);
+ }
+
+ connect("visibility_changed", callable_mp(this, &ThemeEditorPreview::_preview_visibility_changed));
+ [[fallthrough]];
+ }
+ case NOTIFICATION_THEME_CHANGED: {
+ picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons"));
+ } break;
+ case NOTIFICATION_PROCESS: {
+ time_left -= get_process_delta_time();
+ if (time_left < 0) {
+ time_left = 1.5;
+ _refresh_interval();
+ }
+ } break;
+ }
+}
+
+void ThemeEditorPreview::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("control_picked", PropertyInfo(Variant::STRING, "class_name")));
+}
+
+ThemeEditorPreview::ThemeEditorPreview() {
+ preview_toolbar = memnew(HBoxContainer);
+ add_child(preview_toolbar);
+
+ picker_button = memnew(Button);
+ preview_toolbar->add_child(picker_button);
+ picker_button->set_flat(true);
+ picker_button->set_toggle_mode(true);
+ picker_button->set_tooltip(TTR("Toggle the control picker, allowing to visually select control types for edit."));
+ picker_button->connect("pressed", callable_mp(this, &ThemeEditorPreview::_picker_button_cbk));
+
+ MarginContainer *preview_body = memnew(MarginContainer);
+ preview_body->set_custom_minimum_size(Size2(480, 0) * EDSCALE);
+ preview_body->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(preview_body);
+
+ ScrollContainer *preview_container = memnew(ScrollContainer);
+ preview_container->set_enable_v_scroll(true);
+ preview_container->set_enable_h_scroll(true);
+ preview_body->add_child(preview_container);
+
+ MarginContainer *preview_root = memnew(MarginContainer);
+ preview_container->add_child(preview_root);
+ preview_root->set_theme(Theme::get_default());
+ preview_root->set_clip_contents(true);
+ preview_root->set_custom_minimum_size(Size2(450, 0) * EDSCALE);
+ preview_root->set_v_size_flags(SIZE_EXPAND_FILL);
+ preview_root->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ preview_bg = memnew(ColorRect);
+ preview_bg->set_anchors_and_offsets_preset(PRESET_WIDE);
+ preview_bg->set_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
+ preview_root->add_child(preview_bg);
+
+ preview_content = memnew(MarginContainer);
+ preview_root->add_child(preview_content);
+ preview_content->add_theme_constant_override("margin_right", 4 * EDSCALE);
+ preview_content->add_theme_constant_override("margin_top", 4 * EDSCALE);
+ preview_content->add_theme_constant_override("margin_left", 4 * EDSCALE);
+ preview_content->add_theme_constant_override("margin_bottom", 4 * EDSCALE);
+
+ preview_overlay = memnew(MarginContainer);
+ preview_overlay->set_mouse_filter(MOUSE_FILTER_IGNORE);
+ preview_body->add_child(preview_overlay);
+
+ picker_overlay = memnew(Control);
+ add_preview_overlay(picker_overlay);
+ picker_overlay->connect("draw", callable_mp(this, &ThemeEditorPreview::_draw_picker_overlay));
+ picker_overlay->connect("gui_input", callable_mp(this, &ThemeEditorPreview::_gui_input_picker_overlay));
+}
+
+DefaultThemeEditorPreview::DefaultThemeEditorPreview() {
+ Panel *main_panel = memnew(Panel);
+ preview_content->add_child(main_panel);
+
+ MarginContainer *main_mc = memnew(MarginContainer);
+ main_mc->add_theme_constant_override("margin_right", 4 * EDSCALE);
+ main_mc->add_theme_constant_override("margin_top", 4 * EDSCALE);
+ main_mc->add_theme_constant_override("margin_left", 4 * EDSCALE);
+ main_mc->add_theme_constant_override("margin_bottom", 4 * EDSCALE);
+ preview_content->add_child(main_mc);
+
+ HBoxContainer *main_hb = memnew(HBoxContainer);
+ main_mc->add_child(main_hb);
+ main_hb->add_theme_constant_override("separation", 20 * EDSCALE);
+
+ VBoxContainer *first_vb = memnew(VBoxContainer);
+ main_hb->add_child(first_vb);
+ first_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ first_vb->add_theme_constant_override("separation", 10 * EDSCALE);
+
+ first_vb->add_child(memnew(Label("Label")));
+
+ first_vb->add_child(memnew(Button("Button")));
+ Button *bt = memnew(Button);
+ bt->set_text(TTR("Toggle Button"));
+ bt->set_toggle_mode(true);
+ bt->set_pressed(true);
+ first_vb->add_child(bt);
+ bt = memnew(Button);
+ bt->set_text(TTR("Disabled Button"));
+ bt->set_disabled(true);
+ first_vb->add_child(bt);
+ Button *tb = memnew(Button);
+ tb->set_flat(true);
+ tb->set_text("Button");
+ first_vb->add_child(tb);
+
+ CheckButton *cb = memnew(CheckButton);
+ cb->set_text("CheckButton");
+ first_vb->add_child(cb);
+ CheckBox *cbx = memnew(CheckBox);
+ cbx->set_text("CheckBox");
+ first_vb->add_child(cbx);
+
+ MenuButton *test_menu_button = memnew(MenuButton);
+ test_menu_button->set_text("MenuButton");
+ test_menu_button->get_popup()->add_item(TTR("Item"));
+ test_menu_button->get_popup()->add_item(TTR("Disabled Item"));
+ test_menu_button->get_popup()->set_item_disabled(1, true);
+ test_menu_button->get_popup()->add_separator();
+ test_menu_button->get_popup()->add_check_item(TTR("Check Item"));
+ test_menu_button->get_popup()->add_check_item(TTR("Checked Item"));
+ test_menu_button->get_popup()->set_item_checked(4, true);
+ test_menu_button->get_popup()->add_separator();
+ test_menu_button->get_popup()->add_radio_check_item(TTR("Radio Item"));
+ test_menu_button->get_popup()->add_radio_check_item(TTR("Checked Radio Item"));
+ test_menu_button->get_popup()->set_item_checked(7, true);
+ test_menu_button->get_popup()->add_separator(TTR("Named Sep."));
+
+ PopupMenu *test_submenu = memnew(PopupMenu);
+ test_menu_button->get_popup()->add_child(test_submenu);
+ test_submenu->set_name("submenu");
+ test_menu_button->get_popup()->add_submenu_item(TTR("Submenu"), "submenu");
+ test_submenu->add_item(TTR("Subitem 1"));
+ test_submenu->add_item(TTR("Subitem 2"));
+ first_vb->add_child(test_menu_button);
+
+ OptionButton *test_option_button = memnew(OptionButton);
+ test_option_button->add_item("OptionButton");
+ test_option_button->add_separator();
+ test_option_button->add_item(TTR("Has"));
+ test_option_button->add_item(TTR("Many"));
+ test_option_button->add_item(TTR("Options"));
+ first_vb->add_child(test_option_button);
+ first_vb->add_child(memnew(ColorPickerButton));
+
+ VBoxContainer *second_vb = memnew(VBoxContainer);
+ second_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ main_hb->add_child(second_vb);
+ second_vb->add_theme_constant_override("separation", 10 * EDSCALE);
+ LineEdit *le = memnew(LineEdit);
+ le->set_text("LineEdit");
+ second_vb->add_child(le);
+ le = memnew(LineEdit);
+ le->set_text(TTR("Disabled LineEdit"));
+ le->set_editable(false);
+ second_vb->add_child(le);
+ TextEdit *te = memnew(TextEdit);
+ te->set_text("TextEdit");
+ te->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
+ second_vb->add_child(te);
+ second_vb->add_child(memnew(SpinBox));
+
+ HBoxContainer *vhb = memnew(HBoxContainer);
+ second_vb->add_child(vhb);
+ vhb->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
+ vhb->add_child(memnew(VSlider));
+ VScrollBar *vsb = memnew(VScrollBar);
+ vsb->set_page(25);
+ vhb->add_child(vsb);
+ vhb->add_child(memnew(VSeparator));
+ VBoxContainer *hvb = memnew(VBoxContainer);
+ vhb->add_child(hvb);
+ hvb->set_alignment(BoxContainer::ALIGN_CENTER);
+ hvb->set_h_size_flags(SIZE_EXPAND_FILL);
+ hvb->add_child(memnew(HSlider));
+ HScrollBar *hsb = memnew(HScrollBar);
+ hsb->set_page(25);
+ hvb->add_child(hsb);
+ HSlider *hs = memnew(HSlider);
+ hs->set_editable(false);
+ hvb->add_child(hs);
+ hvb->add_child(memnew(HSeparator));
+ ProgressBar *pb = memnew(ProgressBar);
+ pb->set_value(50);
+ hvb->add_child(pb);
+
+ VBoxContainer *third_vb = memnew(VBoxContainer);
+ third_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ third_vb->add_theme_constant_override("separation", 10 * EDSCALE);
+ main_hb->add_child(third_vb);
+
+ TabContainer *tc = memnew(TabContainer);
+ third_vb->add_child(tc);
+ tc->set_custom_minimum_size(Size2(0, 135) * EDSCALE);
+ Control *tcc = memnew(Control);
+ tcc->set_name(TTR("Tab 1"));
+ tc->add_child(tcc);
+ tcc = memnew(Control);
+ tcc->set_name(TTR("Tab 2"));
+ tc->add_child(tcc);
+ tcc = memnew(Control);
+ tcc->set_name(TTR("Tab 3"));
+ tc->add_child(tcc);
+ tc->set_tab_disabled(2, true);
+
+ Tree *test_tree = memnew(Tree);
+ third_vb->add_child(test_tree);
+ test_tree->set_custom_minimum_size(Size2(0, 175) * EDSCALE);
+
+ TreeItem *item = test_tree->create_item();
+ item->set_text(0, "Tree");
+ item = test_tree->create_item(test_tree->get_root());
+ item->set_text(0, "Item");
+ item = test_tree->create_item(test_tree->get_root());
+ item->set_editable(0, true);
+ item->set_text(0, TTR("Editable Item"));
+ TreeItem *sub_tree = test_tree->create_item(test_tree->get_root());
+ sub_tree->set_text(0, TTR("Subtree"));
+ item = test_tree->create_item(sub_tree);
+ item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ item->set_editable(0, true);
+ item->set_text(0, "Check Item");
+ item = test_tree->create_item(sub_tree);
+ item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
+ item->set_editable(0, true);
+ item->set_range_config(0, 0, 20, 0.1);
+ item->set_range(0, 2);
+ item = test_tree->create_item(sub_tree);
+ item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
+ item->set_editable(0, true);
+ item->set_text(0, TTR("Has,Many,Options"));
+ item->set_range(0, 2);
+}
+
+void SceneThemeEditorPreview::_reload_scene() {
+ if (loaded_scene.is_null()) {
+ return;
+ }
+
+ if (loaded_scene->get_path().is_empty() || !ResourceLoader::exists(loaded_scene->get_path())) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid path, the PackedScene resource was probably moved or removed."));
+ emit_signal("scene_invalidated");
+ return;
+ }
+
+ for (int i = preview_content->get_child_count() - 1; i >= 0; i--) {
+ Node *node = preview_content->get_child(i);
+ node->queue_delete();
+ preview_content->remove_child(node);
+ }
+
+ Node *instance = loaded_scene->instance();
+ if (!instance || !Object::cast_to<Control>(instance)) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid PackedScene resource, must have a Control node at its root."));
+ emit_signal("scene_invalidated");
+ return;
+ }
+
+ preview_content->add_child(instance);
+ emit_signal("scene_reloaded");
+}
+
+void SceneThemeEditorPreview::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ reload_scene_button->set_icon(get_theme_icon("Reload", "EditorIcons"));
+ } break;
+ }
+}
+
+void SceneThemeEditorPreview::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("scene_invalidated"));
+ ADD_SIGNAL(MethodInfo("scene_reloaded"));
+}
+
+bool SceneThemeEditorPreview::set_preview_scene(const String &p_path) {
+ loaded_scene = ResourceLoader::load(p_path);
+ if (loaded_scene.is_null()) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid file, not a PackedScene resource."));
+ return false;
+ }
+
+ Node *instance = loaded_scene->instance();
+ if (!instance || !Object::cast_to<Control>(instance)) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid PackedScene resource, must have a Control node at its root."));
+ return false;
+ }
+
+ preview_content->add_child(instance);
+ return true;
+}
+
+String SceneThemeEditorPreview::get_preview_scene_path() const {
+ if (loaded_scene.is_null()) {
+ return "";
+ }
+
+ return loaded_scene->get_path();
+}
+
+SceneThemeEditorPreview::SceneThemeEditorPreview() {
+ preview_toolbar->add_child(memnew(VSeparator));
+
+ reload_scene_button = memnew(Button);
+ reload_scene_button->set_flat(true);
+ reload_scene_button->set_tooltip(TTR("Reload the scene to reflect its most actual state."));
+ preview_toolbar->add_child(reload_scene_button);
+ reload_scene_button->connect("pressed", callable_mp(this, &SceneThemeEditorPreview::_reload_scene));
+}
diff --git a/editor/plugins/theme_editor_preview.h b/editor/plugins/theme_editor_preview.h
new file mode 100644
index 0000000000..efb7e424d4
--- /dev/null
+++ b/editor/plugins/theme_editor_preview.h
@@ -0,0 +1,118 @@
+/*************************************************************************/
+/* theme_editor_preview.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef THEME_EDITOR_PREVIEW_H
+#define THEME_EDITOR_PREVIEW_H
+
+#include "scene/gui/box_container.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/color_picker.h"
+#include "scene/gui/color_rect.h"
+#include "scene/gui/label.h"
+#include "scene/gui/margin_container.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/panel.h"
+#include "scene/gui/progress_bar.h"
+#include "scene/gui/scroll_container.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/spin_box.h"
+#include "scene/gui/tab_container.h"
+#include "scene/gui/text_edit.h"
+#include "scene/gui/tree.h"
+#include "scene/resources/theme.h"
+
+#include "editor/editor_node.h"
+
+class ThemeEditorPreview : public VBoxContainer {
+ GDCLASS(ThemeEditorPreview, VBoxContainer);
+
+ ColorRect *preview_bg;
+ MarginContainer *preview_overlay;
+ Control *picker_overlay;
+ Control *hovered_control = nullptr;
+
+ double time_left = 0;
+
+ void _propagate_redraw(Control *p_at);
+ void _refresh_interval();
+ void _preview_visibility_changed();
+
+ void _picker_button_cbk();
+ Control *_find_hovered_control(Control *p_parent, Vector2 p_mouse_position);
+
+ void _draw_picker_overlay();
+ void _gui_input_picker_overlay(const Ref<InputEvent> &p_event);
+
+protected:
+ HBoxContainer *preview_toolbar;
+ MarginContainer *preview_content;
+ Button *picker_button;
+
+ void add_preview_overlay(Control *p_overlay);
+
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_preview_theme(const Ref<Theme> &p_theme);
+
+ ThemeEditorPreview();
+};
+
+class DefaultThemeEditorPreview : public ThemeEditorPreview {
+ GDCLASS(DefaultThemeEditorPreview, ThemeEditorPreview);
+
+public:
+ DefaultThemeEditorPreview();
+};
+
+class SceneThemeEditorPreview : public ThemeEditorPreview {
+ GDCLASS(SceneThemeEditorPreview, ThemeEditorPreview);
+
+ Ref<PackedScene> loaded_scene;
+
+ Button *reload_scene_button;
+
+ void _reload_scene();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ bool set_preview_scene(const String &p_path);
+ String get_preview_scene_path() const;
+
+ SceneThemeEditorPreview();
+};
+
+#endif // THEME_EDITOR_PREVIEW_H
diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp
index 4f7eabac24..78f181e321 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -39,9 +39,10 @@
#include "scene/gui/texture_rect.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
void TileAtlasView::_gui_input(const Ref<InputEvent> &p_event) {
- bool ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL);
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
@@ -195,9 +196,9 @@ void TileAtlasView::_base_tiles_root_control_gui_input(const Ref<InputEvent> &p_
if (mm.is_valid()) {
Transform2D xform = base_tiles_drawing_root->get_transform().affine_inverse();
Vector2i coords = get_atlas_tile_coords_at_pos(xform.xform(mm->get_position()));
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
coords = tile_set_atlas_source->get_tile_at_coords(coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
base_tiles_root_control->set_tooltip(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: 0"), source_id, coords));
}
}
@@ -215,7 +216,7 @@ void TileAtlasView::_draw_base_tiles() {
for (int x = 0; x < grid_size.x; x++) {
for (int y = 0; y < grid_size.y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
Rect2i rect = Rect2i(texture_region_size * coords + margins, texture_region_size);
base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
}
@@ -229,17 +230,23 @@ void TileAtlasView::_draw_base_tiles() {
rect.set_end(Vector2i(texture->get_size().x, margins.y));
base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
// Bottom
- rect.position = Vector2i(0, margins.y + (grid_size.y * texture_region_size.y));
- rect.set_end(texture->get_size());
- base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
+ int bottom_border = margins.y + (grid_size.y * texture_region_size.y);
+ if (bottom_border < texture->get_size().y) {
+ rect.position = Vector2i(0, bottom_border);
+ rect.set_end(texture->get_size());
+ base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
+ }
// Left
rect.position = Vector2i(0, margins.y);
rect.set_end(Vector2i(margins.x, margins.y + (grid_size.y * texture_region_size.y)));
base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
// Right.
- rect.position = Vector2i(margins.x + (grid_size.x * texture_region_size.x), margins.y);
- rect.set_end(Vector2i(texture->get_size().x, margins.y + (grid_size.y * texture_region_size.y)));
- base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
+ int right_border = margins.x + (grid_size.x * texture_region_size.x);
+ if (right_border < texture->get_size().x) {
+ rect.position = Vector2i(right_border, margins.y);
+ rect.set_end(Vector2i(texture->get_size().x, margins.y + (grid_size.y * texture_region_size.y)));
+ base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
+ }
// Draw actual tiles, using their properties (modulation, etc...)
for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
@@ -249,7 +256,7 @@ void TileAtlasView::_draw_base_tiles() {
Vector2i offset_pos = (margins + (atlas_coords * texture_region_size) + tile_set_atlas_source->get_tile_texture_region(atlas_coords).size / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, 0));
// Draw the tile.
- TileSetAtlasPluginRendering::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0);
+ TileSetPluginAtlasRendering::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0);
}
}
}
@@ -268,7 +275,7 @@ void TileAtlasView::_draw_base_tiles_texture_grid() {
for (int y = 0; y < grid_size.y; y++) {
Vector2i origin = margins + (Vector2i(x, y) * (texture_region_size + separation));
Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
- if (base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
if (base_tile_coords == Vector2i(x, y)) {
// Draw existing tile.
Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(base_tile_coords);
@@ -299,7 +306,7 @@ void TileAtlasView::_draw_base_tiles_dark() {
Vector2i origin = margins + (Vector2i(x, y) * (texture_region_size + separation));
Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
- if (base_tile_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (base_tile_coords == TileSetSource::INVALID_ATLAS_COORDS) {
// Draw the grid.
base_tiles_dark->draw_rect(Rect2i(origin, texture_region_size), Color(0.0, 0.0, 0.0, 0.5), true);
}
@@ -310,6 +317,7 @@ void TileAtlasView::_draw_base_tiles_dark() {
void TileAtlasView::_draw_base_tiles_shape_grid() {
// Draw the shapes.
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
Vector2i tile_shape_size = tile_set->get_tile_size();
for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
Vector2i tile_id = tile_set_atlas_source->get_tile_id(i);
@@ -318,7 +326,7 @@ void TileAtlasView::_draw_base_tiles_shape_grid() {
Vector2 origin = texture_region.position + (texture_region.size - tile_shape_size) / 2 + in_tile_base_offset;
// Draw only if the tile shape fits in the texture region
- tile_set->draw_tile_shape(base_tiles_shape_grid, Rect2(origin, tile_shape_size), Color(1.0, 0.5, 0.2, 0.8));
+ tile_set->draw_tile_shape(base_tiles_shape_grid, Rect2(origin, tile_shape_size), grid_color);
}
}
@@ -331,7 +339,7 @@ void TileAtlasView::_alternative_tiles_root_control_gui_input(const Ref<InputEve
Vector3i coords3 = get_alternative_tile_at_pos(xform.xform(mm->get_position()));
Vector2i coords = Vector2i(coords3.x, coords3.y);
int alternative_id = coords3.z;
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative_id != TileSetSource::INVALID_TILE_ALTERNATIVE) {
alternative_tiles_root_control->set_tooltip(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: %d"), source_id, coords, alternative_id));
}
}
@@ -364,7 +372,7 @@ void TileAtlasView::_draw_alternatives() {
}
// Draw the tile.
- TileSetAtlasPluginRendering::draw_tile(alternatives_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, alternative_id);
+ TileSetPluginAtlasRendering::draw_tile(alternatives_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, alternative_id);
// Increment the x position.
current_pos.x += transposed ? texture_region.size.y : texture_region.size.x;
@@ -464,7 +472,7 @@ Vector2i TileAtlasView::get_atlas_tile_coords_at_pos(const Vector2 p_pos) const
return ret;
}
- return TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ return TileSetSource::INVALID_ATLAS_COORDS;
}
void TileAtlasView::_update_alternative_tiles_rect_cache() {
@@ -506,7 +514,7 @@ Vector3i TileAtlasView::get_alternative_tile_at_pos(const Vector2 p_pos) const {
}
}
- return Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ return Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
Rect2i TileAtlasView::get_alternative_tile_rect(const Vector2i p_coords, int p_alternative_tile) {
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 0b674bec39..61457e3e59 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -113,7 +113,22 @@ void TileDataPositionEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform
ERR_FAIL_COND(value.get_type() != Variant::VECTOR2I && value.get_type() != Variant::VECTOR2);
Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon("EditorPosition", "EditorIcons");
- p_canvas_item->draw_texture(position_icon, p_transform.get_origin() + Vector2(value) - position_icon->get_size() / 2);
+ p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(value)) - position_icon->get_size() / 2);
+}
+
+void TileDataYSortEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
+ TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+ ERR_FAIL_COND(!tile_data);
+
+ bool valid;
+ Variant value = tile_data->get(p_property, &valid);
+ if (!valid) {
+ return;
+ }
+ ERR_FAIL_COND(value.get_type() != Variant::INT);
+
+ Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon("EditorPosition", "EditorIcons");
+ p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(0, value)) - position_icon->get_size() / 2);
}
void TileDataOcclusionShapeEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
@@ -166,7 +181,7 @@ void TileDataTerrainsEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform
Vector<String> components = String(p_property).split("/", true);
if (components[0] == "terrain_mode" || components[0] == "terrain" || components[0] == "terrains_peering_bit") {
- TileSetAtlasPluginTerrain::draw_terrains(p_canvas_item, p_transform, p_tile_set, tile_data);
+ TileSetPluginAtlasTerrain::draw_terrains(p_canvas_item, p_transform, p_tile_set, tile_data);
}
}
diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h
index f4f9c25157..b82189e1ee 100644
--- a/editor/plugins/tiles/tile_data_editors.h
+++ b/editor/plugins/tiles/tile_data_editors.h
@@ -79,6 +79,13 @@ public:
virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
};
+class TileDataYSortEditor : public TileDataEditor {
+ GDCLASS(TileDataYSortEditor, TileDataEditor);
+
+public:
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+};
+
class TileDataOcclusionShapeEditor : public TileDataEditor {
GDCLASS(TileDataOcclusionShapeEditor, TileDataEditor);
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 5937472e2b..ef13d8ea12 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -32,6 +32,7 @@
#include "tiles_editor_plugin.h"
+#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
@@ -55,18 +56,25 @@ void TileMapEditorTilesPlugin::_notification(int p_what) {
picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons"));
erase_button->set_icon(get_theme_icon("Eraser", "EditorIcons"));
- missing_texture_texture = get_theme_icon("TileSet", "EditorIcons");
+ toggle_grid_button->set_icon(get_theme_icon("Grid", "EditorIcons"));
+
+ missing_atlas_texture_icon = get_theme_icon("TileSet", "EditorIcons");
+
+ toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
break;
case NOTIFICATION_VISIBILITY_CHANGED:
_stop_dragging();
+ break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED:
+ toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
+ break;
}
}
void TileMapEditorTilesPlugin::tile_set_changed() {
_update_fix_selected_and_hovered();
- _update_bottom_panel();
_update_tile_set_sources_list();
- _update_atlas_view();
+ _update_bottom_panel();
}
void TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled(bool p_pressed) {
@@ -77,6 +85,10 @@ void TileMapEditorTilesPlugin::_on_scattering_spinbox_changed(double p_value) {
scattering = p_value;
}
+void TileMapEditorTilesPlugin::_on_grid_toggled(bool p_pressed) {
+ EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed);
+}
+
void TileMapEditorTilesPlugin::_update_toolbar() {
// Stop draggig if needed.
_stop_dragging();
@@ -146,19 +158,38 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
for (int i = 0; i < tile_set->get_source_count(); i++) {
int source_id = tile_set->get_source_id(i);
- // TODO: handle with virtual functions
TileSetSource *source = *tile_set->get_source(source_id);
+
+ Ref<Texture2D> texture;
+ String item_text;
+
+ // Atlas source.
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
- Ref<Texture2D> texture = atlas_source->get_texture();
+ texture = atlas_source->get_texture();
if (texture.is_valid()) {
- sources_list->add_item(vformat("%s - (id:%d)", texture->get_path().get_file(), source_id), texture);
+ item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
} else {
- sources_list->add_item(vformat("No Texture Atlas Source - (id:%d)", source_id), missing_texture_texture);
+ item_text = vformat("No Texture Atlas Source (id:%d)", source_id);
}
- } else {
- sources_list->add_item(vformat("Unknown Type Source - (id:%d)", source_id), missing_texture_texture);
}
+
+ // Scene collection source.
+ TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ if (scene_collection_source) {
+ texture = get_theme_icon("PackedScene", "EditorIcons");
+ item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id);
+ }
+
+ // Use default if not valid.
+ if (item_text.is_empty()) {
+ item_text = vformat(TTR("Unknown Type Source (id:%d)"), source_id);
+ }
+ if (!texture.is_valid()) {
+ texture = missing_atlas_texture_icon;
+ }
+
+ sources_list->add_item(item_text, texture);
sources_list->set_item_metadata(i, source_id);
}
@@ -176,7 +207,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current());
}
-void TileMapEditorTilesPlugin::_update_atlas_view() {
+void TileMapEditorTilesPlugin::_update_bottom_panel() {
// Update the atlas display.
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
@@ -185,39 +216,161 @@ void TileMapEditorTilesPlugin::_update_atlas_view() {
Ref<TileSet> tile_set = tile_map->get_tileset();
if (!tile_set.is_valid()) {
- tile_atlas_view->hide();
return;
}
int source_index = sources_list->get_current();
if (source_index >= 0 && source_index < sources_list->get_item_count()) {
+ atlas_sources_split_container->show();
+ missing_source_label->hide();
+
int source_id = sources_list->get_item_metadata(source_index);
TileSetSource *source = *tile_set->get_source(source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+
if (atlas_source) {
- tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id);
tile_atlas_view->show();
+ scene_tiles_list->hide();
+ invalid_source_label->hide();
+ _update_atlas_view();
+ } else if (scenes_collection_source) {
+ tile_atlas_view->hide();
+ scene_tiles_list->show();
+ invalid_source_label->hide();
+ _update_scenes_collection_view();
+ } else {
+ tile_atlas_view->hide();
+ scene_tiles_list->hide();
+ invalid_source_label->show();
}
} else {
+ atlas_sources_split_container->hide();
+ missing_source_label->show();
+
tile_atlas_view->hide();
+ scene_tiles_list->hide();
+ invalid_source_label->hide();
}
+}
- // Synchronize atlas view.
- TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view);
+void TileMapEditorTilesPlugin::_update_atlas_view() {
+ TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
+ if (!tile_map) {
+ return;
+ }
+ Ref<TileSet> tile_set = tile_map->get_tileset();
+ if (!tile_set.is_valid()) {
+ return;
+ }
+
+ int source_id = sources_list->get_item_metadata(sources_list->get_current());
+ TileSetSource *source = *tile_set->get_source(source_id);
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ ERR_FAIL_COND(!atlas_source);
+
+ tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id);
+ TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view);
tile_atlas_control->update();
}
-void TileMapEditorTilesPlugin::_update_bottom_panel() {
+void TileMapEditorTilesPlugin::_update_scenes_collection_view() {
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
return;
}
+
Ref<TileSet> tile_set = tile_map->get_tileset();
+ if (!tile_set.is_valid()) {
+ return;
+ }
+
+ int source_id = sources_list->get_item_metadata(sources_list->get_current());
+ TileSetSource *source = *tile_set->get_source(source_id);
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ ERR_FAIL_COND(!scenes_collection_source);
+
+ // Clear the list.
+ scene_tiles_list->clear();
- // Update the tabs.
- missing_source_label->set_visible(tile_set.is_valid() && tile_set->get_source_count() == 0);
- atlas_sources_split_container->set_visible(tile_set.is_valid() && tile_set->get_source_count() > 0);
+ // Rebuild the list.
+ for (int i = 0; i < scenes_collection_source->get_scene_tiles_count(); i++) {
+ int scene_id = scenes_collection_source->get_scene_tile_id(i);
+
+ Ref<PackedScene> scene = scenes_collection_source->get_scene_tile_scene(scene_id);
+
+ int item_index = 0;
+ if (scene.is_valid()) {
+ item_index = scene_tiles_list->add_item(vformat("%s (path:%s id:%d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id));
+ Variant udata = i;
+ EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata);
+ } else {
+ item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons"));
+ }
+ scene_tiles_list->set_item_metadata(item_index, scene_id);
+
+ // Check if in selection.
+ if (tile_set_selection.has(TileMapCell(source_id, Vector2i(), scene_id))) {
+ scene_tiles_list->select(item_index, false);
+ }
+ }
+
+ // Icon size update.
+ int int_size = int(EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size")) * EDSCALE;
+ scene_tiles_list->set_fixed_icon_size(Vector2(int_size, int_size));
+}
+
+void TileMapEditorTilesPlugin::_scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) {
+ int index = p_ud;
+
+ if (index >= 0 && index < scene_tiles_list->get_item_count()) {
+ scene_tiles_list->set_item_icon(index, p_preview);
+ }
+}
+
+void TileMapEditorTilesPlugin::_scenes_list_multi_selected(int p_index, bool p_selected) {
+ TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
+ if (!tile_map) {
+ return;
+ }
+
+ Ref<TileSet> tile_set = tile_map->get_tileset();
+ if (!tile_set.is_valid()) {
+ return;
+ }
+
+ // Add or remove the Tile form the selection.
+ int scene_id = scene_tiles_list->get_item_metadata(p_index);
+ int source_id = sources_list->get_item_metadata(sources_list->get_current());
+ TileSetSource *source = *tile_set->get_source(source_id);
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ ERR_FAIL_COND(!scenes_collection_source);
+
+ TileMapCell selected = TileMapCell(source_id, Vector2i(), scene_id);
+
+ // Clear the selection if shift is not pressed.
+ if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ tile_set_selection.clear();
+ }
+
+ if (p_selected) {
+ tile_set_selection.insert(selected);
+ } else {
+ if (tile_set_selection.has(selected)) {
+ tile_set_selection.erase(selected);
+ }
+ }
+
+ _update_selection_pattern_from_tileset_selection();
+}
+
+void TileMapEditorTilesPlugin::_scenes_list_nothing_selected() {
+ scene_tiles_list->deselect_all();
+ tile_set_selection.clear();
+ tile_map_selection.clear();
+ selection_pattern->clear();
+ _update_selection_pattern_from_tileset_selection();
}
bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
@@ -257,7 +410,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!tile_map_selection.is_empty()) {
undo_redo->create_action(TTR("Delete tiles"));
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
- undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get()));
}
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
@@ -288,7 +441,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!tile_map_selection.is_empty()) {
undo_redo->create_action(TTR("Delete tiles"));
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
- undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get()));
}
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
@@ -357,14 +510,14 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
// Pressed
if (tool_buttons_group->get_pressed_button() == select_tool_button) {
drag_start_mouse_pos = mpos;
- if (tile_map_selection.has(tile_map->world_to_map(drag_start_mouse_pos)) && !mb->get_shift()) {
+ if (tile_map_selection.has(tile_map->world_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed()) {
// Move the selection
drag_type = DRAG_TYPE_MOVE;
drag_modified.clear();
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
Vector2i coords = E->get();
drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
- tile_map->set_cell(coords, -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ tile_map->set_cell(coords, -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
} else {
// Select tiles
@@ -460,14 +613,16 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
// Draw the selection.
if (is_visible_in_tree() && tool_buttons_group->get_pressed_button() == select_tool_button) {
// In select mode, we only draw the current selection if we are modifying it (pressing control or shift).
- if (drag_type == DRAG_TYPE_MOVE || (drag_type == DRAG_TYPE_SELECT && !Input::get_singleton()->is_key_pressed(KEY_CONTROL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ if (drag_type == DRAG_TYPE_MOVE || (drag_type == DRAG_TYPE_SELECT && !Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
// Do nothing
} else {
- tile_map->draw_cells_outline(p_overlay, tile_map_selection, Color(0.0, 0.0, 1.0), xform);
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+ tile_map->draw_cells_outline(p_overlay, tile_map_selection, selection_color, xform);
}
}
- // handle the preview of the tiles to be placed.
+ // Handle the preview of the tiles to be placed.
if (is_visible_in_tree() && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered.
Map<Vector2i, TileMapCell> preview;
Rect2i drawn_grid_rect;
@@ -562,32 +717,37 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
const int fading = 5;
// Draw the lines of the grid behind the preview.
- if (drawn_grid_rect.size.x > 0 && drawn_grid_rect.size.y > 0) {
- drawn_grid_rect = drawn_grid_rect.grow(fading);
- for (int x = drawn_grid_rect.position.x; x < (drawn_grid_rect.position.x + drawn_grid_rect.size.x); x++) {
- for (int y = drawn_grid_rect.position.y; y < (drawn_grid_rect.position.y + drawn_grid_rect.size.y); y++) {
- Vector2i pos_in_rect = Vector2i(x, y) - drawn_grid_rect.position;
-
- // Fade out the border of the grid.
- float left_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.x), 0.0f, 1.0f);
- float right_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.x, (float)(drawn_grid_rect.size.x - fading), (float)pos_in_rect.x), 0.0f, 1.0f);
- float top_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.y), 0.0f, 1.0f);
- float bottom_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.y, (float)(drawn_grid_rect.size.y - fading), (float)pos_in_rect.y), 0.0f, 1.0f);
- float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
-
- Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(Vector2(x, y)) - tile_shape_size / 2, tile_shape_size));
- tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 0.5, 0.2, 0.5 * opacity), false);
+ bool display_grid = EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid");
+ if (display_grid) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ if (drawn_grid_rect.size.x > 0 && drawn_grid_rect.size.y > 0) {
+ drawn_grid_rect = drawn_grid_rect.grow(fading);
+ for (int x = drawn_grid_rect.position.x; x < (drawn_grid_rect.position.x + drawn_grid_rect.size.x); x++) {
+ for (int y = drawn_grid_rect.position.y; y < (drawn_grid_rect.position.y + drawn_grid_rect.size.y); y++) {
+ Vector2i pos_in_rect = Vector2i(x, y) - drawn_grid_rect.position;
+
+ // Fade out the border of the grid.
+ float left_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.x), 0.0f, 1.0f);
+ float right_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.x, (float)(drawn_grid_rect.size.x - fading), (float)pos_in_rect.x), 0.0f, 1.0f);
+ float top_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.y), 0.0f, 1.0f);
+ float bottom_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.y, (float)(drawn_grid_rect.size.y - fading), (float)pos_in_rect.y), 0.0f, 1.0f);
+ float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
+
+ Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(Vector2(x, y)) - tile_shape_size / 2, tile_shape_size));
+ Color color = grid_color;
+ color.a = color.a * opacity;
+ tile_set->draw_tile_shape(p_overlay, cell_region, color, false);
+ }
}
}
}
// Draw the preview.
for (Map<Vector2i, TileMapCell>::Element *E = preview.front(); E; E = E->next()) {
+ Vector2i size = tile_set->get_tile_size();
+ Vector2 position = tile_map->map_to_world(E->key()) - size / 2;
+ Rect2 cell_region = xform.xform(Rect2(position, size));
if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) {
- Vector2i size = tile_set->get_tile_size();
- Vector2 position = tile_map->map_to_world(E->key()) - size / 2;
- Rect2 cell_region = xform.xform(Rect2(position, size));
-
tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0, 0.5), true);
} else {
if (tile_set->has_source(E->get().source_id)) {
@@ -629,12 +789,10 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
// Draw the tile.
p_overlay->draw_texture_rect_region(atlas_source->get_texture(), dest_rect, source_rect, modulate * Color(1.0, 1.0, 1.0, 0.5), transpose, tile_set->is_uv_clipping());
+ } else {
+ tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0, 0.5), true);
}
} else {
- Vector2i size = tile_set->get_tile_size();
- Vector2 position = tile_map->map_to_world(E->key()) - size / 2;
- Rect2 cell_region = xform.xform(Rect2(position, size));
-
tile_set->draw_tile_shape(p_overlay, cell_region, Color(0.0, 0.0, 0.0, 0.5), true);
}
}
@@ -669,7 +827,9 @@ TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(const TileMapPattern *p_
TileSetSource *source = *tile_set->get_source(source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
- sum += Object::cast_to<TileData>(atlas_source->get_tile_data(atlas_coords, alternative_tile))->get_probability();
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(atlas_coords, alternative_tile));
+ ERR_FAIL_COND_V(!tile_data, TileMapCell());
+ sum += tile_data->get_probability();
} else {
sum += 1.0;
}
@@ -698,7 +858,7 @@ TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(const TileMapPattern *p_
return TileMapCell();
}
-Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2i p_to_mouse_pos) {
+Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos) {
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
return Map<Vector2i, TileMapCell>();
@@ -711,7 +871,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
Map<Vector2i, TileMapCell> output;
@@ -763,7 +923,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
// Compute the offset to align things to the bottom or right.
@@ -814,7 +974,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
Map<Vector2i, TileMapCell> output;
@@ -930,14 +1090,14 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
undo_redo->create_action(TTR("Change selection"));
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
- if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT) && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT) && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
tile_map_selection.clear();
}
Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos) - tile_map->world_to_map(drag_start_mouse_pos)).abs();
for (int x = rect.position.x; x <= rect.get_end().x; x++) {
for (int y = rect.position.y; y <= rect.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
if (tile_map_selection.has(coords)) {
tile_map_selection.erase(coords);
}
@@ -1090,8 +1250,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
hovered_tile.source_id = -1;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
tile_map_selection.clear();
selection_pattern->clear();
@@ -1101,8 +1261,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
Ref<TileSet> tile_set = tile_map->get_tileset();
if (!tile_set.is_valid()) {
hovered_tile.source_id = -1;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
tile_map_selection.clear();
selection_pattern->clear();
@@ -1112,8 +1272,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
int source_index = sources_list->get_current();
if (source_index < 0 || source_index >= sources_list->get_item_count()) {
hovered_tile.source_id = -1;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
tile_map_selection.clear();
selection_pattern->clear();
@@ -1128,8 +1288,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
!tile_set->get_source(hovered_tile.source_id)->has_tile(hovered_tile.get_atlas_coords()) ||
!tile_set->get_source(hovered_tile.source_id)->has_alternative_tile(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)) {
hovered_tile.source_id = -1;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
}
// Selection if needed.
@@ -1187,6 +1347,7 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection(
per_source[E->get().source_id].push_back(&(E->get()));
}
+ int vertical_offset = 0;
for (Map<int, List<const TileMapCell *>>::Element *E_source = per_source.front(); E_source; E_source = E_source->next()) {
// Per source.
List<const TileMapCell *> unorganized;
@@ -1199,24 +1360,21 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection(
// Organize using coordinates.
for (List<const TileMapCell *>::Element *E_cell = E_source->get().front(); E_cell; E_cell = E_cell->next()) {
const TileMapCell *current = E_cell->get();
- if (organized_pattern.has(current->get_atlas_coords())) {
- if (current->alternative_tile < organized_pattern[current->get_atlas_coords()]->alternative_tile) {
- unorganized.push_back(organized_pattern[current->get_atlas_coords()]);
- organized_pattern[current->get_atlas_coords()] = current;
- } else {
- unorganized.push_back(current);
- }
- } else {
+ if (current->alternative_tile == 0) {
organized_pattern[current->get_atlas_coords()] = current;
+ } else {
+ unorganized.push_back(current);
}
}
// Compute the encompassing rect for the organized pattern.
Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front();
- encompassing_rect_coords = Rect2i(E_cell->key(), Vector2i(1, 1));
- for (; E_cell; E_cell = E_cell->next()) {
- encompassing_rect_coords.expand_to(E_cell->key() + Vector2i(1, 1));
- encompassing_rect_coords.expand_to(E_cell->key());
+ if (E_cell) {
+ encompassing_rect_coords = Rect2i(E_cell->key(), Vector2i(1, 1));
+ for (; E_cell; E_cell = E_cell->next()) {
+ encompassing_rect_coords.expand_to(E_cell->key() + Vector2i(1, 1));
+ encompassing_rect_coords.expand_to(E_cell->key());
+ }
}
} else {
// Add everything unorganized.
@@ -1227,12 +1385,15 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection(
// Now add everything to the output pattern.
for (Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front(); E_cell; E_cell = E_cell->next()) {
- selection_pattern->set_cell(E_cell->key() - encompassing_rect_coords.position, E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile);
+ selection_pattern->set_cell(E_cell->key() - encompassing_rect_coords.position + Vector2i(0, vertical_offset), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile);
}
Vector2i organized_size = selection_pattern->get_size();
+ int unorganized_index = 0;
for (List<const TileMapCell *>::Element *E_cell = unorganized.front(); E_cell; E_cell = E_cell->next()) {
- selection_pattern->set_cell(Vector2(organized_size.x, 0), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile);
+ selection_pattern->set_cell(Vector2(organized_size.x + unorganized_index, vertical_offset), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile);
+ unorganized_index++;
}
+ vertical_offset += MAX(organized_size.y, 1);
}
CanvasItemEditor::get_singleton()->update_viewport();
}
@@ -1246,7 +1407,7 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern(
tile_set_selection.insert(TileMapCell(selection_pattern->get_cell_source_id(coords), selection_pattern->get_cell_atlas_coords(coords), selection_pattern->get_cell_alternative_tile(coords)));
}
}
- _update_atlas_view();
+ _update_bottom_panel();
}
void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
@@ -1276,14 +1437,16 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
}
// Draw the selection.
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) {
if (E->get().source_id == source_id && E->get().alternative_tile == 0) {
- tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E->get().get_atlas_coords()), Color(0.0, 0.0, 1.0), false);
+ tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E->get().get_atlas_coords()), selection_color, false);
}
}
// Draw the hovered tile.
- if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) {
+ if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) {
tile_atlas_control->draw_rect(atlas->get_tile_texture_region(hovered_tile.get_atlas_coords()), Color(1.0, 1.0, 1.0), false);
}
@@ -1299,22 +1462,22 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
for (int x = region.position.x; x < region.get_end().x; x++) {
for (int y = region.position.y; y < region.get_end().y; y++) {
Vector2i tile = atlas->get_tile_at_coords(Vector2i(x, y));
- if (tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile != TileSetSource::INVALID_ATLAS_COORDS) {
to_draw.insert(tile);
}
}
}
-
+ Color selection_rect_color = selection_color.lightened(0.2);
for (Set<Vector2i>::Element *E = to_draw.front(); E; E = E->next()) {
- tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E->get()), Color(0.8, 0.8, 1.0), false);
+ tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E->get()), selection_rect_color, false);
}
}
}
void TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited() {
hovered_tile.source_id = -1;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_dragging_selection = false;
tile_atlas_control->update();
}
@@ -1347,12 +1510,12 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
// Update the hovered tile
hovered_tile.source_id = source_id;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
coords = atlas->get_tile_at_coords(coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
hovered_tile.set_atlas_coords(coords);
hovered_tile.alternative_tile = 0;
}
@@ -1369,12 +1532,12 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
if (mb->is_pressed()) { // Pressed
tile_set_dragging_selection = true;
tile_set_drag_start_mouse_pos = tile_atlas_control->get_local_mouse_position();
- if (!mb->get_shift()) {
+ if (!mb->is_shift_pressed()) {
tile_set_selection.clear();
}
- if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0) {
- if (mb->get_shift() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0))) {
+ if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0) {
+ if (mb->is_shift_pressed() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0))) {
tile_set_selection.erase(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0));
} else {
tile_set_selection.insert(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0));
@@ -1383,24 +1546,24 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
_update_selection_pattern_from_tileset_selection();
} else { // Released
if (tile_set_dragging_selection) {
- if (!mb->get_shift()) {
+ if (!mb->is_shift_pressed()) {
tile_set_selection.clear();
}
// Compute the covered area.
Vector2i start_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_set_drag_start_mouse_pos);
Vector2i end_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
- if (start_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && end_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (start_tile != TileSetSource::INVALID_ATLAS_COORDS && end_tile != TileSetSource::INVALID_ATLAS_COORDS) {
Rect2i region = Rect2i(start_tile, end_tile - start_tile).abs();
region.size += Vector2i(1, 1);
// To update the selection, we copy the selected/not selected status of the tiles we drag from.
Vector2i start_coords = atlas->get_tile_at_coords(start_tile);
- if (mb->get_shift() && start_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && !tile_set_selection.has(TileMapCell(source_id, start_coords, 0))) {
+ if (mb->is_shift_pressed() && start_coords != TileSetSource::INVALID_ATLAS_COORDS && !tile_set_selection.has(TileMapCell(source_id, start_coords, 0))) {
// Remove from the selection.
for (int x = region.position.x; x < region.get_end().x; x++) {
for (int y = region.position.y; y < region.get_end().y; y++) {
Vector2i tile_coords = atlas->get_tile_at_coords(Vector2i(x, y));
- if (tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_selection.has(TileMapCell(source_id, tile_coords, 0))) {
+ if (tile_coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_selection.has(TileMapCell(source_id, tile_coords, 0))) {
tile_set_selection.erase(TileMapCell(source_id, tile_coords, 0));
}
}
@@ -1410,7 +1573,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
for (int x = region.position.x; x < region.get_end().x; x++) {
for (int y = region.position.y; y < region.get_end().y; y++) {
Vector2i tile_coords = atlas->get_tile_at_coords(Vector2i(x, y));
- if (tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
tile_set_selection.insert(TileMapCell(source_id, tile_coords, 0));
}
}
@@ -1453,7 +1616,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
// Draw the selection.
for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) {
- if (E->get().source_id == source_id && E->get().get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && E->get().alternative_tile > 0) {
+ if (E->get().source_id == source_id && E->get().get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && E->get().alternative_tile > 0) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E->get().get_atlas_coords(), E->get().alternative_tile);
if (rect != Rect2i()) {
alternative_tiles_control->draw_rect(rect, Color(0.2, 0.2, 1.0), false);
@@ -1462,7 +1625,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
}
// Draw hovered tile.
- if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) {
+ if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile);
if (rect != Rect2i()) {
alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false);
@@ -1472,8 +1635,8 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
void TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited() {
hovered_tile.source_id = -1;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_dragging_selection = false;
alternative_tiles_control->update();
}
@@ -1506,12 +1669,12 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In
// Update the hovered tile
hovered_tile.source_id = source_id;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
Vector3i alternative_coords = tile_atlas_view->get_alternative_tile_at_pos(alternative_tiles_control->get_local_mouse_position());
Vector2i coords = Vector2i(alternative_coords.x, alternative_coords.y);
int alternative = alternative_coords.z;
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative != TileSetSource::INVALID_TILE_ALTERNATIVE) {
hovered_tile.set_atlas_coords(coords);
hovered_tile.alternative_tile = alternative;
}
@@ -1526,12 +1689,12 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In
if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) { // Pressed
// Left click pressed.
- if (!mb->get_shift()) {
+ if (!mb->is_shift_pressed()) {
tile_set_selection.clear();
}
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
- if (mb->get_shift() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile))) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ if (mb->is_shift_pressed() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile))) {
tile_set_selection.erase(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile));
} else {
tile_set_selection.insert(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile));
@@ -1565,13 +1728,14 @@ TypedArray<Vector2i> TileMapEditorTilesPlugin::_get_tile_map_selection() const {
void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id) {
tile_map_id = p_tile_map_id;
- // Clean the selection.
+ // Clear the selection.
tile_set_selection.clear();
tile_map_selection.clear();
selection_pattern->clear();
}
void TileMapEditorTilesPlugin::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileMapEditorTilesPlugin::_scene_thumbnail_done);
ClassDB::bind_method(D_METHOD("_set_tile_map_selection", "selection"), &TileMapEditorTilesPlugin::_set_tile_map_selection);
ClassDB::bind_method(D_METHOD("_get_tile_map_selection"), &TileMapEditorTilesPlugin::_get_tile_map_selection);
}
@@ -1588,6 +1752,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
// --- Toolbar ---
toolbar = memnew(HBoxContainer);
+ toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
HBoxContainer *tilemap_tiles_tools_buttons = memnew(HBoxContainer);
@@ -1632,7 +1797,6 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", KEY_B));
bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
-
toolbar->add_child(tilemap_tiles_tools_buttons);
// -- TileMap tool settings --
@@ -1692,6 +1856,18 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
_on_random_tile_checkbox_toggled(false);
+ // Wide empty separation control.
+ Control *h_empty_space = memnew(Control);
+ h_empty_space->set_h_size_flags(SIZE_EXPAND_FILL);
+ toolbar->add_child(h_empty_space);
+
+ // Grid toggle.
+ toggle_grid_button = memnew(Button);
+ toggle_grid_button->set_flat(true);
+ toggle_grid_button->set_toggle_mode(true);
+ toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditorTilesPlugin::_on_grid_toggled));
+ toolbar->add_child(toggle_grid_button);
+
// Default tool.
paint_tool_button->set_pressed(true);
_update_toolbar();
@@ -1718,20 +1894,20 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
sources_list->set_h_size_flags(SIZE_EXPAND_FILL);
sources_list->set_stretch_ratio(0.25);
sources_list->set_custom_minimum_size(Size2i(70, 0) * EDSCALE);
+ sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
- sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_atlas_view).unbind(1));
+ sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_bottom_panel).unbind(1));
sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current));
sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list));
- //sources_list->set_drag_forwarding(this);
atlas_sources_split_container->add_child(sources_list);
+ // Tile atlas source.
tile_atlas_view = memnew(TileAtlasView);
tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL);
tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL);
tile_atlas_view->set_texture_grid_visible(false);
tile_atlas_view->set_tile_shape_grid_visible(false);
tile_atlas_view->connect("transform_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_view_transform));
- //tile_atlas_view->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_view), varray(tile_atlas_view));
atlas_sources_split_container->add_child(tile_atlas_view);
tile_atlas_control = memnew(Control);
@@ -1746,6 +1922,27 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
alternative_tiles_control->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input));
tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control);
+ // Scenes collection source.
+ scene_tiles_list = memnew(ItemList);
+ scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ scene_tiles_list->set_drag_forwarding(this);
+ scene_tiles_list->set_select_mode(ItemList::SELECT_MULTI);
+ scene_tiles_list->connect("multi_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_multi_selected));
+ scene_tiles_list->connect("nothing_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_nothing_selected));
+ scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+ atlas_sources_split_container->add_child(scene_tiles_list);
+
+ // Invalid source label.
+ invalid_source_label = memnew(Label);
+ invalid_source_label->set_text(TTR("Invalid source selected."));
+ invalid_source_label->set_h_size_flags(SIZE_EXPAND_FILL);
+ invalid_source_label->set_v_size_flags(SIZE_EXPAND_FILL);
+ invalid_source_label->set_align(Label::ALIGN_CENTER);
+ invalid_source_label->set_valign(Label::VALIGN_CENTER);
+ invalid_source_label->hide();
+ atlas_sources_split_container->add_child(invalid_source_label);
+
_update_bottom_panel();
}
@@ -2147,7 +2344,7 @@ Set<TileMapEditorTerrainsPlugin::Constraint> TileMapEditorTerrainsPlugin::_get_c
Map<int, int> terrain_count;
- // Count the number of occurences per terrain.
+ // Count the number of occurrences per terrain.
Map<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits();
for (Map<Vector2i, TileSet::CellNeighbor>::Element *E_overlapping = overlapping_terrain_bits.front(); E_overlapping; E_overlapping = E_overlapping->next()) {
if (!p_to_replace.has(E_overlapping->key())) {
@@ -2165,7 +2362,7 @@ Set<TileMapEditorTerrainsPlugin::Constraint> TileMapEditorTerrainsPlugin::_get_c
}
}
- // Get the terrain with the max number of occurences.
+ // Get the terrain with the max number of occurrences.
int max = 0;
int max_terrain = -1;
for (Map<int, int>::Element *E_terrain_count = terrain_count.front(); E_terrain_count; E_terrain_count = E_terrain_count->next()) {
@@ -2231,7 +2428,7 @@ Map<Vector2i, TileMapEditorTerrainsPlugin::TerrainsTilePattern> TileMapEditorTer
per_cell_acceptable_tiles[E->get()] = _get_valid_terrains_tile_patterns_for_constraints(p_terrain_set, E->get(), constraints);
}
- // Ouput map.
+ // Output map.
Map<Vector2i, TerrainsTilePattern> output;
// Add all positions to a set.
@@ -2450,7 +2647,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map
output[E->key()] = _get_random_tile_from_pattern(p_terrain_set, E->get());
}
- // Override the WFC results to make sure at least the painted tiles are acutally painted.
+ // Override the WFC results to make sure at least the painted tiles are actually painted.
for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) {
output[E_to_paint->key()] = _get_random_tile_from_pattern(p_terrain_set, E_to_paint->get());
}
@@ -2587,7 +2784,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
}
if (need_tree_item_switch) {
- for (tree_item = terrains_tree->get_root()->get_children(); tree_item; tree_item = tree_item->get_next_visible()) {
+ for (tree_item = terrains_tree->get_root()->get_first_child(); tree_item; tree_item = tree_item->get_next_visible()) {
Dictionary metadata_dict = tree_item->get_metadata(0);
if (metadata_dict.has("terrain_set") && metadata_dict.has("terrain_id")) {
int terrain_set = metadata_dict["terrain_set"];
@@ -2771,8 +2968,8 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
TileMapCell empty_cell;
empty_cell.source_id = -1;
- empty_cell.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- empty_cell.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ empty_cell.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ empty_cell.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
per_terrain_terrains_tile_patterns_tiles[i][empty_pattern].insert(empty_cell);
}
}
@@ -3263,19 +3460,25 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
}
// Draw the grid.
- for (int x = displayed_rect.position.x; x < (displayed_rect.position.x + displayed_rect.size.x); x++) {
- for (int y = displayed_rect.position.y; y < (displayed_rect.position.y + displayed_rect.size.y); y++) {
- Vector2i pos_in_rect = Vector2i(x, y) - displayed_rect.position;
+ bool display_grid = EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid");
+ if (display_grid) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ for (int x = displayed_rect.position.x; x < (displayed_rect.position.x + displayed_rect.size.x); x++) {
+ for (int y = displayed_rect.position.y; y < (displayed_rect.position.y + displayed_rect.size.y); y++) {
+ Vector2i pos_in_rect = Vector2i(x, y) - displayed_rect.position;
- // Fade out the border of the grid.
- float left_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.x), 0.0f, 1.0f);
- float right_opacity = CLAMP(Math::inverse_lerp((float)displayed_rect.size.x, (float)(displayed_rect.size.x - fading), (float)pos_in_rect.x), 0.0f, 1.0f);
- float top_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.y), 0.0f, 1.0f);
- float bottom_opacity = CLAMP(Math::inverse_lerp((float)displayed_rect.size.y, (float)(displayed_rect.size.y - fading), (float)pos_in_rect.y), 0.0f, 1.0f);
- float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
+ // Fade out the border of the grid.
+ float left_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.x), 0.0f, 1.0f);
+ float right_opacity = CLAMP(Math::inverse_lerp((float)displayed_rect.size.x, (float)(displayed_rect.size.x - fading), (float)pos_in_rect.x), 0.0f, 1.0f);
+ float top_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.y), 0.0f, 1.0f);
+ float bottom_opacity = CLAMP(Math::inverse_lerp((float)displayed_rect.size.y, (float)(displayed_rect.size.y - fading), (float)pos_in_rect.y), 0.0f, 1.0f);
+ float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
- Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(Vector2(x, y)) - tile_shape_size / 2, tile_shape_size));
- tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 0.5, 0.2, 0.5 * opacity), false);
+ Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(Vector2(x, y)) - tile_shape_size / 2, tile_shape_size));
+ Color color = grid_color;
+ color.a = color.a * opacity;
+ tile_set->draw_tile_shape(p_overlay, cell_region, color, false);
+ }
}
}
@@ -3337,9 +3540,8 @@ TileMapEditor::TileMapEditor() {
// --- TileMap toolbar ---
tilemap_toolbar = memnew(HBoxContainer);
- //tilemap_toolbar->add_child(memnew(VSeparator));
+ tilemap_toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
tilemap_toolbar->add_child(tabs);
- //tilemap_toolbar->add_child(memnew(VSeparator));
for (int i = 0; i < tile_map_editor_plugins.size(); i++) {
tile_map_editor_plugins[i]->get_toolbar()->hide();
tilemap_toolbar->add_child(tile_map_editor_plugins[i]->get_toolbar());
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index f780686b82..a6f4ec3021 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -58,7 +58,7 @@ private:
ObjectID tile_map_id;
virtual void edit(ObjectID p_tile_map_id) override;
- // Toolbar.
+ ///// Toolbar /////
HBoxContainer *toolbar;
Ref<ButtonGroup> tool_buttons_group;
@@ -82,9 +82,12 @@ private:
void _on_random_tile_checkbox_toggled(bool p_pressed);
void _on_scattering_spinbox_changed(double p_value);
+ Button *toggle_grid_button;
+ void _on_grid_toggled(bool p_pressed);
+
void _update_toolbar();
- // Tilemap editing.
+ ///// Tilemap editing. /////
bool has_mouse = false;
void _mouse_exited_viewport();
@@ -105,12 +108,12 @@ private:
Map<Vector2i, TileMapCell> drag_modified;
TileMapCell _pick_random_tile(const TileMapPattern *p_pattern);
- Map<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2i p_to_mouse_pos);
- Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_mouse_pos, Vector2i p_end_mouse_pos);
+ Map<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos);
+ Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell);
Map<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous);
void _stop_dragging();
- // Selection system.
+ ///// Selection system. /////
Set<Vector2i> tile_map_selection;
TileMapPattern *tile_map_clipboard = memnew(TileMapPattern);
TileMapPattern *selection_pattern = memnew(TileMapPattern);
@@ -124,22 +127,24 @@ private:
void _update_tileset_selection_from_selection_pattern();
void _update_fix_selected_and_hovered();
- // Bottom panel.
- bool tile_set_dragging_selection = false;
- Vector2i tile_set_drag_start_mouse_pos;
-
+ ///// Bottom panel. ////.
Label *missing_source_label;
- HSplitContainer *atlas_sources_split_container;
+ Label *invalid_source_label;
ItemList *sources_list;
- TileAtlasView *tile_atlas_view;
- Ref<Texture2D> missing_texture_texture;
+
+ Ref<Texture2D> missing_atlas_texture_icon;
void _update_tile_set_sources_list();
- void _update_atlas_view();
void _update_bottom_panel();
+ // Atlas sources.
TileMapCell hovered_tile;
+ TileAtlasView *tile_atlas_view;
+ HSplitContainer *atlas_sources_split_container;
+
+ bool tile_set_dragging_selection = false;
+ Vector2i tile_set_drag_start_mouse_pos;
Control *tile_atlas_control;
void _tile_atlas_control_mouse_exited();
@@ -151,6 +156,16 @@ private:
void _tile_alternatives_control_mouse_exited();
void _tile_alternatives_control_gui_input(const Ref<InputEvent> &p_event);
+ void _update_atlas_view();
+
+ // Scenes collection sources.
+ ItemList *scene_tiles_list;
+
+ void _update_scenes_collection_view();
+ void _scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud);
+ void _scenes_list_multi_selected(int p_index, bool p_selected);
+ void _scenes_list_nothing_selected();
+
// Update callback
virtual void tile_set_changed() override;
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 69abbb29f1..8e7d613027 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -53,10 +53,10 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id(int p_id) {
if (source_id == p_id) {
return;
}
- ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet atlas source ID. Another atlas source exists with id %d.", p_id));
+ ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet Atlas Source ID. Another source exists with id %d.", p_id));
int previous_source = source_id;
- source_id = p_id; // source_id must be updated before, because it's used by the atlas source list update.
+ source_id = p_id; // source_id must be updated before, because it's used by the source list update.
tile_set->set_source_id(previous_source, p_id);
emit_signal("changed", "id");
}
@@ -126,7 +126,7 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::edit(Ref<TileSet>
}
// -- Proxy object used by the tile inspector --
-bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, const Variant &p_value) {
+bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_name, const Variant &p_value) {
if (!tile_set_atlas_source) {
return false;
}
@@ -152,9 +152,9 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, c
return true;
} else if (alternative == 0 && p_name == "size_in_atlas") {
Vector2i as_vector2i = Vector2i(p_value);
- ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetAtlasSource::INVALID_ATLAS_COORDS, as_vector2i), false);
+ ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i), false);
- tile_set_atlas_source->move_tile_in_atlas(coords, TileSetAtlasSource::INVALID_ATLAS_COORDS, as_vector2i);
+ tile_set_atlas_source->move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i);
emit_signal("changed", "size_in_atlas");
return true;
} else if (alternative > 0 && p_name == "alternative_id") {
@@ -197,7 +197,7 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, c
return any_valid;
}
-bool TileSetAtlasSourceEditor::TileProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
+bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
if (!tile_set_atlas_source) {
return false;
}
@@ -237,7 +237,7 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_get(const StringName &p_name, V
return false;
}
-void TileSetAtlasSourceEditor::TileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
+void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
if (!tile_set_atlas_source) {
return;
}
@@ -310,12 +310,11 @@ void TileSetAtlasSourceEditor::TileProxyObject::_get_property_list(List<Property
}
}
-void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id, Set<TileSelection> p_tiles) {
+void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles) {
ERR_FAIL_COND(!p_tile_set_atlas_source);
- ERR_FAIL_COND(p_source_id < 0);
ERR_FAIL_COND(p_tiles.is_empty());
for (Set<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) {
- ERR_FAIL_COND(E->get().tile == TileSetAtlasSource::INVALID_ATLAS_COORDS);
+ ERR_FAIL_COND(E->get().tile == TileSetSource::INVALID_ATLAS_COORDS);
ERR_FAIL_COND(E->get().alternative < 0);
}
@@ -333,7 +332,6 @@ void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_
}
tile_set_atlas_source = p_tile_set_atlas_source;
- source_id = p_source_id;
tiles = Set<TileSelection>(p_tiles);
// Connect to changes.
@@ -352,7 +350,7 @@ void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_
notify_property_list_changed();
}
-void TileSetAtlasSourceEditor::TileProxyObject::_bind_methods() {
+void TileSetAtlasSourceEditor::AtlasTileProxyObject::_bind_methods() {
ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
}
@@ -391,12 +389,12 @@ void TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles() {
// Fix hovered.
if (!tile_set_atlas_source->has_tile(hovered_base_tile_coords)) {
- hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
}
Vector2i coords = Vector2i(hovered_alternative_tile_coords.x, hovered_alternative_tile_coords.y);
int alternative = hovered_alternative_tile_coords.z;
if (!tile_set_atlas_source->has_tile(coords) || !tile_set_atlas_source->has_alternative_tile(coords, alternative)) {
- hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
}
@@ -405,7 +403,7 @@ void TileSetAtlasSourceEditor::_update_tile_inspector() {
// Update the proxy object.
if (has_atlas_tile_selected) {
- tile_proxy_object->edit(tile_set_atlas_source, tile_set_atlas_source_id, selection);
+ tile_proxy_object->edit(tile_set_atlas_source, selection);
}
// Update visibility.
@@ -486,7 +484,7 @@ void TileSetAtlasSourceEditor::_update_toolbar() {
}
void TileSetAtlasSourceEditor::_tile_atlas_control_mouse_exited() {
- hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
tile_atlas_control->update();
tile_atlas_control_unscaled->update();
tile_atlas_view->update();
@@ -514,7 +512,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
if (selection.size() == 1) {
// Change the cursor depending on the hovered thing.
TileSelection selected = selection.front()->get();
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
@@ -560,7 +558,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
for (int i = 0; i < line.size(); i++) {
- if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetSource::INVALID_ATLAS_COORDS) {
tile_set_atlas_source->create_tile(line[i]);
drag_modified_tiles.insert(line[i]);
}
@@ -576,7 +574,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
for (int i = 0; i < line.size(); i++) {
Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(line[i]);
- if (base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
drag_modified_tiles.insert(base_tile_coords);
}
}
@@ -662,17 +660,17 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Remove a first tile.
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
coords = tile_set_atlas_source->get_tile_at_coords(coords);
}
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
drag_modified_tiles.insert(coords);
}
} else {
- if (mb->get_shift()) {
+ if (mb->is_shift_pressed()) {
// Create a big tile.
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
// Setup the dragging info, only if we start on an empty tile.
drag_type = DRAG_TYPE_CREATE_BIG_TILE;
drag_start_mouse_pos = mouse_local_pos;
@@ -692,7 +690,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Create a first tile if needed.
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
tile_set_atlas_source->create_tile(coords);
drag_modified_tiles.insert(coords);
}
@@ -707,10 +705,10 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
drag_start_mouse_pos = mouse_local_pos;
drag_last_mouse_pos = drag_start_mouse_pos;
} else {
- if (mb->get_shift()) {
+ if (mb->is_shift_pressed()) {
// Create a big tile.
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
// Setup the dragging info, only if we start on an empty tile.
drag_type = DRAG_TYPE_CREATE_BIG_TILE;
drag_start_mouse_pos = mouse_local_pos;
@@ -732,7 +730,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
drag_type = DRAG_TYPE_NONE;
if (selection.size() == 1) {
TileSelection selected = selection.front()->get();
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
@@ -771,17 +769,17 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Selecting then dragging a tile.
if (drag_type == DRAG_TYPE_NONE) {
- TileSelection selected = { TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE };
+ TileSelection selected = { TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE };
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
coords = tile_set_atlas_source->get_tile_at_coords(coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
selected = { coords, 0 };
}
}
- bool shift = mb->get_shift();
- if (!shift && selection.size() == 1 && selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
+ bool shift = mb->is_shift_pressed();
+ if (!shift && selection.size() == 1 && selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
// Start move dragging.
drag_type = DRAG_TYPE_MOVE_TILE;
drag_start_mouse_pos = mouse_local_pos;
@@ -812,13 +810,13 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Right click pressed.
TileSelection selected = { tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos), 0 };
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
selected.tile = tile_set_atlas_source->get_tile_at_coords(selected.tile);
}
// Set the selection if needed.
if (selection.size() <= 1) {
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
undo_redo->create_action(TTR("Select tiles"));
undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
selection.clear();
@@ -831,15 +829,15 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
}
// Pops up the correct menu, depending on whether we have a tile or not.
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
// We have a tile.
menu_option_coords = selected.tile;
menu_option_alternative = 0;
base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
- } else if (hovered_base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ } else if (hovered_base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
// We don't have a tile, but can create one.
menu_option_coords = hovered_base_tile_coords;
- menu_option_alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
empty_base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
}
} else {
@@ -902,7 +900,7 @@ void TileSetAtlasSourceEditor::_end_dragging() {
for (int x = area.get_position().x; x < area.get_end().x; x++) {
for (int y = area.get_position().y; y < area.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
undo_redo->add_do_method(tile_set_atlas_source, "create_tile", coords);
undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", coords);
}
@@ -923,7 +921,7 @@ void TileSetAtlasSourceEditor::_end_dragging() {
for (int x = area.get_position().x; x < area.get_end().x; x++) {
for (int y = area.get_position().y; y < area.get_end().y; y++) {
Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
to_delete.insert(coords);
}
}
@@ -964,8 +962,8 @@ void TileSetAtlasSourceEditor::_end_dragging() {
case DRAG_TYPE_RECT_SELECT: {
Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
- ERR_FAIL_COND(start_base_tiles_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS);
- ERR_FAIL_COND(new_base_tiles_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS);
+ ERR_FAIL_COND(start_base_tiles_coords == TileSetSource::INVALID_ATLAS_COORDS);
+ ERR_FAIL_COND(new_base_tiles_coords == TileSetSource::INVALID_ATLAS_COORDS);
Rect2i region = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
region.size += Vector2i(1, 1);
@@ -977,7 +975,7 @@ void TileSetAtlasSourceEditor::_end_dragging() {
bool add_to_selection = true;
if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
Vector2i coords = tile_set_atlas_source->get_tile_at_coords(start_base_tiles_coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
if (selection.has({ coords, 0 })) {
add_to_selection = false;
}
@@ -991,7 +989,7 @@ void TileSetAtlasSourceEditor::_end_dragging() {
for (int y = region.position.y; y < region.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
coords = tile_set_atlas_source->get_tile_at_coords(coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
if (add_to_selection && !selection.has({ coords, 0 })) {
selection.insert({ coords, 0 });
} else if (!add_to_selection && selection.has({ coords, 0 })) {
@@ -1180,6 +1178,10 @@ Array TileSetAtlasSourceEditor::_get_selection_as_array() {
}
void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
+ // Colors.
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+
// Draw the selected tile.
if (tools_button_group->get_pressed_button() == tool_select_button) {
for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
@@ -1187,7 +1189,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
if (selected.alternative == 0) {
// Draw the rect.
Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
- tile_atlas_control->draw_rect(region, Color(0.2, 0.2, 1.0), false);
+ tile_atlas_control->draw_rect(region, selection_color, false);
}
}
@@ -1236,14 +1238,14 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
Color color = Color(0.0, 0.0, 0.0);
if (drag_type == DRAG_TYPE_RECT_SELECT) {
- color = Color(0.5, 0.5, 1.0);
+ color = selection_color.lightened(0.2);
}
Set<Vector2i> to_paint;
for (int x = area.get_position().x; x < area.get_end().x; x++) {
for (int y = area.get_position().y; y < area.get_end().y; y++) {
Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
to_paint.insert(coords);
}
}
@@ -1266,7 +1268,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
for (int x = area.get_position().x; x < area.get_end().x; x++) {
for (int y = area.get_position().y; y < area.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
Vector2i origin = margins + (coords * (tile_size + separation));
tile_atlas_control->draw_rect(Rect2i(origin, tile_size), Color(1.0, 1.0, 1.0), false);
}
@@ -1290,7 +1292,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
if (hovered_base_tile_coords.x >= 0 && hovered_base_tile_coords.y >= 0 && hovered_base_tile_coords.x < grid_size.x && hovered_base_tile_coords.y < grid_size.y) {
Vector2i hovered_tile = tile_set_atlas_source->get_tile_at_coords(hovered_base_tile_coords);
- if (hovered_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (hovered_tile != TileSetSource::INVALID_ATLAS_COORDS) {
// Draw existing hovered tile.
tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(hovered_tile), Color(1.0, 1.0, 1.0), false);
} else {
@@ -1349,7 +1351,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
selection.clear();
TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) };
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
selection.insert(selected);
}
@@ -1364,7 +1366,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
selection.clear();
TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) };
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
selection.insert(selected);
}
@@ -1387,7 +1389,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
}
void TileSetAtlasSourceEditor::_tile_alternatives_control_mouse_exited() {
- hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
tile_atlas_control->update();
tile_atlas_control_unscaled->update();
alternative_tiles_control->update();
@@ -1395,11 +1397,14 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_mouse_exited() {
}
void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+
// Update the hovered alternative tile.
if (tools_button_group->get_pressed_button() == tool_select_button) {
// Draw hovered tile.
Vector2i coords = Vector2(hovered_alternative_tile_coords.x, hovered_alternative_tile_coords.y);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, hovered_alternative_tile_coords.z);
if (rect != Rect2i()) {
alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false);
@@ -1412,7 +1417,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
if (selected.alternative >= 1) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(selected.tile, selected.alternative);
if (rect != Rect2i()) {
- alternative_tiles_control->draw_rect(rect, Color(0.2, 0.2, 1.0), false);
+ alternative_tiles_control->draw_rect(rect, selection_color, false);
}
}
}
@@ -1441,7 +1446,7 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
#define ADD_UNDO(obj, property) undo_redo->add_undo_property(obj, property, tile_data->get(property));
- TileProxyObject *tile_data = Object::cast_to<TileProxyObject>(p_edited);
+ AtlasTileProxyObject *tile_data = Object::cast_to<AtlasTileProxyObject>(p_edited);
if (tile_data) {
Vector<String> components = String(p_property).split("/", true, 2);
if (components.size() == 2 && components[1] == "shapes_count") {
@@ -1518,7 +1523,7 @@ void TileSetAtlasSourceEditor::_auto_create_tiles() {
for (int x = 0; x < grid_size.x; x++) {
// Check if we have a tile at the coord
Vector2i coords = Vector2i(x, y);
- if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
// Check if the texture is empty at the given coords.
Rect2i region = Rect2i(margins + (coords * (texture_region_size + separation)), texture_region_size);
bool is_opaque = false;
@@ -1673,7 +1678,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_inspector_label->hide();
middle_vbox_container->add_child(tile_inspector_label);
- tile_proxy_object = memnew(TileProxyObject(this));
+ tile_proxy_object = memnew(AtlasTileProxyObject(this));
tile_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1));
tile_inspector = memnew(EditorInspector);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index ff68aa8288..70f2cdbe01 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -45,8 +45,8 @@ class TileSetAtlasSourceEditor : public HBoxContainer {
private:
// A class to store which tiles are selected.
struct TileSelection {
- Vector2i tile = TileSetAtlasSource::INVALID_ATLAS_COORDS;
- int alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ Vector2i tile = TileSetSource::INVALID_ATLAS_COORDS;
+ int alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
bool operator<(const TileSelection &p_other) const {
if (tile == p_other.tile) {
@@ -80,14 +80,13 @@ private:
};
// -- Proxy object for a tile, needed by the inspector --
- class TileProxyObject : public Object {
- GDCLASS(TileProxyObject, Object);
+ class AtlasTileProxyObject : public Object {
+ GDCLASS(AtlasTileProxyObject, Object);
private:
TileSetAtlasSourceEditor *tiles_set_atlas_source_editor;
TileSetAtlasSource *tile_set_atlas_source = nullptr;
- int source_id;
Set<TileSelection> tiles = Set<TileSelection>();
protected:
@@ -99,10 +98,10 @@ private:
public:
// Update the proxyed object.
- void edit(TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id = -1, Set<TileSelection> p_tiles = Set<TileSelection>());
+ void edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles = Set<TileSelection>());
- TileProxyObject(TileSetAtlasSourceEditor *p_tiles_editor_source_tab) {
- tiles_set_atlas_source_editor = p_tiles_editor_source_tab;
+ AtlasTileProxyObject(TileSetAtlasSourceEditor *p_tiles_set_atlas_source_editor) {
+ tiles_set_atlas_source_editor = p_tiles_set_atlas_source_editor;
}
};
@@ -115,7 +114,7 @@ private:
bool tile_set_atlas_source_changed_needs_update = false;
// -- Inspector --
- TileProxyObject *tile_proxy_object;
+ AtlasTileProxyObject *tile_proxy_object;
Label *tile_inspector_label;
EditorInspector *tile_inspector;
String selected_property;
@@ -175,7 +174,7 @@ private:
ADVANCED_AUTO_REMOVE_TILES,
};
Vector2i menu_option_coords;
- int menu_option_alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ int menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
void _menu_option(int p_option);
// Tool buttons.
@@ -198,7 +197,7 @@ private:
Array _get_selection_as_array();
// A control on the tile atlas to draw and handle input events.
- Vector2i hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ Vector2i hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
PopupMenu *base_tile_popup_menu;
PopupMenu *empty_base_tile_popup_menu;
@@ -213,7 +212,7 @@ private:
void _tile_atlas_view_transform_changed();
// A control over the alternative tiles.
- Vector3i hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ Vector3i hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
PopupMenu *alternative_tile_popup_menu;
Control *alternative_tiles_control;
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 8a5890e9a4..11842981f3 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -76,7 +76,7 @@ void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, C
tile_set_atlas_source_editor->init_source();
}
- // Update the selected source (thus trigerring an update).
+ // Update the selected source (thus triggering an update).
_update_atlas_sources_list(source_id);
}
}
@@ -140,20 +140,39 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
for (int i = 0; i < tile_set->get_source_count(); i++) {
int source_id = tile_set->get_source_id(i);
- // TODO: handle with virtual functions
TileSetSource *source = *tile_set->get_source(source_id);
+
+ Ref<Texture2D> texture;
+ String item_text;
+
+ // Atlas source.
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
- Ref<Texture2D> texture = atlas_source->get_texture();
+ texture = atlas_source->get_texture();
if (texture.is_valid()) {
- sources_list->add_item(vformat("%s - (id:%d)", texture->get_path().get_file(), source_id), texture);
+ item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
} else {
- sources_list->add_item(vformat("No texture atlas source - (id:%d)", source_id), missing_texture_texture);
+ item_text = vformat(TTR("No Texture Atlas Source (id:%d)"), source_id);
}
- } else {
- sources_list->add_item(vformat("Unknown type source - (id:%d)", source_id), missing_texture_texture);
}
- sources_list->set_item_metadata(sources_list->get_item_count() - 1, source_id);
+
+ // Scene collection source.
+ TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ if (scene_collection_source) {
+ texture = get_theme_icon("PackedScene", "EditorIcons");
+ item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id);
+ }
+
+ // Use default if not valid.
+ if (item_text.is_empty()) {
+ item_text = vformat(TTR("Unknown Type Source (id:%d)"), source_id);
+ }
+ if (!texture.is_valid()) {
+ texture = missing_texture_texture;
+ }
+
+ sources_list->add_item(item_text, texture);
+ sources_list->set_item_metadata(i, source_id);
}
// Set again the current selected item if needed.
@@ -193,35 +212,63 @@ void TileSetEditor::_source_selected(int p_source_index) {
if (p_source_index >= 0) {
int source_id = sources_list->get_item_metadata(p_source_index);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(source_id));
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(*tile_set->get_source(source_id));
if (atlas_source) {
- tile_set_atlas_source_editor->edit(*tile_set, atlas_source, source_id);
no_source_selected_label->hide();
+ tile_set_atlas_source_editor->edit(*tile_set, atlas_source, source_id);
tile_set_atlas_source_editor->show();
+ tile_set_scenes_collection_source_editor->hide();
+ } else if (scenes_collection_source) {
+ no_source_selected_label->hide();
+ tile_set_atlas_source_editor->hide();
+ tile_set_scenes_collection_source_editor->edit(*tile_set, scenes_collection_source, source_id);
+ tile_set_scenes_collection_source_editor->show();
} else {
no_source_selected_label->show();
tile_set_atlas_source_editor->hide();
+ tile_set_scenes_collection_source_editor->hide();
}
} else {
no_source_selected_label->show();
tile_set_atlas_source_editor->hide();
+ tile_set_scenes_collection_source_editor->hide();
}
}
-void TileSetEditor::_source_add_pressed() {
+void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
ERR_FAIL_COND(!tile_set.is_valid());
- int source_id = tile_set->get_next_source_id();
+ switch (p_id_pressed) {
+ case 0: {
+ int source_id = tile_set->get_next_source_id();
- Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
+ Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
- // Add a new source.
- undo_redo->create_action(TTR("Add atlas source"));
- undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
- undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
- undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
- undo_redo->commit_action();
+ // Add a new source.
+ undo_redo->create_action(TTR("Add atlas source"));
+ undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
+ undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
+ undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
+ undo_redo->commit_action();
+
+ _update_atlas_sources_list(source_id);
+ } break;
+ case 1: {
+ int source_id = tile_set->get_next_source_id();
+
+ Ref<TileSetScenesCollectionSource> scene_collection_source = memnew(TileSetScenesCollectionSource);
+
+ // Add a new source.
+ undo_redo->create_action(TTR("Add atlas source"));
+ undo_redo->add_do_method(*tile_set, "add_source", scene_collection_source, source_id);
+ undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
+ undo_redo->commit_action();
- _update_atlas_sources_list(source_id);
+ _update_atlas_sources_list(source_id);
+ } break;
+ default:
+ ERR_FAIL();
+ }
}
void TileSetEditor::_source_delete_pressed() {
@@ -251,6 +298,9 @@ void TileSetEditor::_notification(int p_what) {
break;
case NOTIFICATION_INTERNAL_PROCESS:
if (tile_set_changed_needs_update) {
+ if (tile_set.is_valid()) {
+ tile_set->set_edited(true);
+ }
_update_atlas_sources_list();
tile_set_changed_needs_update = false;
}
@@ -386,8 +436,8 @@ void TileSetEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p
}
void TileSetEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &TileSetEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &TileSetEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &TileSetEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &TileSetEditor::drop_data_fw);
}
TileDataEditor *TileSetEditor::get_tile_data_editor(String p_property) {
@@ -398,7 +448,7 @@ TileDataEditor *TileSetEditor::get_tile_data_editor(String p_property) {
} else if (p_property == "probability") {
return tile_data_float_editor;
} else if (p_property == "y_sort_origin") {
- return tile_data_position_editor;
+ return tile_data_y_sort_editor;
} else if (p_property == "texture_offset") {
return tile_data_texture_offset_editor;
} else if (components.size() >= 1 && components[0].begins_with("occlusion_layer_")) {
@@ -434,6 +484,7 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
}
tile_set_atlas_source_editor->hide();
+ tile_set_scenes_collection_source_editor->hide();
no_source_selected_label->show();
}
@@ -464,6 +515,7 @@ TileSetEditor::TileSetEditor() {
sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected));
sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current));
sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list));
+ sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
sources_list->set_drag_forwarding(this);
split_container_left_side->add_child(sources_list);
@@ -477,11 +529,19 @@ TileSetEditor::TileSetEditor() {
sources_delete_button->connect("pressed", callable_mp(this, &TileSetEditor::_source_delete_pressed));
sources_bottom_actions->add_child(sources_delete_button);
- sources_add_button = memnew(Button);
+ sources_add_button = memnew(MenuButton);
sources_add_button->set_flat(true);
- sources_add_button->connect("pressed", callable_mp(this, &TileSetEditor::_source_add_pressed));
+ sources_add_button->get_popup()->add_item(TTR("Atlas"));
+ sources_add_button->get_popup()->add_item(TTR("Scenes Collection"));
+ sources_add_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_source_add_id_pressed));
sources_bottom_actions->add_child(sources_add_button);
+ // Right side container.
+ VBoxContainer *split_container_right_side = memnew(VBoxContainer);
+ split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
+ split_container_right_side->set_v_size_flags(SIZE_EXPAND_FILL);
+ split_container->add_child(split_container_right_side);
+
// No source selected.
no_source_selected_label = memnew(Label);
no_source_selected_label->set_text(TTR("No TileSet source selected. Select or create a TileSet source."));
@@ -489,16 +549,24 @@ TileSetEditor::TileSetEditor() {
no_source_selected_label->set_v_size_flags(SIZE_EXPAND_FILL);
no_source_selected_label->set_align(Label::ALIGN_CENTER);
no_source_selected_label->set_valign(Label::VALIGN_CENTER);
- split_container->add_child(no_source_selected_label);
+ split_container_right_side->add_child(no_source_selected_label);
// Atlases editor.
tile_set_atlas_source_editor = memnew(TileSetAtlasSourceEditor);
tile_set_atlas_source_editor->set_h_size_flags(SIZE_EXPAND_FILL);
tile_set_atlas_source_editor->set_v_size_flags(SIZE_EXPAND_FILL);
tile_set_atlas_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list));
- split_container->add_child(tile_set_atlas_source_editor);
+ split_container_right_side->add_child(tile_set_atlas_source_editor);
tile_set_atlas_source_editor->hide();
+ // Scenes collection editor.
+ tile_set_scenes_collection_source_editor = memnew(TileSetScenesCollectionSourceEditor);
+ tile_set_scenes_collection_source_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ tile_set_scenes_collection_source_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ tile_set_scenes_collection_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list));
+ split_container_right_side->add_child(tile_set_scenes_collection_source_editor);
+ tile_set_scenes_collection_source_editor->hide();
+
// Registers UndoRedo inspector callback.
EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetEditor::_undo_redo_inspector_callback));
}
@@ -510,7 +578,7 @@ TileSetEditor::~TileSetEditor() {
// Delete tile data editors.
memdelete(tile_data_texture_offset_editor);
- memdelete(tile_data_position_editor);
+ memdelete(tile_data_y_sort_editor);
memdelete(tile_data_integer_editor);
memdelete(tile_data_float_editor);
memdelete(tile_data_occlusion_shape_editor);
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index c4aebb40a2..f584c043cc 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -35,6 +35,7 @@
#include "scene/resources/tile_set.h"
#include "tile_data_editors.h"
#include "tile_set_atlas_source_editor.h"
+#include "tile_set_scenes_collection_source_editor.h"
class TileSetEditor : public VBoxContainer {
GDCLASS(TileSetEditor, VBoxContainer);
@@ -47,6 +48,7 @@ private:
Label *no_source_selected_label;
TileSetAtlasSourceEditor *tile_set_atlas_source_editor;
+ TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor;
UndoRedo *undo_redo = EditorNode::get_undo_redo();
@@ -54,7 +56,7 @@ private:
// List of tile data editors.
TileDataTextureOffsetEditor *tile_data_texture_offset_editor = memnew(TileDataTextureOffsetEditor);
- TileDataPositionEditor *tile_data_position_editor = memnew(TileDataPositionEditor);
+ TileDataYSortEditor *tile_data_y_sort_editor = memnew(TileDataYSortEditor);
TileDataIntegerEditor *tile_data_integer_editor = memnew(TileDataIntegerEditor);
TileDataFloatEditor *tile_data_float_editor = memnew(TileDataFloatEditor);
TileDataOcclusionShapeEditor *tile_data_occlusion_shape_editor = memnew(TileDataOcclusionShapeEditor);
@@ -64,11 +66,11 @@ private:
// -- Sources management --
Button *sources_delete_button;
- Button *sources_add_button;
+ MenuButton *sources_add_button;
ItemList *sources_list;
Ref<Texture2D> missing_texture_texture;
void _source_selected(int p_source_index);
- void _source_add_pressed();
+ void _source_add_id_pressed(int p_id_pressed);
void _source_delete_pressed();
void _tile_set_changed();
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
new file mode 100644
index 0000000000..568d4ca8d7
--- /dev/null
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -0,0 +1,511 @@
+/*************************************************************************/
+/* tile_set_scenes_collection_source_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "tile_set_scenes_collection_source_editor.h"
+
+#include "editor/editor_resource_preview.h"
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+
+#include "scene/gui/item_list.h"
+
+#include "core/core_string_names.h"
+
+void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id(int p_id) {
+ ERR_FAIL_COND(p_id < 0);
+ if (source_id == p_id) {
+ return;
+ }
+ ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet Scenes Collection source ID. Another TileSet source exists with id %d.", p_id));
+
+ int previous_source = source_id;
+ source_id = p_id; // source_id must be updated before, because it's used by the source list update.
+ tile_set->set_source_id(previous_source, p_id);
+ emit_signal("changed", "id");
+}
+
+int TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id() {
+ return source_id;
+}
+
+bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_set(const StringName &p_name, const Variant &p_value) {
+ bool valid = false;
+ tile_set_scenes_collection_source->set(p_name, p_value, &valid);
+ if (valid) {
+ emit_signal("changed", String(p_name).utf8().get_data());
+ }
+ return valid;
+}
+
+bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
+ if (!tile_set_scenes_collection_source) {
+ return false;
+ }
+ bool valid = false;
+ r_ret = tile_set_scenes_collection_source->get(p_name, &valid);
+ return valid;
+}
+
+void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_bind_methods() {
+ // -- Shape and layout --
+ ClassDB::bind_method(D_METHOD("set_id", "id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id);
+ ClassDB::bind_method(D_METHOD("get_id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
+
+ ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
+}
+
+void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ ERR_FAIL_COND(!p_tile_set_scenes_collection_source);
+ ERR_FAIL_COND(p_source_id < 0);
+ ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source);
+
+ // Disconnect to changes.
+ if (tile_set_scenes_collection_source) {
+ tile_set_scenes_collection_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ }
+
+ tile_set = p_tile_set;
+ tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
+ source_id = p_source_id;
+
+ // Connect to changes.
+ if (tile_set_scenes_collection_source) {
+ if (!tile_set_scenes_collection_source->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
+ tile_set_scenes_collection_source->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ }
+ }
+
+ notify_property_list_changed();
+}
+
+// -- Proxy object used by the tile inspector --
+bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_set(const StringName &p_name, const Variant &p_value) {
+ if (!tile_set_scenes_collection_source) {
+ return false;
+ }
+
+ if (p_name == "id") {
+ int as_int = int(p_value);
+ ERR_FAIL_COND_V(as_int < 0, false);
+ ERR_FAIL_COND_V(tile_set_scenes_collection_source->has_scene_tile_id(as_int), false);
+ tile_set_scenes_collection_source->set_scene_tile_id(scene_id, as_int);
+ scene_id = as_int;
+ emit_signal("changed", "id");
+ for (int i = 0; i < tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_count(); i++) {
+ if (int(tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_metadata(i)) == scene_id) {
+ tile_set_scenes_collection_source_editor->scene_tiles_list->select(i);
+ break;
+ }
+ }
+ return true;
+ } else if (p_name == "scene") {
+ tile_set_scenes_collection_source->set_scene_tile_scene(scene_id, p_value);
+ emit_signal("changed", "scene");
+ return true;
+ } else if (p_name == "display_placeholder") {
+ tile_set_scenes_collection_source->set_scene_tile_display_placeholder(scene_id, p_value);
+ emit_signal("changed", "display_placeholder");
+ return true;
+ }
+
+ return false;
+}
+
+bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
+ if (!tile_set_scenes_collection_source) {
+ return false;
+ }
+
+ if (p_name == "id") {
+ r_ret = scene_id;
+ return true;
+ } else if (p_name == "scene") {
+ r_ret = tile_set_scenes_collection_source->get_scene_tile_scene(scene_id);
+ return true;
+ } else if (p_name == "display_placeholder") {
+ r_ret = tile_set_scenes_collection_source->get_scene_tile_display_placeholder(scene_id);
+ return true;
+ }
+
+ return false;
+}
+
+void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
+ if (!tile_set_scenes_collection_source) {
+ return;
+ }
+
+ p_list->push_back(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_NONE, ""));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "scene", PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "display_placeholder", PROPERTY_HINT_NONE, ""));
+}
+
+void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::edit(TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_scene_id) {
+ ERR_FAIL_COND(!p_tile_set_scenes_collection_source);
+ ERR_FAIL_COND(!p_tile_set_scenes_collection_source->has_scene_tile_id(p_scene_id));
+
+ tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
+ scene_id = p_scene_id;
+
+ notify_property_list_changed();
+}
+
+void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
+}
+
+void TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed(String p_what) {
+ if (p_what == "id") {
+ emit_signal("source_id_changed", scenes_collection_source_proxy_object->get_id());
+ }
+}
+
+void TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed() {
+ tile_set_scenes_collection_source_changed_needs_update = true;
+}
+
+void TileSetScenesCollectionSourceEditor::_scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) {
+ int index = p_ud;
+
+ if (index >= 0 && index < scene_tiles_list->get_item_count()) {
+ scene_tiles_list->set_item_icon(index, p_preview);
+ }
+}
+
+void TileSetScenesCollectionSourceEditor::_scenes_list_item_activated(int p_index) {
+ Ref<PackedScene> packed_scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_tiles_list->get_item_metadata(p_index));
+ if (packed_scene.is_valid()) {
+ EditorNode::get_singleton()->open_request(packed_scene->get_path());
+ }
+}
+
+void TileSetScenesCollectionSourceEditor::_source_add_pressed() {
+ int scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id();
+ undo_redo->create_action(TTR("Add a Scene Tile"));
+ undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", Ref<PackedScene>(), scene_id);
+ undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
+ undo_redo->commit_action();
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+}
+
+void TileSetScenesCollectionSourceEditor::_source_delete_pressed() {
+ Vector<int> selected_indices = scene_tiles_list->get_selected_items();
+ ERR_FAIL_COND(selected_indices.size() <= 0);
+ int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]);
+
+ undo_redo->create_action(TTR("Remove a Scene Tile"));
+ undo_redo->add_do_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
+ undo_redo->add_undo_method(tile_set_scenes_collection_source, "create_scene_tile", tile_set_scenes_collection_source->get_scene_tile_scene(scene_id), scene_id);
+ undo_redo->commit_action();
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+}
+
+void TileSetScenesCollectionSourceEditor::_update_source_inspector() {
+ // Update the proxy object.
+ scenes_collection_source_proxy_object->edit(tile_set, tile_set_scenes_collection_source, tile_set_source_id);
+}
+
+void TileSetScenesCollectionSourceEditor::_update_tile_inspector() {
+ Vector<int> selected_indices = scene_tiles_list->get_selected_items();
+ bool has_atlas_tile_selected = (selected_indices.size() > 0);
+
+ // Update the proxy object.
+ if (has_atlas_tile_selected) {
+ int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]);
+ tile_proxy_object->edit(tile_set_scenes_collection_source, scene_id);
+ }
+
+ // Update visibility.
+ tile_inspector_label->set_visible(has_atlas_tile_selected);
+ tile_inspector->set_visible(has_atlas_tile_selected);
+}
+
+void TileSetScenesCollectionSourceEditor::_update_action_buttons() {
+ Vector<int> selected_indices = scene_tiles_list->get_selected_items();
+ scene_tile_delete_button->set_disabled(selected_indices.size() <= 0);
+}
+
+void TileSetScenesCollectionSourceEditor::_update_scenes_list() {
+ if (!tile_set_scenes_collection_source) {
+ return;
+ }
+
+ // Get the previously selected id.
+ Vector<int> selected_indices = scene_tiles_list->get_selected_items();
+ int old_selected_scene_id = (selected_indices.size() > 0) ? int(scene_tiles_list->get_item_metadata(selected_indices[0])) : -1;
+
+ // Clear the list.
+ scene_tiles_list->clear();
+
+ // Rebuild the list.
+ int to_reselect = -1;
+ for (int i = 0; i < tile_set_scenes_collection_source->get_scene_tiles_count(); i++) {
+ int scene_id = tile_set_scenes_collection_source->get_scene_tile_id(i);
+
+ Ref<PackedScene> scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_id);
+
+ int item_index = 0;
+ if (scene.is_valid()) {
+ item_index = scene_tiles_list->add_item(vformat("%s (path:%s id:%d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id));
+ Variant udata = i;
+ EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata);
+ } else {
+ item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons"));
+ }
+ scene_tiles_list->set_item_metadata(item_index, scene_id);
+
+ if (old_selected_scene_id >= 0 && scene_id == old_selected_scene_id) {
+ to_reselect = i;
+ }
+ }
+
+ // Reselect if needed.
+ if (to_reselect >= 0) {
+ scene_tiles_list->select(to_reselect);
+ }
+
+ // Icon size update.
+ int int_size = int(EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size")) * EDSCALE;
+ scene_tiles_list->set_fixed_icon_size(Vector2(int_size, int_size));
+}
+
+void TileSetScenesCollectionSourceEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED:
+ scene_tile_add_button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ scene_tile_delete_button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ _update_scenes_list();
+ break;
+ case NOTIFICATION_INTERNAL_PROCESS:
+ if (tile_set_scenes_collection_source_changed_needs_update) {
+ // Update everything.
+ _update_source_inspector();
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+ tile_set_scenes_collection_source_changed_needs_update = false;
+ }
+ break;
+ case NOTIFICATION_VISIBILITY_CHANGED:
+ // Update things just in case.
+ _update_scenes_list();
+ _update_action_buttons();
+ break;
+ default:
+ break;
+ }
+}
+
+void TileSetScenesCollectionSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ ERR_FAIL_COND(!p_tile_set_scenes_collection_source);
+ ERR_FAIL_COND(p_source_id < 0);
+ ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source);
+
+ if (p_tile_set == tile_set && p_tile_set_scenes_collection_source == tile_set_scenes_collection_source && p_source_id == tile_set_source_id) {
+ return;
+ }
+
+ // Remove listener for old objects.
+ if (tile_set_scenes_collection_source) {
+ tile_set_scenes_collection_source->disconnect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
+ }
+
+ // Change the edited object.
+ tile_set = p_tile_set;
+ tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
+ tile_set_source_id = p_source_id;
+
+ // Add the listener again.
+ if (tile_set_scenes_collection_source) {
+ tile_set_scenes_collection_source->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
+ }
+
+ // Update everything.
+ _update_source_inspector();
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+}
+
+void TileSetScenesCollectionSourceEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+ if (!can_drop_data_fw(p_point, p_data, p_from)) {
+ return;
+ }
+
+ if (p_from == scene_tiles_list) {
+ // Handle dropping a texture in the list of atlas resources.
+ int scene_id = -1;
+ Dictionary d = p_data;
+ Vector<String> files = d["files"];
+ for (int i = 0; i < files.size(); i++) {
+ Ref<PackedScene> resource = ResourceLoader::load(files[i]);
+ if (resource.is_valid()) {
+ scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id();
+ undo_redo->create_action(TTR("Add a Scene Tile"));
+ undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", resource, scene_id);
+ undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
+ undo_redo->commit_action();
+ }
+ }
+
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+ }
+}
+
+bool TileSetScenesCollectionSourceEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+ if (p_from == scene_tiles_list) {
+ Dictionary d = p_data;
+
+ if (!d.has("type")) {
+ return false;
+ }
+
+ // Check if we have a Texture2D.
+ if (String(d["type"]) == "files") {
+ Vector<String> files = d["files"];
+
+ if (files.size() == 0) {
+ return false;
+ }
+
+ for (int i = 0; i < files.size(); i++) {
+ String file = files[i];
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+
+ if (!ClassDB::is_parent_class(ftype, "PackedScene")) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+void TileSetScenesCollectionSourceEditor::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("source_id_changed", PropertyInfo(Variant::INT, "source_id")));
+
+ ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileSetScenesCollectionSourceEditor::_scene_thumbnail_done);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &TileSetScenesCollectionSourceEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &TileSetScenesCollectionSourceEditor::drop_data_fw);
+}
+
+TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() {
+ // -- Right side --
+ HSplitContainer *split_container_right_side = memnew(HSplitContainer);
+ split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
+ add_child(split_container_right_side);
+
+ // Middle panel.
+ ScrollContainer *middle_panel = memnew(ScrollContainer);
+ middle_panel->set_enable_h_scroll(false);
+ middle_panel->set_custom_minimum_size(Size2i(200, 0) * EDSCALE);
+ split_container_right_side->add_child(middle_panel);
+
+ VBoxContainer *middle_vbox_container = memnew(VBoxContainer);
+ middle_vbox_container->set_h_size_flags(SIZE_EXPAND_FILL);
+ middle_panel->add_child(middle_vbox_container);
+
+ // Scenes collection source inspector.
+ scenes_collection_source_inspector_label = memnew(Label);
+ scenes_collection_source_inspector_label->set_text(TTR("Scenes collection properties:"));
+ middle_vbox_container->add_child(scenes_collection_source_inspector_label);
+
+ scenes_collection_source_proxy_object = memnew(TileSetScenesCollectionProxyObject());
+ scenes_collection_source_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed));
+
+ scenes_collection_source_inspector = memnew(EditorInspector);
+ scenes_collection_source_inspector->set_undo_redo(undo_redo);
+ scenes_collection_source_inspector->set_enable_v_scroll(false);
+ scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object);
+ middle_vbox_container->add_child(scenes_collection_source_inspector);
+
+ // Tile inspector.
+ tile_inspector_label = memnew(Label);
+ tile_inspector_label->set_text(TTR("Tile properties:"));
+ tile_inspector_label->hide();
+ middle_vbox_container->add_child(tile_inspector_label);
+
+ tile_proxy_object = memnew(SceneTileProxyObject(this));
+ tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_scenes_list).unbind(1));
+ tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
+
+ tile_inspector = memnew(EditorInspector);
+ tile_inspector->set_undo_redo(undo_redo);
+ tile_inspector->set_enable_v_scroll(false);
+ tile_inspector->edit(tile_proxy_object);
+ tile_inspector->set_use_folding(true);
+ middle_vbox_container->add_child(tile_inspector);
+
+ // Scenes list.
+ VBoxContainer *right_vbox_container = memnew(VBoxContainer);
+ split_container_right_side->add_child(right_vbox_container);
+
+ scene_tiles_list = memnew(ItemList);
+ scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ scene_tiles_list->set_drag_forwarding(this);
+ scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_tile_inspector).unbind(1));
+ scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
+ scene_tiles_list->connect("item_activated", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_list_item_activated));
+ scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+ right_vbox_container->add_child(scene_tiles_list);
+
+ HBoxContainer *scenes_bottom_actions = memnew(HBoxContainer);
+ right_vbox_container->add_child(scenes_bottom_actions);
+
+ scene_tile_add_button = memnew(Button);
+ scene_tile_add_button->set_flat(true);
+ scene_tile_add_button->connect("pressed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_add_pressed));
+ scenes_bottom_actions->add_child(scene_tile_add_button);
+
+ scene_tile_delete_button = memnew(Button);
+ scene_tile_delete_button->set_flat(true);
+ scene_tile_delete_button->set_disabled(true);
+ scene_tile_delete_button->connect("pressed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_delete_pressed));
+ scenes_bottom_actions->add_child(scene_tile_delete_button);
+}
+
+TileSetScenesCollectionSourceEditor::~TileSetScenesCollectionSourceEditor() {
+ memdelete(scenes_collection_source_proxy_object);
+ memdelete(tile_proxy_object);
+}
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
new file mode 100644
index 0000000000..195aa79bc4
--- /dev/null
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
@@ -0,0 +1,139 @@
+/*************************************************************************/
+/* tile_set_scenes_collection_source_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TILE_SET_SCENES_COLLECTION_SOURCE_EDITOR_H
+#define TILE_SET_SCENES_COLLECTION_SOURCE_EDITOR_H
+
+#include "editor/editor_node.h"
+#include "scene/gui/box_container.h"
+#include "scene/resources/tile_set.h"
+
+class TileSetScenesCollectionSourceEditor : public HBoxContainer {
+ GDCLASS(TileSetScenesCollectionSourceEditor, HBoxContainer);
+
+private:
+ // -- Proxy object for an atlas source, needed by the inspector --
+ class TileSetScenesCollectionProxyObject : public Object {
+ GDCLASS(TileSetScenesCollectionProxyObject, Object);
+
+ private:
+ Ref<TileSet> tile_set;
+ TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
+ int source_id = -1;
+
+ protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ static void _bind_methods();
+
+ public:
+ void set_id(int p_id);
+ int get_id();
+
+ void edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id);
+ };
+
+ // -- Proxy object for a tile, needed by the inspector --
+ class SceneTileProxyObject : public Object {
+ GDCLASS(SceneTileProxyObject, Object);
+
+ private:
+ TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor;
+
+ TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
+ int source_id;
+ int scene_id;
+
+ protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ static void _bind_methods();
+
+ public:
+ // Update the proxyed object.
+ void edit(TileSetScenesCollectionSource *p_tile_set_atlas_source, int p_scene_id);
+
+ SceneTileProxyObject(TileSetScenesCollectionSourceEditor *p_tiles_set_scenes_collection_source_editor) {
+ tile_set_scenes_collection_source_editor = p_tiles_set_scenes_collection_source_editor;
+ }
+ };
+
+private:
+ Ref<TileSet> tile_set;
+ TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
+ int tile_set_source_id = -1;
+
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ bool tile_set_scenes_collection_source_changed_needs_update = false;
+
+ // Source inspector.
+ TileSetScenesCollectionProxyObject *scenes_collection_source_proxy_object;
+ Label *scenes_collection_source_inspector_label;
+ EditorInspector *scenes_collection_source_inspector;
+
+ // Tile inspector.
+ SceneTileProxyObject *tile_proxy_object;
+ Label *tile_inspector_label;
+ EditorInspector *tile_inspector;
+
+ ItemList *scene_tiles_list;
+ Button *scene_tile_add_button;
+ Button *scene_tile_delete_button;
+
+ void _tile_set_scenes_collection_source_changed();
+ void _scenes_collection_source_proxy_object_changed(String p_what);
+ void _scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud);
+ void _scenes_list_item_activated(int p_index);
+
+ void _source_add_pressed();
+ void _source_delete_pressed();
+
+ // Update methods.
+ void _update_source_inspector();
+ void _update_tile_inspector();
+ void _update_scenes_list();
+ void _update_action_buttons();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id);
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ TileSetScenesCollectionSourceEditor();
+ ~TileSetScenesCollectionSourceEditor();
+};
+
+#endif
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 971ff15073..fb111efc17 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -202,6 +202,7 @@ TilesEditor::TilesEditor(EditorNode *p_editor) {
// Toolbar.
HBoxContainer *toolbar = memnew(HBoxContainer);
+ toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
add_child(toolbar);
// Switch button.
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index 0af3b936cb..75a944e910 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -180,7 +180,7 @@ void VersionControlEditorPlugin::_stage_selected() {
staged_files_count = 0;
TreeItem *root = stage_files->get_root();
if (root) {
- TreeItem *file_entry = root->get_children();
+ TreeItem *file_entry = root->get_first_child();
while (file_entry) {
if (file_entry->is_checked(0)) {
EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0));
@@ -207,7 +207,7 @@ void VersionControlEditorPlugin::_stage_all() {
staged_files_count = 0;
TreeItem *root = stage_files->get_root();
if (root) {
- TreeItem *file_entry = root->get_children();
+ TreeItem *file_entry = root->get_first_child();
while (file_entry) {
EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0));
file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor"));
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 1d4c23fee6..237cd83b84 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -44,6 +44,7 @@
#include "scene/gui/panel.h"
#include "scene/main/window.h"
#include "scene/resources/visual_shader_nodes.h"
+#include "scene/resources/visual_shader_particle_nodes.h"
#include "scene/resources/visual_shader_sdf_nodes.h"
#include "servers/display_server.h"
#include "servers/rendering/shader_types.h"
@@ -71,13 +72,13 @@ const int MAX_FLOAT_CONST_DEFS = sizeof(float_constant_defs) / sizeof(FloatConst
Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
if (get_script_instance()) {
- return get_script_instance()->call("create_editor", p_parent_resource, p_node);
+ return get_script_instance()->call("_create_editor", p_parent_resource, p_node);
}
return nullptr;
}
void VisualShaderNodePlugin::_bind_methods() {
- BIND_VMETHOD(MethodInfo(Variant::OBJECT, "create_editor", PropertyInfo(Variant::OBJECT, "parent_resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::OBJECT, "for_node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode")));
+ BIND_VMETHOD(MethodInfo(Variant::OBJECT, "_create_editor", PropertyInfo(Variant::OBJECT, "parent_resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::OBJECT, "for_node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode")));
}
///////////////////
@@ -322,6 +323,12 @@ void VisualShaderGraphPlugin::register_uniform_name(int p_node_id, LineEdit *p_u
links[p_node_id].uniform_name = p_uniform_name;
}
+void VisualShaderGraphPlugin::update_theme() {
+ vector_expanded_color[0] = VisualShaderEditor::get_singleton()->get_theme_color("axis_x_color", "Editor"); // red
+ vector_expanded_color[1] = VisualShaderEditor::get_singleton()->get_theme_color("axis_y_color", "Editor"); // green
+ vector_expanded_color[2] = VisualShaderEditor::get_singleton()->get_theme_color("axis_z_color", "Editor"); // blue
+}
+
void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (p_type != visual_shader->get_shader_type()) {
return;
@@ -340,6 +347,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Color(1.0, 1.0, 0.0), // sampler
};
+ static const String vector_expanded_name[3] = {
+ "red",
+ "green",
+ "blue"
+ };
+
Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id);
Ref<VisualShaderNodeResizableBase> resizable_node = Object::cast_to<VisualShaderNodeResizableBase>(vsnode.ptr());
@@ -349,6 +362,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr());
bool is_group = !group_node.is_null();
+ bool is_comment = false;
+
Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr());
bool is_expression = !expression_node.is_null();
String expression = "";
@@ -392,17 +407,22 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (is_resizable) {
Ref<VisualShaderNodeComment> comment_node = Object::cast_to<VisualShaderNodeComment>(vsnode.ptr());
if (comment_node.is_valid()) {
+ is_comment = true;
node->set_comment(true);
Label *comment_label = memnew(Label);
node->add_child(comment_label);
comment_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
comment_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- comment_label->set_mouse_filter(Control::MouseFilter::MOUSE_FILTER_STOP);
comment_label->set_text(comment_node->get_description());
}
}
+ Ref<VisualShaderNodeParticleEmit> emit = vsnode;
+ if (emit.is_valid()) {
+ node->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
+ }
+
Ref<VisualShaderNodeUniform> uniform = vsnode;
if (uniform.is_valid()) {
VisualShaderEditor::get_singleton()->graph->add_child(node);
@@ -551,13 +571,32 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
}
- for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) {
+ int output_port_count = 0;
+ for (int i = 0; i < vsnode->get_output_port_count(); i++) {
+ if (vsnode->_is_output_port_expanded(i)) {
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ output_port_count += 3;
+ }
+ }
+ output_port_count++;
+ }
+ int max_ports = MAX(vsnode->get_input_port_count(), output_port_count);
+ VisualShaderNode::PortType expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
+ int expanded_port_counter = 0;
+
+ for (int i = 0, j = 0; i < max_ports; i++, j++) {
+ if (expanded_type == VisualShaderNode::PORT_TYPE_VECTOR && expanded_port_counter >= 3) {
+ expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
+ expanded_port_counter = 0;
+ i -= 3;
+ }
+
if (vsnode->is_port_separator(i)) {
node->add_child(memnew(HSeparator));
port_offset++;
}
- bool valid_left = i < vsnode->get_input_port_count();
+ bool valid_left = j < vsnode->get_input_port_count();
VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR;
bool port_left_used = false;
String name_left;
@@ -565,18 +604,24 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
name_left = vsnode->get_input_port_name(i);
port_left = vsnode->get_input_port_type(i);
for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
- if (E->get().to_node == p_id && E->get().to_port == i) {
+ if (E->get().to_node == p_id && E->get().to_port == j) {
port_left_used = true;
}
}
}
- bool valid_right = i < vsnode->get_output_port_count();
+ bool valid_right = true;
VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR;
String name_right;
- if (valid_right) {
- name_right = vsnode->get_output_port_name(i);
- port_right = vsnode->get_output_port_type(i);
+
+ if (expanded_type == VisualShaderNode::PORT_TYPE_SCALAR) {
+ valid_right = i < vsnode->get_output_port_count();
+ if (valid_right) {
+ name_right = vsnode->get_output_port_name(i);
+ port_right = vsnode->get_output_port_type(i);
+ }
+ } else {
+ name_right = vector_expanded_name[expanded_port_counter++];
}
HBoxContainer *hb = memnew(HBoxContainer);
@@ -684,17 +729,29 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
}
- if (valid_right && visual_shader->get_shader_type() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
- TextureButton *preview = memnew(TextureButton);
- preview->set_toggle_mode(true);
- preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
- preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
- preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ if (valid_right) {
+ if (vsnode->is_output_port_expandable(i)) {
+ TextureButton *expand = memnew(TextureButton);
+ expand->set_toggle_mode(true);
+ expand->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiTreeArrowDown", "EditorIcons"));
+ expand->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiTreeArrowRight", "EditorIcons"));
+ expand->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ expand->set_pressed(vsnode->_is_output_port_expanded(i));
+ expand->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_expand_output_port), varray(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
+ hb->add_child(expand);
+ }
+ if (visual_shader->get_shader_type() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
+ TextureButton *preview = memnew(TextureButton);
+ preview->set_toggle_mode(true);
+ preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
+ preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
+ preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
- register_output_port(p_id, i, preview);
+ register_output_port(p_id, j, preview);
- preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, i), CONNECT_DEFERRED);
- hb->add_child(preview);
+ preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, j), CONNECT_DEFERRED);
+ hb->add_child(preview);
+ }
}
if (is_group) {
@@ -706,7 +763,40 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
node->add_child(hb);
+ if (expanded_type != VisualShaderNode::PORT_TYPE_SCALAR) {
+ continue;
+ }
+
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
+
+ if (vsnode->_is_output_port_expanded(i)) {
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ port_offset++;
+ valid_left = (i + 1) < vsnode->get_input_port_count();
+ port_left = VisualShaderNode::PORT_TYPE_SCALAR;
+ if (valid_left) {
+ port_left = vsnode->get_input_port_type(i + 1);
+ }
+ node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
+ port_offset++;
+
+ valid_left = (i + 2) < vsnode->get_input_port_count();
+ port_left = VisualShaderNode::PORT_TYPE_SCALAR;
+ if (valid_left) {
+ port_left = vsnode->get_input_port_type(i + 2);
+ }
+ node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
+ port_offset++;
+
+ valid_left = (i + 3) < vsnode->get_input_port_count();
+ port_left = VisualShaderNode::PORT_TYPE_SCALAR;
+ if (valid_left) {
+ port_left = vsnode->get_input_port_type(i + 3);
+ }
+ node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]);
+ expanded_type = VisualShaderNode::PORT_TYPE_VECTOR;
+ }
+ }
}
if (vsnode->get_output_port_for_preview() >= 0) {
@@ -729,7 +819,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
CodeEdit *expression_box = memnew(CodeEdit);
Ref<CodeHighlighter> expression_syntax_highlighter;
expression_syntax_highlighter.instance();
- expression_node->set_control(expression_box, 0);
+ expression_node->set_ctrl_pressed(expression_box, 0);
node->add_child(expression_box);
register_expression_edit(p_id, expression_box);
@@ -764,6 +854,10 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
expression_syntax_highlighter->add_color_region("//", "", comment_color, true);
+ expression_box->clear_comment_delimiters();
+ expression_box->add_comment_delimiter("/*", "*/", false);
+ expression_box->add_comment_delimiter("//", "", true);
+
expression_box->set_text(expression);
expression_box->set_context_menu_enabled(false);
expression_box->set_draw_line_numbers(true);
@@ -773,6 +867,9 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (!uniform.is_valid()) {
VisualShaderEditor::get_singleton()->graph->add_child(node);
+ if (is_comment) {
+ VisualShaderEditor::get_singleton()->graph->move_child(node, 0); // to prevents a bug where comment node overlaps its content
+ }
VisualShaderEditor::get_singleton()->_update_created_node(node);
if (is_resizable) {
VisualShaderEditor::get_singleton()->call_deferred("_set_node_size", (int)p_type, p_id, size);
@@ -922,13 +1019,13 @@ bool VisualShaderEditor::_is_available(int p_mode) {
if (p_mode != -1) {
switch (current_mode) {
- case 0: // Vertex or Emit
+ case 0: // Vertex / Emit
current_mode = 1;
break;
- case 1: // Fragment or Process
+ case 1: // Fragment / Process
current_mode = 2;
break;
- case 2: // Light or End
+ case 2: // Light / Collide
current_mode = 4;
break;
default:
@@ -1130,7 +1227,7 @@ void VisualShaderEditor::_update_options_menu() {
item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("bool", "EditorIcons"));
break;
case VisualShaderNode::PORT_TYPE_TRANSFORM:
- item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform", "EditorIcons"));
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform3D", "EditorIcons"));
break;
case VisualShaderNode::PORT_TYPE_SAMPLER:
item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("ImageTexture", "EditorIcons"));
@@ -1144,22 +1241,29 @@ void VisualShaderEditor::_update_options_menu() {
void VisualShaderEditor::_set_mode(int p_which) {
if (p_which == VisualShader::MODE_SKY) {
- edit_type_standart->set_visible(false);
+ edit_type_standard->set_visible(false);
edit_type_particles->set_visible(false);
edit_type_sky->set_visible(true);
edit_type = edit_type_sky;
+ custom_mode_box->set_visible(false);
mode = MODE_FLAGS_SKY;
} else if (p_which == VisualShader::MODE_PARTICLES) {
- edit_type_standart->set_visible(false);
+ edit_type_standard->set_visible(false);
edit_type_particles->set_visible(true);
edit_type_sky->set_visible(false);
edit_type = edit_type_particles;
+ if ((edit_type->get_selected() + 3) > VisualShader::TYPE_PROCESS) {
+ custom_mode_box->set_visible(false);
+ } else {
+ custom_mode_box->set_visible(true);
+ }
mode = MODE_FLAGS_PARTICLES;
} else {
edit_type_particles->set_visible(false);
- edit_type_standart->set_visible(true);
+ edit_type_standard->set_visible(true);
edit_type_sky->set_visible(false);
- edit_type = edit_type_standart;
+ edit_type = edit_type_standard;
+ custom_mode_box->set_visible(false);
mode = MODE_FLAGS_SPATIAL_CANVASITEM;
}
visual_shader->set_shader_type(get_current_shader_type());
@@ -1288,6 +1392,7 @@ void VisualShaderEditor::_update_graph() {
graph_plugin->clear_links();
graph_plugin->make_dirty(true);
+ graph_plugin->update_theme();
for (int n_i = 0; n_i < nodes.size(); n_i++) {
graph_plugin->add_node(type, nodes[n_i]);
@@ -1311,9 +1416,9 @@ void VisualShaderEditor::_update_graph() {
VisualShader::Type VisualShaderEditor::get_current_shader_type() const {
VisualShader::Type type;
if (mode & MODE_FLAGS_PARTICLES) {
- type = VisualShader::Type(edit_type->get_selected() + 3);
+ type = VisualShader::Type(edit_type->get_selected() + 3 + (custom_mode_enabled ? 3 : 0));
} else if (mode & MODE_FLAGS_SKY) {
- type = VisualShader::Type(edit_type->get_selected() + 6);
+ type = VisualShader::Type(edit_type->get_selected() + 8);
} else {
type = VisualShader::Type(edit_type->get_selected());
}
@@ -1436,6 +1541,92 @@ void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *
undo_redo->commit_action();
}
+void VisualShaderEditor::_expand_output_port(int p_node, int p_port, bool p_expand) {
+ VisualShader::Type type = get_current_shader_type();
+
+ Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
+ ERR_FAIL_COND(!node.is_valid());
+
+ if (p_expand) {
+ undo_redo->create_action(TTR("Expand Output Port"));
+ } else {
+ undo_redo->create_action(TTR("Shrink Output Port"));
+ }
+
+ undo_redo->add_do_method(node.ptr(), "_set_output_port_expanded", p_port, p_expand);
+ undo_redo->add_undo_method(node.ptr(), "_set_output_port_expanded", p_port, !p_expand);
+
+ int type_size = 0;
+ if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ type_size = 3;
+ }
+
+ List<VisualShader::Connection> conns;
+ visual_shader->get_node_connections(type, &conns);
+
+ for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
+ int from_node = E->get().from_node;
+ int from_port = E->get().from_port;
+ int to_node = E->get().to_node;
+ int to_port = E->get().to_port;
+
+ if (from_node == p_node) {
+ if (p_expand) {
+ if (from_port > p_port) { // reconnect ports after expanded ports
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port);
+
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port + type_size, to_node, to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port + type_size, to_node, to_port);
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port + type_size, to_node, to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port + type_size, to_node, to_port);
+ }
+ } else {
+ if (from_port > p_port + type_size) { // reconnect ports after expanded ports
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port);
+
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_port - type_size, to_node, to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port - type_size, to_node, to_port);
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port - type_size, to_node, to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port - type_size, to_node, to_port);
+ } else if (from_port > p_port) { // disconnect component ports
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port);
+ }
+ }
+ }
+ }
+
+ int preview_port = node->get_output_port_for_preview();
+ if (p_expand) {
+ if (preview_port > p_port) {
+ undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port + type_size);
+ undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
+ }
+ } else {
+ if (preview_port > p_port + type_size) {
+ undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port - type_size);
+ undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
+ }
+ }
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
+ undo_redo->commit_action();
+}
+
void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
VisualShader::Type type = get_current_shader_type();
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
@@ -1584,7 +1775,7 @@ void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p
Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
Control *text_box = nullptr;
if (!expression_node.is_null()) {
- text_box = expression_node->get_control(0);
+ text_box = expression_node->is_ctrl_pressed(0);
if (text_box) {
text_box->set_custom_minimum_size(Size2(0, 0));
}
@@ -1812,47 +2003,6 @@ void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node,
editing_port = p_port;
}
-void VisualShaderEditor::_add_custom_node(const String &p_path) {
- int idx = -1;
-
- for (int i = custom_node_option_idx; i < add_options.size(); i++) {
- if (add_options[i].script.is_valid()) {
- if (add_options[i].script->get_path() == p_path) {
- idx = i;
- break;
- }
- }
- }
- if (idx != -1) {
- _add_node(idx);
- }
-}
-
-void VisualShaderEditor::_add_cubemap_node(const String &p_path) {
- VisualShaderNodeCubemap *cubemap = (VisualShaderNodeCubemap *)_add_node(cubemap_node_option_idx, -1);
- cubemap->set_cube_map(ResourceLoader::load(p_path));
-}
-
-void VisualShaderEditor::_add_texture2d_node(const String &p_path) {
- VisualShaderNodeTexture *texture2d = (VisualShaderNodeTexture *)_add_node(texture2d_node_option_idx, -1);
- texture2d->set_texture(ResourceLoader::load(p_path));
-}
-
-void VisualShaderEditor::_add_texture2d_array_node(const String &p_path) {
- VisualShaderNodeTexture2DArray *texture2d_array = (VisualShaderNodeTexture2DArray *)_add_node(texture2d_array_node_option_idx, -1);
- texture2d_array->set_texture_array(ResourceLoader::load(p_path));
-}
-
-void VisualShaderEditor::_add_texture3d_node(const String &p_path) {
- VisualShaderNodeTexture3D *texture3d = (VisualShaderNodeTexture3D *)_add_node(texture3d_node_option_idx, -1);
- texture3d->set_texture(ResourceLoader::load(p_path));
-}
-
-void VisualShaderEditor::_add_curve_node(const String &p_path) {
- VisualShaderNodeCurveTexture *curve = (VisualShaderNodeCurveTexture *)_add_node(curve_node_option_idx, -1);
- curve->set_texture(ResourceLoader::load(p_path));
-}
-
void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, int p_op_idx) {
// FLOAT_OP
{
@@ -1944,6 +2094,16 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, int p_op_idx) {
}
}
+ //UV_FUNC
+ {
+ VisualShaderNodeUVFunc *uvFunc = Object::cast_to<VisualShaderNodeUVFunc>(p_node);
+
+ if (uvFunc) {
+ uvFunc->set_function((VisualShaderNodeUVFunc::Function)p_op_idx);
+ return;
+ }
+ }
+
// IS
{
VisualShaderNodeIs *is = Object::cast_to<VisualShaderNodeIs>(p_node);
@@ -2041,8 +2201,8 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, int p_op_idx) {
}
}
-VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
- ERR_FAIL_INDEX_V(p_idx, add_options.size(), nullptr);
+void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_path, int p_node_idx) {
+ ERR_FAIL_INDEX(p_idx, add_options.size());
Ref<VisualShaderNode> vsnode;
@@ -2050,7 +2210,7 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
if (!is_custom && add_options[p_idx].type != String()) {
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(add_options[p_idx].type));
- ERR_FAIL_COND_V(!vsn, nullptr);
+ ERR_FAIL_COND(!vsn);
VisualShaderNodeFloatConstant *constant = Object::cast_to<VisualShaderNodeFloatConstant>(vsn);
@@ -2072,10 +2232,10 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
vsnode = Ref<VisualShaderNode>(vsn);
} else {
- ERR_FAIL_COND_V(add_options[p_idx].script.is_null(), nullptr);
+ ERR_FAIL_COND(add_options[p_idx].script.is_null());
String base_type = add_options[p_idx].script->get_instance_base_type();
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(base_type));
- ERR_FAIL_COND_V(!vsn, nullptr);
+ ERR_FAIL_COND(!vsn);
vsnode = Ref<VisualShaderNode>(vsn);
vsnode->set_script(add_options[p_idx].script);
}
@@ -2094,7 +2254,11 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
int id_to_use = visual_shader->get_valid_node_id(type);
- undo_redo->create_action(TTR("Add Node to Visual Shader"));
+ if (p_resource_path.is_empty()) {
+ undo_redo->create_action(TTR("Add Node to Visual Shader"));
+ } else {
+ id_to_use += p_node_idx;
+ }
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use);
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use);
undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_to_use);
@@ -2209,8 +2373,30 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
graph_plugin->call_deferred("update_curve", id_to_use);
}
- undo_redo->commit_action();
- return vsnode.ptr();
+ if (p_resource_path.is_empty()) {
+ undo_redo->commit_action();
+ } else {
+ //post-initialization
+
+ VisualShaderNodeTexture *texture2d = Object::cast_to<VisualShaderNodeTexture>(vsnode.ptr());
+ VisualShaderNodeTexture3D *texture3d = Object::cast_to<VisualShaderNodeTexture3D>(vsnode.ptr());
+
+ if (texture2d || texture3d || curve) {
+ undo_redo->add_do_method(vsnode.ptr(), "set_texture", ResourceLoader::load(p_resource_path));
+ return;
+ }
+
+ VisualShaderNodeCubemap *cubemap = Object::cast_to<VisualShaderNodeCubemap>(vsnode.ptr());
+ if (cubemap) {
+ undo_redo->add_do_method(vsnode.ptr(), "set_cube_map", ResourceLoader::load(p_resource_path));
+ return;
+ }
+
+ VisualShaderNodeTexture2DArray *texture2d_array = Object::cast_to<VisualShaderNodeTexture2DArray>(vsnode.ptr());
+ if (texture2d_array) {
+ undo_redo->add_do_method(vsnode.ptr(), "set_texture_array", ResourceLoader::load(p_resource_path));
+ }
+ }
}
void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, int p_node) {
@@ -2427,7 +2613,7 @@ void VisualShaderEditor::_convert_constants_to_uniforms(bool p_vice_versa) {
for (Set<int>::Element *E = current_set.front(); E; E = E->next()) {
int node_id = E->get();
Ref<VisualShaderNode> node = visual_shader->get_node(type_id, node_id);
- bool catched = false;
+ bool caught = false;
Variant var;
// float
@@ -2436,112 +2622,112 @@ void VisualShaderEditor::_convert_constants_to_uniforms(bool p_vice_versa) {
if (float_const.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeFloatConstant", "VisualShaderNodeFloatUniform");
var = float_const->get_constant();
- catched = true;
+ caught = true;
}
} else {
Ref<VisualShaderNodeFloatUniform> float_uniform = Object::cast_to<VisualShaderNodeFloatUniform>(node.ptr());
if (float_uniform.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeFloatUniform", "VisualShaderNodeFloatConstant");
var = float_uniform->get_default_value();
- catched = true;
+ caught = true;
}
}
// int
- if (!catched) {
+ if (!caught) {
if (!p_vice_versa) {
Ref<VisualShaderNodeIntConstant> int_const = Object::cast_to<VisualShaderNodeIntConstant>(node.ptr());
if (int_const.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeIntConstant", "VisualShaderNodeIntUniform");
var = int_const->get_constant();
- catched = true;
+ caught = true;
}
} else {
Ref<VisualShaderNodeIntUniform> int_uniform = Object::cast_to<VisualShaderNodeIntUniform>(node.ptr());
if (int_uniform.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeIntUniform", "VisualShaderNodeIntConstant");
var = int_uniform->get_default_value();
- catched = true;
+ caught = true;
}
}
}
// boolean
- if (!catched) {
+ if (!caught) {
if (!p_vice_versa) {
Ref<VisualShaderNodeBooleanConstant> boolean_const = Object::cast_to<VisualShaderNodeBooleanConstant>(node.ptr());
if (boolean_const.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeBooleanConstant", "VisualShaderNodeBooleanUniform");
var = boolean_const->get_constant();
- catched = true;
+ caught = true;
}
} else {
Ref<VisualShaderNodeBooleanUniform> boolean_uniform = Object::cast_to<VisualShaderNodeBooleanUniform>(node.ptr());
if (boolean_uniform.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeBooleanUniform", "VisualShaderNodeBooleanConstant");
var = boolean_uniform->get_default_value();
- catched = true;
+ caught = true;
}
}
}
// vec3
- if (!catched) {
+ if (!caught) {
if (!p_vice_versa) {
Ref<VisualShaderNodeVec3Constant> vec3_const = Object::cast_to<VisualShaderNodeVec3Constant>(node.ptr());
if (vec3_const.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeVec3Constant", "VisualShaderNodeVec3Uniform");
var = vec3_const->get_constant();
- catched = true;
+ caught = true;
}
} else {
Ref<VisualShaderNodeVec3Uniform> vec3_uniform = Object::cast_to<VisualShaderNodeVec3Uniform>(node.ptr());
if (vec3_uniform.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeVec3Uniform", "VisualShaderNodeVec3Constant");
var = vec3_uniform->get_default_value();
- catched = true;
+ caught = true;
}
}
}
// color
- if (!catched) {
+ if (!caught) {
if (!p_vice_versa) {
Ref<VisualShaderNodeColorConstant> color_const = Object::cast_to<VisualShaderNodeColorConstant>(node.ptr());
if (color_const.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeColorConstant", "VisualShaderNodeColorUniform");
var = color_const->get_constant();
- catched = true;
+ caught = true;
}
} else {
Ref<VisualShaderNodeColorUniform> color_uniform = Object::cast_to<VisualShaderNodeColorUniform>(node.ptr());
if (color_uniform.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeColorUniform", "VisualShaderNodeColorConstant");
var = color_uniform->get_default_value();
- catched = true;
+ caught = true;
}
}
}
// transform
- if (!catched) {
+ if (!caught) {
if (!p_vice_versa) {
Ref<VisualShaderNodeTransformConstant> transform_const = Object::cast_to<VisualShaderNodeTransformConstant>(node.ptr());
if (transform_const.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeTransformConstant", "VisualShaderNodeTransformUniform");
var = transform_const->get_constant();
- catched = true;
+ caught = true;
}
} else {
Ref<VisualShaderNodeTransformUniform> transform_uniform = Object::cast_to<VisualShaderNodeTransformUniform>(node.ptr());
if (transform_uniform.is_valid()) {
_replace_node(type_id, node_id, "VisualShaderNodeTransformUniform", "VisualShaderNodeTransformConstant");
var = transform_uniform->get_default_value();
- catched = true;
+ caught = true;
}
}
}
- ERR_CONTINUE(!catched);
+ ERR_CONTINUE(!caught);
int preview_port = node->get_output_port_for_preview();
if (!p_vice_versa) {
@@ -2762,10 +2948,10 @@ void VisualShaderEditor::_notification(int p_what) {
// collapse tree by default
- TreeItem *category = members->get_root()->get_children();
+ TreeItem *category = members->get_root()->get_first_child();
while (category) {
category->set_collapsed(true);
- TreeItem *sub_category = category->get_children();
+ TreeItem *sub_category = category->get_first_child();
while (sub_category) {
sub_category->set_collapsed(true);
sub_category = sub_category->get_next();
@@ -2786,9 +2972,6 @@ void VisualShaderEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
highend_label->set_modulate(get_theme_color("vulkan_color", "Editor"));
- error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
-
node_filter->set_right_icon(Control::get_theme_icon("Search", "EditorIcons"));
preview_shader->set_icon(Control::get_theme_icon("Shader", "EditorIcons"));
@@ -2825,9 +3008,14 @@ void VisualShaderEditor::_notification(int p_what) {
syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
syntax_highlighter->add_color_region("//", "", comment_color, true);
- error_text->add_theme_font_override("font", get_theme_font("status_source", "EditorFonts"));
- error_text->add_theme_font_size_override("font_size", get_theme_font_size("status_source_size", "EditorFonts"));
- error_text->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ preview_text->clear_comment_delimiters();
+ preview_text->add_comment_delimiter("/*", "*/", false);
+ preview_text->add_comment_delimiter("//", "", true);
+
+ error_panel->add_theme_style_override("panel", get_theme_stylebox("panel", "Panel"));
+ error_label->add_theme_font_override("font", get_theme_font("status_source", "EditorFonts"));
+ error_label->add_theme_font_size_override("font_size", get_theme_font_size("status_source_size", "EditorFonts"));
+ error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
}
tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Tools", "EditorIcons"));
@@ -3049,8 +3237,18 @@ void VisualShaderEditor::_mode_selected(int p_id) {
int offset = 0;
if (mode & MODE_FLAGS_PARTICLES) {
offset = 3;
+ if (p_id + offset > VisualShader::TYPE_PROCESS) {
+ custom_mode_box->set_visible(false);
+ custom_mode_enabled = false;
+ } else {
+ custom_mode_box->set_visible(true);
+ if (custom_mode_box->is_pressed()) {
+ custom_mode_enabled = true;
+ offset += 3;
+ }
+ }
} else if (mode & MODE_FLAGS_SKY) {
- offset = 6;
+ offset = 8;
}
visual_shader->set_shader_type(VisualShader::Type(p_id + offset));
@@ -3058,6 +3256,21 @@ void VisualShaderEditor::_mode_selected(int p_id) {
_update_graph();
}
+void VisualShaderEditor::_custom_mode_toggled(bool p_enabled) {
+ if (!(mode & MODE_FLAGS_PARTICLES)) {
+ return;
+ }
+ custom_mode_enabled = p_enabled;
+ int id = edit_type->get_selected() + 3;
+ if (p_enabled) {
+ visual_shader->set_shader_type(VisualShader::Type(id + 3));
+ } else {
+ visual_shader->set_shader_type(VisualShader::Type(id));
+ }
+ _update_options_menu();
+ _update_graph();
+}
+
void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input, String p_name) {
String prev_name = p_input->get_input_name();
@@ -3210,14 +3423,14 @@ void VisualShaderEditor::_member_cancel() {
}
void VisualShaderEditor::_tools_menu_option(int p_idx) {
- TreeItem *category = members->get_root()->get_children();
+ TreeItem *category = members->get_root()->get_first_child();
switch (p_idx) {
case EXPAND_ALL:
while (category) {
category->set_collapsed(false);
- TreeItem *sub_category = category->get_children();
+ TreeItem *sub_category = category->get_first_child();
while (sub_category) {
sub_category->set_collapsed(false);
sub_category = sub_category->get_next();
@@ -3231,7 +3444,7 @@ void VisualShaderEditor::_tools_menu_option(int p_idx) {
while (category) {
category->set_collapsed(true);
- TreeItem *sub_category = category->get_children();
+ TreeItem *sub_category = category->get_first_child();
while (sub_category) {
sub_category->set_collapsed(true);
sub_category = sub_category->get_next();
@@ -3333,47 +3546,56 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
saved_node_pos_dirty = true;
_add_node(idx, add_options[idx].sub_func);
} else if (d.has("files")) {
+ undo_redo->create_action(TTR("Add Node(s) to Visual Shader"));
+
if (d["files"].get_type() == Variant::PACKED_STRING_ARRAY) {
- int j = 0;
PackedStringArray arr = d["files"];
for (int i = 0; i < arr.size(); i++) {
String type = ResourceLoader::get_resource_type(arr[i]);
if (type == "GDScript") {
Ref<Script> script = ResourceLoader::load(arr[i]);
if (script->get_instance_base_type() == "VisualShaderNodeCustom") {
- saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
- _add_custom_node(arr[i]);
- j++;
+
+ int idx = -1;
+
+ for (int j = custom_node_option_idx; j < add_options.size(); j++) {
+ if (add_options[j].script.is_valid()) {
+ if (add_options[j].script->get_path() == arr[i]) {
+ idx = j;
+ break;
+ }
+ }
+ }
+ if (idx != -1) {
+ _add_node(idx, -1, arr[i], i);
+ }
}
} else if (type == "CurveTexture") {
- saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
- _add_curve_node(arr[i]);
- j++;
+ _add_node(curve_node_option_idx, -1, arr[i], i);
} else if (ClassDB::get_parent_class(type) == "Texture2D") {
- saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
- _add_texture2d_node(arr[i]);
- j++;
+ _add_node(texture2d_node_option_idx, -1, arr[i], i);
} else if (type == "Texture2DArray") {
- saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
- _add_texture2d_array_node(arr[i]);
- j++;
+ _add_node(texture2d_array_node_option_idx, -1, arr[i], i);
} else if (ClassDB::get_parent_class(type) == "Texture3D") {
- saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
- _add_texture3d_node(arr[i]);
- j++;
+ _add_node(texture3d_node_option_idx, -1, arr[i], i);
} else if (type == "Cubemap") {
- saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
- _add_cubemap_node(arr[i]);
- j++;
+ _add_node(cubemap_node_option_idx, -1, arr[i], i);
}
}
}
+ undo_redo->commit_action();
}
}
}
@@ -3429,17 +3651,18 @@ void VisualShaderEditor::_update_preview() {
Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type);
for (int i = 0; i < preview_text->get_line_count(); i++) {
- preview_text->set_line_as_marked(i, false);
+ preview_text->set_line_background_color(i, Color(0, 0, 0, 0));
}
if (err != OK) {
- preview_text->set_line_as_marked(sl.get_error_line() - 1, true);
- error_text->set_visible(true);
+ Color error_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
+ preview_text->set_line_background_color(sl.get_error_line() - 1, error_line_color);
+ error_panel->show();
String text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
- error_text->set_text(text);
+ error_label->set_text(text);
shader_error = true;
} else {
- error_text->set_visible(false);
+ error_panel->hide();
shader_error = false;
}
}
@@ -3469,10 +3692,11 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_float_constant_selected", &VisualShaderEditor::_float_constant_selected);
ClassDB::bind_method("_update_constant", &VisualShaderEditor::_update_constant);
ClassDB::bind_method("_update_uniform", &VisualShaderEditor::_update_uniform);
+ ClassDB::bind_method("_expand_output_port", &VisualShaderEditor::_expand_output_port);
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &VisualShaderEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &VisualShaderEditor::drop_data_fw);
ClassDB::bind_method("_is_available", &VisualShaderEditor::_is_available);
}
@@ -3545,17 +3769,23 @@ VisualShaderEditor::VisualShaderEditor() {
graph->get_zoom_hbox()->add_child(vs);
graph->get_zoom_hbox()->move_child(vs, 0);
- edit_type_standart = memnew(OptionButton);
- edit_type_standart->add_item(TTR("Vertex"));
- edit_type_standart->add_item(TTR("Fragment"));
- edit_type_standart->add_item(TTR("Light"));
- edit_type_standart->select(1);
- edit_type_standart->connect("item_selected", callable_mp(this, &VisualShaderEditor::_mode_selected));
+ custom_mode_box = memnew(CheckBox);
+ custom_mode_box->set_text(TTR("Custom"));
+ custom_mode_box->set_pressed(false);
+ custom_mode_box->set_visible(false);
+ custom_mode_box->connect("toggled", callable_mp(this, &VisualShaderEditor::_custom_mode_toggled));
+
+ edit_type_standard = memnew(OptionButton);
+ edit_type_standard->add_item(TTR("Vertex"));
+ edit_type_standard->add_item(TTR("Fragment"));
+ edit_type_standard->add_item(TTR("Light"));
+ edit_type_standard->select(1);
+ edit_type_standard->connect("item_selected", callable_mp(this, &VisualShaderEditor::_mode_selected));
edit_type_particles = memnew(OptionButton);
- edit_type_particles->add_item(TTR("Emit"));
+ edit_type_particles->add_item(TTR("Start"));
edit_type_particles->add_item(TTR("Process"));
- edit_type_particles->add_item(TTR("End"));
+ edit_type_particles->add_item(TTR("Collide"));
edit_type_particles->select(0);
edit_type_particles->connect("item_selected", callable_mp(this, &VisualShaderEditor::_mode_selected));
@@ -3564,14 +3794,16 @@ VisualShaderEditor::VisualShaderEditor() {
edit_type_sky->select(0);
edit_type_sky->connect("item_selected", callable_mp(this, &VisualShaderEditor::_mode_selected));
- edit_type = edit_type_standart;
+ edit_type = edit_type_standard;
+ graph->get_zoom_hbox()->add_child(custom_mode_box);
+ graph->get_zoom_hbox()->move_child(custom_mode_box, 0);
+ graph->get_zoom_hbox()->add_child(edit_type_standard);
+ graph->get_zoom_hbox()->move_child(edit_type_standard, 0);
graph->get_zoom_hbox()->add_child(edit_type_particles);
graph->get_zoom_hbox()->move_child(edit_type_particles, 0);
graph->get_zoom_hbox()->add_child(edit_type_sky);
graph->get_zoom_hbox()->move_child(edit_type_sky, 0);
- graph->get_zoom_hbox()->add_child(edit_type_standart);
- graph->get_zoom_hbox()->move_child(edit_type_standart, 0);
add_node = memnew(Button);
add_node->set_flat(true);
@@ -3600,6 +3832,7 @@ VisualShaderEditor::VisualShaderEditor() {
preview_vbox = memnew(VBoxContainer);
preview_window->add_child(preview_vbox);
+ preview_vbox->add_theme_constant_override("separation", 0);
preview_text = memnew(CodeEdit);
syntax_highlighter.instance();
@@ -3609,10 +3842,13 @@ VisualShaderEditor::VisualShaderEditor() {
preview_text->set_draw_line_numbers(true);
preview_text->set_readonly(true);
- error_text = memnew(Label);
- preview_vbox->add_child(error_text);
- error_text->set_autowrap(true);
- error_text->set_visible(false);
+ error_panel = memnew(PanelContainer);
+ preview_vbox->add_child(error_panel);
+ error_panel->set_visible(false);
+
+ error_label = memnew(Label);
+ error_panel->add_child(error_label);
+ error_label->set_autowrap(true);
///////////////////////////////////////
// POPUP MENU
@@ -3787,9 +4023,10 @@ VisualShaderEditor::VisualShaderEditor() {
// INPUT
+ const String input_param_shader_modes = TTR("'%s' input parameter for all shader modes.");
+
// SPATIAL-FOR-ALL
- const String input_param_shader_modes = TTR("'%s' input parameter for all shader modes.");
add_options.push_back(AddOption("Camera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "camera"), "camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("InvCamera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_camera"), "inv_camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("InvProjection", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_projection"), "inv_projection", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
@@ -3808,6 +4045,23 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv"), "uv", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_CANVAS_ITEM));
+ // PARTICLES-FOR-ALL
+
+ add_options.push_back(AddOption("Active", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active"), "active", VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Alpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("AttractorForce", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "attractor_force"), "attractor_force", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Custom", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("CustomAlpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Delta", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("EmissionTransform", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Index", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("LifeTime", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Restart", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "restart"), "restart", VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Transform", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Velocity", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_PARTICLES));
+
/////////////////
add_options.push_back(AddOption("Input", "Input", "Common", "VisualShaderNodeInput", TTR("Input parameter.")));
@@ -3820,11 +4074,12 @@ VisualShaderEditor::VisualShaderEditor() {
const String input_param_for_sky_shader_mode = TTR("'%s' input parameter for sky shader mode.");
const String input_param_for_light_shader_mode = TTR("'%s' input parameter for light shader mode.");
const String input_param_for_vertex_shader_mode = TTR("'%s' input parameter for vertex shader mode.");
- const String input_param_for_emit_shader_mode = TTR("'%s' input parameter for emit shader mode.");
+ const String input_param_for_start_shader_mode = TTR("'%s' input parameter for start shader mode.");
const String input_param_for_process_shader_mode = TTR("'%s' input parameter for process shader mode.");
- const String input_param_for_end_shader_mode = TTR("'%s' input parameter for end shader mode.");
- const String input_param_for_emit_and_process_shader_mode = TTR("'%s' input parameter for emit and process shader mode.");
- const String input_param_for_vertex_and_fragment_shader_mode = TTR("'%s' input parameter for vertex and fragment shader mode.");
+ const String input_param_for_collide_shader_mode = TTR("'%s' input parameter for collide shader mode.");
+ const String input_param_for_start_and_process_shader_mode = TTR("'%s' input parameter for start and process shader modes.");
+ const String input_param_for_process_and_collide_shader_mode = TTR("'%s' input parameter for process and collide shader modes.");
+ const String input_param_for_vertex_and_fragment_shader_mode = TTR("'%s' input parameter for vertex and fragment shader modes.");
add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
@@ -3901,50 +4156,6 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("World", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "world"), "world", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
- // PARTICLES INPUTS
-
- add_options.push_back(AddOption("Active", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active"), "active", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Alpha", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Color", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Custom", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("CustomAlpha", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Delta", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("EmissionTransform", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Index", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("LifeTime", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Restart", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Time", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Transform", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Velocity", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
-
- add_options.push_back(AddOption("Active", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active"), "active", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Alpha", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Color", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Custom", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("CustomAlpha", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Delta", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("EmissionTransform", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Index", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("LifeTime", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Restart", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Time", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Transform", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Velocity", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
-
- add_options.push_back(AddOption("Active", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active"), "active", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Alpha", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Color", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Custom", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("CustomAlpha", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Delta", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("EmissionTransform", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Index", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("LifeTime", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Restart", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Time", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Transform", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Velocity", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_END, Shader::MODE_PARTICLES));
-
// SKY INPUTS
add_options.push_back(AddOption("AtCubeMapPass", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_cubemap_pass"), "at_cubemap_pass", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
@@ -3977,6 +4188,22 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("SkyCoords", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "sky_coords"), "sky_coords", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Time", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
+ // PARTICLES
+
+ add_options.push_back(AddOption("CollisionDepth", "Input", "Collide", "VisualShaderNodeInput", vformat(input_param_for_collide_shader_mode, "collision_depth"), "collision_depth", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("CollisionNormal", "Input", "Collide", "VisualShaderNodeInput", vformat(input_param_for_collide_shader_mode, "collision_normal"), "collision_normal", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
+
+ add_options.push_back(AddOption("EmitParticle", "Particles", "", "VisualShaderNodeParticleEmit", "", -1, -1, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("ParticleAccelerator", "Particles", "", "VisualShaderNodeParticleAccelerator", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("ParticleRandomness", "Particles", "", "VisualShaderNodeParticleRandomness", "", -1, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("MultiplyByAxisAngle", "Particles", "Transform", "VisualShaderNodeParticleMultiplyByAxisAngle", "A node for help to multiply a position input vector by rotation using specific axis. Intended to work with emitters.", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
+
+ add_options.push_back(AddOption("BoxEmitter", "Particles", "Emitters", "VisualShaderNodeParticleBoxEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("RingEmitter", "Particles", "Emitters", "VisualShaderNodeParticleRingEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("SphereEmitter", "Particles", "Emitters", "VisualShaderNodeParticleSphereEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
+
+ add_options.push_back(AddOption("ConeVelocity", "Particles", "Velocity", "VisualShaderNodeParticleConeVelocity", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
+
// SCALAR
add_options.push_back(AddOption("FloatFunc", "Scalar", "Common", "VisualShaderNodeFloatFunc", TTR("Float function."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
@@ -4064,6 +4291,8 @@ VisualShaderEditor::VisualShaderEditor() {
// TEXTURES
+ add_options.push_back(AddOption("UVFunc", "Textures", "Common", "VisualShaderNodeUVFunc", TTR("Function to be applied on texture coordinates."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
+
cubemap_node_option_idx = add_options.size();
add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), -1, -1));
curve_node_option_idx = add_options.size();
@@ -4074,6 +4303,8 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Texture2DArray", "Textures", "Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), -1, -1, -1, -1, -1));
texture3d_node_option_idx = add_options.size();
add_options.push_back(AddOption("Texture3D", "Textures", "Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D texture lookup."), -1, -1));
+ add_options.push_back(AddOption("UVPanning", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply panning function on texture coordinates."), VisualShaderNodeUVFunc::FUNC_PANNING, VisualShaderNode::PORT_TYPE_VECTOR));
+ add_options.push_back(AddOption("UVScaling", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply scaling function on texture coordinates."), VisualShaderNodeUVFunc::FUNC_SCALING, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."), -1, -1));
add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."), -1, -1));
@@ -4090,6 +4321,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("TransformDecompose", "Transform", "Composition", "VisualShaderNodeTransformDecompose", TTR("Decomposes transform to four vectors.")));
add_options.push_back(AddOption("Determinant", "Transform", "Functions", "VisualShaderNodeDeterminant", TTR("Calculates the determinant of a transform."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
+ add_options.push_back(AddOption("GetBillboardMatrix", "Transform", "Functions", "VisualShaderNodeBillboard", TTR("Calculates how the object should face the camera to be applied on Model View Matrix output port for 3D objects."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Inverse", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the inverse of a transform."), VisualShaderNodeTransformFunc::FUNC_INVERSE, VisualShaderNode::PORT_TYPE_TRANSFORM));
add_options.push_back(AddOption("Transpose", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the transpose of a transform."), VisualShaderNodeTransformFunc::FUNC_TRANSPOSE, VisualShaderNode::PORT_TYPE_TRANSFORM));
@@ -4192,13 +4424,6 @@ VisualShaderEditor::VisualShaderEditor() {
_update_options_menu();
- error_panel = memnew(PanelContainer);
- add_child(error_panel);
- error_label = memnew(Label);
- error_panel->add_child(error_label);
- error_label->set_text("eh");
- error_panel->hide();
-
undo_redo = EditorNode::get_singleton()->get_undo_redo();
Ref<VisualShaderNodePluginDefault> default_plugin;
@@ -4279,7 +4504,7 @@ public:
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("int", "EditorIcons"),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Vector3", "EditorIcons"),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("bool", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform", "EditorIcons"),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform3D", "EditorIcons"),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("ImageTexture", "EditorIcons"),
};
@@ -4324,7 +4549,7 @@ public:
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("int", "EditorIcons"),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("bool", "EditorIcons"),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Vector3", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform", "EditorIcons"),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform3D", "EditorIcons"),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Color", "EditorIcons"),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon("ImageTexture", "EditorIcons"),
};
@@ -4515,7 +4740,7 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
if (Object::cast_to<EditorPropertyResource>(prop)) {
Object::cast_to<EditorPropertyResource>(prop)->set_use_sub_inspector(false);
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- } else if (Object::cast_to<EditorPropertyTransform>(prop) || Object::cast_to<EditorPropertyVector3>(prop)) {
+ } else if (Object::cast_to<EditorPropertyTransform3D>(prop) || Object::cast_to<EditorPropertyVector3>(prop)) {
prop->set_custom_minimum_size(Size2(250 * EDSCALE, 0));
} else if (Object::cast_to<EditorPropertyFloat>(prop)) {
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 6d57d38cab..fa98c6b780 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -41,8 +41,8 @@
#include "scene/gui/tree.h"
#include "scene/resources/visual_shader.h"
-class VisualShaderNodePlugin : public Reference {
- GDCLASS(VisualShaderNodePlugin, Reference);
+class VisualShaderNodePlugin : public RefCounted {
+ GDCLASS(VisualShaderNodePlugin, RefCounted);
protected:
static void _bind_methods();
@@ -51,8 +51,8 @@ public:
virtual Control *create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node);
};
-class VisualShaderGraphPlugin : public Reference {
- GDCLASS(VisualShaderGraphPlugin, Reference);
+class VisualShaderGraphPlugin : public RefCounted {
+ GDCLASS(VisualShaderGraphPlugin, RefCounted);
private:
struct InputPort {
@@ -83,6 +83,8 @@ private:
List<VisualShader::Connection> connections;
bool dirty = false;
+ Color vector_expanded_color[3];
+
protected:
static void _bind_methods();
@@ -119,6 +121,7 @@ public:
void set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression);
int get_constant_index(float p_constant) const;
void update_node_size(int p_node_id);
+ void update_theme();
VisualShader::Type get_shader_type() const;
VisualShaderGraphPlugin();
@@ -139,12 +142,11 @@ class VisualShaderEditor : public VBoxContainer {
Button *preview_shader;
OptionButton *edit_type = nullptr;
- OptionButton *edit_type_standart;
+ OptionButton *edit_type_standard;
OptionButton *edit_type_particles;
OptionButton *edit_type_sky;
-
- PanelContainer *error_panel;
- Label *error_label;
+ CheckBox *custom_mode_box;
+ bool custom_mode_enabled = false;
bool pending_update_preview;
bool shader_error;
@@ -152,7 +154,8 @@ class VisualShaderEditor : public VBoxContainer {
VBoxContainer *preview_vbox;
CodeEdit *preview_text;
Ref<CodeHighlighter> syntax_highlighter;
- Label *error_text;
+ PanelContainer *error_panel;
+ Label *error_label;
UndoRedo *undo_redo;
Point2 saved_node_pos;
@@ -188,7 +191,9 @@ class VisualShaderEditor : public VBoxContainer {
enum ParticlesTypeFlags {
TYPE_FLAGS_EMIT = 1,
TYPE_FLAGS_PROCESS = 2,
- TYPE_FLAGS_END = 4
+ TYPE_FLAGS_COLLIDE = 4,
+ TYPE_FLAGS_EMIT_CUSTOM = 8,
+ TYPE_FLAGS_PROCESS_CUSTOM = 16,
};
enum SkyTypeFlags {
@@ -290,15 +295,8 @@ class VisualShaderEditor : public VBoxContainer {
void _draw_color_over_button(Object *obj, Color p_color);
- void _add_custom_node(const String &p_path);
- void _add_cubemap_node(const String &p_path);
- void _add_texture2d_node(const String &p_path);
- void _add_texture2d_array_node(const String &p_path);
- void _add_texture3d_node(const String &p_path);
- void _add_curve_node(const String &p_path);
-
void _setup_node(VisualShaderNode *p_node, int p_op_idx);
- VisualShaderNode *_add_node(int p_idx, int p_op_idx = -1);
+ void _add_node(int p_idx, int p_op_idx = -1, String p_resource_path = "", int p_node_idx = -1);
void _update_options_menu();
void _set_mode(int p_which);
@@ -391,6 +389,7 @@ class VisualShaderEditor : public VBoxContainer {
Ref<VisualShaderGraphPlugin> graph_plugin;
void _mode_selected(int p_id);
+ void _custom_mode_toggled(bool p_enabled);
void _input_select_item(Ref<VisualShaderNodeInput> input, String name);
void _uniform_select_item(Ref<VisualShaderNodeUniformRef> p_uniform, String p_name);
@@ -408,6 +407,7 @@ class VisualShaderEditor : public VBoxContainer {
void _remove_output_port(int p_node, int p_port);
void _change_output_port_type(int p_type, int p_node, int p_port);
void _change_output_port_name(const String &p_text, Object *p_line_edit, int p_node, int p_port);
+ void _expand_output_port(int p_node, int p_port, bool p_expand);
void _expression_focus_out(Object *code_edit, int p_node);
diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp
new file mode 100644
index 0000000000..d30cc7ad17
--- /dev/null
+++ b/editor/plugins/voxel_gi_editor_plugin.cpp
@@ -0,0 +1,173 @@
+/*************************************************************************/
+/* voxel_gi_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "voxel_gi_editor_plugin.h"
+
+void VoxelGIEditorPlugin::_bake() {
+ if (voxel_gi) {
+ if (voxel_gi->get_probe_data().is_null()) {
+ String path = get_tree()->get_edited_scene_root()->get_filename();
+ if (path == String()) {
+ path = "res://" + voxel_gi->get_name() + "_data.res";
+ } else {
+ String ext = path.get_extension();
+ path = path.get_basename() + "." + voxel_gi->get_name() + "_data.res";
+ }
+ probe_file->set_current_path(path);
+ probe_file->popup_file_dialog();
+ return;
+ }
+ voxel_gi->bake();
+ }
+}
+
+void VoxelGIEditorPlugin::edit(Object *p_object) {
+ VoxelGI *s = Object::cast_to<VoxelGI>(p_object);
+ if (!s) {
+ return;
+ }
+
+ voxel_gi = s;
+}
+
+bool VoxelGIEditorPlugin::handles(Object *p_object) const {
+ return p_object->is_class("VoxelGI");
+}
+
+void VoxelGIEditorPlugin::_notification(int p_what) {
+ if (p_what == NOTIFICATION_PROCESS) {
+ if (!voxel_gi) {
+ return;
+ }
+
+ const Vector3i size = voxel_gi->get_estimated_cell_size();
+ String text = vformat(String::utf8("%d × %d × %d"), size.x, size.y, size.z);
+ int data_size = 4;
+ if (GLOBAL_GET("rendering/quality/voxel_gi/anisotropic")) {
+ data_size += 4;
+ }
+ const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0);
+ text += " - " + vformat(TTR("VRAM Size: %s MB"), String::num(size_mb, 2));
+
+ if (bake_info->get_text() == text) {
+ return;
+ }
+
+ // Color the label depending on the estimated performance level.
+ Color color;
+ if (size_mb <= 16.0 + CMP_EPSILON) {
+ // Fast.
+ color = bake_info->get_theme_color("success_color", "Editor");
+ } else if (size_mb <= 64.0 + CMP_EPSILON) {
+ // Medium.
+ color = bake_info->get_theme_color("warning_color", "Editor");
+ } else {
+ // Slow.
+ color = bake_info->get_theme_color("error_color", "Editor");
+ }
+ bake_info->add_theme_color_override("font_color", color);
+
+ bake_info->set_text(text);
+ }
+}
+
+void VoxelGIEditorPlugin::make_visible(bool p_visible) {
+ if (p_visible) {
+ bake_hb->show();
+ set_process(true);
+ } else {
+ bake_hb->hide();
+ set_process(false);
+ }
+}
+
+EditorProgress *VoxelGIEditorPlugin::tmp_progress = nullptr;
+
+void VoxelGIEditorPlugin::bake_func_begin(int p_steps) {
+ ERR_FAIL_COND(tmp_progress != nullptr);
+
+ tmp_progress = memnew(EditorProgress("bake_gi", TTR("Bake GI Probe"), p_steps));
+}
+
+void VoxelGIEditorPlugin::bake_func_step(int p_step, const String &p_description) {
+ ERR_FAIL_COND(tmp_progress == nullptr);
+ tmp_progress->step(p_description, p_step, false);
+}
+
+void VoxelGIEditorPlugin::bake_func_end() {
+ ERR_FAIL_COND(tmp_progress == nullptr);
+ memdelete(tmp_progress);
+ tmp_progress = nullptr;
+}
+
+void VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake(const String &p_path) {
+ probe_file->hide();
+ if (voxel_gi) {
+ voxel_gi->bake();
+ ERR_FAIL_COND(voxel_gi->get_probe_data().is_null());
+ ResourceSaver::save(p_path, voxel_gi->get_probe_data(), ResourceSaver::FLAG_CHANGE_PATH);
+ }
+}
+
+void VoxelGIEditorPlugin::_bind_methods() {
+}
+
+VoxelGIEditorPlugin::VoxelGIEditorPlugin(EditorNode *p_node) {
+ editor = p_node;
+ bake_hb = memnew(HBoxContainer);
+ bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ bake_hb->hide();
+ bake = memnew(Button);
+ bake->set_flat(true);
+ bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
+ bake->set_text(TTR("Bake GI Probe"));
+ bake->connect("pressed", callable_mp(this, &VoxelGIEditorPlugin::_bake));
+ bake_hb->add_child(bake);
+ bake_info = memnew(Label);
+ bake_info->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ bake_info->set_clip_text(true);
+ bake_hb->add_child(bake_info);
+
+ add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake_hb);
+ voxel_gi = nullptr;
+ probe_file = memnew(EditorFileDialog);
+ probe_file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ probe_file->add_filter("*.res");
+ probe_file->connect("file_selected", callable_mp(this, &VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake));
+ get_editor_interface()->get_base_control()->add_child(probe_file);
+ probe_file->set_title(TTR("Select path for VoxelGI Data File"));
+
+ VoxelGI::bake_begin_function = bake_func_begin;
+ VoxelGI::bake_step_function = bake_func_step;
+ VoxelGI::bake_end_function = bake_func_end;
+}
+
+VoxelGIEditorPlugin::~VoxelGIEditorPlugin() {
+}
diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h
new file mode 100644
index 0000000000..4d3cfe90f6
--- /dev/null
+++ b/editor/plugins/voxel_gi_editor_plugin.h
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* voxel_gi_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef VOXEL_GIEDITORPLUGIN_H
+#define VOXEL_GIEDITORPLUGIN_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "scene/3d/voxel_gi.h"
+#include "scene/resources/material.h"
+
+class VoxelGIEditorPlugin : public EditorPlugin {
+ GDCLASS(VoxelGIEditorPlugin, EditorPlugin);
+
+ VoxelGI *voxel_gi;
+
+ HBoxContainer *bake_hb;
+ Label *bake_info;
+ Button *bake;
+ EditorNode *editor;
+
+ EditorFileDialog *probe_file;
+
+ static EditorProgress *tmp_progress;
+ static void bake_func_begin(int p_steps);
+ static void bake_func_step(int p_step, const String &p_description);
+ static void bake_func_end();
+
+ void _bake();
+ void _voxel_gi_save_path_and_bake(const String &p_path);
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ virtual String get_name() const override { return "VoxelGI"; }
+ bool has_main_screen() const override { return false; }
+ virtual void edit(Object *p_object) override;
+ virtual bool handles(Object *p_object) const override;
+ virtual void make_visible(bool p_visible) override;
+
+ VoxelGIEditorPlugin(EditorNode *p_node);
+ ~VoxelGIEditorPlugin();
+};
+
+#endif // VOXEL_GIEDITORPLUGIN_H
diff --git a/editor/pot_generator.h b/editor/pot_generator.h
index ab055e0c0e..61300064ba 100644
--- a/editor/pot_generator.h
+++ b/editor/pot_generator.h
@@ -31,7 +31,7 @@
#ifndef POT_GENERATOR_H
#define POT_GENERATOR_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/templates/ordered_hash_map.h"
#include "core/templates/set.h"
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 3ede50320a..7ca2d4d324 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -31,11 +31,11 @@
#include "project_export.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/string/optimized_translation.h"
#include "editor_data.h"
@@ -795,7 +795,7 @@ void ProjectExportDialog::_tree_changed() {
}
void ProjectExportDialog::_check_dir_recursive(TreeItem *p_dir, bool p_checked) {
- for (TreeItem *child = p_dir->get_children(); child; child = child->get_next()) {
+ for (TreeItem *child = p_dir->get_first_child(); child; child = child->get_next()) {
String path = child->get_metadata(0);
child->set_checked(0, p_checked);
@@ -818,7 +818,7 @@ void ProjectExportDialog::_refresh_parent_checks(TreeItem *p_item) {
}
bool checked = true;
- for (TreeItem *child = parent->get_children(); child; child = child->get_next()) {
+ for (TreeItem *child = parent->get_first_child(); child; child = child->get_next()) {
checked = checked && child->is_checked(0);
if (!checked) {
break;
@@ -978,9 +978,9 @@ void ProjectExportDialog::_export_all(bool p_debug) {
}
void ProjectExportDialog::_bind_methods() {
- ClassDB::bind_method("get_drag_data_fw", &ProjectExportDialog::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw", &ProjectExportDialog::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw", &ProjectExportDialog::drop_data_fw);
+ ClassDB::bind_method("_get_drag_data_fw", &ProjectExportDialog::get_drag_data_fw);
+ ClassDB::bind_method("_can_drop_data_fw", &ProjectExportDialog::can_drop_data_fw);
+ ClassDB::bind_method("_drop_data_fw", &ProjectExportDialog::drop_data_fw);
ClassDB::bind_method("_export_all", &ProjectExportDialog::_export_all);
ClassDB::bind_method("set_export_path", &ProjectExportDialog::set_export_path);
ClassDB::bind_method("get_export_path", &ProjectExportDialog::get_export_path);
diff --git a/editor/project_export.h b/editor/project_export.h
index cfd4934c34..aeace708b8 100644
--- a/editor/project_export.h
+++ b/editor/project_export.h
@@ -31,7 +31,7 @@
#ifndef PROJECT_EXPORT_SETTINGS_H
#define PROJECT_EXPORT_SETTINGS_H
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/thread.h"
#include "editor/editor_export.h"
#include "editor/editor_file_dialog.h"
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 2b75144ac7..12490f687e 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -31,11 +31,11 @@
#include "project_manager.h"
#include "core/io/config_file.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
#include "core/io/stream_peer_ssl.h"
#include "core/io/zip_io.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/string/translation.h"
@@ -100,7 +100,6 @@ private:
FileDialog *fdialog_install;
String zip_path;
String zip_title;
- String zip_root;
AcceptDialog *dialog_error;
String fav_dir;
@@ -201,9 +200,7 @@ private:
char fname[16384];
ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
- String fname_str = String(fname);
- if (fname_str.ends_with("project.godot")) {
- zip_root = fname_str.substr(0, fname_str.rfind("project.godot"));
+ if (String(fname).ends_with("project.godot")) {
break;
}
@@ -524,7 +521,24 @@ private:
return;
}
+ // Find the zip_root
+ String zip_root;
int ret = unzGoToFirstFile(pkg);
+ while (ret == UNZ_OK) {
+ unz_file_info info;
+ char fname[16384];
+ unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
+
+ String name = fname;
+ if (name.ends_with("project.godot")) {
+ zip_root = name.substr(0, name.rfind("project.godot"));
+ break;
+ }
+
+ ret = unzGoToNextFile(pkg);
+ }
+
+ ret = unzGoToFirstFile(pkg);
Vector<String> failed_files;
@@ -1470,16 +1484,7 @@ Vector<ProjectList::Item> ProjectList::get_selected_projects() const {
void ProjectList::ensure_project_visible(int p_index) {
const Item &item = _projects[p_index];
-
- int item_top = item.control->get_position().y;
- int item_bottom = item.control->get_position().y + item.control->get_size().y;
-
- if (item_top < get_v_scroll()) {
- set_v_scroll(item_top);
-
- } else if (item_bottom > get_v_scroll() + get_size().y) {
- set_v_scroll(item_bottom - get_size().y);
- }
+ ensure_control_visible(item.control);
}
int ProjectList::get_single_selected_index() const {
@@ -1740,7 +1745,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
const Item &clicked_project = _projects[clicked_index];
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (mb->get_shift() && _selected_project_keys.size() > 0 && _last_clicked != "" && clicked_project.project_key != _last_clicked) {
+ if (mb->is_shift_pressed() && _selected_project_keys.size() > 0 && _last_clicked != "" && clicked_project.project_key != _last_clicked) {
int anchor_index = -1;
for (int i = 0; i < _projects.size(); ++i) {
const Item &p = _projects[i];
@@ -1752,7 +1757,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
CRASH_COND(anchor_index == -1);
select_range(anchor_index, clicked_index);
- } else if (mb->get_control()) {
+ } else if (mb->is_ctrl_pressed()) {
toggle_select(clicked_index);
} else {
@@ -1762,7 +1767,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
emit_signal(SIGNAL_SELECTION_CHANGED);
- if (!mb->get_control() && mb->is_double_click()) {
+ if (!mb->is_ctrl_pressed() && mb->is_double_click()) {
emit_signal(SIGNAL_PROJECT_ASK_OPEN);
}
}
@@ -1937,7 +1942,7 @@ void ProjectManager::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
} break;
case KEY_UP: {
- if (k->get_shift()) {
+ if (k->is_shift_pressed()) {
break;
}
@@ -1951,7 +1956,7 @@ void ProjectManager::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
break;
}
case KEY_DOWN: {
- if (k->get_shift()) {
+ if (k->is_shift_pressed()) {
break;
}
@@ -1964,7 +1969,7 @@ void ProjectManager::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
} break;
case KEY_F: {
- if (k->get_command()) {
+ if (k->is_command_pressed()) {
this->search_box->grab_focus();
} else {
keycode_handled = false;
@@ -2124,8 +2129,8 @@ void ProjectManager::_run_project_confirm() {
const String &selected = selected_list[i].project_key;
String path = EditorSettings::get_singleton()->get("projects/" + selected);
- // `.right(6)` on `IMPORTED_FILES_PATH` strips away the leading "res://".
- if (!DirAccess::exists(path.plus_file(ProjectSettings::IMPORTED_FILES_PATH.right(6)))) {
+ // `.substr(6)` on `IMPORTED_FILES_PATH` strips away the leading "res://".
+ if (!DirAccess::exists(path.plus_file(ProjectSettings::IMPORTED_FILES_PATH.substr(6)))) {
run_error_diag->set_text(TTR("Can't run project: Assets need to be imported.\nPlease edit the project to trigger the initial import."));
run_error_diag->popup_centered();
continue;
@@ -2485,7 +2490,7 @@ ProjectManager::ProjectManager() {
tabs->connect("tab_changed", callable_mp(this, &ProjectManager::_on_tab_changed));
HBoxContainer *projects_hb = memnew(HBoxContainer);
- projects_hb->set_name(TTR("Projects"));
+ projects_hb->set_name(TTR("Local Projects"));
tabs->add_child(projects_hb);
{
@@ -2616,7 +2621,7 @@ ProjectManager::ProjectManager() {
version_btn = memnew(LinkButton);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
- hash = "." + hash.left(9);
+ hash = " " + vformat("[%s]", hash.left(9));
}
version_btn->set_text("v" VERSION_FULL_BUILD + hash);
// Fade the version label to be less prominent, but still readable.
@@ -2667,7 +2672,7 @@ ProjectManager::ProjectManager() {
if (StreamPeerSSL::is_available()) {
asset_library = memnew(EditorAssetLibrary(true));
- asset_library->set_name(TTR("Templates"));
+ asset_library->set_name(TTR("Asset Library Projects"));
tabs->add_child(asset_library);
asset_library->connect("install_asset", callable_mp(this, &ProjectManager::_install_project));
} else {
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 8b0d9ae0fc..c44f8d9a4b 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -727,13 +727,13 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
value_editor[3]->set_text(String::num(plane.d));
} break;
- case Variant::QUAT: {
+ case Variant::QUATERNION: {
field_names.push_back("x");
field_names.push_back("y");
field_names.push_back("z");
field_names.push_back("w");
config_value_editors(4, 4, 10, field_names);
- Quat q = v;
+ Quaternion q = v;
value_editor[0]->set_text(String::num(q.x));
value_editor[1]->set_text(String::num(q.y));
value_editor[2]->set_text(String::num(q.z));
@@ -791,7 +791,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
}
} break;
- case Variant::TRANSFORM: {
+ case Variant::TRANSFORM3D: {
field_names.push_back("xx");
field_names.push_back("xy");
field_names.push_back("xz");
@@ -806,7 +806,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
field_names.push_back("zo");
config_value_editors(12, 4, 16, field_names);
- Transform tr = v;
+ Transform3D tr = v;
for (int i = 0; i < 9; i++) {
value_editor[(i / 3) * 4 + i % 3]->set_text(String::num(tr.basis.elements[i / 3][i % 3]));
}
@@ -1446,6 +1446,8 @@ void CustomPropertyEditor::_modified(String p_string) {
return;
}
+ Variant prev_v = v;
+
updating = true;
switch (type) {
case Variant::INT: {
@@ -1459,14 +1461,18 @@ void CustomPropertyEditor::_modified(String p_string) {
} else {
v = expr->execute(Array(), nullptr, false);
}
- emit_signal("variant_changed");
+ if (v != prev_v) {
+ emit_signal("variant_changed");
+ }
} break;
case Variant::FLOAT: {
if (hint != PROPERTY_HINT_EXP_EASING) {
String text = TS->parse_number(value_editor[0]->get_text());
v = _parse_real_expression(text);
- emit_signal("variant_changed");
+ if (v != prev_v) {
+ emit_signal("variant_changed");
+ }
}
} break;
@@ -1479,7 +1485,9 @@ void CustomPropertyEditor::_modified(String p_string) {
vec.x = _parse_real_expression(value_editor[0]->get_text());
vec.y = _parse_real_expression(value_editor[1]->get_text());
v = vec;
- _emit_changed_whole_or_field();
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
case Variant::RECT2: {
@@ -1490,7 +1498,9 @@ void CustomPropertyEditor::_modified(String p_string) {
r2.size.x = _parse_real_expression(value_editor[2]->get_text());
r2.size.y = _parse_real_expression(value_editor[3]->get_text());
v = r2;
- _emit_changed_whole_or_field();
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
@@ -1500,7 +1510,9 @@ void CustomPropertyEditor::_modified(String p_string) {
vec.y = _parse_real_expression(value_editor[1]->get_text());
vec.z = _parse_real_expression(value_editor[2]->get_text());
v = vec;
- _emit_changed_whole_or_field();
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
case Variant::PLANE: {
@@ -1510,17 +1522,21 @@ void CustomPropertyEditor::_modified(String p_string) {
pl.normal.z = _parse_real_expression(value_editor[2]->get_text());
pl.d = _parse_real_expression(value_editor[3]->get_text());
v = pl;
- _emit_changed_whole_or_field();
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
- case Variant::QUAT: {
- Quat q;
+ case Variant::QUATERNION: {
+ Quaternion q;
q.x = _parse_real_expression(value_editor[0]->get_text());
q.y = _parse_real_expression(value_editor[1]->get_text());
q.z = _parse_real_expression(value_editor[2]->get_text());
q.w = _parse_real_expression(value_editor[3]->get_text());
v = q;
- _emit_changed_whole_or_field();
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
case Variant::AABB: {
@@ -1534,7 +1550,9 @@ void CustomPropertyEditor::_modified(String p_string) {
size.y = _parse_real_expression(value_editor[4]->get_text());
size.z = _parse_real_expression(value_editor[5]->get_text());
v = AABB(pos, size);
- _emit_changed_whole_or_field();
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
case Variant::TRANSFORM2D: {
@@ -1544,7 +1562,9 @@ void CustomPropertyEditor::_modified(String p_string) {
}
v = m;
- _emit_changed_whole_or_field();
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
case Variant::BASIS: {
@@ -1554,10 +1574,12 @@ void CustomPropertyEditor::_modified(String p_string) {
}
v = m;
- _emit_changed_whole_or_field();
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
- case Variant::TRANSFORM: {
+ case Variant::TRANSFORM3D: {
Basis basis;
for (int i = 0; i < 9; i++) {
basis.elements[i / 3][i % 3] = _parse_real_expression(value_editor[(i / 3) * 4 + i % 3]->get_text());
@@ -1569,8 +1591,10 @@ void CustomPropertyEditor::_modified(String p_string) {
origin.y = _parse_real_expression(value_editor[7]->get_text());
origin.z = _parse_real_expression(value_editor[11]->get_text());
- v = Transform(basis, origin);
- _emit_changed_whole_or_field();
+ v = Transform3D(basis, origin);
+ if (v != prev_v) {
+ _emit_changed_whole_or_field();
+ }
} break;
case Variant::COLOR: {
@@ -1578,7 +1602,9 @@ void CustomPropertyEditor::_modified(String p_string) {
case Variant::NODE_PATH: {
v = NodePath(value_editor[0]->get_text());
- emit_signal("variant_changed");
+ if (v != prev_v) {
+ emit_signal("variant_changed");
+ }
} break;
case Variant::DICTIONARY: {
} break;
@@ -1635,11 +1661,11 @@ void CustomPropertyEditor::_focus_enter() {
case Variant::RECT2:
case Variant::VECTOR3:
case Variant::PLANE:
- case Variant::QUAT:
+ case Variant::QUATERNION:
case Variant::AABB:
case Variant::TRANSFORM2D:
case Variant::BASIS:
- case Variant::TRANSFORM: {
+ case Variant::TRANSFORM3D: {
for (int i = 0; i < MAX_VALUE_EDITORS; ++i) {
if (value_editor[i]->has_focus()) {
focused_value_editor = i;
@@ -1654,25 +1680,7 @@ void CustomPropertyEditor::_focus_enter() {
}
void CustomPropertyEditor::_focus_exit() {
- switch (type) {
- case Variant::FLOAT:
- case Variant::STRING:
- case Variant::VECTOR2:
- case Variant::RECT2:
- case Variant::VECTOR3:
- case Variant::PLANE:
- case Variant::QUAT:
- case Variant::AABB:
- case Variant::TRANSFORM2D:
- case Variant::BASIS:
- case Variant::TRANSFORM: {
- for (int i = 0; i < MAX_VALUE_EDITORS; ++i) {
- value_editor[i]->select(0, 0);
- }
- } break;
- default: {
- }
- }
+ _modified(String());
}
void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) {
diff --git a/editor/property_editor.h b/editor/property_editor.h
index c6929f3b42..8a587b50b0 100644
--- a/editor/property_editor.h
+++ b/editor/property_editor.h
@@ -50,8 +50,8 @@ class PropertyValueEvaluator;
class CreateDialog;
class PropertySelector;
-class EditorResourceConversionPlugin : public Reference {
- GDCLASS(EditorResourceConversionPlugin, Reference);
+class EditorResourceConversionPlugin : public RefCounted {
+ GDCLASS(EditorResourceConversionPlugin, RefCounted);
protected:
static void _bind_methods();
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index da798962e5..00652c02c8 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -52,7 +52,7 @@ void PropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) {
search_box->accept_event();
TreeItem *root = search_options->get_root();
- if (!root->get_children()) {
+ if (!root->get_first_child()) {
break;
}
@@ -125,18 +125,23 @@ void PropertySelector::_update_search() {
search_options->get_theme_icon("float", "EditorIcons"),
search_options->get_theme_icon("String", "EditorIcons"),
search_options->get_theme_icon("Vector2", "EditorIcons"),
+ search_options->get_theme_icon("Vector2i", "EditorIcons"),
search_options->get_theme_icon("Rect2", "EditorIcons"),
+ search_options->get_theme_icon("Rect2i", "EditorIcons"),
search_options->get_theme_icon("Vector3", "EditorIcons"),
+ search_options->get_theme_icon("Vector3i", "EditorIcons"),
search_options->get_theme_icon("Transform2D", "EditorIcons"),
search_options->get_theme_icon("Plane", "EditorIcons"),
- search_options->get_theme_icon("Quat", "EditorIcons"),
+ search_options->get_theme_icon("Quaternion", "EditorIcons"),
search_options->get_theme_icon("AABB", "EditorIcons"),
search_options->get_theme_icon("Basis", "EditorIcons"),
- search_options->get_theme_icon("Transform", "EditorIcons"),
+ search_options->get_theme_icon("Transform3D", "EditorIcons"),
search_options->get_theme_icon("Color", "EditorIcons"),
- search_options->get_theme_icon("Path", "EditorIcons"),
+ search_options->get_theme_icon("NodePath", "EditorIcons"),
search_options->get_theme_icon("RID", "EditorIcons"),
- search_options->get_theme_icon("Object", "EditorIcons"),
+ search_options->get_theme_icon("MiniObject", "EditorIcons"),
+ search_options->get_theme_icon("Callable", "EditorIcons"),
+ search_options->get_theme_icon("Signal", "EditorIcons"),
search_options->get_theme_icon("Dictionary", "EditorIcons"),
search_options->get_theme_icon("Array", "EditorIcons"),
search_options->get_theme_icon("PackedByteArray", "EditorIcons"),
@@ -150,7 +155,7 @@ void PropertySelector::_update_search() {
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
if (E->get().usage == PROPERTY_USAGE_CATEGORY) {
- if (category && category->get_children() == nullptr) {
+ if (category && category->get_first_child() == nullptr) {
memdelete(category); //old category was unused
}
category = search_options->create_item(root);
@@ -192,7 +197,7 @@ void PropertySelector::_update_search() {
item->set_selectable(0, true);
}
- if (category && category->get_children() == nullptr) {
+ if (category && category->get_first_child() == nullptr) {
memdelete(category); //old category was unused
}
} else {
@@ -225,7 +230,7 @@ void PropertySelector::_update_search() {
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
if (E->get().name.begins_with("*")) {
- if (category && category->get_children() == nullptr) {
+ if (category && category->get_first_child() == nullptr) {
memdelete(category); //old category was unused
}
category = search_options->create_item(root);
@@ -316,12 +321,12 @@ void PropertySelector::_update_search() {
}
}
- if (category && category->get_children() == nullptr) {
+ if (category && category->get_first_child() == nullptr) {
memdelete(category); //old category was unused
}
}
- get_ok_button()->set_disabled(root->get_children() == nullptr);
+ get_ok_button()->set_disabled(root->get_first_child() == nullptr);
}
void PropertySelector::_confirmed() {
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
index 7f720d65d0..e8e13bab21 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -102,7 +102,7 @@ void EditorQuickOpen::_update_search() {
ti->set_icon(0, *icons.lookup_ptr(entries[i].path.get_extension()));
}
- TreeItem *to_select = root->get_children();
+ TreeItem *to_select = root->get_first_child();
to_select->select(0);
to_select->set_as_cursor(0);
search_options->scroll_to_item(to_select);
@@ -170,7 +170,7 @@ void EditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) {
if (allow_multi_select) {
TreeItem *root = search_options->get_root();
- if (!root->get_children()) {
+ if (!root->get_first_child()) {
break;
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 4068a102df..8d59b478ba 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1833,7 +1833,7 @@ bool SceneTreeDock::_is_collapsed_recursive(TreeItem *p_item) const {
TreeItem *item = needs_check.back()->get();
needs_check.pop_back();
- TreeItem *child = item->get_children();
+ TreeItem *child = item->get_first_child();
is_branch_collapsed = item->is_collapsed() && child;
if (is_branch_collapsed) {
@@ -1857,7 +1857,7 @@ void SceneTreeDock::_set_collapsed_recursive(TreeItem *p_item, bool p_collapsed)
item->set_collapsed(p_collapsed);
- TreeItem *child = item->get_children();
+ TreeItem *child = item->get_first_child();
while (child) {
to_collapse.push_back(child);
child = child->get_next();
@@ -2059,6 +2059,8 @@ void SceneTreeDock::_selection_changed() {
_tool_selected(TOOL_MULTI_EDIT);
} else if (selection_size == 0) {
editor->push_item(nullptr);
+ } else {
+ editor->push_item(EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->value());
}
_update_script_button();
@@ -2959,6 +2961,7 @@ void SceneTreeDock::_clear_clipboard() {
void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap) {
List<PropertyInfo> props;
p_node->get_property_list(&props);
+ bool is_instanced = EditorPropertyRevert::may_node_be_in_instance(p_node);
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
@@ -2969,6 +2972,15 @@ void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap)
if (v.is_ref()) {
RES res = v;
if (res.is_valid()) {
+ if (is_instanced) {
+ Variant orig;
+ if (EditorPropertyRevert::get_instanced_node_original_property(p_node, E->get().name, orig)) {
+ if (!EditorPropertyRevert::is_node_property_different(p_node, v, orig)) {
+ continue;
+ }
+ }
+ }
+
if ((res->get_path() == "" || res->get_path().find("::") > -1) && !r_remap.has(res)) {
_create_remap_for_resource(res, r_remap);
}
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index d0bf83eb2d..a5620f8cc5 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -699,7 +699,7 @@ TreeItem *SceneTreeEditor::_find(TreeItem *p_node, const NodePath &p_path) {
return p_node;
}
- TreeItem *children = p_node->get_children();
+ TreeItem *children = p_node->get_first_child();
while (children) {
TreeItem *n = _find(children, p_path);
if (n) {
@@ -883,7 +883,7 @@ void SceneTreeEditor::_update_selection(TreeItem *item) {
item->deselect(0);
}
- TreeItem *c = item->get_children();
+ TreeItem *c = item->get_first_child();
while (c) {
_update_selection(c);
@@ -1129,9 +1129,9 @@ void SceneTreeEditor::_bind_methods() {
ClassDB::bind_method("_rename_node", &SceneTreeEditor::_rename_node);
ClassDB::bind_method("_test_update_tree", &SceneTreeEditor::_test_update_tree);
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SceneTreeEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SceneTreeEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &SceneTreeEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &SceneTreeEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &SceneTreeEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &SceneTreeEditor::drop_data_fw);
ClassDB::bind_method(D_METHOD("update_tree"), &SceneTreeEditor::update_tree);
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index c2bfdaae96..650decfd49 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -31,9 +31,9 @@
#include "script_create_dialog.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
#include "core/object/script_language.h"
-#include "core/os/file_access.h"
#include "core/string/string_builder.h"
#include "editor/create_dialog.h"
#include "editor/editor_node.h"
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 541ec224b9..c05a3c2f89 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -235,8 +235,8 @@ void EditorSettingsDialog::_update_shortcuts() {
// Before clearing the tree, take note of which categories are collapsed so that this state can be maintained when the tree is repopulated.
Map<String, bool> collapsed;
- if (shortcuts->get_root() && shortcuts->get_root()->get_children()) {
- for (TreeItem *item = shortcuts->get_root()->get_children(); item; item = item->get_next()) {
+ if (shortcuts->get_root() && shortcuts->get_root()->get_first_child()) {
+ for (TreeItem *item = shortcuts->get_root()->get_first_child(); item; item = item->get_next()) {
collapsed[item->get_text(0)] = item->is_collapsed();
}
}
@@ -261,10 +261,6 @@ void EditorSettingsDialog::_update_shortcuts() {
for (OrderedHashMap<StringName, InputMap::Action>::Element E = action_map.front(); E; E = E.next()) {
String action_name = E.key();
- if (!shortcut_filter.is_subsequence_ofi(action_name)) {
- continue;
- }
-
InputMap::Action action = E.get();
Array events; // Need to get the list of events into an array so it can be set as metadata on the item.
@@ -298,6 +294,10 @@ void EditorSettingsDialog::_update_shortcuts() {
// Join the text of the events with a delimiter so they can all be displayed in one cell.
String events_display_string = event_strings.is_empty() ? "None" : String("; ").join(event_strings);
+ if (!shortcut_filter.is_subsequence_ofi(action_name) && (events_display_string == "None" || !shortcut_filter.is_subsequence_ofi(events_display_string))) {
+ continue;
+ }
+
TreeItem *item = shortcuts->create_item(common_section);
item->set_text(0, action_name);
item->set_text(1, events_display_string);
@@ -380,7 +380,7 @@ void EditorSettingsDialog::_update_shortcuts() {
// remove sections with no shortcuts
for (Map<String, TreeItem *>::Element *E = sections.front(); E; E = E->next()) {
TreeItem *section = E->get();
- if (section->get_children() == nullptr) {
+ if (section->get_first_child() == nullptr) {
root->remove_child(section);
}
}
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index ebef5be9ed..1893c6b6bb 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -199,7 +199,7 @@ protected:
pinfo.type = Variant::TRANSFORM2D;
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- pinfo.type = Variant::TRANSFORM;
+ pinfo.type = Variant::TRANSFORM3D;
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
pinfo.type = Variant::PACKED_INT32_ARRAY;
@@ -326,7 +326,7 @@ static Variant create_var(RS::GlobalVariableType p_type) {
return Transform2D();
}
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- return Transform();
+ return Transform3D();
}
case RS::GLOBAL_VAR_TYPE_MAT4: {
Vector<real_t> xform;
diff --git a/editor/translations/af.po b/editor/translations/af.po
index c528e2a063..3b031597c5 100644
--- a/editor/translations/af.po
+++ b/editor/translations/af.po
@@ -2590,7 +2590,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -3006,6 +3006,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5266,16 +5270,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10132,7 +10127,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index 52c609055c..14e83cd623 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -2568,7 +2568,7 @@ msgstr "غير قادر علي تحميل النص البرمجي Ù„Ù„Ø¥Ø¶Ø§ÙØ©
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"غير قادر علي تحميل النص البرمجي Ø§Ù„Ø¥Ø¶Ø§ÙØ¨ من المسار: '%s' يبدو أن Ø´ÙÙØ±Ø© "
@@ -3018,6 +3018,10 @@ msgid "About"
msgstr "حول"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "تشغيل المشروع."
@@ -5233,18 +5237,9 @@ msgstr ""
"[0.0،1.0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr "تم تجميع محرر Godot دون دعم لتتبع الأشعة. لا يمكن بناء خرائط الإضاءة."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10151,7 +10146,7 @@ msgstr "زر Ø§Ù„ÙØ£Ø±Ø©"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"اسم ÙØ¹Ø§Ù„ية غير صحيح. لا يمكن أن يكون ÙØ§Ø±ØºØ§Ù‹ أو يتضمن '/'ØŒ ':'ØŒ '='ØŒ '\\' أو "
diff --git a/editor/translations/az.po b/editor/translations/az.po
index 266e51d7fe..70bae366d7 100644
--- a/editor/translations/az.po
+++ b/editor/translations/az.po
@@ -2512,7 +2512,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2918,6 +2918,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5072,16 +5076,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9760,7 +9755,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index 6f0b756ce1..f934340bfe 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -2457,7 +2457,7 @@ msgstr "Ðе може да Ñе зареди добавката-Ñкрипт оÑ
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Ðе може да Ñе зареди добавката-Ñкрипт от: „%s“. Изглежда има грешка в кода. "
@@ -2886,6 +2886,10 @@ msgid "About"
msgstr "ОтноÑно"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "ПуÑкане на проекта."
@@ -5065,18 +5069,9 @@ msgstr ""
"принадлежат на квадратната облаÑÑ‚ [0.0,1.0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Редакторът на Godot е бил компилиран без поддръжка за траÑиране на лъчи. Ðе "
"могат да Ñе изпичат карти на оÑветеноÑÑ‚."
@@ -9795,7 +9790,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index d47fbe367c..9c6d70b301 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -2655,7 +2655,7 @@ msgstr "%s হতে সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ তà§à¦²à¦¤à§‡/লোডে à¦
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"'%s' পাথ বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦° করে অà§à¦¯à¦¾à¦¡-অন সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ লোড করা সমà§à¦­à¦¬ হয়নি। সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿà¦Ÿà¦¿ টà§à¦² মোডে নেই।"
@@ -3136,6 +3136,10 @@ msgid "About"
msgstr "সমà§à¦¬à¦¨à§à¦§à§‡"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "পà§à¦°à¦•লà§à¦ªà¦Ÿà¦¿ চালান।"
@@ -5550,16 +5554,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10731,7 +10726,7 @@ msgstr "মাউসের বোতাম"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/br.po b/editor/translations/br.po
index ab03bb5425..307b5b365f 100644
--- a/editor/translations/br.po
+++ b/editor/translations/br.po
@@ -2457,7 +2457,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2863,6 +2863,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5017,16 +5021,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9705,7 +9700,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index 4086771705..5dd319fbc1 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -2561,7 +2561,7 @@ msgstr "Error carregant l'Script complement des del camí: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"No es pot carregar l'script d'addon des del camí: '%s' Sembla que hi ha un "
@@ -3017,6 +3017,10 @@ msgid "About"
msgstr "Quant a"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Reprodueix el projecte."
@@ -5285,16 +5289,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10414,7 +10409,7 @@ msgstr "Botó del ratolí"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nom d'acció no vàlid. No pot estar buit ni contenir '/', ':', '=', '\\' o "
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index b0d92db7a0..dd0f7a51c9 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -25,12 +25,13 @@
# kubajz22 <til.jakubesko@seznam.cz>, 2020.
# Václav Blažej <vaclavblazej@seznam.cz>, 2020, 2021.
# ProfJack <profjackcz@gmail.com>, 2021.
+# swifterik <blaha.j502@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-03 06:13+0000\n"
-"Last-Translator: Vojtěch Šamla <auzkok@seznam.cz>\n"
+"PO-Revision-Date: 2021-05-21 11:33+0000\n"
+"Last-Translator: swifterik <blaha.j502@gmail.com>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/"
"cs/>\n"
"Language: cs\n"
@@ -2547,14 +2548,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "Nelze naÄíst skript rozšíření z cesty: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Nelze naÄíst skript rozšíření z cesty: '%s'. Zdá se, že se v kódu nachází "
-"chyba. Prosím, zkontrolujte syntax."
+"chyba.\n"
+"Deaktivujte rozšíření '%s' abyste předešli dalším chybám."
#: editor/editor_node.cpp
msgid ""
@@ -2994,6 +2995,10 @@ msgid "About"
msgstr "O aplikaci"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Podpořte projekt Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Spustit projekt."
@@ -5215,18 +5220,9 @@ msgstr ""
"Ätvercové oblasti [0.0, 1.0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Godot byl sestaven bez podpory ray tracingu, světelné mapy nelze zapéct."
@@ -10109,7 +10105,7 @@ msgstr "TlaÄítko myÅ¡i"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Neplatné jméno akce. Nesmí být prázdné nebo obsahovat '/', ':', '=', '\\' "
@@ -11637,7 +11633,6 @@ msgid "Post processing"
msgstr "Následné zpracování"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Plotting lightmaps"
msgstr "Vykreslování světelných map"
diff --git a/editor/translations/da.po b/editor/translations/da.po
index 64e6e1c517..a4ed166f41 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -2639,7 +2639,7 @@ msgstr "Kan ikke indlæse addon script fra stien: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Kan ikke indlæse tilføjelse script fra sti: '%s' Der ser ud til at være en "
@@ -3102,6 +3102,10 @@ msgid "About"
msgstr "Om"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Spil dit projekt."
@@ -5406,16 +5410,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10358,7 +10353,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/de.po b/editor/translations/de.po
index 4bfa2e5796..567a096e48 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -68,12 +68,13 @@
# Daniel Plaster <danimineiromc@googlemail.com>, 2021.
# El Captian <elcaptian@posteo.me>, 2021.
# Ron Eric Hackländer <mail@roneric.net>, 2021.
+# Stephan Kerbl <stephankerbl@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-03 21:29+0000\n"
-"Last-Translator: Günther Bohn <ciscouser@gmx.de>\n"
+"PO-Revision-Date: 2021-05-24 21:36+0000\n"
+"Last-Translator: Stephan Kerbl <stephankerbl@gmail.com>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
"Language: de\n"
@@ -2448,8 +2449,7 @@ msgid ""
"Please read the documentation relevant to debugging to better understand "
"this workflow."
msgstr ""
-"Dies ist ein Laufzeit-Objekt Objekt, Änderungen an ihm werden nicht "
-"gespeichert.\n"
+"Dies ist ein Laufzeit-Objekt, Änderungen werden nicht gespeichert.\n"
"Die Dokumentation zum Debugging beschreibt den nötigen Arbeitsablauf."
#: editor/editor_node.cpp
@@ -2617,14 +2617,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "Erweiterungsskript konnte nicht geladen werden: ‚%s‘."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Erweiterungsskript konnte nicht von folgendem Pfad geladen werden: ‚%s‘. Es "
-"scheint ein Fehler im Quellcode zu sein. Bitte Syntax überprüfen."
+"Erweiterungsskript auf folgendem Pfad konnte nicht geladen werden: ‚%s‘. Es "
+"scheint ein Fehler in dessen Quellcode zu sein.\n"
+"Die Erweiterung ‚%s‘ wird deaktiviert um weitere Fehler zu verhindern."
#: editor/editor_node.cpp
msgid ""
@@ -3075,6 +3075,10 @@ msgid "About"
msgstr "Über"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Unterstützung der Godot-Entwicklung"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Projekt abspielen."
@@ -4936,7 +4940,7 @@ msgstr "Abspielmodus:"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "AnimationTree"
-msgstr "AnimationsBaum"
+msgstr "AnimationTree"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "New name:"
@@ -5313,19 +5317,9 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
-"Diese Godot-Version wurde ohne Raytracing-Unterstützung erstellt, Lightmaps "
+"Der Godot-Editor wurde ohne Raytracing-Unterstützung erstellt; Lightmaps "
"können damit nicht gebacken werden."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10255,7 +10249,7 @@ msgstr "Maustaste"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Ungültiger Aktionsname. Er kann weder leer sein noch ‚/‘, ‚:‘, ‚=‘, ‘\\‘ "
@@ -13333,6 +13327,18 @@ msgid "Constants cannot be modified."
msgstr "Konstanten können nicht verändert werden."
#~ msgid ""
+#~ "Godot editor was built without ray tracing support; lightmaps can't be "
+#~ "baked.\n"
+#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta "
+#~ "emulation on Godot.app in the application settings\n"
+#~ "then restart the editor."
+#~ msgstr ""
+#~ "Der Godot-Editor wurde ohne Raytracing-Unterstützung gebaut; Lightmaps "
+#~ "können nicht gebacken werden.\n"
+#~ "Nutzer eines Macs basierend auf Apple Silicon sollten Rosetta-Emulation "
+#~ "in den Anwendungseinstellungen aktivieren und den Editor neu starten."
+
+#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
#~ "InterpolatedCamera ist veraltet und wird in Godot 4.0 entfernt werden."
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index 2483cd1ed4..2ecb929f1f 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -2435,7 +2435,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2841,6 +2841,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -4995,16 +4999,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9683,7 +9678,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/el.po b/editor/translations/el.po
index bbd2148968..e968002238 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -2,22 +2,22 @@
# Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
# Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
-# George Tsiamasiotis <gtsiam@windowslive.com>, 2017-2018, 2019, 2020.
+# George Tsiamasiotis <gtsiam@windowslive.com>, 2017-2018, 2019, 2020, 2021.
# Georgios Katsanakis <geo.elgeo@gmail.com>, 2019.
# Overloaded <manoschool@yahoo.gr>, 2019.
# Eternal Death <eternaldeath0001@gmail.com>, 2019.
# Overloaded @ Orama Interactive http://orama-interactive.com/ <manoschool@yahoo.gr>, 2020.
# pandektis <pandektis@gmail.com>, 2020.
# KostasMSC <kargyris@athtech.gr>, 2020.
-# lawfulRobot <czavantias@gmail.com>, 2020.
+# lawfulRobot <czavantias@gmail.com>, 2020, 2021.
# Michalis <michalisntovas@yahoo.gr>, 2021.
# leriaz <leriaz@live.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-26 22:31+0000\n"
-"Last-Translator: Michalis <michalisntovas@yahoo.gr>\n"
+"PO-Revision-Date: 2021-05-30 04:15+0000\n"
+"Last-Translator: lawfulRobot <czavantias@gmail.com>\n"
"Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/"
"el/>\n"
"Language: el\n"
@@ -1051,15 +1051,15 @@ msgstr ""
"επαναφέÏετε."
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
"Remove them anyway? (no undo)\n"
"You can find the removed files in the system trash to restore them."
msgstr ""
-"Τα αÏχεία που αφαιÏοÏνται απαιτοÏνται από άλλους πόÏους για να δουλέψουν.\n"
-"Îα αφαιÏεθοÏν; (ΑδÏνατη η αναίÏεση)"
+"Τα αÏχεία που αφαιÏοÏνται απαιτοÏνται για την λειτουÏγία άλλων πόÏων.\n"
+"Îα αφαιÏεθοÏν; (ΑδÏνατη η αναίÏεση)\n"
+"ΜποÏείτε να τα επαναφέÏετε αÏγότεÏα από τον κάδο ανακÏκλωσης του συστήματος."
#: editor/dependency_editor.cpp
msgid "Cannot remove:"
@@ -1614,22 +1614,20 @@ msgstr ""
"«Driver Fallback Enabled»."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'PVRTC' texture compression for GLES2. Enable "
"'Import Pvrtc' in Project Settings."
msgstr ""
-"Η πλατφόÏμα Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Î±Ï€Î±Î¹Ï„ÎµÎ¯ «ETC» συμπίεση υφών για το GLES2. "
-"ΕνεÏγοποιήστε το «Import Etc» στις Ρυθμίσεις ΈÏγου."
+"Η πλατφόÏμα Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Î±Ï€Î±Î¹Ï„ÎµÎ¯ συμπίεση υφών 'PVRTC' για το GLES2. "
+"ΕνεÏγοποιήστε το 'Εισαγωγή PVRTC' στις Ρυθμίσεις ΈÏγου."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'ETC2' or 'PVRTC' texture compression for GLES3. "
"Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings."
msgstr ""
-"Η πλατφόÏμα Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Î±Ï€Î±Î¹Ï„ÎµÎ¯ «ETC2» συμπίεση υφών για το GLES3. "
-"ΕνεÏγοποιήστε το «Import Etc 2» στις Ρυθμίσεις ΈÏγου."
+"Η πλατφόÏμα Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Î±Ï€Î±Î¹Ï„ÎµÎ¯ συμπίεση υφών 'ETC2' ή PVRTC' για το GLES3. "
+"ΕνεÏγοποιήστε το 'Εισαγωγή ETC2' ή 'Εισαγωγή PVRTC' στις Ρυθμίσεις ΈÏγου."
#: editor/editor_export.cpp
#, fuzzy
@@ -2323,6 +2321,10 @@ msgid ""
"An error occurred while trying to save the editor layout.\n"
"Make sure the editor's user data path is writable."
msgstr ""
+"ΠÏόεκυψε ένα σφάλμα κατά την αποθήκευση της διάταξης του Ï€ÏογÏάμματος "
+"επεξεÏγασίας.\n"
+"Βεβαιωθείτε ότι η διαδÏομή δεδομένων του χÏήστη του Ï€ÏογÏάμματος "
+"επεξεÏγασίας είναι εγγÏάψιμη."
#: editor/editor_node.cpp
msgid ""
@@ -2330,15 +2332,18 @@ msgid ""
"To restore the Default layout to its base settings, use the Delete Layout "
"option and delete the Default layout."
msgstr ""
+"Η Ï€Ïοεπιλεγμένη διάταξη του Ï€ÏογÏάμματος επεξεÏγασίας έχει παÏακαμφθεί.\n"
+"Για να επαναφέÏετε την ΠÏοεπιλεγμένη διάταξη στις βασικές Ïυθμίσεις, "
+"διαλέξτε την επιλογή ΔιαγÏαφή Διάταξης και διαγÏάψτε την ΠÏοεπιλεγμένη "
+"διάταξη."
#: editor/editor_node.cpp
msgid "Layout name not found!"
msgstr "Το όνομα της διάταξης δεν βÏέθηκε!"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Restored the Default layout to its base settings."
-msgstr "ΕπαναφοÏά της Ï€Ïοεπιλεγμένης διάταξης στις βασικές Ïυθμίσεις."
+msgstr "Έγινε επαναφοÏά της Ï€Ïοεπιλεγμένης διάταξης στις βασικές Ïυθμίσεις."
#: editor/editor_node.cpp
msgid ""
@@ -2397,7 +2402,7 @@ msgstr "Δεν υπάÏχει καθοÏισμένη σκηνή για εκτεÎ
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "Αποθήκευση σκηνής Ï€Ïιν την εκτέλεση..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2546,25 +2551,23 @@ msgstr ""
"αÏχείου ÏÏθμισης."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
-"ΑδÏνατη η έυÏεση του πεδίου 'script' για την Ï€Ïόσθετη επέκταση στο: 'res://"
-"addons/%s'."
+"ΑδÏνατη η έυÏεση του πεδίου δέσμης ενεÏγειών για το Ï€Ïόσθετο στο: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
msgstr "ΑδÏνατη η φόÏτωση δέσμης ενεÏγειών Ï€Ïοσθέτου από τη διαδÏομή: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Αποτυχία φόÏτωσης δέσμης ενεÏγειών Ï€Ïοσθέτου από τη διαδÏομή: '%s'. Φαίνεται "
-"πως υπάÏχει λάθος στον κώδικα."
+"πως υπάÏχει λάθος στον κώδικα.\n"
+"Έγινε απενεÏγοποίηση το Ï€Ïοσθέτου '%s' για αποτÏοπή πεÏαιτέÏω Ï€Ïοβλημάτων."
#: editor/editor_node.cpp
msgid ""
@@ -3015,6 +3018,11 @@ msgid "About"
msgstr "Σχετικά"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Support Godot Development"
+msgstr "ΥποστηÏίξτε την ανάπτυξη του Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "ΑναπαÏαγωγή του έÏγου."
@@ -3157,13 +3165,12 @@ msgid "Open & Run a Script"
msgstr "Άνοιξε & ΤÏέξε μία δέσμη ενεÏγειών"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"The following files are newer on disk.\n"
"What action should be taken?"
msgstr ""
"Τα ακόλουθα αÏχεία είναι νεότεÏα στον δίσκο.\n"
-"Τι δÏάση να ληφθεί;:"
+"Τι δÏάση να ληφθεί;"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
@@ -3705,9 +3712,12 @@ msgstr ""
"επανεισάγετε το χειÏοκίνητα."
#: editor/filesystem_dock.cpp
+#, fuzzy
msgid ""
"Importing has been disabled for this file, so it can't be opened for editing."
msgstr ""
+"Η εισαγωγή έχει απενεÏγοποιηθεί για αυτό το αÏχείο, οπότε δεν μποÏεί να "
+"ανοιχτεί για επεξεÏγασία."
#: editor/filesystem_dock.cpp
msgid "Cannot move/rename resources root."
@@ -3754,6 +3764,12 @@ msgid ""
"\n"
"Do you wish to overwrite them?"
msgstr ""
+"Τα ακόλουθα αÏχεία ή φάκελοι συγκÏοÏονται με στοιχεία στον Ï€ÏοοÏισμό \"%s"
+"\":\n"
+"\n"
+"%s\n"
+"\n"
+"Θέλετε να τα αντικαταστήσετε;"
#: editor/filesystem_dock.cpp
msgid "Renaming file:"
@@ -3836,7 +3852,7 @@ msgstr "ΑναπαÏαγωγή..."
#: editor/filesystem_dock.cpp
#, fuzzy
msgid "Move to Trash"
-msgstr "Μετακίνηση AutoLoad"
+msgstr "Μετακίνηση στα αποÏÏίμματα"
#: editor/filesystem_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
msgid "Rename..."
@@ -3947,19 +3963,16 @@ msgid "Searching..."
msgstr "Αναζήτηση..."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d match in %d file."
-msgstr "%d αποτελέσματα."
+msgstr "%d αποτέλεσμα σε %d αÏχείο."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d file."
-msgstr "%d αποτελέσματα."
+msgstr "%d αποτελέσματα σε %d αÏχείο."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d files."
-msgstr "%d αποτελέσματα."
+msgstr "%d αποτελέσματα σε %d αÏχεία."
#: editor/groups_editor.cpp
msgid "Add to Group"
@@ -4099,23 +4112,20 @@ msgid "Saving..."
msgstr "Αποθήκευση..."
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Select Importer"
-msgstr "Επιλογή ΛειτουÏγίας"
+msgstr "Επιλογή Εισαγωγέα"
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Importer:"
-msgstr "Εισαγωγή"
+msgstr "Εισαγωγέας:"
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Reset to Defaults"
-msgstr "ΧÏήση Ï€Ïοεπιλεγμένου sRGB"
+msgstr "ΕπαναφοÏά Ï€Ïοεπιλογών"
#: editor/import_dock.cpp
msgid "Keep File (No Import)"
-msgstr ""
+msgstr "ΔιατήÏηση αÏχειου (ΧωÏίς Εισαγωγή)"
#: editor/import_dock.cpp
msgid "%d Files"
@@ -5220,16 +5230,13 @@ msgid "Assets ZIP File"
msgstr "ΑÏχείο ZIP των Στοιχείων"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid ""
"Can't determine a save path for lightmap images.\n"
"Save your scene and try again."
msgstr ""
"Δεν ήταν δυνατός ο Ï€ÏοσδιοÏισμός διαδÏομής αποθήκευσης για εικόνες "
"lightmap.\n"
-"ΑποθηκεÏστε τη σκηνή σας (ώστε οι εικόνες να αποθηκευτοÏν στον ίδιο "
-"κατάλογο), ή επιλέξτε μία διαδÏομή αποθήκευσης από τις ιδιότητες του "
-"BakedLightMap."
+"ΑποθηκεÏστε τη σκηνή σας και δοκιμάστε ξανα."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -5257,16 +5264,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -7434,9 +7432,8 @@ msgid "Yaw"
msgstr "ΠαÏέκκλιση"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Size"
-msgstr "Μέγεθος: "
+msgstr "Μέγεθος"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
@@ -10213,7 +10210,7 @@ msgstr "Κουμπί ποντικιοÏ"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"ΆκυÏο όνομα ενέÏγειας. Δεν μποÏεί να είναι άδειο ή να πεÏιέχει «/», «:», "
@@ -10769,9 +10766,8 @@ msgid "Instance Child Scene"
msgstr "ΑÏχικοποίηση σκηνής ως παιδί"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Can't paste root node into the same scene."
-msgstr "Δεν είναι δυνατή η λειτουÏγία σε κόμβους από ξένη σκηνή!"
+msgstr "Δεν είναι δυνατή η επικόλληση του ÏÎ¹Î¶Î¹ÎºÎ¿Ï ÎºÏŒÎ¼Î²Î¿Ï… στην ίδια σκηνή."
#: editor/scene_tree_dock.cpp
#, fuzzy
@@ -12825,9 +12821,8 @@ msgid "Finding meshes and lights"
msgstr ""
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "Ανάλυση γεωμετÏίας..."
+msgstr "ΠÏοετοιμασία γεωμετÏίας (%d/%d)"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
diff --git a/editor/translations/eo.po b/editor/translations/eo.po
index b03935e346..81bc346073 100644
--- a/editor/translations/eo.po
+++ b/editor/translations/eo.po
@@ -16,7 +16,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2021-05-11 06:54+0000\n"
+"PO-Revision-Date: 2021-06-02 09:04+0000\n"
"Last-Translator: mourning20s <mourning20s@protonmail.com>\n"
"Language-Team: Esperanto <https://hosted.weblate.org/projects/godot-engine/"
"godot/eo/>\n"
@@ -196,27 +196,27 @@ msgstr "Aliigi Animadon Iteracion"
#: editor/animation_track_editor.cpp
msgid "Property Track"
-msgstr "Atributo Vojeto"
+msgstr "Atributa trako"
#: editor/animation_track_editor.cpp
msgid "3D Transform Track"
-msgstr "3D Transformo Vojeto"
+msgstr "3D-transforma trako"
#: editor/animation_track_editor.cpp
msgid "Call Method Track"
-msgstr "Alvoki Metodon Vojeto"
+msgstr "Metod-alvoka trako"
#: editor/animation_track_editor.cpp
msgid "Bezier Curve Track"
-msgstr "Bezier-kurbo Vojeto"
+msgstr "Bezier-kurba trako"
#: editor/animation_track_editor.cpp
msgid "Audio Playback Track"
-msgstr "AÅ­dio Reproduktado Vojeto"
+msgstr "AÅ­dia reproduktada trako"
#: editor/animation_track_editor.cpp
msgid "Animation Playback Track"
-msgstr "Animado Reproduktado Vojeto"
+msgstr "Animacia reproduktada trako"
#: editor/animation_track_editor.cpp
msgid "Animation length (frames)"
@@ -228,7 +228,7 @@ msgstr "Animado loneco (sekundoj)"
#: editor/animation_track_editor.cpp
msgid "Add Track"
-msgstr "Adici Vojeton"
+msgstr "Aldoni trakon"
#: editor/animation_track_editor.cpp
msgid "Animation Looping"
@@ -249,11 +249,11 @@ msgstr "Animado Filmitaĵero:"
#: editor/animation_track_editor.cpp
msgid "Change Track Path"
-msgstr "Aliigi Vojeton Vojon"
+msgstr "ÅœanÄi vojon de trako"
#: editor/animation_track_editor.cpp
msgid "Toggle this track on/off."
-msgstr "Baskuligi tio ĉi vojeto Åaltita/malÅaltita."
+msgstr "Åœalti/malÅalti ĉi tiun trakon."
#: editor/animation_track_editor.cpp
msgid "Update Mode (How this property is set)"
@@ -269,7 +269,7 @@ msgstr "Iteracio Volvi Modo (Interpoli finon kun komenco de iteracio)"
#: editor/animation_track_editor.cpp
msgid "Remove this track."
-msgstr "Forigi tio ĉi vojeton."
+msgstr "Forigi ĉi tiun trakon."
#: editor/animation_track_editor.cpp
msgid "Time (s): "
@@ -277,7 +277,7 @@ msgstr "Fojo (s): "
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
-msgstr "Baskuligi Vojeton Åœaltitis"
+msgstr "Åœalti/malÅalti trakon"
#: editor/animation_track_editor.cpp
msgid "Continuous"
@@ -343,15 +343,15 @@ msgstr "Aliigi Animadon Iteracion Modon"
#: editor/animation_track_editor.cpp
msgid "Remove Anim Track"
-msgstr "Formovi Animadon Vojeton"
+msgstr "Forigi animacian trakon"
#: editor/animation_track_editor.cpp
msgid "Create NEW track for %s and insert key?"
-msgstr "Fari NOVAN vojeton por %s kaj enmeti Ålosilon?"
+msgstr "Krei NOVAN trakon por %s kaj enmeti Ålosilon?"
#: editor/animation_track_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
-msgstr "Fari %d NOVAJN vojetojn kaj enmeti Ålosilojn?"
+msgstr "Krei %d NOVAJN trakojn kaj enmeti Ålosilojn?"
#: editor/animation_track_editor.cpp editor/create_dialog.cpp
#: editor/editor_audio_buses.cpp editor/editor_feature_profile.cpp
@@ -379,7 +379,7 @@ msgstr "Animado Krei & Enmeti"
#: editor/animation_track_editor.cpp
msgid "Anim Insert Track & Key"
-msgstr "Animado Enmeti Vojeton & Åœlosilon"
+msgstr "Animacio enmeti trakon kaj Ålosilon"
#: editor/animation_track_editor.cpp
msgid "Anim Insert Key"
@@ -391,11 +391,12 @@ msgstr "Aliigi Animadon PaÅon"
#: editor/animation_track_editor.cpp
msgid "Rearrange Tracks"
-msgstr "RearanÄi Vojetojn"
+msgstr "RearanÄi trakojn"
#: editor/animation_track_editor.cpp
+#, fuzzy
msgid "Transform tracks only apply to Spatial-based nodes."
-msgstr "Transforma vojetoj nur almetas al Spatial nodojn."
+msgstr "Transformaj trakoj nur aplikas al Spatial-ajn nodojn."
#: editor/animation_track_editor.cpp
msgid ""
@@ -404,14 +405,14 @@ msgid ""
"-AudioStreamPlayer2D\n"
"-AudioStreamPlayer3D"
msgstr ""
-"AÅ­dio vojetoj nur volas indiki al nodojn de tipojn:\n"
+"AÅ­diaj trakoj nur eblas indiki al nodoj de tipoj:\n"
"-AudioStreamPlayer\n"
"-AudioStreamPlayer2D\n"
"-AudioStreamPlayer3D"
#: editor/animation_track_editor.cpp
msgid "Animation tracks can only point to AnimationPlayer nodes."
-msgstr "Animado vojetoj nur volas indiki al AnimationPlayer nodojn."
+msgstr "Animaciaj trakoj nur eblas indiki al AnimationPlayer-aj nodoj."
#: editor/animation_track_editor.cpp
msgid "An animation player can't animate itself, only other players."
@@ -419,39 +420,39 @@ msgstr "Animado legilo ne volas animi si mem, nur aliajn ludantojn."
#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
-msgstr "Äœi ne estas ebla adici novan vojeton sen radiko"
+msgstr "Ne eblas aldoni novan trakon sen radiko"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr "Nevalida trako por Bezier (neniu taŭga subproprietaĵoj)"
+msgstr "Nevalida trako por Bezier (neniaj taÅ­gaj atributoj)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
-msgstr "Adici Bezier-vojeton"
+msgstr "Aldoni Bezier-an trakon"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a key."
-msgstr "Vojeto vojo estas malvalida, do ne volas adici Ålosilon."
+msgstr "Vojo de trako estas nevalida, do ne eblas aldoni Ålosilon."
#: editor/animation_track_editor.cpp
msgid "Track is not of type Spatial, can't insert key"
-msgstr "Vojeto ne estas de tipo Spatial, ne volas enmeti Ålosilon"
+msgstr "Trako ne estas de tipo Spatial, ne eblas enmeti Ålosilon"
#: editor/animation_track_editor.cpp
msgid "Add Transform Track Key"
-msgstr "Adici Transformon Vojeton Åœlosilon"
+msgstr "Aldoni transforman trakan Ålosilon"
#: editor/animation_track_editor.cpp
msgid "Add Track Key"
-msgstr "Adici Vojeton Åœlosilon"
+msgstr "Aldoni trakan Ålosilon"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a method key."
-msgstr "Vojeto vojo estas malvalida, do ne volas adici metodon Ålosilon."
+msgstr "Vojo de trako estas nevalida, do ne eblas aldoni metodan Ålosilon."
#: editor/animation_track_editor.cpp
msgid "Add Method Track Key"
-msgstr "Adici Metodon Vojeton Åœlosilon"
+msgstr "Aldoni metodan trakan Ålosilon"
#: editor/animation_track_editor.cpp
msgid "Method not found in object: "
@@ -467,7 +468,7 @@ msgstr "Tondujo estas malplena"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
-msgstr "ElpoÅigi Vojetojn"
+msgstr "Alglui trakojn"
#: editor/animation_track_editor.cpp
msgid "Anim Scale Keys"
@@ -477,7 +478,8 @@ msgstr "Animado Skali Åœlosilojn"
msgid ""
"This option does not work for Bezier editing, as it's only a single track."
msgstr ""
-"Tio ĉi opcio ne funkcias por Bezier redakti, ĉar Äi estas nur unuopa vojeto."
+"Tiu ĉi opcio ne funkcias por Bezier-a redaktado, ĉar Äi estas nur unuopa "
+"trako."
#: editor/animation_track_editor.cpp
msgid ""
@@ -491,14 +493,14 @@ msgid ""
"Alternatively, use an import preset that imports animations to separate "
"files."
msgstr ""
-"Tio ĉi animado apartenas al enporta sceno, do aliigoj al enportajn vojetojn "
+"Tiu ĉi animacio apartenas enportitan scenon, do ÅanÄojn al enportitaj trakoj "
"ne konservos.\n"
"\n"
-"Por Åalti la eblecon aldoni proprajn vojetojn, navigu al la enporto-agordoj "
-"de la sceno kaj agordu \n"
-"\"Animado > Memorilo\" al \"Dosieroj\", Åaltu \"Animado -> Konservi Proprajn "
-"Vojetojn\", poste re-enportu.\n"
-"Alterne, uzu enporto-antaÅ­elekton ke enportas animadojn al malkunajn "
+"Por Åalti la eblecon de aldoni proprajn trakojn, navigu al la enportaj "
+"agordoj de la sceno kaj agordu\n"
+"\"Animacio > Memorilo\" al \"Dosieroj\", Åaltu \"Animacio -> Konservi "
+"proprajn trakojn\", poste reenportu.\n"
+"Alterne, uzu enporta antaÅ­agordo ke enportas animaciojn al malkunajn "
"dosierojn."
#: editor/animation_track_editor.cpp
@@ -507,15 +509,15 @@ msgstr "Averto: Redaktanti importis animadon"
#: editor/animation_track_editor.cpp
msgid "Select an AnimationPlayer node to create and edit animations."
-msgstr "Selektu AnimationPlayer nodo por krei kaj redakti animadoj."
+msgstr "Elektu AnimationPlayer-a nodo por krei kaj redakti animadojn."
#: editor/animation_track_editor.cpp
msgid "Only show tracks from nodes selected in tree."
-msgstr "Nur vidigi vojetojn el elektis nodojn en arbo."
+msgstr "Nur vidigi trakojn el elektitajn nodojn en la arbo."
#: editor/animation_track_editor.cpp
msgid "Group tracks by node or display them as plain list."
-msgstr "Grupigi vojetoj de nodo aÅ­ montri ilin kiel klara listo."
+msgstr "Grupigi trakojn per nodo aÅ­ vidigi ilin kiel simplan liston."
#: editor/animation_track_editor.cpp
msgid "Snap:"
@@ -542,7 +544,7 @@ msgstr "FPS"
#: editor/project_settings_editor.cpp editor/property_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Edit"
-msgstr "Editi"
+msgstr "Redakti"
#: editor/animation_track_editor.cpp
msgid "Animation properties."
@@ -550,7 +552,7 @@ msgstr "Animado atributoj."
#: editor/animation_track_editor.cpp
msgid "Copy Tracks"
-msgstr "Duplikati Vojetojn"
+msgstr "Kopii trakojn"
#: editor/animation_track_editor.cpp
msgid "Scale Selection"
@@ -622,7 +624,7 @@ msgstr "Forigi Nevalidajn Åœlosilojn"
#: editor/animation_track_editor.cpp
msgid "Remove unresolved and empty tracks"
-msgstr "Forigi maladrestrajn kaj malplenajn vojetojn"
+msgstr "Forigi nesolvitajn kaj malplenajn trakojn"
#: editor/animation_track_editor.cpp
msgid "Clean-up all animations"
@@ -642,7 +644,7 @@ msgstr "Skali RejÅo:"
#: editor/animation_track_editor.cpp
msgid "Select Tracks to Copy"
-msgstr "Elekti vojetojn por duplikati"
+msgstr "Elekti trakojn por kopii"
#: editor/animation_track_editor.cpp editor/editor_log.cpp
#: editor/editor_properties.cpp
@@ -651,7 +653,7 @@ msgstr "Elekti vojetojn por duplikati"
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
-msgstr "Duplikati"
+msgstr "Kopii"
#: editor/animation_track_editor.cpp
msgid "Select All/None"
@@ -659,15 +661,15 @@ msgstr "Elekti Ĉiuj/Neniuj"
#: editor/animation_track_editor_plugins.cpp
msgid "Add Audio Track Clip"
-msgstr "Adici Aŭdio-Vojeton Eltondaĵon"
+msgstr "Aldoni aŭdio-trakan eltondaĵon"
#: editor/animation_track_editor_plugins.cpp
msgid "Change Audio Track Clip Start Offset"
-msgstr "Aliigi AÅ­dio-Vojeton Eltondaĵon Komencon DeiÄon"
+msgstr "ÅœanÄi komencan deÅovon de aÅ­dio-traka eltondaĵo"
#: editor/animation_track_editor_plugins.cpp
msgid "Change Audio Track Clip End Offset"
-msgstr "Aliigi AÅ­dio-Vojeton Eltondaĵon Finon DeiÄon"
+msgstr "ÅœanÄi finan deÅovon de aÅ­dio-traka eltondaĵo"
#: editor/array_property_edit.cpp
msgid "Resize Array"
@@ -998,7 +1000,7 @@ msgstr "Rimedo"
#: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp
#: editor/project_manager.cpp editor/project_settings_editor.cpp
msgid "Path"
-msgstr "dosierindiko"
+msgstr "Dosierindiko"
#: editor/dependency_editor.cpp
msgid "Dependencies:"
@@ -1127,7 +1129,7 @@ msgstr "Fondintoj de la Projekto"
#: editor/editor_about.cpp
msgid "Lead Developer"
-msgstr "Ĉefprogramisto"
+msgstr "Ĉefa ellaboranto"
#. TRANSLATORS: This refers to a job title.
#. The trailing space is used to distinguish with the project list application,
@@ -1389,7 +1391,7 @@ msgstr "Eraris konservi dosieron: %s"
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
-msgstr "Aldoni Buso"
+msgstr "Aldoni Buson"
#: editor/editor_audio_buses.cpp
msgid "Add a new Audio Bus to this layout."
@@ -1415,7 +1417,7 @@ msgstr "Konservi ĉi tiun busan aranÄon al dosiero."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
msgid "Load Default"
-msgstr "Åœargi defaÅ­lto"
+msgstr "Åœargi defaÅ­lton"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
@@ -1985,7 +1987,7 @@ msgstr "Priskribo"
#: editor/editor_help.cpp
msgid "Online Tutorials"
-msgstr "Retaj Instruiloj"
+msgstr "Retaj instruiloj"
#: editor/editor_help.cpp
msgid "Properties"
@@ -2005,7 +2007,7 @@ msgstr "Metodoj"
#: editor/editor_help.cpp
msgid "Theme Properties"
-msgstr "Etosaj Atributoj"
+msgstr "Etosaj atributoj"
#: editor/editor_help.cpp
msgid "Enumerations"
@@ -2017,7 +2019,7 @@ msgstr "Konstantoj"
#: editor/editor_help.cpp
msgid "Property Descriptions"
-msgstr "Priskribo de Atributoj"
+msgstr "Priskribo de atributoj"
#: editor/editor_help.cpp
msgid "(value)"
@@ -2033,7 +2035,7 @@ msgstr ""
#: editor/editor_help.cpp
msgid "Method Descriptions"
-msgstr "Metodaj Priskriboj"
+msgstr "Metodaj priskriboj"
#: editor/editor_help.cpp
msgid ""
@@ -2273,6 +2275,8 @@ msgid ""
"This scene can't be saved because there is a cyclic instancing inclusion.\n"
"Please resolve it and then attempt to save again."
msgstr ""
+"Tiun ĉi scenon ne konserveblas ĉar estas enmeto de cikla ekzemplado.\n"
+"Bonvolu solvi Äin kaj poste provu rekonservi."
#: editor/editor_node.cpp
msgid ""
@@ -2283,9 +2287,8 @@ msgstr ""
"verigus."
#: editor/editor_node.cpp editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Can't overwrite scene that is still open!"
-msgstr "Ne eble anstataÅ­igas scenon ke esti ankoraÅ­ malferma!"
+msgstr "Ne eble anstataÅ­igas scenon ke estas ankoraÅ­ malferma!"
#: editor/editor_node.cpp
msgid "Can't load MeshLibrary for merging!"
@@ -2308,6 +2311,8 @@ msgid ""
"An error occurred while trying to save the editor layout.\n"
"Make sure the editor's user data path is writable."
msgstr ""
+"Eraro okazis dum provas konservi la aranÄon de la redaktilon.\n"
+"Verigu la uzantan datumvojon de la redaktilo esti skribebla."
#: editor/editor_node.cpp
msgid ""
@@ -2315,6 +2320,9 @@ msgid ""
"To restore the Default layout to its base settings, use the Delete Layout "
"option and delete the Default layout."
msgstr ""
+"DefaÅ­lta redaktila aranÄo transpasiÄis.\n"
+"Por restaÅ­ri la defaÅ­ltan aranÄon al Äiaj bazaj agordoj, uzu la opcion "
+"\"Forigi aranÄon\" kontraÅ­ la defaÅ­lta aranÄo."
#: editor/editor_node.cpp
msgid "Layout name not found!"
@@ -2322,7 +2330,7 @@ msgstr "Nomon de aranÄo ne trovis!"
#: editor/editor_node.cpp
msgid "Restored the Default layout to its base settings."
-msgstr ""
+msgstr "RestaÅ­ris la defaÅ­ltan aranÄon al Äiaj bazaj agordoj."
#: editor/editor_node.cpp
msgid ""
@@ -2330,18 +2338,25 @@ msgid ""
"Please read the documentation relevant to importing scenes to better "
"understand this workflow."
msgstr ""
+"Tiu ĉi risurco apartenas enportitan scenon, do Äi estas ne redaktebla.\n"
+"Bonvolu legi la dokumentaron rilate enportecon de scenoj por pli bone "
+"komprenu ĉi tiun laborfluon."
#: editor/editor_node.cpp
msgid ""
"This resource belongs to a scene that was instanced or inherited.\n"
"Changes to it won't be kept when saving the current scene."
msgstr ""
+"Tiu ĉi risurco apartenas ekzemplitan aŭ hereditan scenon.\n"
+"ÅœanÄoj al Äi ne teniÄos kiam konservi la aktualan scenon."
#: editor/editor_node.cpp
msgid ""
"This resource was imported, so it's not editable. Change its settings in the "
"import panel and then re-import."
msgstr ""
+"Tiu ĉi risurco enportiÄis, do Äi ne estas redaktebla. ÅœanÄu Äiajn agordojn "
+"en la enporta panelo kaj poste reenportu."
#: editor/editor_node.cpp
msgid ""
@@ -2350,6 +2365,10 @@ msgid ""
"Please read the documentation relevant to importing scenes to better "
"understand this workflow."
msgstr ""
+"Tiu ĉi sceno enportiÄis, do ÅanÄoj al Äi ne teniÄos.\n"
+"Ekzempli Äin aÅ­ heredi permesigos ÅanÄojn al Äi.\n"
+"Bonvolu legi la dokumentaron rilate enportecon de scenoj por pli bone "
+"komprenu ĉi tiun laborfluon."
#: editor/editor_node.cpp
msgid ""
@@ -2357,10 +2376,13 @@ msgid ""
"Please read the documentation relevant to debugging to better understand "
"this workflow."
msgstr ""
+"Tio ĉi estas fora objekto, do ÅanÄoj al Äi ne teniÄos.\n"
+"Bonvolu legi la dokumentaron rilate sencimigon por pli bone komprenu ĉi tiun "
+"laborfluon."
#: editor/editor_node.cpp
msgid "There is no defined scene to run."
-msgstr ""
+msgstr "Estas ne definita sceno por ruli."
#: editor/editor_node.cpp
msgid "Save scene before running..."
@@ -2452,6 +2474,8 @@ msgid ""
"The current scene has unsaved changes.\n"
"Reload the saved scene anyway? This action cannot be undone."
msgstr ""
+"La aktuala sceno havas malkonservitajn ÅanÄojn.\n"
+"ReÅargi la konservitan scenon spite? Tiu ĉi ago ne estas malfarebla."
#: editor/editor_node.cpp
msgid "Quick Run Scene..."
@@ -2479,21 +2503,25 @@ msgstr "Konservi kaj foriri"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "Konservi ÅanÄojn al la jena(j) sceno(j) antaÅ­ foriri?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Konservi ÅanÄojn al la jena(j) sceno(j) antaÅ­ malfermi projektan mastrumilon?"
#: editor/editor_node.cpp
+#, fuzzy
msgid ""
"This option is deprecated. Situations where refresh must be forced are now "
"considered a bug. Please report."
msgstr ""
+"Tiu ĉi opcio estas evitinda. Statoj en kiu aktualigo deviÄi estas nun "
+"konsideri kiel cimo. Bonvolu raporti."
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
-msgstr ""
+msgstr "Elektu ĉefan scenon"
#: editor/editor_node.cpp
msgid "Close Scene"
@@ -2506,36 +2534,47 @@ msgstr "Remalfermi ferman scenon"
#: editor/editor_node.cpp
msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
+"Ne eblas enÅalti kromprogramon ĉe: '%s' analizo de agordaro ne sukcesis."
#: editor/editor_node.cpp
msgid "Unable to find script field for addon plugin at: '%s'."
-msgstr ""
+msgstr "Ne eblas trovi skriptan kampon por kromprogramo ĉe: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
-msgstr ""
+msgstr "Ne eblas Åargi kromprograman skripton el dosierindiko: '%s'."
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
+"Ne eblas Åargi kromprograman skripton el dosierindinko: '%s'. Povas esti pro "
+"koda eraro en tiu skripto.\n"
+"MalÅaltas la kromprogramon ĉe '%s' por malebligi pli erarojn."
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
+"Ne eblas Åargi kromprograman skripton ĉe dosierindiko: '%s'. Baza tipo ne "
+"estas EditorPlugin."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
+"Ne eblas Åargi kromprograman skripton ĉe dosierindiko: '%s'. Skripto ne "
+"estas en ila reÄimo."
#: editor/editor_node.cpp
+#, fuzzy
msgid ""
"Scene '%s' was automatically imported, so it can't be modified.\n"
"To make changes to it, a new inherited scene can be created."
msgstr ""
+"Sceno '%s' aÅ­tomate enportiÄis, do ne eblas redakti Äin.\n"
+"Por ÅanÄu Äin, nova heredita sceno povas kreiÄi."
#: editor/editor_node.cpp
msgid ""
@@ -2545,11 +2584,11 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
-msgstr ""
+msgstr "Sceno '%s' havas rompitajn dependojn:"
#: editor/editor_node.cpp
msgid "Clear Recent Scenes"
-msgstr ""
+msgstr "Vakigi lastajn scenojn"
#: editor/editor_node.cpp
msgid ""
@@ -2557,6 +2596,8 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"Ne ĉefa sceno definiÄis iam, elekti unu?\n"
+"Vi povas ÅanÄi Äin poste en \"Projektaj agordoj\" en la 'apliko' kategorio."
#: editor/editor_node.cpp
msgid ""
@@ -2564,6 +2605,8 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"Elektita sceno '%s' ekzisitas, elekti validan unuon?\n"
+"Vi povas ÅanÄi Äin poste en \"Projektaj agordoj\" en la 'apliko' kategorio."
#: editor/editor_node.cpp
msgid ""
@@ -2571,14 +2614,16 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"Elektita sceno '%s' ne estas scena dosiero, elekti validan unuon?\n"
+"Vi povas ÅanÄi Äin poste en \"Projektaj agordoj\" en la 'apliko' kategorio."
#: editor/editor_node.cpp
msgid "Save Layout"
-msgstr ""
+msgstr "Konservi aranÄon"
#: editor/editor_node.cpp
msgid "Delete Layout"
-msgstr ""
+msgstr "Forigi aranÄon"
#: editor/editor_node.cpp editor/import_dock.cpp
#: editor/script_create_dialog.cpp
@@ -2592,7 +2637,7 @@ msgstr "Montri en dosiersistemo"
#: editor/editor_node.cpp
msgid "Play This Scene"
-msgstr "Starti ĉi tiu scenon"
+msgstr "Ludi ĉi tiun scenon"
#: editor/editor_node.cpp
msgid "Close Tab"
@@ -2652,7 +2697,7 @@ msgstr "Sceno"
#: editor/editor_node.cpp
msgid "Go to previously opened scene."
-msgstr ""
+msgstr "Iri al antaÅ­e malfermitan scenon."
#: editor/editor_node.cpp
msgid "Copy Text"
@@ -2732,7 +2777,7 @@ msgstr "Projekto"
#: editor/editor_node.cpp
msgid "Project Settings..."
-msgstr "Projekta agordoj..."
+msgstr "Projektaj agordoj..."
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
#, fuzzy
@@ -2877,11 +2922,11 @@ msgstr "Redaktilo"
#: editor/editor_node.cpp
msgid "Editor Settings..."
-msgstr "Editila agordoj..."
+msgstr "Agordoj de la redaktilo..."
#: editor/editor_node.cpp
msgid "Editor Layout"
-msgstr "AranÄon de editilo"
+msgstr "AranÄo de la redaktilo"
#: editor/editor_node.cpp
msgid "Take Screenshot"
@@ -2890,6 +2935,8 @@ msgstr "Ekranfoti"
#: editor/editor_node.cpp
msgid "Screenshots are stored in the Editor Data/Settings Folder."
msgstr ""
+"Ekrankopioj estas konservintaj en la datumaj/agordaj dosierujo de la "
+"redaktilo."
#: editor/editor_node.cpp
msgid "Toggle Fullscreen"
@@ -2901,19 +2948,19 @@ msgstr "Baskuli la konzolon de sistemo"
#: editor/editor_node.cpp
msgid "Open Editor Data/Settings Folder"
-msgstr "Malfermi dosierujon de editilan datumoj/agordoj"
+msgstr "Malfermi datumajn/agordajn dosierujon de la redaktilo"
#: editor/editor_node.cpp
msgid "Open Editor Data Folder"
-msgstr "Malfermi dosierujon de editila datumoj"
+msgstr "Malfermi datumajn dosierujon de la redaktilo"
#: editor/editor_node.cpp
msgid "Open Editor Settings Folder"
-msgstr "Malfermi dosierujon de editila agordoj"
+msgstr "Malfermi agordajn dosierujon de la redaktilo"
#: editor/editor_node.cpp
msgid "Manage Editor Features..."
-msgstr "Mastrumi editilan eblecoj..."
+msgstr "Mastrumi eblecojn de la redaktilo..."
#: editor/editor_node.cpp
msgid "Manage Export Templates..."
@@ -2925,9 +2972,8 @@ msgstr "Helpo"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
-#, fuzzy
msgid "Online Docs"
-msgstr "Enreta dokoj"
+msgstr "Enreta dokumentaro"
#: editor/editor_node.cpp
msgid "Q&A"
@@ -2950,12 +2996,16 @@ msgid "About"
msgstr "Pri"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Subteni Godot ellaboradon"
+
+#: editor/editor_node.cpp
msgid "Play the project."
-msgstr "Stari la projekton."
+msgstr "Ludi la projekton."
#: editor/editor_node.cpp
msgid "Play"
-msgstr "Starti"
+msgstr "Ludi"
#: editor/editor_node.cpp
msgid "Pause the scene execution for debugging."
@@ -2971,19 +3021,19 @@ msgstr "Halti la scenon."
#: editor/editor_node.cpp
msgid "Play the edited scene."
-msgstr "Starti la redaktantan scenon."
+msgstr "Ludi la redaktantan scenon."
#: editor/editor_node.cpp
msgid "Play Scene"
-msgstr "Starti scenon"
+msgstr "Ludi scenon"
#: editor/editor_node.cpp
msgid "Play custom scene"
-msgstr "Starti propran scenon"
+msgstr "Ludi laÅ­mendan scenon"
#: editor/editor_node.cpp
msgid "Play Custom Scene"
-msgstr "Starti propran scenon"
+msgstr "Ludi laÅ­mendan scenon"
#: editor/editor_node.cpp
#, fuzzy
@@ -3022,7 +3072,7 @@ msgstr "Inspektoro"
#: editor/editor_node.cpp
msgid "Expand Bottom Panel"
-msgstr ""
+msgstr "Etendi suban panelon"
#: editor/editor_node.cpp
msgid "Output"
@@ -3061,7 +3111,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
-msgstr ""
+msgstr "Enporti Åablonojn el ZIP-a dosiero"
#: editor/editor_node.cpp
#, fuzzy
@@ -3070,11 +3120,11 @@ msgstr "Åœablonoj"
#: editor/editor_node.cpp
msgid "Export Library"
-msgstr ""
+msgstr "Eksporti bibliotekon"
#: editor/editor_node.cpp
msgid "Merge With Existing"
-msgstr ""
+msgstr "Kunfandi kun ekzistanta"
#: editor/editor_node.cpp
msgid "Open & Run a Script"
@@ -3085,24 +3135,26 @@ msgid ""
"The following files are newer on disk.\n"
"What action should be taken?"
msgstr ""
+"La jenaj dosieroj estas pli novaj sur disko.\n"
+"Kian agon fari?"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Reload"
-msgstr ""
+msgstr "ReÅargi"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Resave"
-msgstr ""
+msgstr "Rekonservi"
#: editor/editor_node.cpp
msgid "New Inherited"
-msgstr ""
+msgstr "Nova heredita"
#: editor/editor_node.cpp
msgid "Load Errors"
-msgstr ""
+msgstr "Åœargaj eraroj"
#: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Select"
@@ -3155,11 +3207,11 @@ msgstr "Konektu al skripto:"
#: editor/editor_plugin_settings.cpp
msgid "Edit Plugin"
-msgstr ""
+msgstr "Redakti kromprogramon"
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
-msgstr ""
+msgstr "Instalitaj kromprogramoj:"
#: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp
msgid "Update"
@@ -3180,7 +3232,7 @@ msgstr "Stato:"
#: editor/editor_plugin_settings.cpp
msgid "Edit:"
-msgstr ""
+msgstr "Redakti:"
#: editor/editor_profiler.cpp
msgid "Measure:"
@@ -3224,27 +3276,27 @@ msgstr "Alvokoj"
#: editor/editor_properties.cpp
msgid "Edit Text:"
-msgstr ""
+msgstr "Redakti tekston:"
#: editor/editor_properties.cpp editor/script_create_dialog.cpp
msgid "On"
-msgstr ""
+msgstr "Åœaltita"
#: editor/editor_properties.cpp
msgid "Layer"
-msgstr ""
+msgstr "Tavolo"
#: editor/editor_properties.cpp
msgid "Bit %d, value %d"
-msgstr ""
+msgstr "Bito %d, valoro %d"
#: editor/editor_properties.cpp
msgid "[Empty]"
-msgstr ""
+msgstr "[Malplena]"
#: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp
msgid "Assign..."
-msgstr ""
+msgstr "Asigni..."
#: editor/editor_properties.cpp
msgid "Invalid RID"
@@ -3255,12 +3307,16 @@ msgid ""
"The selected resource (%s) does not match any type expected for this "
"property (%s)."
msgstr ""
+"La elektinta risurco (%s) ne kongruas ian atenditan tipon por ĉi tiu "
+"atributo (%s)."
#: editor/editor_properties.cpp
msgid ""
"Can't create a ViewportTexture on resources saved as a file.\n"
"Resource needs to belong to a scene."
msgstr ""
+"Ne eblas krei ViewportTexture por risurcoj konservite kiel dosiero.\n"
+"Risurco devas aparteni scenon."
#: editor/editor_properties.cpp
msgid ""
@@ -3269,10 +3325,14 @@ msgid ""
"Please switch on the 'local to scene' property on it (and all resources "
"containing it up to a node)."
msgstr ""
+"Ne eblas krei ViewportTexture por tiu risurco ĉar Äi ne agordas esti loke al "
+"sceno.\n"
+"Bonvolu Åalti la 'loke al sceno' atributon por Äi (kaj ĉiaj risurcoj kiu "
+"enhavas Äin, rekursie al nodo)."
#: editor/editor_properties.cpp editor/property_editor.cpp
msgid "Pick a Viewport"
-msgstr ""
+msgstr "Elekti Viewport"
#: editor/editor_properties.cpp editor/property_editor.cpp
msgid "New Script"
@@ -3310,7 +3370,7 @@ msgstr "Konverti al %s"
#: editor/editor_properties.cpp editor/property_editor.cpp
msgid "Selected node is not a Viewport!"
-msgstr ""
+msgstr "Elektinta nodo ne estas Viewport!"
#: editor/editor_properties_array_dict.cpp
msgid "Size: "
@@ -3343,6 +3403,9 @@ msgid ""
"Please add a runnable preset in the Export menu or define an existing preset "
"as runnable."
msgstr ""
+"Ne rulebla eksporta antaÅ­agordo troviÄis por ĉi tiu platformo.\n"
+"Bonvolu aldoni ruleblan antaÅ­agordon per la Eksporto menuo aÅ­ defini "
+"ekzistantan antaÅ­agordon kiel rulebla."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -3350,15 +3413,15 @@ msgstr "Skribu vian logikon en la _run() metodo."
#: editor/editor_run_script.cpp
msgid "There is an edited scene already."
-msgstr ""
+msgstr "Estas redaktanta sceno jam."
#: editor/editor_run_script.cpp
msgid "Couldn't instance script:"
-msgstr ""
+msgstr "Ne eblis ekzempli skripton:"
#: editor/editor_run_script.cpp
msgid "Did you forget the 'tool' keyword?"
-msgstr ""
+msgstr "Ĉu vi forgesis la Ålosilvorton 'tool'?"
#: editor/editor_run_script.cpp
msgid "Couldn't run script:"
@@ -3371,6 +3434,8 @@ msgstr "Ĉu vi forgesis la '_run' metodo?"
#: editor/editor_spin_slider.cpp
msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes."
msgstr ""
+"Premteni stirklavon por rondigi al entjeroj. Premteni majuskligan klavon por "
+"pli precizaj ÅanÄoj."
#: editor/editor_sub_scene.cpp
#, fuzzy
@@ -3383,7 +3448,7 @@ msgstr "Foliumi"
#: editor/editor_sub_scene.cpp
msgid "Scene Path:"
-msgstr ""
+msgstr "Scena dosierindiko:"
#: editor/editor_sub_scene.cpp
msgid "Import From Node:"
@@ -3420,182 +3485,188 @@ msgstr "(Aktuala)"
#: editor/export_template_manager.cpp
msgid "Retrieving mirrors, please wait..."
-msgstr ""
+msgstr "Ricevas spegulojn, bonvolu atendi..."
#: editor/export_template_manager.cpp
msgid "Remove template version '%s'?"
-msgstr ""
+msgstr "Forigi la version '%s' de Åablono?"
#: editor/export_template_manager.cpp
msgid "Can't open export templates zip."
-msgstr ""
+msgstr "Ne eblas malfermi ZIP de eksportaj Åablonoj."
#: editor/export_template_manager.cpp
msgid "Invalid version.txt format inside templates: %s."
-msgstr ""
+msgstr "Nevalida formo de version.txt en Åablonoj: %s."
#: editor/export_template_manager.cpp
msgid "No version.txt found inside templates."
-msgstr ""
+msgstr "Ne version.txt troviÄis en Åablonoj."
#: editor/export_template_manager.cpp
msgid "Error creating path for templates:"
-msgstr ""
+msgstr "Eraro dum kreo de dosierindiko por Åablonoj:"
#: editor/export_template_manager.cpp
msgid "Extracting Export Templates"
-msgstr ""
+msgstr "Ekstraktas eksportajn Åablonojn"
#: editor/export_template_manager.cpp
msgid "Importing:"
-msgstr ""
+msgstr "Enportas:"
#: editor/export_template_manager.cpp
msgid "Error getting the list of mirrors."
-msgstr ""
+msgstr "Eraro dum ricevo de la listo de speguloj."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Eraro dum analizo de la JSON de la spegula listo. Bonvolu raporti tiun "
+"problemon!"
#: editor/export_template_manager.cpp
msgid ""
"No download links found for this version. Direct download is only available "
"for official releases."
msgstr ""
+"Ne elÅutaj ligiloj troviÄis por ĉi tiu versio. Direkta elÅuto estas nur "
+"disponebla por oficaj eldonoj."
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Can't resolve."
-msgstr ""
+msgstr "Ne eblas adrestrovi."
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Can't connect."
-msgstr ""
+msgstr "Ne eblas konekti."
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "No response."
-msgstr ""
+msgstr "Ne respondo."
#: editor/export_template_manager.cpp
msgid "Request Failed."
-msgstr ""
+msgstr "Demando eraris."
#: editor/export_template_manager.cpp
msgid "Redirect Loop."
-msgstr ""
+msgstr "Alidirekta iteracio."
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed:"
-msgstr ""
+msgstr "Eraris:"
#: editor/export_template_manager.cpp
msgid "Download Complete."
-msgstr ""
+msgstr "ElÅuto kompleta."
#: editor/export_template_manager.cpp
msgid "Cannot remove temporary file:"
-msgstr ""
+msgstr "Ne eblas forigi provizoran dosieron:"
#: editor/export_template_manager.cpp
msgid ""
"Templates installation failed.\n"
"The problematic templates archives can be found at '%s'."
msgstr ""
+"Instalado de Åablonoj eraris.\n"
+"La arkivoj de problemaj Åablonoj eble troviÄas ĉe '%s'."
#: editor/export_template_manager.cpp
msgid "Error requesting URL:"
-msgstr ""
+msgstr "Eraro dum demandi la URL:"
#: editor/export_template_manager.cpp
msgid "Connecting to Mirror..."
-msgstr ""
+msgstr "Konektas al spegulo..."
#: editor/export_template_manager.cpp
msgid "Disconnected"
-msgstr ""
+msgstr "Malkonektis"
#: editor/export_template_manager.cpp
msgid "Resolving"
-msgstr ""
+msgstr "Adrestrovas"
#: editor/export_template_manager.cpp
msgid "Can't Resolve"
-msgstr ""
+msgstr "Ne eblas adrestrovi"
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Connecting..."
-msgstr ""
+msgstr "Konektas..."
#: editor/export_template_manager.cpp
msgid "Can't Connect"
-msgstr ""
+msgstr "Ne eblas konekti"
#: editor/export_template_manager.cpp
msgid "Connected"
-msgstr ""
+msgstr "Konektis"
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Requesting..."
-msgstr ""
+msgstr "Demandas..."
#: editor/export_template_manager.cpp
msgid "Downloading"
-msgstr ""
+msgstr "ElÅutas"
#: editor/export_template_manager.cpp
msgid "Connection Error"
-msgstr ""
+msgstr "Konekta eraro"
#: editor/export_template_manager.cpp
msgid "SSL Handshake Error"
-msgstr ""
+msgstr "SSL-kvitanca eraro"
#: editor/export_template_manager.cpp
msgid "Uncompressing Android Build Sources"
-msgstr ""
+msgstr "Malkompaktigas kompilajn fontkodojn por Android"
#: editor/export_template_manager.cpp
msgid "Current Version:"
-msgstr ""
+msgstr "Aktuala versio:"
#: editor/export_template_manager.cpp
msgid "Installed Versions:"
-msgstr ""
+msgstr "Instalintaj versioj:"
#: editor/export_template_manager.cpp
msgid "Install From File"
-msgstr ""
+msgstr "Instali el dosiero"
#: editor/export_template_manager.cpp
msgid "Remove Template"
-msgstr ""
+msgstr "Forigi Åablonon"
#: editor/export_template_manager.cpp
msgid "Select Template File"
-msgstr ""
+msgstr "Elekti Åablonan dosieron"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Godot Export Templates"
-msgstr "Mastrumi eksportaj Åablonoj"
+msgstr "Eksportajn Åablonojn de Godot"
#: editor/export_template_manager.cpp
msgid "Export Template Manager"
-msgstr ""
+msgstr "Mastrumilo de eksportaj Åablonoj"
#: editor/export_template_manager.cpp
msgid "Download Templates"
-msgstr ""
+msgstr "ElÅutilo de Åablonoj"
#: editor/export_template_manager.cpp
msgid "Select mirror from list: (Shift+Click: Open in Browser)"
msgstr ""
+"Elekti spegulon el listo: (Majuskliga klavo+Alklako: Malfermi en retumilon)"
#: editor/filesystem_dock.cpp
msgid "Favorites"
@@ -3604,31 +3675,36 @@ msgstr "Favoritaj"
#: editor/filesystem_dock.cpp
msgid "Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
+"Stato: Enporto de dosiero eraris. Bonvolu ripari dosieron kaj reenporti "
+"permane."
#: editor/filesystem_dock.cpp
msgid ""
"Importing has been disabled for this file, so it can't be opened for editing."
msgstr ""
+"Enportadon malÅaltis por ĉi tiu dosiero, do Äin ne eblas malfermi por "
+"redakto."
#: editor/filesystem_dock.cpp
msgid "Cannot move/rename resources root."
-msgstr ""
+msgstr "Ne eblas movi/renomi risurcan radikon."
#: editor/filesystem_dock.cpp
+#, fuzzy
msgid "Cannot move a folder into itself."
-msgstr ""
+msgstr "Ne eblas movi dosierujon en sin mem."
#: editor/filesystem_dock.cpp
msgid "Error moving:"
-msgstr ""
+msgstr "Eraro dum movado de:"
#: editor/filesystem_dock.cpp
msgid "Error duplicating:"
-msgstr ""
+msgstr "Eraro dum duplikati:"
#: editor/filesystem_dock.cpp
msgid "Unable to update dependencies:"
-msgstr ""
+msgstr "Ne eblas Äisdatigi dependojn:"
#: editor/filesystem_dock.cpp editor/scene_tree_editor.cpp
msgid "No name provided."
@@ -3655,31 +3731,36 @@ msgid ""
"\n"
"Do you wish to overwrite them?"
msgstr ""
+"La jenaj dosieroj aÅ­ dosierujoj konfliktas kun elementoj en la cela loko "
+"'%s':\n"
+"\n"
+"%s\n"
+"\n"
+"Ĉu vi volas anstataŭigi ilin?"
#: editor/filesystem_dock.cpp
msgid "Renaming file:"
-msgstr ""
+msgstr "Renomas dosieron:"
#: editor/filesystem_dock.cpp
msgid "Renaming folder:"
-msgstr ""
+msgstr "Renomas dosierujon:"
#: editor/filesystem_dock.cpp
msgid "Duplicating file:"
-msgstr ""
+msgstr "Duplikatas dosieron:"
#: editor/filesystem_dock.cpp
msgid "Duplicating folder:"
-msgstr ""
+msgstr "Duplikatas dosierujon:"
#: editor/filesystem_dock.cpp
msgid "New Inherited Scene"
msgstr "Nova heredita sceno"
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Set As Main Scene"
-msgstr "Konservi ĉiujn scenojn"
+msgstr "Defini kiel ĉefan scenon"
#: editor/filesystem_dock.cpp
msgid "Open Scenes"
@@ -3724,12 +3805,12 @@ msgstr "Nova risurco..."
#: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp
#: editor/script_editor_debugger.cpp
msgid "Expand All"
-msgstr ""
+msgstr "Etendi tuton"
#: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp
#: editor/script_editor_debugger.cpp
msgid "Collapse All"
-msgstr ""
+msgstr "Maletendi tuton"
#: editor/filesystem_dock.cpp
msgid "Duplicate..."
@@ -3768,6 +3849,8 @@ msgid ""
"Scanning Files,\n"
"Please Wait..."
msgstr ""
+"Skanas dosierojn,\n"
+"Bonvolu atendi..."
#: editor/filesystem_dock.cpp
msgid "Move"
@@ -3846,19 +3929,16 @@ msgid "Searching..."
msgstr "Serĉas..."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d match in %d file."
-msgstr "Trovis %d matĉo(j)n."
+msgstr "%d rekono en %d dosiero."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d file."
-msgstr "Trovis %d matĉo(j)n."
+msgstr "%d rekonoj en %d dosiero."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d files."
-msgstr "Trovis %d matĉo(j)n."
+msgstr "%d rekonoj en %d dosieroj."
#: editor/groups_editor.cpp
msgid "Add to Group"
@@ -3889,7 +3969,6 @@ msgid "Groups"
msgstr "Grupoj"
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Nodes Not in Group"
msgstr "Nodoj ne en grupo"
@@ -3911,9 +3990,8 @@ msgid "Group Editor"
msgstr "Grupredaktilo"
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Manage Groups"
-msgstr "Administri grupojn"
+msgstr "Agordi grupojn"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Single Scene"
@@ -3982,15 +4060,15 @@ msgstr "Ne elbe Åargis la post-enportan skripton:"
#: editor/import/resource_importer_scene.cpp
msgid "Invalid/broken script for post-import (check console):"
-msgstr ""
+msgstr "Nevalida/rompita skripto por post-enporto (ekzamenu konzolon):"
#: editor/import/resource_importer_scene.cpp
msgid "Error running post-import script:"
-msgstr ""
+msgstr "Eraro dum ruli post-enportan skripton:"
#: editor/import/resource_importer_scene.cpp
msgid "Did you return a Node-derived object in the `post_import()` method?"
-msgstr ""
+msgstr "Ĉu vi revenis Nodo-devenitan objekton en la metodo `post_import()`?"
#: editor/import/resource_importer_scene.cpp
msgid "Saving..."
@@ -4006,11 +4084,11 @@ msgstr "Enportilo:"
#: editor/import_defaults_editor.cpp
msgid "Reset to Defaults"
-msgstr ""
+msgstr "Rekomencigi al defaÅ­ltoj"
#: editor/import_dock.cpp
msgid "Keep File (No Import)"
-msgstr ""
+msgstr "Konservi dosieron (ne enporto)"
#: editor/import_dock.cpp
#, fuzzy
@@ -4019,11 +4097,11 @@ msgstr "Trovi en dosierojn"
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "Agordi kiel defaÅ­lton por '%s'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "Vakigi defaÅ­lton por '%s'"
#: editor/import_dock.cpp
msgid "Import As:"
@@ -4031,19 +4109,20 @@ msgstr "Enporti kiel:"
#: editor/import_dock.cpp
msgid "Preset"
-msgstr ""
+msgstr "AntaÅ­agordo"
#: editor/import_dock.cpp
msgid "Reimport"
-msgstr ""
+msgstr "Reenporti"
#: editor/import_dock.cpp
msgid "Save Scenes, Re-Import, and Restart"
-msgstr ""
+msgstr "Konservi scenojn, reenporti, kaj rekomenci"
#: editor/import_dock.cpp
msgid "Changing the type of an imported file requires editor restart."
msgstr ""
+"ÅœanÄado de la tipo de enportita dosiero postulas redaktilan rekomencon."
#: editor/import_dock.cpp
#, fuzzy
@@ -4054,15 +4133,15 @@ msgstr ""
#: editor/inspector_dock.cpp
msgid "Failed to load resource."
-msgstr ""
+msgstr "Ne eblas Åargi risurcon."
#: editor/inspector_dock.cpp
msgid "Expand All Properties"
-msgstr ""
+msgstr "Etendi ĉiajn atributojn"
#: editor/inspector_dock.cpp
msgid "Collapse All Properties"
-msgstr ""
+msgstr "Maletendi ĉiajn atributojn"
#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -4071,23 +4150,23 @@ msgstr "Konservi kiel..."
#: editor/inspector_dock.cpp
msgid "Copy Params"
-msgstr ""
+msgstr "Kopii parametrojn"
#: editor/inspector_dock.cpp
msgid "Edit Resource Clipboard"
-msgstr ""
+msgstr "Redakti risurcan tondujon"
#: editor/inspector_dock.cpp
msgid "Copy Resource"
-msgstr ""
+msgstr "Kopii risurcon"
#: editor/inspector_dock.cpp
msgid "Make Built-In"
-msgstr ""
+msgstr "Enkonstruigi"
#: editor/inspector_dock.cpp
msgid "Make Sub-Resources Unique"
-msgstr ""
+msgstr "Subrisurcojn unikigi"
#: editor/inspector_dock.cpp
msgid "Open in Help"
@@ -4095,39 +4174,39 @@ msgstr "Malfermi en helpo"
#: editor/inspector_dock.cpp
msgid "Create a new resource in memory and edit it."
-msgstr ""
+msgstr "Krei novan risurcon en memoro kaj redakti Äin."
#: editor/inspector_dock.cpp
msgid "Load an existing resource from disk and edit it."
-msgstr ""
+msgstr "Åœargi ekzistantan risurcon el disko kaj redakti Äin."
#: editor/inspector_dock.cpp
msgid "Save the currently edited resource."
-msgstr ""
+msgstr "Konservi la aktuale redaktantan risurcon."
#: editor/inspector_dock.cpp
msgid "Go to the previous edited object in history."
-msgstr ""
+msgstr "Iri al la antaÅ­e redaktinta objekto en historio."
#: editor/inspector_dock.cpp
msgid "Go to the next edited object in history."
-msgstr ""
+msgstr "Iri al la poste redaktinta objekto en historio."
#: editor/inspector_dock.cpp
msgid "History of recently edited objects."
-msgstr ""
+msgstr "Historio de lastatempe redaktintaj objektoj."
#: editor/inspector_dock.cpp
msgid "Object properties."
-msgstr ""
+msgstr "Atributoj de la objekto."
#: editor/inspector_dock.cpp
msgid "Filter properties"
-msgstr ""
+msgstr "Filtri atributojn"
#: editor/inspector_dock.cpp
msgid "Changes may be lost!"
-msgstr ""
+msgstr "ÅœanÄoj eble perdiÄos!"
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
@@ -4135,46 +4214,46 @@ msgstr ""
#: editor/node_dock.cpp
msgid "Select a single node to edit its signals and groups."
-msgstr ""
+msgstr "Elektu unu nodon por redakti Äiajn signalojn kaj grupojn."
#: editor/plugin_config_dialog.cpp
msgid "Edit a Plugin"
-msgstr ""
+msgstr "Redakti kromprogramon"
#: editor/plugin_config_dialog.cpp
msgid "Create a Plugin"
-msgstr ""
+msgstr "Krei kromprogramon"
#: editor/plugin_config_dialog.cpp
msgid "Plugin Name:"
-msgstr ""
+msgstr "Nomo de kromprogramon:"
#: editor/plugin_config_dialog.cpp
msgid "Subfolder:"
-msgstr ""
+msgstr "Subdosierujo:"
#: editor/plugin_config_dialog.cpp editor/script_create_dialog.cpp
msgid "Language:"
-msgstr ""
+msgstr "Lingvo:"
#: editor/plugin_config_dialog.cpp
msgid "Script Name:"
-msgstr ""
+msgstr "Nomo de skripto:"
#: editor/plugin_config_dialog.cpp
msgid "Activate now?"
-msgstr ""
+msgstr "Aktivigi nun?"
#: editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create Polygon"
-msgstr ""
+msgstr "Krei plurlateron"
#: editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Create points."
-msgstr ""
+msgstr "Krei punktojn."
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
@@ -4182,27 +4261,30 @@ msgid ""
"LMB: Move Point\n"
"RMB: Erase Point"
msgstr ""
+"Redakti punktojn.\n"
+"Maldekstra musbutono: Movi punkton\n"
+"Dekstra musbutono: Forigi punkton"
#: editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Erase points."
-msgstr ""
+msgstr "Forigi punktojn."
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid "Edit Polygon"
-msgstr ""
+msgstr "Redakti plurlateron"
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid "Insert Point"
-msgstr ""
+msgstr "Enmeti punkton"
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid "Edit Polygon (Remove Point)"
-msgstr ""
+msgstr "Redakti plurlateron (forigi punkton)"
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid "Remove Polygon And Point"
-msgstr ""
+msgstr "Forigi plurlateron kaj punkton"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
@@ -4210,51 +4292,52 @@ msgstr ""
#: editor/plugins/animation_state_machine_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Add Animation"
-msgstr ""
+msgstr "Aldoni animacion"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Load..."
-msgstr ""
+msgstr "Åœargi..."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Move Node Point"
-msgstr ""
+msgstr "Movi punkton de nodo"
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Change BlendSpace1D Limits"
-msgstr ""
+msgstr "ÅœanÄi limojn de BlendSpace1D"
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Change BlendSpace1D Labels"
-msgstr ""
+msgstr "ÅœanÄi etikedojn de BlendSpace1D"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
#: editor/plugins/animation_state_machine_editor.cpp
msgid "This type of node can't be used. Only root nodes are allowed."
msgstr ""
+"Tiun ĉi tipon de nodo ne eblas uzi. Nur radikaj nodoj estas permesitaj."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Add Node Point"
-msgstr ""
+msgstr "Aldoni punkton de nodo"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Add Animation Point"
-msgstr ""
+msgstr "Aldoni punkton de animacio"
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Remove BlendSpace1D Point"
-msgstr ""
+msgstr "Forigi punkton de BlendSpace1D"
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Move BlendSpace1D Node Point"
-msgstr ""
+msgstr "Movi punkton de BlendSpace1D"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
@@ -4264,26 +4347,29 @@ msgid ""
"AnimationTree is inactive.\n"
"Activate to enable playback, check node warnings if activation fails."
msgstr ""
+"AnimationTree estas neaktiva.\n"
+"Aktivigu por Åalti reproduktado, ekzamenu avertojn de nodo se aktivigo "
+"erarus."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Set the blending position within the space"
-msgstr ""
+msgstr "Difini la miksan pozicion en la spaco"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Select and move points, create points with RMB."
-msgstr ""
+msgstr "Elekti kaj movi punktojn, krei punktojn per dekstra musbutono."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp scene/gui/graph_edit.cpp
msgid "Enable snap and show grid."
-msgstr ""
+msgstr "Åœalti kradokapton kaj vidi kradon."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Point"
-msgstr ""
+msgstr "Punkto"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
@@ -4296,125 +4382,126 @@ msgstr "Malfermi la redaktilon"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Open Animation Node"
-msgstr ""
+msgstr "Malfermi animacian nodon"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Triangle already exists."
-msgstr ""
+msgstr "Triangulo jam ekzistas."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Add Triangle"
-msgstr ""
+msgstr "Aldoni triangulon"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Change BlendSpace2D Limits"
-msgstr ""
+msgstr "ÅœanÄi limojn de BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Change BlendSpace2D Labels"
-msgstr ""
+msgstr "ÅœanÄi etikedojn de BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Remove BlendSpace2D Point"
-msgstr ""
+msgstr "Forigi punktojn de BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Remove BlendSpace2D Triangle"
-msgstr ""
+msgstr "Forigi triangulojn de BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "BlendSpace2D does not belong to an AnimationTree node."
-msgstr ""
+msgstr "BlendSpace2D ne apartenas AnimationTree-an nodon."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "No triangles exist, so no blending can take place."
-msgstr ""
+msgstr "Ne trianguloj ekzistas, do miksado ne eblas."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Toggle Auto Triangles"
-msgstr ""
+msgstr "Baskuli aÅ­tomatajn triangulojn"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Create triangles by connecting points."
-msgstr ""
+msgstr "Krei triangulojn per konekti punktojn."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Erase points and triangles."
-msgstr ""
+msgstr "Forigi punktojn kaj triangulojn."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Generate blend triangles automatically (instead of manually)"
-msgstr ""
+msgstr "Generi miksajn triangulojn aÅ­tomate (anstataÅ­ permane)"
#: editor/plugins/animation_blend_space_2d_editor.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "Blend:"
-msgstr ""
+msgstr "Mikso:"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Parameter Changed"
-msgstr ""
+msgstr "Parametro ÅanÄiÄis"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "Edit Filters"
-msgstr ""
+msgstr "Redakti filtrojn"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Output node can't be added to the blend tree."
-msgstr ""
+msgstr "Ne eblas aldoni eligan nodon al la miksan arbon."
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Add Node to BlendTree"
-msgstr ""
+msgstr "Aldoni nodon al BlendTree"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Node Moved"
-msgstr ""
+msgstr "Nodo moviÄis"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Unable to connect, port may be in use or connection may be invalid."
msgstr ""
+"Ne eblas konekti, pordo povas esti en uzo aÅ­ konekto povas esti nevalida."
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Nodes Connected"
-msgstr ""
+msgstr "Nodoj konektiÄis"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Nodes Disconnected"
-msgstr ""
+msgstr "Nodoj malkonektiÄis"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Set Animation"
-msgstr ""
+msgstr "Difini animacion"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Delete Node"
-msgstr ""
+msgstr "Forigi nodon"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Delete Node(s)"
-msgstr ""
+msgstr "Forigi nodo(j)n"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Toggle Filter On/Off"
-msgstr ""
+msgstr "Åœalti/malÅalti filtron"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Change Filter"
-msgstr ""
+msgstr "ÅœanÄi filtron"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "No animation player set, so unable to retrieve track names."
-msgstr ""
+msgstr "Ne animacian ludilon difinas, do ne eblas ricevi nomojn de trakoj."
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Player path set is invalid, so unable to retrieve track names."
-msgstr ""
+msgstr "Vojaro de ludilo estas nevalida, do ne eblas ricevi nomojn de trakoj."
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/root_motion_editor_plugin.cpp
@@ -4422,6 +4509,8 @@ msgid ""
"Animation player has no valid root node path, so unable to retrieve track "
"names."
msgstr ""
+"Animacia ludilo ne havas valida radika nodo-vojo, do ne eblas ricevi nomojn "
+"de trakoj."
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#, fuzzy
@@ -4441,55 +4530,56 @@ msgstr "Funkcioj:"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Node Renamed"
-msgstr ""
+msgstr "Nodo renomiÄis"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Add Node..."
-msgstr ""
+msgstr "Aldoni nodon..."
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/root_motion_editor_plugin.cpp
msgid "Edit Filtered Tracks:"
-msgstr ""
+msgstr "Redakti filtritajn trakojn:"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Enable Filtering"
-msgstr ""
+msgstr "Åœalti filtradon"
#: editor/plugins/animation_player_editor_plugin.cpp
+#, fuzzy
msgid "Toggle Autoplay"
-msgstr ""
+msgstr "Baskuli aÅ­toludadon"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "New Animation Name:"
-msgstr ""
+msgstr "Nomo de nova animacio:"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "New Anim"
-msgstr ""
+msgstr "Nova animacio"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Change Animation Name:"
-msgstr ""
+msgstr "ÅœanÄi nomon de animacio:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Delete Animation?"
-msgstr ""
+msgstr "Forigi animacion?"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Remove Animation"
-msgstr ""
+msgstr "Forigi animacion"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Invalid animation name!"
-msgstr ""
+msgstr "Nevalida nomo de animacio!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation name already exists!"
-msgstr ""
+msgstr "Nomo de animacio jam ekzistas!"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
@@ -4499,71 +4589,71 @@ msgstr "Renomi animaĵon"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Blend Next Changed"
-msgstr ""
+msgstr "Mikso sekvo ÅanÄiÄis"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Change Blend Time"
-msgstr ""
+msgstr "ÅœanÄi tempon de mikso"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Load Animation"
-msgstr ""
+msgstr "Åœargi animacion"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Duplicate Animation"
-msgstr ""
+msgstr "Duplikati animacion"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "No animation to copy!"
-msgstr ""
+msgstr "Ne animacio por kopii!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "No animation resource on clipboard!"
-msgstr ""
+msgstr "Ne animacia risurco en tondujo!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Pasted Animation"
-msgstr ""
+msgstr "Algluis animacion"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Paste Animation"
-msgstr ""
+msgstr "Alglui animacion"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "No animation to edit!"
-msgstr ""
+msgstr "Ne animacio por redakti!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation backwards from current pos. (A)"
-msgstr ""
+msgstr "Ludi elektitan animacion retre el aktuala pozicio. (A)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation backwards from end. (Shift+A)"
-msgstr ""
+msgstr "Ludi elektitan animacion retre el fino. (Majuskliga klavo+A)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Stop animation playback. (S)"
-msgstr ""
+msgstr "Halti reproduktadon de animacio. (S)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation from start. (Shift+D)"
-msgstr ""
+msgstr "Ludi elektitan animacion el komenco. (Majuskliga klavo+D)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation from current pos. (D)"
-msgstr ""
+msgstr "Ludi elektitan animacion el aktuala pozicio. (D)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation position (in seconds)."
-msgstr ""
+msgstr "Pozicio de animacio (en sekundoj)."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Scale animation playback globally for the node."
-msgstr ""
+msgstr "Skali reproduktadon de animacio malloke por la nodo."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation Tools"
-msgstr ""
+msgstr "Iloj de animacio"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation"
@@ -4571,7 +4661,7 @@ msgstr "Animacio"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Edit Transitions..."
-msgstr ""
+msgstr "Redakti transpasojn..."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Open in Inspector"
@@ -4579,147 +4669,147 @@ msgstr "Malfermi en la Inspektoro"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Display list of animations in player."
-msgstr ""
+msgstr "Vidigi liston de animacioj en ludilo."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Autoplay on Load"
-msgstr ""
+msgstr "AÅ­toludi al Åargo"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Enable Onion Skinning"
-msgstr ""
+msgstr "Åœalti cepo-haÅ­tadon"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Onion Skinning Options"
-msgstr ""
+msgstr "Cepo-haÅ­tadaj opcioj"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Directions"
-msgstr ""
+msgstr "Direktoj"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Past"
-msgstr ""
+msgstr "Pasinteco"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Future"
-msgstr ""
+msgstr "Estonteco"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Depth"
-msgstr ""
+msgstr "Profundo"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "1 step"
-msgstr ""
+msgstr "1 paÅo"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "2 steps"
-msgstr ""
+msgstr "2 paÅoj"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "3 steps"
-msgstr ""
+msgstr "3 paÅoj"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Differences Only"
-msgstr ""
+msgstr "Malsamoj nur"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Force White Modulate"
-msgstr ""
+msgstr "Altrudi blankan moduladon"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Include Gizmos (3D)"
-msgstr ""
+msgstr "Inkludi gizmojn (3D)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Pin AnimationPlayer"
-msgstr ""
+msgstr "Fiksi AnimationPlayer"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Create New Animation"
-msgstr ""
+msgstr "Krei novan animacion"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation Name:"
-msgstr ""
+msgstr "Nomo de animacio:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
msgid "Error!"
-msgstr ""
+msgstr "Eraro!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Blend Times:"
-msgstr ""
+msgstr "Tempoj de mikso:"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Next (Auto Queue):"
-msgstr ""
+msgstr "Sekvo (aÅ­tomata atendovico):"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Cross-Animation Blend Times"
-msgstr ""
+msgstr "Tempoj de trans-animacia mikso"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Move Node"
-msgstr ""
+msgstr "Movi nodon"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Transition exists!"
-msgstr ""
+msgstr "Transpaso ekzistas!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
-msgstr ""
+msgstr "Aldoni transpason"
#: editor/plugins/animation_state_machine_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Node"
-msgstr ""
+msgstr "Aldoni nodon"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "End"
-msgstr ""
+msgstr "Fino"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Immediate"
-msgstr ""
+msgstr "Tuja"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Sync"
-msgstr ""
+msgstr "Sinkrona"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "At End"
-msgstr ""
+msgstr "Je la fino"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Travel"
-msgstr ""
+msgstr "VojaÄa"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Start and end nodes are needed for a sub-transition."
-msgstr ""
+msgstr "Komencan kaj finan nodojn bezonas por sub-transpaso."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "No playback resource set at path: %s."
-msgstr ""
+msgstr "Ne reproduktada risurcaro al vojo: %s."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Node Removed"
-msgstr ""
+msgstr "Nodon forigis"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Transition Removed"
-msgstr ""
+msgstr "Transpason forigis"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Set Start Node (Autoplay)"
-msgstr ""
+msgstr "Difini komencan nodon (aÅ­toludadon)"
#: editor/plugins/animation_state_machine_editor.cpp
msgid ""
@@ -4727,56 +4817,62 @@ msgid ""
"RMB to add new nodes.\n"
"Shift+LMB to create connections."
msgstr ""
+"Elekti kaj movi nodojn.\n"
+"Dekstra musbutono por aldoni novajn nodojn.\n"
+"Majuskliga klavo+maldekstra musbutono por krei konektojn."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Create new nodes."
-msgstr ""
+msgstr "Krei novajn nodojn."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Connect nodes."
-msgstr ""
+msgstr "Konekti nodojn."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Remove selected node or transition."
-msgstr ""
+msgstr "Forigi elektitan nodon aÅ­ transpason."
#: editor/plugins/animation_state_machine_editor.cpp
+#, fuzzy
msgid "Toggle autoplay this animation on start, restart or seek to zero."
msgstr ""
+"Baskuli aŭtoludadon de ĉi tiu animacio al komenco, rekomenco aŭ enpoziciigo "
+"al nulo."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Set the end animation. This is useful for sub-transitions."
-msgstr ""
+msgstr "Difinu la finan animacion. Tio ĉi estas utila por sub-transpasoj."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Transition: "
-msgstr ""
+msgstr "Transpaso: "
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Play Mode:"
-msgstr ""
+msgstr "ReÄimo de ludado:"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "AnimationTree"
-msgstr ""
+msgstr "AnimationTree"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "New name:"
-msgstr ""
+msgstr "Nova nomo:"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Scale:"
-msgstr ""
+msgstr "Skalo:"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "Fade In (s):"
-msgstr ""
+msgstr "Maldissolvo (s):"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "Fade Out (s):"
-msgstr ""
+msgstr "Fordissolvo (s):"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "Blend"
@@ -4899,100 +4995,99 @@ msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Contents:"
-msgstr ""
+msgstr "Enhavo:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "View Files"
-msgstr ""
+msgstr "Vidi dosierojn"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Connection error, please try again."
-msgstr ""
+msgstr "Konekta eraro, bonvolu provi ree."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Can't connect to host:"
-msgstr ""
+msgstr "Ne eblas konekti al retejo:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "No response from host:"
-msgstr ""
+msgstr "Ne respondo el retejo:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Can't resolve hostname:"
-msgstr ""
+msgstr "Ne eblas adrestrovi nomon de retejo:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Request failed, return code:"
-msgstr ""
+msgstr "Peto eraris, revena kodo:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Request failed."
-msgstr ""
+msgstr "Peto eraris."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Cannot save response to:"
-msgstr ""
+msgstr "Ne eblas konservi respondon al:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Write error."
-msgstr ""
+msgstr "Skribada eraro."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Request failed, too many redirects"
-msgstr ""
+msgstr "Peto eraris, tro da alidirektoj"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Redirect loop."
-msgstr ""
+msgstr "Alidirekta iteracio."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Request failed, timeout"
-msgstr ""
+msgstr "Peto eraris, tempolimo"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Timeout."
-msgstr "Tempo:"
+msgstr "Tempolimo."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
+msgstr "Malbona haketaĵo el elÅutaĵo, supozas dosieron esti tuÅaĉita."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Expected:"
-msgstr ""
+msgstr "Atendito:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Got:"
-msgstr ""
+msgstr "Ricevinto:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed SHA-256 hash check"
-msgstr ""
+msgstr "Kontrolo de SHA-256-a haketaĵo eraris"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
-msgstr ""
+msgstr "Eraro de havaĵa elÅuto:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Downloading (%s / %s)..."
-msgstr ""
+msgstr "ElÅutas (%s / %s)..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Downloading..."
-msgstr ""
+msgstr "ElÅutas..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Resolving..."
-msgstr ""
+msgstr "Adrestrovas..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Error making request"
-msgstr ""
+msgstr "Eraro dum petado"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Idle"
-msgstr ""
+msgstr "Senokupa"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Install..."
@@ -5004,105 +5099,107 @@ msgstr "Reprovi"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Download Error"
-msgstr ""
+msgstr "ElÅuta eraro"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Download for this asset is already in progress!"
-msgstr ""
+msgstr "ElÅutado de ĉi tiu havaĵo estas jam farata!"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Recently Updated"
-msgstr ""
+msgstr "Plej lastatempe Äisdatigita"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Least Recently Updated"
-msgstr ""
+msgstr "Malplej lastatempe Äisdatigita"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Name (A-Z)"
-msgstr ""
+msgstr "Nomo (A-Z)"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Name (Z-A)"
-msgstr ""
+msgstr "Nomo (Z-A)"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "License (A-Z)"
-msgstr ""
+msgstr "Permesilo (A-Z)"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "License (Z-A)"
-msgstr ""
+msgstr "Permesilo (Z-A)"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "First"
-msgstr ""
+msgstr "Unua"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Previous"
-msgstr ""
+msgstr "AntaÅ­a"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Next"
-msgstr ""
+msgstr "Sekva"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Last"
-msgstr ""
+msgstr "Lasta"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "All"
-msgstr ""
+msgstr "Tuta"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "No results for \"%s\"."
-msgstr ""
+msgstr "Ne rezultoj por \"%s\"."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Import..."
-msgstr ""
+msgstr "Enporti..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Plugins..."
-msgstr ""
+msgstr "Kromprogramoj..."
#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
msgid "Sort:"
-msgstr "Ordigi:"
+msgstr "Ordigo:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Category:"
-msgstr ""
+msgstr "Kategorio:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Site:"
-msgstr ""
+msgstr "Retejo:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Support"
-msgstr ""
+msgstr "Helpo"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Official"
-msgstr ""
+msgstr "Ofica"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Testing"
-msgstr ""
+msgstr "Testada"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Loading..."
-msgstr ""
+msgstr "Åœargas..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Assets ZIP File"
-msgstr ""
+msgstr "ZIP-dosiero de havaĵoj"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Can't determine a save path for lightmap images.\n"
"Save your scene and try again."
msgstr ""
+"Ne eblas determini konservan dosierindikon por lummapaj bildoj.\n"
+"Konservu vian scenon kaj provu ree."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -5126,25 +5223,16 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
-msgstr ""
+msgstr "Baki lummapojn"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Select lightmap bake file:"
-msgstr ""
+msgstr "Elekti dosieron por bakado de lummapo:"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5153,106 +5241,103 @@ msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Configure Snap"
-msgstr ""
+msgstr "Agordi kapton"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Grid Offset:"
-msgstr ""
+msgstr "Krada deÅovo:"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Grid Step:"
-msgstr ""
+msgstr "Krada paÅo:"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Primary Line Every:"
-msgstr ""
+msgstr "Ĉefa linio al ĉiu:"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "steps"
-msgstr ""
+msgstr "paÅoj"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Rotation Offset:"
-msgstr ""
+msgstr "Rotacia deÅovo:"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Rotation Step:"
-msgstr ""
+msgstr "Rotacia paÅo:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Scale Step:"
-msgstr "Skali RejÅo:"
+msgstr "Skala paÅo:"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Move Vertical Guide"
-msgstr ""
+msgstr "Movi vertikalan gvidilon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Create Vertical Guide"
-msgstr ""
+msgstr "Krei vertikalan gvidilon"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Remove Vertical Guide"
-msgstr "Forigi Nevalidajn Åœlosilojn"
+msgstr "Forigi vertikalan gvidilon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Move Horizontal Guide"
-msgstr ""
+msgstr "Movi horizontalan gvidilon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Create Horizontal Guide"
-msgstr ""
+msgstr "Krei horizontalan gvidilon"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Remove Horizontal Guide"
-msgstr "Forigi Nevalidajn Åœlosilojn"
+msgstr "Forigi horizontalan gvidilon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Create Horizontal and Vertical Guides"
-msgstr ""
+msgstr "Krei horizontalajn kaj vertikalajn gvidilojn"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"
-msgstr ""
+msgstr "Agordi la deÅovon de la pivoto de CanvasItem \"%s\" al (%d, %d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Rotate %d CanvasItems"
-msgstr ""
+msgstr "Rotacii %d CanvasItem-ojn"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Rotate CanvasItem \"%s\" to %d degrees"
-msgstr ""
+msgstr "Rotacii CanvasItem \"%s\" al %d gradoj"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Move CanvasItem \"%s\" Anchor"
-msgstr ""
+msgstr "Movi la ankron de CanvasItem \"%s\""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale Node2D \"%s\" to (%s, %s)"
-msgstr ""
+msgstr "Skali Node2D \"%s\" al (%s, %s)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Resize Control \"%s\" to (%d, %d)"
-msgstr ""
+msgstr "Regrandigi Control \"%s\" al (%d, %d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale %d CanvasItems"
-msgstr ""
+msgstr "Skali %d CanvasItem-ojn"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale CanvasItem \"%s\" to (%s, %s)"
-msgstr ""
+msgstr "Skali CanvasItem \"%s\" al (%s, %s)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Move %d CanvasItems"
-msgstr ""
+msgstr "Movi %d CanvasItem-ojn"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Move CanvasItem \"%s\" to (%d, %d)"
-msgstr ""
+msgstr "Movi CanvasItem \"%s\" al (%d, %d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid ""
@@ -5272,67 +5357,67 @@ msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Top Left"
-msgstr ""
+msgstr "Supre maldekstre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Top Right"
-msgstr ""
+msgstr "Supre dekstre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Bottom Right"
-msgstr ""
+msgstr "Malsupre dekstre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Bottom Left"
-msgstr ""
+msgstr "Malsupre maldekstre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Left"
-msgstr ""
+msgstr "Centre maldekstre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Top"
-msgstr ""
+msgstr "Centre supre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Right"
-msgstr ""
+msgstr "Centre dekstre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Bottom"
-msgstr ""
+msgstr "Centre malsupre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center"
-msgstr ""
+msgstr "Centre"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Left Wide"
-msgstr ""
+msgstr "Maldekstre vaste"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Top Wide"
-msgstr ""
+msgstr "Supre vaste"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Right Wide"
-msgstr ""
+msgstr "Dekstre vaste"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Bottom Wide"
-msgstr ""
+msgstr "Malsupre vaste"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "VCenter Wide"
-msgstr ""
+msgstr "Vertikalcentre vaste"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "HCenter Wide"
-msgstr ""
+msgstr "Horizontalcentre vaste"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Full Rect"
-msgstr ""
+msgstr "Plene rektangula"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -5341,15 +5426,15 @@ msgstr "Skali RejÅo:"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Anchors only"
-msgstr ""
+msgstr "Nur ankroj"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Change Anchors and Margins"
-msgstr ""
+msgstr "ÅœanÄi ankrojn kaj marÄenojn"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Change Anchors"
-msgstr ""
+msgstr "ÅœanÄi ankrojn"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5357,6 +5442,8 @@ msgid ""
"Game Camera Override\n"
"Overrides game camera with editor viewport camera."
msgstr ""
+"Transpaso de la luda fotilo\n"
+"Transpasi ludan fotilon kun viduja fotilo de la redaktilo."
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5364,98 +5451,104 @@ msgid ""
"Game Camera Override\n"
"No game instance running."
msgstr ""
+"Transpaso de la luda fotilo\n"
+"Ne luda ekzemplo ruliÄas."
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Lock Selected"
-msgstr ""
+msgstr "Åœlosi elektiton"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Unlock Selected"
-msgstr ""
+msgstr "MalÅlosi elektiton"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Group Selected"
-msgstr ""
+msgstr "Grupigi elektiton"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Ungroup Selected"
-msgstr ""
+msgstr "Malgrupigi elektiton"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
-msgstr ""
+msgstr "Alglui pozon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Clear Guides"
-msgstr ""
+msgstr "Vakigi gvidilojn"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Create Custom Bone(s) from Node(s)"
-msgstr ""
+msgstr "Krei proprajn osto(j)n el nodo(j)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Clear Bones"
-msgstr ""
+msgstr "Vakigi ostojn"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make IK Chain"
-msgstr ""
+msgstr "Krei IK-an ĉenon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Clear IK Chain"
-msgstr ""
+msgstr "Vakigi IK-an ĉenon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid ""
"Warning: Children of a container get their position and size determined only "
"by their parent."
msgstr ""
+"Verto: Infanoj de stirilujo determinas iliajn poziciojn kaj grandojn nur per "
+"ilia patro."
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/texture_region_editor_plugin.cpp
#: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp
msgid "Zoom Reset"
-msgstr ""
+msgstr "Rekomencigi zomon"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Select Mode"
-msgstr ""
+msgstr "Elektada reÄimo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Drag: Rotate"
-msgstr ""
+msgstr "Åœovado: Rotacii"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Alt+Drag: Move"
-msgstr ""
+msgstr "Alt-klavo+Åovado: Movi"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)."
msgstr ""
+"Premi 'V' por ÅanÄi pivoton, 'Majuskliga klavo+V' por Åovi pivoton (dum "
+"movado)."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Alt+RMB: Depth list selection"
-msgstr ""
+msgstr "Alt-klavo+dekstra musbutono: Elektado el profunda listo"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode"
-msgstr ""
+msgstr "Movada reÄimo"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotate Mode"
-msgstr ""
+msgstr "Rotaciada reÄimo"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Scale Mode"
-msgstr ""
+msgstr "Skalada reÄimo"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5463,97 +5556,99 @@ msgid ""
"Show a list of all objects at the position clicked\n"
"(same as Alt+RMB in select mode)."
msgstr ""
+"Vidigi liston de ĉiuj objektoj al la alklakita pozicio.\n"
+"(samo kiel Alt-klavo+dekstra musbutono en elektada reÄimo)."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Click to change object's rotation pivot."
-msgstr ""
+msgstr "Alklaku por ÅanÄi rotacian pivoton de objekto."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Pan Mode"
-msgstr ""
+msgstr "Panoramada reÄimo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Ruler Mode"
-msgstr ""
+msgstr "Mezurado reÄimo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Toggle smart snapping."
-msgstr ""
+msgstr "Baskuli inteligentan kaptadon."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Smart Snap"
-msgstr ""
+msgstr "Uzi inteligentan kaptadon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Toggle grid snapping."
-msgstr ""
+msgstr "Baskuli kaptadon per krado."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Grid Snap"
-msgstr ""
+msgstr "Uzi kapton per krado"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snapping Options"
-msgstr ""
+msgstr "Opcioj de kaptado"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Rotation Snap"
-msgstr ""
+msgstr "Uzi rotacian kaptadon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Scale Snap"
-msgstr ""
+msgstr "Uzi skalan kaptadon"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap Relative"
-msgstr ""
+msgstr "Kapti relative"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Pixel Snap"
-msgstr ""
+msgstr "Uzi kaptadon per rastrumero"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Smart Snapping"
-msgstr ""
+msgstr "Inteligenta kaptado"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Configure Snap..."
-msgstr ""
+msgstr "Agordi kaptadon..."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap to Parent"
-msgstr ""
+msgstr "Kapti al patro"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap to Node Anchor"
-msgstr ""
+msgstr "Kapti al ankro de nodo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap to Node Sides"
-msgstr ""
+msgstr "Kapti al flankoj de nodo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap to Node Center"
-msgstr ""
+msgstr "Kapti al centro de nodo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap to Other Nodes"
-msgstr ""
+msgstr "Kapti al aliaj nodoj"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap to Guides"
-msgstr ""
+msgstr "Kapti al gvidiloj"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Lock the selected object in place (can't be moved)."
-msgstr ""
+msgstr "Åœlosi la elektitan objekton samloke (ne movebla)."
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Unlock the selected object (can be moved)."
-msgstr ""
+msgstr "MalÅlosi la elektitan objekton (movebla)."
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -6867,20 +6962,20 @@ msgstr "Serĉo"
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
-msgstr ""
+msgstr "PaÅi en"
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Over"
-msgstr ""
+msgstr "PaÅi poste"
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Break"
-msgstr ""
+msgstr "PaÅ­zi rulon"
#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_editor_debugger.cpp
msgid "Continue"
-msgstr ""
+msgstr "DaÅ­rigi"
#: editor/plugins/script_editor_plugin.cpp
msgid "Keep Debugger Open"
@@ -6892,7 +6987,7 @@ msgstr ""
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation."
-msgstr ""
+msgstr "Malfermi enretan dokumentaron de Godot."
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -6927,19 +7022,19 @@ msgstr "Rezultoj de serĉo"
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Scripts"
-msgstr ""
+msgstr "Vakigi lastajn skriptojn"
#: editor/plugins/script_text_editor.cpp
msgid "Connections to method:"
-msgstr ""
+msgstr "Konektoj al metodo:"
#: editor/plugins/script_text_editor.cpp editor/script_editor_debugger.cpp
msgid "Source"
-msgstr ""
+msgstr "Fonto"
#: editor/plugins/script_text_editor.cpp
msgid "Target"
-msgstr ""
+msgstr "Celo"
#: editor/plugins/script_text_editor.cpp
msgid ""
@@ -6952,15 +7047,15 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
msgid "Line"
-msgstr ""
+msgstr "Linio"
#: editor/plugins/script_text_editor.cpp
msgid "Go to Function"
-msgstr ""
+msgstr "Iri al funkcio"
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr "Nur risurcoj el dosiersistemo povas esti forigita."
+msgstr "Nur risurcojn el la dosiersistemo eblas forigi."
#: editor/plugins/script_text_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
@@ -6969,83 +7064,83 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
msgid "Lookup Symbol"
-msgstr ""
+msgstr "Ricevi simbolon"
#: editor/plugins/script_text_editor.cpp
msgid "Pick Color"
-msgstr ""
+msgstr "Elekti koloron"
#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
msgid "Convert Case"
-msgstr ""
+msgstr "Konverti usklon"
#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
msgid "Uppercase"
-msgstr ""
+msgstr "Majuskla"
#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
msgid "Lowercase"
-msgstr ""
+msgstr "Minuskla"
#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
msgid "Capitalize"
-msgstr ""
+msgstr "Kapitaligi"
#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
msgid "Syntax Highlighter"
-msgstr ""
+msgstr "Sintaksa markilo"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
msgid "Bookmarks"
-msgstr ""
+msgstr "PaÄosignoj"
#: editor/plugins/script_text_editor.cpp
msgid "Breakpoints"
-msgstr ""
+msgstr "PaÅ­zpunktoj"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
msgid "Go To"
-msgstr ""
+msgstr "Iri al"
#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
-msgstr ""
+msgstr "Eltondi"
#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
#: scene/gui/text_edit.cpp
msgid "Select All"
-msgstr "Elektaro ĉiuj"
+msgstr "Elekti tutan"
#: editor/plugins/script_text_editor.cpp
msgid "Delete Line"
-msgstr ""
+msgstr "Forigi linion"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
-msgstr ""
+msgstr "KrommarÄeni maldekstren"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Right"
-msgstr ""
+msgstr "KrommarÄeni dekstren"
#: editor/plugins/script_text_editor.cpp
msgid "Toggle Comment"
-msgstr ""
+msgstr "Baskuli komenton"
#: editor/plugins/script_text_editor.cpp
msgid "Fold/Unfold Line"
-msgstr ""
+msgstr "Faldi/Malfaldi linion"
#: editor/plugins/script_text_editor.cpp
msgid "Fold All Lines"
-msgstr ""
+msgstr "Faldi ĉiujn liniojn"
#: editor/plugins/script_text_editor.cpp
msgid "Unfold All Lines"
-msgstr ""
+msgstr "Malfaldi ĉiujn liniojn"
#: editor/plugins/script_text_editor.cpp
msgid "Clone Down"
@@ -7438,6 +7533,12 @@ msgid ""
"Closed eye: Gizmo is hidden.\n"
"Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")."
msgstr ""
+"Alklaku por baskuli inter videblaj statoj.\n"
+"\n"
+"Malferma okulo: Gizmo estas videbla.\n"
+"Ferma okulo: Gizmo estas kaÅita.\n"
+"Duonferma okulo: Gizmo estas ankaÅ­ videbla tra maldiafanaj surfacoj (\"iks-"
+"rada\")."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Snap Nodes To Floor"
@@ -7456,11 +7557,11 @@ msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Use Local Space"
-msgstr ""
+msgstr "Uzi lokan spacon"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Use Snap"
-msgstr ""
+msgstr "Uzi kapton krade"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom View"
@@ -9522,16 +9623,17 @@ msgstr ""
#: editor/project_manager.cpp
msgid "The path specified doesn't exist."
-msgstr ""
+msgstr "La provizinta dosierindiko ne ekzistas."
#: editor/project_manager.cpp
msgid "Error opening package file (it's not in ZIP format)."
-msgstr ""
+msgstr "Eraro dum malfermi pakaĵan dosieron (ne estas en ZIP-formo)."
#: editor/project_manager.cpp
msgid ""
"Invalid \".zip\" project file; it doesn't contain a \"project.godot\" file."
msgstr ""
+"Nevalida projekta \".zip\" dosiero; Äi ne enhavas dosieron \"project.godot\"."
#: editor/project_manager.cpp
msgid "Please choose an empty folder."
@@ -9539,11 +9641,11 @@ msgstr "Bonvolu, elektu malplenan dosierujon."
#: editor/project_manager.cpp
msgid "Please choose a \"project.godot\" or \".zip\" file."
-msgstr ""
+msgstr "Bonvolu elekti \"project.godot\" aÅ­ \".zip\" dosieron."
#: editor/project_manager.cpp
msgid "This directory already contains a Godot project."
-msgstr ""
+msgstr "Tiu ĉi dosierujo jam enhavas Godot-an projekton."
#: editor/project_manager.cpp
msgid "New Game Project"
@@ -9551,41 +9653,43 @@ msgstr "Nova luda projekto"
#: editor/project_manager.cpp
msgid "Imported Project"
-msgstr ""
+msgstr "Enportita projekto"
#: editor/project_manager.cpp
msgid "Invalid Project Name."
-msgstr ""
+msgstr "Nevalida nomo de projekto."
#: editor/project_manager.cpp
msgid "Couldn't create folder."
-msgstr "Ne povis krei dosierujon."
+msgstr "Ne eblas krei dosierujon."
#: editor/project_manager.cpp
msgid "There is already a folder in this path with the specified name."
-msgstr ""
+msgstr "Estas jam dosierujo en ĉi tiu dosierindiko kun la provizinta nomo."
#: editor/project_manager.cpp
msgid "It would be a good idea to name your project."
-msgstr ""
+msgstr "Nomi vian projekton estus konsilinde."
#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
-msgstr ""
+msgstr "Nevalida dosierindiko de projekto (ÅanÄis ion ajn?)."
#: editor/project_manager.cpp
msgid ""
"Couldn't load project.godot in project path (error %d). It may be missing or "
"corrupted."
msgstr ""
+"Ne eblas Åargi project.godot en projekta dosierindiko (eraro %d). Äœi eble "
+"estas manka aÅ­ difektita."
#: editor/project_manager.cpp
msgid "Couldn't edit project.godot in project path."
-msgstr ""
+msgstr "Ne eblas redakti project.godot en projekta dosierindiko."
#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
-msgstr ""
+msgstr "Ne eblas krei project.godot en projekta dosierindiko."
#: editor/project_manager.cpp
msgid "Rename Project"
@@ -9593,11 +9697,11 @@ msgstr "Renomi projekton"
#: editor/project_manager.cpp
msgid "Import Existing Project"
-msgstr ""
+msgstr "Enporti ekzistantan projekton"
#: editor/project_manager.cpp
msgid "Import & Edit"
-msgstr ""
+msgstr "Enporti kaj redakti"
#: editor/project_manager.cpp
msgid "Create New Project"
@@ -9624,9 +9728,8 @@ msgid "Project Path:"
msgstr "Projekta vojo:"
#: editor/project_manager.cpp
-#, fuzzy
msgid "Project Installation Path:"
-msgstr "Projekta instala vojo:"
+msgstr "Dosierindiko de projekta instalo:"
#: editor/project_manager.cpp
msgid "Renderer:"
@@ -9634,68 +9737,64 @@ msgstr "Bildigilo:"
#: editor/project_manager.cpp
msgid "OpenGL ES 3.0"
-msgstr ""
+msgstr "OpenGL ES 3.0"
#: editor/project_manager.cpp
msgid "Not supported by your GPU drivers."
-msgstr ""
+msgstr "Ne subtenata de la peliloj de via grafika procesoro."
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Higher visual quality\n"
"All features available\n"
"Incompatible with older hardware\n"
"Not recommended for web games"
msgstr ""
-"Pli alta vida kvalito\n"
-"Ĉiuj ebloj disponeblaj\n"
+"Pli bona vida kvalito\n"
+"Ĉiuj eblecoj disponeblas\n"
"Nekongruas kun pli malnova aparataro\n"
-"Nerekomendita por teksaĵaj ludoj"
+"Ne rekomendas por retaj ludoj"
#: editor/project_manager.cpp
msgid "OpenGL ES 2.0"
-msgstr ""
+msgstr "OpenGL ES 2.0"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Lower visual quality\n"
"Some features not available\n"
"Works on most hardware\n"
"Recommended for web games"
msgstr ""
-"Pli malalta vida kvalito\n"
-"Iom ebloj ne disponeblaj\n"
-"Laboras en plej multaj aparataroj\n"
-"Rekomendita por teksaĵaj ludoj"
+"Malpli bona vida kvalito\n"
+"Iuj eblecoj ne disponeblas\n"
+"Kongruas kun plej de aparataro\n"
+"Rekomendas por retaj ludoj"
#: editor/project_manager.cpp
+#, fuzzy
msgid "Renderer can be changed later, but scenes may need to be adjusted."
-msgstr ""
+msgstr "Bildigilo ÅanÄeblas poste, sed scenoj eble bezonos Äustigon."
#: editor/project_manager.cpp
msgid "Unnamed Project"
-msgstr ""
+msgstr "Sennoma projekto"
#: editor/project_manager.cpp
-#, fuzzy
msgid "Missing Project"
-msgstr "Malkanta projekto"
+msgstr "Manka projekto"
#: editor/project_manager.cpp
-#, fuzzy
msgid "Error: Project is missing on the filesystem."
msgstr "Eraro: projekto estas manka en la dosiersistemo."
#: editor/project_manager.cpp
msgid "Can't open project at '%s'."
-msgstr "Ne povas malfermi projekto ĉe '%s'."
+msgstr "Ne eblas malfermi projekton ĉe '%s'."
#: editor/project_manager.cpp
-#, fuzzy
msgid "Are you sure to open more than one project?"
-msgstr "Ĉu vi certa en malfermaĵo pli ol unun projekton?"
+msgstr "Ĉu vi certe volas malfermi plurajn projektojn?"
#: editor/project_manager.cpp
msgid ""
@@ -9709,6 +9808,15 @@ msgid ""
"Warning: You won't be able to open the project with previous versions of the "
"engine anymore."
msgstr ""
+"La jena projekto-agordara dosiero ne specifas la versio de Godot per kiu "
+"krei Äin.\n"
+"\n"
+"%s\n"
+"\n"
+"Se vi pluigus malfermi Äin, Äi konvertiÄos al aktuala agordo-dosierformo de "
+"Godot.\n"
+"Averto: Vi ne eblos malfermi la projekton per antaÅ­aj versioj de la "
+"videoludilo plue."
#: editor/project_manager.cpp
msgid ""
@@ -9721,12 +9829,22 @@ msgid ""
"Warning: You won't be able to open the project with previous versions of the "
"engine anymore."
msgstr ""
+"La jena projekto-agordara dosiero generiÄis per pli malnova versio de la "
+"videoludilo, kaj bezonas konverti al ĉi tiu versio:\n"
+"\n"
+"%s\n"
+"\n"
+"Ĉu vi volas konverti Äin?\n"
+"Averto: Vi ne eblos malfermi la projekton per antaÅ­aj versioj de la "
+"videoludilo plue."
#: editor/project_manager.cpp
msgid ""
"The project settings were created by a newer engine version, whose settings "
"are not compatible with this version."
msgstr ""
+"La projektaj agordoj kreiÄis per pli nova versio de la videoludilo, en kio "
+"la agordoj ne estas kongruantaj kun ĉi tiu versio."
#: editor/project_manager.cpp
msgid ""
@@ -9778,7 +9896,7 @@ msgstr ""
#. TRANSLATORS: This refers to the application where users manage their Godot projects.
#: editor/project_manager.cpp
msgid "Project Manager"
-msgstr ""
+msgstr "Mastrumilo de Projektoj"
#: editor/project_manager.cpp
msgid "Projects"
@@ -9786,12 +9904,11 @@ msgstr "Projektoj"
#: editor/project_manager.cpp
msgid "Loading, please wait..."
-msgstr ""
+msgstr "Åœargas, bonvolu atendi..."
#: editor/project_manager.cpp
-#, fuzzy
msgid "Last Modified"
-msgstr "Modifita"
+msgstr "Lastaj modifitaj"
#: editor/project_manager.cpp
msgid "Scan"
@@ -9807,7 +9924,7 @@ msgstr "Nova projekto"
#: editor/project_manager.cpp
msgid "Remove Missing"
-msgstr ""
+msgstr "Forigi mankan"
#: editor/project_manager.cpp
msgid "Templates"
@@ -9815,17 +9932,20 @@ msgstr "Åœablonoj"
#: editor/project_manager.cpp
msgid "Restart Now"
-msgstr ""
+msgstr "Rekomenci nun"
#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr ""
+msgstr "Ne eblas ruli projekton"
#: editor/project_manager.cpp
msgid ""
"You currently don't have any projects.\n"
"Would you like to explore official example projects in the Asset Library?"
msgstr ""
+"Vi aktuale ne havas iujn projektojn.\n"
+"Ĉu vi volas esplori la oficajn ekzemplajn projektojn en la biblioteko de "
+"havaĵoj?"
#: editor/project_manager.cpp
msgid ""
@@ -9836,145 +9956,147 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid "Key "
-msgstr ""
+msgstr "Klavo "
#: editor/project_settings_editor.cpp
msgid "Joy Button"
-msgstr ""
+msgstr "Butono de stirstango"
#: editor/project_settings_editor.cpp
msgid "Joy Axis"
-msgstr ""
+msgstr "Akso de stirstango"
#: editor/project_settings_editor.cpp
msgid "Mouse Button"
-msgstr ""
+msgstr "Musbutono"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
+"Nevalida nomo de faro. Äœi eblas nek esti malplena nek enhavi '/', ':', '=', "
+"'\\' aÅ­ '\"'"
#: editor/project_settings_editor.cpp
msgid "An action with the name '%s' already exists."
-msgstr ""
+msgstr "Faro kun la nomo '%s' jam ekzistas."
#: editor/project_settings_editor.cpp
msgid "Rename Input Action Event"
-msgstr ""
+msgstr "Renomi eventon de eniga faro"
#: editor/project_settings_editor.cpp
msgid "Change Action deadzone"
-msgstr ""
+msgstr "ÅœanÄi mortzonon de faro"
#: editor/project_settings_editor.cpp
msgid "Add Input Action Event"
-msgstr ""
+msgstr "Aldoni eventon de eniga faro"
#: editor/project_settings_editor.cpp
msgid "All Devices"
-msgstr ""
+msgstr "Ĉiuj aparatoj"
#: editor/project_settings_editor.cpp
msgid "Device"
-msgstr ""
+msgstr "Aparato"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
msgid "Press a Key..."
-msgstr ""
+msgstr "Premi klavon..."
#: editor/project_settings_editor.cpp
msgid "Mouse Button Index:"
-msgstr ""
+msgstr "Indekso de musbutono:"
#: editor/project_settings_editor.cpp
msgid "Left Button"
-msgstr ""
+msgstr "Maldekstra butono"
#: editor/project_settings_editor.cpp
msgid "Right Button"
-msgstr ""
+msgstr "Dekstra butono"
#: editor/project_settings_editor.cpp
msgid "Middle Button"
-msgstr ""
+msgstr "Meza butono"
#: editor/project_settings_editor.cpp
msgid "Wheel Up Button"
-msgstr ""
+msgstr "Radeto supren"
#: editor/project_settings_editor.cpp
msgid "Wheel Down Button"
-msgstr ""
+msgstr "Radeto malsupren"
#: editor/project_settings_editor.cpp
msgid "Wheel Left Button"
-msgstr ""
+msgstr "Radeto maldekstren"
#: editor/project_settings_editor.cpp
msgid "Wheel Right Button"
-msgstr ""
+msgstr "Radeto dekstren"
#: editor/project_settings_editor.cpp
msgid "X Button 1"
-msgstr ""
+msgstr "X-butono 1"
#: editor/project_settings_editor.cpp
msgid "X Button 2"
-msgstr ""
+msgstr "X-butono 2"
#: editor/project_settings_editor.cpp
msgid "Joypad Axis Index:"
-msgstr ""
+msgstr "Indekso de la stirstanga akso:"
#: editor/project_settings_editor.cpp
msgid "Axis"
-msgstr ""
+msgstr "Akso"
#: editor/project_settings_editor.cpp
msgid "Joypad Button Index:"
-msgstr ""
+msgstr "Indekso de la stirstanga butono:"
#: editor/project_settings_editor.cpp
msgid "Erase Input Action"
-msgstr ""
+msgstr "Forigi enigan faron"
#: editor/project_settings_editor.cpp
msgid "Erase Input Action Event"
-msgstr ""
+msgstr "Forigi eventon de eniga faro"
#: editor/project_settings_editor.cpp
msgid "Add Event"
-msgstr ""
+msgstr "Aldoni eventon"
#: editor/project_settings_editor.cpp
msgid "Button"
-msgstr ""
+msgstr "Butono"
#: editor/project_settings_editor.cpp
msgid "Left Button."
-msgstr ""
+msgstr "Maldesktra butono."
#: editor/project_settings_editor.cpp
msgid "Right Button."
-msgstr ""
+msgstr "Dekstra butono."
#: editor/project_settings_editor.cpp
msgid "Middle Button."
-msgstr ""
+msgstr "Meza butono."
#: editor/project_settings_editor.cpp
msgid "Wheel Up."
-msgstr ""
+msgstr "Radeto supren."
#: editor/project_settings_editor.cpp
msgid "Wheel Down."
-msgstr ""
+msgstr "Radeto malsupren."
#: editor/project_settings_editor.cpp
msgid "Add Global Property"
-msgstr ""
+msgstr "Aldoni mallokan atributon"
#: editor/project_settings_editor.cpp
msgid "Select a setting item first!"
@@ -9990,7 +10112,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid "Delete Item"
-msgstr ""
+msgstr "Forigi elementon"
#: editor/project_settings_editor.cpp
msgid ""
@@ -10000,19 +10122,19 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid "Add Input Action"
-msgstr ""
+msgstr "Aldoni enigan faron"
#: editor/project_settings_editor.cpp
msgid "Error saving settings."
-msgstr ""
+msgstr "Eraro dum konservi agordojn."
#: editor/project_settings_editor.cpp
msgid "Settings saved OK."
-msgstr ""
+msgstr "Agordoj konserviÄis bone."
#: editor/project_settings_editor.cpp
msgid "Moved Input Action Event"
-msgstr ""
+msgstr "Movis eventon de eniga faro"
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
@@ -10020,15 +10142,15 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid "Add Translation"
-msgstr ""
+msgstr "Aldoni tradukon"
#: editor/project_settings_editor.cpp
msgid "Remove Translation"
-msgstr ""
+msgstr "Forigi tradukon"
#: editor/project_settings_editor.cpp
msgid "Add Remapped Path"
-msgstr ""
+msgstr "Aldoni dosierindikon de remapo"
#: editor/project_settings_editor.cpp
msgid "Resource Remap Add Remap"
@@ -10056,108 +10178,107 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
-msgstr ""
+msgstr "Projektaj agordoj (project.godot)"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
msgid "General"
-msgstr ""
+msgstr "Äœenerala"
#: editor/project_settings_editor.cpp
msgid "Override For..."
-msgstr ""
+msgstr "Redifino por..."
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
msgid "The editor must be restarted for changes to take effect."
-msgstr ""
+msgstr "La redaktilon devas rekomencigi por ÅanÄoj efektiviÄus."
#: editor/project_settings_editor.cpp
msgid "Input Map"
-msgstr ""
+msgstr "Eniga mapo"
#: editor/project_settings_editor.cpp
msgid "Action:"
-msgstr ""
+msgstr "Faro:"
#: editor/project_settings_editor.cpp
msgid "Action"
-msgstr ""
+msgstr "Faro"
#: editor/project_settings_editor.cpp
msgid "Deadzone"
-msgstr ""
+msgstr "Mortzono"
#: editor/project_settings_editor.cpp
msgid "Device:"
-msgstr ""
+msgstr "Aparato:"
#: editor/project_settings_editor.cpp
msgid "Index:"
-msgstr ""
+msgstr "Indekso:"
#: editor/project_settings_editor.cpp
msgid "Localization"
-msgstr ""
+msgstr "Lokaĵigado"
#: editor/project_settings_editor.cpp
msgid "Translations"
-msgstr ""
+msgstr "Tradukoj"
#: editor/project_settings_editor.cpp
msgid "Translations:"
-msgstr ""
+msgstr "Tradukoj:"
#: editor/project_settings_editor.cpp
msgid "Remaps"
-msgstr ""
+msgstr "Remapoj"
#: editor/project_settings_editor.cpp
msgid "Resources:"
-msgstr ""
+msgstr "Risurcoj:"
#: editor/project_settings_editor.cpp
msgid "Remaps by Locale:"
-msgstr ""
+msgstr "Remapoj per lokaĵaro:"
#: editor/project_settings_editor.cpp
msgid "Locale"
-msgstr ""
+msgstr "Lokaĵaro"
#: editor/project_settings_editor.cpp
msgid "Locales Filter"
-msgstr ""
+msgstr "Filtro de lokaĵaroj"
#: editor/project_settings_editor.cpp
msgid "Show All Locales"
-msgstr ""
+msgstr "Vidigi ĉiajn lokaĵarojn"
#: editor/project_settings_editor.cpp
msgid "Show Selected Locales Only"
-msgstr ""
+msgstr "Vidigi nur elektitajn lokaĵarojn"
#: editor/project_settings_editor.cpp
msgid "Filter mode:"
-msgstr ""
+msgstr "ReÄimo de filtro:"
#: editor/project_settings_editor.cpp
msgid "Locales:"
-msgstr ""
+msgstr "Lokaĵaroj:"
#: editor/project_settings_editor.cpp
msgid "AutoLoad"
-msgstr ""
+msgstr "AÅ­toÅargado"
#: editor/project_settings_editor.cpp
msgid "Plugins"
-msgstr ""
+msgstr "Kromprogramoj"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Import Defaults"
-msgstr "Enporti dokon"
+msgstr "Enporti defaÅ­ltojn"
#: editor/property_editor.cpp
msgid "Preset..."
-msgstr ""
+msgstr "AntaÅ­agordo..."
#: editor/property_editor.cpp
msgid "Zero"
@@ -10173,19 +10294,19 @@ msgstr ""
#: editor/property_editor.cpp
msgid "File..."
-msgstr ""
+msgstr "Dosiero..."
#: editor/property_editor.cpp
msgid "Dir..."
-msgstr ""
+msgstr "Dosierujo..."
#: editor/property_editor.cpp
msgid "Assign"
-msgstr ""
+msgstr "Valorizi"
#: editor/property_editor.cpp
msgid "Select Node"
-msgstr ""
+msgstr "Elekti nodon"
#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
@@ -10193,55 +10314,55 @@ msgstr ""
#: editor/property_editor.cpp
msgid "Pick a Node"
-msgstr ""
+msgstr "Elekti nodon"
#: editor/property_editor.cpp
msgid "Bit %d, val %d."
-msgstr ""
+msgstr "Bito %d, valoro %d."
#: editor/property_selector.cpp
msgid "Select Property"
-msgstr ""
+msgstr "Elekti atributon"
#: editor/property_selector.cpp
msgid "Select Virtual Method"
-msgstr ""
+msgstr "Elekti virtualan metodon"
#: editor/property_selector.cpp
msgid "Select Method"
-msgstr ""
+msgstr "Elekti metodon"
#: editor/rename_dialog.cpp editor/scene_tree_dock.cpp
msgid "Batch Rename"
-msgstr ""
+msgstr "Renomi staple"
#: editor/rename_dialog.cpp
msgid "Replace:"
-msgstr "AnstataÅ­igi:"
+msgstr "AnstataÅ­igo:"
#: editor/rename_dialog.cpp
msgid "Prefix:"
-msgstr ""
+msgstr "Prefikso:"
#: editor/rename_dialog.cpp
msgid "Suffix:"
-msgstr ""
+msgstr "Sufikso:"
#: editor/rename_dialog.cpp
msgid "Use Regular Expressions"
-msgstr ""
+msgstr "Uzi regulesprimojn"
#: editor/rename_dialog.cpp
msgid "Advanced Options"
-msgstr ""
+msgstr "Specialaj opcioj"
#: editor/rename_dialog.cpp
msgid "Substitute"
-msgstr ""
+msgstr "AnstatÅ­igi"
#: editor/rename_dialog.cpp
msgid "Node name"
-msgstr ""
+msgstr "Nomo de nodo"
#: editor/rename_dialog.cpp
msgid "Node's parent name, if available"
@@ -10353,27 +10474,27 @@ msgstr ""
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
-msgstr ""
+msgstr "ReÄimo de rulo:"
#: editor/run_settings_dialog.cpp
msgid "Current Scene"
-msgstr ""
+msgstr "Aktuala sceno"
#: editor/run_settings_dialog.cpp
msgid "Main Scene"
-msgstr ""
+msgstr "Ĉefa sceno"
#: editor/run_settings_dialog.cpp
msgid "Main Scene Arguments:"
-msgstr ""
+msgstr "Parametroj de ĉefa sceno:"
#: editor/run_settings_dialog.cpp
msgid "Scene Run Settings"
-msgstr ""
+msgstr "Agordoj de rulo de la sceno"
#: editor/scene_tree_dock.cpp
msgid "No parent to instance the scenes at."
-msgstr ""
+msgstr "Ne patro por ekzempli la scenojn al."
#: editor/scene_tree_dock.cpp
msgid "Error loading scene from %s"
@@ -10575,7 +10696,7 @@ msgstr "Åœargi kiel lokokupilo"
#: editor/scene_tree_dock.cpp
msgid "Open Documentation"
-msgstr "Malfermi dokumentaro"
+msgstr "Malfermi dokumentaron"
#: editor/scene_tree_dock.cpp
msgid ""
diff --git a/editor/translations/es.po b/editor/translations/es.po
index 15c577a9c8..fcb8ffc033 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -61,12 +61,14 @@
# SteamGoblin <SteamGoblin860@gmail.com>, 2021.
# Francisco C <pruebasfrancisco17@gmail.com>, 2021.
# Cam <cameron.toms@gmail.com>, 2021.
+# Juan camilo <jugarciago01@gmail.com>, 2021.
+# Manuel González <mgoopazo@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-27 22:12+0000\n"
-"Last-Translator: Cam <cameron.toms@gmail.com>\n"
+"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"Last-Translator: Manuel González <mgoopazo@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
"Language: es\n"
@@ -2611,14 +2613,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "No se pudo cargar el script addon desde la ruta: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"No se puede cargar el script de addon desde la ruta: '%s' Parece que hay un "
-"error en el código, por favor compruebe la sintaxis."
+"error en el código, por favor compruebe la sintaxis.\n"
+"Desactivar el addon en '%s' para prevenir mas errores."
#: editor/editor_node.cpp
msgid ""
@@ -3068,6 +3070,10 @@ msgid "About"
msgstr "Acerca de"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Apoyar el desarrollo de Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Reproducir el proyecto."
@@ -5312,18 +5318,9 @@ msgstr ""
"están contenidos dentro de la región cuadrangular [0,0,1,0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"El editor de Godot se construyó sin soporte de trazado de rayos, los "
"lightmaps no pueden ser bakeados."
@@ -10249,7 +10246,7 @@ msgstr "Botón del Mouse"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nombre de acción inválido. No puede estar vacío o contener '/', ':', '=', "
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index 524f628f6c..c4f8c6c4e4 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -21,8 +21,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-22 14:39+0000\n"
-"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n"
+"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
"Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/"
"godot-engine/godot/es_AR/>\n"
"Language: es_AR\n"
@@ -2564,14 +2564,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "No se pudo cargar el script de addon desde la ruta: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"No se pudo cargar el script de addon desde la ruta: '%s' Parece haber un "
-"error en el código. Por favor, revisá la sintaxis."
+"No se pudo cargar el script de addon desde la ruta: '%s'. Puede ser por un "
+"error de código en dicho script.\n"
+"Desactivando el addon en '%s' para prevenir nuevos errores."
#: editor/editor_node.cpp
msgid ""
@@ -3019,6 +3019,10 @@ msgid "About"
msgstr "Acerca de"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Apoyar el desarrollo de Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Reproducir el proyecto."
@@ -5263,19 +5267,9 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
-msgstr ""
-"El editor de Godot se compiló sin soporte de ray tracing, los lightmaps no "
+"El editor de Godot se compiló sin soporte para ray tracing, los lightmaps no "
"pueden ser bakeados."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10191,7 +10185,7 @@ msgstr "Botón de Mouse"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nombre de acción inválido. No puede estar vacío o contener '/', ':', '=', "
diff --git a/editor/translations/et.po b/editor/translations/et.po
index cd60a34dc2..d75337154a 100644
--- a/editor/translations/et.po
+++ b/editor/translations/et.po
@@ -2484,7 +2484,7 @@ msgstr "Lisa-skripti ei olnud võimalik laadida teelt: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Lisa-skripti ei olnud võimalik laadida teelt: '%s'. Tundub, et koodis on "
@@ -2897,6 +2897,10 @@ msgid "About"
msgstr "Teave"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Mängi projekti."
@@ -5054,16 +5058,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9751,7 +9746,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/eu.po b/editor/translations/eu.po
index 6dc3f5645f..b74c0906fc 100644
--- a/editor/translations/eu.po
+++ b/editor/translations/eu.po
@@ -2450,7 +2450,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2856,6 +2856,10 @@ msgid "About"
msgstr "Honi buruz"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5018,16 +5022,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9716,7 +9711,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index e2acd6a256..388bf1ca48 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -2492,7 +2492,7 @@ msgstr "امکان بارگیری اسکریپت Ø§ÙØ²ÙˆÙ†Ù‡ از مسیر وج
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2907,6 +2907,10 @@ msgid "About"
msgstr "درباره"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "اجرای پروژه."
@@ -5207,16 +5211,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10182,7 +10177,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index 81688234f2..9a1d7d7df1 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -16,7 +16,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-22 14:40+0000\n"
+"PO-Revision-Date: 2021-05-19 20:16+0000\n"
"Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n"
"Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/"
"godot/fi/>\n"
@@ -2539,14 +2539,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "Virhe ladattaessa lisäosaa polusta: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Virhe ladattaessa lisäosaa polusta: '%s'. Koodissa vaikuttaa olevan virhe, "
-"ole hyvä ja tarkista syntaksi."
+"Lisäosaskriptin lataus ei onnistunut polusta: '%s'. Tämä saattaa johtua "
+"koodivirheestä skriptissä.\n"
+"Lisäosa '%s' poistetaan käytöstä tulevien virheiden estämiseksi."
#: editor/editor_node.cpp
msgid ""
@@ -2985,6 +2985,10 @@ msgid "About"
msgstr "Tietoja"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Tue Godotin kehitystä"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Käynnistä projekti."
@@ -5219,17 +5223,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Godot-editori on käännetty ilman ray tracing -tukea, joten lightmappeja ei "
"voi kehittää."
@@ -10134,7 +10128,7 @@ msgstr "Hiiren painike"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Virheellinen toiminnon nimi. Se ei voi olla tyhjä eikä voi sisältää merkkejä "
@@ -13174,6 +13168,19 @@ msgid "Constants cannot be modified."
msgstr "Vakioita ei voi muokata."
#~ msgid ""
+#~ "Godot editor was built without ray tracing support; lightmaps can't be "
+#~ "baked.\n"
+#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta "
+#~ "emulation on Godot.app in the application settings\n"
+#~ "then restart the editor."
+#~ msgstr ""
+#~ "Godot-editori on käännetty ilman ray tracing -tukea, joten lightmappeja "
+#~ "ei voi kehittää.\n"
+#~ "Jos käytät Apple Silicon -pohjaista Mac-tietokonetta, yritä pakottaa "
+#~ "Rosetta-emulaatio Godot.app:iin sovelluksen asetuksissa\n"
+#~ "ja käynnistä sitten editori uudestaan."
+
+#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
#~ "InterpolatedCamera on vanhentunut ja poistetaan Godot 4.0 versiossa."
diff --git a/editor/translations/fil.po b/editor/translations/fil.po
index 8798d8034f..e0bc6cd724 100644
--- a/editor/translations/fil.po
+++ b/editor/translations/fil.po
@@ -2450,7 +2450,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2856,6 +2856,10 @@ msgid "About"
msgstr "Tungkol"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5013,16 +5017,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9709,7 +9704,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index 0e71b3ea89..5b310fc215 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -2634,14 +2634,14 @@ msgstr ""
"Impossible de charger le script de l’extension depuis le chemin : « %s »."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Impossible de charger le script de l’extension depuis le chemin : « %s ». Il "
-"semble y avoir une erreur dans le code, merci de vérifier la syntaxe."
+"Impossible de charger le script de l’extension depuis le chemin : « %s ». "
+"Cela peut être dû à une erreur de programmation dans ce script.\n"
+"L'extension « %s » a été désactivée pour prévenir de nouvelles erreures."
#: editor/editor_node.cpp
msgid ""
@@ -3092,6 +3092,10 @@ msgid "About"
msgstr "À propos"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Soutenir le développement de Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Lancer le projet."
@@ -3198,7 +3202,7 @@ msgstr ""
"personnalisé à l'exportation (ajout de modules, modification du fichier "
"AndroidManifest.xml, etc.).\n"
"Notez que pour faire des compilations personnalisées au lieu d'utiliser des "
-"APKs pré-construits, l'option \"Use Custom Build\" doit être activée dans le "
+"APKs préconstruits, l'option \"Use Custom Build\" doit être activée dans le "
"Preset d'exportation Android."
#: editor/editor_node.cpp
@@ -5338,20 +5342,10 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"L'éditeur Godot a été compilé sans support du ray tracing, les lightmaps ne "
-"peuvent pas être pré-calculées."
+"peuvent pas être précalculées."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -5359,7 +5353,7 @@ msgstr "Précalculer les lightmaps"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Select lightmap bake file:"
-msgstr "Sélectionnez le fichier de pré-calcul de lightmap :"
+msgstr "Sélectionnez le fichier de précalcul de lightmap :"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -10291,7 +10285,7 @@ msgstr "Bouton de souris"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nom d'action invalide. Il ne peut être vide ni contenir « / », « : », « = », "
@@ -11809,7 +11803,7 @@ msgstr ""
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr "Commencer le pré-calcul"
+msgstr "Commencer le précalcul"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
diff --git a/editor/translations/ga.po b/editor/translations/ga.po
index 134331d7bf..4da29e17ba 100644
--- a/editor/translations/ga.po
+++ b/editor/translations/ga.po
@@ -2445,7 +2445,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2851,6 +2851,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5010,16 +5014,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9704,7 +9699,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/gl.po b/editor/translations/gl.po
index 816b4234fa..f4394da9da 100644
--- a/editor/translations/gl.po
+++ b/editor/translations/gl.po
@@ -2544,7 +2544,7 @@ msgstr ""
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Non se puido cargar Script de característica adicional (Addon) na ruta: "
@@ -2993,6 +2993,10 @@ msgid "About"
msgstr "Acerca De"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Reproduce o proxecto."
@@ -5181,16 +5185,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9995,7 +9990,7 @@ msgstr "Botón do Rato"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nome de acción inválido. O nome non pode estar baleiro, nin conter '/', ':', "
diff --git a/editor/translations/he.po b/editor/translations/he.po
index 831c34978c..08780f2e03 100644
--- a/editor/translations/he.po
+++ b/editor/translations/he.po
@@ -2544,7 +2544,7 @@ msgstr "×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה מנתיב: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה מנתיב: '%s' נר××” שיש שגי××” בקוד, ×× × ×‘×“×•×§ ×ת "
@@ -2980,6 +2980,10 @@ msgid "About"
msgstr "על ×ודות"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "הרצת המיז×."
@@ -5230,16 +5234,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10172,7 +10167,7 @@ msgstr "כפתור עכבר"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/hi.po b/editor/translations/hi.po
index d10b2e81c0..30381cf861 100644
--- a/editor/translations/hi.po
+++ b/editor/translations/hi.po
@@ -2522,7 +2522,7 @@ msgstr "पथ से à¤à¤¡à¤‘न सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ लोड करà
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"रासà¥à¤¤à¥‡ से à¤à¤¡à¤‘न सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ लोड करने में असमरà¥à¤¥: '% à¤à¤¸' कोड में गड़बड़ी लगती है, कृपया सिंटेकà¥à¤¸ की "
@@ -2961,6 +2961,10 @@ msgid "About"
msgstr "के बारे में"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "पà¥à¤°à¥‹à¤œà¥‡à¤•à¥à¤Ÿ चलाà¤à¤‚।"
@@ -5152,16 +5156,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9939,7 +9934,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/hr.po b/editor/translations/hr.po
index 7fec3f22ac..826d73fda0 100644
--- a/editor/translations/hr.po
+++ b/editor/translations/hr.po
@@ -2457,7 +2457,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2863,6 +2863,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5024,16 +5028,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9725,7 +9720,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index ff223c33d3..698e87b776 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -2564,7 +2564,7 @@ msgstr "Nem sikerült az addon szkript betöltése a következő útvonalról: '
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Nem lehet betölteni az addon szkriptet a(z) '%s' útvonalról. Úgy tűnik, hiba "
@@ -3009,6 +3009,10 @@ msgid "About"
msgstr "Névjegy"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Projekt futtatása."
@@ -5203,16 +5207,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9908,7 +9903,7 @@ msgstr "Egérgomb"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/id.po b/editor/translations/id.po
index a53c0a385a..8d20cb79fb 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -2564,7 +2564,7 @@ msgstr "Tidak bisa memuat script addon dari lokasi: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Tidak dapat memuat script addon dari path: '%s' Mungkin ada kesalahan dalam "
@@ -3011,6 +3011,10 @@ msgid "About"
msgstr "Tentang"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Mainkan proyek."
@@ -5231,18 +5235,9 @@ msgstr ""
"persegi [0.0,1.0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Editor Godot di-build tanpa dukungan ray tracing, sehingga lightmaps tidak "
"dapat di-bake."
@@ -10159,7 +10154,7 @@ msgstr "Tombol Mouse"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nama aksi tidak valid. Tidak boleh kosong atau mengandung '/', ':', '=', "
diff --git a/editor/translations/is.po b/editor/translations/is.po
index 92b71ba410..8f3e11c207 100644
--- a/editor/translations/is.po
+++ b/editor/translations/is.po
@@ -2482,7 +2482,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2891,6 +2891,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5066,16 +5070,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9816,7 +9811,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/it.po b/editor/translations/it.po
index c98565ba1b..d8a4db264f 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -63,7 +63,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-14 11:20+0000\n"
+"PO-Revision-Date: 2021-06-02 09:04+0000\n"
"Last-Translator: Riteo Siuga <lorenzocerqua@tutanota.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot/it/>\n"
@@ -1315,15 +1315,15 @@ msgstr "Altoparlanti"
#: editor/editor_audio_buses.cpp
msgid "Add Effect"
-msgstr "Aggiungi effetto"
+msgstr "Aggiungi un effetto"
#: editor/editor_audio_buses.cpp
msgid "Rename Audio Bus"
-msgstr "Rinomina bus audio"
+msgstr "Rinomina un bus audio"
#: editor/editor_audio_buses.cpp
msgid "Change Audio Bus Volume"
-msgstr "Cambia il volume del bus audio"
+msgstr "Cambia il volume di un bus audio"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Solo"
@@ -1334,6 +1334,7 @@ msgid "Toggle Audio Bus Mute"
msgstr "Commuta l'ammutolimento di un bus audio"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Toggle Audio Bus Bypass Effects"
msgstr "Commuta bypass effetti del bus audio"
@@ -1366,6 +1367,7 @@ msgid "Mute"
msgstr "Muto"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Bypass"
msgstr "Bypassa"
@@ -1501,26 +1503,32 @@ msgid "Must not collide with an existing global constant name."
msgstr "Non deve collidere con il nome di una costante globale esistente."
#: editor/editor_autoload_settings.cpp
+#, fuzzy
msgid "Keyword cannot be used as an autoload name."
msgstr "Una parola chiave non può essere utilizzata come nome di un Autoload."
#: editor/editor_autoload_settings.cpp
+#, fuzzy
msgid "Autoload '%s' already exists!"
msgstr "L'Autoload \"%s\" esiste già!"
#: editor/editor_autoload_settings.cpp
+#, fuzzy
msgid "Rename Autoload"
msgstr "Rinomina un Autoload"
#: editor/editor_autoload_settings.cpp
+#, fuzzy
msgid "Toggle AutoLoad Globals"
msgstr "Commuta AutoLoad globals"
#: editor/editor_autoload_settings.cpp
+#, fuzzy
msgid "Move Autoload"
msgstr "Sposta un Autoload"
#: editor/editor_autoload_settings.cpp
+#, fuzzy
msgid "Remove Autoload"
msgstr "Rimuovi un Autoload"
@@ -1712,25 +1720,29 @@ msgstr "Editor 3D"
#: editor/editor_feature_profile.cpp
msgid "Script Editor"
-msgstr "Editor script"
+msgstr "Editor degli script"
#: editor/editor_feature_profile.cpp
+#, fuzzy
msgid "Asset Library"
msgstr "Libreria degli asset"
#: editor/editor_feature_profile.cpp
msgid "Scene Tree Editing"
-msgstr "Editor delle scene"
+msgstr "Modifica delle scene"
#: editor/editor_feature_profile.cpp
+#, fuzzy
msgid "Node Dock"
msgstr "Riquadro dei nodi"
#: editor/editor_feature_profile.cpp
+#, fuzzy
msgid "FileSystem Dock"
msgstr "Riquadro del FileSystem"
#: editor/editor_feature_profile.cpp
+#, fuzzy
msgid "Import Dock"
msgstr "Riquadro d'importazione"
@@ -1739,6 +1751,7 @@ msgid "Erase profile '%s'? (no undo)"
msgstr "Eliminare il profilo \"%s\"? (non annullabile)"
#: editor/editor_feature_profile.cpp
+#, fuzzy
msgid "Profile must be a valid filename and must not contain '.'"
msgstr ""
"Il profilo deve essere un nome di file valido e non può contenere \".\""
@@ -2014,16 +2027,17 @@ msgid ""
"There are multiple importers for different types pointing to file %s, import "
"aborted"
msgstr ""
-"Ci sono importatori multipli per tipi differenti che puntano al file %s, "
+"Esistono più importatori per tipi diversi che puntano al file %s, "
"importazione annullata"
#: editor/editor_file_system.cpp
+#, fuzzy
msgid "(Re)Importing Assets"
msgstr "Reimportazione degli asset"
#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
msgid "Top"
-msgstr "In alto"
+msgstr "In cima"
#: editor/editor_help.cpp
msgid "Class:"
@@ -2043,6 +2057,7 @@ msgid "Description"
msgstr "Descrizione"
#: editor/editor_help.cpp
+#, fuzzy
msgid "Online Tutorials"
msgstr "Tutorial Online"
@@ -2109,7 +2124,7 @@ msgstr "Cerca aiuto"
#: editor/editor_help_search.cpp
msgid "Case Sensitive"
-msgstr "Distinzione maiuscole/minuscole"
+msgstr "Distingui tra maiuscole e minuscole"
#: editor/editor_help_search.cpp
msgid "Show Hierarchy"
@@ -2181,7 +2196,7 @@ msgstr "Imposta"
#: editor/editor_inspector.cpp
msgid "Set Multiple:"
-msgstr "Imposta multiplo:"
+msgstr "Imposta più valori:"
#: editor/editor_log.cpp
msgid "Output:"
@@ -2202,6 +2217,7 @@ msgid "Clear"
msgstr "Rimuovi tutto"
#: editor/editor_log.cpp
+#, fuzzy
msgid "Clear Output"
msgstr "Svuota output"
@@ -2606,14 +2622,14 @@ msgstr ""
"\"."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Impossibile caricare uno script aggiuntivo dal percorso: \"%s\" Sembra "
-"esserci un errore nel codice, controlla la sintassi."
+"esserci un errore nel codice, controlla la sintassi.\n"
+"Disabilitata l'aggiunta di '%s' per prevenire ulteriori errori."
#: editor/editor_node.cpp
msgid ""
@@ -3060,6 +3076,10 @@ msgid "About"
msgstr "Informazioni su Godot"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Supporta lo Sviluppo di Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Esegui il progetto."
@@ -3903,7 +3923,7 @@ msgstr "Cartella/File successivo"
#: editor/filesystem_dock.cpp
msgid "Re-Scan Filesystem"
-msgstr "Re-Scan Filesystem"
+msgstr "Riscansiona il Filesystem"
#: editor/filesystem_dock.cpp
msgid "Toggle Split Mode"
@@ -5301,18 +5321,9 @@ msgstr ""
"all'interno nella regione [0.0,1.0] quadra."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Godot Editor è stato costruito senza il supporto per il ray tracing, quindi "
"il baking delle lightmaps non è possibile."
@@ -7650,9 +7661,12 @@ msgid "View Rotation Locked"
msgstr "Rotazione Vista Bloccata"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid ""
"To zoom further, change the camera's clipping planes (View -> Settings...)"
msgstr ""
+"Per maggiore zoom, cambia i piani del clip della videocamera (Vista -> "
+"Impostazioni)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
@@ -10248,7 +10262,7 @@ msgstr "Pulsante Mouse"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nome dell'azione non valido. Non può essere vuoto o contenere \"/\", \":\", "
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index 138cee8cb3..b47b97b20e 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -32,12 +32,13 @@
# Wataru Onuki <bettawat@yahoo.co.jp>, 2020, 2021.
# sporeball <sporeballdev@gmail.com>, 2020.
# BinotaLIU <me@binota.org>, 2020, 2021.
+# 都築 æœ¬æˆ <motonari728@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-10 15:32+0000\n"
-"Last-Translator: nitenook <admin@alterbaum.net>\n"
+"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"Last-Translator: 都築 æœ¬æˆ <motonari728@gmail.com>\n"
"Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/"
"godot/ja/>\n"
"Language: ja\n"
@@ -2562,14 +2563,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "パス '%s' ã‹ã‚‰ã‚¢ãƒ‰ã‚ªãƒ³ã‚¹ã‚¯ãƒªãƒ—トを読込ã‚ã¾ã›ã‚“。"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"パス '%s' ã‹ã‚‰ã‚¢ãƒ‰ã‚ªãƒ³ã‚¹ã‚¯ãƒªãƒ—トを読ã¿è¾¼ã‚ã¾ã›ã‚“。コードã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚‹å¯èƒ½æ€§"
-"ãŒã‚りã¾ã™ã€‚構文を確èªã—ã¦ãã ã•ã„。"
+"ãŒã‚りã¾ã™ã€‚\n"
+"構文を確èªã—ã¦ãã ã•ã„。"
#: editor/editor_node.cpp
msgid ""
@@ -3013,6 +3014,10 @@ msgid "About"
msgstr "概è¦"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Godotã®é–‹ç™ºã‚’サãƒãƒ¼ãƒˆã™ã‚‹"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "プロジェクトを実行。"
@@ -4099,9 +4104,8 @@ msgid "Importer:"
msgstr "インãƒãƒ¼ãƒˆ"
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Reset to Defaults"
-msgstr "デフォルトを読込む"
+msgstr "デフォルトã«ãƒªã‚»ãƒƒãƒˆã™ã‚‹"
#: editor/import_dock.cpp
msgid "Keep File (No Import)"
@@ -5239,18 +5243,9 @@ msgstr ""
"ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"GodotエディタãŒãƒ¬ã‚¤ãƒˆãƒ¬ãƒ¼ã‚·ãƒ³ã‚°ã«å¯¾å¿œã›ãšã«ãƒ“ルドã•れã¦ãŠã‚Šã€ãƒ©ã‚¤ãƒˆãƒžãƒƒãƒ—ã®ãƒ™"
"イクãŒã§ãã¾ã›ã‚“。"
@@ -10145,7 +10140,7 @@ msgstr "マウスボタン"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"アクションåãŒç„¡åйã§ã™ã€‚空ã«ã—ãŸã‚Šã€'/'ã€':'ã€'='ã€'\\'ã€'\"'ã‚’å«ã‚ã‚‹ã“ã¨ã¯ã§"
diff --git a/editor/translations/ka.po b/editor/translations/ka.po
index a2972e9c1e..7c6f378627 100644
--- a/editor/translations/ka.po
+++ b/editor/translations/ka.po
@@ -2562,7 +2562,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2975,6 +2975,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5192,16 +5196,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10022,7 +10017,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/km.po b/editor/translations/km.po
index 25785c2415..21149c748f 100644
--- a/editor/translations/km.po
+++ b/editor/translations/km.po
@@ -2441,7 +2441,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2847,6 +2847,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5001,16 +5005,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9689,7 +9684,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index 287df00aab..cc41ee5d41 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -26,7 +26,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-03 06:13+0000\n"
+"PO-Revision-Date: 2021-05-19 20:16+0000\n"
"Last-Translator: Myeongjin Lee <aranet100@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot/ko/>\n"
@@ -2544,14 +2544,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "ë‹¤ìŒ ê²½ë¡œì—서 애드온 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 ì—†ìŒ: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"ë‹¤ìŒ ê²½ë¡œì—서 애드온 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 ì—†ìŒ: '%s' ì½”ë“œì— ì˜¤ë¥˜ê°€ 있는 것 ê°™"
-"습니다. ë¬¸ë²•ì„ í™•ì¸í•´ë³´ì„¸ìš”."
+"ë‹¤ìŒ ê²½ë¡œì—서 애드온 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 ì—†ìŒ: '%s' 해당 스í¬ë¦½íŠ¸ì˜ ì½”ë“œì— "
+"오류가 있는 것 같습니다.\n"
+"추가 오류를 방지하려면 '%s'ì—서 ì• ë“œì˜¨ì„ ë¹„í™œì„±í™”í•˜ì„¸ìš”."
#: editor/editor_node.cpp
msgid ""
@@ -2991,6 +2991,10 @@ msgid "About"
msgstr "ì •ë³´"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Godot 개발 ì§€ì›"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "프로ì íŠ¸ë¥¼ 실행합니다."
@@ -5204,20 +5208,10 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
-"Godot 편집기가 ë ˆì´ íŠ¸ë ˆì´ì‹± ì§€ì› ì—†ì´ ë¹Œë“œë˜ì–´ 있어, ë¼ì´íŠ¸ë§µì´ êµ¬ì›Œì§ˆ 수 ì—†"
-"습니다."
+"Godot 편집기는 ë ˆì´ íŠ¸ë ˆì´ì‹± ì§€ì› ì—†ì´ ë¹Œë“œë˜ì—ˆìœ¼ë©° ë¼ì´íŠ¸ë§µì€ êµ¬ìš¸ 수 없습니"
+"다."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -10069,7 +10063,7 @@ msgstr "마우스 버튼"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"ìž˜ëª»ëœ ì•¡ì…˜ ì´ë¦„. 공백ì´ê±°ë‚˜, '/' , ':', '=', '\\', '\"' 를 í¬í•¨í•˜ë©´ 안 ë©ë‹ˆ"
@@ -13057,6 +13051,19 @@ msgid "Constants cannot be modified."
msgstr "ìƒìˆ˜ëŠ” 수정할 수 없습니다."
#~ msgid ""
+#~ "Godot editor was built without ray tracing support; lightmaps can't be "
+#~ "baked.\n"
+#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta "
+#~ "emulation on Godot.app in the application settings\n"
+#~ "then restart the editor."
+#~ msgstr ""
+#~ "Godot 편집기는 ë ˆì´ íŠ¸ë ˆì´ì‹± ì§€ì› ì—†ì´ ë¹Œë“œë˜ì—ˆìœ¼ë©° ë¼ì´íŠ¸ë§µì€ êµ¬ìš¸ 수 ì—†"
+#~ "습니다.\n"
+#~ "Apple Silicon ê¸°ë°˜ì˜ Macì„ ì‚¬ìš© ì¤‘ì¸ ê²½ìš°, 애플리케ì´ì…˜ 설정ì—서 Godot.app"
+#~ "ì˜ Rosetta ì—뮬레ì´ì…˜ 강제로\n"
+#~ "시ë„하고 나서 편집기를 다시 시작하세요."
+
+#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
#~ "InterpolatedCamera는 ë” ì´ìƒ 사용ë˜ì§€ 않으며 Godot 4.0ì—서 제거ë©ë‹ˆë‹¤."
diff --git a/editor/translations/lt.po b/editor/translations/lt.po
index 6fdb5257d3..b04d49c871 100644
--- a/editor/translations/lt.po
+++ b/editor/translations/lt.po
@@ -2514,7 +2514,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2927,6 +2927,10 @@ msgid "About"
msgstr "Apie"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5160,16 +5164,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9995,7 +9990,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/lv.po b/editor/translations/lv.po
index 832a099a1c..f51c38c6b8 100644
--- a/editor/translations/lv.po
+++ b/editor/translations/lv.po
@@ -2487,7 +2487,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2893,6 +2893,10 @@ msgid "About"
msgstr "Par"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5053,16 +5057,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9820,7 +9815,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/mi.po b/editor/translations/mi.po
index f3726999ff..6beaf559b3 100644
--- a/editor/translations/mi.po
+++ b/editor/translations/mi.po
@@ -2433,7 +2433,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2839,6 +2839,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -4993,16 +4997,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9681,7 +9676,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/mk.po b/editor/translations/mk.po
index 1c2910404c..6cb5e626cb 100644
--- a/editor/translations/mk.po
+++ b/editor/translations/mk.po
@@ -2440,7 +2440,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2846,6 +2846,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5000,16 +5004,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9688,7 +9683,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/ml.po b/editor/translations/ml.po
index ca6259e4d2..0b3a3e2f85 100644
--- a/editor/translations/ml.po
+++ b/editor/translations/ml.po
@@ -2445,7 +2445,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2851,6 +2851,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5008,16 +5012,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9698,7 +9693,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/mr.po b/editor/translations/mr.po
index 1f44ad0b6a..7b2683f181 100644
--- a/editor/translations/mr.po
+++ b/editor/translations/mr.po
@@ -2440,7 +2440,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2846,6 +2846,10 @@ msgid "About"
msgstr "आमचà¥à¤¯à¤¾ बदà¥à¤¦à¤²"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5000,16 +5004,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9689,7 +9684,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/ms.po b/editor/translations/ms.po
index d2cc1c47d9..0dc54a314a 100644
--- a/editor/translations/ms.po
+++ b/editor/translations/ms.po
@@ -9,11 +9,12 @@
# Muhammad Hazim bin Hafizalshah <muhammadhazimhafizalshah@gmail.com>, 2020.
# keviinx <keviinx@yahoo.com>, 2020.
# Keviindran Ramachandran <keviinx@yahoo.com>, 2020, 2021.
+# Jacque Fresco <aidter@use.startmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-10 15:32+0000\n"
+"PO-Revision-Date: 2021-05-29 13:49+0000\n"
"Last-Translator: Keviindran Ramachandran <keviinx@yahoo.com>\n"
"Language-Team: Malay <https://hosted.weblate.org/projects/godot-engine/godot/"
"ms/>\n"
@@ -2552,7 +2553,7 @@ msgstr "Tidak dapat memuatkan skrip addon dari laluan: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Tidak dapat memuat skrip addon dari laluan: '%s' Nampaknya terdapat ralat "
@@ -3030,6 +3031,10 @@ msgid "About"
msgstr "Tentang"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Sokong Pembangunan Godot"
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "Play the project."
msgstr "Main projek."
@@ -4413,15 +4418,15 @@ msgstr "Sunting Poligon"
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid "Insert Point"
-msgstr ""
+msgstr "Masukkan Titik"
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid "Edit Polygon (Remove Point)"
-msgstr ""
+msgstr "Sunting Poligon (Keluarkan Titik)"
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid "Remove Polygon And Point"
-msgstr ""
+msgstr "Keluarkan Poligon Dan Titik"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
@@ -4429,38 +4434,38 @@ msgstr ""
#: editor/plugins/animation_state_machine_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Add Animation"
-msgstr ""
+msgstr "Tambah Animasi"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Load..."
-msgstr ""
+msgstr "Muatkan..."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Move Node Point"
-msgstr ""
+msgstr "Pindahkan Titik Nod"
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Change BlendSpace1D Limits"
-msgstr ""
+msgstr "Tukar Had-had BlendSpace1D"
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Change BlendSpace1D Labels"
-msgstr ""
+msgstr "Tukar Label-label BlendSpace1D"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
#: editor/plugins/animation_state_machine_editor.cpp
msgid "This type of node can't be used. Only root nodes are allowed."
-msgstr ""
+msgstr "Nod jenis ini tidak boleh digunakan. Hanya nod-nod akar dibenarkan."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Add Node Point"
-msgstr ""
+msgstr "Tambah Titik Nod"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
@@ -4469,11 +4474,11 @@ msgstr "Tambah Titik Animasi"
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Remove BlendSpace1D Point"
-msgstr ""
+msgstr "Keluarkan Titik BlendSpace1D"
#: editor/plugins/animation_blend_space_1d_editor.cpp
msgid "Move BlendSpace1D Node Point"
-msgstr ""
+msgstr "Pindahkan Titik Nod BlendSpace1D"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
@@ -4483,11 +4488,15 @@ msgid ""
"AnimationTree is inactive.\n"
"Activate to enable playback, check node warnings if activation fails."
msgstr ""
+"AnimationTree tidak aktif.\n"
+"Aktifkan untuk membenarkan main balik, periksa amaran nod jika pengaktifan "
+"gagal."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
+#, fuzzy
msgid "Set the blending position within the space"
-msgstr ""
+msgstr "Tetapkan kedudukan pengadunan dalam ruang"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
@@ -4829,15 +4838,15 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "1 step"
-msgstr ""
+msgstr "1 langkah"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "2 steps"
-msgstr ""
+msgstr "2 langkah"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "3 steps"
-msgstr ""
+msgstr "3 langkah"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Differences Only"
@@ -5345,16 +5354,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -8201,15 +8201,15 @@ msgstr "Tidak Aktif"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Tab 1"
-msgstr ""
+msgstr "Tab 1"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Tab 2"
-msgstr ""
+msgstr "Tab 2"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Tab 3"
-msgstr ""
+msgstr "Tab 3"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Editable Item"
@@ -8754,7 +8754,7 @@ msgstr ""
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "(GLES3 only)"
-msgstr ""
+msgstr "(GLES3 sahaja)"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Add Output"
@@ -10055,7 +10055,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
@@ -10121,11 +10121,11 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid "X Button 1"
-msgstr ""
+msgstr "Butang X 1"
#: editor/project_settings_editor.cpp
msgid "X Button 2"
-msgstr ""
+msgstr "Butang X 2"
#: editor/project_settings_editor.cpp
msgid "Joypad Axis Index:"
@@ -11023,7 +11023,7 @@ msgstr ""
#: editor/script_create_dialog.cpp
msgid "Allowed: a-z, A-Z, 0-9, _ and ."
-msgstr ""
+msgstr "Benarkan: a-z, A-Z, 0-9, _ dan ."
#: editor/script_create_dialog.cpp
msgid "Built-in script (into scene file)."
@@ -12360,7 +12360,7 @@ msgstr ""
#: scene/2d/joints_2d.cpp
msgid "Node A and Node B must be PhysicsBody2Ds"
-msgstr ""
+msgstr "Nod A dan Nod B mestilah PhysicsBody2Ds"
#: scene/2d/joints_2d.cpp
msgid "Node A must be a PhysicsBody2D"
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index b0d147350a..7d6077e69c 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -17,12 +17,13 @@
# Petter Reinholdtsen <pere-weblate@hungry.com>, 2019, 2020.
# Patrick Sletvold <patricksletvold@hotmail.com>, 2021.
# Kristoffer <kskau93@gmail.com>, 2021.
+# Lili Zoey <sayaks1@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-03-31 03:53+0000\n"
-"Last-Translator: Kristoffer <kskau93@gmail.com>\n"
+"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"Last-Translator: Lili Zoey <sayaks1@gmail.com>\n"
"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/godot-"
"engine/godot/nb_NO/>\n"
"Language: nb\n"
@@ -30,7 +31,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.6-dev\n"
+"X-Generator: Weblate 4.7-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -188,9 +189,8 @@ msgid "Anim Multi Change Keyframe Value"
msgstr "Anim Endre flere Nøkkelbildeverdier"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Anim Multi Change Call"
-msgstr "Anim Forandre Kall"
+msgstr "Anim Forandre flere Kall"
#: editor/animation_track_editor.cpp
msgid "Change Animation Length"
@@ -924,9 +924,8 @@ msgid "Signals"
msgstr "Signaler"
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Filter signals"
-msgstr "Filtrer Filer..."
+msgstr "Filtrer Signaler"
#: editor/connections_dialog.cpp
msgid "Are you sure you want to remove all connections from this signal?"
@@ -939,9 +938,8 @@ msgid "Disconnect All"
msgstr "Koble Fra"
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Edit..."
-msgstr "Rediger"
+msgstr "Rediger..."
#: editor/connections_dialog.cpp
#, fuzzy
@@ -1496,7 +1494,7 @@ msgstr ""
#: editor/editor_autoload_settings.cpp
msgid "Keyword cannot be used as an autoload name."
-msgstr ""
+msgstr "Nøkkelord kan ikke brukes som autoloadnavn."
#: editor/editor_autoload_settings.cpp
msgid "Autoload '%s' already exists!"
@@ -2641,7 +2639,7 @@ msgstr "Kan ikke laste addon-skript fra bane: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Kunne ikke laste tillegsskript fra sti: '%s' Script er ikke i verktøymodus."
@@ -3103,6 +3101,10 @@ msgid "About"
msgstr "Om"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Spill prosjektet."
@@ -4129,7 +4131,7 @@ msgstr "Legg til i Gruppe"
#: editor/groups_editor.cpp
msgid "Empty groups will be automatically removed."
-msgstr ""
+msgstr "Tomme grupper vil automatisk bli fjernet."
#: editor/groups_editor.cpp
msgid "Group Editor"
@@ -4969,11 +4971,11 @@ msgstr "Legg til node"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "End"
-msgstr ""
+msgstr "Slutt"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Immediate"
-msgstr ""
+msgstr "Umiddelbart"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Sync"
@@ -5331,11 +5333,11 @@ msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Name (A-Z)"
-msgstr ""
+msgstr "Navn (A-Z)"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Name (Z-A)"
-msgstr ""
+msgstr "Navn (Z-A)"
#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
@@ -5445,16 +5447,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -8829,9 +8822,8 @@ msgid ""
msgstr ""
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Delete selected Rect."
-msgstr "Slett valgte filer?"
+msgstr "Slett valgte Rect."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid ""
@@ -10456,7 +10448,7 @@ msgstr "Museknapp"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index d28d0fbb55..41a5cf103a 100644
--- a/editor/translations/nl.po
+++ b/editor/translations/nl.po
@@ -43,11 +43,14 @@
# kitfka <philipthuijs@gmail.com>, 2020.
# Mike van Leeuwen <mkvanleeuwen@gmail.com>, 2020.
# marnicq van loon <marnicqvanloon@gmail.com>, 2020.
+# T-rex08 <ipadtriceratops@gmail.com>, 2021.
+# Dwarffish <hoogvlietjohan@gmail.com>, 2021.
+# Arthur de Roos <arthur.de.roos@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-02-05 23:44+0000\n"
+"PO-Revision-Date: 2021-05-29 13:49+0000\n"
"Last-Translator: Stijn Hinlopen <f.a.hinlopen@gmail.com>\n"
"Language-Team: Dutch <https://hosted.weblate.org/projects/godot-engine/godot/"
"nl/>\n"
@@ -56,7 +59,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.5-dev\n"
+"X-Generator: Weblate 4.7-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -1197,11 +1200,11 @@ msgstr "Gouden Sponsors"
#: editor/editor_about.cpp
msgid "Silver Sponsors"
-msgstr "Zilveren Sponsoren"
+msgstr "Zilveren Sponsors"
#: editor/editor_about.cpp
msgid "Bronze Sponsors"
-msgstr "Bronzen Sponsoren"
+msgstr "Bronzen Sponsors"
#: editor/editor_about.cpp
msgid "Mini Sponsors"
@@ -1643,34 +1646,31 @@ msgstr ""
"'Driver Fallback Enabled' uit."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'PVRTC' texture compression for GLES2. Enable "
"'Import Pvrtc' in Project Settings."
msgstr ""
-"Doelplatform vereist 'ETC' textuurcompressie voor GLES2. Schakel 'Import "
+"Doelplatform vereist 'PVRTC' textuurcompressie voor GLES2. Schakel 'Import "
"Etc' in bij de Projectinstellingen."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'ETC2' or 'PVRTC' texture compression for GLES3. "
"Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings."
msgstr ""
-"Doelplatform vereist 'ETC2' textuurcompressie voor GLES3. Schakel 'Import "
-"Etc 2' in de Projectinstellingen in."
+"Doelplatform vereist 'ETC2' of 'PVRTC' textuurcompressie voor GLES3. Schakel "
+"'Import Etc 2' of 'Import Pvrtc' in de Projectinstellingen in."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'PVRTC' texture compression for the driver fallback "
"to GLES2.\n"
"Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback "
"Enabled'."
msgstr ""
-"Doelplatform vereist 'ETC' textuurcompressie zodat het stuurprogramma kan "
+"Doelplatform vereist 'PVRTC' textuurcompressie zodat het stuurprogramma kan "
"terugvallen op GLES2.\n"
-"Schakel 'Import Etc' in bij de Projectinstellingen, of schakel de optie "
+"Schakel 'Import Pvrtc' in bij de Projectinstellingen, of schakel de optie "
"'Driver Fallback Enabled' uit."
#: editor/editor_export.cpp platform/android/export/export.cpp
@@ -1931,7 +1931,7 @@ msgstr "Favoriet Omschakelen"
#: editor/editor_file_dialog.cpp
msgid "Toggle Mode"
-msgstr "Modus omschakelen"
+msgstr "Modus wisselen"
#: editor/editor_file_dialog.cpp
msgid "Focus Path"
@@ -2030,7 +2030,7 @@ msgstr "Beschrijving"
#: editor/editor_help.cpp
msgid "Online Tutorials"
-msgstr "Online Zelfstudie"
+msgstr "Online Handleidingen"
#: editor/editor_help.cpp
msgid "Properties"
@@ -2577,24 +2577,22 @@ msgstr ""
"mislukt."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Unable to find script field for addon plugin at: '%s'."
-msgstr ""
-"Onmogelijk om scriptveld te vinden voor de plugin op: 'res://addons/%s'."
+msgstr "Onmogelijk om scriptveld te vinden voor de plugin op: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
msgstr "Volgend script kon niet geladen worden: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Script kon niet geladen worden van het pad: '%s'. Er lijkt een fout in de "
-"code te zijn, controleer de syntax."
+"Extra script kon niet geladen worden van het pad: '%s'. Dit kan veroorzaakt "
+"worden door een fout in dat script.\n"
+"Schakel de extra uit op '%s' om toekomstige fouten te vermijden."
#: editor/editor_node.cpp
msgid ""
@@ -2886,7 +2884,6 @@ msgid "Small Deploy with Network Filesystem"
msgstr "Kleine uitrol met netwerkbestandssysteem"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, using one-click deploy for Android will only "
"export an executable without the project data.\n"
@@ -2895,11 +2892,11 @@ msgid ""
"On Android, deploying will use the USB cable for faster performance. This "
"option speeds up testing for projects with large assets."
msgstr ""
-"Wanneer deze optie is ingeschakeld, zal export of deploy een minimaal "
-"uitvoerbaar bestand creëren.\n"
+"Wanneer deze optie is ingeschakeld, zal op Android een uitvoerbaar bestand "
+"zonder de project data geëxporteerd worden.\n"
"Het bestandssysteem wordt beschikbaar gesteld aan het project door de editor "
"over het netwerk.\n"
-"Op Android zal deploy de USB verbinding gebruiken voor hogere prestaties. "
+"Op Android zal de USB verbinding gebruikt worden voor hogere prestaties. "
"Deze optie versnelt het testen van spellen met veel data."
#: editor/editor_node.cpp
@@ -2907,26 +2904,24 @@ msgid "Visible Collision Shapes"
msgstr "Botsingsvormen tonen"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, collision shapes and raycast nodes (for 2D and "
"3D) will be visible in the running project."
msgstr ""
-"Botsingsdetectievormen en raycast knopen (voor 2D en 3D) zullen zichtbaar "
-"zijn in het draaiend spel wanneer deze optie aan staat."
+"Wanneer deze optie aan staat zullen botsingsdetectievormen en raycast knopen "
+"(voor 2D en 3D) zichtbaar zijn in het draaiend spel."
#: editor/editor_node.cpp
msgid "Visible Navigation"
msgstr "Navigatie zichtbaar"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, navigation meshes and polygons will be visible "
"in the running project."
msgstr ""
-"Navigatie meshes en polygonen zijn zichtbaar in het draaiend spel wanneer "
-"deze optie aanstaat."
+"Navigatie vormen zijn zichtbaar in het draaiend spel wanneer deze optie "
+"aanstaat."
#: editor/editor_node.cpp
msgid "Synchronize Scene Changes"
@@ -2949,17 +2944,16 @@ msgid "Synchronize Script Changes"
msgstr "Veranderingen in scripts synchroniseren"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, any script that is saved will be reloaded in "
"the running project.\n"
"When used remotely on a device, this is more efficient when the network "
"filesystem option is enabled."
msgstr ""
-"Wanneer deze optie aanstaat wordt ieder script dat wordt opgeslagen "
-"toegepast op het draaiend spel.\n"
+"Wanneer deze optie aanstaat wordt ieder script dat is opgeslagen herlopen in "
+"het draaiende spel.\n"
"Wanneer dit op afstand wordt gebruikt op een andere machine, is dit "
-"efficiënter met het netwerk bestandssysteem."
+"efficiënter met de netwerk bestandssysteem optie aan."
#: editor/editor_node.cpp editor/script_create_dialog.cpp
msgid "Editor"
@@ -3039,6 +3033,10 @@ msgid "About"
msgstr "Over"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Ondersteun Godot Development"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Speel het project."
@@ -3180,13 +3178,12 @@ msgid "Open & Run a Script"
msgstr "Voer Een Script Uit"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"The following files are newer on disk.\n"
"What action should be taken?"
msgstr ""
"De volgende bestanden zijn nieuwer op de schijf.\n"
-"Welke aktie moet worden genomen?:"
+"Welke actie moet worden genomen?"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
@@ -3448,13 +3445,12 @@ msgid "Add Key/Value Pair"
msgstr "Sleutel/waarde-paar toevoegen"
#: editor/editor_run_native.cpp
-#, fuzzy
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the Export menu or define an existing preset "
"as runnable."
msgstr ""
-"Geen uitvoerbare export preset gevonden voor dit platform.\n"
+"Geen uitvoerbare exporteer preset gevonden voor dit platform.\n"
"Voeg een uitvoerbare preset toe in het exportmenu."
#: editor/editor_run_script.cpp
@@ -3731,6 +3727,8 @@ msgstr ""
msgid ""
"Importing has been disabled for this file, so it can't be opened for editing."
msgstr ""
+"Importeren is uitgeschakeld voor dit bestand, het kan niet worden geopend om "
+"te bewerken."
#: editor/filesystem_dock.cpp
msgid "Cannot move/rename resources root."
@@ -3777,11 +3775,12 @@ msgid ""
"\n"
"Do you wish to overwrite them?"
msgstr ""
-"De volgende bestanden of mappen conflicteren met elementen in '%s':\n"
+"De volgende bestanden of folders conflicteren met de bestanden in de locatie "
+"'%s':\n"
"\n"
"%s\n"
"\n"
-"Wil je deze overschrijven?"
+"Wilt u deze bestanden overschrijven?"
#: editor/filesystem_dock.cpp
msgid "Renaming file:"
@@ -4121,23 +4120,20 @@ msgid "Saving..."
msgstr "Opslaan..."
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Select Importer"
-msgstr "Selecteermodus"
+msgstr "Selecteer Importeren"
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Importer:"
-msgstr "Importeren"
+msgstr "Lader:"
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Reset to Defaults"
-msgstr "Laad standaard"
+msgstr "Reset naar standaard waarden"
#: editor/import_dock.cpp
msgid "Keep File (No Import)"
-msgstr ""
+msgstr "Bestand bewaren (niet importeren)"
#: editor/import_dock.cpp
msgid "%d Files"
@@ -5106,9 +5102,8 @@ msgid "Got:"
msgstr "Gekregen:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Failed SHA-256 hash check"
-msgstr "SHA256-proef mislukt"
+msgstr "SHA256-hash controle mislukt"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5239,14 +5234,12 @@ msgid "Assets ZIP File"
msgstr "Assets ZIP Bestand"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid ""
"Can't determine a save path for lightmap images.\n"
"Save your scene and try again."
msgstr ""
-"Kan geen opslag pad voor de lichtmappen bepalen.\n"
-"Sla jouw scène op (om lichtmappen op te slaan in dezelfde map) of kies een "
-"opslag pad vanaf de BakedLightmap eigenschappen."
+"Kan geen opslagplaats voor de lichtmap afbeeldingen bepalen.\n"
+"Sla uw scène op en probeer opnieuw."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -5265,26 +5258,22 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Failed determining lightmap size. Maximum lightmap size too small?"
msgstr ""
+"Lichtmap grootte bepalen mislukt. Is de maximale lichtmap grootte te klein?"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Some mesh is invalid. Make sure the UV2 channel values are contained within "
"the [0.0,1.0] square region."
msgstr ""
+"Sommige vormen zijn ongeldig. Controleer of de UV2 kanaal waarden binnen het "
+"vierkante [0.0,1.0] bereik zijn."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
+"Godot editor is gemaakt zonder ray tracing ondersteuning, en lichtmappen "
+"kunnen hierdoor niet ingebakken worden."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -5361,7 +5350,7 @@ msgstr "Maak nieuwe horizontale en verticale gidsen"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"
-msgstr "Draaipuntverschuiving van het CanvasItem „%s“ op (%d, %d) zetten"
+msgstr "CanvasItem \"%s\" draaipunt verschuiving instellen als (%d, %d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Rotate %d CanvasItems"
@@ -6691,7 +6680,6 @@ msgid "Shift: Move All"
msgstr "Shift: Beweeg alles"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Shift+Command: Scale"
msgstr "Shift+Ctrl: Schaal"
@@ -7427,9 +7415,8 @@ msgid "Yaw"
msgstr "Yaw"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Size"
-msgstr "Grootte: "
+msgstr "Grootte"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
@@ -9589,7 +9576,7 @@ msgstr ""
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "A reference to an existing uniform."
-msgstr "Een verwijzing naar een bestaande uniform."
+msgstr "Een verwijzing naar een bestaand uniform."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "(Fragment/Light mode only) Scalar derivative function."
@@ -9956,7 +9943,7 @@ msgstr "OpenGL ES 3.0"
#: editor/project_manager.cpp
msgid "Not supported by your GPU drivers."
-msgstr "Niet ondersteund door de GPU drivers op dit systeem."
+msgstr "Niet ondersteund door uw GPU drivers."
#: editor/project_manager.cpp
msgid ""
@@ -10113,9 +10100,8 @@ msgid ""
"Language changed.\n"
"The interface will update after restarting the editor or project manager."
msgstr ""
-"De taal is veranderd. \n"
-"De gebruikersomgeving wordt bij het herstarten van de editor of "
-"projectbeheer bijgewerkt."
+"De taal is veranderd.\n"
+"De gebruikersomgeving wordt bijgewerkt na het herstarten."
#: editor/project_manager.cpp
msgid ""
@@ -10135,9 +10121,8 @@ msgid "Projects"
msgstr "Projecten"
#: editor/project_manager.cpp
-#, fuzzy
msgid "Loading, please wait..."
-msgstr "Mirrors ophalen, even wachten a.u.b..."
+msgstr "Aan het laden, even wachten a.u.b..."
#: editor/project_manager.cpp
msgid "Last Modified"
@@ -10208,7 +10193,7 @@ msgstr "Muis Knop"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Ongeldige actienaam. Kan niet leeg zijn en mag niet '/', ':', '=', '\\' of "
@@ -10511,9 +10496,8 @@ msgid "Plugins"
msgstr "Plugins"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Import Defaults"
-msgstr "Laad standaard"
+msgstr "Laad de standaard waarden"
#: editor/property_editor.cpp
msgid "Preset..."
@@ -10771,7 +10755,6 @@ msgid "Can't paste root node into the same scene."
msgstr "Kan deze operatie niet uitvoeren op knopen uit een vreemde scène!"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Paste Node(s)"
msgstr "Knopen plakken"
@@ -10815,7 +10798,7 @@ msgstr "Knoop tot wortelknoop maken"
#: editor/scene_tree_dock.cpp
msgid "Delete %d nodes and any children?"
-msgstr "%d knopen en hun (eventuele) kinderen verwijderen?"
+msgstr "Verwijder %d knopen en eventuele kinderen?"
#: editor/scene_tree_dock.cpp
msgid "Delete %d nodes?"
@@ -10903,7 +10886,6 @@ msgid "Attach Script"
msgstr "Script toevoegen"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Cut Node(s)"
msgstr "Knopen knippen"
@@ -11421,7 +11403,7 @@ msgstr "Editor Instellingen"
#: editor/settings_config_dialog.cpp
msgid "Shortcuts"
-msgstr "Snelkoppelingen"
+msgstr "Sneltoetsen"
#: editor/settings_config_dialog.cpp
msgid "Binding"
@@ -12308,7 +12290,7 @@ msgstr "Ongeldig Android SDK pad voor custom build in Editor Settings."
#: platform/android/export/export.cpp
msgid "Missing 'build-tools' directory!"
-msgstr ""
+msgstr "'build tools' map ontbreekt!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
@@ -12358,19 +12340,20 @@ msgstr ""
#: platform/android/export/export.cpp
msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
-msgstr ""
+msgstr "\"Export AAB\" is alleen geldig als \"Use Custom Build\" aan staat."
#: platform/android/export/export.cpp
msgid "Invalid filename! Android App Bundle requires the *.aab extension."
msgstr ""
+"Bestandsnaam niet toegestaan! Android App Bundle vereist een *.aab extensie."
#: platform/android/export/export.cpp
msgid "APK Expansion not compatible with Android App Bundle."
-msgstr ""
+msgstr "APK Expansion werkt niet samen met Android App Bundle."
#: platform/android/export/export.cpp
msgid "Invalid filename! Android APK requires the *.apk extension."
-msgstr ""
+msgstr "Bestandsnaam niet toegestaan! Android APK vereist een *.apk extensie."
#: platform/android/export/export.cpp
msgid ""
@@ -12406,13 +12389,15 @@ msgstr ""
#: platform/android/export/export.cpp
msgid "Moving output"
-msgstr ""
+msgstr "Output verplaatsen"
#: platform/android/export/export.cpp
msgid ""
"Unable to copy and rename export file, check gradle project directory for "
"outputs."
msgstr ""
+"Niet in staat om het export bestand te kopiëren en hernoemen. Controleer de "
+"gradle project folder voor outputs."
#: platform/iphone/export/export.cpp
msgid "Identifier is missing."
@@ -12604,6 +12589,9 @@ msgid ""
"Polygon-based shapes are not meant be used nor edited directly through the "
"CollisionShape2D node. Please use the CollisionPolygon2D node instead."
msgstr ""
+"Op polygonen gebaseerde vormen zijn niet bedoeld om rechtstreeks via het "
+"CollisionShape2D-knooppunt te worden gebruikt of bewerkt. Gebruik in plaats "
+"daarvan het CollisionPolygon2D-knooppunt."
#: scene/2d/cpu_particles_2d.cpp
msgid ""
@@ -12615,15 +12603,15 @@ msgstr ""
#: scene/2d/joints_2d.cpp
msgid "Node A and Node B must be PhysicsBody2Ds"
-msgstr ""
+msgstr "Knoop A en Knoop B moeten PhysicsBody2D zijn"
#: scene/2d/joints_2d.cpp
msgid "Node A must be a PhysicsBody2D"
-msgstr ""
+msgstr "Knoop A moet een PhysicsBody2D zijn"
#: scene/2d/joints_2d.cpp
msgid "Node B must be a PhysicsBody2D"
-msgstr ""
+msgstr "Knoop B moet een PhysicsBody2D zijn"
#: scene/2d/joints_2d.cpp
msgid "Joint is not connected to two PhysicsBody2Ds"
@@ -12631,7 +12619,7 @@ msgstr ""
#: scene/2d/joints_2d.cpp
msgid "Node A and Node B must be different PhysicsBody2Ds"
-msgstr ""
+msgstr "Knoop A en Knoop B moeten verschillende PhysicsBody2D's zijn"
#: scene/2d/light_2d.cpp
msgid ""
@@ -12793,14 +12781,12 @@ msgid "Finding meshes and lights"
msgstr ""
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "Geometrie aan het ontleden..."
+msgstr "Geometrie aan het voorbereiden (%d/%d)"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing environment"
-msgstr "Bekijk Omgeving"
+msgstr "Omgeving aan het voorbereiden"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -12808,14 +12794,12 @@ msgid "Generating capture"
msgstr "Bouw Lightmappen"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Saving lightmaps"
-msgstr "Bouw Lightmappen"
+msgstr "Lightmappen aan het opslaan"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Done"
-msgstr "Klaar!"
+msgstr "Klaar"
#: scene/3d/collision_object.cpp
msgid ""
@@ -12966,15 +12950,15 @@ msgstr ""
#: scene/3d/physics_joint.cpp
msgid "Node A and Node B must be PhysicsBodies"
-msgstr ""
+msgstr "Knoop A en Knoop B moeten PhysicsBody's zijn"
#: scene/3d/physics_joint.cpp
msgid "Node A must be a PhysicsBody"
-msgstr ""
+msgstr "Knoop A moet een PhysicsBody zijn"
#: scene/3d/physics_joint.cpp
msgid "Node B must be a PhysicsBody"
-msgstr ""
+msgstr "Knoop B moet een PhysicsBody zijn"
#: scene/3d/physics_joint.cpp
msgid "Joint is not connected to any PhysicsBodies"
@@ -12982,7 +12966,7 @@ msgstr ""
#: scene/3d/physics_joint.cpp
msgid "Node A and Node B must be different PhysicsBodies"
-msgstr ""
+msgstr "Knoop A en Knoop B moeten PhysicsBody's zijn"
#: scene/3d/remote_transform.cpp
msgid ""
diff --git a/editor/translations/or.po b/editor/translations/or.po
index 7dfd981fba..e3b057e2c8 100644
--- a/editor/translations/or.po
+++ b/editor/translations/or.po
@@ -2439,7 +2439,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2845,6 +2845,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -4999,16 +5003,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9687,7 +9682,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index 2ed4d52cc0..6c3367a0ab 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -52,7 +52,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-22 14:39+0000\n"
+"PO-Revision-Date: 2021-05-19 20:16+0000\n"
"Last-Translator: Tomek <kobewi4e@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot/pl/>\n"
@@ -2572,14 +2572,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "Nie można załadować skryptu dodatku z ścieżki: \"%s\"."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Nie można załadować skryptu dodatku ze ścieżki: \"%s\" W kodzie znajduje się "
-"błąd, sprawdź składnię."
+"Nie można załadować skryptu dodatku ze ścieżki: \"%s\". Może to być "
+"spowodowane błędem w skrypcie.\n"
+"Wyłączam dodatek \"%s\" by uniknąć dalszych błędów."
#: editor/editor_node.cpp
msgid ""
@@ -3022,6 +3022,10 @@ msgid "About"
msgstr "O silniku"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Wesprzyj rozwój Godota"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Uruchom projekt."
@@ -3268,11 +3272,11 @@ msgstr "Zmierzono:"
#: editor/editor_profiler.cpp
msgid "Frame Time (sec)"
-msgstr "Czas ramki (sek)"
+msgstr "Czas klatki (sek)"
#: editor/editor_profiler.cpp
msgid "Average Time (sec)"
-msgstr "Åšredni Czas (sek)"
+msgstr "Åšredni czas (sek)"
#: editor/editor_profiler.cpp
msgid "Frame %"
@@ -3284,11 +3288,11 @@ msgstr "Klatka fizyki %"
#: editor/editor_profiler.cpp
msgid "Inclusive"
-msgstr "Włącznie"
+msgstr "ÅÄ…cznie"
#: editor/editor_profiler.cpp
msgid "Self"
-msgstr "Ten obiekt"
+msgstr "Pojedynczo"
#: editor/editor_profiler.cpp
msgid "Frame #:"
@@ -5254,20 +5258,10 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
-msgstr ""
-"Godot został zbudowany bez wsparcia ray tracingu, mapy światła nie mogą być "
-"wypalone."
+"Edytor Godota został zbudowany bez wsparcia ray tracingu, mapy światła nie "
+"mogą zostać wypalone."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -10173,7 +10167,7 @@ msgstr "Przycisk myszy"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Niepoprawna nazwa akcji. Nie może być pusta ani zawierać \"/\", \":\", \"="
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index a59c7226f2..8ad62171b2 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -2520,7 +2520,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2937,6 +2937,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5169,16 +5173,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10025,7 +10020,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/pt.po b/editor/translations/pt.po
index 21fe589473..b164fc2f52 100644
--- a/editor/translations/pt.po
+++ b/editor/translations/pt.po
@@ -22,8 +22,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-10 15:32+0000\n"
-"Last-Translator: ssantos <ssantos@web.de>\n"
+"PO-Revision-Date: 2021-05-18 14:51+0000\n"
+"Last-Translator: João Lopes <linux-man@hotmail.com>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/"
"godot/pt/>\n"
"Language: pt\n"
@@ -2550,14 +2550,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "Incapaz de carregar script addon do caminho: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Incapaz de carregar script addon do caminho: '%s' Parece haver um erro no "
-"código, reveja a sintaxe."
+"código, reveja a sintaxe.\n"
+"A desativar o addon em '%s' para prevenir mais erros."
#: editor/editor_node.cpp
msgid ""
@@ -3002,6 +3002,10 @@ msgid "About"
msgstr "Sobre"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Apoie o Desenvolvimento do Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Executa o projeto."
@@ -5232,17 +5236,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Editor Godot foi compilado sem suporte para ray tracing, lightmaps não podem "
"ser consolidados."
@@ -10138,7 +10132,7 @@ msgstr "Botão do rato"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nome de ação inválido. Não pode ser vazio nem conter '/', ':', '=', '\\' ou "
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 9f9138e20a..7bfa3e7b97 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -115,12 +115,13 @@
# Lucas E. <lukas.ed45@gmail.com>, 2021.
# Gabriel Silveira <gabomfim99@gmail.com>, 2021.
# Arthur Phillip D. Silva <artphil.dev@gmail.com>, 2021.
+# Gustavo HM 102 <gustavohm102@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: 2016-05-30\n"
-"PO-Revision-Date: 2021-04-11 22:02+0000\n"
-"Last-Translator: Arthur Phillip D. Silva <artphil.dev@gmail.com>\n"
+"PO-Revision-Date: 2021-05-24 21:36+0000\n"
+"Last-Translator: Gustavo HM 102 <gustavohm102@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_BR/>\n"
"Language: pt_BR\n"
@@ -128,7 +129,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.6-dev\n"
+"X-Generator: Weblate 4.7-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -2650,14 +2651,14 @@ msgstr ""
"'%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Não foi possível localizar a área do script para o complemento do plugin em: "
-"'%s'."
+"Não foi possível localizar o script do caminho: '%s'. Isso pode ser devido a "
+"um erro de código nesse script.\n"
+"Desativando o addon em '%s' para prevenir erros futuros."
#: editor/editor_node.cpp
msgid ""
@@ -3102,6 +3103,11 @@ msgid "About"
msgstr "Sobre"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Support Godot Development"
+msgstr "Apoie o desenvolvimento do Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Roda o projeto."
@@ -5342,20 +5348,10 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"O editor Godot foi construído sem suporte à ray tracing, os lightmaps não "
-"podem ser bakeados."
+"podem ser refinados."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -7676,9 +7672,12 @@ msgid "View Rotation Locked"
msgstr "Ver Rotação Bloqueada"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid ""
"To zoom further, change the camera's clipping planes (View -> Settings...)"
msgstr ""
+"Para dar mais zoom, mude os planos de clipping da câmera (Visão -> "
+"Configurações...)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
@@ -10256,7 +10255,7 @@ msgstr "Botão do Mous"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Nome da ação inválido. Não pode estar vazio nem conter '/', ':', '=', '\\' "
@@ -11063,11 +11062,15 @@ msgid "Remote"
msgstr "Remoto"
#: editor/scene_tree_dock.cpp
+#, fuzzy
msgid ""
"If selected, the Remote scene tree dock will cause the project to stutter "
"every time it updates.\n"
"Switch back to the Local scene tree dock to improve performance."
msgstr ""
+"Se selecionado, o painel da árvore de cena Remota vai fazer o projeto travar "
+"toda hora que atualizar.\n"
+"Volta para o painel da árvore de cena Local para melhorar a performance."
#: editor/scene_tree_dock.cpp
msgid "Local"
diff --git a/editor/translations/ro.po b/editor/translations/ro.po
index fdf99eda10..b86af89ae2 100644
--- a/editor/translations/ro.po
+++ b/editor/translations/ro.po
@@ -2560,7 +2560,7 @@ msgstr "Nu a putut fi încărcat scriptul add-on din calea: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Imposibil de încărcat scriptul addon din cale: '%s' Se pare că există o "
@@ -3011,6 +3011,10 @@ msgid "About"
msgstr "Despre"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Rulează proiectul."
@@ -5240,16 +5244,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10186,7 +10181,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index a0f20328ee..acf8b3caaf 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -98,7 +98,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-14 11:20+0000\n"
+"PO-Revision-Date: 2021-05-21 11:33+0000\n"
"Last-Translator: Danil Alexeev <danil@alexeev.xyz>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
@@ -2625,14 +2625,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "Ðе удалоÑÑŒ загрузить Ñкрипт из иÑточника: «%s»."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Ðевозможно загрузить Ñкрипт аддона из иÑточника: «%s». Ð’ коде еÑть ошибка, "
-"пожалуйÑта, проверьте ÑинтакÑиÑ."
+"Ðевозможно загрузить Ñкрипт аддона по пути: «%s». Это может быть ÑвÑзано Ñ "
+"ошибкой в коде Ñкрипта.\n"
+"Ðддон «%s» отключён Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐ¸Ñ… ошибок."
#: editor/editor_node.cpp
msgid ""
@@ -3075,6 +3075,10 @@ msgid "About"
msgstr "О Godot Engine"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Поддержать разработку Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "ЗапуÑтить проект."
@@ -5305,17 +5309,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Редактор Godot был Ñобран без поддержки траÑÑировки лучей, карты оÑÐ²ÐµÑ‰ÐµÐ½Ð¸Ñ "
"невозможно запечь."
@@ -10218,7 +10212,7 @@ msgstr "Кнопка мыши"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Ðеверное Ð¸Ð¼Ñ Ð´ÐµÐ¹ÑтвиÑ. Оно не может быть пуÑтым и не может Ñодержать Ñимволы "
@@ -10822,7 +10816,7 @@ msgstr "Сделать узел корневым"
#: editor/scene_tree_dock.cpp
msgid "Delete %d nodes and any children?"
-msgstr "Удалить узел «%d» и его дочерние Ñлементы?"
+msgstr "Удалить %d узлов и их детей?"
#: editor/scene_tree_dock.cpp
msgid "Delete %d nodes?"
@@ -10834,7 +10828,7 @@ msgstr "Удалить корневой узел «%s»?"
#: editor/scene_tree_dock.cpp
msgid "Delete node \"%s\" and its children?"
-msgstr "Удалить узел «%s» и его дочерние Ñлементы?"
+msgstr "Удалить узел «%s» и его детей?"
#: editor/scene_tree_dock.cpp
msgid "Delete node \"%s\"?"
diff --git a/editor/translations/si.po b/editor/translations/si.po
index f3d3a7039f..b62a68170b 100644
--- a/editor/translations/si.po
+++ b/editor/translations/si.po
@@ -2465,7 +2465,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2871,6 +2871,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5039,16 +5043,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9766,7 +9761,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index af44e0eac1..c56b65ea9b 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -2534,7 +2534,7 @@ msgstr "Nepodarilo sa naÄítaÅ¥ addon script z cesty: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Nepodarilo sa nájsť addon script z cesty: '%s' Vyzerá to tak že by mohol byť "
@@ -2980,6 +2980,10 @@ msgid "About"
msgstr "O nás"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Spustiť projekt."
@@ -5200,16 +5204,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10082,7 +10077,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index 8e005a05db..534d8a8af8 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -2647,7 +2647,7 @@ msgstr "Ni mogoÄe naložiti dodatno skripto iz poti: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Ni mogoÄe naložiti dodatno skripto iz poti: '%s' Skripta ni v naÄinu orodje."
@@ -3114,6 +3114,10 @@ msgid "About"
msgstr "O Programu"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Zaženi projekt."
@@ -5438,16 +5442,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10423,7 +10418,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/sq.po b/editor/translations/sq.po
index f95143dfce..9adfd21568 100644
--- a/editor/translations/sq.po
+++ b/editor/translations/sq.po
@@ -2589,7 +2589,7 @@ msgstr "I paaftë të ngarkojë shkrimin e shtojcës nga rruga: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"I paaftë të ngarkojë shkrimin e shtojcës nga rruga: '%s' Me sa duket është "
@@ -3052,6 +3052,10 @@ msgid "About"
msgstr "Rreth"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Luaj projektin."
@@ -5288,16 +5292,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10077,7 +10072,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po
index bc417703cc..d839ee4d1b 100644
--- a/editor/translations/sr_Cyrl.po
+++ b/editor/translations/sr_Cyrl.po
@@ -2764,7 +2764,7 @@ msgstr "ÐеуÑпех при учитавању Ñкриптице додатк
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"ÐеуÑпех при учитавању Ñкриптице додатка Ñа путем „%s“. Скриптица није у "
@@ -3242,6 +3242,10 @@ msgid "About"
msgstr "О"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Покрени пројекат."
@@ -5703,16 +5707,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -11282,7 +11277,7 @@ msgstr "Миш Дугме"
#: editor/project_settings_editor.cpp
#, fuzzy
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Ðеважеће име акције. Ðе може бити празно или Ñадржати '/', ':', '=', '\\' "
diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po
index 5f0a7bb237..bb42742181 100644
--- a/editor/translations/sr_Latn.po
+++ b/editor/translations/sr_Latn.po
@@ -2478,7 +2478,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2886,6 +2886,10 @@ msgid "About"
msgstr "O nama / O Godou"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5063,16 +5067,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9846,7 +9841,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/sv.po b/editor/translations/sv.po
index cf330e6223..073e2b0670 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -2600,7 +2600,7 @@ msgstr "Kunde inte ladda addon script från sökväg: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Kunde inte ladda addon script från sökväg: '%s' Skript är inte i "
@@ -3036,6 +3036,10 @@ msgid "About"
msgstr "Om"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Spela projektet."
@@ -5298,16 +5302,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10211,7 +10206,7 @@ msgstr "Musknapp"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/ta.po b/editor/translations/ta.po
index 375dbacff3..ed08398eeb 100644
--- a/editor/translations/ta.po
+++ b/editor/translations/ta.po
@@ -2469,7 +2469,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2877,6 +2877,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5048,16 +5052,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9766,7 +9761,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/te.po b/editor/translations/te.po
index 41850d2d56..62741d508d 100644
--- a/editor/translations/te.po
+++ b/editor/translations/te.po
@@ -2442,7 +2442,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2848,6 +2848,10 @@ msgid "About"
msgstr "à°—à±à°°à°¿à°‚à°šà°¿"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5002,16 +5006,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9691,7 +9686,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/th.po b/editor/translations/th.po
index 38ef19e80c..3f01cae158 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -2517,7 +2517,7 @@ msgstr "ไม่สามารถโหลดสคริปต์จาà¸: '
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"ไม่สามารถโหลดสคริปต์ส่วนเสริมจาà¸: '%s' เหมือนว่าจะเà¸à¸´à¸”ข้อผิดพลาดขึ้นในโค้ด "
@@ -2951,6 +2951,10 @@ msgid "About"
msgstr "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "เล่นโปรเจà¸à¸•์"
@@ -5141,18 +5145,9 @@ msgid ""
msgstr "mesh บางส่วนไม่ถูà¸à¸•้อง ตรวจสอบให้à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸²à¸„่า UV2 อยู่ในพื้นที่สี่เหลี่ยม [0.0,1.0]"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"ตัวà¹à¸à¹‰à¹„ข Godot ถูà¸à¸ªà¸£à¹‰à¸²à¸‡à¹‚ดยไม่ได้สนับสนุน Ray Tracing ดังนั้นจึงไม่สามารถปั้น Lightmap ได้"
@@ -9981,7 +9976,7 @@ msgstr "ปุ่มเมาส์"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr "ชื่อผิดพลาด ไม่สามารถเป็นช่องว่างหรือประà¸à¸­à¸šà¸”้วย '/', ':', '=', '\\' หรือ '\"'"
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index e49efb20b5..ae07c290e2 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -58,12 +58,14 @@
# Çağlar KOPARIR <ckoparir@gmail.com>, 2021.
# Cem Eren Fukara <cefukara@hotmail.com>, 2021.
# Jafar Tarverdiyev <cefertarverdiyevv@gmail.com>, 2021.
+# ali aydın <alimxaydin@gmail.com>, 2021.
+# Cannur Daşkıran <canndask@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-14 11:20+0000\n"
-"Last-Translator: Jafar Tarverdiyev <cefertarverdiyevv@gmail.com>\n"
+"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"Last-Translator: ali aydın <alimxaydin@gmail.com>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot/tr/>\n"
"Language: tr\n"
@@ -1556,7 +1558,7 @@ msgstr "İsim"
#: editor/editor_autoload_settings.cpp
msgid "Singleton"
-msgstr "Tekil"
+msgstr "Tekil nesne"
#: editor/editor_data.cpp editor/inspector_dock.cpp
msgid "Paste Params"
@@ -2040,7 +2042,7 @@ msgstr "Çevrimiçi Rehberler"
#: editor/editor_help.cpp
msgid "Properties"
-msgstr "Özellikleri"
+msgstr "Özellikler"
#: editor/editor_help.cpp
msgid "override:"
@@ -2581,21 +2583,22 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Unable to find script field for addon plugin at: '%s'."
-msgstr "Eklentide için betik alanı bulunamıyor: '%s'."
+msgstr "Eklenti için betik alanı şu konumda bulunamıyor: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
msgstr "Yoldaki eklenti betiği yüklenemedi: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"'%s' adresindeki eklenti betik yüklenemiyor. Kodun içinde bir hata var gibi "
-"görünüyor, lütfen sözdizimini kontrol edin."
+"görünüyor.\n"
+"Daha fazla hatayı önlemek için '% s' adresindeki eklenti devre dışı "
+"bırakılıyor."
#: editor/editor_node.cpp
msgid ""
@@ -3038,6 +3041,10 @@ msgid "About"
msgstr "Hakkında"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Godot'u GeliÅŸtirmeye Destek Olun"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Projeti oynat."
@@ -4126,7 +4133,7 @@ msgstr "İçe Aktarıcı'yı seçin"
#: editor/import_defaults_editor.cpp
msgid "Importer:"
-msgstr "İçe Aktar"
+msgstr "İçe Alımcı:"
#: editor/import_defaults_editor.cpp
msgid "Reset to Defaults"
@@ -5104,7 +5111,7 @@ msgstr "Alınan:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed SHA-256 hash check"
-msgstr "SHA-256 hash kontrolü başarısız oldu"
+msgstr "Başarısız SHA-256 hash sınaması"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5270,20 +5277,10 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
-"Godot editör ışın yansıma desteği olmadan derlenmiş, ışık haritaları "
-"piÅŸirilemez."
+"Godot editör ışın yansıma desteği olmadan derlenmiş, ışık haritaları çizilip "
+"sabitlenemez."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -10177,7 +10174,7 @@ msgstr "Fare Düğmesi"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Geçersiz işlem adı. Boş olamaz ve '/', ':', '=', '\\' veya '\"' içeremez"
@@ -10733,11 +10730,11 @@ msgstr "Çocuk Sahnesini Örnekle"
#: editor/scene_tree_dock.cpp
msgid "Can't paste root node into the same scene."
-msgstr "Kök düğüm aynı sahneye yapıştırılamıyor."
+msgstr "Kök düğümü aynı sahne içine yapıştırılamaz."
#: editor/scene_tree_dock.cpp
msgid "Paste Node(s)"
-msgstr "Düğümleri Yapıştır"
+msgstr "Düğüm(leri) Yapıştır"
#: editor/scene_tree_dock.cpp
msgid "Detach Script"
@@ -10868,7 +10865,7 @@ msgstr "Betik İliştir"
#: editor/scene_tree_dock.cpp
msgid "Cut Node(s)"
-msgstr "Düğümleri Kes(s)"
+msgstr "Düğüm(leri) Kes"
#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
@@ -10988,6 +10985,9 @@ msgid ""
"every time it updates.\n"
"Switch back to the Local scene tree dock to improve performance."
msgstr ""
+"Seçilirse, Uzak sahne ağacı yuvası, projenin her güncellendiğinde "
+"takılmasına neden olur.\n"
+"Performansı artırmak için Yerel sahne ağaç yuvasına geri dönün."
#: editor/scene_tree_dock.cpp
msgid "Local"
diff --git a/editor/translations/tzm.po b/editor/translations/tzm.po
index 7980101d8a..c06fa4f106 100644
--- a/editor/translations/tzm.po
+++ b/editor/translations/tzm.po
@@ -2440,7 +2440,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2846,6 +2846,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5000,16 +5004,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9688,7 +9683,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index 576ebc4433..52a125fc02 100644
--- a/editor/translations/uk.po
+++ b/editor/translations/uk.po
@@ -20,7 +20,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Ukrainian (Godot Engine)\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-22 14:40+0000\n"
+"PO-Revision-Date: 2021-05-18 14:51+0000\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/"
"godot/uk/>\n"
@@ -2556,14 +2556,14 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "Ðеможливо завантажити Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ñкрипт зі шлÑху: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Ðеможливо завантажити Ñкрипт Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð· шлÑху «%s». ЗдаєтьÑÑ, у коді Ñ” "
-"помилка, будь лаÑка, перевірте ÑинтакÑиÑ."
+"Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ додатковий Ñкрипт з такою адреÑою: «%s». Причиною "
+"може бути помилка у коді цього Ñкрипту.\n"
+"Вимикаємо додаток у «%s», щоб запобігти подальшим помилкам."
#: editor/editor_node.cpp
msgid ""
@@ -3010,6 +3010,10 @@ msgid "About"
msgstr "Про"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "Підтримати розробку Godot"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "ЗапуÑтити проєкт."
@@ -5248,17 +5252,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Редактор Godot було зібрано без підтримки траÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ñ–Ð². Карти "
"оÑÐ²Ñ–Ñ‚Ð»ÐµÐ½Ð½Ñ Ð½Ðµ вдаÑтьÑÑ Ð¿Ð¾Ð±ÑƒÐ´ÑƒÐ²Ð°Ñ‚Ð¸."
@@ -10174,7 +10168,7 @@ msgstr "Кнопка миші"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
"Ðекоректна назва дії. Ðазва не може бути порожньою Ñ– не може міÑтити "
@@ -13235,6 +13229,19 @@ msgid "Constants cannot be modified."
msgstr "Сталі не можна змінювати."
#~ msgid ""
+#~ "Godot editor was built without ray tracing support; lightmaps can't be "
+#~ "baked.\n"
+#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta "
+#~ "emulation on Godot.app in the application settings\n"
+#~ "then restart the editor."
+#~ msgstr ""
+#~ "Редактор Godot було зібрано без підтримки траÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ñ–Ð²; мапи "
+#~ "оÑÐ²Ñ–Ñ‚Ð»ÐµÐ½Ð½Ñ Ñтворити не вдаÑтьÑÑ.\n"
+#~ "Якщо ви кориÑтуєтеÑÑ Mac на оÑнові Apple Silicon, Ñпробуйте примуÑово "
+#~ "вÑтановити емулÑцію Rosetta Ð´Ð»Ñ Godot.app у параметрах програми,\n"
+#~ "а потім перезапуÑтіть редактор."
+
+#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
#~ "InterpolatedCamera вважаєтьÑÑ Ð·Ð°Ñтарілою, Ñ—Ñ— буде вилучено у Godot 4.0."
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index d71c823f96..19e41bb657 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -2490,7 +2490,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -2900,6 +2900,10 @@ msgid "About"
msgstr ""
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr ""
@@ -5106,16 +5110,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -9937,7 +9932,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/vi.po b/editor/translations/vi.po
index b1a6984df9..c532ba4f50 100644
--- a/editor/translations/vi.po
+++ b/editor/translations/vi.po
@@ -2535,7 +2535,7 @@ msgstr "Không thể tải tệp addon từ đưá»ng dẫn: '%s'."
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
"Không thể nạp tệp lệnh bổ trợ từ đưá»ng dẫn: '%s' Có vẻ có lá»—i trong mã, hãy "
@@ -2971,6 +2971,10 @@ msgid "About"
msgstr "VỠchúng tôi"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "Chạy dự án."
@@ -5172,16 +5176,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10018,7 +10013,7 @@ msgstr "Nút chuột"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr "Tên hành động không được trống hoặc chứa '/', ':', '=', '\\' hoặc '\"'"
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index 57d34e4b6f..b65b62655e 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -78,12 +78,13 @@
# Weiduo Xie <xwditfr@gmail.com>, 2021.
# suplife <2634557184@qq.com>, 2021.
# luoji <564144019@qq.com>, 2021.
+# zeng haochen <m18621006730@163.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Chinese (Simplified) (Godot Engine)\n"
"POT-Creation-Date: 2018-01-20 12:15+0200\n"
-"PO-Revision-Date: 2021-04-26 22:32+0000\n"
-"Last-Translator: qjyqjyqjyqjy <qjyqjyqjyqjy@sina.com.cn>\n"
+"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"Last-Translator: Haoyu Qiu <timothyqiu32@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hans/>\n"
"Language: zh_CN\n"
@@ -100,7 +101,7 @@ msgstr "convert() çš„å‚æ•°ç±»åž‹æ— æ•ˆï¼Œè¯·ä½¿ç”¨ TYPE_* 常é‡ã€‚"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
-msgstr "应为长度为 1 的字符串(1 字符)。"
+msgstr "应为长度为 1 的字符串(1个字符)。"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/mono/glue/gd_glue.cpp
@@ -2564,12 +2565,13 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "无法从路径 “%s†中加载加载项脚本。"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
-msgstr "无法从路径 “%s†加载加载项脚本:脚本似乎有代ç é”™è¯¯ï¼Œè¯·æ£€æŸ¥å…¶è¯­æ³•。"
+msgstr ""
+"无法从路径“%sâ€åŠ è½½åŠ è½½é¡¹è„šæœ¬ï¼šè¯¥è„šæœ¬å¯èƒ½æœ‰ä»£ç é”™è¯¯ã€‚\n"
+"ç¦ç”¨åŠ è½½é¡¹â€œ%sâ€å¯é˜»æ­¢å…¶è¿›ä¸€æ­¥æŠ¥é”™ã€‚"
#: editor/editor_node.cpp
msgid ""
@@ -2995,6 +2997,10 @@ msgid "About"
msgstr "关于"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "æ”¯æŒ Godot å¼€å‘"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "è¿è¡Œæ­¤é¡¹ç›®ã€‚"
@@ -5185,18 +5191,8 @@ msgstr "æŸäº›ç½‘格无效。确ä¿UV2通é“值包å«åœ¨[0.0,1.0]平方区域内
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
-msgstr "Godot编辑器是在没有光线跟踪支æŒçš„æƒ…况下构建的,光照贴图无法烘焙。"
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
+msgstr "Godot 编辑器是在没有光线跟踪支æŒçš„æƒ…况下构建的,无法烘焙光照贴图。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -10012,7 +10008,7 @@ msgstr "鼠标按键"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr "无效的æ“作å称。æ“作åä¸èƒ½ä¸ºç©ºï¼Œä¹Ÿä¸èƒ½åŒ…å« â€œ/â€, “:â€, “=â€, “\\†或 “\"â€"
@@ -12935,6 +12931,18 @@ msgid "Constants cannot be modified."
msgstr "ä¸å…许修改常é‡ã€‚"
#~ msgid ""
+#~ "Godot editor was built without ray tracing support; lightmaps can't be "
+#~ "baked.\n"
+#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta "
+#~ "emulation on Godot.app in the application settings\n"
+#~ "then restart the editor."
+#~ msgstr ""
+#~ "Godot 编辑器是在没有光线跟踪支æŒçš„æƒ…况下构建的;无法烘焙光照贴图。\n"
+#~ "如果你使用的是基于 Apple Silicon çš„ Mac,å¯ä»¥å°è¯•在应用设置中让 Godot.app "
+#~ "强制使用 Rosetta 模拟\n"
+#~ "å¹¶é‡å¯ç¼–辑器。"
+
+#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "InterpolatedCamera 已废弃,将在 Godot 4.0 中删除。"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index 7f181fe4be..0e5af962b5 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -2610,7 +2610,7 @@ msgstr "載入字形出ç¾éŒ¯èª¤"
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
@@ -3059,6 +3059,10 @@ msgid "About"
msgstr "關於"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "é‹è¡Œå°ˆæ¡ˆ"
@@ -5395,16 +5399,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -10370,7 +10365,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr ""
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index f5f0feb333..255f31dfbc 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -6,7 +6,7 @@
# Billy SU <g4691821@gmail.com>, 2018.
# Chao Yu <casd82@gmail.com>, 2017.
# Cliffs Dover <bottle@dancingbottle.com>, 2017.
-# Kisaragi Hiu <mail@kisaragi-hiu.com>, 2018.
+# Kisaragi Hiu <mail@kisaragi-hiu.com>, 2018, 2021.
# Matt <chchwy@gmail.com>, 2017.
# popcade <popcade@gmail.com>, 2016.
# Qing <icinriiq@gmail.com>, 2018.
@@ -29,8 +29,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-03-16 10:40+0000\n"
-"Last-Translator: BinotaLIU <me@binota.org>\n"
+"PO-Revision-Date: 2021-05-24 21:36+0000\n"
+"Last-Translator: Kisaragi Hiu <mail@kisaragi-hiu.com>\n"
"Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hant/>\n"
"Language: zh_TW\n"
@@ -38,7 +38,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.5.2-dev\n"
+"X-Generator: Weblate 4.7-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -2516,7 +2516,7 @@ msgstr "無法自路徑「%sã€è¼‰å…¥æ“´å……腳本。"
#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
-"error in that script. \n"
+"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr "無法自路徑「%sã€è¼‰å…¥æ“´å……腳本。å¯èƒ½ç‚ºç¨‹å¼ç¢¼ä¸­æœ‰éŒ¯èª¤ï¼Œè«‹æª¢æŸ¥èªžæ³•。"
@@ -2944,6 +2944,10 @@ msgid "About"
msgstr "關於"
#: editor/editor_node.cpp
+msgid "Support Godot Development"
+msgstr "æ”¯æ´ Godot 開發"
+
+#: editor/editor_node.cpp
msgid "Play the project."
msgstr "執行該專案。"
@@ -4015,7 +4019,7 @@ msgstr "é‡è¨­ç‚ºé è¨­"
#: editor/import_dock.cpp
msgid "Keep File (No Import)"
-msgstr ""
+msgstr "ä¿ç•™æª”案(ä¸åŒ¯å…¥ï¼‰"
#: editor/import_dock.cpp
msgid "%d Files"
@@ -5133,18 +5137,9 @@ msgid ""
msgstr "éƒ¨åˆ†ç¶²æ ¼ç„¡æ•ˆã€‚è«‹ç¢ºä¿ UV2 通é“çš„å€¼ä½æ–¼ [0.0,1.0] 矩形內。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be "
-"baked.\n"
-"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation "
-"on Godot.app in the application settings\n"
-"then restart the editor."
-msgstr ""
-
-#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"Godot editor was built without ray tracing support; lightmaps can't be baked."
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
"Godot 編輯器在建制時未啟用光線追蹤 (Ray Tracing) 支æ´ï¼Œç„¡æ³•烘焙光照圖。"
@@ -7444,7 +7439,7 @@ msgstr "視圖旋轉已鎖定"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
"To zoom further, change the camera's clipping planes (View -> Settings...)"
-msgstr ""
+msgstr "è‹¥è¦å†ç¹¼çºŒæ”¾å¤§ï¼Œè«‹è‡³ 檢視 -> 設定... 修改æ”影機的剪è£å¹³é¢"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
@@ -9963,7 +9958,7 @@ msgstr "滑鼠按鈕"
#: editor/project_settings_editor.cpp
msgid ""
-"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
msgstr "無效的æ“作å稱。å稱ä¸å¯ç•™ç©ºæˆ–åŒ…å« â€œ/â€, “:â€, “=â€, “\\†或 “\"â€"
diff --git a/main/main.cpp b/main/main.cpp
index 67d8d93728..f1905fc47b 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -36,6 +36,7 @@
#include "core/debugger/engine_debugger.h"
#include "core/input/input.h"
#include "core/input/input_map.h"
+#include "core/io/dir_access.h"
#include "core/io/file_access_network.h"
#include "core/io/file_access_pack.h"
#include "core/io/file_access_zip.h"
@@ -43,8 +44,8 @@
#include "core/io/ip.h"
#include "core/io/resource_loader.h"
#include "core/object/message_queue.h"
-#include "core/os/dir_access.h"
#include "core/os/os.h"
+#include "core/os/time.h"
#include "core/register_core_types.h"
#include "core/string/translation.h"
#include "core/version.h"
@@ -101,6 +102,7 @@ static InputMap *input_map = nullptr;
static TranslationServer *translation_server = nullptr;
static Performance *performance = nullptr;
static PackedData *packed_data = nullptr;
+static Time *time_singleton = nullptr;
#ifdef MINIZIP_ENABLED
static ZipArchive *zip_packed_data = nullptr;
#endif
@@ -532,6 +534,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
MAIN_PRINT("Main: Initialize Globals");
input_map = memnew(InputMap);
+ time_singleton = memnew(Time);
globals = memnew(ProjectSettings);
register_core_settings(); //here globals are present
@@ -1327,35 +1330,19 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
{
- String orientation = GLOBAL_DEF("display/window/handheld/orientation", "landscape");
-
- if (orientation == "portrait") {
- window_orientation = DisplayServer::SCREEN_PORTRAIT;
- } else if (orientation == "reverse_landscape") {
- window_orientation = DisplayServer::SCREEN_REVERSE_LANDSCAPE;
- } else if (orientation == "reverse_portrait") {
- window_orientation = DisplayServer::SCREEN_REVERSE_PORTRAIT;
- } else if (orientation == "sensor_landscape") {
- window_orientation = DisplayServer::SCREEN_SENSOR_LANDSCAPE;
- } else if (orientation == "sensor_portrait") {
- window_orientation = DisplayServer::SCREEN_SENSOR_PORTRAIT;
- } else if (orientation == "sensor") {
- window_orientation = DisplayServer::SCREEN_SENSOR;
- } else {
- window_orientation = DisplayServer::SCREEN_LANDSCAPE;
- }
+ window_orientation = DisplayServer::ScreenOrientation(int(GLOBAL_DEF_BASIC("display/window/handheld/orientation", DisplayServer::ScreenOrientation::SCREEN_LANDSCAPE)));
}
Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF_BASIC("physics/common/physics_fps", 60));
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps",
PropertyInfo(Variant::INT, "physics/common/physics_fps",
- PROPERTY_HINT_RANGE, "1,120,1,or_greater"));
+ PROPERTY_HINT_RANGE, "1,1000,1"));
Engine::get_singleton()->set_physics_jitter_fix(GLOBAL_DEF("physics/common/physics_jitter_fix", 0.5));
Engine::get_singleton()->set_target_fps(GLOBAL_DEF("debug/settings/fps/force_fps", 0));
ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/fps/force_fps",
PropertyInfo(Variant::INT,
"debug/settings/fps/force_fps",
- PROPERTY_HINT_RANGE, "0,120,1,or_greater"));
+ PROPERTY_HINT_RANGE, "0,1000,1"));
GLOBAL_DEF("debug/settings/stdout/print_fps", false);
GLOBAL_DEF("debug/settings/stdout/verbose_stdout", false);
@@ -1418,6 +1405,9 @@ error:
if (input_map) {
memdelete(input_map);
}
+ if (time_singleton) {
+ memdelete(time_singleton);
+ }
if (translation_server) {
memdelete(translation_server);
}
@@ -1461,6 +1451,12 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
}
#endif
+#ifdef TOOLS_ENABLED
+ if (editor || project_manager) {
+ EditorPaths::create();
+ }
+#endif
+
/* Determine text driver */
if (text_driver == "") {
@@ -2383,10 +2379,8 @@ bool Main::start() {
}
// Load SSL Certificates from Editor Settings (or builtin)
- Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting(
- "network/ssl/editor_ssl_certificates")
- .
- operator String());
+ Crypto::load_default_certificates(
+ EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String());
}
#endif
}
@@ -2677,6 +2671,9 @@ void Main::cleanup(bool p_force) {
if (input_map) {
memdelete(input_map);
}
+ if (time_singleton) {
+ memdelete(time_singleton);
+ }
if (translation_server) {
memdelete(translation_server);
}
diff --git a/methods.py b/methods.py
index 6f1e7a7279..1afd1ca0d4 100644
--- a/methods.py
+++ b/methods.py
@@ -787,9 +787,18 @@ def get_compiler_version(env):
return None
else: # TODO: Implement for MSVC
return None
- match = re.search("[0-9]+\.[0-9.]+", version)
+ match = re.search(
+ "(?:(?<=version )|(?<=\) )|(?<=^))"
+ "(?P<major>\d+)"
+ "(?:\.(?P<minor>\d*))?"
+ "(?:\.(?P<patch>\d*))?"
+ "(?:-(?P<metadata1>[0-9a-zA-Z-]*))?"
+ "(?:\+(?P<metadata2>[0-9a-zA-Z-]*))?"
+ "(?: (?P<date>[0-9]{8}|[0-9]{6})(?![0-9a-zA-Z]))?",
+ version,
+ )
if match is not None:
- return list(map(int, match.group().split(".")))
+ return match.groupdict()
else:
return None
diff --git a/misc/dist/html/service-worker.js b/misc/dist/html/service-worker.js
index f8dee8cd5b..063e40a6cb 100644
--- a/misc/dist/html/service-worker.js
+++ b/misc/dist/html/service-worker.js
@@ -1,6 +1,6 @@
// This service worker is required to expose an exported Godot project as a
// Progressive Web App. It provides an offline fallback page telling the user
-// that they need an Internet conneciton to run the project if desired.
+// that they need an Internet connection to run the project if desired.
// Incrementing CACHE_VERSION will kick off the install event and force
// previously cached resources to be updated from the network.
const CACHE_VERSION = "@GODOT_VERSION@";
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
index b9ad431e6e..fd69725a21 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -255,7 +255,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
OTHER_LDFLAGS = "$linker_flags";
SDKROOT = iphoneos;
- TARGETED_DEVICE_FAMILY = "1,2";
+ TARGETED_DEVICE_FAMILY = "$targeted_device_family";
};
name = Debug;
};
@@ -294,7 +294,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
OTHER_LDFLAGS = "$linker_flags";
SDKROOT = iphoneos;
- TARGETED_DEVICE_FAMILY = "1,2";
+ TARGETED_DEVICE_FAMILY = "$targeted_device_family";
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -323,7 +323,7 @@
PRODUCT_BUNDLE_IDENTIFIER = $bundle_identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "$provisioning_profile_uuid_debug";
- TARGETED_DEVICE_FAMILY = "1,2";
+ TARGETED_DEVICE_FAMILY = "$targeted_device_family";
VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64";
WRAPPER_EXTENSION = app;
};
@@ -353,7 +353,7 @@
PRODUCT_BUNDLE_IDENTIFIER = $bundle_identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "$provisioning_profile_uuid_release";
- TARGETED_DEVICE_FAMILY = "1,2";
+ TARGETED_DEVICE_FAMILY = "$targeted_device_family";
VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64";
WRAPPER_EXTENSION = app;
};
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme b/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme
index b6beeb012f..d61a53d5c2 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme
@@ -23,7 +23,7 @@
</BuildActionEntries>
</BuildAction>
<TestAction
- buildConfiguration = "Debug"
+ buildConfiguration = "$default_build_config"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
@@ -42,7 +42,7 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
- buildConfiguration = "Debug"
+ buildConfiguration = "$default_build_config"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
@@ -67,7 +67,7 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
- buildConfiguration = "Debug"
+ buildConfiguration = "$default_build_config"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
@@ -84,10 +84,10 @@
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
- buildConfiguration = "Debug">
+ buildConfiguration = "$default_build_config">
</AnalyzeAction>
<ArchiveAction
- buildConfiguration = "Debug"
+ buildConfiguration = "$default_build_config"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
diff --git a/misc/dist/linux/org.godotengine.Godot.xml b/misc/dist/linux/org.godotengine.Godot.xml
index 2f647f71a6..e51179cd61 100644
--- a/misc/dist/linux/org.godotengine.Godot.xml
+++ b/misc/dist/linux/org.godotengine.Godot.xml
@@ -21,6 +21,12 @@
<glob pattern="*.escn"/>
</mime-type>
+ <mime-type type="application/x-godot-shader">
+ <comment>Godot Engine shader</comment>
+ <icon name="x-godot-shader" />
+ <glob pattern="*.gdshader"/>
+ </mime-type>
+
<mime-type type="application/x-gdscript">
<comment>GDScript script</comment>
<icon name="x-gdscript" />
diff --git a/misc/dist/osx/editor.entitlements b/misc/dist/osx/editor.entitlements
new file mode 100644
index 0000000000..5496f65dcc
--- /dev/null
+++ b/misc/dist/osx/editor.entitlements
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.security.device.audio-input</key>
+ <true/>
+ <key>com.apple.security.device.camera</key>
+ <true/>
+ <key>com.apple.security.cs.disable-library-validation</key>
+ <true/>
+</dict>
+</plist>
diff --git a/misc/dist/osx/editor_mono.entitlements b/misc/dist/osx/editor_mono.entitlements
new file mode 100644
index 0000000000..c61c287652
--- /dev/null
+++ b/misc/dist/osx/editor_mono.entitlements
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.security.cs.allow-dyld-environment-variables</key>
+ <true/>
+ <key>com.apple.security.cs.allow-jit</key>
+ <true/>
+ <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
+ <true/>
+ <key>com.apple.security.cs.disable-library-validation</key>
+ <true/>
+ <key>com.apple.security.device.audio-input</key>
+ <true/>
+ <key>com.apple.security.device.camera</key>
+ <true/>
+</dict>
+</plist>
diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/osx_template.app/Contents/Info.plist
index aad24935d0..8e221df946 100644
--- a/misc/dist/osx_template.app/Contents/Info.plist
+++ b/misc/dist/osx_template.app/Contents/Info.plist
@@ -36,6 +36,8 @@
</array>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
+ <key>LSApplicationCategoryType</key>
+ <string>public.app-category.$app_category</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
<key>LSMinimumSystemVersionByArchitecture</key>
diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/osx_tools.app/Contents/Info.plist
index 1c682f339f..8e70d4c203 100644
--- a/misc/dist/osx_tools.app/Contents/Info.plist
+++ b/misc/dist/osx_tools.app/Contents/Info.plist
@@ -38,6 +38,8 @@
</array>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
+ <key>LSApplicationCategoryType</key>
+ <string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
<key>LSMinimumSystemVersionByArchitecture</key>
diff --git a/misc/hooks/canonicalize_filename.sh b/misc/hooks/canonicalize_filename.sh
index 5eecabf5bc..5fcae6ee70 100755
--- a/misc/hooks/canonicalize_filename.sh
+++ b/misc/hooks/canonicalize_filename.sh
@@ -13,7 +13,7 @@
# There should be no need to change anything below this line.
# Canonicalize by recursively following every symlink in every component of the
-# specified filename. This should reproduce the results of the GNU version of
+# specified filename. This should reproduce the results of the GNU version of
# readlink with the -f option.
#
# Reference: http://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac
diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format
index 2dac8e9a55..81bc412944 100755
--- a/misc/hooks/pre-commit-clang-format
+++ b/misc/hooks/pre-commit-clang-format
@@ -76,7 +76,8 @@ fi
# To get consistent formatting, we recommend contributors to use the same
# clang-format version as CI.
-RECOMMENDED_CLANG_FORMAT_MAJOR="11"
+RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="11"
+RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="12"
if [ ! -x "$CLANG_FORMAT" ] ; then
message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x."
@@ -106,8 +107,8 @@ fi
CLANG_FORMAT_VERSION="$(clang-format --version | sed "s/[^0-9\.]*\([0-9\.]*\).*/\1/")"
CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d. -f1)"
-if [ "$CLANG_FORMAT_MAJOR" != "$RECOMMENDED_CLANG_FORMAT_MAJOR" ]; then
- echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x)."
+if [[ "$CLANG_FORMAT_MAJOR" -lt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MIN" || "$CLANG_FORMAT_MAJOR" -gt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MAX" ]]; then
+ echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected between $RECOMMENDED_CLANG_FORMAT_MAJOR_MIN.x.x and $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX.x.x)."
echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly."
fi
diff --git a/misc/scripts/check_ci_log.py b/misc/scripts/check_ci_log.py
index f2cdf95c7b..56c32b154c 100755
--- a/misc/scripts/check_ci_log.py
+++ b/misc/scripts/check_ci_log.py
@@ -53,11 +53,11 @@ if file_contents.find("ObjectDB instances leaked at exit") != -1:
# execution of project
if file_contents.find("Assertion failed") != -1:
- print("ERROR: Assertion failed in project, check exectution log for more info")
+ print("ERROR: Assertion failed in project, check execution log for more info")
sys.exit(1)
# For now Godot leaks a lot of rendering stuff so for now we just show info
-# about it and this needs to be reenabled after fixing this memory leaks.
+# about it and this needs to be re-enabled after fixing this memory leaks.
if file_contents.find("were leaked") != -1 or file_contents.find("were never freed") != -1:
print("WARNING: Memory leak was found")
diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp
index f22e74cafb..27b49a6609 100644
--- a/modules/bmp/image_loader_bmp.cpp
+++ b/modules/bmp/image_loader_bmp.cpp
@@ -205,7 +205,7 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
// A valid bmp file should always at least have a
// file header and a minimal info header
- if (f->get_len() > BITMAP_FILE_HEADER_SIZE + BITMAP_INFO_HEADER_MIN_SIZE) {
+ if (f->get_length() > BITMAP_FILE_HEADER_SIZE + BITMAP_INFO_HEADER_MIN_SIZE) {
// File Header
bmp_header.bmp_file_header.bmp_signature = f->get_16();
if (bmp_header.bmp_file_header.bmp_signature == BITMAP_SIGNATURE) {
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index e601884486..e07be14c5b 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -268,7 +268,7 @@ PhysicsServer3D::AreaSpaceOverrideMode BulletPhysicsServer3D::area_get_space_ove
return area->get_spOv_mode();
}
-void BulletPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) {
+void BulletPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
AreaBullet *area = area_owner.getornull(p_area);
ERR_FAIL_COND(!area);
@@ -288,7 +288,7 @@ void BulletPhysicsServer3D::area_set_shape(RID p_area, int p_shape_idx, RID p_sh
area->set_shape(p_shape_idx, shape);
}
-void BulletPhysicsServer3D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) {
+void BulletPhysicsServer3D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) {
AreaBullet *area = area_owner.getornull(p_area);
ERR_FAIL_COND(!area);
@@ -309,9 +309,9 @@ RID BulletPhysicsServer3D::area_get_shape(RID p_area, int p_shape_idx) const {
return area->get_shape(p_shape_idx)->get_self();
}
-Transform BulletPhysicsServer3D::area_get_shape_transform(RID p_area, int p_shape_idx) const {
+Transform3D BulletPhysicsServer3D::area_get_shape_transform(RID p_area, int p_shape_idx) const {
AreaBullet *area = area_owner.getornull(p_area);
- ERR_FAIL_COND_V(!area, Transform());
+ ERR_FAIL_COND_V(!area, Transform3D());
return area->get_shape_transform(p_shape_idx);
}
@@ -382,15 +382,15 @@ Variant BulletPhysicsServer3D::area_get_param(RID p_area, AreaParameter p_param)
}
}
-void BulletPhysicsServer3D::area_set_transform(RID p_area, const Transform &p_transform) {
+void BulletPhysicsServer3D::area_set_transform(RID p_area, const Transform3D &p_transform) {
AreaBullet *area = area_owner.getornull(p_area);
ERR_FAIL_COND(!area);
area->set_transform(p_transform);
}
-Transform BulletPhysicsServer3D::area_get_transform(RID p_area) const {
+Transform3D BulletPhysicsServer3D::area_get_transform(RID p_area) const {
AreaBullet *area = area_owner.getornull(p_area);
- ERR_FAIL_COND_V(!area, Transform());
+ ERR_FAIL_COND_V(!area, Transform3D());
return area->get_transform();
}
@@ -484,7 +484,7 @@ PhysicsServer3D::BodyMode BulletPhysicsServer3D::body_get_mode(RID p_body) const
return body->get_mode();
}
-void BulletPhysicsServer3D::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) {
+void BulletPhysicsServer3D::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -504,7 +504,7 @@ void BulletPhysicsServer3D::body_set_shape(RID p_body, int p_shape_idx, RID p_sh
body->set_shape(p_shape_idx, shape);
}
-void BulletPhysicsServer3D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) {
+void BulletPhysicsServer3D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -527,9 +527,9 @@ RID BulletPhysicsServer3D::body_get_shape(RID p_body, int p_shape_idx) const {
return shape->get_self();
}
-Transform BulletPhysicsServer3D::body_get_shape_transform(RID p_body, int p_shape_idx) const {
+Transform3D BulletPhysicsServer3D::body_get_shape_transform(RID p_body, int p_shape_idx) const {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, Transform());
+ ERR_FAIL_COND_V(!body, Transform3D());
return body->get_shape_transform(p_shape_idx);
}
@@ -842,7 +842,7 @@ PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_bod
return BulletPhysicsDirectBodyState3D::get_singleton(body);
}
-bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -850,7 +850,7 @@ bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform &p_from
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes);
}
-int BulletPhysicsServer3D::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
+int BulletPhysicsServer3D::body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0);
ERR_FAIL_COND_V(!body->get_space(), 0);
@@ -990,7 +990,7 @@ Variant BulletPhysicsServer3D::soft_body_get_state(RID p_body, BodyState p_state
return Variant();
}
-void BulletPhysicsServer3D::soft_body_set_transform(RID p_body, const Transform &p_transform) {
+void BulletPhysicsServer3D::soft_body_set_transform(RID p_body, const Transform3D &p_transform) {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -1205,7 +1205,7 @@ Vector3 BulletPhysicsServer3D::pin_joint_get_local_b(RID p_joint) const {
return pin_joint->getPivotInB();
}
-RID BulletPhysicsServer3D::joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) {
+RID BulletPhysicsServer3D::joint_create_hinge(RID p_body_A, const Transform3D &p_hinge_A, RID p_body_B, const Transform3D &p_hinge_B) {
RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A);
ERR_FAIL_COND_V(!body_A, RID());
JointAssertSpace(body_A, "A", RID());
@@ -1277,7 +1277,7 @@ bool BulletPhysicsServer3D::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_f
return hinge_joint->get_flag(p_flag);
}
-RID BulletPhysicsServer3D::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+RID BulletPhysicsServer3D::joint_create_slider(RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A);
ERR_FAIL_COND_V(!body_A, RID());
JointAssertSpace(body_A, "A", RID());
@@ -1313,7 +1313,7 @@ real_t BulletPhysicsServer3D::slider_joint_get_param(RID p_joint, SliderJointPar
return slider_joint->get_param(p_param);
}
-RID BulletPhysicsServer3D::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+RID BulletPhysicsServer3D::joint_create_cone_twist(RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A);
ERR_FAIL_COND_V(!body_A, RID());
JointAssertSpace(body_A, "A", RID());
@@ -1347,7 +1347,7 @@ real_t BulletPhysicsServer3D::cone_twist_joint_get_param(RID p_joint, ConeTwistJ
return coneTwist_joint->get_param(p_param);
}
-RID BulletPhysicsServer3D::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+RID BulletPhysicsServer3D::joint_create_generic_6dof(RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A);
ERR_FAIL_COND_V(!body_A, RID());
JointAssertSpace(body_A, "A", RID());
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index de0379c873..d34d619ba2 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -134,12 +134,12 @@ public:
virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override;
virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override;
- virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) override;
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) override;
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) override;
- virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) override;
+ virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) override;
virtual int area_get_shape_count(RID p_area) const override;
virtual RID area_get_shape(RID p_area, int p_shape_idx) const override;
- virtual Transform area_get_shape_transform(RID p_area, int p_shape_idx) const override;
+ virtual Transform3D area_get_shape_transform(RID p_area, int p_shape_idx) const override;
virtual void area_remove_shape(RID p_area, int p_shape_idx) override;
virtual void area_clear_shapes(RID p_area) override;
virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) override;
@@ -153,8 +153,8 @@ public:
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) override;
virtual Variant area_get_param(RID p_area, AreaParameter p_param) const override;
- virtual void area_set_transform(RID p_area, const Transform &p_transform) override;
- virtual Transform area_get_transform(RID p_area) const override;
+ virtual void area_set_transform(RID p_area, const Transform3D &p_transform) override;
+ virtual Transform3D area_get_transform(RID p_area) const override;
virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override;
@@ -166,7 +166,7 @@ public:
/* RIGID BODY API */
- virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false) override;
+ virtual RID body_create(BodyMode p_mode = BODY_MODE_DYNAMIC, bool p_init_sleeping = false) override;
virtual void body_set_space(RID p_body, RID p_space) override;
virtual RID body_get_space(RID p_body) const override;
@@ -174,14 +174,14 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode) override;
virtual BodyMode body_get_mode(RID p_body) const override;
- virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) override;
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) override;
// Not supported, Please remove and add new shape
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) override;
- virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) override;
+ virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) override;
virtual int body_get_shape_count(RID p_body) const override;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const override;
- virtual Transform body_get_shape_transform(RID p_body, int p_shape_idx) const override;
+ virtual Transform3D body_get_shape_transform(RID p_body, int p_shape_idx) const override;
virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) override;
@@ -253,8 +253,8 @@ public:
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
- virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
- virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
+ virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
+ virtual int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
/* SOFT BODY API */
@@ -283,7 +283,7 @@ public:
virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const override;
/// Special function. This function has bad performance
- virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) override;
+ virtual void soft_body_set_transform(RID p_body, const Transform3D &p_transform) override;
virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override;
@@ -333,7 +333,7 @@ public:
virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) override;
virtual Vector3 pin_joint_get_local_b(RID p_joint) const override;
- virtual RID joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) override;
+ virtual RID joint_create_hinge(RID p_body_A, const Transform3D &p_hinge_A, RID p_body_B, const Transform3D &p_hinge_B) override;
virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) override;
virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) override;
@@ -343,19 +343,19 @@ public:
virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const override;
/// Reference frame is A
- virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override;
+ virtual RID joint_create_slider(RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override;
virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) override;
virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const override;
/// Reference frame is A
- virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override;
+ virtual RID joint_create_cone_twist(RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override;
virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) override;
virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const override;
/// Reference frame is A
- virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override;
+ virtual RID joint_create_generic_6dof(RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override;
virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) override;
virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) override;
diff --git a/modules/bullet/bullet_types_converter.cpp b/modules/bullet/bullet_types_converter.cpp
index 19d4816372..01461767bd 100644
--- a/modules/bullet/bullet_types_converter.cpp
+++ b/modules/bullet/bullet_types_converter.cpp
@@ -59,7 +59,7 @@ void INVERT_B_TO_G(btMatrix3x3 const &inVal, Basis &outVal) {
INVERT_B_TO_G(inVal[2], outVal[2]);
}
-void B_TO_G(btTransform const &inVal, Transform &outVal) {
+void B_TO_G(btTransform const &inVal, Transform3D &outVal) {
B_TO_G(inVal.getBasis(), outVal.basis);
B_TO_G(inVal.getOrigin(), outVal.origin);
}
@@ -89,7 +89,7 @@ void INVERT_G_TO_B(Basis const &inVal, btMatrix3x3 &outVal) {
INVERT_G_TO_B(inVal[2], outVal[2]);
}
-void G_TO_B(Transform const &inVal, btTransform &outVal) {
+void G_TO_B(Transform3D const &inVal, btTransform &outVal) {
G_TO_B(inVal.basis, outVal.getBasis());
G_TO_B(inVal.origin, outVal.getOrigin());
}
diff --git a/modules/bullet/bullet_types_converter.h b/modules/bullet/bullet_types_converter.h
index ca9b7175dd..e184fe1769 100644
--- a/modules/bullet/bullet_types_converter.h
+++ b/modules/bullet/bullet_types_converter.h
@@ -32,7 +32,7 @@
#define BULLET_TYPES_CONVERTER_H
#include "core/math/basis.h"
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include "core/math/vector3.h"
#include "core/typedefs.h"
@@ -49,14 +49,14 @@ extern void B_TO_G(btVector3 const &inVal, Vector3 &outVal);
extern void INVERT_B_TO_G(btVector3 const &inVal, Vector3 &outVal);
extern void B_TO_G(btMatrix3x3 const &inVal, Basis &outVal);
extern void INVERT_B_TO_G(btMatrix3x3 const &inVal, Basis &outVal);
-extern void B_TO_G(btTransform const &inVal, Transform &outVal);
+extern void B_TO_G(btTransform const &inVal, Transform3D &outVal);
// Godot TO Bullet
extern void G_TO_B(Vector3 const &inVal, btVector3 &outVal);
extern void INVERT_G_TO_B(Vector3 const &inVal, btVector3 &outVal);
extern void G_TO_B(Basis const &inVal, btMatrix3x3 &outVal);
extern void INVERT_G_TO_B(Basis const &inVal, btMatrix3x3 &outVal);
-extern void G_TO_B(Transform const &inVal, btTransform &outVal);
+extern void G_TO_B(Transform3D const &inVal, btTransform &outVal);
extern void UNSCALE_BT_BASIS(btTransform &scaledBasis);
#endif
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp
index d9f5beb5a1..c45bd5bbc0 100644
--- a/modules/bullet/collision_object_bullet.cpp
+++ b/modules/bullet/collision_object_bullet.cpp
@@ -49,7 +49,7 @@
CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {}
-void CollisionObjectBullet::ShapeWrapper::set_transform(const Transform &p_transform) {
+void CollisionObjectBullet::ShapeWrapper::set_transform(const Transform3D &p_transform) {
G_TO_B(p_transform.get_basis().get_scale_abs(), scale);
G_TO_B(p_transform, transform);
UNSCALE_BT_BASIS(transform);
@@ -193,7 +193,7 @@ int CollisionObjectBullet::get_godot_object_flags() const {
return bt_collision_object->getUserIndex2();
}
-void CollisionObjectBullet::set_transform(const Transform &p_global_transform) {
+void CollisionObjectBullet::set_transform(const Transform3D &p_global_transform) {
set_body_scale(p_global_transform.basis.get_scale_abs());
btTransform bt_transform;
@@ -203,8 +203,8 @@ void CollisionObjectBullet::set_transform(const Transform &p_global_transform) {
set_transform__bullet(bt_transform);
}
-Transform CollisionObjectBullet::get_transform() const {
- Transform t;
+Transform3D CollisionObjectBullet::get_transform() const {
+ Transform3D t;
B_TO_G(get_transform__bullet(), t);
t.basis.scale(body_scale);
return t;
@@ -230,7 +230,7 @@ RigidCollisionObjectBullet::~RigidCollisionObjectBullet() {
}
}
-void RigidCollisionObjectBullet::add_shape(ShapeBullet *p_shape, const Transform &p_transform, bool p_disabled) {
+void RigidCollisionObjectBullet::add_shape(ShapeBullet *p_shape, const Transform3D &p_transform, bool p_disabled) {
shapes.push_back(ShapeWrapper(p_shape, p_transform, !p_disabled));
p_shape->add_owner(this);
reload_shapes();
@@ -296,7 +296,7 @@ void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBod
}
}
-void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) {
+void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform3D &p_transform) {
ERR_FAIL_INDEX(p_index, get_shape_count());
shapes.write[p_index].set_transform(p_transform);
@@ -307,8 +307,8 @@ const btTransform &RigidCollisionObjectBullet::get_bt_shape_transform(int p_inde
return shapes[p_index].transform;
}
-Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const {
- Transform trs;
+Transform3D RigidCollisionObjectBullet::get_shape_transform(int p_index) const {
+ Transform3D trs;
B_TO_G(shapes[p_index].transform, trs);
return trs;
}
diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h
index c8081a53f1..944ab89b87 100644
--- a/modules/bullet/collision_object_bullet.h
+++ b/modules/bullet/collision_object_bullet.h
@@ -31,7 +31,7 @@
#ifndef COLLISION_OBJECT_BULLET_H
#define COLLISION_OBJECT_BULLET_H
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include "core/math/vector3.h"
#include "core/object/class_db.h"
#include "core/templates/vset.h"
@@ -83,7 +83,7 @@ public:
set_transform(p_transform);
}
- ShapeWrapper(ShapeBullet *p_shape, const Transform &p_transform, bool p_active) :
+ ShapeWrapper(ShapeBullet *p_shape, const Transform3D &p_transform, bool p_active) :
shape(p_shape),
active(p_active) {
set_transform(p_transform);
@@ -102,7 +102,7 @@ public:
active = otherShape.active;
}
- void set_transform(const Transform &p_transform);
+ void set_transform(const Transform3D &p_transform);
void set_transform(const btTransform &p_transform);
btTransform get_adjusted_transform() const;
@@ -202,8 +202,8 @@ public:
void set_godot_object_flags(int flags);
int get_godot_object_flags() const;
- void set_transform(const Transform &p_global_transform);
- Transform get_transform() const;
+ void set_transform(const Transform3D &p_global_transform);
+ Transform3D get_transform() const;
virtual void set_transform__bullet(const btTransform &p_global_transform);
virtual const btTransform &get_transform__bullet() const;
@@ -225,7 +225,7 @@ public:
_FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; }
- void add_shape(ShapeBullet *p_shape, const Transform &p_transform = Transform(), bool p_disabled = false);
+ void add_shape(ShapeBullet *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false);
void set_shape(int p_index, ShapeBullet *p_shape);
int get_shape_count() const;
@@ -238,10 +238,10 @@ public:
void remove_shape_full(int p_index);
void remove_all_shapes(bool p_permanentlyFromThisBody = false, bool p_force_not_reload = false);
- void set_shape_transform(int p_index, const Transform &p_transform);
+ void set_shape_transform(int p_index, const Transform3D &p_transform);
const btTransform &get_bt_shape_transform(int p_index) const;
- Transform get_shape_transform(int p_index) const;
+ Transform3D get_shape_transform(int p_index) const;
void set_shape_disabled(int p_index, bool p_disabled);
bool is_shape_disabled(int p_index);
diff --git a/modules/bullet/cone_twist_joint_bullet.cpp b/modules/bullet/cone_twist_joint_bullet.cpp
index e785780c5b..34516d8b3b 100644
--- a/modules/bullet/cone_twist_joint_bullet.cpp
+++ b/modules/bullet/cone_twist_joint_bullet.cpp
@@ -40,16 +40,16 @@
@author AndreaCatania
*/
-ConeTwistJointBullet::ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &rbAFrame, const Transform &rbBFrame) :
+ConeTwistJointBullet::ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame) :
JointBullet() {
- Transform scaled_AFrame(rbAFrame.scaled(rbA->get_body_scale()));
+ Transform3D scaled_AFrame(rbAFrame.scaled(rbA->get_body_scale()));
scaled_AFrame.basis.rotref_posscale_decomposition(scaled_AFrame.basis);
btTransform btFrameA;
G_TO_B(scaled_AFrame, btFrameA);
if (rbB) {
- Transform scaled_BFrame(rbBFrame.scaled(rbB->get_body_scale()));
+ Transform3D scaled_BFrame(rbBFrame.scaled(rbB->get_body_scale()));
scaled_BFrame.basis.rotref_posscale_decomposition(scaled_BFrame.basis);
btTransform btFrameB;
diff --git a/modules/bullet/cone_twist_joint_bullet.h b/modules/bullet/cone_twist_joint_bullet.h
index 7d6bafd292..7e51f7d644 100644
--- a/modules/bullet/cone_twist_joint_bullet.h
+++ b/modules/bullet/cone_twist_joint_bullet.h
@@ -43,7 +43,7 @@ class ConeTwistJointBullet : public JointBullet {
class btConeTwistConstraint *coneConstraint;
public:
- ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &rbAFrame, const Transform &rbBFrame);
+ ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame);
virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_CONE_TWIST; }
diff --git a/modules/bullet/config.py b/modules/bullet/config.py
index be7cf74f6f..83605f1f9b 100644
--- a/modules/bullet/config.py
+++ b/modules/bullet/config.py
@@ -1,6 +1,7 @@
def can_build(env, platform):
# API Changed and bullet is disabled at the moment
return False
+ # Later change to return not env["disable_3d"]
def configure(env):
diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp
index 43ad6c56d5..7e04d57b9d 100644
--- a/modules/bullet/generic_6dof_joint_bullet.cpp
+++ b/modules/bullet/generic_6dof_joint_bullet.cpp
@@ -40,7 +40,7 @@
@author AndreaCatania
*/
-Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB) :
+Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform3D &frameInA, const Transform3D &frameInB) :
JointBullet() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < PhysicsServer3D::G6DOF_JOINT_FLAG_MAX; j++) {
@@ -48,7 +48,7 @@ Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBu
}
}
- Transform scaled_AFrame(frameInA.scaled(rbA->get_body_scale()));
+ Transform3D scaled_AFrame(frameInA.scaled(rbA->get_body_scale()));
scaled_AFrame.basis.rotref_posscale_decomposition(scaled_AFrame.basis);
@@ -56,7 +56,7 @@ Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBu
G_TO_B(scaled_AFrame, btFrameA);
if (rbB) {
- Transform scaled_BFrame(frameInB.scaled(rbB->get_body_scale()));
+ Transform3D scaled_BFrame(frameInB.scaled(rbB->get_body_scale()));
scaled_BFrame.basis.rotref_posscale_decomposition(scaled_BFrame.basis);
@@ -71,30 +71,30 @@ Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBu
setup(sixDOFConstraint);
}
-Transform Generic6DOFJointBullet::getFrameOffsetA() const {
+Transform3D Generic6DOFJointBullet::getFrameOffsetA() const {
btTransform btTrs = sixDOFConstraint->getFrameOffsetA();
- Transform gTrs;
+ Transform3D gTrs;
B_TO_G(btTrs, gTrs);
return gTrs;
}
-Transform Generic6DOFJointBullet::getFrameOffsetB() const {
+Transform3D Generic6DOFJointBullet::getFrameOffsetB() const {
btTransform btTrs = sixDOFConstraint->getFrameOffsetB();
- Transform gTrs;
+ Transform3D gTrs;
B_TO_G(btTrs, gTrs);
return gTrs;
}
-Transform Generic6DOFJointBullet::getFrameOffsetA() {
+Transform3D Generic6DOFJointBullet::getFrameOffsetA() {
btTransform btTrs = sixDOFConstraint->getFrameOffsetA();
- Transform gTrs;
+ Transform3D gTrs;
B_TO_G(btTrs, gTrs);
return gTrs;
}
-Transform Generic6DOFJointBullet::getFrameOffsetB() {
+Transform3D Generic6DOFJointBullet::getFrameOffsetB() {
btTransform btTrs = sixDOFConstraint->getFrameOffsetB();
- Transform gTrs;
+ Transform3D gTrs;
B_TO_G(btTrs, gTrs);
return gTrs;
}
diff --git a/modules/bullet/generic_6dof_joint_bullet.h b/modules/bullet/generic_6dof_joint_bullet.h
index 62b8e85a81..00567e3085 100644
--- a/modules/bullet/generic_6dof_joint_bullet.h
+++ b/modules/bullet/generic_6dof_joint_bullet.h
@@ -48,14 +48,14 @@ class Generic6DOFJointBullet : public JointBullet {
bool flags[3][PhysicsServer3D::G6DOF_JOINT_FLAG_MAX];
public:
- Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB);
+ Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform3D &frameInA, const Transform3D &frameInB);
virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_6DOF; }
- Transform getFrameOffsetA() const;
- Transform getFrameOffsetB() const;
- Transform getFrameOffsetA();
- Transform getFrameOffsetB();
+ Transform3D getFrameOffsetA() const;
+ Transform3D getFrameOffsetB() const;
+ Transform3D getFrameOffsetA();
+ Transform3D getFrameOffsetB();
void set_linear_lower_limit(const Vector3 &linearLower);
void set_linear_upper_limit(const Vector3 &linearUpper);
diff --git a/modules/bullet/hinge_joint_bullet.cpp b/modules/bullet/hinge_joint_bullet.cpp
index 4ceb98729f..b5fe50cf5f 100644
--- a/modules/bullet/hinge_joint_bullet.cpp
+++ b/modules/bullet/hinge_joint_bullet.cpp
@@ -40,16 +40,16 @@
@author AndreaCatania
*/
-HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameA, const Transform &frameB) :
+HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform3D &frameA, const Transform3D &frameB) :
JointBullet() {
- Transform scaled_AFrame(frameA.scaled(rbA->get_body_scale()));
+ Transform3D scaled_AFrame(frameA.scaled(rbA->get_body_scale()));
scaled_AFrame.basis.rotref_posscale_decomposition(scaled_AFrame.basis);
btTransform btFrameA;
G_TO_B(scaled_AFrame, btFrameA);
if (rbB) {
- Transform scaled_BFrame(frameB.scaled(rbB->get_body_scale()));
+ Transform3D scaled_BFrame(frameB.scaled(rbB->get_body_scale()));
scaled_BFrame.basis.rotref_posscale_decomposition(scaled_BFrame.basis);
btTransform btFrameB;
diff --git a/modules/bullet/hinge_joint_bullet.h b/modules/bullet/hinge_joint_bullet.h
index 06a95be374..dd0f69ba68 100644
--- a/modules/bullet/hinge_joint_bullet.h
+++ b/modules/bullet/hinge_joint_bullet.h
@@ -41,7 +41,7 @@ class HingeJointBullet : public JointBullet {
class btHingeConstraint *hingeConstraint;
public:
- HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameA, const Transform &frameB);
+ HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform3D &frameA, const Transform3D &frameB);
HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB);
virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_HINGE; }
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 675da1a597..ce39d4f0df 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -106,11 +106,11 @@ Vector3 BulletPhysicsDirectBodyState3D::get_angular_velocity() const {
return body->get_angular_velocity();
}
-void BulletPhysicsDirectBodyState3D::set_transform(const Transform &p_transform) {
+void BulletPhysicsDirectBodyState3D::set_transform(const Transform3D &p_transform) {
body->set_transform(p_transform);
}
-Transform BulletPhysicsDirectBodyState3D::get_transform() const {
+Transform3D BulletPhysicsDirectBodyState3D::get_transform() const {
return body->get_transform();
}
@@ -268,7 +268,7 @@ RigidBodyBullet::RigidBodyBullet() :
reload_shapes();
setupBulletCollisionObject(btBody);
- set_mode(PhysicsServer3D::BODY_MODE_RIGID);
+ set_mode(PhysicsServer3D::BODY_MODE_DYNAMIC);
reload_axis_lock();
areasWhereIam.resize(maxAreasWhereIam);
@@ -531,14 +531,14 @@ void RigidBodyBullet::set_mode(PhysicsServer3D::BodyMode p_mode) {
reload_axis_lock();
_internal_set_mass(0);
break;
- case PhysicsServer3D::BODY_MODE_RIGID:
- mode = PhysicsServer3D::BODY_MODE_RIGID;
+ case PhysicsServer3D::BODY_MODE_DYNAMIC:
+ mode = PhysicsServer3D::BODY_MODE_DYNAMIC;
reload_axis_lock();
_internal_set_mass(0 == mass ? 1 : mass);
scratch_space_override_modificator();
break;
- case PhysicsServer3D::BODY_MODE_CHARACTER:
- mode = PhysicsServer3D::BODY_MODE_CHARACTER;
+ case PhysicsServer3D::MODE_DYNAMIC_LOCKED:
+ mode = PhysicsServer3D::MODE_DYNAMIC_LOCKED;
reload_axis_lock();
_internal_set_mass(0 == mass ? 1 : mass);
scratch_space_override_modificator();
@@ -711,7 +711,7 @@ bool RigidBodyBullet::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const {
void RigidBodyBullet::reload_axis_lock() {
btBody->setLinearFactor(btVector3(btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_X)), btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Y)), btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Z))));
- if (PhysicsServer3D::BODY_MODE_CHARACTER == mode) {
+ if (PhysicsServer3D::MODE_DYNAMIC_LOCKED == mode) {
/// When character angular is always locked
btBody->setAngularFactor(btVector3(0., 0., 0.));
} else {
@@ -1006,7 +1006,7 @@ void RigidBodyBullet::_internal_set_mass(real_t p_mass) {
// Rigidbody is dynamic if and only if mass is non Zero, otherwise static
const bool isDynamic = p_mass != 0.f;
if (isDynamic) {
- if (PhysicsServer3D::BODY_MODE_RIGID != mode && PhysicsServer3D::BODY_MODE_CHARACTER != mode) {
+ if (PhysicsServer3D::BODY_MODE_DYNAMIC != mode && PhysicsServer3D::MODE_DYNAMIC_LOCKED != mode) {
return;
}
@@ -1015,7 +1015,7 @@ void RigidBodyBullet::_internal_set_mass(real_t p_mass) {
mainShape->calculateLocalInertia(p_mass, localInertia);
}
- if (PhysicsServer3D::BODY_MODE_RIGID == mode) {
+ if (PhysicsServer3D::BODY_MODE_DYNAMIC == mode) {
btBody->setCollisionFlags(clearedCurrentFlags); // Just set the flags without Kin and Static
} else {
btBody->setCollisionFlags(clearedCurrentFlags | btCollisionObject::CF_CHARACTER_OBJECT);
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 843ff4a7af..606df7134b 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -107,8 +107,8 @@ public:
virtual void set_angular_velocity(const Vector3 &p_velocity) override;
virtual Vector3 get_angular_velocity() const override;
- virtual void set_transform(const Transform &p_transform) override;
- virtual Transform get_transform() const override;
+ virtual void set_transform(const Transform3D &p_transform) override;
+ virtual Transform3D get_transform() const override;
virtual void add_central_force(const Vector3 &p_force) override;
virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
diff --git a/modules/bullet/slider_joint_bullet.cpp b/modules/bullet/slider_joint_bullet.cpp
index 45c892851b..1d83118468 100644
--- a/modules/bullet/slider_joint_bullet.cpp
+++ b/modules/bullet/slider_joint_bullet.cpp
@@ -40,16 +40,16 @@
@author AndreaCatania
*/
-SliderJointBullet::SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB) :
+SliderJointBullet::SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform3D &frameInA, const Transform3D &frameInB) :
JointBullet() {
- Transform scaled_AFrame(frameInA.scaled(rbA->get_body_scale()));
+ Transform3D scaled_AFrame(frameInA.scaled(rbA->get_body_scale()));
scaled_AFrame.basis.rotref_posscale_decomposition(scaled_AFrame.basis);
btTransform btFrameA;
G_TO_B(scaled_AFrame, btFrameA);
if (rbB) {
- Transform scaled_BFrame(frameInB.scaled(rbB->get_body_scale()));
+ Transform3D scaled_BFrame(frameInB.scaled(rbB->get_body_scale()));
scaled_BFrame.basis.rotref_posscale_decomposition(scaled_BFrame.basis);
btTransform btFrameB;
@@ -70,44 +70,44 @@ const RigidBodyBullet *SliderJointBullet::getRigidBodyB() const {
return static_cast<RigidBodyBullet *>(sliderConstraint->getRigidBodyB().getUserPointer());
}
-const Transform SliderJointBullet::getCalculatedTransformA() const {
+const Transform3D SliderJointBullet::getCalculatedTransformA() const {
btTransform btTransform = sliderConstraint->getCalculatedTransformA();
- Transform gTrans;
+ Transform3D gTrans;
B_TO_G(btTransform, gTrans);
return gTrans;
}
-const Transform SliderJointBullet::getCalculatedTransformB() const {
+const Transform3D SliderJointBullet::getCalculatedTransformB() const {
btTransform btTransform = sliderConstraint->getCalculatedTransformB();
- Transform gTrans;
+ Transform3D gTrans;
B_TO_G(btTransform, gTrans);
return gTrans;
}
-const Transform SliderJointBullet::getFrameOffsetA() const {
+const Transform3D SliderJointBullet::getFrameOffsetA() const {
btTransform btTransform = sliderConstraint->getFrameOffsetA();
- Transform gTrans;
+ Transform3D gTrans;
B_TO_G(btTransform, gTrans);
return gTrans;
}
-const Transform SliderJointBullet::getFrameOffsetB() const {
+const Transform3D SliderJointBullet::getFrameOffsetB() const {
btTransform btTransform = sliderConstraint->getFrameOffsetB();
- Transform gTrans;
+ Transform3D gTrans;
B_TO_G(btTransform, gTrans);
return gTrans;
}
-Transform SliderJointBullet::getFrameOffsetA() {
+Transform3D SliderJointBullet::getFrameOffsetA() {
btTransform btTransform = sliderConstraint->getFrameOffsetA();
- Transform gTrans;
+ Transform3D gTrans;
B_TO_G(btTransform, gTrans);
return gTrans;
}
-Transform SliderJointBullet::getFrameOffsetB() {
+Transform3D SliderJointBullet::getFrameOffsetB() {
btTransform btTransform = sliderConstraint->getFrameOffsetB();
- Transform gTrans;
+ Transform3D gTrans;
B_TO_G(btTransform, gTrans);
return gTrans;
}
diff --git a/modules/bullet/slider_joint_bullet.h b/modules/bullet/slider_joint_bullet.h
index 90964671c2..0c93558449 100644
--- a/modules/bullet/slider_joint_bullet.h
+++ b/modules/bullet/slider_joint_bullet.h
@@ -44,18 +44,18 @@ class SliderJointBullet : public JointBullet {
public:
/// Reference frame is A
- SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB);
+ SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform3D &frameInA, const Transform3D &frameInB);
virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_SLIDER; }
const RigidBodyBullet *getRigidBodyA() const;
const RigidBodyBullet *getRigidBodyB() const;
- const Transform getCalculatedTransformA() const;
- const Transform getCalculatedTransformB() const;
- const Transform getFrameOffsetA() const;
- const Transform getFrameOffsetB() const;
- Transform getFrameOffsetA();
- Transform getFrameOffsetB();
+ const Transform3D getCalculatedTransformA() const;
+ const Transform3D getCalculatedTransformB() const;
+ const Transform3D getFrameOffsetA() const;
+ const Transform3D getFrameOffsetB() const;
+ Transform3D getFrameOffsetA();
+ Transform3D getFrameOffsetB();
real_t getLowerLinLimit() const;
void setLowerLinLimit(real_t lowerLimit);
real_t getUpperLinLimit() const;
diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp
index 2c8727baf2..bbbb0e7851 100644
--- a/modules/bullet/soft_body_bullet.cpp
+++ b/modules/bullet/soft_body_bullet.cpp
@@ -136,7 +136,7 @@ void SoftBodyBullet::destroy_soft_body() {
bt_soft_body = nullptr;
}
-void SoftBodyBullet::set_soft_transform(const Transform &p_transform) {
+void SoftBodyBullet::set_soft_transform(const Transform3D &p_transform) {
reset_all_node_positions();
move_all_nodes(p_transform);
}
@@ -159,7 +159,7 @@ AABB SoftBodyBullet::get_bounds() const {
return aabb;
}
-void SoftBodyBullet::move_all_nodes(const Transform &p_transform) {
+void SoftBodyBullet::move_all_nodes(const Transform3D &p_transform) {
if (!bt_soft_body) {
return;
}
diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h
index 87023b2517..63708b57a7 100644
--- a/modules/bullet/soft_body_bullet.h
+++ b/modules/bullet/soft_body_bullet.h
@@ -104,11 +104,11 @@ public:
void destroy_soft_body();
// Special function. This function has bad performance
- void set_soft_transform(const Transform &p_transform);
+ void set_soft_transform(const Transform3D &p_transform);
AABB get_bounds() const;
- void move_all_nodes(const Transform &p_transform);
+ void move_all_nodes(const Transform3D &p_transform);
void set_node_position(int node_index, const Vector3 &p_global_position);
void set_node_position(int node_index, const btVector3 &p_global_position);
void get_node_position(int node_index, Vector3 &r_position) const;
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index bdaec4a09e..33dd9ef56d 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -117,7 +117,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V
}
}
-int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0) {
return 0;
}
@@ -152,7 +152,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra
return btQuery.m_count;
}
-bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &r_closest_safe, real_t &r_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
+bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &r_closest_safe, real_t &r_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
r_closest_safe = 0.0f;
r_closest_unsafe = 0.0f;
btVector3 bt_motion;
@@ -214,7 +214,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf
}
/// Returns the list of contacts pairs in this order: Local contact, other body contact
-bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0) {
return false;
}
@@ -250,7 +250,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &
return btQuery.m_count;
}
-bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape);
ERR_FAIL_COND_V(!shape, false);
@@ -445,7 +445,7 @@ real_t SpaceBullet::get_param(PhysicsServer3D::SpaceParameter p_param) {
case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO:
case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
default:
- WARN_PRINT("The SpaceBullet doesn't support this get parameter (" + itos(p_param) + "), 0 is returned.");
+ WARN_PRINT("The SpaceBullet doesn't support this get parameter (" + itos(p_param) + "), 0 is returned.");
return 0.f;
}
}
@@ -908,7 +908,7 @@ static Ref<StandardMaterial3D> red_mat;
static Ref<StandardMaterial3D> blue_mat;
#endif
-bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) {
#if debug_test_motion
/// Yes I know this is not good, but I've used it as fast debugging hack.
/// I'm leaving it here just for speedup the other eventual debugs
@@ -1062,7 +1062,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
return has_penetration;
}
-int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin) {
+int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin) {
btTransform body_transform;
G_TO_B(p_transform, body_transform);
UNSCALE_BT_BASIS(body_transform);
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index 87aa2b9e93..36d0538e6b 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -78,11 +78,11 @@ public:
virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override;
- virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &r_closest_safe, real_t &r_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
+ virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &r_closest_safe, real_t &r_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
/// Returns the list of contacts pairs in this order: Local contact, other body contact
- virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override;
};
@@ -188,8 +188,8 @@ public:
real_t get_linear_damp() const { return linear_damp; }
real_t get_angular_damp() const { return angular_damp; }
- bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes);
- int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin);
+ bool test_body_motion(RigidBodyBullet *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes);
+ int test_ray_separation(RigidBodyBullet *p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin);
private:
void create_empty_world(bool p_create_soft_world);
diff --git a/modules/csg/config.py b/modules/csg/config.py
index 9106cbceca..3991b846f9 100644
--- a/modules/csg/config.py
+++ b/modules/csg/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return True
+ return not env["disable_3d"]
def configure(env):
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 7387842259..5a37486568 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -265,7 +265,7 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector<
_regen_face_aabbs();
}
-void CSGBrush::copy_from(const CSGBrush &p_brush, const Transform &p_xform) {
+void CSGBrush::copy_from(const CSGBrush &p_brush, const Transform3D &p_xform) {
faces = p_brush.faces;
materials = p_brush.materials;
diff --git a/modules/csg/csg.h b/modules/csg/csg.h
index 3fbed66e5c..c872860486 100644
--- a/modules/csg/csg.h
+++ b/modules/csg/csg.h
@@ -33,10 +33,10 @@
#include "core/math/aabb.h"
#include "core/math/plane.h"
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include "core/math/vector2.h"
#include "core/math/vector3.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/templates/list.h"
#include "core/templates/map.h"
#include "core/templates/oa_hash_map.h"
@@ -60,7 +60,7 @@ struct CSGBrush {
// Create a brush from faces.
void build_from_faces(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials, const Vector<bool> &p_invert_faces);
- void copy_from(const CSGBrush &p_brush, const Transform &p_xform);
+ void copy_from(const CSGBrush &p_brush, const Transform3D &p_xform);
};
struct CSGBrushOperation {
@@ -165,8 +165,8 @@ struct CSGBrushOperation {
Vector<Vertex2D> vertices;
Vector<Face2D> faces;
Plane plane;
- Transform to_2D;
- Transform to_3D;
+ Transform3D to_2D;
+ Transform3D to_3D;
float vertex_snap2 = 0.0;
inline int _get_point_idx(const Vector2 &p_point);
diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp
index 8a46dcca65..37a7d96de5 100644
--- a/modules/csg/csg_gizmos.cpp
+++ b/modules/csg/csg_gizmos.cpp
@@ -99,9 +99,9 @@ Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int
void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
- Transform gt = cs->get_global_transform();
+ Transform3D gt = cs->get_global_transform();
//gt.orthonormalize();
- Transform gi = gt.affine_inverse();
+ Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 541b7036ac..d6690bb96c 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -578,7 +578,7 @@ Array CSGShape3D::get_meshes() const {
if (root_mesh.is_valid()) {
Array arr;
arr.resize(2);
- arr[0] = Transform();
+ arr[0] = Transform3D();
arr[1] = root_mesh;
return arr;
}
@@ -923,45 +923,43 @@ CSGBrush *CSGSphere3D::_build_brush() {
Ref<Material> *materialsw = materials.ptrw();
bool *invertw = invert.ptrw();
+ const double lat_step = 1.0 / rings;
+ const double lon_step = 1.0 / radial_segments;
int face = 0;
- const double lat_step = Math_TAU / rings;
- const double lon_step = Math_TAU / radial_segments;
-
for (int i = 1; i <= rings; i++) {
- double lat0 = lat_step * (i - 1) - Math_TAU / 4;
- double z0 = Math::sin(lat0);
- double zr0 = Math::cos(lat0);
- double u0 = double(i - 1) / rings;
-
- double lat1 = lat_step * i - Math_TAU / 4;
- double z1 = Math::sin(lat1);
- double zr1 = Math::cos(lat1);
- double u1 = double(i) / rings;
-
- for (int j = radial_segments; j >= 1; j--) {
- double lng0 = lon_step * (j - 1);
+ double lat0 = Math_PI * (0.5 - (i - 1) * lat_step);
+ double c0 = Math::cos(lat0);
+ double s0 = Math::sin(lat0);
+ double v0 = double(i - 1) / rings;
+
+ double lat1 = Math_PI * (0.5 - i * lat_step);
+ double c1 = Math::cos(lat1);
+ double s1 = Math::sin(lat1);
+ double v1 = double(i) / rings;
+
+ for (int j = 1; j <= radial_segments; j++) {
+ double lng0 = Math_TAU * (0.5 - (j - 1) * lon_step);
double x0 = Math::cos(lng0);
double y0 = Math::sin(lng0);
- double v0 = double(i - 1) / radial_segments;
+ double u0 = double(j - 1) / radial_segments;
- double lng1 = lon_step * j;
+ double lng1 = Math_TAU * (0.5 - j * lon_step);
double x1 = Math::cos(lng1);
double y1 = Math::sin(lng1);
- double v1 = double(i) / radial_segments;
+ double u1 = double(j) / radial_segments;
Vector3 v[4] = {
- Vector3(x1 * zr0, z0, y1 * zr0) * radius,
- Vector3(x1 * zr1, z1, y1 * zr1) * radius,
- Vector3(x0 * zr1, z1, y0 * zr1) * radius,
- Vector3(x0 * zr0, z0, y0 * zr0) * radius
+ Vector3(x0 * c0, s0, y0 * c0) * radius,
+ Vector3(x1 * c0, s0, y1 * c0) * radius,
+ Vector3(x1 * c1, s1, y1 * c1) * radius,
+ Vector3(x0 * c1, s1, y0 * c1) * radius,
};
Vector2 u[4] = {
- Vector2(v1, u0),
- Vector2(v1, u1),
- Vector2(v0, u1),
- Vector2(v0, u0),
-
+ Vector2(u0, v0),
+ Vector2(u1, v0),
+ Vector2(u1, v1),
+ Vector2(u0, v1),
};
if (i < rings) {
@@ -1980,13 +1978,13 @@ CSGBrush *CSGPolygon3D::_build_brush() {
float u1 = 0.0;
float u2 = path_continuous_u ? 0.0 : 1.0;
- Transform path_to_this;
+ Transform3D path_to_this;
if (!path_local) {
// center on paths origin
path_to_this = get_global_transform().affine_inverse() * path->get_global_transform();
}
- Transform prev_xf;
+ Transform3D prev_xf;
Vector3 lookat_dir;
@@ -2008,7 +2006,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
ofs = 0.0;
}
- Transform xf;
+ Transform3D xf;
xf.origin = curve->interpolate_baked(ofs);
Vector3 local_dir;
diff --git a/modules/csg/doc_classes/CSGShape3D.xml b/modules/csg/doc_classes/CSGShape3D.xml
index dac556c7f1..01ec46e707 100644
--- a/modules/csg/doc_classes/CSGShape3D.xml
+++ b/modules/csg/doc_classes/CSGShape3D.xml
@@ -31,7 +31,7 @@
<return type="Array">
</return>
<description>
- Returns an [Array] with two elements, the first is the [Transform] of this node and the second is the root [Mesh] of this node. Only works when this node is the root shape.
+ Returns an [Array] with two elements, the first is the [Transform3D] of this node and the second is the root [Mesh] of this node. Only works when this node is the root shape.
</description>
</method>
<method name="is_root_shape" qualifiers="const">
diff --git a/modules/csg/icons/CSGBox3D.svg b/modules/csg/icons/CSGBox3D.svg
index ceef9196a7..2740cc2f8c 100644
--- a/modules/csg/icons/CSGBox3D.svg
+++ b/modules/csg/icons/CSGBox3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/><path d="m8 .94531-7 3.5v7.2227l7 3.5.29492-.14844c-.18282-.30101-.29492-.64737-.29492-1.0195v-2c0-.72651.40824-1.3664 1-1.7168v-1.6699l4-2v1.3867h1c.36419 0 .70336.10754 1 .2832v-3.8379zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002z" fill="#fc9c9c" stroke-width="1.0667"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#5fb2ff"/><path d="m8 .94531-7 3.5v7.2227l7 3.5.29492-.14844c-.18282-.30101-.29492-.64737-.29492-1.0195v-2c0-.72651.40824-1.3664 1-1.7168v-1.6699l4-2v1.3867h1c.36419 0 .70336.10754 1 .2832v-3.8379zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002z" fill="#fc7f7f" stroke-width="1.0667"/></svg>
diff --git a/modules/csg/icons/CSGCapsule3D.svg b/modules/csg/icons/CSGCapsule3D.svg
index 14e582ee84..db4f71864b 100644
--- a/modules/csg/icons/CSGCapsule3D.svg
+++ b/modules/csg/icons/CSGCapsule3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.7527 0-5 2.2418-5 4.9902v4.0176c0 2.7484 2.2473 4.9922 5 4.9922.092943 0 .18367-.008623.27539-.013672-.17055-.29341-.27539-.62792-.27539-.98633v-2c0-.72887.41095-1.3691 1.0059-1.7188v-.28125c.34771-.034464.68259-.10691 1.0156-.19922.10394-.99856.95603-1.8008 1.9785-1.8008h1v-2.0098c0-2.7484-2.2473-4.9902-5-4.9902zm-1.0059 2.127v4.8574c-.66556-.1047-1.2974-.37231-1.9941-.66211v-1.3223c0-1.3474.79841-2.4642 1.9941-2.873zm2.0117 0c1.1957.4088 1.9941 1.5256 1.9941 2.873v1.3457c-.68406.3054-1.3142.57292-1.9941.66602v-4.8848zm-4.0059 6.334c.67836.2231 1.3126.44599 1.9941.52539v2.8848c-1.1957-.4092-1.9941-1.5237-1.9941-2.8711v-.53906z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.7527 0-5 2.2418-5 4.9902v4.0176c0 2.7484 2.2473 4.9922 5 4.9922.092943 0 .18367-.008623.27539-.013672-.17055-.29341-.27539-.62792-.27539-.98633v-2c0-.72887.41095-1.3691 1.0059-1.7188v-.28125c.34771-.034464.68259-.10691 1.0156-.19922.10394-.99856.95603-1.8008 1.9785-1.8008h1v-2.0098c0-2.7484-2.2473-4.9902-5-4.9902zm-1.0059 2.127v4.8574c-.66556-.1047-1.2974-.37231-1.9941-.66211v-1.3223c0-1.3474.79841-2.4642 1.9941-2.873zm2.0117 0c1.1957.4088 1.9941 1.5256 1.9941 2.873v1.3457c-.68406.3054-1.3142.57292-1.9941.66602v-4.8848zm-4.0059 6.334c.67836.2231 1.3126.44599 1.9941.52539v2.8848c-1.1957-.4092-1.9941-1.5237-1.9941-2.8711v-.53906z" fill="#fc7f7f"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#5fb2ff"/></svg>
diff --git a/modules/csg/icons/CSGCombiner3D.svg b/modules/csg/icons/CSGCombiner3D.svg
index 50ce4179d9..692ba54cb8 100644
--- a/modules/csg/icons/CSGCombiner3D.svg
+++ b/modules/csg/icons/CSGCombiner3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/><path d="m3 1c-1.1046 0-2 .89543-2 2h2zm2 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2c0-1.1046-.89543-2-2-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4v2h2v-2zm0 4c0 1.1046.89543 2 2 2v-2zm4 0v2h2v-2z" fill="#fc9c9c"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#5fb2ff"/><path d="m3 1c-1.1046 0-2 .89543-2 2h2zm2 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2c0-1.1046-.89543-2-2-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4v2h2v-2zm0 4c0 1.1046.89543 2 2 2v-2zm4 0v2h2v-2z" fill="#fc7f7f"/></svg>
diff --git a/modules/csg/icons/CSGCylinder3D.svg b/modules/csg/icons/CSGCylinder3D.svg
index c84594928a..4bc2427887 100644
--- a/modules/csg/icons/CSGCylinder3D.svg
+++ b/modules/csg/icons/CSGCylinder3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-1.7469 0-3.328.22648-4.5586.63672-.61528.20512-1.1471.45187-1.5898.80078-.44272.34891-.85156.88101-.85156 1.5625v8c0 .68149.40884 1.2155.85156 1.5645.44272.34891.97457.59577 1.5898.80078 1.2306.41024 2.8117.63477 4.5586.63477.095648 0 .18467-.008426.2793-.009766-.1722-.29446-.2793-.62995-.2793-.99023v-1c-1.5668 0-2.9867-.2195-3.9277-.5332-.46329-.15435-.90474-.33752-1.0723-.4668v-5.8125c.1468.058667.2835.12515.44141.17773 1.2306.41024 2.8117.63477 4.5586.63477s3.328-.22453 4.5586-.63477c.15791-.052267.29461-.11864.44141-.17773v1.8125h1c.36396 0 .70348.10774 1 .2832v-4.2832c0-.68149-.40884-1.2136-.85156-1.5625-.44272-.34891-.97457-.59566-1.5898-.80078-1.2306-.41024-2.8117-.63672-4.5586-.63672zm0 2c1.5668 0 2.9867.22145 3.9277.53516.46368.15456.80138.33741.96875.4668-.16752.12928-.50546.3105-.96875.46484-.94102.31371-2.361.5332-3.9277.5332s-2.9867-.2195-3.9277-.5332c-.46329-.15435-.80123-.33556-.96875-.46484.16737-.12939.50507-.31224.96875-.4668.94102-.31371 2.361-.53516 3.9277-.53516z" fill="#fc9c9c" stroke-width="1.0667" transform="scale(.9375)"/><path d="m11.25 8.4375c-.51938 0-.9375.41812-.9375.9375v.9375h1.875v1.875h.9375c.51938 0 .9375-.41812.9375-.9375v-1.875c0-.51938-.41812-.9375-.9375-.9375zm.9375 3.75h-1.875v-1.875h-.9375c-.51938 0-.9375.41812-.9375.9375v1.875c0 .51938.41812.9375.9375.9375h1.875c.51938 0 .9375-.41812.9375-.9375z" fill="#84c2ff"/></svg>
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-1.7469 0-3.328.22648-4.5586.63672-.61528.20512-1.1471.45187-1.5898.80078-.44272.34891-.85156.88101-.85156 1.5625v8c0 .68149.40884 1.2155.85156 1.5645.44272.34891.97457.59577 1.5898.80078 1.2306.41024 2.8117.63477 4.5586.63477.095648 0 .18467-.008426.2793-.009766-.1722-.29446-.2793-.62995-.2793-.99023v-1c-1.5668 0-2.9867-.2195-3.9277-.5332-.46329-.15435-.90474-.33752-1.0723-.4668v-5.8125c.1468.058667.2835.12515.44141.17773 1.2306.41024 2.8117.63477 4.5586.63477s3.328-.22453 4.5586-.63477c.15791-.052267.29461-.11864.44141-.17773v1.8125h1c.36396 0 .70348.10774 1 .2832v-4.2832c0-.68149-.40884-1.2136-.85156-1.5625-.44272-.34891-.97457-.59566-1.5898-.80078-1.2306-.41024-2.8117-.63672-4.5586-.63672zm0 2c1.5668 0 2.9867.22145 3.9277.53516.46368.15456.80138.33741.96875.4668-.16752.12928-.50546.3105-.96875.46484-.94102.31371-2.361.5332-3.9277.5332s-2.9867-.2195-3.9277-.5332c-.46329-.15435-.80123-.33556-.96875-.46484.16737-.12939.50507-.31224.96875-.4668.94102-.31371 2.361-.53516 3.9277-.53516z" fill="#fc7f7f" stroke-width="1.0667" transform="scale(.9375)"/><path d="m11.25 8.4375c-.51938 0-.9375.41812-.9375.9375v.9375h1.875v1.875h.9375c.51938 0 .9375-.41812.9375-.9375v-1.875c0-.51938-.41812-.9375-.9375-.9375zm.9375 3.75h-1.875v-1.875h-.9375c-.51938 0-.9375.41812-.9375.9375v1.875c0 .51938.41812.9375.9375.9375h1.875c.51938 0 .9375-.41812.9375-.9375z" fill="#5fb2ff"/></svg>
diff --git a/modules/csg/icons/CSGMesh3D.svg b/modules/csg/icons/CSGMesh3D.svg
index 962e71f6ae..8f4a1736fb 100644
--- a/modules/csg/icons/CSGMesh3D.svg
+++ b/modules/csg/icons/CSGMesh3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h3.2695v-2h-3.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l4.916 4.916c.31428-.20669.68609-.33008 1.084-.33008 0-.3979.12338-.76971.33008-1.084l-4.916-4.916h5.8574c.17478.30301.42598.55488.72852.73047v3.2695h2v-3.2715c.61771-.35663.99874-1.0152 1-1.7285 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h3.2695v-2h-3.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l4.916 4.916c.31428-.20669.68609-.33008 1.084-.33008 0-.3979.12338-.76971.33008-1.084l-4.916-4.916h5.8574c.17478.30301.42598.55488.72852.73047v3.2695h2v-3.2715c.61771-.35663.99874-1.0152 1-1.7285 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1z" fill="#fc7f7f"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#5fb2ff"/></svg>
diff --git a/modules/csg/icons/CSGPolygon3D.svg b/modules/csg/icons/CSGPolygon3D.svg
index 1d496e5fd9..971f3577bb 100644
--- a/modules/csg/icons/CSGPolygon3D.svg
+++ b/modules/csg/icons/CSGPolygon3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002c-.14254.00487-.28238.04016-.41016.10352l-6 3c-.33878.16944-.55276.51574-.55273.89453v5.832c-.105.61631.37487 1.1768 1 1.168h5v2c.0000216.67546.64487 1.1297 1.2617.95898-.16118-.28721-.26172-.61135-.26172-.95898v-2c0-.72673.40794-1.3664 1-1.7168v-1.666l4-2v1.3828h1c.36397 0 .70348.10774 1 .2832v-3.2773c.000006-.00195.000006-.0039094 0-.0058594.000026-.37879-.21395-.72509-.55273-.89453l-6-3c-.15022-.074574-.31679-.11017-.48438-.10352zm.037109 2.1172 3.7637 1.8809-2.7637 1.3809v-1.3809c-.0000552-.55226-.44774-.99994-1-1h-1.7617l1.7617-.88086zm-5 2.8809h4v4h-4z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002c-.14254.00487-.28238.04016-.41016.10352l-6 3c-.33878.16944-.55276.51574-.55273.89453v5.832c-.105.61631.37487 1.1768 1 1.168h5v2c.0000216.67546.64487 1.1297 1.2617.95898-.16118-.28721-.26172-.61135-.26172-.95898v-2c0-.72673.40794-1.3664 1-1.7168v-1.666l4-2v1.3828h1c.36397 0 .70348.10774 1 .2832v-3.2773c.000006-.00195.000006-.0039094 0-.0058594.000026-.37879-.21395-.72509-.55273-.89453l-6-3c-.15022-.074574-.31679-.11017-.48438-.10352zm.037109 2.1172 3.7637 1.8809-2.7637 1.3809v-1.3809c-.0000552-.55226-.44774-.99994-1-1h-1.7617l1.7617-.88086zm-5 2.8809h4v4h-4z" fill="#fc7f7f"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#5fb2ff"/></svg>
diff --git a/modules/csg/icons/CSGSphere3D.svg b/modules/csg/icons/CSGSphere3D.svg
index 639e38f49f..770af80632 100644
--- a/modules/csg/icons/CSGSphere3D.svg
+++ b/modules/csg/icons/CSGSphere3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 .093042 0 .18321-.01004.27539-.013672-.17055-.29341-.27539-.62792-.27539-.98633v-2c0-.72673.40794-1.3664 1-1.7168v-.33398c.34074-.019259.67728-.069097 1.0156-.10547.083091-1.0187.94713-1.8438 1.9844-1.8438h2c.35841 0 .69292.10484.98633.27539.003633-.092184.013672-.18235.013672-.27539 0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-.071342-2.6061-.29819-3.9434-.69141.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549.41253 3.637 2.0767 3.9414 4.1699-1.3046.36677-2.6158.60259-3.9414.6875zm-5.7793 6.2988c1.2733.31892 2.5337.50215 3.7793.5625v2.9414c-1.8291-.36719-3.266-1.7339-3.7793-3.5039z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 .093042 0 .18321-.01004.27539-.013672-.17055-.29341-.27539-.62792-.27539-.98633v-2c0-.72673.40794-1.3664 1-1.7168v-.33398c.34074-.019259.67728-.069097 1.0156-.10547.083091-1.0187.94713-1.8438 1.9844-1.8438h2c.35841 0 .69292.10484.98633.27539.003633-.092184.013672-.18235.013672-.27539 0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-.071342-2.6061-.29819-3.9434-.69141.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549.41253 3.637 2.0767 3.9414 4.1699-1.3046.36677-2.6158.60259-3.9414.6875zm-5.7793 6.2988c1.2733.31892 2.5337.50215 3.7793.5625v2.9414c-1.8291-.36719-3.266-1.7339-3.7793-3.5039z" fill="#fc7f7f"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#5fb2ff"/></svg>
diff --git a/modules/csg/icons/CSGTorus3D.svg b/modules/csg/icons/CSGTorus3D.svg
index eb8c0f37cb..ece9c68d28 100644
--- a/modules/csg/icons/CSGTorus3D.svg
+++ b/modules/csg/icons/CSGTorus3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3c-1.8145 0-3.4691.41721-4.7461 1.1621-1.277.745-2.2539 1.9082-2.2539 3.3379 0 1.4298.9769 2.5949 2.2539 3.3398s2.9316 1.1602 4.7461 1.1602c0-1.0907.90931-2 2-2 0-.080836.013744-.15778.023438-.23633-.61769.14673-1.3008.23633-2.0234.23633-1.4992 0-2.8437-.36687-3.7383-.88867-.89456-.5219-1.2617-1.108-1.2617-1.6113 0-.5032.36716-1.0876 1.2617-1.6094.89456-.5219 2.2391-.89062 3.7383-.89062s2.8437.36872 3.7383.89062c.89456.5218 1.2617 1.1062 1.2617 1.6094 0 .15978-.053679.32822-.13281.5h1.1328c.32481 0 .62893.088408.90234.23047.057552-.23582.097656-.47718.097656-.73047 0-1.4297-.9769-2.5929-2.2539-3.3379-1.277-.7449-2.9316-1.1621-4.7461-1.1621z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3c-1.8145 0-3.4691.41721-4.7461 1.1621-1.277.745-2.2539 1.9082-2.2539 3.3379 0 1.4298.9769 2.5949 2.2539 3.3398s2.9316 1.1602 4.7461 1.1602c0-1.0907.90931-2 2-2 0-.080836.013744-.15778.023438-.23633-.61769.14673-1.3008.23633-2.0234.23633-1.4992 0-2.8437-.36687-3.7383-.88867-.89456-.5219-1.2617-1.108-1.2617-1.6113 0-.5032.36716-1.0876 1.2617-1.6094.89456-.5219 2.2391-.89062 3.7383-.89062s2.8437.36872 3.7383.89062c.89456.5218 1.2617 1.1062 1.2617 1.6094 0 .15978-.053679.32822-.13281.5h1.1328c.32481 0 .62893.088408.90234.23047.057552-.23582.097656-.47718.097656-.73047 0-1.4297-.9769-2.5929-2.2539-3.3379-1.277-.7449-2.9316-1.1621-4.7461-1.1621z" fill="#fc7f7f"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#5fb2ff"/></svg>
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index 2fef576b77..fced61a600 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -30,7 +30,7 @@
#include "texture_loader_dds.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#define PF_FOURCC(s) ((uint32_t)(((s)[3] << 24U) | ((s)[2] << 16U) | ((s)[1] << 8U) | ((s)[0])))
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index f22ff29349..271cb03c9f 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -144,7 +144,7 @@
</argument>
<description>
Sets the timeout parameters for a peer. The timeout parameters control how and when a peer will timeout from a failure to acknowledge reliable traffic. Timeout values are expressed in milliseconds.
- The [code]timeout_limit[/code] is a factor that, multiplied by a value based on the avarage round trip time, will determine the timeout limit for a reliable packet. When that limit is reached, the timeout will be doubled, and the peer will be disconnected if that limit has reached [code]timeout_min[/code]. The [code]timeout_max[/code] parameter, on the other hand, defines a fixed timeout for which any packet must be acknowledged or the peer will be dropped.
+ The [code]timeout_limit[/code] is a factor that, multiplied by a value based on the average round trip time, will determine the timeout limit for a reliable packet. When that limit is reached, the timeout will be doubled, and the peer will be disconnected if that limit has reached [code]timeout_min[/code]. The [code]timeout_max[/code] parameter, on the other hand, defines a fixed timeout for which any packet must be acknowledged or the peer will be dropped.
</description>
</method>
</methods>
diff --git a/modules/fbx/README.md b/modules/fbx/README.md
index 2a2f186463..8eca4bd3c9 100644
--- a/modules/fbx/README.md
+++ b/modules/fbx/README.md
@@ -15,7 +15,7 @@ functionality. If anything we should give this parser back to assimp at some poi
# Updating assimp fbx parser
-Don't. it's not possible the code is rewritten in many areas to remove thirdparty deps and various bugs are fixed.
+Don't. It's not possible the code is rewritten in many areas to remove thirdparty deps and various bugs are fixed.
Many days were put into rewriting the parser to use safe code and safe memory accessors.
@@ -79,23 +79,23 @@ enum RotOrder {
// references: ComputePivotTransform / run the calculation
// This is the local pivot transform for the node, not the global transforms
Transform ComputePivotTransform(
- Transform chain[TransformationComp_MAXIMUM],
- Transform &geometric_transform) {
+ Transform3D chain[TransformationComp_MAXIMUM],
+ Transform3D &geometric_transform) {
// Maya pivots
- Transform T = chain[TransformationComp_Translation];
- Transform Roff = chain[TransformationComp_RotationOffset];
- Transform Rp = chain[TransformationComp_RotationPivot];
- Transform Rpre = chain[TransformationComp_PreRotation];
- Transform R = chain[TransformationComp_Rotation];
- Transform Rpost = chain[TransformationComp_PostRotation];
- Transform Soff = chain[TransformationComp_ScalingOffset];
- Transform Sp = chain[TransformationComp_ScalingPivot];
- Transform S = chain[TransformationComp_Scaling];
+ Transform3D T = chain[TransformationComp_Translation];
+ Transform3D Roff = chain[TransformationComp_RotationOffset];
+ Transform3D Rp = chain[TransformationComp_RotationPivot];
+ Transform3D Rpre = chain[TransformationComp_PreRotation];
+ Transform3D R = chain[TransformationComp_Rotation];
+ Transform3D Rpost = chain[TransformationComp_PostRotation];
+ Transform3D Soff = chain[TransformationComp_ScalingOffset];
+ Transform3D Sp = chain[TransformationComp_ScalingPivot];
+ Transform3D S = chain[TransformationComp_Scaling];
// 3DS Max Pivots
- Transform OT = chain[TransformationComp_GeometricTranslation];
- Transform OR = chain[TransformationComp_GeometricRotation];
- Transform OS = chain[TransformationComp_GeometricScaling];
+ Transform3D OT = chain[TransformationComp_GeometricTranslation];
+ Transform3D OR = chain[TransformationComp_GeometricRotation];
+ Transform3D OS = chain[TransformationComp_GeometricScaling];
// Calculate 3DS max pivot transform - use geometric space (e.g doesn't effect children nodes only the current node)
geometric_transform = OT * OR * OS;
diff --git a/modules/fbx/data/fbx_bone.h b/modules/fbx/data/fbx_bone.h
index efba147b89..83918ad1e2 100644
--- a/modules/fbx/data/fbx_bone.h
+++ b/modules/fbx/data/fbx_bone.h
@@ -38,7 +38,7 @@
struct PivotTransform;
-struct FBXBone : public Reference {
+struct FBXBone : public RefCounted {
uint64_t parent_bone_id = 0;
uint64_t bone_id = 0;
diff --git a/modules/fbx/data/fbx_material.h b/modules/fbx/data/fbx_material.h
index 23310b8e1d..5fd4d9212b 100644
--- a/modules/fbx/data/fbx_material.h
+++ b/modules/fbx/data/fbx_material.h
@@ -33,10 +33,10 @@
#include "tools/import_utils.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/string/ustring.h"
-struct FBXMaterial : public Reference {
+struct FBXMaterial : public RefCounted {
String material_name = String();
bool warning_non_pbr_material = false;
FBXDocParser::Material *material = nullptr;
@@ -266,7 +266,7 @@ struct FBXMaterial : public Reference {
/* storing the texture properties like color */
template <class T>
- struct TexturePropertyMapping : Reference {
+ struct TexturePropertyMapping : RefCounted {
StandardMaterial3D::TextureParam map_mode = StandardMaterial3D::TextureParam::TEXTURE_ALBEDO;
const T property = T();
};
diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp
index 304d1598f6..8f32c523f9 100644
--- a/modules/fbx/data/fbx_mesh_data.cpp
+++ b/modules/fbx/data/fbx_mesh_data.cpp
@@ -945,7 +945,7 @@ void FBXMeshData::triangulate_polygon(SurfaceData *surface, const Vector<int> &p
for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
TPPLPoly &tp = I->get();
- ERR_FAIL_COND_MSG(tp.GetNumPoints() != 3, "The triangulator retuned more points, how this is possible?");
+ ERR_FAIL_COND_MSG(tp.GetNumPoints() != 3, "The triangulator returned more points, how this is possible?");
// Find Index
for (int i = 2; i >= 0; i -= 1) {
const Vector2 vertex = tp.GetPoint(i);
@@ -1126,8 +1126,8 @@ HashMap<int, R> FBXMeshData::extract_per_vertex_data(
}
const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index);
ERR_FAIL_COND_V_MSG(vertex_index < 0, (HashMap<int, R>()), "FBX file corrupted: #ERR8");
- ERR_FAIL_COND_V_MSG(vertex_index >= p_vertex_count, (HashMap<int, R>()), "FBX file seems corrupted: #ERR9.");
- ERR_FAIL_COND_V_MSG(p_mapping_data.index[polygon_vertex_index] < 0, (HashMap<int, R>()), "FBX file seems corrupted: #ERR10.");
+ ERR_FAIL_COND_V_MSG(vertex_index >= p_vertex_count, (HashMap<int, R>()), "FBX file seems corrupted: #ERR9.");
+ ERR_FAIL_COND_V_MSG(p_mapping_data.index[polygon_vertex_index] < 0, (HashMap<int, R>()), "FBX file seems corrupted: #ERR10.");
ERR_FAIL_COND_V_MSG(p_mapping_data.index[polygon_vertex_index] >= (int)p_mapping_data.data.size(), (HashMap<int, R>()), "FBX file seems corrupted: #ERR11.");
aggregate_vertex_data[vertex_index].push_back({ polygon_id, p_mapping_data.data[p_mapping_data.index[polygon_vertex_index]] });
}
diff --git a/modules/fbx/data/fbx_mesh_data.h b/modules/fbx/data/fbx_mesh_data.h
index 575f833584..7486c5c59c 100644
--- a/modules/fbx/data/fbx_mesh_data.h
+++ b/modules/fbx/data/fbx_mesh_data.h
@@ -78,7 +78,7 @@ struct VertexData {
};
// Caches mesh information and instantiates meshes for you using helper functions.
-struct FBXMeshData : Reference {
+struct FBXMeshData : RefCounted {
struct MorphVertexData {
// TODO we have only these??
/// Each element is a vertex. Not supposed to be void.
@@ -156,7 +156,7 @@ private:
/// [0, 2, 1, 3, 4]
/// The negative values are computed using this formula: `(-value) - 1`
///
- /// Returns the vertex index from the poligon vertex.
+ /// Returns the vertex index from the polygon vertex.
/// Returns -1 if `p_index` is invalid.
int get_vertex_from_polygon_vertex(const std::vector<int> &p_face_indices, int p_index) const;
diff --git a/modules/fbx/data/fbx_node.h b/modules/fbx/data/fbx_node.h
index a6f62f3388..75461e397d 100644
--- a/modules/fbx/data/fbx_node.h
+++ b/modules/fbx/data/fbx_node.h
@@ -40,7 +40,7 @@
class Node3D;
struct PivotTransform;
-struct FBXNode : Reference, ModelAbstraction {
+struct FBXNode : RefCounted, ModelAbstraction {
uint64_t current_node_id = 0;
String node_name = String();
Node3D *godot_node = nullptr;
diff --git a/modules/fbx/data/fbx_skeleton.h b/modules/fbx/data/fbx_skeleton.h
index df937cde49..b6103df949 100644
--- a/modules/fbx/data/fbx_skeleton.h
+++ b/modules/fbx/data/fbx_skeleton.h
@@ -35,14 +35,14 @@
#include "fbx_node.h"
#include "model_abstraction.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "scene/3d/skeleton_3d.h"
struct FBXNode;
struct ImportState;
struct FBXBone;
-struct FBXSkeleton : Reference {
+struct FBXSkeleton : RefCounted {
Ref<FBXNode> fbx_node = Ref<FBXNode>();
Vector<Ref<FBXBone>> skeleton_bones = Vector<Ref<FBXBone>>();
Skeleton3D *skeleton = nullptr;
diff --git a/modules/fbx/data/pivot_transform.cpp b/modules/fbx/data/pivot_transform.cpp
index f4055c830f..4cf42257a4 100644
--- a/modules/fbx/data/pivot_transform.cpp
+++ b/modules/fbx/data/pivot_transform.cpp
@@ -90,7 +90,7 @@ void PivotTransform::ReadTransformChain() {
if (ok) {
geometric_rotation = ImportUtils::EulerToQuaternion(rot, ImportUtils::deg2rad(GeometricRotation));
} else {
- geometric_rotation = Quat();
+ geometric_rotation = Quaternion();
}
const Vector3 &GeometricTranslation = ImportUtils::safe_import_vector3(FBXDocParser::PropertyGet<Vector3>(props, "GeometricTranslation", ok));
@@ -100,7 +100,7 @@ void PivotTransform::ReadTransformChain() {
geometric_translation = Vector3(0, 0, 0);
}
- if (geometric_rotation != Quat()) {
+ if (geometric_rotation != Quaternion()) {
print_error("geometric rotation is unsupported!");
//CRASH_COND(true);
}
@@ -116,8 +116,8 @@ void PivotTransform::ReadTransformChain() {
}
}
-Transform PivotTransform::ComputeLocalTransform(Vector3 p_translation, Quat p_rotation, Vector3 p_scaling) const {
- Transform T, Roff, Rp, Soff, Sp, S;
+Transform3D PivotTransform::ComputeLocalTransform(Vector3 p_translation, Quaternion p_rotation, Vector3 p_scaling) const {
+ Transform3D T, Roff, Rp, Soff, Sp, S;
// Here I assume this is the operation which needs done.
// Its WorldTransform * V
@@ -132,29 +132,29 @@ Transform PivotTransform::ComputeLocalTransform(Vector3 p_translation, Quat p_ro
// Scaling node
S.scale(p_scaling);
// Rotation pivots
- Transform Rpre = Transform(pre_rotation);
- Transform R = Transform(p_rotation);
- Transform Rpost = Transform(post_rotation);
+ Transform3D Rpre = Transform3D(pre_rotation);
+ Transform3D R = Transform3D(p_rotation);
+ Transform3D Rpost = Transform3D(post_rotation);
return T * Roff * Rp * Rpre * R * Rpost.affine_inverse() * Rp.affine_inverse() * Soff * Sp * S * Sp.affine_inverse();
}
-Transform PivotTransform::ComputeGlobalTransform(Transform t) const {
+Transform3D PivotTransform::ComputeGlobalTransform(Transform3D t) const {
Vector3 pos = t.origin;
Vector3 scale = t.basis.get_scale();
- Quat rot = t.basis.get_rotation_quat();
+ Quaternion rot = t.basis.get_rotation_quaternion();
return ComputeGlobalTransform(pos, rot, scale);
}
-Transform PivotTransform::ComputeLocalTransform(Transform t) const {
+Transform3D PivotTransform::ComputeLocalTransform(Transform3D t) const {
Vector3 pos = t.origin;
Vector3 scale = t.basis.get_scale();
- Quat rot = t.basis.get_rotation_quat();
+ Quaternion rot = t.basis.get_rotation_quaternion();
return ComputeLocalTransform(pos, rot, scale);
}
-Transform PivotTransform::ComputeGlobalTransform(Vector3 p_translation, Quat p_rotation, Vector3 p_scaling) const {
- Transform T, Roff, Rp, Soff, Sp, S;
+Transform3D PivotTransform::ComputeGlobalTransform(Vector3 p_translation, Quaternion p_rotation, Vector3 p_scaling) const {
+ Transform3D T, Roff, Rp, Soff, Sp, S;
// Here I assume this is the operation which needs done.
// Its WorldTransform * V
@@ -170,26 +170,26 @@ Transform PivotTransform::ComputeGlobalTransform(Vector3 p_translation, Quat p_r
S.scale(p_scaling);
// Rotation pivots
- Transform Rpre = Transform(pre_rotation);
- Transform R = Transform(p_rotation);
- Transform Rpost = Transform(post_rotation);
+ Transform3D Rpre = Transform3D(pre_rotation);
+ Transform3D R = Transform3D(p_rotation);
+ Transform3D Rpost = Transform3D(post_rotation);
- Transform parent_global_xform;
- Transform parent_local_scaling_m;
+ Transform3D parent_global_xform;
+ Transform3D parent_local_scaling_m;
if (parent_transform.is_valid()) {
parent_global_xform = parent_transform->GlobalTransform;
parent_local_scaling_m = parent_transform->Local_Scaling_Matrix;
}
- Transform local_rotation_m, parent_global_rotation_m;
- Quat parent_global_rotation = parent_global_xform.basis.get_rotation_quat();
- parent_global_rotation_m.basis.set_quat(parent_global_rotation);
+ Transform3D local_rotation_m, parent_global_rotation_m;
+ Quaternion parent_global_rotation = parent_global_xform.basis.get_rotation_quaternion();
+ parent_global_rotation_m.basis.set_quaternion(parent_global_rotation);
local_rotation_m = Rpre * R * Rpost;
- //Basis parent_global_rotation = Basis(parent_global_xform.get_basis().get_rotation_quat().normalized());
+ //Basis parent_global_rotation = Basis(parent_global_xform.get_basis().get_rotation_quaternion().normalized());
- Transform local_shear_scaling, parent_shear_scaling, parent_shear_rotation, parent_shear_translation;
+ Transform3D local_shear_scaling, parent_shear_scaling, parent_shear_rotation, parent_shear_translation;
Vector3 parent_translation = parent_global_xform.get_origin();
parent_shear_translation.origin = parent_translation;
parent_shear_rotation = parent_shear_translation.affine_inverse() * parent_global_xform;
@@ -197,26 +197,26 @@ Transform PivotTransform::ComputeGlobalTransform(Vector3 p_translation, Quat p_r
local_shear_scaling = S;
// Inherit type handler - we don't care about T here, just reordering RSrs etc.
- Transform global_rotation_scale;
+ Transform3D global_rotation_scale;
if (inherit_type == FBXDocParser::Transform_RrSs) {
global_rotation_scale = parent_global_rotation_m * local_rotation_m * parent_shear_scaling * local_shear_scaling;
} else if (inherit_type == FBXDocParser::Transform_RSrs) {
global_rotation_scale = parent_global_rotation_m * parent_shear_scaling * local_rotation_m * local_shear_scaling;
} else if (inherit_type == FBXDocParser::Transform_Rrs) {
- Transform parent_global_shear_m_noLocal = parent_shear_scaling * parent_local_scaling_m.affine_inverse();
+ Transform3D parent_global_shear_m_noLocal = parent_shear_scaling * parent_local_scaling_m.affine_inverse();
global_rotation_scale = parent_global_rotation_m * local_rotation_m * parent_global_shear_m_noLocal * local_shear_scaling;
}
- Transform local_transform = T * Roff * Rp * Rpre * R * Rpost.affine_inverse() * Rp.affine_inverse() * Soff * Sp * S * Sp.affine_inverse();
- //Transform local_translation_pivoted = Transform(Basis(), LocalTransform.origin);
+ Transform3D local_transform = T * Roff * Rp * Rpre * R * Rpost.affine_inverse() * Rp.affine_inverse() * Soff * Sp * S * Sp.affine_inverse();
+ //Transform3D local_translation_pivoted = Transform3D(Basis(), LocalTransform.origin);
- ERR_FAIL_COND_V_MSG(local_transform.basis.determinant() == 0, Transform(), "Det == 0 prevented in scene file");
+ ERR_FAIL_COND_V_MSG(local_transform.basis.determinant() == 0, Transform3D(), "Det == 0 prevented in scene file");
// manual hack to force SSC not to be compensated for - until we can handle it properly with tests
return parent_global_xform * local_transform;
}
void PivotTransform::ComputePivotTransform() {
- Transform T, Roff, Rp, Soff, Sp, S;
+ Transform3D T, Roff, Rp, Soff, Sp, S;
// Here I assume this is the operation which needs done.
// Its WorldTransform * V
@@ -237,26 +237,26 @@ void PivotTransform::ComputePivotTransform() {
Local_Scaling_Matrix = S; // copy for when node / child is looking for the value of this.
// Rotation pivots
- Transform Rpre = Transform(pre_rotation);
- Transform R = Transform(rotation);
- Transform Rpost = Transform(post_rotation);
+ Transform3D Rpre = Transform3D(pre_rotation);
+ Transform3D R = Transform3D(rotation);
+ Transform3D Rpost = Transform3D(post_rotation);
- Transform parent_global_xform;
- Transform parent_local_scaling_m;
+ Transform3D parent_global_xform;
+ Transform3D parent_local_scaling_m;
if (parent_transform.is_valid()) {
parent_global_xform = parent_transform->GlobalTransform;
parent_local_scaling_m = parent_transform->Local_Scaling_Matrix;
}
- Transform local_rotation_m, parent_global_rotation_m;
- Quat parent_global_rotation = parent_global_xform.basis.get_rotation_quat();
- parent_global_rotation_m.basis.set_quat(parent_global_rotation);
+ Transform3D local_rotation_m, parent_global_rotation_m;
+ Quaternion parent_global_rotation = parent_global_xform.basis.get_rotation_quaternion();
+ parent_global_rotation_m.basis.set_quaternion(parent_global_rotation);
local_rotation_m = Rpre * R * Rpost;
- //Basis parent_global_rotation = Basis(parent_global_xform.get_basis().get_rotation_quat().normalized());
+ //Basis parent_global_rotation = Basis(parent_global_xform.get_basis().get_rotation_quaternion().normalized());
- Transform local_shear_scaling, parent_shear_scaling, parent_shear_rotation, parent_shear_translation;
+ Transform3D local_shear_scaling, parent_shear_scaling, parent_shear_rotation, parent_shear_translation;
Vector3 parent_translation = parent_global_xform.get_origin();
parent_shear_translation.origin = parent_translation;
parent_shear_rotation = parent_shear_translation.affine_inverse() * parent_global_xform;
@@ -264,24 +264,24 @@ void PivotTransform::ComputePivotTransform() {
local_shear_scaling = S;
// Inherit type handler - we don't care about T here, just reordering RSrs etc.
- Transform global_rotation_scale;
+ Transform3D global_rotation_scale;
if (inherit_type == FBXDocParser::Transform_RrSs) {
global_rotation_scale = parent_global_rotation_m * local_rotation_m * parent_shear_scaling * local_shear_scaling;
} else if (inherit_type == FBXDocParser::Transform_RSrs) {
global_rotation_scale = parent_global_rotation_m * parent_shear_scaling * local_rotation_m * local_shear_scaling;
} else if (inherit_type == FBXDocParser::Transform_Rrs) {
- Transform parent_global_shear_m_noLocal = parent_shear_scaling * parent_local_scaling_m.inverse();
+ Transform3D parent_global_shear_m_noLocal = parent_shear_scaling * parent_local_scaling_m.inverse();
global_rotation_scale = parent_global_rotation_m * local_rotation_m * parent_global_shear_m_noLocal * local_shear_scaling;
}
- LocalTransform = Transform();
+ LocalTransform = Transform3D();
LocalTransform = T * Roff * Rp * Rpre * R * Rpost.affine_inverse() * Rp.affine_inverse() * Soff * Sp * S * Sp.affine_inverse();
ERR_FAIL_COND_MSG(LocalTransform.basis.determinant() == 0, "invalid scale reset");
- Transform local_translation_pivoted = Transform(Basis(), LocalTransform.origin);
- GlobalTransform = Transform();
+ Transform3D local_translation_pivoted = Transform3D(Basis(), LocalTransform.origin);
+ GlobalTransform = Transform3D();
//GlobalTransform = parent_global_xform * LocalTransform;
- Transform global_origin = Transform(Basis(), parent_translation);
+ Transform3D global_origin = Transform3D(Basis(), parent_translation);
GlobalTransform = (global_origin * local_translation_pivoted) * global_rotation_scale;
ImportUtils::debug_xform("local xform calculation", LocalTransform);
diff --git a/modules/fbx/data/pivot_transform.h b/modules/fbx/data/pivot_transform.h
index 9996027870..099b268075 100644
--- a/modules/fbx/data/pivot_transform.h
+++ b/modules/fbx/data/pivot_transform.h
@@ -31,8 +31,8 @@
#ifndef PIVOT_TRANSFORM_H
#define PIVOT_TRANSFORM_H
-#include "core/math/transform.h"
-#include "core/object/reference.h"
+#include "core/math/transform_3d.h"
+#include "core/object/ref_counted.h"
#include "model_abstraction.h"
@@ -55,13 +55,13 @@ enum TransformationComp {
TransformationComp_MAXIMUM
};
// Abstract away pivot data so its simpler to handle
-struct PivotTransform : Reference, ModelAbstraction {
+struct PivotTransform : RefCounted, ModelAbstraction {
// at the end we want to keep geometric_ everything, post and pre rotation
// these are used during animation data processing / keyframe ingestion the rest can be simplified down / out.
- Quat pre_rotation = Quat();
- Quat post_rotation = Quat();
- Quat rotation = Quat();
- Quat geometric_rotation = Quat();
+ Quaternion pre_rotation = Quaternion();
+ Quaternion post_rotation = Quaternion();
+ Quaternion rotation = Quaternion();
+ Quaternion geometric_rotation = Quaternion();
Vector3 rotation_pivot = Vector3();
Vector3 rotation_offset = Vector3();
Vector3 scaling_offset = Vector3(1.0, 1.0, 1.0);
@@ -85,10 +85,10 @@ struct PivotTransform : Reference, ModelAbstraction {
print_verbose("raw post_rotation " + raw_post_rotation * (180 / Math_PI));
}
- Transform ComputeGlobalTransform(Transform t) const;
- Transform ComputeLocalTransform(Transform t) const;
- Transform ComputeGlobalTransform(Vector3 p_translation, Quat p_rotation, Vector3 p_scaling) const;
- Transform ComputeLocalTransform(Vector3 p_translation, Quat p_rotation, Vector3 p_scaling) const;
+ Transform3D ComputeGlobalTransform(Transform3D t) const;
+ Transform3D ComputeLocalTransform(Transform3D t) const;
+ Transform3D ComputeGlobalTransform(Vector3 p_translation, Quaternion p_rotation, Vector3 p_scaling) const;
+ Transform3D ComputeLocalTransform(Vector3 p_translation, Quaternion p_rotation, Vector3 p_scaling) const;
/* Extract into xforms and calculate once */
void ComputePivotTransform();
@@ -105,10 +105,10 @@ struct PivotTransform : Reference, ModelAbstraction {
//Transform chain[TransformationComp_MAXIMUM];
// cached for later use
- Transform GlobalTransform = Transform();
- Transform LocalTransform = Transform();
- Transform Local_Scaling_Matrix = Transform(); // used for inherit type.
- Transform GeometricTransform = Transform(); // 3DS max only
+ Transform3D GlobalTransform = Transform3D();
+ Transform3D LocalTransform = Transform3D();
+ Transform3D Local_Scaling_Matrix = Transform3D(); // used for inherit type.
+ Transform3D GeometricTransform = Transform3D(); // 3DS max only
FBXDocParser::TransformInheritance inherit_type = FBXDocParser::TransformInheritance_MAX; // maya fbx requires this - sorry <3
};
diff --git a/modules/fbx/editor_scene_importer_fbx.cpp b/modules/fbx/editor_scene_importer_fbx.cpp
index ccbea21541..40deaae74d 100644
--- a/modules/fbx/editor_scene_importer_fbx.cpp
+++ b/modules/fbx/editor_scene_importer_fbx.cpp
@@ -102,7 +102,7 @@ Node3D *EditorSceneImporterFBX::import_scene(const String &p_path, uint32_t p_fl
FBXDocParser::TokenList tokens;
bool is_binary = false;
- data.resize(f->get_len());
+ data.resize(f->get_length());
ERR_FAIL_COND_V(data.size() < 64, nullptr);
@@ -258,24 +258,24 @@ struct EditorSceneImporterAssetImportInterpolate {
//thank you for existing, partial specialization
template <>
-struct EditorSceneImporterAssetImportInterpolate<Quat> {
- Quat lerp(const Quat &a, const Quat &b, float c) const {
- ERR_FAIL_COND_V(!a.is_normalized(), Quat());
- ERR_FAIL_COND_V(!b.is_normalized(), Quat());
+struct EditorSceneImporterAssetImportInterpolate<Quaternion> {
+ Quaternion lerp(const Quaternion &a, const Quaternion &b, float c) const {
+ ERR_FAIL_COND_V(!a.is_normalized(), Quaternion());
+ ERR_FAIL_COND_V(!b.is_normalized(), Quaternion());
return a.slerp(b, c).normalized();
}
- Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) {
- ERR_FAIL_COND_V(!p1.is_normalized(), Quat());
- ERR_FAIL_COND_V(!p2.is_normalized(), Quat());
+ Quaternion catmull_rom(const Quaternion &p0, const Quaternion &p1, const Quaternion &p2, const Quaternion &p3, float c) {
+ ERR_FAIL_COND_V(!p1.is_normalized(), Quaternion());
+ ERR_FAIL_COND_V(!p2.is_normalized(), Quaternion());
return p1.slerp(p2, c).normalized();
}
- Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) {
- ERR_FAIL_COND_V(!start.is_normalized(), Quat());
- ERR_FAIL_COND_V(!end.is_normalized(), Quat());
+ Quaternion bezier(Quaternion start, Quaternion control_1, Quaternion control_2, Quaternion end, float t) {
+ ERR_FAIL_COND_V(!start.is_normalized(), Quaternion());
+ ERR_FAIL_COND_V(!end.is_normalized(), Quaternion());
return start.slerp(end, t).normalized();
}
@@ -888,7 +888,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
// we need to know what object the curves are for.
// we need the target ID and the target name for the track reduction.
- FBXDocParser::Model::RotOrder quat_rotation_order = FBXDocParser::Model::RotOrder_EulerXYZ;
+ FBXDocParser::Model::RotOrder quaternion_rotation_order = FBXDocParser::Model::RotOrder_EulerXYZ;
// T:: R:: S:: Visible:: Custom::
for (const FBXDocParser::AnimationCurveNode *curve_node : node_list) {
@@ -910,7 +910,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
continue;
} else {
//print_verbose("[doc] applied rotation order: " + itos(target->RotationOrder()));
- quat_rotation_order = target->RotationOrder();
+ quaternion_rotation_order = target->RotationOrder();
}
uint64_t target_id = target->ID();
@@ -1011,7 +1011,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
// track count is 5.
// next track id is 5.
const uint64_t target_id = track->key();
- int track_idx = animation->add_track(Animation::TYPE_TRANSFORM);
+ int track_idx = animation->add_track(Animation::TYPE_TRANSFORM3D);
// animation->track_set_path(track_idx, node_path);
Ref<FBXBone> bone;
@@ -1023,7 +1023,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
bone = state.fbx_bone_map[target_id];
}
- Transform target_transform;
+ Transform3D target_transform;
if (state.fbx_target_map.has(target_id)) {
Ref<FBXNode> node_ref = state.fbx_target_map[target_id];
@@ -1056,7 +1056,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
//print_verbose("[doc] node animation path: " + node_path);
}
} else {
- // note: this could actually be unsafe this means we should be careful about continuing here, if we see bizzare effects later we should disable this.
+ // note: this could actually be unsafe this means we should be careful about continuing here, if we see bizarre effects later we should disable this.
// I am not sure if this is unsafe or not, testing will tell us this.
print_error("[doc] invalid fbx target detected for this track");
continue;
@@ -1086,7 +1086,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
Vector<float> pos_times;
Vector<Vector3> scale_values;
Vector<float> scale_times;
- Vector<Quat> rot_values;
+ Vector<Quaternion> rot_values;
Vector<float> rot_times;
double max_duration = 0;
@@ -1122,8 +1122,8 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
bool got_pre = false;
bool got_post = false;
- Quat post_rotation;
- Quat pre_rotation;
+ Quaternion post_rotation;
+ Quaternion pre_rotation;
// Rotation matrix
const Vector3 &PreRotation = FBXDocParser::PropertyGet<Vector3>(props, "PreRotation", got_pre);
@@ -1137,24 +1137,24 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
post_rotation = ImportUtils::EulerToQuaternion(rot_order, ImportUtils::deg2rad(PostRotation));
}
- Quat lastQuat = Quat();
+ Quaternion lastQuaternion = Quaternion();
for (std::pair<int64_t, Vector3> rotation_key : rotation_keys.keyframes) {
double animation_track_time = CONVERT_FBX_TIME(rotation_key.first);
//print_verbose("euler rotation key: " + rotation_key.second);
- Quat rot_key_value = ImportUtils::EulerToQuaternion(quat_rotation_order, ImportUtils::deg2rad(rotation_key.second));
+ Quaternion rot_key_value = ImportUtils::EulerToQuaternion(quaternion_rotation_order, ImportUtils::deg2rad(rotation_key.second));
- if (lastQuat != Quat() && rot_key_value.dot(lastQuat) < 0) {
+ if (lastQuaternion != Quaternion() && rot_key_value.dot(lastQuaternion) < 0) {
rot_key_value.x = -rot_key_value.x;
rot_key_value.y = -rot_key_value.y;
rot_key_value.z = -rot_key_value.z;
rot_key_value.w = -rot_key_value.w;
}
// pre_post rotation possibly could fix orientation
- Quat final_rotation = pre_rotation * rot_key_value * post_rotation;
+ Quaternion final_rotation = pre_rotation * rot_key_value * post_rotation;
- lastQuat = final_rotation;
+ lastQuaternion = final_rotation;
if (animation_track_time > max_duration) {
max_duration = animation_track_time;
@@ -1165,7 +1165,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
}
bool valid_rest = false;
- Transform bone_rest;
+ Transform3D bone_rest;
int skeleton_bone = -1;
if (state.fbx_bone_map.has(target_id)) {
if (bone.is_valid() && bone->fbx_skeleton.is_valid()) {
@@ -1182,13 +1182,13 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
}
const Vector3 def_pos = translation_keys.has_default ? (translation_keys.default_value * state.scale) : bone_rest.origin;
- const Quat def_rot = rotation_keys.has_default ? ImportUtils::EulerToQuaternion(quat_rotation_order, ImportUtils::deg2rad(rotation_keys.default_value)) : bone_rest.basis.get_rotation_quat();
+ const Quaternion def_rot = rotation_keys.has_default ? ImportUtils::EulerToQuaternion(quaternion_rotation_order, ImportUtils::deg2rad(rotation_keys.default_value)) : bone_rest.basis.get_rotation_quaternion();
const Vector3 def_scale = scale_keys.has_default ? scale_keys.default_value : bone_rest.basis.get_scale();
print_verbose("track defaults: p(" + def_pos + ") s(" + def_scale + ") r(" + def_rot + ")");
while (true) {
Vector3 pos = def_pos;
- Quat rot = def_rot;
+ Quaternion rot = def_rot;
Vector3 scale = def_scale;
if (pos_values.size()) {
@@ -1197,7 +1197,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
}
if (rot_values.size()) {
- rot = _interpolate_track<Quat>(rot_times, rot_values, time,
+ rot = _interpolate_track<Quaternion>(rot_times, rot_values, time,
AssetImportAnimation::INTERP_LINEAR);
}
@@ -1208,13 +1208,13 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
// node animations must also include pivots
if (skeleton_bone >= 0) {
- Transform xform = Transform();
- xform.basis.set_quat_scale(rot, scale);
+ Transform3D xform = Transform3D();
+ xform.basis.set_quaternion_scale(rot, scale);
xform.origin = pos;
- const Transform t = bone_rest.affine_inverse() * xform;
+ const Transform3D t = bone_rest.affine_inverse() * xform;
// populate this again
- rot = t.basis.get_rotation_quat();
+ rot = t.basis.get_rotation_quaternion();
rot.normalize();
scale = t.basis.get_scale();
pos = t.origin;
diff --git a/modules/fbx/fbx_parser/FBXDeformer.cpp b/modules/fbx/fbx_parser/FBXDeformer.cpp
index 039718ae15..4220ba62a7 100644
--- a/modules/fbx/fbx_parser/FBXDeformer.cpp
+++ b/modules/fbx/fbx_parser/FBXDeformer.cpp
@@ -78,7 +78,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXMeshGeometry.h"
#include "FBXParser.h"
#include "core/math/math_funcs.h"
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include <iostream>
diff --git a/modules/fbx/fbx_parser/FBXDocument.cpp b/modules/fbx/fbx_parser/FBXDocument.cpp
index bb85d6ff7c..89c69d2ee8 100644
--- a/modules/fbx/fbx_parser/FBXDocument.cpp
+++ b/modules/fbx/fbx_parser/FBXDocument.cpp
@@ -487,7 +487,7 @@ const std::vector<const AnimationStack *> &Document::AnimationStacks() const {
const AnimationStack *stack = lazy->Get<AnimationStack>();
ERR_CONTINUE_MSG(!stack, "invalid ptr to AnimationStack - conversion failure");
- // We push back the weak reference :) to keep things simple, as ownership is on the parser side so it wont be cleaned up.
+ // We push back the weak reference :) to keep things simple, as ownership is on the parser side so it won't be cleaned up.
animationStacksResolved.push_back(stack);
}
diff --git a/modules/fbx/fbx_parser/FBXDocument.h b/modules/fbx/fbx_parser/FBXDocument.h
index 9664cd763a..885ff8fca4 100644
--- a/modules/fbx/fbx_parser/FBXDocument.h
+++ b/modules/fbx/fbx_parser/FBXDocument.h
@@ -37,7 +37,7 @@
#include "FBXCommon.h"
#include "FBXParser.h"
#include "FBXProperties.h"
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include "core/math/vector2.h"
#include "core/math/vector3.h"
#include "core/string/print_string.h"
@@ -242,13 +242,13 @@ public:
return target_id;
}
- Transform GetBindPose() const {
+ Transform3D GetBindPose() const {
return transform;
}
private:
uint64_t target_id = 0;
- Transform transform;
+ Transform3D transform;
};
/** DOM base class for FBX cameras attached to a node */
@@ -699,7 +699,7 @@ private:
typedef std::vector<int64_t> KeyTimeList;
typedef std::vector<float> KeyValueList;
-/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
+/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */
class AnimationCurve : public Object {
public:
AnimationCurve(uint64_t id, const ElementPtr element, const std::string &name, const Document &doc);
@@ -905,11 +905,11 @@ public:
}
/** */
- const Transform &GetTransform() const {
+ const Transform3D &GetTransform() const {
return transform;
}
- const Transform &TransformLink() const {
+ const Transform3D &TransformLink() const {
return transformLink;
}
@@ -917,7 +917,7 @@ public:
return node;
}
- const Transform &TransformAssociateModel() const {
+ const Transform3D &TransformAssociateModel() const {
return transformAssociateModel;
}
@@ -941,9 +941,9 @@ private:
std::vector<float> weights;
std::vector<unsigned int> indices;
- Transform transform;
- Transform transformLink;
- Transform transformAssociateModel;
+ Transform3D transform;
+ Transform3D transformLink;
+ Transform3D transformAssociateModel;
SkinLinkMode link_mode;
bool valid_transformAssociateModel = false;
const Model *node = nullptr;
diff --git a/modules/fbx/fbx_parser/FBXMeshGeometry.cpp b/modules/fbx/fbx_parser/FBXMeshGeometry.cpp
index a28e7565c6..2cc25a0690 100644
--- a/modules/fbx/fbx_parser/FBXMeshGeometry.cpp
+++ b/modules/fbx/fbx_parser/FBXMeshGeometry.cpp
@@ -125,7 +125,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const ElementPtr element, const std::str
ScopePtr sc = element->Compound();
ERR_FAIL_COND_MSG(sc == nullptr, "failed to read geometry, prevented crash");
- ERR_FAIL_COND_MSG(!HasElement(sc, "Vertices"), "Detected mesh with no vertexes, didn't populate the mesh");
+ ERR_FAIL_COND_MSG(!HasElement(sc, "Vertices"), "Detected mesh with no vertices, didn't populate the mesh");
// must have Mesh elements:
const ElementPtr Vertices = GetRequiredElement(sc, "Vertices", element);
@@ -140,7 +140,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const ElementPtr element, const std::str
ParseVectorDataArray(m_vertices, Vertices);
ParseVectorDataArray(m_face_indices, PolygonVertexIndex);
- ERR_FAIL_COND_MSG(m_vertices.empty(), "mesh with no vertexes in FBX file, did you mean to delete it?");
+ ERR_FAIL_COND_MSG(m_vertices.empty(), "mesh with no vertices in FBX file, did you mean to delete it?");
ERR_FAIL_COND_MSG(m_face_indices.empty(), "mesh has no faces, was this intended?");
// Retrieve layer elements, for all of the mesh
@@ -278,7 +278,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const ElementPtr element, const std::str
}
}
// As the algorithm above, this check is useless. Because the first
- // ever vertex is always considered the begining of a polygon.
+ // ever vertex is always considered the beginning of a polygon.
ERR_FAIL_COND_MSG(found_it == false, "Was not possible to find the first vertex of this polygon. FBX file is corrupted.");
} else {
@@ -418,7 +418,7 @@ MeshGeometry::MappingData<T> MeshGeometry::resolve_vertex_data_array(
// parse data into array
ParseVectorDataArray(tempData.data, GetRequiredElement(source, dataElementName));
- // index array wont always exist
+ // index array won't always exist
const ElementPtr element = GetOptionalElement(source, indexDataElementName);
if (element) {
ParseVectorDataArray(tempData.index, element);
diff --git a/modules/fbx/fbx_parser/FBXMeshGeometry.h b/modules/fbx/fbx_parser/FBXMeshGeometry.h
index 05493c4aec..c9b25f008d 100644
--- a/modules/fbx/fbx_parser/FBXMeshGeometry.h
+++ b/modules/fbx/fbx_parser/FBXMeshGeometry.h
@@ -122,7 +122,7 @@ typedef std::vector<int> MatIndexArray;
/// ## Map Type:
/// * None The mapping is undetermined.
/// * ByVertex There will be one mapping coordinate for each surface control point/vertex (ControlPoint is a vertex).
-/// * If you have direct reference type verticies[x]
+/// * If you have direct reference type vertices[x]
/// * If you have IndexToDirect reference type the UV
/// * ByPolygonVertex There will be one mapping coordinate for each vertex, for every polygon of which it is a part. This means that a vertex will have as many mapping coordinates as polygons of which it is a part. (Sorted by polygon, referencing vertex)
/// * ByPolygon There can be only one mapping coordinate for the whole polygon.
@@ -186,7 +186,7 @@ public:
/// Returns -1 if the vertices doesn't form an edge. Vertex order, doesn't
// matter.
static int get_edge_id(const std::vector<Edge> &p_map, int p_vertex_a, int p_vertex_b);
- // Retuns the edge point bu that ID, or the edge with -1 vertices if the
+ // Returns the edge point bu that ID, or the edge with -1 vertices if the
// id is not valid.
static Edge get_edge(const std::vector<Edge> &p_map, int p_id);
diff --git a/modules/fbx/fbx_parser/FBXParser.cpp b/modules/fbx/fbx_parser/FBXParser.cpp
index 98435b5c0f..163518d18f 100644
--- a/modules/fbx/fbx_parser/FBXParser.cpp
+++ b/modules/fbx/fbx_parser/FBXParser.cpp
@@ -82,7 +82,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXParser.h"
#include "FBXTokenizer.h"
#include "core/math/math_defs.h"
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include "core/math/vector3.h"
#include "core/string/print_string.h"
@@ -1157,7 +1157,7 @@ void ParseVectorDataArray(std::vector<int64_t> &out, const ElementPtr el) {
}
// ------------------------------------------------------------------------------------------------
-Transform ReadMatrix(const ElementPtr element) {
+Transform3D ReadMatrix(const ElementPtr element) {
std::vector<float> values;
ParseVectorDataArray(values, element);
@@ -1172,7 +1172,7 @@ Transform ReadMatrix(const ElementPtr element) {
}
}
- Transform xform;
+ Transform3D xform;
Basis basis;
basis.set(
diff --git a/modules/fbx/fbx_parser/FBXParser.h b/modules/fbx/fbx_parser/FBXParser.h
index 8b248e8791..93836c2205 100644
--- a/modules/fbx/fbx_parser/FBXParser.h
+++ b/modules/fbx/fbx_parser/FBXParser.h
@@ -81,7 +81,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include "core/math/color.h"
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include "core/math/vector2.h"
#include "core/math/vector3.h"
@@ -264,7 +264,7 @@ TokenPtr GetRequiredToken(const ElementPtr el, unsigned int index);
// ------------------------------------------------------------------------------------------------
// read a 4x4 matrix from an array of 16 floats
-Transform ReadMatrix(const ElementPtr element);
+Transform3D ReadMatrix(const ElementPtr element);
} // namespace FBXDocParser
#endif // FBX_PARSER_H
diff --git a/modules/fbx/tools/import_utils.cpp b/modules/fbx/tools/import_utils.cpp
index c87dd1fd3a..66b0153308 100644
--- a/modules/fbx/tools/import_utils.cpp
+++ b/modules/fbx/tools/import_utils.cpp
@@ -80,7 +80,7 @@ Basis ImportUtils::EulerToBasis(FBXDocParser::Model::RotOrder mode, const Vector
return ret;
}
-Quat ImportUtils::EulerToQuaternion(FBXDocParser::Model::RotOrder mode, const Vector3 &p_rotation) {
+Quaternion ImportUtils::EulerToQuaternion(FBXDocParser::Model::RotOrder mode, const Vector3 &p_rotation) {
return ImportUtils::EulerToBasis(mode, p_rotation);
}
@@ -117,18 +117,18 @@ Vector3 ImportUtils::BasisToEuler(FBXDocParser::Model::RotOrder mode, const Basi
}
}
-Vector3 ImportUtils::QuaternionToEuler(FBXDocParser::Model::RotOrder mode, const Quat &p_rotation) {
+Vector3 ImportUtils::QuaternionToEuler(FBXDocParser::Model::RotOrder mode, const Quaternion &p_rotation) {
return BasisToEuler(mode, p_rotation);
}
-Transform get_unscaled_transform(const Transform &p_initial, real_t p_scale) {
- Transform unscaled = Transform(p_initial.basis, p_initial.origin * p_scale);
- ERR_FAIL_COND_V_MSG(unscaled.basis.determinant() == 0, Transform(), "det is zero unscaled?");
+Transform3D get_unscaled_transform(const Transform3D &p_initial, real_t p_scale) {
+ Transform3D unscaled = Transform3D(p_initial.basis, p_initial.origin * p_scale);
+ ERR_FAIL_COND_V_MSG(unscaled.basis.determinant() == 0, Transform3D(), "det is zero unscaled?");
return unscaled;
}
Vector3 get_poly_normal(const std::vector<Vector3> &p_vertices) {
- ERR_FAIL_COND_V_MSG(p_vertices.size() < 3, Vector3(0, 0, 0), "At least 3 vertices are necesary");
+ ERR_FAIL_COND_V_MSG(p_vertices.size() < 3, Vector3(0, 0, 0), "At least 3 vertices are necessary");
// Using long double to make sure that normal is computed for even really tiny objects.
typedef long double ldouble;
ldouble x = 0.0;
diff --git a/modules/fbx/tools/import_utils.h b/modules/fbx/tools/import_utils.h
index cf0f811e35..7625f67256 100644
--- a/modules/fbx/tools/import_utils.h
+++ b/modules/fbx/tools/import_utils.h
@@ -56,15 +56,15 @@ public:
static Basis EulerToBasis(FBXDocParser::Model::RotOrder mode, const Vector3 &p_rotation);
/// Converts rotation order vector (in rad) to quaternion.
- static Quat EulerToQuaternion(FBXDocParser::Model::RotOrder mode, const Vector3 &p_rotation);
+ static Quaternion EulerToQuaternion(FBXDocParser::Model::RotOrder mode, const Vector3 &p_rotation);
/// Converts basis into rotation order vector (in rad).
static Vector3 BasisToEuler(FBXDocParser::Model::RotOrder mode, const Basis &p_rotation);
/// Converts quaternion into rotation order vector (in rad).
- static Vector3 QuaternionToEuler(FBXDocParser::Model::RotOrder mode, const Quat &p_rotation);
+ static Vector3 QuaternionToEuler(FBXDocParser::Model::RotOrder mode, const Quaternion &p_rotation);
- static void debug_xform(String name, const Transform &t) {
+ static void debug_xform(String name, const Transform3D &t) {
print_verbose(name + " " + t.origin + " rotation: " + (t.basis.get_euler() * (180 / Math_PI)));
}
@@ -391,7 +391,7 @@ public:
};
// Apply the transforms so the basis will have scale 1.
-Transform get_unscaled_transform(const Transform &p_initial, real_t p_scale);
+Transform3D get_unscaled_transform(const Transform3D &p_initial, real_t p_scale);
/// Uses the Newell's method to compute any polygon normal.
/// The polygon must be at least size of 3 or bigger.
diff --git a/modules/fbx/tools/validation_tools.h b/modules/fbx/tools/validation_tools.h
index fe0c92b22f..6c15eb7e12 100644
--- a/modules/fbx/tools/validation_tools.h
+++ b/modules/fbx/tools/validation_tools.h
@@ -33,8 +33,8 @@
#ifdef TOOLS_ENABLED
+#include "core/io/file_access.h"
#include "core/io/json.h"
-#include "core/os/file_access.h"
#include "core/string/ustring.h"
#include "core/templates/local_vector.h"
#include "core/templates/map.h"
diff --git a/modules/gdnative/doc_classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml
index 44d9e32ed8..4f1530598c 100644
--- a/modules/gdnative/doc_classes/GDNative.xml
+++ b/modules/gdnative/doc_classes/GDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDNative" inherits="Reference" version="4.0">
+<class name="GDNative" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 0de6b27d27..e552f443cf 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -32,8 +32,9 @@
#include "core/config/project_settings.h"
#include "core/core_constants.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_encrypted.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "scene/main/scene_tree.h"
@@ -335,9 +336,18 @@ bool GDNative::initialize() {
// On OSX the exported libraries are located under the Frameworks directory.
// So we need to replace the library path.
String path = ProjectSettings::get_singleton()->globalize_path(lib_path);
- if (!FileAccess::exists(path)) {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ if (!da->file_exists(path) && !da->dir_exists(path)) {
path = OS::get_singleton()->get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(lib_path.get_file());
}
+
+ if (da->dir_exists(path)) { // Target library is a ".framework", add library base name to the path.
+ path = path.plus_file(path.get_file().get_basename());
+ }
+
+ memdelete(da);
+
#else
String path = ProjectSettings::get_singleton()->globalize_path(lib_path);
#endif
diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h
index a28c58ec0d..0cc6487ea4 100644
--- a/modules/gdnative/gdnative.h
+++ b/modules/gdnative/gdnative.h
@@ -138,8 +138,8 @@ struct GDNativeCallRegistry {
Vector<StringName> get_native_call_types();
};
-class GDNative : public Reference {
- GDCLASS(GDNative, Reference);
+class GDNative : public RefCounted {
+ GDCLASS(GDNative, RefCounted);
Ref<GDNativeLibrary> library;
diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp
deleted file mode 100644
index 8ebcf7c91f..0000000000
--- a/modules/gdnative/gdnative/quat.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*************************************************************************/
-/* quat.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "gdnative/quat.h"
-
-#include "core/math/quat.h"
-
-static_assert(sizeof(godot_quat) == sizeof(Quat), "Quat size mismatch");
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void GDAPI godot_quat_new(godot_quat *p_self) {
- memnew_placement(p_self, Quat);
-}
-
-void GDAPI godot_quat_new_copy(godot_quat *r_dest, const godot_quat *p_src) {
- memnew_placement(r_dest, Quat(*(Quat *)p_src));
-}
-
-godot_real_t GDAPI *godot_quat_operator_index(godot_quat *p_self, godot_int p_index) {
- Quat *self = (Quat *)p_self;
- return (godot_real_t *)&self->operator[](p_index);
-}
-
-const godot_real_t GDAPI *godot_quat_operator_index_const(const godot_quat *p_self, godot_int p_index) {
- const Quat *self = (const Quat *)p_self;
- return (const godot_real_t *)&self->operator[](p_index);
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/modules/gdnative/gdnative/quaternion.cpp b/modules/gdnative/gdnative/quaternion.cpp
new file mode 100644
index 0000000000..62bcbbd382
--- /dev/null
+++ b/modules/gdnative/gdnative/quaternion.cpp
@@ -0,0 +1,61 @@
+/*************************************************************************/
+/* quaternion.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "gdnative/quaternion.h"
+
+#include "core/math/quaternion.h"
+
+static_assert(sizeof(godot_quaternion) == sizeof(Quaternion), "Quaternion size mismatch");
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GDAPI godot_quaternion_new(godot_quaternion *p_self) {
+ memnew_placement(p_self, Quaternion);
+}
+
+void GDAPI godot_quaternion_new_copy(godot_quaternion *r_dest, const godot_quaternion *p_src) {
+ memnew_placement(r_dest, Quaternion(*(Quaternion *)p_src));
+}
+
+godot_real_t GDAPI *godot_quaternion_operator_index(godot_quaternion *p_self, godot_int p_index) {
+ Quaternion *self = (Quaternion *)p_self;
+ return (godot_real_t *)&self->operator[](p_index);
+}
+
+const godot_real_t GDAPI *godot_quaternion_operator_index_const(const godot_quaternion *p_self, godot_int p_index) {
+ const Quaternion *self = (const Quaternion *)p_self;
+ return (const godot_real_t *)&self->operator[](p_index);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp
deleted file mode 100644
index bfaaa13db2..0000000000
--- a/modules/gdnative/gdnative/transform.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*************************************************************************/
-/* transform.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "gdnative/transform.h"
-
-#include "core/math/transform.h"
-
-static_assert(sizeof(godot_transform) == sizeof(Transform), "Transform size mismatch");
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void GDAPI godot_transform_new(godot_transform *p_self) {
- memnew_placement(p_self, Transform);
-}
-
-void GDAPI godot_transform_new_copy(godot_transform *r_dest, const godot_transform *p_src) {
- memnew_placement(r_dest, Transform(*(Transform *)p_src));
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/modules/gdnative/gdnative/transform_3d.cpp b/modules/gdnative/gdnative/transform_3d.cpp
new file mode 100644
index 0000000000..8bd2a68d63
--- /dev/null
+++ b/modules/gdnative/gdnative/transform_3d.cpp
@@ -0,0 +1,51 @@
+/*************************************************************************/
+/* transform_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "gdnative/transform_3d.h"
+
+#include "core/math/transform_3d.h"
+
+static_assert(sizeof(godot_transform3d) == sizeof(Transform3D), "Transform3D size mismatch");
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GDAPI godot_transform3d_new(godot_transform3d *p_self) {
+ memnew_placement(p_self, Transform3D);
+}
+
+void GDAPI godot_transform3d_new_copy(godot_transform3d *r_dest, const godot_transform3d *p_src) {
+ memnew_placement(r_dest, Transform3D(*(Transform3D *)p_src));
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp
index 7801e21ab2..cfb57137bb 100644
--- a/modules/gdnative/gdnative/variant.cpp
+++ b/modules/gdnative/gdnative/variant.cpp
@@ -30,7 +30,7 @@
#include "gdnative/variant.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/variant/variant.h"
#ifdef __cplusplus
@@ -143,10 +143,10 @@ void GDAPI godot_variant_new_plane(godot_variant *r_dest, const godot_plane *p_p
memnew_placement_custom(dest, Variant, Variant(*plane));
}
-void GDAPI godot_variant_new_quat(godot_variant *r_dest, const godot_quat *p_quat) {
+void GDAPI godot_variant_new_quaternion(godot_variant *r_dest, const godot_quaternion *p_quaternion) {
Variant *dest = (Variant *)r_dest;
- const Quat *quat = (const Quat *)p_quat;
- memnew_placement_custom(dest, Variant, Variant(*quat));
+ const Quaternion *quaternion = (const Quaternion *)p_quaternion;
+ memnew_placement_custom(dest, Variant, Variant(*quaternion));
}
void GDAPI godot_variant_new_aabb(godot_variant *r_dest, const godot_aabb *p_aabb) {
@@ -161,9 +161,9 @@ void GDAPI godot_variant_new_basis(godot_variant *r_dest, const godot_basis *p_b
memnew_placement_custom(dest, Variant, Variant(*basis));
}
-void GDAPI godot_variant_new_transform(godot_variant *r_dest, const godot_transform *p_trans) {
+void GDAPI godot_variant_new_transform3d(godot_variant *r_dest, const godot_transform3d *p_trans) {
Variant *dest = (Variant *)r_dest;
- const Transform *trans = (const Transform *)p_trans;
+ const Transform3D *trans = (const Transform3D *)p_trans;
memnew_placement_custom(dest, Variant, Variant(*trans));
}
@@ -200,17 +200,17 @@ void GDAPI godot_variant_new_signal(godot_variant *r_dest, const godot_signal *p
void GDAPI godot_variant_new_object(godot_variant *r_dest, const godot_object *p_obj) {
Variant *dest = (Variant *)r_dest;
const Object *obj = (const Object *)p_obj;
- const Reference *reference = Object::cast_to<Reference>(obj);
+ const RefCounted *ref_counted = Object::cast_to<RefCounted>(obj);
REF ref;
- if (reference) {
- ref = REF(reference);
+ if (ref_counted) {
+ ref = REF(ref_counted);
}
if (!ref.is_null()) {
memnew_placement_custom(dest, Variant, Variant(ref));
} else {
#if defined(DEBUG_METHODS_ENABLED)
- if (reference) {
- ERR_PRINT("Reference object has 0 refcount in godot_variant_new_object - you lost it somewhere.");
+ if (ref_counted) {
+ ERR_PRINT("RefCounted object has 0 refcount in godot_variant_new_object - you lost it somewhere.");
}
#endif
memnew_placement_custom(dest, Variant, Variant(obj));
@@ -378,10 +378,10 @@ godot_plane GDAPI godot_variant_as_plane(const godot_variant *p_self) {
return raw_dest;
}
-godot_quat GDAPI godot_variant_as_quat(const godot_variant *p_self) {
- godot_quat raw_dest;
+godot_quaternion GDAPI godot_variant_as_quaternion(const godot_variant *p_self) {
+ godot_quaternion raw_dest;
const Variant *self = (const Variant *)p_self;
- Quat *dest = (Quat *)&raw_dest;
+ Quaternion *dest = (Quaternion *)&raw_dest;
*dest = *self;
return raw_dest;
}
@@ -402,10 +402,10 @@ godot_basis GDAPI godot_variant_as_basis(const godot_variant *p_self) {
return raw_dest;
}
-godot_transform GDAPI godot_variant_as_transform(const godot_variant *p_self) {
- godot_transform raw_dest;
+godot_transform3d GDAPI godot_variant_as_transform3d(const godot_variant *p_self) {
+ godot_transform3d raw_dest;
const Variant *self = (const Variant *)p_self;
- Transform *dest = (Transform *)&raw_dest;
+ Transform3D *dest = (Transform3D *)&raw_dest;
*dest = *self;
return raw_dest;
}
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 489083e795..8c65447e5d 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -469,7 +469,7 @@
]
},
{
- "name": "godot_variant_new_quat",
+ "name": "godot_variant_new_quaternion",
"return_type": "void",
"arguments": [
[
@@ -477,8 +477,8 @@
"r_dest"
],
[
- "const godot_quat *",
- "p_quat"
+ "const godot_quaternion *",
+ "p_quaternion"
]
]
},
@@ -511,7 +511,7 @@
]
},
{
- "name": "godot_variant_new_transform",
+ "name": "godot_variant_new_transform3d",
"return_type": "void",
"arguments": [
[
@@ -519,7 +519,7 @@
"r_dest"
],
[
- "const godot_transform *",
+ "const godot_transform3d *",
"p_trans"
]
]
@@ -893,8 +893,8 @@
]
},
{
- "name": "godot_variant_as_quat",
- "return_type": "godot_quat",
+ "name": "godot_variant_as_quaternion",
+ "return_type": "godot_quaternion",
"arguments": [
[
"const godot_variant *",
@@ -923,8 +923,8 @@
]
},
{
- "name": "godot_variant_as_transform",
- "return_type": "godot_transform",
+ "name": "godot_variant_as_transform3d",
+ "return_type": "godot_transform3d",
"arguments": [
[
"const godot_variant *",
@@ -3866,35 +3866,35 @@
]
},
{
- "name": "godot_quat_new",
+ "name": "godot_quaternion_new",
"return_type": "void",
"arguments": [
[
- "godot_quat *",
+ "godot_quaternion *",
"p_self"
]
]
},
{
- "name": "godot_quat_new_copy",
+ "name": "godot_quaternion_new_copy",
"return_type": "void",
"arguments": [
[
- "godot_quat *",
+ "godot_quaternion *",
"r_dest"
],
[
- "const godot_quat *",
+ "const godot_quaternion *",
"p_src"
]
]
},
{
- "name": "godot_quat_operator_index",
+ "name": "godot_quaternion_operator_index",
"return_type": "godot_real_t *",
"arguments": [
[
- "godot_quat *",
+ "godot_quaternion *",
"p_self"
],
[
@@ -3904,11 +3904,11 @@
]
},
{
- "name": "godot_quat_operator_index_const",
+ "name": "godot_quaternion_operator_index_const",
"return_type": "const godot_real_t *",
"arguments": [
[
- "const godot_quat *",
+ "const godot_quaternion *",
"p_self"
],
[
@@ -4344,25 +4344,25 @@
]
},
{
- "name": "godot_transform_new",
+ "name": "godot_transform3d_new",
"return_type": "void",
"arguments": [
[
- "godot_transform *",
+ "godot_transform3d *",
"r_dest"
]
]
},
{
- "name": "godot_transform_new_copy",
+ "name": "godot_transform3d_new_copy",
"return_type": "void",
"arguments": [
[
- "godot_transform *",
+ "godot_transform3d *",
"r_dest"
],
[
- "const godot_transform *",
+ "const godot_transform3d *",
"p_src"
]
]
@@ -5068,12 +5068,12 @@
},
{
"name": "godot_xr_get_worldscale",
- "return_type": "godot_float",
+ "return_type": "godot_real_t",
"arguments": []
},
{
"name": "godot_xr_get_reference_frame",
- "return_type": "godot_transform",
+ "return_type": "godot_transform3d",
"arguments": []
},
{
@@ -5145,7 +5145,7 @@
"p_controller_id"
],
[
- "godot_transform *",
+ "godot_transform3d *",
"p_transform"
],
[
@@ -5189,7 +5189,7 @@
"p_exis"
],
[
- "godot_float",
+ "godot_real_t",
"p_value"
],
[
@@ -5200,7 +5200,7 @@
},
{
"name": "godot_xr_get_controller_rumble",
- "return_type": "godot_float",
+ "return_type": "godot_real_t",
"arguments": [
[
"godot_int",
diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp
index dfb26c13e3..b4ac0d886e 100644
--- a/modules/gdnative/gdnative_library_editor_plugin.cpp
+++ b/modules/gdnative/gdnative_library_editor_plugin.cpp
@@ -131,7 +131,7 @@ void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) {
EditorFileDialog::FileMode mode = EditorFileDialog::FILE_MODE_OPEN_FILE;
if (id == BUTTON_SELECT_DEPENDENCES) {
mode = EditorFileDialog::FILE_MODE_OPEN_FILES;
- } else if (treeItem->get_text(0) == "iOS") {
+ } else if (treeItem->get_text(0) == "iOS" || treeItem->get_text(0) == "macOS") {
mode = EditorFileDialog::FILE_MODE_OPEN_ANY;
}
@@ -278,11 +278,10 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() {
platforms["X11"] = platform_linux;
NativePlatformConfig platform_osx;
- platform_osx.name = "Mac OSX";
+ platform_osx.name = "macOS";
platform_osx.entries.push_back("64");
- platform_osx.entries.push_back("32");
- platform_osx.library_extension = "*.dylib";
- platforms["OSX"] = platform_osx;
+ platform_osx.library_extension = "*.framework; Framework, *.dylib; Dynamic Library";
+ platforms["macOS"] = platform_osx;
NativePlatformConfig platform_haiku;
platform_haiku.name = "Haiku";
diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index 9af9226a79..d8c290f6bd 100644
--- a/modules/gdnative/include/gdnative/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -149,9 +149,9 @@ typedef void godot_object;
#include <gdnative/plane.h>
-/////// Quat
+/////// Quaternion
-#include <gdnative/quat.h>
+#include <gdnative/quaternion.h>
/////// AABB
@@ -161,9 +161,9 @@ typedef void godot_object;
#include <gdnative/basis.h>
-/////// Transform
+/////// Transform3D
-#include <gdnative/transform.h>
+#include <gdnative/transform_3d.h>
/////// Color
diff --git a/modules/gdnative/include/gdnative/quat.h b/modules/gdnative/include/gdnative/quat.h
deleted file mode 100644
index 00abdb4404..0000000000
--- a/modules/gdnative/include/gdnative/quat.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*************************************************************************/
-/* quat.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef GODOT_QUAT_H
-#define GODOT_QUAT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <gdnative/math_defs.h>
-
-#define GODOT_QUAT_SIZE (sizeof(godot_real_t) * 4)
-
-#ifndef GODOT_CORE_API_GODOT_QUAT_TYPE_DEFINED
-#define GODOT_CORE_API_GODOT_QUAT_TYPE_DEFINED
-typedef struct {
- uint8_t _dont_touch_that[GODOT_QUAT_SIZE];
-} godot_quat;
-#endif
-
-#include <gdnative/gdnative.h>
-
-void GDAPI godot_quat_new(godot_quat *p_self);
-void GDAPI godot_quat_new_copy(godot_quat *r_dest, const godot_quat *p_src);
-godot_real_t GDAPI *godot_quat_operator_index(godot_quat *p_self, godot_int p_index);
-const godot_real_t GDAPI *godot_quat_operator_index_const(const godot_quat *p_self, godot_int p_index);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // GODOT_QUAT_H
diff --git a/modules/gdnative/include/gdnative/quaternion.h b/modules/gdnative/include/gdnative/quaternion.h
new file mode 100644
index 0000000000..75754e6ab5
--- /dev/null
+++ b/modules/gdnative/include/gdnative/quaternion.h
@@ -0,0 +1,60 @@
+/*************************************************************************/
+/* quaternion.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_QUATERNION_H
+#define GODOT_QUATERNION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <gdnative/math_defs.h>
+
+#define GODOT_QUATERNION_SIZE (sizeof(godot_real_t) * 4)
+
+#ifndef GODOT_CORE_API_GODOT_QUATERNION_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_QUATERNION_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_QUATERNION_SIZE];
+} godot_quaternion;
+#endif
+
+#include <gdnative/gdnative.h>
+
+void GDAPI godot_quaternion_new(godot_quaternion *p_self);
+void GDAPI godot_quaternion_new_copy(godot_quaternion *r_dest, const godot_quaternion *p_src);
+godot_real_t GDAPI *godot_quaternion_operator_index(godot_quaternion *p_self, godot_int p_index);
+const godot_real_t GDAPI *godot_quaternion_operator_index_const(const godot_quaternion *p_self, godot_int p_index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GODOT_QUATERNION_H
diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h
deleted file mode 100644
index 3861b5683a..0000000000
--- a/modules/gdnative/include/gdnative/transform.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*************************************************************************/
-/* transform.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef GODOT_TRANSFORM_H
-#define GODOT_TRANSFORM_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <gdnative/math_defs.h>
-
-#define GODOT_TRANSFORM_SIZE (sizeof(godot_real_t) * 12)
-
-#ifndef GODOT_CORE_API_GODOT_TRANSFORM_TYPE_DEFINED
-#define GODOT_CORE_API_GODOT_TRANSFORM_TYPE_DEFINED
-typedef struct {
- uint8_t _dont_touch_that[GODOT_TRANSFORM_SIZE];
-} godot_transform;
-#endif
-
-#include <gdnative/gdnative.h>
-
-void GDAPI godot_transform_new(godot_transform *p_self);
-void GDAPI godot_transform_new_copy(godot_transform *r_dest, const godot_transform *p_src);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // GODOT_TRANSFORM_H
diff --git a/modules/gdnative/include/gdnative/transform_3d.h b/modules/gdnative/include/gdnative/transform_3d.h
new file mode 100644
index 0000000000..97ad451e9b
--- /dev/null
+++ b/modules/gdnative/include/gdnative/transform_3d.h
@@ -0,0 +1,60 @@
+/*************************************************************************/
+/* transform_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_TRANSFORM3D_H
+#define GODOT_TRANSFORM3D_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <gdnative/math_defs.h>
+
+#define GODOT_TRANSFORM3D_SIZE (sizeof(godot_real_t) * 12)
+
+#ifndef GODOT_CORE_API_GODOT_TRANSFORM3D_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_TRANSFORM3D_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_TRANSFORM3D_SIZE];
+} godot_transform3d;
+#endif
+
+#include <gdnative/gdnative.h>
+
+void GDAPI godot_transform3d_new(godot_transform3d *p_self);
+void GDAPI godot_transform3d_new_copy(godot_transform3d *r_dest, const godot_transform3d *p_src);
+godot_vector3 GDAPI *godot_transform3d_operator_index(godot_transform3d *p_self, godot_int p_index);
+const godot_vector3 GDAPI *godot_transform3d_operator_index_const(const godot_transform3d *p_self, godot_int p_index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GODOT_TRANSFORM3D_H
diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h
index 3e06ed9aa4..dd4f76cf57 100644
--- a/modules/gdnative/include/gdnative/variant.h
+++ b/modules/gdnative/include/gdnative/variant.h
@@ -56,10 +56,10 @@ typedef enum godot_variant_type {
GODOT_VARIANT_TYPE_VECTOR3I,
GODOT_VARIANT_TYPE_TRANSFORM2D,
GODOT_VARIANT_TYPE_PLANE,
- GODOT_VARIANT_TYPE_QUAT,
+ GODOT_VARIANT_TYPE_QUATERNION,
GODOT_VARIANT_TYPE_AABB,
GODOT_VARIANT_TYPE_BASIS,
- GODOT_VARIANT_TYPE_TRANSFORM,
+ GODOT_VARIANT_TYPE_TRANSFORM3D,
// misc types
GODOT_VARIANT_TYPE_COLOR,
@@ -177,14 +177,14 @@ typedef void (*godot_ptr_utility_function)(void *r_return, const void **p_argume
#include <gdnative/node_path.h>
#include <gdnative/packed_arrays.h>
#include <gdnative/plane.h>
-#include <gdnative/quat.h>
+#include <gdnative/quaternion.h>
#include <gdnative/rect2.h>
#include <gdnative/rid.h>
#include <gdnative/signal.h>
#include <gdnative/string.h>
#include <gdnative/string_name.h>
-#include <gdnative/transform.h>
#include <gdnative/transform2d.h>
+#include <gdnative/transform_3d.h>
#include <gdnative/variant.h>
#include <gdnative/vector2.h>
#include <gdnative/vector3.h>
@@ -208,10 +208,10 @@ void GDAPI godot_variant_new_vector3(godot_variant *r_dest, const godot_vector3
void GDAPI godot_variant_new_vector3i(godot_variant *r_dest, const godot_vector3i *p_v3);
void GDAPI godot_variant_new_transform2d(godot_variant *r_dest, const godot_transform2d *p_t2d);
void GDAPI godot_variant_new_plane(godot_variant *r_dest, const godot_plane *p_plane);
-void GDAPI godot_variant_new_quat(godot_variant *r_dest, const godot_quat *p_quat);
+void GDAPI godot_variant_new_quaternion(godot_variant *r_dest, const godot_quaternion *p_quaternion);
void GDAPI godot_variant_new_aabb(godot_variant *r_dest, const godot_aabb *p_aabb);
void GDAPI godot_variant_new_basis(godot_variant *r_dest, const godot_basis *p_basis);
-void GDAPI godot_variant_new_transform(godot_variant *r_dest, const godot_transform *p_trans);
+void GDAPI godot_variant_new_transform3d(godot_variant *r_dest, const godot_transform3d *p_trans);
void GDAPI godot_variant_new_color(godot_variant *r_dest, const godot_color *p_color);
void GDAPI godot_variant_new_string_name(godot_variant *r_dest, const godot_string_name *p_s);
void GDAPI godot_variant_new_node_path(godot_variant *r_dest, const godot_node_path *p_np);
@@ -243,10 +243,10 @@ godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_self);
godot_vector3i GDAPI godot_variant_as_vector3i(const godot_variant *p_self);
godot_transform2d GDAPI godot_variant_as_transform2d(const godot_variant *p_self);
godot_plane GDAPI godot_variant_as_plane(const godot_variant *p_self);
-godot_quat GDAPI godot_variant_as_quat(const godot_variant *p_self);
+godot_quaternion GDAPI godot_variant_as_quaternion(const godot_variant *p_self);
godot_aabb GDAPI godot_variant_as_aabb(const godot_variant *p_self);
godot_basis GDAPI godot_variant_as_basis(const godot_variant *p_self);
-godot_transform GDAPI godot_variant_as_transform(const godot_variant *p_self);
+godot_transform3d GDAPI godot_variant_as_transform3d(const godot_variant *p_self);
godot_color GDAPI godot_variant_as_color(const godot_variant *p_self);
godot_string_name GDAPI godot_variant_as_string_name(const godot_variant *p_self);
godot_node_path GDAPI godot_variant_as_node_path(const godot_variant *p_self);
diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h
index b76f89cc99..34ed4f097d 100644
--- a/modules/gdnative/include/pluginscript/godot_pluginscript.h
+++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h
@@ -61,7 +61,7 @@ typedef struct {
//this is used by script languages that keep a reference counter of their own
//you can make make Ref<> not die when it reaches zero, so deleting the reference
//depends entirely from the script.
- // Note: You can set those function pointer to nullptr if not needed.
+ // Note: You can set those function pointer to nullptr if not needed.
void (*refcount_incremented)(godot_pluginscript_instance_data *p_data);
bool (*refcount_decremented)(godot_pluginscript_instance_data *p_data); // return true if it can die
} godot_pluginscript_instance_desc;
@@ -121,12 +121,12 @@ typedef struct {
const char *name;
const char *type;
const char *extension;
- const char **recognized_extensions; // nullptr terminated array
+ const char **recognized_extensions; // nullptr terminated array
godot_pluginscript_language_data *(*init)();
void (*finish)(godot_pluginscript_language_data *p_data);
- const char **reserved_words; // nullptr terminated array
- const char **comment_delimiters; // nullptr terminated array
- const char **string_delimiters; // nullptr terminated array
+ const char **reserved_words; // nullptr terminated array
+ const char **comment_delimiters; // nullptr terminated array
+ const char **string_delimiters; // nullptr terminated array
godot_bool has_named_classes;
godot_bool supports_builtin_mode;
godot_bool can_inherit_from_file;
diff --git a/modules/gdnative/include/xr/godot_xr.h b/modules/gdnative/include/xr/godot_xr.h
index 7eaf1c7ec3..53cb830cbb 100644
--- a/modules/gdnative/include/xr/godot_xr.h
+++ b/modules/gdnative/include/xr/godot_xr.h
@@ -41,8 +41,8 @@ extern "C" {
// version info to detect whether a call is available
// Use these to populate version in your plugin
-#define GODOTVR_API_MAJOR 1
-#define GODOTVR_API_MINOR 1
+#define GODOTVR_API_MAJOR 4
+#define GODOTVR_API_MINOR 0
typedef struct {
godot_gdnative_api_version version; /* version of our API */
@@ -52,25 +52,32 @@ typedef struct {
godot_int (*get_capabilities)(const void *);
godot_bool (*get_anchor_detection_is_enabled)(const void *);
void (*set_anchor_detection_is_enabled)(void *, godot_bool);
- godot_bool (*is_stereo)(const void *);
+ godot_int (*get_view_count)(const void *);
godot_bool (*is_initialized)(const void *);
godot_bool (*initialize)(void *);
void (*uninitialize)(void *);
godot_vector2 (*get_render_targetsize)(const void *);
- godot_transform (*get_transform_for_eye)(void *, godot_int, godot_transform *);
- void (*fill_projection_for_eye)(void *, godot_float *, godot_int, godot_float, godot_float, godot_float);
- void (*commit_for_eye)(void *, godot_int, godot_rid *, godot_rect2 *);
+
+ godot_transform3d (*get_camera_transform)(void *);
+ godot_transform3d (*get_transform_for_view)(void *, godot_int, godot_transform3d *);
+ void (*fill_projection_for_view)(void *, godot_real_t *, godot_int, godot_real_t, godot_real_t, godot_real_t);
+ void (*commit_views)(void *, godot_rid *, godot_rect2 *);
+
void (*process)(void *);
- godot_int (*get_external_texture_for_eye)(void *, godot_int);
void (*notification)(void *, godot_int);
godot_int (*get_camera_feed_id)(void *);
+
+ // possibly deprecate but adding/keeping as a reminder these are in Godot 3
+ void (*commit_for_eye)(void *, godot_int, godot_rid *, godot_rect2 *);
+ godot_int (*get_external_texture_for_eye)(void *, godot_int);
+ godot_int (*get_external_depth_for_eye)(void *, godot_int);
} godot_xr_interface_gdnative;
void GDAPI godot_xr_register_interface(const godot_xr_interface_gdnative *p_interface);
// helper functions to access XRServer data
-godot_float GDAPI godot_xr_get_worldscale();
-godot_transform GDAPI godot_xr_get_reference_frame();
+godot_real_t GDAPI godot_xr_get_worldscale();
+godot_transform3d GDAPI godot_xr_get_reference_frame();
// helper functions for rendering
void GDAPI godot_xr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect);
@@ -79,10 +86,10 @@ godot_int GDAPI godot_xr_get_texid(godot_rid *p_render_target);
// helper functions for updating XR controllers
godot_int GDAPI godot_xr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
void GDAPI godot_xr_remove_controller(godot_int p_controller_id);
-void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
+void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform3d *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
void GDAPI godot_xr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed);
-void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_float p_value, godot_bool p_can_be_negative);
-godot_float GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id);
+void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real_t p_value, godot_bool p_can_be_negative);
+godot_real_t GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index f184c84615..57717010f7 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -34,10 +34,11 @@
#include "core/config/engine.h"
#include "core/core_constants.h"
+#include "core/io/file_access.h"
#include "core/object/class_db.h"
-#include "core/os/file_access.h"
#include "core/string/string_builder.h"
#include "core/templates/pair.h"
+#include "core/variant/variant_parser.h"
// helper stuff
@@ -121,7 +122,7 @@ struct ClassAPI {
String singleton_name;
bool is_instantiable = false;
// @Unclear
- bool is_reference = false;
+ bool is_ref_counted = false;
bool has_indexing = false; // For builtin types.
String indexed_type; // For builtin types.
bool is_keyed = false; // For builtin types.
@@ -254,10 +255,10 @@ List<ClassAPI> generate_c_api_classes() {
{
List<StringName> inheriters;
- ClassDB::get_inheriters_from_class("Reference", &inheriters);
- bool is_reference = !!inheriters.find(class_name) || class_name == "Reference";
+ ClassDB::get_inheriters_from_class("RefCounted", &inheriters);
+ bool is_ref_counted = !!inheriters.find(class_name) || class_name == "RefCounted";
// @Unclear
- class_api.is_reference = !class_api.is_singleton && is_reference;
+ class_api.is_ref_counted = !class_api.is_singleton && is_ref_counted;
}
// constants
@@ -509,10 +510,10 @@ List<ClassAPI> generate_c_builtin_api_types() {
case Variant::PACKED_VECTOR2_ARRAY:
case Variant::PACKED_VECTOR3_ARRAY:
case Variant::PACKED_COLOR_ARRAY:
- class_api.is_reference = true;
+ class_api.is_ref_counted = true;
break;
default:
- class_api.is_reference = false;
+ class_api.is_ref_counted = false;
break;
}
@@ -638,6 +639,7 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) {
// I'm sorry for the \t mess
List<String> source;
+ VariantWriter writer;
source.push_back("[\n");
@@ -652,7 +654,7 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) {
source.push_back(String("\t\t\"singleton\": ") + (api.is_singleton ? "true" : "false") + ",\n");
source.push_back("\t\t\"singleton_name\": \"" + api.singleton_name + "\",\n");
source.push_back(String("\t\t\"instantiable\": ") + (api.is_instantiable ? "true" : "false") + ",\n");
- source.push_back(String("\t\t\"is_reference\": ") + (api.is_reference ? "true" : "false") + ",\n");
+ source.push_back(String("\t\t\"is_ref_counted\": ") + (api.is_ref_counted ? "true" : "false") + ",\n");
source.push_back("\t\t\"constants\": {\n");
for (List<ConstantAPI>::Element *e = api.constants.front(); e; e = e->next()) {
@@ -682,7 +684,12 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) {
source.push_back("\t\t\t\t\t\t\"name\": \"" + e->get().argument_names[i] + "\",\n");
source.push_back("\t\t\t\t\t\t\"type\": \"" + e->get().argument_types[i] + "\",\n");
source.push_back(String("\t\t\t\t\t\t\"has_default_value\": ") + (e->get().default_arguments.has(i) ? "true" : "false") + ",\n");
- source.push_back("\t\t\t\t\t\t\"default_value\": \"" + (e->get().default_arguments.has(i) ? (String)e->get().default_arguments[i] : "") + "\"\n");
+ String default_value;
+ if (e->get().default_arguments.has(i)) {
+ writer.write_to_string(e->get().default_arguments[i], default_value);
+ default_value = default_value.replace("\n", "").json_escape();
+ }
+ source.push_back("\t\t\t\t\t\t\"default_value\": \"" + default_value + "\"\n");
source.push_back(String("\t\t\t\t\t}") + ((i < e->get().argument_names.size() - 1) ? "," : "") + "\n");
}
source.push_back("\t\t\t\t]\n");
@@ -708,7 +715,12 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) {
source.push_back("\t\t\t\t\t\t\"name\": \"" + e->get().argument_names[i] + "\",\n");
source.push_back("\t\t\t\t\t\t\"type\": \"" + e->get().argument_types[i] + "\",\n");
source.push_back(String("\t\t\t\t\t\t\"has_default_value\": ") + (e->get().default_arguments.has(i) ? "true" : "false") + ",\n");
- source.push_back("\t\t\t\t\t\t\"default_value\": \"" + (e->get().default_arguments.has(i) ? (String)e->get().default_arguments[i] : "") + "\"\n");
+ String default_value;
+ if (e->get().default_arguments.has(i)) {
+ writer.write_to_string(e->get().default_arguments[i], default_value);
+ default_value = default_value.replace("\n", "").json_escape();
+ }
+ source.push_back("\t\t\t\t\t\t\"default_value\": \"" + default_value + "\"\n");
source.push_back(String("\t\t\t\t\t}") + ((i < e->get().argument_names.size() - 1) ? "," : "") + "\n");
}
source.push_back("\t\t\t\t]\n");
@@ -756,6 +768,8 @@ static void append_indented(StringBuilder &p_source, const char *p_text) {
}
static void write_builtin_method(StringBuilder &p_source, const MethodAPI &p_method) {
+ VariantWriter writer;
+
append_indented(p_source, vformat(R"("name": "%s",)", p_method.method_name));
append_indented(p_source, vformat(R"("return_type": "%s",)", p_method.return_type));
append_indented(p_source, vformat(R"("is_const": %s,)", p_method.is_const ? "true" : "false"));
@@ -771,7 +785,12 @@ static void write_builtin_method(StringBuilder &p_source, const MethodAPI &p_met
append_indented(p_source, vformat(R"("name": "%s",)", p_method.argument_names[i]));
append_indented(p_source, vformat(R"("type": "%s",)", p_method.argument_types[i]));
append_indented(p_source, vformat(R"("has_default_value": %s,)", p_method.default_arguments.has(i) ? "true" : "false"));
- append_indented(p_source, vformat(R"("default_value": "%s")", p_method.default_arguments.has(i) ? p_method.default_arguments[i].operator String() : ""));
+ String default_value;
+ if (p_method.default_arguments.has(i)) {
+ writer.write_to_string(p_method.default_arguments[i], default_value);
+ default_value = default_value.replace("\n", "").json_escape();
+ }
+ append_indented(p_source, vformat(R"("default_value": "%s")", default_value));
indent_level--;
append_indented(p_source, i < p_method.argument_count - 1 ? "}," : "}");
@@ -794,7 +813,7 @@ static List<String> generate_c_builtin_api_json(const List<ClassAPI> &p_api) {
append_indented(source, vformat(R"("name": "%s",)", class_api.class_name));
append_indented(source, vformat(R"("is_instantiable": %s,)", class_api.is_instantiable ? "true" : "false"));
- append_indented(source, vformat(R"("is_reference": %s,)", class_api.is_reference ? "true" : "false"));
+ append_indented(source, vformat(R"("is_ref_counted": %s,)", class_api.is_ref_counted ? "true" : "false"));
append_indented(source, vformat(R"("has_indexing": %s,)", class_api.has_indexing ? "true" : "false"));
append_indented(source, vformat(R"("indexed_type": "%s",)", class_api.has_indexing && class_api.indexed_type == "Nil" ? "Variant" : class_api.indexed_type));
append_indented(source, vformat(R"("is_keyed": %s,)", class_api.is_keyed ? "true" : "false"));
diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp
index b2abf8b8ae..b10a747568 100644
--- a/modules/gdnative/nativescript/godot_nativescript.cpp
+++ b/modules/gdnative/nativescript/godot_nativescript.cpp
@@ -70,8 +70,7 @@ void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char
const NativeScriptDesc *b = desc.base_data;
while (b) {
- desc.rpc_count += b->rpc_count;
- desc.rset_count += b->rset_count;
+ desc.rpc_methods.append_array(b->rpc_methods);
b = b->base_data;
}
@@ -94,8 +93,6 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const
desc.destroy_func = p_destroy_func;
desc.is_tool = true;
desc.base = p_base;
- desc.rpc_count = 0;
- desc.rset_count = 0;
if (classes->has(p_base)) {
desc.base_data = &(*classes)[p_base];
@@ -103,8 +100,7 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const
const NativeScriptDesc *b = desc.base_data;
while (b) {
- desc.rpc_count += b->rpc_count;
- desc.rset_count += b->rset_count;
+ desc.rpc_methods.append_array(b->rpc_methods);
b = b->base_data;
}
@@ -126,13 +122,16 @@ void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const cha
method.method = p_method;
method.rpc_mode = p_attr.rpc_type;
method.rpc_method_id = UINT16_MAX;
- if (p_attr.rpc_type != GODOT_METHOD_RPC_MODE_DISABLED) {
- method.rpc_method_id = E->get().rpc_count;
- E->get().rpc_count += 1;
- }
method.info = MethodInfo(p_function_name);
E->get().methods.insert(p_function_name, method);
+
+ if (p_attr.rpc_type != GODOT_METHOD_RPC_MODE_DISABLED) {
+ MultiplayerAPI::RPCConfig nd;
+ nd.name = String(p_name);
+ nd.rpc_mode = MultiplayerAPI::RPCMode(p_attr.rpc_type);
+ E->get().rpc_methods.push_back(nd);
+ }
}
void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const char *p_name, const char *p_path, godot_nativescript_property_attributes *p_attr, godot_nativescript_property_set_func p_set_func, godot_nativescript_property_get_func p_get_func) {
@@ -144,11 +143,6 @@ void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const c
NativeScriptDesc::Property property;
property.default_value = *(Variant *)&p_attr->default_value;
property.getter = p_get_func;
- property.rset_mode = p_attr->rset_type;
- if (p_attr->rset_type != GODOT_METHOD_RPC_MODE_DISABLED) {
- property.rset_property_id = E->get().rset_count;
- E->get().rset_count += 1;
- }
property.setter = p_set_func;
property.info = PropertyInfo((Variant::Type)p_attr->type,
p_path,
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index 46af70f73c..6c2d038654 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -37,8 +37,8 @@
#include "core/config/project_settings.h"
#include "core/core_constants.h"
#include "core/core_string_names.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_encrypted.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "main/main.h"
@@ -415,245 +415,11 @@ void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const {
}
}
-Vector<ScriptNetData> NativeScript::get_rpc_methods() const {
- Vector<ScriptNetData> v;
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
- if (E->get().rpc_mode != GODOT_METHOD_RPC_MODE_DISABLED) {
- ScriptNetData nd;
- nd.name = E->key();
- nd.mode = MultiplayerAPI::RPCMode(E->get().rpc_mode);
- v.push_back(nd);
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return v;
-}
-
-uint16_t NativeScript::get_rpc_method_id(const StringName &p_method) const {
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
- if (E) {
- return E->get().rpc_method_id;
- }
-
- script_data = script_data->base_data;
- }
-
- return UINT16_MAX;
-}
-
-StringName NativeScript::get_rpc_method(uint16_t p_id) const {
- ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName());
-
+const Vector<MultiplayerAPI::RPCConfig> NativeScript::get_rpc_methods() const {
NativeScriptDesc *script_data = get_script_desc();
+ ERR_FAIL_COND_V(!script_data, Vector<MultiplayerAPI::RPCConfig>());
- while (script_data) {
- for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
- if (E->get().rpc_method_id == p_id) {
- return E->key();
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return StringName();
-}
-
-MultiplayerAPI::RPCMode NativeScript::get_rpc_mode_by_id(uint16_t p_id) const {
- ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED);
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
- if (E->get().rpc_method_id == p_id) {
- switch (E->get().rpc_mode) {
- case GODOT_METHOD_RPC_MODE_DISABLED:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- case GODOT_METHOD_RPC_MODE_REMOTE:
- return MultiplayerAPI::RPC_MODE_REMOTE;
- case GODOT_METHOD_RPC_MODE_MASTER:
- return MultiplayerAPI::RPC_MODE_MASTER;
- case GODOT_METHOD_RPC_MODE_PUPPET:
- return MultiplayerAPI::RPC_MODE_PUPPET;
- case GODOT_METHOD_RPC_MODE_REMOTESYNC:
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- case GODOT_METHOD_RPC_MODE_MASTERSYNC:
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- default:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-MultiplayerAPI::RPCMode NativeScript::get_rpc_mode(const StringName &p_method) const {
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
- if (E) {
- switch (E->get().rpc_mode) {
- case GODOT_METHOD_RPC_MODE_DISABLED:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- case GODOT_METHOD_RPC_MODE_REMOTE:
- return MultiplayerAPI::RPC_MODE_REMOTE;
- case GODOT_METHOD_RPC_MODE_MASTER:
- return MultiplayerAPI::RPC_MODE_MASTER;
- case GODOT_METHOD_RPC_MODE_PUPPET:
- return MultiplayerAPI::RPC_MODE_PUPPET;
- case GODOT_METHOD_RPC_MODE_REMOTESYNC:
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- case GODOT_METHOD_RPC_MODE_MASTERSYNC:
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- default:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-Vector<ScriptNetData> NativeScript::get_rset_properties() const {
- Vector<ScriptNetData> v;
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
- if (E.get().rset_mode != GODOT_METHOD_RPC_MODE_DISABLED) {
- ScriptNetData nd;
- nd.name = E.key();
- nd.mode = MultiplayerAPI::RPCMode(E.get().rset_mode);
- v.push_back(nd);
- }
- }
- script_data = script_data->base_data;
- }
-
- return v;
-}
-
-uint16_t NativeScript::get_rset_property_id(const StringName &p_variable) const {
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
- if (E) {
- return E.get().rset_property_id;
- }
-
- script_data = script_data->base_data;
- }
-
- return UINT16_MAX;
-}
-
-StringName NativeScript::get_rset_property(uint16_t p_id) const {
- ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName());
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
- if (E.get().rset_property_id == p_id) {
- return E.key();
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return StringName();
-}
-
-MultiplayerAPI::RPCMode NativeScript::get_rset_mode_by_id(uint16_t p_id) const {
- ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED);
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
- if (E.get().rset_property_id == p_id) {
- switch (E.get().rset_mode) {
- case GODOT_METHOD_RPC_MODE_DISABLED:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- case GODOT_METHOD_RPC_MODE_REMOTE:
- return MultiplayerAPI::RPC_MODE_REMOTE;
- case GODOT_METHOD_RPC_MODE_MASTER:
- return MultiplayerAPI::RPC_MODE_MASTER;
- case GODOT_METHOD_RPC_MODE_PUPPET:
- return MultiplayerAPI::RPC_MODE_PUPPET;
- case GODOT_METHOD_RPC_MODE_REMOTESYNC:
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- case GODOT_METHOD_RPC_MODE_MASTERSYNC:
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- default:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-MultiplayerAPI::RPCMode NativeScript::get_rset_mode(const StringName &p_variable) const {
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
- if (E) {
- switch (E.get().rset_mode) {
- case GODOT_METHOD_RPC_MODE_DISABLED:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- case GODOT_METHOD_RPC_MODE_REMOTE:
- return MultiplayerAPI::RPC_MODE_REMOTE;
- case GODOT_METHOD_RPC_MODE_MASTER:
- return MultiplayerAPI::RPC_MODE_MASTER;
- case GODOT_METHOD_RPC_MODE_PUPPET:
- return MultiplayerAPI::RPC_MODE_PUPPET;
- case GODOT_METHOD_RPC_MODE_REMOTESYNC:
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- case GODOT_METHOD_RPC_MODE_MASTERSYNC:
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- default:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return MultiplayerAPI::RPC_MODE_DISABLED;
+ return script_data->rpc_methods;
}
String NativeScript::get_class_documentation() const {
@@ -739,7 +505,7 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
if (!(script_data->base_native_type == "")) {
owner = ClassDB::instance(script_data->base_native_type);
} else {
- owner = memnew(Reference);
+ owner = memnew(RefCounted);
}
if (!owner) {
@@ -747,7 +513,7 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
return Variant();
}
- Reference *r = Object::cast_to<Reference>(owner);
+ RefCounted *r = Object::cast_to<RefCounted>(owner);
if (r) {
ref = REF(r);
}
@@ -1046,46 +812,10 @@ Ref<Script> NativeScriptInstance::get_script() const {
return script;
}
-Vector<ScriptNetData> NativeScriptInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> NativeScriptInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t NativeScriptInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName NativeScriptInstance::get_rpc_method(uint16_t p_id) const {
- return script->get_rpc_method(p_id);
-}
-
-MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode_by_id(uint16_t p_id) const {
- return script->get_rpc_mode_by_id(p_id);
-}
-
-MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> NativeScriptInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t NativeScriptInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName NativeScriptInstance::get_rset_property(uint16_t p_id) const {
- return script->get_rset_property(p_id);
-}
-
-MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode_by_id(uint16_t p_id) const {
- return script->get_rset_mode_by_id(p_id);
-}
-
-MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
ScriptLanguage *NativeScriptInstance::get_language() {
return NativeScriptLanguage::get_singleton();
}
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index ca5e76e43e..1756321281 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -62,8 +62,6 @@ struct NativeScriptDesc {
godot_nativescript_property_get_func getter;
PropertyInfo info;
Variant default_value;
- int rset_mode = 0;
- uint16_t rset_property_id;
String documentation;
};
@@ -72,9 +70,8 @@ struct NativeScriptDesc {
String documentation;
};
- uint16_t rpc_count = 0;
Map<StringName, Method> methods;
- uint16_t rset_count = 0;
+ Vector<MultiplayerAPI::RPCConfig> rpc_methods;
OrderedHashMap<StringName, Property> properties;
Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals
StringName base;
@@ -178,17 +175,7 @@ public:
virtual void get_script_method_list(List<MethodInfo> *p_list) const override;
virtual void get_script_property_list(List<PropertyInfo> *p_list) const override;
- virtual Vector<ScriptNetData> get_rpc_methods() const override;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const override;
- virtual StringName get_rpc_method(uint16_t p_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- virtual Vector<ScriptNetData> get_rset_properties() const override;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const override;
- virtual StringName get_rset_property(uint16_t p_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
String get_class_documentation() const;
String get_method_documentation(const StringName &p_method) const;
@@ -226,17 +213,7 @@ public:
String to_string(bool *r_valid);
virtual Ref<Script> get_script() const;
- virtual Vector<ScriptNetData> get_rpc_methods() const;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
-
- virtual Vector<ScriptNetData> get_rset_properties() const;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
- virtual StringName get_rset_property(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const;
virtual ScriptLanguage *get_language();
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp
index 7f8dba0906..ed1c0af3ed 100644
--- a/modules/gdnative/pluginscript/pluginscript_instance.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp
@@ -100,46 +100,10 @@ String PluginScriptInstance::to_string(bool *r_valid) {
return str_ret;
}
-Vector<ScriptNetData> PluginScriptInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> PluginScriptInstance::get_rpc_methods() const {
return _script->get_rpc_methods();
}
-uint16_t PluginScriptInstance::get_rpc_method_id(const StringName &p_variable) const {
- return _script->get_rpc_method_id(p_variable);
-}
-
-StringName PluginScriptInstance::get_rpc_method(uint16_t p_id) const {
- return _script->get_rpc_method(p_id);
-}
-
-MultiplayerAPI::RPCMode PluginScriptInstance::get_rpc_mode_by_id(uint16_t p_id) const {
- return _script->get_rpc_mode_by_id(p_id);
-}
-
-MultiplayerAPI::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const {
- return _script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> PluginScriptInstance::get_rset_properties() const {
- return _script->get_rset_properties();
-}
-
-uint16_t PluginScriptInstance::get_rset_property_id(const StringName &p_variable) const {
- return _script->get_rset_property_id(p_variable);
-}
-
-StringName PluginScriptInstance::get_rset_property(uint16_t p_id) const {
- return _script->get_rset_property(p_id);
-}
-
-MultiplayerAPI::RPCMode PluginScriptInstance::get_rset_mode_by_id(uint16_t p_id) const {
- return _script->get_rset_mode_by_id(p_id);
-}
-
-MultiplayerAPI::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return _script->get_rset_mode(p_variable);
-}
-
void PluginScriptInstance::refcount_incremented() {
if (_desc->refcount_decremented) {
_desc->refcount_incremented(_data);
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h
index b263c0e62c..25b62ae8ab 100644
--- a/modules/gdnative/pluginscript/pluginscript_instance.h
+++ b/modules/gdnative/pluginscript/pluginscript_instance.h
@@ -71,17 +71,7 @@ public:
void set_path(const String &p_path);
- virtual Vector<ScriptNetData> get_rpc_methods() const;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
-
- virtual Vector<ScriptNetData> get_rset_properties() const;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
- virtual StringName get_rset_property(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const;
virtual void refcount_incremented();
virtual bool refcount_decremented();
diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp
index 1360cf0299..0291ae560b 100644
--- a/modules/gdnative/pluginscript/pluginscript_language.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_language.cpp
@@ -30,7 +30,7 @@
// Godot imports
#include "core/config/project_settings.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
// PluginScript imports
#include "pluginscript_language.h"
diff --git a/modules/gdnative/pluginscript/pluginscript_loader.cpp b/modules/gdnative/pluginscript/pluginscript_loader.cpp
index f2165cd225..462452a897 100644
--- a/modules/gdnative/pluginscript/pluginscript_loader.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_loader.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
// Godot imports
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
// Pythonscript imports
#include "pluginscript_language.h"
#include "pluginscript_loader.h"
diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp
index 31e6a81975..1dabb1db63 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_script.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
// Godot imports
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
// PluginScript imports
#include "pluginscript_instance.h"
#include "pluginscript_script.h"
@@ -94,7 +94,7 @@ Variant PluginScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
Object *owner = nullptr;
if (get_instance_base_type() == "") {
- owner = memnew(Reference);
+ owner = memnew(RefCounted);
} else {
owner = ClassDB::instance(get_instance_base_type());
}
@@ -104,7 +104,7 @@ Variant PluginScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
return Variant();
}
- Reference *r = Object::cast_to<Reference>(owner);
+ RefCounted *r = Object::cast_to<RefCounted>(owner);
if (r) {
ref = REF(r);
}
@@ -212,6 +212,8 @@ ScriptInstance *PluginScript::instance_create(Object *p_this) {
}
bool PluginScript::instance_has(const Object *p_this) const {
+ ERR_FAIL_COND_V(!_language, false);
+
_language->lock();
bool hasit = _instances.has((Object *)p_this);
_language->unlock();
@@ -310,10 +312,9 @@ Error PluginScript::reload(bool p_keep_state) {
}
Array *methods = (Array *)&manifest.methods;
_rpc_methods.clear();
- _rpc_variables.clear();
if (_ref_base_parent.is_valid()) {
+ /// XXX TODO Should this be _rpc_methods.append_array(...)
_rpc_methods = _ref_base_parent->get_rpc_methods();
- _rpc_variables = _ref_base_parent->get_rset_properties();
}
for (int i = 0; i < methods->size(); ++i) {
Dictionary v = (*methods)[i];
@@ -322,9 +323,10 @@ Error PluginScript::reload(bool p_keep_state) {
// rpc_mode is passed as an optional field and is not part of MethodInfo
Variant var = v["rpc_mode"];
if (var != Variant()) {
- ScriptNetData nd;
+ MultiplayerAPI::RPCConfig nd;
nd.name = mi.name;
- nd.mode = MultiplayerAPI::RPCMode(int(var));
+ nd.rpc_mode = MultiplayerAPI::RPCMode(int(var));
+ // TODO Transfer Channel
if (_rpc_methods.find(nd) == -1) {
_rpc_methods.push_back(nd);
}
@@ -332,7 +334,7 @@ Error PluginScript::reload(bool p_keep_state) {
}
// Sort so we are 100% that they are always the same.
- _rpc_methods.sort_custom<SortNetData>();
+ _rpc_methods.sort_custom<MultiplayerAPI::SortRPCConfig>();
Array *signals = (Array *)&manifest.signals;
for (int i = 0; i < signals->size(); ++i) {
@@ -346,21 +348,8 @@ Error PluginScript::reload(bool p_keep_state) {
PropertyInfo pi = PropertyInfo::from_dict(v);
_properties_info[pi.name] = pi;
_properties_default_values[pi.name] = v["default_value"];
- // rset_mode is passed as an optional field and is not part of PropertyInfo
- Variant var = v["rset_mode"];
- if (var != Variant()) {
- ScriptNetData nd;
- nd.name = pi.name;
- nd.mode = MultiplayerAPI::RPCMode(int(var));
- if (_rpc_variables.find(nd) == -1) {
- _rpc_variables.push_back(nd);
- }
- }
}
- // Sort so we are 100% that they are always the same.
- _rpc_variables.sort_custom<SortNetData>();
-
#ifdef TOOLS_ENABLED
/*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
@@ -441,10 +430,10 @@ Error PluginScript::load_source_code(const String &p_path) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err, err, "Cannot open file '" + p_path + "'.");
- int len = f->get_len();
+ uint64_t len = f->get_length();
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
- int r = f->get_buffer(w, len);
+ uint64_t r = f->get_buffer(w, len);
f->close();
memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
@@ -484,76 +473,10 @@ int PluginScript::get_member_line(const StringName &p_member) const {
return -1;
}
-Vector<ScriptNetData> PluginScript::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> PluginScript::get_rpc_methods() const {
return _rpc_methods;
}
-uint16_t PluginScript::get_rpc_method_id(const StringName &p_method) const {
- ASSERT_SCRIPT_VALID_V(UINT16_MAX);
- for (int i = 0; i < _rpc_methods.size(); i++) {
- if (_rpc_methods[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName PluginScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- ASSERT_SCRIPT_VALID_V(StringName());
- if (p_rpc_method_id >= _rpc_methods.size()) {
- return StringName();
- }
- return _rpc_methods[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode PluginScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
- if (p_rpc_method_id >= _rpc_methods.size()) {
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- return _rpc_methods[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const {
- ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> PluginScript::get_rset_properties() const {
- return _rpc_variables;
-}
-
-uint16_t PluginScript::get_rset_property_id(const StringName &p_property) const {
- ASSERT_SCRIPT_VALID_V(UINT16_MAX);
- for (int i = 0; i < _rpc_variables.size(); i++) {
- if (_rpc_variables[i].name == p_property) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName PluginScript::get_rset_property(const uint16_t p_rset_property_id) const {
- ASSERT_SCRIPT_VALID_V(StringName());
- if (p_rset_property_id >= _rpc_variables.size()) {
- return StringName();
- }
- return _rpc_variables[p_rset_property_id].name;
-}
-
-MultiplayerAPI::RPCMode PluginScript::get_rset_mode_by_id(const uint16_t p_rset_property_id) const {
- ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
- if (p_rset_property_id >= _rpc_variables.size()) {
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- return _rpc_variables[p_rset_property_id].mode;
-}
-
-MultiplayerAPI::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const {
- ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
PluginScript::PluginScript() :
_script_list(this) {
}
diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h
index 1c86f2056d..97989a19d8 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.h
+++ b/modules/gdnative/pluginscript/pluginscript_script.h
@@ -61,8 +61,7 @@ private:
Map<StringName, PropertyInfo> _properties_info;
Map<StringName, MethodInfo> _signals_info;
Map<StringName, MethodInfo> _methods_info;
- Vector<ScriptNetData> _rpc_methods;
- Vector<ScriptNetData> _rpc_variables;
+ Vector<MultiplayerAPI::RPCConfig> _rpc_methods;
Set<Object *> _instances;
//exported members
@@ -137,17 +136,7 @@ public:
virtual int get_member_line(const StringName &p_member) const override;
- virtual Vector<ScriptNetData> get_rpc_methods() const override;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const override;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- virtual Vector<ScriptNetData> get_rset_properties() const override;
- virtual uint16_t get_rset_property_id(const StringName &p_property) const override;
- virtual StringName get_rset_property(const uint16_t p_rset_property_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
PluginScript();
void init(PluginScriptLanguage *language);
diff --git a/modules/gdnative/pluginscript/register_types.cpp b/modules/gdnative/pluginscript/register_types.cpp
index b94538b2f7..433544178f 100644
--- a/modules/gdnative/pluginscript/register_types.cpp
+++ b/modules/gdnative/pluginscript/register_types.cpp
@@ -31,9 +31,9 @@
#include "register_types.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
-#include "core/os/dir_access.h"
#include "core/os/os.h"
#include "scene/main/scene_tree.h"
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index d08bde9e23..cf19c0c44c 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -363,7 +363,7 @@ void unregister_gdnative_types() {
print_line(String("aabb:\t") + itos(sizeof(AABB)));
print_line(String("rid:\t") + itos(sizeof(RID)));
print_line(String("string:\t") + itos(sizeof(String)));
- print_line(String("transform:\t") + itos(sizeof(Transform)));
+ print_line(String("transform:\t") + itos(sizeof(Transform3D)));
print_line(String("transfo2D:\t") + itos(sizeof(Transform2D)));
print_line(String("variant:\t") + itos(sizeof(Variant)));
print_line(String("vector2:\t") + itos(sizeof(Vector2)));
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
index f2fb0a2fdc..8b0434c7dd 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
@@ -47,11 +47,7 @@ godot_int GDAPI godot_videodecoder_file_read(void *ptr, uint8_t *buf, int buf_si
// if file exists
if (file) {
- long bytes_read = file->get_buffer(buf, buf_size);
- // No bytes to read => EOF
- if (bytes_read == 0) {
- return 0;
- }
+ int64_t bytes_read = file->get_buffer(buf, buf_size);
return bytes_read;
}
return -1;
@@ -62,41 +58,35 @@ int64_t GDAPI godot_videodecoder_file_seek(void *ptr, int64_t pos, int whence) {
FileAccess *file = reinterpret_cast<FileAccess *>(ptr);
if (file) {
- size_t len = file->get_len();
+ int64_t len = file->get_length();
switch (whence) {
case SEEK_SET: {
- // Just for explicitness
- size_t new_pos = static_cast<size_t>(pos);
- if (new_pos > len) {
+ if (pos > len) {
return -1;
}
- file->seek(new_pos);
- pos = static_cast<int64_t>(file->get_position());
- return pos;
+ file->seek(pos);
+ return file->get_position();
} break;
case SEEK_CUR: {
// Just in case it doesn't exist
- if (pos < 0 && (size_t)-pos > file->get_position()) {
+ if (pos < 0 && -pos > (int64_t)file->get_position()) {
return -1;
}
- pos = pos + static_cast<int>(file->get_position());
- file->seek(pos);
- pos = static_cast<int64_t>(file->get_position());
- return pos;
+ file->seek(file->get_position() + pos);
+ return file->get_position();
} break;
case SEEK_END: {
// Just in case something goes wrong
- if ((size_t)-pos > len) {
+ if (-pos > len) {
return -1;
}
file->seek_end(pos);
- pos = static_cast<int64_t>(file->get_position());
- return pos;
+ return file->get_position();
} break;
default: {
// Only 4 possible options, hence default = AVSEEK_SIZE
// Asks to return the length of file
- return static_cast<int64_t>(len);
+ return len;
} break;
}
}
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.h b/modules/gdnative/videodecoder/video_stream_gdnative.h
index 140888cd4b..c605dbb433 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.h
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.h
@@ -32,7 +32,7 @@
#define VIDEO_STREAM_GDNATIVE_H
#include "../gdnative.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "scene/resources/texture.h"
#include "scene/resources/video_stream.h"
diff --git a/modules/gdnative/xr/xr_interface_gdnative.cpp b/modules/gdnative/xr/xr_interface_gdnative.cpp
index 122cb5849b..ff959affa3 100644
--- a/modules/gdnative/xr/xr_interface_gdnative.cpp
+++ b/modules/gdnative/xr/xr_interface_gdnative.cpp
@@ -70,8 +70,13 @@ void XRInterfaceGDNative::set_interface(const godot_xr_interface_gdnative *p_int
// this should only be called once, just being paranoid..
if (interface) {
cleanup();
+ interface = NULL;
}
+ // validate
+ ERR_FAIL_NULL(p_interface);
+ ERR_FAIL_COND_MSG(p_interface->version.major < 4, "This is an incompatible GDNative XR plugin.");
+
// bind to our interface
interface = p_interface;
@@ -119,14 +124,14 @@ int XRInterfaceGDNative::get_camera_feed_id() {
return (unsigned int)interface->get_camera_feed_id(data);
}
-bool XRInterfaceGDNative::is_stereo() {
- bool stereo;
+uint32_t XRInterfaceGDNative::get_view_count() {
+ uint32_t view_count;
- ERR_FAIL_COND_V(interface == nullptr, false);
+ ERR_FAIL_COND_V(interface == nullptr, 1);
- stereo = interface->is_stereo(data);
+ view_count = interface->get_view_count(data);
- return stereo;
+ return view_count;
}
bool XRInterfaceGDNative::is_initialized() const {
@@ -173,28 +178,52 @@ Size2 XRInterfaceGDNative::get_render_targetsize() {
return *vec;
}
-Transform XRInterfaceGDNative::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {
- Transform *ret;
+Transform3D XRInterfaceGDNative::get_camera_transform() {
+ Transform3D *ret;
+
+ ERR_FAIL_COND_V(interface == nullptr, Transform3D());
+
+ godot_transform3d t = interface->get_camera_transform(data);
+
+ ret = (Transform3D *)&t;
+
+ return *ret;
+}
+
+Transform3D XRInterfaceGDNative::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
+ Transform3D *ret;
- ERR_FAIL_COND_V(interface == nullptr, Transform());
+ ERR_FAIL_COND_V(interface == nullptr, Transform3D());
- godot_transform t = interface->get_transform_for_eye(data, (int)p_eye, (godot_transform *)&p_cam_transform);
+ godot_transform3d t = interface->get_transform_for_view(data, (int)p_view, (godot_transform3d *)&p_cam_transform);
- ret = (Transform *)&t;
+ ret = (Transform3D *)&t;
return *ret;
}
-CameraMatrix XRInterfaceGDNative::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+CameraMatrix XRInterfaceGDNative::get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
CameraMatrix cm;
ERR_FAIL_COND_V(interface == nullptr, CameraMatrix());
- interface->fill_projection_for_eye(data, (godot_float *)cm.matrix, (godot_int)p_eye, p_aspect, p_z_near, p_z_far);
+ interface->fill_projection_for_view(data, (godot_real_t *)cm.matrix, (godot_int)p_view, p_aspect, p_z_near, p_z_far);
return cm;
}
+Vector<BlitToScreen> XRInterfaceGDNative::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+ // possibly move this as a member variable and add a callback to populate?
+ Vector<BlitToScreen> blit_to_screen;
+
+ ERR_FAIL_COND_V(interface == nullptr, blit_to_screen);
+
+ // must implement
+ interface->commit_views(data, (godot_rid *)&p_render_target, (godot_rect2 *)&p_screen_rect);
+
+ return blit_to_screen;
+}
+
unsigned int XRInterfaceGDNative::get_external_texture_for_eye(XRInterface::Eyes p_eye) {
ERR_FAIL_COND_V(interface == nullptr, 0);
@@ -234,22 +263,22 @@ void GDAPI godot_xr_register_interface(const godot_xr_interface_gdnative *p_inte
XRServer::get_singleton()->add_interface(new_interface);
}
-godot_float GDAPI godot_xr_get_worldscale() {
+godot_real_t GDAPI godot_xr_get_worldscale() {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, 1.0);
return xr_server->get_world_scale();
}
-godot_transform GDAPI godot_xr_get_reference_frame() {
- godot_transform reference_frame;
- Transform *reference_frame_ptr = (Transform *)&reference_frame;
+godot_transform3d GDAPI godot_xr_get_reference_frame() {
+ godot_transform3d reference_frame;
+ Transform3D *reference_frame_ptr = (Transform3D *)&reference_frame;
XRServer *xr_server = XRServer::get_singleton();
if (xr_server != nullptr) {
*reference_frame_ptr = xr_server->get_reference_frame();
} else {
- memnew_placement(&reference_frame, Transform);
+ memnew_placement(&reference_frame, Transform3D);
}
return reference_frame;
@@ -356,13 +385,13 @@ void GDAPI godot_xr_remove_controller(godot_int p_controller_id) {
}
}
-void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
+void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform3d *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
if (tracker.is_valid()) {
- Transform *transform = (Transform *)p_transform;
+ Transform3D *transform = (Transform3D *)p_transform;
if (p_tracks_orientation) {
tracker->set_orientation(transform->basis);
}
@@ -388,7 +417,7 @@ void GDAPI godot_xr_set_controller_button(godot_int p_controller_id, godot_int p
}
}
-void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_float p_value, godot_bool p_can_be_negative) {
+void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real_t p_value, godot_bool p_can_be_negative) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
@@ -407,7 +436,7 @@ void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_a
}
}
-godot_float GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id) {
+godot_real_t GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, 0.0);
diff --git a/modules/gdnative/xr/xr_interface_gdnative.h b/modules/gdnative/xr/xr_interface_gdnative.h
index 84bd8fc731..42e9206c1f 100644
--- a/modules/gdnative/xr/xr_interface_gdnative.h
+++ b/modules/gdnative/xr/xr_interface_gdnative.h
@@ -72,20 +72,24 @@ public:
/** rendering and internal **/
virtual Size2 get_render_targetsize() override;
- virtual bool is_stereo() override;
- virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) override;
+ virtual uint32_t get_view_count() override;
+ virtual Transform3D get_camera_transform() override;
+ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
// we expose a Vector<float> version of this function to GDNative
Vector<float> _get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
// and a CameraMatrix version to XRServer
- virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
+ virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
- virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye) override;
- virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process() override;
virtual void notification(int p_what) override;
+
+ // deprecated
+ virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye) override;
};
#endif // XR_INTERFACE_GDNATIVE_H
diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp
index 88ef434e0f..d5e6e5e69f 100644
--- a/modules/gdnavigation/gd_navigation_server.cpp
+++ b/modules/gdnavigation/gd_navigation_server.cpp
@@ -270,7 +270,7 @@ COMMAND_2(region_set_map, RID, p_region, RID, p_map) {
}
}
-COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform) {
+COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform) {
NavRegion *region = region_owner.getornull(p_region);
ERR_FAIL_COND(region == nullptr);
diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/gdnavigation/gd_navigation_server.h
index 2f51f6431e..759d15e508 100644
--- a/modules/gdnavigation/gd_navigation_server.h
+++ b/modules/gdnavigation/gd_navigation_server.h
@@ -113,7 +113,7 @@ public:
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers);
virtual uint32_t region_get_layers(RID p_region) const;
- COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform);
+ COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform);
COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh);
virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const;
virtual int region_get_connections_count(RID p_region) const;
diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp
index 2513c62b6a..41306f0687 100644
--- a/modules/gdnavigation/nav_map.cpp
+++ b/modules/gdnavigation/nav_map.cpp
@@ -112,7 +112,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
}
}
- // Check for trival cases
+ // Check for trivial cases
if (!begin_poly || !end_poly) {
return Vector<Vector3>();
}
diff --git a/modules/gdnavigation/nav_region.cpp b/modules/gdnavigation/nav_region.cpp
index c1690b2a4b..81b15a49f5 100644
--- a/modules/gdnavigation/nav_region.cpp
+++ b/modules/gdnavigation/nav_region.cpp
@@ -52,7 +52,7 @@ uint32_t NavRegion::get_layers() const {
return layers;
}
-void NavRegion::set_transform(Transform p_transform) {
+void NavRegion::set_transform(Transform3D p_transform) {
transform = p_transform;
polygons_dirty = true;
}
diff --git a/modules/gdnavigation/nav_region.h b/modules/gdnavigation/nav_region.h
index 527b2500ac..f8b067e638 100644
--- a/modules/gdnavigation/nav_region.h
+++ b/modules/gdnavigation/nav_region.h
@@ -46,7 +46,7 @@ class NavRegion;
class NavRegion : public NavRid {
NavMap *map = nullptr;
- Transform transform;
+ Transform3D transform;
Ref<NavigationMesh> mesh;
uint32_t layers = 1;
Vector<gd::Edge::Connection> connections;
@@ -71,8 +71,8 @@ public:
void set_layers(uint32_t p_layers);
uint32_t get_layers() const;
- void set_transform(Transform transform);
- const Transform &get_transform() const {
+ void set_transform(Transform3D transform);
+ const Transform3D &get_transform() const {
return transform;
}
diff --git a/modules/gdnavigation/navigation_mesh_generator.cpp b/modules/gdnavigation/navigation_mesh_generator.cpp
index a7d4e79148..d69c9114b9 100644
--- a/modules/gdnavigation/navigation_mesh_generator.cpp
+++ b/modules/gdnavigation/navigation_mesh_generator.cpp
@@ -32,7 +32,7 @@
#include "navigation_mesh_generator.h"
-#include "core/math/quick_hull.h"
+#include "core/math/convex_hull.h"
#include "core/os/thread.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/mesh_instance_3d.h"
@@ -68,7 +68,7 @@ void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> &
p_verticies.push_back(p_vec3.z);
}
-void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) {
+void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform3D &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) {
int current_vertex_count;
for (int i = 0; i < p_mesh->get_surface_count(); i++) {
@@ -123,7 +123,7 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform
}
}
-void NavigationMeshGenerator::_add_faces(const PackedVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) {
+void NavigationMeshGenerator::_add_faces(const PackedVector3Array &p_faces, const Transform3D &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) {
int face_count = p_faces.size() / 3;
int current_vertex_count = p_verticies.size() / 3;
@@ -138,7 +138,7 @@ void NavigationMeshGenerator::_add_faces(const PackedVector3Array &p_faces, cons
}
}
-void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children) {
+void NavigationMeshGenerator::_parse_geometry(Transform3D p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children) {
if (Object::cast_to<MeshInstance3D>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) {
MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(p_node);
Ref<Mesh> mesh = mesh_instance->get_mesh();
@@ -169,7 +169,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform,
if (Object::cast_to<CollisionShape3D>(child)) {
CollisionShape3D *col_shape = Object::cast_to<CollisionShape3D>(child);
- Transform transform = p_accumulated_transform * static_body->get_transform() * col_shape->get_transform();
+ Transform3D transform = p_accumulated_transform * static_body->get_transform() * col_shape->get_transform();
Ref<Mesh> mesh;
Ref<Shape3D> s = col_shape->get_shape();
@@ -220,7 +220,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform,
Vector<Vector3> varr = Variant(convex_polygon->get_points());
Geometry3D::MeshData md;
- Error err = QuickHull::build(varr, md);
+ Error err = ConvexHullComputer::convex_hull(varr, md);
if (err == OK) {
PackedVector3Array faces;
@@ -251,7 +251,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform,
if (Object::cast_to<GridMap>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) {
GridMap *gridmap_instance = Object::cast_to<GridMap>(p_node);
Array meshes = gridmap_instance->get_meshes();
- Transform xform = gridmap_instance->get_transform();
+ Transform3D xform = gridmap_instance->get_transform();
for (int i = 0; i < meshes.size(); i += 2) {
Ref<Mesh> mesh = meshes[i + 1];
if (mesh.is_valid()) {
@@ -513,7 +513,7 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
p_node->get_tree()->get_nodes_in_group(p_nav_mesh->get_source_group_name(), &parse_nodes);
}
- Transform navmesh_xform = Object::cast_to<Node3D>(p_node)->get_transform().affine_inverse();
+ Transform3D navmesh_xform = Object::cast_to<Node3D>(p_node)->get_transform().affine_inverse();
for (const List<Node *>::Element *E = parse_nodes.front(); E; E = E->next()) {
int geometry_type = p_nav_mesh->get_parsed_geometry_type();
uint32_t collision_mask = p_nav_mesh->get_collision_mask();
diff --git a/modules/gdnavigation/navigation_mesh_generator.h b/modules/gdnavigation/navigation_mesh_generator.h
index 88ccdb1c41..847c7d097b 100644
--- a/modules/gdnavigation/navigation_mesh_generator.h
+++ b/modules/gdnavigation/navigation_mesh_generator.h
@@ -50,9 +50,9 @@ protected:
static void _bind_methods();
static void _add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies);
- static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
- static void _add_faces(const PackedVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
- static void _parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children);
+ static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform3D &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
+ static void _add_faces(const PackedVector3Array &p_faces, const Transform3D &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
+ static void _parse_geometry(Transform3D p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children);
static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh);
static void _build_recast_navigation_mesh(
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 9e974b6fdc..58620f2b3e 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -240,10 +240,10 @@
</method>
</methods>
<constants>
- <constant name="PI" value="3.141593">
+ <constant name="PI" value="3.14159265358979">
Constant that represents how many times the diameter of a circle fits around its perimeter. This is equivalent to [code]TAU / 2[/code].
</constant>
- <constant name="TAU" value="6.283185">
+ <constant name="TAU" value="6.28318530717959">
The circle constant, the circumference of the unit circle in radians.
</constant>
<constant name="INF" value="inf">
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index ca646dff15..b867b03903 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -64,6 +64,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
bool in_function_args = false;
bool in_member_variable = false;
bool in_node_path = false;
+ bool in_annotation = false;
bool is_hex_notation = false;
bool is_bin_notation = false;
bool expect_type = false;
@@ -357,9 +358,18 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
in_node_path = false;
}
+ if (!in_annotation && in_region == -1 && str[j] == '@') {
+ in_annotation = true;
+ } else if (in_region != -1 || is_a_symbol) {
+ in_annotation = false;
+ }
+
if (in_node_path) {
next_type = NODE_PATH;
color = node_path_color;
+ } else if (in_annotation) {
+ next_type = ANNOTATION;
+ color = annotation_color;
} else if (in_keyword) {
next_type = KEYWORD;
color = keyword_color;
@@ -546,19 +556,22 @@ void GDScriptSyntaxHighlighter::_update_cache() {
}
const String text_edit_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
- const bool default_theme = text_edit_color_theme == "Default";
+ const bool godot_2_theme = text_edit_color_theme == "Godot 2";
- if (default_theme || EditorSettings::get_singleton()->is_dark_theme()) {
+ if (godot_2_theme || EditorSettings::get_singleton()->is_dark_theme()) {
function_definition_color = Color(0.4, 0.9, 1.0);
node_path_color = Color(0.39, 0.76, 0.35);
+ annotation_color = Color(1.0, 0.7, 0.45);
} else {
function_definition_color = Color(0.0, 0.65, 0.73);
node_path_color = Color(0.32, 0.55, 0.29);
+ annotation_color = Color(0.8, 0.5, 0.25);
}
EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color);
EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color);
- if (text_edit_color_theme == "Adaptive" || default_theme) {
+ EDITOR_DEF("text_editor/highlighting/gdscript/annotation_color", annotation_color);
+ if (text_edit_color_theme == "Default" || godot_2_theme) {
EditorSettings::get_singleton()->set_initial_value(
"text_editor/highlighting/gdscript/function_definition_color",
function_definition_color,
@@ -567,10 +580,15 @@ void GDScriptSyntaxHighlighter::_update_cache() {
"text_editor/highlighting/gdscript/node_path_color",
node_path_color,
true);
+ EditorSettings::get_singleton()->set_initial_value(
+ "text_editor/highlighting/gdscript/annotation_color",
+ annotation_color,
+ true);
}
function_definition_color = EDITOR_GET("text_editor/highlighting/gdscript/function_definition_color");
node_path_color = EDITOR_GET("text_editor/highlighting/gdscript/node_path_color");
+ annotation_color = EDITOR_GET("text_editor/highlighting/gdscript/annotation_color");
type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
}
diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h
index 1b57cb1923..d07c182aa6 100644
--- a/modules/gdscript/editor/gdscript_highlighter.h
+++ b/modules/gdscript/editor/gdscript_highlighter.h
@@ -54,6 +54,7 @@ private:
NONE,
REGION,
NODE_PATH,
+ ANNOTATION,
SYMBOL,
NUMBER,
FUNCTION,
@@ -72,6 +73,7 @@ private:
Color number_color;
Color member_color;
Color node_path_color;
+ Color annotation_color;
Color type_color;
void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false);
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 859c1acde9..1567576009 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -36,8 +36,8 @@
#include "core/config/project_settings.h"
#include "core/core_constants.h"
#include "core/core_string_names.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_encrypted.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "gdscript_analyzer.h"
#include "gdscript_cache.h"
@@ -75,9 +75,9 @@ Variant GDScriptNativeClass::_new() {
Object *o = instance();
ERR_FAIL_COND_V_MSG(!o, Variant(), "Class type: '" + String(name) + "' is not instantiable.");
- Reference *ref = Object::cast_to<Reference>(o);
- if (ref) {
- return REF(ref);
+ RefCounted *rc = Object::cast_to<RefCounted>(o);
+ if (rc) {
+ return REF(rc);
} else {
return o;
}
@@ -98,11 +98,11 @@ void GDScript::_super_implicit_constructor(GDScript *p_script, GDScriptInstance
p_script->implicit_initializer->call(p_instance, nullptr, 0, r_error);
}
-GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error) {
+GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error) {
/* STEP 1, CREATE */
GDScriptInstance *instance = memnew(GDScriptInstance);
- instance->base_ref = p_isref;
+ instance->base_ref_counted = p_is_ref_counted;
instance->members.resize(member_indices.size());
instance->script = Ref<GDScript>(this);
instance->owner = p_owner;
@@ -172,11 +172,11 @@ Variant GDScript::_new(const Variant **p_args, int p_argcount, Callable::CallErr
if (_baseptr->native.ptr()) {
owner = _baseptr->native->instance();
} else {
- owner = memnew(Reference); //by default, no base means use reference
+ owner = memnew(RefCounted); //by default, no base means use reference
}
ERR_FAIL_COND_V_MSG(!owner, Variant(), "Can't inherit from a virtual class.");
- Reference *r = Object::cast_to<Reference>(owner);
+ RefCounted *r = Object::cast_to<RefCounted>(owner);
if (r) {
ref = REF(r);
}
@@ -353,14 +353,14 @@ ScriptInstance *GDScript::instance_create(Object *p_this) {
}
Callable::CallError unchecked_error;
- return _create_instance(nullptr, 0, p_this, Object::cast_to<Reference>(p_this) != nullptr, unchecked_error);
+ return _create_instance(nullptr, 0, p_this, Object::cast_to<RefCounted>(p_this) != nullptr, unchecked_error);
}
PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this) {
#ifdef TOOLS_ENABLED
PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(GDScriptLanguage::get_singleton(), Ref<Script>(this), p_this));
placeholders.insert(si);
- _update_exports();
+ _update_exports(nullptr, false, si);
return si;
#else
return nullptr;
@@ -481,7 +481,7 @@ void GDScript::_update_doc() {
methods[i].return_val.class_name = _get_gdscript_reference_class_name(Object::cast_to<GDScript>(return_type.script_type));
}
- // Change class name if argumetn is script reference.
+ // Change class name if argument is script reference.
for (int j = 0; j < fn->get_argument_count(); j++) {
GDScriptDataType arg_type = fn->get_argument_type(j);
if (arg_type.kind == GDScriptDataType::GDSCRIPT) {
@@ -584,7 +584,7 @@ void GDScript::_update_doc() {
}
#endif
-bool GDScript::_update_exports(bool *r_err, bool p_recursive_call) {
+bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderScriptInstance *p_instance_to_update) {
#ifdef TOOLS_ENABLED
static Vector<GDScript *> base_caches;
@@ -721,15 +721,19 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call) {
}
}
- if (placeholders.size()) { //hm :(
+ if ((changed || p_instance_to_update) && placeholders.size()) { //hm :(
// update placeholders if any
Map<StringName, Variant> values;
List<PropertyInfo> propnames;
_update_exports_values(values, propnames);
- for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
- E->get()->update(propnames, values);
+ if (changed) {
+ for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
+ E->get()->update(propnames, values);
+ }
+ } else {
+ p_instance_to_update->update(propnames, values);
}
}
@@ -897,68 +901,10 @@ void GDScript::get_members(Set<StringName> *p_members) {
}
}
-Vector<ScriptNetData> GDScript::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> GDScript::get_rpc_methods() const {
return rpc_functions;
}
-uint16_t GDScript::get_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < rpc_functions.size(); i++) {
- if (rpc_functions[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName GDScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- if (p_rpc_method_id >= rpc_functions.size()) {
- return StringName();
- }
- return rpc_functions[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode GDScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- if (p_rpc_method_id >= rpc_functions.size()) {
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- return rpc_functions[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode GDScript::get_rpc_mode(const StringName &p_method) const {
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> GDScript::get_rset_properties() const {
- return rpc_variables;
-}
-
-uint16_t GDScript::get_rset_property_id(const StringName &p_variable) const {
- for (int i = 0; i < rpc_variables.size(); i++) {
- if (rpc_variables[i].name == p_variable) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName GDScript::get_rset_property(const uint16_t p_rset_member_id) const {
- if (p_rset_member_id >= rpc_variables.size()) {
- return StringName();
- }
- return rpc_variables[p_rset_member_id].name;
-}
-
-MultiplayerAPI::RPCMode GDScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- if (p_rset_member_id >= rpc_variables.size()) {
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- return rpc_variables[p_rset_member_id].mode;
-}
-
-MultiplayerAPI::RPCMode GDScript::get_rset_mode(const StringName &p_variable) const {
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
GDScript *top = this;
while (top) {
@@ -1045,10 +991,10 @@ Error GDScript::load_source_code(const String &p_path) {
ERR_FAIL_COND_V(err, err);
}
- int len = f->get_len();
+ uint64_t len = f->get_length();
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
- int r = f->get_buffer(w, len);
+ uint64_t r = f->get_buffer(w, len);
f->close();
memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
@@ -1210,10 +1156,8 @@ void GDScript::_save_orphaned_subclasses() {
void GDScript::_init_rpc_methods_properties() {
// Copy the base rpc methods so we don't mask their IDs.
rpc_functions.clear();
- rpc_variables.clear();
if (base.is_valid()) {
rpc_functions = base->rpc_functions;
- rpc_variables = base->rpc_variables;
}
GDScript *cscript = this;
@@ -1222,25 +1166,17 @@ void GDScript::_init_rpc_methods_properties() {
// RPC Methods
for (Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.front(); E; E = E->next()) {
if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
- ScriptNetData nd;
+ MultiplayerAPI::RPCConfig nd;
nd.name = E->key();
- nd.mode = E->get()->get_rpc_mode();
+ nd.rpc_mode = E->get()->get_rpc_mode();
+ // TODO
+ nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ nd.channel = 0;
if (-1 == rpc_functions.find(nd)) {
rpc_functions.push_back(nd);
}
}
}
- // RSet
- for (Map<StringName, MemberInfo>::Element *E = cscript->member_indices.front(); E; E = E->next()) {
- if (E->get().rpc_mode != MultiplayerAPI::RPC_MODE_DISABLED) {
- ScriptNetData nd;
- nd.name = E->key();
- nd.mode = E->get().rpc_mode;
- if (-1 == rpc_variables.find(nd)) {
- rpc_variables.push_back(nd);
- }
- }
- }
if (cscript != this) {
sub_E = sub_E->next();
@@ -1254,8 +1190,7 @@ void GDScript::_init_rpc_methods_properties() {
}
// Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<SortNetData>();
- rpc_variables.sort_custom<SortNetData>();
+ rpc_functions.sort_custom<MultiplayerAPI::SortRPCConfig>();
}
GDScript::~GDScript() {
@@ -1611,46 +1546,10 @@ ScriptLanguage *GDScriptInstance::get_language() {
return GDScriptLanguage::get_singleton();
}
-Vector<ScriptNetData> GDScriptInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> GDScriptInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t GDScriptInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName GDScriptInstance::get_rpc_method(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_method(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_mode_by_id(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> GDScriptInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t GDScriptInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName GDScriptInstance::get_rset_property(const uint16_t p_rset_member_id) const {
- return script->get_rset_property(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- return script->get_rset_mode_by_id(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
void GDScriptInstance::reload_members() {
#ifdef DEBUG_ENABLED
@@ -1681,7 +1580,7 @@ void GDScriptInstance::reload_members() {
GDScriptInstance::GDScriptInstance() {
owner = nullptr;
- base_ref = false;
+ base_ref_counted = false;
}
GDScriptInstance::~GDScriptInstance() {
@@ -2169,7 +2068,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
if (err == OK) {
const GDScriptParser::ClassNode *c = parser.get_tree();
if (r_icon_path) {
- if (c->icon_path.is_empty() || c->icon_path.is_abs_path()) {
+ if (c->icon_path.is_empty() || c->icon_path.is_absolute_path()) {
*r_icon_path = c->icon_path;
} else if (c->icon_path.is_rel_path()) {
*r_icon_path = p_path.get_base_dir().plus_file(c->icon_path).simplify_path();
@@ -2237,7 +2136,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
break;
}
} else {
- *r_base_type = "Reference";
+ *r_base_type = "RefCounted";
subclass = nullptr;
}
}
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 6df66e876d..602553bb1a 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -39,8 +39,8 @@
#include "core/object/script_language.h"
#include "gdscript_function.h"
-class GDScriptNativeClass : public Reference {
- GDCLASS(GDScriptNativeClass, Reference);
+class GDScriptNativeClass : public RefCounted {
+ GDCLASS(GDScriptNativeClass, RefCounted);
StringName name;
@@ -86,8 +86,7 @@ class GDScript : public Script {
Map<StringName, MemberInfo> member_indices; //members are just indices to the instanced script.
Map<StringName, Ref<GDScript>> subclasses;
Map<StringName, Vector<StringName>> _signals;
- Vector<ScriptNetData> rpc_functions;
- Vector<ScriptNetData> rpc_variables;
+ Vector<MultiplayerAPI::RPCConfig> rpc_functions;
#ifdef TOOLS_ENABLED
@@ -133,7 +132,7 @@ class GDScript : public Script {
SelfList<GDScriptFunctionState>::List pending_func_states;
void _super_implicit_constructor(GDScript *p_script, GDScriptInstance *p_instance, Callable::CallError &r_error);
- GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error);
+ GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);
void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path);
@@ -149,7 +148,7 @@ class GDScript : public Script {
#endif
- bool _update_exports(bool *r_err = nullptr, bool p_recursive_call = false);
+ bool _update_exports(bool *r_err = nullptr, bool p_recursive_call = false, PlaceHolderScriptInstance *p_instance_to_update = nullptr);
void _save_orphaned_subclasses();
void _init_rpc_methods_properties();
@@ -158,7 +157,7 @@ class GDScript : public Script {
void _get_script_method_list(List<MethodInfo> *r_list, bool p_include_base) const;
void _get_script_signal_list(List<MethodInfo> *r_list, bool p_include_base) const;
- // This method will map the class name from "Reference" to "MyClass.InnerClass".
+ // This method will map the class name from "RefCounted" to "MyClass.InnerClass".
static String _get_gdscript_reference_class_name(const GDScript *p_gdscript);
protected:
@@ -247,17 +246,7 @@ public:
virtual void get_constants(Map<StringName, Variant> *p_constants) override;
virtual void get_members(Set<StringName> *p_members) override;
- virtual Vector<ScriptNetData> get_rpc_methods() const override;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const override;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- virtual Vector<ScriptNetData> get_rset_properties() const override;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const override;
- virtual StringName get_rset_property(const uint16_t p_variable_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
#ifdef TOOLS_ENABLED
virtual bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -281,7 +270,7 @@ class GDScriptInstance : public ScriptInstance {
Map<StringName, int> member_indices_cache; //used only for hot script reloading
#endif
Vector<Variant> members;
- bool base_ref;
+ bool base_ref_counted;
SelfList<GDScriptFunctionState>::List pending_func_states;
@@ -310,17 +299,7 @@ public:
void reload_members();
- virtual Vector<ScriptNetData> get_rpc_methods() const;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
-
- virtual Vector<ScriptNetData> get_rset_properties() const;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
- virtual StringName get_rset_property(const uint16_t p_variable_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const;
GDScriptInstance();
~GDScriptInstance();
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 17ae52f3ab..c3edc813d2 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -31,10 +31,10 @@
#include "gdscript_analyzer.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/object/class_db.h"
#include "core/object/script_language.h"
-#include "core/os/file_access.h"
#include "core/templates/hash_map.h"
#include "gdscript.h"
#include "gdscript_utility_functions.h"
@@ -163,7 +163,7 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
if (!p_class->extends_used) {
result.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
result.kind = GDScriptParser::DataType::NATIVE;
- result.native_type = "Reference";
+ result.native_type = "RefCounted";
} else {
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
@@ -543,6 +543,7 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
} else {
// TODO: Add warning.
mark_node_unsafe(member.variable->initializer);
+ member.variable->use_conversion_assign = true;
}
} else if (datatype.builtin_type == Variant::INT && member.variable->initializer->get_datatype().builtin_type == Variant::FLOAT) {
#ifdef DEBUG_ENABLED
@@ -552,6 +553,7 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
if (member.variable->initializer->get_datatype().is_variant()) {
// TODO: Warn unsafe assign.
mark_node_unsafe(member.variable->initializer);
+ member.variable->use_conversion_assign = true;
}
}
} else if (member.variable->infer_datatype) {
@@ -1145,6 +1147,7 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
} else {
// TODO: Add warning.
mark_node_unsafe(p_variable->initializer);
+ p_variable->use_conversion_assign = true;
}
#ifdef DEBUG_ENABLED
} else if (type.builtin_type == Variant::INT && p_variable->initializer->get_datatype().builtin_type == Variant::FLOAT) {
@@ -1154,6 +1157,7 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
if (p_variable->initializer->get_datatype().is_variant()) {
// TODO: Warn unsafe assign.
mark_node_unsafe(p_variable->initializer);
+ p_variable->use_conversion_assign = true;
}
}
} else if (p_variable->infer_datatype) {
@@ -1608,10 +1612,12 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
} else {
// TODO: Add warning.
mark_node_unsafe(p_assignment);
+ p_assignment->use_conversion_assign = true;
}
} else {
// TODO: Warning in this case.
mark_node_unsafe(p_assignment);
+ p_assignment->use_conversion_assign = true;
}
}
} else {
@@ -1621,6 +1627,9 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
if (assignee_type.has_no_type() || assigned_value_type.is_variant()) {
mark_node_unsafe(p_assignment);
+ if (assignee_type.is_hard_type()) {
+ p_assignment->use_conversion_assign = true;
+ }
}
if (p_assignment->assignee->type == GDScriptParser::Node::IDENTIFIER) {
@@ -2059,9 +2068,11 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
if (p_call->is_super) {
base_type = parser->current_class->base_type;
+ base_type.is_meta_type = false;
is_self = true;
} else if (callee_type == GDScriptParser::Node::IDENTIFIER) {
base_type = parser->current_class->get_datatype();
+ base_type.is_meta_type = false;
is_self = true;
} else if (callee_type == GDScriptParser::Node::SUBSCRIPT) {
GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(p_call->callee);
@@ -2078,9 +2089,23 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
mark_node_unsafe(p_call);
return;
}
- reduce_expression(subscript->base);
+ if (subscript->attribute == nullptr) {
+ // Invalid call. Error already sent in parser.
+ p_call->set_datatype(call_type);
+ mark_node_unsafe(p_call);
+ return;
+ }
- base_type = subscript->base->get_datatype();
+ GDScriptParser::IdentifierNode *base_id = nullptr;
+ if (subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
+ base_id = static_cast<GDScriptParser::IdentifierNode *>(subscript->base);
+ }
+ if (base_id && GDScriptParser::get_builtin_type(base_id->name) < Variant::VARIANT_MAX) {
+ base_type = make_builtin_meta_type(GDScriptParser::get_builtin_type(base_id->name));
+ } else {
+ reduce_expression(subscript->base);
+ base_type = subscript->base->get_datatype();
+ }
} else {
// Invalid call. Error already sent in parser.
// TODO: Could check if Callable here too.
@@ -2800,7 +2825,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
case Variant::RECT2:
case Variant::RECT2I:
case Variant::PLANE:
- case Variant::QUAT:
+ case Variant::QUATERNION:
case Variant::AABB:
case Variant::OBJECT:
error = index_type.builtin_type != Variant::STRING;
@@ -2811,8 +2836,8 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
case Variant::VECTOR2I:
case Variant::VECTOR3:
case Variant::VECTOR3I:
- case Variant::TRANSFORM:
case Variant::TRANSFORM2D:
+ case Variant::TRANSFORM3D:
error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT &&
index_type.builtin_type != Variant::STRING;
break;
@@ -2879,7 +2904,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
case Variant::PACKED_FLOAT64_ARRAY:
case Variant::VECTOR2:
case Variant::VECTOR3:
- case Variant::QUAT:
+ case Variant::QUATERNION:
result_type.builtin_type = Variant::FLOAT;
break;
// Return Color.
@@ -2908,7 +2933,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
result_type.builtin_type = Variant::VECTOR3;
break;
// Depends on the index.
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
case Variant::PLANE:
case Variant::COLOR:
case Variant::DICTIONARY:
diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h
index aabf407c76..8cd3fcf837 100644
--- a/modules/gdscript/gdscript_analyzer.h
+++ b/modules/gdscript/gdscript_analyzer.h
@@ -32,7 +32,7 @@
#define GDSCRIPT_ANALYZER_H
#include "core/object/object.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/templates/set.h"
#include "gdscript_cache.h"
#include "gdscript_parser.h"
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 0da99ccee3..6998cc5bb7 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -85,10 +85,10 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type
case Variant::VECTOR3I:
case Variant::TRANSFORM2D:
case Variant::PLANE:
- case Variant::QUAT:
+ case Variant::QUATERNION:
case Variant::AABB:
case Variant::BASIS:
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
case Variant::COLOR:
case Variant::STRING_NAME:
case Variant::NODE_PATH:
@@ -129,12 +129,6 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type
int idx = temporaries.size();
pool.push_back(idx);
temporaries.push_back(new_temp);
-
- // First time using this, so adjust to the proper type.
- if (temp_type != Variant::NIL) {
- Address addr(Address::TEMPORARY, idx, p_type);
- write_type_adjust(addr, temp_type);
- }
}
int slot = pool.front()->get();
pool.pop_front();
@@ -189,8 +183,12 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
append(GDScriptFunction::OPCODE_END, 0);
for (int i = 0; i < temporaries.size(); i++) {
+ int stack_index = i + max_locals + RESERVED_STACK;
for (int j = 0; j < temporaries[i].bytecode_indices.size(); j++) {
- opcodes.write[temporaries[i].bytecode_indices[j]] = (i + max_locals + RESERVED_STACK) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ opcodes.write[temporaries[i].bytecode_indices[j]] = stack_index | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ }
+ if (temporaries[i].type != Variant::NIL) {
+ function->temporary_slots[stack_index] = temporaries[i].type;
}
}
@@ -460,8 +458,8 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia
case Variant::PLANE:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PLANE, 1);
break;
- case Variant::QUAT:
- append(GDScriptFunction::OPCODE_TYPE_ADJUST_QUAT, 1);
+ case Variant::QUATERNION:
+ append(GDScriptFunction::OPCODE_TYPE_ADJUST_QUATERNION, 1);
break;
case Variant::AABB:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_AABB, 1);
@@ -469,7 +467,7 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia
case Variant::BASIS:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_BASIS, 1);
break;
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM, 1);
break;
case Variant::COLOR:
@@ -781,63 +779,43 @@ void GDScriptByteCodeGenerator::write_get_member(const Address &p_target, const
append(p_name);
}
-void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) {
- if (p_target.type.has_type && !p_source.type.has_type) {
- // Typed assignment.
- switch (p_target.type.kind) {
- case GDScriptDataType::BUILTIN: {
- if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) {
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY, 2);
- append(p_target);
- append(p_source);
- } else {
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2);
- append(p_target);
- append(p_source);
- append(p_target.type.builtin_type);
- }
- } break;
- case GDScriptDataType::NATIVE: {
- int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type];
- Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
- class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE, 3);
- append(p_target);
- append(p_source);
- append(class_idx);
- } break;
- case GDScriptDataType::SCRIPT:
- case GDScriptDataType::GDSCRIPT: {
- Variant script = p_target.type.script_type;
- int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
-
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT, 3);
+void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_target, const Address &p_source) {
+ switch (p_target.type.kind) {
+ case GDScriptDataType::BUILTIN: {
+ if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) {
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY, 2);
append(p_target);
append(p_source);
- append(idx);
- } break;
- default: {
- ERR_PRINT("Compiler bug: unresolved assign.");
-
- // Shouldn't get here, but fail-safe to a regular assignment
- append(GDScriptFunction::OPCODE_ASSIGN, 2);
+ } else {
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2);
append(p_target);
append(p_source);
+ append(p_target.type.builtin_type);
}
- }
- } else {
- if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) {
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY, 2);
+ } break;
+ case GDScriptDataType::NATIVE: {
+ int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type];
+ Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
+ class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE, 3);
append(p_target);
append(p_source);
- } else if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) {
- // Need conversion..
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2);
+ append(class_idx);
+ } break;
+ case GDScriptDataType::SCRIPT:
+ case GDScriptDataType::GDSCRIPT: {
+ Variant script = p_target.type.script_type;
+ int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
+
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT, 3);
append(p_target);
append(p_source);
- append(p_target.type.builtin_type);
- } else {
- // Either untyped assignment or already type-checked by the parser
+ append(idx);
+ } break;
+ default: {
+ ERR_PRINT("Compiler bug: unresolved assign.");
+
+ // Shouldn't get here, but fail-safe to a regular assignment
append(GDScriptFunction::OPCODE_ASSIGN, 2);
append(p_target);
append(p_source);
@@ -845,6 +823,24 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
}
}
+void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) {
+ if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) {
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY, 2);
+ append(p_target);
+ append(p_source);
+ } else if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) {
+ // Need conversion.
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2);
+ append(p_target);
+ append(p_source);
+ append(p_target.type.builtin_type);
+ } else {
+ append(GDScriptFunction::OPCODE_ASSIGN, 2);
+ append(p_target);
+ append(p_source);
+ }
+}
+
void GDScriptByteCodeGenerator::write_assign_true(const Address &p_target) {
append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1);
append(p_target);
@@ -1017,6 +1013,56 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target,
append(Variant::get_validated_builtin_method(p_type, p_method));
}
+void GDScriptByteCodeGenerator::write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) {
+ bool is_validated = false;
+
+ // Check if all types are correct.
+ if (Variant::is_builtin_method_vararg(p_type, p_method)) {
+ is_validated = true; // Vararg works fine with any argument, since they can be any type.
+ } else if (p_arguments.size() == Variant::get_builtin_method_argument_count(p_type, p_method)) {
+ bool all_types_exact = true;
+ for (int i = 0; i < p_arguments.size(); i++) {
+ if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_builtin_method_argument_type(p_type, p_method, i))) {
+ all_types_exact = false;
+ break;
+ }
+ }
+
+ is_validated = all_types_exact;
+ }
+
+ if (!is_validated) {
+ // Perform regular call.
+ append(GDScriptFunction::OPCODE_CALL_BUILTIN_STATIC, p_arguments.size() + 1);
+ for (int i = 0; i < p_arguments.size(); i++) {
+ append(p_arguments[i]);
+ }
+ append(p_target);
+ append(p_type);
+ append(p_method);
+ append(p_arguments.size());
+ return;
+ }
+
+ if (p_target.mode == Address::TEMPORARY) {
+ Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
+ Variant::Type temp_type = temporaries[p_target.address].type;
+ if (result_type != temp_type) {
+ write_type_adjust(p_target, result_type);
+ }
+ }
+
+ append(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size());
+
+ for (int i = 0; i < p_arguments.size(); i++) {
+ append(p_arguments[i]);
+ }
+ append(Address()); // No base since it's static.
+ append(p_target);
+ append(p_arguments.size());
+ append(Variant::get_validated_builtin_method(p_type, p_method));
+}
+
void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) {
append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL_METHOD_BIND : GDScriptFunction::OPCODE_CALL_METHOD_BIND_RET, 2 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
@@ -1054,12 +1100,12 @@ void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, cons
CASE_TYPE(PLANE);
CASE_TYPE(AABB);
CASE_TYPE(BASIS);
- CASE_TYPE(TRANSFORM);
+ CASE_TYPE(TRANSFORM3D);
CASE_TYPE(COLOR);
CASE_TYPE(STRING_NAME);
CASE_TYPE(NODE_PATH);
CASE_TYPE(RID);
- CASE_TYPE(QUAT);
+ CASE_TYPE(QUATERNION);
CASE_TYPE(OBJECT);
CASE_TYPE(CALLABLE);
CASE_TYPE(SIGNAL);
diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h
index c060476f39..b1f3cd5fb3 100644
--- a/modules/gdscript/gdscript_byte_codegen.h
+++ b/modules/gdscript/gdscript_byte_codegen.h
@@ -450,6 +450,7 @@ public:
virtual void write_set_member(const Address &p_value, const StringName &p_name) override;
virtual void write_get_member(const Address &p_target, const StringName &p_name) override;
virtual void write_assign(const Address &p_target, const Address &p_source) override;
+ virtual void write_assign_with_conversion(const Address &p_target, const Address &p_source) override;
virtual void write_assign_true(const Address &p_target) override;
virtual void write_assign_false(const Address &p_target) override;
virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src) override;
@@ -461,6 +462,7 @@ public:
virtual void write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) override;
virtual void write_call_gdscript_utility(const Address &p_target, GDScriptUtilityFunctions::FunctionPtr p_function, const Vector<Address> &p_arguments) override;
virtual void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) override;
+ virtual void write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) override;
virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp
index 113d36be98..a3b1fb93f9 100644
--- a/modules/gdscript/gdscript_cache.cpp
+++ b/modules/gdscript/gdscript_cache.cpp
@@ -30,7 +30,7 @@
#include "gdscript_cache.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/templates/vector.h"
#include "gdscript.h"
#include "gdscript_analyzer.h"
@@ -153,9 +153,9 @@ String GDScriptCache::get_source_code(const String &p_path) {
ERR_FAIL_COND_V(err, "");
}
- int len = f->get_len();
+ uint64_t len = f->get_length();
source_file.resize(len + 1);
- int r = f->get_buffer(source_file.ptrw(), len);
+ uint64_t r = f->get_buffer(source_file.ptrw(), len);
f->close();
ERR_FAIL_COND_V(r != len, "");
source_file.write[len] = 0;
diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h
index d1d2a2abbf..943638d29f 100644
--- a/modules/gdscript/gdscript_cache.h
+++ b/modules/gdscript/gdscript_cache.h
@@ -31,7 +31,7 @@
#ifndef GDSCRIPT_CACHE_H
#define GDSCRIPT_CACHE_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/mutex.h"
#include "core/templates/hash_map.h"
#include "core/templates/set.h"
@@ -40,7 +40,7 @@
class GDScriptAnalyzer;
class GDScriptParser;
-class GDScriptParserRef : public Reference {
+class GDScriptParserRef : public RefCounted {
public:
enum Status {
EMPTY,
diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h
index ae9a8ede5e..cac6544f03 100644
--- a/modules/gdscript/gdscript_codegen.h
+++ b/modules/gdscript/gdscript_codegen.h
@@ -111,6 +111,7 @@ public:
virtual void write_set_member(const Address &p_value, const StringName &p_name) = 0;
virtual void write_get_member(const Address &p_target, const StringName &p_name) = 0;
virtual void write_assign(const Address &p_target, const Address &p_source) = 0;
+ virtual void write_assign_with_conversion(const Address &p_target, const Address &p_source) = 0;
virtual void write_assign_true(const Address &p_target) = 0;
virtual void write_assign_false(const Address &p_target) = 0;
virtual void write_assign_default_parameter(const Address &dst, const Address &src) = 0;
@@ -122,6 +123,7 @@ public:
virtual void write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) = 0;
virtual void write_call_gdscript_utility(const Address &p_target, GDScriptUtilityFunctions::FunctionPtr p_function, const Vector<Address> &p_arguments) = 0;
virtual void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) = 0;
+ virtual void write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) = 0;
virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 37ce8ae2cb..6d6b9e15af 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -537,39 +537,44 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(call->callee);
if (subscript->is_attribute) {
- GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
- if (r_error) {
- return GDScriptCodeGenerator::Address();
- }
- if (within_await) {
- gen->write_call_async(result, base, call->function_name, arguments);
- } else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) {
- // Native method, use faster path.
- StringName class_name;
- if (base.type.kind == GDScriptDataType::NATIVE) {
- class_name = base.type.native_type;
- } else {
- class_name = base.type.native_type == StringName() ? base.type.script_type->get_instance_base_type() : base.type.native_type;
+ // May be static built-in method call.
+ if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) < Variant::VARIANT_MAX) {
+ gen->write_call_builtin_type_static(result, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name), subscript->attribute->name, arguments);
+ } else {
+ GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
+ if (r_error) {
+ return GDScriptCodeGenerator::Address();
}
- if (ClassDB::class_exists(class_name) && ClassDB::has_method(class_name, call->function_name)) {
- MethodBind *method = ClassDB::get_method(class_name, call->function_name);
- if (_have_exact_arguments(method, arguments)) {
- // Exact arguments, use ptrcall.
- gen->write_call_ptrcall(result, base, method, arguments);
+ if (within_await) {
+ gen->write_call_async(result, base, call->function_name, arguments);
+ } else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) {
+ // Native method, use faster path.
+ StringName class_name;
+ if (base.type.kind == GDScriptDataType::NATIVE) {
+ class_name = base.type.native_type;
} else {
- // Not exact arguments, but still can use method bind call.
- gen->write_call_method_bind(result, base, method, arguments);
+ class_name = base.type.native_type == StringName() ? base.type.script_type->get_instance_base_type() : base.type.native_type;
}
+ if (ClassDB::class_exists(class_name) && ClassDB::has_method(class_name, call->function_name)) {
+ MethodBind *method = ClassDB::get_method(class_name, call->function_name);
+ if (_have_exact_arguments(method, arguments)) {
+ // Exact arguments, use ptrcall.
+ gen->write_call_ptrcall(result, base, method, arguments);
+ } else {
+ // Not exact arguments, but still can use method bind call.
+ gen->write_call_method_bind(result, base, method, arguments);
+ }
+ } else {
+ gen->write_call(result, base, call->function_name, arguments);
+ }
+ } else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) {
+ gen->write_call_builtin_type(result, base, base.type.builtin_type, call->function_name, arguments);
} else {
gen->write_call(result, base, call->function_name, arguments);
}
- } else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) {
- gen->write_call_builtin_type(result, base, base.type.builtin_type, call->function_name, arguments);
- } else {
- gen->write_call(result, base, call->function_name, arguments);
- }
- if (base.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
- gen->pop_temporary();
+ if (base.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+ gen->pop_temporary();
+ }
}
} else {
_set_error("Cannot call something that isn't a function.", call->callee);
@@ -966,6 +971,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
} else {
gen->write_set(prev_base, key, assigned);
}
+ if (key.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+ gen->pop_temporary();
+ }
if (assigned.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
gen->pop_temporary();
}
@@ -1076,7 +1084,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
gen->write_call(GDScriptCodeGenerator::Address(), GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), setter_function, args);
} else {
// Just assign.
- gen->write_assign(target, op_result);
+ if (assignment->use_conversion_assign) {
+ gen->write_assign_with_conversion(target, op_result);
+ } else {
+ gen->write_assign(target, op_result);
+ }
}
if (op_result.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
@@ -1784,7 +1796,11 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
if (error) {
return error;
}
- gen->write_assign(local, src_address);
+ if (lv->use_conversion_assign) {
+ gen->write_assign_with_conversion(local, src_address);
+ } else {
+ gen->write_assign(local, src_address);
+ }
if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
@@ -1922,7 +1938,11 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
return nullptr;
}
- codegen.generator->write_assign(dst_address, src_address);
+ if (field->use_conversion_assign) {
+ codegen.generator->write_assign_with_conversion(dst_address, src_address);
+ } else {
+ codegen.generator->write_assign(dst_address, src_address);
+ }
if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
@@ -2203,7 +2223,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
if (err) {
return err;
}
- if (base.is_null() && !base->is_valid()) {
+ if (base.is_null() || !base->is_valid()) {
return ERR_COMPILATION_FAILED;
}
}
@@ -2262,9 +2282,10 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
}
prop_info.hint = export_info.hint;
prop_info.hint_string = export_info.hint_string;
- prop_info.usage = export_info.usage;
+ prop_info.usage = export_info.usage | PROPERTY_USAGE_SCRIPT_VARIABLE;
+ } else {
+ prop_info.usage = PROPERTY_USAGE_SCRIPT_VARIABLE;
}
- prop_info.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
#ifdef TOOLS_ENABLED
p_script->doc_variables[name] = variable->doc_description;
#endif
@@ -2491,7 +2512,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
p_script->placeholders.erase(psi); //remove placeholder
GDScriptInstance *instance = memnew(GDScriptInstance);
- instance->base_ref = Object::cast_to<Reference>(E->get());
+ instance->base_ref_counted = Object::cast_to<RefCounted>(E->get());
instance->members.resize(p_script->member_indices.size());
instance->script = Ref<GDScript>(p_script);
instance->owner = E->get();
diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp
index 789af57b4c..1acb9ceddc 100644
--- a/modules/gdscript/gdscript_disassembler.cpp
+++ b/modules/gdscript/gdscript_disassembler.cpp
@@ -397,7 +397,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
text += DADDR(1 + argc);
text += " = ";
- text += "<unkown type>(";
+ text += "<unknown type>(";
for (int i = 0; i < argc; i++) {
if (i > 0) {
text += ", ";
@@ -542,6 +542,28 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
incr = 5 + argc;
} break;
+ case OPCODE_CALL_BUILTIN_STATIC: {
+ Variant::Type type = (Variant::Type)_code_ptr[ip + 1 + instr_var_args];
+ int argc = _code_ptr[ip + 3 + instr_var_args];
+
+ text += "call built-in method static ";
+ text += DADDR(1 + argc);
+ text += " = ";
+ text += Variant::get_type_name(type);
+ text += ".";
+ text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]].operator String();
+ text += "(";
+
+ for (int i = 0; i < argc; i++) {
+ if (i > 0) {
+ text += ", ";
+ }
+ text += DADDR(1 + i);
+ }
+ text += ")";
+
+ incr += 5 + argc;
+ } break;
case OPCODE_CALL_PTRCALL_NO_RETURN: {
text += "call-ptrcall (no return) ";
@@ -598,12 +620,12 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
DISASSEMBLE_PTRCALL(PLANE);
DISASSEMBLE_PTRCALL(AABB);
DISASSEMBLE_PTRCALL(BASIS);
- DISASSEMBLE_PTRCALL(TRANSFORM);
+ DISASSEMBLE_PTRCALL(TRANSFORM3D);
DISASSEMBLE_PTRCALL(COLOR);
DISASSEMBLE_PTRCALL(STRING_NAME);
DISASSEMBLE_PTRCALL(NODE_PATH);
DISASSEMBLE_PTRCALL(RID);
- DISASSEMBLE_PTRCALL(QUAT);
+ DISASSEMBLE_PTRCALL(QUATERNION);
DISASSEMBLE_PTRCALL(OBJECT);
DISASSEMBLE_PTRCALL(CALLABLE);
DISASSEMBLE_PTRCALL(SIGNAL);
@@ -666,7 +688,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
int argc = _code_ptr[ip + 1 + instr_var_args];
text += DADDR(1 + argc) + " = ";
- text += "<unkown function>";
+ text += "<unknown function>";
text += "(";
for (int i = 0; i < argc; i++) {
@@ -935,7 +957,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
DISASSEMBLE_TYPE_ADJUST(VECTOR3I);
DISASSEMBLE_TYPE_ADJUST(TRANSFORM2D);
DISASSEMBLE_TYPE_ADJUST(PLANE);
- DISASSEMBLE_TYPE_ADJUST(QUAT);
+ DISASSEMBLE_TYPE_ADJUST(QUATERNION);
DISASSEMBLE_TYPE_ADJUST(AABB);
DISASSEMBLE_TYPE_ADJUST(BASIS);
DISASSEMBLE_TYPE_ADJUST(TRANSFORM);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 6ae825d2bd..18b7810919 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -32,7 +32,7 @@
#include "core/config/engine.h"
#include "core/core_constants.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "gdscript_analyzer.h"
#include "gdscript_compiler.h"
#include "gdscript_parser.h"
@@ -741,6 +741,7 @@ static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite,
ScriptCodeCompletionOption option;
if (p_suite->locals[i].type == GDScriptParser::SuiteNode::Local::CONSTANT) {
option = ScriptCodeCompletionOption(p_suite->locals[i].name, ScriptCodeCompletionOption::KIND_CONSTANT);
+ option.default_value = p_suite->locals[i].constant->initializer->reduced_value;
} else {
option = ScriptCodeCompletionOption(p_suite->locals[i].name, ScriptCodeCompletionOption::KIND_VARIABLE);
}
@@ -1028,7 +1029,7 @@ static void _find_identifiers(GDScriptParser::CompletionContext &p_context, bool
}
static const char *_type_names[Variant::VARIANT_MAX] = {
- "null", "bool", "int", "float", "String", "StringName", "Vector2", "Vector2i", "Rect2", "Rect2i", "Vector3", "Vector3i", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
+ "null", "bool", "int", "float", "String", "StringName", "Vector2", "Vector2i", "Rect2", "Rect2i", "Vector3", "Vector3i", "Transform2D", "Plane", "Quaternion", "AABB", "Basis", "Transform3D",
"Color", "NodePath", "RID", "Signal", "Callable", "Object", "Dictionary", "Array", "PackedByteArray", "PackedInt32Array", "PackedInt64Array", "PackedFloat32Array", "PackedFloat64Array", "PackedStringArray",
"PackedVector2Array", "PackedVector3Array", "PackedColorArray"
};
@@ -2872,7 +2873,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
StringName parent = ClassDB::get_parent_class(class_name);
if (parent != StringName()) {
if (String(parent).begins_with("_")) {
- base_type.native_type = String(parent).right(1);
+ base_type.native_type = String(parent).substr(1);
} else {
base_type.native_type = parent;
}
@@ -3066,7 +3067,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
// proxy class remove the underscore.
if (r_result.class_name.begins_with("_")) {
- r_result.class_name = r_result.class_name.right(1);
+ r_result.class_name = r_result.class_name.substr(1);
}
return OK;
}
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index 70b62ced6d..553c2ecc01 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -31,7 +31,7 @@
#ifndef GDSCRIPT_FUNCTION_H
#define GDSCRIPT_FUNCTION_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
#include "core/os/thread.h"
#include "core/string/string_name.h"
@@ -263,6 +263,7 @@ public:
OPCODE_CALL_SELF_BASE,
OPCODE_CALL_METHOD_BIND,
OPCODE_CALL_METHOD_BIND_RET,
+ OPCODE_CALL_BUILTIN_STATIC,
// ptrcall have one instruction per return type.
OPCODE_CALL_PTRCALL_NO_RETURN,
OPCODE_CALL_PTRCALL_BOOL,
@@ -277,10 +278,10 @@ public:
OPCODE_CALL_PTRCALL_VECTOR3I,
OPCODE_CALL_PTRCALL_TRANSFORM2D,
OPCODE_CALL_PTRCALL_PLANE,
- OPCODE_CALL_PTRCALL_QUAT,
+ OPCODE_CALL_PTRCALL_QUATERNION,
OPCODE_CALL_PTRCALL_AABB,
OPCODE_CALL_PTRCALL_BASIS,
- OPCODE_CALL_PTRCALL_TRANSFORM,
+ OPCODE_CALL_PTRCALL_TRANSFORM3D,
OPCODE_CALL_PTRCALL_COLOR,
OPCODE_CALL_PTRCALL_STRING_NAME,
OPCODE_CALL_PTRCALL_NODE_PATH,
@@ -364,7 +365,7 @@ public:
OPCODE_TYPE_ADJUST_VECTOR3I,
OPCODE_TYPE_ADJUST_TRANSFORM2D,
OPCODE_TYPE_ADJUST_PLANE,
- OPCODE_TYPE_ADJUST_QUAT,
+ OPCODE_TYPE_ADJUST_QUATERNION,
OPCODE_TYPE_ADJUST_AABB,
OPCODE_TYPE_ADJUST_BASIS,
OPCODE_TYPE_ADJUST_TRANSFORM,
@@ -496,6 +497,8 @@ private:
Vector<GDScriptDataType> argument_types;
GDScriptDataType return_type;
+ Map<int, Variant::Type> temporary_slots;
+
#ifdef TOOLS_ENABLED
Vector<StringName> arg_names;
Vector<Variant> default_arg_values;
@@ -594,8 +597,8 @@ public:
~GDScriptFunction();
};
-class GDScriptFunctionState : public Reference {
- GDCLASS(GDScriptFunctionState, Reference);
+class GDScriptFunctionState : public RefCounted {
+ GDCLASS(GDScriptFunctionState, RefCounted);
friend class GDScriptFunction;
GDScriptFunction *function = nullptr;
GDScriptFunction::CallState state;
diff --git a/modules/gdscript/gdscript_lambda_callable.h b/modules/gdscript/gdscript_lambda_callable.h
index 357c845250..336778d549 100644
--- a/modules/gdscript/gdscript_lambda_callable.h
+++ b/modules/gdscript/gdscript_lambda_callable.h
@@ -31,7 +31,7 @@
#ifndef GDSCRIPT_LAMBDA_CALLABLE
#define GDSCRIPT_LAMBDA_CALLABLE
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/templates/vector.h"
#include "core/variant/callable.h"
#include "core/variant/variant.h"
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index f9027c3a87..ba208ebfe8 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -31,9 +31,9 @@
#include "gdscript_parser.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
-#include "core/os/file_access.h"
#include "gdscript.h"
#ifdef DEBUG_ENABLED
@@ -61,9 +61,9 @@ Variant::Type GDScriptParser::get_builtin_type(const StringName &p_type) {
builtin_types["Vector3i"] = Variant::VECTOR3I;
builtin_types["AABB"] = Variant::AABB;
builtin_types["Plane"] = Variant::PLANE;
- builtin_types["Quat"] = Variant::QUAT;
+ builtin_types["Quaternion"] = Variant::QUATERNION;
builtin_types["Basis"] = Variant::BASIS;
- builtin_types["Transform"] = Variant::TRANSFORM;
+ builtin_types["Transform3D"] = Variant::TRANSFORM3D;
builtin_types["Color"] = Variant::COLOR;
builtin_types["RID"] = Variant::RID;
builtin_types["Object"] = Variant::OBJECT;
@@ -1173,7 +1173,7 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() {
consume(GDScriptTokenizer::Token::BRACE_CLOSE, R"(Expected closing "}" for enum.)");
#ifdef TOOLS_ENABLED
- // Enum values documentaion.
+ // Enum values documentation.
for (int i = 0; i < enum_node->values.size(); i++) {
if (i == enum_node->values.size() - 1) {
// If close bracket is same line as last value.
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index b1b29a7bd1..9e0b60a407 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -33,7 +33,7 @@
#include "core/io/multiplayer_api.h"
#include "core/io/resource.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
#include "core/string/string_name.h"
#include "core/string/ustring.h"
@@ -370,6 +370,7 @@ public:
Variant::Operator variant_op = Variant::OP_MAX;
ExpressionNode *assignee = nullptr;
ExpressionNode *assigned_value = nullptr;
+ bool use_conversion_assign = false;
AssignmentNode() {
type = ASSIGNMENT;
@@ -1119,6 +1120,7 @@ public:
MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
int assignments = 0;
int usages = 0;
+ bool use_conversion_assign = false;
#ifdef TOOLS_ENABLED
String doc_description;
#endif // TOOLS_ENABLED
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 4757ec6ca9..8a261a88e3 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -152,6 +152,44 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
return err_text;
}
+void (*type_init_function_table[])(Variant *) = {
+ nullptr, // NIL (shouldn't be called).
+ &VariantInitializer<bool>::init, // BOOL.
+ &VariantInitializer<int64_t>::init, // INT.
+ &VariantInitializer<double>::init, // FLOAT.
+ &VariantInitializer<String>::init, // STRING.
+ &VariantInitializer<Vector2>::init, // VECTOR2.
+ &VariantInitializer<Vector2i>::init, // VECTOR2I.
+ &VariantInitializer<Rect2>::init, // RECT2.
+ &VariantInitializer<Rect2i>::init, // RECT2I.
+ &VariantInitializer<Vector3>::init, // VECTOR3.
+ &VariantInitializer<Vector3i>::init, // VECTOR3I.
+ &VariantInitializer<Transform2D>::init, // TRANSFORM2D.
+ &VariantInitializer<Plane>::init, // PLANE.
+ &VariantInitializer<Quaternion>::init, // QUATERNION.
+ &VariantInitializer<AABB>::init, // AABB.
+ &VariantInitializer<Basis>::init, // BASIS.
+ &VariantInitializer<Transform3D>::init, // TRANSFORM3D.
+ &VariantInitializer<Color>::init, // COLOR.
+ &VariantInitializer<StringName>::init, // STRING_NAME.
+ &VariantInitializer<NodePath>::init, // NODE_PATH.
+ &VariantInitializer<RID>::init, // RID.
+ &VariantTypeAdjust<Object *>::adjust, // OBJECT.
+ &VariantInitializer<Callable>::init, // CALLABLE.
+ &VariantInitializer<Signal>::init, // SIGNAL.
+ &VariantInitializer<Dictionary>::init, // DICTIONARY.
+ &VariantInitializer<Array>::init, // ARRAY.
+ &VariantInitializer<PackedByteArray>::init, // PACKED_BYTE_ARRAY.
+ &VariantInitializer<PackedInt32Array>::init, // PACKED_INT32_ARRAY.
+ &VariantInitializer<PackedInt64Array>::init, // PACKED_INT64_ARRAY.
+ &VariantInitializer<PackedFloat32Array>::init, // PACKED_FLOAT32_ARRAY.
+ &VariantInitializer<PackedFloat64Array>::init, // PACKED_FLOAT64_ARRAY.
+ &VariantInitializer<PackedStringArray>::init, // PACKED_STRING_ARRAY.
+ &VariantInitializer<PackedVector2Array>::init, // PACKED_VECTOR2_ARRAY.
+ &VariantInitializer<PackedVector3Array>::init, // PACKED_VECTOR3_ARRAY.
+ &VariantInitializer<PackedColorArray>::init, // PACKED_COLOR_ARRAY.
+};
+
#if defined(__GNUC__)
#define OPCODES_TABLE \
static const void *switch_table_ops[] = { \
@@ -196,6 +234,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
&&OPCODE_CALL_SELF_BASE, \
&&OPCODE_CALL_METHOD_BIND, \
&&OPCODE_CALL_METHOD_BIND_RET, \
+ &&OPCODE_CALL_BUILTIN_STATIC, \
&&OPCODE_CALL_PTRCALL_NO_RETURN, \
&&OPCODE_CALL_PTRCALL_BOOL, \
&&OPCODE_CALL_PTRCALL_INT, \
@@ -209,10 +248,10 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
&&OPCODE_CALL_PTRCALL_VECTOR3I, \
&&OPCODE_CALL_PTRCALL_TRANSFORM2D, \
&&OPCODE_CALL_PTRCALL_PLANE, \
- &&OPCODE_CALL_PTRCALL_QUAT, \
+ &&OPCODE_CALL_PTRCALL_QUATERNION, \
&&OPCODE_CALL_PTRCALL_AABB, \
&&OPCODE_CALL_PTRCALL_BASIS, \
- &&OPCODE_CALL_PTRCALL_TRANSFORM, \
+ &&OPCODE_CALL_PTRCALL_TRANSFORM3D, \
&&OPCODE_CALL_PTRCALL_COLOR, \
&&OPCODE_CALL_PTRCALL_STRING_NAME, \
&&OPCODE_CALL_PTRCALL_NODE_PATH, \
@@ -296,7 +335,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
&&OPCODE_TYPE_ADJUST_VECTOR3I, \
&&OPCODE_TYPE_ADJUST_TRANSFORM2D, \
&&OPCODE_TYPE_ADJUST_PLANE, \
- &&OPCODE_TYPE_ADJUST_QUAT, \
+ &&OPCODE_TYPE_ADJUST_QUATERNION, \
&&OPCODE_TYPE_ADJUST_AABB, \
&&OPCODE_TYPE_ADJUST_BASIS, \
&&OPCODE_TYPE_ADJUST_TRANSFORM, \
@@ -359,7 +398,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
#define OP_GET_VECTOR3I get_vector3i
#define OP_GET_RECT2 get_rect2
#define OP_GET_RECT2I get_rect2i
-#define OP_GET_QUAT get_quat
+#define OP_GET_QUATERNION get_quaternion
#define OP_GET_COLOR get_color
#define OP_GET_STRING get_string
#define OP_GET_STRING_NAME get_string_name
@@ -377,7 +416,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
#define OP_GET_PACKED_VECTOR2_ARRAY get_vector2_array
#define OP_GET_PACKED_VECTOR3_ARRAY get_vector3_array
#define OP_GET_PACKED_COLOR_ARRAY get_color_array
-#define OP_GET_TRANSFORM get_transform
+#define OP_GET_TRANSFORM3D get_transform
#define OP_GET_TRANSFORM2D get_transform2d
#define OP_GET_PLANE get_plane
#define OP_GET_AABB get_aabb
@@ -491,6 +530,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
+ for (const Map<int, Variant::Type>::Element *E = temporary_slots.front(); E; E = E->next()) {
+ type_init_function_table[E->get()](&stack[E->key()]);
+ }
+
String err_text;
#ifdef DEBUG_ENABLED
@@ -1573,6 +1616,51 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
DISPATCH_OPCODE;
+ OPCODE(OPCODE_CALL_BUILTIN_STATIC) {
+ CHECK_SPACE(4 + instr_arg_count);
+
+ ip += instr_arg_count;
+
+ GD_ERR_BREAK(_code_ptr[ip + 1] < 0 || _code_ptr[ip + 1] >= Variant::VARIANT_MAX);
+ Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 1];
+
+ int methodname_idx = _code_ptr[ip + 2];
+ GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count);
+ const StringName *methodname = &_global_names_ptr[methodname_idx];
+
+ int argc = _code_ptr[ip + 3];
+ GD_ERR_BREAK(argc < 0);
+
+ GET_INSTRUCTION_ARG(ret, argc);
+
+ const Variant **argptrs = const_cast<const Variant **>(instruction_args);
+
+#ifdef DEBUG_ENABLED
+ uint64_t call_time = 0;
+
+ if (GDScriptLanguage::get_singleton()->profiling) {
+ call_time = OS::get_singleton()->get_ticks_usec();
+ }
+#endif
+
+ Callable::CallError err;
+ Variant::call_static(builtin_type, *methodname, argptrs, argc, *ret, err);
+
+#ifdef DEBUG_ENABLED
+ if (GDScriptLanguage::get_singleton()->profiling) {
+ function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
+ }
+
+ if (err.error != Callable::CallError::CALL_OK) {
+ err_text = _get_call_error(err, "static function '" + methodname->operator String() + "' in type '" + Variant::get_type_name(builtin_type) + "'", argptrs);
+ OPCODE_BREAK;
+ }
+#endif
+
+ ip += 4;
+ }
+ DISPATCH_OPCODE;
+
#ifdef DEBUG_ENABLED
#define OPCODE_CALL_PTR(m_type) \
OPCODE(OPCODE_CALL_PTRCALL_##m_type) { \
@@ -1645,10 +1733,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_CALL_PTR(VECTOR3I);
OPCODE_CALL_PTR(TRANSFORM2D);
OPCODE_CALL_PTR(PLANE);
- OPCODE_CALL_PTR(QUAT);
+ OPCODE_CALL_PTR(QUATERNION);
OPCODE_CALL_PTR(AABB);
OPCODE_CALL_PTR(BASIS);
- OPCODE_CALL_PTR(TRANSFORM);
+ OPCODE_CALL_PTR(TRANSFORM3D);
OPCODE_CALL_PTR(COLOR);
OPCODE_CALL_PTR(STRING_NAME);
OPCODE_CALL_PTR(NODE_PATH);
@@ -1882,7 +1970,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (err.error != Callable::CallError::CALL_OK) {
// TODO: Add this information in debug.
- String methodstr = "<unkown function>";
+ String methodstr = "<unknown function>";
if (dst->get_type() == Variant::STRING) {
// Call provided error string.
err_text = "Error calling GDScript utility function '" + methodstr + "': " + String(*dst);
@@ -1901,7 +1989,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
ip += instr_arg_count;
- int self_fun = _code_ptr[ip + 1];
+ int argc = _code_ptr[ip + 1];
+ GD_ERR_BREAK(argc < 0);
+
+ int self_fun = _code_ptr[ip + 2];
#ifdef DEBUG_ENABLED
if (self_fun < 0 || self_fun >= _global_names_count) {
err_text = "compiler bug, function name not found";
@@ -1910,9 +2001,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
const StringName *methodname = &_global_names_ptr[self_fun];
- int argc = _code_ptr[ip + 2];
- GD_ERR_BREAK(argc < 0);
-
Variant **argptrs = instruction_args;
GET_INSTRUCTION_ARG(dst, argc);
@@ -3062,10 +3150,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i);
OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D);
OPCODE_TYPE_ADJUST(PLANE, Plane);
- OPCODE_TYPE_ADJUST(QUAT, Quat);
+ OPCODE_TYPE_ADJUST(QUATERNION, Quaternion);
OPCODE_TYPE_ADJUST(AABB, AABB);
OPCODE_TYPE_ADJUST(BASIS, Basis);
- OPCODE_TYPE_ADJUST(TRANSFORM, Transform);
+ OPCODE_TYPE_ADJUST(TRANSFORM, Transform3D);
OPCODE_TYPE_ADJUST(COLOR, Color);
OPCODE_TYPE_ADJUST(STRING_NAME, StringName);
OPCODE_TYPE_ADJUST(NODE_PATH, NodePath);
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h
index a5c5a233b1..969c38eab6 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.h
+++ b/modules/gdscript/language_server/gdscript_language_protocol.h
@@ -46,7 +46,7 @@ class GDScriptLanguageProtocol : public JSONRPC {
GDCLASS(GDScriptLanguageProtocol, JSONRPC)
private:
- struct LSPeer : Reference {
+ struct LSPeer : RefCounted {
Ref<StreamPeerTCP> connection;
uint8_t req_buf[LSP_MAX_BUFFER_SIZE];
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index 340a7b9343..33597c286f 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -30,7 +30,7 @@
#include "gdscript_language_server.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h
index 792e601bc1..17f1d5d5e3 100644
--- a/modules/gdscript/language_server/gdscript_text_document.h
+++ b/modules/gdscript/language_server/gdscript_text_document.h
@@ -31,12 +31,12 @@
#ifndef GDSCRIPT_TEXT_DOCUMENT_H
#define GDSCRIPT_TEXT_DOCUMENT_H
-#include "core/object/reference.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
+#include "core/object/ref_counted.h"
#include "lsp.hpp"
-class GDScriptTextDocument : public Reference {
- GDCLASS(GDScriptTextDocument, Reference)
+class GDScriptTextDocument : public RefCounted {
+ GDCLASS(GDScriptTextDocument, RefCounted)
protected:
static void _bind_methods();
diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h
index 27616a2989..8b166a873c 100644
--- a/modules/gdscript/language_server/gdscript_workspace.h
+++ b/modules/gdscript/language_server/gdscript_workspace.h
@@ -37,8 +37,8 @@
#include "gdscript_extend_parser.h"
#include "lsp.hpp"
-class GDScriptWorkspace : public Reference {
- GDCLASS(GDScriptWorkspace, Reference);
+class GDScriptWorkspace : public RefCounted {
+ GDCLASS(GDScriptWorkspace, RefCounted);
private:
void _get_owners(EditorFileSystemDirectory *efsd, String p_path, List<String> &owners);
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp
index 47bcfeaefc..a7dcfdb22d 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/lsp.hpp
@@ -766,7 +766,7 @@ struct MarkupContent {
// Use namespace instead of enumeration to follow the LSP specifications
// lsp::EnumName::EnumValue is OK but lsp::EnumValue is not
-// And here C++ compilers are unhappy with our enumeration name like Color, File, Reference etc.
+// And here C++ compilers are unhappy with our enumeration name like Color, File, RefCounted etc.
/**
* The kind of a completion entry.
*/
@@ -788,7 +788,7 @@ static const int Keyword = 14;
static const int Snippet = 15;
static const int Color = 16;
static const int File = 17;
-static const int Reference = 18;
+static const int RefCounted = 18;
static const int Folder = 19;
static const int EnumMember = 20;
static const int Constant = 21;
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index 2d2f94f5e0..867142019f 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -30,10 +30,10 @@
#include "register_types.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_encrypted.h"
#include "core/io/resource_loader.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "gdscript.h"
#include "gdscript_analyzer.h"
#include "gdscript_cache.h"
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index 76ae43e792..67bc927517 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -37,8 +37,8 @@
#include "core/config/project_settings.h"
#include "core/core_string_names.h"
+#include "core/io/dir_access.h"
#include "core/io/file_access_pack.h"
-#include "core/os/dir_access.h"
#include "core/os/os.h"
#include "core/string/string_builder.h"
#include "scene/resources/packed_scene.h"
@@ -257,6 +257,7 @@ bool GDScriptTestRunner::make_tests() {
ERR_FAIL_COND_V_MSG(err != OK, false, "Could not open specified test directory.");
+ source_dir = dir->get_current_dir() + "/"; // Make it absolute path.
return make_tests_for_dir(dir->get_current_dir());
}
@@ -361,11 +362,9 @@ void GDScriptTest::error_handler(void *p_this, const char *p_function, const cha
break;
}
- builder.append("\n>> ");
- builder.append(p_function);
- builder.append("\n>> ");
+ builder.append("\n>> on function: ");
builder.append(p_function);
- builder.append("\n>> ");
+ builder.append("()\n>> ");
builder.append(String(p_file).trim_prefix(self->base_dir));
builder.append("\n>> ");
builder.append(itos(p_line));
@@ -512,9 +511,9 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
// Create object instance for test.
Object *obj = ClassDB::instance(script->get_native()->get_name());
- Ref<Reference> obj_ref;
- if (obj->is_reference()) {
- obj_ref = Ref<Reference>(Object::cast_to<Reference>(obj));
+ Ref<RefCounted> obj_ref;
+ if (obj->is_ref_counted()) {
+ obj_ref = Ref<RefCounted>(Object::cast_to<RefCounted>(obj));
}
obj->set_script(script);
GDScriptInstance *instance = static_cast<GDScriptInstance *>(obj->get_script_instance());
diff --git a/modules/gdscript/tests/gdscript_test_runner_suite.h b/modules/gdscript/tests/gdscript_test_runner_suite.h
index 136907b316..cf4e61f07d 100644
--- a/modules/gdscript/tests/gdscript_test_runner_suite.h
+++ b/modules/gdscript/tests/gdscript_test_runner_suite.h
@@ -48,6 +48,27 @@ TEST_SUITE("[Modules][GDScript]") {
}
}
+TEST_CASE("[Modules][GDScript] Load source code dynamically and run it") {
+ Ref<GDScript> gdscript = memnew(GDScript);
+ gdscript->set_source_code(R"(
+extends RefCounted
+
+func _init():
+ set_meta("result", 42)
+)");
+ // A spurious `Condition "err" is true` message is printed (despite parsing being successful and returning `OK`).
+ // Silence it.
+ ERR_PRINT_OFF;
+ const Error error = gdscript->reload();
+ ERR_PRINT_ON;
+ CHECK_MESSAGE(error == OK, "The script should parse successfully.");
+
+ // Run the script by assigning it to a reference-counted object.
+ Ref<RefCounted> ref_counted = memnew(RefCounted);
+ ref_counted->set_script(gdscript);
+ CHECK_MESSAGE(int(ref_counted->get_meta("result")) == 42, "The script should assign object metadata successfully.");
+}
+
} // namespace GDScriptTests
#endif // GDSCRIPT_TEST_RUNNER_SUITE_H
diff --git a/modules/gdscript/tests/scripts/analyzer/features/call_self_get_name.gd b/modules/gdscript/tests/scripts/analyzer/features/call_self_get_name.gd
new file mode 100644
index 0000000000..d21d8bce96
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/call_self_get_name.gd
@@ -0,0 +1,9 @@
+extends Node
+
+func test():
+ set_name("TestNodeName")
+ if get_name() == &"TestNodeName":
+ print("Name is equal")
+ else:
+ print("Name is not equal")
+ print(get_name() is StringName)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/call_self_get_name.out b/modules/gdscript/tests/scripts/analyzer/features/call_self_get_name.out
new file mode 100644
index 0000000000..dc4348d9c3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/call_self_get_name.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+Name is equal
+True
diff --git a/modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.gd b/modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.gd
new file mode 100644
index 0000000000..10780b5379
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.gd
@@ -0,0 +1,5 @@
+func test():
+ var node := Node.new()
+ var inside_tree = node.is_inside_tree
+ node.free()
+ inside_tree.call()
diff --git a/modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.out b/modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.out
new file mode 100644
index 0000000000..e585c374e2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/callable_call_after_free_object.gd
+>> 5
+>> Attempt to call function 'null::is_inside_tree (Callable)' on a null instance.
diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp
index 36da64bbaa..c37d52febd 100644
--- a/modules/gdscript/tests/test_gdscript.cpp
+++ b/modules/gdscript/tests/test_gdscript.cpp
@@ -31,8 +31,8 @@
#include "test_gdscript.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_pack.h"
-#include "core/os/file_access.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "core/string/string_builder.h"
@@ -215,8 +215,8 @@ void test(TestType p_type) {
init_language(fa->get_path_absolute().get_base_dir());
Vector<uint8_t> buf;
- int flen = fa->get_len();
- buf.resize(fa->get_len() + 1);
+ uint64_t flen = fa->get_length();
+ buf.resize(flen + 1);
fa->get_buffer(buf.ptrw(), flen);
buf.write[flen] = 0;
diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp
index 4331daadfc..730c6b89f7 100644
--- a/modules/glslang/register_types.cpp
+++ b/modules/glslang/register_types.cpp
@@ -116,6 +116,10 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
}
}
+ if (p_capabilities->supports_multiview) {
+ preamble += "#define has_VK_KHR_multiview 1\n";
+ }
+
if (preamble != "") {
shader.setPreamble(preamble.c_str());
}
@@ -179,11 +183,18 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
return ret;
}
+static String _get_cache_key_function_glsl(const RenderingDevice::Capabilities *p_capabilities) {
+ String version;
+ version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(p_capabilities->version_major) + ", minor=" + itos(p_capabilities->version_minor) + " , subgroup_size=" + itos(p_capabilities->subgroup_operations) + " , subgroup_ops=" + itos(p_capabilities->subgroup_operations) + " , subgroup_in_shaders=" + itos(p_capabilities->subgroup_in_shaders);
+ return version;
+}
+
void preregister_glslang_types() {
// initialize in case it's not initialized. This is done once per thread
// and it's safe to call multiple times
glslang::InitializeProcess();
RenderingDevice::shader_set_compile_function(_compile_shader_glsl);
+ RenderingDevice::shader_set_get_cache_key_function(_get_cache_key_function_glsl);
}
void register_glslang_types() {
diff --git a/modules/gltf/doc_classes/GLTFNode.xml b/modules/gltf/doc_classes/GLTFNode.xml
index 5b7d4fadec..5d84d7088b 100644
--- a/modules/gltf/doc_classes/GLTFNode.xml
+++ b/modules/gltf/doc_classes/GLTFNode.xml
@@ -13,8 +13,6 @@
</member>
<member name="children" type="PackedInt32Array" setter="set_children" getter="get_children" default="PackedInt32Array( )">
</member>
- <member name="fake_joint_parent" type="int" setter="set_fake_joint_parent" getter="get_fake_joint_parent" default="-1">
- </member>
<member name="height" type="int" setter="set_height" getter="get_height" default="-1">
</member>
<member name="joint" type="bool" setter="set_joint" getter="get_joint" default="false">
@@ -25,7 +23,7 @@
</member>
<member name="parent" type="int" setter="set_parent" getter="get_parent" default="-1">
</member>
- <member name="rotation" type="Quat" setter="set_rotation" getter="get_rotation" default="Quat( 0, 0, 0, 1 )">
+ <member name="rotation" type="Quaternion" setter="set_rotation" getter="get_rotation" default="Quaternion( 0, 0, 0, 1 )">
</member>
<member name="scale" type="Vector3" setter="set_scale" getter="get_scale" default="Vector3( 1, 1, 1 )">
</member>
@@ -35,7 +33,7 @@
</member>
<member name="translation" type="Vector3" setter="set_translation" getter="get_translation" default="Vector3( 0, 0, 0 )">
</member>
- <member name="xform" type="Transform" setter="set_xform" getter="get_xform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ <member name="xform" type="Transform3D" setter="set_xform" getter="get_xform" default="Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
</member>
</members>
<constants>
diff --git a/modules/gltf/editor_scene_importer_gltf.cpp b/modules/gltf/editor_scene_importer_gltf.cpp
index 35f44ca122..21b4bb75fb 100644
--- a/modules/gltf/editor_scene_importer_gltf.cpp
+++ b/modules/gltf/editor_scene_importer_gltf.cpp
@@ -29,10 +29,10 @@
/*************************************************************************/
#include "core/crypto/crypto_core.h"
+#include "core/io/file_access.h"
#include "core/io/json.h"
#include "core/math/disjoint_set.h"
#include "core/math/math_defs.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "editor/import/resource_importer_scene.h"
#include "modules/gltf/gltf_state.h"
diff --git a/modules/gltf/gltf_animation.h b/modules/gltf/gltf_animation.h
index a494e6bd67..216d2161c4 100644
--- a/modules/gltf/gltf_animation.h
+++ b/modules/gltf/gltf_animation.h
@@ -56,7 +56,7 @@ public:
struct Track {
Channel<Vector3> translation_track;
- Channel<Quat> rotation_track;
+ Channel<Quaternion> rotation_track;
Channel<Vector3> scale_track;
Vector<Channel<float>> weight_tracks;
};
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index e67e29f7b4..bc4de76344 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -49,9 +49,9 @@
#include "core/core_bind.h"
#include "core/crypto/crypto_core.h"
+#include "core/io/file_access.h"
#include "core/io/json.h"
#include "core/math/disjoint_set.h"
-#include "core/os/file_access.h"
#include "core/variant/typed_array.h"
#include "core/version.h"
#include "core/version_hash.gen.h"
@@ -233,7 +233,7 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
}
Vector<uint8_t> array;
- array.resize(f->get_len());
+ array.resize(f->get_length());
f->get_buffer(array.ptrw(), array.size());
String text;
text.parse_utf8((const char *)array.ptr(), array.size());
@@ -342,25 +342,25 @@ static Vector3 _arr_to_vec3(const Array &p_array) {
return Vector3(p_array[0], p_array[1], p_array[2]);
}
-static Array _quat_to_array(const Quat &p_quat) {
+static Array _quaternion_to_array(const Quaternion &p_quaternion) {
Array array;
array.resize(4);
- array[0] = p_quat.x;
- array[1] = p_quat.y;
- array[2] = p_quat.z;
- array[3] = p_quat.w;
+ array[0] = p_quaternion.x;
+ array[1] = p_quaternion.y;
+ array[2] = p_quaternion.z;
+ array[3] = p_quaternion.w;
return array;
}
-static Quat _arr_to_quat(const Array &p_array) {
- ERR_FAIL_COND_V(p_array.size() != 4, Quat());
- return Quat(p_array[0], p_array[1], p_array[2], p_array[3]);
+static Quaternion _arr_to_quaternion(const Array &p_array) {
+ ERR_FAIL_COND_V(p_array.size() != 4, Quaternion());
+ return Quaternion(p_array[0], p_array[1], p_array[2], p_array[3]);
}
-static Transform _arr_to_xform(const Array &p_array) {
- ERR_FAIL_COND_V(p_array.size() != 16, Transform());
+static Transform3D _arr_to_xform(const Array &p_array) {
+ ERR_FAIL_COND_V(p_array.size() != 16, Transform3D());
- Transform xform;
+ Transform3D xform;
xform.basis.set_axis(Vector3::AXIS_X, Vector3(p_array[0], p_array[1], p_array[2]));
xform.basis.set_axis(Vector3::AXIS_Y, Vector3(p_array[4], p_array[5], p_array[6]));
xform.basis.set_axis(Vector3::AXIS_Z, Vector3(p_array[8], p_array[9], p_array[10]));
@@ -369,7 +369,7 @@ static Transform _arr_to_xform(const Array &p_array) {
return xform;
}
-static Vector<real_t> _xform_to_array(const Transform p_transform) {
+static Vector<real_t> _xform_to_array(const Transform3D p_transform) {
Vector<real_t> array;
array.resize(16);
Vector3 axis_x = p_transform.get_basis().get_axis(Vector3::AXIS_X);
@@ -421,12 +421,12 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) {
}
if (n->skeleton != -1 && n->skin < 0) {
}
- if (n->xform != Transform()) {
+ if (n->xform != Transform3D()) {
node["matrix"] = _xform_to_array(n->xform);
}
- if (!n->rotation.is_equal_approx(Quat())) {
- node["rotation"] = _quat_to_array(n->rotation);
+ if (!n->rotation.is_equal_approx(Quaternion())) {
+ node["rotation"] = _quaternion_to_array(n->rotation);
}
if (!n->scale.is_equal_approx(Vector3(1.0f, 1.0f, 1.0f))) {
@@ -591,13 +591,13 @@ Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) {
node->translation = _arr_to_vec3(n["translation"]);
}
if (n.has("rotation")) {
- node->rotation = _arr_to_quat(n["rotation"]);
+ node->rotation = _arr_to_quaternion(n["rotation"]);
}
if (n.has("scale")) {
node->scale = _arr_to_vec3(n["scale"]);
}
- node->xform.basis.set_quat_scale(node->rotation, node->scale);
+ node->xform.basis.set_quaternion_scale(node->rotation, node->scale);
node->xform.origin = node->translation;
}
@@ -664,7 +664,7 @@ static Vector<uint8_t> _parse_base64_uri(const String &uri) {
int start = uri.find(",");
ERR_FAIL_COND_V(start == -1, Vector<uint8_t>());
- CharString substr = uri.right(start + 1).ascii();
+ CharString substr = uri.substr(start + 1).ascii();
int strlen = substr.length();
@@ -1779,7 +1779,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state,
return state->accessors.size() - 1;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quats(Ref<GLTFState> state, const Vector<Quat> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> state, const Vector<Quaternion> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1794,11 +1794,11 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quats(Ref<GLTFState> state,
Vector<double> type_min;
type_min.resize(element_count);
for (int i = 0; i < p_attribs.size(); i++) {
- Quat quat = p_attribs[i];
- attribs.write[(i * element_count) + 0] = Math::snapped(quat.x, CMP_NORMALIZE_TOLERANCE);
- attribs.write[(i * element_count) + 1] = Math::snapped(quat.y, CMP_NORMALIZE_TOLERANCE);
- attribs.write[(i * element_count) + 2] = Math::snapped(quat.z, CMP_NORMALIZE_TOLERANCE);
- attribs.write[(i * element_count) + 3] = Math::snapped(quat.w, CMP_NORMALIZE_TOLERANCE);
+ Quaternion quaternion = p_attribs[i];
+ attribs.write[(i * element_count) + 0] = Math::snapped(quaternion.x, CMP_NORMALIZE_TOLERANCE);
+ attribs.write[(i * element_count) + 1] = Math::snapped(quaternion.y, CMP_NORMALIZE_TOLERANCE);
+ attribs.write[(i * element_count) + 2] = Math::snapped(quaternion.z, CMP_NORMALIZE_TOLERANCE);
+ attribs.write[(i * element_count) + 3] = Math::snapped(quaternion.w, CMP_NORMALIZE_TOLERANCE);
_calc_accessor_min_max(i, element_count, type_max, attribs, type_min);
}
@@ -1939,7 +1939,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, c
return state->accessors.size() - 1;
}
-GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state, const Vector<Transform> p_attribs, const bool p_for_vertex) {
+GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state, const Vector<Transform3D> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
}
@@ -1953,7 +1953,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state,
Vector<double> type_min;
type_min.resize(element_count);
for (int i = 0; i < p_attribs.size(); i++) {
- Transform attrib = p_attribs[i];
+ Transform3D attrib = p_attribs[i];
Basis basis = attrib.get_basis();
Vector3 axis_0 = basis.get_axis(Vector3::AXIS_X);
@@ -2053,9 +2053,9 @@ Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> state, cons
}
return ret;
}
-Vector<Quat> GLTFDocument::_decode_accessor_as_quat(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+Vector<Quaternion> GLTFDocument::_decode_accessor_as_quaternion(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Quat> ret;
+ Vector<Quaternion> ret;
if (attribs.size() == 0) {
return ret;
@@ -2067,7 +2067,7 @@ Vector<Quat> GLTFDocument::_decode_accessor_as_quat(Ref<GLTFState> state, const
ret.resize(ret_size);
{
for (int i = 0; i < ret_size; i++) {
- ret.write[i] = Quat(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]).normalized();
+ ret.write[i] = Quaternion(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]).normalized();
}
}
return ret;
@@ -2107,9 +2107,9 @@ Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> state, cons
return ret;
}
-Vector<Transform> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Transform> ret;
+ Vector<Transform3D> ret;
if (attribs.size() == 0) {
return ret;
@@ -2821,8 +2821,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
}
blend_weights.write[j] = weights[j];
}
- mesh->set_blend_weights(blend_weights);
}
+ mesh->set_blend_weights(blend_weights);
mesh->set_mesh(import_mesh);
state->meshes.push_back(mesh);
@@ -3031,8 +3031,11 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
}
}
- ERR_FAIL_COND_V_MSG(img.is_null(), ERR_FILE_CORRUPT,
- vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype));
+ if (img.is_null()) {
+ ERR_PRINT(vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype));
+ state->images.push_back(Ref<Texture2D>());
+ continue;
+ }
Ref<ImageTexture> t;
t.instance();
@@ -4105,81 +4108,10 @@ Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> state,
subtree_set.get_members(subtree_nodes, subtree_root);
for (int subtree_i = 0; subtree_i < subtree_nodes.size(); ++subtree_i) {
- ERR_FAIL_COND_V(_reparent_to_fake_joint(state, skeleton, subtree_nodes[subtree_i]), FAILED);
-
- // We modified the tree, recompute all the heights
- _compute_node_heights(state);
- }
- }
-
- return OK;
-}
-
-Error GLTFDocument::_reparent_to_fake_joint(Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton, const GLTFNodeIndex node_index) {
- Ref<GLTFNode> node = state->nodes[node_index];
-
- // Can we just "steal" this joint if it is just a spatial node?
- if (node->skin < 0 && node->mesh < 0 && node->camera < 0) {
- node->joint = true;
- // Add the joint to the skeletons joints
- skeleton->joints.push_back(node_index);
- return OK;
- }
-
- GLTFNode *fake_joint = memnew(GLTFNode);
- const GLTFNodeIndex fake_joint_index = state->nodes.size();
- state->nodes.push_back(fake_joint);
-
- // We better not be a joint, or we messed up in our logic
- if (node->joint) {
- return FAILED;
- }
-
- fake_joint->translation = node->translation;
- fake_joint->rotation = node->rotation;
- fake_joint->scale = node->scale;
- fake_joint->xform = node->xform;
- fake_joint->joint = true;
-
- // We can use the exact same name here, because the joint will be inside a skeleton and not the scene
- fake_joint->set_name(node->get_name());
-
- // Clear the nodes transforms, since it will be parented to the fake joint
- node->translation = Vector3(0, 0, 0);
- node->rotation = Quat();
- node->scale = Vector3(1, 1, 1);
- node->xform = Transform();
-
- // Transfer the node children to the fake joint
- for (int child_i = 0; child_i < node->children.size(); ++child_i) {
- Ref<GLTFNode> child = state->nodes[node->children[child_i]];
- child->parent = fake_joint_index;
- }
-
- fake_joint->children = node->children;
- node->children.clear();
-
- // add the fake joint to the parent and remove the original joint
- if (node->parent >= 0) {
- Ref<GLTFNode> parent = state->nodes[node->parent];
- parent->children.erase(node_index);
- parent->children.push_back(fake_joint_index);
- fake_joint->parent = node->parent;
- }
-
- // Add the node to the fake joint
- fake_joint->children.push_back(node_index);
- node->parent = fake_joint_index;
- node->fake_joint_parent = fake_joint_index;
-
- // Add the fake joint to the skeletons joints
- skeleton->joints.push_back(fake_joint_index);
-
- // Replace skin_skeletons with fake joints if we must.
- for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) {
- Ref<GLTFSkin> skin = state->skins.write[skin_i];
- if (skin->skin_root == node_index) {
- skin->skin_root = fake_joint_index;
+ Ref<GLTFNode> node = state->nodes[subtree_nodes[subtree_i]];
+ node->joint = true;
+ // Add the joint to the skeletons joints
+ skeleton->joints.push_back(subtree_nodes[subtree_i]);
}
}
@@ -4347,7 +4279,7 @@ Error GLTFDocument::_create_skins(Ref<GLTFState> state) {
GLTFNodeIndex node = gltf_skin->joints_original[joint_i];
String bone_name = state->nodes[node]->get_name();
- Transform xform;
+ Transform3D xform;
if (has_ibms) {
xform = gltf_skin->inverse_binds[joint_i];
}
@@ -4387,9 +4319,12 @@ bool GLTFDocument::_skins_are_same(const Ref<Skin> skin_a, const Ref<Skin> skin_
if (skin_a->get_bind_bone(i) != skin_b->get_bind_bone(i)) {
return false;
}
+ if (skin_a->get_bind_name(i) != skin_b->get_bind_name(i)) {
+ return false;
+ }
- Transform a_xform = skin_a->get_bind_pose(i);
- Transform b_xform = skin_b->get_bind_pose(i);
+ Transform3D a_xform = skin_a->get_bind_pose(i);
+ Transform3D b_xform = skin_b->get_bind_pose(i);
if (a_xform != b_xform) {
return false;
@@ -4672,8 +4607,8 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) {
s["interpolation"] = interpolation_to_string(track.rotation_track.interpolation);
Vector<real_t> times = Variant(track.rotation_track.times);
s["input"] = _encode_accessor_as_floats(state, times, false);
- Vector<Quat> values = track.rotation_track.values;
- s["output"] = _encode_accessor_as_quats(state, values, false);
+ Vector<Quaternion> values = track.rotation_track.values;
+ s["output"] = _encode_accessor_as_quaternions(state, values, false);
samplers.push_back(s);
@@ -4842,7 +4777,7 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) {
track->translation_track.times = Variant(times); //convert via variant
track->translation_track.values = Variant(translations); //convert via variant
} else if (path == "rotation") {
- const Vector<Quat> rotations = _decode_accessor_as_quat(state, output, false);
+ const Vector<Quaternion> rotations = _decode_accessor_as_quaternion(state, output, false);
track->rotation_track.interpolation = interp;
track->rotation_track.times = Variant(times); //convert via variant
track->rotation_track.values = rotations;
@@ -4914,10 +4849,9 @@ void GLTFDocument::_assign_scene_names(Ref<GLTFState> state) {
}
}
-BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> state, Skeleton3D *skeleton, const GLTFNodeIndex node_index) {
+BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> state, Skeleton3D *skeleton, const GLTFNodeIndex node_index, const GLTFNodeIndex bone_index) {
Ref<GLTFNode> gltf_node = state->nodes[node_index];
- Ref<GLTFNode> bone_node = state->nodes[gltf_node->parent];
-
+ Ref<GLTFNode> bone_node = state->nodes[bone_index];
BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D);
print_verbose("glTF: Creating bone attachment for: " + gltf_node->get_name());
@@ -5002,7 +4936,7 @@ EditorSceneImporterMeshNode3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFSta
return mi;
}
-Light3D *GLTFDocument::_generate_light(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) {
+Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) {
Ref<GLTFNode> gltf_node = state->nodes[node_index];
ERR_FAIL_INDEX_V(gltf_node->light, state->lights.size(), nullptr);
@@ -5051,7 +4985,7 @@ Light3D *GLTFDocument::_generate_light(Ref<GLTFState> state, Node *scene_parent,
light->set_param(SpotLight3D::PARAM_SPOT_ATTENUATION, angle_attenuation);
return light;
}
- return nullptr;
+ return memnew(Node3D);
}
Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) {
@@ -5141,9 +5075,9 @@ GLTFSkeletonIndex GLTFDocument::_convert_skeleton(Ref<GLTFState> state, Skeleton
}
void GLTFDocument::_convert_spatial(Ref<GLTFState> state, Node3D *p_spatial, Ref<GLTFNode> p_node) {
- Transform xform = p_spatial->get_transform();
+ Transform3D xform = p_spatial->get_transform();
p_node->scale = xform.basis.get_scale();
- p_node->rotation = xform.basis.get_rotation_quat();
+ p_node->rotation = xform.basis.get_rotation_quaternion();
p_node->translation = xform.origin;
}
@@ -5306,7 +5240,7 @@ void GLTFDocument::_convert_grid_map_to_gltf(Node *p_scene_parent, const GLTFNod
Vector3(cell_location.x, cell_location.y, cell_location.z));
EditorSceneImporterMeshNode3D *import_mesh_node = memnew(EditorSceneImporterMeshNode3D);
import_mesh_node->set_mesh(grid_map->get_mesh_library()->get_item_mesh(cell));
- Transform cell_xform;
+ Transform3D cell_xform;
cell_xform.basis.set_orthogonal_index(
grid_map->get_cell_item_orientation(
Vector3(cell_location.x, cell_location.y, cell_location.z)));
@@ -5334,15 +5268,15 @@ void GLTFDocument::_convert_mult_mesh_instance_to_gltf(Node *p_scene_parent, con
for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count();
instance_i++) {
GLTFNode *new_gltf_node = memnew(GLTFNode);
- Transform transform;
+ Transform3D transform;
if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_2D) {
Transform2D xform_2d = multi_mesh->get_instance_transform_2d(instance_i);
transform.origin =
Vector3(xform_2d.get_origin().x, 0, xform_2d.get_origin().y);
real_t rotation = xform_2d.get_rotation();
- Quat quat(Vector3(0, 1, 0), rotation);
+ Quaternion quaternion(Vector3(0, 1, 0), rotation);
Size2 scale = xform_2d.get_scale();
- transform.basis.set_quat_scale(quat,
+ transform.basis.set_quaternion_scale(quaternion,
Vector3(scale.x, 0, scale.y));
transform =
multi_mesh_instance->get_transform() * transform;
@@ -5423,31 +5357,22 @@ void GLTFDocument::_convert_mesh_to_gltf(Node *p_scene_parent, Ref<GLTFState> st
void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) {
Ref<GLTFNode> gltf_node = state->nodes[node_index];
+ if (gltf_node->skeleton >= 0) {
+ _generate_skeleton_bone_node(state, scene_parent, scene_root, node_index);
+ return;
+ }
+
Node3D *current_node = nullptr;
// Is our parent a skeleton
Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(scene_parent);
- if (gltf_node->skeleton >= 0) {
- Skeleton3D *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton;
+ const bool non_bone_parented_to_skeleton = active_skeleton;
- if (active_skeleton != skeleton) {
- ERR_FAIL_COND_MSG(active_skeleton != nullptr, "glTF: Generating scene detected direct parented Skeletons");
-
- // Add it to the scene if it has not already been added
- if (skeleton->get_parent() == nullptr) {
- scene_parent->add_child(skeleton);
- skeleton->set_owner(scene_root);
- }
- }
-
- active_skeleton = skeleton;
- current_node = skeleton;
- }
-
- // If we have an active skeleton, and the node is node skinned, we need to create a bone attachment
- if (current_node == nullptr && active_skeleton != nullptr && gltf_node->skin < 0) {
- BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index);
+ // skinned meshes must not be placed in a bone attachment.
+ if (non_bone_parented_to_skeleton && gltf_node->skin < 0) {
+ // Bone Attachment - Parent Case
+ BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent);
scene_parent->add_child(bone_attachment);
bone_attachment->set_owner(scene_root);
@@ -5461,7 +5386,86 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent
}
// We still have not managed to make a node
- if (current_node == nullptr) {
+ if (gltf_node->mesh >= 0) {
+ current_node = _generate_mesh_instance(state, scene_parent, node_index);
+ } else if (gltf_node->camera >= 0) {
+ current_node = _generate_camera(state, scene_parent, node_index);
+ } else if (gltf_node->light >= 0) {
+ current_node = _generate_light(state, scene_parent, node_index);
+ } else {
+ current_node = _generate_spatial(state, scene_parent, node_index);
+ }
+
+ scene_parent->add_child(current_node);
+ if (current_node != scene_root) {
+ current_node->set_owner(scene_root);
+ }
+ current_node->set_transform(gltf_node->xform);
+ current_node->set_name(gltf_node->get_name());
+
+ state->scene_nodes.insert(node_index, current_node);
+
+ for (int i = 0; i < gltf_node->children.size(); ++i) {
+ _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]);
+ }
+}
+
+void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) {
+ Ref<GLTFNode> gltf_node = state->nodes[node_index];
+
+ Node3D *current_node = nullptr;
+
+ Skeleton3D *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton;
+ // In this case, this node is already a bone in skeleton.
+ const bool is_skinned_mesh = (gltf_node->skin >= 0 && gltf_node->mesh >= 0);
+ const bool requires_extra_node = (gltf_node->mesh >= 0 || gltf_node->camera >= 0 || gltf_node->light >= 0);
+
+ Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(scene_parent);
+ if (active_skeleton != skeleton) {
+ if (active_skeleton) {
+ // Bone Attachment - Direct Parented Skeleton Case
+ BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent);
+
+ scene_parent->add_child(bone_attachment);
+ bone_attachment->set_owner(scene_root);
+
+ // There is no gltf_node that represent this, so just directly create a unique name
+ bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D"));
+
+ // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
+ // and attach it to the bone_attachment
+ scene_parent = bone_attachment;
+ WARN_PRINT(vformat("glTF: Generating scene detected direct parented Skeletons at node %d", node_index));
+ }
+
+ // Add it to the scene if it has not already been added
+ if (skeleton->get_parent() == nullptr) {
+ scene_parent->add_child(skeleton);
+ skeleton->set_owner(scene_root);
+ }
+ }
+
+ active_skeleton = skeleton;
+ current_node = skeleton;
+
+ if (requires_extra_node) {
+ // skinned meshes must not be placed in a bone attachment.
+ if (!is_skinned_mesh) {
+ // Bone Attachment - Same Node Case
+ BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, node_index);
+
+ scene_parent->add_child(bone_attachment);
+ bone_attachment->set_owner(scene_root);
+
+ // There is no gltf_node that represent this, so just directly create a unique name
+ bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D"));
+
+ // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
+ // and attach it to the bone_attachment
+ scene_parent = bone_attachment;
+ }
+
+ // We still have not managed to make a node
if (gltf_node->mesh >= 0) {
current_node = _generate_mesh_instance(state, scene_parent, node_index);
} else if (gltf_node->camera >= 0) {
@@ -5470,22 +5474,18 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent
current_node = _generate_light(state, scene_parent, node_index);
}
- if (!current_node) {
- current_node = _generate_spatial(state, scene_parent, node_index);
- }
-
scene_parent->add_child(current_node);
if (current_node != scene_root) {
current_node->set_owner(scene_root);
}
- current_node->set_transform(gltf_node->xform);
+ // Do not set transform here. Transform is already applied to our bone.
current_node->set_name(gltf_node->get_name());
}
state->scene_nodes.insert(node_index, current_node);
for (int i = 0; i < gltf_node->children.size(); ++i) {
- _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]);
+ _generate_scene_node(state, active_skeleton, scene_root, gltf_node->children[i]);
}
}
@@ -5516,24 +5516,24 @@ struct EditorSceneImporterGLTFInterpolate {
// thank you for existing, partial specialization
template <>
-struct EditorSceneImporterGLTFInterpolate<Quat> {
- Quat lerp(const Quat &a, const Quat &b, const float c) const {
- ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quat(), "The quaternion \"a\" must be normalized.");
- ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quat(), "The quaternion \"b\" must be normalized.");
+struct EditorSceneImporterGLTFInterpolate<Quaternion> {
+ Quaternion lerp(const Quaternion &a, const Quaternion &b, const float c) const {
+ ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quaternion(), "The quaternion \"a\" must be normalized.");
+ ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quaternion(), "The quaternion \"b\" must be normalized.");
return a.slerp(b, c).normalized();
}
- Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, const float c) {
- ERR_FAIL_COND_V_MSG(!p1.is_normalized(), Quat(), "The quaternion \"p1\" must be normalized.");
- ERR_FAIL_COND_V_MSG(!p2.is_normalized(), Quat(), "The quaternion \"p2\" must be normalized.");
+ Quaternion catmull_rom(const Quaternion &p0, const Quaternion &p1, const Quaternion &p2, const Quaternion &p3, const float c) {
+ ERR_FAIL_COND_V_MSG(!p1.is_normalized(), Quaternion(), "The quaternion \"p1\" must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p2.is_normalized(), Quaternion(), "The quaternion \"p2\" must be normalized.");
return p1.slerp(p2, c).normalized();
}
- Quat bezier(const Quat start, const Quat control_1, const Quat control_2, const Quat end, const float t) {
- ERR_FAIL_COND_V_MSG(!start.is_normalized(), Quat(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!end.is_normalized(), Quat(), "The end quaternion must be normalized.");
+ Quaternion bezier(const Quaternion start, const Quaternion control_1, const Quaternion control_2, const Quaternion end, const float t) {
+ ERR_FAIL_COND_V_MSG(!start.is_normalized(), Quaternion(), "The start quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!end.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
return start.slerp(end, t).normalized();
}
@@ -5626,28 +5626,30 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
for (Map<int, GLTFAnimation::Track>::Element *track_i = anim->get_tracks().front(); track_i; track_i = track_i->next()) {
const GLTFAnimation::Track &track = track_i->get();
- //need to find the path
+ //need to find the path: for skeletons, weight tracks will affect the mesh
NodePath node_path;
+ //for skeletons, transform tracks always affect bones
+ NodePath transform_node_path;
GLTFNodeIndex node_index = track_i->key();
- if (state->nodes[node_index]->fake_joint_parent >= 0) {
- // Should be same as parent
- node_index = state->nodes[node_index]->fake_joint_parent;
- }
const Ref<GLTFNode> gltf_node = state->nodes[track_i->key()];
+ Node *root = ap->get_parent();
+ ERR_FAIL_COND(root == nullptr);
+ Map<GLTFNodeIndex, Node *>::Element *node_element = state->scene_nodes.find(node_index);
+ ERR_CONTINUE_MSG(node_element == nullptr, vformat("Unable to find node %d for animation", node_index));
+ node_path = root->get_path_to(node_element->get());
+
if (gltf_node->skeleton >= 0) {
- const Skeleton3D *sk = Object::cast_to<Skeleton3D>(state->scene_nodes.find(node_index)->get());
+ const Skeleton3D *sk = state->skeletons[gltf_node->skeleton]->godot_skeleton;
ERR_FAIL_COND(sk == nullptr);
const String path = ap->get_parent()->get_path_to(sk);
const String bone = gltf_node->get_name();
- node_path = path + ":" + bone;
+ transform_node_path = path + ":" + bone;
} else {
- Node *root = ap->get_parent();
- Node *godot_node = state->scene_nodes.find(node_index)->get();
- node_path = root->get_path_to(godot_node);
+ transform_node_path = node_path;
}
for (int i = 0; i < track.rotation_track.times.size(); i++) {
@@ -5666,18 +5668,20 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
}
- if (track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) {
+ // Animated TRS properties will not affect a skinned mesh.
+ const bool transform_affects_skinned_mesh_instance = gltf_node->skeleton < 0 && gltf_node->skin >= 0;
+ if ((track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) && !transform_affects_skinned_mesh_instance) {
//make transform track
int track_idx = animation->get_track_count();
- animation->add_track(Animation::TYPE_TRANSFORM);
- animation->track_set_path(track_idx, node_path);
+ animation->add_track(Animation::TYPE_TRANSFORM3D);
+ animation->track_set_path(track_idx, transform_node_path);
//first determine animation length
const double increment = 1.0 / bake_fps;
double time = 0.0;
Vector3 base_pos;
- Quat base_rot;
+ Quaternion base_rot;
Vector3 base_scale = Vector3(1, 1, 1);
if (!track.rotation_track.values.size()) {
@@ -5695,7 +5699,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
bool last = false;
while (true) {
Vector3 pos = base_pos;
- Quat rot = base_rot;
+ Quaternion rot = base_rot;
Vector3 scale = base_scale;
if (track.translation_track.times.size()) {
@@ -5703,7 +5707,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
if (track.rotation_track.times.size()) {
- rot = _interpolate_track<Quat>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
+ rot = _interpolate_track<Quaternion>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
}
if (track.scale_track.times.size()) {
@@ -5711,15 +5715,15 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
if (gltf_node->skeleton >= 0) {
- Transform xform;
- xform.basis.set_quat_scale(rot, scale);
+ Transform3D xform;
+ xform.basis.set_quaternion_scale(rot, scale);
xform.origin = pos;
const Skeleton3D *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton;
const int bone_idx = skeleton->find_bone(gltf_node->get_name());
xform = skeleton->get_bone_rest(bone_idx).affine_inverse() * xform;
- rot = xform.basis.get_rotation_quat();
+ rot = xform.basis.get_rotation_quaternion();
rot.normalize();
scale = xform.basis.get_scale();
pos = xform.origin;
@@ -5804,9 +5808,9 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
}
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->get());
ERR_CONTINUE(!mi);
- Transform mi_xform = mi->get_transform();
+ Transform3D mi_xform = mi->get_transform();
node->scale = mi_xform.basis.get_scale();
- node->rotation = mi_xform.basis.get_rotation_quat();
+ node->rotation = mi_xform.basis.get_rotation_quaternion();
node->translation = mi_xform.origin;
Dictionary json_skin;
@@ -5868,9 +5872,9 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
String gltf_bone_name = _gen_unique_bone_name(state, skeleton_gltf_i, godot_bone_name);
joint_node->set_name(gltf_bone_name);
- Transform bone_rest_xform = skeleton->get_bone_rest(bone_index);
+ Transform3D bone_rest_xform = skeleton->get_bone_rest(bone_index);
joint_node->scale = bone_rest_xform.basis.get_scale();
- joint_node->rotation = bone_rest_xform.basis.get_rotation_quat();
+ joint_node->rotation = bone_rest_xform.basis.get_rotation_quaternion();
joint_node->translation = bone_rest_xform.origin;
joint_node->joint = true;
@@ -5975,13 +5979,15 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo
const GLTFSkinIndex skin_i = node->skin;
Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(node_i);
+ ERR_CONTINUE_MSG(mi_element == nullptr, vformat("Unable to find node %d", node_i));
+
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(mi_element->get());
- ERR_FAIL_COND(mi == nullptr);
+ ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to EditorSceneImporterMeshNode3D", node_i, mi_element->get()->get_class_name()));
const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton;
Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i];
Skeleton3D *skeleton = gltf_skeleton->godot_skeleton;
- ERR_FAIL_COND(skeleton == nullptr);
+ ERR_CONTINUE_MSG(skeleton == nullptr, vformat("Unable to find Skeleton for node %d skin %d", node_i, skin_i));
mi->get_parent()->remove_child(mi);
skeleton->add_child(mi);
@@ -5989,12 +5995,12 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo
mi->set_skin(state->skins.write[skin_i]->godot_skin);
mi->set_skeleton_path(mi->get_path_to(skeleton));
- mi->set_transform(Transform());
+ mi->set_transform(Transform3D());
}
}
}
-GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, Transform p_bone_rest, int32_t p_track_i, GLTFNodeIndex p_node_i) {
+GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, Transform3D p_bone_rest, int32_t p_track_i, GLTFNodeIndex p_node_i) {
Animation::InterpolationType interpolation = p_animation->track_get_interpolation_type(p_track_i);
GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
@@ -6014,7 +6020,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
times.write[key_i] = p_animation->track_get_key_time(p_track_i, key_i);
}
const float BAKE_FPS = 30.0f;
- if (track_type == Animation::TYPE_TRANSFORM) {
+ if (track_type == Animation::TYPE_TRANSFORM3D) {
p_track.translation_track.times = times;
p_track.translation_track.interpolation = gltf_interpolation;
p_track.rotation_track.times = times;
@@ -6030,16 +6036,16 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
p_track.rotation_track.interpolation = gltf_interpolation;
for (int32_t key_i = 0; key_i < key_count; key_i++) {
Vector3 translation;
- Quat rotation;
+ Quaternion rotation;
Vector3 scale;
Error err = p_animation->transform_track_get_key(p_track_i, key_i, &translation, &rotation, &scale);
ERR_CONTINUE(err != OK);
- Transform xform;
- xform.basis.set_quat_scale(rotation, scale);
+ Transform3D xform;
+ xform.basis.set_quaternion_scale(rotation, scale);
xform.origin = translation;
xform = p_bone_rest * xform;
p_track.translation_track.values.write[key_i] = xform.get_origin();
- p_track.rotation_track.values.write[key_i] = xform.basis.get_rotation_quat();
+ p_track.rotation_track.values.write[key_i] = xform.basis.get_rotation_quaternion();
p_track.scale_track.values.write[key_i] = xform.basis.get_scale();
}
} else if (path.find(":transform") != -1) {
@@ -6057,9 +6063,9 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
p_track.rotation_track.values.resize(key_count);
p_track.rotation_track.interpolation = gltf_interpolation;
for (int32_t key_i = 0; key_i < key_count; key_i++) {
- Transform xform = p_animation->track_get_key_value(p_track_i, key_i);
+ Transform3D xform = p_animation->track_get_key_value(p_track_i, key_i);
p_track.translation_track.values.write[key_i] = xform.get_origin();
- p_track.rotation_track.values.write[key_i] = xform.basis.get_rotation_quat();
+ p_track.rotation_track.values.write[key_i] = xform.basis.get_rotation_quaternion();
p_track.scale_track.values.write[key_i] = xform.basis.get_scale();
}
} else if (track_type == Animation::TYPE_VALUE) {
@@ -6071,7 +6077,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
p_track.rotation_track.interpolation = gltf_interpolation;
for (int32_t key_i = 0; key_i < key_count; key_i++) {
- Quat rotation_track = p_animation->track_get_key_value(p_track_i, key_i);
+ Quaternion rotation_track = p_animation->track_get_key_value(p_track_i, key_i);
p_track.rotation_track.values.write[key_i] = rotation_track;
}
} else if (path.find(":translation") != -1) {
@@ -6098,7 +6104,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
rotation_radian.x = Math::deg2rad(rotation_degrees.x);
rotation_radian.y = Math::deg2rad(rotation_degrees.y);
rotation_radian.z = Math::deg2rad(rotation_degrees.z);
- p_track.rotation_track.values.write[key_i] = Quat(rotation_radian);
+ p_track.rotation_track.values.write[key_i] = Quaternion(rotation_radian);
}
} else if (path.find(":scale") != -1) {
p_track.scale_track.times = times;
@@ -6204,7 +6210,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (translation_track_i) {
track = translation_track_i->get();
}
- track = _convert_animation_track(state, track, animation, Transform(), track_i, node_index);
+ track = _convert_animation_track(state, track, animation, Transform3D(), track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
}
}
@@ -6220,7 +6226,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (rotation_degree_track_i) {
track = rotation_degree_track_i->get();
}
- track = _convert_animation_track(state, track, animation, Transform(), track_i, node_index);
+ track = _convert_animation_track(state, track, animation, Transform3D(), track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
}
}
@@ -6236,7 +6242,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (scale_track_i) {
track = scale_track_i->get();
}
- track = _convert_animation_track(state, track, animation, Transform(), track_i, node_index);
+ track = _convert_animation_track(state, track, animation, Transform3D(), track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
}
}
@@ -6247,7 +6253,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
for (Map<GLTFNodeIndex, Node *>::Element *transform_track_i = state->scene_nodes.front(); transform_track_i; transform_track_i = transform_track_i->next()) {
if (transform_track_i->get() == node) {
GLTFAnimation::Track track;
- track = _convert_animation_track(state, track, animation, Transform(), track_i, transform_track_i->key());
+ track = _convert_animation_track(state, track, animation, Transform3D(), track_i, transform_track_i->key());
gltf_animation->get_tracks().insert(transform_track_i->key(), track);
}
}
@@ -6335,7 +6341,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
Ref<GLTFSkeleton> skeleton_gltf = state->skeletons[skeleton_gltf_i];
int32_t bone = skeleton->find_bone(suffix);
ERR_CONTINUE(bone == -1);
- Transform xform = skeleton->get_bone_rest(bone);
+ Transform3D xform = skeleton->get_bone_rest(bone);
if (!skeleton_gltf->godot_bone_node.has(bone)) {
continue;
}
@@ -6362,7 +6368,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
if (node_track_i) {
track = node_track_i->get();
}
- track = _convert_animation_track(state, track, animation, Transform(), track_i, node_index);
+ track = _convert_animation_track(state, track, animation, Transform3D(), track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
break;
}
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index bda1ce87d6..514373c4f0 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -205,7 +205,7 @@ private:
Vector<Color> _decode_accessor_as_color(Ref<GLTFState> state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Quat> _decode_accessor_as_quat(Ref<GLTFState> state,
+ Vector<Quaternion> _decode_accessor_as_quaternion(Ref<GLTFState> state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
Vector<Transform2D> _decode_accessor_as_xform2d(Ref<GLTFState> state,
@@ -214,7 +214,7 @@ private:
Vector<Basis> _decode_accessor_as_basis(Ref<GLTFState> state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
- Vector<Transform> _decode_accessor_as_xform(Ref<GLTFState> state,
+ Vector<Transform3D> _decode_accessor_as_xform(Ref<GLTFState> state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
Error _parse_meshes(Ref<GLTFState> state);
@@ -260,11 +260,12 @@ private:
Error _serialize_animations(Ref<GLTFState> state);
BoneAttachment3D *_generate_bone_attachment(Ref<GLTFState> state,
Skeleton3D *skeleton,
- const GLTFNodeIndex node_index);
+ const GLTFNodeIndex node_index,
+ const GLTFNodeIndex bone_index);
EditorSceneImporterMeshNode3D *_generate_mesh_instance(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index);
Camera3D *_generate_camera(Ref<GLTFState> state, Node *scene_parent,
const GLTFNodeIndex node_index);
- Light3D *_generate_light(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index);
+ Node3D *_generate_light(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index);
Node3D *_generate_spatial(Ref<GLTFState> state, Node *scene_parent,
const GLTFNodeIndex node_index);
void _assign_scene_names(Ref<GLTFState> state);
@@ -272,8 +273,8 @@ private:
T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values,
const float p_time,
const GLTFAnimation::Interpolation p_interp);
- GLTFAccessorIndex _encode_accessor_as_quats(Ref<GLTFState> state,
- const Vector<Quat> p_attribs,
+ GLTFAccessorIndex _encode_accessor_as_quaternions(Ref<GLTFState> state,
+ const Vector<Quaternion> p_attribs,
const bool p_for_vertex);
GLTFAccessorIndex _encode_accessor_as_weights(Ref<GLTFState> state,
const Vector<Color> p_attribs,
@@ -316,7 +317,7 @@ private:
const Vector<int32_t> p_attribs,
const bool p_for_vertex);
GLTFAccessorIndex _encode_accessor_as_xform(Ref<GLTFState> state,
- const Vector<Transform> p_attribs,
+ const Vector<Transform3D> p_attribs,
const bool p_for_vertex);
Error _encode_buffer_view(Ref<GLTFState> state, const double *src,
const int count, const GLTFType type,
@@ -332,7 +333,7 @@ private:
String interpolation_to_string(const GLTFAnimation::Interpolation p_interp);
GLTFAnimation::Track _convert_animation_track(Ref<GLTFState> state,
GLTFAnimation::Track p_track,
- Ref<Animation> p_animation, Transform p_bone_rest,
+ Ref<Animation> p_animation, Transform3D p_bone_rest,
int32_t p_track_i,
GLTFNodeIndex p_node_i);
Error _encode_buffer_bins(Ref<GLTFState> state, const String &p_path);
@@ -365,6 +366,7 @@ public:
void _generate_scene_node(Ref<GLTFState> state, Node *scene_parent,
Node3D *scene_root,
const GLTFNodeIndex node_index);
+ void _generate_skeleton_bone_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index);
void _import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
const GLTFAnimationIndex index, const int bake_fps);
GLTFMeshIndex _convert_mesh_instance(Ref<GLTFState> state,
diff --git a/modules/gltf/gltf_node.cpp b/modules/gltf/gltf_node.cpp
index 777c6fbd9a..5db7ad66c3 100644
--- a/modules/gltf/gltf_node.cpp
+++ b/modules/gltf/gltf_node.cpp
@@ -55,24 +55,21 @@ void GLTFNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &GLTFNode::set_scale);
ClassDB::bind_method(D_METHOD("get_children"), &GLTFNode::get_children);
ClassDB::bind_method(D_METHOD("set_children", "children"), &GLTFNode::set_children);
- ClassDB::bind_method(D_METHOD("get_fake_joint_parent"), &GLTFNode::get_fake_joint_parent);
- ClassDB::bind_method(D_METHOD("set_fake_joint_parent", "fake_joint_parent"), &GLTFNode::set_fake_joint_parent);
ClassDB::bind_method(D_METHOD("get_light"), &GLTFNode::get_light);
ClassDB::bind_method(D_METHOD("set_light", "light"), &GLTFNode::set_light);
ADD_PROPERTY(PropertyInfo(Variant::INT, "parent"), "set_parent", "get_parent"); // GLTFNodeIndex
ADD_PROPERTY(PropertyInfo(Variant::INT, "height"), "set_height", "get_height"); // int
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "xform"), "set_xform", "get_xform"); // Transform
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "xform"), "set_xform", "get_xform"); // Transform3D
ADD_PROPERTY(PropertyInfo(Variant::INT, "mesh"), "set_mesh", "get_mesh"); // GLTFMeshIndex
ADD_PROPERTY(PropertyInfo(Variant::INT, "camera"), "set_camera", "get_camera"); // GLTFCameraIndex
ADD_PROPERTY(PropertyInfo(Variant::INT, "skin"), "set_skin", "get_skin"); // GLTFSkinIndex
ADD_PROPERTY(PropertyInfo(Variant::INT, "skeleton"), "set_skeleton", "get_skeleton"); // GLTFSkeletonIndex
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "joint"), "set_joint", "get_joint"); // bool
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation"), "set_translation", "get_translation"); // Vector3
- ADD_PROPERTY(PropertyInfo(Variant::QUAT, "rotation"), "set_rotation", "get_rotation"); // Quat
+ ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "rotation"), "set_rotation", "get_rotation"); // Quaternion
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale"), "set_scale", "get_scale"); // Vector3
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "children"), "set_children", "get_children"); // Vector<int>
- ADD_PROPERTY(PropertyInfo(Variant::INT, "fake_joint_parent"), "set_fake_joint_parent", "get_fake_joint_parent"); // GLTFNodeIndex
ADD_PROPERTY(PropertyInfo(Variant::INT, "light"), "set_light", "get_light"); // GLTFLightIndex
}
@@ -92,11 +89,11 @@ void GLTFNode::set_height(int p_height) {
height = p_height;
}
-Transform GLTFNode::get_xform() {
+Transform3D GLTFNode::get_xform() {
return xform;
}
-void GLTFNode::set_xform(Transform p_xform) {
+void GLTFNode::set_xform(Transform3D p_xform) {
xform = p_xform;
}
@@ -148,11 +145,11 @@ void GLTFNode::set_translation(Vector3 p_translation) {
translation = p_translation;
}
-Quat GLTFNode::get_rotation() {
+Quaternion GLTFNode::get_rotation() {
return rotation;
}
-void GLTFNode::set_rotation(Quat p_rotation) {
+void GLTFNode::set_rotation(Quaternion p_rotation) {
rotation = p_rotation;
}
@@ -172,14 +169,6 @@ void GLTFNode::set_children(Vector<int> p_children) {
children = p_children;
}
-GLTFNodeIndex GLTFNode::get_fake_joint_parent() {
- return fake_joint_parent;
-}
-
-void GLTFNode::set_fake_joint_parent(GLTFNodeIndex p_fake_joint_parent) {
- fake_joint_parent = p_fake_joint_parent;
-}
-
GLTFLightIndex GLTFNode::get_light() {
return light;
}
diff --git a/modules/gltf/gltf_node.h b/modules/gltf/gltf_node.h
index ce8aff8944..378b6da8bf 100644
--- a/modules/gltf/gltf_node.h
+++ b/modules/gltf/gltf_node.h
@@ -43,17 +43,16 @@ private:
// matrices need to be transformed to this
GLTFNodeIndex parent = -1;
int height = -1;
- Transform xform;
+ Transform3D xform;
GLTFMeshIndex mesh = -1;
GLTFCameraIndex camera = -1;
GLTFSkinIndex skin = -1;
GLTFSkeletonIndex skeleton = -1;
bool joint = false;
Vector3 translation;
- Quat rotation;
+ Quaternion rotation;
Vector3 scale = Vector3(1, 1, 1);
Vector<int> children;
- GLTFNodeIndex fake_joint_parent = -1;
GLTFLightIndex light = -1;
protected:
@@ -66,8 +65,8 @@ public:
int get_height();
void set_height(int p_height);
- Transform get_xform();
- void set_xform(Transform p_xform);
+ Transform3D get_xform();
+ void set_xform(Transform3D p_xform);
GLTFMeshIndex get_mesh();
void set_mesh(GLTFMeshIndex p_mesh);
@@ -87,8 +86,8 @@ public:
Vector3 get_translation();
void set_translation(Vector3 p_translation);
- Quat get_rotation();
- void set_rotation(Quat p_rotation);
+ Quaternion get_rotation();
+ void set_rotation(Quaternion p_rotation);
Vector3 get_scale();
void set_scale(Vector3 p_scale);
@@ -96,9 +95,6 @@ public:
Vector<int> get_children();
void set_children(Vector<int> p_children);
- GLTFNodeIndex get_fake_joint_parent();
- void set_fake_joint_parent(GLTFNodeIndex p_fake_joint_parent);
-
GLTFLightIndex get_light();
void set_light(GLTFLightIndex p_light);
};
diff --git a/modules/gltf/gltf_skin.cpp b/modules/gltf/gltf_skin.cpp
index 5a61e5778c..5cf17135ac 100644
--- a/modules/gltf/gltf_skin.cpp
+++ b/modules/gltf/gltf_skin.cpp
@@ -54,7 +54,7 @@ void GLTFSkin::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "skin_root"), "set_skin_root", "get_skin_root"); // GLTFNodeIndex
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "joints_original"), "set_joints_original", "get_joints_original"); // Vector<GLTFNodeIndex>
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "inverse_binds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_inverse_binds", "get_inverse_binds"); // Vector<Transform>
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "inverse_binds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_inverse_binds", "get_inverse_binds"); // Vector<Transform3D>
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "joints"), "set_joints", "get_joints"); // Vector<GLTFNodeIndex>
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "non_joints"), "set_non_joints", "get_non_joints"); // Vector<GLTFNodeIndex>
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "roots"), "set_roots", "get_roots"); // Vector<GLTFNodeIndex>
diff --git a/modules/gltf/gltf_skin.h b/modules/gltf/gltf_skin.h
index 7cc09d85bc..e32e2d397c 100644
--- a/modules/gltf/gltf_skin.h
+++ b/modules/gltf/gltf_skin.h
@@ -43,7 +43,7 @@ private:
GLTFNodeIndex skin_root = -1;
Vector<GLTFNodeIndex> joints_original;
- Vector<Transform> inverse_binds;
+ Vector<Transform3D> inverse_binds;
// Note: joints + non_joints should form a complete subtree, or subtrees
// with a common parent
diff --git a/modules/gridmap/config.py b/modules/gridmap/config.py
index a6319fe1ea..720401b92d 100644
--- a/modules/gridmap/config.py
+++ b/modules/gridmap/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return True
+ return not env["disable_3d"]
def configure(env):
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 9b6fa138e5..fb0a2c9953 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -41,7 +41,7 @@
<return type="Array">
</return>
<description>
- Returns an array of [ArrayMesh]es and [Transform] references of all bake meshes that exist within the current GridMap.
+ Returns an array of [ArrayMesh]es and [Transform3D] references of all bake meshes that exist within the current GridMap.
</description>
</method>
<method name="get_cell_item" qualifiers="const">
@@ -84,7 +84,7 @@
<return type="Array">
</return>
<description>
- Returns an array of [Transform] and [Mesh] references corresponding to the non-empty cells in the grid. The transforms are specified in world space.
+ Returns an array of [Transform3D] and [Mesh] references corresponding to the non-empty cells in the grid. The transforms are specified in world space.
</description>
</method>
<method name="get_used_cells" qualifiers="const">
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index eaceaac33c..45af59622f 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -446,7 +446,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
* and set said multimesh bounding box to one containing all cells which have this item
*/
- Map<int, List<Pair<Transform, IndexKey>>> multimesh_items;
+ Map<int, List<Pair<Transform3D, IndexKey>>> multimesh_items;
for (Set<IndexKey>::Element *E = g.cells.front(); E; E = E->next()) {
ERR_CONTINUE(!cell_map.has(E->get()));
@@ -459,7 +459,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
Vector3 cellpos = Vector3(E->get().x, E->get().y, E->get().z);
Vector3 ofs = _get_offset();
- Transform xform;
+ Transform3D xform;
xform.basis.set_orthogonal_index(c.rot);
xform.set_origin(cellpos * cell_size + ofs);
@@ -467,10 +467,10 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
if (baked_meshes.size() == 0) {
if (mesh_library->get_item_mesh(c.item).is_valid()) {
if (!multimesh_items.has(c.item)) {
- multimesh_items[c.item] = List<Pair<Transform, IndexKey>>();
+ multimesh_items[c.item] = List<Pair<Transform3D, IndexKey>>();
}
- Pair<Transform, IndexKey> p;
+ Pair<Transform3D, IndexKey> p;
p.first = xform;
p.second = E->get();
multimesh_items[c.item].push_back(p);
@@ -511,7 +511,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
//update multimeshes, only if not baked
if (baked_meshes.size() == 0) {
- for (Map<int, List<Pair<Transform, IndexKey>>>::Element *E = multimesh_items.front(); E; E = E->next()) {
+ for (Map<int, List<Pair<Transform3D, IndexKey>>>::Element *E = multimesh_items.front(); E; E = E->next()) {
Octant::MultimeshInstance mmi;
RID mm = RS::get_singleton()->multimesh_create();
@@ -519,7 +519,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
RS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid());
int idx = 0;
- for (List<Pair<Transform, IndexKey>>::Element *F = E->get().front(); F; F = F->next()) {
+ for (List<Pair<Transform3D, IndexKey>>::Element *F = E->get().front(); F; F = F->next()) {
RS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first);
#ifdef TOOLS_ENABLED
@@ -672,7 +672,7 @@ void GridMap::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- Transform new_xform = get_global_transform();
+ Transform3D new_xform = get_global_transform();
if (new_xform == last_transform) {
break;
}
@@ -686,7 +686,6 @@ void GridMap::_notification(int p_what) {
for (int i = 0; i < baked_meshes.size(); i++) {
RS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform());
}
-
} break;
case NOTIFICATION_EXIT_WORLD: {
for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) {
@@ -934,7 +933,7 @@ Array GridMap::get_meshes() {
Vector3 cellpos = Vector3(ik.x, ik.y, ik.z);
- Transform xform;
+ Transform3D xform;
xform.basis.set_orthogonal_index(E->get().rot);
@@ -988,7 +987,7 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe
Vector3 cellpos = Vector3(key.x, key.y, key.z);
Vector3 ofs = _get_offset();
- Transform xform;
+ Transform3D xform;
xform.basis.set_orthogonal_index(E->get().rot);
xform.set_origin(cellpos * cell_size + ofs);
@@ -1057,7 +1056,7 @@ Array GridMap::get_bake_meshes() {
Array arr;
for (int i = 0; i < baked_meshes.size(); i++) {
arr.push_back(baked_meshes[i].mesh);
- arr.push_back(Transform());
+ arr.push_back(Transform3D());
}
return arr;
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 4c04d492f7..8cd82e1f4c 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -89,7 +89,7 @@ class GridMap : public Node3D {
struct Octant {
struct NavMesh {
RID region;
- Transform xform;
+ Transform3D xform;
};
struct MultimeshInstance {
@@ -97,7 +97,7 @@ class GridMap : public Node3D {
RID multimesh;
struct Item {
int index = 0;
- Transform transform;
+ Transform3D transform;
IndexKey key;
};
@@ -137,7 +137,7 @@ class GridMap : public Node3D {
bool bake_navigation = false;
uint32_t navigation_layers = 1;
- Transform last_transform;
+ Transform3D last_transform;
bool _in_tree = false;
Vector3 cell_size = Vector3(2, 2, 2);
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 74ae45a46e..a47ed6652d 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -255,7 +255,7 @@ void GridMapEditor::_menu_option(int p_option) {
}
void GridMapEditor::_update_cursor_transform() {
- cursor_transform = Transform();
+ cursor_transform = Transform3D();
cursor_transform.origin = cursor_origin;
cursor_transform.basis.set_orthogonal_index(cursor_rot);
cursor_transform.basis *= node->get_cell_scale();
@@ -268,7 +268,7 @@ void GridMapEditor::_update_cursor_transform() {
}
void GridMapEditor::_update_selection_transform() {
- Transform xf_zero;
+ Transform3D xf_zero;
xf_zero.basis.set_zero();
if (!selection.active) {
@@ -279,7 +279,7 @@ void GridMapEditor::_update_selection_transform() {
return;
}
- Transform xf;
+ Transform3D xf;
xf.scale((Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size());
xf.origin = selection.begin * node->get_cell_size();
@@ -297,7 +297,7 @@ void GridMapEditor::_update_selection_transform() {
scale *= node->get_cell_size();
position *= node->get_cell_size();
- Transform xf2;
+ Transform3D xf2;
xf2.basis.scale(scale);
xf2.origin = position;
@@ -362,7 +362,7 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b
Camera3D *camera = p_camera;
Vector3 from = camera->project_ray_origin(p_point);
Vector3 normal = camera->project_ray_normal(p_point);
- Transform local_xform = node->get_global_transform().affine_inverse();
+ Transform3D local_xform = node->get_global_transform().affine_inverse();
Vector<Plane> planes = camera->get_frustum();
from = local_xform.xform(from);
normal = local_xform.basis.xform(normal).normalized();
@@ -540,7 +540,7 @@ void GridMapEditor::_set_clipboard_data() {
void GridMapEditor::_update_paste_indicator() {
if (input_action != INPUT_PASTE) {
- Transform xf;
+ Transform3D xf;
xf.basis.set_zero();
RenderingServer::get_singleton()->instance_set_transform(paste_instance, xf);
return;
@@ -548,7 +548,7 @@ void GridMapEditor::_update_paste_indicator() {
Vector3 center = 0.5 * Vector3(real_t(node->get_center_x()), real_t(node->get_center_y()), real_t(node->get_center_z()));
Vector3 scale = (Vector3(1, 1, 1) + (paste_indicator.end - paste_indicator.begin)) * node->get_cell_size();
- Transform xf;
+ Transform3D xf;
xf.scale(scale);
xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size();
Basis rot;
@@ -561,7 +561,7 @@ void GridMapEditor::_update_paste_indicator() {
for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) {
ClipboardItem &item = E->get();
- xf = Transform();
+ xf = Transform3D();
xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size();
xf.basis = rot * xf.basis;
xf.translate(item.grid_offset * node->get_cell_size());
@@ -615,13 +615,13 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && (mb->get_command() || mb->get_shift())) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && (mb->is_command_pressed() || mb->is_shift_pressed())) {
if (mb->is_pressed()) {
floor->set_value(floor->get_value() + mb->get_factor());
}
return true; // Eaten.
- } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && (mb->get_command() || mb->get_shift())) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && (mb->is_command_pressed() || mb->is_shift_pressed())) {
if (mb->is_pressed()) {
floor->set_value(floor->get_value() - mb->get_factor());
}
@@ -630,7 +630,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
if (mb->is_pressed()) {
Node3DEditorViewport::NavigationScheme nav_scheme = (Node3DEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
- if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->get_alt()) {
+ if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->is_alt_pressed()) {
input_action = INPUT_NONE;
} else if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
bool can_edit = (node && node->get_mesh_library().is_valid());
@@ -638,10 +638,10 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
_do_paste();
input_action = INPUT_NONE;
_update_paste_indicator();
- } else if (mb->get_shift() && can_edit) {
+ } else if (mb->is_shift_pressed() && can_edit) {
input_action = INPUT_SELECT;
last_selection = selection;
- } else if (mb->get_command() && can_edit) {
+ } else if (mb->is_command_pressed() && can_edit) {
input_action = INPUT_PICK;
} else {
input_action = INPUT_PAINT;
@@ -732,7 +732,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
}
}
- if (k->get_shift() && selection.active && input_action != INPUT_PASTE) {
+ if (k->is_shift_pressed() && selection.active && input_action != INPUT_PASTE) {
if (k->get_keycode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) {
selection.click[edit_axis]--;
_validate_selection();
@@ -749,7 +749,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid()) {
- if (pan_gesture->get_alt() && (pan_gesture->get_command() || pan_gesture->get_shift())) {
+ if (pan_gesture->is_alt_pressed() && (pan_gesture->is_command_pressed() || pan_gesture->is_shift_pressed())) {
const real_t delta = pan_gesture->get_delta().y * 0.5;
accumulated_floor_delta += delta;
int step = 0;
@@ -810,7 +810,7 @@ void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) {
const Ref<InputEventMouseButton> mb = p_ie;
// Zoom in/out using Ctrl + mouse wheel
- if (mb.is_valid() && mb->is_pressed() && mb->get_command()) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed()) {
if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
size_slider->set_value(size_slider->get_value() + 0.2);
}
@@ -1068,7 +1068,7 @@ void GridMapEditor::_notification(int p_what) {
return;
}
- Transform xf = node->get_global_transform();
+ Transform3D xf = node->get_global_transform();
if (xf != grid_xform) {
for (int i = 0; i < 3; i++) {
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 6c7f0bedf6..0e29c88d26 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -95,8 +95,8 @@ class GridMapEditor : public VBoxContainer {
ClipMode clip_mode = CLIP_DISABLED;
bool lock_view = false;
- Transform grid_xform;
- Transform edit_grid_xform;
+ Transform3D grid_xform;
+ Transform3D edit_grid_xform;
Vector3::Axis edit_axis;
int edit_floor[3];
Vector3 grid_ofs;
@@ -146,7 +146,7 @@ class GridMapEditor : public VBoxContainer {
PasteIndicator paste_indicator;
bool cursor_visible = false;
- Transform cursor_transform;
+ Transform3D cursor_transform;
Vector3 cursor_origin;
diff --git a/modules/gridmap/icons/GridMap.svg b/modules/gridmap/icons/GridMap.svg
index 7a36fd888c..e208257855 100644
--- a/modules/gridmap/icons/GridMap.svg
+++ b/modules/gridmap/icons/GridMap.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1-6 3v8l6 3 6-3v-2l-2-1-4 2-2-1v-4l2-1v-2l2-1zm4 2-2 1v2l2 1 2-1v-2z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1-6 3v8l6 3 6-3v-2l-2-1-4 2-2-1v-4l2-1v-2l2-1zm4 2-2 1v2l2 1 2-1v-2z" fill="#fc7f7f" fill-opacity=".99608"/></svg>
diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp
index 7daf6a3a57..d237544d66 100644
--- a/modules/jpg/image_loader_jpegd.cpp
+++ b/modules/jpg/image_loader_jpegd.cpp
@@ -105,7 +105,7 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p
Error ImageLoaderJPG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
Vector<uint8_t> src_image;
- int src_image_len = f->get_len();
+ uint64_t src_image_len = f->get_length();
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
src_image.resize(src_image_len);
diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp
index 987306af2a..3cd2da3d85 100644
--- a/modules/mbedtls/crypto_mbedtls.cpp
+++ b/modules/mbedtls/crypto_mbedtls.cpp
@@ -30,7 +30,7 @@
#include "crypto_mbedtls.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
@@ -58,7 +58,7 @@ Error CryptoKeyMbedTLS::load(String p_path, bool p_public_only) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot open CryptoKeyMbedTLS file '" + p_path + "'.");
- int flen = f->get_len();
+ uint64_t flen = f->get_length();
out.resize(flen + 1);
f->get_buffer(out.ptrw(), flen);
out.write[flen] = 0; // string terminator
@@ -146,7 +146,7 @@ Error X509CertificateMbedTLS::load(String p_path) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot open X509CertificateMbedTLS file '" + p_path + "'.");
- int flen = f->get_len();
+ uint64_t flen = f->get_length();
out.resize(flen + 1);
f->get_buffer(out.ptrw(), flen);
out.write[flen] = 0; // string terminator
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp
index d77d946a77..11c9f64e21 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.cpp
+++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp
@@ -31,8 +31,8 @@
#include "packet_peer_mbed_dtls.h"
#include "mbedtls/platform_util.h"
+#include "core/io/file_access.h"
#include "core/io/stream_peer_ssl.h"
-#include "core/os/file_access.h"
int PacketPeerMbedDTLS::bio_send(void *ctx, const unsigned char *buf, size_t len) {
if (buf == nullptr || len <= 0) {
diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/ssl_context_mbedtls.h
index 30632018a8..1b55a54a10 100644
--- a/modules/mbedtls/ssl_context_mbedtls.h
+++ b/modules/mbedtls/ssl_context_mbedtls.h
@@ -33,9 +33,9 @@
#include "crypto_mbedtls.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include <mbedtls/config.h>
#include <mbedtls/ctr_drbg.h>
@@ -46,7 +46,7 @@
class SSLContextMbedTLS;
-class CookieContextMbedTLS : public Reference {
+class CookieContextMbedTLS : public RefCounted {
friend class SSLContextMbedTLS;
protected:
@@ -63,7 +63,7 @@ public:
~CookieContextMbedTLS();
};
-class SSLContextMbedTLS : public Reference {
+class SSLContextMbedTLS : public RefCounted {
protected:
bool inited = false;
diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp
index 8e40451806..bc72b04fa4 100644
--- a/modules/mbedtls/stream_peer_mbedtls.cpp
+++ b/modules/mbedtls/stream_peer_mbedtls.cpp
@@ -30,8 +30,8 @@
#include "stream_peer_mbedtls.h"
+#include "core/io/file_access.h"
#include "core/io/stream_peer_tcp.h"
-#include "core/os/file_access.h"
int StreamPeerMbedTLS::bio_send(void *ctx, const unsigned char *buf, size_t len) {
if (buf == nullptr || len <= 0) {
diff --git a/modules/meshoptimizer/config.py b/modules/meshoptimizer/config.py
index 82e4e43397..b7e69569b9 100644
--- a/modules/meshoptimizer/config.py
+++ b/modules/meshoptimizer/config.py
@@ -1,6 +1,6 @@
def can_build(env, platform):
# Having this on release by default, it's small and a lot of users like to do procedural stuff
- return True
+ return not env["disable_3d"]
def configure(env):
diff --git a/modules/meshoptimizer/register_types.cpp b/modules/meshoptimizer/register_types.cpp
index a03310f518..77cc82a4e2 100644
--- a/modules/meshoptimizer/register_types.cpp
+++ b/modules/meshoptimizer/register_types.cpp
@@ -35,6 +35,7 @@
void register_meshoptimizer_types() {
SurfaceTool::optimize_vertex_cache_func = meshopt_optimizeVertexCache;
SurfaceTool::simplify_func = meshopt_simplify;
+ SurfaceTool::simplify_with_attrib_func = meshopt_simplifyWithAttributes;
SurfaceTool::simplify_scale_func = meshopt_simplifyScale;
SurfaceTool::simplify_sloppy_func = meshopt_simplifySloppy;
}
diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp
index 24ec206191..600bbe9bb5 100644
--- a/modules/minimp3/audio_stream_mp3.cpp
+++ b/modules/minimp3/audio_stream_mp3.cpp
@@ -35,7 +35,7 @@
#include "audio_stream_mp3.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
void AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND(!active);
diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp
index afd26fb79e..dc16125726 100644
--- a/modules/minimp3/resource_importer_mp3.cpp
+++ b/modules/minimp3/resource_importer_mp3.cpp
@@ -30,8 +30,8 @@
#include "resource_importer_mp3.h"
+#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "scene/resources/texture.h"
String ResourceImporterMP3::get_importer_name() const {
@@ -79,7 +79,7 @@ Error ResourceImporterMP3::import(const String &p_source_file, const String &p_s
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
- size_t len = f->get_len();
+ uint64_t len = f->get_length();
Vector<uint8_t> data;
data.resize(len);
diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py
index ee401c1a2a..f6b64fb690 100644
--- a/modules/mobile_vr/config.py
+++ b/modules/mobile_vr/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return True
+ return not env["disable_3d"]
def configure(env):
diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp
index 5140cfbbaf..590b95ab79 100644
--- a/modules/mobile_vr/mobile_vr_interface.cpp
+++ b/modules/mobile_vr/mobile_vr_interface.cpp
@@ -185,8 +185,8 @@ void MobileVRInterface::set_position_from_sensors() {
// if you have a gyro + accelerometer that combo tends to be better than combining all three but without a gyro you need the magnetometer..
if (has_magneto && has_grav && !has_gyro) {
// convert to quaternions, easier to smooth those out
- Quat transform_quat(orientation);
- Quat acc_mag_quat(combine_acc_mag(grav, magneto));
+ Quaternion transform_quat(orientation);
+ Quaternion acc_mag_quat(combine_acc_mag(grav, magneto));
transform_quat = transform_quat.slerp(acc_mag_quat, 0.1);
orientation = Basis(transform_quat);
@@ -300,9 +300,9 @@ real_t MobileVRInterface::get_k2() const {
return k2;
};
-bool MobileVRInterface::is_stereo() {
+uint32_t MobileVRInterface::get_view_count() {
// needs stereo...
- return true;
+ return 2;
};
bool MobileVRInterface::is_initialized() const {
@@ -361,10 +361,32 @@ Size2 MobileVRInterface::get_render_targetsize() {
return target_size;
};
-Transform MobileVRInterface::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {
+Transform3D MobileVRInterface::get_camera_transform() {
_THREAD_SAFE_METHOD_
- Transform transform_for_eye;
+ Transform3D transform_for_eye;
+
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, transform_for_eye);
+
+ if (initialized) {
+ float world_scale = xr_server->get_world_scale();
+
+ // just scale our origin point of our transform
+ Transform3D hmd_transform;
+ hmd_transform.basis = orientation;
+ hmd_transform.origin = Vector3(0.0, eye_height * world_scale, 0.0);
+
+ transform_for_eye = (xr_server->get_reference_frame()) * hmd_transform;
+ }
+
+ return transform_for_eye;
+};
+
+Transform3D MobileVRInterface::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
+ _THREAD_SAFE_METHOD_
+
+ Transform3D transform_for_eye;
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, transform_for_eye);
@@ -374,16 +396,16 @@ Transform MobileVRInterface::get_transform_for_eye(XRInterface::Eyes p_eye, cons
// we don't need to check for the existence of our HMD, doesn't affect our values...
// note * 0.01 to convert cm to m and * 0.5 as we're moving half in each direction...
- if (p_eye == XRInterface::EYE_LEFT) {
+ if (p_view == 0) {
transform_for_eye.origin.x = -(intraocular_dist * 0.01 * 0.5 * world_scale);
- } else if (p_eye == XRInterface::EYE_RIGHT) {
+ } else if (p_view == 1) {
transform_for_eye.origin.x = intraocular_dist * 0.01 * 0.5 * world_scale;
} else {
- // for mono we don't reposition, we want our center position.
+ // should not have any other values..
};
// just scale our origin point of our transform
- Transform hmd_transform;
+ Transform3D hmd_transform;
hmd_transform.basis = orientation;
hmd_transform.origin = Vector3(0.0, eye_height * world_scale, 0.0);
@@ -396,21 +418,13 @@ Transform MobileVRInterface::get_transform_for_eye(XRInterface::Eyes p_eye, cons
return transform_for_eye;
};
-CameraMatrix MobileVRInterface::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+CameraMatrix MobileVRInterface::get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
_THREAD_SAFE_METHOD_
CameraMatrix eye;
- if (p_eye == XRInterface::EYE_MONO) {
- ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real camera's properties
- // which probably means implementing a specific class for iOS and Android. For now this is purely here as an example.
- // Note also that if you use a normal viewport with AR/VR turned off you can still use the tracker output of this interface
- // to position a stock standard Godot camera and have control over this.
- // This will make more sense when we implement ARkit on iOS (probably a separate interface).
- eye.set_perspective(60.0, p_aspect, p_z_near, p_z_far, false);
- } else {
- eye.set_for_hmd(p_eye == XRInterface::EYE_LEFT ? 1 : 2, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far);
- };
+ aspect = p_aspect;
+ eye.set_for_hmd(p_view + 1, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far);
return eye;
};
@@ -440,6 +454,45 @@ void MobileVRInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_tar
eye_center.y = 0.0;
}
+Vector<BlitToScreen> MobileVRInterface::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+ _THREAD_SAFE_METHOD_
+
+ Vector<BlitToScreen> blit_to_screen;
+
+ // We must have a valid render target
+ ERR_FAIL_COND_V(!p_render_target.is_valid(), blit_to_screen);
+
+ // Because we are rendering to our device we must use our main viewport!
+ ERR_FAIL_COND_V(p_screen_rect == Rect2(), blit_to_screen);
+
+ // and add our blits
+ BlitToScreen blit;
+ blit.render_target = p_render_target;
+ blit.multi_view.use_layer = true;
+ blit.lens_distortion.apply = true;
+ blit.lens_distortion.k1 = k1;
+ blit.lens_distortion.k2 = k2;
+ blit.lens_distortion.upscale = oversample;
+ blit.lens_distortion.aspect_ratio = aspect;
+
+ // left eye
+ blit.rect = p_screen_rect;
+ blit.rect.size.width *= 0.5;
+ blit.multi_view.layer = 0;
+ blit.lens_distortion.eye_center.x = ((-intraocular_dist / 2.0) + (display_width / 4.0)) / (display_width / 2.0);
+ blit_to_screen.push_back(blit);
+
+ // right eye
+ blit.rect = p_screen_rect;
+ blit.rect.size.width *= 0.5;
+ blit.rect.position.x = blit.rect.size.width;
+ blit.multi_view.layer = 1;
+ blit.lens_distortion.eye_center.x = ((intraocular_dist / 2.0) - (display_width / 4.0)) / (display_width / 2.0);
+ blit_to_screen.push_back(blit);
+
+ return blit_to_screen;
+}
+
void MobileVRInterface::process() {
_THREAD_SAFE_METHOD_
diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h
index d28c2196af..29ce0f92c8 100644
--- a/modules/mobile_vr/mobile_vr_interface.h
+++ b/modules/mobile_vr/mobile_vr_interface.h
@@ -63,9 +63,9 @@ private:
real_t display_to_lens = 4.0;
real_t oversample = 1.5;
- //@TODO not yet used, these are needed in our distortion shader...
real_t k1 = 0.215;
real_t k2 = 0.215;
+ real_t aspect = 1.0;
/*
logic for processing our sensor data, this was originally in our positional tracker logic but I think
@@ -138,16 +138,20 @@ public:
virtual void uninitialize() override;
virtual Size2 get_render_targetsize() override;
- virtual bool is_stereo() override;
- virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) override;
- virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
- virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual uint32_t get_view_count() override;
+ virtual Transform3D get_camera_transform() override;
+ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
+ virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
+ virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process() override;
virtual void notification(int p_what) override {}
MobileVRInterface();
~MobileVRInterface();
+
+ // deprecated
+ virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override;
};
#endif // !MOBILE_VR_INTERFACE_H
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp
index 553c6eca53..bd02ec0eac 100644
--- a/modules/mono/class_db_api_json.cpp
+++ b/modules/mono/class_db_api_json.cpp
@@ -33,8 +33,8 @@
#ifdef DEBUG_METHODS_ENABLED
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/json.h"
-#include "core/os/file_access.h"
#include "core/version.h"
void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index ffb04bfd37..576256b6ec 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -37,8 +37,8 @@
#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
+#include "core/io/file_access.h"
#include "core/io/json.h"
-#include "core/os/file_access.h"
#include "core/os/mutex.h"
#include "core/os/os.h"
#include "core/os/thread.h"
@@ -368,7 +368,7 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin
"}\n";
// Replaces all spaces in p_class_name with underscores to prevent
- // erronous C# Script templates from being generated when the object name
+ // invalid C# Script templates from being generated when the object name
// has spaces in it.
String class_name_no_spaces = p_class_name.replace(" ", "_");
String base_class_name = get_base_class_name(p_base_class_name, class_name_no_spaces);
@@ -496,10 +496,10 @@ static String variant_type_to_managed_name(const String &p_var_type_name) {
Variant::VECTOR3I,
Variant::TRANSFORM2D,
Variant::PLANE,
- Variant::QUAT,
+ Variant::QUATERNION,
Variant::AABB,
Variant::BASIS,
- Variant::TRANSFORM,
+ Variant::TRANSFORM3D,
Variant::COLOR,
Variant::STRING_NAME,
Variant::NODE_PATH,
@@ -863,13 +863,13 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
List<Ref<CSharpScript>> to_reload;
// We need to keep reference instances alive during reloading
- List<Ref<Reference>> ref_instances;
+ List<Ref<RefCounted>> rc_instances;
for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
CSharpScriptBinding &script_binding = E->value();
- Reference *ref = Object::cast_to<Reference>(script_binding.owner);
- if (ref) {
- ref_instances.push_back(Ref<Reference>(ref));
+ RefCounted *rc = Object::cast_to<RefCounted>(script_binding.owner);
+ if (rc) {
+ rc_instances.push_back(Ref<RefCounted>(rc));
}
}
@@ -892,9 +892,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
Object *obj = F->get();
script->pending_reload_instances.insert(obj->get_instance_id());
- Reference *ref = Object::cast_to<Reference>(obj);
- if (ref) {
- ref_instances.push_back(Ref<Reference>(ref));
+ RefCounted *rc = Object::cast_to<RefCounted>(obj);
+ if (rc) {
+ rc_instances.push_back(Ref<RefCounted>(rc));
}
}
@@ -903,9 +903,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
Object *obj = F->get()->get_owner();
script->pending_reload_instances.insert(obj->get_instance_id());
- Reference *ref = Object::cast_to<Reference>(obj);
- if (ref) {
- ref_instances.push_back(Ref<Reference>(ref));
+ RefCounted *rc = Object::cast_to<RefCounted>(obj);
+ if (rc) {
+ rc_instances.push_back(Ref<RefCounted>(rc));
}
}
#endif
@@ -1438,16 +1438,16 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
r_script_binding.owner = p_object;
// Tie managed to unmanaged
- Reference *ref = Object::cast_to<Reference>(p_object);
+ RefCounted *rc = Object::cast_to<RefCounted>(p_object);
- if (ref) {
+ if (rc) {
// Unsafe refcount increment. The managed instance also counts as a reference.
// This way if the unmanaged world has no references to our owner
// but the managed instance is alive, the refcount will be 1 instead of 0.
- // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
+ // See: godot_icall_RefCounted_Dtor(MonoObject *p_obj, Object *p_ptr)
- ref->reference();
- CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ rc->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(rc);
}
return true;
@@ -1511,10 +1511,10 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) {
}
void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
- Reference *ref_owner = Object::cast_to<Reference>(p_object);
+ RefCounted *rc_owner = Object::cast_to<RefCounted>(p_object);
#ifdef DEBUG_ENABLED
- CRASH_COND(!ref_owner);
+ CRASH_COND(!rc_owner);
CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
#endif
@@ -1528,7 +1528,7 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
return;
}
- if (ref_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ if (rc_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
GD_MONO_SCOPE_THREAD_ATTACH;
// The reference count was increased after the managed side was the only one referencing our owner.
@@ -1548,10 +1548,10 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
}
bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
- Reference *ref_owner = Object::cast_to<Reference>(p_object);
+ RefCounted *rc_owner = Object::cast_to<RefCounted>(p_object);
#ifdef DEBUG_ENABLED
- CRASH_COND(!ref_owner);
+ CRASH_COND(!rc_owner);
CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
#endif
@@ -1561,7 +1561,7 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
MonoGCHandleData &gchandle = script_binding.gchandle;
- int refcount = ref_owner->reference_get_count();
+ int refcount = rc_owner->reference_get_count();
if (!script_binding.inited) {
return refcount == 0;
@@ -1592,13 +1592,13 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle) {
CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(p_script)));
- Reference *ref = Object::cast_to<Reference>(p_owner);
+ RefCounted *rc = Object::cast_to<RefCounted>(p_owner);
- instance->base_ref = ref != nullptr;
+ instance->base_ref_counted = rc != nullptr;
instance->owner = p_owner;
instance->gchandle = p_gchandle;
- if (instance->base_ref) {
+ if (instance->base_ref_counted) {
instance->_reference_owner_unsafe();
}
@@ -1900,7 +1900,7 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
bool CSharpInstance::_reference_owner_unsafe() {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(owner == nullptr);
CRASH_COND(unsafe_referenced); // already referenced
#endif
@@ -1911,7 +1911,7 @@ bool CSharpInstance::_reference_owner_unsafe() {
// See: _unreference_owner_unsafe()
// May not me referenced yet, so we must use init_ref() instead of reference()
- if (static_cast<Reference *>(owner)->init_ref()) {
+ if (static_cast<RefCounted *>(owner)->init_ref()) {
CSharpLanguage::get_singleton()->post_unsafe_reference(owner);
unsafe_referenced = true;
}
@@ -1921,7 +1921,7 @@ bool CSharpInstance::_reference_owner_unsafe() {
bool CSharpInstance::_unreference_owner_unsafe() {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(owner == nullptr);
#endif
@@ -1938,7 +1938,7 @@ bool CSharpInstance::_unreference_owner_unsafe() {
// Destroying the owner here means self destructing, so we defer the owner destruction to the caller.
CSharpLanguage::get_singleton()->pre_unsafe_unreference(owner);
- return static_cast<Reference *>(owner)->unreference();
+ return static_cast<RefCounted *>(owner)->unreference();
}
MonoObject *CSharpInstance::_internal_new_managed() {
@@ -1970,7 +1970,7 @@ MonoObject *CSharpInstance::_internal_new_managed() {
// Tie managed to unmanaged
gchandle = MonoGCHandleData::new_strong_handle(mono_object);
- if (base_ref) {
+ if (base_ref_counted) {
_reference_owner_unsafe(); // Here, after assigning the gchandle (for the refcount_incremented callback)
}
@@ -1987,7 +1987,7 @@ void CSharpInstance::mono_object_disposed(MonoObject *p_obj) {
disconnect_event_signals();
#ifdef DEBUG_ENABLED
- CRASH_COND(base_ref);
+ CRASH_COND(base_ref_counted);
CRASH_COND(gchandle.is_released());
#endif
CSharpLanguage::get_singleton()->release_script_gchandle(p_obj, gchandle);
@@ -1995,7 +1995,7 @@ void CSharpInstance::mono_object_disposed(MonoObject *p_obj) {
void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance) {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(gchandle.is_released());
#endif
@@ -2056,13 +2056,13 @@ void CSharpInstance::disconnect_event_signals() {
void CSharpInstance::refcount_incremented() {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(owner == nullptr);
#endif
- Reference *ref_owner = Object::cast_to<Reference>(owner);
+ RefCounted *rc_owner = Object::cast_to<RefCounted>(owner);
- if (ref_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ if (rc_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
GD_MONO_SCOPE_THREAD_ATTACH;
// The reference count was increased after the managed side was the only one referencing our owner.
@@ -2078,13 +2078,13 @@ void CSharpInstance::refcount_incremented() {
bool CSharpInstance::refcount_decremented() {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(owner == nullptr);
#endif
- Reference *ref_owner = Object::cast_to<Reference>(owner);
+ RefCounted *rc_owner = Object::cast_to<RefCounted>(owner);
- int refcount = ref_owner->reference_get_count();
+ int refcount = rc_owner->reference_get_count();
if (refcount == 1 && !gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -2105,46 +2105,10 @@ bool CSharpInstance::refcount_decremented() {
return ref_dying;
}
-Vector<ScriptNetData> CSharpInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> CSharpInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t CSharpInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName CSharpInstance::get_rpc_method(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_method(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_mode_by_id(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> CSharpInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t CSharpInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName CSharpInstance::get_rset_property(const uint16_t p_rset_member_id) const {
- return script->get_rset_property(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- return script->get_rset_mode_by_id(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
void CSharpInstance::notification(int p_notification) {
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -2155,12 +2119,12 @@ void CSharpInstance::notification(int p_notification) {
predelete_notified = true;
- if (base_ref) {
- // It's not safe to proceed if the owner derives Reference and the refcount reached 0.
+ if (base_ref_counted) {
+ // It's not safe to proceed if the owner derives RefCounted and the refcount reached 0.
// At this point, Dispose() was already called (manually or from the finalizer) so
// that's not a problem. The refcount wouldn't have reached 0 otherwise, since the
// managed side references it and Dispose() needs to be called to release it.
- // However, this means C# Reference scripts can't receive NOTIFICATION_PREDELETE, but
+ // However, this means C# RefCounted scripts can't receive NOTIFICATION_PREDELETE, but
// this is likely the case with GDScript as well: https://github.com/godotengine/godot/issues/6784
return;
}
@@ -2286,15 +2250,15 @@ CSharpInstance::~CSharpInstance() {
}
// If not being called from the owner's destructor, and we still hold a reference to the owner
- if (base_ref && !ref_dying && owner && unsafe_referenced) {
+ if (base_ref_counted && !ref_dying && owner && unsafe_referenced) {
// The owner's script or script instance is being replaced (or removed)
// Transfer ownership to an "instance binding"
- Reference *ref_owner = static_cast<Reference *>(owner);
+ RefCounted *rc_owner = static_cast<RefCounted *>(owner);
// We will unreference the owner before referencing it again, so we need to keep it alive
- Ref<Reference> scope_keep_owner_alive(ref_owner);
+ Ref<RefCounted> scope_keep_owner_alive(rc_owner);
(void)scope_keep_owner_alive;
// Unreference the owner here, before the new "instance binding" references it.
@@ -2319,7 +2283,7 @@ CSharpInstance::~CSharpInstance() {
#ifdef DEBUG_ENABLED
// The "instance binding" holds a reference so the refcount should be at least 2 before `scope_keep_owner_alive` goes out of scope
- CRASH_COND(ref_owner->reference_get_count() <= 1);
+ CRASH_COND(rc_owner->reference_get_count() <= 1);
#endif
}
@@ -2406,7 +2370,7 @@ void CSharpScript::_update_member_info_no_exports() {
}
#endif
-bool CSharpScript::_update_exports() {
+bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_update) {
#ifdef TOOLS_ENABLED
bool is_editor = Engine::get_singleton()->is_editor_hint();
if (is_editor) {
@@ -2547,7 +2511,7 @@ bool CSharpScript::_update_exports() {
#ifdef TOOLS_ENABLED
if (is_editor) {
// Need to check this here, before disposal
- bool base_ref = Object::cast_to<Reference>(tmp_native) != nullptr;
+ bool base_ref_counted = Object::cast_to<RefCounted>(tmp_native) != nullptr;
// Dispose the temporary managed instance
@@ -2562,7 +2526,7 @@ bool CSharpScript::_update_exports() {
GDMonoUtils::free_gchandle(tmp_pinned_gchandle);
tmp_object = nullptr;
- if (tmp_native && !base_ref) {
+ if (tmp_native && !base_ref_counted) {
Node *node = Object::cast_to<Node>(tmp_native);
if (node && node->is_inside_tree()) {
ERR_PRINT("Temporary instance was added to the scene tree.");
@@ -2578,14 +2542,18 @@ bool CSharpScript::_update_exports() {
if (is_editor) {
placeholder_fallback_enabled = false;
- if (placeholders.size()) {
+ if ((changed || p_instance_to_update) && placeholders.size()) {
// Update placeholders if any
Map<StringName, Variant> values;
List<PropertyInfo> propnames;
_update_exports_values(values, propnames);
- for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
- E->get()->update(propnames, values);
+ if (changed) {
+ for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
+ E->get()->update(propnames, values);
+ }
+ } else {
+ p_instance_to_update->update(propnames, values);
}
}
}
@@ -3046,7 +3014,6 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
p_script->rpc_functions.clear();
- p_script->rpc_variables.clear();
GDMonoClass *top = p_script->script_class;
while (top && top != p_script->native) {
@@ -3060,9 +3027,12 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
if (!methods[i]->is_static()) {
MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]);
if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
+ MultiplayerAPI::RPCConfig nd;
nd.name = methods[i]->get_name();
- nd.mode = mode;
+ nd.rpc_mode = mode;
+ // TODO Transfer mode, channel
+ nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ nd.channel = 0;
if (-1 == p_script->rpc_functions.find(nd)) {
p_script->rpc_functions.push_back(nd);
}
@@ -3071,46 +3041,11 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
}
}
- {
- Vector<GDMonoField *> fields = top->get_all_fields();
- for (int i = 0; i < fields.size(); i++) {
- if (!fields[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(fields[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = fields[i]->get_name();
- nd.mode = mode;
- if (-1 == p_script->rpc_variables.find(nd)) {
- p_script->rpc_variables.push_back(nd);
- }
- }
- }
- }
- }
-
- {
- Vector<GDMonoProperty *> properties = top->get_all_properties();
- for (int i = 0; i < properties.size(); i++) {
- if (!properties[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(properties[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = properties[i]->get_name();
- nd.mode = mode;
- if (-1 == p_script->rpc_variables.find(nd)) {
- p_script->rpc_variables.push_back(nd);
- }
- }
- }
- }
- }
-
top = top->get_parent_class();
}
// Sort so we are 100% that they are always the same.
- p_script->rpc_functions.sort_custom<SortNetData>();
- p_script->rpc_variables.sort_custom<SortNetData>();
+ p_script->rpc_functions.sort_custom<MultiplayerAPI::SortRPCConfig>();
p_script->load_script_signals(p_script->script_class, p_script->native);
}
@@ -3146,7 +3081,7 @@ StringName CSharpScript::get_instance_base_type() const {
}
}
-CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error) {
+CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error) {
GD_MONO_ASSERT_THREAD_ATTACHED;
/* STEP 1, CREATE */
@@ -3162,10 +3097,10 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
ERR_FAIL_V_MSG(nullptr, "Constructor not found.");
}
- Ref<Reference> ref;
- if (p_isref) {
+ Ref<RefCounted> ref;
+ if (p_is_ref_counted) {
// Hold it alive. Important if we have to dispose a script instance binding before creating the CSharpInstance.
- ref = Ref<Reference>(static_cast<Reference *>(p_owner));
+ ref = Ref<RefCounted>(static_cast<RefCounted *>(p_owner));
}
// If the object had a script instance binding, dispose it before adding the CSharpInstance
@@ -3191,7 +3126,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
}
CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(this)));
- instance->base_ref = p_isref;
+ instance->base_ref_counted = p_is_ref_counted;
instance->owner = p_owner;
instance->owner->set_script_instance(instance);
@@ -3216,7 +3151,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
// Tie managed to unmanaged
instance->gchandle = MonoGCHandleData::new_strong_handle(mono_object);
- if (instance->base_ref) {
+ if (instance->base_ref_counted) {
instance->_reference_owner_unsafe(); // Here, after assigning the gchandle (for the refcount_incremented callback)
}
@@ -3251,7 +3186,7 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
Object *owner = ClassDB::instance(NATIVE_GDMONOCLASS_NAME(native));
REF ref;
- Reference *r = Object::cast_to<Reference>(owner);
+ RefCounted *r = Object::cast_to<RefCounted>(owner);
if (r) {
ref = REF(r);
}
@@ -3292,14 +3227,14 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) {
GD_MONO_SCOPE_THREAD_ATTACH;
Callable::CallError unchecked_error;
- return _create_instance(nullptr, 0, p_this, Object::cast_to<Reference>(p_this) != nullptr, unchecked_error);
+ return _create_instance(nullptr, 0, p_this, Object::cast_to<RefCounted>(p_this) != nullptr, unchecked_error);
}
PlaceHolderScriptInstance *CSharpScript::placeholder_instance_create(Object *p_this) {
#ifdef TOOLS_ENABLED
PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(CSharpLanguage::get_singleton(), Ref<Script>(this), p_this));
placeholders.insert(si);
- _update_exports();
+ _update_exports(si);
return si;
#else
return nullptr;
@@ -3543,60 +3478,10 @@ MultiplayerAPI::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_m
return MultiplayerAPI::RPC_MODE_DISABLED;
}
-Vector<ScriptNetData> CSharpScript::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> CSharpScript::get_rpc_methods() const {
return rpc_functions;
}
-uint16_t CSharpScript::get_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < rpc_functions.size(); i++) {
- if (rpc_functions[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName CSharpScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName());
- return rpc_functions[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_functions[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode(const StringName &p_method) const {
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> CSharpScript::get_rset_properties() const {
- return rpc_variables;
-}
-
-uint16_t CSharpScript::get_rset_property_id(const StringName &p_variable) const {
- for (int i = 0; i < rpc_variables.size(); i++) {
- if (rpc_variables[i].name == p_variable) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName CSharpScript::get_rset_property(const uint16_t p_rset_member_id) const {
- ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName());
- return rpc_variables[p_rset_member_id].name;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- ERR_FAIL_COND_V(p_rset_member_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_functions[p_rset_member_id].mode;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rset_mode(const StringName &p_variable) const {
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
Error CSharpScript::load_source_code(const String &p_path) {
Error ferr = read_all_file_utf8(p_path, source);
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 992c7e93c8..965e882c5b 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -136,8 +136,7 @@ private:
Map<StringName, EventSignal> event_signals;
bool signals_invalidated = true;
- Vector<ScriptNetData> rpc_functions;
- Vector<ScriptNetData> rpc_variables;
+ Vector<MultiplayerAPI::RPCConfig> rpc_functions;
#ifdef TOOLS_ENABLED
List<PropertyInfo> exported_members_cache; // members_cache
@@ -164,14 +163,14 @@ private:
void load_script_signals(GDMonoClass *p_class, GDMonoClass *p_native_class);
bool _get_signal(GDMonoClass *p_class, GDMonoMethod *p_delegate_invoke, Vector<SignalParameter> &params);
- bool _update_exports();
+ bool _update_exports(PlaceHolderScriptInstance *p_instance_to_update = nullptr);
bool _get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported);
#ifdef TOOLS_ENABLED
static int _try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string);
#endif
- CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error);
+ CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);
Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
// Do not use unless you know what you are doing
@@ -235,17 +234,7 @@ public:
int get_member_line(const StringName &p_member) const override;
- Vector<ScriptNetData> get_rpc_methods() const override;
- uint16_t get_rpc_method_id(const StringName &p_method) const override;
- StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- Vector<ScriptNetData> get_rset_properties() const override;
- uint16_t get_rset_property_id(const StringName &p_variable) const override;
- StringName get_rset_property(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
#ifdef TOOLS_ENABLED
bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -262,7 +251,7 @@ class CSharpInstance : public ScriptInstance {
friend class CSharpLanguage;
Object *owner = nullptr;
- bool base_ref = false;
+ bool base_ref_counted = false;
bool ref_dying = false;
bool unsafe_referenced = false;
bool predelete_notified = false;
@@ -322,17 +311,7 @@ public:
void refcount_incremented() override;
bool refcount_decremented() override;
- Vector<ScriptNetData> get_rpc_methods() const override;
- uint16_t get_rpc_method_id(const StringName &p_method) const override;
- StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- Vector<ScriptNetData> get_rset_properties() const override;
- uint16_t get_rset_property_id(const StringName &p_variable) const override;
- StringName get_rset_property(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
void notification(int p_notification) override;
void _call_notification(int p_notification);
@@ -470,7 +449,7 @@ public:
/* EDITOR FUNCTIONS */
void get_reserved_words(List<String> *p_words) const override;
- bool is_control_flow_keyword(String p_keyword) const;
+ bool is_control_flow_keyword(String p_keyword) const override;
void get_comment_delimiters(List<String> *p_delimiters) const override;
void get_string_delimiters(List<String> *p_delimiters) const override;
Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const override;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
index 51055dc9b9..27737c3da0 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
@@ -7,7 +7,7 @@ using Path = System.IO.Path;
namespace GodotTools.Build
{
[Serializable]
- public sealed class BuildInfo : Reference // TODO Remove Reference once we have proper serialization
+ public sealed class BuildInfo : RefCounted // TODO Remove RefCounted once we have proper serialization
{
public string Solution { get; }
public string[] Targets { get; }
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
index 1a1639aac7..c380707587 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
@@ -11,7 +11,7 @@ namespace GodotTools.Build
public class BuildOutputView : VBoxContainer, ISerializationListener
{
[Serializable]
- private class BuildIssue : Reference // TODO Remove Reference once we have proper serialization
+ private class BuildIssue : RefCounted // TODO Remove RefCounted once we have proper serialization
{
public bool Warning { get; set; }
public string File { get; set; }
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 58561c5097..c71c44d79d 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -371,7 +371,7 @@ namespace GodotTools
return (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor") != ExternalEditorId.None;
}
- public override bool Build()
+ public override bool _Build()
{
return BuildManager.EditorBuildCallback();
}
@@ -413,9 +413,9 @@ namespace GodotTools
bottomPanelBtn.Icon = MSBuildPanel.BuildOutputView.BuildStateIcon;
}
- public override void EnablePlugin()
+ public override void _EnablePlugin()
{
- base.EnablePlugin();
+ base._EnablePlugin();
if (Instance != null)
throw new InvalidOperationException();
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index b48e5df9eb..7e944ed4a5 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -35,8 +35,8 @@
#include "core/config/engine.h"
#include "core/core_constants.h"
#include "core/io/compression.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#include "core/string/ucaps.h"
#include "main/main.h"
@@ -1260,7 +1260,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
CRASH_COND(itype.cname != name_cache.type_Object);
CRASH_COND(!itype.is_instantiable);
CRASH_COND(itype.api_type != ClassDB::API_CORE);
- CRASH_COND(itype.is_reference);
+ CRASH_COND(itype.is_ref_counted);
CRASH_COND(itype.is_singleton);
}
@@ -2284,8 +2284,8 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
}
if (return_type->is_object_type) {
- ptrcall_return_type = return_type->is_reference ? "Ref<Reference>" : return_type->c_type;
- initialization = return_type->is_reference ? "" : " = nullptr";
+ ptrcall_return_type = return_type->is_ref_counted ? "Ref<RefCounted>" : return_type->c_type;
+ initialization = return_type->is_ref_counted ? "" : " = nullptr";
} else {
ptrcall_return_type = return_type->c_type;
}
@@ -2520,10 +2520,10 @@ bool BindingsGenerator::_arg_default_value_is_assignable_to_type(const Variant &
p_arg_type.name == name_cache.type_NodePath;
case Variant::NODE_PATH:
return p_arg_type.name == name_cache.type_NodePath;
- case Variant::TRANSFORM:
case Variant::TRANSFORM2D:
+ case Variant::TRANSFORM3D:
case Variant::BASIS:
- case Variant::QUAT:
+ case Variant::QUATERNION:
case Variant::PLANE:
case Variant::AABB:
case Variant::COLOR:
@@ -2600,12 +2600,12 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.base_name = ClassDB::get_parent_class(type_cname);
itype.is_singleton = Engine::get_singleton()->has_singleton(itype.proxy_name);
itype.is_instantiable = class_info->creation_func && !itype.is_singleton;
- itype.is_reference = ClassDB::is_parent_class(type_cname, name_cache.type_Reference);
- itype.memory_own = itype.is_reference;
+ itype.is_ref_counted = ClassDB::is_parent_class(type_cname, name_cache.type_RefCounted);
+ itype.memory_own = itype.is_ref_counted;
itype.c_out = "\treturn ";
itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
- itype.c_out += itype.is_reference ? "(%1.ptr());\n" : "(%1);\n";
+ itype.c_out += itype.is_ref_counted ? "(%1.ptr());\n" : "(%1);\n";
itype.cs_in = itype.is_singleton ? BINDINGS_PTR_FIELD : "Object." CS_SMETHOD_GETINSTANCE "(%0)";
@@ -2741,7 +2741,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
imethod.return_type.cname = return_info.class_name;
bool bad_reference_hint = !imethod.is_virtual && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE &&
- ClassDB::is_parent_class(return_info.class_name, name_cache.type_Reference);
+ ClassDB::is_parent_class(return_info.class_name, name_cache.type_RefCounted);
ERR_FAIL_COND_V_MSG(bad_reference_hint, false,
String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
" Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'.");
@@ -3053,28 +3053,25 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
break;
case Variant::PLANE: {
Plane plane = p_val.operator Plane();
- r_iarg.default_argument = "new Plane(new Vector3(" + plane.normal.operator String() + "), " + rtos(plane.d) + ")";
+ r_iarg.default_argument = "new Plane(new Vector3" + plane.normal.operator String() + ", " + rtos(plane.d) + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
case Variant::AABB: {
AABB aabb = p_val.operator ::AABB();
- r_iarg.default_argument = "new AABB(new Vector3(" + aabb.position.operator String() + "), new Vector3(" + aabb.position.operator String() + "))";
+ r_iarg.default_argument = "new AABB(new Vector3" + aabb.position.operator String() + ", new Vector3" + aabb.position.operator String() + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
case Variant::RECT2: {
Rect2 rect = p_val.operator Rect2();
- r_iarg.default_argument = "new Rect2(new Vector2(" + rect.position.operator String() + "), new Vector2(" + rect.position.operator String() + "))";
+ r_iarg.default_argument = "new Rect2(new Vector2" + rect.position.operator String() + ", new Vector2" + rect.position.operator String() + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
case Variant::RECT2I: {
Rect2i rect = p_val.operator Rect2i();
- r_iarg.default_argument = "new Rect2i(new Vector2i(" + rect.position.operator String() + "), new Vector2i(" + rect.position.operator String() + "))";
+ r_iarg.default_argument = "new Rect2i(new Vector2i" + rect.position.operator String() + ", new Vector2i" + rect.position.operator String() + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
case Variant::COLOR:
- r_iarg.default_argument = "new %s(" + r_iarg.default_argument + ")";
- r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
- break;
case Variant::VECTOR2:
case Variant::VECTOR2I:
case Variant::VECTOR3:
@@ -3123,13 +3120,13 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
- case Variant::TRANSFORM: {
- Transform transform = p_val.operator Transform();
- if (transform == Transform()) {
- r_iarg.default_argument = "Transform.Identity";
+ case Variant::TRANSFORM3D: {
+ Transform3D transform = p_val.operator Transform3D();
+ if (transform == Transform3D()) {
+ r_iarg.default_argument = "Transform3D.Identity";
} else {
Basis basis = transform.basis;
- r_iarg.default_argument = "new Transform(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ", new Vector3" + transform.origin.operator String() + ")";
+ r_iarg.default_argument = "new Transform3D(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ", new Vector3" + transform.origin.operator String() + ")";
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
@@ -3142,12 +3139,12 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
- case Variant::QUAT: {
- Quat quat = p_val.operator Quat();
- if (quat == Quat()) {
- r_iarg.default_argument = "Quat.Identity";
+ case Variant::QUATERNION: {
+ Quaternion quaternion = p_val.operator Quaternion();
+ if (quaternion == Quaternion()) {
+ r_iarg.default_argument = "Quaternion.Identity";
} else {
- r_iarg.default_argument = "new Quat" + quat.operator String();
+ r_iarg.default_argument = "new Quaternion" + quaternion.operator String();
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
@@ -3196,8 +3193,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
INSERT_STRUCT_TYPE(Vector3)
INSERT_STRUCT_TYPE(Vector3i)
INSERT_STRUCT_TYPE(Basis)
- INSERT_STRUCT_TYPE(Quat)
- INSERT_STRUCT_TYPE(Transform)
+ INSERT_STRUCT_TYPE(Quaternion)
+ INSERT_STRUCT_TYPE(Transform3D)
INSERT_STRUCT_TYPE(AABB)
INSERT_STRUCT_TYPE(Color)
INSERT_STRUCT_TYPE(Plane)
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 876046176b..48c0e02723 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -216,7 +216,7 @@ class BindingsGenerator {
bool is_enum = false;
bool is_object_type = false;
bool is_singleton = false;
- bool is_reference = false;
+ bool is_ref_counted = false;
/**
* Used only by Object-derived types.
@@ -228,7 +228,7 @@ class BindingsGenerator {
/**
* Used only by Object-derived types.
* Determines if the C# class owns the native handle and must free it somehow when disposed.
- * e.g.: Reference types must notify when the C# instance is disposed, for proper refcounting.
+ * e.g.: RefCounted types must notify when the C# instance is disposed, for proper refcounting.
*/
bool memory_own = false;
@@ -295,7 +295,7 @@ class BindingsGenerator {
* VarArg (fictitious type to represent variable arguments): Array
* float: double (because ptrcall only supports double)
* int: int64_t (because ptrcall only supports int64_t and uint64_t)
- * Reference types override this for the type of the return variable: Ref<Reference>
+ * RefCounted types override this for the type of the return variable: Ref<RefCounted>
*/
String c_type;
@@ -534,7 +534,7 @@ class BindingsGenerator {
StringName type_Variant = StaticCString::create("Variant");
StringName type_VarArg = StaticCString::create("VarArg");
StringName type_Object = StaticCString::create("Object");
- StringName type_Reference = StaticCString::create("Reference");
+ StringName type_RefCounted = StaticCString::create("RefCounted");
StringName type_RID = StaticCString::create("RID");
StringName type_String = StaticCString::create("String");
StringName type_StringName = StaticCString::create("StringName");
@@ -623,7 +623,7 @@ class BindingsGenerator {
}
inline String get_unique_sig(const TypeInterface &p_type) {
- if (p_type.is_reference) {
+ if (p_type.is_ref_counted) {
return "Ref";
} else if (p_type.is_object_type) {
return "Obj";
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
index 3aecce50f5..2b641a8937 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
@@ -676,7 +676,7 @@ namespace Godot
public override string ToString()
{
- return String.Format("{0} - {1}", new object[]
+ return String.Format("{0}, {1}", new object[]
{
_position.ToString(),
_size.ToString()
@@ -685,7 +685,7 @@ namespace Godot
public string ToString(string format)
{
- return String.Format("{0} - {1}", new object[]
+ return String.Format("{0}, {1}", new object[]
{
_position.ToString(format),
_size.ToString(format)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index 3f1120575f..5dbf5d5657 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -207,7 +207,7 @@ namespace Godot
}
}
- public Quat RotationQuat()
+ public Quaternion RotationQuaternion()
{
Basis orthonormalizedBasis = Orthonormalized();
real_t det = orthonormalizedBasis.Determinant();
@@ -218,18 +218,18 @@ namespace Godot
orthonormalizedBasis = orthonormalizedBasis.Scaled(-Vector3.One);
}
- return orthonormalizedBasis.Quat();
+ return orthonormalizedBasis.Quaternion();
}
- internal void SetQuatScale(Quat quat, Vector3 scale)
+ internal void SetQuaternionScale(Quaternion quaternion, Vector3 scale)
{
SetDiagonal(scale);
- Rotate(quat);
+ Rotate(quaternion);
}
- private void Rotate(Quat quat)
+ private void Rotate(Quaternion quaternion)
{
- this *= new Basis(quat);
+ this *= new Basis(quaternion);
}
private void SetDiagonal(Vector3 diagonal)
@@ -263,8 +263,8 @@ namespace Godot
/// The returned vector contains the rotation angles in
/// the format (X angle, Y angle, Z angle).
///
- /// Consider using the <see cref="Basis.Quat()"/> method instead, which
- /// returns a <see cref="Godot.Quat"/> quaternion instead of Euler angles.
+ /// Consider using the <see cref="Basis.Quaternion()"/> method instead, which
+ /// returns a <see cref="Godot.Quaternion"/> quaternion instead of Euler angles.
/// </summary>
/// <returns>A Vector3 representing the basis rotation in Euler angles.</returns>
public Vector3 GetEuler()
@@ -486,8 +486,8 @@ namespace Godot
/// <returns>The resulting basis matrix of the interpolation.</returns>
public Basis Slerp(Basis target, real_t weight)
{
- Quat from = new Quat(this);
- Quat to = new Quat(target);
+ Quaternion from = new Quaternion(this);
+ Quaternion to = new Quaternion(target);
Basis b = new Basis(from.Slerp(to, weight));
b.Row0 *= Mathf.Lerp(Row0.Length(), target.Row0.Length(), weight);
@@ -588,8 +588,8 @@ namespace Godot
/// See <see cref="GetEuler()"/> if you need Euler angles, but keep in
/// mind that quaternions should generally be preferred to Euler angles.
/// </summary>
- /// <returns>A <see cref="Godot.Quat"/> representing the basis's rotation.</returns>
- public Quat Quat()
+ /// <returns>A <see cref="Godot.Quaternion"/> representing the basis's rotation.</returns>
+ public Quaternion Quaternion()
{
real_t trace = Row0[0] + Row1[1] + Row2[2];
@@ -597,7 +597,7 @@ namespace Godot
{
real_t s = Mathf.Sqrt(trace + 1.0f) * 2f;
real_t inv_s = 1f / s;
- return new Quat(
+ return new Quaternion(
(Row2[1] - Row1[2]) * inv_s,
(Row0[2] - Row2[0]) * inv_s,
(Row1[0] - Row0[1]) * inv_s,
@@ -609,7 +609,7 @@ namespace Godot
{
real_t s = Mathf.Sqrt(Row0[0] - Row1[1] - Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
- return new Quat(
+ return new Quaternion(
s * 0.25f,
(Row0[1] + Row1[0]) * inv_s,
(Row0[2] + Row2[0]) * inv_s,
@@ -621,7 +621,7 @@ namespace Godot
{
real_t s = Mathf.Sqrt(-Row0[0] + Row1[1] - Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
- return new Quat(
+ return new Quaternion(
(Row0[1] + Row1[0]) * inv_s,
s * 0.25f,
(Row1[2] + Row2[1]) * inv_s,
@@ -632,7 +632,7 @@ namespace Godot
{
real_t s = Mathf.Sqrt(-Row0[0] - Row1[1] + Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
- return new Quat(
+ return new Quaternion(
(Row0[2] + Row2[0]) * inv_s,
(Row1[2] + Row2[1]) * inv_s,
s * 0.25f,
@@ -699,23 +699,23 @@ namespace Godot
/// <summary>
/// Constructs a pure rotation basis matrix from the given quaternion.
/// </summary>
- /// <param name="quat">The quaternion to create the basis from.</param>
- public Basis(Quat quat)
+ /// <param name="quaternion">The quaternion to create the basis from.</param>
+ public Basis(Quaternion quaternion)
{
- real_t s = 2.0f / quat.LengthSquared;
+ real_t s = 2.0f / quaternion.LengthSquared;
- real_t xs = quat.x * s;
- real_t ys = quat.y * s;
- real_t zs = quat.z * s;
- real_t wx = quat.w * xs;
- real_t wy = quat.w * ys;
- real_t wz = quat.w * zs;
- real_t xx = quat.x * xs;
- real_t xy = quat.x * ys;
- real_t xz = quat.x * zs;
- real_t yy = quat.y * ys;
- real_t yz = quat.y * zs;
- real_t zz = quat.z * zs;
+ real_t xs = quaternion.x * s;
+ real_t ys = quaternion.y * s;
+ real_t zs = quaternion.z * s;
+ real_t wx = quaternion.w * xs;
+ real_t wy = quaternion.w * ys;
+ real_t wz = quaternion.w * zs;
+ real_t xx = quaternion.x * xs;
+ real_t xy = quaternion.x * ys;
+ real_t xz = quaternion.x * zs;
+ real_t yy = quaternion.y * ys;
+ real_t yz = quaternion.y * zs;
+ real_t zz = quaternion.z * zs;
Row0 = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy);
Row1 = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx);
@@ -727,8 +727,8 @@ namespace Godot
/// (in the YXZ convention: when *composing*, first Y, then X, and Z last),
/// given in the vector format as (X angle, Y angle, Z angle).
///
- /// Consider using the <see cref="Basis(Quat)"/> constructor instead, which
- /// uses a <see cref="Godot.Quat"/> quaternion instead of Euler angles.
+ /// Consider using the <see cref="Basis(Quaternion)"/> constructor instead, which
+ /// uses a <see cref="Godot.Quaternion"/> quaternion instead of Euler angles.
/// </summary>
/// <param name="eulerYXZ">The Euler angles to create the basis from.</param>
public Basis(Vector3 eulerYXZ)
@@ -863,22 +863,16 @@ namespace Godot
public override string ToString()
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- Row0.ToString(),
- Row1.ToString(),
- Row2.ToString()
- });
+ return "[X: " + x.ToString() +
+ ", Y: " + y.ToString() +
+ ", Z: " + z.ToString() + "]";
}
public string ToString(string format)
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- Row0.ToString(format),
- Row1.ToString(format),
- Row2.ToString(format)
- });
+ return "[X: " + x.ToString(format) +
+ ", Y: " + y.ToString(format) +
+ ", Z: " + z.ToString(format) + "]";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index 2a9f834aac..155ffcff32 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -257,6 +257,27 @@ namespace Godot
}
/// <summary>
+ /// Returns a new color with all components clamped between the
+ /// components of `min` and `max` using
+ /// <see cref="Mathf.Clamp(float, float, float)"/>.
+ /// </summary>
+ /// <param name="min">The color with minimum allowed values.</param>
+ /// <param name="max">The color with maximum allowed values.</param>
+ /// <returns>The color with all components clamped.</returns>
+ public Color Clamp(Color? min = null, Color? max = null)
+ {
+ Color minimum = min ?? new Color(0, 0, 0, 0);
+ Color maximum = max ?? new Color(1, 1, 1, 1);
+ return new Color
+ (
+ (float)Mathf.Clamp(r, minimum.r, maximum.r),
+ (float)Mathf.Clamp(g, minimum.g, maximum.g),
+ (float)Mathf.Clamp(b, minimum.b, maximum.b),
+ (float)Mathf.Clamp(a, minimum.a, maximum.a)
+ );
+ }
+
+ /// <summary>
/// Returns a new color resulting from making this color darker
/// by the specified ratio (on the range of 0 to 1).
/// </summary>
@@ -989,12 +1010,12 @@ namespace Godot
public override string ToString()
{
- return String.Format("{0},{1},{2},{3}", r.ToString(), g.ToString(), b.ToString(), a.ToString());
+ return String.Format("({0}, {1}, {2}, {3})", r.ToString(), g.ToString(), b.ToString(), a.ToString());
}
public string ToString(string format)
{
- return String.Format("{0},{1},{2},{3}", r.ToString(format), g.ToString(format), b.ToString(format), a.ToString(format));
+ return String.Format("({0}, {1}, {2}, {3})", r.ToString(format), g.ToString(format), b.ToString(format), a.ToString(format));
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
index 48582d5ad8..d486d79557 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
@@ -66,7 +66,7 @@ namespace Godot
if (memoryOwn)
{
memoryOwn = false;
- godot_icall_Reference_Disposed(this, ptr, !disposing);
+ godot_icall_RefCounted_Disposed(this, ptr, !disposing);
}
else
{
@@ -129,7 +129,7 @@ namespace Godot
internal static extern void godot_icall_Object_Disposed(Object obj, IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Reference_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
+ internal static extern void godot_icall_RefCounted_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void godot_icall_Object_ConnectEventSignals(IntPtr obj);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
index 2f8b5f297c..ad6ca51e8b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
@@ -355,7 +355,7 @@ namespace Godot
public override string ToString()
{
- return String.Format("({0}, {1})", new object[]
+ return String.Format("{0}, {1}", new object[]
{
_normal.ToString(),
D.ToString()
@@ -364,7 +364,7 @@ namespace Godot
public string ToString(string format)
{
- return String.Format("({0}, {1})", new object[]
+ return String.Format("{0}, {1}", new object[]
{
_normal.ToString(format),
D.ToString(format)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs
deleted file mode 100644
index bd3bcb0c58..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs
+++ /dev/null
@@ -1,541 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-#if REAL_T_IS_DOUBLE
-using real_t = System.Double;
-#else
-using real_t = System.Single;
-#endif
-
-namespace Godot
-{
- /// <summary>
- /// A unit quaternion used for representing 3D rotations.
- /// Quaternions need to be normalized to be used for rotation.
- ///
- /// It is similar to Basis, which implements matrix representation of
- /// rotations, and can be parametrized using both an axis-angle pair
- /// or Euler angles. Basis stores rotation, scale, and shearing,
- /// while Quat only stores rotation.
- ///
- /// Due to its compactness and the way it is stored in memory, certain
- /// operations (obtaining axis-angle and performing SLERP, in particular)
- /// are more efficient and robust against floating-point errors.
- /// </summary>
- [Serializable]
- [StructLayout(LayoutKind.Sequential)]
- public struct Quat : IEquatable<Quat>
- {
- /// <summary>
- /// X component of the quaternion (imaginary `i` axis part).
- /// Quaternion components should usually not be manipulated directly.
- /// </summary>
- public real_t x;
-
- /// <summary>
- /// Y component of the quaternion (imaginary `j` axis part).
- /// Quaternion components should usually not be manipulated directly.
- /// </summary>
- public real_t y;
-
- /// <summary>
- /// Z component of the quaternion (imaginary `k` axis part).
- /// Quaternion components should usually not be manipulated directly.
- /// </summary>
- public real_t z;
-
- /// <summary>
- /// W component of the quaternion (real part).
- /// Quaternion components should usually not be manipulated directly.
- /// </summary>
- public real_t w;
-
- /// <summary>
- /// Access quaternion components using their index.
- /// </summary>
- /// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`, `[3]` is equivalent to `.w`.</value>
- public real_t this[int index]
- {
- get
- {
- switch (index)
- {
- case 0:
- return x;
- case 1:
- return y;
- case 2:
- return z;
- case 3:
- return w;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- set
- {
- switch (index)
- {
- case 0:
- x = value;
- break;
- case 1:
- y = value;
- break;
- case 2:
- z = value;
- break;
- case 3:
- w = value;
- break;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- }
-
- /// <summary>
- /// Returns the length (magnitude) of the quaternion.
- /// </summary>
- /// <value>Equivalent to `Mathf.Sqrt(LengthSquared)`.</value>
- public real_t Length
- {
- get { return Mathf.Sqrt(LengthSquared); }
- }
-
- /// <summary>
- /// Returns the squared length (squared magnitude) of the quaternion.
- /// This method runs faster than <see cref="Length"/>, so prefer it if
- /// you need to compare quaternions or need the squared length for some formula.
- /// </summary>
- /// <value>Equivalent to `Dot(this)`.</value>
- public real_t LengthSquared
- {
- get { return Dot(this); }
- }
-
- /// <summary>
- /// Performs a cubic spherical interpolation between quaternions `preA`,
- /// this vector, `b`, and `postB`, by the given amount `t`.
- /// </summary>
- /// <param name="b">The destination quaternion.</param>
- /// <param name="preA">A quaternion before this quaternion.</param>
- /// <param name="postB">A quaternion after `b`.</param>
- /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
- /// <returns>The interpolated quaternion.</returns>
- public Quat CubicSlerp(Quat b, Quat preA, Quat postB, real_t weight)
- {
- real_t t2 = (1.0f - weight) * weight * 2f;
- Quat sp = Slerp(b, weight);
- Quat sq = preA.Slerpni(postB, weight);
- return sp.Slerpni(sq, t2);
- }
-
- /// <summary>
- /// Returns the dot product of two quaternions.
- /// </summary>
- /// <param name="b">The other quaternion.</param>
- /// <returns>The dot product.</returns>
- public real_t Dot(Quat b)
- {
- return x * b.x + y * b.y + z * b.z + w * b.w;
- }
-
- /// <summary>
- /// Returns Euler angles (in the YXZ convention: when decomposing,
- /// first Z, then X, and Y last) corresponding to the rotation
- /// represented by the unit quaternion. Returned vector contains
- /// the rotation angles in the format (X angle, Y angle, Z angle).
- /// </summary>
- /// <returns>The Euler angle representation of this quaternion.</returns>
- public Vector3 GetEuler()
- {
-#if DEBUG
- if (!IsNormalized())
- {
- throw new InvalidOperationException("Quat is not normalized");
- }
-#endif
- var basis = new Basis(this);
- return basis.GetEuler();
- }
-
- /// <summary>
- /// Returns the inverse of the quaternion.
- /// </summary>
- /// <returns>The inverse quaternion.</returns>
- public Quat Inverse()
- {
-#if DEBUG
- if (!IsNormalized())
- {
- throw new InvalidOperationException("Quat is not normalized");
- }
-#endif
- return new Quat(-x, -y, -z, w);
- }
-
- /// <summary>
- /// Returns whether the quaternion is normalized or not.
- /// </summary>
- /// <returns>A bool for whether the quaternion is normalized or not.</returns>
- public bool IsNormalized()
- {
- return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
- }
-
- /// <summary>
- /// Returns a copy of the quaternion, normalized to unit length.
- /// </summary>
- /// <returns>The normalized quaternion.</returns>
- public Quat Normalized()
- {
- return this / Length;
- }
-
- /// <summary>
- /// Returns the result of the spherical linear interpolation between
- /// this quaternion and `to` by amount `weight`.
- ///
- /// Note: Both quaternions must be normalized.
- /// </summary>
- /// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
- /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
- /// <returns>The resulting quaternion of the interpolation.</returns>
- public Quat Slerp(Quat to, real_t weight)
- {
-#if DEBUG
- if (!IsNormalized())
- {
- throw new InvalidOperationException("Quat is not normalized");
- }
- if (!to.IsNormalized())
- {
- throw new ArgumentException("Argument is not normalized", nameof(to));
- }
-#endif
-
- // Calculate cosine.
- real_t cosom = x * to.x + y * to.y + z * to.z + w * to.w;
-
- var to1 = new Quat();
-
- // Adjust signs if necessary.
- if (cosom < 0.0)
- {
- cosom = -cosom;
- to1.x = -to.x;
- to1.y = -to.y;
- to1.z = -to.z;
- to1.w = -to.w;
- }
- else
- {
- to1.x = to.x;
- to1.y = to.y;
- to1.z = to.z;
- to1.w = to.w;
- }
-
- real_t sinom, scale0, scale1;
-
- // Calculate coefficients.
- if (1.0 - cosom > Mathf.Epsilon)
- {
- // Standard case (Slerp).
- real_t omega = Mathf.Acos(cosom);
- sinom = Mathf.Sin(omega);
- scale0 = Mathf.Sin((1.0f - weight) * omega) / sinom;
- scale1 = Mathf.Sin(weight * omega) / sinom;
- }
- else
- {
- // Quaternions are very close so we can do a linear interpolation.
- scale0 = 1.0f - weight;
- scale1 = weight;
- }
-
- // Calculate final values.
- return new Quat
- (
- scale0 * x + scale1 * to1.x,
- scale0 * y + scale1 * to1.y,
- scale0 * z + scale1 * to1.z,
- scale0 * w + scale1 * to1.w
- );
- }
-
- /// <summary>
- /// Returns the result of the spherical linear interpolation between
- /// this quaternion and `to` by amount `weight`, but without
- /// checking if the rotation path is not bigger than 90 degrees.
- /// </summary>
- /// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
- /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
- /// <returns>The resulting quaternion of the interpolation.</returns>
- public Quat Slerpni(Quat to, real_t weight)
- {
- real_t dot = Dot(to);
-
- if (Mathf.Abs(dot) > 0.9999f)
- {
- return this;
- }
-
- real_t theta = Mathf.Acos(dot);
- real_t sinT = 1.0f / Mathf.Sin(theta);
- real_t newFactor = Mathf.Sin(weight * theta) * sinT;
- real_t invFactor = Mathf.Sin((1.0f - weight) * theta) * sinT;
-
- return new Quat
- (
- invFactor * x + newFactor * to.x,
- invFactor * y + newFactor * to.y,
- invFactor * z + newFactor * to.z,
- invFactor * w + newFactor * to.w
- );
- }
-
- /// <summary>
- /// Returns a vector transformed (multiplied) by this quaternion.
- /// </summary>
- /// <param name="v">A vector to transform.</param>
- /// <returns>The transformed vector.</returns>
- public Vector3 Xform(Vector3 v)
- {
-#if DEBUG
- if (!IsNormalized())
- {
- throw new InvalidOperationException("Quat is not normalized");
- }
-#endif
- var u = new Vector3(x, y, z);
- Vector3 uv = u.Cross(v);
- return v + ((uv * w) + u.Cross(uv)) * 2;
- }
-
- // Constants
- private static readonly Quat _identity = new Quat(0, 0, 0, 1);
-
- /// <summary>
- /// The identity quaternion, representing no rotation.
- /// Equivalent to an identity <see cref="Basis"/> matrix. If a vector is transformed by
- /// an identity quaternion, it will not change.
- /// </summary>
- /// <value>Equivalent to `new Quat(0, 0, 0, 1)`.</value>
- public static Quat Identity { get { return _identity; } }
-
- /// <summary>
- /// Constructs a quaternion defined by the given values.
- /// </summary>
- /// <param name="x">X component of the quaternion (imaginary `i` axis part).</param>
- /// <param name="y">Y component of the quaternion (imaginary `j` axis part).</param>
- /// <param name="z">Z component of the quaternion (imaginary `k` axis part).</param>
- /// <param name="w">W component of the quaternion (real part).</param>
- public Quat(real_t x, real_t y, real_t z, real_t w)
- {
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
- }
-
- /// <summary>
- /// Constructs a quaternion from the given quaternion.
- /// </summary>
- /// <param name="q">The existing quaternion.</param>
- public Quat(Quat q)
- {
- this = q;
- }
-
- /// <summary>
- /// Constructs a quaternion from the given <see cref="Basis"/>.
- /// </summary>
- /// <param name="basis">The basis to construct from.</param>
- public Quat(Basis basis)
- {
- this = basis.Quat();
- }
-
- /// <summary>
- /// Constructs a quaternion that will perform a rotation specified by
- /// Euler angles (in the YXZ convention: when decomposing,
- /// first Z, then X, and Y last),
- /// given in the vector format as (X angle, Y angle, Z angle).
- /// </summary>
- /// <param name="eulerYXZ"></param>
- public Quat(Vector3 eulerYXZ)
- {
- real_t half_a1 = eulerYXZ.y * 0.5f;
- real_t half_a2 = eulerYXZ.x * 0.5f;
- real_t half_a3 = eulerYXZ.z * 0.5f;
-
- // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
- // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
- // a3 is the angle of the first rotation, following the notation in this reference.
-
- real_t cos_a1 = Mathf.Cos(half_a1);
- real_t sin_a1 = Mathf.Sin(half_a1);
- real_t cos_a2 = Mathf.Cos(half_a2);
- real_t sin_a2 = Mathf.Sin(half_a2);
- real_t cos_a3 = Mathf.Cos(half_a3);
- real_t sin_a3 = Mathf.Sin(half_a3);
-
- x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
- y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
- z = cos_a1 * cos_a2 * sin_a3 - sin_a1 * sin_a2 * cos_a3;
- w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
- }
-
- /// <summary>
- /// Constructs a quaternion that will rotate around the given axis
- /// by the specified angle. The axis must be a normalized vector.
- /// </summary>
- /// <param name="axis">The axis to rotate around. Must be normalized.</param>
- /// <param name="angle">The angle to rotate, in radians.</param>
- public Quat(Vector3 axis, real_t angle)
- {
-#if DEBUG
- if (!axis.IsNormalized())
- {
- throw new ArgumentException("Argument is not normalized", nameof(axis));
- }
-#endif
-
- real_t d = axis.Length();
-
- if (d == 0f)
- {
- x = 0f;
- y = 0f;
- z = 0f;
- w = 0f;
- }
- else
- {
- real_t sinAngle = Mathf.Sin(angle * 0.5f);
- real_t cosAngle = Mathf.Cos(angle * 0.5f);
- real_t s = sinAngle / d;
-
- x = axis.x * s;
- y = axis.y * s;
- z = axis.z * s;
- w = cosAngle;
- }
- }
-
- public static Quat operator *(Quat left, Quat right)
- {
- return new Quat
- (
- left.w * right.x + left.x * right.w + left.y * right.z - left.z * right.y,
- left.w * right.y + left.y * right.w + left.z * right.x - left.x * right.z,
- left.w * right.z + left.z * right.w + left.x * right.y - left.y * right.x,
- left.w * right.w - left.x * right.x - left.y * right.y - left.z * right.z
- );
- }
-
- public static Quat operator +(Quat left, Quat right)
- {
- return new Quat(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w);
- }
-
- public static Quat operator -(Quat left, Quat right)
- {
- return new Quat(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w);
- }
-
- public static Quat operator -(Quat left)
- {
- return new Quat(-left.x, -left.y, -left.z, -left.w);
- }
-
- public static Quat operator *(Quat left, Vector3 right)
- {
- return new Quat
- (
- left.w * right.x + left.y * right.z - left.z * right.y,
- left.w * right.y + left.z * right.x - left.x * right.z,
- left.w * right.z + left.x * right.y - left.y * right.x,
- -left.x * right.x - left.y * right.y - left.z * right.z
- );
- }
-
- public static Quat operator *(Vector3 left, Quat right)
- {
- return new Quat
- (
- right.w * left.x + right.y * left.z - right.z * left.y,
- right.w * left.y + right.z * left.x - right.x * left.z,
- right.w * left.z + right.x * left.y - right.y * left.x,
- -right.x * left.x - right.y * left.y - right.z * left.z
- );
- }
-
- public static Quat operator *(Quat left, real_t right)
- {
- return new Quat(left.x * right, left.y * right, left.z * right, left.w * right);
- }
-
- public static Quat operator *(real_t left, Quat right)
- {
- return new Quat(right.x * left, right.y * left, right.z * left, right.w * left);
- }
-
- public static Quat operator /(Quat left, real_t right)
- {
- return left * (1.0f / right);
- }
-
- public static bool operator ==(Quat left, Quat right)
- {
- return left.Equals(right);
- }
-
- public static bool operator !=(Quat left, Quat right)
- {
- return !left.Equals(right);
- }
-
- public override bool Equals(object obj)
- {
- if (obj is Quat)
- {
- return Equals((Quat)obj);
- }
-
- return false;
- }
-
- public bool Equals(Quat other)
- {
- return x == other.x && y == other.y && z == other.z && w == other.w;
- }
-
- /// <summary>
- /// Returns true if this quaternion and `other` are approximately equal, by running
- /// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
- /// </summary>
- /// <param name="other">The other quaternion to compare.</param>
- /// <returns>Whether or not the quaternions are approximately equal.</returns>
- public bool IsEqualApprox(Quat other)
- {
- return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
- }
-
- public override int GetHashCode()
- {
- return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
- }
-
- public override string ToString()
- {
- return String.Format("({0}, {1}, {2}, {3})", x.ToString(), y.ToString(), z.ToString(), w.ToString());
- }
-
- public string ToString(string format)
- {
- return String.Format("({0}, {1}, {2}, {3})", x.ToString(format), y.ToString(format), z.ToString(format), w.ToString(format));
- }
- }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
new file mode 100644
index 0000000000..b087b4c200
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
@@ -0,0 +1,541 @@
+using System;
+using System.Runtime.InteropServices;
+#if REAL_T_IS_DOUBLE
+using real_t = System.Double;
+#else
+using real_t = System.Single;
+#endif
+
+namespace Godot
+{
+ /// <summary>
+ /// A unit quaternion used for representing 3D rotations.
+ /// Quaternions need to be normalized to be used for rotation.
+ ///
+ /// It is similar to Basis, which implements matrix representation of
+ /// rotations, and can be parametrized using both an axis-angle pair
+ /// or Euler angles. Basis stores rotation, scale, and shearing,
+ /// while Quaternion only stores rotation.
+ ///
+ /// Due to its compactness and the way it is stored in memory, certain
+ /// operations (obtaining axis-angle and performing SLERP, in particular)
+ /// are more efficient and robust against floating-point errors.
+ /// </summary>
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Quaternion : IEquatable<Quaternion>
+ {
+ /// <summary>
+ /// X component of the quaternion (imaginary `i` axis part).
+ /// Quaternion components should usually not be manipulated directly.
+ /// </summary>
+ public real_t x;
+
+ /// <summary>
+ /// Y component of the quaternion (imaginary `j` axis part).
+ /// Quaternion components should usually not be manipulated directly.
+ /// </summary>
+ public real_t y;
+
+ /// <summary>
+ /// Z component of the quaternion (imaginary `k` axis part).
+ /// Quaternion components should usually not be manipulated directly.
+ /// </summary>
+ public real_t z;
+
+ /// <summary>
+ /// W component of the quaternion (real part).
+ /// Quaternion components should usually not be manipulated directly.
+ /// </summary>
+ public real_t w;
+
+ /// <summary>
+ /// Access quaternion components using their index.
+ /// </summary>
+ /// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`, `[3]` is equivalent to `.w`.</value>
+ public real_t this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ break;
+ case 1:
+ y = value;
+ break;
+ case 2:
+ z = value;
+ break;
+ case 3:
+ w = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the length (magnitude) of the quaternion.
+ /// </summary>
+ /// <value>Equivalent to `Mathf.Sqrt(LengthSquared)`.</value>
+ public real_t Length
+ {
+ get { return Mathf.Sqrt(LengthSquared); }
+ }
+
+ /// <summary>
+ /// Returns the squared length (squared magnitude) of the quaternion.
+ /// This method runs faster than <see cref="Length"/>, so prefer it if
+ /// you need to compare quaternions or need the squared length for some formula.
+ /// </summary>
+ /// <value>Equivalent to `Dot(this)`.</value>
+ public real_t LengthSquared
+ {
+ get { return Dot(this); }
+ }
+
+ /// <summary>
+ /// Performs a cubic spherical interpolation between quaternions `preA`,
+ /// this vector, `b`, and `postB`, by the given amount `t`.
+ /// </summary>
+ /// <param name="b">The destination quaternion.</param>
+ /// <param name="preA">A quaternion before this quaternion.</param>
+ /// <param name="postB">A quaternion after `b`.</param>
+ /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The interpolated quaternion.</returns>
+ public Quaternion CubicSlerp(Quaternion b, Quaternion preA, Quaternion postB, real_t weight)
+ {
+ real_t t2 = (1.0f - weight) * weight * 2f;
+ Quaternion sp = Slerp(b, weight);
+ Quaternion sq = preA.Slerpni(postB, weight);
+ return sp.Slerpni(sq, t2);
+ }
+
+ /// <summary>
+ /// Returns the dot product of two quaternions.
+ /// </summary>
+ /// <param name="b">The other quaternion.</param>
+ /// <returns>The dot product.</returns>
+ public real_t Dot(Quaternion b)
+ {
+ return x * b.x + y * b.y + z * b.z + w * b.w;
+ }
+
+ /// <summary>
+ /// Returns Euler angles (in the YXZ convention: when decomposing,
+ /// first Z, then X, and Y last) corresponding to the rotation
+ /// represented by the unit quaternion. Returned vector contains
+ /// the rotation angles in the format (X angle, Y angle, Z angle).
+ /// </summary>
+ /// <returns>The Euler angle representation of this quaternion.</returns>
+ public Vector3 GetEuler()
+ {
+#if DEBUG
+ if (!IsNormalized())
+ {
+ throw new InvalidOperationException("Quaternion is not normalized");
+ }
+#endif
+ var basis = new Basis(this);
+ return basis.GetEuler();
+ }
+
+ /// <summary>
+ /// Returns the inverse of the quaternion.
+ /// </summary>
+ /// <returns>The inverse quaternion.</returns>
+ public Quaternion Inverse()
+ {
+#if DEBUG
+ if (!IsNormalized())
+ {
+ throw new InvalidOperationException("Quaternion is not normalized");
+ }
+#endif
+ return new Quaternion(-x, -y, -z, w);
+ }
+
+ /// <summary>
+ /// Returns whether the quaternion is normalized or not.
+ /// </summary>
+ /// <returns>A bool for whether the quaternion is normalized or not.</returns>
+ public bool IsNormalized()
+ {
+ return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
+ }
+
+ /// <summary>
+ /// Returns a copy of the quaternion, normalized to unit length.
+ /// </summary>
+ /// <returns>The normalized quaternion.</returns>
+ public Quaternion Normalized()
+ {
+ return this / Length;
+ }
+
+ /// <summary>
+ /// Returns the result of the spherical linear interpolation between
+ /// this quaternion and `to` by amount `weight`.
+ ///
+ /// Note: Both quaternions must be normalized.
+ /// </summary>
+ /// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
+ /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting quaternion of the interpolation.</returns>
+ public Quaternion Slerp(Quaternion to, real_t weight)
+ {
+#if DEBUG
+ if (!IsNormalized())
+ {
+ throw new InvalidOperationException("Quaternion is not normalized");
+ }
+ if (!to.IsNormalized())
+ {
+ throw new ArgumentException("Argument is not normalized", nameof(to));
+ }
+#endif
+
+ // Calculate cosine.
+ real_t cosom = x * to.x + y * to.y + z * to.z + w * to.w;
+
+ var to1 = new Quaternion();
+
+ // Adjust signs if necessary.
+ if (cosom < 0.0)
+ {
+ cosom = -cosom;
+ to1.x = -to.x;
+ to1.y = -to.y;
+ to1.z = -to.z;
+ to1.w = -to.w;
+ }
+ else
+ {
+ to1.x = to.x;
+ to1.y = to.y;
+ to1.z = to.z;
+ to1.w = to.w;
+ }
+
+ real_t sinom, scale0, scale1;
+
+ // Calculate coefficients.
+ if (1.0 - cosom > Mathf.Epsilon)
+ {
+ // Standard case (Slerp).
+ real_t omega = Mathf.Acos(cosom);
+ sinom = Mathf.Sin(omega);
+ scale0 = Mathf.Sin((1.0f - weight) * omega) / sinom;
+ scale1 = Mathf.Sin(weight * omega) / sinom;
+ }
+ else
+ {
+ // Quaternions are very close so we can do a linear interpolation.
+ scale0 = 1.0f - weight;
+ scale1 = weight;
+ }
+
+ // Calculate final values.
+ return new Quaternion
+ (
+ scale0 * x + scale1 * to1.x,
+ scale0 * y + scale1 * to1.y,
+ scale0 * z + scale1 * to1.z,
+ scale0 * w + scale1 * to1.w
+ );
+ }
+
+ /// <summary>
+ /// Returns the result of the spherical linear interpolation between
+ /// this quaternion and `to` by amount `weight`, but without
+ /// checking if the rotation path is not bigger than 90 degrees.
+ /// </summary>
+ /// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
+ /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting quaternion of the interpolation.</returns>
+ public Quaternion Slerpni(Quaternion to, real_t weight)
+ {
+ real_t dot = Dot(to);
+
+ if (Mathf.Abs(dot) > 0.9999f)
+ {
+ return this;
+ }
+
+ real_t theta = Mathf.Acos(dot);
+ real_t sinT = 1.0f / Mathf.Sin(theta);
+ real_t newFactor = Mathf.Sin(weight * theta) * sinT;
+ real_t invFactor = Mathf.Sin((1.0f - weight) * theta) * sinT;
+
+ return new Quaternion
+ (
+ invFactor * x + newFactor * to.x,
+ invFactor * y + newFactor * to.y,
+ invFactor * z + newFactor * to.z,
+ invFactor * w + newFactor * to.w
+ );
+ }
+
+ /// <summary>
+ /// Returns a vector transformed (multiplied) by this quaternion.
+ /// </summary>
+ /// <param name="v">A vector to transform.</param>
+ /// <returns>The transformed vector.</returns>
+ public Vector3 Xform(Vector3 v)
+ {
+#if DEBUG
+ if (!IsNormalized())
+ {
+ throw new InvalidOperationException("Quaternion is not normalized");
+ }
+#endif
+ var u = new Vector3(x, y, z);
+ Vector3 uv = u.Cross(v);
+ return v + ((uv * w) + u.Cross(uv)) * 2;
+ }
+
+ // Constants
+ private static readonly Quaternion _identity = new Quaternion(0, 0, 0, 1);
+
+ /// <summary>
+ /// The identity quaternion, representing no rotation.
+ /// Equivalent to an identity <see cref="Basis"/> matrix. If a vector is transformed by
+ /// an identity quaternion, it will not change.
+ /// </summary>
+ /// <value>Equivalent to `new Quaternion(0, 0, 0, 1)`.</value>
+ public static Quaternion Identity { get { return _identity; } }
+
+ /// <summary>
+ /// Constructs a quaternion defined by the given values.
+ /// </summary>
+ /// <param name="x">X component of the quaternion (imaginary `i` axis part).</param>
+ /// <param name="y">Y component of the quaternion (imaginary `j` axis part).</param>
+ /// <param name="z">Z component of the quaternion (imaginary `k` axis part).</param>
+ /// <param name="w">W component of the quaternion (real part).</param>
+ public Quaternion(real_t x, real_t y, real_t z, real_t w)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ /// <summary>
+ /// Constructs a quaternion from the given quaternion.
+ /// </summary>
+ /// <param name="q">The existing quaternion.</param>
+ public Quaternion(Quaternion q)
+ {
+ this = q;
+ }
+
+ /// <summary>
+ /// Constructs a quaternion from the given <see cref="Basis"/>.
+ /// </summary>
+ /// <param name="basis">The basis to construct from.</param>
+ public Quaternion(Basis basis)
+ {
+ this = basis.Quaternion();
+ }
+
+ /// <summary>
+ /// Constructs a quaternion that will perform a rotation specified by
+ /// Euler angles (in the YXZ convention: when decomposing,
+ /// first Z, then X, and Y last),
+ /// given in the vector format as (X angle, Y angle, Z angle).
+ /// </summary>
+ /// <param name="eulerYXZ"></param>
+ public Quaternion(Vector3 eulerYXZ)
+ {
+ real_t half_a1 = eulerYXZ.y * 0.5f;
+ real_t half_a2 = eulerYXZ.x * 0.5f;
+ real_t half_a3 = eulerYXZ.z * 0.5f;
+
+ // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
+ // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
+ // a3 is the angle of the first rotation, following the notation in this reference.
+
+ real_t cos_a1 = Mathf.Cos(half_a1);
+ real_t sin_a1 = Mathf.Sin(half_a1);
+ real_t cos_a2 = Mathf.Cos(half_a2);
+ real_t sin_a2 = Mathf.Sin(half_a2);
+ real_t cos_a3 = Mathf.Cos(half_a3);
+ real_t sin_a3 = Mathf.Sin(half_a3);
+
+ x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
+ y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
+ z = cos_a1 * cos_a2 * sin_a3 - sin_a1 * sin_a2 * cos_a3;
+ w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
+ }
+
+ /// <summary>
+ /// Constructs a quaternion that will rotate around the given axis
+ /// by the specified angle. The axis must be a normalized vector.
+ /// </summary>
+ /// <param name="axis">The axis to rotate around. Must be normalized.</param>
+ /// <param name="angle">The angle to rotate, in radians.</param>
+ public Quaternion(Vector3 axis, real_t angle)
+ {
+#if DEBUG
+ if (!axis.IsNormalized())
+ {
+ throw new ArgumentException("Argument is not normalized", nameof(axis));
+ }
+#endif
+
+ real_t d = axis.Length();
+
+ if (d == 0f)
+ {
+ x = 0f;
+ y = 0f;
+ z = 0f;
+ w = 0f;
+ }
+ else
+ {
+ real_t sinAngle = Mathf.Sin(angle * 0.5f);
+ real_t cosAngle = Mathf.Cos(angle * 0.5f);
+ real_t s = sinAngle / d;
+
+ x = axis.x * s;
+ y = axis.y * s;
+ z = axis.z * s;
+ w = cosAngle;
+ }
+ }
+
+ public static Quaternion operator *(Quaternion left, Quaternion right)
+ {
+ return new Quaternion
+ (
+ left.w * right.x + left.x * right.w + left.y * right.z - left.z * right.y,
+ left.w * right.y + left.y * right.w + left.z * right.x - left.x * right.z,
+ left.w * right.z + left.z * right.w + left.x * right.y - left.y * right.x,
+ left.w * right.w - left.x * right.x - left.y * right.y - left.z * right.z
+ );
+ }
+
+ public static Quaternion operator +(Quaternion left, Quaternion right)
+ {
+ return new Quaternion(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w);
+ }
+
+ public static Quaternion operator -(Quaternion left, Quaternion right)
+ {
+ return new Quaternion(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w);
+ }
+
+ public static Quaternion operator -(Quaternion left)
+ {
+ return new Quaternion(-left.x, -left.y, -left.z, -left.w);
+ }
+
+ public static Quaternion operator *(Quaternion left, Vector3 right)
+ {
+ return new Quaternion
+ (
+ left.w * right.x + left.y * right.z - left.z * right.y,
+ left.w * right.y + left.z * right.x - left.x * right.z,
+ left.w * right.z + left.x * right.y - left.y * right.x,
+ -left.x * right.x - left.y * right.y - left.z * right.z
+ );
+ }
+
+ public static Quaternion operator *(Vector3 left, Quaternion right)
+ {
+ return new Quaternion
+ (
+ right.w * left.x + right.y * left.z - right.z * left.y,
+ right.w * left.y + right.z * left.x - right.x * left.z,
+ right.w * left.z + right.x * left.y - right.y * left.x,
+ -right.x * left.x - right.y * left.y - right.z * left.z
+ );
+ }
+
+ public static Quaternion operator *(Quaternion left, real_t right)
+ {
+ return new Quaternion(left.x * right, left.y * right, left.z * right, left.w * right);
+ }
+
+ public static Quaternion operator *(real_t left, Quaternion right)
+ {
+ return new Quaternion(right.x * left, right.y * left, right.z * left, right.w * left);
+ }
+
+ public static Quaternion operator /(Quaternion left, real_t right)
+ {
+ return left * (1.0f / right);
+ }
+
+ public static bool operator ==(Quaternion left, Quaternion right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Quaternion left, Quaternion right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Quaternion)
+ {
+ return Equals((Quaternion)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Quaternion other)
+ {
+ return x == other.x && y == other.y && z == other.z && w == other.w;
+ }
+
+ /// <summary>
+ /// Returns true if this quaternion and `other` are approximately equal, by running
+ /// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
+ /// </summary>
+ /// <param name="other">The other quaternion to compare.</param>
+ /// <returns>Whether or not the quaternions are approximately equal.</returns>
+ public bool IsEqualApprox(Quaternion other)
+ {
+ return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
+ }
+
+ public override int GetHashCode()
+ {
+ return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1}, {2}, {3})", x.ToString(), y.ToString(), z.ToString(), w.ToString());
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1}, {2}, {3})", x.ToString(format), y.ToString(format), z.ToString(format), w.ToString(format));
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index 868c3536fe..612fb64a3d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
@@ -405,7 +405,7 @@ namespace Godot
public override string ToString()
{
- return String.Format("({0}, {1})", new object[]
+ return String.Format("{0}, {1}", new object[]
{
_position.ToString(),
_size.ToString()
@@ -414,7 +414,7 @@ namespace Godot
public string ToString(string format)
{
- return String.Format("({0}, {1})", new object[]
+ return String.Format("{0}, {1}", new object[]
{
_position.ToString(format),
_size.ToString(format)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs
deleted file mode 100644
index ac47f6029f..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs
+++ /dev/null
@@ -1,412 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-#if REAL_T_IS_DOUBLE
-using real_t = System.Double;
-#else
-using real_t = System.Single;
-#endif
-
-namespace Godot
-{
- /// <summary>
- /// 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations.
- /// It can represent transformations such as translation, rotation, or scaling.
- /// It consists of a <see cref="Basis"/> (first 3 columns) and a
- /// <see cref="Vector3"/> for the origin (last column).
- ///
- /// For more information, read this documentation article:
- /// https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html
- /// </summary>
- [Serializable]
- [StructLayout(LayoutKind.Sequential)]
- public struct Transform : IEquatable<Transform>
- {
- /// <summary>
- /// The <see cref="Basis"/> of this transform. Contains the X, Y, and Z basis
- /// vectors (columns 0 to 2) and is responsible for rotation and scale.
- /// </summary>
- public Basis basis;
-
- /// <summary>
- /// The origin vector (column 3, the fourth column). Equivalent to array index `[3]`.
- /// </summary>
- public Vector3 origin;
-
- /// <summary>
- /// Access whole columns in the form of Vector3. The fourth column is the origin vector.
- /// </summary>
- /// <param name="column">Which column vector.</param>
- public Vector3 this[int column]
- {
- get
- {
- switch (column)
- {
- case 0:
- return basis.Column0;
- case 1:
- return basis.Column1;
- case 2:
- return basis.Column2;
- case 3:
- return origin;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- set
- {
- switch (column)
- {
- case 0:
- basis.Column0 = value;
- return;
- case 1:
- basis.Column1 = value;
- return;
- case 2:
- basis.Column2 = value;
- return;
- case 3:
- origin = value;
- return;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- }
-
- /// <summary>
- /// Access matrix elements in column-major order. The fourth column is the origin vector.
- /// </summary>
- /// <param name="column">Which column, the matrix horizontal position.</param>
- /// <param name="row">Which row, the matrix vertical position.</param>
- public real_t this[int column, int row]
- {
- get
- {
- if (column == 3)
- {
- return origin[row];
- }
- return basis[column, row];
- }
- set
- {
- if (column == 3)
- {
- origin[row] = value;
- return;
- }
- basis[column, row] = value;
- }
- }
-
- /// <summary>
- /// Returns the inverse of the transform, under the assumption that
- /// the transformation is composed of rotation, scaling, and translation.
- /// </summary>
- /// <returns>The inverse transformation matrix.</returns>
- public Transform AffineInverse()
- {
- Basis basisInv = basis.Inverse();
- return new Transform(basisInv, basisInv.Xform(-origin));
- }
-
- /// <summary>
- /// Interpolates this transform to the other `transform` by `weight`.
- /// </summary>
- /// <param name="transform">The other transform.</param>
- /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
- /// <returns>The interpolated transform.</returns>
- public Transform InterpolateWith(Transform transform, real_t weight)
- {
- /* not sure if very "efficient" but good enough? */
-
- Vector3 sourceScale = basis.Scale;
- Quat sourceRotation = basis.RotationQuat();
- Vector3 sourceLocation = origin;
-
- Vector3 destinationScale = transform.basis.Scale;
- Quat destinationRotation = transform.basis.RotationQuat();
- Vector3 destinationLocation = transform.origin;
-
- var interpolated = new Transform();
- interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, weight).Normalized(), sourceScale.Lerp(destinationScale, weight));
- interpolated.origin = sourceLocation.Lerp(destinationLocation, weight);
-
- return interpolated;
- }
-
- /// <summary>
- /// Returns the inverse of the transform, under the assumption that
- /// the transformation is composed of rotation and translation
- /// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
- /// </summary>
- /// <returns>The inverse matrix.</returns>
- public Transform Inverse()
- {
- Basis basisTr = basis.Transposed();
- return new Transform(basisTr, basisTr.Xform(-origin));
- }
-
- /// <summary>
- /// Returns a copy of the transform rotated such that its
- /// -Z axis (forward) points towards the target position.
- ///
- /// The transform will first be rotated around the given up vector,
- /// and then fully aligned to the target by a further rotation around
- /// an axis perpendicular to both the target and up vectors.
- ///
- /// Operations take place in global space.
- /// </summary>
- /// <param name="target">The object to look at.</param>
- /// <param name="up">The relative up direction</param>
- /// <returns>The resulting transform.</returns>
- public Transform LookingAt(Vector3 target, Vector3 up)
- {
- var t = this;
- t.SetLookAt(origin, target, up);
- return t;
- }
-
- /// <summary>
- /// Returns the transform with the basis orthogonal (90 degrees),
- /// and normalized axis vectors (scale of 1 or -1).
- /// </summary>
- /// <returns>The orthonormalized transform.</returns>
- public Transform Orthonormalized()
- {
- return new Transform(basis.Orthonormalized(), origin);
- }
-
- /// <summary>
- /// Rotates the transform around the given `axis` by `phi` (in radians),
- /// using matrix multiplication. The axis must be a normalized vector.
- /// </summary>
- /// <param name="axis">The axis to rotate around. Must be normalized.</param>
- /// <param name="phi">The angle to rotate, in radians.</param>
- /// <returns>The rotated transformation matrix.</returns>
- public Transform Rotated(Vector3 axis, real_t phi)
- {
- return new Transform(new Basis(axis, phi), new Vector3()) * this;
- }
-
- /// <summary>
- /// Scales the transform by the given 3D scaling factor, using matrix multiplication.
- /// </summary>
- /// <param name="scale">The scale to introduce.</param>
- /// <returns>The scaled transformation matrix.</returns>
- public Transform Scaled(Vector3 scale)
- {
- return new Transform(basis.Scaled(scale), origin * scale);
- }
-
- private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
- {
- // Make rotation matrix
- // Z vector
- Vector3 column2 = eye - target;
-
- column2.Normalize();
-
- Vector3 column1 = up;
-
- Vector3 column0 = column1.Cross(column2);
-
- // Recompute Y = Z cross X
- column1 = column2.Cross(column0);
-
- column0.Normalize();
- column1.Normalize();
-
- basis = new Basis(column0, column1, column2);
-
- origin = eye;
- }
-
- /// <summary>
- /// Translates the transform by the given `offset`,
- /// relative to the transform's basis vectors.
- ///
- /// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
- /// this does not use matrix multiplication.
- /// </summary>
- /// <param name="offset">The offset to translate by.</param>
- /// <returns>The translated matrix.</returns>
- public Transform Translated(Vector3 offset)
- {
- return new Transform(basis, new Vector3
- (
- origin[0] += basis.Row0.Dot(offset),
- origin[1] += basis.Row1.Dot(offset),
- origin[2] += basis.Row2.Dot(offset)
- ));
- }
-
- /// <summary>
- /// Returns a vector transformed (multiplied) by this transformation matrix.
- /// </summary>
- /// <param name="v">A vector to transform.</param>
- /// <returns>The transformed vector.</returns>
- public Vector3 Xform(Vector3 v)
- {
- return new Vector3
- (
- basis.Row0.Dot(v) + origin.x,
- basis.Row1.Dot(v) + origin.y,
- basis.Row2.Dot(v) + origin.z
- );
- }
-
- /// <summary>
- /// Returns a vector transformed (multiplied) by the transposed transformation matrix.
- ///
- /// Note: This results in a multiplication by the inverse of the
- /// transformation matrix only if it represents a rotation-reflection.
- /// </summary>
- /// <param name="v">A vector to inversely transform.</param>
- /// <returns>The inversely transformed vector.</returns>
- public Vector3 XformInv(Vector3 v)
- {
- Vector3 vInv = v - origin;
-
- return new Vector3
- (
- basis.Row0[0] * vInv.x + basis.Row1[0] * vInv.y + basis.Row2[0] * vInv.z,
- basis.Row0[1] * vInv.x + basis.Row1[1] * vInv.y + basis.Row2[1] * vInv.z,
- basis.Row0[2] * vInv.x + basis.Row1[2] * vInv.y + basis.Row2[2] * vInv.z
- );
- }
-
- // Constants
- private static readonly Transform _identity = new Transform(Basis.Identity, Vector3.Zero);
- private static readonly Transform _flipX = new Transform(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero);
- private static readonly Transform _flipY = new Transform(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
- private static readonly Transform _flipZ = new Transform(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
-
- /// <summary>
- /// The identity transform, with no translation, rotation, or scaling applied.
- /// This is used as a replacement for `Transform()` in GDScript.
- /// Do not use `new Transform()` with no arguments in C#, because it sets all values to zero.
- /// </summary>
- /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Back, Vector3.Zero)`.</value>
- public static Transform Identity { get { return _identity; } }
- /// <summary>
- /// The transform that will flip something along the X axis.
- /// </summary>
- /// <value>Equivalent to `new Transform(Vector3.Left, Vector3.Up, Vector3.Back, Vector3.Zero)`.</value>
- public static Transform FlipX { get { return _flipX; } }
- /// <summary>
- /// The transform that will flip something along the Y axis.
- /// </summary>
- /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Down, Vector3.Back, Vector3.Zero)`.</value>
- public static Transform FlipY { get { return _flipY; } }
- /// <summary>
- /// The transform that will flip something along the Z axis.
- /// </summary>
- /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Forward, Vector3.Zero)`.</value>
- public static Transform FlipZ { get { return _flipZ; } }
-
- /// <summary>
- /// Constructs a transformation matrix from 4 vectors (matrix columns).
- /// </summary>
- /// <param name="column0">The X vector, or column index 0.</param>
- /// <param name="column1">The Y vector, or column index 1.</param>
- /// <param name="column2">The Z vector, or column index 2.</param>
- /// <param name="origin">The origin vector, or column index 3.</param>
- public Transform(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
- {
- basis = new Basis(column0, column1, column2);
- this.origin = origin;
- }
-
- /// <summary>
- /// Constructs a transformation matrix from the given quaternion and origin vector.
- /// </summary>
- /// <param name="quat">The <see cref="Godot.Quat"/> to create the basis from.</param>
- /// <param name="origin">The origin vector, or column index 3.</param>
- public Transform(Quat quat, Vector3 origin)
- {
- basis = new Basis(quat);
- this.origin = origin;
- }
-
- /// <summary>
- /// Constructs a transformation matrix from the given basis and origin vector.
- /// </summary>
- /// <param name="basis">The <see cref="Godot.Basis"/> to create the basis from.</param>
- /// <param name="origin">The origin vector, or column index 3.</param>
- public Transform(Basis basis, Vector3 origin)
- {
- this.basis = basis;
- this.origin = origin;
- }
-
- public static Transform operator *(Transform left, Transform right)
- {
- left.origin = left.Xform(right.origin);
- left.basis *= right.basis;
- return left;
- }
-
- public static bool operator ==(Transform left, Transform right)
- {
- return left.Equals(right);
- }
-
- public static bool operator !=(Transform left, Transform right)
- {
- return !left.Equals(right);
- }
-
- public override bool Equals(object obj)
- {
- if (obj is Transform)
- {
- return Equals((Transform)obj);
- }
-
- return false;
- }
-
- public bool Equals(Transform other)
- {
- return basis.Equals(other.basis) && origin.Equals(other.origin);
- }
-
- /// <summary>
- /// Returns true if this transform and `other` are approximately equal, by running
- /// <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
- /// </summary>
- /// <param name="other">The other transform to compare.</param>
- /// <returns>Whether or not the matrices are approximately equal.</returns>
- public bool IsEqualApprox(Transform other)
- {
- return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin);
- }
-
- public override int GetHashCode()
- {
- return basis.GetHashCode() ^ origin.GetHashCode();
- }
-
- public override string ToString()
- {
- return String.Format("{0} - {1}", new object[]
- {
- basis.ToString(),
- origin.ToString()
- });
- }
-
- public string ToString(string format)
- {
- return String.Format("{0} - {1}", new object[]
- {
- basis.ToString(format),
- origin.ToString(format)
- });
- }
- }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index bc0f81b2a7..fe93592667 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -492,22 +492,16 @@ namespace Godot
public override string ToString()
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- x.ToString(),
- y.ToString(),
- origin.ToString()
- });
+ return "[X: " + x.ToString() +
+ ", Y: " + y.ToString() +
+ ", O: " + origin.ToString() + "]";
}
public string ToString(string format)
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- x.ToString(format),
- y.ToString(format),
- origin.ToString(format)
- });
+ return "[X: " + x.ToString(format) +
+ ", Y: " + y.ToString(format) +
+ ", O: " + origin.ToString(format) + "]";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
new file mode 100644
index 0000000000..26b1a9e8b2
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -0,0 +1,410 @@
+using System;
+using System.Runtime.InteropServices;
+#if REAL_T_IS_DOUBLE
+using real_t = System.Double;
+#else
+using real_t = System.Single;
+#endif
+
+namespace Godot
+{
+ /// <summary>
+ /// 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations.
+ /// It can represent transformations such as translation, rotation, or scaling.
+ /// It consists of a <see cref="Basis"/> (first 3 columns) and a
+ /// <see cref="Vector3"/> for the origin (last column).
+ ///
+ /// For more information, read this documentation article:
+ /// https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html
+ /// </summary>
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Transform3D : IEquatable<Transform3D>
+ {
+ /// <summary>
+ /// The <see cref="Basis"/> of this transform. Contains the X, Y, and Z basis
+ /// vectors (columns 0 to 2) and is responsible for rotation and scale.
+ /// </summary>
+ public Basis basis;
+
+ /// <summary>
+ /// The origin vector (column 3, the fourth column). Equivalent to array index `[3]`.
+ /// </summary>
+ public Vector3 origin;
+
+ /// <summary>
+ /// Access whole columns in the form of Vector3. The fourth column is the origin vector.
+ /// </summary>
+ /// <param name="column">Which column vector.</param>
+ public Vector3 this[int column]
+ {
+ get
+ {
+ switch (column)
+ {
+ case 0:
+ return basis.Column0;
+ case 1:
+ return basis.Column1;
+ case 2:
+ return basis.Column2;
+ case 3:
+ return origin;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (column)
+ {
+ case 0:
+ basis.Column0 = value;
+ return;
+ case 1:
+ basis.Column1 = value;
+ return;
+ case 2:
+ basis.Column2 = value;
+ return;
+ case 3:
+ origin = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Access matrix elements in column-major order. The fourth column is the origin vector.
+ /// </summary>
+ /// <param name="column">Which column, the matrix horizontal position.</param>
+ /// <param name="row">Which row, the matrix vertical position.</param>
+ public real_t this[int column, int row]
+ {
+ get
+ {
+ if (column == 3)
+ {
+ return origin[row];
+ }
+ return basis[column, row];
+ }
+ set
+ {
+ if (column == 3)
+ {
+ origin[row] = value;
+ return;
+ }
+ basis[column, row] = value;
+ }
+ }
+
+ /// <summary>
+ /// Returns the inverse of the transform, under the assumption that
+ /// the transformation is composed of rotation, scaling, and translation.
+ /// </summary>
+ /// <returns>The inverse transformation matrix.</returns>
+ public Transform3D AffineInverse()
+ {
+ Basis basisInv = basis.Inverse();
+ return new Transform3D(basisInv, basisInv.Xform(-origin));
+ }
+
+ /// <summary>
+ /// Interpolates this transform to the other `transform` by `weight`.
+ /// </summary>
+ /// <param name="transform">The other transform.</param>
+ /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The interpolated transform.</returns>
+ public Transform3D InterpolateWith(Transform3D transform, real_t weight)
+ {
+ /* not sure if very "efficient" but good enough? */
+
+ Vector3 sourceScale = basis.Scale;
+ Quaternion sourceRotation = basis.RotationQuaternion();
+ Vector3 sourceLocation = origin;
+
+ Vector3 destinationScale = transform.basis.Scale;
+ Quaternion destinationRotation = transform.basis.RotationQuaternion();
+ Vector3 destinationLocation = transform.origin;
+
+ var interpolated = new Transform3D();
+ interpolated.basis.SetQuaternionScale(sourceRotation.Slerp(destinationRotation, weight).Normalized(), sourceScale.Lerp(destinationScale, weight));
+ interpolated.origin = sourceLocation.Lerp(destinationLocation, weight);
+
+ return interpolated;
+ }
+
+ /// <summary>
+ /// Returns the inverse of the transform, under the assumption that
+ /// the transformation is composed of rotation and translation
+ /// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
+ /// </summary>
+ /// <returns>The inverse matrix.</returns>
+ public Transform3D Inverse()
+ {
+ Basis basisTr = basis.Transposed();
+ return new Transform3D(basisTr, basisTr.Xform(-origin));
+ }
+
+ /// <summary>
+ /// Returns a copy of the transform rotated such that its
+ /// -Z axis (forward) points towards the target position.
+ ///
+ /// The transform will first be rotated around the given up vector,
+ /// and then fully aligned to the target by a further rotation around
+ /// an axis perpendicular to both the target and up vectors.
+ ///
+ /// Operations take place in global space.
+ /// </summary>
+ /// <param name="target">The object to look at.</param>
+ /// <param name="up">The relative up direction</param>
+ /// <returns>The resulting transform.</returns>
+ public Transform3D LookingAt(Vector3 target, Vector3 up)
+ {
+ var t = this;
+ t.SetLookAt(origin, target, up);
+ return t;
+ }
+
+ /// <summary>
+ /// Returns the transform with the basis orthogonal (90 degrees),
+ /// and normalized axis vectors (scale of 1 or -1).
+ /// </summary>
+ /// <returns>The orthonormalized transform.</returns>
+ public Transform3D Orthonormalized()
+ {
+ return new Transform3D(basis.Orthonormalized(), origin);
+ }
+
+ /// <summary>
+ /// Rotates the transform around the given `axis` by `phi` (in radians),
+ /// using matrix multiplication. The axis must be a normalized vector.
+ /// </summary>
+ /// <param name="axis">The axis to rotate around. Must be normalized.</param>
+ /// <param name="phi">The angle to rotate, in radians.</param>
+ /// <returns>The rotated transformation matrix.</returns>
+ public Transform3D Rotated(Vector3 axis, real_t phi)
+ {
+ return new Transform3D(new Basis(axis, phi), new Vector3()) * this;
+ }
+
+ /// <summary>
+ /// Scales the transform by the given 3D scaling factor, using matrix multiplication.
+ /// </summary>
+ /// <param name="scale">The scale to introduce.</param>
+ /// <returns>The scaled transformation matrix.</returns>
+ public Transform3D Scaled(Vector3 scale)
+ {
+ return new Transform3D(basis.Scaled(scale), origin * scale);
+ }
+
+ private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
+ {
+ // Make rotation matrix
+ // Z vector
+ Vector3 column2 = eye - target;
+
+ column2.Normalize();
+
+ Vector3 column1 = up;
+
+ Vector3 column0 = column1.Cross(column2);
+
+ // Recompute Y = Z cross X
+ column1 = column2.Cross(column0);
+
+ column0.Normalize();
+ column1.Normalize();
+
+ basis = new Basis(column0, column1, column2);
+
+ origin = eye;
+ }
+
+ /// <summary>
+ /// Translates the transform by the given `offset`,
+ /// relative to the transform's basis vectors.
+ ///
+ /// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
+ /// this does not use matrix multiplication.
+ /// </summary>
+ /// <param name="offset">The offset to translate by.</param>
+ /// <returns>The translated matrix.</returns>
+ public Transform3D Translated(Vector3 offset)
+ {
+ return new Transform3D(basis, new Vector3
+ (
+ origin[0] += basis.Row0.Dot(offset),
+ origin[1] += basis.Row1.Dot(offset),
+ origin[2] += basis.Row2.Dot(offset)
+ ));
+ }
+
+ /// <summary>
+ /// Returns a vector transformed (multiplied) by this transformation matrix.
+ /// </summary>
+ /// <param name="v">A vector to transform.</param>
+ /// <returns>The transformed vector.</returns>
+ public Vector3 Xform(Vector3 v)
+ {
+ return new Vector3
+ (
+ basis.Row0.Dot(v) + origin.x,
+ basis.Row1.Dot(v) + origin.y,
+ basis.Row2.Dot(v) + origin.z
+ );
+ }
+
+ /// <summary>
+ /// Returns a vector transformed (multiplied) by the transposed transformation matrix.
+ ///
+ /// Note: This results in a multiplication by the inverse of the
+ /// transformation matrix only if it represents a rotation-reflection.
+ /// </summary>
+ /// <param name="v">A vector to inversely transform.</param>
+ /// <returns>The inversely transformed vector.</returns>
+ public Vector3 XformInv(Vector3 v)
+ {
+ Vector3 vInv = v - origin;
+
+ return new Vector3
+ (
+ basis.Row0[0] * vInv.x + basis.Row1[0] * vInv.y + basis.Row2[0] * vInv.z,
+ basis.Row0[1] * vInv.x + basis.Row1[1] * vInv.y + basis.Row2[1] * vInv.z,
+ basis.Row0[2] * vInv.x + basis.Row1[2] * vInv.y + basis.Row2[2] * vInv.z
+ );
+ }
+
+ // Constants
+ private static readonly Transform3D _identity = new Transform3D(Basis.Identity, Vector3.Zero);
+ private static readonly Transform3D _flipX = new Transform3D(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero);
+ private static readonly Transform3D _flipY = new Transform3D(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
+ private static readonly Transform3D _flipZ = new Transform3D(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
+
+ /// <summary>
+ /// The identity transform, with no translation, rotation, or scaling applied.
+ /// This is used as a replacement for `Transform()` in GDScript.
+ /// Do not use `new Transform()` with no arguments in C#, because it sets all values to zero.
+ /// </summary>
+ /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Back, Vector3.Zero)`.</value>
+ public static Transform3D Identity { get { return _identity; } }
+ /// <summary>
+ /// The transform that will flip something along the X axis.
+ /// </summary>
+ /// <value>Equivalent to `new Transform(Vector3.Left, Vector3.Up, Vector3.Back, Vector3.Zero)`.</value>
+ public static Transform3D FlipX { get { return _flipX; } }
+ /// <summary>
+ /// The transform that will flip something along the Y axis.
+ /// </summary>
+ /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Down, Vector3.Back, Vector3.Zero)`.</value>
+ public static Transform3D FlipY { get { return _flipY; } }
+ /// <summary>
+ /// The transform that will flip something along the Z axis.
+ /// </summary>
+ /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Forward, Vector3.Zero)`.</value>
+ public static Transform3D FlipZ { get { return _flipZ; } }
+
+ /// <summary>
+ /// Constructs a transformation matrix from 4 vectors (matrix columns).
+ /// </summary>
+ /// <param name="column0">The X vector, or column index 0.</param>
+ /// <param name="column1">The Y vector, or column index 1.</param>
+ /// <param name="column2">The Z vector, or column index 2.</param>
+ /// <param name="origin">The origin vector, or column index 3.</param>
+ public Transform3D(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
+ {
+ basis = new Basis(column0, column1, column2);
+ this.origin = origin;
+ }
+
+ /// <summary>
+ /// Constructs a transformation matrix from the given quaternion and origin vector.
+ /// </summary>
+ /// <param name="quaternion">The <see cref="Godot.Quaternion"/> to create the basis from.</param>
+ /// <param name="origin">The origin vector, or column index 3.</param>
+ public Transform3D(Quaternion quaternion, Vector3 origin)
+ {
+ basis = new Basis(quaternion);
+ this.origin = origin;
+ }
+
+ /// <summary>
+ /// Constructs a transformation matrix from the given basis and origin vector.
+ /// </summary>
+ /// <param name="basis">The <see cref="Godot.Basis"/> to create the basis from.</param>
+ /// <param name="origin">The origin vector, or column index 3.</param>
+ public Transform3D(Basis basis, Vector3 origin)
+ {
+ this.basis = basis;
+ this.origin = origin;
+ }
+
+ public static Transform3D operator *(Transform3D left, Transform3D right)
+ {
+ left.origin = left.Xform(right.origin);
+ left.basis *= right.basis;
+ return left;
+ }
+
+ public static bool operator ==(Transform3D left, Transform3D right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Transform3D left, Transform3D right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Transform3D)
+ {
+ return Equals((Transform3D)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Transform3D other)
+ {
+ return basis.Equals(other.basis) && origin.Equals(other.origin);
+ }
+
+ /// <summary>
+ /// Returns true if this transform and `other` are approximately equal, by running
+ /// <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
+ /// </summary>
+ /// <param name="other">The other transform to compare.</param>
+ /// <returns>Whether or not the matrices are approximately equal.</returns>
+ public bool IsEqualApprox(Transform3D other)
+ {
+ return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin);
+ }
+
+ public override int GetHashCode()
+ {
+ return basis.GetHashCode() ^ origin.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return "[X: " + basis.x.ToString() +
+ ", Y: " + basis.y.ToString() +
+ ", Z: " + basis.z.ToString() +
+ ", O: " + origin.ToString() + "]";
+ }
+
+ public string ToString(string format)
+ {
+ return "[X: " + basis.x.ToString(format) +
+ ", Y: " + basis.y.ToString(format) +
+ ", Z: " + basis.z.ToString(format) +
+ ", O: " + origin.ToString(format) + "]";
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 6279ea1ace..af053bd263 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -160,22 +160,20 @@ namespace Godot
}
/// <summary>
- /// Returns the vector with a maximum length by limiting its length to `length`.
+ /// Returns a new vector with all components clamped between the
+ /// components of `min` and `max` using
+ /// <see cref="Mathf.Clamp(real_t, real_t, real_t)"/>.
/// </summary>
- /// <param name="length">The length to limit to.</param>
- /// <returns>The vector with its length limited.</returns>
- public Vector2 Clamped(real_t length)
+ /// <param name="min">The vector with minimum allowed values.</param>
+ /// <param name="max">The vector with maximum allowed values.</param>
+ /// <returns>The vector with all components clamped.</returns>
+ public Vector2 Clamp(Vector2 min, Vector2 max)
{
- var v = this;
- real_t l = Length();
-
- if (l > 0 && length < l)
- {
- v /= l;
- v *= length;
- }
-
- return v;
+ return new Vector2
+ (
+ Mathf.Clamp(x, min.x, max.x),
+ Mathf.Clamp(y, min.y, max.y)
+ );
}
/// <summary>
@@ -335,6 +333,25 @@ namespace Godot
}
/// <summary>
+ /// Returns the vector with a maximum length by limiting its length to `length`.
+ /// </summary>
+ /// <param name="length">The length to limit to.</param>
+ /// <returns>The vector with its length limited.</returns>
+ public Vector2 LimitLength(real_t length = 1.0f)
+ {
+ Vector2 v = this;
+ real_t l = Length();
+
+ if (l > 0 && length < l)
+ {
+ v /= l;
+ v *= length;
+ }
+
+ return v;
+ }
+
+ /// <summary>
/// Returns the axis of the vector's largest value. See <see cref="Axis"/>.
/// If both components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
@@ -425,7 +442,7 @@ namespace Godot
#if DEBUG
if (!normal.IsNormalized())
{
- throw new ArgumentException("Argument is not normalized", nameof(normal));
+ throw new ArgumentException("Argument is not normalized", nameof(normal));
}
#endif
return 2 * Dot(normal) * normal - this;
@@ -519,7 +536,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Perpendicular()
+ public Vector2 Orthogonal()
{
return new Vector2(y, -x);
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
index 8dd9ab2f0d..9068593fd8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
@@ -120,6 +120,23 @@ namespace Godot
}
/// <summary>
+ /// Returns a new vector with all components clamped between the
+ /// components of `min` and `max` using
+ /// <see cref="Mathf.Clamp(int, int, int)"/>.
+ /// </summary>
+ /// <param name="min">The vector with minimum allowed values.</param>
+ /// <param name="max">The vector with maximum allowed values.</param>
+ /// <returns>The vector with all components clamped.</returns>
+ public Vector2i Clamp(Vector2i min, Vector2i max)
+ {
+ return new Vector2i
+ (
+ Mathf.Clamp(x, min.x, max.x),
+ Mathf.Clamp(y, min.y, max.y)
+ );
+ }
+
+ /// <summary>
/// Returns the cross product of this vector and `b`.
/// </summary>
/// <param name="b">The other vector.</param>
@@ -248,13 +265,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector rotated 90 degrees counter-clockwise
+ /// Returns a perpendicular vector rotated 90 degrees counter-clockwise
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Perpendicular()
+ public Vector2i Orthogonal()
{
- return new Vector2(y, -x);
+ return new Vector2i(y, -x);
}
// Constants
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 3b895bbbf6..31a9af2d9e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -140,6 +140,24 @@ namespace Godot
}
/// <summary>
+ /// Returns a new vector with all components clamped between the
+ /// components of `min` and `max` using
+ /// <see cref="Mathf.Clamp(real_t, real_t, real_t)"/>.
+ /// </summary>
+ /// <param name="min">The vector with minimum allowed values.</param>
+ /// <param name="max">The vector with maximum allowed values.</param>
+ /// <returns>The vector with all components clamped.</returns>
+ public Vector3 Clamp(Vector3 min, Vector3 max)
+ {
+ return new Vector3
+ (
+ Mathf.Clamp(x, min.x, max.x),
+ Mathf.Clamp(y, min.y, max.y),
+ Mathf.Clamp(z, min.z, max.z)
+ );
+ }
+
+ /// <summary>
/// Returns the cross product of this vector and `b`.
/// </summary>
/// <param name="b">The other vector.</param>
@@ -313,6 +331,25 @@ namespace Godot
}
/// <summary>
+ /// Returns the vector with a maximum length by limiting its length to `length`.
+ /// </summary>
+ /// <param name="length">The length to limit to.</param>
+ /// <returns>The vector with its length limited.</returns>
+ public Vector3 LimitLength(real_t length = 1.0f)
+ {
+ Vector3 v = this;
+ real_t l = Length();
+
+ if (l > 0 && length < l)
+ {
+ v /= l;
+ v *= length;
+ }
+
+ return v;
+ }
+
+ /// <summary>
/// Returns the axis of the vector's largest value. See <see cref="Axis"/>.
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
@@ -419,7 +456,7 @@ namespace Godot
#if DEBUG
if (!normal.IsNormalized())
{
- throw new ArgumentException("Argument is not normalized", nameof(normal));
+ throw new ArgumentException("Argument is not normalized", nameof(normal));
}
#endif
return 2.0f * Dot(normal) * normal - this;
@@ -437,7 +474,7 @@ namespace Godot
#if DEBUG
if (!axis.IsNormalized())
{
- throw new ArgumentException("Argument is not normalized", nameof(axis));
+ throw new ArgumentException("Argument is not normalized", nameof(axis));
}
#endif
return new Basis(axis, phi).Xform(this);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
index bf25ba9cb3..e727afa3ff 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
@@ -89,6 +89,24 @@ namespace Godot
}
/// <summary>
+ /// Returns a new vector with all components clamped between the
+ /// components of `min` and `max` using
+ /// <see cref="Mathf.Clamp(int, int, int)"/>.
+ /// </summary>
+ /// <param name="min">The vector with minimum allowed values.</param>
+ /// <param name="max">The vector with maximum allowed values.</param>
+ /// <returns>The vector with all components clamped.</returns>
+ public Vector3i Clamp(Vector3i min, Vector3i max)
+ {
+ return new Vector3i
+ (
+ Mathf.Clamp(x, min.x, max.x),
+ Mathf.Clamp(y, min.y, max.y),
+ Mathf.Clamp(z, min.z, max.z)
+ );
+ }
+
+ /// <summary>
/// Returns the squared distance between this vector and `b`.
/// This method runs faster than <see cref="DistanceTo"/>, so prefer it if
/// you need to compare vectors or need the squared distance for some formula.
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 54aaaf1f92..1fcfe74c86 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -50,7 +50,7 @@
<Compile Include="Core\NodePath.cs" />
<Compile Include="Core\Object.base.cs" />
<Compile Include="Core\Plane.cs" />
- <Compile Include="Core\Quat.cs" />
+ <Compile Include="Core\Quaternion.cs" />
<Compile Include="Core\Rect2.cs" />
<Compile Include="Core\Rect2i.cs" />
<Compile Include="Core\RID.cs" />
@@ -58,8 +58,8 @@
<Compile Include="Core\SignalAwaiter.cs" />
<Compile Include="Core\StringExtensions.cs" />
<Compile Include="Core\StringName.cs" />
- <Compile Include="Core\Transform.cs" />
<Compile Include="Core\Transform2D.cs" />
+ <Compile Include="Core\Transform3D.cs" />
<Compile Include="Core\UnhandledExceptionArgs.cs" />
<Compile Include="Core\Vector2.cs" />
<Compile Include="Core\Vector2i.cs" />
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 34a96eba17..2b6d2761ca 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -31,7 +31,7 @@
#ifdef MONO_GLUE_ENABLED
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/string/string_name.h"
#include "../csharp_script.h"
@@ -78,17 +78,17 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
}
}
-void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
+void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
#ifdef DEBUG_ENABLED
CRASH_COND(p_ptr == nullptr);
- // This is only called with Reference derived classes
- CRASH_COND(!Object::cast_to<Reference>(p_ptr));
+ // This is only called with RefCounted derived classes
+ CRASH_COND(!Object::cast_to<RefCounted>(p_ptr));
#endif
- Reference *ref = static_cast<Reference *>(p_ptr);
+ RefCounted *rc = static_cast<RefCounted *>(p_ptr);
- if (ref->get_script_instance()) {
- CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(ref->get_script_instance());
+ if (rc->get_script_instance()) {
+ CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(rc->get_script_instance());
if (cs_instance) {
if (!cs_instance->is_destructing_script_instance()) {
bool delete_owner;
@@ -97,9 +97,9 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolea
cs_instance->mono_object_disposed_baseref(p_obj, p_is_finalizer, delete_owner, remove_script_instance);
if (delete_owner) {
- memdelete(ref);
+ memdelete(rc);
} else if (remove_script_instance) {
- ref->set_script_instance(nullptr);
+ rc->set_script_instance(nullptr);
}
}
return;
@@ -108,11 +108,11 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolea
// Unsafe refcount decrement. The managed instance also counts as a reference.
// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
- CSharpLanguage::get_singleton()->pre_unsafe_unreference(ref);
- if (ref->unreference()) {
- memdelete(ref);
+ CSharpLanguage::get_singleton()->pre_unsafe_unreference(rc);
+ if (rc->unreference()) {
+ memdelete(rc);
} else {
- void *data = ref->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+ void *data = rc->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
if (data) {
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
@@ -145,10 +145,10 @@ MonoObject *godot_icall_Object_weakref(Object *p_ptr) {
}
Ref<WeakRef> wref;
- Reference *ref = Object::cast_to<Reference>(p_ptr);
+ RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
- if (ref) {
- REF r = ref;
+ if (rc) {
+ REF r = rc;
if (!r.is_valid()) {
return nullptr;
}
@@ -242,7 +242,7 @@ MonoString *godot_icall_Object_ToString(Object *p_ptr) {
void godot_register_object_icalls() {
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Ctor", godot_icall_Object_Ctor);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Disposed", godot_icall_Object_Disposed);
- GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Reference_Disposed", godot_icall_Reference_Disposed);
+ GDMonoUtils::add_internal_call("Godot.Object::godot_icall_RefCounted_Disposed", godot_icall_RefCounted_Disposed);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ConnectEventSignals", godot_icall_Object_ConnectEventSignals);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", godot_icall_Object_ClassDB_get_method);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ToString", godot_icall_Object_ToString);
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
index 3db52d7c30..eed3bd2167 100644
--- a/modules/mono/glue/glue_header.h
+++ b/modules/mono/glue/glue_header.h
@@ -61,7 +61,7 @@ void godot_register_glue_header_icalls() {
#include "core/config/engine.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/string/node_path.h"
#include "core/string/ustring.h"
#include "core/typedefs.h"
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index 020a40575c..375ad413c4 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -31,7 +31,7 @@
#include "godotsharp_dirs.h"
#include "core/config/project_settings.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/os.h"
#ifdef TOOLS_ENABLED
@@ -63,8 +63,8 @@ String _get_expected_build_config() {
String _get_mono_user_dir() {
#ifdef TOOLS_ENABLED
- if (EditorSettings::get_singleton()) {
- return EditorSettings::get_singleton()->get_data_dir().plus_file("mono");
+ if (EditorPaths::get_singleton()) {
+ return EditorPaths::get_singleton()->get_data_dir().plus_file("mono");
} else {
String settings_path;
diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h
index f435aab3dd..d0e51d159f 100644
--- a/modules/mono/mono_gc_handle.h
+++ b/modules/mono/mono_gc_handle.h
@@ -33,7 +33,7 @@
#include <mono/jit/jit.h>
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
namespace gdmono {
@@ -79,8 +79,8 @@ struct MonoGCHandleData {
static MonoGCHandleData new_weak_handle(MonoObject *p_object);
};
-class MonoGCHandleRef : public Reference {
- GDCLASS(MonoGCHandleRef, Reference);
+class MonoGCHandleRef : public RefCounted {
+ GDCLASS(MonoGCHandleRef, RefCounted);
MonoGCHandleData data;
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index c523d381f6..a3acfbd995 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -39,8 +39,8 @@
#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#include "core/os/thread.h"
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index a1556bace5..67d6f3ef29 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -34,8 +34,8 @@
#include <mono/metadata/tokentype.h>
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_pack.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/templates/list.h"
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index d66cc29b9a..341ca88728 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -109,8 +109,8 @@ void CachedData::clear_godot_api_cache() {
class_Vector3 = nullptr;
class_Vector3i = nullptr;
class_Basis = nullptr;
- class_Quat = nullptr;
- class_Transform = nullptr;
+ class_Quaternion = nullptr;
+ class_Transform3D = nullptr;
class_AABB = nullptr;
class_Color = nullptr;
class_Plane = nullptr;
@@ -238,8 +238,8 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3));
CACHE_CLASS_AND_CHECK(Vector3i, GODOT_API_CLASS(Vector3i));
CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis));
- CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat));
- CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform));
+ CACHE_CLASS_AND_CHECK(Quaternion, GODOT_API_CLASS(Quaternion));
+ CACHE_CLASS_AND_CHECK(Transform3D, GODOT_API_CLASS(Transform3D));
CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB));
CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index 51370da452..3d867060f5 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -80,8 +80,8 @@ struct CachedData {
GDMonoClass *class_Vector3;
GDMonoClass *class_Vector3i;
GDMonoClass *class_Basis;
- GDMonoClass *class_Quat;
- GDMonoClass *class_Transform;
+ GDMonoClass *class_Quaternion;
+ GDMonoClass *class_Transform3D;
GDMonoClass *class_AABB;
GDMonoClass *class_Color;
GDMonoClass *class_Plane;
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index 1d4d52dfce..111eaa0bbf 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -146,14 +146,14 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
break;
}
- if (tclass == CACHED_CLASS(Quat)) {
- GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_value.operator ::Quat());
+ if (tclass == CACHED_CLASS(Quaternion)) {
+ GDMonoMarshal::M_Quaternion from = MARSHALLED_OUT(Quaternion, p_value.operator ::Quaternion());
mono_field_set_value(p_object, mono_field, &from);
break;
}
- if (tclass == CACHED_CLASS(Transform)) {
- GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_value.operator ::Transform());
+ if (tclass == CACHED_CLASS(Transform3D)) {
+ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D());
mono_field_set_value(p_object, mono_field, &from);
break;
}
@@ -336,8 +336,8 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_value.operator ::Plane());
mono_field_set_value(p_object, mono_field, &from);
} break;
- case Variant::QUAT: {
- GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_value.operator ::Quat());
+ case Variant::QUATERNION: {
+ GDMonoMarshal::M_Quaternion from = MARSHALLED_OUT(Quaternion, p_value.operator ::Quaternion());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::AABB: {
@@ -348,8 +348,8 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
mono_field_set_value(p_object, mono_field, &from);
} break;
- case Variant::TRANSFORM: {
- GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_value.operator ::Transform());
+ case Variant::TRANSFORM3D: {
+ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::COLOR: {
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index fa93c6533a..d7df18d5da 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -51,7 +51,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// All mono objects created from the managed world (e.g.: 'new Player()')
// need to have a CSharpScript in order for their methods to be callable from the unmanaged side
- Reference *ref = Object::cast_to<Reference>(unmanaged);
+ RefCounted *rc = Object::cast_to<RefCounted>(unmanaged);
GDMonoClass *klass = GDMonoUtils::get_object_class(managed);
@@ -73,18 +73,18 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
script_binding.inited = true;
script_binding.type_name = NATIVE_GDMONOCLASS_NAME(klass);
script_binding.wrapper_class = klass;
- script_binding.gchandle = ref ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
+ script_binding.gchandle = rc ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
script_binding.owner = unmanaged;
- if (ref) {
+ if (rc) {
// Unsafe refcount increment. The managed instance also counts as a reference.
// This way if the unmanaged world has no references to our owner
// but the managed instance is alive, the refcount will be 1 instead of 0.
- // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
+ // See: godot_icall_RefCounted_Dtor(MonoObject *p_obj, Object *p_ptr)
// May not me referenced yet, so we must use init_ref() instead of reference()
- if (ref->init_ref()) {
- CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ if (rc->init_ref()) {
+ CSharpLanguage::get_singleton()->post_unsafe_reference(rc);
}
}
@@ -99,7 +99,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
return;
}
- MonoGCHandleData gchandle = ref ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
+ MonoGCHandleData gchandle = rc ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass, native);
diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp
index dafd36c36b..179bbfb40c 100644
--- a/modules/mono/mono_gd/gd_mono_log.cpp
+++ b/modules/mono/mono_gd/gd_mono_log.cpp
@@ -32,7 +32,7 @@
#include <stdlib.h> // abort
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/os.h"
#include "../godotsharp_dirs.h"
@@ -161,8 +161,8 @@ void GDMonoLog::initialize() {
OS::Time time_now = OS::get_singleton()->get_time();
String log_file_name = str_format("%04d-%02d-%02d_%02d.%02d.%02d",
- date_now.year, date_now.month, date_now.day,
- time_now.hour, time_now.min, time_now.sec);
+ (int)date_now.year, (int)date_now.month, (int)date_now.day,
+ (int)time_now.hour, (int)time_now.minute, (int)time_now.second);
log_file_name += str_format("_%d", OS::get_singleton()->get_process_id());
diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h
index f7a53156ab..9ddbd251ac 100644
--- a/modules/mono/mono_gd/gd_mono_log.h
+++ b/modules/mono/mono_gd/gd_mono_log.h
@@ -41,7 +41,7 @@
#endif
#ifdef GD_MONO_LOG_ENABLED
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#endif
class GDMonoLog {
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 359f6bba4d..9f2977bfa2 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -104,12 +104,12 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_
return Variant::BASIS;
}
- if (vtclass == CACHED_CLASS(Quat)) {
- return Variant::QUAT;
+ if (vtclass == CACHED_CLASS(Quaternion)) {
+ return Variant::QUATERNION;
}
- if (vtclass == CACHED_CLASS(Transform)) {
- return Variant::TRANSFORM;
+ if (vtclass == CACHED_CLASS(Transform3D)) {
+ return Variant::TRANSFORM3D;
}
if (vtclass == CACHED_CLASS(AABB)) {
@@ -508,9 +508,9 @@ MonoObject *variant_to_mono_object(const Variant &p_var) {
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var.operator ::Plane());
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from);
}
- case Variant::QUAT: {
- GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_var.operator ::Quat());
- return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Quat), &from);
+ case Variant::QUATERNION: {
+ GDMonoMarshal::M_Quaternion from = MARSHALLED_OUT(Quaternion, p_var.operator ::Quaternion());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Quaternion), &from);
}
case Variant::AABB: {
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_var.operator ::AABB());
@@ -520,9 +520,9 @@ MonoObject *variant_to_mono_object(const Variant &p_var) {
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_var.operator ::Basis());
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Basis), &from);
}
- case Variant::TRANSFORM: {
- GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_var.operator ::Transform());
- return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform), &from);
+ case Variant::TRANSFORM3D: {
+ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_var.operator ::Transform3D());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform3D), &from);
}
case Variant::COLOR: {
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var.operator ::Color());
@@ -619,8 +619,8 @@ size_t variant_get_managed_unboxed_size(const ManagedType &p_type) {
RETURN_CHECK_FOR_STRUCT(Vector3);
RETURN_CHECK_FOR_STRUCT(Vector3i);
RETURN_CHECK_FOR_STRUCT(Basis);
- RETURN_CHECK_FOR_STRUCT(Quat);
- RETURN_CHECK_FOR_STRUCT(Transform);
+ RETURN_CHECK_FOR_STRUCT(Quaternion);
+ RETURN_CHECK_FOR_STRUCT(Transform3D);
RETURN_CHECK_FOR_STRUCT(AABB);
RETURN_CHECK_FOR_STRUCT(Color);
RETURN_CHECK_FOR_STRUCT(Plane);
@@ -724,8 +724,8 @@ void *variant_to_managed_unboxed(const Variant &p_var, const ManagedType &p_type
RETURN_CHECK_FOR_STRUCT(Vector3);
RETURN_CHECK_FOR_STRUCT(Vector3i);
RETURN_CHECK_FOR_STRUCT(Basis);
- RETURN_CHECK_FOR_STRUCT(Quat);
- RETURN_CHECK_FOR_STRUCT(Transform);
+ RETURN_CHECK_FOR_STRUCT(Quaternion);
+ RETURN_CHECK_FOR_STRUCT(Transform3D);
RETURN_CHECK_FOR_STRUCT(AABB);
RETURN_CHECK_FOR_STRUCT(Color);
RETURN_CHECK_FOR_STRUCT(Plane);
@@ -880,8 +880,8 @@ MonoObject *variant_to_mono_object(const Variant &p_var, const ManagedType &p_ty
RETURN_CHECK_FOR_STRUCT(Vector3);
RETURN_CHECK_FOR_STRUCT(Vector3i);
RETURN_CHECK_FOR_STRUCT(Basis);
- RETURN_CHECK_FOR_STRUCT(Quat);
- RETURN_CHECK_FOR_STRUCT(Transform);
+ RETURN_CHECK_FOR_STRUCT(Quaternion);
+ RETURN_CHECK_FOR_STRUCT(Transform3D);
RETURN_CHECK_FOR_STRUCT(AABB);
RETURN_CHECK_FOR_STRUCT(Color);
RETURN_CHECK_FOR_STRUCT(Plane);
@@ -1036,12 +1036,12 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
return MARSHALLED_IN(Basis, unbox_addr<GDMonoMarshal::M_Basis>(p_obj));
}
- if (vtclass == CACHED_CLASS(Quat)) {
- return MARSHALLED_IN(Quat, unbox_addr<GDMonoMarshal::M_Quat>(p_obj));
+ if (vtclass == CACHED_CLASS(Quaternion)) {
+ return MARSHALLED_IN(Quaternion, unbox_addr<GDMonoMarshal::M_Quaternion>(p_obj));
}
- if (vtclass == CACHED_CLASS(Transform)) {
- return MARSHALLED_IN(Transform, unbox_addr<GDMonoMarshal::M_Transform>(p_obj));
+ if (vtclass == CACHED_CLASS(Transform3D)) {
+ return MARSHALLED_IN(Transform3D, unbox_addr<GDMonoMarshal::M_Transform3D>(p_obj));
}
if (vtclass == CACHED_CLASS(AABB)) {
@@ -1136,8 +1136,8 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
Object *ptr = unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_obj));
if (ptr != nullptr) {
- Reference *ref = Object::cast_to<Reference>(ptr);
- return ref ? Variant(Ref<Reference>(ref)) : Variant(ptr);
+ RefCounted *rc = Object::cast_to<RefCounted>(ptr);
+ return rc ? Variant(Ref<RefCounted>(rc)) : Variant(ptr);
}
return Variant();
}
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 668809ae5d..88afc7ebc5 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -263,15 +263,15 @@ enum {
MATCHES_Basis = (MATCHES_Vector3 && (sizeof(Basis) == (sizeof(Vector3) * 3))), // No field offset required, it stores an array
- MATCHES_Quat = (MATCHES_real_t && (sizeof(Quat) == (sizeof(real_t) * 4)) &&
- offsetof(Quat, x) == (sizeof(real_t) * 0) &&
- offsetof(Quat, y) == (sizeof(real_t) * 1) &&
- offsetof(Quat, z) == (sizeof(real_t) * 2) &&
- offsetof(Quat, w) == (sizeof(real_t) * 3)),
+ MATCHES_Quaternion = (MATCHES_real_t && (sizeof(Quaternion) == (sizeof(real_t) * 4)) &&
+ offsetof(Quaternion, x) == (sizeof(real_t) * 0) &&
+ offsetof(Quaternion, y) == (sizeof(real_t) * 1) &&
+ offsetof(Quaternion, z) == (sizeof(real_t) * 2) &&
+ offsetof(Quaternion, w) == (sizeof(real_t) * 3)),
- MATCHES_Transform = (MATCHES_Basis && MATCHES_Vector3 && (sizeof(Transform) == (sizeof(Basis) + sizeof(Vector3))) &&
- offsetof(Transform, basis) == 0 &&
- offsetof(Transform, origin) == sizeof(Basis)),
+ MATCHES_Transform3D = (MATCHES_Basis && MATCHES_Vector3 && (sizeof(Transform3D) == (sizeof(Basis) + sizeof(Vector3))) &&
+ offsetof(Transform3D, basis) == 0 &&
+ offsetof(Transform3D, origin) == sizeof(Basis)),
MATCHES_AABB = (MATCHES_Vector3 && (sizeof(AABB) == (sizeof(Vector3) * 2)) &&
offsetof(AABB, position) == (sizeof(Vector3) * 0) &&
@@ -292,7 +292,7 @@ enum {
#ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY
/* clang-format off */
static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 &&
- MATCHES_Basis && MATCHES_Quat && MATCHES_Transform && MATCHES_AABB && MATCHES_Color &&
+ MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_AABB && MATCHES_Color &&
MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i);
/* clang-format on */
#endif
@@ -420,29 +420,29 @@ struct M_Basis {
}
};
-struct M_Quat {
+struct M_Quaternion {
real_t x, y, z, w;
- static _FORCE_INLINE_ Quat convert_to(const M_Quat &p_from) {
- return Quat(p_from.x, p_from.y, p_from.z, p_from.w);
+ static _FORCE_INLINE_ Quaternion convert_to(const M_Quaternion &p_from) {
+ return Quaternion(p_from.x, p_from.y, p_from.z, p_from.w);
}
- static _FORCE_INLINE_ M_Quat convert_from(const Quat &p_from) {
- M_Quat ret = { p_from.x, p_from.y, p_from.z, p_from.w };
+ static _FORCE_INLINE_ M_Quaternion convert_from(const Quaternion &p_from) {
+ M_Quaternion ret = { p_from.x, p_from.y, p_from.z, p_from.w };
return ret;
}
};
-struct M_Transform {
+struct M_Transform3D {
M_Basis basis;
M_Vector3 origin;
- static _FORCE_INLINE_ Transform convert_to(const M_Transform &p_from) {
- return Transform(M_Basis::convert_to(p_from.basis), M_Vector3::convert_to(p_from.origin));
+ static _FORCE_INLINE_ Transform3D convert_to(const M_Transform3D &p_from) {
+ return Transform3D(M_Basis::convert_to(p_from.basis), M_Vector3::convert_to(p_from.origin));
}
- static _FORCE_INLINE_ M_Transform convert_from(const Transform &p_from) {
- M_Transform ret = { M_Basis::convert_from(p_from.basis), M_Vector3::convert_from(p_from.origin) };
+ static _FORCE_INLINE_ M_Transform3D convert_from(const Transform3D &p_from) {
+ M_Transform3D ret = { M_Basis::convert_from(p_from.basis), M_Vector3::convert_from(p_from.origin) };
return ret;
}
};
@@ -533,8 +533,8 @@ DECL_TYPE_MARSHAL_TEMPLATES(Transform2D)
DECL_TYPE_MARSHAL_TEMPLATES(Vector3)
DECL_TYPE_MARSHAL_TEMPLATES(Vector3i)
DECL_TYPE_MARSHAL_TEMPLATES(Basis)
-DECL_TYPE_MARSHAL_TEMPLATES(Quat)
-DECL_TYPE_MARSHAL_TEMPLATES(Transform)
+DECL_TYPE_MARSHAL_TEMPLATES(Quaternion)
+DECL_TYPE_MARSHAL_TEMPLATES(Transform3D)
DECL_TYPE_MARSHAL_TEMPLATES(AABB)
DECL_TYPE_MARSHAL_TEMPLATES(Color)
DECL_TYPE_MARSHAL_TEMPLATES(Plane)
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 6e0a263c7f..df45cb8e92 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -35,8 +35,8 @@
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
-#include "core/object/reference.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
+#include "core/object/ref_counted.h"
#include "core/os/mutex.h"
#include "core/os/os.h"
@@ -108,15 +108,15 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
gchandle = MonoGCHandleData::new_strong_handle(mono_object);
// Tie managed to unmanaged
- Reference *ref = Object::cast_to<Reference>(unmanaged);
+ RefCounted *rc = Object::cast_to<RefCounted>(unmanaged);
- if (ref) {
+ if (rc) {
// Unsafe refcount increment. The managed instance also counts as a reference.
// This way if the unmanaged world has no references to our owner
// but the managed instance is alive, the refcount will be 1 instead of 0.
- // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
- ref->reference();
- CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ // See: godot_icall_RefCounted_Dtor(MonoObject *p_obj, Object *p_ptr)
+ rc->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(rc);
}
return mono_object;
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 9e024418e1..773501e93d 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -41,7 +41,7 @@
#endif
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#define UNHANDLED_EXCEPTION(m_exc) \
if (unlikely(m_exc != nullptr)) { \
diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h
index 4c77f8cfed..e12ea45b3f 100644
--- a/modules/mono/signal_awaiter_utils.h
+++ b/modules/mono/signal_awaiter_utils.h
@@ -31,7 +31,7 @@
#ifndef SIGNAL_AWAITER_UTILS_H
#define SIGNAL_AWAITER_UTILS_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "csharp_script.h"
#include "mono_gc_handle.h"
diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp
index bb1265e959..6b616dd52d 100644
--- a/modules/mono/utils/mono_reg_utils.cpp
+++ b/modules/mono/utils/mono_reg_utils.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "mono_reg_utils.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#ifdef WINDOWS_ENABLED
diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp
index 93d44628ac..ec04d50704 100644
--- a/modules/mono/utils/path_utils.cpp
+++ b/modules/mono/utils/path_utils.cpp
@@ -31,8 +31,8 @@
#include "path_utils.h"
#include "core/config/project_settings.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#ifdef WINDOWS_ENABLED
@@ -80,7 +80,7 @@ String cwd() {
}
String abspath(const String &p_path) {
- if (p_path.is_abs_path()) {
+ if (p_path.is_absolute_path()) {
return p_path.simplify_path();
} else {
return path::join(path::cwd(), p_path).simplify_path();
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index 43de77005e..053618ebe4 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -30,7 +30,7 @@
#include "string_utils.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include <stdio.h>
#include <stdlib.h>
@@ -170,10 +170,10 @@ Error read_all_file_utf8(const String &p_path, String &r_content) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
- int len = f->get_len();
+ uint64_t len = f->get_length();
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
- int r = f->get_buffer(w, len);
+ uint64_t r = f->get_buffer(w, len);
f->close();
memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml
index 38c5138482..a12412a9cd 100644
--- a/modules/opensimplex/doc_classes/NoiseTexture.xml
+++ b/modules/opensimplex/doc_classes/NoiseTexture.xml
@@ -31,6 +31,9 @@
<member name="noise" type="OpenSimplexNoise" setter="set_noise" getter="get_noise">
The [OpenSimplexNoise] instance used to generate the noise.
</member>
+ <member name="noise_offset" type="Vector2" setter="set_noise_offset" getter="get_noise_offset" default="Vector2( 0, 0 )">
+ An offset used to specify the noise space coordinate of the top left corner of the generated noise. This value is ignored if [member seamless] is enabled.
+ </member>
<member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false">
Whether the texture can be tiled without visible seams or not. Seamless textures take longer to generate.
[b]Note:[/b] Seamless noise has a lower contrast compared to non-seamless noise. This is due to the way noise uses higher dimensions for generating seamless noise.
diff --git a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
index ad82f87213..2fdbd61ee7 100644
--- a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
+++ b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
@@ -31,8 +31,10 @@
</argument>
<argument index="1" name="height" type="int">
</argument>
+ <argument index="2" name="noise_offset" type="Vector2" default="Vector2( 0, 0 )">
+ </argument>
<description>
- Generate a noise image in [constant Image.FORMAT_L8] format with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters.
+ Generate a noise image in [constant Image.FORMAT_L8] format with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters. If [code]noise_offset[/code] is specified, then the offset value is used as the coordinates of the top-left corner of the generated noise.
</description>
</method>
<method name="get_noise_1d" qualifiers="const">
diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp
index 7272d32fac..9e0155da94 100644
--- a/modules/opensimplex/noise_texture.cpp
+++ b/modules/opensimplex/noise_texture.cpp
@@ -52,6 +52,9 @@ void NoiseTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise);
ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise);
+ ClassDB::bind_method(D_METHOD("set_noise_offset", "noise_offset"), &NoiseTexture::set_noise_offset);
+ ClassDB::bind_method(D_METHOD("get_noise_offset"), &NoiseTexture::get_noise_offset);
+
ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless);
ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless);
@@ -71,6 +74,7 @@ void NoiseTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normal_map"), "set_as_normal_map", "is_normal_map");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "noise_offset"), "set_noise_offset", "get_noise_offset");
}
void NoiseTexture::_validate_property(PropertyInfo &property) const {
@@ -130,7 +134,7 @@ Ref<Image> NoiseTexture::_generate_texture() {
if (seamless) {
image = ref_noise->get_seamless_image(size.x);
} else {
- image = ref_noise->get_image(size.x, size.y);
+ image = ref_noise->get_image(size.x, size.y, noise_offset);
}
if (as_normal_map) {
@@ -198,6 +202,14 @@ void NoiseTexture::set_height(int p_height) {
_queue_update();
}
+void NoiseTexture::set_noise_offset(Vector2 p_noise_offset) {
+ if (noise_offset == p_noise_offset) {
+ return;
+ }
+ noise_offset = p_noise_offset;
+ _queue_update();
+}
+
void NoiseTexture::set_seamless(bool p_seamless) {
if (p_seamless == seamless) {
return;
@@ -245,6 +257,10 @@ int NoiseTexture::get_height() const {
return size.y;
}
+Vector2 NoiseTexture::get_noise_offset() const {
+ return noise_offset;
+}
+
RID NoiseTexture::get_rid() const {
if (!texture.is_valid()) {
texture = RS::get_singleton()->texture_2d_placeholder_create();
diff --git a/modules/opensimplex/noise_texture.h b/modules/opensimplex/noise_texture.h
index 6983ae18fe..6237b6460d 100644
--- a/modules/opensimplex/noise_texture.h
+++ b/modules/opensimplex/noise_texture.h
@@ -34,7 +34,7 @@
#include "open_simplex_noise.h"
#include "core/io/image.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "editor/property_editor.h"
@@ -56,6 +56,7 @@ private:
Ref<OpenSimplexNoise> noise;
Vector2i size = Vector2i(512, 512);
+ Vector2 noise_offset;
bool seamless = false;
bool as_normal_map = false;
float bump_strength = 8.0;
@@ -79,6 +80,9 @@ public:
void set_width(int p_width);
void set_height(int p_height);
+ void set_noise_offset(Vector2 p_noise_offset);
+ Vector2 get_noise_offset() const;
+
void set_seamless(bool p_seamless);
bool get_seamless();
diff --git a/modules/opensimplex/open_simplex_noise.cpp b/modules/opensimplex/open_simplex_noise.cpp
index 3773946112..f0a8867284 100644
--- a/modules/opensimplex/open_simplex_noise.cpp
+++ b/modules/opensimplex/open_simplex_noise.cpp
@@ -96,7 +96,7 @@ void OpenSimplexNoise::set_lacunarity(float p_lacunarity) {
emit_changed();
}
-Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) const {
+Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height, const Vector2 &p_noise_offset) const {
Vector<uint8_t> data;
data.resize(p_width * p_height);
@@ -104,7 +104,7 @@ Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) const {
for (int i = 0; i < p_height; i++) {
for (int j = 0; j < p_width; j++) {
- float v = get_noise_2d(j, i);
+ float v = get_noise_2d(float(j) + p_noise_offset.x, float(i) + p_noise_offset.y);
v = v * 0.5 + 0.5; // Normalize [0..1]
wd8[(i * p_width + j)] = uint8_t(CLAMP(v * 255.0, 0, 255));
}
@@ -161,7 +161,7 @@ void OpenSimplexNoise::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lacunarity", "lacunarity"), &OpenSimplexNoise::set_lacunarity);
ClassDB::bind_method(D_METHOD("get_lacunarity"), &OpenSimplexNoise::get_lacunarity);
- ClassDB::bind_method(D_METHOD("get_image", "width", "height"), &OpenSimplexNoise::get_image);
+ ClassDB::bind_method(D_METHOD("get_image", "width", "height", "noise_offset"), &OpenSimplexNoise::get_image, DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("get_seamless_image", "size"), &OpenSimplexNoise::get_seamless_image);
ClassDB::bind_method(D_METHOD("get_noise_1d", "x"), &OpenSimplexNoise::get_noise_1d);
diff --git a/modules/opensimplex/open_simplex_noise.h b/modules/opensimplex/open_simplex_noise.h
index 847c157409..dcf922a8bf 100644
--- a/modules/opensimplex/open_simplex_noise.h
+++ b/modules/opensimplex/open_simplex_noise.h
@@ -32,7 +32,7 @@
#define OPEN_SIMPLEX_NOISE_H
#include "core/io/image.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "scene/resources/texture.h"
#include "thirdparty/misc/open-simplex-noise.h"
@@ -75,7 +75,7 @@ public:
void set_lacunarity(float p_lacunarity);
float get_lacunarity() const { return lacunarity; }
- Ref<Image> get_image(int p_width, int p_height) const;
+ Ref<Image> get_image(int p_width, int p_height, const Vector2 &p_noise_offset = Vector2()) const;
Ref<Image> get_seamless_image(int p_size) const;
float get_noise_1d(float x) const;
diff --git a/modules/pvr/image_compress_pvrtc.cpp b/modules/pvr/image_compress_pvrtc.cpp
index 6cb9837f49..4d0430fa92 100644
--- a/modules/pvr/image_compress_pvrtc.cpp
+++ b/modules/pvr/image_compress_pvrtc.cpp
@@ -31,7 +31,7 @@
#include "image_compress_pvrtc.h"
#include "core/io/image.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include <PvrTcEncoder.h>
#include <RgbaBitmap.h>
diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp
index 83f032ca2b..cb12976090 100644
--- a/modules/pvr/texture_loader_pvr.cpp
+++ b/modules/pvr/texture_loader_pvr.cpp
@@ -30,7 +30,7 @@
#include "texture_loader_pvr.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
static void _pvrtc_decompress(Image *p_img);
diff --git a/modules/raycast/SCsub b/modules/raycast/SCsub
index 57120bff26..6e7b3e7b8d 100644
--- a/modules/raycast/SCsub
+++ b/modules/raycast/SCsub
@@ -10,7 +10,7 @@ env_raycast = env_modules.Clone()
thirdparty_obj = []
if env["builtin_embree"]:
- thirdparty_dir = "#thirdparty/embree-aarch64/"
+ thirdparty_dir = "#thirdparty/embree/"
embree_src = [
"common/sys/sysinfo.cpp",
@@ -28,16 +28,6 @@ if env["builtin_embree"]:
"common/lexers/stringstream.cpp",
"common/lexers/tokenstream.cpp",
"common/tasking/taskschedulerinternal.cpp",
- "common/algorithms/parallel_for.cpp",
- "common/algorithms/parallel_reduce.cpp",
- "common/algorithms/parallel_prefix_sum.cpp",
- "common/algorithms/parallel_for_for.cpp",
- "common/algorithms/parallel_for_for_prefix_sum.cpp",
- "common/algorithms/parallel_partition.cpp",
- "common/algorithms/parallel_sort.cpp",
- "common/algorithms/parallel_set.cpp",
- "common/algorithms/parallel_map.cpp",
- "common/algorithms/parallel_filter.cpp",
"kernels/common/device.cpp",
"kernels/common/stat.cpp",
"kernels/common/acceln.cpp",
@@ -82,13 +72,17 @@ if env["builtin_embree"]:
if env["platform"] == "windows":
if env.msvc:
env.Append(LINKFLAGS=["psapi.lib"])
- env_raycast.Append(CPPDEFINES=["__SSE2__", "__SSE__"])
else:
env.Append(LIBS=["psapi"])
env_thirdparty = env_raycast.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
+
+ if not env["arch"] in ["x86", "x86_64"] or env.msvc:
+ # Embree needs those, it will automatically use SSE2NEON in ARM
+ env_thirdparty.Append(CPPDEFINES=["__SSE2__", "__SSE__"])
+
env.modules_sources += thirdparty_obj
diff --git a/modules/raycast/config.py b/modules/raycast/config.py
index 3da9ace9d8..5de36c5322 100644
--- a/modules/raycast/config.py
+++ b/modules/raycast/config.py
@@ -1,6 +1,5 @@
def can_build(env, platform):
- # Depends on Embree library, which supports only x86_64 (originally)
- # and aarch64 (thanks to the embree-aarch64 fork).
+ # Depends on Embree library, which only supports x86_64 and aarch64.
if platform == "android":
return env["android_arch"] in ["arm64v8", "x86_64"]
diff --git a/modules/raycast/godot_update_embree.py b/modules/raycast/godot_update_embree.py
index db4fa95c21..31a25a318f 100644
--- a/modules/raycast/godot_update_embree.py
+++ b/modules/raycast/godot_update_embree.py
@@ -11,6 +11,7 @@ include_dirs = [
"common/algorithms",
"common/lexers",
"common/simd",
+ "common/simd/arm",
"include/embree3",
"kernels/subdiv",
"kernels/geometry",
@@ -32,16 +33,6 @@ cpp_files = [
"common/lexers/stringstream.cpp",
"common/lexers/tokenstream.cpp",
"common/tasking/taskschedulerinternal.cpp",
- "common/algorithms/parallel_for.cpp",
- "common/algorithms/parallel_reduce.cpp",
- "common/algorithms/parallel_prefix_sum.cpp",
- "common/algorithms/parallel_for_for.cpp",
- "common/algorithms/parallel_for_for_prefix_sum.cpp",
- "common/algorithms/parallel_partition.cpp",
- "common/algorithms/parallel_sort.cpp",
- "common/algorithms/parallel_set.cpp",
- "common/algorithms/parallel_map.cpp",
- "common/algorithms/parallel_filter.cpp",
"kernels/common/device.cpp",
"kernels/common/stat.cpp",
"kernels/common/acceln.cpp",
@@ -74,11 +65,11 @@ cpp_files = [
os.chdir("../../thirdparty")
-dir_name = "embree-aarch64"
+dir_name = "embree"
if os.path.exists(dir_name):
shutil.rmtree(dir_name)
-subprocess.run(["git", "clone", "https://github.com/lighttransport/embree-aarch64.git", "embree-tmp"])
+subprocess.run(["git", "clone", "https://github.com/embree/embree.git", "embree-tmp"])
os.chdir("embree-tmp")
commit_hash = str(subprocess.check_output(["git", "rev-parse", "HEAD"], universal_newlines=True)).strip()
@@ -197,7 +188,7 @@ with open("CMakeLists.txt", "r") as cmake_file:
with open(os.path.join(dest_dir, "include/embree3/rtcore_config.h"), "w") as config_file:
config_file.write(
f"""
-// Copyright 2009-2020 Intel Corporation
+// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp
index 66558efa8c..88c0145ebc 100644
--- a/modules/raycast/raycast_occlusion_cull.cpp
+++ b/modules/raycast/raycast_occlusion_cull.cpp
@@ -64,7 +64,7 @@ void RaycastOcclusionCull::RaycastHZBuffer::resize(const Size2i &p_size) {
camera_ray_masks.resize(ray_packets_count * TILE_SIZE * TILE_SIZE);
}
-void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool) {
+void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool) {
CameraRayThreadData td;
td.camera_matrix = p_cam_projection;
td.camera_transform = p_cam_transform;
@@ -82,7 +82,7 @@ void RaycastOcclusionCull::RaycastHZBuffer::_camera_rays_threaded(uint32_t p_thr
_generate_camera_rays(p_data->camera_transform, p_data->camera_matrix, p_data->camera_orthogonal, from, to);
}
-void RaycastOcclusionCull::RaycastHZBuffer::_generate_camera_rays(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, int p_from, int p_to) {
+void RaycastOcclusionCull::RaycastHZBuffer::_generate_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, int p_from, int p_to) {
Size2i buffer_size = sizes[0];
CameraMatrix inv_camera_matrix = p_cam_projection.inverse();
@@ -227,7 +227,7 @@ void RaycastOcclusionCull::remove_scenario(RID p_scenario) {
scenario.removed = true;
}
-void RaycastOcclusionCull::scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform &p_xform, bool p_enabled) {
+void RaycastOcclusionCull::scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform3D &p_xform, bool p_enabled) {
ERR_FAIL_COND(!scenarios.has(p_scenario));
Scenario &scenario = scenarios[p_scenario];
@@ -345,7 +345,7 @@ void RaycastOcclusionCull::Scenario::_transform_vertices_thread(uint32_t p_threa
_transform_vertices_range(p_data->read, p_data->write, p_data->xform, from, to);
}
-void RaycastOcclusionCull::Scenario::_transform_vertices_range(const Vector3 *p_read, Vector3 *p_write, const Transform &p_xform, int p_from, int p_to) {
+void RaycastOcclusionCull::Scenario::_transform_vertices_range(const Vector3 *p_read, Vector3 *p_write, const Transform3D &p_xform, int p_from, int p_to) {
for (int i = p_from; i < p_to; i++) {
p_write[i] = p_xform.xform(p_read[i]);
}
@@ -491,7 +491,7 @@ void RaycastOcclusionCull::buffer_set_size(RID p_buffer, const Vector2i &p_size)
buffers[p_buffer].resize(p_size);
}
-void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {
+void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {
if (!buffers.has(p_buffer)) {
return;
}
diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h
index acaceb9459..85710a790c 100644
--- a/modules/raycast/raycast_occlusion_cull.h
+++ b/modules/raycast/raycast_occlusion_cull.h
@@ -34,7 +34,7 @@
#include "core/io/image.h"
#include "core/math/camera_matrix.h"
#include "core/object/object.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "scene/resources/mesh.h"
@@ -52,14 +52,14 @@ public:
struct CameraRayThreadData {
CameraMatrix camera_matrix;
- Transform camera_transform;
+ Transform3D camera_transform;
bool camera_orthogonal;
int thread_count;
Size2i buffer_size;
};
void _camera_rays_threaded(uint32_t p_thread, CameraRayThreadData *p_data);
- void _generate_camera_rays(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, int p_from, int p_to);
+ void _generate_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, int p_from, int p_to);
public:
LocalVector<RayPacket> camera_rays;
@@ -69,7 +69,7 @@ public:
virtual void clear() override;
virtual void resize(const Size2i &p_size) override;
void sort_rays();
- void update_camera_rays(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool);
+ void update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool);
};
private:
@@ -99,7 +99,7 @@ private:
RID occluder;
LocalVector<uint32_t> indices;
LocalVector<Vector3> xformed_vertices;
- Transform xform;
+ Transform3D xform;
bool enabled = true;
bool removed = false;
};
@@ -113,7 +113,7 @@ private:
struct TransformThreadData {
uint32_t thread_count;
uint32_t vertex_count;
- Transform xform;
+ Transform3D xform;
const Vector3 *read;
Vector3 *write;
};
@@ -134,7 +134,7 @@ private:
void _update_dirty_instance_thread(int p_idx, RID *p_instances);
void _update_dirty_instance(int p_idx, RID *p_instances, ThreadWorkPool *p_thread_pool);
void _transform_vertices_thread(uint32_t p_thread, TransformThreadData *p_data);
- void _transform_vertices_range(const Vector3 *p_read, Vector3 *p_write, const Transform &p_xform, int p_from, int p_to);
+ void _transform_vertices_range(const Vector3 *p_read, Vector3 *p_write, const Transform3D &p_xform, int p_from, int p_to);
static void _commit_scene(void *p_ud);
bool update(ThreadWorkPool &p_thread_pool);
@@ -164,7 +164,7 @@ public:
virtual void add_scenario(RID p_scenario) override;
virtual void remove_scenario(RID p_scenario) override;
- virtual void scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform &p_xform, bool p_enabled) override;
+ virtual void scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform3D &p_xform, bool p_enabled) override;
virtual void scenario_remove_instance(RID p_scenario, RID p_instance) override;
virtual void add_buffer(RID p_buffer) override;
@@ -172,7 +172,7 @@ public:
virtual HZBuffer *buffer_get_ptr(RID p_buffer) override;
virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) override;
virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) override;
- virtual void buffer_update(RID p_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) override;
+ virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) override;
virtual RID buffer_get_debug_texture(RID p_buffer) override;
virtual void set_build_quality(RS::ViewportOcclusionCullingBuildQuality p_quality) override;
diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml
index b21f5d1e7a..7f5a0dfecb 100644
--- a/modules/regex/doc_classes/RegEx.xml
+++ b/modules/regex/doc_classes/RegEx.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegEx" inherits="Reference" version="4.0">
+<class name="RegEx" inherits="RefCounted" version="4.0">
<brief_description>
Class for searching text for patterns using regular expressions.
</brief_description>
diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml
index a45de60aef..cfe00f83ee 100644
--- a/modules/regex/doc_classes/RegExMatch.xml
+++ b/modules/regex/doc_classes/RegExMatch.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegExMatch" inherits="Reference" version="4.0">
+<class name="RegExMatch" inherits="RefCounted" version="4.0">
<brief_description>
Contains the results of a [RegEx] search.
</brief_description>
diff --git a/modules/regex/regex.h b/modules/regex/regex.h
index f5773042fb..68fe2bc6e0 100644
--- a/modules/regex/regex.h
+++ b/modules/regex/regex.h
@@ -31,15 +31,15 @@
#ifndef REGEX_H
#define REGEX_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/string/ustring.h"
#include "core/templates/map.h"
#include "core/templates/vector.h"
#include "core/variant/array.h"
#include "core/variant/dictionary.h"
-class RegExMatch : public Reference {
- GDCLASS(RegExMatch, Reference);
+class RegExMatch : public RefCounted {
+ GDCLASS(RegExMatch, RefCounted);
struct Range {
int start = 0;
@@ -68,8 +68,8 @@ public:
int get_end(const Variant &p_name) const;
};
-class RegEx : public Reference {
- GDCLASS(RegEx, Reference);
+class RegEx : public RefCounted {
+ GDCLASS(RegEx, RefCounted);
void *general_ctx;
void *code = nullptr;
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
index e8e481de2d..78b4749939 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
@@ -30,7 +30,7 @@
#include "audio_stream_ogg_vorbis.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND(!active);
diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp
index ec1c30783a..a0de5e5f0f 100644
--- a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp
+++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp
@@ -30,8 +30,8 @@
#include "resource_importer_ogg_vorbis.h"
+#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "scene/resources/texture.h"
String ResourceImporterOGGVorbis::get_importer_name() const {
@@ -79,7 +79,7 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'.");
- size_t len = f->get_len();
+ uint64_t len = f->get_length();
Vector<uint8_t> data;
data.resize(len);
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index 6ce3e4b4b3..4911346b96 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -140,7 +140,7 @@ Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *p
}
Error ImageLoaderSVG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
- uint32_t size = f->get_len();
+ uint64_t size = f->get_length();
Vector<uint8_t> src_image;
src_image.resize(size + 1);
uint8_t *src_w = src_image.ptrw();
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index a55b6dc283..d06c5c2f14 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -131,7 +131,7 @@ if env["builtin_harfbuzz"]:
]
)
- if env["platform"] == "android" or env["platform"] == "linuxbsd" or env["platform"] == "server":
+ if env["platform"] == "android" or env["platform"] == "linuxbsd":
env_harfbuzz.Append(CCFLAGS=["-DHAVE_PTHREAD"])
if env["platform"] == "javascript":
diff --git a/modules/text_server_adv/dynamic_font_adv.cpp b/modules/text_server_adv/dynamic_font_adv.cpp
index 326af7f0ee..c29aac05bb 100644
--- a/modules/text_server_adv/dynamic_font_adv.cpp
+++ b/modules/text_server_adv/dynamic_font_adv.cpp
@@ -66,7 +66,7 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(
ERR_FAIL_V_MSG(nullptr, "Cannot open font file '" + font_path + "'.");
}
- size_t len = f->get_len();
+ uint64_t len = f->get_length();
font_mem_cache.resize(len);
f->get_buffer(font_mem_cache.ptrw(), len);
font_mem = font_mem_cache.ptr();
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 8b8b6b7cd3..906ebe4993 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -181,7 +181,7 @@ bool TextServerAdvanced::load_support_data(const String &p_filename) {
UErrorCode err = U_ZERO_ERROR;
// ICU data found.
- size_t len = f->get_len();
+ uint64_t len = f->get_length();
icu_data = (uint8_t *)memalloc(len);
f->get_buffer(icu_data, len);
f->close();
@@ -2352,24 +2352,22 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
sd->glyphs.push_back(gl);
} else {
Vector<RID> fonts;
- // Push fonts with the language and script support first.
- for (int l = 0; l < span.fonts.size(); l++) {
- if ((font_is_language_supported(span.fonts[l], span.language)) && (font_is_script_supported(span.fonts[l], script))) {
- fonts.push_back(sd->spans[k].fonts[l]);
- }
- }
- // Push fonts with the script support.
- for (int l = 0; l < sd->spans[k].fonts.size(); l++) {
- if (!(font_is_language_supported(span.fonts[l], span.language)) && (font_is_script_supported(span.fonts[l], script))) {
- fonts.push_back(sd->spans[k].fonts[l]);
- }
- }
- // Push the rest valid fonts.
- for (int l = 0; l < sd->spans[k].fonts.size(); l++) {
- if (!(font_is_language_supported(span.fonts[l], span.language)) && !(font_is_script_supported(span.fonts[l], script))) {
- fonts.push_back(sd->spans[k].fonts[l]);
+ Vector<RID> fonts_scr_only;
+ Vector<RID> fonts_no_match;
+ int font_count = span.fonts.size();
+ for (int l = 0; l < font_count; l++) {
+ if (font_is_script_supported(span.fonts[l], script)) {
+ if (font_is_language_supported(span.fonts[l], span.language)) {
+ fonts.push_back(sd->spans[k].fonts[l]);
+ } else {
+ fonts_scr_only.push_back(sd->spans[k].fonts[l]);
+ }
+ } else {
+ fonts_no_match.push_back(sd->spans[k].fonts[l]);
}
}
+ fonts.append_array(fonts_scr_only);
+ fonts.append_array(fonts_no_match);
_shape_run(sd, MAX(sd->spans[k].start, script_run_start), MIN(sd->spans[k].end, script_run_end), sd->script_iter->script_ranges[j].script, bidi_run_direction, fonts, k, 0);
}
}
diff --git a/modules/text_server_fb/dynamic_font_fb.cpp b/modules/text_server_fb/dynamic_font_fb.cpp
index dec1d6f83f..a261ba8f37 100644
--- a/modules/text_server_fb/dynamic_font_fb.cpp
+++ b/modules/text_server_fb/dynamic_font_fb.cpp
@@ -65,7 +65,7 @@ DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size(
ERR_FAIL_V_MSG(nullptr, "Cannot open font file '" + font_path + "'.");
}
- size_t len = f->get_len();
+ uint64_t len = f->get_length();
font_mem_cache.resize(len);
f->get_buffer(font_mem_cache.ptrw(), len);
font_mem = font_mem_cache.ptr();
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 98a67ef309..a22559efdd 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -634,17 +634,17 @@ bool TextServerFallback::shaped_text_add_string(RID p_shaped, const String &p_te
span.start = sd->text.length();
span.end = span.start + p_text.length();
// Pre-sort fonts, push fonts with the language support first.
- for (int i = 0; i < p_fonts.size(); i++) {
+ Vector<RID> fonts_no_match;
+ int font_count = p_fonts.size();
+ for (int i = 0; i < font_count; i++) {
if (font_is_language_supported(p_fonts[i], p_language)) {
span.fonts.push_back(p_fonts[i]);
+ } else {
+ fonts_no_match.push_back(p_fonts[i]);
}
}
- // Push the rest valid fonts.
- for (int i = 0; i < p_fonts.size(); i++) {
- if (!font_is_language_supported(p_fonts[i], p_language)) {
- span.fonts.push_back(p_fonts[i]);
- }
- }
+ span.fonts.append_array(fonts_no_match);
+
ERR_FAIL_COND_V(span.fonts.is_empty(), false);
span.font_size = p_size;
span.language = p_language;
diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp
index ef53661557..6eaa2d24a8 100644
--- a/modules/tga/image_loader_tga.cpp
+++ b/modules/tga/image_loader_tga.cpp
@@ -35,7 +35,7 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
-Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size) {
+Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size, size_t p_input_size) {
Error error;
Vector<uint8_t> pixels;
@@ -56,11 +56,14 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t
compressed_pos += 1;
count = (c & 0x7f) + 1;
- if (output_pos + count * p_pixel_size > output_pos) {
+ if (output_pos + count * p_pixel_size > p_output_size) {
return ERR_PARSE_ERROR;
}
if (c & 0x80) {
+ if (compressed_pos + p_pixel_size > p_input_size) {
+ return ERR_PARSE_ERROR;
+ }
for (size_t i = 0; i < p_pixel_size; i++) {
pixels_w[i] = p_compressed_buffer[compressed_pos];
compressed_pos += 1;
@@ -72,6 +75,9 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t
output_pos += p_pixel_size;
}
} else {
+ if (compressed_pos + count * p_pixel_size > p_input_size) {
+ return ERR_PARSE_ERROR;
+ }
count *= p_pixel_size;
for (size_t i = 0; i < count; i++) {
p_uncompressed_buffer[output_pos] = p_compressed_buffer[compressed_pos];
@@ -83,7 +89,7 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t
return OK;
}
-Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_output_size) {
+Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_input_size) {
#define TGA_PUT_PIXEL(r, g, b, a) \
int image_data_ofs = ((y * width) + x); \
image_data_w[image_data_ofs * 4 + 0] = r; \
@@ -134,7 +140,7 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
if (p_is_monochrome) {
while (y != y_end) {
while (x != x_end) {
- if (i > p_output_size) {
+ if (i >= p_input_size) {
return ERR_PARSE_ERROR;
}
uint8_t shade = p_buffer[i];
@@ -150,7 +156,7 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else {
while (y != y_end) {
while (x != x_end) {
- if (i > p_output_size) {
+ if (i >= p_input_size) {
return ERR_PARSE_ERROR;
}
uint8_t index = p_buffer[i];
@@ -181,7 +187,7 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else if (p_header.pixel_depth == 24) {
while (y != y_end) {
while (x != x_end) {
- if (i + 2 > p_output_size) {
+ if (i + 2 >= p_input_size) {
return ERR_PARSE_ERROR;
}
@@ -200,7 +206,7 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else if (p_header.pixel_depth == 32) {
while (y != y_end) {
while (x != x_end) {
- if (i + 3 > p_output_size) {
+ if (i + 3 >= p_input_size) {
return ERR_PARSE_ERROR;
}
@@ -226,9 +232,9 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
Vector<uint8_t> src_image;
- int src_image_len = f->get_len();
+ uint64_t src_image_len = f->get_length();
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
- ERR_FAIL_COND_V(src_image_len < (int)sizeof(tga_header_s), ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V(src_image_len < (int64_t)sizeof(tga_header_s), ERR_FILE_CORRUPT);
src_image.resize(src_image_len);
Error err = OK;
@@ -307,7 +313,7 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
const uint8_t *buffer = nullptr;
if (is_encoded) {
- err = decode_tga_rle(src_image_r, pixel_size, uncompressed_buffer_w, buffer_size);
+ err = decode_tga_rle(src_image_r, pixel_size, uncompressed_buffer_w, buffer_size, src_image_len);
if (err == OK) {
uncompressed_buffer_r = uncompressed_buffer.ptr();
diff --git a/modules/tga/image_loader_tga.h b/modules/tga/image_loader_tga.h
index cb2ce07edd..e4463a322f 100644
--- a/modules/tga/image_loader_tga.h
+++ b/modules/tga/image_loader_tga.h
@@ -72,8 +72,8 @@ class ImageLoaderTGA : public ImageFormatLoader {
uint8_t pixel_depth = 0;
uint8_t image_descriptor = 0;
};
- static Error decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size);
- static Error convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_output_size);
+ static Error decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size, size_t p_input_size);
+ static Error convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_input_size);
public:
virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 54f5b3f424..4400445f30 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -58,7 +58,7 @@ int VideoStreamPlaybackTheora::buffer_data() {
#else
- int bytes = file->get_buffer((uint8_t *)buffer, 4096);
+ uint64_t bytes = file->get_buffer((uint8_t *)buffer, 4096);
ogg_sync_wrote(&oy, bytes);
return (bytes);
@@ -176,7 +176,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
thread_eof = false;
//pre-fill buffer
int to_read = ring_buffer.space_left();
- int read = file->get_buffer(read_buffer.ptr(), to_read);
+ uint64_t read = file->get_buffer(read_buffer.ptr(), to_read);
ring_buffer.write(read_buffer.ptr(), read);
thread.start(_streaming_thread, this);
@@ -302,7 +302,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
}
}
- /* and now we have it all. initialize decoders */
+ /* And now we have it all. Initialize decoders. */
if (theora_p) {
td = th_decode_alloc(&ti, ts);
px_fmt = ti.pixel_fmt;
@@ -484,10 +484,10 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
//printf("frame time %f, play time %f, ready %i\n", (float)videobuf_time, get_time(), videobuf_ready);
- /* is it already too old to be useful? This is only actually
- useful cosmetically after a SIGSTOP. Note that we have to
+ /* is it already too old to be useful? This is only actually
+ useful cosmetically after a SIGSTOP. Note that we have to
decode the frame even if we don't show it (for now) due to
- keyframing. Soon enough libtheora will be able to deal
+ keyframing. Soon enough libtheora will be able to deal
with non-keyframe seeks. */
if (videobuf_time >= get_time()) {
@@ -632,8 +632,8 @@ void VideoStreamPlaybackTheora::_streaming_thread(void *ud) {
//just fill back the buffer
if (!vs->thread_eof) {
int to_read = vs->ring_buffer.space_left();
- if (to_read) {
- int read = vs->file->get_buffer(vs->read_buffer.ptr(), to_read);
+ if (to_read > 0) {
+ uint64_t read = vs->file->get_buffer(vs->read_buffer.ptr(), to_read);
vs->ring_buffer.write(vs->read_buffer.ptr(), read);
vs->thread_eof = vs->file->eof_reached();
}
diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index 2685a8a013..760173d0df 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -31,8 +31,8 @@
#ifndef VIDEO_STREAM_THEORA_H
#define VIDEO_STREAM_THEORA_H
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
-#include "core/os/file_access.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "core/templates/ring_buffer.h"
diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp
index 47214e6974..eb7a8597e6 100644
--- a/modules/tinyexr/image_loader_tinyexr.cpp
+++ b/modules/tinyexr/image_loader_tinyexr.cpp
@@ -37,7 +37,7 @@
Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
Vector<uint8_t> src_image;
- int src_image_len = f->get_len();
+ uint64_t src_image_len = f->get_length();
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
src_image.resize(src_image_len);
diff --git a/modules/upnp/doc_classes/UPNP.xml b/modules/upnp/doc_classes/UPNP.xml
index 785c8dad50..09a2c8a88c 100644
--- a/modules/upnp/doc_classes/UPNP.xml
+++ b/modules/upnp/doc_classes/UPNP.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="UPNP" inherits="Reference" version="4.0">
+<class name="UPNP" inherits="RefCounted" version="4.0">
<brief_description>
UPNP network functions.
</brief_description>
diff --git a/modules/upnp/doc_classes/UPNPDevice.xml b/modules/upnp/doc_classes/UPNPDevice.xml
index f3b96bb89d..f7b5386d86 100644
--- a/modules/upnp/doc_classes/UPNPDevice.xml
+++ b/modules/upnp/doc_classes/UPNPDevice.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="UPNPDevice" inherits="Reference" version="4.0">
+<class name="UPNPDevice" inherits="RefCounted" version="4.0">
<brief_description>
UPNP device.
</brief_description>
diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h
index a0cca96bc8..b961a9667f 100644
--- a/modules/upnp/upnp.h
+++ b/modules/upnp/upnp.h
@@ -31,14 +31,14 @@
#ifndef GODOT_UPNP_H
#define GODOT_UPNP_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "upnp_device.h"
#include <miniupnpc/miniupnpc.h>
-class UPNP : public Reference {
- GDCLASS(UPNP, Reference);
+class UPNP : public RefCounted {
+ GDCLASS(UPNP, RefCounted);
private:
String discover_multicast_if = "";
diff --git a/modules/upnp/upnp_device.h b/modules/upnp/upnp_device.h
index 126e761a56..0a66c36ab9 100644
--- a/modules/upnp/upnp_device.h
+++ b/modules/upnp/upnp_device.h
@@ -31,10 +31,10 @@
#ifndef GODOT_UPNP_DEVICE_H
#define GODOT_UPNP_DEVICE_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
-class UPNPDevice : public Reference {
- GDCLASS(UPNPDevice, Reference);
+class UPNPDevice : public RefCounted {
+ GDCLASS(UPNPDevice, RefCounted);
public:
enum IGDStatus {
diff --git a/modules/vhacd/config.py b/modules/vhacd/config.py
index d22f9454ed..a42f27fbe1 100644
--- a/modules/vhacd/config.py
+++ b/modules/vhacd/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return True
+ return not env["disable_3d"]
def configure(env):
diff --git a/modules/visual_script/doc_classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml
index 5112ea43a7..0798375a96 100644
--- a/modules/visual_script/doc_classes/VisualScript.xml
+++ b/modules/visual_script/doc_classes/VisualScript.xml
@@ -4,7 +4,7 @@
A script implemented in the Visual Script programming environment.
</brief_description>
<description>
- A script implemented in the Visual Script programming environment. The script extends the functionality of all objects that instance it.
+ A script implemented in the Visual Script programming environment. The script extends the functionality of all objects that instance it.
[method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes.
You are most likely to use this class via the Visual Script editor or when writing plugins for it.
</description>
diff --git a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
index de5d731cc0..d6b96957f5 100644
--- a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
@@ -15,10 +15,10 @@
<methods>
</methods>
<members>
- <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="@&quot;Object&quot;">
+ <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
The constant's parent class.
</member>
- <member name="constant" type="StringName" setter="set_class_constant" getter="get_class_constant" default="@&quot;&quot;">
+ <member name="constant" type="StringName" setter="set_class_constant" getter="get_class_constant" default="&amp;&quot;&quot;">
The constant to return. See the given class for its available constants.
</member>
</members>
diff --git a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
index 5c9c8d3eca..df3121d093 100644
--- a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
@@ -15,7 +15,7 @@
<methods>
</methods>
<members>
- <member name="signal" type="StringName" setter="set_signal" getter="get_signal" default="@&quot;&quot;">
+ <member name="signal" type="StringName" setter="set_signal" getter="get_signal" default="&amp;&quot;&quot;">
The signal to emit.
</member>
</members>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
index 2d0fac1fa0..48104afcf7 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
@@ -11,13 +11,13 @@
<members>
<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
</member>
- <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="@&quot;Object&quot;">
+ <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
</member>
<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
</member>
<member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptFunctionCall.CallMode" default="0">
</member>
- <member name="function" type="StringName" setter="set_function" getter="get_function" default="@&quot;&quot;">
+ <member name="function" type="StringName" setter="set_function" getter="get_function" default="&amp;&quot;&quot;">
</member>
<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
</member>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
index 68083614a6..9ed71bf10e 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunctionState" inherits="Reference" version="4.0">
+<class name="VisualScriptFunctionState" inherits="RefCounted" version="4.0">
<brief_description>
</brief_description>
<description>
@@ -28,7 +28,7 @@
<method name="resume">
<return type="Variant">
</return>
- <argument index="0" name="args" type="Array" default="null">
+ <argument index="0" name="args" type="Array" default="[ ]">
</argument>
<description>
</description>
diff --git a/modules/visual_script/doc_classes/VisualScriptInputAction.xml b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
index 6c296fdb4b..9ca67feacb 100644
--- a/modules/visual_script/doc_classes/VisualScriptInputAction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
@@ -9,7 +9,7 @@
<methods>
</methods>
<members>
- <member name="action" type="StringName" setter="set_action_name" getter="get_action_name" default="@&quot;&quot;">
+ <member name="action" type="StringName" setter="set_action_name" getter="get_action_name" default="&amp;&quot;&quot;">
</member>
<member name="mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="VisualScriptInputAction.Mode" default="0">
</member>
diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
index c3741eea89..185f0f1ffb 100644
--- a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
@@ -18,7 +18,7 @@
<member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type" default="0">
The local variable's type.
</member>
- <member name="var_name" type="StringName" setter="set_var_name" getter="get_var_name" default="@&quot;new_local&quot;">
+ <member name="var_name" type="StringName" setter="set_var_name" getter="get_var_name" default="&amp;&quot;new_local&quot;">
The local variable's name.
</member>
</members>
diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
index 619bbb90ca..865f0153c9 100644
--- a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
@@ -20,7 +20,7 @@
<member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type" default="0">
The local variable's type.
</member>
- <member name="var_name" type="StringName" setter="set_var_name" getter="get_var_name" default="@&quot;new_local&quot;">
+ <member name="var_name" type="StringName" setter="set_var_name" getter="get_var_name" default="&amp;&quot;new_local&quot;">
The local variable's name.
</member>
</members>
diff --git a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
index 1c22070ab1..ff6c723a3e 100644
--- a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
@@ -11,7 +11,7 @@
<members>
<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
</member>
- <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="@&quot;Object&quot;">
+ <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
</member>
<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
</member>
@@ -19,7 +19,7 @@
</member>
<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
</member>
- <member name="property" type="StringName" setter="set_property" getter="get_property" default="@&quot;&quot;">
+ <member name="property" type="StringName" setter="set_property" getter="get_property" default="&amp;&quot;&quot;">
</member>
<member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertyGet.CallMode" default="0">
</member>
diff --git a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
index 629576e261..71bfc4c8a5 100644
--- a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -13,7 +13,7 @@
</member>
<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
</member>
- <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="@&quot;Object&quot;">
+ <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
</member>
<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
</member>
@@ -21,7 +21,7 @@
</member>
<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
</member>
- <member name="property" type="StringName" setter="set_property" getter="get_property" default="@&quot;&quot;">
+ <member name="property" type="StringName" setter="set_property" getter="get_property" default="&amp;&quot;&quot;">
</member>
<member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertySet.CallMode" default="0">
</member>
diff --git a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
index 80a8d31041..9e3e020f2d 100644
--- a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
+++ b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
@@ -11,7 +11,7 @@
<members>
<member name="base_script" type="String" setter="set_base_script" getter="get_base_script" default="&quot;&quot;">
</member>
- <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="@&quot;Object&quot;">
+ <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
</member>
</members>
<constants>
diff --git a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
index d182e14e4d..df20ac53f2 100644
--- a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
@@ -15,7 +15,7 @@
<methods>
</methods>
<members>
- <member name="var_name" type="StringName" setter="set_variable" getter="get_variable" default="@&quot;&quot;">
+ <member name="var_name" type="StringName" setter="set_variable" getter="get_variable" default="&amp;&quot;&quot;">
The variable's name.
</member>
</members>
diff --git a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
index 3bd392dd85..eb8ebbe338 100644
--- a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
@@ -16,7 +16,7 @@
<methods>
</methods>
<members>
- <member name="var_name" type="StringName" setter="set_variable" getter="get_variable" default="@&quot;&quot;">
+ <member name="var_name" type="StringName" setter="set_variable" getter="get_variable" default="&amp;&quot;&quot;">
The variable's name.
</member>
</members>
diff --git a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
index 483cdfeaf8..c59234433f 100644
--- a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
@@ -9,13 +9,13 @@
<methods>
</methods>
<members>
- <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="@&quot;Object&quot;">
+ <member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
</member>
<member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptYieldSignal.CallMode" default="0">
</member>
<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
</member>
- <member name="signal" type="StringName" setter="set_signal" getter="get_signal" default="@&quot;&quot;">
+ <member name="signal" type="StringName" setter="set_signal" getter="get_signal" default="&amp;&quot;&quot;">
</member>
</members>
<constants>
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index b863f622bd..7badb1b717 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -954,60 +954,10 @@ bool VisualScript::are_subnodes_edited() const {
}
#endif
-Vector<ScriptNetData> VisualScript::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> VisualScript::get_rpc_methods() const {
return rpc_functions;
}
-uint16_t VisualScript::get_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < rpc_functions.size(); i++) {
- if (rpc_functions[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName VisualScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName());
- return rpc_functions[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode VisualScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_functions[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode VisualScript::get_rpc_mode(const StringName &p_method) const {
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> VisualScript::get_rset_properties() const {
- return rpc_variables;
-}
-
-uint16_t VisualScript::get_rset_property_id(const StringName &p_variable) const {
- for (int i = 0; i < rpc_variables.size(); i++) {
- if (rpc_variables[i].name == p_variable) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName VisualScript::get_rset_property(const uint16_t p_rset_property_id) const {
- ERR_FAIL_COND_V(p_rset_property_id >= rpc_variables.size(), StringName());
- return rpc_variables[p_rset_property_id].name;
-}
-
-MultiplayerAPI::RPCMode VisualScript::get_rset_mode_by_id(const uint16_t p_rset_variable_id) const {
- ERR_FAIL_COND_V(p_rset_variable_id >= rpc_variables.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_variables[p_rset_variable_id].mode;
-}
-
-MultiplayerAPI::RPCMode VisualScript::get_rset_mode(const StringName &p_variable) const {
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
void VisualScript::_set_data(const Dictionary &p_data) {
Dictionary d = p_data;
if (d.has("base_type")) {
@@ -1065,7 +1015,6 @@ void VisualScript::_set_data(const Dictionary &p_data) {
// Takes all the rpc methods.
rpc_functions.clear();
- rpc_variables.clear();
List<StringName> fns;
functions.get_key_list(&fns);
for (const List<StringName>::Element *E = fns.front(); E; E = E->next()) {
@@ -1073,9 +1022,10 @@ void VisualScript::_set_data(const Dictionary &p_data) {
Ref<VisualScriptFunction> vsf = nodes[functions[E->get()].func_id].node;
if (vsf.is_valid()) {
if (vsf->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
- ScriptNetData nd;
+ MultiplayerAPI::RPCConfig nd;
nd.name = E->get();
- nd.mode = vsf->get_rpc_mode();
+ nd.rpc_mode = vsf->get_rpc_mode();
+ nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE; // TODO
if (rpc_functions.find(nd) == -1) {
rpc_functions.push_back(nd);
}
@@ -1085,7 +1035,7 @@ void VisualScript::_set_data(const Dictionary &p_data) {
}
// Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<SortNetData>();
+ rpc_functions.sort_custom<MultiplayerAPI::SortRPCConfig>();
}
Dictionary VisualScript::_get_data() const {
@@ -1882,46 +1832,10 @@ Ref<Script> VisualScriptInstance::get_script() const {
return script;
}
-Vector<ScriptNetData> VisualScriptInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> VisualScriptInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t VisualScriptInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName VisualScriptInstance::get_rpc_method(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_method(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_mode_by_id(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> VisualScriptInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t VisualScriptInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName VisualScriptInstance::get_rset_property(const uint16_t p_rset_property_id) const {
- return script->get_rset_property(p_rset_property_id);
-}
-
-MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode_by_id(const uint16_t p_rset_variable_id) const {
- return script->get_rset_mode_by_id(p_rset_variable_id);
-}
-
-MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) {
script = p_script;
owner = p_owner;
@@ -2290,7 +2204,7 @@ Variant VisualScriptFunctionState::resume(Array p_args) {
void VisualScriptFunctionState::_bind_methods() {
ClassDB::bind_method(D_METHOD("connect_to_signal", "obj", "signals", "args"), &VisualScriptFunctionState::connect_to_signal);
- ClassDB::bind_method(D_METHOD("resume", "args"), &VisualScriptFunctionState::resume, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("resume", "args"), &VisualScriptFunctionState::resume, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("is_valid"), &VisualScriptFunctionState::is_valid);
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &VisualScriptFunctionState::_signal_callback, MethodInfo("_signal_callback"));
}
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index cc78b3242d..438ec99a56 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -234,8 +234,7 @@ private:
HashMap<StringName, Function> functions;
HashMap<StringName, Variable> variables;
Map<StringName, Vector<Argument>> custom_signals;
- Vector<ScriptNetData> rpc_functions;
- Vector<ScriptNetData> rpc_variables;
+ Vector<MultiplayerAPI::RPCConfig> rpc_functions;
Map<Object *, VisualScriptInstance *> instances;
@@ -363,17 +362,7 @@ public:
virtual int get_member_line(const StringName &p_member) const override;
- virtual Vector<ScriptNetData> get_rpc_methods() const override;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const override;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- virtual Vector<ScriptNetData> get_rset_properties() const override;
- virtual uint16_t get_rset_property_id(const StringName &p_property) const override;
- virtual StringName get_rset_property(const uint16_t p_rset_property_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
#ifdef TOOLS_ENABLED
virtual bool are_subnodes_edited() const;
@@ -454,24 +443,14 @@ public:
virtual ScriptLanguage *get_language();
- virtual Vector<ScriptNetData> get_rpc_methods() const;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
-
- virtual Vector<ScriptNetData> get_rset_properties() const;
- virtual uint16_t get_rset_property_id(const StringName &p_property) const;
- virtual StringName get_rset_property(const uint16_t p_rset_property_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const;
VisualScriptInstance();
~VisualScriptInstance();
};
-class VisualScriptFunctionState : public Reference {
- GDCLASS(VisualScriptFunctionState, Reference);
+class VisualScriptFunctionState : public RefCounted {
+ GDCLASS(VisualScriptFunctionState, RefCounted);
friend class VisualScriptInstance;
ObjectID instance_id;
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 3b24de433c..a3133f126d 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -33,7 +33,7 @@
#include "core/io/marshalls.h"
#include "core/math/math_funcs.h"
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
@@ -132,6 +132,7 @@ bool VisualScriptBuiltinFunc::has_input_sequence_port() const {
case TEXT_PRINT:
case TEXT_PRINTERR:
case TEXT_PRINTRAW:
+ case MATH_SEED:
return true;
default:
return false;
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index dc400982e8..96f103f95a 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -381,7 +381,7 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::PLANE:
color = Color(0.97, 0.44, 0.44);
break;
- case Variant::QUAT:
+ case Variant::QUATERNION:
color = Color(0.93, 0.41, 0.64);
break;
case Variant::AABB:
@@ -390,7 +390,7 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::BASIS:
color = Color(0.89, 0.93, 0.41);
break;
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
color = Color(0.96, 0.66, 0.43);
break;
@@ -487,7 +487,7 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::PLANE:
color = Color(0.97, 0.44, 0.44);
break;
- case Variant::QUAT:
+ case Variant::QUATERNION:
color = Color(0.93, 0.41, 0.64);
break;
case Variant::AABB:
@@ -496,7 +496,7 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::BASIS:
color = Color(0.7, 0.73, 0.1);
break;
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
color = Color(0.96, 0.56, 0.28);
break;
@@ -624,10 +624,10 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Control::get_theme_icon("Vector3i", "EditorIcons"),
Control::get_theme_icon("Transform2D", "EditorIcons"),
Control::get_theme_icon("Plane", "EditorIcons"),
- Control::get_theme_icon("Quat", "EditorIcons"),
+ Control::get_theme_icon("Quaternion", "EditorIcons"),
Control::get_theme_icon("AABB", "EditorIcons"),
Control::get_theme_icon("Basis", "EditorIcons"),
- Control::get_theme_icon("Transform", "EditorIcons"),
+ Control::get_theme_icon("Transform3D", "EditorIcons"),
Control::get_theme_icon("Color", "EditorIcons"),
Control::get_theme_icon("NodePath", "EditorIcons"),
Control::get_theme_icon("RID", "EditorIcons"),
@@ -739,6 +739,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
}
Color c = sbf->get_border_color();
+ c = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0, 0.85) : Color(0.0, 0.0, 0.0, 0.85);
Color ic = c;
gnode->add_theme_color_override("title_color", c);
c.a = 1;
@@ -1074,10 +1075,10 @@ void VisualScriptEditor::_update_members() {
Control::get_theme_icon("Vector3i", "EditorIcons"),
Control::get_theme_icon("Transform2D", "EditorIcons"),
Control::get_theme_icon("Plane", "EditorIcons"),
- Control::get_theme_icon("Quat", "EditorIcons"),
+ Control::get_theme_icon("Quaternion", "EditorIcons"),
Control::get_theme_icon("AABB", "EditorIcons"),
Control::get_theme_icon("Basis", "EditorIcons"),
- Control::get_theme_icon("Transform", "EditorIcons"),
+ Control::get_theme_icon("Transform3D", "EditorIcons"),
Control::get_theme_icon("Color", "EditorIcons"),
Control::get_theme_icon("NodePath", "EditorIcons"),
Control::get_theme_icon("RID", "EditorIcons"),
@@ -1168,11 +1169,11 @@ void VisualScriptEditor::_member_selected() {
selected = ti->get_metadata(0);
- if (ti->get_parent() == members->get_root()->get_children()) {
+ if (ti->get_parent() == members->get_root()->get_first_child()) {
#ifdef OSX_ENABLED
bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_META);
#else
- bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL);
#endif
if (held_ctrl) {
ERR_FAIL_COND(!script->has_function(selected));
@@ -1214,7 +1215,7 @@ void VisualScriptEditor::_member_edited() {
TreeItem *root = members->get_root();
- if (ti->get_parent() == root->get_children()) {
+ if (ti->get_parent() == root->get_first_child()) {
selected = new_name;
int node_id = script->get_function_node_id(name);
@@ -1255,7 +1256,7 @@ void VisualScriptEditor::_member_edited() {
return; // Or crash because it will become invalid.
}
- if (ti->get_parent() == root->get_children()->get_next()) {
+ if (ti->get_parent() == root->get_first_child()->get_next()) {
selected = new_name;
undo_redo->create_action(TTR("Rename Variable"));
undo_redo->add_do_method(script.ptr(), "rename_variable", name, new_name);
@@ -1271,7 +1272,7 @@ void VisualScriptEditor::_member_edited() {
return; // Or crash because it will become invalid.
}
- if (ti->get_parent() == root->get_children()->get_next()->get_next()) {
+ if (ti->get_parent() == root->get_first_child()->get_next()->get_next()) {
selected = new_name;
undo_redo->create_action(TTR("Rename Signal"));
undo_redo->add_do_method(script.ptr(), "rename_custom_signal", name, new_name);
@@ -1405,7 +1406,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt
if (ti->get_parent() == root) {
//main buttons
- if (ti == root->get_children()) {
+ if (ti == root->get_first_child()) {
// Add function, this one uses menu.
if (p_button == 1) {
@@ -1442,7 +1443,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt
return; // Or crash because it will become invalid.
}
- if (ti == root->get_children()->get_next()) {
+ if (ti == root->get_first_child()->get_next()) {
// Add variable.
String name = _validate_name("new_variable");
selected = name;
@@ -1458,7 +1459,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt
return; // Or crash because it will become invalid.
}
- if (ti == root->get_children()->get_next()->get_next()) {
+ if (ti == root->get_first_child()->get_next()->get_next()) {
// Add variable.
String name = _validate_name("new_signal");
selected = name;
@@ -1473,7 +1474,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt
undo_redo->commit_action();
return; // Or crash because it will become invalid.
}
- } else if (ti->get_parent() == root->get_children()) {
+ } else if (ti->get_parent() == root->get_first_child()) {
selected = ti->get_text(0);
function_name_edit->set_position(Input::get_singleton()->get_mouse_position() - Vector2(60, -10));
function_name_edit->popup();
@@ -1841,18 +1842,18 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) {
TreeItem *ti = members->get_selected();
if (ti) {
TreeItem *root = members->get_root();
- if (ti->get_parent() == root->get_children()) {
+ if (ti->get_parent() == root->get_first_child()) {
member_type = MEMBER_FUNCTION;
}
- if (ti->get_parent() == root->get_children()->get_next()) {
+ if (ti->get_parent() == root->get_first_child()->get_next()) {
member_type = MEMBER_VARIABLE;
}
- if (ti->get_parent() == root->get_children()->get_next()->get_next()) {
+ if (ti->get_parent() == root->get_first_child()->get_next()->get_next()) {
member_type = MEMBER_SIGNAL;
}
member_name = ti->get_text(0);
}
- if (ED_IS_SHORTCUT("visual_script_editor/delete_selected", p_event)) {
+ if (ED_IS_SHORTCUT("ui_graph_delete", p_event)) {
_member_option(MEMBER_REMOVE);
}
if (ED_IS_SHORTCUT("visual_script_editor/edit_member", p_event)) {
@@ -1864,7 +1865,7 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> btn = p_event;
if (btn.is_valid() && btn->is_double_click()) {
TreeItem *ti = members->get_selected();
- if (ti && ti->get_parent() == members->get_root()->get_children()) { // to check if it's a function
+ if (ti && ti->get_parent() == members->get_root()->get_first_child()) { // to check if it's a function
_center_on_node(script->get_function_node_id(ti->get_metadata(0)));
}
}
@@ -1946,13 +1947,13 @@ Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f
Dictionary dd;
TreeItem *root = members->get_root();
- if (it->get_parent() == root->get_children()) {
+ if (it->get_parent() == root->get_first_child()) {
dd["type"] = "visual_script_function_drag";
dd["function"] = type;
- } else if (it->get_parent() == root->get_children()->get_next()) {
+ } else if (it->get_parent() == root->get_first_child()->get_next()) {
dd["type"] = "visual_script_variable_drag";
dd["variable"] = type;
- } else if (it->get_parent() == root->get_children()->get_next()->get_next()) {
+ } else if (it->get_parent() == root->get_first_child()->get_next()->get_next()) {
dd["type"] = "visual_script_signal_drag";
dd["signal"] = type;
@@ -2070,7 +2071,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
#ifdef OSX_ENABLED
bool use_set = Input::get_singleton()->is_key_pressed(KEY_META);
#else
- bool use_set = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool use_set = Input::get_singleton()->is_key_pressed(KEY_CTRL);
#endif
Vector2 ofs = graph->get_scroll_ofs() + p_point;
if (graph->is_using_snap()) {
@@ -2258,7 +2259,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
#ifdef OSX_ENABLED
bool use_node = Input::get_singleton()->is_key_pressed(KEY_META);
#else
- bool use_node = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool use_node = Input::get_singleton()->is_key_pressed(KEY_CTRL);
#endif
Array nodes = d["nodes"];
@@ -2341,7 +2342,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
#ifdef OSX_ENABLED
bool use_get = Input::get_singleton()->is_key_pressed(KEY_META);
#else
- bool use_get = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool use_get = Input::get_singleton()->is_key_pressed(KEY_CTRL);
#endif
if (!node || Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
@@ -2710,6 +2711,10 @@ void VisualScriptEditor::set_debugger_active(bool p_active) {
}
}
+Control *VisualScriptEditor::get_base_editor() const {
+ return graph;
+}
+
void VisualScriptEditor::set_tooltip_request_func(String p_method, Object *p_obj) {
}
@@ -4111,32 +4116,32 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) {
Ref<Texture2D> edit_icon = Control::get_theme_icon("Edit", "EditorIcons");
- if (ti->get_parent() == root->get_children()) {
+ if (ti->get_parent() == root->get_first_child()) {
member_type = MEMBER_FUNCTION;
member_name = ti->get_text(0);
member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT);
member_popup->add_separator();
- member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE);
+ member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE);
member_popup->popup();
return;
}
- if (ti->get_parent() == root->get_children()->get_next()) {
+ if (ti->get_parent() == root->get_first_child()->get_next()) {
member_type = MEMBER_VARIABLE;
member_name = ti->get_text(0);
member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT);
member_popup->add_separator();
- member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE);
+ member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE);
member_popup->popup();
return;
}
- if (ti->get_parent() == root->get_children()->get_next()->get_next()) {
+ if (ti->get_parent() == root->get_first_child()->get_next()->get_next()) {
member_type = MEMBER_SIGNAL;
member_name = ti->get_text(0);
member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT);
member_popup->add_separator();
- member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE);
+ member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE);
member_popup->popup();
return;
}
@@ -4238,9 +4243,9 @@ void VisualScriptEditor::_bind_methods() {
ClassDB::bind_method("_create_new_node_from_name", &VisualScriptEditor::_create_new_node_from_name);
- ClassDB::bind_method("get_drag_data_fw", &VisualScriptEditor::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw", &VisualScriptEditor::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw", &VisualScriptEditor::drop_data_fw);
+ ClassDB::bind_method("_get_drag_data_fw", &VisualScriptEditor::get_drag_data_fw);
+ ClassDB::bind_method("_can_drop_data_fw", &VisualScriptEditor::can_drop_data_fw);
+ ClassDB::bind_method("_drop_data_fw", &VisualScriptEditor::drop_data_fw);
ClassDB::bind_method("_input", &VisualScriptEditor::_input);
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index fc9a2df60f..ca06b807cc 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -317,9 +317,12 @@ public:
virtual void set_tooltip_request_func(String p_method, Object *p_obj) override;
virtual Control *get_edit_menu() override;
virtual void clear_edit_menu() override;
+ virtual void set_find_replace_bar(FindReplaceBar *p_bar) override { p_bar->hide(); }; // Not needed here.
virtual bool can_lose_focus_on_node_selection() override { return false; }
virtual void validate() override;
+ virtual Control *get_base_editor() const override;
+
static void register_editor();
static void free_clipboard();
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 9310b86627..a0ba7b1962 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -737,20 +737,22 @@ public:
}
int to_id = 0;
- bool reliable = true;
+ //bool reliable = true;
if (rpc_mode >= VisualScriptFunctionCall::RPC_RELIABLE_TO_ID) {
to_id = *p_args[0];
p_args += 1;
p_argcount -= 1;
- if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE_TO_ID) {
- reliable = false;
- }
- } else if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE) {
- reliable = false;
+ //if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE_TO_ID) {
+ //reliable = false;
+ //}
}
+ //else if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE) {
+ //reliable = false;
+ //}
- node->rpcp(to_id, !reliable, function, p_args, p_argcount);
+ // TODO reliable?
+ node->rpcp(to_id, function, p_args, p_argcount);
return true;
}
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index fed6637acb..07dc3dfaf6 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -3918,10 +3918,10 @@ void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2I), create_node_deconst_typed<Variant::Type::RECT2I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM2D), create_node_deconst_typed<Variant::Type::TRANSFORM2D>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PLANE), create_node_deconst_typed<Variant::Type::PLANE>);
- VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::QUAT), create_node_deconst_typed<Variant::Type::QUAT>);
+ VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::QUATERNION), create_node_deconst_typed<Variant::Type::QUATERNION>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::AABB), create_node_deconst_typed<Variant::Type::AABB>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::BASIS), create_node_deconst_typed<Variant::Type::BASIS>);
- VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM), create_node_deconst_typed<Variant::Type::TRANSFORM>);
+ VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM3D), create_node_deconst_typed<Variant::Type::TRANSFORM3D>);
VisualScriptLanguage::singleton->add_register_func("functions/compose_array", create_node_generic<VisualScriptComposeArray>);
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp
index 862cac5c67..4a1e020bd4 100644
--- a/modules/visual_script/visual_script_property_selector.cpp
+++ b/modules/visual_script/visual_script_property_selector.cpp
@@ -59,7 +59,7 @@ void VisualScriptPropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) {
search_box->accept_event();
TreeItem *root = search_options->get_root();
- if (!root->get_children()) {
+ if (!root->get_first_child()) {
break;
}
@@ -108,10 +108,10 @@ void VisualScriptPropertySelector::_update_search() {
vbc->get_theme_icon("Vector3", "EditorIcons"),
vbc->get_theme_icon("Transform2D", "EditorIcons"),
vbc->get_theme_icon("Plane", "EditorIcons"),
- vbc->get_theme_icon("Quat", "EditorIcons"),
+ vbc->get_theme_icon("Quaternion", "EditorIcons"),
vbc->get_theme_icon("AABB", "EditorIcons"),
vbc->get_theme_icon("Basis", "EditorIcons"),
- vbc->get_theme_icon("Transform", "EditorIcons"),
+ vbc->get_theme_icon("Transform3D", "EditorIcons"),
vbc->get_theme_icon("Color", "EditorIcons"),
vbc->get_theme_icon("Path", "EditorIcons"),
vbc->get_theme_icon("RID", "EditorIcons"),
@@ -265,7 +265,7 @@ void VisualScriptPropertySelector::_update_search() {
item->set_metadata(2, connecting);
}
- if (category && category->get_children() == nullptr) {
+ if (category && category->get_first_child() == nullptr) {
memdelete(category); //old category was unused
}
}
@@ -310,7 +310,7 @@ void VisualScriptPropertySelector::_update_search() {
found = true;
}
- get_ok_button()->set_disabled(root->get_children() == nullptr);
+ get_ok_button()->set_disabled(root->get_first_child() == nullptr);
}
void VisualScriptPropertySelector::create_visualscript_item(const String &name, TreeItem *const root, const String &search_input, const String &text) {
diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub
index 67d3f1bebd..4334cf732b 100644
--- a/modules/webm/libvpx/SCsub
+++ b/modules/webm/libvpx/SCsub
@@ -235,7 +235,7 @@ if env["platform"] == "uwp":
else:
import platform
- is_x11_or_server_arm = (env["platform"] == "linuxbsd" or env["platform"] == "server") and (
+ is_x11_or_server_arm = env["platform"] == "linuxbsd" and (
platform.machine().startswith("arm") or platform.machine().startswith("aarch")
)
is_macos_x86 = env["platform"] == "osx" and ("arch" in env and (env["arch"] != "arm64"))
@@ -314,12 +314,7 @@ if webm_cpu_x86:
if webm_cpu_arm:
if env["platform"] == "iphone":
env_libvpx["ASFLAGS"] = "-arch armv7"
- elif (
- env["platform"] == "android"
- and env["android_arch"] == "armv7"
- or env["platform"] == "linuxbsd"
- or env["platform"] == "server"
- ):
+ elif env["platform"] == "android" and env["android_arch"] == "armv7" or env["platform"] == "linuxbsd":
env_libvpx["ASFLAGS"] = "-mfpu=neon"
elif env["platform"] == "uwp":
env_libvpx["AS"] = "armasm"
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index a6b64b342e..6ec0bde7bd 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -31,7 +31,7 @@
#include "video_stream_webm.h"
#include "core/config/project_settings.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#include "servers/audio_server.h"
@@ -62,10 +62,10 @@ public:
virtual int Read(long long pos, long len, unsigned char *buf) {
if (file) {
- if (file->get_position() != (size_t)pos) {
+ if (file->get_position() != (uint64_t)pos) {
file->seek(pos);
}
- if (file->get_buffer(buf, len) == len) {
+ if (file->get_buffer(buf, len) == (uint64_t)len) {
return 0;
}
}
@@ -74,7 +74,7 @@ public:
virtual int Length(long long *total, long long *available) {
if (file) {
- const size_t len = file->get_len();
+ const uint64_t len = file->get_length();
if (total) {
*total = len;
}
diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp
index 6e62840a3e..772445190c 100644
--- a/modules/webp/image_loader_webp.cpp
+++ b/modules/webp/image_loader_webp.cpp
@@ -30,6 +30,7 @@
#include "image_loader_webp.h"
+#include "core/config/project_settings.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -69,12 +70,77 @@ static Vector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quali
w[2] = 'B';
w[3] = 'P';
memcpy(&w[4], dst_buff, dst_size);
- free(dst_buff);
+ WebPFree(dst_buff);
return dst;
}
-static Ref<Image> _webp_lossy_unpack(const Vector<uint8_t> &p_buffer) {
+static Vector<uint8_t> _webp_lossless_pack(const Ref<Image> &p_image) {
+ ERR_FAIL_COND_V(p_image.is_null() || p_image->is_empty(), Vector<uint8_t>());
+
+ int compression_level = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/webp_compression_level");
+ compression_level = CLAMP(compression_level, 0, 9);
+
+ Ref<Image> img = p_image->duplicate();
+ if (img->detect_alpha()) {
+ img->convert(Image::FORMAT_RGBA8);
+ } else {
+ img->convert(Image::FORMAT_RGB8);
+ }
+
+ Size2 s(img->get_width(), img->get_height());
+ Vector<uint8_t> data = img->get_data();
+ const uint8_t *r = data.ptr();
+
+ // we need to use the more complex API in order to access the 'exact' flag...
+
+ WebPConfig config;
+ WebPPicture pic;
+ if (!WebPConfigInit(&config) || !WebPConfigLosslessPreset(&config, compression_level) || !WebPPictureInit(&pic)) {
+ ERR_FAIL_V(Vector<uint8_t>());
+ }
+
+ WebPMemoryWriter wrt;
+ config.exact = 1;
+ pic.use_argb = 1;
+ pic.width = s.width;
+ pic.height = s.height;
+ pic.writer = WebPMemoryWrite;
+ pic.custom_ptr = &wrt;
+ WebPMemoryWriterInit(&wrt);
+
+ bool success_import = false;
+ if (img->get_format() == Image::FORMAT_RGB8) {
+ success_import = WebPPictureImportRGB(&pic, r, 3 * s.width);
+ } else {
+ success_import = WebPPictureImportRGBA(&pic, r, 4 * s.width);
+ }
+ bool success_encode = false;
+ if (success_import) {
+ success_encode = WebPEncode(&config, &pic);
+ }
+ WebPPictureFree(&pic);
+
+ if (!success_encode) {
+ WebPMemoryWriterClear(&wrt);
+ ERR_FAIL_V_MSG(Vector<uint8_t>(), "WebP packing failed.");
+ }
+
+ // copy from wrt
+ Vector<uint8_t> dst;
+ dst.resize(4 + wrt.size);
+ uint8_t *w = dst.ptrw();
+ w[0] = 'W';
+ w[1] = 'E';
+ w[2] = 'B';
+ w[3] = 'P';
+ memcpy(&w[4], wrt.mem, wrt.size);
+ WebPMemoryWriterClear(&wrt);
+
+ return dst;
+}
+
+static Ref<Image> _webp_unpack(const Vector<uint8_t> &p_buffer) {
int size = p_buffer.size() - 4;
ERR_FAIL_COND_V(size <= 0, Ref<Image>());
const uint8_t *r = p_buffer.ptr();
@@ -147,7 +213,7 @@ static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) {
Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
Vector<uint8_t> src_image;
- int src_image_len = f->get_len();
+ uint64_t src_image_len = f->get_length();
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
src_image.resize(src_image_len);
@@ -168,6 +234,7 @@ void ImageLoaderWEBP::get_recognized_extensions(List<String> *p_extensions) cons
ImageLoaderWEBP::ImageLoaderWEBP() {
Image::_webp_mem_loader_func = _webp_mem_loader_func;
- Image::lossy_packer = _webp_lossy_pack;
- Image::lossy_unpacker = _webp_lossy_unpack;
+ Image::webp_lossy_packer = _webp_lossy_pack;
+ Image::webp_lossless_packer = _webp_lossless_pack;
+ Image::webp_unpacker = _webp_unpack;
}
diff --git a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
index e21dee8eff..62e524825d 100644
--- a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
+++ b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebRTCPeerConnection" inherits="Reference" version="4.0">
+<class name="WebRTCPeerConnection" inherits="RefCounted" version="4.0">
<brief_description>
Interface to a WebRTC peer connection.
</brief_description>
@@ -48,7 +48,7 @@
Valid [code]options[/code] are:
[codeblock]
{
- "negotiated": true, # When set to true (default off), means the channel is negotiated out of band. "id" must be set too. data_channel_received will not be called.
+ "negotiated": true, # When set to true (default off), means the channel is negotiated out of band. "id" must be set too. "data_channel_received" will not be called.
"id": 1, # When "negotiated" is true this value must also be set to the same value on both peer.
# Only one of maxRetransmits and maxPacketLifeTime can be specified, not both. They make the channel unreliable (but also better at real time).
diff --git a/modules/webrtc/webrtc_multiplayer.h b/modules/webrtc/webrtc_multiplayer.h
index 6b4ae6fcc8..2ddb98f656 100644
--- a/modules/webrtc/webrtc_multiplayer.h
+++ b/modules/webrtc/webrtc_multiplayer.h
@@ -48,7 +48,7 @@ private:
CH_RESERVED_MAX = 3
};
- class ConnectedPeer : public Reference {
+ class ConnectedPeer : public RefCounted {
public:
Ref<WebRTCPeerConnection> connection;
List<Ref<WebRTCDataChannel>> channels;
diff --git a/modules/webrtc/webrtc_peer_connection.h b/modules/webrtc/webrtc_peer_connection.h
index ae75864489..fcfb9ae9ae 100644
--- a/modules/webrtc/webrtc_peer_connection.h
+++ b/modules/webrtc/webrtc_peer_connection.h
@@ -34,8 +34,8 @@
#include "core/io/packet_peer.h"
#include "modules/webrtc/webrtc_data_channel.h"
-class WebRTCPeerConnection : public Reference {
- GDCLASS(WebRTCPeerConnection, Reference);
+class WebRTCPeerConnection : public RefCounted {
+ GDCLASS(WebRTCPeerConnection, RefCounted);
public:
enum ConnectionState {
diff --git a/modules/websocket/emws_server.h b/modules/websocket/emws_server.h
index e7285ccb86..d36e3a3557 100644
--- a/modules/websocket/emws_server.h
+++ b/modules/websocket/emws_server.h
@@ -33,7 +33,7 @@
#ifdef JAVASCRIPT_ENABLED
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "emws_peer.h"
#include "websocket_server.h"
diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h
index 10da51fce5..bc5e591e7b 100644
--- a/modules/websocket/websocket_server.h
+++ b/modules/websocket/websocket_server.h
@@ -32,7 +32,7 @@
#define WEBSOCKET_H
#include "core/crypto/crypto.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "websocket_multiplayer_peer.h"
#include "websocket_peer.h"
diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h
index c2cf9df58b..39177a16a8 100644
--- a/modules/websocket/wsl_server.h
+++ b/modules/websocket/wsl_server.h
@@ -46,7 +46,7 @@ class WSLServer : public WebSocketServer {
GDCIIMPL(WSLServer, WebSocketServer);
private:
- class PendingPeer : public Reference {
+ class PendingPeer : public RefCounted {
private:
bool _parse_request(const Vector<String> p_protocols);
diff --git a/modules/webxr/config.py b/modules/webxr/config.py
index 9efebed4e6..f676ef3483 100644
--- a/modules/webxr/config.py
+++ b/modules/webxr/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return True
+ return not env["disable_3d"]
def configure(env):
diff --git a/modules/webxr/doc_classes/WebXRInterface.xml b/modules/webxr/doc_classes/WebXRInterface.xml
index 2407d44496..9b3a063ef5 100644
--- a/modules/webxr/doc_classes/WebXRInterface.xml
+++ b/modules/webxr/doc_classes/WebXRInterface.xml
@@ -7,7 +7,7 @@
WebXR is an open standard that allows creating VR and AR applications that run in the web browser.
As such, this interface is only available when running in an HTML5 export.
WebXR supports a wide range of devices, from the very capable (like Valve Index, HTC Vive, Oculus Rift and Quest) down to the much less capable (like Google Cardboard, Oculus Go, GearVR, or plain smartphones).
- Since WebXR is based on Javascript, it makes extensive use of callbacks, which means that [WebXRInterface] is forced to use signals, where other AR/VR interfaces would instead use functions that return a result immediately. This makes [WebXRInterface] quite a bit more complicated to intialize than other AR/VR interfaces.
+ Since WebXR is based on Javascript, it makes extensive use of callbacks, which means that [WebXRInterface] is forced to use signals, where other AR/VR interfaces would instead use functions that return a result immediately. This makes [WebXRInterface] quite a bit more complicated to initialize than other AR/VR interfaces.
Here's the minimum code required to start an immersive VR session:
[codeblock]
extends Node3D
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index 06f3fe6284..13981e73e1 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -265,8 +265,8 @@ void WebXRInterfaceJS::uninitialize() {
};
};
-Transform WebXRInterfaceJS::_js_matrix_to_transform(float *p_js_matrix) {
- Transform transform;
+Transform3D WebXRInterfaceJS::_js_matrix_to_transform(float *p_js_matrix) {
+ Transform3D transform;
transform.basis.elements[0].x = p_js_matrix[0];
transform.basis.elements[1].x = p_js_matrix[1];
@@ -305,13 +305,30 @@ Size2 WebXRInterfaceJS::get_render_targetsize() {
return render_targetsize;
};
-Transform WebXRInterfaceJS::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {
- Transform transform_for_eye;
+Transform3D WebXRInterfaceJS::get_camera_transform() {
+ Transform3D transform_for_eye;
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, transform_for_eye);
- float *js_matrix = godot_webxr_get_transform_for_eye(p_eye);
+ float *js_matrix = godot_webxr_get_transform_for_eye(0);
+ if (!initialized || js_matrix == nullptr) {
+ return transform_for_eye;
+ }
+
+ transform_for_eye = _js_matrix_to_transform(js_matrix);
+ free(js_matrix);
+
+ return xr_server->get_reference_frame() * transform_for_eye;
+};
+
+Transform3D WebXRInterfaceJS::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
+ Transform3D transform_for_eye;
+
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, transform_for_eye);
+
+ float *js_matrix = godot_webxr_get_transform_for_eye(p_view + 1);
if (!initialized || js_matrix == nullptr) {
transform_for_eye = p_cam_transform;
return transform_for_eye;
@@ -323,10 +340,10 @@ Transform WebXRInterfaceJS::get_transform_for_eye(XRInterface::Eyes p_eye, const
return p_cam_transform * xr_server->get_reference_frame() * transform_for_eye;
};
-CameraMatrix WebXRInterfaceJS::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+CameraMatrix WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
CameraMatrix eye;
- float *js_matrix = godot_webxr_get_projection_for_eye(p_eye);
+ float *js_matrix = godot_webxr_get_projection_for_eye(p_view + 1);
if (!initialized || js_matrix == nullptr) {
return eye;
}
@@ -399,7 +416,7 @@ void WebXRInterfaceJS::_update_tracker(int p_controller_id) {
float *tracker_matrix = godot_webxr_get_controller_transform(p_controller_id);
if (tracker_matrix) {
- Transform transform = _js_matrix_to_transform(tracker_matrix);
+ Transform3D transform = _js_matrix_to_transform(tracker_matrix);
tracker->set_position(transform.origin);
tracker->set_orientation(transform.basis);
free(tracker_matrix);
diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h
index 7c841c1911..723ab952cd 100644
--- a/modules/webxr/webxr_interface_js.h
+++ b/modules/webxr/webxr_interface_js.h
@@ -56,7 +56,7 @@ private:
bool controllers_state[2];
Size2 render_targetsize;
- Transform _js_matrix_to_transform(float *p_js_matrix);
+ Transform3D _js_matrix_to_transform(float *p_js_matrix);
void _update_tracker(int p_controller_id);
public:
@@ -84,8 +84,9 @@ public:
virtual Size2 get_render_targetsize() override;
virtual bool is_stereo() override;
- virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) override;
- virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
+ virtual Transform3D get_camera_transform() override;
+ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
+ virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye) override;
virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override;
diff --git a/platform/android/SCsub b/platform/android/SCsub
index 7e9dac926c..56fbd2f7e4 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -9,7 +9,6 @@ android_files = [
"dir_access_jandroid.cpp",
"thread_jandroid.cpp",
"net_socket_android.cpp",
- "audio_driver_jandroid.cpp",
"java_godot_lib_jni.cpp",
"java_class_wrapper.cpp",
"java_godot_wrapper.cpp",
diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h
index e0ee2888c0..6d25a366a4 100644
--- a/platform/android/android_keys_utils.h
+++ b/platform/android/android_keys_utils.h
@@ -127,8 +127,8 @@ static _WinTranslatePair _ak_to_keycode[] = {
{ KEY_BACKSLASH, AKEYCODE_BACKSLASH },
{ KEY_BRACKETLEFT, AKEYCODE_LEFT_BRACKET },
{ KEY_BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET },
- { KEY_CONTROL, AKEYCODE_CTRL_LEFT },
- { KEY_CONTROL, AKEYCODE_CTRL_RIGHT },
+ { KEY_CTRL, AKEYCODE_CTRL_LEFT },
+ { KEY_CTRL, AKEYCODE_CTRL_RIGHT },
{ KEY_UNKNOWN, 0 }
};
/*
diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h
index d6c7a1abe5..ff7bf43573 100644
--- a/platform/android/api/java_class_wrapper.h
+++ b/platform/android/api/java_class_wrapper.h
@@ -31,7 +31,7 @@
#ifndef JAVA_CLASS_WRAPPER_H
#define JAVA_CLASS_WRAPPER_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#ifdef ANDROID_ENABLED
#include <android/log.h>
@@ -42,8 +42,8 @@
class JavaObject;
#endif
-class JavaClass : public Reference {
- GDCLASS(JavaClass, Reference);
+class JavaClass : public RefCounted {
+ GDCLASS(JavaClass, RefCounted);
#ifdef ANDROID_ENABLED
enum ArgumentType{
@@ -184,8 +184,8 @@ public:
JavaClass();
};
-class JavaObject : public Reference {
- GDCLASS(JavaObject, Reference);
+class JavaObject : public RefCounted {
+ GDCLASS(JavaObject, RefCounted);
#ifdef ANDROID_ENABLED
Ref<JavaClass> base_class;
diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp
deleted file mode 100644
index 3a2ccac481..0000000000
--- a/platform/android/audio_driver_jandroid.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*************************************************************************/
-/* audio_driver_jandroid.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "audio_driver_jandroid.h"
-
-#include "core/config/project_settings.h"
-#include "core/os/os.h"
-#include "thread_jandroid.h"
-
-AudioDriverAndroid *AudioDriverAndroid::s_ad = nullptr;
-
-jobject AudioDriverAndroid::io;
-jmethodID AudioDriverAndroid::_init_audio;
-jmethodID AudioDriverAndroid::_write_buffer;
-jmethodID AudioDriverAndroid::_quit;
-jmethodID AudioDriverAndroid::_pause;
-bool AudioDriverAndroid::active = false;
-jclass AudioDriverAndroid::cls;
-int AudioDriverAndroid::audioBufferFrames = 0;
-int AudioDriverAndroid::mix_rate = 44100;
-bool AudioDriverAndroid::quit = false;
-jobject AudioDriverAndroid::audioBuffer = nullptr;
-void *AudioDriverAndroid::audioBufferPinned = nullptr;
-Mutex AudioDriverAndroid::mutex;
-int32_t *AudioDriverAndroid::audioBuffer32 = nullptr;
-
-const char *AudioDriverAndroid::get_name() const {
- return "Android";
-}
-
-Error AudioDriverAndroid::init() {
- /*
- // TODO: pass in/return a (Java) device ID, also whether we're opening for input or output
- this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
- SDL_CalculateAudioSpec(&this->spec);
-
- if (this->spec.samples == 0) {
- // Init failed?
- SDL_SetError("Java-side initialization failed!");
- return 0;
- }
-*/
-
- //Android_JNI_SetupThread();
-
- // __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
-
- JNIEnv *env = get_jni_env();
- int mix_rate = GLOBAL_GET("audio/driver/mix_rate");
-
- int latency = GLOBAL_GET("audio/driver/output_latency");
- unsigned int buffer_size = next_power_of_2(latency * mix_rate / 1000);
- print_verbose("Audio buffer size: " + itos(buffer_size));
-
- audioBuffer = env->CallObjectMethod(io, _init_audio, mix_rate, buffer_size);
-
- ERR_FAIL_COND_V(audioBuffer == nullptr, ERR_INVALID_PARAMETER);
-
- audioBuffer = env->NewGlobalRef(audioBuffer);
-
- jboolean isCopy = JNI_FALSE;
- audioBufferPinned = env->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
- audioBufferFrames = env->GetArrayLength((jshortArray)audioBuffer);
- audioBuffer32 = memnew_arr(int32_t, audioBufferFrames);
-
- return OK;
-}
-
-void AudioDriverAndroid::start() {
- active = true;
-}
-
-void AudioDriverAndroid::setup(jobject p_io) {
- JNIEnv *env = get_jni_env();
- io = p_io;
-
- jclass c = env->GetObjectClass(io);
- cls = (jclass)env->NewGlobalRef(c);
-
- _init_audio = env->GetMethodID(cls, "audioInit", "(II)Ljava/lang/Object;");
- _write_buffer = env->GetMethodID(cls, "audioWriteShortBuffer", "([S)V");
- _quit = env->GetMethodID(cls, "audioQuit", "()V");
- _pause = env->GetMethodID(cls, "audioPause", "(Z)V");
-}
-
-void AudioDriverAndroid::thread_func(JNIEnv *env) {
- jclass cls = env->FindClass("org/godotengine/godot/Godot");
- if (cls) {
- cls = (jclass)env->NewGlobalRef(cls);
- }
- jfieldID fid = env->GetStaticFieldID(cls, "io", "Lorg/godotengine/godot/GodotIO;");
- jobject ob = env->GetStaticObjectField(cls, fid);
- jobject gob = env->NewGlobalRef(ob);
- jclass c = env->GetObjectClass(gob);
- jclass lcls = (jclass)env->NewGlobalRef(c);
- _write_buffer = env->GetMethodID(lcls, "audioWriteShortBuffer", "([S)V");
-
- while (!quit) {
- int16_t *ptr = (int16_t *)audioBufferPinned;
- int fc = audioBufferFrames;
-
- if (!s_ad->active || mutex.try_lock() != OK) {
- for (int i = 0; i < fc; i++) {
- ptr[i] = 0;
- }
-
- } else {
- s_ad->audio_server_process(fc / 2, audioBuffer32);
-
- mutex.unlock();
-
- for (int i = 0; i < fc; i++) {
- ptr[i] = audioBuffer32[i] >> 16;
- }
- }
- env->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)ptr, JNI_COMMIT);
- env->CallVoidMethod(gob, _write_buffer, (jshortArray)audioBuffer);
- }
-}
-
-int AudioDriverAndroid::get_mix_rate() const {
- return mix_rate;
-}
-
-AudioDriver::SpeakerMode AudioDriverAndroid::get_speaker_mode() const {
- return SPEAKER_MODE_STEREO;
-}
-
-void AudioDriverAndroid::lock() {
- mutex.lock();
-}
-
-void AudioDriverAndroid::unlock() {
- mutex.unlock();
-}
-
-void AudioDriverAndroid::finish() {
- JNIEnv *env = get_jni_env();
- env->CallVoidMethod(io, _quit);
-
- if (audioBuffer) {
- env->DeleteGlobalRef(audioBuffer);
- audioBuffer = nullptr;
- audioBufferPinned = nullptr;
- }
-
- active = false;
-}
-
-void AudioDriverAndroid::set_pause(bool p_pause) {
- JNIEnv *env = get_jni_env();
- env->CallVoidMethod(io, _pause, p_pause);
-}
-
-AudioDriverAndroid::AudioDriverAndroid() {
- s_ad = this;
- active = false;
-}
diff --git a/platform/android/audio_driver_jandroid.h b/platform/android/audio_driver_jandroid.h
deleted file mode 100644
index 9007fd2f81..0000000000
--- a/platform/android/audio_driver_jandroid.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*************************************************************************/
-/* audio_driver_jandroid.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef AUDIO_DRIVER_ANDROID_H
-#define AUDIO_DRIVER_ANDROID_H
-
-#include "servers/audio_server.h"
-
-#include "java_godot_lib_jni.h"
-
-class AudioDriverAndroid : public AudioDriver {
- static Mutex mutex;
- static AudioDriverAndroid *s_ad;
- static jobject io;
- static jmethodID _init_audio;
- static jmethodID _write_buffer;
- static jmethodID _quit;
- static jmethodID _pause;
- static bool active;
- static bool quit;
-
- static jclass cls;
-
- static jobject audioBuffer;
- static void *audioBufferPinned;
- static int32_t *audioBuffer32;
- static int audioBufferFrames;
- static int mix_rate;
-
-public:
- void set_singleton();
-
- virtual const char *get_name() const;
-
- virtual Error init();
- virtual void start();
- virtual int get_mix_rate() const;
- virtual SpeakerMode get_speaker_mode() const;
- virtual void lock();
- virtual void unlock();
- virtual void finish();
-
- virtual void set_pause(bool p_pause);
-
- static void setup(jobject p_io);
- static void thread_func(JNIEnv *env);
-
- AudioDriverAndroid();
-};
-
-#endif // AUDIO_DRIVER_ANDROID_H
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 2a80a3c45b..1b6af8662e 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -250,7 +250,7 @@ def configure(env):
env["RANLIB"] = tools_path + "/ranlib"
env["AS"] = tools_path + "/as"
- common_opts = ["-fno-integrated-as", "-gcc-toolchain", gcc_toolchain_path]
+ common_opts = ["-gcc-toolchain", gcc_toolchain_path]
# Compile flags
@@ -285,6 +285,9 @@ def configure(env):
)
env.Append(CPPDEFINES=["NO_STATVFS", "GLES_ENABLED"])
+ if get_platform(env["ndk_platform"]) >= 24:
+ env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)])
+
env["neon_enabled"] = False
if env["android_arch"] == "x86":
target_opts = ["-target", "i686-none-linux-android"]
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index f8ac29c738..0bae090702 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -201,8 +201,7 @@ String DirAccessJAndroid::get_filesystem_type() const {
return "APK";
}
-//FileType get_file_type() const;
-size_t DirAccessJAndroid::get_space_left() {
+uint64_t DirAccessJAndroid::get_space_left() {
return 0;
}
diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h
index fed468d051..cdf98187ed 100644
--- a/platform/android/dir_access_jandroid.h
+++ b/platform/android/dir_access_jandroid.h
@@ -31,7 +31,7 @@
#ifndef DIR_ACCESS_JANDROID_H
#define DIR_ACCESS_JANDROID_H
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "java_godot_lib_jni.h"
#include <stdio.h>
@@ -74,10 +74,13 @@ public:
virtual Error rename(String p_from, String p_to);
virtual Error remove(String p_name);
+ virtual bool is_link(String p_file) { return false; }
+ virtual String read_link(String p_file) { return p_file; }
+ virtual Error create_link(String p_source, String p_target) { return FAILED; }
+
virtual String get_filesystem_type() const;
- //virtual FileType get_file_type() const;
- size_t get_space_left();
+ uint64_t get_space_left();
static void setup(jobject p_io);
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 7a32184139..ff61eeaee1 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -36,8 +36,6 @@
#include "java_godot_wrapper.h"
#include "os_android.h"
-#include <android/input.h>
-
#if defined(VULKAN_ENABLED)
#include "drivers/vulkan/rendering_device_vulkan.h"
#include "platform/android/vulkan/vulkan_context_android.h"
@@ -51,7 +49,7 @@ DisplayServerAndroid *DisplayServerAndroid::get_singleton() {
bool DisplayServerAndroid::has_feature(Feature p_feature) const {
switch (p_feature) {
//case FEATURE_CONSOLE_WINDOW:
- //case FEATURE_CURSOR_SHAPE:
+ case FEATURE_CURSOR_SHAPE:
//case FEATURE_CUSTOM_CURSOR_SHAPE:
//case FEATURE_GLOBAL_MENU:
//case FEATURE_HIDPI:
@@ -198,7 +196,7 @@ void DisplayServerAndroid::window_set_input_text_callback(const Callable &p_call
}
void DisplayServerAndroid::window_set_rect_changed_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {
- // Not supported on Android.
+ rect_changed_callback = p_callable;
}
void DisplayServerAndroid::window_set_drop_files_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {
@@ -391,6 +389,19 @@ void DisplayServerAndroid::reset_window() {
#endif
}
+void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {
+ if (rect_changed_callback.is_null()) {
+ return;
+ }
+
+ const Variant size = Rect2i(0, 0, p_width, p_height);
+ const Variant *sizep = &size;
+ Variant ret;
+ Callable::CallError ce;
+
+ rect_changed_callback.call(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce);
+}
+
DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver;
@@ -490,10 +501,10 @@ void DisplayServerAndroid::process_joy_event(DisplayServerAndroid::JoypadEvent p
}
void DisplayServerAndroid::_set_key_modifier_state(Ref<InputEventWithModifiers> ev) {
- ev->set_shift(shift_mem);
- ev->set_alt(alt_mem);
- ev->set_metakey(meta_mem);
- ev->set_control(control_mem);
+ ev->set_shift_pressed(shift_mem);
+ ev->set_alt_pressed(alt_mem);
+ ev->set_meta_pressed(meta_mem);
+ ev->set_ctrl_pressed(control_mem);
}
void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed) {
@@ -528,7 +539,7 @@ void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int
if (keycode == KEY_ALT) {
alt_mem = p_pressed;
}
- if (keycode == KEY_CONTROL) {
+ if (keycode == KEY_CTRL) {
control_mem = p_pressed;
}
if (keycode == KEY_META) {
@@ -829,6 +840,12 @@ void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) {
return;
}
+ if (p_mode == MouseMode::MOUSE_MODE_HIDDEN) {
+ OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(CURSOR_TYPE_NULL);
+ } else {
+ cursor_set_shape(cursor_shape);
+ }
+
if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) {
OS_Android::get_singleton()->get_godot_java()->get_godot_view()->request_pointer_capture();
} else {
@@ -870,3 +887,19 @@ int DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_
return godot_button_mask;
}
+
+void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) {
+ if (cursor_shape == p_shape) {
+ return;
+ }
+
+ cursor_shape = p_shape;
+
+ if (mouse_mode == MouseMode::MOUSE_MODE_VISIBLE || mouse_mode == MouseMode::MOUSE_MODE_CONFINED) {
+ OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(android_cursors[cursor_shape]);
+ }
+}
+
+DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {
+ return cursor_shape;
+}
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index b9d1641656..a2f47dcccb 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -70,6 +70,28 @@ private:
int buttons_state;
+ // https://developer.android.com/reference/android/view/PointerIcon
+ // mapping between Godot's cursor shape to Android's'
+ int android_cursors[CURSOR_MAX] = {
+ 1000, //CURSOR_ARROW
+ 1008, //CURSOR_IBEAM
+ 1002, //CURSOR_POINTIN
+ 1007, //CURSOR_CROSS
+ 1004, //CURSOR_WAIT
+ 1004, //CURSOR_BUSY
+ 1021, //CURSOR_DRAG
+ 1021, //CURSOR_CAN_DRO
+ 1000, //CURSOR_FORBIDD (no corresponding icon in Android's icon so fallback to default)
+ 1015, //CURSOR_VSIZE
+ 1014, //CURSOR_HSIZE
+ 1017, //CURSOR_BDIAGSI
+ 1016, //CURSOR_FDIAGSI
+ 1020, //CURSOR_MOVE
+ 1015, //CURSOR_VSPLIT
+ 1014, //CURSOR_HSPLIT
+ 1003, //CURSOR_HELP
+ };
+ const int CURSOR_TYPE_NULL = 0;
MouseMode mouse_mode;
bool keep_screen_on;
@@ -78,6 +100,8 @@ private:
Point2 hover_prev_pos; // needed to calculate the relative position on hover events
Point2 scroll_prev_pos; // needed to calculate the relative position on scroll events
+ CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
+
#if defined(VULKAN_ENABLED)
VulkanContextAndroid *context_vulkan;
RenderingDeviceVulkan *rendering_device_vulkan;
@@ -88,6 +112,7 @@ private:
Callable window_event_callback;
Callable input_event_callback;
Callable input_text_callback;
+ Callable rect_changed_callback;
void _window_callback(const Callable &p_callable, const Variant &p_arg) const;
@@ -180,6 +205,9 @@ public:
void process_joy_event(JoypadEvent p_event);
void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed);
+ virtual void cursor_set_shape(CursorShape p_shape);
+ virtual CursorShape cursor_get_shape() const;
+
void mouse_set_mode(MouseMode p_mode);
MouseMode mouse_get_mode() const;
@@ -188,6 +216,7 @@ public:
static void register_android_driver();
void reset_window();
+ void notify_surface_changed(int p_width, int p_height);
virtual Point2i mouse_get_position() const;
virtual int mouse_get_button_state() const;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index cd3f00f935..1a0c206e28 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -31,11 +31,11 @@
#include "export.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/image_loader.h"
#include "core/io/marshalls.h"
#include "core/io/zip_io.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/templates/safe_refcount.h"
#include "core/version.h"
@@ -609,9 +609,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
zip_fileinfo zipfi;
zipfi.tmz_date.tm_hour = time.hour;
zipfi.tmz_date.tm_mday = date.day;
- zipfi.tmz_date.tm_min = time.min;
+ zipfi.tmz_date.tm_min = time.minute;
zipfi.tmz_date.tm_mon = date.month - 1; // tm_mon is zero indexed
- zipfi.tmz_date.tm_sec = time.sec;
+ zipfi.tmz_date.tm_sec = time.second;
zipfi.tmz_date.tm_year = date.year;
zipfi.dosDate = 0;
zipfi.external_fa = 0;
@@ -847,7 +847,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int version_code = p_preset->get("version/code");
String package_name = p_preset->get("package/unique_name");
- const int screen_orientation = _get_android_orientation_value(_get_screen_orientation());
+ const int screen_orientation =
+ _get_android_orientation_value(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation"))));
bool screen_support_small = p_preset->get("screen/support_small");
bool screen_support_normal = p_preset->get("screen/support_normal");
@@ -856,6 +857,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int xr_mode_index = p_preset->get("xr_features/xr_mode");
+ bool backup_allowed = p_preset->get("user_data_backup/allow");
+
Vector<String> perms;
// Write permissions into the perms variable.
_get_permissions(p_preset, p_give_internet, perms);
@@ -948,6 +951,10 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
}
+ if (tname == "application" && attrname == "allowBackup") {
+ encode_uint32(backup_allowed, &p_manifest.write[iofs + 16]);
+ }
+
if (tname == "instrumentation" && attrname == "targetPackage") {
string_table.write[attr_value] = get_package_name(package_name);
}
@@ -1683,6 +1690,8 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_large"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_xlarge"), true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data_backup/allow"), false));
+
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "apk_expansion/enable"), false));
@@ -1784,7 +1793,7 @@ public:
p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST;
}
- String tmp_export_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport." + uitos(OS::get_singleton()->get_unix_time()) + ".apk");
+ String tmp_export_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpexport." + uitos(OS::get_singleton()->get_unix_time()) + ".apk");
#define CLEANUP_AND_RETURN(m_err) \
{ \
@@ -2028,6 +2037,13 @@ public:
// Validate the rest of the configuration.
String dk = p_preset->get("keystore/debug");
+ String dk_user = p_preset->get("keystore/debug_user");
+ String dk_password = p_preset->get("keystore/debug_password");
+
+ if ((dk.is_empty() || dk_user.is_empty() || dk_password.is_empty()) && (!dk.is_empty() || !dk_user.is_empty() || !dk_password.is_empty())) {
+ valid = false;
+ err += TTR("Either Debug Keystore, Debug User AND Debug Password settings must be configured OR none of them.") + "\n";
+ }
if (!FileAccess::exists(dk)) {
dk = EditorSettings::get_singleton()->get("export/android/debug_keystore");
@@ -2038,6 +2054,13 @@ public:
}
String rk = p_preset->get("keystore/release");
+ String rk_user = p_preset->get("keystore/release_user");
+ String rk_password = p_preset->get("keystore/release_password");
+
+ if ((rk.is_empty() || rk_user.is_empty() || rk_password.is_empty()) && (!rk.is_empty() || !rk_user.is_empty() || !rk_password.is_empty())) {
+ valid = false;
+ err += TTR("Either Release Keystore, Release User AND Release Password settings must be configured OR none of them.") + "\n";
+ }
if (!rk.is_empty() && !FileAccess::exists(rk)) {
valid = false;
@@ -2642,7 +2665,7 @@ public:
FileAccess *dst_f = nullptr;
io2.opaque = &dst_f;
- String tmp_unaligned_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned." + uitos(OS::get_singleton()->get_unix_time()) + ".apk");
+ String tmp_unaligned_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned." + uitos(OS::get_singleton()->get_unix_time()) + ".apk");
#define CLEANUP_AND_RETURN(m_err) \
{ \
diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h
index bbbb526af9..6ab678b8a1 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -31,9 +31,9 @@
#ifndef GODOT_GRADLE_EXPORT_UTIL_H
#define GODOT_GRADLE_EXPORT_UTIL_H
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/zip_io.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "editor/editor_export.h"
@@ -44,28 +44,6 @@ const String godot_project_name_xml_string = R"(<?xml version="1.0" encoding="ut
</resources>
)";
-DisplayServer::ScreenOrientation _get_screen_orientation() {
- String orientation_settings = ProjectSettings::get_singleton()->get("display/window/handheld/orientation");
- DisplayServer::ScreenOrientation screen_orientation;
- if (orientation_settings == "portrait") {
- screen_orientation = DisplayServer::SCREEN_PORTRAIT;
- } else if (orientation_settings == "reverse_landscape") {
- screen_orientation = DisplayServer::SCREEN_REVERSE_LANDSCAPE;
- } else if (orientation_settings == "reverse_portrait") {
- screen_orientation = DisplayServer::SCREEN_REVERSE_PORTRAIT;
- } else if (orientation_settings == "sensor_landscape") {
- screen_orientation = DisplayServer::SCREEN_SENSOR_LANDSCAPE;
- } else if (orientation_settings == "sensor_portrait") {
- screen_orientation = DisplayServer::SCREEN_SENSOR_PORTRAIT;
- } else if (orientation_settings == "sensor") {
- screen_orientation = DisplayServer::SCREEN_SENSOR;
- } else {
- screen_orientation = DisplayServer::SCREEN_LANDSCAPE;
- }
-
- return screen_orientation;
-}
-
int _get_android_orientation_value(DisplayServer::ScreenOrientation screen_orientation) {
switch (screen_orientation) {
case DisplayServer::SCREEN_PORTRAIT:
@@ -266,7 +244,7 @@ String _get_instrumentation_tag(const Ref<EditorExportPreset> &p_preset) {
String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
bool uses_xr = (int)(p_preset->get("xr_features/xr_mode")) == 1;
- String orientation = _get_android_orientation_label(_get_screen_orientation());
+ String orientation = _get_android_orientation_label(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation"))));
String manifest_activity_text = vformat(
" <activity android:name=\"com.godot.game.GodotApp\" "
"tools:replace=\"android:screenOrientation\" "
@@ -280,10 +258,11 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
}
String _get_application_tag(const Ref<EditorExportPreset> &p_preset) {
- String manifest_application_text =
+ String manifest_application_text = vformat(
" <application android:label=\"@string/godot_project_name_string\"\n"
- " android:allowBackup=\"false\" tools:ignore=\"GoogleAppIndexingWarning\"\n"
- " android:icon=\"@mipmap/icon\">\n\n";
+ " android:allowBackup=\"%s\" tools:ignore=\"GoogleAppIndexingWarning\"\n"
+ " android:icon=\"@mipmap/icon\">\n\n",
+ bool_to_string(p_preset->get("user_data_backup/allow")));
manifest_application_text += _get_activity_tag(p_preset);
manifest_application_text += " </application>\n";
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index 705891713f..90370878b7 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -71,8 +71,9 @@ bool FileAccessAndroid::is_open() const {
return a != nullptr;
}
-void FileAccessAndroid::seek(size_t p_position) {
+void FileAccessAndroid::seek(uint64_t p_position) {
ERR_FAIL_COND(!a);
+
AAsset_seek(a, p_position, SEEK_SET);
pos = p_position;
if (pos > len) {
@@ -89,11 +90,11 @@ void FileAccessAndroid::seek_end(int64_t p_position) {
pos = len + p_position;
}
-size_t FileAccessAndroid::get_position() const {
+uint64_t FileAccessAndroid::get_position() const {
return pos;
}
-size_t FileAccessAndroid::get_len() const {
+uint64_t FileAccessAndroid::get_length() const {
return len;
}
@@ -113,11 +114,10 @@ uint8_t FileAccessAndroid::get_8() const {
return byte;
}
-int FileAccessAndroid::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V(p_length < 0, -1);
- off_t r = AAsset_read(a, p_dst, p_length);
+ int r = AAsset_read(a, p_dst, p_length);
if (pos + p_length > len) {
eof = true;
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index 56010c918a..bb4ce36947 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -31,7 +31,7 @@
#ifndef FILE_ACCESS_ANDROID_H
#define FILE_ACCESS_ANDROID_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include <android/asset_manager.h>
#include <android/log.h>
#include <stdio.h>
@@ -40,8 +40,8 @@
class FileAccessAndroid : public FileAccess {
static FileAccess *create_android();
mutable AAsset *a = nullptr;
- mutable size_t len = 0;
- mutable size_t pos = 0;
+ mutable uint64_t len = 0;
+ mutable uint64_t pos = 0;
mutable bool eof = false;
public:
@@ -51,15 +51,15 @@ public:
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
- virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual uint64_t get_position() const; ///< get position in the file
+ virtual uint64_t get_length() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual Error get_error() const; ///< get last error
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index a7fe500be2..a28888d80d 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -118,8 +118,8 @@ task zipCustomBuild(type: Zip) {
}
from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradle.properties', 'gradlew', 'gradlew.bat', 'gradle/**']))
include '**/*'
- archiveName 'android_source.zip'
- destinationDir(file(binDir))
+ archiveFileName = 'android_source.zip'
+ destinationDirectory = file(binDir)
}
def templateExcludedBuildTask() {
diff --git a/platform/android/java/gradlew.bat b/platform/android/java/gradlew.bat
index f9553162f1..11cc30edb0 100644
--- a/platform/android/java/gradlew.bat
+++ b/platform/android/java/gradlew.bat
@@ -1,7 +1,7 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
-@rem Gradle startup script for Windows
+@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@@ -75,7 +75,7 @@ if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
diff --git a/platform/android/java/lib/res/values/strings.xml b/platform/android/java/lib/res/values/strings.xml
index 590b066d8a..010006b81e 100644
--- a/platform/android/java/lib/res/values/strings.xml
+++ b/platform/android/java/lib/res/values/strings.xml
@@ -6,7 +6,7 @@
<string name="text_button_resume_cellular">Resume download</string>
<string name="text_button_wifi_settings">Wi-Fi settings</string>
<string name="text_verifying_download">Verifying Download</string>
- <string name="text_validation_complete">XAPK File Validation Complete. Select OK to exit.</string>
+ <string name="text_validation_complete">XAPK File Validation Complete. Select OK to exit.</string>
<string name="text_validation_failed">XAPK File Validation Failed.</string>
<string name="text_button_pause">Pause Download</string>
<string name="text_button_resume">Resume Download</string>
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
index 63c91561ff..b3ee55ea64 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
@@ -44,11 +44,15 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
+import android.os.Build;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.SurfaceView;
+import androidx.annotation.Keep;
+
/**
* A simple GLSurfaceView sub-class that demonstrate how to perform
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
@@ -72,6 +76,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
private final GodotInputHandler inputHandler;
private final GestureDetector detector;
private final GodotRenderer godotRenderer;
+ private PointerIcon pointerIcon;
public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_32_bits,
boolean p_use_debug_opengl) {
@@ -83,6 +88,9 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
this.inputHandler = new GodotInputHandler(this);
this.detector = new GestureDetector(context, new GodotGestureHandler(this));
this.godotRenderer = new GodotRenderer();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ pointerIcon = PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT);
+ }
init(xrMode, false, 16, 0);
}
@@ -149,6 +157,21 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
return inputHandler.onGenericMotionEvent(event);
}
+ /**
+ * called from JNI to change pointer icon
+ */
+ @Keep
+ public void setPointerIcon(int pointerType) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
+ }
+ }
+
+ @Override
+ public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) {
+ return pointerIcon;
+ }
+
private void init(XRMode xrMode, boolean translucent, int depth, int stencil) {
setPreserveEGLContextOnPause(true);
setFocusableInTouchMode(true);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index c7c7c1b40c..12a8bdb90b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -328,95 +328,6 @@ public class GodotIO {
}
/////////////////////////
- // AUDIO
- /////////////////////////
-
- private Object buf;
- private Thread mAudioThread;
- private AudioTrack mAudioTrack;
-
- public Object audioInit(int sampleRate, int desiredFrames) {
- int channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
- int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
- int frameSize = 4;
-
- System.out.printf("audioInit: initializing audio:\n");
-
- //Log.v("Godot", "Godot audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
-
- // Let the user pick a larger buffer if they really want -- but ye
- // gods they probably shouldn't, the minimums are horrifyingly high
- // latency already
- desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
-
- mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
- channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
-
- audioStartThread();
-
- //Log.v("Godot", "Godot audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
-
- buf = new short[desiredFrames * 2];
- return buf;
- }
-
- public void audioStartThread() {
- mAudioThread = new Thread(new Runnable() {
- public void run() {
- mAudioTrack.play();
- GodotLib.audio();
- }
- });
-
- // I'd take REALTIME if I could get it!
- mAudioThread.setPriority(Thread.MAX_PRIORITY);
- mAudioThread.start();
- }
-
- public void audioWriteShortBuffer(short[] buffer) {
- for (int i = 0; i < buffer.length;) {
- int result = mAudioTrack.write(buffer, i, buffer.length - i);
- if (result > 0) {
- i += result;
- } else if (result == 0) {
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- // Nom nom
- }
- } else {
- Log.w("Godot", "Godot audio: error return from write(short)");
- return;
- }
- }
- }
-
- public void audioQuit() {
- if (mAudioThread != null) {
- try {
- mAudioThread.join();
- } catch (Exception e) {
- Log.v("Godot", "Problem stopping audio thread: " + e);
- }
- mAudioThread = null;
-
- //Log.v("Godot", "Finished waiting for audio thread");
- }
-
- if (mAudioTrack != null) {
- mAudioTrack.stop();
- mAudioTrack = null;
- }
- }
-
- public void audioPause(boolean p_pause) {
- if (p_pause)
- mAudioTrack.pause();
- else
- mAudioTrack.play();
- }
-
- /////////////////////////
// MISCELLANEOUS OS IO
/////////////////////////
@@ -452,6 +363,10 @@ public class GodotIO {
return activity.getFilesDir().getAbsolutePath();
}
+ public String getExternalDataDir() {
+ return activity.getExternalFilesDir(null).getAbsolutePath();
+ }
+
public String getLocale() {
return Locale.getDefault().toString();
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index 534a50e9ed..8108118388 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -175,11 +175,6 @@ public class GodotLib {
public static native void focusout();
/**
- * Invoked when the audio thread is started.
- */
- public static native void audio();
-
- /**
* Used to access Godot global properties.
* @param p_key Property key
* @return String value of the property
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
index 2047c88070..ac333dd827 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
@@ -47,4 +47,6 @@ public interface GodotRenderView {
abstract public void onBackPressed();
abstract public GodotInputHandler getInputHandler();
+
+ abstract public void setPointerIcon(int pointerType);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
index 2e59dbc0d0..169c6cf770 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
@@ -37,17 +37,22 @@ import org.godotengine.godot.vulkan.VkSurfaceView;
import android.annotation.SuppressLint;
import android.content.Context;
+import android.os.Build;
import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.SurfaceView;
+import androidx.annotation.Keep;
+
public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
private final Godot godot;
private final GodotInputHandler mInputHandler;
private final GestureDetector mGestureDetector;
private final VkRenderer mRenderer;
+ private PointerIcon pointerIcon;
public GodotVulkanRenderView(Context context, Godot godot) {
super(context);
@@ -56,7 +61,9 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
mInputHandler = new GodotInputHandler(this);
mGestureDetector = new GestureDetector(context, new GodotGestureHandler(this));
mRenderer = new VkRenderer();
-
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ pointerIcon = PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT);
+ }
setFocusableInTouchMode(true);
startRenderer(mRenderer);
}
@@ -124,6 +131,21 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
return mInputHandler.onGenericMotionEvent(event);
}
+ /**
+ * called from JNI to change pointer icon
+ */
+ @Keep
+ public void setPointerIcon(int pointerType) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
+ }
+ }
+
+ @Override
+ public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) {
+ return pointerIcon;
+ }
+
@Override
public void onResume() {
super.onResume();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
index f0e37d80b8..b01dc2653a 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
@@ -115,7 +115,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf
/**
* Tear down the rendering thread.
*
- * Must not be called before a [VkRenderer] has been set.
+ * Must not be called before a [VkRenderer] has been set.
*/
fun onDestroy() {
vkThread.blockingExit()
diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt
index b967fd5f24..6e59268076 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt
@@ -61,6 +61,7 @@ internal class VkThread(private val vkSurfaceView: VkSurfaceView, private val vk
private var rendererInitialized = false
private var rendererResumed = false
private var resumed = false
+ private var surfaceChanged = false
private var hasSurface = false
private var width = 0
private var height = 0
@@ -141,8 +142,10 @@ internal class VkThread(private val vkSurfaceView: VkSurfaceView, private val vk
fun onSurfaceChanged(width: Int, height: Int) {
lock.withLock {
hasSurface = true
+ surfaceChanged = true;
this.width = width
this.height = height
+
lockCondition.signalAll()
}
}
@@ -188,8 +191,11 @@ internal class VkThread(private val vkSurfaceView: VkSurfaceView, private val vk
rendererInitialized = true
vkRenderer.onVkSurfaceCreated(vkSurfaceView.holder.surface)
}
+ }
+ if (surfaceChanged) {
vkRenderer.onVkSurfaceChanged(vkSurfaceView.holder.surface, width, height)
+ surfaceChanged = false
}
// Break out of the loop so drawing can occur without holding onto the lock.
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index f49b0e843a..ed6b5c3e14 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -102,7 +102,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
if (p_args[i]->get_type() != Variant::OBJECT)
arg_expected = Variant::OBJECT;
else {
- Ref<Reference> ref = *p_args[i];
+ Ref<RefCounted> ref = *p_args[i];
if (!ref.is_null()) {
if (Object::cast_to<JavaObject>(ref.ptr())) {
Ref<JavaObject> jo = ref;
@@ -488,7 +488,7 @@ Variant JavaClass::call(const StringName &p_method, const Variant **p_args, int
return ret;
}
- return Reference::call(p_method, p_args, p_argcount, r_error);
+ return RefCounted::call(p_method, p_args, p_argcount, r_error);
}
JavaClass::JavaClass() {
diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp
index ec3b6f8ac0..5e99135498 100644
--- a/platform/android/java_godot_io_wrapper.cpp
+++ b/platform/android/java_godot_io_wrapper.cpp
@@ -49,6 +49,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
_open_URI = p_env->GetMethodID(cls, "openURI", "(Ljava/lang/String;)I");
_get_data_dir = p_env->GetMethodID(cls, "getDataDir", "()Ljava/lang/String;");
+ _get_external_data_dir = p_env->GetMethodID(cls, "getExternalDataDir", "()Ljava/lang/String;");
_get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;");
_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");
_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");
@@ -92,6 +93,17 @@ String GodotIOJavaWrapper::get_user_data_dir() {
}
}
+String GodotIOJavaWrapper::get_external_data_dir() {
+ if (_get_external_data_dir) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, String());
+ jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_external_data_dir);
+ return jstring_to_string(s, env);
+ } else {
+ return String();
+ }
+}
+
String GodotIOJavaWrapper::get_locale() {
if (_get_locale) {
JNIEnv *env = get_jni_env();
diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h
index 394e97effa..e4c0a4b2c7 100644
--- a/platform/android/java_godot_io_wrapper.h
+++ b/platform/android/java_godot_io_wrapper.h
@@ -47,6 +47,7 @@ private:
jmethodID _open_URI = 0;
jmethodID _get_data_dir = 0;
+ jmethodID _get_external_data_dir = 0;
jmethodID _get_locale = 0;
jmethodID _get_model = 0;
jmethodID _get_screen_DPI = 0;
@@ -66,6 +67,7 @@ public:
Error open_uri(const String &p_uri);
String get_user_data_dir();
+ String get_external_data_dir();
String get_locale();
String get_model();
int get_screen_dpi();
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 0c342dc280..d59366bb64 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -36,7 +36,6 @@
#include "android/asset_manager_jni.h"
#include "api/java_class_wrapper.h"
#include "api/jni_singleton.h"
-#include "audio_driver_jandroid.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/input/input.h"
@@ -94,7 +93,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
FileAccessAndroid::asset_manager = AAssetManager_fromJava(env, amgr);
DirAccessJAndroid::setup(godot_io_java->get_instance());
- AudioDriverAndroid::setup(godot_io_java->get_instance());
NetSocketAndroid::setup(godot_java->get_member_object("netUtils", "Lorg/godotengine/godot/utils/GodotNetUtils;", env));
os_android = new OS_Android(godot_java, godot_io_java, p_use_apk_expansion);
@@ -173,6 +171,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, j
os_android->set_native_window(native_window);
DisplayServerAndroid::get_singleton()->reset_window();
+ DisplayServerAndroid::get_singleton()->notify_surface_changed(p_width, p_height);
}
}
}
@@ -384,11 +383,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env,
os_android->main_loop_focusout();
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz) {
- setup_android_thread();
- AudioDriverAndroid::thread_func(env);
-}
-
JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jclass clazz, jstring path) {
String js = jstring_to_string(path, env);
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index a3e2933185..63e9e6d8e5 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -56,7 +56,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jclass clazz, jint p_device, jint p_hat_x, jint p_hat_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jclass clazz, jint p_device, jboolean p_connected, jstring p_name);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gravity(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z);
diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp
index 6b5e44f371..837d2aeced 100644
--- a/platform/android/java_godot_view_wrapper.cpp
+++ b/platform/android/java_godot_view_wrapper.cpp
@@ -43,6 +43,7 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
if (android_get_device_api_level() >= __ANDROID_API_O__) {
_request_pointer_capture = env->GetMethodID(_cls, "requestPointerCapture", "()V");
_release_pointer_capture = env->GetMethodID(_cls, "releasePointerCapture", "()V");
+ _set_pointer_icon = env->GetMethodID(_cls, "setPointerIcon", "(I)V");
}
}
@@ -64,6 +65,15 @@ void GodotJavaViewWrapper::release_pointer_capture() {
}
}
+void GodotJavaViewWrapper::set_pointer_icon(int pointer_type) {
+ if (_set_pointer_icon != 0) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
+ env->CallVoidMethod(_godot_view, _set_pointer_icon, pointer_type);
+ }
+}
+
GodotJavaViewWrapper::~GodotJavaViewWrapper() {
JNIEnv *env = get_jni_env();
ERR_FAIL_COND(env == nullptr);
diff --git a/platform/android/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h
index bfb4369fb8..da547d8118 100644
--- a/platform/android/java_godot_view_wrapper.h
+++ b/platform/android/java_godot_view_wrapper.h
@@ -45,12 +45,14 @@ private:
jmethodID _request_pointer_capture = 0;
jmethodID _release_pointer_capture = 0;
+ jmethodID _set_pointer_icon = 0;
public:
GodotJavaViewWrapper(jobject godot_view);
void request_pointer_capture();
void release_pointer_capture();
+ void set_pointer_icon(int pointer_type);
~GodotJavaViewWrapper();
};
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 422814dd50..222976d948 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -45,6 +45,23 @@
#include "java_godot_io_wrapper.h"
#include "java_godot_wrapper.h"
+String _remove_symlink(const String &dir) {
+ // Workaround for Android 6.0+ using a symlink.
+ // Save the current directory.
+ char current_dir_name[2048];
+ getcwd(current_dir_name, 2048);
+ // Change directory to the external data directory.
+ chdir(dir.utf8().get_data());
+ // Get the actual directory without the potential symlink.
+ char dir_name_wihout_symlink[2048];
+ getcwd(dir_name_wihout_symlink, 2048);
+ // Convert back to a String.
+ String dir_without_symlink(dir_name_wihout_symlink);
+ // Restore original current directory.
+ chdir(current_dir_name);
+ return dir_without_symlink;
+}
+
class AndroidLogger : public Logger {
public:
virtual void logv(const char *p_format, va_list p_list, bool p_err) {
@@ -199,26 +216,18 @@ String OS_Android::get_user_data_dir() const {
String data_dir = godot_io_java->get_user_data_dir();
if (data_dir != "") {
- //store current dir
- char real_current_dir_name[2048];
- getcwd(real_current_dir_name, 2048);
-
- //go to data dir
- chdir(data_dir.utf8().get_data());
-
- //get actual data dir, so we resolve potential symlink (Android 6.0+ seems to use symlink)
- char data_current_dir_name[2048];
- getcwd(data_current_dir_name, 2048);
-
- //cache by parsing utf8
- data_dir_cache.parse_utf8(data_current_dir_name);
-
- //restore original dir so we don't mess things up
- chdir(real_current_dir_name);
-
+ data_dir_cache = _remove_symlink(data_dir);
return data_dir_cache;
}
+ return ".";
+}
+String OS_Android::get_external_data_dir() const {
+ String data_dir = godot_io_java->get_external_data_dir();
+ if (data_dir != "") {
+ data_dir = _remove_symlink(data_dir);
+ return data_dir;
+ }
return ".";
}
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index dd14b69cf9..1e89e9211d 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -31,7 +31,6 @@
#ifndef OS_ANDROID_H
#define OS_ANDROID_H
-#include "audio_driver_jandroid.h"
#include "audio_driver_opensl.h"
#include "core/os/main_loop.h"
#include "drivers/unix/os_unix.h"
@@ -59,7 +58,6 @@ private:
mutable String data_dir_cache;
- //AudioDriverAndroid audio_driver_android;
AudioDriverOpenSL audio_driver_android;
MainLoop *main_loop;
@@ -111,6 +109,7 @@ public:
virtual Error shell_open(String p_uri) override;
virtual String get_user_data_dir() const override;
+ virtual String get_external_data_dir() const override;
virtual String get_resource_dir() const override;
virtual String get_locale() const override;
virtual String get_model_name() const override;
diff --git a/platform/android/plugin/godot_plugin_config.h b/platform/android/plugin/godot_plugin_config.h
index 173ac115a2..6b708548ae 100644
--- a/platform/android/plugin/godot_plugin_config.h
+++ b/platform/android/plugin/godot_plugin_config.h
@@ -37,8 +37,8 @@
/*
The `config` section and fields are required and defined as follow:
-- **name**: name of the plugin
-- **binary_type**: can be either `local` or `remote`. The type affects the **binary** field
+- **name**: name of the plugin.
+- **binary_type**: can be either `local` or `remote`. The type affects the **binary** field.
- **binary**:
- if **binary_type** is `local`, then this should be the filename of the plugin `aar` file in the `res://android/plugins` directory (e.g: `MyPlugin.aar`).
- if **binary_type** is `remote`, then this should be a declaration for a remote gradle binary (e.g: "org.godot.example:my-plugin:0.0.0").
@@ -102,7 +102,7 @@ struct PluginConfigAndroid {
static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) {
String absolute_path;
if (!dependency_path.is_empty()) {
- if (dependency_path.is_abs_path()) {
+ if (dependency_path.is_absolute_path()) {
absolute_path = ProjectSettings::get_singleton()->globalize_path(dependency_path);
} else {
absolute_path = plugin_config_dir.plus_file(dependency_path);
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index c585c2afbe..e2df573b09 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -31,11 +31,11 @@
#include "export.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/image_loader.h"
#include "core/io/marshalls.h"
#include "core/io/resource_saver.h"
#include "core/io/zip_io.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/templates/safe_refcount.h"
#include "core/version.h"
@@ -353,6 +353,8 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_release", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2));
+
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
@@ -378,11 +380,6 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_left"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_right"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait_upside_down"), true));
-
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "icons/generate_missing"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with retina display
@@ -453,6 +450,8 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
} else if (lines[i].find("$team_id") != -1) {
strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
+ } else if (lines[i].find("$default_build_config") != -1) {
+ strnew += lines[i].replace("$default_build_config", p_debug ? "Debug" : "Release") + "\n";
} else if (lines[i].find("$export_method") != -1) {
int export_method = p_preset->get(p_debug ? "application/export_method_debug" : "application/export_method_release");
strnew += lines[i].replace("$export_method", export_method_string[export_method]) + "\n";
@@ -473,6 +472,20 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$godot_archs", p_config.architectures) + "\n";
} else if (lines[i].find("$linker_flags") != -1) {
strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n";
+ } else if (lines[i].find("$targeted_device_family") != -1) {
+ String xcode_value;
+ switch ((int)p_preset->get("application/targeted_device_family")) {
+ case 0: // iPhone
+ xcode_value = "1";
+ break;
+ case 1: // iPad
+ xcode_value = "2";
+ break;
+ case 2: // iPhone & iPad
+ xcode_value = "1,2";
+ break;
+ }
+ strnew += lines[i].replace("$targeted_device_family", xcode_value) + "\n";
} else if (lines[i].find("$cpp_code") != -1) {
strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n";
} else if (lines[i].find("$docs_in_place") != -1) {
@@ -501,18 +514,39 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$required_device_capabilities", capabilities);
} else if (lines[i].find("$interface_orientations") != -1) {
String orientations;
+ const DisplayServer::ScreenOrientation screen_orientation =
+ DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation")));
- if ((bool)p_preset->get("orientation/portrait")) {
- orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
- }
- if ((bool)p_preset->get("orientation/landscape_left")) {
- orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
- }
- if ((bool)p_preset->get("orientation/landscape_right")) {
- orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
- }
- if ((bool)p_preset->get("orientation/portrait_upside_down")) {
- orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ switch (screen_orientation) {
+ case DisplayServer::SCREEN_LANDSCAPE:
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ break;
+ case DisplayServer::SCREEN_PORTRAIT:
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ break;
+ case DisplayServer::SCREEN_REVERSE_LANDSCAPE:
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ break;
+ case DisplayServer::SCREEN_REVERSE_PORTRAIT:
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR_LANDSCAPE:
+ // Allow both landscape orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR_PORTRAIT:
+ // Allow both portrait orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR:
+ // Allow all screen orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
}
strnew += lines[i].replace("$interface_orientations", orientations);
diff --git a/platform/iphone/godot_app_delegate.m b/platform/iphone/godot_app_delegate.m
index 3ce9bffc79..6c433c5c3c 100644
--- a/platform/iphone/godot_app_delegate.m
+++ b/platform/iphone/godot_app_delegate.m
@@ -56,7 +56,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
[services addObject:service];
}
-// UIApplicationDelegate documantation can be found here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate
+// UIApplicationDelegate documentation can be found here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate
// MARK: Window
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index 458834ce3a..1f08901082 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -33,9 +33,9 @@
#include "os_iphone.h"
#import "app_delegate.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_pack.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "display_server_iphone.h"
#include "drivers/unix/syslog_logger.h"
#import "godot_view.h"
diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h
index e2546e733c..4d0c67bfff 100644
--- a/platform/iphone/plugin/godot_plugin_config.h
+++ b/platform/iphone/plugin/godot_plugin_config.h
@@ -104,7 +104,7 @@ static inline String resolve_local_dependency_path(String plugin_config_dir, Str
return absolute_path;
}
- if (dependency_path.is_abs_path()) {
+ if (dependency_path.is_absolute_path()) {
return dependency_path;
}
@@ -121,7 +121,7 @@ static inline String resolve_system_dependency_path(String dependency_path) {
return absolute_path;
}
- if (dependency_path.is_abs_path()) {
+ if (dependency_path.is_absolute_path()) {
return dependency_path;
}
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index a760e36982..62a8660ae4 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -6,7 +6,7 @@ javascript_files = [
"audio_driver_javascript.cpp",
"display_server_javascript.cpp",
"http_client_javascript.cpp",
- "javascript_eval.cpp",
+ "javascript_singleton.cpp",
"javascript_main.cpp",
"os_javascript.cpp",
"api/javascript_tools_editor_plugin.cpp",
@@ -23,10 +23,8 @@ sys_env.AddJSLibraries(
]
)
-if env["tools"]:
- sys_env.AddJSLibraries(["js/libs/library_godot_editor_tools.js"])
if env["javascript_eval"]:
- sys_env.AddJSLibraries(["js/libs/library_godot_eval.js"])
+ sys_env.AddJSLibraries(["js/libs/library_godot_javascript_singleton.js"])
for lib in sys_env["JS_LIBS"]:
sys_env.Append(LINKFLAGS=["--js-library", lib])
@@ -47,6 +45,7 @@ if env["gdnative_enabled"]:
sys_env.Append(LINKFLAGS=["-s", "MAIN_MODULE=1"])
sys_env.Append(CCFLAGS=["-s", "EXPORT_ALL=1"])
sys_env.Append(LINKFLAGS=["-s", "EXPORT_ALL=1"])
+ sys_env.Append(LINKFLAGS=["-s", "WARN_ON_UNDEFINED_SYMBOLS=0"])
# Force exporting the standard library (printf, malloc, etc.)
sys_env["ENV"]["EMCC_FORCE_STDLIBS"] = "libc,libc++,libc++abi"
# The main emscripten runtime, with exported standard libraries.
diff --git a/platform/javascript/api/api.cpp b/platform/javascript/api/api.cpp
index 2f7bde065f..5ad2bf56cf 100644
--- a/platform/javascript/api/api.cpp
+++ b/platform/javascript/api/api.cpp
@@ -30,13 +30,14 @@
#include "api.h"
#include "core/config/engine.h"
-#include "javascript_eval.h"
+#include "javascript_singleton.h"
#include "javascript_tools_editor_plugin.h"
static JavaScript *javascript_eval;
void register_javascript_api() {
JavaScriptToolsEditorPlugin::initialize();
+ ClassDB::register_virtual_class<JavaScriptObject>();
ClassDB::register_virtual_class<JavaScript>();
javascript_eval = memnew(JavaScript);
Engine::get_singleton()->add_singleton(Engine::Singleton("JavaScript", javascript_eval));
@@ -61,10 +62,46 @@ JavaScript::~JavaScript() {}
void JavaScript::_bind_methods() {
ClassDB::bind_method(D_METHOD("eval", "code", "use_global_execution_context"), &JavaScript::eval, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_interface", "interface"), &JavaScript::get_interface);
+ ClassDB::bind_method(D_METHOD("create_callback", "callable"), &JavaScript::create_callback);
+ {
+ MethodInfo mi;
+ mi.name = "create_object";
+ mi.arguments.push_back(PropertyInfo(Variant::STRING, "object"));
+ ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "create_object", &JavaScript::_create_object_bind, mi);
+ }
+ ClassDB::bind_method(D_METHOD("download_buffer", "buffer", "name", "mime"), &JavaScript::download_buffer, DEFVAL("application/octet-stream"));
}
#if !defined(JAVASCRIPT_ENABLED) || !defined(JAVASCRIPT_EVAL_ENABLED)
Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
return Variant();
}
+
+Ref<JavaScriptObject> JavaScript::get_interface(const String &p_interface) {
+ return Ref<JavaScriptObject>();
+}
+
+Ref<JavaScriptObject> JavaScript::create_callback(const Callable &p_callable) {
+ return Ref<JavaScriptObject>();
+}
+
+Variant JavaScript::_create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ if (p_argcount < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 0;
+ return Ref<JavaScriptObject>();
+ }
+ if (p_args[0]->get_type() != Variant::STRING) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::STRING;
+ return Ref<JavaScriptObject>();
+ }
+ return Ref<JavaScriptObject>();
+}
+#endif
+#if !defined(JAVASCRIPT_ENABLED)
+void JavaScript::download_buffer(Vector<uint8_t> p_arr, const String &p_name, const String &p_mime) {
+}
#endif
diff --git a/platform/javascript/api/javascript_eval.h b/platform/javascript/api/javascript_eval.h
deleted file mode 100644
index 24f7648ed9..0000000000
--- a/platform/javascript/api/javascript_eval.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*************************************************************************/
-/* javascript_eval.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef JAVASCRIPT_EVAL_H
-#define JAVASCRIPT_EVAL_H
-
-#include "core/object/class_db.h"
-
-class JavaScript : public Object {
-private:
- GDCLASS(JavaScript, Object);
-
- static JavaScript *singleton;
-
-protected:
- static void _bind_methods();
-
-public:
- Variant eval(const String &p_code, bool p_use_global_exec_context = false);
-
- static JavaScript *get_singleton();
- JavaScript();
- ~JavaScript();
-};
-
-#endif // JAVASCRIPT_EVAL_H
diff --git a/platform/javascript/api/javascript_singleton.h b/platform/javascript/api/javascript_singleton.h
new file mode 100644
index 0000000000..9d7a392278
--- /dev/null
+++ b/platform/javascript/api/javascript_singleton.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* javascript_singleton.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef JAVASCRIPT_SINGLETON_H
+#define JAVASCRIPT_SINGLETON_H
+
+#include "core/object/class_db.h"
+#include "core/object/ref_counted.h"
+
+class JavaScriptObject : public RefCounted {
+private:
+ GDCLASS(JavaScriptObject, RefCounted);
+
+protected:
+ virtual bool _set(const StringName &p_name, const Variant &p_value) { return false; }
+ virtual bool _get(const StringName &p_name, Variant &r_ret) const { return false; }
+ virtual void _get_property_list(List<PropertyInfo> *p_list) const {}
+};
+
+class JavaScript : public Object {
+private:
+ GDCLASS(JavaScript, Object);
+
+ static JavaScript *singleton;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Variant eval(const String &p_code, bool p_use_global_exec_context = false);
+ Ref<JavaScriptObject> get_interface(const String &p_interface);
+ Ref<JavaScriptObject> create_callback(const Callable &p_callable);
+ Variant _create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ void download_buffer(Vector<uint8_t> p_arr, const String &p_name, const String &p_mime = "application/octet-stream");
+
+ static JavaScript *get_singleton();
+ JavaScript();
+ ~JavaScript();
+};
+
+#endif // JAVASCRIPT_SINGLETON_H
diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp
index 7a2c2b2335..54f541f607 100644
--- a/platform/javascript/api/javascript_tools_editor_plugin.cpp
+++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp
@@ -33,15 +33,15 @@
#include "core/config/engine.h"
#include "core/config/project_settings.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "editor/editor_node.h"
#include <emscripten/emscripten.h>
// JavaScript functions defined in library_godot_editor_tools.js
extern "C" {
-extern void godot_js_editor_download_file(const char *p_path, const char *p_name, const char *p_mime);
+extern void godot_js_os_download_buffer(const uint8_t *p_buf, int p_buf_size, const char *p_name, const char *p_mime);
}
static void _javascript_editor_init_callback() {
@@ -69,7 +69,12 @@ void JavaScriptToolsEditorPlugin::_download_zip(Variant p_v) {
String base_path = resource_path.substr(0, resource_path.rfind("/")) + "/";
_zip_recursive(resource_path, base_path, zip);
zipClose(zip, nullptr);
- godot_js_editor_download_file("/tmp/project.zip", "project.zip", "application/zip");
+ FileAccess *f = FileAccess::open("/tmp/project.zip", FileAccess::READ);
+ ERR_FAIL_COND_MSG(!f, "Unable to create zip file");
+ Vector<uint8_t> buf;
+ buf.resize(f->get_length());
+ f->get_buffer(buf.ptrw(), buf.size());
+ godot_js_os_download_buffer(buf.ptr(), buf.size(), "project.zip", "application/zip");
}
void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, zipFile p_zip) {
@@ -79,7 +84,7 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z
return;
}
Vector<uint8_t> data;
- int len = f->get_len();
+ uint64_t len = f->get_length();
data.resize(len);
f->get_buffer(data.ptrw(), len);
f->close();
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index d01e8a8bd4..da6adc4cd8 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -53,6 +53,7 @@ def get_flags():
# in this platform. For the available networking methods, the browser
# manages TLS.
("module_mbedtls_enabled", False),
+ ("vulkan", False),
]
diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp
index 736a8a9a34..1cc05a2e19 100644
--- a/platform/javascript/display_server_javascript.cpp
+++ b/platform/javascript/display_server_javascript.cpp
@@ -30,8 +30,8 @@
#include "platform/javascript/display_server_javascript.h"
-#include "drivers/dummy/rasterizer_dummy.h"
#include "platform/javascript/os_javascript.h"
+#include "servers/rendering/rasterizer_dummy.h"
#include <emscripten.h>
#include <png.h>
@@ -120,10 +120,10 @@ void DisplayServerJavaScript::request_quit_callback() {
template <typename T>
void DisplayServerJavaScript::dom2godot_mod(T *emscripten_event_ptr, Ref<InputEventWithModifiers> godot_event) {
- godot_event->set_shift(emscripten_event_ptr->shiftKey);
- godot_event->set_alt(emscripten_event_ptr->altKey);
- godot_event->set_control(emscripten_event_ptr->ctrlKey);
- godot_event->set_metakey(emscripten_event_ptr->metaKey);
+ godot_event->set_shift_pressed(emscripten_event_ptr->shiftKey);
+ godot_event->set_alt_pressed(emscripten_event_ptr->altKey);
+ godot_event->set_ctrl_pressed(emscripten_event_ptr->ctrlKey);
+ godot_event->set_meta_pressed(emscripten_event_ptr->metaKey);
}
Ref<InputEventKey> DisplayServerJavaScript::setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) {
@@ -407,9 +407,10 @@ void DisplayServerJavaScript::cursor_set_custom_image(const RES &p_cursor, Curso
// Mouse mode
void DisplayServerJavaScript::mouse_set_mode(MouseMode p_mode) {
- ERR_FAIL_COND_MSG(p_mode == MOUSE_MODE_CONFINED, "MOUSE_MODE_CONFINED is not supported for the HTML5 platform.");
- if (p_mode == mouse_get_mode())
+ ERR_FAIL_COND_MSG(p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN, "MOUSE_MODE_CONFINED is not supported for the HTML5 platform.");
+ if (p_mode == mouse_get_mode()) {
return;
+ }
if (p_mode == MOUSE_MODE_VISIBLE) {
godot_js_display_cursor_set_visible(1);
@@ -455,10 +456,10 @@ EM_BOOL DisplayServerJavaScript::wheel_callback(int p_event_type, const Emscript
ev->set_position(input->get_mouse_position());
ev->set_global_position(ev->get_position());
- ev->set_shift(input->is_key_pressed(KEY_SHIFT));
- ev->set_alt(input->is_key_pressed(KEY_ALT));
- ev->set_control(input->is_key_pressed(KEY_CONTROL));
- ev->set_metakey(input->is_key_pressed(KEY_META));
+ ev->set_shift_pressed(input->is_key_pressed(KEY_SHIFT));
+ ev->set_alt_pressed(input->is_key_pressed(KEY_ALT));
+ ev->set_ctrl_pressed(input->is_key_pressed(KEY_CTRL));
+ ev->set_meta_pressed(input->is_key_pressed(KEY_META));
if (p_event->deltaY < 0)
ev->set_button_index(MOUSE_BUTTON_WHEEL_UP);
@@ -536,7 +537,7 @@ bool DisplayServerJavaScript::screen_is_touchscreen(int p_screen) const {
return godot_js_display_touchscreen_is_available();
}
-// Virtual Keybaord
+// Virtual Keyboard
void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_cursor) {
DisplayServerJavaScript *ds = DisplayServerJavaScript::get_singleton();
if (!ds || ds->input_text_callback.is_null()) {
diff --git a/platform/javascript/dom_keys.inc b/platform/javascript/dom_keys.inc
index 7902efafe0..69340ff58c 100644
--- a/platform/javascript/dom_keys.inc
+++ b/platform/javascript/dom_keys.inc
@@ -159,8 +159,8 @@ int dom_code2godot_scancode(EM_UTF8 const p_code[32], EM_UTF8 const p_key[32], b
DOM2GODOT("Backspace", BACKSPACE);
DOM2GODOT("CapsLock", CAPSLOCK);
DOM2GODOT("ContextMenu", MENU);
- DOM2GODOT("ControlLeft", CONTROL);
- DOM2GODOT("ControlRight", CONTROL);
+ DOM2GODOT("ControlLeft", CTRL);
+ DOM2GODOT("ControlRight", CTRL);
DOM2GODOT("Enter", ENTER);
DOM2GODOT("MetaLeft", SUPER_L);
DOM2GODOT("MetaRight", SUPER_R);
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index 951d86d09e..7e49feee61 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -39,7 +39,7 @@
#include "platform/javascript/logo.gen.h"
#include "platform/javascript/run_icon.gen.h"
-class EditorHTTPServer : public Reference {
+class EditorHTTPServer : public RefCounted {
private:
Ref<TCPServer> server;
Map<String, String> mimes;
@@ -63,7 +63,7 @@ private:
}
void _set_internal_certs(Ref<Crypto> p_crypto) {
- const String cache_path = EditorSettings::get_singleton()->get_cache_dir();
+ const String cache_path = EditorPaths::get_singleton()->get_cache_dir();
const String key_path = cache_path.plus_file("html5_server.key");
const String crt_path = cache_path.plus_file("html5_server.crt");
bool regen = !FileAccess::exists(key_path) || !FileAccess::exists(crt_path);
@@ -138,7 +138,7 @@ public:
const String req_file = req[1].get_file();
const String req_ext = req[1].get_extension();
- const String cache_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("web");
+ const String cache_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("web");
const String filepath = cache_path.plus_file(req_file);
if (!mimes.has(req_ext) || !FileAccess::exists(filepath)) {
@@ -170,8 +170,8 @@ public:
while (true) {
uint8_t bytes[4096];
- int read = f->get_buffer(bytes, 4096);
- if (read < 1) {
+ uint64_t read = f->get_buffer(bytes, 4096);
+ if (read == 0) {
break;
}
err = peer->put_data(bytes, read);
@@ -547,7 +547,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
EditorNode::get_singleton()->show_warning(TTR("Could not read file:") + "\n" + sw_path);
return ERR_FILE_CANT_READ;
}
- sw.resize(f->get_len());
+ sw.resize(f->get_length());
f->get_buffer(sw.ptrw(), sw.size());
memdelete(f);
f = nullptr;
@@ -651,7 +651,7 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/experimental_virtual_keyboard"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "progressive_web_app/enabled"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/offline_page", PROPERTY_HINT_FILE, "*.html"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "progressive_web_app/display", PROPERTY_HINT_ENUM, "Fullscreen,Standalone,Minimal Ui,Browser"), 1));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "progressive_web_app/display", PROPERTY_HINT_ENUM, "Fullscreen,Standalone,Minimal UI,Browser"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "progressive_web_app/orientation", PROPERTY_HINT_ENUM, "Any,Landscape,Portrait"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_144x144", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg,*.svgz"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_180x180", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg,*.svgz"), ""));
@@ -781,13 +781,13 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
FileAccess *f = nullptr;
f = FileAccess::open(pck_path, FileAccess::READ);
if (f) {
- file_sizes[pck_path.get_file()] = (uint64_t)f->get_len();
+ file_sizes[pck_path.get_file()] = (uint64_t)f->get_length();
memdelete(f);
f = nullptr;
}
f = FileAccess::open(base_path + ".wasm", FileAccess::READ);
if (f) {
- file_sizes[base_name + ".wasm"] = (uint64_t)f->get_len();
+ file_sizes[base_name + ".wasm"] = (uint64_t)f->get_length();
memdelete(f);
f = nullptr;
}
@@ -800,7 +800,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
EditorNode::get_singleton()->show_warning(TTR("Could not read HTML shell:") + "\n" + html_path);
return ERR_FILE_CANT_READ;
}
- html.resize(f->get_len());
+ html.resize(f->get_length());
f->get_buffer(html.ptrw(), html.size());
memdelete(f);
f = nullptr;
@@ -888,7 +888,7 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese
return OK;
}
- const String dest = EditorSettings::get_singleton()->get_cache_dir().plus_file("web");
+ const String dest = EditorPaths::get_singleton()->get_cache_dir().plus_file("web");
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (!da->dir_exists(dest)) {
Error err = da->make_dir_recursive(dest);
diff --git a/platform/javascript/godot_js.h b/platform/javascript/godot_js.h
index 8927a83cb3..d332af2c31 100644
--- a/platform/javascript/godot_js.h
+++ b/platform/javascript/godot_js.h
@@ -84,7 +84,7 @@ extern void godot_js_display_cursor_set_custom_shape(const char *p_shape, const
extern void godot_js_display_cursor_set_visible(int p_visible);
// Display gamepad
-extern char *godot_js_display_gamepad_cb(void (*p_on_change)(int p_index, int p_connected, const char *p_id, const char *p_guid));
+extern void godot_js_display_gamepad_cb(void (*p_on_change)(int p_index, int p_connected, const char *p_id, const char *p_guid));
extern int godot_js_display_gamepad_sample();
extern int godot_js_display_gamepad_sample_count();
extern int godot_js_display_gamepad_sample_get(int p_idx, float r_btns[16], int32_t *r_btns_num, float r_axes[10], int32_t *r_axes_num, int32_t *r_standard);
diff --git a/platform/javascript/javascript_eval.cpp b/platform/javascript/javascript_eval.cpp
deleted file mode 100644
index cb19dd20d4..0000000000
--- a/platform/javascript/javascript_eval.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*************************************************************************/
-/* javascript_eval.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef JAVASCRIPT_EVAL_ENABLED
-
-#include "api/javascript_eval.h"
-#include "emscripten.h"
-
-extern "C" {
-union js_eval_ret {
- uint32_t b;
- double d;
- char *s;
-};
-
-extern int godot_js_eval(const char *p_js, int p_use_global_ctx, union js_eval_ret *p_union_ptr, void *p_byte_arr, void *p_byte_arr_write, void *(*p_callback)(void *p_ptr, void *p_ptr2, int p_len));
-}
-
-void *resize_PackedByteArray_and_open_write(void *p_arr, void *r_write, int p_len) {
- PackedByteArray *arr = (PackedByteArray *)p_arr;
- VectorWriteProxy<uint8_t> *write = (VectorWriteProxy<uint8_t> *)r_write;
- arr->resize(p_len);
- *write = arr->write;
- return arr->ptrw();
-}
-
-Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
- union js_eval_ret js_data;
- PackedByteArray arr;
- VectorWriteProxy<uint8_t> arr_write;
-
- Variant::Type return_type = static_cast<Variant::Type>(godot_js_eval(p_code.utf8().get_data(), p_use_global_exec_context, &js_data, &arr, &arr_write, resize_PackedByteArray_and_open_write));
-
- switch (return_type) {
- case Variant::BOOL:
- return js_data.b;
- case Variant::FLOAT:
- return js_data.d;
- case Variant::STRING: {
- String str = String::utf8(js_data.s);
- free(js_data.s); // Must free the string allocated in JS.
- return str;
- }
- case Variant::PACKED_BYTE_ARRAY:
- arr_write = VectorWriteProxy<uint8_t>();
- return arr;
- default:
- return Variant();
- }
-}
-
-#endif // JAVASCRIPT_EVAL_ENABLED
diff --git a/platform/javascript/javascript_singleton.cpp b/platform/javascript/javascript_singleton.cpp
new file mode 100644
index 0000000000..c441ed0517
--- /dev/null
+++ b/platform/javascript/javascript_singleton.cpp
@@ -0,0 +1,346 @@
+/*************************************************************************/
+/* javascript_singleton.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "api/javascript_singleton.h"
+#include "emscripten.h"
+
+extern "C" {
+extern void godot_js_os_download_buffer(const uint8_t *p_buf, int p_buf_size, const char *p_name, const char *p_mime);
+}
+
+#ifdef JAVASCRIPT_EVAL_ENABLED
+
+extern "C" {
+typedef union {
+ int64_t i;
+ double r;
+ void *p;
+} godot_js_wrapper_ex;
+
+typedef int (*GodotJSWrapperVariant2JSCallback)(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock);
+typedef void (*GodotJSWrapperFreeLockCallback)(void **p_lock, int p_type);
+extern int godot_js_wrapper_interface_get(const char *p_name);
+extern int godot_js_wrapper_object_call(int p_id, const char *p_method, void **p_args, int p_argc, GodotJSWrapperVariant2JSCallback p_variant2js_callback, godot_js_wrapper_ex *p_cb_rval, void **p_lock, GodotJSWrapperFreeLockCallback p_lock_callback);
+extern int godot_js_wrapper_object_get(int p_id, godot_js_wrapper_ex *p_val, const char *p_prop);
+extern int godot_js_wrapper_object_getvar(int p_id, int p_type, godot_js_wrapper_ex *p_val);
+extern int godot_js_wrapper_object_setvar(int p_id, int p_key_type, godot_js_wrapper_ex *p_key_ex, int p_val_type, godot_js_wrapper_ex *p_val_ex);
+extern void godot_js_wrapper_object_set(int p_id, const char *p_name, int p_type, godot_js_wrapper_ex *p_val);
+extern void godot_js_wrapper_object_unref(int p_id);
+extern int godot_js_wrapper_create_cb(void *p_ref, void (*p_callback)(void *p_ref, int p_arg_id, int p_argc));
+extern int godot_js_wrapper_create_object(const char *p_method, void **p_args, int p_argc, GodotJSWrapperVariant2JSCallback p_variant2js_callback, godot_js_wrapper_ex *p_cb_rval, void **p_lock, GodotJSWrapperFreeLockCallback p_lock_callback);
+};
+
+class JavaScriptObjectImpl : public JavaScriptObject {
+private:
+ friend class JavaScript;
+
+ int _js_id = 0;
+ Callable _callable;
+
+ static int _variant2js(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock);
+ static void _free_lock(void **p_lock, int p_type);
+ static Variant _js2variant(int p_type, godot_js_wrapper_ex *p_val);
+ static void *_alloc_variants(int p_size);
+ static void _callback(void *p_ref, int p_arg_id, int p_argc);
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value) override;
+ bool _get(const StringName &p_name, Variant &r_ret) const override;
+ void _get_property_list(List<PropertyInfo> *p_list) const override;
+
+public:
+ Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const override;
+ void setvar(const Variant &p_key, const Variant &p_value, bool *r_valid = nullptr) override;
+ Variant call(const StringName &p_method, const Variant **p_args, int p_argc, Callable::CallError &r_error) override;
+ JavaScriptObjectImpl() {}
+ JavaScriptObjectImpl(int p_id) { _js_id = p_id; }
+ ~JavaScriptObjectImpl() {
+ if (_js_id) {
+ godot_js_wrapper_object_unref(_js_id);
+ }
+ }
+};
+
+bool JavaScriptObjectImpl::_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND_V_MSG(!_js_id, false, "Invalid JS instance");
+ const String name = p_name;
+ godot_js_wrapper_ex exchange;
+ void *lock = nullptr;
+ const Variant *v = &p_value;
+ int type = _variant2js((const void **)&v, 0, &exchange, &lock);
+ godot_js_wrapper_object_set(_js_id, name.utf8().get_data(), type, &exchange);
+ if (lock) {
+ _free_lock(&lock, type);
+ }
+ return true;
+}
+
+bool JavaScriptObjectImpl::_get(const StringName &p_name, Variant &r_ret) const {
+ ERR_FAIL_COND_V_MSG(!_js_id, false, "Invalid JS instance");
+ const String name = p_name;
+ godot_js_wrapper_ex exchange;
+ int type = godot_js_wrapper_object_get(_js_id, &exchange, name.utf8().get_data());
+ r_ret = _js2variant(type, &exchange);
+ return true;
+}
+
+Variant JavaScriptObjectImpl::getvar(const Variant &p_key, bool *r_valid) const {
+ if (r_valid) {
+ *r_valid = false;
+ }
+ godot_js_wrapper_ex exchange;
+ void *lock = nullptr;
+ const Variant *v = &p_key;
+ int prop_type = _variant2js((const void **)&v, 0, &exchange, &lock);
+ int type = godot_js_wrapper_object_getvar(_js_id, prop_type, &exchange);
+ if (lock) {
+ _free_lock(&lock, prop_type);
+ }
+ if (type < 0) {
+ return Variant();
+ }
+ if (r_valid) {
+ *r_valid = true;
+ }
+ return _js2variant(type, &exchange);
+}
+
+void JavaScriptObjectImpl::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) {
+ if (r_valid) {
+ *r_valid = false;
+ }
+ godot_js_wrapper_ex kex, vex;
+ void *klock = nullptr;
+ void *vlock = nullptr;
+ const Variant *kv = &p_key;
+ const Variant *vv = &p_value;
+ int ktype = _variant2js((const void **)&kv, 0, &kex, &klock);
+ int vtype = _variant2js((const void **)&vv, 0, &vex, &vlock);
+ int ret = godot_js_wrapper_object_setvar(_js_id, ktype, &kex, vtype, &vex);
+ if (klock) {
+ _free_lock(&klock, ktype);
+ }
+ if (vlock) {
+ _free_lock(&vlock, vtype);
+ }
+ if (ret == 0 && r_valid) {
+ *r_valid = true;
+ }
+}
+
+void JavaScriptObjectImpl::_get_property_list(List<PropertyInfo> *p_list) const {
+}
+
+void JavaScriptObjectImpl::_free_lock(void **p_lock, int p_type) {
+ ERR_FAIL_COND_MSG(*p_lock == nullptr, "No lock to free!");
+ const Variant::Type type = (Variant::Type)p_type;
+ switch (type) {
+ case Variant::STRING: {
+ CharString *cs = (CharString *)(*p_lock);
+ memdelete(cs);
+ *p_lock = nullptr;
+ } break;
+ default:
+ ERR_FAIL_MSG("Unknown lock type to free. Likely a bug.");
+ }
+}
+
+Variant JavaScriptObjectImpl::_js2variant(int p_type, godot_js_wrapper_ex *p_val) {
+ Variant::Type type = (Variant::Type)p_type;
+ switch (type) {
+ case Variant::BOOL:
+ return Variant((bool)p_val->i);
+ case Variant::INT:
+ return p_val->i;
+ case Variant::FLOAT:
+ return p_val->r;
+ case Variant::STRING: {
+ String out((const char *)p_val->p);
+ free(p_val->p);
+ return out;
+ }
+ case Variant::OBJECT: {
+ return memnew(JavaScriptObjectImpl(p_val->i));
+ }
+ default:
+ return Variant();
+ }
+}
+
+int JavaScriptObjectImpl::_variant2js(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock) {
+ const Variant **args = (const Variant **)p_args;
+ const Variant *v = args[p_pos];
+ Variant::Type type = v->get_type();
+ switch (type) {
+ case Variant::BOOL:
+ r_val->i = v->operator bool() ? 1 : 0;
+ break;
+ case Variant::INT: {
+ const int64_t tmp = v->operator int64_t();
+ if (tmp >= 1 << 31) {
+ r_val->r = (double)tmp;
+ return Variant::FLOAT;
+ }
+ r_val->i = v->operator int64_t();
+ } break;
+ case Variant::FLOAT:
+ r_val->r = v->operator real_t();
+ break;
+ case Variant::STRING: {
+ CharString *cs = memnew(CharString(v->operator String().utf8()));
+ r_val->p = (void *)cs->get_data();
+ *p_lock = (void *)cs;
+ } break;
+ case Variant::OBJECT: {
+ JavaScriptObject *js_obj = Object::cast_to<JavaScriptObject>(v->operator Object *());
+ r_val->i = js_obj != nullptr ? ((JavaScriptObjectImpl *)js_obj)->_js_id : 0;
+ } break;
+ default:
+ break;
+ }
+ return type;
+}
+
+Variant JavaScriptObjectImpl::call(const StringName &p_method, const Variant **p_args, int p_argc, Callable::CallError &r_error) {
+ godot_js_wrapper_ex exchange;
+ const String method = p_method;
+ void *lock = nullptr;
+ const int type = godot_js_wrapper_object_call(_js_id, method.utf8().get_data(), (void **)p_args, p_argc, &_variant2js, &exchange, &lock, &_free_lock);
+ r_error.error = Callable::CallError::CALL_OK;
+ if (type < 0) {
+ r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ return Variant();
+ }
+ return _js2variant(type, &exchange);
+}
+
+void JavaScriptObjectImpl::_callback(void *p_ref, int p_args_id, int p_argc) {
+ const JavaScriptObjectImpl *obj = (JavaScriptObjectImpl *)p_ref;
+ ERR_FAIL_COND_MSG(obj->_callable.is_null(), "JavaScript callback failed.");
+ Vector<const Variant *> argp;
+ Array arg_arr;
+ for (int i = 0; i < p_argc; i++) {
+ godot_js_wrapper_ex exchange;
+ exchange.i = i;
+ int type = godot_js_wrapper_object_getvar(p_args_id, Variant::INT, &exchange);
+ arg_arr.push_back(_js2variant(type, &exchange));
+ }
+ Variant arg = arg_arr;
+ const Variant *argv[1] = { &arg };
+ Callable::CallError err;
+ Variant ret;
+ obj->_callable.call(argv, 1, ret, err);
+}
+
+Ref<JavaScriptObject> JavaScript::create_callback(const Callable &p_callable) {
+ Ref<JavaScriptObjectImpl> out = memnew(JavaScriptObjectImpl);
+ out->_callable = p_callable;
+ out->_js_id = godot_js_wrapper_create_cb(out.ptr(), JavaScriptObjectImpl::_callback);
+ return out;
+}
+
+Ref<JavaScriptObject> JavaScript::get_interface(const String &p_interface) {
+ int js_id = godot_js_wrapper_interface_get(p_interface.utf8().get_data());
+ ERR_FAIL_COND_V_MSG(!js_id, Ref<JavaScriptObject>(), "No interface '" + p_interface + "' registered.");
+ return Ref<JavaScriptObject>(memnew(JavaScriptObjectImpl(js_id)));
+}
+
+Variant JavaScript::_create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ if (p_argcount < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 0;
+ return Ref<JavaScriptObject>();
+ }
+ if (p_args[0]->get_type() != Variant::STRING) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::STRING;
+ return Ref<JavaScriptObject>();
+ }
+ godot_js_wrapper_ex exchange;
+ const String object = *p_args[0];
+ void *lock = nullptr;
+ const Variant **args = p_argcount > 1 ? &p_args[1] : nullptr;
+ const int type = godot_js_wrapper_create_object(object.utf8().get_data(), (void **)args, p_argcount - 1, &JavaScriptObjectImpl::_variant2js, &exchange, &lock, &JavaScriptObjectImpl::_free_lock);
+ r_error.error = Callable::CallError::CALL_OK;
+ if (type < 0) {
+ r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ return Ref<JavaScriptObject>();
+ }
+ return JavaScriptObjectImpl::_js2variant(type, &exchange);
+}
+
+extern "C" {
+union js_eval_ret {
+ uint32_t b;
+ double d;
+ char *s;
+};
+
+extern int godot_js_eval(const char *p_js, int p_use_global_ctx, union js_eval_ret *p_union_ptr, void *p_byte_arr, void *p_byte_arr_write, void *(*p_callback)(void *p_ptr, void *p_ptr2, int p_len));
+}
+
+void *resize_PackedByteArray_and_open_write(void *p_arr, void *r_write, int p_len) {
+ PackedByteArray *arr = (PackedByteArray *)p_arr;
+ VectorWriteProxy<uint8_t> *write = (VectorWriteProxy<uint8_t> *)r_write;
+ arr->resize(p_len);
+ *write = arr->write;
+ return arr->ptrw();
+}
+
+Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
+ union js_eval_ret js_data;
+ PackedByteArray arr;
+ VectorWriteProxy<uint8_t> arr_write;
+
+ Variant::Type return_type = static_cast<Variant::Type>(godot_js_eval(p_code.utf8().get_data(), p_use_global_exec_context, &js_data, &arr, &arr_write, resize_PackedByteArray_and_open_write));
+
+ switch (return_type) {
+ case Variant::BOOL:
+ return js_data.b;
+ case Variant::FLOAT:
+ return js_data.d;
+ case Variant::STRING: {
+ String str = String::utf8(js_data.s);
+ free(js_data.s); // Must free the string allocated in JS.
+ return str;
+ }
+ case Variant::PACKED_BYTE_ARRAY:
+ arr_write = VectorWriteProxy<uint8_t>();
+ return arr;
+ default:
+ return Variant();
+ }
+}
+#endif // JAVASCRIPT_EVAL_ENABLED
+
+void JavaScript::download_buffer(Vector<uint8_t> p_arr, const String &p_name, const String &p_mime) {
+ godot_js_os_download_buffer(p_arr.ptr(), p_arr.size(), p_name.utf8().get_data(), p_mime.utf8().get_data());
+}
diff --git a/platform/javascript/js/libs/library_godot_audio.js b/platform/javascript/js/libs/library_godot_audio.js
index ac4055516c..45c3a3fe2e 100644
--- a/platform/javascript/js/libs/library_godot_audio.js
+++ b/platform/javascript/js/libs/library_godot_audio.js
@@ -59,7 +59,7 @@ const GodotAudio = {
}
onstatechange(state);
};
- ctx.onstatechange(); // Immeditately notify state.
+ ctx.onstatechange(); // Immediately notify state.
// Update computed latency
GodotAudio.interval = setInterval(function () {
let computed_latency = 0;
diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js
index 91cab5eacc..affae90370 100644
--- a/platform/javascript/js/libs/library_godot_display.js
+++ b/platform/javascript/js/libs/library_godot_display.js
@@ -683,7 +683,7 @@ const GodotDisplay = {
return GodotDisplayScreen.exitFullscreen();
},
- godot_js_display_desired_size_set__sig: 'v',
+ godot_js_display_desired_size_set__sig: 'vii',
godot_js_display_desired_size_set: function (width, height) {
GodotDisplayScreen.desired_size = [width, height];
GodotDisplayScreen.updateSize();
diff --git a/platform/javascript/js/libs/library_godot_editor_tools.js b/platform/javascript/js/libs/library_godot_editor_tools.js
deleted file mode 100644
index d7f1ad5ea1..0000000000
--- a/platform/javascript/js/libs/library_godot_editor_tools.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/*************************************************************************/
-/* library_godot_editor_tools.js */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-const GodotEditorTools = {
- godot_js_editor_download_file__deps: ['$FS'],
- godot_js_editor_download_file__sig: 'viii',
- godot_js_editor_download_file: function (p_path, p_name, p_mime) {
- const path = GodotRuntime.parseString(p_path);
- const name = GodotRuntime.parseString(p_name);
- const mime = GodotRuntime.parseString(p_mime);
- const size = FS.stat(path)['size'];
- const buf = new Uint8Array(size);
- const fd = FS.open(path, 'r');
- FS.read(fd, buf, 0, size);
- FS.close(fd);
- FS.unlink(path);
- const blob = new Blob([buf], { type: mime });
- const url = window.URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = name;
- a.style.display = 'none';
- document.body.appendChild(a);
- a.click();
- a.remove();
- window.URL.revokeObjectURL(url);
- },
-};
-
-mergeInto(LibraryManager.library, GodotEditorTools);
diff --git a/platform/javascript/js/libs/library_godot_eval.js b/platform/javascript/js/libs/library_godot_eval.js
deleted file mode 100644
index 9ab392b813..0000000000
--- a/platform/javascript/js/libs/library_godot_eval.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/*************************************************************************/
-/* library_godot_eval.js */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-const GodotEval = {
- godot_js_eval__deps: ['$GodotRuntime'],
- godot_js_eval__sig: 'iiiiiii',
- godot_js_eval: function (p_js, p_use_global_ctx, p_union_ptr, p_byte_arr, p_byte_arr_write, p_callback) {
- const js_code = GodotRuntime.parseString(p_js);
- let eval_ret = null;
- try {
- if (p_use_global_ctx) {
- // indirect eval call grants global execution context
- const global_eval = eval; // eslint-disable-line no-eval
- eval_ret = global_eval(js_code);
- } else {
- eval_ret = eval(js_code); // eslint-disable-line no-eval
- }
- } catch (e) {
- GodotRuntime.error(e);
- }
-
- switch (typeof eval_ret) {
- case 'boolean':
- GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'i32');
- return 1; // BOOL
-
- case 'number':
- GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'double');
- return 3; // REAL
-
- case 'string':
- GodotRuntime.setHeapValue(p_union_ptr, GodotRuntime.allocString(eval_ret), '*');
- return 4; // STRING
-
- case 'object':
- if (eval_ret === null) {
- break;
- }
-
- if (ArrayBuffer.isView(eval_ret) && !(eval_ret instanceof Uint8Array)) {
- eval_ret = new Uint8Array(eval_ret.buffer);
- } else if (eval_ret instanceof ArrayBuffer) {
- eval_ret = new Uint8Array(eval_ret);
- }
- if (eval_ret instanceof Uint8Array) {
- const func = GodotRuntime.get_func(p_callback);
- const bytes_ptr = func(p_byte_arr, p_byte_arr_write, eval_ret.length);
- HEAPU8.set(eval_ret, bytes_ptr);
- return 20; // POOL_BYTE_ARRAY
- }
- break;
-
- // no default
- }
- return 0; // NIL
- },
-};
-
-mergeInto(LibraryManager.library, GodotEval);
diff --git a/platform/javascript/js/libs/library_godot_fetch.js b/platform/javascript/js/libs/library_godot_fetch.js
index de5ae2b1ae..615f9de8b0 100644
--- a/platform/javascript/js/libs/library_godot_fetch.js
+++ b/platform/javascript/js/libs/library_godot_fetch.js
@@ -29,7 +29,7 @@
/*************************************************************************/
const GodotFetch = {
- $GodotFetch__deps: ['$GodotRuntime'],
+ $GodotFetch__deps: ['$IDHandler', '$GodotRuntime'],
$GodotFetch: {
onread: function (id, result) {
@@ -126,7 +126,7 @@ const GodotFetch = {
},
},
- godot_js_fetch_create__sig: 'iii',
+ godot_js_fetch_create__sig: 'iiiiiii',
godot_js_fetch_create: function (p_method, p_url, p_headers, p_headers_size, p_body, p_body_size) {
const method = GodotRuntime.parseString(p_method);
const url = GodotRuntime.parseString(p_url);
@@ -176,7 +176,7 @@ const GodotFetch = {
return obj.status;
},
- godot_js_fetch_read_headers__sig: 'iii',
+ godot_js_fetch_read_headers__sig: 'iiii',
godot_js_fetch_read_headers: function (p_id, p_parse_cb, p_ref) {
const obj = IDHandler.get(p_id);
if (!obj || !obj.response) {
@@ -193,7 +193,7 @@ const GodotFetch = {
return 0;
},
- godot_js_fetch_read_chunk__sig: 'ii',
+ godot_js_fetch_read_chunk__sig: 'iiii',
godot_js_fetch_read_chunk: function (p_id, p_buf, p_buf_size) {
const obj = IDHandler.get(p_id);
if (!obj || !obj.response) {
diff --git a/platform/javascript/js/libs/library_godot_javascript_singleton.js b/platform/javascript/js/libs/library_godot_javascript_singleton.js
new file mode 100644
index 0000000000..cb80273ca8
--- /dev/null
+++ b/platform/javascript/js/libs/library_godot_javascript_singleton.js
@@ -0,0 +1,333 @@
+/*************************************************************************/
+/* library_godot_eval.js */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+const GodotJSWrapper = {
+
+ $GodotJSWrapper__deps: ['$GodotRuntime', '$IDHandler'],
+ $GodotJSWrapper__postset: 'GodotJSWrapper.proxies = new Map();',
+ $GodotJSWrapper: {
+ proxies: null,
+
+ MyProxy: function (val) {
+ const id = IDHandler.add(this);
+ GodotJSWrapper.proxies.set(val, id);
+ let refs = 1;
+ this.ref = function () {
+ refs++;
+ };
+ this.unref = function () {
+ refs--;
+ if (refs === 0) {
+ IDHandler.remove(id);
+ GodotJSWrapper.proxies.delete(val);
+ }
+ };
+ this.get_val = function () {
+ return val;
+ };
+ this.get_id = function () {
+ return id;
+ };
+ },
+
+ get_proxied: function (val) {
+ const id = GodotJSWrapper.proxies.get(val);
+ if (id === undefined) {
+ const proxy = new GodotJSWrapper.MyProxy(val);
+ return proxy.get_id();
+ }
+ IDHandler.get(id).ref();
+ return id;
+ },
+
+ get_proxied_value: function (id) {
+ const proxy = IDHandler.get(id);
+ if (proxy === undefined) {
+ return undefined;
+ }
+ return proxy.get_val();
+ },
+
+ variant2js: function (type, val) {
+ switch (type) {
+ case 0:
+ return null;
+ case 1:
+ return !!GodotRuntime.getHeapValue(val, 'i64');
+ case 2:
+ return GodotRuntime.getHeapValue(val, 'i64');
+ case 3:
+ return GodotRuntime.getHeapValue(val, 'double');
+ case 4:
+ return GodotRuntime.parseString(GodotRuntime.getHeapValue(val, '*'));
+ case 21: // OBJECT
+ return GodotJSWrapper.get_proxied_value(GodotRuntime.getHeapValue(val, 'i64'));
+ default:
+ return undefined;
+ }
+ },
+
+ js2variant: function (p_val, p_exchange) {
+ if (p_val === undefined || p_val === null) {
+ return 0; // NIL
+ }
+ const type = typeof (p_val);
+ if (type === 'boolean') {
+ GodotRuntime.setHeapValue(p_exchange, p_val, 'i64');
+ return 1; // BOOL
+ } else if (type === 'number') {
+ if (Number.isInteger(p_val)) {
+ GodotRuntime.setHeapValue(p_exchange, p_val, 'i64');
+ return 2; // INT
+ }
+ GodotRuntime.setHeapValue(p_exchange, p_val, 'double');
+ return 3; // REAL
+ } else if (type === 'string') {
+ const c_str = GodotRuntime.allocString(p_val);
+ GodotRuntime.setHeapValue(p_exchange, c_str, '*');
+ return 4; // STRING
+ }
+ const id = GodotJSWrapper.get_proxied(p_val);
+ GodotRuntime.setHeapValue(p_exchange, id, 'i64');
+ return 21;
+ },
+ },
+
+ godot_js_wrapper_interface_get__sig: 'ii',
+ godot_js_wrapper_interface_get: function (p_name) {
+ const name = GodotRuntime.parseString(p_name);
+ if (typeof (window[name]) !== 'undefined') {
+ return GodotJSWrapper.get_proxied(window[name]);
+ }
+ return 0;
+ },
+
+ godot_js_wrapper_object_get__sig: 'iiii',
+ godot_js_wrapper_object_get: function (p_id, p_exchange, p_prop) {
+ const obj = GodotJSWrapper.get_proxied_value(p_id);
+ if (obj === undefined) {
+ return 0;
+ }
+ if (p_prop) {
+ const prop = GodotRuntime.parseString(p_prop);
+ try {
+ return GodotJSWrapper.js2variant(obj[prop], p_exchange);
+ } catch (e) {
+ GodotRuntime.error(`Error getting variable ${prop} on object`, obj);
+ return 0; // NIL
+ }
+ }
+ return GodotJSWrapper.js2variant(obj, p_exchange);
+ },
+
+ godot_js_wrapper_object_set__sig: 'viiii',
+ godot_js_wrapper_object_set: function (p_id, p_name, p_type, p_exchange) {
+ const obj = GodotJSWrapper.get_proxied_value(p_id);
+ if (obj === undefined) {
+ return;
+ }
+ const name = GodotRuntime.parseString(p_name);
+ try {
+ obj[name] = GodotJSWrapper.variant2js(p_type, p_exchange);
+ } catch (e) {
+ GodotRuntime.error(`Error setting variable ${name} on object`, obj);
+ }
+ },
+
+ godot_js_wrapper_object_call__sig: 'iiiiiiiii',
+ godot_js_wrapper_object_call: function (p_id, p_method, p_args, p_argc, p_convert_callback, p_exchange, p_lock, p_free_lock_callback) {
+ const obj = GodotJSWrapper.get_proxied_value(p_id);
+ if (obj === undefined) {
+ return -1;
+ }
+ const method = GodotRuntime.parseString(p_method);
+ const convert = GodotRuntime.get_func(p_convert_callback);
+ const freeLock = GodotRuntime.get_func(p_free_lock_callback);
+ const args = new Array(p_argc);
+ for (let i = 0; i < p_argc; i++) {
+ const type = convert(p_args, i, p_exchange, p_lock);
+ const lock = GodotRuntime.getHeapValue(p_lock, '*');
+ args[i] = GodotJSWrapper.variant2js(type, p_exchange);
+ if (lock) {
+ freeLock(p_lock, type);
+ }
+ }
+ try {
+ const res = obj[method](...args);
+ return GodotJSWrapper.js2variant(res, p_exchange);
+ } catch (e) {
+ GodotRuntime.error(`Error calling method ${method} on:`, obj, 'error:', e);
+ return -1;
+ }
+ },
+
+ godot_js_wrapper_object_unref__sig: 'vi',
+ godot_js_wrapper_object_unref: function (p_id) {
+ const proxy = IDHandler.get(p_id);
+ if (proxy !== undefined) {
+ proxy.unref();
+ }
+ },
+
+ godot_js_wrapper_create_cb__sig: 'iii',
+ godot_js_wrapper_create_cb: function (p_ref, p_func) {
+ const func = GodotRuntime.get_func(p_func);
+ let id = 0;
+ const cb = function () {
+ if (!GodotJSWrapper.get_proxied_value(id)) {
+ return;
+ }
+ const args = Array.from(arguments);
+ func(p_ref, GodotJSWrapper.get_proxied(args), args.length);
+ };
+ id = GodotJSWrapper.get_proxied(cb);
+ return id;
+ },
+
+ godot_js_wrapper_object_getvar__sig: 'iiii',
+ godot_js_wrapper_object_getvar: function (p_id, p_type, p_exchange) {
+ const obj = GodotJSWrapper.get_proxied_value(p_id);
+ if (obj === undefined) {
+ return -1;
+ }
+ const prop = GodotJSWrapper.variant2js(p_type, p_exchange);
+ if (prop === undefined || prop === null) {
+ return -1;
+ }
+ try {
+ return GodotJSWrapper.js2variant(obj[prop], p_exchange);
+ } catch (e) {
+ GodotRuntime.error(`Error getting variable ${prop} on object`, obj, e);
+ return -1;
+ }
+ },
+
+ godot_js_wrapper_object_setvar__sig: 'iiiiii',
+ godot_js_wrapper_object_setvar: function (p_id, p_key_type, p_key_ex, p_val_type, p_val_ex) {
+ const obj = GodotJSWrapper.get_proxied_value(p_id);
+ if (obj === undefined) {
+ return -1;
+ }
+ const key = GodotJSWrapper.variant2js(p_key_type, p_key_ex);
+ try {
+ obj[key] = GodotJSWrapper.variant2js(p_val_type, p_val_ex);
+ return 0;
+ } catch (e) {
+ GodotRuntime.error(`Error setting variable ${key} on object`, obj);
+ return -1;
+ }
+ },
+
+ godot_js_wrapper_create_object__sig: 'iiiiiiii',
+ godot_js_wrapper_create_object: function (p_object, p_args, p_argc, p_convert_callback, p_exchange, p_lock, p_free_lock_callback) {
+ const name = GodotRuntime.parseString(p_object);
+ if (typeof (window[name]) === 'undefined') {
+ return -1;
+ }
+ const convert = GodotRuntime.get_func(p_convert_callback);
+ const freeLock = GodotRuntime.get_func(p_free_lock_callback);
+ const args = new Array(p_argc);
+ for (let i = 0; i < p_argc; i++) {
+ const type = convert(p_args, i, p_exchange, p_lock);
+ const lock = GodotRuntime.getHeapValue(p_lock, '*');
+ args[i] = GodotJSWrapper.variant2js(type, p_exchange);
+ if (lock) {
+ freeLock(p_lock, type);
+ }
+ }
+ try {
+ const res = new window[name](...args);
+ return GodotJSWrapper.js2variant(res, p_exchange);
+ } catch (e) {
+ GodotRuntime.error(`Error calling constructor ${name} with args:`, args, 'error:', e);
+ return -1;
+ }
+ },
+};
+
+autoAddDeps(GodotJSWrapper, '$GodotJSWrapper');
+mergeInto(LibraryManager.library, GodotJSWrapper);
+
+const GodotEval = {
+ godot_js_eval__deps: ['$GodotRuntime'],
+ godot_js_eval__sig: 'iiiiiii',
+ godot_js_eval: function (p_js, p_use_global_ctx, p_union_ptr, p_byte_arr, p_byte_arr_write, p_callback) {
+ const js_code = GodotRuntime.parseString(p_js);
+ let eval_ret = null;
+ try {
+ if (p_use_global_ctx) {
+ // indirect eval call grants global execution context
+ const global_eval = eval; // eslint-disable-line no-eval
+ eval_ret = global_eval(js_code);
+ } else {
+ eval_ret = eval(js_code); // eslint-disable-line no-eval
+ }
+ } catch (e) {
+ GodotRuntime.error(e);
+ }
+
+ switch (typeof eval_ret) {
+ case 'boolean':
+ GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'i32');
+ return 1; // BOOL
+
+ case 'number':
+ GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'double');
+ return 3; // REAL
+
+ case 'string':
+ GodotRuntime.setHeapValue(p_union_ptr, GodotRuntime.allocString(eval_ret), '*');
+ return 4; // STRING
+
+ case 'object':
+ if (eval_ret === null) {
+ break;
+ }
+
+ if (ArrayBuffer.isView(eval_ret) && !(eval_ret instanceof Uint8Array)) {
+ eval_ret = new Uint8Array(eval_ret.buffer);
+ } else if (eval_ret instanceof ArrayBuffer) {
+ eval_ret = new Uint8Array(eval_ret);
+ }
+ if (eval_ret instanceof Uint8Array) {
+ const func = GodotRuntime.get_func(p_callback);
+ const bytes_ptr = func(p_byte_arr, p_byte_arr_write, eval_ret.length);
+ HEAPU8.set(eval_ret, bytes_ptr);
+ return 20; // POOL_BYTE_ARRAY
+ }
+ break;
+
+ // no default
+ }
+ return 0; // NIL
+ },
+};
+
+mergeInto(LibraryManager.library, GodotEval);
diff --git a/platform/javascript/js/libs/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js
index 1d9f889bce..7414b8cc47 100644
--- a/platform/javascript/js/libs/library_godot_os.js
+++ b/platform/javascript/js/libs/library_godot_os.js
@@ -304,6 +304,23 @@ const GodotOS = {
godot_js_os_hw_concurrency_get: function () {
return navigator.hardwareConcurrency || 1;
},
+
+ godot_js_os_download_buffer__sig: 'viiii',
+ godot_js_os_download_buffer: function (p_ptr, p_size, p_name, p_mime) {
+ const buf = GodotRuntime.heapSlice(HEAP8, p_ptr, p_size);
+ const name = GodotRuntime.parseString(p_name);
+ const mime = GodotRuntime.parseString(p_mime);
+ const blob = new Blob([buf], { type: mime });
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = name;
+ a.style.display = 'none';
+ document.body.appendChild(a);
+ a.click();
+ a.remove();
+ window.URL.revokeObjectURL(url);
+ },
};
autoAddDeps(GodotOS, '$GodotOS');
diff --git a/platform/javascript/package-lock.json b/platform/javascript/package-lock.json
index 8bf5c52ff6..8003619576 100644
--- a/platform/javascript/package-lock.json
+++ b/platform/javascript/package-lock.json
@@ -5,27 +5,27 @@
"requires": true,
"dependencies": {
"@babel/code-frame": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
- "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+ "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
"dev": true,
"requires": {
"@babel/highlight": "^7.10.4"
}
},
"@babel/helper-validator-identifier": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
- "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
+ "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
"dev": true
},
"@babel/highlight": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
- "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
+ "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.10.4",
+ "@babel/helper-validator-identifier": "^7.14.5",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
@@ -40,39 +40,38 @@
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
}
}
},
"@babel/parser": {
- "version": "7.14.1",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz",
- "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==",
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.5.tgz",
+ "integrity": "sha512-TM8C+xtH/9n1qzX+JNHi7AN2zHMTiPUtspO0ZdHflW8KaskkALhMmuMHb4bCmNdv9VAPzJX3/bXqkVLnAvsPfg==",
"dev": true
},
"@eslint/eslintrc": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
- "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz",
+ "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
"debug": "^4.1.1",
"espree": "^7.3.0",
- "globals": "^12.1.0",
+ "globals": "^13.9.0",
"ignore": "^4.0.6",
"import-fresh": "^3.2.1",
"js-yaml": "^3.13.1",
- "lodash": "^4.17.19",
"minimatch": "^3.0.4",
"strip-json-comments": "^3.1.1"
}
},
- "@types/color-name": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
- "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
- "dev": true
- },
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -80,9 +79,9 @@
"dev": true
},
"acorn": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
- "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true
},
"acorn-jsx": {
@@ -92,9 +91,9 @@
"dev": true
},
"ajv": {
- "version": "6.12.5",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
- "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@@ -134,78 +133,39 @@
}
},
"array-includes": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz",
- "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz",
+ "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==",
"dev": true,
"requires": {
+ "call-bind": "^1.0.2",
"define-properties": "^1.1.3",
- "es-abstract": "^1.17.0",
+ "es-abstract": "^1.18.0-next.2",
+ "get-intrinsic": "^1.1.1",
"is-string": "^1.0.5"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- }
}
},
"array.prototype.flat": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz",
- "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz",
+ "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==",
"dev": true,
"requires": {
+ "call-bind": "^1.0.0",
"define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- }
+ "es-abstract": "^1.18.0-next.1"
}
},
"astral-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
- "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
"dev": true
},
"balanced-match": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"bluebird": {
@@ -224,6 +184,16 @@
"concat-map": "0.0.1"
}
},
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -231,18 +201,18 @@
"dev": true
},
"catharsis": {
- "version": "0.8.11",
- "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz",
- "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==",
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz",
+ "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==",
"dev": true,
"requires": {
- "lodash": "^4.17.14"
+ "lodash": "^4.17.15"
}
},
"chalk": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
- "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
+ "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
@@ -250,12 +220,11 @@
},
"dependencies": {
"ansi-styles": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
- "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
- "@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
@@ -313,15 +282,9 @@
"dev": true
},
"confusing-browser-globals": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz",
- "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==",
- "dev": true
- },
- "contains-path": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
- "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz",
+ "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==",
"dev": true
},
"cross-spawn": {
@@ -336,12 +299,12 @@
}
},
"debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+ "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
- "ms": "^2.1.1"
+ "ms": "2.1.2"
}
},
"deep-is": {
@@ -369,9 +332,9 @@
}
},
"emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"enquirer": {
@@ -399,23 +362,27 @@
}
},
"es-abstract": {
- "version": "1.18.0-next.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz",
- "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==",
+ "version": "1.18.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
+ "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
"dev": true,
"requires": {
+ "call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
+ "get-intrinsic": "^1.1.1",
"has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-negative-zero": "^2.0.0",
- "is-regex": "^1.1.1",
- "object-inspect": "^1.8.0",
+ "has-symbols": "^1.0.2",
+ "is-callable": "^1.2.3",
+ "is-negative-zero": "^2.0.1",
+ "is-regex": "^1.1.3",
+ "is-string": "^1.0.6",
+ "object-inspect": "^1.10.3",
"object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
+ "object.assign": "^4.1.2",
+ "string.prototype.trimend": "^1.0.4",
+ "string.prototype.trimstart": "^1.0.4",
+ "unbox-primitive": "^1.0.1"
}
},
"es-to-primitive": {
@@ -430,35 +397,37 @@
}
},
"escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true
},
"eslint": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.9.0.tgz",
- "integrity": "sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA==",
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz",
+ "integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.0.0",
- "@eslint/eslintrc": "^0.1.3",
+ "@babel/code-frame": "7.12.11",
+ "@eslint/eslintrc": "^0.4.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"enquirer": "^2.3.5",
- "eslint-scope": "^5.1.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^5.1.1",
"eslint-utils": "^2.1.0",
- "eslint-visitor-keys": "^1.3.0",
- "espree": "^7.3.0",
- "esquery": "^1.2.0",
+ "eslint-visitor-keys": "^2.0.0",
+ "espree": "^7.3.1",
+ "esquery": "^1.4.0",
"esutils": "^2.0.2",
- "file-entry-cache": "^5.0.1",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
"functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.0.0",
- "globals": "^12.1.0",
+ "glob-parent": "^5.1.2",
+ "globals": "^13.6.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
@@ -466,7 +435,7 @@
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
- "lodash": "^4.17.19",
+ "lodash.merge": "^4.6.2",
"minimatch": "^3.0.4",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
@@ -475,19 +444,19 @@
"semver": "^7.2.1",
"strip-ansi": "^6.0.0",
"strip-json-comments": "^3.1.0",
- "table": "^5.2.3",
+ "table": "^6.0.9",
"text-table": "^0.2.0",
"v8-compile-cache": "^2.0.3"
}
},
"eslint-config-airbnb-base": {
- "version": "14.2.0",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz",
- "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==",
+ "version": "14.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz",
+ "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==",
"dev": true,
"requires": {
- "confusing-browser-globals": "^1.0.9",
- "object.assign": "^4.1.0",
+ "confusing-browser-globals": "^1.0.10",
+ "object.assign": "^4.1.2",
"object.entries": "^1.1.2"
}
},
@@ -519,50 +488,46 @@
}
},
"eslint-module-utils": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz",
- "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==",
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz",
+ "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==",
"dev": true,
"requires": {
- "debug": "^2.6.9",
+ "debug": "^3.2.7",
"pkg-dir": "^2.0.0"
},
"dependencies": {
"debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"requires": {
- "ms": "2.0.0"
+ "ms": "^2.1.1"
}
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
}
}
},
"eslint-plugin-import": {
- "version": "2.22.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz",
- "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==",
+ "version": "2.23.4",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz",
+ "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==",
"dev": true,
"requires": {
- "array-includes": "^3.1.1",
- "array.prototype.flat": "^1.2.3",
- "contains-path": "^0.1.0",
+ "array-includes": "^3.1.3",
+ "array.prototype.flat": "^1.2.4",
"debug": "^2.6.9",
- "doctrine": "1.5.0",
- "eslint-import-resolver-node": "^0.3.3",
- "eslint-module-utils": "^2.6.0",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.4",
+ "eslint-module-utils": "^2.6.1",
+ "find-up": "^2.0.0",
"has": "^1.0.3",
+ "is-core-module": "^2.4.0",
"minimatch": "^3.0.4",
- "object.values": "^1.1.1",
- "read-pkg-up": "^2.0.0",
- "resolve": "^1.17.0",
+ "object.values": "^1.1.3",
+ "pkg-up": "^2.0.0",
+ "read-pkg-up": "^3.0.0",
+ "resolve": "^1.20.0",
"tsconfig-paths": "^3.9.0"
},
"dependencies": {
@@ -576,13 +541,12 @@
}
},
"doctrine": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
- "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
"dev": true,
"requires": {
- "esutils": "^2.0.2",
- "isarray": "^1.0.0"
+ "esutils": "^2.0.2"
}
},
"ms": {
@@ -610,23 +574,39 @@
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
}
},
"eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
"dev": true
},
"espree": {
- "version": "7.3.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
- "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
"dev": true,
"requires": {
"acorn": "^7.4.0",
- "acorn-jsx": "^5.2.0",
+ "acorn-jsx": "^5.3.1",
"eslint-visitor-keys": "^1.3.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
}
},
"esprima": {
@@ -636,9 +616,9 @@
"dev": true
},
"esquery": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
- "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
"dev": true,
"requires": {
"estraverse": "^5.1.0"
@@ -700,12 +680,12 @@
"dev": true
},
"file-entry-cache": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
- "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
"dev": true,
"requires": {
- "flat-cache": "^2.0.1"
+ "flat-cache": "^3.0.4"
}
},
"find-up": {
@@ -718,20 +698,19 @@
}
},
"flat-cache": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
- "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
"dev": true,
"requires": {
- "flatted": "^2.0.0",
- "rimraf": "2.6.3",
- "write": "1.0.3"
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
}
},
"flatted": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
- "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
+ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
"dev": true
},
"fs.realpath": {
@@ -752,10 +731,21 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
"glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "version": "7.1.7",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
@@ -767,27 +757,27 @@
}
},
"glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"globals": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
- "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "version": "13.9.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz",
+ "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==",
"dev": true,
"requires": {
- "type-fest": "^0.8.1"
+ "type-fest": "^0.20.2"
}
},
"graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
+ "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
"dev": true
},
"has": {
@@ -799,6 +789,12 @@
"function-bind": "^1.1.1"
}
},
+ "has-bigints": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
+ "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
+ "dev": true
+ },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -806,9 +802,9 @@
"dev": true
},
"has-symbols": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
"dev": true
},
"hosted-git-info": {
@@ -824,9 +820,9 @@
"dev": true
},
"import-fresh": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
- "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
"dev": true,
"requires": {
"parent-module": "^1.0.0",
@@ -861,16 +857,40 @@
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
"dev": true
},
+ "is-bigint": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
+ "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
+ "dev": true
+ },
+ "is-boolean-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
+ "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
"is-callable": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz",
- "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
+ "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
"dev": true
},
+ "is-core-module": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
+ "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
"is-date-object": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
- "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
+ "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
"dev": true
},
"is-extglob": {
@@ -880,9 +900,9 @@
"dev": true
},
"is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"is-glob": {
@@ -895,41 +915,42 @@
}
},
"is-negative-zero": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
- "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
+ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+ "dev": true
+ },
+ "is-number-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
+ "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
"dev": true
},
"is-regex": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
- "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
+ "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
"dev": true,
"requires": {
- "has-symbols": "^1.0.1"
+ "call-bind": "^1.0.2",
+ "has-symbols": "^1.0.2"
}
},
"is-string": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
- "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
+ "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
"dev": true
},
"is-symbol": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
- "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"dev": true,
"requires": {
- "has-symbols": "^1.0.1"
+ "has-symbols": "^1.0.2"
}
},
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
- },
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -943,9 +964,9 @@
"dev": true
},
"js-yaml": {
- "version": "3.14.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
- "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
@@ -962,13 +983,14 @@
}
},
"jsdoc": {
- "version": "github:jsdoc/jsdoc#544a992824631fc652183d8b0b4b1281dc961560",
- "from": "github:jsdoc/jsdoc#544a992824631fc652183d8b0b4b1281dc961560",
+ "version": "3.6.7",
+ "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz",
+ "integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==",
"dev": true,
"requires": {
"@babel/parser": "^7.9.4",
"bluebird": "^3.7.2",
- "catharsis": "^0.8.11",
+ "catharsis": "^0.9.0",
"escape-string-regexp": "^2.0.0",
"js2xmlparser": "^4.0.1",
"klaw": "^3.0.0",
@@ -979,7 +1001,7 @@
"requizzle": "^0.2.3",
"strip-json-comments": "^3.1.0",
"taffydb": "2.6.2",
- "underscore": "~1.12.1"
+ "underscore": "~1.13.1"
},
"dependencies": {
"escape-string-regexp": {
@@ -987,15 +1009,15 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
"dev": true
- },
- "mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "dev": true
}
}
},
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -1046,14 +1068,14 @@
}
},
"load-json-file": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
- "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
- "parse-json": "^2.2.0",
- "pify": "^2.0.0",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
"strip-bom": "^3.0.0"
}
},
@@ -1073,6 +1095,33 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
+ "dev": true
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
"markdown-it": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
@@ -1093,9 +1142,9 @@
"dev": true
},
"marked": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.3.tgz",
- "integrity": "sha512-5otztIIcJfPc2qGTN8cVtOJEjNJZ0jwa46INMagrYfk0EvqtRuEHLsEe0LrFS0/q+ZRKT0+kXK7P2T1AN5lWRA==",
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.7.tgz",
+ "integrity": "sha512-BJXxkuIfJchcXOJWTT2DOL+yFWifFv2yGYOUzvXg8Qz610QKw+sHCvTMYwA+qWGhlA2uivBezChZ/pBy1tWdkQ==",
"dev": true
},
"mdurl": {
@@ -1120,13 +1169,10 @@
"dev": true
},
"mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
- "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
},
"ms": {
"version": "2.1.2",
@@ -1161,9 +1207,9 @@
}
},
"object-inspect": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
- "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
+ "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
"dev": true
},
"object-keys": {
@@ -1173,80 +1219,37 @@
"dev": true
},
"object.assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz",
- "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
"dev": true,
"requires": {
+ "call-bind": "^1.0.0",
"define-properties": "^1.1.3",
- "es-abstract": "^1.18.0-next.0",
"has-symbols": "^1.0.1",
"object-keys": "^1.1.1"
}
},
"object.entries": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz",
- "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.4.tgz",
+ "integrity": "sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA==",
"dev": true,
"requires": {
+ "call-bind": "^1.0.2",
"define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "has": "^1.0.3"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- }
+ "es-abstract": "^1.18.2"
}
},
"object.values": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz",
- "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz",
+ "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==",
"dev": true,
"requires": {
+ "call-bind": "^1.0.2",
"define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- }
+ "es-abstract": "^1.18.2"
}
},
"once": {
@@ -1306,12 +1309,13 @@
}
},
"parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"dev": true,
"requires": {
- "error-ex": "^1.2.0"
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
}
},
"path-exists": {
@@ -1333,24 +1337,24 @@
"dev": true
},
"path-parse": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
- "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"path-type": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
- "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
"dev": true,
"requires": {
- "pify": "^2.0.0"
+ "pify": "^3.0.0"
}
},
"pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
},
"pkg-dir": {
@@ -1362,6 +1366,15 @@
"find-up": "^2.1.0"
}
},
+ "pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
+ "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ },
"prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -1381,30 +1394,36 @@
"dev": true
},
"read-pkg": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
- "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
"dev": true,
"requires": {
- "load-json-file": "^2.0.0",
+ "load-json-file": "^4.0.0",
"normalize-package-data": "^2.3.2",
- "path-type": "^2.0.0"
+ "path-type": "^3.0.0"
}
},
"read-pkg-up": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
- "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
+ "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
"dev": true,
"requires": {
"find-up": "^2.0.0",
- "read-pkg": "^2.0.0"
+ "read-pkg": "^3.0.0"
}
},
"regexpp": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
- "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true
+ },
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true
},
"requizzle": {
@@ -1417,11 +1436,12 @@
}
},
"resolve": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
- "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+ "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
"dev": true,
"requires": {
+ "is-core-module": "^2.2.0",
"path-parse": "^1.0.6"
}
},
@@ -1432,19 +1452,22 @@
"dev": true
},
"rimraf": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
- "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"semver": {
- "version": "7.3.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
- "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
- "dev": true
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
},
"shebang-command": {
"version": "2.0.0",
@@ -1462,14 +1485,40 @@
"dev": true
},
"slice-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
- "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
"dev": true,
"requires": {
- "ansi-styles": "^3.2.0",
- "astral-regex": "^1.0.0",
- "is-fullwidth-code-point": "^2.0.0"
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ }
}
},
"spdx-correct": {
@@ -1499,9 +1548,9 @@
}
},
"spdx-license-ids": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz",
- "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==",
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
+ "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
"dev": true
},
"sprintf-js": {
@@ -1511,93 +1560,34 @@
"dev": true
},
"string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+ "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
"dev": true,
"requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
}
},
"string.prototype.trimend": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
- "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
+ "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
"dev": true,
"requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- }
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
}
},
"string.prototype.trimstart": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
- "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
+ "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
"dev": true,
"requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- }
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
}
},
"strip-ansi": {
@@ -1631,15 +1621,37 @@
}
},
"table": {
- "version": "5.4.6",
- "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
- "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz",
+ "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==",
"dev": true,
"requires": {
- "ajv": "^6.10.2",
- "lodash": "^4.17.14",
- "slice-ansi": "^2.1.0",
- "string-width": "^3.0.0"
+ "ajv": "^8.0.1",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz",
+ "integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ }
}
},
"taffydb": {
@@ -1676,9 +1688,9 @@
}
},
"type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true
},
"uc.micro": {
@@ -1687,25 +1699,37 @@
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
"dev": true
},
+ "unbox-primitive": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
+ "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has-bigints": "^1.0.1",
+ "has-symbols": "^1.0.2",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
"underscore": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
- "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==",
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
+ "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==",
"dev": true
},
"uri-js": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
- "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
"requires": {
"punycode": "^2.1.0"
}
},
"v8-compile-cache": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
- "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
"dev": true
},
"validate-npm-package-license": {
@@ -1727,6 +1751,19 @@
"isexe": "^2.0.0"
}
},
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -1739,20 +1776,17 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
- "write": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
- "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
- "dev": true,
- "requires": {
- "mkdirp": "^0.5.1"
- }
- },
"xmlcreate": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz",
"integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==",
"dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
}
}
}
diff --git a/platform/javascript/package.json b/platform/javascript/package.json
index 53748503f9..9dafae30c5 100644
--- a/platform/javascript/package.json
+++ b/platform/javascript/package.json
@@ -20,9 +20,9 @@
"author": "Godot Engine contributors",
"license": "MIT",
"devDependencies": {
- "eslint": "^7.9.0",
- "eslint-config-airbnb-base": "^14.2.0",
- "eslint-plugin-import": "^2.22.0",
- "jsdoc": "github:jsdoc/jsdoc#544a992824631fc652183d8b0b4b1281dc961560"
+ "eslint": "^7.28.0",
+ "eslint-config-airbnb-base": "^14.2.1",
+ "eslint-plugin-import": "^2.23.4",
+ "jsdoc": "^3.6.7"
}
}
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index 46714e9502..1751d56e71 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -5,21 +5,27 @@ Import("env")
from platform_methods import run_in_subprocess
import platform_linuxbsd_builders
-common_x11 = [
+common_linuxbsd = [
"crash_handler_linuxbsd.cpp",
"os_linuxbsd.cpp",
"joypad_linux.cpp",
- "context_gl_x11.cpp",
- "detect_prime_x11.cpp",
- "display_server_x11.cpp",
- "vulkan_context_x11.cpp",
- "key_mapping_x11.cpp",
]
+if "x11" in env and env["x11"]:
+ common_linuxbsd += [
+ "context_gl_x11.cpp",
+ "detect_prime_x11.cpp",
+ "display_server_x11.cpp",
+ "key_mapping_x11.cpp",
+ ]
+
+if "vulkan" in env and env["vulkan"]:
+ common_linuxbsd.append("vulkan_context_x11.cpp")
+
if "udev" in env and env["udev"]:
- common_x11.append("libudev-so_wrap.c")
+ common_linuxbsd.append("libudev-so_wrap.c")
-prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_x11)
+prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_linuxbsd)
if env["debug_symbols"] and env["separate_debug_symbols"]:
env.AddPostAction(prog, run_in_subprocess(platform_linuxbsd_builders.make_debug_linuxbsd))
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 1876960c57..1487210174 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -73,6 +73,7 @@ def get_opts():
BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False),
BoolVariable("pulseaudio", "Detect and use PulseAudio", True),
BoolVariable("udev", "Use udev for gamepad connection callbacks", True),
+ BoolVariable("x11", "Enable X11 display", True),
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
BoolVariable("touch", "Enable touch events", True),
@@ -362,17 +363,26 @@ def configure(env):
env.ParseConfig("pkg-config zlib --cflags --libs")
env.Prepend(CPPPATH=["#platform/linuxbsd"])
- env.Append(CPPDEFINES=["X11_ENABLED", "UNIX_ENABLED"])
- env.Append(CPPDEFINES=["VULKAN_ENABLED"])
- if not env["builtin_vulkan"]:
- env.ParseConfig("pkg-config vulkan --cflags --libs")
- if not env["builtin_glslang"]:
- # No pkgconfig file for glslang so far
- env.Append(LIBS=["glslang", "SPIRV"])
-
- # env.Append(CPPDEFINES=['OPENGL_ENABLED'])
- env.Append(LIBS=["GL"])
+ if env["x11"]:
+ if not env["vulkan"]:
+ print("Error: X11 support requires vulkan=yes")
+ env.Exit(255)
+ env.Append(CPPDEFINES=["X11_ENABLED"])
+
+ env.Append(CPPDEFINES=["UNIX_ENABLED"])
+ env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)])
+
+ if env["vulkan"]:
+ env.Append(CPPDEFINES=["VULKAN_ENABLED"])
+ if not env["builtin_vulkan"]:
+ env.ParseConfig("pkg-config vulkan --cflags --libs")
+ if not env["builtin_glslang"]:
+ # No pkgconfig file for glslang so far
+ env.Append(LIBS=["glslang", "SPIRV"])
+
+ # env.Append(CPPDEFINES=['OPENGL_ENABLED'])
+ env.Append(LIBS=["GL"])
env.Append(LIBS=["pthread"])
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index be69b2e5da..8b6922699c 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -360,7 +360,7 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
return;
}
- if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) {
+ if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
XUngrabPointer(x11_display, CurrentTime);
}
@@ -376,7 +376,7 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
}
mouse_mode = p_mode;
- if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) {
+ if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
//flush pending motion events
_flush_mouse_motion();
WindowData &main_window = windows[MAIN_WINDOW_ID];
@@ -2166,10 +2166,10 @@ static Atom pick_target_from_atoms(Display *p_disp, Atom p_t1, Atom p_t2, Atom p
}
void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state) {
- state->set_shift((p_x11_state & ShiftMask));
- state->set_control((p_x11_state & ControlMask));
- state->set_alt((p_x11_state & Mod1Mask /*|| p_x11_state&Mod5Mask*/)); //altgr should not count as alt
- state->set_metakey((p_x11_state & Mod4Mask));
+ state->set_shift_pressed((p_x11_state & ShiftMask));
+ state->set_ctrl_pressed((p_x11_state & ControlMask));
+ state->set_alt_pressed((p_x11_state & Mod1Mask /*|| p_x11_state&Mod5Mask*/)); //altgr should not count as alt
+ state->set_meta_pressed((p_x11_state & Mod4Mask));
}
unsigned int DisplayServerX11::_get_mouse_button_state(unsigned int p_x11_button, int p_x11_type) {
@@ -2281,7 +2281,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
//make it consistent across platforms.
k->set_keycode(KEY_TAB);
k->set_physical_keycode(KEY_TAB);
- k->set_shift(true);
+ k->set_shift_pressed(true);
}
Input::get_singleton()->accumulate_input_event(k);
@@ -2409,20 +2409,20 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
//make it consistent across platforms.
k->set_keycode(KEY_TAB);
k->set_physical_keycode(KEY_TAB);
- k->set_shift(true);
+ k->set_shift_pressed(true);
}
//don't set mod state if modifier keys are released by themselves
//else event.is_action() will not work correctly here
if (!k->is_pressed()) {
if (k->get_keycode() == KEY_SHIFT) {
- k->set_shift(false);
- } else if (k->get_keycode() == KEY_CONTROL) {
- k->set_control(false);
+ k->set_shift_pressed(false);
+ } else if (k->get_keycode() == KEY_CTRL) {
+ k->set_ctrl_pressed(false);
} else if (k->get_keycode() == KEY_ALT) {
- k->set_alt(false);
+ k->set_alt_pressed(false);
} else if (k->get_keycode() == KEY_META) {
- k->set_metakey(false);
+ k->set_meta_pressed(false);
}
}
@@ -2766,7 +2766,7 @@ void DisplayServerX11::process_events() {
do_mouse_warp = false;
// Is the current mouse mode one where it needs to be grabbed.
- bool mouse_mode_grab = mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED;
+ bool mouse_mode_grab = mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN;
xi.pressure = 0;
xi.tilt = Vector2();
@@ -3030,7 +3030,7 @@ void DisplayServerX11::process_events() {
for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
if (mouse_mode == MOUSE_MODE_CONFINED) {
XUndefineCursor(x11_display, E->get().x11_window);
- } else if (mouse_mode == MOUSE_MODE_CAPTURED) { // or re-hide it in captured mode
+ } else if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { // Or re-hide it.
XDefineCursor(x11_display, E->get().x11_window, null_cursor);
}
diff --git a/platform/linuxbsd/export/export.cpp b/platform/linuxbsd/export/export.cpp
index cb95068314..3ee088dd35 100644
--- a/platform/linuxbsd/export/export.cpp
+++ b/platform/linuxbsd/export/export.cpp
@@ -30,7 +30,7 @@
#include "export.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "editor/editor_export.h"
#include "platform/linuxbsd/logo.gen.h"
#include "scene/resources/texture.h"
diff --git a/platform/linuxbsd/key_mapping_x11.cpp b/platform/linuxbsd/key_mapping_x11.cpp
index f9f612fa74..74257a7e61 100644
--- a/platform/linuxbsd/key_mapping_x11.cpp
+++ b/platform/linuxbsd/key_mapping_x11.cpp
@@ -61,8 +61,8 @@ static _XTranslatePair _xkeysym_to_keycode[] = {
{ XK_Shift_L, KEY_SHIFT },
{ XK_Shift_R, KEY_SHIFT },
{ XK_Shift_Lock, KEY_SHIFT },
- { XK_Control_L, KEY_CONTROL },
- { XK_Control_R, KEY_CONTROL },
+ { XK_Control_L, KEY_CTRL },
+ { XK_Control_R, KEY_CTRL },
{ XK_Meta_L, KEY_META },
{ XK_Meta_R, KEY_META },
{ XK_Alt_L, KEY_ALT },
@@ -213,7 +213,7 @@ static _TranslatePair _scancode_to_keycode[] = {
{ KEY_BRACELEFT, 0x22 },
{ KEY_BRACERIGHT, 0x23 },
{ KEY_ENTER, 0x24 },
- { KEY_CONTROL, 0x25 },
+ { KEY_CTRL, 0x25 },
{ KEY_A, 0x26 },
{ KEY_S, 0x27 },
{ KEY_D, 0x28 },
@@ -272,7 +272,7 @@ static _TranslatePair _scancode_to_keycode[] = {
{ KEY_F11, 0x5F },
{ KEY_F12, 0x60 },
{ KEY_KP_ENTER, 0x68 },
- { KEY_CONTROL, 0x69 },
+ { KEY_CTRL, 0x69 },
{ KEY_KP_DIVIDE, 0x6A },
{ KEY_PRINT, 0x6B },
{ KEY_ALT, 0x6C },
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 09e1f9461c..c6a2fa5be7 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -30,7 +30,7 @@
#include "os_linuxbsd.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "main/main.h"
#ifdef X11_ENABLED
@@ -116,6 +116,8 @@ String OS_LinuxBSD::get_name() const {
return "FreeBSD";
#elif defined(__NetBSD__)
return "NetBSD";
+#elif defined(__OpenBSD__)
+ return "OpenBSD";
#else
return "BSD";
#endif
@@ -164,7 +166,12 @@ bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
String OS_LinuxBSD::get_config_path() const {
if (has_environment("XDG_CONFIG_HOME")) {
- return get_environment("XDG_CONFIG_HOME");
+ if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
+ return get_environment("XDG_CONFIG_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.config` or `.` per the XDG Base Directory specification.");
+ return has_environment("HOME") ? get_environment("HOME").plus_file(".config") : ".";
+ }
} else if (has_environment("HOME")) {
return get_environment("HOME").plus_file(".config");
} else {
@@ -174,7 +181,12 @@ String OS_LinuxBSD::get_config_path() const {
String OS_LinuxBSD::get_data_path() const {
if (has_environment("XDG_DATA_HOME")) {
- return get_environment("XDG_DATA_HOME");
+ if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
+ return get_environment("XDG_DATA_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.local/share` or `get_config_path()` per the XDG Base Directory specification.");
+ return has_environment("HOME") ? get_environment("HOME").plus_file(".local/share") : get_config_path();
+ }
} else if (has_environment("HOME")) {
return get_environment("HOME").plus_file(".local/share");
} else {
@@ -184,7 +196,12 @@ String OS_LinuxBSD::get_data_path() const {
String OS_LinuxBSD::get_cache_path() const {
if (has_environment("XDG_CACHE_HOME")) {
- return get_environment("XDG_CACHE_HOME");
+ if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
+ return get_environment("XDG_CACHE_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.cache` or `get_config_path()` per the XDG Base Directory specification.");
+ return has_environment("HOME") ? get_environment("HOME").plus_file(".cache") : get_config_path();
+ }
} else if (has_environment("HOME")) {
return get_environment("HOME").plus_file(".cache");
} else {
@@ -408,8 +425,8 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// Generates the .trashinfo file
OS::Date date = OS::get_singleton()->get_date(false);
OS::Time time = OS::get_singleton()->get_time(false);
- String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, date.month, date.day, time.hour, time.min);
- timestamp = vformat("%s%02d", timestamp, time.sec); // vformat only supports up to 6 arguments.
+ String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, date.month, date.day, time.hour, time.minute);
+ timestamp = vformat("%s%02d", timestamp, time.second); // vformat only supports up to 6 arguments.
String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;
diff --git a/platform/osx/dir_access_osx.h b/platform/osx/dir_access_osx.h
index f61581979f..a894723e64 100644
--- a/platform/osx/dir_access_osx.h
+++ b/platform/osx/dir_access_osx.h
@@ -38,7 +38,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "drivers/unix/dir_access_unix.h"
class DirAccessOSX : public DirAccessUnix {
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 473ae95036..408feb4db9 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -66,10 +66,10 @@
static bool ignore_momentum_scroll = false;
static void _get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) {
- r_state->set_shift((p_osx_state & NSEventModifierFlagShift));
- r_state->set_control((p_osx_state & NSEventModifierFlagControl));
- r_state->set_alt((p_osx_state & NSEventModifierFlagOption));
- r_state->set_metakey((p_osx_state & NSEventModifierFlagCommand));
+ r_state->set_shift_pressed((p_osx_state & NSEventModifierFlagShift));
+ r_state->set_ctrl_pressed((p_osx_state & NSEventModifierFlagControl));
+ r_state->set_alt_pressed((p_osx_state & NSEventModifierFlagOption));
+ r_state->set_meta_pressed((p_osx_state & NSEventModifierFlagCommand));
}
static Vector2i _get_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_locationInWindow) {
@@ -368,6 +368,10 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
if (wd.resize_disabled) {
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
}
+
+ if (wd.on_top) {
+ [wd.window_object setLevel:NSFloatingWindowLevel];
+ }
}
- (void)windowDidChangeBackingProperties:(NSNotification *)notification {
@@ -880,7 +884,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
return;
}
- if (DS_OSX->mouse_mode == DisplayServer::MOUSE_MODE_CONFINED) {
+ if (DS_OSX->mouse_mode == DisplayServer::MOUSE_MODE_CONFINED || DS_OSX->mouse_mode == DisplayServer::MOUSE_MODE_CONFINED_HIDDEN) {
// Discard late events
if (([event timestamp]) < DS_OSX->last_warp) {
return;
@@ -1133,10 +1137,10 @@ static int translateKey(unsigned int key) {
/* 38 */ KEY_SHIFT,
/* 39 */ KEY_CAPSLOCK,
/* 3a */ KEY_ALT,
- /* 3b */ KEY_CONTROL,
+ /* 3b */ KEY_CTRL,
/* 3c */ KEY_SHIFT,
/* 3d */ KEY_ALT,
- /* 3e */ KEY_CONTROL,
+ /* 3e */ KEY_CTRL,
/* 3f */ KEY_UNKNOWN, /* Function */
/* 40 */ KEY_UNKNOWN, /* F17 */
/* 41 */ KEY_KP_PERIOD,
@@ -2102,7 +2106,12 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
} else if (p_mode == MOUSE_MODE_CONFINED) {
CGDisplayShowCursor(kCGDirectMainDisplay);
CGAssociateMouseAndMouseCursorPosition(false);
- } else {
+ } else if (p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
+ if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
+ CGDisplayHideCursor(kCGDirectMainDisplay);
+ }
+ CGAssociateMouseAndMouseCursorPosition(false);
+ } else { // MOUSE_MODE_VISIBLE
CGDisplayShowCursor(kCGDirectMainDisplay);
CGAssociateMouseAndMouseCursorPosition(true);
}
@@ -2139,7 +2148,7 @@ void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) {
CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0);
CGAssociateMouseAndMouseCursorPosition(false);
CGWarpMouseCursorPosition(lMouseWarpPos);
- if (mouse_mode != MOUSE_MODE_CONFINED) {
+ if (mouse_mode != MOUSE_MODE_CONFINED && mouse_mode != MOUSE_MODE_CONFINED_HIDDEN) {
CGAssociateMouseAndMouseCursorPosition(true);
}
}
@@ -2437,7 +2446,7 @@ void DisplayServerOSX::_update_window(WindowData p_wd) {
[p_wd.window_object setHidesOnDeactivate:YES];
} else {
// Reset these when our window is not a borderless window that covers up the screen
- if (p_wd.on_top) {
+ if (p_wd.on_top && !p_wd.fullscreen) {
[p_wd.window_object setLevel:NSFloatingWindowLevel];
} else {
[p_wd.window_object setLevel:NSNormalWindowLevel];
@@ -2786,6 +2795,7 @@ void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) {
[wd.window_object deminiaturize:nil];
} break;
case WINDOW_MODE_FULLSCREEN: {
+ [wd.window_object setLevel:NSNormalWindowLevel];
if (wd.layered_window) {
_set_window_per_pixel_transparency_enabled(true, p_window);
}
@@ -2903,6 +2913,9 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
} break;
case WINDOW_FLAG_ALWAYS_ON_TOP: {
wd.on_top = p_enabled;
+ if (wd.fullscreen) {
+ return;
+ }
if (p_enabled) {
[wd.window_object setLevel:NSFloatingWindowLevel];
} else {
@@ -2940,7 +2953,11 @@ bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) co
return [wd.window_object styleMask] == NSWindowStyleMaskBorderless;
} break;
case WINDOW_FLAG_ALWAYS_ON_TOP: {
- return [wd.window_object level] == NSFloatingWindowLevel;
+ if (wd.fullscreen) {
+ return wd.on_top;
+ } else {
+ return [wd.window_object level] == NSFloatingWindowLevel;
+ }
} break;
case WINDOW_FLAG_TRANSPARENT: {
return wd.layered_window;
@@ -3467,7 +3484,7 @@ void DisplayServerOSX::set_native_icon(const String &p_filename) {
ERR_FAIL_COND(!f);
Vector<uint8_t> data;
- uint32_t len = f->get_len();
+ uint64_t len = f->get_length();
data.resize(len);
f->get_buffer((uint8_t *)&data.write[0], len);
memdelete(f);
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 51204bc8f6..f52853ca9e 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -31,11 +31,11 @@
#include "export.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/io/resource_saver.h"
#include "core/io/zip_io.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/version.h"
#include "editor/editor_export.h"
@@ -147,6 +147,7 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_category", PROPERTY_HINT_ENUM, "Business,Developer-tools,Education,Entertainment,Finance,Games,Action-games,Adventure-games,Arcade-games,Board-games,Card-games,Casino-games,Dice-games,Educational-games,Family-games,Kids-games,Music-games,Puzzle-games,Racing-games,Role-playing-games,Simulation-games,Sports-games,Strategy-games,Trivia-games,Word-games,Graphics-design,Healthcare-fitness,Lifestyle,Medical,Music,News,Photography,Productivity,Reference,Social-networking,Sports,Travel,Utilities,Video,Weather"), "Games"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
@@ -301,7 +302,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
if (icon_infos[i].is_png) {
// Encode PNG icon.
it->create_from_image(copy);
- String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("icon.png");
+ String path = EditorPaths::get_singleton()->get_cache_dir().plus_file("icon.png");
ResourceSaver::save(path, it);
FileAccess *f = FileAccess::open(path, FileAccess::READ);
@@ -312,7 +313,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
}
int ofs = data.size();
- uint32_t len = f->get_len();
+ uint64_t len = f->get_length();
data.resize(data.size() + len + 8);
f->get_buffer(&data.write[ofs + 8], len);
memdelete(f);
@@ -386,6 +387,9 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n";
} else if (lines[i].find("$signature") != -1) {
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
+ } else if (lines[i].find("$app_category") != -1) {
+ String cat = p_preset->get("application/app_category");
+ strnew += lines[i].replace("$app_category", cat.to_lower()) + "\n";
} else if (lines[i].find("$copyright") != -1) {
strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
} else if (lines[i].find("$highres") != -1) {
@@ -610,7 +614,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
// Create our application bundle.
String tmp_app_dir_name = pkg_name + ".app";
- String tmp_app_path_name = EditorSettings::get_singleton()->get_cache_dir().plus_file(tmp_app_dir_name);
+ String tmp_app_path_name = EditorPaths::get_singleton()->get_cache_dir().plus_file(tmp_app_dir_name);
print_line("Exporting to " + tmp_app_path_name);
Error err = OK;
@@ -689,8 +693,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (iconpath.get_extension() == "icns") {
FileAccess *icon = FileAccess::open(iconpath, FileAccess::READ);
if (icon) {
- data.resize(icon->get_len());
- icon->get_buffer(&data.write[0], icon->get_len());
+ data.resize(icon->get_length());
+ icon->get_buffer(&data.write[0], icon->get_length());
icon->close();
memdelete(icon);
}
@@ -774,7 +778,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
String ent_path = p_preset->get("codesign/entitlements/custom_file");
if (sign_enabled && (ent_path == "")) {
- ent_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".entitlements");
+ ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + ".entitlements");
FileAccess *ent_f = FileAccess::open(ent_path, FileAccess::WRITE);
if (ent_f) {
@@ -894,9 +898,22 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (err == OK) {
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < shared_objects.size(); i++) {
- err = da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
+ String src_path = ProjectSettings::get_singleton()->globalize_path(shared_objects[i].path);
+ if (da->dir_exists(src_path)) {
+#ifndef UNIX_ENABLED
+ WARN_PRINT("Relative symlinks are not supported, exported " + src_path.get_file() + " might be broken!");
+#endif
+ print_verbose("export framework: " + src_path + " -> " + tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file());
+ err = da->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file());
+ if (err == OK) {
+ err = da->copy_dir(src_path, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file(), -1, true);
+ }
+ } else {
+ print_verbose("export dylib: " + src_path + " -> " + tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file());
+ err = da->copy(src_path, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file());
+ }
if (err == OK && sign_enabled) {
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file(), ent_path);
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file(), ent_path);
}
}
memdelete(da);
@@ -946,7 +963,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
zlib_filefunc_def io_dst = zipio_create_io_from_file(&dst_f);
zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io_dst);
- _zip_folder_recursive(zip, EditorSettings::get_singleton()->get_cache_dir(), pkg_name + ".app", pkg_name);
+ _zip_folder_recursive(zip, EditorPaths::get_singleton()->get_cache_dir(), pkg_name + ".app", pkg_name);
zipClose(zip, nullptr);
}
@@ -980,7 +997,48 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
if (f == "." || f == "..") {
continue;
}
- if (da->current_is_dir()) {
+ if (da->is_link(f)) {
+ OS::Time time = OS::get_singleton()->get_time();
+ OS::Date date = OS::get_singleton()->get_date();
+
+ zip_fileinfo zipfi;
+ zipfi.tmz_date.tm_hour = time.hour;
+ zipfi.tmz_date.tm_mday = date.day;
+ zipfi.tmz_date.tm_min = time.minute;
+ zipfi.tmz_date.tm_mon = date.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, http://www.cplusplus.com/reference/ctime/tm/
+ zipfi.tmz_date.tm_sec = time.second;
+ zipfi.tmz_date.tm_year = date.year;
+ zipfi.dosDate = 0;
+ // 0120000: symbolic link type
+ // 0000755: permissions rwxr-xr-x
+ // 0000644: permissions rw-r--r--
+ uint32_t _mode = 0120644;
+ zipfi.external_fa = (_mode << 16L) | !(_mode & 0200);
+ zipfi.internal_fa = 0;
+
+ zipOpenNewFileInZip4(p_zip,
+ p_folder.plus_file(f).utf8().get_data(),
+ &zipfi,
+ nullptr,
+ 0,
+ nullptr,
+ 0,
+ nullptr,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION,
+ 0,
+ -MAX_WBITS,
+ DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY,
+ nullptr,
+ 0,
+ 0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
+ 0);
+
+ String target = da->read_link(f);
+ zipWriteInFileInZip(p_zip, target.utf8().get_data(), target.utf8().size());
+ zipCloseFileInZip(p_zip);
+ } else if (da->current_is_dir()) {
_zip_folder_recursive(p_zip, p_root_path, p_folder.plus_file(f), p_pkg_name);
} else {
bool is_executable = (p_folder.ends_with("MacOS") && (f == p_pkg_name));
@@ -991,9 +1049,9 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
zip_fileinfo zipfi;
zipfi.tmz_date.tm_hour = time.hour;
zipfi.tmz_date.tm_mday = date.day;
- zipfi.tmz_date.tm_min = time.min;
+ zipfi.tmz_date.tm_min = time.minute;
zipfi.tmz_date.tm_mon = date.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, http://www.cplusplus.com/reference/ctime/tm/
- zipfi.tmz_date.tm_sec = time.sec;
+ zipfi.tmz_date.tm_sec = time.second;
zipfi.tmz_date.tm_year = date.year;
zipfi.dosDate = 0;
// 0100000: regular file type
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index e6feda5a9b..b65d84d900 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -188,31 +188,45 @@ MainLoop *OS_OSX::get_main_loop() const {
}
String OS_OSX::get_config_path() const {
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
if (has_environment("XDG_CONFIG_HOME")) {
- return get_environment("XDG_CONFIG_HOME");
- } else if (has_environment("HOME")) {
+ if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
+ return get_environment("XDG_CONFIG_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Library/Application Support` or `.` per the XDG Base Directory specification.");
+ }
+ }
+ if (has_environment("HOME")) {
return get_environment("HOME").plus_file("Library/Application Support");
- } else {
- return ".";
}
+ return ".";
}
String OS_OSX::get_data_path() const {
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
if (has_environment("XDG_DATA_HOME")) {
- return get_environment("XDG_DATA_HOME");
- } else {
- return get_config_path();
+ if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
+ return get_environment("XDG_DATA_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification.");
+ }
}
+ return get_config_path();
}
String OS_OSX::get_cache_path() const {
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
if (has_environment("XDG_CACHE_HOME")) {
- return get_environment("XDG_CACHE_HOME");
- } else if (has_environment("HOME")) {
+ if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
+ return get_environment("XDG_CACHE_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Libary/Caches` or `get_config_path()` per the XDG Base Directory specification.");
+ }
+ }
+ if (has_environment("HOME")) {
return get_environment("HOME").plus_file("Library/Caches");
- } else {
- return get_config_path();
}
+ return get_config_path();
}
String OS_OSX::get_bundle_resource_dir() const {
diff --git a/platform/server/SCsub b/platform/server/SCsub
deleted file mode 100644
index 15b9af4d25..0000000000
--- a/platform/server/SCsub
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-
-Import("env")
-
-common_server = [
- "os_server.cpp",
-]
-
-if sys.platform == "darwin":
- common_server.append("#platform/osx/crash_handler_osx.mm")
-else:
- common_server.append("#platform/x11/crash_handler_x11.cpp")
-
-prog = env.add_program("#bin/godot_server", ["godot_server.cpp"] + common_server)
diff --git a/platform/server/detect.py b/platform/server/detect.py
deleted file mode 100644
index 478bcad212..0000000000
--- a/platform/server/detect.py
+++ /dev/null
@@ -1,296 +0,0 @@
-import os
-import platform
-import sys
-
-# This file is mostly based on platform/x11/detect.py.
-# If editing this file, make sure to apply relevant changes here too.
-
-
-def is_active():
- return True
-
-
-def get_name():
- return "Server"
-
-
-def get_program_suffix():
- if sys.platform == "darwin":
- return "osx"
- return "linuxbsd"
-
-
-def can_build():
- if os.name != "posix":
- return False
-
- return True
-
-
-def get_opts():
- from SCons.Variables import BoolVariable, EnumVariable
-
- return [
- BoolVariable("use_llvm", "Use the LLVM compiler", False),
- BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True),
- BoolVariable("use_coverage", "Test Godot coverage", False),
- BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False),
- BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN)", False),
- BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN)", False),
- BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False),
- BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False),
- BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
- BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
- BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", False),
- ]
-
-
-def get_flags():
- return []
-
-
-def configure(env):
-
- ## Build type
-
- if env["target"] == "release":
- if env["optimize"] == "speed": # optimize for speed (default)
- env.Prepend(CCFLAGS=["-O3"])
- elif env["optimize"] == "size": # optimize for size
- env.Prepend(CCFLAGS=["-Os"])
-
- if env["debug_symbols"]:
- env.Prepend(CCFLAGS=["-g2"])
-
- elif env["target"] == "release_debug":
- if env["optimize"] == "speed": # optimize for speed (default)
- env.Prepend(CCFLAGS=["-O2"])
- elif env["optimize"] == "size": # optimize for size
- env.Prepend(CCFLAGS=["-Os"])
- env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
-
- if env["debug_symbols"]:
- env.Prepend(CCFLAGS=["-g2"])
-
- elif env["target"] == "debug":
- env.Prepend(CCFLAGS=["-g3"])
- env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
- env.Append(LINKFLAGS=["-rdynamic"])
-
- ## Architecture
-
- is64 = sys.maxsize > 2 ** 32
- if env["bits"] == "default":
- env["bits"] = "64" if is64 else "32"
-
- ## Compiler configuration
-
- if "CXX" in env and "clang" in os.path.basename(env["CXX"]):
- # Convenience check to enforce the use_llvm overrides when CXX is clang(++)
- env["use_llvm"] = True
-
- if env["use_llvm"]:
- if "clang++" not in os.path.basename(env["CXX"]):
- env["CC"] = "clang"
- env["CXX"] = "clang++"
- env.extra_suffix = ".llvm" + env.extra_suffix
- env.Append(LIBS=["atomic"])
-
- if env["use_coverage"]:
- env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
- env.Append(LINKFLAGS=["-ftest-coverage", "-fprofile-arcs"])
-
- if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"] or env["use_msan"]:
- env.extra_suffix += "s"
-
- if env["use_ubsan"]:
- env.Append(
- CCFLAGS=[
- "-fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin"
- ]
- )
- env.Append(LINKFLAGS=["-fsanitize=undefined"])
- if env["use_llvm"]:
- env.Append(
- CCFLAGS=[
- "-fsanitize=nullability-return,nullability-arg,function,nullability-assign,implicit-integer-sign-change"
- ]
- )
- else:
- env.Append(CCFLAGS=["-fsanitize=bounds-strict"])
-
- if env["use_asan"]:
- env.Append(CCFLAGS=["-fsanitize=address,pointer-subtract,pointer-compare"])
- env.Append(LINKFLAGS=["-fsanitize=address"])
-
- if env["use_lsan"]:
- env.Append(CCFLAGS=["-fsanitize=leak"])
- env.Append(LINKFLAGS=["-fsanitize=leak"])
-
- if env["use_tsan"]:
- env.Append(CCFLAGS=["-fsanitize=thread"])
- env.Append(LINKFLAGS=["-fsanitize=thread"])
-
- if env["use_msan"] and env["use_llvm"]:
- env.Append(CCFLAGS=["-fsanitize=memory"])
- env.Append(CCFLAGS=["-fsanitize-memory-track-origins"])
- env.Append(CCFLAGS=["-fsanitize-recover=memory"])
- env.Append(LINKFLAGS=["-fsanitize=memory"])
-
- if env["use_lto"]:
- env.Append(CCFLAGS=["-flto"])
- if not env["use_llvm"] and env.GetOption("num_jobs") > 1:
- env.Append(LINKFLAGS=["-flto=" + str(env.GetOption("num_jobs"))])
- else:
- env.Append(LINKFLAGS=["-flto"])
- if not env["use_llvm"]:
- env["RANLIB"] = "gcc-ranlib"
- env["AR"] = "gcc-ar"
-
- env.Append(CCFLAGS=["-pipe"])
- env.Append(LINKFLAGS=["-pipe"])
-
- ## Dependencies
-
- # FIXME: Check for existence of the libs before parsing their flags with pkg-config
-
- # freetype depends on libpng and zlib, so bundling one of them while keeping others
- # as shared libraries leads to weird issues
- if (
- env["builtin_freetype"]
- or env["builtin_libpng"]
- or env["builtin_zlib"]
- or env["builtin_graphite"]
- or env["builtin_harfbuzz"]
- ):
- env["builtin_freetype"] = True
- env["builtin_libpng"] = True
- env["builtin_zlib"] = True
- env["builtin_graphite"] = True
- env["builtin_harfbuzz"] = True
-
- if not env["builtin_freetype"]:
- env.ParseConfig("pkg-config freetype2 --cflags --libs")
-
- if not env["builtin_graphite"]:
- env.ParseConfig("pkg-config graphite2 --cflags --libs")
-
- if not env["builtin_icu"]:
- env.ParseConfig("pkg-config icu-uc --cflags --libs")
-
- if not env["builtin_harfbuzz"]:
- env.ParseConfig("pkg-config harfbuzz harfbuzz-icu --cflags --libs")
-
- if not env["builtin_libpng"]:
- env.ParseConfig("pkg-config libpng16 --cflags --libs")
-
- if not env["builtin_bullet"]:
- # We need at least version 2.89
- import subprocess
-
- bullet_version = subprocess.check_output(["pkg-config", "bullet", "--modversion"]).strip()
- if str(bullet_version) < "2.89":
- # Abort as system bullet was requested but too old
- print(
- "Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format(
- bullet_version, "2.89"
- )
- )
- sys.exit(255)
- env.ParseConfig("pkg-config bullet --cflags --libs")
-
- if False: # not env['builtin_assimp']:
- # FIXME: Add min version check
- env.ParseConfig("pkg-config assimp --cflags --libs")
-
- if not env["builtin_enet"]:
- env.ParseConfig("pkg-config libenet --cflags --libs")
-
- if not env["builtin_squish"]:
- env.ParseConfig("pkg-config libsquish --cflags --libs")
-
- if not env["builtin_zstd"]:
- env.ParseConfig("pkg-config libzstd --cflags --libs")
-
- # Sound and video libraries
- # Keep the order as it triggers chained dependencies (ogg needed by others, etc.)
-
- if not env["builtin_libtheora"]:
- env["builtin_libogg"] = False # Needed to link against system libtheora
- env["builtin_libvorbis"] = False # Needed to link against system libtheora
- env.ParseConfig("pkg-config theora theoradec --cflags --libs")
- else:
- list_of_x86 = ["x86_64", "x86", "i386", "i586"]
- if any(platform.machine() in s for s in list_of_x86):
- env["x86_libtheora_opt_gcc"] = True
-
- if not env["builtin_libvpx"]:
- env.ParseConfig("pkg-config vpx --cflags --libs")
-
- if not env["builtin_libvorbis"]:
- env["builtin_libogg"] = False # Needed to link against system libvorbis
- env.ParseConfig("pkg-config vorbis vorbisfile --cflags --libs")
-
- if not env["builtin_opus"]:
- env["builtin_libogg"] = False # Needed to link against system opus
- env.ParseConfig("pkg-config opus opusfile --cflags --libs")
-
- if not env["builtin_libogg"]:
- env.ParseConfig("pkg-config ogg --cflags --libs")
-
- if not env["builtin_libwebp"]:
- env.ParseConfig("pkg-config libwebp --cflags --libs")
-
- if not env["builtin_mbedtls"]:
- # mbedTLS does not provide a pkgconfig config yet. See https://github.com/ARMmbed/mbedtls/issues/228
- env.Append(LIBS=["mbedtls", "mbedcrypto", "mbedx509"])
-
- if not env["builtin_wslay"]:
- env.ParseConfig("pkg-config libwslay --cflags --libs")
-
- if not env["builtin_miniupnpc"]:
- # No pkgconfig file so far, hardcode default paths.
- env.Prepend(CPPPATH=["/usr/include/miniupnpc"])
- env.Append(LIBS=["miniupnpc"])
-
- # On Linux wchar_t should be 32-bits
- # 16-bit library shouldn't be required due to compiler optimisations
- if not env["builtin_pcre2"]:
- env.ParseConfig("pkg-config libpcre2-32 --cflags --libs")
-
- ## Flags
-
- # Linkflags below this line should typically stay the last ones
- if not env["builtin_zlib"]:
- env.ParseConfig("pkg-config zlib --cflags --libs")
-
- env.Prepend(CPPPATH=["#platform/server"])
- env.Append(CPPDEFINES=["SERVER_ENABLED", "UNIX_ENABLED"])
-
- if platform.system() == "Darwin":
- env.Append(
- LINKFLAGS=[
- "-framework",
- "Cocoa",
- "-framework",
- "Carbon",
- "-lz",
- "-framework",
- "IOKit",
- ]
- )
-
- env.Append(LIBS=["pthread"])
-
- if platform.system() == "Linux":
- env.Append(LIBS=["dl"])
-
- if platform.system().find("BSD") >= 0:
- env["execinfo"] = True
-
- if env["execinfo"]:
- env.Append(LIBS=["execinfo"])
-
- # Link those statically for portability
- if env["use_static_cpp"]:
- env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"])
diff --git a/platform/server/godot_server.cpp b/platform/server/godot_server.cpp
deleted file mode 100644
index 1ced95fcbc..0000000000
--- a/platform/server/godot_server.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*************************************************************************/
-/* godot_server.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "main/main.h"
-#include "os_server.h"
-
-int main(int argc, char *argv[]) {
- OS_Server os;
-
- // We must override main when testing is enabled
- TEST_MAIN_OVERRIDE
-
- Error err = Main::setup(argv[0], argc - 1, &argv[1]);
- if (err != OK)
- return 255;
-
- if (Main::start())
- os.run(); // it is actually the OS that decides how to run
- Main::cleanup();
-
- return os.get_exit_code();
-}
diff --git a/platform/server/logo.png b/platform/server/logo.png
deleted file mode 100644
index 8666ada9ca..0000000000
--- a/platform/server/logo.png
+++ /dev/null
Binary files differ
diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp
deleted file mode 100644
index 852ec7c4ef..0000000000
--- a/platform/server/os_server.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/*************************************************************************/
-/* os_server.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "os_server.h"
-
-#include "core/string/print_string.h"
-#include "drivers/dummy/rasterizer_dummy.h"
-#include "drivers/dummy/texture_loader_dummy.h"
-#include "servers/rendering/rendering_server_default.h"
-
-#include "main/main.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-int OS_Server::get_video_driver_count() const {
- return 1;
-}
-
-const char *OS_Server::get_video_driver_name(int p_driver) const {
- return "Dummy";
-}
-
-int OS_Server::get_current_video_driver() const {
- return video_driver_index;
-}
-
-void OS_Server::initialize_core() {
- crash_handler.initialize();
-
- OS_Unix::initialize_core();
-}
-
-Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
- args = OS::get_singleton()->get_cmdline_args();
- current_videomode = p_desired;
- main_loop = nullptr;
-
- RasterizerDummy::make_current();
-
- video_driver_index = p_video_driver; // unused in server platform, but should still be initialized
-
- rendering_server = memnew(RenderingServerDefault);
- rendering_server->init();
-
- AudioDriverManager::initialize(p_audio_driver);
-
- input = memnew(InputDefault);
-
- _ensure_user_data_dir();
-
- resource_loader_dummy.instance();
- ResourceLoader::add_resource_format_loader(resource_loader_dummy);
-
- return OK;
-}
-
-void OS_Server::finalize() {
- if (main_loop)
- memdelete(main_loop);
- main_loop = nullptr;
-
- rendering_server->finish();
- memdelete(rendering_server);
-
- memdelete(input);
-
- ResourceLoader::remove_resource_format_loader(resource_loader_dummy);
- resource_loader_dummy.unref();
-
- args.clear();
-}
-
-void OS_Server::set_mouse_show(bool p_show) {
-}
-
-void OS_Server::set_mouse_grab(bool p_grab) {
- grab = p_grab;
-}
-
-bool OS_Server::is_mouse_grab_enabled() const {
- return grab;
-}
-
-int OS_Server::get_mouse_button_state() const {
- return 0;
-}
-
-Point2 OS_Server::get_mouse_position() const {
- return Point2();
-}
-
-void OS_Server::set_window_title(const String &p_title) {
-}
-
-void OS_Server::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
-}
-
-OS::VideoMode OS_Server::get_video_mode(int p_screen) const {
- return current_videomode;
-}
-
-Size2 OS_Server::get_window_size() const {
- return Vector2(current_videomode.width, current_videomode.height);
-}
-
-void OS_Server::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
-}
-
-MainLoop *OS_Server::get_main_loop() const {
- return main_loop;
-}
-
-void OS_Server::delete_main_loop() {
- if (main_loop)
- memdelete(main_loop);
- main_loop = nullptr;
-}
-
-void OS_Server::set_main_loop(MainLoop *p_main_loop) {
- main_loop = p_main_loop;
- input->set_main_loop(p_main_loop);
-}
-
-String OS_Server::get_name() const {
- return "Server";
-}
-
-void OS_Server::move_window_to_foreground() {
-}
-
-bool OS_Server::_check_internal_feature_support(const String &p_feature) {
- return p_feature == "pc";
-}
-
-void OS_Server::run() {
- force_quit = false;
-
- if (!main_loop)
- return;
-
- main_loop->init();
-
- while (!force_quit) {
- if (Main::iteration())
- break;
- };
-
- main_loop->finish();
-}
-
-String OS_Server::get_config_path() const {
- if (has_environment("XDG_CONFIG_HOME")) {
- return get_environment("XDG_CONFIG_HOME");
- } else if (has_environment("HOME")) {
- return get_environment("HOME").plus_file(".config");
- } else {
- return ".";
- }
-}
-
-String OS_Server::get_data_path() const {
- if (has_environment("XDG_DATA_HOME")) {
- return get_environment("XDG_DATA_HOME");
- } else if (has_environment("HOME")) {
- return get_environment("HOME").plus_file(".local/share");
- } else {
- return get_config_path();
- }
-}
-
-String OS_Server::get_cache_path() const {
- if (has_environment("XDG_CACHE_HOME")) {
- return get_environment("XDG_CACHE_HOME");
- } else if (has_environment("HOME")) {
- return get_environment("HOME").plus_file(".cache");
- } else {
- return get_config_path();
- }
-}
-
-String OS_Server::get_system_dir(SystemDir p_dir) const {
- String xdgparam;
-
- switch (p_dir) {
- case SYSTEM_DIR_DESKTOP: {
- xdgparam = "DESKTOP";
- } break;
- case SYSTEM_DIR_DCIM: {
- xdgparam = "PICTURES";
-
- } break;
- case SYSTEM_DIR_DOCUMENTS: {
- xdgparam = "DOCUMENTS";
-
- } break;
- case SYSTEM_DIR_DOWNLOADS: {
- xdgparam = "DOWNLOAD";
-
- } break;
- case SYSTEM_DIR_MOVIES: {
- xdgparam = "VIDEOS";
-
- } break;
- case SYSTEM_DIR_MUSIC: {
- xdgparam = "MUSIC";
-
- } break;
- case SYSTEM_DIR_PICTURES: {
- xdgparam = "PICTURES";
-
- } break;
- case SYSTEM_DIR_RINGTONES: {
- xdgparam = "MUSIC";
-
- } break;
- }
-
- String pipe;
- List<String> arg;
- arg.push_back(xdgparam);
- Error err = const_cast<OS_Server *>(this)->execute("xdg-user-dir", arg, true, nullptr, &pipe);
- if (err != OK)
- return ".";
- return pipe.strip_edges();
-}
-
-void OS_Server::disable_crash_handler() {
- crash_handler.disable();
-}
-
-bool OS_Server::is_disable_crash_handler() const {
- return crash_handler.is_disabled();
-}
-
-OS_Server::OS_Server() {
- //adriver here
- grab = false;
-};
diff --git a/platform/server/os_server.h b/platform/server/os_server.h
deleted file mode 100644
index 61025fa14b..0000000000
--- a/platform/server/os_server.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*************************************************************************/
-/* os_server.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef OS_SERVER_H
-#define OS_SERVER_H
-
-#include "core/input/input.h"
-#include "drivers/dummy/texture_loader_dummy.h"
-#include "drivers/unix/os_unix.h"
-#ifdef __APPLE__
-#include "platform/osx/crash_handler_osx.h"
-#include "platform/osx/semaphore_osx.h"
-#else
-#include "platform/x11/crash_handler_linuxbsd.h"
-#endif
-#include "servers/audio_server.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering_server.h"
-
-#undef CursorShape
-
-class OS_Server : public OS_Unix {
- RenderingServer *rendering_server = nullptr;
- VideoMode current_videomode;
- List<String> args;
- MainLoop *main_loop = nullptr;
-
- bool grab = false;
-
- virtual void delete_main_loop();
-
- bool force_quit = false;
-
- InputDefault *input = nullptr;
-
- CrashHandler crash_handler;
-
- int video_driver_index = 0;
-
- Ref<ResourceFormatDummyTexture> resource_loader_dummy;
-
-protected:
- virtual int get_video_driver_count() const;
- virtual const char *get_video_driver_name(int p_driver) const;
- virtual int get_current_video_driver() const;
-
- virtual void initialize_core();
- virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
- virtual void finalize();
-
- virtual void set_main_loop(MainLoop *p_main_loop);
-
-public:
- virtual String get_name() const;
-
- virtual void set_mouse_show(bool p_show);
- virtual void set_mouse_grab(bool p_grab);
- virtual bool is_mouse_grab_enabled() const;
- virtual Point2 get_mouse_position() const;
- virtual int get_mouse_button_state() const;
- virtual void set_window_title(const String &p_title);
-
- virtual MainLoop *get_main_loop() const;
-
- virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0);
- virtual VideoMode get_video_mode(int p_screen = 0) const;
- virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const;
-
- virtual Size2 get_window_size() const;
-
- virtual void move_window_to_foreground();
-
- void run();
-
- virtual bool _check_internal_feature_support(const String &p_feature);
-
- virtual String get_config_path() const;
- virtual String get_data_path() const;
- virtual String get_cache_path() const;
-
- virtual String get_system_dir(SystemDir p_dir) const;
-
- void disable_crash_handler();
- bool is_disable_crash_handler() const;
-
- OS_Server();
-};
-
-#endif
diff --git a/platform/server/platform_config.h b/platform/server/platform_config.h
deleted file mode 100644
index 32a19d811b..0000000000
--- a/platform/server/platform_config.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*************************************************************************/
-/* platform_config.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#if defined(__linux__) || defined(__APPLE__)
-#include <alloca.h>
-#endif
-
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
-#include <stdlib.h> // alloca
-// FreeBSD and OpenBSD use pthread_set_name_np, while other platforms,
-// include NetBSD, use pthread_setname_np. NetBSD's version however requires
-// a different format, we handle this directly in thread_posix.
-#ifdef __NetBSD__
-#define PTHREAD_NETBSD_SET_NAME
-#else
-#define PTHREAD_BSD_SET_NAME
-#endif
-#endif
-
-#ifdef __APPLE__
-#define PTHREAD_RENAME_SELF
-#endif
diff --git a/platform/uwp/app.cpp b/platform/uwp/app.cpp
index b7e4361831..67f054aeaa 100644
--- a/platform/uwp/app.cpp
+++ b/platform/uwp/app.cpp
@@ -34,8 +34,8 @@
#include "app.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/os/keyboard.h"
#include "main/main.h"
@@ -333,8 +333,9 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Co
os->input_event(screen_drag);
} else {
// In case the mouse grabbed, MouseMoved will handle this
- if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED)
+ if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED) {
return;
+ }
Ref<InputEventMouseMotion> mouse_motion;
mouse_motion.instance();
@@ -351,8 +352,9 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Co
void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) {
// In case the mouse isn't grabbed, PointerMoved will handle this
- if (os->get_mouse_mode() != OS::MouseMode::MOUSE_MODE_CAPTURED)
+ if (os->get_mouse_mode() != OS::MouseMode::MOUSE_MODE_CAPTURED) {
return;
+ }
Windows::Foundation::Point pos;
pos.X = last_mouse_pos.X + args->MouseDelta.X;
@@ -383,7 +385,7 @@ void App::key_event(Windows::UI::Core::CoreWindow ^ sender, bool p_pressed, Wind
ke.type = OS_UWP::KeyEvent::MessageType::KEY_EVENT_MESSAGE;
ke.unicode = 0;
ke.keycode = KeyMappingWindows::get_keysym((unsigned int)key_args->VirtualKey);
- ke.physical_keycode = KeyMappingWindows::get_scansym((unsigned int)key_args->KeyStatus.ScanCode);
+ ke.physical_keycode = KeyMappingWindows::get_scansym((unsigned int)key_args->KeyStatus.ScanCode, key_args->KeyStatus.IsExtendedKey);
ke.echo = (!p_pressed && !key_args->KeyStatus.IsKeyReleased) || (p_pressed && key_args->KeyStatus.WasKeyDown);
} else {
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 217c119978..1b14aac3da 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -33,11 +33,11 @@
#include "core/config/project_settings.h"
#include "core/core_bind.h"
#include "core/crypto/crypto_core.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/io/zip_io.h"
#include "core/object/class_db.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "core/version.h"
#include "editor/editor_export.h"
#include "editor/editor_node.h"
@@ -567,12 +567,12 @@ void AppxPackager::finish() {
// Create and add block map file
EditorNode::progress_task_step("export", "Creating block map...", 4);
- const String &tmp_blockmap_file_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpblockmap.xml");
+ const String &tmp_blockmap_file_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpblockmap.xml");
make_block_map(tmp_blockmap_file_path);
FileAccess *blockmap_file = FileAccess::open(tmp_blockmap_file_path, FileAccess::READ);
Vector<uint8_t> blockmap_buffer;
- blockmap_buffer.resize(blockmap_file->get_len());
+ blockmap_buffer.resize(blockmap_file->get_length());
blockmap_file->get_buffer(blockmap_buffer.ptrw(), blockmap_buffer.size());
@@ -585,12 +585,12 @@ void AppxPackager::finish() {
EditorNode::progress_task_step("export", "Setting content types...", 5);
- const String &tmp_content_types_file_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpcontenttypes.xml");
+ const String &tmp_content_types_file_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpcontenttypes.xml");
make_content_types(tmp_content_types_file_path);
FileAccess *types_file = FileAccess::open(tmp_content_types_file_path, FileAccess::READ);
Vector<uint8_t> types_buffer;
- types_buffer.resize(types_file->get_len());
+ types_buffer.resize(types_file->get_length());
types_file->get_buffer(types_buffer.ptrw(), types_buffer.size());
@@ -879,7 +879,7 @@ class EditorExportPlatformUWP : public EditorExportPlatform {
return data;
}
- String tmp_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("uwp_tmp_logo.png");
+ String tmp_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("uwp_tmp_logo.png");
Error err = texture->get_image()->save_png(tmp_path);
@@ -900,7 +900,7 @@ class EditorExportPlatformUWP : public EditorExportPlatform {
ERR_FAIL_V_MSG(data, err_string);
}
- data.resize(f->get_len());
+ data.resize(f->get_length());
f->get_buffer(data.ptrw(), data.size());
f->close();
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 2314a392cc..65934b6681 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -400,14 +400,12 @@ void OS_UWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, Gyrom
void OS_UWP::set_mouse_mode(MouseMode p_mode) {
if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) {
CoreWindow::GetForCurrentThread()->SetPointerCapture();
-
} else {
CoreWindow::GetForCurrentThread()->ReleasePointerCapture();
}
- if (p_mode == MouseMode::MOUSE_MODE_CAPTURED || p_mode == MouseMode::MOUSE_MODE_HIDDEN) {
+ if (p_mode == MouseMode::MOUSE_MODE_HIDDEN || p_mode == MouseMode::MOUSE_MODE_CAPTURED || p_mode == MouseMode::MOUSE_MODE_CONFINED_HIDDEN) {
CoreWindow::GetForCurrentThread()->PointerCursor = nullptr;
-
} else {
CoreWindow::GetForCurrentThread()->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
}
@@ -565,9 +563,9 @@ void OS_UWP::process_key_events() {
Ref<InputEventKey> key_event;
key_event.instance();
- key_event->set_alt(kev.alt);
- key_event->set_shift(kev.shift);
- key_event->set_control(kev.control);
+ key_event->set_alt_pressed(kev.alt);
+ key_event->set_shift_pressed(kev.shift);
+ key_event->set_ctrl_pressed(kev.control);
key_event->set_echo(kev.echo);
key_event->set_keycode(kev.keycode);
key_event->set_physical_keycode(kev.physical_keycode);
diff --git a/platform/windows/context_gl_windows.cpp b/platform/windows/context_gl_windows.cpp
index 207b0a1168..7cf9738f13 100644
--- a/platform/windows/context_gl_windows.cpp
+++ b/platform/windows/context_gl_windows.cpp
@@ -94,7 +94,7 @@ void ContextGL_Windows::swap_buffers() {
if (vsync_via_compositor_now != vsync_via_compositor) {
// The previous frame had a different operating mode than this
- // frame. Set the 'vsync_via_compositor' member variable and the
+ // frame. Set the 'vsync_via_compositor' member variable and the
// OpenGL swap interval to their proper values.
set_use_vsync(true);
}
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 4b859da340..f16595f379 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -84,7 +84,8 @@ void DisplayServerWindows::alert(const String &p_alert, const String &p_title) {
}
void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
- if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED) {
+ if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
+ // Mouse is grabbed (captured or confined).
WindowData &wd = windows[MAIN_WINDOW_ID];
RECT clipRect;
@@ -100,11 +101,12 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
SetCapture(wd.hWnd);
}
} else {
+ // Mouse is free to move around (not captured or confined).
ReleaseCapture();
ClipCursor(nullptr);
}
- if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) {
+ if (p_mode == MOUSE_MODE_HIDDEN || p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
if (hCursor == nullptr) {
hCursor = SetCursor(nullptr);
} else {
@@ -715,7 +717,7 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window
MoveWindow(wd.hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
#endif
// Don't let the mouse leave the window when moved
- if (mouse_mode == MOUSE_MODE_CONFINED) {
+ if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
RECT rect;
GetClientRect(wd.hWnd, &rect);
ClientToScreen(wd.hWnd, (POINT *)&rect.left);
@@ -841,7 +843,7 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
MoveWindow(wd.hWnd, rect.left, rect.top, w, h, TRUE);
// Don't let the mouse leave the window when resizing to a smaller resolution
- if (mouse_mode == MOUSE_MODE_CONFINED) {
+ if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
RECT crect;
GetClientRect(wd.hWnd, &crect);
ClientToScreen(wd.hWnd, (POINT *)&crect.left);
@@ -1119,7 +1121,7 @@ bool DisplayServerWindows::window_can_draw(WindowID p_window) const {
ERR_FAIL_COND_V(!windows.has(p_window), false);
const WindowData &wd = windows[p_window];
- return wd.minimized;
+ return !wd.minimized;
}
bool DisplayServerWindows::can_any_window_draw() const {
@@ -1889,7 +1891,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
// Run a timer to prevent event catching warning if the focused window is closing.
windows[window_id].focus_timer_id = SetTimer(windows[window_id].hWnd, 2, USER_TIMER_MINIMUM, (TIMERPROC) nullptr);
}
- return 0; // Return To The Message Loop
+ return 0; // Return To The Message Loop
}
case WM_GETMINMAXINFO: {
if (windows[window_id].resizable && !windows[window_id].fullscreen) {
@@ -1966,9 +1968,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm.instance();
mm->set_window_id(window_id);
- mm->set_control(control_mem);
- mm->set_shift(shift_mem);
- mm->set_alt(alt_mem);
+ mm->set_ctrl_pressed(control_mem);
+ mm->set_shift_pressed(shift_mem);
+ mm->set_alt_pressed(alt_mem);
mm->set_pressure((raw->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN) ? 1.0f : 0.0f);
@@ -2062,9 +2064,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
Ref<InputEventMouseMotion> mm;
mm.instance();
mm->set_window_id(window_id);
- mm->set_control(GetKeyState(VK_CONTROL) < 0);
- mm->set_shift(GetKeyState(VK_SHIFT) < 0);
- mm->set_alt(alt_mem);
+ mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
+ mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
+ mm->set_alt_pressed(alt_mem);
mm->set_pressure(windows[window_id].last_pressure);
mm->set_tilt(windows[window_id].last_tilt);
@@ -2189,8 +2191,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
// Don't calculate relative mouse movement if we don't have focus in CAPTURED mode.
- if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED)
+ if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) {
break;
+ }
Ref<InputEventMouseMotion> mm;
mm.instance();
@@ -2205,9 +2208,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_tilt(Vector2((float)pen_info.tiltX / 90, (float)pen_info.tiltY / 90));
}
- mm->set_control(GetKeyState(VK_CONTROL) < 0);
- mm->set_shift(GetKeyState(VK_SHIFT) < 0);
- mm->set_alt(alt_mem);
+ mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
+ mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
+ mm->set_alt_pressed(alt_mem);
mm->set_button_mask(last_button_state);
@@ -2294,15 +2297,16 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
// Don't calculate relative mouse movement if we don't have focus in CAPTURED mode.
- if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED)
+ if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) {
break;
+ }
Ref<InputEventMouseMotion> mm;
mm.instance();
mm->set_window_id(window_id);
- mm->set_control((wParam & MK_CONTROL) != 0);
- mm->set_shift((wParam & MK_SHIFT) != 0);
- mm->set_alt(alt_mem);
+ mm->set_ctrl_pressed((wParam & MK_CONTROL) != 0);
+ mm->set_shift_pressed((wParam & MK_SHIFT) != 0);
+ mm->set_alt_pressed(alt_mem);
if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
// Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not updated recently.
@@ -2427,20 +2431,23 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
case WM_MOUSEWHEEL: {
mb->set_pressed(true);
int motion = (short)HIWORD(wParam);
- if (!motion)
+ if (!motion) {
return 0;
+ }
- if (motion > 0)
+ if (motion > 0) {
mb->set_button_index(MOUSE_BUTTON_WHEEL_UP);
- else
+ } else {
mb->set_button_index(MOUSE_BUTTON_WHEEL_DOWN);
+ }
} break;
case WM_MOUSEHWHEEL: {
mb->set_pressed(true);
int motion = (short)HIWORD(wParam);
- if (!motion)
+ if (!motion) {
return 0;
+ }
if (motion < 0) {
mb->set_button_index(MOUSE_BUTTON_WHEEL_LEFT);
@@ -2452,24 +2459,27 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
} break;
case WM_XBUTTONDOWN: {
mb->set_pressed(true);
- if (HIWORD(wParam) == XBUTTON1)
+ if (HIWORD(wParam) == XBUTTON1) {
mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
- else
+ } else {
mb->set_button_index(MOUSE_BUTTON_XBUTTON2);
+ }
} break;
case WM_XBUTTONUP: {
mb->set_pressed(false);
- if (HIWORD(wParam) == XBUTTON1)
+ if (HIWORD(wParam) == XBUTTON1) {
mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
- else
+ } else {
mb->set_button_index(MOUSE_BUTTON_XBUTTON2);
+ }
} break;
case WM_XBUTTONDBLCLK: {
mb->set_pressed(true);
- if (HIWORD(wParam) == XBUTTON1)
+ if (HIWORD(wParam) == XBUTTON1) {
mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
- else
+ } else {
mb->set_button_index(MOUSE_BUTTON_XBUTTON2);
+ }
mb->set_double_click(true);
} break;
default: {
@@ -2477,14 +2487,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- mb->set_control((wParam & MK_CONTROL) != 0);
- mb->set_shift((wParam & MK_SHIFT) != 0);
- mb->set_alt(alt_mem);
- //mb->get_alt()=(wParam&MK_MENU)!=0;
- if (mb->is_pressed())
+ mb->set_ctrl_pressed((wParam & MK_CONTROL) != 0);
+ mb->set_shift_pressed((wParam & MK_SHIFT) != 0);
+ mb->set_alt_pressed(alt_mem);
+ //mb->is_alt_pressed()=(wParam&MK_MENU)!=0;
+ if (mb->is_pressed()) {
last_button_state |= (1 << (mb->get_button_index() - 1));
- else
+ } else {
last_button_state &= ~(1 << (mb->get_button_index() - 1));
+ }
mb->set_button_mask(last_button_state);
mb->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
@@ -2726,7 +2737,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
} break;
case WM_SETCURSOR: {
if (LOWORD(lParam) == HTCLIENT) {
- if (windows[window_id].window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) {
+ if (windows[window_id].window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN)) {
//Hide the cursor
if (hCursor == nullptr) {
hCursor = SetCursor(nullptr);
@@ -2835,17 +2846,17 @@ void DisplayServerWindows::_process_key_events() {
k.instance();
k->set_window_id(ke.window_id);
- k->set_shift(ke.shift);
- k->set_alt(ke.alt);
- k->set_control(ke.control);
- k->set_metakey(ke.meta);
+ k->set_shift_pressed(ke.shift);
+ k->set_alt_pressed(ke.alt);
+ k->set_ctrl_pressed(ke.control);
+ k->set_meta_pressed(ke.meta);
k->set_pressed(true);
k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam));
k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)));
k->set_unicode(unicode);
if (k->get_unicode() && gr_mem) {
- k->set_alt(false);
- k->set_control(false);
+ k->set_alt_pressed(false);
+ k->set_ctrl_pressed(false);
}
if (k->get_unicode() < 32)
@@ -2862,10 +2873,10 @@ void DisplayServerWindows::_process_key_events() {
k.instance();
k->set_window_id(ke.window_id);
- k->set_shift(ke.shift);
- k->set_alt(ke.alt);
- k->set_control(ke.control);
- k->set_metakey(ke.meta);
+ k->set_shift_pressed(ke.shift);
+ k->set_alt_pressed(ke.alt);
+ k->set_ctrl_pressed(ke.control);
+ k->set_meta_pressed(ke.meta);
k->set_pressed(ke.uMsg == WM_KEYDOWN);
@@ -2900,8 +2911,8 @@ void DisplayServerWindows::_process_key_events() {
k->set_unicode(unicode);
}
if (k->get_unicode() && gr_mem) {
- k->set_alt(false);
- k->set_control(false);
+ k->set_alt_pressed(false);
+ k->set_ctrl_pressed(false);
}
if (k->get_unicode() < 32)
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 222597b3ff..803d9371f5 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#include "editor/editor_export.h"
#include "editor/editor_node.h"
diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis
index 857c6a88f1..bb855e4ac8 100644
--- a/platform/windows/godot.natvis
+++ b/platform/windows/godot.natvis
@@ -40,13 +40,13 @@
<DisplayString Condition="type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString>
<DisplayString Condition="type == Variant::AABB">{_data._aabb}</DisplayString>
<DisplayString Condition="type == Variant::BASIS">{_data._basis}</DisplayString>
- <DisplayString Condition="type == Variant::TRANSFORM">{_data._transform}</DisplayString>
+ <DisplayString Condition="type == Variant::TRANSFORM3D">{_data._transform}</DisplayString>
<DisplayString Condition="type == Variant::STRING">{*(String *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::RECT2">{*(Rect2 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::VECTOR3">{*(Vector3 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::QUAT">{*(Quat *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::QUATERNION">{*(Quaternion *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::NODE_PATH">{*(NodePath *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::RID">{*(::RID *)_data._mem}</DisplayString>
@@ -72,13 +72,13 @@
<Item Name="[value]" Condition="type == Variant::TRANSFORM2D">_data._transform2d</Item>
<Item Name="[value]" Condition="type == Variant::AABB">_data._aabb</Item>
<Item Name="[value]" Condition="type == Variant::BASIS">_data._basis</Item>
- <Item Name="[value]" Condition="type == Variant::TRANSFORM">_data._transform</Item>
+ <Item Name="[value]" Condition="type == Variant::TRANSFORM3D">_data._transform</Item>
<Item Name="[value]" Condition="type == Variant::STRING">*(String *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::RECT2">*(Rect2 *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::VECTOR3">*(Vector3 *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::PLANE">*(Plane *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::QUAT">*(Quat *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::QUATERNION">*(Quaternion *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::COLOR">*(Color *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::NODE_PATH">*(NodePath *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::RID">*(::RID *)_data._mem</Item>
@@ -128,8 +128,8 @@
</Expand>
</Type>
- <Type Name="Quat">
- <DisplayString>Quat {{{x},{y},{z},{w}}}</DisplayString>
+ <Type Name="Quaternion">
+ <DisplayString>Quaternion {{{x},{y},{z},{w}}}</DisplayString>
<Expand>
<Item Name="x">x</Item>
<Item Name="y">y</Item>
diff --git a/platform/windows/key_mapping_windows.cpp b/platform/windows/key_mapping_windows.cpp
index 3312c91932..c367c69826 100644
--- a/platform/windows/key_mapping_windows.cpp
+++ b/platform/windows/key_mapping_windows.cpp
@@ -47,7 +47,7 @@ static _WinTranslatePair _vk_to_keycode[] = {
{ KEY_SHIFT, VK_SHIFT }, //(0x10)
- { KEY_CONTROL, VK_CONTROL }, //(0x11)
+ { KEY_CTRL, VK_CONTROL }, //(0x11)
{ KEY_ALT, VK_MENU }, //(0x12)
@@ -166,8 +166,8 @@ static _WinTranslatePair _vk_to_keycode[] = {
{ KEY_SCROLLLOCK, VK_SCROLL }, // (0x91)
{ KEY_SHIFT, VK_LSHIFT }, // (0xA0)
{ KEY_SHIFT, VK_RSHIFT }, // (0xA1)
- { KEY_CONTROL, VK_LCONTROL }, // (0xA2)
- { KEY_CONTROL, VK_RCONTROL }, // (0xA3)
+ { KEY_CTRL, VK_LCONTROL }, // (0xA2)
+ { KEY_CTRL, VK_RCONTROL }, // (0xA3)
{ KEY_MENU, VK_LMENU }, // (0xA4)
{ KEY_MENU, VK_RMENU }, // (0xA5)
@@ -265,7 +265,7 @@ static _WinTranslatePair _scancode_to_keycode[] = {
{ KEY_BRACELEFT, 0x1A },
{ KEY_BRACERIGHT, 0x1B },
{ KEY_ENTER, 0x1C },
- { KEY_CONTROL, 0x1D },
+ { KEY_CTRL, 0x1D },
{ KEY_A, 0x1E },
{ KEY_S, 0x1F },
{ KEY_D, 0x20 },
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index f517190a89..c956fe49ae 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -315,8 +315,8 @@ OS::Time OS_Windows::get_time(bool utc) const {
Time time;
time.hour = systemtime.wHour;
- time.min = systemtime.wMinute;
- time.sec = systemtime.wSecond;
+ time.minute = systemtime.wMinute;
+ time.second = systemtime.wSecond;
return time;
}
@@ -631,31 +631,45 @@ MainLoop *OS_Windows::get_main_loop() const {
}
String OS_Windows::get_config_path() const {
- if (has_environment("XDG_CONFIG_HOME")) { // unlikely, but after all why not?
- return get_environment("XDG_CONFIG_HOME");
- } else if (has_environment("APPDATA")) {
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
+ if (has_environment("XDG_CONFIG_HOME")) {
+ if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
+ return get_environment("XDG_CONFIG_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `%APPDATA%` or `.` per the XDG Base Directory specification.");
+ }
+ }
+ if (has_environment("APPDATA")) {
return get_environment("APPDATA");
- } else {
- return ".";
}
+ return ".";
}
String OS_Windows::get_data_path() const {
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
if (has_environment("XDG_DATA_HOME")) {
- return get_environment("XDG_DATA_HOME");
- } else {
- return get_config_path();
+ if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
+ return get_environment("XDG_DATA_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification.");
+ }
}
+ return get_config_path();
}
String OS_Windows::get_cache_path() const {
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
if (has_environment("XDG_CACHE_HOME")) {
- return get_environment("XDG_CACHE_HOME");
- } else if (has_environment("TEMP")) {
+ if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
+ return get_environment("XDG_CACHE_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%TEMP%` or `get_config_path()` per the XDG Base Directory specification.");
+ }
+ }
+ if (has_environment("TEMP")) {
return get_environment("TEMP");
- } else {
- return get_config_path();
}
+ return get_config_path();
}
// Get properly capitalized engine name for system paths
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 9dfdd7bd0e..597693aa6a 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -118,7 +118,7 @@ void Area2D::_body_enter_tree(ObjectID p_id) {
E->get().in_tree = true;
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
}
@@ -132,7 +132,7 @@ void Area2D::_body_exit_tree(ObjectID p_id) {
E->get().in_tree = false;
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
}
@@ -154,6 +154,7 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
if (body_in) {
if (!E) {
E = body_map.insert(objid, BodyState());
+ E->get().rid = p_body;
E->get().rc = 0;
E->get().in_tree = node && node->is_inside_tree();
if (node) {
@@ -170,7 +171,7 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
}
if (!node || E->get().in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape);
}
} else {
@@ -192,7 +193,7 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
}
}
if (!node || in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape);
}
}
@@ -211,7 +212,7 @@ void Area2D::_area_enter_tree(ObjectID p_id) {
E->get().in_tree = true;
emit_signal(SceneStringNames::get_singleton()->area_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
}
@@ -225,7 +226,7 @@ void Area2D::_area_exit_tree(ObjectID p_id) {
E->get().in_tree = false;
emit_signal(SceneStringNames::get_singleton()->area_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
}
@@ -246,6 +247,7 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
if (area_in) {
if (!E) {
E = area_map.insert(objid, AreaState());
+ E->get().rid = p_area;
E->get().rc = 0;
E->get().in_tree = node && node->is_inside_tree();
if (node) {
@@ -262,7 +264,7 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
}
if (!node || E->get().in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, objid, node, p_area_shape, p_self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape);
}
} else {
@@ -284,7 +286,7 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
}
}
if (!node || in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, obj, p_area_shape, p_self_shape);
}
}
@@ -315,7 +317,7 @@ void Area2D::_clear_monitoring() {
}
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->key(), node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
@@ -343,7 +345,7 @@ void Area2D::_clear_monitoring() {
}
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->key(), node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
@@ -532,13 +534,13 @@ void Area2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout);
ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout);
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D")));
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D")));
- ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D")));
ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D")));
@@ -551,7 +553,7 @@ void Area2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_vec"), "set_gravity_vector", "get_gravity_vector");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.001"), "set_gravity", "get_gravity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-4096,4096,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
@@ -568,7 +570,7 @@ void Area2D::_bind_methods() {
Area2D::Area2D() :
CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) {
- set_gravity(98);
+ set_gravity(980);
set_gravity_vector(Vector2(0, 1));
set_monitoring(true);
set_monitorable(true);
diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h
index d6fcb2c2a5..2c29e4660d 100644
--- a/scene/2d/area_2d.h
+++ b/scene/2d/area_2d.h
@@ -83,6 +83,7 @@ private:
};
struct BodyState {
+ RID rid;
int rc = 0;
bool in_tree = false;
VSet<ShapePair> shapes;
@@ -114,6 +115,7 @@ private:
};
struct AreaState {
+ RID rid;
int rc = 0;
bool in_tree = false;
VSet<AreaShapePair> shapes;
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 01045502d5..ca4b8d72a1 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -270,11 +270,10 @@ void Camera2D::_notification(int p_what) {
}
if (screen_drawing_enabled) {
- Color area_axis_color(0.5, 0.42, 0.87, 0.63);
+ Color area_axis_color(1, 0.4, 1, 0.63);
real_t area_axis_width = 1;
if (is_current()) {
area_axis_width = 3;
- area_axis_color.a = 0.83;
}
Transform2D inv_camera_transform = get_camera_transform().affine_inverse();
@@ -295,10 +294,9 @@ void Camera2D::_notification(int p_what) {
}
if (limit_drawing_enabled) {
- Color limit_drawing_color(1, 1, 0, 0.63);
+ Color limit_drawing_color(1, 1, 0.25, 0.63);
real_t limit_drawing_width = 1;
if (is_current()) {
- limit_drawing_color.a = 0.83;
limit_drawing_width = 3;
}
@@ -317,11 +315,10 @@ void Camera2D::_notification(int p_what) {
}
if (margin_drawing_enabled) {
- Color margin_drawing_color(0, 1, 1, 0.63);
+ Color margin_drawing_color(0.25, 1, 1, 0.63);
real_t margin_drawing_width = 1;
if (is_current()) {
margin_drawing_width = 3;
- margin_drawing_color.a = 0.83;
}
Transform2D inv_camera_transform = get_camera_transform().affine_inverse();
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index de648d404c..a633923be7 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -408,6 +408,10 @@ void CollisionObject2D::set_only_update_transform_changes(bool p_enable) {
only_update_transform_changes = p_enable;
}
+bool CollisionObject2D::is_only_update_transform_changes_enabled() const {
+ return only_update_transform_changes;
+}
+
void CollisionObject2D::_update_pickable() {
if (!is_inside_tree()) {
return;
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index bb1a9dfcf5..e10f3097d9 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -62,7 +62,7 @@ class CollisionObject2D : public Node2D {
int total_subshapes = 0;
Map<uint32_t, ShapeData> shapes;
- bool only_update_transform_changes = false; //this is used for sync physics in KinematicBody
+ bool only_update_transform_changes = false; //this is used for sync physics in CharacterBody2D
protected:
CollisionObject2D(RID p_rid, bool p_area);
@@ -77,6 +77,7 @@ protected:
void _mouse_exit();
void set_only_update_transform_changes(bool p_enable);
+ bool is_only_update_transform_changes_enabled() const;
public:
void set_collision_layer(uint32_t p_layer);
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index a69ef73a54..2a2fde80e2 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -244,7 +244,7 @@ TypedArray<String> CollisionPolygon2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject2D>(get_parent())) {
- warnings.push_back(TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."));
+ warnings.push_back(TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape."));
}
int polygon_count = polygon.size();
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index d9009ef85c..60780f1cc3 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -181,7 +181,7 @@ TypedArray<String> CollisionShape2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject2D>(get_parent())) {
- warnings.push_back(TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."));
+ warnings.push_back(TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape."));
}
if (!shape.is_valid()) {
warnings.push_back(TTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!"));
diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index ba34a0f45d..92b8be77cf 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -169,7 +169,7 @@ private:
Vector<Color> emission_colors;
int emission_point_count = 0;
- Vector2 gravity = Vector2(0, 98);
+ Vector2 gravity = Vector2(0, 980);
void _update_internal();
void _particles_process(float p_delta);
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index 774a194e39..d7404ff479 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -115,7 +115,7 @@ void GPUParticles2D::set_use_local_coordinates(bool p_enable) {
void GPUParticles2D::_update_particle_emission_transform() {
Transform2D xf2d = get_global_transform();
- Transform xf;
+ Transform3D xf;
xf.basis.set_axis(0, Vector3(xf2d.get_axis(0).x, xf2d.get_axis(0).y, 0));
xf.basis.set_axis(1, Vector3(xf2d.get_axis(1).x, xf2d.get_axis(1).y, 0));
xf.set_origin(Vector3(xf2d.get_origin().x, xf2d.get_origin().y, 0));
@@ -140,6 +140,62 @@ void GPUParticles2D::set_process_material(const Ref<Material> &p_material) {
update_configuration_warnings();
}
+void GPUParticles2D::set_trail_enabled(bool p_enabled) {
+ trail_enabled = p_enabled;
+ RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length);
+ update_configuration_warnings();
+ update();
+
+ RS::get_singleton()->particles_set_transform_align(particles, p_enabled ? RS::PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY : RS::PARTICLES_TRANSFORM_ALIGN_DISABLED);
+}
+void GPUParticles2D::set_trail_length(float p_seconds) {
+ ERR_FAIL_COND(p_seconds < 0.001);
+ trail_length = p_seconds;
+ RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length);
+ update();
+}
+
+void GPUParticles2D::set_trail_sections(int p_sections) {
+ ERR_FAIL_COND(p_sections < 2);
+ ERR_FAIL_COND(p_sections > 128);
+
+ trail_sections = p_sections;
+ update();
+}
+void GPUParticles2D::set_trail_section_subdivisions(int p_subdivisions) {
+ ERR_FAIL_COND(trail_section_subdivisions < 1);
+ ERR_FAIL_COND(trail_section_subdivisions > 1024);
+
+ trail_section_subdivisions = p_subdivisions;
+ update();
+}
+
+bool GPUParticles2D::is_trail_enabled() const {
+ return trail_enabled;
+}
+float GPUParticles2D::get_trail_length() const {
+ return trail_length;
+}
+
+void GPUParticles2D::_update_collision_size() {
+ float csize = collision_base_size;
+
+ if (texture.is_valid()) {
+ csize *= (texture->get_width() + texture->get_height()) / 4.0; //half size since its a radius
+ }
+
+ RS::get_singleton()->particles_set_collision_base_size(particles, csize);
+}
+
+void GPUParticles2D::set_collision_base_size(float p_size) {
+ collision_base_size = p_size;
+ _update_collision_size();
+}
+
+float GPUParticles2D::get_collision_base_size() const {
+ return collision_base_size;
+}
+
void GPUParticles2D::set_speed_scale(float p_scale) {
speed_scale = p_scale;
RS::get_singleton()->particles_set_speed_scale(particles, p_scale);
@@ -157,6 +213,13 @@ float GPUParticles2D::get_lifetime() const {
return lifetime;
}
+int GPUParticles2D::get_trail_sections() const {
+ return trail_sections;
+}
+int GPUParticles2D::get_trail_section_subdivisions() const {
+ return trail_section_subdivisions;
+}
+
bool GPUParticles2D::get_one_shot() const {
return one_shot;
}
@@ -253,6 +316,7 @@ Rect2 GPUParticles2D::capture_rect() const {
void GPUParticles2D::set_texture(const Ref<Texture2D> &p_texture) {
texture = p_texture;
+ _update_collision_size();
update();
}
@@ -271,10 +335,119 @@ void GPUParticles2D::restart() {
void GPUParticles2D::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
RID texture_rid;
+ Size2 size;
if (texture.is_valid()) {
texture_rid = texture->get_rid();
+ size = texture->get_size();
+ } else {
+ size = Size2(1, 1);
}
+ if (trail_enabled) {
+ RS::get_singleton()->mesh_clear(mesh);
+ PackedVector2Array points;
+ PackedVector2Array uvs;
+ PackedInt32Array bone_indices;
+ PackedFloat32Array bone_weights;
+ PackedInt32Array indices;
+
+ int total_segments = trail_sections * trail_section_subdivisions;
+ float depth = size.height * trail_sections;
+
+ for (int j = 0; j <= total_segments; j++) {
+ float v = j;
+ v /= total_segments;
+
+ float y = depth * v;
+ y = (depth * 0.5) - y;
+
+ int bone = j / trail_section_subdivisions;
+ float blend = 1.0 - float(j % trail_section_subdivisions) / float(trail_section_subdivisions);
+
+ float s = size.width;
+
+ points.push_back(Vector2(-s * 0.5, 0));
+ points.push_back(Vector2(+s * 0.5, 0));
+
+ uvs.push_back(Vector2(0, v));
+ uvs.push_back(Vector2(1, v));
+
+ for (int i = 0; i < 2; i++) {
+ bone_indices.push_back(bone);
+ bone_indices.push_back(MIN(trail_sections, bone + 1));
+ bone_indices.push_back(0);
+ bone_indices.push_back(0);
+
+ bone_weights.push_back(blend);
+ bone_weights.push_back(1.0 - blend);
+ bone_weights.push_back(0);
+ bone_weights.push_back(0);
+ }
+
+ if (j > 0) {
+ int base = j * 2 - 2;
+ indices.push_back(base + 0);
+ indices.push_back(base + 1);
+ indices.push_back(base + 2);
+
+ indices.push_back(base + 1);
+ indices.push_back(base + 3);
+ indices.push_back(base + 2);
+ }
+ }
+
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ arr[RS::ARRAY_VERTEX] = points;
+ arr[RS::ARRAY_TEX_UV] = uvs;
+ arr[RS::ARRAY_BONES] = bone_indices;
+ arr[RS::ARRAY_WEIGHTS] = bone_weights;
+ arr[RS::ARRAY_INDEX] = indices;
+
+ RS::get_singleton()->mesh_add_surface_from_arrays(mesh, RS::PRIMITIVE_TRIANGLES, arr, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
+
+ Vector<Transform3D> xforms;
+ for (int i = 0; i <= trail_sections; i++) {
+ Transform3D xform;
+ /*
+ xform.origin.y = depth / 2.0 - size.height * float(i);
+ xform.origin.y = -xform.origin.y; //bind is an inverse transform, so negate y */
+ xforms.push_back(xform);
+ }
+
+ RS::get_singleton()->particles_set_trail_bind_poses(particles, xforms);
+
+ } else {
+ RS::get_singleton()->mesh_clear(mesh);
+ Vector<Vector2> points;
+ points.resize(4);
+ points.write[0] = Vector2(-size.x / 2.0, -size.y / 2.0);
+ points.write[1] = Vector2(size.x / 2.0, -size.y / 2.0);
+ points.write[2] = Vector2(size.x / 2.0, size.y / 2.0);
+ points.write[3] = Vector2(-size.x / 2.0, size.y / 2.0);
+ Vector<Vector2> uvs;
+ uvs.resize(4);
+ uvs.write[0] = Vector2(0, 0);
+ uvs.write[1] = Vector2(1, 0);
+ uvs.write[2] = Vector2(1, 1);
+ uvs.write[3] = Vector2(0, 1);
+ Vector<int> indices;
+ indices.resize(6);
+ indices.write[0] = 0;
+ indices.write[1] = 1;
+ indices.write[2] = 2;
+ indices.write[3] = 0;
+ indices.write[4] = 2;
+ indices.write[5] = 3;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ arr[RS::ARRAY_VERTEX] = points;
+ arr[RS::ARRAY_TEX_UV] = uvs;
+ arr[RS::ARRAY_INDEX] = indices;
+
+ RS::get_singleton()->mesh_add_surface_from_arrays(mesh, RS::PRIMITIVE_TRIANGLES, arr, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
+ RS::get_singleton()->particles_set_trail_bind_poses(particles, Vector<Transform3D>());
+ }
RS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid);
#ifdef TOOLS_ENABLED
@@ -318,6 +491,7 @@ void GPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &GPUParticles2D::set_fractional_delta);
ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles2D::set_process_material);
ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles2D::set_speed_scale);
+ ClassDB::bind_method(D_METHOD("set_collision_base_size", "size"), &GPUParticles2D::set_collision_base_size);
ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles2D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles2D::get_amount);
@@ -332,6 +506,7 @@ void GPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_fractional_delta"), &GPUParticles2D::get_fractional_delta);
ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles2D::get_process_material);
ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles2D::get_speed_scale);
+ ClassDB::bind_method(D_METHOD("get_collision_base_size"), &GPUParticles2D::get_collision_base_size);
ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles2D::set_draw_order);
ClassDB::bind_method(D_METHOD("get_draw_order"), &GPUParticles2D::get_draw_order);
@@ -343,6 +518,18 @@ void GPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("restart"), &GPUParticles2D::restart);
+ ClassDB::bind_method(D_METHOD("set_trail_enabled", "enabled"), &GPUParticles2D::set_trail_enabled);
+ ClassDB::bind_method(D_METHOD("set_trail_length", "secs"), &GPUParticles2D::set_trail_length);
+
+ ClassDB::bind_method(D_METHOD("is_trail_enabled"), &GPUParticles2D::is_trail_enabled);
+ ClassDB::bind_method(D_METHOD("get_trail_length"), &GPUParticles2D::get_trail_length);
+
+ ClassDB::bind_method(D_METHOD("set_trail_sections", "sections"), &GPUParticles2D::set_trail_sections);
+ ClassDB::bind_method(D_METHOD("get_trail_sections"), &GPUParticles2D::get_trail_sections);
+
+ ClassDB::bind_method(D_METHOD("set_trail_section_subdivisions", "subdivisions"), &GPUParticles2D::set_trail_section_subdivisions);
+ ClassDB::bind_method(D_METHOD("get_trail_section_subdivisions"), &GPUParticles2D::get_trail_section_subdivisions);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
@@ -354,10 +541,17 @@ void GPUParticles2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
+ ADD_GROUP("Collision", "collision_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_collision_base_size", "get_collision_base_size");
ADD_GROUP("Drawing", "");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "visibility_rect"), "set_visibility_rect", "get_visibility_rect");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime"), "set_draw_order", "get_draw_order");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,Reverse Lifetime"), "set_draw_order", "get_draw_order");
+ ADD_GROUP("Trails", "trail_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_trail_enabled", "is_trail_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_trail_length", "get_trail_length");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_trail_sections", "get_trail_sections");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_section_subdivisions", PROPERTY_HINT_RANGE, "1,1024,1"), "set_trail_section_subdivisions", "get_trail_section_subdivisions");
ADD_GROUP("Process Material", "process_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material");
ADD_GROUP("Textures", "");
@@ -365,12 +559,17 @@ void GPUParticles2D::_bind_methods() {
BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX);
BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME);
+ BIND_ENUM_CONSTANT(DRAW_ORDER_REVERSE_LIFETIME);
}
GPUParticles2D::GPUParticles2D() {
particles = RS::get_singleton()->particles_create();
RS::get_singleton()->particles_set_mode(particles, RS::PARTICLES_MODE_2D);
+ mesh = RS::get_singleton()->mesh_create();
+ RS::get_singleton()->particles_set_draw_passes(particles, 1);
+ RS::get_singleton()->particles_set_draw_pass_mesh(particles, 0, mesh);
+
one_shot = false; // Needed so that set_emitting doesn't access uninitialized values
set_emitting(true);
set_one_shot(false);
@@ -383,10 +582,13 @@ GPUParticles2D::GPUParticles2D() {
set_randomness_ratio(0);
set_visibility_rect(Rect2(Vector2(-100, -100), Vector2(200, 200)));
set_use_local_coordinates(true);
- set_draw_order(DRAW_ORDER_INDEX);
+ set_draw_order(DRAW_ORDER_LIFETIME);
set_speed_scale(1);
+ set_fixed_fps(30);
+ set_collision_base_size(collision_base_size);
}
GPUParticles2D::~GPUParticles2D() {
RS::get_singleton()->free(particles);
+ RS::get_singleton()->free(mesh);
}
diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h
index 20f9f768ed..9d8e61daf7 100644
--- a/scene/2d/gpu_particles_2d.h
+++ b/scene/2d/gpu_particles_2d.h
@@ -43,6 +43,7 @@ public:
enum DrawOrder {
DRAW_ORDER_INDEX,
DRAW_ORDER_LIFETIME,
+ DRAW_ORDER_REVERSE_LIFETIME,
};
private:
@@ -68,11 +69,23 @@ private:
void _update_particle_emission_transform();
+ NodePath sub_emitter;
+ float collision_base_size = 1.0;
+
+ bool trail_enabled = false;
+ float trail_length = 0.3;
+ int trail_sections = 8;
+ int trail_section_subdivisions = 4;
+
+ RID mesh;
+
protected:
static void _bind_methods();
virtual void _validate_property(PropertyInfo &property) const override;
void _notification(int p_what);
+ void _update_collision_size();
+
public:
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
@@ -85,6 +98,11 @@ public:
void set_use_local_coordinates(bool p_enable);
void set_process_material(const Ref<Material> &p_material);
void set_speed_scale(float p_scale);
+ void set_collision_base_size(float p_ratio);
+ void set_trail_enabled(bool p_enabled);
+ void set_trail_length(float p_seconds);
+ void set_trail_sections(int p_sections);
+ void set_trail_section_subdivisions(int p_subdivisions);
bool is_emitting() const;
int get_amount() const;
@@ -98,6 +116,12 @@ public:
Ref<Material> get_process_material() const;
float get_speed_scale() const;
+ float get_collision_base_size() const;
+ bool is_trail_enabled() const;
+ float get_trail_length() const;
+ int get_trail_sections() const;
+ int get_trail_section_subdivisions() const;
+
void set_fixed_fps(int p_count);
int get_fixed_fps() const;
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 8fb765f16b..ce57895341 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -281,7 +281,7 @@ void Light2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Add,Sub,Mix"), "set_blend_mode", "get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Add,Subtract,Mix"), "set_blend_mode", "get_blend_mode");
ADD_GROUP("Range", "range_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_min", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_min", "get_z_range_min");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_max", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_max", "get_z_range_max");
@@ -292,7 +292,7 @@ void Light2D::_bind_methods() {
ADD_GROUP("Shadow", "shadow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow_enabled", "is_shadow_enabled");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF5,PCF13"), "set_shadow_filter", "get_shadow_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_filter", PROPERTY_HINT_ENUM, "None (Fast),PCF5 (Average),PCF13 (Slow)"), "set_shadow_filter", "get_shadow_filter");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask");
diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp
index b7a0028199..15008390b7 100644
--- a/scene/2d/mesh_instance_2d.cpp
+++ b/scene/2d/mesh_instance_2d.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "mesh_instance_2d.h"
+#include "scene/scene_string_names.h"
void MeshInstance2D::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
@@ -70,7 +71,7 @@ void MeshInstance2D::set_texture(const Ref<Texture2D> &p_texture) {
}
texture = p_texture;
update();
- emit_signal("texture_changed");
+ emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
void MeshInstance2D::set_normal_map(const Ref<Texture2D> &p_texture) {
diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp
index 72a899370e..1bff2f337d 100644
--- a/scene/2d/multimesh_instance_2d.cpp
+++ b/scene/2d/multimesh_instance_2d.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "multimesh_instance_2d.h"
+#include "scene/scene_string_names.h"
void MultiMeshInstance2D::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
@@ -70,7 +71,7 @@ void MultiMeshInstance2D::set_texture(const Ref<Texture2D> &p_texture) {
}
texture = p_texture;
update();
- emit_signal("texture_changed");
+ emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
Ref<Texture2D> MultiMeshInstance2D::get_texture() const {
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 8afc43ddc9..049d121213 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -391,6 +391,15 @@ Point2 Node2D::to_global(Point2 p_local) const {
return get_global_transform().xform(p_local);
}
+void Node2D::set_y_sort_enabled(bool p_enabled) {
+ y_sort_enabled = p_enabled;
+ RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), y_sort_enabled);
+}
+
+bool Node2D::is_y_sort_enabled() const {
+ return y_sort_enabled;
+}
+
void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_position", "position"), &Node2D::set_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Node2D::set_rotation);
@@ -437,6 +446,9 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &Node2D::set_z_as_relative);
ClassDB::bind_method(D_METHOD("is_z_relative"), &Node2D::is_z_relative);
+ ClassDB::bind_method(D_METHOD("set_y_sort_enabled", "enabled"), &Node2D::set_y_sort_enabled);
+ ClassDB::bind_method(D_METHOD("is_y_sort_enabled"), &Node2D::is_y_sort_enabled);
+
ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent);
ADD_GROUP("Transform", "");
@@ -454,7 +466,8 @@ void Node2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_scale", PROPERTY_HINT_NONE, "", 0), "set_global_scale", "get_global_scale");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform");
- ADD_GROUP("Z Index", "");
+ ADD_GROUP("Ordering", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_index", "get_z_index");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "z_as_relative"), "set_z_as_relative", "is_z_relative");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "y_sort_enabled"), "set_y_sort_enabled", "is_y_sort_enabled");
}
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 358b7e6520..339efd9179 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -42,6 +42,7 @@ class Node2D : public CanvasItem {
real_t skew = 0.0;
int z_index = 0;
bool z_relative = true;
+ bool y_sort_enabled = false;
Transform2D _mat;
@@ -117,6 +118,9 @@ public:
void set_z_as_relative(bool p_enabled);
bool is_z_relative() const;
+ virtual void set_y_sort_enabled(bool p_enabled);
+ virtual bool is_y_sort_enabled() const;
+
Transform2D get_relative_transform_to_parent(const Node *p_parent) const;
Transform2D get_transform() const override;
diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physical_bone_2d.cpp
new file mode 100644
index 0000000000..0c1be16174
--- /dev/null
+++ b/scene/2d/physical_bone_2d.cpp
@@ -0,0 +1,303 @@
+/*************************************************************************/
+/* physical_bone_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "physical_bone_2d.h"
+
+void PhysicalBone2D::_notification(int p_what) {
+ if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
+ // Position the RigidBody in the correct position
+ if (follow_bone_when_simulating) {
+ _position_at_bone2d();
+ }
+
+ // Keep the child joint in the correct position.
+ if (child_joint && auto_configure_joint) {
+ child_joint->set_global_position(get_global_position());
+ }
+ } else if (p_what == NOTIFICATION_READY) {
+ _find_skeleton_parent();
+ _find_joint_child();
+
+ // Configure joint
+ if (child_joint && auto_configure_joint) {
+ _auto_configure_joint();
+ }
+
+ // Simulate physics if set
+ if (simulate_physics) {
+ _start_physics_simulation();
+ } else {
+ _stop_physics_simulation();
+ }
+
+ set_physics_process_internal(true);
+ }
+}
+
+void PhysicalBone2D::_position_at_bone2d() {
+ // Reset to Bone2D position
+ if (parent_skeleton) {
+ Bone2D *bone_to_use = parent_skeleton->get_bone(bone2d_index);
+ ERR_FAIL_COND_MSG(bone_to_use == nullptr, "It's not possible to position the bone with ID: " + itos(bone2d_index));
+ set_global_transform(bone_to_use->get_global_transform());
+ }
+}
+
+void PhysicalBone2D::_find_skeleton_parent() {
+ Node *current_parent = get_parent();
+
+ while (current_parent != nullptr) {
+ Skeleton2D *potential_skeleton = Object::cast_to<Skeleton2D>(current_parent);
+ if (potential_skeleton) {
+ parent_skeleton = potential_skeleton;
+ break;
+ } else {
+ PhysicalBone2D *potential_parent_bone = Object::cast_to<PhysicalBone2D>(current_parent);
+ if (potential_parent_bone) {
+ current_parent = potential_parent_bone->get_parent();
+ } else {
+ current_parent = nullptr;
+ }
+ }
+ }
+}
+
+void PhysicalBone2D::_find_joint_child() {
+ for (int i = 0; i < get_child_count(); i++) {
+ Node *child_node = get_child(i);
+ Joint2D *potential_joint = Object::cast_to<Joint2D>(child_node);
+ if (potential_joint) {
+ child_joint = potential_joint;
+ break;
+ }
+ }
+}
+
+TypedArray<String> PhysicalBone2D::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (!parent_skeleton) {
+ warnings.push_back(TTR("A PhysicalBone2D only works with a Skeleton2D or another PhysicalBone2D as a parent node!"));
+ }
+ if (parent_skeleton && bone2d_index <= -1) {
+ warnings.push_back(TTR("A PhysicalBone2D needs to be assigned to a Bone2D node in order to function! Please set a Bone2D node in the inspector."));
+ }
+ if (!child_joint) {
+ PhysicalBone2D *parent_bone = Object::cast_to<PhysicalBone2D>(get_parent());
+ if (parent_bone) {
+ warnings.push_back(TTR("A PhysicalBone2D node should have a Joint2D-based child node to keep bones connected! Please add a Joint2D-based node as a child to this node!"));
+ }
+ }
+
+ return warnings;
+}
+
+void PhysicalBone2D::_auto_configure_joint() {
+ if (!auto_configure_joint) {
+ return;
+ }
+
+ if (child_joint) {
+ // Node A = parent | Node B = this node
+ Node *parent_node = get_parent();
+ PhysicalBone2D *potential_parent_bone = Object::cast_to<PhysicalBone2D>(parent_node);
+
+ if (potential_parent_bone) {
+ child_joint->set_node_a(child_joint->get_path_to(potential_parent_bone));
+ child_joint->set_node_b(child_joint->get_path_to(this));
+ } else {
+ WARN_PRINT("Cannot setup joint without a parent PhysicalBone2D node.");
+ }
+
+ // Place the child joint at this node's position.
+ child_joint->set_global_position(get_global_position());
+ }
+}
+
+void PhysicalBone2D::_start_physics_simulation() {
+ if (_internal_simulate_physics) {
+ return;
+ }
+
+ // Reset to Bone2D position
+ _position_at_bone2d();
+
+ // Apply the layers and masks
+ PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
+ PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
+
+ // Apply the correct mode
+ RigidBody2D::Mode rigid_mode = get_mode();
+ if (rigid_mode == RigidBody2D::MODE_STATIC) {
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);
+ } else if (rigid_mode == RigidBody2D::MODE_DYNAMIC) {
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC);
+ } else if (rigid_mode == RigidBody2D::MODE_KINEMATIC) {
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_KINEMATIC);
+ } else if (rigid_mode == RigidBody2D::MODE_DYNAMIC_LOCKED) {
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC_LOCKED);
+ } else {
+ // Default to Rigid
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC);
+ }
+
+ _internal_simulate_physics = true;
+ set_physics_process_internal(true);
+}
+
+void PhysicalBone2D::_stop_physics_simulation() {
+ if (_internal_simulate_physics) {
+ _internal_simulate_physics = false;
+
+ // Reset to Bone2D position
+ _position_at_bone2d();
+
+ set_physics_process_internal(false);
+ PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0);
+ PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0);
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);
+ }
+}
+
+Joint2D *PhysicalBone2D::get_joint() const {
+ return child_joint;
+}
+
+bool PhysicalBone2D::get_auto_configure_joint() const {
+ return auto_configure_joint;
+}
+
+void PhysicalBone2D::set_auto_configure_joint(bool p_auto_configure) {
+ auto_configure_joint = p_auto_configure;
+ _auto_configure_joint();
+}
+
+void PhysicalBone2D::set_simulate_physics(bool p_simulate) {
+ if (p_simulate == simulate_physics) {
+ return;
+ }
+ simulate_physics = p_simulate;
+
+ if (simulate_physics) {
+ _start_physics_simulation();
+ } else {
+ _stop_physics_simulation();
+ }
+}
+
+bool PhysicalBone2D::get_simulate_physics() const {
+ return simulate_physics;
+}
+
+bool PhysicalBone2D::is_simulating_physics() const {
+ return _internal_simulate_physics;
+}
+
+void PhysicalBone2D::set_bone2d_nodepath(const NodePath &p_nodepath) {
+ bone2d_nodepath = p_nodepath;
+ notify_property_list_changed();
+}
+
+NodePath PhysicalBone2D::get_bone2d_nodepath() const {
+ return bone2d_nodepath;
+}
+
+void PhysicalBone2D::set_bone2d_index(int p_bone_idx) {
+ ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
+
+ if (!is_inside_tree()) {
+ bone2d_index = p_bone_idx;
+ return;
+ }
+
+ if (parent_skeleton) {
+ ERR_FAIL_INDEX_MSG(p_bone_idx, parent_skeleton->get_bone_count(), "Passed-in Bone index is out of range!");
+ bone2d_index = p_bone_idx;
+
+ bone2d_nodepath = get_path_to(parent_skeleton->get_bone(bone2d_index));
+ } else {
+ WARN_PRINT("Cannot verify bone index...");
+ bone2d_index = p_bone_idx;
+ }
+
+ notify_property_list_changed();
+}
+
+int PhysicalBone2D::get_bone2d_index() const {
+ return bone2d_index;
+}
+
+void PhysicalBone2D::set_follow_bone_when_simulating(bool p_follow_bone) {
+ follow_bone_when_simulating = p_follow_bone;
+
+ if (_internal_simulate_physics) {
+ _stop_physics_simulation();
+ _start_physics_simulation();
+ }
+}
+
+bool PhysicalBone2D::get_follow_bone_when_simulating() const {
+ return follow_bone_when_simulating;
+}
+
+void PhysicalBone2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_joint"), &PhysicalBone2D::get_joint);
+ ClassDB::bind_method(D_METHOD("get_auto_configure_joint"), &PhysicalBone2D::get_auto_configure_joint);
+ ClassDB::bind_method(D_METHOD("set_auto_configure_joint", "auto_configure_joint"), &PhysicalBone2D::set_auto_configure_joint);
+
+ ClassDB::bind_method(D_METHOD("set_simulate_physics", "simulate_physics"), &PhysicalBone2D::set_simulate_physics);
+ ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone2D::get_simulate_physics);
+ ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone2D::is_simulating_physics);
+
+ ClassDB::bind_method(D_METHOD("set_bone2d_nodepath", "nodepath"), &PhysicalBone2D::set_bone2d_nodepath);
+ ClassDB::bind_method(D_METHOD("get_bone2d_nodepath"), &PhysicalBone2D::get_bone2d_nodepath);
+ ClassDB::bind_method(D_METHOD("set_bone2d_index", "bone_index"), &PhysicalBone2D::set_bone2d_index);
+ ClassDB::bind_method(D_METHOD("get_bone2d_index"), &PhysicalBone2D::get_bone2d_index);
+ ClassDB::bind_method(D_METHOD("set_follow_bone_when_simulating", "follow_bone"), &PhysicalBone2D::set_follow_bone_when_simulating);
+ ClassDB::bind_method(D_METHOD("get_follow_bone_when_simulating"), &PhysicalBone2D::get_follow_bone_when_simulating);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "bone2d_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D"), "set_bone2d_nodepath", "get_bone2d_nodepath");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bone2d_index", PROPERTY_HINT_RANGE, "-1, 1000, 1"), "set_bone2d_index", "get_bone2d_index");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_configure_joint"), "set_auto_configure_joint", "get_auto_configure_joint");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "simulate_physics"), "set_simulate_physics", "get_simulate_physics");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_bone_when_simulating"), "set_follow_bone_when_simulating", "get_follow_bone_when_simulating");
+}
+
+PhysicalBone2D::PhysicalBone2D() {
+ // Stop the RigidBody from executing its force integration.
+ PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0);
+ PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0);
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);
+
+ child_joint = nullptr;
+}
+
+PhysicalBone2D::~PhysicalBone2D() {
+}
diff --git a/scene/2d/physical_bone_2d.h b/scene/2d/physical_bone_2d.h
new file mode 100644
index 0000000000..46a2772bad
--- /dev/null
+++ b/scene/2d/physical_bone_2d.h
@@ -0,0 +1,88 @@
+/*************************************************************************/
+/* physical_bone_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PHYSICAL_BONE_2D_H
+#define PHYSICAL_BONE_2D_H
+
+#include "scene/2d/joints_2d.h"
+#include "scene/2d/physics_body_2d.h"
+
+#include "scene/2d/skeleton_2d.h"
+
+class PhysicalBone2D : public RigidBody2D {
+ GDCLASS(PhysicalBone2D, RigidBody2D);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+private:
+ Skeleton2D *parent_skeleton = nullptr;
+ int bone2d_index = -1;
+ NodePath bone2d_nodepath;
+ bool follow_bone_when_simulating = false;
+
+ Joint2D *child_joint;
+ bool auto_configure_joint = true;
+
+ bool simulate_physics = false;
+ bool _internal_simulate_physics = false;
+
+ void _find_skeleton_parent();
+ void _find_joint_child();
+ void _auto_configure_joint();
+
+ void _start_physics_simulation();
+ void _stop_physics_simulation();
+ void _position_at_bone2d();
+
+public:
+ Joint2D *get_joint() const;
+ bool get_auto_configure_joint() const;
+ void set_auto_configure_joint(bool p_auto_configure);
+
+ void set_simulate_physics(bool p_simulate);
+ bool get_simulate_physics() const;
+ bool is_simulating_physics() const;
+
+ void set_bone2d_nodepath(const NodePath &p_nodepath);
+ NodePath get_bone2d_nodepath() const;
+ void set_bone2d_index(int p_bone_idx);
+ int get_bone2d_index() const;
+ void set_follow_bone_when_simulating(bool p_follow);
+ bool get_follow_bone_when_simulating() const;
+
+ TypedArray<String> get_configuration_warnings() const override;
+
+ PhysicalBone2D();
+ ~PhysicalBone2D();
+};
+
+#endif // PHYSICAL_BONE_2D_H
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 3f2f6d6b1c..4b72043a46 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -38,10 +38,10 @@
#include "core/templates/rid.h"
#include "scene/scene_string_names.h"
-void PhysicsBody2D::_notification(int p_what) {
-}
-
void PhysicsBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only", "safe_margin"), &PhysicsBody2D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false), DEFVAL(0.08));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "collision", "safe_margin"), &PhysicsBody2D::test_move, DEFVAL(true), DEFVAL(true), DEFVAL(Variant()), DEFVAL(0.08));
+
ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions);
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with);
ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody2D::remove_collision_exception_with);
@@ -53,6 +53,56 @@ PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) :
set_pickable(false);
}
+PhysicsBody2D::~PhysicsBody2D() {
+ if (motion_cache.is_valid()) {
+ motion_cache->owner = nullptr;
+ }
+}
+
+Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only, real_t p_margin) {
+ PhysicsServer2D::MotionResult result;
+
+ if (move_and_collide(p_motion, p_infinite_inertia, result, p_margin, p_exclude_raycast_shapes, p_test_only)) {
+ if (motion_cache.is_null()) {
+ motion_cache.instance();
+ motion_cache->owner = this;
+ }
+
+ motion_cache->result = result;
+
+ return motion_cache;
+ }
+
+ return Ref<KinematicCollision2D>();
+}
+
+bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only) {
+ if (is_only_update_transform_changes_enabled()) {
+ ERR_PRINT("Move functions do not work together with 'sync to physics' option. Please read the documentation.");
+ }
+ Transform2D gt = get_global_transform();
+ bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, p_margin, &r_result, p_exclude_raycast_shapes);
+
+ if (!p_test_only) {
+ gt.elements[2] += r_result.motion;
+ set_global_transform(gt);
+ }
+
+ return colliding;
+}
+
+bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, const Ref<KinematicCollision2D> &r_collision, real_t p_margin) {
+ ERR_FAIL_COND_V(!is_inside_tree(), false);
+
+ PhysicsServer2D::MotionResult *r = nullptr;
+ if (r_collision.is_valid()) {
+ // Needs const_cast because method bindings don't support non-const Ref.
+ r = const_cast<PhysicsServer2D::MotionResult *>(&r_collision->result);
+ }
+
+ return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, p_margin, r, p_exclude_raycast_shapes);
+}
+
TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
List<RID> exceptions;
PhysicsServer2D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
@@ -83,12 +133,22 @@ void PhysicsBody2D::remove_collision_exception_with(Node *p_node) {
void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) {
constant_linear_velocity = p_vel;
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
+
+ if (kinematic_motion) {
+ _update_kinematic_motion();
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
+ }
}
void StaticBody2D::set_constant_angular_velocity(real_t p_vel) {
constant_angular_velocity = p_vel;
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
+
+ if (kinematic_motion) {
+ _update_kinematic_motion();
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
+ }
}
Vector2 StaticBody2D::get_constant_linear_velocity() const {
@@ -118,27 +178,74 @@ Ref<PhysicsMaterial> StaticBody2D::get_physics_material_override() const {
return physics_material_override;
}
+void StaticBody2D::set_kinematic_motion_enabled(bool p_enabled) {
+ if (p_enabled == kinematic_motion) {
+ return;
+ }
+
+ kinematic_motion = p_enabled;
+
+ if (kinematic_motion) {
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC);
+ }
+
+ _update_kinematic_motion();
+}
+
+bool StaticBody2D::is_kinematic_motion_enabled() const {
+ return kinematic_motion;
+}
+
+void StaticBody2D::_notification(int p_what) {
+ if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+
+ ERR_FAIL_COND(!kinematic_motion);
+
+ real_t delta_time = get_physics_process_delta_time();
+
+ Transform2D new_transform = get_global_transform();
+
+ new_transform.translate(constant_linear_velocity * delta_time);
+ new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
+
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
+
+ // Propagate transform change to node.
+ set_block_transform_notify(true);
+ set_global_transform(new_transform);
+ set_block_transform_notify(false);
+ }
+}
+
void StaticBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity);
ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_kinematic_motion_enabled", "enabled"), &StaticBody2D::set_kinematic_motion_enabled);
+ ClassDB::bind_method(D_METHOD("is_kinematic_motion_enabled"), &StaticBody2D::is_kinematic_motion_enabled);
+
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
}
StaticBody2D::StaticBody2D() :
PhysicsBody2D(PhysicsServer2D::BODY_MODE_STATIC) {
}
-StaticBody2D::~StaticBody2D() {
-}
-
void StaticBody2D::_reload_physics_characteristics() {
if (physics_material_override.is_null()) {
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
@@ -149,6 +256,23 @@ void StaticBody2D::_reload_physics_characteristics() {
}
}
+void StaticBody2D::_update_kinematic_motion() {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+
+ if (kinematic_motion) {
+ if (!Math::is_zero_approx(constant_angular_velocity) || !constant_linear_velocity.is_equal_approx(Vector2())) {
+ set_physics_process_internal(true);
+ return;
+ }
+ }
+
+ set_physics_process_internal(false);
+}
+
void RigidBody2D::_body_enter_tree(ObjectID p_id) {
Object *obj = ObjectDB::get_instance(p_id);
Node *node = Object::cast_to<Node>(obj);
@@ -165,7 +289,7 @@ void RigidBody2D::_body_enter_tree(ObjectID p_id) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
}
contact_monitor->locked = false;
@@ -186,13 +310,13 @@ void RigidBody2D::_body_exit_tree(ObjectID p_id) {
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
}
contact_monitor->locked = false;
}
-void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape) {
+void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) {
bool body_in = p_status == 1;
ObjectID objid = p_instance;
@@ -207,6 +331,7 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
if (body_in) {
if (!E) {
E = contact_monitor->body_map.insert(objid, BodyState());
+ E->get().rid = p_body;
//E->get().rc=0;
E->get().in_scene = node && node->is_inside_tree();
if (node) {
@@ -225,7 +350,7 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
}
if (E->get().in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_local_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
}
} else {
@@ -249,25 +374,18 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
contact_monitor->body_map.erase(E);
}
if (node && in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, node, p_body_shape, p_local_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, node, p_body_shape, p_local_shape);
}
}
}
struct _RigidBody2DInOut {
+ RID rid;
ObjectID id;
int shape = 0;
int local_shape = 0;
};
-bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result) {
- PhysicsServer2D::MotionResult *r = nullptr;
- if (p_result.is_valid()) {
- r = p_result->get_result_ptr();
- }
- return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r);
-}
-
void RigidBody2D::_direct_state_changed(Object *p_state) {
#ifdef DEBUG_ENABLED
state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
@@ -311,6 +429,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
//put the ones to add
for (int i = 0; i < state->get_contact_count(); i++) {
+ RID rid = state->get_contact_collider(i);
ObjectID obj = state->get_contact_collider_id(i);
int local_shape = state->get_contact_local_shape(i);
int shape = state->get_contact_collider_shape(i);
@@ -319,6 +438,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(obj);
if (!E) {
+ toadd[toadd_count].rid = rid;
toadd[toadd_count].local_shape = local_shape;
toadd[toadd_count].id = obj;
toadd[toadd_count].shape = shape;
@@ -329,6 +449,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
ShapePair sp(shape, local_shape);
int idx = E->get().shapes.find(sp);
if (idx == -1) {
+ toadd[toadd_count].rid = rid;
toadd[toadd_count].local_shape = local_shape;
toadd[toadd_count].id = obj;
toadd[toadd_count].shape = shape;
@@ -344,6 +465,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
for (Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.front(); E; E = E->next()) {
for (int i = 0; i < E->get().shapes.size(); i++) {
if (!E->get().shapes[i].tagged) {
+ toremove[toremove_count].rid = E->get().rid;
toremove[toremove_count].body_id = E->key();
toremove[toremove_count].pair = E->get().shapes[i];
toremove_count++;
@@ -354,13 +476,13 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
//process removals
for (int i = 0; i < toremove_count; i++) {
- _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
+ _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
}
//process additions
for (int i = 0; i < toadd_count; i++) {
- _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
+ _body_inout(1, toadd[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
}
contact_monitor->locked = false;
@@ -372,8 +494,8 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
void RigidBody2D::set_mode(Mode p_mode) {
mode = p_mode;
switch (p_mode) {
- case MODE_RIGID: {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_RIGID);
+ case MODE_DYNAMIC: {
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_DYNAMIC);
} break;
case MODE_STATIC: {
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC);
@@ -383,8 +505,8 @@ void RigidBody2D::set_mode(Mode p_mode) {
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC);
} break;
- case MODE_CHARACTER: {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_CHARACTER);
+ case MODE_DYNAMIC_LOCKED: {
+ PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED);
} break;
}
@@ -660,8 +782,8 @@ TypedArray<String> RigidBody2D::get_configuration_warnings() const {
TypedArray<String> warnings = CollisionObject2D::get_configuration_warnings();
- if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.elements[0].length() - 1.0) > 0.05 || ABS(t.elements[1].length() - 1.0) > 0.05)) {
- warnings.push_back(TTR("Size changes to RigidBody2D (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
+ if ((get_mode() == MODE_DYNAMIC || get_mode() == MODE_DYNAMIC_LOCKED) && (ABS(t.elements[0].length() - 1.0) > 0.05 || ABS(t.elements[1].length() - 1.0) > 0.05)) {
+ warnings.push_back(TTR("Size changes to RigidBody2D (in dynamic modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
}
return warnings;
@@ -728,13 +850,11 @@ void RigidBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep);
ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep);
- ClassDB::bind_method(D_METHOD("test_motion", "motion", "infinite_inertia", "margin", "result"), &RigidBody2D::_test_motion, DEFVAL(true), DEFVAL(0.08), DEFVAL(Variant()));
-
ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies);
BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState2D")));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Rigid,Static,Character,Kinematic"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Dynamic,Static,DynamicLocked,Kinematic"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", 0), "set_inertia", "get_inertia");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
@@ -755,15 +875,15 @@ void RigidBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "applied_force"), "set_applied_force", "get_applied_force");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "applied_torque"), "set_applied_torque", "get_applied_torque");
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
- BIND_ENUM_CONSTANT(MODE_RIGID);
+ BIND_ENUM_CONSTANT(MODE_DYNAMIC);
BIND_ENUM_CONSTANT(MODE_STATIC);
- BIND_ENUM_CONSTANT(MODE_CHARACTER);
+ BIND_ENUM_CONSTANT(MODE_DYNAMIC_LOCKED);
BIND_ENUM_CONSTANT(MODE_KINEMATIC);
BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
@@ -772,7 +892,7 @@ void RigidBody2D::_bind_methods() {
}
RigidBody2D::RigidBody2D() :
- PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
+ PhysicsBody2D(PhysicsServer2D::BODY_MODE_DYNAMIC) {
PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &RigidBody2D::_direct_state_changed));
}
@@ -794,95 +914,13 @@ void RigidBody2D::_reload_physics_characteristics() {
//////////////////////////
-Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) {
- Collision col;
-
- if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) {
- if (motion_cache.is_null()) {
- motion_cache.instance();
- motion_cache->owner = this;
- }
-
- motion_cache->collision = col;
-
- return motion_cache;
- }
-
- return Ref<KinematicCollision2D>();
-}
-
-bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) {
- PhysicsServer2D::SeparationResult sep_res[8]; //max 8 rays
-
- Transform2D gt = get_global_transform();
-
- Vector2 recover;
- int hits = PhysicsServer2D::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin);
- int deepest = -1;
- real_t deepest_depth;
- for (int i = 0; i < hits; i++) {
- if (deepest == -1 || sep_res[i].collision_depth > deepest_depth) {
- deepest = i;
- deepest_depth = sep_res[i].collision_depth;
- }
- }
-
- gt.elements[2] += recover;
- set_global_transform(gt);
-
- if (deepest != -1) {
- r_collision.collider = sep_res[deepest].collider_id;
- r_collision.collider_metadata = sep_res[deepest].collider_metadata;
- r_collision.collider_shape = sep_res[deepest].collider_shape;
- r_collision.collider_vel = sep_res[deepest].collider_velocity;
- r_collision.collision = sep_res[deepest].collision_point;
- r_collision.normal = sep_res[deepest].collision_normal;
- r_collision.local_shape = sep_res[deepest].collision_local_shape;
- r_collision.travel = recover;
- r_collision.remainder = Vector2();
-
- return true;
- } else {
- return false;
- }
-}
-
-bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {
- if (sync_to_physics) {
- ERR_PRINT("Functions move_and_slide and move_and_collide do not work together with 'sync to physics' option. Please read the documentation.");
- }
- Transform2D gt = get_global_transform();
- PhysicsServer2D::MotionResult result;
- bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result, p_exclude_raycast_shapes);
-
- if (colliding) {
- r_collision.collider_metadata = result.collider_metadata;
- r_collision.collider_shape = result.collider_shape;
- r_collision.collider_vel = result.collider_velocity;
- r_collision.collision = result.collision_point;
- r_collision.normal = result.collision_normal;
- r_collision.collider = result.collider_id;
- r_collision.collider_rid = result.collider;
- r_collision.travel = result.motion;
- r_collision.remainder = result.remainder;
- r_collision.local_shape = result.collision_local_shape;
- }
-
- if (!p_test_only) {
- gt.elements[2] += result.motion;
- set_global_transform(gt);
- }
-
- return colliding;
-}
-
//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
#define FLOOR_ANGLE_THRESHOLD 0.01
-Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, real_t p_floor_max_angle, bool p_infinite_inertia) {
- Vector2 body_velocity = p_linear_velocity;
- Vector2 body_velocity_normal = body_velocity.normalized();
- Vector2 up_direction = p_up_direction.normalized();
+void CharacterBody2D::move_and_slide() {
+ Vector2 body_velocity_normal = linear_velocity.normalized();
+
+ bool was_on_floor = on_floor;
Vector2 current_floor_velocity = floor_velocity;
if (on_floor && on_floor_body.is_valid()) {
@@ -894,69 +932,71 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
}
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
- Vector2 motion = (current_floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
+ Vector2 motion = (current_floor_velocity + linear_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
on_floor = false;
on_floor_body = RID();
on_ceiling = false;
on_wall = false;
- colliders.clear();
+ motion_results.clear();
floor_normal = Vector2();
floor_velocity = Vector2();
- while (p_max_slides) {
- Collision collision;
+ int slide_count = max_slides;
+ while (slide_count) {
+ PhysicsServer2D::MotionResult result;
bool found_collision = false;
for (int i = 0; i < 2; ++i) {
bool collided;
if (i == 0) { //collide
- collided = move_and_collide(motion, p_infinite_inertia, collision);
+ collided = move_and_collide(motion, infinite_inertia, result, margin);
if (!collided) {
motion = Vector2(); //clear because no collision happened and motion completed
}
} else { //separate raycasts (if any)
- collided = separate_raycast_shapes(p_infinite_inertia, collision);
+ collided = separate_raycast_shapes(result);
if (collided) {
- collision.remainder = motion; //keep
- collision.travel = Vector2();
+ result.remainder = motion; //keep
+ result.motion = Vector2();
}
}
if (collided) {
found_collision = true;
- colliders.push_back(collision);
- motion = collision.remainder;
+ motion_results.push_back(result);
+ motion = result.remainder;
if (up_direction == Vector2()) {
//all is a wall
on_wall = true;
} else {
- if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
on_floor = true;
- floor_normal = collision.normal;
- on_floor_body = collision.collider_rid;
- floor_velocity = collision.collider_vel;
+ floor_normal = result.collision_normal;
+ on_floor_body = result.collider;
+ floor_velocity = result.collider_velocity;
- if (p_stop_on_slope) {
- if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) {
+ if (stop_on_slope) {
+ if ((body_velocity_normal + up_direction).length() < 0.01 && result.motion.length() < 1) {
Transform2D gt = get_global_transform();
- gt.elements[2] -= collision.travel.slide(up_direction);
+ gt.elements[2] -= result.motion.slide(up_direction);
set_global_transform(gt);
- return Vector2();
+ linear_velocity = Vector2();
+ return;
}
}
- } else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ } else if (Math::acos(result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
on_ceiling = true;
} else {
on_wall = true;
}
}
- motion = motion.slide(collision.normal);
- body_velocity = body_velocity.slide(collision.normal);
+ motion = motion.slide(result.collision_normal);
+ linear_velocity = linear_velocity.slide(result.collision_normal);
}
}
@@ -964,36 +1004,28 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
break;
}
- --p_max_slides;
+ --slide_count;
}
- return body_velocity;
-}
-
-Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, real_t p_floor_max_angle, bool p_infinite_inertia) {
- Vector2 up_direction = p_up_direction.normalized();
- bool was_on_floor = on_floor;
-
- Vector2 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
- if (!was_on_floor || p_snap == Vector2()) {
- return ret;
+ if (!was_on_floor || snap == Vector2()) {
+ return;
}
- Collision col;
+ // Apply snap.
Transform2D gt = get_global_transform();
-
- if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
+ PhysicsServer2D::MotionResult result;
+ if (move_and_collide(snap, infinite_inertia, result, margin, false, true)) {
bool apply = true;
if (up_direction != Vector2()) {
- if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
+ if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
on_floor = true;
- floor_normal = col.normal;
- on_floor_body = col.collider_rid;
- floor_velocity = col.collider_vel;
- if (p_stop_on_slope) {
+ floor_normal = result.collision_normal;
+ on_floor_body = result.collider;
+ floor_velocity = result.collider_velocity;
+ if (stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
// so only ensure that motion happens on floor direction in this case.
- col.travel = up_direction * up_direction.dot(col.travel);
+ result.motion = up_direction * up_direction.dot(result.motion);
}
} else {
@@ -1002,59 +1034,87 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
}
if (apply) {
- gt.elements[2] += col.travel;
+ gt.elements[2] += result.motion;
set_global_transform(gt);
}
}
-
- return ret;
}
-bool KinematicBody2D::is_on_floor() const {
- return on_floor;
-}
+bool CharacterBody2D::separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result) {
+ PhysicsServer2D::SeparationResult sep_res[8]; //max 8 rays
-bool KinematicBody2D::is_on_wall() const {
- return on_wall;
+ Transform2D gt = get_global_transform();
+
+ Vector2 recover;
+ int hits = PhysicsServer2D::get_singleton()->body_test_ray_separation(get_rid(), gt, infinite_inertia, recover, sep_res, 8, margin);
+ int deepest = -1;
+ real_t deepest_depth;
+ for (int i = 0; i < hits; i++) {
+ if (deepest == -1 || sep_res[i].collision_depth > deepest_depth) {
+ deepest = i;
+ deepest_depth = sep_res[i].collision_depth;
+ }
+ }
+
+ gt.elements[2] += recover;
+ set_global_transform(gt);
+
+ if (deepest != -1) {
+ r_result.collider_id = sep_res[deepest].collider_id;
+ r_result.collider_metadata = sep_res[deepest].collider_metadata;
+ r_result.collider_shape = sep_res[deepest].collider_shape;
+ r_result.collider_velocity = sep_res[deepest].collider_velocity;
+ r_result.collision_point = sep_res[deepest].collision_point;
+ r_result.collision_normal = sep_res[deepest].collision_normal;
+ r_result.collision_local_shape = sep_res[deepest].collision_local_shape;
+ r_result.motion = recover;
+ r_result.remainder = Vector2();
+
+ return true;
+ } else {
+ return false;
+ }
}
-bool KinematicBody2D::is_on_ceiling() const {
- return on_ceiling;
+const Vector2 &CharacterBody2D::get_linear_velocity() const {
+ return linear_velocity;
}
-Vector2 KinematicBody2D::get_floor_normal() const {
- return floor_normal;
+void CharacterBody2D::set_linear_velocity(const Vector2 &p_velocity) {
+ linear_velocity = p_velocity;
}
-Vector2 KinematicBody2D::get_floor_velocity() const {
- return floor_velocity;
+bool CharacterBody2D::is_on_floor() const {
+ return on_floor;
}
-bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia) {
- ERR_FAIL_COND_V(!is_inside_tree(), false);
+bool CharacterBody2D::is_on_wall() const {
+ return on_wall;
+}
- return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin);
+bool CharacterBody2D::is_on_ceiling() const {
+ return on_ceiling;
}
-void KinematicBody2D::set_safe_margin(real_t p_margin) {
- margin = p_margin;
+Vector2 CharacterBody2D::get_floor_normal() const {
+ return floor_normal;
}
-real_t KinematicBody2D::get_safe_margin() const {
- return margin;
+Vector2 CharacterBody2D::get_floor_velocity() const {
+ return floor_velocity;
}
-int KinematicBody2D::get_slide_count() const {
- return colliders.size();
+int CharacterBody2D::get_slide_count() const {
+ return motion_results.size();
}
-KinematicBody2D::Collision KinematicBody2D::get_slide_collision(int p_bounce) const {
- ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Collision());
- return colliders[p_bounce];
+PhysicsServer2D::MotionResult CharacterBody2D::get_slide_collision(int p_bounce) const {
+ ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), PhysicsServer2D::MotionResult());
+ return motion_results[p_bounce];
}
-Ref<KinematicCollision2D> KinematicBody2D::_get_slide_collision(int p_bounce) {
- ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Ref<KinematicCollision2D>());
+Ref<KinematicCollision2D> CharacterBody2D::_get_slide_collision(int p_bounce) {
+ ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), Ref<KinematicCollision2D>());
if (p_bounce >= slide_colliders.size()) {
slide_colliders.resize(p_bounce + 1);
}
@@ -1064,11 +1124,11 @@ Ref<KinematicCollision2D> KinematicBody2D::_get_slide_collision(int p_bounce) {
slide_colliders.write[p_bounce]->owner = this;
}
- slide_colliders.write[p_bounce]->collision = colliders[p_bounce];
+ slide_colliders.write[p_bounce]->result = motion_results[p_bounce];
return slide_colliders[p_bounce];
}
-void KinematicBody2D::set_sync_to_physics(bool p_enable) {
+void CharacterBody2D::set_sync_to_physics(bool p_enable) {
if (sync_to_physics == p_enable) {
return;
}
@@ -1079,7 +1139,7 @@ void KinematicBody2D::set_sync_to_physics(bool p_enable) {
}
if (p_enable) {
- PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &KinematicBody2D::_direct_state_changed));
+ PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &CharacterBody2D::_direct_state_changed));
set_only_update_transform_changes(true);
set_notify_local_transform(true);
} else {
@@ -1089,11 +1149,11 @@ void KinematicBody2D::set_sync_to_physics(bool p_enable) {
}
}
-bool KinematicBody2D::is_sync_to_physics_enabled() const {
+bool CharacterBody2D::is_sync_to_physics_enabled() const {
return sync_to_physics;
}
-void KinematicBody2D::_direct_state_changed(Object *p_state) {
+void CharacterBody2D::_direct_state_changed(Object *p_state) {
if (!sync_to_physics) {
return;
}
@@ -1107,7 +1167,71 @@ void KinematicBody2D::_direct_state_changed(Object *p_state) {
set_notify_local_transform(true);
}
-void KinematicBody2D::_notification(int p_what) {
+void CharacterBody2D::set_safe_margin(real_t p_margin) {
+ margin = p_margin;
+}
+
+real_t CharacterBody2D::get_safe_margin() const {
+ return margin;
+}
+
+bool CharacterBody2D::is_stop_on_slope_enabled() const {
+ return stop_on_slope;
+}
+
+void CharacterBody2D::set_stop_on_slope_enabled(bool p_enabled) {
+ stop_on_slope = p_enabled;
+}
+
+bool CharacterBody2D::is_infinite_inertia_enabled() const {
+ return infinite_inertia;
+}
+void CharacterBody2D::set_infinite_inertia_enabled(bool p_enabled) {
+ infinite_inertia = p_enabled;
+}
+
+int CharacterBody2D::get_max_slides() const {
+ return max_slides;
+}
+
+void CharacterBody2D::set_max_slides(int p_max_slides) {
+ ERR_FAIL_COND(p_max_slides > 0);
+ max_slides = p_max_slides;
+}
+
+real_t CharacterBody2D::get_floor_max_angle() const {
+ return floor_max_angle;
+}
+
+void CharacterBody2D::set_floor_max_angle(real_t p_radians) {
+ floor_max_angle = p_radians;
+}
+
+real_t CharacterBody2D::get_floor_max_angle_degrees() const {
+ return Math::rad2deg(floor_max_angle);
+}
+
+void CharacterBody2D::set_floor_max_angle_degrees(real_t p_degrees) {
+ floor_max_angle = Math::deg2rad(p_degrees);
+}
+
+const Vector2 &CharacterBody2D::get_snap() const {
+ return snap;
+}
+
+void CharacterBody2D::set_snap(const Vector2 &p_snap) {
+ snap = p_snap;
+}
+
+const Vector2 &CharacterBody2D::get_up_direction() const {
+ return up_direction;
+}
+
+void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) {
+ up_direction = p_up_direction.normalized();
+}
+
+void CharacterBody2D::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
last_valid_transform = get_global_transform();
@@ -1116,7 +1240,7 @@ void KinematicBody2D::_notification(int p_what) {
on_floor_body = RID();
on_ceiling = false;
on_wall = false;
- colliders.clear();
+ motion_results.clear();
floor_velocity = Vector2();
}
@@ -1131,47 +1255,58 @@ void KinematicBody2D::_notification(int p_what) {
}
}
-void KinematicBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody2D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
-
- ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move, DEFVAL(true));
-
- ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor);
- ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling);
- ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody2D::is_on_wall);
- ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody2D::get_floor_normal);
- ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody2D::get_floor_velocity);
+void CharacterBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody2D::move_and_slide);
+
+ ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &CharacterBody2D::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"), &CharacterBody2D::get_linear_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &CharacterBody2D::set_safe_margin);
+ ClassDB::bind_method(D_METHOD("get_safe_margin"), &CharacterBody2D::get_safe_margin);
+ ClassDB::bind_method(D_METHOD("is_stop_on_slope_enabled"), &CharacterBody2D::is_stop_on_slope_enabled);
+ ClassDB::bind_method(D_METHOD("set_stop_on_slope_enabled", "enabled"), &CharacterBody2D::set_stop_on_slope_enabled);
+ ClassDB::bind_method(D_METHOD("is_infinite_inertia_enabled"), &CharacterBody2D::is_infinite_inertia_enabled);
+ ClassDB::bind_method(D_METHOD("set_infinite_inertia_enabled", "enabled"), &CharacterBody2D::set_infinite_inertia_enabled);
+ ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides);
+ ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides);
+ ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("get_floor_max_angle_degrees"), &CharacterBody2D::get_floor_max_angle_degrees);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle_degrees", "degrees"), &CharacterBody2D::set_floor_max_angle_degrees);
+ ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody2D::get_snap);
+ ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody2D::set_snap);
+ ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction);
+ ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction);
+
+ ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody2D::is_on_floor);
+ ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody2D::is_on_ceiling);
+ ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody2D::is_on_wall);
+ ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody2D::get_floor_normal);
+ ClassDB::bind_method(D_METHOD("get_floor_velocity"), &CharacterBody2D::get_floor_velocity);
+ ClassDB::bind_method(D_METHOD("get_slide_count"), &CharacterBody2D::get_slide_count);
+ ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision);
+
+ ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &CharacterBody2D::set_sync_to_physics);
+ ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &CharacterBody2D::is_sync_to_physics_enabled);
- ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody2D::set_safe_margin);
- ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody2D::get_safe_margin);
-
- ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody2D::get_slide_count);
- ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody2D::_get_slide_collision);
-
- ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &KinematicBody2D::set_sync_to_physics);
- ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &KinematicBody2D::is_sync_to_physics_enabled);
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides"), "set_max_slides", "get_max_slides");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle_degrees", PROPERTY_HINT_RANGE, "0,180,0.1", PROPERTY_USAGE_EDITOR), "set_floor_max_angle_degrees", "get_floor_max_angle_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap"), "set_snap", "get_snap");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motion/sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
-KinematicBody2D::KinematicBody2D() :
+CharacterBody2D::CharacterBody2D() :
PhysicsBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
- margin = 0.08;
-
- on_floor = false;
- on_ceiling = false;
- on_wall = false;
- sync_to_physics = false;
}
-KinematicBody2D::~KinematicBody2D() {
- if (motion_cache.is_valid()) {
- motion_cache->owner = nullptr;
- }
-
+CharacterBody2D::~CharacterBody2D() {
for (int i = 0; i < slide_colliders.size(); i++) {
if (slide_colliders[i].is_valid()) {
slide_colliders.write[i]->owner = nullptr;
@@ -1182,39 +1317,39 @@ KinematicBody2D::~KinematicBody2D() {
////////////////////////
Vector2 KinematicCollision2D::get_position() const {
- return collision.collision;
+ return result.collision_point;
}
Vector2 KinematicCollision2D::get_normal() const {
- return collision.normal;
+ return result.collision_normal;
}
Vector2 KinematicCollision2D::get_travel() const {
- return collision.travel;
+ return result.motion;
}
Vector2 KinematicCollision2D::get_remainder() const {
- return collision.remainder;
+ return result.remainder;
}
Object *KinematicCollision2D::get_local_shape() const {
if (!owner) {
return nullptr;
}
- uint32_t ownerid = owner->shape_find_owner(collision.local_shape);
+ uint32_t ownerid = owner->shape_find_owner(result.collision_local_shape);
return owner->shape_owner_get_owner(ownerid);
}
Object *KinematicCollision2D::get_collider() const {
- if (collision.collider.is_valid()) {
- return ObjectDB::get_instance(collision.collider);
+ if (result.collider_id.is_valid()) {
+ return ObjectDB::get_instance(result.collider_id);
}
return nullptr;
}
ObjectID KinematicCollision2D::get_collider_id() const {
- return collision.collider;
+ return result.collider_id;
}
Object *KinematicCollision2D::get_collider_shape() const {
@@ -1222,7 +1357,7 @@ Object *KinematicCollision2D::get_collider_shape() const {
if (collider) {
CollisionObject2D *obj2d = Object::cast_to<CollisionObject2D>(collider);
if (obj2d) {
- uint32_t ownerid = obj2d->shape_find_owner(collision.collider_shape);
+ uint32_t ownerid = obj2d->shape_find_owner(result.collider_shape);
return obj2d->shape_owner_get_owner(ownerid);
}
}
@@ -1231,11 +1366,11 @@ Object *KinematicCollision2D::get_collider_shape() const {
}
int KinematicCollision2D::get_collider_shape_index() const {
- return collision.collider_shape;
+ return result.collider_shape;
}
Vector2 KinematicCollision2D::get_collider_velocity() const {
- return collision.collider_vel;
+ return result.collider_velocity;
}
Variant KinematicCollision2D::get_collider_metadata() const {
@@ -1267,9 +1402,3 @@ void KinematicCollision2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collider_velocity"), "", "get_collider_velocity");
ADD_PROPERTY(PropertyInfo(Variant::NIL, "collider_metadata", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "", "get_collider_metadata");
}
-
-KinematicCollision2D::KinematicCollision2D() {
- collision.collider_shape = 0;
- collision.local_shape = 0;
- owner = nullptr;
-}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index e0fc0766bc..423f792132 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -42,17 +42,22 @@ class PhysicsBody2D : public CollisionObject2D {
GDCLASS(PhysicsBody2D, CollisionObject2D);
protected:
- void _notification(int p_what);
+ static void _bind_methods();
PhysicsBody2D(PhysicsServer2D::BodyMode p_mode);
- static void _bind_methods();
+ Ref<KinematicCollision2D> motion_cache;
+
+ Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false, real_t p_margin = 0.08);
public:
+ bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
+ bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08);
+
TypedArray<PhysicsBody2D> get_collision_exceptions();
void add_collision_exception_with(Node *p_node); //must be physicsbody
void remove_collision_exception_with(Node *p_node);
- PhysicsBody2D();
+ virtual ~PhysicsBody2D();
};
class StaticBody2D : public PhysicsBody2D {
@@ -63,7 +68,10 @@ class StaticBody2D : public PhysicsBody2D {
Ref<PhysicsMaterial> physics_material_override;
+ bool kinematic_motion = false;
+
protected:
+ void _notification(int p_what);
static void _bind_methods();
public:
@@ -77,10 +85,14 @@ public:
real_t get_constant_angular_velocity() const;
StaticBody2D();
- ~StaticBody2D();
private:
void _reload_physics_characteristics();
+
+ void _update_kinematic_motion();
+
+ void set_kinematic_motion_enabled(bool p_enabled);
+ bool is_kinematic_motion_enabled() const;
};
class RigidBody2D : public PhysicsBody2D {
@@ -88,9 +100,9 @@ class RigidBody2D : public PhysicsBody2D {
public:
enum Mode {
- MODE_RIGID,
+ MODE_DYNAMIC,
MODE_STATIC,
- MODE_CHARACTER,
+ MODE_DYNAMIC_LOCKED,
MODE_KINEMATIC,
};
@@ -103,7 +115,7 @@ public:
private:
bool can_sleep = true;
PhysicsDirectBodyState2D *state = nullptr;
- Mode mode = MODE_RIGID;
+ Mode mode = MODE_DYNAMIC;
real_t mass = 1.0;
Ref<PhysicsMaterial> physics_material_override;
@@ -140,10 +152,12 @@ private:
}
};
struct RigidBody2D_RemoveAction {
+ RID rid;
ObjectID body_id;
ShapePair pair;
};
struct BodyState {
+ RID rid;
//int rc;
bool in_scene = false;
VSet<ShapePair> shapes;
@@ -158,11 +172,9 @@ private:
void _body_enter_tree(ObjectID p_id);
void _body_exit_tree(ObjectID p_id);
- void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape);
+ void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape);
void _direct_state_changed(Object *p_state);
- bool _test_motion(const Vector2 &p_motion, bool p_infinite_inertia = true, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>());
-
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -243,62 +255,73 @@ private:
VARIANT_ENUM_CAST(RigidBody2D::Mode);
VARIANT_ENUM_CAST(RigidBody2D::CCDMode);
-class KinematicBody2D : public PhysicsBody2D {
- GDCLASS(KinematicBody2D, PhysicsBody2D);
-
-public:
- struct Collision {
- Vector2 collision;
- Vector2 normal;
- Vector2 collider_vel;
- ObjectID collider;
- RID collider_rid;
- int collider_shape = 0;
- Variant collider_metadata;
- Vector2 remainder;
- Vector2 travel;
- int local_shape = 0;
- };
+class CharacterBody2D : public PhysicsBody2D {
+ GDCLASS(CharacterBody2D, PhysicsBody2D);
private:
- real_t margin;
+ real_t margin = 0.08;
+
+ bool stop_on_slope = false;
+ bool infinite_inertia = true;
+ int max_slides = 4;
+ real_t floor_max_angle = Math::deg2rad((real_t)45.0);
+ Vector2 snap;
+ Vector2 up_direction = Vector2(0.0, -1.0);
+
+ Vector2 linear_velocity;
Vector2 floor_normal;
Vector2 floor_velocity;
RID on_floor_body;
- bool on_floor;
- bool on_ceiling;
- bool on_wall;
- bool sync_to_physics;
+ bool on_floor = false;
+ bool on_ceiling = false;
+ bool on_wall = false;
+ bool sync_to_physics = false;
- Vector<Collision> colliders;
+ Vector<PhysicsServer2D::MotionResult> motion_results;
Vector<Ref<KinematicCollision2D>> slide_colliders;
- Ref<KinematicCollision2D> motion_cache;
- _FORCE_INLINE_ bool _ignores_mode(PhysicsServer2D::BodyMode) const;
-
- Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);
+ bool separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result);
+
Transform2D last_valid_transform;
void _direct_state_changed(Object *p_state);
+ void set_safe_margin(real_t p_margin);
+ real_t get_safe_margin() const;
+
+ bool is_stop_on_slope_enabled() const;
+ void set_stop_on_slope_enabled(bool p_enabled);
+
+ bool is_infinite_inertia_enabled() const;
+ void set_infinite_inertia_enabled(bool p_enabled);
+
+ int get_max_slides() const;
+ void set_max_slides(int p_max_slides);
+
+ real_t get_floor_max_angle() const;
+ void set_floor_max_angle(real_t p_radians);
+
+ real_t get_floor_max_angle_degrees() const;
+ void set_floor_max_angle_degrees(real_t p_degrees);
+
+ const Vector2 &get_snap() const;
+ void set_snap(const Vector2 &p_snap);
+
+ const Vector2 &get_up_direction() const;
+ void set_up_direction(const Vector2 &p_up_direction);
+
protected:
void _notification(int p_what);
static void _bind_methods();
public:
- bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
-
- bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia = true);
-
- bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision);
+ void move_and_slide();
- void set_safe_margin(real_t p_margin);
- real_t get_safe_margin() const;
+ const Vector2 &get_linear_velocity() const;
+ void set_linear_velocity(const Vector2 &p_velocity);
- Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, real_t p_floor_max_angle = Math::deg2rad((real_t)45.0), bool p_infinite_inertia = true);
- Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, real_t p_floor_max_angle = Math::deg2rad((real_t)45.0), bool p_infinite_inertia = true);
bool is_on_floor() const;
bool is_on_wall() const;
bool is_on_ceiling() const;
@@ -306,21 +329,22 @@ public:
Vector2 get_floor_velocity() const;
int get_slide_count() const;
- Collision get_slide_collision(int p_bounce) const;
+ PhysicsServer2D::MotionResult get_slide_collision(int p_bounce) const;
void set_sync_to_physics(bool p_enable);
bool is_sync_to_physics_enabled() const;
- KinematicBody2D();
- ~KinematicBody2D();
+ CharacterBody2D();
+ ~CharacterBody2D();
};
-class KinematicCollision2D : public Reference {
- GDCLASS(KinematicCollision2D, Reference);
+class KinematicCollision2D : public RefCounted {
+ GDCLASS(KinematicCollision2D, RefCounted);
- KinematicBody2D *owner;
- friend class KinematicBody2D;
- KinematicBody2D::Collision collision;
+ PhysicsBody2D *owner = nullptr;
+ friend class PhysicsBody2D;
+ friend class CharacterBody2D;
+ PhysicsServer2D::MotionResult result;
protected:
static void _bind_methods();
@@ -337,8 +361,6 @@ public:
int get_collider_shape_index() const;
Vector2 get_collider_velocity() const;
Variant get_collider_metadata() const;
-
- KinematicCollision2D();
};
#endif // PHYSICS_BODY_2D_H
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index 5c7d65e3e0..1019f85c8a 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -36,10 +36,41 @@
const real_t DEFAULT_GIZMO_EXTENTS = 10.0;
void Position2D::_draw_cross() {
- real_t extents = get_gizmo_extents();
- // Colors taken from `axis_x_color` and `axis_y_color` (defined in `editor/editor_themes.cpp`)
- draw_line(Point2(-extents, 0), Point2(+extents, 0), Color(0.96, 0.20, 0.32));
- draw_line(Point2(0, -extents), Point2(0, +extents), Color(0.53, 0.84, 0.01));
+ const real_t extents = get_gizmo_extents();
+
+ // Add more points to create a "hard stop" in the color gradient.
+ PackedVector2Array points_x;
+ points_x.push_back(Point2(+extents, 0));
+ points_x.push_back(Point2());
+ points_x.push_back(Point2());
+ points_x.push_back(Point2(-extents, 0));
+
+ PackedVector2Array points_y;
+ points_y.push_back(Point2(0, +extents));
+ points_y.push_back(Point2());
+ points_y.push_back(Point2());
+ points_y.push_back(Point2(0, -extents));
+
+ // Use the axis color which is brighter for the positive axis.
+ // Use a darkened axis color for the negative axis.
+ // This makes it possible to see in which direction the Position3D node is rotated
+ // (which can be important depending on how it's used).
+ // Axis colors are taken from `axis_x_color` and `axis_y_color` (defined in `editor/editor_themes.cpp`).
+ PackedColorArray colors_x;
+ const Color color_x = Color(0.96, 0.20, 0.32);
+ colors_x.push_back(color_x);
+ colors_x.push_back(color_x);
+ colors_x.push_back(color_x.lerp(Color(0, 0, 0), 0.5));
+ colors_x.push_back(color_x.lerp(Color(0, 0, 0), 0.5));
+ draw_multiline_colors(points_x, colors_x);
+
+ PackedColorArray colors_y;
+ const Color color_y = Color(0.53, 0.84, 0.01);
+ colors_y.push_back(color_y);
+ colors_y.push_back(color_y);
+ colors_y.push_back(color_y.lerp(Color(0, 0, 0), 0.5));
+ colors_y.push_back(color_y.lerp(Color(0, 0, 0), 0.5));
+ draw_multiline_colors(points_y, colors_y);
}
#ifdef TOOLS_ENABLED
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 22180797f0..8f1f5fadbc 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -30,6 +30,69 @@
#include "skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_settings.h"
+#include "editor/plugins/canvas_item_editor_plugin.h"
+#endif //TOOLS_ENABLED
+
+bool Bone2D::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path.begins_with("auto_calculate_length_and_angle")) {
+ set_autocalculate_length_and_angle(p_value);
+ } else if (path.begins_with("length")) {
+ set_length(p_value);
+ } else if (path.begins_with("bone_angle")) {
+ set_bone_angle(Math::deg2rad(float(p_value)));
+ } else if (path.begins_with("default_length")) {
+ set_length(p_value);
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path.begins_with("editor_settings/show_bone_gizmo")) {
+ _editor_set_show_bone_gizmo(p_value);
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+bool Bone2D::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("auto_calculate_length_and_angle")) {
+ r_ret = get_autocalculate_length_and_angle();
+ } else if (path.begins_with("length")) {
+ r_ret = get_length();
+ } else if (path.begins_with("bone_angle")) {
+ r_ret = Math::rad2deg(get_bone_angle());
+ } else if (path.begins_with("default_length")) {
+ r_ret = get_length();
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path.begins_with("editor_settings/show_bone_gizmo")) {
+ r_ret = _editor_get_show_bone_gizmo();
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+void Bone2D::_get_property_list(List<PropertyInfo> *p_list) const {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "auto_calculate_length_and_angle", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ if (!autocalculate_length_and_angle) {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "1, 1024, 1", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "bone_angle", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
+ }
+
+#ifdef TOOLS_ENABLED
+ p_list->push_back(PropertyInfo(Variant::BOOL, "editor_settings/show_bone_gizmo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+#endif // TOOLS_ENABLED
+}
+
void Bone2D::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
Node *parent = get_parent();
@@ -53,19 +116,54 @@ void Bone2D::_notification(int p_what) {
skeleton->bones.push_back(bone);
skeleton->_make_bone_setup_dirty();
}
+
+ cache_transform = get_transform();
+ copy_transform_to_cache = true;
+
+#ifdef TOOLS_ENABLED
+ // Only draw the gizmo in the editor!
+ if (Engine::get_singleton()->is_editor_hint() == false) {
+ return;
+ }
+
+ update();
+#endif // TOOLS_ENABLED
}
- if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
+
+ else if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
if (skeleton) {
skeleton->_make_transform_dirty();
}
+ if (copy_transform_to_cache) {
+ cache_transform = get_transform();
+ }
+#ifdef TOOLS_ENABLED
+ // Only draw the gizmo in the editor!
+ if (Engine::get_singleton()->is_editor_hint() == false) {
+ return;
+ }
+
+ update();
+
+ if (get_parent()) {
+ Bone2D *parent_bone = Object::cast_to<Bone2D>(get_parent());
+ if (parent_bone) {
+ parent_bone->update();
+ }
+ }
+#endif // TOOLS_ENABLED
}
- if (p_what == NOTIFICATION_MOVED_IN_PARENT) {
+
+ else if (p_what == NOTIFICATION_MOVED_IN_PARENT) {
if (skeleton) {
skeleton->_make_bone_setup_dirty();
}
+ if (copy_transform_to_cache) {
+ cache_transform = get_transform();
+ }
}
- if (p_what == NOTIFICATION_EXIT_TREE) {
+ else if (p_what == NOTIFICATION_EXIT_TREE) {
if (skeleton) {
for (int i = 0; i < skeleton->bones.size(); i++) {
if (skeleton->bones[i].bone == this) {
@@ -77,9 +175,200 @@ void Bone2D::_notification(int p_what) {
skeleton = nullptr;
}
parent_bone = nullptr;
+ set_transform(cache_transform);
}
+
+ else if (p_what == NOTIFICATION_READY) {
+ if (autocalculate_length_and_angle) {
+ calculate_length_and_rotation();
+ }
+ }
+#ifdef TOOLS_ENABLED
+ else if (p_what == NOTIFICATION_EDITOR_PRE_SAVE || p_what == NOTIFICATION_EDITOR_POST_SAVE) {
+ Transform2D tmp_trans = get_transform();
+ set_transform(cache_transform);
+ cache_transform = tmp_trans;
+ }
+ // Bone2D Editor gizmo drawing:
+#ifndef _MSC_VER
+#warning TODO Bone2D gizmo drawing needs to be moved to an editor plugin
+#endif
+ else if (p_what == NOTIFICATION_DRAW) {
+ // Only draw the gizmo in the editor!
+ if (Engine::get_singleton()->is_editor_hint() == false) {
+ return;
+ }
+
+ if (editor_gizmo_rid.is_null()) {
+ editor_gizmo_rid = RenderingServer::get_singleton()->canvas_item_create();
+ RenderingServer::get_singleton()->canvas_item_set_parent(editor_gizmo_rid, get_canvas_item());
+ RenderingServer::get_singleton()->canvas_item_set_z_as_relative_to_parent(editor_gizmo_rid, true);
+ RenderingServer::get_singleton()->canvas_item_set_z_index(editor_gizmo_rid, 10);
+ }
+ RenderingServer::get_singleton()->canvas_item_clear(editor_gizmo_rid);
+
+ if (!_editor_show_bone_gizmo) {
+ return;
+ }
+
+ // Undo scaling
+ Transform2D editor_gizmo_trans = Transform2D();
+ editor_gizmo_trans.set_scale(Vector2(1, 1) / get_global_scale());
+ RenderingServer::get_singleton()->canvas_item_set_transform(editor_gizmo_rid, editor_gizmo_trans);
+
+ Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1");
+ Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2");
+ Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
+ Color bone_outline_color = EditorSettings::get_singleton()->get("editors/2d/bone_outline_color");
+ Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
+
+ bool Bone2D_found = false;
+ for (int i = 0; i < get_child_count(); i++) {
+ Bone2D *child_node = nullptr;
+ child_node = Object::cast_to<Bone2D>(get_child(i));
+ if (!child_node) {
+ continue;
+ }
+ Bone2D_found = true;
+
+ Vector<Vector2> bone_shape;
+ Vector<Vector2> bone_shape_outline;
+
+ _editor_get_bone_shape(&bone_shape, &bone_shape_outline, child_node);
+
+ Vector<Color> colors;
+ if (has_meta("_local_pose_override_enabled_")) {
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ } else {
+ colors.push_back(bone_color1);
+ colors.push_back(bone_color2);
+ colors.push_back(bone_color1);
+ colors.push_back(bone_color2);
+ }
+
+ Vector<Color> outline_colors;
+ if (CanvasItemEditor::get_singleton()->editor_selection->is_selected(this)) {
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ } else {
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ }
+
+ RenderingServer::get_singleton()->canvas_item_add_polygon(editor_gizmo_rid, bone_shape_outline, outline_colors);
+ RenderingServer::get_singleton()->canvas_item_add_polygon(editor_gizmo_rid, bone_shape, colors);
+ }
+
+ if (!Bone2D_found) {
+ Vector<Vector2> bone_shape;
+ Vector<Vector2> bone_shape_outline;
+
+ _editor_get_bone_shape(&bone_shape, &bone_shape_outline, nullptr);
+
+ Vector<Color> colors;
+ if (has_meta("_local_pose_override_enabled_")) {
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ } else {
+ colors.push_back(bone_color1);
+ colors.push_back(bone_color2);
+ colors.push_back(bone_color1);
+ colors.push_back(bone_color2);
+ }
+
+ Vector<Color> outline_colors;
+ if (CanvasItemEditor::get_singleton()->editor_selection->is_selected(this)) {
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ } else {
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ }
+
+ RenderingServer::get_singleton()->canvas_item_add_polygon(editor_gizmo_rid, bone_shape_outline, outline_colors);
+ RenderingServer::get_singleton()->canvas_item_add_polygon(editor_gizmo_rid, bone_shape, colors);
+ }
+ }
+#endif // TOOLS_ENALBED
}
+#ifdef TOOLS_ENABLED
+bool Bone2D::_editor_get_bone_shape(Vector<Vector2> *p_shape, Vector<Vector2> *p_outline_shape, Bone2D *p_other_bone) {
+ int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
+ int bone_outline_width = EditorSettings::get_singleton()->get("editors/2d/bone_outline_size");
+
+ if (!is_inside_tree()) {
+ return false; //may have been removed
+ }
+ if (!p_other_bone && length <= 0) {
+ return false;
+ }
+
+ Vector2 rel;
+ if (p_other_bone) {
+ rel = (p_other_bone->get_global_transform().get_origin() - get_global_transform().get_origin());
+ rel = rel.rotated(-get_global_rotation()); // Undo Bone2D node's rotation so its drawn correctly regardless of the node's rotation
+ } else {
+ float angle_to_use = get_rotation() + bone_angle;
+ rel = Vector2(cos(angle_to_use), sin(angle_to_use)) * (length * MIN(get_global_scale().x, get_global_scale().y));
+ rel = rel.rotated(-get_rotation()); // Undo Bone2D node's rotation so its drawn correctly regardless of the node's rotation
+ }
+
+ Vector2 relt = rel.rotated(Math_PI * 0.5).normalized() * bone_width;
+ Vector2 reln = rel.normalized();
+ Vector2 reltn = relt.normalized();
+
+ if (p_shape) {
+ p_shape->clear();
+ p_shape->push_back(Vector2(0, 0));
+ p_shape->push_back(rel * 0.2 + relt);
+ p_shape->push_back(rel);
+ p_shape->push_back(rel * 0.2 - relt);
+ }
+
+ if (p_outline_shape) {
+ p_outline_shape->clear();
+ p_outline_shape->push_back((-reln - reltn) * bone_outline_width);
+ p_outline_shape->push_back((-reln + reltn) * bone_outline_width);
+ p_outline_shape->push_back(rel * 0.2 + relt + reltn * bone_outline_width);
+ p_outline_shape->push_back(rel + (reln + reltn) * bone_outline_width);
+ p_outline_shape->push_back(rel + (reln - reltn) * bone_outline_width);
+ p_outline_shape->push_back(rel * 0.2 - relt - reltn * bone_outline_width);
+ }
+ return true;
+}
+
+void Bone2D::_editor_set_show_bone_gizmo(bool p_show_gizmo) {
+ _editor_show_bone_gizmo = p_show_gizmo;
+ update();
+}
+
+bool Bone2D::_editor_get_show_bone_gizmo() const {
+ return _editor_show_bone_gizmo;
+}
+#endif // TOOLS_ENABLED
+
void Bone2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rest", "rest"), &Bone2D::set_rest);
ClassDB::bind_method(D_METHOD("get_rest"), &Bone2D::get_rest);
@@ -90,8 +379,14 @@ void Bone2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_length", "default_length"), &Bone2D::set_default_length);
ClassDB::bind_method(D_METHOD("get_default_length"), &Bone2D::get_default_length);
+ ClassDB::bind_method(D_METHOD("set_autocalculate_length_and_angle", "auto_calculate"), &Bone2D::set_autocalculate_length_and_angle);
+ ClassDB::bind_method(D_METHOD("get_autocalculate_length_and_angle"), &Bone2D::get_autocalculate_length_and_angle);
+ ClassDB::bind_method(D_METHOD("set_length", "length"), &Bone2D::set_length);
+ ClassDB::bind_method(D_METHOD("get_length"), &Bone2D::get_length);
+ ClassDB::bind_method(D_METHOD("set_bone_angle", "angle"), &Bone2D::set_bone_angle);
+ ClassDB::bind_method(D_METHOD("get_bone_angle"), &Bone2D::get_bone_angle);
+
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "rest"), "set_rest", "get_rest");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_length", PROPERTY_HINT_RANGE, "1,1024,1"), "set_default_length", "get_default_length");
}
void Bone2D::set_rest(const Transform2D &p_rest) {
@@ -119,12 +414,14 @@ void Bone2D::apply_rest() {
set_transform(rest);
}
-void Bone2D::set_default_length(real_t p_length) {
- default_length = p_length;
+void Bone2D::set_default_length(float p_length) {
+ WARN_DEPRECATED_MSG("set_default_length is deprecated. Please use set_length instead!");
+ set_length(p_length);
}
-real_t Bone2D::get_default_length() const {
- return default_length;
+float Bone2D::get_default_length() const {
+ WARN_DEPRECATED_MSG("get_default_length is deprecated. Please use get_length instead!");
+ return get_length();
}
int Bone2D::get_index_in_skeleton() const {
@@ -150,16 +447,121 @@ TypedArray<String> Bone2D::get_configuration_warnings() const {
return warnings;
}
+void Bone2D::calculate_length_and_rotation() {
+ // if there is at least a single child Bone2D node, we can calculate
+ // the length and direction. We will always just use the first Bone2D for this.
+ bool calculated = false;
+ int child_count = get_child_count();
+ if (child_count > 0) {
+ for (int i = 0; i < child_count; i++) {
+ Bone2D *child = Object::cast_to<Bone2D>(get_child(i));
+ if (child) {
+ Vector2 child_local_pos = to_local(child->get_global_transform().get_origin());
+ length = child_local_pos.length();
+ bone_angle = Math::atan2(child_local_pos.normalized().y, child_local_pos.normalized().x);
+ calculated = true;
+ break;
+ }
+ }
+ }
+ if (calculated) {
+ return; // Finished!
+ } else {
+ WARN_PRINT("No Bone2D children of node " + get_name() + ". Cannot calculate bone length or angle reliably.\nUsing transform rotation for bone angle");
+ bone_angle = get_transform().get_rotation();
+ return;
+ }
+}
+
+void Bone2D::set_autocalculate_length_and_angle(bool p_autocalculate) {
+ autocalculate_length_and_angle = p_autocalculate;
+ if (autocalculate_length_and_angle) {
+ calculate_length_and_rotation();
+ }
+ notify_property_list_changed();
+}
+
+bool Bone2D::get_autocalculate_length_and_angle() const {
+ return autocalculate_length_and_angle;
+}
+
+void Bone2D::set_length(float p_length) {
+ length = p_length;
+
+#ifdef TOOLS_ENABLED
+ update();
+#endif // TOOLS_ENABLED
+}
+
+float Bone2D::get_length() const {
+ return length;
+}
+
+void Bone2D::set_bone_angle(float p_angle) {
+ bone_angle = p_angle;
+
+#ifdef TOOLS_ENABLED
+ update();
+#endif // TOOLS_ENABLED
+}
+
+float Bone2D::get_bone_angle() const {
+ return bone_angle;
+}
+
Bone2D::Bone2D() {
+ skeleton = nullptr;
+ parent_bone = nullptr;
+ skeleton_index = -1;
+ length = 16;
+ bone_angle = 0;
+ autocalculate_length_and_angle = true;
set_notify_local_transform(true);
//this is a clever hack so the bone knows no rest has been set yet, allowing to show an error.
for (int i = 0; i < 3; i++) {
rest[i] = Vector2(0, 0);
}
+ copy_transform_to_cache = true;
+}
+
+Bone2D::~Bone2D() {
+#ifdef TOOLS_ENABLED
+ if (!editor_gizmo_rid.is_null()) {
+ RenderingServer::get_singleton()->free(editor_gizmo_rid);
+ }
+#endif // TOOLS_ENABLED
}
//////////////////////////////////////
+bool Skeleton2D::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path.begins_with("modification_stack")) {
+ set_modification_stack(p_value);
+ return true;
+ }
+ return true;
+}
+
+bool Skeleton2D::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("modification_stack")) {
+ r_ret = get_modification_stack();
+ return true;
+ }
+ return true;
+}
+
+void Skeleton2D::_get_property_list(List<PropertyInfo> *p_list) const {
+ p_list->push_back(
+ PropertyInfo(Variant::OBJECT, "modification_stack",
+ PROPERTY_HINT_RESOURCE_TYPE,
+ "SkeletonModificationStack2D",
+ PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
+}
+
void Skeleton2D::_make_bone_setup_dirty() {
if (bone_setup_dirty) {
return;
@@ -189,6 +591,8 @@ void Skeleton2D::_update_bone_setup() {
} else {
bones.write[i].parent_index = -1;
}
+
+ bones.write[i].local_pose_override = bones[i].bone->get_skeleton_rest();
}
transform_dirty = true;
@@ -257,19 +661,121 @@ void Skeleton2D::_notification(int p_what) {
if (transform_dirty) {
_update_transform();
}
-
request_ready();
}
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
RS::get_singleton()->skeleton_set_base_transform_2d(skeleton, get_global_transform());
+ } else if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
+ if (modification_stack.is_valid()) {
+ execute_modifications(get_process_delta_time(), SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_process);
+ }
+ } else if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
+ if (modification_stack.is_valid()) {
+ execute_modifications(get_physics_process_delta_time(), SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_physics_process);
+ }
}
+#ifdef TOOLS_ENABLED
+ else if (p_what == NOTIFICATION_DRAW) {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (modification_stack.is_valid()) {
+ modification_stack->draw_editor_gizmos();
+ }
+ }
+ }
+#endif // TOOLS_ENABLED
}
RID Skeleton2D::get_skeleton() const {
return skeleton;
}
+void Skeleton2D::set_bone_local_pose_override(int p_bone_idx, Transform2D p_override, float p_amount, bool p_persistent) {
+ ERR_FAIL_INDEX_MSG(p_bone_idx, bones.size(), "Bone index is out of range!");
+ bones.write[p_bone_idx].local_pose_override = p_override;
+ bones.write[p_bone_idx].local_pose_override_amount = p_amount;
+ bones.write[p_bone_idx].local_pose_override_persistent = p_persistent;
+}
+
+Transform2D Skeleton2D::get_bone_local_pose_override(int p_bone_idx) {
+ ERR_FAIL_INDEX_V_MSG(p_bone_idx, bones.size(), Transform2D(), "Bone index is out of range!");
+ return bones[p_bone_idx].local_pose_override;
+}
+
+void Skeleton2D::set_modification_stack(Ref<SkeletonModificationStack2D> p_stack) {
+ if (modification_stack.is_valid()) {
+ modification_stack->is_setup = false;
+ modification_stack->set_skeleton(nullptr);
+
+ set_process_internal(false);
+ set_physics_process_internal(false);
+ }
+ modification_stack = p_stack;
+ if (modification_stack.is_valid()) {
+ modification_stack->set_skeleton(this);
+ modification_stack->setup();
+
+ set_process_internal(true);
+ set_physics_process_internal(true);
+
+#ifdef TOOLS_ENABLED
+ modification_stack->set_editor_gizmos_dirty(true);
+#endif // TOOLS_ENABLED
+ }
+}
+
+Ref<SkeletonModificationStack2D> Skeleton2D::get_modification_stack() const {
+ return modification_stack;
+}
+
+void Skeleton2D::execute_modifications(float p_delta, int p_execution_mode) {
+ if (!modification_stack.is_valid()) {
+ return;
+ }
+
+ // Do not cache the transform changes caused by the modifications!
+ for (int i = 0; i < bones.size(); i++) {
+ bones[i].bone->copy_transform_to_cache = false;
+ }
+
+ if (modification_stack->skeleton != this) {
+ modification_stack->set_skeleton(this);
+ }
+
+ modification_stack->execute(p_delta, p_execution_mode);
+
+ // Only apply the local pose override on _process. Otherwise, just calculate the local_pose_override and reset the transform.
+ if (p_execution_mode == SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_process) {
+ for (int i = 0; i < bones.size(); i++) {
+ if (bones[i].local_pose_override_amount > 0) {
+ bones[i].bone->set_meta("_local_pose_override_enabled_", true);
+
+ Transform2D final_trans = bones[i].bone->cache_transform;
+ final_trans = final_trans.interpolate_with(bones[i].local_pose_override, bones[i].local_pose_override_amount);
+ bones[i].bone->set_transform(final_trans);
+ bones[i].bone->propagate_call("force_update_transform");
+
+ if (bones[i].local_pose_override_persistent) {
+ bones.write[i].local_pose_override_amount = 0.0;
+ }
+ } else {
+ // TODO: see if there is a way to undo the override without having to resort to setting every bone's transform.
+ bones[i].bone->remove_meta("_local_pose_override_enabled_");
+ bones[i].bone->set_transform(bones[i].bone->cache_transform);
+ }
+ }
+ }
+
+ // Cache any future transform changes
+ for (int i = 0; i < bones.size(); i++) {
+ bones[i].bone->copy_transform_to_cache = true;
+ }
+
+#ifdef TOOLS_ENABLED
+ modification_stack->set_editor_gizmos_dirty(true);
+#endif // TOOLS_ENABLED
+}
+
void Skeleton2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_bone_setup"), &Skeleton2D::_update_bone_setup);
ClassDB::bind_method(D_METHOD("_update_transform"), &Skeleton2D::_update_transform);
@@ -279,6 +785,13 @@ void Skeleton2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_skeleton"), &Skeleton2D::get_skeleton);
+ ClassDB::bind_method(D_METHOD("set_modification_stack", "modification_stack"), &Skeleton2D::set_modification_stack);
+ ClassDB::bind_method(D_METHOD("get_modification_stack"), &Skeleton2D::get_modification_stack);
+ ClassDB::bind_method(D_METHOD("execute_modifications", "delta", "execution_mode"), &Skeleton2D::execute_modifications);
+
+ ClassDB::bind_method(D_METHOD("set_bone_local_pose_override", "bone_idx", "override_pose", "strength", "persistent"), &Skeleton2D::set_bone_local_pose_override);
+ ClassDB::bind_method(D_METHOD("get_bone_local_pose_override", "bone_idx"), &Skeleton2D::get_bone_local_pose_override);
+
ADD_SIGNAL(MethodInfo("bone_setup_changed"));
}
diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h
index fd62b87bde..59bd711960 100644
--- a/scene/2d/skeleton_2d.h
+++ b/scene/2d/skeleton_2d.h
@@ -32,6 +32,7 @@
#define SKELETON_2D_H
#include "scene/2d/node_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
class Skeleton2D;
@@ -46,15 +47,32 @@ class Bone2D : public Node2D {
Bone2D *parent_bone = nullptr;
Skeleton2D *skeleton = nullptr;
Transform2D rest;
- real_t default_length = 16.0;
+
+ bool autocalculate_length_and_angle = true;
+ float length = 16;
+ float bone_angle = 0;
int skeleton_index = -1;
+ void calculate_length_and_rotation();
+
+#ifdef TOOLS_ENABLED
+ RID editor_gizmo_rid;
+ bool _editor_get_bone_shape(Vector<Vector2> *p_shape, Vector<Vector2> *p_outline_shape, Bone2D *p_other_bone);
+ bool _editor_show_bone_gizmo = true;
+#endif // TOOLS ENABLED
+
protected:
void _notification(int p_what);
static void _bind_methods();
+ bool _set(const StringName &p_path, const Variant &p_value);
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
public:
+ Transform2D cache_transform;
+ bool copy_transform_to_cache = true;
+
void set_rest(const Transform2D &p_rest);
Transform2D get_rest() const;
void apply_rest();
@@ -65,11 +83,26 @@ public:
void set_default_length(real_t p_length);
real_t get_default_length() const;
+ void set_autocalculate_length_and_angle(bool p_autocalculate);
+ bool get_autocalculate_length_and_angle() const;
+ void set_length(float p_length);
+ float get_length() const;
+ void set_bone_angle(float p_angle);
+ float get_bone_angle() const;
+
int get_index_in_skeleton() const;
+#ifdef TOOLS_ENABLED
+ void _editor_set_show_bone_gizmo(bool p_show_gizmo);
+ bool _editor_get_show_bone_gizmo() const;
+#endif // TOOLS_ENABLED
+
Bone2D();
+ ~Bone2D();
};
+class SkeletonModificationStack2D;
+
class Skeleton2D : public Node2D {
GDCLASS(Skeleton2D, Node2D);
@@ -86,6 +119,11 @@ class Skeleton2D : public Node2D {
int parent_index = 0;
Transform2D accum_transform;
Transform2D rest_inverse;
+
+ //Transform2D local_pose_cache;
+ Transform2D local_pose_override;
+ float local_pose_override_amount = 0;
+ bool local_pose_override_persistent = false;
};
Vector<Bone> bones;
@@ -100,15 +138,28 @@ class Skeleton2D : public Node2D {
RID skeleton;
+ Ref<SkeletonModificationStack2D> modification_stack;
+
protected:
void _notification(int p_what);
static void _bind_methods();
+ bool _set(const StringName &p_path, const Variant &p_value);
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
public:
int get_bone_count() const;
Bone2D *get_bone(int p_idx);
RID get_skeleton() const;
+
+ void set_bone_local_pose_override(int p_bone_idx, Transform2D p_override, float p_amount, bool p_persistent = true);
+ Transform2D get_bone_local_pose_override(int p_bone_idx);
+
+ Ref<SkeletonModificationStack2D> get_modification_stack() const;
+ void set_modification_stack(Ref<SkeletonModificationStack2D> p_stack);
+ void execute_modifications(float p_delta, int p_execution_mode);
+
Skeleton2D();
~Skeleton2D();
};
diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp
index 7c93edbff9..40e0f4523f 100644
--- a/scene/2d/sprite_2d.cpp
+++ b/scene/2d/sprite_2d.cpp
@@ -153,7 +153,7 @@ void Sprite2D::set_texture(const Ref<Texture2D> &p_texture) {
}
update();
- emit_signal("texture_changed");
+ emit_signal(SceneStringNames::get_singleton()->texture_changed);
item_rect_changed();
}
@@ -254,15 +254,15 @@ int Sprite2D::get_frame() const {
return frame;
}
-void Sprite2D::set_frame_coords(const Vector2 &p_coord) {
- ERR_FAIL_INDEX(int(p_coord.x), hframes);
- ERR_FAIL_INDEX(int(p_coord.y), vframes);
+void Sprite2D::set_frame_coords(const Vector2i &p_coord) {
+ ERR_FAIL_INDEX(p_coord.x, hframes);
+ ERR_FAIL_INDEX(p_coord.y, vframes);
- set_frame(int(p_coord.y) * hframes + int(p_coord.x));
+ set_frame(p_coord.y * hframes + p_coord.x);
}
-Vector2 Sprite2D::get_frame_coords() const {
- return Vector2(frame % hframes, frame / hframes);
+Vector2i Sprite2D::get_frame_coords() const {
+ return Vector2i(frame % hframes, frame / hframes);
}
void Sprite2D::set_vframes(int p_amount) {
@@ -452,7 +452,7 @@ void Sprite2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h
index 9db74cfe26..49df78c59d 100644
--- a/scene/2d/sprite_2d.h
+++ b/scene/2d/sprite_2d.h
@@ -109,8 +109,8 @@ public:
void set_frame(int p_frame);
int get_frame() const;
- void set_frame_coords(const Vector2 &p_coord);
- Vector2 get_frame_coords() const;
+ void set_frame_coords(const Vector2i &p_coord);
+ Vector2i get_frame_coords() const;
void set_vframes(int p_amount);
int get_vframes() const;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 0afead0863..e39c8841cd 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -64,13 +64,13 @@ int TileMapPattern::get_cell_source_id(const Vector2i &p_coords) const {
}
Vector2i TileMapPattern::get_cell_atlas_coords(const Vector2i &p_coords) const {
- ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetAtlasSource::INVALID_ATLAS_COORDS);
+ ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetSource::INVALID_ATLAS_COORDS);
return pattern[p_coords].get_atlas_coords();
}
int TileMapPattern::get_cell_alternative_tile(const Vector2i &p_coords) const {
- ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetSource::INVALID_TILE_ALTERNATIVE);
return pattern[p_coords].alternative_tile;
}
@@ -113,7 +113,7 @@ void TileMapPattern::clear() {
};
void TileMapPattern::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(-1), DEFVAL(TileSetAtlasSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE));
+ ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(-1), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
ClassDB::bind_method(D_METHOD("has_cell", "coords"), &TileMapPattern::has_cell);
ClassDB::bind_method(D_METHOD("remove_cell", "coords"), &TileMapPattern::remove_cell);
ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapPattern::get_cell_source_id);
@@ -314,37 +314,30 @@ void TileMap::set_quadrant_size(int p_size) {
emit_signal("changed");
}
-void TileMap::_fix_cell_transform(Transform2D &xform, const TileMapCell &p_cell, const Vector2 &p_offset, const Size2 &p_sc) {
- Size2 s = p_sc;
- Vector2 offset = p_offset;
+void TileMap::set_collision_visibility_mode(TileMap::VisibilityMode p_show_collision) {
+ show_collision = p_show_collision;
+ _recreate_quadrants();
+ emit_signal("changed");
+}
- // Flip/transpose: update the tile transform.
- TileSetSource *source = *tile_set->get_source(p_cell.source_id);
- TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
- if (!atlas_source) {
- return;
- }
- TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(p_cell.get_atlas_coords(), p_cell.alternative_tile));
- if (tile_data->get_transpose()) {
- SWAP(xform.elements[0].x, xform.elements[0].y);
- SWAP(xform.elements[1].x, xform.elements[1].y);
- SWAP(offset.x, offset.y);
- SWAP(s.x, s.y);
- }
+TileMap::VisibilityMode TileMap::get_collision_visibility_mode() {
+ return show_collision;
+}
- if (tile_data->get_flip_h()) {
- xform.elements[0].x = -xform.elements[0].x;
- xform.elements[1].x = -xform.elements[1].x;
- offset.x = s.x - offset.x;
- }
+void TileMap::set_navigation_visibility_mode(TileMap::VisibilityMode p_show_navigation) {
+ show_navigation = p_show_navigation;
+ _recreate_quadrants();
+ emit_signal("changed");
+}
- if (tile_data->get_flip_v()) {
- xform.elements[0].y = -xform.elements[0].y;
- xform.elements[1].y = -xform.elements[1].y;
- offset.y = s.y - offset.y;
- }
+TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() {
+ return show_navigation;
+}
- xform.elements[2] += offset;
+void TileMap::set_y_sort_enabled(bool p_enable) {
+ Node2D::set_y_sort_enabled(p_enable);
+ _recreate_quadrants();
+ emit_signal("changed");
}
void TileMap::update_dirty_quadrants() {
@@ -520,12 +513,12 @@ void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i
Vector2i atlas_coords = p_atlas_coords;
int alternative_tile = p_alternative_tile;
- if ((source_id == -1 || atlas_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) &&
- (source_id != -1 || atlas_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE)) {
+ if ((source_id == -1 || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) &&
+ (source_id != -1 || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) {
WARN_PRINT("Setting a cell a cell as empty requires both source_id, atlas_coord and alternative_tile to be set to their respective \"invalid\" values. Values were thus changes accordingly.");
source_id = -1;
- atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
- alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ atlas_coords = TileSetSource::INVALID_ATLAS_COORDS;
+ alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
}
if (!E && source_id == -1) {
@@ -602,7 +595,7 @@ Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords) const {
const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
if (!E) {
- return TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ return TileSetSource::INVALID_ATLAS_COORDS;
}
return E->get().get_atlas_coords();
@@ -613,7 +606,7 @@ int TileMap::get_cell_alternative_tile(const Vector2i &p_coords) const {
const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
if (!E) {
- return TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ return TileSetSource::INVALID_TILE_ALTERNATIVE;
}
return E->get().alternative_tile;
@@ -718,12 +711,17 @@ Map<Vector2i, TileMapQuadrant> &TileMap::get_quadrant_map() {
void TileMap::fix_invalid_tiles() {
ERR_FAIL_COND_MSG(tile_set.is_null(), "Cannot fix invalid tiles if Tileset is not open.");
+
+ Set<Vector2i> coords;
for (Map<Vector2i, TileMapCell>::Element *E = tile_map.front(); E; E = E->next()) {
TileSetSource *source = *tile_set->get_source(E->get().source_id);
if (!source || !source->has_tile(E->get().get_atlas_coords()) || !source->has_alternative_tile(E->get().get_atlas_coords(), E->get().alternative_tile)) {
- set_cell(E->key(), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ coords.insert(E->key());
}
}
+ for (Set<Vector2i>::Element *E = coords.front(); E; E = E->next()) {
+ set_cell(E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ }
}
void TileMap::_recreate_quadrants() {
@@ -777,6 +775,11 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
int offset = (format >= FORMAT_2) ? 3 : 2;
clear();
+
+#ifdef DISABLE_DEPRECATED
+ ERR_FAIL_COND_MSG(format != FORMAT_3, vformat("Cannot handle deprecated TileMap data format version %d. This Godot version was compiled with no support for deprecated data.", format));
+#endif
+
for (int i = 0; i < c; i += offset) {
const uint8_t *ptr = (const uint8_t *)&r[i];
uint8_t local[12];
@@ -806,6 +809,7 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
uint16_t alternative_tile = decode_uint16(&local[10]);
set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile);
} else {
+#ifndef DISABLE_DEPRECATED
uint32_t v = decode_uint32(&local[4]);
v &= (1 << 29) - 1;
@@ -828,6 +832,7 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
}
set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
+#endif
}
}
}
@@ -1716,7 +1721,13 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_quadrant_size", "size"), &TileMap::set_quadrant_size);
ClassDB::bind_method(D_METHOD("get_quadrant_size"), &TileMap::get_quadrant_size);
- ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(-1), DEFVAL(TileSetAtlasSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE));
+ ClassDB::bind_method(D_METHOD("set_collision_visibility_mode", "show_collision"), &TileMap::set_collision_visibility_mode);
+ ClassDB::bind_method(D_METHOD("get_collision_visibility_mode"), &TileMap::get_collision_visibility_mode);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_visibility_mode", "show_navigation"), &TileMap::set_navigation_visibility_mode);
+ ClassDB::bind_method(D_METHOD("get_navigation_visibility_mode"), &TileMap::get_navigation_visibility_mode);
+
+ ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(-1), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMap::get_cell_source_id);
ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMap::get_cell_atlas_coords);
ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMap::get_cell_alternative_tile);
@@ -1740,10 +1751,16 @@ void TileMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tileset", "get_tileset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_quadrant_size", PROPERTY_HINT_RANGE, "1,128,1"), "set_quadrant_size", "get_quadrant_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "show_collision", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_collision_visibility_mode", "get_collision_visibility_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "show_navigation", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_navigation_visibility_mode", "get_navigation_visibility_mode");
ADD_PROPERTY_DEFAULT("format", FORMAT_1);
ADD_SIGNAL(MethodInfo("changed"));
+
+ BIND_ENUM_CONSTANT(VISIBILITY_MODE_DEFAULT);
+ BIND_ENUM_CONSTANT(VISIBILITY_MODE_FORCE_HIDE);
+ BIND_ENUM_CONSTANT(VISIBILITY_MODE_FORCE_SHOW);
}
void TileMap::_tile_set_changed() {
@@ -1752,12 +1769,6 @@ void TileMap::_tile_set_changed() {
}
TileMap::TileMap() {
- rect_cache_dirty = true;
- used_size_cache_dirty = true;
- pending_update = false;
- quadrant_size = 16;
- format = FORMAT_1; // Assume lowest possible format if none is present
-
set_notify_transform(true);
set_notify_local_transform(false);
}
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index e9dbccbdb9..3001e6b471 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -48,7 +48,7 @@ union TileMapCell {
};
uint64_t _u64t;
- TileMapCell(int p_source_id = -1, Vector2i p_atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ TileMapCell(int p_source_id = -1, Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE) {
source_id = p_source_id;
set_atlas_coords(p_atlas_coords);
alternative_tile = p_alternative_tile;
@@ -112,16 +112,19 @@ struct TileMapQuadrant {
// Debug.
RID debug_canvas_item;
- // Rendering
+ // Rendering.
List<RID> canvas_items;
List<RID> occluders;
// Physics.
List<RID> bodies;
- // Navigation
+ // Navigation.
Map<Vector2i, Vector<RID>> navigation_regions;
+ // Scenes.
+ Map<Vector2i, String> scenes;
+
void operator=(const TileMapQuadrant &q) {
coords = q.coords;
debug_canvas_item = q.debug_canvas_item;
@@ -176,37 +179,45 @@ class TileMap : public Node2D {
GDCLASS(TileMap, Node2D);
public:
+ enum VisibilityMode {
+ VISIBILITY_MODE_DEFAULT,
+ VISIBILITY_MODE_FORCE_SHOW,
+ VISIBILITY_MODE_FORCE_HIDE,
+ };
+
private:
friend class TileSetPlugin;
+ // A compatibility enum to specify how is the data if formatted.
enum DataFormat {
FORMAT_1 = 0,
FORMAT_2,
FORMAT_3
};
+ mutable DataFormat format = FORMAT_1; // Assume lowest possible format if none is present;
+ // Properties.
Ref<TileSet> tile_set;
- int quadrant_size;
- Transform2D custom_transform;
-
- // Map of cells
- Map<Vector2i, TileMapCell> tile_map;
-
- Vector2i _coords_to_quadrant_coords(const Vector2i &p_coords) const;
-
- Map<Vector2i, TileMapQuadrant> quadrant_map;
-
- SelfList<TileMapQuadrant>::List dirty_quadrant_list;
+ int quadrant_size = 16;
+ VisibilityMode show_collision = VISIBILITY_MODE_DEFAULT;
+ VisibilityMode show_navigation = VISIBILITY_MODE_DEFAULT;
+ // Updates.
bool pending_update = false;
+ // Rect.
Rect2 rect_cache;
bool rect_cache_dirty = true;
Rect2 used_size_cache;
- bool used_size_cache_dirty;
- mutable DataFormat format;
+ bool used_size_cache_dirty = true;
- void _fix_cell_transform(Transform2D &xform, const TileMapCell &p_cell, const Vector2 &p_offset, const Size2 &p_sc);
+ // Map of cells.
+ Map<Vector2i, TileMapCell> tile_map;
+
+ // Quadrants management.
+ Map<Vector2i, TileMapQuadrant> quadrant_map;
+ Vector2i _coords_to_quadrant_coords(const Vector2i &p_coords) const;
+ SelfList<TileMapQuadrant>::List dirty_quadrant_list;
Map<Vector2i, TileMapQuadrant>::Element *_create_quadrant(const Vector2i &p_qk);
void _erase_quadrant(Map<Vector2i, TileMapQuadrant>::Element *Q);
@@ -216,8 +227,7 @@ private:
void _clear_quadrants();
void _recompute_rect_cache();
- void _update_all_items_material_state();
-
+ // Set and get tiles from data arrays.
void _set_tile_data(const Vector<int> &p_data);
Vector<int> _get_tile_data() const;
@@ -248,7 +258,13 @@ public:
void set_quadrant_size(int p_size);
int get_quadrant_size() const;
- void set_cell(const Vector2i &p_coords, int p_source_id = -1, const Vector2i p_atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ void set_collision_visibility_mode(VisibilityMode p_show_collision);
+ VisibilityMode get_collision_visibility_mode();
+
+ void set_navigation_visibility_mode(VisibilityMode p_show_navigation);
+ VisibilityMode get_navigation_visibility_mode();
+
+ void set_cell(const Vector2i &p_coords, int p_source_id = -1, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE);
int get_cell_source_id(const Vector2i &p_coords) const;
Vector2i get_cell_atlas_coords(const Vector2i &p_coords) const;
int get_cell_alternative_tile(const Vector2i &p_coords) const;
@@ -263,6 +279,7 @@ public:
int get_effective_quadrant_size() const;
void update_dirty_quadrants();
+ virtual void set_y_sort_enabled(bool p_enable) override;
Vector2 map_to_world(const Vector2i &p_pos) const;
Vector2i world_to_map(const Vector2 &p_pos) const;
@@ -290,4 +307,7 @@ public:
TileMap();
~TileMap();
};
+
+VARIANT_ENUM_CAST(TileMap::VisibilityMode);
+
#endif // TILE_MAP_H
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index 8feb47f1cc..c85b2c85a4 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -176,7 +176,7 @@ void VisibilityEnabler2D::_find_nodes(Node *p_node) {
{
RigidBody2D *rb2d = Object::cast_to<RigidBody2D>(p_node);
- if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_CHARACTER || rb2d->get_mode() == RigidBody2D::MODE_RIGID))) {
+ if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_DYNAMIC || rb2d->get_mode() == RigidBody2D::MODE_DYNAMIC_LOCKED))) {
add = true;
meta = rb2d->get_mode();
}
diff --git a/scene/2d/y_sort.cpp b/scene/2d/y_sort.cpp
deleted file mode 100644
index 7e7bc27cc2..0000000000
--- a/scene/2d/y_sort.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*************************************************************************/
-/* y_sort.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "y_sort.h"
-
-void YSort::set_sort_enabled(bool p_enabled) {
- sort_enabled = p_enabled;
- RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), sort_enabled);
-}
-
-bool YSort::is_sort_enabled() const {
- return sort_enabled;
-}
-
-void YSort::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_sort_enabled", "enabled"), &YSort::set_sort_enabled);
- ClassDB::bind_method(D_METHOD("is_sort_enabled"), &YSort::is_sort_enabled);
-
- ADD_GROUP("Sort", "sort_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sort_enabled"), "set_sort_enabled", "is_sort_enabled");
-}
-
-YSort::YSort() {
- RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), true);
-}
diff --git a/scene/2d/y_sort.h b/scene/2d/y_sort.h
deleted file mode 100644
index 7d36ee3391..0000000000
--- a/scene/2d/y_sort.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*************************************************************************/
-/* y_sort.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef Y_SORT_H
-#define Y_SORT_H
-
-#include "scene/2d/node_2d.h"
-
-class YSort : public Node2D {
- GDCLASS(YSort, Node2D);
- bool sort_enabled = true;
- static void _bind_methods();
-
-public:
- void set_sort_enabled(bool p_enabled);
- bool is_sort_enabled() const;
- YSort();
-};
-
-#endif // Y_SORT_H
diff --git a/scene/3d/SCsub b/scene/3d/SCsub
index ce69e8aa19..40bdaee47d 100644
--- a/scene/3d/SCsub
+++ b/scene/3d/SCsub
@@ -4,6 +4,5 @@ Import("env")
if env["disable_3d"]:
env.add_source_files(env.scene_sources, "node_3d.cpp")
- env.add_source_files(env.scene_sources, "skeleton_3d.cpp")
else:
env.add_source_files(env.scene_sources, "*.cpp")
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index e187e06308..44708cddff 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -118,7 +118,7 @@ void Area3D::_body_enter_tree(ObjectID p_id) {
E->get().in_tree = true;
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
}
@@ -132,7 +132,7 @@ void Area3D::_body_exit_tree(ObjectID p_id) {
E->get().in_tree = false;
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
}
@@ -154,6 +154,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
if (body_in) {
if (!E) {
E = body_map.insert(objid, BodyState());
+ E->get().rid = p_body;
E->get().rc = 0;
E->get().in_tree = node && node->is_inside_tree();
if (node) {
@@ -170,7 +171,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
}
if (E->get().in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape);
}
} else {
@@ -192,7 +193,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
}
}
if (node && in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape);
}
}
@@ -224,7 +225,7 @@ void Area3D::_clear_monitoring() {
}
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->key(), node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape);
}
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
@@ -253,7 +254,7 @@ void Area3D::_clear_monitoring() {
}
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->key(), node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
@@ -298,7 +299,7 @@ void Area3D::_area_enter_tree(ObjectID p_id) {
E->get().in_tree = true;
emit_signal(SceneStringNames::get_singleton()->area_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
}
@@ -312,7 +313,7 @@ void Area3D::_area_exit_tree(ObjectID p_id) {
E->get().in_tree = false;
emit_signal(SceneStringNames::get_singleton()->area_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape);
}
}
@@ -334,6 +335,7 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
if (area_in) {
if (!E) {
E = area_map.insert(objid, AreaState());
+ E->get().rid = p_area;
E->get().rc = 0;
E->get().in_tree = node && node->is_inside_tree();
if (node) {
@@ -350,7 +352,7 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
}
if (!node || E->get().in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, objid, node, p_area_shape, p_self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape);
}
} else {
@@ -372,7 +374,7 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
}
}
if (!node || in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape);
+ emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, obj, p_area_shape, p_self_shape);
}
}
@@ -582,13 +584,13 @@ void Area3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area3D::set_reverb_uniformity);
ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area3D::get_reverb_uniformity);
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
- ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D")));
ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D")));
@@ -601,7 +603,7 @@ void Area3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_gravity", "get_gravity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-32,32,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h
index 9605a937af..5b8d612717 100644
--- a/scene/3d/area_3d.h
+++ b/scene/3d/area_3d.h
@@ -83,6 +83,7 @@ private:
};
struct BodyState {
+ RID rid;
int rc = 0;
bool in_tree = false;
VSet<ShapePair> shapes;
@@ -114,6 +115,7 @@ private:
};
struct AreaState {
+ RID rid;
int rc = 0;
bool in_tree = false;
VSet<AreaShapePair> shapes;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 72392be5bd..cad4330c17 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -962,9 +962,9 @@ void AudioStreamPlayer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stream_playback"), &AudioStreamPlayer3D::get_stream_playback);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,InverseSquare,Log,Disabled"), "set_attenuation_model", "get_attenuation_model");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,Inverse Square,Log,Disabled"), "set_attenuation_model", "get_attenuation_model");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater"), "set_unit_size", "get_unit_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing");
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index 70c535bd89..8aec493602 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -98,7 +98,7 @@ private:
AttenuationModel attenuation_model = ATTENUATION_INVERSE_DISTANCE;
float unit_db = 0.0;
- float unit_size = 1.0;
+ float unit_size = 10.0;
float max_db = 3.0;
float pitch_scale = 1.0;
bool autoplay = false;
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
deleted file mode 100644
index ef648a126e..0000000000
--- a/scene/3d/baked_lightmap.cpp
+++ /dev/null
@@ -1,1466 +0,0 @@
-/*************************************************************************/
-/* baked_lightmap.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "baked_lightmap.h"
-
-#include "core/io/config_file.h"
-#include "core/io/resource_saver.h"
-#include "core/math/camera_matrix.h"
-#include "core/math/delaunay_3d.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
-#include "core/os/os.h"
-#include "core/templates/sort_array.h"
-#include "lightmap_probe.h"
-
-void BakedLightmapData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) {
- User user;
- user.path = p_path;
- user.uv_scale = p_uv_scale;
- user.slice_index = p_slice_index;
- user.sub_instance = p_sub_instance;
- users.push_back(user);
-}
-
-int BakedLightmapData::get_user_count() const {
- return users.size();
-}
-
-NodePath BakedLightmapData::get_user_path(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), NodePath());
- return users[p_user].path;
-}
-
-int32_t BakedLightmapData::get_user_sub_instance(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), -1);
- return users[p_user].sub_instance;
-}
-
-Rect2 BakedLightmapData::get_user_lightmap_uv_scale(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), Rect2());
- return users[p_user].uv_scale;
-}
-
-int BakedLightmapData::get_user_lightmap_slice_index(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), -1);
- return users[p_user].slice_index;
-}
-
-void BakedLightmapData::clear_users() {
- users.clear();
-}
-
-void BakedLightmapData::_set_user_data(const Array &p_data) {
- ERR_FAIL_COND(p_data.size() <= 0);
- ERR_FAIL_COND((p_data.size() % 4) != 0);
-
- for (int i = 0; i < p_data.size(); i += 4) {
- add_user(p_data[i + 0], p_data[i + 1], p_data[i + 2], p_data[i + 3]);
- }
-}
-
-Array BakedLightmapData::_get_user_data() const {
- Array ret;
- for (int i = 0; i < users.size(); i++) {
- ret.push_back(users[i].path);
- ret.push_back(users[i].uv_scale);
- ret.push_back(users[i].slice_index);
- ret.push_back(users[i].sub_instance);
- }
- return ret;
-}
-
-RID BakedLightmapData::get_rid() const {
- return lightmap;
-}
-
-void BakedLightmapData::clear() {
- users.clear();
-}
-
-void BakedLightmapData::set_light_texture(const Ref<TextureLayered> &p_light_texture) {
- light_texture = p_light_texture;
- RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics);
-}
-
-Ref<TextureLayered> BakedLightmapData::get_light_texture() const {
- return light_texture;
-}
-
-void BakedLightmapData::set_uses_spherical_harmonics(bool p_enable) {
- uses_spherical_harmonics = p_enable;
- RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics);
-}
-
-bool BakedLightmapData::is_using_spherical_harmonics() const {
- return uses_spherical_harmonics;
-}
-
-void BakedLightmapData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
- if (p_points.size()) {
- int pc = p_points.size();
- ERR_FAIL_COND(pc * 9 != p_point_sh.size());
- ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
- ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
- RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, p_points, p_point_sh, p_tetrahedra, p_bsp_tree);
- RS::get_singleton()->lightmap_set_probe_bounds(lightmap, p_bounds);
- RS::get_singleton()->lightmap_set_probe_interior(lightmap, p_interior);
- } else {
- RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, PackedVector3Array(), PackedColorArray(), PackedInt32Array(), PackedInt32Array());
- RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB());
- RS::get_singleton()->lightmap_set_probe_interior(lightmap, false);
- }
- interior = p_interior;
- bounds = p_bounds;
-}
-
-PackedVector3Array BakedLightmapData::get_capture_points() const {
- return RS::get_singleton()->lightmap_get_probe_capture_points(lightmap);
-}
-
-PackedColorArray BakedLightmapData::get_capture_sh() const {
- return RS::get_singleton()->lightmap_get_probe_capture_sh(lightmap);
-}
-
-PackedInt32Array BakedLightmapData::get_capture_tetrahedra() const {
- return RS::get_singleton()->lightmap_get_probe_capture_tetrahedra(lightmap);
-}
-
-PackedInt32Array BakedLightmapData::get_capture_bsp_tree() const {
- return RS::get_singleton()->lightmap_get_probe_capture_bsp_tree(lightmap);
-}
-
-AABB BakedLightmapData::get_capture_bounds() const {
- return bounds;
-}
-
-bool BakedLightmapData::is_interior() const {
- return interior;
-}
-
-void BakedLightmapData::_set_probe_data(const Dictionary &p_data) {
- ERR_FAIL_COND(!p_data.has("bounds"));
- ERR_FAIL_COND(!p_data.has("points"));
- ERR_FAIL_COND(!p_data.has("tetrahedra"));
- ERR_FAIL_COND(!p_data.has("bsp"));
- ERR_FAIL_COND(!p_data.has("sh"));
- ERR_FAIL_COND(!p_data.has("interior"));
- set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]);
-}
-
-Dictionary BakedLightmapData::_get_probe_data() const {
- Dictionary d;
- d["bounds"] = get_capture_bounds();
- d["points"] = get_capture_points();
- d["tetrahedra"] = get_capture_tetrahedra();
- d["bsp"] = get_capture_bsp_tree();
- d["sh"] = get_capture_sh();
- d["interior"] = is_interior();
- return d;
-}
-
-void BakedLightmapData::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &BakedLightmapData::_set_user_data);
- ClassDB::bind_method(D_METHOD("_get_user_data"), &BakedLightmapData::_get_user_data);
-
- ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &BakedLightmapData::set_light_texture);
- ClassDB::bind_method(D_METHOD("get_light_texture"), &BakedLightmapData::get_light_texture);
-
- ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &BakedLightmapData::set_uses_spherical_harmonics);
- ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &BakedLightmapData::is_using_spherical_harmonics);
-
- ClassDB::bind_method(D_METHOD("add_user", "path", "uv_scale", "slice_index", "sub_instance"), &BakedLightmapData::add_user);
- ClassDB::bind_method(D_METHOD("get_user_count"), &BakedLightmapData::get_user_count);
- ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path);
- ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users);
-
- ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &BakedLightmapData::_set_probe_data);
- ClassDB::bind_method(D_METHOD("_get_probe_data"), &BakedLightmapData::_get_probe_data);
-
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered"), "set_light_texture", "get_light_texture");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data");
-}
-
-BakedLightmapData::BakedLightmapData() {
- lightmap = RS::get_singleton()->lightmap_create();
-}
-
-BakedLightmapData::~BakedLightmapData() {
- RS::get_singleton()->free(lightmap);
-}
-
-///////////////////////////
-
-void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes) {
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
- if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) {
- Ref<Mesh> mesh = mi->get_mesh();
- if (mesh.is_valid()) {
- bool all_have_uv2_and_normal = true;
- bool surfaces_found = false;
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
- continue;
- }
- if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) {
- all_have_uv2_and_normal = false;
- break;
- }
- if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_NORMAL)) {
- all_have_uv2_and_normal = false;
- break;
- }
- surfaces_found = true;
- }
-
- if (surfaces_found && all_have_uv2_and_normal) {
- //READY TO BAKE! size hint could be computed if not found, actually..
-
- MeshesFound mf;
- mf.xform = get_global_transform().affine_inverse() * mi->get_global_transform();
- mf.node_path = get_path_to(mi);
- mf.subindex = -1;
- mf.mesh = mesh;
-
- static const int lightmap_scale[GeometryInstance3D::LIGHTMAP_SCALE_MAX] = { 1, 2, 4, 8 };
- mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()];
-
- Ref<Material> all_override = mi->get_material_override();
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- if (all_override.is_valid()) {
- mf.overrides.push_back(all_override);
- } else {
- mf.overrides.push_back(mi->get_surface_override_material(i));
- }
- }
-
- meshes.push_back(mf);
- }
- }
- }
-
- Node3D *s = Object::cast_to<Node3D>(p_at_node);
-
- if (!mi && s) {
- Array bmeshes = p_at_node->call("get_bake_bmeshes");
- if (bmeshes.size() && (bmeshes.size() & 1) == 0) {
- Transform xf = get_global_transform().affine_inverse() * s->get_global_transform();
- for (int i = 0; i < bmeshes.size(); i += 2) {
- Ref<Mesh> mesh = bmeshes[i];
- if (!mesh.is_valid()) {
- continue;
- }
-
- MeshesFound mf;
-
- Transform mesh_xf = bmeshes[i + 1];
- mf.xform = xf * mesh_xf;
- mf.node_path = get_path_to(s);
- mf.subindex = i / 2;
- mf.lightmap_scale = 1;
- mf.mesh = mesh;
-
- meshes.push_back(mf);
- }
- }
- }
-
- Light3D *light = Object::cast_to<Light3D>(p_at_node);
-
- if (light && light->get_bake_mode() != Light3D::BAKE_DISABLED) {
- LightsFound lf;
- lf.xform = get_global_transform().affine_inverse() * light->get_global_transform();
- lf.light = light;
- lights.push_back(lf);
- }
-
- LightmapProbe *probe = Object::cast_to<LightmapProbe>(p_at_node);
-
- if (probe) {
- Transform xf = get_global_transform().affine_inverse() * probe->get_global_transform();
- probes.push_back(xf.origin);
- }
-
- for (int i = 0; i < p_at_node->get_child_count(); i++) {
- Node *child = p_at_node->get_child(i);
- if (!child->get_owner()) {
- continue; //maybe a helper
- }
-
- _find_meshes_and_lights(child, meshes, lights, probes);
- }
-}
-
-int BakedLightmap::_bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const {
- int over = 0;
- int under = 0;
- int coplanar = 0;
- const BSPSimplex &s = p_simplices[p_simplex];
- for (int i = 0; i < 4; i++) {
- const Vector3 v = p_points[s.vertices[i]];
- if (p_plane.has_point(v)) { //coplanar
- coplanar++;
- } else if (p_plane.is_point_over(v)) {
- over++;
- } else {
- under++;
- }
- }
-
- ERR_FAIL_COND_V(under == 0 && over == 0, -2); //should never happen, we discarded flat simplices before, but in any case drop it from the bsp tree and throw an error
- if (under == 0) {
- return 1; // all over
- } else if (over == 0) {
- return -1; // all under
- } else {
- return 0; // crossing
- }
-}
-
-//#define DEBUG_BSP
-
-int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const LocalVector<Plane> &p_planes, LocalVector<int32_t> &planes_tested, const LocalVector<BSPSimplex> &p_simplices, const LocalVector<int32_t> &p_simplex_indices, LocalVector<BSPNode> &bsp_nodes) {
- //if we reach here, it means there is more than one simplex
- int32_t node_index = (int32_t)bsp_nodes.size();
- bsp_nodes.push_back(BSPNode());
-
- //test with all the simplex planes
- Plane best_plane;
- float best_plane_score = -1.0;
-
- for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
- const BSPSimplex &s = p_simplices[p_simplex_indices[i]];
- for (int j = 0; j < 4; j++) {
- uint32_t plane_index = s.planes[j];
- if (planes_tested[plane_index] == node_index) {
- continue; //tested this plane already
- }
-
- planes_tested[plane_index] = node_index;
-
- static const int face_order[4][3] = {
- { 0, 1, 2 },
- { 0, 2, 3 },
- { 0, 1, 3 },
- { 1, 2, 3 }
- };
-
- // despite getting rid of plane duplicates, we should still use here the actual plane to avoid numerical error
- // from thinking this same simplex is intersecting rather than on a side
- Vector3 v0 = p_points[s.vertices[face_order[j][0]]];
- Vector3 v1 = p_points[s.vertices[face_order[j][1]]];
- Vector3 v2 = p_points[s.vertices[face_order[j][2]]];
-
- Plane plane(v0, v1, v2);
-
- //test with all the simplices
- int over_count = 0;
- int under_count = 0;
-
- for (uint32_t k = 0; k < p_simplex_indices.size(); k++) {
- int side = _bsp_get_simplex_side(p_points, p_simplices, plane, p_simplex_indices[k]);
- if (side == -2) {
- continue; //this simplex is invalid, skip for now
- } else if (side < 0) {
- under_count++;
- } else if (side > 0) {
- over_count++;
- }
- }
-
- if (under_count == 0 && over_count == 0) {
- continue; //most likely precision issue with a flat simplex, do not try this plane
- }
-
- if (under_count > over_count) { //make sure under is always less than over, so we can compute the same ratio
- SWAP(under_count, over_count);
- }
-
- float score = 0; //by default, score is 0 (worst)
- if (over_count > 0) {
- //give score mainly based on ratio (under / over), this means that this plane is splitting simplices a lot, but its balanced
- score = float(under_count) / over_count;
- }
-
- //adjusting priority over least splits, probably not a great idea
- //score *= Math::sqrt(float(over_count + under_count) / p_simplex_indices.size()); //also multiply score
-
- if (score > best_plane_score) {
- best_plane = plane;
- best_plane_score = score;
- }
- }
- }
-
- LocalVector<int32_t> indices_over;
- LocalVector<int32_t> indices_under;
-
- //split again, but add to list
- for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
- uint32_t index = p_simplex_indices[i];
- int side = _bsp_get_simplex_side(p_points, p_simplices, best_plane, index);
-
- if (side == -2) {
- continue; //simplex sits on the plane, does not make sense to use it
- }
- if (side <= 0) {
- indices_under.push_back(index);
- }
-
- if (side >= 0) {
- indices_over.push_back(index);
- }
- }
-
-#ifdef DEBUG_BSP
- print_line("node " + itos(node_index) + " found plane: " + best_plane + " score:" + rtos(best_plane_score) + " - over " + itos(indices_over.size()) + " under " + itos(indices_under.size()) + " intersecting " + itos(intersecting));
-#endif
-
- if (best_plane_score < 0.0 || indices_over.size() == p_simplex_indices.size() || indices_under.size() == p_simplex_indices.size()) {
- ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug
-
- // Failed to separate the tetrahedrons using planes
- // this means Delaunay broke at some point.
- // Luckily, because we are using tetrahedrons, we can resort to
- // less precise but still working ways to generate the separating plane
- // this will most likely look bad when interpolating, but at least it will not crash.
- // and the arctifact will most likely also be very small, so too difficult to notice.
-
- //find the longest axis
-
- WARN_PRINT("Inconsistency found in triangulation while building BSP, probe interpolation quality may degrade a bit.");
-
- LocalVector<Vector3> centers;
- AABB bounds_all;
- for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
- AABB bounds;
- for (uint32_t j = 0; j < 4; j++) {
- Vector3 p = p_points[p_simplices[p_simplex_indices[i]].vertices[j]];
- if (j == 0) {
- bounds.position = p;
- } else {
- bounds.expand_to(p);
- }
- }
- if (i == 0) {
- centers.push_back(bounds.position + bounds.size * 0.5);
- } else {
- bounds_all.merge_with(bounds);
- }
- }
- Vector3::Axis longest_axis = Vector3::Axis(bounds_all.get_longest_axis_index());
-
- //find the simplex that will go under
- uint32_t min_d_idx = 0xFFFFFFFF;
- float min_d_dist = 1e20;
-
- for (uint32_t i = 0; i < centers.size(); i++) {
- if (centers[i][longest_axis] < min_d_dist) {
- min_d_idx = i;
- min_d_dist = centers[i][longest_axis];
- }
- }
- //rebuild best_plane and over/under arrays
- best_plane = Plane();
- best_plane.normal[longest_axis] = 1.0;
- best_plane.d = min_d_dist;
-
- indices_under.clear();
- indices_under.push_back(min_d_idx);
-
- indices_over.clear();
-
- for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
- if (i == min_d_idx) {
- continue;
- }
- indices_over.push_back(p_simplex_indices[i]);
- }
- }
-
- BSPNode node;
- node.plane = best_plane;
-
- if (indices_under.size() == 0) {
- //nothing to do here
- node.under = BSPNode::EMPTY_LEAF;
- } else if (indices_under.size() == 1) {
- node.under = -(indices_under[0] + 1);
- } else {
- node.under = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_under, bsp_nodes);
- }
-
- if (indices_over.size() == 0) {
- //nothing to do here
- node.over = BSPNode::EMPTY_LEAF;
- } else if (indices_over.size() == 1) {
- node.over = -(indices_over[0] + 1);
- } else {
- node.over = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_over, bsp_nodes);
- }
-
- bsp_nodes[node_index] = node;
-
- return node_index;
-}
-
-bool BakedLightmap::_lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh) {
- BakeStepUD *bsud = (BakeStepUD *)ud;
- bool ret = false;
- if (bsud->func) {
- ret = bsud->func(bsud->from_percent + p_completion * (bsud->to_percent - bsud->from_percent), p_text, bsud->ud, p_refresh);
- }
- return ret;
-}
-
-void BakedLightmap::_plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle) {
- for (int i = 0; i < 8; i++) {
- Vector3i pos = p_cell->offset;
- uint32_t half_size = p_cell->size / 2;
- if (i & 1) {
- pos.x += half_size;
- }
- if (i & 2) {
- pos.y += half_size;
- }
- if (i & 4) {
- pos.z += half_size;
- }
-
- AABB subcell;
- subcell.position = Vector3(pos) * p_cell_size;
- subcell.size = Vector3(half_size, half_size, half_size) * p_cell_size;
-
- if (!Geometry3D::triangle_box_overlap(subcell.position + subcell.size * 0.5, subcell.size * 0.5, p_triangle)) {
- continue;
- }
-
- if (p_cell->children[i] == nullptr) {
- GenProbesOctree *child = memnew(GenProbesOctree);
- child->offset = pos;
- child->size = half_size;
- p_cell->children[i] = child;
- }
-
- if (half_size > 1) {
- //still levels missing
- _plot_triangle_into_octree(p_cell->children[i], p_cell_size, p_triangle);
- }
- }
-}
-
-void BakedLightmap::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector<Vector3> &probe_positions, LocalVector<Vector3> &new_probe_positions, HashMap<Vector3i, bool, Vector3iHash> &positions_used, const AABB &p_bounds) {
- for (int i = 0; i < 8; i++) {
- Vector3i pos = p_cell->offset;
- if (i & 1) {
- pos.x += p_cell->size;
- }
- if (i & 2) {
- pos.y += p_cell->size;
- }
- if (i & 4) {
- pos.z += p_cell->size;
- }
-
- if (p_cell->size == 1 && !positions_used.has(pos)) {
- //new position to insert!
- Vector3 real_pos = p_bounds.position + Vector3(pos) * p_cell_size;
- //see if a user submitted probe is too close
- int ppcount = probe_positions.size();
- const Vector3 *pp = probe_positions.ptr();
- bool exists = false;
- for (int j = 0; j < ppcount; j++) {
- if (pp[j].distance_to(real_pos) < CMP_EPSILON) {
- exists = true;
- break;
- }
- }
-
- if (!exists) {
- new_probe_positions.push_back(real_pos);
- }
-
- positions_used[pos] = true;
- }
-
- if (p_cell->children[i] != nullptr) {
- _gen_new_positions_from_octree(p_cell->children[i], p_cell_size, probe_positions, new_probe_positions, positions_used, p_bounds);
- }
- }
-}
-
-BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) {
- if (p_image_data_path == "") {
- if (get_light_data().is_null()) {
- return BAKE_ERROR_NO_SAVE_PATH;
- }
-
- p_image_data_path = get_light_data()->get_path();
- if (!p_image_data_path.is_resource_file()) {
- return BAKE_ERROR_NO_SAVE_PATH;
- }
- }
-
- Ref<Lightmapper> lightmapper = Lightmapper::create();
- ERR_FAIL_COND_V(lightmapper.is_null(), BAKE_ERROR_NO_LIGHTMAPPER);
-
- BakeStepUD bsud;
- bsud.func = p_bake_step;
- bsud.ud = p_bake_userdata;
- bsud.from_percent = 0.2;
- bsud.to_percent = 0.8;
-
- if (p_bake_step) {
- p_bake_step(0.0, TTR("Finding meshes, lights and probes"), p_bake_userdata, true);
- }
- /* STEP 1, FIND MESHES, LIGHTS AND PROBES */
- Vector<Lightmapper::MeshData> mesh_data;
- Vector<LightsFound> lights_found;
- Vector<Vector3> probes_found;
- AABB bounds;
- {
- Vector<MeshesFound> meshes_found;
- _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), meshes_found, lights_found, probes_found);
-
- if (meshes_found.size() == 0) {
- return BAKE_ERROR_NO_MESHES;
- }
- // create mesh data for insert
-
- //get the base material textures, help compute atlas size and bounds
- for (int m_i = 0; m_i < meshes_found.size(); m_i++) {
- if (p_bake_step) {
- float p = (float)(m_i) / meshes_found.size();
- p_bake_step(p * 0.1, vformat(TTR("Preparing geometry %d/%d"), m_i, meshes_found.size()), p_bake_userdata, false);
- }
-
- MeshesFound &mf = meshes_found.write[m_i];
-
- Size2i lightmap_size = mf.mesh->get_lightmap_size_hint() * mf.lightmap_scale;
- Vector<RID> overrides;
- overrides.resize(mf.overrides.size());
- for (int i = 0; i < mf.overrides.size(); i++) {
- if (mf.overrides[i].is_valid()) {
- overrides.write[i] = mf.overrides[i]->get_rid();
- }
- }
- TypedArray<Image> images = RS::get_singleton()->bake_render_uv2(mf.mesh->get_rid(), overrides, lightmap_size);
-
- ERR_FAIL_COND_V(images.is_empty(), BAKE_ERROR_CANT_CREATE_IMAGE);
-
- Ref<Image> albedo = images[RS::BAKE_CHANNEL_ALBEDO_ALPHA];
- Ref<Image> orm = images[RS::BAKE_CHANNEL_ORM];
-
- //multiply albedo by metal
-
- Lightmapper::MeshData md;
-
- {
- Dictionary d;
- d["path"] = mf.node_path;
- if (mf.subindex >= 0) {
- d["subindex"] = mf.subindex;
- }
- md.userdata = d;
- }
-
- {
- if (albedo->get_format() != Image::FORMAT_RGBA8) {
- albedo->convert(Image::FORMAT_RGBA8);
- }
- if (orm->get_format() != Image::FORMAT_RGBA8) {
- orm->convert(Image::FORMAT_RGBA8);
- }
- Vector<uint8_t> albedo_alpha = albedo->get_data();
- Vector<uint8_t> orm_data = orm->get_data();
-
- Vector<uint8_t> albedom;
- uint32_t len = albedo_alpha.size();
- albedom.resize(len);
- const uint8_t *r_aa = albedo_alpha.ptr();
- const uint8_t *r_orm = orm_data.ptr();
- uint8_t *w_albedo = albedom.ptrw();
-
- for (uint32_t i = 0; i < len; i += 4) {
- w_albedo[i + 0] = uint8_t(CLAMP(float(r_aa[i + 0]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
- w_albedo[i + 1] = uint8_t(CLAMP(float(r_aa[i + 1]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
- w_albedo[i + 2] = uint8_t(CLAMP(float(r_aa[i + 2]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
- w_albedo[i + 3] = 255;
- }
-
- md.albedo_on_uv2.instance();
- md.albedo_on_uv2->create(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom);
- }
-
- md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION];
- if (md.emission_on_uv2->get_format() != Image::FORMAT_RGBAH) {
- md.emission_on_uv2->convert(Image::FORMAT_RGBAH);
- }
-
- //get geometry
-
- Basis normal_xform = mf.xform.basis.inverse().transposed();
-
- for (int i = 0; i < mf.mesh->get_surface_count(); i++) {
- if (mf.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
- continue;
- }
- Array a = mf.mesh->surface_get_arrays(i);
-
- Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
- const Vector3 *vr = vertices.ptr();
- Vector<Vector2> uv = a[Mesh::ARRAY_TEX_UV2];
- const Vector2 *uvr = nullptr;
- Vector<Vector3> normals = a[Mesh::ARRAY_NORMAL];
- const Vector3 *nr = nullptr;
- Vector<int> index = a[Mesh::ARRAY_INDEX];
-
- ERR_CONTINUE(uv.size() == 0);
- ERR_CONTINUE(normals.size() == 0);
-
- uvr = uv.ptr();
- nr = normals.ptr();
-
- int facecount;
- const int *ir = nullptr;
-
- if (index.size()) {
- facecount = index.size() / 3;
- ir = index.ptr();
- } else {
- facecount = vertices.size() / 3;
- }
-
- for (int j = 0; j < facecount; j++) {
- uint32_t vidx[3];
-
- if (ir) {
- for (int k = 0; k < 3; k++) {
- vidx[k] = ir[j * 3 + k];
- }
- } else {
- for (int k = 0; k < 3; k++) {
- vidx[k] = j * 3 + k;
- }
- }
-
- for (int k = 0; k < 3; k++) {
- Vector3 v = mf.xform.xform(vr[vidx[k]]);
- if (bounds == AABB()) {
- bounds.position = v;
- } else {
- bounds.expand_to(v);
- }
- md.points.push_back(v);
-
- md.uv2.push_back(uvr[vidx[k]]);
- md.normal.push_back(normal_xform.xform(nr[vidx[k]]).normalized());
- }
- }
- }
-
- mesh_data.push_back(md);
- }
- }
-
- /* STEP 2, CREATE PROBES */
-
- if (p_bake_step) {
- p_bake_step(0.3, TTR("Creating probes"), p_bake_userdata, true);
- }
-
- //bounds need to include the user probes
- for (int i = 0; i < probes_found.size(); i++) {
- bounds.expand_to(probes_found[i]);
- }
-
- bounds.grow_by(bounds.size.length() * 0.001);
-
- if (gen_probes == GENERATE_PROBES_DISABLED) {
- // generate 8 probes on bound endpoints
- for (int i = 0; i < 8; i++) {
- probes_found.push_back(bounds.get_endpoint(i));
- }
- } else {
- // detect probes from geometry
- static const int subdiv_values[6] = { 0, 4, 8, 16, 32 };
- int subdiv = subdiv_values[gen_probes];
-
- float subdiv_cell_size;
- Vector3i bound_limit;
- {
- int longest_axis = bounds.get_longest_axis_index();
- subdiv_cell_size = bounds.size[longest_axis] / subdiv;
- int axis_n1 = (longest_axis + 1) % 3;
- int axis_n2 = (longest_axis + 2) % 3;
-
- bound_limit[longest_axis] = subdiv;
- bound_limit[axis_n1] = int(Math::ceil(bounds.size[axis_n1] / subdiv_cell_size));
- bound_limit[axis_n2] = int(Math::ceil(bounds.size[axis_n2] / subdiv_cell_size));
- //compensate bounds
- bounds.size[axis_n1] = bound_limit[axis_n1] * subdiv_cell_size;
- bounds.size[axis_n2] = bound_limit[axis_n2] * subdiv_cell_size;
- }
-
- GenProbesOctree octree;
- octree.size = subdiv;
-
- for (int i = 0; i < mesh_data.size(); i++) {
- if (p_bake_step) {
- float p = (float)(i) / mesh_data.size();
- p_bake_step(0.3 + p * 0.1, vformat(TTR("Creating probes from mesh %d/%d"), i, mesh_data.size()), p_bake_userdata, false);
- }
-
- for (int j = 0; j < mesh_data[i].points.size(); j += 3) {
- Vector3 points[3] = { mesh_data[i].points[j + 0] - bounds.position, mesh_data[i].points[j + 1] - bounds.position, mesh_data[i].points[j + 2] - bounds.position };
- _plot_triangle_into_octree(&octree, subdiv_cell_size, points);
- }
- }
-
- LocalVector<Vector3> new_probe_positions;
- HashMap<Vector3i, bool, Vector3iHash> positions_used;
- for (uint32_t i = 0; i < 8; i++) { //insert bounding endpoints
- Vector3i pos;
- if (i & 1) {
- pos.x += bound_limit.x;
- }
- if (i & 2) {
- pos.y += bound_limit.y;
- }
- if (i & 4) {
- pos.z += bound_limit.z;
- }
-
- positions_used[pos] = true;
- Vector3 real_pos = bounds.position + Vector3(pos) * subdiv_cell_size; //use same formula for numerical stability
- new_probe_positions.push_back(real_pos);
- }
- //skip first level, since probes are always added at bounds endpoints anyway (code above this)
- for (int i = 0; i < 8; i++) {
- if (octree.children[i]) {
- _gen_new_positions_from_octree(octree.children[i], subdiv_cell_size, probes_found, new_probe_positions, positions_used, bounds);
- }
- }
-
- for (uint32_t i = 0; i < new_probe_positions.size(); i++) {
- probes_found.push_back(new_probe_positions[i]);
- }
- }
-
- // Add everything to lightmapper
- if (p_bake_step) {
- p_bake_step(0.4, TTR("Preparing Lightmapper"), p_bake_userdata, true);
- }
-
- {
- for (int i = 0; i < mesh_data.size(); i++) {
- lightmapper->add_mesh(mesh_data[i]);
- }
- for (int i = 0; i < lights_found.size(); i++) {
- Light3D *light = lights_found[i].light;
- Transform xf = lights_found[i].xform;
-
- if (Object::cast_to<DirectionalLight3D>(light)) {
- DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light);
- lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE));
- } else if (Object::cast_to<OmniLight3D>(light)) {
- OmniLight3D *l = Object::cast_to<OmniLight3D>(light);
- lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
- } else if (Object::cast_to<SpotLight3D>(light)) {
- SpotLight3D *l = Object::cast_to<SpotLight3D>(light);
- lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
- }
- }
- for (int i = 0; i < probes_found.size(); i++) {
- lightmapper->add_probe(probes_found[i]);
- }
- }
-
- Ref<Image> environment_image;
- Basis environment_transform;
-
- // Add everything to lightmapper
- if (environment_mode != ENVIRONMENT_MODE_DISABLED) {
- if (p_bake_step) {
- p_bake_step(4.1, TTR("Preparing Environment"), p_bake_userdata, true);
- }
-
- environment_transform = get_global_transform().basis;
-
- switch (environment_mode) {
- case ENVIRONMENT_MODE_DISABLED: {
- //nothing
- } break;
- case ENVIRONMENT_MODE_SCENE: {
- Ref<World3D> world = get_world_3d();
- if (world.is_valid()) {
- Ref<Environment> env = world->get_environment();
- if (env.is_null()) {
- env = world->get_fallback_environment();
- }
-
- if (env.is_valid()) {
- environment_image = RS::get_singleton()->environment_bake_panorama(env->get_rid(), true, Size2i(128, 64));
- }
- }
- } break;
- case ENVIRONMENT_MODE_CUSTOM_SKY: {
- if (environment_custom_sky.is_valid()) {
- environment_image = RS::get_singleton()->sky_bake_panorama(environment_custom_sky->get_rid(), environment_custom_energy, true, Size2i(128, 64));
- }
-
- } break;
- case ENVIRONMENT_MODE_CUSTOM_COLOR: {
- environment_image.instance();
- environment_image->create(128, 64, false, Image::FORMAT_RGBAF);
- Color c = environment_custom_color;
- c.r *= environment_custom_energy;
- c.g *= environment_custom_energy;
- c.b *= environment_custom_energy;
- for (int i = 0; i < 128; i++) {
- for (int j = 0; j < 64; j++) {
- environment_image->set_pixel(i, j, c);
- }
- }
-
- } break;
- }
- }
-
- Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud);
-
- if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) {
- return BAKE_ERROR_MESHES_INVALID;
- }
-
- /* POSTBAKE: Save Textures */
-
- Ref<TextureLayered> texture;
- {
- Vector<Ref<Image>> images;
- for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
- images.push_back(lightmapper->get_bake_texture(i));
- }
- //we assume they are all the same, so let's create a large one for saving
- Ref<Image> large_image;
- large_image.instance();
-
- large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format());
-
- for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
- large_image->blit_rect(images[i], Rect2(0, 0, images[i]->get_width(), images[i]->get_height()), Point2(0, images[i]->get_height() * i));
- }
-
- String base_path = p_image_data_path.get_basename() + ".exr";
-
- Ref<ConfigFile> config;
-
- config.instance();
- if (FileAccess::exists(base_path + ".import")) {
- config->load(base_path + ".import");
- }
-
- config->set_value("remap", "importer", "2d_array_texture");
- config->set_value("remap", "type", "StreamTexture2DArray");
- if (!config->has_section_key("params", "compress/mode")) {
- config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be
- }
- config->set_value("params", "compress/channel_pack", 1);
- config->set_value("params", "mipmaps/generate", false);
- config->set_value("params", "slices/horizontal", 1);
- config->set_value("params", "slices/vertical", images.size());
-
- config->save(base_path + ".import");
-
- Error err = large_image->save_exr(base_path, false);
- ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE);
- ResourceLoader::import(base_path);
- Ref<Texture> t = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus?
- ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE);
- texture = t;
- }
-
- /* POSTBAKE: Save Light Data */
-
- Ref<BakedLightmapData> data;
- if (get_light_data().is_valid()) {
- data = get_light_data();
- set_light_data(Ref<BakedLightmapData>()); //clear
- data->clear();
- } else {
- data.instance();
- }
-
- data->set_light_texture(texture);
- data->set_uses_spherical_harmonics(directional);
-
- for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
- Dictionary d = lightmapper->get_bake_mesh_userdata(i);
- NodePath np = d["path"];
- int32_t subindex = -1;
- if (d.has("subindex")) {
- subindex = d["subindex"];
- }
-
- Rect2 uv_scale = lightmapper->get_bake_mesh_uv_scale(i);
- int slice_index = lightmapper->get_bake_mesh_texture_slice(i);
- data->add_user(np, uv_scale, slice_index, subindex);
- }
-
- {
- // create tetrahedrons
- Vector<Vector3> points;
- Vector<Color> sh;
- points.resize(lightmapper->get_bake_probe_count());
- sh.resize(lightmapper->get_bake_probe_count() * 9);
- for (int i = 0; i < lightmapper->get_bake_probe_count(); i++) {
- points.write[i] = lightmapper->get_bake_probe_point(i);
- Vector<Color> colors = lightmapper->get_bake_probe_sh(i);
- ERR_CONTINUE(colors.size() != 9);
- for (int j = 0; j < 9; j++) {
- sh.write[i * 9 + j] = colors[j];
- }
- }
-
- //Obtain solved simplices
-
- if (p_bake_step) {
- p_bake_step(0.8, TTR("Generating Probe Volumes"), p_bake_userdata, true);
- }
- Vector<Delaunay3D::OutputSimplex> solved_simplices = Delaunay3D::tetrahedralize(points);
-
- LocalVector<BSPSimplex> bsp_simplices;
- LocalVector<Plane> bsp_planes;
- LocalVector<int32_t> bsp_simplex_indices;
- PackedInt32Array tetrahedrons;
-
- for (int i = 0; i < solved_simplices.size(); i++) {
- //Prepare a special representation of the simplex, which uses a BSP Tree
- BSPSimplex bsp_simplex;
- for (int j = 0; j < 4; j++) {
- bsp_simplex.vertices[j] = solved_simplices[i].points[j];
- }
- for (int j = 0; j < 4; j++) {
- static const int face_order[4][3] = {
- { 0, 1, 2 },
- { 0, 2, 3 },
- { 0, 1, 3 },
- { 1, 2, 3 }
- };
- Vector3 a = points[solved_simplices[i].points[face_order[j][0]]];
- Vector3 b = points[solved_simplices[i].points[face_order[j][1]]];
- Vector3 c = points[solved_simplices[i].points[face_order[j][2]]];
-
- //store planes in an array, but ensure they are reused, to speed up processing
-
- Plane p(a, b, c);
- int plane_index = -1;
- for (uint32_t k = 0; k < bsp_planes.size(); k++) {
- if (bsp_planes[k].is_equal_approx_any_side(p)) {
- plane_index = k;
- break;
- }
- }
-
- if (plane_index == -1) {
- plane_index = bsp_planes.size();
- bsp_planes.push_back(p);
- }
-
- bsp_simplex.planes[j] = plane_index;
-
- //also fill simplex array
- tetrahedrons.push_back(solved_simplices[i].points[j]);
- }
-
- bsp_simplex_indices.push_back(bsp_simplices.size());
- bsp_simplices.push_back(bsp_simplex);
- }
-
-//#define DEBUG_SIMPLICES_AS_OBJ_FILE
-#ifdef DEBUG_SIMPLICES_AS_OBJ_FILE
- {
- FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE);
- for (uint32_t i = 0; i < bsp_simplices.size(); i++) {
- f->store_line("o Simplex" + itos(i));
- for (int j = 0; j < 4; j++) {
- f->store_line(vformat("v %f %f %f", points[bsp_simplices[i].vertices[j]].x, points[bsp_simplices[i].vertices[j]].y, points[bsp_simplices[i].vertices[j]].z));
- }
- static const int face_order[4][3] = {
- { 1, 2, 3 },
- { 1, 3, 4 },
- { 1, 2, 4 },
- { 2, 3, 4 }
- };
-
- for (int j = 0; j < 4; j++) {
- f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2]));
- }
- }
- f->close();
- }
-#endif
-
- LocalVector<BSPNode> bsp_nodes;
- LocalVector<int32_t> planes_tested;
- planes_tested.resize(bsp_planes.size());
- for (uint32_t i = 0; i < planes_tested.size(); i++) {
- planes_tested[i] = 0x7FFFFFFF;
- }
-
- if (p_bake_step) {
- p_bake_step(0.9, TTR("Generating Probe Acceleration Structures"), p_bake_userdata, true);
- }
-
- _compute_bsp_tree(points, bsp_planes, planes_tested, bsp_simplices, bsp_simplex_indices, bsp_nodes);
-
- PackedInt32Array bsp_array;
- bsp_array.resize(bsp_nodes.size() * 6); // six 32 bits values used for each BSP node
- {
- float *fptr = (float *)bsp_array.ptrw();
- int32_t *iptr = (int32_t *)bsp_array.ptrw();
- for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
- fptr[i * 6 + 0] = bsp_nodes[i].plane.normal.x;
- fptr[i * 6 + 1] = bsp_nodes[i].plane.normal.y;
- fptr[i * 6 + 2] = bsp_nodes[i].plane.normal.z;
- fptr[i * 6 + 3] = bsp_nodes[i].plane.d;
- iptr[i * 6 + 4] = bsp_nodes[i].over;
- iptr[i * 6 + 5] = bsp_nodes[i].under;
- }
-//#define DEBUG_BSP_TREE
-#ifdef DEBUG_BSP_TREE
- FileAccessRef f = FileAccess::open("res://bsp.txt", FileAccess::WRITE);
- for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
- f->store_line(itos(i) + " - plane: " + bsp_nodes[i].plane + " over: " + itos(bsp_nodes[i].over) + " under: " + itos(bsp_nodes[i].under));
- }
-#endif
- }
-
- /* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */
-
- data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array);
- /* Compute a BSP tree of the simplices, so it's easy to find the exact one */
- }
-
- Error err = ResourceSaver::save(p_image_data_path, data);
- data->set_path(p_image_data_path);
-
- if (err != OK) {
- return BAKE_ERROR_CANT_CREATE_IMAGE;
- }
-
- set_light_data(data);
-
- return BAKE_ERROR_OK;
-}
-
-void BakedLightmap::_notification(int p_what) {
- if (p_what == NOTIFICATION_POST_ENTER_TREE) {
- if (light_data.is_valid()) {
- _assign_lightmaps();
- }
- }
-
- if (p_what == NOTIFICATION_EXIT_TREE) {
- if (light_data.is_valid()) {
- _clear_lightmaps();
- }
- }
-}
-
-void BakedLightmap::_assign_lightmaps() {
- ERR_FAIL_COND(!light_data.is_valid());
-
- for (int i = 0; i < light_data->get_user_count(); i++) {
- Node *node = get_node(light_data->get_user_path(i));
- int instance_idx = light_data->get_user_sub_instance(i);
- if (instance_idx >= 0) {
- RID instance = node->call("get_bake_mesh_instance", instance_idx);
- if (instance.is_valid()) {
- RS::get_singleton()->instance_geometry_set_lightmap(instance, get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i));
- }
- } else {
- VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(node);
- ERR_CONTINUE(!vi);
- RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i));
- }
- }
-}
-
-void BakedLightmap::_clear_lightmaps() {
- ERR_FAIL_COND(!light_data.is_valid());
- for (int i = 0; i < light_data->get_user_count(); i++) {
- Node *node = get_node(light_data->get_user_path(i));
- int instance_idx = light_data->get_user_sub_instance(i);
- if (instance_idx >= 0) {
- RID instance = node->call("get_bake_mesh_instance", instance_idx);
- if (instance.is_valid()) {
- RS::get_singleton()->instance_geometry_set_lightmap(instance, RID(), Rect2(), 0);
- }
- } else {
- VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(node);
- ERR_CONTINUE(!vi);
- RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), RID(), Rect2(), 0);
- }
- }
-}
-
-void BakedLightmap::set_light_data(const Ref<BakedLightmapData> &p_data) {
- if (light_data.is_valid()) {
- if (is_inside_tree()) {
- _clear_lightmaps();
- }
- set_base(RID());
- }
- light_data = p_data;
-
- if (light_data.is_valid()) {
- set_base(light_data->get_rid());
- if (is_inside_tree()) {
- _assign_lightmaps();
- }
- }
-
- update_gizmo();
-}
-
-Ref<BakedLightmapData> BakedLightmap::get_light_data() const {
- return light_data;
-}
-
-void BakedLightmap::set_bake_quality(BakeQuality p_quality) {
- bake_quality = p_quality;
-}
-
-BakedLightmap::BakeQuality BakedLightmap::get_bake_quality() const {
- return bake_quality;
-}
-
-AABB BakedLightmap::get_aabb() const {
- return AABB();
-}
-
-Vector<Face3> BakedLightmap::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
-void BakedLightmap::set_use_denoiser(bool p_enable) {
- use_denoiser = p_enable;
-}
-
-bool BakedLightmap::is_using_denoiser() const {
- return use_denoiser;
-}
-
-void BakedLightmap::set_directional(bool p_enable) {
- directional = p_enable;
-}
-
-bool BakedLightmap::is_directional() const {
- return directional;
-}
-
-void BakedLightmap::set_interior(bool p_enable) {
- interior = p_enable;
-}
-
-bool BakedLightmap::is_interior() const {
- return interior;
-}
-
-void BakedLightmap::set_environment_mode(EnvironmentMode p_mode) {
- environment_mode = p_mode;
- notify_property_list_changed();
-}
-
-BakedLightmap::EnvironmentMode BakedLightmap::get_environment_mode() const {
- return environment_mode;
-}
-
-void BakedLightmap::set_environment_custom_sky(const Ref<Sky> &p_sky) {
- environment_custom_sky = p_sky;
-}
-
-Ref<Sky> BakedLightmap::get_environment_custom_sky() const {
- return environment_custom_sky;
-}
-
-void BakedLightmap::set_environment_custom_color(const Color &p_color) {
- environment_custom_color = p_color;
-}
-
-Color BakedLightmap::get_environment_custom_color() const {
- return environment_custom_color;
-}
-
-void BakedLightmap::set_environment_custom_energy(float p_energy) {
- environment_custom_energy = p_energy;
-}
-
-float BakedLightmap::get_environment_custom_energy() const {
- return environment_custom_energy;
-}
-
-void BakedLightmap::set_bounces(int p_bounces) {
- ERR_FAIL_COND(p_bounces < 0 || p_bounces > 16);
- bounces = p_bounces;
-}
-
-int BakedLightmap::get_bounces() const {
- return bounces;
-}
-
-void BakedLightmap::set_bias(float p_bias) {
- ERR_FAIL_COND(p_bias < 0.00001);
- bias = p_bias;
-}
-
-float BakedLightmap::get_bias() const {
- return bias;
-}
-
-void BakedLightmap::set_max_texture_size(int p_size) {
- ERR_FAIL_COND(p_size < 2048);
- max_texture_size = p_size;
-}
-
-int BakedLightmap::get_max_texture_size() const {
- return max_texture_size;
-}
-
-void BakedLightmap::set_generate_probes(GenerateProbes p_generate_probes) {
- gen_probes = p_generate_probes;
-}
-
-BakedLightmap::GenerateProbes BakedLightmap::get_generate_probes() const {
- return gen_probes;
-}
-
-void BakedLightmap::_validate_property(PropertyInfo &property) const {
- if (property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
- property.usage = 0;
- }
- if (property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) {
- property.usage = 0;
- }
- if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
- property.usage = 0;
- }
-}
-
-void BakedLightmap::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_light_data", "data"), &BakedLightmap::set_light_data);
- ClassDB::bind_method(D_METHOD("get_light_data"), &BakedLightmap::get_light_data);
-
- ClassDB::bind_method(D_METHOD("set_bake_quality", "bake_quality"), &BakedLightmap::set_bake_quality);
- ClassDB::bind_method(D_METHOD("get_bake_quality"), &BakedLightmap::get_bake_quality);
-
- ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &BakedLightmap::set_bounces);
- ClassDB::bind_method(D_METHOD("get_bounces"), &BakedLightmap::get_bounces);
-
- ClassDB::bind_method(D_METHOD("set_generate_probes", "subdivision"), &BakedLightmap::set_generate_probes);
- ClassDB::bind_method(D_METHOD("get_generate_probes"), &BakedLightmap::get_generate_probes);
-
- ClassDB::bind_method(D_METHOD("set_bias", "bias"), &BakedLightmap::set_bias);
- ClassDB::bind_method(D_METHOD("get_bias"), &BakedLightmap::get_bias);
-
- ClassDB::bind_method(D_METHOD("set_environment_mode", "mode"), &BakedLightmap::set_environment_mode);
- ClassDB::bind_method(D_METHOD("get_environment_mode"), &BakedLightmap::get_environment_mode);
-
- ClassDB::bind_method(D_METHOD("set_environment_custom_sky", "sky"), &BakedLightmap::set_environment_custom_sky);
- ClassDB::bind_method(D_METHOD("get_environment_custom_sky"), &BakedLightmap::get_environment_custom_sky);
-
- ClassDB::bind_method(D_METHOD("set_environment_custom_color", "color"), &BakedLightmap::set_environment_custom_color);
- ClassDB::bind_method(D_METHOD("get_environment_custom_color"), &BakedLightmap::get_environment_custom_color);
-
- ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &BakedLightmap::set_environment_custom_energy);
- ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &BakedLightmap::get_environment_custom_energy);
-
- ClassDB::bind_method(D_METHOD("set_max_texture_size", "max_texture_size"), &BakedLightmap::set_max_texture_size);
- ClassDB::bind_method(D_METHOD("get_max_texture_size"), &BakedLightmap::get_max_texture_size);
-
- ClassDB::bind_method(D_METHOD("set_use_denoiser", "use_denoiser"), &BakedLightmap::set_use_denoiser);
- ClassDB::bind_method(D_METHOD("is_using_denoiser"), &BakedLightmap::is_using_denoiser);
-
- ClassDB::bind_method(D_METHOD("set_interior", "enable"), &BakedLightmap::set_interior);
- ClassDB::bind_method(D_METHOD("is_interior"), &BakedLightmap::is_interior);
-
- ClassDB::bind_method(D_METHOD("set_directional", "directional"), &BakedLightmap::set_directional);
- ClassDB::bind_method(D_METHOD("is_directional"), &BakedLightmap::is_directional);
-
- // ClassDB::bind_method(D_METHOD("bake", "from_node"), &BakedLightmap::bake, DEFVAL(Variant()));
-
- ADD_GROUP("Tweaks", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,16,1"), "set_bounces", "get_bounces");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional"), "set_directional", "is_directional");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size"), "set_max_texture_size", "get_max_texture_size");
- ADD_GROUP("Environment", "environment_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky");
- ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy");
- ADD_GROUP("Gen Probes", "generate_probes_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes");
- ADD_GROUP("Data", "");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedLightmapData"), "set_light_data", "get_light_data");
-
- BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW);
- BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM);
- BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH);
- BIND_ENUM_CONSTANT(BAKE_QUALITY_ULTRA);
-
- BIND_ENUM_CONSTANT(GENERATE_PROBES_DISABLED);
- BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_4);
- BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_8);
- BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_16);
- BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_32);
-
- BIND_ENUM_CONSTANT(BAKE_ERROR_OK);
- BIND_ENUM_CONSTANT(BAKE_ERROR_NO_LIGHTMAPPER);
- BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH);
- BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES);
- BIND_ENUM_CONSTANT(BAKE_ERROR_MESHES_INVALID);
- BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE);
- BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED);
-
- BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_DISABLED);
- BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_SCENE);
- BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_SKY);
- BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_COLOR);
-}
-
-BakedLightmap::BakedLightmap() {
-}
diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h
deleted file mode 100644
index e2d89ab2d0..0000000000
--- a/scene/3d/baked_lightmap.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/*************************************************************************/
-/* baked_lightmap.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef BAKED_LIGHTMAP_H
-#define BAKED_LIGHTMAP_H
-
-#include "core/templates/local_vector.h"
-#include "scene/3d/light_3d.h"
-#include "scene/3d/lightmapper.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/multimesh_instance_3d.h"
-#include "scene/3d/visual_instance_3d.h"
-#include "scene/resources/sky.h"
-
-class BakedLightmapData : public Resource {
- GDCLASS(BakedLightmapData, Resource);
- RES_BASE_EXTENSION("lmbake")
-
- Ref<TextureLayered> light_texture;
-
- bool uses_spherical_harmonics = false;
- bool interior = false;
-
- RID lightmap;
- AABB bounds;
-
- struct User {
- NodePath path;
- int32_t sub_instance = 0;
- Rect2 uv_scale;
- int slice_index = 0;
- };
-
- Vector<User> users;
-
- void _set_user_data(const Array &p_data);
- Array _get_user_data() const;
- void _set_probe_data(const Dictionary &p_data);
- Dictionary _get_probe_data() const;
-
-protected:
- static void _bind_methods();
-
-public:
- void add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance = -1);
- int get_user_count() const;
- NodePath get_user_path(int p_user) const;
- int32_t get_user_sub_instance(int p_user) const;
- Rect2 get_user_lightmap_uv_scale(int p_user) const;
- int get_user_lightmap_slice_index(int p_user) const;
- void clear_users();
-
- void set_light_texture(const Ref<TextureLayered> &p_light_texture);
- Ref<TextureLayered> get_light_texture() const;
-
- void set_uses_spherical_harmonics(bool p_enable);
- bool is_using_spherical_harmonics() const;
-
- bool is_interior() const;
-
- void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree);
- PackedVector3Array get_capture_points() const;
- PackedColorArray get_capture_sh() const;
- PackedInt32Array get_capture_tetrahedra() const;
- PackedInt32Array get_capture_bsp_tree() const;
- AABB get_capture_bounds() const;
-
- void clear();
-
- virtual RID get_rid() const override;
- BakedLightmapData();
- ~BakedLightmapData();
-};
-
-class BakedLightmap : public VisualInstance3D {
- GDCLASS(BakedLightmap, VisualInstance3D);
-
-public:
- enum BakeQuality {
- BAKE_QUALITY_LOW,
- BAKE_QUALITY_MEDIUM,
- BAKE_QUALITY_HIGH,
- BAKE_QUALITY_ULTRA,
- };
-
- enum GenerateProbes {
- GENERATE_PROBES_DISABLED,
- GENERATE_PROBES_SUBDIV_4,
- GENERATE_PROBES_SUBDIV_8,
- GENERATE_PROBES_SUBDIV_16,
- GENERATE_PROBES_SUBDIV_32,
- };
-
- enum BakeError {
- BAKE_ERROR_OK,
- BAKE_ERROR_NO_LIGHTMAPPER,
- BAKE_ERROR_NO_SAVE_PATH,
- BAKE_ERROR_NO_MESHES,
- BAKE_ERROR_MESHES_INVALID,
- BAKE_ERROR_CANT_CREATE_IMAGE,
- BAKE_ERROR_USER_ABORTED,
- };
-
- enum EnvironmentMode {
- ENVIRONMENT_MODE_DISABLED,
- ENVIRONMENT_MODE_SCENE,
- ENVIRONMENT_MODE_CUSTOM_SKY,
- ENVIRONMENT_MODE_CUSTOM_COLOR,
- };
-
-private:
- BakeQuality bake_quality = BAKE_QUALITY_MEDIUM;
- bool use_denoiser = true;
- int bounces = 1;
- float bias = 0.0005;
- int max_texture_size = 16384;
- bool interior = false;
- EnvironmentMode environment_mode = ENVIRONMENT_MODE_DISABLED;
- Ref<Sky> environment_custom_sky;
- Color environment_custom_color = Color(0.2, 0.7, 1.0);
- float environment_custom_energy = 1.0;
- bool directional = false;
- GenerateProbes gen_probes = GENERATE_PROBES_DISABLED;
-
- Ref<BakedLightmapData> light_data;
-
- struct LightsFound {
- Transform xform;
- Light3D *light = nullptr;
- };
-
- struct MeshesFound {
- Transform xform;
- NodePath node_path;
- int32_t subindex = 0;
- Ref<Mesh> mesh;
- int32_t lightmap_scale = 0;
- Vector<Ref<Material>> overrides;
- };
-
- void _find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes);
-
- void _assign_lightmaps();
- void _clear_lightmaps();
-
- struct BakeTimeData {
- String text;
- int pass = 0;
- uint64_t last_step = 0;
- };
-
- struct BSPSimplex {
- int vertices[4] = {};
- int planes[4] = {};
- };
-
- struct BSPNode {
- static const int32_t EMPTY_LEAF = INT32_MIN;
- Plane plane;
- int32_t over = EMPTY_LEAF;
- int32_t under = EMPTY_LEAF;
- };
-
- int _bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const;
- int32_t _compute_bsp_tree(const Vector<Vector3> &p_points, const LocalVector<Plane> &p_planes, LocalVector<int32_t> &planes_tested, const LocalVector<BSPSimplex> &p_simplices, const LocalVector<int32_t> &p_simplex_indices, LocalVector<BSPNode> &bsp_nodes);
-
- struct BakeStepUD {
- Lightmapper::BakeStepFunc func;
- void *ud = nullptr;
- float from_percent = 0.0;
- float to_percent = 0.0;
- };
-
- static bool _lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh);
-
- struct GenProbesOctree {
- Vector3i offset;
- uint32_t size = 0;
- GenProbesOctree *children[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
- ~GenProbesOctree() {
- for (int i = 0; i < 8; i++) {
- if (children[i] != nullptr) {
- memdelete(children[i]);
- }
- }
- }
- };
-
- struct Vector3iHash {
- _FORCE_INLINE_ static uint32_t hash(const Vector3i &p_vtx) {
- uint32_t h = hash_djb2_one_32(p_vtx.x);
- h = hash_djb2_one_32(p_vtx.y, h);
- return hash_djb2_one_32(p_vtx.z, h);
- }
- };
-
- void _plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle);
- void _gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector<Vector3> &probe_positions, LocalVector<Vector3> &new_probe_positions, HashMap<Vector3i, bool, Vector3iHash> &positions_used, const AABB &p_bounds);
-
-protected:
- void _validate_property(PropertyInfo &property) const override;
- static void _bind_methods();
- void _notification(int p_what);
-
-public:
- void set_light_data(const Ref<BakedLightmapData> &p_data);
- Ref<BakedLightmapData> get_light_data() const;
-
- void set_bake_quality(BakeQuality p_quality);
- BakeQuality get_bake_quality() const;
-
- void set_use_denoiser(bool p_enable);
- bool is_using_denoiser() const;
-
- void set_directional(bool p_enable);
- bool is_directional() const;
-
- void set_interior(bool p_interior);
- bool is_interior() const;
-
- void set_environment_mode(EnvironmentMode p_mode);
- EnvironmentMode get_environment_mode() const;
-
- void set_environment_custom_sky(const Ref<Sky> &p_sky);
- Ref<Sky> get_environment_custom_sky() const;
-
- void set_environment_custom_color(const Color &p_color);
- Color get_environment_custom_color() const;
-
- void set_environment_custom_energy(float p_energy);
- float get_environment_custom_energy() const;
-
- void set_bounces(int p_bounces);
- int get_bounces() const;
-
- void set_bias(float p_bias);
- float get_bias() const;
-
- void set_max_texture_size(int p_size);
- int get_max_texture_size() const;
-
- void set_generate_probes(GenerateProbes p_generate_probes);
- GenerateProbes get_generate_probes() const;
-
- AABB get_aabb() const override;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
-
- BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr);
- BakedLightmap();
-};
-
-VARIANT_ENUM_CAST(BakedLightmap::BakeQuality);
-VARIANT_ENUM_CAST(BakedLightmap::GenerateProbes);
-VARIANT_ENUM_CAST(BakedLightmap::BakeError);
-VARIANT_ENUM_CAST(BakedLightmap::EnvironmentMode);
-
-#endif // BAKED_LIGHTMAP_H
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 041da4f6ff..6b8851b4f8 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -150,8 +150,8 @@ void Camera3D::_notification(int p_what) {
}
}
-Transform Camera3D::get_camera_transform() const {
- Transform tr = get_global_transform().orthonormalized();
+Transform3D Camera3D::get_camera_transform() const {
+ Transform3D tr = get_global_transform().orthonormalized();
tr.origin += tr.basis.get_axis(1) * v_offset;
tr.origin += tr.basis.get_axis(0) * h_offset;
return tr;
@@ -318,7 +318,7 @@ Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const {
};
bool Camera3D::is_position_behind(const Vector3 &p_pos) const {
- Transform t = get_global_transform();
+ Transform3D t = get_global_transform();
Vector3 eyedir = -t.basis.get_axis(2).normalized();
return eyedir.dot(p_pos - t.origin) < near;
}
@@ -337,7 +337,7 @@ Vector<Vector3> Camera3D::get_near_plane_points() const {
}
Vector3 endpoints[8];
- cm.get_endpoints(Transform(), endpoints);
+ cm.get_endpoints(Transform3D(), endpoints);
Vector<Vector3> points;
points.push_back(Vector3());
@@ -500,6 +500,7 @@ void Camera3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera3D::set_doppler_tracking);
ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera3D::get_doppler_tracking);
ClassDB::bind_method(D_METHOD("get_frustum"), &Camera3D::get_frustum);
+ ClassDB::bind_method(D_METHOD("is_position_in_frustum", "world_point"), &Camera3D::is_position_in_frustum);
ClassDB::bind_method(D_METHOD("get_camera_rid"), &Camera3D::get_camera);
ClassDB::bind_method(D_METHOD("set_cull_mask_bit", "layer", "enable"), &Camera3D::set_cull_mask_bit);
@@ -623,6 +624,16 @@ Vector<Plane> Camera3D::get_frustum() const {
return cm.get_projection_planes(get_camera_transform());
}
+bool Camera3D::is_position_in_frustum(const Vector3 &p_position) const {
+ Vector<Plane> frustum = get_frustum();
+ for (int i = 0; i < frustum.size(); i++) {
+ if (frustum[i].is_point_over(p_position)) {
+ return false;
+ }
+ }
+ return true;
+}
+
void Camera3D::set_v_offset(float p_offset) {
v_offset = p_offset;
_update_camera();
@@ -686,8 +697,8 @@ ClippedCamera3D::ClipProcessCallback ClippedCamera3D::get_process_callback() con
return process_callback;
}
-Transform ClippedCamera3D::get_camera_transform() const {
- Transform t = Camera3D::get_camera_transform();
+Transform3D ClippedCamera3D::get_camera_transform() const {
+ Transform3D t = Camera3D::get_camera_transform();
t.origin += -t.basis.get_axis(Vector3::AXIS_Z).normalized() * clip_offset;
return t;
}
@@ -735,7 +746,7 @@ void ClippedCamera3D::_notification(int p_what) {
}
}
- Transform xf = get_global_transform();
+ Transform3D xf = get_global_transform();
xf.origin = ray_from;
xf.orthonormalize();
diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h
index cea61e4db8..c6efc8f9a9 100644
--- a/scene/3d/camera_3d.h
+++ b/scene/3d/camera_3d.h
@@ -134,7 +134,7 @@ public:
void set_near(float p_near);
void set_frustum_offset(Vector2 p_offset);
- virtual Transform get_camera_transform() const;
+ virtual Transform3D get_camera_transform() const;
virtual Vector3 project_ray_normal(const Point2 &p_pos) const;
virtual Vector3 project_ray_origin(const Point2 &p_pos) const;
@@ -153,6 +153,7 @@ public:
bool get_cull_mask_bit(int p_layer) const;
virtual Vector<Plane> get_frustum() const;
+ bool is_position_in_frustum(const Vector3 &p_position) const;
void set_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_environment() const;
@@ -207,7 +208,7 @@ private:
protected:
void _notification(int p_what);
static void _bind_methods();
- virtual Transform get_camera_transform() const override;
+ virtual Transform3D get_camera_transform() const override;
public:
void set_clip_to_areas(bool p_clip);
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index 914b3ad816..a04667e53b 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -215,6 +215,11 @@ void CollisionObject3D::_shape_changed(const Ref<Shape3D> &p_shape) {
}
void CollisionObject3D::_update_debug_shapes() {
+ if (!is_inside_tree()) {
+ debug_shapes_to_update.clear();
+ return;
+ }
+
for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) {
if (shapes.has(shapedata_idx->get())) {
ShapeData &shapedata = shapes[shapedata_idx->get()];
@@ -321,9 +326,9 @@ void CollisionObject3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes);
ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner);
- BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
+ BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "position"), PropertyInfo(Variant::VECTOR3, "normal"), PropertyInfo(Variant::INT, "shape_idx")));
- ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
+ ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "position"), PropertyInfo(Variant::VECTOR3, "normal"), PropertyInfo(Variant::INT, "shape_idx")));
ADD_SIGNAL(MethodInfo("mouse_entered"));
ADD_SIGNAL(MethodInfo("mouse_exited"));
@@ -401,7 +406,7 @@ Array CollisionObject3D::_get_shape_owners() {
return ret;
}
-void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform) {
+void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transform3D &p_transform) {
ERR_FAIL_COND(!shapes.has(p_owner));
ShapeData &sd = shapes[p_owner];
@@ -416,9 +421,8 @@ void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transf
_update_shape_data(p_owner);
}
-
-Transform CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const {
- ERR_FAIL_COND_V(!shapes.has(p_owner), Transform());
+Transform3D CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const {
+ ERR_FAIL_COND_V(!shapes.has(p_owner), Transform3D());
return shapes[p_owner].xform;
}
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h
index 7ff3c5efde..50a9b4fcd0 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/collision_object_3d.h
@@ -46,7 +46,7 @@ class CollisionObject3D : public Node3D {
struct ShapeData {
Object *owner = nullptr;
- Transform xform;
+ Transform3D xform;
struct ShapeBase {
RID debug_shape;
Ref<Shape3D> shape;
@@ -66,7 +66,7 @@ class CollisionObject3D : public Node3D {
Set<uint32_t> debug_shapes_to_update;
int debug_shapes_count = 0;
- Transform debug_shape_old_transform;
+ Transform3D debug_shape_old_transform;
void _update_pickable();
@@ -107,8 +107,8 @@ public:
void get_shape_owners(List<uint32_t> *r_owners);
Array _get_shape_owners();
- void shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform);
- Transform shape_owner_get_transform(uint32_t p_owner) const;
+ void shape_owner_set_transform(uint32_t p_owner, const Transform3D &p_transform);
+ Transform3D shape_owner_get_transform(uint32_t p_owner) const;
Object *shape_owner_get_owner(uint32_t p_owner) const;
void shape_owner_set_disabled(uint32_t p_owner, bool p_disabled);
diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp
index ac715b22b2..8a4f8b639b 100644
--- a/scene/3d/collision_polygon_3d.cpp
+++ b/scene/3d/collision_polygon_3d.cpp
@@ -171,7 +171,7 @@ TypedArray<String> CollisionPolygon3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject3D>(get_parent())) {
- warnings.push_back(TTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape."));
+ warnings.push_back(TTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape."));
}
if (polygon.is_empty()) {
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index 70d9cebb83..be3fde8013 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -124,7 +124,7 @@ TypedArray<String> CollisionShape3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject3D>(get_parent())) {
- warnings.push_back(TTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape."));
+ warnings.push_back(TTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape."));
}
if (!shape.is_valid()) {
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index aa29728c73..2301fef651 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -574,7 +574,7 @@ void CPUParticles3D::_particles_process(float p_delta) {
}
}
- Transform emission_xform;
+ Transform3D emission_xform;
Basis velocity_xform;
if (!local_coords) {
emission_xform = get_global_transform();
@@ -693,7 +693,7 @@ void CPUParticles3D::_particles_process(float p_delta) {
p.custom[0] = Math::deg2rad(base_angle); //angle
p.custom[1] = 0.0; //phase
p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation offset (0-1)
- p.transform = Transform();
+ p.transform = Transform3D();
p.time = 0;
p.lifetime = lifetime * (1.0 - Math::randf() * lifetime_randomness);
p.base_color = Color(1, 1, 1, 1);
@@ -1030,7 +1030,7 @@ void CPUParticles3D::_update_particle_data_buffer() {
for (int i = 0; i < pc; i++) {
int idx = order ? order[i] : i;
- Transform t = r[idx].transform;
+ Transform3D t = r[idx].transform;
if (!local_coords) {
t = inv_emission_transform * t;
@@ -1139,7 +1139,7 @@ void CPUParticles3D::_notification(int p_what) {
float *ptr = w;
for (int i = 0; i < pc; i++) {
- Transform t = inv_emission_transform * r[i].transform;
+ Transform3D t = inv_emission_transform * r[i].transform;
if (r[i].active) {
ptr[0] = t.basis.elements[0][0];
diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index c073c93c47..b35e659757 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -83,7 +83,7 @@ private:
bool emitting = false;
struct Particle {
- Transform transform;
+ Transform3D transform;
Color color;
float custom[4] = {};
Vector3 velocity;
@@ -141,7 +141,7 @@ private:
int fixed_fps = 0;
bool fractional_delta = true;
- Transform inv_emission_transform;
+ Transform3D inv_emission_transform;
SafeFlag can_update;
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
deleted file mode 100644
index 4d7fc29f15..0000000000
--- a/scene/3d/gi_probe.cpp
+++ /dev/null
@@ -1,549 +0,0 @@
-/*************************************************************************/
-/* gi_probe.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "gi_probe.h"
-
-#include "core/os/os.h"
-
-#include "mesh_instance_3d.h"
-#include "voxelizer.h"
-
-void GIProbeData::_set_data(const Dictionary &p_data) {
- ERR_FAIL_COND(!p_data.has("bounds"));
- ERR_FAIL_COND(!p_data.has("octree_size"));
- ERR_FAIL_COND(!p_data.has("octree_cells"));
- ERR_FAIL_COND(!p_data.has("octree_data"));
- ERR_FAIL_COND(!p_data.has("octree_df") && !p_data.has("octree_df_png"));
- ERR_FAIL_COND(!p_data.has("level_counts"));
- ERR_FAIL_COND(!p_data.has("to_cell_xform"));
-
- AABB bounds = p_data["bounds"];
- Vector3 octree_size = p_data["octree_size"];
- Vector<uint8_t> octree_cells = p_data["octree_cells"];
- Vector<uint8_t> octree_data = p_data["octree_data"];
-
- Vector<uint8_t> octree_df;
- if (p_data.has("octree_df")) {
- octree_df = p_data["octree_df"];
- } else if (p_data.has("octree_df_png")) {
- Vector<uint8_t> octree_df_png = p_data["octree_df_png"];
- Ref<Image> img;
- img.instance();
- Error err = img->load_png_from_buffer(octree_df_png);
- ERR_FAIL_COND(err != OK);
- ERR_FAIL_COND(img->get_format() != Image::FORMAT_L8);
- octree_df = img->get_data();
- }
- Vector<int> octree_levels = p_data["level_counts"];
- Transform to_cell_xform = p_data["to_cell_xform"];
-
- allocate(to_cell_xform, bounds, octree_size, octree_cells, octree_data, octree_df, octree_levels);
-}
-
-Dictionary GIProbeData::_get_data() const {
- Dictionary d;
- d["bounds"] = get_bounds();
- Vector3i otsize = get_octree_size();
- d["octree_size"] = Vector3(otsize);
- d["octree_cells"] = get_octree_cells();
- d["octree_data"] = get_data_cells();
- if (otsize != Vector3i()) {
- Ref<Image> img;
- img.instance();
- img->create(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field());
- Vector<uint8_t> df_png = img->save_png_to_buffer();
- ERR_FAIL_COND_V(df_png.size() == 0, Dictionary());
- d["octree_df_png"] = df_png;
- } else {
- d["octree_df"] = Vector<uint8_t>();
- }
-
- d["level_counts"] = get_level_counts();
- d["to_cell_xform"] = get_to_cell_xform();
- return d;
-}
-
-void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
- RS::get_singleton()->gi_probe_allocate_data(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts);
- bounds = p_aabb;
- to_cell_xform = p_to_cell_xform;
- octree_size = p_octree_size;
-}
-
-AABB GIProbeData::get_bounds() const {
- return bounds;
-}
-
-Vector3 GIProbeData::get_octree_size() const {
- return octree_size;
-}
-
-Vector<uint8_t> GIProbeData::get_octree_cells() const {
- return RS::get_singleton()->gi_probe_get_octree_cells(probe);
-}
-
-Vector<uint8_t> GIProbeData::get_data_cells() const {
- return RS::get_singleton()->gi_probe_get_data_cells(probe);
-}
-
-Vector<uint8_t> GIProbeData::get_distance_field() const {
- return RS::get_singleton()->gi_probe_get_distance_field(probe);
-}
-
-Vector<int> GIProbeData::get_level_counts() const {
- return RS::get_singleton()->gi_probe_get_level_counts(probe);
-}
-
-Transform GIProbeData::get_to_cell_xform() const {
- return to_cell_xform;
-}
-
-void GIProbeData::set_dynamic_range(float p_range) {
- RS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range);
- dynamic_range = p_range;
-}
-
-float GIProbeData::get_dynamic_range() const {
- return dynamic_range;
-}
-
-void GIProbeData::set_propagation(float p_propagation) {
- RS::get_singleton()->gi_probe_set_propagation(probe, p_propagation);
- propagation = p_propagation;
-}
-
-float GIProbeData::get_propagation() const {
- return propagation;
-}
-
-void GIProbeData::set_anisotropy_strength(float p_anisotropy_strength) {
- RS::get_singleton()->gi_probe_set_anisotropy_strength(probe, p_anisotropy_strength);
- anisotropy_strength = p_anisotropy_strength;
-}
-
-float GIProbeData::get_anisotropy_strength() const {
- return anisotropy_strength;
-}
-
-void GIProbeData::set_energy(float p_energy) {
- RS::get_singleton()->gi_probe_set_energy(probe, p_energy);
- energy = p_energy;
-}
-
-float GIProbeData::get_energy() const {
- return energy;
-}
-
-void GIProbeData::set_ao(float p_ao) {
- RS::get_singleton()->gi_probe_set_ao(probe, p_ao);
- ao = p_ao;
-}
-
-float GIProbeData::get_ao() const {
- return ao;
-}
-
-void GIProbeData::set_ao_size(float p_ao_size) {
- RS::get_singleton()->gi_probe_set_ao_size(probe, p_ao_size);
- ao_size = p_ao_size;
-}
-
-float GIProbeData::get_ao_size() const {
- return ao_size;
-}
-
-void GIProbeData::set_bias(float p_bias) {
- RS::get_singleton()->gi_probe_set_bias(probe, p_bias);
- bias = p_bias;
-}
-
-float GIProbeData::get_bias() const {
- return bias;
-}
-
-void GIProbeData::set_normal_bias(float p_normal_bias) {
- RS::get_singleton()->gi_probe_set_normal_bias(probe, p_normal_bias);
- normal_bias = p_normal_bias;
-}
-
-float GIProbeData::get_normal_bias() const {
- return normal_bias;
-}
-
-void GIProbeData::set_interior(bool p_enable) {
- RS::get_singleton()->gi_probe_set_interior(probe, p_enable);
- interior = p_enable;
-}
-
-bool GIProbeData::is_interior() const {
- return interior;
-}
-
-void GIProbeData::set_use_two_bounces(bool p_enable) {
- RS::get_singleton()->gi_probe_set_use_two_bounces(probe, p_enable);
- use_two_bounces = p_enable;
-}
-
-bool GIProbeData::is_using_two_bounces() const {
- return use_two_bounces;
-}
-
-RID GIProbeData::get_rid() const {
- return probe;
-}
-
-void GIProbeData::_validate_property(PropertyInfo &property) const {
- if (property.name == "anisotropy_strength") {
- bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/global_illumination/gi_probes/anisotropic");
- if (!anisotropy_enabled) {
- property.usage = PROPERTY_USAGE_NOEDITOR;
- }
- }
-}
-
-void GIProbeData::_bind_methods() {
- ClassDB::bind_method(D_METHOD("allocate", "to_cell_xform", "aabb", "octree_size", "octree_cells", "data_cells", "distance_field", "level_counts"), &GIProbeData::allocate);
-
- ClassDB::bind_method(D_METHOD("get_bounds"), &GIProbeData::get_bounds);
- ClassDB::bind_method(D_METHOD("get_octree_size"), &GIProbeData::get_octree_size);
- ClassDB::bind_method(D_METHOD("get_to_cell_xform"), &GIProbeData::get_to_cell_xform);
- ClassDB::bind_method(D_METHOD("get_octree_cells"), &GIProbeData::get_octree_cells);
- ClassDB::bind_method(D_METHOD("get_data_cells"), &GIProbeData::get_data_cells);
- ClassDB::bind_method(D_METHOD("get_level_counts"), &GIProbeData::get_level_counts);
-
- ClassDB::bind_method(D_METHOD("set_dynamic_range", "dynamic_range"), &GIProbeData::set_dynamic_range);
- ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbeData::get_dynamic_range);
-
- ClassDB::bind_method(D_METHOD("set_energy", "energy"), &GIProbeData::set_energy);
- ClassDB::bind_method(D_METHOD("get_energy"), &GIProbeData::get_energy);
-
- ClassDB::bind_method(D_METHOD("set_bias", "bias"), &GIProbeData::set_bias);
- ClassDB::bind_method(D_METHOD("get_bias"), &GIProbeData::get_bias);
-
- ClassDB::bind_method(D_METHOD("set_normal_bias", "bias"), &GIProbeData::set_normal_bias);
- ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbeData::get_normal_bias);
-
- ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &GIProbeData::set_propagation);
- ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbeData::get_propagation);
-
- ClassDB::bind_method(D_METHOD("set_anisotropy_strength", "strength"), &GIProbeData::set_anisotropy_strength);
- ClassDB::bind_method(D_METHOD("get_anisotropy_strength"), &GIProbeData::get_anisotropy_strength);
-
- ClassDB::bind_method(D_METHOD("set_ao", "ao"), &GIProbeData::set_ao);
- ClassDB::bind_method(D_METHOD("get_ao"), &GIProbeData::get_ao);
-
- ClassDB::bind_method(D_METHOD("set_ao_size", "strength"), &GIProbeData::set_ao_size);
- ClassDB::bind_method(D_METHOD("get_ao_size"), &GIProbeData::get_ao_size);
-
- ClassDB::bind_method(D_METHOD("set_interior", "interior"), &GIProbeData::set_interior);
- ClassDB::bind_method(D_METHOD("is_interior"), &GIProbeData::is_interior);
-
- ClassDB::bind_method(D_METHOD("set_use_two_bounces", "enable"), &GIProbeData::set_use_two_bounces);
- ClassDB::bind_method(D_METHOD("is_using_two_bounces"), &GIProbeData::is_using_two_bounces);
-
- ClassDB::bind_method(D_METHOD("_set_data", "data"), &GIProbeData::_set_data);
- ClassDB::bind_method(D_METHOD("_get_data"), &GIProbeData::_get_data);
-
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_dynamic_range", "get_dynamic_range");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_bias", "get_bias");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_normal_bias", "get_normal_bias");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anisotropy_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy_strength", "get_anisotropy_strength");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao", "get_ao");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_size", "get_ao_size");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_two_bounces"), "set_use_two_bounces", "is_using_two_bounces");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
-}
-
-GIProbeData::GIProbeData() {
- probe = RS::get_singleton()->gi_probe_create();
-}
-
-GIProbeData::~GIProbeData() {
- RS::get_singleton()->free(probe);
-}
-
-//////////////////////
-//////////////////////
-
-void GIProbe::set_probe_data(const Ref<GIProbeData> &p_data) {
- if (p_data.is_valid()) {
- RS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid());
- } else {
- RS::get_singleton()->instance_set_base(get_instance(), RID());
- }
-
- probe_data = p_data;
-}
-
-Ref<GIProbeData> GIProbe::get_probe_data() const {
- return probe_data;
-}
-
-void GIProbe::set_subdiv(Subdiv p_subdiv) {
- ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX);
- subdiv = p_subdiv;
- update_gizmo();
-}
-
-GIProbe::Subdiv GIProbe::get_subdiv() const {
- return subdiv;
-}
-
-void GIProbe::set_extents(const Vector3 &p_extents) {
- extents = p_extents;
- update_gizmo();
-}
-
-Vector3 GIProbe::get_extents() const {
- return extents;
-}
-
-void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
- if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) {
- Ref<Mesh> mesh = mi->get_mesh();
- if (mesh.is_valid()) {
- AABB aabb = mesh->get_aabb();
-
- Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform();
-
- if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
- PlotMesh pm;
- pm.local_xform = xf;
- pm.mesh = mesh;
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- pm.instance_materials.push_back(mi->get_surface_override_material(i));
- }
- pm.override_material = mi->get_material_override();
- plot_meshes.push_back(pm);
- }
- }
- }
-
- Node3D *s = Object::cast_to<Node3D>(p_at_node);
- if (s) {
- if (s->is_visible_in_tree()) {
- Array meshes = p_at_node->call("get_meshes");
- for (int i = 0; i < meshes.size(); i += 2) {
- Transform mxf = meshes[i];
- Ref<Mesh> mesh = meshes[i + 1];
- if (!mesh.is_valid()) {
- continue;
- }
-
- AABB aabb = mesh->get_aabb();
-
- Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf);
-
- if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
- PlotMesh pm;
- pm.local_xform = xf;
- pm.mesh = mesh;
- plot_meshes.push_back(pm);
- }
- }
- }
- }
-
- for (int i = 0; i < p_at_node->get_child_count(); i++) {
- Node *child = p_at_node->get_child(i);
- _find_meshes(child, plot_meshes);
- }
-}
-
-GIProbe::BakeBeginFunc GIProbe::bake_begin_function = nullptr;
-GIProbe::BakeStepFunc GIProbe::bake_step_function = nullptr;
-GIProbe::BakeEndFunc GIProbe::bake_end_function = nullptr;
-
-Vector3i GIProbe::get_estimated_cell_size() const {
- static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
- int cell_subdiv = subdiv_value[subdiv];
- int axis_cell_size[3];
- AABB bounds = AABB(-extents, extents * 2.0);
- int longest_axis = bounds.get_longest_axis_index();
- axis_cell_size[longest_axis] = 1 << cell_subdiv;
-
- for (int i = 0; i < 3; i++) {
- if (i == longest_axis) {
- continue;
- }
-
- axis_cell_size[i] = axis_cell_size[longest_axis];
- float axis_size = bounds.size[longest_axis];
-
- //shrink until fit subdiv
- while (axis_size / 2.0 >= bounds.size[i]) {
- axis_size /= 2.0;
- axis_cell_size[i] >>= 1;
- }
- }
-
- return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]);
-}
-
-void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
- static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
-
- p_from_node = p_from_node ? p_from_node : get_parent();
- ERR_FAIL_NULL(p_from_node);
-
- Voxelizer baker;
-
- baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0));
-
- List<PlotMesh> mesh_list;
-
- _find_meshes(p_from_node, mesh_list);
-
- if (bake_begin_function) {
- bake_begin_function(mesh_list.size() + 1);
- }
-
- int pmc = 0;
-
- for (List<PlotMesh>::Element *E = mesh_list.front(); E; E = E->next()) {
- if (bake_step_function) {
- bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size()));
- }
-
- pmc++;
-
- baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material);
- }
- if (bake_step_function) {
- bake_step_function(pmc++, RTR("Finishing Plot"));
- }
-
- baker.end_bake();
-
- //create the data for visual server
-
- if (p_create_visual_debug) {
- MultiMeshInstance3D *mmi = memnew(MultiMeshInstance3D);
- mmi->set_multimesh(baker.create_debug_multimesh());
- add_child(mmi);
-#ifdef TOOLS_ENABLED
- if (get_tree()->get_edited_scene_root() == this) {
- mmi->set_owner(this);
- } else {
- mmi->set_owner(get_owner());
- }
-#else
- mmi->set_owner(get_owner());
-#endif
-
- } else {
- Ref<GIProbeData> probe_data = get_probe_data();
-
- if (probe_data.is_null()) {
- probe_data.instance();
- }
-
- if (bake_step_function) {
- bake_step_function(pmc++, RTR("Generating Distance Field"));
- }
-
- Vector<uint8_t> df = baker.get_sdf_3d_image();
-
- probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_giprobe_octree_size(), baker.get_giprobe_octree_cells(), baker.get_giprobe_data_cells(), df, baker.get_giprobe_level_cell_count());
-
- set_probe_data(probe_data);
-#ifdef TOOLS_ENABLED
- probe_data->set_edited(true); //so it gets saved
-#endif
- }
-
- if (bake_end_function) {
- bake_end_function();
- }
-
- notify_property_list_changed(); //bake property may have changed
-}
-
-void GIProbe::_debug_bake() {
- bake(nullptr, true);
-}
-
-AABB GIProbe::get_aabb() const {
- return AABB(-extents, extents * 2);
-}
-
-Vector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
-TypedArray<String> GIProbe::get_configuration_warnings() const {
- TypedArray<String> warnings = Node::get_configuration_warnings();
-
- if (RenderingServer::get_singleton()->is_low_end()) {
- warnings.push_back(TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead."));
- } else if (probe_data.is_null()) {
- warnings.push_back(TTR("No GIProbe data set, so this node is disabled. Bake static objects to enable GI."));
- }
- return warnings;
-}
-
-void GIProbe::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &GIProbe::set_probe_data);
- ClassDB::bind_method(D_METHOD("get_probe_data"), &GIProbe::get_probe_data);
-
- ClassDB::bind_method(D_METHOD("set_subdiv", "subdiv"), &GIProbe::set_subdiv);
- ClassDB::bind_method(D_METHOD("get_subdiv"), &GIProbe::get_subdiv);
-
- ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GIProbe::set_extents);
- ClassDB::bind_method(D_METHOD("get_extents"), &GIProbe::get_extents);
-
- ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &GIProbe::bake, DEFVAL(Variant()), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("debug_bake"), &GIProbe::_debug_bake);
- ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
-
- BIND_ENUM_CONSTANT(SUBDIV_64);
- BIND_ENUM_CONSTANT(SUBDIV_128);
- BIND_ENUM_CONSTANT(SUBDIV_256);
- BIND_ENUM_CONSTANT(SUBDIV_512);
- BIND_ENUM_CONSTANT(SUBDIV_MAX);
-}
-
-GIProbe::GIProbe() {
- gi_probe = RS::get_singleton()->gi_probe_create();
- set_disable_scale(true);
-}
-
-GIProbe::~GIProbe() {
- RS::get_singleton()->free(gi_probe);
-}
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
deleted file mode 100644
index dac7dd3e17..0000000000
--- a/scene/3d/gi_probe.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*************************************************************************/
-/* gi_probe.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef GIPROBE_H
-#define GIPROBE_H
-
-#include "multimesh_instance_3d.h"
-#include "scene/3d/visual_instance_3d.h"
-
-class GIProbeData : public Resource {
- GDCLASS(GIProbeData, Resource);
-
- RID probe;
-
- void _set_data(const Dictionary &p_data);
- Dictionary _get_data() const;
-
- Transform to_cell_xform;
- AABB bounds;
- Vector3 octree_size;
-
- float dynamic_range = 4.0;
- float energy = 1.0;
- float bias = 1.5;
- float normal_bias = 0.0;
- float propagation = 0.7;
- float anisotropy_strength = 0.5;
- float ao = 0.0;
- float ao_size = 0.5;
- bool interior = false;
- bool use_two_bounces = false;
-
-protected:
- static void _bind_methods();
- void _validate_property(PropertyInfo &property) const override;
-
-public:
- void allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
- AABB get_bounds() const;
- Vector3 get_octree_size() const;
- Vector<uint8_t> get_octree_cells() const;
- Vector<uint8_t> get_data_cells() const;
- Vector<uint8_t> get_distance_field() const;
- Vector<int> get_level_counts() const;
- Transform get_to_cell_xform() const;
-
- void set_dynamic_range(float p_range);
- float get_dynamic_range() const;
-
- void set_propagation(float p_propagation);
- float get_propagation() const;
-
- void set_anisotropy_strength(float p_anisotropy_strength);
- float get_anisotropy_strength() const;
-
- void set_ao(float p_ao);
- float get_ao() const;
-
- void set_ao_size(float p_ao_size);
- float get_ao_size() const;
-
- void set_energy(float p_energy);
- float get_energy() const;
-
- void set_bias(float p_bias);
- float get_bias() const;
-
- void set_normal_bias(float p_normal_bias);
- float get_normal_bias() const;
-
- void set_interior(bool p_enable);
- bool is_interior() const;
-
- void set_use_two_bounces(bool p_enable);
- bool is_using_two_bounces() const;
-
- virtual RID get_rid() const override;
-
- GIProbeData();
- ~GIProbeData();
-};
-
-class GIProbe : public VisualInstance3D {
- GDCLASS(GIProbe, VisualInstance3D);
-
-public:
- enum Subdiv {
- SUBDIV_64,
- SUBDIV_128,
- SUBDIV_256,
- SUBDIV_512,
- SUBDIV_MAX
-
- };
-
- typedef void (*BakeBeginFunc)(int);
- typedef void (*BakeStepFunc)(int, const String &);
- typedef void (*BakeEndFunc)();
-
-private:
- Ref<GIProbeData> probe_data;
-
- RID gi_probe;
-
- Subdiv subdiv = SUBDIV_128;
- Vector3 extents = Vector3(10, 10, 10);
-
- struct PlotMesh {
- Ref<Material> override_material;
- Vector<Ref<Material>> instance_materials;
- Ref<Mesh> mesh;
- Transform local_xform;
- };
-
- void _find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes);
- void _debug_bake();
-
-protected:
- static void _bind_methods();
-
-public:
- static BakeBeginFunc bake_begin_function;
- static BakeStepFunc bake_step_function;
- static BakeEndFunc bake_end_function;
-
- void set_probe_data(const Ref<GIProbeData> &p_data);
- Ref<GIProbeData> get_probe_data() const;
-
- void set_subdiv(Subdiv p_subdiv);
- Subdiv get_subdiv() const;
-
- void set_extents(const Vector3 &p_extents);
- Vector3 get_extents() const;
- Vector3i get_estimated_cell_size() const;
-
- void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false);
-
- virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
-
- TypedArray<String> get_configuration_warnings() const override;
-
- GIProbe();
- ~GIProbe();
-};
-
-VARIANT_ENUM_CAST(GIProbe::Subdiv)
-
-#endif // GIPROBE_H
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 50044ddc67..d7f4bfeb4e 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -181,7 +181,7 @@ void GPUParticles3D::set_draw_order(DrawOrder p_order) {
RS::get_singleton()->particles_set_draw_order(particles, RS::ParticlesDrawOrder(p_order));
}
-void GPUParticles3D::set_enable_trail(bool p_enabled) {
+void GPUParticles3D::set_trail_enabled(bool p_enabled) {
trail_enabled = p_enabled;
RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length);
update_configuration_warnings();
@@ -391,7 +391,7 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const {
}
}
-void GPUParticles3D::emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+void GPUParticles3D::emit_particle(const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
RS::get_singleton()->particles_emit(particles, p_transform, p_velocity, p_color, p_custom, p_emit_flags);
}
@@ -458,7 +458,7 @@ void GPUParticles3D::_notification(int p_what) {
}
void GPUParticles3D::_skinning_changed() {
- Vector<Transform> xforms;
+ Vector<Transform3D> xforms;
if (skin.is_valid()) {
xforms.resize(skin->get_bind_count());
for (int i = 0; i < skin->get_bind_count(); i++) {
@@ -552,7 +552,7 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle);
- ClassDB::bind_method(D_METHOD("set_enable_trail", "enabled"), &GPUParticles3D::set_enable_trail);
+ ClassDB::bind_method(D_METHOD("set_trail_enabled", "enabled"), &GPUParticles3D::set_trail_enabled);
ClassDB::bind_method(D_METHOD("set_trail_length", "secs"), &GPUParticles3D::set_trail_length);
ClassDB::bind_method(D_METHOD("is_trail_enabled"), &GPUParticles3D::is_trail_enabled);
@@ -579,11 +579,11 @@ void GPUParticles3D::_bind_methods() {
ADD_GROUP("Drawing", "");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,Reverse Lifetime,View Depth"), "set_draw_order", "get_draw_order");
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_align", PROPERTY_HINT_ENUM, "Disabled,ZBillboard,YToVelocity,ZBillboardYToVelocity"), "set_transform_align", "get_transform_align");
ADD_GROUP("Trails", "trail_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_enable_trail", "is_trail_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,4,0.01"), "set_trail_length", "get_trail_length");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_trail_enabled", "is_trail_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_trail_length", "get_trail_length");
ADD_GROUP("Process Material", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material");
ADD_GROUP("Draw Passes", "draw_");
@@ -595,6 +595,7 @@ void GPUParticles3D::_bind_methods() {
BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX);
BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME);
+ BIND_ENUM_CONSTANT(DRAW_ORDER_REVERSE_LIFETIME);
BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH);
BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION);
@@ -632,7 +633,7 @@ GPUParticles3D::GPUParticles3D() {
set_draw_passes(1);
set_draw_order(DRAW_ORDER_INDEX);
set_speed_scale(1);
- set_collision_base_size(0.01);
+ set_collision_base_size(collision_base_size);
set_transform_align(TRANSFORM_ALIGN_DISABLED);
}
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index 1f9cea79b6..7b21cf03f1 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -44,6 +44,7 @@ public:
enum DrawOrder {
DRAW_ORDER_INDEX,
DRAW_ORDER_LIFETIME,
+ DRAW_ORDER_REVERSE_LIFETIME,
DRAW_ORDER_VIEW_DEPTH,
};
@@ -74,7 +75,7 @@ private:
bool fractional_delta;
bool interpolate = true;
NodePath sub_emitter;
- float collision_base_size;
+ float collision_base_size = 0.01;
bool trail_enabled = false;
float trail_length = 0.3;
@@ -113,7 +114,7 @@ public:
void set_process_material(const Ref<Material> &p_material);
void set_speed_scale(float p_scale);
void set_collision_base_size(float p_ratio);
- void set_enable_trail(bool p_enabled);
+ void set_trail_enabled(bool p_enabled);
void set_trail_length(float p_seconds);
bool is_emitting() const;
@@ -170,7 +171,7 @@ public:
EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM
};
- void emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
+ void emit_particle(const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
AABB capture_aabb() const;
GPUParticles3D();
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index 628b823f89..322bc60fce 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -131,7 +131,7 @@ void GPUParticlesCollisionSDF::_find_meshes(const AABB &p_aabb, Node *p_at_node,
if (mesh.is_valid()) {
AABB aabb = mesh->get_aabb();
- Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform();
+ Transform3D xf = get_global_transform().affine_inverse() * mi->get_global_transform();
if (p_aabb.intersects(xf.xform(aabb))) {
PlotMesh pm;
@@ -147,7 +147,7 @@ void GPUParticlesCollisionSDF::_find_meshes(const AABB &p_aabb, Node *p_at_node,
if (s->is_visible_in_tree()) {
Array meshes = p_at_node->call("get_meshes");
for (int i = 0; i < meshes.size(); i += 2) {
- Transform mxf = meshes[i];
+ Transform3D mxf = meshes[i];
Ref<Mesh> mesh = meshes[i + 1];
if (!mesh.is_valid()) {
continue;
@@ -155,7 +155,7 @@ void GPUParticlesCollisionSDF::_find_meshes(const AABB &p_aabb, Node *p_at_node,
AABB aabb = mesh->get_aabb();
- Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf);
+ Transform3D xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf);
if (p_aabb.intersects(xf.xform(aabb))) {
PlotMesh pm;
@@ -598,14 +598,14 @@ void GPUParticlesCollisionHeightField::_notification(int p_what) {
if (follow_camera_mode && get_viewport()) {
Camera3D *cam = get_viewport()->get_camera();
if (cam) {
- Transform xform = get_global_transform();
+ Transform3D xform = get_global_transform();
Vector3 x_axis = xform.basis.get_axis(Vector3::AXIS_X).normalized();
Vector3 z_axis = xform.basis.get_axis(Vector3::AXIS_Z).normalized();
float x_len = xform.basis.get_scale().x;
float z_len = xform.basis.get_scale().z;
Vector3 cam_pos = cam->get_global_transform().origin;
- Transform new_xform = xform;
+ Transform3D new_xform = xform;
while (x_axis.dot(cam_pos - new_xform.origin) > x_len) {
new_xform.origin += x_axis * x_len;
@@ -653,7 +653,7 @@ void GPUParticlesCollisionHeightField::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096,8192"), "set_resolution", "get_resolution");
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "WhenMoved,Always"), "set_update_mode", "get_update_mode");
- ADD_GROUP("Folow Camera", "follow_camera_");
+ ADD_GROUP("Follow Camera", "follow_camera_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_camera_enabled"), "set_follow_camera_mode", "is_follow_camera_mode_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "follow_camera_push_ratio", PROPERTY_HINT_RANGE, "0.01,1,0.01"), "set_follow_camera_push_ratio", "get_follow_camera_push_ratio");
diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h
index 81c33663f3..c55463378d 100644
--- a/scene/3d/gpu_particles_collision_3d.h
+++ b/scene/3d/gpu_particles_collision_3d.h
@@ -119,7 +119,7 @@ private:
struct PlotMesh {
Ref<Mesh> mesh;
- Transform local_xform;
+ Transform3D local_xform;
};
void _find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes);
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
new file mode 100644
index 0000000000..a3f681e53c
--- /dev/null
+++ b/scene/3d/lightmap_gi.cpp
@@ -0,0 +1,1466 @@
+/*************************************************************************/
+/* lightmap_gi.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "lightmap_gi.h"
+
+#include "core/io/config_file.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
+#include "core/io/resource_saver.h"
+#include "core/math/camera_matrix.h"
+#include "core/math/delaunay_3d.h"
+#include "core/os/os.h"
+#include "core/templates/sort_array.h"
+#include "lightmap_probe.h"
+
+void LightmapGIData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) {
+ User user;
+ user.path = p_path;
+ user.uv_scale = p_uv_scale;
+ user.slice_index = p_slice_index;
+ user.sub_instance = p_sub_instance;
+ users.push_back(user);
+}
+
+int LightmapGIData::get_user_count() const {
+ return users.size();
+}
+
+NodePath LightmapGIData::get_user_path(int p_user) const {
+ ERR_FAIL_INDEX_V(p_user, users.size(), NodePath());
+ return users[p_user].path;
+}
+
+int32_t LightmapGIData::get_user_sub_instance(int p_user) const {
+ ERR_FAIL_INDEX_V(p_user, users.size(), -1);
+ return users[p_user].sub_instance;
+}
+
+Rect2 LightmapGIData::get_user_lightmap_uv_scale(int p_user) const {
+ ERR_FAIL_INDEX_V(p_user, users.size(), Rect2());
+ return users[p_user].uv_scale;
+}
+
+int LightmapGIData::get_user_lightmap_slice_index(int p_user) const {
+ ERR_FAIL_INDEX_V(p_user, users.size(), -1);
+ return users[p_user].slice_index;
+}
+
+void LightmapGIData::clear_users() {
+ users.clear();
+}
+
+void LightmapGIData::_set_user_data(const Array &p_data) {
+ ERR_FAIL_COND(p_data.size() <= 0);
+ ERR_FAIL_COND((p_data.size() % 4) != 0);
+
+ for (int i = 0; i < p_data.size(); i += 4) {
+ add_user(p_data[i + 0], p_data[i + 1], p_data[i + 2], p_data[i + 3]);
+ }
+}
+
+Array LightmapGIData::_get_user_data() const {
+ Array ret;
+ for (int i = 0; i < users.size(); i++) {
+ ret.push_back(users[i].path);
+ ret.push_back(users[i].uv_scale);
+ ret.push_back(users[i].slice_index);
+ ret.push_back(users[i].sub_instance);
+ }
+ return ret;
+}
+
+RID LightmapGIData::get_rid() const {
+ return lightmap;
+}
+
+void LightmapGIData::clear() {
+ users.clear();
+}
+
+void LightmapGIData::set_light_texture(const Ref<TextureLayered> &p_light_texture) {
+ light_texture = p_light_texture;
+ RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics);
+}
+
+Ref<TextureLayered> LightmapGIData::get_light_texture() const {
+ return light_texture;
+}
+
+void LightmapGIData::set_uses_spherical_harmonics(bool p_enable) {
+ uses_spherical_harmonics = p_enable;
+ RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics);
+}
+
+bool LightmapGIData::is_using_spherical_harmonics() const {
+ return uses_spherical_harmonics;
+}
+
+void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
+ if (p_points.size()) {
+ int pc = p_points.size();
+ ERR_FAIL_COND(pc * 9 != p_point_sh.size());
+ ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
+ ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
+ RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, p_points, p_point_sh, p_tetrahedra, p_bsp_tree);
+ RS::get_singleton()->lightmap_set_probe_bounds(lightmap, p_bounds);
+ RS::get_singleton()->lightmap_set_probe_interior(lightmap, p_interior);
+ } else {
+ RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, PackedVector3Array(), PackedColorArray(), PackedInt32Array(), PackedInt32Array());
+ RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB());
+ RS::get_singleton()->lightmap_set_probe_interior(lightmap, false);
+ }
+ interior = p_interior;
+ bounds = p_bounds;
+}
+
+PackedVector3Array LightmapGIData::get_capture_points() const {
+ return RS::get_singleton()->lightmap_get_probe_capture_points(lightmap);
+}
+
+PackedColorArray LightmapGIData::get_capture_sh() const {
+ return RS::get_singleton()->lightmap_get_probe_capture_sh(lightmap);
+}
+
+PackedInt32Array LightmapGIData::get_capture_tetrahedra() const {
+ return RS::get_singleton()->lightmap_get_probe_capture_tetrahedra(lightmap);
+}
+
+PackedInt32Array LightmapGIData::get_capture_bsp_tree() const {
+ return RS::get_singleton()->lightmap_get_probe_capture_bsp_tree(lightmap);
+}
+
+AABB LightmapGIData::get_capture_bounds() const {
+ return bounds;
+}
+
+bool LightmapGIData::is_interior() const {
+ return interior;
+}
+
+void LightmapGIData::_set_probe_data(const Dictionary &p_data) {
+ ERR_FAIL_COND(!p_data.has("bounds"));
+ ERR_FAIL_COND(!p_data.has("points"));
+ ERR_FAIL_COND(!p_data.has("tetrahedra"));
+ ERR_FAIL_COND(!p_data.has("bsp"));
+ ERR_FAIL_COND(!p_data.has("sh"));
+ ERR_FAIL_COND(!p_data.has("interior"));
+ set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]);
+}
+
+Dictionary LightmapGIData::_get_probe_data() const {
+ Dictionary d;
+ d["bounds"] = get_capture_bounds();
+ d["points"] = get_capture_points();
+ d["tetrahedra"] = get_capture_tetrahedra();
+ d["bsp"] = get_capture_bsp_tree();
+ d["sh"] = get_capture_sh();
+ d["interior"] = is_interior();
+ return d;
+}
+
+void LightmapGIData::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &LightmapGIData::_set_user_data);
+ ClassDB::bind_method(D_METHOD("_get_user_data"), &LightmapGIData::_get_user_data);
+
+ ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &LightmapGIData::set_light_texture);
+ ClassDB::bind_method(D_METHOD("get_light_texture"), &LightmapGIData::get_light_texture);
+
+ ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &LightmapGIData::set_uses_spherical_harmonics);
+ ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &LightmapGIData::is_using_spherical_harmonics);
+
+ ClassDB::bind_method(D_METHOD("add_user", "path", "uv_scale", "slice_index", "sub_instance"), &LightmapGIData::add_user);
+ ClassDB::bind_method(D_METHOD("get_user_count"), &LightmapGIData::get_user_count);
+ ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &LightmapGIData::get_user_path);
+ ClassDB::bind_method(D_METHOD("clear_users"), &LightmapGIData::clear_users);
+
+ ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data);
+ ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered"), "set_light_texture", "get_light_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data");
+}
+
+LightmapGIData::LightmapGIData() {
+ lightmap = RS::get_singleton()->lightmap_create();
+}
+
+LightmapGIData::~LightmapGIData() {
+ RS::get_singleton()->free(lightmap);
+}
+
+///////////////////////////
+
+void LightmapGI::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes) {
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
+ if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) {
+ Ref<Mesh> mesh = mi->get_mesh();
+ if (mesh.is_valid()) {
+ bool all_have_uv2_and_normal = true;
+ bool surfaces_found = false;
+ for (int i = 0; i < mesh->get_surface_count(); i++) {
+ if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
+ continue;
+ }
+ if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) {
+ all_have_uv2_and_normal = false;
+ break;
+ }
+ if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_NORMAL)) {
+ all_have_uv2_and_normal = false;
+ break;
+ }
+ surfaces_found = true;
+ }
+
+ if (surfaces_found && all_have_uv2_and_normal) {
+ //READY TO BAKE! size hint could be computed if not found, actually..
+
+ MeshesFound mf;
+ mf.xform = get_global_transform().affine_inverse() * mi->get_global_transform();
+ mf.node_path = get_path_to(mi);
+ mf.subindex = -1;
+ mf.mesh = mesh;
+
+ static const int lightmap_scale[GeometryInstance3D::LIGHTMAP_SCALE_MAX] = { 1, 2, 4, 8 };
+ mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()];
+
+ Ref<Material> all_override = mi->get_material_override();
+ for (int i = 0; i < mesh->get_surface_count(); i++) {
+ if (all_override.is_valid()) {
+ mf.overrides.push_back(all_override);
+ } else {
+ mf.overrides.push_back(mi->get_surface_override_material(i));
+ }
+ }
+
+ meshes.push_back(mf);
+ }
+ }
+ }
+
+ Node3D *s = Object::cast_to<Node3D>(p_at_node);
+
+ if (!mi && s) {
+ Array bmeshes = p_at_node->call("get_bake_bmeshes");
+ if (bmeshes.size() && (bmeshes.size() & 1) == 0) {
+ Transform3D xf = get_global_transform().affine_inverse() * s->get_global_transform();
+ for (int i = 0; i < bmeshes.size(); i += 2) {
+ Ref<Mesh> mesh = bmeshes[i];
+ if (!mesh.is_valid()) {
+ continue;
+ }
+
+ MeshesFound mf;
+
+ Transform3D mesh_xf = bmeshes[i + 1];
+ mf.xform = xf * mesh_xf;
+ mf.node_path = get_path_to(s);
+ mf.subindex = i / 2;
+ mf.lightmap_scale = 1;
+ mf.mesh = mesh;
+
+ meshes.push_back(mf);
+ }
+ }
+ }
+
+ Light3D *light = Object::cast_to<Light3D>(p_at_node);
+
+ if (light && light->get_bake_mode() != Light3D::BAKE_DISABLED) {
+ LightsFound lf;
+ lf.xform = get_global_transform().affine_inverse() * light->get_global_transform();
+ lf.light = light;
+ lights.push_back(lf);
+ }
+
+ LightmapProbe *probe = Object::cast_to<LightmapProbe>(p_at_node);
+
+ if (probe) {
+ Transform3D xf = get_global_transform().affine_inverse() * probe->get_global_transform();
+ probes.push_back(xf.origin);
+ }
+
+ for (int i = 0; i < p_at_node->get_child_count(); i++) {
+ Node *child = p_at_node->get_child(i);
+ if (!child->get_owner()) {
+ continue; //maybe a helper
+ }
+
+ _find_meshes_and_lights(child, meshes, lights, probes);
+ }
+}
+
+int LightmapGI::_bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const {
+ int over = 0;
+ int under = 0;
+ int coplanar = 0;
+ const BSPSimplex &s = p_simplices[p_simplex];
+ for (int i = 0; i < 4; i++) {
+ const Vector3 v = p_points[s.vertices[i]];
+ if (p_plane.has_point(v)) { //coplanar
+ coplanar++;
+ } else if (p_plane.is_point_over(v)) {
+ over++;
+ } else {
+ under++;
+ }
+ }
+
+ ERR_FAIL_COND_V(under == 0 && over == 0, -2); //should never happen, we discarded flat simplices before, but in any case drop it from the bsp tree and throw an error
+ if (under == 0) {
+ return 1; // all over
+ } else if (over == 0) {
+ return -1; // all under
+ } else {
+ return 0; // crossing
+ }
+}
+
+//#define DEBUG_BSP
+
+int32_t LightmapGI::_compute_bsp_tree(const Vector<Vector3> &p_points, const LocalVector<Plane> &p_planes, LocalVector<int32_t> &planes_tested, const LocalVector<BSPSimplex> &p_simplices, const LocalVector<int32_t> &p_simplex_indices, LocalVector<BSPNode> &bsp_nodes) {
+ //if we reach here, it means there is more than one simplex
+ int32_t node_index = (int32_t)bsp_nodes.size();
+ bsp_nodes.push_back(BSPNode());
+
+ //test with all the simplex planes
+ Plane best_plane;
+ float best_plane_score = -1.0;
+
+ for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
+ const BSPSimplex &s = p_simplices[p_simplex_indices[i]];
+ for (int j = 0; j < 4; j++) {
+ uint32_t plane_index = s.planes[j];
+ if (planes_tested[plane_index] == node_index) {
+ continue; //tested this plane already
+ }
+
+ planes_tested[plane_index] = node_index;
+
+ static const int face_order[4][3] = {
+ { 0, 1, 2 },
+ { 0, 2, 3 },
+ { 0, 1, 3 },
+ { 1, 2, 3 }
+ };
+
+ // despite getting rid of plane duplicates, we should still use here the actual plane to avoid numerical error
+ // from thinking this same simplex is intersecting rather than on a side
+ Vector3 v0 = p_points[s.vertices[face_order[j][0]]];
+ Vector3 v1 = p_points[s.vertices[face_order[j][1]]];
+ Vector3 v2 = p_points[s.vertices[face_order[j][2]]];
+
+ Plane plane(v0, v1, v2);
+
+ //test with all the simplices
+ int over_count = 0;
+ int under_count = 0;
+
+ for (uint32_t k = 0; k < p_simplex_indices.size(); k++) {
+ int side = _bsp_get_simplex_side(p_points, p_simplices, plane, p_simplex_indices[k]);
+ if (side == -2) {
+ continue; //this simplex is invalid, skip for now
+ } else if (side < 0) {
+ under_count++;
+ } else if (side > 0) {
+ over_count++;
+ }
+ }
+
+ if (under_count == 0 && over_count == 0) {
+ continue; //most likely precision issue with a flat simplex, do not try this plane
+ }
+
+ if (under_count > over_count) { //make sure under is always less than over, so we can compute the same ratio
+ SWAP(under_count, over_count);
+ }
+
+ float score = 0; //by default, score is 0 (worst)
+ if (over_count > 0) {
+ //give score mainly based on ratio (under / over), this means that this plane is splitting simplices a lot, but its balanced
+ score = float(under_count) / over_count;
+ }
+
+ //adjusting priority over least splits, probably not a great idea
+ //score *= Math::sqrt(float(over_count + under_count) / p_simplex_indices.size()); //also multiply score
+
+ if (score > best_plane_score) {
+ best_plane = plane;
+ best_plane_score = score;
+ }
+ }
+ }
+
+ LocalVector<int32_t> indices_over;
+ LocalVector<int32_t> indices_under;
+
+ //split again, but add to list
+ for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
+ uint32_t index = p_simplex_indices[i];
+ int side = _bsp_get_simplex_side(p_points, p_simplices, best_plane, index);
+
+ if (side == -2) {
+ continue; //simplex sits on the plane, does not make sense to use it
+ }
+ if (side <= 0) {
+ indices_under.push_back(index);
+ }
+
+ if (side >= 0) {
+ indices_over.push_back(index);
+ }
+ }
+
+#ifdef DEBUG_BSP
+ print_line("node " + itos(node_index) + " found plane: " + best_plane + " score:" + rtos(best_plane_score) + " - over " + itos(indices_over.size()) + " under " + itos(indices_under.size()) + " intersecting " + itos(intersecting));
+#endif
+
+ if (best_plane_score < 0.0 || indices_over.size() == p_simplex_indices.size() || indices_under.size() == p_simplex_indices.size()) {
+ ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug
+
+ // Failed to separate the tetrahedrons using planes
+ // this means Delaunay broke at some point.
+ // Luckily, because we are using tetrahedrons, we can resort to
+ // less precise but still working ways to generate the separating plane
+ // this will most likely look bad when interpolating, but at least it will not crash.
+ // and the arctifact will most likely also be very small, so too difficult to notice.
+
+ //find the longest axis
+
+ WARN_PRINT("Inconsistency found in triangulation while building BSP, probe interpolation quality may degrade a bit.");
+
+ LocalVector<Vector3> centers;
+ AABB bounds_all;
+ for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
+ AABB bounds;
+ for (uint32_t j = 0; j < 4; j++) {
+ Vector3 p = p_points[p_simplices[p_simplex_indices[i]].vertices[j]];
+ if (j == 0) {
+ bounds.position = p;
+ } else {
+ bounds.expand_to(p);
+ }
+ }
+ if (i == 0) {
+ centers.push_back(bounds.position + bounds.size * 0.5);
+ } else {
+ bounds_all.merge_with(bounds);
+ }
+ }
+ Vector3::Axis longest_axis = Vector3::Axis(bounds_all.get_longest_axis_index());
+
+ //find the simplex that will go under
+ uint32_t min_d_idx = 0xFFFFFFFF;
+ float min_d_dist = 1e20;
+
+ for (uint32_t i = 0; i < centers.size(); i++) {
+ if (centers[i][longest_axis] < min_d_dist) {
+ min_d_idx = i;
+ min_d_dist = centers[i][longest_axis];
+ }
+ }
+ //rebuild best_plane and over/under arrays
+ best_plane = Plane();
+ best_plane.normal[longest_axis] = 1.0;
+ best_plane.d = min_d_dist;
+
+ indices_under.clear();
+ indices_under.push_back(min_d_idx);
+
+ indices_over.clear();
+
+ for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
+ if (i == min_d_idx) {
+ continue;
+ }
+ indices_over.push_back(p_simplex_indices[i]);
+ }
+ }
+
+ BSPNode node;
+ node.plane = best_plane;
+
+ if (indices_under.size() == 0) {
+ //nothing to do here
+ node.under = BSPNode::EMPTY_LEAF;
+ } else if (indices_under.size() == 1) {
+ node.under = -(indices_under[0] + 1);
+ } else {
+ node.under = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_under, bsp_nodes);
+ }
+
+ if (indices_over.size() == 0) {
+ //nothing to do here
+ node.over = BSPNode::EMPTY_LEAF;
+ } else if (indices_over.size() == 1) {
+ node.over = -(indices_over[0] + 1);
+ } else {
+ node.over = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_over, bsp_nodes);
+ }
+
+ bsp_nodes[node_index] = node;
+
+ return node_index;
+}
+
+bool LightmapGI::_lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh) {
+ BakeStepUD *bsud = (BakeStepUD *)ud;
+ bool ret = false;
+ if (bsud->func) {
+ ret = bsud->func(bsud->from_percent + p_completion * (bsud->to_percent - bsud->from_percent), p_text, bsud->ud, p_refresh);
+ }
+ return ret;
+}
+
+void LightmapGI::_plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle) {
+ for (int i = 0; i < 8; i++) {
+ Vector3i pos = p_cell->offset;
+ uint32_t half_size = p_cell->size / 2;
+ if (i & 1) {
+ pos.x += half_size;
+ }
+ if (i & 2) {
+ pos.y += half_size;
+ }
+ if (i & 4) {
+ pos.z += half_size;
+ }
+
+ AABB subcell;
+ subcell.position = Vector3(pos) * p_cell_size;
+ subcell.size = Vector3(half_size, half_size, half_size) * p_cell_size;
+
+ if (!Geometry3D::triangle_box_overlap(subcell.position + subcell.size * 0.5, subcell.size * 0.5, p_triangle)) {
+ continue;
+ }
+
+ if (p_cell->children[i] == nullptr) {
+ GenProbesOctree *child = memnew(GenProbesOctree);
+ child->offset = pos;
+ child->size = half_size;
+ p_cell->children[i] = child;
+ }
+
+ if (half_size > 1) {
+ //still levels missing
+ _plot_triangle_into_octree(p_cell->children[i], p_cell_size, p_triangle);
+ }
+ }
+}
+
+void LightmapGI::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector<Vector3> &probe_positions, LocalVector<Vector3> &new_probe_positions, HashMap<Vector3i, bool, Vector3iHash> &positions_used, const AABB &p_bounds) {
+ for (int i = 0; i < 8; i++) {
+ Vector3i pos = p_cell->offset;
+ if (i & 1) {
+ pos.x += p_cell->size;
+ }
+ if (i & 2) {
+ pos.y += p_cell->size;
+ }
+ if (i & 4) {
+ pos.z += p_cell->size;
+ }
+
+ if (p_cell->size == 1 && !positions_used.has(pos)) {
+ //new position to insert!
+ Vector3 real_pos = p_bounds.position + Vector3(pos) * p_cell_size;
+ //see if a user submitted probe is too close
+ int ppcount = probe_positions.size();
+ const Vector3 *pp = probe_positions.ptr();
+ bool exists = false;
+ for (int j = 0; j < ppcount; j++) {
+ if (pp[j].distance_to(real_pos) < CMP_EPSILON) {
+ exists = true;
+ break;
+ }
+ }
+
+ if (!exists) {
+ new_probe_positions.push_back(real_pos);
+ }
+
+ positions_used[pos] = true;
+ }
+
+ if (p_cell->children[i] != nullptr) {
+ _gen_new_positions_from_octree(p_cell->children[i], p_cell_size, probe_positions, new_probe_positions, positions_used, p_bounds);
+ }
+ }
+}
+
+LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) {
+ if (p_image_data_path == "") {
+ if (get_light_data().is_null()) {
+ return BAKE_ERROR_NO_SAVE_PATH;
+ }
+
+ p_image_data_path = get_light_data()->get_path();
+ if (!p_image_data_path.is_resource_file()) {
+ return BAKE_ERROR_NO_SAVE_PATH;
+ }
+ }
+
+ Ref<Lightmapper> lightmapper = Lightmapper::create();
+ ERR_FAIL_COND_V(lightmapper.is_null(), BAKE_ERROR_NO_LIGHTMAPPER);
+
+ BakeStepUD bsud;
+ bsud.func = p_bake_step;
+ bsud.ud = p_bake_userdata;
+ bsud.from_percent = 0.2;
+ bsud.to_percent = 0.8;
+
+ if (p_bake_step) {
+ p_bake_step(0.0, TTR("Finding meshes, lights and probes"), p_bake_userdata, true);
+ }
+ /* STEP 1, FIND MESHES, LIGHTS AND PROBES */
+ Vector<Lightmapper::MeshData> mesh_data;
+ Vector<LightsFound> lights_found;
+ Vector<Vector3> probes_found;
+ AABB bounds;
+ {
+ Vector<MeshesFound> meshes_found;
+ _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), meshes_found, lights_found, probes_found);
+
+ if (meshes_found.size() == 0) {
+ return BAKE_ERROR_NO_MESHES;
+ }
+ // create mesh data for insert
+
+ //get the base material textures, help compute atlas size and bounds
+ for (int m_i = 0; m_i < meshes_found.size(); m_i++) {
+ if (p_bake_step) {
+ float p = (float)(m_i) / meshes_found.size();
+ p_bake_step(p * 0.1, vformat(TTR("Preparing geometry %d/%d"), m_i, meshes_found.size()), p_bake_userdata, false);
+ }
+
+ MeshesFound &mf = meshes_found.write[m_i];
+
+ Size2i lightmap_size = mf.mesh->get_lightmap_size_hint() * mf.lightmap_scale;
+ Vector<RID> overrides;
+ overrides.resize(mf.overrides.size());
+ for (int i = 0; i < mf.overrides.size(); i++) {
+ if (mf.overrides[i].is_valid()) {
+ overrides.write[i] = mf.overrides[i]->get_rid();
+ }
+ }
+ TypedArray<Image> images = RS::get_singleton()->bake_render_uv2(mf.mesh->get_rid(), overrides, lightmap_size);
+
+ ERR_FAIL_COND_V(images.is_empty(), BAKE_ERROR_CANT_CREATE_IMAGE);
+
+ Ref<Image> albedo = images[RS::BAKE_CHANNEL_ALBEDO_ALPHA];
+ Ref<Image> orm = images[RS::BAKE_CHANNEL_ORM];
+
+ //multiply albedo by metal
+
+ Lightmapper::MeshData md;
+
+ {
+ Dictionary d;
+ d["path"] = mf.node_path;
+ if (mf.subindex >= 0) {
+ d["subindex"] = mf.subindex;
+ }
+ md.userdata = d;
+ }
+
+ {
+ if (albedo->get_format() != Image::FORMAT_RGBA8) {
+ albedo->convert(Image::FORMAT_RGBA8);
+ }
+ if (orm->get_format() != Image::FORMAT_RGBA8) {
+ orm->convert(Image::FORMAT_RGBA8);
+ }
+ Vector<uint8_t> albedo_alpha = albedo->get_data();
+ Vector<uint8_t> orm_data = orm->get_data();
+
+ Vector<uint8_t> albedom;
+ uint32_t len = albedo_alpha.size();
+ albedom.resize(len);
+ const uint8_t *r_aa = albedo_alpha.ptr();
+ const uint8_t *r_orm = orm_data.ptr();
+ uint8_t *w_albedo = albedom.ptrw();
+
+ for (uint32_t i = 0; i < len; i += 4) {
+ w_albedo[i + 0] = uint8_t(CLAMP(float(r_aa[i + 0]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
+ w_albedo[i + 1] = uint8_t(CLAMP(float(r_aa[i + 1]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
+ w_albedo[i + 2] = uint8_t(CLAMP(float(r_aa[i + 2]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
+ w_albedo[i + 3] = 255;
+ }
+
+ md.albedo_on_uv2.instance();
+ md.albedo_on_uv2->create(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom);
+ }
+
+ md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION];
+ if (md.emission_on_uv2->get_format() != Image::FORMAT_RGBAH) {
+ md.emission_on_uv2->convert(Image::FORMAT_RGBAH);
+ }
+
+ //get geometry
+
+ Basis normal_xform = mf.xform.basis.inverse().transposed();
+
+ for (int i = 0; i < mf.mesh->get_surface_count(); i++) {
+ if (mf.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
+ continue;
+ }
+ Array a = mf.mesh->surface_get_arrays(i);
+
+ Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
+ const Vector3 *vr = vertices.ptr();
+ Vector<Vector2> uv = a[Mesh::ARRAY_TEX_UV2];
+ const Vector2 *uvr = nullptr;
+ Vector<Vector3> normals = a[Mesh::ARRAY_NORMAL];
+ const Vector3 *nr = nullptr;
+ Vector<int> index = a[Mesh::ARRAY_INDEX];
+
+ ERR_CONTINUE(uv.size() == 0);
+ ERR_CONTINUE(normals.size() == 0);
+
+ uvr = uv.ptr();
+ nr = normals.ptr();
+
+ int facecount;
+ const int *ir = nullptr;
+
+ if (index.size()) {
+ facecount = index.size() / 3;
+ ir = index.ptr();
+ } else {
+ facecount = vertices.size() / 3;
+ }
+
+ for (int j = 0; j < facecount; j++) {
+ uint32_t vidx[3];
+
+ if (ir) {
+ for (int k = 0; k < 3; k++) {
+ vidx[k] = ir[j * 3 + k];
+ }
+ } else {
+ for (int k = 0; k < 3; k++) {
+ vidx[k] = j * 3 + k;
+ }
+ }
+
+ for (int k = 0; k < 3; k++) {
+ Vector3 v = mf.xform.xform(vr[vidx[k]]);
+ if (bounds == AABB()) {
+ bounds.position = v;
+ } else {
+ bounds.expand_to(v);
+ }
+ md.points.push_back(v);
+
+ md.uv2.push_back(uvr[vidx[k]]);
+ md.normal.push_back(normal_xform.xform(nr[vidx[k]]).normalized());
+ }
+ }
+ }
+
+ mesh_data.push_back(md);
+ }
+ }
+
+ /* STEP 2, CREATE PROBES */
+
+ if (p_bake_step) {
+ p_bake_step(0.3, TTR("Creating probes"), p_bake_userdata, true);
+ }
+
+ //bounds need to include the user probes
+ for (int i = 0; i < probes_found.size(); i++) {
+ bounds.expand_to(probes_found[i]);
+ }
+
+ bounds.grow_by(bounds.size.length() * 0.001);
+
+ if (gen_probes == GENERATE_PROBES_DISABLED) {
+ // generate 8 probes on bound endpoints
+ for (int i = 0; i < 8; i++) {
+ probes_found.push_back(bounds.get_endpoint(i));
+ }
+ } else {
+ // detect probes from geometry
+ static const int subdiv_values[6] = { 0, 4, 8, 16, 32 };
+ int subdiv = subdiv_values[gen_probes];
+
+ float subdiv_cell_size;
+ Vector3i bound_limit;
+ {
+ int longest_axis = bounds.get_longest_axis_index();
+ subdiv_cell_size = bounds.size[longest_axis] / subdiv;
+ int axis_n1 = (longest_axis + 1) % 3;
+ int axis_n2 = (longest_axis + 2) % 3;
+
+ bound_limit[longest_axis] = subdiv;
+ bound_limit[axis_n1] = int(Math::ceil(bounds.size[axis_n1] / subdiv_cell_size));
+ bound_limit[axis_n2] = int(Math::ceil(bounds.size[axis_n2] / subdiv_cell_size));
+ //compensate bounds
+ bounds.size[axis_n1] = bound_limit[axis_n1] * subdiv_cell_size;
+ bounds.size[axis_n2] = bound_limit[axis_n2] * subdiv_cell_size;
+ }
+
+ GenProbesOctree octree;
+ octree.size = subdiv;
+
+ for (int i = 0; i < mesh_data.size(); i++) {
+ if (p_bake_step) {
+ float p = (float)(i) / mesh_data.size();
+ p_bake_step(0.3 + p * 0.1, vformat(TTR("Creating probes from mesh %d/%d"), i, mesh_data.size()), p_bake_userdata, false);
+ }
+
+ for (int j = 0; j < mesh_data[i].points.size(); j += 3) {
+ Vector3 points[3] = { mesh_data[i].points[j + 0] - bounds.position, mesh_data[i].points[j + 1] - bounds.position, mesh_data[i].points[j + 2] - bounds.position };
+ _plot_triangle_into_octree(&octree, subdiv_cell_size, points);
+ }
+ }
+
+ LocalVector<Vector3> new_probe_positions;
+ HashMap<Vector3i, bool, Vector3iHash> positions_used;
+ for (uint32_t i = 0; i < 8; i++) { //insert bounding endpoints
+ Vector3i pos;
+ if (i & 1) {
+ pos.x += bound_limit.x;
+ }
+ if (i & 2) {
+ pos.y += bound_limit.y;
+ }
+ if (i & 4) {
+ pos.z += bound_limit.z;
+ }
+
+ positions_used[pos] = true;
+ Vector3 real_pos = bounds.position + Vector3(pos) * subdiv_cell_size; //use same formula for numerical stability
+ new_probe_positions.push_back(real_pos);
+ }
+ //skip first level, since probes are always added at bounds endpoints anyway (code above this)
+ for (int i = 0; i < 8; i++) {
+ if (octree.children[i]) {
+ _gen_new_positions_from_octree(octree.children[i], subdiv_cell_size, probes_found, new_probe_positions, positions_used, bounds);
+ }
+ }
+
+ for (uint32_t i = 0; i < new_probe_positions.size(); i++) {
+ probes_found.push_back(new_probe_positions[i]);
+ }
+ }
+
+ // Add everything to lightmapper
+ if (p_bake_step) {
+ p_bake_step(0.4, TTR("Preparing Lightmapper"), p_bake_userdata, true);
+ }
+
+ {
+ for (int i = 0; i < mesh_data.size(); i++) {
+ lightmapper->add_mesh(mesh_data[i]);
+ }
+ for (int i = 0; i < lights_found.size(); i++) {
+ Light3D *light = lights_found[i].light;
+ Transform3D xf = lights_found[i].xform;
+
+ if (Object::cast_to<DirectionalLight3D>(light)) {
+ DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light);
+ lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE));
+ } else if (Object::cast_to<OmniLight3D>(light)) {
+ OmniLight3D *l = Object::cast_to<OmniLight3D>(light);
+ lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
+ } else if (Object::cast_to<SpotLight3D>(light)) {
+ SpotLight3D *l = Object::cast_to<SpotLight3D>(light);
+ lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE));
+ }
+ }
+ for (int i = 0; i < probes_found.size(); i++) {
+ lightmapper->add_probe(probes_found[i]);
+ }
+ }
+
+ Ref<Image> environment_image;
+ Basis environment_transform;
+
+ // Add everything to lightmapper
+ if (environment_mode != ENVIRONMENT_MODE_DISABLED) {
+ if (p_bake_step) {
+ p_bake_step(4.1, TTR("Preparing Environment"), p_bake_userdata, true);
+ }
+
+ environment_transform = get_global_transform().basis;
+
+ switch (environment_mode) {
+ case ENVIRONMENT_MODE_DISABLED: {
+ //nothing
+ } break;
+ case ENVIRONMENT_MODE_SCENE: {
+ Ref<World3D> world = get_world_3d();
+ if (world.is_valid()) {
+ Ref<Environment> env = world->get_environment();
+ if (env.is_null()) {
+ env = world->get_fallback_environment();
+ }
+
+ if (env.is_valid()) {
+ environment_image = RS::get_singleton()->environment_bake_panorama(env->get_rid(), true, Size2i(128, 64));
+ }
+ }
+ } break;
+ case ENVIRONMENT_MODE_CUSTOM_SKY: {
+ if (environment_custom_sky.is_valid()) {
+ environment_image = RS::get_singleton()->sky_bake_panorama(environment_custom_sky->get_rid(), environment_custom_energy, true, Size2i(128, 64));
+ }
+
+ } break;
+ case ENVIRONMENT_MODE_CUSTOM_COLOR: {
+ environment_image.instance();
+ environment_image->create(128, 64, false, Image::FORMAT_RGBAF);
+ Color c = environment_custom_color;
+ c.r *= environment_custom_energy;
+ c.g *= environment_custom_energy;
+ c.b *= environment_custom_energy;
+ for (int i = 0; i < 128; i++) {
+ for (int j = 0; j < 64; j++) {
+ environment_image->set_pixel(i, j, c);
+ }
+ }
+
+ } break;
+ }
+ }
+
+ Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud);
+
+ if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) {
+ return BAKE_ERROR_MESHES_INVALID;
+ }
+
+ /* POSTBAKE: Save Textures */
+
+ Ref<TextureLayered> texture;
+ {
+ Vector<Ref<Image>> images;
+ for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
+ images.push_back(lightmapper->get_bake_texture(i));
+ }
+ //we assume they are all the same, so let's create a large one for saving
+ Ref<Image> large_image;
+ large_image.instance();
+
+ large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format());
+
+ for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
+ large_image->blit_rect(images[i], Rect2(0, 0, images[i]->get_width(), images[i]->get_height()), Point2(0, images[i]->get_height() * i));
+ }
+
+ String base_path = p_image_data_path.get_basename() + ".exr";
+
+ Ref<ConfigFile> config;
+
+ config.instance();
+ if (FileAccess::exists(base_path + ".import")) {
+ config->load(base_path + ".import");
+ }
+
+ config->set_value("remap", "importer", "2d_array_texture");
+ config->set_value("remap", "type", "StreamTexture2DArray");
+ if (!config->has_section_key("params", "compress/mode")) {
+ config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be
+ }
+ config->set_value("params", "compress/channel_pack", 1);
+ config->set_value("params", "mipmaps/generate", false);
+ config->set_value("params", "slices/horizontal", 1);
+ config->set_value("params", "slices/vertical", images.size());
+
+ config->save(base_path + ".import");
+
+ Error err = large_image->save_exr(base_path, false);
+ ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE);
+ ResourceLoader::import(base_path);
+ Ref<Texture> t = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus?
+ ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE);
+ texture = t;
+ }
+
+ /* POSTBAKE: Save Light Data */
+
+ Ref<LightmapGIData> data;
+ if (get_light_data().is_valid()) {
+ data = get_light_data();
+ set_light_data(Ref<LightmapGIData>()); //clear
+ data->clear();
+ } else {
+ data.instance();
+ }
+
+ data->set_light_texture(texture);
+ data->set_uses_spherical_harmonics(directional);
+
+ for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
+ Dictionary d = lightmapper->get_bake_mesh_userdata(i);
+ NodePath np = d["path"];
+ int32_t subindex = -1;
+ if (d.has("subindex")) {
+ subindex = d["subindex"];
+ }
+
+ Rect2 uv_scale = lightmapper->get_bake_mesh_uv_scale(i);
+ int slice_index = lightmapper->get_bake_mesh_texture_slice(i);
+ data->add_user(np, uv_scale, slice_index, subindex);
+ }
+
+ {
+ // create tetrahedrons
+ Vector<Vector3> points;
+ Vector<Color> sh;
+ points.resize(lightmapper->get_bake_probe_count());
+ sh.resize(lightmapper->get_bake_probe_count() * 9);
+ for (int i = 0; i < lightmapper->get_bake_probe_count(); i++) {
+ points.write[i] = lightmapper->get_bake_probe_point(i);
+ Vector<Color> colors = lightmapper->get_bake_probe_sh(i);
+ ERR_CONTINUE(colors.size() != 9);
+ for (int j = 0; j < 9; j++) {
+ sh.write[i * 9 + j] = colors[j];
+ }
+ }
+
+ //Obtain solved simplices
+
+ if (p_bake_step) {
+ p_bake_step(0.8, TTR("Generating Probe Volumes"), p_bake_userdata, true);
+ }
+ Vector<Delaunay3D::OutputSimplex> solved_simplices = Delaunay3D::tetrahedralize(points);
+
+ LocalVector<BSPSimplex> bsp_simplices;
+ LocalVector<Plane> bsp_planes;
+ LocalVector<int32_t> bsp_simplex_indices;
+ PackedInt32Array tetrahedrons;
+
+ for (int i = 0; i < solved_simplices.size(); i++) {
+ //Prepare a special representation of the simplex, which uses a BSP Tree
+ BSPSimplex bsp_simplex;
+ for (int j = 0; j < 4; j++) {
+ bsp_simplex.vertices[j] = solved_simplices[i].points[j];
+ }
+ for (int j = 0; j < 4; j++) {
+ static const int face_order[4][3] = {
+ { 0, 1, 2 },
+ { 0, 2, 3 },
+ { 0, 1, 3 },
+ { 1, 2, 3 }
+ };
+ Vector3 a = points[solved_simplices[i].points[face_order[j][0]]];
+ Vector3 b = points[solved_simplices[i].points[face_order[j][1]]];
+ Vector3 c = points[solved_simplices[i].points[face_order[j][2]]];
+
+ //store planes in an array, but ensure they are reused, to speed up processing
+
+ Plane p(a, b, c);
+ int plane_index = -1;
+ for (uint32_t k = 0; k < bsp_planes.size(); k++) {
+ if (bsp_planes[k].is_equal_approx_any_side(p)) {
+ plane_index = k;
+ break;
+ }
+ }
+
+ if (plane_index == -1) {
+ plane_index = bsp_planes.size();
+ bsp_planes.push_back(p);
+ }
+
+ bsp_simplex.planes[j] = plane_index;
+
+ //also fill simplex array
+ tetrahedrons.push_back(solved_simplices[i].points[j]);
+ }
+
+ bsp_simplex_indices.push_back(bsp_simplices.size());
+ bsp_simplices.push_back(bsp_simplex);
+ }
+
+//#define DEBUG_SIMPLICES_AS_OBJ_FILE
+#ifdef DEBUG_SIMPLICES_AS_OBJ_FILE
+ {
+ FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE);
+ for (uint32_t i = 0; i < bsp_simplices.size(); i++) {
+ f->store_line("o Simplex" + itos(i));
+ for (int j = 0; j < 4; j++) {
+ f->store_line(vformat("v %f %f %f", points[bsp_simplices[i].vertices[j]].x, points[bsp_simplices[i].vertices[j]].y, points[bsp_simplices[i].vertices[j]].z));
+ }
+ static const int face_order[4][3] = {
+ { 1, 2, 3 },
+ { 1, 3, 4 },
+ { 1, 2, 4 },
+ { 2, 3, 4 }
+ };
+
+ for (int j = 0; j < 4; j++) {
+ f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2]));
+ }
+ }
+ f->close();
+ }
+#endif
+
+ LocalVector<BSPNode> bsp_nodes;
+ LocalVector<int32_t> planes_tested;
+ planes_tested.resize(bsp_planes.size());
+ for (uint32_t i = 0; i < planes_tested.size(); i++) {
+ planes_tested[i] = 0x7FFFFFFF;
+ }
+
+ if (p_bake_step) {
+ p_bake_step(0.9, TTR("Generating Probe Acceleration Structures"), p_bake_userdata, true);
+ }
+
+ _compute_bsp_tree(points, bsp_planes, planes_tested, bsp_simplices, bsp_simplex_indices, bsp_nodes);
+
+ PackedInt32Array bsp_array;
+ bsp_array.resize(bsp_nodes.size() * 6); // six 32 bits values used for each BSP node
+ {
+ float *fptr = (float *)bsp_array.ptrw();
+ int32_t *iptr = (int32_t *)bsp_array.ptrw();
+ for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
+ fptr[i * 6 + 0] = bsp_nodes[i].plane.normal.x;
+ fptr[i * 6 + 1] = bsp_nodes[i].plane.normal.y;
+ fptr[i * 6 + 2] = bsp_nodes[i].plane.normal.z;
+ fptr[i * 6 + 3] = bsp_nodes[i].plane.d;
+ iptr[i * 6 + 4] = bsp_nodes[i].over;
+ iptr[i * 6 + 5] = bsp_nodes[i].under;
+ }
+//#define DEBUG_BSP_TREE
+#ifdef DEBUG_BSP_TREE
+ FileAccessRef f = FileAccess::open("res://bsp.txt", FileAccess::WRITE);
+ for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
+ f->store_line(itos(i) + " - plane: " + bsp_nodes[i].plane + " over: " + itos(bsp_nodes[i].over) + " under: " + itos(bsp_nodes[i].under));
+ }
+#endif
+ }
+
+ /* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */
+
+ data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array);
+ /* Compute a BSP tree of the simplices, so it's easy to find the exact one */
+ }
+
+ Error err = ResourceSaver::save(p_image_data_path, data);
+ data->set_path(p_image_data_path);
+
+ if (err != OK) {
+ return BAKE_ERROR_CANT_CREATE_IMAGE;
+ }
+
+ set_light_data(data);
+
+ return BAKE_ERROR_OK;
+}
+
+void LightmapGI::_notification(int p_what) {
+ if (p_what == NOTIFICATION_POST_ENTER_TREE) {
+ if (light_data.is_valid()) {
+ _assign_lightmaps();
+ }
+ }
+
+ if (p_what == NOTIFICATION_EXIT_TREE) {
+ if (light_data.is_valid()) {
+ _clear_lightmaps();
+ }
+ }
+}
+
+void LightmapGI::_assign_lightmaps() {
+ ERR_FAIL_COND(!light_data.is_valid());
+
+ for (int i = 0; i < light_data->get_user_count(); i++) {
+ Node *node = get_node(light_data->get_user_path(i));
+ int instance_idx = light_data->get_user_sub_instance(i);
+ if (instance_idx >= 0) {
+ RID instance = node->call("get_bake_mesh_instance", instance_idx);
+ if (instance.is_valid()) {
+ RS::get_singleton()->instance_geometry_set_lightmap(instance, get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i));
+ }
+ } else {
+ VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(node);
+ ERR_CONTINUE(!vi);
+ RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i));
+ }
+ }
+}
+
+void LightmapGI::_clear_lightmaps() {
+ ERR_FAIL_COND(!light_data.is_valid());
+ for (int i = 0; i < light_data->get_user_count(); i++) {
+ Node *node = get_node(light_data->get_user_path(i));
+ int instance_idx = light_data->get_user_sub_instance(i);
+ if (instance_idx >= 0) {
+ RID instance = node->call("get_bake_mesh_instance", instance_idx);
+ if (instance.is_valid()) {
+ RS::get_singleton()->instance_geometry_set_lightmap(instance, RID(), Rect2(), 0);
+ }
+ } else {
+ VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(node);
+ ERR_CONTINUE(!vi);
+ RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), RID(), Rect2(), 0);
+ }
+ }
+}
+
+void LightmapGI::set_light_data(const Ref<LightmapGIData> &p_data) {
+ if (light_data.is_valid()) {
+ if (is_inside_tree()) {
+ _clear_lightmaps();
+ }
+ set_base(RID());
+ }
+ light_data = p_data;
+
+ if (light_data.is_valid()) {
+ set_base(light_data->get_rid());
+ if (is_inside_tree()) {
+ _assign_lightmaps();
+ }
+ }
+
+ update_gizmo();
+}
+
+Ref<LightmapGIData> LightmapGI::get_light_data() const {
+ return light_data;
+}
+
+void LightmapGI::set_bake_quality(BakeQuality p_quality) {
+ bake_quality = p_quality;
+}
+
+LightmapGI::BakeQuality LightmapGI::get_bake_quality() const {
+ return bake_quality;
+}
+
+AABB LightmapGI::get_aabb() const {
+ return AABB();
+}
+
+Vector<Face3> LightmapGI::get_faces(uint32_t p_usage_flags) const {
+ return Vector<Face3>();
+}
+
+void LightmapGI::set_use_denoiser(bool p_enable) {
+ use_denoiser = p_enable;
+}
+
+bool LightmapGI::is_using_denoiser() const {
+ return use_denoiser;
+}
+
+void LightmapGI::set_directional(bool p_enable) {
+ directional = p_enable;
+}
+
+bool LightmapGI::is_directional() const {
+ return directional;
+}
+
+void LightmapGI::set_interior(bool p_enable) {
+ interior = p_enable;
+}
+
+bool LightmapGI::is_interior() const {
+ return interior;
+}
+
+void LightmapGI::set_environment_mode(EnvironmentMode p_mode) {
+ environment_mode = p_mode;
+ notify_property_list_changed();
+}
+
+LightmapGI::EnvironmentMode LightmapGI::get_environment_mode() const {
+ return environment_mode;
+}
+
+void LightmapGI::set_environment_custom_sky(const Ref<Sky> &p_sky) {
+ environment_custom_sky = p_sky;
+}
+
+Ref<Sky> LightmapGI::get_environment_custom_sky() const {
+ return environment_custom_sky;
+}
+
+void LightmapGI::set_environment_custom_color(const Color &p_color) {
+ environment_custom_color = p_color;
+}
+
+Color LightmapGI::get_environment_custom_color() const {
+ return environment_custom_color;
+}
+
+void LightmapGI::set_environment_custom_energy(float p_energy) {
+ environment_custom_energy = p_energy;
+}
+
+float LightmapGI::get_environment_custom_energy() const {
+ return environment_custom_energy;
+}
+
+void LightmapGI::set_bounces(int p_bounces) {
+ ERR_FAIL_COND(p_bounces < 0 || p_bounces > 16);
+ bounces = p_bounces;
+}
+
+int LightmapGI::get_bounces() const {
+ return bounces;
+}
+
+void LightmapGI::set_bias(float p_bias) {
+ ERR_FAIL_COND(p_bias < 0.00001);
+ bias = p_bias;
+}
+
+float LightmapGI::get_bias() const {
+ return bias;
+}
+
+void LightmapGI::set_max_texture_size(int p_size) {
+ ERR_FAIL_COND(p_size < 2048);
+ max_texture_size = p_size;
+}
+
+int LightmapGI::get_max_texture_size() const {
+ return max_texture_size;
+}
+
+void LightmapGI::set_generate_probes(GenerateProbes p_generate_probes) {
+ gen_probes = p_generate_probes;
+}
+
+LightmapGI::GenerateProbes LightmapGI::get_generate_probes() const {
+ return gen_probes;
+}
+
+void LightmapGI::_validate_property(PropertyInfo &property) const {
+ if (property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
+ property.usage = 0;
+ }
+ if (property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) {
+ property.usage = 0;
+ }
+ if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
+ property.usage = 0;
+ }
+}
+
+void LightmapGI::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_light_data", "data"), &LightmapGI::set_light_data);
+ ClassDB::bind_method(D_METHOD("get_light_data"), &LightmapGI::get_light_data);
+
+ ClassDB::bind_method(D_METHOD("set_bake_quality", "bake_quality"), &LightmapGI::set_bake_quality);
+ ClassDB::bind_method(D_METHOD("get_bake_quality"), &LightmapGI::get_bake_quality);
+
+ ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &LightmapGI::set_bounces);
+ ClassDB::bind_method(D_METHOD("get_bounces"), &LightmapGI::get_bounces);
+
+ ClassDB::bind_method(D_METHOD("set_generate_probes", "subdivision"), &LightmapGI::set_generate_probes);
+ ClassDB::bind_method(D_METHOD("get_generate_probes"), &LightmapGI::get_generate_probes);
+
+ ClassDB::bind_method(D_METHOD("set_bias", "bias"), &LightmapGI::set_bias);
+ ClassDB::bind_method(D_METHOD("get_bias"), &LightmapGI::get_bias);
+
+ ClassDB::bind_method(D_METHOD("set_environment_mode", "mode"), &LightmapGI::set_environment_mode);
+ ClassDB::bind_method(D_METHOD("get_environment_mode"), &LightmapGI::get_environment_mode);
+
+ ClassDB::bind_method(D_METHOD("set_environment_custom_sky", "sky"), &LightmapGI::set_environment_custom_sky);
+ ClassDB::bind_method(D_METHOD("get_environment_custom_sky"), &LightmapGI::get_environment_custom_sky);
+
+ ClassDB::bind_method(D_METHOD("set_environment_custom_color", "color"), &LightmapGI::set_environment_custom_color);
+ ClassDB::bind_method(D_METHOD("get_environment_custom_color"), &LightmapGI::get_environment_custom_color);
+
+ ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &LightmapGI::set_environment_custom_energy);
+ ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &LightmapGI::get_environment_custom_energy);
+
+ ClassDB::bind_method(D_METHOD("set_max_texture_size", "max_texture_size"), &LightmapGI::set_max_texture_size);
+ ClassDB::bind_method(D_METHOD("get_max_texture_size"), &LightmapGI::get_max_texture_size);
+
+ ClassDB::bind_method(D_METHOD("set_use_denoiser", "use_denoiser"), &LightmapGI::set_use_denoiser);
+ ClassDB::bind_method(D_METHOD("is_using_denoiser"), &LightmapGI::is_using_denoiser);
+
+ ClassDB::bind_method(D_METHOD("set_interior", "enable"), &LightmapGI::set_interior);
+ ClassDB::bind_method(D_METHOD("is_interior"), &LightmapGI::is_interior);
+
+ ClassDB::bind_method(D_METHOD("set_directional", "directional"), &LightmapGI::set_directional);
+ ClassDB::bind_method(D_METHOD("is_directional"), &LightmapGI::is_directional);
+
+ // ClassDB::bind_method(D_METHOD("bake", "from_node"), &LightmapGI::bake, DEFVAL(Variant()));
+
+ ADD_GROUP("Tweaks", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,16,1"), "set_bounces", "get_bounces");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional"), "set_directional", "is_directional");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size"), "set_max_texture_size", "get_max_texture_size");
+ ADD_GROUP("Environment", "environment_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy");
+ ADD_GROUP("Gen Probes", "generate_probes_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes");
+ ADD_GROUP("Data", "");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "LightmapGIData"), "set_light_data", "get_light_data");
+
+ BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW);
+ BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM);
+ BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH);
+ BIND_ENUM_CONSTANT(BAKE_QUALITY_ULTRA);
+
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_DISABLED);
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_4);
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_8);
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_16);
+ BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_32);
+
+ BIND_ENUM_CONSTANT(BAKE_ERROR_OK);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_NO_LIGHTMAPPER);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_MESHES_INVALID);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED);
+
+ BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_SCENE);
+ BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_SKY);
+ BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_COLOR);
+}
+
+LightmapGI::LightmapGI() {
+}
diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h
new file mode 100644
index 0000000000..8a54512383
--- /dev/null
+++ b/scene/3d/lightmap_gi.h
@@ -0,0 +1,284 @@
+/*************************************************************************/
+/* lightmap_gi.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef LIGHTMAP_GI_H
+#define LIGHTMAP_GI_H
+
+#include "core/templates/local_vector.h"
+#include "scene/3d/light_3d.h"
+#include "scene/3d/lightmapper.h"
+#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/multimesh_instance_3d.h"
+#include "scene/3d/visual_instance_3d.h"
+#include "scene/resources/sky.h"
+
+class LightmapGIData : public Resource {
+ GDCLASS(LightmapGIData, Resource);
+ RES_BASE_EXTENSION("lmbake")
+
+ Ref<TextureLayered> light_texture;
+
+ bool uses_spherical_harmonics = false;
+ bool interior = false;
+
+ RID lightmap;
+ AABB bounds;
+
+ struct User {
+ NodePath path;
+ int32_t sub_instance = 0;
+ Rect2 uv_scale;
+ int slice_index = 0;
+ };
+
+ Vector<User> users;
+
+ void _set_user_data(const Array &p_data);
+ Array _get_user_data() const;
+ void _set_probe_data(const Dictionary &p_data);
+ Dictionary _get_probe_data() const;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance = -1);
+ int get_user_count() const;
+ NodePath get_user_path(int p_user) const;
+ int32_t get_user_sub_instance(int p_user) const;
+ Rect2 get_user_lightmap_uv_scale(int p_user) const;
+ int get_user_lightmap_slice_index(int p_user) const;
+ void clear_users();
+
+ void set_light_texture(const Ref<TextureLayered> &p_light_texture);
+ Ref<TextureLayered> get_light_texture() const;
+
+ void set_uses_spherical_harmonics(bool p_enable);
+ bool is_using_spherical_harmonics() const;
+
+ bool is_interior() const;
+
+ void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree);
+ PackedVector3Array get_capture_points() const;
+ PackedColorArray get_capture_sh() const;
+ PackedInt32Array get_capture_tetrahedra() const;
+ PackedInt32Array get_capture_bsp_tree() const;
+ AABB get_capture_bounds() const;
+
+ void clear();
+
+ virtual RID get_rid() const override;
+ LightmapGIData();
+ ~LightmapGIData();
+};
+
+class LightmapGI : public VisualInstance3D {
+ GDCLASS(LightmapGI, VisualInstance3D);
+
+public:
+ enum BakeQuality {
+ BAKE_QUALITY_LOW,
+ BAKE_QUALITY_MEDIUM,
+ BAKE_QUALITY_HIGH,
+ BAKE_QUALITY_ULTRA,
+ };
+
+ enum GenerateProbes {
+ GENERATE_PROBES_DISABLED,
+ GENERATE_PROBES_SUBDIV_4,
+ GENERATE_PROBES_SUBDIV_8,
+ GENERATE_PROBES_SUBDIV_16,
+ GENERATE_PROBES_SUBDIV_32,
+ };
+
+ enum BakeError {
+ BAKE_ERROR_OK,
+ BAKE_ERROR_NO_LIGHTMAPPER,
+ BAKE_ERROR_NO_SAVE_PATH,
+ BAKE_ERROR_NO_MESHES,
+ BAKE_ERROR_MESHES_INVALID,
+ BAKE_ERROR_CANT_CREATE_IMAGE,
+ BAKE_ERROR_USER_ABORTED,
+ };
+
+ enum EnvironmentMode {
+ ENVIRONMENT_MODE_DISABLED,
+ ENVIRONMENT_MODE_SCENE,
+ ENVIRONMENT_MODE_CUSTOM_SKY,
+ ENVIRONMENT_MODE_CUSTOM_COLOR,
+ };
+
+private:
+ BakeQuality bake_quality = BAKE_QUALITY_MEDIUM;
+ bool use_denoiser = true;
+ int bounces = 1;
+ float bias = 0.0005;
+ int max_texture_size = 16384;
+ bool interior = false;
+ EnvironmentMode environment_mode = ENVIRONMENT_MODE_DISABLED;
+ Ref<Sky> environment_custom_sky;
+ Color environment_custom_color = Color(0.2, 0.7, 1.0);
+ float environment_custom_energy = 1.0;
+ bool directional = false;
+ GenerateProbes gen_probes = GENERATE_PROBES_DISABLED;
+
+ Ref<LightmapGIData> light_data;
+
+ struct LightsFound {
+ Transform3D xform;
+ Light3D *light = nullptr;
+ };
+
+ struct MeshesFound {
+ Transform3D xform;
+ NodePath node_path;
+ int32_t subindex = 0;
+ Ref<Mesh> mesh;
+ int32_t lightmap_scale = 0;
+ Vector<Ref<Material>> overrides;
+ };
+
+ void _find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes);
+
+ void _assign_lightmaps();
+ void _clear_lightmaps();
+
+ struct BakeTimeData {
+ String text;
+ int pass = 0;
+ uint64_t last_step = 0;
+ };
+
+ struct BSPSimplex {
+ int vertices[4] = {};
+ int planes[4] = {};
+ };
+
+ struct BSPNode {
+ static const int32_t EMPTY_LEAF = INT32_MIN;
+ Plane plane;
+ int32_t over = EMPTY_LEAF;
+ int32_t under = EMPTY_LEAF;
+ };
+
+ int _bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const;
+ int32_t _compute_bsp_tree(const Vector<Vector3> &p_points, const LocalVector<Plane> &p_planes, LocalVector<int32_t> &planes_tested, const LocalVector<BSPSimplex> &p_simplices, const LocalVector<int32_t> &p_simplex_indices, LocalVector<BSPNode> &bsp_nodes);
+
+ struct BakeStepUD {
+ Lightmapper::BakeStepFunc func;
+ void *ud = nullptr;
+ float from_percent = 0.0;
+ float to_percent = 0.0;
+ };
+
+ static bool _lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh);
+
+ struct GenProbesOctree {
+ Vector3i offset;
+ uint32_t size = 0;
+ GenProbesOctree *children[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+ ~GenProbesOctree() {
+ for (int i = 0; i < 8; i++) {
+ if (children[i] != nullptr) {
+ memdelete(children[i]);
+ }
+ }
+ }
+ };
+
+ struct Vector3iHash {
+ _FORCE_INLINE_ static uint32_t hash(const Vector3i &p_vtx) {
+ uint32_t h = hash_djb2_one_32(p_vtx.x);
+ h = hash_djb2_one_32(p_vtx.y, h);
+ return hash_djb2_one_32(p_vtx.z, h);
+ }
+ };
+
+ void _plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle);
+ void _gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector<Vector3> &probe_positions, LocalVector<Vector3> &new_probe_positions, HashMap<Vector3i, bool, Vector3iHash> &positions_used, const AABB &p_bounds);
+
+protected:
+ void _validate_property(PropertyInfo &property) const override;
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ void set_light_data(const Ref<LightmapGIData> &p_data);
+ Ref<LightmapGIData> get_light_data() const;
+
+ void set_bake_quality(BakeQuality p_quality);
+ BakeQuality get_bake_quality() const;
+
+ void set_use_denoiser(bool p_enable);
+ bool is_using_denoiser() const;
+
+ void set_directional(bool p_enable);
+ bool is_directional() const;
+
+ void set_interior(bool p_interior);
+ bool is_interior() const;
+
+ void set_environment_mode(EnvironmentMode p_mode);
+ EnvironmentMode get_environment_mode() const;
+
+ void set_environment_custom_sky(const Ref<Sky> &p_sky);
+ Ref<Sky> get_environment_custom_sky() const;
+
+ void set_environment_custom_color(const Color &p_color);
+ Color get_environment_custom_color() const;
+
+ void set_environment_custom_energy(float p_energy);
+ float get_environment_custom_energy() const;
+
+ void set_bounces(int p_bounces);
+ int get_bounces() const;
+
+ void set_bias(float p_bias);
+ float get_bias() const;
+
+ void set_max_texture_size(int p_size);
+ int get_max_texture_size() const;
+
+ void set_generate_probes(GenerateProbes p_generate_probes);
+ GenerateProbes get_generate_probes() const;
+
+ AABB get_aabb() const override;
+ Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
+
+ BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr);
+ LightmapGI();
+};
+
+VARIANT_ENUM_CAST(LightmapGI::BakeQuality);
+VARIANT_ENUM_CAST(LightmapGI::GenerateProbes);
+VARIANT_ENUM_CAST(LightmapGI::BakeError);
+VARIANT_ENUM_CAST(LightmapGI::EnvironmentMode);
+
+#endif // BAKED_LIGHTMAP_H
diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h
index f63515f666..3a6a88d435 100644
--- a/scene/3d/lightmapper.h
+++ b/scene/3d/lightmapper.h
@@ -44,8 +44,8 @@
#endif
-class LightmapDenoiser : public Reference {
- GDCLASS(LightmapDenoiser, Reference)
+class LightmapDenoiser : public RefCounted {
+ GDCLASS(LightmapDenoiser, RefCounted)
protected:
static LightmapDenoiser *(*create_function)();
@@ -54,8 +54,8 @@ public:
static Ref<LightmapDenoiser> create();
};
-class LightmapRaycaster : public Reference {
- GDCLASS(LightmapRaycaster, Reference)
+class LightmapRaycaster : public RefCounted {
+ GDCLASS(LightmapRaycaster, RefCounted)
protected:
static LightmapRaycaster *(*create_function)();
@@ -121,8 +121,8 @@ public:
static Ref<LightmapRaycaster> create();
};
-class Lightmapper : public Reference {
- GDCLASS(Lightmapper, Reference)
+class Lightmapper : public RefCounted {
+ GDCLASS(Lightmapper, RefCounted)
public:
enum GenerateProbes {
GENERATE_PROBES_DISABLED,
diff --git a/scene/3d/listener_3d.cpp b/scene/3d/listener_3d.cpp
index 9842f152d7..636be083ab 100644
--- a/scene/3d/listener_3d.cpp
+++ b/scene/3d/listener_3d.cpp
@@ -105,7 +105,7 @@ void Listener3D::_notification(int p_what) {
}
}
-Transform Listener3D::get_listener_transform() const {
+Transform3D Listener3D::get_listener_transform() const {
return get_global_transform().orthonormalized();
}
diff --git a/scene/3d/listener_3d.h b/scene/3d/listener_3d.h
index 85657a8e53..bcc66f167c 100644
--- a/scene/3d/listener_3d.h
+++ b/scene/3d/listener_3d.h
@@ -65,7 +65,7 @@ public:
void clear_current();
bool is_current() const;
- virtual Transform get_listener_transform() const;
+ virtual Transform3D get_listener_transform() const;
void set_visible_layers(uint32_t p_layers);
uint32_t get_visible_layers() const;
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 27d5487a1a..c495f68890 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -427,7 +427,7 @@ void MeshInstance3D::create_debug_tangents() {
add_child(mi);
#ifdef TOOLS_ENABLED
- if (this == get_tree()->get_edited_scene_root()) {
+ if (is_inside_tree() && this == get_tree()->get_edited_scene_root()) {
mi->set_owner(this);
} else {
mi->set_owner(get_owner());
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index ba0f8cc870..e96b8ee1f9 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -32,6 +32,7 @@
#include "core/config/engine.h"
#include "core/object/message_queue.h"
+#include "scene/3d/visual_instance_3d.h"
#include "scene/main/scene_tree.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
@@ -148,6 +149,7 @@ void Node3D::_notification(int p_what) {
_notify_dirty();
notification(NOTIFICATION_ENTER_WORLD);
+ _update_visibility_parent(true);
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -161,6 +163,7 @@ void Node3D::_notification(int p_what) {
data.parent = nullptr;
data.C = nullptr;
data.top_level_active = false;
+ _update_visibility_parent(true);
} break;
case NOTIFICATION_ENTER_WORLD: {
data.inside_world = true;
@@ -223,7 +226,7 @@ void Node3D::_notification(int p_what) {
}
}
-void Node3D::set_transform(const Transform &p_transform) {
+void Node3D::set_transform(const Transform3D &p_transform) {
data.local_transform = p_transform;
data.dirty |= DIRTY_VECTORS;
_propagate_transform_changed(this);
@@ -232,8 +235,8 @@ void Node3D::set_transform(const Transform &p_transform) {
}
}
-void Node3D::set_global_transform(const Transform &p_transform) {
- Transform xform =
+void Node3D::set_global_transform(const Transform3D &p_transform) {
+ Transform3D xform =
(data.parent && !data.top_level_active) ?
data.parent->get_global_transform().affine_inverse() * p_transform :
p_transform;
@@ -241,16 +244,15 @@ void Node3D::set_global_transform(const Transform &p_transform) {
set_transform(xform);
}
-Transform Node3D::get_transform() const {
+Transform3D Node3D::get_transform() const {
if (data.dirty & DIRTY_LOCAL) {
_update_local_transform();
}
return data.local_transform;
}
-
-Transform Node3D::get_global_transform() const {
- ERR_FAIL_COND_V(!is_inside_tree(), Transform());
+Transform3D Node3D::get_global_transform() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), Transform3D());
if (data.dirty & DIRTY_GLOBAL) {
if (data.dirty & DIRTY_LOCAL) {
@@ -274,25 +276,28 @@ Transform Node3D::get_global_transform() const {
}
#ifdef TOOLS_ENABLED
-Transform Node3D::get_global_gizmo_transform() const {
+Transform3D Node3D::get_global_gizmo_transform() const {
return get_global_transform();
}
-Transform Node3D::get_local_gizmo_transform() const {
+Transform3D Node3D::get_local_gizmo_transform() const {
return get_transform();
}
#endif
-Node3D *Node3D::get_parent_spatial() const {
- return data.parent;
+Node3D *Node3D::get_parent_node_3d() const {
+ if (data.top_level) {
+ return nullptr;
+ }
+
+ return Object::cast_to<Node3D>(get_parent());
}
-Transform Node3D::get_relative_transform(const Node *p_parent) const {
- if (p_parent == this) {
- return Transform();
- }
+Transform3D Node3D::get_relative_transform(const Node *p_parent) const {
+ if (p_parent == this)
+ return Transform3D();
- ERR_FAIL_COND_V(!data.parent, Transform());
+ ERR_FAIL_COND_V(!data.parent, Transform3D());
if (p_parent == data.parent) {
return get_transform();
@@ -301,8 +306,8 @@ Transform Node3D::get_relative_transform(const Node *p_parent) const {
}
}
-void Node3D::set_translation(const Vector3 &p_translation) {
- data.local_transform.origin = p_translation;
+void Node3D::set_position(const Vector3 &p_position) {
+ data.local_transform.origin = p_position;
_propagate_transform_changed(this);
if (data.notify_local_transform) {
notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
@@ -341,7 +346,7 @@ void Node3D::set_scale(const Vector3 &p_scale) {
}
}
-Vector3 Node3D::get_translation() const {
+Vector3 Node3D::get_position() const {
return data.local_transform.origin;
}
@@ -557,87 +562,87 @@ bool Node3D::is_visible() const {
}
void Node3D::rotate_object_local(const Vector3 &p_axis, float p_angle) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.basis.rotate_local(p_axis, p_angle);
set_transform(t);
}
void Node3D::rotate(const Vector3 &p_axis, float p_angle) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.basis.rotate(p_axis, p_angle);
set_transform(t);
}
void Node3D::rotate_x(float p_angle) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.basis.rotate(Vector3(1, 0, 0), p_angle);
set_transform(t);
}
void Node3D::rotate_y(float p_angle) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.basis.rotate(Vector3(0, 1, 0), p_angle);
set_transform(t);
}
void Node3D::rotate_z(float p_angle) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.basis.rotate(Vector3(0, 0, 1), p_angle);
set_transform(t);
}
void Node3D::translate(const Vector3 &p_offset) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.translate(p_offset);
set_transform(t);
}
void Node3D::translate_object_local(const Vector3 &p_offset) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
- Transform s;
+ Transform3D s;
s.translate(p_offset);
set_transform(t * s);
}
void Node3D::scale(const Vector3 &p_ratio) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.basis.scale(p_ratio);
set_transform(t);
}
void Node3D::scale_object_local(const Vector3 &p_scale) {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.basis.scale_local(p_scale);
set_transform(t);
}
void Node3D::global_rotate(const Vector3 &p_axis, float p_angle) {
- Transform t = get_global_transform();
+ Transform3D t = get_global_transform();
t.basis.rotate(p_axis, p_angle);
set_global_transform(t);
}
void Node3D::global_scale(const Vector3 &p_scale) {
- Transform t = get_global_transform();
+ Transform3D t = get_global_transform();
t.basis.scale(p_scale);
set_global_transform(t);
}
void Node3D::global_translate(const Vector3 &p_offset) {
- Transform t = get_global_transform();
+ Transform3D t = get_global_transform();
t.origin += p_offset;
set_global_transform(t);
}
void Node3D::orthonormalize() {
- Transform t = get_transform();
+ Transform3D t = get_transform();
t.orthonormalize();
set_transform(t);
}
void Node3D::set_identity() {
- set_transform(Transform());
+ set_transform(Transform3D());
}
void Node3D::look_at(const Vector3 &p_target, const Vector3 &p_up) {
@@ -649,7 +654,7 @@ void Node3D::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target
ERR_FAIL_COND_MSG(p_pos == p_target, "Node origin and target are in the same position, look_at() failed.");
ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos) == Vector3(), "Up vector and direction between node origin and target are aligned, look_at() failed.");
- Transform lookat;
+ Transform3D lookat;
lookat.origin = p_pos;
Vector3 original_scale(get_scale());
@@ -692,11 +697,56 @@ void Node3D::force_update_transform() {
notification(NOTIFICATION_TRANSFORM_CHANGED);
}
+void Node3D::_update_visibility_parent(bool p_update_root) {
+ RID new_parent;
+
+ if (!visibility_parent_path.is_empty()) {
+ if (!p_update_root) {
+ return;
+ }
+ Node *parent = get_node_or_null(visibility_parent_path);
+ ERR_FAIL_COND_MSG(!parent, "Can't find visibility parent node at path: " + visibility_parent_path);
+ ERR_FAIL_COND_MSG(parent == this, "The visibility parent can't be the same node.");
+ GeometryInstance3D *gi = Object::cast_to<GeometryInstance3D>(parent);
+ ERR_FAIL_COND_MSG(!gi, "The visibility parent node must be a GeometryInstance3D, at path: " + visibility_parent_path);
+ new_parent = gi ? gi->get_instance() : RID();
+ } else if (data.parent) {
+ new_parent = data.parent->data.visibility_parent;
+ }
+
+ if (new_parent == data.visibility_parent) {
+ return;
+ }
+
+ data.visibility_parent = new_parent;
+
+ VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(this);
+ if (vi) {
+ RS::get_singleton()->instance_set_visibility_parent(vi->get_instance(), data.visibility_parent);
+ }
+
+ for (List<Node3D *>::Element *E = data.children.front(); E; E = E->next()) {
+ Node3D *c = E->get();
+ c->_update_visibility_parent(false);
+ }
+}
+
+void Node3D::set_visibility_parent(const NodePath &p_path) {
+ visibility_parent_path = p_path;
+ if (is_inside_tree()) {
+ _update_visibility_parent(true);
+ }
+}
+
+NodePath Node3D::get_visibility_parent() const {
+ return visibility_parent_path;
+}
+
void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "local"), &Node3D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &Node3D::get_transform);
- ClassDB::bind_method(D_METHOD("set_translation", "translation"), &Node3D::set_translation);
- ClassDB::bind_method(D_METHOD("get_translation"), &Node3D::get_translation);
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &Node3D::set_position);
+ ClassDB::bind_method(D_METHOD("get_position"), &Node3D::get_position);
ClassDB::bind_method(D_METHOD("set_rotation", "euler"), &Node3D::set_rotation);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node3D::get_rotation);
ClassDB::bind_method(D_METHOD("set_rotation_degrees", "euler_degrees"), &Node3D::set_rotation_degrees);
@@ -705,7 +755,7 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_scale"), &Node3D::get_scale);
ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Node3D::set_global_transform);
ClassDB::bind_method(D_METHOD("get_global_transform"), &Node3D::get_global_transform);
- ClassDB::bind_method(D_METHOD("get_parent_spatial"), &Node3D::get_parent_spatial);
+ ClassDB::bind_method(D_METHOD("get_parent_node_3d"), &Node3D::get_parent_node_3d);
ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Node3D::set_ignore_transform_notification);
ClassDB::bind_method(D_METHOD("set_as_top_level", "enable"), &Node3D::set_as_top_level);
ClassDB::bind_method(D_METHOD("is_set_as_top_level"), &Node3D::is_set_as_top_level);
@@ -715,6 +765,9 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_update_transform"), &Node3D::force_update_transform);
+ ClassDB::bind_method(D_METHOD("set_visibility_parent", "path"), &Node3D::set_visibility_parent);
+ ClassDB::bind_method(D_METHOD("get_visibility_parent"), &Node3D::get_visibility_parent);
+
ClassDB::bind_method(D_METHOD("_update_gizmo"), &Node3D::_update_gizmo);
ClassDB::bind_method(D_METHOD("update_gizmo"), &Node3D::update_gizmo);
@@ -758,18 +811,19 @@ void Node3D::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_EXIT_WORLD);
BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
- //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ;
+ //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM3D,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ;
ADD_GROUP("Transform", "");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_translation", "get_translation");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
ADD_GROUP("Matrix", "");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform");
ADD_GROUP("Visibility", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "visibility_parent", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GeometryInstance3D"), "set_visibility_parent", "get_visibility_parent");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "Node3DGizmo", 0), "set_gizmo", "get_gizmo");
ADD_SIGNAL(MethodInfo("visibility_changed"));
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index a62c7b31a8..c7e36cf2ec 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -34,8 +34,8 @@
#include "scene/main/node.h"
#include "scene/main/scene_tree.h"
-class Node3DGizmo : public Reference {
- GDCLASS(Node3DGizmo, Reference);
+class Node3DGizmo : public RefCounted {
+ GDCLASS(Node3DGizmo, RefCounted);
public:
virtual void create() = 0;
@@ -62,8 +62,8 @@ class Node3D : public Node {
mutable SelfList<Node> xform_change;
struct Data {
- mutable Transform global_transform;
- mutable Transform local_transform;
+ mutable Transform3D global_transform;
+ mutable Transform3D local_transform;
mutable Vector3 rotation;
mutable Vector3 scale = Vector3(1, 1, 1);
@@ -75,6 +75,8 @@ class Node3D : public Node {
bool top_level = false;
bool inside_world = false;
+ RID visibility_parent;
+
int children_lock = 0;
Node3D *parent = nullptr;
List<Node3D *> children;
@@ -95,12 +97,17 @@ class Node3D : public Node {
} data;
+ NodePath visibility_parent_path;
+
void _update_gizmo();
void _notify_dirty();
void _propagate_transform_changed(Node3D *p_origin);
void _propagate_visibility_changed();
+ void _propagate_visibility_parent();
+ void _update_visibility_parent(bool p_update_root);
+
protected:
_FORCE_INLINE_ void set_ignore_transform_notification(bool p_ignore) { data.ignore_notification = p_ignore; }
@@ -118,29 +125,29 @@ public:
NOTIFICATION_LOCAL_TRANSFORM_CHANGED = 44,
};
- Node3D *get_parent_spatial() const;
+ Node3D *get_parent_node_3d() const;
Ref<World3D> get_world_3d() const;
- void set_translation(const Vector3 &p_translation);
+ void set_position(const Vector3 &p_position);
void set_rotation(const Vector3 &p_euler_rad);
void set_rotation_degrees(const Vector3 &p_euler_deg);
void set_scale(const Vector3 &p_scale);
- Vector3 get_translation() const;
+ Vector3 get_position() const;
Vector3 get_rotation() const;
Vector3 get_rotation_degrees() const;
Vector3 get_scale() const;
- void set_transform(const Transform &p_transform);
- void set_global_transform(const Transform &p_transform);
+ void set_transform(const Transform3D &p_transform);
+ void set_global_transform(const Transform3D &p_transform);
- Transform get_transform() const;
- Transform get_global_transform() const;
+ Transform3D get_transform() const;
+ Transform3D get_global_transform() const;
#ifdef TOOLS_ENABLED
- virtual Transform get_global_gizmo_transform() const;
- virtual Transform get_local_gizmo_transform() const;
+ virtual Transform3D get_global_gizmo_transform() const;
+ virtual Transform3D get_local_gizmo_transform() const;
#endif
void set_as_top_level(bool p_enabled);
@@ -156,7 +163,7 @@ public:
_FORCE_INLINE_ bool is_inside_world() const { return data.inside_world; }
- Transform get_relative_transform(const Node *p_parent) const;
+ Transform3D get_relative_transform(const Node *p_parent) const;
void rotate(const Vector3 &p_axis, float p_angle);
void rotate_x(float p_angle);
@@ -196,6 +203,9 @@ public:
void force_update_transform();
+ void set_visibility_parent(const NodePath &p_path);
+ NodePath get_visibility_parent() const;
+
Node3D();
};
diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index d3a256db34..429e1d4b98 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -233,7 +233,7 @@ void OccluderInstance3D::_bake_node(Node *p_node, PackedVector3Array &r_vertices
}
if (valid) {
- Transform global_to_local = get_global_transform().affine_inverse() * mi->get_global_transform();
+ Transform3D global_to_local = get_global_transform().affine_inverse() * mi->get_global_transform();
for (int i = 0; i < mesh->get_surface_count(); i++) {
if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 4ec4ee6207..de115b35e3 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -108,7 +108,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
}
Vector3 pos = c->interpolate_baked(offset, cubic);
- Transform t = get_transform();
+ Transform3D t = get_transform();
// Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
// will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index dd1a797568..25c7c3d798 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -43,16 +43,35 @@
#include "editor/plugins/node_3d_editor_plugin.h"
#endif
-Vector3 PhysicsBody3D::get_linear_velocity() const {
- return Vector3();
+void PhysicsBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only", "safe_margin"), &PhysicsBody3D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false), DEFVAL(0.001));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "collision", "safe_margin"), &PhysicsBody3D::test_move, DEFVAL(true), DEFVAL(true), DEFVAL(Variant()), DEFVAL(0.001));
+
+ ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicsBody3D::set_axis_lock);
+ ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicsBody3D::get_axis_lock);
+
+ ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody3D::get_collision_exceptions);
+ ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody3D::add_collision_exception_with);
+ ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody3D::remove_collision_exception_with);
+
+ ADD_GROUP("Axis Lock", "axis_lock_");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Z);
}
-Vector3 PhysicsBody3D::get_angular_velocity() const {
- return Vector3();
+PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
+ CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) {
+ PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), p_mode);
}
-real_t PhysicsBody3D::get_inverse_mass() const {
- return 0;
+PhysicsBody3D::~PhysicsBody3D() {
+ if (motion_cache.is_valid()) {
+ motion_cache->owner = nullptr;
+ }
}
TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() {
@@ -83,11 +102,75 @@ void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid());
}
-void PhysicsBody3D::_bind_methods() {}
+Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only, real_t p_margin) {
+ PhysicsServer3D::MotionResult result;
+ if (move_and_collide(p_motion, p_infinite_inertia, result, p_margin, p_exclude_raycast_shapes, p_test_only)) {
+ if (motion_cache.is_null()) {
+ motion_cache.instance();
+ motion_cache->owner = this;
+ }
+
+ motion_cache->result = result;
-PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
- CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), p_mode);
+ return motion_cache;
+ }
+
+ return Ref<KinematicCollision3D>();
+}
+
+bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only) {
+ Transform3D gt = get_global_transform();
+ bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, p_margin, &r_result, p_exclude_raycast_shapes);
+
+ for (int i = 0; i < 3; i++) {
+ if (locked_axis & (1 << i)) {
+ r_result.motion[i] = 0;
+ }
+ }
+
+ if (!p_test_only) {
+ gt.origin += r_result.motion;
+ set_global_transform(gt);
+ }
+
+ return colliding;
+}
+
+bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, const Ref<KinematicCollision3D> &r_collision, real_t p_margin) {
+ ERR_FAIL_COND_V(!is_inside_tree(), false);
+
+ PhysicsServer3D::MotionResult *r = nullptr;
+ if (r_collision.is_valid()) {
+ // Needs const_cast because method bindings don't support non-const Ref.
+ r = const_cast<PhysicsServer3D::MotionResult *>(&r_collision->result);
+ }
+
+ return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, p_margin, r, p_exclude_raycast_shapes);
+}
+
+void PhysicsBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
+ if (p_lock) {
+ locked_axis |= p_axis;
+ } else {
+ locked_axis &= (~p_axis);
+ }
+ PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
+}
+
+bool PhysicsBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
+ return (locked_axis & p_axis);
+}
+
+Vector3 PhysicsBody3D::get_linear_velocity() const {
+ return Vector3();
+}
+
+Vector3 PhysicsBody3D::get_angular_velocity() const {
+ return Vector3();
+}
+
+real_t PhysicsBody3D::get_inverse_mass() const {
+ return 0;
}
void StaticBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
@@ -109,14 +192,44 @@ Ref<PhysicsMaterial> StaticBody3D::get_physics_material_override() const {
return physics_material_override;
}
+void StaticBody3D::set_kinematic_motion_enabled(bool p_enabled) {
+ if (p_enabled == kinematic_motion) {
+ return;
+ }
+
+ kinematic_motion = p_enabled;
+
+ if (kinematic_motion) {
+ PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC);
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
+ }
+
+ _update_kinematic_motion();
+}
+
+bool StaticBody3D::is_kinematic_motion_enabled() const {
+ return kinematic_motion;
+}
+
void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) {
constant_linear_velocity = p_vel;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
+
+ if (kinematic_motion) {
+ _update_kinematic_motion();
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
+ }
}
void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
constant_angular_velocity = p_vel;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
+
+ if (kinematic_motion) {
+ _update_kinematic_motion();
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
+ }
}
Vector3 StaticBody3D::get_constant_linear_velocity() const {
@@ -127,30 +240,81 @@ Vector3 StaticBody3D::get_constant_angular_velocity() const {
return constant_angular_velocity;
}
+Vector3 StaticBody3D::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+Vector3 StaticBody3D::get_angular_velocity() const {
+ return angular_velocity;
+}
+
+void StaticBody3D::_notification(int p_what) {
+ if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+
+ ERR_FAIL_COND(!kinematic_motion);
+
+ real_t delta_time = get_physics_process_delta_time();
+
+ Transform3D new_transform = get_global_transform();
+ new_transform.origin += constant_linear_velocity * delta_time;
+
+ real_t ang_vel = constant_angular_velocity.length();
+ if (!Math::is_zero_approx(ang_vel)) {
+ Vector3 ang_vel_axis = constant_angular_velocity / ang_vel;
+ Basis rot(ang_vel_axis, ang_vel * delta_time);
+ new_transform.basis = rot * new_transform.basis;
+ new_transform.orthonormalize();
+ }
+
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
+
+ // Propagate transform change to node.
+ set_ignore_transform_notification(true);
+ set_global_transform(new_transform);
+ set_ignore_transform_notification(false);
+ _on_transform_changed();
+ }
+}
+
void StaticBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);
ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_kinematic_motion_enabled", "enabled"), &StaticBody3D::set_kinematic_motion_enabled);
+ ClassDB::bind_method(D_METHOD("is_kinematic_motion_enabled"), &StaticBody3D::is_kinematic_motion_enabled);
+
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
- ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody3D::get_collision_exceptions);
- ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody3D::add_collision_exception_with);
- ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody3D::remove_collision_exception_with);
-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
+}
+
+void StaticBody3D::_direct_state_changed(Object *p_state) {
+#ifdef DEBUG_ENABLED
+ PhysicsDirectBodyState3D *state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
+ ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument");
+#else
+ PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state; //trust it
+#endif
+
+ linear_velocity = state->get_linear_velocity();
+ angular_velocity = state->get_angular_velocity();
}
StaticBody3D::StaticBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
}
-StaticBody3D::~StaticBody3D() {}
-
void StaticBody3D::_reload_physics_characteristics() {
if (physics_material_override.is_null()) {
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
@@ -161,6 +325,27 @@ void StaticBody3D::_reload_physics_characteristics() {
}
}
+void StaticBody3D::_update_kinematic_motion() {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+
+ if (kinematic_motion) {
+ PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &StaticBody3D::_direct_state_changed));
+
+ if (!constant_angular_velocity.is_equal_approx(Vector3()) || !constant_linear_velocity.is_equal_approx(Vector3())) {
+ set_physics_process_internal(true);
+ return;
+ }
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
+ }
+
+ set_physics_process_internal(false);
+}
+
void RigidBody3D::_body_enter_tree(ObjectID p_id) {
Object *obj = ObjectDB::get_instance(p_id);
Node *node = Object::cast_to<Node>(obj);
@@ -178,7 +363,7 @@ void RigidBody3D::_body_enter_tree(ObjectID p_id) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
}
contact_monitor->locked = false;
@@ -199,13 +384,13 @@ void RigidBody3D::_body_exit_tree(ObjectID p_id) {
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
for (int i = 0; i < E->get().shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape);
}
contact_monitor->locked = false;
}
-void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape) {
+void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) {
bool body_in = p_status == 1;
ObjectID objid = p_instance;
@@ -220,6 +405,7 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
if (body_in) {
if (!E) {
E = contact_monitor->body_map.insert(objid, BodyState());
+ E->get().rid = p_body;
//E->get().rc=0;
E->get().in_tree = node && node->is_inside_tree();
if (node) {
@@ -236,7 +422,7 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
}
if (E->get().in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_local_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
}
} else {
@@ -260,12 +446,13 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
contact_monitor->body_map.erase(E);
}
if (node && in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_local_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_local_shape);
}
}
}
struct _RigidBodyInOut {
+ RID rid;
ObjectID id;
int shape = 0;
int local_shape = 0;
@@ -314,6 +501,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
//put the ones to add
for (int i = 0; i < state->get_contact_count(); i++) {
+ RID rid = state->get_contact_collider(i);
ObjectID obj = state->get_contact_collider_id(i);
int local_shape = state->get_contact_local_shape(i);
int shape = state->get_contact_collider_shape(i);
@@ -322,6 +510,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(obj);
if (!E) {
+ toadd[toadd_count].rid = rid;
toadd[toadd_count].local_shape = local_shape;
toadd[toadd_count].id = obj;
toadd[toadd_count].shape = shape;
@@ -332,6 +521,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
ShapePair sp(shape, local_shape);
int idx = E->get().shapes.find(sp);
if (idx == -1) {
+ toadd[toadd_count].rid = rid;
toadd[toadd_count].local_shape = local_shape;
toadd[toadd_count].id = obj;
toadd[toadd_count].shape = shape;
@@ -347,6 +537,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
for (Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.front(); E; E = E->next()) {
for (int i = 0; i < E->get().shapes.size(); i++) {
if (!E->get().shapes[i].tagged) {
+ toremove[toremove_count].rid = E->get().rid;
toremove[toremove_count].body_id = E->key();
toremove[toremove_count].pair = E->get().shapes[i];
toremove_count++;
@@ -357,13 +548,13 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
//process removals
for (int i = 0; i < toremove_count; i++) {
- _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
+ _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
}
//process additions
for (int i = 0; i < toadd_count; i++) {
- _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
+ _body_inout(1, toremove[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
}
contact_monitor->locked = false;
@@ -392,15 +583,15 @@ void RigidBody3D::_notification(int p_what) {
void RigidBody3D::set_mode(Mode p_mode) {
mode = p_mode;
switch (p_mode) {
- case MODE_RIGID: {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_RIGID);
+ case MODE_DYNAMIC: {
+ PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC);
} break;
case MODE_STATIC: {
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
} break;
- case MODE_CHARACTER: {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_CHARACTER);
+ case MODE_DYNAMIC_LOCKED: {
+ PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED);
} break;
case MODE_KINEMATIC: {
@@ -511,7 +702,7 @@ Vector3 RigidBody3D::get_angular_velocity() const {
return angular_velocity;
}
-Basis RigidBody3D::get_inverse_inertia_tensor() {
+Basis RigidBody3D::get_inverse_inertia_tensor() const {
return inverse_inertia_tensor;
}
@@ -621,14 +812,6 @@ bool RigidBody3D::is_contact_monitor_enabled() const {
return contact_monitor != nullptr;
}
-void RigidBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
- PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
-}
-
-bool RigidBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
- return PhysicsServer3D::get_singleton()->body_is_axis_locked(get_rid(), p_axis);
-}
-
Array RigidBody3D::get_colliding_bodies() const {
ERR_FAIL_COND_V(!contact_monitor, Array());
@@ -648,12 +831,12 @@ Array RigidBody3D::get_colliding_bodies() const {
}
TypedArray<String> RigidBody3D::get_configuration_warnings() const {
- Transform t = get_transform();
+ Transform3D t = get_transform();
TypedArray<String> warnings = Node::get_configuration_warnings();
- if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) {
- warnings.push_back(TTR("Size changes to RigidBody3D (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
+ if ((get_mode() == MODE_DYNAMIC || get_mode() == MODE_DYNAMIC_LOCKED) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) {
+ warnings.push_back(TTR("Size changes to RigidBody3D (in dynamic modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
}
return warnings;
@@ -714,14 +897,11 @@ void RigidBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody3D::set_can_sleep);
ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody3D::is_able_to_sleep);
- ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &RigidBody3D::set_axis_lock);
- ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &RigidBody3D::get_axis_lock);
-
ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody3D::get_colliding_bodies);
BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState3D")));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Rigid,Static,Character,Kinematic"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Dynamic,Static,DynamicLocked,Kinematic"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
@@ -731,13 +911,6 @@ void RigidBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
- ADD_GROUP("Axis Lock", "axis_lock_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Z);
ADD_GROUP("Linear", "linear_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
@@ -745,20 +918,20 @@ void RigidBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
- BIND_ENUM_CONSTANT(MODE_RIGID);
+ BIND_ENUM_CONSTANT(MODE_DYNAMIC);
BIND_ENUM_CONSTANT(MODE_STATIC);
- BIND_ENUM_CONSTANT(MODE_CHARACTER);
+ BIND_ENUM_CONSTANT(MODE_DYNAMIC_LOCKED);
BIND_ENUM_CONSTANT(MODE_KINEMATIC);
}
RigidBody3D::RigidBody3D() :
- PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) {
+ PhysicsBody3D(PhysicsServer3D::BODY_MODE_DYNAMIC) {
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &RigidBody3D::_direct_state_changed));
}
@@ -778,147 +951,92 @@ void RigidBody3D::_reload_physics_characteristics() {
}
}
-//////////////////////////////////////////////////////
-//////////////////////////
-
-Ref<KinematicCollision3D> KinematicBody3D::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) {
- Collision col;
- if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) {
- if (motion_cache.is_null()) {
- motion_cache.instance();
- motion_cache->owner = this;
- }
-
- motion_cache->collision = col;
-
- return motion_cache;
- }
-
- return Ref<KinematicCollision3D>();
-}
-
-Vector3 KinematicBody3D::get_linear_velocity() const {
- return linear_velocity;
-}
-
-Vector3 KinematicBody3D::get_angular_velocity() const {
- return angular_velocity;
-}
-
-bool KinematicBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {
- Transform gt = get_global_transform();
- PhysicsServer3D::MotionResult result;
- bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes);
-
- if (colliding) {
- r_collision.collider_metadata = result.collider_metadata;
- r_collision.collider_shape = result.collider_shape;
- r_collision.collider_vel = result.collider_velocity;
- r_collision.collision = result.collision_point;
- r_collision.normal = result.collision_normal;
- r_collision.collider = result.collider_id;
- r_collision.collider_rid = result.collider;
- r_collision.travel = result.motion;
- r_collision.remainder = result.remainder;
- r_collision.local_shape = result.collision_local_shape;
- }
-
- for (int i = 0; i < 3; i++) {
- if (locked_axis & (1 << i)) {
- result.motion[i] = 0;
- }
- }
-
- if (!p_test_only) {
- gt.origin += result.motion;
- set_global_transform(gt);
- }
-
- return colliding;
-}
+///////////////////////////////////////
//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
#define FLOOR_ANGLE_THRESHOLD 0.01
-Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, real_t p_floor_max_angle, bool p_infinite_inertia) {
- Vector3 body_velocity = p_linear_velocity;
- Vector3 body_velocity_normal = body_velocity.normalized();
- Vector3 up_direction = p_up_direction.normalized();
+void CharacterBody3D::move_and_slide() {
+ Vector3 body_velocity_normal = linear_velocity.normalized();
+
+ bool was_on_floor = on_floor;
for (int i = 0; i < 3; i++) {
if (locked_axis & (1 << i)) {
- body_velocity[i] = 0;
+ linear_velocity[i] = 0.0;
}
}
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
- Vector3 motion = (floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
+ Vector3 motion = (floor_velocity + linear_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
on_floor = false;
on_floor_body = RID();
on_ceiling = false;
on_wall = false;
- colliders.clear();
+ motion_results.clear();
floor_normal = Vector3();
floor_velocity = Vector3();
- while (p_max_slides) {
- Collision collision;
+ int slide_count = max_slides;
+ while (slide_count) {
+ PhysicsServer3D::MotionResult result;
bool found_collision = false;
for (int i = 0; i < 2; ++i) {
bool collided;
if (i == 0) { //collide
- collided = move_and_collide(motion, p_infinite_inertia, collision);
+ collided = move_and_collide(motion, infinite_inertia, result, margin);
if (!collided) {
motion = Vector3(); //clear because no collision happened and motion completed
}
} else { //separate raycasts (if any)
- collided = separate_raycast_shapes(p_infinite_inertia, collision);
+ collided = separate_raycast_shapes(result);
if (collided) {
- collision.remainder = motion; //keep
- collision.travel = Vector3();
+ result.remainder = motion; //keep
+ result.motion = Vector3();
}
}
if (collided) {
found_collision = true;
- colliders.push_back(collision);
- motion = collision.remainder;
+ motion_results.push_back(result);
+ motion = result.remainder;
if (up_direction == Vector3()) {
//all is a wall
on_wall = true;
} else {
- if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
on_floor = true;
- floor_normal = collision.normal;
- on_floor_body = collision.collider_rid;
- floor_velocity = collision.collider_vel;
-
- if (p_stop_on_slope) {
- if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) {
- Transform gt = get_global_transform();
- gt.origin -= collision.travel.slide(up_direction);
+ floor_normal = result.collision_normal;
+ on_floor_body = result.collider;
+ floor_velocity = result.collider_velocity;
+
+ if (stop_on_slope) {
+ if ((body_velocity_normal + up_direction).length() < 0.01 && result.motion.length() < 1) {
+ Transform3D gt = get_global_transform();
+ gt.origin -= result.motion.slide(up_direction);
set_global_transform(gt);
- return Vector3();
+ linear_velocity = Vector3();
+ return;
}
}
- } else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ } else if (Math::acos(result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
on_ceiling = true;
} else {
on_wall = true;
}
}
- motion = motion.slide(collision.normal);
- body_velocity = body_velocity.slide(collision.normal);
+ motion = motion.slide(result.collision_normal);
+ linear_velocity = linear_velocity.slide(result.collision_normal);
for (int j = 0; j < 3; j++) {
if (locked_axis & (1 << j)) {
- body_velocity[j] = 0;
+ linear_velocity[j] = 0.0;
}
}
}
@@ -928,83 +1046,47 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const
break;
}
- --p_max_slides;
+ --slide_count;
}
- return body_velocity;
-}
-
-Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, real_t p_floor_max_angle, bool p_infinite_inertia) {
- Vector3 up_direction = p_up_direction.normalized();
- bool was_on_floor = on_floor;
-
- Vector3 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
- if (!was_on_floor || p_snap == Vector3()) {
- return ret;
+ if (!was_on_floor || snap == Vector3()) {
+ return;
}
- Collision col;
- Transform gt = get_global_transform();
-
- if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
+ // Apply snap.
+ Transform3D gt = get_global_transform();
+ PhysicsServer3D::MotionResult result;
+ if (move_and_collide(snap, infinite_inertia, result, margin, false, true)) {
bool apply = true;
if (up_direction != Vector3()) {
- if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
+ if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
on_floor = true;
- floor_normal = col.normal;
- on_floor_body = col.collider_rid;
- floor_velocity = col.collider_vel;
- if (p_stop_on_slope) {
+ floor_normal = result.collision_normal;
+ on_floor_body = result.collider;
+ floor_velocity = result.collider_velocity;
+ if (stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
// so only ensure that motion happens on floor direction in this case.
- col.travel = col.travel.project(up_direction);
+ result.motion = result.motion.project(up_direction);
}
} else {
apply = false; //snapped with floor direction, but did not snap to a floor, do not snap.
}
}
if (apply) {
- gt.origin += col.travel;
+ gt.origin += result.motion;
set_global_transform(gt);
}
}
-
- return ret;
-}
-
-bool KinematicBody3D::is_on_floor() const {
- return on_floor;
-}
-
-bool KinematicBody3D::is_on_wall() const {
- return on_wall;
}
-bool KinematicBody3D::is_on_ceiling() const {
- return on_ceiling;
-}
-
-Vector3 KinematicBody3D::get_floor_normal() const {
- return floor_normal;
-}
-
-Vector3 KinematicBody3D::get_floor_velocity() const {
- return floor_velocity;
-}
-
-bool KinematicBody3D::test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia) {
- ERR_FAIL_COND_V(!is_inside_tree(), false);
-
- return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia);
-}
-
-bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) {
+bool CharacterBody3D::separate_raycast_shapes(PhysicsServer3D::MotionResult &r_result) {
PhysicsServer3D::SeparationResult sep_res[8]; //max 8 rays
- Transform gt = get_global_transform();
+ Transform3D gt = get_global_transform();
Vector3 recover;
- int hits = PhysicsServer3D::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin);
+ int hits = PhysicsServer3D::get_singleton()->body_test_ray_separation(get_rid(), gt, infinite_inertia, recover, sep_res, 8, margin);
int deepest = -1;
real_t deepest_depth;
for (int i = 0; i < hits; i++) {
@@ -1018,15 +1100,15 @@ bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision
set_global_transform(gt);
if (deepest != -1) {
- r_collision.collider = sep_res[deepest].collider_id;
- r_collision.collider_metadata = sep_res[deepest].collider_metadata;
- r_collision.collider_shape = sep_res[deepest].collider_shape;
- r_collision.collider_vel = sep_res[deepest].collider_velocity;
- r_collision.collision = sep_res[deepest].collision_point;
- r_collision.normal = sep_res[deepest].collision_normal;
- r_collision.local_shape = sep_res[deepest].collision_local_shape;
- r_collision.travel = recover;
- r_collision.remainder = Vector3();
+ r_result.collider_id = sep_res[deepest].collider_id;
+ r_result.collider_metadata = sep_res[deepest].collider_metadata;
+ r_result.collider_shape = sep_res[deepest].collider_shape;
+ r_result.collider_velocity = sep_res[deepest].collider_velocity;
+ r_result.collision_point = sep_res[deepest].collision_point;
+ r_result.collision_normal = sep_res[deepest].collision_normal;
+ r_result.collision_local_shape = sep_res[deepest].collision_local_shape;
+ r_result.motion = recover;
+ r_result.remainder = Vector3();
return true;
} else {
@@ -1034,39 +1116,53 @@ bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision
}
}
-void KinematicBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
- if (p_lock) {
- locked_axis |= p_axis;
- } else {
- locked_axis &= (~p_axis);
- }
- PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
+void CharacterBody3D::set_safe_margin(real_t p_margin) {
+ margin = p_margin;
}
-bool KinematicBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
- return PhysicsServer3D::get_singleton()->body_is_axis_locked(get_rid(), p_axis);
+real_t CharacterBody3D::get_safe_margin() const {
+ return margin;
}
-void KinematicBody3D::set_safe_margin(real_t p_margin) {
- margin = p_margin;
- PhysicsServer3D::get_singleton()->body_set_kinematic_safe_margin(get_rid(), margin);
+Vector3 CharacterBody3D::get_linear_velocity() const {
+ return linear_velocity;
}
-real_t KinematicBody3D::get_safe_margin() const {
- return margin;
+void CharacterBody3D::set_linear_velocity(const Vector3 &p_velocity) {
+ linear_velocity = p_velocity;
+}
+
+bool CharacterBody3D::is_on_floor() const {
+ return on_floor;
+}
+
+bool CharacterBody3D::is_on_wall() const {
+ return on_wall;
+}
+
+bool CharacterBody3D::is_on_ceiling() const {
+ return on_ceiling;
}
-int KinematicBody3D::get_slide_count() const {
- return colliders.size();
+Vector3 CharacterBody3D::get_floor_normal() const {
+ return floor_normal;
+}
+
+Vector3 CharacterBody3D::get_floor_velocity() const {
+ return floor_velocity;
+}
+
+int CharacterBody3D::get_slide_count() const {
+ return motion_results.size();
}
-KinematicBody3D::Collision KinematicBody3D::get_slide_collision(int p_bounce) const {
- ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Collision());
- return colliders[p_bounce];
+PhysicsServer3D::MotionResult CharacterBody3D::get_slide_collision(int p_bounce) const {
+ ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), PhysicsServer3D::MotionResult());
+ return motion_results[p_bounce];
}
-Ref<KinematicCollision3D> KinematicBody3D::_get_slide_collision(int p_bounce) {
- ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Ref<KinematicCollision3D>());
+Ref<KinematicCollision3D> CharacterBody3D::_get_slide_collision(int p_bounce) {
+ ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), Ref<KinematicCollision3D>());
if (p_bounce >= slide_colliders.size()) {
slide_colliders.resize(p_bounce + 1);
}
@@ -1076,75 +1172,126 @@ Ref<KinematicCollision3D> KinematicBody3D::_get_slide_collision(int p_bounce) {
slide_colliders.write[p_bounce]->owner = this;
}
- slide_colliders.write[p_bounce]->collision = colliders[p_bounce];
+ slide_colliders.write[p_bounce]->result = motion_results[p_bounce];
return slide_colliders[p_bounce];
}
-void KinematicBody3D::_notification(int p_what) {
+bool CharacterBody3D::is_stop_on_slope_enabled() const {
+ return stop_on_slope;
+}
+
+void CharacterBody3D::set_stop_on_slope_enabled(bool p_enabled) {
+ stop_on_slope = p_enabled;
+}
+
+bool CharacterBody3D::is_infinite_inertia_enabled() const {
+ return infinite_inertia;
+}
+void CharacterBody3D::set_infinite_inertia_enabled(bool p_enabled) {
+ infinite_inertia = p_enabled;
+}
+
+int CharacterBody3D::get_max_slides() const {
+ return max_slides;
+}
+
+void CharacterBody3D::set_max_slides(int p_max_slides) {
+ ERR_FAIL_COND(p_max_slides > 0);
+ max_slides = p_max_slides;
+}
+
+real_t CharacterBody3D::get_floor_max_angle() const {
+ return floor_max_angle;
+}
+
+void CharacterBody3D::set_floor_max_angle(real_t p_radians) {
+ floor_max_angle = p_radians;
+}
+
+real_t CharacterBody3D::get_floor_max_angle_degrees() const {
+ return Math::rad2deg(floor_max_angle);
+}
+
+void CharacterBody3D::set_floor_max_angle_degrees(real_t p_degrees) {
+ floor_max_angle = Math::deg2rad(p_degrees);
+}
+
+const Vector3 &CharacterBody3D::get_snap() const {
+ return snap;
+}
+
+void CharacterBody3D::set_snap(const Vector3 &p_snap) {
+ snap = p_snap;
+}
+
+const Vector3 &CharacterBody3D::get_up_direction() const {
+ return up_direction;
+}
+
+void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) {
+ up_direction = p_up_direction.normalized();
+}
+
+void CharacterBody3D::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
// Reset move_and_slide() data.
on_floor = false;
on_floor_body = RID();
on_ceiling = false;
on_wall = false;
- colliders.clear();
+ motion_results.clear();
floor_velocity = Vector3();
}
}
-void KinematicBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody3D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
-
- ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody3D::test_move, DEFVAL(true));
+void CharacterBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody3D::move_and_slide);
- ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody3D::is_on_floor);
- ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody3D::is_on_ceiling);
- ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody3D::is_on_wall);
- ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody3D::get_floor_normal);
- ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody3D::get_floor_velocity);
+ ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &CharacterBody3D::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"), &CharacterBody3D::get_linear_velocity);
- ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &KinematicBody3D::set_axis_lock);
- ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &KinematicBody3D::get_axis_lock);
+ ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &CharacterBody3D::set_safe_margin);
+ ClassDB::bind_method(D_METHOD("get_safe_margin"), &CharacterBody3D::get_safe_margin);
+ ClassDB::bind_method(D_METHOD("is_stop_on_slope_enabled"), &CharacterBody3D::is_stop_on_slope_enabled);
+ ClassDB::bind_method(D_METHOD("set_stop_on_slope_enabled", "enabled"), &CharacterBody3D::set_stop_on_slope_enabled);
+ ClassDB::bind_method(D_METHOD("is_infinite_inertia_enabled"), &CharacterBody3D::is_infinite_inertia_enabled);
+ ClassDB::bind_method(D_METHOD("set_infinite_inertia_enabled", "enabled"), &CharacterBody3D::set_infinite_inertia_enabled);
+ ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody3D::get_max_slides);
+ ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody3D::set_max_slides);
+ ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody3D::get_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody3D::set_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("get_floor_max_angle_degrees"), &CharacterBody3D::get_floor_max_angle_degrees);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle_degrees", "degrees"), &CharacterBody3D::set_floor_max_angle_degrees);
+ ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody3D::get_snap);
+ ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody3D::set_snap);
+ ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody3D::get_up_direction);
+ ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody3D::set_up_direction);
- ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody3D::set_safe_margin);
- ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody3D::get_safe_margin);
+ ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody3D::is_on_floor);
+ ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody3D::is_on_ceiling);
+ ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody3D::is_on_wall);
+ ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody3D::get_floor_normal);
+ ClassDB::bind_method(D_METHOD("get_floor_velocity"), &CharacterBody3D::get_floor_velocity);
- ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody3D::get_slide_count);
- ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody3D::_get_slide_collision);
-
- ADD_GROUP("Axis Lock", "axis_lock_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
+ ClassDB::bind_method(D_METHOD("get_slide_count"), &CharacterBody3D::get_slide_count);
+ ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody3D::_get_slide_collision);
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides"), "set_max_slides", "get_max_slides");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle_degrees", PROPERTY_HINT_RANGE, "0,180,0.1", PROPERTY_USAGE_EDITOR), "set_floor_max_angle_degrees", "get_floor_max_angle_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "snap"), "set_snap", "get_snap");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
-void KinematicBody3D::_direct_state_changed(Object *p_state) {
-#ifdef DEBUG_ENABLED
- PhysicsDirectBodyState3D *state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
- ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument");
-#else
- PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state; //trust it
-#endif
-
- linear_velocity = state->get_linear_velocity();
- angular_velocity = state->get_angular_velocity();
-}
-
-KinematicBody3D::KinematicBody3D() :
+CharacterBody3D::CharacterBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
- set_safe_margin(0.001);
- PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &KinematicBody3D::_direct_state_changed));
}
-KinematicBody3D::~KinematicBody3D() {
- if (motion_cache.is_valid()) {
- motion_cache->owner = nullptr;
- }
-
+CharacterBody3D::~CharacterBody3D() {
for (int i = 0; i < slide_colliders.size(); i++) {
if (slide_colliders[i].is_valid()) {
slide_colliders.write[i]->owner = nullptr;
@@ -1155,39 +1302,39 @@ KinematicBody3D::~KinematicBody3D() {
///////////////////////////////////////
Vector3 KinematicCollision3D::get_position() const {
- return collision.collision;
+ return result.collision_point;
}
Vector3 KinematicCollision3D::get_normal() const {
- return collision.normal;
+ return result.collision_normal;
}
Vector3 KinematicCollision3D::get_travel() const {
- return collision.travel;
+ return result.motion;
}
Vector3 KinematicCollision3D::get_remainder() const {
- return collision.remainder;
+ return result.remainder;
}
Object *KinematicCollision3D::get_local_shape() const {
if (!owner) {
return nullptr;
}
- uint32_t ownerid = owner->shape_find_owner(collision.local_shape);
+ uint32_t ownerid = owner->shape_find_owner(result.collision_local_shape);
return owner->shape_owner_get_owner(ownerid);
}
Object *KinematicCollision3D::get_collider() const {
- if (collision.collider.is_valid()) {
- return ObjectDB::get_instance(collision.collider);
+ if (result.collider_id.is_valid()) {
+ return ObjectDB::get_instance(result.collider_id);
}
return nullptr;
}
ObjectID KinematicCollision3D::get_collider_id() const {
- return collision.collider;
+ return result.collider_id;
}
Object *KinematicCollision3D::get_collider_shape() const {
@@ -1195,7 +1342,7 @@ Object *KinematicCollision3D::get_collider_shape() const {
if (collider) {
CollisionObject3D *obj2d = Object::cast_to<CollisionObject3D>(collider);
if (obj2d) {
- uint32_t ownerid = obj2d->shape_find_owner(collision.collider_shape);
+ uint32_t ownerid = obj2d->shape_find_owner(result.collider_shape);
return obj2d->shape_owner_get_owner(ownerid);
}
}
@@ -1204,11 +1351,11 @@ Object *KinematicCollision3D::get_collider_shape() const {
}
int KinematicCollision3D::get_collider_shape_index() const {
- return collision.collider_shape;
+ return result.collider_shape;
}
Vector3 KinematicCollision3D::get_collider_velocity() const {
- return collision.collider_vel;
+ return result.collider_velocity;
}
Variant KinematicCollision3D::get_collider_metadata() const {
@@ -1241,12 +1388,6 @@ void KinematicCollision3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::NIL, "collider_metadata", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "", "get_collider_metadata");
}
-KinematicCollision3D::KinematicCollision3D() {
- collision.collider_shape = 0;
- collision.local_shape = 0;
- owner = nullptr;
-}
-
///////////////////////////////////////
bool PhysicalBone3D::JointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
@@ -1952,6 +2093,8 @@ void PhysicalBone3D::_notification(int p_what) {
if (parent_skeleton) {
if (-1 != bone_id) {
parent_skeleton->unbind_physical_bone_from_bone(bone_id);
+ parent_skeleton->unbind_child_node_from_bone(bone_id, this);
+ bone_id = -1;
}
}
parent_skeleton = nullptr;
@@ -1981,7 +2124,7 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) {
state = (PhysicsDirectBodyState3D *)p_state; //trust it
#endif
- Transform global_transform(state->get_transform());
+ Transform3D global_transform(state->get_transform());
set_ignore_transform_notification(true);
set_global_transform(global_transform);
@@ -2040,16 +2183,13 @@ void PhysicalBone3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &PhysicalBone3D::set_can_sleep);
ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &PhysicalBone3D::is_able_to_sleep);
- ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicalBone3D::set_axis_lock);
- ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicalBone3D::get_axis_lock);
-
ADD_GROUP("Joint", "joint_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,PinJoint,ConeJoint,HingeJoint,SliderJoint,6DOFJoint"), "set_joint_type", "get_joint_type");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "joint_offset"), "set_joint_offset", "get_joint_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "joint_offset"), "set_joint_offset", "get_joint_offset");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_joint_rotation_degrees", "get_joint_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation", PROPERTY_HINT_NONE, "", 0), "set_joint_rotation", "get_joint_rotation");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "body_offset"), "set_body_offset", "get_body_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
@@ -2059,14 +2199,6 @@ void PhysicalBone3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
- ADD_GROUP("Axis Lock", "axis_lock_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Z);
-
BIND_ENUM_CONSTANT(JOINT_TYPE_NONE);
BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
BIND_ENUM_CONSTANT(JOINT_TYPE_CONE);
@@ -2116,8 +2248,8 @@ void PhysicalBone3D::_reload_joint() {
return;
}
- Transform joint_transf = get_global_transform() * joint_offset;
- Transform local_a = body_a->get_global_transform().affine_inverse() * joint_transf;
+ Transform3D joint_transf = get_global_transform() * joint_offset;
+ Transform3D local_a = body_a->get_global_transform().affine_inverse() * joint_transf;
local_a.orthonormalize();
switch (get_joint_type()) {
@@ -2210,11 +2342,11 @@ void PhysicalBone3D::_set_gizmo_move_joint(bool p_move_joint) {
}
#ifdef TOOLS_ENABLED
-Transform PhysicalBone3D::get_global_gizmo_transform() const {
+Transform3D PhysicalBone3D::get_global_gizmo_transform() const {
return gizmo_move_joint ? get_global_transform() * joint_offset : get_global_transform();
}
-Transform PhysicalBone3D::get_local_gizmo_transform() const {
+Transform3D PhysicalBone3D::get_local_gizmo_transform() const {
return gizmo_move_joint ? get_transform() * joint_offset : get_transform();
}
#endif
@@ -2270,13 +2402,13 @@ PhysicalBone3D::JointType PhysicalBone3D::get_joint_type() const {
return joint_data ? joint_data->get_joint_type() : JOINT_TYPE_NONE;
}
-void PhysicalBone3D::set_joint_offset(const Transform &p_offset) {
+void PhysicalBone3D::set_joint_offset(const Transform3D &p_offset) {
joint_offset = p_offset;
_update_joint_offset();
}
-const Transform &PhysicalBone3D::get_joint_offset() const {
+const Transform3D &PhysicalBone3D::get_joint_offset() const {
return joint_offset;
}
@@ -2298,11 +2430,11 @@ Vector3 PhysicalBone3D::get_joint_rotation_degrees() const {
return get_joint_rotation() * (180.0 / Math_PI);
}
-const Transform &PhysicalBone3D::get_body_offset() const {
+const Transform3D &PhysicalBone3D::get_body_offset() const {
return body_offset;
}
-void PhysicalBone3D::set_body_offset(const Transform &p_offset) {
+void PhysicalBone3D::set_body_offset(const Transform3D &p_offset) {
body_offset = p_offset;
body_offset_inverse = body_offset.affine_inverse();
@@ -2408,14 +2540,6 @@ bool PhysicalBone3D::is_able_to_sleep() const {
return can_sleep;
}
-void PhysicalBone3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
- PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
-}
-
-bool PhysicalBone3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
- return PhysicsServer3D::get_singleton()->body_is_axis_locked(get_rid(), p_axis);
-}
-
PhysicalBone3D::PhysicalBone3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
joint = PhysicsServer3D::get_singleton()->joint_create();
@@ -2455,7 +2579,7 @@ void PhysicalBone3D::update_bone_id() {
void PhysicalBone3D::update_offset() {
#ifdef TOOLS_ENABLED
if (parent_skeleton) {
- Transform bone_transform(parent_skeleton->get_global_transform());
+ Transform3D bone_transform(parent_skeleton->get_global_transform());
if (-1 != bone_id) {
bone_transform *= parent_skeleton->get_bone_global_pose(bone_id);
}
@@ -2475,7 +2599,7 @@ void PhysicalBone3D::_start_physics_simulation() {
return;
}
reset_to_rest_position();
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_RIGID);
+ PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC);
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_direct_state_changed));
@@ -2498,7 +2622,7 @@ void PhysicalBone3D::_stop_physics_simulation() {
}
if (_internal_simulate_physics) {
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
- parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false);
+ parent_skeleton->set_bone_global_pose_override(bone_id, Transform3D(), 0.0, false);
set_as_top_level(false);
_internal_simulate_physics = false;
}
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 21afe66861..8df3635be0 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -37,6 +37,8 @@
#include "servers/physics_server_3d.h"
#include "skeleton_3d.h"
+class KinematicCollision3D;
+
class PhysicsBody3D : public CollisionObject3D {
GDCLASS(PhysicsBody3D, CollisionObject3D);
@@ -44,7 +46,19 @@ protected:
static void _bind_methods();
PhysicsBody3D(PhysicsServer3D::BodyMode p_mode);
+ Ref<KinematicCollision3D> motion_cache;
+
+ uint16_t locked_axis = 0;
+
+ Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false, real_t p_margin = 0.001);
+
public:
+ bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
+ bool test_move(const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001);
+
+ void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
+ bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
+
virtual Vector3 get_linear_velocity() const;
virtual Vector3 get_angular_velocity() const;
virtual real_t get_inverse_mass() const;
@@ -53,7 +67,7 @@ public:
void add_collision_exception_with(Node *p_node); //must be physicsbody
void remove_collision_exception_with(Node *p_node);
- PhysicsBody3D();
+ virtual ~PhysicsBody3D();
};
class StaticBody3D : public PhysicsBody3D {
@@ -62,11 +76,19 @@ class StaticBody3D : public PhysicsBody3D {
Vector3 constant_linear_velocity;
Vector3 constant_angular_velocity;
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
+
Ref<PhysicsMaterial> physics_material_override;
+ bool kinematic_motion = false;
+
protected:
+ void _notification(int p_what);
static void _bind_methods();
+ void _direct_state_changed(Object *p_state);
+
public:
void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
Ref<PhysicsMaterial> get_physics_material_override() const;
@@ -77,11 +99,18 @@ public:
Vector3 get_constant_linear_velocity() const;
Vector3 get_constant_angular_velocity() const;
+ virtual Vector3 get_linear_velocity() const override;
+ virtual Vector3 get_angular_velocity() const override;
+
StaticBody3D();
- ~StaticBody3D();
private:
void _reload_physics_characteristics();
+
+ void _update_kinematic_motion();
+
+ void set_kinematic_motion_enabled(bool p_enabled);
+ bool is_kinematic_motion_enabled() const;
};
class RigidBody3D : public PhysicsBody3D {
@@ -89,16 +118,16 @@ class RigidBody3D : public PhysicsBody3D {
public:
enum Mode {
- MODE_RIGID,
+ MODE_DYNAMIC,
MODE_STATIC,
- MODE_CHARACTER,
+ MODE_DYNAMIC_LOCKED,
MODE_KINEMATIC,
};
protected:
bool can_sleep = true;
PhysicsDirectBodyState3D *state = nullptr;
- Mode mode = MODE_RIGID;
+ Mode mode = MODE_DYNAMIC;
real_t mass = 1.0;
Ref<PhysicsMaterial> physics_material_override;
@@ -137,10 +166,12 @@ protected:
}
};
struct RigidBody3D_RemoveAction {
+ RID rid;
ObjectID body_id;
ShapePair pair;
};
struct BodyState {
+ RID rid;
//int rc;
bool in_tree = false;
VSet<ShapePair> shapes;
@@ -155,7 +186,7 @@ protected:
void _body_enter_tree(ObjectID p_id);
void _body_exit_tree(ObjectID p_id);
- void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape);
+ void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape);
virtual void _direct_state_changed(Object *p_state);
void _notification(int p_what);
@@ -181,7 +212,7 @@ public:
void set_angular_velocity(const Vector3 &p_velocity);
Vector3 get_angular_velocity() const override;
- Basis get_inverse_inertia_tensor();
+ Basis get_inverse_inertia_tensor() const;
void set_gravity_scale(real_t p_gravity_scale);
real_t get_gravity_scale() const;
@@ -210,9 +241,6 @@ public:
void set_use_continuous_collision_detection(bool p_enable);
bool is_using_continuous_collision_detection() const;
- void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
- bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
-
Array get_colliding_bodies() const;
void add_central_force(const Vector3 &p_force);
@@ -236,30 +264,20 @@ VARIANT_ENUM_CAST(RigidBody3D::Mode);
class KinematicCollision3D;
-class KinematicBody3D : public PhysicsBody3D {
- GDCLASS(KinematicBody3D, PhysicsBody3D);
-
-public:
- struct Collision {
- Vector3 collision;
- Vector3 normal;
- Vector3 collider_vel;
- ObjectID collider;
- RID collider_rid;
- int collider_shape = 0;
- Variant collider_metadata;
- Vector3 remainder;
- Vector3 travel;
- int local_shape = 0;
- };
+class CharacterBody3D : public PhysicsBody3D {
+ GDCLASS(CharacterBody3D, PhysicsBody3D);
private:
- Vector3 linear_velocity;
- Vector3 angular_velocity;
+ real_t margin = 0.001;
- uint16_t locked_axis = 0;
+ bool stop_on_slope = false;
+ bool infinite_inertia = true;
+ int max_slides = 4;
+ real_t floor_max_angle = Math::deg2rad((real_t)45.0);
+ Vector3 snap;
+ Vector3 up_direction = Vector3(0.0, 1.0, 0.0);
- real_t margin;
+ Vector3 linear_velocity;
Vector3 floor_normal;
Vector3 floor_velocity;
@@ -267,38 +285,47 @@ private:
bool on_floor = false;
bool on_ceiling = false;
bool on_wall = false;
- Vector<Collision> colliders;
+ Vector<PhysicsServer3D::MotionResult> motion_results;
Vector<Ref<KinematicCollision3D>> slide_colliders;
- Ref<KinematicCollision3D> motion_cache;
-
- _FORCE_INLINE_ bool _ignores_mode(PhysicsServer3D::BodyMode) const;
- Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
Ref<KinematicCollision3D> _get_slide_collision(int p_bounce);
-protected:
- void _notification(int p_what);
- static void _bind_methods();
+ bool separate_raycast_shapes(PhysicsServer3D::MotionResult &r_result);
- virtual void _direct_state_changed(Object *p_state);
+ void set_safe_margin(real_t p_margin);
+ real_t get_safe_margin() const;
-public:
- virtual Vector3 get_linear_velocity() const override;
- virtual Vector3 get_angular_velocity() const override;
+ bool is_stop_on_slope_enabled() const;
+ void set_stop_on_slope_enabled(bool p_enabled);
- bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
- bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia);
+ bool is_infinite_inertia_enabled() const;
+ void set_infinite_inertia_enabled(bool p_enabled);
- bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision);
+ int get_max_slides() const;
+ void set_max_slides(int p_max_slides);
- void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
- bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
+ real_t get_floor_max_angle() const;
+ void set_floor_max_angle(real_t p_radians);
- void set_safe_margin(real_t p_margin);
- real_t get_safe_margin() const;
+ real_t get_floor_max_angle_degrees() const;
+ void set_floor_max_angle_degrees(real_t p_degrees);
+
+ const Vector3 &get_snap() const;
+ void set_snap(const Vector3 &p_snap);
+
+ const Vector3 &get_up_direction() const;
+ void set_up_direction(const Vector3 &p_up_direction);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void move_and_slide();
+
+ virtual Vector3 get_linear_velocity() const override;
+ void set_linear_velocity(const Vector3 &p_velocity);
- Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, real_t p_floor_max_angle = Math::deg2rad((real_t)45.0), bool p_infinite_inertia = true);
- Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, real_t p_floor_max_angle = Math::deg2rad((real_t)45.0), bool p_infinite_inertia = true);
bool is_on_floor() const;
bool is_on_wall() const;
bool is_on_ceiling() const;
@@ -306,18 +333,19 @@ public:
Vector3 get_floor_velocity() const;
int get_slide_count() const;
- Collision get_slide_collision(int p_bounce) const;
+ PhysicsServer3D::MotionResult get_slide_collision(int p_bounce) const;
- KinematicBody3D();
- ~KinematicBody3D();
+ CharacterBody3D();
+ ~CharacterBody3D();
};
-class KinematicCollision3D : public Reference {
- GDCLASS(KinematicCollision3D, Reference);
+class KinematicCollision3D : public RefCounted {
+ GDCLASS(KinematicCollision3D, RefCounted);
- KinematicBody3D *owner;
- friend class KinematicBody3D;
- KinematicBody3D::Collision collision;
+ PhysicsBody3D *owner = nullptr;
+ friend class PhysicsBody3D;
+ friend class CharacterBody3D;
+ PhysicsServer3D::MotionResult result;
protected:
static void _bind_methods();
@@ -334,8 +362,6 @@ public:
int get_collider_shape_index() const;
Vector3 get_collider_velocity() const;
Variant get_collider_metadata() const;
-
- KinematicCollision3D();
};
class PhysicalBone3D : public PhysicsBody3D {
@@ -465,12 +491,12 @@ private:
#endif
JointData *joint_data = nullptr;
- Transform joint_offset;
+ Transform3D joint_offset;
RID joint;
Skeleton3D *parent_skeleton = nullptr;
- Transform body_offset;
- Transform body_offset_inverse;
+ Transform3D body_offset;
+ Transform3D body_offset_inverse;
bool simulate_physics = false;
bool _internal_simulate_physics = false;
int bone_id = -1;
@@ -506,8 +532,8 @@ public:
public:
#ifdef TOOLS_ENABLED
- virtual Transform get_global_gizmo_transform() const override;
- virtual Transform get_local_gizmo_transform() const override;
+ virtual Transform3D get_global_gizmo_transform() const override;
+ virtual Transform3D get_local_gizmo_transform() const override;
#endif
const JointData *get_joint_data() const;
@@ -518,8 +544,8 @@ public:
void set_joint_type(JointType p_joint_type);
JointType get_joint_type() const;
- void set_joint_offset(const Transform &p_offset);
- const Transform &get_joint_offset() const;
+ void set_joint_offset(const Transform3D &p_offset);
+ const Transform3D &get_joint_offset() const;
void set_joint_rotation(const Vector3 &p_euler_rad);
Vector3 get_joint_rotation() const;
@@ -527,8 +553,8 @@ public:
void set_joint_rotation_degrees(const Vector3 &p_euler_deg);
Vector3 get_joint_rotation_degrees() const;
- void set_body_offset(const Transform &p_offset);
- const Transform &get_body_offset() const;
+ void set_body_offset(const Transform3D &p_offset);
+ const Transform3D &get_body_offset() const;
void set_simulate_physics(bool p_simulate);
bool get_simulate_physics();
@@ -558,9 +584,6 @@ public:
void set_can_sleep(bool p_active);
bool is_able_to_sleep() const;
- void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
- bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
-
void apply_central_impulse(const Vector3 &p_impulse);
void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp
index 3d58d1c10e..01f10c171f 100644
--- a/scene/3d/physics_joint_3d.cpp
+++ b/scene/3d/physics_joint_3d.cpp
@@ -372,15 +372,15 @@ bool HingeJoint3D::get_flag(Flag p_flag) const {
}
void HingeJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
- Transform gt = get_global_transform();
- Transform ainv = body_a->get_global_transform().affine_inverse();
+ Transform3D gt = get_global_transform();
+ Transform3D ainv = body_a->get_global_transform().affine_inverse();
- Transform local_a = ainv * gt;
+ Transform3D local_a = ainv * gt;
local_a.orthonormalize();
- Transform local_b = gt;
+ Transform3D local_b = gt;
if (body_b) {
- Transform binv = body_b->get_global_transform().affine_inverse();
+ Transform3D binv = body_b->get_global_transform().affine_inverse();
local_b = binv * gt;
}
@@ -506,15 +506,15 @@ real_t SliderJoint3D::get_param(Param p_param) const {
}
void SliderJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
- Transform gt = get_global_transform();
- Transform ainv = body_a->get_global_transform().affine_inverse();
+ Transform3D gt = get_global_transform();
+ Transform3D ainv = body_a->get_global_transform().affine_inverse();
- Transform local_a = ainv * gt;
+ Transform3D local_a = ainv * gt;
local_a.orthonormalize();
- Transform local_b = gt;
+ Transform3D local_b = gt;
if (body_b) {
- Transform binv = body_b->get_global_transform().affine_inverse();
+ Transform3D binv = body_b->get_global_transform().affine_inverse();
local_b = binv * gt;
}
@@ -611,18 +611,18 @@ real_t ConeTwistJoint3D::get_param(Param p_param) const {
}
void ConeTwistJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
- Transform gt = get_global_transform();
+ Transform3D gt = get_global_transform();
//Vector3 cone_twistpos = gt.origin;
//Vector3 cone_twistdir = gt.basis.get_axis(2);
- Transform ainv = body_a->get_global_transform().affine_inverse();
+ Transform3D ainv = body_a->get_global_transform().affine_inverse();
- Transform local_a = ainv * gt;
+ Transform3D local_a = ainv * gt;
local_a.orthonormalize();
- Transform local_b = gt;
+ Transform3D local_b = gt;
if (body_b) {
- Transform binv = body_b->get_global_transform().affine_inverse();
+ Transform3D binv = body_b->get_global_transform().affine_inverse();
local_b = binv * gt;
}
@@ -936,18 +936,18 @@ bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const {
}
void Generic6DOFJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
- Transform gt = get_global_transform();
+ Transform3D gt = get_global_transform();
//Vector3 cone_twistpos = gt.origin;
//Vector3 cone_twistdir = gt.basis.get_axis(2);
- Transform ainv = body_a->get_global_transform().affine_inverse();
+ Transform3D ainv = body_a->get_global_transform().affine_inverse();
- Transform local_a = ainv * gt;
+ Transform3D local_a = ainv * gt;
local_a.orthonormalize();
- Transform local_b = gt;
+ Transform3D local_b = gt;
if (body_b) {
- Transform binv = body_b->get_global_transform().affine_inverse();
+ Transform3D binv = body_b->get_global_transform().affine_inverse();
local_b = binv * gt;
}
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index 475f8c07fd..db841101e5 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -205,7 +205,7 @@ void RayCast3D::_update_raycast_state() {
PhysicsDirectSpaceState3D *dss = PhysicsServer3D::get_singleton()->space_get_direct_state(w3d->get_space());
ERR_FAIL_COND(!dss);
- Transform gt = get_global_transform();
+ Transform3D gt = get_global_transform();
Vector3 to = target_position;
if (to == Vector3()) {
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index ad24f39bce..7762156b4a 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -230,7 +230,7 @@ void ReflectionProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &ReflectionProbe::set_update_mode);
ClassDB::bind_method(D_METHOD("get_update_mode"), &ReflectionProbe::get_update_mode);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once,Always"), "set_update_mode", "get_update_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once (Fast),Always (Slow)"), "set_update_mode", "get_update_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "intensity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_intensity", "get_intensity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,16384,0.1,or_greater"), "set_max_distance", "get_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
@@ -242,7 +242,7 @@ void ReflectionProbe::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
ADD_GROUP("Ambient", "ambient_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_mode", PROPERTY_HINT_ENUM, "Disabled,Environment,ConstantColor"), "set_ambient_mode", "get_ambient_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_mode", PROPERTY_HINT_ENUM, "Disabled,Environment,Constant Color"), "set_ambient_mode", "get_ambient_mode");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ambient_color", "get_ambient_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_color_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_color_energy", "get_ambient_color_energy");
diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp
index 29a407905b..a7b3a6f1ec 100644
--- a/scene/3d/remote_transform_3d.cpp
+++ b/scene/3d/remote_transform_3d.cpp
@@ -65,7 +65,7 @@ void RemoteTransform3D::_update_remote() {
if (update_remote_position && update_remote_rotation && update_remote_scale) {
n->set_global_transform(get_global_transform());
} else {
- Transform our_trans = get_global_transform();
+ Transform3D our_trans = get_global_transform();
if (update_remote_rotation) {
n->set_rotation(our_trans.basis.get_rotation());
@@ -76,7 +76,7 @@ void RemoteTransform3D::_update_remote() {
}
if (update_remote_position) {
- Transform n_trans = n->get_global_transform();
+ Transform3D n_trans = n->get_global_transform();
n_trans.set_origin(our_trans.get_origin());
n->set_global_transform(n_trans);
@@ -87,7 +87,7 @@ void RemoteTransform3D::_update_remote() {
if (update_remote_position && update_remote_rotation && update_remote_scale) {
n->set_transform(get_transform());
} else {
- Transform our_trans = get_transform();
+ Transform3D our_trans = get_transform();
if (update_remote_rotation) {
n->set_rotation(our_trans.basis.get_rotation());
@@ -98,7 +98,7 @@ void RemoteTransform3D::_update_remote() {
}
if (update_remote_position) {
- Transform n_trans = n->get_transform();
+ Transform3D n_trans = n->get_transform();
n_trans.set_origin(our_trans.get_origin());
n->set_transform(n_trans);
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index 59233708f6..f9d613a4bb 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -94,20 +94,6 @@ bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) {
set_bone_enabled(which, p_value);
} else if (what == "pose") {
set_bone_pose(which, p_value);
- } else if (what == "bound_children") {
- Array children = p_value;
-
- if (is_inside_tree()) {
- bones.write[which].nodes_bound.clear();
-
- for (int i = 0; i < children.size(); i++) {
- NodePath npath = children[i];
- ERR_CONTINUE(npath.operator String() == "");
- Node *node = get_node(npath);
- ERR_CONTINUE(!node);
- bind_child_node_to_bone(which, node);
- }
- }
} else {
return false;
}
@@ -137,19 +123,6 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const {
r_ret = is_bone_enabled(which);
} else if (what == "pose") {
r_ret = get_bone_pose(which);
- } else if (what == "bound_children") {
- Array children;
-
- for (const List<ObjectID>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) {
- Object *obj = ObjectDB::get_instance(E->get());
- ERR_CONTINUE(!obj);
- Node *node = Object::cast_to<Node>(obj);
- ERR_CONTINUE(!node);
- NodePath npath = get_path_to(node);
- children.push_back(npath);
- }
-
- r_ret = children;
} else {
return false;
}
@@ -162,10 +135,9 @@ void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const {
String prep = "bones/" + itos(i) + "/";
p_list->push_back(PropertyInfo(Variant::STRING, prep + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::ARRAY, prep + "bound_children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
}
}
@@ -239,7 +211,7 @@ void Skeleton3D::_notification(int p_what) {
if (b.disable_rest) {
if (b.enabled) {
- Transform pose = b.pose;
+ Transform3D pose = b.pose;
if (b.custom_pose_enable) {
pose = b.custom_pose * pose;
}
@@ -255,14 +227,14 @@ void Skeleton3D::_notification(int p_what) {
b.pose_global = bonesptr[b.parent].pose_global;
b.pose_global_no_override = bonesptr[b.parent].pose_global;
} else {
- b.pose_global = Transform();
- b.pose_global_no_override = Transform();
+ b.pose_global = Transform3D();
+ b.pose_global_no_override = Transform3D();
}
}
} else {
if (b.enabled) {
- Transform pose = b.pose;
+ Transform3D pose = b.pose;
if (b.custom_pose_enable) {
pose = b.custom_pose * pose;
}
@@ -365,7 +337,6 @@ void Skeleton3D::_notification(int p_what) {
} break;
-#ifndef _3D_DISABLED
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
// This is active only if the skeleton animates the physical bones
// and the state of the bone is not active.
@@ -384,7 +355,6 @@ void Skeleton3D::_notification(int p_what) {
set_physics_process_internal(true);
}
} break;
-#endif
}
}
@@ -396,7 +366,7 @@ void Skeleton3D::clear_bones_global_pose_override() {
_make_dirty();
}
-void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent) {
+void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, float p_amount, bool p_persistent) {
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].global_pose_override_amount = p_amount;
bones.write[p_bone].global_pose_override = p_pose;
@@ -404,16 +374,16 @@ void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform &p_po
_make_dirty();
}
-Transform Skeleton3D::get_bone_global_pose(int p_bone) const {
- ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
+Transform3D Skeleton3D::get_bone_global_pose(int p_bone) const {
+ ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform3D());
if (dirty) {
const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON);
}
return bones[p_bone].pose_global;
}
-Transform Skeleton3D::get_bone_global_pose_no_override(int p_bone) const {
- ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
+Transform3D Skeleton3D::get_bone_global_pose_no_override(int p_bone) const {
+ ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform3D());
if (dirty) {
const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON);
}
@@ -524,15 +494,14 @@ int Skeleton3D::get_bone_parent(int p_bone) const {
return bones[p_bone].parent;
}
-void Skeleton3D::set_bone_rest(int p_bone, const Transform &p_rest) {
+void Skeleton3D::set_bone_rest(int p_bone, const Transform3D &p_rest) {
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].rest = p_rest;
_make_dirty();
}
-
-Transform Skeleton3D::get_bone_rest(int p_bone) const {
- ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
+Transform3D Skeleton3D::get_bone_rest(int p_bone) const {
+ ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform3D());
return bones[p_bone].rest;
}
@@ -591,7 +560,7 @@ void Skeleton3D::clear_bones() {
// posing api
-void Skeleton3D::set_bone_pose(int p_bone, const Transform &p_pose) {
+void Skeleton3D::set_bone_pose(int p_bone, const Transform3D &p_pose) {
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].pose = p_pose;
@@ -599,24 +568,23 @@ void Skeleton3D::set_bone_pose(int p_bone, const Transform &p_pose) {
_make_dirty();
}
}
-
-Transform Skeleton3D::get_bone_pose(int p_bone) const {
- ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
+Transform3D Skeleton3D::get_bone_pose(int p_bone) const {
+ ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform3D());
return bones[p_bone].pose;
}
-void Skeleton3D::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) {
+void Skeleton3D::set_bone_custom_pose(int p_bone, const Transform3D &p_custom_pose) {
ERR_FAIL_INDEX(p_bone, bones.size());
//ERR_FAIL_COND( !is_inside_scene() );
- bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform());
+ bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform3D());
bones.write[p_bone].custom_pose = p_custom_pose;
_make_dirty();
}
-Transform Skeleton3D::get_bone_custom_pose(int p_bone) const {
- ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
+Transform3D Skeleton3D::get_bone_custom_pose(int p_bone) const {
+ ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform3D());
return bones[p_bone].custom_pose;
}
@@ -651,8 +619,6 @@ void Skeleton3D::localize_rests() {
}
}
-#ifndef _3D_DISABLED
-
void Skeleton3D::set_animate_physical_bones(bool p_animate) {
animate_physical_bones = p_animate;
@@ -726,7 +692,7 @@ void Skeleton3D::_rebuild_physical_bones_cache() {
const int b_size = bones.size();
for (int i = 0; i < b_size; ++i) {
PhysicalBone3D *parent_pb = _get_physical_bone_parent(i);
- if (parent_pb != bones[i].physical_bone) {
+ if (parent_pb != bones[i].cache_parent_physical_bone) {
bones.write[i].cache_parent_physical_bone = parent_pb;
if (bones[i].physical_bone) {
bones[i].physical_bone->_on_bone_parent_changed();
@@ -813,8 +779,6 @@ void Skeleton3D::physical_bones_remove_collision_exception(RID p_exception) {
_physical_bones_add_remove_collision_exception(false, this, p_exception);
}
-#endif // _3D_DISABLED
-
void Skeleton3D::_skin_changed() {
_make_dirty();
}
@@ -880,11 +844,11 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) {
}
// helper functions
-Transform Skeleton3D::bone_transform_to_world_transform(Transform p_bone_transform) {
+Transform3D Skeleton3D::bone_transform_to_world_transform(Transform3D p_bone_transform) {
return get_global_transform() * p_bone_transform;
}
-Transform Skeleton3D::world_transform_to_bone_transform(Transform p_world_transform) {
+Transform3D Skeleton3D::world_transform_to_bone_transform(Transform3D p_world_transform) {
return get_global_transform().affine_inverse() * p_world_transform;
}
@@ -912,10 +876,6 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton3D::set_bone_disable_rest);
ClassDB::bind_method(D_METHOD("is_bone_rest_disabled", "bone_idx"), &Skeleton3D::is_bone_rest_disabled);
- ClassDB::bind_method(D_METHOD("bind_child_node_to_bone", "bone_idx", "node"), &Skeleton3D::bind_child_node_to_bone);
- ClassDB::bind_method(D_METHOD("unbind_child_node_from_bone", "bone_idx", "node"), &Skeleton3D::unbind_child_node_from_bone);
- ClassDB::bind_method(D_METHOD("get_bound_child_nodes_to_bone", "bone_idx"), &Skeleton3D::_get_bound_child_nodes_to_bone);
-
ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton3D::clear_bones);
ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton3D::get_bone_pose);
@@ -932,8 +892,6 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("bone_transform_to_world_transform", "bone_transform"), &Skeleton3D::bone_transform_to_world_transform);
ClassDB::bind_method(D_METHOD("world_transform_to_bone_transform", "world_transform"), &Skeleton3D::world_transform_to_bone_transform);
-#ifndef _3D_DISABLED
-
ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton3D::set_animate_physical_bones);
ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton3D::get_animate_physical_bones);
@@ -943,7 +901,6 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton3D::physical_bones_remove_collision_exception);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones");
-#endif // _3D_DISABLED
#ifdef TOOLS_ENABLED
ADD_SIGNAL(MethodInfo("pose_updated"));
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index 508cd7c329..2f6e416c8c 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -35,16 +35,13 @@
#include "scene/3d/node_3d.h"
#include "scene/resources/skin.h"
-#ifndef _3D_DISABLED
typedef int BoneId;
class PhysicalBone3D;
-#endif // _3D_DISABLED
-
class Skeleton3D;
-class SkinReference : public Reference {
- GDCLASS(SkinReference, Reference)
+class SkinReference : public RefCounted {
+ GDCLASS(SkinReference, RefCounted)
friend class Skeleton3D;
Skeleton3D *skeleton_node;
@@ -79,23 +76,21 @@ private:
int sort_index = 0; //used for re-sorting process order
bool disable_rest = false;
- Transform rest;
+ Transform3D rest;
- Transform pose;
- Transform pose_global;
- Transform pose_global_no_override;
+ Transform3D pose;
+ Transform3D pose_global;
+ Transform3D pose_global_no_override;
bool custom_pose_enable = false;
- Transform custom_pose;
+ Transform3D custom_pose;
float global_pose_override_amount = 0.0;
bool global_pose_override_reset = false;
- Transform global_pose_override;
+ Transform3D global_pose_override;
-#ifndef _3D_DISABLED
PhysicalBone3D *physical_bone = nullptr;
PhysicalBone3D *cache_parent_physical_bone = nullptr;
-#endif // _3D_DISABLED
List<ObjectID> nodes_bound;
};
@@ -114,18 +109,6 @@ private:
uint64_t version = 1;
- // bind helpers
- Array _get_bound_child_nodes_to_bone(int p_bone) const {
- Array bound;
- List<Node *> children;
- get_bound_child_nodes_to_bone(p_bone, &children);
-
- for (int i = 0; i < children.size(); i++) {
- bound.push_back(children[i]);
- }
- return bound;
- }
-
void _update_process_order();
protected:
@@ -158,13 +141,13 @@ public:
int get_bone_count() const;
- void set_bone_rest(int p_bone, const Transform &p_rest);
- Transform get_bone_rest(int p_bone) const;
- Transform get_bone_global_pose(int p_bone) const;
- Transform get_bone_global_pose_no_override(int p_bone) const;
+ void set_bone_rest(int p_bone, const Transform3D &p_rest);
+ Transform3D get_bone_rest(int p_bone) const;
+ Transform3D get_bone_global_pose(int p_bone) const;
+ Transform3D get_bone_global_pose_no_override(int p_bone) const;
void clear_bones_global_pose_override();
- void set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent = false);
+ void set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, float p_amount, bool p_persistent = false);
void set_bone_enabled(int p_bone, bool p_enabled);
bool is_bone_enabled(int p_bone) const;
@@ -177,11 +160,11 @@ public:
// posing api
- void set_bone_pose(int p_bone, const Transform &p_pose);
- Transform get_bone_pose(int p_bone) const;
+ void set_bone_pose(int p_bone, const Transform3D &p_pose);
+ Transform3D get_bone_pose(int p_bone) const;
- void set_bone_custom_pose(int p_bone, const Transform &p_custom_pose);
- Transform get_bone_custom_pose(int p_bone) const;
+ void set_bone_custom_pose(int p_bone, const Transform3D &p_custom_pose);
+ Transform3D get_bone_custom_pose(int p_bone) const;
void localize_rests(); // used for loaders and tools
int get_process_order(int p_idx);
@@ -190,10 +173,9 @@ public:
Ref<SkinReference> register_skin(const Ref<Skin> &p_skin);
// Helper functions
- Transform bone_transform_to_world_transform(Transform p_transform);
- Transform world_transform_to_bone_transform(Transform p_transform);
+ Transform3D bone_transform_to_world_transform(Transform3D p_transform);
+ Transform3D world_transform_to_bone_transform(Transform3D p_transform);
-#ifndef _3D_DISABLED
// Physical bone API
void set_animate_physical_bones(bool p_animate);
@@ -215,7 +197,6 @@ public:
void physical_bones_start_simulation_on(const TypedArray<StringName> &p_bones);
void physical_bones_add_collision_exception(RID p_exception);
void physical_bones_remove_collision_exception(RID p_exception);
-#endif // _3D_DISABLED
public:
Skeleton3D();
diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index bd1c202205..1005d51e63 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -129,7 +129,7 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
return true;
}
-void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet) {
+void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet, Vector3 p_origin_pos) {
real_t distance_to_goal(1e4);
real_t previous_distance_to_goal(0);
int can_solve(p_task->max_iterations);
@@ -138,7 +138,7 @@ void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet) {
--can_solve;
solve_simple_backwards(p_task->chain, p_solve_magnet);
- solve_simple_forwards(p_task->chain, p_solve_magnet);
+ solve_simple_forwards(p_task->chain, p_solve_magnet, p_origin_pos);
distance_to_goal = (p_task->chain.tips[0].chain_item->current_pos - p_task->chain.tips[0].end_effector->goal_transform.origin).length();
}
@@ -176,13 +176,13 @@ void FabrikInverseKinematic::solve_simple_backwards(Chain &r_chain, bool p_solve
}
}
-void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_magnet) {
+void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_magnet, Vector3 p_origin_pos) {
if (p_solve_magnet && !r_chain.middle_chain_item) {
return;
}
ChainItem *sub_chain_root(&r_chain.chain_root);
- Vector3 origin(r_chain.chain_root.initial_transform.origin);
+ Vector3 origin = p_origin_pos;
while (sub_chain_root) { // Reach the tip
sub_chain_root->current_pos = origin;
@@ -212,7 +212,7 @@ void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_
}
}
-FabrikInverseKinematic::Task *FabrikInverseKinematic::create_simple_task(Skeleton3D *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform) {
+FabrikInverseKinematic::Task *FabrikInverseKinematic::create_simple_task(Skeleton3D *p_sk, BoneId root_bone, BoneId tip_bone, const Transform3D &goal_transform) {
FabrikInverseKinematic::EndEffector ee;
ee.tip_bone = tip_bone;
@@ -236,17 +236,17 @@ void FabrikInverseKinematic::free_task(Task *p_task) {
}
}
-void FabrikInverseKinematic::set_goal(Task *p_task, const Transform &p_goal) {
+void FabrikInverseKinematic::set_goal(Task *p_task, const Transform3D &p_goal) {
p_task->goal_global_transform = p_goal;
}
-void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_transf, real_t blending_delta) {
+void FabrikInverseKinematic::make_goal(Task *p_task, const Transform3D &p_inverse_transf, real_t blending_delta) {
if (blending_delta >= 0.99f) {
// Update the end_effector (local transform) without blending
p_task->end_effectors.write[0].goal_transform = p_inverse_transf * p_task->goal_global_transform;
} else {
// End effector in local transform
- const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose_no_override(p_task->end_effectors[0].tip_bone));
+ const Transform3D end_effector_pose(p_task->skeleton->get_bone_global_pose_no_override(p_task->end_effectors[0].tip_bone));
// Update the end_effector (local transform) by blending with current pose
p_task->end_effectors.write[0].goal_transform = end_effector_pose.interpolate_with(p_inverse_transf * p_task->goal_global_transform, blending_delta);
@@ -273,18 +273,21 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
// Update the initial root transform so its synced with any animation changes
_update_chain(p_task->skeleton, &p_task->chain.chain_root);
+ p_task->skeleton->set_bone_global_pose_override(p_task->chain.chain_root.bone, Transform3D(), 0.0, false);
+ Vector3 origin_pos = p_task->skeleton->get_bone_global_pose(p_task->chain.chain_root.bone).origin;
+
make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta);
if (p_use_magnet && p_task->chain.middle_chain_item) {
p_task->chain.magnet_position = p_task->chain.middle_chain_item->initial_transform.origin.lerp(p_magnet_position, blending_delta);
- solve_simple(p_task, true);
+ solve_simple(p_task, true, origin_pos);
}
- solve_simple(p_task, false);
+ solve_simple(p_task, false, origin_pos);
// Assign new bone position.
ChainItem *ci(&p_task->chain.chain_root);
while (ci) {
- Transform new_bone_pose(ci->initial_transform);
+ Transform3D new_bone_pose(ci->initial_transform);
new_bone_pose.origin = ci->current_pos;
if (!ci->children.is_empty()) {
@@ -394,7 +397,7 @@ void SkeletonIK3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "root_bone"), "set_root_bone", "get_root_bone");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "tip_bone"), "set_tip_bone", "get_tip_bone");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interpolation", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_interpolation", "get_interpolation");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "target"), "set_target_transform", "get_target_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "target"), "set_target_transform", "get_target_transform");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_tip_basis"), "set_override_tip_basis", "is_override_tip_basis");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_magnet"), "set_use_magnet", "is_using_magnet");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "magnet"), "set_magnet_position", "get_magnet_position");
@@ -458,12 +461,12 @@ real_t SkeletonIK3D::get_interpolation() const {
return interpolation;
}
-void SkeletonIK3D::set_target_transform(const Transform &p_target) {
+void SkeletonIK3D::set_target_transform(const Transform3D &p_target) {
target = p_target;
reload_goal();
}
-const Transform &SkeletonIK3D::get_target_transform() const {
+const Transform3D &SkeletonIK3D::get_target_transform() const {
return target;
}
@@ -534,7 +537,7 @@ void SkeletonIK3D::stop() {
}
}
-Transform SkeletonIK3D::_get_target_transform() {
+Transform3D SkeletonIK3D::_get_target_transform() {
if (!target_node_override && !target_node_path_override.is_empty()) {
target_node_override = Object::cast_to<Node3D>(get_node(target_node_path_override));
}
diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h
index 9255e18b72..81dfe675c3 100644
--- a/scene/3d/skeleton_ik_3d.h
+++ b/scene/3d/skeleton_ik_3d.h
@@ -37,13 +37,13 @@
* @author AndreaCatania
*/
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
#include "scene/3d/skeleton_3d.h"
class FabrikInverseKinematic {
struct EndEffector {
BoneId tip_bone;
- Transform goal_transform;
+ Transform3D goal_transform;
};
struct ChainItem {
@@ -55,7 +55,7 @@ class FabrikInverseKinematic {
real_t length = 0.0;
/// Positions relative to root bone
- Transform initial_transform;
+ Transform3D initial_transform;
Vector3 current_pos;
// Direction from this bone to child
Vector3 current_ori;
@@ -97,7 +97,7 @@ public:
BoneId root_bone = -1;
Vector<EndEffector> end_effectors;
- Transform goal_global_transform;
+ Transform3D goal_global_transform;
Task() {}
};
@@ -106,17 +106,17 @@ private:
/// Init a chain that starts from the root to tip
static bool build_chain(Task *p_task, bool p_force_simple_chain = true);
- static void solve_simple(Task *p_task, bool p_solve_magnet);
+ static void solve_simple(Task *p_task, bool p_solve_magnet, Vector3 p_origin_pos);
/// Special solvers that solve only chains with one end effector
static void solve_simple_backwards(Chain &r_chain, bool p_solve_magnet);
- static void solve_simple_forwards(Chain &r_chain, bool p_solve_magnet);
+ static void solve_simple_forwards(Chain &r_chain, bool p_solve_magnet, Vector3 p_origin_pos);
public:
- static Task *create_simple_task(Skeleton3D *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform);
+ static Task *create_simple_task(Skeleton3D *p_sk, BoneId root_bone, BoneId tip_bone, const Transform3D &goal_transform);
static void free_task(Task *p_task);
// The goal of chain should be always in local space
- static void set_goal(Task *p_task, const Transform &p_goal);
- static void make_goal(Task *p_task, const Transform &p_inverse_transf, real_t blending_delta);
+ static void set_goal(Task *p_task, const Transform3D &p_goal);
+ static void make_goal(Task *p_task, const Transform3D &p_inverse_transf, real_t blending_delta);
static void solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position);
static void _update_chain(const Skeleton3D *p_skeleton, ChainItem *p_chain_item);
@@ -128,7 +128,7 @@ class SkeletonIK3D : public Node {
StringName root_bone;
StringName tip_bone;
real_t interpolation = 1.0;
- Transform target;
+ Transform3D target;
NodePath target_node_path_override;
bool override_tip_basis = true;
bool use_magnet = false;
@@ -161,8 +161,8 @@ public:
void set_interpolation(real_t p_interpolation);
real_t get_interpolation() const;
- void set_target_transform(const Transform &p_target);
- const Transform &get_target_transform() const;
+ void set_target_transform(const Transform3D &p_target);
+ const Transform3D &get_target_transform() const;
void set_target_node(const NodePath &p_node);
NodePath get_target_node();
@@ -190,7 +190,7 @@ public:
void stop();
private:
- Transform _get_target_transform();
+ Transform3D _get_target_transform();
void reload_chain();
void reload_goal();
void _solve_chain();
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index dc4deb0570..df5474d03e 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -283,7 +283,7 @@ void SoftBody3D::_notification(int p_what) {
set_notify_transform(false);
// Required to be top level with Transform at center of world in order to modify RenderingServer only to support custom Transform
set_as_top_level(true);
- set_transform(Transform());
+ set_transform(Transform3D());
set_notify_transform(true);
} break;
@@ -373,7 +373,7 @@ TypedArray<String> SoftBody3D::get_configuration_warnings() const {
warnings.push_back(TTR("This body will be ignored until you set a mesh."));
}
- Transform t = get_transform();
+ Transform3D t = get_transform();
if ((ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) {
warnings.push_back(TTR("Size changes to SoftBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
}
@@ -408,7 +408,7 @@ void SoftBody3D::_draw_soft_mesh() {
/// Necessary in order to render the mesh correctly (Soft body nodes are in global space)
simulation_started = true;
call_deferred("set_as_top_level", true);
- call_deferred("set_transform", Transform());
+ call_deferred("set_transform", Transform3D());
}
_update_physics_server();
diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp
index 9518b47696..1911e14d54 100644
--- a/scene/3d/spring_arm_3d.cpp
+++ b/scene/3d/spring_arm_3d.cpp
@@ -153,7 +153,7 @@ void SpringArm3D::process_spring() {
}
current_spring_length = spring_length * motion_delta;
- Transform childs_transform;
+ Transform3D childs_transform;
childs_transform.origin = get_global_transform().origin + cast_direction * (spring_length * motion_delta);
for (int i = get_child_count() - 1; 0 <= i; --i) {
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 33b8b488c6..9ec461d973 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -505,6 +505,7 @@ void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed));
}
_queue_update();
+ emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
Ref<Texture2D> Sprite3D::get_texture() const {
@@ -551,15 +552,15 @@ int Sprite3D::get_frame() const {
return frame;
}
-void Sprite3D::set_frame_coords(const Vector2 &p_coord) {
- ERR_FAIL_INDEX(int(p_coord.x), hframes);
- ERR_FAIL_INDEX(int(p_coord.y), vframes);
+void Sprite3D::set_frame_coords(const Vector2i &p_coord) {
+ ERR_FAIL_INDEX(p_coord.x, hframes);
+ ERR_FAIL_INDEX(p_coord.y, vframes);
- set_frame(int(p_coord.y) * hframes + int(p_coord.x));
+ set_frame(p_coord.y * hframes + p_coord.x);
}
-Vector2 Sprite3D::get_frame_coords() const {
- return Vector2(frame % hframes, frame / hframes);
+Vector2i Sprite3D::get_frame_coords() const {
+ return Vector2i(frame % hframes, frame / hframes);
}
void Sprite3D::set_vframes(int p_amount) {
@@ -657,12 +658,13 @@ void Sprite3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
ADD_SIGNAL(MethodInfo("frame_changed"));
+ ADD_SIGNAL(MethodInfo("texture_changed"));
}
Sprite3D::Sprite3D() {
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 5e47e66bcb..e3dd117804 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -176,8 +176,8 @@ public:
void set_frame(int p_frame);
int get_frame() const;
- void set_frame_coords(const Vector2 &p_coord);
- Vector2 get_frame_coords() const;
+ void set_frame_coords(const Vector2i &p_coord);
+ Vector2i get_frame_coords() const;
void set_vframes(int p_amount);
int get_vframes() const;
diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp
index 9493f686c4..0d88769b70 100644
--- a/scene/3d/vehicle_body_3d.cpp
+++ b/scene/3d/vehicle_body_3d.cpp
@@ -346,7 +346,7 @@ VehicleWheel3D::VehicleWheel3D() {
void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState3D *s) {
wheel.m_raycastInfo.m_isInContact = false;
- Transform chassisTrans = s->get_transform();
+ Transform3D chassisTrans = s->get_transform();
/*
if (interpolatedTransform && (getRigidBody()->getMotionState())) {
getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
@@ -784,7 +784,7 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) {
Vector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
- Vector3 vChassisWorldUp = s->get_transform().basis.transposed()[1]; //getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
+ Vector3 vChassisWorldUp = s->get_transform().basis.transposed()[1]; //getRigidBody()->getCenterOfMassTransform3D().getBasis().getColumn(m_indexUpAxis);
rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f - wheelInfo.m_rollInfluence));
#else
rel_pos[1] *= wheelInfo.m_rollInfluence; //?
@@ -841,7 +841,7 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) {
Vector3 vel = state->get_linear_velocity() + (state->get_angular_velocity()).cross(relpos); // * mPos);
if (wheel.m_raycastInfo.m_isInContact) {
- const Transform &chassisWorldTransform = state->get_transform();
+ const Transform3D &chassisWorldTransform = state->get_transform();
Vector3 fwd(
chassisWorldTransform.basis[0][Vector3::AXIS_Z],
diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h
index 646071a363..2c10205ea3 100644
--- a/scene/3d/vehicle_body_3d.h
+++ b/scene/3d/vehicle_body_3d.h
@@ -40,8 +40,8 @@ class VehicleWheel3D : public Node3D {
friend class VehicleBody3D;
- Transform m_worldTransform;
- Transform local_xform;
+ Transform3D m_worldTransform;
+ Transform3D local_xform;
bool engine_traction = false;
bool steers = false;
diff --git a/scene/3d/velocity_tracker_3d.h b/scene/3d/velocity_tracker_3d.h
index e971f4755a..827c3f5bd8 100644
--- a/scene/3d/velocity_tracker_3d.h
+++ b/scene/3d/velocity_tracker_3d.h
@@ -33,8 +33,8 @@
#include "scene/3d/node_3d.h"
-class VelocityTracker3D : public Reference {
- GDCLASS(VelocityTracker3D, Reference);
+class VelocityTracker3D : public RefCounted {
+ GDCLASS(VelocityTracker3D, RefCounted);
struct PositionHistory {
uint64_t frame = 0;
diff --git a/scene/3d/visibility_notifier_3d.cpp b/scene/3d/visibility_notifier_3d.cpp
index 471838b9d1..b230cb2fd7 100644
--- a/scene/3d/visibility_notifier_3d.cpp
+++ b/scene/3d/visibility_notifier_3d.cpp
@@ -138,7 +138,7 @@ void VisibilityEnabler3D::_find_nodes(Node *p_node) {
{
RigidBody3D *rb = Object::cast_to<RigidBody3D>(p_node);
- if (rb && ((rb->get_mode() == RigidBody3D::MODE_CHARACTER || rb->get_mode() == RigidBody3D::MODE_RIGID))) {
+ if (rb && ((rb->get_mode() == RigidBody3D::MODE_DYNAMIC || rb->get_mode() == RigidBody3D::MODE_DYNAMIC_LOCKED))) {
add = true;
meta = rb->get_mode();
}
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index d81b09b86c..c16e3c2d78 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -61,7 +61,7 @@ void VisualInstance3D::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- Transform gt = get_global_transform();
+ Transform3D gt = get_global_transform();
RenderingServer::get_singleton()->instance_set_transform(instance, gt);
} break;
case NOTIFICATION_EXIT_WORLD: {
@@ -150,40 +150,40 @@ Ref<Material> GeometryInstance3D::get_material_override() const {
return material_override;
}
-void GeometryInstance3D::set_lod_min_distance(float p_dist) {
- lod_min_distance = p_dist;
- RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
+void GeometryInstance3D::set_visibility_range_begin(float p_dist) {
+ visibility_range_begin = p_dist;
+ RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
}
-float GeometryInstance3D::get_lod_min_distance() const {
- return lod_min_distance;
+float GeometryInstance3D::get_visibility_range_begin() const {
+ return visibility_range_begin;
}
-void GeometryInstance3D::set_lod_max_distance(float p_dist) {
- lod_max_distance = p_dist;
- RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
+void GeometryInstance3D::set_visibility_range_end(float p_dist) {
+ visibility_range_end = p_dist;
+ RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
}
-float GeometryInstance3D::get_lod_max_distance() const {
- return lod_max_distance;
+float GeometryInstance3D::get_visibility_range_end() const {
+ return visibility_range_end;
}
-void GeometryInstance3D::set_lod_min_hysteresis(float p_dist) {
- lod_min_hysteresis = p_dist;
- RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
+void GeometryInstance3D::set_visibility_range_begin_margin(float p_dist) {
+ visibility_range_begin_margin = p_dist;
+ RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
}
-float GeometryInstance3D::get_lod_min_hysteresis() const {
- return lod_min_hysteresis;
+float GeometryInstance3D::get_visibility_range_begin_margin() const {
+ return visibility_range_begin_margin;
}
-void GeometryInstance3D::set_lod_max_hysteresis(float p_dist) {
- lod_max_hysteresis = p_dist;
- RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
+void GeometryInstance3D::set_visibility_range_end_margin(float p_dist) {
+ visibility_range_end_margin = p_dist;
+ RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
}
-float GeometryInstance3D::get_lod_max_hysteresis() const {
- return lod_max_hysteresis;
+float GeometryInstance3D::get_visibility_range_end_margin() const {
+ return visibility_range_end_margin;
}
void GeometryInstance3D::_notification(int p_what) {
@@ -357,17 +357,17 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lod_bias", "bias"), &GeometryInstance3D::set_lod_bias);
ClassDB::bind_method(D_METHOD("get_lod_bias"), &GeometryInstance3D::get_lod_bias);
- ClassDB::bind_method(D_METHOD("set_lod_max_hysteresis", "mode"), &GeometryInstance3D::set_lod_max_hysteresis);
- ClassDB::bind_method(D_METHOD("get_lod_max_hysteresis"), &GeometryInstance3D::get_lod_max_hysteresis);
+ ClassDB::bind_method(D_METHOD("set_visibility_range_end_margin", "distance"), &GeometryInstance3D::set_visibility_range_end_margin);
+ ClassDB::bind_method(D_METHOD("get_visibility_range_end_margin"), &GeometryInstance3D::get_visibility_range_end_margin);
- ClassDB::bind_method(D_METHOD("set_lod_max_distance", "mode"), &GeometryInstance3D::set_lod_max_distance);
- ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance3D::get_lod_max_distance);
+ ClassDB::bind_method(D_METHOD("set_visibility_range_end", "distance"), &GeometryInstance3D::set_visibility_range_end);
+ ClassDB::bind_method(D_METHOD("get_visibility_range_end"), &GeometryInstance3D::get_visibility_range_end);
- ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis", "mode"), &GeometryInstance3D::set_lod_min_hysteresis);
- ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance3D::get_lod_min_hysteresis);
+ ClassDB::bind_method(D_METHOD("set_visibility_range_begin_margin", "distance"), &GeometryInstance3D::set_visibility_range_begin_margin);
+ ClassDB::bind_method(D_METHOD("get_visibility_range_begin_margin"), &GeometryInstance3D::get_visibility_range_begin_margin);
- ClassDB::bind_method(D_METHOD("set_lod_min_distance", "mode"), &GeometryInstance3D::set_lod_min_distance);
- ClassDB::bind_method(D_METHOD("get_lod_min_distance"), &GeometryInstance3D::get_lod_min_distance);
+ ClassDB::bind_method(D_METHOD("set_visibility_range_begin", "distance"), &GeometryInstance3D::set_visibility_range_begin);
+ ClassDB::bind_method(D_METHOD("get_visibility_range_begin"), &GeometryInstance3D::get_visibility_range_begin);
ClassDB::bind_method(D_METHOD("set_shader_instance_uniform", "uniform", "value"), &GeometryInstance3D::set_shader_instance_uniform);
ClassDB::bind_method(D_METHOD("get_shader_instance_uniform", "uniform"), &GeometryInstance3D::get_shader_instance_uniform);
@@ -398,11 +398,11 @@ void GeometryInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Baked,Dynamic"), "set_gi_mode", "get_gi_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, "1x,2x,4x,8x"), "set_lightmap_scale", "get_lightmap_scale");
- ADD_GROUP("LOD", "lod_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_hysteresis", "get_lod_min_hysteresis");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_distance", "get_lod_max_distance");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_hysteresis", "get_lod_max_hysteresis");
+ ADD_GROUP("Visibility Range", "visibility_range_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_begin", "get_visibility_range_begin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_end", "get_visibility_range_end");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_end_margin", "get_visibility_range_end_margin");
//ADD_SIGNAL( MethodInfo("visibility_changed"));
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index 68d29ef81e..2d5699859b 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -107,10 +107,13 @@ public:
private:
ShadowCastingSetting shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
Ref<Material> material_override;
- float lod_min_distance = 0.0;
- float lod_max_distance = 0.0;
- float lod_min_hysteresis = 0.0;
- float lod_max_hysteresis = 0.0;
+
+ float visibility_range_begin = 0.0;
+ float visibility_range_end = 0.0;
+ float visibility_range_begin_margin = 0.0;
+ float visibility_range_end_margin = 0.0;
+
+ Vector<NodePath> visibility_range_children;
float lod_bias = 1.0;
@@ -136,17 +139,20 @@ public:
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
ShadowCastingSetting get_cast_shadows_setting() const;
- void set_lod_min_distance(float p_dist);
- float get_lod_min_distance() const;
+ void set_visibility_range_begin(float p_dist);
+ float get_visibility_range_begin() const;
+
+ void set_visibility_range_end(float p_dist);
+ float get_visibility_range_end() const;
- void set_lod_max_distance(float p_dist);
- float get_lod_max_distance() const;
+ void set_visibility_range_begin_margin(float p_dist);
+ float get_visibility_range_begin_margin() const;
- void set_lod_min_hysteresis(float p_dist);
- float get_lod_min_hysteresis() const;
+ void set_visibility_range_end_margin(float p_dist);
+ float get_visibility_range_end_margin() const;
- void set_lod_max_hysteresis(float p_dist);
- float get_lod_max_hysteresis() const;
+ void set_visibility_range_parent(const Node *p_parent);
+ void clear_visibility_range_parent();
void set_material_override(const Ref<Material> &p_material);
Ref<Material> get_material_override() const;
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
new file mode 100644
index 0000000000..e00be9204c
--- /dev/null
+++ b/scene/3d/voxel_gi.cpp
@@ -0,0 +1,549 @@
+/*************************************************************************/
+/* voxel_gi.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "voxel_gi.h"
+
+#include "core/os/os.h"
+
+#include "mesh_instance_3d.h"
+#include "voxelizer.h"
+
+void VoxelGIData::_set_data(const Dictionary &p_data) {
+ ERR_FAIL_COND(!p_data.has("bounds"));
+ ERR_FAIL_COND(!p_data.has("octree_size"));
+ ERR_FAIL_COND(!p_data.has("octree_cells"));
+ ERR_FAIL_COND(!p_data.has("octree_data"));
+ ERR_FAIL_COND(!p_data.has("octree_df") && !p_data.has("octree_df_png"));
+ ERR_FAIL_COND(!p_data.has("level_counts"));
+ ERR_FAIL_COND(!p_data.has("to_cell_xform"));
+
+ AABB bounds = p_data["bounds"];
+ Vector3 octree_size = p_data["octree_size"];
+ Vector<uint8_t> octree_cells = p_data["octree_cells"];
+ Vector<uint8_t> octree_data = p_data["octree_data"];
+
+ Vector<uint8_t> octree_df;
+ if (p_data.has("octree_df")) {
+ octree_df = p_data["octree_df"];
+ } else if (p_data.has("octree_df_png")) {
+ Vector<uint8_t> octree_df_png = p_data["octree_df_png"];
+ Ref<Image> img;
+ img.instance();
+ Error err = img->load_png_from_buffer(octree_df_png);
+ ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND(img->get_format() != Image::FORMAT_L8);
+ octree_df = img->get_data();
+ }
+ Vector<int> octree_levels = p_data["level_counts"];
+ Transform3D to_cell_xform = p_data["to_cell_xform"];
+
+ allocate(to_cell_xform, bounds, octree_size, octree_cells, octree_data, octree_df, octree_levels);
+}
+
+Dictionary VoxelGIData::_get_data() const {
+ Dictionary d;
+ d["bounds"] = get_bounds();
+ Vector3i otsize = get_octree_size();
+ d["octree_size"] = Vector3(otsize);
+ d["octree_cells"] = get_octree_cells();
+ d["octree_data"] = get_data_cells();
+ if (otsize != Vector3i()) {
+ Ref<Image> img;
+ img.instance();
+ img->create(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field());
+ Vector<uint8_t> df_png = img->save_png_to_buffer();
+ ERR_FAIL_COND_V(df_png.size() == 0, Dictionary());
+ d["octree_df_png"] = df_png;
+ } else {
+ d["octree_df"] = Vector<uint8_t>();
+ }
+
+ d["level_counts"] = get_level_counts();
+ d["to_cell_xform"] = get_to_cell_xform();
+ return d;
+}
+
+void VoxelGIData::allocate(const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
+ RS::get_singleton()->voxel_gi_allocate_data(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts);
+ bounds = p_aabb;
+ to_cell_xform = p_to_cell_xform;
+ octree_size = p_octree_size;
+}
+
+AABB VoxelGIData::get_bounds() const {
+ return bounds;
+}
+
+Vector3 VoxelGIData::get_octree_size() const {
+ return octree_size;
+}
+
+Vector<uint8_t> VoxelGIData::get_octree_cells() const {
+ return RS::get_singleton()->voxel_gi_get_octree_cells(probe);
+}
+
+Vector<uint8_t> VoxelGIData::get_data_cells() const {
+ return RS::get_singleton()->voxel_gi_get_data_cells(probe);
+}
+
+Vector<uint8_t> VoxelGIData::get_distance_field() const {
+ return RS::get_singleton()->voxel_gi_get_distance_field(probe);
+}
+
+Vector<int> VoxelGIData::get_level_counts() const {
+ return RS::get_singleton()->voxel_gi_get_level_counts(probe);
+}
+
+Transform3D VoxelGIData::get_to_cell_xform() const {
+ return to_cell_xform;
+}
+
+void VoxelGIData::set_dynamic_range(float p_range) {
+ RS::get_singleton()->voxel_gi_set_dynamic_range(probe, p_range);
+ dynamic_range = p_range;
+}
+
+float VoxelGIData::get_dynamic_range() const {
+ return dynamic_range;
+}
+
+void VoxelGIData::set_propagation(float p_propagation) {
+ RS::get_singleton()->voxel_gi_set_propagation(probe, p_propagation);
+ propagation = p_propagation;
+}
+
+float VoxelGIData::get_propagation() const {
+ return propagation;
+}
+
+void VoxelGIData::set_anisotropy_strength(float p_anisotropy_strength) {
+ RS::get_singleton()->voxel_gi_set_anisotropy_strength(probe, p_anisotropy_strength);
+ anisotropy_strength = p_anisotropy_strength;
+}
+
+float VoxelGIData::get_anisotropy_strength() const {
+ return anisotropy_strength;
+}
+
+void VoxelGIData::set_energy(float p_energy) {
+ RS::get_singleton()->voxel_gi_set_energy(probe, p_energy);
+ energy = p_energy;
+}
+
+float VoxelGIData::get_energy() const {
+ return energy;
+}
+
+void VoxelGIData::set_ao(float p_ao) {
+ RS::get_singleton()->voxel_gi_set_ao(probe, p_ao);
+ ao = p_ao;
+}
+
+float VoxelGIData::get_ao() const {
+ return ao;
+}
+
+void VoxelGIData::set_ao_size(float p_ao_size) {
+ RS::get_singleton()->voxel_gi_set_ao_size(probe, p_ao_size);
+ ao_size = p_ao_size;
+}
+
+float VoxelGIData::get_ao_size() const {
+ return ao_size;
+}
+
+void VoxelGIData::set_bias(float p_bias) {
+ RS::get_singleton()->voxel_gi_set_bias(probe, p_bias);
+ bias = p_bias;
+}
+
+float VoxelGIData::get_bias() const {
+ return bias;
+}
+
+void VoxelGIData::set_normal_bias(float p_normal_bias) {
+ RS::get_singleton()->voxel_gi_set_normal_bias(probe, p_normal_bias);
+ normal_bias = p_normal_bias;
+}
+
+float VoxelGIData::get_normal_bias() const {
+ return normal_bias;
+}
+
+void VoxelGIData::set_interior(bool p_enable) {
+ RS::get_singleton()->voxel_gi_set_interior(probe, p_enable);
+ interior = p_enable;
+}
+
+bool VoxelGIData::is_interior() const {
+ return interior;
+}
+
+void VoxelGIData::set_use_two_bounces(bool p_enable) {
+ RS::get_singleton()->voxel_gi_set_use_two_bounces(probe, p_enable);
+ use_two_bounces = p_enable;
+}
+
+bool VoxelGIData::is_using_two_bounces() const {
+ return use_two_bounces;
+}
+
+RID VoxelGIData::get_rid() const {
+ return probe;
+}
+
+void VoxelGIData::_validate_property(PropertyInfo &property) const {
+ if (property.name == "anisotropy_strength") {
+ bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/global_illumination/voxel_gi/anisotropic");
+ if (!anisotropy_enabled) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+ }
+}
+
+void VoxelGIData::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("allocate", "to_cell_xform", "aabb", "octree_size", "octree_cells", "data_cells", "distance_field", "level_counts"), &VoxelGIData::allocate);
+
+ ClassDB::bind_method(D_METHOD("get_bounds"), &VoxelGIData::get_bounds);
+ ClassDB::bind_method(D_METHOD("get_octree_size"), &VoxelGIData::get_octree_size);
+ ClassDB::bind_method(D_METHOD("get_to_cell_xform"), &VoxelGIData::get_to_cell_xform);
+ ClassDB::bind_method(D_METHOD("get_octree_cells"), &VoxelGIData::get_octree_cells);
+ ClassDB::bind_method(D_METHOD("get_data_cells"), &VoxelGIData::get_data_cells);
+ ClassDB::bind_method(D_METHOD("get_level_counts"), &VoxelGIData::get_level_counts);
+
+ ClassDB::bind_method(D_METHOD("set_dynamic_range", "dynamic_range"), &VoxelGIData::set_dynamic_range);
+ ClassDB::bind_method(D_METHOD("get_dynamic_range"), &VoxelGIData::get_dynamic_range);
+
+ ClassDB::bind_method(D_METHOD("set_energy", "energy"), &VoxelGIData::set_energy);
+ ClassDB::bind_method(D_METHOD("get_energy"), &VoxelGIData::get_energy);
+
+ ClassDB::bind_method(D_METHOD("set_bias", "bias"), &VoxelGIData::set_bias);
+ ClassDB::bind_method(D_METHOD("get_bias"), &VoxelGIData::get_bias);
+
+ ClassDB::bind_method(D_METHOD("set_normal_bias", "bias"), &VoxelGIData::set_normal_bias);
+ ClassDB::bind_method(D_METHOD("get_normal_bias"), &VoxelGIData::get_normal_bias);
+
+ ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &VoxelGIData::set_propagation);
+ ClassDB::bind_method(D_METHOD("get_propagation"), &VoxelGIData::get_propagation);
+
+ ClassDB::bind_method(D_METHOD("set_anisotropy_strength", "strength"), &VoxelGIData::set_anisotropy_strength);
+ ClassDB::bind_method(D_METHOD("get_anisotropy_strength"), &VoxelGIData::get_anisotropy_strength);
+
+ ClassDB::bind_method(D_METHOD("set_ao", "ao"), &VoxelGIData::set_ao);
+ ClassDB::bind_method(D_METHOD("get_ao"), &VoxelGIData::get_ao);
+
+ ClassDB::bind_method(D_METHOD("set_ao_size", "strength"), &VoxelGIData::set_ao_size);
+ ClassDB::bind_method(D_METHOD("get_ao_size"), &VoxelGIData::get_ao_size);
+
+ ClassDB::bind_method(D_METHOD("set_interior", "interior"), &VoxelGIData::set_interior);
+ ClassDB::bind_method(D_METHOD("is_interior"), &VoxelGIData::is_interior);
+
+ ClassDB::bind_method(D_METHOD("set_use_two_bounces", "enable"), &VoxelGIData::set_use_two_bounces);
+ ClassDB::bind_method(D_METHOD("is_using_two_bounces"), &VoxelGIData::is_using_two_bounces);
+
+ ClassDB::bind_method(D_METHOD("_set_data", "data"), &VoxelGIData::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"), &VoxelGIData::_get_data);
+
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_dynamic_range", "get_dynamic_range");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_energy", "get_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_bias", "get_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_normal_bias", "get_normal_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anisotropy_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy_strength", "get_anisotropy_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao", "get_ao");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_size", "get_ao_size");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_two_bounces"), "set_use_two_bounces", "is_using_two_bounces");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
+}
+
+VoxelGIData::VoxelGIData() {
+ probe = RS::get_singleton()->voxel_gi_create();
+}
+
+VoxelGIData::~VoxelGIData() {
+ RS::get_singleton()->free(probe);
+}
+
+//////////////////////
+//////////////////////
+
+void VoxelGI::set_probe_data(const Ref<VoxelGIData> &p_data) {
+ if (p_data.is_valid()) {
+ RS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid());
+ } else {
+ RS::get_singleton()->instance_set_base(get_instance(), RID());
+ }
+
+ probe_data = p_data;
+}
+
+Ref<VoxelGIData> VoxelGI::get_probe_data() const {
+ return probe_data;
+}
+
+void VoxelGI::set_subdiv(Subdiv p_subdiv) {
+ ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX);
+ subdiv = p_subdiv;
+ update_gizmo();
+}
+
+VoxelGI::Subdiv VoxelGI::get_subdiv() const {
+ return subdiv;
+}
+
+void VoxelGI::set_extents(const Vector3 &p_extents) {
+ extents = p_extents;
+ update_gizmo();
+}
+
+Vector3 VoxelGI::get_extents() const {
+ return extents;
+}
+
+void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
+ if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) {
+ Ref<Mesh> mesh = mi->get_mesh();
+ if (mesh.is_valid()) {
+ AABB aabb = mesh->get_aabb();
+
+ Transform3D xf = get_global_transform().affine_inverse() * mi->get_global_transform();
+
+ if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
+ PlotMesh pm;
+ pm.local_xform = xf;
+ pm.mesh = mesh;
+ for (int i = 0; i < mesh->get_surface_count(); i++) {
+ pm.instance_materials.push_back(mi->get_surface_override_material(i));
+ }
+ pm.override_material = mi->get_material_override();
+ plot_meshes.push_back(pm);
+ }
+ }
+ }
+
+ Node3D *s = Object::cast_to<Node3D>(p_at_node);
+ if (s) {
+ if (s->is_visible_in_tree()) {
+ Array meshes = p_at_node->call("get_meshes");
+ for (int i = 0; i < meshes.size(); i += 2) {
+ Transform3D mxf = meshes[i];
+ Ref<Mesh> mesh = meshes[i + 1];
+ if (!mesh.is_valid()) {
+ continue;
+ }
+
+ AABB aabb = mesh->get_aabb();
+
+ Transform3D xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf);
+
+ if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
+ PlotMesh pm;
+ pm.local_xform = xf;
+ pm.mesh = mesh;
+ plot_meshes.push_back(pm);
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < p_at_node->get_child_count(); i++) {
+ Node *child = p_at_node->get_child(i);
+ _find_meshes(child, plot_meshes);
+ }
+}
+
+VoxelGI::BakeBeginFunc VoxelGI::bake_begin_function = nullptr;
+VoxelGI::BakeStepFunc VoxelGI::bake_step_function = nullptr;
+VoxelGI::BakeEndFunc VoxelGI::bake_end_function = nullptr;
+
+Vector3i VoxelGI::get_estimated_cell_size() const {
+ static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
+ int cell_subdiv = subdiv_value[subdiv];
+ int axis_cell_size[3];
+ AABB bounds = AABB(-extents, extents * 2.0);
+ int longest_axis = bounds.get_longest_axis_index();
+ axis_cell_size[longest_axis] = 1 << cell_subdiv;
+
+ for (int i = 0; i < 3; i++) {
+ if (i == longest_axis) {
+ continue;
+ }
+
+ axis_cell_size[i] = axis_cell_size[longest_axis];
+ float axis_size = bounds.size[longest_axis];
+
+ //shrink until fit subdiv
+ while (axis_size / 2.0 >= bounds.size[i]) {
+ axis_size /= 2.0;
+ axis_cell_size[i] >>= 1;
+ }
+ }
+
+ return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]);
+}
+
+void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) {
+ static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
+
+ p_from_node = p_from_node ? p_from_node : get_parent();
+ ERR_FAIL_NULL(p_from_node);
+
+ Voxelizer baker;
+
+ baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0));
+
+ List<PlotMesh> mesh_list;
+
+ _find_meshes(p_from_node, mesh_list);
+
+ if (bake_begin_function) {
+ bake_begin_function(mesh_list.size() + 1);
+ }
+
+ int pmc = 0;
+
+ for (List<PlotMesh>::Element *E = mesh_list.front(); E; E = E->next()) {
+ if (bake_step_function) {
+ bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size()));
+ }
+
+ pmc++;
+
+ baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material);
+ }
+ if (bake_step_function) {
+ bake_step_function(pmc++, RTR("Finishing Plot"));
+ }
+
+ baker.end_bake();
+
+ //create the data for visual server
+
+ if (p_create_visual_debug) {
+ MultiMeshInstance3D *mmi = memnew(MultiMeshInstance3D);
+ mmi->set_multimesh(baker.create_debug_multimesh());
+ add_child(mmi);
+#ifdef TOOLS_ENABLED
+ if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) {
+ mmi->set_owner(this);
+ } else {
+ mmi->set_owner(get_owner());
+ }
+#else
+ mmi->set_owner(get_owner());
+#endif
+
+ } else {
+ Ref<VoxelGIData> probe_data = get_probe_data();
+
+ if (probe_data.is_null()) {
+ probe_data.instance();
+ }
+
+ if (bake_step_function) {
+ bake_step_function(pmc++, RTR("Generating Distance Field"));
+ }
+
+ Vector<uint8_t> df = baker.get_sdf_3d_image();
+
+ probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count());
+
+ set_probe_data(probe_data);
+#ifdef TOOLS_ENABLED
+ probe_data->set_edited(true); //so it gets saved
+#endif
+ }
+
+ if (bake_end_function) {
+ bake_end_function();
+ }
+
+ notify_property_list_changed(); //bake property may have changed
+}
+
+void VoxelGI::_debug_bake() {
+ bake(nullptr, true);
+}
+
+AABB VoxelGI::get_aabb() const {
+ return AABB(-extents, extents * 2);
+}
+
+Vector<Face3> VoxelGI::get_faces(uint32_t p_usage_flags) const {
+ return Vector<Face3>();
+}
+
+TypedArray<String> VoxelGI::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (RenderingServer::get_singleton()->is_low_end()) {
+ warnings.push_back(TTR("VoxelGIs are not supported by the GLES2 video driver.\nUse a LightmapGI instead."));
+ } else if (probe_data.is_null()) {
+ warnings.push_back(TTR("No VoxelGI data set, so this node is disabled. Bake static objects to enable GI."));
+ }
+ return warnings;
+}
+
+void VoxelGI::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &VoxelGI::set_probe_data);
+ ClassDB::bind_method(D_METHOD("get_probe_data"), &VoxelGI::get_probe_data);
+
+ ClassDB::bind_method(D_METHOD("set_subdiv", "subdiv"), &VoxelGI::set_subdiv);
+ ClassDB::bind_method(D_METHOD("get_subdiv"), &VoxelGI::get_subdiv);
+
+ ClassDB::bind_method(D_METHOD("set_extents", "extents"), &VoxelGI::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"), &VoxelGI::get_extents);
+
+ ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &VoxelGI::bake, DEFVAL(Variant()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("debug_bake"), &VoxelGI::_debug_bake);
+ ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "VoxelGIData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
+
+ BIND_ENUM_CONSTANT(SUBDIV_64);
+ BIND_ENUM_CONSTANT(SUBDIV_128);
+ BIND_ENUM_CONSTANT(SUBDIV_256);
+ BIND_ENUM_CONSTANT(SUBDIV_512);
+ BIND_ENUM_CONSTANT(SUBDIV_MAX);
+}
+
+VoxelGI::VoxelGI() {
+ voxel_gi = RS::get_singleton()->voxel_gi_create();
+ set_disable_scale(true);
+}
+
+VoxelGI::~VoxelGI() {
+ RS::get_singleton()->free(voxel_gi);
+}
diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h
new file mode 100644
index 0000000000..5b9ee28b33
--- /dev/null
+++ b/scene/3d/voxel_gi.h
@@ -0,0 +1,176 @@
+/*************************************************************************/
+/* voxel_gi.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef VOXEL_GI_H
+#define VOXEL_GI_H
+
+#include "multimesh_instance_3d.h"
+#include "scene/3d/visual_instance_3d.h"
+
+class VoxelGIData : public Resource {
+ GDCLASS(VoxelGIData, Resource);
+
+ RID probe;
+
+ void _set_data(const Dictionary &p_data);
+ Dictionary _get_data() const;
+
+ Transform3D to_cell_xform;
+ AABB bounds;
+ Vector3 octree_size;
+
+ float dynamic_range = 4.0;
+ float energy = 1.0;
+ float bias = 1.5;
+ float normal_bias = 0.0;
+ float propagation = 0.7;
+ float anisotropy_strength = 0.5;
+ float ao = 0.0;
+ float ao_size = 0.5;
+ bool interior = false;
+ bool use_two_bounces = false;
+
+protected:
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
+
+public:
+ void allocate(const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
+ AABB get_bounds() const;
+ Vector3 get_octree_size() const;
+ Vector<uint8_t> get_octree_cells() const;
+ Vector<uint8_t> get_data_cells() const;
+ Vector<uint8_t> get_distance_field() const;
+ Vector<int> get_level_counts() const;
+ Transform3D get_to_cell_xform() const;
+
+ void set_dynamic_range(float p_range);
+ float get_dynamic_range() const;
+
+ void set_propagation(float p_propagation);
+ float get_propagation() const;
+
+ void set_anisotropy_strength(float p_anisotropy_strength);
+ float get_anisotropy_strength() const;
+
+ void set_ao(float p_ao);
+ float get_ao() const;
+
+ void set_ao_size(float p_ao_size);
+ float get_ao_size() const;
+
+ void set_energy(float p_energy);
+ float get_energy() const;
+
+ void set_bias(float p_bias);
+ float get_bias() const;
+
+ void set_normal_bias(float p_normal_bias);
+ float get_normal_bias() const;
+
+ void set_interior(bool p_enable);
+ bool is_interior() const;
+
+ void set_use_two_bounces(bool p_enable);
+ bool is_using_two_bounces() const;
+
+ virtual RID get_rid() const override;
+
+ VoxelGIData();
+ ~VoxelGIData();
+};
+
+class VoxelGI : public VisualInstance3D {
+ GDCLASS(VoxelGI, VisualInstance3D);
+
+public:
+ enum Subdiv {
+ SUBDIV_64,
+ SUBDIV_128,
+ SUBDIV_256,
+ SUBDIV_512,
+ SUBDIV_MAX
+
+ };
+
+ typedef void (*BakeBeginFunc)(int);
+ typedef void (*BakeStepFunc)(int, const String &);
+ typedef void (*BakeEndFunc)();
+
+private:
+ Ref<VoxelGIData> probe_data;
+
+ RID voxel_gi;
+
+ Subdiv subdiv = SUBDIV_128;
+ Vector3 extents = Vector3(10, 10, 10);
+
+ struct PlotMesh {
+ Ref<Material> override_material;
+ Vector<Ref<Material>> instance_materials;
+ Ref<Mesh> mesh;
+ Transform3D local_xform;
+ };
+
+ void _find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes);
+ void _debug_bake();
+
+protected:
+ static void _bind_methods();
+
+public:
+ static BakeBeginFunc bake_begin_function;
+ static BakeStepFunc bake_step_function;
+ static BakeEndFunc bake_end_function;
+
+ void set_probe_data(const Ref<VoxelGIData> &p_data);
+ Ref<VoxelGIData> get_probe_data() const;
+
+ void set_subdiv(Subdiv p_subdiv);
+ Subdiv get_subdiv() const;
+
+ void set_extents(const Vector3 &p_extents);
+ Vector3 get_extents() const;
+ Vector3i get_estimated_cell_size() const;
+
+ void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false);
+
+ virtual AABB get_aabb() const override;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
+
+ TypedArray<String> get_configuration_warnings() const override;
+
+ VoxelGI();
+ ~VoxelGI();
+};
+
+VARIANT_ENUM_CAST(VoxelGI::Subdiv)
+
+#endif // VOXEL_GI_H
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index 1b9ce0201f..ee0c3fe9b6 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -378,7 +378,7 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material
return mc;
}
-void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material) {
+void Voxelizer::plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material) {
for (int i = 0; i < p_mesh->get_surface_count(); i++) {
if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
continue; //only triangles
@@ -647,11 +647,11 @@ void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) {
po2_bounds.size[i] = po2_bounds.size[longest_axis];
}
- Transform to_bounds;
+ Transform3D to_bounds;
to_bounds.basis.scale(Vector3(po2_bounds.size[longest_axis], po2_bounds.size[longest_axis], po2_bounds.size[longest_axis]));
to_bounds.origin = po2_bounds.position;
- Transform to_grid;
+ Transform3D to_grid;
to_grid.basis.scale(Vector3(axis_cell_size[longest_axis], axis_cell_size[longest_axis], axis_cell_size[longest_axis]));
to_cell_space = to_grid * to_bounds.affine_inverse();
@@ -668,19 +668,19 @@ void Voxelizer::end_bake() {
//create the data for visual server
-int Voxelizer::get_gi_probe_octree_depth() const {
+int Voxelizer::get_voxel_gi_octree_depth() const {
return cell_subdiv;
}
-Vector3i Voxelizer::get_giprobe_octree_size() const {
+Vector3i Voxelizer::get_voxel_gi_octree_size() const {
return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]);
}
-int Voxelizer::get_giprobe_cell_count() const {
+int Voxelizer::get_voxel_gi_cell_count() const {
return bake_cells.size();
}
-Vector<uint8_t> Voxelizer::get_giprobe_octree_cells() const {
+Vector<uint8_t> Voxelizer::get_voxel_gi_octree_cells() const {
Vector<uint8_t> data;
data.resize((8 * 4) * bake_cells.size()); //8 uint32t values
{
@@ -700,7 +700,7 @@ Vector<uint8_t> Voxelizer::get_giprobe_octree_cells() const {
return data;
}
-Vector<uint8_t> Voxelizer::get_giprobe_data_cells() const {
+Vector<uint8_t> Voxelizer::get_voxel_gi_data_cells() const {
Vector<uint8_t> data;
data.resize((4 * 4) * bake_cells.size()); //8 uint32t values
{
@@ -755,7 +755,7 @@ Vector<uint8_t> Voxelizer::get_giprobe_data_cells() const {
return data;
}
-Vector<int> Voxelizer::get_giprobe_level_cell_count() const {
+Vector<int> Voxelizer::get_voxel_gi_level_cell_count() const {
uint32_t cell_count = bake_cells.size();
const Cell *cells = bake_cells.ptr();
Vector<int> level_count;
@@ -819,7 +819,7 @@ static void edt(float *f, int stride, int n) {
#undef square
Vector<uint8_t> Voxelizer::get_sdf_3d_image() const {
- Vector3i octree_size = get_giprobe_octree_size();
+ Vector3i octree_size = get_voxel_gi_octree_size();
uint32_t float_count = octree_size.x * octree_size.y * octree_size.z;
float *work_memory = memnew_arr(float, float_count);
@@ -891,7 +891,7 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const {
void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx) {
if (p_level == cell_subdiv - 1) {
Vector3 center = p_aabb.position + p_aabb.size * 0.5;
- Transform xform;
+ Transform3D xform;
xform.origin = center;
xform.basis.scale(p_aabb.size * 0.5);
p_multimesh->set_instance_transform(idx, xform);
@@ -1002,7 +1002,7 @@ Ref<MultiMesh> Voxelizer::create_debug_multimesh() {
return mm;
}
-Transform Voxelizer::get_to_cell_space_xform() const {
+Transform3D Voxelizer::get_to_cell_space_xform() const {
return to_cell_space;
}
diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h
index 87f949e7db..e500d2d4c3 100644
--- a/scene/3d/voxelizer.h
+++ b/scene/3d/voxelizer.h
@@ -93,7 +93,7 @@ private:
AABB po2_bounds;
int axis_cell_size[3] = {};
- Transform to_cell_space;
+ Transform3D to_cell_space;
int color_scan_cell_width = 4;
int bake_texture_size = 128;
@@ -114,20 +114,20 @@ private:
public:
void begin_bake(int p_subdiv, const AABB &p_bounds);
- void plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material);
+ void plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material);
void end_bake();
- int get_gi_probe_octree_depth() const;
- Vector3i get_giprobe_octree_size() const;
- int get_giprobe_cell_count() const;
- Vector<uint8_t> get_giprobe_octree_cells() const;
- Vector<uint8_t> get_giprobe_data_cells() const;
- Vector<int> get_giprobe_level_cell_count() const;
+ int get_voxel_gi_octree_depth() const;
+ Vector3i get_voxel_gi_octree_size() const;
+ int get_voxel_gi_cell_count() const;
+ Vector<uint8_t> get_voxel_gi_octree_cells() const;
+ Vector<uint8_t> get_voxel_gi_data_cells() const;
+ Vector<int> get_voxel_gi_level_cell_count() const;
Vector<uint8_t> get_sdf_3d_image() const;
Ref<MultiMesh> create_debug_multimesh();
- Transform get_to_cell_space_xform() const;
+ Transform3D get_to_cell_space_xform() const;
Voxelizer();
};
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index b5037f9be7..4f2c816934 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -86,7 +86,8 @@ Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const {
Vector2 cpos = get_viewport()->get_camera_coords(p_pos);
Vector3 ray;
- CameraMatrix cm = xr_interface->get_projection_for_eye(XRInterface::EYE_MONO, viewport_size.aspect(), get_near(), get_far());
+ // Just use the first view, if multiple views are supported this function has no good result
+ CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
Vector2 screen_he = cm.get_viewport_half_extents();
ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -get_near()).normalized();
@@ -108,7 +109,8 @@ Point2 XRCamera3D::unproject_position(const Vector3 &p_pos) const {
Size2 viewport_size = get_viewport()->get_visible_rect().size;
- CameraMatrix cm = xr_interface->get_projection_for_eye(XRInterface::EYE_MONO, viewport_size.aspect(), get_near(), get_far());
+ // Just use the first view, if multiple views are supported this function has no good result
+ CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
Plane p(get_camera_transform().xform_inv(p_pos), 1.0);
@@ -137,7 +139,8 @@ Vector3 XRCamera3D::project_position(const Point2 &p_point, float p_z_depth) con
Size2 viewport_size = get_viewport()->get_visible_rect().size;
- CameraMatrix cm = xr_interface->get_projection_for_eye(XRInterface::EYE_MONO, viewport_size.aspect(), get_near(), get_far());
+ // Just use the first view, if multiple views are supported this function has no good result
+ CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
Vector2 vp_he = cm.get_viewport_half_extents();
@@ -165,7 +168,8 @@ Vector<Plane> XRCamera3D::get_frustum() const {
ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>());
Size2 viewport_size = get_viewport()->get_visible_rect().size;
- CameraMatrix cm = xr_interface->get_projection_for_eye(XRInterface::EYE_MONO, viewport_size.aspect(), get_near(), get_far());
+ // TODO Just use the first view for now, this is mostly for debugging so we may look into using our combined projection here.
+ CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
return cm.get_projection_planes(get_camera_transform());
};
@@ -397,7 +401,7 @@ void XRAnchor3D::_notification(int p_what) {
is_active = false;
} else {
is_active = true;
- Transform transform;
+ Transform3D transform;
// we'll need our world_scale
real_t world_scale = xr_server->get_world_scale();
@@ -493,7 +497,7 @@ TypedArray<String> XRAnchor3D::get_configuration_warnings() const {
};
Plane XRAnchor3D::get_plane() const {
- Vector3 location = get_translation();
+ Vector3 location = get_position();
Basis orientation = get_transform().basis;
Plane plane(location, orientation.get_axis(1).normalized());
@@ -516,6 +520,11 @@ TypedArray<String> XROrigin3D::get_configuration_warnings() const {
}
}
+ bool xr_enabled = GLOBAL_GET("rendering/xr/enabled");
+ if (!xr_enabled) {
+ warnings.push_back(TTR("XR is not enabled in rendering project settings. Stereoscopic output is not supported unless this is enabled."));
+ }
+
return warnings;
};
@@ -571,7 +580,7 @@ void XROrigin3D::_notification(int p_what) {
Ref<XRInterface> xr_interface = xr_server->get_primary_interface();
if (xr_interface.is_valid() && tracked_camera != nullptr) {
// get our positioning transform for our headset
- Transform t = xr_interface->get_transform_for_eye(XRInterface::EYE_MONO, Transform());
+ Transform3D t = xr_interface->get_camera_transform();
// now apply this to our camera
tracked_camera->set_transform(t);
diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp
index 689acdd57b..b8980fd56b 100644
--- a/scene/animation/animation_cache.cpp
+++ b/scene/animation/animation_cache.cpp
@@ -80,10 +80,11 @@ void AnimationCache::_update_cache() {
Ref<Resource> res;
- if (animation->track_get_type(i) == Animation::TYPE_TRANSFORM) {
+ if (animation->track_get_type(i) == Animation::TYPE_TRANSFORM3D) {
+#ifndef _3D_DISABLED
if (np.get_subname_count() > 1) {
path_cache.push_back(Path());
- ERR_CONTINUE_MSG(animation->track_get_type(i) == Animation::TYPE_TRANSFORM, "Transform tracks can't have a subpath '" + np + "'.");
+ ERR_CONTINUE_MSG(animation->track_get_type(i) == Animation::TYPE_TRANSFORM3D, "Transform tracks can't have a subpath '" + np + "'.");
}
Node3D *sp = Object::cast_to<Node3D>(node);
@@ -113,8 +114,8 @@ void AnimationCache::_update_cache() {
path.skeleton = sk;
}
- path.spatial = sp;
-
+ path.node_3d = sp;
+#endif // _3D_DISABLED
} else {
if (np.get_subname_count() > 0) {
RES res2;
@@ -167,7 +168,7 @@ void AnimationCache::_update_cache() {
cache_valid = true;
}
-void AnimationCache::set_track_transform(int p_idx, const Transform &p_transform) {
+void AnimationCache::set_track_transform(int p_idx, const Transform3D &p_transform) {
if (cache_dirty) {
_update_cache();
}
@@ -179,14 +180,16 @@ void AnimationCache::set_track_transform(int p_idx, const Transform &p_transform
return;
}
+#ifndef _3D_DISABLED
ERR_FAIL_COND(!p.node);
- ERR_FAIL_COND(!p.spatial);
+ ERR_FAIL_COND(!p.node_3d);
if (p.skeleton) {
p.skeleton->set_bone_pose(p.bone_idx, p_transform);
} else {
- p.spatial->set_transform(p_transform);
+ p.node_3d->set_transform(p_transform);
}
+#endif // _3D_DISABLED
}
void AnimationCache::set_track_value(int p_idx, const Variant &p_value) {
@@ -231,11 +234,11 @@ void AnimationCache::set_all(float p_time, float p_delta) {
int tc = animation->get_track_count();
for (int i = 0; i < tc; i++) {
switch (animation->track_get_type(i)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
Vector3 loc, scale;
- Quat rot;
+ Quaternion rot;
animation->transform_track_interpolate(i, p_time, &loc, &rot, &scale);
- Transform tr(Basis(rot), loc);
+ Transform3D tr(Basis(rot), loc);
tr.basis.scale(scale);
set_track_transform(i, tr);
diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h
index 07c9d09ae0..c856e644f7 100644
--- a/scene/animation/animation_cache.h
+++ b/scene/animation/animation_cache.h
@@ -40,9 +40,11 @@ class AnimationCache : public Object {
struct Path {
RES resource;
Object *object = nullptr;
- Skeleton3D *skeleton = nullptr; // haxor
+#ifndef _3D_DISABLED
+ Skeleton3D *skeleton = nullptr;
+ Node3D *node_3d = nullptr;
+#endif // _3D_DISABLED
Node *node = nullptr;
- Node3D *spatial = nullptr;
int bone_idx = -1;
Vector<StringName> subpath;
@@ -67,7 +69,7 @@ protected:
static void _bind_methods();
public:
- void set_track_transform(int p_idx, const Transform &p_transform);
+ void set_track_transform(int p_idx, const Transform3D &p_transform);
void set_track_value(int p_idx, const Variant &p_value);
void call_track(int p_idx, const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index 246fff6d57..65918a2989 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -115,7 +115,7 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_priority", "priority"), &AnimationNodeStateMachineTransition::set_priority);
ClassDB::bind_method(D_METHOD("get_priority"), &AnimationNodeStateMachineTransition::get_priority);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,AtEnd"), "set_switch_mode", "get_switch_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,At End"), "set_switch_mode", "get_switch_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_advance"), "set_auto_advance", "has_auto_advance");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "advance_condition"), "set_advance_condition", "get_advance_condition");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,240,0.01"), "set_xfade_time", "get_xfade_time");
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 0c1798a876..2d565fc47a 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -252,6 +252,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
ObjectID id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id();
int bone_idx = -1;
+#ifndef _3D_DISABLED
if (a->track_get_path(i).get_subname_count() == 1 && Object::cast_to<Skeleton3D>(child)) {
Skeleton3D *sk = Object::cast_to<Skeleton3D>(child);
bone_idx = sk->find_bone(a->track_get_path(i).get_subname(0));
@@ -259,6 +260,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
continue;
}
}
+#endif // _3D_DISABLED
{
if (!child->is_connected("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed))) {
@@ -279,11 +281,12 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
p_anim->node_cache[i]->node = child;
p_anim->node_cache[i]->resource = resource;
p_anim->node_cache[i]->node_2d = Object::cast_to<Node2D>(child);
- if (a->track_get_type(i) == Animation::TYPE_TRANSFORM) {
+#ifndef _3D_DISABLED
+ if (a->track_get_type(i) == Animation::TYPE_TRANSFORM3D) {
// special cases and caches for transform tracks
- // cache spatial
- p_anim->node_cache[i]->spatial = Object::cast_to<Node3D>(child);
+ // cache node_3d
+ p_anim->node_cache[i]->node_3d = Object::cast_to<Node3D>(child);
// cache skeleton
p_anim->node_cache[i]->skeleton = Object::cast_to<Skeleton3D>(child);
if (p_anim->node_cache[i]->skeleton) {
@@ -294,7 +297,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
if (p_anim->node_cache[i]->bone_idx < 0) {
// broken track (nonexistent bone)
p_anim->node_cache[i]->skeleton = nullptr;
- p_anim->node_cache[i]->spatial = nullptr;
+ p_anim->node_cache[i]->node_3d = nullptr;
ERR_CONTINUE(p_anim->node_cache[i]->bone_idx < 0);
}
} else {
@@ -303,6 +306,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
}
}
}
+#endif // _3D_DISABLED
if (a->track_get_type(i) == Animation::TYPE_VALUE) {
if (!p_anim->node_cache[i]->property_anim.has(a->track_get_path(i).get_concatenated_subnames())) {
@@ -366,13 +370,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
}
switch (a->track_get_type(i)) {
- case Animation::TYPE_TRANSFORM: {
- if (!nc->spatial) {
+ case Animation::TYPE_TRANSFORM3D: {
+#ifndef _3D_DISABLED
+ if (!nc->node_3d) {
continue;
}
Vector3 loc;
- Quat rot;
+ Quaternion rot;
Vector3 scale;
Error err = a->transform_track_interpolate(i, p_time, &loc, &rot, &scale);
@@ -395,7 +400,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
nc->rot_accum = nc->rot_accum.slerp(rot, p_interp);
nc->scale_accum = nc->scale_accum.lerp(scale, p_interp);
}
-
+#endif // _3D_DISABLED
} break;
case Animation::TYPE_VALUE: {
if (!nc->node) {
@@ -838,20 +843,21 @@ void AnimationPlayer::_animation_process2(float p_delta, bool p_started) {
void AnimationPlayer::_animation_update_transforms() {
{
- Transform t;
+ Transform3D t;
for (int i = 0; i < cache_update_size; i++) {
TrackNodeCache *nc = cache_update[i];
ERR_CONTINUE(nc->accum_pass != accum_pass);
t.origin = nc->loc_accum;
- t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum);
+ t.basis.set_quaternion_scale(nc->rot_accum, nc->scale_accum);
+#ifndef _3D_DISABLED
if (nc->skeleton && nc->bone_idx >= 0) {
nc->skeleton->set_bone_pose(nc->bone_idx, t);
-
- } else if (nc->spatial) {
- nc->spatial->set_transform(t);
+ } else if (nc->node_3d) {
+ nc->node_3d->set_transform(t);
}
+#endif // _3D_DISABLED
}
}
@@ -1523,11 +1529,11 @@ Ref<AnimatedValuesBackup> AnimationPlayer::backup_animated_values(Node *p_root_o
entry.value = nc->skeleton->get_bone_pose(nc->bone_idx);
backup->entries.push_back(entry);
} else {
- if (nc->spatial) {
+ if (nc->node_3d) {
AnimatedValuesBackup::Entry entry;
- entry.object = nc->spatial;
+ entry.object = nc->node_3d;
entry.subpath.push_back("transform");
- entry.value = nc->spatial->get_transform();
+ entry.value = nc->node_3d->get_transform();
entry.bone_idx = -1;
backup->entries.push_back(entry);
} else {
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 2a1821c215..7cd9de1fa1 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -37,8 +37,8 @@
#include "scene/resources/animation.h"
#ifdef TOOLS_ENABLED
-class AnimatedValuesBackup : public Reference {
- GDCLASS(AnimatedValuesBackup, Reference);
+class AnimatedValuesBackup : public RefCounted {
+ GDCLASS(AnimatedValuesBackup, RefCounted);
struct Entry {
Object *object = nullptr;
@@ -93,14 +93,16 @@ private:
uint32_t id = 0;
RES resource;
Node *node = nullptr;
- Node3D *spatial = nullptr;
Node2D *node_2d = nullptr;
+#ifndef _3D_DISABLED
+ Node3D *node_3d = nullptr;
Skeleton3D *skeleton = nullptr;
+#endif // _3D_DISABLED
int bone_idx = -1;
// accumulated transforms
Vector3 loc_accum;
- Quat rot_accum;
+ Quaternion rot_accum;
Vector3 scale_accum;
uint64_t accum_pass = 0;
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 2ad871ba61..6fac70bdd5 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -37,7 +37,7 @@
void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const {
if (get_script_instance()) {
- Array parameters = get_script_instance()->call("get_parameter_list");
+ Array parameters = get_script_instance()->call("_get_parameter_list");
for (int i = 0; i < parameters.size(); i++) {
Dictionary d = parameters[i];
ERR_CONTINUE(d.is_empty());
@@ -48,7 +48,7 @@ void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const {
Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter) const {
if (get_script_instance()) {
- return get_script_instance()->call("get_parameter_default_value", p_parameter);
+ return get_script_instance()->call("_get_parameter_default_value", p_parameter);
}
return Variant();
}
@@ -73,7 +73,7 @@ Variant AnimationNode::get_parameter(const StringName &p_name) const {
void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
if (get_script_instance()) {
- Dictionary cn = get_script_instance()->call("get_child_nodes");
+ Dictionary cn = get_script_instance()->call("_get_child_nodes");
List<Variant> keys;
cn.get_key_list(&keys);
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
@@ -299,7 +299,7 @@ String AnimationNode::get_input_name(int p_input) {
String AnimationNode::get_caption() const {
if (get_script_instance()) {
- return get_script_instance()->call("get_caption");
+ return get_script_instance()->call("_get_caption");
}
return "Node";
@@ -330,7 +330,7 @@ void AnimationNode::remove_input(int p_index) {
float AnimationNode::process(float p_time, bool p_seek) {
if (get_script_instance()) {
- return get_script_instance()->call("process", p_time, p_seek);
+ return get_script_instance()->call("_process", p_time, p_seek);
}
return 0;
@@ -357,6 +357,10 @@ bool AnimationNode::is_path_filtered(const NodePath &p_path) const {
}
bool AnimationNode::has_filter() const {
+ if (get_script_instance()) {
+ return get_script_instance()->call("_has_filter");
+ }
+
return false;
}
@@ -387,7 +391,7 @@ void AnimationNode::_validate_property(PropertyInfo &property) const {
Ref<AnimationNode> AnimationNode::get_child_by_name(const StringName &p_name) {
if (get_script_instance()) {
- return get_script_instance()->call("get_child_by_name", p_name);
+ return get_script_instance()->call("_get_child_by_name", p_name);
}
return Ref<AnimationNode>();
}
@@ -418,17 +422,17 @@ void AnimationNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_filter_enabled", "is_filter_enabled");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "filters", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_filters", "_get_filters");
- BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "get_child_nodes"));
- BIND_VMETHOD(MethodInfo(Variant::ARRAY, "get_parameter_list"));
- BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_child_by_name", PropertyInfo(Variant::STRING, "name")));
+ BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "_get_child_nodes"));
+ BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_parameter_list"));
+ BIND_VMETHOD(MethodInfo(Variant::OBJECT, "_get_child_by_name", PropertyInfo(Variant::STRING, "name")));
{
- MethodInfo mi = MethodInfo(Variant::NIL, "get_parameter_default_value", PropertyInfo(Variant::STRING_NAME, "name"));
+ MethodInfo mi = MethodInfo(Variant::NIL, "_get_parameter_default_value", PropertyInfo(Variant::STRING_NAME, "name"));
mi.return_val.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
BIND_VMETHOD(mi);
}
- BIND_VMETHOD(MethodInfo("process", PropertyInfo(Variant::FLOAT, "time"), PropertyInfo(Variant::BOOL, "seek")));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "get_caption"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_filter"));
+ BIND_VMETHOD(MethodInfo("_process", PropertyInfo(Variant::FLOAT, "time"), PropertyInfo(Variant::BOOL, "seek")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_caption"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_filter"));
ADD_SIGNAL(MethodInfo("removed_from_graph"));
@@ -581,22 +585,23 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track = track_value;
} break;
- case Animation::TYPE_TRANSFORM: {
- Node3D *spatial = Object::cast_to<Node3D>(child);
+ case Animation::TYPE_TRANSFORM3D: {
+#ifndef _3D_DISABLED
+ Node3D *node_3d = Object::cast_to<Node3D>(child);
- if (!spatial) {
- ERR_PRINT("AnimationTree: '" + String(E->get()) + "', transform track does not point to spatial: '" + String(path) + "'");
+ if (!node_3d) {
+ ERR_PRINT("AnimationTree: '" + String(E->get()) + "', transform track does not point to Node3D: '" + String(path) + "'");
continue;
}
TrackCacheTransform *track_xform = memnew(TrackCacheTransform);
- track_xform->spatial = spatial;
+ track_xform->node_3d = node_3d;
track_xform->skeleton = nullptr;
track_xform->bone_idx = -1;
- if (path.get_subname_count() == 1 && Object::cast_to<Skeleton3D>(spatial)) {
- Skeleton3D *sk = Object::cast_to<Skeleton3D>(spatial);
+ if (path.get_subname_count() == 1 && Object::cast_to<Skeleton3D>(node_3d)) {
+ Skeleton3D *sk = Object::cast_to<Skeleton3D>(node_3d);
track_xform->skeleton = sk;
int bone_idx = sk->find_bone(path.get_subname(0));
if (bone_idx != -1) {
@@ -604,11 +609,11 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
}
}
- track_xform->object = spatial;
+ track_xform->object = node_3d;
track_xform->object_id = track_xform->object->get_instance_id();
track = track_xform;
-
+#endif // _3D_DISABLED
} break;
case Animation::TYPE_METHOD: {
TrackCacheMethod *track_method = memnew(TrackCacheMethod);
@@ -718,7 +723,7 @@ void AnimationTree::_process_graph(float p_delta) {
//check all tracks, see if they need modification
- root_motion_transform = Transform();
+ root_motion_transform = Transform3D();
if (!root.is_valid()) {
ERR_PRINT("AnimationTree: root AnimationNode is not set, disabling playback.");
@@ -844,14 +849,15 @@ void AnimationTree::_process_graph(float p_delta) {
}
switch (track->type) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
+#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
if (track->root_motion) {
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
t->loc = Vector3();
- t->rot = Quat();
+ t->rot = Quaternion();
t->rot_blend_accum = 0;
t->scale = Vector3(1, 1, 1);
}
@@ -866,7 +872,7 @@ void AnimationTree::_process_graph(float p_delta) {
}
Vector3 loc[2];
- Quat rot[2];
+ Quaternion rot[2];
Vector3 scale[2];
if (prev_time > time) {
@@ -879,7 +885,7 @@ void AnimationTree::_process_graph(float p_delta) {
t->loc += (loc[1] - loc[0]) * blend;
t->scale += (scale[1] - scale[0]) * blend;
- Quat q = Quat().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
+ Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
t->rot = (t->rot * q).normalized();
prev_time = 0;
@@ -894,14 +900,14 @@ void AnimationTree::_process_graph(float p_delta) {
t->loc += (loc[1] - loc[0]) * blend;
t->scale += (scale[1] - scale[0]) * blend;
- Quat q = Quat().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
+ Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
t->rot = (t->rot * q).normalized();
prev_time = 0;
} else {
Vector3 loc;
- Quat rot;
+ Quaternion rot;
Vector3 scale;
Error err = a->transform_track_interpolate(i, time, &loc, &rot, &scale);
@@ -930,7 +936,7 @@ void AnimationTree::_process_graph(float p_delta) {
}
t->scale = t->scale.lerp(scale, blend);
}
-
+#endif // _3D_DISABLED
} break;
case Animation::TYPE_VALUE: {
TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
@@ -1188,13 +1194,14 @@ void AnimationTree::_process_graph(float p_delta) {
}
switch (track->type) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
+#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
- Transform xform;
+ Transform3D xform;
xform.origin = t->loc;
- xform.basis.set_quat_scale(t->rot, t->scale);
+ xform.basis.set_quaternion_scale(t->rot, t->scale);
if (t->root_motion) {
root_motion_transform = xform;
@@ -1206,9 +1213,9 @@ void AnimationTree::_process_graph(float p_delta) {
t->skeleton->set_bone_pose(t->bone_idx, xform);
} else if (!t->skeleton) {
- t->spatial->set_transform(xform);
+ t->node_3d->set_transform(xform);
}
-
+#endif // _3D_DISABLED
} break;
case Animation::TYPE_VALUE: {
TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
@@ -1311,7 +1318,7 @@ NodePath AnimationTree::get_root_motion_track() const {
return root_motion_track;
}
-Transform AnimationTree::get_root_motion_transform() const {
+Transform3D AnimationTree::get_root_motion_transform() const {
return root_motion_transform;
}
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 700ff1cb5b..60e0c7200a 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -184,16 +184,18 @@ private:
};
struct TrackCacheTransform : public TrackCache {
- Node3D *spatial = nullptr;
+#ifndef _3D_DISABLED
+ Node3D *node_3d = nullptr;
Skeleton3D *skeleton = nullptr;
+#endif // _3D_DISABLED
int bone_idx = -1;
Vector3 loc;
- Quat rot;
+ Quaternion rot;
float rot_blend_accum = 0.0;
Vector3 scale;
TrackCacheTransform() {
- type = Animation::TYPE_TRANSFORM;
+ type = Animation::TYPE_TRANSFORM3D;
}
};
@@ -257,7 +259,7 @@ private:
bool started = true;
NodePath root_motion_track;
- Transform root_motion_transform;
+ Transform3D root_motion_transform;
friend class AnimationNode;
bool properties_dirty = true;
@@ -308,7 +310,7 @@ public:
void set_root_motion_track(const NodePath &p_track);
NodePath get_root_motion_track() const;
- Transform get_root_motion_transform() const;
+ Transform3D get_root_motion_transform() const;
float get_connection_activity(const StringName &p_path, int p_connection) const;
void advance(float p_time);
diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp
index 9ee1f32581..b963cf5702 100644
--- a/scene/animation/root_motion_view.cpp
+++ b/scene/animation/root_motion_view.cpp
@@ -82,7 +82,7 @@ void RootMotionView::_notification(int p_what) {
}
if (p_what == NOTIFICATION_INTERNAL_PROCESS || p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
- Transform transform;
+ Transform3D transform;
if (has_node(path)) {
Node *node = get_node(path);
@@ -103,7 +103,7 @@ void RootMotionView::_notification(int p_what) {
}
}
- if (!first && transform == Transform()) {
+ if (!first && transform == Transform3D()) {
return;
}
diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h
index afcff6137f..4cd3c7b443 100644
--- a/scene/animation/root_motion_view.h
+++ b/scene/animation/root_motion_view.h
@@ -46,7 +46,7 @@ public:
bool first = true;
bool zero_y = true;
- Transform accumulated;
+ Transform3D accumulated;
private:
void _notification(int p_what);
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 2030808724..b4e597f75e 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -519,11 +519,11 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
result = r;
} break;
- case Variant::QUAT: {
+ case Variant::QUATERNION: {
// Get the quaternian for the initial and delta values
- Quat i = initial_val;
- Quat d = delta_val;
- Quat r;
+ Quaternion i = initial_val;
+ Quaternion d = delta_val;
+ Quaternion r;
// Execute the equation on the quaternian values and mutate the r quaternian
// This uses the custom APPLY_EQUATION macro defined above
@@ -571,11 +571,11 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
result = r;
} break;
- case Variant::TRANSFORM: {
+ case Variant::TRANSFORM3D: {
// Get the transforms for the initial and delta values
- Transform i = initial_val;
- Transform d = delta_val;
- Transform r;
+ Transform3D i = initial_val;
+ Transform3D d = delta_val;
+ Transform3D r;
// Execute the equation for each of the transforms and their origin and mutate the r transform
// This uses the custom APPLY_EQUATION macro defined above
@@ -1202,9 +1202,9 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final
delta_val = d;
} break;
- case Variant::QUAT:
+ case Variant::QUATERNION:
// Convert to quaternianls and find the delta
- delta_val = final_val.operator Quat() - initial_val.operator Quat();
+ delta_val = final_val.operator Quaternion() - initial_val.operator Quaternion();
break;
case Variant::AABB: {
@@ -1229,11 +1229,11 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final
f.elements[2][2] - i.elements[2][2]);
} break;
- case Variant::TRANSFORM: {
+ case Variant::TRANSFORM3D: {
// Build a new transform which is the difference between the initial and final values
- Transform i = initial_val;
- Transform f = final_val;
- Transform d;
+ Transform3D i = initial_val;
+ Transform3D f = final_val;
+ Transform3D d;
d.set(f.basis.elements[0][0] - i.basis.elements[0][0],
f.basis.elements[0][1] - i.basis.elements[0][1],
f.basis.elements[0][2] - i.basis.elements[0][2],
@@ -1266,10 +1266,10 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final
Variant::RECT2,
Variant::VECTOR3,
Variant::TRANSFORM2D,
- Variant::QUAT,
+ Variant::QUATERNION,
Variant::AABB,
Variant::BASIS,
- Variant::TRANSFORM,
+ Variant::TRANSFORM3D,
Variant::COLOR,
};
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index a1d4adcd41..11ce9b2ddc 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -98,7 +98,7 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
} else if (p_msg == "override_camera_3D:transform") {
ERR_FAIL_COND_V(p_args.size() < 5, ERR_INVALID_DATA);
- Transform transform = p_args[0];
+ Transform3D transform = p_args[0];
bool is_perspective = p_args[1];
float size_or_fov = p_args[2];
float near = p_args[3];
diff --git a/scene/gui/aspect_ratio_container.cpp b/scene/gui/aspect_ratio_container.cpp
index c7f6c0e2da..fb6fa9dec9 100644
--- a/scene/gui/aspect_ratio_container.cpp
+++ b/scene/gui/aspect_ratio_container.cpp
@@ -155,7 +155,7 @@ void AspectRatioContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_alignment_vertical"), &AspectRatioContainer::get_alignment_vertical);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio"), "set_ratio", "get_ratio");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Width controls height,Height controls width,Fit,Cover"), "set_stretch_mode", "get_stretch_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Width Controls Height,Height Controls Width,Fit,Cover"), "set_stretch_mode", "get_stretch_mode");
ADD_GROUP("Alignment", "alignment_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment_horizontal", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment_horizontal", "get_alignment_horizontal");
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index ac067aa001..66155958cf 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -98,17 +98,14 @@ void BaseButton::_notification(int p_what) {
}
if (p_what == NOTIFICATION_FOCUS_ENTER) {
- status.hovering = true;
update();
}
if (p_what == NOTIFICATION_FOCUS_EXIT) {
if (status.press_attempt) {
status.press_attempt = false;
- status.hovering = false;
update();
} else if (status.hovering) {
- status.hovering = false;
update();
}
}
@@ -175,10 +172,9 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
status.hovering = false;
}
}
- // pressed state should be correct with button_up signal
- emit_signal("button_up");
status.press_attempt = false;
status.pressing_inside = false;
+ emit_signal("button_up");
}
update();
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index b0bcde8865..c0df5271b4 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -533,7 +533,7 @@ void Button::_bind_methods() {
BIND_ENUM_CONSTANT(ALIGN_RIGHT);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_button_icon", "get_button_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 28a0ea0100..48e327ce78 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -30,6 +30,18 @@
#include "code_edit.h"
+#include "core/os/keyboard.h"
+#include "core/string/string_builder.h"
+#include "core/string/ustring.h"
+
+static bool _is_whitespace(char32_t c) {
+ return c == '\t' || c == ' ';
+}
+
+static bool _is_char(char32_t c) {
+ return !is_symbol(c);
+}
+
void CodeEdit::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
@@ -52,12 +64,325 @@ void CodeEdit::_notification(int p_what) {
folding_color = get_theme_color("code_folding_color");
can_fold_icon = get_theme_icon("can_fold");
folded_icon = get_theme_icon("folded");
+
+ code_completion_max_width = get_theme_constant("completion_max_width") * cache.font->get_char_size('x').x;
+ code_completion_max_lines = get_theme_constant("completion_lines");
+ code_completion_scroll_width = get_theme_constant("completion_scroll_width");
+ code_completion_scroll_color = get_theme_color("completion_scroll_color");
+ code_completion_background_color = get_theme_color("completion_background_color");
+ code_completion_selected_color = get_theme_color("completion_selected_color");
+ code_completion_existing_color = get_theme_color("completion_existing_color");
} break;
case NOTIFICATION_DRAW: {
+ RID ci = get_canvas_item();
+ const bool caret_visible = is_caret_visible();
+ const bool rtl = is_layout_rtl();
+ const int row_height = get_row_height();
+
+ bool code_completion_below = false;
+ if (caret_visible && code_completion_active && code_completion_options.size() > 0) {
+ Ref<StyleBox> csb = get_theme_stylebox("completion");
+
+ const int code_completion_options_count = code_completion_options.size();
+ const int lines = MIN(code_completion_options_count, code_completion_max_lines);
+ const int icon_hsep = get_theme_constant("hseparation", "ItemList");
+ const Size2 icon_area_size(row_height, row_height);
+
+ code_completion_rect.size.width = code_completion_longest_line + icon_hsep + icon_area_size.width + 2;
+ code_completion_rect.size.height = lines * row_height;
+
+ const Point2 caret_pos = get_caret_draw_pos();
+ const int total_height = csb->get_minimum_size().y + code_completion_rect.size.height;
+ if (caret_pos.y + row_height + total_height > get_size().height) {
+ code_completion_rect.position.y = (caret_pos.y - total_height - row_height) + cache.line_spacing;
+ } else {
+ code_completion_rect.position.y = caret_pos.y + (cache.line_spacing / 2.0f);
+ code_completion_below = true;
+ }
+
+ const int scroll_width = code_completion_options_count > code_completion_max_lines ? code_completion_scroll_width : 0;
+ const int code_completion_base_width = cache.font->get_string_size(code_completion_base).width;
+ if (caret_pos.x - code_completion_base_width + code_completion_rect.size.width + scroll_width > get_size().width) {
+ code_completion_rect.position.x = get_size().width - code_completion_rect.size.width - scroll_width;
+ } else {
+ code_completion_rect.position.x = caret_pos.x - code_completion_base_width;
+ }
+
+ draw_style_box(csb, Rect2(code_completion_rect.position - csb->get_offset(), code_completion_rect.size + csb->get_minimum_size() + Size2(scroll_width, 0)));
+ if (code_completion_background_color.a > 0.01) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(code_completion_rect.position, code_completion_rect.size + Size2(scroll_width, 0)), code_completion_background_color);
+ }
+
+ code_completion_line_ofs = CLAMP(code_completion_current_selected - lines / 2, 0, code_completion_options_count - lines);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(code_completion_rect.position.x, code_completion_rect.position.y + (code_completion_current_selected - code_completion_line_ofs) * row_height), Size2(code_completion_rect.size.width, row_height)), code_completion_selected_color);
+ draw_rect(Rect2(code_completion_rect.position + Vector2(icon_area_size.x + icon_hsep, 0), Size2(MIN(code_completion_base_width, code_completion_rect.size.width - (icon_area_size.x + icon_hsep)), code_completion_rect.size.height)), code_completion_existing_color);
+
+ for (int i = 0; i < lines; i++) {
+ int l = code_completion_line_ofs + i;
+ ERR_CONTINUE(l < 0 || l >= code_completion_options_count);
+
+ Ref<TextLine> tl;
+ tl.instance();
+ tl->add_string(code_completion_options[l].display, cache.font, cache.font_size);
+
+ int yofs = (row_height - tl->get_size().y) / 2;
+ Point2 title_pos(code_completion_rect.position.x, code_completion_rect.position.y + i * row_height + yofs);
+
+ /* Draw completion icon if it is valid. */
+ const Ref<Texture2D> &icon = code_completion_options[l].icon;
+ Rect2 icon_area(code_completion_rect.position.x, code_completion_rect.position.y + i * row_height, icon_area_size.width, icon_area_size.height);
+ if (icon.is_valid()) {
+ Size2 icon_size = icon_area.size * 0.7;
+ icon->draw_rect(ci, Rect2(icon_area.position + (icon_area.size - icon_size) / 2, icon_size));
+ }
+ title_pos.x = icon_area.position.x + icon_area.size.width + icon_hsep;
+
+ tl->set_width(code_completion_rect.size.width - (icon_area_size.x + icon_hsep));
+ if (rtl) {
+ if (code_completion_options[l].default_value.get_type() == Variant::COLOR) {
+ draw_rect(Rect2(Point2(code_completion_rect.position.x, icon_area.position.y), icon_area_size), (Color)code_completion_options[l].default_value);
+ }
+ tl->set_align(HALIGN_RIGHT);
+ } else {
+ if (code_completion_options[l].default_value.get_type() == Variant::COLOR) {
+ draw_rect(Rect2(Point2(code_completion_rect.position.x + code_completion_rect.size.width - icon_area_size.x, icon_area.position.y), icon_area_size), (Color)code_completion_options[l].default_value);
+ }
+ tl->set_align(HALIGN_LEFT);
+ }
+ tl->draw(ci, title_pos, code_completion_options[l].font_color);
+ }
+
+ /* Draw a small scroll rectangle to show a position in the options. */
+ if (scroll_width) {
+ float r = (float)code_completion_max_lines / code_completion_options_count;
+ float o = (float)code_completion_line_ofs / code_completion_options_count;
+ draw_rect(Rect2(code_completion_rect.position.x + code_completion_rect.size.width, code_completion_rect.position.y + o * code_completion_rect.size.y, scroll_width, code_completion_rect.size.y * r), code_completion_scroll_color);
+ }
+ }
+
+ /* Code hint */
+ if (caret_visible && code_hint != "" && (!code_completion_active || (code_completion_below != code_hint_draw_below))) {
+ const Ref<Font> font = cache.font;
+ const int font_height = font->get_height(cache.font_size);
+ Ref<StyleBox> sb = get_theme_stylebox("panel", "TooltipPanel");
+ Color font_color = get_theme_color("font_color", "TooltipLabel");
+
+ Vector<String> code_hint_lines = code_hint.split("\n");
+ int line_count = code_hint_lines.size();
+
+ int max_width = 0;
+ for (int i = 0; i < line_count; i++) {
+ max_width = MAX(max_width, font->get_string_size(code_hint_lines[i], cache.font_size).x);
+ }
+ Size2 minsize = sb->get_minimum_size() + Size2(max_width, line_count * font_height + (cache.line_spacing * line_count - 1));
+
+ int offset = font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), cache.font_size).x;
+ if (code_hint_xpos == -0xFFFF) {
+ code_hint_xpos = get_caret_draw_pos().x - offset;
+ }
+ Point2 hint_ofs = Vector2(code_hint_xpos, get_caret_draw_pos().y);
+ if (code_hint_draw_below) {
+ hint_ofs.y += cache.line_spacing / 2.0f;
+ } else {
+ hint_ofs.y -= (minsize.y + row_height) - cache.line_spacing;
+ }
+
+ draw_style_box(sb, Rect2(hint_ofs, minsize));
+
+ int line_spacing = 0;
+ for (int i = 0; i < line_count; i++) {
+ const String &line = code_hint_lines[i];
+
+ int begin = 0;
+ int end = 0;
+ if (line.find(String::chr(0xFFFF)) != -1) {
+ begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), cache.font_size).x;
+ end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), cache.font_size).x;
+ }
+
+ Point2 round_ofs = hint_ofs + sb->get_offset() + Vector2(0, font->get_ascent() + font_height * i + line_spacing);
+ round_ofs = round_ofs.round();
+ draw_string(font, round_ofs, line.replace(String::chr(0xFFFF), ""), HALIGN_LEFT, -1, cache.font_size, font_color);
+ if (end > 0) {
+ Vector2 b = hint_ofs + sb->get_offset() + Vector2(begin, font_height + font_height * i + line_spacing - 1);
+ draw_line(b, b + Vector2(end - begin, 0), font_color);
+ }
+ line_spacing += cache.line_spacing;
+ }
+ }
} break;
}
}
+void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
+ Ref<InputEventMouseButton> mb = p_gui_input;
+
+ if (mb.is_valid()) {
+ if (code_completion_active && code_completion_rect.has_point(mb->get_position())) {
+ if (!mb->is_pressed()) {
+ return;
+ }
+
+ switch (mb->get_button_index()) {
+ case MOUSE_BUTTON_WHEEL_UP: {
+ if (code_completion_current_selected > 0) {
+ code_completion_current_selected--;
+ update();
+ }
+ } break;
+ case MOUSE_BUTTON_WHEEL_DOWN: {
+ if (code_completion_current_selected < code_completion_options.size() - 1) {
+ code_completion_current_selected++;
+ update();
+ }
+ } break;
+ case MOUSE_BUTTON_LEFT: {
+ code_completion_current_selected = CLAMP(code_completion_line_ofs + (mb->get_position().y - code_completion_rect.position.y) / get_row_height(), 0, code_completion_options.size() - 1);
+ if (mb->is_double_click()) {
+ confirm_code_completion();
+ }
+ update();
+ } break;
+ }
+ return;
+ }
+ cancel_code_completion();
+ set_code_hint("");
+ }
+
+ Ref<InputEventKey> k = p_gui_input;
+ bool update_code_completion = false;
+ if (!k.is_valid()) {
+ TextEdit::_gui_input(p_gui_input);
+ return;
+ }
+
+ /* If a modifier has been pressed, and nothing else, return. */
+ if (!k->is_pressed() || k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) {
+ return;
+ }
+
+ /* Allow unicode handling if: */
+ /* No Modifiers are pressed (except shift) */
+ bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed());
+
+ /* AUTO-COMPLETE */
+ if (code_completion_enabled && k->is_action("ui_text_completion_query", true)) {
+ request_code_completion(true);
+ accept_event();
+ return;
+ }
+
+ if (code_completion_active) {
+ if (k->is_action("ui_up", true)) {
+ if (code_completion_current_selected > 0) {
+ code_completion_current_selected--;
+ } else {
+ code_completion_current_selected = code_completion_options.size() - 1;
+ }
+ update();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_down", true)) {
+ if (code_completion_current_selected < code_completion_options.size() - 1) {
+ code_completion_current_selected++;
+ } else {
+ code_completion_current_selected = 0;
+ }
+ update();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_page_up", true)) {
+ code_completion_current_selected = MAX(0, code_completion_current_selected - code_completion_max_lines);
+ update();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_page_down", true)) {
+ code_completion_current_selected = MIN(code_completion_options.size() - 1, code_completion_current_selected + code_completion_max_lines);
+ update();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_home", true)) {
+ code_completion_current_selected = 0;
+ update();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_end", true)) {
+ code_completion_current_selected = MIN(code_completion_options.size() - 1, code_completion_current_selected + code_completion_max_lines);
+ update();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_completion_replace", true) || k->is_action("ui_text_completion_accept", true)) {
+ confirm_code_completion(k->is_action("ui_text_completion_replace", true));
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_cancel", true)) {
+ cancel_code_completion();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_backspace", true)) {
+ backspace_at_cursor();
+ _filter_code_completion_candidates();
+ accept_event();
+ return;
+ }
+
+ if (k->is_action("ui_left", true) || k->is_action("ui_right", true)) {
+ update_code_completion = true;
+ } else {
+ update_code_completion = (allow_unicode_handling && k->get_unicode() >= 32);
+ }
+
+ if (!update_code_completion) {
+ cancel_code_completion();
+ }
+ }
+
+ /* MISC */
+ if (k->is_action("ui_cancel", true)) {
+ set_code_hint("");
+ accept_event();
+ return;
+ }
+ if (allow_unicode_handling && k->get_unicode() == ')') {
+ set_code_hint("");
+ }
+
+ /* Remove shift otherwise actions will not match. */
+ k = k->duplicate();
+ k->set_shift_pressed(false);
+
+ if (k->is_action("ui_text_caret_up", true) ||
+ k->is_action("ui_text_caret_down", true) ||
+ k->is_action("ui_text_caret_line_start", true) ||
+ k->is_action("ui_text_caret_line_end", true) ||
+ k->is_action("ui_text_caret_page_up", true) ||
+ k->is_action("ui_text_caret_page_down", true)) {
+ set_code_hint("");
+ }
+
+ TextEdit::_gui_input(p_gui_input);
+
+ if (update_code_completion) {
+ _filter_code_completion_candidates();
+ }
+}
+
+Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
+ if ((code_completion_active && code_completion_rect.has_point(p_pos)) || (is_readonly() && (!is_selecting_enabled() || get_line_count() == 0))) {
+ return CURSOR_ARROW;
+ }
+ return TextEdit::get_cursor_shape(p_pos);
+}
+
/* Main Gutter */
void CodeEdit::_update_draw_main_gutter() {
set_gutter_draw(main_gutter, draw_breakpoints || draw_bookmarks || draw_executing_lines);
@@ -275,6 +600,455 @@ void CodeEdit::_fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_regi
folded_icon->draw_rect(get_canvas_item(), p_region, false, folding_color);
}
+/* Delimiters */
+// Strings
+void CodeEdit::add_string_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only) {
+ _add_delimiter(p_start_key, p_end_key, p_line_only, TYPE_STRING);
+}
+
+void CodeEdit::remove_string_delimiter(const String &p_start_key) {
+ _remove_delimiter(p_start_key, TYPE_STRING);
+}
+
+bool CodeEdit::has_string_delimiter(const String &p_start_key) const {
+ return _has_delimiter(p_start_key, TYPE_STRING);
+}
+
+void CodeEdit::set_string_delimiters(const TypedArray<String> &p_string_delimiters) {
+ _set_delimiters(p_string_delimiters, TYPE_STRING);
+}
+
+void CodeEdit::clear_string_delimiters() {
+ _clear_delimiters(TYPE_STRING);
+}
+
+TypedArray<String> CodeEdit::get_string_delimiters() const {
+ return _get_delimiters(TYPE_STRING);
+}
+
+int CodeEdit::is_in_string(int p_line, int p_column) const {
+ return _is_in_delimiter(p_line, p_column, TYPE_STRING);
+}
+
+// Comments
+void CodeEdit::add_comment_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only) {
+ _add_delimiter(p_start_key, p_end_key, p_line_only, TYPE_COMMENT);
+}
+
+void CodeEdit::remove_comment_delimiter(const String &p_start_key) {
+ _remove_delimiter(p_start_key, TYPE_COMMENT);
+}
+
+bool CodeEdit::has_comment_delimiter(const String &p_start_key) const {
+ return _has_delimiter(p_start_key, TYPE_COMMENT);
+}
+
+void CodeEdit::set_comment_delimiters(const TypedArray<String> &p_comment_delimiters) {
+ _set_delimiters(p_comment_delimiters, TYPE_COMMENT);
+}
+
+void CodeEdit::clear_comment_delimiters() {
+ _clear_delimiters(TYPE_COMMENT);
+}
+
+TypedArray<String> CodeEdit::get_comment_delimiters() const {
+ return _get_delimiters(TYPE_COMMENT);
+}
+
+int CodeEdit::is_in_comment(int p_line, int p_column) const {
+ return _is_in_delimiter(p_line, p_column, TYPE_COMMENT);
+}
+
+String CodeEdit::get_delimiter_start_key(int p_delimiter_idx) const {
+ ERR_FAIL_INDEX_V(p_delimiter_idx, delimiters.size(), "");
+ return delimiters[p_delimiter_idx].start_key;
+}
+
+String CodeEdit::get_delimiter_end_key(int p_delimiter_idx) const {
+ ERR_FAIL_INDEX_V(p_delimiter_idx, delimiters.size(), "");
+ return delimiters[p_delimiter_idx].end_key;
+}
+
+Point2 CodeEdit::get_delimiter_start_position(int p_line, int p_column) const {
+ if (delimiters.size() == 0) {
+ return Point2(-1, -1);
+ }
+ ERR_FAIL_INDEX_V(p_line, get_line_count(), Point2(-1, -1));
+ ERR_FAIL_COND_V(p_column - 1 > get_line(p_line).size(), Point2(-1, -1));
+
+ Point2 start_position;
+ start_position.y = -1;
+ start_position.x = -1;
+
+ bool in_region = ((p_line <= 0 || delimiter_cache[p_line - 1].size() < 1) ? -1 : delimiter_cache[p_line - 1].back()->value()) != -1;
+
+ /* Check the keys for this line. */
+ for (Map<int, int>::Element *E = delimiter_cache[p_line].front(); E; E = E->next()) {
+ if (E->key() > p_column) {
+ break;
+ }
+ in_region = E->value() != -1;
+ start_position.x = in_region ? E->key() : -1;
+ }
+
+ /* Region was found on this line and is not a multiline continuation. */
+ if (start_position.x != -1 && start_position.x != get_line(p_line).length() + 1) {
+ start_position.y = p_line;
+ return start_position;
+ }
+
+ /* Not in a region */
+ if (!in_region) {
+ return start_position;
+ }
+
+ /* Region starts on a previous line */
+ for (int i = p_line - 1; i >= 0; i--) {
+ if (delimiter_cache[i].size() < 1) {
+ continue;
+ }
+ start_position.y = i;
+ start_position.x = delimiter_cache[i].back()->key();
+
+ /* Make sure it's not a multiline continuation. */
+ if (start_position.x != get_line(i).length() + 1) {
+ break;
+ }
+ }
+ return start_position;
+}
+
+Point2 CodeEdit::get_delimiter_end_position(int p_line, int p_column) const {
+ if (delimiters.size() == 0) {
+ return Point2(-1, -1);
+ }
+ ERR_FAIL_INDEX_V(p_line, get_line_count(), Point2(-1, -1));
+ ERR_FAIL_COND_V(p_column - 1 > get_line(p_line).size(), Point2(-1, -1));
+
+ Point2 end_position;
+ end_position.y = -1;
+ end_position.x = -1;
+
+ int region = (p_line <= 0 || delimiter_cache[p_line - 1].size() < 1) ? -1 : delimiter_cache[p_line - 1].back()->value();
+
+ /* Check the keys for this line. */
+ for (Map<int, int>::Element *E = delimiter_cache[p_line].front(); E; E = E->next()) {
+ end_position.x = (E->value() == -1) ? E->key() : -1;
+ if (E->key() > p_column) {
+ break;
+ }
+ region = E->value();
+ }
+
+ /* Region was found on this line and is not a multiline continuation. */
+ if (region != -1 && end_position.x != -1 && (delimiters[region].line_only || end_position.x != get_line(p_line).length() + 1)) {
+ end_position.y = p_line;
+ return end_position;
+ }
+
+ /* Not in a region */
+ if (region == -1) {
+ end_position.x = -1;
+ return end_position;
+ }
+
+ /* Region ends on a later line */
+ for (int i = p_line + 1; i < get_line_count(); i++) {
+ if (delimiter_cache[i].size() < 1 || delimiter_cache[i].front()->value() != -1) {
+ continue;
+ }
+ end_position.x = delimiter_cache[i].front()->key();
+
+ /* Make sure it's not a multiline continuation. */
+ if (get_line(i).length() > 0 && end_position.x != get_line(i).length() + 1) {
+ end_position.y = i;
+ break;
+ }
+ end_position.x = -1;
+ }
+ return end_position;
+}
+
+/* Code hint */
+void CodeEdit::set_code_hint(const String &p_hint) {
+ code_hint = p_hint;
+ code_hint_xpos = -0xFFFF;
+ update();
+}
+
+void CodeEdit::set_code_hint_draw_below(bool p_below) {
+ code_hint_draw_below = p_below;
+ update();
+}
+
+/* Code Completion */
+void CodeEdit::set_code_completion_enabled(bool p_enable) {
+ code_completion_enabled = p_enable;
+}
+
+bool CodeEdit::is_code_completion_enabled() const {
+ return code_completion_enabled;
+}
+
+void CodeEdit::set_code_completion_prefixes(const TypedArray<String> &p_prefixes) {
+ code_completion_prefixes.clear();
+ for (int i = 0; i < p_prefixes.size(); i++) {
+ code_completion_prefixes.insert(p_prefixes[i]);
+ }
+}
+
+TypedArray<String> CodeEdit::get_code_completion_prefixes() const {
+ TypedArray<String> prefixes;
+ for (Set<String>::Element *E = code_completion_prefixes.front(); E; E = E->next()) {
+ prefixes.push_back(E->get());
+ }
+ return prefixes;
+}
+
+String CodeEdit::get_text_for_code_completion() const {
+ StringBuilder completion_text;
+ const int text_size = get_line_count();
+ for (int i = 0; i < text_size; i++) {
+ String line = get_line(i);
+
+ if (i == cursor_get_line()) {
+ completion_text += line.substr(0, cursor_get_column());
+ /* Not unicode, represents the caret. */
+ completion_text += String::chr(0xFFFF);
+ completion_text += line.substr(cursor_get_column(), line.size());
+ } else {
+ completion_text += line;
+ }
+
+ if (i != text_size - 1) {
+ completion_text += "\n";
+ }
+ }
+ return completion_text.as_string();
+}
+
+void CodeEdit::request_code_completion(bool p_force) {
+ ScriptInstance *si = get_script_instance();
+ if (si && si->has_method("_request_code_completion")) {
+ si->call("_request_code_completion", p_force);
+ return;
+ }
+
+ /* Don't re-query if all existing options are quoted types, eg path, signal. */
+ bool ignored = code_completion_active && !code_completion_options.is_empty();
+ if (ignored) {
+ ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_PLAIN_TEXT;
+ const ScriptCodeCompletionOption *previous_option = nullptr;
+ for (int i = 0; i < code_completion_options.size(); i++) {
+ const ScriptCodeCompletionOption &current_option = code_completion_options[i];
+ if (!previous_option) {
+ previous_option = &current_option;
+ kind = current_option.kind;
+ }
+ if (previous_option->kind != current_option.kind) {
+ ignored = false;
+ break;
+ }
+ }
+ ignored = ignored && (kind == ScriptCodeCompletionOption::KIND_FILE_PATH || kind == ScriptCodeCompletionOption::KIND_NODE_PATH || kind == ScriptCodeCompletionOption::KIND_SIGNAL);
+ }
+
+ if (ignored) {
+ return;
+ }
+
+ if (p_force) {
+ emit_signal("request_code_completion");
+ return;
+ }
+
+ String line = get_line(cursor_get_line());
+ int ofs = CLAMP(cursor_get_column(), 0, line.length());
+
+ if (ofs > 0 && (is_in_string(cursor_get_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(String::chr(line[ofs - 1])))) {
+ emit_signal("request_code_completion");
+ } else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(String::chr(line[ofs - 2]))) {
+ emit_signal("request_code_completion");
+ }
+}
+
+void CodeEdit::add_code_completion_option(CodeCompletionKind p_type, const String &p_display_text, const String &p_insert_text, const Color &p_text_color, const RES &p_icon, const Variant &p_value) {
+ ScriptCodeCompletionOption completion_option;
+ completion_option.kind = (ScriptCodeCompletionOption::Kind)p_type;
+ completion_option.display = p_display_text;
+ completion_option.insert_text = p_insert_text;
+ completion_option.font_color = p_text_color;
+ completion_option.icon = p_icon;
+ completion_option.default_value = p_value;
+ code_completion_option_submitted.push_back(completion_option);
+}
+
+void CodeEdit::update_code_completion_options(bool p_forced) {
+ code_completion_forced = p_forced;
+ code_completion_option_sources = code_completion_option_submitted;
+ code_completion_option_submitted.clear();
+ _filter_code_completion_candidates();
+}
+
+TypedArray<Dictionary> CodeEdit::get_code_completion_options() const {
+ if (!code_completion_active) {
+ return TypedArray<Dictionary>();
+ }
+
+ TypedArray<Dictionary> completion_options;
+ completion_options.resize(code_completion_options.size());
+ for (int i = 0; i < code_completion_options.size(); i++) {
+ Dictionary option;
+ option["kind"] = code_completion_options[i].kind;
+ option["display_text"] = code_completion_options[i].display;
+ option["insert_text"] = code_completion_options[i].insert_text;
+ option["font_color"] = code_completion_options[i].font_color;
+ option["icon"] = code_completion_options[i].icon;
+ option["default_value"] = code_completion_options[i].default_value;
+ completion_options[i] = option;
+ }
+ return completion_options;
+}
+
+Dictionary CodeEdit::get_code_completion_option(int p_index) const {
+ if (!code_completion_active) {
+ return Dictionary();
+ }
+ ERR_FAIL_INDEX_V(p_index, code_completion_options.size(), Dictionary());
+
+ Dictionary option;
+ option["kind"] = code_completion_options[p_index].kind;
+ option["display_text"] = code_completion_options[p_index].display;
+ option["insert_text"] = code_completion_options[p_index].insert_text;
+ option["font_color"] = code_completion_options[p_index].font_color;
+ option["icon"] = code_completion_options[p_index].icon;
+ option["default_value"] = code_completion_options[p_index].default_value;
+ return option;
+}
+
+int CodeEdit::get_code_completion_selected_index() const {
+ return (code_completion_active) ? code_completion_current_selected : -1;
+}
+
+void CodeEdit::set_code_completion_selected_index(int p_index) {
+ if (!code_completion_active) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_index, code_completion_options.size());
+ code_completion_current_selected = p_index;
+ update();
+}
+
+void CodeEdit::confirm_code_completion(bool p_replace) {
+ if (is_readonly() || !code_completion_active) {
+ return;
+ }
+
+ ScriptInstance *si = get_script_instance();
+ if (si && si->has_method("_confirm_code_completion")) {
+ si->call("_confirm_code_completion", p_replace);
+ return;
+ }
+ begin_complex_operation();
+
+ int caret_line = cursor_get_line();
+
+ const String &insert_text = code_completion_options[code_completion_current_selected].insert_text;
+ const String &display_text = code_completion_options[code_completion_current_selected].display;
+
+ if (p_replace) {
+ /* Find end of current section */
+ const String line = get_line(caret_line);
+ int caret_col = cursor_get_column();
+ int caret_remove_line = caret_line;
+
+ bool merge_text = true;
+ int in_string = is_in_string(caret_line, caret_col);
+ if (in_string != -1) {
+ Point2 string_end = get_delimiter_end_position(caret_line, caret_col);
+ if (string_end.x != -1) {
+ merge_text = false;
+ caret_remove_line = string_end.y;
+ caret_col = string_end.x - 1;
+ }
+ }
+
+ if (merge_text) {
+ for (; caret_col < line.length(); caret_col++) {
+ if (!_is_char(line[caret_col])) {
+ break;
+ }
+ }
+ }
+
+ /* Replace. */
+ _remove_text(caret_line, cursor_get_column() - code_completion_base.length(), caret_remove_line, caret_col);
+ cursor_set_column(cursor_get_column() - code_completion_base.length(), false);
+ insert_text_at_cursor(insert_text);
+ } else {
+ /* Get first non-matching char. */
+ const String line = get_line(caret_line);
+ int caret_col = cursor_get_column();
+ int matching_chars = code_completion_base.length();
+ for (; matching_chars <= insert_text.length(); matching_chars++) {
+ if (caret_col >= line.length() || line[caret_col] != insert_text[matching_chars]) {
+ break;
+ }
+ caret_col++;
+ }
+
+ /* Remove base completion text. */
+ _remove_text(caret_line, cursor_get_column() - code_completion_base.length(), caret_line, cursor_get_column());
+ cursor_set_column(cursor_get_column() - code_completion_base.length(), false);
+
+ /* Merge with text. */
+ insert_text_at_cursor(insert_text.substr(0, code_completion_base.length()));
+ cursor_set_column(caret_col, false);
+ insert_text_at_cursor(insert_text.substr(matching_chars));
+ }
+
+ /* TODO: merge with autobrace completion, when in CodeEdit. */
+ /* Handle merging of symbols eg strings, brackets. */
+ const String line = get_line(caret_line);
+ char32_t next_char = line[cursor_get_column()];
+ char32_t last_completion_char = insert_text[insert_text.length() - 1];
+ char32_t last_completion_char_display = display_text[display_text.length() - 1];
+
+ if ((last_completion_char == '"' || last_completion_char == '\'') && (last_completion_char == next_char || last_completion_char_display == next_char)) {
+ _remove_text(caret_line, cursor_get_column(), caret_line, cursor_get_column() + 1);
+ }
+
+ if (last_completion_char == '(') {
+ if (next_char == last_completion_char) {
+ _remove_text(caret_line, cursor_get_column() - 1, caret_line, cursor_get_column());
+ } else if (auto_brace_completion_enabled) {
+ insert_text_at_cursor(")");
+ cursor_set_column(cursor_get_column() - 1);
+ }
+ } else if (last_completion_char == ')' && next_char == '(') {
+ _remove_text(caret_line, cursor_get_column() - 2, caret_line, cursor_get_column());
+ if (line[cursor_get_column() + 1] != ')') {
+ cursor_set_column(cursor_get_column() - 1);
+ }
+ }
+
+ end_complex_operation();
+
+ cancel_code_completion();
+ if (last_completion_char == '(') {
+ request_code_completion();
+ }
+}
+
+void CodeEdit::cancel_code_completion() {
+ if (!code_completion_active) {
+ return;
+ }
+ code_completion_forced = false;
+ code_completion_active = false;
+ update();
+}
+
void CodeEdit::_bind_methods() {
/* Main Gutter */
ClassDB::bind_method(D_METHOD("_main_gutter_draw_callback"), &CodeEdit::_main_gutter_draw_callback);
@@ -320,6 +1094,76 @@ void CodeEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_draw_fold_gutter", "enable"), &CodeEdit::set_draw_fold_gutter);
ClassDB::bind_method(D_METHOD("is_drawing_fold_gutter"), &CodeEdit::is_drawing_fold_gutter);
+ /* Delimiters */
+ // Strings
+ ClassDB::bind_method(D_METHOD("add_string_delimiter", "start_key", "end_key", "line_only"), &CodeEdit::add_string_delimiter, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("remove_string_delimiter", "start_key"), &CodeEdit::remove_string_delimiter);
+ ClassDB::bind_method(D_METHOD("has_string_delimiter", "start_key"), &CodeEdit::has_string_delimiter);
+
+ ClassDB::bind_method(D_METHOD("set_string_delimiters", "string_delimiters"), &CodeEdit::set_string_delimiters);
+ ClassDB::bind_method(D_METHOD("clear_string_delimiters"), &CodeEdit::clear_string_delimiters);
+ ClassDB::bind_method(D_METHOD("get_string_delimiters"), &CodeEdit::get_string_delimiters);
+
+ ClassDB::bind_method(D_METHOD("is_in_string", "line", "column"), &CodeEdit::is_in_string, DEFVAL(-1));
+
+ // Comments
+ ClassDB::bind_method(D_METHOD("add_comment_delimiter", "start_key", "end_key", "line_only"), &CodeEdit::add_comment_delimiter, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("remove_comment_delimiter", "start_key"), &CodeEdit::remove_comment_delimiter);
+ ClassDB::bind_method(D_METHOD("has_comment_delimiter", "start_key"), &CodeEdit::has_comment_delimiter);
+
+ ClassDB::bind_method(D_METHOD("set_comment_delimiters", "comment_delimiters"), &CodeEdit::set_comment_delimiters);
+ ClassDB::bind_method(D_METHOD("clear_comment_delimiters"), &CodeEdit::clear_comment_delimiters);
+ ClassDB::bind_method(D_METHOD("get_comment_delimiters"), &CodeEdit::get_comment_delimiters);
+
+ ClassDB::bind_method(D_METHOD("is_in_comment", "line", "column"), &CodeEdit::is_in_comment, DEFVAL(-1));
+
+ // Util
+ ClassDB::bind_method(D_METHOD("get_delimiter_start_key", "delimiter_index"), &CodeEdit::get_delimiter_start_key);
+ ClassDB::bind_method(D_METHOD("get_delimiter_end_key", "delimiter_index"), &CodeEdit::get_delimiter_end_key);
+
+ ClassDB::bind_method(D_METHOD("get_delimiter_start_postion", "line", "column"), &CodeEdit::get_delimiter_start_position);
+ ClassDB::bind_method(D_METHOD("get_delimiter_end_postion", "line", "column"), &CodeEdit::get_delimiter_end_position);
+
+ /* Code hint */
+ ClassDB::bind_method(D_METHOD("set_code_hint", "code_hint"), &CodeEdit::set_code_hint);
+ ClassDB::bind_method(D_METHOD("set_code_hint_draw_below", "draw_below"), &CodeEdit::set_code_hint_draw_below);
+
+ /* Code Completion */
+ BIND_ENUM_CONSTANT(KIND_CLASS);
+ BIND_ENUM_CONSTANT(KIND_FUNCTION);
+ BIND_ENUM_CONSTANT(KIND_SIGNAL);
+ BIND_ENUM_CONSTANT(KIND_VARIABLE);
+ BIND_ENUM_CONSTANT(KIND_MEMBER);
+ BIND_ENUM_CONSTANT(KIND_ENUM);
+ BIND_ENUM_CONSTANT(KIND_CONSTANT);
+ BIND_ENUM_CONSTANT(KIND_NODE_PATH);
+ BIND_ENUM_CONSTANT(KIND_FILE_PATH);
+ BIND_ENUM_CONSTANT(KIND_PLAIN_TEXT);
+
+ ClassDB::bind_method(D_METHOD("get_text_for_code_completion"), &CodeEdit::get_text_for_code_completion);
+ ClassDB::bind_method(D_METHOD("request_code_completion", "force"), &CodeEdit::request_code_completion, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_code_completion_option", "type", "display_text", "insert_text", "text_color", "icon", "value"), &CodeEdit::add_code_completion_option, DEFVAL(Color(1, 1, 1)), DEFVAL(RES()), DEFVAL(Variant::NIL));
+ ClassDB::bind_method(D_METHOD("update_code_completion_options", "force"), &CodeEdit::update_code_completion_options);
+ ClassDB::bind_method(D_METHOD("get_code_completion_options"), &CodeEdit::get_code_completion_options);
+ ClassDB::bind_method(D_METHOD("get_code_completion_option", "index"), &CodeEdit::get_code_completion_option);
+ ClassDB::bind_method(D_METHOD("get_code_completion_selected_index"), &CodeEdit::get_code_completion_selected_index);
+ ClassDB::bind_method(D_METHOD("set_code_completion_selected_index", "index"), &CodeEdit::set_code_completion_selected_index);
+
+ ClassDB::bind_method(D_METHOD("confirm_code_completion", "replace"), &CodeEdit::confirm_code_completion, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("cancel_code_completion"), &CodeEdit::cancel_code_completion);
+
+ ClassDB::bind_method(D_METHOD("set_code_completion_enabled", "enable"), &CodeEdit::set_code_completion_enabled);
+ ClassDB::bind_method(D_METHOD("is_code_completion_enabled"), &CodeEdit::is_code_completion_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_code_completion_prefixes", "prefixes"), &CodeEdit::set_code_completion_prefixes);
+ ClassDB::bind_method(D_METHOD("get_code_comletion_prefixes"), &CodeEdit::get_code_completion_prefixes);
+
+ // Overridable
+ BIND_VMETHOD(MethodInfo("_confirm_code_completion", PropertyInfo(Variant::BOOL, "replace")));
+ BIND_VMETHOD(MethodInfo("_request_code_completion", PropertyInfo(Variant::BOOL, "force")));
+ BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_filter_code_completion_candidates", PropertyInfo(Variant::ARRAY, "candidates")));
+
+ /* Inspector */
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_breakpoints_gutter"), "set_draw_breakpoints_gutter", "is_drawing_breakpoints_gutter");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_bookmarks"), "set_draw_bookmarks_gutter", "is_drawing_bookmarks_gutter");
@@ -331,7 +1175,17 @@ void CodeEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter");
+ ADD_GROUP("Delimiters", "delimiter_");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "delimiter_strings"), "set_string_delimiters", "get_string_delimiters");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "delimiter_comments"), "set_comment_delimiters", "get_comment_delimiters");
+
+ ADD_GROUP("Code Completion", "code_completion_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "code_completion_enabled"), "set_code_completion_enabled", "is_code_completion_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "code_completion_prefixes"), "set_code_completion_prefixes", "get_code_comletion_prefixes");
+
+ /* Signals */
ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "line")));
+ ADD_SIGNAL(MethodInfo("request_code_completion"));
}
void CodeEdit::_gutter_clicked(int p_line, int p_gutter) {
@@ -360,7 +1214,569 @@ void CodeEdit::_gutter_clicked(int p_line, int p_gutter) {
}
}
+void CodeEdit::_update_gutter_indexes() {
+ for (int i = 0; i < get_gutter_count(); i++) {
+ if (get_gutter_name(i) == "main_gutter") {
+ main_gutter = i;
+ continue;
+ }
+
+ if (get_gutter_name(i) == "line_numbers") {
+ line_number_gutter = i;
+ continue;
+ }
+
+ if (get_gutter_name(i) == "fold_gutter") {
+ fold_gutter = i;
+ continue;
+ }
+ }
+}
+
+/* Delimiters */
+void CodeEdit::_update_delimiter_cache(int p_from_line, int p_to_line) {
+ if (delimiters.size() == 0) {
+ return;
+ }
+
+ int line_count = get_line_count();
+ if (p_to_line == -1) {
+ p_to_line = line_count;
+ }
+
+ int start_line = MIN(p_from_line, p_to_line);
+ int end_line = MAX(p_from_line, p_to_line);
+
+ /* Make sure delimiter_cache has all the lines. */
+ if (start_line != end_line) {
+ if (p_to_line < p_from_line) {
+ for (int i = end_line; i > start_line; i--) {
+ delimiter_cache.remove(i);
+ }
+ } else {
+ for (int i = start_line; i < end_line; i++) {
+ delimiter_cache.insert(i, Map<int, int>());
+ }
+ }
+ }
+
+ int in_region = -1;
+ for (int i = start_line; i < MIN(end_line + 1, line_count); i++) {
+ int current_end_region = (i <= 0 || delimiter_cache[i].size() < 1) ? -1 : delimiter_cache[i].back()->value();
+ in_region = (i <= 0 || delimiter_cache[i - 1].size() < 1) ? -1 : delimiter_cache[i - 1].back()->value();
+
+ const String &str = get_line(i);
+ const int line_length = str.length();
+ delimiter_cache.write[i].clear();
+
+ if (str.length() == 0) {
+ if (in_region != -1) {
+ delimiter_cache.write[i][0] = in_region;
+ }
+ if (i == end_line && current_end_region != in_region) {
+ end_line++;
+ end_line = MIN(end_line, line_count);
+ }
+ continue;
+ }
+
+ int end_region = -1;
+ for (int j = 0; j < line_length; j++) {
+ int from = j;
+ for (; from < line_length; from++) {
+ if (str[from] == '\\') {
+ from++;
+ continue;
+ }
+ break;
+ }
+
+ /* check if we are in entering a region */
+ bool same_line = false;
+ if (in_region == -1) {
+ for (int d = 0; d < delimiters.size(); d++) {
+ /* check there is enough room */
+ int chars_left = line_length - from;
+ int start_key_length = delimiters[d].start_key.length();
+ int end_key_length = delimiters[d].end_key.length();
+ if (chars_left < start_key_length) {
+ continue;
+ }
+
+ /* search the line */
+ bool match = true;
+ const char32_t *start_key = delimiters[d].start_key.get_data();
+ for (int k = 0; k < start_key_length; k++) {
+ if (start_key[k] != str[from + k]) {
+ match = false;
+ break;
+ }
+ }
+ if (!match) {
+ continue;
+ }
+ same_line = true;
+ in_region = d;
+ delimiter_cache.write[i][from + 1] = d;
+ from += start_key_length;
+
+ /* check if it's the whole line */
+ if (end_key_length == 0 || delimiters[d].line_only || from + end_key_length > line_length) {
+ j = line_length;
+ if (delimiters[d].line_only) {
+ delimiter_cache.write[i][line_length + 1] = -1;
+ } else {
+ end_region = in_region;
+ }
+ }
+ break;
+ }
+
+ if (j == line_length || in_region == -1) {
+ continue;
+ }
+ }
+
+ /* if we are in one find the end key */
+ /* search the line */
+ int region_end_index = -1;
+ int end_key_length = delimiters[in_region].end_key.length();
+ const char32_t *end_key = delimiters[in_region].end_key.get_data();
+ for (; from < line_length; from++) {
+ if (line_length - from < end_key_length) {
+ break;
+ }
+
+ if (!is_symbol(str[from])) {
+ continue;
+ }
+
+ if (str[from] == '\\') {
+ from++;
+ continue;
+ }
+
+ region_end_index = from;
+ for (int k = 0; k < end_key_length; k++) {
+ if (end_key[k] != str[from + k]) {
+ region_end_index = -1;
+ break;
+ }
+ }
+
+ if (region_end_index != -1) {
+ break;
+ }
+ }
+
+ j = from + (end_key_length - 1);
+ end_region = (region_end_index == -1) ? in_region : -1;
+ if (!same_line || region_end_index != -1) {
+ delimiter_cache.write[i][j + 1] = end_region;
+ }
+ in_region = -1;
+ }
+
+ if (i == end_line && current_end_region != end_region) {
+ end_line++;
+ end_line = MIN(end_line, line_count);
+ }
+ }
+}
+
+int CodeEdit::_is_in_delimiter(int p_line, int p_column, DelimiterType p_type) const {
+ if (delimiters.size() == 0) {
+ return -1;
+ }
+ ERR_FAIL_INDEX_V(p_line, get_line_count(), 0);
+
+ int region = (p_line <= 0 || delimiter_cache[p_line - 1].size() < 1) ? -1 : delimiter_cache[p_line - 1].back()->value();
+ bool in_region = region != -1 && delimiters[region].type == p_type;
+ for (Map<int, int>::Element *E = delimiter_cache[p_line].front(); E; E = E->next()) {
+ /* If column is specified, loop untill the key is larger then the column. */
+ if (p_column != -1) {
+ if (E->key() > p_column) {
+ break;
+ }
+ in_region = E->value() != -1 && delimiters[E->value()].type == p_type;
+ region = in_region ? E->value() : -1;
+ continue;
+ }
+
+ /* If no column, calulate if the entire line is a region */
+ /* excluding whitespace. */
+ const String line = get_line(p_line);
+ if (!in_region) {
+ if (E->value() == -1 || delimiters[E->value()].type != p_type) {
+ break;
+ }
+
+ region = E->value();
+ in_region = true;
+ for (int i = E->key() - 2; i >= 0; i--) {
+ if (!_is_whitespace(line[i])) {
+ return -1;
+ }
+ }
+ }
+
+ if (delimiters[region].line_only) {
+ return region;
+ }
+
+ int end_col = E->key();
+ if (E->value() != -1) {
+ if (!E->next()) {
+ return region;
+ }
+ end_col = E->next()->key();
+ }
+
+ for (int i = end_col; i < line.length(); i++) {
+ if (!_is_whitespace(line[i])) {
+ return -1;
+ }
+ }
+ return region;
+ }
+ return in_region ? region : -1;
+}
+
+void CodeEdit::_add_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only, DelimiterType p_type) {
+ if (p_start_key.length() > 0) {
+ for (int i = 0; i < p_start_key.length(); i++) {
+ ERR_FAIL_COND_MSG(!is_symbol(p_start_key[i]), "delimiter must start with a symbol");
+ }
+ }
+
+ if (p_end_key.length() > 0) {
+ for (int i = 0; i < p_end_key.length(); i++) {
+ ERR_FAIL_COND_MSG(!is_symbol(p_end_key[i]), "delimiter must end with a symbol");
+ }
+ }
+
+ int at = 0;
+ for (int i = 0; i < delimiters.size(); i++) {
+ ERR_FAIL_COND_MSG(delimiters[i].start_key == p_start_key, "delimiter with start key '" + p_start_key + "' already exists.");
+ if (p_start_key.length() < delimiters[i].start_key.length()) {
+ at++;
+ }
+ }
+
+ Delimiter delimiter;
+ delimiter.type = p_type;
+ delimiter.start_key = p_start_key;
+ delimiter.end_key = p_end_key;
+ delimiter.line_only = p_line_only || p_end_key == "";
+ delimiters.insert(at, delimiter);
+ if (!setting_delimiters) {
+ delimiter_cache.clear();
+ _update_delimiter_cache();
+ }
+}
+
+void CodeEdit::_remove_delimiter(const String &p_start_key, DelimiterType p_type) {
+ for (int i = 0; i < delimiters.size(); i++) {
+ if (delimiters[i].start_key != p_start_key) {
+ continue;
+ }
+
+ if (delimiters[i].type != p_type) {
+ break;
+ }
+
+ delimiters.remove(i);
+ if (!setting_delimiters) {
+ delimiter_cache.clear();
+ _update_delimiter_cache();
+ }
+ break;
+ }
+}
+
+bool CodeEdit::_has_delimiter(const String &p_start_key, DelimiterType p_type) const {
+ for (int i = 0; i < delimiters.size(); i++) {
+ if (delimiters[i].start_key == p_start_key) {
+ return delimiters[i].type == p_type;
+ }
+ }
+ return false;
+}
+
+void CodeEdit::_set_delimiters(const TypedArray<String> &p_delimiters, DelimiterType p_type) {
+ setting_delimiters = true;
+ _clear_delimiters(p_type);
+
+ for (int i = 0; i < p_delimiters.size(); i++) {
+ String key = p_delimiters[i].is_null() ? "" : p_delimiters[i];
+
+ const String start_key = key.get_slice(" ", 0);
+ const String end_key = key.get_slice_count(" ") > 1 ? key.get_slice(" ", 1) : String();
+
+ _add_delimiter(start_key, end_key, end_key == "", p_type);
+ }
+ setting_delimiters = false;
+ _update_delimiter_cache();
+}
+
+void CodeEdit::_clear_delimiters(DelimiterType p_type) {
+ for (int i = delimiters.size() - 1; i >= 0; i--) {
+ if (delimiters[i].type == p_type) {
+ delimiters.remove(i);
+ }
+ }
+ delimiter_cache.clear();
+ if (!setting_delimiters) {
+ _update_delimiter_cache();
+ }
+}
+
+TypedArray<String> CodeEdit::_get_delimiters(DelimiterType p_type) const {
+ TypedArray<String> r_delimiters;
+ for (int i = 0; i < delimiters.size(); i++) {
+ if (delimiters[i].type != p_type) {
+ continue;
+ }
+ r_delimiters.push_back(delimiters[i].start_key + (delimiters[i].end_key.is_empty() ? "" : " " + delimiters[i].end_key));
+ }
+ return r_delimiters;
+}
+
+/* Code Completion */
+void CodeEdit::_filter_code_completion_candidates() {
+ ScriptInstance *si = get_script_instance();
+ if (si && si->has_method("_filter_code_completion_candidates")) {
+ code_completion_options.clear();
+ code_completion_base = "";
+
+ /* Build options argument. */
+ TypedArray<Dictionary> completion_options_sources;
+ completion_options_sources.resize(code_completion_option_sources.size());
+ int i = 0;
+ for (List<ScriptCodeCompletionOption>::Element *E = code_completion_option_sources.front(); E; E = E->next()) {
+ Dictionary option;
+ option["kind"] = E->get().kind;
+ option["display_text"] = E->get().display;
+ option["insert_text"] = E->get().insert_text;
+ option["font_color"] = E->get().font_color;
+ option["icon"] = E->get().icon;
+ option["default_value"] = E->get().default_value;
+ completion_options_sources[i] = option;
+ i++;
+ }
+
+ TypedArray<Dictionary> completion_options = si->call("_filter_code_completion_candidates", completion_options_sources);
+
+ /* No options to complete, cancel. */
+ if (completion_options.size() == 0) {
+ cancel_code_completion();
+ return;
+ }
+
+ /* Convert back into options. */
+ int max_width = 0;
+ for (i = 0; i < completion_options.size(); i++) {
+ ScriptCodeCompletionOption option;
+ option.kind = (ScriptCodeCompletionOption::Kind)(int)completion_options[i].get("kind");
+ option.display = completion_options[i].get("display_text");
+ option.insert_text = completion_options[i].get("insert_text");
+ option.font_color = completion_options[i].get("font_color");
+ option.icon = completion_options[i].get("icon");
+ option.default_value = completion_options[i].get("default_value");
+
+ max_width = MAX(max_width, cache.font->get_string_size(option.display).width);
+ code_completion_options.push_back(option);
+ }
+
+ code_completion_longest_line = MIN(max_width, code_completion_max_width);
+ code_completion_current_selected = 0;
+ code_completion_active = true;
+ update();
+ return;
+ }
+
+ const int caret_line = cursor_get_line();
+ const int caret_column = cursor_get_column();
+ const String line = get_line(caret_line);
+
+ if (caret_column > 0 && line[caret_column - 1] == '(' && !code_completion_forced) {
+ cancel_code_completion();
+ return;
+ }
+
+ /* Get string status, are we in one or at the close. */
+ int in_string = is_in_string(caret_line, caret_column);
+ int first_quote_col = -1;
+ if (in_string != -1) {
+ Point2 string_start_pos = get_delimiter_start_position(caret_line, caret_column);
+ first_quote_col = (string_start_pos.y == caret_line) ? string_start_pos.x : -1;
+ } else if (caret_column > 0) {
+ if (is_in_string(caret_line, caret_column - 1) != -1) {
+ first_quote_col = caret_column - 1;
+ }
+ }
+
+ int cofs = caret_column;
+ String string_to_complete;
+ bool prev_is_word = false;
+
+ /* Cancel if we are at the close of a string. */
+ if (in_string == -1 && first_quote_col == cofs - 1) {
+ cancel_code_completion();
+ return;
+ /* In a string, therefore we are trying to complete the string text. */
+ } else if (in_string != -1 && first_quote_col != -1) {
+ int key_length = delimiters[in_string].start_key.length();
+ string_to_complete = line.substr(first_quote_col - key_length, (cofs - first_quote_col) + key_length);
+ /* If we have a space, previous word might be a keyword. eg "func |". */
+ } else if (cofs > 0 && line[cofs - 1] == ' ') {
+ int ofs = cofs - 1;
+ while (ofs >= 0 && line[ofs] == ' ') {
+ ofs--;
+ }
+ prev_is_word = _is_char(line[ofs]);
+ /* Otherwise get current word and set cofs to the start. */
+ } else {
+ int start_cofs = cofs;
+ while (cofs > 0 && line[cofs - 1] > 32 && (line[cofs - 1] == '/' || _is_char(line[cofs - 1]))) {
+ cofs--;
+ }
+ string_to_complete = line.substr(cofs, start_cofs - cofs);
+ }
+
+ /* If all else fails, check for a prefix. */
+ /* Single space between caret and prefix is okay. */
+ bool prev_is_prefix = false;
+ if (cofs > 0 && code_completion_prefixes.has(String::chr(line[cofs - 1]))) {
+ prev_is_prefix = true;
+ } else if (cofs > 1 && line[cofs - 1] == ' ' && code_completion_prefixes.has(String::chr(line[cofs - 2]))) {
+ prev_is_prefix = true;
+ }
+
+ if (!prev_is_word && string_to_complete.is_empty() && (cofs == 0 || !prev_is_prefix)) {
+ cancel_code_completion();
+ return;
+ }
+
+ /* Filter Options. */
+ /* For now handle only tradional quoted strings. */
+ bool single_quote = in_string != -1 && first_quote_col > 0 && delimiters[in_string].start_key == "'";
+
+ code_completion_options.clear();
+ code_completion_base = string_to_complete;
+
+ Vector<ScriptCodeCompletionOption> completion_options_casei;
+ Vector<ScriptCodeCompletionOption> completion_options_subseq;
+ Vector<ScriptCodeCompletionOption> completion_options_subseq_casei;
+
+ int max_width = 0;
+ String string_to_complete_lower = string_to_complete.to_lower();
+ for (List<ScriptCodeCompletionOption>::Element *E = code_completion_option_sources.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption &option = E->get();
+
+ if (single_quote && option.display.is_quoted()) {
+ option.display = option.display.unquote().quote("'");
+ }
+
+ if (in_string != -1) {
+ String quote = single_quote ? "'" : "\"";
+ option.display = option.display.unquote().quote(quote);
+ option.insert_text = option.insert_text.unquote().quote(quote);
+ }
+
+ if (option.display.length() == 0) {
+ continue;
+ }
+
+ if (string_to_complete.length() == 0) {
+ code_completion_options.push_back(option);
+ max_width = MAX(max_width, cache.font->get_string_size(option.display).width);
+ continue;
+ }
+
+ /* This code works the same as:
+
+ if (option.display.begins_with(s)) {
+ completion_options.push_back(option);
+ } else if (option.display.to_lower().begins_with(s.to_lower())) {
+ completion_options_casei.push_back(option);
+ } else if (s.is_subsequence_of(option.display)) {
+ completion_options_subseq.push_back(option);
+ } else if (s.is_subsequence_ofi(option.display)) {
+ completion_options_subseq_casei.push_back(option);
+ }
+
+ But is more performant due to being inlined and looping over the characters only once
+ */
+
+ String display_lower = option.display.to_lower();
+
+ const char32_t *ssq = &string_to_complete[0];
+ const char32_t *ssq_lower = &string_to_complete_lower[0];
+
+ const char32_t *tgt = &option.display[0];
+ const char32_t *tgt_lower = &display_lower[0];
+
+ const char32_t *ssq_last_tgt = nullptr;
+ const char32_t *ssq_lower_last_tgt = nullptr;
+
+ for (; *tgt; tgt++, tgt_lower++) {
+ if (*ssq == *tgt) {
+ ssq++;
+ ssq_last_tgt = tgt;
+ }
+ if (*ssq_lower == *tgt_lower) {
+ ssq_lower++;
+ ssq_lower_last_tgt = tgt;
+ }
+ }
+
+ /* Matched the whole subsequence in s. */
+ if (!*ssq) {
+ /* Finished matching in the first s.length() characters. */
+ if (ssq_last_tgt == &option.display[string_to_complete.length() - 1]) {
+ code_completion_options.push_back(option);
+ } else {
+ completion_options_subseq.push_back(option);
+ }
+ max_width = MAX(max_width, cache.font->get_string_size(option.display).width);
+ /* Matched the whole subsequence in s_lower. */
+ } else if (!*ssq_lower) {
+ /* Finished matching in the first s.length() characters. */
+ if (ssq_lower_last_tgt == &option.display[string_to_complete.length() - 1]) {
+ completion_options_casei.push_back(option);
+ } else {
+ completion_options_subseq_casei.push_back(option);
+ }
+ max_width = MAX(max_width, cache.font->get_string_size(option.display).width);
+ }
+ }
+
+ code_completion_options.append_array(completion_options_casei);
+ code_completion_options.append_array(completion_options_subseq);
+ code_completion_options.append_array(completion_options_subseq_casei);
+
+ /* No options to complete, cancel. */
+ if (code_completion_options.size() == 0) {
+ cancel_code_completion();
+ return;
+ }
+
+ /* A perfect match, stop completion. */
+ if (code_completion_options.size() == 1 && string_to_complete == code_completion_options[0].display) {
+ cancel_code_completion();
+ return;
+ }
+
+ code_completion_longest_line = MIN(max_width, code_completion_max_width);
+ code_completion_current_selected = 0;
+ code_completion_active = true;
+ update();
+}
+
void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
+ _update_delimiter_cache(p_from_line, p_to_line);
+
if (p_from_line == p_to_line) {
return;
}
@@ -392,25 +1808,6 @@ void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
}
}
-void CodeEdit::_update_gutter_indexes() {
- for (int i = 0; i < get_gutter_count(); i++) {
- if (get_gutter_name(i) == "main_gutter") {
- main_gutter = i;
- continue;
- }
-
- if (get_gutter_name(i) == "line_numbers") {
- line_number_gutter = i;
- continue;
- }
-
- if (get_gutter_name(i) == "fold_gutter") {
- fold_gutter = i;
- continue;
- }
- }
-}
-
CodeEdit::CodeEdit() {
/* Text Direction */
set_layout_direction(LAYOUT_DIRECTION_LTR);
diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h
index d0c39ec0f1..6305eacf83 100644
--- a/scene/gui/code_edit.h
+++ b/scene/gui/code_edit.h
@@ -36,6 +36,22 @@
class CodeEdit : public TextEdit {
GDCLASS(CodeEdit, TextEdit)
+public:
+ /* Keep enum in sync with: */
+ /* /core/object/script_language.h - ScriptCodeCompletionOption::Kind */
+ enum CodeCompletionKind {
+ KIND_CLASS,
+ KIND_FUNCTION,
+ KIND_SIGNAL,
+ KIND_VARIABLE,
+ KIND_MEMBER,
+ KIND_ENUM,
+ KIND_CONSTANT,
+ KIND_NODE_PATH,
+ KIND_FILE_PATH,
+ KIND_PLAIN_TEXT,
+ };
+
private:
/* Main Gutter */
enum MainGutterType {
@@ -80,16 +96,113 @@ private:
void _fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_region);
void _gutter_clicked(int p_line, int p_gutter);
- void _lines_edited_from(int p_from_line, int p_to_line);
-
void _update_gutter_indexes();
+ /* Delimiters */
+ enum DelimiterType {
+ TYPE_STRING,
+ TYPE_COMMENT,
+ };
+
+ struct Delimiter {
+ DelimiterType type;
+ String start_key = "";
+ String end_key = "";
+ bool line_only = true;
+ };
+ bool setting_delimiters = false;
+ Vector<Delimiter> delimiters;
+ /*
+ * Vector entry per line, contains a Map of column numbers to delimiter index, -1 marks the end of a region.
+ * e.g the following text will be stored as so:
+ *
+ * 0: nothing here
+ * 1:
+ * 2: # test
+ * 3: "test" text "multiline
+ * 4:
+ * 5: test
+ * 6: string"
+ *
+ * Vector [
+ * 0 = []
+ * 1 = []
+ * 2 = [
+ * 1 = 1
+ * 6 = -1
+ * ]
+ * 3 = [
+ * 1 = 0
+ * 6 = -1
+ * 13 = 0
+ * ]
+ * 4 = [
+ * 0 = 0
+ * ]
+ * 5 = [
+ * 5 = 0
+ * ]
+ * 6 = [
+ * 7 = -1
+ * ]
+ * ]
+ */
+ Vector<Map<int, int>> delimiter_cache;
+
+ void _update_delimiter_cache(int p_from_line = 0, int p_to_line = -1);
+ int _is_in_delimiter(int p_line, int p_column, DelimiterType p_type) const;
+
+ void _add_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only, DelimiterType p_type);
+ void _remove_delimiter(const String &p_start_key, DelimiterType p_type);
+ bool _has_delimiter(const String &p_start_key, DelimiterType p_type) const;
+
+ void _set_delimiters(const TypedArray<String> &p_delimiters, DelimiterType p_type);
+ void _clear_delimiters(DelimiterType p_type);
+ TypedArray<String> _get_delimiters(DelimiterType p_type) const;
+
+ /* Code Hint */
+ String code_hint = "";
+
+ bool code_hint_draw_below = true;
+ int code_hint_xpos = -0xFFFF;
+
+ /* Code Completion */
+ bool code_completion_enabled = false;
+ bool code_completion_forced = false;
+
+ int code_completion_max_width = 0;
+ int code_completion_max_lines = 7;
+ int code_completion_scroll_width = 0;
+ Color code_completion_scroll_color = Color(0, 0, 0, 0);
+ Color code_completion_background_color = Color(0, 0, 0, 0);
+ Color code_completion_selected_color = Color(0, 0, 0, 0);
+ Color code_completion_existing_color = Color(0, 0, 0, 0);
+
+ bool code_completion_active = false;
+ Vector<ScriptCodeCompletionOption> code_completion_options;
+ int code_completion_line_ofs = 0;
+ int code_completion_current_selected = 0;
+ int code_completion_longest_line = 0;
+ Rect2i code_completion_rect;
+
+ Set<String> code_completion_prefixes;
+ List<ScriptCodeCompletionOption> code_completion_option_submitted;
+ List<ScriptCodeCompletionOption> code_completion_option_sources;
+ String code_completion_base;
+
+ void _filter_code_completion_candidates();
+
+ void _lines_edited_from(int p_from_line, int p_to_line);
+
protected:
+ void _gui_input(const Ref<InputEvent> &p_gui_input) override;
void _notification(int p_what);
static void _bind_methods();
public:
+ virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
+
/* Main Gutter */
void set_draw_breakpoints_gutter(bool p_draw);
bool is_drawing_breakpoints_gutter() const;
@@ -128,8 +241,64 @@ public:
void set_draw_fold_gutter(bool p_draw);
bool is_drawing_fold_gutter() const;
+ /* Delimiters */
+ void add_string_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only = false);
+ void remove_string_delimiter(const String &p_start_key);
+ bool has_string_delimiter(const String &p_start_key) const;
+
+ void set_string_delimiters(const TypedArray<String> &p_string_delimiters);
+ void clear_string_delimiters();
+ TypedArray<String> get_string_delimiters() const;
+
+ int is_in_string(int p_line, int p_column = -1) const;
+
+ void add_comment_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only = false);
+ void remove_comment_delimiter(const String &p_start_key);
+ bool has_comment_delimiter(const String &p_start_key) const;
+
+ void set_comment_delimiters(const TypedArray<String> &p_comment_delimiters);
+ void clear_comment_delimiters();
+ TypedArray<String> get_comment_delimiters() const;
+
+ int is_in_comment(int p_line, int p_column = -1) const;
+
+ String get_delimiter_start_key(int p_delimiter_idx) const;
+ String get_delimiter_end_key(int p_delimiter_idx) const;
+
+ Point2 get_delimiter_start_position(int p_line, int p_column) const;
+ Point2 get_delimiter_end_position(int p_line, int p_column) const;
+
+ /* Code hint */
+ void set_code_hint(const String &p_hint);
+ void set_code_hint_draw_below(bool p_below);
+
+ /* Code Completion */
+ void set_code_completion_enabled(bool p_enable);
+ bool is_code_completion_enabled() const;
+
+ void set_code_completion_prefixes(const TypedArray<String> &p_prefixes);
+ TypedArray<String> get_code_completion_prefixes() const;
+
+ String get_text_for_code_completion() const;
+
+ void request_code_completion(bool p_force = false);
+
+ void add_code_completion_option(CodeCompletionKind p_type, const String &p_display_text, const String &p_insert_text, const Color &p_text_color = Color(1, 1, 1), const RES &p_icon = RES(), const Variant &p_value = Variant::NIL);
+ void update_code_completion_options(bool p_forced = false);
+
+ TypedArray<Dictionary> get_code_completion_options() const;
+ Dictionary get_code_completion_option(int p_index) const;
+
+ int get_code_completion_selected_index() const;
+ void set_code_completion_selected_index(int p_index);
+
+ void confirm_code_completion(bool p_replace = false);
+ void cancel_code_completion();
+
CodeEdit();
~CodeEdit();
};
+VARIANT_ENUM_CAST(CodeEdit::CodeCompletionKind);
+
#endif // CODEEDIT_H
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index fdee136b82..c0b4563615 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -84,6 +84,55 @@ void ColorPicker::_notification(int p_what) {
}
}
+Ref<Shader> ColorPicker::wheel_shader;
+Ref<Shader> ColorPicker::circle_shader;
+
+void ColorPicker::init_shaders() {
+ wheel_shader.instance();
+ wheel_shader->set_code(
+ "shader_type canvas_item;"
+ "void fragment() {"
+ " float x = UV.x - 0.5;"
+ " float y = UV.y - 0.5;"
+ " float a = atan(y, x);"
+ " x += 0.001;"
+ " y += 0.001;"
+ " float b = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
+ " x -= 0.002;"
+ " float b2 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
+ " y -= 0.002;"
+ " float b3 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
+ " x += 0.002;"
+ " float b4 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
+ " COLOR = vec4(clamp((abs(fract(((a - TAU) / TAU) + vec3(3.0, 2.0, 1.0) / 3.0) * 6.0 - 3.0) - 1.0), 0.0, 1.0), (b + b2 + b3 + b4) / 4.00);"
+ "}");
+
+ circle_shader.instance();
+ circle_shader->set_code(
+ "shader_type canvas_item;"
+ "uniform float v = 1.0;"
+ "void fragment() {"
+ " float x = UV.x - 0.5;"
+ " float y = UV.y - 0.5;"
+ " float a = atan(y, x);"
+ " x += 0.001;"
+ " y += 0.001;"
+ " float b = float(sqrt(x * x + y * y) < 0.5);"
+ " x -= 0.002;"
+ " float b2 = float(sqrt(x * x + y * y) < 0.5);"
+ " y -= 0.002;"
+ " float b3 = float(sqrt(x * x + y * y) < 0.5);"
+ " x += 0.002;"
+ " float b4 = float(sqrt(x * x + y * y) < 0.5);"
+ " COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.00);"
+ "}");
+}
+
+void ColorPicker::finish_shaders() {
+ wheel_shader.unref();
+ circle_shader.unref();
+}
+
void ColorPicker::set_focus_on_line_edit() {
c_text->call_deferred("grab_focus");
}
@@ -1165,14 +1214,8 @@ ColorPicker::ColorPicker() :
hb_edit->add_child(wheel_edit);
wheel_mat.instance();
- circle_mat.instance();
-
- Ref<Shader> wheel_shader(memnew(Shader));
- wheel_shader->set_code("shader_type canvas_item;const float TAU=6.28318530718;void fragment(){float x=UV.x-0.5;float y=UV.y-0.5;float a=atan(y,x);x+=0.001;y+=0.001;float b=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);x-=0.002;float b2=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);y-=0.002;float b3=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);x+=0.002;float b4=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);COLOR=vec4(clamp((abs(fract(((a-TAU)/TAU)+vec3(3.0,2.0,1.0)/3.0)*6.0-3.0)-1.0),0.0,1.0),(b+b2+b3+b4)/4.00);}");
wheel_mat->set_shader(wheel_shader);
-
- Ref<Shader> circle_shader(memnew(Shader));
- circle_shader->set_code("shader_type canvas_item;const float TAU=6.28318530718;uniform float v=1.0;void fragment(){float x=UV.x-0.5;float y=UV.y-0.5;float a=atan(y,x);x+=0.001;y+=0.001;float b=float(sqrt(x*x+y*y)<0.5);x-=0.002;float b2=float(sqrt(x*x+y*y)<0.5);y-=0.002;float b3=float(sqrt(x*x+y*y)<0.5);x+=0.002;float b4=float(sqrt(x*x+y*y)<0.5);COLOR=vec4(mix(vec3(1.0),clamp(abs(fract(vec3((a-TAU)/TAU)+vec3(1.0,2.0/3.0,1.0/3.0))*6.0-vec3(3.0))-vec3(1.0),0.0,1.0),((float(sqrt(x*x+y*y))*2.0))/1.0)*vec3(v),(b+b2+b3+b4)/4.00);}");
+ circle_mat.instance();
circle_mat->set_shader(circle_shader);
MarginContainer *wheel_margin(memnew(MarginContainer));
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 400074e6e9..14113467d0 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -56,6 +56,9 @@ public:
};
private:
+ static Ref<Shader> wheel_shader;
+ static Ref<Shader> circle_shader;
+
Control *screen = nullptr;
Control *uv_edit = memnew(Control);
Control *w_edit = memnew(Control);
@@ -128,6 +131,9 @@ protected:
static void _bind_methods();
public:
+ static void init_shaders();
+ static void finish_shaders();
+
void set_edit_alpha(bool p_show);
bool is_editing_alpha() const;
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index ce5eef93aa..c84627c21e 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -168,6 +168,12 @@ Size2 Control::_edit_get_minimum_size() const {
}
#endif
+void Control::accept_event() {
+ if (is_inside_tree()) {
+ get_viewport()->_gui_accept_event();
+ }
+}
+
void Control::set_custom_minimum_size(const Size2 &p_custom) {
if (p_custom == data.custom_minimum_size) {
return;
@@ -509,7 +515,9 @@ void Control::_notification(int p_notification) {
get_viewport()->_gui_remove_control(this);
} break;
case NOTIFICATION_READY: {
+#ifdef DEBUG_ENABLED
connect("ready", callable_mp(this, &Control::_clear_size_warning), varray(), CONNECT_DEFERRED | CONNECT_ONESHOT);
+#endif
} break;
case NOTIFICATION_ENTER_CANVAS: {
@@ -654,7 +662,7 @@ bool Control::has_point(const Point2 &p_point) const {
Variant v = p_point;
const Variant *p = &v;
Callable::CallError ce;
- Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->has_point, &p, 1, ce);
+ Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_has_point, &p, 1, ce);
if (ce.error == Callable::CallError::CALL_OK) {
return ret;
}
@@ -679,7 +687,7 @@ Variant Control::get_drag_data(const Point2 &p_point) {
Object *obj = ObjectDB::get_instance(data.drag_owner);
if (obj) {
Control *c = Object::cast_to<Control>(obj);
- return c->call("get_drag_data_fw", p_point, this);
+ return c->call("_get_drag_data_fw", p_point, this);
}
}
@@ -687,7 +695,7 @@ Variant Control::get_drag_data(const Point2 &p_point) {
Variant v = p_point;
const Variant *p = &v;
Callable::CallError ce;
- Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->get_drag_data, &p, 1, ce);
+ Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_get_drag_data, &p, 1, ce);
if (ce.error == Callable::CallError::CALL_OK) {
return ret;
}
@@ -701,7 +709,7 @@ bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const
Object *obj = ObjectDB::get_instance(data.drag_owner);
if (obj) {
Control *c = Object::cast_to<Control>(obj);
- return c->call("can_drop_data_fw", p_point, p_data, this);
+ return c->call("_can_drop_data_fw", p_point, p_data, this);
}
}
@@ -709,7 +717,7 @@ bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const
Variant v = p_point;
const Variant *p[2] = { &v, &p_data };
Callable::CallError ce;
- Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->can_drop_data, p, 2, ce);
+ Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_can_drop_data, p, 2, ce);
if (ce.error == Callable::CallError::CALL_OK) {
return ret;
}
@@ -723,7 +731,7 @@ void Control::drop_data(const Point2 &p_point, const Variant &p_data) {
Object *obj = ObjectDB::get_instance(data.drag_owner);
if (obj) {
Control *c = Object::cast_to<Control>(obj);
- c->call("drop_data_fw", p_point, p_data, this);
+ c->call("_drop_data_fw", p_point, p_data, this);
return;
}
}
@@ -732,7 +740,7 @@ void Control::drop_data(const Point2 &p_point, const Variant &p_data) {
Variant v = p_point;
const Variant *p[2] = { &v, &p_data };
Callable::CallError ce;
- Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->drop_data, p, 2, ce);
+ Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_drop_data, p, 2, ce);
if (ce.error == Callable::CallError::CALL_OK) {
return;
}
@@ -765,32 +773,27 @@ Size2 Control::get_minimum_size() const {
}
template <class T>
-bool Control::_find_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, T &r_ret, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_node_type) {
- // try with custom themes
+T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) {
+ ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, T(), "At least one theme type must be specified.");
+
+ // First, look through each control or window node in the branch, until no valid parent can be found.
+ // For each control iterate through its inheritance chain and see if p_name exists in any of them.
Control *theme_owner = p_theme_owner;
Window *theme_owner_window = p_theme_owner_window;
while (theme_owner || theme_owner_window) {
- StringName class_name = p_node_type;
-
- while (class_name != StringName()) {
- if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) {
- r_ret = (theme_owner->data.theme.operator->()->*get_func)(p_name, class_name);
- return true;
+ for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
+ if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E->get())) {
+ return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E->get());
}
- if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) {
- r_ret = (theme_owner_window->theme.operator->()->*get_func)(p_name, class_name);
- return true;
+ if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E->get())) {
+ return theme_owner_window->theme->get_theme_item(p_data_type, p_name, E->get());
}
-
- class_name = ClassDB::get_parent_class_nocheck(class_name);
}
Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
-
Control *parent_c = Object::cast_to<Control>(parent);
-
if (parent_c) {
theme_owner = parent_c->data.theme_owner;
theme_owner_window = parent_c->data.theme_owner_window;
@@ -805,33 +808,47 @@ bool Control::_find_theme_item(Control *p_theme_owner, Window *p_theme_owner_win
}
}
}
- return false;
+
+ // Secondly, check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
+ if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E->get())) {
+ return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E->get());
+ }
+ }
+ }
+
+ // Lastly, fall back on the items defined in the default Theme, if they exist.
+ for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
+ if (Theme::get_default()->has_theme_item(p_data_type, p_name, E->get())) {
+ return Theme::get_default()->get_theme_item(p_data_type, p_name, E->get());
+ }
+ }
+ // If they don't exist, use any type to return the default/empty value.
+ return Theme::get_default()->get_theme_item(p_data_type, p_name, p_theme_types[0]);
}
-bool Control::_has_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_node_type) {
- // try with custom themes
+bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) {
+ ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, false, "At least one theme type must be specified.");
+
+ // First, look through each control or window node in the branch, until no valid parent can be found.
+ // For each control iterate through its inheritance chain and see if p_name exists in any of them.
Control *theme_owner = p_theme_owner;
Window *theme_owner_window = p_theme_owner_window;
while (theme_owner || theme_owner_window) {
- StringName class_name = p_node_type;
-
- while (class_name != StringName()) {
- if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) {
+ for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
+ if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E->get())) {
return true;
}
- if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) {
+ if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E->get())) {
return true;
}
-
- class_name = ClassDB::get_parent_class_nocheck(class_name);
}
Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
-
Control *parent_c = Object::cast_to<Control>(parent);
-
if (parent_c) {
theme_owner = parent_c->data.theme_owner;
theme_owner_window = parent_c->data.theme_owner_window;
@@ -846,179 +863,112 @@ bool Control::_has_theme_item(Control *p_theme_owner, Window *p_theme_owner_wind
}
}
}
- return false;
-}
-Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
- const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
- if (tex) {
- return *tex;
+ // Secondly, check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
+ if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E->get())) {
+ return true;
+ }
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return get_icons(data.theme_owner, data.theme_owner_window, p_name, type);
+ // Lastly, fall back on the items defined in the default Theme, if they exist.
+ for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
+ if (Theme::get_default()->has_theme_item(p_data_type, p_name, E->get())) {
+ return true;
+ }
+ }
+ return false;
}
-Ref<Texture2D> Control::get_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- Ref<Texture2D> icon;
-
- if (_find_theme_item(p_theme_owner, p_theme_owner_window, icon, &Theme::get_icon, &Theme::has_icon, p_name, p_node_type)) {
- return icon;
+void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (data.theme_custom_type != StringName()) {
+ p_list->push_back(data.theme_custom_type);
+ }
+ Theme::get_type_dependencies(get_class_name(), p_list);
+ } else {
+ Theme::get_type_dependencies(p_theme_type, p_list);
}
+}
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_icon(p_name, p_node_type)) {
- return Theme::get_project_default()->get_icon(p_name, p_node_type);
+Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
+ if (tex) {
+ return *tex;
}
}
- return Theme::get_default()->get_icon(p_name, p_node_type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<Ref<Texture2D>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
}
-Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
const Ref<StyleBox> *style = data.style_override.getptr(p_name);
if (style) {
return *style;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return get_styleboxs(data.theme_owner, data.theme_owner_window, p_name, type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<Ref<StyleBox>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
}
-Ref<StyleBox> Control::get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- Ref<StyleBox> stylebox;
-
- if (_find_theme_item(p_theme_owner, p_theme_owner_window, stylebox, &Theme::get_stylebox, &Theme::has_stylebox, p_name, p_node_type)) {
- return stylebox;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_stylebox(p_name, p_node_type)) {
- return Theme::get_project_default()->get_stylebox(p_name, p_node_type);
- }
- }
-
- return Theme::get_default()->get_stylebox(p_name, p_node_type);
-}
-
-Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
const Ref<Font> *font = data.font_override.getptr(p_name);
if (font) {
return *font;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return get_fonts(data.theme_owner, data.theme_owner_window, p_name, type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<Ref<Font>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
}
-int Control::get_theme_font_size(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
const int *font_size = data.font_size_override.getptr(p_name);
if (font_size) {
return *font_size;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return get_font_sizes(data.theme_owner, data.theme_owner_window, p_name, type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
}
-Ref<Font> Control::get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- Ref<Font> font;
-
- if (_find_theme_item(p_theme_owner, p_theme_owner_window, font, &Theme::get_font, &Theme::has_font, p_name, p_node_type)) {
- return font;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_font(p_name, p_node_type)) {
- return Theme::get_project_default()->get_font(p_name, p_node_type);
- }
- }
-
- return Theme::get_default()->get_font(p_name, p_node_type);
-}
-
-int Control::get_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- int font_size;
-
- if (_find_theme_item(p_theme_owner, p_theme_owner_window, font_size, &Theme::get_font_size, &Theme::has_font_size, p_name, p_node_type)) {
- return font_size;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_font_size(p_name, p_node_type)) {
- return Theme::get_project_default()->get_font_size(p_name, p_node_type);
- }
- }
-
- return Theme::get_default()->get_font_size(p_name, p_node_type);
-}
-
-Color Control::get_theme_color(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+Color Control::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
const Color *color = data.color_override.getptr(p_name);
if (color) {
return *color;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return get_colors(data.theme_owner, data.theme_owner_window, p_name, type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<Color>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
}
-Color Control::get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- Color color;
-
- if (_find_theme_item(p_theme_owner, p_theme_owner_window, color, &Theme::get_color, &Theme::has_color, p_name, p_node_type)) {
- return color;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_color(p_name, p_node_type)) {
- return Theme::get_project_default()->get_color(p_name, p_node_type);
- }
- }
- return Theme::get_default()->get_color(p_name, p_node_type);
-}
-
-int Control::get_theme_constant(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
const int *constant = data.constant_override.getptr(p_name);
if (constant) {
return *constant;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return get_constants(data.theme_owner, data.theme_owner_window, p_name, type);
-}
-
-int Control::get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- int constant;
-
- if (_find_theme_item(p_theme_owner, p_theme_owner_window, constant, &Theme::get_constant, &Theme::has_constant, p_name, p_node_type)) {
- return constant;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_constant(p_name, p_node_type)) {
- return Theme::get_project_default()->get_constant(p_name, p_node_type);
- }
- }
- return Theme::get_default()->get_constant(p_name, p_node_type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
}
bool Control::has_theme_icon_override(const StringName &p_name) const {
@@ -1051,154 +1001,76 @@ bool Control::has_theme_constant_override(const StringName &p_name) const {
return constant != nullptr;
}
-bool Control::has_theme_icon(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
if (has_theme_icon_override(p_name)) {
return true;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return has_icons(data.theme_owner, data.theme_owner_window, p_name, type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
}
-bool Control::has_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_icon, p_name, p_node_type)) {
- return true;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_color(p_name, p_node_type)) {
- return true;
- }
- }
- return Theme::get_default()->has_icon(p_name, p_node_type);
-}
-
-bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
if (has_theme_stylebox_override(p_name)) {
return true;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return has_styleboxs(data.theme_owner, data.theme_owner_window, p_name, type);
-}
-
-bool Control::has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_stylebox, p_name, p_node_type)) {
- return true;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_stylebox(p_name, p_node_type)) {
- return true;
- }
- }
- return Theme::get_default()->has_stylebox(p_name, p_node_type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
}
-bool Control::has_theme_font(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
if (has_theme_font_override(p_name)) {
return true;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return has_fonts(data.theme_owner, data.theme_owner_window, p_name, type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
}
-bool Control::has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_font, p_name, p_node_type)) {
- return true;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_font(p_name, p_node_type)) {
- return true;
- }
- }
- return Theme::get_default()->has_font(p_name, p_node_type);
-}
-
-bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
if (has_theme_font_size_override(p_name)) {
return true;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return has_font_sizes(data.theme_owner, data.theme_owner_window, p_name, type);
-}
-
-bool Control::has_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_font_size, p_name, p_node_type)) {
- return true;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_font_size(p_name, p_node_type)) {
- return true;
- }
- }
- return Theme::get_default()->has_font_size(p_name, p_node_type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
}
-bool Control::has_theme_color(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+bool Control::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
if (has_theme_color_override(p_name)) {
return true;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return has_colors(data.theme_owner, data.theme_owner_window, p_name, type);
-}
-
-bool Control::has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_color, p_name, p_node_type)) {
- return true;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_color(p_name, p_node_type)) {
- return true;
- }
- }
- return Theme::get_default()->has_color(p_name, p_node_type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
}
-bool Control::has_theme_constant(const StringName &p_name, const StringName &p_node_type) const {
- if (p_node_type == StringName() || p_node_type == get_class_name()) {
+bool Control::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
if (has_theme_constant_override(p_name)) {
return true;
}
}
- StringName type = p_node_type ? p_node_type : get_class_name();
-
- return has_constants(data.theme_owner, data.theme_owner_window, p_name, p_node_type);
-}
-
-bool Control::has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
- if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_constant, p_name, p_node_type)) {
- return true;
- }
-
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_constant(p_name, p_node_type)) {
- return true;
- }
- }
- return Theme::get_default()->has_constant(p_name, p_node_type);
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
}
Rect2 Control::get_parent_anchorable_rect() const {
@@ -1709,8 +1581,8 @@ void Control::set_rect(const Rect2 &p_rect) {
void Control::_set_size(const Size2 &p_size) {
#ifdef DEBUG_ENABLED
- if (data.size_warning) {
- WARN_PRINT("Adjusting the size of Control nodes before they are fully initialized is unreliable. Consider deferring it with set_deferred().");
+ if (data.size_warning && (data.anchor[SIDE_LEFT] != data.anchor[SIDE_RIGHT] || data.anchor[SIDE_TOP] != data.anchor[SIDE_BOTTOM])) {
+ WARN_PRINT("Nodes with non-equal opposite anchors will have their size overriden after _ready(). \nIf you want to set size, change the anchors or consider using set_deferred().");
}
#endif
set_size(p_size);
@@ -2171,16 +2043,19 @@ void Control::set_theme(const Ref<Theme> &p_theme) {
}
}
-void Control::accept_event() {
- if (is_inside_tree()) {
- get_viewport()->_gui_accept_event();
- }
-}
-
Ref<Theme> Control::get_theme() const {
return data.theme;
}
+void Control::set_theme_custom_type(const StringName &p_theme_type) {
+ data.theme_custom_type = p_theme_type;
+ _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window);
+}
+
+StringName Control::get_theme_custom_type() const {
+ return data.theme_custom_type;
+}
+
void Control::set_tooltip(const String &p_tooltip) {
data.tooltip = p_tooltip;
update_configuration_warnings();
@@ -2499,9 +2374,9 @@ bool Control::is_text_field() const {
return false;
}
-Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_node_type, const Array &p_args, const String p_text) const {
+Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const {
Vector<Vector2i> ret;
- switch (p_node_type) {
+ switch (p_theme_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
for (int i = 0; i < p_text.length(); i++) {
@@ -2811,6 +2686,9 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Control::set_theme);
ClassDB::bind_method(D_METHOD("get_theme"), &Control::get_theme);
+ ClassDB::bind_method(D_METHOD("set_theme_custom_type", "theme_type"), &Control::set_theme_custom_type);
+ ClassDB::bind_method(D_METHOD("get_theme_custom_type"), &Control::get_theme_custom_type);
+
ClassDB::bind_method(D_METHOD("add_theme_icon_override", "name", "texture"), &Control::add_theme_icon_override);
ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Control::add_theme_style_override);
ClassDB::bind_method(D_METHOD("add_theme_font_override", "name", "font"), &Control::add_theme_font_override);
@@ -2825,12 +2703,12 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_theme_color_override", "name"), &Control::remove_theme_color_override);
ClassDB::bind_method(D_METHOD("remove_theme_constant_override", "name"), &Control::remove_theme_constant_override);
- ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "node_type"), &Control::get_theme_icon, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "node_type"), &Control::get_theme_stylebox, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_font", "name", "node_type"), &Control::get_theme_font, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "node_type"), &Control::get_theme_font_size, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_color", "name", "node_type"), &Control::get_theme_color, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "node_type"), &Control::get_theme_constant, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "theme_type"), &Control::get_theme_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "theme_type"), &Control::get_theme_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_font", "name", "theme_type"), &Control::get_theme_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "theme_type"), &Control::get_theme_font_size, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_color", "name", "theme_type"), &Control::get_theme_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "theme_type"), &Control::get_theme_constant, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_icon_override", "name"), &Control::has_theme_icon_override);
ClassDB::bind_method(D_METHOD("has_theme_stylebox_override", "name"), &Control::has_theme_stylebox_override);
@@ -2839,12 +2717,12 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_theme_color_override", "name"), &Control::has_theme_color_override);
ClassDB::bind_method(D_METHOD("has_theme_constant_override", "name"), &Control::has_theme_constant_override);
- ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "node_type"), &Control::has_theme_icon, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "node_type"), &Control::has_theme_stylebox, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_font", "name", "node_type"), &Control::has_theme_font, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "node_type"), &Control::has_theme_font_size, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_color", "name", "node_type"), &Control::has_theme_color, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "node_type"), &Control::has_theme_constant, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "theme_type"), &Control::has_theme_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "theme_type"), &Control::has_theme_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_font", "name", "theme_type"), &Control::has_theme_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "theme_type"), &Control::has_theme_font_size, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_color", "name", "theme_type"), &Control::has_theme_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "theme_type"), &Control::has_theme_constant, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_parent_control"), &Control::get_parent_control);
@@ -2897,12 +2775,12 @@ void Control::_bind_methods() {
BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size"));
- MethodInfo get_drag_data = MethodInfo("get_drag_data", PropertyInfo(Variant::VECTOR2, "position"));
+ MethodInfo get_drag_data = MethodInfo("_get_drag_data", PropertyInfo(Variant::VECTOR2, "position"));
get_drag_data.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
BIND_VMETHOD(get_drag_data);
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_drop_data", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::NIL, "data")));
- BIND_VMETHOD(MethodInfo("drop_data", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::NIL, "data")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_can_drop_data", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::NIL, "data")));
+ BIND_VMETHOD(MethodInfo("_drop_data", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::NIL, "data")));
BIND_VMETHOD(MethodInfo(
PropertyInfo(Variant::OBJECT, "control", PROPERTY_HINT_RESOURCE_TYPE, "Control"),
"_make_custom_tooltip", PropertyInfo(Variant::STRING, "for_text")));
@@ -2925,7 +2803,7 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_v_grow_direction", "get_v_grow_direction");
ADD_GROUP("Layout Direction", "layout_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-right,Right-to-left"), "set_layout_direction", "get_layout_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction");
ADD_GROUP("Rect", "rect_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position");
@@ -2952,14 +2830,15 @@ void Control::_bind_methods() {
ADD_GROUP("Mouse", "mouse_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,Ibeam,Pointing hand,Cross,Wait,Busy,Drag,Can drop,Forbidden,Vertical resize,Horizontal resize,Secondary diagonal resize,Main diagonal resize,Move,Vertical split,Horizontal split,Help"), "set_default_cursor_shape", "get_default_cursor_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,I-Beam,Pointing Hand,Cross,Wait,Busy,Drag,Can Drop,Forbidden,Vertical Resize,Horizontal Resize,Secondary Diagonal Resize,Main Diagonal Resize,Move,Vertical Split,Horizontal Split,Help"), "set_default_cursor_shape", "get_default_cursor_shape");
ADD_GROUP("Size Flags", "size_flags_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags");
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_v_size_flags", "get_v_size_flags");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio");
- ADD_GROUP("Theme", "");
+ ADD_GROUP("Theme", "theme_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type");
ADD_GROUP("", "");
BIND_ENUM_CONSTANT(FOCUS_NONE);
@@ -3061,5 +2940,5 @@ void Control::_bind_methods() {
ADD_SIGNAL(MethodInfo("minimum_size_changed"));
ADD_SIGNAL(MethodInfo("theme_changed"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_point", PropertyInfo(Variant::VECTOR2, "point")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_point", PropertyInfo(Variant::VECTOR2, "point")));
}
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 1f397df589..a05025c32d 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -201,6 +201,8 @@ private:
Ref<Theme> theme;
Control *theme_owner = nullptr;
Window *theme_owner_window = nullptr;
+ StringName theme_custom_type;
+
String tooltip;
CursorShape default_cursor = CURSOR_ARROW;
@@ -258,23 +260,9 @@ private:
static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true);
template <class T>
- _FORCE_INLINE_ static bool _find_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, T &, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_node_type);
-
- _FORCE_INLINE_ static bool _has_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_node_type);
-
- static Ref<Texture2D> get_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static Ref<StyleBox> get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static Ref<Font> get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static int get_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static Color get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static int get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
-
- static bool has_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static bool has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static bool has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static bool has_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static bool has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
- static bool has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
+ static T get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types);
+ static bool has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types);
+ _FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const;
protected:
virtual void add_child_notify(Node *p_child) override;
@@ -282,7 +270,7 @@ protected:
//virtual void _window_gui_input(InputEvent p_event);
- virtual Vector<Vector2i> structured_text_parser(StructuredTextParser p_node_type, const Array &p_args, const String p_text) const;
+ virtual Vector<Vector2i> structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const;
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -415,6 +403,9 @@ public:
void set_theme(const Ref<Theme> &p_theme);
Ref<Theme> get_theme() const;
+ void set_theme_custom_type(const StringName &p_theme_type);
+ StringName get_theme_custom_type() const;
+
void set_h_size_flags(int p_flags);
int get_h_size_flags() const;
@@ -466,12 +457,12 @@ public:
void remove_theme_color_override(const StringName &p_name);
void remove_theme_constant_override(const StringName &p_name);
- Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- int get_theme_font_size(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- Color get_theme_color(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- int get_theme_constant(const StringName &p_name, const StringName &p_node_type = StringName()) const;
+ Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ int get_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ Color get_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ int get_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
bool has_theme_icon_override(const StringName &p_name) const;
bool has_theme_stylebox_override(const StringName &p_name) const;
@@ -480,12 +471,12 @@ public:
bool has_theme_color_override(const StringName &p_name) const;
bool has_theme_constant_override(const StringName &p_name) const;
- bool has_theme_icon(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- bool has_theme_stylebox(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- bool has_theme_font(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- bool has_theme_font_size(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- bool has_theme_color(const StringName &p_name, const StringName &p_node_type = StringName()) const;
- bool has_theme_constant(const StringName &p_name, const StringName &p_node_type = StringName()) const;
+ bool has_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
/* TOOLTIP */
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index b6884bd37d..7cae091c57 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -155,7 +155,7 @@ bool AcceptDialog::has_autowrap() {
return label->has_autowrap();
}
-void AcceptDialog::register_text_enter(Node *p_line_edit) {
+void AcceptDialog::register_text_enter(Control *p_line_edit) {
ERR_FAIL_NULL(p_line_edit);
LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit);
if (line_edit) {
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index b072055d49..69035001c0 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -77,7 +77,7 @@ public:
Label *get_label() { return label; }
static void set_swap_cancel_ok(bool p_swap);
- void register_text_enter(Node *p_line_edit);
+ void register_text_enter(Control *p_line_edit);
Button *get_ok_button() { return ok; }
Button *add_button(const String &p_text, bool p_right = false, const String &p_action = "");
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 5409b44b9e..806039d7ac 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -105,7 +105,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
switch (k->get_keycode()) {
case KEY_H: {
- if (k->get_command()) {
+ if (k->is_command_pressed()) {
set_show_hidden_files(!show_hidden_files);
} else {
handled = false;
@@ -589,8 +589,8 @@ void FileDialog::update_file_list() {
files.pop_front();
}
- if (tree->get_root() && tree->get_root()->get_children() && tree->get_selected() == nullptr) {
- tree->get_root()->get_children()->select(0);
+ if (tree->get_root() && tree->get_root()->get_first_child() && tree->get_selected() == nullptr) {
+ tree->get_root()->get_first_child()->select(0);
}
}
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 4996f00cb3..55774b488c 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -32,7 +32,7 @@
#define FILE_DIALOG_H
#include "box_container.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index ebefb2938f..7278ca6e94 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -127,7 +127,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
//Hold alt key to duplicate selected color
- if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->get_alt()) {
+ if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->is_alt_pressed()) {
int x = mb->get_position().x;
grabbed = _get_point_from_pos(x);
@@ -236,9 +236,9 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
// Snap to "round" coordinates if holding Ctrl.
// Be more precise if holding Shift as well
- if (mm->get_control()) {
- newofs = Math::snapped(newofs, mm->get_shift() ? 0.025 : 0.1);
- } else if (mm->get_shift()) {
+ if (mm->is_ctrl_pressed()) {
+ newofs = Math::snapped(newofs, mm->is_shift_pressed() ? 0.025 : 0.1);
+ } else if (mm->is_shift_pressed()) {
// Snap to nearest point if holding just Shift
const float snap_threshold = 0.03;
float smallest_ofs = snap_threshold;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 06c9cf1b63..1e444e439d 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -42,8 +42,13 @@
#define ZOOM_SCALE 1.2
-#define MIN_ZOOM (((1 / ZOOM_SCALE) / ZOOM_SCALE) / ZOOM_SCALE)
-#define MAX_ZOOM (1 * ZOOM_SCALE * ZOOM_SCALE * ZOOM_SCALE)
+// Allow dezooming 8 times from the default zoom level.
+// At low zoom levels, text is unreadable due to its small size and poor filtering,
+// but this is still useful for previewing purposes.
+#define MIN_ZOOM (1 / Math::pow(ZOOM_SCALE, 8))
+
+// Allow zooming 4 times from the default zoom level.
+#define MAX_ZOOM (1 * Math::pow(ZOOM_SCALE, 4))
#define MINIMAP_OFFSET 12
#define MINIMAP_PADDING 5
@@ -824,7 +829,7 @@ void GraphEdit::_bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors,
}
}
-void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_bezier_ratio = 1.0) {
+void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_bezier_ratio) {
//cubic bezier code
float diff = p_to.x - p_from.x;
float cp_offset;
@@ -1091,7 +1096,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
// Snapping can be toggled temporarily by holding down Ctrl.
// This is done here as to not toggle the grid when holding down Ctrl.
- if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
const int snap = get_snap();
pos = pos.snapped(Vector2(snap, snap));
}
@@ -1174,7 +1179,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && dragging) {
- if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
//deselect current node
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
@@ -1238,7 +1243,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
dragging = true;
drag_accum = Vector2();
just_selected = !gn->is_selected();
- if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
for (int i = 0; i < get_child_count(); i++) {
GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i));
if (o_gn) {
@@ -1275,7 +1280,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
box_selecting = true;
box_selecting_from = b->get_position();
- if (b->get_control()) {
+ if (b->is_ctrl_pressed()) {
box_selection_mode_additive = true;
previous_selected.clear();
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -1286,7 +1291,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
previous_selected.push_back(gn2);
}
- } else if (b->get_shift()) {
+ } else if (b->is_shift_pressed()) {
box_selection_mode_additive = false;
previous_selected.clear();
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -1322,9 +1327,9 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
minimap->update();
}
- if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
set_zoom_custom(zoom * ZOOM_SCALE, b->get_position());
- } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
set_zoom_custom(zoom / ZOOM_SCALE, b->get_position());
} else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index fa3b113705..8a51bcb11e 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -163,7 +163,7 @@ private:
void _bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const;
- void _draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_bezier_ratio);
+ void _draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_bezier_ratio = 1.0);
void _graph_node_raised(Node *p_gn);
void _graph_node_moved(Node *p_gn);
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 7d5c53effe..77c502cf8d 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -228,7 +228,7 @@ void GraphNode::_resort() {
}
stretch_avail += stretch_diff - sb->get_margin(SIDE_BOTTOM) - sb->get_margin(SIDE_TOP); //available stretch space.
- /** Second, pass sucessively to discard elements that can't be stretched, this will run while stretchable
+ /** Second, pass successively to discard elements that can't be stretched, this will run while stretchable
elements exist */
while (stretch_ratio_total > 0) { // first of all, don't even be here if no stretchable objects exist
@@ -459,7 +459,7 @@ void GraphNode::_shape() {
}
void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right) {
- ERR_FAIL_COND(p_idx < 0);
+ ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set slot with p_idx (%d) lesser than zero.", p_idx));
if (!p_enable_left && p_type_left == 0 && p_color_left == Color(1, 1, 1, 1) &&
!p_enable_right && p_type_right == 0 && p_color_right == Color(1, 1, 1, 1) &&
@@ -503,6 +503,26 @@ bool GraphNode::is_slot_enabled_left(int p_idx) const {
return slot_info[p_idx].enable_left;
}
+void GraphNode::set_slot_enabled_left(int p_idx, bool p_enable_left) {
+ ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set enable_left for the slot with p_idx (%d) lesser than zero.", p_idx));
+
+ slot_info[p_idx].enable_left = p_enable_left;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
+void GraphNode::set_slot_type_left(int p_idx, int p_type_left) {
+ ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set type_left for the slot '%d' because it hasn't been enabled.", p_idx));
+
+ slot_info[p_idx].type_left = p_type_left;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
int GraphNode::get_slot_type_left(int p_idx) const {
if (!slot_info.has(p_idx)) {
return 0;
@@ -510,6 +530,16 @@ int GraphNode::get_slot_type_left(int p_idx) const {
return slot_info[p_idx].type_left;
}
+void GraphNode::set_slot_color_left(int p_idx, const Color &p_color_left) {
+ ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set color_left for the slot '%d' because it hasn't been enabled.", p_idx));
+
+ slot_info[p_idx].color_left = p_color_left;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
Color GraphNode::get_slot_color_left(int p_idx) const {
if (!slot_info.has(p_idx)) {
return Color(1, 1, 1, 1);
@@ -524,6 +554,26 @@ bool GraphNode::is_slot_enabled_right(int p_idx) const {
return slot_info[p_idx].enable_right;
}
+void GraphNode::set_slot_enabled_right(int p_idx, bool p_enable_right) {
+ ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set enable_right for the slot with p_idx (%d) lesser than zero.", p_idx));
+
+ slot_info[p_idx].enable_right = p_enable_right;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
+void GraphNode::set_slot_type_right(int p_idx, int p_type_right) {
+ ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set type_right for the slot '%d' because it hasn't been enabled.", p_idx));
+
+ slot_info[p_idx].type_right = p_type_right;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
int GraphNode::get_slot_type_right(int p_idx) const {
if (!slot_info.has(p_idx)) {
return 0;
@@ -531,6 +581,16 @@ int GraphNode::get_slot_type_right(int p_idx) const {
return slot_info[p_idx].type_right;
}
+void GraphNode::set_slot_color_right(int p_idx, const Color &p_color_right) {
+ ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set color_right for the slot '%d' because it hasn't been enabled.", p_idx));
+
+ slot_info[p_idx].color_right = p_color_right;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
Color GraphNode::get_slot_color_right(int p_idx) const {
if (!slot_info.has(p_idx)) {
return Color(1, 1, 1, 1);
@@ -891,11 +951,23 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right"), &GraphNode::set_slot, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("clear_slot", "idx"), &GraphNode::clear_slot);
ClassDB::bind_method(D_METHOD("clear_all_slots"), &GraphNode::clear_all_slots);
+
ClassDB::bind_method(D_METHOD("is_slot_enabled_left", "idx"), &GraphNode::is_slot_enabled_left);
+ ClassDB::bind_method(D_METHOD("set_slot_enabled_left", "idx", "enable_left"), &GraphNode::set_slot_enabled_left);
+
+ ClassDB::bind_method(D_METHOD("set_slot_type_left", "idx", "type_left"), &GraphNode::set_slot_type_left);
ClassDB::bind_method(D_METHOD("get_slot_type_left", "idx"), &GraphNode::get_slot_type_left);
+
+ ClassDB::bind_method(D_METHOD("set_slot_color_left", "idx", "color_left"), &GraphNode::set_slot_color_left);
ClassDB::bind_method(D_METHOD("get_slot_color_left", "idx"), &GraphNode::get_slot_color_left);
+
ClassDB::bind_method(D_METHOD("is_slot_enabled_right", "idx"), &GraphNode::is_slot_enabled_right);
+ ClassDB::bind_method(D_METHOD("set_slot_enabled_right", "idx", "enable_right"), &GraphNode::set_slot_enabled_right);
+
+ ClassDB::bind_method(D_METHOD("set_slot_type_right", "idx", "type_right"), &GraphNode::set_slot_type_right);
ClassDB::bind_method(D_METHOD("get_slot_type_right", "idx"), &GraphNode::get_slot_type_right);
+
+ ClassDB::bind_method(D_METHOD("set_slot_color_right", "idx", "color_right"), &GraphNode::set_slot_color_right);
ClassDB::bind_method(D_METHOD("get_slot_color_right", "idx"), &GraphNode::get_slot_color_right);
ClassDB::bind_method(D_METHOD("set_position_offset", "offset"), &GraphNode::set_position_offset);
@@ -927,7 +999,7 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_overlay"), &GraphNode::get_overlay);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset"), "set_position_offset", "get_position_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index 1bc54dddb7..c70f616b47 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -113,11 +113,23 @@ public:
void set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left = Ref<Texture2D>(), const Ref<Texture2D> &p_custom_right = Ref<Texture2D>());
void clear_slot(int p_idx);
void clear_all_slots();
+
bool is_slot_enabled_left(int p_idx) const;
+ void set_slot_enabled_left(int p_idx, bool p_enable_left);
+
+ void set_slot_type_left(int p_idx, int p_type_left);
int get_slot_type_left(int p_idx) const;
+
+ void set_slot_color_left(int p_idx, const Color &p_color_left);
Color get_slot_color_left(int p_idx) const;
+
bool is_slot_enabled_right(int p_idx) const;
+ void set_slot_enabled_right(int p_idx, bool p_enable_right);
+
+ void set_slot_type_right(int p_idx, int p_type_right);
int get_slot_type_right(int p_idx) const;
+
+ void set_slot_color_right(int p_idx, const Color &p_color_right);
Color get_slot_color_right(int p_idx) const;
void set_title(const String &p_title);
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 541925a802..a54f5eef06 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -33,7 +33,7 @@
void GridContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
- Map<int, int> col_minw; // Max of min_width of all controls in each col (indexed by col).
+ Map<int, int> col_minw; // Max of min_width of all controls in each col (indexed by col).
Map<int, int> row_minh; // Max of min_height of all controls in each row (indexed by row).
Set<int> col_expanded; // Columns which have the SIZE_EXPAND flag set.
Set<int> row_expanded; // Rows which have the SIZE_EXPAND flag set.
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 0bdae2b118..150980b2e9 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -581,11 +581,11 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (closest != -1) {
int i = closest;
- if (select_mode == SELECT_MULTI && items[i].selected && mb->get_command()) {
+ if (select_mode == SELECT_MULTI && items[i].selected && mb->is_command_pressed()) {
deselect(i);
emit_signal("multi_selected", i, false);
- } else if (select_mode == SELECT_MULTI && mb->get_shift() && current >= 0 && current < items.size() && current != i) {
+ } else if (select_mode == SELECT_MULTI && mb->is_shift_pressed() && current >= 0 && current < items.size() && current != i) {
int from = current;
int to = i;
if (i < current) {
@@ -603,7 +603,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
emit_signal("item_rmb_selected", i, get_local_mouse_position());
}
} else {
- if (!mb->is_double_click() && !mb->get_command() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (!mb->is_double_click() && !mb->is_command_pressed() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
defer_select_single = i;
return;
}
@@ -613,7 +613,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
} else {
bool selected = items[i].selected;
- select(i, select_mode == SELECT_SINGLE || !mb->get_command());
+ select(i, select_mode == SELECT_SINGLE || !mb->is_command_pressed());
if (!selected || allow_reselect) {
if (select_mode == SELECT_SINGLE) {
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index be73fd8f51..0ce0130ad5 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -217,6 +217,7 @@ void Label::_notification(int p_what) {
for (int64_t i = lines_skipped; i < last_line; i++) {
total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM) + line_spacing;
}
+ total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM);
int vbegin = 0, vsep = 0;
if (lines_visible > 0) {
@@ -695,7 +696,7 @@ void Label::_bind_methods() {
BIND_ENUM_CONSTANT(VALIGN_FILL);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align");
ADD_PROPERTY(PropertyInfo(Variant::INT, "valign", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_valign", "get_valign");
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index bfd739788f..c2ed9c1a3c 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -250,11 +250,11 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
return;
}
- shift_selection_check_pre(b->get_shift());
+ shift_selection_check_pre(b->is_shift_pressed());
set_caret_at_pixel_pos(b->get_position().x);
- if (b->get_shift()) {
+ if (b->is_shift_pressed()) {
selection_fill_at_caret();
selection.creating = true;
@@ -442,9 +442,9 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
// Cursor Movement
k = k->duplicate();
- bool shift_pressed = k->get_shift();
+ bool shift_pressed = k->is_shift_pressed();
// Remove shift or else actions will not match. Use above variable for selection.
- k->set_shift(false);
+ k->set_shift_pressed(false);
if (k->is_action("ui_text_caret_word_left", true)) {
_move_caret_left(shift_pressed, true);
@@ -490,7 +490,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
// Allow unicode handling if:
// * No Modifiers are pressed (except shift)
- bool allow_unicode_handling = !(k->get_command() || k->get_control() || k->get_alt() || k->get_metakey());
+ bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed());
if (allow_unicode_handling && editable && k->get_unicode() >= 32) {
// Handle Unicode (if no modifiers active)
@@ -2209,7 +2209,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars");
ADD_GROUP("Structured Text", "structured_text_");
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 1f7b61e3d1..d45ffde715 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -292,7 +292,7 @@ void LinkButton::_bind_methods() {
BIND_ENUM_CONSTANT(UNDERLINE_MODE_NEVER);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
ADD_GROUP("Structured Text", "structured_text_");
diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp
index 29a38ad5e3..8bf25ac915 100644
--- a/scene/gui/nine_patch_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -30,6 +30,7 @@
#include "nine_patch_rect.h"
+#include "scene/scene_string_names.h"
#include "servers/rendering_server.h"
void NinePatchRect::_notification(int p_what) {
@@ -97,7 +98,7 @@ void NinePatchRect::set_texture(const Ref<Texture2D> &p_tex) {
texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites
*/
minimum_size_changed();
- emit_signal("texture_changed");
+ emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
Ref<Texture2D> NinePatchRect::get_texture() const {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 44df8eafdc..2100707d2d 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1282,16 +1282,16 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo
if (code == 0) {
code = k->get_unicode();
}
- if (k->get_control()) {
+ if (k->is_ctrl_pressed()) {
code |= KEY_MASK_CTRL;
}
- if (k->get_alt()) {
+ if (k->is_alt_pressed()) {
code |= KEY_MASK_ALT;
}
- if (k->get_metakey()) {
+ if (k->is_meta_pressed()) {
code |= KEY_MASK_META;
}
- if (k->get_shift()) {
+ if (k->is_shift_pressed()) {
code |= KEY_MASK_SHIFT;
}
}
diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h
index f2e2823eff..d809fd502f 100644
--- a/scene/gui/rich_text_effect.h
+++ b/scene/gui/rich_text_effect.h
@@ -47,8 +47,8 @@ public:
RichTextEffect();
};
-class CharFXTransform : public Reference {
- GDCLASS(CharFXTransform, Reference);
+class CharFXTransform : public RefCounted {
+ GDCLASS(CharFXTransform, RefCounted);
protected:
static void _bind_methods();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 2800ab0442..a2c3b4ed8a 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2232,18 +2232,22 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub
int size = p_item->subitems.size();
if (size == 0) {
p_item->parent->subitems.erase(p_item);
+ // If a newline was erased, all lines AFTER the newline need to be decremented.
if (p_item->type == ITEM_NEWLINE) {
current_frame->lines.remove(p_line);
- for (int i = p_subitem_line; i < current->subitems.size(); i++) {
- if (current->subitems[i]->line > 0) {
+ for (int i = 0; i < current->subitems.size(); i++) {
+ if (current->subitems[i]->line > p_subitem_line) {
current->subitems[i]->line--;
}
}
}
} else {
+ // First, remove all child items for the provided item.
for (int i = 0; i < size; i++) {
_remove_item(p_item->subitems.front()->get(), p_line, p_subitem_line);
}
+ // Then remove the provided item itself.
+ p_item->parent->subitems.erase(p_item);
}
}
@@ -2303,21 +2307,23 @@ bool RichTextLabel::remove_line(const int p_line) {
return false;
}
- int i = 0;
- while (i < current->subitems.size() && current->subitems[i]->line < p_line) {
- i++;
+ // Remove all subitems with the same line as that provided.
+ Vector<int> subitem_indices_to_remove;
+ for (int i = 0; i < current->subitems.size(); i++) {
+ if (current->subitems[i]->line == p_line) {
+ subitem_indices_to_remove.push_back(i);
+ }
}
- bool was_newline = false;
- while (i < current->subitems.size()) {
- was_newline = current->subitems[i]->type == ITEM_NEWLINE;
- _remove_item(current->subitems[i], current->subitems[i]->line, p_line);
- if (was_newline) {
- break;
- }
+ bool had_newline = false;
+ // Reverse for loop to remove items from the end first.
+ for (int i = subitem_indices_to_remove.size() - 1; i >= 0; i--) {
+ int subitem_idx = subitem_indices_to_remove[i];
+ had_newline = had_newline || current->subitems[subitem_idx]->type == ITEM_NEWLINE;
+ _remove_item(current->subitems[subitem_idx], current->subitems[subitem_idx]->line, p_line);
}
- if (!was_newline) {
+ if (!had_newline) {
current_frame->lines.remove(p_line);
if (current_frame->lines.size() == 0) {
current_frame->lines.resize(1);
@@ -2329,6 +2335,7 @@ bool RichTextLabel::remove_line(const int p_line) {
}
main->first_invalid_line = 0; // p_line ???
+ update();
return true;
}
@@ -2613,14 +2620,6 @@ void RichTextLabel::pop() {
current = current->parent;
}
-// Creates a new line without adding an ItemNewline to the previous line.
-// Useful when wanting to calling remove_line and add a new line immediately after.
-void RichTextLabel::increment_line_count() {
- _validate_line_caches(main);
- current_frame->lines.resize(current_frame->lines.size() + 1);
- _invalidate_current_line(current_frame);
-}
-
void RichTextLabel::clear() {
main->_clear_children();
current = main;
@@ -3935,7 +3934,7 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_ARRAY_TYPE, "RichTextEffect", (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE)), "set_effects", "get_effects");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_GROUP("Structured Text", "structured_text_");
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index afc88e070a..e3e457d1f2 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -483,8 +483,6 @@ public:
void push_cell();
void pop();
- void increment_line_count();
-
void clear();
void set_offset(int p_pixel);
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 67dcf458b0..5f872644ab 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -98,7 +98,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb.is_valid()) {
if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) {
// only horizontal is enabled, scroll horizontally
- if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) {
+ if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) {
h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor());
} else if (v_scroll->is_visible_in_tree()) {
v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8 * mb->get_factor());
@@ -107,7 +107,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) {
// only horizontal is enabled, scroll horizontally
- if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) {
+ if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) {
h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor());
} else if (v_scroll->is_visible()) {
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8 * mb->get_factor());
@@ -238,32 +238,25 @@ void ScrollContainer::_update_scrollbar_position() {
_updating_scrollbars = false;
}
-void ScrollContainer::_ensure_focused_visible(Control *p_control) {
- if (!follow_focus) {
- return;
+void ScrollContainer::_gui_focus_changed(Control *p_control) {
+ if (follow_focus && is_a_parent_of(p_control)) {
+ ensure_control_visible(p_control);
}
+}
- if (is_a_parent_of(p_control)) {
- Rect2 global_rect = get_global_rect();
- Rect2 other_rect = p_control->get_global_rect();
- float right_margin = 0.0;
- if (v_scroll->is_visible()) {
- right_margin += v_scroll->get_size().x;
- }
- float bottom_margin = 0.0;
- if (h_scroll->is_visible()) {
- bottom_margin += h_scroll->get_size().y;
- }
+void ScrollContainer::ensure_control_visible(Control *p_control) {
+ ERR_FAIL_COND_MSG(!is_a_parent_of(p_control), "Must be a parent of the control.");
- float diff = MAX(MIN(other_rect.position.y, global_rect.position.y), other_rect.position.y + other_rect.size.y - global_rect.size.y + bottom_margin);
- set_v_scroll(get_v_scroll() + (diff - global_rect.position.y));
- if (is_layout_rtl()) {
- diff = MAX(MIN(other_rect.position.x, global_rect.position.x), other_rect.position.x + other_rect.size.x - global_rect.size.x);
- } else {
- diff = MAX(MIN(other_rect.position.x, global_rect.position.x), other_rect.position.x + other_rect.size.x - global_rect.size.x + right_margin);
- }
- set_h_scroll(get_h_scroll() + (diff - global_rect.position.x));
- }
+ Rect2 global_rect = get_global_rect();
+ Rect2 other_rect = p_control->get_global_rect();
+ float right_margin = v_scroll->is_visible() ? v_scroll->get_size().x : 0.0f;
+ float bottom_margin = h_scroll->is_visible() ? h_scroll->get_size().y : 0.0f;
+
+ Vector2 diff = Vector2(MAX(MIN(other_rect.position.x, global_rect.position.x), other_rect.position.x + other_rect.size.x - global_rect.size.x + (!is_layout_rtl() ? right_margin : 0.0f)),
+ MAX(MIN(other_rect.position.y, global_rect.position.y), other_rect.position.y + other_rect.size.y - global_rect.size.y + bottom_margin));
+
+ set_h_scroll(get_h_scroll() + (diff.x - global_rect.position.x));
+ set_v_scroll(get_v_scroll() + (diff.y - global_rect.position.y));
}
void ScrollContainer::_update_dimensions() {
@@ -334,7 +327,7 @@ void ScrollContainer::_notification(int p_what) {
};
if (p_what == NOTIFICATION_READY) {
- get_viewport()->connect("gui_focus_changed", callable_mp(this, &ScrollContainer::_ensure_focused_visible));
+ get_viewport()->connect("gui_focus_changed", callable_mp(this, &ScrollContainer::_gui_focus_changed));
_update_dimensions();
}
@@ -608,6 +601,7 @@ void ScrollContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_h_scrollbar"), &ScrollContainer::get_h_scrollbar);
ClassDB::bind_method(D_METHOD("get_v_scrollbar"), &ScrollContainer::get_v_scrollbar);
+ ClassDB::bind_method(D_METHOD("ensure_control_visible", "control"), &ScrollContainer::ensure_control_visible);
ADD_SIGNAL(MethodInfo("scroll_started"));
ADD_SIGNAL(MethodInfo("scroll_ended"));
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index f61df70b85..c77a0d62f5 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -69,6 +69,7 @@ protected:
Size2 get_minimum_size() const override;
void _gui_input(const Ref<InputEvent> &p_gui_input);
+ void _gui_focus_changed(Control *p_control);
void _update_dimensions();
void _notification(int p_what);
@@ -77,7 +78,6 @@ protected:
bool _updating_scrollbars = false;
void _update_scrollbar_position();
- void _ensure_focused_visible(Control *p_node);
public:
void set_h_scroll(int p_pos);
@@ -106,6 +106,7 @@ public:
HScrollBar *get_h_scrollbar();
VScrollBar *get_v_scrollbar();
+ void ensure_control_visible(Control *p_control);
virtual bool clips_input() const override;
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index a407ef21cb..5947f3b99e 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -172,7 +172,7 @@ void Slider::_notification(int p_what) {
int widget_width = style->get_minimum_size().width + style->get_center_size().width;
float areasize = size.height - grabber->get_size().height;
style->draw(ci, Rect2i(Point2i(size.width / 2 - widget_width / 2, 0), Size2i(widget_width, size.height)));
- grabber_area->draw(ci, Rect2i(Point2i((size.width - widget_width) / 2, size.height - areasize * ratio - grabber->get_size().height / 2), Size2i(widget_width, areasize * ratio + grabber->get_size().width / 2)));
+ grabber_area->draw(ci, Rect2i(Point2i((size.width - widget_width) / 2, size.height - areasize * ratio - grabber->get_size().height / 2), Size2i(widget_width, areasize * ratio + grabber->get_size().height / 2)));
if (ticks > 1) {
int grabber_offset = (grabber->get_size().height / 2 - tick->get_height() / 2);
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 13ff2c5b86..df4cf9a740 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -353,7 +353,7 @@ void SplitContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "split_offset"), "set_split_offset", "get_split_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collapsed"), "set_collapsed", "is_collapsed");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "dragger_visibility", PROPERTY_HINT_ENUM, "Visible,Hidden,Hidden & Collapsed"), "set_dragger_visibility", "get_dragger_visibility");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "dragger_visibility", PROPERTY_HINT_ENUM, "Visible,Hidden,Hidden and Collapsed"), "set_dragger_visibility", "get_dragger_visibility");
BIND_ENUM_CONSTANT(DRAGGER_VISIBLE);
BIND_ENUM_CONSTANT(DRAGGER_HIDDEN);
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 6cbc5890ce..11096e7976 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -127,7 +127,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->is_command_pressed()) {
if (scrolling_enabled && buttons_visible) {
if (offset > 0) {
offset--;
@@ -136,7 +136,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->is_command_pressed()) {
if (scrolling_enabled && buttons_visible) {
if (missing_right) {
offset++;
@@ -256,6 +256,7 @@ void Tabs::_notification(int p_what) {
_update_cache();
update();
} break;
+ case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED: {
for (int i = 0; i < tabs.size(); ++i) {
_shape(i);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index c924f89709..07ccad70b1 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -253,7 +253,6 @@ void TextEdit::Text::set(int p_line, const String &p_text, const Vector<Vector2i
void TextEdit::Text::insert(int p_at, const String &p_text, const Vector<Vector2i> &p_bidi_override) {
Line line;
line.gutters.resize(gutter_count);
- line.marked = false;
line.hidden = false;
line.data = p_text;
line.bidi_override = p_bidi_override;
@@ -802,9 +801,6 @@ void TextEdit::_notification(int p_what) {
}
}
- bool is_cursor_line_visible = false;
- Point2 cursor_pos;
-
// Get the highlighted words.
String highlighted_text = get_selection_text();
@@ -867,6 +863,8 @@ void TextEdit::_notification(int p_what) {
Dictionary color_map = _get_line_syntax_highlighting(minimap_line);
+ Color line_background_color = text.get_line_background_color(minimap_line);
+ line_background_color.a *= 0.6;
Color current_color = cache.font_color;
if (readonly) {
current_color = cache.font_readonly_color;
@@ -901,6 +899,12 @@ void TextEdit::_notification(int p_what) {
} else {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, cache.minimap_width, 2), cache.current_line_color);
}
+ } else if (line_background_color != Color(0, 0, 0, 0)) {
+ if (rtl) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - cache.minimap_width, i * 3, cache.minimap_width, 2), line_background_color);
+ } else {
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, cache.minimap_width, 2), line_background_color);
+ }
}
Color previous_color;
@@ -980,6 +984,8 @@ void TextEdit::_notification(int p_what) {
}
// draw main text
+ cursor.visible = false;
+ const int caret_wrap_index = get_cursor_wrap_index();
int row_height = get_row_height();
int line = first_visible_line;
for (int i = 0; i < draw_amount; i++) {
@@ -1048,11 +1054,11 @@ void TextEdit::_notification(int p_what) {
break;
}
- if (text.is_marked(line)) {
+ if (text.get_line_background_color(line) != Color(0, 0, 0, 0)) {
if (rtl) {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), cache.mark_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line));
} else {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, row_height), cache.mark_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line));
}
}
@@ -1180,7 +1186,8 @@ void TextEdit::_notification(int p_what) {
if (rect.position.x < xmargin_beg) {
rect.size.x -= (xmargin_beg - rect.position.x);
rect.position.x = xmargin_beg;
- } else if (rect.position.x + rect.size.x > xmargin_end) {
+ }
+ if (rect.position.x + rect.size.x > xmargin_end) {
rect.size.x = xmargin_end - rect.position.x;
}
draw_rect(rect, cache.selection_color, true);
@@ -1259,7 +1266,6 @@ void TextEdit::_notification(int p_what) {
}
}
- const int line_top_offset_y = ofs_y;
ofs_y += (row_height - text_height) / 2;
const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(rid);
@@ -1364,9 +1370,9 @@ void TextEdit::_notification(int p_what) {
#else
int caret_width = 1;
#endif
- if (!clipped && cursor.line == line && ((line_wrap_index == line_wrap_amount) || (cursor.column != TS->shaped_text_get_range(rid).y))) {
- is_cursor_line_visible = true;
- cursor_pos.y = line_top_offset_y;
+
+ if (!clipped && cursor.line == line && line_wrap_index == caret_wrap_index) {
+ cursor.draw_pos.y = ofs_y + ldata->get_line_descent(line_wrap_index);
if (ime_text.length() == 0) {
Rect2 l_caret, t_caret;
@@ -1387,57 +1393,60 @@ void TextEdit::_notification(int p_what) {
}
if ((l_caret != Rect2() && (l_dir == TextServer::DIRECTION_AUTO || l_dir == (TextServer::Direction)input_direction)) || (t_caret == Rect2())) {
- cursor_pos.x = char_margin + ofs_x + l_caret.position.x;
+ cursor.draw_pos.x = char_margin + ofs_x + l_caret.position.x;
} else {
- cursor_pos.x = char_margin + ofs_x + t_caret.position.x;
+ cursor.draw_pos.x = char_margin + ofs_x + t_caret.position.x;
}
- if (draw_caret && cursor_pos.x >= xmargin_beg && cursor_pos.x < xmargin_end) {
- if (block_caret || insert_mode) {
- //Block or underline caret, draw trailing carets at full height.
- int h = cache.font->get_height(cache.font_size);
-
- if (t_caret != Rect2()) {
- if (insert_mode) {
- t_caret.position.y = TS->shaped_text_get_descent(rid);
- t_caret.size.y = caret_width;
- } else {
- t_caret.position.y = -TS->shaped_text_get_ascent(rid);
- t_caret.size.y = h;
- }
- t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+ if (cursor.draw_pos.x >= xmargin_beg && cursor.draw_pos.x < xmargin_end) {
+ cursor.visible = true;
+ if (draw_caret) {
+ if (block_caret || insert_mode) {
+ //Block or underline caret, draw trailing carets at full height.
+ int h = cache.font->get_height(cache.font_size);
+
+ if (t_caret != Rect2()) {
+ if (insert_mode) {
+ t_caret.position.y = TS->shaped_text_get_descent(rid);
+ t_caret.size.y = caret_width;
+ } else {
+ t_caret.position.y = -TS->shaped_text_get_ascent(rid);
+ t_caret.size.y = h;
+ }
+ t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+
+ draw_rect(t_caret, cache.caret_color, false);
+ } else { // End of the line.
+ if (insert_mode) {
+ l_caret.position.y = TS->shaped_text_get_descent(rid);
+ l_caret.size.y = caret_width;
+ } else {
+ l_caret.position.y = -TS->shaped_text_get_ascent(rid);
+ l_caret.size.y = h;
+ }
+ l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+ l_caret.size.x = cache.font->get_char_size('M', 0, cache.font_size).x;
- draw_rect(t_caret, cache.caret_color, false);
- } else { // End of the line.
- if (insert_mode) {
- l_caret.position.y = TS->shaped_text_get_descent(rid);
- l_caret.size.y = caret_width;
- } else {
- l_caret.position.y = -TS->shaped_text_get_ascent(rid);
- l_caret.size.y = h;
+ draw_rect(l_caret, cache.caret_color, false);
+ }
+ } else {
+ // Normal caret.
+ if (l_caret != Rect2() && l_dir == TextServer::DIRECTION_AUTO) {
+ // Draw extra marker on top of mid caret.
+ Rect2 trect = Rect2(l_caret.position.x - 3 * caret_width, l_caret.position.y, 6 * caret_width, caret_width);
+ trect.position += Vector2(char_margin + ofs_x, ofs_y);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, cache.caret_color);
}
l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
- l_caret.size.x = cache.font->get_char_size('M', 0, cache.font_size).x;
-
- draw_rect(l_caret, cache.caret_color, false);
- }
- } else {
- // Normal caret.
- if (l_caret != Rect2() && l_dir == TextServer::DIRECTION_AUTO) {
- // Draw extra marker on top of mid caret.
- Rect2 trect = Rect2(l_caret.position.x - 3 * caret_width, l_caret.position.y, 6 * caret_width, caret_width);
- trect.position += Vector2(char_margin + ofs_x, ofs_y);
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, cache.caret_color);
- }
- l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
- l_caret.size.x = caret_width;
+ l_caret.size.x = caret_width;
- draw_rect(l_caret, cache.caret_color);
+ draw_rect(l_caret, cache.caret_color);
- t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
- t_caret.size.x = caret_width;
+ t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+ t_caret.size.x = caret_width;
- draw_rect(t_caret, cache.caret_color);
+ draw_rect(t_caret, cache.caret_color);
+ }
}
}
} else {
@@ -1457,7 +1466,7 @@ void TextEdit::_notification(int p_what) {
}
rect.size.y = caret_width;
draw_rect(rect, cache.caret_color);
- cursor_pos.x = rect.position.x;
+ cursor.draw_pos.x = rect.position.x;
}
}
{
@@ -1476,7 +1485,7 @@ void TextEdit::_notification(int p_what) {
}
rect.size.y = caret_width * 3;
draw_rect(rect, cache.caret_color);
- cursor_pos.x = rect.position.x;
+ cursor.draw_pos.x = rect.position.x;
}
}
}
@@ -1484,227 +1493,10 @@ void TextEdit::_notification(int p_what) {
}
}
- bool completion_below = false;
- if (completion_active && is_cursor_line_visible && completion_options.size() > 0) {
- // Completion panel
-
- const Ref<StyleBox> csb = get_theme_stylebox("completion");
- const int maxlines = get_theme_constant("completion_lines");
- const int cmax_width = get_theme_constant("completion_max_width") * cache.font->get_char_size('x', 0, cache.font_size).x;
- const Color scrollc = get_theme_color("completion_scroll_color");
-
- const int completion_options_size = completion_options.size();
- const int row_count = MIN(completion_options_size, maxlines);
- const int completion_rows_height = row_count * row_height;
- const int completion_base_width = cache.font->get_string_size(completion_base, cache.font_size).width;
-
- int scroll_rectangle_width = get_theme_constant("completion_scroll_width");
- int width = 0;
-
- // Compute max width of the panel based on the longest completion option
- if (completion_options_size < 50) {
- for (int i = 0; i < completion_options_size; i++) {
- int line_width = MIN(cache.font->get_string_size(completion_options[i].display, cache.font_size).x, cmax_width);
- if (line_width > width) {
- width = line_width;
- }
- }
- } else {
- width = cmax_width;
- }
-
- // Add space for completion icons.
- const int icon_hsep = get_theme_constant("hseparation", "ItemList");
- const Size2 icon_area_size(row_height, row_height);
- const int icon_area_width = icon_area_size.width + icon_hsep;
- width += icon_area_width;
-
- const int line_from = CLAMP(completion_index - row_count / 2, 0, completion_options_size - row_count);
-
- for (int i = 0; i < row_count; i++) {
- int l = line_from + i;
- ERR_CONTINUE(l < 0 || l >= completion_options_size);
- if (completion_options[l].default_value.get_type() == Variant::COLOR) {
- width += icon_area_size.width;
- break;
- }
- }
-
- // Position completion panel
- completion_rect.size.width = width + 2;
- completion_rect.size.height = completion_rows_height;
-
- if (completion_options_size <= maxlines) {
- scroll_rectangle_width = 0;
- }
-
- const Point2 csb_offset = csb->get_offset();
-
- const int total_width = completion_rect.size.width + csb->get_minimum_size().x + scroll_rectangle_width;
- const int total_height = completion_rect.size.height + csb->get_minimum_size().y;
-
- const int rect_left_border_x = cursor_pos.x - completion_base_width - icon_area_width - csb_offset.x;
- const int rect_right_border_x = rect_left_border_x + total_width;
-
- if (rect_left_border_x < 0) {
- // Anchor the completion panel to the left
- completion_rect.position.x = 0;
- } else if (rect_right_border_x > get_size().width) {
- // Anchor the completion panel to the right
- completion_rect.position.x = get_size().width - total_width;
- } else {
- // Let the completion panel float with the cursor
- completion_rect.position.x = rect_left_border_x;
- }
-
- if (cursor_pos.y + row_height + total_height > get_size().height && cursor_pos.y > total_height) {
- // Completion panel above the cursor line
- completion_rect.position.y = cursor_pos.y - total_height;
- } else {
- // Completion panel below the cursor line
- completion_rect.position.y = cursor_pos.y + row_height;
- completion_below = true;
- }
-
- draw_style_box(csb, Rect2(completion_rect.position - csb_offset, completion_rect.size + csb->get_minimum_size() + Size2(scroll_rectangle_width, 0)));
-
- if (cache.completion_background_color.a > 0.01) {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(completion_rect.position, completion_rect.size + Size2(scroll_rectangle_width, 0)), cache.completion_background_color);
- }
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(completion_rect.position.x, completion_rect.position.y + (completion_index - line_from) * get_row_height()), Size2(completion_rect.size.width, get_row_height())), cache.completion_selected_color);
-
- draw_rect(Rect2(completion_rect.position + Vector2(icon_area_size.x + icon_hsep, 0), Size2(MIN(completion_base_width, completion_rect.size.width - (icon_area_size.x + icon_hsep)), completion_rect.size.height)), cache.completion_existing_color);
-
- for (int i = 0; i < row_count; i++) {
- int l = line_from + i;
- ERR_CONTINUE(l < 0 || l >= completion_options_size);
-
- Ref<TextLine> tl;
- tl.instance();
- tl->add_string(completion_options[l].display, cache.font, cache.font_size);
-
- int yofs = (row_height - tl->get_size().y) / 2;
- Point2 title_pos(completion_rect.position.x, completion_rect.position.y + i * row_height + yofs);
-
- // Draw completion icon if it is valid.
- Ref<Texture2D> icon = completion_options[l].icon;
- Rect2 icon_area(completion_rect.position.x, completion_rect.position.y + i * row_height, icon_area_size.width, icon_area_size.height);
- if (icon.is_valid()) {
- const real_t max_scale = 0.7f;
- const real_t side = max_scale * icon_area.size.width;
- real_t scale = MIN(side / icon->get_width(), side / icon->get_height());
- Size2 icon_size = icon->get_size() * scale;
- draw_texture_rect(icon, Rect2(icon_area.position + (icon_area.size - icon_size) / 2, icon_size));
- }
-
- title_pos.x = icon_area.position.x + icon_area.size.width + icon_hsep;
-
- tl->set_width(completion_rect.size.width - (icon_area_size.x + icon_hsep));
-
- if (rtl) {
- if (completion_options[l].default_value.get_type() == Variant::COLOR) {
- draw_rect(Rect2(Point2(completion_rect.position.x, icon_area.position.y), icon_area_size), (Color)completion_options[l].default_value);
- }
- tl->set_align(HALIGN_RIGHT);
- } else {
- if (completion_options[l].default_value.get_type() == Variant::COLOR) {
- draw_rect(Rect2(Point2(completion_rect.position.x + completion_rect.size.width - icon_area_size.x, icon_area.position.y), icon_area_size), (Color)completion_options[l].default_value);
- }
- tl->set_align(HALIGN_LEFT);
- }
- if (cache.outline_size > 0 && cache.outline_color.a > 0) {
- tl->draw_outline(ci, title_pos, cache.outline_size, cache.outline_color);
- }
- tl->draw(ci, title_pos, completion_options[l].font_color);
- }
-
- if (scroll_rectangle_width) {
- // Draw a small scroll rectangle to show a position in the options.
- float r = (float)maxlines / completion_options_size;
- float o = (float)line_from / completion_options_size;
- draw_rect(Rect2(completion_rect.position.x + completion_rect.size.width, completion_rect.position.y + o * completion_rect.size.y, scroll_rectangle_width, completion_rect.size.y * r), scrollc);
- }
-
- completion_line_ofs = line_from;
- }
-
- // Check to see if the hint should be drawn.
- bool show_hint = false;
- if (is_cursor_line_visible && completion_hint != "") {
- if (completion_active) {
- if (completion_below && !callhint_below) {
- show_hint = true;
- } else if (!completion_below && callhint_below) {
- show_hint = true;
- }
- } else {
- show_hint = true;
- }
- }
-
- if (show_hint) {
- Ref<StyleBox> sb = get_theme_stylebox("panel", "TooltipPanel");
- Ref<Font> font = cache.font;
- Color font_color = get_theme_color("font_color", "TooltipLabel");
-
- int max_w = 0;
- int sc = completion_hint.get_slice_count("\n");
- int offset = 0;
- int spacing = 0;
- for (int i = 0; i < sc; i++) {
- String l = completion_hint.get_slice("\n", i);
- int len = font->get_string_size(l, cache.font_size).x;
- max_w = MAX(len, max_w);
- if (i == 0) {
- offset = font->get_string_size(l.substr(0, l.find(String::chr(0xFFFF))), cache.font_size).x;
- } else {
- spacing += cache.line_spacing;
- }
- }
-
- Size2 size2 = Size2(max_w, sc * font->get_height(cache.font_size) + spacing);
- Size2 minsize = size2 + sb->get_minimum_size();
-
- if (completion_hint_offset == -0xFFFF) {
- completion_hint_offset = cursor_pos.x - offset;
- }
-
- Point2 hint_ofs = Vector2(completion_hint_offset, cursor_pos.y) + callhint_offset;
-
- if (callhint_below) {
- hint_ofs.y += row_height + sb->get_offset().y;
- } else {
- hint_ofs.y -= minsize.y + sb->get_offset().y;
- }
-
- draw_style_box(sb, Rect2(hint_ofs, minsize));
-
- spacing = 0;
- for (int i = 0; i < sc; i++) {
- int begin = 0;
- int end = 0;
- String l = completion_hint.get_slice("\n", i);
-
- if (l.find(String::chr(0xFFFF)) != -1) {
- begin = font->get_string_size(l.substr(0, l.find(String::chr(0xFFFF))), cache.font_size).x;
- end = font->get_string_size(l.substr(0, l.rfind(String::chr(0xFFFF))), cache.font_size).x;
- }
-
- Point2 round_ofs = hint_ofs + sb->get_offset() + Vector2(0, font->get_ascent(cache.font_size) + font->get_height(cache.font_size) * i + spacing);
- round_ofs = round_ofs.round();
- draw_string(font, round_ofs, l.replace(String::chr(0xFFFF), ""), HALIGN_LEFT, -1, cache.font_size, font_color);
- if (end > 0) {
- Vector2 b = hint_ofs + sb->get_offset() + Vector2(begin, font->get_height(cache.font_size) + font->get_height(cache.font_size) * i + spacing - 1);
- draw_line(b, b + Vector2(end - begin, 0), font_color);
- }
- spacing += cache.line_spacing;
- }
- }
-
if (has_focus()) {
if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
- DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id());
+ DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor.draw_pos, get_viewport()->get_window_id());
}
}
} break;
@@ -2419,8 +2211,6 @@ void TextEdit::_move_cursor_up(bool p_select) {
if (p_select) {
_post_shift_selection();
}
-
- _cancel_code_hint();
}
void TextEdit::_move_cursor_down(bool p_select) {
@@ -2443,8 +2233,6 @@ void TextEdit::_move_cursor_down(bool p_select) {
if (p_select) {
_post_shift_selection();
}
-
- _cancel_code_hint();
}
void TextEdit::_move_cursor_to_line_start(bool p_select) {
@@ -2484,9 +2272,6 @@ void TextEdit::_move_cursor_to_line_start(bool p_select) {
if (p_select) {
_post_shift_selection();
}
-
- _cancel_completion();
- completion_hint = "";
}
void TextEdit::_move_cursor_to_line_end(bool p_select) {
@@ -2512,8 +2297,6 @@ void TextEdit::_move_cursor_to_line_end(bool p_select) {
if (p_select) {
_post_shift_selection();
}
- _cancel_completion();
- completion_hint = "";
}
void TextEdit::_move_cursor_page_up(bool p_select) {
@@ -2530,9 +2313,6 @@ void TextEdit::_move_cursor_page_up(bool p_select) {
if (p_select) {
_post_shift_selection();
}
-
- _cancel_completion();
- completion_hint = "";
}
void TextEdit::_move_cursor_page_down(bool p_select) {
@@ -2549,9 +2329,6 @@ void TextEdit::_move_cursor_page_down(bool p_select) {
if (p_select) {
_post_shift_selection();
}
-
- _cancel_completion();
- completion_hint = "";
}
void TextEdit::_backspace(bool p_word, bool p_all_to_left) {
@@ -2684,11 +2461,7 @@ void TextEdit::_move_cursor_document_end(bool p_select) {
}
}
-void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection, bool p_update_auto_complete) {
- if (p_update_auto_complete) {
- _reset_caret_blink_timer();
- }
-
+void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection) {
if (p_had_selection) {
_delete_selection();
}
@@ -2705,11 +2478,6 @@ void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection,
const char32_t chr[2] = { (char32_t)unicode, 0 };
- // Clear completion hint when function closed
- if (completion_hint != "" && unicode == ')') {
- completion_hint = "";
- }
-
if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
_consume_pair_symbol(chr[0]);
} else {
@@ -2719,10 +2487,6 @@ void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection,
if ((insert_mode && !p_had_selection) || (selection.active != p_had_selection)) {
end_complex_operation();
}
-
- if (p_update_auto_complete) {
- _update_completion_candidates();
- }
}
void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) const {
@@ -2878,53 +2642,27 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// Ignore mouse clicks in IME input mode.
return;
}
- if (completion_active && completion_rect.has_point(mpos)) {
- if (!mb->is_pressed()) {
- return;
- }
-
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
- if (completion_index > 0) {
- completion_index--;
- completion_current = completion_options[completion_index];
- update();
- }
- }
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
- if (completion_index < completion_options.size() - 1) {
- completion_index++;
- completion_current = completion_options[completion_index];
- update();
- }
- }
-
- if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
- completion_index = CLAMP(completion_line_ofs + (mpos.y - completion_rect.position.y) / get_row_height(), 0, completion_options.size() - 1);
-
- completion_current = completion_options[completion_index];
- update();
- if (mb->is_double_click()) {
- _confirm_completion();
- }
- }
- return;
- } else {
- _cancel_completion();
- _cancel_code_hint();
- }
if (mb->is_pressed()) {
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) {
- if (mb->get_shift()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->is_command_pressed()) {
+ if (mb->is_shift_pressed()) {
h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor()));
+ } else if (mb->is_alt_pressed()) {
+ // Scroll 5 times as fast as normal (like in Visual Studio Code).
+ _scroll_up(15 * mb->get_factor());
} else if (v_scroll->is_visible()) {
+ // Scroll 3 lines.
_scroll_up(3 * mb->get_factor());
}
}
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) {
- if (mb->get_shift()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->is_command_pressed()) {
+ if (mb->is_shift_pressed()) {
h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor()));
+ } else if (mb->is_alt_pressed()) {
+ // Scroll 5 times as fast as normal (like in Visual Studio Code).
+ _scroll_down(15 * mb->get_factor());
} else if (v_scroll->is_visible()) {
+ // Scroll 3 lines.
_scroll_down(3 * mb->get_factor());
}
}
@@ -2977,7 +2715,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
cursor_set_line(row, false, false);
cursor_set_column(col);
- if (mb->get_shift() && (cursor.column != prev_col || cursor.line != prev_line)) {
+ if (mb->is_shift_pressed() && (cursor.column != prev_col || cursor.line != prev_line)) {
if (!selection.active) {
selection.active = true;
selection.selecting_mode = SelectionMode::SELECTION_MODE_POINTER;
@@ -3073,7 +2811,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
} else {
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (mb->get_command() && highlighted_word != String()) {
+ if (mb->is_command_pressed() && highlighted_word != String()) {
int row, col;
_get_mouse_pos(Point2i(mpos.x, mpos.y), row, col);
@@ -3116,7 +2854,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
mpos.x = get_size().x - mpos.x;
}
if (select_identifiers_enabled) {
- if (!dragging_minimap && !dragging_selection && mm->get_command() && mm->get_button_mask() == 0) {
+ if (!dragging_minimap && !dragging_selection && mm->is_command_pressed() && mm->get_button_mask() == 0) {
String new_word = get_word_at_pos(mpos);
if (new_word != highlighted_word) {
emit_signal("symbol_validate", new_word);
@@ -3165,7 +2903,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
#ifdef OSX_ENABLED
if (k->get_keycode() == KEY_META) {
#else
- if (k->get_keycode() == KEY_CONTROL) {
+ if (k->get_keycode() == KEY_CTRL) {
#endif
if (select_identifiers_enabled) {
if (k->is_pressed() && !dragging_minimap && !dragging_selection) {
@@ -3183,7 +2921,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
// If a modifier has been pressed, and nothing else, return.
- if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) {
+ if (k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) {
return;
}
@@ -3191,7 +2929,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// Allow unicode handling if:
// * No Modifiers are pressed (except shift)
- bool allow_unicode_handling = !(k->get_command() || k->get_control() || k->get_alt() || k->get_metakey());
+ bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed());
// Save here for insert mode, just in case it is cleared in the following section.
bool had_selection = selection.active;
@@ -3200,96 +2938,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// Check and handle all built in shortcuts.
- // AUTO-COMPLETE
-
- if (k->is_action("ui_text_completion_query", true)) {
- query_code_comple();
- accept_event();
- return;
- }
-
- if (completion_active) {
- if (k->is_action("ui_up", true)) {
- if (completion_index > 0) {
- completion_index--;
- } else {
- completion_index = completion_options.size() - 1;
- }
- completion_current = completion_options[completion_index];
- update();
- accept_event();
- return;
- }
- if (k->is_action("ui_down", true)) {
- if (completion_index < completion_options.size() - 1) {
- completion_index++;
- } else {
- completion_index = 0;
- }
- completion_current = completion_options[completion_index];
- update();
- accept_event();
- return;
- }
- if (k->is_action("ui_page_up", true)) {
- completion_index -= get_theme_constant("completion_lines");
- if (completion_index < 0) {
- completion_index = 0;
- }
- completion_current = completion_options[completion_index];
- update();
- accept_event();
- return;
- }
- if (k->is_action("ui_page_down", true)) {
- completion_index += get_theme_constant("completion_lines");
- if (completion_index >= completion_options.size()) {
- completion_index = completion_options.size() - 1;
- }
- completion_current = completion_options[completion_index];
- update();
- accept_event();
- return;
- }
- if (k->is_action("ui_home", true)) {
- if (completion_index > 0) {
- completion_index = 0;
- completion_current = completion_options[completion_index];
- update();
- }
- accept_event();
- return;
- }
- if (k->is_action("ui_end", true)) {
- if (completion_index < completion_options.size() - 1) {
- completion_index = completion_options.size() - 1;
- completion_current = completion_options[completion_index];
- update();
- }
- accept_event();
- return;
- }
- if (k->is_action("ui_text_completion_accept", true)) {
- _confirm_completion();
- accept_event();
- return;
- }
- if (k->is_action("ui_cancel", true)) {
- _cancel_completion();
- accept_event();
- return;
- }
-
- // Handle Unicode here (if no modifiers active) and update autocomplete.
- if (k->get_unicode() >= 32) {
- if (allow_unicode_handling && !readonly) {
- _handle_unicode_character(k->get_unicode(), had_selection, true);
- accept_event();
- return;
- }
- }
- }
-
// NEWLINES.
if (k->is_action("ui_text_newline_above", true)) {
_new_line(false, true);
@@ -3332,9 +2980,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (k->is_action("ui_text_backspace", true)) {
_backspace();
- if (completion_active) {
- _update_completion_candidates();
- }
accept_event();
return;
}
@@ -3366,13 +3011,18 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
- // SELECT ALL, CUT, COPY, PASTE.
+ // SELECT ALL, SELECT WORD UNDER CARET, CUT, COPY, PASTE.
if (k->is_action("ui_text_select_all", true)) {
select_all();
accept_event();
return;
}
+ if (k->is_action("ui_text_select_word_under_caret", true)) {
+ select_word_under_caret();
+ accept_event();
+ return;
+ }
if (k->is_action("ui_cut", true)) {
cut();
accept_event();
@@ -3402,7 +3052,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
// MISC.
-
if (k->is_action("ui_menu", true)) {
if (context_menu_enabled) {
menu->set_position(get_screen_transform().xform(_get_cursor_pixel_pos()));
@@ -3419,14 +3068,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
accept_event();
return;
}
- if (k->is_action("ui_cancel", true)) {
- if (completion_hint != "") {
- completion_hint = "";
- update();
- }
- accept_event();
- return;
- }
if (k->is_action("ui_swap_input_direction", true)) {
_swap_current_input_direction();
accept_event();
@@ -3436,9 +3077,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// CURSOR MOVEMENT
k = k->duplicate();
- bool shift_pressed = k->get_shift();
+ bool shift_pressed = k->is_shift_pressed();
// Remove shift or else actions will not match. Use above variable for selection.
- k->set_shift(false);
+ k->set_shift_pressed(false);
// CURSOR MOVEMENT - LEFT, RIGHT.
if (k->is_action("ui_text_caret_word_left", true)) {
@@ -3512,7 +3153,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (allow_unicode_handling && !readonly && k->get_unicode() >= 32) {
// Handle Unicode (if no modifiers active).
- _handle_unicode_character(k->get_unicode(), had_selection, false);
+ _handle_unicode_character(k->get_unicode(), had_selection);
accept_event();
return;
}
@@ -4273,6 +3914,14 @@ void TextEdit::cursor_set_line(int p_row, bool p_adjust_viewport, bool p_can_be_
}
}
+Point2 TextEdit::get_caret_draw_pos() const {
+ return cursor.draw_pos;
+}
+
+bool TextEdit::is_caret_visible() const {
+ return cursor.visible;
+}
+
int TextEdit::cursor_get_column() const {
return cursor.column;
}
@@ -4450,10 +4099,6 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
return CURSOR_POINTING_HAND;
}
- if ((completion_active && completion_rect.has_point(p_pos)) || (is_readonly() && (!is_selecting_enabled() || text.size() == 0))) {
- return CURSOR_ARROW;
- }
-
int row, col;
_get_mouse_pos(p_pos, row, col);
@@ -4665,26 +4310,6 @@ String TextEdit::get_text_for_lookup_completion() {
return longthing;
}
-String TextEdit::get_text_for_completion() {
- String longthing;
- int len = text.size();
- for (int i = 0; i < len; i++) {
- if (i == cursor.line) {
- longthing += text[i].substr(0, cursor.column);
- longthing += String::chr(0xFFFF); // Not unicode, represents the cursor.
- longthing += text[i].substr(cursor.column, text[i].size());
- } else {
- longthing += text[i];
- }
-
- if (i != len - 1) {
- longthing += "\n";
- }
- }
-
- return longthing;
-};
-
String TextEdit::get_line(int line) const {
if (line < 0 || line >= text.size()) {
return "";
@@ -4767,10 +4392,6 @@ void TextEdit::_update_caches() {
cache.style_normal = get_theme_stylebox("normal");
cache.style_focus = get_theme_stylebox("focus");
cache.style_readonly = get_theme_stylebox("read_only");
- cache.completion_background_color = get_theme_color("completion_background_color");
- cache.completion_selected_color = get_theme_color("completion_selected_color");
- cache.completion_existing_color = get_theme_color("completion_existing_color");
- cache.completion_font_color = get_theme_color("completion_font_color");
cache.font = get_theme_font("font");
cache.font_size = get_theme_font_size("font_size");
cache.outline_color = get_theme_color("font_outline_color");
@@ -4781,7 +4402,6 @@ void TextEdit::_update_caches() {
cache.font_selected_color = get_theme_color("font_selected_color");
cache.font_readonly_color = get_theme_color("font_readonly_color");
cache.selection_color = get_theme_color("selection_color");
- cache.mark_color = get_theme_color("mark_color");
cache.current_line_color = get_theme_color("current_line_color");
cache.line_length_guideline_color = get_theme_color("line_length_guideline_color");
cache.code_folding_color = get_theme_color("code_folding_color");
@@ -5011,6 +4631,18 @@ bool TextEdit::is_line_gutter_clickable(int p_line, int p_gutter) const {
return text.is_line_gutter_clickable(p_line, p_gutter);
}
+// Line style
+void TextEdit::set_line_background_color(int p_line, const Color &p_color) {
+ ERR_FAIL_INDEX(p_line, text.size());
+ text.set_line_background_color(p_line, p_color);
+ update();
+}
+
+Color TextEdit::get_line_background_color(int p_line) {
+ ERR_FAIL_INDEX_V(p_line, text.size(), Color());
+ return text.get_line_background_color(p_line);
+}
+
void TextEdit::add_keyword(const String &p_keyword) {
keywords.insert(p_keyword);
}
@@ -5123,6 +4755,39 @@ void TextEdit::select_all() {
update();
}
+void TextEdit::select_word_under_caret() {
+ if (!selecting_enabled) {
+ return;
+ }
+
+ if (text.size() == 1 && text[0].length() == 0) {
+ return;
+ }
+
+ if (selection.active) {
+ // Allow toggling selection by pressing the shortcut a second time.
+ // This is also usable as a general-purpose "deselect" shortcut after
+ // selecting anything.
+ deselect();
+ return;
+ }
+
+ int begin = 0;
+ int end = 0;
+ const Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(cursor.line)->get_rid());
+ for (int i = 0; i < words.size(); i++) {
+ if (words[i].x <= cursor.column && words[i].y >= cursor.column) {
+ begin = words[i].x;
+ end = words[i].y;
+ break;
+ }
+ }
+
+ select(cursor.line, begin, cursor.line, end);
+ // Move the cursor to the end of the word for easier editing.
+ cursor_set_column(end, false);
+}
+
void TextEdit::deselect() {
selection.active = false;
update();
@@ -5429,12 +5094,6 @@ void TextEdit::_text_changed_emit() {
text_changed_dirty = false;
}
-void TextEdit::set_line_as_marked(int p_line, bool p_marked) {
- ERR_FAIL_INDEX(p_line, text.size());
- text.set_marked(p_line, p_marked);
- update();
-}
-
void TextEdit::set_line_as_hidden(int p_line, bool p_hidden) {
ERR_FAIL_INDEX(p_line, text.size());
if (is_hiding_enabled() || !p_hidden) {
@@ -5827,7 +5486,6 @@ void TextEdit::undo() {
if (undo_stack_pos->get().type == TextOperation::TYPE_REMOVE) {
cursor_set_line(undo_stack_pos->get().to_line, false);
cursor_set_column(undo_stack_pos->get().to_column);
- _cancel_code_hint();
} else {
cursor_set_line(undo_stack_pos->get().from_line, false);
cursor_set_column(undo_stack_pos->get().from_column);
@@ -6103,313 +5761,6 @@ float TextEdit::get_v_scroll_speed() const {
return v_scroll_speed;
}
-void TextEdit::set_completion(bool p_enabled, const Vector<String> &p_prefixes) {
- completion_prefixes.clear();
- completion_enabled = p_enabled;
- for (int i = 0; i < p_prefixes.size(); i++) {
- completion_prefixes.insert(p_prefixes[i]);
- }
-}
-
-void TextEdit::_confirm_completion() {
- begin_complex_operation();
-
- _remove_text(cursor.line, cursor.column - completion_base.length(), cursor.line, cursor.column);
- cursor_set_column(cursor.column - completion_base.length(), false);
- insert_text_at_cursor(completion_current.insert_text);
-
- // When inserted into the middle of an existing string/method, don't add an unnecessary quote/bracket.
- String line = text[cursor.line];
- char32_t next_char = line[cursor.column];
- char32_t last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1];
- char32_t last_completion_char_display = completion_current.display[completion_current.display.length() - 1];
-
- if ((last_completion_char == '"' || last_completion_char == '\'') && (last_completion_char == next_char || last_completion_char_display == next_char)) {
- _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
- }
-
- if (last_completion_char == '(') {
- if (next_char == last_completion_char) {
- _base_remove_text(cursor.line, cursor.column - 1, cursor.line, cursor.column);
- } else if (auto_brace_completion_enabled) {
- insert_text_at_cursor(")");
- cursor.column--;
- }
- } else if (last_completion_char == ')' && next_char == '(') {
- _base_remove_text(cursor.line, cursor.column - 2, cursor.line, cursor.column);
- if (line[cursor.column + 1] != ')') {
- cursor.column--;
- }
- }
-
- end_complex_operation();
-
- _cancel_completion();
-
- if (last_completion_char == '(') {
- query_code_comple();
- }
-}
-
-void TextEdit::_cancel_code_hint() {
- completion_hint = "";
- update();
-}
-
-void TextEdit::_cancel_completion() {
- if (!completion_active) {
- return;
- }
-
- completion_active = false;
- completion_forced = false;
- update();
-}
-
-static bool _is_completable(char32_t c) {
- return !_is_symbol(c) || c == '"' || c == '\'';
-}
-
-void TextEdit::_update_completion_candidates() {
- String l = text[cursor.line];
- int cofs = CLAMP(cursor.column, 0, l.length());
-
- String s;
-
- // Look for keywords first.
-
- bool inquote = false;
- int first_quote = -1;
- int restore_quotes = -1;
-
- int c = cofs - 1;
- while (c >= 0) {
- if (l[c] == '"' || l[c] == '\'') {
- inquote = !inquote;
- if (first_quote == -1) {
- first_quote = c;
- }
- restore_quotes = 0;
- } else if (restore_quotes == 0 && l[c] == '$') {
- restore_quotes = 1;
- } else if (restore_quotes == 0 && !_is_whitespace(l[c])) {
- restore_quotes = -1;
- }
- c--;
- }
-
- bool pre_keyword = false;
- bool cancel = false;
-
- if (!inquote && first_quote == cofs - 1) {
- // No completion here.
- cancel = true;
- } else if (inquote && first_quote != -1) {
- s = l.substr(first_quote, cofs - first_quote);
- } else if (cofs > 0 && l[cofs - 1] == ' ') {
- int kofs = cofs - 1;
- String kw;
- while (kofs >= 0 && l[kofs] == ' ') {
- kofs--;
- }
-
- while (kofs >= 0 && l[kofs] > 32 && _is_completable(l[kofs])) {
- kw = String::chr(l[kofs]) + kw;
- kofs--;
- }
-
- pre_keyword = keywords.has(kw);
-
- } else {
- while (cofs > 0 && l[cofs - 1] > 32 && (l[cofs - 1] == '/' || _is_completable(l[cofs - 1]))) {
- s = String::chr(l[cofs - 1]) + s;
- if (l[cofs - 1] == '\'' || l[cofs - 1] == '"' || l[cofs - 1] == '$') {
- break;
- }
-
- cofs--;
- }
- }
-
- if (cursor.column > 0 && l[cursor.column - 1] == '(' && !pre_keyword && !completion_forced) {
- cancel = true;
- }
-
- update();
-
- bool prev_is_prefix = false;
- if (cofs > 0 && completion_prefixes.has(String::chr(l[cofs - 1]))) {
- prev_is_prefix = true;
- }
- // Check with one space before prefix, to allow indent.
- if (cofs > 1 && l[cofs - 1] == ' ' && completion_prefixes.has(String::chr(l[cofs - 2]))) {
- prev_is_prefix = true;
- }
-
- if (cancel || (!pre_keyword && s == "" && (cofs == 0 || !prev_is_prefix))) {
- // None to complete, cancel.
- _cancel_completion();
- return;
- }
-
- completion_options.clear();
- completion_index = 0;
- completion_base = s;
- Vector<float> sim_cache;
- bool single_quote = s.begins_with("'");
- Vector<ScriptCodeCompletionOption> completion_options_casei;
- Vector<ScriptCodeCompletionOption> completion_options_subseq;
- Vector<ScriptCodeCompletionOption> completion_options_subseq_casei;
-
- String s_lower = s.to_lower();
-
- for (List<ScriptCodeCompletionOption>::Element *E = completion_sources.front(); E; E = E->next()) {
- ScriptCodeCompletionOption &option = E->get();
-
- if (single_quote && option.display.is_quoted()) {
- option.display = option.display.unquote().quote("'");
- }
-
- if (inquote && restore_quotes == 1 && !option.display.is_quoted()) {
- String quote = single_quote ? "'" : "\"";
- option.display = option.display.quote(quote);
- option.insert_text = option.insert_text.quote(quote);
- }
-
- if (option.display.length() == 0) {
- continue;
- } else if (s.length() == 0) {
- completion_options.push_back(option);
- } else {
- // This code works the same as:
- /*
- if (option.display.begins_with(s)) {
- completion_options.push_back(option);
- } else if (option.display.to_lower().begins_with(s.to_lower())) {
- completion_options_casei.push_back(option);
- } else if (s.is_subsequence_of(option.display)) {
- completion_options_subseq.push_back(option);
- } else if (s.is_subsequence_ofi(option.display)) {
- completion_options_subseq_casei.push_back(option);
- }
- */
- // But is more performant due to being inlined and looping over the characters only once
-
- String display_lower = option.display.to_lower();
-
- const char32_t *ssq = &s[0];
- const char32_t *ssq_lower = &s_lower[0];
-
- const char32_t *tgt = &option.display[0];
- const char32_t *tgt_lower = &display_lower[0];
-
- const char32_t *ssq_last_tgt = nullptr;
- const char32_t *ssq_lower_last_tgt = nullptr;
-
- for (; *tgt; tgt++, tgt_lower++) {
- if (*ssq == *tgt) {
- ssq++;
- ssq_last_tgt = tgt;
- }
- if (*ssq_lower == *tgt_lower) {
- ssq_lower++;
- ssq_lower_last_tgt = tgt;
- }
- }
-
- if (!*ssq) { // Matched the whole subsequence in s
- if (ssq_last_tgt == &option.display[s.length() - 1]) { // Finished matching in the first s.length() characters
- completion_options.push_back(option);
- } else {
- completion_options_subseq.push_back(option);
- }
- } else if (!*ssq_lower) { // Matched the whole subsequence in s_lower
- if (ssq_lower_last_tgt == &option.display[s.length() - 1]) { // Finished matching in the first s.length() characters
- completion_options_casei.push_back(option);
- } else {
- completion_options_subseq_casei.push_back(option);
- }
- }
- }
- }
-
- completion_options.append_array(completion_options_casei);
- completion_options.append_array(completion_options_subseq);
- completion_options.append_array(completion_options_subseq_casei);
-
- if (completion_options.size() == 0) {
- // No options to complete, cancel.
- _cancel_completion();
- return;
- }
-
- if (completion_options.size() == 1 && s == completion_options[0].display) {
- // A perfect match, stop completion.
- _cancel_completion();
- return;
- }
-
- // The top of the list is the best match.
- completion_current = completion_options[0];
- completion_enabled = true;
-}
-
-void TextEdit::query_code_comple() {
- String l = text[cursor.line];
- int ofs = CLAMP(cursor.column, 0, l.length());
-
- bool inquote = false;
-
- int c = ofs - 1;
- while (c >= 0) {
- if (l[c] == '"' || l[c] == '\'') {
- inquote = !inquote;
- }
- c--;
- }
-
- bool ignored = completion_active && !completion_options.is_empty();
- if (ignored) {
- ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_PLAIN_TEXT;
- const ScriptCodeCompletionOption *previous_option = nullptr;
- for (int i = 0; i < completion_options.size(); i++) {
- const ScriptCodeCompletionOption &current_option = completion_options[i];
- if (!previous_option) {
- previous_option = &current_option;
- kind = current_option.kind;
- }
- if (previous_option->kind != current_option.kind) {
- ignored = false;
- break;
- }
- }
- ignored = ignored && (kind == ScriptCodeCompletionOption::KIND_FILE_PATH || kind == ScriptCodeCompletionOption::KIND_NODE_PATH || kind == ScriptCodeCompletionOption::KIND_SIGNAL);
- }
-
- if (!ignored) {
- if (ofs > 0 && (inquote || _is_completable(l[ofs - 1]) || completion_prefixes.has(String::chr(l[ofs - 1])))) {
- emit_signal("request_completion");
- } else if (ofs > 1 && l[ofs - 1] == ' ' && completion_prefixes.has(String::chr(l[ofs - 2]))) { // Make it work with a space too, it's good enough.
- emit_signal("request_completion");
- }
- }
-}
-
-void TextEdit::set_code_hint(const String &p_hint) {
- completion_hint = p_hint;
- completion_hint_offset = -0xFFFF;
- update();
-}
-
-void TextEdit::code_complete(const List<ScriptCodeCompletionOption> &p_strings, bool p_forced) {
- completion_sources = p_strings;
- completion_active = true;
- completion_forced = p_forced;
- completion_current = ScriptCodeCompletionOption();
- completion_index = 0;
- _update_completion_candidates();
-}
-
String TextEdit::get_word_at_pos(const Vector2 &p_pos) const {
int row, col;
_get_mouse_pos(p_pos, row, col);
@@ -6845,6 +6196,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_line_count"), &TextEdit::get_line_count);
ClassDB::bind_method(D_METHOD("get_text"), &TextEdit::get_text);
ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line);
+ ClassDB::bind_method(D_METHOD("get_visible_line_count"), &TextEdit::get_total_visible_rows);
ClassDB::bind_method(D_METHOD("set_line", "line", "new_text"), &TextEdit::set_line);
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &TextEdit::set_structured_text_bidi_override);
@@ -6856,6 +6208,8 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("cursor_set_column", "column", "adjust_viewport"), &TextEdit::cursor_set_column, DEFVAL(true));
ClassDB::bind_method(D_METHOD("cursor_set_line", "line", "adjust_viewport", "can_be_hidden", "wrap_index"), &TextEdit::cursor_set_line, DEFVAL(true), DEFVAL(true), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_caret_draw_pos"), &TextEdit::get_caret_draw_pos);
+ ClassDB::bind_method(D_METHOD("is_caret_visible"), &TextEdit::is_caret_visible);
ClassDB::bind_method(D_METHOD("cursor_get_column"), &TextEdit::cursor_get_column);
ClassDB::bind_method(D_METHOD("cursor_get_line"), &TextEdit::cursor_get_line);
ClassDB::bind_method(D_METHOD("cursor_set_blink_enabled", "enable"), &TextEdit::cursor_set_blink_enabled);
@@ -6971,6 +6325,10 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_line_gutter_clickable", "line", "gutter", "clickable"), &TextEdit::set_line_gutter_clickable);
ClassDB::bind_method(D_METHOD("is_line_gutter_clickable", "line", "gutter"), &TextEdit::is_line_gutter_clickable);
+ // Line style
+ ClassDB::bind_method(D_METHOD("set_line_background_color", "line", "color"), &TextEdit::set_line_background_color);
+ ClassDB::bind_method(D_METHOD("get_line_background_color", "line"), &TextEdit::get_line_background_color);
+
ClassDB::bind_method(D_METHOD("set_highlight_current_line", "enabled"), &TextEdit::set_highlight_current_line);
ClassDB::bind_method(D_METHOD("is_highlight_current_line_enabled"), &TextEdit::is_highlight_current_line_enabled);
@@ -6992,7 +6350,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_minimap_width"), &TextEdit::get_minimap_width);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly");
@@ -7032,7 +6390,6 @@ void TextEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("cursor_changed"));
ADD_SIGNAL(MethodInfo("text_changed"));
ADD_SIGNAL(MethodInfo("lines_edited_from", PropertyInfo(Variant::INT, "from_line"), PropertyInfo(Variant::INT, "to_line")));
- ADD_SIGNAL(MethodInfo("request_completion"));
ADD_SIGNAL(MethodInfo("gutter_clicked", PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "gutter")));
ADD_SIGNAL(MethodInfo("gutter_added"));
ADD_SIGNAL(MethodInfo("gutter_removed"));
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index b0c7314c65..f963e664d1 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -92,7 +92,7 @@ private:
Vector<Vector2i> bidi_override;
Ref<TextParagraph> data_buf;
- bool marked = false;
+ Color background_color = Color(0, 0, 0, 0);
bool hidden = false;
Line() {
@@ -129,12 +129,11 @@ private:
void set_width(float p_width);
int get_line_wrap_amount(int p_line) const;
+
Vector<Vector2i> get_line_wrap_ranges(int p_line) const;
const Ref<TextParagraph> get_line_data(int p_line) const;
void set(int p_line, const String &p_text, const Vector<Vector2i> &p_bidi_override);
- void set_marked(int p_line, bool p_marked) { text.write[p_line].marked = p_marked; }
- bool is_marked(int p_line) const { return text[p_line].marked; }
void set_hidden(int p_line, bool p_hidden) { text.write[p_line].hidden = p_hidden; }
bool is_hidden(int p_line) const { return text[p_line].hidden; }
void insert(int p_at, const String &p_text, const Vector<Vector2i> &p_bidi_override);
@@ -167,9 +166,15 @@ private:
void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable) { text.write[p_line].gutters.write[p_gutter].clickable = p_clickable; }
bool is_line_gutter_clickable(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].clickable; }
+
+ /* Line style. */
+ void set_line_background_color(int p_line, const Color &p_color) { text.write[p_line].background_color = p_color; }
+ const Color get_line_background_color(int p_line) const { return text[p_line].background_color; }
};
struct Cursor {
+ Point2 draw_pos;
+ bool visible = false;
int last_fit_x = 0;
int line = 0;
int column = 0; ///< cursor
@@ -236,20 +241,6 @@ private:
Dictionary _get_line_syntax_highlighting(int p_line);
- Set<String> completion_prefixes;
- bool completion_enabled = false;
- List<ScriptCodeCompletionOption> completion_sources;
- Vector<ScriptCodeCompletionOption> completion_options;
- bool completion_active = false;
- bool completion_forced = false;
- ScriptCodeCompletionOption completion_current;
- String completion_base;
- int completion_index = 0;
- Rect2i completion_rect;
- int completion_line_ofs = 0;
- String completion_hint;
- int completion_hint_offset = 0;
-
bool setting_text = false;
// data
@@ -303,10 +294,10 @@ private:
bool highlight_all_occurrences = false;
bool scroll_past_end_of_file_enabled = false;
- bool auto_brace_completion_enabled = false;
bool brace_matching_enabled = false;
bool highlight_current_line = false;
bool auto_indent = false;
+
String cut_copy_line;
bool insert_mode = false;
bool select_identifiers_enabled = false;
@@ -338,9 +329,6 @@ private:
bool next_operation_is_complex = false;
- bool callhint_below = false;
- Vector2 callhint_offset;
-
String search_text;
uint32_t search_flags = 0;
int search_result_line = 0;
@@ -434,10 +422,6 @@ private:
PopupMenu *menu_ctl;
void _clear();
- void _cancel_completion();
- void _cancel_code_hint();
- void _confirm_completion();
- void _update_completion_candidates();
int _calculate_spaces_till_next_left_indent(int column);
int _calculate_spaces_till_next_right_indent(int column);
@@ -460,9 +444,11 @@ private:
void _delete_selection();
void _move_cursor_document_start(bool p_select);
void _move_cursor_document_end(bool p_select);
- void _handle_unicode_character(uint32_t unicode, bool p_had_selection, bool p_update_auto_complete);
+ void _handle_unicode_character(uint32_t unicode, bool p_had_selection);
protected:
+ bool auto_brace_completion_enabled = false;
+
struct Cache {
Ref<Texture2D> tab_icon;
Ref<Texture2D> space_icon;
@@ -474,17 +460,12 @@ protected:
int font_size = 16;
int outline_size = 0;
Color outline_color;
- Color completion_background_color;
- Color completion_selected_color;
- Color completion_existing_color;
- Color completion_font_color;
Color caret_color;
Color caret_background_color;
Color font_color;
Color font_selected_color;
Color font_readonly_color;
Color selection_color;
- Color mark_color;
Color code_folding_color;
Color current_line_color;
Color line_length_guideline_color;
@@ -503,7 +484,7 @@ protected:
void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr);
void _remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
void _insert_text_at_cursor(const String &p_text);
- void _gui_input(const Ref<InputEvent> &p_gui_input);
+ virtual void _gui_input(const Ref<InputEvent> &p_gui_input);
void _notification(int p_what);
void _consume_pair_symbol(char32_t ch);
@@ -561,6 +542,10 @@ public:
void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable);
bool is_line_gutter_clickable(int p_line, int p_gutter) const;
+ // Line style
+ void set_line_background_color(int p_line, const Color &p_color);
+ Color get_line_background_color(int p_line);
+
enum MenuItems {
MENU_CUT,
MENU_COPY,
@@ -637,7 +622,6 @@ public:
void insert_text_at_cursor(const String &p_text);
void insert_at(const String &p_text, int at);
int get_line_count() const;
- void set_line_as_marked(int p_line, bool p_marked);
void set_line_as_hidden(int p_line, bool p_hidden);
bool is_line_hidden(int p_line) const;
@@ -676,10 +660,6 @@ public:
brace_matching_enabled = p_enabled;
update();
}
- inline void set_callhint_settings(bool below, Vector2 offset) {
- callhint_below = below;
- callhint_offset = offset;
- }
void set_auto_indent(bool p_auto_indent);
void center_viewport_to_cursor();
@@ -690,6 +670,8 @@ public:
void cursor_set_column(int p_col, bool p_adjust_viewport = true);
void cursor_set_line(int p_row, bool p_adjust_viewport = true, bool p_can_be_hidden = true, int p_wrap_index = 0);
+ Point2 get_caret_draw_pos() const;
+ bool is_caret_visible() const;
int cursor_get_column() const;
int cursor_get_line() const;
Vector2i _get_cursor_pixel_pos(bool p_adjust_viewport = true);
@@ -726,6 +708,7 @@ public:
void copy();
void paste();
void select_all();
+ void select_word_under_caret();
void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
void deselect();
void swap_lines(int line1, int line2);
@@ -805,11 +788,6 @@ public:
void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
- void set_completion(bool p_enabled, const Vector<String> &p_prefixes);
- void code_complete(const List<ScriptCodeCompletionOption> &p_strings, bool p_forced = false);
- void set_code_hint(const String &p_hint);
- void query_code_comple();
-
void set_select_identifiers_on_hover(bool p_enable);
bool is_selecting_identifiers_on_hover_enabled() const;
@@ -827,7 +805,6 @@ public:
PopupMenu *get_menu() const;
- String get_text_for_completion();
String get_text_for_lookup_completion();
virtual bool is_text_field() const override;
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index f43e3d1a9d..8659ea06a2 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -295,11 +295,13 @@ void TextureButton::set_normal_texture(const Ref<Texture2D> &p_normal) {
void TextureButton::set_pressed_texture(const Ref<Texture2D> &p_pressed) {
pressed = p_pressed;
update();
+ minimum_size_changed();
}
void TextureButton::set_hover_texture(const Ref<Texture2D> &p_hover) {
hover = p_hover;
update();
+ minimum_size_changed();
}
void TextureButton::set_disabled_texture(const Ref<Texture2D> &p_disabled) {
@@ -310,6 +312,7 @@ void TextureButton::set_disabled_texture(const Ref<Texture2D> &p_disabled) {
void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
click_mask = p_click_mask;
update();
+ minimum_size_changed();
}
Ref<Texture2D> TextureButton::get_normal_texture() const {
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 7028d7aed4..f66cc13af5 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -47,36 +47,6 @@
#include <limits.h>
-void TreeItem::move_to_top() {
- if (!parent || parent->children == this) {
- return; //already on top
- }
- TreeItem *prev = get_prev();
- prev->next = next;
- next = parent->children;
- parent->children = this;
-}
-
-void TreeItem::move_to_bottom() {
- if (!parent || !next) {
- return;
- }
-
- TreeItem *prev = get_prev();
- TreeItem *last = next;
- while (last->next) {
- last = last->next;
- }
-
- if (prev) {
- prev->next = next;
- } else {
- parent->children = next;
- }
- last->next = this;
- next = nullptr;
-}
-
Size2 TreeItem::Cell::get_icon_size() const {
if (icon.is_null()) {
return Size2();
@@ -118,6 +88,54 @@ void TreeItem::_cell_deselected(int p_cell) {
tree->item_deselected(p_cell, this);
}
+void TreeItem::_change_tree(Tree *p_tree) {
+ if (p_tree == tree) {
+ return;
+ }
+
+ TreeItem *c = first_child;
+ while (c) {
+ c->_change_tree(p_tree);
+ c = c->next;
+ }
+
+ if (tree && tree->root == this) {
+ tree->root = nullptr;
+ }
+
+ if (tree && tree->popup_edited_item == this) {
+ tree->popup_edited_item = nullptr;
+ tree->pressing_for_editor = false;
+ }
+
+ if (tree && tree->cache.hover_item == this) {
+ tree->cache.hover_item = nullptr;
+ }
+
+ if (tree && tree->selected_item == this) {
+ tree->selected_item = nullptr;
+ }
+
+ if (tree && tree->drop_mode_over == this) {
+ tree->drop_mode_over = nullptr;
+ }
+
+ if (tree && tree->single_select_defer == this) {
+ tree->single_select_defer = nullptr;
+ }
+
+ if (tree && tree->edited_item == this) {
+ tree->edited_item = nullptr;
+ tree->pressing_for_editor = false;
+ }
+
+ tree = p_tree;
+
+ if (tree) {
+ cells.resize(tree->columns.size());
+ }
+}
+
/* cell mode */
void TreeItem::set_cell_mode(int p_column, TreeCellMode p_mode) {
ERR_FAIL_INDEX(p_column, cells.size());
@@ -427,20 +445,74 @@ int TreeItem::get_custom_minimum_height() const {
return custom_min_height;
}
+/* Item manipulation */
+
+TreeItem *TreeItem::create_child(int p_idx) {
+ TreeItem *ti = memnew(TreeItem(tree));
+ if (tree) {
+ ti->cells.resize(tree->columns.size());
+ }
+
+ TreeItem *l_prev = nullptr;
+ TreeItem *c = first_child;
+ int idx = 0;
+
+ while (c) {
+ if (idx++ == p_idx) {
+ c->prev = ti;
+ ti->next = c;
+ break;
+ }
+ l_prev = c;
+ c = c->next;
+ }
+
+ if (l_prev) {
+ l_prev->next = ti;
+ ti->prev = l_prev;
+ if (!children_cache.is_empty()) {
+ if (ti->next) {
+ children_cache.insert(p_idx, ti);
+ } else {
+ children_cache.append(ti);
+ }
+ }
+ } else {
+ first_child = ti;
+ if (!children_cache.is_empty()) {
+ children_cache.insert(0, ti);
+ }
+ }
+
+ ti->parent = this;
+
+ return ti;
+}
+
+Tree *TreeItem::get_tree() {
+ return tree;
+}
+
TreeItem *TreeItem::get_next() {
return next;
}
TreeItem *TreeItem::get_prev() {
- if (!parent || parent->children == this) {
- return nullptr;
+ if (prev) {
+ return prev;
}
- TreeItem *prev = parent->children;
- while (prev && prev->next != this) {
- prev = prev->next;
+ if (!parent || parent->first_child == this) {
+ return nullptr;
+ }
+ // This is an edge case
+ TreeItem *l_prev = parent->first_child;
+ while (l_prev && l_prev->next != this) {
+ l_prev = l_prev->next;
}
+ prev = l_prev;
+
return prev;
}
@@ -448,8 +520,8 @@ TreeItem *TreeItem::get_parent() {
return parent;
}
-TreeItem *TreeItem::get_children() {
- return children;
+TreeItem *TreeItem::get_first_child() {
+ return first_child;
}
TreeItem *TreeItem::get_prev_visible(bool p_wrap) {
@@ -475,10 +547,10 @@ TreeItem *TreeItem::get_prev_visible(bool p_wrap) {
}
} else {
current = prev;
- while (!current->collapsed && current->children) {
+ while (!current->collapsed && current->first_child) {
//go to the very end
- current = current->children;
+ current = current->first_child;
while (current->next) {
current = current->next;
}
@@ -491,8 +563,8 @@ TreeItem *TreeItem::get_prev_visible(bool p_wrap) {
TreeItem *TreeItem::get_next_visible(bool p_wrap) {
TreeItem *current = this;
- if (!current->collapsed && current->children) {
- current = current->children;
+ if (!current->collapsed && current->first_child) {
+ current = current->first_child;
} else if (current->next) {
current = current->next;
@@ -515,24 +587,136 @@ TreeItem *TreeItem::get_next_visible(bool p_wrap) {
return current;
}
-void TreeItem::remove_child(TreeItem *p_item) {
+TreeItem *TreeItem::get_child(int p_idx) {
+ _create_children_cache();
+ ERR_FAIL_INDEX_V(p_idx, children_cache.size(), nullptr);
+ return children_cache.get(p_idx);
+}
+
+int TreeItem::get_child_count() {
+ _create_children_cache();
+ return children_cache.size();
+}
+
+Array TreeItem::get_children() {
+ int size = get_child_count();
+ Array arr;
+ arr.resize(size);
+ for (int i = 0; i < size; i++) {
+ arr[i] = children_cache[i];
+ }
+
+ return arr;
+}
+
+int TreeItem::get_index() {
+ int idx = 0;
+ TreeItem *c = this;
+
+ while (c) {
+ c = c->get_prev();
+ idx++;
+ }
+ return idx - 1;
+}
+
+void TreeItem::move_before(TreeItem *p_item) {
ERR_FAIL_NULL(p_item);
- TreeItem **c = &children;
+ ERR_FAIL_COND(is_root);
+ ERR_FAIL_COND(!p_item->parent);
+
+ if (p_item == this) {
+ return;
+ }
- while (*c) {
- if ((*c) == p_item) {
- TreeItem *aux = *c;
+ TreeItem *p = p_item->parent;
+ while (p) {
+ ERR_FAIL_COND_MSG(p == this, "Can't move to a descendant");
+ p = p->parent;
+ }
- *c = (*c)->next;
+ Tree *old_tree = tree;
+ _unlink_from_tree();
+ _change_tree(p_item->tree);
- aux->parent = nullptr;
- return;
- }
+ parent = p_item->parent;
+
+ TreeItem *item_prev = p_item->get_prev();
+ if (item_prev) {
+ item_prev->next = this;
+ parent->children_cache.clear();
+ } else {
+ parent->first_child = this;
+ parent->children_cache.insert(0, this);
+ }
- c = &(*c)->next;
+ prev = item_prev;
+ next = p_item;
+ p_item->prev = this;
+
+ if (old_tree && old_tree != tree) {
+ old_tree->update();
}
- ERR_FAIL();
+ if (tree) {
+ tree->update();
+ }
+}
+
+void TreeItem::move_after(TreeItem *p_item) {
+ ERR_FAIL_NULL(p_item);
+ ERR_FAIL_COND(is_root);
+ ERR_FAIL_COND(!p_item->parent);
+
+ if (p_item == this) {
+ return;
+ }
+
+ TreeItem *p = p_item->parent;
+ while (p) {
+ ERR_FAIL_COND_MSG(p == this, "Can't move to a descendant");
+ p = p->parent;
+ }
+
+ Tree *old_tree = tree;
+ _unlink_from_tree();
+ _change_tree(p_item->tree);
+
+ if (p_item->next) {
+ p_item->next->prev = this;
+ }
+ parent = p_item->parent;
+ prev = p_item;
+ next = p_item->next;
+ p_item->next = this;
+
+ if (next) {
+ parent->children_cache.clear();
+ } else {
+ parent->children_cache.append(this);
+ }
+
+ if (old_tree && old_tree != tree) {
+ old_tree->update();
+ }
+
+ if (tree) {
+ tree->update();
+ }
+}
+
+void TreeItem::remove_child(TreeItem *p_item) {
+ ERR_FAIL_NULL(p_item);
+ ERR_FAIL_COND(p_item->parent != this);
+
+ p_item->_unlink_from_tree();
+ p_item->prev = nullptr;
+ p_item->next = nullptr;
+ p_item->parent = nullptr;
+
+ if (tree) {
+ tree->update();
+ }
}
void TreeItem::set_selectable(int p_column, bool p_selectable) {
@@ -686,6 +870,15 @@ void TreeItem::clear_custom_color(int p_column) {
_changed_notify(p_column);
}
+void TreeItem::set_custom_font(int p_column, const Ref<Font> &p_font) {
+ ERR_FAIL_INDEX(p_column, cells.size());
+ cells.write[p_column].custom_font = p_font;
+}
+Ref<Font> TreeItem::get_custom_font(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, cells.size(), Ref<Font>());
+ return cells[p_column].custom_font;
+}
+
void TreeItem::set_tooltip(int p_column, const String &p_tooltip) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].tooltip = p_tooltip;
@@ -785,7 +978,7 @@ void recursive_call_aux(TreeItem *p_item, const StringName &p_method, const Vari
return;
}
p_item->call(p_method, p_args, p_argcount, r_error);
- TreeItem *c = p_item->get_children();
+ TreeItem *c = p_item->get_first_child();
while (c) {
recursive_call_aux(c, p_method, p_args, p_argcount, r_error);
c = c->get_next();
@@ -855,16 +1048,6 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_minimum_height", "height"), &TreeItem::set_custom_minimum_height);
ClassDB::bind_method(D_METHOD("get_custom_minimum_height"), &TreeItem::get_custom_minimum_height);
- ClassDB::bind_method(D_METHOD("get_next"), &TreeItem::get_next);
- ClassDB::bind_method(D_METHOD("get_prev"), &TreeItem::get_prev);
- ClassDB::bind_method(D_METHOD("get_parent"), &TreeItem::get_parent);
- ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children);
-
- ClassDB::bind_method(D_METHOD("get_next_visible", "wrap"), &TreeItem::get_next_visible, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_prev_visible", "wrap"), &TreeItem::get_prev_visible, DEFVAL(false));
-
- ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child);
-
ClassDB::bind_method(D_METHOD("set_selectable", "column", "selectable"), &TreeItem::set_selectable);
ClassDB::bind_method(D_METHOD("is_selectable", "column"), &TreeItem::is_selectable);
@@ -876,8 +1059,11 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_editable", "column"), &TreeItem::is_editable);
ClassDB::bind_method(D_METHOD("set_custom_color", "column", "color"), &TreeItem::set_custom_color);
- ClassDB::bind_method(D_METHOD("clear_custom_color", "column"), &TreeItem::clear_custom_color);
ClassDB::bind_method(D_METHOD("get_custom_color", "column"), &TreeItem::get_custom_color);
+ ClassDB::bind_method(D_METHOD("clear_custom_color", "column"), &TreeItem::clear_custom_color);
+
+ ClassDB::bind_method(D_METHOD("set_custom_font", "column", "font"), &TreeItem::set_custom_font);
+ ClassDB::bind_method(D_METHOD("get_custom_font", "column"), &TreeItem::get_custom_font);
ClassDB::bind_method(D_METHOD("set_custom_bg_color", "column", "color", "just_outline"), &TreeItem::set_custom_bg_color, DEFVAL(false));
ClassDB::bind_method(D_METHOD("clear_custom_bg_color", "column"), &TreeItem::clear_custom_bg_color);
@@ -895,19 +1081,38 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_button_disabled", "column", "button_idx", "disabled"), &TreeItem::set_button_disabled);
ClassDB::bind_method(D_METHOD("is_button_disabled", "column", "button_idx"), &TreeItem::is_button_disabled);
- ClassDB::bind_method(D_METHOD("set_expand_right", "column", "enable"), &TreeItem::set_expand_right);
- ClassDB::bind_method(D_METHOD("get_expand_right", "column"), &TreeItem::get_expand_right);
-
ClassDB::bind_method(D_METHOD("set_tooltip", "column", "tooltip"), &TreeItem::set_tooltip);
ClassDB::bind_method(D_METHOD("get_tooltip", "column"), &TreeItem::get_tooltip);
ClassDB::bind_method(D_METHOD("set_text_align", "column", "text_align"), &TreeItem::set_text_align);
ClassDB::bind_method(D_METHOD("get_text_align", "column"), &TreeItem::get_text_align);
- ClassDB::bind_method(D_METHOD("move_to_top"), &TreeItem::move_to_top);
- ClassDB::bind_method(D_METHOD("move_to_bottom"), &TreeItem::move_to_bottom);
+
+ ClassDB::bind_method(D_METHOD("set_expand_right", "column", "enable"), &TreeItem::set_expand_right);
+ ClassDB::bind_method(D_METHOD("get_expand_right", "column"), &TreeItem::get_expand_right);
ClassDB::bind_method(D_METHOD("set_disable_folding", "disable"), &TreeItem::set_disable_folding);
ClassDB::bind_method(D_METHOD("is_folding_disabled"), &TreeItem::is_folding_disabled);
+ ClassDB::bind_method(D_METHOD("create_child", "idx"), &TreeItem::create_child, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_tree"), &TreeItem::get_tree);
+
+ ClassDB::bind_method(D_METHOD("get_next"), &TreeItem::get_next);
+ ClassDB::bind_method(D_METHOD("get_prev"), &TreeItem::get_prev);
+ ClassDB::bind_method(D_METHOD("get_parent"), &TreeItem::get_parent);
+ ClassDB::bind_method(D_METHOD("get_first_child"), &TreeItem::get_first_child);
+
+ ClassDB::bind_method(D_METHOD("get_next_visible", "wrap"), &TreeItem::get_next_visible, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_prev_visible", "wrap"), &TreeItem::get_prev_visible, DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("get_child", "idx"), &TreeItem::get_child);
+ ClassDB::bind_method(D_METHOD("get_child_count"), &TreeItem::get_child_count);
+ ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children);
+ ClassDB::bind_method(D_METHOD("get_index"), &TreeItem::get_index);
+
+ ClassDB::bind_method(D_METHOD("move_before", "item"), &TreeItem::_move_before);
+ ClassDB::bind_method(D_METHOD("move_after", "item"), &TreeItem::_move_after);
+
+ ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child);
+
{
MethodInfo mi;
mi.name = "call_recursive";
@@ -932,7 +1137,7 @@ void TreeItem::_bind_methods() {
}
void TreeItem::clear_children() {
- TreeItem *c = children;
+ TreeItem *c = first_child;
while (c) {
TreeItem *aux = c;
c = c->get_next();
@@ -940,56 +1145,18 @@ void TreeItem::clear_children() {
memdelete(aux);
}
- children = nullptr;
+ first_child = nullptr;
};
TreeItem::TreeItem(Tree *p_tree) {
tree = p_tree;
- collapsed = false;
- disable_folding = false;
- custom_min_height = 0;
-
- parent = nullptr; // parent item
- next = nullptr; // next in list
- children = nullptr; //child items
}
TreeItem::~TreeItem() {
+ _unlink_from_tree();
+ prev = nullptr;
clear_children();
-
- if (parent) {
- parent->remove_child(this);
- }
-
- if (tree && tree->root == this) {
- tree->root = nullptr;
- }
-
- if (tree && tree->popup_edited_item == this) {
- tree->popup_edited_item = nullptr;
- tree->pressing_for_editor = false;
- }
-
- if (tree && tree->cache.hover_item == this) {
- tree->cache.hover_item = nullptr;
- }
-
- if (tree && tree->selected_item == this) {
- tree->selected_item = nullptr;
- }
-
- if (tree && tree->drop_mode_over == this) {
- tree->drop_mode_over = nullptr;
- }
-
- if (tree && tree->single_select_defer == this) {
- tree->single_select_defer = nullptr;
- }
-
- if (tree && tree->edited_item == this) {
- tree->edited_item = nullptr;
- tree->pressing_for_editor = false;
- }
+ _change_tree(nullptr);
}
/**********************************************/
@@ -1029,15 +1196,23 @@ void Tree::update_cache() {
cache.font_color = get_theme_color("font_color");
cache.font_selected_color = get_theme_color("font_selected_color");
- cache.guide_color = get_theme_color("guide_color");
cache.drop_position_color = get_theme_color("drop_position_color");
cache.hseparation = get_theme_constant("hseparation");
cache.vseparation = get_theme_constant("vseparation");
cache.item_margin = get_theme_constant("item_margin");
cache.button_margin = get_theme_constant("button_margin");
+
cache.draw_guides = get_theme_constant("draw_guides");
+ cache.guide_color = get_theme_color("guide_color");
cache.draw_relationship_lines = get_theme_constant("draw_relationship_lines");
+ cache.relationship_line_width = get_theme_constant("relationship_line_width");
+ cache.parent_hl_line_width = get_theme_constant("parent_hl_line_width");
+ cache.children_hl_line_width = get_theme_constant("children_hl_line_width");
+ cache.parent_hl_line_margin = get_theme_constant("parent_hl_line_margin");
cache.relationship_line_color = get_theme_color("relationship_line_color");
+ cache.parent_hl_line_color = get_theme_color("parent_hl_line_color");
+ cache.children_hl_line_color = get_theme_color("children_hl_line_color");
+
cache.scroll_border = get_theme_constant("scroll_border");
cache.scroll_speed = get_theme_constant("scroll_speed");
@@ -1116,7 +1291,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
if (!p_item->collapsed) { /* if not collapsed, check the children */
- TreeItem *c = p_item->children;
+ TreeItem *c = p_item->first_child;
while (c) {
height += get_item_height(c);
@@ -1209,6 +1384,7 @@ void Tree::update_column(int p_col) {
} else {
columns.write[p_col].text_buf->set_direction((TextServer::Direction)columns[p_col].text_direction);
}
+
columns.write[p_col].text_buf->add_string(columns[p_col].title, cache.font, cache.font_size, columns[p_col].opentype_features, (columns[p_col].language != "") ? columns[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
}
@@ -1253,7 +1429,14 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
} else {
p_item->cells.write[p_col].text_buf->set_direction((TextServer::Direction)p_item->cells[p_col].text_direction);
}
- p_item->cells.write[p_col].text_buf->add_string(valtext, cache.font, cache.font_size, p_item->cells[p_col].opentype_features, (p_item->cells[p_col].language != "") ? p_item->cells[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
+
+ Ref<Font> font;
+ if (p_item->cells[p_col].custom_font.is_valid()) {
+ font = p_item->cells[p_col].custom_font;
+ } else {
+ font = cache.font;
+ }
+ p_item->cells.write[p_col].text_buf->add_string(valtext, font, cache.font_size, p_item->cells[p_col].opentype_features, (p_item->cells[p_col].language != "") ? p_item->cells[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
TS->shaped_text_set_bidi_override(p_item->cells[p_col].text_buf->get_rid(), structured_text_parser(p_item->cells[p_col].st_parser, p_item->cells[p_col].st_args, valtext));
p_item->cells.write[p_col].dirty = false;
}
@@ -1263,7 +1446,7 @@ void Tree::update_item_cache(TreeItem *p_item) {
update_item_cell(p_item, i);
}
- TreeItem *c = p_item->children;
+ TreeItem *c = p_item->first_child;
while (c) {
update_item_cache(c);
c = c->next;
@@ -1430,7 +1613,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (drop_mode_flags && drop_mode_over == p_item) {
Rect2 r = cell_rect;
- bool has_parent = p_item->get_children() != nullptr;
+ bool has_parent = p_item->get_first_child() != nullptr;
if (rtl) {
r.position.x = get_size().width - r.position.x - r.size.x;
}
@@ -1626,7 +1809,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
}
- if (!p_item->disable_folding && !hide_folding && p_item->children) { //has children, draw the guide box
+ if (!p_item->disable_folding && !hide_folding && p_item->first_child) { //has children, draw the guide box
Ref<Texture2D> arrow;
@@ -1656,40 +1839,81 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (!p_item->collapsed) { /* if not collapsed, check the children */
- TreeItem *c = p_item->children;
+ TreeItem *c = p_item->first_child;
- int prev_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
+ int base_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
+ int prev_ofs = base_ofs;
+ int prev_hl_ofs = base_ofs;
while (c) {
if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root)) {
int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
- int parent_ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
+ int parent_ofs = p_pos.x + cache.item_margin;
Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
- if (c->get_children() != nullptr) {
+ if (c->get_first_child() != nullptr) {
root_pos -= Point2i(cache.arrow->get_width(), 0);
}
- float line_width = 1.0;
+ float line_width = cache.relationship_line_width;
+ float parent_line_width = cache.parent_hl_line_width;
+ float children_line_width = cache.children_hl_line_width;
+
#ifdef TOOLS_ENABLED
line_width *= Math::round(EDSCALE);
+ parent_line_width *= Math::round(EDSCALE);
+ children_line_width *= Math::round(EDSCALE);
#endif
Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;
+ int more_prev_ofs = 0;
+
if (root_pos.y + line_width >= 0) {
if (rtl) {
root_pos.x = get_size().width - root_pos.x;
parent_pos.x = get_size().width - parent_pos.x;
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), Point2i(parent_pos.x, prev_ofs), cache.relationship_line_color, line_width);
+
+ // Order of parts on this bend: the horizontal line first, then the vertical line.
+ if (_is_branch_selected(c)) {
+ // If this item or one of its children is selected, we draw the line using parent highlight style.
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+
+ more_prev_ofs = cache.parent_hl_line_margin;
+ prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+ } else if (p_item->is_selected(0)) {
+ // If parent item is selected (but this item is not), we draw the line using children highlight style.
+ // Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
+ if (_is_sibling_branch_selected(c)) {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+
+ prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+ } else {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), cache.children_hl_line_color, children_line_width);
+ }
+ } else {
+ // If nothing of the above is true, we draw the line using normal style.
+ // Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
+ if (_is_sibling_branch_selected(c)) {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + cache.parent_hl_line_margin, root_pos.y), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+
+ prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+ } else {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), cache.relationship_line_color, line_width);
+ }
+ }
}
if (htotal < 0) {
return -1;
}
- prev_ofs = root_pos.y;
+ prev_ofs = root_pos.y + more_prev_ofs;
}
if (htotal >= 0) {
@@ -1698,10 +1922,10 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (child_h < 0) {
if (cache.draw_relationship_lines == 0) {
return -1; // break, stop drawing, no need to anymore
- } else {
- htotal = -1;
- children_pos.y = cache.offset.y + p_draw_size.height;
}
+
+ htotal = -1;
+ children_pos.y = cache.offset.y + p_draw_size.height;
} else {
htotal += child_h;
children_pos.y += child_h;
@@ -1723,8 +1947,8 @@ int Tree::_count_selected_items(TreeItem *p_from) const {
}
}
- if (p_from->get_children()) {
- count += _count_selected_items(p_from->get_children());
+ if (p_from->get_first_child()) {
+ count += _count_selected_items(p_from->get_first_child());
}
if (p_from->get_next()) {
@@ -1734,6 +1958,36 @@ int Tree::_count_selected_items(TreeItem *p_from) const {
return count;
}
+bool Tree::_is_branch_selected(TreeItem *p_from) const {
+ for (int i = 0; i < columns.size(); i++) {
+ if (p_from->is_selected(i)) {
+ return true;
+ }
+ }
+
+ TreeItem *child_item = p_from->get_first_child();
+ while (child_item) {
+ if (_is_branch_selected(child_item)) {
+ return true;
+ }
+ child_item = child_item->get_next();
+ }
+
+ return false;
+}
+
+bool Tree::_is_sibling_branch_selected(TreeItem *p_from) const {
+ TreeItem *sibling_item = p_from->get_next();
+ while (sibling_item) {
+ if (_is_branch_selected(sibling_item)) {
+ return true;
+ }
+ sibling_item = sibling_item->get_next();
+ }
+
+ return false;
+}
+
void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev, bool *r_in_range, bool p_force_deselect) {
TreeItem::Cell &selected_cell = p_selected->cells.write[p_col];
@@ -1812,7 +2066,7 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c
*r_in_range = false;
}
- TreeItem *c = p_current->children;
+ TreeItem *c = p_current->first_child;
while (c) {
select_single_item(p_selected, c, p_col, p_prev, r_in_range, p_current->is_collapsed() || p_force_deselect);
@@ -1839,7 +2093,6 @@ void Tree::_range_click_timeout() {
click_handled = false;
Ref<InputEventMouseButton> mb;
mb.instance();
- ;
propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case)
blocked++;
@@ -1879,7 +2132,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
if (!p_item->disable_folding && !hide_folding && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) {
- if (p_item->children) {
+ if (p_item->first_child) {
p_item->set_collapsed(!p_item->is_collapsed());
}
@@ -1926,7 +2179,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
x -= cache.hseparation;
}
- if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_children()) {
+ if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_first_child()) {
p_item->set_collapsed(!p_item->is_collapsed());
return -1; //collapse/uncollapse because nothing can be done with item
}
@@ -1971,7 +2224,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
return -1;
}
- if (select_mode == SELECT_MULTI && p_mod->get_command() && c.selectable) {
+ if (select_mode == SELECT_MULTI && p_mod->is_command_pressed() && c.selectable) {
if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) {
p_item->select(col);
emit_signal("multi_selected", p_item, col, true);
@@ -1988,7 +2241,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
} else {
if (c.selectable) {
- if (select_mode == SELECT_MULTI && p_mod->get_shift() && selected_item && selected_item != p_item) {
+ if (select_mode == SELECT_MULTI && p_mod->is_shift_pressed() && selected_item && selected_item != p_item) {
bool inrange = false;
select_single_item(p_item, root, col, selected_item, &inrange);
@@ -2164,7 +2417,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
if (!p_item->collapsed) { /* if not collapsed, check the children */
- TreeItem *c = p_item->children;
+ TreeItem *c = p_item->first_child;
while (c) {
int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, p_double_click, c, p_button, p_mod);
@@ -2270,7 +2523,7 @@ void Tree::popup_select(int p_option) {
void Tree::_go_left() {
if (selected_col == 0) {
- if (selected_item->get_children() != nullptr && !selected_item->is_collapsed()) {
+ if (selected_item->get_first_child() != nullptr && !selected_item->is_collapsed()) {
selected_item->set_collapsed(true);
} else {
if (columns.size() == 1) { // goto parent with one column
@@ -2298,7 +2551,7 @@ void Tree::_go_left() {
void Tree::_go_right() {
if (selected_col == (columns.size() - 1)) {
- if (selected_item->get_children() != nullptr && selected_item->is_collapsed()) {
+ if (selected_item->get_first_child() != nullptr && selected_item->is_collapsed()) {
selected_item->set_collapsed(false);
} else if (selected_item->get_next_visible()) {
selected_col = 0;
@@ -2406,7 +2659,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventKey> k = p_event;
- bool is_command = k.is_valid() && k->get_command();
+ bool is_command = k.is_valid() && k->is_command_pressed();
if (p_event->is_action("ui_right") && p_event->is_pressed()) {
if (!cursor_can_exit_tree) {
accept_event();
@@ -2415,9 +2668,9 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (!selected_item || select_mode == SELECT_ROW || selected_col > (columns.size() - 1)) {
return;
}
- if (k.is_valid() && k->get_alt()) {
+ if (k.is_valid() && k->is_alt_pressed()) {
selected_item->set_collapsed(false);
- TreeItem *next = selected_item->get_children();
+ TreeItem *next = selected_item->get_first_child();
while (next && next != selected_item->next) {
next->set_collapsed(false);
next = next->get_next_visible();
@@ -2434,9 +2687,9 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
return;
}
- if (k.is_valid() && k->get_alt()) {
+ if (k.is_valid() && k->is_alt_pressed()) {
selected_item->set_collapsed(true);
- TreeItem *next = selected_item->get_children();
+ TreeItem *next = selected_item->get_first_child();
while (next && next != selected_item->next) {
next->set_collapsed(true);
next = next->get_next_visible();
@@ -2564,7 +2817,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (!k->is_pressed()) {
return;
}
- if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) {
+ if (k->is_command_pressed() || (k->is_shift_pressed() && k->get_unicode() == 0) || k->is_meta_pressed()) {
return;
}
if (!root) {
@@ -2834,7 +3087,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
break;
}
}
- if (!root || (!root->get_children() && hide_root)) {
+ if (!root || (!root->get_first_child() && hide_root)) {
if (b->get_button_index() == MOUSE_BUTTON_RIGHT && allow_rmb_select) {
emit_signal("empty_tree_rmb_selected", get_local_mouse_position());
}
@@ -2873,14 +3126,14 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
drag_accum = 0;
//last_drag_accum=0;
drag_from = v_scroll->get_value();
- drag_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
+ drag_touching = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
drag_touching_deaccel = false;
if (drag_touching) {
set_physics_process_internal(true);
}
if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (get_item_at_position(b->get_position()) == nullptr && !b->get_shift() && !b->get_control() && !b->get_command()) {
+ if (get_item_at_position(b->get_position()) == nullptr && !b->is_shift_pressed() && !b->is_ctrl_pressed() && !b->is_command_pressed()) {
emit_signal("nothing_selected");
}
}
@@ -3269,38 +3522,15 @@ TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) {
TreeItem *ti = nullptr;
if (p_parent) {
- // Append or insert a new item to the given parent.
- ti = memnew(TreeItem(this));
- ERR_FAIL_COND_V(!ti, nullptr);
- ti->cells.resize(columns.size());
-
- TreeItem *prev = nullptr;
- TreeItem *c = p_parent->children;
- int idx = 0;
-
- while (c) {
- if (idx++ == p_idx) {
- ti->next = c;
- break;
- }
- prev = c;
- c = c->next;
- }
-
- if (prev) {
- prev->next = ti;
- } else {
- p_parent->children = ti;
- }
- ti->parent = p_parent;
-
+ ERR_FAIL_COND_V_MSG(p_parent->tree != this, nullptr, "A different tree owns the given parent");
+ ti = p_parent->create_child(p_idx);
} else {
if (!root) {
// No root exists, make the given item the new root.
ti = memnew(TreeItem(this));
ERR_FAIL_COND_V(!ti, nullptr);
ti->cells.resize(columns.size());
-
+ ti->is_root = true;
root = ti;
} else {
// Root exists, append or insert to root.
@@ -3321,8 +3551,8 @@ TreeItem *Tree::get_last_item() {
while (last) {
if (last->next) {
last = last->next;
- } else if (last->children) {
- last = last->children;
+ } else if (last->first_child) {
+ last = last->first_child;
} else {
break;
}
@@ -3491,8 +3721,8 @@ TreeItem *Tree::get_next_selected(TreeItem *p_item) {
if (!p_item) {
p_item = root;
} else {
- if (p_item->children) {
- p_item = p_item->children;
+ if (p_item->first_child) {
+ p_item = p_item->first_child;
} else if (p_item->next) {
p_item = p_item->next;
@@ -3561,7 +3791,7 @@ int Tree::get_column_width(int p_column) const {
void Tree::propagate_set_columns(TreeItem *p_item) {
p_item->cells.resize(columns.size());
- TreeItem *c = p_item->get_children();
+ TreeItem *c = p_item->get_first_child();
while (c) {
propagate_set_columns(c);
c = c->next;
@@ -3611,8 +3841,8 @@ int Tree::get_item_offset(TreeItem *p_item) const {
ofs += cache.vseparation;
}
- if (it->children && !it->collapsed) {
- it = it->children;
+ if (it->first_child && !it->collapsed) {
+ it = it->first_child;
} else if (it->next) {
it = it->next;
@@ -3935,7 +4165,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_
return nullptr; // do not try children, it's collapsed
}
- TreeItem *n = p_item->get_children();
+ TreeItem *n = p_item->get_first_child();
while (n) {
int ch;
TreeItem *r = _find_item_at_pos(n, pos, r_column, ch, section);
@@ -4255,7 +4485,7 @@ void Tree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_folding"), "set_hide_folding", "is_folding_hidden");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_root"), "set_hide_root", "is_root_hidden");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In between"), "set_drop_mode_flags", "get_drop_mode_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In Between"), "set_drop_mode_flags", "get_drop_mode_flags");
ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Row,Multi"), "set_select_mode", "get_select_mode");
ADD_SIGNAL(MethodInfo("item_selected"));
@@ -4334,6 +4564,8 @@ Tree::Tree() {
set_mouse_filter(MOUSE_FILTER_STOP);
set_clip_contents(true);
+
+ update_cache();
}
Tree::~Tree() {
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 6d36f0df7f..5176d01497 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -112,6 +112,8 @@ private:
Vector<Button> buttons;
+ Ref<Font> custom_font;
+
Cell() {
text_buf.instance();
}
@@ -122,14 +124,18 @@ private:
Vector<Cell> cells;
- bool collapsed; // won't show children
- bool disable_folding;
- int custom_min_height;
+ bool collapsed = false; // won't show children
+ bool disable_folding = false;
+ int custom_min_height = 0;
+
+ TreeItem *parent = nullptr; // parent item
+ TreeItem *prev = nullptr; // previous in list
+ TreeItem *next = nullptr; // next in list
+ TreeItem *first_child = nullptr;
- TreeItem *parent; // parent item
- TreeItem *next; // next in list
- TreeItem *children; //child items
- Tree *tree; //tree (for reference)
+ Vector<TreeItem *> children_cache;
+ bool is_root = false; // for tree root
+ Tree *tree; // tree (for reference)
TreeItem(Tree *p_tree);
@@ -138,9 +144,40 @@ private:
void _cell_selected(int p_cell);
void _cell_deselected(int p_cell);
+ void _change_tree(Tree *p_tree);
+
+ _FORCE_INLINE_ void _create_children_cache() {
+ if (children_cache.is_empty()) {
+ TreeItem *c = first_child;
+ while (c) {
+ children_cache.append(c);
+ c = c->next;
+ }
+ }
+ }
+
+ _FORCE_INLINE_ void _unlink_from_tree() {
+ TreeItem *p = get_prev();
+ if (p) {
+ p->next = next;
+ }
+ if (next) {
+ next->prev = p;
+ }
+ if (parent) {
+ if (!parent->children_cache.is_empty()) {
+ parent->children_cache.remove(get_index());
+ }
+ if (parent->first_child == this) {
+ parent->first_child = next;
+ }
+ }
+ }
+
protected:
static void _bind_methods();
- //bind helpers
+
+ // Bind helpers
Dictionary _get_range_config(int p_column) {
Dictionary d;
double min = 0.0, max = 0.0, step = 0.0;
@@ -156,6 +193,13 @@ protected:
remove_child(Object::cast_to<TreeItem>(p_child));
}
+ void _move_before(Object *p_item) {
+ move_before(Object::cast_to<TreeItem>(p_item));
+ }
+ void _move_after(Object *p_item) {
+ move_after(Object::cast_to<TreeItem>(p_item));
+ }
+
Variant _call_recursive_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
public:
@@ -234,16 +278,6 @@ public:
void set_custom_minimum_height(int p_height);
int get_custom_minimum_height() const;
- TreeItem *get_prev();
- TreeItem *get_next();
- TreeItem *get_parent();
- TreeItem *get_children();
-
- TreeItem *get_prev_visible(bool p_wrap = false);
- TreeItem *get_next_visible(bool p_wrap = false);
-
- void remove_child(TreeItem *p_item);
-
void set_selectable(int p_column, bool p_selectable);
bool is_selectable(int p_column) const;
@@ -259,6 +293,9 @@ public:
Color get_custom_color(int p_column) const;
void clear_custom_color(int p_column);
+ void set_custom_font(int p_column, const Ref<Font> &p_font);
+ Ref<Font> get_custom_font(int p_column) const;
+
void set_custom_bg_color(int p_column, const Color &p_color, bool p_bg_outline = false);
void clear_custom_bg_color(int p_column);
Color get_custom_bg_color(int p_column) const;
@@ -269,22 +306,43 @@ public:
void set_tooltip(int p_column, const String &p_tooltip);
String get_tooltip(int p_column) const;
- void clear_children();
-
void set_text_align(int p_column, TextAlign p_align);
TextAlign get_text_align(int p_column) const;
void set_expand_right(int p_column, bool p_enable);
bool get_expand_right(int p_column) const;
- void move_to_top();
- void move_to_bottom();
-
void set_disable_folding(bool p_disable);
bool is_folding_disabled() const;
+ /* Item manipulation */
+
+ TreeItem *create_child(int p_idx = -1);
+
+ Tree *get_tree();
+
+ TreeItem *get_prev();
+ TreeItem *get_next();
+ TreeItem *get_parent();
+ TreeItem *get_first_child();
+
+ TreeItem *get_prev_visible(bool p_wrap = false);
+ TreeItem *get_next_visible(bool p_wrap = false);
+
+ TreeItem *get_child(int p_idx);
+ int get_child_count();
+ Array get_children();
+ int get_index();
+
+ void move_before(TreeItem *p_item);
+ void move_after(TreeItem *p_item);
+
+ void remove_child(TreeItem *p_item);
+
void call_recursive(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ void clear_children();
+
~TreeItem();
};
@@ -441,6 +499,8 @@ private:
Color guide_color;
Color drop_position_color;
Color relationship_line_color;
+ Color parent_hl_line_color;
+ Color children_hl_line_color;
Color custom_button_font_highlight;
int hseparation = 0;
@@ -449,6 +509,10 @@ private:
int button_margin = 0;
Point2 offset;
int draw_relationship_lines = 0;
+ int relationship_line_width = 0;
+ int parent_hl_line_width = 0;
+ int children_hl_line_width = 0;
+ int parent_hl_line_margin = 0;
int draw_guides = 0;
int scroll_border = 0;
int scroll_speed = 0;
@@ -521,6 +585,8 @@ private:
bool hide_folding = false;
int _count_selected_items(TreeItem *p_from) const;
+ bool _is_branch_selected(TreeItem *p_from) const;
+ bool _is_sibling_branch_selected(TreeItem *p_from) const;
void _go_left();
void _go_right();
void _go_down();
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index fa98a10a26..181fe606c8 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -271,7 +271,7 @@ void CanvasItemMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "loop"), &CanvasItemMaterial::set_particles_anim_loop);
ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &CanvasItemMaterial::get_particles_anim_loop);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,Premult Alpha"), "set_blend_mode", "get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply,Premultiplied Alpha"), "set_blend_mode", "get_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mode", PROPERTY_HINT_ENUM, "Normal,Unshaded,Light Only"), "set_light_mode", "get_light_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_animation"), "set_particles_animation", "get_particles_animation");
@@ -1414,7 +1414,7 @@ CanvasItem::~CanvasItem() {
///////////////////////////////////////////////////////////////////
void CanvasTexture::set_diffuse_texture(const Ref<Texture2D> &p_diffuse) {
- ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_diffuse.ptr()) != nullptr, "Cant self-assign a CanvasTexture");
+ ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_diffuse.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
diffuse_texture = p_diffuse;
RID tex_rid = diffuse_texture.is_valid() ? diffuse_texture->get_rid() : RID();
@@ -1426,7 +1426,7 @@ Ref<Texture2D> CanvasTexture::get_diffuse_texture() const {
}
void CanvasTexture::set_normal_texture(const Ref<Texture2D> &p_normal) {
- ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_normal.ptr()) != nullptr, "Cant self-assign a CanvasTexture");
+ ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_normal.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
normal_texture = p_normal;
RID tex_rid = normal_texture.is_valid() ? normal_texture->get_rid() : RID();
RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_NORMAL, tex_rid);
@@ -1436,7 +1436,7 @@ Ref<Texture2D> CanvasTexture::get_normal_texture() const {
}
void CanvasTexture::set_specular_texture(const Ref<Texture2D> &p_specular) {
- ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_specular.ptr()) != nullptr, "Cant self-assign a CanvasTexture");
+ ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_specular.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
specular_texture = p_specular;
RID tex_rid = specular_texture.is_valid() ? specular_texture->get_rid() : RID();
RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_SPECULAR, tex_rid);
@@ -1554,7 +1554,7 @@ void CanvasTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "specular_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_specular_color", "get_specular_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "specular_shininess", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular_shininess", "get_specular_shininess");
ADD_GROUP("Texture", "texture_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Aniso.,Linear Mipmap Aniso."), "set_texture_filter", "get_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
}
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 884696d58d..927b114fbc 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -375,17 +375,19 @@ bool HTTPRequest::_update_connection() {
}
PackedByteArray chunk = client->read_response_body_chunk();
- downloaded.add(chunk.size());
- if (file) {
- const uint8_t *r = chunk.ptr();
- file->store_buffer(r, chunk.size());
- if (file->get_error() != OK) {
- call_deferred("_request_done", RESULT_DOWNLOAD_FILE_WRITE_ERROR, response_code, response_headers, PackedByteArray());
- return true;
+ if (chunk.size()) {
+ downloaded.add(chunk.size());
+ if (file) {
+ const uint8_t *r = chunk.ptr();
+ file->store_buffer(r, chunk.size());
+ if (file->get_error() != OK) {
+ call_deferred("_request_done", RESULT_DOWNLOAD_FILE_WRITE_ERROR, response_code, response_headers, PackedByteArray());
+ return true;
+ }
+ } else {
+ body.append_array(chunk);
}
- } else {
- body.append_array(chunk);
}
if (body_size_limit >= 0 && downloaded.get() > body_size_limit) {
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 92b0ff28e9..22e822253f 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -31,8 +31,8 @@
#ifndef HTTPREQUEST_H
#define HTTPREQUEST_H
+#include "core/io/file_access.h"
#include "core/io/http_client.h"
-#include "core/os/file_access.h"
#include "core/os/thread.h"
#include "core/templates/safe_refcount.h"
#include "node.h"
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index c90d3e4a32..622c271935 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -292,7 +292,7 @@ void Node::_propagate_exit_tree() {
void Node::move_child(Node *p_child, int p_pos) {
ERR_FAIL_NULL(p_child);
- ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1, "Invalid new child position: " + itos(p_pos) + ".");
+ ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1, vformat("Invalid new child position: %d.", p_pos));
ERR_FAIL_COND_MSG(p_child->data.parent != this, "Child is not a child of this node.");
ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, move_child() failed. Consider using call_deferred(\"move_child\") instead (or \"popup\" if this is from a popup).");
@@ -491,36 +491,24 @@ bool Node::is_network_master() const {
/***** RPC CONFIG ********/
-uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode) {
- uint16_t mid = get_node_rpc_method_id(p_method);
- if (mid == UINT16_MAX) {
- // It's new
- NetData nd;
- nd.name = p_method;
- nd.mode = p_mode;
- data.rpc_methods.push_back(nd);
- return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15);
- } else {
- int c_mid = (~(1 << 15)) & mid;
- data.rpc_methods.write[c_mid].mode = p_mode;
- return mid;
- }
-}
-
-uint16_t Node::rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode) {
- uint16_t pid = get_node_rset_property_id(p_property);
- if (pid == UINT16_MAX) {
- // It's new
- NetData nd;
- nd.name = p_property;
- nd.mode = p_mode;
- data.rpc_properties.push_back(nd);
- return ((uint16_t)data.rpc_properties.size() - 1) | (1 << 15);
- } else {
- int c_pid = (~(1 << 15)) & pid;
- data.rpc_properties.write[c_pid].mode = p_mode;
- return pid;
+uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel) {
+ for (int i = 0; i < data.rpc_methods.size(); i++) {
+ if (data.rpc_methods[i].name == p_method) {
+ MultiplayerAPI::RPCConfig &nd = data.rpc_methods.write[i];
+ nd.rpc_mode = p_rpc_mode;
+ nd.transfer_mode = p_transfer_mode;
+ nd.channel = p_channel;
+ return i | (1 << 15);
+ }
}
+ // New method
+ MultiplayerAPI::RPCConfig nd;
+ nd.name = p_method;
+ nd.rpc_mode = p_rpc_mode;
+ nd.transfer_mode = p_transfer_mode;
+ nd.channel = p_channel;
+ data.rpc_methods.push_back(nd);
+ return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15);
}
/***** RPC FUNCTIONS ********/
@@ -536,7 +524,7 @@ void Node::rpc(const StringName &p_method, VARIANT_ARG_DECLARE) {
argc++;
}
- rpcp(0, false, p_method, argptr, argc);
+ rpcp(0, p_method, argptr, argc);
}
void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
@@ -550,35 +538,7 @@ void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE
argc++;
}
- rpcp(p_peer_id, false, p_method, argptr, argc);
-}
-
-void Node::rpc_unreliable(const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- rpcp(0, true, p_method, argptr, argc);
-}
-
-void Node::rpc_unreliable_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- rpcp(p_peer_id, true, p_method, argptr, argc);
+ rpcp(p_peer_id, p_method, argptr, argc);
}
Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
@@ -597,7 +557,7 @@ Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallEr
StringName method = *p_args[0];
- rpcp(0, false, method, &p_args[1], p_argcount - 1);
+ rpcp(0, method, &p_args[1], p_argcount - 1);
r_error.error = Callable::CallError::CALL_OK;
return Variant();
@@ -627,92 +587,17 @@ Variant Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::Cal
int peer_id = *p_args[0];
StringName method = *p_args[1];
- rpcp(peer_id, false, method, &p_args[2], p_argcount - 2);
-
- r_error.error = Callable::CallError::CALL_OK;
- return Variant();
-}
-
-Variant Node::_rpc_unreliable_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- if (p_argcount < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- return Variant();
- }
-
- if (p_args[0]->get_type() != Variant::STRING_NAME) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING_NAME;
- return Variant();
- }
-
- StringName method = *p_args[0];
-
- rpcp(0, true, method, &p_args[1], p_argcount - 1);
+ rpcp(peer_id, method, &p_args[2], p_argcount - 2);
r_error.error = Callable::CallError::CALL_OK;
return Variant();
}
-Variant Node::_rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- if (p_argcount < 2) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 2;
- return Variant();
- }
-
- if (p_args[0]->get_type() != Variant::INT) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::INT;
- return Variant();
- }
-
- if (p_args[1]->get_type() != Variant::STRING_NAME) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 1;
- r_error.expected = Variant::STRING_NAME;
- return Variant();
- }
-
- int peer_id = *p_args[0];
- StringName method = *p_args[1];
-
- rpcp(peer_id, true, method, &p_args[2], p_argcount - 2);
-
- r_error.error = Callable::CallError::CALL_OK;
- return Variant();
-}
-
-void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
ERR_FAIL_COND(!is_inside_tree());
- get_multiplayer()->rpcp(this, p_peer_id, p_unreliable, p_method, p_arg, p_argcount);
-}
-
-void Node::rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
- ERR_FAIL_COND(!is_inside_tree());
- get_multiplayer()->rsetp(this, p_peer_id, p_unreliable, p_property, p_value);
-}
-
-/******** RSET *********/
-void Node::rset(const StringName &p_property, const Variant &p_value) {
- rsetp(0, false, p_property, p_value);
-}
-
-void Node::rset_id(int p_peer_id, const StringName &p_property, const Variant &p_value) {
- rsetp(p_peer_id, false, p_property, p_value);
-}
-
-void Node::rset_unreliable(const StringName &p_property, const Variant &p_value) {
- rsetp(0, true, p_property, p_value);
+ get_multiplayer()->rpcp(this, p_peer_id, true, p_method, p_arg, p_argcount);
}
-void Node::rset_unreliable_id(int p_peer_id, const StringName &p_property, const Variant &p_value) {
- rsetp(p_peer_id, true, p_property, p_value);
-}
-
-//////////// end of rpc
Ref<MultiplayerAPI> Node::get_multiplayer() const {
if (multiplayer.is_valid()) {
return multiplayer;
@@ -731,99 +616,11 @@ void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
multiplayer = p_multiplayer;
}
-uint16_t Node::get_node_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < data.rpc_methods.size(); i++) {
- if (data.rpc_methods[i].name == p_method) {
- // Returns `i` with the high bit set to 1 so we know that this id comes
- // from the node and not the script.
- return i | (1 << 15);
- }
- }
- return UINT16_MAX;
-}
-
-StringName Node::get_node_rpc_method(const uint16_t p_rpc_method_id) const {
- // Make sure this is a node generated ID.
- if (((1 << 15) & p_rpc_method_id) > 0) {
- int mid = (~(1 << 15)) & p_rpc_method_id;
- if (mid < data.rpc_methods.size()) {
- return data.rpc_methods[mid].name;
- }
- }
- return StringName();
+Vector<MultiplayerAPI::RPCConfig> Node::get_node_rpc_methods() const {
+ return data.rpc_methods;
}
-MultiplayerAPI::RPCMode Node::get_node_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- // Make sure this is a node generated ID.
- if (((1 << 15) & p_rpc_method_id) > 0) {
- int mid = (~(1 << 15)) & p_rpc_method_id;
- if (mid < data.rpc_methods.size()) {
- return data.rpc_methods[mid].mode;
- }
- }
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-MultiplayerAPI::RPCMode Node::get_node_rpc_mode(const StringName &p_method) const {
- return get_node_rpc_mode_by_id(get_node_rpc_method_id(p_method));
-}
-
-uint16_t Node::get_node_rset_property_id(const StringName &p_property) const {
- for (int i = 0; i < data.rpc_properties.size(); i++) {
- if (data.rpc_properties[i].name == p_property) {
- // Returns `i` with the high bit set to 1 so we know that this id comes
- // from the node and not the script.
- return i | (1 << 15);
- }
- }
- return UINT16_MAX;
-}
-
-StringName Node::get_node_rset_property(const uint16_t p_rset_property_id) const {
- // Make sure this is a node generated ID.
- if (((1 << 15) & p_rset_property_id) > 0) {
- int mid = (~(1 << 15)) & p_rset_property_id;
- if (mid < data.rpc_properties.size()) {
- return data.rpc_properties[mid].name;
- }
- }
- return StringName();
-}
-
-MultiplayerAPI::RPCMode Node::get_node_rset_mode_by_id(const uint16_t p_rset_property_id) const {
- if (((1 << 15) & p_rset_property_id) > 0) {
- int mid = (~(1 << 15)) & p_rset_property_id;
- if (mid < data.rpc_properties.size()) {
- return data.rpc_properties[mid].mode;
- }
- }
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-MultiplayerAPI::RPCMode Node::get_node_rset_mode(const StringName &p_property) const {
- return get_node_rset_mode_by_id(get_node_rset_property_id(p_property));
-}
-
-String Node::get_rpc_md5() const {
- String rpc_list;
- for (int i = 0; i < data.rpc_methods.size(); i += 1) {
- rpc_list += String(data.rpc_methods[i].name);
- }
- for (int i = 0; i < data.rpc_properties.size(); i += 1) {
- rpc_list += String(data.rpc_properties[i].name);
- }
- if (get_script_instance()) {
- Vector<ScriptNetData> rpc = get_script_instance()->get_rpc_methods();
- for (int i = 0; i < rpc.size(); i += 1) {
- rpc_list += String(rpc[i].name);
- }
- rpc = get_script_instance()->get_rset_properties();
- for (int i = 0; i < rpc.size(); i += 1) {
- rpc_list += String(rpc[i].name);
- }
- }
- return rpc_list.md5_text();
-}
+//////////// end of rpc
bool Node::can_process_notification(int p_what) const {
switch (p_what) {
@@ -1240,8 +1037,11 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name) {
void Node::add_child(Node *p_child, bool p_legible_unique_name) {
ERR_FAIL_NULL(p_child);
- ERR_FAIL_COND_MSG(p_child == this, "Can't add child '" + p_child->get_name() + "' to itself."); // adding to itself!
- ERR_FAIL_COND_MSG(p_child->data.parent, "Can't add child '" + p_child->get_name() + "' to '" + get_name() + "', already has a parent '" + p_child->data.parent->get_name() + "'."); //Fail if node has a parent
+ ERR_FAIL_COND_MSG(p_child == this, vformat("Can't add child '%s' to itself.", p_child->get_name())); // adding to itself!
+ ERR_FAIL_COND_MSG(p_child->data.parent, vformat("Can't add child '%s' to '%s', already has a parent '%s'.", p_child->get_name(), get_name(), p_child->data.parent->get_name())); //Fail if node has a parent
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_MSG(p_child->is_a_parent_of(this), vformat("Can't add child '%s' to '%s' as it would result in a cyclic dependency since '%s' is already a parent of '%s'.", p_child->get_name(), get_name(), p_child->get_name(), get_name()));
+#endif
ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_node() failed. Consider using call_deferred(\"add_child\", child) instead.");
/* Validate name */
@@ -1252,7 +1052,7 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) {
void Node::add_sibling(Node *p_sibling, bool p_legible_unique_name) {
ERR_FAIL_NULL(p_sibling);
- ERR_FAIL_COND_MSG(p_sibling == this, "Can't add sibling '" + p_sibling->get_name() + "' to itself."); // adding to itself!
+ ERR_FAIL_COND_MSG(p_sibling == this, vformat("Can't add sibling '%s' to itself.", p_sibling->get_name())); // adding to itself!
ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_sibling() failed. Consider using call_deferred(\"add_sibling\", sibling) instead.");
get_parent()->add_child(p_sibling, p_legible_unique_name);
@@ -1307,7 +1107,7 @@ void Node::remove_child(Node *p_child) {
}
}
- ERR_FAIL_COND_MSG(idx == -1, "Cannot remove child node " + p_child->get_name() + " as it is not a child of this node.");
+ ERR_FAIL_COND_MSG(idx == -1, vformat("Cannot remove child node '%s' as it is not a child of this node.", p_child->get_name()));
//ERR_FAIL_COND( p_child->data.blocked > 0 );
//if (data.scene) { does not matter
@@ -2391,7 +2191,7 @@ void Node::_replace_connections_target(Node *p_new_target) {
if (c.flags & CONNECT_PERSIST) {
c.signal.get_object()->disconnect(c.signal.get_name(), Callable(this, c.callable.get_method()));
bool valid = p_new_target->has_method(c.callable.get_method()) || Ref<Script>(p_new_target->get_script()).is_null() || Ref<Script>(p_new_target->get_script())->has_method(c.callable.get_method());
- ERR_CONTINUE_MSG(!valid, "Attempt to connect signal '" + c.signal.get_object()->get_class() + "." + c.signal.get_name() + "' to nonexistent method '" + c.callable.get_object()->get_class() + "." + c.callable.get_method() + "'.");
+ ERR_CONTINUE_MSG(!valid, vformat("Attempt to connect signal '%s.%s' to nonexistent method '%s.%s'.", c.signal.get_object()->get_class(), c.signal.get_name(), c.callable.get_object()->get_class(), c.callable.get_method()));
c.signal.get_object()->connect(c.signal.get_name(), Callable(p_new_target, c.callable.get_method()), c.binds, c.flags);
}
}
@@ -2776,8 +2576,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer);
ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer);
ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer);
- ClassDB::bind_method(D_METHOD("rpc_config", "method", "mode"), &Node::rpc_config);
- ClassDB::bind_method(D_METHOD("rset_config", "property", "mode"), &Node::rset_config);
+ ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
@@ -2794,22 +2593,13 @@ void Node::_bind_methods() {
mi.name = "rpc";
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc", &Node::_rpc_bind, mi);
- mi.name = "rpc_unreliable";
- ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_unreliable", &Node::_rpc_unreliable_bind, mi);
mi.arguments.push_front(PropertyInfo(Variant::INT, "peer_id"));
mi.name = "rpc_id";
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_id", &Node::_rpc_id_bind, mi);
- mi.name = "rpc_unreliable_id";
- ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_unreliable_id", &Node::_rpc_unreliable_id_bind, mi);
}
- ClassDB::bind_method(D_METHOD("rset", "property", "value"), &Node::rset);
- ClassDB::bind_method(D_METHOD("rset_id", "peer_id", "property", "value"), &Node::rset_id);
- ClassDB::bind_method(D_METHOD("rset_unreliable", "property", "value"), &Node::rset_unreliable);
- ClassDB::bind_method(D_METHOD("rset_unreliable_id", "peer_id", "property", "value"), &Node::rset_unreliable_id);
-
ClassDB::bind_method(D_METHOD("update_configuration_warnings"), &Node::update_configuration_warnings);
BIND_CONSTANT(NOTIFICATION_ENTER_TREE);
@@ -2830,6 +2620,9 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE);
+ BIND_CONSTANT(NOTIFICATION_EDITOR_PRE_SAVE);
+ BIND_CONSTANT(NOTIFICATION_EDITOR_POST_SAVE);
+
BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER);
BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT);
BIND_CONSTANT(NOTIFICATION_WM_WINDOW_FOCUS_IN);
@@ -2872,7 +2665,7 @@ void Node::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_custom_multiplayer", "get_custom_multiplayer");
ADD_GROUP("Process", "process_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,WhenPaused,Always,Disabled"), "set_process_mode", "get_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,When Paused,Always,Disabled"), "set_process_mode", "get_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_priority"), "set_process_priority", "get_process_priority");
ADD_GROUP("Editor Description", "editor_");
diff --git a/scene/main/node.h b/scene/main/node.h
index 6ca2317d9e..e7b36f351b 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -80,11 +80,6 @@ private:
SceneTree::Group *group = nullptr;
};
- struct NetData {
- StringName name;
- MultiplayerAPI::RPCMode mode = MultiplayerAPI::RPCMode::RPC_MODE_DISABLED;
- };
-
struct Data {
String filename;
Ref<SceneState> instance_state;
@@ -116,8 +111,7 @@ private:
Node *process_owner = nullptr;
int network_master = 1; // Server by default.
- Vector<NetData> rpc_methods;
- Vector<NetData> rpc_properties;
+ Vector<MultiplayerAPI::RPCConfig> rpc_methods;
// Variables used to properly sort the node when processing, ignored otherwise.
// TODO: Should move all the stuff below to bits.
@@ -179,9 +173,7 @@ private:
Array _get_groups() const;
Variant _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- Variant _rpc_unreliable_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Variant _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- Variant _rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
friend class SceneTree;
@@ -253,6 +245,10 @@ public:
NOTIFICATION_APPLICATION_FOCUS_IN = MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN,
NOTIFICATION_APPLICATION_FOCUS_OUT = MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT,
NOTIFICATION_TEXT_SERVER_CHANGED = MainLoop::NOTIFICATION_TEXT_SERVER_CHANGED,
+
+ // Editor specific node notifications
+ NOTIFICATION_EDITOR_PRE_SAVE = 9001,
+ NOTIFICATION_EDITOR_POST_SAVE = 9002,
};
/* NODE/TREE */
@@ -425,42 +421,17 @@ public:
int get_network_master() const;
bool is_network_master() const;
- uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode); // config a local method for RPC
- uint16_t rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode); // config a local property for RPC
+ uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
+ Vector<MultiplayerAPI::RPCConfig> get_node_rpc_methods() const;
- void rpc(const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode
- void rpc_unreliable(const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode
- void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode
- void rpc_unreliable_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode
-
- void rset(const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode
- void rset_unreliable(const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode
- void rset_id(int p_peer_id, const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode
- void rset_unreliable_id(int p_peer_id, const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode
-
- void rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);
- void rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value);
+ void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel
+ void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel
+ void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
Ref<MultiplayerAPI> get_multiplayer() const;
Ref<MultiplayerAPI> get_custom_multiplayer() const;
void set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer);
- /// Returns the rpc method ID, otherwise UINT32_MAX
- uint16_t get_node_rpc_method_id(const StringName &p_method) const;
- StringName get_node_rpc_method(const uint16_t p_rpc_method_id) const;
- MultiplayerAPI::RPCMode get_node_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
- MultiplayerAPI::RPCMode get_node_rpc_mode(const StringName &p_method) const;
-
- /// Returns the rpc property ID, otherwise UINT32_MAX
- uint16_t get_node_rset_property_id(const StringName &p_property) const;
- StringName get_node_rset_property(const uint16_t p_rset_property_id) const;
- MultiplayerAPI::RPCMode get_node_rset_mode_by_id(const uint16_t p_rpc_method_id) const;
- MultiplayerAPI::RPCMode get_node_rset_mode(const StringName &p_property) const;
-
- /// Can be used to check if the rpc methods and the rset properties are the
- /// same across the peers.
- String get_rpc_md5() const;
-
Node();
~Node();
};
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 387af3703b..e4ba93feec 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -33,10 +33,10 @@
#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
#include "core/input/input.h"
+#include "core/io/dir_access.h"
#include "core/io/marshalls.h"
#include "core/io/resource_loader.h"
#include "core/object/message_queue.h"
-#include "core/os/dir_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -1267,7 +1267,7 @@ void SceneTree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
ADD_SIGNAL(MethodInfo("tree_changed"));
- ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it cant be removed in run-time
+ ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it can't be removed in run-time
ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index a2f2adb8f8..78c4c14e97 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -48,8 +48,8 @@ class Material;
class Mesh;
class SceneDebugger;
-class SceneTreeTimer : public Reference {
- GDCLASS(SceneTreeTimer, Reference);
+class SceneTreeTimer : public RefCounted {
+ GDCLASS(SceneTreeTimer, RefCounted);
float time_left = 0.0;
bool process_always = true;
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index cb3b2cb392..3d65c12cb7 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -169,7 +169,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
pinfo.type = Variant::TRANSFORM2D;
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- pinfo.type = Variant::TRANSFORM;
+ pinfo.type = Variant::TRANSFORM3D;
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
pinfo.type = Variant::PACKED_INT32_ARRAY;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index b94a818b06..5369792194 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -197,8 +197,8 @@ void Viewport::update_worlds() {
}
void Viewport::_collision_object_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
- Transform object_transform = p_object->get_global_transform();
- Transform camera_transform = p_camera->get_global_transform();
+ Transform3D object_transform = p_object->get_global_transform();
+ Transform3D camera_transform = p_camera->get_global_transform();
ObjectID id = p_object->get_instance_id();
//avoid sending the fake event unnecessarily if nothing really changed in the context
@@ -553,7 +553,7 @@ void Viewport::_notification(int p_what) {
RS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count);
for (int i = 0; i < point_count; i++) {
- Transform point_transform;
+ Transform3D point_transform;
point_transform.origin = points[i];
RS::get_singleton()->multimesh_instance_set_transform(contact_3d_debug_multimesh, i, point_transform);
}
@@ -617,10 +617,10 @@ void Viewport::_process_picking() {
mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
mm->set_global_position(physics_last_mousepos);
mm->set_position(physics_last_mousepos);
- mm->set_alt(physics_last_mouse_state.alt);
- mm->set_shift(physics_last_mouse_state.shift);
- mm->set_control(physics_last_mouse_state.control);
- mm->set_metakey(physics_last_mouse_state.meta);
+ mm->set_alt_pressed(physics_last_mouse_state.alt);
+ mm->set_shift_pressed(physics_last_mouse_state.shift);
+ mm->set_ctrl_pressed(physics_last_mouse_state.control);
+ mm->set_meta_pressed(physics_last_mouse_state.meta);
mm->set_button_mask(physics_last_mouse_state.mouse_mask);
physics_picking_events.push_back(mm);
}
@@ -641,10 +641,10 @@ void Viewport::_process_picking() {
physics_has_last_mousepos = true;
physics_last_mousepos = pos;
- physics_last_mouse_state.alt = mm->get_alt();
- physics_last_mouse_state.shift = mm->get_shift();
- physics_last_mouse_state.control = mm->get_control();
- physics_last_mouse_state.meta = mm->get_metakey();
+ physics_last_mouse_state.alt = mm->is_alt_pressed();
+ physics_last_mouse_state.shift = mm->is_shift_pressed();
+ physics_last_mouse_state.control = mm->is_ctrl_pressed();
+ physics_last_mouse_state.meta = mm->is_meta_pressed();
physics_last_mouse_state.mouse_mask = mm->get_button_mask();
}
@@ -656,10 +656,10 @@ void Viewport::_process_picking() {
physics_has_last_mousepos = true;
physics_last_mousepos = pos;
- physics_last_mouse_state.alt = mb->get_alt();
- physics_last_mouse_state.shift = mb->get_shift();
- physics_last_mouse_state.control = mb->get_control();
- physics_last_mouse_state.meta = mb->get_metakey();
+ physics_last_mouse_state.alt = mb->is_alt_pressed();
+ physics_last_mouse_state.shift = mb->is_shift_pressed();
+ physics_last_mouse_state.control = mb->is_ctrl_pressed();
+ physics_last_mouse_state.meta = mb->is_meta_pressed();
if (mb->is_pressed()) {
physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1));
@@ -676,10 +676,10 @@ void Viewport::_process_picking() {
Ref<InputEventKey> k = ev;
if (k.is_valid()) {
//only for mask
- physics_last_mouse_state.alt = k->get_alt();
- physics_last_mouse_state.shift = k->get_shift();
- physics_last_mouse_state.control = k->get_control();
- physics_last_mouse_state.meta = k->get_metakey();
+ physics_last_mouse_state.alt = k->is_alt_pressed();
+ physics_last_mouse_state.shift = k->is_shift_pressed();
+ physics_last_mouse_state.control = k->is_ctrl_pressed();
+ physics_last_mouse_state.meta = k->is_meta_pressed();
continue;
}
@@ -1341,19 +1341,19 @@ bool Viewport::is_camera_override_enabled() const {
return camera_override;
}
-void Viewport::set_camera_override_transform(const Transform &p_transform) {
+void Viewport::set_camera_override_transform(const Transform3D &p_transform) {
if (camera_override) {
camera_override.transform = p_transform;
RenderingServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform);
}
}
-Transform Viewport::get_camera_override_transform() const {
+Transform3D Viewport::get_camera_override_transform() const {
if (camera_override) {
return camera_override.transform;
}
- return Transform();
+ return Transform3D();
}
void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
@@ -2402,10 +2402,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *from = gui.key_focus ? gui.key_focus : nullptr; //hmm
//keyboard focus
- //if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) {
+ //if (from && p_event->is_pressed() && !p_event->is_alt_pressed() && !p_event->is_meta_pressed() && !p_event->key->is_command_pressed()) {
Ref<InputEventKey> k = p_event;
//need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/right/etc> is handled here when it shouldn't be.
- bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey());
+ bool mods = k.is_valid() && (k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_shift_pressed() || k->is_meta_pressed());
if (from && p_event->is_pressed()) {
Control *next = nullptr;
@@ -2547,6 +2547,8 @@ void Viewport::_gui_remove_control(Control *p_control) {
}
Window *Viewport::get_base_window() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), nullptr);
+
Viewport *v = const_cast<Viewport *>(this);
Window *w = Object::cast_to<Window>(v);
while (!w) {
@@ -3336,6 +3338,7 @@ bool Viewport::is_input_handled() const {
return local_input_handled;
} else {
const Viewport *vp = this;
+ ERR_FAIL_COND_V(!is_inside_tree(), false);
while (true) {
if (Object::cast_to<Window>(vp)) {
break;
@@ -3601,8 +3604,8 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_vertices_to_pixel"), "set_snap_2d_vertices_to_pixel", "is_snap_2d_vertices_to_pixel_enabled");
ADD_GROUP("Rendering", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled,FXAA"), "set_screen_space_aa", "get_screen_space_aa");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"), "set_msaa", "get_msaa");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), "set_screen_space_aa", "get_screen_space_aa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_occlusion_culling"), "set_use_occlusion_culling", "is_using_occlusion_culling");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
@@ -3669,9 +3672,9 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(DEBUG_DRAW_OVERDRAW);
BIND_ENUM_CONSTANT(DEBUG_DRAW_WIREFRAME);
BIND_ENUM_CONSTANT(DEBUG_DRAW_NORMAL_BUFFER);
- BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_ALBEDO);
- BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_LIGHTING);
- BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_EMISSION);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_ALBEDO);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_LIGHTING);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_EMISSION);
BIND_ENUM_CONSTANT(DEBUG_DRAW_SHADOW_ATLAS);
BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS);
BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 2e88e1251d..2d7f5101c2 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -130,9 +130,9 @@ public:
DEBUG_DRAW_OVERDRAW,
DEBUG_DRAW_WIREFRAME,
DEBUG_DRAW_NORMAL_BUFFER,
- DEBUG_DRAW_GI_PROBE_ALBEDO,
- DEBUG_DRAW_GI_PROBE_LIGHTING,
- DEBUG_DRAW_GI_PROBE_EMISSION,
+ DEBUG_DRAW_VOXEL_GI_ALBEDO,
+ DEBUG_DRAW_VOXEL_GI_LIGHTING,
+ DEBUG_DRAW_VOXEL_GI_EMISSION,
DEBUG_DRAW_SHADOW_ATLAS,
DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
DEBUG_DRAW_SCENE_LUMINANCE,
@@ -193,7 +193,7 @@ private:
Set<Listener3D *> listeners;
struct CameraOverrideData {
- Transform transform;
+ Transform3D transform;
enum Projection {
PROJECTION_PERSPECTIVE,
PROJECTION_ORTHOGONAL
@@ -231,7 +231,7 @@ private:
Transform2D global_canvas_transform;
Transform2D stretch_transform;
- Size2i size;
+ Size2i size = Size2i(512, 512);
Size2i size_2d_override;
bool size_allocated = false;
bool use_xr = false;
@@ -254,8 +254,8 @@ private:
List<Ref<InputEvent>> physics_picking_events;
ObjectID physics_object_capture;
ObjectID physics_object_over;
- Transform physics_last_object_transform;
- Transform physics_last_camera_transform;
+ Transform3D physics_last_object_transform;
+ Transform3D physics_last_camera_transform;
ObjectID physics_last_id;
bool physics_has_last_mousepos = false;
Vector2 physics_last_mousepos = Vector2(Math_INF, Math_INF);
@@ -493,8 +493,8 @@ public:
void enable_camera_override(bool p_enable);
bool is_camera_override_enabled() const;
- void set_camera_override_transform(const Transform &p_transform);
- Transform get_camera_override_transform() const;
+ void set_camera_override_transform(const Transform3D &p_transform);
+ Transform3D get_camera_override_transform() const;
void set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
void set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far);
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index bacb0030bb..d793be1869 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -1169,64 +1169,96 @@ Ref<Theme> Window::get_theme() const {
return theme;
}
-Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::get_icons(theme_owner, theme_owner_window, p_name, type);
+void Window::set_theme_custom_type(const StringName &p_theme_type) {
+ theme_custom_type = p_theme_type;
+ Control::_propagate_theme_changed(this, theme_owner, theme_owner_window);
}
-Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::get_styleboxs(theme_owner, theme_owner_window, p_name, type);
+StringName Window::get_theme_custom_type() const {
+ return theme_custom_type;
}
-Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::get_fonts(theme_owner, theme_owner_window, p_name, type);
+void Window::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_custom_type) {
+ if (theme_custom_type != StringName()) {
+ p_list->push_back(theme_custom_type);
+ }
+ Theme::get_type_dependencies(get_class_name(), p_list);
+ } else {
+ Theme::get_type_dependencies(p_theme_type, p_list);
+ }
+}
+
+Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::get_theme_item_in_types<Ref<Texture2D>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
}
-int Window::get_theme_font_size(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::get_font_sizes(theme_owner, theme_owner_window, p_name, type);
+Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::get_theme_item_in_types<Ref<StyleBox>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
}
-Color Window::get_theme_color(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::get_colors(theme_owner, theme_owner_window, p_name, type);
+Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::get_theme_item_in_types<Ref<Font>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
}
-int Window::get_theme_constant(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::get_constants(theme_owner, theme_owner_window, p_name, type);
+int Window::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::get_theme_item_in_types<int>(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
}
-bool Window::has_theme_icon(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::has_icons(theme_owner, theme_owner_window, p_name, type);
+Color Window::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::get_theme_item_in_types<Color>(theme_owner, theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
}
-bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::has_styleboxs(theme_owner, theme_owner_window, p_name, type);
+int Window::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::get_theme_item_in_types<int>(theme_owner, theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
}
-bool Window::has_theme_font(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::has_fonts(theme_owner, theme_owner_window, p_name, type);
+bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
}
-bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::has_font_sizes(theme_owner, theme_owner_window, p_name, type);
+bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
}
-bool Window::has_theme_color(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::has_colors(theme_owner, theme_owner_window, p_name, type);
+bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
}
-bool Window::has_theme_constant(const StringName &p_name, const StringName &p_type) const {
- StringName type = p_type ? p_type : get_class_name();
- return Control::has_constants(theme_owner, theme_owner_window, p_name, type);
+bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
+}
+
+bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
+}
+
+bool Window::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
}
Rect2i Window::get_parent_rect() const {
@@ -1382,19 +1414,22 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme);
ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme);
- ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "type"), &Window::get_theme_icon, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "type"), &Window::get_theme_stylebox, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_font", "name", "type"), &Window::get_theme_font, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "type"), &Window::get_theme_font_size, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_color", "name", "type"), &Window::get_theme_color, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "type"), &Window::get_theme_constant, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("set_theme_custom_type", "theme_type"), &Window::set_theme_custom_type);
+ ClassDB::bind_method(D_METHOD("get_theme_custom_type"), &Window::get_theme_custom_type);
+
+ ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "theme_type"), &Window::get_theme_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "theme_type"), &Window::get_theme_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_font", "name", "theme_type"), &Window::get_theme_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "theme_type"), &Window::get_theme_font_size, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_color", "name", "theme_type"), &Window::get_theme_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "theme_type"), &Window::get_theme_constant, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "type"), &Window::has_theme_icon, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "type"), &Window::has_theme_stylebox, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_font", "name", "type"), &Window::has_theme_font, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "type"), &Window::has_theme_font_size, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_color", "name", "type"), &Window::has_theme_color, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "type"), &Window::has_theme_constant, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "theme_type"), &Window::has_theme_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "theme_type"), &Window::has_theme_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_font", "name", "theme_type"), &Window::has_theme_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "theme_type"), &Window::has_theme_font_size, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_color", "name", "theme_type"), &Window::has_theme_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "theme_type"), &Window::has_theme_constant, DEFVAL(""));
ClassDB::bind_method(D_METHOD("set_layout_direction", "direction"), &Window::set_layout_direction);
ClassDB::bind_method(D_METHOD("get_layout_direction"), &Window::get_layout_direction);
@@ -1409,7 +1444,7 @@ void Window::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,FullScreen"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_screen"), "set_current_screen", "get_current_screen");
ADD_GROUP("Flags", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
@@ -1426,10 +1461,11 @@ void Window::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "max_size"), "set_max_size", "get_max_size");
ADD_GROUP("Content Scale", "content_scale_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,CanvasItems,Viewport"), "set_content_scale_mode", "get_content_scale_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,KeepWidth,KeepHeight,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
- ADD_GROUP("Theme", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Canvas Items,Viewport"), "set_content_scale_mode", "get_content_scale_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,Keep Width,Keep Height,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
+ ADD_GROUP("Theme", "theme_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type");
ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
diff --git a/scene/main/window.h b/scene/main/window.h
index 38846ed00e..494c386606 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -130,6 +130,7 @@ private:
Ref<Theme> theme;
Control *theme_owner = nullptr;
Window *theme_owner_window = nullptr;
+ StringName theme_custom_type;
Viewport *embedder = nullptr;
@@ -241,6 +242,10 @@ public:
void set_theme(const Ref<Theme> &p_theme);
Ref<Theme> get_theme() const;
+ void set_theme_custom_type(const StringName &p_theme_type);
+ StringName get_theme_custom_type() const;
+ _FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const;
+
Size2 get_contents_minimum_size() const;
void grab_focus();
@@ -252,19 +257,19 @@ public:
Rect2i get_usable_parent_rect() const;
- Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
- Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
- Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const;
- int get_theme_font_size(const StringName &p_name, const StringName &p_type = StringName()) const;
- Color get_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const;
- int get_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
-
- bool has_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_theme_font_size(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ int get_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ Color get_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ int get_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+
+ bool has_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+ bool has_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
Rect2i get_parent_rect() const;
virtual DisplayServer::WindowID get_window_id() const override;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 5b5eb946f0..332976a18d 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -55,6 +55,7 @@
#include "scene/2d/parallax_background.h"
#include "scene/2d/parallax_layer.h"
#include "scene/2d/path_2d.h"
+#include "scene/2d/physical_bone_2d.h"
#include "scene/2d/physics_body_2d.h"
#include "scene/2d/polygon_2d.h"
#include "scene/2d/position_2d.h"
@@ -65,7 +66,6 @@
#include "scene/2d/tile_map.h"
#include "scene/2d/touch_screen_button.h"
#include "scene/2d/visibility_notifier_2d.h"
-#include "scene/2d/y_sort.h"
#include "scene/animation/animation_blend_space_1d.h"
#include "scene/animation/animation_blend_space_2d.h"
#include "scene/animation/animation_blend_tree.h"
@@ -161,6 +161,15 @@
#include "scene/resources/rectangle_shape_2d.h"
#include "scene/resources/resource_format_text.h"
#include "scene/resources/segment_shape_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+#include "scene/resources/skeleton_modification_2d_ccdik.h"
+#include "scene/resources/skeleton_modification_2d_fabrik.h"
+#include "scene/resources/skeleton_modification_2d_jiggle.h"
+#include "scene/resources/skeleton_modification_2d_lookat.h"
+#include "scene/resources/skeleton_modification_2d_physicalbones.h"
+#include "scene/resources/skeleton_modification_2d_stackholder.h"
+#include "scene/resources/skeleton_modification_2d_twoboneik.h"
+#include "scene/resources/skeleton_modification_stack_2d.h"
#include "scene/resources/sky.h"
#include "scene/resources/sky_material.h"
#include "scene/resources/sphere_shape_3d.h"
@@ -174,33 +183,29 @@
#include "scene/resources/video_stream.h"
#include "scene/resources/visual_shader.h"
#include "scene/resources/visual_shader_nodes.h"
+#include "scene/resources/visual_shader_particle_nodes.h"
#include "scene/resources/visual_shader_sdf_nodes.h"
#include "scene/resources/world_2d.h"
#include "scene/resources/world_3d.h"
#include "scene/resources/world_margin_shape_3d.h"
#include "scene/scene_string_names.h"
-// Needed by animation code, so keep when 3D disabled.
-#include "scene/3d/node_3d.h"
-#include "scene/3d/skeleton_3d.h"
-
#include "scene/main/shader_globals_override.h"
#ifndef _3D_DISABLED
#include "scene/3d/area_3d.h"
#include "scene/3d/audio_stream_player_3d.h"
-#include "scene/3d/baked_lightmap.h"
#include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_polygon_3d.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/cpu_particles_3d.h"
#include "scene/3d/decal.h"
-#include "scene/3d/gi_probe.h"
#include "scene/3d/gpu_particles_3d.h"
#include "scene/3d/gpu_particles_collision_3d.h"
#include "scene/3d/immediate_geometry_3d.h"
#include "scene/3d/light_3d.h"
+#include "scene/3d/lightmap_gi.h"
#include "scene/3d/lightmap_probe.h"
#include "scene/3d/listener_3d.h"
#include "scene/3d/mesh_instance_3d.h"
@@ -208,6 +213,7 @@
#include "scene/3d/navigation_agent_3d.h"
#include "scene/3d/navigation_obstacle_3d.h"
#include "scene/3d/navigation_region_3d.h"
+#include "scene/3d/node_3d.h"
#include "scene/3d/occluder_instance_3d.h"
#include "scene/3d/path_3d.h"
#include "scene/3d/physics_body_3d.h"
@@ -217,12 +223,14 @@
#include "scene/3d/ray_cast_3d.h"
#include "scene/3d/reflection_probe.h"
#include "scene/3d/remote_transform_3d.h"
+#include "scene/3d/skeleton_3d.h"
#include "scene/3d/skeleton_ik_3d.h"
#include "scene/3d/soft_body_3d.h"
#include "scene/3d/spring_arm_3d.h"
#include "scene/3d/sprite_3d.h"
#include "scene/3d/vehicle_body_3d.h"
#include "scene/3d/visibility_notifier_3d.h"
+#include "scene/3d/voxel_gi.h"
#include "scene/3d/world_environment.h"
#include "scene/3d/xr_nodes.h"
#include "scene/resources/environment.h"
@@ -395,14 +403,7 @@ void register_scene_types() {
AcceptDialog::set_swap_cancel_ok(swap_cancel_ok);
#endif
- /* REGISTER 3D */
-
- // Needed even with _3D_DISABLED as used in animation code.
- ClassDB::register_class<Node3D>();
- ClassDB::register_virtual_class<Node3DGizmo>();
- ClassDB::register_class<Skin>();
- ClassDB::register_virtual_class<SkinReference>();
- ClassDB::register_class<Skeleton3D>();
+ /* REGISTER ANIMATION */
ClassDB::register_class<AnimationPlayer>();
ClassDB::register_class<Tween>();
@@ -432,7 +433,14 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
+ /* REGISTER 3D */
+
#ifndef _3D_DISABLED
+ ClassDB::register_class<Node3D>();
+ ClassDB::register_virtual_class<Node3DGizmo>();
+ ClassDB::register_class<Skin>();
+ ClassDB::register_virtual_class<SkinReference>();
+ ClassDB::register_class<Skeleton3D>();
ClassDB::register_virtual_class<VisualInstance3D>();
ClassDB::register_virtual_class<GeometryInstance3D>();
ClassDB::register_class<Camera3D>();
@@ -455,10 +463,10 @@ void register_scene_types() {
ClassDB::register_class<SpotLight3D>();
ClassDB::register_class<ReflectionProbe>();
ClassDB::register_class<Decal>();
- ClassDB::register_class<GIProbe>();
- ClassDB::register_class<GIProbeData>();
- ClassDB::register_class<BakedLightmap>();
- ClassDB::register_class<BakedLightmapData>();
+ ClassDB::register_class<VoxelGI>();
+ ClassDB::register_class<VoxelGIData>();
+ ClassDB::register_class<LightmapGI>();
+ ClassDB::register_class<LightmapGIData>();
ClassDB::register_class<LightmapProbe>();
ClassDB::register_virtual_class<Lightmapper>();
ClassDB::register_class<GPUParticles3D>();
@@ -484,7 +492,7 @@ void register_scene_types() {
ClassDB::register_class<StaticBody3D>();
ClassDB::register_class<RigidBody3D>();
ClassDB::register_class<KinematicCollision3D>();
- ClassDB::register_class<KinematicBody3D>();
+ ClassDB::register_class<CharacterBody3D>();
ClassDB::register_class<SpringArm3D>();
ClassDB::register_class<PhysicalBone3D>();
@@ -553,6 +561,7 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeVectorFunc>();
ClassDB::register_class<VisualShaderNodeColorFunc>();
ClassDB::register_class<VisualShaderNodeTransformFunc>();
+ ClassDB::register_class<VisualShaderNodeUVFunc>();
ClassDB::register_class<VisualShaderNodeDotProduct>();
ClassDB::register_class<VisualShaderNodeVectorLen>();
ClassDB::register_class<VisualShaderNodeDeterminant>();
@@ -597,6 +606,7 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeIs>();
ClassDB::register_class<VisualShaderNodeCompare>();
ClassDB::register_class<VisualShaderNodeMultiplyAdd>();
+ ClassDB::register_class<VisualShaderNodeBillboard>();
ClassDB::register_class<VisualShaderNodeSDFToScreenUV>();
ClassDB::register_class<VisualShaderNodeScreenUVToSDF>();
@@ -604,6 +614,17 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeTextureSDFNormal>();
ClassDB::register_class<VisualShaderNodeSDFRaymarch>();
+ ClassDB::register_class<VisualShaderNodeParticleOutput>();
+ ClassDB::register_virtual_class<VisualShaderNodeParticleEmitter>();
+ ClassDB::register_class<VisualShaderNodeParticleSphereEmitter>();
+ ClassDB::register_class<VisualShaderNodeParticleBoxEmitter>();
+ ClassDB::register_class<VisualShaderNodeParticleRingEmitter>();
+ ClassDB::register_class<VisualShaderNodeParticleMultiplyByAxisAngle>();
+ ClassDB::register_class<VisualShaderNodeParticleConeVelocity>();
+ ClassDB::register_class<VisualShaderNodeParticleRandomness>();
+ ClassDB::register_class<VisualShaderNodeParticleAccelerator>();
+ ClassDB::register_class<VisualShaderNodeParticleEmit>();
+
ClassDB::register_class<ShaderMaterial>();
ClassDB::register_virtual_class<CanvasItem>();
ClassDB::register_class<CanvasTexture>();
@@ -628,7 +649,7 @@ void register_scene_types() {
ClassDB::register_virtual_class<PhysicsBody2D>();
ClassDB::register_class<StaticBody2D>();
ClassDB::register_class<RigidBody2D>();
- ClassDB::register_class<KinematicBody2D>();
+ ClassDB::register_class<CharacterBody2D>();
ClassDB::register_class<KinematicCollision2D>();
ClassDB::register_class<Area2D>();
ClassDB::register_class<CollisionShape2D>();
@@ -644,7 +665,6 @@ void register_scene_types() {
ClassDB::register_class<DirectionalLight2D>();
ClassDB::register_class<LightOccluder2D>();
ClassDB::register_class<OccluderPolygon2D>();
- ClassDB::register_class<YSort>();
ClassDB::register_class<BackBufferCopy>();
OS::get_singleton()->yield(); //may take time to init
@@ -657,6 +677,7 @@ void register_scene_types() {
ClassDB::register_class<TileSet>();
ClassDB::register_virtual_class<TileSetSource>();
ClassDB::register_class<TileSetAtlasSource>();
+ ClassDB::register_class<TileSetScenesCollectionSource>();
ClassDB::register_class<TileData>();
ClassDB::register_class<TileMap>();
ClassDB::register_class<ParallaxBackground>();
@@ -664,6 +685,18 @@ void register_scene_types() {
ClassDB::register_class<TouchScreenButton>();
ClassDB::register_class<RemoteTransform2D>();
+ ClassDB::register_class<SkeletonModificationStack2D>();
+ ClassDB::register_class<SkeletonModification2D>();
+ ClassDB::register_class<SkeletonModification2DLookAt>();
+ ClassDB::register_class<SkeletonModification2DCCDIK>();
+ ClassDB::register_class<SkeletonModification2DFABRIK>();
+ ClassDB::register_class<SkeletonModification2DJiggle>();
+ ClassDB::register_class<SkeletonModification2DTwoBoneIK>();
+ ClassDB::register_class<SkeletonModification2DStackHolder>();
+
+ ClassDB::register_class<PhysicalBone2D>();
+ ClassDB::register_class<SkeletonModification2DPhysicalBones>();
+
OS::get_singleton()->yield(); //may take time to init
/* REGISTER RESOURCES */
@@ -820,6 +853,11 @@ void register_scene_types() {
ClassDB::add_compatibility_class("ToolButton", "Button");
ClassDB::add_compatibility_class("Navigation3D", "Node3D");
ClassDB::add_compatibility_class("Navigation2D", "Node2D");
+ ClassDB::add_compatibility_class("YSort", "Node2D");
+ ClassDB::add_compatibility_class("GIProbe", "VoxelGI");
+ ClassDB::add_compatibility_class("GIProbeData", "VoxelGIData");
+ ClassDB::add_compatibility_class("BakedLightmap", "LightmapGI");
+ ClassDB::add_compatibility_class("BakedLightmapData", "LightmapGIData");
// Renamed in 4.0.
// Keep alphabetical ordering to easily locate classes and avoid duplicates.
@@ -865,7 +903,8 @@ void register_scene_types() {
ClassDB::add_compatibility_class("HingeJoint", "HingeJoint3D");
ClassDB::add_compatibility_class("ImmediateGeometry", "ImmediateGeometry3D");
ClassDB::add_compatibility_class("Joint", "Joint3D");
- ClassDB::add_compatibility_class("KinematicBody", "KinematicBody3D");
+ ClassDB::add_compatibility_class("KinematicBody", "CharacterBody3D");
+ ClassDB::add_compatibility_class("KinematicBody2D", "CharacterBody2D");
ClassDB::add_compatibility_class("KinematicCollision", "KinematicCollision3D");
ClassDB::add_compatibility_class("Light", "Light3D");
ClassDB::add_compatibility_class("Listener", "Listener3D");
@@ -979,6 +1018,7 @@ void register_scene_types() {
// Always make the default theme to avoid invalid default font/icon/style in the given theme.
if (RenderingServer::get_singleton()) {
make_default_theme(default_theme_hidpi, font);
+ ColorPicker::init_shaders(); // RenderingServer needs to exist for this to succeed.
}
if (theme_path != String()) {
@@ -1035,5 +1075,6 @@ void unregister_scene_types() {
ParticlesMaterial::finish_shaders();
CanvasItemMaterial::finish_shaders();
+ ColorPicker::finish_shaders();
SceneStringNames::free();
}
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 6f64ac6d04..640ec50eb9 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -43,8 +43,8 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
if (tracks.size() == track && what == "type") {
String type = p_value;
- if (type == "transform") {
- add_track(TYPE_TRANSFORM);
+ if (type == "transform" || type == "transform3d") {
+ add_track(TYPE_TRANSFORM3D);
} else if (type == "value") {
add_track(TYPE_VALUE);
} else if (type == "method") {
@@ -75,7 +75,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
} else if (what == "enabled") {
track_set_enabled(track, p_value);
} else if (what == "keys" || what == "key_values") {
- if (track_get_type(track) == TYPE_TRANSFORM) {
+ if (track_get_type(track) == TYPE_TRANSFORM3D) {
TransformTrack *tt = static_cast<TransformTrack *>(tracks[track]);
Vector<float> values = p_value;
int vcount = values.size();
@@ -318,7 +318,7 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
ERR_FAIL_INDEX_V(track, tracks.size(), false);
if (what == "type") {
switch (track_get_type(track)) {
- case TYPE_TRANSFORM:
+ case TYPE_TRANSFORM3D:
r_ret = "transform";
break;
case TYPE_VALUE:
@@ -351,7 +351,7 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
} else if (what == "enabled") {
r_ret = track_is_enabled(track);
} else if (what == "keys") {
- if (track_get_type(track) == TYPE_TRANSFORM) {
+ if (track_get_type(track) == TYPE_TRANSFORM3D) {
Vector<float> keys;
int kk = track_get_key_count(track);
keys.resize(kk * 12);
@@ -361,7 +361,7 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
int idx = 0;
for (int i = 0; i < track_get_key_count(track); i++) {
Vector3 loc;
- Quat rot;
+ Quaternion rot;
Vector3 scale;
transform_track_get_key(track, i, &loc, &rot, &scale);
@@ -590,7 +590,7 @@ int Animation::add_track(TrackType p_type, int p_at_pos) {
}
switch (p_type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = memnew(TransformTrack);
tracks.insert(p_at_pos, tt);
} break;
@@ -628,7 +628,7 @@ void Animation::remove_track(int p_track) {
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
_clear(tt->transforms);
@@ -671,7 +671,7 @@ int Animation::get_track_count() const {
}
Animation::TrackType Animation::track_get_type(int p_track) const {
- ERR_FAIL_INDEX_V(p_track, tracks.size(), TYPE_TRANSFORM);
+ ERR_FAIL_INDEX_V(p_track, tracks.size(), TYPE_TRANSFORM3D);
return tracks[p_track]->type;
}
@@ -773,12 +773,12 @@ void Animation::_clear(T &p_keys) {
p_keys.clear();
}
-Error Animation::transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const {
+Error Animation::transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
TransformTrack *tt = static_cast<TransformTrack *>(t);
- ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM3D, ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_key, tt->transforms.size(), ERR_INVALID_PARAMETER);
if (r_loc) {
@@ -794,10 +794,10 @@ Error Animation::transform_track_get_key(int p_track, int p_key, Vector3 *r_loc,
return OK;
}
-int Animation::transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quat &p_rot, const Vector3 &p_scale) {
+int Animation::transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quaternion &p_rot, const Vector3 &p_scale) {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
- ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, -1);
+ ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM3D, -1);
TransformTrack *tt = static_cast<TransformTrack *>(t);
@@ -823,7 +823,7 @@ void Animation::track_remove_key(int p_track, int p_idx) {
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_idx, tt->transforms.size());
tt->transforms.remove(p_idx);
@@ -869,7 +869,7 @@ int Animation::track_find_key(int p_track, float p_time, bool p_exact) const {
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
int k = _find(tt->transforms, p_time);
if (k < 0 || k >= tt->transforms.size()) {
@@ -951,14 +951,14 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
Dictionary d = p_key;
Vector3 loc;
if (d.has("location")) {
loc = d["location"];
}
- Quat rot;
+ Quaternion rot;
if (d.has("rotation")) {
rot = d["rotation"];
}
@@ -1053,7 +1053,7 @@ int Animation::track_get_key_count(int p_track) const {
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
return tt->transforms.size();
} break;
@@ -1088,7 +1088,7 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const {
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), Variant());
@@ -1156,7 +1156,7 @@ float Animation::track_get_key_time(int p_track, int p_key_idx) const {
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), -1);
return tt->transforms[p_key_idx].time;
@@ -1201,7 +1201,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) {
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_key_idx, tt->transforms.size());
TKey<TransformKey> key = tt->transforms[p_key_idx];
@@ -1265,7 +1265,7 @@ float Animation::track_get_key_transition(int p_track, int p_key_idx) const {
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), -1);
return tt->transforms[p_key_idx].transition;
@@ -1301,7 +1301,7 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_key_idx, tt->transforms.size());
@@ -1384,7 +1384,7 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_tra
Track *t = tracks[p_track];
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_key_idx, tt->transforms.size());
tt->transforms.write[p_key_idx].transition = p_transition;
@@ -1462,7 +1462,7 @@ Vector3 Animation::_interpolate(const Vector3 &p_a, const Vector3 &p_b, float p_
return p_a.lerp(p_b, p_c);
}
-Quat Animation::_interpolate(const Quat &p_a, const Quat &p_b, float p_c) const {
+Quaternion Animation::_interpolate(const Quaternion &p_a, const Quaternion &p_b, float p_c) const {
return p_a.slerp(p_b, p_c);
}
@@ -1490,7 +1490,7 @@ Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a
return p_a.cubic_interpolate(p_b, p_pre_a, p_post_b, p_c);
}
-Quat Animation::_cubic_interpolate(const Quat &p_pre_a, const Quat &p_a, const Quat &p_b, const Quat &p_post_b, float p_c) const {
+Quaternion Animation::_cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, float p_c) const {
return p_a.cubic_slerp(p_b, p_pre_a, p_post_b, p_c);
}
@@ -1555,11 +1555,11 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a
return a.cubic_interpolate(b, pa, pb, p_c);
}
- case Variant::QUAT: {
- Quat a = p_a;
- Quat b = p_b;
- Quat pa = p_pre_a;
- Quat pb = p_post_b;
+ case Variant::QUATERNION: {
+ Quaternion a = p_a;
+ Quaternion b = p_b;
+ Quaternion pa = p_pre_a;
+ Quaternion pb = p_post_b;
return a.cubic_slerp(b, pa, pb, p_c);
}
@@ -1728,10 +1728,10 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
// do a barrel roll
}
-Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const {
+Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
- ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM3D, ERR_INVALID_PARAMETER);
TransformTrack *tt = static_cast<TransformTrack *>(t);
@@ -1932,7 +1932,7 @@ void Animation::track_get_key_indices_in_range(int p_track, float p_time, float
// handle loop by splitting
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
const TransformTrack *tt = static_cast<const TransformTrack *>(t);
_track_get_key_indices_in_range(tt->transforms, from_time, length, p_indices);
_track_get_key_indices_in_range(tt->transforms, 0, to_time, p_indices);
@@ -1988,7 +1988,7 @@ void Animation::track_get_key_indices_in_range(int p_track, float p_time, float
}
switch (t->type) {
- case TYPE_TRANSFORM: {
+ case TYPE_TRANSFORM3D: {
const TransformTrack *tt = static_cast<const TransformTrack *>(t);
_track_get_key_indices_in_range(tt->transforms, from_time, to_time, p_indices);
@@ -2681,7 +2681,7 @@ void Animation::_bind_methods() {
ADD_SIGNAL(MethodInfo("tracks_changed"));
BIND_ENUM_CONSTANT(TYPE_VALUE);
- BIND_ENUM_CONSTANT(TYPE_TRANSFORM);
+ BIND_ENUM_CONSTANT(TYPE_TRANSFORM3D);
BIND_ENUM_CONSTANT(TYPE_METHOD);
BIND_ENUM_CONSTANT(TYPE_BEZIER);
BIND_ENUM_CONSTANT(TYPE_AUDIO);
@@ -2751,9 +2751,9 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
{ //rotation
- const Quat &q0 = t0.value.rot;
- const Quat &q1 = t1.value.rot;
- const Quat &q2 = t2.value.rot;
+ const Quaternion &q0 = t0.value.rot;
+ const Quaternion &q1 = t1.value.rot;
+ const Quaternion &q2 = t2.value.rot;
//localize both to rotation from q0
@@ -2763,8 +2763,8 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
}
} else {
- Quat r02 = (q0.inverse() * q2).normalized();
- Quat r01 = (q0.inverse() * q1).normalized();
+ Quaternion r02 = (q0.inverse() * q2).normalized();
+ Quaternion r01 = (q0.inverse() * q1).normalized();
Vector3 v02, v01;
real_t a02, a01;
@@ -2877,7 +2877,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) {
ERR_FAIL_INDEX(p_idx, tracks.size());
- ERR_FAIL_COND(tracks[p_idx]->type != TYPE_TRANSFORM);
+ ERR_FAIL_COND(tracks[p_idx]->type != TYPE_TRANSFORM3D);
TransformTrack *tt = static_cast<TransformTrack *>(tracks[p_idx]);
bool prev_erased = false;
TKey<TransformKey> first_erased;
@@ -2917,7 +2917,7 @@ void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err,
void Animation::optimize(float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) {
for (int i = 0; i < tracks.size(); i++) {
- if (tracks[i]->type == TYPE_TRANSFORM) {
+ if (tracks[i]->type == TYPE_TRANSFORM3D) {
_transform_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle);
}
}
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 66bc71c834..1484007333 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -42,7 +42,7 @@ class Animation : public Resource {
public:
enum TrackType {
TYPE_VALUE, ///< Set a value in a property, can be interpolated.
- TYPE_TRANSFORM, ///< Transform a node or a bone.
+ TYPE_TRANSFORM3D, ///< Transform a node or a bone.
TYPE_METHOD, ///< Call any method on a specific node.
TYPE_BEZIER, ///< Bezier curve
TYPE_AUDIO,
@@ -88,7 +88,7 @@ private:
struct TransformKey {
Vector3 loc;
- Quat rot;
+ Quaternion rot;
Vector3 scale;
};
@@ -97,7 +97,7 @@ private:
struct TransformTrack : public Track {
Vector<TKey<TransformKey>> transforms;
- TransformTrack() { type = TYPE_TRANSFORM; }
+ TransformTrack() { type = TYPE_TRANSFORM3D; }
};
/* PROPERTY VALUE TRACK */
@@ -186,13 +186,13 @@ private:
_FORCE_INLINE_ Animation::TransformKey _interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, float p_c) const;
_FORCE_INLINE_ Vector3 _interpolate(const Vector3 &p_a, const Vector3 &p_b, float p_c) const;
- _FORCE_INLINE_ Quat _interpolate(const Quat &p_a, const Quat &p_b, float p_c) const;
+ _FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, float p_c) const;
_FORCE_INLINE_ Variant _interpolate(const Variant &p_a, const Variant &p_b, float p_c) const;
_FORCE_INLINE_ float _interpolate(const float &p_a, const float &p_b, float p_c) const;
_FORCE_INLINE_ Animation::TransformKey _cubic_interpolate(const Animation::TransformKey &p_pre_a, const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, const Animation::TransformKey &p_post_b, float p_c) const;
_FORCE_INLINE_ Vector3 _cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, float p_c) const;
- _FORCE_INLINE_ Quat _cubic_interpolate(const Quat &p_pre_a, const Quat &p_a, const Quat &p_b, const Quat &p_post_b, float p_c) const;
+ _FORCE_INLINE_ Quaternion _cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, float p_c) const;
_FORCE_INLINE_ Variant _cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, float p_c) const;
_FORCE_INLINE_ float _cubic_interpolate(const float &p_pre_a, const float &p_a, const float &p_b, const float &p_post_b, float p_c) const;
@@ -213,7 +213,7 @@ private:
private:
Array _transform_track_interpolate(int p_track, float p_time) const {
Vector3 loc;
- Quat rot;
+ Quaternion rot;
Vector3 scale;
transform_track_interpolate(p_track, p_time, &loc, &rot, &scale);
Array ret;
@@ -291,8 +291,8 @@ public:
float track_get_key_time(int p_track, int p_key_idx) const;
float track_get_key_transition(int p_track, int p_key_idx) const;
- int transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quat &p_rot = Quat(), const Vector3 &p_scale = Vector3());
- Error transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const;
+ int transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quaternion &p_rot = Quaternion(), const Vector3 &p_scale = Vector3());
+ Error transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const;
void track_set_interpolation_type(int p_track, InterpolationType p_interp);
InterpolationType track_get_interpolation_type(int p_track) const;
@@ -321,7 +321,7 @@ public:
void track_set_interpolation_loop_wrap(int p_track, bool p_enable);
bool track_get_interpolation_loop_wrap(int p_track) const;
- Error transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const;
+ Error transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const;
Variant value_track_interpolate(int p_track, float p_time) const;
void value_track_get_key_indices(int p_track, float p_time, float p_delta, List<int> *p_indices) const;
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index 9a9f019dda..81062feb46 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -30,8 +30,8 @@
#include "audio_stream_sample.h"
+#include "core/io/file_access.h"
#include "core/io/marshalls.h"
-#include "core/os/file_access.h"
void AudioStreamPlaybackSample::start(float p_from_pos) {
if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) {
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp
index e9bfac3653..0ffeb8a5bf 100644
--- a/scene/resources/bit_map.cpp
+++ b/scene/resources/bit_map.cpp
@@ -38,7 +38,7 @@ void BitMap::create(const Size2 &p_size) {
width = p_size.width;
height = p_size.height;
- bitmask.resize(((width * height) / 8) + 1);
+ bitmask.resize((((width * height) - 1) / 8) + 1);
memset(bitmask.ptrw(), 0, bitmask.size());
}
diff --git a/scene/resources/convex_polygon_shape_3d.cpp b/scene/resources/convex_polygon_shape_3d.cpp
index 9e030bc077..6b895da606 100644
--- a/scene/resources/convex_polygon_shape_3d.cpp
+++ b/scene/resources/convex_polygon_shape_3d.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "convex_polygon_shape_3d.h"
-#include "core/math/quick_hull.h"
+#include "core/math/convex_hull.h"
#include "servers/physics_server_3d.h"
Vector<Vector3> ConvexPolygonShape3D::get_debug_mesh_lines() const {
@@ -38,7 +38,7 @@ Vector<Vector3> ConvexPolygonShape3D::get_debug_mesh_lines() const {
if (points.size() > 3) {
Vector<Vector3> varr = Variant(points);
Geometry3D::MeshData md;
- Error err = QuickHull::build(varr, md);
+ Error err = ConvexHullComputer::convex_hull(varr, md);
if (err == OK) {
Vector<Vector3> lines;
lines.resize(md.edges.size() * 2);
diff --git a/scene/resources/default_theme/SCsub b/scene/resources/default_theme/SCsub
index fc61250247..0fb6bb2c62 100644
--- a/scene/resources/default_theme/SCsub
+++ b/scene/resources/default_theme/SCsub
@@ -2,4 +2,16 @@
Import("env")
+import os
+import os.path
+from platform_methods import run_in_subprocess
+import default_theme_builders
+
env.add_source_files(env.scene_sources, "*.cpp")
+
+env.Depends("#scene/resources/default_theme/default_font.gen.h", "#thirdparty/fonts/OpenSans_SemiBold.ttf")
+env.CommandNoCache(
+ "#scene/resources/default_theme/default_font.gen.h",
+ "#thirdparty/fonts/OpenSans_SemiBold.ttf",
+ run_in_subprocess(default_theme_builders.make_fonts_header),
+)
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 7c00c6d146..b91a5c0b7f 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -30,15 +30,12 @@
#include "default_theme.h"
-#include "scene/resources/theme.h"
-
#include "core/os/os.h"
-#include "theme_data.h"
-
-#include "font_hidpi.inc"
-#include "font_lodpi.inc"
-
+#include "default_font.gen.h"
+#include "scene/resources/font.h"
+#include "scene/resources/theme.h"
#include "servers/text_server.h"
+#include "theme_data.h"
typedef Map<const void *, Ref<ImageTexture>> TexCacheMap;
@@ -128,38 +125,6 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false,
return texture;
}
-static Ref<FontData> make_font(int p_height, int p_ascent, int p_charcount, const int *p_char_rects, int p_kerning_count, const int *p_kernings, int p_w, int p_h, const unsigned char *p_img) {
- Ref<FontData> font(memnew(FontData));
- font->new_bitmap(p_height, p_ascent, p_height);
-
- Ref<Image> image = memnew(Image(p_img));
- Ref<ImageTexture> tex = memnew(ImageTexture);
- tex->create_from_image(image);
-
- font->bitmap_add_texture(tex);
-
- for (int i = 0; i < p_charcount; i++) {
- const int *c = &p_char_rects[i * 8];
-
- int chr = c[0];
- Rect2 frect;
- frect.position.x = c[1];
- frect.position.y = c[2];
- frect.size.x = c[3];
- frect.size.y = c[4];
- Point2 align(c[6], c[5]);
- int advance = c[7];
-
- font->bitmap_add_char(chr, 0, frect, align, advance);
- }
-
- for (int i = 0; i < p_kerning_count; i++) {
- font->bitmap_add_kerning_pair(p_kernings[i * 3 + 0], p_kernings[i * 3 + 1], p_kernings[i * 3 + 2]);
- }
-
- return font;
-}
-
static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
Ref<StyleBox> style(memnew(StyleBoxEmpty));
@@ -467,7 +432,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("normal", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0));
theme->set_stylebox("focus", "TextEdit", focus);
theme->set_stylebox("read_only", "TextEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4, 0, 0, 0, 0));
- theme->set_stylebox("completion", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0));
theme->set_icon("tab", "TextEdit", make_icon(tab_png));
theme->set_icon("space", "TextEdit", make_icon(space_png));
@@ -476,17 +440,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_font_size("font_size", "TextEdit", -1);
theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0));
- theme->set_color("completion_background_color", "TextEdit", Color(0.17, 0.16, 0.2));
- theme->set_color("completion_selected_color", "TextEdit", Color(0.26, 0.26, 0.27));
- theme->set_color("completion_existing_color", "TextEdit", Color(0.87, 0.87, 0.87, 0.13));
- theme->set_color("completion_scroll_color", "TextEdit", control_font_pressed_color);
- theme->set_color("completion_font_color", "TextEdit", Color(0.67, 0.67, 0.67));
theme->set_color("font_color", "TextEdit", control_font_color);
theme->set_color("font_selected_color", "TextEdit", Color(0, 0, 0));
theme->set_color("font_readonly_color", "TextEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
theme->set_color("font_outline_color", "TextEdit", Color(1, 1, 1));
theme->set_color("selection_color", "TextEdit", control_selection_color);
- theme->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4));
theme->set_color("code_folding_color", "TextEdit", Color(0.8, 0.8, 0.8, 0.8));
theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8));
theme->set_color("caret_color", "TextEdit", control_font_color);
@@ -494,9 +452,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2));
theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15));
- theme->set_constant("completion_lines", "TextEdit", 7);
- theme->set_constant("completion_max_width", "TextEdit", 50);
- theme->set_constant("completion_scroll_width", "TextEdit", 3);
theme->set_constant("line_spacing", "TextEdit", 4 * scale);
theme->set_constant("outline_size", "TextEdit", 0);
@@ -529,7 +484,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_readonly_color", "CodeEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
theme->set_color("font_outline_color", "CodeEdit", Color(1, 1, 1));
theme->set_color("selection_color", "CodeEdit", control_selection_color);
- theme->set_color("mark_color", "CodeEdit", Color(1.0, 0.4, 0.4, 0.4));
theme->set_color("bookmark_color", "CodeEdit", Color(0.5, 0.64, 1, 0.8));
theme->set_color("breakpoint_color", "CodeEdit", Color(0.9, 0.29, 0.3));
theme->set_color("executing_line_color", "CodeEdit", Color(0.98, 0.89, 0.27));
@@ -756,6 +710,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1));
theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2));
theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27));
+ theme->set_color("parent_hl_line_color", "Tree", Color(0.27, 0.27, 0.27));
+ theme->set_color("children_hl_line_color", "Tree", Color(0.27, 0.27, 0.27));
theme->set_color("custom_button_font_highlight", "Tree", control_font_hover_color);
theme->set_constant("hseparation", "Tree", 4 * scale);
@@ -763,6 +719,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("item_margin", "Tree", 12 * scale);
theme->set_constant("button_margin", "Tree", 4 * scale);
theme->set_constant("draw_relationship_lines", "Tree", 0);
+ theme->set_constant("relationship_line_width", "Tree", 1);
+ theme->set_constant("parent_hl_line_width", "Tree", 1);
+ theme->set_constant("children_hl_line_width", "Tree", 1);
+ theme->set_constant("parent_hl_line_margin", "Tree", 0);
theme->set_constant("draw_guides", "Tree", 1);
theme->set_constant("scroll_border", "Tree", 4);
theme->set_constant("scroll_speed", "Tree", 12);
@@ -1024,18 +984,25 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) {
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
- int default_font_size = 14;
+ int default_font_size = 16;
if (p_font.is_valid()) {
+ // Use the custom font defined in the Project Settings.
default_font = p_font;
- } else if (p_hidpi) {
- Ref<FontData> font_data = make_font(_hidpi_font_height, _hidpi_font_ascent, _hidpi_font_charcount, &_hidpi_font_charrects[0][0], _hidpi_font_kerning_pair_count, &_hidpi_font_kerning_pairs[0][0], _hidpi_font_img_width, _hidpi_font_img_height, _hidpi_font_img_data);
- default_font.instance();
- default_font->add_data(font_data);
} else {
- Ref<FontData> font_data = make_font(_lodpi_font_height, _lodpi_font_ascent, _lodpi_font_charcount, &_lodpi_font_charrects[0][0], _lodpi_font_kerning_pair_count, &_lodpi_font_kerning_pairs[0][0], _lodpi_font_img_width, _lodpi_font_img_height, _lodpi_font_img_data);
- default_font.instance();
- default_font->add_data(font_data);
+ // Use the default DynamicFont (separate from the editor font).
+ // The default DynamicFont is chosen to have a small file size since it's
+ // embedded in both editor and export template binaries.
+ Ref<Font> dynamic_font;
+ dynamic_font.instance();
+
+ Ref<FontData> dynamic_font_data;
+ dynamic_font_data.instance();
+ dynamic_font_data->load_memory(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size, "ttf", default_font_size);
+ dynamic_font->add_data(dynamic_font_data);
+
+ default_font = dynamic_font;
}
+
Ref<Font> large_font = default_font;
fill_default_theme(t, default_font, large_font, default_icon, default_style, p_hidpi ? 2.0 : 1.0);
diff --git a/scene/resources/default_theme/default_theme_builders.py b/scene/resources/default_theme/default_theme_builders.py
new file mode 100644
index 0000000000..0455d6d246
--- /dev/null
+++ b/scene/resources/default_theme/default_theme_builders.py
@@ -0,0 +1,40 @@
+"""Functions used to generate source files during build time
+
+All such functions are invoked in a subprocess on Windows to prevent build flakiness.
+
+"""
+import os
+import os.path
+from platform_methods import subprocess_main
+
+
+def make_fonts_header(target, source, env):
+ dst = target[0]
+
+ g = open(dst, "w", encoding="utf-8")
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _DEFAULT_FONTS_H\n")
+ g.write("#define _DEFAULT_FONTS_H\n")
+
+ # Saving uncompressed, since FreeType will reference from memory pointer.
+ for i in range(len(source)):
+ with open(source[i], "rb") as f:
+ buf = f.read()
+
+ name = os.path.splitext(os.path.basename(source[i]))[0]
+
+ g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n")
+ g.write("static const unsigned char _font_" + name + "[] = {\n")
+ for j in range(len(buf)):
+ g.write("\t" + str(buf[j]) + ",\n")
+
+ g.write("};\n")
+
+ g.write("#endif")
+
+ g.close()
+
+
+if __name__ == "__main__":
+ subprocess_main(globals())
diff --git a/scene/resources/default_theme/font_hidpi.inc b/scene/resources/default_theme/font_hidpi.inc
deleted file mode 100644
index 4860149e6b..0000000000
--- a/scene/resources/default_theme/font_hidpi.inc
+++ /dev/null
@@ -1,25463 +0,0 @@
-/* clang-format off */
-static const int _hidpi_font_height=25;
-static const int _hidpi_font_ascent=19;
-static const int _hidpi_font_charcount=191;
-static const int _hidpi_font_charrects[191][8]={
-/* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */
-{192,63,23,16,23,-4,-1,15},
-{224,184,182,10,19,0,1,13},
-{64,98,2,18,19,2,1,21},
-{96,159,234,5,4,0,5,14},
-{160,0,0,0,0,19,0,6},
-{32,0,0,0,0,19,0,6},
-{33,2,249,3,17,2,2,6},
-{193,83,25,16,23,-4,-1,15},
-{225,92,160,10,19,0,1,13},
-{65,163,23,16,17,2,-1,15},
-{161,246,236,3,17,6,2,6},
-{97,142,190,10,13,6,1,13},
-{162,67,214,9,17,2,2,13},
-{98,242,136,11,18,1,2,14},
-{194,103,25,16,23,-4,-1,15},
-{226,106,160,10,19,0,1,13},
-{66,122,146,11,17,2,2,15},
-{34,226,203,8,6,2,1,10},
-{35,189,44,14,17,2,1,16},
-{163,62,166,11,17,2,1,13},
-{195,123,23,16,23,-4,-1,15},
-{227,134,167,10,19,0,1,13},
-{67,209,65,12,17,2,1,14},
-{99,225,186,9,13,6,1,11},
-{228,170,182,10,18,1,1,13},
-{100,227,143,11,18,1,1,14},
-{196,23,23,16,22,-3,-1,15},
-{36,2,179,10,20,1,2,13},
-{68,193,65,12,17,2,2,16},
-{164,176,65,13,12,5,0,13},
-{37,120,2,18,17,2,1,20},
-{69,41,222,9,17,2,2,13},
-{165,98,99,12,17,2,1,13},
-{197,43,23,16,21,-2,-1,15},
-{229,16,179,10,20,-1,1,13},
-{101,189,109,11,13,6,1,13},
-{38,183,23,16,17,2,1,17},
-{70,54,222,9,17,2,2,12},
-{198,75,2,19,17,2,-1,20},
-{102,202,212,8,18,1,1,8},
-{166,44,268,2,24,1,6,13},
-{230,142,2,18,13,6,1,20},
-{71,2,71,14,17,2,1,17},
-{167,176,160,10,18,1,0,12},
-{199,146,94,12,23,2,1,14},
-{103,159,67,13,19,6,0,13},
-{231,212,189,9,19,6,1,11},
-{39,30,271,3,6,2,1,5},
-{72,130,99,12,17,2,2,17},
-{104,162,160,10,18,1,2,14},
-{200,238,186,9,23,-4,2,13},
-{40,46,243,7,21,2,1,7},
-{232,2,156,11,19,0,1,13},
-{168,68,235,7,3,1,4,14},
-{73,106,209,8,17,2,0,9},
-{169,230,2,17,17,2,1,20},
-{105,222,232,4,18,1,1,6},
-{201,28,222,9,23,-4,2,13},
-{41,130,238,6,21,2,0,7},
-{233,197,126,11,19,0,1,13},
-{202,93,209,9,23,-4,2,13},
-{74,13,225,7,22,2,-2,7},
-{234,167,137,11,19,0,1,13},
-{42,82,120,12,11,1,0,13},
-{170,100,236,6,8,2,1,8},
-{106,110,237,6,24,1,-1,6},
-{171,144,121,11,10,8,0,12},
-{43,2,119,12,12,5,1,13},
-{203,80,209,9,22,-3,2,13},
-{107,32,177,11,18,1,2,12},
-{235,77,166,11,18,1,1,13},
-{75,74,77,13,17,2,2,14},
-{44,230,213,4,6,16,1,6},
-{172,204,109,11,7,10,1,13},
-{236,204,234,5,19,0,0,6},
-{204,130,211,8,23,-4,0,9},
-{108,23,271,3,18,1,2,6},
-{76,86,188,10,17,2,2,12},
-{173,140,238,6,2,12,1,8},
-{45,120,237,6,2,12,1,8},
-{109,208,2,18,13,6,2,22},
-{205,178,205,8,23,-4,0,9},
-{237,213,234,5,19,0,2,6},
-{77,143,19,16,17,2,2,21},
-{46,9,251,3,3,16,2,6},
-{110,100,183,10,13,6,2,14},
-{206,154,207,8,23,-4,0,9},
-{238,238,213,8,19,0,-1,6},
-{174,2,23,17,17,2,1,20},
-{78,91,78,13,17,2,2,18},
-{175,18,125,12,2,-1,0,12},
-{111,162,90,12,13,6,1,14},
-{207,118,211,8,22,-3,0,9},
-{239,24,249,7,18,1,0,6},
-{79,203,23,15,17,2,1,18},
-{47,120,167,10,17,2,-1,9},
-{176,166,207,8,8,2,1,10},
-{112,212,143,11,19,6,2,14},
-{240,18,103,12,18,1,1,14},
-{208,171,44,14,17,2,0,16},
-{80,128,190,10,17,2,2,14},
-{48,234,115,11,17,2,1,13},
-{177,66,127,12,14,5,1,13},
-{113,182,126,11,19,6,1,14},
-{241,30,199,10,19,0,2,14},
-{81,97,52,15,22,2,1,18},
-{209,142,67,13,23,-4,2,18},
-{49,57,243,7,17,2,2,13},
-{178,190,206,8,10,2,0,8},
-{114,142,207,8,13,6,2,10},
-{242,242,87,12,19,0,1,14},
-{210,59,50,15,23,-4,1,18},
-{82,82,99,12,17,2,2,14},
-{50,2,135,11,17,2,1,13},
-{179,35,249,7,10,2,0,8},
-{115,72,188,10,13,6,0,11},
-{243,226,92,12,19,0,1,14},
-{211,40,49,15,23,-4,1,18},
-{83,129,125,11,17,2,0,13},
-{51,17,135,11,17,2,1,13},
-{180,168,219,5,4,0,5,14},
-{116,214,212,8,16,3,0,8},
-{244,194,86,12,19,0,1,14},
-{212,21,49,15,23,-4,1,18},
-{84,66,106,12,17,2,0,13},
-{52,125,78,13,17,2,0,13},
-{53,32,156,11,17,2,1,13},
-{85,50,106,12,17,2,2,17},
-{181,204,166,10,19,6,2,14},
-{117,198,189,10,13,6,2,14},
-{245,178,86,12,19,0,1,14},
-{213,2,44,15,23,-4,1,18},
-{54,47,156,11,17,2,1,13},
-{86,222,23,15,17,2,-1,14},
-{246,241,65,12,18,1,1,14},
-{214,116,52,15,22,-3,1,18},
-{182,34,131,12,21,1,1,16},
-{118,135,50,14,13,6,-1,12},
-{55,62,145,11,17,2,1,13},
-{87,2,2,22,17,2,-1,21},
-{119,28,2,20,13,6,-1,18},
-{215,114,125,11,11,5,1,13},
-{247,210,92,12,10,6,0,13},
-{183,16,251,3,3,9,2,6},
-{56,77,145,11,17,2,1,13},
-{88,225,44,14,17,2,-1,13},
-{216,78,52,15,19,1,1,18},
-{248,98,120,12,15,5,1,14},
-{120,50,127,12,13,6,0,12},
-{184,150,234,5,6,19,0,5},
-{89,207,44,14,17,2,-1,13},
-{121,153,44,14,19,6,-1,12},
-{217,225,65,12,23,-4,2,17},
-{249,44,199,10,19,0,2,14},
-{57,92,139,11,17,2,1,13},
-{185,177,232,5,10,2,0,8},
-{218,2,92,12,23,-4,2,17},
-{250,156,184,10,19,0,2,14},
-{90,232,165,10,17,2,1,13},
-{122,148,167,10,13,6,1,11},
-{58,37,263,3,13,6,2,6},
-{186,90,236,6,8,2,1,8},
-{219,34,104,12,23,-4,2,17},
-{123,2,224,7,21,2,1,9},
-{91,186,232,5,21,2,2,7},
-{251,58,191,10,19,0,2,14},
-{59,238,236,4,16,6,1,6},
-{187,47,177,11,10,8,1,12},
-{188,164,2,18,17,2,0,18},
-{252,190,149,10,18,1,2,14},
-{124,50,268,2,24,1,6,13},
-{220,114,99,12,22,-3,2,17},
-{92,137,146,11,17,2,-1,9},
-{60,159,121,11,12,5,1,13},
-{189,186,2,18,17,2,0,18},
-{253,56,77,14,25,0,-1,12},
-{221,20,76,14,23,-4,-1,13},
-{125,79,235,7,21,2,1,9},
-{93,195,234,5,21,2,0,7},
-{61,152,137,11,6,8,1,13},
-{190,52,2,19,17,2,0,18},
-{222,114,188,10,17,2,2,14},
-{254,219,115,11,24,1,2,14},
-{62,174,109,11,12,5,1,13},
-{94,108,78,13,11,2,0,13},
-{126,107,140,11,5,8,1,13},
-{223,17,156,11,18,1,2,14},
-{191,15,203,9,18,6,0,10},
-{255,38,76,14,24,1,-1,12},
-{63,2,203,9,17,2,0,10},
-{95,218,166,10,2,21,0,10},
-};
-static const int _hidpi_font_kerning_pair_count=0;
-static const int _hidpi_font_kerning_pairs[1][3]={
-{0,0,0}
-};
-static const int _hidpi_font_img_width=256;
-static const int _hidpi_font_img_height=512;
-static const int _hidpi_font_img_data_size=25255;
-static const unsigned char _hidpi_font_img_data[25255]={
-137,
-80,
-78,
-71,
-13,
-10,
-26,
-10,
-0,
-0,
-0,
-13,
-73,
-72,
-68,
-82,
-0,
-0,
-1,
-0,
-0,
-0,
-2,
-0,
-8,
-6,
-0,
-0,
-0,
-109,
-154,
-178,
-251,
-0,
-0,
-32,
-0,
-73,
-68,
-65,
-84,
-120,
-156,
-236,
-157,
-119,
-184,
-38,
-53,
-245,
-199,
-51,
-84,
-165,
-55,
-1,
-21,
-16,
-41,
-34,
-42,
-130,
-98,
-23,
-1,
-21,
-20,
-84,
-108,
-40,
-138,
-138,
-10,
-34,
-40,
-86,
-148,
-159,
-216,
-11,
-34,
-138,
-130,
-162,
-40,
-32,
-160,
-128,
-160,
-2,
-162,
-32,
-162,
-34,
-34,
-29,
-145,
-142,
-235,
-210,
-219,
-210,
-151,
-14,
-219,
-251,
-231,
-247,
-199,
-57,
-97,
-114,
-231,
-205,
-204,
-100,
-102,
-50,
-239,
-189,
-119,
-111,
-190,
-207,
-179,
-207,
-221,
-55,
-57,
-57,
-147,
-153,
-73,
-206,
-36,
-39,
-167,
-24,
-147,
-144,
-144,
-144,
-144,
-144,
-144,
-48,
-129,
-1,
-172,
-75,
-142,
-45,
-74,
-104,
-158,
-231,
-208,
-188,
-176,
-132,
-230,
-85,
-14,
-205,
-58,
-158,
-250,
-245,
-156,
-250,
-103,
-121,
-234,
-95,
-237,
-212,
-239,
-225,
-169,
-95,
-25,
-88,
-160,
-245,
-235,
-122,
-234,
-55,
-5,
-78,
-0,
-238,
-5,
-230,
-2,
-83,
-128,
-95,
-2,
-107,
-149,
-244,
-119,
-105,
-224,
-22,
-224,
-65,
-96,
-37,
-31,
-77,
-8,
-128,
-143,
-211,
-0,
-129,
-60,
-215,
-1,
-190,
-8,
-156,
-15,
-220,
-13,
-204,
-1,
-30,
-7,
-38,
-1,
-63,
-3,
-182,
-12,
-228,
-243,
-33,
-224,
-102,
-109,
-255,
-63,
-224,
-109,
-21,
-180,
-235,
-3,
-179,
-244,
-249,
-173,
-88,
-195,
-119,
-109,
-224,
-43,
-192,
-101,
-192,
-19,
-250,
-188,
-239,
-5,
-126,
-3,
-108,
-160,
-52,
-27,
-0,
-191,
-7,
-30,
-86,
-190,
-215,
-0,
-159,
-0,
-150,
-168,
-224,
-187,
-42,
-112,
-172,
-62,
-170,
-211,
-42,
-232,
-26,
-189,
-187,
-62,
-248,
-42,
-175,
-235,
-244,
-255,
-239,
-211,
-103,
-49,
-67,
-223,
-211,
-133,
-246,
-89,
-3,
-75,
-0,
-159,
-5,
-174,
-211,
-231,
-240,
-36,
-240,
-79,
-224,
-117,
-117,
-253,
-214,
-246,
-43,
-105,
-251,
-127,
-1,
-143,
-0,
-243,
-245,
-239,
-185,
-192,
-103,
-234,
-222,
-85,
-16,
-128,
-27,
-244,
-134,
-246,
-45,
-169,
-255,
-164,
-51,
-134,
-247,
-41,
-161,
-249,
-138,
-214,
-79,
-174,
-184,
-206,
-205,
-74,
-243,
-126,
-79,
-221,
-33,
-206,
-53,
-78,
-247,
-212,
-239,
-164,
-117,
-55,
-150,
-240,
-254,
-43,
-48,
-93,
-7,
-225,
-87,
-129,
-95,
-1,
-139,
-128,
-127,
-149,
-208,
-127,
-65,
-249,
-125,
-188,
-172,
-191,
-33,
-0,
-174,
-5,
-22,
-2,
-151,
-56,
-253,
-191,
-86,
-127,
-15,
-252,
-171,
-225,
-245,
-52,
-224,
-251,
-192,
-108,
-229,
-115,
-43,
-112,
-6,
-112,
-52,
-112,
-18,
-112,
-149,
-94,
-11,
-224,
-52,
-96,
-149,
-10,
-94,
-175,
-215,
-251,
-183,
-130,
-240,
-126,
-29,
-60,
-94,
-225,
-1,
-156,
-165,
-124,
-119,
-14,
-184,
-231,
-43,
-149,
-118,
-1,
-112,
-35,
-112,
-5,
-50,
-209,
-1,
-30,
-211,
-107,
-63,
-166,
-191,
-239,
-214,
-241,
-101,
-251,
-125,
-98,
-9,
-207,
-247,
-2,
-83,
-129,
-187,
-128,
-153,
-84,
-79,
-212,
-224,
-119,
-215,
-35,
-95,
-144,
-9,
-253,
-85,
-253,
-255,
-125,
-250,
-126,
-158,
-212,
-223,
-139,
-128,
-157,
-245,
-61,
-161,
-215,
-191,
-70,
-251,
-128,
-190,
-139,
-87,
-215,
-92,
-99,
-39,
-224,
-81,
-100,
-194,
-31,
-13,
-236,
-14,
-188,
-93,
-255,
-30,
-173,
-229,
-143,
-80,
-33,
-216,
-131,
-0,
-28,
-166,
-157,
-250,
-75,
-73,
-253,
-105,
-136,
-148,
-159,
-11,
-156,
-82,
-66,
-115,
-142,
-242,
-56,
-164,
-226,
-58,
-63,
-87,
-154,
-35,
-60,
-117,
-183,
-235,
-96,
-189,
-18,
-145,
-164,
-79,
-43,
-212,
-31,
-170,
-109,
-127,
-90,
-194,
-123,
-85,
-96,
-181,
-66,
-217,
-121,
-192,
-116,
-15,
-237,
-26,
-136,
-164,
-254,
-47,
-21,
-95,
-164,
-58,
-0,
-175,
-209,
-62,
-253,
-85,
-127,
-91,
-120,
-87,
-82,
-53,
-188,
-214,
-0,
-254,
-173,
-237,
-79,
-1,
-94,
-80,
-66,
-183,
-46,
-240,
-107,
-165,
-187,
-17,
-88,
-181,
-132,
-238,
-79,
-74,
-179,
-137,
-254,
-126,
-169,
-254,
-62,
-201,
-67,
-251,
-110,
-247,
-62,
-2,
-250,
-250,
-38,
-224,
-115,
-238,
-243,
-70,
-190,
-158,
-71,
-58,
-131,
-127,
-33,
-176,
-139,
-83,
-255,
-34,
-100,
-34,
-2,
-188,
-215,
-195,
-243,
-64,
-224,
-183,
-192,
-234,
-84,
-76,
-212,
-166,
-239,
-174,
-71,
-190,
-22,
-243,
-129,
-15,
-58,
-229,
-203,
-33,
-31,
-35,
-128,
-121,
-200,
-234,
-235,
-237,
-133,
-235,
-92,
-163,
-245,
-103,
-84,
-240,
-255,
-178,
-62,
-195,
-31,
-0,
-43,
-148,
-208,
-172,
-0,
-28,
-172,
-116,
-95,
-174,
-235,
-115,
-213,
-205,
-236,
-168,
-29,
-122,
-18,
-88,
-178,
-80,
-183,
-4,
-34,
-133,
-174,
-212,
-127,
-15,
-120,
-218,
-47,
-67,
-46,
-217,
-182,
-171,
-184,
-206,
-59,
-148,
-102,
-114,
-161,
-124,
-11,
-45,
-63,
-94,
-111,
-24,
-224,
-45,
-5,
-154,
-171,
-181,
-188,
-86,
-218,
-33,
-95,
-210,
-215,
-35,
-203,
-211,
-223,
-122,
-234,
-127,
-161,
-188,
-222,
-80,
-199,
-171,
-230,
-58,
-191,
-85,
-62,
-239,
-208,
-223,
-22,
-141,
-4,
-0,
-176,
-20,
-178,
-66,
-152,
-15,
-236,
-22,
-216,
-102,
-95,
-189,
-214,
-159,
-75,
-234,
-239,
-5,
-110,
-45,
-148,
-221,
-9,
-220,
-89,
-40,
-91,
-1,
-184,
-7,
-249,
-154,
-61,
-183,
-73,
-191,
-61,
-215,
-92,
-203,
-121,
-6,
-199,
-121,
-234,
-247,
-215,
-186,
-127,
-212,
-240,
-129,
-242,
-137,
-218,
-250,
-221,
-197,
-228,
-235,
-220,
-231,
-209,
-158,
-186,
-45,
-156,
-250,
-67,
-61,
-245,
-239,
-209,
-186,
-7,
-75,
-120,
-239,
-132,
-76,
-234,
-93,
-245,
-247,
-18,
-192,
-222,
-200,
-252,
-155,
-137,
-204,
-199,
-75,
-128,
-79,
-107,
-253,
-110,
-74,
-223,
-110,
-37,
-128,
-72,
-173,
-57,
-218,
-169,
-87,
-20,
-234,
-236,
-151,
-227,
-112,
-231,
-33,
-109,
-82,
-160,
-217,
-74,
-203,
-103,
-0,
-203,
-86,
-92,
-103,
-37,
-29,
-228,
-139,
-128,
-213,
-157,
-242,
-3,
-180,
-253,
-135,
-145,
-175,
-11,
-192,
-145,
-78,
-253,
-202,
-122,
-131,
-243,
-40,
-145,
-134,
-14,
-173,
-139,
-127,
-22,
-251,
-3,
-188,
-0,
-89,
-186,
-122,
-39,
-78,
-40,
-128,
-103,
-32,
-43,
-162,
-251,
-80,
-161,
-233,
-92,
-183,
-169,
-0,
-248,
-134,
-182,
-251,
-124,
-195,
-118,
-118,
-121,
-249,
-90,
-79,
-221,
-60,
-224,
-226,
-66,
-217,
-165,
-192,
-220,
-66,
-217,
-143,
-149,
-199,
-87,
-155,
-92,
-187,
-162,
-79,
-115,
-149,
-223,
-174,
-158,
-186,
-55,
-106,
-221,
-35,
-53,
-60,
-192,
-51,
-81,
-187,
-190,
-187,
-152,
-124,
-157,
-119,
-61,
-48,
-233,
-128,
-167,
-59,
-245,
-59,
-120,
-234,
-55,
-211,
-186,
-5,
-37,
-109,
-31,
-6,
-14,
-114,
-202,
-78,
-82,
-250,
-169,
-250,
-255,
-211,
-149,
-230,
-215,
-14,
-205,
-193,
-200,
-118,
-160,
-157,
-78,
-0,
-81,
-42,
-0,
-236,
-95,
-40,
-255,
-63,
-251,
-66,
-129,
-15,
-234,
-255,
-247,
-46,
-208,
-216,
-1,
-124,
-86,
-192,
-117,
-46,
-85,
-218,
-119,
-56,
-101,
-215,
-35,
-66,
-97,
-45,
-125,
-0,
-179,
-129,
-123,
-157,
-122,
-187,
-255,
-191,
-48,
-128,
-255,
-14,
-200,
-222,
-235,
-8,
-109,
-115,
-80,
-161,
-254,
-108,
-100,
-114,
-108,
-92,
-199,
-171,
-230,
-58,
-86,
-231,
-241,
-93,
-167,
-204,
-34,
-88,
-0,
-32,
-66,
-241,
-9,
-100,
-133,
-147,
-57,
-229,
-203,
-34,
-203,
-192,
-201,
-136,
-112,
-158,
-141,
-124,
-193,
-207,
-36,
-95,
-214,
-219,
-47,
-141,
-111,
-75,
-53,
-157,
-130,
-206,
-1,
-217,
-98,
-76,
-115,
-126,
-111,
-142,
-12,
-252,
-27,
-128,
-165,
-27,
-244,
-121,
-73,
-68,
-241,
-117,
-18,
-162,
-220,
-186,
-31,
-152,
-166,
-207,
-53,
-4,
-11,
-107,
-248,
-131,
-127,
-162,
-118,
-122,
-119,
-49,
-249,
-58,
-247,
-178,
-89,
-77,
-253,
-139,
-61,
-117,
-27,
-217,
-74,
-79,
-221,
-199,
-16,
-37,
-228,
-242,
-250,
-251,
-189,
-74,
-122,
-5,
-35,
-63,
-154,
-203,
-0,
-43,
-59,
-191,
-87,
-64,
-4,
-192,
-103,
-66,
-239,
-161,
-120,
-97,
-59,
-209,
-255,
-81,
-40,
-63,
-91,
-203,
-159,
-173,
-255,
-0,
-126,
-87,
-160,
-57,
-79,
-203,
-63,
-29,
-112,
-157,
-111,
-43,
-237,
-161,
-250,
-219,
-158,
-48,
-92,
-234,
-208,
-252,
-93,
-203,
-94,
-170,
-191,
-237,
-254,
-255,
-107,
-13,
-239,
-233,
-66,
-224,
-9,
-231,
-183,
-221,
-234,
-252,
-184,
-9,
-31,
-15,
-223,
-37,
-16,
-125,
-197,
-66,
-224,
-57,
-78,
-185,
-69,
-19,
-1,
-176,
-151,
-182,
-249,
-136,
-83,
-182,
-52,
-114,
-2,
-0,
-162,
-80,
-60,
-4,
-89,
-129,
-221,
-173,
-101,
-175,
-117,
-104,
-239,
-3,
-174,
-247,
-240,
-189,
-137,
-193,
-45,
-192,
-20,
-84,
-137,
-10,
-100,
-228,
-58,
-135,
-109,
-27,
-244,
-119,
-13,
-70,
-42,
-1,
-255,
-131,
-40,
-94,
-127,
-10,
-28,
-228,
-60,
-131,
-235,
-40,
-81,
-132,
-82,
-175,
-12,
-133,
-194,
-68,
-141,
-241,
-238,
-98,
-242,
-117,
-238,
-115,
-163,
-166,
-245,
-84,
-11,
-128,
-243,
-25,
-185,
-250,
-253,
-135,
-146,
-110,
-19,
-208,
-167,
-163,
-129,
-115,
-155,
-220,
-135,
-219,
-120,
-115,
-189,
-208,
-12,
-244,
-107,
-64,
-190,
-183,
-191,
-201,
-161,
-187,
-13,
-184,
-207,
-249,
-189,
-44,
-185,
-214,
-218,
-251,
-48,
-10,
-215,
-121,
-173,
-210,
-94,
-166,
-191,
-191,
-172,
-191,
-247,
-115,
-104,
-62,
-165,
-101,
-223,
-208,
-223,
-118,
-192,
-189,
-162,
-130,
-239,
-42,
-133,
-223,
-75,
-34,
-95,
-182,
-71,
-244,
-247,
-82,
-246,
-183,
-75,
-11,
-124,
-196,
-55,
-48,
-106,
-238,
-225,
-237,
-218,
-230,
-239,
-133,
-242,
-90,
-120,
-120,
-157,
-170,
-85,
-207,
-112,
-202,
-172,
-48,
-62,
-13,
-88,
-202,
-41,
-63,
-89,
-203,
-95,
-228,
-148,
-93,
-12,
-60,
-238,
-225,
-251,
-59,
-165,
-45,
-42,
-1,
-79,
-214,
-223,
-123,
-235,
-239,
-19,
-244,
-119,
-208,
-145,
-33,
-162,
-167,
-1,
-81,
-150,
-61,
-167,
-80,
-151,
-57,
-183,
-218,
-90,
-191,
-82,
-124,
-31,
-177,
-222,
-93,
-13,
-223,
-117,
-17,
-1,
-118,
-135,
-62,
-131,
-59,
-145,
-15,
-79,
-153,
-2,
-206,
-34,
-182,
-0,
-120,
-20,
-248,
-168,
-243,
-219,
-30,
-253,
-45,
-89,
-164,
-245,
-180,
-221,
-157,
-154,
-237,
-85,
-85,
-227,
-12,
-120,
-64,
-251,
-181,
-149,
-150,
-109,
-173,
-191,
-143,
-112,
-232,
-236,
-121,
-234,
-70,
-250,
-123,
-91,
-253,
-125,
-91,
-224,
-117,
-150,
-66,
-148,
-141,
-115,
-144,
-47,
-157,
-61,
-62,
-219,
-208,
-161,
-89,
-95,
-203,
-46,
-66,
-20,
-122,
-243,
-245,
-193,
-84,
-157,
-33,
-207,
-65,
-142,
-204,
-190,
-11,
-124,
-29,
-153,
-24,
-0,
-7,
-107,
-253,
-167,
-245,
-247,
-167,
-156,
-54,
-175,
-64,
-246,
-85,
-115,
-66,
-7,
-145,
-182,
-179,
-171,
-162,
-119,
-21,
-202,
-45,
-130,
-143,
-1,
-145,
-163,
-190,
-187,
-10,
-101,
-147,
-148,
-207,
-250,
-37,
-215,
-93,
-199,
-41,
-59,
-135,
-194,
-190,
-94,
-203,
-95,
-137,
-124,
-161,
-167,
-144,
-31,
-3,
-46,
-68,
-236,
-45,
-158,
-129,
-28,
-211,
-61,
-166,
-255,
-15,
-62,
-50,
-212,
-247,
-0,
-126,
-77,
-254,
-218,
-206,
-51,
-104,
-183,
-20,
-53,
-222,
-137,
-26,
-229,
-221,
-85,
-241,
-5,
-254,
-172,
-207,
-224,
-12,
-228,
-163,
-100,
-79,
-90,
-6,
-148,
-200,
-14,
-47,
-136,
-47,
-0,
-22,
-48,
-242,
-212,
-96,
-62,
-30,
-197,
-123,
-201,
-53,
-223,
-14,
-204,
-15,
-161,
-45,
-99,
-240,
-27,
-237,
-151,
-253,
-242,
-126,
-71,
-127,
-191,
-199,
-161,
-249,
-144,
-150,
-125,
-76,
-127,
-219,
-37,
-253,
-207,
-27,
-92,
-231,
-207,
-218,
-230,
-213,
-200,
-222,
-107,
-146,
-135,
-102,
-178,
-214,
-109,
-163,
-180,
-127,
-168,
-225,
-121,
-16,
-114,
-44,
-54,
-83,
-7,
-197,
-100,
-196,
-152,
-102,
-73,
-228,
-136,
-240,
-17,
-68,
-215,
-176,
-148,
-210,
-175,
-141,
-104,
-202,
-247,
-68,
-20,
-87,
-161,
-131,
-104,
-35,
-29,
-40,
-247,
-227,
-124,
-157,
-181,
-206,
-162,
-201,
-22,
-224,
-73,
-224,
-170,
-66,
-217,
-108,
-224,
-81,
-15,
-237,
-85,
-202,
-127,
-69,
-167,
-236,
-106,
-28,
-125,
-73,
-129,
-254,
-29,
-200,
-23,
-110,
-174,
-254,
-221,
-89,
-203,
-237,
-123,
-222,
-75,
-127,
-255,
-81,
-127,
-23,
-87,
-11,
-3,
-103,
-246,
-228,
-202,
-226,
-55,
-122,
-234,
-236,
-106,
-14,
-224,
-114,
-28,
-157,
-70,
-19,
-104,
-251,
-211,
-244,
-255,
-49,
-223,
-93,
-41,
-95,
-96,
-53,
-224,
-85,
-5,
-250,
-243,
-128,
-89,
-21,
-188,
-160,
-255,
-21,
-192,
-195,
-200,
-60,
-8,
-57,
-154,
-108,
-191,
-2,
-80,
-6,
-86,
-201,
-247,
-47,
-253,
-125,
-1,
-131,
-26,
-251,
-117,
-148,
-230,
-4,
-135,
-6,
-26,
-28,
-65,
-144,
-75,
-222,
-163,
-245,
-239,
-119,
-60,
-52,
-7,
-219,
-235,
-232,
-223,
-214,
-6,
-59,
-192,
-79,
-148,
-199,
-14,
-250,
-123,
-25,
-68,
-25,
-249,
-91,
-253,
-253,
-212,
-192,
-8,
-224,
-101,
-245,
-17,
-85,
-104,
-34,
-0,
-230,
-1,
-255,
-46,
-148,
-61,
-12,
-60,
-89,
-40,
-179,
-43,
-39,
-236,
-96,
-32,
-63,
-189,
-105,
-162,
-189,
-182,
-43,
-182,
-127,
-163,
-19,
-20,
-255,
-145,
-225,
-20,
-10,
-71,
-134,
-90,
-110,
-183,
-99,
-167,
-0,
-203,
-104,
-89,
-134,
-28,
-69,
-205,
-70,
-116,
-2,
-183,
-43,
-205,
-177,
-192,
-154,
-78,
-219,
-117,
-16,
-163,
-178,
-183,
-54,
-232,
-111,
-180,
-119,
-87,
-197,
-183,
-132,
-230,
-122,
-60,
-31,
-39,
-231,
-186,
-16,
-95,
-0,
-92,
-200,
-72,
-29,
-128,
-213,
-135,
-189,
-38,
-224,
-158,
-142,
-166,
-196,
-240,
-45,
-8,
-192,
-154,
-200,
-132,
-159,
-142,
-44,
-207,
-103,
-162,
-230,
-142,
-5,
-186,
-219,
-144,
-189,
-210,
-82,
-250,
-210,
-231,
-160,
-90,
-203,
-192,
-235,
-108,
-162,
-55,
-53,
-189,
-108,
-194,
-0,
-175,
-211,
-186,
-25,
-250,
-119,
-253,
-150,
-247,
-180,
-49,
-50,
-201,
-254,
-238,
-148,
-253,
-18,
-217,
-195,
-46,
-167,
-191,
-131,
-6,
-17,
-114,
-66,
-241,
-168,
-62,
-35,
-223,
-18,
-223,
-162,
-137,
-0,
-152,
-138,
-163,
-99,
-209,
-178,
-127,
-41,
-159,
-173,
-156,
-178,
-143,
-146,
-91,
-211,
-109,
-168,
-101,
-86,
-87,
-50,
-112,
-228,
-86,
-114,
-173,
-101,
-144,
-85,
-210,
-124,
-28,
-237,
-180,
-62,
-31,
-223,
-137,
-129,
-111,
-107,
-177,
-141,
-211,
-143,
-135,
-145,
-21,
-136,
-181,
-250,
-187,
-9,
-153,
-228,
-47,
-39,
-223,
-42,
-44,
-210,
-255,
-91,
-59,
-17,
-8,
-80,
-22,
-235,
-181,
-162,
-189,
-187,
-58,
-190,
-30,
-154,
-207,
-107,
-223,
-119,
-42,
-169,
-183,
-136,
-45,
-0,
-246,
-98,
-228,
-41,
-128,
-181,
-25,
-248,
-15,
-176,
-70,
-129,
-118,
-25,
-231,
-255,
-246,
-20,
-224,
-115,
-229,
-119,
-30,
-0,
-114,
-43,
-165,
-119,
-234,
-95,
-159,
-33,
-131,
-213,
-3,
-216,
-115,
-221,
-198,
-154,
-71,
-114,
-141,
-246,
-192,
-87,
-70,
-235,
-151,
-116,
-6,
-214,
-45,
-109,
-238,
-69,
-249,
-156,
-137,
-12,
-248,
-23,
-232,
-239,
-79,
-40,
-223,
-13,
-28,
-154,
-160,
-65,
-4,
-236,
-81,
-117,
-191,
-206,
-75,
-111,
-34,
-0,
-46,
-213,
-254,
-173,
-224,
-148,
-189,
-81,
-7,
-223,
-147,
-136,
-117,
-221,
-73,
-58,
-96,
-63,
-141,
-28,
-25,
-94,
-139,
-216,
-100,
-204,
-210,
-246,
-75,
-85,
-93,
-195,
-225,
-251,
-53,
-223,
-59,
-37,
-224,
-200,
-176,
-80,
-183,
-53,
-114,
-108,
-252,
-48,
-50,
-177,
-111,
-68,
-108,
-57,
-220,
-99,
-169,
-231,
-32,
-71,
-177,
-119,
-34,
-203,
-244,
-25,
-218,
-239,
-131,
-128,
-181,
-3,
-251,
-27,
-237,
-221,
-85,
-241,
-245,
-212,
-127,
-82,
-235,
-247,
-172,
-224,
-97,
-17,
-91,
-0,
-44,
-135,
-8,
-204,
-239,
-57,
-101,
-118,
-203,
-246,
-16,
-162,
-8,
-62,
-22,
-177,
-113,
-113,
-143,
-116,
-127,
-160,
-207,
-102,
-229,
-34,
-207,
-70,
-64,
-108,
-209,
-33,
-215,
-56,
-15,
-44,
-215,
-200,
-245,
-0,
-182,
-99,
-251,
-249,
-120,
-141,
-54,
-200,
-5,
-212,
-207,
-157,
-178,
-186,
-179,
-234,
-245,
-43,
-248,
-217,
-229,
-239,
-46,
-37,
-245,
-22,
-77,
-4,
-192,
-129,
-218,
-230,
-125,
-133,
-242,
-183,
-34,
-75,
-208,
-185,
-136,
-118,
-126,
-119,
-45,
-223,
-17,
-89,
-98,
-63,
-170,
-207,
-127,
-117,
-63,
-231,
-129,
-235,
-108,
-128,
-8,
-140,
-187,
-41,
-104,
-182,
-41,
-63,
-50,
-108,
-45,
-120,
-187,
-34,
-246,
-187,
-171,
-226,
-91,
-168,
-255,
-54,
-34,
-120,
-223,
-226,
-171,
-31,
-6,
-128,
-119,
-225,
-152,
-82,
-35,
-91,
-172,
-61,
-80,
-161,
-140,
-163,
-220,
-213,
-250,
-15,
-40,
-253,
-59,
-99,
-92,
-252,
-245,
-250,
-128,
-158,
-64,
-164,
-224,
-128,
-101,
-17,
-185,
-30,
-224,
-113,
-253,
-251,
-34,
-31,
-175,
-209,
-4,
-178,
-130,
-248,
-175,
-246,
-209,
-213,
-97,
-124,
-222,
-243,
-15,
-228,
-220,
-250,
-243,
-148,
-120,
-129,
-33,
-90,
-103,
-144,
-229,
-153,
-215,
-104,
-198,
-25,
-136,
-77,
-4,
-192,
-198,
-250,
-66,
-175,
-43,
-227,
-27,
-3,
-192,
-223,
-180,
-111,
-239,
-242,
-212,
-149,
-29,
-25,
-54,
-222,
-91,
-199,
-64,
-236,
-119,
-87,
-199,
-215,
-169,
-251,
-37,
-34,
-12,
-159,
-223,
-215,
-189,
-133,
-2,
-57,
-201,
-90,
-8,
-124,
-143,
-146,
-237,
-53,
-176,
-60,
-242,
-193,
-94,
-8,
-124,
-61,
-214,
-133,
-151,
-33,
-223,
-119,
-95,
-86,
-65,
-119,
-155,
-210,
-220,
-19,
-229,
-194,
-145,
-65,
-110,
-96,
-227,
-245,
-112,
-44,
-208,
-214,
-14,
-118,
-114,
-101,
-228,
-193,
-53,
-124,
-160,
-161,
-55,
-32,
-185,
-213,
-226,
-81,
-116,
-112,
-78,
-170,
-232,
-151,
-221,
-71,
-122,
-45,
-53,
-41,
-63,
-50,
-12,
-114,
-89,
-141,
-141,
-216,
-239,
-46,
-132,
-47,
-114,
-252,
-55,
-19,
-248,
-166,
-71,
-200,
-120,
-173,
-253,
-250,
-6,
-178,
-18,
-120,
-28,
-249,
-232,
-28,
-137,
-232,
-129,
-222,
-174,
-127,
-143,
-212,
-242,
-199,
-136,
-241,
-229,
-47,
-92,
-248,
-47,
-250,
-160,
-190,
-87,
-65,
-99,
-245,
-0,
-199,
-70,
-189,
-120,
-4,
-32,
-230,
-181,
-15,
-34,
-190,
-221,
-181,
-95,
-213,
-186,
-65,
-132,
-120,
-146,
-205,
-70,
-246,
-229,
-165,
-198,
-78,
-4,
-160,
-164,
-221,
-178,
-228,
-74,
-196,
-243,
-241,
-216,
-246,
-59,
-180,
-27,
-0,
-95,
-168,
-187,
-39,
-135,
-126,
-69,
-68,
-203,
-63,
-139,
-234,
-237,
-205,
-187,
-144,
-189,
-252,
-92,
-253,
-235,
-221,
-230,
-244,
-141,
-216,
-239,
-46,
-148,
-111,
-205,
-107,
-251,
-68,
-219,
-251,
-233,
-10,
-96,
-21,
-228,
-56,
-251,
-2,
-100,
-219,
-183,
-64,
-255,
-94,
-128,
-184,
-47,
-119,
-219,
-243,
-39,
-140,
-13,
-168,
-16,
-248,
-57,
-178,
-237,
-2,
-57,
-29,
-248,
-27,
-112,
-34,
-162,
-4,
-252,
-7,
-98,
-246,
-91,
-42,
-72,
-134,
-216,
-87,
-23,
-63,
-11,
-160,
-255,
-180,
-219,
-96,
-24,
-125,
-76,
-72,
-24,
-151,
-0,
-158,
-139,
-24,
-96,
-93,
-128,
-44,
-197,
-231,
-32,
-202,
-175,
-135,
-16,
-37,
-208,
-143,
-40,
-24,
-172,
-140,
-66,
-31,
-93,
-220,
-75,
-141,
-193,
-15,
-35,
-143,
-72,
-147,
-0,
-72,
-72,
-24,
-207,
-208,
-121,
-188,
-8,
-177,
-182,
-132,
-10,
-35,
-21,
-68,
-97,
-188,
-8,
-81,
-212,
-37,
-1,
-48,
-70,
-16,
-93,
-209,
-148,
-48,
-225,
-144,
-25,
-99,
-206,
-214,
-255,
-191,
-167,
-130,
-238,
-125,
-74,
-219,
-41,
-254,
-66,
-194,
-144,
-64,
-79,
-65,
-8,
-17,
-207,
-182,
-219,
-172,
-210,
-2,
-177,
-197,
-190,
-3,
-245,
-78,
-107,
-201,
-115,
-51,
-196,
-230,
-124,
-134,
-46,
-153,
-91,
-251,
-248,
-147,
-219,
-217,
-79,
-199,
-241,
-204,
-155,
-104,
-32,
-204,
-235,
-204,
-194,
-6,
-111,
-185,
-171,
-130,
-246,
-74,
-29,
-67,
-79,
-5,
-141,
-109,
-208,
-151,
-23,
-58,
-215,
-218,
-60,
-180,
-93,
-129,
-199,
-43,
-16,
-95,
-135,
-169,
-228,
-78,
-101,
-127,
-35,
-192,
-189,
-182,
-132,
-223,
-106,
-72,
-28,
-192,
-75,
-17,
-165,
-226,
-60,
-253,
-123,
-9,
-240,
-37,
-234,
-143,
-34,
-215,
-38,
-183,
-164,
-172,
-220,
-202,
-57,
-207,
-108,
-33,
-129,
-198,
-83,
-157,
-64,
-143,
-65,
-8,
-201,
-157,
-72,
-94,
-171,
-191,
-109,
-20,
-161,
-217,
-29,
-250,
-123,
-57,
-162,
-28,
-219,
-6,
-241,
-138,
-187,
-168,
-3,
-175,
-231,
-234,
-139,
-4,
-79,
-128,
-141,
-197,
-9,
-58,
-8,
-207,
-67,
-142,
-152,
-78,
-67,
-237,
-22,
-16,
-123,
-254,
-251,
-2,
-218,
-91,
-108,
-130,
-24,
-43,
-129,
-199,
-85,
-27,
-57,
-177,
-0,
-241,
-98,
-124,
-81,
-11,
-1,
-240,
-67,
-231,
-90,
-3,
-22,
-169,
-1,
-237,
-183,
-39,
-87,
-170,
-62,
-138,
-152,
-45,
-91,
-19,
-229,
-133,
-148,
-152,
-249,
-86,
-240,
-123,
-55,
-185,
-237,
-11,
-136,
-149,
-227,
-21,
-228,
-71,
-226,
-232,
-24,
-26,
-112,
-148,
-42,
-240,
-185,
-64,
-105,
-75,
-143,
-148,
-149,
-206,
-250,
-195,
-92,
-208,
-164,
-159,
-173,
-64,
-207,
-65,
-8,
-25,
-92,
-1,
-172,
-130,
-172,
-0,
-188,
-65,
-70,
-3,
-121,
-206,
-68,
-221,
-82,
-129,
-93,
-240,
-4,
-0,
-109,
-200,
-111,
-75,
-196,
-0,
-106,
-33,
-240,
-242,
-46,
-188,
-10,
-124,
-215,
-36,
-183,
-173,
-184,
-162,
-3,
-31,
-87,
-155,
-30,
-100,
-79,
-95,
-194,
-231,
-56,
-228,
-88,
-112,
-50,
-178,
-63,
-183,
-251,
-249,
-89,
-192,
-49,
-1,
-237,
-45,
-54,
-35,
-247,
-24,
-253,
-145,
-135,
-206,
-70,
-204,
-253,
-8,
-121,
-188,
-137,
-208,
-208,
-232,
-75,
-34,
-167,
-30,
-211,
-244,
-223,
-3,
-4,
-172,
-78,
-10,
-60,
-236,
-170,
-238,
-120,
-52,
-52,
-28,
-114,
-218,
-98,
-45,
-88,
-7,
-252,
-92,
-42,
-120,
-237,
-72,
-30,
-150,
-254,
-116,
-10,
-199,
-193,
-136,
-233,
-243,
-239,
-181,
-126,
-14,
-21,
-95,
-119,
-114,
-31,
-142,
-74,
-75,
-75,
-228,
-200,
-18,
-28,
-55,
-232,
-94,
-192,
-96,
-16,
-66,
-23,
-179,
-16,
-5,
-206,
-103,
-28,
-250,
-110,
-65,
-8,
-35,
-1,
-89,
-94,
-158,
-133,
-216,
-166,
-159,
-67,
-64,
-200,
-176,
-0,
-158,
-91,
-234,
-96,
-187,
-33,
-70,
-31,
-149,
-231,
-81,
-250,
-44,
-31,
-160,
-16,
-68,
-163,
-1,
-143,
-23,
-33,
-66,
-196,
-78,
-136,
-25,
-148,
-216,
-178,
-7,
-240,
-154,
-10,
-124,
-64,
-255,
-255,
-98,
-68,
-56,
-63,
-137,
-172,
-10,
-188,
-121,
-20,
-10,
-237,
-45,
-182,
-32,
-143,
-111,
-119,
-135,
-135,
-110,
-146,
-78,
-134,
-149,
-112,
-2,
-101,
-6,
-246,
-241,
-205,
-74,
-126,
-166,
-254,
-3,
-216,
-177,
-225,
-125,
-218,
-85,
-231,
-75,
-10,
-229,
-91,
-218,
-137,
-26,
-200,
-231,
-105,
-200,
-105,
-7,
-72,
-0,
-151,
-210,
-83,
-15,
-228,
-216,
-22,
-196,
-124,
-219,
-43,
-176,
-24,
-185,
-13,
-240,
-90,
-209,
-146,
-111,
-127,
-250,
-93,
-254,
-227,
-15,
-66,
-8,
-178,
-23,
-62,
-10,
-248,
-3,
-185,
-27,
-234,
-199,
-28,
-154,
-110,
-65,
-8,
-35,
-0,
-177,
-129,
-182,
-152,
-6,
-60,
-111,
-180,
-250,
-82,
-6,
-196,
-51,
-110,
-33,
-178,
-116,
-108,
-28,
-46,
-92,
-121,
-172,
-133,
-44,
-55,
-167,
-33,
-49,
-20,
-94,
-167,
-2,
-224,
-142,
-144,
-9,
-235,
-225,
-23,
-228,
-60,
-84,
-209,
-254,
-41,
-1,
-160,
-191,
-109,
-190,
-135,
-45,
-29,
-154,
-77,
-181,
-236,
-116,
-253,
-221,
-84,
-0,
-216,
-136,
-203,
-123,
-34,
-113,
-242,
-0,
-126,
-223,
-176,
-159,
-214,
-225,
-236,
-205,
-133,
-114,
-203,
-47,
-200,
-215,
-129,
-220,
-77,
-126,
-54,
-142,
-123,
-115,
-9,
-173,
-13,
-63,
-14,
-78,
-220,
-75,
-15,
-221,
-133,
-74,
-243,
-141,
-146,
-250,
-175,
-107,
-125,
-231,
-143,
-90,
-37,
-40,
-4,
-33,
-212,
-50,
-128,
-41,
-206,
-239,
-151,
-105,
-217,
-121,
-78,
-89,
-227,
-32,
-132,
-68,
-80,
-234,
-20,
-248,
-117,
-218,
-35,
-14,
-3,
-136,
-85,
-221,
-84,
-2,
-179,
-249,
-148,
-240,
-184,
-10,
-49,
-211,
-117,
-93,
-120,
-95,
-138,
-36,
-155,
-184,
-170,
-170,
-109,
-31,
-240,
-8,
-0,
-235,
-208,
-244,
-125,
-135,
-198,
-110,
-13,
-172,
-67,
-75,
-176,
-0,
-64,
-172,
-23,
-103,
-34,
-75,
-238,
-103,
-32,
-138,
-183,
-121,
-200,
-106,
-52,
-56,
-139,
-19,
-121,
-20,
-235,
-243,
-200,
-99,
-31,
-108,
-71,
-190,
-143,
-31,
-240,
-139,
-40,
-225,
-99,
-151,
-246,
-65,
-39,
-25,
-228,
-1,
-86,
-142,
-175,
-160,
-177,
-219,
-185,
-107,
-75,
-234,
-109,
-24,
-252,
-214,
-91,
-189,
-32,
-80,
-8,
-66,
-168,
-101,
-69,
-1,
-176,
-162,
-150,
-253,
-175,
-64,
-215,
-40,
-8,
-97,
-204,
-9,
-75,
-132,
-61,
-162,
-135,
-103,
-84,
-1,
-53,
-214,
-209,
-246,
-126,
-61,
-2,
-192,
-78,
-238,
-91,
-28,
-154,
-155,
-144,
-85,
-202,
-114,
-5,
-154,
-16,
-1,
-96,
-221,
-174,
-255,
-233,
-148,
-89,
-103,
-166,
-143,
-85,
-181,
-45,
-240,
-121,
-22,
-185,
-75,
-249,
-49,
-200,
-170,
-98,
-17,
-34,
-76,
-62,
-217,
-128,
-143,
-93,
-225,
-4,
-133,
-78,
-39,
-143,
-140,
-52,
-16,
-172,
-213,
-161,
-113,
-183,
-1,
-235,
-23,
-234,
-108,
-26,
-189,
-133,
-192,
-51,
-67,
-251,
-217,
-10,
-20,
-66,
-16,
-105,
-217,
-83,
-2,
-0,
-241,
-79,
-182,
-46,
-194,
-71,
-20,
-232,
-130,
-67,
-16,
-197,
-158,
-176,
-68,
-216,
-35,
-122,
-120,
-142,
-249,
-21,
-69,
-76,
-180,
-189,
-223,
-162,
-0,
-208,
-178,
-91,
-181,
-108,
-115,
-103,
-178,
-255,
-214,
-169,
-111,
-34,
-0,
-172,
-150,
-124,
-79,
-167,
-236,
-35,
-90,
-214,
-104,
-73,
-76,
-158,
-245,
-200,
-226,
-82,
-52,
-218,
-116,
-3,
-30,
-118,
-11,
-252,
-161,
-64,
-250,
-221,
-148,
-254,
-177,
-26,
-58,
-187,
-13,
-216,
-183,
-80,
-254,
-89,
-45,
-111,
-125,
-170,
-21,
-12,
-10,
-65,
-8,
-181,
-12,
-68,
-82,
-90,
-205,
-181,
-125,
-112,
-69,
-23,
-202,
-224,
-32,
-132,
-68,
-158,
-176,
-68,
-216,
-35,
-22,
-248,
-141,
-249,
-21,
-69,
-76,
-126,
-93,
-238,
-215,
-233,
-131,
-43,
-0,
-108,
-70,
-167,
-3,
-157,
-255,
-239,
-228,
-212,
-7,
-9,
-0,
-68,
-155,
-110,
-191,
-210,
-110,
-234,
-177,
-149,
-17,
-165,
-222,
-34,
-2,
-163,
-67,
-33,
-43,
-9,
-155,
-142,
-204,
-226,
-7,
-33,
-109,
-11,
-124,
-172,
-246,
-191,
-54,
-111,
-162,
-210,
-239,
-172,
-244,
-149,
-115,
-131,
-124,
-27,
-80,
-76,
-224,
-114,
-190,
-150,
-183,
-14,
-172,
-26,
-12,
-202,
-87,
-0,
-51,
-16,
-39,
-148,
-187,
-245,
-1,
-108,
-224,
-105,
-219,
-100,
-5,
-16,
-109,
-194,
-18,
-105,
-143,
-88,
-224,
-57,
-230,
-87,
-20,
-49,
-249,
-117,
-185,
-95,
-167,
-15,
-174,
-0,
-176,
-154,
-245,
-155,
-17,
-229,
-228,
-99,
-140,
-12,
-89,
-21,
-42,
-0,
-108,
-146,
-153,
-129,
-112,
-93,
-136,
-203,
-46,
-192,
-55,
-107,
-120,
-44,
-137,
-28,
-117,
-218,
-113,
-252,
-85,
-36,
-145,
-137,
-205,
-90,
-244,
-253,
-2,
-189,
-53,
-104,
-242,
-70,
-182,
-70,
-142,
-134,
-33,
-60,
-109,
-91,
-232,
-10,
-224,
-153,
-200,
-50,
-127,
-33,
-170,
-92,
-68,
-242,
-46,
-44,
-64,
-4,
-221,
-64,
-22,
-237,
-232,
-160,
-16,
-132,
-80,
-203,
-32,
-223,
-2,
-216,
-24,
-248,
-190,
-140,
-42,
-65,
-65,
-8,
-137,
-60,
-97,
-137,
-180,
-71,
-44,
-240,
-28,
-211,
-43,
-138,
-30,
-248,
-181,
-190,
-95,
-114,
-108,
-81,
-40,
-191,
-195,
-169,
-59,
-182,
-80,
-23,
-42,
-0,
-110,
-161,
-30,
-183,
-214,
-240,
-176,
-123,
-240,
-135,
-113,
-210,
-217,
-35,
-81,
-150,
-236,
-209,
-160,
-171,
-176,
-252,
-165,
-150,
-121,
-147,
-131,
-32,
-138,
-92,
-8,
-215,
-1,
-212,
-102,
-202,
-118,
-104,
-47,
-82,
-218,
-143,
-235,
-239,
-143,
-234,
-239,
-139,
-235,
-218,
-70,
-1,
-133,
-32,
-132,
-90,
-6,
-35,
-149,
-128,
-231,
-107,
-217,
-235,
-157,
-178,
-224,
-32,
-132,
-68,
-158,
-176,
-68,
-220,
-35,
-106,
-219,
-49,
-191,
-162,
-136,
-201,
-175,
-235,
-253,
-146,
-163,
-40,
-0,
-126,
-228,
-212,
-109,
-87,
-168,
-171,
-21,
-0,
-200,
-17,
-39,
-200,
-87,
-187,
-44,
-171,
-144,
-13,
-36,
-91,
-229,
-128,
-100,
-163,
-18,
-15,
-164,
-178,
-71,
-12,
-122,
-158,
-18,
-2,
-72,
-102,
-170,
-57,
-136,
-197,
-160,
-215,
-148,
-156,
-60,
-55,
-95,
-232,
-41,
-128,
-205,
-204,
-60,
-144,
-32,
-213,
-67,
-251,
-25,
-165,
-61,
-189,
-208,
-246,
-179,
-33,
-215,
-234,
-12,
-252,
-65,
-8,
-97,
-164,
-0,
-216,
-18,
-89,
-146,
-92,
-75,
-30,
-146,
-58,
-56,
-8,
-33,
-113,
-149,
-58,
-207,
-33,
-210,
-30,
-209,
-105,
-59,
-30,
-86,
-20,
-49,
-183,
-80,
-157,
-238,
-151,
-28,
-69,
-1,
-96,
-195,
-166,
-77,
-101,
-48,
-203,
-116,
-136,
-0,
-176,
-6,
-83,
-135,
-87,
-208,
-252,
-76,
-105,
-142,
-170,
-160,
-177,
-177,
-3,
-183,
-45,
-169,
-127,
-51,
-121,
-54,
-43,
-123,
-74,
-240,
-195,
-10,
-126,
-239,
-83,
-154,
-57,
-52,
-179,
-3,
-120,
-123,
-21,
-173,
-210,
-219,
-109,
-192,
-147,
-200,
-92,
-156,
-174,
-99,
-248,
-217,
-117,
-109,
-163,
-129,
-193,
-32,
-132,
-224,
-8,
-0,
-45,
-179,
-22,
-78,
-31,
-163,
-65,
-16,
-66,
-34,
-79,
-88,
-34,
-236,
-17,
-61,
-237,
-198,
-244,
-138,
-162,
-7,
-126,
-81,
-239,
-55,
-6,
-16,
-19,
-93,
-59,
-25,
-95,
-89,
-65,
-103,
-29,
-100,
-30,
-163,
-36,
-19,
-53,
-146,
-238,
-28,
-224,
-43,
-21,
-124,
-118,
-37,
-199,
-29,
-84,
-68,
-31,
-210,
-190,
-221,
-165,
-180,
-191,
-43,
-163,
-83,
-90,
-107,
-102,
-124,
-19,
-225,
-74,
-85,
-187,
-13,
-248,
-162,
-254,
-173,
-204,
-157,
-216,
-11,
-232,
-41,
-8,
-97,
-236,
-9,
-75,
-132,
-61,
-98,
-129,
-223,
-115,
-24,
-227,
-43,
-138,
-152,
-252,
-250,
-184,
-223,
-24,
-32,
-143,
-91,
-88,
-107,
-157,
-71,
-190,
-196,
-247,
-186,
-33,
-147,
-39,
-253,
-152,
-173,
-207,
-206,
-205,
-175,
-184,
-30,
-146,
-123,
-241,
-225,
-194,
-152,
-57,
-160,
-230,
-154,
-111,
-34,
-63,
-13,
-56,
-133,
-193,
-188,
-136,
-235,
-145,
-7,
-87,
-157,
-67,
-133,
-16,
-243,
-240,
-182,
-219,
-128,
-251,
-245,
-111,
-183,
-216,
-254,
-109,
-65,
-15,
-65,
-8,
-137,
-56,
-97,
-137,
-180,
-71,
-44,
-240,
-28,
-15,
-43,
-138,
-152,
-91,
-168,
-232,
-247,
-27,
-3,
-228,
-113,
-40,
-107,
-175,
-77,
-110,
-121,
-120,
-102,
-73,
-253,
-74,
-136,
-167,
-168,
-197,
-124,
-228,
-52,
-203,
-245,
-228,
-91,
-136,
-108,
-57,
-118,
-116,
-198,
-204,
-64,
-134,
-170,
-2,
-223,
-119,
-21,
-120,
-220,
-166,
-215,
-113,
-189,
-1,
-167,
-226,
-232,
-202,
-2,
-239,
-253,
-89,
-136,
-224,
-69,
-255,
-174,
-83,
-223,
-170,
-39,
-16,
-49,
-8,
-33,
-145,
-39,
-44,
-145,
-246,
-136,
-5,
-250,
-49,
-189,
-162,
-232,
-129,
-95,
-212,
-251,
-141,
-1,
-100,
-91,
-99,
-221,
-118,
-7,
-142,
-155,
-61,
-244,
-214,
-207,
-96,
-30,
-37,
-177,
-27,
-144,
-204,
-86,
-159,
-68,
-20,
-216,
-54,
-174,
-197,
-99,
-136,
-99,
-219,
-161,
-56,
-161,
-191,
-145,
-109,
-133,
-61,
-234,
-251,
-118,
-205,
-181,
-215,
-64,
-132,
-232,
-101,
-72,
-152,
-54,
-27,
-174,
-237,
-98,
-100,
-101,
-209,
-54,
-94,
-134,
-77,
-102,
-251,
-239,
-122,
-234,
-113,
-2,
-34,
-78,
-88,
-34,
-238,
-17,
-29,
-218,
-49,
-191,
-162,
-136,
-201,
-175,
-143,
-251,
-77,
-72,
-240,
-34,
-246,
-132,
-37,
-226,
-30,
-209,
-161,
-27,
-15,
-43,
-138,
-152,
-91,
-168,
-232,
-247,
-155,
-144,
-224,
-69,
-236,
-9,
-75,
-196,
-61,
-162,
-210,
-140,
-249,
-21,
-69,
-76,
-126,
-125,
-220,
-111,
-66,
-66,
-41,
-98,
-78,
-88,
-250,
-217,
-35,
-142,
-249,
-21,
-69,
-76,
-126,
-125,
-220,
-111,
-194,
-4,
-3,
-225,
-231,
-154,
-209,
-39,
-108,
-108,
-196,
-20,
-80,
-74,
-19,
-123,
-203,
-19,
-155,
-95,
-212,
-251,
-13,
-1,
-162,
-48,
-179,
-86,
-119,
-165,
-249,
-246,
-144,
-252,
-136,
-32,
-182,
-250,
-107,
-84,
-208,
-21,
-177,
-16,
-57,
-206,
-187,
-4,
-177,
-247,
-95,
-181,
-97,
-255,
-214,
-82,
-62,
-39,
-20,
-202,
-47,
-3,
-30,
-172,
-104,
-183,
-10,
-185,
-210,
-240,
-131,
-21,
-116,
-239,
-82,
-154,
-39,
-129,
-85,
-60,
-245,
-43,
-146,
-219,
-44,
-236,
-81,
-193,
-103,
-71,
-165,
-185,
-135,
-190,
-3,
-240,
-208,
-49,
-96,
-228,
-120,
-0,
-227,
-96,
-69,
-17,
-147,
-95,
-31,
-247,
-27,
-10,
-242,
-179,
-241,
-42,
-75,
-187,
-131,
-148,
-230,
-212,
-26,
-94,
-22,
-54,
-247,
-226,
-127,
-200,
-163,
-254,
-160,
-99,
-118,
-32,
-155,
-117,
-5,
-191,
-237,
-181,
-221,
-23,
-157,
-178,
-12,
-217,
-86,
-253,
-179,
-166,
-237,
-183,
-181,
-109,
-105,
-92,
-65,
-114,
-205,
-254,
-129,
-21,
-52,
-86,
-72,
-60,
-130,
-39,
-211,
-51,
-18,
-142,
-204,
-190,
-223,
-119,
-135,
-222,
-91,
-107,
-208,
-49,
-96,
-228,
-68,
-5,
-241,
-87,
-20,
-67,
-255,
-98,
-247,
-1,
-36,
-98,
-51,
-136,
-243,
-210,
-64,
-40,
-50,
-96,
-9,
-242,
-120,
-123,
-111,
-170,
-225,
-101,
-81,
-52,
-65,
-222,
-20,
-248,
-179,
-214,
-45,
-160,
-196,
-4,
-216,
-195,
-239,
-11,
-218,
-102,
-123,
-167,
-204,
-70,
-50,
-174,
-244,
-182,
-100,
-228,
-42,
-224,
-205,
-158,
-122,
-27,
-69,
-107,
-186,
-111,
-98,
-23,
-104,
-109,
-223,
-127,
-229,
-169,
-179,
-130,
-198,
-155,
-216,
-53,
-58,
-232,
-24,
-48,
-114,
-34,
-130,
-200,
-95,
-216,
-216,
-252,
-70,
-27,
-136,
-89,
-44,
-120,
-108,
-227,
-129,
-29,
-180,
-110,
-10,
-53,
-153,
-145,
-203,
-4,
-128,
-214,
-101,
-192,
-201,
-90,
-127,
-23,
-97,
-137,
-69,
-143,
-87,
-250,
-181,
-157,
-178,
-119,
-106,
-217,
-71,
-3,
-218,
-219,
-201,
-57,
-224,
-17,
-75,
-190,
-242,
-25,
-136,
-150,
-236,
-161,
-93,
-151,
-220,
-7,
-96,
-43,
-167,
-124,
-67,
-196,
-154,
-113,
-38,
-195,
-178,
-206,
-164,
-99,
-192,
-200,
-132,
-132,
-34,
-200,
-191,
-180,
-103,
-120,
-234,
-78,
-209,
-186,
-111,
-5,
-240,
-41,
-21,
-0,
-90,
-191,
-6,
-185,
-147,
-207,
-7,
-2,
-248,
-93,
-13,
-60,
-84,
-40,
-179,
-118,
-23,
-181,
-81,
-131,
-24,
-185,
-10,
-112,
-3,
-162,
-174,
-163,
-2,
-124,
-22,
-129,
-31,
-77,
-96,
-95,
-229,
-243,
-63,
-59,
-7,
-201,
-205,
-189,
-27,
-133,
-224,
-31,
-115,
-32,
-82,
-60,
-123,
-135,
-95,
-148,
-56,
-251,
-9,
-195,
-1,
-226,
-33,
-103,
-93,
-110,
-215,
-116,
-202,
-87,
-213,
-242,
-133,
-192,
-122,
-1,
-124,
-42,
-5,
-128,
-210,
-216,
-128,
-156,
-94,
-167,
-29,
-90,
-160,
-166,
-79,
-118,
-21,
-112,
-170,
-83,
-102,
-19,
-122,
-252,
-180,
-238,
-158,
-156,
-54,
-75,
-2,
-215,
-104,
-187,
-47,
-145,
-235,
-6,
-38,
-19,
-176,
-154,
-137,
-2,
-58,
-166,
-61,
-42,
-225,
-25,
-45,
-158,
-189,
-195,
-179,
-83,
-156,
-125,
-82,
-26,
-176,
-74,
-32,
-91,
-16,
-235,
-82,
-91,
-186,
-5,
-1,
-54,
-82,
-154,
-218,
-173,
-7,
-185,
-59,
-243,
-126,
-78,
-153,
-77,
-144,
-113,
-118,
-85,
-91,
-135,
-222,
-162,
-74,
-0,
-236,
-175,
-52,
-94,
-227,
-40,
-224,
-88,
-253,
-119,
-186,
-210,
-93,
-227,
-148,
-29,
-139,
-172,
-32,
-30,
-118,
-203,
-106,
-250,
-100,
-87,
-1,
-11,
-144,
-37,
-251,
-242,
-200,
-137,
-204,
-28,
-26,
-186,
-244,
-34,
-122,
-131,
-133,
-58,
-71,
-238,
-69,
-182,
-4,
-175,
-107,
-194,
-163,
-53,
-136,
-148,
-246,
-168,
-192,
-51,
-106,
-60,
-123,
-229,
-25,
-35,
-206,
-254,
-132,
-73,
-3,
-214,
-22,
-228,
-138,
-169,
-82,
-37,
-36,
-240,
-93,
-165,
-249,
-99,
-0,
-191,
-173,
-149,
-246,
-122,
-167,
-204,
-10,
-226,
-247,
-214,
-180,
-173,
-68,
-129,
-214,
-134,
-227,
-122,
-162,
-134,
-167,
-141,
-219,
-183,
-135,
-83,
-182,
-188,
-142,
-173,
-63,
-212,
-221,
-79,
-129,
-151,
-93,
-5,
-28,
-65,
-190,
-218,
-109,
-101,
-73,
-73,
-110,
-215,
-1,
-240,
-235,
-54,
-60,
-218,
-92,
-52,
-90,
-218,
-163,
-66,
-187,
-232,
-241,
-236,
-137,
-16,
-103,
-95,
-249,
-244,
-146,
-6,
-172,
-112,
-141,
-12,
-9,
-38,
-81,
-171,
-87,
-33,
-242,
-234,
-139,
-142,
-201,
-88,
-201,
-163,
-233,
-122,
-143,
-33,
-245,
-222,
-166,
-40,
-77,
-80,
-134,
-40,
-242,
-208,
-90,
-47,
-37,
-87,
-92,
-62,
-140,
-19,
-59,
-176,
-164,
-157,
-181,
-122,
-180,
-184,
-214,
-41,
-187,
-164,
-64,
-107,
-39,
-246,
-188,
-26,
-158,
-7,
-40,
-157,
-187,
-119,
-183,
-1,
-77,
-188,
-201,
-58,
-42,
-120,
-217,
-85,
-192,
-44,
-125,
-38,
-243,
-105,
-169,
-180,
-3,
-246,
-113,
-238,
-179,
-113,
-0,
-211,
-54,
-23,
-140,
-154,
-246,
-104,
-60,
-129,
-142,
-105,
-192,
-60,
-147,
-118,
-46,
-98,
-172,
-113,
-1,
-226,
-137,
-182,
-159,
-62,
-175,
-223,
-214,
-240,
-9,
-89,
-125,
-61,
-68,
-33,
-204,
-86,
-13,
-207,
-78,
-201,
-88,
-129,
-101,
-144,
-179,
-105,
-240,
-8,
-124,
-224,
-245,
-90,
-231,
-61,
-222,
-43,
-225,
-249,
-121,
-109,
-115,
-32,
-185,
-178,
-205,
-27,
-135,
-175,
-164,
-189,
-69,
-213,
-22,
-224,
-163,
-74,
-83,
-25,
-172,
-22,
-9,
-171,
-182,
-0,
-120,
-154,
-83,
-182,
-167,
-182,
-13,
-118,
-119,
-119,
-218,
-126,
-219,
-233,
-95,
-171,
-47,
-55,
-226,
-225,
-249,
-48,
-162,
-245,
-159,
-133,
-108,
-71,
-106,
-117,
-35,
-157,
-64,
-15,
-105,
-143,
-38,
-2,
-60,
-147,
-246,
-14,
-157,
-180,
-247,
-144,
-251,
-118,
-131,
-124,
-201,
-189,
-249,
-223,
-148,
-79,
-211,
-213,
-87,
-168,
-87,
-98,
-231,
-100,
-172,
-192,
-225,
-122,
-221,
-95,
-120,
-234,
-236,
-17,
-90,
-169,
-129,
-143,
-167,
-205,
-106,
-58,
-206,
-46,
-35,
-95,
-254,
-7,
-235,
-131,
-2,
-5,
-128,
-205,
-72,
-52,
-201,
-83,
-231,
-238,
-245,
-31,
-211,
-177,
-236,
-150,
-93,
-171,
-109,
-255,
-68,
-192,
-254,
-191,
-192,
-123,
-21,
-167,
-127,
-175,
-14,
-109,
-87,
-224,
-113,
-168,
-182,
-255,
-46,
-121,
-124,
-197,
-147,
-218,
-240,
-106,
-114,
-209,
-232,
-105,
-143,
-148,
-46,
-218,
-146,
-54,
-38,
-175,
-24,
-40,
-76,
-218,
-211,
-128,
-13,
-11,
-245,
-27,
-147,
-235,
-24,
-230,
-80,
-72,
-78,
-233,
-208,
-181,
-89,
-125,
-221,
-194,
-144,
-142,
-106,
-201,
-141,
-89,
-30,
-193,
-209,
-68,
-35,
-123,
-101,
-235,
-132,
-84,
-106,
-226,
-91,
-194,
-243,
-68,
-125,
-127,
-139,
-128,
-203,
-26,
-182,
-181,
-168,
-18,
-0,
-231,
-42,
-205,
-128,
-209,
-26,
-45,
-16,
-187,
-127,
-21,
-109,
-55,
-66,
-86,
-144,
-15,
-34,
-38,
-194,
-107,
-144,
-219,
-6,
-116,
-218,
-238,
-214,
-93,
-184,
-143,
-180,
-71,
-209,
-20,
-138,
-49,
-121,
-41,
-191,
-78,
-194,
-132,
-145,
-147,
-246,
-119,
-120,
-38,
-45,
-240,
-33,
-173,
-183,
-198,
-60,
-215,
-151,
-208,
-181,
-93,
-125,
-5,
-229,
-180,
-139,
-1,
-228,
-24,
-10,
-156,
-21,
-31,
-240,
-97,
-45,
-107,
-52,
-129,
-181,
-173,
-221,
-138,
-64,
-243,
-112,
-102,
-22,
-101,
-118,
-0,
-27,
-147,
-167,
-219,
-42,
-53,
-9,
-38,
-87,
-72,
-126,
-163,
-80,
-254,
-16,
-112,
-121,
-147,
-62,
-53,
-233,
-95,
-77,
-91,
-27,
-219,
-97,
-31,
-167,
-236,
-123,
-90,
-118,
-126,
-219,
-62,
-133,
-92,
-56,
-106,
-218,
-35,
-226,
-230,
-81,
-143,
-170,
-156,
-36,
-130,
-48,
-33,
-159,
-180,
-179,
-240,
-56,
-174,
-32,
-146,
-251,
-97,
-29,
-136,
-111,
-35,
-159,
-180,
-3,
-138,
-50,
-198,
-199,
-234,
-235,
-255,
-244,
-154,
-238,
-57,
-183,
-253,
-202,
-238,
-21,
-202,
-199,
-105,
-187,
-190,
-182,
-157,
-14,
-172,
-208,
-176,
-173,
-133,
-207,
-18,
-240,
-233,
-228,
-138,
-194,
-201,
-84,
-175,
-166,
-62,
-169,
-116,
-174,
-80,
-123,
-166,
-150,
-5,
-47,
-251,
-155,
-244,
-175,
-166,
-157,
-213,
-167,
-220,
-204,
-200,
-248,
-133,
-171,
-146,
-27,
-26,
-213,
-70,
-24,
-110,
-5,
-34,
-166,
-61,
-34,
-162,
-66,
-49,
-38,
-47,
-165,
-137,
-34,
-76,
-28,
-26,
-239,
-209,
-23,
-121,
-84,
-216,
-159,
-233,
-111,
-27,
-231,
-221,
-183,
-36,
-109,
-187,
-250,
-42,
-85,
-90,
-18,
-127,
-197,
-244,
-76,
-125,
-110,
-51,
-145,
-176,
-213,
-107,
-33,
-194,
-173,
-109,
-68,
-98,
-155,
-246,
-186,
-241,
-68,
-115,
-250,
-239,
-102,
-36,
-90,
-2,
-216,
-22,
-184,
-82,
-235,
-102,
-81,
-51,
-1,
-129,
-159,
-43,
-237,
-115,
-157,
-50,
-155,
-29,
-168,
-117,
-64,
-78,
-95,
-255,
-2,
-218,
-44,
-129,
-132,
-41,
-3,
-143,
-179,
-15,
-240,
-45,
-173,
-187,
-145,
-62,
-182,
-126,
-68,
-76,
-123,
-68,
-68,
-133,
-98,
-100,
-94,
-49,
-5,
-147,
-157,
-180,
-251,
-123,
-234,
-172,
-119,
-217,
-221,
-232,
-215,
-141,
-138,
-44,
-49,
-180,
-95,
-125,
-61,
-94,
-82,
-223,
-215,
-113,
-174,
-53,
-73,
-221,
-25,
-216,
-91,
-255,
-127,
-98,
-72,
-219,
-2,
-159,
-165,
-16,
-129,
-4,
-240,
-178,
-22,
-237,
-45,
-236,
-49,
-224,
-181,
-228,
-46,
-211,
-32,
-199,
-203,
-175,
-8,
-224,
-115,
-62,
-98,
-155,
-146,
-57,
-101,
-246,
-196,
-230,
-13,
-77,
-251,
-229,
-233,
-95,
-19,
-1,
-176,
-151,
-182,
-185,
-180,
-164,
-126,
-37,
-36,
-38,
-39,
-120,
-18,
-157,
-116,
-6,
-17,
-211,
-30,
-17,
-113,
-73,
-27,
-153,
-87,
-76,
-97,
-226,
-157,
-180,
-200,
-215,
-209,
-166,
-198,
-122,
-171,
-83,
-110,
-245,
-1,
-143,
-122,
-120,
-181,
-93,
-125,
-45,
-240,
-212,
-245,
-118,
-156,
-75,
-158,
-24,
-227,
-120,
-224,
-239,
-250,
-255,
-70,
-19,
-5,
-57,
-86,
-180,
-167,
-10,
-23,
-52,
-105,
-235,
-240,
-40,
-98,
-54,
-114,
-234,
-114,
-38,
-240,
-113,
-2,
-35,
-24,
-33,
-123,
-253,
-127,
-23,
-202,
-78,
-80,
-158,
-149,
-227,
-35,
-176,
-127,
-65,
-2,
-0,
-153,
-220,
-86,
-89,
-92,
-149,
-233,
-200,
-206,
-185,
-135,
-136,
-173,
-240,
-38,
-98,
-218,
-35,
-34,
-42,
-20,
-35,
-243,
-138,
-41,
-76,
-188,
-147,
-150,
-252,
-216,
-230,
-228,
-66,
-121,
-213,
-150,
-169,
-237,
-234,
-107,
-154,
-167,
-174,
-183,
-227,
-92,
-68,
-184,
-216,
-112,
-241,
-179,
-144,
-175,
-120,
-169,
-128,
-113,
-218,
-173,
-132,
-40,
-64,
-175,
-32,
-183,
-41,
-120,
-130,
-0,
-15,
-199,
-132,
-126,
-225,
-186,
-93,
-254,
-69,
-255,
-190,
-57,
-100,
-224,
-24,
-99,
-172,
-239,
-243,
-233,
-30,
-18,
-235,
-86,
-121,
-119,
-96,
-63,
-108,
-128,
-145,
-103,
-246,
-204,
-203,
-122,
-118,
-133,
-106,
-120,
-175,
-212,
-191,
-62,
-11,
-193,
-233,
-250,
-247,
-233,
-182,
-0,
-241,
-28,
-219,
-215,
-24,
-243,
-152,
-49,
-166,
-184,
-135,
-92,
-174,
-208,
-206,
-197,
-3,
-250,
-119,
-221,
-192,
-126,
-217,
-120,
-241,
-119,
-121,
-234,
-172,
-146,
-241,
-156,
-44,
-203,
-30,
-242,
-212,
-63,
-133,
-44,
-203,
-30,
-53,
-198,
-88,
-251,
-251,
-218,
-19,
-133,
-44,
-203,
-230,
-24,
-99,
-78,
-49,
-198,
-172,
-105,
-228,
-190,
-79,
-200,
-178,
-44,
-228,
-136,
-108,
-145,
-49,
-102,
-101,
-99,
-204,
-22,
-198,
-152,
-101,
-140,
-140,
-181,
-151,
-100,
-89,
-118,
-71,
-64,
-219,
-132,
-30,
-225,
-10,
-128,
-51,
-140,
-76,
-178,
-101,
-141,
-49,
-135,
-213,
-180,
-251,
-137,
-145,
-1,
-125,
-179,
-49,
-230,
-175,
-158,
-122,
-155,
-81,
-40,
-200,
-218,
-204,
-24,
-51,
-75,
-255,
-250,
-194,
-28,
-197,
-228,
-21,
-83,
-152,
-216,
-201,
-181,
-142,
-49,
-198,
-32,
-75,
-232,
-99,
-140,
-49,
-75,
-26,
-99,
-246,
-203,
-178,
-172,
-24,
-74,
-202,
-78,
-218,
-251,
-61,
-188,
-174,
-214,
-191,
-161,
-89,
-100,
-172,
-64,
-242,
-153,
-81,
-199,
-20,
-114,
-3,
-200,
-178,
-236,
-19,
-89,
-142,
-111,
-7,
-182,
-153,
-145,
-101,
-217,
-58,
-89,
-150,
-45,
-147,
-101,
-217,
-74,
-89,
-150,
-189,
-61,
-203,
-178,
-59,
-3,
-251,
-151,
-208,
-35,
-158,
-18,
-0,
-89,
-150,
-205,
-53,
-198,
-124,
-220,
-24,
-179,
-208,
-24,
-179,
-43,
-21,
-105,
-143,
-140,
-49,
-187,
-25,
-99,
-230,
-26,
-99,
-62,
-146,
-101,
-217,
-66,
-15,
-223,
-25,
-250,
-119,
-57,
-79,
-157,
-15,
-85,
-95,
-199,
-152,
-188,
-98,
-10,
-19,
-59,
-249,
-236,
-196,
-217,
-215,
-200,
-228,
-59,
-47,
-203,
-50,
-95,
-54,
-88,
-75,
-119,
-165,
-167,
-174,
-237,
-234,
-107,
-192,
-175,
-222,
-196,
-21,
-114,
-9,
-139,
-57,
-70,
-68,
-94,
-201,
-178,
-236,
-28,
-99,
-204,
-123,
-141,
-49,
-79,
-24,
-99,
-118,
-49,
-198,
-76,
-193,
-73,
-123,
-100,
-100,
-201,
-185,
-171,
-49,
-230,
-65,
-99,
-204,
-142,
-89,
-150,
-149,
-125,
-101,
-218,
-46,
-105,
-125,
-95,
-199,
-152,
-188,
-98,
-10,
-147,
-127,
-232,
-223,
-29,
-16,
-141,
-243,
-119,
-140,
-8,
-150,
-189,
-139,
-132,
-1,
-91,
-166,
-54,
-171,
-175,
-27,
-77,
-46,
-56,
-92,
-196,
-20,
-114,
-227,
-2,
-136,
-157,
-197,
-41,
-148,
-28,
-143,
-33,
-217,
-129,
-254,
-136,
-39,
-100,
-151,
-214,
-23,
-209,
-58,
-200,
-40,
-18,
-196,
-117,
-111,
-224,
-31,
-192,
-125,
-136,
-237,
-197,
-52,
-228,
-136,
-239,
-135,
-56,
-14,
-113,
-37,
-237,
-59,
-185,
-168,
-211,
-209,
-249,
-203,
-50,
-233,
-148,
-246,
-136,
-184,
-10,
-197,
-152,
-188,
-98,
-158,
-116,
-44,
-67,
-158,
-196,
-209,
-42,
-210,
-6,
-142,
-4,
-149,
-182,
-54,
-83,
-44,
-205,
-146,
-78,
-206,
-162,
-228,
-152,
-139,
-136,
-199,
-185,
-227,
-5,
-58,
-232,
-209,
-231,
-252,
-101,
-224,
-6,
-125,
-39,
-147,
-145,
-99,
-189,
-83,
-181,
-222,
-39,
-48,
-125,
-199,
-138,
-173,
-130,
-140,
-34,
-169,
-207,
-111,
-119,
-218,
-77,
-69,
-20,
-159,
-55,
-146,
-91,
-38,
-86,
-230,
-112,
-164,
-163,
-139,
-58,
-29,
-157,
-191,
-162,
-128,
-136,
-121,
-212,
-35,
-243,
-138,
-38,
-76,
-180,
-126,
-123,
-231,
-197,
-78,
-7,
-54,
-45,
-212,
-55,
-202,
-20,
-75,
-120,
-210,
-201,
-109,
-43,
-120,
-68,
-19,
-114,
-49,
-64,
-216,
-241,
-226,
-234,
-192,
-33,
-136,
-127,
-195,
-92,
-202,
-225,
-245,
-55,
-64,
-162,
-232,
-252,
-202,
-161,
-187,
-29,
-17,
-162,
-147,
-157,
-178,
-83,
-40,
-113,
-55,
-118,
-104,
-90,
-7,
-25,
-5,
-94,
-64,
-46,
-124,
-255,
-11,
-108,
-83,
-168,
-95,
-11,
-137,
-16,
-84,
-155,
-48,
-148,
-14,
-46,
-234,
-68,
-112,
-254,
-234,
-12,
-34,
-230,
-81,
-143,
-204,
-43,
-154,
-48,
-81,
-154,
-103,
-146,
-219,
-3,
-128,
-56,
-108,
-220,
-197,
-160,
-197,
-93,
-112,
-166,
-88,
-6,
-87,
-95,
-11,
-201,
-133,
-204,
-69,
-212,
-251,
-40,
-68,
-21,
-114,
-129,
-60,
-90,
-135,
-144,
-215,
-251,
-181,
-95,
-205,
-219,
-129,
-99,
-128,
-163,
-129,
-91,
-157,
-231,
-119,
-55,
-226,
-33,
-87,
-122,
-239,
-228,
-246,
-242,
-199,
-49,
-210,
-97,
-201,
-90,
-28,
-126,
-161,
-162,
-173,
-69,
-171,
-32,
-163,
-74,
-99,
-45,
-16,
-175,
-37,
-66,
-204,
-126,
-58,
-186,
-168,
-143,
-58,
-136,
-152,
-71,
-61,
-22,
-47,
-34,
-10,
-19,
-165,
-57,
-70,
-105,
-14,
-71,
-246,
-138,
-255,
-209,
-151,
-22,
-37,
-83,
-172,
-115,
-29,
-43,
-184,
-102,
-2,
-149,
-186,
-16,
-34,
-11,
-185,
-192,
-254,
-29,
-71,
-203,
-16,
-242,
-192,
-79,
-245,
-250,
-255,
-194,
-49,
-224,
-65,
-246,
-237,
-103,
-107,
-93,
-109,
-48,
-76,
-100,
-245,
-48,
-3,
-88,
-190,
-80,
-158,
-33,
-1,
-54,
-7,
-220,
-130,
-29,
-26,
-139,
-86,
-65,
-70,
-201,
-45,
-63,
-33,
-32,
-136,
-232,
-132,
-1,
-17,
-243,
-168,
-199,
-226,
-69,
-92,
-193,
-180,
-2,
-146,
-66,
-189,
-215,
-220,
-121,
-200,
-18,
-215,
-46,
-103,
-47,
-5,
-158,
-94,
-65,
-27,
-85,
-200,
-5,
-246,
-175,
-117,
-8,
-121,
-114,
-147,
-224,
-29,
-61,
-117,
-111,
-214,
-186,
-255,
-5,
-244,
-97,
-54,
-37,
-201,
-57,
-144,
-85,
-209,
-204,
-138,
-182,
-22,
-173,
-130,
-140,
-34,
-43,
-22,
-40,
-49,
-227,
-29,
-22,
-144,
-109,
-198,
-65,
-136,
-192,
-155,
-129,
-8,
-247,
-255,
-34,
-65,
-74,
-26,
-101,
-75,
-50,
-192,
-243,
-145,
-101,
-213,
-165,
-200,
-87,
-109,
-46,
-98,
-111,
-125,
-35,
-98,
-6,
-250,
-57,
-28,
-39,
-138,
-10,
-62,
-209,
-242,
-168,
-199,
-226,
-69,
-68,
-193,
-52,
-44,
-32,
-49,
-16,
-173,
-91,
-241,
-5,
-84,
-36,
-153,
-32,
-162,
-144,
-11,
-236,
-91,
-107,
-231,
-20,
-242,
-61,
-255,
-102,
-158,
-186,
-205,
-180,
-110,
-150,
-175,
-109,
-129,
-246,
-118,
-68,
-219,
-62,
-32,
-28,
-17,
-13,
-252,
-109,
-21,
-109,
-67,
-4,
-64,
-105,
-144,
-81,
-157,
-112,
-0,
-223,
-173,
-235,
-103,
-9,
-239,
-5,
-250,
-111,
-243,
-10,
-154,
-45,
-108,
-39,
-75,
-234,
-95,
-69,
-110,
-101,
-57,
-11,
-9,
-117,
-126,
-13,
-249,
-202,
-229,
-30,
-42,
-2,
-210,
-184,
-140,
-150,
-71,
-150,
-116,
-118,
-223,
-185,
-0,
-89,
-94,
-93,
-142,
-104,
-87,
-109,
-148,
-88,
-232,
-224,
-49,
-53,
-218,
-32,
-162,
-96,
-26,
-22,
-16,
-51,
-95,
-27,
-101,
-168,
-50,
-172,
-58,
-227,
-68,
-200,
-145,
-231,
-196,
-27,
-176,
-68,
-36,
-79,
-206,
-225,
-59,
-210,
-45,
-210,
-218,
-40,
-58,
-199,
-48,
-210,
-149,
-214,
-78,
-220,
-210,
-12,
-63,
-206,
-243,
-168,
-18,
-0,
-165,
-65,
-70,
-157,
-231,
-252,
-209,
-186,
-126,
-118,
-184,
-126,
-169,
-0,
-64,
-20,
-125,
-246,
-68,
-234,
-199,
-56,
-66,
-16,
-153,
-207,
-214,
-235,
-241,
-14,
-10,
-91,
-164,
-34,
-163,
-21,
-201,
-195,
-33,
-61,
-12,
-124,
-134,
-194,
-210,
-1,
-89,
-98,
-110,
-143,
-68,
-62,
-45,
-93,
-138,
-38,
-244,
-3,
-96,
-23,
-2,
-61,
-240,
-232,
-81,
-200,
-21,
-132,
-72,
-41,
-159,
-170,
-129,
-171,
-245,
-214,
-49,
-104,
-50,
-78,
-0,
-77,
-36,
-169,
-198,
-127,
-237,
-164,
-174,
-233,
-75,
-230,
-240,
-1,
-249,
-96,
-157,
-236,
-180,
-135,
-138,
-175,
-115,
-224,
-4,
-44,
-13,
-50,
-74,
-67,
-103,
-174,
-150,
-215,
-175,
-18,
-0,
-214,
-255,
-165,
-204,
-147,
-48,
-67,
-20,
-211,
-0,
-159,
-173,
-234,
-136,
-117,
-150,
-185,
-135,
-228,
-168,
-145,
-80,
-1,
-70,
-162,
-42,
-225,
-103,
-157,
-0,
-88,
-93,
-39,
-44,
-136,
-128,
-186,
-65,
-133,
-129,
-221,
-26,
-76,
-193,
-73,
-217,
-85,
-194,
-227,
-56,
-165,
-253,
-13,
-162,
-140,
-189,
-17,
-89,
-6,
-223,
-164,
-191,
-109,
-236,
-127,
-239,
-185,
-122,
-224,
-4,
-252,
-168,
-210,
-12,
-4,
-25,
-37,
-63,
-254,
-251,
-112,
-85,
-63,
-43,
-120,
-119,
-21,
-0,
-151,
-106,
-213,
-167,
-42,
-218,
-127,
-86,
-105,
-46,
-40,
-35,
-120,
-137,
-211,
-145,
-237,
-189,
-68,
-9,
-9,
-10,
-29,
-39,
-139,
-16,
-101,
-211,
-92,
-10,
-49,
-7,
-28,
-186,
-74,
-1,
-160,
-52,
-171,
-146,
-123,
-125,
-46,
-64,
-244,
-18,
-55,
-35,
-231,
-230,
-171,
-5,
-244,
-229,
-173,
-192,
-31,
-40,
-183,
-4,
-92,
-22,
-73,
-178,
-234,
-141,
-242,
-27,
-56,
-1,
-171,
-130,
-140,
-90,
-219,
-139,
-218,
-4,
-174,
-29,
-174,
-95,
-37,
-0,
-108,
-44,
-132,
-82,
-215,
-108,
-224,
-141,
-101,
-2,
-204,
-18,
-28,
-166,
-4,
-215,
-182,
-185,
-137,
-16,
-208,
-33,
-149,
-23,
-49,
-76,
-28,
-19,
-162,
-193,
-25,
-180,
-223,
-210,
-191,
-139,
-86,
-90,
-155,
-0,
-0,
-32,
-0,
-73,
-68,
-65,
-84,
-222,
-140,
-196,
-129,
-2,
-224,
-215,
-136,
-206,
-105,
-167,
-254,
-122,
-92,
-142,
-192,
-9,
-88,
-21,
-100,
-212,
-218,
-94,
-84,
-166,
-18,
-239,
-120,
-253,
-42,
-1,
-96,
-149,
-195,
-85,
-39,
-86,
-175,
-84,
-154,
-1,
-119,
-116,
-75,
-96,
-247,
-254,
-223,
-111,
-115,
-19,
-33,
-160,
-67,
-42,
-47,
-122,
-48,
-113,
-108,
-34,
-144,
-234,
-94,
-18,
-178,
-207,
-178,
-3,
-225,
-34,
-156,
-56,
-243,
-139,
-35,
-156,
-231,
-241,
-108,
-242,
-0,
-40,
-3,
-105,
-189,
-3,
-5,
-192,
-44,
-228,
-200,
-106,
-83,
-106,
-50,
-3,
-247,
-129,
-128,
-119,
-91,
-25,
-100,
-20,
-120,
-175,
-214,
-45,
-4,
-158,
-23,
-251,
-250,
-74,
-83,
-37,
-0,
-108,
-164,
-160,
-170,
-24,
-150,
-219,
-41,
-205,
-64,
-64,
-154,
-34,
-147,
-221,
-155,
-222,
-64,
-8,
-232,
-152,
-202,
-139,
-30,
-76,
-28,
-105,
-32,
-144,
-2,
-6,
-137,
-53,
-104,
-249,
-175,
-237,
-99,
-5,
-143,
-78,
-138,
-51,
-15,
-253,
-174,
-74,
-94,
-155,
-89,
-55,
-128,
-215,
-55,
-156,
-126,
-174,
-82,
-65,
-103,
-177,
-62,
-185,
-130,
-236,
-6,
-10,
-203,
-240,
-144,
-123,
-97,
-164,
-25,
-175,
-139,
-25,
-136,
-113,
-85,
-109,
-134,
-223,
-46,
-168,
-122,
-183,
-4,
-4,
-25,
-69,
-140,
-150,
-172,
-53,
-227,
-165,
-64,
-168,
-179,
-89,
-237,
-245,
-29,
-154,
-42,
-1,
-112,
-145,
-86,
-149,
-42,
-248,
-144,
-99,
-123,
-128,
-139,
-203,
-8,
-236,
-50,
-194,
-171,
-201,
-44,
-121,
-65,
-193,
-241,
-210,
-137,
-148,
-202,
-43,
-22,
-104,
-40,
-144,
-106,
-6,
-137,
-53,
-55,
-189,
-3,
-40,
-117,
-171,
-45,
-60,
-186,
-214,
-138,
-179,
-2,
-173,
-59,
-248,
-158,
-164,
-194,
-62,
-32,
-128,
-151,
-107,
-107,
-0,
-97,
-2,
-96,
-83,
-253,
-125,
-158,
-254,
-254,
-92,
-129,
-174,
-78,
-9,
-248,
-2,
-68,
-121,
-103,
-147,
-97,
-62,
-162,
-255,
-30,
-103,
-100,
-98,
-149,
-248,
-113,
-240,
-6,
-239,
-165,
-117,
-144,
-81,
-36,
-196,
-184,
-85,
-92,
-94,
-173,
-109,
-151,
-40,
-208,
-108,
-4,
-236,
-27,
-114,
-125,
-15,
-77,
-149,
-0,
-176,
-153,
-150,
-188,
-222,
-185,
-140,
-60,
-5,
-248,
-82,
-217,
-5,
-172,
-34,
-225,
-35,
-37,
-245,
-151,
-56,
-255,
-174,
-45,
-235,
-204,
-120,
-1,
-13,
-5,
-82,
-217,
-75,
-34,
-15,
-142,
-249,
-32,
-37,
-138,
-176,
-2,
-143,
-40,
-138,
-51,
-135,
-246,
-51,
-74,
-106,
-99,
-244,
-253,
-40,
-228,
-126,
-60,
-124,
-150,
-67,
-180,
-230,
-247,
-146,
-159,
-41,
-135,
-8,
-128,
-23,
-235,
-239,
-23,
-35,
-10,
-188,
-199,
-113,
-194,
-164,
-215,
-12,
-220,
-237,
-17,
-205,
-255,
-21,
-192,
-11,
-61,
-245,
-43,
-146,
-39,
-30,
-237,
-197,
-89,
-169,
-112,
-47,
-93,
-131,
-140,
-190,
-9,
-57,
-102,
-181,
-120,
-20,
-49,
-198,
-185,
-66,
-199,
-90,
-217,
-115,
-240,
-142,
-173,
-2,
-77,
-213,
-115,
-92,
-158,
-252,
-35,
-240,
-115,
-156,
-179,
-126,
-125,
-175,
-246,
-136,
-244,
-94,
-74,
-86,
-167,
-6,
-152,
-164,
-68,
-7,
-4,
-220,
-104,
-163,
-37,
-106,
-27,
-32,
-103,
-216,
-118,
-223,
-95,
-154,
-117,
-6,
-217,
-159,
-129,
-76,
-168,
-129,
-248,
-252,
-17,
-251,
-51,
-240,
-146,
-144,
-189,
-223,
-66,
-228,
-203,
-235,
-205,
-250,
-83,
-194,
-227,
-91,
-250,
-183,
-181,
-226,
-76,
-233,
-86,
-68,
-4,
-207,
-253,
-200,
-82,
-245,
-106,
-228,
-75,
-245,
-172,
-22,
-247,
-247,
-11,
-189,
-228,
-62,
-206,
-96,
-13,
-17,
-0,
-238,
-243,
-56,
-82,
-203,
-142,
-114,
-202,
-170,
-6,
-174,
-61,
-254,
-219,
-164,
-226,
-58,
-171,
-42,
-77,
-111,
-238,
-172,
-12,
-162,
-85,
-144,
-81,
-229,
-181,
-18,
-226,
-130,
-124,
-62,
-178,
-181,
-156,
-175,
-255,
-30,
-68,
-44,
-56,
-7,
-188,
-52,
-125,
-207,
-210,
-67,
-83,
-183,
-146,
-122,
-33,
-185,
-11,
-243,
-108,
-68,
-240,
-216,
-241,
-128,
-94,
-191,
-60,
-2,
-51,
-249,
-126,
-216,
-191,
-71,
-8,
-236,
-12,
-121,
-134,
-84,
-128,
-15,
-86,
-240,
-120,
-151,
-210,
-60,
-89,
-54,
-208,
-200,
-205,
-85,
-171,
-150,
-203,
-7,
-41,
-205,
-169,
-101,
-52,
-49,
-80,
-124,
-73,
-136,
-82,
-101,
-46,
-34,
-164,
-182,
-109,
-200,
-163,
-179,
-226,
-76,
-233,
-236,
-209,
-212,
-167,
-244,
-247,
-219,
-245,
-247,
-145,
-13,
-239,
-109,
-7,
-109,
-247,
-111,
-196,
-239,
-192,
-42,
-70,
-155,
-10,
-128,
-53,
-144,
-21,
-192,
-83,
-102,
-173,
-53,
-99,
-197,
-46,
-153,
-253,
-95,
-37,
-243,
-212,
-22,
-1,
-96,
-177,
-141,
-31,
-232,
-60,
-239,
-82,
-171,
-76,
-224,
-13,
-74,
-227,
-11,
-78,
-99,
-105,
-86,
-65,
-236,
-254,
-255,
-139,
-40,
-85,
-103,
-34,
-102,
-202,
-223,
-163,
-238,
-227,
-232,
-92,
-0,
-106,
-150,
-197,
-117,
-3,
-148,
-60,
-67,
-170,
-215,
-57,
-67,
-105,
-46,
-86,
-154,
-3,
-43,
-104,
-182,
-81,
-26,
-111,
-230,
-89,
-100,
-159,
-102,
-67,
-96,
-15,
-76,
-36,
-165,
-137,
-178,
-146,
-112,
-7,
-60,
-226,
-170,
-57,
-29,
-249,
-250,
-15,
-36,
-113,
-168,
-184,
-134,
-69,
-12,
-197,
-217,
-154,
-218,
-135,
-187,
-112,
-252,
-220,
-17,
-201,
-63,
-143,
-64,
-67,
-46,
-196,
-16,
-231,
-126,
-229,
-181,
-161,
-150,
-89,
-115,
-239,
-70,
-2,
-64,
-203,
-173,
-178,
-233,
-124,
-253,
-253,
-162,
-178,
-123,
-33,
-223,
-95,
-123,
-93,
-117,
-145,
-252,
-5,
-151,
-43,
-205,
-183,
-67,
-238,
-103,
-60,
-130,
-124,
-245,
-253,
-241,
-10,
-26,
-155,
-197,
-168,
-116,
-78,
-197,
-232,
-200,
-191,
-157,
-65,
-89,
-234,
-74,
-90,
-55,
-64,
-25,
-185,
-10,
-24,
-8,
-195,
-68,
-158,
-108,
-114,
-58,
-53,
-74,
-43,
-100,
-95,
-10,
-254,
-0,
-31,
-246,
-203,
-53,
-133,
-138,
-227,
-35,
-34,
-172,
-36,
-156,
-1,
-191,
-3,
-185,
-208,
-241,
-133,
-247,
-170,
-186,
-23,
-139,
-78,
-138,
-51,
-165,
-177,
-246,
-221,
-123,
-22,
-202,
-173,
-253,
-124,
-80,
-54,
-89,
-114,
-47,
-183,
-61,
-156,
-50,
-171,
-124,
-107,
-35,
-0,
-150,
-210,
-241,
-3,
-240,
-30,
-36,
-194,
-141,
-247,
-94,
-16,
-197,
-153,
-93,
-162,
-254,
-27,
-217,
-171,
-254,
-16,
-248,
-37,
-162,
-217,
-182,
-10,
-201,
-83,
-41,
-9,
-230,
-177,
-56,
-128,
-60,
-148,
-252,
-85,
-248,
-79,
-25,
-50,
-242,
-172,
-65,
-223,
-235,
-179,
-35,
-27,
-146,
-31,
-7,
-222,
-141,
-56,
-64,
-12,
-228,
-109,
-67,
-60,
-143,
-234,
-6,
-168,
-93,
-5,
-252,
-203,
-83,
-103,
-39,
-100,
-173,
-194,
-10,
-248,
-130,
-210,
-14,
-4,
-192,
-68,
-60,
-221,
-160,
-230,
-248,
-139,
-56,
-43,
-9,
-139,
-251,
-116,
-130,
-44,
-212,
-191,
-193,
-137,
-49,
-28,
-30,
-173,
-21,
-103,
-90,
-191,
-33,
-242,
-149,
-190,
-181,
-120,
-63,
-206,
-96,
-89,
-72,
-141,
-247,
-23,
-185,
-121,
-235,
-31,
-11,
-229,
-22,
-141,
-5,
-128,
-214,
-89,
-55,
-222,
-41,
-228,
-57,
-0,
-203,
-238,
-101,
-19,
-100,
-251,
-121,
-51,
-34,
-12,
-22,
-32,
-219,
-194,
-73,
-136,
-99,
-207,
-152,
-241,
-200,
-236,
-11,
-136,
-223,
-131,
-13,
-44,
-115,
-56,
-206,
-156,
-67,
-244,
-60,
-86,
-183,
-242,
-8,
-53,
-102,
-209,
-49,
-58,
-243,
-60,
-242,
-37,
-9,
-58,
-208,
-110,
-38,
-207,
-229,
-126,
-47,
-206,
-241,
-76,
-5,
-31,
-119,
-21,
-176,
-165,
-83,
-190,
-14,
-34,
-217,
-103,
-81,
-227,
-43,
-174,
-244,
-171,
-35,
-75,
-248,
-249,
-56,
-171,
-18,
-68,
-57,
-52,
-71,
-7,
-250,
-122,
-1,
-124,
-58,
-173,
-36,
-156,
-231,
-49,
-21,
-73,
-189,
-101,
-87,
-12,
-247,
-16,
-232,
-107,
-237,
-155,
-52,
-52,
-84,
-156,
-105,
-189,
-141,
-80,
-227,
-77,
-37,
-134,
-228,
-5,
-4,
-143,
-208,
-116,
-104,
-214,
-215,
-65,
-119,
-63,
-133,
-85,
-152,
-211,
-207,
-86,
-2,
-64,
-235,
-255,
-162,
-245,
-7,
-215,
-141,
-149,
-97,
-129,
-6,
-49,
-15,
-128,
-79,
-59,
-247,
-88,
-233,
-121,
-25,
-3,
-58,
-166,
-108,
-112,
-22,
-87,
-137,
-103,
-221,
-121,
-31,
-167,
-16,
-102,
-172,
-207,
-206,
-44,
-1,
-188,
-31,
-89,
-122,
-77,
-33,
-151,
-204,
-51,
-144,
-227,
-134,
-115,
-244,
-197,
-122,
-163,
-172,
-58,
-124,
-236,
-42,
-192,
-205,
-40,
-107,
-7,
-196,
-79,
-27,
-244,
-231,
-183,
-218,
-102,
-63,
-167,
-236,
-83,
-90,
-118,
-118,
-85,
-91,
-135,
-190,
-211,
-74,
-194,
-25,
-12,
-175,
-210,
-223,
-75,
-147,
-71,
-112,
-13,
-50,
-70,
-242,
-77,
-26,
-154,
-43,
-206,
-182,
-68,
-4,
-240,
-13,
-148,
-11,
-171,
-140,
-92,
-136,
-15,
-28,
-95,
-233,
-251,
-189,
-72,
-249,
-248,
-148,
-144,
-22,
-93,
-4,
-192,
-198,
-228,
-74,
-82,
-239,
-189,
-244,
-1,
-58,
-132,
-39,
-115,
-120,
-188,
-72,
-199,
-250,
-52,
-253,
-55,
-3,
-120,
-65,
-191,
-61,
-55,
-6,
-217,
-46,
-253,
-28,
-57,
-29,
-153,
-173,
-215,
-189,
-30,
-217,
-34,
-4,
-127,
-249,
-233,
-24,
-89,
-56,
-26,
-200,
-87,
-1,
-11,
-144,
-101,
-235,
-242,
-200,
-249,
-234,
-28,
-224,
-217,
-13,
-248,
-216,
-60,
-238,
-215,
-59,
-101,
-246,
-38,
-223,
-27,
-200,
-163,
-211,
-74,
-162,
-100,
-242,
-110,
-66,
-46,
-181,
-107,
-61,
-193,
-202,
-38,
-13,
-205,
-20,
-103,
-255,
-12,
-185,
-111,
-100,
-255,
-13,
-112,
-174,
-167,
-206,
-250,
-200,
-123,
-67,
-144,
-59,
-253,
-108,
-45,
-0,
-148,
-230,
-71,
-14,
-221,
-176,
-4,
-192,
-113,
-180,
-12,
-79,
-166,
-237,
-215,
-66,
-162,
-20,
-77,
-3,
-94,
-13,
-188,
-14,
-153,
-136,
-119,
-16,
-176,
-98,
-29,
-11,
-160,
-99,
-100,
-225,
-216,
-157,
-177,
-171,
-128,
-35,
-200,
-151,
-85,
-71,
-213,
-183,
-28,
-224,
-99,
-61,
-174,
-94,
-138,
-216,
-140,
-131,
-196,
-44,
-8,
-86,
-14,
-209,
-97,
-37,
-81,
-54,
-224,
-201,
-181,
-179,
-79,
-226,
-248,
-179,
-55,
-228,
-17,
-172,
-56,
-139,
-1,
-242,
-227,
-183,
-91,
-116,
-114,
-20,
-255,
-89,
-88,
-215,
-92,
-95,
-88,
-116,
-239,
-189,
-20,
-104,
-86,
-162,
-194,
-0,
-166,
-15,
-208,
-33,
-60,
-153,
-182,
-185,
-10,
-89,
-245,
-190,
-216,
-41,
-123,
-41,
-114,
-218,
-226,
-203,
-196,
-52,
-38,
-65,
-135,
-200,
-194,
-177,
-59,
-98,
-87,
-1,
-179,
-244,
-193,
-206,
-175,
-155,
-40,
-37,
-124,
-172,
-185,
-227,
-129,
-228,
-246,
-234,
-63,
-110,
-200,
-163,
-245,
-74,
-162,
-106,
-192,
-3,
-103,
-105,
-221,
-37,
-84,
-236,
-51,
-107,
-120,
-4,
-43,
-206,
-186,
-130,
-22,
-232,
-163,
-31,
-37,
-125,
-235,
-20,
-215,
-142,
-14,
-225,
-201,
-22,
-55,
-48,
-86,
-34,
-11,
-147,
-175,
-2,
-0,
-126,
-221,
-146,
-199,
-106,
-200,
-190,
-200,
-42,
-35,
-161,
-197,
-190,
-140,
-150,
-43,
-137,
-154,
-201,
-187,
-38,
-249,
-146,
-235,
-235,
-109,
-120,
-104,
-253,
-152,
-80,
-156,
-57,
-253,
-44,
-221,
-2,
-244,
-116,
-221,
-56,
-113,
-237,
-18,
-226,
-129,
-14,
-62,
-252,
-14,
-143,
-85,
-156,
-65,
-245,
-234,
-14,
-125,
-57,
-17,
-57,
-149,
-88,
-4,
-92,
-214,
-146,
-71,
-171,
-149,
-68,
-192,
-228,
-125,
-155,
-214,
-207,
-167,
-100,
-201,
-21,
-192,
-99,
-84,
-20,
-103,
-158,
-126,
-12,
-93,
-0,
-16,
-41,
-174,
-29,
-221,
-87,
-16,
-209,
-34,
-235,
-34,
-167,
-103,
-181,
-122,
-135,
-26,
-30,
-157,
-231,
-95,
-39,
-208,
-193,
-135,
-191,
-192,
-167,
-114,
-240,
-7,
-242,
-216,
-202,
-225,
-243,
-177,
-150,
-60,
-90,
-173,
-36,
-66,
-250,
-143,
-232,
-57,
-64,
-246,
-214,
-3,
-131,
-52,
-144,
-199,
-208,
-21,
-103,
-158,
-62,
-140,
-134,
-0,
-232,
-28,
-215,
-142,
-142,
-43,
-136,
-174,
-237,
-61,
-252,
-126,
-5,
-124,
-38,
-148,
-190,
-132,
-71,
-163,
-249,
-71,
-228,
-208,
-224,
-157,
-124,
-248,
-11,
-188,
-106,
-7,
-127,
-0,
-15,
-187,
-55,
-158,
-142,
-199,
-64,
-169,
-1,
-159,
-206,
-43,
-137,
-150,
-215,
-13,
-17,
-0,
-67,
-87,
-156,
-121,
-250,
-208,
-73,
-0,
-208,
-34,
-65,
-38,
-29,
-227,
-218,
-209,
-113,
-5,
-209,
-181,
-125,
-31,
-104,
-58,
-255,
-136,
-189,
-133,
-34,
-162,
-15,
-127,
-36,
-1,
-96,
-253,
-238,
-143,
-237,
-216,
-151,
-206,
-43,
-137,
-4,
-63,
-104,
-153,
-32,
-147,
-142,
-113,
-237,
-232,
-184,
-130,
-232,
-218,
-190,
-15,
-52,
-153,
-127,
-99,
-81,
-128,
-21,
-59,
-216,
-73,
-0,
-32,
-71,
-101,
-119,
-42,
-143,
-114,
-183,
-198,
-48,
-94,
-81,
-86,
-18,
-9,
-35,
-65,
-135,
-4,
-153,
-116,
-140,
-107,
-71,
-247,
-21,
-68,
-140,
-21,
-72,
-40,
-46,
-41,
-187,
-70,
-91,
-208,
-82,
-128,
-141,
-139,
-35,
-19,
-68,
-67,
-127,
-168,
-49,
-102,
-125,
-99,
-204,
-133,
-89,
-150,
-117,
-61,
-143,
-181,
-38,
-180,
-167,
-100,
-89,
-54,
-163,
-35,
-175,
-4,
-35,
-3,
-204,
-24,
-115,
-130,
-49,
-102,
-101,
-99,
-204,
-117,
-198,
-152,
-173,
-179,
-44,
-27,
-225,
-186,
-154,
-101,
-217,
-131,
-198,
-24,
-111,
-10,
-117,
-99,
-204,
-52,
-99,
-204,
-106,
-198,
-152,
-42,
-129,
-188,
-162,
-67,
-91,
-132,
-205,
-204,
-124,
-99,
-69,
-123,
-123,
-252,
-235,
-91,
-6,
-119,
-109,
-191,
-192,
-24,
-19,
-154,
-26,
-172,
-52,
-79,
-97,
-7,
-216,
-128,
-170,
-222,
-116,
-112,
-89,
-150,
-129,
-56,
-136,
-189,
-220,
-24,
-243,
-110,
-99,
-204,
-207,
-70,
-16,
-16,
-33,
-61,
-81,
-21,
-28,
-233,
-23,
-180,
-2,
-64,
-246,
-194,
-215,
-171,
-212,
-178,
-251,
-154,
-39,
-232,
-152,
-175,
-128,
-136,
-43,
-137,
-132,
-28,
-116,
-76,
-144,
-73,
-199,
-184,
-118,
-116,
-95,
-65,
-116,
-143,
-172,
-27,
-1,
-180,
-84,
-226,
-209,
-53,
-52,
-120,
-200,
-4,
-237,
-34,
-0,
-154,
-2,
-73,
-188,
-121,
-47,
-185,
-2,
-233,
-76,
-2,
-114,
-17,
-214,
-240,
-92,
-134,
-60,
-60,
-210,
-5,
-145,
-186,
-106,
-121,
-23,
-49,
-23,
-217,
-147,
-253,
-3,
-248,
-24,
-53,
-6,
-42,
-228,
-129,
-39,
-75,
-51,
-225,
-146,
-251,
-51,
-84,
-126,
-105,
-104,
-17,
-66,
-189,
-235,
-251,
-167,
-99,
-130,
-76,
-58,
-198,
-181,
-163,
-99,
-100,
-220,
-174,
-237,
-99,
-128,
-14,
-74,
-60,
-186,
-10,
-176,
-174,
-3,
-96,
-172,
-130,
-158,
-86,
-18,
-158,
-235,
-88,
-216,
-184,
-114,
-87,
-58,
-215,
-3,
-9,
-128,
-82,
-26,
-45,
-150,
-220,
-142,
-224,
-94,
-252,
-57,
-232,
-151,
-32,
-87,
-174,
-13,
-228,
-209,
-43,
-208,
-54,
-14,
-161,
-222,
-245,
-253,
-211,
-61,
-65,
-102,
-167,
-184,
-118,
-116,
-95,
-65,
-116,
-143,
-172,
-59,
-72,
-255,
-107,
-2,
-143,
-1,
-233,
-126,
-138,
-209,
-77,
-128,
-117,
-29,
-0,
-99,
-21,
-244,
-176,
-146,
-40,
-185,
-206,
-192,
-243,
-67,
-38,
-237,
-174,
-228,
-19,
-242,
-59,
-21,
-237,
-109,
-30,
-123,
-240,
-231,
-160,
-183,
-2,
-226,
-22,
-106,
-98,
-231,
-211,
-34,
-132,
-122,
-215,
-247,
-79,
-199,
-4,
-153,
-202,
-163,
-117,
-92,
-59,
-186,
-175,
-32,
-186,
-71,
-214,
-29,
-108,
-115,
-51,
-112,
-116,
-32,
-109,
-215,
-83,
-140,
-110,
-2,
-172,
-235,
-0,
-152,
-232,
-168,
-122,
-126,
-192,
-207,
-180,
-174,
-74,
-193,
-100,
-128,
-15,
-41,
-221,
-149,
-158,
-186,
-127,
-104,
-221,
-39,
-98,
-246,
-219,
-225,
-223,
-233,
-253,
-211,
-49,
-65,
-166,
-195,
-167,
-85,
-92,
-59,
-186,
-175,
-32,
-186,
-71,
-214,
-237,
-118,
-223,
-93,
-79,
-33,
-186,
-9,
-176,
-174,
-3,
-192,
-211,
-153,
-115,
-129,
-29,
-156,
-178,
-231,
-33,
-174,
-154,
-222,
-32,
-22,
-227,
-29,
-85,
-207,
-15,
-137,
-173,
-0,
-48,
-167,
-134,
-135,
-171,
-160,
-220,
-202,
-41,
-223,
-4,
-49,
-90,
-122,
-136,
-158,
-50,
-50,
-119,
-125,
-255,
-116,
-76,
-144,
-25,
-3,
-116,
-140,
-140,
-219,
-181,
-125,
-199,
-190,
-119,
-181,
-131,
-232,
-38,
-192,
-186,
-14,
-128,
-2,
-221,
-1,
-228,
-246,
-203,
-23,
-35,
-89,
-135,
-23,
-34,
-231,
-238,
-223,
-174,
-106,
-235,
-240,
-24,
-106,
-68,
-150,
-174,
-168,
-122,
-126,
-72,
-104,
-105,
-0,
-223,
-241,
-85,
-145,
-214,
-222,
-247,
-31,
-157,
-50,
-251,
-242,
-170,
-2,
-150,
-116,
-58,
-197,
-233,
-250,
-254,
-233,
-152,
-32,
-51,
-22,
-232,
-18,
-25,
-55,
-66,
-251,
-14,
-253,
-238,
-124,
-10,
-65,
-23,
-1,
-214,
-117,
-0,
-120,
-104,
-119,
-33,
-247,
-59,
-7,
-177,
-189,
-175,
-205,
-244,
-170,
-109,
-71,
-37,
-34,
-75,
-23,
-84,
-61,
-63,
-36,
-200,
-37,
-4,
-68,
-47,
-66,
-226,
-251,
-63,
-132,
-8,
-204,
-231,
-34,
-49,
-225,
-166,
-233,
-75,
-172,
-90,
-2,
-119,
-157,
-192,
-93,
-219,
-119,
-74,
-144,
-57,
-209,
-65,
-164,
-83,
-8,
-218,
-10,
-176,
-88,
-2,
-0,
-216,
-131,
-60,
-28,
-213,
-125,
-136,
-115,
-203,
-44,
-100,
-9,
-91,
-27,
-189,
-135,
-150,
-17,
-89,
-136,
-247,
-5,
-12,
-66,
-69,
-251,
-162,
-18,
-112,
-119,
-68,
-186,
-47,
-162,
-66,
-186,
-23,
-120,
-89,
-147,
-231,
-159,
-144,
-103,
-254,
-169,
-140,
-236,
-210,
-245,
-253,
-69,
-184,
-255,
-78,
-9,
-50,
-39,
-58,
-232,
-225,
-20,
-34,
-4,
-125,
-88,
-2,
-46,
-105,
-140,
-153,
-103,
-140,
-217,
-205,
-136,
-165,
-221,
-124,
-36,
-212,
-213,
-89,
-198,
-152,
-223,
-0,
-87,
-102,
-89,
-54,
-165,
-162,
-253,
-95,
-141,
-49,
-153,
-49,
-102,
-171,
-44,
-203,
-38,
-25,
-99,
-12,
-176,
-181,
-49,
-230,
-116,
-173,
-43,
-219,
-131,
-217,
-64,
-28,
-3,
-97,
-149,
-3,
-225,
-211,
-190,
-190,
-86,
-255,
-94,
-103,
-140,
-153,
-25,
-200,
-231,
-56,
-96,
-166,
-49,
-102,
-89,
-99,
-204,
-6,
-70,
-172,
-219,
-102,
-24,
-99,
-246,
-200,
-178,
-204,
-171,
-160,
-241,
-224,
-23,
-198,
-152,
-47,
-25,
-99,
-62,
-102,
-140,
-121,
-208,
-24,
-179,
-200,
-24,
-211,
-40,
-248,
-73,
-7,
-84,
-221,
-235,
-242,
-198,
-152,
-50,
-1,
-115,
-134,
-49,
-230,
-14,
-35,
-247,
-124,
-28,
-176,
-125,
-150,
-101,
-179,
-122,
-232,
-223,
-226,
-138,
-63,
-25,
-99,
-94,
-103,
-140,
-249,
-160,
-41,
-90,
-233,
-25,
-81,
-226,
-105,
-157,
-49,
-198,
-252,
-37,
-250,
-213,
-187,
-126,
-65,
-2,
-248,
-31,
-170,
-77,
-91,
-103,
-243,
-173,
-225,
-31,
-189,
-255,
-33,
-60,
-61,
-180,
-69,
-60,
-66,
-96,
-96,
-70,
-242,
-48,
-221,
-85,
-240,
-234,
-67,
-186,
-222,
-127,
-140,
-231,
-71,
-135,
-4,
-153,
-19,
-29,
-140,
-242,
-41,
-132,
-33,
-82,
-122,
-162,
-138,
-182,
-171,
-144,
-159,
-21,
-15,
-229,
-28,
-222,
-67,
-51,
-12,
-1,
-224,
-110,
-1,
-206,
-215,
-178,
-61,
-170,
-218,
-58,
-244,
-59,
-50,
-50,
-9,
-171,
-197,
-181,
-78,
-153,
-55,
-19,
-81,
-215,
-251,
-143,
-245,
-252,
-104,
-153,
-32,
-179,
-41,
-144,
-60,
-123,
-219,
-118,
-228,
-241,
-44,
-228,
-136,
-246,
-118,
-196,
-86,
-227,
-17,
-36,
-188,
-155,
-55,
-55,
-132,
-182,
-9,
-70,
-139,
-254,
-140,
-218,
-41,
-132,
-33,
-82,
-122,
-34,
-224,
-53,
-136,
-214,
-255,
-110,
-228,
-107,
-48,
-93,
-95,
-254,
-231,
-145,
-68,
-15,
-0,
-159,
-247,
-180,
-27,
-85,
-45,
-118,
-9,
-125,
-45,
-207,
-42,
-90,
-224,
-37,
-200,
-158,
-248,
-65,
-90,
-72,
-237,
-174,
-215,
-247,
-208,
-12,
-229,
-249,
-209,
-34,
-65,
-102,
-83,
-144,
-107,
-205,
-91,
-9,
-2,
-196,
-215,
-222,
-42,
-222,
-166,
-33,
-147,
-237,
-86,
-231,
-57,
-120,
-141,
-182,
-24,
-41,
-160,
-203,
-254,
-61,
-25,
-58,
-198,
-60,
-252,
-71,
-229,
-20,
-194,
-16,
-33,
-61,
-17,
-240,
-85,
-242,
-164,
-33,
-211,
-148,
-151,
-43,
-193,
-30,
-208,
-191,
-255,
-240,
-180,
-29,
-51,
-3,
-184,
-9,
-207,
-58,
-90,
-36,
-42,
-12,
-192,
-192,
-190,
-206,
-195,
-99,
-92,
-111,
-1,
-74,
-218,
-188,
-4,
-249,
-154,
-109,
-90,
-79,
-29,
-14,
-196,
-165,
-251,
-23,
-228,
-99,
-43,
-88,
-16,
-32,
-2,
-234,
-30,
-109,
-247,
-45,
-70,
-230,
-86,
-220,
-1,
-249,
-104,
-65,
-131,
-172,
-79,
-5,
-254,
-151,
-52,
-121,
-70,
-99,
-2,
-116,
-76,
-79,
-68,
-126,
-68,
-177,
-200,
-243,
-80,
-159,
-142,
-8,
-7,
-139,
-123,
-60,
-237,
-199,
-220,
-0,
-14,
-225,
-89,
-71,
-11,
-60,
-83,
-7,
-212,
-2,
-60,
-145,
-112,
-10,
-180,
-227,
-126,
-11,
-224,
-105,
-243,
-7,
-29,
-19,
-231,
-19,
-89,
-8,
-40,
-255,
-53,
-17,
-239,
-57,
-107,
-136,
-84,
-43,
-8,
-128,
-47,
-42,
-173,
-55,
-115,
-18,
-240,
-93,
-173,
-255,
-83,
-203,
-62,
-141,
-63,
-1,
-96,
-204,
-83,
-3,
-176,
-85,
-122,
-34,
-242,
-208,
-216,
-165,
-81,
-127,
-129,
-19,
-44,
-111,
-79,
-221,
-152,
-27,
-192,
-33,
-60,
-67,
-104,
-129,
-175,
-105,
-221,
-69,
-33,
-215,
-141,
-125,
-125,
-135,
-102,
-52,
-4,
-192,
-187,
-17,
-223,
-4,
-128,
-107,
-67,
-219,
-53,
-5,
-242,
-85,
-223,
-159,
-124,
-149,
-89,
-42,
-8,
-128,
-11,
-149,
-198,
-107,
-181,
-136,
-232,
-49,
-0,
-166,
-182,
-236,
-203,
-248,
-20,
-0,
-198,
-24,
-67,
-203,
-244,
-68,
-72,
-104,
-109,
-128,
-247,
-87,
-208,
-188,
-85,
-105,
-230,
-122,
-234,
-198,
-220,
-0,
-142,
-53,
-1,
-145,
-21,
-208,
-93,
-90,
-255,
-65,
-95,
-251,
-62,
-175,
-239,
-208,
-12,
-93,
-0,
-56,
-109,
-47,
-5,
-158,
-104,
-218,
-174,
-197,
-117,
-150,
-5,
-62,
-129,
-56,
-67,
-129,
-223,
-110,
-222,
-245,
-210,
-172,
-194,
-194,
-150,
-125,
-24,
-55,
-2,
-96,
-192,
-14,
-32,
-203,
-178,
-59,
-141,
-49,
-109,
-76,
-111,
-173,
-146,
-235,
-222,
-10,
-154,
-39,
-245,
-239,
-99,
-45,
-248,
-143,
-91,
-100,
-89,
-54,
-27,
-241,
-243,
-255,
-157,
-49,
-230,
-71,
-192,
-153,
-197,
-104,
-57,
-17,
-48,
-211,
-200,
-57,
-125,
-85,
-228,
-87,
-107,
-137,
-57,
-148,
-40,
-72,
-136,
-99,
-16,
-70,
-108,
-7,
-182,
-52,
-198,
-252,
-97,
-24,
-215,
-213,
-107,
-90,
-248,
-140,
-146,
-236,
-88,
-253,
-175,
-233,
-231,
-89,
-124,
-222,
-24,
-51,
-16,
-80,
-213,
-17,
-10,
-27,
-103,
-89,
-118,
-91,
-27,
-198,
-192,
-134,
-198,
-152,
-111,
-24,
-99,
-182,
-55,
-198,
-172,
-110,
-196,
-78,
-228,
-76,
-99,
-204,
-1,
-89,
-150,
-61,
-220,
-174,
-187,
-17,
-64,
-190,
-244,
-218,
-165,
-130,
-230,
-195,
-74,
-243,
-119,
-79,
-221,
-152,
-251,
-130,
-133,
-240,
-28,
-43,
-32,
-210,
-41,
-78,
-228,
-62,
-205,
-64,
-180,
-245,
-83,
-144,
-227,
-182,
-222,
-130,
-81,
-34,
-91,
-128,
-47,
-57,
-227,
-112,
-10,
-176,
-15,
-176,
-172,
-135,
-214,
-58,
-222,
-148,
-154,
-221,
-246,
-212,
-71,
-139,
-141,
-90,
-182,
-127,
-41,
-185,
-158,
-110,
-6,
-146,
-241,
-218,
-42,
-65,
-239,
-35,
-32,
-75,
-118,
-111,
-32,
-79,
-89,
-253,
-199,
-10,
-154,
-191,
-41,
-205,
-94,
-158,
-186,
-174,
-2,
-32,
-186,
-29,
-195,
-56,
-19,
-0,
-157,
-79,
-113,
-198,
-35,
-16,
-37,
-224,
-247,
-200,
-109,
-76,
-110,
-70,
-204,
-175,
-75,
-173,
-92,
-201,
-93,
-111,
-191,
-48,
-228,
-190,
-182,
-22,
-0,
-136,
-89,
-185,
-77,
-113,
-127,
-2,
-42,
-76,
-129,
-149,
-17,
-69,
-43,
-104,
-114,
-217,
-81,
-1,
-114,
-220,
-99,
-207,
-102,
-191,
-138,
-35,
-121,
-145,
-125,
-217,
-119,
-156,
-23,
-52,
-224,
-210,
-26,
-65,
-0,
-68,
-255,
-2,
-142,
-51,
-1,
-208,
-233,
-20,
-103,
-188,
-1,
-57,
-6,
-252,
-57,
-249,
-23,
-112,
-18,
-226,
-118,
-93,
-25,
-44,
-69,
-219,
-238,
-167,
-109,
-174,
-199,
-19,
-125,
-169,
-47,
-116,
-20,
-0,
-111,
-215,
-182,
-247,
-2,
-79,
-43,
-212,
-45,
-79,
-158,
-154,
-238,
-85,
-49,
-59,
-124,
-24,
-13,
-98,
-160,
-3,
-31,
-32,
-63,
-49,
-152,
-129,
-156,
-32,
-92,
-77,
-254,
-117,
-190,
-7,
-120,
-97,
-73,
-219,
-174,
-2,
-32,
-250,
-23,
-112,
-60,
-9,
-0,
-99,
-186,
-157,
-226,
-140,
-55,
-144,
-127,
-108,
-174,
-4,
-222,
-233,
-123,
-231,
-21,
-109,
-87,
-64,
-182,
-8,
-32,
-17,
-162,
-54,
-44,
-212,
-63,
-7,
-81,
-36,
-238,
-80,
-198,
-163,
-101,
-159,
-187,
-8,
-0,
-43,
-192,
-189,
-246,
-36,
-228,
-89,
-169,
-126,
-208,
-189,
-167,
-57,
-83,
-104,
-24,
-195,
-28,
-9,
-252,
-113,
-4,
-249,
-41,
-130,
-141,
-106,
-250,
-29,
-186,
-231,
-155,
-175,
-18,
-0,
-209,
-191,
-128,
-93,
-5,
-0,
-34,
-248,
-162,
-41,
-153,
-144,
-124,
-134,
-223,
-167,
-58,
-55,
-94,
-171,
-83,
-156,
-241,
-6,
-196,
-123,
-238,
-205,
-29,
-218,
-111,
-70,
-126,
-50,
-3,
-242,
-5,
-157,
-66,
-110,
-4,
-4,
-145,
-227,
-80,
-56,
-124,
-159,
-131,
-28,
-143,
-90,
-171,
-65,
-155,
-190,
-252,
-45,
-21,
-109,
-255,
-163,
-109,
-119,
-43,
-169,
-223,
-93,
-235,
-207,
-139,
-221,
-225,
-232,
-73,
-12,
-74,
-174,
-213,
-121,
-15,
-79,
-228,
-47,
-96,
-4,
-1,
-112,
-59,
-208,
-72,
-219,
-203,
-96,
-88,
-232,
-39,
-245,
-30,
-190,
-133,
-44,
-119,
-103,
-0,
-207,
-106,
-211,
-159,
-190,
-129,
-68,
-93,
-62,
-7,
-103,
-27,
-230,
-43,
-107,
-200,
-115,
-91,
-34,
-71,
-112,
-118,
-120,
-175,
-12,
-124,
-5,
-89,
-69,
-76,
-67,
-140,
-181,
-30,
-211,
-201,
-246,
-157,
-216,
-2,
-211,
-25,
-79,
-63,
-212,
-191,
-247,
-1,
-151,
-147,
-7,
-3,
-5,
-143,
-153,
-188,
-182,
-181,
-202,
-77,
-239,
-252,
-32,
-143,
-22,
-52,
-96,
-100,
-215,
-181,
-195,
-195,
-18,
-0,
-177,
-124,
-17,
-162,
-125,
-1,
-35,
-8,
-128,
-127,
-211,
-32,
-76,
-54,
-254,
-176,
-208,
-147,
-28,
-1,
-6,
-112,
-112,
-155,
-190,
-12,
-3,
-120,
-150,
-169,
-190,
-178,
-64,
-94,
-219,
-34,
-198,
-60,
-208,
-99,
-28,
-254,
-97,
-194,
-121,
-135,
-115,
-113,
-98,
-99,
-32,
-219,
-83,
-27,
-247,
-97,
-30,
-158,
-120,
-10,
-228,
-186,
-14,
-111,
-206,
-5,
-224,
-101,
-90,
-31,
-239,
-88,
-115,
-200,
-2,
-96,
-92,
-107,
-177,
-129,
-53,
-144,
-200,
-174,
-155,
-57,
-101,
-167,
-227,
-152,
-147,
-34,
-169,
-179,
-190,
-136,
-39,
-203,
-43,
-213,
-97,
-161,
-63,
-224,
-12,
-158,
-41,
-140,
-193,
-116,
-102,
-228,
-71,
-188,
-215,
-160,
-10,
-96,
-95,
-89,
-0,
-31,
-119,
-226,
-207,
-70,
-236,
-253,
-215,
-239,
-181,
-243,
-67,
-130,
-243,
-14,
-189,
-193,
-93,
-200,
-79,
-201,
-14,
-241,
-212,
-217,
-188,
-138,
-155,
-149,
-180,
-125,
-177,
-214,
-183,
-50,
-94,
-50,
-192,
-15,
-8,
-199,
-59,
-91,
-93,
-164,
-250,
-250,
-227,
-90,
-139,
-141,
-248,
-194,
-91,
-220,
-141,
-164,
-117,
-190,
-88,
-255,
-29,
-73,
-174,
-116,
-2,
-216,
-201,
-211,
-222,
-27,
-22,
-26,
-241,
-37,
-176,
-86,
-150,
-118,
-25,
-232,
-93,
-38,
-142,
-22,
-128,
-205,
-145,
-47,
-212,
-116,
-244,
-235,
-229,
-43,
-171,
-225,
-225,
-78,
-252,
-39,
-16,
-93,
-199,
-154,
-253,
-247,
-126,
-120,
-112,
-222,
-255,
-219,
-74,
-234,
-109,
-236,
-200,
-171,
-61,
-117,
-118,
-107,
-91,
-183,
-2,
-8,
-13,
-92,
-51,
-192,
-224,
-19,
-12,
-186,
-53,
-162,
-147,
-178,
-88,
-254,
-186,
-138,
-155,
-11,
-66,
-73,
-31,
-198,
-173,
-22,
-27,
-17,
-0,
-255,
-208,
-254,
-22,
-149,
-73,
-211,
-181,
-236,
-106,
-100,
-63,
-60,
-224,
-111,
-142,
-39,
-44,
-52,
-178,
-234,
-177,
-225,
-192,
-143,
-5,
-246,
-213,
-255,
-15,
-100,
-215,
-85,
-250,
-205,
-41,
-28,
-17,
-57,
-117,
-75,
-81,
-227,
-75,
-142,
-104,
-199,
-191,
-174,
-207,
-221,
-26,
-241,
-60,
-140,
-8,
-177,
-239,
-80,
-208,
-150,
-107,
-155,
-149,
-200,
-205,
-110,
-63,
-92,
-86,
-86,
-113,
-77,
-119,
-226,
-79,
-69,
-4,
-225,
-74,
-85,
-109,
-198,
-43,
-156,
-241,
-80,
-246,
-21,
-127,
-189,
-214,
-15,
-152,
-76,
-35,
-250,
-2,
-168,
-215,
-1,
-60,
-16,
-187,
-195,
-65,
-91,
-0,
-36,
-40,
-100,
-240,
-191,
-10,
-62,
-139,
-133,
-22,
-27,
-145,
-230,
-243,
-16,
-79,
-184,
-218,
-88,
-254,
-228,
-214,
-105,
-175,
-119,
-202,
-108,
-172,
-247,
-91,
-144,
-179,
-222,
-29,
-244,
-183,
-47,
-44,
-244,
-11,
-17,
-69,
-214,
-63,
-138,
-66,
-0,
-88,
-26,
-217,
-142,
-204,
-161,
-228,
-156,
-24,
-81,
-62,
-222,
-172,
-252,
-23,
-234,
-4,
-190,
-18,
-39,
-136,
-7,
-254,
-132,
-26,
-43,
-147,
-135,
-50,
-255,
-112,
-89,
-89,
-201,
-53,
-237,
-196,
-191,
-3,
-209,
-239,
-120,
-133,
-87,
-23,
-32,
-31,
-149,
-243,
-200,
-181,
-237,
-23,
-163,
-43,
-88,
-116,
-75,
-217,
-128,
-215,
-154,
-228,
-202,
-234,
-43,
-90,
-244,
-197,
-98,
-227,
-146,
-250,
-170,
-220,
-133,
-54,
-102,
-96,
-153,
-3,
-147,
-61,
-5,
-184,
-172,
-105,
-191,
-234,
-58,
-60,
-20,
-29,
-64,
-87,
-32,
-57,
-7,
-64,
-190,
-164,
-3,
-86,
-96,
-200,
-23,
-208,
-126,
-101,
-75,
-61,
-22,
-11,
-109,
-26,
-217,
-65,
-56,
-237,
-94,
-128,
-172,
-100,
-78,
-1,
-206,
-70,
-4,
-153,
-87,
-234,
-59,
-109,
-70,
-132,
-133,
-70,
-142,
-169,
-230,
-32,
-66,
-228,
-101,
-90,
-246,
-170,
-138,
-1,
-178,
-52,
-112,
-134,
-214,
-63,
-37,
-4,
-16,
-45,
-252,
-153,
-90,
-126,
-22,
-37,
-123,
-113,
-224,
-120,
-165,
-185,
-141,
-66,
-4,
-102,
-196,
-200,
-235,
-8,
-74,
-162,
-58,
-35,
-38,
-170,
-179,
-25,
-185,
-5,
-24,
-40,
-243,
-180,
-179,
-58,
-143,
-219,
-145,
-21,
-104,
-84,
-1,
-64,
-158,
-72,
-3,
-100,
-251,
-228,
-70,
-37,
-250,
-50,
-170,
-88,
-107,
-192,
-239,
-40,
-135,
-215,
-128,
-30,
-39,
-160,
-189,
-133,
-55,
-232,
-13,
-249,
-87,
-252,
-113,
-79,
-221,
-33,
-90,
-119,
-120,
-73,
-219,
-95,
-104,
-125,
-101,
-240,
-216,
-54,
-29,
-30,
-47,
-2,
-96,
-57,
-96,
-178,
-246,
-249,
-32,
-79,
-253,
-247,
-181,
-110,
-18,
-129,
-201,
-53,
-218,
-220,
-63,
-226,
-249,
-103,
-83,
-124,
-109,
-79,
-254,
-213,
-190,
-145,
-234,
-243,
-123,
-27,
-157,
-230,
-77,
-192,
-211,
-28,
-30,
-95,
-118,
-104,
-42,
-195,
-66,
-35,
-66,
-224,
-207,
-74,
-115,
-54,
-242,
-37,
-254,
-171,
-254,
-46,
-157,
-252,
-218,
-214,
-158,
-62,
-148,
-250,
-114,
-212,
-220,
-183,
-253,
-2,
-185,
-74,
-192,
-129,
-178,
-66,
-155,
-101,
-17,
-123,
-125,
-171,
-31,
-153,
-138,
-184,
-244,
-118,
-222,
-2,
-0,
-27,
-147,
-199,
-39,
-252,
-63,
-84,
-177,
-140,
-108,
-171,
-62,
-70,
-174,
-84,
-11,
-245,
-11,
-121,
-185,
-182,
-121,
-156,
-246,
-167,
-66,
-22,
-239,
-40,
-169,
-255,
-148,
-214,
-95,
-229,
-169,
-179,
-249,
-29,
-239,
-163,
-218,
-18,
-208,
-171,
-95,
-104,
-5,
-101,
-56,
-46,
-4,
-128,
-49,
-198,
-0,
-155,
-34,
-75,
-180,
-69,
-192,
-118,
-78,
-249,
-246,
-90,
-54,
-29,
-216,
-164,
-1,
-191,
-198,
-247,
-79,
-158,
-6,
-236,
-78,
-29,
-108,
-25,
-112,
-131,
-150,
-253,
-178,
-162,
-221,
-83,
-97,
-161,
-129,
-159,
-234,
-255,
-207,
-199,
-49,
-109,
-37,
-32,
-44,
-52,
-242,
-197,
-183,
-66,
-192,
-218,
-199,
-87,
-78,
-126,
-109,
-103,
-151,
-182,
-91,
-85,
-209,
-213,
-240,
-176,
-249,
-15,
-126,
-86,
-85,
-230,
-105,
-183,
-52,
-34,
-44,
-236,
-22,
-228,
-9,
-196,
-22,
-162,
-181,
-18,
-144,
-60,
-8,
-173,
-215,
-48,
-134,
-60,
-54,
-69,
-168,
-0,
-184,
-17,
-17,
-80,
-91,
-118,
-232,
-147,
-197,
-175,
-74,
-234,
-207,
-211,
-250,
-31,
-150,
-212,
-91,
-189,
-220,
-111,
-200,
-125,
-1,
-86,
-4,
-78,
-213,
-242,
-235,
-9,
-48,
-133,
-110,
-210,
-225,
-237,
-232,
-43,
-8,
-97,
-79,
-0,
-62,
-168,
-15,
-99,
-42,
-178,
-175,
-93,
-139,
-124,
-217,
-87,
-26,
-171,
-160,
-132,
-23,
-52,
-23,
-0,
-107,
-35,
-58,
-140,
-253,
-157,
-178,
-143,
-35,
-91,
-148,
-117,
-42,
-218,
-89,
-5,
-223,
-221,
-136,
-176,
-122,
-12,
-88,
-215,
-169,
-15,
-78,
-78,
-137,
-40,
-243,
-236,
-201,
-193,
-163,
-192,
-138,
-1,
-253,
-182,
-118,
-24,
-165,
-9,
-76,
-3,
-120,
-44,
-139,
-40,
-57,
-247,
-170,
-42,
-171,
-104,
-111,
-147,
-169,
-218,
-213,
-207,
-44,
-125,
-150,
-235,
-183,
-232,
-203,
-53,
-202,
-99,
-159,
-146,
-250,
-157,
-155,
-8,
-128,
-24,
-112,
-4,
-192,
-2,
-36,
-252,
-155,
-187,
-42,
-249,
-63,
-173,
-155,
-75,
-137,
-169,
-48,
-162,
-31,
-179,
-39,
-65,
-51,
-16,
-161,
-100,
-149,
-230,
-143,
-83,
-19,
-113,
-106,
-204,
-67,
-7,
-192,
-62,
-136,
-1,
-141,
-61,
-18,
-244,
-162,
-134,
-143,
-205,
-85,
-127,
-142,
-254,
-131,
-22,
-123,
-35,
-109,
-55,
-44,
-59,
-136,
-21,
-200,
-21,
-103,
-224,
-40,
-123,
-104,
-16,
-22,
-154,
-145,
-219,
-0,
-43,
-4,
-254,
-130,
-19,
-162,
-173,
-164,
-157,
-141,
-90,
-52,
-15,
-89,
-138,
-46,
-89,
-69,
-223,
-39,
-116,
-66,
-188,
-19,
-81,
-66,
-66,
-11,
-67,
-32,
-242,
-16,
-97,
-222,
-184,
-126,
-136,
-94,
-163,
-118,
-44,
-197,
-132,
-243,
-110,
-109,
-170,
-239,
-7,
-24,
-180,
-4,
-172,
-212,
-57,
-33,
-31,
-152,
-35,
-17,
-191,
-154,
-185,
-250,
-247,
-215,
-140,
-119,
-91,
-9,
-125,
-233,
-127,
-28,
-152,
-233,
-57,
-30,
-66,
-20,
-84,
-15,
-213,
-189,
-52,
-100,
-15,
-125,
-157,
-211,
-246,
-42,
-234,
-151,
-192,
-163,
-106,
-7,
-161,
-125,
-248,
-142,
-115,
-141,
-89,
-72,
-44,
-192,
-38,
-201,
-45,
-93,
-69,
-224,
-25,
-200,
-222,
-240,
-116,
-253,
-93,
-41,
-4,
-180,
-173,
-213,
-23,
-128,
-8,
-163,
-175,
-50,
-202,
-103,
-241,
-192,
-155,
-105,
-24,
-74,
-77,
-219,
-217,
-108,
-197,
-175,
-40,
-169,
-223,
-216,
-222,
-104,
-5,
-143,
-198,
-97,
-195,
-107,
-250,
-100,
-241,
-44,
-100,
-165,
-243,
-31,
-100,
-91,
-58,
-29,
-9,
-83,
-22,
-111,
-255,
-62,
-222,
-64,
-158,
-65,
-183,
-12,
-159,
-80,
-186,
-79,
-84,
-189,
-52,
-135,
-159,
-155,
-92,
-116,
-239,
-0,
-250,
-78,
-118,
-16,
-93,
-1,
-60,
-3,
-249,
-106,
-205,
-5,
-14,
-70,
-150,
-228,
-51,
-144,
-37,
-222,
-36,
-234,
-211,
-99,
-219,
-163,
-62,
-244,
-239,
-210,
-78,
-185,
-141,
-201,
-119,
-38,
-213,
-66,
-96,
-9,
-125,
-110,
-246,
-204,
-25,
-29,
-248,
-63,
-165,
-143,
-100,
-20,
-61,
-130,
-124,
-5,
-89,
-22,
-195,
-114,
-51,
-123,
-131,
-37,
-245,
-173,
-194,
-134,
-215,
-244,
-201,
-98,
-192,
-158,
-98,
-194,
-131,
-220,
-12,
-178,
-12,
-193,
-2,
-0,
-241,
-182,
-122,
-2,
-209,
-218,
-46,
-68,
-246,
-211,
-165,
-251,
-239,
-10,
-62,
-48,
-188,
-45,
-192,
-114,
-58,
-201,
-127,
-212,
-178,
-253,
-243,
-145,
-125,
-224,
-83,
-147,
-223,
-169,
-91,
-10,
-9,
-216,
-50,
-147,
-18,
-75,
-50,
-15,
-253,
-206,
-228,
-138,
-73,
-16,
-5,
-221,
-184,
-177,
-204,
-35,
-95,
-1,
-238,
-89,
-82,
-255,
-182,
-50,
-1,
-64,
-79,
-97,
-195,
-157,
-103,
-217,
-42,
-34,
-80,
-239,
-64,
-236,
-217,
-191,
-133,
-72,
-187,
-39,
-145,
-165,
-231,
-36,
-36,
-81,
-65,
-165,
-253,
-57,
-34,
-81,
-15,
-71,
-52,
-222,
-51,
-144,
-51,
-224,
-155,
-144,
-4,
-151,
-181,
-222,
-107,
-228,
-202,
-141,
-78,
-2,
-0,
-88,
-18,
-49,
-246,
-0,
-49,
-30,
-178,
-231,
-167,
-23,
-208,
-80,
-67,
-170,
-237,
-198,
-211,
-41,
-200,
-243,
-139,
-147,
-223,
-169,
-91,
-146,
-22,
-74,
-34,
-36,
-144,
-171,
-221,
-79,
-7,
-217,
-79,
-140,
-5,
-144,
-159,
-164,
-120,
-243,
-232,
-145,
-155,
-150,
-251,
-4,
-64,
-47,
-97,
-195,
-199,
-180,
-0,
-0,
-62,
-68,
-190,
-108,
-90,
-128,
-236,
-123,
-220,
-165,
-224,
-245,
-128,
-55,
-224,
-164,
-78,
-124,
-155,
-16,
-100,
-14,
-98,
-185,
-118,
-143,
-83,
-246,
-48,
-53,
-199,
-111,
-140,
-76,
-37,
-238,
-67,
-168,
-0,
-248,
-166,
-210,
-79,
-66,
-52,
-208,
-203,
-146,
-107,
-184,
-191,
-214,
-240,
-153,
-192,
-56,
-18,
-0,
-125,
-193,
-62,
-115,
-224,
-161,
-209,
-238,
-75,
-40,
-16,
-97,
-104,
-141,
-171,
-246,
-41,
-212,
-189,
-7,
-81,
-118,
-226,
-27,
-75,
-244,
-20,
-54,
-220,
-25,
-203,
-209,
-5,
-64,
-103,
-222,
-58,
-137,
-231,
-81,
-56,
-127,
-5,
-94,
-65,
-254,
-117,
-246,
-102,
-168,
-37,
-143,
-199,
-254,
-49,
-70,
-122,
-177,
-61,
-31,
-57,
-170,
-128,
-18,
-73,
-236,
-208,
-186,
-46,
-175,
-173,
-4,
-0,
-146,
-78,
-124,
-1,
-34,
-76,
-94,
-236,
-148,
-111,
-174,
-101,
-243,
-9,
-76,
-209,
-173,
-237,
-146,
-0,
-48,
-198,
-0,
-175,
-213,
-103,
-49,
-16,
-206,
-61,
-160,
-109,
-48,
-2,
-120,
-185,
-122,
-157,
-218,
-96,
-29,
-228,
-71,
-171,
-144,
-251,
-222,
-219,
-165,
-189,
-253,
-138,
-251,
-4,
-64,
-47,
-97,
-195,
-157,
-118,
-99,
-82,
-0,
-44,
-65,
-121,
-184,
-174,
-189,
-148,
-249,
-93,
-21,
-109,
-189,
-91,
-4,
-224,
-29,
-218,
-182,
-210,
-79,
-153,
-145,
-222,
-114,
-62,
-84,
-10,
-0,
-100,
-223,
-118,
-135,
-210,
-250,
-108,
-214,
-247,
-215,
-186,
-219,
-9,
-56,
-23,
-215,
-54,
-227,
-206,
-14,
-162,
-15,
-56,
-239,
-255,
-198,
-22,
-109,
-67,
-114,
-233,
-93,
-66,
-141,
-160,
-5,
-94,
-132,
-108,
-45,
-167,
-233,
-191,
-25,
-20,
-76,
-150,
-75,
-218,
-189,
-13,
-249,
-162,
-91,
-109,
-251,
-127,
-128,
-247,
-2,
-235,
-218,
-129,
-229,
-105,
-99,
-87,
-14,
-215,
-117,
-233,
-179,
-135,
-111,
-183,
-73,
-58,
-74,
-188,
-173,
-70,
-20,
-96,
-94,
-139,
-182,
-219,
-106,
-219,
-1,
-251,
-230,
-2,
-221,
-239,
-171,
-231,
-127,
-173,
-0,
-56,
-73,
-233,
-46,
-194,
-179,
-215,
-71,
-132,
-148,
-85,
-106,
-157,
-232,
-169,
-247,
-157,
-2,
-148,
-253,
-235,
-124,
-10,
-128,
-8,
-151,
-179,
-144,
-175,
-205,
-28,
-68,
-195,
-124,
-8,
-125,
-38,
-128,
-44,
-239,
-203,
-230,
-200,
-113,
-215,
-43,
-139,
-207,
-14,
-177,
-162,
-180,
-95,
-196,
-74,
-3,
-164,
-30,
-251,
-183,
-22,
-114,
-44,
-57,
-13,
-89,
-229,
-189,
-14,
-17,
-0,
-119,
-0,
-107,
-181,
-228,
-185,
-161,
-29,
-88,
-158,
-186,
-81,
-9,
-27,
-222,
-5,
-125,
-11,
-0,
-187,
-231,
-169,
-74,
-250,
-81,
-214,
-214,
-58,
-41,
-84,
-42,
-144,
-24,
-233,
-79,
-223,
-88,
-0,
-116,
-5,
-67,
-180,
-3,
-32,
-95,
-141,
-128,
-124,
-149,
-110,
-38,
-215,
-129,
-220,
-71,
-3,
-115,
-229,
-24,
-32,
-119,
-50,
-2,
-153,
-100,
-215,
-33,
-138,
-96,
-55,
-205,
-247,
-31,
-168,
-8,
-181,
-221,
-115,
-255,
-174,
-66,
-86,
-136,
-238,
-182,
-238,
-165,
-72,
-76,
-191,
-1,
-187,
-249,
-64,
-158,
-27,
-217,
-27,
-243,
-212,
-141,
-74,
-216,
-240,
-46,
-112,
-222,
-211,
-6,
-125,
-48,
-183,
-17,
-71,
-143,
-9,
-164,
-95,
-6,
-217,
-255,
-255,
-4,
-81,
-4,
-94,
-67,
-137,
-39,
-89,
-161,
-221,
-215,
-201,
-21,
-135,
-69,
-244,
-42,
-0,
-134,
-5,
-228,
-43,
-187,
-72,
-39,
-252,
-7,
-200,
-205,
-65,
-159,
-129,
-216,
-254,
-163,
-19,
-208,
-231,
-209,
-248,
-74,
-224,
-159,
-200,
-215,
-111,
-22,
-98,
-26,
-252,
-85,
-224,
-185,
-14,
-205,
-218,
-192,
-111,
-27,
-246,
-105,
-69,
-36,
-54,
-222,
-121,
-200,
-22,
-105,
-58,
-162,
-15,
-186,
-15,
-49,
-40,
-122,
-87,
-135,
-251,
-13,
-70,
-219,
-107,
-180,
-236,
-87,
-149,
-0,
-24,
-149,
-176,
-225,
-93,
-224,
-60,
-198,
-117,
-128,
-93,
-16,
-33,
-22,
-20,
-112,
-180,
-142,
-241,
-115,
-144,
-37,
-234,
-2,
-2,
-150,
-23,
-133,
-119,
-58,
-9,
-177,
-121,
-14,
-126,
-136,
-136,
-100,
-63,
-88,
-7,
-222,
-223,
-201,
-221,
-124,
-23,
-23,
-1,
-96,
-183,
-42,
-62,
-143,
-197,
-101,
-201,
-245,
-24,
-239,
-241,
-212,
-91,
-69,
-230,
-181,
-140,
-52,
-74,
-1,
-81,
-182,
-94,
-133,
-76,
-220,
-57,
-195,
-185,
-155,
-122,
-16,
-73,
-7,
-208,
-67,
-191,
-170,
-4,
-192,
-168,
-132,
-13,
-239,
-2,
-103,
-28,
-88,
-147,
-241,
-224,
-128,
-163,
-85,
-76,
-151,
-6,
-46,
-211,
-198,
-65,
-241,
-198,
-145,
-175,
-215,
-36,
-196,
-1,
-103,
-33,
-114,
-58,
-112,
-8,
-29,
-44,
-201,
-22,
-51,
-1,
-112,
-183,
-222,
-207,
-75,
-74,
-234,
-109,
-16,
-144,
-147,
-61,
-117,
-39,
-1,
-207,
-116,
-126,
-111,
-4,
-124,
-67,
-5,
-194,
-60,
-196,
-208,
-231,
-92,
-26,
-156,
-116,
-140,
-7,
-16,
-217,
-36,
-87,
-121,
-150,
-10,
-0,
-173,
-111,
-21,
-54,
-92,
-203,
-175,
-211,
-255,
-55,
-10,
-253,
-221,
-165,
-207,
-78,
-159,
-230,
-225,
-56,
-189,
-17,
-16,
-112,
-180,
-234,
-130,
-191,
-210,
-134,
-151,
-208,
-98,
-255,
-135,
-44,
-107,
-191,
-174,
-23,
-190,
-159,
-246,
-57,
-209,
-22,
-39,
-1,
-96,
-207,
-159,
-159,
-81,
-82,
-111,
-143,
-220,
-90,
-37,
-143,
-92,
-220,
-64,
-15,
-38,
-185,
-202,
-183,
-82,
-0,
-40,
-77,
-227,
-176,
-225,
-202,
-114,
-22,
-178,
-53,
-131,
-24,
-95,
-226,
-128,
-62,
-59,
-188,
-27,
-7,
-28,
-45,
-187,
-216,
-193,
-218,
-224,
-150,
-178,
-193,
-218,
-160,
-227,
-214,
-56,
-231,
-172,
-150,
-237,
-163,
-11,
-0,
-26,
-160,
-130,
-199,
-70,
-136,
-95,
-249,
-125,
-200,
-210,
-252,
-126,
-196,
-87,
-187,
-84,
-202,
-234,
-64,
-2,
-120,
-126,
-73,
-253,
-139,
-180,
-62,
-118,
-246,
-224,
-113,
-7,
-122,
-50,
-201,
-237,
-19,
-206,
-176,
-105,
-28,
-250,
-59,
-128,
-119,
-136,
-0,
-104,
-28,
-112,
-212,
-71,
-252,
-37,
-37,
-190,
-31,
-71,
-193,
-212,
-22,
-228,
-199,
-136,
-173,
-34,
-150,
-106,
-219,
-216,
-2,
-96,
-114,
-205,
-191,
-59,
-170,
-250,
-140,
-28,
-157,
-89,
-203,
-201,
-153,
-136,
-38,
-223,
-250,
-102,
-79,
-163,
-124,
-137,
-111,
-51,
-188,
-120,
-29,
-148,
-200,
-5,
-111,
-212,
-88,
-248,
-248,
-49,
-27,
-89,
-214,
-158,
-137,
-196,
-81,
-240,
-154,
-74,
-3,
-171,
-43,
-237,
-28,
-58,
-126,
-12,
-26,
-246,
-185,
-23,
-147,
-220,
-62,
-225,
-60,
-219,
-56,
-95,
-226,
-145,
-109,
-67,
-4,
-128,
-215,
-220,
-155,
-138,
-128,
-163,
-69,
-66,
-43,
-41,
-30,
-2,
-54,
-109,
-218,
-201,
-18,
-158,
-219,
-40,
-207,
-39,
-91,
-182,
-135,
-33,
-111,
-1,
-16,
-255,
-7,
-128,
-95,
-148,
-212,
-159,
-171,
-245,
-167,
-161,
-70,
-80,
-136,
-242,
-200,
-122,
-222,
-157,
-91,
-210,
-110,
-31,
-173,
-191,
-31,
-71,
-72,
-32,
-118,
-10,
-159,
-33,
-15,
-85,
-85,
-105,
-55,
-209,
-226,
-126,
-44,
-174,
-37,
-87,
-188,
-93,
-67,
-110,
-231,
-15,
-162,
-120,
-245,
-230,
-216,
-67,
-124,
-206,
-1,
-190,
-26,
-179,
-95,
-53,
-125,
-238,
-197,
-36,
-183,
-79,
-56,
-207,
-178,
-251,
-151,
-120,
-176,
-109,
-136,
-0,
-40,
-139,
-191,
-88,
-26,
-112,
-212,
-37,
-218,
-133,
-220,
-123,
-46,
-90,
-66,
-76,
-242,
-0,
-8,
-173,
-242,
-150,
-105,
-219,
-161,
-9,
-0,
-196,
-51,
-239,
-17,
-125,
-22,
-94,
-215,
-77,
-114,
-31,
-253,
-77,
-10,
-229,
-207,
-215,
-242,
-178,
-149,
-195,
-146,
-72,
-188,
-62,
-144,
-109,
-195,
-69,
-200,
-23,
-248,
-78,
-189,
-158,
-77,
-144,
-50,
-37,
-242,
-61,
-89,
-108,
-81,
-40,
-95,
-18,
-216,
-155,
-252,
-248,
-213,
-123,
-228,
-135,
-156,
-206,
-128,
-40,
-49,
-135,
-18,
-44,
-132,
-158,
-76,
-114,
-251,
-132,
-211,
-167,
-198,
-161,
-191,
-29,
-154,
-98,
-36,
-227,
-75,
-16,
-235,
-197,
-245,
-44,
-243,
-138,
-235,
-54,
-10,
-56,
-234,
-198,
-155,
-219,
-193,
-24,
-115,
-146,
-49,
-102,
-166,
-49,
-102,
-199,
-44,
-203,
-130,
-82,
-104,
-107,
-219,
-115,
-145,
-44,
-48,
-43,
-23,
-202,
-215,
-0,
-14,
-52,
-198,
-88,
-103,
-12,
-175,
-47,
-193,
-24,
-196,
-158,
-198,
-152,
-213,
-141,
-49,
-103,
-100,
-89,
-118,
-123,
-9,
-205,
-52,
-253,
-187,
-160,
-80,
-190,
-72,
-255,
-122,
-95,
-112,
-150,
-101,
-11,
-141,
-49,
-59,
-25,
-99,
-190,
-96,
-140,
-153,
-108,
-140,
-121,
-153,
-49,
-102,
-107,
-99,
-204,
-29,
-198,
-152,
-237,
-140,
-49,
-147,
-148,
-244,
-250,
-86,
-61,
-111,
-136,
-44,
-203,
-22,
-102,
-89,
-246,
-75,
-99,
-204,
-63,
-181,
-104,
-235,
-18,
-186,
-107,
-140,
-49,
-151,
-25,
-99,
-214,
-53,
-198,
-120,
-131,
-90,
-246,
-0,
-59,
-158,
-254,
-107,
-140,
-185,
-180,
-226,
-95,
-235,
-80,
-216,
-200,
-138,
-237,
-54,
-59,
-118,
-129,
-85,
-145,
-237,
-223,
-192,
-41,
-76,
-67,
-148,
-29,
-197,
-206,
-210,
-191,
-222,
-0,
-177,
-72,
-68,
-160,
-191,
-25,
-99,
-94,
-175,
-180,
-55,
-27,
-99,
-54,
-50,
-198,
-156,
-106,
-140,
-217,
-55,
-224,
-186,
-235,
-151,
-148,
-91,
-157,
-147,
-127,
-60,
-147,
-239,
-95,
-167,
-82,
-189,
-55,
-30,
-152,
-196,
-142,
-244,
-89,
-132,
-40,
-109,
-254,
-135,
-124,
-209,
-236,
-87,
-101,
-1,
-78,
-116,
-219,
-166,
-80,
-30,
-67,
-89,
-1,
-32,
-190,
-240,
-246,
-248,
-231,
-213,
-21,
-116,
-39,
-42,
-205,
-247,
-10,
-229,
-54,
-241,
-99,
-144,
-209,
-148,
-135,
-175,
-221,
-215,
-182,
-142,
-205,
-87,
-194,
-215,
-194,
-187,
-178,
-67,
-18,
-143,
-0,
-28,
-86,
-193,
-99,
-87,
-165,
-137,
-151,
-129,
-182,
-2,
-12,
-193,
-36,
-23,
-209,
-107,
-0,
-188,
-86,
-127,
-219,
-232,
-187,
-179,
-91,
-242,
-179,
-104,
-19,
-250,
-187,
-117,
-36,
-99,
-231,
-186,
-173,
-2,
-142,
-54,
-209,
-138,
-159,
-230,
-105,
-187,
-35,
-162,
-13,
-159,
-132,
-156,
-151,
-206,
-71,
-20,
-97,
-147,
-17,
-43,
-194,
-78,
-193,
-10,
-245,
-186,
-195,
-18,
-0,
-187,
-233,
-245,
-42,
-147,
-122,
-34,
-203,
-49,
-235,
-37,
-249,
-83,
-96,
-3,
-242,
-173,
-206,
-245,
-180,
-8,
-158,
-161,
-47,
-218,
-186,
-46,
-87,
-230,
-17,
-104,
-193,
-219,
-98,
-64,
-0,
-32,
-250,
-7,
-27,
-64,
-99,
-192,
-0,
-201,
-161,
-91,
-218,
-185,
-103,
-175,
-227,
-88,
-76,
-48,
-4,
-147,
-92,
-6,
-87,
-0,
-171,
-32,
-43,
-128,
-83,
-90,
-242,
-179,
-104,
-19,
-250,
-187,
-117,
-36,
-99,
-231,
-186,
-173,
-2,
-142,
-38,
-152,
-167,
-30,
-150,
-141,
-72,
-91,
-107,
-254,
-138,
-72,
-236,
-171,
-25,
-137,
-95,
-2,
-171,
-180,
-188,
-190,
-245,
-186,
-59,
-191,
-77,
-251,
-26,
-222,
-3,
-2,
-0,
-49,
-217,
-222,
-20,
-56,
-70,
-235,
-254,
-76,
-137,
-18,
-208,
-105,
-99,
-227,
-22,
-30,
-25,
-187,
-143,
-158,
-107,
-141,
-103,
-147,
-220,
-198,
-95,
-98,
-58,
-68,
-50,
-214,
-226,
-7,
-201,
-117,
-72,
-141,
-3,
-142,
-78,
-120,
-32,
-209,
-111,
-64,
-108,
-31,
-106,
-163,
-7,
-233,
-132,
-189,
-23,
-145,
-186,
-214,
-113,
-230,
-6,
-26,
-154,
-136,
-34,
-193,
-59,
-191,
-170,
-124,
-102,
-81,
-178,
-124,
-236,
-2,
-170,
-113,
-17,
-162,
-195,
-169,
-156,
-252,
-202,
-231,
-89,
-200,
-57,
-246,
-116,
-122,
-142,
-19,
-200,
-248,
-54,
-201,
-109,
-252,
-37,
-166,
-67,
-36,
-99,
-45,
-254,
-147,
-254,
-63,
-5,
-28,
-109,
-3,
-114,
-119,
-225,
-79,
-214,
-208,
-45,
-1,
-252,
-86,
-105,
-47,
-70,
-52,
-255,
-203,
-34,
-73,
-61,
-158,
-64,
-116,
-31,
-7,
-86,
-180,
-255,
-53,
-146,
-190,
-235,
-207,
-72,
-8,
-116,
-27,
-12,
-229,
-1,
-122,
-74,
-126,
-234,
-12,
-76,
-247,
-24,
-240,
-74,
-36,
-142,
-224,
-2,
-189,
-247,
-215,
-4,
-242,
-58,
-89,
-121,
-125,
-174,
-143,
-190,
-22,
-174,
-213,
-202,
-36,
-55,
-128,
-175,
-133,
-111,
-34,
-214,
-90,
-9,
-6,
-240,
-109,
-28,
-250,
-155,
-8,
-145,
-140,
-19,
-90,
-2,
-241,
-51,
-7,
-9,
-95,
-86,
-153,
-58,
-140,
-220,
-162,
-235,
-66,
-10,
-81,
-118,
-145,
-175,
-210,
-157,
-90,
-255,
-145,
-146,
-246,
-199,
-32,
-147,
-126,
-1,
-114,
-212,
-117,
-33,
-98,
-244,
-210,
-219,
-23,
-213,
-25,
-124,
-190,
-99,
-192,
-143,
-146,
-7,
-80,
-173,
-253,
-154,
-146,
-43,
-202,
-110,
-33,
-96,
-213,
-208,
-21,
-180,
-48,
-201,
-13,
-224,
-217,
-183,
-0,
-104,
-28,
-250,
-155,
-142,
-145,
-140,
-163,
-0,
-241,
-40,
-67,
-59,
-28,
-108,
-245,
-165,
-15,
-237,
-24,
-68,
-241,
-247,
-184,
-182,
-191,
-9,
-113,
-96,
-241,
-90,
-197,
-105,
-187,
-189,
-169,
-135,
-215,
-168,
-166,
-192,
-103,
-101,
-100,
-207,
-120,
-33,
-50,
-169,
-230,
-107,
-31,
-130,
-246,
-170,
-228,
-201,
-52,
-106,
-181,
-239,
-228,
-169,
-175,
-203,
-94,
-148,
-205,
-225,
-55,
-102,
-236,
-249,
-157,
-103,
-89,
-119,
-10,
-16,
-116,
-164,
-134,
-172,
-36,
-96,
-12,
-45,
-191,
-155,
-192,
-121,
-30,
-125,
-9,
-128,
-198,
-161,
-191,
-233,
-16,
-201,
-56,
-26,
-144,
-244,
-67,
-54,
-209,
-96,
-80,
-54,
-29,
-196,
-44,
-214,
-218,
-184,
-207,
-69,
-20,
-105,
-215,
-144,
-47,
-211,
-230,
-1,
-59,
-149,
-180,
-253,
-134,
-210,
-84,
-29,
-63,
-86,
-30,
-169,
-33,
-150,
-134,
-110,
-84,
-225,
-7,
-181,
-221,
-20,
-224,
-204,
-128,
-254,
-111,
-138,
-44,
-219,
-103,
-19,
-32,
-244,
-200,
-29,
-122,
-188,
-209,
-142,
-129,
-103,
-107,
-253,
-88,
-114,
-203,
-173,
-19,
-0,
-31,
-209,
-250,
-89,
-190,
-122,
-15,
-253,
-158,
-74,
-223,
-202,
-191,
-99,
-180,
-49,
-4,
-1,
-208,
-88,
-219,
-78,
-135,
-72,
-198,
-81,
-1,
-108,
-73,
-30,
-87,
-255,
-229,
-1,
-244,
-103,
-105,
-191,
-46,
-99,
-100,
-64,
-209,
-229,
-200,
-143,
-46,
-38,
-151,
-180,
-181,
-254,
-203,
-94,
-205,
-103,
-192,
-181,
-55,
-35,
-183,
-202,
-251,
-13,
-133,
-227,
-41,
-2,
-180,
-199,
-228,
-49,
-7,
-74,
-147,
-119,
-22,
-232,
-173,
-75,
-175,
-247,
-235,
-135,
-88,
-84,
-2,
-220,
-20,
-118,
-23,
-253,
-35,
-64,
-0,
-216,
-19,
-136,
-202,
-216,
-141,
-14,
-253,
-211,
-17,
-47,
-189,
-133,
-244,
-17,
-133,
-166,
-103,
-140,
-81,
-1,
-208,
-58,
-146,
-113,
-116,
-168,
-16,
-120,
-0,
-184,
-33,
-128,
-214,
-106,
-47,
-7,
-98,
-229,
-145,
-155,
-144,
-122,
-191,
-134,
-192,
-41,
-90,
-223,
-202,
-186,
-140,
-252,
-88,
-165,
-84,
-233,
-86,
-211,
-126,
-29,
-125,
-176,
-139,
-8,
-244,
-208,
-34,
-63,
-175,
-189,
-157,
-130,
-177,
-16,
-98,
-19,
-97,
-87,
-80,
-251,
-151,
-241,
-24,
-54,
-2,
-4,
-128,
-117,
-253,
-190,
-188,
-1,
-79,
-123,
-228,
-116,
-104,
-188,
-158,
-14,
-7,
-99,
-81,
-0,
-104,
-251,
-170,
-72,
-198,
-95,
-71,
-21,
-198,
-109,
-120,
-247,
-134,
-154,
-135,
-121,
-144,
-214,
-253,
-179,
-164,
-237,
-249,
-90,
-95,
-187,
-210,
-240,
-180,
-125,
-177,
-182,
-157,
-66,
-77,
-242,
-203,
-10,
-30,
-118,
-50,
-255,
-185,
-65,
-155,
-21,
-201,
-189,
-250,
-64,
-190,
-132,
-55,
-50,
-50,
-161,
-233,
-25,
-4,
-158,
-93,
-3,
-107,
-146,
-167,
-231,
-190,
-34,
-176,
-77,
-211,
-16,
-217,
-22,
-69,
-37,
-96,
-6,
-236,
-65,
-174,
-129,
-174,
-205,
-226,
-235,
-180,
-125,
-46,
-185,
-239,
-200,
-114,
-161,
-237,
-106,
-250,
-215,
-118,
-226,
-108,
-139,
-124,
-76,
-110,
-211,
-73,
-50,
-3,
-49,
-170,
-58,
-20,
-143,
-14,
-170,
-102,
-204,
-142,
-154,
-0,
-80,
-30,
-222,
-72,
-198,
-90,
-119,
-93,
-155,
-228,
-11,
-222,
-105,
-0,
-0,
-32,
-0,
-73,
-68,
-65,
-84,
-126,
-245,
-10,
-223,
-77,
-35,
-103,
-184,
-54,
-55,
-252,
-109,
-192,
-179,
-75,
-218,
-94,
-175,
-52,
-222,
-250,
-154,
-235,
-30,
-168,
-109,
-127,
-210,
-178,
-223,
-171,
-146,
-235,
-41,
-26,
-69,
-250,
-69,
-172,
-226,
-246,
-65,
-142,
-207,
-30,
-211,
-9,
-244,
-40,
-18,
-179,
-239,
-169,
-88,
-127,
-129,
-188,
-142,
-210,
-62,
-60,
-0,
-60,
-39,
-128,
-190,
-113,
-136,
-108,
-231,
-29,
-185,
-199,
-128,
-151,
-147,
-103,
-16,
-6,
-57,
-222,
-107,
-154,
-61,
-233,
-47,
-218,
-246,
-227,
-77,
-218,
-85,
-244,
-175,
-205,
-210,
-217,
-21,
-134,
-183,
-35,
-177,
-18,
-239,
-33,
-55,
-157,
-29,
-88,
-29,
-86,
-93,
-143,
-252,
-195,
-50,
-42,
-2,
-96,
-84,
-65,
-139,
-240,
-75,
-197,
-155,
-70,
-190,
-12,
-54,
-106,
-203,
-239,
-168,
-176,
-140,
-115,
-6,
-224,
-13,
-228,
-122,
-135,
-25,
-136,
-34,
-241,
-48,
-96,
-227,
-138,
-182,
-214,
-183,
-250,
-3,
-136,
-34,
-240,
-92,
-228,
-4,
-194,
-102,
-214,
-221,
-151,
-81,
-138,
-100,
-27,
-10,
-36,
-86,
-194,
-66,
-237,
-119,
-173,
-7,
-38,
-45,
-67,
-100,
-227,
-199,
-34,
-114,
-161,
-181,
-107,
-203,
-254,
-91,
-151,
-220,
-255,
-182,
-105,
-239,
-233,
-95,
-27,
-1,
-96,
-141,
-176,
-182,
-43,
-148,
-175,
-130,
-152,
-118,
-15,
-40,
-107,
-201,
-133,
-195,
-139,
-60,
-117,
-54,
-151,
-197,
-216,
-250,
-210,
-246,
-13,
-90,
-134,
-95,
-42,
-190,
-60,
-242,
-188,
-238,
-181,
-54,
-220,
-192,
-57,
-74,
-251,
-24,
-18,
-84,
-99,
-50,
-249,
-30,
-26,
-68,
-8,
-121,
-191,
-46,
-228,
-86,
-98,
-135,
-32,
-95,
-224,
-123,
-144,
-47,
-210,
-69,
-228,
-10,
-147,
-191,
-50,
-138,
-185,
-238,
-235,
-128,
-108,
-29,
-166,
-2,
-91,
-6,
-210,
-71,
-15,
-145,
-61,
-22,
-208,
-81,
-0,
-216,
-49,
-251,
-170,
-6,
-109,
-236,
-24,
-123,
-183,
-167,
-238,
-232,
-9,
-39,
-0,
-232,
-16,
-126,
-201,
-35,
-0,
-172,
-86,
-62,
-40,
-35,
-47,
-158,
-76,
-61,
-192,
-243,
-200,
-45,
-206,
-22,
-1,
-219,
-122,
-104,
-158,
-112,
-234,
-191,
-228,
-78,
-116,
-196,
-108,
-210,
-30,
-13,
-214,
-166,
-7,
-79,
-24,
-93,
-116,
-20,
-0,
-214,
-131,
-114,
-26,
-18,
-200,
-165,
-54,
-89,
-8,
-185,
-221,
-199,
-21,
-56,
-33,
-235,
-17,
-109,
-187,
-213,
-196,
-79,
-40,
-1,
-208,
-58,
-252,
-146,
-71,
-0,
-156,
-161,
-191,
-255,
-71,
-71,
-175,
-54,
-135,
-215,
-217,
-158,
-58,
-171,
-184,
-250,
-105,
-73,
-91,
-107,
-100,
-84,
-233,
-217,
-151,
-48,
-250,
-112,
-198,
-208,
-250,
-72,
-120,
-178,
-43,
-244,
-67,
-242,
-36,
-178,
-69,
-169,
-212,
-209,
-0,
-7,
-56,
-60,
-230,
-35,
-137,
-76,
-94,
-91,
-65,
-255,
-26,
-103,
-252,
-204,
-64,
-156,
-186,
-172,
-201,
-241,
-183,
-24,
-35,
-218,
-118,
-2,
-17,
-227,
-66,
-173,
-195,
-47,
-57,
-253,
-176,
-2,
-96,
-53,
-196,
-198,
-29,
-100,
-41,
-254,
-77,
-90,
-46,
-195,
-145,
-99,
-53,
-240,
-251,
-79,
-91,
-205,
-185,
-55,
-12,
-54,
-98,
-224,
-3,
-53,
-161,
-200,
-144,
-213,
-198,
-137,
-200,
-82,
-124,
-62,
-178,
-31,
-191,
-4,
-201,
-224,
-227,
-205,
-136,
-172,
-237,
-90,
-5,
-147,
-64,
-146,
-119,
-124,
-13,
-81,
-194,
-77,
-211,
-107,
-78,
-69,
-132,
-221,
-86,
-177,
-219,
-141,
-7,
-56,
-99,
-200,
-166,
-115,
-191,
-27,
-217,
-130,
-218,
-119,
-60,
-159,
-146,
-248,
-12,
-192,
-203,
-144,
-45,
-228,
-99,
-200,
-135,
-234,
-50,
-135,
-223,
-241,
-192,
-178,
-37,
-237,
-222,
-128,
-156,
-66,
-77,
-67,
-38,
-252,
-53,
-168,
-249,
-54,
-37,
-218,
-246,
-226,
-88,
-47,
-212,
-133,
-132,
-236,
-170,
-132,
-167,
-93,
-85,
-46,
-5,
-107,
-143,
-210,
-42,
-212,
-94,
-241,
-66,
-173,
-195,
-47,
-249,
-30,
-10,
-162,
-37,
-255,
-6,
-121,
-128,
-131,
-179,
-129,
-167,
-181,
-232,
-151,
-245,
-128,
-26,
-8,
-208,
-128,
-40,
-42,
-161,
-160,
-252,
-113,
-234,
-159,
-161,
-245,
-165,
-89,
-109,
-17,
-187,
-118,
-235,
-140,
-51,
-23,
-209,
-67,
-184,
-105,
-209,
-75,
-99,
-236,
-211,
-50,
-152,
-4,
-185,
-185,
-245,
-124,
-228,
-20,
-228,
-42,
-242,
-237,
-204,
-2,
-224,
-245,
-49,
-219,
-85,
-244,
-227,
-45,
-218,
-54,
-232,
-232,
-209,
-211,
-126,
-64,
-168,
-35,
-19,
-174,
-18,
-37,
-188,
-44,
-230,
-3,
-187,
-56,
-229,
-171,
-59,
-247,
-93,
-182,
-58,
-181,
-31,
-155,
-55,
-59,
-101,
-219,
-144,
-7,
-118,
-245,
-174,
-16,
-219,
-192,
-233,
-103,
-83,
-1,
-112,
-82,
-200,
-191,
-6,
-253,
-88,
-146,
-252,
-4,
-173,
-117,
-176,
-29,
-151,
-97,
-235,
-140,
-168,
-53,
-15,
-101,
-11,
-114,
-79,
-168,
-160,
-228,
-34,
-133,
-246,
-239,
-212,
-182,
-183,
-122,
-234,
-172,
-17,
-145,
-247,
-1,
-144,
-11,
-143,
-187,
-43,
-248,
-219,
-243,
-252,
-75,
-113,
-204,
-128,
-17,
-171,
-172,
-255,
-171,
-233,
-91,
-171,
-96,
-18,
-136,
-78,
-229,
-211,
-56,
-206,
-63,
-136,
-213,
-164,
-221,
-151,
-150,
-5,
-20,
-109,
-213,
-174,
-162,
-31,
-246,
-20,
-197,
-187,
-234,
-83,
-154,
-181,
-17,
-99,
-171,
-199,
-245,
-126,
-183,
-208,
-242,
-221,
-128,
-251,
-60,
-244,
-239,
-69,
-242,
-44,
-22,
-255,
-253,
-81,
-175,
-229,
-181,
-52,
-116,
-198,
-208,
-81,
-158,
-58,
-235,
-7,
-255,
-96,
-73,
-91,
-43,
-192,
-87,
-45,
-148,
-111,
-169,
-229,
-211,
-124,
-237,
-218,
-160,
-102,
-172,
-183,
-182,
-31,
-104,
-209,
-15,
-107,
-185,
-121,
-55,
-45,
-62,
-172,
-62,
-134,
-173,
-195,
-47,
-85,
-61,
-20,
-173,
-183,
-166,
-177,
-222,
-244,
-226,
-53,
-188,
-173,
-153,
-241,
-64,
-116,
-94,
-29,
-108,
-32,
-202,
-203,
-1,
-15,
-62,
-224,
-251,
-90,
-95,
-154,
-43,
-143,
-124,
-133,
-210,
-58,
-99,
-75,
-44,
-144,
-123,
-36,
-54,
-90,
-210,
-181,
-105,
-135,
-100,
-199,
-93,
-132,
-28,
-161,
-121,
-151,
-200,
-74,
-119,
-28,
-178,
-23,
-159,
-172,
-244,
-139,
-244,
-255,
-179,
-8,
-207,
-21,
-185,
-20,
-249,
-87,
-220,
-235,
-106,
-237,
-140,
-161,
-1,
-111,
-57,
-242,
-92,
-9,
-197,
-248,
-139,
-182,
-222,
-58,
-103,
-125,
-177,
-80,
-190,
-154,
-150,
-63,
-28,
-210,
-207,
-16,
-140,
-5,
-1,
-128,
-196,
-143,
-176,
-10,
-238,
-82,
-225,
-221,
-148,
-105,
-235,
-240,
-75,
-1,
-2,
-96,
-11,
-173,
-247,
-45,
-227,
-255,
-12,
-236,
-4,
-172,
-84,
-40,
-127,
-22,
-185,
-121,
-234,
-116,
-96,
-125,
-79,
-219,
-165,
-200,
-61,
-168,
-46,
-70,
-181,
-191,
-136,
-117,
-219,
-222,
-200,
-228,
-94,
-68,
-197,
-241,
-144,
-211,
-247,
-129,
-243,
-224,
-97,
-131,
-138,
-156,
-245,
-177,
-219,
-1,
-63,
-214,
-38,
-3,
-57,
-10,
-11,
-116,
-83,
-129,
-15,
-232,
-255,
-95,
-140,
-172,
-2,
-108,
-154,
-171,
-160,
-212,
-220,
-136,
-82,
-13,
-224,
-156,
-10,
-26,
-139,
-1,
-165,
-113,
-221,
-196,
-66,
-44,
-231,
-108,
-252,
-201,
-19,
-201,
-117,
-81,
-54,
-191,
-197,
-9,
-33,
-253,
-12,
-188,
-151,
-210,
-177,
-94,
-215,
-207,
-136,
-125,
-248,
-182,
-94,
-230,
-26,
-98,
-185,
-99,
-211,
-33,
-252,
-146,
-251,
-80,
-244,
-101,
-63,
-203,
-169,
-91,
-154,
-220,
-34,
-112,
-96,
-175,
-233,
-180,
-93,
-132,
-68,
-215,
-185,
-158,
-145,
-250,
-136,
-71,
-41,
-217,
-227,
-107,
-251,
-231,
-147,
-239,
-217,
-231,
-33,
-123,
-120,
-55,
-88,
-68,
-229,
-254,
-200,
-161,
-107,
-44,
-0,
-104,
-153,
-179,
-14,
-17,
-92,
-31,
-68,
-142,
-57,
-39,
-33,
-210,
-124,
-58,
-185,
-86,
-186,
-108,
-160,
-183,
-106,
-231,
-225,
-179,
-28,
-121,
-32,
-144,
-245,
-234,
-250,
-26,
-194,
-179,
-162,
-253,
-75,
-245,
-189,
-60,
-65,
-197,
-177,
-176,
-59,
-134,
-60,
-117,
-33,
-105,
-188,
-94,
-67,
-190,
-202,
-88,
-132,
-40,
-74,
-23,
-33,
-218,
-253,
-213,
-187,
-220,
-67,
-204,
-126,
-70,
-184,
-254,
-51,
-201,
-21,
-163,
-241,
-130,
-165,
-210,
-33,
-252,
-146,
-251,
-80,
-156,
-23,
-112,
-51,
-98,
-16,
-100,
-39,
-243,
-130,
-146,
-182,
-111,
-67,
-162,
-235,
-220,
-138,
-44,
-43,
-109,
-176,
-135,
-203,
-144,
-211,
-131,
-218,
-224,
-154,
-136,
-178,
-239,
-80,
-229,
-49,
-87,
-219,
-159,
-77,
-64,
-242,
-72,
-167,
-239,
-141,
-4,
-0,
-237,
-141,
-166,
-214,
-36,
-247,
-165,
-183,
-207,
-197,
-70,
-82,
-182,
-171,
-25,
-159,
-18,
-169,
-85,
-187,
-146,
-62,
-216,
-253,
-227,
-233,
-77,
-238,
-185,
-41,
-144,
-152,
-131,
-54,
-198,
-226,
-110,
-53,
-180,
-79,
-141,
-33,
-79,
-93,
-240,
-196,
-2,
-94,
-133,
-172,
-28,
-109,
-148,
-235,
-203,
-112,
-18,
-170,
-118,
-69,
-172,
-126,
-118,
-184,
-190,
-141,
-223,
-248,
-215,
-62,
-152,
-119,
-201,
-136,
-138,
-62,
-128,
-189,
-244,
-161,
-79,
-67,
-36,
-255,
-20,
-100,
-153,
-223,
-200,
-214,
-190,
-111,
-144,
-107,
-240,
-189,
-168,
-105,
-219,
-197,
-104,
-234,
-55,
-90,
-55,
-21,
-49,
-58,
-121,
-186,
-83,
-87,
-165,
-69,
-110,
-213,
-174,
-164,
-255,
-255,
-85,
-242,
-202,
-47,
-8,
-29,
-143,
-29,
-17,
-229,
-31,
-4,
-164,
-238,
-114,
-199,
-144,
-167,
-174,
-241,
-196,
-66,
-78,
-15,
-78,
-213,
-102,
-165,
-91,
-143,
-166,
-168,
-233,
-103,
-175,
-17,
-123,
-128,
-23,
-34,
-130,
-127,
-1,
-125,
-69,
-101,
-166,
-135,
-240,
-75,
-99,
-17,
-136,
-143,
-194,
-105,
-206,
-11,
-61,
-71,
-127,
-159,
-134,
-39,
-244,
-121,
-161,
-109,
-23,
-163,
-41,
-187,
-106,
-24,
-8,
-23,
-70,
-158,
-67,
-209,
-39,
-0,
-90,
-181,
-243,
-208,
-110,
-173,
-164,
-33,
-110,
-222,
-173,
-143,
-29,
-17,
-197,
-164,
-13,
-150,
-26,
-178,
-138,
-171,
-154,
-88,
-173,
-190,
-172,
-136,
-16,
-128,
-192,
-32,
-39,
-129,
-60,
-45,
-124,
-62,
-4,
-189,
-70,
-236,
-33,
-63,
-181,
-57,
-186,
-15,
-254,
-19,
-18,
-85,
-47,
-180,
-162,
-77,
-23,
-163,
-41,
-123,
-234,
-176,
-173,
-167,
-206,
-38,
-21,
-241,
-9,
-128,
-86,
-237,
-60,
-180,
-246,
-171,
-248,
-169,
-0,
-218,
-182,
-199,
-149,
-79,
-71,
-182,
-128,
-224,
-177,
-181,
-47,
-105,
-211,
-74,
-0,
-32,
-142,
-103,
-251,
-81,
-80,
-18,
-35,
-129,
-91,
-191,
-172,
-205,
-188,
-193,
-104,
-218,
-192,
-233,
-167,
-207,
-135,
-224,
-136,
-190,
-4,
-0,
-121,
-66,
-145,
-25,
-44,
-38,
-31,
-225,
-49,
-129,
-150,
-2,
-160,
-139,
-209,
-148,
-221,
-175,
-31,
-135,
-42,
-216,
-116,
-176,
-238,
-69,
-133,
-50,
-175,
-109,
-187,
-2,
-143,
-103,
-145,
-39,
-109,
-25,
-240,
-191,
-104,
-112,
-255,
-149,
-199,
-142,
-136,
-98,
-20,
-224,
-196,
-6,
-60,
-45,
-154,
-10,
-128,
-45,
-156,
-182,
-83,
-145,
-149,
-235,
-21,
-228,
-43,
-166,
-57,
-56,
-6,
-66,
-93,
-225,
-92,
-171,
-232,
-67,
-240,
-46,
-122,
-138,
-216,
-163,
-239,
-217,
-234,
-127,
-190,
-21,
-147,
-247,
-168,
-163,
-234,
-197,
-7,
-180,
-253,
-56,
-18,
-94,
-123,
-153,
-170,
-178,
-138,
-246,
-75,
-59,
-215,
-127,
-126,
-29,
-189,
-211,
-174,
-139,
-209,
-212,
-78,
-133,
-1,
-123,
-53,
-185,
-13,
-198,
-126,
-168,
-34,
-54,
-86,
-187,
-2,
-15,
-107,
-47,
-255,
-243,
-208,
-123,
-45,
-225,
-83,
-122,
-236,
-136,
-36,
-191,
-180,
-39,
-58,
-193,
-9,
-82,
-170,
-198,
-1,
-213,
-2,
-96,
-57,
-224,
-115,
-250,
-188,
-109,
-92,
-134,
-199,
-16,
-229,
-227,
-49,
-68,
-202,
-112,
-237,
-233,
-39,
-228,
-62,
-4,
-174,
-242,
-124,
-126,
-221,
-123,
-104,
-113,
-205,
-143,
-40,
-255,
-7,
-0,
-111,
-78,
-193,
-113,
-139,
-170,
-23,
-31,
-208,
-214,
-198,
-19,
-60,
-162,
-170,
-172,
-162,
-253,
-122,
-206,
-245,
-87,
-171,
-163,
-119,
-218,
-117,
-202,
-89,
-135,
-248,
-155,
-95,
-142,
-40,
-11,
-167,
-33,
-166,
-172,
-239,
-214,
-186,
-147,
-203,
-6,
-80,
-219,
-118,
-90,
-239,
-166,
-245,
-10,
-18,
-118,
-180,
-56,
-118,
-116,
-38,
-195,
-121,
-248,
-45,
-2,
-127,
-0,
-172,
-27,
-246,
-164,
-198,
-30,
-156,
-241,
-178,
-23,
-114,
-234,
-51,
-15,
-17,
-118,
-135,
-33,
-6,
-58,
-255,
-139,
-41,
-0,
-144,
-237,
-148,
-85,
-56,
-119,
-10,
-186,
-210,
-244,
-194,
-0,
-199,
-55,
-108,
-179,
-153,
-14,
-208,
-25,
-192,
-5,
-84,
-4,
-243,
-40,
-92,
-167,
-173,
-0,
-88,
-150,
-124,
-105,
-180,
-91,
-89,
-89,
-69,
-123,
-155,
-171,
-189,
-209,
-30,
-145,
-33,
-228,
-172,
-139,
-13,
-36,
-104,
-10,
-4,
-154,
-11,
-211,
-254,
-184,
-50,
-4,
-193,
-126,
-251,
-99,
-13,
-206,
-61,
-84,
-218,
-79,
-68,
-188,
-222,
-87,
-236,
-24,
-101,
-152,
-113,
-45,
-90,
-10,
-128,
-203,
-145,
-229,
-247,
-54,
-136,
-86,
-253,
-162,
-192,
-235,
-180,
-18,
-0,
-218,
-254,
-121,
-136,
-192,
-153,
-137,
-6,
-201,
-240,
-149,
-121,
-218,
-109,
-133,
-236,
-229,
-231,
-18,
-96,
-47,
-80,
-104,
-59,
-30,
-115,
-214,
-89,
-135,
-153,
-218,
-156,
-135,
-74,
-31,
-237,
-216,
-113,
-113,
-130,
-51,
-94,
-135,
-18,
-9,
-153,
-60,
-206,
-228,
-221,
-52,
-216,
-106,
-182,
-189,
-216,
-26,
-136,
-59,
-166,
-53,
-222,
-88,
-136,
-44,
-233,
-206,
-69,
-114,
-215,
-85,
-38,
-59,
-208,
-9,
-103,
-131,
-23,
-238,
-2,
-76,
-15,
-184,
-102,
-39,
-1,
-160,
-60,
-62,
-172,
-60,
-110,
-69,
-77,
-138,
-125,
-101,
-37,
-215,
-125,
-130,
-234,
-116,
-232,
-3,
-171,
-3,
-198,
-89,
-206,
-58,
-114,
-167,
-168,
-187,
-8,
-252,
-138,
-16,
-233,
-216,
-113,
-113,
-67,
-140,
-241,
-218,
-242,
-122,
-149,
-136,
-113,
-161,
-13,
-200,
-227,
-243,
-89,
-239,
-170,
-39,
-201,
-205,
-14,
-161,
-102,
-201,
-139,
-104,
-96,
-207,
-66,
-206,
-154,
-207,
-1,
-46,
-108,
-112,
-131,
-27,
-21,
-202,
-215,
-118,
-38,
-217,
-55,
-107,
-120,
-216,
-201,
-126,
-39,
-185,
-103,
-222,
-64,
-89,
-201,
-117,
-91,
-61,
-92,
-122,
-202,
-89,
-215,
-7,
-144,
-92,
-132,
-0,
-95,
-105,
-208,
-38,
-202,
-177,
-99,
-108,
-208,
-62,
-6,
-67,
-171,
-140,
-87,
-30,
-62,
-222,
-241,
-58,
-238,
-1,
-252,
-93,
-111,
-236,
-100,
-228,
-11,
-7,
-226,
-219,
-157,
-33,
-129,
-53,
-190,
-10,
-172,
-80,
-195,
-99,
-115,
-228,
-120,
-100,
-38,
-226,
-156,
-83,
-27,
-103,
-223,
-247,
-64,
-245,
-250,
-54,
-237,
-118,
-93,
-86,
-160,
-231,
-233,
-75,
-157,
-141,
-134,
-127,
-246,
-149,
-245,
-1,
-250,
-203,
-89,
-119,
-157,
-254,
-191,
-113,
-100,
-28,
-15,
-191,
-213,
-180,
-253,
-156,
-38,
-3,
-159,
-8,
-199,
-142,
-125,
-128,
-246,
-49,
-24,
-26,
-103,
-188,
-42,
-225,
-179,
-216,
-10,
-0,
-251,
-213,
-127,
-174,
-254,
-134,
-134,
-58,
-128,
-150,
-215,
-29,
-241,
-64,
-17,
-205,
-179,
-21,
-70,
-103,
-81,
-177,
-100,
-101,
-164,
-194,
-239,
-163,
-101,
-101,
-227,
-9,
-218,
-239,
-89,
-136,
-9,
-46,
-52,
-136,
-140,
-19,
-185,
-31,
-157,
-143,
-29,
-27,
-92,
-43,
-56,
-47,
-2,
-45,
-99,
-48,
-40,
-109,
-163,
-140,
-87,
-37,
-60,
-22,
-91,
-1,
-96,
-131,
-118,
-188,
-64,
-127,
-15,
-91,
-0,
-172,
-171,
-191,
-173,
-179,
-195,
-21,
-212,
-156,
-121,
-146,
-31,
-249,
-29,
-85,
-85,
-54,
-158,
-224,
-60,
-143,
-198,
-145,
-113,
-122,
-232,
-75,
-235,
-99,
-199,
-134,
-215,
-105,
-148,
-23,
-161,
-227,
-181,
-130,
-51,
-94,
-77,
-40,
-144,
-107,
-125,
-207,
-71,
-210,
-101,
-5,
-11,
-0,
-58,
-56,
-141,
-56,
-3,
-126,
-37,
-242,
-175,
-222,
-109,
-132,
-217,
-143,
-239,
-133,
-232,
-26,
-150,
-169,
-42,
-27,
-79,
-112,
-158,
-71,
-227,
-200,
-56,
-227,
-17,
-52,
-204,
-139,
-176,
-56,
-3,
-120,
-1,
-146,
-165,
-249,
-78,
-68,
-7,
-243,
-32,
-178,
-157,
-252,
-70,
-9,
-125,
-20,
-189,
-134,
-101,
-182,
-22,
-185,
-59,
-171,
-53,
-105,
-60,
-139,
-138,
-104,
-49,
-158,
-142,
-180,
-113,
-26,
-65,
-7,
-192,
-251,
-201,
-131,
-58,
-116,
-138,
-36,
-60,
-158,
-225,
-8,
-128,
-198,
-145,
-113,
-198,
-35,
-104,
-144,
-23,
-161,
-203,
-135,
-102,
-172,
-3,
-9,
-125,
-103,
-183,
-225,
-243,
-17,
-155,
-11,
-155,
-113,
-219,
-235,
-250,
-75,
-36,
-189,
-134,
-203,
-112,
-5,
-196,
-189,
-213,
-77,
-181,
-253,
-40,
-146,
-130,
-107,
-224,
-40,
-205,
-105,
-215,
-58,
-86,
-157,
-35,
-0,
-102,
-59,
-215,
-236,
-100,
-170,
-218,
-7,
-144,
-147,
-141,
-63,
-170,
-144,
-156,
-141,
-40,
-58,
-39,
-35,
-22,
-96,
-3,
-251,
-73,
-231,
-94,
-26,
-125,
-213,
-156,
-118,
-141,
-34,
-227,
-180,
-189,
-222,
-120,
-2,
-237,
-131,
-169,
-142,
-105,
-193,
-129,
-164,
-147,
-183,
-167,
-71,
-191,
-64,
-77,
-168,
-17,
-5,
-252,
-22,
-84,
-40,
-178,
-137,
-160,
-215,
-240,
-49,
-93,
-74,
-59,
-243,
-8,
-249,
-106,
-224,
-54,
-26,
-90,
-63,
-17,
-16,
-171,
-206,
-25,
-184,
-23,
-0,
-219,
-59,
-15,
-98,
-224,
-11,
-56,
-90,
-0,
-118,
-37,
-95,
-157,
-216,
-140,
-173,
-55,
-145,
-167,
-151,
-58,
-204,
-211,
-166,
-171,
-0,
-104,
-27,
-118,
-122,
-113,
-22,
-0,
-109,
-189,
-19,
-27,
-11,
-142,
-182,
-239,
-193,
-161,
-9,
-94,
-206,
-147,
-39,
-208,
-253,
-119,
-248,
-211,
-24,
-209,
-62,
-190,
-94,
-67,
-59,
-116,
-60,
-34,
-157,
-172,
-251,
-107,
-35,
-229,
-19,
-1,
-177,
-234,
-138,
-15,
-26,
-201,
-84,
-11,
-226,
-71,
-62,
-38,
-220,
-30,
-201,
-131,
-78,
-126,
-169,
-80,
-190,
-58,
-240,
-73,
-60,
-130,
-177,
-237,
-132,
-108,
-59,
-240,
-34,
-92,
-207,
-98,
-158,
-14,
-166,
-179,
-245,
-93,
-84,
-157,
-194,
-52,
-254,
-178,
-182,
-189,
-191,
-154,
-123,
-168,
-243,
-78,
-108,
-44,
-56,
-186,
-244,
-147,
-134,
-203,
-121,
-68,
-225,
-13,
-99,
-196,
-110,
-196,
-24,
-51,
-242,
-20,
-0,
-216,
-68,
-127,
-151,
-133,
-116,
-110,
-29,
-171,
-206,
-247,
-160,
-201,
-67,
-72,
-159,
-67,
-172,
-160,
-135,
-35,
-175,
-217,
-52,
-181,
-182,
-53,
-138,
-121,
-69,
-131,
-107,
-88,
-12,
-91,
-0,
-88,
-204,
-67,
-38,
-227,
-57,
-192,
-158,
-148,
-196,
-246,
-115,
-232,
-109,
-214,
-224,
-171,
-16,
-133,
-156,
-197,
-69,
-148,
-164,
-254,
-102,
-20,
-190,
-172,
-37,
-253,
-104,
-27,
-76,
-181,
-84,
-112,
-116,
-120,
-15,
-141,
-151,
-243,
-228,
-199,
-171,
-3,
-17,
-164,
-70,
-13,
-218,
-161,
-227,
-245,
-255,
-214,
-231,
-218,
-151,
-157,
-167,
-83,
-172,
-58,
-223,
-131,
-70,
-190,
-172,
-54,
-208,
-231,
-126,
-145,
-239,
-171,
-77,
-106,
-109,
-187,
-2,
-186,
-140,
-26,
-115,
-104,
-167,
-141,
-197,
-176,
-5,
-64,
-217,
-68,
-190,
-20,
-207,
-177,
-170,
-175,
-159,
-72,
-210,
-137,
-221,
-201,
-183,
-56,
-7,
-148,
-244,
-117,
-216,
-95,
-214,
-40,
-65,
-81,
-29,
-126,
-85,
-110,
-205,
-109,
-223,
-67,
-227,
-229,
-60,
-185,
-123,
-121,
-155,
-15,
-76,
-41,
-66,
-121,
-89,
-134,
-199,
-2,
-219,
-162,
-199,
-103,
-202,
-227,
-120,
-36,
-20,
-180,
-205,
-246,
-251,
-27,
-79,
-187,
-78,
-78,
-35,
-101,
-15,
-26,
-209,
-7,
-44,
-66,
-190,
-190,
-47,
-109,
-116,
-51,
-229,
-215,
-106,
-155,
-90,
-251,
-185,
-228,
-89,
-102,
-108,
-222,
-185,
-186,
-120,
-122,
-22,
-163,
-182,
-5,
-96,
-112,
-34,
-127,
-183,
-73,
-63,
-117,
-76,
-0,
-220,
-212,
-240,
-30,
-250,
-248,
-178,
-182,
-254,
-208,
-208,
-206,
-173,
-185,
-109,
-63,
-27,
-47,
-231,
-201,
-87,
-77,
-219,
-54,
-104,
-99,
-97,
-5,
-126,
-55,
-7,
-33,
-135,
-225,
-28,
-242,
-227,
-192,
-69,
-78,
-249,
-36,
-60,
-103,
-243,
-116,
-116,
-26,
-169,
-121,
-208,
-54,
-118,
-253,
-77,
-68,
-8,
-132,
-64,
-135,
-212,
-218,
-200,
-151,
-237,
-235,
-140,
-60,
-33,
-249,
-95,
-217,
-75,
-115,
-104,
-70,
-93,
-7,
-64,
-197,
-68,
-174,
-105,
-183,
-187,
-29,
-19,
-13,
-239,
-161,
-143,
-47,
-107,
-219,
-96,
-170,
-93,
-221,
-154,
-155,
-246,
-179,
-241,
-114,
-30,
-177,
-244,
-132,
-6,
-89,
-172,
-171,
-222,
-91,
-43,
-32,
-190,
-241,
-127,
-67,
-150,
-222,
-118,
-73,
-50,
-13,
-56,
-29,
-217,
-67,
-150,
-37,
-88,
-28,
-147,
-78,
-35,
-125,
-1,
-9,
-172,
-241,
-254,
-194,
-160,
-218,
-217,
-67,
-215,
-234,
-5,
-117,
-24,
-120,
-165,
-215,
-163,
-98,
-34,
-215,
-180,
-219,
-77,
-235,
-158,
-40,
-233,
-235,
-48,
-191,
-172,
-109,
-131,
-169,
-182,
-21,
-28,
-109,
-251,
-217,
-102,
-57,
-127,
-176,
-182,
-57,
-191,
-65,
-155,
-210,
-247,
-22,
-5,
-202,
-252,
-248,
-0,
-186,
-49,
-233,
-52,
-210,
-55,
-244,
-30,
-109,
-16,
-200,
-41,
-158,
-250,
-126,
-95,
-80,
-131,
-235,
-81,
-49,
-145,
-107,
-218,
-157,
-160,
-117,
-255,
-242,
-212,
-13,
-251,
-203,
-218,
-54,
-152,
-106,
-91,
-193,
-81,
-213,
-207,
-23,
-87,
-180,
-107,
-179,
-156,
-95,
-151,
-60,
-143,
-193,
-33,
-56,
-241,
-26,
-145,
-20,
-110,
-187,
-86,
-244,
-111,
-212,
-5,
-192,
-208,
-156,
-70,
-186,
-160,
-237,
-192,
-171,
-225,
-249,
-82,
-109,
-214,
-232,
-203,
-218,
-7,
-170,
-174,
-71,
-245,
-68,
-30,
-104,
-135,
-56,
-84,
-125,
-158,
-92,
-119,
-240,
-78,
-79,
-187,
-62,
-190,
-172,
-85,
-19,
-171,
-109,
-48,
-213,
-182,
-130,
-195,
-222,
-187,
-47,
-252,
-247,
-59,
-42,
-218,
-53,
-94,
-206,
-107,
-187,
-247,
-145,
-219,
-220,
-204,
-67,
-156,
-192,
-102,
-233,
-239,
-255,
-120,
-232,
-75,
-223,
-119,
-20,
-40,
-243,
-227,
-3,
-105,
-135,
-226,
-52,
-210,
-5,
-53,
-3,
-175,
-106,
-192,
-110,
-128,
-132,
-151,
-222,
-160,
-80,
-254,
-52,
-114,
-39,
-150,
-43,
-43,
-174,
-55,
-106,
-2,
-128,
-176,
-137,
-108,
-97,
-149,
-73,
-215,
-49,
-50,
-6,
-196,
-129,
-37,
-215,
-107,
-251,
-101,
-109,
-59,
-177,
-218,
-6,
-83,
-109,
-43,
-56,
-172,
-137,
-173,
-47,
-252,
-247,
-209,
-21,
-237,
-26,
-47,
-231,
-157,
-182,
-155,
-35,
-185,
-13,
-239,
-65,
-182,
-18,
-51,
-144,
-147,
-167,
-15,
-121,
-104,
-7,
-222,
-247,
-98,
-5,
-106,
-34,
-215,
-208,
-208,
-17,
-194,
-121,
-96,
-93,
-194,
-78,
-63,
-128,
-104,
-121,
-175,
-36,
-15,
-213,
-52,
-11,
-216,
-186,
-226,
-122,
-195,
-22,
-0,
-77,
-39,
-114,
-17,
-179,
-144,
-19,
-143,
-147,
-80,
-159,
-251,
-146,
-118,
-109,
-191,
-172,
-173,
-38,
-150,
-214,
-55,
-254,
-208,
-208,
-94,
-112,
-216,
-163,
-204,
-98,
-248,
-239,
-247,
-144,
-239,
-243,
-125,
-237,
-26,
-47,
-231,
-219,
-192,
-243,
-222,
-6,
-16,
-227,
-58,
-189,
-130,
-134,
-185,
-231,
-11,
-109,
-27,
-57,
-66,
-56,
-207,
-165,
-75,
-216,
-233,
-71,
-145,
-175,
-198,
-227,
-136,
-31,
-192,
-49,
-192,
-38,
-53,
-215,
-27,
-182,
-0,
-176,
-8,
-157,
-200,
-173,
-250,
-73,
-251,
-47,
-107,
-171,
-137,
-213,
-5,
-180,
-19,
-28,
-175,
-113,
-238,
-195,
-134,
-255,
-182,
-17,
-160,
-190,
-133,
-90,
-250,
-149,
-92,
-175,
-209,
-114,
-190,
-229,
-61,
-89,
-196,
-57,
-6,
-28,
-13,
-208,
-49,
-247,
-60,
-13,
-28,
-33,
-156,
-7,
-54,
-148,
-164,
-142,
-109,
-39,
-214,
-176,
-175,
-215,
-161,
-93,
-219,
-47,
-107,
-235,
-137,
-53,
-108,
-0,
-111,
-64,
-220,
-227,
-167,
-105,
-191,
-174,
-65,
-183,
-60,
-168,
-0,
-172,
-104,
-27,
-188,
-156,
-111,
-217,
-183,
-161,
-142,
-175,
-94,
-64,
-156,
-220,
-243,
-65,
-142,
-16,
-73,
-0,
-196,
-109,
-167,
-109,
-219,
-230,
-55,
-104,
-61,
-177,
-198,
-27,
-144,
-128,
-172,
-179,
-233,
-47,
-65,
-73,
-52,
-59,
-128,
-149,
-129,
-207,
-34,
-182,
-223,
-143,
-35,
-75,
-151,
-59,
-145,
-163,
-174,
-210,
-188,
-238,
-5,
-30,
-63,
-69,
-246,
-63,
-191,
-8,
-164,
-239,
-148,
-123,
-190,
-9,
-70,
-81,
-0,
-148,
-46,
-209,
-208,
-8,
-202,
-145,
-175,
-55,
-52,
-1,
-144,
-80,
-15,
-196,
-106,
-116,
-145,
-10,
-188,
-82,
-33,
-64,
-190,
-69,
-216,
-190,
-170,
-204,
-169,
-139,
-46,
-0,
-174,
-115,
-152,
-62,
-142,
-132,
-8,
-179,
-150,
-128,
-15,
-17,
-96,
-3,
-79,
-238,
-241,
-52,
-51,
-74,
-167,
-34,
-162,
-70,
-0,
-148,
-30,
-63,
-69,
-184,
-94,
-21,
-62,
-223,
-195,
-245,
-146,
-0,
-24,
-67,
-0,
-222,
-77,
-158,
-133,
-250,
-218,
-10,
-186,
-187,
-138,
-239,
-193,
-87,
-230,
-212,
-69,
-23,
-0,
-123,
-0,
-63,
-193,
-201,
-59,
-142,
-36,
-147,
-188,
-64,
-47,
-116,
-106,
-0,
-143,
-35,
-145,
-229,
-78,
-200,
-254,
-29,
-90,
-68,
-191,
-173,
-153,
-200,
-85,
-202,
-188,
-86,
-199,
-79,
-139,
-59,
-22,
-87,
-1,
-64,
-131,
-64,
-163,
-67,
-234,
-207,
-165,
-148,
-88,
-84,
-106,
-189,
-61,
-213,
-90,
-167,
-170,
-204,
-169,
-27,
-206,
-123,
-3,
-94,
-168,
-23,
-122,
-44,
-50,
-95,
-104,
-17,
-253,
-182,
-131,
-0,
-104,
-125,
-252,
-180,
-56,
-99,
-49,
-22,
-0,
-149,
-129,
-70,
-145,
-232,
-87,
-7,
-33,
-39,
-37,
-115,
-144,
-237,
-238,
-161,
-212,
-132,
-190,
-111,
-216,
-135,
-157,
-145,
-21,
-192,
-1,
-122,
-141,
-210,
-108,
-201,
-72,
-252,
-5,
-112,
-76,
-238,
-125,
-101,
-78,
-221,
-208,
-4,
-192,
-202,
-118,
-178,
-70,
-230,
-107,
-209,
-40,
-250,
-109,
-7,
-1,
-48,
-244,
-227,
-167,
-197,
-25,
-250,
-184,
-46,
-215,
-255,
-175,
-173,
-19,
-238,
-110,
-68,
-195,
-127,
-123,
-69,
-187,
-224,
-88,
-12,
-200,
-10,
-244,
-100,
-100,
-85,
-248,
-36,
-240,
-59,
-2,
-130,
-196,
-16,
-16,
-104,
-84,
-199,
-195,
-34,
-36,
-120,
-201,
-151,
-201,
-147,
-167,
-252,
-182,
-142,
-127,
-40,
-144,
-143,
-217,
-124,
-228,
-68,
-228,
-103,
-84,
-56,
-180,
-33,
-39,
-6,
-211,
-234,
-202,
-156,
-58,
-139,
-126,
-143,
-1,
-17,
-141,
-45,
-212,
-36,
-208,
-68,
-206,
-203,
-33,
-48,
-96,
-165,
-115,
-3,
-141,
-162,
-223,
-118,
-16,
-0,
-227,
-230,
-248,
-105,
-60,
-64,
-159,
-219,
-61,
-72,
-26,
-180,
-41,
-250,
-123,
-33,
-162,
-60,
-190,
-180,
-164,
-77,
-112,
-44,
-6,
-157,
-252,
-54,
-83,
-213,
-249,
-72,
-128,
-218,
-121,
-200,
-74,
-174,
-82,
-8,
-16,
-16,
-104,
-20,
-73,
-152,
-242,
-170,
-66,
-217,
-121,
-68,
-254,
-208,
-133,
-2,
-241,
-124,
-189,
-163,
-174,
-204,
-169,
-171,
-69,
-140,
-78,
-173,
-64,
-238,
-240,
-241,
-165,
-26,
-218,
-87,
-148,
-77,
-218,
-154,
-27,
-104,
-20,
-253,
-214,
-105,
-215,
-38,
-160,
-68,
-47,
-199,
-79,
-180,
-76,
-87,
-165,
-180,
-65,
-95,
-68,
-242,
-56,
-141,
-62,
-188,
-172,
-77,
-191,
-187,
-64,
-175,
-59,
-31,
-17,
-164,
-255,
-3,
-222,
-132,
-38,
-74,
-197,
-241,
-11,
-112,
-232,
-27,
-197,
-98,
-64,
-143,
-17,
-113,
-50,
-60,
-35,
-66,
-124,
-62,
-112,
-82,
-79,
-247,
-116,
-61,
-48,
-169,
-15,
-222,
-227,
-14,
-72,
-162,
-208,
-203,
-245,
-37,
-92,
-74,
-69,
-22,
-92,
-196,
-2,
-236,
-159,
-74,
-91,
-155,
-161,
-69,
-219,
-88,
-180,
-141,
-126,
-59,
-148,
-227,
-188,
-16,
-208,
-62,
-93,
-85,
-163,
-232,
-68,
-72,
-172,
-185,
-67,
-157,
-103,
-240,
-123,
-224,
-67,
-68,
-136,
-149,
-208,
-20,
-78,
-31,
-30,
-194,
-217,
-82,
-85,
-208,
-55,
-138,
-197,
-160,
-207,
-99,
-96,
-43,
-1,
-252,
-133,
-10,
-101,
-90,
-91,
-32,
-62,
-19,
-139,
-128,
-157,
-98,
-243,
-30,
-119,
-64,
-210,
-45,
-93,
-175,
-47,
-248,
-106,
-52,
-174,
-89,
-5,
-189,
-85,
-162,
-205,
-2,
-158,
-31,
-120,
-141,
-86,
-19,
-121,
-140,
-10,
-128,
-198,
-233,
-170,
-104,
-25,
-157,
-72,
-219,
-90,
-84,
-42,
-128,
-60,
-253,
-170,
-92,
-153,
-208,
-192,
-191,
-194,
-233,
-195,
-103,
-171,
-232,
-218,
-66,
-251,
-112,
-139,
-167,
-252,
-12,
-60,
-251,
-98,
-58,
-172,
-144,
-144,
-192,
-174,
-243,
-129,
-61,
-99,
-222,
-195,
-184,
-5,
-18,
-204,
-16,
-224,
-6,
-106,
-164,
-59,
-146,
-4,
-19,
-100,
-73,
-61,
-96,
-176,
-80,
-209,
-174,
-15,
-1,
-16,
-253,
-60,
-191,
-47,
-208,
-45,
-58,
-81,
-168,
-0,
-104,
-180,
-50,
-161,
-129,
-127,
-133,
-211,
-135,
-94,
-146,
-175,
-146,
-7,
-134,
-117,
-21,
-196,
-47,
-71,
-156,
-144,
-188,
-71,
-210,
-180,
-88,
-33,
-1,
-223,
-70,
-20,
-140,
-111,
-9,
-236,
-215,
-146,
-218,
-230,
-38,
-196,
-232,
-237,
-33,
-42,
-182,
-122,
-228,
-130,
-125,
-131,
-50,
-154,
-49,
-7,
-242,
-176,
-87,
-219,
-212,
-208,
-109,
-133,
-44,
-155,
-230,
-1,
-219,
-53,
-188,
-70,
-91,
-1,
-48,
-225,
-207,
-243,
-27,
-8,
-128,
-54,
-43,
-147,
-32,
-255,
-138,
-170,
-247,
-87,
-66,
-223,
-232,
-11,
-13,
-172,
-135,
-248,
-22,
-44,
-2,
-206,
-5,
-206,
-68,
-4,
-218,
-163,
-192,
-179,
-107,
-174,
-85,
-251,
-124,
-116,
-34,
-255,
-82,
-39,
-114,
-208,
-170,
-85,
-219,
-125,
-67,
-121,
-47,
-66,
-244,
-70,
-183,
-0,
-191,
-175,
-160,
-183,
-31,
-211,
-198,
-201,
-68,
-201,
-243,
-100,
-222,
-83,
-65,
-211,
-40,
-194,
-117,
-232,
-133,
-237,
-36,
-27,
-80,
-230,
-20,
-232,
-78,
-87,
-186,
-111,
-182,
-184,
-70,
-233,
-0,
-98,
-140,
-156,
-231,
-59,
-125,
-44,
-53,
-89,
-174,
-24,
-212,
-79,
-33,
-70,
-95,
-74,
-174,
-217,
-203,
-25,
-48,
-1,
-254,
-21,
-85,
-239,
-175,
-162,
-77,
-163,
-47,
-52,
-34,
-4,
-78,
-35,
-215,
-145,
-156,
-74,
-128,
-89,
-122,
-200,
-243,
-65,
-182,
-18,
-51,
-129,
-111,
-34,
-251,
-127,
-247,
-95,
-105,
-106,
-58,
-242,
-120,
-153,
-95,
-112,
-202,
-202,
-66,
-174,
-175,
-134,
-156,
-70,
-52,
-122,
-78,
-78,
-251,
-255,
-105,
-91,
-111,
-162,
-91,
-90,
-68,
-184,
-142,
-10,
-231,
-230,
-26,
-101,
-12,
-210,
-182,
-165,
-3,
-136,
-49,
-114,
-158,
-239,
-244,
-177,
-106,
-9,
-105,
-17,
-124,
-30,
-75,
-0,
-2,
-251,
-53,
-106,
-198,
-59,
-85,
-239,
-175,
-65,
-219,
-190,
-4,
-88,
-45,
-255,
-154,
-199,
-255,
-137,
-138,
-118,
-214,
-205,
-183,
-46,
-148,
-252,
-81,
-228,
-113,
-1,
-138,
-152,
-26,
-112,
-15,
-171,
-146,
-155,
-226,
-15,
-196,
-23,
-164,
-131,
-14,
-201,
-69,
-87,
-103,
-28,
-59,
-1,
-163,
-90,
-9,
-214,
-224,
-96,
-99,
-204,
-91,
-141,
-49,
-47,
-55,
-198,
-220,
-13,
-220,
-108,
-140,
-89,
-195,
-24,
-179,
-158,
-49,
-230,
-219,
-198,
-152,
-47,
-27,
-99,
-158,
-214,
-150,
-57,
-34,
-205,
-247,
-51,
-198,
-236,
-229,
-20,
-79,
-7,
-238,
-50,
-198,
-252,
-57,
-203,
-178,
-50,
-251,
-253,
-221,
-179,
-44,
-187,
-174,
-225,
-229,
-174,
-51,
-198,
-244,
-226,
-55,
-161,
-247,
-49,
-191,
-164,
-250,
-229,
-89,
-150,
-85,
-234,
-25,
-22,
-119,
-100,
-89,
-214,
-56,
-225,
-12,
-146,
-164,
-198,
-158,
-134,
-205,
-171,
-33,
-127,
-194,
-24,
-115,
-184,
-49,
-102,
-127,
-253,
-253,
-75,
-45,
-51,
-198,
-152,
-233,
-1,
-151,
-219,
-198,
-24,
-147,
-25,
-99,
-174,
-206,
-178,
-204,
-103,
-202,
-252,
-87,
-173,
-223,
-42,
-203,
-178,
-73,
-218,
-191,
-173,
-141,
-49,
-167,
-107,
-93,
-187,
-163,
-97,
-100,
-95,
-52,
-27,
-56,
-60,
-128,
-246,
-30,
-149,
-80,
-3,
-38,
-187,
-1,
-109,
-75,
-191,
-32,
-140,
-210,
-121,
-190,
-182,
-63,
-217,
-233,
-219,
-44,
-196,
-168,
-228,
-94,
-253,
-253,
-231,
-138,
-251,
-8,
-254,
-154,
-181,
-105,
-211,
-166,
-61,
-13,
-150,
-220,
-52,
-223,
-163,
-151,
-190,
-191,
-88,
-253,
-111,
-139,
-62,
-248,
-35,
-123,
-255,
-219,
-125,
-15,
-39,
-176,
-47,
-141,
-158,
-19,
-98,
-57,
-8,
-145,
-34,
-8,
-53,
-185,
-176,
-117,
-65,
-172,
-61,
-107,
-69,
-156,
-127,
-64,
-38,
-224,
-250,
-78,
-249,
-166,
-136,
-107,
-240,
-238,
-189,
-118,
-54,
-50,
-144,
-100,
-36,
-22,
-135,
-224,
-164,
-196,
-2,
-214,
-199,
-227,
-206,
-217,
-102,
-176,
-117,
-29,
-160,
-77,
-219,
-135,
-210,
-211,
-76,
-96,
-180,
-26,
-216,
-109,
-250,
-63,
-22,
-248,
-3,
-63,
-208,
-127,
-22,
-71,
-217,
-178,
-192,
-190,
-52,
-21,
-0,
-183,
-234,
-191,
-202,
-208,
-120,
-209,
-65,
-179,
-21,
-192,
-218,
-136,
-253,
-183,
-197,
-253,
-228,
-81,
-97,
-64,
-189,
-253,
-198,
-11,
-200,
-163,
-231,
-94,
-220,
-160,
-77,
-227,
-193,
-214,
-117,
-128,
-54,
-109,
-223,
-7,
-253,
-48,
-5,
-0,
-13,
-61,
-251,
-186,
-62,
-223,
-64,
-222,
-161,
-167,
-31,
-173,
-159,
-83,
-95,
-125,
-114,
-177,
-68,
-177,
-32,
-203,
-178,
-189,
-179,
-44,
-123,
-122,
-150,
-101,
-159,
-169,
-107,
-156,
-101,
-217,
-84,
-35,
-123,
-141,
-195,
-141,
-49,
-83,
-140,
-236,
-197,
-151,
-48,
-198,
-92,
-108,
-140,
-249,
-156,
-49,
-102,
-219,
-166,
-29,
-26,
-101,
-88,
-101,
-75,
-173,
-9,
-239,
-68,
-71,
-150,
-227,
-182,
-33,
-92,
-238,
-0,
-99,
-204,
-242,
-198,
-152,
-169,
-198,
-152,
-104,
-65,
-84,
-18,
-186,
-43,
-1,
-77,
-150,
-101,
-15,
-25,
-99,
-62,
-171,
-255,
-198,
-59,
-236,
-17,
-211,
-141,
-45,
-218,
-94,
-75,
-201,
-118,
-176,
-141,
-194,
-41,
-65,
-128,
-216,
-34,
-124,
-220,
-136,
-2,
-109,
-199,
-44,
-203,
-238,
-26,
-229,
-46,
-45,
-86,
-24,
-90,
-72,
-174,
-50,
-32,
-249,
-6,
-239,
-48,
-34,
-225,
-175,
-204,
-178,
-204,
-119,
-228,
-81,
-171,
-212,
-43,
-78,
-178,
-54,
-109,
-140,
-49,
-118,
-207,
-239,
-77,
-131,
-94,
-131,
-54,
-26,
-253,
-36,
-52,
-234,
-241,
-27,
-99,
-204,
-195,
-198,
-152,
-183,
-182,
-56,
-101,
-73,
-168,
-193,
-168,
-11,
-0,
-211,
-108,
-121,
-215,
-102,
-146,
-53,
-105,
-51,
-199,
-136,
-16,
-88,
-174,
-142,
-208,
-131,
-49,
-117,
-12,
-184,
-184,
-32,
-203,
-178,
-168,
-193,
-52,
-19,
-2,
-129,
-132,
-8,
-251,
-15,
-240,
-120,
-143,
-215,
-168,
-13,
-220,
-160,
-116,
-67,
-81,
-180,
-33,
-102,
-179,
-0,
-123,
-213,
-83,
-15,
-183,
-111,
-218,
-238,
-29,
-12,
-106,
-233,
-63,
-136,
-115,
-90,
-17,
-227,
-122,
-125,
-42,
-209,
-198,
-59,
-255,
-166,
-10,
-55,
-52,
-206,
-4,
-145,
-82,
-220,
-199,
-232,
-147,
-139,
-1,
-37,
-160,
-50,
-220,
-223,
-24,
-243,
-43,
-99,
-204,
-43,
-141,
-49,
-247,
-55,
-232,
-64,
-211,
-7,
-110,
-151,
-119,
-219,
-141,
-145,
-229,
-221,
-213,
-250,
-119,
-151,
-74,
-170,
-81,
-0,
-98,
-216,
-115,
-134,
-49,
-230,
-11,
-78,
-241,
-251,
-141,
-49,
-39,
-25,
-99,
-134,
-103,
-254,
-153,
-208,
-20,
-183,
-234,
-223,
-49,
-55,
-166,
-140,
-41,
-17,
-0,
-198,
-152,
-125,
-245,
-239,
-39,
-178,
-44,
-123,
-97,
-9,
-77,
-103,
-100,
-89,
-182,
-105,
-150,
-101,
-107,
-103,
-89,
-118,
-117,
-61,
-245,
-80,
-96,
-195,
-65,
-189,
-17,
-248,
-46,
-35,
-227,
-179,
-173,
-5,
-188,
-125,
-148,
-250,
-101,
-178,
-44,
-91,
-144,
-149,
-99,
-66,
-91,
-245,
-89,
-216,
-21,
-146,
-83,
-180,
-127,
-200,
-10,
-169,
-103,
-28,
-235,
-244,
-229,
-102,
-196,
-132,
-189,
-214,
-20,
-120,
-84,
-225,
-124,
-209,
-155,
-250,
-246,
-143,
-153,
-37,
-93,
-219,
-62,
-145,
-59,
-56,
-129,
-156,
-61,
-223,
-64,
-30,
-154,
-42,
-74,
-150,
-214,
-190,
-159,
-87,
-215,
-235,
-141,
-197,
-247,
-25,
-192,
-115,
-40,
-17,
-147,
-28,
-158,
-161,
-91,
-128,
-12,
-216,
-95,
-199,
-209,
-108,
-196,
-122,
-213,
-27,
-50,
-109,
-88,
-125,
-114,
-81,
-167,
-4,
-12,
-138,
-239,
-215,
-4,
-208,
-74,
-59,
-63,
-76,
-236,
-98,
-140,
-249,
-146,
-49,
-102,
-79,
-99,
-204,
-250,
-198,
-24,
-171,
-132,
-186,
-195,
-24,
-83,
-26,
-213,
-53,
-161,
-30,
-192,
-59,
-140,
-49,
-110,
-34,
-213,
-253,
-129,
-179,
-140,
-49,
-167,
-103,
-89,
-214,
-41,
-22,
-95,
-150,
-101,
-11,
-140,
-216,
-198,
-143,
-41,
-100,
-89,
-134,
-17,
-255,
-149,
-131,
-71,
-187,
-47,
-62,
-140,
-230,
-41,
-192,
-176,
-142,
-205,
-26,
-181,
-201,
-178,
-108,
-190,
-49,
-230,
-123,
-198,
-152,
-239,
-57,
-194,
-106,
-165,
-44,
-203,
-234,
-28,
-56,
-142,
-163,
-36,
-33,
-74,
-150,
-101,
-91,
-213,
-180,
-93,
-236,
-65,
-174,
-195,
-112,
-241,
-126,
-253,
-247,
-114,
-99,
-76,
-218,
-198,
-140,
-2,
-70,
-83,
-0,
-12,
-235,
-216,
-44,
-198,
-81,
-91,
-101,
-108,
-63,
-69,
-155,
-229,
-236,
-132,
-17,
-26,
-99,
-245,
-11,
-221,
-20,
-139,
-155,
-125,
-198,
-128,
-0,
-96,
-100,
-18,
-133,
-97,
-186,
-249,
-134,
-160,
-141,
-208,
-104,
-211,
-198,
-24,
-19,
-246,
-178,
-59,
-14,
-136,
-94,
-117,
-0,
-125,
-46,
-185,
-19,
-22,
-51,
-0,
-203,
-3,
-47,
-3,
-254,
-165,
-10,
-133,
-191,
-53,
-104,
-27,
-172,
-212,
-25,
-150,
-210,
-172,
-111,
-69,
-214,
-88,
-71,
-27,
-165,
-24,
-45,
-237,
-12,
-198,
-2,
-144,
-0,
-26,
-199,
-106,
-191,
-79,
-243,
-212,
-15,
-96,
-52,
-250,
-233,
-244,
-103,
-105,
-228,
-68,
-224,
-78,
-26,
-4,
-240,
-232,
-179,
-67,
-22,
-55,
-2,
-95,
-1,
-130,
-131,
-106,
-36,
-1,
-48,
-254,
-209,
-70,
-96,
-140,
-21,
-0,
-239,
-69,
-162,
-83,
-221,
-133,
-68,
-225,
-169,
-18,
-0,
-87,
-17,
-51,
-115,
-78,
-75,
-0,
-27,
-58,
-125,
-26,
-181,
-227,
-101,
-215,
-14,
-224,
-127,
-70,
-246,
-202,
-235,
-25,
-99,
-94,
-104,
-196,
-60,
-55,
-97,
-130,
-160,
-15,
-59,
-3,
-224,
-37,
-200,
-209,
-151,
-215,
-156,
-151,
-6,
-97,
-200,
-107,
-176,
-185,
-49,
-230,
-95,
-198,
-152,
-16,
-107,
-187,
-247,
-103,
-89,
-182,
-149,
-79,
-199,
-226,
-147,
-124,
-109,
-251,
-76,
-189,
-11,
-243,
-221,
-198,
-152,
-43,
-141,
-49,
-119,
-26,
-99,
-46,
-15,
-232,
-119,
-255,
-0,
-86,
-68,
-242,
-145,
-1,
-252,
-179,
-65,
-187,
-224,
-175,
-109,
-197,
-87,
-166,
-234,
-161,
-7,
-243,
-239,
-210,
-70,
-219,
-5,
-199,
-210,
-71,
-76,
-152,
-255,
-3,
-236,
-209,
-228,
-26,
-19,
-5,
-192,
-31,
-144,
-184,
-118,
-231,
-251,
-132,
-0,
-13,
-194,
-144,
-55,
-184,
-38,
-84,
-175,
-0,
-74,
-207,
-202,
-201,
-227,
-56,
-218,
-73,
-238,
-27,
-139,
-65,
-125,
-166,
-38,
-57,
-233,
-152,
-5,
-176,
-142,
-243,
-176,
-86,
-10,
-108,
-19,
-60,
-217,
-28,
-218,
-54,
-65,
-52,
-135,
-33,
-0,
-130,
-99,
-233,
-147,
-39,
-79,
-1,
-248,
-98,
-13,
-223,
-37,
-144,
-40,
-67,
-143,
-35,
-65,
-83,
-14,
-68,
-98,
-204,
-21,
-233,
-62,
-15,
-92,
-134,
-132,
-230,
-126,
-20,
-248,
-59,
-240,
-188,
-38,
-247,
-48,
-86,
-128,
-100,
-198,
-61,
-205,
-190,
-239,
-18,
-154,
-160,
-48,
-228,
-13,
-174,
-9,
-45,
-5,
-128,
-67,
-91,
-23,
-146,
-174,
-178,
-207,
-4,
-250,
-184,
-116,
-5,
-18,
-54,
-124,
-54,
-240,
-75,
-79,
-221,
-47,
-144,
-237,
-208,
-79,
-219,
-48,
-182,
-216,
-176,
-33,
-125,
-223,
-58,
-128,
-94,
-133,
-134,
-182,
-107,
-20,
-75,
-31,
-201,
-42,
-3,
-240,
-64,
-13,
-223,
-47,
-34,
-81,
-139,
-191,
-160,
-255,
-230,
-227,
-137,
-62,
-139,
-164,
-146,
-62,
-20,
-120,
-63,
-176,
-59,
-146,
-120,
-226,
-162,
-10,
-190,
-149,
-202,
-36,
-74,
-80,
-255,
-36,
-226,
-1,
-73,
-45,
-87,
-26,
-98,
-142,
-128,
-48,
-228,
-13,
-174,
-5,
-61,
-11,
-128,
-186,
-62,
-19,
-144,
-156,
-180,
-105,
-159,
-74,
-218,
-219,
-240,
-125,
-3,
-238,
-235,
-78,
-221,
-147,
-109,
-24,
-55,
-234,
-88,
-147,
-201,
-214,
-132,
-214,
-211,
-166,
-20,
-49,
-174,
-211,
-6,
-192,
-243,
-235,
-6,
-139,
-210,
-93,
-11,
-252,
-213,
-249,
-253,
-87,
-60,
-166,
-197,
-158,
-118,
-135,
-81,
-145,
-177,
-150,
-26,
-101,
-18,
-178,
-162,
-25,
-248,
-231,
-161,
-179,
-193,
-80,
-127,
-94,
-211,
-159,
-208,
-231,
-191,
-51,
-178,
-2,
-56,
-64,
-175,
-57,
-20,
-43,
-74,
-237,
-78,
-239,
-2,
-32,
-6,
-154,
-244,
-169,
-164,
-253,
-145,
-200,
-10,
-224,
-23,
-158,
-58,
-187,
-58,
-56,
-178,
-247,
-142,
-53,
-153,
-108,
-195,
-154,
-152,
-195,
-66,
-232,
-96,
-65,
-210,
-79,
-29,
-230,
-252,
-62,
-12,
-24,
-176,
-179,
-64,
-146,
-178,
-254,
-12,
-177,
-29,
-159,
-129,
-198,
-134,
-175,
-224,
-107,
-87,
-0,
-141,
-226,
-193,
-123,
-248,
-172,
-6,
-220,
-167,
-183,
-242,
-158,
-10,
-186,
-80,
-129,
-50,
-3,
-89,
-229,
-76,
-209,
-251,
-25,
-138,
-82,
-121,
-34,
-9,
-128,
-24,
-24,
-11,
-1,
-65,
-38,
-10,
-22,
-153,
-145,
-150,
-112,
-101,
-158,
-152,
-191,
-49,
-18,
-19,
-254,
-48,
-99,
-204,
-100,
-99,
-204,
-206,
-250,
-207,
-11,
-53,
-93,
-30,
-136,
-162,
-212,
-20,
-89,
-150,
-61,
-134,
-164,
-150,
-250,
-147,
-49,
-230,
-112,
-224,
-239,
-89,
-150,
-13,
-88,
-41,
-102,
-89,
-22,
-116,
-60,
-156,
-101,
-217,
-10,
-93,
-251,
-52,
-150,
-225,
-8,
-135,
-141,
-139,
-113,
-17,
-171,
-234,
-198,
-26,
-202,
-6,
-161,
-117,
-2,
-170,
-76,
-13,
-150,
-208,
-8,
-183,
-24,
-99,
-54,
-113,
-126,
-63,
-207,
-228,
-190,
-226,
-46,
-182,
-54,
-198,
-28,
-159,
-101,
-217,
-215,
-178,
-44,
-251,
-189,
-49,
-102,
-152,
-97,
-161,
-207,
-48,
-198,
-220,
-100,
-140,
-89,
-219,
-24,
-19,
-39,
-207,
-92,
-194,
-168,
-0,
-248,
-152,
-174,
-46,
-94,
-92,
-69,
-87,
-38,
-0,
-172,
-212,
-122,
-83,
-192,
-133,
-92,
-30,
-115,
-3,
-251,
-183,
-56,
-225,
-169,
-136,
-73,
-192,
-186,
-21,
-116,
-71,
-27,
-99,
-182,
-3,
-246,
-3,
-246,
-51,
-198,
-108,
-103,
-114,
-95,
-113,
-23,
-119,
-24,
-99,
-182,
-69,
-148,
-128,
-223,
-51,
-198,
-188,
-173,
-174,
-3,
-177,
-150,
-146,
-234,
-185,
-102,
-253,
-233,
-247,
-41,
-188,
-219,
-113,
-1,
-181,
-91,
-40,
-221,
-194,
-76,
-32,
-172,
-84,
-248,
-27,
-14,
-196,
-178,
-202,
-226,
-250,
-26,
-218,
-245,
-148,
-110,
-33,
-1,
-199,
-134,
-14,
-223,
-96,
-141,
-126,
-0,
-207,
-159,
-43,
-207,
-63,
-4,
-208,
-238,
-66,
-158,
-179,
-109,
-149,
-166,
-215,
-42,
-225,
-121,
-182,
-242,
-59,
-23,
-209,
-14,
-15,
-152,
-206,
-34,
-126,
-225,
-223,
-36,
-63,
-6,
-252,
-14,
-254,
-99,
-192,
-215,
-144,
-251,
-142,
-159,
-13,
-236,
-90,
-183,
-23,
-141,
-185,
-151,
-68,
-108,
-65,
-108,
-142,
-197,
-215,
-117,
-229,
-55,
-86,
-208,
-228,
-25,
-17,
-118,
-10,
-80,
-202,
-47,
-244,
-90,
-49,
-223,
-155,
-135,
-247,
-55,
-149,
-119,
-80,
-218,
-115,
-31,
-131,
-119,
-2,
-23,
-227,
-81,
-84,
-57,
-52,
-75,
-3,
-39,
-233,
-133,
-74,
-143,
-170,
-10,
-109,
-106,
-209,
-176,
-159,
-59,
-107,
-179,
-251,
-129,
-213,
-43,
-232,
-50,
-68,
-35,
-237,
-34,
-150,
-0,
-120,
-58,
-98,
-62,
-125,
-99,
-155,
-123,
-136,
-112,
-253,
-168,
-3,
-9,
-248,
-183,
-242,
-59,
-48,
-6,
-191,
-177,
-128,
-38,
-207,
-136,
-197,
-67,
-0,
-28,
-162,
-188,
-223,
-87,
-69,
-87,
-170,
-4,
-204,
-178,
-236,
-12,
-51,
-232,
-191,
-109,
-153,
-223,
-103,
-140,
-185,
-215,
-136,
-217,
-240,
-218,
-70,
-162,
-233,
-238,
-23,
-210,
-177,
-152,
-238,
-148,
-72,
-250,
-114,
-155,
-193,
-232,
-179,
-89,
-150,
-61,
-90,
-66,
-183,
-188,
-145,
-96,
-30,
-239,
-50,
-18,
-247,
-111,
-99,
-211,
-102,
-105,
-84,
-142,
-21,
-140,
-49,
-47,
-50,
-242,
-60,
-102,
-26,
-89,
-198,
-143,
-103,
-156,
-103,
-140,
-121,
-181,
-49,
-166,
-242,
-28,
-59,
-97,
-76,
-35,
-104,
-11,
-208,
-118,
-143,
-55,
-199,
-136,
-221,
-245,
-211,
-140,
-49,
-103,
-25,
-99,
-94,
-155,
-249,
-51,
-152,
-246,
-141,
-221,
-141,
-49,
-207,
-52,
-198,
-220,
-108,
-140,
-249,
-99,
-5,
-221,
-95,
-140,
-76,
-254,
-11,
-141,
-236,
-189,
-99,
-251,
-116,
-159,
-98,
-140,
-249,
-128,
-17,
-13,
-250,
-218,
-89,
-150,
-85,
-42,
-94,
-198,
-1,
-172,
-0,
-171,
-210,
-105,
-36,
-140,
-50,
-144,
-179,
-126,
-128,
-123,
-60,
-213,
-43,
-234,
-223,
-74,
-1,
-208,
-234,
-24,
-48,
-203,
-178,
-32,
-11,
-193,
-62,
-129,
-36,
-77,
-180,
-230,
-183,
-135,
-168,
-2,
-171,
-12,
-63,
-54,
-198,
-220,
-99,
-140,
-249,
-120,
-150,
-101,
-243,
-104,
-224,
-233,
-24,
-208,
-143,
-149,
-141,
-49,
-175,
-215,
-159,
-95,
-201,
-178,
-172,
-77,
-82,
-145,
-177,
-134,
-135,
-244,
-239,
-26,
-163,
-218,
-139,
-132,
-58,
-188,
-74,
-255,
-254,
-213,
-83,
-103,
-39,
-254,
-138,
-158,
-186,
-167,
-48,
-158,
-237,
-0,
-94,
-105,
-140,
-217,
-192,
-200,
-145,
-165,
-215,
-76,
-215,
-34,
-203,
-178,
-179,
-140,
-172,
-84,
-44,
-150,
-46,
-163,
-109,
-129,
-167,
-38,
-73,
-150,
-101,
-247,
-70,
-228,
-59,
-154,
-120,
-68,
-255,
-174,
-54,
-170,
-189,
-72,
-40,
-5,
-176,
-170,
-17,
-175,
-93,
-99,
-140,
-249,
-181,
-135,
-164,
-217,
-22,
-0,
-152,
-171,
-203,
-137,
-168,
-174,
-137,
-52,
-243,
-174,
-219,
-20,
-201,
-208,
-123,
-175,
-246,
-103,
-10,
-146,
-173,
-216,
-103,
-225,
-182,
-173,
-254,
-189,
-34,
-32,
-94,
-95,
-159,
-88,
-172,
-66,
-68,
-41,
-150,
-209,
-191,
-211,
-70,
-181,
-23,
-9,
-85,
-216,
-198,
-200,
-216,
-187,
-186,
-100,
-251,
-221,
-120,
-11,
-48,
-221,
-24,
-179,
-186,
-137,
-255,
-210,
-223,
-102,
-140,
-89,
-214,
-136,
-146,
-236,
-82,
-35,
-82,
-235,
-185,
-70,
-246,
-238,
-69,
-28,
-98,
-196,
-16,
-230,
-116,
-35,
-6,
-41,
-27,
-26,
-73,
-12,
-185,
-145,
-49,
-230,
-141,
-5,
-218,
-109,
-244,
-239,
-121,
-145,
-251,
-155,
-144,
-191,
-155,
-135,
-71,
-181,
-23,
-139,
-57,
-58,
-42,
-196,
-223,
-160,
-127,
-15,
-45,
-169,
-111,
-188,
-5,
-152,
-102,
-74,
-4,
-0,
-226,
-110,
-248,
-97,
-99,
-204,
-113,
-89,
-150,
-237,
-19,
-90,
-167,
-56,
-203,
-72,
-236,
-187,
-201,
-250,
-123,
-178,
-145,
-32,
-8,
-87,
-122,
-104,
-63,
-100,
-228,
-185,
-60,
-117,
-244,
-8,
-60,
-215,
-248,
-77,
-93,
-173,
-143,
-245,
-120,
-215,
-184,
-143,
-69,
-88,
-247,
-227,
-74,
-15,
-199,
-113,
-138,
-147,
-81,
-223,
-133,
-113,
-30,
-120,
-117,
-71,
-35,
-6,
-123,
-167,
-150,
-212,
-55,
-51,
-4,
-2,
-174,
-211,
-45,
-192,
-241,
-158,
-186,
-16,
-183,
-195,
-168,
-202,
-47,
-224,
-105,
-192,
-235,
-17,
-191,
-235,
-223,
-122,
-234,
-109,
-178,
-142,
-183,
-182,
-224,
-109,
-209,
-217,
-14,
-0,
-216,
-76,
-121,
-205,
-235,
-202,
-171,
-67,
-31,
-162,
-158,
-39,
-3,
-103,
-41,
-191,
-178,
-175,
-203,
-184,
-3,
-30,
-84,
-208,
-14,
-197,
-14,
-160,
-79,
-56,
-91,
-250,
-202,
-36,
-36,
-197,
-45,
-128,
-49,
-254,
-45,
-192,
-137,
-70,
-190,
-242,
-191,
-241,
-212,
-157,
-96,
-140,
-249,
-168,
-254,
-141,
-130,
-194,
-131,
-63,
-215,
-24,
-227,
-139,
-184,
-99,
-39,
-175,
-247,
-236,
-127,
-136,
-216,
-65,
-255,
-250,
-236,
-250,
-199,
-29,
-144,
-19,
-146,
-109,
-245,
-231,
-57,
-163,
-216,
-149,
-168,
-8,
-89,
-110,
-147,
-91,
-161,
-214,
-158,
-18,
-85,
-241,
-27,
-11,
-161,
-195,
-179,
-44,
-91,
-182,
-158,
-202,
-1,
-226,
-159,
-14,
-61,
-89,
-127,
-53,
-145,
-138,
-192,
-14,
-136,
-133,
-223,
-17,
-218,
-230,
-32,
-15,
-205,
-227,
-90,
-183,
-181,
-143,
-71,
-96,
-95,
-58,
-173,
-0,
-16,
-147,
-93,
-139,
-82,
-143,
-189,
-190,
-17,
-243,
-139,
-131,
-248,
-32,
-128,
-132,
-189,
-90,
-166,
-190,
-197,
-226,
-131,
-38,
-171,
-132,
-197,
-14,
-72,
-8,
-104,
-144,
-204,
-192,
-125,
-240,
-111,
-53,
-72,
-129,
-11,
-241,
-68,
-147,
-1,
-110,
-85,
-126,
-141,
-179,
-174,
-70,
-20,
-0,
-143,
-33,
-230,
-210,
-239,
-236,
-194,
-167,
-43,
-34,
-11,
-128,
-75,
-149,
-215,
-119,
-99,
-244,
-45,
-97,
-108,
-35,
-116,
-11,
-48,
-20,
-0,
-171,
-100,
-89,
-246,
-132,
-243,
-123,
-73,
-99,
-204,
-51,
-140,
-63,
-71,
-225,
-253,
-70,
-78,
-7,
-188,
-17,
-103,
-135,
-129,
-44,
-203,
-22,
-171,
-115,
-114,
-196,
-113,
-228,
-53,
-70,
-18,
-194,
-44,
-54,
-251,
-255,
-132,
-114,
-184,
-166,
-192,
-211,
-10,
-127,
-71,
-3,
-83,
-129,
-51,
-144,
-212,
-220,
-95,
-55,
-198,
-92,
-96,
-100,
-130,
-255,
-202,
-67,
-107,
-247,
-107,
-111,
-240,
-212,
-77,
-24,
-48,
-210,
-243,
-176,
-52,
-238,
-94,
-0,
-159,
-149,
-141,
-49,
-71,
-233,
-207,
-207,
-186,
-130,
-56,
-97,
-2,
-128,
-220,
-125,
-176,
-151,
-36,
-5,
-33,
-203,
-84,
-224,
-32,
-196,
-163,
-110,
-38,
-18,
-106,
-106,
-50,
-18,
-76,
-115,
-32,
-40,
-6,
-240,
-70,
-229,
-55,
-151,
-134,
-153,
-107,
-98,
-109,
-1,
-198,
-2,
-128,
-183,
-235,
-189,
-60,
-94,
-79,
-93,
-201,
-199,
-134,
-131,
-111,
-30,
-67,
-46,
-97,
-252,
-3,
-216,
-87,
-7,
-192,
-182,
-61,
-241,
-143,
-182,
-79,
-85,
-126,
-203,
-34,
-145,
-87,
-1,
-118,
-107,
-217,
-151,
-113,
-43,
-0,
-128,
-187,
-145,
-248,
-245,
-243,
-244,
-94,
-14,
-24,
-237,
-62,
-37,
-140,
-99,
-144,
-135,
-16,
-10,
-201,
-174,
-210,
-134,
-127,
-84,
-1,
-160,
-60,
-247,
-87,
-158,
-147,
-98,
-241,
-28,
-47,
-64,
-148,
-160,
-243,
-144,
-64,
-158,
-95,
-247,
-173,
-146,
-18,
-18,
-198,
-12,
-122,
-18,
-0,
-43,
-34,
-201,
-51,
-0,
-106,
-67,
-103,
-37,
-36,
-36,
-140,
-18,
-250,
-16,
-0,
-202,
-247,
-67,
-202,
-247,
-238,
-241,
-188,
-164,
-79,
-72,
-24,
-85,
-32,
-94,
-119,
-179,
-129,
-195,
-235,
-169,
-91,
-241,
-15,
-22,
-0,
-84,
-164,
-60,
-42,
-161,
-63,
-82,
-121,
-255,
-174,
-123,
-79,
-19,
-18,
-38,
-32,
-200,
-109,
-250,
-123,
-57,
-254,
-105,
-40,
-0,
-122,
-241,
-47,
-72,
-72,
-72,
-24,
-9,
-215,
-14,
-224,
-68,
-35,
-161,
-190,
-134,
-146,
-194,
-169,
-6,
-39,
-24,
-233,
-75,
-52,
-255,
-130,
-132,
-132,
-132,
-81,
-68,
-95,
-58,
-128,
-132,
-132,
-132,
-132,
-132,
-132,
-132,
-137,
-0,
-93,
-69,
-148,
-165,
-3,
-111,
-156,
-84,
-36,
-33,
-97,
-34,
-99,
-220,
-165,
-126,
-74,
-72,
-72,
-136,
-135,
-36,
-0,
-18,
-18,
-38,
-48,
-122,
-21,
-0,
-85,
-138,
-63,
-231,
-168,
-111,
-251,
-62,
-251,
-144,
-144,
-144,
-80,
-142,
-209,
-92,
-1,
-60,
-92,
-248,
-155,
-144,
-144,
-48,
-100,
-140,
-5,
-1,
-240,
-72,
-177,
-194,
-177,
-74,
-60,
-98,
-200,
-125,
-74,
-72,
-152,
-80,
-24,
-77,
-1,
-96,
-39,
-190,
-111,
-5,
-176,
-155,
-145,
-192,
-140,
-31,
-30,
-94,
-119,
-18,
-18,
-38,
-30,
-70,
-123,
-5,
-48,
-61,
-203,
-178,
-185,
-158,
-58,
-107,
-149,
-232,
-139,
-66,
-156,
-144,
-144,
-16,
-9,
-163,
-153,
-27,
-240,
-97,
-227,
-89,
-254,
-27,
-99,
-76,
-150,
-101,
-123,
-27,
-99,
-246,
-30,
-110,
-119,
-18,
-18,
-18,
-162,
-98,
-152,
-230,
-191,
-201,
-16,
-40,
-33,
-161,
-57,
-146,
-29,
-64,
-66,
-194,
-4,
-70,
-18,
-0,
-9,
-9,
-19,
-24,
-73,
-0,
-36,
-36,
-76,
-96,
-36,
-1,
-144,
-144,
-48,
-129,
-145,
-4,
-64,
-66,
-194,
-4,
-198,
-184,
-19,
-0,
-73,
-219,
-159,
-144,
-16,
-15,
-227,
-78,
-0,
-36,
-36,
-36,
-196,
-67,
-18,
-0,
-9,
-9,
-19,
-24,
-73,
-0,
-36,
-36,
-76,
-96,
-36,
-1,
-144,
-144,
-48,
-117,
-14,
-169,
-49,
-0,
-0,
-2,
-74,
-73,
-68,
-65,
-84,
-129,
-145,
-4,
-64,
-66,
-194,
-4,
-70,
-175,
-206,
-64,
-89,
-150,
-101,
-125,
-242,
-79,
-72,
-72,
-232,
-134,
-180,
-2,
-72,
-72,
-152,
-192,
-72,
-2,
-32,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-225,
-255,
-219,
-131,
-3,
-2,
-0,
-0,
-0,
-0,
-33,
-253,
-95,
-221,
-17,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-208,
-17,
-112,
-180,
-144,
-16,
-164,
-2,
-78,
-0,
-0,
-0,
-0,
-73,
-69,
-78,
-68,
-174,
-66,
-96,
-130,
-};
-/* clang-format on */
diff --git a/scene/resources/default_theme/font_lodpi.inc b/scene/resources/default_theme/font_lodpi.inc
deleted file mode 100644
index d2f5851224..0000000000
--- a/scene/resources/default_theme/font_lodpi.inc
+++ /dev/null
@@ -1,13117 +0,0 @@
-/* clang-format off */
-static const int _lodpi_font_height=14;
-static const int _lodpi_font_ascent=11;
-static const int _lodpi_font_charcount=191;
-static const int _lodpi_font_charrects[191][8]={
-/* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */
-{64,72,34,10,11,1,1,12},
-{224,85,180,5,11,0,1,7},
-{192,32,16,11,13,-2,-1,9},
-{96,2,216,3,2,0,3,8},
-{160,0,0,0,0,11,0,4},
-{32,0,0,0,0,11,0,4},
-{33,65,234,2,10,1,1,4},
-{225,112,169,5,11,0,1,7},
-{193,17,16,11,13,-2,-1,9},
-{161,2,222,2,11,3,1,4},
-{65,2,16,11,10,1,-1,9},
-{97,76,188,5,8,3,1,7},
-{98,102,165,6,11,0,1,8},
-{226,72,143,6,11,0,1,7},
-{194,113,2,11,13,-2,-1,9},
-{66,46,109,7,10,1,1,9},
-{162,12,136,6,10,1,1,8},
-{34,49,187,5,4,1,1,6},
-{35,78,66,8,10,1,0,9},
-{163,22,167,6,10,1,1,8},
-{195,53,2,11,14,-3,-1,9},
-{227,2,155,6,12,-1,1,7},
-{67,68,115,7,10,1,1,8},
-{99,40,179,5,8,3,1,7},
-{228,121,169,5,11,0,1,7},
-{196,98,2,11,13,-2,-1,9},
-{36,102,137,6,12,0,1,8},
-{100,82,150,6,11,0,1,8},
-{68,90,66,8,10,1,1,10},
-{164,14,79,8,7,3,0,8},
-{37,2,30,10,10,1,1,12},
-{69,29,191,5,10,1,1,7},
-{165,79,98,7,10,1,0,8},
-{229,20,196,5,12,-1,1,7},
-{197,83,2,11,12,-1,-1,9},
-{101,32,124,6,8,3,1,8},
-{38,67,49,9,10,1,1,10},
-{70,101,105,6,10,1,1,7},
-{198,21,2,12,10,1,-1,12},
-{166,95,228,2,14,0,3,7},
-{102,2,201,5,11,0,0,4},
-{230,58,34,10,8,3,1,12},
-{71,66,65,8,10,1,1,10},
-{231,2,186,5,11,3,1,7},
-{199,57,97,7,13,1,1,8},
-{103,13,107,7,11,3,1,7},
-{167,112,131,6,11,0,0,7},
-{39,119,219,2,4,1,1,3},
-{72,54,65,8,10,1,1,10},
-{232,62,143,6,11,0,1,8},
-{200,47,195,5,13,-2,1,7},
-{40,93,212,4,12,1,1,4},
-{104,72,158,6,11,0,1,8},
-{168,77,217,4,2,0,2,8},
-{73,38,191,5,10,1,0,5},
-{169,44,34,10,10,1,1,12},
-{233,52,142,6,11,0,1,8},
-{201,56,197,5,13,-2,1,7},
-{41,51,226,3,12,1,0,4},
-{105,109,213,3,11,0,0,4},
-{106,101,213,4,14,0,-1,4},
-{74,92,195,5,13,1,-2,3},
-{202,65,202,5,13,-2,1,7},
-{42,108,80,7,6,0,0,8},
-{170,29,205,4,5,1,0,5},
-{234,12,181,6,11,0,1,8},
-{171,22,181,5,6,4,1,7},
-{43,101,94,7,7,3,0,8},
-{107,112,92,7,11,0,1,7},
-{203,83,200,5,13,-2,1,7},
-{235,2,171,6,11,0,1,8},
-{75,102,66,8,10,1,1,8},
-{44,107,231,2,3,9,1,4},
-{172,2,104,7,4,6,0,8},
-{108,113,228,2,11,0,1,4},
-{204,101,196,5,13,-2,0,5},
-{236,30,214,3,11,0,0,4},
-{76,22,124,6,10,1,1,7},
-{173,16,229,3,2,7,1,5},
-{45,123,201,3,2,7,1,5},
-{109,68,2,11,8,3,1,13},
-{205,11,211,5,13,-2,0,5},
-{237,37,214,3,11,0,1,4},
-{77,62,20,10,10,1,1,12},
-{46,101,231,2,2,9,1,4},
-{110,111,107,6,8,3,1,8},
-{206,20,212,5,13,-2,0,5},
-{238,11,196,5,11,0,-1,4},
-{174,30,33,10,10,1,1,12},
-{78,2,79,8,10,1,1,10},
-{175,35,111,7,1,-1,0,7},
-{111,102,153,6,8,3,1,8},
-{207,119,184,5,13,-2,0,5},
-{239,69,219,4,11,0,0,4},
-{79,41,66,9,10,1,1,11},
-{47,90,105,7,10,1,-1,5},
-{176,61,219,4,4,1,1,6},
-{112,32,150,6,11,3,1,8},
-{240,82,165,6,11,0,1,8},
-{208,86,33,9,10,1,0,10},
-{80,52,128,6,10,1,1,8},
-{48,42,135,6,10,1,1,8},
-{177,46,97,7,8,3,0,8},
-{113,22,152,6,11,3,1,8},
-{241,2,112,6,12,-1,1,8},
-{81,15,59,9,13,1,1,11},
-{209,74,80,8,14,-3,1,10},
-{49,45,212,4,10,1,2,8},
-{178,58,187,5,6,1,0,5},
-{114,85,217,4,8,3,1,5},
-{210,2,62,9,13,-2,1,11},
-{242,62,165,6,11,0,1,8},
-{82,35,97,7,10,1,1,8},
-{50,57,114,7,10,1,1,8},
-{179,53,214,4,6,1,0,5},
-{115,112,146,6,8,3,0,7},
-{211,106,49,9,13,-2,1,11},
-{243,52,172,6,11,0,1,8},
-{83,24,96,7,10,1,0,7},
-{51,22,138,6,10,1,1,8},
-{180,9,228,3,2,0,3,8},
-{116,67,188,5,10,1,0,5},
-{212,93,49,9,13,-2,1,11},
-{244,42,164,6,11,0,1,8},
-{84,13,93,7,10,1,0,7},
-{52,24,110,7,10,1,1,8},
-{53,92,119,6,10,1,1,8},
-{85,114,66,8,10,1,1,10},
-{213,2,44,9,14,-3,1,11},
-{117,42,123,6,8,3,1,8},
-{181,2,140,6,11,3,1,8},
-{245,12,165,6,12,-1,1,8},
-{54,82,121,6,10,1,1,8},
-{86,76,18,10,10,1,-1,8},
-{246,72,173,6,11,0,1,8},
-{214,80,49,9,13,-2,1,11},
-{182,68,98,7,13,0,1,9},
-{118,15,47,9,8,3,-1,7},
-{55,72,129,6,10,1,1,8},
-{87,2,2,15,10,1,-1,13},
-{119,37,2,12,8,3,-1,10},
-{247,90,94,7,7,3,0,8},
-{215,2,93,7,7,3,0,8},
-{183,77,223,2,2,5,1,4},
-{56,62,129,6,10,1,1,8},
-{88,90,19,10,10,1,-1,8},
-{216,99,33,9,12,0,1,11},
-{248,2,128,6,8,3,1,8},
-{120,119,80,7,8,3,0,7},
-{184,116,212,3,3,11,0,3},
-{89,28,65,9,10,1,-1,7},
-{217,38,80,8,13,-2,1,10},
-{249,52,157,6,11,0,1,8},
-{121,112,33,9,11,3,-1,7},
-{57,12,122,6,10,1,1,8},
-{185,23,229,3,6,1,0,5},
-{218,26,79,8,13,-2,1,10},
-{250,42,149,6,11,0,1,8},
-{90,32,136,6,10,1,1,8},
-{122,112,119,6,8,3,1,7},
-{58,89,229,2,8,3,1,4},
-{186,37,205,4,5,1,0,5},
-{219,50,80,8,13,-2,1,10},
-{91,58,227,3,12,1,1,4},
-{123,103,180,5,12,1,0,5},
-{251,12,150,6,11,0,1,8},
-{59,71,234,2,9,3,1,4},
-{187,31,181,5,6,4,1,7},
-{188,16,33,10,10,1,0,10},
-{124,83,229,2,14,0,3,7},
-{220,62,79,8,13,-2,1,10},
-{252,92,133,6,11,0,1,8},
-{92,97,80,7,10,1,-1,5},
-{60,92,153,6,7,3,1,8},
-{189,47,20,11,10,1,0,10},
-{253,28,47,9,14,0,-1,7},
-{221,54,48,9,13,-2,-1,7},
-{93,44,226,3,12,1,0,4},
-{125,110,196,5,12,1,0,5},
-{61,79,112,7,5,4,0,8},
-{190,104,19,10,10,1,0,10},
-{222,32,165,6,10,1,1,8},
-{254,102,119,6,14,0,1,8},
-{62,112,158,6,7,3,1,8},
-{94,86,80,7,6,1,0,7},
-{126,62,158,6,3,5,1,8},
-{223,82,135,6,11,0,1,8},
-{255,41,48,9,14,0,-1,7},
-{191,94,180,5,11,3,0,6},
-{63,74,202,5,10,1,0,6},
-{95,92,148,6,1,12,0,6},
-};
-static const int _lodpi_font_kerning_pair_count=0;
-static const int _lodpi_font_kerning_pairs[1][3]={
-{0,0,0},
-};
-static const int _lodpi_font_img_width=128;
-static const int _lodpi_font_img_height=256;
-static const int _lodpi_font_img_data_size=12909;
-static const unsigned char _lodpi_font_img_data[12909]={
-137,
-80,
-78,
-71,
-13,
-10,
-26,
-10,
-0,
-0,
-0,
-13,
-73,
-72,
-68,
-82,
-0,
-0,
-0,
-128,
-0,
-0,
-1,
-0,
-8,
-6,
-0,
-0,
-0,
-123,
-249,
-126,
-167,
-0,
-0,
-32,
-0,
-73,
-68,
-65,
-84,
-120,
-156,
-237,
-157,
-119,
-184,
-30,
-85,
-181,
-255,
-191,
-59,
-128,
-8,
-210,
-155,
-82,
-77,
-232,
-221,
-2,
-210,
-164,
-132,
-26,
-154,
-5,
-164,
-131,
-63,
-224,
-98,
-65,
-4,
-68,
-46,
-8,
-42,
-23,
-84,
-80,
-41,
-94,
-16,
-21,
-17,
-197,
-10,
-22,
-80,
-17,
-21,
-4,
-5,
-65,
-16,
-41,
-42,
-185,
-116,
-19,
-106,
-128,
-80,
-46,
-32,
-33,
-148,
-208,
-18,
-62,
-191,
-63,
-214,
-122,
-115,
-230,
-204,
-217,
-51,
-179,
-103,
-222,
-121,
-223,
-115,
-146,
-123,
-190,
-207,
-115,
-158,
-51,
-101,
-237,
-50,
-243,
-174,
-217,
-123,
-237,
-213,
-182,
-52,
-138,
-81,
-140,
-98,
-20,
-2,
-150,
-3,
-222,
-0,
-54,
-207,
-93,
-255,
-32,
-134,
-247,
-231,
-174,
-111,
-237,
-244,
-203,
-38,
-212,
-61,
-31,
-48,
-149,
-2,
-68,
-232,
-87,
-242,
-91,
-107,
-102,
-174,
-253,
-28,
-184,
-58,
-115,
-190,
-178,
-211,
-172,
-88,
-243,
-57,
-199,
-84,
-220,
-7,
-216,
-17,
-184,
-21,
-120,
-21,
-184,
-23,
-216,
-9,
-56,
-192,
-143,
-103,
-0,
-55,
-1,
-235,
-36,
-180,
-245,
-117,
-224,
-122,
-224,
-244,
-58,
-125,
-244,
-178,
-247,
-0,
-239,
-4,
-222,
-13,
-220,
-85,
-179,
-236,
-55,
-253,
-57,
-190,
-89,
-69,
-59,
-251,
-101,
-132,
-16,
-30,
-151,
-116,
-171,
-164,
-157,
-114,
-52,
-59,
-74,
-186,
-94,
-210,
-118,
-185,
-235,
-59,
-73,
-250,
-123,
-8,
-225,
-137,
-132,
-62,
-237,
-39,
-233,
-113,
-73,
-11,
-248,
-249,
-206,
-126,
-188,
-64,
-230,
-218,
-108,
-132,
-16,
-30,
-145,
-116,
-175,
-164,
-205,
-252,
-129,
-230,
-149,
-180,
-161,
-164,
-21,
-129,
-133,
-156,
-108,
-115,
-73,
-147,
-67,
-8,
-143,
-150,
-53,
-12,
-28,
-9,
-76,
-3,
-206,
-4,
-198,
-74,
-186,
-49,
-161,
-191,
-103,
-75,
-58,
-76,
-210,
-242,
-178,
-103,
-191,
-88,
-210,
-17,
-146,
-118,
-151,
-52,
-78,
-210,
-51,
-146,
-190,
-157,
-80,
-207,
-102,
-33,
-132,
-45,
-37,
-109,
-157,
-64,
-155,
-199,
-204,
-204,
-241,
-172,
-212,
-66,
-192,
-119,
-37,
-45,
-41,
-105,
-13,
-73,
-75,
-251,
-121,
-114,
-225,
-19,
-128,
-137,
-185,
-107,
-15,
-1,
-59,
-3,
-255,
-202,
-93,
-191,
-11,
-248,
-108,
-98,
-189,
-119,
-2,
-251,
-250,
-49,
-64,
-158,
-153,
-98,
-101,
-206,
-1,
-206,
-247,
-227,
-109,
-128,
-75,
-129,
-31,
-117,
-70,
-34,
-224,
-188,
-20,
-14,
-7,
-110,
-241,
-209,
-226,
-76,
-224,
-57,
-224,
-136,
-10,
-122,
-128,
-79,
-100,
-206,
-215,
-205,
-247,
-217,
-71,
-136,
-23,
-18,
-218,
-190,
-223,
-203,
-222,
-93,
-69,
-59,
-34,
-0,
-172,
-159,
-29,
-214,
-129,
-53,
-128,
-71,
-252,
-120,
-42,
-176,
-188,
-31,
-175,
-232,
-15,
-182,
-118,
-66,
-157,
-59,
-1,
-143,
-250,
-87,
-92,
-135,
-1,
-62,
-216,
-121,
-113,
-192,
-89,
-192,
-97,
-192,
-65,
-192,
-185,
-126,
-237,
-110,
-114,
-211,
-82,
-65,
-61,
-165,
-67,
-126,
-132,
-30,
-96,
-219,
-204,
-249,
-88,
-191,
-54,
-54,
-115,
-109,
-115,
-24,
-58,
-117,
-69,
-234,
-186,
-12,
-248,
-53,
-240,
-251,
-58,
-125,
-240,
-178,
-59,
-121,
-187,
-249,
-17,
-185,
-167,
-101,
-59,
-95,
-252,
-193,
-126,
-124,
-100,
-230,
-43,
-252,
-17,
-112,
-144,
-31,
-127,
-28,
-184,
-47,
-177,
-190,
-107,
-128,
-207,
-100,
-206,
-135,
-160,
-160,
-220,
-162,
-192,
-107,
-254,
-255,
-62,
-76,
-46,
-88,
-14,
-120,
-16,
-88,
-204,
-239,
-45,
-146,
-216,
-135,
-228,
-23,
-226,
-116,
-155,
-103,
-206,
-59,
-12,
-176,
-66,
-230,
-90,
-37,
-3,
-0,
-227,
-128,
-151,
-252,
-99,
-121,
-41,
-203,
-64,
-137,
-125,
-238,
-134,
-121,
-26,
-151,
-21,
-112,
-54,
-112,
-177,
-31,
-255,
-1,
-216,
-211,
-143,
-247,
-7,
-46,
-244,
-227,
-75,
-129,
-175,
-37,
-212,
-245,
-110,
-224,
-5,
-96,
-177,
-204,
-53,
-252,
-7,
-121,
-115,
-231,
-175,
-164,
-252,
-77,
-192,
-129,
-192,
-29,
-153,
-107,
-119,
-0,
-7,
-3,
-55,
-212,
-120,
-166,
-228,
-23,
-210,
-34,
-3,
-156,
-14,
-252,
-218,
-143,
-47,
-1,
-78,
-171,
-209,
-223,
-198,
-204,
-211,
-45,
-227,
-9,
-216,
-22,
-19,
-154,
-22,
-0,
-158,
-7,
-22,
-247,
-235,
-111,
-5,
-30,
-199,
-36,
-250,
-231,
-201,
-173,
-22,
-10,
-234,
-250,
-121,
-236,
-139,
-39,
-97,
-10,
-240,
-242,
-39,
-3,
-55,
-0,
-95,
-201,
-92,
-59,
-195,
-25,
-227,
-164,
-196,
-58,
-106,
-189,
-144,
-54,
-24,
-192,
-25,
-251,
-25,
-96,
-15,
-63,
-223,
-195,
-207,
-11,
-153,
-61,
-87,
-190,
-27,
-230,
-105,
-92,
-182,
-83,
-193,
-188,
-206,
-0,
-31,
-7,
-110,
-206,
-221,
-187,
-29,
-27,
-9,
-158,
-162,
-122,
-57,
-53,
-22,
-27,
-166,
-215,
-206,
-126,
-237,
-53,
-25,
-96,
-75,
-167,
-223,
-44,
-115,
-109,
-187,
-252,
-181,
-138,
-58,
-106,
-189,
-144,
-150,
-24,
-224,
-64,
-255,
-72,
-22,
-240,
-243,
-55,
-3,
-211,
-129,
-3,
-19,
-250,
-219,
-152,
-121,
-186,
-101,
-188,
-108,
-69,
-63,
-195,
-164,
-231,
-47,
-230,
-174,
-127,
-205,
-191,
-190,
-31,
-36,
-212,
-113,
-54,
-240,
-219,
-200,
-117,
-72,
-156,
-2,
-186,
-69,
-107,
-47,
-164,
-126,
-187,
-127,
-39,
-142,
-91,
-18,
-202,
-118,
-195,
-60,
-141,
-203,
-230,
-43,
-218,
-219,
-59,
-252,
-222,
-220,
-245,
-9,
-126,
-253,
-3,
-21,
-229,
-23,
-7,
-94,
-4,
-198,
-71,
-238,
-13,
-65,
-173,
-206,
-213,
-64,
-107,
-47,
-164,
-94,
-155,
-239,
-1,
-102,
-97,
-43,
-168,
-236,
-200,
-183,
-154,
-95,
-223,
-176,
-162,
-124,
-55,
-204,
-211,
-184,
-236,
-92,
-137,
-225,
-120,
-33,
-216,
-106,
-233,
-55,
-5,
-247,
-46,
-5,
-126,
-88,
-82,
-182,
-49,
-243,
-116,
-203,
-120,
-115,
-29,
-134,
-227,
-133,
-0,
-75,
-2,
-47,
-3,
-91,
-21,
-220,
-223,
-214,
-239,
-47,
-89,
-112,
-191,
-27,
-230,
-105,
-92,
-118,
-174,
-196,
-156,
-246,
-66,
-186,
-97,
-158,
-110,
-25,
-111,
-174,
-195,
-232,
-11,
-105,
-1,
-116,
-163,
-78,
-180,
-242,
-75,
-1,
-255,
-11,
-252,
-180,
-102,
-185,
-159,
-123,
-185,
-165,
-154,
-180,
-59,
-138,
-150,
-64,
-55,
-234,
-68,
-43,
-127,
-5,
-166,
-195,
-175,
-171,
-139,
-159,
-7,
-51,
-163,
-254,
-161,
-73,
-187,
-163,
-104,
-1,
-116,
-171,
-78,
-156,
-139,
-1,
-44,
-3,
-188,
-14,
-108,
-19,
-185,
-183,
-131,
-223,
-91,
-102,
-56,
-250,
-214,
-4,
-69,
-95,
-231,
-39,
-36,
-93,
-233,
-182,
-246,
-63,
-250,
-121,
-50,
-186,
-153,
-62,
-186,
-157,
-122,
-122,
-141,
-16,
-194,
-83,
-146,
-174,
-146,
-180,
-103,
-228,
-246,
-158,
-146,
-254,
-228,
-52,
-131,
-0,
-44,
-136,
-57,
-121,
-124,
-46,
-114,
-239,
-72,
-191,
-183,
-96,
-228,
-222,
-217,
-152,
-129,
-238,
-62,
-224,
-204,
-204,
-245,
-177,
-152,
-133,
-54,
-201,
-32,
-150,
-12,
-90,
-208,
-158,
-117,
-51,
-125,
-212,
-41,
-235,
-194,
-222,
-143,
-129,
-215,
-114,
-215,
-43,
-95,
-142,
-51,
-217,
-171,
-184,
-173,
-35,
-119,
-239,
-77,
-192,
-211,
-80,
-104,
-169,
-220,
-215,
-229,
-148,
-121,
-50,
-215,
-230,
-245,
-50,
-251,
-148,
-180,
-185,
-30,
-102,
-28,
-219,
-58,
-115,
-109,
-99,
-204,
-79,
-97,
-221,
-130,
-50,
-107,
-250,
-180,
-184,
-46,
-240,
-104,
-230,
-250,
-133,
-192,
-167,
-138,
-218,
-106,
-12,
-186,
-212,
-158,
-117,
-51,
-125,
-212,
-45,
-11,
-252,
-2,
-179,
-77,
-204,
-200,
-93,
-175,
-124,
-57,
-206,
-0,
-55,
-147,
-113,
-254,
-200,
-220,
-219,
-3,
-184,
-177,
-132,
-1,
-22,
-244,
-119,
-180,
-77,
-230,
-218,
-118,
-217,
-247,
-86,
-210,
-238,
-199,
-128,
-39,
-129,
-101,
-157,
-129,
-31,
-6,
-62,
-86,
-81,
-230,
-58,
-103,
-174,
-143,
-248,
-249,
-187,
-48,
-103,
-147,
-55,
-149,
-149,
-107,
-4,
-186,
-212,
-158,
-49,
-12,
-150,
-44,
-96,
-102,
-230,
-56,
-233,
-229,
-248,
-51,
-29,
-79,
-206,
-224,
-229,
-247,
-254,
-0,
-28,
-81,
-196,
-0,
-78,
-243,
-35,
-220,
-57,
-197,
-207,
-207,
-3,
-126,
-148,
-216,
-223,
-95,
-96,
-190,
-130,
-127,
-0,
-126,
-145,
-88,
-102,
-89,
-224,
-223,
-126,
-252,
-39,
-220,
-195,
-170,
-85,
-208,
-189,
-30,
-123,
-88,
-44,
-89,
-57,
-6,
-72,
-122,
-57,
-206,
-0,
-219,
-98,
-243,
-235,
-26,
-153,
-235,
-203,
-3,
-255,
-196,
-220,
-208,
-202,
-24,
-96,
-59,
-124,
-26,
-240,
-191,
-167,
-200,
-120,
-18,
-85,
-180,
-189,
-48,
-54,
-69,
-61,
-69,
-197,
-28,
-142,
-59,
-189,
-2,
-107,
-97,
-158,
-85,
-219,
-99,
-14,
-171,
-1,
-27,
-253,
-94,
-43,
-43,
-95,
-11,
-116,
-169,
-61,
-99,
-152,
-44,
-89,
-29,
-6,
-200,
-188,
-156,
-147,
-128,
-73,
-216,
-240,
-26,
-157,
-10,
-156,
-1,
-182,
-195,
-124,
-14,
-190,
-156,
-185,
-254,
-121,
-224,
-112,
-191,
-87,
-198,
-0,
-99,
-128,
-199,
-156,
-81,
-182,
-246,
-31,
-52,
-105,
-201,
-235,
-31,
-218,
-116,
-108,
-154,
-27,
-178,
-154,
-200,
-209,
-222,
-130,
-9,
-128,
-119,
-2,
-239,
-243,
-231,
-219,
-14,
-88,
-221,
-127,
-175,
-25,
-101,
-229,
-147,
-65,
-11,
-218,
-51,
-134,
-201,
-146,
-5,
-204,
-244,
-47,
-162,
-243,
-114,
-54,
-197,
-28,
-90,
-22,
-3,
-166,
-23,
-148,
-233,
-48,
-192,
-106,
-206,
-40,
-99,
-188,
-142,
-187,
-49,
-107,
-102,
-41,
-3,
-120,
-29,
-103,
-96,
-186,
-142,
-179,
-73,
-116,
-253,
-118,
-198,
-254,
-23,
-240,
-73,
-224,
-88,
-108,
-4,
-90,
-168,
-186,
-164,
-4,
-236,
-7,
-252,
-17,
-152,
-31,
-184,
-26,
-120,
-27,
-240,
-122,
-74,
-217,
-158,
-131,
-97,
-182,
-100,
-117,
-94,
-78,
-238,
-218,
-4,
-224,
-138,
-2,
-122,
-112,
-199,
-20,
-76,
-224,
-219,
-22,
-24,
-143,
-207,
-201,
-137,
-12,
-240,
-14,
-108,
-249,
-54,
-25,
-88,
-191,
-170,
-143,
-94,
-230,
-76,
-224,
-42,
-103,
-182,
-121,
-128,
-127,
-0,
-149,
-46,
-230,
-216,
-202,
-228,
-126,
-44,
-86,
-224,
-28,
-6,
-166,
-202,
-153,
-85,
-101,
-251,
-2,
-134,
-209,
-146,
-149,
-125,
-57,
-153,
-107,
-155,
-2,
-215,
-82,
-108,
-121,
-203,
-50,
-192,
-161,
-216,
-114,
-242,
-2,
-96,
-123,
-191,
-86,
-201,
-0,
-78,
-119,
-59,
-112,
-123,
-21,
-157,
-211,
-110,
-9,
-60,
-75,
-38,
-152,
-5,
-243,
-196,
-126,
-149,
-204,
-210,
-176,
-160,
-236,
-81,
-192,
-5,
-126,
-252,
-47,
-108,
-138,
-155,
-228,
-207,
-49,
-188,
-90,
-83,
-134,
-217,
-146,
-149,
-125,
-57,
-126,
-190,
-13,
-112,
-17,
-176,
-112,
-73,
-153,
-44,
-3,
-44,
-14,
-252,
-219,
-95,
-236,
-24,
-191,
-150,
-196,
-0,
-169,
-0,
-222,
-2,
-60,
-64,
-68,
-166,
-193,
-228,
-144,
-7,
-129,
-183,
-20,
-148,
-93,
-4,
-147,
-55,
-198,
-70,
-238,
-141,
-140,
-17,
-96,
-184,
-16,
-123,
-57,
-206,
-48,
-247,
-101,
-190,
-146,
-141,
-34,
-229,
-102,
-51,
-128,
-159,
-255,
-146,
-140,
-11,
-92,
-219,
-12,
-48,
-226,
-1,
-108,
-229,
-28,
-122,
-47,
-176,
-113,
-230,
-250,
-242,
-152,
-144,
-212,
-174,
-202,
-113,
-20,
-35,
-11,
-152,
-20,
-190,
-13,
-166,
-139,
-191,
-46,
-115,
-253,
-7,
-192,
-145,
-195,
-217,
-183,
-81,
-244,
-1,
-216,
-154,
-244,
-45,
-192,
-66,
-248,
-210,
-9,
-211,
-63,
-223,
-75,
-47,
-84,
-142,
-163,
-24,
-89,
-192,
-140,
-20,
-29,
-6,
-120,
-222,
-175,
-93,
-78,
-137,
-113,
-195,
-105,
-26,
-27,
-100,
-156,
-110,
-39,
-204,
-0,
-116,
-149,
-255,
-93,
-6,
-76,
-232,
-254,
-137,
-134,
-31,
-12,
-198,
-12,
-44,
-170,
-233,
-68,
-42,
-236,
-5,
-5,
-117,
-189,
-189,
-224,
-250,
-82,
-190,
-138,
-200,
-135,
-245,
-111,
-130,
-197,
-101,
-44,
-157,
-218,
-192,
-13,
-153,
-41,
-224,
-111,
-216,
-154,
-248,
-159,
-152,
-150,
-107,
-136,
-108,
-144,
-41,
-215,
-141,
-65,
-230,
-100,
-224,
-123,
-89,
-9,
-31,
-88,
-218,
-175,
-149,
-70,
-254,
-212,
-101,
-28,
-111,
-107,
-50,
-240,
-138,
-255,
-159,
-0,
-124,
-26,
-51,
-204,
-60,
-5,
-156,
-75,
-196,
-28,
-155,
-41,
-191,
-14,
-240,
-83,
-23,
-56,
-159,
-198,
-150,
-157,
-167,
-149,
-49,
-184,
-255,
-240,
-157,
-24,
-136,
-177,
-192,
-7,
-48,
-101,
-213,
-223,
-139,
-218,
-194,
-116,
-254,
-223,
-243,
-118,
-94,
-5,
-166,
-248,
-52,
-252,
-34,
-176,
-92,
-65,
-153,
-139,
-240,
-24,
-206,
-204,
-181,
-115,
-113,
-187,
-74,
-18,
-128,
-205,
-48,
-201,
-249,
-126,
-96,
-139,
-140,
-76,
-16,
-149,
-13,
-34,
-229,
-107,
-25,
-100,
-128,
-93,
-24,
-80,
-186,
-128,
-169,
-70,
-31,
-7,
-142,
-245,
-107,
-223,
-43,
-250,
-65,
-155,
-48,
-14,
-102,
-194,
-125,
-15,
-182,
-228,
-251,
-152,
-127,
-145,
-147,
-176,
-105,
-110,
-37,
-255,
-0,
-162,
-241,
-142,
-192,
-110,
-254,
-110,
-246,
-194,
-109,
-19,
-152,
-99,
-200,
-119,
-252,
-171,
-142,
-46,
-55,
-253,
-185,
-182,
-203,
-93,
-91,
-8,
-91,
-242,
-157,
-16,
-161,
-95,
-10,
-19,
-184,
-127,
-131,
-41,
-153,
-22,
-1,
-54,
-192,
-84,
-228,
-143,
-20,
-49,
-27,
-3,
-150,
-200,
-5,
-253,
-124,
-126,
-44,
-186,
-107,
-151,
-24,
-125,
-37,
-128,
-125,
-112,
-229,
-2,
-17,
-217,
-160,
-160,
-76,
-45,
-131,
-12,
-230,
-50,
-182,
-148,
-31,
-131,
-169,
-53,
-87,
-195,
-194,
-211,
-23,
-244,
-31,
-244,
-178,
-72,
-185,
-44,
-227,
-172,
-4,
-252,
-197,
-31,
-246,
-119,
-126,
-173,
-144,
-113,
-50,
-117,
-204,
-139,
-105,
-24,
-63,
-150,
-185,
-182,
-7,
-240,
-112,
-132,
-118,
-172,
-191,
-252,
-149,
-10,
-234,
-186,
-144,
-140,
-45,
-33,
-119,
-111,
-8,
-3,
-248,
-245,
-207,
-17,
-201,
-250,
-1,
-252,
-183,
-51,
-229,
-152,
-28,
-237,
-3,
-152,
-138,
-250,
-11,
-5,
-237,
-4,
-103,
-170,
-255,
-231,
-231,
-123,
-249,
-199,
-52,
-79,
-140,
-190,
-20,
-152,
-86,
-237,
-94,
-92,
-181,
-73,
-68,
-54,
-40,
-40,
-151,
-55,
-200,
-148,
-90,
-171,
-24,
-156,
-238,
-5,
-224,
-67,
-192,
-113,
-152,
-110,
-188,
-163,
-140,
-185,
-42,
-82,
-46,
-203,
-56,
-191,
-195,
-244,
-241,
-99,
-112,
-61,
-64,
-9,
-227,
-172,
-128,
-133,
-188,
-61,
-236,
-127,
-49,
-188,
-17,
-41,
-247,
-117,
-224,
-56,
-63,
-94,
-13,
-83,
-27,
-79,
-197,
-134,
-230,
-21,
-48,
-245,
-245,
-189,
-145,
-114,
-67,
-144,
-185,
-247,
-65,
-224,
-229,
-72,
-153,
-201,
-157,
-182,
-252,
-124,
-93,
-76,
-167,
-177,
-165,
-191,
-155,
-59,
-242,
-101,
-50,
-180,
-159,
-7,
-174,
-241,
-227,
-203,
-129,
-83,
-139,
-104,
-75,
-1,
-124,
-138,
-140,
-93,
-27,
-147,
-7,
-182,
-198,
-101,
-131,
-146,
-114,
-121,
-131,
-76,
-169,
-181,
-42,
-194,
-0,
-87,
-96,
-115,
-241,
-58,
-153,
-235,
-49,
-6,
-200,
-150,
-123,
-14,
-88,
-61,
-66,
-19,
-43,
-247,
-103,
-204,
-211,
-104,
-17,
-103,
-24,
-176,
-16,
-184,
-172,
-237,
-97,
-136,
-233,
-25,
-251,
-34,
-215,
-246,
-227,
-107,
-128,
-195,
-252,
-248,
-85,
-44,
-98,
-122,
-12,
-240,
-74,
-164,
-92,
-39,
-16,
-118,
-167,
-124,
-221,
-192,
-238,
-192,
-139,
-145,
-50,
-175,
-0,
-123,
-249,
-241,
-188,
-152,
-12,
-118,
-150,
-159,
-239,
-89,
-244,
-46,
-253,
-254,
-114,
-152,
-208,
-183,
-14,
-230,
-151,
-184,
-70,
-17,
-109,
-33,
-252,
-229,
-60,
-202,
-96,
-93,
-245,
-32,
-217,
-160,
-162,
-124,
-178,
-181,
-202,
-127,
-240,
-37,
-253,
-24,
-167,
-61,
-16,
-56,
-207,
-175,
-45,
-69,
-252,
-75,
-206,
-51,
-192,
-106,
-17,
-154,
-24,
-3,
-188,
-4,
-236,
-234,
-199,
-227,
-188,
-205,
-83,
-202,
-158,
-199,
-105,
-95,
-102,
-96,
-110,
-125,
-9,
-120,
-59,
-54,
-26,
-130,
-141,
-150,
-139,
-3,
-79,
-23,
-148,
-133,
-248,
-20,
-240,
-37,
-224,
-214,
-200,
-245,
-87,
-24,
-200,
-199,
-112,
-2,
-54,
-34,
-116,
-204,
-227,
-123,
-17,
-25,
-53,
-114,
-229,
-127,
-135,
-77,
-191,
-133,
-31,
-106,
-207,
-64,
-77,
-107,
-21,
-102,
-219,
-254,
-185,
-31,
-119,
-24,
-32,
-96,
-158,
-50,
-155,
-96,
-115,
-249,
-16,
-199,
-208,
-28,
-227,
-252,
-22,
-243,
-34,
-26,
-195,
-192,
-180,
-80,
-196,
-56,
-147,
-176,
-233,
-226,
-173,
-216,
-84,
-112,
-163,
-51,
-208,
-222,
-206,
-16,
-239,
-5,
-118,
-143,
-148,
-123,
-9,
-88,
-212,
-143,
-31,
-194,
-134,
-227,
-29,
-176,
-17,
-96,
-25,
-44,
-140,
-254,
-226,
-130,
-103,
-28,
-194,
-0,
-94,
-230,
-73,
-224,
-63,
-35,
-244,
-147,
-49,
-47,
-165,
-245,
-48,
-33,
-117,
-211,
-204,
-189,
-227,
-129,
-59,
-99,
-237,
-228,
-222,
-41,
-184,
-235,
-88,
-95,
-65,
-3,
-107,
-21,
-240,
-85,
-44,
-16,
-36,
-43,
-205,
-47,
-133,
-45,
-45,
-79,
-46,
-40,
-147,
-101,
-156,
-149,
-176,
-37,
-224,
-52,
-60,
-137,
-85,
-9,
-227,
-108,
-143,
-205,
-253,
-211,
-129,
-111,
-97,
-67,
-236,
-209,
-126,
-237,
-117,
-108,
-78,
-143,
-249,
-7,
-78,
-196,
-163,
-156,
-177,
-161,
-123,
-138,
-63,
-215,
-4,
-224,
-127,
-48,
-225,
-108,
-229,
-130,
-190,
-130,
-77,
-1,
-11,
-96,
-242,
-194,
-1,
-152,
-176,
-118,
-13,
-145,
-21,
-18,
-230,
-91,
-112,
-15,
-54,
-141,
-158,
-150,
-185,
-62,
-143,
-51,
-71,
-244,
-157,
-100,
-232,
-118,
-114,
-134,
-45,
-52,
-130,
-245,
-4,
-116,
-97,
-173,
-242,
-31,
-244,
-10,
-108,
-202,
-184,
-218,
-143,
-75,
-151,
-47,
-77,
-24,
-167,
-41,
-128,
-255,
-44,
-98,
-224,
-132,
-178,
-89,
-60,
-143,
-45,
-169,
-143,
-2,
-230,
-43,
-160,
-95,
-6,
-147,
-222,
-95,
-198,
-150,
-172,
-11,
-99,
-115,
-250,
-149,
-206,
-116,
-67,
-150,
-129,
-206,
-28,
-11,
-97,
-194,
-232,
-93,
-192,
-25,
-77,
-250,
-58,
-199,
-161,
-9,
-227,
-52,
-108,
-103,
-62,
-255,
-98,
-127,
-69,
-198,
-117,
-219,
-127,
-172,
-86,
-29,
-51,
-177,
-21,
-204,
-115,
-152,
-101,
-242,
-49,
-76,
-168,
-155,
-234,
-35,
-86,
-52,
-84,
-206,
-71,
-150,
-87,
-188,
-220,
-15,
-128,
-249,
-219,
-236,
-147,
-168,
-25,
-218,
-53,
-55,
-194,
-153,
-224,
-211,
-152,
-84,
-62,
-13,
-243,
-29,
-120,
-0,
-23,
-88,
-91,
-110,
-43,
-26,
-31,
-208,
-55,
-144,
-203,
-172,
-73,
-196,
-109,
-122,
-20,
-115,
-15,
-98,
-95,
-247,
-254,
-146,
-54,
-240,
-227,
-219,
-36,
-213,
-138,
-238,
-29,
-197,
-28,
-142,
-58,
-67,
-190,
-207,
-89,
-175,
-145,
-243,
-184,
-193,
-194,
-157,
-94,
-45,
-154,
-183,
-114,
-180,
-141,
-194,
-200,
-71,
-209,
-3,
-48,
-216,
-18,
-213,
-17,
-64,
-190,
-77,
-137,
-73,
-17,
-211,
-174,
-125,
-35,
-119,
-237,
-219,
-20,
-172,
-141,
-35,
-229,
-107,
-133,
-145,
-211,
-48,
-139,
-246,
-40,
-163,
-85,
-128,
-1,
-75,
-212,
-165,
-12,
-88,
-162,
-214,
-243,
-31,
-248,
-62,
-92,
-25,
-18,
-41,
-183,
-11,
-166,
-194,
-237,
-228,
-2,
-126,
-147,
-11,
-73,
-61,
-177,
-233,
-99,
-214,
-183,
-14,
-3,
-36,
-121,
-227,
-122,
-185,
-36,
-70,
-195,
-20,
-66,
-19,
-49,
-69,
-204,
-237,
-84,
-104,
-63,
-115,
-101,
-107,
-51,
-39,
-53,
-82,
-187,
-231,
-202,
-181,
-203,
-208,
-152,
-37,
-234,
-94,
-114,
-22,
-36,
-76,
-203,
-54,
-153,
-98,
-139,
-215,
-60,
-62,
-98,
-236,
-226,
-231,
-187,
-59,
-35,
-69,
-95,
-52,
-109,
-57,
-48,
-244,
-8,
-152,
-54,
-243,
-84,
-96,
-9,
-76,
-115,
-152,
-148,
-19,
-217,
-203,
-214,
-98,
-78,
-224,
-187,
-152,
-86,
-114,
-117,
-76,
-135,
-145,
-156,
-218,
-189,
-238,
-200,
-153,
-82,
-225,
-32,
-75,
-84,
-238,
-222,
-241,
-101,
-28,
-141,
-41,
-102,
-126,
-230,
-199,
-191,
-161,
-192,
-108,
-153,
-161,
-175,
-229,
-192,
-208,
-132,
-105,
-176,
-168,
-160,
-105,
-228,
-220,
-176,
-49,
-83,
-247,
-179,
-37,
-35,
-218,
-11,
-25,
-102,
-222,
-139,
-2,
-61,
-255,
-92,
-7,
-50,
-150,
-168,
-200,
-189,
-82,
-67,
-4,
-102,
-38,
-157,
-142,
-185,
-135,
-205,
-160,
-192,
-118,
-158,
-161,
-175,
-237,
-192,
-80,
-151,
-105,
-252,
-254,
-137,
-152,
-118,
-44,
-100,
-174,
-221,
-70,
-196,
-25,
-35,
-115,
-255,
-39,
-152,
-61,
-98,
-2,
-166,
-149,
-59,
-172,
-236,
-89,
-188,
-76,
-19,
-217,
-169,
-47,
-101,
-146,
-209,
-13,
-3,
-56,
-205,
-95,
-49,
-15,
-153,
-63,
-150,
-209,
-57,
-109,
-109,
-7,
-134,
-134,
-76,
-179,
-136,
-127,
-237,
-239,
-243,
-243,
-157,
-177,
-136,
-227,
-178,
-128,
-145,
-245,
-48,
-211,
-246,
-27,
-192,
-222,
-9,
-207,
-82,
-91,
-118,
-234,
-87,
-153,
-90,
-192,
-116,
-205,
-199,
-23,
-220,
-75,
-177,
-68,
-29,
-236,
-47,
-46,
-150,
-58,
-37,
-70,
-95,
-203,
-129,
-161,
-9,
-211,
-100,
-218,
-185,
-193,
-143,
-255,
-74,
-193,
-52,
-231,
-247,
-223,
-235,
-12,
-115,
-54,
-166,
-233,
-251,
-25,
-3,
-206,
-41,
-135,
-19,
-113,
-200,
-160,
-129,
-236,
-212,
-175,
-50,
-181,
-128,
-37,
-130,
-190,
-47,
-210,
-64,
-146,
-37,
-170,
-65,
-123,
-181,
-29,
-24,
-234,
-50,
-141,
-211,
-45,
-236,
-95,
-253,
-103,
-49,
-169,
-57,
-26,
-126,
-229,
-180,
-119,
-0,
-95,
-242,
-227,
-149,
-24,
-112,
-200,
-92,
-206,
-153,
-237,
-195,
-145,
-50,
-181,
-101,
-167,
-126,
-149,
-169,
-133,
-204,
-16,
-115,
-21,
-230,
-138,
-148,
-181,
-68,
-117,
-63,
-196,
-196,
-219,
-172,
-229,
-192,
-208,
-132,
-105,
-188,
-220,
-113,
-24,
-134,
-216,
-224,
-115,
-116,
-47,
-2,
-187,
-101,
-206,
-87,
-198,
-28,
-100,
-94,
-0,
-190,
-95,
-80,
-166,
-246,
-212,
-217,
-175,
-50,
-41,
-200,
-238,
-26,
-246,
-140,
-164,
-77,
-36,
-77,
-145,
-244,
-39,
-73,
-255,
-150,
-101,
-8,
-123,
-80,
-182,
-251,
-85,
-161,
-67,
-104,
-23,
-248,
-158,
-164,
-237,
-37,
-37,
-165,
-109,
-245,
-157,
-205,
-174,
-148,
-116,
-150,
-108,
-199,
-178,
-201,
-137,
-237,
-116,
-148,
-82,
-67,
-210,
-215,
-231,
-112,
-163,
-164,
-227,
-176,
-101,
-220,
-56,
-73,
-155,
-202,
-118,
-239,
-154,
-79,
-210,
-180,
-196,
-182,
-230,
-40,
-204,
-155,
-61,
-241,
-45,
-224,
-62,
-218,
-199,
-246,
-103,
-74,
-154,
-33,
-233,
-162,
-26,
-101,
-190,
-39,
-233,
-119,
-170,
-215,
-207,
-212,
-32,
-207,
-131,
-36,
-125,
-93,
-198,
-248,
-11,
-73,
-154,
-36,
-233,
-11,
-146,
-110,
-146,
-116,
-45,
-240,
-74,
-8,
-33,
-191,
-130,
-152,
-34,
-41,
-234,
-16,
-226,
-215,
-239,
-143,
-92,
-239,
-87,
-153,
-222,
-131,
-226,
-165,
-73,
-52,
-89,
-34,
-93,
-58,
-48,
-208,
-192,
-235,
-133,
-129,
-93,
-63,
-86,
-173,
-211,
-86,
-98,
-221,
-181,
-101,
-167,
-126,
-149,
-233,
-57,
-40,
-95,
-154,
-60,
-64,
-102,
-179,
-168,
-76,
-153,
-218,
-14,
-12,
-45,
-48,
-77,
-47,
-25,
-160,
-182,
-236,
-212,
-175,
-50,
-61,
-7,
-189,
-94,
-154,
-12,
-212,
-215,
-91,
-175,
-151,
-46,
-145,
-25,
-5,
-31,
-167,
-190,
-82,
-167,
-167,
-101,
-154,
-62,
-80,
-82,
-198,
-110,
-122,
-189,
-52,
-25,
-197,
-240,
-128,
-196,
-140,
-221,
-244,
-104,
-105,
-50,
-138,
-254,
-97,
-222,
-216,
-197,
-16,
-194,
-44,
-73,
-71,
-181,
-80,
-127,
-123,
-73,
-12,
-71,
-209,
-19,
-12,
-50,
-37,
-82,
-223,
-216,
-48,
-69,
-229,
-75,
-147,
-41,
-249,
-139,
-52,
-180,
-210,
-213,
-133,
-11,
-125,
-177,
-168,
-156,
-194,
-220,
-63,
-152,
-47,
-195,
-49,
-152,
-63,
-192,
-75,
-152,
-98,
-232,
-110,
-160,
-141,
-143,
-97,
-100,
-163,
-66,
-162,
-47,
-146,
-76,
-171,
-150,
-38,
-255,
-85,
-208,
-86,
-19,
-43,
-93,
-45,
-230,
-172,
-203,
-0,
-254,
-227,
-95,
-135,
-5,
-101,
-236,
-224,
-140,
-250,
-86,
-224,
-253,
-177,
-122,
-114,
-253,
-122,
-202,
-143,
-151,
-6,
-30,
-47,
-233,
-79,
-7,
-149,
-201,
-34,
-98,
-253,
-199,
-98,
-45,
-175,
-35,
-30,
-195,
-56,
-147,
-248,
-30,
-6,
-105,
-201,
-174,
-104,
-102,
-160,
-40,
-91,
-154,
-220,
-73,
-65,
-6,
-76,
-106,
-90,
-233,
-26,
-50,
-103,
-93,
-6,
-56,
-14,
-75,
-252,
-80,
-107,
-4,
-2,
-118,
-197,
-147,
-81,
-98,
-219,
-202,
-71,
-211,
-220,
-123,
-127,
-146,
-147,
-69,
-228,
-251,
-15,
-124,
-25,
-27,
-153,
-138,
-114,
-4,
-212,
-122,
-222,
-14,
-178,
-83,
-192,
-174,
-146,
-190,
-239,
-243,
-255,
-108,
-132,
-16,
-222,
-144,
-169,
-106,
-135,
-108,
-22,
-25,
-81,
-31,
-79,
-147,
-116,
-151,
-164,
-151,
-36,
-109,
-17,
-66,
-24,
-18,
-1,
-235,
-229,
-158,
-151,
-244,
-223,
-146,
-58,
-43,
-136,
-207,
-74,
-58,
-35,
-132,
-240,
-66,
-65,
-63,
-63,
-43,
-233,
-85,
-73,
-31,
-10,
-33,
-220,
-30,
-66,
-120,
-62,
-132,
-112,
-167,
-108,
-131,
-134,
-55,
-36,
-125,
-166,
-160,
-92,
-29,
-236,
-39,
-233,
-188,
-6,
-42,
-239,
-13,
-36,
-77,
-140,
-28,
-199,
-240,
-122,
-8,
-225,
-149,
-16,
-194,
-148,
-16,
-194,
-111,
-37,
-109,
-37,
-105,
-41,
-73,
-71,
-151,
-53,
-0,
-28,
-42,
-105,
-15,
-73,
-59,
-250,
-187,
-107,
-31,
-180,
-36,
-209,
-99,
-86,
-186,
-137,
-249,
-145,
-36,
-66,
-87,
-199,
-74,
-215,
-196,
-122,
-86,
-138,
-8,
-253,
-12,
-96,
-191,
-148,
-103,
-116,
-250,
-231,
-252,
-111,
-38,
-102,
-44,
-26,
-116,
-92,
-208,
-159,
-58,
-201,
-34,
-240,
-175,
-247,
-3,
-62,
-250,
-69,
-115,
-4,
-37,
-212,
-159,
-60,
-2,
-180,
-133,
-79,
-75,
-90,
-69,
-210,
-37,
-148,
-36,
-67,
-242,
-175,
-253,
-12,
-73,
-95,
-145,
-116,
-122,
-8,
-225,
-165,
-146,
-58,
-223,
-46,
-233,
-161,
-130,
-123,
-15,
-122,
-123,
-49,
-236,
-44,
-105,
-129,
-220,
-223,
-206,
-69,
-93,
-146,
-217,
-38,
-102,
-163,
-140,
-97,
-66,
-8,
-139,
-133,
-16,
-22,
-147,
-244,
-164,
-164,
-181,
-252,
-248,
-127,
-37,
-173,
-238,
-199,
-169,
-184,
-167,
-164,
-255,
-235,
-75,
-250,
-153,
-108,
-116,
-28,
-146,
-189,
-164,
-13,
-100,
-25,
-96,
-138,
-90,
-48,
-54,
-132,
-16,
-238,
-149,
-89,
-248,
-222,
-144,
-84,
-149,
-201,
-58,
-213,
-74,
-215,
-20,
-157,
-33,
-119,
-246,
-95,
-73,
-159,
-30,
-148,
-148,
-207,
-53,
-80,
-198,
-48,
-194,
-118,
-20,
-39,
-132,
-48,
-21,
-75,
-224,
-52,
-203,
-13,
-106,
-117,
-48,
-70,
-210,
-172,
-130,
-123,
-235,
-203,
-166,
-166,
-147,
-128,
-229,
-107,
-214,
-155,
-220,
-120,
-7,
-151,
-73,
-58,
-36,
-63,
-116,
-251,
-249,
-193,
-146,
-46,
-77,
-173,
-52,
-132,
-240,
-247,
-16,
-194,
-110,
-33,
-132,
-170,
-60,
-182,
-169,
-86,
-186,
-41,
-234,
-189,
-37,
-236,
-18,
-73,
-135,
-146,
-145,
-176,
-203,
-24,
-198,
-135,
-249,
-127,
-73,
-90,
-214,
-143,
-39,
-75,
-90,
-174,
-51,
-53,
-212,
-104,
-247,
-157,
-94,
-54,
-134,
-11,
-93,
-86,
-184,
-72,
-210,
-79,
-200,
-172,
-154,
-34,
-152,
-37,
-51,
-91,
-231,
-241,
-38,
-229,
-70,
-182,
-44,
-178,
-12,
-112,
-170,
-19,
-95,
-73,
-70,
-162,
-151,
-116,
-185,
-211,
-69,
-51,
-104,
-245,
-9,
-173,
-49,
-103,
-9,
-206,
-144,
-9,
-175,
-127,
-194,
-178,
-164,
-45,
-138,
-173,
-74,
-162,
-95,
-158,
-15,
-243,
-231,
-72,
-58,
-209,
-143,
-207,
-148,
-116,
-82,
-102,
-106,
-168,
-4,
-102,
-49,
-253,
-152,
-108,
-152,
-47,
-195,
-103,
-36,
-173,
-36,
-233,
-216,
-18,
-154,
-123,
-37,
-189,
-59,
-114,
-125,
-35,
-191,
-151,
-212,
-161,
-254,
-24,
-27,
-6,
-218,
-75,
-178,
-210,
-209,
-204,
-122,
-86,
-91,
-40,
-194,
-188,
-154,
-191,
-137,
-101,
-5,
-155,
-233,
-130,
-225,
-189,
-20,
-236,
-235,
-227,
-237,
-79,
-240,
-227,
-203,
-40,
-217,
-234,
-206,
-251,
-83,
-39,
-89,
-196,
-160,
-254,
-99,
-233,
-239,
-95,
-6,
-54,
-200,
-211,
-250,
-253,
-61,
-48,
-167,
-217,
-3,
-253,
-119,
-124,
-27,
-112,
-144,
-11,
-165,
-251,
-23,
-245,
-107,
-142,
-65,
-191,
-153,
-51,
-177,
-79,
-79,
-116,
-218,
-247,
-227,
-183,
-149,
-208,
-102,
-145,
-146,
-44,
-98,
-8,
-3,
-99,
-241,
-23,
-147,
-41,
-78,
-43,
-255,
-62,
-44,
-132,
-253,
-101,
-103,
-222,
-155,
-129,
-15,
-117,
-243,
-140,
-163,
-24,
-197,
-40,
-70,
-49,
-138,
-185,
-31,
-62,
-231,
-220,
-157,
-159,
-147,
-42,
-132,
-166,
-43,
-124,
-94,
-126,
-210,
-231,
-230,
-239,
-2,
-151,
-39,
-180,
-53,
-98,
-66,
-181,
-105,
-24,
-110,
-62,
-183,
-32,
-175,
-9,
-92,
-84,
-210,
-49,
-53,
-202,
-63,
-41,
-105,
-89,
-73,
-107,
-75,
-90,
-75,
-210,
-91,
-252,
-90,
-21,
-46,
-144,
-45,
-125,
-134,
-4,
-90,
-228,
-65,
-162,
-119,
-82,
-174,
-76,
-157,
-144,
-235,
-236,
-26,
-185,
-72,
-33,
-83,
-214,
-86,
-85,
-184,
-249,
-10,
-152,
-89,
-121,
-205,
-18,
-154,
-206,
-190,
-73,
-235,
-213,
-108,
-187,
-52,
-112,
-21,
-203,
-99,
-124,
-117,
-238,
-218,
-159,
-201,
-236,
-175,
-148,
-189,
-1,
-240,
-31,
-46,
-161,
-142,
-203,
-92,
-47,
-27,
-1,
-30,
-3,
-86,
-201,
-156,
-47,
-82,
-213,
-169,
-186,
-32,
-209,
-59,
-41,
-67,
-223,
-56,
-228,
-58,
-177,
-254,
-90,
-57,
-148,
-128,
-243,
-49,
-251,
-72,
-105,
-194,
-12,
-108,
-207,
-133,
-115,
-203,
-104,
-156,
-110,
-33,
-6,
-194,
-213,
-254,
-234,
-255,
-3,
-17,
-203,
-171,
-255,
-30,
-15,
-2,
-255,
-225,
-231,
-135,
-96,
-206,
-186,
-67,
-173,
-174,
-206,
-0,
-91,
-250,
-131,
-93,
-158,
-185,
-94,
-198,
-0,
-79,
-144,
-73,
-146,
-136,
-173,
-207,
-163,
-241,
-244,
-116,
-107,
-175,
-110,
-25,
-77,
-251,
-131,
-237,
-228,
-185,
-178,
-191,
-167,
-231,
-128,
-35,
-74,
-104,
-215,
-240,
-23,
-62,
-63,
-102,
-30,
-127,
-103,
-9,
-237,
-70,
-216,
-154,
-189,
-106,
-131,
-141,
-19,
-48,
-179,
-245,
-79,
-49,
-31,
-138,
-159,
-98,
-9,
-58,
-190,
-88,
-64,
-191,
-137,
-223,
-127,
-167,
-255,
-31,
-178,
-231,
-67,
-135,
-16,
-108,
-139,
-182,
-133,
-176,
-112,
-168,
-78,
-170,
-215,
-50,
-6,
-248,
-1,
-150,
-174,
-117,
-49,
-255,
-241,
-127,
-82,
-244,
-197,
-121,
-253,
-117,
-236,
-243,
-181,
-126,
-160,
-6,
-244,
-181,
-250,
-147,
-185,
-95,
-39,
-135,
-210,
-175,
-128,
-143,
-250,
-241,
-190,
-68,
-82,
-216,
-230,
-232,
-255,
-9,
-28,
-94,
-65,
-179,
-8,
-182,
-165,
-252,
-49,
-216,
-212,
-114,
-180,
-159,
-23,
-250,
-49,
-96,
-142,
-39,
-51,
-136,
-56,
-232,
-228,
-31,
-38,
-184,
-13,
-255,
-40,
-73,
-103,
-71,
-135,
-138,
-193,
-120,
-171,
-164,
-103,
-100,
-170,
-198,
-251,
-100,
-115,
-104,
-105,
-110,
-128,
-26,
-152,
-39,
-210,
-191,
-54,
-233,
-107,
-193,
-25,
-230,
-110,
-111,
-39,
-123,
-189,
-136,
-193,
-54,
-148,
-244,
-46,
-13,
-132,
-189,
-93,
-36,
-105,
-53,
-96,
-147,
-146,
-102,
-206,
-145,
-52,
-36,
-93,
-109,
-22,
-238,
-15,
-48,
-77,
-246,
-27,
-29,
-44,
-179,
-190,
-78,
-171,
-240,
-99,
-24,
-39,
-233,
-89,
-255,
-63,
-8,
-209,
-23,
-22,
-66,
-248,
-181,
-44,
-69,
-220,
-41,
-42,
-49,
-36,
-132,
-16,
-118,
-9,
-33,
-28,
-18,
-66,
-88,
-38,
-132,
-240,
-182,
-16,
-194,
-193,
-33,
-132,
-29,
-203,
-30,
-96,
-14,
-71,
-29,
-33,
-249,
-84,
-73,
-167,
-116,
-12,
-98,
-238,
-88,
-243,
-21,
-73,
-101,
-177,
-18,
-191,
-144,
-244,
-54,
-42,
-118,
-17,
-149,
-180,
-177,
-164,
-137,
-33,
-132,
-95,
-74,
-186,
-69,
-210,
-123,
-139,
-8,
-49,
-175,
-171,
-237,
-36,
-189,
-71,
-210,
-14,
-120,
-198,
-244,
-24,
-225,
-160,
-33,
-17,
-203,
-160,
-253,
-60,
-182,
-189,
-74,
-215,
-115,
-116,
-131,
-41,
-96,
-36,
-210,
-215,
-18,
-146,
-155,
-0,
-115,
-205,
-251,
-101,
-75,
-117,
-45,
-137,
-201,
-105,
-157,
-233,
-124,
-79,
-63,
-95,
-162,
-67,
-83,
-56,
-100,
-134,
-16,
-30,
-146,
-244,
-85,
-73,
-95,
-106,
-163,
-51,
-115,
-9,
-238,
-151,
-116,
-190,
-164,
-111,
-245,
-176,
-141,
-115,
-37,
-189,
-159,
-130,
-13,
-162,
-106,
-226,
-219,
-146,
-238,
-8,
-33,
-252,
-74,
-146,
-124,
-196,
-184,
-211,
-175,
-75,
-170,
-158,
-51,
-191,
-38,
-11,
-19,
-111,
-3,
-141,
-236,
-213,
-61,
-68,
-147,
-254,
-204,
-39,
-233,
-68,
-73,
-235,
-119,
-190,
-170,
-182,
-17,
-66,
-184,
-95,
-210,
-181,
-50,
-51,
-113,
-183,
-117,
-237,
-29,
-66,
-152,
-144,
-187,
-182,
-67,
-8,
-97,
-246,
-86,
-128,
-217,
-252,
-0,
-33,
-132,
-112,
-117,
-142,
-248,
-245,
-16,
-194,
-58,
-33,
-132,
-50,
-71,
-132,
-84,
-212,
-181,
-87,
-215,
-253,
-129,
-234,
-210,
-55,
-177,
-159,
-215,
-21,
-146,
-155,
-226,
-28,
-73,
-31,
-197,
-115,
-47,
-206,
-21,
-160,
-166,
-189,
-26,
-83,
-209,
-126,
-62,
-114,
-253,
-11,
-46,
-141,
-119,
-75,
-95,
-183,
-63,
-121,
-25,
-233,
-114,
-44,
-151,
-208,
-248,
-54,
-101,
-128,
-185,
-26,
-212,
-176,
-87,
-55,
-248,
-129,
-106,
-59,
-68,
-212,
-236,
-79,
-158,
-1,
-90,
-21,
-146,
-71,
-17,
-65,
-157,
-31,
-168,
-9,
-125,
-205,
-190,
-12,
-89,
-53,
-96,
-46,
-237,
-79,
-14,
-39,
-3,
-120,
-191,
-54,
-175,
-166,
-76,
-171,
-108,
-173,
-252,
-57,
-17,
-71,
-68,
-74,
-208,
-74,
-71,
-70,
-32,
-10,
-24,
-96,
-62,
-204,
-130,
-58,
-231,
-51,
-0,
-176,
-10,
-166,
-99,
-222,
-193,
-207,
-183,
-33,
-183,
-143,
-95,
-134,
-182,
-179,
-207,
-222,
-26,
-222,
-129,
-181,
-41,
-216,
-119,
-111,
-20,
-67,
-129,
-109,
-170,
-149,
-36,
-88,
-99,
-6,
-173,
-168,
-219,
-152,
-223,
-111,
-117,
-4,
-216,
-210,
-153,
-224,
-243,
-254,
-127,
-124,
-5,
-253,
-88,
-239,
-64,
-235,
-169,
-87,
-230,
-102,
-164,
-254,
-248,
-78,
-75,
-217,
-135,
-149,
-101,
-0,
-204,
-225,
-244,
-38,
-114,
-41,
-117,
-235,
-118,
-238,
-24,
-175,
-52,
-154,
-53,
-52,
-71,
-155,
-196,
-0,
-88,
-46,
-225,
-171,
-49,
-227,
-197,
-19,
-152,
-141,
-255,
-255,
-252,
-94,
-68,
-41,
-72,
-101,
-0,
-44,
-136,
-247,
-55,
-192,
-239,
-105,
-178,
-103,
-176,
-87,
-182,
-149,
-127,
-249,
-157,
-72,
-217,
-237,
-43,
-232,
-83,
-25,
-224,
-70,
-44,
-217,
-243,
-50,
-152,
-229,
-234,
-160,
-146,
-135,
-129,
-129,
-125,
-252,
-206,
-1,
-22,
-79,
-232,
-119,
-233,
-48,
-233,
-52,
-75,
-97,
-142,
-34,
-83,
-177,
-56,
-200,
-135,
-40,
-216,
-45,
-188,
-23,
-192,
-220,
-192,
-99,
-136,
-109,
-33,
-123,
-97,
-1,
-237,
-175,
-34,
-180,
-96,
-91,
-204,
-125,
-195,
-191,
-254,
-232,
-182,
-244,
-41,
-29,
-28,
-135,
-205,
-249,
-219,
-248,
-249,
-22,
-126,
-190,
-86,
-73,
-153,
-84,
-6,
-120,
-153,
-34,
-35,
-196,
-96,
-58,
-48,
-223,
-249,
-133,
-49,
-251,
-248,
-157,
-120,
-26,
-250,
-132,
-114,
-101,
-95,
-201,
-34,
-152,
-59,
-245,
-213,
-152,
-235,
-215,
-226,
-254,
-124,
-177,
-212,
-175,
-11,
-3,
-23,
-224,
-210,
-125,
-22,
-17,
-218,
-107,
-129,
-255,
-206,
-93,
-59,
-25,
-207,
-77,
-156,
-187,
-62,
-134,
-220,
-62,
-197,
-254,
-55,
-36,
-225,
-21,
-38,
-92,
-118,
-238,
-131,
-5,
-169,
-188,
-153,
-8,
-147,
-251,
-253,
-142,
-7,
-212,
-16,
-121,
-173,
-22,
-200,
-24,
-57,
-252,
-188,
-40,
-104,
-177,
-115,
-63,
-149,
-1,
-238,
-33,
-205,
-219,
-5,
-6,
-175,
-181,
-247,
-7,
-42,
-85,
-209,
-9,
-12,
-112,
-10,
-230,
-189,
-84,
-24,
-172,
-154,
-161,
-61,
-39,
-247,
-187,
-79,
-194,
-116,
-10,
-147,
-34,
-180,
-91,
-96,
-211,
-90,
-103,
-43,
-219,
-249,
-253,
-163,
-121,
-127,
-69,
-27,
-109,
-203,
-0,
-191,
-194,
-188,
-160,
-174,
-168,
-83,
-119,
-215,
-168,
-193,
-0,
-59,
-99,
-27,
-62,
-92,
-71,
-137,
-61,
-60,
-194,
-0,
-31,
-6,
-162,
-193,
-150,
-212,
-27,
-38,
-239,
-166,
-98,
-19,
-139,
-12,
-237,
-99,
-185,
-250,
-238,
-242,
-235,
-81,
-135,
-81,
-44,
-215,
-241,
-201,
-126,
-124,
-176,
-51,
-123,
-233,
-143,
-64,
-15,
-86,
-1,
-216,
-200,
-245,
-16,
-240,
-233,
-148,
-122,
-91,
-65,
-42,
-3,
-56,
-237,
-234,
-152,
-144,
-50,
-139,
-200,
-208,
-235,
-52,
-48,
-48,
-5,
-108,
-140,
-165,
-145,
-249,
-66,
-1,
-109,
-157,
-97,
-242,
-21,
-96,
-159,
-88,
-61,
-17,
-218,
-153,
-53,
-25,
-96,
-19,
-204,
-71,
-112,
-17,
-108,
-47,
-225,
-131,
-83,
-218,
-105,
-11,
-29,
-6,
-240,
-227,
-205,
-49,
-5,
-216,
-187,
-250,
-213,
-120,
-237,
-101,
-32,
-182,
-15,
-79,
-52,
-214,
-63,
-242,
-53,
-31,
-153,
-88,
-39,
-148,
-15,
-147,
-175,
-144,
-176,
-249,
-131,
-211,
-78,
-175,
-195,
-0,
-126,
-239,
-114,
-76,
-250,
-158,
-74,
-36,
-206,
-175,
-151,
-200,
-50,
-128,
-159,
-127,
-5,
-155,
-182,
-10,
-19,
-110,
-12,
-43,
-176,
-164,
-75,
-209,
-52,
-39,
-254,
-48,
-219,
-249,
-241,
-223,
-129,
-66,
-239,
-155,
-220,
-8,
-112,
-169,
-143,
-26,
-69,
-35,
-192,
-36,
-224,
-115,
-137,
-253,
-251,
-83,
-42,
-3,
-48,
-48,
-250,
-228,
-177,
-66,
-74,
-91,
-35,
-10,
-184,
-85,
-43,
-134,
-46,
-235,
-93,
-10,
-51,
-208,
-44,
-141,
-249,
-200,
-95,
-6,
-252,
-174,
-128,
-54,
-203,
-0,
-187,
-97,
-75,
-209,
-162,
-68,
-83,
-117,
-100,
-128,
-51,
-177,
-249,
-177,
-242,
-235,
-196,
-146,
-80,
-61,
-156,
-194,
-0,
-126,
-61,
-59,
-13,
-237,
-196,
-156,
-170,
-13,
-37,
-190,
-76,
-89,
-180,
-5,
-6,
-88,
-28,
-219,
-170,
-165,
-147,
-71,
-231,
-18,
-10,
-162,
-104,
-115,
-12,
-16,
-48,
-225,
-45,
-233,
-203,
-173,
-232,
-195,
-210,
-152,
-167,
-243,
-223,
-176,
-53,
-243,
-34,
-216,
-178,
-183,
-72,
-22,
-121,
-51,
-176,
-1,
-176,
-97,
-25,
-3,
-208,
-197,
-8,
-224,
-12,
-254,
-40,
-17,
-165,
-77,
-65,
-157,
-253,
-183,
-55,
-116,
-30,
-176,
-143,
-237,
-205,
-102,
-0,
-63,
-255,
-48,
-45,
-37,
-143,
-4,
-150,
-7,
-190,
-143,
-133,
-176,
-205,
-194,
-76,
-185,
-215,
-38,
-148,
-235,
-201,
-8,
-128,
-229,
-58,
-40,
-202,
-163,
-56,
-187,
-174,
-236,
-95,
-74,
-189,
-173,
-2,
-155,
-103,
-135,
-36,
-71,
-192,
-180,
-121,
-127,
-241,
-151,
-217,
-193,
-227,
-100,
-156,
-13,
-71,
-50,
-128,
-139,
-129,
-75,
-18,
-105,
-43,
-133,
-64,
-191,
-63,
-136,
-121,
-43,
-104,
-87,
-199,
-150,
-197,
-149,
-35,
-97,
-66,
-155,
-187,
-96,
-59,
-156,
-206,
-192,
-130,
-86,
-214,
-79,
-233,
-67,
-87,
-192,
-134,
-244,
-147,
-252,
-248,
-68,
-224,
-250,
-158,
-55,
-218,
-34,
-176,
-41,
-33,
-41,
-223,
-94,
-42,
-3,
-212,
-108,
-255,
-44,
-160,
-112,
-151,
-148,
-154,
-12,
-48,
-25,
-155,
-170,
-150,
-193,
-132,
-225,
-222,
-255,
-22,
-206,
-109,
-219,
-250,
-241,
-182,
-68,
-244,
-217,
-125,
-232,
-67,
-22,
-47,
-99,
-243,
-233,
-197,
-84,
-107,
-47,
-255,
-138,
-173,
-48,
-62,
-153,
-216,
-78,
-171,
-12,
-128,
-89,
-236,
-166,
-1,
-91,
-149,
-208,
-68,
-81,
-64,
-247,
-137,
-204,
-249,
-142,
-64,
-81,
-178,
-205,
-40,
-154,
-90,
-228,
-238,
-151,
-244,
-65,
-31,
-242,
-63,
-168,
-226,
-44,
-87,
-131,
-128,
-205,
-233,
-80,
-18,
-35,
-87,
-19,
-157,
-60,
-128,
-111,
-147,
-101,
-50,
-93,
-82,
-210,
-144,
-85,
-64,
-22,
-33,
-132,
-45,
-66,
-8,
-27,
-133,
-16,
-206,
-105,
-169,
-15,
-117,
-177,
-159,
-164,
-199,
-66,
-8,
-215,
-85,
-208,
-197,
-114,
-28,
-198,
-144,
-117,
-96,
-125,
-81,
-182,
-215,
-81,
-111,
-225,
-67,
-206,
-52,
-204,
-106,
-55,
-145,
-4,
-205,
-19,
-176,
-32,
-166,
-217,
-123,
-190,
-136,
-1,
-48,
-189,
-122,
-244,
-47,
-66,
-59,
-100,
-152,
-196,
-36,
-235,
-178,
-132,
-147,
-195,
-14,
-204,
-101,
-173,
-116,
-244,
-169,
-57,
-5,
-100,
-149,
-64,
-155,
-199,
-70,
-138,
-50,
-148,
-186,
-29,
-3,
-99,
-60,
-164,
-105,
-16,
-66,
-8,
-255,
-196,
-214,
-212,
-107,
-132,
-16,
-30,
-76,
-108,
-235,
-51,
-178,
-221,
-184,
-10,
-99,
-223,
-66,
-8,
-141,
-184,
-23,
-83,
-254,
-140,
-149,
-237,
-36,
-86,
-103,
-7,
-178,
-174,
-128,
-57,
-204,
-68,
-87,
-18,
-49,
-87,
-122,
-44,
-50,
-119,
-13,
-73,
-63,
-233,
-109,
-207,
-26,
-130,
-26,
-177,
-239,
-88,
-122,
-179,
-14,
-158,
-164,
-68,
-213,
-138,
-45,
-193,
-158,
-192,
-148,
-66,
-111,
-180,
-49,
-5,
-20,
-76,
-147,
-23,
-208,
-212,
-25,
-162,
-89,
-31,
-138,
-76,
-188,
-209,
-37,
-27,
-233,
-57,
-0,
-250,
-54,
-2,
-228,
-101,
-128,
-253,
-101,
-25,
-175,
-37,
-11,
-14,
-141,
-166,
-112,
-1,
-206,
-145,
-101,
-239,
-92,
-213,
-255,
-206,
-85,
-121,
-34,
-201,
-175,
-74,
-58,
-199,
-179,
-139,
-183,
-105,
-174,
-236,
-204,
-147,
-11,
-75,
-26,
-47,
-11,
-234,
-248,
-122,
-164,
-191,
-27,
-98,
-186,
-250,
-233,
-88,
-130,
-234,
-139,
-40,
-73,
-233,
-150,
-138,
-16,
-194,
-27,
-249,
-84,
-180,
-153,
-148,
-180,
-249,
-62,
-44,
-41,
-105,
-47,
-101,
-194,
-178,
-70,
-28,
-72,
-116,
-211,
-242,
-121,
-121,
-163,
-204,
-249,
-38,
-20,
-164,
-71,
-197,
-52,
-111,
-143,
-227,
-198,
-9,
-231,
-218,
-182,
-70,
-128,
-188,
-12,
-176,
-63,
-240,
-108,
-132,
-246,
-66,
-204,
-81,
-99,
-101,
-108,
-13,
-126,
-45,
-5,
-121,
-253,
-157,
-62,
-201,
-123,
-136,
-30,
-169,
-207,
-135,
-5,
-222,
-239,
-36,
-165,
-2,
-102,
-207,
-62,
-210,
-143,
-23,
-244,
-23,
-28,
-141,
-104,
-5,
-110,
-192,
-44,
-84,
-171,
-250,
-31,
-152,
-255,
-126,
-87,
-201,
-143,
-11,
-24,
-224,
-96,
-224,
-177,
-132,
-178,
-239,
-163,
-216,
-32,
-85,
-199,
-123,
-168,
-214,
-20,
-48,
-162,
-225,
-47,
-52,
-73,
-169,
-224,
-95,
-252,
-173,
-152,
-243,
-196,
-67,
-88,
-166,
-176,
-168,
-22,
-176,
-232,
-11,
-1,
-254,
-210,
-66,
-127,
-59,
-234,
-210,
-69,
-49,
-143,
-230,
-251,
-129,
-51,
-19,
-202,
-126,
-130,
-72,
-184,
-152,
-223,
-75,
-246,
-30,
-154,
-171,
-224,
-47,
-180,
-43,
-165,
-66,
-141,
-118,
-218,
-22,
-2,
-103,
-98,
-185,
-120,
-78,
-166,
-98,
-83,
-73,
-44,
-5,
-206,
-125,
-192,
-199,
-11,
-238,
-39,
-123,
-15,
-205,
-85,
-240,
-23,
-185,
-109,
-230,
-188,
-182,
-68,
-89,
-163,
-157,
-182,
-20,
-65,
-117,
-219,
-158,
-199,
-71,
-182,
-223,
-80,
-224,
-146,
-69,
-13,
-239,
-161,
-134,
-125,
-56,
-44,
-50,
-26,
-198,
-18,
-85,
-64,
-66,
-192,
-7,
-240,
-59,
-76,
-86,
-153,
-138,
-9,
-184,
-93,
-233,
-1,
-94,
-173,
-83,
-184,
-9,
-90,
-10,
-53,
-175,
-13,
-76,
-192,
-253,
-129,
-164,
-197,
-101,
-123,
-239,
-148,
-189,
-168,
-94,
-10,
-113,
-75,
-73,
-186,
-66,
-82,
-214,
-219,
-169,
-82,
-110,
-41,
-66,
-8,
-97,
-182,
-3,
-42,
-240,
-99,
-21,
-107,
-12,
-163,
-152,
-123,
-226,
-207,
-75,
-224,
-95,
-251,
-119,
-100,
-75,
-214,
-9,
-33,
-132,
-178,
-253,
-143,
-166,
-168,
-120,
-11,
-151,
-170,
-118,
-86,
-150,
-229,
-1,
-218,
-82,
-166,
-150,
-30,
-31,
-66,
-184,
-41,
-71,
-182,
-148,
-164,
-7,
-61,
-17,
-68,
-107,
-0,
-54,
-147,
-244,
-33,
-89,
-194,
-206,
-100,
-212,
-182,
-5,
-96,
-82,
-242,
-143,
-128,
-127,
-99,
-10,
-160,
-202,
-8,
-162,
-17,
-128,
-111,
-200,
-244,
-4,
-71,
-200,
-146,
-48,
-117,
-86,
-36,
-177,
-156,
-124,
-127,
-144,
-37,
-103,
-168,
-229,
-219,
-135,
-101,
-50,
-189,
-78,
-54,
-122,
-76,
-144,
-237,
-115,
-116,
-103,
-132,
-116,
-41,
-217,
-222,
-66,
-41,
-216,
-4,
-19,
-204,
-103,
-96,
-249,
-0,
-163,
-242,
-141,
-143,
-110,
-223,
-146,
-244,
-213,
-16,
-194,
-163,
-117,
-250,
-157,
-173,
-100,
-208,
-156,
-83,
-36,
-3,
-0,
-223,
-193,
-44,
-106,
-171,
-57,
-205,
-35,
-192,
-1,
-141,
-26,
-237,
-65,
-255,
-74,
-202,
-198,
-240,
-145,
-8,
-109,
-45,
-239,
-161,
-76,
-185,
-255,
-194,
-54,
-131,
-172,
-218,
-45,
-237,
-50,
-204,
-59,
-234,
-53,
-76,
-63,
-242,
-109,
-34,
-153,
-70,
-188,
-127,
-183,
-97,
-190,
-23,
-107,
-98,
-130,
-235,
-23,
-10,
-234,
-60,
-212,
-239,
-247,
-126,
-87,
-117,
-239,
-244,
-142,
-153,
-243,
-143,
-18,
-89,
-46,
-22,
-9,
-55,
-5,
-117,
-158,
-128,
-229,
-3,
-126,
-26,
-56,
-151,
-226,
-141,
-20,
-187,
-82,
-123,
-166,
-130,
-6,
-222,
-67,
-88,
-46,
-130,
-74,
-247,
-53,
-44,
-115,
-215,
-170,
-216,
-82,
-123,
-107,
-204,
-97,
-245,
-194,
-8,
-29,
-120,
-138,
-87,
-63,
-255,
-52,
-241,
-76,
-39,
-75,
-98,
-163,
-241,
-46,
-169,
-207,
-215,
-21,
-48,
-117,
-234,
-123,
-51,
-231,
-59,
-0,
-67,
-146,
-20,
-166,
-50,
-0,
-176,
-31,
-166,
-88,
-90,
-23,
-88,
-9,
-83,
-28,
-197,
-180,
-110,
-125,
-99,
-128,
-38,
-192,
-252,
-29,
-191,
-136,
-133,
-179,
-189,
-128,
-69,
-233,
-84,
-42,
-187,
-176,
-61,
-25,
-103,
-68,
-174,
-67,
-38,
-95,
-32,
-166,
-188,
-26,
-34,
-164,
-99,
-35,
-114,
-105,
-6,
-210,
-50,
-52,
-241,
-7,
-184,
-94,
-210,
-17,
-62,
-52,
-190,
-93,
-182,
-251,
-103,
-179,
-128,
-68,
-195,
-17,
-146,
-190,
-22,
-66,
-184,
-43,
-132,
-240,
-136,
-76,
-151,
-191,
-103,
-23,
-245,
-13,
-23,
-22,
-146,
-180,
-181,
-164,
-221,
-36,
-173,
-40,
-233,
-101,
-153,
-141,
-164,
-10,
-243,
-73,
-122,
-170,
-224,
-222,
-152,
-220,
-113,
-140,
-225,
-63,
-42,
-105,
-51,
-6,
-150,
-130,
-83,
-233,
-165,
-91,
-186,
-127,
-165,
-87,
-98,
-246,
-128,
-59,
-157,
-235,
-159,
-137,
-208,
-165,
-142,
-0,
-207,
-50,
-20,
-67,
-76,
-208,
-145,
-17,
-96,
-251,
-17,
-54,
-2,
-188,
-64,
-38,
-0,
-22,
-83,
-31,
-199,
-70,
-198,
-227,
-125,
-180,
-91,
-26,
-139,
-198,
-190,
-15,
-56,
-37,
-66,
-7,
-158,
-103,
-216,
-207,
-143,
-161,
-7,
-251,
-25,
-204,
-230,
-48,
-76,
-175,
-125,
-134,
-255,
-32,
-79,
-99,
-33,
-221,
-135,
-228,
-11,
-132,
-16,
-30,
-9,
-33,
-236,
-24,
-66,
-88,
-40,
-132,
-176,
-158,
-164,
-87,
-148,
-186,
-45,
-89,
-113,
-31,
-246,
-209,
-96,
-207,
-151,
-216,
-136,
-242,
-146,
-6,
-123,
-187,
-172,
-17,
-171,
-44,
-195,
-68,
-179,
-48,
-19,
-244,
-55,
-72,
-8,
-49,
-111,
-1,
-119,
-201,
-190,
-252,
-14,
-22,
-146,
-121,
-232,
-228,
-241,
-30,
-217,
-40,
-58,
-85,
-210,
-121,
-146,
-126,
-36,
-41,
-154,
-233,
-91,
-210,
-145,
-152,
-0,
-184,
-150,
-164,
-195,
-212,
-75,
-63,
-2,
-224,
-63,
-157,
-27,
-215,
-198,
-50,
-91,
-19,
-99,
-128,
-72,
-185,
-137,
-192,
-137,
-145,
-235,
-169,
-35,
-192,
-45,
-120,
-112,
-101,
-5,
-221,
-13,
-152,
-6,
-111,
-25,
-76,
-58,
-159,
-28,
-27,
-1,
-188,
-221,
-78,
-124,
-225,
-38,
-152,
-106,
-247,
-231,
-17,
-186,
-113,
-88,
-166,
-243,
-206,
-30,
-192,
-151,
-18,
-217,
-159,
-55,
-50,
-58,
-81,
-208,
-238,
-129,
-152,
-13,
-97,
-75,
-108,
-133,
-116,
-3,
-240,
-157,
-170,
-231,
-42,
-121,
-94,
-128,
-207,
-96,
-246,
-141,
-151,
-177,
-125,
-7,
-122,
-23,
-118,
-134,
-5,
-54,
-30,
-229,
-199,
-215,
-96,
-214,
-176,
-91,
-34,
-116,
-243,
-99,
-238,
-226,
-75,
-98,
-142,
-35,
-83,
-137,
-108,
-221,
-86,
-131,
-1,
-246,
-194,
-156,
-80,
-62,
-4,
-172,
-136,
-229,
-5,
-216,
-45,
-66,
-247,
-78,
-103,
-182,
-87,
-48,
-139,
-229,
-174,
-37,
-12,
-144,
-141,
-45,
-56,
-0,
-152,
-22,
-161,
-187,
-25,
-11,
-169,
-30,
-135,
-229,
-71,
-250,
-5,
-112,
-107,
-132,
-110,
-213,
-220,
-223,
-215,
-40,
-112,
-148,
-193,
-150,
-130,
-79,
-97,
-82,
-249,
-15,
-169,
-200,
-253,
-95,
-6,
-127,
-142,
-118,
-114,
-255,
-36,
-54,
-56,
-29,
-147,
-52,
-183,
-193,
-252,
-214,
-118,
-45,
-120,
-113,
-27,
-97,
-107,
-216,
-255,
-197,
-162,
-124,
-242,
-251,
-237,
-118,
-232,
-146,
-24,
-192,
-105,
-63,
-130,
-133,
-99,
-205,
-116,
-134,
-250,
-84,
-23,
-207,
-145,
-103,
-128,
-168,
-137,
-24,
-155,
-179,
-179,
-50,
-197,
-150,
-84,
-24,
-191,
-48,
-91,
-194,
-20,
-122,
-104,
-43,
-200,
-180,
-149,
-204,
-0,
-152,
-60,
-52,
-209,
-71,
-138,
-169,
-36,
-140,
-168,
-177,
-74,
-166,
-97,
-67,
-231,
-141,
-152,
-37,
-240,
-3,
-68,
-156,
-43,
-106,
-212,
-7,
-67,
-163,
-91,
-74,
-211,
-184,
-180,
-129,
-76,
-187,
-139,
-49,
-32,
-100,
-157,
-29,
-161,
-251,
-33,
-240,
-107,
-204,
-58,
-184,
-16,
-230,
-49,
-84,
-234,
-41,
-12,
-236,
-141,
-41,
-137,
-122,
-174,
-66,
-175,
-201,
-0,
-79,
-98,
-250,
-152,
-69,
-177,
-216,
-198,
-241,
-77,
-26,
-252,
-7,
-22,
-230,
-220,
-217,
-135,
-230,
-104,
-224,
-239,
-181,
-43,
-26,
-168,
-47,
-134,
-82,
-151,
-237,
-54,
-144,
-105,
-107,
-38,
-230,
-171,
-112,
-10,
-241,
-173,
-89,
-231,
-199,
-194,
-179,
-158,
-197,
-134,
-236,
-243,
-168,
-222,
-0,
-234,
-22,
-224,
-179,
-45,
-244,
-177,
-213,
-157,
-202,
-188,
-190,
-243,
-233,
-38,
-132,
-14,
-248,
-148,
-191,
-184,
-253,
-49,
-65,
-240,
-1,
-224,
-208,
-110,
-59,
-215,
-111,
-248,
-51,
-164,
-200,
-30,
-187,
-251,
-151,
-179,
-157,
-63,
-251,
-179,
-148,
-7,
-107,
-116,
-146,
-47,
-44,
-217,
-66,
-31,
-239,
-200,
-48,
-192,
-237,
-45,
-212,
-55,
-30,
-115,
-209,
-159,
-142,
-109,
-47,
-91,
-223,
-153,
-5,
-203,
-171,
-251,
-15,
-127,
-17,
-211,
-128,
-47,
-85,
-125,
-17,
-253,
-4,
-22,
-45,
-124,
-154,
-247,
-237,
-25,
-34,
-137,
-161,
-157,
-46,
-149,
-1,
-38,
-147,
-209,
-239,
-99,
-94,
-66,
-49,
-227,
-77,
-231,
-254,
-111,
-40,
-217,
-129,
-12,
-203,
-104,
-50,
-209,
-153,
-228,
-206,
-70,
-195,
-112,
-67,
-120,
-123,
-7,
-249,
-135,
-123,
-11,
-240,
-219,
-126,
-53,
-12,
-53,
-247,
-186,
-43,
-168,
-99,
-8,
-34,
-116,
-7,
-99,
-235,
-250,
-119,
-97,
-110,
-107,
-79,
-1,
-187,
-23,
-212,
-151,
-194,
-0,
-47,
-98,
-38,
-212,
-206,
-249,
-86,
-68,
-20,
-55,
-126,
-111,
-21,
-159,
-82,
-10,
-179,
-112,
-249,
-87,
-253,
-77,
-204,
-135,
-240,
-43,
-64,
-212,
-220,
-235,
-253,
-107,
-85,
-165,
-141,
-9,
-180,
-59,
-249,
-241,
-102,
-244,
-58,
-56,
-6,
-56,
-28,
-19,
-174,
-240,
-161,
-39,
-105,
-79,
-191,
-130,
-186,
-242,
-14,
-149,
-151,
-17,
-9,
-156,
-196,
-150,
-166,
-95,
-204,
-156,
-159,
-76,
-68,
-7,
-94,
-131,
-1,
-174,
-196,
-214,
-254,
-227,
-176,
-117,
-251,
-31,
-129,
-95,
-23,
-208,
-126,
-11,
-184,
-170,
-162,
-190,
-89,
-157,
-175,
-30,
-19,
-66,
-135,
-232,
-247,
-51,
-253,
-171,
-197,
-0,
-20,
-120,
-92,
-103,
-238,
-159,
-238,
-31,
-196,
-193,
-192,
-73,
-192,
-53,
-101,
-244,
-93,
-193,
-27,
-121,
-209,
-135,
-156,
-21,
-176,
-124,
-193,
-155,
-69,
-232,
-222,
-135,
-101,
-5,
-123,
-17,
-27,
-182,
-47,
-7,
-86,
-175,
-168,
-123,
-107,
-108,
-41,
-51,
-54,
-114,
-111,
-42,
-153,
-204,
-223,
-152,
-222,
-160,
-177,
-39,
-141,
-247,
-253,
-82,
-6,
-166,
-148,
-11,
-137,
-236,
-78,
-234,
-95,
-244,
-139,
-84,
-88,
-219,
-178,
-63,
-44,
-230,
-36,
-251,
-199,
-42,
-58,
-63,
-239,
-154,
-1,
-156,
-102,
-87,
-76,
-249,
-4,
-137,
-249,
-144,
-26,
-1,
-83,
-194,
-156,
-154,
-64,
-247,
-117,
-224,
-8,
-76,
-149,
-185,
-10,
-54,
-135,
-22,
-174,
-42,
-48,
-85,
-244,
-109,
-192,
-87,
-10,
-238,
-191,
-204,
-96,
-159,
-197,
-109,
-129,
-215,
-154,
-61,
-69,
-79,
-60,
-184,
-94,
-0,
-0,
-18,
-40,
-73,
-68,
-65,
-84,
-251,
-200,
-49,
-192,
-115,
-192,
-7,
-170,
-232,
-252,
-188,
-200,
-239,
-98,
-69,
-76,
-178,
-159,
-226,
-101,
-30,
-163,
-64,
-238,
-201,
-149,
-251,
-36,
-53,
-118,
-111,
-205,
-218,
-2,
-82,
-57,
-115,
-13,
-73,
-149,
-203,
-195,
-16,
-194,
-81,
-33,
-132,
-111,
-134,
-16,
-38,
-133,
-16,
-30,
-144,
-237,
-23,
-92,
-54,
-2,
-252,
-135,
-108,
-31,
-194,
-175,
-22,
-220,
-207,
-247,
-101,
-94,
-73,
-175,
-87,
-245,
-99,
-152,
-48,
-70,
-233,
-190,
-121,
-69,
-116,
-157,
-60,
-74,
-239,
-147,
-244,
-188,
-164,
-93,
-36,
-253,
-45,
-79,
-132,
-173,
-253,
-247,
-195,
-54,
-201,
-88,
-92,
-182,
-181,
-221,
-16,
-5,
-94,
-17,
-154,
-40,
-52,
-130,
-226,
-102,
-201,
-40,
-48,
-231,
-142,
-119,
-201,
-12,
-30,
-81,
-243,
-40,
-230,
-17,
-115,
-138,
-164,
-207,
-135,
-16,
-138,
-180,
-113,
-79,
-203,
-28,
-58,
-59,
-88,
-212,
-175,
-141,
-68,
-156,
-45,
-233,
-187,
-192,
-191,
-66,
-8,
-249,
-101,
-94,
-146,
-81,
-75,
-182,
-41,
-247,
-255,
-132,
-16,
-238,
-4,
-8,
-33,
-220,
-86,
-210,
-222,
-161,
-50,
-195,
-82,
-144,
-52,
-81,
-210,
-190,
-181,
-123,
-92,
-99,
-104,
-186,
-139,
-136,
-249,
-178,
-164,
-78,
-48,
-1,
-233,
-28,
-10,
-220,
-165,
-176,
-181,
-235,
-109,
-148,
-44,
-59,
-49,
-161,
-237,
-212,
-204,
-249,
-233,
-84,
-11,
-102,
-125,
-219,
-166,
-62,
-55,
-5,
-4,
-151,
-47,
-254,
-26,
-161,
-75,
-53,
-106,
-77,
-192,
-220,
-237,
-30,
-197,
-150,
-150,
-221,
-229,
-1,
-174,
-243,
-0,
-126,
-94,
-196,
-0,
-31,
-193,
-92,
-164,
-14,
-192,
-92,
-167,
-86,
-195,
-118,
-167,
-140,
-213,
-185,
-152,
-207,
-101,
-31,
-196,
-116,
-253,
-223,
-143,
-208,
-140,
-245,
-249,
-189,
-116,
-183,
-76,
-204,
-104,
-244,
-12,
-166,
-60,
-121,
-47,
-166,
-175,
-56,
-168,
-162,
-204,
-21,
-88,
-58,
-150,
-40,
-99,
-81,
-99,
-107,
-122,
-42,
-182,
-164,
-143,
-188,
-191,
-9,
-192,
-16,
-239,
-99,
-18,
-141,
-90,
-78,
-59,
-47,
-102,
-163,
-152,
-137,
-41,
-121,
-26,
-219,
-72,
-42,
-17,
-121,
-128,
-66,
-135,
-11,
-44,
-140,
-60,
-187,
-12,
-188,
-60,
-70,
-151,
-43,
-179,
-47,
-145,
-120,
-60,
-44,
-173,
-203,
-101,
-164,
-133,
-87,
-127,
-145,
-1,
-69,
-213,
-233,
-116,
-153,
-24,
-153,
-196,
-173,
-233,
-73,
-216,
-146,
-62,
-55,
-2,
-108,
-134,
-105,
-23,
-155,
-121,
-232,
-14,
-173,
-251,
-57,
-10,
-140,
-115,
-173,
-193,
-31,
-32,
-235,
-236,
-121,
-120,
-17,
-3,
-228,
-202,
-36,
-41,
-130,
-176,
-244,
-48,
-49,
-171,
-92,
-20,
-245,
-159,
-96,
-80,
-157,
-149,
-78,
-166,
-109,
-35,
-199,
-0,
-19,
-177,
-81,
-114,
-136,
-215,
-113,
-141,
-250,
-254,
-11,
-27,
-233,
-222,
-234,
-117,
-157,
-69,
-36,
-99,
-121,
-107,
-240,
-7,
-200,
-206,
-77,
-15,
-116,
-243,
-67,
-248,
-215,
-250,
-78,
-44,
-213,
-250,
-54,
-36,
-6,
-110,
-118,
-11,
-18,
-157,
-76,
-157,
-54,
-197,
-27,
-121,
-127,
-76,
-203,
-247,
-146,
-255,
-47,
-220,
-168,
-185,
-77,
-96,
-166,
-246,
-71,
-49,
-211,
-251,
-27,
-254,
-28,
-27,
-20,
-208,
-110,
-129,
-5,
-235,
-118,
-204,
-193,
-73,
-50,
-90,
-190,
-18,
-48,
-109,
-219,
-11,
-192,
-189,
-152,
-121,
-177,
-27,
-6,
-184,
-16,
-211,
-78,
-189,
-234,
-204,
-244,
-101,
-250,
-16,
-54,
-141,
-237,
-154,
-113,
-72,
-230,
-124,
-15,
-224,
-225,
-8,
-93,
-170,
-55,
-242,
-54,
-152,
-60,
-180,
-4,
-182,
-81,
-228,
-255,
-244,
-250,
-25,
-34,
-125,
-168,
-210,
-4,
-62,
-132,
-237,
-243,
-180,
-24,
-150,
-225,
-116,
-124,
-147,
-70,
-160,
-124,
-111,
-251,
-57,
-2,
-164,
-59,
-153,
-38,
-49,
-74,
-174,
-204,
-22,
-68,
-92,
-179,
-107,
-246,
-47,
-41,
-9,
-86,
-174,
-76,
-21,
-3,
-60,
-5,
-28,
-219,
-77,
-191,
-134,
-8,
-129,
-35,
-21,
-84,
-44,
-237,
-48,
-129,
-105,
-111,
-42,
-132,
-202,
-26,
-140,
-50,
-214,
-135,
-227,
-39,
-241,
-189,
-4,
-122,
-241,
-92,
-221,
-0,
-19,
-176,
-103,
-0,
-127,
-198,
-183,
-252,
-105,
-82,
-73,
-45,
-6,
-160,
-98,
-89,
-84,
-179,
-221,
-221,
-72,
-136,
-129,
-115,
-250,
-170,
-165,
-93,
-170,
-147,
-105,
-42,
-163,
-252,
-5,
-243,
-143,
-92,
-15,
-91,
-218,
-165,
-134,
-163,
-245,
-53,
-112,
-5,
-147,
-181,
-78,
-195,
-150,
-151,
-69,
-94,
-198,
-173,
-53,
-86,
-185,
-44,
-170,
-81,
-23,
-152,
-67,
-106,
-101,
-12,
-92,
-98,
-125,
-169,
-78,
-166,
-169,
-140,
-50,
-3,
-247,
-247,
-119,
-134,
-25,
-145,
-12,
-144,
-105,
-247,
-195,
-20,
-152,
-181,
-251,
-221,
-145,
-249,
-177,
-180,
-104,
-51,
-48,
-97,
-235,
-253,
-177,
-23,
-226,
-12,
-144,
-18,
-3,
-55,
-104,
-132,
-42,
-123,
-193,
-36,
-56,
-153,
-214,
-96,
-148,
-251,
-49,
-211,
-243,
-242,
-62,
-26,
-140,
-40,
-6,
-192,
-4,
-191,
-15,
-99,
-182,
-128,
-37,
-48,
-79,
-237,
-59,
-122,
-217,
-96,
-210,
-15,
-129,
-217,
-165,
-31,
-194,
-188,
-84,
-214,
-197,
-252,
-214,
-138,
-24,
-32,
-37,
-6,
-46,
-153,
-1,
-106,
-60,
-75,
-10,
-163,
-124,
-8,
-243,
-25,
-124,
-12,
-83,
-198,
-12,
-73,
-1,
-231,
-116,
-89,
-134,
-159,
-236,
-140,
-92,
-217,
-63,
-204,
-185,
-101,
-136,
-74,
-155,
-193,
-129,
-58,
-207,
-98,
-190,
-141,
-177,
-228,
-147,
-139,
-98,
-102,
-247,
-23,
-48,
-129,
-242,
-58,
-224,
-29,
-169,
-239,
-160,
-54,
-106,
-48,
-192,
-36,
-50,
-91,
-190,
-224,
-169,
-81,
-10,
-234,
-203,
-154,
-121,
-63,
-16,
-123,
-201,
-189,
-96,
-128,
-54,
-17,
-97,
-248,
-127,
-149,
-245,
-15,
-155,
-62,
-47,
-246,
-15,
-99,
-136,
-241,
-134,
-193,
-129,
-58,
-107,
-251,
-113,
-235,
-62,
-154,
-85,
-94,
-176,
-221,
-248,
-4,
-142,
-211,
-224,
-144,
-177,
-178,
-140,
-24,
-43,
-103,
-142,
-87,
-171,
-160,
-29,
-169,
-216,
-87,
-150,
-12,
-243,
-158,
-16,
-194,
-93,
-146,
-138,
-108,
-6,
-203,
-97,
-17,
-67,
-151,
-72,
-250,
-173,
-164,
-117,
-67,
-8,
-67,
-34,
-151,
-36,
-29,
-144,
-169,
-239,
-30,
-89,
-130,
-201,
-131,
-218,
-238,
-244,
-160,
-31,
-152,
-92,
-170,
-88,
-73,
-55,
-118,
-81,
-247,
-171,
-210,
-32,
-179,
-241,
-204,
-18,
-218,
-38,
-49,
-112,
-35,
-45,
-141,
-91,
-42,
-195,
-79,
-150,
-180,
-130,
-164,
-119,
-135,
-16,
-126,
-26,
-203,
-197,
-236,
-88,
-89,
-210,
-3,
-185,
-250,
-74,
-61,
-170,
-154,
-160,
-81,
-170,
-216,
-28,
-138,
-126,
-136,
-71,
-52,
-248,
-203,
-46,
-203,
-187,
-115,
-129,
-164,
-203,
-100,
-182,
-236,
-107,
-20,
-73,
-247,
-170,
-116,
-59,
-122,
-45,
-43,
-95,
-139,
-72,
-101,
-248,
-141,
-100,
-161,
-227,
-119,
-96,
-22,
-213,
-162,
-140,
-34,
-111,
-104,
-112,
-90,
-221,
-222,
-123,
-104,
-167,
-12,
-249,
-46,
-104,
-84,
-26,
-141,
-128,
-207,
-97,
-42,
-229,
-53,
-49,
-147,
-241,
-173,
-37,
-50,
-64,
-74,
-58,
-180,
-36,
-59,
-186,
-211,
-86,
-90,
-249,
-48,
-255,
-132,
-231,
-177,
-37,
-232,
-62,
-152,
-4,
-253,
-229,
-46,
-250,
-119,
-87,
-86,
-136,
-164,
-66,
-149,
-142,
-121,
-55,
-95,
-238,
-178,
-210,
-144,
-20,
-59,
-216,
-166,
-22,
-71,
-103,
-206,
-163,
-129,
-58,
-88,
-112,
-75,
-212,
-70,
-80,
-11,
-36,
-26,
-61,
-82,
-127,
-8,
-76,
-177,
-242,
-83,
-204,
-64,
-113,
-63,
-190,
-45,
-125,
-132,
-46,
-245,
-5,
-39,
-219,
-209,
-83,
-0,
-156,
-138,
-5,
-184,
-238,
-131,
-249,
-213,
-191,
-72,
-36,
-147,
-119,
-141,
-254,
-229,
-25,
-126,
-98,
-74,
-255,
-128,
-77,
-137,
-120,
-241,
-2,
-135,
-248,
-123,
-235,
-8,
-129,
-209,
-64,
-29,
-76,
-11,
-120,
-15,
-150,
-0,
-59,
-26,
-167,
-153,
-4,
-18,
-141,
-30,
-77,
-127,
-8,
-138,
-87,
-11,
-73,
-47,
-56,
-21,
-249,
-250,
-138,
-218,
-109,
-90,
-95,
-9,
-93,
-158,
-225,
-119,
-239,
-178,
-221,
-128,
-237,
-199,
-52,
-141,
-138,
-64,
-29,
-108,
-201,
-184,
-191,
-51,
-242,
-119,
-128,
-101,
-155,
-182,
-219,
-169,
-176,
-107,
-163,
-71,
-164,
-206,
-126,
-41,
-70,
-122,
-193,
-0,
-71,
-210,
-239,
-157,
-185,
-26,
-0,
-120,
-19,
-150,
-243,
-32,
-57,
-197,
-111,
-214,
-43,
-120,
-182,
-209,
-67,
-182,
-11,
-70,
-95,
-247,
-192,
-29,
-225,
-56,
-92,
-210,
-33,
-178,
-93,
-73,
-158,
-144,
-229,
-228,
-27,
-49,
-192,
-100,
-158,
-3,
-36,
-221,
-46,
-233,
-53,
-153,
-160,
-89,
-187,
-146,
-70,
-70,
-143,
-145,
-134,
-30,
-141,
-0,
-61,
-79,
-162,
-221,
-20,
-216,
-74,
-98,
-18,
-230,
-86,
-215,
-60,
-7,
-51,
-13,
-141,
-30,
-253,
-6,
-245,
-157,
-51,
-187,
-74,
-38,
-229,
-245,
-245,
-60,
-137,
-118,
-83,
-96,
-78,
-60,
-155,
-54,
-45,
-159,
-21,
-42,
-30,
-151,
-180,
-49,
-150,
-219,
-174,
-112,
-99,
-167,
-130,
-78,
-52,
-94,
-163,
-250,
-11,
-78,
-205,
-36,
-242,
-93,
-89,
-14,
-222,
-53,
-36,
-45,
-77,
-220,
-10,
-217,
-11,
-125,
-65,
-146,
-60,
-132,
-37,
-153,
-56,
-20,
-216,
-147,
-72,
-242,
-199,
-58,
-72,
-21,
-62,
-67,
-8,
-219,
-68,
-242,
-17,
-55,
-106,
-48,
-201,
-232,
-225,
-180,
-201,
-155,
-75,
-37,
-180,
-155,
-204,
-0,
-137,
-245,
-181,
-173,
-47,
-72,
-158,
-82,
-176,
-112,
-181,
-89,
-152,
-175,
-193,
-184,
-46,
-159,
-35,
-137,
-1,
-134,
-5,
-46,
-9,
-175,
-236,
-12,
-240,
-28,
-112,
-68,
-1,
-221,
-170,
-192,
-245,
-152,
-110,
-225,
-62,
-96,
-255,
-8,
-77,
-7,
-165,
-105,
-221,
-72,
-183,
-142,
-181,
-173,
-47,
-168,
-195,
-0,
-151,
-96,
-145,
-193,
-151,
-23,
-140,
-78,
-117,
-219,
-237,
-139,
-3,
-106,
-109,
-164,
-14,
-249,
-152,
-139,
-210,
-165,
-88,
-36,
-238,
-22,
-192,
-187,
-35,
-52,
-144,
-150,
-214,
-173,
-85,
-235,
-88,
-13,
-134,
-74,
-102,
-128,
-12,
-205,
-130,
-152,
-71,
-111,
-227,
-47,
-216,
-219,
-61,
-154,
-68,
-79,
-169,
-190,
-33,
-245,
-197,
-57,
-237,
-12,
-96,
-231,
-138,
-250,
-96,
-112,
-86,
-175,
-253,
-137,
-103,
-39,
-155,
-157,
-198,
-206,
-207,
-63,
-77,
-119,
-83,
-79,
-219,
-12,
-181,
-16,
-230,
-15,
-240,
-44,
-166,
-8,
-186,
-22,
-248,
-65,
-23,
-245,
-65,
-13,
-79,
-41,
-170,
-125,
-37,
-219,
-201,
-75,
-84,
-231,
-197,
-249,
-67,
-140,
-175,
-168,
-47,
-207,
-0,
-69,
-105,
-221,
-166,
-147,
-9,
-65,
-195,
-28,
-71,
-186,
-201,
-98,
-214,
-54,
-67,
-157,
-137,
-169,
-208,
-215,
-240,
-247,
-114,
-15,
-5,
-89,
-66,
-18,
-235,
-131,
-4,
-79,
-169,
-204,
-253,
-42,
-95,
-201,
-234,
-188,
-68,
-41,
-92,
-82,
-231,
-197,
-213,
-96,
-128,
-148,
-180,
-110,
-211,
-128,
-236,
-246,
-40,
-221,
-166,
-177,
-107,
-155,
-161,
-166,
-228,
-126,
-176,
-131,
-40,
-200,
-18,
-146,
-88,
-31,
-12,
-94,
-126,
-70,
-61,
-165,
-186,
-69,
-158,
-91,
-178,
-38,
-204,
-89,
-5,
-101,
-146,
-236,
-212,
-12,
-172,
-34,
-254,
-140,
-185,
-92,
-149,
-249,
-3,
-252,
-65,
-210,
-51,
-178,
-188,
-185,
-23,
-73,
-138,
-249,
-184,
-223,
-39,
-219,
-242,
-165,
-131,
-85,
-84,
-226,
-56,
-82,
-53,
-36,
-170,
-125,
-115,
-235,
-91,
-101,
-90,
-194,
-14,
-158,
-145,
-45,
-73,
-219,
-66,
-52,
-91,
-56,
-9,
-70,
-188,
-50,
-154,
-65,
-15,
-29,
-66,
-88,
-63,
-132,
-112,
-91,
-8,
-97,
-98,
-8,
-161,
-200,
-175,
-44,
-233,
-197,
-133,
-16,
-58,
-46,
-214,
-219,
-134,
-16,
-230,
-13,
-33,
-148,
-229,
-34,
-216,
-222,
-105,
-198,
-133,
-16,
-78,
-8,
-33,
-196,
-50,
-127,
-156,
-39,
-233,
-176,
-206,
-212,
-35,
-233,
-147,
-178,
-77,
-160,
-138,
-112,
-129,
-164,
-159,
-73,
-42,
-218,
-233,
-35,
-153,
-161,
-18,
-231,
-207,
-71,
-37,
-45,
-151,
-57,
-31,
-39,
-115,
-254,
-232,
-6,
-41,
-158,
-82,
-79,
-200,
-156,
-104,
-86,
-148,
-169,
-240,
-99,
-106,
-234,
-20,
-26,
-137,
-180,
-88,
-185,
-84,
-59,
-245,
-252,
-62,
-140,
-149,
-234,
-165,
-243,
-50,
-64,
-9,
-93,
-178,
-117,
-44,
-5,
-36,
-154,
-91,
-157,
-182,
-114,
-254,
-4,
-190,
-128,
-173,
-96,
-58,
-66,
-219,
-100,
-42,
-194,
-215,
-43,
-250,
-135,
-183,
-187,
-38,
-176,
-22,
-240,
-32,
-240,
-153,
-138,
-50,
-149,
-70,
-188,
-66,
-26,
-210,
-99,
-229,
-82,
-237,
-212,
-251,
-49,
-32,
-20,
-205,
-78,
-182,
-156,
-240,
-236,
-93,
-129,
-244,
-229,
-93,
-219,
-12,
-53,
-63,
-38,
-8,
-62,
-225,
-245,
-157,
-22,
-107,
-183,
-70,
-125,
-175,
-99,
-91,
-249,
-150,
-102,
-11,
-39,
-33,
-114,
-41,
-133,
-70,
-164,
-7,
-85,
-38,
-189,
-56,
-10,
-208,
-232,
-109,
-212,
-0,
-195,
-164,
-47,
-24,
-46,
-144,
-96,
-196,
-75,
-161,
-17,
-137,
-177,
-114,
-35,
-29,
-140,
-112,
-125,
-65,
-219,
-32,
-193,
-136,
-87,
-70,
-147,
-223,
-147,
-38,
-101,
-231,
-142,
-145,
-142,
-182,
-189,
-105,
-251,
-226,
-158,
-221,
-5,
-82,
-140,
-120,
-213,
-52,
-36,
-198,
-202,
-245,
-27,
-62,
-4,
-127,
-25,
-91,
-103,
-191,
-72,
-197,
-14,
-89,
-140,
-112,
-125,
-65,
-219,
-32,
-193,
-136,
-151,
-66,
-35,
-18,
-99,
-229,
-250,
-13,
-224,
-40,
-108,
-101,
-50,
-1,
-75,
-56,
-89,
-149,
-76,
-42,
-105,
-149,
-82,
-163,
-253,
-70,
-12,
-69,
-130,
-169,
-25,
-115,
-72,
-189,
-39,
-161,
-174,
-9,
-254,
-129,
-150,
-230,
-17,
-232,
-26,
-212,
-216,
-185,
-131,
-132,
-240,
-112,
-224,
-91,
-153,
-227,
-111,
-84,
-220,
-31,
-162,
-253,
-243,
-235,
-183,
-147,
-176,
-33,
-99,
-134,
-62,
-121,
-121,
-151,
-88,
-95,
-35,
-134,
-34,
-205,
-212,
-188,
-31,
-80,
-169,
-43,
-192,
-18,
-64,
-156,
-76,
-127,
-54,
-191,
-170,
-6,
-105,
-89,
-179,
-182,
-0,
-206,
-247,
-227,
-205,
-128,
-239,
-69,
-104,
-190,
-207,
-64,
-98,
-165,
-243,
-137,
-120,
-182,
-96,
-75,
-160,
-104,
-218,
-213,
-130,
-190,
-13,
-155,
-190,
-160,
-87,
-240,
-15,
-109,
-124,
-63,
-219,
-236,
-26,
-152,
-143,
-218,
-134,
-249,
-227,
-28,
-205,
-134,
-157,
-57,
-221,
-143,
-127,
-31,
-161,
-121,
-53,
-59,
-4,
-247,
-27,
-77,
-24,
-138,
-244,
-24,
-139,
-13,
-128,
-202,
-116,
-183,
-206,
-0,
-133,
-155,
-89,
-116,
-131,
-70,
-95,
-6,
-105,
-105,
-216,
-230,
-41,
-56,
-46,
-163,
-139,
-169,
-139,
-31,
-80,
-205,
-45,
-209,
-219,
-68,
-8,
-129,
-16,
-194,
-151,
-66,
-8,
-139,
-251,
-223,
-137,
-37,
-241,
-124,
-29,
-164,
-169,
-94,
-165,
-93,
-53,
-120,
-197,
-50,
-8,
-152,
-95,
-193,
-129,
-50,
-27,
-77,
-105,
-254,
-162,
-146,
-58,
-90,
-221,
-158,
-166,
-142,
-198,
-112,
-171,
-204,
-20,
-48,
-123,
-58,
-200,
-209,
-124,
-31,
-216,
-210,
-143,
-207,
-39,
-226,
-64,
-129,
-69,
-20,
-61,
-142,
-185,
-91,
-173,
-74,
-65,
-86,
-210,
-145,
-10,
-10,
-84,
-175,
-192,
-58,
-152,
-215,
-210,
-129,
-37,
-101,
-193,
-164,
-247,
-198,
-35,
-32,
-169,
-219,
-211,
-144,
-184,
-220,
-162,
-70,
-118,
-45,
-50,
-187,
-112,
-17,
-17,
-22,
-169,
-16,
-18,
-253,
-250,
-60,
-152,
-38,
-110,
-42,
-166,
-208,
-24,
-178,
-153,
-196,
-72,
-3,
-105,
-234,
-217,
-75,
-171,
-158,
-5,
-179,
-104,
-30,
-139,
-41,
-233,
-150,
-232,
-93,
-143,
-149,
-190,
-220,
-98,
-4,
-106,
-12,
-201,
-8,
-138,
-20,
-8,
-141,
-62,
-143,
-79,
-194,
-86,
-57,
-189,
-203,
-185,
-171,
-100,
-245,
-236,
-244,
-148,
-121,
-29,
-203,
-23,
-12,
-176,
-69,
-131,
-126,
-108,
-130,
-173,
-253,
-241,
-81,
-180,
-216,
-199,
-144,
-196,
-229,
-22,
-137,
-217,
-181,
-250,
-9,
-127,
-200,
-45,
-242,
-199,
-57,
-154,
-77,
-129,
-5,
-48,
-199,
-147,
-194,
-36,
-74,
-88,
-142,
-223,
-117,
-75,
-238,
-167,
-216,
-223,
-83,
-212,
-179,
-47,
-146,
-152,
-151,
-209,
-127,
-192,
-241,
-41,
-180,
-145,
-178,
-99,
-189,
-124,
-212,
-16,
-151,
-21,
-2,
-87,
-151,
-84,
-232,
-114,
-148,
-193,
-100,
-89,
-86,
-139,
-87,
-178,
-127,
-77,
-58,
-215,
-34,
-158,
-245,
-191,
-252,
-241,
-108,
-132,
-16,
-110,
-10,
-33,
-188,
-44,
-105,
-99,
-21,
-36,
-190,
-192,
-172,
-109,
-71,
-75,
-90,
-172,
-164,
-173,
-20,
-1,
-47,
-69,
-61,
-123,
-147,
-164,
-99,
-48,
-185,
-102,
-107,
-224,
-240,
-146,
-54,
-123,
-15,
-18,
-151,
-91,
-140,
-64,
-141,
-33,
-150,
-24,
-105,
-217,
-252,
-113,
-132,
-110,
-83,
-204,
-89,
-51,
-186,
-247,
-31,
-3,
-123,
-238,
-60,
-133,
-201,
-28,
-165,
-31,
-4,
-197,
-2,
-94,
-138,
-122,
-118,
-101,
-44,
-170,
-231,
-37,
-76,
-183,
-80,
-168,
-134,
-247,
-169,
-235,
-44,
-26,
-200,
-1,
-85,
-35,
-64,
-150,
-240,
-30,
-224,
-184,
-196,
-74,
-187,
-218,
-235,
-151,
-8,
-34,
-52,
-233,
-243,
-87,
-90,
-155,
-219,
-96,
-49,
-244,
-11,
-39,
-244,
-173,
-208,
-157,
-155,
-97,
-200,
-28,
-138,
-233,
-11,
-254,
-66,
-131,
-152,
-196,
-58,
-12,
-208,
-183,
-229,
-150,
-119,
-104,
-208,
-190,
-194,
-5,
-116,
-105,
-157,
-79,
-107,
-243,
-101,
-204,
-148,
-59,
-201,
-255,
-162,
-158,
-74,
-9,
-12,
-80,
-41,
-224,
-141,
-36,
-84,
-189,
-195,
-172,
-226,
-229,
-44,
-153,
-99,
-227,
-143,
-37,
-45,
-33,
-233,
-247,
-254,
-215,
-43,
-188,
-222,
-79,
-217,
-33,
-132,
-208,
-86,
-82,
-169,
-141,
-36,
-237,
-229,
-123,
-249,
-172,
-221,
-82,
-157,
-195,
-134,
-217,
-66,
-96,
-8,
-97,
-86,
-8,
-225,
-216,
-16,
-194,
-10,
-178,
-132,
-77,
-61,
-223,
-233,
-123,
-14,
-69,
-227,
-32,
-218,
-57,
-6,
-192,
-210,
-68,
-182,
-119,
-105,
-177,
-254,
-74,
-25,
-192,
-233,
-42,
-167,
-0,
-90,
-206,
-8,
-134,
-109,
-206,
-176,
-101,
-201,
-253,
-228,
-32,
-218,
-132,
-182,
-160,
-197,
-192,
-216,
-130,
-54,
-234,
-77,
-163,
-192,
-95,
-49,
-19,
-232,
-39,
-11,
-238,
-39,
-101,
-9,
-199,
-76,
-161,
-215,
-3,
-167,
-71,
-238,
-181,
-38,
-3,
-144,
-184,
-239,
-79,
-42,
-48,
-111,
-222,
-51,
-129,
-69,
-128,
-229,
-170,
-75,
-116,
-213,
-86,
-33,
-3,
-84,
-49,
-54,
-166,
-71,
-184,
-25,
-216,
-190,
-164,
-254,
-77,
-48,
-33,
-29,
-103,
-216,
-238,
-130,
-77,
-169,
-145,
-37,
-28,
-183,
-153,
-3,
-255,
-136,
-220,
-75,
-226,
-252,
-218,
-220,
-91,
-94,
-87,
-210,
-22,
-114,
-152,
-13,
-99,
-18,
-230,
-149,
-219,
-120,
-107,
-218,
-196,
-62,
-149,
-49,
-64,
-41,
-99,
-99,
-91,
-218,
-126,
-25,
-75,
-233,
-51,
-242,
-224,
-35,
-197,
-117,
-196,
-13,
-69,
-173,
-48,
-0,
-17,
-148,
-212,
-85,
-26,
-59,
-55,
-28,
-72,
-125,
-15,
-37,
-229,
-199,
-151,
-61,
-115,
-207,
-224,
-29,
-239,
-54,
-244,
-185,
-235,
-41,
-32,
-181,
-158,
-145,
-138,
-34,
-6,
-32,
-81,
-7,
-50,
-34,
-25,
-128,
-52,
-93,
-121,
-229,
-151,
-75,
-194,
-252,
-149,
-242,
-5,
-213,
-25,
-37,
-218,
-0,
-53,
-236,
-239,
-101,
-253,
-175,
-98,
-254,
-12,
-205,
-235,
-192,
-129,
-64,
-163,
-101,
-110,
-62,
-89,
-244,
-78,
-88,
-182,
-203,
-87,
-129,
-235,
-155,
-84,
-168,
-4,
-93,
-121,
-136,
-32,
-66,
-115,
-115,
-8,
-97,
-5,
-191,
-189,
-124,
-8,
-97,
-200,
-198,
-201,
-53,
-176,
-179,
-6,
-187,
-187,
-247,
-18,
-41,
-1,
-182,
-173,
-32,
-132,
-48,
-69,
-210,
-30,
-50,
-29,
-78,
-101,
-36,
-114,
-229,
-71,
-128,
-237,
-85,
-123,
-18,
-182,
-9,
-65,
-97,
-182,
-201,
-178,
-17,
-32,
-71,
-215,
-122,
-194,
-201,
-72,
-63,
-170,
-70,
-146,
-202,
-81,
-194,
-233,
-170,
-178,
-143,
-125,
-17,
-91,
-33,
-188,
-132,
-173,
-148,
-186,
-86,
-2,
-181,
-48,
-2,
-44,
-129,
-153,
-231,
-143,
-37,
-109,
-251,
-219,
-78,
-220,
-226,
-154,
-157,
-107,
-121,
-129,
-104,
-5,
-73,
-215,
-132,
-16,
-166,
-135,
-16,
-158,
-80,
-3,
-208,
-255,
-132,
-147,
-93,
-127,
-221,
-164,
-101,
-31,
-123,
-70,
-22,
-145,
-252,
-14,
-89,
-100,
-241,
-144,
-200,
-228,
-126,
-79,
-55,
-146,
-214,
-145,
-237,
-168,
-126,
-86,
-8,
-225,
-153,
-42,
-226,
-16,
-194,
-164,
-206,
-223,
-144,
-155,
-88,
-98,
-35,
-112,
-75,
-88,
-89,
-69,
-101,
-35,
-0,
-125,
-212,
-149,
-167,
-124,
-221,
-189,
-248,
-81,
-48,
-7,
-214,
-162,
-93,
-77,
-146,
-133,
-210,
-22,
-70,
-128,
-174,
-133,
-192,
-172,
-42,
-120,
-23,
-63,
-220,
-221,
-213,
-193,
-77,
-177,
-145,
-164,
-175,
-135,
-16,
-238,
-84,
-129,
-93,
-29,
-248,
-33,
-112,
-35,
-22,
-199,
-119,
-66,
-228,
-254,
-246,
-126,
-255,
-111,
-180,
-227,
-14,
-93,
-58,
-74,
-52,
-96,
-146,
-247,
-72,
-122,
-168,
-224,
-222,
-235,
-41,
-126,
-18,
-12,
-56,
-210,
-118,
-19,
-101,
-212,
-110,
-144,
-106,
-217,
-151,
-157,
-74,
-71,
-194,
-46,
-91,
-192,
-124,
-254,
-127,
-94,
-226,
-249,
-128,
-110,
-195,
-20,
-29,
-75,
-2,
-255,
-172,
-232,
-71,
-233,
-23,
-87,
-99,
-148,
-72,
-250,
-114,
-125,
-100,
-123,
-30,
-216,
-175,
-97,
-91,
-203,
-96,
-94,
-73,
-39,
-97,
-171,
-155,
-104,
-230,
-175,
-170,
-17,
-0,
-155,
-255,
-191,
-65,
-133,
-207,
-66,
-45,
-164,
-50,
-64,
-69,
-29,
-41,
-206,
-16,
-159,
-192,
-66,
-157,
-174,
-35,
-238,
-80,
-49,
-37,
-118,
-92,
-208,
-223,
-210,
-47,
-183,
-6,
-3,
-164,
-102,
-43,
-189,
-25,
-248,
-97,
-23,
-253,
-153,
-142,
-169,
-113,
-175,
-39,
-18,
-43,
-145,
-161,
-171,
-98,
-128,
-23,
-48,
-231,
-150,
-230,
-249,
-129,
-11,
-30,
-160,
-231,
-217,
-41,
-49,
-149,
-236,
-155,
-253,
-75,
-24,
-178,
-124,
-193,
-166,
-134,
-37,
-48,
-245,
-237,
-109,
-93,
-182,
-85,
-249,
-117,
-215,
-100,
-128,
-153,
-148,
-251,
-18,
-116,
-173,
-152,
-162,
-109,
-29,
-126,
-141,
-134,
-251,
-197,
-0,
-231,
-96,
-6,
-167,
-223,
-19,
-223,
-36,
-114,
-107,
-76,
-6,
-184,
-145,
-76,
-166,
-172,
-134,
-109,
-165,
-142,
-18,
-165,
-52,
-53,
-218,
-234,
-169,
-117,
-175,
-167,
-232,
-23,
-3,
-140,
-52,
-212,
-249,
-114,
-49,
-69,
-217,
-222,
-37,
-245,
-204,
-81,
-12,
-208,
-52,
-52,
-44,
-201,
-178,
-54,
-135,
-33,
-73,
-122,
-87,
-181,
-228,
-61,
-95,
-183,
-83,
-192,
-136,
-7,
-213,
-89,
-41,
-91,
-217,
-89,
-188,
-162,
-15,
-251,
-249,
-124,
-220,
-181,
-16,
-212,
-214,
-151,
-91,
-103,
-42,
-1,
-62,
-6,
-252,
-185,
-219,
-54,
-11,
-234,
-190,
-24,
-184,
-164,
-23,
-117,
-167,
-52,
-222,
-218,
-206,
-226,
-37,
-109,
-28,
-136,
-45,
-55,
-95,
-109,
-145,
-1,
-250,
-102,
-85,
-196,
-18,
-99,
-79,
-163,
-100,
-163,
-7,
-239,
-199,
-195,
-192,
-123,
-234,
-220,
-243,
-251,
-189,
-241,
-232,
-162,
-69,
-87,
-109,
-74,
-60,
-94,
-170,
-166,
-24,
-103,
-176,
-85,
-48,
-75,
-216,
-16,
-6,
-192,
-118,
-61,
-123,
-8,
-243,
-2,
-62,
-51,
-161,
-47,
-201,
-95,
-110,
-27,
-240,
-175,
-191,
-52,
-49,
-68,
-83,
-6,
-160,
-194,
-163,
-171,
-107,
-80,
-189,
-62,
-77,
-181,
-101,
-23,
-122,
-188,
-144,
-232,
-188,
-225,
-109,
-196,
-24,
-96,
-77,
-175,
-127,
-93,
-224,
-209,
-212,
-103,
-235,
-23,
-176,
-192,
-208,
-115,
-170,
-41,
-251,
-136,
-178,
-47,
-50,
-71,
-151,
-106,
-167,
-46,
-165,
-105,
-3,
-69,
-12,
-224,
-247,
-174,
-195,
-242,
-23,
-124,
-164,
-151,
-125,
-104,
-2,
-204,
-234,
-250,
-209,
-4,
-58,
-40,
-214,
-184,
-22,
-222,
-171,
-131,
-236,
-23,
-118,
-128,
-164,
-159,
-43,
-109,
-227,
-230,
-86,
-80,
-244,
-16,
-109,
-60,
-92,
-8,
-97,
-43,
-73,
-235,
-75,
-58,
-173,
-155,
-122,
-98,
-160,
-194,
-233,
-195,
-251,
-191,
-62,
-166,
-210,
-126,
-58,
-82,
-197,
-210,
-50,
-235,
-226,
-176,
-99,
-118,
-96,
-72,
-8,
-97,
-150,
-164,
-163,
-74,
-104,
-231,
-24,
-0,
-43,
-134,
-16,
-30,
-149,
-25,
-163,
-26,
-167,
-108,
-47,
-65,
-138,
-211,
-199,
-143,
-37,
-157,
-44,
-41,
-230,
-21,
-20,
-100,
-73,
-183,
-135,
-29,
-35,
-198,
-65,
-178,
-101,
-252,
-10,
-184,
-79,
-210,
-197,
-138,
-4,
-111,
-96,
-18,
-255,
-195,
-46,
-40,
-78,
-136,
-220,
-47,
-253,
-194,
-19,
-179,
-170,
-255,
-44,
-132,
-240,
-235,
-16,
-66,
-76,
-216,
-251,
-183,
-164,
-158,
-239,
-108,
-78,
-66,
-130,
-173,
-178,
-20,
-238,
-115,
-44,
-66,
-8,
-27,
-87,
-144,
-156,
-39,
-105,
-127,
-73,
-79,
-75,
-186,
-66,
-150,
-218,
-61,
-139,
-54,
-220,
-186,
-162,
-123,
-47,
-59,
-110,
-147,
-57,
-150,
-244,
-26,
-209,
-80,
-249,
-44,
-230,
-74,
-6,
-72,
-192,
-24,
-217,
-143,
-60,
-83,
-17,
-205,
-94,
-8,
-33,
-187,
-55,
-112,
-211,
-31,
-170,
-76,
-155,
-120,
-165,
-164,
-126,
-164,
-154,
-171,
-100,
-128,
-236,
-222,
-193,
-147,
-128,
-189,
-122,
-222,
-165,
-22,
-225,
-14,
-163,
-77,
-172,
-133,
-31,
-151,
-244,
-11,
-73,
-87,
-169,
-32,
-190,
-175,
-45,
-41,
-187,
-0,
-23,
-72,
-90,
-145,
-18,
-115,
-112,
-75,
-72,
-103,
-0,
-89,
-186,
-182,
-170,
-117,
-247,
-38,
-146,
-110,
-240,
-211,
-235,
-138,
-214,
-248,
-35,
-29,
-33,
-132,
-203,
-67,
-8,
-111,
-247,
-29,
-74,
-174,
-168,
-91,
-30,
-184,
-149,
-72,
-196,
-83,
-141,
-246,
-159,
-147,
-116,
-156,
-164,
-83,
-154,
-214,
-145,
-216,
-206,
-86,
-77,
-125,
-59,
-27,
-131,
-26,
-182,
-236,
-94,
-46,
-3,
-187,
-69,
-197,
-26,
-124,
-34,
-112,
-107,
-147,
-178,
-13,
-250,
-176,
-89,
-183,
-245,
-164,
-54,
-54,
-29,
-88,
-186,
-47,
-141,
-205,
-1,
-24,
-78,
-38,
-196,
-92,
-225,
-198,
-99,
-187,
-169,
-22,
-186,
-231,
-183,
-129,
-172,
-16,
-56,
-70,
-115,
-192,
-254,
-0,
-48,
-160,
-167,
-207,
-7,
-148,
-0,
-127,
-146,
-116,
-73,
-8,
-225,
-59,
-125,
-239,
-88,
-187,
-120,
-80,
-210,
-235,
-146,
-142,
-239,
-219,
-16,
-142,
-5,
-60,
-12,
-91,
-74,
-214,
-84,
-96,
-134,
-144,
-29,
-178,
-140,
-144,
-185,
-183,
-9,
-102,
-101,
-91,
-40,
-114,
-111,
-54,
-18,
-219,
-25,
-246,
-105,
-168,
-31,
-200,
-239,
-24,
-18,
-29,
-1,
-24,
-65,
-14,
-32,
-238,
-172,
-17,
-219,
-86,
-78,
-33,
-132,
-155,
-37,
-61,
-37,
-105,
-136,
-199,
-174,
-99,
-130,
-122,
-31,
-26,
-150,
-12,
-103,
-178,
-174,
-77,
-207,
-221,
-48,
-107,
-18,
-3,
-168,
-100,
-15,
-190,
-178,
-47,
-203,
-231,
-178,
-31,
-3,
-209,
-31,
-172,
-71,
-248,
-179,
-236,
-135,
-142,
-225,
-181,
-94,
-230,
-37,
-42,
-250,
-65,
-49,
-155,
-192,
-196,
-94,
-181,
-219,
-13,
-146,
-100,
-128,
-16,
-194,
-78,
-37,
-117,
-148,
-77,
-27,
-231,
-200,
-18,
-77,
-237,
-89,
-191,
-107,
-141,
-113,
-155,
-164,
-227,
-187,
-173,
-36,
-22,
-176,
-218,
-5,
-222,
-144,
-134,
-238,
-250,
-57,
-18,
-208,
-181,
-16,
-24,
-141,
-51,
-27,
-184,
-183,
-143,
-36,
-1,
-63,
-174,
-223,
-181,
-198,
-120,
-70,
-150,
-237,
-108,
-196,
-32,
-132,
-240,
-238,
-58,
-244,
-190,
-196,
-36,
-132,
-176,
-97,
-238,
-250,
-169,
-146,
-246,
-13,
-33,
-188,
-189,
-173,
-190,
-205,
-113,
-171,
-128,
-4,
-228,
-183,
-182,
-157,
-19,
-81,
-212,
-255,
-117,
-36,
-253,
-178,
-205,
-134,
-178,
-230,
-224,
-57,
-253,
-165,
-117,
-176,
-148,
-70,
-136,
-173,
-189,
-10,
-69,
-239,
-188,
-100,
-196,
-120,
-151,
-164,
-99,
-218,
-236,
-195,
-220,
-104,
-14,
-126,
-135,
-76,
-14,
-72,
-134,
-11,
-111,
-255,
-47,
-114,
-125,
-68,
-9,
-111,
-158,
-48,
-163,
-219,
-13,
-169,
-7,
-161,
-47,
-12,
-80,
-177,
-115,
-120,
-219,
-216,
-70,
-102,
-228,
-169,
-131,
-55,
-36,
-197,
-182,
-100,
-107,
-69,
-120,
-115,
-219,
-65,
-97,
-144,
-235,
-112,
-98,
-142,
-51,
-7,
-251,
-50,
-43,
-154,
-116,
-194,
-173,
-107,
-43,
-202,
-150,
-173,
-117,
-240,
-134,
-164,
-151,
-242,
-23,
-235,
-10,
-111,
-37,
-24,
-177,
-211,
-235,
-28,
-199,
-0,
-146,
-94,
-46,
-185,
-247,
-37,
-73,
-159,
-117,
-107,
-91,
-12,
-111,
-2,
-222,
-28,
-209,
-5,
-204,
-82,
-124,
-4,
-104,
-5,
-69,
-140,
-228,
-186,
-147,
-5,
-134,
-115,
-191,
-133,
-57,
-142,
-1,
-202,
-132,
-213,
-16,
-194,
-206,
-21,
-197,
-255,
-216,
-33,
-205,
-93,
-143,
-142,
-0,
-255,
-23,
-48,
-199,
-49,
-64,
-83,
-84,
-172,
-114,
-138,
-100,
-128,
-57,
-2,
-221,
-172,
-224,
-230,
-198,
-85,
-64,
-19,
-204,
-82,
-100,
-4,
-0,
-78,
-165,
-96,
-71,
-180,
-185,
-5,
-255,
-103,
-70,
-128,
-50,
-132,
-16,
-22,
-45,
-184,
-213,
-186,
-226,
-101,
-20,
-35,
-16,
-20,
-196,
-252,
-187,
-103,
-211,
-26,
-53,
-234,
-105,
-197,
-186,
-215,
-79,
-140,
-142,
-0,
-134,
-34,
-141,
-92,
-173,
-108,
-105,
-115,
-145,
-54,
-117,
-20,
-163,
-24,
-197,
-40,
-70,
-49,
-138,
-81,
-140,
-98,
-20,
-163,
-24,
-197,
-40,
-70,
-49,
-138,
-81,
-140,
-98,
-20,
-163,
-24,
-197,
-40,
-70,
-49,
-138,
-81,
-204,
-37,
-248,
-255,
-129,
-51,
-157,
-250,
-111,
-139,
-157,
-153,
-0,
-0,
-0,
-0,
-73,
-69,
-78,
-68,
-174,
-66,
-96,
-130,
-};
-/* clang-format on */
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 75dd417f7f..2c5634e6ef 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -505,9 +505,6 @@ void BaseMaterial3D::_update_shader() {
case DIFFUSE_LAMBERT_WRAP:
code += ",diffuse_lambert_wrap";
break;
- case DIFFUSE_OREN_NAYAR:
- code += ",diffuse_oren_nayar";
- break;
case DIFFUSE_TOON:
code += ",diffuse_toon";
break;
@@ -891,7 +888,7 @@ void BaseMaterial3D::_update_shader() {
code += "\t\tfloat current_layer_depth = 0.0;\n";
code += "\t\tvec2 P = view_dir.xy * heightmap_scale;\n";
code += "\t\tvec2 delta = P / num_layers;\n";
- code += "\t\tvec2 ofs = base_uv;\n";
+ code += "\t\tvec2 ofs = base_uv;\n";
if (flags[FLAG_INVERT_HEIGHTMAP]) {
code += "\t\tfloat depth = texture(texture_heightmap, ofs).r;\n";
} else {
@@ -1760,7 +1757,8 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
if (orm) {
if (property.name == "shading_mode") {
- property.hint_string = "Unshaded,PerPixel"; //vertex not supported in ORM mode, since no individual roughness.
+ // Vertex not supported in ORM mode, since no individual roughness.
+ property.hint_string = "Unshaded,Per-Pixel";
}
if (property.name.begins_with("roughness") || property.name.begins_with("metallic") || property.name.begins_with("ao_texture")) {
property.usage = 0;
@@ -2387,19 +2385,19 @@ void BaseMaterial3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_distance_fade_min_distance"), &BaseMaterial3D::get_distance_fade_min_distance);
ADD_GROUP("Transparency", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth PrePass"), "set_transparency", "get_transparency");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth Pre-Pass"), "set_transparency", "get_transparency");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply"), "set_blend_mode", "get_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never"), "set_depth_draw_mode", "get_depth_draw_mode");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST);
ADD_GROUP("Shading", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,PerPixel,PerVertex"), "set_shading_mode", "get_shading_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,Per-Pixel,Per-Vertex"), "set_shading_mode", "get_shading_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Toon"), "set_diffuse_mode", "get_diffuse_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT);
@@ -2502,7 +2500,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_GROUP("Detail", "detail_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "detail_enabled"), "set_feature", "get_feature", FEATURE_DETAIL);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_mask", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_MASK);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_detail_blend_mode", "get_detail_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply"), "set_detail_blend_mode", "get_detail_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_uv_layer", PROPERTY_HINT_ENUM, "UV1,UV2"), "set_detail_uv", "get_detail_uv");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_ALBEDO);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL);
@@ -2653,7 +2651,6 @@ void BaseMaterial3D::_bind_methods() {
BIND_ENUM_CONSTANT(DIFFUSE_BURLEY);
BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT);
BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT_WRAP);
- BIND_ENUM_CONSTANT(DIFFUSE_OREN_NAYAR);
BIND_ENUM_CONSTANT(DIFFUSE_TOON);
BIND_ENUM_CONSTANT(SPECULAR_SCHLICK_GGX);
diff --git a/scene/resources/material.h b/scene/resources/material.h
index ad1b7b3e33..dc3ecdb5de 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -243,7 +243,6 @@ public:
DIFFUSE_BURLEY,
DIFFUSE_LAMBERT,
DIFFUSE_LAMBERT_WRAP,
- DIFFUSE_OREN_NAYAR,
DIFFUSE_TOON,
DIFFUSE_MAX
};
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 33ad15b938..5e8e77c730 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -582,8 +582,9 @@ Vector<Ref<Shape3D>> Mesh::convex_decompose() const {
int Mesh::get_builtin_bind_pose_count() const {
return 0;
}
-Transform Mesh::get_builtin_bind_pose(int p_index) const {
- return Transform();
+
+Transform3D Mesh::get_builtin_bind_pose(int p_index) const {
+ return Transform3D();
}
Mesh::Mesh() {
@@ -1410,12 +1411,12 @@ struct ArrayMeshLightmapSurface {
uint32_t format = 0;
};
-Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) {
+Error ArrayMesh::lightmap_unwrap(const Transform3D &p_base_transform, float p_texel_size) {
Vector<uint8_t> null_cache;
return lightmap_unwrap_cached(p_base_transform, p_texel_size, null_cache, null_cache, false);
}
-Error ArrayMesh::lightmap_unwrap_cached(const Transform &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache, bool p_generate_cache) {
+Error ArrayMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache, bool p_generate_cache) {
ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes.");
@@ -1431,7 +1432,7 @@ Error ArrayMesh::lightmap_unwrap_cached(const Transform &p_base_transform, float
Basis basis = p_base_transform.get_basis();
Vector3 scale = Vector3(basis.get_axis(0).length(), basis.get_axis(1).length(), basis.get_axis(2).length());
- Transform transform;
+ Transform3D transform;
transform.scale(scale);
Basis normal_basis = transform.basis.inverse().transposed();
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index aa830d7b50..2dfb46782b 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -166,7 +166,7 @@ public:
Vector<Ref<Shape3D>> convex_decompose() const;
virtual int get_builtin_bind_pose_count() const;
- virtual Transform get_builtin_bind_pose(int p_index) const;
+ virtual Transform3D get_builtin_bind_pose(int p_index) const;
Mesh();
};
@@ -262,8 +262,8 @@ public:
void regen_normal_maps();
- Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
- Error lightmap_unwrap_cached(const Transform &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache, bool p_generate_cache = true);
+ Error lightmap_unwrap(const Transform3D &p_base_transform = Transform3D(), float p_texel_size = 0.05);
+ Error lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache, bool p_generate_cache = true);
virtual void reload_from_file() override;
diff --git a/scene/resources/mesh_data_tool.h b/scene/resources/mesh_data_tool.h
index f5c8f11437..b0ebfba7ee 100644
--- a/scene/resources/mesh_data_tool.h
+++ b/scene/resources/mesh_data_tool.h
@@ -33,8 +33,8 @@
#include "scene/resources/mesh.h"
-class MeshDataTool : public Reference {
- GDCLASS(MeshDataTool, Reference);
+class MeshDataTool : public RefCounted {
+ GDCLASS(MeshDataTool, RefCounted);
int format = 0;
struct Vertex {
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index ad90481fbd..33c9ca6d1e 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -97,10 +97,10 @@ void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
String name = "item/" + itos(E->key()) + "/";
p_list->push_back(PropertyInfo(Variant::STRING, name + "name"));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + "mesh_transform"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, name + "mesh_transform"));
p_list->push_back(PropertyInfo(Variant::ARRAY, name + "shapes"));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + "navmesh_transform"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, name + "navmesh_transform"));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "preview", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_HELPER));
}
}
@@ -145,7 +145,7 @@ void MeshLibrary::set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navm
notify_property_list_changed();
}
-void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform &p_transform) {
+void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform3D &p_transform) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
item_map[p_item].navmesh_transform = p_transform;
notify_change_to_owners();
@@ -180,8 +180,8 @@ Ref<NavigationMesh> MeshLibrary::get_item_navmesh(int p_item) const {
return item_map[p_item].navmesh;
}
-Transform MeshLibrary::get_item_navmesh_transform(int p_item) const {
- ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
+Transform3D MeshLibrary::get_item_navmesh_transform(int p_item) const {
+ ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform3D(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
return item_map[p_item].navmesh_transform;
}
diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h
index 1da624c275..1e8a6bf3ff 100644
--- a/scene/resources/mesh_library.h
+++ b/scene/resources/mesh_library.h
@@ -44,14 +44,14 @@ class MeshLibrary : public Resource {
public:
struct ShapeData {
Ref<Shape3D> shape;
- Transform local_transform;
+ Transform3D local_transform;
};
struct Item {
String name;
Ref<Mesh> mesh;
Vector<ShapeData> shapes;
Ref<Texture2D> preview;
- Transform navmesh_transform;
+ Transform3D navmesh_transform;
Ref<NavigationMesh> navmesh;
};
@@ -73,13 +73,13 @@ public:
void set_item_name(int p_item, const String &p_name);
void set_item_mesh(int p_item, const Ref<Mesh> &p_mesh);
void set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh);
- void set_item_navmesh_transform(int p_item, const Transform &p_transform);
+ void set_item_navmesh_transform(int p_item, const Transform3D &p_transform);
void set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes);
void set_item_preview(int p_item, const Ref<Texture2D> &p_preview);
String get_item_name(int p_item) const;
Ref<Mesh> get_item_mesh(int p_item) const;
Ref<NavigationMesh> get_item_navmesh(int p_item) const;
- Transform get_item_navmesh_transform(int p_item) const;
+ Transform3D get_item_navmesh_transform(int p_item) const;
Vector<ShapeData> get_item_shapes(int p_item) const;
Ref<Texture2D> get_item_preview(int p_item) const;
diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp
index 4991887eb3..dea5c4e7d3 100644
--- a/scene/resources/multimesh.cpp
+++ b/scene/resources/multimesh.cpp
@@ -50,7 +50,7 @@ void MultiMesh::_set_transform_array(const Vector<Vector3> &p_array) {
const Vector3 *r = xforms.ptr();
for (int i = 0; i < len / 4; i++) {
- Transform t;
+ Transform3D t;
t.basis[0] = r[i * 4 + 0];
t.basis[1] = r[i * 4 + 1];
t.basis[2] = r[i * 4 + 2];
@@ -75,7 +75,7 @@ Vector<Vector3> MultiMesh::_get_transform_array() const {
Vector3 *w = xforms.ptrw();
for (int i = 0; i < instance_count; i++) {
- Transform t = get_instance_transform(i);
+ Transform3D t = get_instance_transform(i);
w[i * 4 + 0] = t.basis[0];
w[i * 4 + 1] = t.basis[1];
w[i * 4 + 2] = t.basis[2];
@@ -236,7 +236,7 @@ int MultiMesh::get_visible_instance_count() const {
return visible_instance_count;
}
-void MultiMesh::set_instance_transform(int p_instance, const Transform &p_transform) {
+void MultiMesh::set_instance_transform(int p_instance, const Transform3D &p_transform) {
RenderingServer::get_singleton()->multimesh_instance_set_transform(multimesh, p_instance, p_transform);
}
@@ -244,7 +244,7 @@ void MultiMesh::set_instance_transform_2d(int p_instance, const Transform2D &p_t
RenderingServer::get_singleton()->multimesh_instance_set_transform_2d(multimesh, p_instance, p_transform);
}
-Transform MultiMesh::get_instance_transform(int p_instance) const {
+Transform3D MultiMesh::get_instance_transform(int p_instance) const {
return RenderingServer::get_singleton()->multimesh_instance_get_transform(multimesh, p_instance);
}
diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h
index ca5c42d47a..2fe0927e6f 100644
--- a/scene/resources/multimesh.h
+++ b/scene/resources/multimesh.h
@@ -92,9 +92,9 @@ public:
void set_visible_instance_count(int p_count);
int get_visible_instance_count() const;
- void set_instance_transform(int p_instance, const Transform &p_transform);
+ void set_instance_transform(int p_instance, const Transform3D &p_transform);
void set_instance_transform_2d(int p_instance, const Transform2D &p_transform);
- Transform get_instance_transform(int p_instance) const;
+ Transform3D get_instance_transform(int p_instance) const;
Transform2D get_instance_transform_2d(int p_instance) const;
void set_instance_color(int p_instance, const Color &p_color);
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index 78a0aeaa9a..e85b933439 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -34,8 +34,8 @@
#include "core/io/resource.h"
#include "scene/main/node.h"
-class SceneState : public Reference {
- GDCLASS(SceneState, Reference);
+class SceneState : public RefCounted {
+ GDCLASS(SceneState, RefCounted);
Vector<StringName> names;
Vector<Variant> variants;
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index 59e699326d..60d5566f08 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -1316,7 +1316,7 @@ void ParticlesMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET);
ADD_GROUP("Sub Emitter", "sub_emitter_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled,Constant,AtEnd,AtCollision"), "set_sub_emitter_mode", "get_sub_emitter_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled,Constant,At End,At Collision"), "set_sub_emitter_mode", "get_sub_emitter_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sub_emitter_frequency", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_sub_emitter_frequency", "get_sub_emitter_frequency");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_amount_at_end", PROPERTY_HINT_RANGE, "1,32,1"), "set_sub_emitter_amount_at_end", "get_sub_emitter_amount_at_end");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sub_emitter_keep_velocity"), "set_sub_emitter_keep_velocity", "get_sub_emitter_keep_velocity");
@@ -1391,7 +1391,7 @@ ParticlesMaterial::ParticlesMaterial() :
set_sub_emitter_keep_velocity(false);
set_attractor_interaction_enabled(true);
- set_collision_enabled(true);
+ set_collision_enabled(false);
set_collision_bounce(0.0);
set_collision_friction(0.0);
set_collision_use_scale(false);
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index c3d84aeda2..a745df522b 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -1133,7 +1133,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
Vector3 normal_left, normal_right;
normal_left = Vector3(-size.y, size.x * left_to_right, 0.0);
- normal_right = Vector3(size.y, size.x * left_to_right, 0.0);
+ normal_right = Vector3(size.y, size.x * (1.0 - left_to_right), 0.0);
normal_left.normalize();
normal_right.normalize();
@@ -1607,10 +1607,10 @@ int TubeTrailMesh::get_builtin_bind_pose_count() const {
return sections + 1;
}
-Transform TubeTrailMesh::get_builtin_bind_pose(int p_index) const {
+Transform3D TubeTrailMesh::get_builtin_bind_pose(int p_index) const {
float depth = section_length * sections;
- Transform xform;
+ Transform3D xform;
xform.origin.y = depth / 2.0 - section_length * float(p_index);
xform.origin.y = -xform.origin.y; //bind is an inverse transform, so negate y
@@ -1931,10 +1931,10 @@ int RibbonTrailMesh::get_builtin_bind_pose_count() const {
return sections + 1;
}
-Transform RibbonTrailMesh::get_builtin_bind_pose(int p_index) const {
+Transform3D RibbonTrailMesh::get_builtin_bind_pose(int p_index) const {
float depth = section_length * sections;
- Transform xform;
+ Transform3D xform;
xform.origin.y = depth / 2.0 - section_length * float(p_index);
xform.origin.y = -xform.origin.y; //bind is an inverse transform, so negate y
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index ec5806489e..bd6f94921e 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -374,7 +374,7 @@ public:
Ref<Curve> get_curve() const;
virtual int get_builtin_bind_pose_count() const override;
- virtual Transform get_builtin_bind_pose(int p_index) const override;
+ virtual Transform3D get_builtin_bind_pose(int p_index) const override;
TubeTrailMesh();
};
@@ -424,7 +424,7 @@ public:
Ref<Curve> get_curve() const;
virtual int get_builtin_bind_pose_count() const override;
- virtual Transform get_builtin_bind_pose(int p_index) const override;
+ virtual Transform3D get_builtin_bind_pose(int p_index) const override;
RibbonTrailMesh();
};
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index f2751b7604..2a60f54fdd 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -31,14 +31,14 @@
#include "resource_format_text.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
#include "core/io/resource_format_binary.h"
-#include "core/os/dir_access.h"
#include "core/version.h"
//version 2: changed names for basis, aabb, Vectors, etc.
#define FORMAT_VERSION 2
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/version.h"
#define _printerr() ERR_PRINT(String(res_path + ":" + itos(lines) + " - Parse Error: " + error_text).utf8().get_data());
@@ -978,7 +978,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
}
wf->store_32(0); //string table size, will not be in use
- size_t ext_res_count_pos = wf->get_position();
+ uint64_t ext_res_count_pos = wf->get_position();
wf->store_32(0); //zero ext resources, still parsing them
@@ -1041,7 +1041,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
//now, save resources to a separate file, for now
- size_t sub_res_count_pos = wf->get_position();
+ uint64_t sub_res_count_pos = wf->get_position();
wf->store_32(0); //zero sub resources, still parsing them
String temp_file = p_path + ".temp";
@@ -1050,8 +1050,8 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
return ERR_CANT_OPEN;
}
- Vector<size_t> local_offsets;
- Vector<size_t> local_pointers_pos;
+ Vector<uint64_t> local_offsets;
+ Vector<uint64_t> local_pointers_pos;
while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
String type;
@@ -1089,7 +1089,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
wf->store_64(0); //temp local offset
bs_save_unicode_string(wf2, type);
- size_t propcount_ofs = wf2->get_position();
+ uint64_t propcount_ofs = wf2->get_position();
wf2->store_32(0);
int prop_count = 0;
@@ -1159,7 +1159,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
local_offsets.push_back(wf2->get_position());
bs_save_unicode_string(wf2, "PackedScene");
- size_t propcount_ofs = wf2->get_position();
+ uint64_t propcount_ofs = wf2->get_position();
wf2->store_32(0);
int prop_count = 0;
@@ -1185,7 +1185,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
wf2->close();
- size_t offset_from = wf->get_position();
+ uint64_t offset_from = wf->get_position();
wf->seek(sub_res_count_pos); //plus one because the saved one
wf->store_32(local_offsets.size());
diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h
index 2dc683415d..f5d9cca859 100644
--- a/scene/resources/resource_format_text.h
+++ b/scene/resources/resource_format_text.h
@@ -31,9 +31,9 @@
#ifndef RESOURCE_FORMAT_TEXT_H
#define RESOURCE_FORMAT_TEXT_H
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
-#include "core/os/file_access.h"
#include "core/variant/variant_parser.h"
#include "scene/resources/packed_scene.h"
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 77c6199794..cbd44315b7 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -30,7 +30,7 @@
#include "shader.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "scene/scene_string_names.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering_server.h"
@@ -184,7 +184,7 @@ RES ResourceFormatLoaderShader::load(const String &p_path, const String &p_origi
}
void ResourceFormatLoaderShader::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("shader");
+ p_extensions->push_back("gdshader");
}
bool ResourceFormatLoaderShader::handles_type(const String &p_type) const {
@@ -193,7 +193,7 @@ bool ResourceFormatLoaderShader::handles_type(const String &p_type) const {
String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const {
String el = p_path.get_extension().to_lower();
- if (el == "shader") {
+ if (el == "gdshader") {
return "Shader";
}
return "";
@@ -224,7 +224,7 @@ Error ResourceFormatSaverShader::save(const String &p_path, const RES &p_resourc
void ResourceFormatSaverShader::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
if (const Shader *shader = Object::cast_to<Shader>(*p_resource)) {
if (shader->is_text_shader()) {
- p_extensions->push_back("shader");
+ p_extensions->push_back("gdshader");
}
}
}
diff --git a/scene/resources/shape_3d.cpp b/scene/resources/shape_3d.cpp
index cb44e059a3..a02a0e5488 100644
--- a/scene/resources/shape_3d.cpp
+++ b/scene/resources/shape_3d.cpp
@@ -35,7 +35,7 @@
#include "scene/resources/mesh.h"
#include "servers/physics_server_3d.h"
-void Shape3D::add_vertices_to_array(Vector<Vector3> &array, const Transform &p_xform) {
+void Shape3D::add_vertices_to_array(Vector<Vector3> &array, const Transform3D &p_xform) {
Vector<Vector3> toadd = get_debug_mesh_lines();
if (toadd.size()) {
diff --git a/scene/resources/shape_3d.h b/scene/resources/shape_3d.h
index 0644940fd4..b8e529cd3c 100644
--- a/scene/resources/shape_3d.h
+++ b/scene/resources/shape_3d.h
@@ -60,7 +60,7 @@ public:
/// Returns the radius of a sphere that fully enclose this shape
virtual real_t get_enclosing_radius() const = 0;
- void add_vertices_to_array(Vector<Vector3> &array, const Transform &p_xform);
+ void add_vertices_to_array(Vector<Vector3> &array, const Transform3D &p_xform);
real_t get_margin() const;
void set_margin(real_t p_margin);
diff --git a/scene/resources/skeleton_modification_2d.cpp b/scene/resources/skeleton_modification_2d.cpp
new file mode 100644
index 0000000000..b52a60006a
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d.cpp
@@ -0,0 +1,253 @@
+/*************************************************************************/
+/* skeleton_modification_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_2d.h"
+#include "scene/2d/skeleton_2d.h"
+
+#include "scene/2d/collision_object_2d.h"
+#include "scene/2d/collision_shape_2d.h"
+#include "scene/2d/physical_bone_2d.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_settings.h"
+#endif // TOOLS_ENABLED
+
+///////////////////////////////////////
+// Modification2D
+///////////////////////////////////////
+
+void SkeletonModification2D::_execute(float p_delta) {
+ call("_execute", p_delta);
+
+ if (!enabled) {
+ return;
+ }
+}
+
+void SkeletonModification2D::_setup_modification(SkeletonModificationStack2D *p_stack) {
+ stack = p_stack;
+ if (stack) {
+ is_setup = true;
+ } else {
+ WARN_PRINT("Could not setup modification with name " + get_name());
+ }
+
+ call("_setup_modification", p_stack);
+}
+
+void SkeletonModification2D::_draw_editor_gizmo() {
+ call("_draw_editor_gizmo");
+}
+
+void SkeletonModification2D::set_enabled(bool p_enabled) {
+ enabled = p_enabled;
+
+#ifdef TOOLS_ENABLED
+ if (editor_draw_gizmo) {
+ if (stack) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2D::get_enabled() {
+ return enabled;
+}
+
+float SkeletonModification2D::clamp_angle(float p_angle, float p_min_bound, float p_max_bound, bool p_invert) {
+ // Map to the 0 to 360 range (in radians though) instead of the -180 to 180 range.
+ if (p_angle < 0) {
+ p_angle = Math_TAU + p_angle;
+ }
+
+ // Make min and max in the range of 0 to 360 (in radians), and make sure they are in the right order
+ if (p_min_bound < 0) {
+ p_min_bound = Math_TAU + p_min_bound;
+ }
+ if (p_max_bound < 0) {
+ p_max_bound = Math_TAU + p_max_bound;
+ }
+ if (p_min_bound > p_max_bound) {
+ float tmp = p_min_bound;
+ p_min_bound = p_max_bound;
+ p_max_bound = tmp;
+ }
+
+ // Note: May not be the most optimal way to clamp, but it always constraints to the nearest angle.
+ if (p_invert == false) {
+ if (p_angle < p_min_bound || p_angle > p_max_bound) {
+ Vector2 min_bound_vec = Vector2(Math::cos(p_min_bound), Math::sin(p_min_bound));
+ Vector2 max_bound_vec = Vector2(Math::cos(p_max_bound), Math::sin(p_max_bound));
+ Vector2 angle_vec = Vector2(Math::cos(p_angle), Math::sin(p_angle));
+
+ if (angle_vec.distance_squared_to(min_bound_vec) <= angle_vec.distance_squared_to(max_bound_vec)) {
+ p_angle = p_min_bound;
+ } else {
+ p_angle = p_max_bound;
+ }
+ }
+ } else {
+ if (p_angle > p_min_bound && p_angle < p_max_bound) {
+ Vector2 min_bound_vec = Vector2(Math::cos(p_min_bound), Math::sin(p_min_bound));
+ Vector2 max_bound_vec = Vector2(Math::cos(p_max_bound), Math::sin(p_max_bound));
+ Vector2 angle_vec = Vector2(Math::cos(p_angle), Math::sin(p_angle));
+
+ if (angle_vec.distance_squared_to(min_bound_vec) <= angle_vec.distance_squared_to(max_bound_vec)) {
+ p_angle = p_min_bound;
+ } else {
+ p_angle = p_max_bound;
+ }
+ }
+ }
+ return p_angle;
+}
+
+void SkeletonModification2D::editor_draw_angle_constraints(Bone2D *p_operation_bone, float p_min_bound, float p_max_bound,
+ bool p_constraint_enabled, bool p_constraint_in_localspace, bool p_constraint_inverted) {
+ if (!p_operation_bone) {
+ return;
+ }
+
+ Color bone_ik_color = Color(1.0, 0.65, 0.0, 0.4);
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
+ }
+#endif // TOOLS_ENABLED
+
+ float arc_angle_min = p_min_bound;
+ float arc_angle_max = p_max_bound;
+ if (arc_angle_min < 0) {
+ arc_angle_min = (Math_PI * 2) + arc_angle_min;
+ }
+ if (arc_angle_max < 0) {
+ arc_angle_max = (Math_PI * 2) + arc_angle_max;
+ }
+ if (arc_angle_min > arc_angle_max) {
+ float tmp = arc_angle_min;
+ arc_angle_min = arc_angle_max;
+ arc_angle_max = tmp;
+ }
+ arc_angle_min += p_operation_bone->get_bone_angle();
+ arc_angle_max += p_operation_bone->get_bone_angle();
+
+ if (p_constraint_enabled) {
+ if (p_constraint_in_localspace) {
+ Node *operation_bone_parent = p_operation_bone->get_parent();
+ Bone2D *operation_bone_parent_bone = Object::cast_to<Bone2D>(operation_bone_parent);
+
+ if (operation_bone_parent_bone) {
+ stack->skeleton->draw_set_transform(
+ stack->skeleton->get_global_transform().affine_inverse().xform(p_operation_bone->get_global_position()),
+ operation_bone_parent_bone->get_global_rotation() - stack->skeleton->get_global_rotation());
+ } else {
+ stack->skeleton->draw_set_transform(stack->skeleton->get_global_transform().affine_inverse().xform(p_operation_bone->get_global_position()));
+ }
+ } else {
+ stack->skeleton->draw_set_transform(stack->skeleton->get_global_transform().affine_inverse().xform(p_operation_bone->get_global_position()));
+ }
+
+ if (p_constraint_inverted) {
+ stack->skeleton->draw_arc(Vector2(0, 0), p_operation_bone->get_length(),
+ arc_angle_min + (Math_PI * 2), arc_angle_max, 32, bone_ik_color, 1.0);
+ } else {
+ stack->skeleton->draw_arc(Vector2(0, 0), p_operation_bone->get_length(),
+ arc_angle_min, arc_angle_max, 32, bone_ik_color, 1.0);
+ }
+ stack->skeleton->draw_line(Vector2(0, 0), Vector2(Math::cos(arc_angle_min), Math::sin(arc_angle_min)) * p_operation_bone->get_length(), bone_ik_color, 1.0);
+ stack->skeleton->draw_line(Vector2(0, 0), Vector2(Math::cos(arc_angle_max), Math::sin(arc_angle_max)) * p_operation_bone->get_length(), bone_ik_color, 1.0);
+
+ } else {
+ stack->skeleton->draw_set_transform(stack->skeleton->get_global_transform().affine_inverse().xform(p_operation_bone->get_global_position()));
+ stack->skeleton->draw_arc(Vector2(0, 0), p_operation_bone->get_length(), 0, Math_PI * 2, 32, bone_ik_color, 1.0);
+ stack->skeleton->draw_line(Vector2(0, 0), Vector2(1, 0) * p_operation_bone->get_length(), bone_ik_color, 1.0);
+ }
+}
+
+Ref<SkeletonModificationStack2D> SkeletonModification2D::get_modification_stack() {
+ return stack;
+}
+
+void SkeletonModification2D::set_is_setup(bool p_setup) {
+ is_setup = p_setup;
+}
+
+bool SkeletonModification2D::get_is_setup() const {
+ return is_setup;
+}
+
+void SkeletonModification2D::set_execution_mode(int p_mode) {
+ execution_mode = p_mode;
+}
+
+int SkeletonModification2D::get_execution_mode() const {
+ return execution_mode;
+}
+
+void SkeletonModification2D::set_editor_draw_gizmo(bool p_draw_gizmo) {
+ editor_draw_gizmo = p_draw_gizmo;
+#ifdef TOOLS_ENABLED
+ if (is_setup) {
+ if (stack) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2D::get_editor_draw_gizmo() const {
+ return editor_draw_gizmo;
+}
+
+void SkeletonModification2D::_bind_methods() {
+ BIND_VMETHOD(MethodInfo("_execute", PropertyInfo(Variant::FLOAT, "delta")));
+ BIND_VMETHOD(MethodInfo("_setup_modification", PropertyInfo(Variant::OBJECT, "modification_stack", PROPERTY_HINT_RESOURCE_TYPE, "SkeletonModificationStack2D")));
+ BIND_VMETHOD(MethodInfo("_draw_editor_gizmo"));
+
+ ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &SkeletonModification2D::set_enabled);
+ ClassDB::bind_method(D_METHOD("get_enabled"), &SkeletonModification2D::get_enabled);
+ ClassDB::bind_method(D_METHOD("get_modification_stack"), &SkeletonModification2D::get_modification_stack);
+ ClassDB::bind_method(D_METHOD("set_is_setup", "is_setup"), &SkeletonModification2D::set_is_setup);
+ ClassDB::bind_method(D_METHOD("get_is_setup"), &SkeletonModification2D::get_is_setup);
+ ClassDB::bind_method(D_METHOD("set_execution_mode", "execution_mode"), &SkeletonModification2D::set_execution_mode);
+ ClassDB::bind_method(D_METHOD("get_execution_mode"), &SkeletonModification2D::get_execution_mode);
+ ClassDB::bind_method(D_METHOD("clamp_angle", "angle", "min", "max", "invert"), &SkeletonModification2D::clamp_angle);
+ ClassDB::bind_method(D_METHOD("set_editor_draw_gizmo", "draw_gizmo"), &SkeletonModification2D::set_editor_draw_gizmo);
+ ClassDB::bind_method(D_METHOD("get_editor_draw_gizmo"), &SkeletonModification2D::get_editor_draw_gizmo);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "execution_mode", PROPERTY_HINT_ENUM, "process, physics_process"), "set_execution_mode", "get_execution_mode");
+}
+
+SkeletonModification2D::SkeletonModification2D() {
+ stack = nullptr;
+ is_setup = false;
+}
diff --git a/scene/resources/skeleton_modification_2d.h b/scene/resources/skeleton_modification_2d.h
new file mode 100644
index 0000000000..18633e55cb
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d.h
@@ -0,0 +1,85 @@
+/*************************************************************************/
+/* skeleton_modification_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATION2D_H
+#define SKELETONMODIFICATION2D_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_stack_2d.h"
+
+///////////////////////////////////////
+// SkeletonModification2D
+///////////////////////////////////////
+
+class SkeletonModificationStack2D;
+class Bone2D;
+
+class SkeletonModification2D : public Resource {
+ GDCLASS(SkeletonModification2D, Resource);
+ friend class Skeleton2D;
+ friend class Bone2D;
+
+protected:
+ static void _bind_methods();
+
+ SkeletonModificationStack2D *stack;
+ int execution_mode = 0; // 0 = process
+
+ bool enabled = true;
+ bool is_setup = false;
+
+ bool _print_execution_error(bool p_condition, String p_message);
+
+public:
+ virtual void _execute(float _delta);
+ virtual void _setup_modification(SkeletonModificationStack2D *p_stack);
+ virtual void _draw_editor_gizmo();
+
+ bool editor_draw_gizmo = false;
+ void set_editor_draw_gizmo(bool p_draw_gizmo);
+ bool get_editor_draw_gizmo() const;
+
+ void set_enabled(bool p_enabled);
+ bool get_enabled();
+
+ Ref<SkeletonModificationStack2D> get_modification_stack();
+ void set_is_setup(bool p_setup);
+ bool get_is_setup() const;
+
+ void set_execution_mode(int p_mode);
+ int get_execution_mode() const;
+
+ float clamp_angle(float p_angle, float p_min_bound, float p_max_bound, bool p_invert_clamp = false);
+ void editor_draw_angle_constraints(Bone2D *p_operation_bone, float p_min_bound, float p_max_bound, bool p_constraint_enabled, bool p_constraint_in_localspace, bool p_constraint_inverted);
+
+ SkeletonModification2D();
+};
+
+#endif // SKELETONMODIFICATION2D_H
diff --git a/scene/resources/skeleton_modification_2d_ccdik.cpp b/scene/resources/skeleton_modification_2d_ccdik.cpp
new file mode 100644
index 0000000000..7ea60e584e
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_ccdik.cpp
@@ -0,0 +1,545 @@
+/*************************************************************************/
+/* skeleton_modification_2d_ccdik.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_2d_ccdik.h"
+#include "scene/2d/skeleton_2d.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_settings.h"
+#endif // TOOLS_ENABLED
+
+bool SkeletonModification2DCCDIK::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path.begins_with("joint_data/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, ccdik_data_chain.size(), false);
+
+ if (what == "bone2d_node") {
+ set_ccdik_joint_bone2d_node(which, p_value);
+ } else if (what == "bone_index") {
+ set_ccdik_joint_bone_index(which, p_value);
+ } else if (what == "rotate_from_joint") {
+ set_ccdik_joint_rotate_from_joint(which, p_value);
+ } else if (what == "enable_constraint") {
+ set_ccdik_joint_enable_constraint(which, p_value);
+ } else if (what == "constraint_angle_min") {
+ set_ccdik_joint_constraint_angle_min(which, Math::deg2rad(float(p_value)));
+ } else if (what == "constraint_angle_max") {
+ set_ccdik_joint_constraint_angle_max(which, Math::deg2rad(float(p_value)));
+ } else if (what == "constraint_angle_invert") {
+ set_ccdik_joint_constraint_angle_invert(which, p_value);
+ } else if (what == "constraint_in_localspace") {
+ set_ccdik_joint_constraint_in_localspace(which, p_value);
+ }
+
+#ifdef TOOLS_ENABLED
+ if (what.begins_with("editor_draw_gizmo")) {
+ set_ccdik_joint_editor_draw_gizmo(which, p_value);
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path.begins_with("editor/draw_gizmo")) {
+ set_editor_draw_gizmo(p_value);
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+bool SkeletonModification2DCCDIK::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("joint_data/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, ccdik_data_chain.size(), false);
+
+ if (what == "bone2d_node") {
+ r_ret = get_ccdik_joint_bone2d_node(which);
+ } else if (what == "bone_index") {
+ r_ret = get_ccdik_joint_bone_index(which);
+ } else if (what == "rotate_from_joint") {
+ r_ret = get_ccdik_joint_rotate_from_joint(which);
+ } else if (what == "enable_constraint") {
+ r_ret = get_ccdik_joint_enable_constraint(which);
+ } else if (what == "constraint_angle_min") {
+ r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_min(which));
+ } else if (what == "constraint_angle_max") {
+ r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_max(which));
+ } else if (what == "constraint_angle_invert") {
+ r_ret = get_ccdik_joint_constraint_angle_invert(which);
+ } else if (what == "constraint_in_localspace") {
+ r_ret = get_ccdik_joint_constraint_in_localspace(which);
+ }
+
+#ifdef TOOLS_ENABLED
+ if (what.begins_with("editor_draw_gizmo")) {
+ r_ret = get_ccdik_joint_editor_draw_gizmo(which);
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path.begins_with("editor/draw_gizmo")) {
+ r_ret = get_editor_draw_gizmo();
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+void SkeletonModification2DCCDIK::_get_property_list(List<PropertyInfo> *p_list) const {
+ for (int i = 0; i < ccdik_data_chain.size(); i++) {
+ String base_string = "joint_data/" + itos(i) + "/";
+
+ p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::NODE_PATH, base_string + "bone2d_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "rotate_from_joint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+
+ p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "enable_constraint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ if (ccdik_data_chain[i].enable_constraint) {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "constraint_angle_min", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "constraint_angle_max", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "constraint_angle_invert", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "constraint_in_localspace", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "editor_draw_gizmo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+#endif // TOOLS_ENABLED
+ }
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "editor/draw_gizmo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+#endif // TOOLS_ENABLED
+}
+
+void SkeletonModification2DCCDIK::_execute(float p_delta) {
+ ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
+ "Modification is not setup and therefore cannot execute!");
+ if (!enabled) {
+ return;
+ }
+
+ if (target_node_cache.is_null()) {
+ WARN_PRINT_ONCE("Target cache is out of date. Attempting to update...");
+ update_target_cache();
+ return;
+ }
+ if (tip_node_cache.is_null()) {
+ WARN_PRINT_ONCE("Tip cache is out of date. Attempting to update...");
+ update_tip_cache();
+ return;
+ }
+
+ Node2D *target = Object::cast_to<Node2D>(ObjectDB::get_instance(target_node_cache));
+ if (!target || !target->is_inside_tree()) {
+ ERR_PRINT_ONCE("Target node is not in the scene tree. Cannot execute modification!");
+ return;
+ }
+
+ Node2D *tip = Object::cast_to<Node2D>(ObjectDB::get_instance(tip_node_cache));
+ if (!tip || !tip->is_inside_tree()) {
+ ERR_PRINT_ONCE("Tip node is not in the scene tree. Cannot execute modification!");
+ return;
+ }
+
+ for (int i = 0; i < ccdik_data_chain.size(); i++) {
+ _execute_ccdik_joint(i, target, tip);
+ }
+}
+
+void SkeletonModification2DCCDIK::_execute_ccdik_joint(int p_joint_idx, Node2D *p_target, Node2D *p_tip) {
+ CCDIK_Joint_Data2D ccdik_data = ccdik_data_chain[p_joint_idx];
+ if (ccdik_data.bone_idx < 0 || ccdik_data.bone_idx > stack->skeleton->get_bone_count()) {
+ ERR_PRINT_ONCE("2D CCDIK joint: bone index not found!");
+ return;
+ }
+
+ Bone2D *operation_bone = stack->skeleton->get_bone(ccdik_data.bone_idx);
+ Transform2D operation_transform = operation_bone->get_global_transform();
+
+ if (ccdik_data.rotate_from_joint) {
+ // To rotate from the joint, simply look at the target!
+ operation_transform.set_rotation(
+ operation_transform.looking_at(p_target->get_global_transform().get_origin()).get_rotation() - operation_bone->get_bone_angle());
+ } else {
+ // How to rotate from the tip: get the difference of rotation needed from the tip to the target, from the perspective of the joint.
+ // Because we are only using the offset, we do not need to account for the bone angle of the Bone2D node.
+ float joint_to_tip = operation_transform.get_origin().angle_to_point(p_tip->get_global_transform().get_origin());
+ float joint_to_target = operation_transform.get_origin().angle_to_point(p_target->get_global_transform().get_origin());
+ operation_transform.set_rotation(
+ operation_transform.get_rotation() + (joint_to_target - joint_to_tip));
+ }
+
+ // Reset scale
+ operation_transform.set_scale(operation_bone->get_global_transform().get_scale());
+
+ // Apply constraints in globalspace:
+ if (ccdik_data.enable_constraint && !ccdik_data.constraint_in_localspace) {
+ operation_transform.set_rotation(clamp_angle(operation_transform.get_rotation(), ccdik_data.constraint_angle_min, ccdik_data.constraint_angle_max, ccdik_data.constraint_angle_invert));
+ }
+
+ // Convert from a global transform to a delta and then apply the delta to the local transform.
+ operation_bone->set_global_transform(operation_transform);
+ operation_transform = operation_bone->get_transform();
+
+ // Apply constraints in localspace:
+ if (ccdik_data.enable_constraint && ccdik_data.constraint_in_localspace) {
+ operation_transform.set_rotation(clamp_angle(operation_transform.get_rotation(), ccdik_data.constraint_angle_min, ccdik_data.constraint_angle_max, ccdik_data.constraint_angle_invert));
+ }
+
+ // Set the local pose override, and to make sure child bones are also updated, set the transform of the bone.
+ stack->skeleton->set_bone_local_pose_override(ccdik_data.bone_idx, operation_transform, stack->strength, true);
+ operation_bone->set_transform(operation_transform);
+ operation_bone->notification(operation_bone->NOTIFICATION_TRANSFORM_CHANGED);
+}
+
+void SkeletonModification2DCCDIK::_setup_modification(SkeletonModificationStack2D *p_stack) {
+ stack = p_stack;
+
+ if (stack != nullptr) {
+ is_setup = true;
+ update_target_cache();
+ update_tip_cache();
+ }
+}
+
+void SkeletonModification2DCCDIK::_draw_editor_gizmo() {
+ if (!enabled || !is_setup) {
+ return;
+ }
+
+ for (int i = 0; i < ccdik_data_chain.size(); i++) {
+ if (!ccdik_data_chain[i].editor_draw_gizmo) {
+ continue;
+ }
+
+ Bone2D *operation_bone = stack->skeleton->get_bone(ccdik_data_chain[i].bone_idx);
+ editor_draw_angle_constraints(operation_bone, ccdik_data_chain[i].constraint_angle_min, ccdik_data_chain[i].constraint_angle_max,
+ ccdik_data_chain[i].enable_constraint, ccdik_data_chain[i].constraint_in_localspace, ccdik_data_chain[i].constraint_angle_invert);
+ }
+}
+
+void SkeletonModification2DCCDIK::update_target_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ return;
+ }
+
+ target_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(target_node)) {
+ Node *node = stack->skeleton->get_node(target_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update target cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update target cache: node is not in the scene tree!");
+ target_node_cache = node->get_instance_id();
+ }
+ }
+ }
+}
+
+void SkeletonModification2DCCDIK::update_tip_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update tip cache: modification is not properly setup!");
+ return;
+ }
+
+ tip_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(tip_node)) {
+ Node *node = stack->skeleton->get_node(tip_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update tip cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update tip cache: node is not in the scene tree!");
+ tip_node_cache = node->get_instance_id();
+ }
+ }
+ }
+}
+
+void SkeletonModification2DCCDIK::ccdik_joint_update_bone2d_cache(int p_joint_idx) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "Cannot update bone2d cache: joint index out of range!");
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update CCDIK Bone2D cache: modification is not properly setup!");
+ return;
+ }
+
+ ccdik_data_chain.write[p_joint_idx].bone2d_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(ccdik_data_chain[p_joint_idx].bone2d_node)) {
+ Node *node = stack->skeleton->get_node(ccdik_data_chain[p_joint_idx].bone2d_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update CCDIK joint " + itos(p_joint_idx) + " Bone2D cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update CCDIK joint " + itos(p_joint_idx) + " Bone2D cache: node is not in the scene tree!");
+ ccdik_data_chain.write[p_joint_idx].bone2d_node_cache = node->get_instance_id();
+
+ Bone2D *bone = Object::cast_to<Bone2D>(node);
+ if (bone) {
+ ccdik_data_chain.write[p_joint_idx].bone_idx = bone->get_index_in_skeleton();
+ } else {
+ ERR_FAIL_MSG("CCDIK joint " + itos(p_joint_idx) + " Bone2D cache: Nodepath to Bone2D is not a Bone2D node!");
+ }
+ }
+ }
+ }
+}
+
+void SkeletonModification2DCCDIK::set_target_node(const NodePath &p_target_node) {
+ target_node = p_target_node;
+ update_target_cache();
+}
+
+NodePath SkeletonModification2DCCDIK::get_target_node() const {
+ return target_node;
+}
+
+void SkeletonModification2DCCDIK::set_tip_node(const NodePath &p_tip_node) {
+ tip_node = p_tip_node;
+ update_tip_cache();
+}
+
+NodePath SkeletonModification2DCCDIK::get_tip_node() const {
+ return tip_node;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_data_chain_length(int p_length) {
+ ccdik_data_chain.resize(p_length);
+ notify_property_list_changed();
+}
+
+int SkeletonModification2DCCDIK::get_ccdik_data_chain_length() {
+ return ccdik_data_chain.size();
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_bone2d_node(int p_joint_idx, const NodePath &p_target_node) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCDIK joint out of range!");
+ ccdik_data_chain.write[p_joint_idx].bone2d_node = p_target_node;
+ ccdik_joint_update_bone2d_cache(p_joint_idx);
+
+ notify_property_list_changed();
+}
+
+NodePath SkeletonModification2DCCDIK::get_ccdik_joint_bone2d_node(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), NodePath(), "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].bone2d_node;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_bone_index(int p_joint_idx, int p_bone_idx) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCCDIK joint out of range!");
+ ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
+
+ if (is_setup) {
+ if (stack->skeleton) {
+ ERR_FAIL_INDEX_MSG(p_bone_idx, stack->skeleton->get_bone_count(), "Passed-in Bone index is out of range!");
+ ccdik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ ccdik_data_chain.write[p_joint_idx].bone2d_node_cache = stack->skeleton->get_bone(p_bone_idx)->get_instance_id();
+ ccdik_data_chain.write[p_joint_idx].bone2d_node = stack->skeleton->get_path_to(stack->skeleton->get_bone(p_bone_idx));
+ } else {
+ WARN_PRINT("Cannot verify the CCDIK joint " + itos(p_joint_idx) + " bone index for this modification...");
+ ccdik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ }
+ } else {
+ WARN_PRINT("Cannot verify the CCDIK joint " + itos(p_joint_idx) + " bone index for this modification...");
+ ccdik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ }
+
+ notify_property_list_changed();
+}
+
+int SkeletonModification2DCCDIK::get_ccdik_joint_bone_index(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), -1, "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].bone_idx;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_rotate_from_joint(int p_joint_idx, bool p_rotate_from_joint) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCDIK joint out of range!");
+ ccdik_data_chain.write[p_joint_idx].rotate_from_joint = p_rotate_from_joint;
+}
+
+bool SkeletonModification2DCCDIK::get_ccdik_joint_rotate_from_joint(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), false, "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].rotate_from_joint;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_enable_constraint(int p_joint_idx, bool p_constraint) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCDIK joint out of range!");
+ ccdik_data_chain.write[p_joint_idx].enable_constraint = p_constraint;
+ notify_property_list_changed();
+
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2DCCDIK::get_ccdik_joint_enable_constraint(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), false, "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].enable_constraint;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_constraint_angle_min(int p_joint_idx, float p_angle_min) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCDIK joint out of range!");
+ ccdik_data_chain.write[p_joint_idx].constraint_angle_min = p_angle_min;
+
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+float SkeletonModification2DCCDIK::get_ccdik_joint_constraint_angle_min(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), 0.0, "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].constraint_angle_min;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_constraint_angle_max(int p_joint_idx, float p_angle_max) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCDIK joint out of range!");
+ ccdik_data_chain.write[p_joint_idx].constraint_angle_max = p_angle_max;
+
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+float SkeletonModification2DCCDIK::get_ccdik_joint_constraint_angle_max(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), 0.0, "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].constraint_angle_max;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_constraint_angle_invert(int p_joint_idx, bool p_invert) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCDIK joint out of range!");
+ ccdik_data_chain.write[p_joint_idx].constraint_angle_invert = p_invert;
+
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2DCCDIK::get_ccdik_joint_constraint_angle_invert(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), false, "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].constraint_angle_invert;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_constraint_in_localspace(int p_joint_idx, bool p_constraint_in_localspace) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCDIK joint out of range!");
+ ccdik_data_chain.write[p_joint_idx].constraint_in_localspace = p_constraint_in_localspace;
+
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2DCCDIK::get_ccdik_joint_constraint_in_localspace(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), false, "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].constraint_in_localspace;
+}
+
+void SkeletonModification2DCCDIK::set_ccdik_joint_editor_draw_gizmo(int p_joint_idx, bool p_draw_gizmo) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "CCDIK joint out of range!");
+ ccdik_data_chain.write[p_joint_idx].editor_draw_gizmo = p_draw_gizmo;
+
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2DCCDIK::get_ccdik_joint_editor_draw_gizmo(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, ccdik_data_chain.size(), false, "CCDIK joint out of range!");
+ return ccdik_data_chain[p_joint_idx].editor_draw_gizmo;
+}
+
+void SkeletonModification2DCCDIK::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification2DCCDIK::set_target_node);
+ ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification2DCCDIK::get_target_node);
+ ClassDB::bind_method(D_METHOD("set_tip_node", "tip_nodepath"), &SkeletonModification2DCCDIK::set_tip_node);
+ ClassDB::bind_method(D_METHOD("get_tip_node"), &SkeletonModification2DCCDIK::get_tip_node);
+
+ ClassDB::bind_method(D_METHOD("set_ccdik_data_chain_length", "length"), &SkeletonModification2DCCDIK::set_ccdik_data_chain_length);
+ ClassDB::bind_method(D_METHOD("get_ccdik_data_chain_length"), &SkeletonModification2DCCDIK::get_ccdik_data_chain_length);
+
+ ClassDB::bind_method(D_METHOD("set_ccdik_joint_bone2d_node", "joint_idx", "bone2d_nodepath"), &SkeletonModification2DCCDIK::set_ccdik_joint_bone2d_node);
+ ClassDB::bind_method(D_METHOD("get_ccdik_joint_bone2d_node", "joint_idx"), &SkeletonModification2DCCDIK::get_ccdik_joint_bone2d_node);
+ ClassDB::bind_method(D_METHOD("set_ccdik_joint_bone_index", "joint_idx", "bone_idx"), &SkeletonModification2DCCDIK::set_ccdik_joint_bone_index);
+ ClassDB::bind_method(D_METHOD("get_ccdik_joint_bone_index", "joint_idx"), &SkeletonModification2DCCDIK::get_ccdik_joint_bone_index);
+ ClassDB::bind_method(D_METHOD("set_ccdik_joint_rotate_from_joint", "joint_idx", "rotate_from_joint"), &SkeletonModification2DCCDIK::set_ccdik_joint_rotate_from_joint);
+ ClassDB::bind_method(D_METHOD("get_ccdik_joint_rotate_from_joint", "joint_idx"), &SkeletonModification2DCCDIK::get_ccdik_joint_rotate_from_joint);
+ ClassDB::bind_method(D_METHOD("set_ccdik_joint_enable_constraint", "joint_idx", "enable_constraint"), &SkeletonModification2DCCDIK::set_ccdik_joint_enable_constraint);
+ ClassDB::bind_method(D_METHOD("get_ccdik_joint_enable_constraint", "joint_idx"), &SkeletonModification2DCCDIK::get_ccdik_joint_enable_constraint);
+ ClassDB::bind_method(D_METHOD("set_ccdik_joint_constraint_angle_min", "joint_idx", "angle_min"), &SkeletonModification2DCCDIK::set_ccdik_joint_constraint_angle_min);
+ ClassDB::bind_method(D_METHOD("get_ccdik_joint_constraint_angle_min", "joint_idx"), &SkeletonModification2DCCDIK::get_ccdik_joint_constraint_angle_min);
+ ClassDB::bind_method(D_METHOD("set_ccdik_joint_constraint_angle_max", "joint_idx", "angle_max"), &SkeletonModification2DCCDIK::set_ccdik_joint_constraint_angle_max);
+ ClassDB::bind_method(D_METHOD("get_ccdik_joint_constraint_angle_max", "joint_idx"), &SkeletonModification2DCCDIK::get_ccdik_joint_constraint_angle_max);
+ ClassDB::bind_method(D_METHOD("set_ccdik_joint_constraint_angle_invert", "joint_idx", "invert"), &SkeletonModification2DCCDIK::set_ccdik_joint_constraint_angle_invert);
+ ClassDB::bind_method(D_METHOD("get_ccdik_joint_constraint_angle_invert", "joint_idx"), &SkeletonModification2DCCDIK::get_ccdik_joint_constraint_angle_invert);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D"), "set_target_node", "get_target_node");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "tip_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D"), "set_tip_node", "get_tip_node");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "ccdik_data_chain_length", PROPERTY_HINT_RANGE, "0, 100, 1"), "set_ccdik_data_chain_length", "get_ccdik_data_chain_length");
+}
+
+SkeletonModification2DCCDIK::SkeletonModification2DCCDIK() {
+ stack = nullptr;
+ is_setup = false;
+ enabled = true;
+ editor_draw_gizmo = true;
+}
+
+SkeletonModification2DCCDIK::~SkeletonModification2DCCDIK() {
+}
diff --git a/scene/resources/skeleton_modification_2d_ccdik.h b/scene/resources/skeleton_modification_2d_ccdik.h
new file mode 100644
index 0000000000..dc48291f62
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_ccdik.h
@@ -0,0 +1,116 @@
+/*************************************************************************/
+/* skeleton_modification_2d_ccdik.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATION2DCCDIK_H
+#define SKELETONMODIFICATION2DCCDIK_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+///////////////////////////////////////
+// SkeletonModification2DCCDIK
+///////////////////////////////////////
+
+class SkeletonModification2DCCDIK : public SkeletonModification2D {
+ GDCLASS(SkeletonModification2DCCDIK, SkeletonModification2D);
+
+private:
+ struct CCDIK_Joint_Data2D {
+ int bone_idx = -1;
+ NodePath bone2d_node;
+ ObjectID bone2d_node_cache;
+ bool rotate_from_joint = false;
+
+ bool enable_constraint = false;
+ float constraint_angle_min = 0;
+ float constraint_angle_max = (2.0 * Math_PI);
+ bool constraint_angle_invert = false;
+ bool constraint_in_localspace = true;
+
+ bool editor_draw_gizmo = true;
+ };
+
+ Vector<CCDIK_Joint_Data2D> ccdik_data_chain;
+
+ NodePath target_node;
+ ObjectID target_node_cache;
+ void update_target_cache();
+
+ NodePath tip_node;
+ ObjectID tip_node_cache;
+ void update_tip_cache();
+
+ void ccdik_joint_update_bone2d_cache(int p_joint_idx);
+ void _execute_ccdik_joint(int p_joint_idx, Node2D *p_target, Node2D *p_tip);
+
+protected:
+ static void _bind_methods();
+ bool _set(const StringName &p_path, const Variant &p_value);
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ void _execute(float p_delta) override;
+ void _setup_modification(SkeletonModificationStack2D *p_stack) override;
+ void _draw_editor_gizmo() override;
+
+ void set_target_node(const NodePath &p_target_node);
+ NodePath get_target_node() const;
+ void set_tip_node(const NodePath &p_tip_node);
+ NodePath get_tip_node() const;
+
+ int get_ccdik_data_chain_length();
+ void set_ccdik_data_chain_length(int p_new_length);
+
+ void set_ccdik_joint_bone2d_node(int p_joint_idx, const NodePath &p_target_node);
+ NodePath get_ccdik_joint_bone2d_node(int p_joint_idx) const;
+ void set_ccdik_joint_bone_index(int p_joint_idx, int p_bone_idx);
+ int get_ccdik_joint_bone_index(int p_joint_idx) const;
+
+ void set_ccdik_joint_rotate_from_joint(int p_joint_idx, bool p_rotate_from_joint);
+ bool get_ccdik_joint_rotate_from_joint(int p_joint_idx) const;
+ void set_ccdik_joint_enable_constraint(int p_joint_idx, bool p_constraint);
+ bool get_ccdik_joint_enable_constraint(int p_joint_idx) const;
+ void set_ccdik_joint_constraint_angle_min(int p_joint_idx, float p_angle_min);
+ float get_ccdik_joint_constraint_angle_min(int p_joint_idx) const;
+ void set_ccdik_joint_constraint_angle_max(int p_joint_idx, float p_angle_max);
+ float get_ccdik_joint_constraint_angle_max(int p_joint_idx) const;
+ void set_ccdik_joint_constraint_angle_invert(int p_joint_idx, bool p_invert);
+ bool get_ccdik_joint_constraint_angle_invert(int p_joint_idx) const;
+ void set_ccdik_joint_constraint_in_localspace(int p_joint_idx, bool p_constraint_in_localspace);
+ bool get_ccdik_joint_constraint_in_localspace(int p_joint_idx) const;
+ void set_ccdik_joint_editor_draw_gizmo(int p_joint_idx, bool p_draw_gizmo);
+ bool get_ccdik_joint_editor_draw_gizmo(int p_joint_idx) const;
+
+ SkeletonModification2DCCDIK();
+ ~SkeletonModification2DCCDIK();
+};
+
+#endif // SKELETONMODIFICATION2DCCDIK_H
diff --git a/scene/resources/skeleton_modification_2d_fabrik.cpp b/scene/resources/skeleton_modification_2d_fabrik.cpp
new file mode 100644
index 0000000000..aef852f7e4
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_fabrik.cpp
@@ -0,0 +1,444 @@
+/*************************************************************************/
+/* skeleton_modification_2d_fabrik.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_2d_fabrik.h"
+#include "scene/2d/skeleton_2d.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_settings.h"
+#endif // TOOLS_ENABLED
+
+bool SkeletonModification2DFABRIK::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path.begins_with("joint_data/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, fabrik_data_chain.size(), false);
+
+ if (what == "bone2d_node") {
+ set_fabrik_joint_bone2d_node(which, p_value);
+ } else if (what == "bone_index") {
+ set_fabrik_joint_bone_index(which, p_value);
+ } else if (what == "magnet_position") {
+ set_fabrik_joint_magnet_position(which, p_value);
+ } else if (what == "use_target_rotation") {
+ set_fabrik_joint_use_target_rotation(which, p_value);
+ }
+ }
+
+ return true;
+}
+
+bool SkeletonModification2DFABRIK::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("joint_data/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, fabrik_data_chain.size(), false);
+
+ if (what == "bone2d_node") {
+ r_ret = get_fabrik_joint_bone2d_node(which);
+ } else if (what == "bone_index") {
+ r_ret = get_fabrik_joint_bone_index(which);
+ } else if (what == "magnet_position") {
+ r_ret = get_fabrik_joint_magnet_position(which);
+ } else if (what == "use_target_rotation") {
+ r_ret = get_fabrik_joint_use_target_rotation(which);
+ }
+ return true;
+ }
+ return true;
+}
+
+void SkeletonModification2DFABRIK::_get_property_list(List<PropertyInfo> *p_list) const {
+ for (int i = 0; i < fabrik_data_chain.size(); i++) {
+ String base_string = "joint_data/" + itos(i) + "/";
+
+ p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::NODE_PATH, base_string + "bone2d_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D", PROPERTY_USAGE_DEFAULT));
+
+ if (i > 0) {
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, base_string + "magnet_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+ if (i == fabrik_data_chain.size() - 1) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "use_target_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+ }
+}
+
+void SkeletonModification2DFABRIK::_execute(float p_delta) {
+ ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
+ "Modification is not setup and therefore cannot execute!");
+ if (!enabled) {
+ return;
+ }
+
+ if (target_node_cache.is_null()) {
+ WARN_PRINT_ONCE("Target cache is out of date. Attempting to update...");
+ update_target_cache();
+ return;
+ }
+
+ if (fabrik_data_chain.size() <= 1) {
+ ERR_PRINT_ONCE("FABRIK requires at least two joints to operate! Cannot execute modification!");
+ return;
+ }
+
+ Node2D *target = Object::cast_to<Node2D>(ObjectDB::get_instance(target_node_cache));
+ if (!target || !target->is_inside_tree()) {
+ ERR_PRINT_ONCE("Target node is not in the scene tree. Cannot execute modification!");
+ return;
+ }
+ target_global_pose = target->get_global_transform();
+
+ if (fabrik_data_chain[0].bone2d_node_cache.is_null() && !fabrik_data_chain[0].bone2d_node.is_empty()) {
+ fabrik_joint_update_bone2d_cache(0);
+ WARN_PRINT("Bone2D cache for origin joint is out of date. Updating...");
+ }
+
+ Bone2D *origin_bone2d_node = Object::cast_to<Bone2D>(ObjectDB::get_instance(fabrik_data_chain[0].bone2d_node_cache));
+ if (!origin_bone2d_node || !origin_bone2d_node->is_inside_tree()) {
+ ERR_PRINT_ONCE("Origin joint's Bone2D node is not in the scene tree. Cannot execute modification!");
+ return;
+ }
+
+ origin_global_pose = origin_bone2d_node->get_global_transform();
+
+ if (fabrik_transform_chain.size() != fabrik_data_chain.size()) {
+ fabrik_transform_chain.resize(fabrik_data_chain.size());
+ }
+
+ for (int i = 0; i < fabrik_data_chain.size(); i++) {
+ // Update the transform chain
+ if (fabrik_data_chain[i].bone2d_node_cache.is_null() && !fabrik_data_chain[i].bone2d_node.is_empty()) {
+ WARN_PRINT_ONCE("Bone2D cache for joint " + itos(i) + " is out of date.. Attempting to update...");
+ fabrik_joint_update_bone2d_cache(i);
+ }
+ Bone2D *joint_bone2d_node = Object::cast_to<Bone2D>(ObjectDB::get_instance(fabrik_data_chain[i].bone2d_node_cache));
+ if (!joint_bone2d_node) {
+ ERR_PRINT_ONCE("FABRIK Joint " + itos(i) + " does not have a Bone2D node set! Cannot execute modification!");
+ return;
+ }
+ fabrik_transform_chain.write[i] = joint_bone2d_node->get_global_transform();
+
+ // Apply magnet positions
+ if (i == 0) {
+ continue; // The origin cannot use a magnet position!
+ } else {
+ Transform2D joint_trans = fabrik_transform_chain[i];
+ joint_trans.set_origin(joint_trans.get_origin() + fabrik_data_chain[i].magnet_position);
+ fabrik_transform_chain.write[i] = joint_trans;
+ }
+ }
+
+ Bone2D *final_bone2d_node = Object::cast_to<Bone2D>(ObjectDB::get_instance(fabrik_data_chain[fabrik_data_chain.size() - 1].bone2d_node_cache));
+ float final_bone2d_angle = final_bone2d_node->get_global_transform().get_rotation();
+ if (fabrik_data_chain[fabrik_data_chain.size() - 1].use_target_rotation) {
+ final_bone2d_angle = target_global_pose.get_rotation();
+ }
+ Vector2 final_bone2d_direction = Vector2(Math::cos(final_bone2d_angle), Math::sin(final_bone2d_angle));
+ float final_bone2d_length = final_bone2d_node->get_length() * MIN(final_bone2d_node->get_global_scale().x, final_bone2d_node->get_global_scale().y);
+ float target_distance = (final_bone2d_node->get_global_transform().get_origin() + (final_bone2d_direction * final_bone2d_length)).distance_to(target->get_global_transform().get_origin());
+ chain_iterations = 0;
+
+ while (target_distance > chain_tolarance) {
+ chain_backwards();
+ chain_forwards();
+
+ final_bone2d_angle = final_bone2d_node->get_global_transform().get_rotation();
+ if (fabrik_data_chain[fabrik_data_chain.size() - 1].use_target_rotation) {
+ final_bone2d_angle = target_global_pose.get_rotation();
+ }
+ final_bone2d_direction = Vector2(Math::cos(final_bone2d_angle), Math::sin(final_bone2d_angle));
+ target_distance = (final_bone2d_node->get_global_transform().get_origin() + (final_bone2d_direction * final_bone2d_length)).distance_to(target->get_global_transform().get_origin());
+
+ chain_iterations += 1;
+ if (chain_iterations >= chain_max_iterations) {
+ break;
+ }
+ }
+
+ // Apply all of the saved transforms to the Bone2D nodes
+ for (int i = 0; i < fabrik_data_chain.size(); i++) {
+ Bone2D *joint_bone2d_node = Object::cast_to<Bone2D>(ObjectDB::get_instance(fabrik_data_chain[i].bone2d_node_cache));
+ if (!joint_bone2d_node) {
+ ERR_PRINT_ONCE("FABRIK Joint " + itos(i) + " does not have a Bone2D node set!");
+ continue;
+ }
+ Transform2D chain_trans = fabrik_transform_chain[i];
+
+ // Apply rotation
+ if (i + 1 < fabrik_data_chain.size()) {
+ chain_trans = chain_trans.looking_at(fabrik_transform_chain[i + 1].get_origin());
+ } else {
+ if (fabrik_data_chain[i].use_target_rotation) {
+ chain_trans.set_rotation(target_global_pose.get_rotation());
+ } else {
+ chain_trans = chain_trans.looking_at(target_global_pose.get_origin());
+ }
+ }
+ // Adjust for the bone angle
+ chain_trans.set_rotation(chain_trans.get_rotation() - joint_bone2d_node->get_bone_angle());
+
+ // Reset scale
+ chain_trans.set_scale(joint_bone2d_node->get_global_transform().get_scale());
+
+ // Apply to the bone, and to the override
+ joint_bone2d_node->set_global_transform(chain_trans);
+ stack->skeleton->set_bone_local_pose_override(fabrik_data_chain[i].bone_idx, joint_bone2d_node->get_transform(), stack->strength, true);
+ }
+}
+
+void SkeletonModification2DFABRIK::chain_backwards() {
+ int final_joint_index = fabrik_data_chain.size() - 1;
+ Bone2D *final_bone2d_node = Object::cast_to<Bone2D>(ObjectDB::get_instance(fabrik_data_chain[final_joint_index].bone2d_node_cache));
+ Transform2D final_bone2d_trans = fabrik_transform_chain[final_joint_index];
+
+ // Set the rotation of the tip bone
+ final_bone2d_trans = final_bone2d_trans.looking_at(target_global_pose.get_origin());
+
+ // Set the position of the tip bone
+ float final_bone2d_angle = final_bone2d_trans.get_rotation();
+ if (fabrik_data_chain[final_joint_index].use_target_rotation) {
+ final_bone2d_angle = target_global_pose.get_rotation();
+ }
+ Vector2 final_bone2d_direction = Vector2(Math::cos(final_bone2d_angle), Math::sin(final_bone2d_angle));
+ float final_bone2d_length = final_bone2d_node->get_length() * MIN(final_bone2d_node->get_global_scale().x, final_bone2d_node->get_global_scale().y);
+ final_bone2d_trans.set_origin(target_global_pose.get_origin() - (final_bone2d_direction * final_bone2d_length));
+
+ // Save the transform
+ fabrik_transform_chain.write[final_joint_index] = final_bone2d_trans;
+
+ int i = final_joint_index;
+ while (i >= 1) {
+ Transform2D previous_pose = fabrik_transform_chain[i];
+ i -= 1;
+ Bone2D *current_bone2d_node = Object::cast_to<Bone2D>(ObjectDB::get_instance(fabrik_data_chain[i].bone2d_node_cache));
+ Transform2D current_pose = fabrik_transform_chain[i];
+
+ float current_bone2d_node_length = current_bone2d_node->get_length() * MIN(current_bone2d_node->get_global_scale().x, current_bone2d_node->get_global_scale().y);
+ float length = current_bone2d_node_length / (previous_pose.get_origin() - current_pose.get_origin()).length();
+ Vector2 finish_position = previous_pose.get_origin().lerp(current_pose.get_origin(), length);
+ current_pose.set_origin(finish_position);
+
+ // Save the transform
+ fabrik_transform_chain.write[i] = current_pose;
+ }
+}
+
+void SkeletonModification2DFABRIK::chain_forwards() {
+ Transform2D origin_bone2d_trans = fabrik_transform_chain[0];
+ origin_bone2d_trans.set_origin(origin_global_pose.get_origin());
+ // Save the position
+ fabrik_transform_chain.write[0] = origin_bone2d_trans;
+
+ for (int i = 0; i < fabrik_data_chain.size() - 1; i++) {
+ Bone2D *current_bone2d_node = Object::cast_to<Bone2D>(ObjectDB::get_instance(fabrik_data_chain[i].bone2d_node_cache));
+ Transform2D current_pose = fabrik_transform_chain[i];
+ Transform2D next_pose = fabrik_transform_chain[i + 1];
+
+ float current_bone2d_node_length = current_bone2d_node->get_length() * MIN(current_bone2d_node->get_global_scale().x, current_bone2d_node->get_global_scale().y);
+ float length = current_bone2d_node_length / (current_pose.get_origin() - next_pose.get_origin()).length();
+ Vector2 finish_position = current_pose.get_origin().lerp(next_pose.get_origin(), length);
+ current_pose.set_origin(finish_position);
+
+ // Apply to the bone
+ fabrik_transform_chain.write[i + 1] = current_pose;
+ }
+}
+
+void SkeletonModification2DFABRIK::_setup_modification(SkeletonModificationStack2D *p_stack) {
+ stack = p_stack;
+
+ if (stack != nullptr) {
+ is_setup = true;
+ update_target_cache();
+ }
+}
+
+void SkeletonModification2DFABRIK::update_target_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ return;
+ }
+
+ target_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(target_node)) {
+ Node *node = stack->skeleton->get_node(target_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update target cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update target cache: node is not in scene tree!");
+ target_node_cache = node->get_instance_id();
+ }
+ }
+ }
+}
+
+void SkeletonModification2DFABRIK::fabrik_joint_update_bone2d_cache(int p_joint_idx) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, fabrik_data_chain.size(), "Cannot update bone2d cache: joint index out of range!");
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update FABRIK Bone2D cache: modification is not properly setup!");
+ return;
+ }
+
+ fabrik_data_chain.write[p_joint_idx].bone2d_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(fabrik_data_chain[p_joint_idx].bone2d_node)) {
+ Node *node = stack->skeleton->get_node(fabrik_data_chain[p_joint_idx].bone2d_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update FABRIK joint " + itos(p_joint_idx) + " Bone2D cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update FABRIK joint " + itos(p_joint_idx) + " Bone2D cache: node is not in scene tree!");
+ fabrik_data_chain.write[p_joint_idx].bone2d_node_cache = node->get_instance_id();
+
+ Bone2D *bone = Object::cast_to<Bone2D>(node);
+ if (bone) {
+ fabrik_data_chain.write[p_joint_idx].bone_idx = bone->get_index_in_skeleton();
+ } else {
+ ERR_FAIL_MSG("FABRIK joint " + itos(p_joint_idx) + " Bone2D cache: Nodepath to Bone2D is not a Bone2D node!");
+ }
+ }
+ }
+ }
+}
+
+void SkeletonModification2DFABRIK::set_target_node(const NodePath &p_target_node) {
+ target_node = p_target_node;
+ update_target_cache();
+}
+
+NodePath SkeletonModification2DFABRIK::get_target_node() const {
+ return target_node;
+}
+
+void SkeletonModification2DFABRIK::set_fabrik_data_chain_length(int p_length) {
+ fabrik_data_chain.resize(p_length);
+ notify_property_list_changed();
+}
+
+int SkeletonModification2DFABRIK::get_fabrik_data_chain_length() {
+ return fabrik_data_chain.size();
+}
+
+void SkeletonModification2DFABRIK::set_fabrik_joint_bone2d_node(int p_joint_idx, const NodePath &p_target_node) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, fabrik_data_chain.size(), "FABRIK joint out of range!");
+ fabrik_data_chain.write[p_joint_idx].bone2d_node = p_target_node;
+ fabrik_joint_update_bone2d_cache(p_joint_idx);
+
+ notify_property_list_changed();
+}
+
+NodePath SkeletonModification2DFABRIK::get_fabrik_joint_bone2d_node(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, fabrik_data_chain.size(), NodePath(), "FABRIK joint out of range!");
+ return fabrik_data_chain[p_joint_idx].bone2d_node;
+}
+
+void SkeletonModification2DFABRIK::set_fabrik_joint_bone_index(int p_joint_idx, int p_bone_idx) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, fabrik_data_chain.size(), "FABRIK joint out of range!");
+ ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
+
+ if (is_setup) {
+ if (stack->skeleton) {
+ ERR_FAIL_INDEX_MSG(p_bone_idx, stack->skeleton->get_bone_count(), "Passed-in Bone index is out of range!");
+ fabrik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ fabrik_data_chain.write[p_joint_idx].bone2d_node_cache = stack->skeleton->get_bone(p_bone_idx)->get_instance_id();
+ fabrik_data_chain.write[p_joint_idx].bone2d_node = stack->skeleton->get_path_to(stack->skeleton->get_bone(p_bone_idx));
+ } else {
+ WARN_PRINT("Cannot verify the FABRIK joint " + itos(p_joint_idx) + " bone index for this modification...");
+ fabrik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ }
+ } else {
+ WARN_PRINT("Cannot verify the FABRIK joint " + itos(p_joint_idx) + " bone index for this modification...");
+ fabrik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ }
+
+ notify_property_list_changed();
+}
+
+int SkeletonModification2DFABRIK::get_fabrik_joint_bone_index(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, fabrik_data_chain.size(), -1, "FABRIK joint out of range!");
+ return fabrik_data_chain[p_joint_idx].bone_idx;
+}
+
+void SkeletonModification2DFABRIK::set_fabrik_joint_magnet_position(int p_joint_idx, Vector2 p_magnet_position) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, fabrik_data_chain.size(), "FABRIK joint out of range!");
+ fabrik_data_chain.write[p_joint_idx].magnet_position = p_magnet_position;
+}
+
+Vector2 SkeletonModification2DFABRIK::get_fabrik_joint_magnet_position(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, fabrik_data_chain.size(), Vector2(), "FABRIK joint out of range!");
+ return fabrik_data_chain[p_joint_idx].magnet_position;
+}
+
+void SkeletonModification2DFABRIK::set_fabrik_joint_use_target_rotation(int p_joint_idx, bool p_use_target_rotation) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, fabrik_data_chain.size(), "FABRIK joint out of range!");
+ fabrik_data_chain.write[p_joint_idx].use_target_rotation = p_use_target_rotation;
+}
+
+bool SkeletonModification2DFABRIK::get_fabrik_joint_use_target_rotation(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, fabrik_data_chain.size(), false, "FABRIK joint out of range!");
+ return fabrik_data_chain[p_joint_idx].use_target_rotation;
+}
+
+void SkeletonModification2DFABRIK::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification2DFABRIK::set_target_node);
+ ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification2DFABRIK::get_target_node);
+
+ ClassDB::bind_method(D_METHOD("set_fabrik_data_chain_length", "length"), &SkeletonModification2DFABRIK::set_fabrik_data_chain_length);
+ ClassDB::bind_method(D_METHOD("get_fabrik_data_chain_length"), &SkeletonModification2DFABRIK::get_fabrik_data_chain_length);
+
+ ClassDB::bind_method(D_METHOD("set_fabrik_joint_bone2d_node", "joint_idx", "bone2d_nodepath"), &SkeletonModification2DFABRIK::set_fabrik_joint_bone2d_node);
+ ClassDB::bind_method(D_METHOD("get_fabrik_joint_bone2d_node", "joint_idx"), &SkeletonModification2DFABRIK::get_fabrik_joint_bone2d_node);
+ ClassDB::bind_method(D_METHOD("set_fabrik_joint_bone_index", "joint_idx", "bone_idx"), &SkeletonModification2DFABRIK::set_fabrik_joint_bone_index);
+ ClassDB::bind_method(D_METHOD("get_fabrik_joint_bone_index", "joint_idx"), &SkeletonModification2DFABRIK::get_fabrik_joint_bone_index);
+ ClassDB::bind_method(D_METHOD("set_fabrik_joint_magnet_position", "joint_idx", "magnet_position"), &SkeletonModification2DFABRIK::set_fabrik_joint_magnet_position);
+ ClassDB::bind_method(D_METHOD("get_fabrik_joint_magnet_position", "joint_idx"), &SkeletonModification2DFABRIK::get_fabrik_joint_magnet_position);
+ ClassDB::bind_method(D_METHOD("set_fabrik_joint_use_target_rotation", "joint_idx", "use_target_rotation"), &SkeletonModification2DFABRIK::set_fabrik_joint_use_target_rotation);
+ ClassDB::bind_method(D_METHOD("get_fabrik_joint_use_target_rotation", "joint_idx"), &SkeletonModification2DFABRIK::get_fabrik_joint_use_target_rotation);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D"), "set_target_node", "get_target_node");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "fabrik_data_chain_length", PROPERTY_HINT_RANGE, "0, 100, 1"), "set_fabrik_data_chain_length", "get_fabrik_data_chain_length");
+}
+
+SkeletonModification2DFABRIK::SkeletonModification2DFABRIK() {
+ stack = nullptr;
+ is_setup = false;
+ enabled = true;
+ editor_draw_gizmo = false;
+}
+
+SkeletonModification2DFABRIK::~SkeletonModification2DFABRIK() {
+}
diff --git a/scene/resources/skeleton_modification_2d_fabrik.h b/scene/resources/skeleton_modification_2d_fabrik.h
new file mode 100644
index 0000000000..79e0106e26
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_fabrik.h
@@ -0,0 +1,108 @@
+/*************************************************************************/
+/* skeleton_modification_2d_fabrik.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATION2DFABRIK_H
+#define SKELETONMODIFICATION2DFABRIK_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+///////////////////////////////////////
+// SkeletonModification2DFABRIK
+///////////////////////////////////////
+
+class SkeletonModification2DFABRIK : public SkeletonModification2D {
+ GDCLASS(SkeletonModification2DFABRIK, SkeletonModification2D);
+
+private:
+ struct FABRIK_Joint_Data2D {
+ int bone_idx = -1;
+ NodePath bone2d_node;
+ ObjectID bone2d_node_cache;
+
+ Vector2 magnet_position = Vector2(0, 0);
+ bool use_target_rotation = false;
+
+ bool editor_draw_gizmo = true;
+ };
+
+ Vector<FABRIK_Joint_Data2D> fabrik_data_chain;
+
+ // Unlike in 3D, we need a vector of Transform2D objects to perform FABRIK.
+ // This is because FABRIK (unlike CCDIK) needs to operate on transforms that are NOT
+ // affected by each other, making the transforms stored in Bone2D unusable, as well as those in Skeleton2D.
+ // For this reason, this modification stores a vector of Transform2Ds used for the calculations, which are then applied at the end.
+ Vector<Transform2D> fabrik_transform_chain;
+
+ NodePath target_node;
+ ObjectID target_node_cache;
+ void update_target_cache();
+
+ float chain_tolarance = 0.01;
+ int chain_max_iterations = 10;
+ int chain_iterations = 0;
+ Transform2D target_global_pose = Transform2D();
+ Transform2D origin_global_pose = Transform2D();
+
+ void fabrik_joint_update_bone2d_cache(int p_joint_idx);
+ void chain_backwards();
+ void chain_forwards();
+
+protected:
+ static void _bind_methods();
+ bool _set(const StringName &p_path, const Variant &p_value);
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ void _execute(float p_delta) override;
+ void _setup_modification(SkeletonModificationStack2D *p_stack) override;
+
+ void set_target_node(const NodePath &p_target_node);
+ NodePath get_target_node() const;
+
+ int get_fabrik_data_chain_length();
+ void set_fabrik_data_chain_length(int p_new_length);
+
+ void set_fabrik_joint_bone2d_node(int p_joint_idx, const NodePath &p_target_node);
+ NodePath get_fabrik_joint_bone2d_node(int p_joint_idx) const;
+ void set_fabrik_joint_bone_index(int p_joint_idx, int p_bone_idx);
+ int get_fabrik_joint_bone_index(int p_joint_idx) const;
+
+ void set_fabrik_joint_magnet_position(int p_joint_idx, Vector2 p_magnet_position);
+ Vector2 get_fabrik_joint_magnet_position(int p_joint_idx) const;
+ void set_fabrik_joint_use_target_rotation(int p_joint_idx, bool p_use_target_rotation);
+ bool get_fabrik_joint_use_target_rotation(int p_joint_idx) const;
+
+ SkeletonModification2DFABRIK();
+ ~SkeletonModification2DFABRIK();
+};
+
+#endif // SKELETONMODIFICATION2DFABRIK_H
diff --git a/scene/resources/skeleton_modification_2d_jiggle.cpp b/scene/resources/skeleton_modification_2d_jiggle.cpp
new file mode 100644
index 0000000000..2547083336
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_jiggle.cpp
@@ -0,0 +1,564 @@
+/*************************************************************************/
+/* skeleton_modification_2d_jiggle.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_2d_jiggle.h"
+#include "scene/2d/skeleton_2d.h"
+
+bool SkeletonModification2DJiggle::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path.begins_with("joint_data/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, jiggle_data_chain.size(), false);
+
+ if (what == "bone2d_node") {
+ set_jiggle_joint_bone2d_node(which, p_value);
+ } else if (what == "bone_index") {
+ set_jiggle_joint_bone_index(which, p_value);
+ } else if (what == "override_defaults") {
+ set_jiggle_joint_override(which, p_value);
+ } else if (what == "stiffness") {
+ set_jiggle_joint_stiffness(which, p_value);
+ } else if (what == "mass") {
+ set_jiggle_joint_mass(which, p_value);
+ } else if (what == "damping") {
+ set_jiggle_joint_damping(which, p_value);
+ } else if (what == "use_gravity") {
+ set_jiggle_joint_use_gravity(which, p_value);
+ } else if (what == "gravity") {
+ set_jiggle_joint_gravity(which, p_value);
+ }
+ return true;
+ } else {
+ if (path == "use_colliders") {
+ set_use_colliders(p_value);
+ } else if (path == "collision_mask") {
+ set_collision_mask(p_value);
+ }
+ }
+ return true;
+}
+
+bool SkeletonModification2DJiggle::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("joint_data/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, jiggle_data_chain.size(), false);
+
+ if (what == "bone2d_node") {
+ r_ret = get_jiggle_joint_bone2d_node(which);
+ } else if (what == "bone_index") {
+ r_ret = get_jiggle_joint_bone_index(which);
+ } else if (what == "override_defaults") {
+ r_ret = get_jiggle_joint_override(which);
+ } else if (what == "stiffness") {
+ r_ret = get_jiggle_joint_stiffness(which);
+ } else if (what == "mass") {
+ r_ret = get_jiggle_joint_mass(which);
+ } else if (what == "damping") {
+ r_ret = get_jiggle_joint_damping(which);
+ } else if (what == "use_gravity") {
+ r_ret = get_jiggle_joint_use_gravity(which);
+ } else if (what == "gravity") {
+ r_ret = get_jiggle_joint_gravity(which);
+ }
+ return true;
+ } else {
+ if (path == "use_colliders") {
+ r_ret = get_use_colliders();
+ } else if (path == "collision_mask") {
+ r_ret = get_collision_mask();
+ }
+ }
+ return true;
+}
+
+void SkeletonModification2DJiggle::_get_property_list(List<PropertyInfo> *p_list) const {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "use_colliders", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ if (use_colliders) {
+ p_list->push_back(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS, "", PROPERTY_USAGE_DEFAULT));
+ }
+
+ for (int i = 0; i < jiggle_data_chain.size(); i++) {
+ String base_string = "joint_data/" + itos(i) + "/";
+
+ p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::NODE_PATH, base_string + "bone2d_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "override_defaults", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+
+ if (jiggle_data_chain[i].override_defaults) {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "stiffness", PROPERTY_HINT_RANGE, "0, 1000, 0.01", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "mass", PROPERTY_HINT_RANGE, "0, 1000, 0.01", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "damping", PROPERTY_HINT_RANGE, "0, 1, 0.01", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "use_gravity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ if (jiggle_data_chain[i].use_gravity) {
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, base_string + "gravity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+ }
+ }
+}
+
+void SkeletonModification2DJiggle::_execute(float p_delta) {
+ ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
+ "Modification is not setup and therefore cannot execute!");
+ if (!enabled) {
+ return;
+ }
+ if (target_node_cache.is_null()) {
+ WARN_PRINT_ONCE("Target cache is out of date. Attempting to update...");
+ update_target_cache();
+ return;
+ }
+ Node2D *target = Object::cast_to<Node2D>(ObjectDB::get_instance(target_node_cache));
+ if (!target || !target->is_inside_tree()) {
+ ERR_PRINT_ONCE("Target node is not in the scene tree. Cannot execute modification!");
+ return;
+ }
+
+ for (int i = 0; i < jiggle_data_chain.size(); i++) {
+ _execute_jiggle_joint(i, target, p_delta);
+ }
+}
+
+void SkeletonModification2DJiggle::_execute_jiggle_joint(int p_joint_idx, Node2D *p_target, float p_delta) {
+ // Adopted from: https://wiki.unity3d.com/index.php/JiggleBone
+ // With modifications by TwistedTwigleg.
+
+ if (jiggle_data_chain[p_joint_idx].bone_idx <= -1 || jiggle_data_chain[p_joint_idx].bone_idx > stack->skeleton->get_bone_count()) {
+ ERR_PRINT_ONCE("Jiggle joint " + itos(p_joint_idx) + " bone index is invalid. Cannot execute modification on joint...");
+ return;
+ }
+
+ if (jiggle_data_chain[p_joint_idx].bone2d_node_cache.is_null() && !jiggle_data_chain[p_joint_idx].bone2d_node.is_empty()) {
+ WARN_PRINT_ONCE("Bone2D cache for joint " + itos(p_joint_idx) + " is out of date. Updating...");
+ jiggle_joint_update_bone2d_cache(p_joint_idx);
+ }
+
+ Bone2D *operation_bone = stack->skeleton->get_bone(jiggle_data_chain[p_joint_idx].bone_idx);
+ if (!operation_bone) {
+ ERR_PRINT_ONCE("Jiggle joint " + itos(p_joint_idx) + " does not have a Bone2D node or it cannot be found!");
+ return;
+ }
+
+ Transform2D operation_bone_trans = operation_bone->get_global_transform();
+ Vector2 target_position = p_target->get_global_transform().get_origin();
+
+ jiggle_data_chain.write[p_joint_idx].force = (target_position - jiggle_data_chain[p_joint_idx].dynamic_position) * jiggle_data_chain[p_joint_idx].stiffness * p_delta;
+
+ if (jiggle_data_chain[p_joint_idx].use_gravity) {
+ jiggle_data_chain.write[p_joint_idx].force += jiggle_data_chain[p_joint_idx].gravity * p_delta;
+ }
+
+ jiggle_data_chain.write[p_joint_idx].acceleration = jiggle_data_chain[p_joint_idx].force / jiggle_data_chain[p_joint_idx].mass;
+ jiggle_data_chain.write[p_joint_idx].velocity += jiggle_data_chain[p_joint_idx].acceleration * (1 - jiggle_data_chain[p_joint_idx].damping);
+
+ jiggle_data_chain.write[p_joint_idx].dynamic_position += jiggle_data_chain[p_joint_idx].velocity + jiggle_data_chain[p_joint_idx].force;
+ jiggle_data_chain.write[p_joint_idx].dynamic_position += operation_bone_trans.get_origin() - jiggle_data_chain[p_joint_idx].last_position;
+ jiggle_data_chain.write[p_joint_idx].last_position = operation_bone_trans.get_origin();
+
+ // Collision detection/response
+ if (use_colliders) {
+ if (execution_mode == SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_physics_process) {
+ Ref<World2D> world_2d = stack->skeleton->get_world_2d();
+ ERR_FAIL_COND(world_2d.is_null());
+ PhysicsDirectSpaceState2D *space_state = PhysicsServer2D::get_singleton()->space_get_direct_state(world_2d->get_space());
+ PhysicsDirectSpaceState2D::RayResult ray_result;
+
+ // Add exception support?
+ bool ray_hit = space_state->intersect_ray(operation_bone_trans.get_origin(), jiggle_data_chain[p_joint_idx].dynamic_position,
+ ray_result, Set<RID>(), collision_mask);
+
+ if (ray_hit) {
+ jiggle_data_chain.write[p_joint_idx].dynamic_position = jiggle_data_chain[p_joint_idx].last_noncollision_position;
+ jiggle_data_chain.write[p_joint_idx].acceleration = Vector2(0, 0);
+ jiggle_data_chain.write[p_joint_idx].velocity = Vector2(0, 0);
+ } else {
+ jiggle_data_chain.write[p_joint_idx].last_noncollision_position = jiggle_data_chain[p_joint_idx].dynamic_position;
+ }
+ } else {
+ WARN_PRINT_ONCE("Jiggle 2D modifier: You cannot detect colliders without the stack mode being set to _physics_process!");
+ }
+ }
+
+ // Rotate the bone using the dynamic position!
+ operation_bone_trans = operation_bone_trans.looking_at(jiggle_data_chain[p_joint_idx].dynamic_position);
+ operation_bone_trans.set_rotation(operation_bone_trans.get_rotation() - operation_bone->get_bone_angle());
+
+ // Reset scale
+ operation_bone_trans.set_scale(operation_bone->get_global_transform().get_scale());
+
+ operation_bone->set_global_transform(operation_bone_trans);
+ stack->skeleton->set_bone_local_pose_override(jiggle_data_chain[p_joint_idx].bone_idx, operation_bone->get_transform(), stack->strength, true);
+}
+
+void SkeletonModification2DJiggle::_update_jiggle_joint_data() {
+ for (int i = 0; i < jiggle_data_chain.size(); i++) {
+ if (!jiggle_data_chain[i].override_defaults) {
+ set_jiggle_joint_stiffness(i, stiffness);
+ set_jiggle_joint_mass(i, mass);
+ set_jiggle_joint_damping(i, damping);
+ set_jiggle_joint_use_gravity(i, use_gravity);
+ set_jiggle_joint_gravity(i, gravity);
+ }
+ }
+}
+
+void SkeletonModification2DJiggle::_setup_modification(SkeletonModificationStack2D *p_stack) {
+ stack = p_stack;
+
+ if (stack) {
+ is_setup = true;
+
+ if (stack->skeleton) {
+ for (int i = 0; i < jiggle_data_chain.size(); i++) {
+ int bone_idx = jiggle_data_chain[i].bone_idx;
+ if (bone_idx > 0 && bone_idx < stack->skeleton->get_bone_count()) {
+ Bone2D *bone2d_node = stack->skeleton->get_bone(bone_idx);
+ jiggle_data_chain.write[i].dynamic_position = bone2d_node->get_global_transform().get_origin();
+ }
+ }
+ }
+
+ update_target_cache();
+ }
+}
+
+void SkeletonModification2DJiggle::update_target_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ return;
+ }
+
+ target_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(target_node)) {
+ Node *node = stack->skeleton->get_node(target_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update target cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update target cache: node is not in scene tree!");
+ target_node_cache = node->get_instance_id();
+ }
+ }
+ }
+}
+
+void SkeletonModification2DJiggle::jiggle_joint_update_bone2d_cache(int p_joint_idx) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, jiggle_data_chain.size(), "Cannot update bone2d cache: joint index out of range!");
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update Jiggle " + itos(p_joint_idx) + " Bone2D cache: modification is not properly setup!");
+ return;
+ }
+
+ jiggle_data_chain.write[p_joint_idx].bone2d_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(jiggle_data_chain[p_joint_idx].bone2d_node)) {
+ Node *node = stack->skeleton->get_node(jiggle_data_chain[p_joint_idx].bone2d_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update Jiggle joint " + itos(p_joint_idx) + " Bone2D cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update Jiggle joint " + itos(p_joint_idx) + " Bone2D cache: node is not in scene tree!");
+ jiggle_data_chain.write[p_joint_idx].bone2d_node_cache = node->get_instance_id();
+
+ Bone2D *bone = Object::cast_to<Bone2D>(node);
+ if (bone) {
+ jiggle_data_chain.write[p_joint_idx].bone_idx = bone->get_index_in_skeleton();
+ } else {
+ ERR_FAIL_MSG("Jiggle joint " + itos(p_joint_idx) + " Bone2D cache: Nodepath to Bone2D is not a Bone2D node!");
+ }
+ }
+ }
+ }
+}
+
+void SkeletonModification2DJiggle::set_target_node(const NodePath &p_target_node) {
+ target_node = p_target_node;
+ update_target_cache();
+}
+
+NodePath SkeletonModification2DJiggle::get_target_node() const {
+ return target_node;
+}
+
+void SkeletonModification2DJiggle::set_stiffness(float p_stiffness) {
+ ERR_FAIL_COND_MSG(p_stiffness < 0, "Stiffness cannot be set to a negative value!");
+ stiffness = p_stiffness;
+ _update_jiggle_joint_data();
+}
+
+float SkeletonModification2DJiggle::get_stiffness() const {
+ return stiffness;
+}
+
+void SkeletonModification2DJiggle::set_mass(float p_mass) {
+ ERR_FAIL_COND_MSG(p_mass < 0, "Mass cannot be set to a negative value!");
+ mass = p_mass;
+ _update_jiggle_joint_data();
+}
+
+float SkeletonModification2DJiggle::get_mass() const {
+ return mass;
+}
+
+void SkeletonModification2DJiggle::set_damping(float p_damping) {
+ ERR_FAIL_COND_MSG(p_damping < 0, "Damping cannot be set to a negative value!");
+ ERR_FAIL_COND_MSG(p_damping > 1, "Damping cannot be more than one!");
+ damping = p_damping;
+ _update_jiggle_joint_data();
+}
+
+float SkeletonModification2DJiggle::get_damping() const {
+ return damping;
+}
+
+void SkeletonModification2DJiggle::set_use_gravity(bool p_use_gravity) {
+ use_gravity = p_use_gravity;
+ _update_jiggle_joint_data();
+}
+
+bool SkeletonModification2DJiggle::get_use_gravity() const {
+ return use_gravity;
+}
+
+void SkeletonModification2DJiggle::set_gravity(Vector2 p_gravity) {
+ gravity = p_gravity;
+ _update_jiggle_joint_data();
+}
+
+Vector2 SkeletonModification2DJiggle::get_gravity() const {
+ return gravity;
+}
+
+void SkeletonModification2DJiggle::set_use_colliders(bool p_use_colliders) {
+ use_colliders = p_use_colliders;
+ notify_property_list_changed();
+}
+
+bool SkeletonModification2DJiggle::get_use_colliders() const {
+ return use_colliders;
+}
+
+void SkeletonModification2DJiggle::set_collision_mask(int p_mask) {
+ collision_mask = p_mask;
+}
+
+int SkeletonModification2DJiggle::get_collision_mask() const {
+ return collision_mask;
+}
+
+// Jiggle joint data functions
+int SkeletonModification2DJiggle::get_jiggle_data_chain_length() {
+ return jiggle_data_chain.size();
+}
+
+void SkeletonModification2DJiggle::set_jiggle_data_chain_length(int p_length) {
+ ERR_FAIL_COND(p_length < 0);
+ jiggle_data_chain.resize(p_length);
+ notify_property_list_changed();
+}
+
+void SkeletonModification2DJiggle::set_jiggle_joint_bone2d_node(int p_joint_idx, const NodePath &p_target_node) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, jiggle_data_chain.size(), "Jiggle joint out of range!");
+ jiggle_data_chain.write[p_joint_idx].bone2d_node = p_target_node;
+ jiggle_joint_update_bone2d_cache(p_joint_idx);
+
+ notify_property_list_changed();
+}
+
+NodePath SkeletonModification2DJiggle::get_jiggle_joint_bone2d_node(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, jiggle_data_chain.size(), NodePath(), "Jiggle joint out of range!");
+ return jiggle_data_chain[p_joint_idx].bone2d_node;
+}
+
+void SkeletonModification2DJiggle::set_jiggle_joint_bone_index(int p_joint_idx, int p_bone_idx) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, jiggle_data_chain.size(), "Jiggle joint out of range!");
+ ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
+
+ if (is_setup) {
+ if (stack->skeleton) {
+ ERR_FAIL_INDEX_MSG(p_bone_idx, stack->skeleton->get_bone_count(), "Passed-in Bone index is out of range!");
+ jiggle_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ jiggle_data_chain.write[p_joint_idx].bone2d_node_cache = stack->skeleton->get_bone(p_bone_idx)->get_instance_id();
+ jiggle_data_chain.write[p_joint_idx].bone2d_node = stack->skeleton->get_path_to(stack->skeleton->get_bone(p_bone_idx));
+ } else {
+ WARN_PRINT("Cannot verify the Jiggle joint " + itos(p_joint_idx) + " bone index for this modification...");
+ jiggle_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ }
+ } else {
+ WARN_PRINT("Cannot verify the Jiggle joint " + itos(p_joint_idx) + " bone index for this modification...");
+ jiggle_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
+ }
+
+ notify_property_list_changed();
+}
+
+int SkeletonModification2DJiggle::get_jiggle_joint_bone_index(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, jiggle_data_chain.size(), -1, "Jiggle joint out of range!");
+ return jiggle_data_chain[p_joint_idx].bone_idx;
+}
+
+void SkeletonModification2DJiggle::set_jiggle_joint_override(int p_joint_idx, bool p_override) {
+ ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size());
+ jiggle_data_chain.write[p_joint_idx].override_defaults = p_override;
+ _update_jiggle_joint_data();
+ notify_property_list_changed();
+}
+
+bool SkeletonModification2DJiggle::get_jiggle_joint_override(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), false);
+ return jiggle_data_chain[p_joint_idx].override_defaults;
+}
+
+void SkeletonModification2DJiggle::set_jiggle_joint_stiffness(int p_joint_idx, float p_stiffness) {
+ ERR_FAIL_COND_MSG(p_stiffness < 0, "Stiffness cannot be set to a negative value!");
+ ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size());
+ jiggle_data_chain.write[p_joint_idx].stiffness = p_stiffness;
+}
+
+float SkeletonModification2DJiggle::get_jiggle_joint_stiffness(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), -1);
+ return jiggle_data_chain[p_joint_idx].stiffness;
+}
+
+void SkeletonModification2DJiggle::set_jiggle_joint_mass(int p_joint_idx, float p_mass) {
+ ERR_FAIL_COND_MSG(p_mass < 0, "Mass cannot be set to a negative value!");
+ ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size());
+ jiggle_data_chain.write[p_joint_idx].mass = p_mass;
+}
+
+float SkeletonModification2DJiggle::get_jiggle_joint_mass(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), -1);
+ return jiggle_data_chain[p_joint_idx].mass;
+}
+
+void SkeletonModification2DJiggle::set_jiggle_joint_damping(int p_joint_idx, float p_damping) {
+ ERR_FAIL_COND_MSG(p_damping < 0, "Damping cannot be set to a negative value!");
+ ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size());
+ jiggle_data_chain.write[p_joint_idx].damping = p_damping;
+}
+
+float SkeletonModification2DJiggle::get_jiggle_joint_damping(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), -1);
+ return jiggle_data_chain[p_joint_idx].damping;
+}
+
+void SkeletonModification2DJiggle::set_jiggle_joint_use_gravity(int p_joint_idx, bool p_use_gravity) {
+ ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size());
+ jiggle_data_chain.write[p_joint_idx].use_gravity = p_use_gravity;
+ notify_property_list_changed();
+}
+
+bool SkeletonModification2DJiggle::get_jiggle_joint_use_gravity(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), false);
+ return jiggle_data_chain[p_joint_idx].use_gravity;
+}
+
+void SkeletonModification2DJiggle::set_jiggle_joint_gravity(int p_joint_idx, Vector2 p_gravity) {
+ ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size());
+ jiggle_data_chain.write[p_joint_idx].gravity = p_gravity;
+}
+
+Vector2 SkeletonModification2DJiggle::get_jiggle_joint_gravity(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), Vector2(0, 0));
+ return jiggle_data_chain[p_joint_idx].gravity;
+}
+
+void SkeletonModification2DJiggle::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification2DJiggle::set_target_node);
+ ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification2DJiggle::get_target_node);
+
+ ClassDB::bind_method(D_METHOD("set_jiggle_data_chain_length", "length"), &SkeletonModification2DJiggle::set_jiggle_data_chain_length);
+ ClassDB::bind_method(D_METHOD("get_jiggle_data_chain_length"), &SkeletonModification2DJiggle::get_jiggle_data_chain_length);
+
+ ClassDB::bind_method(D_METHOD("set_stiffness", "stiffness"), &SkeletonModification2DJiggle::set_stiffness);
+ ClassDB::bind_method(D_METHOD("get_stiffness"), &SkeletonModification2DJiggle::get_stiffness);
+ ClassDB::bind_method(D_METHOD("set_mass", "mass"), &SkeletonModification2DJiggle::set_mass);
+ ClassDB::bind_method(D_METHOD("get_mass"), &SkeletonModification2DJiggle::get_mass);
+ ClassDB::bind_method(D_METHOD("set_damping", "damping"), &SkeletonModification2DJiggle::set_damping);
+ ClassDB::bind_method(D_METHOD("get_damping"), &SkeletonModification2DJiggle::get_damping);
+ ClassDB::bind_method(D_METHOD("set_use_gravity", "use_gravity"), &SkeletonModification2DJiggle::set_use_gravity);
+ ClassDB::bind_method(D_METHOD("get_use_gravity"), &SkeletonModification2DJiggle::get_use_gravity);
+ ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &SkeletonModification2DJiggle::set_gravity);
+ ClassDB::bind_method(D_METHOD("get_gravity"), &SkeletonModification2DJiggle::get_gravity);
+
+ ClassDB::bind_method(D_METHOD("set_use_colliders", "use_colliders"), &SkeletonModification2DJiggle::set_use_colliders);
+ ClassDB::bind_method(D_METHOD("get_use_colliders"), &SkeletonModification2DJiggle::get_use_colliders);
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SkeletonModification2DJiggle::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &SkeletonModification2DJiggle::get_collision_mask);
+
+ // Jiggle joint data functions
+ ClassDB::bind_method(D_METHOD("set_jiggle_joint_bone2d_node", "joint_idx", "bone2d_node"), &SkeletonModification2DJiggle::set_jiggle_joint_bone2d_node);
+ ClassDB::bind_method(D_METHOD("get_jiggle_joint_bone2d_node", "joint_idx"), &SkeletonModification2DJiggle::get_jiggle_joint_bone2d_node);
+ ClassDB::bind_method(D_METHOD("set_jiggle_joint_bone_index", "joint_idx", "bone_idx"), &SkeletonModification2DJiggle::set_jiggle_joint_bone_index);
+ ClassDB::bind_method(D_METHOD("get_jiggle_joint_bone_index", "joint_idx"), &SkeletonModification2DJiggle::get_jiggle_joint_bone_index);
+ ClassDB::bind_method(D_METHOD("set_jiggle_joint_override", "joint_idx", "override"), &SkeletonModification2DJiggle::set_jiggle_joint_override);
+ ClassDB::bind_method(D_METHOD("get_jiggle_joint_override", "joint_idx"), &SkeletonModification2DJiggle::get_jiggle_joint_override);
+ ClassDB::bind_method(D_METHOD("set_jiggle_joint_stiffness", "joint_idx", "stiffness"), &SkeletonModification2DJiggle::set_jiggle_joint_stiffness);
+ ClassDB::bind_method(D_METHOD("get_jiggle_joint_stiffness", "joint_idx"), &SkeletonModification2DJiggle::get_jiggle_joint_stiffness);
+ ClassDB::bind_method(D_METHOD("set_jiggle_joint_mass", "joint_idx", "mass"), &SkeletonModification2DJiggle::set_jiggle_joint_mass);
+ ClassDB::bind_method(D_METHOD("get_jiggle_joint_mass", "joint_idx"), &SkeletonModification2DJiggle::get_jiggle_joint_mass);
+ ClassDB::bind_method(D_METHOD("set_jiggle_joint_damping", "joint_idx", "damping"), &SkeletonModification2DJiggle::set_jiggle_joint_damping);
+ ClassDB::bind_method(D_METHOD("get_jiggle_joint_damping", "joint_idx"), &SkeletonModification2DJiggle::get_jiggle_joint_damping);
+ ClassDB::bind_method(D_METHOD("set_jiggle_joint_use_gravity", "joint_idx", "use_gravity"), &SkeletonModification2DJiggle::set_jiggle_joint_use_gravity);
+ ClassDB::bind_method(D_METHOD("get_jiggle_joint_use_gravity", "joint_idx"), &SkeletonModification2DJiggle::get_jiggle_joint_use_gravity);
+ ClassDB::bind_method(D_METHOD("set_jiggle_joint_gravity", "joint_idx", "gravity"), &SkeletonModification2DJiggle::set_jiggle_joint_gravity);
+ ClassDB::bind_method(D_METHOD("get_jiggle_joint_gravity", "joint_idx"), &SkeletonModification2DJiggle::get_jiggle_joint_gravity);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D"), "set_target_node", "get_target_node");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "jiggle_data_chain_length", PROPERTY_HINT_RANGE, "0,100,1"), "set_jiggle_data_chain_length", "get_jiggle_data_chain_length");
+ ADD_GROUP("Default Joint Settings", "");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness"), "set_stiffness", "get_stiffness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0, 1, 0.01"), "set_damping", "get_damping");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_gravity"), "set_use_gravity", "get_use_gravity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity"), "set_gravity", "get_gravity");
+ ADD_GROUP("", "");
+}
+
+SkeletonModification2DJiggle::SkeletonModification2DJiggle() {
+ stack = nullptr;
+ is_setup = false;
+ jiggle_data_chain = Vector<Jiggle_Joint_Data2D>();
+ stiffness = 3;
+ mass = 0.75;
+ damping = 0.75;
+ use_gravity = false;
+ gravity = Vector2(0, 6.0);
+ enabled = true;
+ editor_draw_gizmo = false; // Nothing to really show in a gizmo right now.
+}
+
+SkeletonModification2DJiggle::~SkeletonModification2DJiggle() {
+}
diff --git a/scene/resources/skeleton_modification_2d_jiggle.h b/scene/resources/skeleton_modification_2d_jiggle.h
new file mode 100644
index 0000000000..e24038a1db
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_jiggle.h
@@ -0,0 +1,139 @@
+/*************************************************************************/
+/* skeleton_modification_2d_jiggle.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATION2DJIGGLE_H
+#define SKELETONMODIFICATION2DJIGGLE_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+///////////////////////////////////////
+// SkeletonModification2DJIGGLE
+///////////////////////////////////////
+
+class SkeletonModification2DJiggle : public SkeletonModification2D {
+ GDCLASS(SkeletonModification2DJiggle, SkeletonModification2D);
+
+private:
+ struct Jiggle_Joint_Data2D {
+ int bone_idx = -1;
+ NodePath bone2d_node;
+ ObjectID bone2d_node_cache;
+
+ bool override_defaults = false;
+ float stiffness = 3;
+ float mass = 0.75;
+ float damping = 0.75;
+ bool use_gravity = false;
+ Vector2 gravity = Vector2(0, 6.0);
+
+ Vector2 force = Vector2(0, 0);
+ Vector2 acceleration = Vector2(0, 0);
+ Vector2 velocity = Vector2(0, 0);
+ Vector2 last_position = Vector2(0, 0);
+ Vector2 dynamic_position = Vector2(0, 0);
+
+ Vector2 last_noncollision_position = Vector2(0, 0);
+ };
+
+ Vector<Jiggle_Joint_Data2D> jiggle_data_chain;
+
+ NodePath target_node;
+ ObjectID target_node_cache;
+ void update_target_cache();
+
+ float stiffness = 3;
+ float mass = 0.75;
+ float damping = 0.75;
+ bool use_gravity = false;
+ Vector2 gravity = Vector2(0, 6);
+
+ bool use_colliders = false;
+ uint32_t collision_mask = 1;
+
+ void jiggle_joint_update_bone2d_cache(int p_joint_idx);
+ void _execute_jiggle_joint(int p_joint_idx, Node2D *p_target, float p_delta);
+ void _update_jiggle_joint_data();
+
+protected:
+ static void _bind_methods();
+ bool _set(const StringName &p_path, const Variant &p_value);
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ void _execute(float p_delta) override;
+ void _setup_modification(SkeletonModificationStack2D *p_stack) override;
+
+ void set_target_node(const NodePath &p_target_node);
+ NodePath get_target_node() const;
+
+ void set_stiffness(float p_stiffness);
+ float get_stiffness() const;
+ void set_mass(float p_mass);
+ float get_mass() const;
+ void set_damping(float p_damping);
+ float get_damping() const;
+ void set_use_gravity(bool p_use_gravity);
+ bool get_use_gravity() const;
+ void set_gravity(Vector2 p_gravity);
+ Vector2 get_gravity() const;
+
+ void set_use_colliders(bool p_use_colliders);
+ bool get_use_colliders() const;
+ void set_collision_mask(int p_mask);
+ int get_collision_mask() const;
+
+ int get_jiggle_data_chain_length();
+ void set_jiggle_data_chain_length(int p_new_length);
+
+ void set_jiggle_joint_bone2d_node(int p_joint_idx, const NodePath &p_target_node);
+ NodePath get_jiggle_joint_bone2d_node(int p_joint_idx) const;
+ void set_jiggle_joint_bone_index(int p_joint_idx, int p_bone_idx);
+ int get_jiggle_joint_bone_index(int p_joint_idx) const;
+
+ void set_jiggle_joint_override(int p_joint_idx, bool p_override);
+ bool get_jiggle_joint_override(int p_joint_idx) const;
+ void set_jiggle_joint_stiffness(int p_joint_idx, float p_stiffness);
+ float get_jiggle_joint_stiffness(int p_joint_idx) const;
+ void set_jiggle_joint_mass(int p_joint_idx, float p_mass);
+ float get_jiggle_joint_mass(int p_joint_idx) const;
+ void set_jiggle_joint_damping(int p_joint_idx, float p_damping);
+ float get_jiggle_joint_damping(int p_joint_idx) const;
+ void set_jiggle_joint_use_gravity(int p_joint_idx, bool p_use_gravity);
+ bool get_jiggle_joint_use_gravity(int p_joint_idx) const;
+ void set_jiggle_joint_gravity(int p_joint_idx, Vector2 p_gravity);
+ Vector2 get_jiggle_joint_gravity(int p_joint_idx) const;
+
+ SkeletonModification2DJiggle();
+ ~SkeletonModification2DJiggle();
+};
+
+#endif // SKELETONMODIFICATION2DJIGGLE_H
diff --git a/scene/resources/skeleton_modification_2d_lookat.cpp b/scene/resources/skeleton_modification_2d_lookat.cpp
new file mode 100644
index 0000000000..fd5c8c7cc2
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_lookat.cpp
@@ -0,0 +1,407 @@
+/*************************************************************************/
+/* skeleton_modification_2d_lookat.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_2d_lookat.h"
+#include "scene/2d/skeleton_2d.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_settings.h"
+#endif // TOOLS_ENABLED
+
+bool SkeletonModification2DLookAt::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path.begins_with("enable_constraint")) {
+ set_enable_constraint(p_value);
+ } else if (path.begins_with("constraint_angle_min")) {
+ set_constraint_angle_min(Math::deg2rad(float(p_value)));
+ } else if (path.begins_with("constraint_angle_max")) {
+ set_constraint_angle_max(Math::deg2rad(float(p_value)));
+ } else if (path.begins_with("constraint_angle_invert")) {
+ set_constraint_angle_invert(p_value);
+ } else if (path.begins_with("constraint_in_localspace")) {
+ set_constraint_in_localspace(p_value);
+ } else if (path.begins_with("additional_rotation")) {
+ set_additional_rotation(Math::deg2rad(float(p_value)));
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path.begins_with("editor/draw_gizmo")) {
+ set_editor_draw_gizmo(p_value);
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+bool SkeletonModification2DLookAt::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("enable_constraint")) {
+ r_ret = get_enable_constraint();
+ } else if (path.begins_with("constraint_angle_min")) {
+ r_ret = Math::rad2deg(get_constraint_angle_min());
+ } else if (path.begins_with("constraint_angle_max")) {
+ r_ret = Math::rad2deg(get_constraint_angle_max());
+ } else if (path.begins_with("constraint_angle_invert")) {
+ r_ret = get_constraint_angle_invert();
+ } else if (path.begins_with("constraint_in_localspace")) {
+ r_ret = get_constraint_in_localspace();
+ } else if (path.begins_with("additional_rotation")) {
+ r_ret = Math::rad2deg(get_additional_rotation());
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path.begins_with("editor/draw_gizmo")) {
+ r_ret = get_editor_draw_gizmo();
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+void SkeletonModification2DLookAt::_get_property_list(List<PropertyInfo> *p_list) const {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "enable_constraint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ if (enable_constraint) {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "constraint_angle_min", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "constraint_angle_max", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "constraint_angle_invert", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "constraint_in_localspace", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "additional_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "editor/draw_gizmo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+#endif // TOOLS_ENABLED
+}
+
+void SkeletonModification2DLookAt::_execute(float p_delta) {
+ ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
+ "Modification is not setup and therefore cannot execute!");
+ if (!enabled) {
+ return;
+ }
+
+ if (target_node_cache.is_null()) {
+ WARN_PRINT_ONCE("Target cache is out of date. Attempting to update...");
+ update_target_cache();
+ return;
+ }
+
+ if (bone2d_node_cache.is_null() && !bone2d_node.is_empty()) {
+ update_bone2d_cache();
+ WARN_PRINT_ONCE("Bone2D node cache is out of date. Attempting to update...");
+ return;
+ }
+
+ if (target_node_reference == nullptr) {
+ target_node_reference = Object::cast_to<Node2D>(ObjectDB::get_instance(target_node_cache));
+ }
+ if (!target_node_reference || !target_node_reference->is_inside_tree()) {
+ ERR_PRINT_ONCE("Target node is not in the scene tree. Cannot execute modification!");
+ return;
+ }
+ if (bone_idx <= -1) {
+ ERR_PRINT_ONCE("Bone index is invalid. Cannot execute modification!");
+ return;
+ }
+
+ Bone2D *operation_bone = stack->skeleton->get_bone(bone_idx);
+ if (operation_bone == nullptr) {
+ ERR_PRINT_ONCE("bone_idx for modification does not point to a valid bone! Cannot execute modification");
+ return;
+ }
+
+ Transform2D operation_transform = operation_bone->get_global_transform();
+ Transform2D target_trans = target_node_reference->get_global_transform();
+
+ // Look at the target!
+ operation_transform = operation_transform.looking_at(target_trans.get_origin());
+ // Apply whatever scale it had prior to looking_at
+ operation_transform.set_scale(operation_bone->get_global_transform().get_scale());
+
+ // Account for the direction the bone faces in:
+ operation_transform.set_rotation(operation_transform.get_rotation() - operation_bone->get_bone_angle());
+
+ // Apply additional rotation
+ operation_transform.set_rotation(operation_transform.get_rotation() + additional_rotation);
+
+ // Apply constraints in globalspace:
+ if (enable_constraint && !constraint_in_localspace) {
+ operation_transform.set_rotation(clamp_angle(operation_transform.get_rotation(), constraint_angle_min, constraint_angle_max, constraint_angle_invert));
+ }
+
+ // Convert from a global transform to a local transform via the Bone2D node
+ operation_bone->set_global_transform(operation_transform);
+ operation_transform = operation_bone->get_transform();
+
+ // Apply constraints in localspace:
+ if (enable_constraint && constraint_in_localspace) {
+ operation_transform.set_rotation(clamp_angle(operation_transform.get_rotation(), constraint_angle_min, constraint_angle_max, constraint_angle_invert));
+ }
+
+ // Set the local pose override, and to make sure child bones are also updated, set the transform of the bone.
+ stack->skeleton->set_bone_local_pose_override(bone_idx, operation_transform, stack->strength, true);
+ operation_bone->set_transform(operation_transform);
+}
+
+void SkeletonModification2DLookAt::_setup_modification(SkeletonModificationStack2D *p_stack) {
+ stack = p_stack;
+
+ if (stack != nullptr) {
+ is_setup = true;
+ update_target_cache();
+ update_bone2d_cache();
+ }
+}
+
+void SkeletonModification2DLookAt::_draw_editor_gizmo() {
+ if (!enabled || !is_setup) {
+ return;
+ }
+
+ Bone2D *operation_bone = stack->skeleton->get_bone(bone_idx);
+ editor_draw_angle_constraints(operation_bone, constraint_angle_min, constraint_angle_max,
+ enable_constraint, constraint_in_localspace, constraint_angle_invert);
+}
+
+void SkeletonModification2DLookAt::update_bone2d_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update Bone2D cache: modification is not properly setup!");
+ return;
+ }
+
+ bone2d_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(bone2d_node)) {
+ Node *node = stack->skeleton->get_node(bone2d_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update Bone2D cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update Bone2D cache: node is not in the scene tree!");
+ bone2d_node_cache = node->get_instance_id();
+
+ Bone2D *bone = Object::cast_to<Bone2D>(node);
+ if (bone) {
+ bone_idx = bone->get_index_in_skeleton();
+ } else {
+ ERR_FAIL_MSG("Error Bone2D cache: Nodepath to Bone2D is not a Bone2D node!");
+ }
+
+ // Set this to null so we update it
+ target_node_reference = nullptr;
+ }
+ }
+ }
+}
+
+void SkeletonModification2DLookAt::set_bone2d_node(const NodePath &p_target_node) {
+ bone2d_node = p_target_node;
+ update_bone2d_cache();
+}
+
+NodePath SkeletonModification2DLookAt::get_bone2d_node() const {
+ return bone2d_node;
+}
+
+int SkeletonModification2DLookAt::get_bone_index() const {
+ return bone_idx;
+}
+
+void SkeletonModification2DLookAt::set_bone_index(int p_bone_idx) {
+ ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
+
+ if (is_setup) {
+ if (stack->skeleton) {
+ ERR_FAIL_INDEX_MSG(p_bone_idx, stack->skeleton->get_bone_count(), "Passed-in Bone index is out of range!");
+ bone_idx = p_bone_idx;
+ bone2d_node_cache = stack->skeleton->get_bone(p_bone_idx)->get_instance_id();
+ bone2d_node = stack->skeleton->get_path_to(stack->skeleton->get_bone(p_bone_idx));
+ } else {
+ WARN_PRINT("Cannot verify the bone index for this modification...");
+ bone_idx = p_bone_idx;
+ }
+ } else {
+ WARN_PRINT("Cannot verify the bone index for this modification...");
+ bone_idx = p_bone_idx;
+ }
+
+ notify_property_list_changed();
+}
+
+void SkeletonModification2DLookAt::update_target_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ return;
+ }
+
+ target_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(target_node)) {
+ Node *node = stack->skeleton->get_node(target_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update target cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update target cache: node is not in the scene tree!");
+ target_node_cache = node->get_instance_id();
+ }
+ }
+ }
+}
+
+void SkeletonModification2DLookAt::set_target_node(const NodePath &p_target_node) {
+ target_node = p_target_node;
+ update_target_cache();
+}
+
+NodePath SkeletonModification2DLookAt::get_target_node() const {
+ return target_node;
+}
+
+float SkeletonModification2DLookAt::get_additional_rotation() const {
+ return additional_rotation;
+}
+
+void SkeletonModification2DLookAt::set_additional_rotation(float p_rotation) {
+ additional_rotation = p_rotation;
+}
+
+void SkeletonModification2DLookAt::set_enable_constraint(bool p_constraint) {
+ enable_constraint = p_constraint;
+ notify_property_list_changed();
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2DLookAt::get_enable_constraint() const {
+ return enable_constraint;
+}
+
+void SkeletonModification2DLookAt::set_constraint_angle_min(float p_angle_min) {
+ constraint_angle_min = p_angle_min;
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+float SkeletonModification2DLookAt::get_constraint_angle_min() const {
+ return constraint_angle_min;
+}
+
+void SkeletonModification2DLookAt::set_constraint_angle_max(float p_angle_max) {
+ constraint_angle_max = p_angle_max;
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+float SkeletonModification2DLookAt::get_constraint_angle_max() const {
+ return constraint_angle_max;
+}
+
+void SkeletonModification2DLookAt::set_constraint_angle_invert(bool p_invert) {
+ constraint_angle_invert = p_invert;
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2DLookAt::get_constraint_angle_invert() const {
+ return constraint_angle_invert;
+}
+
+void SkeletonModification2DLookAt::set_constraint_in_localspace(bool p_constraint_in_localspace) {
+ constraint_in_localspace = p_constraint_in_localspace;
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2DLookAt::get_constraint_in_localspace() const {
+ return constraint_in_localspace;
+}
+
+void SkeletonModification2DLookAt::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_bone2d_node", "bone2d_nodepath"), &SkeletonModification2DLookAt::set_bone2d_node);
+ ClassDB::bind_method(D_METHOD("get_bone2d_node"), &SkeletonModification2DLookAt::get_bone2d_node);
+ ClassDB::bind_method(D_METHOD("set_bone_index", "bone_idx"), &SkeletonModification2DLookAt::set_bone_index);
+ ClassDB::bind_method(D_METHOD("get_bone_index"), &SkeletonModification2DLookAt::get_bone_index);
+
+ ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification2DLookAt::set_target_node);
+ ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification2DLookAt::get_target_node);
+
+ ClassDB::bind_method(D_METHOD("set_additional_rotation", "rotation"), &SkeletonModification2DLookAt::set_additional_rotation);
+ ClassDB::bind_method(D_METHOD("get_additional_rotation"), &SkeletonModification2DLookAt::get_additional_rotation);
+
+ ClassDB::bind_method(D_METHOD("set_enable_constraint", "enable_constraint"), &SkeletonModification2DLookAt::set_enable_constraint);
+ ClassDB::bind_method(D_METHOD("get_enable_constraint"), &SkeletonModification2DLookAt::get_enable_constraint);
+ ClassDB::bind_method(D_METHOD("set_constraint_angle_min", "angle_min"), &SkeletonModification2DLookAt::set_constraint_angle_min);
+ ClassDB::bind_method(D_METHOD("get_constraint_angle_min"), &SkeletonModification2DLookAt::get_constraint_angle_min);
+ ClassDB::bind_method(D_METHOD("set_constraint_angle_max", "angle_max"), &SkeletonModification2DLookAt::set_constraint_angle_max);
+ ClassDB::bind_method(D_METHOD("get_constraint_angle_max"), &SkeletonModification2DLookAt::get_constraint_angle_max);
+ ClassDB::bind_method(D_METHOD("set_constraint_angle_invert", "invert"), &SkeletonModification2DLookAt::set_constraint_angle_invert);
+ ClassDB::bind_method(D_METHOD("get_constraint_angle_invert"), &SkeletonModification2DLookAt::get_constraint_angle_invert);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_index"), "set_bone_index", "get_bone_index");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "bone2d_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D"), "set_bone2d_node", "get_bone2d_node");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D"), "set_target_node", "get_target_node");
+}
+
+SkeletonModification2DLookAt::SkeletonModification2DLookAt() {
+ stack = nullptr;
+ is_setup = false;
+ bone_idx = -1;
+ additional_rotation = 0;
+ enable_constraint = false;
+ constraint_angle_min = 0;
+ constraint_angle_max = Math_PI * 2;
+ constraint_angle_invert = false;
+ enabled = true;
+
+ editor_draw_gizmo = true;
+}
+
+SkeletonModification2DLookAt::~SkeletonModification2DLookAt() {
+}
diff --git a/scene/resources/skeleton_modification_2d_lookat.h b/scene/resources/skeleton_modification_2d_lookat.h
new file mode 100644
index 0000000000..6aff30b826
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_lookat.h
@@ -0,0 +1,100 @@
+/*************************************************************************/
+/* skeleton_modification_2d_lookat.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATION2DLOOKAT_H
+#define SKELETONMODIFICATION2DLOOKAT_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+///////////////////////////////////////
+// SkeletonModification2DLookAt
+///////////////////////////////////////
+
+class SkeletonModification2DLookAt : public SkeletonModification2D {
+ GDCLASS(SkeletonModification2DLookAt, SkeletonModification2D);
+
+private:
+ int bone_idx = -1;
+ NodePath bone2d_node;
+ ObjectID bone2d_node_cache;
+
+ NodePath target_node;
+ ObjectID target_node_cache;
+ Node2D *target_node_reference = nullptr;
+
+ float additional_rotation = 0;
+ bool enable_constraint = false;
+ float constraint_angle_min = 0;
+ float constraint_angle_max = (2.0 * Math_PI);
+ bool constraint_angle_invert = false;
+ bool constraint_in_localspace = true;
+
+ void update_bone2d_cache();
+ void update_target_cache();
+
+protected:
+ static void _bind_methods();
+ bool _set(const StringName &p_path, const Variant &p_value);
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ void _execute(float p_delta) override;
+ void _setup_modification(SkeletonModificationStack2D *p_stack) override;
+ void _draw_editor_gizmo() override;
+
+ void set_bone2d_node(const NodePath &p_target_node);
+ NodePath get_bone2d_node() const;
+ void set_bone_index(int p_idx);
+ int get_bone_index() const;
+
+ void set_target_node(const NodePath &p_target_node);
+ NodePath get_target_node() const;
+
+ void set_additional_rotation(float p_rotation);
+ float get_additional_rotation() const;
+
+ void set_enable_constraint(bool p_constraint);
+ bool get_enable_constraint() const;
+ void set_constraint_angle_min(float p_angle_min);
+ float get_constraint_angle_min() const;
+ void set_constraint_angle_max(float p_angle_max);
+ float get_constraint_angle_max() const;
+ void set_constraint_angle_invert(bool p_invert);
+ bool get_constraint_angle_invert() const;
+ void set_constraint_in_localspace(bool p_constraint_in_localspace);
+ bool get_constraint_in_localspace() const;
+
+ SkeletonModification2DLookAt();
+ ~SkeletonModification2DLookAt();
+};
+
+#endif // SKELETONMODIFICATION2DLOOKAT_H
diff --git a/scene/resources/skeleton_modification_2d_physicalbones.cpp b/scene/resources/skeleton_modification_2d_physicalbones.cpp
new file mode 100644
index 0000000000..9dedb93f36
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_physicalbones.cpp
@@ -0,0 +1,297 @@
+/*************************************************************************/
+/* skeleton_modification_2d_physicalbones.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_2d_physicalbones.h"
+#include "scene/2d/physical_bone_2d.h"
+#include "scene/2d/skeleton_2d.h"
+
+bool SkeletonModification2DPhysicalBones::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+#ifdef TOOLS_ENABLED
+ // Exposes a way to fetch the PhysicalBone2D nodes from the Godot editor.
+ if (is_setup) {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (path.begins_with("fetch_bones")) {
+ fetch_physical_bones();
+ notify_property_list_changed();
+ return true;
+ }
+ }
+ }
+#endif //TOOLS_ENABLED
+
+ if (path.begins_with("joint_")) {
+ int which = path.get_slicec('_', 1).to_int();
+ String what = path.get_slicec('_', 2);
+ ERR_FAIL_INDEX_V(which, physical_bone_chain.size(), false);
+
+ if (what == "nodepath") {
+ set_physical_bone_node(which, p_value);
+ }
+ return true;
+ }
+ return true;
+}
+
+bool SkeletonModification2DPhysicalBones::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (path.begins_with("fetch_bones")) {
+ return true; // Do nothing!
+ }
+ }
+#endif //TOOLS_ENABLED
+
+ if (path.begins_with("joint_")) {
+ int which = path.get_slicec('_', 1).to_int();
+ String what = path.get_slicec('_', 2);
+ ERR_FAIL_INDEX_V(which, physical_bone_chain.size(), false);
+
+ if (what == "nodepath") {
+ r_ret = get_physical_bone_node(which);
+ }
+ return true;
+ }
+ return true;
+}
+
+void SkeletonModification2DPhysicalBones::_get_property_list(List<PropertyInfo> *p_list) const {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "fetch_bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+#endif //TOOLS_ENABLED
+
+ for (int i = 0; i < physical_bone_chain.size(); i++) {
+ String base_string = "joint_" + itos(i) + "_";
+
+ p_list->push_back(PropertyInfo(Variant::NODE_PATH, base_string + "nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicalBone2D", PROPERTY_USAGE_DEFAULT));
+ }
+}
+
+void SkeletonModification2DPhysicalBones::_execute(float p_delta) {
+ ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
+ "Modification is not setup and therefore cannot execute!");
+ if (!enabled) {
+ return;
+ }
+
+ if (_simulation_state_dirty) {
+ _update_simulation_state();
+ }
+
+ for (int i = 0; i < physical_bone_chain.size(); i++) {
+ PhysicalBone_Data2D bone_data = physical_bone_chain[i];
+ if (bone_data.physical_bone_node_cache.is_null()) {
+ WARN_PRINT_ONCE("PhysicalBone2D cache " + itos(i) + " is out of date. Attempting to update...");
+ _physical_bone_update_cache(i);
+ continue;
+ }
+
+ PhysicalBone2D *physical_bone = Object::cast_to<PhysicalBone2D>(ObjectDB::get_instance(bone_data.physical_bone_node_cache));
+ if (!physical_bone) {
+ ERR_PRINT_ONCE("PhysicalBone2D not found at index " + itos(i) + "!");
+ return;
+ }
+ if (physical_bone->get_bone2d_index() < 0 || physical_bone->get_bone2d_index() > stack->skeleton->get_bone_count()) {
+ ERR_PRINT_ONCE("PhysicalBone2D at index " + itos(i) + " has invalid Bone2D!");
+ return;
+ }
+ Bone2D *bone_2d = stack->skeleton->get_bone(physical_bone->get_bone2d_index());
+
+ if (physical_bone->get_simulate_physics() && !physical_bone->get_follow_bone_when_simulating()) {
+ bone_2d->set_global_transform(physical_bone->get_global_transform());
+ stack->skeleton->set_bone_local_pose_override(physical_bone->get_bone2d_index(), bone_2d->get_transform(), stack->strength, true);
+ }
+ }
+}
+
+void SkeletonModification2DPhysicalBones::_setup_modification(SkeletonModificationStack2D *p_stack) {
+ stack = p_stack;
+
+ if (stack) {
+ is_setup = true;
+
+ if (stack->skeleton) {
+ for (int i = 0; i < physical_bone_chain.size(); i++) {
+ _physical_bone_update_cache(i);
+ }
+ }
+ }
+}
+
+void SkeletonModification2DPhysicalBones::_physical_bone_update_cache(int p_joint_idx) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, physical_bone_chain.size(), "Cannot update PhysicalBone2D cache: joint index out of range!");
+ if (!is_setup || !stack) {
+ if (!stack) {
+ ERR_PRINT_ONCE("Cannot update PhysicalBone2D cache: modification is not properly setup!");
+ }
+ return;
+ }
+
+ physical_bone_chain.write[p_joint_idx].physical_bone_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(physical_bone_chain[p_joint_idx].physical_bone_node)) {
+ Node *node = stack->skeleton->get_node(physical_bone_chain[p_joint_idx].physical_bone_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update Physical Bone2D " + itos(p_joint_idx) + " cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update Physical Bone2D " + itos(p_joint_idx) + " cache: node is not in scene tree!");
+ physical_bone_chain.write[p_joint_idx].physical_bone_node_cache = node->get_instance_id();
+ }
+ }
+ }
+}
+
+int SkeletonModification2DPhysicalBones::get_physical_bone_chain_length() {
+ return physical_bone_chain.size();
+}
+
+void SkeletonModification2DPhysicalBones::set_physical_bone_chain_length(int p_length) {
+ ERR_FAIL_COND(p_length < 0);
+ physical_bone_chain.resize(p_length);
+ notify_property_list_changed();
+}
+
+void SkeletonModification2DPhysicalBones::fetch_physical_bones() {
+ ERR_FAIL_COND_MSG(!stack, "No modification stack found! Cannot fetch physical bones!");
+ ERR_FAIL_COND_MSG(!stack->skeleton, "No skeleton found! Cannot fetch physical bones!");
+
+ physical_bone_chain.clear();
+
+ List<Node *> node_queue = List<Node *>();
+ node_queue.push_back(stack->skeleton);
+
+ while (node_queue.size() > 0) {
+ Node *node_to_process = node_queue[0];
+ node_queue.pop_front();
+
+ if (node_to_process != nullptr) {
+ PhysicalBone2D *potential_bone = Object::cast_to<PhysicalBone2D>(node_to_process);
+ if (potential_bone) {
+ PhysicalBone_Data2D new_data = PhysicalBone_Data2D();
+ new_data.physical_bone_node = stack->skeleton->get_path_to(potential_bone);
+ new_data.physical_bone_node_cache = potential_bone->get_instance_id();
+ physical_bone_chain.push_back(new_data);
+ }
+ for (int i = 0; i < node_to_process->get_child_count(); i++) {
+ node_queue.push_back(node_to_process->get_child(i));
+ }
+ }
+ }
+}
+
+void SkeletonModification2DPhysicalBones::start_simulation(const TypedArray<StringName> &p_bones) {
+ _simulation_state_dirty = true;
+ _simulation_state_dirty_names = p_bones;
+ _simulation_state_dirty_process = true;
+
+ if (is_setup) {
+ _update_simulation_state();
+ }
+}
+
+void SkeletonModification2DPhysicalBones::stop_simulation(const TypedArray<StringName> &p_bones) {
+ _simulation_state_dirty = true;
+ _simulation_state_dirty_names = p_bones;
+ _simulation_state_dirty_process = false;
+
+ if (is_setup) {
+ _update_simulation_state();
+ }
+}
+
+void SkeletonModification2DPhysicalBones::_update_simulation_state() {
+ if (!_simulation_state_dirty) {
+ return;
+ }
+ _simulation_state_dirty = false;
+
+ if (_simulation_state_dirty_names.size() <= 0) {
+ for (int i = 0; i < physical_bone_chain.size(); i++) {
+ PhysicalBone2D *physical_bone = Object::cast_to<PhysicalBone2D>(stack->skeleton->get_node(physical_bone_chain[i].physical_bone_node));
+ if (!physical_bone) {
+ continue;
+ }
+
+ physical_bone->set_simulate_physics(_simulation_state_dirty_process);
+ }
+ } else {
+ for (int i = 0; i < physical_bone_chain.size(); i++) {
+ PhysicalBone2D *physical_bone = Object::cast_to<PhysicalBone2D>(ObjectDB::get_instance(physical_bone_chain[i].physical_bone_node_cache));
+ if (!physical_bone) {
+ continue;
+ }
+ if (_simulation_state_dirty_names.has(physical_bone->get_name())) {
+ physical_bone->set_simulate_physics(_simulation_state_dirty_process);
+ }
+ }
+ }
+}
+
+void SkeletonModification2DPhysicalBones::set_physical_bone_node(int p_joint_idx, const NodePath &p_nodepath) {
+ ERR_FAIL_INDEX_MSG(p_joint_idx, physical_bone_chain.size(), "Joint index out of range!");
+ physical_bone_chain.write[p_joint_idx].physical_bone_node = p_nodepath;
+ _physical_bone_update_cache(p_joint_idx);
+}
+
+NodePath SkeletonModification2DPhysicalBones::get_physical_bone_node(int p_joint_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_joint_idx, physical_bone_chain.size(), NodePath(), "Joint index out of range!");
+ return physical_bone_chain[p_joint_idx].physical_bone_node;
+}
+
+void SkeletonModification2DPhysicalBones::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_physical_bone_chain_length", "length"), &SkeletonModification2DPhysicalBones::set_physical_bone_chain_length);
+ ClassDB::bind_method(D_METHOD("get_physical_bone_chain_length"), &SkeletonModification2DPhysicalBones::get_physical_bone_chain_length);
+
+ ClassDB::bind_method(D_METHOD("set_physical_bone_node", "joint_idx", "physicalbone2d_node"), &SkeletonModification2DPhysicalBones::set_physical_bone_node);
+ ClassDB::bind_method(D_METHOD("get_physical_bone_node", "joint_idx"), &SkeletonModification2DPhysicalBones::get_physical_bone_node);
+
+ ClassDB::bind_method(D_METHOD("fetch_physical_bones"), &SkeletonModification2DPhysicalBones::fetch_physical_bones);
+ ClassDB::bind_method(D_METHOD("start_simulation", "bones"), &SkeletonModification2DPhysicalBones::start_simulation, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("stop_simulation", "bones"), &SkeletonModification2DPhysicalBones::stop_simulation, DEFVAL(Array()));
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "physical_bone_chain_length", PROPERTY_HINT_RANGE, "0,100,1"), "set_physical_bone_chain_length", "get_physical_bone_chain_length");
+}
+
+SkeletonModification2DPhysicalBones::SkeletonModification2DPhysicalBones() {
+ stack = nullptr;
+ is_setup = false;
+ physical_bone_chain = Vector<PhysicalBone_Data2D>();
+ enabled = true;
+ editor_draw_gizmo = false; // Nothing to really show in a gizmo right now.
+}
+
+SkeletonModification2DPhysicalBones::~SkeletonModification2DPhysicalBones() {
+}
diff --git a/scene/resources/skeleton_modification_2d_physicalbones.h b/scene/resources/skeleton_modification_2d_physicalbones.h
new file mode 100644
index 0000000000..cdf6a5f570
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_physicalbones.h
@@ -0,0 +1,82 @@
+/*************************************************************************/
+/* skeleton_modification_2d_physicalbones.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATION2DPHYSICALBONES_H
+#define SKELETONMODIFICATION2DPHYSICALBONES_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+///////////////////////////////////////
+// SkeletonModification2DJIGGLE
+///////////////////////////////////////
+
+class SkeletonModification2DPhysicalBones : public SkeletonModification2D {
+ GDCLASS(SkeletonModification2DPhysicalBones, SkeletonModification2D);
+
+private:
+ struct PhysicalBone_Data2D {
+ NodePath physical_bone_node;
+ ObjectID physical_bone_node_cache;
+ };
+ Vector<PhysicalBone_Data2D> physical_bone_chain;
+
+ void _physical_bone_update_cache(int p_joint_idx);
+
+ bool _simulation_state_dirty = false;
+ TypedArray<StringName> _simulation_state_dirty_names;
+ bool _simulation_state_dirty_process;
+ void _update_simulation_state();
+
+protected:
+ static void _bind_methods();
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ bool _set(const StringName &p_path, const Variant &p_value);
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ void _execute(float p_delta) override;
+ void _setup_modification(SkeletonModificationStack2D *p_stack) override;
+
+ int get_physical_bone_chain_length();
+ void set_physical_bone_chain_length(int p_new_length);
+
+ void set_physical_bone_node(int p_joint_idx, const NodePath &p_path);
+ NodePath get_physical_bone_node(int p_joint_idx) const;
+
+ void fetch_physical_bones();
+ void start_simulation(const TypedArray<StringName> &p_bones);
+ void stop_simulation(const TypedArray<StringName> &p_bones);
+
+ SkeletonModification2DPhysicalBones();
+ ~SkeletonModification2DPhysicalBones();
+};
+
+#endif // SKELETONMODIFICATION2DPHYSICALBONES_H
diff --git a/scene/resources/skeleton_modification_2d_stackholder.cpp b/scene/resources/skeleton_modification_2d_stackholder.cpp
new file mode 100644
index 0000000000..9436092cd9
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_stackholder.cpp
@@ -0,0 +1,131 @@
+/*************************************************************************/
+/* skeleton_modification_2d_stackholder.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_2d_stackholder.h"
+#include "scene/2d/skeleton_2d.h"
+
+bool SkeletonModification2DStackHolder::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path == "held_modification_stack") {
+ set_held_modification_stack(p_value);
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path == "editor/draw_gizmo") {
+ set_editor_draw_gizmo(p_value);
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+bool SkeletonModification2DStackHolder::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path == "held_modification_stack") {
+ r_ret = get_held_modification_stack();
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path == "editor/draw_gizmo") {
+ r_ret = get_editor_draw_gizmo();
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+void SkeletonModification2DStackHolder::_get_property_list(List<PropertyInfo> *p_list) const {
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "held_modification_stack", PROPERTY_HINT_RESOURCE_TYPE, "SkeletonModificationStack2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "editor/draw_gizmo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+#endif // TOOLS_ENABLED
+}
+
+void SkeletonModification2DStackHolder::_execute(float p_delta) {
+ ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
+ "Modification is not setup and therefore cannot execute!");
+
+ if (held_modification_stack.is_valid()) {
+ held_modification_stack->execute(p_delta, execution_mode);
+ }
+}
+
+void SkeletonModification2DStackHolder::_setup_modification(SkeletonModificationStack2D *p_stack) {
+ stack = p_stack;
+
+ if (stack != nullptr) {
+ is_setup = true;
+
+ if (held_modification_stack.is_valid()) {
+ held_modification_stack->set_skeleton(stack->get_skeleton());
+ held_modification_stack->setup();
+ }
+ }
+}
+
+void SkeletonModification2DStackHolder::_draw_editor_gizmo() {
+ if (stack) {
+ if (held_modification_stack.is_valid()) {
+ held_modification_stack->draw_editor_gizmos();
+ }
+ }
+}
+
+void SkeletonModification2DStackHolder::set_held_modification_stack(Ref<SkeletonModificationStack2D> p_held_stack) {
+ held_modification_stack = p_held_stack;
+
+ if (is_setup && held_modification_stack.is_valid()) {
+ held_modification_stack->set_skeleton(stack->get_skeleton());
+ held_modification_stack->setup();
+ }
+}
+
+Ref<SkeletonModificationStack2D> SkeletonModification2DStackHolder::get_held_modification_stack() const {
+ return held_modification_stack;
+}
+
+void SkeletonModification2DStackHolder::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_held_modification_stack", "held_modification_stack"), &SkeletonModification2DStackHolder::set_held_modification_stack);
+ ClassDB::bind_method(D_METHOD("get_held_modification_stack"), &SkeletonModification2DStackHolder::get_held_modification_stack);
+}
+
+SkeletonModification2DStackHolder::SkeletonModification2DStackHolder() {
+ stack = nullptr;
+ is_setup = false;
+ enabled = true;
+}
+
+SkeletonModification2DStackHolder::~SkeletonModification2DStackHolder() {
+}
diff --git a/scene/resources/skeleton_modification_2d_stackholder.h b/scene/resources/skeleton_modification_2d_stackholder.h
new file mode 100644
index 0000000000..9cc38e3942
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_stackholder.h
@@ -0,0 +1,64 @@
+/*************************************************************************/
+/* skeleton_modification_2d_stackholder.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATION2DSTACKHOLDER_H
+#define SKELETONMODIFICATION2DSTACKHOLDER_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+///////////////////////////////////////
+// SkeletonModification2DJIGGLE
+///////////////////////////////////////
+
+class SkeletonModification2DStackHolder : public SkeletonModification2D {
+ GDCLASS(SkeletonModification2DStackHolder, SkeletonModification2D);
+
+protected:
+ static void _bind_methods();
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ bool _set(const StringName &p_path, const Variant &p_value);
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ Ref<SkeletonModificationStack2D> held_modification_stack;
+
+ void _execute(float p_delta) override;
+ void _setup_modification(SkeletonModificationStack2D *p_stack) override;
+ void _draw_editor_gizmo() override;
+
+ void set_held_modification_stack(Ref<SkeletonModificationStack2D> p_held_stack);
+ Ref<SkeletonModificationStack2D> get_held_modification_stack() const;
+
+ SkeletonModification2DStackHolder();
+ ~SkeletonModification2DStackHolder();
+};
+
+#endif // SKELETONMODIFICATION2DSTACKHOLDER_H
diff --git a/scene/resources/skeleton_modification_2d_twoboneik.cpp b/scene/resources/skeleton_modification_2d_twoboneik.cpp
new file mode 100644
index 0000000000..0a91290015
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_twoboneik.cpp
@@ -0,0 +1,481 @@
+/*************************************************************************/
+/* skeleton_modification_2d_twoboneik.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_2d_twoboneik.h"
+#include "scene/2d/skeleton_2d.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_settings.h"
+#endif // TOOLS_ENABLED
+
+bool SkeletonModification2DTwoBoneIK::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path == "joint_one_bone_idx") {
+ set_joint_one_bone_idx(p_value);
+ } else if (path == "joint_one_bone2d_node") {
+ set_joint_one_bone2d_node(p_value);
+ } else if (path == "joint_two_bone_idx") {
+ set_joint_two_bone_idx(p_value);
+ } else if (path == "joint_two_bone2d_node") {
+ set_joint_two_bone2d_node(p_value);
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path.begins_with("editor/draw_gizmo")) {
+ set_editor_draw_gizmo(p_value);
+ } else if (path.begins_with("editor/draw_min_max")) {
+ set_editor_draw_min_max(p_value);
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+bool SkeletonModification2DTwoBoneIK::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path == "joint_one_bone_idx") {
+ r_ret = get_joint_one_bone_idx();
+ } else if (path == "joint_one_bone2d_node") {
+ r_ret = get_joint_one_bone2d_node();
+ } else if (path == "joint_two_bone_idx") {
+ r_ret = get_joint_two_bone_idx();
+ } else if (path == "joint_two_bone2d_node") {
+ r_ret = get_joint_two_bone2d_node();
+ }
+
+#ifdef TOOLS_ENABLED
+ if (path.begins_with("editor/draw_gizmo")) {
+ r_ret = get_editor_draw_gizmo();
+ } else if (path.begins_with("editor/draw_min_max")) {
+ r_ret = get_editor_draw_min_max();
+ }
+#endif // TOOLS_ENABLED
+
+ return true;
+}
+
+void SkeletonModification2DTwoBoneIK::_get_property_list(List<PropertyInfo> *p_list) const {
+ p_list->push_back(PropertyInfo(Variant::INT, "joint_one_bone_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::NODE_PATH, "joint_one_bone2d_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D", PROPERTY_USAGE_DEFAULT));
+
+ p_list->push_back(PropertyInfo(Variant::INT, "joint_two_bone_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::NODE_PATH, "joint_two_bone2d_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D", PROPERTY_USAGE_DEFAULT));
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "editor/draw_gizmo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "editor/draw_min_max", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
+ }
+#endif // TOOLS_ENABLED
+}
+
+void SkeletonModification2DTwoBoneIK::_execute(float p_delta) {
+ ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
+ "Modification is not setup and therefore cannot execute!");
+ if (!enabled) {
+ return;
+ }
+
+ if (target_node_cache.is_null()) {
+ WARN_PRINT_ONCE("Target cache is out of date. Attempting to update...");
+ update_target_cache();
+ return;
+ }
+
+ if (joint_one_bone2d_node_cache.is_null() && !joint_one_bone2d_node.is_empty()) {
+ WARN_PRINT_ONCE("Joint one Bone2D node cache is out of date. Attempting to update...");
+ update_joint_one_bone2d_cache();
+ }
+ if (joint_two_bone2d_node_cache.is_null() && !joint_two_bone2d_node.is_empty()) {
+ WARN_PRINT_ONCE("Joint two Bone2D node cache is out of date. Attempting to update...");
+ update_joint_two_bone2d_cache();
+ }
+
+ Node2D *target = Object::cast_to<Node2D>(ObjectDB::get_instance(target_node_cache));
+ if (!target || !target->is_inside_tree()) {
+ ERR_PRINT_ONCE("Target node is not in the scene tree. Cannot execute modification!");
+ return;
+ }
+
+ Bone2D *joint_one_bone = stack->skeleton->get_bone(joint_one_bone_idx);
+ if (joint_one_bone == nullptr) {
+ ERR_PRINT_ONCE("Joint one bone_idx does not point to a valid bone! Cannot execute modification!");
+ return;
+ }
+
+ Bone2D *joint_two_bone = stack->skeleton->get_bone(joint_two_bone_idx);
+ if (joint_two_bone == nullptr) {
+ ERR_PRINT_ONCE("Joint two bone_idx does not point to a valid bone! Cannot execute modification!");
+ return;
+ }
+
+ // Adopted from the links below:
+ // http://theorangeduck.com/page/simple-two-joint
+ // https://www.alanzucconi.com/2018/05/02/ik-2d-2/
+ // With modifications by TwistedTwigleg
+ Vector2 target_difference = target->get_global_transform().get_origin() - joint_one_bone->get_global_transform().get_origin();
+ float joint_one_to_target = target_difference.length();
+ float angle_atan = Math::atan2(target_difference.y, target_difference.x);
+
+ float bone_one_length = joint_one_bone->get_length() * MIN(joint_one_bone->get_global_scale().x, joint_one_bone->get_global_scale().y);
+ float bone_two_length = joint_two_bone->get_length() * MIN(joint_two_bone->get_global_scale().x, joint_two_bone->get_global_scale().y);
+ bool override_angles_due_to_out_of_range = false;
+
+ if (joint_one_to_target < target_minimum_distance) {
+ joint_one_to_target = target_minimum_distance;
+ }
+ if (joint_one_to_target > target_maximum_distance && target_maximum_distance > 0.0) {
+ joint_one_to_target = target_maximum_distance;
+ }
+
+ if (bone_one_length + bone_two_length < joint_one_to_target) {
+ override_angles_due_to_out_of_range = true;
+ }
+
+ if (!override_angles_due_to_out_of_range) {
+ float angle_0 = Math::acos(((joint_one_to_target * joint_one_to_target) + (bone_one_length * bone_one_length) - (bone_two_length * bone_two_length)) / (2.0 * joint_one_to_target * bone_one_length));
+ float angle_1 = Math::acos(((bone_two_length * bone_two_length) + (bone_one_length * bone_one_length) - (joint_one_to_target * joint_one_to_target)) / (2.0 * bone_two_length * bone_one_length));
+
+ if (flip_bend_direction) {
+ angle_0 = -angle_0;
+ angle_1 = -angle_1;
+ }
+
+ if (isnan(angle_0) || isnan(angle_1)) {
+ // We cannot solve for this angle! Do nothing to avoid setting the rotation (and scale) to NaN.
+ } else {
+ joint_one_bone->set_global_rotation(angle_atan - angle_0 - joint_one_bone->get_bone_angle());
+ joint_two_bone->set_rotation(-Math_PI - angle_1 - joint_two_bone->get_bone_angle() + joint_one_bone->get_bone_angle());
+ }
+ } else {
+ joint_one_bone->set_global_rotation(angle_atan - joint_one_bone->get_bone_angle());
+ joint_two_bone->set_global_rotation(angle_atan - joint_two_bone->get_bone_angle());
+ }
+
+ stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, joint_one_bone->get_transform(), stack->strength, true);
+ stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, joint_two_bone->get_transform(), stack->strength, true);
+}
+
+void SkeletonModification2DTwoBoneIK::_setup_modification(SkeletonModificationStack2D *p_stack) {
+ stack = p_stack;
+
+ if (stack) {
+ is_setup = true;
+ update_target_cache();
+ update_joint_one_bone2d_cache();
+ update_joint_two_bone2d_cache();
+ }
+}
+
+void SkeletonModification2DTwoBoneIK::_draw_editor_gizmo() {
+ if (!enabled || !is_setup) {
+ return;
+ }
+
+ Bone2D *operation_bone_one = stack->skeleton->get_bone(joint_one_bone_idx);
+ if (!operation_bone_one) {
+ return;
+ }
+ stack->skeleton->draw_set_transform(
+ stack->skeleton->get_global_transform().affine_inverse().xform(operation_bone_one->get_global_position()),
+ operation_bone_one->get_global_rotation() - stack->skeleton->get_global_rotation());
+
+ Color bone_ik_color = Color(1.0, 0.65, 0.0, 0.4);
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
+ }
+#endif // TOOLS_ENABLED
+
+ if (flip_bend_direction) {
+ float angle = -(Math_PI * 0.5) + operation_bone_one->get_bone_angle();
+ stack->skeleton->draw_line(Vector2(0, 0), Vector2(Math::cos(angle), sin(angle)) * (operation_bone_one->get_length() * 0.5), bone_ik_color, 2.0);
+ } else {
+ float angle = (Math_PI * 0.5) + operation_bone_one->get_bone_angle();
+ stack->skeleton->draw_line(Vector2(0, 0), Vector2(Math::cos(angle), sin(angle)) * (operation_bone_one->get_length() * 0.5), bone_ik_color, 2.0);
+ }
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (editor_draw_min_max) {
+ if (target_maximum_distance != 0.0 || target_minimum_distance != 0.0) {
+ Vector2 target_direction = Vector2(0, 1);
+ if (target_node_cache.is_valid()) {
+ stack->skeleton->draw_set_transform(Vector2(0, 0), 0.0);
+ Node2D *target = Object::cast_to<Node2D>(ObjectDB::get_instance(target_node_cache));
+ target_direction = operation_bone_one->get_global_position().direction_to(target->get_global_position());
+ }
+
+ stack->skeleton->draw_circle(target_direction * target_minimum_distance, 8, bone_ik_color);
+ stack->skeleton->draw_circle(target_direction * target_maximum_distance, 8, bone_ik_color);
+ stack->skeleton->draw_line(target_direction * target_minimum_distance, target_direction * target_maximum_distance, bone_ik_color, 2.0);
+ }
+ }
+ }
+#endif // TOOLS_ENABLED
+}
+
+void SkeletonModification2DTwoBoneIK::update_target_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ return;
+ }
+
+ target_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(target_node)) {
+ Node *node = stack->skeleton->get_node(target_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update target cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update target cache: node is not in the scene tree!");
+ target_node_cache = node->get_instance_id();
+ }
+ }
+ }
+}
+
+void SkeletonModification2DTwoBoneIK::update_joint_one_bone2d_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update joint one Bone2D cache: modification is not properly setup!");
+ return;
+ }
+
+ joint_one_bone2d_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(joint_one_bone2d_node)) {
+ Node *node = stack->skeleton->get_node(joint_one_bone2d_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update update joint one Bone2D cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update update joint one Bone2D cache: node is not in the scene tree!");
+ joint_one_bone2d_node_cache = node->get_instance_id();
+
+ Bone2D *bone = Object::cast_to<Bone2D>(node);
+ if (bone) {
+ joint_one_bone_idx = bone->get_index_in_skeleton();
+ } else {
+ ERR_FAIL_MSG("update joint one Bone2D cache: Nodepath to Bone2D is not a Bone2D node!");
+ }
+ }
+ }
+ }
+}
+
+void SkeletonModification2DTwoBoneIK::update_joint_two_bone2d_cache() {
+ if (!is_setup || !stack) {
+ ERR_PRINT_ONCE("Cannot update joint two Bone2D cache: modification is not properly setup!");
+ return;
+ }
+
+ joint_two_bone2d_node_cache = ObjectID();
+ if (stack->skeleton) {
+ if (stack->skeleton->is_inside_tree()) {
+ if (stack->skeleton->has_node(joint_two_bone2d_node)) {
+ Node *node = stack->skeleton->get_node(joint_two_bone2d_node);
+ ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
+ "Cannot update update joint two Bone2D cache: node is this modification's skeleton or cannot be found!");
+ ERR_FAIL_COND_MSG(!node->is_inside_tree(),
+ "Cannot update update joint two Bone2D cache: node is not in scene tree!");
+ joint_two_bone2d_node_cache = node->get_instance_id();
+
+ Bone2D *bone = Object::cast_to<Bone2D>(node);
+ if (bone) {
+ joint_two_bone_idx = bone->get_index_in_skeleton();
+ } else {
+ ERR_FAIL_MSG("update joint two Bone2D cache: Nodepath to Bone2D is not a Bone2D node!");
+ }
+ }
+ }
+ }
+}
+
+void SkeletonModification2DTwoBoneIK::set_target_node(const NodePath &p_target_node) {
+ target_node = p_target_node;
+ update_target_cache();
+}
+
+NodePath SkeletonModification2DTwoBoneIK::get_target_node() const {
+ return target_node;
+}
+
+void SkeletonModification2DTwoBoneIK::set_joint_one_bone2d_node(const NodePath &p_target_node) {
+ joint_one_bone2d_node = p_target_node;
+ update_joint_one_bone2d_cache();
+ notify_property_list_changed();
+}
+
+void SkeletonModification2DTwoBoneIK::set_target_minimum_distance(float p_distance) {
+ ERR_FAIL_COND_MSG(p_distance < 0, "Target minimum distance cannot be less than zero!");
+ target_minimum_distance = p_distance;
+}
+
+float SkeletonModification2DTwoBoneIK::get_target_minimum_distance() const {
+ return target_minimum_distance;
+}
+
+void SkeletonModification2DTwoBoneIK::set_target_maximum_distance(float p_distance) {
+ ERR_FAIL_COND_MSG(p_distance < 0, "Target maximum distance cannot be less than zero!");
+ target_maximum_distance = p_distance;
+}
+
+float SkeletonModification2DTwoBoneIK::get_target_maximum_distance() const {
+ return target_maximum_distance;
+}
+
+void SkeletonModification2DTwoBoneIK::set_flip_bend_direction(bool p_flip_direction) {
+ flip_bend_direction = p_flip_direction;
+
+#ifdef TOOLS_ENABLED
+ if (stack && is_setup) {
+ stack->set_editor_gizmos_dirty(true);
+ }
+#endif // TOOLS_ENABLED
+}
+
+bool SkeletonModification2DTwoBoneIK::get_flip_bend_direction() const {
+ return flip_bend_direction;
+}
+
+NodePath SkeletonModification2DTwoBoneIK::get_joint_one_bone2d_node() const {
+ return joint_one_bone2d_node;
+}
+
+void SkeletonModification2DTwoBoneIK::set_joint_two_bone2d_node(const NodePath &p_target_node) {
+ joint_two_bone2d_node = p_target_node;
+ update_joint_two_bone2d_cache();
+ notify_property_list_changed();
+}
+
+NodePath SkeletonModification2DTwoBoneIK::get_joint_two_bone2d_node() const {
+ return joint_two_bone2d_node;
+}
+
+void SkeletonModification2DTwoBoneIK::set_joint_one_bone_idx(int p_bone_idx) {
+ ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
+
+ if (is_setup) {
+ if (stack->skeleton) {
+ ERR_FAIL_INDEX_MSG(p_bone_idx, stack->skeleton->get_bone_count(), "Passed-in Bone index is out of range!");
+ joint_one_bone_idx = p_bone_idx;
+ joint_one_bone2d_node_cache = stack->skeleton->get_bone(p_bone_idx)->get_instance_id();
+ joint_one_bone2d_node = stack->skeleton->get_path_to(stack->skeleton->get_bone(p_bone_idx));
+ } else {
+ WARN_PRINT("TwoBoneIK: Cannot verify the joint bone index for joint one...");
+ joint_one_bone_idx = p_bone_idx;
+ }
+ } else {
+ WARN_PRINT("TwoBoneIK: Cannot verify the joint bone index for joint one...");
+ joint_one_bone_idx = p_bone_idx;
+ }
+
+ notify_property_list_changed();
+}
+
+int SkeletonModification2DTwoBoneIK::get_joint_one_bone_idx() const {
+ return joint_one_bone_idx;
+}
+
+void SkeletonModification2DTwoBoneIK::set_joint_two_bone_idx(int p_bone_idx) {
+ ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
+
+ if (is_setup) {
+ if (stack->skeleton) {
+ ERR_FAIL_INDEX_MSG(p_bone_idx, stack->skeleton->get_bone_count(), "Passed-in Bone index is out of range!");
+ joint_two_bone_idx = p_bone_idx;
+ joint_two_bone2d_node_cache = stack->skeleton->get_bone(p_bone_idx)->get_instance_id();
+ joint_two_bone2d_node = stack->skeleton->get_path_to(stack->skeleton->get_bone(p_bone_idx));
+ } else {
+ WARN_PRINT("TwoBoneIK: Cannot verify the joint bone index for joint two...");
+ joint_two_bone_idx = p_bone_idx;
+ }
+ } else {
+ WARN_PRINT("TwoBoneIK: Cannot verify the joint bone index for joint two...");
+ joint_two_bone_idx = p_bone_idx;
+ }
+
+ notify_property_list_changed();
+}
+
+int SkeletonModification2DTwoBoneIK::get_joint_two_bone_idx() const {
+ return joint_two_bone_idx;
+}
+
+#ifdef TOOLS_ENABLED
+void SkeletonModification2DTwoBoneIK::set_editor_draw_min_max(bool p_draw) {
+ editor_draw_min_max = p_draw;
+}
+
+bool SkeletonModification2DTwoBoneIK::get_editor_draw_min_max() const {
+ return editor_draw_min_max;
+}
+#endif // TOOLS_ENABLED
+
+void SkeletonModification2DTwoBoneIK::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification2DTwoBoneIK::set_target_node);
+ ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification2DTwoBoneIK::get_target_node);
+
+ ClassDB::bind_method(D_METHOD("set_target_minimum_distance", "minimum_distance"), &SkeletonModification2DTwoBoneIK::set_target_minimum_distance);
+ ClassDB::bind_method(D_METHOD("get_target_minimum_distance"), &SkeletonModification2DTwoBoneIK::get_target_minimum_distance);
+ ClassDB::bind_method(D_METHOD("set_target_maximum_distance", "maximum_distance"), &SkeletonModification2DTwoBoneIK::set_target_maximum_distance);
+ ClassDB::bind_method(D_METHOD("get_target_maximum_distance"), &SkeletonModification2DTwoBoneIK::get_target_maximum_distance);
+ ClassDB::bind_method(D_METHOD("set_flip_bend_direction", "flip_direction"), &SkeletonModification2DTwoBoneIK::set_flip_bend_direction);
+ ClassDB::bind_method(D_METHOD("get_flip_bend_direction"), &SkeletonModification2DTwoBoneIK::get_flip_bend_direction);
+
+ ClassDB::bind_method(D_METHOD("set_joint_one_bone2d_node", "bone2d_node"), &SkeletonModification2DTwoBoneIK::set_joint_one_bone2d_node);
+ ClassDB::bind_method(D_METHOD("get_joint_one_bone2d_node"), &SkeletonModification2DTwoBoneIK::get_joint_one_bone2d_node);
+ ClassDB::bind_method(D_METHOD("set_joint_one_bone_idx", "bone_idx"), &SkeletonModification2DTwoBoneIK::set_joint_one_bone_idx);
+ ClassDB::bind_method(D_METHOD("get_joint_one_bone_idx"), &SkeletonModification2DTwoBoneIK::get_joint_one_bone_idx);
+
+ ClassDB::bind_method(D_METHOD("set_joint_two_bone2d_node", "bone2d_node"), &SkeletonModification2DTwoBoneIK::set_joint_two_bone2d_node);
+ ClassDB::bind_method(D_METHOD("get_joint_two_bone2d_node"), &SkeletonModification2DTwoBoneIK::get_joint_two_bone2d_node);
+ ClassDB::bind_method(D_METHOD("set_joint_two_bone_idx", "bone_idx"), &SkeletonModification2DTwoBoneIK::set_joint_two_bone_idx);
+ ClassDB::bind_method(D_METHOD("get_joint_two_bone_idx"), &SkeletonModification2DTwoBoneIK::get_joint_two_bone_idx);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D"), "set_target_node", "get_target_node");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_minimum_distance", PROPERTY_HINT_RANGE, "0, 100000000, 0.01"), "set_target_minimum_distance", "get_target_minimum_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_maximum_distance", PROPERTY_HINT_NONE, "0, 100000000, 0.01"), "set_target_maximum_distance", "get_target_maximum_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_bend_direction", PROPERTY_HINT_NONE, ""), "set_flip_bend_direction", "get_flip_bend_direction");
+ ADD_GROUP("", "");
+}
+
+SkeletonModification2DTwoBoneIK::SkeletonModification2DTwoBoneIK() {
+ stack = nullptr;
+ is_setup = false;
+ enabled = true;
+ editor_draw_gizmo = true;
+}
+
+SkeletonModification2DTwoBoneIK::~SkeletonModification2DTwoBoneIK() {
+}
diff --git a/scene/resources/skeleton_modification_2d_twoboneik.h b/scene/resources/skeleton_modification_2d_twoboneik.h
new file mode 100644
index 0000000000..c7e545a488
--- /dev/null
+++ b/scene/resources/skeleton_modification_2d_twoboneik.h
@@ -0,0 +1,107 @@
+/*************************************************************************/
+/* skeleton_modification_2d_twoboneik.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATION2DTWOBONEIK_H
+#define SKELETONMODIFICATION2DTWOBONEIK_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+///////////////////////////////////////
+// SkeletonModification2DJIGGLE
+///////////////////////////////////////
+
+class SkeletonModification2DTwoBoneIK : public SkeletonModification2D {
+ GDCLASS(SkeletonModification2DTwoBoneIK, SkeletonModification2D);
+
+private:
+ NodePath target_node;
+ ObjectID target_node_cache;
+ float target_minimum_distance = 0;
+ float target_maximum_distance = 0;
+ bool flip_bend_direction = false;
+
+ NodePath joint_one_bone2d_node;
+ ObjectID joint_one_bone2d_node_cache;
+ int joint_one_bone_idx = -1;
+
+ NodePath joint_two_bone2d_node;
+ ObjectID joint_two_bone2d_node_cache;
+ int joint_two_bone_idx = -1;
+
+#ifdef TOOLS_ENABLED
+ bool editor_draw_min_max = false;
+#endif // TOOLS_ENABLED
+
+ void update_target_cache();
+ void update_joint_one_bone2d_cache();
+ void update_joint_two_bone2d_cache();
+
+protected:
+ static void _bind_methods();
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ bool _set(const StringName &p_path, const Variant &p_value);
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ void _execute(float p_delta) override;
+ void _setup_modification(SkeletonModificationStack2D *p_stack) override;
+ void _draw_editor_gizmo() override;
+
+ void set_target_node(const NodePath &p_target_node);
+ NodePath get_target_node() const;
+
+ void set_target_minimum_distance(float p_minimum_distance);
+ float get_target_minimum_distance() const;
+ void set_target_maximum_distance(float p_maximum_distance);
+ float get_target_maximum_distance() const;
+ void set_flip_bend_direction(bool p_flip_direction);
+ bool get_flip_bend_direction() const;
+
+ void set_joint_one_bone2d_node(const NodePath &p_node);
+ NodePath get_joint_one_bone2d_node() const;
+ void set_joint_one_bone_idx(int p_bone_idx);
+ int get_joint_one_bone_idx() const;
+
+ void set_joint_two_bone2d_node(const NodePath &p_node);
+ NodePath get_joint_two_bone2d_node() const;
+ void set_joint_two_bone_idx(int p_bone_idx);
+ int get_joint_two_bone_idx() const;
+
+#ifdef TOOLS_ENABLED
+ void set_editor_draw_min_max(bool p_draw);
+ bool get_editor_draw_min_max() const;
+#endif // TOOLS_ENABLED
+
+ SkeletonModification2DTwoBoneIK();
+ ~SkeletonModification2DTwoBoneIK();
+};
+
+#endif // SKELETONMODIFICATION2DTWOBONEIK_H
diff --git a/scene/resources/skeleton_modification_stack_2d.cpp b/scene/resources/skeleton_modification_stack_2d.cpp
new file mode 100644
index 0000000000..72c1c330ef
--- /dev/null
+++ b/scene/resources/skeleton_modification_stack_2d.cpp
@@ -0,0 +1,269 @@
+/*************************************************************************/
+/* skeleton_modification_stack_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_modification_stack_2d.h"
+#include "scene/2d/skeleton_2d.h"
+
+void SkeletonModificationStack2D::_get_property_list(List<PropertyInfo> *p_list) const {
+ for (int i = 0; i < modifications.size(); i++) {
+ p_list->push_back(
+ PropertyInfo(Variant::OBJECT, "modifications/" + itos(i),
+ PROPERTY_HINT_RESOURCE_TYPE,
+ "SkeletonModification2D",
+ PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
+ }
+}
+
+bool SkeletonModificationStack2D::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+
+ if (path.begins_with("modifications/")) {
+ int mod_idx = path.get_slicec('/', 1).to_int();
+ set_modification(mod_idx, p_value);
+ return true;
+ }
+ return true;
+}
+
+bool SkeletonModificationStack2D::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("modifications/")) {
+ int mod_idx = path.get_slicec('/', 1).to_int();
+ r_ret = get_modification(mod_idx);
+ return true;
+ }
+ return true;
+}
+
+void SkeletonModificationStack2D::setup() {
+ if (is_setup) {
+ return;
+ }
+
+ if (skeleton != nullptr) {
+ is_setup = true;
+ for (int i = 0; i < modifications.size(); i++) {
+ if (!modifications[i].is_valid()) {
+ continue;
+ }
+ modifications.get(i)->_setup_modification(this);
+ }
+
+#ifdef TOOLS_ENABLED
+ set_editor_gizmos_dirty(true);
+#endif // TOOLS_ENABLED
+
+ } else {
+ WARN_PRINT("Cannot setup SkeletonModificationStack2D: no Skeleton2D set!");
+ }
+}
+
+void SkeletonModificationStack2D::execute(float p_delta, int p_execution_mode) {
+ ERR_FAIL_COND_MSG(!is_setup || skeleton == nullptr || is_queued_for_deletion(),
+ "Modification stack is not properly setup and therefore cannot execute!");
+
+ if (!skeleton->is_inside_tree()) {
+ ERR_PRINT_ONCE("Skeleton is not inside SceneTree! Cannot execute modification!");
+ return;
+ }
+
+ if (!enabled) {
+ return;
+ }
+
+ for (int i = 0; i < modifications.size(); i++) {
+ if (!modifications[i].is_valid()) {
+ continue;
+ }
+
+ if (modifications[i]->get_execution_mode() == p_execution_mode) {
+ modifications.get(i)->_execute(p_delta);
+ }
+ }
+}
+
+void SkeletonModificationStack2D::draw_editor_gizmos() {
+ if (!is_setup) {
+ return;
+ }
+
+ if (editor_gizmo_dirty) {
+ for (int i = 0; i < modifications.size(); i++) {
+ if (!modifications[i].is_valid()) {
+ continue;
+ }
+
+ if (modifications[i]->editor_draw_gizmo) {
+ modifications.get(i)->_draw_editor_gizmo();
+ }
+ }
+ skeleton->draw_set_transform(Vector2(0, 0));
+ editor_gizmo_dirty = false;
+ }
+}
+
+void SkeletonModificationStack2D::set_editor_gizmos_dirty(bool p_dirty) {
+ if (!is_setup) {
+ return;
+ }
+
+ if (!editor_gizmo_dirty && p_dirty) {
+ editor_gizmo_dirty = p_dirty;
+ if (skeleton) {
+ skeleton->update();
+ }
+ } else {
+ editor_gizmo_dirty = p_dirty;
+ }
+}
+
+void SkeletonModificationStack2D::enable_all_modifications(bool p_enabled) {
+ for (int i = 0; i < modifications.size(); i++) {
+ if (!modifications[i].is_valid()) {
+ continue;
+ }
+ modifications.get(i)->set_enabled(p_enabled);
+ }
+}
+
+Ref<SkeletonModification2D> SkeletonModificationStack2D::get_modification(int p_mod_idx) const {
+ ERR_FAIL_INDEX_V(p_mod_idx, modifications.size(), nullptr);
+ return modifications[p_mod_idx];
+}
+
+void SkeletonModificationStack2D::add_modification(Ref<SkeletonModification2D> p_mod) {
+ ERR_FAIL_COND(!p_mod.is_valid());
+
+ p_mod->_setup_modification(this);
+ modifications.push_back(p_mod);
+
+#ifdef TOOLS_ENABLED
+ set_editor_gizmos_dirty(true);
+#endif // TOOLS_ENABLED
+}
+
+void SkeletonModificationStack2D::delete_modification(int p_mod_idx) {
+ ERR_FAIL_INDEX(p_mod_idx, modifications.size());
+ modifications.remove(p_mod_idx);
+
+#ifdef TOOLS_ENABLED
+ set_editor_gizmos_dirty(true);
+#endif // TOOLS_ENABLED
+}
+
+void SkeletonModificationStack2D::set_modification(int p_mod_idx, Ref<SkeletonModification2D> p_mod) {
+ ERR_FAIL_INDEX(p_mod_idx, modifications.size());
+
+ if (p_mod == nullptr) {
+ modifications.insert(p_mod_idx, nullptr);
+ } else {
+ p_mod->_setup_modification(this);
+ modifications.insert(p_mod_idx, p_mod);
+ }
+
+#ifdef TOOLS_ENABLED
+ set_editor_gizmos_dirty(true);
+#endif // TOOLS_ENABLED
+}
+
+void SkeletonModificationStack2D::set_modification_count(int p_count) {
+ modifications.resize(p_count);
+ notify_property_list_changed();
+
+#ifdef TOOLS_ENABLED
+ set_editor_gizmos_dirty(true);
+#endif // TOOLS_ENABLED
+}
+
+int SkeletonModificationStack2D::get_modification_count() const {
+ return modifications.size();
+}
+
+void SkeletonModificationStack2D::set_skeleton(Skeleton2D *p_skeleton) {
+ skeleton = p_skeleton;
+}
+
+Skeleton2D *SkeletonModificationStack2D::get_skeleton() const {
+ return skeleton;
+}
+
+bool SkeletonModificationStack2D::get_is_setup() const {
+ return is_setup;
+}
+
+void SkeletonModificationStack2D::set_enabled(bool p_enabled) {
+ enabled = p_enabled;
+}
+
+bool SkeletonModificationStack2D::get_enabled() const {
+ return enabled;
+}
+
+void SkeletonModificationStack2D::set_strength(float p_strength) {
+ ERR_FAIL_COND_MSG(p_strength < 0, "Strength cannot be less than zero!");
+ ERR_FAIL_COND_MSG(p_strength > 1, "Strength cannot be more than one!");
+ strength = p_strength;
+}
+
+float SkeletonModificationStack2D::get_strength() const {
+ return strength;
+}
+
+void SkeletonModificationStack2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("setup"), &SkeletonModificationStack2D::setup);
+ ClassDB::bind_method(D_METHOD("execute", "delta", "execution_mode"), &SkeletonModificationStack2D::execute);
+
+ ClassDB::bind_method(D_METHOD("enable_all_modifications", "enabled"), &SkeletonModificationStack2D::enable_all_modifications);
+ ClassDB::bind_method(D_METHOD("get_modification", "mod_idx"), &SkeletonModificationStack2D::get_modification);
+ ClassDB::bind_method(D_METHOD("add_modification", "modification"), &SkeletonModificationStack2D::add_modification);
+ ClassDB::bind_method(D_METHOD("delete_modification", "mod_idx"), &SkeletonModificationStack2D::delete_modification);
+ ClassDB::bind_method(D_METHOD("set_modification", "mod_idx", "modification"), &SkeletonModificationStack2D::set_modification);
+
+ ClassDB::bind_method(D_METHOD("set_modification_count"), &SkeletonModificationStack2D::set_modification_count);
+ ClassDB::bind_method(D_METHOD("get_modification_count"), &SkeletonModificationStack2D::get_modification_count);
+
+ ClassDB::bind_method(D_METHOD("get_is_setup"), &SkeletonModificationStack2D::get_is_setup);
+
+ ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &SkeletonModificationStack2D::set_enabled);
+ ClassDB::bind_method(D_METHOD("get_enabled"), &SkeletonModificationStack2D::get_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_strength", "strength"), &SkeletonModificationStack2D::set_strength);
+ ClassDB::bind_method(D_METHOD("get_strength"), &SkeletonModificationStack2D::get_strength);
+
+ ClassDB::bind_method(D_METHOD("get_skeleton"), &SkeletonModificationStack2D::get_skeleton);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0, 1, 0.001"), "set_strength", "get_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1"), "set_modification_count", "get_modification_count");
+}
+
+SkeletonModificationStack2D::SkeletonModificationStack2D() {
+}
diff --git a/scene/resources/skeleton_modification_stack_2d.h b/scene/resources/skeleton_modification_stack_2d.h
new file mode 100644
index 0000000000..58855701a1
--- /dev/null
+++ b/scene/resources/skeleton_modification_stack_2d.h
@@ -0,0 +1,99 @@
+/*************************************************************************/
+/* skeleton_modification_stack_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SKELETONMODIFICATIONSTACK2D_H
+#define SKELETONMODIFICATIONSTACK2D_H
+
+#include "scene/2d/skeleton_2d.h"
+#include "scene/resources/skeleton_modification_2d.h"
+
+///////////////////////////////////////
+// SkeletonModificationStack2D
+///////////////////////////////////////
+
+class Skeleton2D;
+class SkeletonModification2D;
+class Bone2D;
+
+class SkeletonModificationStack2D : public Resource {
+ GDCLASS(SkeletonModificationStack2D, Resource);
+ friend class Skeleton2D;
+ friend class SkeletonModification2D;
+
+protected:
+ static void _bind_methods();
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+ bool _set(const StringName &p_path, const Variant &p_value);
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+
+public:
+ Skeleton2D *skeleton = nullptr;
+ bool is_setup = false;
+ bool enabled = false;
+ float strength = 1.0;
+
+ enum EXECUTION_MODE {
+ execution_mode_process,
+ execution_mode_physics_process
+ };
+
+ Vector<Ref<SkeletonModification2D>> modifications = Vector<Ref<SkeletonModification2D>>();
+
+ void setup();
+ void execute(float p_delta, int p_execution_mode);
+
+ bool editor_gizmo_dirty = false;
+ void draw_editor_gizmos();
+ void set_editor_gizmos_dirty(bool p_dirty);
+
+ void enable_all_modifications(bool p_enable);
+ Ref<SkeletonModification2D> get_modification(int p_mod_idx) const;
+ void add_modification(Ref<SkeletonModification2D> p_mod);
+ void delete_modification(int p_mod_idx);
+ void set_modification(int p_mod_idx, Ref<SkeletonModification2D> p_mod);
+
+ void set_modification_count(int p_count);
+ int get_modification_count() const;
+
+ void set_skeleton(Skeleton2D *p_skeleton);
+ Skeleton2D *get_skeleton() const;
+
+ bool get_is_setup() const;
+
+ void set_enabled(bool p_enabled);
+ bool get_enabled() const;
+
+ void set_strength(float p_strength);
+ float get_strength() const;
+
+ SkeletonModificationStack2D();
+};
+
+#endif // SKELETONMODIFICATION2D_H
diff --git a/scene/resources/skin.cpp b/scene/resources/skin.cpp
index fee8fdbde2..710612ae05 100644
--- a/scene/resources/skin.cpp
+++ b/scene/resources/skin.cpp
@@ -38,14 +38,14 @@ void Skin::set_bind_count(int p_size) {
emit_changed();
}
-void Skin::add_bind(int p_bone, const Transform &p_pose) {
+void Skin::add_bind(int p_bone, const Transform3D &p_pose) {
uint32_t index = bind_count;
set_bind_count(bind_count + 1);
set_bind_bone(index, p_bone);
set_bind_pose(index, p_pose);
}
-void Skin::add_named_bind(const String &p_name, const Transform &p_pose) {
+void Skin::add_named_bind(const String &p_name, const Transform3D &p_pose) {
uint32_t index = bind_count;
set_bind_count(bind_count + 1);
set_bind_name(index, p_name);
@@ -68,7 +68,7 @@ void Skin::set_bind_bone(int p_index, int p_bone) {
emit_changed();
}
-void Skin::set_bind_pose(int p_index, const Transform &p_pose) {
+void Skin::set_bind_pose(int p_index, const Transform3D &p_pose) {
ERR_FAIL_INDEX(p_index, bind_count);
binds_ptr[p_index].pose = p_pose;
emit_changed();
@@ -134,7 +134,7 @@ void Skin::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < get_bind_count(); i++) {
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bind/" + itos(i) + "/name"));
p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater", get_bind_name(i) != StringName() ? PROPERTY_USAGE_NOEDITOR : PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM, "bind/" + itos(i) + "/pose"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, "bind/" + itos(i) + "/pose"));
}
}
diff --git a/scene/resources/skin.h b/scene/resources/skin.h
index f5d64f96aa..6857bf743a 100644
--- a/scene/resources/skin.h
+++ b/scene/resources/skin.h
@@ -39,7 +39,7 @@ class Skin : public Resource {
struct Bind {
int bone = -1;
StringName name;
- Transform pose;
+ Transform3D pose;
};
Vector<Bind> binds;
@@ -59,11 +59,11 @@ public:
void set_bind_count(int p_size);
inline int get_bind_count() const { return bind_count; }
- void add_bind(int p_bone, const Transform &p_pose);
- void add_named_bind(const String &p_name, const Transform &p_pose);
+ void add_bind(int p_bone, const Transform3D &p_pose);
+ void add_named_bind(const String &p_name, const Transform3D &p_pose);
void set_bind_bone(int p_index, int p_bone);
- void set_bind_pose(int p_index, const Transform &p_pose);
+ void set_bind_pose(int p_index, const Transform3D &p_pose);
void set_bind_name(int p_index, const StringName &p_name);
inline int get_bind_bone(int p_index) const {
@@ -80,9 +80,9 @@ public:
return binds_ptr[p_index].name;
}
- inline Transform get_bind_pose(int p_index) const {
+ inline Transform3D get_bind_pose(int p_index) const {
#ifdef DEBUG_ENABLED
- ERR_FAIL_INDEX_V(p_index, bind_count, Transform());
+ ERR_FAIL_INDEX_V(p_index, bind_count, Transform3D());
#endif
return binds_ptr[p_index].pose;
}
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index f50ee9c4c8..9d79c22159 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -193,7 +193,6 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() {
code += "uniform float ground_energy = 1.0;\n\n";
code += "uniform float sun_angle_max = 1.74;\n";
code += "uniform float sun_curve : hint_range(0, 1) = 0.05;\n\n";
- code += "const float PI = 3.1415926535897932384626433833;\n\n";
code += "void sky() {\n";
code += "\tfloat v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));\n";
code += "\tfloat c = (1.0 - v_angle / (PI * 0.5));\n";
@@ -499,7 +498,6 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() {
code += "uniform sampler2D night_sky : hint_black;";
- code += "const float PI = 3.141592653589793238462643383279502884197169;\n";
code += "const vec3 UP = vec3( 0.0, 1.0, 0.0 );\n\n";
code += "// Sun constants\n";
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 2159f1bc97..87371224e0 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -121,7 +121,6 @@ void StyleBoxTexture::set_texture(Ref<Texture2D> p_texture) {
} else {
region_rect = Rect2(Point2(), texture->get_size());
}
- emit_signal("texture_changed");
emit_changed();
}
@@ -285,8 +284,6 @@ void StyleBoxTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_v_axis_stretch_mode", "mode"), &StyleBoxTexture::set_v_axis_stretch_mode);
ClassDB::bind_method(D_METHOD("get_v_axis_stretch_mode"), &StyleBoxTexture::get_v_axis_stretch_mode);
- ADD_SIGNAL(MethodInfo("texture_changed"));
-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
ADD_GROUP("Margin", "margin_");
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index ff682a40f4..1e78561bec 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -35,6 +35,7 @@
SurfaceTool::OptimizeVertexCacheFunc SurfaceTool::optimize_vertex_cache_func = nullptr;
SurfaceTool::SimplifyFunc SurfaceTool::simplify_func = nullptr;
+SurfaceTool::SimplifyWithAttribFunc SurfaceTool::simplify_with_attrib_func = nullptr;
SurfaceTool::SimplifyScaleFunc SurfaceTool::simplify_scale_func = nullptr;
SurfaceTool::SimplifySloppyFunc SurfaceTool::simplify_sloppy_func = nullptr;
@@ -369,13 +370,13 @@ Array SurfaceTool::commit_to_arrays() {
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
const Vertex &v = vertex_array[idx];
- w[idx + 0] = v.tangent.x;
- w[idx + 1] = v.tangent.y;
- w[idx + 2] = v.tangent.z;
+ w[idx * 4 + 0] = v.tangent.x;
+ w[idx * 4 + 1] = v.tangent.y;
+ w[idx * 4 + 2] = v.tangent.z;
//float d = v.tangent.dot(v.binormal,v.normal);
float d = v.binormal.dot(v.normal.cross(v.tangent));
- w[idx + 3] = d < 0 ? -1 : 1;
+ w[idx * 4 + 3] = d < 0 ? -1 : 1;
}
a[i] = array;
@@ -856,7 +857,7 @@ void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_sur
_create_list_from_arrays(arr[shape_idx], &vertex_array, &index_array, format);
}
-void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform) {
+void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform3D &p_xform) {
ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::append_from() must be a valid object of type Mesh");
if (vertex_array.size() == 0) {
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index 28addf2245..bde6702759 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -35,8 +35,8 @@
#include "scene/resources/mesh.h"
#include "thirdparty/misc/mikktspace.h"
-class SurfaceTool : public Reference {
- GDCLASS(SurfaceTool, Reference);
+class SurfaceTool : public RefCounted {
+ GDCLASS(SurfaceTool, RefCounted);
public:
struct Vertex {
@@ -78,6 +78,8 @@ public:
static OptimizeVertexCacheFunc optimize_vertex_cache_func;
typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_error);
static SimplifyFunc simplify_func;
+ typedef size_t (*SimplifyWithAttribFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float *result_error, const float *attributes, const float *attribute_weights, size_t attribute_count);
+ static SimplifyWithAttribFunc simplify_with_attrib_func;
typedef float (*SimplifyScaleFunc)(const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
static SimplifyScaleFunc simplify_scale_func;
typedef size_t (*SimplifySloppyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *out_result_error);
@@ -184,7 +186,7 @@ public:
Array commit_to_arrays();
void create_from(const Ref<Mesh> &p_existing, int p_surface);
void create_from_blend_shape(const Ref<Mesh> &p_existing, int p_surface, const String &p_blend_shape_name);
- void append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform);
+ void append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform3D &p_xform);
Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>(), uint32_t p_flags = 0);
SurfaceTool();
diff --git a/scene/resources/text_file.cpp b/scene/resources/text_file.cpp
index cf07003720..33bb0a83e9 100644
--- a/scene/resources/text_file.cpp
+++ b/scene/resources/text_file.cpp
@@ -30,7 +30,7 @@
#include "text_file.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
bool TextFile::has_text() const {
return text != "";
@@ -55,10 +55,10 @@ Error TextFile::load_text(const String &p_path) {
ERR_FAIL_COND_V_MSG(err, err, "Cannot open TextFile '" + p_path + "'.");
- int len = f->get_len();
+ uint64_t len = f->get_length();
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
- int r = f->get_buffer(w, len);
+ uint64_t r = f->get_buffer(w, len);
f->close();
memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index 925867a1f2..f1eff6e84f 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -74,7 +74,7 @@ void TextLine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextLine::set_flags);
ClassDB::bind_method(D_METHOD("get_flags"), &TextLine::get_flags);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida justification,Word justification,Trim edge spaces after justification,Justification only after last tab"), "set_flags", "get_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justify,Word Justify,Trim Edge Spaces After Justify,Justify Only After Last Tab"), "set_flags", "get_flags");
ClassDB::bind_method(D_METHOD("get_objects"), &TextLine::get_objects);
ClassDB::bind_method(D_METHOD("get_object_rect", "key"), &TextLine::get_object_rect);
diff --git a/scene/resources/text_line.h b/scene/resources/text_line.h
index 74d4f2c32c..1b5c1a3123 100644
--- a/scene/resources/text_line.h
+++ b/scene/resources/text_line.h
@@ -36,8 +36,8 @@
/*************************************************************************/
-class TextLine : public Reference {
- GDCLASS(TextLine, Reference);
+class TextLine : public RefCounted {
+ GDCLASS(TextLine, RefCounted);
RID rid;
int spacing_top = 0;
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 341f5abd80..958c94fe31 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -72,7 +72,7 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextParagraph::set_flags);
ClassDB::bind_method(D_METHOD("get_flags"), &TextParagraph::get_flags);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida justification,Word justification,Trim edge spaces after justification,Justification only after last tab,Break mandatory,Break words,Break graphemes"), "set_flags", "get_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justify,Word Justify,Trim Edge Spaces After Justify,Justify Only After Last Tab,Break Mandatory,Break Words,Break Graphemes"), "set_flags", "get_flags");
ClassDB::bind_method(D_METHOD("set_width", "width"), &TextParagraph::set_width);
ClassDB::bind_method(D_METHOD("get_width"), &TextParagraph::get_width);
diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h
index 4396b07130..a34e745090 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -36,8 +36,8 @@
/*************************************************************************/
-class TextParagraph : public Reference {
- GDCLASS(TextParagraph, Reference);
+class TextParagraph : public RefCounted {
+ GDCLASS(TextParagraph, RefCounted);
RID dropcap_rid;
int dropcap_lines = 0;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 624eae0411..064563d4b5 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -327,7 +327,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit
uint32_t mipmaps = f->get_32();
Image::Format format = Image::Format(f->get_32());
- if (data_format == DATA_FORMAT_LOSSLESS || data_format == DATA_FORMAT_LOSSY || data_format == DATA_FORMAT_BASIS_UNIVERSAL) {
+ if (data_format == DATA_FORMAT_PNG || data_format == DATA_FORMAT_WEBP || data_format == DATA_FORMAT_BASIS_UNIVERSAL) {
//look for a PNG or WEBP file inside
int sw = w;
@@ -335,7 +335,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit
//mipmaps need to be read independently, they will be later combined
Vector<Ref<Image>> mipmap_images;
- int total_size = 0;
+ uint64_t total_size = 0;
bool first = true;
@@ -360,10 +360,10 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit
Ref<Image> img;
if (data_format == DATA_FORMAT_BASIS_UNIVERSAL) {
img = Image::basis_universal_unpacker(pv);
- } else if (data_format == DATA_FORMAT_LOSSLESS) {
- img = Image::lossless_unpacker(pv);
+ } else if (data_format == DATA_FORMAT_PNG) {
+ img = Image::png_unpacker(pv);
} else {
- img = Image::lossy_unpacker(pv);
+ img = Image::webp_unpacker(pv);
}
if (img.is_null() || img->is_empty()) {
@@ -490,7 +490,7 @@ Image::Format StreamTexture2D::get_format() const {
return format;
}
-Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) {
+Error StreamTexture2D::_load_data(const String &p_path, int &r_width, int &r_height, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) {
alpha_cache.unref();
ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER);
@@ -511,8 +511,8 @@ Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &t
memdelete(f);
ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
}
- tw_custom = f->get_32();
- th_custom = f->get_32();
+ r_width = f->get_32();
+ r_height = f->get_32();
uint32_t df = f->get_32(); //data format
//skip reserved
@@ -551,7 +551,7 @@ Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &t
}
Error StreamTexture2D::load(const String &p_path) {
- int lw, lh, lwc, lhc;
+ int lw, lh;
Ref<Image> image;
image.instance();
@@ -560,7 +560,7 @@ Error StreamTexture2D::load(const String &p_path) {
bool request_roughness;
int mipmap_limit;
- Error err = _load_data(p_path, lw, lh, lwc, lhc, image, request_3d, request_normal, request_roughness, mipmap_limit);
+ Error err = _load_data(p_path, lw, lh, image, request_3d, request_normal, request_roughness, mipmap_limit);
if (err) {
return err;
}
@@ -571,12 +571,12 @@ Error StreamTexture2D::load(const String &p_path) {
} else {
texture = RS::get_singleton()->texture_2d_create(image);
}
- if (lwc || lhc) {
- RS::get_singleton()->texture_set_size_override(texture, lwc, lhc);
+ if (lw || lh) {
+ RS::get_singleton()->texture_set_size_override(texture, lw, lh);
}
- w = lwc ? lwc : lw;
- h = lhc ? lhc : lh;
+ w = lw;
+ h = lh;
path_to_file = p_path;
format = image->get_format();
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 264d85d187..3b1815266d 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -31,10 +31,10 @@
#ifndef TEXTURE_H
#define TEXTURE_H
+#include "core/io/file_access.h"
#include "core/io/resource.h"
#include "core/io/resource_loader.h"
#include "core/math/rect2.h"
-#include "core/os/file_access.h"
#include "core/os/mutex.h"
#include "core/os/rw_lock.h"
#include "core/os/thread_safe.h"
@@ -136,8 +136,8 @@ class StreamTexture2D : public Texture2D {
public:
enum DataFormat {
DATA_FORMAT_IMAGE,
- DATA_FORMAT_LOSSLESS,
- DATA_FORMAT_LOSSY,
+ DATA_FORMAT_PNG,
+ DATA_FORMAT_WEBP,
DATA_FORMAT_BASIS_UNIVERSAL,
};
@@ -146,9 +146,6 @@ public:
};
enum FormatBits {
- FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1,
- FORMAT_BIT_LOSSLESS = 1 << 20,
- FORMAT_BIT_LOSSY = 1 << 21,
FORMAT_BIT_STREAM = 1 << 22,
FORMAT_BIT_HAS_MIPMAPS = 1 << 23,
FORMAT_BIT_DETECT_3D = 1 << 24,
@@ -158,7 +155,7 @@ public:
};
private:
- Error _load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit = 0);
+ Error _load_data(const String &p_path, int &r_width, int &r_height, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit = 0);
String path_to_file;
mutable RID texture;
Image::Format format = Image::FORMAT_MAX;
@@ -389,8 +386,8 @@ class StreamTextureLayered : public TextureLayered {
public:
enum DataFormat {
DATA_FORMAT_IMAGE,
- DATA_FORMAT_LOSSLESS,
- DATA_FORMAT_LOSSY,
+ DATA_FORMAT_PNG,
+ DATA_FORMAT_WEBP,
DATA_FORMAT_BASIS_UNIVERSAL,
};
@@ -399,9 +396,6 @@ public:
};
enum FormatBits {
- FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1,
- FORMAT_BIT_LOSSLESS = 1 << 20,
- FORMAT_BIT_LOSSY = 1 << 21,
FORMAT_BIT_STREAM = 1 << 22,
FORMAT_BIT_HAS_MIPMAPS = 1 << 23,
};
@@ -532,8 +526,8 @@ class StreamTexture3D : public Texture3D {
public:
enum DataFormat {
DATA_FORMAT_IMAGE,
- DATA_FORMAT_LOSSLESS,
- DATA_FORMAT_LOSSY,
+ DATA_FORMAT_PNG,
+ DATA_FORMAT_WEBP,
DATA_FORMAT_BASIS_UNIVERSAL,
};
@@ -542,9 +536,6 @@ public:
};
enum FormatBits {
- FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1,
- FORMAT_BIT_LOSSLESS = 1 << 20,
- FORMAT_BIT_LOSSY = 1 << 21,
FORMAT_BIT_STREAM = 1 << 22,
FORMAT_BIT_HAS_MIPMAPS = 1 << 23,
};
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index e8b203417e..89ac033207 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -29,18 +29,23 @@
/*************************************************************************/
#include "theme.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/string/print_string.h"
void Theme::_emit_theme_changed() {
+ if (no_change_propagation) {
+ return;
+ }
+
+ notify_property_list_changed();
emit_changed();
}
-Vector<String> Theme::_get_icon_list(const String &p_node_type) const {
+Vector<String> Theme::_get_icon_list(const String &p_theme_type) const {
Vector<String> ilret;
List<StringName> il;
- get_icon_list(p_node_type, &il);
+ get_icon_list(p_theme_type, &il);
ilret.resize(il.size());
int i = 0;
@@ -66,11 +71,11 @@ Vector<String> Theme::_get_icon_type_list() const {
return ilret;
}
-Vector<String> Theme::_get_stylebox_list(const String &p_node_type) const {
+Vector<String> Theme::_get_stylebox_list(const String &p_theme_type) const {
Vector<String> ilret;
List<StringName> il;
- get_stylebox_list(p_node_type, &il);
+ get_stylebox_list(p_theme_type, &il);
ilret.resize(il.size());
int i = 0;
@@ -96,11 +101,11 @@ Vector<String> Theme::_get_stylebox_type_list() const {
return ilret;
}
-Vector<String> Theme::_get_font_list(const String &p_node_type) const {
+Vector<String> Theme::_get_font_list(const String &p_theme_type) const {
Vector<String> ilret;
List<StringName> il;
- get_font_list(p_node_type, &il);
+ get_font_list(p_theme_type, &il);
ilret.resize(il.size());
int i = 0;
@@ -126,11 +131,11 @@ Vector<String> Theme::_get_font_type_list() const {
return ilret;
}
-Vector<String> Theme::_get_font_size_list(const String &p_node_type) const {
+Vector<String> Theme::_get_font_size_list(const String &p_theme_type) const {
Vector<String> ilret;
List<StringName> il;
- get_font_size_list(p_node_type, &il);
+ get_font_size_list(p_theme_type, &il);
ilret.resize(il.size());
int i = 0;
@@ -156,11 +161,11 @@ Vector<String> Theme::_get_font_size_type_list() const {
return ilret;
}
-Vector<String> Theme::_get_color_list(const String &p_node_type) const {
+Vector<String> Theme::_get_color_list(const String &p_theme_type) const {
Vector<String> ilret;
List<StringName> il;
- get_color_list(p_node_type, &il);
+ get_color_list(p_theme_type, &il);
ilret.resize(il.size());
int i = 0;
@@ -186,11 +191,11 @@ Vector<String> Theme::_get_color_type_list() const {
return ilret;
}
-Vector<String> Theme::_get_constant_list(const String &p_node_type) const {
+Vector<String> Theme::_get_constant_list(const String &p_theme_type) const {
Vector<String> ilret;
List<StringName> il;
- get_constant_list(p_node_type, &il);
+ get_constant_list(p_theme_type, &il);
ilret.resize(il.size());
int i = 0;
@@ -216,20 +221,20 @@ Vector<String> Theme::_get_constant_type_list() const {
return ilret;
}
-Vector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_node_type) const {
+Vector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_theme_type) const {
switch (p_data_type) {
case DATA_TYPE_COLOR:
- return _get_color_list(p_node_type);
+ return _get_color_list(p_theme_type);
case DATA_TYPE_CONSTANT:
- return _get_constant_list(p_node_type);
+ return _get_constant_list(p_theme_type);
case DATA_TYPE_FONT:
- return _get_font_list(p_node_type);
+ return _get_font_list(p_theme_type);
case DATA_TYPE_FONT_SIZE:
- return _get_font_size_list(p_node_type);
+ return _get_font_size_list(p_theme_type);
case DATA_TYPE_ICON:
- return _get_icon_list(p_node_type);
+ return _get_icon_list(p_theme_type);
case DATA_TYPE_STYLEBOX:
- return _get_stylebox_list(p_node_type);
+ return _get_stylebox_list(p_theme_type);
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
@@ -278,19 +283,19 @@ bool Theme::_set(const StringName &p_name, const Variant &p_value) {
if (sname.find("/") != -1) {
String type = sname.get_slicec('/', 1);
- String node_type = sname.get_slicec('/', 0);
+ String theme_type = sname.get_slicec('/', 0);
String name = sname.get_slicec('/', 2);
if (type == "icons") {
- set_icon(name, node_type, p_value);
+ set_icon(name, theme_type, p_value);
} else if (type == "styles") {
- set_stylebox(name, node_type, p_value);
+ set_stylebox(name, theme_type, p_value);
} else if (type == "fonts") {
- set_font(name, node_type, p_value);
+ set_font(name, theme_type, p_value);
} else if (type == "colors") {
- set_color(name, node_type, p_value);
+ set_color(name, theme_type, p_value);
} else if (type == "constants") {
- set_constant(name, node_type, p_value);
+ set_constant(name, theme_type, p_value);
} else {
return false;
}
@@ -306,31 +311,31 @@ bool Theme::_get(const StringName &p_name, Variant &r_ret) const {
if (sname.find("/") != -1) {
String type = sname.get_slicec('/', 1);
- String node_type = sname.get_slicec('/', 0);
+ String theme_type = sname.get_slicec('/', 0);
String name = sname.get_slicec('/', 2);
if (type == "icons") {
- if (!has_icon(name, node_type)) {
+ if (!has_icon(name, theme_type)) {
r_ret = Ref<Texture2D>();
} else {
- r_ret = get_icon(name, node_type);
+ r_ret = get_icon(name, theme_type);
}
} else if (type == "styles") {
- if (!has_stylebox(name, node_type)) {
+ if (!has_stylebox(name, theme_type)) {
r_ret = Ref<StyleBox>();
} else {
- r_ret = get_stylebox(name, node_type);
+ r_ret = get_stylebox(name, theme_type);
}
} else if (type == "fonts") {
- if (!has_font(name, node_type)) {
+ if (!has_font(name, theme_type)) {
r_ret = Ref<Font>();
} else {
- r_ret = get_font(name, node_type);
+ r_ret = get_font(name, theme_type);
}
} else if (type == "colors") {
- r_ret = get_color(name, node_type);
+ r_ret = get_color(name, theme_type);
} else if (type == "constants") {
- r_ret = get_constant(name, node_type);
+ r_ret = get_constant(name, theme_type);
} else {
return false;
}
@@ -415,8 +420,7 @@ void Theme::set_default_theme_font(const Ref<Font> &p_default_font) {
default_theme_font->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED);
}
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
Ref<Font> Theme::get_default_theme_font() const {
@@ -430,8 +434,7 @@ void Theme::set_default_theme_font_size(int p_font_size) {
default_theme_font_size = p_font_size;
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
int Theme::get_default_theme_font_size() const {
@@ -477,83 +480,79 @@ void Theme::set_default_font_size(int p_font_size) {
default_font_size = p_font_size;
}
-void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture2D> &p_icon) {
- bool new_value = !icon_map.has(p_node_type) || !icon_map[p_node_type].has(p_name);
-
- if (icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) {
- icon_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
+void Theme::set_icon(const StringName &p_name, const StringName &p_theme_type, const Ref<Texture2D> &p_icon) {
+ if (icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) {
+ icon_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
}
- icon_map[p_node_type][p_name] = p_icon;
+ icon_map[p_theme_type][p_name] = p_icon;
if (p_icon.is_valid()) {
- icon_map[p_node_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ icon_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED);
}
- if (new_value) {
- notify_property_list_changed();
- emit_changed();
- }
+ _emit_theme_changed();
}
-Ref<Texture2D> Theme::get_icon(const StringName &p_name, const StringName &p_node_type) const {
- if (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) {
- return icon_map[p_node_type][p_name];
+Ref<Texture2D> Theme::get_icon(const StringName &p_name, const StringName &p_theme_type) const {
+ if (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) {
+ return icon_map[p_theme_type][p_name];
} else {
return default_icon;
}
}
-bool Theme::has_icon(const StringName &p_name, const StringName &p_node_type) const {
- return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid());
+bool Theme::has_icon(const StringName &p_name, const StringName &p_theme_type) const {
+ return (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid());
}
-bool Theme::has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const {
- return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name));
+bool Theme::has_icon_nocheck(const StringName &p_name, const StringName &p_theme_type) const {
+ return (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name));
}
-void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(icon_map[p_node_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
- ERR_FAIL_COND_MSG(!icon_map[p_node_type].has(p_old_name), "Cannot rename the icon '" + String(p_old_name) + "' because it does not exist.");
+void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!icon_map.has(p_theme_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(icon_map[p_theme_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
+ ERR_FAIL_COND_MSG(!icon_map[p_theme_type].has(p_old_name), "Cannot rename the icon '" + String(p_old_name) + "' because it does not exist.");
- icon_map[p_node_type][p_name] = icon_map[p_node_type][p_old_name];
- icon_map[p_node_type].erase(p_old_name);
+ icon_map[p_theme_type][p_name] = icon_map[p_theme_type][p_old_name];
+ icon_map[p_theme_type].erase(p_old_name);
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
-void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot clear the icon '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(!icon_map[p_node_type].has(p_name), "Cannot clear the icon '" + String(p_name) + "' because it does not exist.");
+void Theme::clear_icon(const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!icon_map.has(p_theme_type), "Cannot clear the icon '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(!icon_map[p_theme_type].has(p_name), "Cannot clear the icon '" + String(p_name) + "' because it does not exist.");
- if (icon_map[p_node_type][p_name].is_valid()) {
- icon_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
+ if (icon_map[p_theme_type][p_name].is_valid()) {
+ icon_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
}
- icon_map[p_node_type].erase(p_name);
+ icon_map[p_theme_type].erase(p_name);
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
-void Theme::get_icon_list(StringName p_node_type, List<StringName> *p_list) const {
+void Theme::get_icon_list(StringName p_theme_type, List<StringName> *p_list) const {
ERR_FAIL_NULL(p_list);
- if (!icon_map.has(p_node_type)) {
+ if (!icon_map.has(p_theme_type)) {
return;
}
const StringName *key = nullptr;
- while ((key = icon_map[p_node_type].next(key))) {
+ while ((key = icon_map[p_theme_type].next(key))) {
p_list->push_back(*key);
}
}
-void Theme::add_icon_type(const StringName &p_node_type) {
- icon_map[p_node_type] = HashMap<StringName, Ref<Texture2D>>();
+void Theme::add_icon_type(const StringName &p_theme_type) {
+ if (icon_map.has(p_theme_type)) {
+ return;
+ }
+ icon_map[p_theme_type] = HashMap<StringName, Ref<Texture2D>>();
}
void Theme::get_icon_type_list(List<StringName> *p_list) const {
@@ -565,83 +564,79 @@ void Theme::get_icon_type_list(List<StringName> *p_list) const {
}
}
-void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style) {
- bool new_value = !style_map.has(p_node_type) || !style_map[p_node_type].has(p_name);
-
- if (style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) {
- style_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
+void Theme::set_stylebox(const StringName &p_name, const StringName &p_theme_type, const Ref<StyleBox> &p_style) {
+ if (style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) {
+ style_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
}
- style_map[p_node_type][p_name] = p_style;
+ style_map[p_theme_type][p_name] = p_style;
if (p_style.is_valid()) {
- style_map[p_node_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ style_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED);
}
- if (new_value) {
- notify_property_list_changed();
- }
- emit_changed();
+ _emit_theme_changed();
}
-Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_node_type) const {
- if (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) {
- return style_map[p_node_type][p_name];
+Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
+ if (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) {
+ return style_map[p_theme_type][p_name];
} else {
return default_style;
}
}
-bool Theme::has_stylebox(const StringName &p_name, const StringName &p_node_type) const {
- return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid());
+bool Theme::has_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
+ return (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid());
}
-bool Theme::has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const {
- return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name));
+bool Theme::has_stylebox_nocheck(const StringName &p_name, const StringName &p_theme_type) const {
+ return (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name));
}
-void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(style_map[p_node_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
- ERR_FAIL_COND_MSG(!style_map[p_node_type].has(p_old_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because it does not exist.");
+void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!style_map.has(p_theme_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(style_map[p_theme_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
+ ERR_FAIL_COND_MSG(!style_map[p_theme_type].has(p_old_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because it does not exist.");
- style_map[p_node_type][p_name] = style_map[p_node_type][p_old_name];
- style_map[p_node_type].erase(p_old_name);
+ style_map[p_theme_type][p_name] = style_map[p_theme_type][p_old_name];
+ style_map[p_theme_type].erase(p_old_name);
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
-void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot clear the stylebox '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(!style_map[p_node_type].has(p_name), "Cannot clear the stylebox '" + String(p_name) + "' because it does not exist.");
+void Theme::clear_stylebox(const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!style_map.has(p_theme_type), "Cannot clear the stylebox '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(!style_map[p_theme_type].has(p_name), "Cannot clear the stylebox '" + String(p_name) + "' because it does not exist.");
- if (style_map[p_node_type][p_name].is_valid()) {
- style_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
+ if (style_map[p_theme_type][p_name].is_valid()) {
+ style_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
}
- style_map[p_node_type].erase(p_name);
+ style_map[p_theme_type].erase(p_name);
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
-void Theme::get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const {
+void Theme::get_stylebox_list(StringName p_theme_type, List<StringName> *p_list) const {
ERR_FAIL_NULL(p_list);
- if (!style_map.has(p_node_type)) {
+ if (!style_map.has(p_theme_type)) {
return;
}
const StringName *key = nullptr;
- while ((key = style_map[p_node_type].next(key))) {
+ while ((key = style_map[p_theme_type].next(key))) {
p_list->push_back(*key);
}
}
-void Theme::add_stylebox_type(const StringName &p_node_type) {
- style_map[p_node_type] = HashMap<StringName, Ref<StyleBox>>();
+void Theme::add_stylebox_type(const StringName &p_theme_type) {
+ if (style_map.has(p_theme_type)) {
+ return;
+ }
+ style_map[p_theme_type] = HashMap<StringName, Ref<StyleBox>>();
}
void Theme::get_stylebox_type_list(List<StringName> *p_list) const {
@@ -653,28 +648,23 @@ void Theme::get_stylebox_type_list(List<StringName> *p_list) const {
}
}
-void Theme::set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font) {
- bool new_value = !font_map.has(p_node_type) || !font_map[p_node_type].has(p_name);
-
- if (font_map[p_node_type][p_name].is_valid()) {
- font_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
+void Theme::set_font(const StringName &p_name, const StringName &p_theme_type, const Ref<Font> &p_font) {
+ if (font_map[p_theme_type][p_name].is_valid()) {
+ font_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
}
- font_map[p_node_type][p_name] = p_font;
+ font_map[p_theme_type][p_name] = p_font;
if (p_font.is_valid()) {
- font_map[p_node_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ font_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED);
}
- if (new_value) {
- notify_property_list_changed();
- emit_changed();
- }
+ _emit_theme_changed();
}
-Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_node_type) const {
- if (font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid()) {
- return font_map[p_node_type][p_name];
+Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_theme_type) const {
+ if (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) {
+ return font_map[p_theme_type][p_name];
} else if (default_theme_font.is_valid()) {
return default_theme_font;
} else {
@@ -682,55 +672,57 @@ Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_node_typ
}
}
-bool Theme::has_font(const StringName &p_name, const StringName &p_node_type) const {
- return ((font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid()) || default_theme_font.is_valid());
+bool Theme::has_font(const StringName &p_name, const StringName &p_theme_type) const {
+ return ((font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) || default_theme_font.is_valid());
}
-bool Theme::has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const {
- return (font_map.has(p_node_type) && font_map[p_node_type].has(p_name));
+bool Theme::has_font_nocheck(const StringName &p_name, const StringName &p_theme_type) const {
+ return (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name));
}
-void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(font_map[p_node_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
- ERR_FAIL_COND_MSG(!font_map[p_node_type].has(p_old_name), "Cannot rename the font '" + String(p_old_name) + "' because it does not exist.");
+void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!font_map.has(p_theme_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(font_map[p_theme_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
+ ERR_FAIL_COND_MSG(!font_map[p_theme_type].has(p_old_name), "Cannot rename the font '" + String(p_old_name) + "' because it does not exist.");
- font_map[p_node_type][p_name] = font_map[p_node_type][p_old_name];
- font_map[p_node_type].erase(p_old_name);
+ font_map[p_theme_type][p_name] = font_map[p_theme_type][p_old_name];
+ font_map[p_theme_type].erase(p_old_name);
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
-void Theme::clear_font(const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot clear the font '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(!font_map[p_node_type].has(p_name), "Cannot clear the font '" + String(p_name) + "' because it does not exist.");
+void Theme::clear_font(const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!font_map.has(p_theme_type), "Cannot clear the font '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(!font_map[p_theme_type].has(p_name), "Cannot clear the font '" + String(p_name) + "' because it does not exist.");
- if (font_map[p_node_type][p_name].is_valid()) {
- font_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
+ if (font_map[p_theme_type][p_name].is_valid()) {
+ font_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
}
- font_map[p_node_type].erase(p_name);
- notify_property_list_changed();
- emit_changed();
+ font_map[p_theme_type].erase(p_name);
+
+ _emit_theme_changed();
}
-void Theme::get_font_list(StringName p_node_type, List<StringName> *p_list) const {
+void Theme::get_font_list(StringName p_theme_type, List<StringName> *p_list) const {
ERR_FAIL_NULL(p_list);
- if (!font_map.has(p_node_type)) {
+ if (!font_map.has(p_theme_type)) {
return;
}
const StringName *key = nullptr;
- while ((key = font_map[p_node_type].next(key))) {
+ while ((key = font_map[p_theme_type].next(key))) {
p_list->push_back(*key);
}
}
-void Theme::add_font_type(const StringName &p_node_type) {
- font_map[p_node_type] = HashMap<StringName, Ref<Font>>();
+void Theme::add_font_type(const StringName &p_theme_type) {
+ if (font_map.has(p_theme_type)) {
+ return;
+ }
+ font_map[p_theme_type] = HashMap<StringName, Ref<Font>>();
}
void Theme::get_font_type_list(List<StringName> *p_list) const {
@@ -742,20 +734,15 @@ void Theme::get_font_type_list(List<StringName> *p_list) const {
}
}
-void Theme::set_font_size(const StringName &p_name, const StringName &p_node_type, int p_font_size) {
- bool new_value = !font_size_map.has(p_node_type) || !font_size_map[p_node_type].has(p_name);
-
- font_size_map[p_node_type][p_name] = p_font_size;
+void Theme::set_font_size(const StringName &p_name, const StringName &p_theme_type, int p_font_size) {
+ font_size_map[p_theme_type][p_name] = p_font_size;
- if (new_value) {
- notify_property_list_changed();
- emit_changed();
- }
+ _emit_theme_changed();
}
-int Theme::get_font_size(const StringName &p_name, const StringName &p_node_type) const {
- if (font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name) && (font_size_map[p_node_type][p_name] > 0)) {
- return font_size_map[p_node_type][p_name];
+int Theme::get_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ if (font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name) && (font_size_map[p_theme_type][p_name] > 0)) {
+ return font_size_map[p_theme_type][p_name];
} else if (default_theme_font_size > 0) {
return default_theme_font_size;
} else {
@@ -763,51 +750,53 @@ int Theme::get_font_size(const StringName &p_name, const StringName &p_node_type
}
}
-bool Theme::has_font_size(const StringName &p_name, const StringName &p_node_type) const {
- return ((font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name) && (font_size_map[p_node_type][p_name] > 0)) || (default_theme_font_size > 0));
+bool Theme::has_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ return ((font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name) && (font_size_map[p_theme_type][p_name] > 0)) || (default_theme_font_size > 0));
}
-bool Theme::has_font_size_nocheck(const StringName &p_name, const StringName &p_node_type) const {
- return (font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name));
+bool Theme::has_font_size_nocheck(const StringName &p_name, const StringName &p_theme_type) const {
+ return (font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name));
}
-void Theme::rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!font_size_map.has(p_node_type), "Cannot rename the font size '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(font_size_map[p_node_type].has(p_name), "Cannot rename the font size '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
- ERR_FAIL_COND_MSG(!font_size_map[p_node_type].has(p_old_name), "Cannot rename the font size '" + String(p_old_name) + "' because it does not exist.");
+void Theme::rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!font_size_map.has(p_theme_type), "Cannot rename the font size '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(font_size_map[p_theme_type].has(p_name), "Cannot rename the font size '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
+ ERR_FAIL_COND_MSG(!font_size_map[p_theme_type].has(p_old_name), "Cannot rename the font size '" + String(p_old_name) + "' because it does not exist.");
- font_size_map[p_node_type][p_name] = font_size_map[p_node_type][p_old_name];
- font_size_map[p_node_type].erase(p_old_name);
+ font_size_map[p_theme_type][p_name] = font_size_map[p_theme_type][p_old_name];
+ font_size_map[p_theme_type].erase(p_old_name);
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
-void Theme::clear_font_size(const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!font_size_map.has(p_node_type), "Cannot clear the font size '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(!font_size_map[p_node_type].has(p_name), "Cannot clear the font size '" + String(p_name) + "' because it does not exist.");
+void Theme::clear_font_size(const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!font_size_map.has(p_theme_type), "Cannot clear the font size '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(!font_size_map[p_theme_type].has(p_name), "Cannot clear the font size '" + String(p_name) + "' because it does not exist.");
- font_size_map[p_node_type].erase(p_name);
- notify_property_list_changed();
- emit_changed();
+ font_size_map[p_theme_type].erase(p_name);
+
+ _emit_theme_changed();
}
-void Theme::get_font_size_list(StringName p_node_type, List<StringName> *p_list) const {
+void Theme::get_font_size_list(StringName p_theme_type, List<StringName> *p_list) const {
ERR_FAIL_NULL(p_list);
- if (!font_size_map.has(p_node_type)) {
+ if (!font_size_map.has(p_theme_type)) {
return;
}
const StringName *key = nullptr;
- while ((key = font_size_map[p_node_type].next(key))) {
+ while ((key = font_size_map[p_theme_type].next(key))) {
p_list->push_back(*key);
}
}
-void Theme::add_font_size_type(const StringName &p_node_type) {
- font_size_map[p_node_type] = HashMap<StringName, int>();
+void Theme::add_font_size_type(const StringName &p_theme_type) {
+ if (font_size_map.has(p_theme_type)) {
+ return;
+ }
+ font_size_map[p_theme_type] = HashMap<StringName, int>();
}
void Theme::get_font_size_type_list(List<StringName> *p_list) const {
@@ -819,70 +808,67 @@ void Theme::get_font_size_type_list(List<StringName> *p_list) const {
}
}
-void Theme::set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color) {
- bool new_value = !color_map.has(p_node_type) || !color_map[p_node_type].has(p_name);
-
- color_map[p_node_type][p_name] = p_color;
+void Theme::set_color(const StringName &p_name, const StringName &p_theme_type, const Color &p_color) {
+ color_map[p_theme_type][p_name] = p_color;
- if (new_value) {
- notify_property_list_changed();
- emit_changed();
- }
+ _emit_theme_changed();
}
-Color Theme::get_color(const StringName &p_name, const StringName &p_node_type) const {
- if (color_map.has(p_node_type) && color_map[p_node_type].has(p_name)) {
- return color_map[p_node_type][p_name];
+Color Theme::get_color(const StringName &p_name, const StringName &p_theme_type) const {
+ if (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)) {
+ return color_map[p_theme_type][p_name];
} else {
return Color();
}
}
-bool Theme::has_color(const StringName &p_name, const StringName &p_node_type) const {
- return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name));
+bool Theme::has_color(const StringName &p_name, const StringName &p_theme_type) const {
+ return (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name));
}
-bool Theme::has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const {
- return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name));
+bool Theme::has_color_nocheck(const StringName &p_name, const StringName &p_theme_type) const {
+ return (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name));
}
-void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(color_map[p_node_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
- ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_old_name), "Cannot rename the color '" + String(p_old_name) + "' because it does not exist.");
+void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!color_map.has(p_theme_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(color_map[p_theme_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
+ ERR_FAIL_COND_MSG(!color_map[p_theme_type].has(p_old_name), "Cannot rename the color '" + String(p_old_name) + "' because it does not exist.");
- color_map[p_node_type][p_name] = color_map[p_node_type][p_old_name];
- color_map[p_node_type].erase(p_old_name);
+ color_map[p_theme_type][p_name] = color_map[p_theme_type][p_old_name];
+ color_map[p_theme_type].erase(p_old_name);
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
-void Theme::clear_color(const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot clear the color '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_name), "Cannot clear the color '" + String(p_name) + "' because it does not exist.");
+void Theme::clear_color(const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!color_map.has(p_theme_type), "Cannot clear the color '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(!color_map[p_theme_type].has(p_name), "Cannot clear the color '" + String(p_name) + "' because it does not exist.");
- color_map[p_node_type].erase(p_name);
- notify_property_list_changed();
- emit_changed();
+ color_map[p_theme_type].erase(p_name);
+
+ _emit_theme_changed();
}
-void Theme::get_color_list(StringName p_node_type, List<StringName> *p_list) const {
+void Theme::get_color_list(StringName p_theme_type, List<StringName> *p_list) const {
ERR_FAIL_NULL(p_list);
- if (!color_map.has(p_node_type)) {
+ if (!color_map.has(p_theme_type)) {
return;
}
const StringName *key = nullptr;
- while ((key = color_map[p_node_type].next(key))) {
+ while ((key = color_map[p_theme_type].next(key))) {
p_list->push_back(*key);
}
}
-void Theme::add_color_type(const StringName &p_node_type) {
- color_map[p_node_type] = HashMap<StringName, Color>();
+void Theme::add_color_type(const StringName &p_theme_type) {
+ if (color_map.has(p_theme_type)) {
+ return;
+ }
+ color_map[p_theme_type] = HashMap<StringName, Color>();
}
void Theme::get_color_type_list(List<StringName> *p_list) const {
@@ -894,69 +880,67 @@ void Theme::get_color_type_list(List<StringName> *p_list) const {
}
}
-void Theme::set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant) {
- bool new_value = !constant_map.has(p_node_type) || !constant_map[p_node_type].has(p_name);
- constant_map[p_node_type][p_name] = p_constant;
+void Theme::set_constant(const StringName &p_name, const StringName &p_theme_type, int p_constant) {
+ constant_map[p_theme_type][p_name] = p_constant;
- if (new_value) {
- notify_property_list_changed();
- emit_changed();
- }
+ _emit_theme_changed();
}
-int Theme::get_constant(const StringName &p_name, const StringName &p_node_type) const {
- if (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name)) {
- return constant_map[p_node_type][p_name];
+int Theme::get_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ if (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)) {
+ return constant_map[p_theme_type][p_name];
} else {
return 0;
}
}
-bool Theme::has_constant(const StringName &p_name, const StringName &p_node_type) const {
- return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name));
+bool Theme::has_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ return (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name));
}
-bool Theme::has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const {
- return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name));
+bool Theme::has_constant_nocheck(const StringName &p_name, const StringName &p_theme_type) const {
+ return (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name));
}
-void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(constant_map[p_node_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
- ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_old_name), "Cannot rename the constant '" + String(p_old_name) + "' because it does not exist.");
+void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!constant_map.has(p_theme_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(constant_map[p_theme_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
+ ERR_FAIL_COND_MSG(!constant_map[p_theme_type].has(p_old_name), "Cannot rename the constant '" + String(p_old_name) + "' because it does not exist.");
- constant_map[p_node_type][p_name] = constant_map[p_node_type][p_old_name];
- constant_map[p_node_type].erase(p_old_name);
+ constant_map[p_theme_type][p_name] = constant_map[p_theme_type][p_old_name];
+ constant_map[p_theme_type].erase(p_old_name);
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
-void Theme::clear_constant(const StringName &p_name, const StringName &p_node_type) {
- ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot clear the constant '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
- ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_name), "Cannot clear the constant '" + String(p_name) + "' because it does not exist.");
+void Theme::clear_constant(const StringName &p_name, const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!constant_map.has(p_theme_type), "Cannot clear the constant '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist.");
+ ERR_FAIL_COND_MSG(!constant_map[p_theme_type].has(p_name), "Cannot clear the constant '" + String(p_name) + "' because it does not exist.");
- constant_map[p_node_type].erase(p_name);
- notify_property_list_changed();
- emit_changed();
+ constant_map[p_theme_type].erase(p_name);
+
+ _emit_theme_changed();
}
-void Theme::get_constant_list(StringName p_node_type, List<StringName> *p_list) const {
+void Theme::get_constant_list(StringName p_theme_type, List<StringName> *p_list) const {
ERR_FAIL_NULL(p_list);
- if (!constant_map.has(p_node_type)) {
+ if (!constant_map.has(p_theme_type)) {
return;
}
const StringName *key = nullptr;
- while ((key = constant_map[p_node_type].next(key))) {
+ while ((key = constant_map[p_theme_type].next(key))) {
p_list->push_back(*key);
}
}
-void Theme::add_constant_type(const StringName &p_node_type) {
- constant_map[p_node_type] = HashMap<StringName, int>();
+void Theme::add_constant_type(const StringName &p_theme_type) {
+ if (constant_map.has(p_theme_type)) {
+ return;
+ }
+ constant_map[p_theme_type] = HashMap<StringName, int>();
}
void Theme::get_constant_type_list(List<StringName> *p_list) const {
@@ -968,63 +952,63 @@ void Theme::get_constant_type_list(List<StringName> *p_list) const {
}
}
-void Theme::set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value) {
+void Theme::set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type, const Variant &p_value) {
switch (p_data_type) {
case DATA_TYPE_COLOR: {
ERR_FAIL_COND_MSG(p_value.get_type() != Variant::COLOR, "Theme item's data type (Color) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ").");
Color color_value = p_value;
- set_color(p_name, p_node_type, color_value);
+ set_color(p_name, p_theme_type, color_value);
} break;
case DATA_TYPE_CONSTANT: {
ERR_FAIL_COND_MSG(p_value.get_type() != Variant::INT, "Theme item's data type (int) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ").");
int constant_value = p_value;
- set_constant(p_name, p_node_type, constant_value);
+ set_constant(p_name, p_theme_type, constant_value);
} break;
case DATA_TYPE_FONT: {
ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ").");
Ref<Font> font_value = Object::cast_to<Font>(p_value.get_validated_object());
- set_font(p_name, p_node_type, font_value);
+ set_font(p_name, p_theme_type, font_value);
} break;
case DATA_TYPE_FONT_SIZE: {
ERR_FAIL_COND_MSG(p_value.get_type() != Variant::INT, "Theme item's data type (int) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ").");
int font_size_value = p_value;
- set_font_size(p_name, p_node_type, font_size_value);
+ set_font_size(p_name, p_theme_type, font_size_value);
} break;
case DATA_TYPE_ICON: {
ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ").");
Ref<Texture2D> icon_value = Object::cast_to<Texture2D>(p_value.get_validated_object());
- set_icon(p_name, p_node_type, icon_value);
+ set_icon(p_name, p_theme_type, icon_value);
} break;
case DATA_TYPE_STYLEBOX: {
ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ").");
Ref<StyleBox> stylebox_value = Object::cast_to<StyleBox>(p_value.get_validated_object());
- set_stylebox(p_name, p_node_type, stylebox_value);
+ set_stylebox(p_name, p_theme_type, stylebox_value);
} break;
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
}
-Variant Theme::get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const {
+Variant Theme::get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const {
switch (p_data_type) {
case DATA_TYPE_COLOR:
- return get_color(p_name, p_node_type);
+ return get_color(p_name, p_theme_type);
case DATA_TYPE_CONSTANT:
- return get_constant(p_name, p_node_type);
+ return get_constant(p_name, p_theme_type);
case DATA_TYPE_FONT:
- return get_font(p_name, p_node_type);
+ return get_font(p_name, p_theme_type);
case DATA_TYPE_FONT_SIZE:
- return get_font_size(p_name, p_node_type);
+ return get_font_size(p_name, p_theme_type);
case DATA_TYPE_ICON:
- return get_icon(p_name, p_node_type);
+ return get_icon(p_name, p_theme_type);
case DATA_TYPE_STYLEBOX:
- return get_stylebox(p_name, p_node_type);
+ return get_stylebox(p_name, p_theme_type);
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
@@ -1032,20 +1016,20 @@ Variant Theme::get_theme_item(DataType p_data_type, const StringName &p_name, co
return Variant();
}
-bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const {
+bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const {
switch (p_data_type) {
case DATA_TYPE_COLOR:
- return has_color(p_name, p_node_type);
+ return has_color(p_name, p_theme_type);
case DATA_TYPE_CONSTANT:
- return has_constant(p_name, p_node_type);
+ return has_constant(p_name, p_theme_type);
case DATA_TYPE_FONT:
- return has_font(p_name, p_node_type);
+ return has_font(p_name, p_theme_type);
case DATA_TYPE_FONT_SIZE:
- return has_font_size(p_name, p_node_type);
+ return has_font_size(p_name, p_theme_type);
case DATA_TYPE_ICON:
- return has_icon(p_name, p_node_type);
+ return has_icon(p_name, p_theme_type);
case DATA_TYPE_STYLEBOX:
- return has_stylebox(p_name, p_node_type);
+ return has_stylebox(p_name, p_theme_type);
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
@@ -1053,20 +1037,20 @@ bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const
return false;
}
-bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const {
+bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const {
switch (p_data_type) {
case DATA_TYPE_COLOR:
- return has_color_nocheck(p_name, p_node_type);
+ return has_color_nocheck(p_name, p_theme_type);
case DATA_TYPE_CONSTANT:
- return has_constant_nocheck(p_name, p_node_type);
+ return has_constant_nocheck(p_name, p_theme_type);
case DATA_TYPE_FONT:
- return has_font_nocheck(p_name, p_node_type);
+ return has_font_nocheck(p_name, p_theme_type);
case DATA_TYPE_FONT_SIZE:
- return has_font_size_nocheck(p_name, p_node_type);
+ return has_font_size_nocheck(p_name, p_theme_type);
case DATA_TYPE_ICON:
- return has_icon_nocheck(p_name, p_node_type);
+ return has_icon_nocheck(p_name, p_theme_type);
case DATA_TYPE_STYLEBOX:
- return has_stylebox_nocheck(p_name, p_node_type);
+ return has_stylebox_nocheck(p_name, p_theme_type);
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
@@ -1074,100 +1058,100 @@ bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_nam
return false;
}
-void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
+void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) {
switch (p_data_type) {
case DATA_TYPE_COLOR:
- rename_color(p_old_name, p_name, p_node_type);
+ rename_color(p_old_name, p_name, p_theme_type);
break;
case DATA_TYPE_CONSTANT:
- rename_constant(p_old_name, p_name, p_node_type);
+ rename_constant(p_old_name, p_name, p_theme_type);
break;
case DATA_TYPE_FONT:
- rename_font(p_old_name, p_name, p_node_type);
+ rename_font(p_old_name, p_name, p_theme_type);
break;
case DATA_TYPE_FONT_SIZE:
- rename_font_size(p_old_name, p_name, p_node_type);
+ rename_font_size(p_old_name, p_name, p_theme_type);
break;
case DATA_TYPE_ICON:
- rename_icon(p_old_name, p_name, p_node_type);
+ rename_icon(p_old_name, p_name, p_theme_type);
break;
case DATA_TYPE_STYLEBOX:
- rename_stylebox(p_old_name, p_name, p_node_type);
+ rename_stylebox(p_old_name, p_name, p_theme_type);
break;
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
}
-void Theme::clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) {
+void Theme::clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) {
switch (p_data_type) {
case DATA_TYPE_COLOR:
- clear_color(p_name, p_node_type);
+ clear_color(p_name, p_theme_type);
break;
case DATA_TYPE_CONSTANT:
- clear_constant(p_name, p_node_type);
+ clear_constant(p_name, p_theme_type);
break;
case DATA_TYPE_FONT:
- clear_font(p_name, p_node_type);
+ clear_font(p_name, p_theme_type);
break;
case DATA_TYPE_FONT_SIZE:
- clear_font_size(p_name, p_node_type);
+ clear_font_size(p_name, p_theme_type);
break;
case DATA_TYPE_ICON:
- clear_icon(p_name, p_node_type);
+ clear_icon(p_name, p_theme_type);
break;
case DATA_TYPE_STYLEBOX:
- clear_stylebox(p_name, p_node_type);
+ clear_stylebox(p_name, p_theme_type);
break;
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
}
-void Theme::get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const {
+void Theme::get_theme_item_list(DataType p_data_type, StringName p_theme_type, List<StringName> *p_list) const {
switch (p_data_type) {
case DATA_TYPE_COLOR:
- get_color_list(p_node_type, p_list);
+ get_color_list(p_theme_type, p_list);
break;
case DATA_TYPE_CONSTANT:
- get_constant_list(p_node_type, p_list);
+ get_constant_list(p_theme_type, p_list);
break;
case DATA_TYPE_FONT:
- get_font_list(p_node_type, p_list);
+ get_font_list(p_theme_type, p_list);
break;
case DATA_TYPE_FONT_SIZE:
- get_font_size_list(p_node_type, p_list);
+ get_font_size_list(p_theme_type, p_list);
break;
case DATA_TYPE_ICON:
- get_icon_list(p_node_type, p_list);
+ get_icon_list(p_theme_type, p_list);
break;
case DATA_TYPE_STYLEBOX:
- get_stylebox_list(p_node_type, p_list);
+ get_stylebox_list(p_theme_type, p_list);
break;
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
}
-void Theme::add_theme_item_type(DataType p_data_type, const StringName &p_node_type) {
+void Theme::add_theme_item_type(DataType p_data_type, const StringName &p_theme_type) {
switch (p_data_type) {
case DATA_TYPE_COLOR:
- add_color_type(p_node_type);
+ add_color_type(p_theme_type);
break;
case DATA_TYPE_CONSTANT:
- add_constant_type(p_node_type);
+ add_constant_type(p_theme_type);
break;
case DATA_TYPE_FONT:
- add_font_type(p_node_type);
+ add_font_type(p_theme_type);
break;
case DATA_TYPE_FONT_SIZE:
- add_font_size_type(p_node_type);
+ add_font_size_type(p_theme_type);
break;
case DATA_TYPE_ICON:
- add_icon_type(p_node_type);
+ add_icon_type(p_theme_type);
break;
case DATA_TYPE_STYLEBOX:
- add_stylebox_type(p_node_type);
+ add_stylebox_type(p_theme_type);
break;
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
@@ -1199,8 +1183,17 @@ void Theme::get_theme_item_type_list(DataType p_data_type, List<StringName> *p_l
}
}
+void Theme::_freeze_change_propagation() {
+ no_change_propagation = true;
+}
+
+void Theme::_unfreeze_and_propagate_changes() {
+ no_change_propagation = false;
+ _emit_theme_changed();
+}
+
void Theme::clear() {
- //these need disconnecting
+ // These items need disconnecting.
{
const StringName *K = nullptr;
while ((K = icon_map.next(K))) {
@@ -1246,8 +1239,7 @@ void Theme::clear() {
color_map.clear();
constant_map.clear();
- notify_property_list_changed();
- emit_changed();
+ _emit_theme_changed();
}
void Theme::copy_default_theme() {
@@ -1261,6 +1253,8 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
return;
}
+ _freeze_change_propagation();
+
// These items need reconnecting, so add them normally.
{
const StringName *K = nullptr;
@@ -1297,8 +1291,7 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
color_map = p_other->color_map;
constant_map = p_other->constant_map;
- notify_property_list_changed();
- emit_changed();
+ _unfreeze_and_propagate_changes();
}
void Theme::get_type_list(List<StringName> *p_list) const {
@@ -1340,56 +1333,66 @@ void Theme::get_type_list(List<StringName> *p_list) const {
}
}
+void Theme::get_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) {
+ ERR_FAIL_NULL(p_list);
+
+ StringName class_name = p_theme_type;
+ while (class_name != StringName()) {
+ p_list->push_back(class_name);
+ class_name = ClassDB::get_parent_class_nocheck(class_name);
+ }
+}
+
void Theme::reset_state() {
clear();
}
void Theme::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_icon", "name", "node_type", "texture"), &Theme::set_icon);
- ClassDB::bind_method(D_METHOD("get_icon", "name", "node_type"), &Theme::get_icon);
- ClassDB::bind_method(D_METHOD("has_icon", "name", "node_type"), &Theme::has_icon);
- ClassDB::bind_method(D_METHOD("rename_icon", "old_name", "name", "node_type"), &Theme::rename_icon);
- ClassDB::bind_method(D_METHOD("clear_icon", "name", "node_type"), &Theme::clear_icon);
- ClassDB::bind_method(D_METHOD("get_icon_list", "node_type"), &Theme::_get_icon_list);
+ ClassDB::bind_method(D_METHOD("set_icon", "name", "theme_type", "texture"), &Theme::set_icon);
+ ClassDB::bind_method(D_METHOD("get_icon", "name", "theme_type"), &Theme::get_icon);
+ ClassDB::bind_method(D_METHOD("has_icon", "name", "theme_type"), &Theme::has_icon);
+ ClassDB::bind_method(D_METHOD("rename_icon", "old_name", "name", "theme_type"), &Theme::rename_icon);
+ ClassDB::bind_method(D_METHOD("clear_icon", "name", "theme_type"), &Theme::clear_icon);
+ ClassDB::bind_method(D_METHOD("get_icon_list", "theme_type"), &Theme::_get_icon_list);
ClassDB::bind_method(D_METHOD("get_icon_type_list"), &Theme::_get_icon_type_list);
- ClassDB::bind_method(D_METHOD("set_stylebox", "name", "node_type", "texture"), &Theme::set_stylebox);
- ClassDB::bind_method(D_METHOD("get_stylebox", "name", "node_type"), &Theme::get_stylebox);
- ClassDB::bind_method(D_METHOD("has_stylebox", "name", "node_type"), &Theme::has_stylebox);
- ClassDB::bind_method(D_METHOD("rename_stylebox", "old_name", "name", "node_type"), &Theme::rename_stylebox);
- ClassDB::bind_method(D_METHOD("clear_stylebox", "name", "node_type"), &Theme::clear_stylebox);
- ClassDB::bind_method(D_METHOD("get_stylebox_list", "node_type"), &Theme::_get_stylebox_list);
+ ClassDB::bind_method(D_METHOD("set_stylebox", "name", "theme_type", "texture"), &Theme::set_stylebox);
+ ClassDB::bind_method(D_METHOD("get_stylebox", "name", "theme_type"), &Theme::get_stylebox);
+ ClassDB::bind_method(D_METHOD("has_stylebox", "name", "theme_type"), &Theme::has_stylebox);
+ ClassDB::bind_method(D_METHOD("rename_stylebox", "old_name", "name", "theme_type"), &Theme::rename_stylebox);
+ ClassDB::bind_method(D_METHOD("clear_stylebox", "name", "theme_type"), &Theme::clear_stylebox);
+ ClassDB::bind_method(D_METHOD("get_stylebox_list", "theme_type"), &Theme::_get_stylebox_list);
ClassDB::bind_method(D_METHOD("get_stylebox_type_list"), &Theme::_get_stylebox_type_list);
- ClassDB::bind_method(D_METHOD("set_font", "name", "node_type", "font"), &Theme::set_font);
- ClassDB::bind_method(D_METHOD("get_font", "name", "node_type"), &Theme::get_font);
- ClassDB::bind_method(D_METHOD("has_font", "name", "node_type"), &Theme::has_font);
- ClassDB::bind_method(D_METHOD("rename_font", "old_name", "name", "node_type"), &Theme::rename_font);
- ClassDB::bind_method(D_METHOD("clear_font", "name", "node_type"), &Theme::clear_font);
- ClassDB::bind_method(D_METHOD("get_font_list", "node_type"), &Theme::_get_font_list);
+ ClassDB::bind_method(D_METHOD("set_font", "name", "theme_type", "font"), &Theme::set_font);
+ ClassDB::bind_method(D_METHOD("get_font", "name", "theme_type"), &Theme::get_font);
+ ClassDB::bind_method(D_METHOD("has_font", "name", "theme_type"), &Theme::has_font);
+ ClassDB::bind_method(D_METHOD("rename_font", "old_name", "name", "theme_type"), &Theme::rename_font);
+ ClassDB::bind_method(D_METHOD("clear_font", "name", "theme_type"), &Theme::clear_font);
+ ClassDB::bind_method(D_METHOD("get_font_list", "theme_type"), &Theme::_get_font_list);
ClassDB::bind_method(D_METHOD("get_font_type_list"), &Theme::_get_font_type_list);
- ClassDB::bind_method(D_METHOD("set_font_size", "name", "node_type", "font_size"), &Theme::set_font_size);
- ClassDB::bind_method(D_METHOD("get_font_size", "name", "node_type"), &Theme::get_font_size);
- ClassDB::bind_method(D_METHOD("has_font_size", "name", "node_type"), &Theme::has_font_size);
- ClassDB::bind_method(D_METHOD("rename_font_size", "old_name", "name", "node_type"), &Theme::rename_font_size);
- ClassDB::bind_method(D_METHOD("clear_font_size", "name", "node_type"), &Theme::clear_font_size);
- ClassDB::bind_method(D_METHOD("get_font_size_list", "node_type"), &Theme::_get_font_size_list);
+ ClassDB::bind_method(D_METHOD("set_font_size", "name", "theme_type", "font_size"), &Theme::set_font_size);
+ ClassDB::bind_method(D_METHOD("get_font_size", "name", "theme_type"), &Theme::get_font_size);
+ ClassDB::bind_method(D_METHOD("has_font_size", "name", "theme_type"), &Theme::has_font_size);
+ ClassDB::bind_method(D_METHOD("rename_font_size", "old_name", "name", "theme_type"), &Theme::rename_font_size);
+ ClassDB::bind_method(D_METHOD("clear_font_size", "name", "theme_type"), &Theme::clear_font_size);
+ ClassDB::bind_method(D_METHOD("get_font_size_list", "theme_type"), &Theme::_get_font_size_list);
ClassDB::bind_method(D_METHOD("get_font_size_type_list"), &Theme::_get_font_size_type_list);
- ClassDB::bind_method(D_METHOD("set_color", "name", "node_type", "color"), &Theme::set_color);
- ClassDB::bind_method(D_METHOD("get_color", "name", "node_type"), &Theme::get_color);
- ClassDB::bind_method(D_METHOD("has_color", "name", "node_type"), &Theme::has_color);
- ClassDB::bind_method(D_METHOD("rename_color", "old_name", "name", "node_type"), &Theme::rename_color);
- ClassDB::bind_method(D_METHOD("clear_color", "name", "node_type"), &Theme::clear_color);
- ClassDB::bind_method(D_METHOD("get_color_list", "node_type"), &Theme::_get_color_list);
+ ClassDB::bind_method(D_METHOD("set_color", "name", "theme_type", "color"), &Theme::set_color);
+ ClassDB::bind_method(D_METHOD("get_color", "name", "theme_type"), &Theme::get_color);
+ ClassDB::bind_method(D_METHOD("has_color", "name", "theme_type"), &Theme::has_color);
+ ClassDB::bind_method(D_METHOD("rename_color", "old_name", "name", "theme_type"), &Theme::rename_color);
+ ClassDB::bind_method(D_METHOD("clear_color", "name", "theme_type"), &Theme::clear_color);
+ ClassDB::bind_method(D_METHOD("get_color_list", "theme_type"), &Theme::_get_color_list);
ClassDB::bind_method(D_METHOD("get_color_type_list"), &Theme::_get_color_type_list);
- ClassDB::bind_method(D_METHOD("set_constant", "name", "node_type", "constant"), &Theme::set_constant);
- ClassDB::bind_method(D_METHOD("get_constant", "name", "node_type"), &Theme::get_constant);
- ClassDB::bind_method(D_METHOD("has_constant", "name", "node_type"), &Theme::has_constant);
- ClassDB::bind_method(D_METHOD("rename_constant", "old_name", "name", "node_type"), &Theme::rename_constant);
- ClassDB::bind_method(D_METHOD("clear_constant", "name", "node_type"), &Theme::clear_constant);
- ClassDB::bind_method(D_METHOD("get_constant_list", "node_type"), &Theme::_get_constant_list);
+ ClassDB::bind_method(D_METHOD("set_constant", "name", "theme_type", "constant"), &Theme::set_constant);
+ ClassDB::bind_method(D_METHOD("get_constant", "name", "theme_type"), &Theme::get_constant);
+ ClassDB::bind_method(D_METHOD("has_constant", "name", "theme_type"), &Theme::has_constant);
+ ClassDB::bind_method(D_METHOD("rename_constant", "old_name", "name", "theme_type"), &Theme::rename_constant);
+ ClassDB::bind_method(D_METHOD("clear_constant", "name", "theme_type"), &Theme::clear_constant);
+ ClassDB::bind_method(D_METHOD("get_constant_list", "theme_type"), &Theme::_get_constant_list);
ClassDB::bind_method(D_METHOD("get_constant_type_list"), &Theme::_get_constant_type_list);
ClassDB::bind_method(D_METHOD("clear"), &Theme::clear);
@@ -1400,12 +1403,12 @@ void Theme::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_font_size", "font_size"), &Theme::set_default_theme_font_size);
ClassDB::bind_method(D_METHOD("get_default_font_size"), &Theme::get_default_theme_font_size);
- ClassDB::bind_method(D_METHOD("set_theme_item", "data_type", "name", "node_type", "value"), &Theme::set_theme_item);
- ClassDB::bind_method(D_METHOD("get_theme_item", "data_type", "name", "node_type"), &Theme::get_theme_item);
- ClassDB::bind_method(D_METHOD("has_theme_item", "data_type", "name", "node_type"), &Theme::has_theme_item);
- ClassDB::bind_method(D_METHOD("rename_theme_item", "data_type", "old_name", "name", "node_type"), &Theme::rename_theme_item);
- ClassDB::bind_method(D_METHOD("clear_theme_item", "data_type", "name", "node_type"), &Theme::clear_theme_item);
- ClassDB::bind_method(D_METHOD("get_theme_item_list", "data_type", "node_type"), &Theme::_get_theme_item_list);
+ ClassDB::bind_method(D_METHOD("set_theme_item", "data_type", "name", "theme_type", "value"), &Theme::set_theme_item);
+ ClassDB::bind_method(D_METHOD("get_theme_item", "data_type", "name", "theme_type"), &Theme::get_theme_item);
+ ClassDB::bind_method(D_METHOD("has_theme_item", "data_type", "name", "theme_type"), &Theme::has_theme_item);
+ ClassDB::bind_method(D_METHOD("rename_theme_item", "data_type", "old_name", "name", "theme_type"), &Theme::rename_theme_item);
+ ClassDB::bind_method(D_METHOD("clear_theme_item", "data_type", "name", "theme_type"), &Theme::clear_theme_item);
+ ClassDB::bind_method(D_METHOD("get_theme_item_list", "data_type", "theme_type"), &Theme::_get_theme_item_list);
ClassDB::bind_method(D_METHOD("get_theme_item_type_list", "data_type"), &Theme::_get_theme_item_type_list);
ClassDB::bind_method(D_METHOD("get_type_list"), &Theme::_get_type_list);
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index 7e887b6343..fe64fd7290 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -41,6 +41,12 @@ class Theme : public Resource {
GDCLASS(Theme, Resource);
RES_BASE_EXTENSION("theme");
+#ifdef TOOLS_ENABLED
+ friend class ThemeItemImportTree;
+ friend class ThemeItemEditorDialog;
+ friend class ThemeTypeEditor;
+#endif
+
public:
enum DataType {
DATA_TYPE_COLOR,
@@ -53,6 +59,8 @@ public:
};
private:
+ bool no_change_propagation = false;
+
void _emit_theme_changed();
HashMap<StringName, HashMap<StringName, Ref<Texture2D>>> icon_map;
@@ -62,20 +70,20 @@ private:
HashMap<StringName, HashMap<StringName, Color>> color_map;
HashMap<StringName, HashMap<StringName, int>> constant_map;
- Vector<String> _get_icon_list(const String &p_node_type) const;
+ Vector<String> _get_icon_list(const String &p_theme_type) const;
Vector<String> _get_icon_type_list() const;
- Vector<String> _get_stylebox_list(const String &p_node_type) const;
+ Vector<String> _get_stylebox_list(const String &p_theme_type) const;
Vector<String> _get_stylebox_type_list() const;
- Vector<String> _get_font_list(const String &p_node_type) const;
+ Vector<String> _get_font_list(const String &p_theme_type) const;
Vector<String> _get_font_type_list() const;
- Vector<String> _get_font_size_list(const String &p_node_type) const;
+ Vector<String> _get_font_size_list(const String &p_theme_type) const;
Vector<String> _get_font_size_type_list() const;
- Vector<String> _get_color_list(const String &p_node_type) const;
+ Vector<String> _get_color_list(const String &p_theme_type) const;
Vector<String> _get_color_type_list() const;
- Vector<String> _get_constant_list(const String &p_node_type) const;
+ Vector<String> _get_constant_list(const String &p_theme_type) const;
Vector<String> _get_constant_type_list() const;
- Vector<String> _get_theme_item_list(DataType p_data_type, const String &p_node_type) const;
+ Vector<String> _get_theme_item_list(DataType p_data_type, const String &p_theme_type) const;
Vector<String> _get_theme_item_type_list(DataType p_data_type) const;
Vector<String> _get_type_list() const;
@@ -96,6 +104,9 @@ protected:
static void _bind_methods();
+ void _freeze_change_propagation();
+ void _unfreeze_and_propagate_changes();
+
virtual void reset_state() override;
public:
@@ -116,77 +127,78 @@ public:
void set_default_theme_font_size(int p_font_size);
int get_default_theme_font_size() const;
- void set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture2D> &p_icon);
- Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_node_type) const;
- bool has_icon(const StringName &p_name, const StringName &p_node_type) const;
- bool has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const;
- void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
- void clear_icon(const StringName &p_name, const StringName &p_node_type);
- void get_icon_list(StringName p_node_type, List<StringName> *p_list) const;
- void add_icon_type(const StringName &p_node_type);
+ void set_icon(const StringName &p_name, const StringName &p_theme_type, const Ref<Texture2D> &p_icon);
+ Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_icon(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_icon_nocheck(const StringName &p_name, const StringName &p_theme_type) const;
+ void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type);
+ void clear_icon(const StringName &p_name, const StringName &p_theme_type);
+ void get_icon_list(StringName p_theme_type, List<StringName> *p_list) const;
+ void add_icon_type(const StringName &p_theme_type);
void get_icon_type_list(List<StringName> *p_list) const;
- void set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style);
- Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_node_type) const;
- bool has_stylebox(const StringName &p_name, const StringName &p_node_type) const;
- bool has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const;
- void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
- void clear_stylebox(const StringName &p_name, const StringName &p_node_type);
- void get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const;
- void add_stylebox_type(const StringName &p_node_type);
+ void set_stylebox(const StringName &p_name, const StringName &p_theme_type, const Ref<StyleBox> &p_style);
+ Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_stylebox(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_stylebox_nocheck(const StringName &p_name, const StringName &p_theme_type) const;
+ void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type);
+ void clear_stylebox(const StringName &p_name, const StringName &p_theme_type);
+ void get_stylebox_list(StringName p_theme_type, List<StringName> *p_list) const;
+ void add_stylebox_type(const StringName &p_theme_type);
void get_stylebox_type_list(List<StringName> *p_list) const;
- void set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font);
- Ref<Font> get_font(const StringName &p_name, const StringName &p_node_type) const;
- bool has_font(const StringName &p_name, const StringName &p_node_type) const;
- bool has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const;
- void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
- void clear_font(const StringName &p_name, const StringName &p_node_type);
- void get_font_list(StringName p_node_type, List<StringName> *p_list) const;
- void add_font_type(const StringName &p_node_type);
+ void set_font(const StringName &p_name, const StringName &p_theme_type, const Ref<Font> &p_font);
+ Ref<Font> get_font(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_font(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_font_nocheck(const StringName &p_name, const StringName &p_theme_type) const;
+ void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type);
+ void clear_font(const StringName &p_name, const StringName &p_theme_type);
+ void get_font_list(StringName p_theme_type, List<StringName> *p_list) const;
+ void add_font_type(const StringName &p_theme_type);
void get_font_type_list(List<StringName> *p_list) const;
- void set_font_size(const StringName &p_name, const StringName &p_node_type, int p_font_size);
- int get_font_size(const StringName &p_name, const StringName &p_node_type) const;
- bool has_font_size(const StringName &p_name, const StringName &p_node_type) const;
- bool has_font_size_nocheck(const StringName &p_name, const StringName &p_node_type) const;
- void rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
- void clear_font_size(const StringName &p_name, const StringName &p_node_type);
- void get_font_size_list(StringName p_node_type, List<StringName> *p_list) const;
- void add_font_size_type(const StringName &p_node_type);
+ void set_font_size(const StringName &p_name, const StringName &p_theme_type, int p_font_size);
+ int get_font_size(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_font_size(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_font_size_nocheck(const StringName &p_name, const StringName &p_theme_type) const;
+ void rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type);
+ void clear_font_size(const StringName &p_name, const StringName &p_theme_type);
+ void get_font_size_list(StringName p_theme_type, List<StringName> *p_list) const;
+ void add_font_size_type(const StringName &p_theme_type);
void get_font_size_type_list(List<StringName> *p_list) const;
- void set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color);
- Color get_color(const StringName &p_name, const StringName &p_node_type) const;
- bool has_color(const StringName &p_name, const StringName &p_node_type) const;
- bool has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const;
- void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
- void clear_color(const StringName &p_name, const StringName &p_node_type);
- void get_color_list(StringName p_node_type, List<StringName> *p_list) const;
- void add_color_type(const StringName &p_node_type);
+ void set_color(const StringName &p_name, const StringName &p_theme_type, const Color &p_color);
+ Color get_color(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_color(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_color_nocheck(const StringName &p_name, const StringName &p_theme_type) const;
+ void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type);
+ void clear_color(const StringName &p_name, const StringName &p_theme_type);
+ void get_color_list(StringName p_theme_type, List<StringName> *p_list) const;
+ void add_color_type(const StringName &p_theme_type);
void get_color_type_list(List<StringName> *p_list) const;
- void set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant);
- int get_constant(const StringName &p_name, const StringName &p_node_type) const;
- bool has_constant(const StringName &p_name, const StringName &p_node_type) const;
- bool has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const;
- void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
- void clear_constant(const StringName &p_name, const StringName &p_node_type);
- void get_constant_list(StringName p_node_type, List<StringName> *p_list) const;
- void add_constant_type(const StringName &p_node_type);
+ void set_constant(const StringName &p_name, const StringName &p_theme_type, int p_constant);
+ int get_constant(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_constant(const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_constant_nocheck(const StringName &p_name, const StringName &p_theme_type) const;
+ void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type);
+ void clear_constant(const StringName &p_name, const StringName &p_theme_type);
+ void get_constant_list(StringName p_theme_type, List<StringName> *p_list) const;
+ void add_constant_type(const StringName &p_theme_type);
void get_constant_type_list(List<StringName> *p_list) const;
- void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value);
- Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
- bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
- bool has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
- void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
- void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type);
- void get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const;
- void add_theme_item_type(DataType p_data_type, const StringName &p_node_type);
+ void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type, const Variant &p_value);
+ Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const;
+ bool has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const;
+ void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type);
+ void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type);
+ void get_theme_item_list(DataType p_data_type, StringName p_theme_type, List<StringName> *p_list) const;
+ void add_theme_item_type(DataType p_data_type, const StringName &p_theme_type);
void get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const;
void get_type_list(List<StringName> *p_list) const;
+ static void get_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list);
void copy_default_theme();
void copy_theme(const Ref<Theme> &p_other);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index c4b8a56f54..0d6f3c07f0 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -106,15 +106,15 @@ void TileSet::_compute_next_source_id() {
}
// Sources management
-int TileSet::add_source(Ref<TileSetAtlasSource> p_tile_atlas_source, int p_atlas_source_id_override) {
- ERR_FAIL_COND_V(!p_tile_atlas_source.is_valid(), -1);
+int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source_id_override) {
+ ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), -1);
ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), -1, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id;
- sources[new_source_id] = p_tile_atlas_source;
+ sources[new_source_id] = p_tile_set_source;
source_ids.append(new_source_id);
source_ids.sort();
- p_tile_atlas_source->set_tile_set(this);
+ p_tile_set_source->set_tile_set(this);
_compute_next_source_id();
sources[new_source_id]->connect("changed", callable_mp(this, &TileSet::_source_changed));
@@ -668,8 +668,8 @@ void TileSet::reset_state() {
custom_data_layers.clear();
}
-const Vector2i TileSetAtlasSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
-const int TileSetAtlasSource::INVALID_TILE_ALTERNATIVE = -1;
+const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
+const int TileSetSource::INVALID_TILE_ALTERNATIVE = -1;
#ifndef DISABLE_DEPRECATED
void TileSet::compatibility_conversion() {
@@ -835,7 +835,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
} else if (what == "tile_mode") {
ctd->tile_mode = p_value;
} else if (what.left(9) == "autotile") {
- what = what.right(9);
+ what = what.substr(9);
if (what == "bitmask_mode") {
ctd->autotile_bitmask_mode = p_value;
} else if (what == "icon_coordinate") {
@@ -1086,7 +1086,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
} else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_integer()) {
- // Create atlas if it does not exists.
+ // Create source only if it does not exists.
int source_id = components[1].to_int();
if (!has_source(source_id)) {
@@ -1290,7 +1290,7 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tile_skew", "skew"), &TileSet::set_tile_skew);
ClassDB::bind_method(D_METHOD("get_tile_skew"), &TileSet::get_tile_skew);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_shape", PROPERTY_HINT_ENUM, "Square,Isometric,Half-offset square,Hexagon"), "set_tile_shape", "get_tile_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_shape", PROPERTY_HINT_ENUM, "Square,Isometric,Half-Offset Square,Hexagon"), "set_tile_shape", "get_tile_shape");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_layout", PROPERTY_HINT_ENUM, "Stacked,Stacked Offset,Stairs Right,Stairs Down,Diamond Right,Diamond Down"), "set_tile_layout", "get_tile_layout");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_offset_axis", PROPERTY_HINT_ENUM, "Horizontal Offset,Vertical Offset"), "set_tile_offset_axis", "get_tile_offset_axis");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "tile_size"), "set_tile_size", "get_tile_size");
@@ -1399,16 +1399,19 @@ void TileSet::_bind_methods() {
TileSet::TileSet() {
// Instanciatie and list all plugins.
- tile_set_plugins_vector.append(memnew(TileSetAtlasPluginRendering));
- tile_set_plugins_vector.append(memnew(TileSetAtlasPluginPhysics));
- tile_set_plugins_vector.append(memnew(TileSetAtlasPluginTerrain));
- tile_set_plugins_vector.append(memnew(TileSetAtlasPluginNavigation));
+ tile_set_plugins_vector.append(memnew(TileSetPluginAtlasRendering));
+ tile_set_plugins_vector.append(memnew(TileSetPluginAtlasPhysics));
+ tile_set_plugins_vector.append(memnew(TileSetPluginAtlasTerrain));
+ tile_set_plugins_vector.append(memnew(TileSetPluginAtlasNavigation));
+ tile_set_plugins_vector.append(memnew(TileSetPluginScenesCollections));
}
TileSet::~TileSet() {
+#ifndef DISABLE_DEPRECATED
for (Map<int, CompatibilityTileData *>::Element *E = compatibility_data.front(); E; E = E->next()) {
memdelete(E->get());
}
+#endif // DISABLE_DEPRECATED
while (!source_ids.is_empty()) {
remove_source(source_ids[0]);
}
@@ -1530,13 +1533,13 @@ bool TileSetAtlasSource::_set(const StringName &p_name, const Variant &p_value)
// Compute the vector2i if we have coordinates.
Vector<String> coords_split = components[0].split(":");
- Vector2i coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ Vector2i coords = TileSetSource::INVALID_ATLAS_COORDS;
if (coords_split.size() == 2 && coords_split[0].is_valid_integer() && coords_split[1].is_valid_integer()) {
coords = Vector2i(coords_split[0].to_int(), coords_split[1].to_int());
}
// Properties.
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
// Create the tile if needed.
if (!has_tile(coords)) {
create_tile(coords);
@@ -1549,7 +1552,7 @@ bool TileSetAtlasSource::_set(const StringName &p_name, const Variant &p_value)
tiles[coords].next_alternative_id = p_value;
} else if (components[1].is_valid_integer()) {
int alternative_id = components[1].to_int();
- if (alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ if (alternative_id != TileSetSource::INVALID_TILE_ALTERNATIVE) {
// Create the alternative if needed ?
if (!has_alternative_tile(coords, alternative_id)) {
create_alternative_tile(coords, alternative_id);
@@ -1594,7 +1597,7 @@ bool TileSetAtlasSource::_get(const StringName &p_name, Variant &r_ret) const {
return true;
} else if (components[1].is_valid_integer()) {
int alternative_id = components[1].to_int();
- if (alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE && tiles[coords].alternatives.has(alternative_id)) {
+ if (alternative_id != TileSetSource::INVALID_TILE_ALTERNATIVE && tiles[coords].alternatives.has(alternative_id)) {
if (components.size() >= 3) {
bool valid;
r_ret = tiles[coords].alternatives[alternative_id]->get(components[2], &valid);
@@ -1745,7 +1748,7 @@ int TileSetAtlasSource::get_tiles_count() const {
}
Vector2i TileSetAtlasSource::get_tile_id(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, tiles_ids.size(), TileSetAtlasSource::INVALID_ATLAS_COORDS);
+ ERR_FAIL_INDEX_V(p_index, tiles_ids.size(), TileSetSource::INVALID_ATLAS_COORDS);
return tiles_ids[p_index];
}
@@ -1798,7 +1801,7 @@ bool TileSetAtlasSource::can_move_tile_in_atlas(Vector2i p_atlas_coords, Vector2
for (int x = new_rect.position.x; x < new_rect.get_end().x; x++) {
for (int y = new_rect.position.y; y < new_rect.get_end().y; y++) {
Vector2i coords = get_tile_at_coords(Vector2i(x, y));
- if (coords != p_atlas_coords && coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != p_atlas_coords && coords != TileSetSource::INVALID_ATLAS_COORDS) {
return false;
}
}
@@ -1880,7 +1883,7 @@ void TileSetAtlasSource::clear_tiles_outside_texture() {
int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_id_override) {
ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
- ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && (tiles[p_atlas_coords].alternatives.has(p_alternative_id_override) || tiles[p_atlas_coords].alternatives.has(p_alternative_id_override)), -1, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override));
+ ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && tiles[p_atlas_coords].alternatives.has(p_alternative_id_override), -1, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override));
int new_alternative_id = p_alternative_id_override >= 0 ? p_alternative_id_override : tiles[p_atlas_coords].next_alternative_id;
@@ -2034,6 +2037,202 @@ void TileSetAtlasSource::_compute_next_alternative_id(const Vector2i p_atlas_coo
};
}
+/////////////////////////////// TileSetScenesCollectionSource //////////////////////////////////////
+
+void TileSetScenesCollectionSource::_compute_next_alternative_id() {
+ while (scenes.has(next_scene_id)) {
+ next_scene_id = (next_scene_id % 1073741823) + 1; // 2 ** 30
+ };
+}
+
+int TileSetScenesCollectionSource::get_tiles_count() const {
+ return 1;
+}
+
+Vector2i TileSetScenesCollectionSource::get_tile_id(int p_tile_index) const {
+ ERR_FAIL_COND_V(p_tile_index != 0, TileSetSource::INVALID_ATLAS_COORDS);
+ return Vector2i();
+}
+
+bool TileSetScenesCollectionSource::has_tile(Vector2i p_atlas_coords) const {
+ return p_atlas_coords == Vector2i();
+}
+
+int TileSetScenesCollectionSource::get_alternative_tiles_count(const Vector2i p_atlas_coords) const {
+ return scenes_ids.size();
+}
+
+int TileSetScenesCollectionSource::get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const {
+ ERR_FAIL_COND_V(p_atlas_coords != Vector2i(), TileSetSource::INVALID_TILE_ALTERNATIVE);
+ ERR_FAIL_INDEX_V(p_index, scenes_ids.size(), TileSetSource::INVALID_TILE_ALTERNATIVE);
+
+ return scenes_ids[p_index];
+}
+
+bool TileSetScenesCollectionSource::has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const {
+ ERR_FAIL_COND_V(p_atlas_coords != Vector2i(), false);
+ return scenes.has(p_alternative_tile);
+}
+
+int TileSetScenesCollectionSource::create_scene_tile(Ref<PackedScene> p_packed_scene, int p_id_override) {
+ ERR_FAIL_COND_V_MSG(p_id_override >= 0 && scenes.has(p_id_override), -1, vformat("Cannot create scene tile. Another scene tile exists with id %d.", p_id_override));
+
+ int new_scene_id = p_id_override >= 0 ? p_id_override : next_scene_id;
+
+ scenes[new_scene_id] = SceneData();
+ scenes_ids.append(new_scene_id);
+ scenes_ids.sort();
+ set_scene_tile_scene(new_scene_id, p_packed_scene);
+ _compute_next_alternative_id();
+
+ emit_signal("changed");
+
+ return new_scene_id;
+}
+
+void TileSetScenesCollectionSource::set_scene_tile_id(int p_id, int p_new_id) {
+ ERR_FAIL_COND(p_new_id < 0);
+ ERR_FAIL_COND(!has_scene_tile_id(p_id));
+ ERR_FAIL_COND(has_scene_tile_id(p_new_id));
+
+ scenes[p_new_id] = SceneData();
+ scenes[p_new_id] = scenes[p_id];
+ scenes_ids.append(p_new_id);
+ scenes_ids.sort();
+
+ _compute_next_alternative_id();
+
+ scenes.erase(p_id);
+ scenes_ids.erase(p_id);
+
+ emit_signal("changed");
+}
+
+void TileSetScenesCollectionSource::set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene) {
+ ERR_FAIL_COND(!scenes.has(p_id));
+ if (p_packed_scene.is_valid()) {
+ // Make sure we have a root node. Supposed to be at 0 index because find_node_by_path() does not seem to work.
+ ERR_FAIL_COND(!p_packed_scene->get_state().is_valid());
+ ERR_FAIL_COND(p_packed_scene->get_state()->get_node_count() < 1);
+
+ // Check if it extends CanvasItem.
+ String type = p_packed_scene->get_state()->get_node_type(0);
+ bool extends_correct_class = ClassDB::is_parent_class(type, "Control") || ClassDB::is_parent_class(type, "Node2D");
+ ERR_FAIL_COND_MSG(!extends_correct_class, vformat("Invalid PackedScene for TileSetScenesCollectionSource: %s. Root node should extend Control or Node2D.", p_packed_scene->get_path()));
+
+ scenes[p_id].scene = p_packed_scene;
+ } else {
+ scenes[p_id].scene = Ref<PackedScene>();
+ }
+ emit_signal("changed");
+}
+
+Ref<PackedScene> TileSetScenesCollectionSource::get_scene_tile_scene(int p_id) const {
+ ERR_FAIL_COND_V(!scenes.has(p_id), Ref<PackedScene>());
+ return scenes[p_id].scene;
+}
+
+void TileSetScenesCollectionSource::set_scene_tile_display_placeholder(int p_id, bool p_display_placeholder) {
+ ERR_FAIL_COND(!scenes.has(p_id));
+
+ scenes[p_id].display_placeholder = p_display_placeholder;
+
+ emit_signal("changed");
+}
+
+bool TileSetScenesCollectionSource::get_scene_tile_display_placeholder(int p_id) const {
+ ERR_FAIL_COND_V(!scenes.has(p_id), false);
+ return scenes[p_id].display_placeholder;
+}
+
+void TileSetScenesCollectionSource::remove_scene_tile(int p_id) {
+ ERR_FAIL_COND(!scenes.has(p_id));
+
+ scenes.erase(p_id);
+ scenes_ids.erase(p_id);
+ emit_signal("changed");
+}
+
+int TileSetScenesCollectionSource::get_next_scene_tile_id() const {
+ return next_scene_id;
+}
+
+bool TileSetScenesCollectionSource::_set(const StringName &p_name, const Variant &p_value) {
+ Vector<String> components = String(p_name).split("/", true, 2);
+
+ if (components.size() >= 2 && components[0] == "scenes" && components[1].is_valid_integer()) {
+ int scene_id = components[1].to_int();
+ if (components.size() >= 3 && components[2] == "scene") {
+ if (has_scene_tile_id(scene_id)) {
+ set_scene_tile_scene(scene_id, p_value);
+ } else {
+ create_scene_tile(p_value, scene_id);
+ }
+ return true;
+ } else if (components.size() >= 3 && components[2] == "display_placeholder") {
+ if (!has_scene_tile_id(scene_id)) {
+ create_scene_tile(p_value, scene_id);
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool TileSetScenesCollectionSource::_get(const StringName &p_name, Variant &r_ret) const {
+ Vector<String> components = String(p_name).split("/", true, 2);
+
+ if (components.size() >= 2 && components[0] == "scenes" && components[1].is_valid_integer() && scenes.has(components[1].to_int())) {
+ if (components.size() >= 3 && components[2] == "scene") {
+ r_ret = scenes[components[1].to_int()].scene;
+ return true;
+ } else if (components.size() >= 3 && components[2] == "display_placeholder") {
+ r_ret = scenes[components[1].to_int()].scene;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void TileSetScenesCollectionSource::_get_property_list(List<PropertyInfo> *p_list) const {
+ for (int i = 0; i < scenes_ids.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("scenes/%d/scene", scenes_ids[i]), PROPERTY_HINT_RESOURCE_TYPE, "TileSetScenesCollectionSource"));
+
+ PropertyInfo property_info = PropertyInfo(Variant::BOOL, vformat("scenes/%d/display_placeholder", scenes_ids[i]));
+ if (scenes[scenes_ids[i]].display_placeholder == false) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+}
+
+void TileSetScenesCollectionSource::_bind_methods() {
+ // Base tiles
+ ClassDB::bind_method(D_METHOD("get_tiles_count"), &TileSetScenesCollectionSource::get_tiles_count);
+ ClassDB::bind_method(D_METHOD("get_tile_id", "index"), &TileSetScenesCollectionSource::get_tile_id);
+ ClassDB::bind_method(D_METHOD("has_tile", "atlas_coords"), &TileSetScenesCollectionSource::has_tile);
+
+ // Alternative tiles
+ ClassDB::bind_method(D_METHOD("get_alternative_tiles_count", "atlas_coords"), &TileSetScenesCollectionSource::get_alternative_tiles_count);
+ ClassDB::bind_method(D_METHOD("get_alternative_tile_id", "atlas_coords", "index"), &TileSetScenesCollectionSource::get_alternative_tile_id);
+ ClassDB::bind_method(D_METHOD("has_alternative_tile", "atlas_coords", "alternative_tile"), &TileSetScenesCollectionSource::has_alternative_tile);
+
+ ClassDB::bind_method(D_METHOD("get_scene_tiles_count"), &TileSetScenesCollectionSource::get_scene_tiles_count);
+ ClassDB::bind_method(D_METHOD("get_scene_tile_id", "index"), &TileSetScenesCollectionSource::get_scene_tile_id);
+ ClassDB::bind_method(D_METHOD("has_scene_tile_id", "id"), &TileSetScenesCollectionSource::has_scene_tile_id);
+ ClassDB::bind_method(D_METHOD("create_scene_tile", "packed_scene", "id_override"), &TileSetScenesCollectionSource::create_scene_tile, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("set_scene_tile_id", "id", "new_id"), &TileSetScenesCollectionSource::set_scene_tile_id);
+ ClassDB::bind_method(D_METHOD("set_scene_tile_scene", "id", "packed_scene"), &TileSetScenesCollectionSource::set_scene_tile_scene);
+ ClassDB::bind_method(D_METHOD("get_scene_tile_scene", "id"), &TileSetScenesCollectionSource::get_scene_tile_scene);
+ ClassDB::bind_method(D_METHOD("set_scene_tile_display_placeholder", "id", "display_placeholder"), &TileSetScenesCollectionSource::set_scene_tile_display_placeholder);
+ ClassDB::bind_method(D_METHOD("get_scene_tile_display_placeholder", "id"), &TileSetScenesCollectionSource::get_scene_tile_display_placeholder);
+ ClassDB::bind_method(D_METHOD("remove_scene_tile", "id"), &TileSetScenesCollectionSource::remove_scene_tile);
+ ClassDB::bind_method(D_METHOD("get_next_scene_tile_id"), &TileSetScenesCollectionSource::get_next_scene_tile_id);
+}
+
/////////////////////////////// TileData //////////////////////////////////////
void TileData::set_tile_set(const TileSet *p_tile_set) {
@@ -2154,11 +2353,11 @@ int TileData::get_z_index() const {
return z_index;
}
-void TileData::set_y_sort_origin(Vector2i p_y_sort_origin) {
+void TileData::set_y_sort_origin(int p_y_sort_origin) {
y_sort_origin = p_y_sort_origin;
emit_signal("changed");
}
-Vector2i TileData::get_y_sort_origin() const {
+int TileData::get_y_sort_origin() const {
return y_sort_origin;
}
@@ -2255,6 +2454,7 @@ int TileData::get_terrain_set() const {
}
void TileData::set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) {
+ ERR_FAIL_INDEX(p_peering_bit, TileSet::CELL_NEIGHBOR_MAX);
ERR_FAIL_COND(p_terrain_index < -1);
if (tile_set) {
ERR_FAIL_COND(p_terrain_index >= tile_set->get_terrains_count(terrain_set));
@@ -2265,6 +2465,7 @@ void TileData::set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int
}
int TileData::get_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const {
+ ERR_FAIL_INDEX_V(p_peering_bit, TileSet::CELL_NEIGHBOR_MAX, -1);
return terrain_peering_bits[p_peering_bit];
}
@@ -2823,7 +3024,7 @@ void TileData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "texture_offset"), "set_texture_offset", "get_texture_offset");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index"), "set_z_index", "get_z_index");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "y_sort_origin"), "set_y_sort_origin", "get_y_sort_origin");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "y_sort_origin"), "set_y_sort_origin", "get_y_sort_origin");
ADD_GROUP("Terrains", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "terrain_set"), "set_terrain_set", "get_terrain_set");
@@ -2834,10 +3035,10 @@ void TileData::_bind_methods() {
ADD_SIGNAL(MethodInfo("changed"));
}
-/////////////////////////////// TileSetAtlasPluginTerrain //////////////////////////////////////
+/////////////////////////////// TileSetPluginAtlasTerrain //////////////////////////////////////
// --- PLUGINS ---
-void TileSetAtlasPluginTerrain::_draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+void TileSetPluginAtlasTerrain::_draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
Rect2 bit_rect;
bit_rect.size = Vector2(p_size) / 3;
switch (p_bit) {
@@ -2872,7 +3073,7 @@ void TileSetAtlasPluginTerrain::_draw_square_corner_or_side_terrain_bit(CanvasIt
p_canvas_item->draw_rect(bit_rect, p_color);
}
-void TileSetAtlasPluginTerrain::_draw_square_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+void TileSetPluginAtlasTerrain::_draw_square_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
PackedColorArray color_array;
color_array.push_back(p_color);
@@ -2919,7 +3120,7 @@ void TileSetAtlasPluginTerrain::_draw_square_corner_terrain_bit(CanvasItem *p_ca
}
}
-void TileSetAtlasPluginTerrain::_draw_square_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+void TileSetPluginAtlasTerrain::_draw_square_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
PackedColorArray color_array;
color_array.push_back(p_color);
@@ -2958,7 +3159,7 @@ void TileSetAtlasPluginTerrain::_draw_square_side_terrain_bit(CanvasItem *p_canv
}
}
-void TileSetAtlasPluginTerrain::_draw_isometric_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+void TileSetPluginAtlasTerrain::_draw_isometric_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
PackedColorArray color_array;
color_array.push_back(p_color);
@@ -3021,7 +3222,7 @@ void TileSetAtlasPluginTerrain::_draw_isometric_corner_or_side_terrain_bit(Canva
}
}
-void TileSetAtlasPluginTerrain::_draw_isometric_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+void TileSetPluginAtlasTerrain::_draw_isometric_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
PackedColorArray color_array;
color_array.push_back(p_color);
@@ -3068,7 +3269,7 @@ void TileSetAtlasPluginTerrain::_draw_isometric_corner_terrain_bit(CanvasItem *p
}
}
-void TileSetAtlasPluginTerrain::_draw_isometric_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+void TileSetPluginAtlasTerrain::_draw_isometric_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
PackedColorArray color_array;
color_array.push_back(p_color);
@@ -3107,7 +3308,7 @@ void TileSetAtlasPluginTerrain::_draw_isometric_side_terrain_bit(CanvasItem *p_c
}
}
-void TileSetAtlasPluginTerrain::_draw_half_offset_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+void TileSetPluginAtlasTerrain::_draw_half_offset_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
PackedColorArray color_array;
color_array.push_back(p_color);
@@ -3272,7 +3473,7 @@ void TileSetAtlasPluginTerrain::_draw_half_offset_corner_or_side_terrain_bit(Can
}
}
-void TileSetAtlasPluginTerrain::_draw_half_offset_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+void TileSetPluginAtlasTerrain::_draw_half_offset_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
PackedColorArray color_array;
color_array.push_back(p_color);
@@ -3383,7 +3584,7 @@ void TileSetAtlasPluginTerrain::_draw_half_offset_corner_terrain_bit(CanvasItem
}
}
-void TileSetAtlasPluginTerrain::_draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+void TileSetPluginAtlasTerrain::_draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
PackedColorArray color_array;
color_array.push_back(p_color);
@@ -3498,7 +3699,7 @@ void TileSetAtlasPluginTerrain::_draw_half_offset_side_terrain_bit(CanvasItem *p
} \
}
-void TileSetAtlasPluginTerrain::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data) {
+void TileSetPluginAtlasTerrain::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data) {
ERR_FAIL_COND(!p_tile_set);
ERR_FAIL_COND(!p_tile_data);
@@ -3632,9 +3833,9 @@ void TileSetAtlasPluginTerrain::draw_terrains(CanvasItem *p_canvas_item, Transfo
RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
}
-/////////////////////////////// TileSetAtlasPluginRendering //////////////////////////////////////
+/////////////////////////////// TileSetPluginAtlasRendering //////////////////////////////////////
-void TileSetAtlasPluginRendering::tilemap_notification(TileMap *p_tile_map, int p_what) {
+void TileSetPluginAtlasRendering::tilemap_notification(TileMap *p_tile_map, int p_what) {
switch (p_what) {
case CanvasItem::NOTIFICATION_VISIBILITY_CHANGED: {
bool visible = p_tile_map->is_visible_in_tree();
@@ -3669,10 +3870,16 @@ void TileSetAtlasPluginRendering::tilemap_notification(TileMap *p_tile_map, int
}
}
} break;
+ case CanvasItem::NOTIFICATION_DRAW: {
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ if (tile_set.is_valid() || p_tile_map->is_y_sort_enabled()) {
+ RenderingServer::get_singleton()->canvas_item_set_sort_children_by_y(p_tile_map->get_canvas_item(), tile_set->is_y_sorting() || p_tile_map->is_y_sort_enabled());
+ }
+ } break;
}
}
-void TileSetAtlasPluginRendering::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation) {
+void TileSetPluginAtlasRendering::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation) {
ERR_FAIL_COND(!p_tile_set.is_valid());
ERR_FAIL_COND(!p_tile_set->has_source(p_atlas_source_id));
ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_tile(p_atlas_coords));
@@ -3687,6 +3894,12 @@ void TileSetAtlasPluginRendering::draw_tile(RID p_canvas_item, Vector2i p_positi
return;
}
+ // Check if we are in the texture, return otherwise.
+ Vector2i grid_size = atlas_source->get_atlas_grid_size();
+ if (p_atlas_coords.x >= grid_size.x || p_atlas_coords.y >= grid_size.y) {
+ return;
+ }
+
// Get tile data.
TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(p_atlas_coords, p_alternative_tile));
@@ -3724,7 +3937,7 @@ void TileSetAtlasPluginRendering::draw_tile(RID p_canvas_item, Vector2i p_positi
}
}
-void TileSetAtlasPluginRendering::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
+void TileSetPluginAtlasRendering::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
ERR_FAIL_COND(!p_tile_map);
ERR_FAIL_COND(!p_tile_map->is_inside_tree());
Ref<TileSet> tile_set = p_tile_map->get_tileset();
@@ -3775,7 +3988,11 @@ void TileSetAtlasPluginRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
int z_index = tile_data->get_z_index();
// Quandrant pos.
- Vector2 position = p_tile_map->map_to_world(q.coords * p_tile_map->get_effective_quadrant_size()) - tile_set->get_tile_size() / 2;
+ Vector2 position = p_tile_map->map_to_world(q.coords * p_tile_map->get_effective_quadrant_size());
+ if (tile_set->is_y_sorting()) {
+ // When Y-sorting, the quandrant size is sure to be 1, we can thus offset the CanvasItem.
+ position.y += tile_data->get_y_sort_origin();
+ }
// --- CanvasItems ---
// Create two canvas items, for rendering and debug.
@@ -3783,16 +4000,18 @@ void TileSetAtlasPluginRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
// Check if the material or the z_index changed.
if (prev_canvas_item == RID() || prev_material != mat || prev_z_index != z_index) {
+ // If so, create a new CanvasItem.
canvas_item = rs->canvas_item_create();
if (mat.is_valid()) {
rs->canvas_item_set_material(canvas_item, mat->get_rid());
}
rs->canvas_item_set_parent(canvas_item, p_tile_map->get_canvas_item());
rs->canvas_item_set_use_parent_material(canvas_item, p_tile_map->get_use_parent_material() || p_tile_map->get_material().is_valid());
+
Transform2D xform;
xform.set_origin(position);
-
rs->canvas_item_set_transform(canvas_item, xform);
+
rs->canvas_item_set_light_mask(canvas_item, p_tile_map->get_light_mask());
rs->canvas_item_set_z_index(canvas_item, z_index);
@@ -3858,14 +4077,14 @@ void TileSetAtlasPluginRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
}
}
-void TileSetAtlasPluginRendering::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+void TileSetPluginAtlasRendering::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
Ref<TileSet> tile_set = p_tile_map->get_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
quadrant_order_dirty = true;
}
-void TileSetAtlasPluginRendering::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+void TileSetPluginAtlasRendering::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
// Free the canvas items.
for (List<RID>::Element *E = p_quadrant->canvas_items.front(); E; E = E->next()) {
RenderingServer::get_singleton()->free(E->get());
@@ -3879,9 +4098,60 @@ void TileSetAtlasPluginRendering::cleanup_quadrant(TileMap *p_tile_map, TileMapQ
p_quadrant->occluders.clear();
}
-/////////////////////////////// TileSetAtlasPluginPhysics //////////////////////////////////////
+void TileSetPluginAtlasRendering::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
-void TileSetAtlasPluginPhysics::tilemap_notification(TileMap *p_tile_map, int p_what) {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+
+ // Draw a placeholder for scenes needing one.
+ RenderingServer *rs = RenderingServer::get_singleton();
+ Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
+ for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
+ const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
+
+ TileSetSource *source;
+ if (tile_set->has_source(c.source_id)) {
+ source = *tile_set->get_source(c.source_id);
+
+ if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) {
+ continue;
+ }
+
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ Vector2i grid_size = atlas_source->get_atlas_grid_size();
+ if (!atlas_source->get_texture().is_valid() || c.get_atlas_coords().x >= grid_size.x || c.get_atlas_coords().y >= grid_size.y) {
+ // Generate a random color from the hashed values of the tiles.
+ Array to_hash;
+ to_hash.push_back(c.source_id);
+ to_hash.push_back(c.get_atlas_coords());
+ to_hash.push_back(c.alternative_tile);
+ uint32_t hash = RandomPCG(to_hash.hash()).rand();
+
+ Color color;
+ color = color.from_hsv(
+ (float)((hash >> 24) & 0xFF) / 256.0,
+ Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
+ Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
+ 0.8);
+
+ // Draw a placeholder tile.
+ Transform2D xform;
+ xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos);
+ rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform);
+ rs->canvas_item_add_circle(p_quadrant->debug_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color);
+ }
+ }
+ }
+ }
+}
+
+/////////////////////////////// TileSetPluginAtlasPhysics //////////////////////////////////////
+
+void TileSetPluginAtlasPhysics::tilemap_notification(TileMap *p_tile_map, int p_what) {
switch (p_what) {
case CanvasItem::NOTIFICATION_TRANSFORM_CHANGED: {
// Update the bodies transforms.
@@ -3905,7 +4175,7 @@ void TileSetAtlasPluginPhysics::tilemap_notification(TileMap *p_tile_map, int p_
}
}
-void TileSetAtlasPluginPhysics::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
+void TileSetPluginAtlasPhysics::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
ERR_FAIL_COND(!p_tile_map);
ERR_FAIL_COND(!p_tile_map->is_inside_tree());
Ref<TileSet> tile_set = p_tile_map->get_tileset();
@@ -3971,7 +4241,7 @@ void TileSetAtlasPluginPhysics::update_dirty_quadrants(TileMap *p_tile_map, Self
}
}
-void TileSetAtlasPluginPhysics::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+void TileSetPluginAtlasPhysics::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
Ref<TileSet> tile_set = p_tile_map->get_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
@@ -4016,7 +4286,7 @@ void TileSetAtlasPluginPhysics::create_quadrant(TileMap *p_tile_map, TileMapQuad
}
}
-void TileSetAtlasPluginPhysics::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+void TileSetPluginAtlasPhysics::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
// Remove a quadrant.
for (int body_index = 0; body_index < p_quadrant->bodies.size(); body_index++) {
PhysicsServer2D::get_singleton()->free(p_quadrant->bodies[body_index]);
@@ -4024,12 +4294,28 @@ void TileSetAtlasPluginPhysics::cleanup_quadrant(TileMap *p_tile_map, TileMapQua
p_quadrant->bodies.clear();
}
-void TileSetAtlasPluginPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+void TileSetPluginAtlasPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
// Draw the debug collision shapes.
Ref<TileSet> tile_set = p_tile_map->get_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
- if (!p_tile_map->get_tree() || !(Engine::get_singleton()->is_editor_hint() || p_tile_map->get_tree()->is_debugging_collisions_hint())) {
+ if (!p_tile_map->get_tree()) {
+ return;
+ }
+
+ bool show_collision = false;
+ switch (p_tile_map->get_collision_visibility_mode()) {
+ case TileMap::VISIBILITY_MODE_DEFAULT:
+ show_collision = !Engine::get_singleton()->is_editor_hint() && (p_tile_map->get_tree() && p_tile_map->get_tree()->is_debugging_navigation_hint());
+ break;
+ case TileMap::VISIBILITY_MODE_FORCE_HIDE:
+ show_collision = false;
+ break;
+ case TileMap::VISIBILITY_MODE_FORCE_SHOW:
+ show_collision = true;
+ break;
+ }
+ if (!show_collision) {
return;
}
@@ -4071,9 +4357,9 @@ void TileSetAtlasPluginPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMap
}
};
-/////////////////////////////// TileSetAtlasPluginNavigation //////////////////////////////////////
+/////////////////////////////// TileSetPluginAtlasNavigation //////////////////////////////////////
-void TileSetAtlasPluginNavigation::tilemap_notification(TileMap *p_tile_map, int p_what) {
+void TileSetPluginAtlasNavigation::tilemap_notification(TileMap *p_tile_map, int p_what) {
switch (p_what) {
case CanvasItem::NOTIFICATION_TRANSFORM_CHANGED: {
if (p_tile_map->is_inside_tree()) {
@@ -4098,7 +4384,7 @@ void TileSetAtlasPluginNavigation::tilemap_notification(TileMap *p_tile_map, int
}
}
-void TileSetAtlasPluginNavigation::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
+void TileSetPluginAtlasNavigation::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
ERR_FAIL_COND(!p_tile_map);
ERR_FAIL_COND(!p_tile_map->is_inside_tree());
Ref<TileSet> tile_set = p_tile_map->get_tileset();
@@ -4169,7 +4455,7 @@ void TileSetAtlasPluginNavigation::update_dirty_quadrants(TileMap *p_tile_map, S
}
}
-void TileSetAtlasPluginNavigation::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+void TileSetPluginAtlasNavigation::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
// Clear navigation shapes in the quadrant.
for (Map<Vector2i, Vector<RID>>::Element *E = p_quadrant->navigation_regions.front(); E; E = E->next()) {
for (int i = 0; i < E->get().size(); i++) {
@@ -4183,12 +4469,28 @@ void TileSetAtlasPluginNavigation::cleanup_quadrant(TileMap *p_tile_map, TileMap
p_quadrant->navigation_regions.clear();
}
-void TileSetAtlasPluginNavigation::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+void TileSetPluginAtlasNavigation::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
// Draw the debug collision shapes.
Ref<TileSet> tile_set = p_tile_map->get_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
- if (!p_tile_map->get_tree() || !(Engine::get_singleton()->is_editor_hint() || p_tile_map->get_tree()->is_debugging_navigation_hint())) {
+ if (!p_tile_map->get_tree()) {
+ return;
+ }
+
+ bool show_navigation = false;
+ switch (p_tile_map->get_navigation_visibility_mode()) {
+ case TileMap::VISIBILITY_MODE_DEFAULT:
+ show_navigation = !Engine::get_singleton()->is_editor_hint() && (p_tile_map->get_tree() && p_tile_map->get_tree()->is_debugging_navigation_hint());
+ break;
+ case TileMap::VISIBILITY_MODE_FORCE_HIDE:
+ show_navigation = false;
+ break;
+ case TileMap::VISIBILITY_MODE_FORCE_SHOW:
+ show_navigation = true;
+ break;
+ }
+ if (!show_navigation) {
return;
}
@@ -4240,7 +4542,7 @@ void TileSetAtlasPluginNavigation::draw_quadrant_debug(TileMap *p_tile_map, Tile
Vector<Color> colors;
colors.push_back(random_variation_color);
- RS::get_singleton()->canvas_item_add_polygon(p_quadrant->debug_canvas_item, vertices, colors);
+ rs->canvas_item_add_polygon(p_quadrant->debug_canvas_item, vertices, colors);
}
}
}
@@ -4248,3 +4550,121 @@ void TileSetAtlasPluginNavigation::draw_quadrant_debug(TileMap *p_tile_map, Tile
}
}
}
+
+/////////////////////////////// TileSetPluginScenesCollections //////////////////////////////////////
+
+void TileSetPluginScenesCollections::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ SelfList<TileMapQuadrant> *q_list_element = r_dirty_quadrant_list.first();
+ while (q_list_element) {
+ TileMapQuadrant &q = *q_list_element->self();
+
+ // Clear the scenes.
+ for (Map<Vector2i, String>::Element *E = q.scenes.front(); E; E = E->next()) {
+ Node *node = p_tile_map->get_node(E->get());
+ if (node) {
+ node->queue_delete();
+ }
+ }
+
+ q.scenes.clear();
+
+ // Recreate the scenes.
+ for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
+ const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
+
+ TileSetSource *source;
+ if (tile_set->has_source(c.source_id)) {
+ source = *tile_set->get_source(c.source_id);
+
+ if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) {
+ continue;
+ }
+
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ if (scenes_collection_source) {
+ Ref<PackedScene> packed_scene = scenes_collection_source->get_scene_tile_scene(c.alternative_tile);
+ if (packed_scene.is_valid()) {
+ Node *scene = packed_scene->instance();
+ p_tile_map->add_child(scene);
+ Control *scene_as_control = Object::cast_to<Control>(scene);
+ Node2D *scene_as_node2d = Object::cast_to<Node2D>(scene);
+ if (scene_as_control) {
+ scene_as_control->set_position(p_tile_map->map_to_world(E_cell->get()) + scene_as_control->get_position());
+ } else if (scene_as_node2d) {
+ Transform2D xform;
+ xform.set_origin(p_tile_map->map_to_world(E_cell->get()));
+ scene_as_node2d->set_transform(xform * scene_as_node2d->get_transform());
+ }
+ q.scenes[E_cell->get()] = scene->get_name();
+ }
+ }
+ }
+ }
+
+ q_list_element = q_list_element->next();
+ }
+}
+
+void TileSetPluginScenesCollections::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ // Clear the scenes.
+ for (Map<Vector2i, String>::Element *E = p_quadrant->scenes.front(); E; E = E->next()) {
+ Node *node = p_tile_map->get_node(E->get());
+ if (node) {
+ node->queue_delete();
+ }
+ }
+
+ p_quadrant->scenes.clear();
+}
+
+void TileSetPluginScenesCollections::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+
+ // Draw a placeholder for scenes needing one.
+ RenderingServer *rs = RenderingServer::get_singleton();
+ Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
+ for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
+ const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
+
+ TileSetSource *source;
+ if (tile_set->has_source(c.source_id)) {
+ source = *tile_set->get_source(c.source_id);
+
+ if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) {
+ continue;
+ }
+
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ if (scenes_collection_source) {
+ if (!scenes_collection_source->get_scene_tile_scene(c.alternative_tile).is_valid() || scenes_collection_source->get_scene_tile_display_placeholder(c.alternative_tile)) {
+ // Generate a random color from the hashed values of the tiles.
+ Array to_hash;
+ to_hash.push_back(c.source_id);
+ to_hash.push_back(c.alternative_tile);
+ uint32_t hash = RandomPCG(to_hash.hash()).rand();
+
+ Color color;
+ color = color.from_hsv(
+ (float)((hash >> 24) & 0xFF) / 256.0,
+ Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
+ Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
+ 0.8);
+
+ // Draw a placeholder tile.
+ Transform2D xform;
+ xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos);
+ rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform);
+ rs->canvas_item_add_circle(p_quadrant->debug_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color);
+ }
+ }
+ }
+ }
+}
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 20cf183a20..6cf4198f30 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -57,10 +57,10 @@ class TileData;
// Forward-declare the plugins.
class TileSetPlugin;
-class TileSetAtlasPluginRendering;
-class TileSetAtlasPluginPhysics;
-class TileSetAtlasPluginNavigation;
-class TileSetAtlasPluginTerrain;
+class TileSetPluginAtlasRendering;
+class TileSetPluginAtlasPhysics;
+class TileSetPluginAtlasNavigation;
+class TileSetPluginAtlasTerrain;
class TileSet : public Resource {
GDCLASS(TileSet, Resource);
@@ -264,7 +264,7 @@ public:
int get_next_source_id() const;
int get_source_count() const;
int get_source_id(int p_index) const;
- int add_source(Ref<TileSetAtlasSource> p_tile_atlas_source, int p_source_id_override = -1);
+ int add_source(Ref<TileSetSource> p_tile_set_source, int p_source_id_override = -1);
void set_source_id(int p_source_id, int p_new_id);
void remove_source(int p_source_id);
bool has_source(int p_source_id) const;
@@ -338,6 +338,9 @@ protected:
const TileSet *tile_set = nullptr;
public:
+ static const Vector2i INVALID_ATLAS_COORDS; // Vector2i(-1, -1);
+ static const int INVALID_TILE_ALTERNATIVE; // -1;
+
// Not exposed.
virtual void set_tile_set(const TileSet *p_tile_set);
virtual void notify_tile_data_properties_should_change(){};
@@ -358,9 +361,6 @@ class TileSetAtlasSource : public TileSetSource {
GDCLASS(TileSetAtlasSource, TileSetSource);
public:
- static const Vector2i INVALID_ATLAS_COORDS; // Vector2i(-1, -1);
- static const int INVALID_TILE_ALTERNATIVE; // -1;
-
struct TileAlternativesData {
Vector2i size_in_atlas = Vector2i(1, 1);
Vector2i texture_offset;
@@ -443,6 +443,52 @@ public:
~TileSetAtlasSource();
};
+class TileSetScenesCollectionSource : public TileSetSource {
+ GDCLASS(TileSetScenesCollectionSource, TileSetSource);
+
+private:
+ struct SceneData {
+ Ref<PackedScene> scene;
+ bool display_placeholder = false;
+ };
+ Vector<int> scenes_ids;
+ Map<int, SceneData> scenes;
+ int next_scene_id = 1;
+
+ void _compute_next_alternative_id();
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ static void _bind_methods();
+
+public:
+ // Tiles.
+ int get_tiles_count() const override;
+ Vector2i get_tile_id(int p_tile_index) const override;
+ bool has_tile(Vector2i p_atlas_coords) const override;
+
+ // Alternative tiles.
+ int get_alternative_tiles_count(const Vector2i p_atlas_coords) const override;
+ int get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const override;
+ bool has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const override;
+
+ // Scenes sccessors. Lot are similar to "Alternative tiles".
+ int get_scene_tiles_count() { return get_alternative_tiles_count(Vector2i()); }
+ int get_scene_tile_id(int p_index) { return get_alternative_tile_id(Vector2i(), p_index); };
+ bool has_scene_tile_id(int p_id) { return has_alternative_tile(Vector2i(), p_id); };
+ int create_scene_tile(Ref<PackedScene> p_packed_scene = Ref<PackedScene>(), int p_id_override = -1);
+ void set_scene_tile_id(int p_id, int p_new_id);
+ void set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene);
+ Ref<PackedScene> get_scene_tile_scene(int p_id) const;
+ void set_scene_tile_display_placeholder(int p_id, bool p_packed_scene);
+ bool get_scene_tile_display_placeholder(int p_id) const;
+ void remove_scene_tile(int p_id);
+ int get_next_scene_tile_id() const;
+};
+
class TileData : public Object {
GDCLASS(TileData, Object);
@@ -458,7 +504,7 @@ private:
Ref<ShaderMaterial> material = Ref<ShaderMaterial>();
Color modulate = Color(1.0, 1.0, 1.0, 1.0);
int z_index = 0;
- Vector2i y_sort_origin = Vector2i();
+ int y_sort_origin = 0;
Vector<Ref<OccluderPolygon2D>> occluders;
// Physics
@@ -517,8 +563,8 @@ public:
Color get_modulate() const;
void set_z_index(int p_z_index);
int get_z_index() const;
- void set_y_sort_origin(Vector2i p_y_sort_origin);
- Vector2i get_y_sort_origin() const;
+ void set_y_sort_origin(int p_y_sort_origin);
+ int get_y_sort_origin() const;
void set_occluder(int p_layer_id, Ref<OccluderPolygon2D> p_occluder_polygon);
Ref<OccluderPolygon2D> get_occluder(int p_layer_id) const;
@@ -572,8 +618,8 @@ public:
virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant){};
};
-class TileSetAtlasPluginRendering : public TileSetPlugin {
- GDCLASS(TileSetAtlasPluginRendering, TileSetPlugin);
+class TileSetPluginAtlasRendering : public TileSetPlugin {
+ GDCLASS(TileSetPluginAtlasRendering, TileSetPlugin);
private:
static constexpr float fp_adjust = 0.00001;
@@ -585,13 +631,14 @@ public:
virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override;
virtual void create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+ virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
// Other.
static void draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0));
};
-class TileSetAtlasPluginTerrain : public TileSetPlugin {
- GDCLASS(TileSetAtlasPluginTerrain, TileSetPlugin);
+class TileSetPluginAtlasTerrain : public TileSetPlugin {
+ GDCLASS(TileSetPluginAtlasTerrain, TileSetPlugin);
private:
static void _draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
@@ -607,13 +654,11 @@ private:
static void _draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
public:
- //virtual void tilemap_notification(const TileMap * p_tile_map, int p_what);
-
static void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data);
};
-class TileSetAtlasPluginPhysics : public TileSetPlugin {
- GDCLASS(TileSetAtlasPluginPhysics, TileSetPlugin);
+class TileSetPluginAtlasPhysics : public TileSetPlugin {
+ GDCLASS(TileSetPluginAtlasPhysics, TileSetPlugin);
public:
// Tilemap updates
@@ -624,14 +669,23 @@ public:
virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
};
-class TileSetAtlasPluginNavigation : public TileSetPlugin {
- GDCLASS(TileSetAtlasPluginNavigation, TileSetPlugin);
+class TileSetPluginAtlasNavigation : public TileSetPlugin {
+ GDCLASS(TileSetPluginAtlasNavigation, TileSetPlugin);
public:
// Tilemap updates
virtual void tilemap_notification(TileMap *p_tile_map, int p_what) override;
virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override;
- //virtual void create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+ virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+ virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+};
+
+class TileSetPluginScenesCollections : public TileSetPlugin {
+ GDCLASS(TileSetPluginScenesCollections, TileSetPlugin);
+
+public:
+ // Tilemap updates
+ virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override;
virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
};
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index b810f9562e..5759948fe6 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -33,6 +33,7 @@
#include "core/templates/vmap.h"
#include "servers/rendering/shader_types.h"
#include "visual_shader_nodes.h"
+#include "visual_shader_particle_nodes.h"
#include "visual_shader_sdf_nodes.h"
bool VisualShaderNode::is_simple_decl() const {
@@ -60,6 +61,20 @@ Variant VisualShaderNode::get_input_port_default_value(int p_port) const {
return Variant();
}
+void VisualShaderNode::remove_input_port_default_value(int p_port) {
+ if (default_input_values.has(p_port)) {
+ default_input_values.erase(p_port);
+ emit_changed();
+ }
+}
+
+void VisualShaderNode::clear_default_input_values() {
+ if (!default_input_values.is_empty()) {
+ default_input_values.clear();
+ emit_changed();
+ }
+}
+
bool VisualShaderNode::is_port_separator(int p_index) const {
return false;
}
@@ -94,6 +109,52 @@ bool VisualShaderNode::is_generate_input_var(int p_port) const {
return true;
}
+bool VisualShaderNode::is_output_port_expandable(int p_port) const {
+ return false;
+}
+
+void VisualShaderNode::_set_output_ports_expanded(const Array &p_values) {
+ for (int i = 0; i < p_values.size(); i++) {
+ expanded_output_ports[p_values[i]] = true;
+ }
+ emit_changed();
+}
+
+Array VisualShaderNode::_get_output_ports_expanded() const {
+ Array arr;
+ for (int i = 0; i < get_output_port_count(); i++) {
+ if (_is_output_port_expanded(i)) {
+ arr.push_back(i);
+ }
+ }
+ return arr;
+}
+
+void VisualShaderNode::_set_output_port_expanded(int p_port, bool p_expanded) {
+ expanded_output_ports[p_port] = p_expanded;
+ emit_changed();
+}
+
+bool VisualShaderNode::_is_output_port_expanded(int p_port) const {
+ if (expanded_output_ports.has(p_port)) {
+ return expanded_output_ports[p_port];
+ }
+ return false;
+}
+
+int VisualShaderNode::get_expanded_output_port_count() const {
+ int count = get_output_port_count();
+ int count2 = count;
+ for (int i = 0; i < count; i++) {
+ if (is_output_port_expandable(i) && _is_output_port_expanded(i)) {
+ if (get_output_port_type(i) == PORT_TYPE_VECTOR) {
+ count2 += 3;
+ }
+ }
+ }
+ return count2;
+}
+
bool VisualShaderNode::is_code_generated() const {
return true;
}
@@ -106,6 +167,14 @@ bool VisualShaderNode::is_use_prop_slots() const {
return false;
}
+bool VisualShaderNode::is_disabled() const {
+ return disabled;
+}
+
+void VisualShaderNode::set_disabled(bool p_disabled) {
+ disabled = p_disabled;
+}
+
Vector<VisualShader::DefaultTextureParam> VisualShaderNode::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
return Vector<VisualShader::DefaultTextureParam>();
}
@@ -157,14 +226,24 @@ void VisualShaderNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_output_port_for_preview", "port"), &VisualShaderNode::set_output_port_for_preview);
ClassDB::bind_method(D_METHOD("get_output_port_for_preview"), &VisualShaderNode::get_output_port_for_preview);
+ ClassDB::bind_method(D_METHOD("_set_output_port_expanded", "port"), &VisualShaderNode::_set_output_port_expanded);
+ ClassDB::bind_method(D_METHOD("_is_output_port_expanded"), &VisualShaderNode::_is_output_port_expanded);
+
+ ClassDB::bind_method(D_METHOD("_set_output_ports_expanded", "values"), &VisualShaderNode::_set_output_ports_expanded);
+ ClassDB::bind_method(D_METHOD("_get_output_ports_expanded"), &VisualShaderNode::_get_output_ports_expanded);
+
ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value"), &VisualShaderNode::set_input_port_default_value);
ClassDB::bind_method(D_METHOD("get_input_port_default_value", "port"), &VisualShaderNode::get_input_port_default_value);
+ ClassDB::bind_method(D_METHOD("remove_input_port_default_value", "port"), &VisualShaderNode::remove_input_port_default_value);
+ ClassDB::bind_method(D_METHOD("clear_default_input_values"), &VisualShaderNode::clear_default_input_values);
+
ClassDB::bind_method(D_METHOD("set_default_input_values", "values"), &VisualShaderNode::set_default_input_values);
ClassDB::bind_method(D_METHOD("get_default_input_values"), &VisualShaderNode::get_default_input_values);
ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "expanded_output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_output_ports_expanded", "_get_output_ports_expanded");
ADD_SIGNAL(MethodInfo("editor_refresh_request"));
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR);
@@ -312,6 +391,18 @@ void VisualShaderNodeCustom::set_default_input_values(const Array &p_values) {
}
}
+void VisualShaderNodeCustom::remove_input_port_default_value(int p_port) {
+ if (!is_initialized) {
+ VisualShaderNode::remove_input_port_default_value(p_port);
+ }
+}
+
+void VisualShaderNodeCustom::clear_default_input_values() {
+ if (!is_initialized) {
+ VisualShaderNode::clear_default_input_values();
+ }
+}
+
void VisualShaderNodeCustom::_set_input_port_default_value(int p_port, const Variant &p_value) {
VisualShaderNode::set_input_port_default_value(p_port, p_value);
}
@@ -576,7 +667,7 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
return false;
}
- if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_output_port_count()) {
+ if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_expanded_output_port_count()) {
return false;
}
@@ -617,7 +708,7 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from
Graph *g = &graph[p_type];
ERR_FAIL_COND(!g->nodes.has(p_from_node));
- ERR_FAIL_INDEX(p_from_port, g->nodes[p_from_node].node->get_output_port_count());
+ ERR_FAIL_INDEX(p_from_port, g->nodes[p_from_node].node->get_expanded_output_port_count());
ERR_FAIL_COND(!g->nodes.has(p_to_node));
ERR_FAIL_INDEX(p_to_port, g->nodes[p_to_node].node->get_input_port_count());
@@ -639,7 +730,7 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
Graph *g = &graph[p_type];
ERR_FAIL_COND_V(!g->nodes.has(p_from_node), ERR_INVALID_PARAMETER);
- ERR_FAIL_INDEX_V(p_from_port, g->nodes[p_from_node].node->get_output_port_count(), ERR_INVALID_PARAMETER);
+ ERR_FAIL_INDEX_V(p_from_port, g->nodes[p_from_node].node->get_expanded_output_port_count(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!g->nodes.has(p_to_node), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_to_port, g->nodes[p_to_node].node->get_input_port_count(), ERR_INVALID_PARAMETER);
@@ -790,7 +881,7 @@ bool VisualShader::is_text_shader() const {
String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port, Vector<DefaultTextureParam> &default_tex_params) const {
Ref<VisualShaderNode> node = get_node(p_type, p_node);
ERR_FAIL_COND_V(!node.is_valid(), String());
- ERR_FAIL_COND_V(p_port < 0 || p_port >= node->get_output_port_count(), String());
+ ERR_FAIL_COND_V(p_port < 0 || p_port >= node->get_expanded_output_port_count(), String());
ERR_FAIL_COND_V(node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_TRANSFORM, String());
StringBuilder global_code;
@@ -989,9 +1080,11 @@ static const char *type_string[VisualShader::TYPE_MAX] = {
"vertex",
"fragment",
"light",
- "emit",
+ "start",
"process",
- "end",
+ "collide",
+ "start_custom",
+ "process_custom",
"sky",
};
@@ -1207,6 +1300,12 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const {
const Ref<VisualShaderNode> vsnode = graph[type].nodes[node].node;
+ if (vsnode->is_disabled()) {
+ code += "// " + vsnode->get_caption() + ":" + itos(node) + "\n";
+ code += "\t// Node is disabled and code is not generated.\n";
+ return OK;
+ }
+
//check inputs recursively first
int input_count = vsnode->get_input_port_count();
for (int i = 0; i < input_count; i++) {
@@ -1261,7 +1360,8 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
return OK;
}
- code += "// " + vsnode->get_caption() + ":" + itos(node) + "\n";
+ String node_name = "// " + vsnode->get_caption() + ":" + itos(node) + "\n";
+ String node_code;
Vector<String> input_vars;
input_vars.resize(vsnode->get_input_port_count());
@@ -1275,6 +1375,11 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
if (input_connections.has(ck)) {
//connected to something, use that output
int from_node = input_connections[ck]->get().from_node;
+
+ if (graph[type].nodes[from_node].node->is_disabled()) {
+ continue;
+ }
+
int from_port = input_connections[ck]->get().from_port;
VisualShaderNode::PortType in_type = vsnode->get_input_port_type(i);
@@ -1327,21 +1432,21 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
if (defval.get_type() == Variant::FLOAT) {
float val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
- code += "\tfloat " + inputs[i] + " = " + vformat("%.5f", val) + ";\n";
+ node_code += "\tfloat " + inputs[i] + " = " + vformat("%.5f", val) + ";\n";
} else if (defval.get_type() == Variant::INT) {
int val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
- code += "\tint " + inputs[i] + " = " + itos(val) + ";\n";
+ node_code += "\tint " + inputs[i] + " = " + itos(val) + ";\n";
} else if (defval.get_type() == Variant::BOOL) {
bool val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
- code += "\tbool " + inputs[i] + " = " + (val ? "true" : "false") + ";\n";
+ node_code += "\tbool " + inputs[i] + " = " + (val ? "true" : "false") + ";\n";
} else if (defval.get_type() == Variant::VECTOR3) {
Vector3 val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
- code += "\tvec3 " + inputs[i] + " = " + vformat("vec3(%.5f, %.5f, %.5f);\n", val.x, val.y, val.z);
- } else if (defval.get_type() == Variant::TRANSFORM) {
- Transform val = defval;
+ node_code += "\tvec3 " + inputs[i] + " = " + vformat("vec3(%.5f, %.5f, %.5f);\n", val.x, val.y, val.z);
+ } else if (defval.get_type() == Variant::TRANSFORM3D) {
+ Transform3D val = defval;
val.basis.transpose();
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
Array values;
@@ -1354,7 +1459,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
values.push_back(val.origin.y);
values.push_back(val.origin.z);
bool err = false;
- code += "\tmat4 " + inputs[i] + " = " + String("mat4(vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 1.0));\n").sprintf(values, &err);
+ node_code += "\tmat4 " + inputs[i] + " = " + String("mat4(vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 1.0));\n").sprintf(values, &err);
} else {
//will go empty, node is expected to know what it is doing at this point and handle it
}
@@ -1362,13 +1467,30 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
}
int output_count = vsnode->get_output_port_count();
+ int initial_output_count = output_count;
+
+ Map<int, bool> expanded_output_ports;
+
+ for (int i = 0; i < initial_output_count; i++) {
+ bool expanded = false;
+
+ if (vsnode->is_output_port_expandable(i) && vsnode->_is_output_port_expanded(i)) {
+ expanded = true;
+
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ output_count += 3;
+ }
+ }
+ expanded_output_ports.insert(i, expanded);
+ }
+
Vector<String> output_vars;
- output_vars.resize(vsnode->get_output_port_count());
+ output_vars.resize(output_count);
String *outputs = output_vars.ptrw();
if (vsnode->is_simple_decl()) { // less code to generate for some simple_decl nodes
- for (int i = 0; i < output_count; i++) {
- String var_name = "n_out" + itos(node) + "p" + itos(i);
+ for (int i = 0, j = 0; i < initial_output_count; i++, j++) {
+ String var_name = "n_out" + itos(node) + "p" + itos(j);
switch (vsnode->get_output_port_type(i)) {
case VisualShaderNode::PORT_TYPE_SCALAR:
outputs[i] = "float " + var_name;
@@ -1388,34 +1510,88 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
default: {
}
}
+ if (expanded_output_ports[i]) {
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ j += 3;
+ }
+ }
}
} else {
- for (int i = 0; i < output_count; i++) {
- outputs[i] = "n_out" + itos(node) + "p" + itos(i);
+ for (int i = 0, j = 0; i < initial_output_count; i++, j++) {
+ outputs[i] = "n_out" + itos(node) + "p" + itos(j);
switch (vsnode->get_output_port_type(i)) {
case VisualShaderNode::PORT_TYPE_SCALAR:
- code += String() + "\tfloat " + outputs[i] + ";\n";
+ code += "\tfloat " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
- code += String() + "\tint " + outputs[i] + ";\n";
+ code += "\tint " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_VECTOR:
- code += String() + "\tvec3 " + outputs[i] + ";\n";
+ code += "\tvec3 " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
- code += String() + "\tbool " + outputs[i] + ";\n";
+ code += "\tbool " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_TRANSFORM:
- code += String() + "\tmat4 " + outputs[i] + ";\n";
+ code += "\tmat4 " + outputs[i] + ";\n";
break;
default: {
}
}
+ if (expanded_output_ports[i]) {
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ j += 3;
+ }
+ }
}
}
- code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview);
+ node_code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview);
+ if (node_code != String()) {
+ code += node_name;
+ code += node_code;
+ code += "\n";
+ }
+
+ for (int i = 0; i < output_count; i++) {
+ bool new_line_inserted = false;
+ if (expanded_output_ports[i]) {
+ if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
+ if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String r = "n_out" + itos(node) + "p" + itos(i + 1);
+ code += "\tfloat " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
+ outputs[i + 1] = r;
+ }
+
+ if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String g = "n_out" + itos(node) + "p" + itos(i + 2);
+ code += "\tfloat " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
+ outputs[i + 2] = g;
+ }
+
+ if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String b = "n_out" + itos(node) + "p" + itos(i + 3);
+ code += "\tfloat " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
+ outputs[i + 3] = b;
+ }
+
+ i += 3;
+ }
+ }
+ }
code += "\n"; //
processed.insert(node);
@@ -1426,7 +1602,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
bool VisualShader::has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const {
if (!ShaderTypes::get_singleton()->get_functions(p_mode).has(p_func_name)) {
if (p_mode == RenderingServer::ShaderMode::SHADER_PARTICLES) {
- if (p_func_name == "emit" || p_func_name == "process" || p_func_name == "end") {
+ if (p_func_name == "start_custom" || p_func_name == "process_custom" || p_func_name == "collide") {
return true;
}
}
@@ -1507,11 +1683,12 @@ void VisualShader::_update_shader() const {
global_code += "render_mode " + render_mode + ";\n\n";
}
- static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "emit", "process", "end", "sky" };
+ static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "start", "process", "collide", "start_custom", "process_custom", "sky" };
String global_expressions;
Set<String> used_uniform_names;
List<VisualShaderNodeUniform *> uniforms;
+ Map<int, List<int>> emitters;
for (int i = 0, index = 0; i < TYPE_MAX; i++) {
if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
@@ -1536,6 +1713,19 @@ void VisualShader::_update_shader() const {
if (uniform.is_valid()) {
uniforms.push_back(uniform.ptr());
}
+ Ref<VisualShaderNodeParticleEmit> emit_particle = Object::cast_to<VisualShaderNodeParticleEmit>(E->get().node.ptr());
+ if (emit_particle.is_valid()) {
+ if (!emitters.has(i)) {
+ emitters.insert(i, List<int>());
+ }
+
+ for (Map<int, Node>::Element *M = graph[i].nodes.front(); M; M = M->next()) {
+ if (M->get().node == emit_particle.ptr()) {
+ emitters[i].push_back(M->key());
+ break;
+ }
+ }
+ }
}
}
@@ -1584,6 +1774,13 @@ void VisualShader::_update_shader() const {
Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
ERR_FAIL_COND(err != OK);
+ if (emitters.has(i)) {
+ for (List<int>::Element *E = emitters[i].front(); E; E = E->next()) {
+ err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, E->get(), processed, false, classes);
+ ERR_FAIL_COND(err != OK);
+ }
+ }
+
if (shader_mode == Shader::MODE_PARTICLES) {
code_map.insert(i, func_code);
} else {
@@ -1592,19 +1789,130 @@ void VisualShader::_update_shader() const {
}
}
+ String global_compute_code;
+
if (shader_mode == Shader::MODE_PARTICLES) {
- code += "\nvoid compute() {\n";
- code += "\tif (RESTART) {\n";
- code += code_map[TYPE_EMIT];
- code += "\t} else {\n";
- code += code_map[TYPE_PROCESS];
+ bool has_start = !code_map[TYPE_START].is_empty();
+ bool has_start_custom = !code_map[TYPE_START_CUSTOM].is_empty();
+ bool has_process = !code_map[TYPE_PROCESS].is_empty();
+ bool has_process_custom = !code_map[TYPE_PROCESS_CUSTOM].is_empty();
+ bool has_collide = !code_map[TYPE_COLLIDE].is_empty();
+
+ code += "void start() {\n";
+ if (has_start || has_start_custom) {
+ code += "\tuint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
+ code += "\tvec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
+ code += "\tfloat __radians;\n";
+ code += "\tvec3 __vec3_buff1;\n";
+ code += "\tvec3 __vec3_buff2;\n";
+ code += "\tfloat __scalar_buff1;\n";
+ code += "\tfloat __scalar_buff2;\n";
+ code += "\tvec3 __ndiff = normalize(__diff);\n\n";
+ }
+ if (has_start) {
+ code += "\t{\n";
+ code += code_map[TYPE_START].replace("\n\t", "\n\t\t");
+ code += "\t}\n";
+ if (has_start_custom) {
+ code += "\t\n";
+ }
+ }
+ if (has_start_custom) {
+ code += "\t{\n";
+ code += code_map[TYPE_START_CUSTOM].replace("\n\t", "\n\t\t");
+ code += "\t}\n";
+ }
+ code += "}\n\n";
+ code += "void process() {\n";
+ if (has_process || has_process_custom || has_collide) {
+ code += "\tuint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
+ code += "\tvec3 __vec3_buff1;\n";
+ code += "\tvec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
+ code += "\tvec3 __ndiff = normalize(__diff);\n\n";
+ }
+ code += "\t{\n";
+ String tab = "\t";
+ if (has_collide) {
+ code += "\t\tif (COLLIDED) {\n\n";
+ code += code_map[TYPE_COLLIDE].replace("\n\t", "\n\t\t\t");
+ if (has_process) {
+ code += "\t\t} else {\n\n";
+ tab += "\t";
+ }
+ }
+ if (has_process) {
+ code += code_map[TYPE_PROCESS].replace("\n\t", "\n\t" + tab);
+ }
+ if (has_collide) {
+ code += "\t\t}\n";
+ }
code += "\t}\n";
- code += "}\n";
+
+ if (has_process_custom) {
+ code += "\t{\n\n";
+ code += code_map[TYPE_PROCESS_CUSTOM].replace("\n\t", "\n\t\t");
+ code += "\t}\n";
+ }
+
+ code += "}\n\n";
+
+ global_compute_code += "float __rand_from_seed(inout uint seed) {\n";
+ global_compute_code += "\tint k;\n";
+ global_compute_code += "\tint s = int(seed);\n";
+ global_compute_code += "\tif (s == 0)\n";
+ global_compute_code += "\ts = 305420679;\n";
+ global_compute_code += "\tk = s / 127773;\n";
+ global_compute_code += "\ts = 16807 * (s - k * 127773) - 2836 * k;\n";
+ global_compute_code += "\tif (s < 0)\n";
+ global_compute_code += "\t\ts += 2147483647;\n";
+ global_compute_code += "\tseed = uint(s);\n";
+ global_compute_code += "\treturn float(seed % uint(65536)) / 65535.0;\n";
+ global_compute_code += "}\n\n";
+
+ global_compute_code += "float __rand_from_seed_m1_p1(inout uint seed) {\n";
+ global_compute_code += "\treturn __rand_from_seed(seed) * 2.0 - 1.0;\n";
+ global_compute_code += "}\n\n";
+
+ global_compute_code += "float __randf_range(inout uint seed, float from, float to) {\n";
+ global_compute_code += "\treturn __rand_from_seed(seed) * (to - from) + from;\n";
+ global_compute_code += "}\n\n";
+
+ global_compute_code += "vec3 __randv_range(inout uint seed, vec3 from, vec3 to) {\n";
+ global_compute_code += "\treturn vec3(__randf_range(seed, from.x, to.x), __randf_range(seed, from.y, to.y), __randf_range(seed, from.z, to.z));\n";
+ global_compute_code += "}\n\n";
+
+ global_compute_code += "uint __hash(uint x) {\n";
+ global_compute_code += "\tx = ((x >> uint(16)) ^ x) * uint(73244475);\n";
+ global_compute_code += "\tx = ((x >> uint(16)) ^ x) * uint(73244475);\n";
+ global_compute_code += "\tx = (x >> uint(16)) ^ x;\n";
+ global_compute_code += "\treturn x;\n";
+ global_compute_code += "}\n\n";
+
+ global_compute_code += "mat3 __build_rotation_mat3(vec3 axis, float angle) {\n";
+ global_compute_code += "\taxis = normalize(axis);\n";
+ global_compute_code += "\tfloat s = sin(angle);\n";
+ global_compute_code += "\tfloat c = cos(angle);\n";
+ global_compute_code += "\tfloat oc = 1.0 - c;\n";
+ global_compute_code += "\treturn mat3(vec3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s), vec3(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s), vec3(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c));\n";
+ global_compute_code += "}\n\n";
+
+ global_compute_code += "mat4 __build_rotation_mat4(vec3 axis, float angle) {\n";
+ global_compute_code += "\taxis = normalize(axis);\n";
+ global_compute_code += "\tfloat s = sin(angle);\n";
+ global_compute_code += "\tfloat c = cos(angle);\n";
+ global_compute_code += "\tfloat oc = 1.0 - c;\n";
+ global_compute_code += "\treturn mat4(vec4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0), vec4(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0), vec4(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0), vec4(0, 0, 0, 1));\n";
+ global_compute_code += "}\n\n";
+
+ global_compute_code += "vec3 __get_random_unit_vec3(inout uint seed) {\n";
+ global_compute_code += "\treturn normalize(vec3(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n";
+ global_compute_code += "}\n\n";
}
//set code secretly
global_code += "\n\n";
String final_code = global_code;
+ final_code += global_compute_code;
final_code += global_code_per_node;
final_code += global_expressions;
String tcode = code;
@@ -1695,9 +2003,11 @@ void VisualShader::_bind_methods() {
BIND_ENUM_CONSTANT(TYPE_VERTEX);
BIND_ENUM_CONSTANT(TYPE_FRAGMENT);
BIND_ENUM_CONSTANT(TYPE_LIGHT);
- BIND_ENUM_CONSTANT(TYPE_EMIT);
+ BIND_ENUM_CONSTANT(TYPE_START);
BIND_ENUM_CONSTANT(TYPE_PROCESS);
- BIND_ENUM_CONSTANT(TYPE_END);
+ BIND_ENUM_CONSTANT(TYPE_COLLIDE);
+ BIND_ENUM_CONSTANT(TYPE_START_CUSTOM);
+ BIND_ENUM_CONSTANT(TYPE_PROCESS_CUSTOM);
BIND_ENUM_CONSTANT(TYPE_SKY);
BIND_ENUM_CONSTANT(TYPE_MAX);
@@ -1708,11 +2018,20 @@ void VisualShader::_bind_methods() {
VisualShader::VisualShader() {
dirty.set();
for (int i = 0; i < TYPE_MAX; i++) {
- Ref<VisualShaderNodeOutput> output;
- output.instance();
- output->shader_type = Type(i);
- output->shader_mode = shader_mode;
- graph[i].nodes[NODE_ID_OUTPUT].node = output;
+ if (i > (int)TYPE_LIGHT && i < (int)TYPE_SKY) {
+ Ref<VisualShaderNodeParticleOutput> output;
+ output.instance();
+ output->shader_type = Type(i);
+ output->shader_mode = shader_mode;
+ graph[i].nodes[NODE_ID_OUTPUT].node = output;
+ } else {
+ Ref<VisualShaderNodeOutput> output;
+ output.instance();
+ output->shader_type = Type(i);
+ output->shader_mode = shader_mode;
+ graph[i].nodes[NODE_ID_OUTPUT].node = output;
+ }
+
graph[i].nodes[NODE_ID_OUTPUT].position = Vector2(400, 150);
}
}
@@ -1841,27 +2160,45 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "specular_shininess", "SPECULAR_SHININESS.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "specular_shininess_alpha", "SPECULAR_SHININESS.a" },
- // Particles, Emit
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+ // Particles, Start
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR, "attractor_force", "ATTRACTOR_FORCE" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+
+ // Particles, Start (Custom)
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR, "attractor_force", "ATTRACTOR_FORCE" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Particles, Process
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "attractor_force", "ATTRACTOR_FORCE" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
@@ -1871,20 +2208,39 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
- // Particles, End
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+ // Particles, Process (Custom)
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR, "attractor_force", "ATTRACTOR_FORCE" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+
+ // Particles, Collide
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR, "attractor_force", "ATTRACTOR_FORCE" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "collision_depth", "COLLISION_DEPTH" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR, "collision_normal", "COLLISION_NORMAL" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Sky, Sky
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_cubemap_pass", "AT_CUBEMAP_PASS" },
@@ -1960,11 +2316,13 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
- // Particles, Vertex
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "vec3(0.0, 0.0, 1.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+
+ // Particles
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
{ Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr },
};
@@ -2412,6 +2770,8 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_view_matrix", "MODELVIEW_MATRIX" },
+
// Spatial, Fragment
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "albedo", "ALBEDO" },
@@ -2455,30 +2815,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
// Canvas Item, Light
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" },
- // Particles, Emit
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
- // Particles, Process
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
- // Particles, End
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
+
// Sky, Sky
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" },
@@ -2551,9 +2888,13 @@ String VisualShaderNodeOutput::get_output_port_name(int p_port) const {
}
bool VisualShaderNodeOutput::is_port_separator(int p_index) const {
+ if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_VERTEX) {
+ String name = get_input_port_name(p_index);
+ return bool(name == "Model View Matrix");
+ }
if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_FRAGMENT) {
String name = get_input_port_name(p_index);
- return (name == "Normal" || name == "Rim" || name == "Alpha Scissor Threshold");
+ return bool(name == "Normal" || name == "Rim" || name == "Alpha Scissor Threshold");
}
return false;
}
@@ -3148,11 +3489,11 @@ int VisualShaderNodeGroupBase::get_free_output_port_id() const {
return output_ports.size();
}
-void VisualShaderNodeGroupBase::set_control(Control *p_control, int p_index) {
+void VisualShaderNodeGroupBase::set_ctrl_pressed(Control *p_control, int p_index) {
controls[p_index] = p_control;
}
-Control *VisualShaderNodeGroupBase::get_control(int p_index) {
+Control *VisualShaderNodeGroupBase::is_ctrl_pressed(int p_index) {
ERR_FAIL_COND_V(!controls.has(p_index), nullptr);
return controls[p_index];
}
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 8af0fc9e44..53b165fe0f 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -51,9 +51,11 @@ public:
TYPE_VERTEX,
TYPE_FRAGMENT,
TYPE_LIGHT,
- TYPE_EMIT,
+ TYPE_START,
TYPE_PROCESS,
- TYPE_END,
+ TYPE_COLLIDE,
+ TYPE_START_CUSTOM,
+ TYPE_PROCESS_CUSTOM,
TYPE_SKY,
TYPE_MAX
};
@@ -199,9 +201,12 @@ class VisualShaderNode : public Resource {
Map<int, Variant> default_input_values;
Map<int, bool> connected_input_ports;
Map<int, int> connected_output_ports;
+ Map<int, bool> expanded_output_ports;
protected:
bool simple_decl = true;
+ bool disabled = false;
+
static void _bind_methods();
public:
@@ -227,6 +232,8 @@ public:
Variant get_input_port_default_value(int p_port) const; // if NIL (default if node does not set anything) is returned, it means no default value is wanted if disconnected, thus no input var must be supplied (empty string will be supplied)
Array get_default_input_values() const;
virtual void set_default_input_values(const Array &p_values);
+ virtual void remove_input_port_default_value(int p_port);
+ virtual void clear_default_input_values();
virtual int get_output_port_count() const = 0;
virtual PortType get_output_port_type(int p_port) const = 0;
@@ -245,17 +252,28 @@ public:
void set_input_port_connected(int p_port, bool p_connected);
virtual bool is_generate_input_var(int p_port) const;
+ virtual bool is_output_port_expandable(int p_port) const;
+ void _set_output_ports_expanded(const Array &p_data);
+ Array _get_output_ports_expanded() const;
+ void _set_output_port_expanded(int p_port, bool p_expanded);
+ bool _is_output_port_expanded(int p_port) const;
+ int get_expanded_output_port_count() const;
+
virtual bool is_code_generated() const;
virtual bool is_show_prop_names() const;
virtual bool is_use_prop_slots() const;
+ bool is_disabled() const;
+ void set_disabled(bool p_disabled = true);
+
virtual Vector<StringName> get_editable_properties() const;
virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const = 0; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ // If no output is connected, the output var passed will be empty. If no input is connected and input is NIL, the input var passed will be empty.
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const = 0;
virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const;
@@ -291,6 +309,8 @@ protected:
virtual void set_input_port_default_value(int p_port, const Variant &p_value) override;
virtual void set_default_input_values(const Array &p_values) override;
+ virtual void remove_input_port_default_value(int p_port) override;
+ virtual void clear_default_input_values() override;
protected:
void _set_input_port_default_value(int p_port, const Variant &p_value);
@@ -610,8 +630,8 @@ public:
int get_free_input_port_id() const;
int get_free_output_port_id() const;
- void set_control(Control *p_control, int p_index);
- Control *get_control(int p_index);
+ void set_ctrl_pressed(Control *p_control, int p_index);
+ Control *is_ctrl_pressed(int p_index);
void set_editable(bool p_enabled);
bool is_editable() const;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 7943b95177..d3b094de31 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -242,6 +242,13 @@ String VisualShaderNodeColorConstant::get_output_port_name(int p_port) const {
return p_port == 0 ? "" : "alpha"; //no output port means the editor will be used as port
}
+bool VisualShaderNodeColorConstant::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ return true;
+ }
+ return false;
+}
+
String VisualShaderNodeColorConstant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String code;
code += "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n";
@@ -334,10 +341,10 @@ void VisualShaderNodeVec3Constant::_bind_methods() {
VisualShaderNodeVec3Constant::VisualShaderNodeVec3Constant() {
}
-////////////// Transform
+////////////// Transform3D
String VisualShaderNodeTransformConstant::get_caption() const {
- return "Transform";
+ return "Transform3D";
}
int VisualShaderNodeTransformConstant::get_input_port_count() const {
@@ -365,7 +372,7 @@ String VisualShaderNodeTransformConstant::get_output_port_name(int p_port) const
}
String VisualShaderNodeTransformConstant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- Transform t = constant;
+ Transform3D t = constant;
t.basis.transpose();
String code = "\t" + p_output_vars[0] + " = mat4(";
@@ -376,12 +383,12 @@ String VisualShaderNodeTransformConstant::generate_code(Shader::Mode p_mode, Vis
return code;
}
-void VisualShaderNodeTransformConstant::set_constant(Transform p_value) {
+void VisualShaderNodeTransformConstant::set_constant(Transform3D p_value) {
constant = p_value;
emit_changed();
}
-Transform VisualShaderNodeTransformConstant::get_constant() const {
+Transform3D VisualShaderNodeTransformConstant::get_constant() const {
return constant;
}
@@ -395,7 +402,7 @@ void VisualShaderNodeTransformConstant::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeTransformConstant::set_constant);
ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeTransformConstant::get_constant);
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "constant"), "set_constant", "get_constant");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "constant"), "set_constant", "get_constant");
}
VisualShaderNodeTransformConstant::VisualShaderNodeTransformConstant() {
@@ -455,6 +462,13 @@ String VisualShaderNodeTexture::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
+bool VisualShaderNodeTexture::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ return true;
+ }
+ return false;
+}
+
String VisualShaderNodeTexture::get_input_port_default_hint(int p_port) const {
if (p_port == 0) {
return "default";
@@ -775,7 +789,7 @@ void VisualShaderNodeTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,Screen,Texture2D,NormalMap2D,Depth,SamplerPort"), "set_source", "get_source");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap"), "set_texture_type", "get_texture_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map"), "set_texture_type", "get_texture_type");
BIND_ENUM_CONSTANT(SOURCE_TEXTURE);
BIND_ENUM_CONSTANT(SOURCE_SCREEN);
@@ -846,7 +860,7 @@ String VisualShaderNodeCurveTexture::generate_code(Shader::Mode p_mode, VisualSh
}
String id = make_unique_id(p_type, p_id, "curve");
String code;
- code += "\t" + p_output_vars[0] + " = texture(" + id + ", vec2(" + p_input_vars[0] + ", 0.0)).r;\n";
+ code += "\t" + p_output_vars[0] + " = texture(" + id + ", vec2(" + p_input_vars[0] + ")).r;\n";
return code;
}
@@ -917,6 +931,13 @@ String VisualShaderNodeSample3D::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
+bool VisualShaderNodeSample3D::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ return true;
+ }
+ return false;
+}
+
String VisualShaderNodeSample3D::get_input_port_default_hint(int p_port) const {
if (p_port == 0) {
return "default";
@@ -1168,6 +1189,13 @@ String VisualShaderNodeCubemap::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
+bool VisualShaderNodeCubemap::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ return true;
+ }
+ return false;
+}
+
Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubemap::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
VisualShader::DefaultTextureParam dtp;
dtp.name = make_unique_id(p_type, p_id, "cube");
@@ -1308,7 +1336,7 @@ void VisualShaderNodeCubemap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,SamplerPort"), "set_source", "get_source");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "cube_map", PROPERTY_HINT_RESOURCE_TYPE, "Cubemap"), "set_cube_map", "get_cube_map");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap"), "set_texture_type", "get_texture_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map"), "set_texture_type", "get_texture_type");
BIND_ENUM_CONSTANT(SOURCE_TEXTURE);
BIND_ENUM_CONSTANT(SOURCE_PORT);
@@ -1409,7 +1437,7 @@ void VisualShaderNodeFloatOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeFloatOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeFloatOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Power,Max,Min,Atan2,Step"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Power,Max,Min,ATan2,Step"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_ADD);
BIND_ENUM_CONSTANT(OP_SUB);
@@ -1506,7 +1534,7 @@ void VisualShaderNodeIntOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeIntOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeIntOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Max,Min"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Max,Min"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_ADD);
BIND_ENUM_CONSTANT(OP_SUB);
@@ -1615,7 +1643,7 @@ void VisualShaderNodeVectorOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeVectorOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeVectorOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Power,Max,Min,Cross,Atan2,Reflect,Step"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Power,Max,Min,Cross,ATan2,Reflect,Step"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_ADD);
BIND_ENUM_CONSTANT(OP_SUB);
@@ -1785,7 +1813,7 @@ void VisualShaderNodeColorOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeColorOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeColorOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Screen,Difference,Darken,Lighten,Overlay,Dodge,Burn,SoftLight,HardLight"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Screen,Difference,Darken,Lighten,Overlay,Dodge,Burn,Soft Light,Hard Light"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_SCREEN);
BIND_ENUM_CONSTANT(OP_DIFFERENCE);
@@ -1873,8 +1901,8 @@ void VisualShaderNodeTransformMult::_bind_methods() {
}
VisualShaderNodeTransformMult::VisualShaderNodeTransformMult() {
- set_input_port_default_value(0, Transform());
- set_input_port_default_value(1, Transform());
+ set_input_port_default_value(0, Transform3D());
+ set_input_port_default_value(1, Transform3D());
}
////////////// TransformVec Mult
@@ -1947,7 +1975,7 @@ void VisualShaderNodeTransformVecMult::_bind_methods() {
}
VisualShaderNodeTransformVecMult::VisualShaderNodeTransformVecMult() {
- set_input_port_default_value(0, Transform());
+ set_input_port_default_value(0, Transform3D());
set_input_port_default_value(1, Vector3());
}
@@ -2468,7 +2496,144 @@ void VisualShaderNodeTransformFunc::_bind_methods() {
}
VisualShaderNodeTransformFunc::VisualShaderNodeTransformFunc() {
- set_input_port_default_value(0, Transform());
+ set_input_port_default_value(0, Transform3D());
+}
+
+////////////// UV Func
+
+String VisualShaderNodeUVFunc::get_caption() const {
+ return "UVFunc";
+}
+
+int VisualShaderNodeUVFunc::get_input_port_count() const {
+ return 3;
+}
+
+VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_input_port_type(int p_port) const {
+ switch (p_port) {
+ case 0:
+ [[fallthrough]]; // uv
+ case 1:
+ return PORT_TYPE_VECTOR; // scale
+ case 2:
+ return PORT_TYPE_VECTOR; // offset & pivot
+ default:
+ break;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeUVFunc::get_input_port_name(int p_port) const {
+ switch (p_port) {
+ case 0:
+ return "uv";
+ case 1:
+ return "scale";
+ case 2:
+ switch (func) {
+ case FUNC_PANNING:
+ return "offset";
+ case FUNC_SCALING:
+ return "pivot";
+ case FUNC_MAX:
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return "";
+}
+
+String VisualShaderNodeUVFunc::get_input_port_default_hint(int p_port) const {
+ if (p_port == 0) {
+ return "UV";
+ }
+ return "";
+}
+
+int VisualShaderNodeUVFunc::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeUVFunc::get_output_port_name(int p_port) const {
+ return "uv";
+}
+
+bool VisualShaderNodeUVFunc::is_show_prop_names() const {
+ return true;
+}
+
+String VisualShaderNodeUVFunc::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+
+ String uv;
+ if (p_input_vars[0].is_empty()) {
+ uv = "vec3(UV.xy, 0.0)";
+ } else {
+ uv = vformat("%s", p_input_vars[0]);
+ }
+ String scale = vformat("%s", p_input_vars[1]);
+ String offset_pivot = vformat("%s", p_input_vars[2]);
+
+ switch (func) {
+ case FUNC_PANNING: {
+ code += vformat("\t%s = fma(%s, %s, %s);\n", p_output_vars[0], offset_pivot, scale, uv);
+ } break;
+ case FUNC_SCALING: {
+ code += vformat("\t%s = fma((%s - %s), %s, %s);\n", p_output_vars[0], uv, offset_pivot, scale, offset_pivot);
+ } break;
+ case FUNC_MAX:
+ break;
+ }
+ return code;
+}
+
+void VisualShaderNodeUVFunc::set_function(VisualShaderNodeUVFunc::Function p_func) {
+ ERR_FAIL_INDEX(int(p_func), FUNC_MAX);
+ if (func == p_func) {
+ return;
+ }
+ func = p_func;
+
+ if (p_func == FUNC_PANNING) {
+ set_input_port_default_value(2, Vector3()); // offset
+ } else { // FUNC_SCALING
+ set_input_port_default_value(2, Vector3(0.5, 0.5, 0.0)); // pivot
+ }
+ emit_changed();
+}
+
+VisualShaderNodeUVFunc::Function VisualShaderNodeUVFunc::get_function() const {
+ return func;
+}
+
+Vector<StringName> VisualShaderNodeUVFunc::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("function");
+ return props;
+}
+
+void VisualShaderNodeUVFunc::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeUVFunc::set_function);
+ ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeUVFunc::get_function);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Panning,Scaling"), "set_function", "get_function");
+
+ BIND_ENUM_CONSTANT(FUNC_PANNING);
+ BIND_ENUM_CONSTANT(FUNC_SCALING);
+ BIND_ENUM_CONSTANT(FUNC_MAX);
+}
+
+VisualShaderNodeUVFunc::VisualShaderNodeUVFunc() {
+ set_input_port_default_value(1, Vector3(1.0, 1.0, 0.0)); // scale
+ set_input_port_default_value(2, Vector3()); // offset
}
////////////// Dot Product
@@ -2583,7 +2748,7 @@ String VisualShaderNodeDeterminant::generate_code(Shader::Mode p_mode, VisualSha
}
VisualShaderNodeDeterminant::VisualShaderNodeDeterminant() {
- set_input_port_default_value(0, Transform());
+ set_input_port_default_value(0, Transform3D());
}
////////////// Scalar Derivative Function
@@ -3594,7 +3759,7 @@ String VisualShaderNodeTransformDecompose::generate_code(Shader::Mode p_mode, Vi
}
VisualShaderNodeTransformDecompose::VisualShaderNodeTransformDecompose() {
- set_input_port_default_value(0, Transform());
+ set_input_port_default_value(0, Transform3D());
}
////////////// Float Uniform
@@ -3899,7 +4064,7 @@ void VisualShaderNodeIntUniform::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeIntUniform::set_default_value);
ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeIntUniform::get_default_value);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step"), "set_hint", "get_hint");
ADD_PROPERTY(PropertyInfo(Variant::INT, "min"), "set_min", "get_min");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max"), "set_max", "get_max");
ADD_PROPERTY(PropertyInfo(Variant::INT, "step"), "set_step", "get_step");
@@ -4280,12 +4445,12 @@ bool VisualShaderNodeTransformUniform::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeTransformUniform::set_default_value(const Transform &p_value) {
+void VisualShaderNodeTransformUniform::set_default_value(const Transform3D &p_value) {
default_value = p_value;
emit_changed();
}
-Transform VisualShaderNodeTransformUniform::get_default_value() const {
+Transform3D VisualShaderNodeTransformUniform::get_default_value() const {
return default_value;
}
@@ -4314,7 +4479,7 @@ void VisualShaderNodeTransformUniform::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeTransformUniform::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "default_value"), "set_default_value", "get_default_value");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "default_value"), "set_default_value", "get_default_value");
}
bool VisualShaderNodeTransformUniform::is_show_prop_names() const {
@@ -4487,7 +4652,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_color_default", "type"), &VisualShaderNodeTextureUniform::set_color_default);
ClassDB::bind_method(D_METHOD("get_color_default"), &VisualShaderNodeTextureUniform::get_color_default);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap,Aniso"), "set_texture_type", "get_texture_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map,Anisotropic"), "set_texture_type", "get_texture_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White Default,Black Default"), "set_color_default", "get_color_default");
BIND_ENUM_CONSTANT(TYPE_DATA);
@@ -4997,8 +5162,8 @@ void VisualShaderNodeSwitch::set_op_type(OpType p_op_type) {
set_input_port_default_value(2, false);
break;
case OP_TYPE_TRANSFORM:
- set_input_port_default_value(1, Transform());
- set_input_port_default_value(2, Transform());
+ set_input_port_default_value(1, Transform3D());
+ set_input_port_default_value(2, Transform3D());
break;
default:
break;
@@ -5377,8 +5542,8 @@ void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_type) {
simple_decl = true;
break;
case CTYPE_TRANSFORM:
- set_input_port_default_value(0, Transform());
- set_input_port_default_value(1, Transform());
+ set_input_port_default_value(0, Transform3D());
+ set_input_port_default_value(1, Transform3D());
simple_decl = true;
break;
}
@@ -5551,3 +5716,127 @@ VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() {
set_input_port_default_value(1, 0.0);
set_input_port_default_value(2, 0.0);
}
+
+////////////// Billboard
+
+String VisualShaderNodeBillboard::get_caption() const {
+ return "GetBillboardMatrix";
+}
+
+int VisualShaderNodeBillboard::get_input_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeBillboard::PortType VisualShaderNodeBillboard::get_input_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeBillboard::get_input_port_name(int p_port) const {
+ return "";
+}
+
+int VisualShaderNodeBillboard::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeBillboard::PortType VisualShaderNodeBillboard::get_output_port_type(int p_port) const {
+ return PORT_TYPE_TRANSFORM;
+}
+
+String VisualShaderNodeBillboard::get_output_port_name(int p_port) const {
+ return "model_view_matrix";
+}
+
+String VisualShaderNodeBillboard::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+
+ switch (billboard_type) {
+ case BILLBOARD_TYPE_ENABLED:
+ code += "\t{\n";
+ code += "\t\tmat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], CAMERA_MATRIX[1], CAMERA_MATRIX[2], WORLD_MATRIX[3]);\n";
+ if (keep_scale) {
+ code += "\t\t__mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ }
+ code += "\t\t" + p_output_vars[0] + " = __mvm;\n";
+ code += "\t}\n";
+ break;
+ case BILLBOARD_TYPE_FIXED_Y:
+ code += "\t{\n";
+ code += "\t\tmat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], WORLD_MATRIX[1], vec4(normalize(cross(CAMERA_MATRIX[0].xyz, WORLD_MATRIX[1].xyz)), 0.0), WORLD_MATRIX[3]);\n";
+ if (keep_scale) {
+ code += "\t\t__mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ } else {
+ code += "\t\t__mvm = __mvm * mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0 / length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ }
+ code += "\t\t" + p_output_vars[0] + " = __mvm;\n";
+ code += "\t}\n";
+ break;
+ case BILLBOARD_TYPE_PARTICLES:
+ code += "\t{\n";
+ code += "\t\tmat4 __wm = mat4(normalize(CAMERA_MATRIX[0]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[1]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[2]) * length(WORLD_MATRIX[2]), WORLD_MATRIX[3]);\n";
+ code += "\t\t__wm = __wm * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += "\t\t" + p_output_vars[0] + " = INV_CAMERA_MATRIX * __wm;\n";
+ code += "\t}\n";
+ break;
+ default:
+ code += "\t" + p_output_vars[0] + " = mat4(1.0);\n";
+ break;
+ }
+
+ return code;
+}
+
+bool VisualShaderNodeBillboard::is_show_prop_names() const {
+ return true;
+}
+
+void VisualShaderNodeBillboard::set_billboard_type(BillboardType p_billboard_type) {
+ ERR_FAIL_INDEX((int)p_billboard_type, BILLBOARD_TYPE_MAX);
+ billboard_type = p_billboard_type;
+ simple_decl = bool(billboard_type == BILLBOARD_TYPE_DISABLED);
+ set_disabled(simple_decl);
+ emit_changed();
+}
+
+VisualShaderNodeBillboard::BillboardType VisualShaderNodeBillboard::get_billboard_type() const {
+ return billboard_type;
+}
+
+void VisualShaderNodeBillboard::set_keep_scale_enabled(bool p_enabled) {
+ keep_scale = p_enabled;
+ emit_changed();
+}
+
+bool VisualShaderNodeBillboard::is_keep_scale_enabled() const {
+ return keep_scale;
+}
+
+Vector<StringName> VisualShaderNodeBillboard::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("billboard_type");
+ if (billboard_type == BILLBOARD_TYPE_ENABLED || billboard_type == BILLBOARD_TYPE_FIXED_Y) {
+ props.push_back("keep_scale");
+ }
+ return props;
+}
+
+void VisualShaderNodeBillboard::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_billboard_type", "billboard_type"), &VisualShaderNodeBillboard::set_billboard_type);
+ ClassDB::bind_method(D_METHOD("get_billboard_type"), &VisualShaderNodeBillboard::get_billboard_type);
+
+ ClassDB::bind_method(D_METHOD("set_keep_scale_enabled", "enabled"), &VisualShaderNodeBillboard::set_keep_scale_enabled);
+ ClassDB::bind_method(D_METHOD("is_keep_scale_enabled"), &VisualShaderNodeBillboard::is_keep_scale_enabled);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard_type", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particles"), "set_billboard_type", "get_billboard_type");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_scale"), "set_keep_scale_enabled", "is_keep_scale_enabled");
+
+ BIND_ENUM_CONSTANT(BILLBOARD_TYPE_DISABLED);
+ BIND_ENUM_CONSTANT(BILLBOARD_TYPE_ENABLED);
+ BIND_ENUM_CONSTANT(BILLBOARD_TYPE_FIXED_Y);
+ BIND_ENUM_CONSTANT(BILLBOARD_TYPE_PARTICLES);
+ BIND_ENUM_CONSTANT(BILLBOARD_TYPE_MAX);
+}
+
+VisualShaderNodeBillboard::VisualShaderNodeBillboard() {
+ simple_decl = false;
+}
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 594a494cf1..5b44e9f776 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -74,7 +74,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_constant(float p_value);
float get_constant() const;
@@ -104,7 +104,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_constant(int p_value);
int get_constant() const;
@@ -134,7 +134,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_constant(bool p_value);
bool get_constant() const;
@@ -163,8 +163,9 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_constant(Color p_value);
Color get_constant() const;
@@ -194,7 +195,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_constant(Vector3 p_value);
Vector3 get_constant() const;
@@ -208,7 +209,7 @@ public:
class VisualShaderNodeTransformConstant : public VisualShaderNodeConstant {
GDCLASS(VisualShaderNodeTransformConstant, VisualShaderNodeConstant);
- Transform constant;
+ Transform3D constant;
protected:
static void _bind_methods();
@@ -224,10 +225,10 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
- void set_constant(Transform p_value);
- Transform get_constant() const;
+ void set_constant(Transform3D p_value);
+ Transform3D get_constant() const;
virtual Vector<StringName> get_editable_properties() const override;
@@ -275,12 +276,13 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
virtual String get_input_port_default_hint(int p_port) const override;
virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_source(Source p_source);
Source get_source() const;
@@ -323,7 +325,7 @@ public:
virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_texture(Ref<CurveTexture> p_value);
Ref<CurveTexture> get_texture() const;
@@ -359,8 +361,9 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_source(Source p_source);
Source get_source() const;
@@ -452,10 +455,11 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_source(Source p_source);
Source get_source() const;
@@ -512,7 +516,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_operator(Operator p_op);
Operator get_operator() const;
@@ -554,7 +558,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_operator(Operator p_op);
Operator get_operator() const;
@@ -601,7 +605,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_operator(Operator p_op);
Operator get_operator() const;
@@ -647,7 +651,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_operator(Operator p_op);
Operator get_operator() const;
@@ -690,7 +694,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_operator(Operator p_op);
Operator get_operator() const;
@@ -733,7 +737,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_operator(Operator p_op);
Operator get_operator() const;
@@ -804,7 +808,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_function(Function p_func);
Function get_function() const;
@@ -846,7 +850,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_function(Function p_func);
Function get_function() const;
@@ -920,7 +924,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_function(Function p_func);
Function get_function() const;
@@ -961,7 +965,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_function(Function p_func);
Function get_function() const;
@@ -1002,7 +1006,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_function(Function p_func);
Function get_function() const;
@@ -1015,6 +1019,51 @@ public:
VARIANT_ENUM_CAST(VisualShaderNodeTransformFunc::Function)
///////////////////////////////////////
+/// UV FUNC
+///////////////////////////////////////
+
+class VisualShaderNodeUVFunc : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeUVFunc, VisualShaderNode);
+
+public:
+ enum Function {
+ FUNC_PANNING,
+ FUNC_SCALING,
+ FUNC_MAX,
+ };
+
+protected:
+ Function func = FUNC_PANNING;
+
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+ virtual String get_input_port_default_hint(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual bool is_show_prop_names() const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ void set_function(Function p_op);
+ Function get_function() const;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+
+ VisualShaderNodeUVFunc();
+};
+
+VARIANT_ENUM_CAST(VisualShaderNodeUVFunc::Function)
+
+///////////////////////////////////////
/// DOT
///////////////////////////////////////
@@ -1032,7 +1081,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeDotProduct();
};
@@ -1055,7 +1104,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorLen();
};
@@ -1078,7 +1127,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeDeterminant();
};
@@ -1118,7 +1167,7 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeClamp();
};
@@ -1155,7 +1204,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_function(Function p_func);
Function get_function() const;
@@ -1195,7 +1244,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_function(Function p_func);
Function get_function() const;
@@ -1225,7 +1274,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeFaceForward();
};
@@ -1248,7 +1297,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeOuterProduct();
};
@@ -1288,7 +1337,7 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeStep();
};
@@ -1330,7 +1379,7 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeSmoothStep();
};
@@ -1355,7 +1404,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorDistance();
};
@@ -1378,7 +1427,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorRefract();
};
@@ -1418,7 +1467,7 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeMix();
};
@@ -1443,7 +1492,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorCompose();
};
@@ -1464,7 +1513,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeTransformCompose();
};
@@ -1487,7 +1536,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorDecompose();
};
@@ -1508,7 +1557,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeTransformDecompose();
};
@@ -1550,7 +1599,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
virtual bool is_show_prop_names() const override;
virtual bool is_use_prop_slots() const override;
@@ -1616,7 +1665,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
virtual bool is_show_prop_names() const override;
virtual bool is_use_prop_slots() const override;
@@ -1673,7 +1722,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
virtual bool is_show_prop_names() const override;
virtual bool is_use_prop_slots() const override;
@@ -1716,7 +1765,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
virtual bool is_show_prop_names() const override;
@@ -1758,7 +1807,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
virtual bool is_show_prop_names() const override;
virtual bool is_use_prop_slots() const override;
@@ -1784,7 +1833,7 @@ class VisualShaderNodeTransformUniform : public VisualShaderNodeUniform {
private:
bool default_value_enabled = false;
- Transform default_value = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0);
+ Transform3D default_value = Transform3D(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0);
protected:
static void _bind_methods();
@@ -1801,7 +1850,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
virtual bool is_show_prop_names() const override;
virtual bool is_use_prop_slots() const override;
@@ -1809,8 +1858,8 @@ public:
void set_default_value_enabled(bool p_enabled);
bool is_default_value_enabled() const;
- void set_default_value(const Transform &p_value);
- Transform get_default_value() const;
+ void set_default_value(const Transform3D &p_value);
+ Transform3D get_default_value() const;
bool is_qualifier_supported(Qualifier p_qual) const override;
bool is_convertible_to_constant() const override;
@@ -1858,7 +1907,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
virtual bool is_code_generated() const override;
@@ -1895,7 +1944,7 @@ public:
virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeTextureUniformTriplanar();
};
@@ -1918,7 +1967,7 @@ public:
virtual String get_input_port_default_hint(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeTexture2DArrayUniform();
};
@@ -1941,7 +1990,7 @@ public:
virtual String get_input_port_default_hint(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeTexture3DUniform();
};
@@ -1964,7 +2013,7 @@ public:
virtual String get_input_port_default_hint(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeCubemapUniform();
};
@@ -2092,7 +2141,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_function(Function p_func);
Function get_function() const;
@@ -2153,7 +2202,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_comparison_type(ComparisonType p_type);
ComparisonType get_comparison_type() const;
@@ -2201,7 +2250,7 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
void set_op_type(OpType p_type);
OpType get_op_type() const;
@@ -2213,4 +2262,51 @@ public:
VARIANT_ENUM_CAST(VisualShaderNodeMultiplyAdd::OpType)
+class VisualShaderNodeBillboard : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeBillboard, VisualShaderNode);
+
+public:
+ enum BillboardType {
+ BILLBOARD_TYPE_DISABLED,
+ BILLBOARD_TYPE_ENABLED,
+ BILLBOARD_TYPE_FIXED_Y,
+ BILLBOARD_TYPE_PARTICLES,
+ BILLBOARD_TYPE_MAX,
+ };
+
+protected:
+ BillboardType billboard_type = BILLBOARD_TYPE_ENABLED;
+ bool keep_scale = false;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ virtual bool is_show_prop_names() const override;
+
+ void set_billboard_type(BillboardType p_billboard_type);
+ BillboardType get_billboard_type() const;
+
+ void set_keep_scale_enabled(bool p_enabled);
+ bool is_keep_scale_enabled() const;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+
+ VisualShaderNodeBillboard();
+};
+
+VARIANT_ENUM_CAST(VisualShaderNodeBillboard::BillboardType)
+
#endif // VISUAL_SHADER_NODES_H
diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp
new file mode 100644
index 0000000000..29d583a82a
--- /dev/null
+++ b/scene/resources/visual_shader_particle_nodes.cpp
@@ -0,0 +1,1025 @@
+/*************************************************************************/
+/* visual_shader_particle_nodes.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "visual_shader_particle_nodes.h"
+
+// VisualShaderNodeParticleEmitter
+
+int VisualShaderNodeParticleEmitter::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeParticleEmitter::PortType VisualShaderNodeParticleEmitter::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeParticleEmitter::get_output_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "position";
+ }
+ return String();
+}
+
+VisualShaderNodeParticleEmitter::VisualShaderNodeParticleEmitter() {
+}
+
+// VisualShaderNodeParticleSphereEmitter
+
+String VisualShaderNodeParticleSphereEmitter::get_caption() const {
+ return "SphereEmitter";
+}
+
+int VisualShaderNodeParticleSphereEmitter::get_input_port_count() const {
+ return 2;
+}
+
+VisualShaderNodeParticleSphereEmitter::PortType VisualShaderNodeParticleSphereEmitter::get_input_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleSphereEmitter::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "radius";
+ } else if (p_port == 1) {
+ return "inner_radius";
+ }
+ return String();
+}
+
+String VisualShaderNodeParticleSphereEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code;
+ code += "vec3 __get_random_point_in_sphere(inout uint seed, float radius, float inner_radius) {\n";
+ code += "\treturn __get_random_unit_vec3(seed) * __randf_range(seed, inner_radius, radius);\n";
+ code += "}\n\n";
+ return code;
+}
+
+String VisualShaderNodeParticleSphereEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ code += "\t" + p_output_vars[0] + " = __get_random_point_in_sphere(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
+ return code;
+}
+
+VisualShaderNodeParticleSphereEmitter::VisualShaderNodeParticleSphereEmitter() {
+ set_input_port_default_value(0, 10.0);
+ set_input_port_default_value(1, 0.0);
+}
+
+// VisualShaderNodeParticleBoxEmitter
+
+String VisualShaderNodeParticleBoxEmitter::get_caption() const {
+ return "BoxEmitter";
+}
+
+int VisualShaderNodeParticleBoxEmitter::get_input_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleBoxEmitter::get_input_port_type(int p_port) const {
+ if (p_port == 0) {
+ return PORT_TYPE_VECTOR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleBoxEmitter::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "extents";
+ }
+ return String();
+}
+
+String VisualShaderNodeParticleBoxEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code;
+ code += "vec3 __get_random_point_in_box(inout uint seed, vec3 extents) {\n";
+ code += "\tvec3 half_extents = extents / 2.0;\n";
+ code += "\treturn vec3(__randf_range(seed, -half_extents.x, half_extents.x), __randf_range(seed, -half_extents.y, half_extents.y), __randf_range(seed, -half_extents.z, half_extents.z));\n";
+ code += "}\n\n";
+ return code;
+}
+
+String VisualShaderNodeParticleBoxEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ code += "\t" + p_output_vars[0] + " = __get_random_point_in_box(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ");\n";
+ return code;
+}
+
+VisualShaderNodeParticleBoxEmitter::VisualShaderNodeParticleBoxEmitter() {
+ set_input_port_default_value(0, Vector3(1.0, 1.0, 1.0));
+}
+
+// VisualShaderNodeParticleRingEmitter
+
+String VisualShaderNodeParticleRingEmitter::get_caption() const {
+ return "RingEmitter";
+}
+
+int VisualShaderNodeParticleRingEmitter::get_input_port_count() const {
+ return 3;
+}
+
+VisualShaderNodeParticleRingEmitter::PortType VisualShaderNodeParticleRingEmitter::get_input_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleRingEmitter::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "radius";
+ } else if (p_port == 1) {
+ return "inner_radius";
+ } else if (p_port == 2) {
+ return "height";
+ }
+ return String();
+}
+
+String VisualShaderNodeParticleRingEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code;
+ code += "vec3 __get_random_point_on_ring(inout uint seed, float radius, float inner_radius, float height) {\n";
+ code += "\tfloat angle = __rand_from_seed(seed) * PI * 2.0;\n";
+ code += "\tvec2 ring = vec2(sin(angle), cos(angle)) * __randf_range(seed, inner_radius, radius);\n";
+ code += "\treturn vec3(ring.x, __randf_range(seed, min(0.0, height), max(0.0, height)), ring.y);\n";
+ code += "}\n\n";
+ return code;
+}
+
+String VisualShaderNodeParticleRingEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ code = "\t" + p_output_vars[0] + " = __get_random_point_on_ring(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ");\n";
+ return code;
+}
+
+VisualShaderNodeParticleRingEmitter::VisualShaderNodeParticleRingEmitter() {
+ set_input_port_default_value(0, 10.0);
+ set_input_port_default_value(1, 0.0);
+ set_input_port_default_value(2, 0.0);
+}
+
+// VisualShaderNodeParticleMultiplyByAxisAngle
+
+void VisualShaderNodeParticleMultiplyByAxisAngle::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_degrees_mode", "enabled"), &VisualShaderNodeParticleMultiplyByAxisAngle::set_degrees_mode);
+ ClassDB::bind_method(D_METHOD("is_degrees_mode"), &VisualShaderNodeParticleMultiplyByAxisAngle::is_degrees_mode);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "degrees_mode"), "set_degrees_mode", "is_degrees_mode");
+}
+
+String VisualShaderNodeParticleMultiplyByAxisAngle::get_caption() const {
+ return "MultiplyByAxisAngle";
+}
+
+int VisualShaderNodeParticleMultiplyByAxisAngle::get_input_port_count() const {
+ return 3;
+}
+
+VisualShaderNodeParticleMultiplyByAxisAngle::PortType VisualShaderNodeParticleMultiplyByAxisAngle::get_input_port_type(int p_port) const {
+ if (p_port == 0 || p_port == 1) { // position, rotation_axis
+ return PORT_TYPE_VECTOR;
+ }
+ return PORT_TYPE_SCALAR; // angle (degrees/radians)
+}
+
+String VisualShaderNodeParticleMultiplyByAxisAngle::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "position";
+ }
+ if (p_port == 1) {
+ return "axis";
+ }
+ if (p_port == 2) {
+ if (degrees_mode) {
+ return "angle (degrees)";
+ } else {
+ return "angle (radians)";
+ }
+ }
+ return String();
+}
+
+bool VisualShaderNodeParticleMultiplyByAxisAngle::is_show_prop_names() const {
+ return true;
+}
+
+int VisualShaderNodeParticleMultiplyByAxisAngle::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeParticleMultiplyByAxisAngle::PortType VisualShaderNodeParticleMultiplyByAxisAngle::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeParticleMultiplyByAxisAngle::get_output_port_name(int p_port) const {
+ return "position";
+}
+
+String VisualShaderNodeParticleMultiplyByAxisAngle::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ if (degrees_mode) {
+ code += "\t" + p_output_vars[0] + " = __build_rotation_mat3(" + (p_input_vars[1].is_empty() ? ("vec3" + (String)get_input_port_default_value(1)) : p_input_vars[1]) + ", radians(" + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ")) * " + (p_input_vars[0].is_empty() ? "vec3(0.0)" : p_input_vars[0]) + ";\n";
+ } else {
+ code += "\t" + p_output_vars[0] + " = __build_rotation_mat3(" + (p_input_vars[1].is_empty() ? ("vec3" + (String)get_input_port_default_value(1)) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ") * " + (p_input_vars[0].is_empty() ? "vec3(0.0)" : p_input_vars[0]) + ";\n";
+ }
+ return code;
+}
+
+void VisualShaderNodeParticleMultiplyByAxisAngle::set_degrees_mode(bool p_enabled) {
+ degrees_mode = p_enabled;
+ emit_changed();
+}
+
+bool VisualShaderNodeParticleMultiplyByAxisAngle::is_degrees_mode() const {
+ return degrees_mode;
+}
+
+Vector<StringName> VisualShaderNodeParticleMultiplyByAxisAngle::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("degrees_mode");
+ props.push_back("axis_amount");
+ return props;
+}
+
+VisualShaderNodeParticleMultiplyByAxisAngle::VisualShaderNodeParticleMultiplyByAxisAngle() {
+ set_input_port_default_value(1, Vector3(1, 0, 0));
+ set_input_port_default_value(2, 0.0);
+}
+
+// VisualShaderNodeParticleConeVelocity
+
+String VisualShaderNodeParticleConeVelocity::get_caption() const {
+ return "ConeVelocity";
+}
+
+int VisualShaderNodeParticleConeVelocity::get_input_port_count() const {
+ return 2;
+}
+
+VisualShaderNodeParticleConeVelocity::PortType VisualShaderNodeParticleConeVelocity::get_input_port_type(int p_port) const {
+ if (p_port == 0) {
+ return PORT_TYPE_VECTOR;
+ } else if (p_port == 1) {
+ return PORT_TYPE_SCALAR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleConeVelocity::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "direction";
+ } else if (p_port == 1) {
+ return "spread(degrees)";
+ }
+ return String();
+}
+
+int VisualShaderNodeParticleConeVelocity::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeParticleConeVelocity::PortType VisualShaderNodeParticleConeVelocity::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeParticleConeVelocity::get_output_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "velocity";
+ }
+ return String();
+}
+
+String VisualShaderNodeParticleConeVelocity::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ code += "\t__radians = radians(" + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
+ code += "\t__scalar_buff1 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
+ code += "\t__scalar_buff2 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
+ code += "\t__vec3_buff1 = " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + ";\n";
+ code += "\t__scalar_buff1 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.x, __vec3_buff1.z) : sign(__vec3_buff1.x) * (PI / 2.0);\n";
+ code += "\t__scalar_buff2 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.z)) : (__vec3_buff1.x != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.x)) : sign(__vec3_buff1.y) * (PI / 2.0));\n";
+ code += "\t__vec3_buff1 = vec3(sin(__scalar_buff1), 0.0, cos(__scalar_buff1));\n";
+ code += "\t__vec3_buff2 = vec3(0.0, sin(__scalar_buff2), cos(__scalar_buff2));\n";
+ code += "\t__vec3_buff2.z = __vec3_buff2.z / max(0.0001, sqrt(abs(__vec3_buff2.z)));\n";
+ code += "\t" + p_output_vars[0] + " = normalize(vec3(__vec3_buff1.x * __vec3_buff2.z, __vec3_buff2.y, __vec3_buff1.z * __vec3_buff2.z));\n";
+ return code;
+}
+
+VisualShaderNodeParticleConeVelocity::VisualShaderNodeParticleConeVelocity() {
+ set_input_port_default_value(0, Vector3(1, 0, 0));
+ set_input_port_default_value(1, 45.0);
+}
+
+// VisualShaderNodeParticleRandomness
+
+void VisualShaderNodeParticleRandomness::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeParticleRandomness::set_op_type);
+ ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeParticleRandomness::get_op_type);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector"), "set_op_type", "get_op_type");
+
+ BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR);
+ BIND_ENUM_CONSTANT(OP_TYPE_MAX);
+}
+
+Vector<StringName> VisualShaderNodeParticleRandomness::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("op_type");
+ return props;
+}
+
+String VisualShaderNodeParticleRandomness::get_caption() const {
+ return "ParticleRandomness";
+}
+
+int VisualShaderNodeParticleRandomness::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeParticleRandomness::PortType VisualShaderNodeParticleRandomness::get_output_port_type(int p_port) const {
+ if (op_type == OP_TYPE_VECTOR) {
+ return PORT_TYPE_VECTOR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleRandomness::get_output_port_name(int p_port) const {
+ return "random";
+}
+
+int VisualShaderNodeParticleRandomness::get_input_port_count() const {
+ return 2;
+}
+
+VisualShaderNodeParticleRandomness::PortType VisualShaderNodeParticleRandomness::get_input_port_type(int p_port) const {
+ if (op_type == OP_TYPE_VECTOR) {
+ return PORT_TYPE_VECTOR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleRandomness::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "min";
+ } else if (p_port == 1) {
+ return "max";
+ }
+ return String();
+}
+
+String VisualShaderNodeParticleRandomness::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ if (op_type == OP_TYPE_SCALAR) {
+ code += vformat("\t%s = __randf_range(__seed, %s, %s);\n", p_output_vars[0], p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0], p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]);
+ } else if (op_type == OP_TYPE_VECTOR) {
+ code += vformat("\t%s = __randv_range(__seed, %s, %s);\n", p_output_vars[0], p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0], p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]);
+ }
+ return code;
+}
+
+void VisualShaderNodeParticleRandomness::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX((int)p_op_type, OP_TYPE_MAX);
+ if (p_op_type != op_type) {
+ if (p_op_type == OP_TYPE_SCALAR) {
+ set_input_port_default_value(0, 0.0);
+ set_input_port_default_value(1, 1.0);
+ } else {
+ set_input_port_default_value(0, Vector3(-1.0, -1.0, -1.0));
+ set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0));
+ }
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
+VisualShaderNodeParticleRandomness::OpType VisualShaderNodeParticleRandomness::get_op_type() const {
+ return op_type;
+}
+
+VisualShaderNodeParticleRandomness::VisualShaderNodeParticleRandomness() {
+ set_input_port_default_value(0, 0.0);
+ set_input_port_default_value(1, 1.0);
+}
+
+// VisualShaderNodeParticleAccelerator
+
+void VisualShaderNodeParticleAccelerator::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_mode", "mode"), &VisualShaderNodeParticleAccelerator::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"), &VisualShaderNodeParticleAccelerator::get_mode);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Linear,Radial,Tangential"), "set_mode", "get_mode");
+
+ BIND_ENUM_CONSTANT(MODE_LINEAR);
+ BIND_ENUM_CONSTANT(MODE_RADIAL)
+ BIND_ENUM_CONSTANT(MODE_TANGENTIAL);
+ BIND_ENUM_CONSTANT(MODE_MAX);
+}
+
+Vector<StringName> VisualShaderNodeParticleAccelerator::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("mode");
+ return props;
+}
+
+String VisualShaderNodeParticleAccelerator::get_caption() const {
+ return "ParticleAccelerator";
+}
+
+int VisualShaderNodeParticleAccelerator::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeParticleAccelerator::PortType VisualShaderNodeParticleAccelerator::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeParticleAccelerator::get_output_port_name(int p_port) const {
+ return String();
+}
+
+int VisualShaderNodeParticleAccelerator::get_input_port_count() const {
+ return 3;
+}
+
+VisualShaderNodeParticleAccelerator::PortType VisualShaderNodeParticleAccelerator::get_input_port_type(int p_port) const {
+ if (p_port == 0) {
+ return PORT_TYPE_VECTOR;
+ } else if (p_port == 1) {
+ return PORT_TYPE_SCALAR;
+ } else if (p_port == 2) {
+ return PORT_TYPE_VECTOR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleAccelerator::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "amount";
+ } else if (p_port == 1) {
+ return "randomness";
+ } else if (p_port == 2) {
+ return "axis";
+ }
+ return String();
+}
+
+String VisualShaderNodeParticleAccelerator::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ switch (mode) {
+ case MODE_LINEAR:
+ code += "\t" + p_output_vars[0] + " = length(VELOCITY) > 0.0 ? " + "normalize(VELOCITY) * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
+ break;
+ case MODE_RADIAL:
+ code += "\t" + p_output_vars[0] + " = length(__diff) > 0.0 ? __ndiff * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
+ break;
+ case MODE_TANGENTIAL:
+ code += "\t__vec3_buff1 = cross(__ndiff, normalize(" + (p_input_vars[2].is_empty() ? "vec3" + (String)get_input_port_default_value(2) : p_input_vars[2]) + "));\n";
+ code += "\t" + p_output_vars[0] + " = length(__vec3_buff1) > 0.0 ? normalize(__vec3_buff1) * (" + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ")) : vec3(0.0);\n";
+ break;
+ case MODE_MAX:
+ break;
+ default:
+ break;
+ }
+
+ return code;
+}
+
+void VisualShaderNodeParticleAccelerator::set_mode(Mode p_mode) {
+ mode = p_mode;
+ emit_changed();
+}
+
+VisualShaderNodeParticleAccelerator::Mode VisualShaderNodeParticleAccelerator::get_mode() const {
+ return mode;
+}
+
+VisualShaderNodeParticleAccelerator::VisualShaderNodeParticleAccelerator() {
+ set_input_port_default_value(0, Vector3(1, 1, 1));
+ set_input_port_default_value(1, 0.0);
+ set_input_port_default_value(2, Vector3(0, -9.8, 0));
+}
+
+// VisualShaderNodeParticleOutput
+
+String VisualShaderNodeParticleOutput::get_caption() const {
+ if (shader_type == VisualShader::TYPE_START) {
+ return "StartOutput";
+ } else if (shader_type == VisualShader::TYPE_PROCESS) {
+ return "ProcessOutput";
+ } else if (shader_type == VisualShader::TYPE_COLLIDE) {
+ return "CollideOutput";
+ } else if (shader_type == VisualShader::TYPE_START_CUSTOM) {
+ return "CustomStartOutput";
+ } else if (shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ return "CustomProcessOutput";
+ }
+ return String();
+}
+
+int VisualShaderNodeParticleOutput::get_input_port_count() const {
+ if (shader_type == VisualShader::TYPE_START) {
+ return 8;
+ } else if (shader_type == VisualShader::TYPE_COLLIDE) {
+ return 5;
+ } else if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ return 6;
+ } else { // TYPE_PROCESS
+ return 7;
+ }
+ return 0;
+}
+
+VisualShaderNodeParticleOutput::PortType VisualShaderNodeParticleOutput::get_input_port_type(int p_port) const {
+ switch (p_port) {
+ case 0:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ return PORT_TYPE_VECTOR; // custom.rgb
+ }
+ return PORT_TYPE_BOOLEAN; // active
+ case 1:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ break; // custom.a (scalar)
+ }
+ return PORT_TYPE_VECTOR; // velocity
+ case 2:
+ return PORT_TYPE_VECTOR; // color & velocity
+ case 3:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ return PORT_TYPE_VECTOR; // color
+ }
+ break; // alpha (scalar)
+ case 4:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ break; // alpha
+ }
+ if (shader_type == VisualShader::TYPE_PROCESS) {
+ break; // scale
+ }
+ if (shader_type == VisualShader::TYPE_COLLIDE) {
+ return PORT_TYPE_TRANSFORM; // transform
+ }
+ return PORT_TYPE_VECTOR; // position
+ case 5:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ return PORT_TYPE_TRANSFORM; // transform
+ }
+ if (shader_type == VisualShader::TYPE_PROCESS) {
+ return PORT_TYPE_VECTOR; // rotation_axis
+ }
+ break; // scale (scalar)
+ case 6:
+ if (shader_type == VisualShader::TYPE_START) {
+ return PORT_TYPE_VECTOR; // rotation_axis
+ }
+ break;
+ case 7:
+ break; // angle (scalar)
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleOutput::get_input_port_name(int p_port) const {
+ String port_name;
+ switch (p_port) {
+ case 0:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ port_name = "custom";
+ break;
+ }
+ port_name = "active";
+ break;
+ case 1:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ port_name = "custom_alpha";
+ break;
+ }
+ port_name = "velocity";
+ break;
+ case 2:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ port_name = "velocity";
+ break;
+ }
+ port_name = "color";
+ break;
+ case 3:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ port_name = "color";
+ break;
+ }
+ port_name = "alpha";
+ break;
+ case 4:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ port_name = "alpha";
+ break;
+ }
+ if (shader_type == VisualShader::TYPE_PROCESS) {
+ port_name = "scale";
+ break;
+ }
+ if (shader_type == VisualShader::TYPE_COLLIDE) {
+ port_name = "transform";
+ break;
+ }
+ port_name = "position";
+ break;
+ case 5:
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ port_name = "transform";
+ break;
+ }
+ if (shader_type == VisualShader::TYPE_PROCESS) {
+ port_name = "rotation_axis";
+ break;
+ }
+ port_name = "scale";
+ break;
+ case 6:
+ if (shader_type == VisualShader::TYPE_PROCESS) {
+ port_name = "angle_in_radians";
+ break;
+ }
+ port_name = "rotation_axis";
+ break;
+ case 7:
+ port_name = "angle_in_radians";
+ break;
+ default:
+ break;
+ }
+ if (!port_name.is_empty()) {
+ return port_name.capitalize();
+ }
+ return String();
+}
+
+bool VisualShaderNodeParticleOutput::is_port_separator(int p_index) const {
+ if (shader_type == VisualShader::TYPE_START || shader_type == VisualShader::TYPE_PROCESS) {
+ String name = get_input_port_name(p_index);
+ return bool(name == "Scale");
+ }
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ String name = get_input_port_name(p_index);
+ return bool(name == "Velocity");
+ }
+ return false;
+}
+
+String VisualShaderNodeParticleOutput::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ String tab = "\t";
+
+ if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
+ if (!p_input_vars[0].is_empty()) { // custom.rgb
+ code += tab + "CUSTOM.rgb = " + p_input_vars[0] + ";\n";
+ }
+ if (!p_input_vars[1].is_empty()) { // custom.a
+ code += tab + "CUSTOM.a = " + p_input_vars[1] + ";\n";
+ }
+ if (!p_input_vars[2].is_empty()) { // velocity
+ code += tab + "VELOCITY = " + p_input_vars[2] + ";\n";
+ }
+ if (!p_input_vars[3].is_empty()) { // color.rgb
+ code += tab + "COLOR.rgb = " + p_input_vars[3] + ";\n";
+ }
+ if (!p_input_vars[4].is_empty()) { // color.a
+ code += tab + "COLOR.a = " + p_input_vars[4] + ";\n";
+ }
+ if (!p_input_vars[5].is_empty()) { // transform
+ code += tab + "TRANSFORM = " + p_input_vars[5] + ";\n";
+ }
+ } else {
+ if (!p_input_vars[0].is_empty()) { // active (begin)
+ code += tab + "ACTIVE = " + p_input_vars[0] + ";\n";
+ code += tab + "if(ACTIVE) {\n";
+ tab += "\t";
+ }
+ if (!p_input_vars[1].is_empty()) { // velocity
+ code += tab + "VELOCITY = " + p_input_vars[1] + ";\n";
+ }
+ if (!p_input_vars[2].is_empty()) { // color
+ code += tab + "COLOR.rgb = " + p_input_vars[2] + ";\n";
+ }
+ if (!p_input_vars[3].is_empty()) { // alpha
+ code += tab + "COLOR.a = " + p_input_vars[3] + ";\n";
+ }
+
+ // position
+ if (shader_type == VisualShader::TYPE_START) {
+ code += tab + "if (RESTART_POSITION) {\n";
+ if (!p_input_vars[4].is_empty()) {
+ code += tab + "\tTRANSFORM = mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(" + p_input_vars[4] + ", 1.0));\n";
+ } else {
+ code += tab + "\tTRANSFORM = mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ }
+ code += tab + "\tif (RESTART_VELOCITY) {\n";
+ code += tab + "\t\tVELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n";
+ code += tab + "\t}\n";
+ code += tab + "\tTRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n";
+ code += tab + "}\n";
+ } else if (shader_type == VisualShader::TYPE_COLLIDE) { // position
+ if (!p_input_vars[4].is_empty()) {
+ code += tab + "TRANSFORM = " + p_input_vars[4] + ";\n";
+ }
+ }
+
+ if (shader_type == VisualShader::TYPE_START || shader_type == VisualShader::TYPE_PROCESS) {
+ int scale = 5;
+ int rotation_axis = 6;
+ int rotation = 7;
+ if (shader_type == VisualShader::TYPE_PROCESS) {
+ scale = 4;
+ rotation_axis = 5;
+ rotation = 6;
+ }
+ String op;
+ if (shader_type == VisualShader::TYPE_START) {
+ op = "*=";
+ } else {
+ op = "=";
+ }
+
+ if (!p_input_vars[rotation].is_empty()) { // rotation_axis & angle_in_radians
+ String axis;
+ if (p_input_vars[rotation_axis].is_empty()) {
+ axis = "vec3(0, 1, 0)";
+ } else {
+ axis = p_input_vars[rotation_axis];
+ }
+ code += tab + "TRANSFORM " + op + " __build_rotation_mat4(" + axis + ", " + p_input_vars[rotation] + ");\n";
+ }
+ if (!p_input_vars[scale].is_empty()) { // scale
+ code += tab + "TRANSFORM " + op + " mat4(vec4(" + p_input_vars[scale] + ", 0, 0, 0), vec4(0, " + p_input_vars[scale] + ", 0, 0), vec4(0, 0, " + p_input_vars[scale] + ", 0), vec4(0, 0, 0, 1));\n";
+ }
+ }
+ if (!p_input_vars[0].is_empty()) { // active (end)
+ code += "\t}\n";
+ }
+ }
+ return code;
+}
+
+VisualShaderNodeParticleOutput::VisualShaderNodeParticleOutput() {
+}
+
+// EmitParticle
+
+Vector<StringName> VisualShaderNodeParticleEmit::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("flags");
+ return props;
+}
+
+void VisualShaderNodeParticleEmit::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_flags", "flags"), &VisualShaderNodeParticleEmit::set_flags);
+ ClassDB::bind_method(D_METHOD("get_flags"), &VisualShaderNodeParticleEmit::get_flags);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Position,RotScale,Velocity,Color,Custom"), "set_flags", "get_flags");
+
+ BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_ROT_SCALE);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR);
+ BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM);
+}
+
+String VisualShaderNodeParticleEmit::get_caption() const {
+ return "EmitParticle";
+}
+
+int VisualShaderNodeParticleEmit::get_input_port_count() const {
+ return 7;
+}
+
+VisualShaderNodeParticleEmit::PortType VisualShaderNodeParticleEmit::get_input_port_type(int p_port) const {
+ switch (p_port) {
+ case 0:
+ return PORT_TYPE_BOOLEAN;
+ case 1:
+ return PORT_TYPE_TRANSFORM;
+ case 2:
+ return PORT_TYPE_VECTOR;
+ case 3:
+ return PORT_TYPE_VECTOR;
+ case 4:
+ return PORT_TYPE_SCALAR;
+ case 5:
+ return PORT_TYPE_VECTOR;
+ case 6:
+ return PORT_TYPE_SCALAR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleEmit::get_input_port_name(int p_port) const {
+ switch (p_port) {
+ case 0:
+ return "condition";
+ case 1:
+ return "transform";
+ case 2:
+ return "velocity";
+ case 3:
+ return "color";
+ case 4:
+ return "alpha";
+ case 5:
+ return "custom";
+ case 6:
+ return "custom_alpha";
+ }
+ return String();
+}
+
+int VisualShaderNodeParticleEmit::get_output_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeParticleEmit::PortType VisualShaderNodeParticleEmit::get_output_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeParticleEmit::get_output_port_name(int p_port) const {
+ return String();
+}
+
+void VisualShaderNodeParticleEmit::add_flag(EmitFlags p_flag) {
+ flags |= p_flag;
+ emit_changed();
+}
+
+bool VisualShaderNodeParticleEmit::has_flag(EmitFlags p_flag) const {
+ return flags & p_flag;
+}
+
+void VisualShaderNodeParticleEmit::set_flags(EmitFlags p_flags) {
+ flags = (int)p_flags;
+ emit_changed();
+}
+
+VisualShaderNodeParticleEmit::EmitFlags VisualShaderNodeParticleEmit::get_flags() const {
+ return EmitFlags(flags);
+}
+
+bool VisualShaderNodeParticleEmit::is_show_prop_names() const {
+ return true;
+}
+
+bool VisualShaderNodeParticleEmit::is_generate_input_var(int p_port) const {
+ if (p_port == 0) {
+ if (!is_input_port_connected(0)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+String VisualShaderNodeParticleEmit::get_input_port_default_hint(int p_port) const {
+ switch (p_port) {
+ case 1:
+ return "default";
+ case 2:
+ return "default";
+ case 3:
+ return "default";
+ case 4:
+ return "default";
+ case 5:
+ return "default";
+ case 6:
+ return "default";
+ }
+ return String();
+}
+
+String VisualShaderNodeParticleEmit::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ String tab;
+ bool default_condition = false;
+
+ if (!is_input_port_connected(0)) {
+ default_condition = true;
+ if (get_input_port_default_value(0)) {
+ tab = "\t";
+ } else {
+ return code;
+ }
+ } else {
+ tab = "\t\t";
+ }
+
+ String transform;
+ if (p_input_vars[1].is_empty()) {
+ transform = "TRANSFORM";
+ } else {
+ transform = p_input_vars[1];
+ }
+
+ String velocity;
+ if (p_input_vars[2].is_empty()) {
+ velocity = "VELOCITY";
+ } else {
+ velocity = p_input_vars[2];
+ }
+
+ String color;
+ if (p_input_vars[3].is_empty()) {
+ color = "COLOR.rgb";
+ } else {
+ color = p_input_vars[3];
+ }
+
+ String alpha;
+ if (p_input_vars[4].is_empty()) {
+ alpha = "COLOR.a";
+ } else {
+ alpha = p_input_vars[4];
+ }
+
+ String custom;
+ if (p_input_vars[5].is_empty()) {
+ custom = "CUSTOM.rgb";
+ } else {
+ custom = p_input_vars[5];
+ }
+
+ String custom_alpha;
+ if (p_input_vars[6].is_empty()) {
+ custom_alpha = "CUSTOM.a";
+ } else {
+ custom_alpha = p_input_vars[6];
+ }
+
+ List<String> flags_arr;
+
+ if (has_flag(EmitFlags::EMIT_FLAG_POSITION)) {
+ flags_arr.push_back("FLAG_EMIT_POSITION");
+ }
+ if (has_flag(EmitFlags::EMIT_FLAG_ROT_SCALE)) {
+ flags_arr.push_back("FLAG_EMIT_ROT_SCALE");
+ }
+ if (has_flag(EmitFlags::EMIT_FLAG_VELOCITY)) {
+ flags_arr.push_back("FLAG_EMIT_VELOCITY");
+ }
+ if (has_flag(EmitFlags::EMIT_FLAG_COLOR)) {
+ flags_arr.push_back("FLAG_EMIT_COLOR");
+ }
+ if (has_flag(EmitFlags::EMIT_FLAG_CUSTOM)) {
+ flags_arr.push_back("FLAG_EMIT_CUSTOM");
+ }
+
+ String flags;
+
+ for (int i = 0; i < flags_arr.size(); i++) {
+ if (i > 0) {
+ flags += "|";
+ }
+ flags += flags_arr[i];
+ }
+
+ if (flags.is_empty()) {
+ flags = "uint(0)";
+ }
+
+ if (!default_condition) {
+ code += "\tif (" + p_input_vars[0] + ") {\n";
+ }
+
+ code += tab + "emit_subparticle(" + transform + ", " + velocity + ", vec4(" + color + ", " + alpha + "), vec4(" + custom + ", " + custom_alpha + "), " + flags + ");\n";
+
+ if (!default_condition) {
+ code += "\t}\n";
+ }
+
+ return code;
+}
+
+VisualShaderNodeParticleEmit::VisualShaderNodeParticleEmit() {
+ set_input_port_default_value(0, true);
+}
diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h
new file mode 100644
index 0000000000..ecd187a885
--- /dev/null
+++ b/scene/resources/visual_shader_particle_nodes.h
@@ -0,0 +1,285 @@
+/*************************************************************************/
+/* visual_shader_particle_nodes.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef VISUAL_SHADER_PARTICLE_NODES_H
+#define VISUAL_SHADER_PARTICLE_NODES_H
+
+#include "scene/resources/visual_shader.h"
+
+// Emit nodes
+
+class VisualShaderNodeParticleEmitter : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeParticleEmitter, VisualShaderNode);
+
+public:
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ VisualShaderNodeParticleEmitter();
+};
+
+class VisualShaderNodeParticleSphereEmitter : public VisualShaderNodeParticleEmitter {
+ GDCLASS(VisualShaderNodeParticleSphereEmitter, VisualShaderNodeParticleEmitter);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeParticleSphereEmitter();
+};
+
+class VisualShaderNodeParticleBoxEmitter : public VisualShaderNodeParticleEmitter {
+ GDCLASS(VisualShaderNodeParticleBoxEmitter, VisualShaderNodeParticleEmitter);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeParticleBoxEmitter();
+};
+
+class VisualShaderNodeParticleRingEmitter : public VisualShaderNodeParticleEmitter {
+ GDCLASS(VisualShaderNodeParticleRingEmitter, VisualShaderNodeParticleEmitter);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeParticleRingEmitter();
+};
+
+class VisualShaderNodeParticleMultiplyByAxisAngle : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeParticleMultiplyByAxisAngle, VisualShaderNode);
+ bool degrees_mode = true;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+ virtual bool is_show_prop_names() const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ void set_degrees_mode(bool p_enabled);
+ bool is_degrees_mode() const;
+ Vector<StringName> get_editable_properties() const override;
+
+ VisualShaderNodeParticleMultiplyByAxisAngle();
+};
+
+class VisualShaderNodeParticleConeVelocity : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeParticleConeVelocity, VisualShaderNode);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeParticleConeVelocity();
+};
+
+class VisualShaderNodeParticleRandomness : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeParticleRandomness, VisualShaderNode);
+
+public:
+ enum OpType {
+ OP_TYPE_SCALAR,
+ OP_TYPE_VECTOR,
+ OP_TYPE_MAX,
+ };
+
+private:
+ OpType op_type = OP_TYPE_SCALAR;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Vector<StringName> get_editable_properties() const override;
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ void set_op_type(OpType p_type);
+ OpType get_op_type() const;
+
+ VisualShaderNodeParticleRandomness();
+};
+
+VARIANT_ENUM_CAST(VisualShaderNodeParticleRandomness::OpType)
+
+// Process nodes
+
+class VisualShaderNodeParticleAccelerator : public VisualShaderNodeOutput {
+ GDCLASS(VisualShaderNodeParticleAccelerator, VisualShaderNodeOutput);
+
+public:
+ enum Mode {
+ MODE_LINEAR,
+ MODE_RADIAL,
+ MODE_TANGENTIAL,
+ MODE_MAX,
+ };
+
+private:
+ Mode mode = MODE_LINEAR;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Vector<StringName> get_editable_properties() const override;
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ void set_mode(Mode p_mode);
+ Mode get_mode() const;
+
+ VisualShaderNodeParticleAccelerator();
+};
+
+VARIANT_ENUM_CAST(VisualShaderNodeParticleAccelerator::Mode)
+
+// Common nodes
+
+class VisualShaderNodeParticleOutput : public VisualShaderNodeOutput {
+ GDCLASS(VisualShaderNodeParticleOutput, VisualShaderNodeOutput);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+ virtual bool is_port_separator(int p_index) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeParticleOutput();
+};
+
+class VisualShaderNodeParticleEmit : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeParticleEmit, VisualShaderNode);
+
+public:
+ enum EmitFlags {
+ EMIT_FLAG_POSITION = 1,
+ EMIT_FLAG_ROT_SCALE = 2,
+ EMIT_FLAG_VELOCITY = 4,
+ EMIT_FLAG_COLOR = 8,
+ EMIT_FLAG_CUSTOM = 16,
+ };
+
+protected:
+ int flags = EMIT_FLAG_POSITION | EMIT_FLAG_ROT_SCALE | EMIT_FLAG_VELOCITY | EMIT_FLAG_COLOR | EMIT_FLAG_CUSTOM;
+ static void _bind_methods();
+
+public:
+ Vector<StringName> get_editable_properties() const override;
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ void add_flag(EmitFlags p_flag);
+ bool has_flag(EmitFlags p_flag) const;
+
+ void set_flags(EmitFlags p_flags);
+ EmitFlags get_flags() const;
+
+ virtual bool is_show_prop_names() const override;
+ virtual bool is_generate_input_var(int p_port) const override;
+ virtual String get_input_port_default_hint(int p_port) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeParticleEmit();
+};
+
+VARIANT_ENUM_CAST(VisualShaderNodeParticleEmit::EmitFlags)
+
+#endif
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index ccdc5bebd0..0a0742753f 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -357,7 +357,7 @@ World2D::World2D() {
// Create and configure space2D to be more friendly with pixels than meters
space = PhysicsServer2D::get_singleton()->space_create();
PhysicsServer2D::get_singleton()->space_set_active(space, true);
- PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98));
+ PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 980.0));
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1)));
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/2d/default_linear_damp", 0.1));
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 7575ccd5c3..8acab79c9e 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -155,13 +155,13 @@ SceneStringNames::SceneStringNames() {
area_entered = StaticCString::create("area_entered");
area_exited = StaticCString::create("area_exited");
- has_point = StaticCString::create("has_point");
+ _has_point = StaticCString::create("_has_point");
line_separation = StaticCString::create("line_separation");
- get_drag_data = StaticCString::create("get_drag_data");
- drop_data = StaticCString::create("drop_data");
- can_drop_data = StaticCString::create("can_drop_data");
+ _get_drag_data = StaticCString::create("_get_drag_data");
+ _drop_data = StaticCString::create("_drop_data");
+ _can_drop_data = StaticCString::create("_can_drop_data");
_im_update = StaticCString::create("_im_update"); // Sprite3D
@@ -175,6 +175,7 @@ SceneStringNames::SceneStringNames() {
_toggled = StaticCString::create("_toggled");
frame_changed = StaticCString::create("frame_changed");
+ texture_changed = StaticCString::create("texture_changed");
playback_speed = StaticCString::create("playback/speed");
playback_active = StaticCString::create("playback/active");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index a5b489eddc..0c528a45f7 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -138,10 +138,10 @@ public:
StringName grouped;
StringName ungrouped;
- StringName has_point;
- StringName get_drag_data;
- StringName can_drop_data;
- StringName drop_data;
+ StringName _has_point;
+ StringName _get_drag_data;
+ StringName _can_drop_data;
+ StringName _drop_data;
StringName screen_entered;
StringName screen_exited;
@@ -184,6 +184,7 @@ public:
StringName _mouse_exit;
StringName frame_changed;
+ StringName texture_changed;
StringName playback_speed;
StringName playback_active;
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 4556db9b93..5d14f03199 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -34,8 +34,8 @@
#include "core/io/resource.h"
#include "core/math/audio_frame.h"
-class AudioEffectInstance : public Reference {
- GDCLASS(AudioEffectInstance, Reference);
+class AudioEffectInstance : public RefCounted {
+ GDCLASS(AudioEffectInstance, RefCounted);
public:
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) = 0;
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index 93566783be..0d426f99b2 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -36,8 +36,8 @@
#include "servers/audio/audio_filter_sw.h"
#include "servers/audio_server.h"
-class AudioStreamPlayback : public Reference {
- GDCLASS(AudioStreamPlayback, Reference);
+class AudioStreamPlayback : public RefCounted {
+ GDCLASS(AudioStreamPlayback, RefCounted);
public:
virtual void start(float p_from_pos = 0.0) = 0;
diff --git a/servers/audio/effects/audio_effect_capture.h b/servers/audio/effects/audio_effect_capture.h
index 81d4ed6b0f..82686d5b4c 100644
--- a/servers/audio/effects/audio_effect_capture.h
+++ b/servers/audio/effects/audio_effect_capture.h
@@ -33,7 +33,7 @@
#include "core/config/engine.h"
#include "core/math/audio_frame.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/templates/vector.h"
#include "servers/audio/audio_effect.h"
#include "servers/audio_server.h"
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index 06d51776a3..5c076ca3fe 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -159,7 +159,7 @@ void AudioEffectDistortion::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_post_gain", "post_gain"), &AudioEffectDistortion::set_post_gain);
ClassDB::bind_method(D_METHOD("get_post_gain"), &AudioEffectDistortion::get_post_gain);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,WaveShape"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,Wave Shape"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pre_gain", PROPERTY_HINT_RANGE, "-60,60,0.01"), "set_pre_gain", "get_pre_gain");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_keep_hf_hz", "get_keep_hf_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive");
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index b97ec43946..8f56e227e0 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -31,8 +31,8 @@
#ifndef AUDIOEFFECTRECORD_H
#define AUDIOEFFECTRECORD_H
+#include "core/io/file_access.h"
#include "core/io/marshalls.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/os/thread.h"
#include "editor/import/resource_importer_wav.h"
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp
index 7df2f99f67..1d97de5205 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb.cpp
@@ -290,7 +290,7 @@ void Reverb::update_parameters() {
c.feedback = (room_offset + room_scale);
}
- float auxdmp = params.damp / 2.0 + 0.5; //only half the range (0.5 .. 1.0 is enough)
+ float auxdmp = params.damp / 2.0 + 0.5; //only half the range (0.5 .. 1.0 is enough)
auxdmp *= auxdmp;
c.damp = expf(-Math_TAU * auxdmp * 10000 / params.mix_rate); // 0 .. 10khz
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 08c482553b..acfdfa783a 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -32,8 +32,8 @@
#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
+#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "scene/resources/audio_stream_sample.h"
#include "servers/audio/audio_driver_dummy.h"
@@ -1164,6 +1164,9 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
Bus::Effect bfx;
bfx.effect = fx;
bfx.enabled = p_bus_layout->buses[i].effects[j].enabled;
+#if DEBUG_ENABLED
+ bfx.prof_time = 0;
+#endif
bus->effects.push_back(bfx);
}
}
diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h
index eb4ef155bc..fac7ae1b2d 100644
--- a/servers/camera/camera_feed.h
+++ b/servers/camera/camera_feed.h
@@ -43,8 +43,8 @@
camera feeds that can be used as the background for our environment.
**/
-class CameraFeed : public Reference {
- GDCLASS(CameraFeed, Reference);
+class CameraFeed : public RefCounted {
+ GDCLASS(CameraFeed, RefCounted);
public:
enum FeedDataType {
diff --git a/servers/camera_server.h b/servers/camera_server.h
index 97aa8f74ba..7390129df9 100644
--- a/servers/camera_server.h
+++ b/servers/camera_server.h
@@ -32,7 +32,7 @@
#define CAMERA_SERVER_H
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/thread_safe.h"
#include "core/templates/rid.h"
#include "core/variant/variant.h"
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 7bd1075006..ded4b849ef 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -32,14 +32,18 @@
#include "core/input/input.h"
#include "scene/resources/texture.h"
+#include "servers/display_server_headless.h"
DisplayServer *DisplayServer::singleton = nullptr;
DisplayServer::SwitchVSyncCallbackInThread DisplayServer::switch_vsync_function = nullptr;
bool DisplayServer::hidpi_allowed = false;
-DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[DisplayServer::MAX_SERVERS];
-int DisplayServer::server_create_count = 0;
+DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[DisplayServer::MAX_SERVERS] = {
+ { "headless", &DisplayServerHeadless::create_func, &DisplayServerHeadless::get_rendering_drivers_func }
+};
+
+int DisplayServer::server_create_count = 1;
void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) {
WARN_PRINT("Global menus not supported by this display server.");
@@ -505,6 +509,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED);
BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED);
+ BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN);
BIND_CONSTANT(SCREEN_OF_MAIN_WINDOW);
BIND_CONSTANT(MAIN_WINDOW_ID);
@@ -560,9 +565,11 @@ void DisplayServer::_bind_methods() {
void DisplayServer::register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers) {
ERR_FAIL_COND(server_create_count == MAX_SERVERS);
- server_create_functions[server_create_count].name = p_name;
- server_create_functions[server_create_count].create_function = p_function;
- server_create_functions[server_create_count].get_rendering_drivers_function = p_get_drivers;
+ // Headless display server is always last
+ server_create_functions[server_create_count] = server_create_functions[server_create_count - 1];
+ server_create_functions[server_create_count - 1].name = p_name;
+ server_create_functions[server_create_count - 1].create_function = p_function;
+ server_create_functions[server_create_count - 1].get_rendering_drivers_function = p_get_drivers;
server_create_count++;
}
diff --git a/servers/display_server.h b/servers/display_server.h
index f05aa1f59a..b8201f6fd5 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -142,7 +142,8 @@ public:
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
MOUSE_MODE_CAPTURED,
- MOUSE_MODE_CONFINED
+ MOUSE_MODE_CONFINED,
+ MOUSE_MODE_CONFINED_HIDDEN,
};
virtual void mouse_set_mode(MouseMode p_mode);
@@ -175,6 +176,9 @@ public:
return scale;
}
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+
+ // Keep the ScreenOrientation enum values in sync with the `display/window/handheld/orientation`
+ // project setting hint.
enum ScreenOrientation {
SCREEN_LANDSCAPE,
SCREEN_PORTRAIT,
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
new file mode 100644
index 0000000000..8b386c8d9c
--- /dev/null
+++ b/servers/display_server_headless.h
@@ -0,0 +1,127 @@
+/*************************************************************************/
+/* display_server_headless.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef DISPLAY_SERVER_HEADLESS_H
+#define DISPLAY_SERVER_HEADLESS_H
+
+#include "servers/display_server.h"
+
+#include "servers/rendering/rasterizer_dummy.h"
+
+class DisplayServerHeadless : public DisplayServer {
+private:
+ friend class DisplayServer;
+
+ static Vector<String> get_rendering_drivers_func() {
+ Vector<String> drivers;
+ drivers.push_back("dummy");
+ return drivers;
+ }
+
+ static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ r_error = OK;
+ RasterizerDummy::make_current();
+ return memnew(DisplayServerHeadless());
+ }
+
+public:
+ bool has_feature(Feature p_feature) const override { return false; }
+ String get_name() const override { return "headless"; }
+
+ void alert(const String &p_alert, const String &p_title = "ALERT!") override {}
+
+ int get_screen_count() const override { return 0; }
+ Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Point2i(); }
+ Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Size2i(); }
+ Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Rect2i(); }
+ int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return 96; /* 0 might cause issues */ }
+ float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return 1; }
+ float screen_get_max_scale() const override { return 1; }
+
+ Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); }
+
+ WindowID get_window_at_screen_position(const Point2i &p_position) const override { return -1; }
+
+ void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override {}
+ ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override { return ObjectID(); }
+
+ void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override {}
+
+ void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override {}
+ void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override {}
+ void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override {}
+ void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override {}
+
+ void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override {}
+
+ void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID) override {}
+
+ int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override { return -1; }
+ void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override {}
+
+ Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override { return Point2i(); }
+ void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override {}
+
+ void window_set_transient(WindowID p_window, WindowID p_parent) override {}
+
+ void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {}
+ Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
+
+ void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {}
+ Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); };
+
+ void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {}
+ Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
+ Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
+
+ void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override {}
+ WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override { return WINDOW_MODE_MINIMIZED; }
+
+ bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override { return false; }
+
+ void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override {}
+ virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override { return false; }
+
+ void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override {}
+ void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override {}
+
+ bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override { return false; }
+
+ bool can_any_window_draw() const override { return false; }
+
+ void process_events() override {}
+
+ void set_icon(const Ref<Image> &p_icon) override {}
+
+ DisplayServerHeadless() {}
+ ~DisplayServerHeadless() {}
+};
+
+#endif // DISPLAY_SERVER_HEADLESS_H
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 9e32bc209b..ef2635c188 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "servers/navigation_server_2d.h"
-#include "core/math/transform.h"
#include "core/math/transform_2d.h"
+#include "core/math/transform_3d.h"
#include "servers/navigation_server_3d.h"
/**
@@ -129,12 +129,12 @@ static Vector<Vector2> vector_v3_to_v2(const Vector<Vector3> &d) {
return nd;
}
-static Transform trf2_to_trf3(const Transform2D &d) {
+static Transform3D trf2_to_trf3(const Transform2D &d) {
Vector3 o(v2_to_v3(d.get_origin()));
Basis b;
b.rotate(Vector3(0, -1, 0), d.get_rotation());
b.scale(v2_to_v3(d.get_scale()));
- return Transform(b, o);
+ return Transform3D(b, o);
}
static Object *obj_to_obj(Object *d) {
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 420f9c9c18..3aef693ac8 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -106,7 +106,7 @@ public:
virtual uint32_t region_get_layers(RID p_region) const = 0;
/// Set the global transformation of this region.
- virtual void region_set_transform(RID p_region, Transform p_transform) const = 0;
+ virtual void region_set_transform(RID p_region, Transform3D p_transform) const = 0;
/// Set the navigation mesh of this region.
virtual void region_set_navmesh(RID p_region, Ref<NavigationMesh> p_nav_mesh) const = 0;
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index f78a487e27..6f244deb1e 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -43,7 +43,7 @@ void Body2DSW::update_inertias() {
//update shapes and motions
switch (mode) {
- case PhysicsServer2D::BODY_MODE_RIGID: {
+ case PhysicsServer2D::BODY_MODE_DYNAMIC: {
if (user_inertia) {
_inv_inertia = inertia > 0 ? (1.0 / inertia) : 0;
break;
@@ -87,7 +87,7 @@ void Body2DSW::update_inertias() {
_inv_inertia = 0;
_inv_mass = 0;
} break;
- case PhysicsServer2D::BODY_MODE_CHARACTER: {
+ case PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED: {
_inv_inertia = 0;
_inv_mass = 1.0 / mass;
@@ -204,14 +204,14 @@ void Body2DSW::set_mode(PhysicsServer2D::BodyMode p_mode) {
first_time_kinematic = true;
}
} break;
- case PhysicsServer2D::BODY_MODE_RIGID: {
+ case PhysicsServer2D::BODY_MODE_DYNAMIC: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = inertia > 0 ? (1.0 / inertia) : 0;
_set_static(false);
set_active(true);
} break;
- case PhysicsServer2D::BODY_MODE_CHARACTER: {
+ case PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = 0;
_set_static(false);
@@ -219,7 +219,7 @@ void Body2DSW::set_mode(PhysicsServer2D::BodyMode p_mode) {
angular_velocity = 0;
} break;
}
- if (p_mode == PhysicsServer2D::BODY_MODE_RIGID && _inv_inertia == 0) {
+ if (p_mode == PhysicsServer2D::BODY_MODE_DYNAMIC && _inv_inertia == 0) {
_update_inertia();
}
/*
@@ -267,25 +267,16 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY: {
- /*
- if (mode==PhysicsServer2D::BODY_MODE_STATIC)
- break;
- */
linear_velocity = p_variant;
wakeup();
} break;
case PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY: {
- /*
- if (mode!=PhysicsServer2D::BODY_MODE_RIGID)
- break;
- */
angular_velocity = p_variant;
wakeup();
} break;
case PhysicsServer2D::BODY_STATE_SLEEPING: {
- //?
if (mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {
break;
}
@@ -304,7 +295,7 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer2D::BODY_STATE_CAN_SLEEP: {
can_sleep = p_variant;
- if (mode == PhysicsServer2D::BODY_MODE_RIGID && !active && !can_sleep) {
+ if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
set_active(true);
}
@@ -551,7 +542,7 @@ void Body2DSW::wakeup_neighbours() {
continue;
}
Body2DSW *b = n[i];
- if (b->mode != PhysicsServer2D::BODY_MODE_RIGID) {
+ if (b->mode != PhysicsServer2D::BODY_MODE_DYNAMIC) {
continue;
}
@@ -588,9 +579,7 @@ void Body2DSW::call_queries() {
bool Body2DSW::sleep_test(real_t p_step) {
if (mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {
- return true; //
- } else if (mode == PhysicsServer2D::BODY_MODE_CHARACTER) {
- return !active; // characters and kinematic bodies don't sleep unless asked to sleep
+ return true;
} else if (!can_sleep) {
return false;
}
@@ -623,7 +612,7 @@ Body2DSW::Body2DSW() :
active_list(this),
inertia_update_list(this),
direct_state_query_list(this) {
- mode = PhysicsServer2D::BODY_MODE_RIGID;
+ mode = PhysicsServer2D::BODY_MODE_DYNAMIC;
active = true;
angular_velocity = 0;
biased_angular_velocity = 0;
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index eaec582f9b..5a0a628fbc 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -322,7 +322,7 @@ bool GrooveJoint2DSW::setup(real_t p_step) {
Vector2 delta = (B->get_transform().get_origin() + rB) - (A->get_transform().get_origin() + rA);
real_t _b = get_bias();
- gbias = (delta * -(_b == 0 ? space->get_constraint_bias() : _b) * (1.0 / p_step)).clamped(get_max_bias());
+ gbias = (delta * -(_b == 0 ? space->get_constraint_bias() : _b) * (1.0 / p_step)).limit_length(get_max_bias());
correct = true;
return true;
@@ -348,7 +348,7 @@ void GrooveJoint2DSW::solve(real_t p_step) {
Vector2 jOld = jn_acc;
j += jOld;
- jn_acc = (((clamp * j.cross(xf_normal)) > 0) ? j : j.project(xf_normal)).clamped(jn_max);
+ jn_acc = (((clamp * j.cross(xf_normal)) > 0) ? j : j.project(xf_normal)).limit_length(jn_max);
j = jn_acc - jOld;
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
index 425546e5ca..1c2dca0259 100644
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ b/servers/physics_2d/physics_server_2d_sw.cpp
@@ -1237,6 +1237,10 @@ void PhysicsServer2DSW::set_active(bool p_active) {
active = p_active;
};
+void PhysicsServer2DSW::set_collision_iterations(int p_iterations) {
+ iterations = p_iterations;
+};
+
void PhysicsServer2DSW::init() {
doing_sync = false;
last_step = 0.001;
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h
index efa0784245..5002bf5fc8 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/physics_server_2d_sw.h
@@ -247,8 +247,8 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable) override;
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
- virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
+ virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
+ virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.08) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override;
@@ -288,6 +288,8 @@ public:
virtual void end_sync() override;
virtual void finish() override;
+ virtual void set_collision_iterations(int p_iterations) override;
+
virtual bool is_flushing_queries() const override { return flushing_queries; }
int get_process_info(ProcessInfo p_info) override;
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.cpp b/servers/physics_2d/physics_server_2d_wrap_mt.cpp
index 790c87cc44..930b19c2cb 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.cpp
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.cpp
@@ -56,7 +56,7 @@ void PhysicsServer2DWrapMT::thread_loop() {
step_thread_up.set();
while (!exit.is_set()) {
// flush commands one by one, until exit is requested
- command_queue.wait_and_flush_one();
+ command_queue.wait_and_flush();
}
command_queue.flush_all(); // flush all
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h
index 88ac742e40..c776641699 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.h
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.h
@@ -303,6 +303,7 @@ public:
FUNC1(free, RID);
FUNC1(set_active, bool);
+ FUNC1(set_collision_iterations, int);
virtual void init() override;
virtual void step(real_t p_step) override;
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 4f12248c3e..1380e57b57 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -827,7 +827,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
- if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) {
+ if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) {
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
@@ -1109,7 +1109,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
- if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) {
+ if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) {
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
diff --git a/servers/physics_3d/area_3d_sw.cpp b/servers/physics_3d/area_3d_sw.cpp
index bb4e0ed752..a9f5c4aec3 100644
--- a/servers/physics_3d/area_3d_sw.cpp
+++ b/servers/physics_3d/area_3d_sw.cpp
@@ -52,7 +52,7 @@ void Area3DSW::_shapes_changed() {
}
}
-void Area3DSW::set_transform(const Transform &p_transform) {
+void Area3DSW::set_transform(const Transform3D &p_transform) {
if (!moved_list.in_list() && get_space()) {
get_space()->area_add_to_moved_list(&moved_list);
}
diff --git a/servers/physics_3d/area_3d_sw.h b/servers/physics_3d/area_3d_sw.h
index 8a0a1e963b..12f7545c08 100644
--- a/servers/physics_3d/area_3d_sw.h
+++ b/servers/physics_3d/area_3d_sw.h
@@ -156,7 +156,7 @@ public:
void set_monitorable(bool p_monitorable);
_FORCE_INLINE_ bool is_monitorable() const { return monitorable; }
- void set_transform(const Transform &p_transform);
+ void set_transform(const Transform3D &p_transform);
void set_space(Space3DSW *p_space);
diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp
index 4357c474e4..ea6064cb4c 100644
--- a/servers/physics_3d/body_3d_sw.cpp
+++ b/servers/physics_3d/body_3d_sw.cpp
@@ -54,7 +54,7 @@ void Body3DSW::update_inertias() {
// Update shapes and motions.
switch (mode) {
- case PhysicsServer3D::BODY_MODE_RIGID: {
+ case PhysicsServer3D::BODY_MODE_DYNAMIC: {
// Update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet)
real_t total_area = 0;
@@ -65,16 +65,18 @@ void Body3DSW::update_inertias() {
// We have to recompute the center of mass.
center_of_mass_local.zero();
- for (int i = 0; i < get_shape_count(); i++) {
- real_t area = get_shape_area(i);
+ if (total_area != 0.0) {
+ for (int i = 0; i < get_shape_count(); i++) {
+ real_t area = get_shape_area(i);
- real_t mass = area * this->mass / total_area;
+ real_t mass = area * this->mass / total_area;
- // NOTE: we assume that the shape origin is also its center of mass.
- center_of_mass_local += mass * get_shape_transform(i).origin;
- }
+ // NOTE: we assume that the shape origin is also its center of mass.
+ center_of_mass_local += mass * get_shape_transform(i).origin;
+ }
- center_of_mass_local /= mass;
+ center_of_mass_local /= mass;
+ }
// Recompute the inertia tensor.
Basis inertia_tensor;
@@ -86,16 +88,19 @@ void Body3DSW::update_inertias() {
continue;
}
+ real_t area = get_shape_area(i);
+ if (area == 0.0) {
+ continue;
+ }
+
inertia_set = true;
const Shape3DSW *shape = get_shape(i);
- real_t area = get_shape_area(i);
-
real_t mass = area * this->mass / total_area;
Basis shape_inertia_tensor = shape->get_moment_of_inertia(mass).to_diagonal_matrix();
- Transform shape_transform = get_shape_transform(i);
+ Transform3D shape_transform = get_shape_transform(i);
Basis shape_basis = shape_transform.basis.orthonormalized();
// NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor!
@@ -127,7 +132,7 @@ void Body3DSW::update_inertias() {
_inv_inertia_tensor.set_zero();
_inv_mass = 0;
} break;
- case PhysicsServer3D::BODY_MODE_CHARACTER: {
+ case PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED: {
_inv_inertia_tensor.set_zero();
_inv_mass = 1.0 / mass;
@@ -234,13 +239,13 @@ void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) {
}
} break;
- case PhysicsServer3D::BODY_MODE_RIGID: {
+ case PhysicsServer3D::BODY_MODE_DYNAMIC: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_set_static(false);
set_active(true);
} break;
- case PhysicsServer3D::BODY_MODE_CHARACTER: {
+ case PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_set_static(false);
set_active(true);
@@ -281,7 +286,7 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va
_set_inv_transform(get_transform().affine_inverse());
wakeup_neighbours();
} else {
- Transform t = p_variant;
+ Transform3D t = p_variant;
t.orthonormalize();
new_transform = get_transform(); //used as old to compute motion
if (new_transform == t) {
@@ -294,24 +299,15 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: {
- /*
- if (mode==PhysicsServer3D::BODY_MODE_STATIC)
- break;
- */
linear_velocity = p_variant;
wakeup();
} break;
case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: {
- /*
- if (mode!=PhysicsServer3D::BODY_MODE_RIGID)
- break;
- */
angular_velocity = p_variant;
wakeup();
} break;
case PhysicsServer3D::BODY_STATE_SLEEPING: {
- //?
if (mode == PhysicsServer3D::BODY_MODE_STATIC || mode == PhysicsServer3D::BODY_MODE_KINEMATIC) {
break;
}
@@ -328,7 +324,7 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer3D::BODY_STATE_CAN_SLEEP: {
can_sleep = p_variant;
- if (mode == PhysicsServer3D::BODY_MODE_RIGID && !active && !can_sleep) {
+ if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
set_active(true);
}
@@ -580,7 +576,7 @@ void Body3DSW::integrate_velocities(real_t p_step) {
Vector3 total_angular_velocity = angular_velocity + biased_angular_velocity;
real_t ang_vel = total_angular_velocity.length();
- Transform transform = get_transform();
+ Transform3D transform = get_transform();
if (ang_vel != 0.0) {
Vector3 ang_vel_axis = total_angular_velocity / ang_vel;
@@ -612,8 +608,8 @@ void Body3DSW::integrate_velocities(real_t p_step) {
}
/*
-void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) {
- Transform inv_xform = p_xform.affine_inverse();
+void BodySW::simulate_motion(const Transform3D& p_xform,real_t p_step) {
+ Transform3D inv_xform = p_xform.affine_inverse();
if (!get_space()) {
_set_transform(p_xform);
_set_inv_transform(inv_xform);
@@ -654,7 +650,7 @@ void Body3DSW::wakeup_neighbours() {
continue;
}
Body3DSW *b = n[i];
- if (b->mode != PhysicsServer3D::BODY_MODE_RIGID) {
+ if (b->mode != PhysicsServer3D::BODY_MODE_DYNAMIC) {
continue;
}
@@ -688,9 +684,7 @@ void Body3DSW::call_queries() {
bool Body3DSW::sleep_test(real_t p_step) {
if (mode == PhysicsServer3D::BODY_MODE_STATIC || mode == PhysicsServer3D::BODY_MODE_KINEMATIC) {
- return true; //
- } else if (mode == PhysicsServer3D::BODY_MODE_CHARACTER) {
- return !active; // characters don't sleep unless asked to sleep
+ return true;
} else if (!can_sleep) {
return false;
}
@@ -718,22 +712,16 @@ void Body3DSW::set_force_integration_callback(const Callable &p_callable, const
}
}
-void Body3DSW::set_kinematic_margin(real_t p_margin) {
- kinematic_safe_margin = p_margin;
-}
-
Body3DSW::Body3DSW() :
CollisionObject3DSW(TYPE_BODY),
active_list(this),
inertia_update_list(this),
direct_state_query_list(this) {
- mode = PhysicsServer3D::BODY_MODE_RIGID;
+ mode = PhysicsServer3D::BODY_MODE_DYNAMIC;
active = true;
mass = 1;
- kinematic_safe_margin = 0.001;
- //_inv_inertia=Transform();
_inv_mass = 1;
bounce = 0;
friction = 1;
diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h
index 9afb8cd56f..0fa31c5037 100644
--- a/servers/physics_3d/body_3d_sw.h
+++ b/servers/physics_3d/body_3d_sw.h
@@ -55,7 +55,6 @@ class Body3DSW : public CollisionObject3DSW {
uint16_t locked_axis = 0;
- real_t kinematic_safe_margin;
real_t _inv_mass;
Vector3 _inv_inertia; // Relative to the principal axes of inertia
@@ -93,7 +92,7 @@ class Body3DSW : public CollisionObject3DSW {
bool first_time_kinematic;
void _update_inertia();
virtual void _shapes_changed();
- Transform new_transform;
+ Transform3D new_transform;
Map<Constraint3DSW *, int> constraint_map;
@@ -144,9 +143,6 @@ class Body3DSW : public CollisionObject3DSW {
public:
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
- void set_kinematic_margin(real_t p_margin);
- _FORCE_INLINE_ real_t get_kinematic_margin() { return kinematic_safe_margin; }
-
_FORCE_INLINE_ void add_area(Area3DSW *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
@@ -311,7 +307,7 @@ public:
return p_axis.dot(_inv_inertia_tensor.xform_inv(p_axis));
}
- //void simulate_motion(const Transform& p_xform,real_t p_step);
+ //void simulate_motion(const Transform3D& p_xform,real_t p_step);
void call_queries();
void wakeup_neighbours();
@@ -390,8 +386,8 @@ public:
virtual void set_angular_velocity(const Vector3 &p_velocity) override { body->set_angular_velocity(p_velocity); }
virtual Vector3 get_angular_velocity() const override { return body->get_angular_velocity(); }
- virtual void set_transform(const Transform &p_transform) override { body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform); }
- virtual Transform get_transform() const override { return body->get_transform(); }
+ virtual void set_transform(const Transform3D &p_transform) override { body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform); }
+ virtual Transform3D get_transform() const override { return body->get_transform(); }
virtual void add_central_force(const Vector3 &p_force) override { body->add_central_force(p_force); }
virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override {
diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp
index cdb3da665e..aed4815c5e 100644
--- a/servers/physics_3d/body_pair_3d_sw.cpp
+++ b/servers/physics_3d/body_pair_3d_sw.cpp
@@ -161,7 +161,7 @@ void BodyPair3DSW::validate_contacts() {
}
}
-bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform &p_xform_B) {
+bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform3D &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform3D &p_xform_B) {
Vector3 motion = p_A->get_linear_velocity() * p_step;
real_t mlen = motion.length();
if (mlen < CMP_EPSILON) {
@@ -184,7 +184,7 @@ bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const
Vector3 from = p_xform_A.xform(s);
Vector3 to = from + motion;
- Transform from_inv = p_xform_B.affine_inverse();
+ Transform3D from_inv = p_xform_B.affine_inverse();
Vector3 local_from = from_inv.xform(from - mnormal * mlen * 0.1); //start from a little inside the bounding box
Vector3 local_to = from_inv.xform(to);
@@ -240,12 +240,12 @@ bool BodyPair3DSW::setup(real_t p_step) {
validate_contacts();
const Vector3 &offset_A = A->get_transform().get_origin();
- Transform xform_Au = Transform(A->get_transform().basis, Vector3());
- Transform xform_A = xform_Au * A->get_shape_transform(shape_A);
+ Transform3D xform_Au = Transform3D(A->get_transform().basis, Vector3());
+ Transform3D xform_A = xform_Au * A->get_shape_transform(shape_A);
- Transform xform_Bu = B->get_transform();
+ Transform3D xform_Bu = B->get_transform();
xform_Bu.origin -= offset_A;
- Transform xform_B = xform_Bu * B->get_shape_transform(shape_B);
+ Transform3D xform_B = xform_Bu * B->get_shape_transform(shape_B);
Shape3DSW *shape_A_ptr = A->get_shape(shape_A);
Shape3DSW *shape_B_ptr = B->get_shape(shape_B);
@@ -571,7 +571,7 @@ void BodySoftBodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int
void BodySoftBodyPair3DSW::validate_contacts() {
// Make sure to erase contacts that are no longer valid.
- const Transform &transform_A = body->get_transform();
+ const Transform3D &transform_A = body->get_transform();
real_t contact_max_separation = space->get_contact_max_separation();
@@ -612,11 +612,11 @@ bool BodySoftBodyPair3DSW::setup(real_t p_step) {
return false;
}
- const Transform &xform_Au = body->get_transform();
- Transform xform_A = xform_Au * body->get_shape_transform(body_shape);
+ const Transform3D &xform_Au = body->get_transform();
+ Transform3D xform_A = xform_Au * body->get_shape_transform(body_shape);
- Transform xform_Bu = soft_body->get_transform();
- Transform xform_B = xform_Bu * soft_body->get_shape_transform(0);
+ Transform3D xform_Bu = soft_body->get_transform();
+ Transform3D xform_B = xform_Bu * soft_body->get_shape_transform(0);
validate_contacts();
@@ -647,7 +647,7 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) {
bool do_process = false;
- const Transform &transform_A = body->get_transform();
+ const Transform3D &transform_A = body->get_transform();
uint32_t contact_count = contacts.size();
for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) {
diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/body_pair_3d_sw.h
index 3f425ba2d7..976982d1f1 100644
--- a/servers/physics_3d/body_pair_3d_sw.h
+++ b/servers/physics_3d/body_pair_3d_sw.h
@@ -98,7 +98,7 @@ class BodyPair3DSW : public BodyContact3DSW {
void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B);
void validate_contacts();
- bool _test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform &p_xform_B);
+ bool _test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform3D &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform3D &p_xform_B);
public:
virtual bool setup(real_t p_step) override;
diff --git a/servers/physics_3d/collision_object_3d_sw.cpp b/servers/physics_3d/collision_object_3d_sw.cpp
index 459deb1356..51e2432071 100644
--- a/servers/physics_3d/collision_object_3d_sw.cpp
+++ b/servers/physics_3d/collision_object_3d_sw.cpp
@@ -32,7 +32,7 @@
#include "servers/physics_3d/physics_server_3d_sw.h"
#include "space_3d_sw.h"
-void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform &p_transform, bool p_disabled) {
+void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform3D &p_transform, bool p_disabled) {
Shape s;
s.shape = p_shape;
s.xform = p_transform;
@@ -62,7 +62,7 @@ void CollisionObject3DSW::set_shape(int p_index, Shape3DSW *p_shape) {
//_shapes_changed();
}
-void CollisionObject3DSW::set_shape_transform(int p_index, const Transform &p_transform) {
+void CollisionObject3DSW::set_shape_transform(int p_index, const Transform3D &p_transform) {
ERR_FAIL_INDEX(p_index, shapes.size());
shapes.write[p_index].xform = p_transform;
@@ -149,7 +149,7 @@ void CollisionObject3DSW::_update_shapes() {
//not quite correct, should compute the next matrix..
AABB shape_aabb = s.shape->get_aabb();
- Transform xform = transform * s.xform;
+ Transform3D xform = transform * s.xform;
shape_aabb = xform.xform(shape_aabb);
shape_aabb.grow_by((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05);
s.aabb_cache = shape_aabb;
@@ -176,7 +176,7 @@ void CollisionObject3DSW::_update_shapes_with_motion(const Vector3 &p_motion) {
//not quite correct, should compute the next matrix..
AABB shape_aabb = s.shape->get_aabb();
- Transform xform = transform * s.xform;
+ Transform3D xform = transform * s.xform;
shape_aabb = xform.xform(shape_aabb);
shape_aabb.merge_with(AABB(shape_aabb.position + p_motion, shape_aabb.size)); //use motion
s.aabb_cache = shape_aabb;
diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h
index 85221b7746..5505fec3da 100644
--- a/servers/physics_3d/collision_object_3d_sw.h
+++ b/servers/physics_3d/collision_object_3d_sw.h
@@ -60,8 +60,8 @@ private:
uint32_t collision_mask;
struct Shape {
- Transform xform;
- Transform xform_inv;
+ Transform3D xform;
+ Transform3D xform_inv;
BroadPhase3DSW::ID bpid;
AABB aabb_cache; //for rayqueries
real_t area_cache;
@@ -73,8 +73,8 @@ private:
Vector<Shape> shapes;
Space3DSW *space;
- Transform transform;
- Transform inv_transform;
+ Transform3D transform;
+ Transform3D inv_transform;
bool _static;
SelfList<CollisionObject3DSW> pending_shape_update_list;
@@ -85,7 +85,7 @@ protected:
void _update_shapes_with_motion(const Vector3 &p_motion);
void _unregister_shapes();
- _FORCE_INLINE_ void _set_transform(const Transform &p_transform, bool p_update_shapes = true) {
+ _FORCE_INLINE_ void _set_transform(const Transform3D &p_transform, bool p_update_shapes = true) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(p_transform.origin.length_squared() > MAX_OBJECT_DISTANCE_X2, "Object went too far away (more than '" + itos(MAX_OBJECT_DISTANCE) + "' units from origin).");
@@ -96,7 +96,7 @@ protected:
_update_shapes();
}
}
- _FORCE_INLINE_ void _set_inv_transform(const Transform &p_transform) { inv_transform = p_transform; }
+ _FORCE_INLINE_ void _set_inv_transform(const Transform3D &p_transform) { inv_transform = p_transform; }
void _set_static(bool p_static);
virtual void _shapes_changed() = 0;
@@ -116,22 +116,22 @@ public:
void _shape_changed();
_FORCE_INLINE_ Type get_type() const { return type; }
- void add_shape(Shape3DSW *p_shape, const Transform &p_transform = Transform(), bool p_disabled = false);
+ void add_shape(Shape3DSW *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false);
void set_shape(int p_index, Shape3DSW *p_shape);
- void set_shape_transform(int p_index, const Transform &p_transform);
+ void set_shape_transform(int p_index, const Transform3D &p_transform);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
_FORCE_INLINE_ bool is_shape_disabled(int p_index) const {
CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].disabled;
}
_FORCE_INLINE_ Shape3DSW *get_shape(int p_index) const { return shapes[p_index].shape; }
- _FORCE_INLINE_ const Transform &get_shape_transform(int p_index) const { return shapes[p_index].xform; }
- _FORCE_INLINE_ const Transform &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
+ _FORCE_INLINE_ const Transform3D &get_shape_transform(int p_index) const { return shapes[p_index].xform; }
+ _FORCE_INLINE_ const Transform3D &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
_FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
_FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
- _FORCE_INLINE_ const Transform &get_transform() const { return transform; }
- _FORCE_INLINE_ const Transform &get_inv_transform() const { return inv_transform; }
+ _FORCE_INLINE_ const Transform3D &get_transform() const { return transform; }
+ _FORCE_INLINE_ const Transform3D &get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ Space3DSW *get_space() const { return space; }
_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp
index 9d5448dbfa..b362f1ff17 100644
--- a/servers/physics_3d/collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/collision_solver_3d_sat.cpp
@@ -608,8 +608,8 @@ template <class ShapeA, class ShapeB, bool withMargin = false>
class SeparatorAxisTest {
const ShapeA *shape_A;
const ShapeB *shape_B;
- const Transform *transform_A;
- const Transform *transform_B;
+ const Transform3D *transform_A;
+ const Transform3D *transform_B;
real_t best_depth;
Vector3 best_axis;
_CollectorCallback *callback;
@@ -690,7 +690,7 @@ public:
Vector3 axis = (p_point_B - p_point_A);
real_t depth = axis.length();
- // Filter out bogus directions with a treshold and re-testing axis.
+ // Filter out bogus directions with a threshold and re-testing axis.
if (separator->best_depth - depth > 0.001) {
separator->test_axis(axis / depth);
}
@@ -750,7 +750,7 @@ public:
callback->collided = true;
}
- _FORCE_INLINE_ SeparatorAxisTest(const ShapeA *p_shape_A, const Transform &p_transform_A, const ShapeB *p_shape_B, const Transform &p_transform_B, _CollectorCallback *p_callback, real_t p_margin_A = 0, real_t p_margin_B = 0) {
+ _FORCE_INLINE_ SeparatorAxisTest(const ShapeA *p_shape_A, const Transform3D &p_transform_A, const ShapeB *p_shape_B, const Transform3D &p_transform_B, _CollectorCallback *p_callback, real_t p_margin_A = 0, real_t p_margin_B = 0) {
best_depth = 1e15;
shape_A = p_shape_A;
shape_B = p_shape_B;
@@ -764,10 +764,10 @@ public:
/****** SAT TESTS *******/
-typedef void (*CollisionFunc)(const Shape3DSW *, const Transform &, const Shape3DSW *, const Transform &, _CollectorCallback *p_callback, real_t, real_t);
+typedef void (*CollisionFunc)(const Shape3DSW *, const Transform3D &, const Shape3DSW *, const Transform3D &, _CollectorCallback *p_callback, real_t, real_t);
template <bool withMargin>
-static void _collision_sphere_sphere(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_sphere_sphere(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
const SphereShape3DSW *sphere_B = static_cast<const SphereShape3DSW *>(p_b);
@@ -787,7 +787,7 @@ static void _collision_sphere_sphere(const Shape3DSW *p_a, const Transform &p_tr
}
template <bool withMargin>
-static void _collision_sphere_box(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_sphere_box(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
const BoxShape3DSW *box_B = static_cast<const BoxShape3DSW *>(p_b);
@@ -838,7 +838,7 @@ static void _collision_sphere_box(const Shape3DSW *p_a, const Transform &p_trans
}
template <bool withMargin>
-static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b);
@@ -880,7 +880,7 @@ static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform &p_t
}
template <bool withMargin>
-static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
@@ -939,7 +939,7 @@ static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform &p_
}
template <bool withMargin>
-static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
@@ -999,7 +999,7 @@ static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transfo
}
template <bool withMargin>
-static void _collision_sphere_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_sphere_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
@@ -1044,7 +1044,7 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform &p_tran
}
template <bool withMargin>
-static void _collision_box_box(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_box_box(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
const BoxShape3DSW *box_B = static_cast<const BoxShape3DSW *>(p_b);
@@ -1142,7 +1142,7 @@ static void _collision_box_box(const Shape3DSW *p_a, const Transform &p_transfor
}
template <bool withMargin>
-static void _collision_box_capsule(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b);
@@ -1240,7 +1240,7 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform &p_tran
}
template <bool withMargin>
-static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
@@ -1353,7 +1353,7 @@ static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform &p_tra
}
template <bool withMargin>
-static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
@@ -1468,7 +1468,7 @@ static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform
}
template <bool withMargin>
-static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
@@ -1591,7 +1591,7 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
}
template <bool withMargin>
-static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b);
@@ -1655,7 +1655,7 @@ static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform &p_
}
template <bool withMargin>
-static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
@@ -1717,7 +1717,7 @@ static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform &p
}
template <bool withMargin>
-static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
@@ -1781,7 +1781,7 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf
}
template <bool withMargin>
-static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
@@ -1855,7 +1855,7 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra
}
template <bool withMargin>
-static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
@@ -1909,7 +1909,7 @@ static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform &
}
template <bool withMargin>
-static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
@@ -1926,7 +1926,7 @@ static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Trans
}
template <bool withMargin>
-static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
@@ -2031,7 +2031,7 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr
}
template <bool withMargin>
-static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const ConvexPolygonShape3DSW *convex_polygon_A = static_cast<const ConvexPolygonShape3DSW *>(p_a);
const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
@@ -2140,7 +2140,7 @@ static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const
}
template <bool withMargin>
-static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const ConvexPolygonShape3DSW *convex_polygon_A = static_cast<const ConvexPolygonShape3DSW *>(p_a);
const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
@@ -2258,7 +2258,7 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
separator.generate_contacts();
}
-bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) {
+bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) {
PhysicsServer3D::ShapeType type_A = p_shape_A->get_type();
ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_PLANE, false);
@@ -2358,8 +2358,8 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_tr
const Shape3DSW *A = p_shape_A;
const Shape3DSW *B = p_shape_B;
- const Transform *transform_A = &p_transform_A;
- const Transform *transform_B = &p_transform_B;
+ const Transform3D *transform_A = &p_transform_A;
+ const Transform3D *transform_B = &p_transform_B;
real_t margin_A = p_margin_a;
real_t margin_B = p_margin_b;
diff --git a/servers/physics_3d/collision_solver_3d_sat.h b/servers/physics_3d/collision_solver_3d_sat.h
index 97454c0b4a..e50da7b101 100644
--- a/servers/physics_3d/collision_solver_3d_sat.h
+++ b/servers/physics_3d/collision_solver_3d_sat.h
@@ -33,6 +33,6 @@
#include "collision_solver_3d_sw.h"
-bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0);
+bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0);
#endif // COLLISION_SOLVER_SAT_H
diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp
index f655c4626c..67330d497e 100644
--- a/servers/physics_3d/collision_solver_3d_sw.cpp
+++ b/servers/physics_3d/collision_solver_3d_sw.cpp
@@ -37,7 +37,7 @@
#define collision_solver sat_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
const PlaneShape3DSW *plane = static_cast<const PlaneShape3DSW *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_PLANE) {
return false;
@@ -89,14 +89,14 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T
return found;
}
-bool CollisionSolver3DSW::solve_ray(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+bool CollisionSolver3DSW::solve_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
const RayShape3DSW *ray = static_cast<const RayShape3DSW *>(p_shape_A);
Vector3 from = p_transform_A.origin;
Vector3 to = from + p_transform_A.basis.get_axis(2) * ray->get_length();
Vector3 support_A = to;
- Transform ai = p_transform_B.affine_inverse();
+ Transform3D ai = p_transform_B.affine_inverse();
from = ai.xform(from);
to = ai.xform(to);
@@ -146,8 +146,8 @@ struct _SoftBodyQueryInfo {
SoftBody3DSW *soft_body = nullptr;
const Shape3DSW *shape_A = nullptr;
const Shape3DSW *shape_B = nullptr;
- Transform transform_A;
- Transform node_transform;
+ Transform3D transform_A;
+ Transform3D node_transform;
_SoftBodyContactCollisionInfo contact_info;
#ifdef DEBUG_ENABLED
int node_query_count = 0;
@@ -160,7 +160,7 @@ bool CollisionSolver3DSW::soft_body_query_callback(uint32_t p_node_index, void *
Vector3 node_position = query_cinfo.soft_body->get_node_position(p_node_index);
- Transform transform_B;
+ Transform3D transform_B;
transform_B.origin = query_cinfo.node_transform.xform(node_position);
query_cinfo.contact_info.node_index = p_node_index;
@@ -201,11 +201,11 @@ void CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW
#endif
}
-bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
const SoftBodyShape3DSW *soft_body_shape_B = static_cast<const SoftBodyShape3DSW *>(p_shape_B);
SoftBody3DSW *soft_body = soft_body_shape_B->get_soft_body();
- const Transform &world_to_local = soft_body->get_inv_transform();
+ const Transform3D &world_to_local = soft_body->get_inv_transform();
const real_t collision_margin = soft_body->get_collision_margin();
@@ -257,9 +257,9 @@ bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Tran
}
struct _ConcaveCollisionInfo {
- const Transform *transform_A;
+ const Transform3D *transform_A;
const Shape3DSW *shape_A;
- const Transform *transform_B;
+ const Transform3D *transform_B;
CollisionSolver3DSW::CallbackResult result_callback;
void *userdata;
bool swap_result;
@@ -285,7 +285,7 @@ void CollisionSolver3DSW::concave_callback(void *p_userdata, Shape3DSW *p_convex
cinfo.collisions++;
}
-bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) {
+bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) {
const ConcaveShape3DSW *concave_B = static_cast<const ConcaveShape3DSW *>(p_shape_B);
_ConcaveCollisionInfo cinfo;
@@ -302,7 +302,7 @@ bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transf
cinfo.aabb_tests = 0;
- Transform rel_transform = p_transform_A;
+ Transform3D rel_transform = p_transform_A;
rel_transform.origin -= p_transform_B.origin;
//quickly compute a local AABB
@@ -329,7 +329,7 @@ bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transf
return cinfo.collided;
}
-bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
+bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
PhysicsServer3D::ShapeType type_A = p_shape_A->get_type();
PhysicsServer3D::ShapeType type_B = p_shape_B->get_type();
bool concave_A = p_shape_A->is_concave();
@@ -421,7 +421,7 @@ void CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW
cinfo.collisions++;
}
-bool CollisionSolver3DSW::solve_distance_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) {
+bool CollisionSolver3DSW::solve_distance_plane(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) {
const PlaneShape3DSW *plane = static_cast<const PlaneShape3DSW *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_PLANE) {
return false;
@@ -473,7 +473,7 @@ bool CollisionSolver3DSW::solve_distance_plane(const Shape3DSW *p_shape_A, const
return collided;
}
-bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) {
+bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) {
if (p_shape_A->is_concave()) {
return false;
}
@@ -504,7 +504,7 @@ bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Trans
cinfo.aabb_tests = 0;
cinfo.tested = false;
- Transform rel_transform = p_transform_A;
+ Transform3D rel_transform = p_transform_A;
rel_transform.origin -= p_transform_B.origin;
//quickly compute a local AABB
diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/collision_solver_3d_sw.h
index 34ac2c6d3f..a5dd7d48eb 100644
--- a/servers/physics_3d/collision_solver_3d_sw.h
+++ b/servers/physics_3d/collision_solver_3d_sw.h
@@ -42,16 +42,16 @@ private:
static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
static void soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex);
static void concave_callback(void *p_userdata, Shape3DSW *p_convex);
- static bool solve_static_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
- static bool solve_ray(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
- static bool solve_soft_body(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
- static bool solve_concave(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0);
+ static bool solve_static_plane(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_soft_body(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_concave(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0);
static void concave_distance_callback(void *p_userdata, Shape3DSW *p_convex);
- static bool solve_distance_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B);
+ static bool solve_distance_plane(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B);
public:
- static bool solve_static(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
- static bool solve_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = nullptr);
+ static bool solve_static(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
+ static bool solve_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = nullptr);
};
#endif // COLLISION_SOLVER__SW_H
diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp
index 1a8c7f704f..2df991563d 100644
--- a/servers/physics_3d/gjk_epa.cpp
+++ b/servers/physics_3d/gjk_epa.cpp
@@ -107,16 +107,16 @@ typedef unsigned char U1;
struct MinkowskiDiff {
const Shape3DSW* m_shapes[2];
- Transform transform_A;
- Transform transform_B;
+ Transform3D transform_A;
+ Transform3D transform_B;
real_t margin_A = 0.0;
real_t margin_B = 0.0;
Vector3 (*get_support)(const Shape3DSW*, const Vector3&, real_t);
- void Initialize(const Shape3DSW* shape0, const Transform& wtrs0, const real_t margin0,
- const Shape3DSW* shape1, const Transform& wtrs1, const real_t margin1) {
+ void Initialize(const Shape3DSW* shape0, const Transform3D& wtrs0, const real_t margin0,
+ const Shape3DSW* shape1, const Transform3D& wtrs1, const real_t margin1) {
m_shapes[0] = shape0;
m_shapes[1] = shape1;
transform_A = wtrs0;
@@ -862,8 +862,8 @@ struct GJK
};
//
- static void Initialize( const Shape3DSW* shape0, const Transform& wtrs0, real_t margin0,
- const Shape3DSW* shape1, const Transform& wtrs1, real_t margin1,
+ static void Initialize( const Shape3DSW* shape0, const Transform3D& wtrs0, real_t margin0,
+ const Shape3DSW* shape1, const Transform3D& wtrs1, real_t margin1,
sResults& results,
tShape& shape)
{
@@ -885,10 +885,10 @@ struct GJK
//
bool Distance( const Shape3DSW* shape0,
- const Transform& wtrs0,
+ const Transform3D& wtrs0,
real_t margin0,
const Shape3DSW* shape1,
- const Transform& wtrs1,
+ const Transform3D& wtrs1,
real_t margin1,
const Vector3& guess,
sResults& results)
@@ -926,10 +926,10 @@ bool Distance( const Shape3DSW* shape0,
//
bool Penetration( const Shape3DSW* shape0,
- const Transform& wtrs0,
+ const Transform3D& wtrs0,
real_t margin0,
const Shape3DSW* shape1,
- const Transform& wtrs1,
+ const Transform3D& wtrs1,
real_t margin1,
const Vector3& guess,
sResults& results
@@ -993,7 +993,7 @@ bool Penetration( const Shape3DSW* shape0,
/* clang-format on */
-bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) {
+bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) {
GjkEpa2::sResults res;
if (GjkEpa2::Distance(p_shape_A, p_transform_A, 0.0, p_shape_B, p_transform_B, 0.0, p_transform_B.origin - p_transform_A.origin, res)) {
@@ -1005,7 +1005,7 @@ bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_t
return false;
}
-bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, real_t p_margin_A, real_t p_margin_B) {
+bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, real_t p_margin_A, real_t p_margin_B) {
GjkEpa2::sResults res;
if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_margin_A, p_shape_B, p_transform_B, p_margin_B, p_transform_B.origin - p_transform_A.origin, res)) {
diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h
index a7e2e1719e..69e85d2bc0 100644
--- a/servers/physics_3d/gjk_epa.h
+++ b/servers/physics_3d/gjk_epa.h
@@ -34,7 +34,7 @@
#include "collision_solver_3d_sw.h"
#include "shape_3d_sw.h"
-bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
-bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
+bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
+bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
#endif
diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp b/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
index e9efddf165..7315e9c709 100644
--- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
@@ -84,7 +84,7 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) {
return (y < 0.0f) ? -angle : angle;
}
-ConeTwistJoint3DSW::ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &rbAFrame, const Transform &rbBFrame) :
+ConeTwistJoint3DSW::ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame) :
Joint3DSW(_arr, 2) {
A = rbA;
B = rbB;
@@ -211,7 +211,7 @@ bool ConeTwistJoint3DSW::setup(real_t p_timestep) {
// Twist limits
if (m_twistSpan >= real_t(0.)) {
Vector3 b2Axis22 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1));
- Quat rotationArc = Quat(b2Axis1, b1Axis1);
+ Quaternion rotationArc = Quaternion(b2Axis1, b1Axis1);
Vector3 TwistRef = rotationArc.xform(b2Axis22);
real_t twist = atan2fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));
diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h b/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
index b871ea50db..608847352c 100644
--- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
+++ b/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
@@ -73,8 +73,8 @@ public:
JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints
real_t m_appliedImpulse;
- Transform m_rbAFrame;
- Transform m_rbBFrame;
+ Transform3D m_rbAFrame;
+ Transform3D m_rbBFrame;
real_t m_limitSoftness;
real_t m_biasFactor;
@@ -107,7 +107,7 @@ public:
virtual bool setup(real_t p_step) override;
virtual void solve(real_t p_step) override;
- ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &rbAFrame, const Transform &rbBFrame);
+ ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame);
void setAngularOnly(bool angularOnly) {
m_angularOnly = angularOnly;
diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
index 7c504764a7..56aba24b42 100644
--- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
@@ -219,7 +219,7 @@ real_t G6DOFTranslationalLimitMotor3DSW::solveLinearAxis(
//////////////////////////// G6DOFTranslationalLimitMotorSW ////////////////////////////////////
-Generic6DOFJoint3DSW::Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA) :
+Generic6DOFJoint3DSW::Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA) :
Joint3DSW(_arr, 2),
m_frameInA(frameInA),
m_frameInB(frameInB),
diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
index 8af76cefc2..d46437e782 100644
--- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
+++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
@@ -81,7 +81,7 @@ public:
//! temp_variables
//!@{
- real_t m_currentLimitError; //! How much is violated this limit
+ real_t m_currentLimitError; //!< How much is violated this limit
int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit
real_t m_accumulatedImpulse;
//!@}
@@ -113,7 +113,7 @@ public:
return (m_enableMotor || m_currentLimit != 0);
}
- //! calculates error
+ //! calculates error
/*!
calculates m_currentLimit and m_currentLimitError.
*/
@@ -185,8 +185,8 @@ protected:
//! relative_frames
//!@{
- Transform m_frameInA; //!< the constraint space w.r.t body A
- Transform m_frameInB; //!< the constraint space w.r.t body B
+ Transform3D m_frameInA; //!< the constraint space w.r.t body A
+ Transform3D m_frameInB; //!< the constraint space w.r.t body B
//!@}
//! Jacobians
@@ -209,8 +209,8 @@ protected:
//! temporal variables
//!@{
real_t m_timeStep;
- Transform m_calculatedTransformA;
- Transform m_calculatedTransformB;
+ Transform3D m_calculatedTransformA;
+ Transform3D m_calculatedTransformB;
Vector3 m_calculatedAxisAngleDiff;
Vector3 m_calculatedAxis[3];
@@ -233,7 +233,7 @@ protected:
void calculateAngleInfo();
public:
- Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA);
+ Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA);
virtual PhysicsServer3D::JointType get_type() const override { return PhysicsServer3D::JOINT_TYPE_6DOF; }
@@ -251,7 +251,7 @@ public:
/*!
\sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo.
*/
- const Transform &getCalculatedTransformA() const {
+ const Transform3D &getCalculatedTransformA() const {
return m_calculatedTransformA;
}
@@ -259,23 +259,23 @@ public:
/*!
\sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo.
*/
- const Transform &getCalculatedTransformB() const {
+ const Transform3D &getCalculatedTransformB() const {
return m_calculatedTransformB;
}
- const Transform &getFrameOffsetA() const {
+ const Transform3D &getFrameOffsetA() const {
return m_frameInA;
}
- const Transform &getFrameOffsetB() const {
+ const Transform3D &getFrameOffsetB() const {
return m_frameInB;
}
- Transform &getFrameOffsetA() {
+ Transform3D &getFrameOffsetA() {
return m_frameInA;
}
- Transform &getFrameOffsetB() {
+ Transform3D &getFrameOffsetB() {
return m_frameInB;
}
@@ -327,7 +327,7 @@ public:
return &m_angularLimits[index];
}
- //! Retrieves the limit informacion
+ //! Retrieves the limit informacion
G6DOFTranslationalLimitMotor3DSW *getTranslationalLimitMotor() {
return &m_linearLimits;
}
diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp
index bb8858c28a..b928f18231 100644
--- a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp
@@ -67,7 +67,7 @@ static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) {
}
}
-HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameA, const Transform &frameB) :
+HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameA, const Transform3D &frameB) :
Joint3DSW(_arr, 2) {
A = rbA;
B = rbB;
@@ -126,7 +126,7 @@ HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivo
rbAxisA1.y, rbAxisA2.y, axisInA.y,
rbAxisA1.z, rbAxisA2.z, axisInA.z);
- Quat rotationArc = Quat(axisInA, axisInB);
+ Quaternion rotationArc = Quaternion(axisInA, axisInB);
Vector3 rbAxisB1 = rotationArc.xform(rbAxisA1);
Vector3 rbAxisB2 = axisInB.cross(rbAxisB1);
diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.h b/servers/physics_3d/joints/hinge_joint_3d_sw.h
index 2100f5de44..22eb2f4660 100644
--- a/servers/physics_3d/joints/hinge_joint_3d_sw.h
+++ b/servers/physics_3d/joints/hinge_joint_3d_sw.h
@@ -66,8 +66,8 @@ class HingeJoint3DSW : public Joint3DSW {
JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints
JacobianEntry3DSW m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
- Transform m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- Transform m_rbBFrame;
+ Transform3D m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ Transform3D m_rbBFrame;
real_t m_motorTargetVelocity;
real_t m_maxMotorImpulse;
@@ -109,7 +109,7 @@ public:
void set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value);
bool get_flag(PhysicsServer3D::HingeJointFlag p_flag) const;
- HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameA, const Transform &frameB);
+ HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameA, const Transform3D &frameB);
HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB);
};
diff --git a/servers/physics_3d/joints/jacobian_entry_3d_sw.h b/servers/physics_3d/joints/jacobian_entry_3d_sw.h
index 2829a5caf7..6afa70c816 100644
--- a/servers/physics_3d/joints/jacobian_entry_3d_sw.h
+++ b/servers/physics_3d/joints/jacobian_entry_3d_sw.h
@@ -50,7 +50,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#include "core/math/transform.h"
+#include "core/math/transform_3d.h"
class JacobianEntry3DSW {
public:
diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.cpp b/servers/physics_3d/joints/slider_joint_3d_sw.cpp
index 8bd1951311..db9bdb2986 100644
--- a/servers/physics_3d/joints/slider_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/slider_joint_3d_sw.cpp
@@ -111,7 +111,7 @@ void SliderJoint3DSW::initParams() {
//-----------------------------------------------------------------------------
-SliderJoint3DSW::SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB) :
+SliderJoint3DSW::SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB) :
Joint3DSW(_arr, 2),
m_frameInA(frameInA),
m_frameInB(frameInB) {
diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.h b/servers/physics_3d/joints/slider_joint_3d_sw.h
index ef5891d0f9..f357bbd67a 100644
--- a/servers/physics_3d/joints/slider_joint_3d_sw.h
+++ b/servers/physics_3d/joints/slider_joint_3d_sw.h
@@ -76,8 +76,8 @@ protected:
Body3DSW *_arr[2];
};
- Transform m_frameInA;
- Transform m_frameInB;
+ Transform3D m_frameInA;
+ Transform3D m_frameInB;
// linear limits
real_t m_lowerLinLimit;
@@ -120,8 +120,8 @@ protected:
JacobianEntry3DSW m_jacAng[3];
real_t m_timeStep;
- Transform m_calculatedTransformA;
- Transform m_calculatedTransformB;
+ Transform3D m_calculatedTransformA;
+ Transform3D m_calculatedTransformB;
Vector3 m_sliderAxis;
Vector3 m_realPivotAInW;
@@ -152,19 +152,19 @@ protected:
public:
// constructors
- SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB);
+ SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB);
//SliderJointSW();
// overrides
// access
const Body3DSW *getRigidBodyA() const { return A; }
const Body3DSW *getRigidBodyB() const { return B; }
- const Transform &getCalculatedTransformA() const { return m_calculatedTransformA; }
- const Transform &getCalculatedTransformB() const { return m_calculatedTransformB; }
- const Transform &getFrameOffsetA() const { return m_frameInA; }
- const Transform &getFrameOffsetB() const { return m_frameInB; }
- Transform &getFrameOffsetA() { return m_frameInA; }
- Transform &getFrameOffsetB() { return m_frameInB; }
+ const Transform3D &getCalculatedTransformA() const { return m_calculatedTransformA; }
+ const Transform3D &getCalculatedTransformB() const { return m_calculatedTransformB; }
+ const Transform3D &getFrameOffsetA() const { return m_frameInA; }
+ const Transform3D &getFrameOffsetB() const { return m_frameInB; }
+ Transform3D &getFrameOffsetA() { return m_frameInA; }
+ Transform3D &getFrameOffsetB() { return m_frameInB; }
real_t getLowerLinLimit() { return m_lowerLinLimit; }
void setLowerLinLimit(real_t lowerLimit) { m_lowerLinLimit = lowerLimit; }
real_t getUpperLinLimit() { return m_upperLinLimit; }
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index f3eb1ae48f..7a95a8abc8 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -262,7 +262,7 @@ PhysicsServer3D::AreaSpaceOverrideMode PhysicsServer3DSW::area_get_space_overrid
return area->get_space_override_mode();
}
-void PhysicsServer3DSW::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) {
+void PhysicsServer3DSW::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
Area3DSW *area = area_owner.getornull(p_area);
ERR_FAIL_COND(!area);
@@ -283,7 +283,7 @@ void PhysicsServer3DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape)
area->set_shape(p_shape_idx, shape);
}
-void PhysicsServer3DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) {
+void PhysicsServer3DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) {
Area3DSW *area = area_owner.getornull(p_area);
ERR_FAIL_COND(!area);
@@ -307,9 +307,9 @@ RID PhysicsServer3DSW::area_get_shape(RID p_area, int p_shape_idx) const {
return shape->get_self();
}
-Transform PhysicsServer3DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const {
+Transform3D PhysicsServer3DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const {
Area3DSW *area = area_owner.getornull(p_area);
- ERR_FAIL_COND_V(!area, Transform());
+ ERR_FAIL_COND_V(!area, Transform3D());
return area->get_shape_transform(p_shape_idx);
}
@@ -368,7 +368,7 @@ void PhysicsServer3DSW::area_set_param(RID p_area, AreaParameter p_param, const
area->set_param(p_param, p_value);
};
-void PhysicsServer3DSW::area_set_transform(RID p_area, const Transform &p_transform) {
+void PhysicsServer3DSW::area_set_transform(RID p_area, const Transform3D &p_transform) {
Area3DSW *area = area_owner.getornull(p_area);
ERR_FAIL_COND(!area);
area->set_transform(p_transform);
@@ -385,9 +385,9 @@ Variant PhysicsServer3DSW::area_get_param(RID p_area, AreaParameter p_param) con
return area->get_param(p_param);
};
-Transform PhysicsServer3DSW::area_get_transform(RID p_area) const {
+Transform3D PhysicsServer3DSW::area_get_transform(RID p_area) const {
Area3DSW *area = area_owner.getornull(p_area);
- ERR_FAIL_COND_V(!area, Transform());
+ ERR_FAIL_COND_V(!area, Transform3D());
return area->get_transform();
};
@@ -487,7 +487,7 @@ PhysicsServer3D::BodyMode PhysicsServer3DSW::body_get_mode(RID p_body) const {
return body->get_mode();
};
-void PhysicsServer3DSW::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) {
+void PhysicsServer3DSW::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -507,8 +507,7 @@ void PhysicsServer3DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape)
body->set_shape(p_shape_idx, shape);
}
-
-void PhysicsServer3DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) {
+void PhysicsServer3DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -541,9 +540,9 @@ void PhysicsServer3DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, boo
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
-Transform PhysicsServer3DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
+Transform3D PhysicsServer3DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
Body3DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, Transform());
+ ERR_FAIL_COND_V(!body, Transform3D());
return body->get_shape_transform(p_shape_idx);
}
@@ -657,19 +656,6 @@ real_t PhysicsServer3DSW::body_get_param(RID p_body, BodyParameter p_param) cons
return body->get_param(p_param);
};
-void PhysicsServer3DSW::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) {
- Body3DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND(!body);
- body->set_kinematic_margin(p_margin);
-}
-
-real_t PhysicsServer3DSW::body_get_kinematic_safe_margin(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return body->get_kinematic_margin();
-}
-
void PhysicsServer3DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -868,7 +854,7 @@ void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
body->set_ray_pickable(p_enable);
}
-bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -876,10 +862,10 @@ bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform &p_from, co
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, body->get_kinematic_margin(), r_result, p_exclude_raycast_shapes);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
}
-int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
+int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -1010,7 +996,7 @@ Variant PhysicsServer3DSW::soft_body_get_state(RID p_body, BodyState p_state) co
return soft_body->get_state(p_state);
}
-void PhysicsServer3DSW::soft_body_set_transform(RID p_body, const Transform &p_transform) {
+void PhysicsServer3DSW::soft_body_set_transform(RID p_body, const Transform3D &p_transform) {
SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!soft_body);
@@ -1253,7 +1239,7 @@ Vector3 PhysicsServer3DSW::pin_joint_get_local_b(RID p_joint) const {
return pin_joint->get_position_b();
}
-void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) {
+void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_frame_A, RID p_body_B, const Transform3D &p_frame_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
ERR_FAIL_COND(!body_A);
@@ -1378,7 +1364,7 @@ PhysicsServer3DSW::JointType PhysicsServer3DSW::joint_get_type(RID p_joint) cons
return joint->get_type();
}
-void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
ERR_FAIL_COND(!body_A);
@@ -1418,7 +1404,7 @@ real_t PhysicsServer3DSW::slider_joint_get_param(RID p_joint, SliderJointParam p
return slider_joint->get_param(p_param);
}
-void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
ERR_FAIL_COND(!body_A);
@@ -1458,7 +1444,7 @@ real_t PhysicsServer3DSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJoint
return cone_twist_joint->get_param(p_param);
}
-void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
ERR_FAIL_COND(!body_A);
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index 0b42f1d605..57b6385758 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -130,13 +130,13 @@ public:
virtual void area_set_space(RID p_area, RID p_space) override;
virtual RID area_get_space(RID p_area) const override;
- virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) override;
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) override;
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) override;
- virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) override;
+ virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) override;
virtual int area_get_shape_count(RID p_area) const override;
virtual RID area_get_shape(RID p_area, int p_shape_idx) const override;
- virtual Transform area_get_shape_transform(RID p_area, int p_shape_idx) const override;
+ virtual Transform3D area_get_shape_transform(RID p_area, int p_shape_idx) const override;
virtual void area_remove_shape(RID p_area, int p_shape_idx) override;
virtual void area_clear_shapes(RID p_area) override;
@@ -147,10 +147,10 @@ public:
virtual ObjectID area_get_object_instance_id(RID p_area) const override;
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) override;
- virtual void area_set_transform(RID p_area, const Transform &p_transform) override;
+ virtual void area_set_transform(RID p_area, const Transform3D &p_transform) override;
virtual Variant area_get_param(RID p_area, AreaParameter p_param) const override;
- virtual Transform area_get_transform(RID p_area) const override;
+ virtual Transform3D area_get_transform(RID p_area) const override;
virtual void area_set_ray_pickable(RID p_area, bool p_enable) override;
@@ -173,13 +173,13 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode) override;
virtual BodyMode body_get_mode(RID p_body) const override;
- virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) override;
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) override;
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) override;
- virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) override;
+ virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) override;
virtual int body_get_shape_count(RID p_body) const override;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const override;
- virtual Transform body_get_shape_transform(RID p_body, int p_shape_idx) const override;
+ virtual Transform3D body_get_shape_transform(RID p_body, int p_shape_idx) const override;
virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) override;
@@ -204,9 +204,6 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) override;
virtual real_t body_get_param(RID p_body, BodyParameter p_param) const override;
- virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) override;
- virtual real_t body_get_kinematic_safe_margin(RID p_body) const override;
-
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
virtual Variant body_get_state(RID p_body, BodyState p_state) const override;
@@ -245,8 +242,8 @@ public:
virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
- virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
+ virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
+ virtual int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
@@ -273,7 +270,7 @@ public:
virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const override;
- virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) override;
+ virtual void soft_body_set_transform(RID p_body, const Transform3D &p_transform) override;
virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override;
@@ -323,7 +320,7 @@ public:
virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) override;
virtual Vector3 pin_joint_get_local_b(RID p_joint) const override;
- virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) override;
+ virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_frame_A, RID p_body_B, const Transform3D &p_frame_B) override;
virtual void joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) override;
virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) override;
@@ -332,17 +329,17 @@ public:
virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) override;
virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const override;
- virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+ virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override; //reference frame is A
virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) override;
virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const override;
- virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+ virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override; //reference frame is A
virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) override;
virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const override;
- virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+ virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override; //reference frame is A
virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value) override;
virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) const override;
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.cpp b/servers/physics_3d/physics_server_3d_wrap_mt.cpp
index f73f67a756..0a89c1a9c9 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.cpp
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.cpp
@@ -56,7 +56,7 @@ void PhysicsServer3DWrapMT::thread_loop() {
step_thread_up = true;
while (!exit) {
// flush commands one by one, until exit is requested
- command_queue.wait_and_flush_one();
+ command_queue.wait_and_flush();
}
command_queue.flush_all(); // flush all
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h
index 69d0fcf3ed..bda2e30dd1 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.h
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.h
@@ -142,14 +142,14 @@ public:
FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode);
FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID);
- FUNC4(area_add_shape, RID, RID, const Transform &, bool);
+ FUNC4(area_add_shape, RID, RID, const Transform3D &, bool);
FUNC3(area_set_shape, RID, int, RID);
- FUNC3(area_set_shape_transform, RID, int, const Transform &);
+ FUNC3(area_set_shape_transform, RID, int, const Transform3D &);
FUNC3(area_set_shape_disabled, RID, int, bool);
FUNC1RC(int, area_get_shape_count, RID);
FUNC2RC(RID, area_get_shape, RID, int);
- FUNC2RC(Transform, area_get_shape_transform, RID, int);
+ FUNC2RC(Transform3D, area_get_shape_transform, RID, int);
FUNC2(area_remove_shape, RID, int);
FUNC1(area_clear_shapes, RID);
@@ -157,10 +157,10 @@ public:
FUNC1RC(ObjectID, area_get_object_instance_id, RID);
FUNC3(area_set_param, RID, AreaParameter, const Variant &);
- FUNC2(area_set_transform, RID, const Transform &);
+ FUNC2(area_set_transform, RID, const Transform3D &);
FUNC2RC(Variant, area_get_param, RID, AreaParameter);
- FUNC1RC(Transform, area_get_transform, RID);
+ FUNC1RC(Transform3D, area_get_transform, RID);
FUNC2(area_set_collision_mask, RID, uint32_t);
FUNC2(area_set_collision_layer, RID, uint32_t);
@@ -182,12 +182,12 @@ public:
FUNC2(body_set_mode, RID, BodyMode);
FUNC1RC(BodyMode, body_get_mode, RID);
- FUNC4(body_add_shape, RID, RID, const Transform &, bool);
+ FUNC4(body_add_shape, RID, RID, const Transform3D &, bool);
FUNC3(body_set_shape, RID, int, RID);
- FUNC3(body_set_shape_transform, RID, int, const Transform &);
+ FUNC3(body_set_shape_transform, RID, int, const Transform3D &);
FUNC1RC(int, body_get_shape_count, RID);
- FUNC2RC(Transform, body_get_shape_transform, RID, int);
+ FUNC2RC(Transform3D, body_get_shape_transform, RID, int);
FUNC2RC(RID, body_get_shape, RID, int);
FUNC3(body_set_shape_disabled, RID, int, bool);
@@ -213,9 +213,6 @@ public:
FUNC3(body_set_param, RID, BodyParameter, real_t);
FUNC2RC(real_t, body_get_param, RID, BodyParameter);
- FUNC2(body_set_kinematic_safe_margin, RID, real_t);
- FUNC1RC(real_t, body_get_kinematic_safe_margin, RID);
-
FUNC3(body_set_state, RID, BodyState, const Variant &);
FUNC2RC(Variant, body_get_state, RID, BodyState);
@@ -253,12 +250,12 @@ public:
FUNC2(body_set_ray_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
+ bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes);
+ return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
}
- int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
+ int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
return physics_3d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
}
@@ -293,7 +290,7 @@ public:
FUNC3(soft_body_set_state, RID, BodyState, const Variant &);
FUNC2RC(Variant, soft_body_get_state, RID, BodyState);
- FUNC2(soft_body_set_transform, RID, const Transform &);
+ FUNC2(soft_body_set_transform, RID, const Transform3D &);
FUNC2(soft_body_set_simulation_precision, RID, int);
FUNC1RC(int, soft_body_get_simulation_precision, RID);
@@ -341,7 +338,7 @@ public:
FUNC2(pin_joint_set_local_b, RID, const Vector3 &)
FUNC1RC(Vector3, pin_joint_get_local_b, RID)
- FUNC5(joint_make_hinge, RID, RID, const Transform &, RID, const Transform &)
+ FUNC5(joint_make_hinge, RID, RID, const Transform3D &, RID, const Transform3D &)
FUNC7(joint_make_hinge_simple, RID, RID, const Vector3 &, const Vector3 &, RID, const Vector3 &, const Vector3 &)
FUNC3(hinge_joint_set_param, RID, HingeJointParam, real_t)
@@ -350,17 +347,17 @@ public:
FUNC3(hinge_joint_set_flag, RID, HingeJointFlag, bool)
FUNC2RC(bool, hinge_joint_get_flag, RID, HingeJointFlag)
- FUNC5(joint_make_slider, RID, RID, const Transform &, RID, const Transform &)
+ FUNC5(joint_make_slider, RID, RID, const Transform3D &, RID, const Transform3D &)
FUNC3(slider_joint_set_param, RID, SliderJointParam, real_t)
FUNC2RC(real_t, slider_joint_get_param, RID, SliderJointParam)
- FUNC5(joint_make_cone_twist, RID, RID, const Transform &, RID, const Transform &)
+ FUNC5(joint_make_cone_twist, RID, RID, const Transform3D &, RID, const Transform3D &)
FUNC3(cone_twist_joint_set_param, RID, ConeTwistJointParam, real_t)
FUNC2RC(real_t, cone_twist_joint_get_param, RID, ConeTwistJointParam)
- FUNC5(joint_make_generic_6dof, RID, RID, const Transform &, RID, const Transform &)
+ FUNC5(joint_make_generic_6dof, RID, RID, const Transform3D &, RID, const Transform3D &)
FUNC4(generic_6dof_joint_set_param, RID, Vector3::Axis, G6DOFJointAxisParam, real_t)
FUNC3RC(real_t, generic_6dof_joint_get_param, RID, Vector3::Axis, G6DOFJointAxisParam)
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp
index ccd37ca742..2ffab0c923 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/shape_3d_sw.cpp
@@ -31,8 +31,8 @@
#include "shape_3d_sw.h"
#include "core/io/image.h"
+#include "core/math/convex_hull.h"
#include "core/math/geometry_3d.h"
-#include "core/math/quick_hull.h"
#include "core/templates/sort_array.h"
// HeightMapShape3DSW is based on Bullet btHeightfieldTerrainShape.
@@ -114,7 +114,7 @@ Plane PlaneShape3DSW::get_plane() const {
return plane;
}
-void PlaneShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void PlaneShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
// gibberish, a plane is infinity
r_min = -1e7;
r_max = 1e7;
@@ -174,7 +174,7 @@ bool RayShape3DSW::get_slips_on_slope() const {
return slips_on_slope;
}
-void RayShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void RayShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
// don't think this will be even used
r_min = 0;
r_max = 1;
@@ -255,7 +255,7 @@ real_t SphereShape3DSW::get_radius() const {
return radius;
}
-void SphereShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void SphereShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
real_t d = p_normal.dot(p_transform.origin);
// figure out scale at point
@@ -317,7 +317,7 @@ SphereShape3DSW::SphereShape3DSW() {
/********** BOX *************/
-void BoxShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void BoxShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
// no matter the angle, the box is mirrored anyway
Vector3 local_normal = p_transform.basis.xform_inv(p_normal);
@@ -507,7 +507,7 @@ BoxShape3DSW::BoxShape3DSW() {
/********** CAPSULE *************/
-void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
Vector3 n = p_transform.basis.xform_inv(p_normal).normalized();
real_t h = (n.y > 0) ? height : -height;
@@ -674,7 +674,7 @@ CapsuleShape3DSW::CapsuleShape3DSW() {
/********** CYLINDER *************/
-void CylinderShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void CylinderShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
Vector3 cylinder_axis = p_transform.basis.get_axis(1).normalized();
real_t axis_dot = cylinder_axis.dot(p_normal);
@@ -854,7 +854,7 @@ CylinderShape3DSW::CylinderShape3DSW() {
/********** CONVEX POLYGON *************/
-void ConvexPolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void ConvexPolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
int vertex_count = mesh.vertices.size();
if (vertex_count == 0) {
return;
@@ -1089,9 +1089,9 @@ Vector3 ConvexPolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const {
}
void ConvexPolygonShape3DSW::_setup(const Vector<Vector3> &p_vertices) {
- Error err = QuickHull::build(p_vertices, mesh);
+ Error err = ConvexHullComputer::convex_hull(p_vertices, mesh);
if (err != OK) {
- ERR_PRINT("Failed to build QuickHull");
+ ERR_PRINT("Failed to build convex hull");
}
AABB _aabb;
@@ -1120,7 +1120,7 @@ ConvexPolygonShape3DSW::ConvexPolygonShape3DSW() {
/********** FACE POLYGON *************/
-void FaceShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void FaceShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
for (int i = 0; i < 3; i++) {
Vector3 v = p_transform.xform(vertex[i]);
real_t d = p_normal.dot(v);
@@ -1250,7 +1250,7 @@ Vector<Vector3> ConcavePolygonShape3DSW::get_faces() const {
return rfaces;
}
-void ConcavePolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void ConcavePolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
int count = vertices.size();
if (count == 0) {
r_min = 0;
@@ -1647,7 +1647,7 @@ int HeightMapShape3DSW::get_depth() const {
return depth;
}
-void HeightMapShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+void HeightMapShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
//not very useful, but not very used either
p_transform.xform(get_aabb()).project_range_in_plane(Plane(p_normal, 0), r_min, r_max);
}
diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h
index 4d2b6ffbed..bc8bd3e695 100644
--- a/servers/physics_3d/shape_3d_sw.h
+++ b/servers/physics_3d/shape_3d_sw.h
@@ -86,7 +86,7 @@ public:
virtual bool is_concave() const { return false; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const = 0;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const = 0;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const = 0;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0;
@@ -130,7 +130,7 @@ public:
virtual real_t get_area() const { return Math_INF; }
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_PLANE; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; }
@@ -157,7 +157,7 @@ public:
virtual real_t get_area() const { return 0.0; }
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_RAY; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
@@ -185,7 +185,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SPHERE; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
@@ -210,7 +210,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_BOX; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
@@ -239,7 +239,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CAPSULE; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
@@ -268,7 +268,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CYLINDER; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
@@ -293,7 +293,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONVEX_POLYGON; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
@@ -371,7 +371,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
@@ -415,7 +415,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_HEIGHTMAP; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const;
virtual bool intersect_point(const Vector3 &p_point) const;
@@ -441,7 +441,7 @@ struct FaceShape3DSW : public Shape3DSW {
const Vector3 &get_vertex(int p_idx) const { return vertex[p_idx]; }
- void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
@@ -462,11 +462,11 @@ struct MotionShape3DSW : public Shape3DSW {
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONVEX_POLYGON; }
- void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+ void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
Vector3 cast = p_transform.basis.xform(motion);
real_t mina, maxa;
real_t minb, maxb;
- Transform ofsb = p_transform;
+ Transform3D ofsb = p_transform;
ofsb.origin += cast;
shape->project_range(p_normal, p_transform, mina, maxa);
shape->project_range(p_normal, ofsb, minb, maxb);
diff --git a/servers/physics_3d/soft_body_3d_sw.cpp b/servers/physics_3d/soft_body_3d_sw.cpp
index f63a470cbe..63a0fe11ba 100644
--- a/servers/physics_3d/soft_body_3d_sw.cpp
+++ b/servers/physics_3d/soft_body_3d_sw.cpp
@@ -289,7 +289,7 @@ void SoftBody3DSW::update_link_constants() {
}
}
-void SoftBody3DSW::apply_nodes_transform(const Transform &p_transform) {
+void SoftBody3DSW::apply_nodes_transform(const Transform3D &p_transform) {
if (soft_mesh.is_null()) {
return;
}
@@ -684,7 +684,7 @@ void SoftBody3DSW::generate_bending_constraints(int p_distance) {
//
// This function takes in a list of interdependent Links and tries
// to maximize the distance between calculation
-// of dependent links. This increases the amount of parallelism that can
+// of dependent links. This increases the amount of parallelism that can
// be exploited by out-of-order instruction processors with large but
// (inevitably) finite instruction windows.
//
diff --git a/servers/physics_3d/soft_body_3d_sw.h b/servers/physics_3d/soft_body_3d_sw.h
index 98e554218b..ac8bcbf0b9 100644
--- a/servers/physics_3d/soft_body_3d_sw.h
+++ b/servers/physics_3d/soft_body_3d_sw.h
@@ -201,7 +201,7 @@ private:
void reset_link_rest_lengths();
void update_link_constants();
- void apply_nodes_transform(const Transform &p_transform);
+ void apply_nodes_transform(const Transform3D &p_transform);
void add_velocity(const Vector3 &p_velocity);
@@ -231,7 +231,7 @@ public:
SoftBody3DSW *get_soft_body() const { return soft_body; }
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SOFT_BODY; }
- virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; }
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; }
virtual Vector3 get_support(const Vector3 &p_normal) const { return Vector3(); }
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; }
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index 2df824b320..c1e09c9a22 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -59,7 +59,7 @@ int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeRe
int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
int cc = 0;
- //Transform ai = p_xform.affine_inverse();
+ //Transform3D ai = p_xform.affine_inverse();
for (int i = 0; i < amount; i++) {
if (cc >= p_result_max) {
@@ -79,7 +79,7 @@ int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeRe
const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
- Transform inv_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ Transform3D inv_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
inv_xform.affine_invert();
if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_point))) {
@@ -136,7 +136,7 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec
const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
- Transform inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform();
+ Transform3D inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform();
Vector3 local_from = inv_xform.xform(begin);
Vector3 local_to = inv_xform.xform(end);
@@ -146,7 +146,7 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec
Vector3 shape_point, shape_normal;
if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) {
- Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ Transform3D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point = xform.xform(shape_point);
real_t ld = normal.dot(shape_point);
@@ -180,7 +180,7 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec
return true;
}
-int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0) {
return 0;
}
@@ -194,7 +194,7 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
int cc = 0;
- //Transform ai = p_xform.affine_inverse();
+ //Transform3D ai = p_xform.affine_inverse();
for (int i = 0; i < amount; i++) {
if (cc >= p_result_max) {
@@ -239,7 +239,7 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
return cc;
}
-bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
+bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
ERR_FAIL_COND_V(!shape, false);
@@ -252,7 +252,7 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
real_t best_safe = 1;
real_t best_unsafe = 1;
- Transform xform_inv = p_xform.affine_inverse();
+ Transform3D xform_inv = p_xform.affine_inverse();
MotionShape3DSW mshape;
mshape.shape = shape;
mshape.motion = xform_inv.basis.xform(p_motion);
@@ -280,7 +280,7 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
Vector3 point_A, point_B;
Vector3 sep_axis = p_motion.normalized();
- Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (CollisionSolver3DSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) {
continue;
@@ -348,7 +348,7 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
return true;
}
-bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0) {
return false;
}
@@ -432,7 +432,7 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect
rd->best_local_shape = rd->local_shape;
}
-bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
ERR_FAIL_COND_V(!shape, 0);
@@ -512,7 +512,7 @@ Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_ob
continue;
}
- Transform shape_xform = obj->get_transform() * obj->get_shape_transform(i);
+ Transform3D shape_xform = obj->get_transform() * obj->get_shape_transform(i);
Shape3DSW *shape = obj->get_shape(i);
Vector3 point = shape->get_closest_point_to(shape_xform.affine_inverse().xform(p_point));
@@ -573,7 +573,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
return amount;
}
-int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin) {
+int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin) {
AABB body_aabb;
bool shapes_found = false;
@@ -598,7 +598,7 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform &p_tra
body_aabb = p_transform.xform(p_body->get_inv_transform().xform(body_aabb));
body_aabb = body_aabb.grow(p_margin);
- Transform body_transform = p_transform;
+ Transform3D body_transform = p_transform;
for (int i = 0; i < p_result_max; i++) {
//reset results
@@ -636,7 +636,7 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform &p_tra
continue;
}
- Transform body_shape_xform = body_transform * p_body->get_shape_transform(j);
+ Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
@@ -724,7 +724,7 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform &p_tra
return rays_found;
}
-bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -768,7 +768,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
real_t motion_length = p_motion.length();
Vector3 motion_normal = p_motion / motion_length;
- Transform body_transform = p_from;
+ Transform3D body_transform = p_from;
bool recovered = false;
@@ -797,7 +797,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
continue;
}
- Transform body_shape_xform = body_transform * p_body->get_shape_transform(j);
+ Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) {
continue;
@@ -807,6 +807,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
const CollisionObject3DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
+ if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
+ const Body3DSW *b = static_cast<const Body3DSW *>(col_obj);
+ if (p_infinite_inertia && PhysicsServer3D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer3D::BODY_MODE_KINEMATIC != b->get_mode()) {
+ continue;
+ }
+ }
+
if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
collided = cbk.amount > 0;
}
@@ -868,14 +875,14 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
continue;
}
- Transform body_shape_xform = body_transform * p_body->get_shape_transform(j);
+ Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) {
continue;
}
- Transform body_shape_xform_inv = body_shape_xform.affine_inverse();
+ Transform3D body_shape_xform_inv = body_shape_xform.affine_inverse();
MotionShape3DSW mshape;
mshape.shape = body_shape;
mshape.motion = body_shape_xform_inv.basis.xform(p_motion);
@@ -889,11 +896,18 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
const CollisionObject3DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
+ if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
+ const Body3DSW *b = static_cast<const Body3DSW *>(col_obj);
+ if (p_infinite_inertia && PhysicsServer3D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer3D::BODY_MODE_KINEMATIC != b->get_mode()) {
+ continue;
+ }
+ }
+
//test initial overlap, does it collide if going all the way?
Vector3 point_A, point_B;
Vector3 sep_axis = motion_normal;
- Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) {
continue;
@@ -960,7 +974,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
}
//it collided, let's get the rest info in unsafe advance
- Transform ugt = body_transform;
+ Transform3D ugt = body_transform;
ugt.origin += p_motion * unsafe;
_RestCallbackData rcd;
@@ -979,7 +993,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
continue;
}
- Transform body_shape_xform = ugt * p_body->get_shape_transform(j);
+ Transform3D body_shape_xform = ugt * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) {
@@ -994,6 +1008,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
const CollisionObject3DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
+ if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
+ const Body3DSW *b = static_cast<const Body3DSW *>(col_obj);
+ if (p_infinite_inertia && PhysicsServer3D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer3D::BODY_MODE_KINEMATIC != b->get_mode()) {
+ continue;
+ }
+ }
+
rcd.object = col_obj;
rcd.shape = shape_idx;
bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h
index 3a8f452e54..18e93c90cc 100644
--- a/servers/physics_3d/space_3d_sw.h
+++ b/servers/physics_3d/space_3d_sw.h
@@ -50,10 +50,10 @@ public:
virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override;
- virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
- virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
+ virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override;
PhysicsDirectSpaceState3DSW();
@@ -203,8 +203,8 @@ public:
void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; }
uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
- int test_body_ray_separation(Body3DSW *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin);
- bool test_body_motion(Body3DSW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes);
+ int test_body_ray_separation(Body3DSW *p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin);
+ bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes);
Space3DSW();
~Space3DSW();
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 384179f2c3..faab4f43b8 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -509,12 +509,6 @@ void PhysicsTestMotionResult2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape");
}
-PhysicsTestMotionResult2D::PhysicsTestMotionResult2D() {
- colliding = false;
-
- result.collider_shape = 0;
-}
-
///////////////////////////////////////
bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result) {
@@ -675,6 +669,8 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_active", "active"), &PhysicsServer2D::set_active);
+ ClassDB::bind_method(D_METHOD("set_collision_iterations", "iterations"), &PhysicsServer2D::set_collision_iterations);
+
ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer2D::get_process_info);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS);
@@ -713,8 +709,8 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
- BIND_ENUM_CONSTANT(BODY_MODE_RIGID);
- BIND_ENUM_CONSTANT(BODY_MODE_CHARACTER);
+ BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC);
+ BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LOCKED);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index a5cf3f3a46..df39d6ae50 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -33,7 +33,7 @@
#include "core/io/resource.h"
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
class PhysicsDirectSpaceState2D;
@@ -95,8 +95,8 @@ public:
class PhysicsShapeQueryResult2D;
//used for script
-class PhysicsShapeQueryParameters2D : public Reference {
- GDCLASS(PhysicsShapeQueryParameters2D, Reference);
+class PhysicsShapeQueryParameters2D : public RefCounted {
+ GDCLASS(PhysicsShapeQueryParameters2D, RefCounted);
friend class PhysicsDirectSpaceState2D;
RES shape_ref;
@@ -164,8 +164,8 @@ public:
Vector2 normal;
RID rid;
ObjectID collider_id;
- Object *collider;
- int shape;
+ Object *collider = nullptr;
+ int shape = 0;
Variant metadata;
};
@@ -174,8 +174,8 @@ public:
struct ShapeResult {
RID rid;
ObjectID collider_id;
- Object *collider;
- int shape;
+ Object *collider = nullptr;
+ int shape = 0;
Variant metadata;
};
@@ -193,7 +193,7 @@ public:
Vector2 normal;
RID rid;
ObjectID collider_id;
- int shape;
+ int shape = 0;
Vector2 linear_velocity; //velocity at contact point
Variant metadata;
};
@@ -203,8 +203,8 @@ public:
PhysicsDirectSpaceState2D();
};
-class PhysicsShapeQueryResult2D : public Reference {
- GDCLASS(PhysicsShapeQueryResult2D, Reference);
+class PhysicsShapeQueryResult2D : public RefCounted {
+ GDCLASS(PhysicsShapeQueryResult2D, RefCounted);
Vector<PhysicsDirectSpaceState2D::ShapeResult> result;
@@ -370,8 +370,8 @@ public:
enum BodyMode {
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
- BODY_MODE_RIGID,
- BODY_MODE_CHARACTER
+ BODY_MODE_DYNAMIC,
+ BODY_MODE_DYNAMIC_LOCKED,
};
virtual RID body_create() = 0;
@@ -493,17 +493,11 @@ public:
Vector2 collision_point;
Vector2 collision_normal;
Vector2 collider_velocity;
- int collision_local_shape;
+ int collision_local_shape = 0;
ObjectID collider_id;
RID collider;
- int collider_shape;
+ int collider_shape = 0;
Variant collider_metadata;
-
- MotionResult() {
- collision_local_shape = 0;
- collider_shape = 0;
- collider_id = ObjectID();
- }
};
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
@@ -589,6 +583,8 @@ public:
virtual bool is_flushing_queries() const = 0;
+ virtual void set_collision_iterations(int iterations) = 0;
+
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
INFO_COLLISION_PAIRS,
@@ -601,11 +597,10 @@ public:
~PhysicsServer2D();
};
-class PhysicsTestMotionResult2D : public Reference {
- GDCLASS(PhysicsTestMotionResult2D, Reference);
+class PhysicsTestMotionResult2D : public RefCounted {
+ GDCLASS(PhysicsTestMotionResult2D, RefCounted);
PhysicsServer2D::MotionResult result;
- bool colliding;
friend class PhysicsServer2D;
protected:
@@ -614,7 +609,6 @@ protected:
public:
PhysicsServer2D::MotionResult *get_result_ptr() const { return const_cast<PhysicsServer2D::MotionResult *>(&result); }
- //bool is_colliding() const;
Vector2 get_motion() const;
Vector2 get_motion_remainder() const;
@@ -625,8 +619,6 @@ public:
RID get_collider_rid() const;
Object *get_collider() const;
int get_collider_shape() const;
-
- PhysicsTestMotionResult2D();
};
typedef PhysicsServer2D *(*CreatePhysicsServer2DCallback)();
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 80a9bd4c0b..1634169e8a 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -128,7 +128,7 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform"), "set_transform", "get_transform");
}
PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {}
@@ -156,11 +156,11 @@ RID PhysicsShapeQueryParameters3D::get_shape_rid() const {
return shape;
}
-void PhysicsShapeQueryParameters3D::set_transform(const Transform &p_transform) {
+void PhysicsShapeQueryParameters3D::set_transform(const Transform3D &p_transform) {
transform = p_transform;
}
-Transform PhysicsShapeQueryParameters3D::get_transform() const {
+Transform3D PhysicsShapeQueryParameters3D::get_transform() const {
return transform;
}
@@ -242,7 +242,7 @@ void PhysicsShapeQueryParameters3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::RID, "shape_rid"), "set_shape_rid", "get_shape_rid");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform"), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
}
@@ -458,7 +458,7 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer3D::area_set_space_override_mode);
ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer3D::area_get_space_override_mode);
- ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer3D::area_add_shape, DEFVAL(Transform()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer3D::area_add_shape, DEFVAL(Transform3D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer3D::area_set_shape);
ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer3D::area_set_shape_transform);
ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &PhysicsServer3D::area_set_shape_disabled);
@@ -502,7 +502,7 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer3D::body_set_collision_mask);
ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer3D::body_get_collision_mask);
- ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer3D::body_add_shape, DEFVAL(Transform()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer3D::body_add_shape, DEFVAL(Transform3D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer3D::body_set_shape);
ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer3D::body_set_shape_transform);
ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disabled"), &PhysicsServer3D::body_set_shape_disabled);
@@ -523,9 +523,6 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer3D::body_set_param);
ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer3D::body_get_param);
- ClassDB::bind_method(D_METHOD("body_set_kinematic_safe_margin", "body", "margin"), &PhysicsServer3D::body_set_kinematic_safe_margin);
- ClassDB::bind_method(D_METHOD("body_get_kinematic_safe_margin", "body"), &PhysicsServer3D::body_get_kinematic_safe_margin);
-
ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer3D::body_set_state);
ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer3D::body_get_state);
@@ -717,8 +714,8 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
- BIND_ENUM_CONSTANT(BODY_MODE_RIGID);
- BIND_ENUM_CONSTANT(BODY_MODE_CHARACTER);
+ BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC);
+ BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LOCKED);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index c434109865..d9b805de87 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -59,8 +59,8 @@ public:
virtual void set_angular_velocity(const Vector3 &p_velocity) = 0;
virtual Vector3 get_angular_velocity() const = 0;
- virtual void set_transform(const Transform &p_transform) = 0;
- virtual Transform get_transform() const = 0;
+ virtual void set_transform(const Transform3D &p_transform) = 0;
+ virtual Transform3D get_transform() const = 0;
virtual void add_central_force(const Vector3 &p_force) = 0;
virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
@@ -96,13 +96,13 @@ public:
class PhysicsShapeQueryResult3D;
-class PhysicsShapeQueryParameters3D : public Reference {
- GDCLASS(PhysicsShapeQueryParameters3D, Reference);
+class PhysicsShapeQueryParameters3D : public RefCounted {
+ GDCLASS(PhysicsShapeQueryParameters3D, RefCounted);
friend class PhysicsDirectSpaceState3D;
RES shape_ref;
RID shape;
- Transform transform;
+ Transform3D transform;
real_t margin;
Set<RID> exclude;
uint32_t collision_mask;
@@ -119,8 +119,8 @@ public:
void set_shape_rid(const RID &p_shape);
RID get_shape_rid() const;
- void set_transform(const Transform &p_transform);
- Transform get_transform() const;
+ void set_transform(const Transform3D &p_transform);
+ Transform3D get_transform() const;
void set_margin(real_t p_margin);
real_t get_margin() const;
@@ -157,8 +157,8 @@ public:
struct ShapeResult {
RID rid;
ObjectID collider_id;
- Object *collider;
- int shape;
+ Object *collider = nullptr;
+ int shape = 0;
};
virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
@@ -168,36 +168,36 @@ public:
Vector3 normal;
RID rid;
ObjectID collider_id;
- Object *collider;
- int shape;
+ Object *collider = nullptr;
+ int shape = 0;
};
virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0;
- virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
struct ShapeRestInfo {
Vector3 point;
Vector3 normal;
RID rid;
ObjectID collider_id;
- int shape;
+ int shape = 0;
Vector3 linear_velocity; //velocity at contact point
};
- virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0;
+ virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0;
- virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
- virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0;
PhysicsDirectSpaceState3D();
};
-class PhysicsShapeQueryResult3D : public Reference {
- GDCLASS(PhysicsShapeQueryResult3D, Reference);
+class PhysicsShapeQueryResult3D : public RefCounted {
+ GDCLASS(PhysicsShapeQueryResult3D, RefCounted);
Vector<PhysicsDirectSpaceState3D::ShapeResult> result;
@@ -335,13 +335,13 @@ public:
virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0;
virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0;
- virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0;
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) = 0;
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0;
- virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) = 0;
+ virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) = 0;
virtual int area_get_shape_count(RID p_area) const = 0;
virtual RID area_get_shape(RID p_area, int p_shape_idx) const = 0;
- virtual Transform area_get_shape_transform(RID p_area, int p_shape_idx) const = 0;
+ virtual Transform3D area_get_shape_transform(RID p_area, int p_shape_idx) const = 0;
virtual void area_remove_shape(RID p_area, int p_shape_idx) = 0;
virtual void area_clear_shapes(RID p_area) = 0;
@@ -352,10 +352,10 @@ public:
virtual ObjectID area_get_object_instance_id(RID p_area) const = 0;
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0;
- virtual void area_set_transform(RID p_area, const Transform &p_transform) = 0;
+ virtual void area_set_transform(RID p_area, const Transform3D &p_transform) = 0;
virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const = 0;
- virtual Transform area_get_transform(RID p_area) const = 0;
+ virtual Transform3D area_get_transform(RID p_area) const = 0;
virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0;
virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) = 0;
@@ -374,8 +374,8 @@ public:
enum BodyMode {
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
- BODY_MODE_RIGID,
- BODY_MODE_CHARACTER
+ BODY_MODE_DYNAMIC,
+ BODY_MODE_DYNAMIC_LOCKED,
};
virtual RID body_create() = 0;
@@ -386,13 +386,13 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0;
virtual BodyMode body_get_mode(RID p_body) const = 0;
- virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0;
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) = 0;
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0;
- virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) = 0;
+ virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) = 0;
virtual int body_get_shape_count(RID p_body) const = 0;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const = 0;
- virtual Transform body_get_shape_transform(RID p_body, int p_shape_idx) const = 0;
+ virtual Transform3D body_get_shape_transform(RID p_body, int p_shape_idx) const = 0;
virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0;
virtual void body_clear_shapes(RID p_body) = 0;
@@ -428,9 +428,6 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) = 0;
virtual real_t body_get_param(RID p_body, BodyParameter p_param) const = 0;
- virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) = 0;
- virtual real_t body_get_kinematic_safe_margin(RID p_body) const = 0;
-
//state
enum BodyState {
BODY_STATE_TRANSFORM,
@@ -500,19 +497,14 @@ public:
Vector3 collision_point;
Vector3 collision_normal;
Vector3 collider_velocity;
- int collision_local_shape;
+ int collision_local_shape = 0;
ObjectID collider_id;
RID collider;
- int collider_shape;
+ int collider_shape = 0;
Variant collider_metadata;
- MotionResult() {
- collision_local_shape = 0;
- collider_id = ObjectID();
- collider_shape = 0;
- }
};
- virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
+ virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
struct SeparationResult {
real_t collision_depth;
@@ -526,7 +518,7 @@ public:
Variant collider_metadata;
};
- virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) = 0;
+ virtual int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) = 0;
/* SOFT BODY */
@@ -554,7 +546,7 @@ public:
virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0;
virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const = 0;
- virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) = 0;
+ virtual void soft_body_set_transform(RID p_body, const Transform3D &p_transform) = 0;
virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) = 0;
@@ -642,7 +634,7 @@ public:
HINGE_JOINT_FLAG_MAX
};
- virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) = 0;
+ virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_hinge_A, RID p_body_B, const Transform3D &p_hinge_B) = 0;
virtual void joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) = 0;
virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) = 0;
@@ -679,7 +671,7 @@ public:
};
- virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+ virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) = 0; //reference frame is A
virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) = 0;
virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const = 0;
@@ -693,7 +685,7 @@ public:
CONE_TWIST_MAX
};
- virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+ virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) = 0; //reference frame is A
virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) = 0;
virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const = 0;
@@ -734,7 +726,7 @@ public:
G6DOF_JOINT_FLAG_MAX
};
- virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+ virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) = 0; //reference frame is A
virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value) = 0;
virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) const = 0;
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
new file mode 100644
index 0000000000..b44088e822
--- /dev/null
+++ b/servers/rendering/rasterizer_dummy.h
@@ -0,0 +1,787 @@
+/*************************************************************************/
+/* rasterizer_dummy.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RASTERIZER_DUMMY_H
+#define RASTERIZER_DUMMY_H
+
+#include "core/math/camera_matrix.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "scene/resources/mesh.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering_server.h"
+
+class RasterizerSceneDummy : public RendererSceneRender {
+public:
+ GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
+ void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
+ void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
+ void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
+ void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
+ void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
+ void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
+ void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
+ void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+ void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+ void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
+ void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
+ void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
+ void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+
+ uint32_t geometry_instance_get_pair_mask() override { return 0; }
+ void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
+ void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
+ void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
+ void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
+
+ void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
+
+ /* SHADOW ATLAS API */
+
+ RID shadow_atlas_create() override { return RID(); }
+ void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) override {}
+ void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {}
+ bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; }
+
+ void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) override {}
+ int get_directional_light_shadow_size(RID p_light_intance) override { return 0; }
+ void set_directional_shadow_count(int p_count) override {}
+
+ /* SDFGI UPDATE */
+
+ void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
+ int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
+ AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
+ uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
+
+ /* SKY API */
+
+ RID sky_allocate() override { return RID(); }
+ void sky_initialize(RID p_rid) override {}
+ void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {}
+ void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {}
+ void sky_set_material(RID p_sky, RID p_material) override {}
+ Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
+
+ /* ENVIRONMENT API */
+
+ RID environment_allocate() override { return RID(); }
+ void environment_initialize(RID p_rid) override {}
+ void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
+ void environment_set_sky(RID p_env, RID p_sky) override {}
+ void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
+ void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {}
+ void environment_set_bg_color(RID p_env, const Color &p_color) override {}
+ void environment_set_bg_energy(RID p_env, float p_energy) override {}
+ void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
+ void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) override {}
+
+ void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override {}
+ void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
+ void environment_glow_set_use_high_quality(bool p_enable) override {}
+
+ void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {}
+ void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
+ void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {}
+ void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
+
+ void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
+
+ void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
+ void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
+ void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {}
+
+ void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {}
+
+ void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
+
+ void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override {}
+ void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
+ void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
+
+ Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
+
+ bool is_environment(RID p_env) const override { return false; }
+ RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
+ int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
+
+ RID camera_effects_allocate() override { return RID(); }
+ void camera_effects_initialize(RID p_rid) override {}
+ void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
+ void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {}
+
+ void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {}
+ void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {}
+
+ void shadows_quality_set(RS::ShadowQuality p_quality) override {}
+ void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {}
+
+ RID light_instance_create(RID p_light) override { return RID(); }
+ void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
+ void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
+ void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
+ void light_instance_mark_visible(RID p_light_instance) override {}
+
+ RID reflection_atlas_create() override { return RID(); }
+ int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
+ void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
+
+ RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
+ void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
+ void reflection_probe_release_atlas_index(RID p_instance) override {}
+ bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
+ bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
+ bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
+ bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
+
+ RID decal_instance_create(RID p_decal) override { return RID(); }
+ void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
+
+ RID lightmap_instance_create(RID p_lightmap) override { return RID(); }
+ void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {}
+
+ RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); }
+ void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {}
+ bool voxel_gi_needs_update(RID p_probe) const override { return false; }
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
+
+ void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
+
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) override {}
+ void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
+ void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
+
+ void set_scene_pass(uint64_t p_pass) override {}
+ void set_time(double p_time, double p_step) override {}
+ void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
+
+ RID render_buffers_create() override { return RID(); }
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
+ void gi_set_use_half_resolution(bool p_enable) override {}
+
+ void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
+ bool screen_space_roughness_limiter_is_active() const override { return false; }
+
+ void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
+ void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
+
+ TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
+
+ bool free(RID p_rid) override { return true; }
+ void update() override {}
+ void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
+
+ RasterizerSceneDummy() {}
+ ~RasterizerSceneDummy() {}
+};
+
+class RasterizerStorageDummy : public RendererStorage {
+public:
+ bool can_create_resources_async() const override { return false; }
+
+ /* TEXTURE API */
+ struct DummyTexture {
+ Ref<Image> image;
+ };
+ mutable RID_PtrOwner<DummyTexture> texture_owner;
+
+ RID texture_allocate() override {
+ DummyTexture *texture = memnew(DummyTexture);
+ ERR_FAIL_COND_V(!texture, RID());
+ return texture_owner.make_rid(texture);
+ }
+ void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
+ DummyTexture *t = texture_owner.getornull(p_texture);
+ ERR_FAIL_COND(!t);
+ t->image = p_image->duplicate();
+ }
+
+ void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {}
+ void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
+ void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
+ void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
+ void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
+ void texture_proxy_initialize(RID p_texture, RID p_base) override {}
+ void texture_proxy_update(RID p_proxy, RID p_base) override {}
+
+ void texture_2d_placeholder_initialize(RID p_texture) override {}
+ void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {}
+ void texture_3d_placeholder_initialize(RID p_texture) override {}
+
+ Ref<Image> texture_2d_get(RID p_texture) const override {
+ DummyTexture *t = texture_owner.getornull(p_texture);
+ ERR_FAIL_COND_V(!t, Ref<Image>());
+ return t->image;
+ }
+
+ Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
+ Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
+
+ void texture_replace(RID p_texture, RID p_by_texture) override {}
+ void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
+
+ void texture_set_path(RID p_texture, const String &p_path) override {}
+ String texture_get_path(RID p_texture) const override { return String(); }
+
+ void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {}
+ void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {}
+ void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {}
+
+ void texture_debug_usage(List<RS::TextureInfo> *r_info) override {}
+ void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {}
+ Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }
+
+ void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+ void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+
+ /* CANVAS TEXTURE API */
+
+ RID canvas_texture_allocate() override { return RID(); }
+ void canvas_texture_initialize(RID p_rid) override {}
+ void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {}
+ void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {}
+
+ void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {}
+ void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {}
+
+ /* SHADER API */
+
+ RID shader_allocate() override { return RID(); }
+ void shader_initialize(RID p_rid) override {}
+ void shader_set_code(RID p_shader, const String &p_code) override {}
+ String shader_get_code(RID p_shader) const override { return ""; }
+ void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
+
+ void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override {}
+ RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override { return RID(); }
+ Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+ RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
+
+ /* COMMON MATERIAL API */
+
+ RID material_allocate() override { return RID(); }
+ void material_initialize(RID p_rid) override {}
+ void material_set_render_priority(RID p_material, int priority) override {}
+ void material_set_shader(RID p_shader_material, RID p_shader) override {}
+
+ void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {}
+ Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+ void material_set_next_pass(RID p_material, RID p_next_material) override {}
+
+ bool material_is_animated(RID p_material) override { return false; }
+ bool material_casts_shadows(RID p_material) override { return false; }
+ void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
+ void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
+
+ /* MESH API */
+
+ RID mesh_allocate() override { return RID(); }
+ void mesh_initialize(RID p_rid) override {}
+ void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
+ bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
+ RID mesh_instance_create(RID p_base) override { return RID(); }
+ void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
+ void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
+ void mesh_instance_check_for_update(RID p_mesh_instance) override {}
+ void update_mesh_instances() override {}
+ void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) override {}
+ float reflection_probe_get_lod_threshold(RID p_probe) const override { return 0.0; }
+
+ void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
+
+ int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
+
+ void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
+ RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
+
+ void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+
+ void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
+ RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
+
+ RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
+ int mesh_get_surface_count(RID p_mesh) const override { return 0; }
+
+ void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
+ AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
+
+ AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
+ void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
+ void mesh_clear(RID p_mesh) override {}
+
+ /* MULTIMESH API */
+
+ RID multimesh_allocate() override { return RID(); }
+ void multimesh_initialize(RID p_rid) override {}
+ void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
+ int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
+
+ void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
+ void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {}
+ void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {}
+ void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {}
+ void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {}
+
+ RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); }
+ AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); }
+
+ Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); }
+ Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); }
+ Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
+ Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
+ void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {}
+ Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); }
+
+ void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
+ int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
+
+ /* IMMEDIATE API */
+
+ RID immediate_allocate() override { return RID(); }
+ void immediate_initialize(RID p_rid) override {}
+ void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) override {}
+ void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) override {}
+ void immediate_normal(RID p_immediate, const Vector3 &p_normal) override {}
+ void immediate_tangent(RID p_immediate, const Plane &p_tangent) override {}
+ void immediate_color(RID p_immediate, const Color &p_color) override {}
+ void immediate_uv(RID p_immediate, const Vector2 &tex_uv) override {}
+ void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) override {}
+ void immediate_end(RID p_immediate) override {}
+ void immediate_clear(RID p_immediate) override {}
+ void immediate_set_material(RID p_immediate, RID p_material) override {}
+ RID immediate_get_material(RID p_immediate) const override { return RID(); }
+ AABB immediate_get_aabb(RID p_immediate) const override { return AABB(); }
+
+ /* SKELETON API */
+
+ RID skeleton_allocate() override { return RID(); }
+ void skeleton_initialize(RID p_rid) override {}
+ void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
+ void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
+ int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
+ void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {}
+ Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); }
+ void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
+ Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
+
+ /* Light API */
+
+ RID directional_light_allocate() override { return RID(); }
+ void directional_light_initialize(RID p_rid) override {}
+ RID omni_light_allocate() override { return RID(); }
+ void omni_light_initialize(RID p_rid) override {}
+ RID spot_light_allocate() override { return RID(); }
+ void spot_light_initialize(RID p_rid) override {}
+ RID reflection_probe_allocate() override { return RID(); }
+ void reflection_probe_initialize(RID p_rid) override {}
+
+ void light_set_color(RID p_light, const Color &p_color) override {}
+ void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
+ void light_set_shadow(RID p_light, bool p_enabled) override {}
+ void light_set_shadow_color(RID p_light, const Color &p_color) override {}
+ void light_set_projector(RID p_light, RID p_texture) override {}
+ void light_set_negative(RID p_light, bool p_enable) override {}
+ void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
+ void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
+ void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
+ void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
+
+ void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {}
+
+ void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
+ void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
+ bool light_directional_get_blend_splits(RID p_light) const override { return false; }
+ void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) override {}
+ void light_directional_set_sky_only(RID p_light, bool p_sky_only) override {}
+ bool light_directional_is_sky_only(RID p_light) const override { return false; }
+ RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; }
+
+ RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
+ RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
+
+ bool light_has_shadow(RID p_light) const override { return false; }
+
+ RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
+ AABB light_get_aabb(RID p_light) const override { return AABB(); }
+ float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; }
+ Color light_get_color(RID p_light) override { return Color(); }
+ RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; }
+ uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
+ uint64_t light_get_version(RID p_light) const override { return 0; }
+
+ /* PROBE API */
+
+ void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
+ void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
+ void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
+ void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {}
+ void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {}
+ void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {}
+ void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {}
+ void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {}
+ void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {}
+ void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {}
+ void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
+ void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
+ void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
+
+ AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
+ RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
+ uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
+ Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); }
+ Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); }
+ float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
+ bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
+
+ void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
+ void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
+
+ /* DECAL API */
+
+ RID decal_allocate() override { return RID(); }
+ void decal_initialize(RID p_rid) override {}
+ void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
+ void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
+ void decal_set_emission_energy(RID p_decal, float p_energy) override {}
+ void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
+ void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
+ void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
+ void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
+ void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
+ void decal_set_normal_fade(RID p_decal, float p_fade) override {}
+
+ AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
+
+ /* VOXEL GI API */
+
+ RID voxel_gi_allocate() override { return RID(); }
+ void voxel_gi_initialize(RID p_rid) override {}
+ void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override {}
+
+ AABB voxel_gi_get_bounds(RID p_voxel_gi) const override { return AABB(); }
+ Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override { return Vector3i(); }
+ Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+ Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+ Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+
+ Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override { return Vector<int>(); }
+ Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override { return Transform3D(); }
+
+ void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override { return 0; }
+
+ void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_propagation(RID p_voxel_gi) const override { return 0; }
+
+ void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; }
+
+ void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) override {}
+ float voxel_gi_get_ao(RID p_voxel_gi) const override { return 0; }
+
+ void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) override {}
+ float voxel_gi_get_ao_size(RID p_voxel_gi) const override { return 0; }
+
+ void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; }
+
+ void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_normal_bias(RID p_voxel_gi) const override { return 0.0; }
+
+ void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override {}
+ bool voxel_gi_is_interior(RID p_voxel_gi) const override { return false; }
+
+ void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {}
+ bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; }
+
+ void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override {}
+ float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override { return 0; }
+
+ uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; }
+
+ /* LIGHTMAP CAPTURE */
+ RID lightmap_allocate() override { return RID(); }
+ void lightmap_initialize(RID p_rid) override {}
+ void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
+ void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
+ void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
+ void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {}
+ PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
+ PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
+ PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
+ PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); }
+ AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); }
+ void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {}
+ bool lightmap_is_interior(RID p_lightmap) const override { return false; }
+ void lightmap_set_probe_capture_update_speed(float p_speed) override {}
+ float lightmap_get_probe_capture_update_speed() const override { return 0; }
+
+ /* OCCLUDER */
+
+ void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
+
+ /* PARTICLES */
+
+ RID particles_allocate() override { return RID(); }
+ void particles_initialize(RID p_rid) override {}
+ void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {}
+ void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
+ void particles_set_emitting(RID p_particles, bool p_emitting) override {}
+ void particles_set_amount(RID p_particles, int p_amount) override {}
+ void particles_set_lifetime(RID p_particles, float p_lifetime) override {}
+ void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
+ void particles_set_pre_process_time(RID p_particles, float p_time) override {}
+ void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) override {}
+ void particles_set_randomness_ratio(RID p_particles, float p_ratio) override {}
+ void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
+ void particles_set_speed_scale(RID p_particles, float p_scale) override {}
+ void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
+ void particles_set_process_material(RID p_particles, RID p_material) override {}
+ void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
+ void particles_set_interpolate(RID p_particles, bool p_enable) override {}
+ void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
+ void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
+ void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
+ void particles_set_collision_base_size(RID p_particles, float p_size) override {}
+
+ void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
+
+ void particles_set_trails(RID p_particles, bool p_enable, float p_length) override {}
+ void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
+
+ void particles_restart(RID p_particles) override {}
+
+ void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {}
+
+ void particles_set_draw_passes(RID p_particles, int p_count) override {}
+ void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {}
+
+ void particles_request_process(RID p_particles) override {}
+ AABB particles_get_current_aabb(RID p_particles) override { return AABB(); }
+ AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
+
+ void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
+
+ bool particles_get_emitting(RID p_particles) override { return false; }
+ int particles_get_draw_passes(RID p_particles) const override { return 0; }
+ RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); }
+
+ void particles_add_collision(RID p_particles, RID p_instance) override {}
+ void particles_remove_collision(RID p_particles, RID p_instance) override {}
+
+ void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
+
+ void update_particles() override {}
+
+ /* PARTICLES COLLISION */
+
+ RID particles_collision_allocate() override { return RID(); }
+ void particles_collision_initialize(RID p_rid) override {}
+ void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
+ void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
+ void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) override {}
+ void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
+ void particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) override {}
+ void particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) override {}
+ void particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) override {}
+ void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
+ void particles_collision_height_field_update(RID p_particles_collision) override {}
+ void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
+ AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
+ bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
+ RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
+
+ RID particles_collision_instance_create(RID p_collision) override { return RID(); };
+ void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override{};
+ void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override{};
+
+ /* GLOBAL VARIABLES */
+
+ void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
+ void global_variable_remove(const StringName &p_name) override {}
+ Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
+
+ void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
+ void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
+ Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
+ RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
+
+ void global_variables_load_settings(bool p_load_textures = true) override {}
+ void global_variables_clear() override {}
+
+ int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
+ void global_variables_instance_free(RID p_instance) override {}
+ void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
+
+ bool particles_is_inactive(RID p_particles) const override { return false; }
+
+ /* RENDER TARGET */
+
+ RID render_target_create() override { return RID(); }
+ void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
+ void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
+ RID render_target_get_texture(RID p_render_target) override { return RID(); }
+ void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
+ void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
+ bool render_target_was_used(RID p_render_target) override { return false; }
+ void render_target_set_as_unused(RID p_render_target) override {}
+
+ void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
+ bool render_target_is_clear_requested(RID p_render_target) override { return false; }
+ Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); }
+ void render_target_disable_clear_request(RID p_render_target) override {}
+ void render_target_do_clear_request(RID p_render_target) override {}
+
+ void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
+ Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
+ void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
+
+ RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
+ bool free(RID p_rid) override {
+ if (texture_owner.owns(p_rid)) {
+ // delete the texture
+ DummyTexture *texture = texture_owner.getornull(p_rid);
+ texture_owner.free(p_rid);
+ memdelete(texture);
+ }
+ return true;
+ }
+
+ bool has_os_feature(const String &p_feature) const override { return false; }
+
+ void update_dirty_resources() override {}
+
+ void set_debug_generate_wireframes(bool p_generate) override {}
+
+ void render_info_begin_capture() override {}
+ void render_info_end_capture() override {}
+ int get_captured_render_info(RS::RenderInfo p_info) override { return 0; }
+
+ uint64_t get_render_info(RS::RenderInfo p_info) override { return 0; }
+ String get_video_adapter_name() const override { return String(); }
+ String get_video_adapter_vendor() const override { return String(); }
+
+ static RendererStorage *base_singleton;
+
+ void capture_timestamps_begin() override {}
+ void capture_timestamp(const String &p_name) override {}
+ uint32_t get_captured_timestamps_count() const override { return 0; }
+ uint64_t get_captured_timestamps_frame() const override { return 0; }
+ uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; }
+ uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; }
+ String get_captured_timestamp_name(uint32_t p_index) const override { return String(); }
+
+ RasterizerStorageDummy() {}
+ ~RasterizerStorageDummy() {}
+};
+
+class RasterizerCanvasDummy : public RendererCanvasRender {
+public:
+ PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; }
+ void free_polygon(PolygonID p_polygon) override {}
+
+ void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {}
+ void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {}
+
+ RID light_create() override { return RID(); }
+ void light_set_texture(RID p_rid, RID p_texture) override {}
+ void light_set_use_shadow(RID p_rid, bool p_enable) override {}
+ void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {}
+ void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {}
+
+ void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {}
+ RID occluder_polygon_create() override { return RID(); }
+ void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {}
+ void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {}
+ void set_shadow_texture_size(int p_size) override {}
+
+ void draw_window_margins(int *p_margins, RID *p_margin_textures) override {}
+
+ bool free(RID p_rid) override { return true; }
+ void update() override {}
+
+ RasterizerCanvasDummy() {}
+ ~RasterizerCanvasDummy() {}
+};
+
+class RasterizerDummy : public RendererCompositor {
+private:
+ uint64_t frame = 1;
+ float delta = 0;
+
+protected:
+ RasterizerCanvasDummy canvas;
+ RasterizerStorageDummy storage;
+ RasterizerSceneDummy scene;
+
+public:
+ RendererStorage *get_storage() override { return &storage; }
+ RendererCanvasRender *get_canvas() override { return &canvas; }
+ RendererSceneRender *get_scene() override { return &scene; }
+
+ void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {}
+
+ void initialize() override {}
+ void begin_frame(double frame_step) override {
+ frame++;
+ delta = frame_step;
+ }
+
+ void prepare_for_blitting_render_targets() override {}
+ void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {}
+
+ void end_frame(bool p_swap_buffers) override {
+ if (p_swap_buffers) {
+ DisplayServer::get_singleton()->swap_buffers();
+ }
+ }
+
+ void finalize() override {}
+
+ static RendererCompositor *_create_current() {
+ return memnew(RasterizerDummy);
+ }
+
+ static void make_current() {
+ _create_func = _create_current;
+ }
+
+ bool is_low_end() const override { return true; }
+ uint64_t get_frame_number() const override { return frame; }
+ float get_frame_delta_time() const override { return delta; }
+
+ RasterizerDummy() {}
+ ~RasterizerDummy() {}
+};
+
+#endif // RASTERIZER_DUMMY_H
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 67003a6f64..6e126ea77e 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -44,10 +44,10 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas
memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *));
for (int i = 0; i < p_child_item_count; i++) {
- _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr);
+ _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true);
}
if (p_canvas_item) {
- _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr);
+ _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true);
}
RendererCanvasRender::Item *list = nullptr;
@@ -104,98 +104,7 @@ void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<Rende
} while (ysort_owner && ysort_owner->sort_y);
}
-void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) {
- Item *ci = p_canvas_item;
-
- if (!ci->visible) {
- return;
- }
-
- if (ci->children_order_dirty) {
- ci->child_items.sort_custom<ItemIndexSort>();
- ci->children_order_dirty = false;
- }
-
- Rect2 rect = ci->get_rect();
- Transform2D xform = ci->xform;
- if (snapping_2d_transforms_to_pixel) {
- xform.elements[2] = xform.elements[2].floor();
- }
- xform = p_transform * xform;
-
- Rect2 global_rect = xform.xform(rect);
- global_rect.position += p_clip_rect.position;
-
- if (ci->use_parent_material && p_material_owner) {
- ci->material_owner = p_material_owner;
- } else {
- p_material_owner = ci;
- ci->material_owner = nullptr;
- }
-
- Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a);
-
- if (modulate.a < 0.007) {
- return;
- }
-
- int child_item_count = ci->child_items.size();
- Item **child_items = ci->child_items.ptrw();
-
- if (ci->clip) {
- if (p_canvas_clip != nullptr) {
- ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect);
- } else {
- ci->final_clip_rect = global_rect;
- }
- ci->final_clip_rect.position = ci->final_clip_rect.position.round();
- ci->final_clip_rect.size = ci->final_clip_rect.size.round();
- ci->final_clip_owner = ci;
-
- } else {
- ci->final_clip_owner = p_canvas_clip;
- }
-
- if (ci->sort_y) {
- if (ci->ysort_children_count == -1) {
- ci->ysort_children_count = 0;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count);
- }
-
- child_item_count = ci->ysort_children_count;
- child_items = (Item **)alloca(child_item_count * sizeof(Item *));
-
- int i = 0;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i);
-
- SortArray<Item *, ItemPtrSort> sorter;
- sorter.sort(child_items, child_item_count);
- }
-
- if (ci->z_relative) {
- p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
- } else {
- p_z = ci->z_index;
- }
-
- RendererCanvasRender::Item *canvas_group_from = nullptr;
- bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
- if (use_canvas_group) {
- int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
- canvas_group_from = z_last_list[zidx];
- }
-
- for (int i = 0; i < child_item_count; i++) {
- if ((!child_items[i]->behind && !use_canvas_group) || (ci->sort_y && child_items[i]->sort_y)) {
- continue;
- }
- if (ci->sort_y) {
- _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
- } else {
- _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
- }
- }
-
+void _attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from) {
if (ci->copy_back_buffer) {
ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect);
}
@@ -229,7 +138,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
// We have two choices now, if user has drawn something, we must assume users wants to draw the "mask", so compute the size based on this.
// If nothing has been drawn, we just take it over and draw it ourselves.
if (ci->canvas_group->fit_empty && (ci->commands == nullptr ||
- (ci->commands->next == nullptr && ci->commands->type == Item::Command::TYPE_RECT && (static_cast<Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
+ (ci->commands->next == nullptr && ci->commands->type == RendererCanvasCull::Item::Command::TYPE_RECT && (static_cast<RendererCanvasCull::Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
// No commands, or sole command is the one used to draw, so we (re)create the draw command.
ci->clear();
@@ -291,15 +200,117 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
ci->next = nullptr;
}
+}
- for (int i = 0; i < child_item_count; i++) {
- if (child_items[i]->behind || use_canvas_group || (ci->sort_y && child_items[i]->sort_y)) {
- continue;
+void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort) {
+ Item *ci = p_canvas_item;
+
+ if (!ci->visible) {
+ return;
+ }
+
+ if (ci->children_order_dirty) {
+ ci->child_items.sort_custom<ItemIndexSort>();
+ ci->children_order_dirty = false;
+ }
+
+ Rect2 rect = ci->get_rect();
+ Transform2D xform = ci->xform;
+ if (snapping_2d_transforms_to_pixel) {
+ xform.elements[2] = xform.elements[2].floor();
+ }
+ xform = p_transform * xform;
+
+ Rect2 global_rect = xform.xform(rect);
+ global_rect.position += p_clip_rect.position;
+
+ if (ci->use_parent_material && p_material_owner) {
+ ci->material_owner = p_material_owner;
+ } else {
+ p_material_owner = ci;
+ ci->material_owner = nullptr;
+ }
+
+ Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a);
+
+ if (modulate.a < 0.007) {
+ return;
+ }
+
+ int child_item_count = ci->child_items.size();
+ Item **child_items = ci->child_items.ptrw();
+
+ if (ci->clip) {
+ if (p_canvas_clip != nullptr) {
+ ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect);
+ } else {
+ ci->final_clip_rect = global_rect;
}
- if (ci->sort_y) {
- _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
+ ci->final_clip_rect.position = ci->final_clip_rect.position.round();
+ ci->final_clip_rect.size = ci->final_clip_rect.size.round();
+ ci->final_clip_owner = ci;
+
+ } else {
+ ci->final_clip_owner = p_canvas_clip;
+ }
+
+ if (ci->z_relative) {
+ p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
+ } else {
+ p_z = ci->z_index;
+ }
+
+ if (ci->sort_y) {
+ if (allow_y_sort) {
+ if (ci->ysort_children_count == -1) {
+ ci->ysort_children_count = 0;
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count);
+ }
+
+ child_item_count = ci->ysort_children_count + 1;
+ child_items = (Item **)alloca(child_item_count * sizeof(Item *));
+
+ child_items[0] = ci;
+ int i = 1;
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i);
+ ci->ysort_xform = ci->xform.affine_inverse();
+
+ SortArray<Item *, ItemPtrSort> sorter;
+ sorter.sort(child_items, child_item_count);
+
+ for (i = 0; i < child_item_count; i++) {
+ _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false);
+ }
} else {
- _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ RendererCanvasRender::Item *canvas_group_from = nullptr;
+ bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
+ if (use_canvas_group) {
+ int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
+ canvas_group_from = z_last_list[zidx];
+ }
+
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
+ }
+ } else {
+ RendererCanvasRender::Item *canvas_group_from = nullptr;
+ bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
+ if (use_canvas_group) {
+ int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
+ canvas_group_from = z_last_list[zidx];
+ }
+
+ for (int i = 0; i < child_item_count; i++) {
+ if (!child_items[i]->behind && !use_canvas_group) {
+ continue;
+ }
+ _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
+ }
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
+ for (int i = 0; i < child_item_count; i++) {
+ if (child_items[i]->behind || use_canvas_group) {
+ continue;
+ }
+ _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
}
}
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index b71f8e5a9a..37391d7c0e 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -158,7 +158,7 @@ public:
private:
void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel);
- void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner);
+ void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort);
RendererCanvasRender::Item **z_list;
RendererCanvasRender::Item **z_last_list;
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 0e9ef616cb..0266e137c0 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -420,7 +420,6 @@ public:
if (found_xform) {
r = xf.xform(r);
- found_xform = false;
}
if (first) {
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index 8861522d34..80c4625261 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -30,6 +30,7 @@
#include "renderer_compositor.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -39,4 +40,12 @@ RendererCompositor *RendererCompositor::create() {
return _create_func();
}
+bool RendererCompositor::is_xr_enabled() const {
+ return xr_enabled;
+}
+
+RendererCompositor::RendererCompositor() {
+ xr_enabled = GLOBAL_GET("rendering/xr/enabled");
+}
+
RendererCanvasRender *RendererCanvasRender::singleton = nullptr;
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 41aaba0f4c..eabdebf4b3 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -40,7 +40,31 @@
#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
+struct BlitToScreen {
+ RID render_target;
+ Rect2i rect;
+
+ struct {
+ bool use_layer = false;
+ uint32_t layer = 0;
+ } multi_view;
+
+ struct {
+ //lens distorted parameters for VR
+ bool apply = false;
+ Vector2 eye_center;
+ float k1 = 0.0;
+ float k2 = 0.0;
+
+ float upscale = 1.0;
+ float aspect_ratio = 1.0;
+ } lens_distortion;
+};
+
class RendererCompositor {
+private:
+ bool xr_enabled = false;
+
protected:
static RendererCompositor *(*_create_func)();
@@ -56,27 +80,6 @@ public:
virtual void initialize() = 0;
virtual void begin_frame(double frame_step) = 0;
- struct BlitToScreen {
- RID render_target;
- Rect2i rect;
-
- struct {
- bool use_layer = false;
- uint32_t layer = 0;
- } multi_view;
-
- struct {
- //lens distorted parameters for VR
- bool apply = false;
- Vector2 eye_center;
- float k1 = 0.0;
- float k2 = 0.0;
-
- float upscale = 1.0;
- float aspect_ratio = 1.0;
- } lens_distortion;
- };
-
virtual void prepare_for_blitting_render_targets() = 0;
virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0;
@@ -86,7 +89,9 @@ public:
virtual float get_frame_delta_time() const = 0;
virtual bool is_low_end() const = 0;
+ virtual bool is_xr_enabled() const;
+ RendererCompositor();
virtual ~RendererCompositor() {}
};
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 2669a73014..b952ecbff0 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -374,7 +374,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
}
}
-void ClusterBuilderRD::begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y) {
+void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y) {
view_xform = p_view_transform.affine_inverse();
projection = p_cam_projection;
z_near = projection.get_z_near();
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index dc1707b534..ebb81abdad 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -167,7 +167,7 @@ private:
uint32_t render_element_count = 0;
uint32_t render_element_max = 0;
- Transform view_xform;
+ Transform3D view_xform;
CameraMatrix adjusted_projection;
CameraMatrix projection;
float z_far = 0;
@@ -220,9 +220,9 @@ private:
public:
void setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer);
- void begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y);
+ void begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y);
- _FORCE_INLINE_ void add_light(LightType p_type, const Transform &p_transform, float p_radius, float p_spot_aperture) {
+ _FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) {
if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) {
return; //max number elements reached
}
@@ -232,7 +232,7 @@ public:
RenderElementData &e = render_elements[render_element_count];
- Transform xform = view_xform * p_transform;
+ Transform3D xform = view_xform * p_transform;
float radius = xform.basis.get_uniform_scale();
if (radius > 0.98 || radius < 1.02) {
@@ -317,7 +317,7 @@ public:
render_element_count++;
}
- _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform &p_transform, const Vector3 &p_half_extents) {
+ _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform3D &p_transform, const Vector3 &p_half_extents) {
if (p_box_type == BOX_TYPE_DECAL && cluster_count_by_type[ELEMENT_TYPE_DECAL] == max_elements_by_type) {
return; //max number elements reached
}
@@ -326,7 +326,7 @@ public:
}
RenderElementData &e = render_elements[render_element_count];
- Transform xform = view_xform * p_transform;
+ Transform3D xform = view_xform * p_transform;
//extract scale and scale the matrix by it, makes things simpler
Vector3 scale = p_half_extents;
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 563e08fdcb..4fd5520e56 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -34,6 +34,7 @@
#include "core/math/math_defs.h"
#include "core/os/os.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "thirdparty/misc/cubemap_coeffs.h"
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) {
@@ -732,6 +733,11 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
+ if (p_settings.view_count > 1) {
+ // Use MULTIVIEW versions
+ mode += 4;
+ }
+
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
@@ -934,10 +940,10 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, ssao.gather_uniform_set, 0);
+void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, ssao.importance_map_uniform_set, 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
}
for (int i = 0; i < 4; i++) {
@@ -960,7 +966,7 @@ void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
}
-void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &p_depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets) {
+void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &p_depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_downsample_uniform_set, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->draw_command_begin_label("SSAO");
/* FIRST PASS */
@@ -990,7 +996,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
u.ids.push_back(p_depth_mipmaps[3]);
uniforms.push_back(u);
}
- ssao.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, 2), 2);
+ r_downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, 2), 2);
}
float depth_linearize_mul = -p_projection.matrix[3][2];
@@ -1025,7 +1031,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[0]), 1);
if (p_settings.quality > RS::ENV_SSAO_QUALITY_MEDIUM) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.downsample_uniform_set, 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, r_downsample_uniform_set, 2);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.downsample_push_constant, sizeof(SSAODownsamplePushConstant));
@@ -1109,7 +1115,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
u.ids.push_back(ssao.gather_constants_buffer);
uniforms.push_back(u);
}
- ssao.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
+ r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
}
if (p_invalidate_uniform_sets) {
@@ -1136,7 +1142,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
u.ids.push_back(ssao.importance_map_load_counter);
uniforms.push_back(u);
}
- ssao.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
+ r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
}
if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
@@ -1147,7 +1153,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
ssao.importance_map_push_constant.power = p_settings.power;
//base pass
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
- gather_ssao(compute_list, p_ao_pong_slices, p_settings, true);
+ gather_ssao(compute_list, p_ao_pong_slices, p_settings, true, r_gather_uniform_set, RID());
//generate importance map
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
@@ -1178,7 +1184,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
}
- gather_ssao(compute_list, p_ao_slices, p_settings, false);
+ gather_ssao(compute_list, p_ao_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set);
RD::get_singleton()->draw_command_end_label(); // Gather SSAO
}
@@ -1365,15 +1371,18 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
+void EffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
- sky_push_constant.proj[0] = p_camera.matrix[2][0];
- sky_push_constant.proj[1] = p_camera.matrix[0][0];
- sky_push_constant.proj[2] = p_camera.matrix[2][1];
- sky_push_constant.proj[3] = p_camera.matrix[1][1];
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ // We only need key components of our projection matrix
+ sky_push_constant.projections[v][0] = p_projections[v].matrix[2][0];
+ sky_push_constant.projections[v][1] = p_projections[v].matrix[0][0];
+ sky_push_constant.projections[v][2] = p_projections[v].matrix[2][1];
+ sky_push_constant.projections[v][3] = p_projections[v].matrix[1][1];
+ }
sky_push_constant.position[0] = p_position.x;
sky_push_constant.position[1] = p_position.y;
sky_push_constant.position[2] = p_position.z;
@@ -1401,19 +1410,19 @@ void EffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_
RD::get_singleton()->draw_list_draw(draw_list, true);
}
-void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
+void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
ResolvePushConstant push_constant;
push_constant.screen_size[0] = p_screen_size.x;
push_constant.screen_size[1] = p_screen_size.y;
push_constant.samples = p_samples;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[p_source_giprobe.is_valid() ? RESOLVE_MODE_GI_GIPROBE : RESOLVE_MODE_GI]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[p_source_voxel_gi.is_valid() ? RESOLVE_MODE_GI_VOXEL_GI : RESOLVE_MODE_GI]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_source_depth, p_source_normal_roughness), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_dest_depth, p_dest_normal_roughness), 1);
- if (p_source_giprobe.is_valid()) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_giprobe), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_giprobe), 3);
+ if (p_source_voxel_gi.is_valid()) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_voxel_gi), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_voxel_gi), 3);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant));
@@ -1553,12 +1562,29 @@ EffectsRD::EffectsRD() {
tonemap_modes.push_back("\n#define USE_1D_LUT\n");
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
+ // multiview versions of our shaders
+ tonemap_modes.push_back("\n#define MULTIVIEW\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
+
tonemap.shader.initialize(tonemap_modes);
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_NORMAL_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_1D_LUT_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW, false);
+ }
+
tonemap.shader_version = tonemap.shader.version_create();
for (int i = 0; i < TONEMAP_MODE_MAX; i++) {
- tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ if (tonemap.shader.is_variant_enabled(i)) {
+ tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ tonemap.pipelines[i].clear();
+ }
}
}
@@ -1907,7 +1933,7 @@ EffectsRD::EffectsRD() {
{
Vector<String> resolve_modes;
resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n");
- resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define GIPROBE_RESOLVE\n");
+ resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n");
resolve.shader.initialize(resolve_modes);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 1ba25e301b..8b31ffbbd0 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -55,6 +55,7 @@
#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/tonemap.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
@@ -170,6 +171,12 @@ class EffectsRD {
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
TONEMAP_MODE_1D_LUT,
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
+
+ TONEMAP_MODE_NORMAL_MULTIVIEW,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW,
+ TONEMAP_MODE_1D_LUT_MULTIVIEW,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW,
+
TONEMAP_MODE_MAX
};
@@ -378,12 +385,10 @@ class EffectsRD {
SSAODownsamplePushConstant downsample_push_constant;
SsaoDownsampleShaderRD downsample_shader;
RID downsample_shader_version;
- RID downsample_uniform_set;
SSAOGatherPushConstant gather_push_constant;
SsaoShaderRD gather_shader;
RID gather_shader_version;
- RID gather_uniform_set;
RID gather_constants_buffer;
bool gather_initialized = false;
@@ -391,7 +396,6 @@ class EffectsRD {
SsaoImportanceMapShaderRD importance_map_shader;
RID importance_map_shader_version;
RID importance_map_load_counter;
- RID importance_map_uniform_set;
RID counter_uniform_set;
SSAOBlurPushConstant blur_push_constant;
@@ -453,12 +457,12 @@ class EffectsRD {
} filter;
struct SkyPushConstant {
- float orientation[12];
- float proj[4];
- float position[3];
- float multiplier;
- float time;
- float pad[3];
+ float orientation[12]; // 48 - 48
+ float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 64, if we ever need more then 3 we should consider adding this to a set.
+ float position[3]; // 12 - 92
+ float multiplier; // 4 - 96
+ float time; // 4 - 100
+ float pad[3]; // 12 - 112
};
enum SpecularMergeMode {
@@ -585,7 +589,7 @@ class EffectsRD {
enum ResolveMode {
RESOLVE_MODE_GI,
- RESOLVE_MODE_GI_GIPROBE,
+ RESOLVE_MODE_GI_VOXEL_GI,
RESOLVE_MODE_MAX
};
@@ -714,6 +718,7 @@ public:
bool use_fxaa = false;
bool use_debanding = false;
Vector2i texture_size;
+ uint32_t view_count = 1;
};
struct SSAOSettings {
@@ -738,19 +743,19 @@ public:
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
- void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass);
- void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets);
+ void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
+ void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_downsample_uniform_set, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
- void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
+ void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
- void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
void sort_buffer(RID p_uniform_set, int p_size);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 16c6273ff6..1653453c5c 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -93,8 +93,8 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
}
}
-void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_giprobe() {
- if (!giprobe_buffer.is_valid()) {
+void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() {
+ if (!voxelgi_buffer.is_valid()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8_UINT;
tf.width = width;
@@ -105,41 +105,41 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_giprobe()
RD::TextureFormat tf_aa = tf;
tf_aa.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
tf_aa.samples = texture_samples;
- giprobe_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView());
+ voxelgi_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView());
} else {
tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
- giprobe_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ voxelgi_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
Vector<RID> fb;
if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
fb.push_back(depth_msaa);
fb.push_back(normal_roughness_buffer_msaa);
- fb.push_back(giprobe_buffer_msaa);
+ fb.push_back(voxelgi_buffer_msaa);
} else {
fb.push_back(depth);
fb.push_back(normal_roughness_buffer);
- fb.push_back(giprobe_buffer);
+ fb.push_back(voxelgi_buffer);
}
- depth_normal_roughness_giprobe_fb = RD::get_singleton()->framebuffer_create(fb);
+ depth_normal_roughness_voxelgi_fb = RD::get_singleton()->framebuffer_create(fb);
}
}
void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
- if (giprobe_buffer != RID()) {
- RD::get_singleton()->free(giprobe_buffer);
- giprobe_buffer = RID();
+ if (voxelgi_buffer != RID()) {
+ RD::get_singleton()->free(voxelgi_buffer);
+ voxelgi_buffer = RID();
- if (giprobe_buffer_msaa.is_valid()) {
- RD::get_singleton()->free(giprobe_buffer_msaa);
- giprobe_buffer_msaa = RID();
+ if (voxelgi_buffer_msaa.is_valid()) {
+ RD::get_singleton()->free(voxelgi_buffer_msaa);
+ voxelgi_buffer_msaa = RID();
}
- depth_normal_roughness_giprobe_fb = RID();
+ depth_normal_roughness_voxelgi_fb = RID();
}
if (color_msaa.is_valid()) {
@@ -183,9 +183,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
}
}
-void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) {
+void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
clear();
+ ERR_FAIL_COND_MSG(p_view_count != 1, "Multiple views is currently not supported in this renderer, please use the mobile renderer for VR support");
+
msaa = p_msaa;
width = p_width;
@@ -398,8 +400,8 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
} break;
- case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE;
+ case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: {
+ shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI;
} break;
case PASS_MODE_DEPTH_MATERIAL: {
shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL;
@@ -498,8 +500,8 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
_render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
} break;
- case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: {
- _render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: {
+ _render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
} break;
case PASS_MODE_DEPTH_MATERIAL: {
_render_list_template<PASS_MODE_DEPTH_MATERIAL>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
@@ -817,7 +819,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, u
if (inst->store_transform_cache) {
RendererStorageRD::store_transform(inst->transform, instance_data.transform);
} else {
- RendererStorageRD::store_transform(Transform(), instance_data.transform);
+ RendererStorageRD::store_transform(Transform3D(), instance_data.transform);
}
instance_data.flags = inst->flags_cache;
@@ -948,14 +950,14 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;
}
- if (inst->gi_probes[0].is_valid()) {
+ if (inst->voxel_gi_instances[0].is_valid()) {
uint32_t probe0_index = 0xFFFF;
uint32_t probe1_index = 0xFFFF;
- for (uint32_t j = 0; j < scene_state.giprobes_used; j++) {
- if (scene_state.giprobe_ids[j] == inst->gi_probes[0]) {
+ for (uint32_t j = 0; j < scene_state.voxelgis_used; j++) {
+ if (scene_state.voxelgi_ids[j] == inst->voxel_gi_instances[0]) {
probe0_index = j;
- } else if (scene_state.giprobe_ids[j] == inst->gi_probes[1]) {
+ } else if (scene_state.voxelgi_ids[j] == inst->voxel_gi_instances[1]) {
probe1_index = j;
}
}
@@ -966,7 +968,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
inst->gi_offset_cache = probe0_index | (probe1_index << 16);
- flags |= INSTANCE_DATA_FLAG_USE_GIPROBE;
+ flags |= INSTANCE_DATA_FLAG_USE_VOXEL_GI;
uses_gi = true;
} else {
if (p_using_sdfgi && inst->can_sdfgi) {
@@ -1061,14 +1063,14 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
}
-void RenderForwardClustered::_setup_giprobes(const PagedArray<RID> &p_giprobes) {
- scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES));
- for (uint32_t i = 0; i < scene_state.giprobes_used; i++) {
- scene_state.giprobe_ids[i] = p_giprobes[i];
+void RenderForwardClustered::_setup_voxelgis(const PagedArray<RID> &p_voxelgis) {
+ scene_state.voxelgis_used = MIN(p_voxelgis.size(), uint32_t(MAX_VOXEL_GI_INSTANCESS));
+ for (uint32_t i = 0; i < scene_state.voxelgis_used; i++) {
+ scene_state.voxelgi_ids[i] = p_voxelgis[i];
}
}
-void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) {
+void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
if (i >= (int)scene_state.max_lightmaps) {
@@ -1091,6 +1093,8 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
}
void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
+ ERR_FAIL_COND_MSG(p_render_data->view_count != 1, "Multiview is currently not supported in the clustered renderer. Please use the mobile renderer for VR.");
+
RenderBufferDataForwardClustered *render_buffer = nullptr;
if (p_render_data->render_buffers.is_valid()) {
render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
@@ -1120,7 +1124,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_separate_specular = false;
bool using_ssr = false;
bool using_sdfgi = false;
- bool using_giprobe = false;
+ bool using_voxelgi = false;
bool reverse_cull = false;
if (render_buffer) {
@@ -1129,19 +1133,19 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
opaque_framebuffer = render_buffer->color_fb;
- if (p_render_data->gi_probes->size() > 0) {
- using_giprobe = true;
+ if (p_render_data->voxel_gi_instances->size() > 0) {
+ using_voxelgi = true;
}
- if (!p_render_data->environment.is_valid() && using_giprobe) {
- depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE;
+ if (!p_render_data->environment.is_valid() && using_voxelgi) {
+ depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
- } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_giprobe)) {
+ } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
if (environment_is_sdfgi_enabled(p_render_data->environment)) {
- depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also giprobe
+ depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi
using_sdfgi = true;
} else {
- depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
+ depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
if (environment_is_ssr_enabled(p_render_data->environment)) {
@@ -1164,10 +1168,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
depth_framebuffer = render_buffer->depth_normal_roughness_fb;
depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0));
} break;
- case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: {
+ case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: {
_allocate_normal_roughness_texture(render_buffer);
- render_buffer->ensure_giprobe();
- depth_framebuffer = render_buffer->depth_normal_roughness_giprobe_fb;
+ render_buffer->ensure_voxelgi();
+ depth_framebuffer = render_buffer->depth_normal_roughness_voxelgi_fb;
depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0));
depth_pass_clear.push_back(Color(0, 0, 0, 0));
} break;
@@ -1198,12 +1202,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Render Setup");
_setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
- _setup_giprobes(*p_render_data->gi_probes);
+ _setup_voxelgis(*p_render_data->voxel_gi_instances);
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
- _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_giprobe);
+ _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_voxelgi);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
render_list[RENDER_LIST_ALPHA].sort_by_depth();
_fill_instance_data(RENDER_LIST_OPAQUE);
@@ -1293,7 +1297,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color = p_default_bg_color;
}
- bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION;
+ bool debug_voxelgis = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION;
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
bool depth_pre_pass = depth_framebuffer.is_valid();
@@ -1301,7 +1305,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool continue_depth = false;
if (depth_pre_pass) { //depth pre pass
- bool needs_pre_resolve = _needs_post_prepass_render(p_render_data, using_sdfgi || using_giprobe);
+ bool needs_pre_resolve = _needs_post_prepass_render(p_render_data, using_sdfgi || using_voxelgi);
if (needs_pre_resolve) {
RENDER_TIMESTAMP("GI + Render Depth Pre-Pass (parallel)");
} else {
@@ -1312,32 +1316,32 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
RD::get_singleton()->draw_list_end();
//start compute processes here, so they run at the same time as depth pre-pass
- _post_prepass_render(p_render_data, using_sdfgi || using_giprobe);
+ _post_prepass_render(p_render_data, using_sdfgi || using_voxelgi);
}
RD::get_singleton()->draw_command_begin_label("Render Depth Pre-Pass");
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
- bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
+ bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
if (needs_pre_resolve) {
- _pre_resolve_render(p_render_data, using_sdfgi || using_giprobe);
+ _pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi);
}
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
RENDER_TIMESTAMP("Resolve Depth Pre-Pass");
RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass");
- if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) {
+ if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) {
if (needs_pre_resolve) {
RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE);
}
static int texture_samples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8, 16 };
- storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_giprobe ? render_buffer->giprobe_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_giprobe ? render_buffer->giprobe_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_samples[render_buffer->msaa]);
+ storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_voxelgi ? render_buffer->voxelgi_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_voxelgi ? render_buffer->voxelgi_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_samples[render_buffer->msaa]);
} else if (finish_depth) {
RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth);
}
@@ -1347,7 +1351,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
continue_depth = !finish_depth;
}
- _pre_opaque_render(p_render_data, using_ssao, using_sdfgi || using_giprobe, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->giprobe_buffer : RID());
+ _pre_opaque_render(p_render_data, using_ssao, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->voxelgi_buffer : RID());
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
@@ -1363,8 +1367,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
{
- bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_giprobes || debug_sdfgi_probes);
- bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_giprobes || debug_sdfgi_probes);
+ bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
+ bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
//regular forward for now
Vector<Color> c;
@@ -1389,8 +1393,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_end_label();
- if (debug_giprobes) {
- //debug giprobes
+ if (debug_voxelgis) {
+ //debug voxelgis
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
@@ -1398,16 +1402,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- RD::get_singleton()->draw_command_begin_label("Debug GIProbes");
- for (int i = 0; i < (int)p_render_data->gi_probes->size(); i++) {
- gi.debug_giprobe((*p_render_data->gi_probes)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
+ RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs");
+ for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) {
+ gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
}
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
}
if (debug_sdfgi_probes) {
- //debug giprobes
+ //debug voxelgis
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
@@ -1431,7 +1435,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
projection = correction * p_render_data->cam_projection;
}
RD::get_singleton()->draw_command_begin_label("Draw Sky");
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_render_data->cam_transform, time);
+ sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
RD::get_singleton()->draw_command_end_label();
}
@@ -1498,7 +1502,8 @@ void RenderForwardClustered::_render_shadow_begin() {
render_list[RENDER_LIST_SECONDARY].clear();
scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
+
+void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -1585,7 +1590,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup Render Collider Heightfield");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
@@ -1622,7 +1627,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering Material");
RD::get_singleton()->draw_command_begin_label("Render Material");
@@ -1796,7 +1801,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
render_data.cam_projection.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size);
//print_line("pass: " + itos(i) + " cam hsize: " + rtos(h_size) + " vsize: " + rtos(v_size) + " dsize " + rtos(d_size));
- Transform to_bounds;
+ Transform3D to_bounds;
to_bounds.origin = p_bounds.position;
to_bounds.basis.scale(p_bounds.size);
@@ -2058,11 +2063,11 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.resize(MAX_GI_PROBES);
+ u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- for (int i = 0; i < MAX_GI_PROBES; i++) {
- if (p_render_data && i < (int)p_render_data->gi_probes->size()) {
- RID tex = gi.gi_probe_instance_get_texture((*p_render_data->gi_probes)[i]);
+ for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
+ if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) {
+ RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]);
if (!tex.is_valid()) {
tex = default_tex;
}
@@ -2169,7 +2174,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 17;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_data->render_buffers) : render_buffers_get_default_gi_probe_buffer());
+ u.ids.push_back(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer());
uniforms.push_back(u);
}
{
@@ -2278,13 +2283,13 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
}
{
- // No GIProbes
+ // No VoxelGIs
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.resize(MAX_GI_PROBES);
+ u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- for (int i = 0; i < MAX_GI_PROBES; i++) {
+ for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
u.ids.write[i] = default_tex;
}
@@ -2632,7 +2637,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
ginstance->can_sdfgi = false;
if (!lightmap_instance_is_valid(ginstance->lightmap_instance)) {
- if (ginstance->gi_probes[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) {
+ if (ginstance->voxel_gi_instances[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) {
ginstance->can_sdfgi = true;
}
}
@@ -2719,7 +2724,7 @@ void RenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstanc
ginstance->mesh_instance = p_mesh_instance;
_geometry_instance_mark_dirty(ginstance);
}
-void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->transform = p_transform;
@@ -2815,7 +2820,7 @@ void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry
}
uint32_t RenderForwardClustered::geometry_instance_get_pair_mask() {
- return (1 << RS::INSTANCE_GI_PROBE);
+ return (1 << RS::INSTANCE_VOXEL_GI);
}
void RenderForwardClustered::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
}
@@ -2824,30 +2829,31 @@ void RenderForwardClustered::geometry_instance_pair_reflection_probe_instances(G
void RenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
}
-Transform RenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) {
+Transform3D RenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, Transform());
+ ERR_FAIL_COND_V(!ginstance, Transform3D());
return ginstance->transform;
}
+
AABB RenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_instance) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
ERR_FAIL_COND_V(!ginstance, AABB());
return ginstance->data->aabb;
}
-void RenderForwardClustered::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) {
+void RenderForwardClustered::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
- if (p_gi_probe_instance_count > 0) {
- ginstance->gi_probes[0] = p_gi_probe_instances[0];
+ if (p_voxel_gi_instance_count > 0) {
+ ginstance->voxel_gi_instances[0] = p_voxel_gi_instances[0];
} else {
- ginstance->gi_probes[0] = RID();
+ ginstance->voxel_gi_instances[0] = RID();
}
- if (p_gi_probe_instance_count > 1) {
- ginstance->gi_probes[1] = p_gi_probe_instances[1];
+ if (p_voxel_gi_instance_count > 1) {
+ ginstance->voxel_gi_instances[1] = p_voxel_gi_instances[1];
} else {
- ginstance->gi_probes[1] = RID();
+ ginstance->voxel_gi_instances[1] = RID();
}
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index bed3c3b219..579c8de05e 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -52,9 +52,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
enum {
SDFGI_MAX_CASCADES = 8,
- MAX_GI_PROBES = 8,
+ MAX_VOXEL_GI_INSTANCESS = 8,
MAX_LIGHTMAPS = 8,
- MAX_GI_PROBES_PER_INSTANCE = 2,
+ MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE = 2,
INSTANCE_DATA_BUFFER_MIN_SIZE = 4096
};
@@ -79,7 +79,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID depth;
RID specular;
RID normal_roughness_buffer;
- RID giprobe_buffer;
+ RID voxelgi_buffer;
RS::ViewportMSAA msaa;
RD::TextureSamples texture_samples;
@@ -89,11 +89,11 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID specular_msaa;
RID normal_roughness_buffer_msaa;
RID roughness_buffer_msaa;
- RID giprobe_buffer_msaa;
+ RID voxelgi_buffer_msaa;
RID depth_fb;
RID depth_normal_roughness_fb;
- RID depth_normal_roughness_giprobe_fb;
+ RID depth_normal_roughness_voxelgi_fb;
RID color_fb;
RID color_specular_fb;
RID specular_only_fb;
@@ -101,9 +101,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID render_sdfgi_uniform_set;
void ensure_specular();
- void ensure_giprobe();
+ void ensure_voxelgi();
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
~RenderBufferDataForwardClustered();
};
@@ -132,7 +132,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
PASS_MODE_SHADOW_DP,
PASS_MODE_DEPTH,
PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
- PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
+ PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI,
PASS_MODE_DEPTH_MATERIAL,
PASS_MODE_SDF,
};
@@ -189,7 +189,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
- INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11,
+ INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11,
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
@@ -204,7 +204,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
-
float camera_matrix[16];
float inv_camera_matrix[16];
@@ -318,8 +317,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
- RID giprobe_ids[MAX_GI_PROBES];
- uint32_t giprobes_used = 0;
+ RID voxelgi_ids[MAX_VOXEL_GI_INSTANCESS];
+ uint32_t voxelgis_used = 0;
bool used_screen_texture = false;
bool used_normal_texture = false;
@@ -350,8 +349,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
static RenderForwardClustered *singleton;
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
- void _setup_giprobes(const PagedArray<RID> &p_giprobes);
- void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform);
+ void _setup_voxelgis(const PagedArray<RID> &p_voxelgis);
+ void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
struct RenderElementInfo {
uint32_t repeat : 22;
@@ -458,8 +457,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
bool can_sdfgi = false;
//used during setup
uint32_t base_flags = 0;
- Transform transform;
- RID gi_probes[MAX_GI_PROBES_PER_INSTANCE];
+ Transform3D transform;
+ RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE];
RID lightmap_instance;
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
@@ -569,14 +568,14 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color);
virtual void _render_shadow_begin();
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
virtual void _render_shadow_process();
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
public:
virtual GeometryInstance *geometry_instance_create(RID p_base);
@@ -584,7 +583,7 @@ public:
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
@@ -594,7 +593,7 @@ public:
virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance);
+ virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance);
virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
@@ -603,7 +602,7 @@ public:
virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
- virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count);
+ virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count);
virtual bool free(RID p_rid);
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index f7ed0205af..f125931df8 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -30,6 +30,7 @@
#include "scene_shader_forward_clustered.h"
#include "core/config/project_settings.h"
+#include "core/math/math_defs.h"
#include "render_forward_clustered.h"
using namespace RendererSceneRenderImplementation;
@@ -310,7 +311,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
//none, leave empty
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
blend_state = blend_state_depth_normal_roughness;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE) {
+ } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
blend_state = blend_state_depth_normal_roughness_giprobe;
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
@@ -559,17 +560,18 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
{
Vector<String> shader_versions;
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_GIPROBE\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n");
- shader_versions.push_back("");
- shader_versions.push_back("\n#define USE_FORWARD_GI\n");
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n");
- shader_versions.push_back("\n#define USE_LIGHTMAP\n");
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n");
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_DEPTH_PASS_DP
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
+ shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
+ shader_versions.push_back("\n#define USE_FORWARD_GI\n"); // SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI
+ shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR
+ shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
+ shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR
+
shader.initialize(shader_versions, p_defines);
}
@@ -608,6 +610,9 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
//builtins
actions.renames["TIME"] = "scene_data.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
@@ -652,6 +657,11 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ // not implemented but need these just in case code is in the shaders
+ actions.renames["VIEW_INDEX"] = "0";
+ actions.renames["VIEW_MONO_LEFT"] = "0";
+ actions.renames["VIEW_RIGHT"] = "1";
+
//for light
actions.renames["VIEW"] = "view";
actions.renames["LIGHT_COLOR"] = "light_color";
@@ -717,7 +727,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
}
- actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
@@ -749,7 +758,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
actions.global_buffer_array_variable = "global_variables.data";
- actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
+ actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs";
compiler.initialize(actions);
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 7c8879686b..8add9f8095 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -48,7 +48,7 @@ public:
SHADER_VERSION_DEPTH_PASS,
SHADER_VERSION_DEPTH_PASS_DP,
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
- SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
SHADER_VERSION_COLOR_PASS,
@@ -56,6 +56,7 @@ public:
SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+
SHADER_VERSION_MAX
};
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 4e93fa5333..ae09d215ff 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -53,13 +53,14 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
color_fb = RID();
}
-void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) {
+void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
clear();
msaa = p_msaa;
width = p_width;
height = p_height;
+ view_count = p_view_count;
color = p_color_buffer;
depth = p_depth_buffer;
@@ -71,13 +72,18 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
fb.push_back(p_color_buffer);
fb.push_back(depth);
- color_fb = RD::get_singleton()->framebuffer_create(fb);
+ color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
} else {
RD::TextureFormat tf;
+ if (view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else {
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ }
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = p_width;
tf.height = p_height;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
@@ -103,7 +109,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
fb.push_back(color_msaa);
fb.push_back(depth_msaa);
- color_fb = RD::get_singleton()->framebuffer_create(fb);
+ color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
}
}
@@ -226,11 +232,11 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.resize(MAX_GI_PROBES);
+ u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- for (int i = 0; i < MAX_GI_PROBES; i++) {
- if (i < (int)p_gi_probes.size()) {
- RID tex = gi.gi_probe_instance_get_texture(p_gi_probes[i]);
+ for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
+ if (i < (int)p_voxel_gi_instances.size()) {
+ RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]);
if (!tex.is_valid()) {
tex = default_tex;
}
@@ -283,7 +289,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
return render_pass_uniform_sets[p_index];
}
-void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) {
+void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
// This probably needs to change...
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
@@ -479,7 +485,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Vector<Color> c;
c.push_back(clear_color.to_linear());
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
}
@@ -488,14 +494,16 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (draw_sky || draw_sky_fog_only) {
RENDER_TIMESTAMP("Render Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ RD::get_singleton()->draw_command_begin_label("Draw Sky");
+
if (p_render_data->reflection_probe.is_valid()) {
CameraMatrix correction;
correction.set_depth_correction(true);
- projection = correction * p_render_data->cam_projection;
+ CameraMatrix projection = correction * p_render_data->cam_projection;
+ sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ } else {
+ sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
}
- RD::get_singleton()->draw_command_begin_label("Draw Sky");
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_render_data->cam_transform, time);
RD::get_singleton()->draw_command_end_label();
}
@@ -522,7 +530,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
@@ -547,7 +555,7 @@ void RenderForwardMobile::_render_shadow_begin() {
render_list[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
+void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -555,6 +563,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
RenderDataRD render_data;
render_data.cam_projection = p_projection;
render_data.cam_transform = p_transform;
+ render_data.view_projection[0] = p_projection;
render_data.z_near = 0.0;
render_data.z_far = p_zfar;
render_data.instances = &p_instances;
@@ -622,7 +631,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -634,7 +643,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
/* */
-void RenderForwardMobile::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering Material");
RD::get_singleton()->draw_command_begin_label("Render Material");
@@ -647,6 +656,7 @@ void RenderForwardMobile::_render_material(const Transform &p_cam_transform, con
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
render_data.cam_transform = p_cam_transform;
+ render_data.view_projection[0] = p_cam_projection;
render_data.instances = &p_instances;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -746,7 +756,7 @@ void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_
// we don't do GI in low end..
}
-void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup Render Collider Heightfield");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
@@ -757,6 +767,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
render_data.cam_transform = p_cam_transform;
+ render_data.view_projection[0] = p_cam_projection;
render_data.z_near = 0.0;
render_data.z_far = p_cam_projection.get_z_far();
render_data.instances = &p_instances;
@@ -1089,6 +1100,12 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix);
RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
+ for (uint32_t v = 0; v < p_render_data->view_count; v++) {
+ projection = correction * p_render_data->view_projection[v];
+ RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
+ RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
+ }
+
scene_state.ubo.z_far = p_render_data->z_far;
scene_state.ubo.z_near = p_render_data->z_near;
@@ -1364,7 +1381,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
if (inst->store_transform_cache) {
RendererStorageRD::store_transform(inst->transform, push_constant.transform);
} else {
- RendererStorageRD::store_transform(Transform(), push_constant.transform);
+ RendererStorageRD::store_transform(Transform3D(), push_constant.transform);
}
push_constant.flags = inst->flags_cache;
@@ -1426,18 +1443,20 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
case PASS_MODE_COLOR:
case PASS_MODE_COLOR_TRANSPARENT: {
if (element_info.uses_lightmap) {
- shader_version = SceneShaderForwardMobile::SHADER_VERSION_LIGHTMAP_COLOR_PASS;
+ shader_version = p_params->view_count > 1 ? SceneShaderForwardMobile::SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW : SceneShaderForwardMobile::SHADER_VERSION_LIGHTMAP_COLOR_PASS;
} else {
- shader_version = SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS;
+ shader_version = p_params->view_count > 1 ? SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS_MULTIVIEW : SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS;
}
} break;
case PASS_MODE_SHADOW: {
- shader_version = SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS;
+ shader_version = p_params->view_count > 1 ? SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS_MULTIVIEW : SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS;
} break;
case PASS_MODE_SHADOW_DP: {
- shader_version = SceneShaderForwardMobile::SHADER_VERSION_DEPTH_PASS_DP;
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass");
+ shader_version = SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS_DP;
} break;
case PASS_MODE_DEPTH_MATERIAL: {
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass");
shader_version = SceneShaderForwardMobile::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL;
} break;
}
@@ -1557,7 +1576,7 @@ void RenderForwardMobile::geometry_instance_set_mesh_instance(GeometryInstance *
_geometry_instance_mark_dirty(ginstance);
}
-void RenderForwardMobile::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+void RenderForwardMobile::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->transform = p_transform;
@@ -1645,9 +1664,9 @@ void RenderForwardMobile::geometry_instance_set_cast_double_sided_shadows(Geomet
_geometry_instance_mark_dirty(ginstance);
}
-Transform RenderForwardMobile::geometry_instance_get_transform(GeometryInstance *p_instance) {
+Transform3D RenderForwardMobile::geometry_instance_get_transform(GeometryInstance *p_instance) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, Transform());
+ ERR_FAIL_COND_V(!ginstance, Transform3D());
return ginstance->transform;
}
@@ -1725,7 +1744,7 @@ void RenderForwardMobile::geometry_instance_pair_decal_instances(GeometryInstanc
}
}
-void RenderForwardMobile::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) {
+void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
// We do not have this here!
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index bf911319f2..99cbd45b10 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -85,9 +85,10 @@ protected:
RID color_fb;
int width, height;
+ uint32_t view_count;
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
~RenderBufferDataForwardMobile();
};
@@ -104,7 +105,7 @@ protected:
PASS_MODE_SHADOW_DP,
// PASS_MODE_DEPTH,
// PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
- // PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
+ // PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI,
PASS_MODE_DEPTH_MATERIAL,
// PASS_MODE_SDF,
};
@@ -120,6 +121,7 @@ protected:
bool reverse_cull = false;
PassMode pass_mode = PASS_MODE_COLOR;
// bool no_gi = false;
+ uint32_t view_count = 1;
RID render_pass_uniform_set;
bool force_wireframe = false;
Vector2 uv_offset;
@@ -130,13 +132,14 @@ protected:
uint32_t element_offset = 0;
uint32_t barrier = RD::BARRIER_MASK_ALL;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
reverse_cull = p_reverse_cull;
pass_mode = p_pass_mode;
// no_gi = p_no_gi;
+ view_count = p_view_count;
render_pass_uniform_set = p_render_pass_uniform_set;
force_wireframe = p_force_wireframe;
uv_offset = p_uv_offset;
@@ -152,14 +155,14 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color);
virtual void _render_shadow_begin();
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
virtual void _render_shadow_process();
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
@@ -174,7 +177,7 @@ protected:
static RenderForwardMobile *singleton;
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
- void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform);
+ void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
RID render_base_uniform_set;
LocalVector<RID> render_pass_uniform_sets;
@@ -196,10 +199,12 @@ protected:
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
-
float camera_matrix[16];
float inv_camera_matrix[16];
+ float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+ float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+
float viewport_size[2];
float screen_pixel_size[2];
@@ -390,7 +395,7 @@ protected:
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
- INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11,
+ INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11,
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
@@ -489,7 +494,7 @@ protected:
RID transforms_uniform_set;
float depth = 0;
bool mirror = false;
- Transform transform;
+ Transform3D transform;
bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform
bool non_uniform_scale = false;
AABB transformed_aabb; //needed for LOD
@@ -568,7 +573,7 @@ public:
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
@@ -578,7 +583,7 @@ public:
virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance);
+ virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance);
virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
@@ -587,7 +592,7 @@ public:
virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
- virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count);
+ virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count);
virtual bool free(RID p_rid);
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index b9220cc514..b5fb9fbc62 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -30,7 +30,9 @@
#include "scene_shader_forward_mobile.h"
#include "core/config/project_settings.h"
+#include "core/math/math_defs.h"
#include "render_forward_mobile.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
using namespace RendererSceneRenderImplementation;
@@ -290,12 +292,12 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
multisample_state.enable_alpha_to_one = true;
}
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
+ if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_blend;
if (depth_draw == DEPTH_DRAW_OPAQUE) {
depth_stencil.enable_depth_write = false; //alpha does not draw depth
}
- } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
+ } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
//none, blend state contains nothing
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
@@ -303,57 +305,16 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
pipelines[i][j][k].clear();
continue; // do not use this version (will error if using it is attempted)
}
-
- /*
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
- blend_state = blend_state_blend;
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
- depth_stencil.enable_depth_write = false; //alpha does not draw depth
- }
- } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) {
- if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
- //none, blend state contains nothing
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else {
- blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
- }
- } else {
- pipelines[i][j][k].clear();
- continue; // do not use this version (will error if using it is attempted)
- }
- */
} else {
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
+ if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_opaque;
- } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
+ } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
//none, leave empty
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
} else {
// ???
}
-
- /*
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
- blend_state = blend_state_opaque;
- } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
- //none, leave empty
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal_roughness;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE) {
- blend_state = blend_state_depth_normal_roughness_giprobe;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_SDF) {
- blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
- } else {
- //specular write
- blend_state = blend_state_opaque_specular;
- depth_stencil.enable_depth_test = false;
- depth_stencil.enable_depth_write = false;
- }
- */
}
RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
@@ -584,10 +545,22 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
Vector<String> shader_versions;
shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // !BAS! SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_DEPTH_PASS_DP (maybe rename to SHADER_VERSION_SHADOW_PASS_DP?)
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_SHADOW_PASS_DP
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
+
+ // multiview versions of our shaders
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
+
shader.initialize(shader_versions, p_defines);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
+ shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
+ shader.set_variant_enabled(SHADER_VERSION_SHADOW_PASS_MULTIVIEW, false);
+ }
}
storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
@@ -602,7 +575,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix";
actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix";
actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
- actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix";
+ actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
actions.renames["MODELVIEW_MATRIX"] = "modelview";
actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
@@ -625,6 +598,9 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
//builtins
actions.renames["TIME"] = "scene_data.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
@@ -669,6 +645,10 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ actions.renames["VIEW_INDEX"] = "ViewIndex";
+ actions.renames["VIEW_MONO_LEFT"] = "0";
+ actions.renames["VIEW_RIGHT"] = "1";
+
//for light
actions.renames["VIEW"] = "view";
actions.renames["LIGHT_COLOR"] = "light_color";
@@ -733,7 +713,6 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
}
- actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 1517197d25..f4f6ceeb1d 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -47,8 +47,13 @@ public:
SHADER_VERSION_COLOR_PASS,
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
SHADER_VERSION_SHADOW_PASS,
- SHADER_VERSION_DEPTH_PASS_DP,
+ SHADER_VERSION_SHADOW_PASS_DP,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
+
+ SHADER_VERSION_COLOR_PASS_MULTIVIEW,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
+ SHADER_VERSION_SHADOW_PASS_MULTIVIEW,
+
SHADER_VERSION_MAX
};
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index f448698976..9d325fe69b 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -31,8 +31,10 @@
#include "renderer_canvas_render_rd.h"
#include "core/config/project_settings.h"
#include "core/math/geometry_2d.h"
+#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/rendering_server_default.h"
void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
p_mat4[0] = p_transform.elements[0][0];
@@ -74,7 +76,7 @@ void RendererCanvasRenderRD::_update_transform_2d_to_mat2x3(const Transform2D &p
p_mat2x3[5] = p_transform.elements[2][1];
}
-void RendererCanvasRenderRD::_update_transform_to_mat4(const Transform &p_transform, float *p_mat4) {
+void RendererCanvasRenderRD::_update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4) {
p_mat4[0] = p_transform.basis.elements[0][0];
p_mat4[1] = p_transform.basis.elements[1][0];
p_mat4[2] = p_transform.basis.elements[2][0];
@@ -390,7 +392,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
r_last_texture = p_texture;
}
-void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
+void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
//create an empty push constant
RS::CanvasItemTextureFilter current_filter = default_filter;
@@ -747,9 +749,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, const Item
} else if (c->type == Item::Command::TYPE_PARTICLES) {
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
ERR_BREAK(storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D);
+ storage->particles_request_process(pt->particles);
+
if (storage->particles_is_inactive(pt->particles)) {
break;
}
+
+ RenderingServerDefault::redraw_request(); // active particles means redraw request
+
+ bool local_coords = true;
int dpc = storage->particles_get_draw_passes(pt->particles);
if (dpc == 0) {
break; //nothing to draw
@@ -768,6 +776,30 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, const Item
mesh = storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored
texture = pt->texture;
+
+ if (storage->particles_has_collision(pt->particles) && storage->render_target_is_sdf_enabled(p_render_target)) {
+ //pass collision information
+ Transform2D xform;
+ if (local_coords) {
+ xform = p_item->final_transform;
+ } else {
+ xform = p_canvas_transform_inverse;
+ }
+
+ RID sdf_texture = storage->render_target_get_sdf_texture(p_render_target);
+
+ Rect2 to_screen;
+ {
+ Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_render_target);
+
+ to_screen.size = Vector2(1.0 / sdf_rect.size.width, 1.0 / sdf_rect.size.height);
+ to_screen.position = -sdf_rect.position * to_screen.size;
+ }
+
+ storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
+ } else {
+ storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());
+ }
}
if (mesh.is_null()) {
@@ -1052,7 +1084,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
}
- _render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants);
+ _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants);
prev_material = material;
}
@@ -1218,7 +1250,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Size2i ssize = storage->render_target_get_size(p_to_render_target);
- Transform screen_transform;
+ Transform3D screen_transform;
screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
_update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
@@ -1280,6 +1312,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Item *canvas_group_owner = nullptr;
bool update_skeletons = false;
+ bool time_used = false;
while (ci) {
if (ci->copy_back_buffer && canvas_group_owner == nullptr) {
@@ -1305,6 +1338,9 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (md->shader_data->uses_sdf) {
r_sdf_used = true;
}
+ if (md->shader_data->uses_time) {
+ time_used = true;
+ }
if (md->last_frame != RendererCompositorRD::singleton->get_frame_number()) {
md->last_frame = RendererCompositorRD::singleton->get_frame_number();
if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) {
@@ -1401,6 +1437,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
ci = ci->next;
}
+
+ if (time_used) {
+ RenderingServerDefault::redraw_request();
+ }
}
RID RendererCanvasRenderRD::light_create() {
@@ -1499,7 +1539,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
}
Vector3 cam_target = Basis(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
- projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
+ projection = projection * CameraMatrix(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
@@ -1577,7 +1617,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
CameraMatrix projection;
projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance);
- projection = projection * CameraMatrix(Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
+ projection = projection * CameraMatrix(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
@@ -1877,6 +1917,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
uniforms.clear();
uses_screen_texture = false;
uses_sdf = false;
+ uses_time = false;
if (code == String()) {
return; //just invalid, but no error
@@ -1901,6 +1942,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
actions.usage_flag_pointers["texture_sdf"] = &uses_sdf;
+ actions.usage_flag_pointers["TIME"] = &uses_time;
actions.uniforms = &uniforms;
@@ -2367,6 +2409,9 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.renames["CANVAS_MATRIX"] = "canvas_data.canvas_transform";
actions.renames["SCREEN_MATRIX"] = "canvas_data.screen_transform";
actions.renames["TIME"] = "canvas_data.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
actions.renames["AT_LIGHT_PASS"] = "false";
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 8129cc6c9b..8c1376e2dc 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -176,6 +176,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
bool uses_screen_texture = false;
bool uses_sdf = false;
+ bool uses_time = false;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
@@ -425,14 +426,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID _create_base_uniform_set(RID p_to_render_target, bool p_backbuffer);
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); //recursive, so regular inline used instead.
- void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants);
+ void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants);
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);
_FORCE_INLINE_ void _update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4);
- _FORCE_INLINE_ void _update_transform_to_mat4(const Transform &p_transform, float *p_mat4);
+ _FORCE_INLINE_ void _update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4);
void _update_shadow_atlas();
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 0012ba9c27..f9ac7c8fa3 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -31,6 +31,7 @@
#include "renderer_compositor_rd.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
void RendererCompositorRD::prepare_for_blitting_render_targets() {
RD::get_singleton()->prepare_screen_for_drawing();
@@ -155,6 +156,43 @@ void RendererCompositorRD::finalize() {
RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
+ {
+ String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path();
+ if (shader_cache_dir == String()) {
+ shader_cache_dir = "user://";
+ }
+ DirAccessRef da = DirAccess::open(shader_cache_dir);
+ if (!da) {
+ ERR_PRINT("Can't create shader cache folder, no shader caching will happen: " + shader_cache_dir);
+ } else {
+ Error err = da->change_dir("shader_cache");
+ if (err != OK) {
+ err = da->make_dir("shader_cache");
+ }
+ if (err != OK) {
+ ERR_PRINT("Can't create shader cache folder, no shader caching will happen: " + shader_cache_dir);
+ } else {
+ shader_cache_dir = shader_cache_dir.plus_file("shader_cache");
+
+ bool shader_cache_enabled = GLOBAL_GET("rendering/shader_compiler/shader_cache/enabled");
+ if (!Engine::get_singleton()->is_editor_hint() && !shader_cache_enabled) {
+ shader_cache_dir = String(); //disable only if not editor
+ }
+
+ if (shader_cache_dir != String()) {
+ bool compress = GLOBAL_GET("rendering/shader_compiler/shader_cache/compress");
+ bool use_zstd = GLOBAL_GET("rendering/shader_compiler/shader_cache/use_zstd_compression");
+ bool strip_debug = GLOBAL_GET("rendering/shader_compiler/shader_cache/strip_debug");
+
+ ShaderRD::set_shader_cache_dir(shader_cache_dir);
+ ShaderRD::set_shader_cache_save_compressed(compress);
+ ShaderRD::set_shader_cache_save_compressed_zstd(use_zstd);
+ ShaderRD::set_shader_cache_save_debug(!strip_debug);
+ }
+ }
+ }
+ }
+
singleton = this;
time = 0;
@@ -171,3 +209,7 @@ RendererCompositorRD::RendererCompositorRD() {
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
}
}
+
+RendererCompositorRD::~RendererCompositorRD() {
+ ShaderRD::set_shader_cache_dir(String());
+}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 52552f7ee3..7a78322051 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -118,6 +118,6 @@ public:
static RendererCompositorRD *singleton;
RendererCompositorRD();
- ~RendererCompositorRD() {}
+ ~RendererCompositorRD();
};
#endif // RASTERIZER_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index b289b17fad..43a4058ab6 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -1099,7 +1099,7 @@ void RendererSceneGIRD::SDFGI::update_cascades() {
RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE);
}
-void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {
+void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {
if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {
Vector<RD::Uniform> uniforms;
{
@@ -1367,7 +1367,7 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
}
}
-void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) {
+void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) {
/* Update general SDFGI Buffer */
SDFGIData sdfgi_data;
@@ -2012,10 +2012,10 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
}
////////////////////////////////////////////////////////////////////////////////
-// GIProbeInstance
+// VoxelGIInstance
-void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
- uint32_t data_version = storage->gi_probe_get_data_version(probe);
+void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+ uint32_t data_version = storage->voxel_gi_get_data_version(probe);
// (RE)CREATE IF NEEDED
@@ -2034,11 +2034,11 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
dynamic_maps.clear();
- Vector3i octree_size = storage->gi_probe_get_octree_size(probe);
+ Vector3i octree_size = storage->voxel_gi_get_octree_size(probe);
if (octree_size != Vector3i()) {
//can create a 3D texture
- Vector<int> levels = storage->gi_probe_get_level_counts(probe);
+ Vector<int> levels = storage->voxel_gi_get_level_counts(probe);
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@@ -2064,7 +2064,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
}
for (int i = 0; i < levels.size(); i++) {
- GIProbeInstance::Mipmap mipmap;
+ VoxelGIInstance::Mipmap mipmap;
mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), texture, 0, i, RD::TEXTURE_SLICE_3D);
mipmap.level = levels.size() - i - 1;
mipmap.cell_offset = 0;
@@ -2078,14 +2078,14 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(storage->gi_probe_get_octree_buffer(probe));
+ u.ids.push_back(storage->voxel_gi_get_octree_buffer(probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.ids.push_back(storage->gi_probe_get_data_buffer(probe));
+ u.ids.push_back(storage->voxel_gi_get_data_buffer(probe));
uniforms.push_back(u);
}
@@ -2100,7 +2100,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.ids.push_back(storage->gi_probe_get_sdf_texture(probe));
+ u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
@@ -2118,11 +2118,11 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 3;
- u.ids.push_back(gi->gi_probe_lights_uniform);
+ u.ids.push_back(gi->voxel_gi_lights_uniform);
copy_uniforms.push_back(u);
}
- mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT], 0);
+ mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_COMPUTE_LIGHT], 0);
copy_uniforms = uniforms; //restore
@@ -2133,9 +2133,9 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
u.ids.push_back(texture);
copy_uniforms.push_back(u);
}
- mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0);
+ mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0);
} else {
- mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0);
+ mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_COMPUTE_MIPMAP], 0);
}
}
@@ -2147,7 +2147,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
uniforms.push_back(u);
}
- mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0);
+ mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_WRITE_TEXTURE], 0);
mipmaps.push_back(mipmap);
}
@@ -2158,7 +2158,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
int mipmap_index = 0;
while (mipmap_index < mipmaps.size()) {
- GIProbeInstance::DynamicMap dmap;
+ VoxelGIInstance::DynamicMap dmap;
if (oversample > 0) {
dmap.size = dynamic_map_size * (1 << oversample);
@@ -2217,7 +2217,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 3;
- u.ids.push_back(gi->gi_probe_lights_uniform);
+ u.ids.push_back(gi->voxel_gi_lights_uniform);
uniforms.push_back(u);
}
@@ -2253,7 +2253,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.ids.push_back(storage->gi_probe_get_sdf_texture(probe));
+ u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
@@ -2278,7 +2278,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
uniforms.push_back(u);
}
- dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING], 0);
+ dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING], 0);
}
} else {
bool plot = dmap.mipmap >= 0;
@@ -2322,7 +2322,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.ids.push_back(storage->gi_probe_get_sdf_texture(probe));
+ u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
@@ -2345,7 +2345,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
dmap.uniform_set = RD::get_singleton()->uniform_set_create(
uniforms,
- gi->giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : (write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT)],
+ gi->voxel_gi_lighting_shader_version_shaders[(write && plot) ? VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : (write ? VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_PLOT)],
0);
}
@@ -2370,15 +2370,15 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
uint32_t light_count = 0;
if (p_update_light_instances || p_dynamic_objects.size() > 0) {
- light_count = MIN(gi->gi_probe_max_lights, (uint32_t)p_light_instances.size());
+ light_count = MIN(gi->voxel_gi_max_lights, (uint32_t)p_light_instances.size());
{
- Transform to_cell = storage->gi_probe_get_to_cell_xform(probe);
- Transform to_probe_xform = (transform * to_cell.affine_inverse()).affine_inverse();
+ Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(probe);
+ Transform3D to_probe_xform = (transform * to_cell.affine_inverse()).affine_inverse();
//update lights
for (uint32_t i = 0; i < light_count; i++) {
- GIProbeLight &l = gi->gi_probe_lights[i];
+ VoxelGILight &l = gi->voxel_gi_lights[i];
RID light_instance = p_light_instances[i];
RID light = p_scene_render->light_instance_get_base_light(light_instance);
@@ -2399,7 +2399,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
l.cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
l.inv_spot_attenuation = 1.0f / storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
- Transform xform = p_scene_render->light_instance_get_base_transform(light_instance);
+ Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance);
Vector3 pos = to_probe_xform.xform(xform.origin);
Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized();
@@ -2415,7 +2415,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
l.has_shadow = storage->light_has_shadow(light);
}
- RD::get_singleton()->buffer_update(gi->gi_probe_lights_uniform, 0, sizeof(GIProbeLight) * light_count, gi->gi_probe_lights);
+ RD::get_singleton()->buffer_update(gi->voxel_gi_lights_uniform, 0, sizeof(VoxelGILight) * light_count, gi->voxel_gi_lights);
}
}
@@ -2424,17 +2424,17 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
if (mipmaps.size()) {
//can update mipmaps
- Vector3i probe_size = storage->gi_probe_get_octree_size(probe);
+ Vector3i probe_size = storage->voxel_gi_get_octree_size(probe);
- GIProbePushConstant push_constant;
+ VoxelGIPushConstant push_constant;
push_constant.limits[0] = probe_size.x;
push_constant.limits[1] = probe_size.y;
push_constant.limits[2] = probe_size.z;
push_constant.stack_size = mipmaps.size();
push_constant.emission_scale = 1.0;
- push_constant.propagation = storage->gi_probe_get_propagation(probe);
- push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe);
+ push_constant.propagation = storage->voxel_gi_get_propagation(probe);
+ push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe);
push_constant.light_count = light_count;
push_constant.aniso_strength = 0;
@@ -2446,7 +2446,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
int passes;
if (p_update_light_instances) {
- passes = storage->gi_probe_is_using_two_bounces(probe) ? 2 : 1;
+ passes = storage->voxel_gi_is_using_two_bounces(probe) ? 2 : 1;
} else {
passes = 1; //only re-blitting is necessary
}
@@ -2457,9 +2457,9 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
if (p_update_light_instances) {
for (int i = 0; i < mipmaps.size(); i++) {
if (i == 0) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[pass == 0 ? VOXEL_GI_SHADER_VERSION_COMPUTE_LIGHT : VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]);
} else if (i == 1) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_COMPUTE_MIPMAP]);
}
if (pass == 1 || i > 0) {
@@ -2477,7 +2477,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
while (wg_todo) {
int wg_count = MIN(wg_todo, wg_limit_x);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1);
wg_todo -= wg_count;
push_constant.cell_offset += wg_count * wg_size;
@@ -2487,7 +2487,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
}
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_WRITE_TEXTURE]);
for (int i = 0; i < mipmaps.size(); i++) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mipmaps[i].write_uniform_set, 0);
@@ -2498,7 +2498,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
while (wg_todo) {
int wg_count = MIN(wg_todo, wg_limit_x);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1);
wg_todo -= wg_count;
push_constant.cell_offset += wg_count * wg_size;
@@ -2513,15 +2513,15 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
has_dynamic_object_data = false; //clear until dynamic object data is used again
if (p_dynamic_objects.size() && dynamic_maps.size()) {
- Vector3i octree_size = storage->gi_probe_get_octree_size(probe);
+ Vector3i octree_size = storage->voxel_gi_get_octree_size(probe);
int multiplier = dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
- Transform oversample_scale;
+ Transform3D oversample_scale;
oversample_scale.basis.scale(Vector3(multiplier, multiplier, multiplier));
- Transform to_cell = oversample_scale * storage->gi_probe_get_to_cell_xform(probe);
- Transform to_world_xform = transform * to_cell.affine_inverse();
- Transform to_probe_xform = to_world_xform.affine_inverse();
+ Transform3D to_cell = oversample_scale * storage->voxel_gi_get_to_cell_xform(probe);
+ Transform3D to_world_xform = transform * to_cell.affine_inverse();
+ Transform3D to_probe_xform = to_world_xform.affine_inverse();
AABB probe_aabb(Vector3(), octree_size);
@@ -2529,7 +2529,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
RendererSceneRender::GeometryInstance *instance = p_dynamic_objects[i];
- //transform aabb to giprobe
+ //transform aabb to voxel_gi
AABB aabb = (to_probe_xform * p_scene_render->geometry_instance_get_transform(instance)).xform(p_scene_render->geometry_instance_get_aabb(instance));
//this needs to wrap to grid resolution to avoid jitter
@@ -2576,7 +2576,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
Vector3 up_dir = render_up[j];
Vector3 center = aabb.position + aabb.size * 0.5;
- Transform xform;
+ Transform3D xform;
xform.set_look_at(center - aabb.size * 0.5 * render_dir, center, up_dir);
Vector3 x_dir = xform.basis.get_axis(0).abs();
@@ -2601,8 +2601,8 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
- GIProbeDynamicPushConstant push_constant;
- memset(&push_constant, 0, sizeof(GIProbeDynamicPushConstant));
+ VoxelGIDynamicPushConstant push_constant;
+ memset(&push_constant, 0, sizeof(VoxelGIDynamicPushConstant));
push_constant.limits[0] = octree_size.x;
push_constant.limits[1] = octree_size.y;
push_constant.limits[2] = octree_size.z;
@@ -2619,7 +2619,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
push_constant.z_base = xform.origin[z_axis];
push_constant.z_sign = (z_flip ? -1.0 : 1.0);
push_constant.pos_multiplier = float(1.0) / multiplier;
- push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe);
+ push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe);
push_constant.flip_x = x_flip;
push_constant.flip_y = y_flip;
push_constant.rect_pos[0] = rect.position[0];
@@ -2631,16 +2631,16 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
push_constant.prev_rect_size[0] = 0;
push_constant.prev_rect_size[1] = 0;
push_constant.on_mipmap = false;
- push_constant.propagation = storage->gi_probe_get_propagation(probe);
+ push_constant.propagation = storage->voxel_gi_get_propagation(probe);
push_constant.pad[0] = 0;
push_constant.pad[1] = 0;
push_constant.pad[2] = 0;
//process lighting
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[0].uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant));
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1);
//print_line("rect: " + itos(i) + ": " + rect);
@@ -2695,14 +2695,14 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (dynamic_maps[k].mipmap < 0) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]);
} else if (k < dynamic_maps.size() - 1) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]);
} else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]);
}
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[k].uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant));
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1);
}
@@ -2713,22 +2713,22 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c
has_dynamic_object_data = true; //clear until dynamic object data is used again
}
- last_probe_version = storage->gi_probe_get_version(probe);
+ last_probe_version = storage->voxel_gi_get_version(probe);
}
-void RendererSceneGIRD::GIProbeInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
if (mipmaps.size() == 0) {
return;
}
- CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(storage->gi_probe_get_to_cell_xform(probe).affine_inverse());
+ CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(storage->voxel_gi_get_to_cell_xform(probe).affine_inverse());
int level = 0;
- Vector3i octree_size = storage->gi_probe_get_octree_size(probe);
+ Vector3i octree_size = storage->voxel_gi_get_octree_size(probe);
- GIProbeDebugPushConstant push_constant;
+ VoxelGIDebugPushConstant push_constant;
push_constant.alpha = p_alpha;
- push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe);
+ push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe);
push_constant.cell_offset = mipmaps[level].cell_offset;
push_constant.level = level;
@@ -2743,15 +2743,15 @@ void RendererSceneGIRD::GIProbeInstance::debug(RD::DrawListID p_draw_list, RID p
}
}
- if (gi->giprobe_debug_uniform_set.is_valid()) {
- RD::get_singleton()->free(gi->giprobe_debug_uniform_set);
+ if (gi->voxel_gi_debug_uniform_set.is_valid()) {
+ RD::get_singleton()->free(gi->voxel_gi_debug_uniform_set);
}
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(storage->gi_probe_get_data_buffer(probe));
+ u.ids.push_back(storage->voxel_gi_get_data_buffer(probe));
uniforms.push_back(u);
}
{
@@ -2776,19 +2776,19 @@ void RendererSceneGIRD::GIProbeInstance::debug(RD::DrawListID p_draw_list, RID p
cell_count = mipmaps[level].cell_count;
}
- gi->giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_debug_shader_version_shaders[0], 0);
+ gi->voxel_gi_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->voxel_gi_debug_shader_version_shaders[0], 0);
- int giprobe_debug_pipeline = GI_PROBE_DEBUG_COLOR;
+ int voxel_gi_debug_pipeline = VOXEL_GI_DEBUG_COLOR;
if (p_emission) {
- giprobe_debug_pipeline = GI_PROBE_DEBUG_EMISSION;
+ voxel_gi_debug_pipeline = VOXEL_GI_DEBUG_EMISSION;
} else if (p_lighting) {
- giprobe_debug_pipeline = has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT;
+ voxel_gi_debug_pipeline = has_dynamic_object_data ? VOXEL_GI_DEBUG_LIGHT_FULL : VOXEL_GI_DEBUG_LIGHT;
}
RD::get_singleton()->draw_list_bind_render_pipeline(
p_draw_list,
- gi->giprobe_debug_shader_version_pipelines[giprobe_debug_pipeline].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, gi->giprobe_debug_uniform_set, 0);
- RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant));
+ gi->voxel_gi_debug_shader_version_pipelines[voxel_gi_debug_pipeline].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, gi->voxel_gi_debug_uniform_set, 0);
+ RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(VoxelGIDebugPushConstant));
RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36);
}
@@ -2812,13 +2812,13 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
{
//kinda complicated to compute the amount of slots, we try to use as many as we can
- gi_probe_max_lights = 32;
+ voxel_gi_max_lights = 32;
- gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights);
- gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight));
- gi_probe_quality = RS::GIProbeQuality(CLAMP(int(GLOBAL_GET("rendering/global_illumination/gi_probes/quality")), 0, 1));
+ voxel_gi_lights = memnew_arr(VoxelGILight, voxel_gi_max_lights);
+ voxel_gi_lights_uniform = RD::get_singleton()->uniform_buffer_create(voxel_gi_max_lights * sizeof(VoxelGILight));
+ voxel_gi_quality = RS::VoxelGIQuality(CLAMP(int(GLOBAL_GET("rendering/global_illumination/voxel_gi/quality")), 0, 1));
- String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n";
+ String defines = "\n#define MAX_LIGHTS " + itos(voxel_gi_max_lights) + "\n";
Vector<String> versions;
versions.push_back("\n#define MODE_COMPUTE_LIGHT\n");
@@ -2830,11 +2830,11 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n");
versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n#define MODE_DYNAMIC_SHRINK_WRITE\n");
- giprobe_shader.initialize(versions, defines);
- giprobe_lighting_shader_version = giprobe_shader.version_create();
- for (int i = 0; i < GI_PROBE_SHADER_VERSION_MAX; i++) {
- giprobe_lighting_shader_version_shaders[i] = giprobe_shader.version_get_shader(giprobe_lighting_shader_version, i);
- giprobe_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(giprobe_lighting_shader_version_shaders[i]);
+ voxel_gi_shader.initialize(versions, defines);
+ voxel_gi_lighting_shader_version = voxel_gi_shader.version_create();
+ for (int i = 0; i < VOXEL_GI_SHADER_VERSION_MAX; i++) {
+ voxel_gi_lighting_shader_version_shaders[i] = voxel_gi_shader.version_get_shader(voxel_gi_lighting_shader_version, i);
+ voxel_gi_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(voxel_gi_lighting_shader_version_shaders[i]);
}
}
@@ -2846,10 +2846,10 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
versions.push_back("\n#define MODE_DEBUG_EMISSION\n");
versions.push_back("\n#define MODE_DEBUG_LIGHT\n#define MODE_DEBUG_LIGHT_FULL\n");
- giprobe_debug_shader.initialize(versions, defines);
- giprobe_debug_shader_version = giprobe_debug_shader.version_create();
- for (int i = 0; i < GI_PROBE_DEBUG_MAX; i++) {
- giprobe_debug_shader_version_shaders[i] = giprobe_debug_shader.version_get_shader(giprobe_debug_shader_version, i);
+ voxel_gi_debug_shader.initialize(versions, defines);
+ voxel_gi_debug_shader_version = voxel_gi_debug_shader.version_create();
+ for (int i = 0; i < VOXEL_GI_DEBUG_MAX; i++) {
+ voxel_gi_debug_shader_version_shaders[i] = voxel_gi_debug_shader.version_get_shader(voxel_gi_debug_shader_version, i);
RD::PipelineRasterizationState rs;
rs.cull_mode = RD::POLYGON_CULL_FRONT;
@@ -2858,7 +2858,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
ds.enable_depth_write = true;
ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
- giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
+ voxel_gi_debug_shader_version_pipelines[i].setup(voxel_gi_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
}
}
@@ -2944,12 +2944,12 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
//calculate tables
String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
Vector<String> gi_modes;
- gi_modes.push_back("\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n");
gi_modes.push_back("\n#define USE_SDFGI\n");
- gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_GIPROBES\n");
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n");
+ gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n");
gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n");
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n");
shader.initialize(gi_modes, defines);
shader_version = shader.version_create();
@@ -2991,17 +2991,17 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
}
}
}
- default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * MAX_GIPROBES);
+ default_voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(VoxelGIData) * MAX_VOXEL_GI_INSTANCES);
half_resolution = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution");
}
void RendererSceneGIRD::free() {
- RD::get_singleton()->free(default_giprobe_buffer);
- RD::get_singleton()->free(gi_probe_lights_uniform);
+ RD::get_singleton()->free(default_voxel_gi_buffer);
+ RD::get_singleton()->free(voxel_gi_lights_uniform);
RD::get_singleton()->free(sdfgi_ubo);
- giprobe_debug_shader.version_free(giprobe_debug_shader_version);
- giprobe_shader.version_free(giprobe_lighting_shader_version);
+ voxel_gi_debug_shader.version_free(voxel_gi_debug_shader_version);
+ voxel_gi_shader.version_free(voxel_gi_lighting_shader_version);
shader.version_free(shader_version);
sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader);
sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader);
@@ -3009,7 +3009,7 @@ void RendererSceneGIRD::free() {
sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader);
sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader);
- memdelete_arr(gi_probe_lights);
+ memdelete_arr(voxel_gi_lights);
}
RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
@@ -3020,36 +3020,36 @@ RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironme
return sdfgi;
}
-void RendererSceneGIRD::setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used, RendererSceneRenderRD *p_scene_render) {
- r_gi_probes_used = 0;
+void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
+ r_voxel_gi_instances_used = 0;
// feels a little dirty to use our container this way but....
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(rb == nullptr);
- RID gi_probe_buffer = p_scene_render->render_buffers_get_gi_probe_buffer(p_render_buffers);
+ RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers);
- RD::get_singleton()->draw_command_begin_label("GIProbes Setup");
+ RD::get_singleton()->draw_command_begin_label("VoxelGIs Setup");
- GIProbeData gi_probe_data[MAX_GIPROBES];
+ VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES];
- bool giprobes_changed = false;
+ bool voxel_gi_instances_changed = false;
- Transform to_camera;
+ Transform3D to_camera;
to_camera.origin = p_transform.origin; //only translation, make local
- for (int i = 0; i < MAX_GIPROBES; i++) {
+ for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
RID texture;
- if (i < (int)p_gi_probes.size()) {
- GIProbeInstance *gipi = get_probe_instance(p_gi_probes[i]);
+ if (i < (int)p_voxel_gi_instances.size()) {
+ VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]);
if (gipi) {
texture = gipi->texture;
- GIProbeData &gipd = gi_probe_data[i];
+ VoxelGIData &gipd = voxel_gi_data[i];
RID base_probe = gipi->probe;
- Transform to_cell = storage->gi_probe_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera;
+ Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera;
gipd.xform[0] = to_cell.basis.elements[0][0];
gipd.xform[1] = to_cell.basis.elements[1][0];
@@ -3068,36 +3068,36 @@ void RendererSceneGIRD::setup_giprobes(RID p_render_buffers, const Transform &p_
gipd.xform[14] = to_cell.origin.z;
gipd.xform[15] = 1;
- Vector3 bounds = storage->gi_probe_get_octree_size(base_probe);
+ Vector3 bounds = storage->voxel_gi_get_octree_size(base_probe);
gipd.bounds[0] = bounds.x;
gipd.bounds[1] = bounds.y;
gipd.bounds[2] = bounds.z;
- gipd.dynamic_range = storage->gi_probe_get_dynamic_range(base_probe) * storage->gi_probe_get_energy(base_probe);
- gipd.bias = storage->gi_probe_get_bias(base_probe);
- gipd.normal_bias = storage->gi_probe_get_normal_bias(base_probe);
- gipd.blend_ambient = !storage->gi_probe_is_interior(base_probe);
+ gipd.dynamic_range = storage->voxel_gi_get_dynamic_range(base_probe) * storage->voxel_gi_get_energy(base_probe);
+ gipd.bias = storage->voxel_gi_get_bias(base_probe);
+ gipd.normal_bias = storage->voxel_gi_get_normal_bias(base_probe);
+ gipd.blend_ambient = !storage->voxel_gi_is_interior(base_probe);
gipd.anisotropy_strength = 0;
- gipd.ao = storage->gi_probe_get_ao(base_probe);
- gipd.ao_size = Math::pow(storage->gi_probe_get_ao_size(base_probe), 4.0f);
+ gipd.ao = storage->voxel_gi_get_ao(base_probe);
+ gipd.ao_size = Math::pow(storage->voxel_gi_get_ao_size(base_probe), 4.0f);
gipd.mipmaps = gipi->mipmaps.size();
}
- r_gi_probes_used++;
+ r_voxel_gi_instances_used++;
}
if (texture == RID()) {
texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
}
- if (texture != rb->gi.giprobe_textures[i]) {
- giprobes_changed = true;
- rb->gi.giprobe_textures[i] = texture;
+ if (texture != rb->gi.voxel_gi_textures[i]) {
+ voxel_gi_instances_changed = true;
+ rb->gi.voxel_gi_textures[i] = texture;
}
}
- if (giprobes_changed) {
+ if (voxel_gi_instances_changed) {
if (RD::get_singleton()->uniform_set_is_valid(rb->gi.uniform_set)) {
RD::get_singleton()->free(rb->gi.uniform_set);
}
@@ -3112,14 +3112,14 @@ void RendererSceneGIRD::setup_giprobes(RID p_render_buffers, const Transform &p_
}
}
- if (p_gi_probes.size() > 0) {
- RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GIProbeData) * MIN((uint64_t)MAX_GIPROBES, p_gi_probes.size()), gi_probe_data, RD::BARRIER_MASK_COMPUTE);
+ if (p_voxel_gi_instances.size() > 0) {
+ RD::get_singleton()->buffer_update(voxel_gi_buffer, 0, sizeof(VoxelGIData) * MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()), voxel_gi_data, RD::BARRIER_MASK_COMPUTE);
}
RD::get_singleton()->draw_command_end_label();
}
-void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, RendererSceneRenderRD *p_scene_render) {
+void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
RD::get_singleton()->draw_command_begin_label("GI Render");
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
@@ -3157,11 +3157,11 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
- push_constant.max_giprobes = MIN((uint64_t)MAX_GIPROBES, p_gi_probes.size());
- push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH;
+ push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
+ push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH;
bool use_sdfgi = rb->sdfgi != nullptr;
- bool use_giprobes = push_constant.max_giprobes > 0;
+ bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
if (env) {
push_constant.ao_color[0] = env->ao_color.r;
@@ -3311,7 +3311,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 14;
- RID buffer = p_gi_probe_buffer.is_valid() ? p_gi_probe_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
u.ids.push_back(buffer);
uniforms.push_back(u);
}
@@ -3326,15 +3326,15 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 16;
- u.ids.push_back(rb->gi.giprobe_buffer);
+ u.ids.push_back(rb->gi.voxel_gi_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 17;
- for (int i = 0; i < MAX_GIPROBES; i++) {
- u.ids.push_back(rb->gi.giprobe_textures[i]);
+ for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
+ u.ids.push_back(rb->gi.voxel_gi_textures[i]);
}
uniforms.push_back(u);
}
@@ -3345,9 +3345,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
Mode mode;
if (rb->gi.using_half_size_gi) {
- mode = (use_sdfgi && use_giprobes) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_GIPROBE);
+ mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI);
} else {
- mode = (use_sdfgi && use_giprobes) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_GIPROBE);
+ mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
}
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]);
@@ -3364,39 +3364,39 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::get_singleton()->draw_command_end_label();
}
-RID RendererSceneGIRD::gi_probe_instance_create(RID p_base) {
- GIProbeInstance gi_probe;
- gi_probe.gi = this;
- gi_probe.storage = storage;
- gi_probe.probe = p_base;
- RID rid = gi_probe_instance_owner.make_rid(gi_probe);
+RID RendererSceneGIRD::voxel_gi_instance_create(RID p_base) {
+ VoxelGIInstance voxel_gi;
+ voxel_gi.gi = this;
+ voxel_gi.storage = storage;
+ voxel_gi.probe = p_base;
+ RID rid = voxel_gi_instance_owner.make_rid(voxel_gi);
return rid;
}
-void RendererSceneGIRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
- GIProbeInstance *gi_probe = get_probe_instance(p_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererSceneGIRD::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
+ VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->transform = p_xform;
+ voxel_gi->transform = p_xform;
}
-bool RendererSceneGIRD::gi_probe_needs_update(RID p_probe) const {
- GIProbeInstance *gi_probe = get_probe_instance(p_probe);
- ERR_FAIL_COND_V(!gi_probe, false);
+bool RendererSceneGIRD::voxel_gi_needs_update(RID p_probe) const {
+ VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+ ERR_FAIL_COND_V(!voxel_gi, false);
- return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
+ return voxel_gi->last_probe_version != storage->voxel_gi_get_version(voxel_gi->probe);
}
-void RendererSceneGIRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
- GIProbeInstance *gi_probe = get_probe_instance(p_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererSceneGIRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+ VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);
+ voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);
}
-void RendererSceneGIRD::debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererSceneGIRD::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+ VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->debug(p_draw_list, p_framebuffer, p_camera_with_transform, p_lighting, p_emission, p_alpha);
+ voxel_gi->debug(p_draw_list, p_framebuffer, p_camera_with_transform, p_lighting, p_emission, p_alpha);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index 59f5f374d1..45fc7b3951 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -38,13 +38,13 @@
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/gi.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/giprobe.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/giprobe_debug.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -56,9 +56,9 @@ class RendererSceneGIRD {
private:
RendererStorageRD *storage;
- /* GIPROBE INSTANCE */
+ /* VOXEL_GI INSTANCE */
- struct GIProbeLight {
+ struct VoxelGILight {
uint32_t type;
float energy;
float radius;
@@ -74,7 +74,7 @@ private:
uint32_t has_shadow;
};
- struct GIProbePushConstant {
+ struct VoxelGIPushConstant {
int32_t limits[3];
uint32_t stack_size;
@@ -89,7 +89,7 @@ private:
uint32_t pad;
};
- struct GIProbeDynamicPushConstant {
+ struct VoxelGIDynamicPushConstant {
int32_t limits[3];
uint32_t light_count;
int32_t x_dir[3];
@@ -110,36 +110,36 @@ private:
float pad[3];
};
- GIProbeLight *gi_probe_lights;
- uint32_t gi_probe_max_lights;
- RID gi_probe_lights_uniform;
+ VoxelGILight *voxel_gi_lights;
+ uint32_t voxel_gi_max_lights;
+ RID voxel_gi_lights_uniform;
enum {
- GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT,
- GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE,
- GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP,
- GI_PROBE_SHADER_VERSION_WRITE_TEXTURE,
- GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING,
- GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE,
- GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT,
- GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT,
- GI_PROBE_SHADER_VERSION_MAX
+ VOXEL_GI_SHADER_VERSION_COMPUTE_LIGHT,
+ VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE,
+ VOXEL_GI_SHADER_VERSION_COMPUTE_MIPMAP,
+ VOXEL_GI_SHADER_VERSION_WRITE_TEXTURE,
+ VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING,
+ VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE,
+ VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_PLOT,
+ VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT,
+ VOXEL_GI_SHADER_VERSION_MAX
};
- GiprobeShaderRD giprobe_shader;
- RID giprobe_lighting_shader_version;
- RID giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_MAX];
- RID giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_MAX];
+ VoxelGiShaderRD voxel_gi_shader;
+ RID voxel_gi_lighting_shader_version;
+ RID voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_MAX];
+ RID voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_MAX];
enum {
- GI_PROBE_DEBUG_COLOR,
- GI_PROBE_DEBUG_LIGHT,
- GI_PROBE_DEBUG_EMISSION,
- GI_PROBE_DEBUG_LIGHT_FULL,
- GI_PROBE_DEBUG_MAX
+ VOXEL_GI_DEBUG_COLOR,
+ VOXEL_GI_DEBUG_LIGHT,
+ VOXEL_GI_DEBUG_EMISSION,
+ VOXEL_GI_DEBUG_LIGHT_FULL,
+ VOXEL_GI_DEBUG_MAX
};
- struct GIProbeDebugPushConstant {
+ struct VoxelGIDebugPushConstant {
float projection[16];
uint32_t cell_offset;
float dynamic_range;
@@ -149,11 +149,11 @@ private:
uint32_t pad;
};
- GiprobeDebugShaderRD giprobe_debug_shader;
- RID giprobe_debug_shader_version;
- RID giprobe_debug_shader_version_shaders[GI_PROBE_DEBUG_MAX];
- PipelineCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX];
- RID giprobe_debug_uniform_set;
+ VoxelGiDebugShaderRD voxel_gi_debug_shader;
+ RID voxel_gi_debug_shader_version;
+ RID voxel_gi_debug_shader_version_shaders[VOXEL_GI_DEBUG_MAX];
+ PipelineCacheRD voxel_gi_debug_shader_version_pipelines[VOXEL_GI_DEBUG_MAX];
+ RID voxel_gi_debug_uniform_set;
/* SDFGI */
@@ -326,11 +326,11 @@ private:
} sdfgi_shader;
public:
- /* GIPROBE INSTANCE */
+ /* VOXEL_GI INSTANCE */
- //@TODO GIProbeInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
+ //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
- struct GIProbeInstance {
+ struct VoxelGIInstance {
// access to our containers
RendererStorageRD *storage;
RendererSceneGIRD *gi;
@@ -374,25 +374,25 @@ public:
bool has_dynamic_object_data = false;
- Transform transform;
+ Transform3D transform;
void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
};
- mutable RID_Owner<GIProbeInstance> gi_probe_instance_owner;
+ mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
- _FORCE_INLINE_ GIProbeInstance *get_probe_instance(RID p_probe) const {
- return gi_probe_instance_owner.getornull(p_probe);
+ _FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const {
+ return voxel_gi_instance_owner.getornull(p_probe);
};
- _FORCE_INLINE_ RID gi_probe_instance_get_texture(RID p_probe) {
- GIProbeInstance *gi_probe = get_probe_instance(p_probe);
- ERR_FAIL_COND_V(!gi_probe, RID());
- return gi_probe->texture;
+ _FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) {
+ VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+ ERR_FAIL_COND_V(!voxel_gi, RID());
+ return voxel_gi->texture;
};
- RS::GIProbeQuality gi_probe_quality = RS::GI_PROBE_QUALITY_HIGH;
+ RS::VoxelGIQuality voxel_gi_quality = RS::VOXEL_GI_QUALITY_HIGH;
/* SDFGI */
@@ -527,10 +527,10 @@ public:
int get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const;
void update_cascades();
- void debug_draw(const CameraMatrix &p_projection, const Transform &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture);
+ void debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture);
void debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
- void pre_process_gi(const Transform &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
+ void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render);
void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
};
@@ -551,13 +551,13 @@ public:
/* GI */
enum {
- MAX_GIPROBES = 8
+ MAX_VOXEL_GI_INSTANCES = 8
};
// Struct for use in render buffer
struct RenderBuffersGI {
- RID giprobe_textures[MAX_GIPROBES];
- RID giprobe_buffer;
+ RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
+ RID voxel_gi_buffer;
RID full_buffer;
RID full_dispatch;
@@ -601,7 +601,7 @@ public:
ProbeCascadeData cascades[SDFGI::MAX_CASCADES];
};
- struct GIProbeData {
+ struct VoxelGIData {
float xform[16];
float bounds[3];
float dynamic_range;
@@ -624,7 +624,7 @@ public:
float proj_info[4];
float ao_color[3];
- uint32_t max_giprobes;
+ uint32_t max_voxel_gi_instances;
uint32_t high_quality_vct;
uint32_t orthogonal;
@@ -635,16 +635,16 @@ public:
RID sdfgi_ubo;
enum Mode {
- MODE_GIPROBE,
+ MODE_VOXEL_GI,
MODE_SDFGI,
MODE_COMBINED,
- MODE_HALF_RES_GIPROBE,
+ MODE_HALF_RES_VOXEL_GI,
MODE_HALF_RES_SDFGI,
MODE_HALF_RES_COMBINED,
MODE_MAX
};
- RID default_giprobe_buffer;
+ RID default_voxel_gi_buffer;
bool half_resolution = false;
GiShaderRD shader;
@@ -659,14 +659,14 @@ public:
SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
- void setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used, RendererSceneRenderRD *p_scene_render);
- void process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, RendererSceneRenderRD *p_scene_render);
+ void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
+ void process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
- RID gi_probe_instance_create(RID p_base);
- void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
- bool gi_probe_needs_update(RID p_probe) const;
- void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
- void debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ RID voxel_gi_instance_create(RID p_base);
+ void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
+ bool voxel_gi_needs_update(RID p_probe) const;
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
+ void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
};
#endif /* !RENDERING_SERVER_SCENE_GI_RD_H */
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 1f01de1333..be98fb42c0 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -570,7 +570,7 @@ RID RendererSceneRenderRD::reflection_probe_instance_create(RID p_probe) {
return reflection_probe_instance_owner.make_rid(rpi);
}
-void RendererSceneRenderRD::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {
+void RendererSceneRenderRD::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND(!rpi);
@@ -1233,7 +1233,7 @@ RID RendererSceneRenderRD::light_instance_create(RID p_light) {
return li;
}
-void RendererSceneRenderRD::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {
+void RendererSceneRenderRD::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) {
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
@@ -1247,7 +1247,7 @@ void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const
light_instance->aabb = p_aabb;
}
-void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
+void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
@@ -1305,7 +1305,7 @@ RID RendererSceneRenderRD::decal_instance_create(RID p_decal) {
return decal_instance_owner.make_rid(di);
}
-void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Transform &p_transform) {
+void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) {
DecalInstance *di = decal_instance_owner.getornull(p_decal);
ERR_FAIL_COND(!di);
di->transform = p_transform;
@@ -1318,7 +1318,7 @@ RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) {
li.lightmap = p_lightmap;
return lightmap_instance_owner.make_rid(li);
}
-void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) {
+void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {
LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap);
ERR_FAIL_COND(!li);
li->transform = p_transform;
@@ -1326,28 +1326,28 @@ void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, cons
/////////////////////////////////
-RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) {
- return gi.gi_probe_instance_create(p_base);
+RID RendererSceneRenderRD::voxel_gi_instance_create(RID p_base) {
+ return gi.voxel_gi_instance_create(p_base);
}
-void RendererSceneRenderRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
- gi.gi_probe_instance_set_transform_to_data(p_probe, p_xform);
+void RendererSceneRenderRD::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
+ gi.voxel_gi_instance_set_transform_to_data(p_probe, p_xform);
}
-bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {
+bool RendererSceneRenderRD::voxel_gi_needs_update(RID p_probe) const {
if (!is_dynamic_gi_supported()) {
return false;
}
- return gi.gi_probe_needs_update(p_probe);
+ return gi.voxel_gi_needs_update(p_probe);
}
-void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
+void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
if (!is_dynamic_gi_supported()) {
return;
}
- gi.gi_probe_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this);
+ gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this);
}
void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
@@ -1728,7 +1728,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.half_screen_size = Size2i(buffer_width, buffer_height);
settings.quarter_screen_size = Size2i(half_width, half_height);
- storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid);
+ storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ssao.downsample_uniform_set, rb->ssao.gather_uniform_set, rb->ssao.importance_map_uniform_set);
}
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
@@ -1857,6 +1857,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
}
+ tonemap.view_count = p_render_data->view_count;
+
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
}
@@ -1959,17 +1961,17 @@ RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) {
return rb->ssao.ao_final;
}
-RID RendererSceneRenderRD::render_buffers_get_gi_probe_buffer(RID p_render_buffers) {
+RID RendererSceneRenderRD::render_buffers_get_voxel_gi_buffer(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
- if (rb->gi.giprobe_buffer.is_null()) {
- rb->gi.giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererSceneGIRD::GIProbeData) * RendererSceneGIRD::MAX_GIPROBES);
+ if (rb->gi.voxel_gi_buffer.is_null()) {
+ rb->gi.voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererSceneGIRD::VoxelGIData) * RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES);
}
- return rb->gi.giprobe_buffer;
+ return rb->gi.voxel_gi_buffer;
}
-RID RendererSceneRenderRD::render_buffers_get_default_gi_probe_buffer() {
- return gi.default_giprobe_buffer;
+RID RendererSceneRenderRD::render_buffers_get_default_voxel_gi_buffer() {
+ return gi.default_voxel_gi_buffer;
}
RID RendererSceneRenderRD::render_buffers_get_gi_ambient_texture(RID p_render_buffers) {
@@ -2112,7 +2114,9 @@ float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID
return rb->volumetric_fog->spread;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) {
+void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
+ ERR_FAIL_COND_MSG(p_view_count == 0, "Must have atleast 1 view");
+
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
rb->width = p_width;
rb->height = p_height;
@@ -2120,6 +2124,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->msaa = p_msaa;
rb->screen_space_aa = p_screen_space_aa;
rb->use_debanding = p_use_debanding;
+ rb->view_count = p_view_count;
if (is_clustered_enabled()) {
if (rb->cluster_builder == nullptr) {
@@ -2132,9 +2137,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
{
RD::TextureFormat tf;
+ if (rb->view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ }
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = rb->width;
tf.height = rb->height;
+ tf.array_layers = rb->view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -2147,6 +2156,9 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
{
RD::TextureFormat tf;
+ if (rb->view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ }
if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) {
tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
} else {
@@ -2156,6 +2168,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.width = p_width;
tf.height = p_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+ tf.array_layers = rb->view_count; // create a layer for every view
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -2166,7 +2179,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
- rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa);
+ rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
@@ -2284,7 +2297,7 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
return rb->data;
}
-void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment) {
+void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
cluster.reflection_count = 0;
for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
@@ -2344,8 +2357,8 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
- Transform transform = rpi->transform;
- Transform proj = (p_camera_inverse_transform * transform).inverse();
+ Transform3D transform = rpi->transform;
+ Transform3D proj = (p_camera_inverse_transform * transform).inverse();
RendererStorageRD::store_transform(proj, reflection_ubo.local_matrix);
if (current_cluster_builder != nullptr) {
@@ -2360,8 +2373,8 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
}
}
-void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
- Transform inverse_transform = p_camera_transform.affine_inverse();
+void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
+ Transform3D inverse_transform = p_camera_transform.affine_inverse();
r_directional_light_count = 0;
r_positional_light_count = 0;
@@ -2387,7 +2400,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
// Copy to SkyDirectionalLightData
if (r_directional_light_count < sky.sky_scene_state.max_directional_lights) {
RendererSceneSkyRD::SkyDirectionalLightData &sky_light_data = sky.sky_scene_state.directional_lights[r_directional_light_count];
- Transform light_transform = li->transform;
+ Transform3D light_transform = li->transform;
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
sky_light_data.direction[0] = world_direction.x;
@@ -2423,7 +2436,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
Cluster::DirectionalLightData &light_data = cluster.directional_lights[r_directional_light_count];
- Transform light_transform = li->transform;
+ Transform3D light_transform = li->transform;
Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized();
@@ -2513,7 +2526,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
CameraMatrix rectm;
rectm.set_light_atlas_rect(atlas_rect);
- Transform modelview = (inverse_transform * li->shadow_transform[j].transform).inverse();
+ Transform3D modelview = (inverse_transform * li->shadow_transform[j].transform).inverse();
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
@@ -2609,7 +2622,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
LightInstance *li = (i < cluster.omni_light_count) ? cluster.omni_light_sort[index].instance : cluster.spot_light_sort[index].instance;
RID base = li->light;
- Transform light_transform = li->transform;
+ Transform3D light_transform = li->transform;
float sign = storage->light_is_negative(base) ? -1 : 1;
Color linear_col = storage->light_get_color(base).to_linear();
@@ -2709,7 +2722,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
if (type == RS::LIGHT_OMNI) {
light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another
- Transform proj = (inverse_transform * light_transform).inverse();
+ Transform3D proj = (inverse_transform * light_transform).inverse();
RendererStorageRD::store_transform(proj, light_data.shadow_matrix);
@@ -2721,7 +2734,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
} else if (type == RS::LIGHT_SPOT) {
- Transform modelview = (inverse_transform * light_transform).inverse();
+ Transform3D modelview = (inverse_transform * light_transform).inverse();
CameraMatrix bias;
bias.set_light_bias();
@@ -2765,8 +2778,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
}
-void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform) {
- Transform uv_xform;
+void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) {
+ Transform3D uv_xform;
uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
@@ -2785,7 +2798,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
}
RID decal = di->decal;
- Transform xform = di->transform;
+ Transform3D xform = di->transform;
real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
@@ -2817,7 +2830,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
di->render_index = i;
di->cull_mask = storage->decal_get_cull_mask(decal);
- Transform xform = di->transform;
+ Transform3D xform = di->transform;
float fade = 1.0;
if (storage->decal_is_distance_fade_enabled(decal)) {
@@ -2834,9 +2847,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
Vector3 decal_extents = storage->decal_get_extents(decal);
- Transform scale_xform;
+ Transform3D scale_xform;
scale_xform.basis.scale(Vector3(decal_extents.x, decal_extents.y, decal_extents.z));
- Transform to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse();
+ Transform3D to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse();
RendererStorageRD::store_transform(to_decal_xform, dd.xform);
Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized();
@@ -3066,7 +3079,7 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
rb->volumetric_fog = nullptr;
}
-void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count) {
+void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count) {
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -3228,7 +3241,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 11;
- u.ids.push_back(render_buffers_get_gi_probe_buffer(p_render_buffers));
+ u.ids.push_back(render_buffers_get_voxel_gi_buffer(p_render_buffers));
uniforms.push_back(u);
}
@@ -3236,8 +3249,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 12;
- for (int i = 0; i < RendererSceneGIRD::MAX_GIPROBES; i++) {
- u.ids.push_back(rb->gi.giprobe_textures[i]);
+ for (int i = 0; i < RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES; i++) {
+ u.ids.push_back(rb->gi.voxel_gi_textures[i]);
}
uniforms.push_back(u);
}
@@ -3362,10 +3375,10 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.cam_rotation[10] = p_cam_transform.basis[2][2];
params.cam_rotation[11] = 0;
params.filter_axis = 0;
- params.max_gi_probes = env->volumetric_fog_gi_inject > 0.001 ? p_gi_probe_count : 0;
+ params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0;
params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
- Transform to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform;
+ Transform3D to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform;
storage->store_transform(to_prev_cam_view, params.to_prev_view);
params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
@@ -3492,17 +3505,15 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo
}
}
-void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer) {
+void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) {
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
if (p_render_data->render_buffers.is_valid() && p_use_gi) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
ERR_FAIL_COND(rb == nullptr);
- if (rb->sdfgi == nullptr) {
- return;
+ if (rb->sdfgi != nullptr) {
+ rb->sdfgi->store_probes();
}
-
- rb->sdfgi->store_probes();
}
render_state.cube_shadows.clear();
@@ -3569,7 +3580,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
//start GI
if (render_gi) {
- gi.process_gi(p_render_data->render_buffers, p_normal_roughness_buffer, p_gi_probe_buffer, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, *p_render_data->gi_probes, this);
+ gi.process_gi(p_render_data->render_buffers, p_normal_roughness_buffer, p_voxel_gi_buffer, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this);
}
//Do shadow rendering (in parallel with GI)
@@ -3625,12 +3636,12 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
if (is_volumetric_supported()) {
- _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.gi_probe_count);
+ _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count);
}
}
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data) {
// getting this here now so we can direct call a bunch of things more easily
RenderBuffers *rb = nullptr;
if (p_render_buffers.is_valid()) {
@@ -3643,16 +3654,24 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
{
render_data.render_buffers = p_render_buffers;
- render_data.cam_transform = p_cam_transform;
- render_data.cam_projection = p_cam_projection;
- render_data.cam_ortogonal = p_cam_projection.is_orthogonal(); // !BAS! Shouldn't this be p_cam_ortogonal ?
- render_data.z_near = p_cam_projection.get_z_near();
- render_data.z_far = p_cam_projection.get_z_far();
+ // Our first camera is used by default
+ render_data.cam_transform = p_camera_data->main_transform;
+ render_data.cam_projection = p_camera_data->main_projection;
+ render_data.view_projection[0] = p_camera_data->main_projection;
+ render_data.cam_ortogonal = p_camera_data->is_ortogonal;
+
+ render_data.view_count = p_camera_data->view_count;
+ for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
+ render_data.view_projection[v] = p_camera_data->view_projection[v];
+ }
+
+ render_data.z_near = p_camera_data->main_projection.get_z_near();
+ render_data.z_far = p_camera_data->main_projection.get_z_far();
render_data.instances = &p_instances;
render_data.lights = &p_lights;
render_data.reflection_probes = &p_reflection_probes;
- render_data.gi_probes = &p_gi_probes;
+ render_data.voxel_gi_instances = &p_voxel_gi_instances;
render_data.decals = &p_decals;
render_data.lightmaps = &p_lightmaps;
render_data.environment = p_environment;
@@ -3662,8 +3681,9 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
render_data.reflection_probe = p_reflection_probe;
render_data.reflection_probe_pass = p_reflection_probe_pass;
- render_data.lod_distance_multiplier = p_cam_projection.get_lod_multiplier();
- render_data.lod_camera_plane = Plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ // this should be the same for all cameras..
+ render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
+ render_data.lod_camera_plane = Plane(p_camera_data->main_transform.get_origin(), -p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z));
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
render_data.screen_lod_threshold = 0.0;
@@ -3683,7 +3703,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
render_data.lights = &empty;
render_data.reflection_probes = &empty;
- render_data.gi_probes = &empty;
+ render_data.voxel_gi_instances = &empty;
}
//sdfgi first
@@ -3703,12 +3723,12 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
clear_color = storage->get_default_clear_color();
}
- //assign render indices to giprobes
+ //assign render indices to voxel_gi_instances
if (is_dynamic_gi_supported()) {
- for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) {
- RendererSceneGIRD::GIProbeInstance *giprobe_inst = gi.gi_probe_instance_owner.getornull(p_gi_probes[i]);
- if (giprobe_inst) {
- giprobe_inst->render_index = i;
+ for (uint32_t i = 0; i < (uint32_t)p_voxel_gi_instances.size(); i++) {
+ RendererSceneGIRD::VoxelGIInstance *voxel_gi_inst = gi.voxel_gi_instance_owner.getornull(p_voxel_gi_instances[i]);
+ if (voxel_gi_inst) {
+ voxel_gi_inst->render_index = i;
}
}
}
@@ -3730,17 +3750,18 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
current_cluster_builder = nullptr;
}
- if (rb != nullptr && rb->sdfgi != nullptr) {
- rb->sdfgi->update_cascades();
-
- rb->sdfgi->pre_process_gi(p_cam_transform, &render_data, this);
- }
+ render_state.voxel_gi_count = 0;
- render_state.gi_probe_count = 0;
- if (rb != nullptr && rb->sdfgi != nullptr) {
- gi.setup_giprobes(render_data.render_buffers, render_data.cam_transform, *render_data.gi_probes, render_state.gi_probe_count, this);
+ if (rb != nullptr) {
+ if (rb->sdfgi) {
+ rb->sdfgi->update_cascades();
+ rb->sdfgi->pre_process_gi(render_data.cam_transform, &render_data, this);
+ rb->sdfgi->update_light();
+ }
- rb->sdfgi->update_light();
+ if (p_voxel_gi_instances.size()) {
+ gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
+ }
}
render_state.depth_prepass_used = false;
@@ -3782,7 +3803,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
_render_buffers_post_process_and_tonemap(&render_data);
_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) {
- rb->sdfgi->debug_draw(p_cam_projection, p_cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
+ rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
}
}
}
@@ -3808,7 +3829,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
bool flip_y = false;
CameraMatrix light_projection;
- Transform light_transform;
+ Transform3D light_transform;
if (storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
//set pssm stuff
@@ -3958,11 +3979,11 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
}
}
-void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);
}
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
CameraMatrix cm;
@@ -3971,7 +3992,7 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
Vector3 cam_pos = p_transform.origin;
cam_pos.y += extents.y;
- Transform cam_xform;
+ Transform3D cam_xform;
cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_axis(Vector3::AXIS_Y), -p_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider);
@@ -4018,19 +4039,19 @@ bool RendererSceneRenderRD::free(RID p_rid) {
decal_instance_owner.free(p_rid);
} else if (lightmap_instance_owner.owns(p_rid)) {
lightmap_instance_owner.free(p_rid);
- } else if (gi.gi_probe_instance_owner.owns(p_rid)) {
- RendererSceneGIRD::GIProbeInstance *gi_probe = gi.gi_probe_instance_owner.getornull(p_rid);
- if (gi_probe->texture.is_valid()) {
- RD::get_singleton()->free(gi_probe->texture);
- RD::get_singleton()->free(gi_probe->write_buffer);
+ } else if (gi.voxel_gi_instance_owner.owns(p_rid)) {
+ RendererSceneGIRD::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.getornull(p_rid);
+ if (voxel_gi->texture.is_valid()) {
+ RD::get_singleton()->free(voxel_gi->texture);
+ RD::get_singleton()->free(voxel_gi->write_buffer);
}
- for (int i = 0; i < gi_probe->dynamic_maps.size(); i++) {
- RD::get_singleton()->free(gi_probe->dynamic_maps[i].texture);
- RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth);
+ for (int i = 0; i < voxel_gi->dynamic_maps.size(); i++) {
+ RD::get_singleton()->free(voxel_gi->dynamic_maps[i].texture);
+ RD::get_singleton()->free(voxel_gi->dynamic_maps[i].depth);
}
- gi.gi_probe_instance_owner.free(p_rid);
+ gi.voxel_gi_instance_owner.free(p_rid);
} else if (sky.sky_owner.owns(p_rid)) {
sky.update_dirty_skys();
sky.free_sky(p_rid);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 1f82ae6dec..9a793e42c5 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -46,17 +46,21 @@
struct RenderDataRD {
RID render_buffers = RID();
- Transform cam_transform = Transform();
+ Transform3D cam_transform = Transform3D();
CameraMatrix cam_projection = CameraMatrix();
bool cam_ortogonal = false;
+ // For stereo rendering
+ uint32_t view_count = 1;
+ CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+
float z_near = 0.0;
float z_far = 0.0;
const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
- const PagedArray<RID> *gi_probes = nullptr;
+ const PagedArray<RID> *voxel_gi_instances = nullptr;
const PagedArray<RID> *decals = nullptr;
const PagedArray<RID> *lightmaps = nullptr;
RID environment = RID();
@@ -87,26 +91,26 @@ protected:
double time_step = 0;
struct RenderBufferData {
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) = 0;
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0;
virtual ~RenderBufferData() {}
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
- void _setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
- void _setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform);
- void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);
+ void _setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
+ void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
+ void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
virtual void _render_shadow_begin() = 0;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true) = 0;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true) = 0;
virtual void _render_shadow_process() = 0;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
@@ -123,7 +127,7 @@ protected:
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
- void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer);
+ void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer);
// needed for a single argument calls (material and uv2)
PagedArrayPool<GeometryInstance *> cull_argument_pool;
@@ -184,7 +188,7 @@ private:
uint32_t render_index = 0;
uint32_t cull_mask = 0;
- Transform transform;
+ Transform3D transform;
};
mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
@@ -193,7 +197,7 @@ private:
struct DecalInstance {
RID decal;
- Transform transform;
+ Transform3D transform;
uint32_t render_index;
uint32_t cull_mask;
};
@@ -204,7 +208,7 @@ private:
struct LightmapInstance {
RID lightmap;
- Transform transform;
+ Transform3D transform;
};
mutable RID_Owner<LightmapInstance> lightmap_instance_owner;
@@ -312,7 +316,7 @@ private:
struct LightInstance {
struct ShadowTransform {
CameraMatrix camera;
- Transform transform;
+ Transform3D transform;
float farplane;
float split;
float bias_scale;
@@ -329,7 +333,7 @@ private:
AABB aabb;
RID self;
RID light;
- Transform transform;
+ Transform3D transform;
Vector3 light_vector;
Vector3 spot_vector;
@@ -411,6 +415,7 @@ private:
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_debanding = false;
+ uint32_t view_count = 1;
RID render_target;
@@ -454,6 +459,10 @@ private:
Vector<RID> ao_pong_slices;
RID ao_final;
RID importance_map[2];
+
+ RID downsample_uniform_set;
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
} ssao;
struct SSR {
@@ -631,7 +640,7 @@ private:
int render_sdfgi_region_count = 0;
const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr;
- uint32_t gi_probe_count = 0;
+ uint32_t voxel_gi_count = 0;
LocalVector<int> cube_shadows;
LocalVector<int> shadows;
@@ -663,7 +672,7 @@ private:
int last_shadow_filter = -1;
- Transform prev_cam_transform;
+ Transform3D prev_cam_transform;
};
enum {
@@ -692,7 +701,7 @@ private:
float detail_spread;
float gi_inject;
- uint32_t max_gi_probes;
+ uint32_t max_voxel_gi_instances;
uint32_t cluster_type_size;
float screen_size[2];
@@ -721,7 +730,7 @@ private:
bool volumetric_fog_filter_active = true;
void _volumetric_fog_erase(RenderBuffers *rb);
- void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count);
+ void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count);
RID shadow_sampler;
@@ -740,7 +749,7 @@ private:
void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true);
public:
- virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
+ virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0;
/* SHADOW ATLAS API */
@@ -878,9 +887,9 @@ public:
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure);
RID light_instance_create(RID p_light);
- void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
+ void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform);
void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb);
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2());
+ void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2());
void light_instance_mark_visible(RID p_light_instance);
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
@@ -888,7 +897,7 @@ public:
return li->light;
}
- _FORCE_INLINE_ Transform light_instance_get_base_transform(RID p_light_instance) {
+ _FORCE_INLINE_ Transform3D light_instance_get_base_transform(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->transform;
}
@@ -945,7 +954,7 @@ public:
return float(1.0) / shadow_size;
}
- _FORCE_INLINE_ Transform
+ _FORCE_INLINE_ Transform3D
light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].transform;
@@ -1019,7 +1028,7 @@ public:
}
virtual RID reflection_probe_instance_create(RID p_probe);
- virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform);
virtual void reflection_probe_release_atlas_index(RID p_instance);
virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
virtual bool reflection_probe_instance_has_reflection(RID p_instance);
@@ -1063,9 +1072,9 @@ public:
return rpi->last_pass;
}
- _FORCE_INLINE_ Transform reflection_probe_instance_get_transform(RID p_instance) {
+ _FORCE_INLINE_ Transform3D reflection_probe_instance_get_transform(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND_V(!rpi, Transform());
+ ERR_FAIL_COND_V(!rpi, Transform3D());
return rpi->transform;
}
@@ -1078,20 +1087,20 @@ public:
}
virtual RID decal_instance_create(RID p_decal);
- virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform);
+ virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform);
_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal) const {
DecalInstance *decal = decal_instance_owner.getornull(p_decal);
return decal->decal;
}
- _FORCE_INLINE_ Transform decal_instance_get_transform(RID p_decal) const {
+ _FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal) const {
DecalInstance *decal = decal_instance_owner.getornull(p_decal);
return decal->transform;
}
virtual RID lightmap_instance_create(RID p_lightmap);
- virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform);
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform);
_FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr;
}
@@ -1100,7 +1109,7 @@ public:
LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
return li->lightmap;
}
- _FORCE_INLINE_ Transform lightmap_instance_get_transform(RID p_lightmap_instance) {
+ _FORCE_INLINE_ Transform3D lightmap_instance_get_transform(RID p_lightmap_instance) {
LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
return li->transform;
}
@@ -1109,22 +1118,22 @@ public:
/* gi light probes */
- RID gi_probe_instance_create(RID p_base);
- void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
- bool gi_probe_needs_update(RID p_probe) const;
- void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);
- void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi.gi_probe_quality = p_quality; }
+ RID voxel_gi_instance_create(RID p_base);
+ void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
+ bool voxel_gi_needs_update(RID p_probe) const;
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);
+ void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) { gi.voxel_gi_quality = p_quality; }
/* render buffers */
RID render_buffers_create();
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding);
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count);
void gi_set_use_half_resolution(bool p_enable);
RID render_buffers_get_ao_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
- RID render_buffers_get_gi_probe_buffer(RID p_render_buffers);
- RID render_buffers_get_default_gi_probe_buffer();
+ RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers);
+ RID render_buffers_get_default_voxel_gi_buffer();
RID render_buffers_get_gi_ambient_texture(RID p_render_buffers);
RID render_buffers_get_gi_reflection_texture(RID p_render_buffers);
@@ -1147,11 +1156,11 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr);
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr);
- void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances);
+ void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances);
virtual void set_scene_pass(uint64_t p_pass) {
scene_pass = p_pass;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 54c6e81110..1aa01dd16e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -30,7 +30,9 @@
#include "renderer_scene_sky_rd.h"
#include "core/config/project_settings.h"
+#include "core/math/math_defs.h"
#include "renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/rendering_server_default.h"
////////////////////////////////////////////////////////////////////////////////
@@ -125,8 +127,12 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
depth_stencil_state.enable_depth_test = true;
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
- RID shader_variant = scene_singleton->sky.sky_shader.shader.version_get_shader(version, i);
- pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
+ if (scene_singleton->sky.sky_shader.shader.is_variant_enabled(i)) {
+ RID shader_variant = scene_singleton->sky.sky_shader.shader.version_get_shader(version, i);
+ pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ pipelines[i].clear();
+ }
}
valid = true;
@@ -693,7 +699,18 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n"); // Cubemap
sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_HALF_RES_PASS\n"); // Half Res Cubemap
sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_QUARTER_RES_PASS\n"); // Quarter res Cubemap
+
+ sky_modes.push_back("\n#define USE_MULTIVIEW\n"); // Full size multiview
+ sky_modes.push_back("\n#define USE_HALF_RES_PASS\n#define USE_MULTIVIEW\n"); // Half Res multiview
+ sky_modes.push_back("\n#define USE_QUARTER_RES_PASS\n#define USE_MULTIVIEW\n"); // Quarter res multiview
+
sky_shader.shader.initialize(sky_modes, defines);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ sky_shader.shader.set_variant_enabled(SKY_VERSION_BACKGROUND_MULTIVIEW, false);
+ sky_shader.shader.set_variant_enabled(SKY_VERSION_HALF_RES_MULTIVIEW, false);
+ sky_shader.shader.set_variant_enabled(SKY_VERSION_QUARTER_RES_MULTIVIEW, false);
+ }
}
// register our shader funds
@@ -710,6 +727,9 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
actions.renames["SKY_COORDS"] = "panorama_coords";
actions.renames["SCREEN_UV"] = "uv";
actions.renames["TIME"] = "params.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
actions.renames["HALF_RES_COLOR"] = "half_res_color";
actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color";
actions.renames["RADIANCE"] = "radiance";
@@ -874,7 +894,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
}
}
-void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
ERR_FAIL_COND(!p_env); // I guess without an environment we also can't have a sky...
SkyMaterialData *material = nullptr;
@@ -1044,7 +1064,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
}
-void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform &p_transform, double p_time) {
+void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time) {
ERR_FAIL_COND(!p_env);
Sky *sky = get_sky(p_env->sky);
@@ -1131,12 +1151,12 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::DrawListID cubemap_draw_list;
for (int i = 0; i < 6; i++) {
- Transform local_view;
+ Transform3D local_view;
local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
}
@@ -1149,12 +1169,12 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::DrawListID cubemap_draw_list;
for (int i = 0; i < 6; i++) {
- Transform local_view;
+ Transform3D local_view;
local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
}
@@ -1163,12 +1183,12 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP];
for (int i = 0; i < 6; i++) {
- Transform local_view;
+ Transform3D local_view;
local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
@@ -1209,9 +1229,12 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
}
}
-void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, const CameraMatrix &p_projection, const Transform &p_transform, double p_time) {
+void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_view_count == 0);
+ ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
+
Sky *sky = get_sky(p_env->sky);
ERR_FAIL_COND(!sky);
@@ -1253,24 +1276,28 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
float multiplier = p_env->bg_energy;
float custom_fov = p_env->sky_custom_fov;
+
// Camera
CameraMatrix camera;
+ uint32_t view_count = p_view_count;
+ const CameraMatrix *projections = p_projections;
if (custom_fov) {
- float near_plane = p_projection.get_z_near();
- float far_plane = p_projection.get_z_far();
- float aspect = p_projection.get_aspect();
+ // With custom fov we don't support stereo...
+ float near_plane = p_projections[0].get_z_near();
+ float far_plane = p_projections[0].get_z_far();
+ float aspect = p_projections[0].get_aspect();
camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
- } else {
- camera = p_projection;
+ view_count = 1;
+ projections = &camera;
}
sky_transform = p_transform.basis * sky_transform;
if (shader_data->uses_quarter_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
@@ -1278,12 +1305,12 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- storage->get_effects()->render_sky(draw_list, p_time, sky->quarter_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ storage->get_effects()->render_sky(draw_list, p_time, sky->quarter_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
if (shader_data->uses_half_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
@@ -1291,11 +1318,11 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- storage->get_effects()->render_sky(draw_list, p_time, sky->half_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ storage->get_effects()->render_sky(draw_list, p_time, sky->half_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND];
RID texture_uniform_set;
if (sky) {
@@ -1305,7 +1332,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- storage->get_effects()->render_sky(draw_list, p_time, p_fb, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ storage->get_effects()->render_sky(draw_list, p_time, p_fb, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 73390a586b..200902bff2 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -72,6 +72,11 @@ public:
SKY_VERSION_CUBEMAP,
SKY_VERSION_CUBEMAP_HALF_RES,
SKY_VERSION_CUBEMAP_QUARTER_RES,
+
+ SKY_VERSION_BACKGROUND_MULTIVIEW,
+ SKY_VERSION_HALF_RES_MULTIVIEW,
+ SKY_VERSION_QUARTER_RES_MULTIVIEW,
+
SKY_VERSION_MAX
};
@@ -268,9 +273,9 @@ public:
void init(RendererStorageRD *p_storage);
- void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
- void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform &p_transform, double p_time);
- void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, const CameraMatrix &p_projection, const Transform &p_transform, double p_time);
+ void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
+ void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time);
+ void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index f419875d58..64be54115f 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -33,6 +33,7 @@
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/io/resource_loader.h"
+#include "core/math/math_defs.h"
#include "renderer_compositor_rd.h"
#include "servers/rendering/shader_language.h"
@@ -1439,8 +1440,10 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
material->shader_type = new_type;
}
- for (Map<StringName, RID>::Element *E = shader->default_texture_parameter.front(); E; E = E->next()) {
- shader->data->set_default_texture_param(E->key(), E->get());
+ if (shader->data) {
+ for (Map<StringName, RID>::Element *E = shader->default_texture_parameter.front(); E; E = E->next()) {
+ shader->data->set_default_texture_param(E->key(), E->get());
+ }
}
}
@@ -1877,8 +1880,8 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[1] = v.position.y;
gui[2] = v.size.x;
gui[3] = v.size.y;
- } else if (value.get_type() == Variant::QUAT) {
- Quat v = value;
+ } else if (value.get_type() == Variant::QUATERNION) {
+ Quaternion v = value;
gui[0] = v.x;
gui[1] = v.y;
@@ -1925,7 +1928,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[11] = 0;
} break;
case ShaderLanguage::TYPE_MAT4: {
- Transform v = value;
+ Transform3D v = value;
float *gui = (float *)data;
gui[0] = v.basis.elements[0][0];
@@ -2775,7 +2778,7 @@ AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
const float *dataptr = baseptr + j * 8;
- Transform mtx;
+ Transform3D mtx;
mtx.basis.elements[0].x = dataptr[0];
mtx.basis.elements[1].x = dataptr[1];
@@ -2802,7 +2805,7 @@ AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
const float *dataptr = baseptr + j * 12;
- Transform mtx;
+ Transform3D mtx;
mtx.basis.elements[0][0] = dataptr[0];
mtx.basis.elements[0][1] = dataptr[1];
@@ -3477,7 +3480,7 @@ void RendererStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const fl
AABB mesh_aabb = mesh_get_aabb(multimesh->mesh);
for (int i = 0; i < p_instances; i++) {
const float *data = p_data + multimesh->stride_cache * i;
- Transform t;
+ Transform3D t;
if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
t.basis.elements[0][0] = data[0];
@@ -3513,7 +3516,7 @@ void RendererStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const fl
multimesh->aabb = aabb;
}
-void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) {
+void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
@@ -3620,15 +3623,15 @@ RID RendererStorageRD::multimesh_get_mesh(RID p_multimesh) const {
return multimesh->mesh;
}
-Transform RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
+Transform3D RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform());
- ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform());
+ ERR_FAIL_COND_V(!multimesh, Transform3D());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
+ ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D());
_multimesh_make_local(multimesh);
- Transform t;
+ Transform3D t;
{
const float *r = multimesh->data_cache.ptr();
@@ -3822,7 +3825,7 @@ void RendererStorageRD::_update_dirty_multimeshes() {
if (multimesh->data_cache_used_dirty_regions) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- uint32_t visible_region_count = (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
@@ -4064,7 +4067,7 @@ void RendererStorageRD::particles_set_trails(RID p_particles, bool p_enable, flo
particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
}
-void RendererStorageRD::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform> &p_bind_poses) {
+void RendererStorageRD::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) {
@@ -4160,7 +4163,7 @@ void RendererStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitt
}
}
-void RendererStorageRD::particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+void RendererStorageRD::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
ERR_FAIL_COND(particles->amount == 0);
@@ -4228,7 +4231,7 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer);
- Transform inv = particles->emission_transform.affine_inverse();
+ Transform3D inv = particles->emission_transform.affine_inverse();
AABB aabb;
if (buffer.size()) {
@@ -4271,7 +4274,7 @@ AABB RendererStorageRD::particles_get_aabb(RID p_particles) const {
return particles->custom_aabb;
}
-void RendererStorageRD::particles_set_emission_transform(RID p_particles, const Transform &p_transform) {
+void RendererStorageRD::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
@@ -4305,6 +4308,15 @@ void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_partic
particles->collisions.erase(p_particles_collision_instance);
}
+void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
+ Particles *particles = particles_owner.getornull(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->has_sdf_collision = p_enable;
+ particles->sdf_collision_transform = p_xform;
+ particles->sdf_collision_to_screen = p_to_screen;
+ particles->sdf_collision_texture = p_texture;
+}
+
void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) {
if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -4386,7 +4398,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
frame_params.randomness = p_particles->randomness;
if (p_particles->use_local_coords) {
- store_transform(Transform(), frame_params.emission_transform);
+ store_transform(Transform3D(), frame_params.emission_transform);
} else {
store_transform(p_particles->emission_transform, frame_params.emission_transform);
}
@@ -4406,10 +4418,54 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
RID collision_heightmap_texture;
- Transform to_particles;
+ Transform3D to_particles;
if (p_particles->use_local_coords) {
to_particles = p_particles->emission_transform.affine_inverse();
}
+
+ if (p_particles->has_sdf_collision && RD::get_singleton()->texture_is_valid(p_particles->sdf_collision_texture)) {
+ //2D collision
+
+ Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
+ Transform2D revert = xform.affine_inverse();
+ frame_params.collider_count = 1;
+ frame_params.colliders[0].transform[0] = xform.elements[0][0];
+ frame_params.colliders[0].transform[1] = xform.elements[0][1];
+ frame_params.colliders[0].transform[2] = 0;
+ frame_params.colliders[0].transform[3] = xform.elements[2][0];
+
+ frame_params.colliders[0].transform[4] = xform.elements[1][0];
+ frame_params.colliders[0].transform[5] = xform.elements[1][1];
+ frame_params.colliders[0].transform[6] = 0;
+ frame_params.colliders[0].transform[7] = xform.elements[2][1];
+
+ frame_params.colliders[0].transform[8] = revert.elements[0][0];
+ frame_params.colliders[0].transform[9] = revert.elements[0][1];
+ frame_params.colliders[0].transform[10] = 0;
+ frame_params.colliders[0].transform[11] = revert.elements[2][0];
+
+ frame_params.colliders[0].transform[12] = revert.elements[1][0];
+ frame_params.colliders[0].transform[13] = revert.elements[1][1];
+ frame_params.colliders[0].transform[14] = 0;
+ frame_params.colliders[0].transform[15] = revert.elements[2][1];
+
+ frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
+ frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
+ frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x;
+ frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y;
+ frame_params.colliders[0].texture_index = 0;
+ frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF;
+
+ collision_heightmap_texture = p_particles->sdf_collision_texture;
+
+ //replace in all other history frames where used because parameters are no longer valid if screen moves
+ for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) {
+ if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) {
+ p_particles->frame_history[i].colliders[0] = frame_params.colliders[0];
+ }
+ }
+ }
+
uint32_t collision_3d_textures_used = 0;
for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(E->get());
@@ -4419,7 +4475,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
ParticlesCollision *pc = particles_collision_owner.getornull(pci->collision);
ERR_CONTINUE(!pc);
- Transform to_collider = pci->transform;
+ Transform3D to_collider = pci->transform;
if (p_particles->use_local_coords) {
to_collider = to_particles * to_collider;
}
@@ -4657,6 +4713,8 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
ERR_FAIL_COND(!m);
+ p_particles->has_collision_cache = m->shader_data->uses_collision;
+
//todo should maybe compute all particle systems together?
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline);
@@ -4740,6 +4798,11 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
copy_push_constant.trail_total = 1;
copy_push_constant.frame_delta = 0.0;
}
+
+ copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+ copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+ copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+
copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
copy_push_constant.total_particles = particles->amount;
@@ -5019,6 +5082,10 @@ void RendererStorageRD::update_particles() {
copy_push_constant.frame_delta = 0.0;
}
+ copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+ copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+ copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[particles->mode == RS::PARTICLES_MODE_2D ? ParticlesShader::COPY_MODE_FILL_INSTANCES_2D : ParticlesShader::COPY_MODE_FILL_INSTANCES]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
@@ -5049,6 +5116,7 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
valid = false;
ubo_size = 0;
uniforms.clear();
+ uses_collision = false;
if (code == String()) {
return; //just invalid, but no error
@@ -5068,6 +5136,8 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["TIME"] = &uses_time;
*/
+ actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
+
actions.uniforms = &uniforms;
Error err = base_singleton->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
@@ -5454,7 +5524,7 @@ RID RendererStorageRD::particles_collision_instance_create(RID p_collision) {
pci.collision = p_collision;
return particles_collision_instance_owner.make_rid(pci);
}
-void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) {
+void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
ERR_FAIL_COND(!pci);
pci->transform = p_transform;
@@ -5532,7 +5602,7 @@ int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
return skeleton->size;
}
-void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) {
+void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton);
@@ -5557,16 +5627,16 @@ void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone,
_skeleton_make_dirty(skeleton);
}
-Transform RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
+Transform3D RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
- ERR_FAIL_COND_V(!skeleton, Transform());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform());
- ERR_FAIL_COND_V(skeleton->use_2d, Transform());
+ ERR_FAIL_COND_V(!skeleton, Transform3D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
+ ERR_FAIL_COND_V(skeleton->use_2d, Transform3D());
const float *dataptr = skeleton->data.ptr() + p_bone * 12;
- Transform t;
+ Transform3D t;
t.basis.elements[0][0] = dataptr[0];
t.basis.elements[0][1] = dataptr[1];
@@ -6256,36 +6326,36 @@ AABB RendererStorageRD::decal_get_aabb(RID p_decal) const {
return AABB(-decal->extents, decal->extents * 2.0);
}
-RID RendererStorageRD::gi_probe_allocate() {
- return gi_probe_owner.allocate_rid();
+RID RendererStorageRD::voxel_gi_allocate() {
+ return voxel_gi_owner.allocate_rid();
}
-void RendererStorageRD::gi_probe_initialize(RID p_gi_probe) {
- gi_probe_owner.initialize_rid(p_gi_probe, GIProbe());
+void RendererStorageRD::voxel_gi_initialize(RID p_voxel_gi) {
+ voxel_gi_owner.initialize_rid(p_voxel_gi, VoxelGI());
}
-void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- if (gi_probe->octree_buffer.is_valid()) {
- RD::get_singleton()->free(gi_probe->octree_buffer);
- RD::get_singleton()->free(gi_probe->data_buffer);
- if (gi_probe->sdf_texture.is_valid()) {
- RD::get_singleton()->free(gi_probe->sdf_texture);
+ if (voxel_gi->octree_buffer.is_valid()) {
+ RD::get_singleton()->free(voxel_gi->octree_buffer);
+ RD::get_singleton()->free(voxel_gi->data_buffer);
+ if (voxel_gi->sdf_texture.is_valid()) {
+ RD::get_singleton()->free(voxel_gi->sdf_texture);
}
- gi_probe->sdf_texture = RID();
- gi_probe->octree_buffer = RID();
- gi_probe->data_buffer = RID();
- gi_probe->octree_buffer_size = 0;
- gi_probe->data_buffer_size = 0;
- gi_probe->cell_count = 0;
+ voxel_gi->sdf_texture = RID();
+ voxel_gi->octree_buffer = RID();
+ voxel_gi->data_buffer = RID();
+ voxel_gi->octree_buffer_size = 0;
+ voxel_gi->data_buffer_size = 0;
+ voxel_gi->cell_count = 0;
}
- gi_probe->to_cell_xform = p_to_cell_xform;
- gi_probe->bounds = p_aabb;
- gi_probe->octree_size = p_octree_size;
- gi_probe->level_counts = p_level_counts;
+ voxel_gi->to_cell_xform = p_to_cell_xform;
+ voxel_gi->bounds = p_aabb;
+ voxel_gi->octree_size = p_octree_size;
+ voxel_gi->level_counts = p_level_counts;
if (p_octree_cells.size()) {
ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32
@@ -6294,42 +6364,42 @@ void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform &
ERR_FAIL_COND(p_data_cells.size() != (int)cell_count * 16); //see that data size matches
- gi_probe->cell_count = cell_count;
- gi_probe->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells);
- gi_probe->octree_buffer_size = p_octree_cells.size();
- gi_probe->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells);
- gi_probe->data_buffer_size = p_data_cells.size();
+ voxel_gi->cell_count = cell_count;
+ voxel_gi->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells);
+ voxel_gi->octree_buffer_size = p_octree_cells.size();
+ voxel_gi->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells);
+ voxel_gi->data_buffer_size = p_data_cells.size();
if (p_distance_field.size()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = gi_probe->octree_size.x;
- tf.height = gi_probe->octree_size.y;
- tf.depth = gi_probe->octree_size.z;
+ tf.width = voxel_gi->octree_size.x;
+ tf.height = voxel_gi->octree_size.y;
+ tf.depth = voxel_gi->octree_size.z;
tf.texture_type = RD::TEXTURE_TYPE_3D;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
Vector<Vector<uint8_t>> s;
s.push_back(p_distance_field);
- gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
+ voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
}
#if 0
{
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = gi_probe->octree_size.x;
- tf.height = gi_probe->octree_size.y;
- tf.depth = gi_probe->octree_size.z;
+ tf.width = voxel_gi->octree_size.x;
+ tf.height = voxel_gi->octree_size.y;
+ tf.depth = voxel_gi->octree_size.z;
tf.type = RD::TEXTURE_TYPE_3D;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM);
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT);
- gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
RID shared_tex;
{
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_R8_UINT;
- shared_tex = RD::get_singleton()->texture_create_shared(tv, gi_probe->sdf_texture);
+ shared_tex = RD::get_singleton()->texture_create_shared(tv, voxel_gi->sdf_texture);
}
//update SDF texture
Vector<RD::Uniform> uniforms;
@@ -6337,14 +6407,14 @@ void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform &
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(gi_probe->octree_buffer);
+ u.ids.push_back(voxel_gi->octree_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.ids.push_back(gi_probe->data_buffer);
+ u.ids.push_back(voxel_gi->data_buffer);
uniforms.push_back(u);
}
{
@@ -6355,24 +6425,24 @@ void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform &
uniforms.push_back(u);
}
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_sdf_shader_version_shader, 0);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, voxel_gi_sdf_shader_version_shader, 0);
{
uint32_t push_constant[4] = { 0, 0, 0, 0 };
- for (int i = 0; i < gi_probe->level_counts.size() - 1; i++) {
- push_constant[0] += gi_probe->level_counts[i];
+ for (int i = 0; i < voxel_gi->level_counts.size() - 1; i++) {
+ push_constant[0] += voxel_gi->level_counts[i];
}
- push_constant[1] = push_constant[0] + gi_probe->level_counts[gi_probe->level_counts.size() - 1];
+ push_constant[1] = push_constant[0] + voxel_gi->level_counts[voxel_gi->level_counts.size() - 1];
print_line("offset: " + itos(push_constant[0]));
print_line("size: " + itos(push_constant[1]));
//create SDF
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_sdf_shader_pipeline);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, voxel_gi_sdf_shader_pipeline);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, push_constant, sizeof(uint32_t) * 4);
- RD::get_singleton()->compute_list_dispatch(compute_list, gi_probe->octree_size.x / 4, gi_probe->octree_size.y / 4, gi_probe->octree_size.z / 4);
+ RD::get_singleton()->compute_list_dispatch(compute_list, voxel_gi->octree_size.x / 4, voxel_gi->octree_size.y / 4, voxel_gi->octree_size.z / 4);
RD::get_singleton()->compute_list_end();
}
@@ -6382,232 +6452,232 @@ void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform &
#endif
}
- gi_probe->version++;
- gi_probe->data_version++;
+ voxel_gi->version++;
+ voxel_gi->data_version++;
- gi_probe->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
+ voxel_gi->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
-AABB RendererStorageRD::gi_probe_get_bounds(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, AABB());
+AABB RendererStorageRD::voxel_gi_get_bounds(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, AABB());
- return gi_probe->bounds;
+ return voxel_gi->bounds;
}
-Vector3i RendererStorageRD::gi_probe_get_octree_size(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, Vector3i());
- return gi_probe->octree_size;
+Vector3i RendererStorageRD::voxel_gi_get_octree_size(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector3i());
+ return voxel_gi->octree_size;
}
-Vector<uint8_t> RendererStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>());
+Vector<uint8_t> RendererStorageRD::voxel_gi_get_octree_cells(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
- if (gi_probe->octree_buffer.is_valid()) {
- return RD::get_singleton()->buffer_get_data(gi_probe->octree_buffer);
+ if (voxel_gi->octree_buffer.is_valid()) {
+ return RD::get_singleton()->buffer_get_data(voxel_gi->octree_buffer);
}
return Vector<uint8_t>();
}
-Vector<uint8_t> RendererStorageRD::gi_probe_get_data_cells(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>());
+Vector<uint8_t> RendererStorageRD::voxel_gi_get_data_cells(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
- if (gi_probe->data_buffer.is_valid()) {
- return RD::get_singleton()->buffer_get_data(gi_probe->data_buffer);
+ if (voxel_gi->data_buffer.is_valid()) {
+ return RD::get_singleton()->buffer_get_data(voxel_gi->data_buffer);
}
return Vector<uint8_t>();
}
-Vector<uint8_t> RendererStorageRD::gi_probe_get_distance_field(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>());
+Vector<uint8_t> RendererStorageRD::voxel_gi_get_distance_field(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
- if (gi_probe->data_buffer.is_valid()) {
- return RD::get_singleton()->texture_get_data(gi_probe->sdf_texture, 0);
+ if (voxel_gi->data_buffer.is_valid()) {
+ return RD::get_singleton()->texture_get_data(voxel_gi->sdf_texture, 0);
}
return Vector<uint8_t>();
}
-Vector<int> RendererStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, Vector<int>());
+Vector<int> RendererStorageRD::voxel_gi_get_level_counts(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector<int>());
- return gi_probe->level_counts;
+ return voxel_gi->level_counts;
}
-Transform RendererStorageRD::gi_probe_get_to_cell_xform(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, Transform());
+Transform3D RendererStorageRD::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Transform3D());
- return gi_probe->to_cell_xform;
+ return voxel_gi->to_cell_xform;
}
-void RendererStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->dynamic_range = p_range;
- gi_probe->version++;
+ voxel_gi->dynamic_range = p_range;
+ voxel_gi->version++;
}
-float RendererStorageRD::gi_probe_get_dynamic_range(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
+float RendererStorageRD::voxel_gi_get_dynamic_range(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
- return gi_probe->dynamic_range;
+ return voxel_gi->dynamic_range;
}
-void RendererStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->propagation = p_range;
- gi_probe->version++;
+ voxel_gi->propagation = p_range;
+ voxel_gi->version++;
}
-float RendererStorageRD::gi_probe_get_propagation(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->propagation;
+float RendererStorageRD::voxel_gi_get_propagation(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->propagation;
}
-void RendererStorageRD::gi_probe_set_energy(RID p_gi_probe, float p_energy) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_energy(RID p_voxel_gi, float p_energy) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->energy = p_energy;
+ voxel_gi->energy = p_energy;
}
-float RendererStorageRD::gi_probe_get_energy(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->energy;
+float RendererStorageRD::voxel_gi_get_energy(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->energy;
}
-void RendererStorageRD::gi_probe_set_ao(RID p_gi_probe, float p_ao) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_ao(RID p_voxel_gi, float p_ao) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->ao = p_ao;
+ voxel_gi->ao = p_ao;
}
-float RendererStorageRD::gi_probe_get_ao(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->ao;
+float RendererStorageRD::voxel_gi_get_ao(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->ao;
}
-void RendererStorageRD::gi_probe_set_ao_size(RID p_gi_probe, float p_strength) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->ao_size = p_strength;
+ voxel_gi->ao_size = p_strength;
}
-float RendererStorageRD::gi_probe_get_ao_size(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->ao_size;
+float RendererStorageRD::voxel_gi_get_ao_size(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->ao_size;
}
-void RendererStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->bias = p_bias;
+ voxel_gi->bias = p_bias;
}
-float RendererStorageRD::gi_probe_get_bias(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->bias;
+float RendererStorageRD::voxel_gi_get_bias(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->bias;
}
-void RendererStorageRD::gi_probe_set_normal_bias(RID p_gi_probe, float p_normal_bias) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->normal_bias = p_normal_bias;
+ voxel_gi->normal_bias = p_normal_bias;
}
-float RendererStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->normal_bias;
+float RendererStorageRD::voxel_gi_get_normal_bias(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->normal_bias;
}
-void RendererStorageRD::gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->anisotropy_strength = p_strength;
+ voxel_gi->anisotropy_strength = p_strength;
}
-float RendererStorageRD::gi_probe_get_anisotropy_strength(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->anisotropy_strength;
+float RendererStorageRD::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->anisotropy_strength;
}
-void RendererStorageRD::gi_probe_set_interior(RID p_gi_probe, bool p_enable) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->interior = p_enable;
+ voxel_gi->interior = p_enable;
}
-void RendererStorageRD::gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
+void RendererStorageRD::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
- gi_probe->use_two_bounces = p_enable;
- gi_probe->version++;
+ voxel_gi->use_two_bounces = p_enable;
+ voxel_gi->version++;
}
-bool RendererStorageRD::gi_probe_is_using_two_bounces(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, false);
- return gi_probe->use_two_bounces;
+bool RendererStorageRD::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, false);
+ return voxel_gi->use_two_bounces;
}
-bool RendererStorageRD::gi_probe_is_interior(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->interior;
+bool RendererStorageRD::voxel_gi_is_interior(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->interior;
}
-uint32_t RendererStorageRD::gi_probe_get_version(RID p_gi_probe) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->version;
+uint32_t RendererStorageRD::voxel_gi_get_version(RID p_voxel_gi) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->version;
}
-uint32_t RendererStorageRD::gi_probe_get_data_version(RID p_gi_probe) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, 0);
- return gi_probe->data_version;
+uint32_t RendererStorageRD::voxel_gi_get_data_version(RID p_voxel_gi) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->data_version;
}
-RID RendererStorageRD::gi_probe_get_octree_buffer(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, RID());
- return gi_probe->octree_buffer;
+RID RendererStorageRD::voxel_gi_get_octree_buffer(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, RID());
+ return voxel_gi->octree_buffer;
}
-RID RendererStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, RID());
- return gi_probe->data_buffer;
+RID RendererStorageRD::voxel_gi_get_data_buffer(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, RID());
+ return voxel_gi->data_buffer;
}
-RID RendererStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) {
- GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
- ERR_FAIL_COND_V(!gi_probe, RID());
+RID RendererStorageRD::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, RID());
- return gi_probe->sdf_texture;
+ return voxel_gi->sdf_texture;
}
/* LIGHTMAP API */
@@ -6843,9 +6913,13 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) {
rd_format.width = rt->size.width;
rd_format.height = rt->size.height;
rd_format.depth = 1;
- rd_format.array_layers = 1;
+ rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
rd_format.mipmaps = 1;
- rd_format.texture_type = RD::TEXTURE_TYPE_2D;
+ if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
+ rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else {
+ rd_format.texture_type = RD::TEXTURE_TYPE_2D;
+ }
rd_format.samples = RD::TEXTURE_SAMPLES_1;
rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
rd_format.shareable_formats.push_back(rt->color_format);
@@ -6857,7 +6931,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) {
Vector<RID> fb_textures;
fb_textures.push_back(rt->color);
- rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures);
+ rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
if (rt->framebuffer.is_null()) {
_clear_render_target(rt);
ERR_FAIL_COND(rt->framebuffer.is_null());
@@ -6971,12 +7045,15 @@ void RendererStorageRD::render_target_set_position(RID p_render_target, int p_x,
//unused for this render target
}
-void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height) {
+void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
- rt->size.x = p_width;
- rt->size.y = p_height;
- _update_render_target(rt);
+ if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) {
+ rt->size.x = p_width;
+ rt->size.y = p_height;
+ rt->view_count = p_view_count;
+ _update_render_target(rt);
+ }
}
RID RendererStorageRD::render_target_get_texture(RID p_render_target) {
@@ -7133,6 +7210,20 @@ Rect2i RendererStorageRD::render_target_get_sdf_rect(RID p_render_target) const
return _render_target_get_sdf_rect(rt);
}
+void RendererStorageRD::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->sdf_enabled = p_enabled;
+}
+
+bool RendererStorageRD::render_target_is_sdf_enabled(RID p_render_target) const {
+ const RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->sdf_enabled;
+}
+
RID RendererStorageRD::render_target_get_sdf_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
@@ -7200,7 +7291,7 @@ void RendererStorageRD::_render_target_allocate_sdf(RenderTarget *rt) {
rt->process_size.x = MAX(rt->process_size.x, 1);
rt->process_size.y = MAX(rt->process_size.y, 1);
- tformat.format = RD::DATA_FORMAT_R16G16_UINT;
+ tformat.format = RD::DATA_FORMAT_R16G16_SINT;
tformat.width = rt->process_size.width;
tformat.height = rt->process_size.height;
tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -7208,7 +7299,7 @@ void RendererStorageRD::_render_target_allocate_sdf(RenderTarget *rt) {
rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
- tformat.format = RD::DATA_FORMAT_R16_UNORM;
+ tformat.format = RD::DATA_FORMAT_R16_SNORM;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());
@@ -7484,8 +7575,8 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
} else if (decal_owner.owns(p_base)) {
Decal *decal = decal_owner.getornull(p_base);
p_instance->update_dependency(&decal->dependency);
- } else if (gi_probe_owner.owns(p_base)) {
- GIProbe *gip = gi_probe_owner.getornull(p_base);
+ } else if (voxel_gi_owner.owns(p_base)) {
+ VoxelGI *gip = voxel_gi_owner.getornull(p_base);
p_instance->update_dependency(&gip->dependency);
} else if (lightmap_owner.owns(p_base)) {
Lightmap *lm = lightmap_owner.getornull(p_base);
@@ -7522,8 +7613,8 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
if (decal_owner.owns(p_rid)) {
return RS::INSTANCE_DECAL;
}
- if (gi_probe_owner.owns(p_rid)) {
- return RS::INSTANCE_GI_PROBE;
+ if (voxel_gi_owner.owns(p_rid)) {
+ return RS::INSTANCE_VOXEL_GI;
}
if (light_owner.owns(p_rid)) {
return RS::INSTANCE_LIGHT;
@@ -8047,7 +8138,7 @@ void RendererStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::Gl
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Transform v = p_value;
+ Transform3D v = p_value;
bv[0].x = v.basis.elements[0][0];
bv[0].y = v.basis.elements[1][0];
bv[0].z = v.basis.elements[2][0];
@@ -8470,6 +8561,7 @@ bool RendererStorageRD::free(RID p_rid) {
if (texture_owner.owns(p_rid)) {
Texture *t = texture_owner.getornull(p_rid);
+ ERR_FAIL_COND_V(!t, false);
ERR_FAIL_COND_V(t->is_render_target, false);
if (RD::get_singleton()->texture_is_valid(t->rd_texture_srgb)) {
@@ -8580,11 +8672,11 @@ bool RendererStorageRD::free(RID p_rid) {
}
decal->dependency.deleted_notify(p_rid);
decal_owner.free(p_rid);
- } else if (gi_probe_owner.owns(p_rid)) {
- gi_probe_allocate_data(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
- GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
- gi_probe->dependency.deleted_notify(p_rid);
- gi_probe_owner.free(p_rid);
+ } else if (voxel_gi_owner.owns(p_rid)) {
+ voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
+ VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_rid);
+ voxel_gi->dependency.deleted_notify(p_rid);
+ voxel_gi_owner.free(p_rid);
} else if (lightmap_owner.owns(p_rid)) {
lightmap_set_textures(p_rid, RID(), false);
Lightmap *lightmap = lightmap_owner.getornull(p_rid);
@@ -9099,10 +9191,10 @@ RendererStorageRD::RendererStorageRD() {
{
Vector<String> sdf_versions;
sdf_versions.push_back(""); //one only
- giprobe_sdf_shader.initialize(sdf_versions);
- giprobe_sdf_shader_version = giprobe_sdf_shader.version_create();
- giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0);
- giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader);
+ voxel_gi_sdf_shader.initialize(sdf_versions);
+ voxel_gi_sdf_shader_version = voxel_gi_sdf_shader.version_create();
+ voxel_gi_sdf_shader_version_shader = voxel_gi_sdf_shader.version_get_shader(voxel_gi_sdf_shader_version, 0);
+ voxel_gi_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(voxel_gi_sdf_shader_version_shader);
}
using_lightmap_array = true; // high end
@@ -9144,6 +9236,9 @@ RendererStorageRD::RendererStorageRD() {
actions.renames["CUSTOM"] = "PARTICLE.custom";
actions.renames["TRANSFORM"] = "PARTICLE.xform";
actions.renames["TIME"] = "FRAME.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
actions.renames["LIFETIME"] = "params.lifetime";
actions.renames["DELTA"] = "local_delta";
actions.renames["NUMBER"] = "particle_number";
@@ -9315,7 +9410,7 @@ RendererStorageRD::~RendererStorageRD() {
RD::get_singleton()->free(mesh_default_rd_buffers[i]);
}
- giprobe_sdf_shader.version_free(giprobe_sdf_shader_version);
+ voxel_gi_sdf_shader.version_free(voxel_gi_sdf_shader_version);
particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
rt_sdf.shader.version_free(rt_sdf.shader_version);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 49f7f3dba6..28a1044705 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -38,15 +38,15 @@
#include "servers/rendering/renderer_rd/effects_rd.h"
#include "servers/rendering/renderer_rd/shader_compiler_rd.h"
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
class RendererStorageRD : public RendererStorage {
public:
- static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) {
+ static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
p_array[0] = p_mtx.basis.elements[0][0];
p_array[1] = p_mtx.basis.elements[1][0];
p_array[2] = p_mtx.basis.elements[2][0];
@@ -95,7 +95,7 @@ public:
p_array[11] = 0;
}
- static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform &p_mtx, float *p_array) {
+ static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
p_array[0] = p_mtx.basis.elements[0][0];
p_array[1] = p_mtx.basis.elements[0][1];
p_array[2] = p_mtx.basis.elements[0][2];
@@ -638,7 +638,9 @@ private:
COLLISION_TYPE_SPHERE,
COLLISION_TYPE_BOX,
COLLISION_TYPE_SDF,
- COLLISION_TYPE_HEIGHT_FIELD
+ COLLISION_TYPE_HEIGHT_FIELD,
+ COLLISION_TYPE_2D_SDF,
+
};
struct Collider {
@@ -710,6 +712,13 @@ private:
bool restart_request = false;
AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
bool use_local_coords = true;
+ bool has_collision_cache = false;
+
+ bool has_sdf_collision = false;
+ Transform2D sdf_collision_transform;
+ Rect2 sdf_collision_to_screen;
+ RID sdf_collision_texture;
+
RID process_material;
uint32_t frame_counter = 0;
RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
@@ -717,7 +726,7 @@ private:
RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
Vector<RID> draw_passes;
- Vector<Transform> trail_bind_poses;
+ Vector<Transform3D> trail_bind_poses;
bool trail_bind_poses_dirty = false;
RID trail_bind_pose_buffer;
RID trail_bind_pose_uniform_set;
@@ -762,7 +771,7 @@ private:
bool force_sub_emit = false;
- Transform emission_transform;
+ Transform3D emission_transform;
Vector<uint8_t> emission_buffer_data;
@@ -820,6 +829,11 @@ private:
float align_up[3];
uint32_t align_mode;
+
+ uint32_t order_by_lifetime;
+ uint32_t lifetime_split;
+ uint32_t lifetime_reverse;
+ uint32_t pad;
};
enum {
@@ -843,6 +857,7 @@ private:
struct ParticlesShaderData : public ShaderData {
bool valid;
RID version;
+ bool uses_collision = false;
//PipelineCacheRD pipelines[SKY_VERSION_MAX];
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
@@ -926,7 +941,7 @@ private:
struct ParticlesCollisionInstance {
RID collision;
- Transform transform;
+ Transform3D transform;
bool active = false;
};
@@ -1030,9 +1045,9 @@ private:
mutable RID_Owner<Decal, true> decal_owner;
- /* GI PROBE */
+ /* VOXEL GI */
- struct GIProbe {
+ struct VoxelGI {
RID octree_buffer;
RID data_buffer;
RID sdf_texture;
@@ -1044,7 +1059,7 @@ private:
int cell_count = 0;
- Transform to_cell_xform;
+ Transform3D to_cell_xform;
AABB bounds;
Vector3i octree_size;
@@ -1066,12 +1081,12 @@ private:
Dependency dependency;
};
- GiprobeSdfShaderRD giprobe_sdf_shader;
- RID giprobe_sdf_shader_version;
- RID giprobe_sdf_shader_version_shader;
- RID giprobe_sdf_shader_pipeline;
+ VoxelGiSdfShaderRD voxel_gi_sdf_shader;
+ RID voxel_gi_sdf_shader_version;
+ RID voxel_gi_sdf_shader_version_shader;
+ RID voxel_gi_sdf_shader_pipeline;
- mutable RID_Owner<GIProbe, true> gi_probe_owner;
+ mutable RID_Owner<VoxelGI, true> voxel_gi_owner;
/* REFLECTION PROBE */
@@ -1110,6 +1125,7 @@ private:
struct RenderTarget {
Size2i size;
+ uint32_t view_count;
RID framebuffer;
RID color;
@@ -1120,6 +1136,8 @@ private:
bool flags[RENDER_TARGET_FLAG_MAX];
+ bool sdf_enabled = false;
+
RID backbuffer; //used for effects
RID backbuffer_fb;
RID backbuffer_mipmap0;
@@ -1644,14 +1662,14 @@ public:
int multimesh_get_instance_count(RID p_multimesh) const;
void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
+ void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform);
void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
RID multimesh_get_mesh(RID p_multimesh) const;
- Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
+ Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
@@ -1742,10 +1760,10 @@ public:
void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
- void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform);
+ void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform);
int skeleton_get_bone_count(RID p_skeleton) const;
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform);
- Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
+ void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform);
+ Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
@@ -2002,59 +2020,59 @@ public:
virtual AABB decal_get_aabb(RID p_decal) const;
- /* GI PROBE API */
+ /* VOXEL GI API */
- RID gi_probe_allocate();
- void gi_probe_initialize(RID p_gi_probe);
+ RID voxel_gi_allocate();
+ void voxel_gi_initialize(RID p_voxel_gi);
- void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
+ void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
- AABB gi_probe_get_bounds(RID p_gi_probe) const;
- Vector3i gi_probe_get_octree_size(RID p_gi_probe) const;
- Vector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const;
- Vector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const;
- Vector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const;
+ AABB voxel_gi_get_bounds(RID p_voxel_gi) const;
+ Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const;
+ Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const;
+ Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const;
+ Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const;
- Vector<int> gi_probe_get_level_counts(RID p_gi_probe) const;
- Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const;
+ Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const;
+ Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const;
- void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range);
- float gi_probe_get_dynamic_range(RID p_gi_probe) const;
+ void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range);
+ float voxel_gi_get_dynamic_range(RID p_voxel_gi) const;
- void gi_probe_set_propagation(RID p_gi_probe, float p_range);
- float gi_probe_get_propagation(RID p_gi_probe) const;
+ void voxel_gi_set_propagation(RID p_voxel_gi, float p_range);
+ float voxel_gi_get_propagation(RID p_voxel_gi) const;
- void gi_probe_set_energy(RID p_gi_probe, float p_energy);
- float gi_probe_get_energy(RID p_gi_probe) const;
+ void voxel_gi_set_energy(RID p_voxel_gi, float p_energy);
+ float voxel_gi_get_energy(RID p_voxel_gi) const;
- void gi_probe_set_ao(RID p_gi_probe, float p_ao);
- float gi_probe_get_ao(RID p_gi_probe) const;
+ void voxel_gi_set_ao(RID p_voxel_gi, float p_ao);
+ float voxel_gi_get_ao(RID p_voxel_gi) const;
- void gi_probe_set_ao_size(RID p_gi_probe, float p_strength);
- float gi_probe_get_ao_size(RID p_gi_probe) const;
+ void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength);
+ float voxel_gi_get_ao_size(RID p_voxel_gi) const;
- void gi_probe_set_bias(RID p_gi_probe, float p_bias);
- float gi_probe_get_bias(RID p_gi_probe) const;
+ void voxel_gi_set_bias(RID p_voxel_gi, float p_bias);
+ float voxel_gi_get_bias(RID p_voxel_gi) const;
- void gi_probe_set_normal_bias(RID p_gi_probe, float p_range);
- float gi_probe_get_normal_bias(RID p_gi_probe) const;
+ void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range);
+ float voxel_gi_get_normal_bias(RID p_voxel_gi) const;
- void gi_probe_set_interior(RID p_gi_probe, bool p_enable);
- bool gi_probe_is_interior(RID p_gi_probe) const;
+ void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable);
+ bool voxel_gi_is_interior(RID p_voxel_gi) const;
- void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable);
- bool gi_probe_is_using_two_bounces(RID p_gi_probe) const;
+ void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable);
+ bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const;
- void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength);
- float gi_probe_get_anisotropy_strength(RID p_gi_probe) const;
+ void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength);
+ float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const;
- uint32_t gi_probe_get_version(RID p_probe);
- uint32_t gi_probe_get_data_version(RID p_probe);
+ uint32_t voxel_gi_get_version(RID p_probe);
+ uint32_t voxel_gi_get_data_version(RID p_probe);
- RID gi_probe_get_octree_buffer(RID p_gi_probe) const;
- RID gi_probe_get_data_buffer(RID p_gi_probe) const;
+ RID voxel_gi_get_octree_buffer(RID p_voxel_gi) const;
+ RID voxel_gi_get_data_buffer(RID p_voxel_gi) const;
- RID gi_probe_get_sdf_texture(RID p_gi_probe);
+ RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
/* LIGHTMAP CAPTURE */
@@ -2130,10 +2148,10 @@ public:
void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align);
void particles_set_trails(RID p_particles, bool p_enable, float p_length);
- void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform> &p_bind_poses);
+ void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses);
void particles_restart(RID p_particles);
- void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
+ void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
void particles_set_subemitter(RID p_particles, RID p_subemitter_particles);
@@ -2146,7 +2164,7 @@ public:
AABB particles_get_current_aabb(RID p_particles);
AABB particles_get_aabb(RID p_particles) const;
- void particles_set_emission_transform(RID p_particles, const Transform &p_transform);
+ void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform);
bool particles_get_emitting(RID p_particles);
int particles_get_draw_passes(RID p_particles) const;
@@ -2175,6 +2193,13 @@ public:
return particles->amount * r_trail_divisor;
}
+ _FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
+ Particles *particles = particles_owner.getornull(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->has_collision_cache;
+ }
+
_FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND_V(!particles, false);
@@ -2206,6 +2231,7 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance);
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance);
+ virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture);
/* PARTICLES COLLISION */
@@ -2229,7 +2255,7 @@ public:
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision);
- virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform);
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
/* GLOBAL VARIABLES API */
@@ -2257,7 +2283,7 @@ public:
RID render_target_create();
void render_target_set_position(RID p_render_target, int p_x, int p_y);
- void render_target_set_size(RID p_render_target, int p_width, int p_height);
+ void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count);
RID render_target_get_texture(RID p_render_target);
void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
@@ -2280,6 +2306,8 @@ public:
RID render_target_get_sdf_framebuffer(RID p_render_target);
void render_target_sdf_process(RID p_render_target);
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const;
+ void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled);
+ bool render_target_is_sdf_enabled(RID p_render_target) const;
Size2 render_target_get_size(RID p_render_target);
RID render_target_get_rd_framebuffer(RID p_render_target);
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index 24ac85bb35..b347197289 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -369,17 +369,24 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
ERR_FAIL_COND(fidx == -1);
+ Vector<StringName> uses_functions;
+
for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) {
- if (added.has(E->get())) {
+ uses_functions.push_back(E->get());
+ }
+ uses_functions.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
+
+ for (int k = 0; k < uses_functions.size(); k++) {
+ if (added.has(uses_functions[k])) {
continue; //was added already
}
- _dump_function_deps(p_node, E->get(), p_func_code, r_to_add, added);
+ _dump_function_deps(p_node, uses_functions[k], p_func_code, r_to_add, added);
SL::FunctionNode *fnode = nullptr;
for (int i = 0; i < p_node->functions.size(); i++) {
- if (p_node->functions[i].name == E->get()) {
+ if (p_node->functions[i].name == uses_functions[k]) {
fnode = p_node->functions[i].function;
break;
}
@@ -391,10 +398,21 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
String header;
if (fnode->return_type == SL::TYPE_STRUCT) {
- header = _mkid(fnode->return_struct_name) + " " + _mkid(fnode->name) + "(";
+ header = _mkid(fnode->return_struct_name);
} else {
- header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
+ header = _typestr(fnode->return_type);
}
+
+ if (fnode->return_array_size > 0) {
+ header += "[";
+ header += itos(fnode->return_array_size);
+ header += "]";
+ }
+
+ header += " ";
+ header += _mkid(fnode->name);
+ header += "(";
+
for (int i = 0; i < fnode->arguments.size(); i++) {
if (i > 0) {
header += ", ";
@@ -407,13 +425,18 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
} else {
header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
}
+ if (fnode->arguments[i].array_size > 0) {
+ header += "[";
+ header += itos(fnode->arguments[i].array_size);
+ header += "]";
+ }
}
header += ")\n";
r_to_add += header;
- r_to_add += p_func_code[E->get()];
+ r_to_add += p_func_code[uses_functions[k]];
- added.insert(E->get());
+ added.insert(uses_functions[k]);
}
}
@@ -565,63 +588,74 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
uniform_defines.resize(max_uniforms);
bool uses_uniforms = false;
+ Vector<StringName> uniform_names;
+
for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) {
+ uniform_names.push_back(E->key());
+ }
+
+ uniform_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
+
+ for (int k = 0; k < uniform_names.size(); k++) {
+ StringName uniform_name = uniform_names[k];
+ const SL::ShaderNode::Uniform &uniform = pnode->uniforms[uniform_name];
+
String ucode;
- if (E->get().scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ if (uniform.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
//insert, but don't generate any code.
- p_actions.uniforms->insert(E->key(), E->get());
+ p_actions.uniforms->insert(uniform_name, uniform);
continue; //instances are indexed directly, dont need index uniforms
}
- if (SL::is_sampler_type(E->get().type)) {
- ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + E->get().texture_order) + ") uniform ";
+ if (SL::is_sampler_type(uniform.type)) {
+ ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_order) + ") uniform ";
}
- bool is_buffer_global = !SL::is_sampler_type(E->get().type) && E->get().scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
+ bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
if (is_buffer_global) {
//this is an integer to index the global table
ucode += _typestr(ShaderLanguage::TYPE_UINT);
} else {
- ucode += _prestr(E->get().precision);
- ucode += _typestr(E->get().type);
+ ucode += _prestr(uniform.precision);
+ ucode += _typestr(uniform.type);
}
- ucode += " " + _mkid(E->key());
+ ucode += " " + _mkid(uniform_name);
ucode += ";\n";
- if (SL::is_sampler_type(E->get().type)) {
+ if (SL::is_sampler_type(uniform.type)) {
for (int j = 0; j < STAGE_MAX; j++) {
r_gen_code.stage_globals[j] += ucode;
}
GeneratedCode::Texture texture;
- texture.name = E->key();
- texture.hint = E->get().hint;
- texture.type = E->get().type;
- texture.filter = E->get().filter;
- texture.repeat = E->get().repeat;
- texture.global = E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
+ texture.name = uniform_name;
+ texture.hint = uniform.hint;
+ texture.type = uniform.type;
+ texture.filter = uniform.filter;
+ texture.repeat = uniform.repeat;
+ texture.global = uniform.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
if (texture.global) {
r_gen_code.uses_global_textures = true;
}
- r_gen_code.texture_uniforms.write[E->get().texture_order] = texture;
+ r_gen_code.texture_uniforms.write[uniform.texture_order] = texture;
} else {
if (!uses_uniforms) {
uses_uniforms = true;
}
- uniform_defines.write[E->get().order] = ucode;
+ uniform_defines.write[uniform.order] = ucode;
if (is_buffer_global) {
//globals are indices into the global table
- uniform_sizes.write[E->get().order] = _get_datatype_size(ShaderLanguage::TYPE_UINT);
- uniform_alignments.write[E->get().order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
+ uniform_sizes.write[uniform.order] = _get_datatype_size(ShaderLanguage::TYPE_UINT);
+ uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
} else {
- uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type);
- uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type);
+ uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type);
+ uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
}
}
- p_actions.uniforms->insert(E->key(), E->get());
+ p_actions.uniforms->insert(uniform_name, uniform);
}
for (int i = 0; i < max_uniforms; i++) {
@@ -688,21 +722,32 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
List<Pair<StringName, SL::ShaderNode::Varying>> var_frag_to_light;
+ Vector<StringName> varying_names;
+
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) {
- if (E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT || E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
- var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(E->key(), E->get()));
- fragment_varyings.insert(E->key());
+ varying_names.push_back(E->key());
+ }
+
+ varying_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
+
+ for (int k = 0; k < varying_names.size(); k++) {
+ StringName varying_name = varying_names[k];
+ const SL::ShaderNode::Varying &varying = pnode->varyings[varying_name];
+
+ if (varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT || varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
+ var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(varying_name, varying));
+ fragment_varyings.insert(varying_name);
continue;
}
String vcode;
- String interp_mode = _interpstr(E->get().interpolation);
- vcode += _prestr(E->get().precision);
- vcode += _typestr(E->get().type);
- vcode += " " + _mkid(E->key());
- if (E->get().array_size > 0) {
+ String interp_mode = _interpstr(varying.interpolation);
+ vcode += _prestr(varying.precision);
+ vcode += _typestr(varying.type);
+ vcode += " " + _mkid(varying_name);
+ if (varying.array_size > 0) {
vcode += "[";
- vcode += itos(E->get().array_size);
+ vcode += itos(varying.array_size);
vcode += "]";
}
vcode += ";\n";
@@ -959,25 +1004,30 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
declaration += itos(adnode->declarations[i].size);
}
declaration += "]";
- int sz = adnode->declarations[i].initializer.size();
- if (sz > 0) {
+ if (adnode->declarations[i].single_expression) {
declaration += "=";
- if (adnode->datatype == SL::TYPE_STRUCT) {
- declaration += _mkid(adnode->struct_name);
- } else {
- declaration += _typestr(adnode->datatype);
- }
- declaration += "[";
- declaration += itos(sz);
- declaration += "]";
- declaration += "(";
- for (int j = 0; j < sz; j++) {
- declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (j != sz - 1) {
- declaration += ", ";
+ declaration += _dump_node_code(adnode->declarations[i].initializer[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ } else {
+ int sz = adnode->declarations[i].initializer.size();
+ if (sz > 0) {
+ declaration += "=";
+ if (adnode->datatype == SL::TYPE_STRUCT) {
+ declaration += _mkid(adnode->struct_name);
+ } else {
+ declaration += _typestr(adnode->datatype);
}
+ declaration += "[";
+ declaration += itos(sz);
+ declaration += "]";
+ declaration += "(";
+ for (int j = 0; j < sz; j++) {
+ declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ if (j != sz - 1) {
+ declaration += ", ";
+ }
+ }
+ declaration += ")";
}
- declaration += ")";
}
}
@@ -988,7 +1038,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
bool use_fragment_varying = false;
if (!(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
- if (anode->assign_expression != nullptr) {
+ if (anode->assign_expression != nullptr && shader->varyings.has(anode->name)) {
use_fragment_varying = true;
} else {
if (p_assigning) {
@@ -1280,6 +1330,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
} else if (mnode->assign_expression != nullptr) {
code += "=";
code += _dump_node_code(mnode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
+ } else if (mnode->call_expression != nullptr) {
+ code += ".";
+ code += _dump_node_code(mnode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
}
} break;
}
@@ -1451,7 +1504,6 @@ ShaderCompilerRD::ShaderCompilerRD() {
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
}
- actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index f7242a2b17..27305cc938 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -30,8 +30,12 @@
#include "shader_rd.h"
+#include "core/io/compression.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "renderer_compositor_rd.h"
#include "servers/rendering/rendering_device.h"
+#include "thirdparty/misc/smolv.h"
void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) {
Vector<String> lines = String(p_code).split("\n");
@@ -97,6 +101,7 @@ void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) {
void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name) {
name = p_name;
+
if (p_compute_code) {
_add_stage(p_compute_code, STAGE_TYPE_COMPUTE);
is_compute = true;
@@ -109,6 +114,18 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
_add_stage(p_fragment_code, STAGE_TYPE_FRAGMENT);
}
}
+
+ StringBuilder tohash;
+ tohash.append("[VersionKey]");
+ tohash.append(RenderingDevice::get_singleton()->shader_get_cache_key());
+ tohash.append("[Vertex]");
+ tohash.append(p_vertex_code ? p_vertex_code : "");
+ tohash.append("[Fragment]");
+ tohash.append(p_fragment_code ? p_fragment_code : "");
+ tohash.append("[Compute]");
+ tohash.append(p_compute_code ? p_compute_code : "");
+
+ base_sha256 = tohash.as_string().sha256_text();
}
RID ShaderRD::version_create() {
@@ -131,6 +148,9 @@ void ShaderRD::_clear_version(Version *p_version) {
}
memdelete_arr(p_version->variants);
+ if (p_version->variant_stages) {
+ memdelete_arr(p_version->variant_stages);
+ }
p_version->variants = nullptr;
}
}
@@ -183,7 +203,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
return; //variant is disabled, return
}
- Vector<RD::ShaderStageData> stages;
+ Vector<RD::ShaderStageData> &stages = p_version->variant_stages[p_variant];
String error;
String current_source;
@@ -313,6 +333,197 @@ RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_versio
return source_code;
}
+String ShaderRD::_version_get_sha1(Version *p_version) const {
+ StringBuilder hash_build;
+
+ hash_build.append("[uniforms]");
+ hash_build.append(p_version->uniforms.get_data());
+ hash_build.append("[vertex_globals]");
+ hash_build.append(p_version->vertex_globals.get_data());
+ hash_build.append("[fragment_globals]");
+ hash_build.append(p_version->fragment_globals.get_data());
+ hash_build.append("[compute_globals]");
+ hash_build.append(p_version->compute_globals.get_data());
+
+ Vector<StringName> code_sections;
+ for (Map<StringName, CharString>::Element *E = p_version->code_sections.front(); E; E = E->next()) {
+ code_sections.push_back(E->key());
+ }
+ code_sections.sort_custom<StringName::AlphCompare>();
+
+ for (int i = 0; i < code_sections.size(); i++) {
+ hash_build.append(String("[code:") + String(code_sections[i]) + "]");
+ hash_build.append(p_version->code_sections[code_sections[i]].get_data());
+ }
+ for (int i = 0; i < p_version->custom_defines.size(); i++) {
+ hash_build.append("[custom_defines:" + itos(i) + "]");
+ hash_build.append(p_version->custom_defines[i].get_data());
+ }
+
+ return hash_build.as_string().sha1_text();
+}
+
+static const char *shader_file_header = "GDSC";
+static const uint32_t cache_file_version = 1;
+
+bool ShaderRD::_load_from_cache(Version *p_version) {
+ String sha1 = _version_get_sha1(p_version);
+ String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
+
+ uint64_t time_from = OS::get_singleton()->get_ticks_usec();
+
+ FileAccessRef f = FileAccess::open(path, FileAccess::READ);
+ if (!f) {
+ return false;
+ }
+
+ char header[5] = { 0, 0, 0, 0, 0 };
+ f->get_buffer((uint8_t *)header, 4);
+ ERR_FAIL_COND_V(header != String(shader_file_header), false);
+
+ uint32_t file_version = f->get_32();
+ if (file_version != cache_file_version) {
+ return false; // wrong version
+ }
+
+ uint32_t variant_count = f->get_32();
+
+ ERR_FAIL_COND_V(variant_count != (uint32_t)variant_defines.size(), false); //should not happen but check
+
+ bool success = true;
+ for (uint32_t i = 0; i < variant_count; i++) {
+ uint32_t stage_count = f->get_32();
+ p_version->variant_stages[i].resize(stage_count);
+ for (uint32_t j = 0; j < stage_count; j++) {
+ p_version->variant_stages[i].write[j].shader_stage = RD::ShaderStage(f->get_32());
+
+ int compression = f->get_32();
+ uint32_t length = f->get_32();
+
+ if (compression == 0) {
+ Vector<uint8_t> data;
+ data.resize(length);
+
+ f->get_buffer(data.ptrw(), length);
+
+ p_version->variant_stages[i].write[j].spir_v = data;
+ } else {
+ Vector<uint8_t> data;
+
+ if (compression == 2) {
+ //zstd
+ int smol_length = f->get_32();
+ Vector<uint8_t> zstd_data;
+
+ zstd_data.resize(smol_length);
+ f->get_buffer(zstd_data.ptrw(), smol_length);
+
+ data.resize(length);
+ Compression::decompress(data.ptrw(), data.size(), zstd_data.ptr(), zstd_data.size(), Compression::MODE_ZSTD);
+
+ } else {
+ data.resize(length);
+ f->get_buffer(data.ptrw(), length);
+ }
+
+ Vector<uint8_t> spirv;
+ uint32_t spirv_size = smolv::GetDecodedBufferSize(data.ptr(), data.size());
+ spirv.resize(spirv_size);
+ if (!smolv::Decode(data.ptr(), data.size(), spirv.ptrw(), spirv_size)) {
+ ERR_PRINT("Malformed smolv input uncompressing shader " + name + ", variant #" + itos(i) + " stage :" + itos(j));
+ success = false;
+ break;
+ }
+ p_version->variant_stages[i].write[j].spir_v = spirv;
+ }
+ }
+ }
+
+ if (!success) {
+ for (uint32_t i = 0; i < variant_count; i++) {
+ p_version->variant_stages[i].resize(0);
+ }
+ return false;
+ }
+
+ float time_ms = double(OS::get_singleton()->get_ticks_usec() - time_from) / 1000.0;
+
+ print_verbose("Shader cache load success '" + path + "' " + rtos(time_ms) + "ms.");
+
+ for (uint32_t i = 0; i < variant_count; i++) {
+ RID shader = RD::get_singleton()->shader_create(p_version->variant_stages[i]);
+ {
+ MutexLock lock(variant_set_mutex);
+ p_version->variants[i] = shader;
+ }
+ }
+
+ memdelete_arr(p_version->variant_stages); //clear stages
+ p_version->variant_stages = nullptr;
+ p_version->valid = true;
+ return true;
+}
+
+void ShaderRD::_save_to_cache(Version *p_version) {
+ String sha1 = _version_get_sha1(p_version);
+ String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
+
+ FileAccessRef f = FileAccess::open(path, FileAccess::WRITE);
+ ERR_FAIL_COND(!f);
+ f->store_buffer((const uint8_t *)shader_file_header, 4);
+ f->store_32(cache_file_version); //file version
+ uint32_t variant_count = variant_defines.size();
+ f->store_32(variant_count); //variant count
+
+ for (uint32_t i = 0; i < variant_count; i++) {
+ f->store_32(p_version->variant_stages[i].size()); //stage count
+ for (int j = 0; j < p_version->variant_stages[i].size(); j++) {
+ f->store_32(p_version->variant_stages[i][j].shader_stage); //stage count
+ Vector<uint8_t> spirv = p_version->variant_stages[i][j].spir_v;
+
+ bool save_uncompressed = true;
+ if (shader_cache_save_compressed) {
+ smolv::ByteArray smolv;
+ bool strip_debug = !shader_cache_save_debug;
+ if (!smolv::Encode(spirv.ptr(), spirv.size(), smolv, strip_debug ? smolv::kEncodeFlagStripDebugInfo : 0)) {
+ ERR_PRINT("Error compressing shader " + name + ", variant #" + itos(i) + " stage :" + itos(i));
+ } else {
+ bool compress_zstd = shader_cache_save_compressed_zstd;
+
+ if (compress_zstd) {
+ Vector<uint8_t> zstd;
+ zstd.resize(Compression::get_max_compressed_buffer_size(smolv.size(), Compression::MODE_ZSTD));
+ int dst_size = Compression::compress(zstd.ptrw(), &smolv[0], smolv.size(), Compression::MODE_ZSTD);
+ if (dst_size >= 0 && (uint32_t)dst_size < smolv.size()) {
+ f->store_32(2); //compressed zstd
+ f->store_32(smolv.size()); //size of smolv buffer
+ f->store_32(dst_size); //size of smolv buffer
+ f->store_buffer(zstd.ptr(), dst_size); //smolv buffer
+ } else {
+ compress_zstd = false;
+ }
+ }
+
+ if (!compress_zstd) {
+ f->store_32(1); //compressed
+ f->store_32(smolv.size()); //size of smolv buffer
+ f->store_buffer(&smolv[0], smolv.size()); //smolv buffer
+ }
+ save_uncompressed = false;
+ }
+ }
+
+ if (save_uncompressed) {
+ f->store_32(0); //uncompressed
+ f->store_32(spirv.size()); //stage count
+ f->store_buffer(spirv.ptr(), spirv.size()); //stage count
+ }
+ }
+ }
+
+ f->close();
+}
+
void ShaderRD::_compile_version(Version *p_version) {
_clear_version(p_version);
@@ -320,6 +531,15 @@ void ShaderRD::_compile_version(Version *p_version) {
p_version->dirty = false;
p_version->variants = memnew_arr(RID, variant_defines.size());
+ typedef Vector<RD::ShaderStageData> ShaderStageArray;
+ p_version->variant_stages = memnew_arr(ShaderStageArray, variant_defines.size());
+
+ if (shader_cache_dir_valid) {
+ if (_load_from_cache(p_version)) {
+ return;
+ }
+ }
+
#if 1
RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
@@ -351,10 +571,20 @@ void ShaderRD::_compile_version(Version *p_version) {
}
}
memdelete_arr(p_version->variants);
+ if (p_version->variant_stages) {
+ memdelete_arr(p_version->variant_stages);
+ }
p_version->variants = nullptr;
+ p_version->variant_stages = nullptr;
return;
+ } else if (shader_cache_dir_valid) {
+ //save shader cache
+ _save_to_cache(p_version);
}
+ memdelete_arr(p_version->variant_stages); //clear stages
+ p_version->variant_stages = nullptr;
+
p_version->valid = true;
}
@@ -443,6 +673,8 @@ bool ShaderRD::is_variant_enabled(int p_variant) const {
return variants_enabled[p_variant];
}
+bool ShaderRD::shader_cache_cleanup_on_start = false;
+
ShaderRD::ShaderRD() {
// Do not feel forced to use this, in most cases it makes little to no difference.
bool use_32_threads = false;
@@ -469,8 +701,64 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
variant_defines.push_back(p_variant_defines[i].utf8());
variants_enabled.push_back(true);
}
+
+ if (shader_cache_dir != String()) {
+ StringBuilder hash_build;
+
+ hash_build.append("[base_hash]");
+ hash_build.append(base_sha256);
+ hash_build.append("[general_defines]");
+ hash_build.append(general_defines.get_data());
+ for (int i = 0; i < variant_defines.size(); i++) {
+ hash_build.append("[variant_defines:" + itos(i) + "]");
+ hash_build.append(variant_defines[i].get_data());
+ }
+
+ base_sha256 = hash_build.as_string().sha256_text();
+
+ DirAccessRef d = DirAccess::open(shader_cache_dir);
+ ERR_FAIL_COND(!d);
+ if (d->change_dir(name) != OK) {
+ Error err = d->make_dir(name);
+ ERR_FAIL_COND(err != OK);
+ d->change_dir(name);
+ }
+
+ //erase other versions?
+ if (shader_cache_cleanup_on_start) {
+ }
+ //
+ if (d->change_dir(base_sha256) != OK) {
+ Error err = d->make_dir(base_sha256);
+ ERR_FAIL_COND(err != OK);
+ }
+ shader_cache_dir_valid = true;
+
+ print_verbose("Shader '" + name + "' SHA256: " + base_sha256);
+ }
+}
+
+void ShaderRD::set_shader_cache_dir(const String &p_dir) {
+ shader_cache_dir = p_dir;
+}
+
+void ShaderRD::set_shader_cache_save_compressed(bool p_enable) {
+ shader_cache_save_compressed = p_enable;
}
+void ShaderRD::set_shader_cache_save_compressed_zstd(bool p_enable) {
+ shader_cache_save_compressed_zstd = p_enable;
+}
+
+void ShaderRD::set_shader_cache_save_debug(bool p_enable) {
+ shader_cache_save_debug = p_enable;
+}
+
+String ShaderRD::shader_cache_dir;
+bool ShaderRD::shader_cache_save_compressed = true;
+bool ShaderRD::shader_cache_save_compressed_zstd = true;
+bool ShaderRD::shader_cache_save_debug = true;
+
ShaderRD::~ShaderRD() {
List<RID> remaining;
version_owner.get_owned_list(&remaining);
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index f20d539621..9a68e02007 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -59,7 +59,8 @@ class ShaderRD {
Map<StringName, CharString> code_sections;
Vector<CharString> custom_defines;
- RID *variants; //same size as version defines
+ Vector<RD::ShaderStageData> *variant_stages = nullptr;
+ RID *variants = nullptr; //same size as version defines
bool valid;
bool dirty;
@@ -96,10 +97,19 @@ class ShaderRD {
bool is_compute = false;
- const char *name;
+ String name;
CharString base_compute_defines;
+ String base_sha256;
+
+ static String shader_cache_dir;
+ static bool shader_cache_cleanup_on_start;
+ static bool shader_cache_save_compressed;
+ static bool shader_cache_save_compressed_zstd;
+ static bool shader_cache_save_debug;
+ bool shader_cache_dir_valid = false;
+
enum StageType {
STAGE_TYPE_VERTEX,
STAGE_TYPE_FRAGMENT,
@@ -113,6 +123,10 @@ class ShaderRD {
void _add_stage(const char *p_code, StageType p_stage_type);
+ String _version_get_sha1(Version *p_version) const;
+ bool _load_from_cache(Version *p_version);
+ void _save_to_cache(Version *p_version);
+
protected:
ShaderRD();
void setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name);
@@ -148,6 +162,11 @@ public:
void set_variant_enabled(int p_variant, bool p_enabled);
bool is_variant_enabled(int p_variant) const;
+ static void set_shader_cache_dir(const String &p_dir);
+ static void set_shader_cache_save_compressed(bool p_enable);
+ static void set_shader_cache_save_compressed_zstd(bool p_enable);
+ static void set_shader_cache_save_debug(bool p_enable);
+
RS::ShaderNativeSourceCode version_get_native_source_code(RID p_version);
void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index cf4c77db0d..2186bd174b 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -101,36 +101,34 @@ void main() {
uint offset = trail_size * stride * gl_InstanceIndex;
- mat4 matrix;
vec4 pcolor;
+ vec2 new_vertex;
{
uint boffset = offset + bone_attrib.x * stride;
- matrix = mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.x;
- pcolor = transforms.data[boffset + 3] * weight_attrib.x;
+ new_vertex = (vec4(vertex, 0.0, 1.0) * mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy * weight_attrib.x;
+ pcolor = transforms.data[boffset + 2] * weight_attrib.x;
}
if (weight_attrib.y > 0.001) {
uint boffset = offset + bone_attrib.y * stride;
- matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.y;
- pcolor += transforms.data[boffset + 3] * weight_attrib.y;
+ new_vertex += (vec4(vertex, 0.0, 1.0) * mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy * weight_attrib.y;
+ pcolor += transforms.data[boffset + 2] * weight_attrib.y;
}
if (weight_attrib.z > 0.001) {
uint boffset = offset + bone_attrib.z * stride;
- matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.z;
- pcolor += transforms.data[boffset + 3] * weight_attrib.z;
+ new_vertex += (vec4(vertex, 0.0, 1.0) * mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy * weight_attrib.z;
+ pcolor += transforms.data[boffset + 2] * weight_attrib.z;
}
if (weight_attrib.w > 0.001) {
uint boffset = offset + bone_attrib.w * stride;
- matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.w;
- pcolor += transforms.data[boffset + 3] * weight_attrib.w;
+ new_vertex += (vec4(vertex, 0.0, 1.0) * mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy * weight_attrib.w;
+ pcolor += transforms.data[boffset + 2] * weight_attrib.w;
}
- instance_custom = transforms.data[offset + 4];
+ instance_custom = transforms.data[offset + 3];
+ vertex = new_vertex;
color *= pcolor;
- matrix = transpose(matrix);
- world_matrix = world_matrix * matrix;
-
} else
#endif // USE_ATTRIBUTES
@@ -283,7 +281,7 @@ vec2 screen_uv_to_sdf(vec2 p_uv) {
float texture_sdf(vec2 p_sdf) {
vec2 uv = p_sdf * canvas_data.sdf_to_tex.xy + canvas_data.sdf_to_tex.zw;
float d = texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv).r;
- d = d * SDF_MAX_LENGTH - 1.0;
+ d *= SDF_MAX_LENGTH;
return d * canvas_data.tex_to_sdf;
}
diff --git a/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl b/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl
index 65a554e839..2bdfbabfcf 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl
@@ -7,7 +7,7 @@
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout(r8, set = 0, binding = 1) uniform restrict readonly image2D src_pixels;
-layout(r16, set = 0, binding = 2) uniform restrict writeonly image2D dst_sdf;
+layout(r16_snorm, set = 0, binding = 2) uniform restrict writeonly image2D dst_sdf;
layout(rg16i, set = 0, binding = 3) uniform restrict readonly iimage2D src_process;
layout(rg16i, set = 0, binding = 4) uniform restrict writeonly iimage2D dst_process;
@@ -32,7 +32,7 @@ void main() {
#ifdef MODE_LOAD
bool solid = imageLoad(src_pixels, pos).r > 0.5;
- imageStore(dst_process, pos, solid ? ivec4(pos, 0, 0) : ivec4(ivec2(32767), 0, 0));
+ imageStore(dst_process, pos, solid ? ivec4(ivec2(-32767), 0, 0) : ivec4(ivec2(32767), 0, 0));
#endif
#ifdef MODE_LOAD_SHRINK
@@ -43,6 +43,8 @@ void main() {
ivec2 rel = ivec2(32767);
float d = 1e20;
+ int found = 0;
+ int solid_found = 0;
for (int i = 0; i < s; i++) {
for (int j = 0; j < s; j++) {
ivec2 src_pos = base + ivec2(i, j);
@@ -56,10 +58,17 @@ void main() {
d = dist;
rel = src_pos;
}
+ solid_found++;
}
+ found++;
}
}
+ if (solid_found == found) {
+ //mark solid only if all are solid
+ rel = ivec2(-32767);
+ }
+
imageStore(dst_process, pos, ivec4(rel, 0, 0));
#endif
@@ -70,6 +79,12 @@ void main() {
ivec2 rel = imageLoad(src_process, pos).xy;
+ bool solid = rel.x < 0;
+
+ if (solid) {
+ rel = -rel - ivec2(1);
+ }
+
if (center != rel) {
//only process if it does not point to itself
const int ofs_table_size = 8;
@@ -92,6 +107,15 @@ void main() {
continue;
}
ivec2 src_rel = imageLoad(src_process, src_pos).xy;
+ bool src_solid = src_rel.x < 0;
+ if (src_solid) {
+ src_rel = -src_rel - ivec2(1);
+ }
+
+ if (src_solid != solid) {
+ src_rel = ivec2(src_pos << params.shift); //point to itself if of different type
+ }
+
float src_dist = length(vec2(src_rel - center));
if (src_dist < dist) {
dist = src_dist;
@@ -100,18 +124,31 @@ void main() {
}
}
+ if (solid) {
+ rel = -rel - ivec2(1);
+ }
+
imageStore(dst_process, pos, ivec4(rel, 0, 0));
#endif
#ifdef MODE_STORE
ivec2 rel = imageLoad(src_process, pos).xy;
+
+ bool solid = rel.x < 0;
+
+ if (solid) {
+ rel = -rel - ivec2(1);
+ }
+
float d = length(vec2(rel - pos));
- if (d > 0.01) {
- d += 1.0; //make it signed
+
+ if (solid) {
+ d = -d;
}
+
d /= SDF_MAX_LENGTH;
- d = clamp(d, 0.0, 1.0);
+ d = clamp(d, -1.0, 1.0);
imageStore(dst_sdf, pos, vec4(d));
#endif
@@ -122,13 +159,20 @@ void main() {
ivec2 center = base + ivec2(params.shift);
ivec2 rel = imageLoad(src_process, pos).xy;
+
+ bool solid = rel.x < 0;
+
+ if (solid) {
+ rel = -rel - ivec2(1);
+ }
+
float d = length(vec2(rel - center));
- if (d > 0.01) {
- d += 1.0; //make it signed
+ if (solid) {
+ d = -d;
}
d /= SDF_MAX_LENGTH;
- d = clamp(d, 0.0, 1.0);
+ d = clamp(d, -1.0, 1.0);
imageStore(dst_sdf, pos, vec4(d));
#endif
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl
index bfd5c4c88d..3977f4efa0 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/gi.glsl
@@ -35,7 +35,7 @@ layout(set = 0, binding = 11) uniform texture2DArray lightprobe_texture;
layout(set = 0, binding = 12) uniform texture2D depth_buffer;
layout(set = 0, binding = 13) uniform texture2D normal_roughness_buffer;
-layout(set = 0, binding = 14) uniform utexture2D giprobe_buffer;
+layout(set = 0, binding = 14) uniform utexture2D voxel_gi_buffer;
layout(set = 0, binding = 15, std140) uniform SDFGI {
vec3 grid_size;
@@ -65,9 +65,9 @@ layout(set = 0, binding = 15, std140) uniform SDFGI {
}
sdfgi;
-#define MAX_GI_PROBES 8
+#define MAX_VOXEL_GI_INSTANCES 8
-struct GIProbeData {
+struct VoxelGIData {
mat4 xform;
vec3 bounds;
float dynamic_range;
@@ -83,12 +83,12 @@ struct GIProbeData {
uint mipmaps;
};
-layout(set = 0, binding = 16, std140) uniform GIProbes {
- GIProbeData data[MAX_GI_PROBES];
+layout(set = 0, binding = 16, std140) uniform VoxelGIs {
+ VoxelGIData data[MAX_VOXEL_GI_INSTANCES];
}
-gi_probes;
+voxel_gi_instances;
-layout(set = 0, binding = 17) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
+layout(set = 0, binding = 17) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
layout(push_constant, binding = 0, std430) uniform Params {
ivec2 screen_size;
@@ -98,7 +98,7 @@ layout(push_constant, binding = 0, std430) uniform Params {
vec4 proj_info;
vec3 ao_color;
- uint max_giprobes;
+ uint max_voxel_gi_instances;
bool high_quality_vct;
bool orthogonal;
@@ -155,7 +155,7 @@ vec3 reconstruct_position(ivec2 screen_pos) {
return pos;
}
-void sdfgi_probe_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) {
+void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) {
cascade_pos += cam_normal * sdfgi.normal_bias;
vec3 base_pos = floor(cascade_pos);
@@ -293,7 +293,7 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o
float blend;
vec3 diffuse, specular;
- sdfgi_probe_process(cascade, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse, specular);
+ sdfvoxel_gi_process(cascade, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse, specular);
{
//process blend
@@ -323,7 +323,7 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o
} else {
vec3 diffuse2, specular2;
cascade_pos = (cam_pos - sdfgi.cascades[cascade + 1].position) * sdfgi.cascades[cascade + 1].to_probe;
- sdfgi_probe_process(cascade + 1, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse2, specular2);
+ sdfvoxel_gi_process(cascade + 1, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse2, specular2);
diffuse = mix(diffuse, diffuse2, blend);
specular = mix(specular, specular2, blend);
}
@@ -494,26 +494,26 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3
return color;
}
-void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, inout vec4 out_spec, inout vec4 out_diff, inout float out_blend) {
- position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
- ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
- normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz);
+void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, inout vec4 out_spec, inout vec4 out_diff, inout float out_blend) {
+ position = (voxel_gi_instances.data[index].xform * vec4(position, 1.0)).xyz;
+ ref_vec = normalize((voxel_gi_instances.data[index].xform * vec4(ref_vec, 0.0)).xyz);
+ normal = normalize((voxel_gi_instances.data[index].xform * vec4(normal, 0.0)).xyz);
- position += normal * gi_probes.data[index].normal_bias;
+ position += normal * voxel_gi_instances.data[index].normal_bias;
//this causes corrupted pixels, i have no idea why..
- if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) {
+ if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, voxel_gi_instances.data[index].bounds))))) {
return;
}
- mat3 dir_xform = mat3(gi_probes.data[index].xform) * normal_xform;
+ mat3 dir_xform = mat3(voxel_gi_instances.data[index].xform) * normal_xform;
- vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0);
+ vec3 blendv = abs(position / voxel_gi_instances.data[index].bounds * 2.0 - 1.0);
float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0);
//float blend=1.0;
- float max_distance = length(gi_probes.data[index].bounds);
- vec3 cell_size = 1.0 / gi_probes.data[index].bounds;
+ float max_distance = length(voxel_gi_instances.data[index].bounds);
+ vec3 cell_size = 1.0 / voxel_gi_instances.data[index].bounds;
//irradiance
@@ -534,7 +534,7 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
for (uint i = 0; i < cone_dir_count; i++) {
vec3 dir = normalize(dir_xform * cone_dirs[i]);
- light += cone_weights[i] * voxel_cone_trace(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
+ light += cone_weights[i] * voxel_cone_trace(voxel_gi_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, voxel_gi_instances.data[index].bias);
}
} else {
const uint cone_dir_count = 4;
@@ -547,42 +547,42 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
float cone_weights[cone_dir_count] = float[](0.25, 0.25, 0.25, 0.25);
for (int i = 0; i < cone_dir_count; i++) {
vec3 dir = normalize(dir_xform * cone_dirs[i]);
- light += cone_weights[i] * voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, max_distance, gi_probes.data[index].bias);
+ light += cone_weights[i] * voxel_cone_trace_45_degrees(voxel_gi_textures[index], cell_size, position, dir, max_distance, voxel_gi_instances.data[index].bias);
}
}
- if (gi_probes.data[index].ambient_occlusion > 0.001) {
- float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0;
+ if (voxel_gi_instances.data[index].ambient_occlusion > 0.001) {
+ float size = 1.0 + voxel_gi_instances.data[index].ambient_occlusion_size * 7.0;
float taps, blend;
blend = modf(size, taps);
float ao = 0.0;
for (float i = 1.0; i <= taps; i++) {
vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size;
- ao += textureLod(sampler3D(gi_probe_textures[index], linear_sampler_with_mipmaps), ofs, i - 1.0).a * i;
+ ao += textureLod(sampler3D(voxel_gi_textures[index], linear_sampler_with_mipmaps), ofs, i - 1.0).a * i;
}
if (blend > 0.001) {
vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size;
- ao += textureLod(sampler3D(gi_probe_textures[index], linear_sampler_with_mipmaps), ofs, taps).a * (taps + 1.0) * blend;
+ ao += textureLod(sampler3D(voxel_gi_textures[index], linear_sampler_with_mipmaps), ofs, taps).a * (taps + 1.0) * blend;
}
ao = 1.0 - min(1.0, ao);
- light.rgb = mix(params.ao_color, light.rgb, mix(1.0, ao, gi_probes.data[index].ambient_occlusion));
+ light.rgb = mix(params.ao_color, light.rgb, mix(1.0, ao, voxel_gi_instances.data[index].ambient_occlusion));
}
- light.rgb *= gi_probes.data[index].dynamic_range;
- if (!gi_probes.data[index].blend_ambient) {
+ light.rgb *= voxel_gi_instances.data[index].dynamic_range;
+ if (!voxel_gi_instances.data[index].blend_ambient) {
light.a = 1.0;
}
out_diff += light * blend;
//radiance
- vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias);
- irr_light.rgb *= gi_probes.data[index].dynamic_range;
- if (!gi_probes.data[index].blend_ambient) {
+ vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias);
+ irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range;
+ if (!voxel_gi_instances.data[index].blend_ambient) {
irr_light.a = 1.0;
}
@@ -614,9 +614,9 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref
sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light);
#endif
-#ifdef USE_GIPROBES
+#ifdef USE_VOXEL_GI_INSTANCES
{
- uvec2 giprobe_tex = texelFetch(usampler2D(giprobe_buffer, linear_sampler), pos, 0).rg;
+ uvec2 voxel_gi_tex = texelFetch(usampler2D(voxel_gi_buffer, linear_sampler), pos, 0).rg;
roughness *= roughness;
//find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
@@ -628,9 +628,9 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref
vec4 spec_accum = vec4(0.0);
float blend_accum = 0.0;
- for (uint i = 0; i < params.max_giprobes; i++) {
- if (any(equal(uvec2(i), giprobe_tex))) {
- gi_probe_compute(i, vertex, normal, reflection, normal_mat, roughness, spec_accum, amb_accum, blend_accum);
+ for (uint i = 0; i < params.max_voxel_gi_instances; i++) {
+ if (any(equal(uvec2(i), voxel_gi_tex))) {
+ voxel_gi_compute(i, vertex, normal, reflection, normal_mat, roughness, spec_accum, amb_accum, blend_accum);
}
}
if (blend_accum > 0.0) {
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index beaff10793..9f8410fd8a 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -19,6 +19,8 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
+#define SDF_MAX_LENGTH 16384.0
+
/* SET 0: GLOBAL DATA */
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
@@ -54,6 +56,7 @@ struct Attractor {
#define COLLIDER_TYPE_BOX 1
#define COLLIDER_TYPE_SDF 2
#define COLLIDER_TYPE_HEIGHT_FIELD 3
+#define COLLIDER_TYPE_2D_SDF 4
struct Collider {
mat4 transform;
@@ -452,128 +455,167 @@ void main() {
#endif
- for (uint i = 0; i < FRAME.collider_count; i++) {
- vec3 normal;
- float depth;
- bool col = false;
+ if (FRAME.collider_count == 1 && FRAME.colliders[0].type == COLLIDER_TYPE_2D_SDF) {
+ //2D collision
- vec3 rel_vec = PARTICLE.xform[3].xyz - FRAME.colliders[i].transform[3].xyz;
- vec3 local_pos = rel_vec * mat3(FRAME.colliders[i].transform);
+ vec2 pos = PARTICLE.xform[3].xy;
+ vec4 to_sdf_x = FRAME.colliders[0].transform[0];
+ vec4 to_sdf_y = FRAME.colliders[0].transform[1];
+ vec2 sdf_pos = vec2(dot(vec4(pos, 0, 1), to_sdf_x), dot(vec4(pos, 0, 1), to_sdf_y));
- switch (FRAME.colliders[i].type) {
- case COLLIDER_TYPE_SPHERE: {
- float d = length(rel_vec) - (particle_size + FRAME.colliders[i].extents.x);
+ vec4 sdf_to_screen = vec4(FRAME.colliders[0].extents, FRAME.colliders[0].scale);
- if (d < 0.0) {
- col = true;
- depth = -d;
- normal = normalize(rel_vec);
- }
+ vec2 uv_pos = sdf_pos * sdf_to_screen.xy + sdf_to_screen.zw;
- } break;
- case COLLIDER_TYPE_BOX: {
- vec3 abs_pos = abs(local_pos);
- vec3 sgn_pos = sign(local_pos);
+ if (all(greaterThan(uv_pos, vec2(0.0))) && all(lessThan(uv_pos, vec2(1.0)))) {
+ vec2 pos2 = pos + vec2(0, particle_size);
+ vec2 sdf_pos2 = vec2(dot(vec4(pos2, 0, 1), to_sdf_x), dot(vec4(pos2, 0, 1), to_sdf_y));
+ float sdf_particle_size = distance(sdf_pos, sdf_pos2);
+
+ float d = texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv_pos).r * SDF_MAX_LENGTH;
+
+ d -= sdf_particle_size;
+
+ if (d < 0.0) {
+ const float EPSILON = 0.001;
+ vec2 n = normalize(vec2(
+ texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv_pos + vec2(EPSILON, 0.0)).r - texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv_pos - vec2(EPSILON, 0.0)).r,
+ texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv_pos + vec2(0.0, EPSILON)).r - texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv_pos - vec2(0.0, EPSILON)).r));
+
+ collided = true;
+ sdf_pos2 = sdf_pos + n * d;
+ pos2 = vec2(dot(vec4(sdf_pos2, 0, 1), FRAME.colliders[0].transform[2]), dot(vec4(sdf_pos2, 0, 1), FRAME.colliders[0].transform[3]));
+
+ n = pos - pos2;
+
+ collision_normal = normalize(vec3(n, 0.0));
+ collision_depth = length(n);
+ }
+ }
+
+ } else {
+ for (uint i = 0; i < FRAME.collider_count; i++) {
+ vec3 normal;
+ float depth;
+ bool col = false;
- if (any(greaterThan(abs_pos, FRAME.colliders[i].extents))) {
- //point outside box
+ vec3 rel_vec = PARTICLE.xform[3].xyz - FRAME.colliders[i].transform[3].xyz;
+ vec3 local_pos = rel_vec * mat3(FRAME.colliders[i].transform);
- vec3 closest = min(abs_pos, FRAME.colliders[i].extents);
- vec3 rel = abs_pos - closest;
- depth = length(rel) - particle_size;
- if (depth < 0.0) {
+ switch (FRAME.colliders[i].type) {
+ case COLLIDER_TYPE_SPHERE: {
+ float d = length(rel_vec) - (particle_size + FRAME.colliders[i].extents.x);
+
+ if (d < 0.0) {
col = true;
- normal = mat3(FRAME.colliders[i].transform) * (normalize(rel) * sgn_pos);
- depth = -depth;
+ depth = -d;
+ normal = normalize(rel_vec);
}
- } else {
- //point inside box
- vec3 axis_len = FRAME.colliders[i].extents - abs_pos;
- // there has to be a faster way to do this?
- if (all(lessThan(axis_len.xx, axis_len.yz))) {
- normal = vec3(1, 0, 0);
- } else if (all(lessThan(axis_len.yy, axis_len.xz))) {
- normal = vec3(0, 1, 0);
+
+ } break;
+ case COLLIDER_TYPE_BOX: {
+ vec3 abs_pos = abs(local_pos);
+ vec3 sgn_pos = sign(local_pos);
+
+ if (any(greaterThan(abs_pos, FRAME.colliders[i].extents))) {
+ //point outside box
+
+ vec3 closest = min(abs_pos, FRAME.colliders[i].extents);
+ vec3 rel = abs_pos - closest;
+ depth = length(rel) - particle_size;
+ if (depth < 0.0) {
+ col = true;
+ normal = mat3(FRAME.colliders[i].transform) * (normalize(rel) * sgn_pos);
+ depth = -depth;
+ }
} else {
- normal = vec3(0, 0, 1);
+ //point inside box
+ vec3 axis_len = FRAME.colliders[i].extents - abs_pos;
+ // there has to be a faster way to do this?
+ if (all(lessThan(axis_len.xx, axis_len.yz))) {
+ normal = vec3(1, 0, 0);
+ } else if (all(lessThan(axis_len.yy, axis_len.xz))) {
+ normal = vec3(0, 1, 0);
+ } else {
+ normal = vec3(0, 0, 1);
+ }
+
+ col = true;
+ depth = dot(normal * axis_len, vec3(1)) + particle_size;
+ normal = mat3(FRAME.colliders[i].transform) * (normal * sgn_pos);
}
- col = true;
- depth = dot(normal * axis_len, vec3(1)) + particle_size;
- normal = mat3(FRAME.colliders[i].transform) * (normal * sgn_pos);
- }
+ } break;
+ case COLLIDER_TYPE_SDF: {
+ vec3 apos = abs(local_pos);
+ float extra_dist = 0.0;
+ if (any(greaterThan(apos, FRAME.colliders[i].extents))) { //outside
+ vec3 mpos = min(apos, FRAME.colliders[i].extents);
+ extra_dist = distance(mpos, apos);
+ }
- } break;
- case COLLIDER_TYPE_SDF: {
- vec3 apos = abs(local_pos);
- float extra_dist = 0.0;
- if (any(greaterThan(apos, FRAME.colliders[i].extents))) { //outside
- vec3 mpos = min(apos, FRAME.colliders[i].extents);
- extra_dist = distance(mpos, apos);
- }
+ if (extra_dist > particle_size) {
+ continue;
+ }
- if (extra_dist > particle_size) {
- continue;
- }
+ vec3 uvw_pos = (local_pos / FRAME.colliders[i].extents) * 0.5 + 0.5;
+ float s = texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).r;
+ s *= FRAME.colliders[i].scale;
+ s += extra_dist;
+ if (s < particle_size) {
+ col = true;
+ depth = particle_size - s;
+ const float EPSILON = 0.001;
+ normal = mat3(FRAME.colliders[i].transform) *
+ normalize(
+ vec3(
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(EPSILON, 0.0, 0.0)).r,
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, EPSILON, 0.0)).r,
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, 0.0, EPSILON)).r));
+ }
- vec3 uvw_pos = (local_pos / FRAME.colliders[i].extents) * 0.5 + 0.5;
- float s = texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).r;
- s *= FRAME.colliders[i].scale;
- s += extra_dist;
- if (s < particle_size) {
- col = true;
- depth = particle_size - s;
- const float EPSILON = 0.001;
- normal = mat3(FRAME.colliders[i].transform) *
- normalize(
- vec3(
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(EPSILON, 0.0, 0.0)).r,
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, EPSILON, 0.0)).r,
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, 0.0, EPSILON)).r));
- }
+ } break;
+ case COLLIDER_TYPE_HEIGHT_FIELD: {
+ vec3 local_pos_bottom = local_pos;
+ local_pos_bottom.y -= particle_size;
- } break;
- case COLLIDER_TYPE_HEIGHT_FIELD: {
- vec3 local_pos_bottom = local_pos;
- local_pos_bottom.y -= particle_size;
+ if (any(greaterThan(abs(local_pos_bottom), FRAME.colliders[i].extents))) {
+ continue;
+ }
+ const float DELTA = 1.0 / 8192.0;
- if (any(greaterThan(abs(local_pos_bottom), FRAME.colliders[i].extents))) {
- continue;
- }
+ vec3 uvw_pos = vec3(local_pos_bottom / FRAME.colliders[i].extents) * 0.5 + 0.5;
- const float DELTA = 1.0 / 8192.0;
+ float y = 1.0 - texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos.xz).r;
- vec3 uvw_pos = vec3(local_pos_bottom / FRAME.colliders[i].extents) * 0.5 + 0.5;
+ if (y > uvw_pos.y) {
+ //inside heightfield
- float y = 1.0 - texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos.xz).r;
+ vec3 pos1 = (vec3(uvw_pos.x, y, uvw_pos.z) * 2.0 - 1.0) * FRAME.colliders[i].extents;
+ vec3 pos2 = (vec3(uvw_pos.x + DELTA, 1.0 - texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos.xz + vec2(DELTA, 0)).r, uvw_pos.z) * 2.0 - 1.0) * FRAME.colliders[i].extents;
+ vec3 pos3 = (vec3(uvw_pos.x, 1.0 - texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos.xz + vec2(0, DELTA)).r, uvw_pos.z + DELTA) * 2.0 - 1.0) * FRAME.colliders[i].extents;
- if (y > uvw_pos.y) {
- //inside heightfield
+ normal = normalize(cross(pos1 - pos2, pos1 - pos3));
+ float local_y = (vec3(local_pos / FRAME.colliders[i].extents) * 0.5 + 0.5).y;
- vec3 pos1 = (vec3(uvw_pos.x, y, uvw_pos.z) * 2.0 - 1.0) * FRAME.colliders[i].extents;
- vec3 pos2 = (vec3(uvw_pos.x + DELTA, 1.0 - texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos.xz + vec2(DELTA, 0)).r, uvw_pos.z) * 2.0 - 1.0) * FRAME.colliders[i].extents;
- vec3 pos3 = (vec3(uvw_pos.x, 1.0 - texture(sampler2D(height_field_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos.xz + vec2(0, DELTA)).r, uvw_pos.z + DELTA) * 2.0 - 1.0) * FRAME.colliders[i].extents;
+ col = true;
+ depth = dot(normal, pos1) - dot(normal, local_pos_bottom);
+ }
- normal = normalize(cross(pos1 - pos2, pos1 - pos3));
- float local_y = (vec3(local_pos / FRAME.colliders[i].extents) * 0.5 + 0.5).y;
+ } break;
+ }
- col = true;
- depth = dot(normal, pos1) - dot(normal, local_pos_bottom);
+ if (col) {
+ if (!collided) {
+ collided = true;
+ collision_normal = normal;
+ collision_depth = depth;
+ } else {
+ vec3 c = collision_normal * collision_depth;
+ c += normal * max(0.0, depth - dot(normal, c));
+ collision_normal = normalize(c);
+ collision_depth = length(c);
}
-
- } break;
- }
-
- if (col) {
- if (!collided) {
- collided = true;
- collision_normal = normal;
- collision_depth = depth;
- } else {
- vec3 c = collision_normal * collision_depth;
- c += normal * max(0.0, depth - dot(normal, c));
- collision_normal = normalize(c);
- collision_depth = length(c);
}
}
}
diff --git a/servers/rendering/renderer_rd/shaders/particles_copy.glsl b/servers/rendering/renderer_rd/shaders/particles_copy.glsl
index e2bebadf1a..4dceeea995 100644
--- a/servers/rendering/renderer_rd/shaders/particles_copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles_copy.glsl
@@ -53,6 +53,11 @@ layout(push_constant, binding = 0, std430) uniform Params {
vec3 align_up;
uint align_mode;
+
+ bool order_by_lifetime;
+ uint lifetime_split;
+ bool lifetime_reverse;
+ uint pad;
}
params;
@@ -80,7 +85,6 @@ void main() {
#ifdef MODE_FILL_INSTANCES
uint particle = gl_GlobalInvocationID.x;
- uint write_offset = gl_GlobalInvocationID.x * (3 + 1 + 1); //xform + color + custom
if (particle >= params.total_particles) {
return; //discard
@@ -93,7 +97,41 @@ void main() {
} else {
particle = uint(sort_buffer.data[particle].y); //use index from sort buffer
}
-#endif
+#else
+ if (params.order_by_lifetime) {
+ if (params.trail_size > 1) {
+ uint limit = (params.total_particles / params.trail_size) - params.lifetime_split;
+
+ uint base_index = particle / params.trail_size;
+ uint base_offset = particle % params.trail_size;
+
+ if (params.lifetime_reverse) {
+ base_index = (params.total_particles / params.trail_size) - base_index - 1;
+ }
+
+ if (base_index < limit) {
+ base_index = params.lifetime_split + base_index;
+ } else {
+ base_index -= limit;
+ }
+
+ particle = base_index * params.trail_size + base_offset;
+
+ } else {
+ uint limit = params.total_particles - params.lifetime_split;
+
+ if (params.lifetime_reverse) {
+ particle = params.total_particles - particle - 1;
+ }
+
+ if (particle < limit) {
+ particle = params.lifetime_split + particle;
+ } else {
+ particle -= limit;
+ }
+ }
+ }
+#endif // USE_SORT_BUFFER
mat4 txform;
@@ -165,12 +203,17 @@ void main() {
#ifdef MODE_2D
+ uint write_offset = gl_GlobalInvocationID.x * (2 + 1 + 1); //xform + color + custom
+
instances.data[write_offset + 0] = txform[0];
instances.data[write_offset + 1] = txform[1];
instances.data[write_offset + 2] = particles.data[particle].color;
instances.data[write_offset + 3] = particles.data[particle].custom;
#else
+
+ uint write_offset = gl_GlobalInvocationID.x * (3 + 1 + 1); //xform + color + custom
+
instances.data[write_offset + 0] = txform[0];
instances.data[write_offset + 1] = txform[1];
instances.data[write_offset + 2] = txform[2];
diff --git a/servers/rendering/renderer_rd/shaders/resolve.glsl b/servers/rendering/renderer_rd/shaders/resolve.glsl
index 2286a26485..a4610e081c 100644
--- a/servers/rendering/renderer_rd/shaders/resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/resolve.glsl
@@ -13,9 +13,9 @@ layout(set = 0, binding = 1) uniform sampler2DMS source_normal_roughness;
layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_depth;
layout(rgba8, set = 1, binding = 1) uniform restrict writeonly image2D dest_normal_roughness;
-#ifdef GIPROBE_RESOLVE
-layout(set = 2, binding = 0) uniform usampler2DMS source_giprobe;
-layout(rg8ui, set = 3, binding = 0) uniform restrict writeonly uimage2D dest_giprobe;
+#ifdef VOXEL_GI_RESOLVE
+layout(set = 2, binding = 0) uniform usampler2DMS source_voxel_gi;
+layout(rg8ui, set = 3, binding = 0) uniform restrict writeonly uimage2D dest_voxel_gi;
#endif
#endif
@@ -38,8 +38,8 @@ void main() {
float best_depth = 1e20;
vec4 best_normal_roughness = vec4(0.0);
-#ifdef GIPROBE_RESOLVE
- uvec2 best_giprobe;
+#ifdef VOXEL_GI_RESOLVE
+ uvec2 best_voxel_gi;
#endif
#if 0
@@ -50,8 +50,8 @@ void main() {
best_depth = depth;
best_normal_roughness = texelFetch(source_normal_roughness,pos,i);
-#ifdef GIPROBE_RESOLVE
- best_giprobe = texelFetch(source_giprobe,pos,i).rg;
+#ifdef VOXEL_GI_RESOLVE
+ best_voxel_gi = texelFetch(source_voxel_gi,pos,i).rg;
#endif
}
}
@@ -204,16 +204,16 @@ void main() {
#endif
best_depth = texelFetch(source_depth, pos, best_index).r;
best_normal_roughness = texelFetch(source_normal_roughness, pos, best_index);
-#ifdef GIPROBE_RESOLVE
- best_giprobe = texelFetch(source_giprobe, pos, best_index).rg;
+#ifdef VOXEL_GI_RESOLVE
+ best_voxel_gi = texelFetch(source_voxel_gi, pos, best_index).rg;
#endif
#endif
imageStore(dest_depth, pos, vec4(best_depth));
imageStore(dest_normal_roughness, pos, vec4(best_normal_roughness));
-#ifdef GIPROBE_RESOLVE
- imageStore(dest_giprobe, pos, uvec4(best_giprobe, 0, 0));
+#ifdef VOXEL_GI_RESOLVE
+ imageStore(dest_voxel_gi, pos, uvec4(best_voxel_gi, 0, 0));
#endif
#endif
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 1d67a3f1df..ce02d5c4d0 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -426,8 +426,8 @@ layout(location = 4) out float depth_output_buffer;
#ifdef MODE_RENDER_NORMAL_ROUGHNESS
layout(location = 0) out vec4 normal_roughness_output_buffer;
-#ifdef MODE_RENDER_GIPROBE
-layout(location = 1) out uvec2 giprobe_buffer;
+#ifdef MODE_RENDER_VOXEL_GI
+layout(location = 1) out uvec2 voxel_gi_buffer;
#endif
#endif //MODE_RENDER_NORMAL
@@ -662,7 +662,7 @@ void main() {
#endif
#ifdef ALPHA_ANTIALIASING_EDGE_USED
-// If alpha scissor is used, we must further the edge threshold, otherwise we wont get any edge feather
+// If alpha scissor is used, we must further the edge threshold, otherwise we won't get any edge feather
#ifdef ALPHA_SCISSOR_USED
alpha_antialiasing_edge = clamp(alpha_scissor_threshold + alpha_antialiasing_edge, 0.0, 1.0);
#endif
@@ -850,7 +850,7 @@ void main() {
if (scene_data.roughness_limiter_enabled) {
//http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
float roughness2 = roughness * roughness;
- vec3 dndu = dFdx(normal), dndv = dFdx(normal);
+ vec3 dndu = dFdx(normal), dndv = dFdy(normal);
float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv));
float kernelRoughness2 = min(2.0 * variance, scene_data.roughness_limiter_limit); //limit effect
float filteredRoughness2 = min(1.0, roughness2 + kernelRoughness2);
@@ -1042,7 +1042,7 @@ void main() {
}
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
@@ -1054,12 +1054,12 @@ void main() {
vec4 amb_accum = vec4(0.0);
vec4 spec_accum = vec4(0.0);
- gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ voxel_gi_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
uint index2 = instances.data[instance_index].gi_offset >> 16;
if (index2 != 0xFFFF) {
- gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ voxel_gi_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
}
if (amb_accum.a > 0.0) {
@@ -1929,15 +1929,15 @@ void main() {
#ifdef MODE_RENDER_NORMAL_ROUGHNESS
normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
-#ifdef MODE_RENDER_GIPROBE
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
+#ifdef MODE_RENDER_VOXEL_GI
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
uint index2 = instances.data[instance_index].gi_offset >> 16;
- giprobe_buffer.x = index1 & 0xFF;
- giprobe_buffer.y = index2 & 0xFF;
+ voxel_gi_buffer.x = index1 & 0xFF;
+ voxel_gi_buffer.y = index2 & 0xFF;
} else {
- giprobe_buffer.x = 0xFF;
- giprobe_buffer.y = 0xFF;
+ voxel_gi_buffer.x = 0xFF;
+ voxel_gi_buffer.y = 0xFF;
}
#endif
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index ca75d6300e..e64e52623e 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -1,7 +1,7 @@
#define M_PI 3.14159265359
#define ROUGHNESS_MAX_LOD 5
-#define MAX_GI_PROBES 8
+#define MAX_VOXEL_GI_INSTANCES 8
#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic)
@@ -15,7 +15,7 @@
#include "cluster_data_inc.glsl"
#include "decal_data_inc.glsl"
-#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_GIPROBE) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED)
+#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_VOXEL_GI) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED)
#ifndef NORMAL_USED
#define NORMAL_USED
#endif
@@ -57,7 +57,7 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9)
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10)
-#define INSTANCE_FLAGS_USE_GIPROBE (1 << 11)
+#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11)
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
@@ -122,7 +122,7 @@ layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableDat
}
global_variables;
-struct SDFGIProbeCascadeData {
+struct SDFVoxelGICascadeData {
vec3 position;
float to_probe;
ivec3 probe_world_offset;
@@ -153,7 +153,7 @@ layout(set = 0, binding = 13, std140) uniform SDFGI {
vec3 cascade_probe_size;
uint pad5;
- SDFGIProbeCascadeData cascades[SDFGI_MAX_CASCADES];
+ SDFVoxelGICascadeData cascades[SDFGI_MAX_CASCADES];
}
sdfgi;
@@ -275,7 +275,7 @@ layout(set = 1, binding = 5) uniform texture2D directional_shadow_atlas;
layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
-layout(set = 1, binding = 7) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
+layout(set = 1, binding = 7) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
layout(set = 1, binding = 8, std430) buffer restrict readonly ClusterBuffer {
uint data[];
@@ -306,7 +306,7 @@ layout(set = 1, binding = 14) uniform texture2D reflection_buffer;
layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture;
layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades;
-struct GIProbeData {
+struct VoxelGIData {
mat4 xform;
vec3 bounds;
float dynamic_range;
@@ -322,10 +322,10 @@ struct GIProbeData {
uint mipmaps;
};
-layout(set = 1, binding = 17, std140) uniform GIProbes {
- GIProbeData data[MAX_GI_PROBES];
+layout(set = 1, binding = 17, std140) uniform VoxelGIs {
+ VoxelGIData data[MAX_VOXEL_GI_INSTANCES];
}
-gi_probes;
+voxel_gi_instances;
layout(set = 1, binding = 18) uniform texture3D volumetric_fog_texture;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
index b41f16cbe7..c88bd0a14b 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
@@ -48,24 +48,24 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3
return color;
}
-void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) {
- position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
- ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
- normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz);
+void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) {
+ position = (voxel_gi_instances.data[index].xform * vec4(position, 1.0)).xyz;
+ ref_vec = normalize((voxel_gi_instances.data[index].xform * vec4(ref_vec, 0.0)).xyz);
+ normal = normalize((voxel_gi_instances.data[index].xform * vec4(normal, 0.0)).xyz);
- position += normal * gi_probes.data[index].normal_bias;
+ position += normal * voxel_gi_instances.data[index].normal_bias;
//this causes corrupted pixels, i have no idea why..
- if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) {
+ if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, voxel_gi_instances.data[index].bounds))))) {
return;
}
- vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0);
+ vec3 blendv = abs(position / voxel_gi_instances.data[index].bounds * 2.0 - 1.0);
float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0);
//float blend=1.0;
- float max_distance = length(gi_probes.data[index].bounds);
- vec3 cell_size = 1.0 / gi_probes.data[index].bounds;
+ float max_distance = length(voxel_gi_instances.data[index].bounds);
+ vec3 cell_size = 1.0 / voxel_gi_instances.data[index].bounds;
//radiance
@@ -83,26 +83,26 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
vec3 light = vec3(0.0);
for (int i = 0; i < MAX_CONE_DIRS; i++) {
- vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
+ vec3 dir = normalize((voxel_gi_instances.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
- vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
+ vec4 cone_light = voxel_cone_trace_45_degrees(voxel_gi_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, voxel_gi_instances.data[index].bias);
- if (gi_probes.data[index].blend_ambient) {
+ if (voxel_gi_instances.data[index].blend_ambient) {
cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95));
}
light += cone_weights[i] * cone_light.rgb;
}
- light *= gi_probes.data[index].dynamic_range;
+ light *= voxel_gi_instances.data[index].dynamic_range;
out_diff += vec4(light * blend, blend);
//irradiance
- vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias);
- if (gi_probes.data[index].blend_ambient) {
+ vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias);
+ if (voxel_gi_instances.data[index].blend_ambient) {
irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95));
}
- irr_light.rgb *= gi_probes.data[index].dynamic_range;
+ irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range;
//irr_light=vec3(0.0);
out_spec += vec4(irr_light.rgb * blend, blend);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 32a86cb166..709ea45b88 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -144,12 +144,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
float metallic = unpackUnorm4x8(orms).z;
if (metallic < 1.0) {
float roughness = unpackUnorm4x8(orms).y;
-
-#if defined(DIFFUSE_OREN_NAYAR)
- vec3 diffuse_brdf_NL;
-#else
float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
-#endif
#if defined(DIFFUSE_LAMBERT_WRAP)
// energy conserving lambert wrap shader
@@ -243,7 +238,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
#elif defined(SPECULAR_PHONG)
vec3 R = normalize(-reflect(L, N));
+#ifdef USE_SOFT_SHADOWS
float cRdotV = clamp(A + dot(R, V), 0.0, 1.0);
+#else
+ float cRdotV = clamp(dot(R, V), 0.0, 1.0);
+#endif
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
float phong = pow(cRdotV, shininess);
phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index b38b8d803d..aa8a0b96c5 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -96,6 +96,18 @@ layout(location = 8) out float dp_clip;
#endif
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif
+#else
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
invariant gl_Position;
#GLOBALS
@@ -234,7 +246,13 @@ void main() {
vec4 position;
#endif
+#ifdef USE_MULTIVIEW
+ mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex];
+ mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex];
+#else
mat4 projection_matrix = scene_data.projection_matrix;
+ mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+#endif //USE_MULTIVIEW
//using world coordinates
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
@@ -386,10 +404,26 @@ layout(location = 8) in float dp_clip;
#endif
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif
+#else
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
//defines to keep compatibility with vertex
#define world_matrix draw_call.transform
+#ifdef USE_MULTIVIEW
+#define projection_matrix scene_data.projection_matrix_view[ViewIndex]
+#else
#define projection_matrix scene_data.projection_matrix
+#endif
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
//both required for transmittance to be enabled
@@ -622,7 +656,7 @@ void main() {
#endif
#ifdef ALPHA_ANTIALIASING_EDGE_USED
-// If alpha scissor is used, we must further the edge threshold, otherwise we wont get any edge feather
+// If alpha scissor is used, we must further the edge threshold, otherwise we won't get any edge feather
#ifdef ALPHA_SCISSOR_USED
alpha_antialiasing_edge = clamp(alpha_scissor_threshold + alpha_antialiasing_edge, 0.0, 1.0);
#endif
@@ -761,7 +795,7 @@ void main() {
if (scene_data.roughness_limiter_enabled) {
//http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
float roughness2 = roughness * roughness;
- vec3 dndu = dFdx(normal), dndv = dFdx(normal);
+ vec3 dndu = dFdx(normal), dndv = dFdy(normal);
float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv));
float kernelRoughness2 = min(2.0 * variance, scene_data.roughness_limiter_limit); //limit effect
float filteredRoughness2 = min(1.0, roughness2 + kernelRoughness2);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index 0156b58574..7fcd84695d 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -1,4 +1,9 @@
#define M_PI 3.14159265359
+#define MAX_VIEWS 2
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
#include "decal_data_inc.glsl"
@@ -51,7 +56,7 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9)
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10)
-#define INSTANCE_FLAGS_USE_GIPROBE (1 << 11)
+#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11)
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
@@ -121,10 +126,13 @@ global_variables;
layout(set = 1, binding = 0, std140) uniform SceneData {
mat4 projection_matrix;
mat4 inv_projection_matrix;
-
mat4 camera_matrix;
mat4 inv_camera_matrix;
+ // only used for multiview
+ mat4 projection_matrix_view[MAX_VIEWS];
+ mat4 inv_projection_matrix_view[MAX_VIEWS];
+
vec2 viewport_size;
vec2 screen_pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl
index 9924da37d5..41c6325bc5 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/sky.glsl
@@ -4,11 +4,17 @@
#VERSION_DEFINES
+#define MAX_VIEWS 2
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
layout(location = 0) out vec2 uv_interp;
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
- vec4 proj;
+ vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
float time;
}
@@ -26,15 +32,29 @@ void main() {
#VERSION_DEFINES
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
#define M_PI 3.14159265359
+#define MAX_VIEWS 2
layout(location = 0) in vec2 uv_interp;
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
- vec4 proj;
+ vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
- float time; //TODO consider adding vec2 screen res, and float radiance size
+ float time;
}
params;
@@ -85,7 +105,6 @@ struct DirectionalLightData {
layout(set = 0, binding = 3, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
-
directional_lights;
#ifdef MATERIAL_UNIFORMS_USED
@@ -154,8 +173,8 @@ vec4 fog_process(vec3 view, vec3 sky_color) {
void main() {
vec3 cube_normal;
cube_normal.z = -1.0;
- cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y;
- cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.proj.z)) / params.proj.w;
+ cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projections[ViewIndex].x)) / params.projections[ViewIndex].y;
+ cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projections[ViewIndex].z)) / params.projections[ViewIndex].w;
cube_normal = mat3(params.orientation) * cube_normal;
cube_normal.z = -cube_normal.z;
cube_normal = normalize(cube_normal);
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index 86b4da6b08..23f83b3b9c 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -4,6 +4,12 @@
#VERSION_DEFINES
+#ifdef MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#endif
+#endif
+
layout(location = 0) out vec2 uv_interp;
void main() {
@@ -18,9 +24,22 @@ void main() {
#VERSION_DEFINES
+#ifdef MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#endif //MULTIVIEW
+
layout(location = 0) in vec2 uv_interp;
+#ifdef MULTIVIEW
+layout(set = 0, binding = 0) uniform sampler2DArray source_color;
+#else
layout(set = 0, binding = 0) uniform sampler2D source_color;
+#endif
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(set = 2, binding = 0) uniform sampler2D source_glow;
#ifdef USE_1D_LUT
@@ -277,10 +296,17 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
const float FXAA_REDUCE_MUL = (1.0 / 8.0);
const float FXAA_SPAN_MAX = 8.0;
+#ifdef MULTIVIEW
+ vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+ vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+ vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+ vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+#else
vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
+#endif
vec3 rgbM = color;
vec3 luma = vec3(0.299, 0.587, 0.114);
float lumaNW = dot(rgbNW, luma);
@@ -305,8 +331,13 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
dir * rcpDirMin)) *
params.pixel_size;
+#ifdef MULTIVIEW
+ vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz);
+ vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz);
+#else
vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz);
+#endif
float lumaB = dot(rgbB, luma);
if ((lumaB < lumaMin) || (lumaB > lumaMax)) {
@@ -329,7 +360,11 @@ vec3 screen_space_dither(vec2 frag_coord) {
}
void main() {
+#ifdef MULTIVIEW
+ vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb;
+#else
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
+#endif
// Exposure
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
index c793b6ebe1..f2010222e5 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
@@ -72,9 +72,9 @@ layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D dest_ma
layout(set = 0, binding = 10) uniform sampler shadow_sampler;
-#define MAX_GI_PROBES 8
+#define MAX_VOXEL_GI_INSTANCES 8
-struct GIProbeData {
+struct VoxelGIData {
mat4 xform;
vec3 bounds;
float dynamic_range;
@@ -90,12 +90,12 @@ struct GIProbeData {
uint mipmaps;
};
-layout(set = 0, binding = 11, std140) uniform GIProbes {
- GIProbeData data[MAX_GI_PROBES];
+layout(set = 0, binding = 11, std140) uniform VoxelGIs {
+ VoxelGIData data[MAX_VOXEL_GI_INSTANCES];
}
-gi_probes;
+voxel_gi_instances;
-layout(set = 0, binding = 12) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
+layout(set = 0, binding = 12) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
layout(set = 0, binding = 13) uniform sampler linear_sampler_with_mipmaps;
@@ -104,7 +104,7 @@ layout(set = 0, binding = 13) uniform sampler linear_sampler_with_mipmaps;
// SDFGI Integration on set 1
#define SDFGI_MAX_CASCADES 8
-struct SDFGIProbeCascadeData {
+struct SDFVoxelGICascadeData {
vec3 position;
float to_probe;
ivec3 probe_world_offset;
@@ -135,7 +135,7 @@ layout(set = 1, binding = 0, std140) uniform SDFGI {
vec3 cascade_probe_size;
uint pad5;
- SDFGIProbeCascadeData cascades[SDFGI_MAX_CASCADES];
+ SDFVoxelGICascadeData cascades[SDFGI_MAX_CASCADES];
}
sdfgi;
@@ -162,7 +162,7 @@ layout(set = 0, binding = 14, std140) uniform Params {
float detail_spread;
float gi_inject;
- uint max_gi_probes;
+ uint max_voxel_gi_instances;
uint cluster_type_size;
vec2 screen_size;
@@ -533,21 +533,21 @@ void main() {
vec3 world_pos = mat3(params.cam_rotation) * view_pos;
- for (uint i = 0; i < params.max_gi_probes; i++) {
- vec3 position = (gi_probes.data[i].xform * vec4(world_pos, 1.0)).xyz;
+ for (uint i = 0; i < params.max_voxel_gi_instances; i++) {
+ vec3 position = (voxel_gi_instances.data[i].xform * vec4(world_pos, 1.0)).xyz;
//this causes corrupted pixels, i have no idea why..
- if (all(bvec2(all(greaterThanEqual(position, vec3(0.0))), all(lessThan(position, gi_probes.data[i].bounds))))) {
- position /= gi_probes.data[i].bounds;
+ if (all(bvec2(all(greaterThanEqual(position, vec3(0.0))), all(lessThan(position, voxel_gi_instances.data[i].bounds))))) {
+ position /= voxel_gi_instances.data[i].bounds;
vec4 light = vec4(0.0);
- for (uint j = 0; j < gi_probes.data[i].mipmaps; j++) {
- vec4 slight = textureLod(sampler3D(gi_probe_textures[i], linear_sampler_with_mipmaps), position, float(j));
+ for (uint j = 0; j < voxel_gi_instances.data[i].mipmaps; j++) {
+ vec4 slight = textureLod(sampler3D(voxel_gi_textures[i], linear_sampler_with_mipmaps), position, float(j));
float a = (1.0 - light.a);
light += a * slight;
}
- light.rgb *= gi_probes.data[i].dynamic_range * params.gi_inject;
+ light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject;
total_light += light.rgb;
}
diff --git a/servers/rendering/renderer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
index 49a493cdc7..49a493cdc7 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
diff --git a/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
index 7d4d72967a..7d4d72967a 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
diff --git a/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
index e20b3f680d..e20b3f680d 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index db1e3d1377..3b25498ed8 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -42,7 +42,7 @@ public:
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0;
- virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0;
+ virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform) = 0;
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
virtual void camera_set_camera_effects(RID p_camera, RID p_fx) = 0;
@@ -63,6 +63,8 @@ public:
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) = 0;
virtual bool is_scenario(RID p_scenario) const = 0;
virtual RID scenario_get_environment(RID p_scenario) = 0;
+ virtual void scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport) = 0;
+ virtual void scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport) = 0;
virtual RID instance_allocate() = 0;
virtual void instance_initialize(RID p_rid) = 0;
@@ -70,7 +72,7 @@ public:
virtual void instance_set_base(RID p_instance, RID p_base) = 0;
virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0;
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0;
- virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
+ virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0;
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0;
virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) = 0;
@@ -82,6 +84,7 @@ public:
virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0;
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
+ virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance) = 0;
// don't use these in a game!
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0;
@@ -92,8 +95,7 @@ public:
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) = 0;
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
- virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
- virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
@@ -189,20 +191,19 @@ public:
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
- virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
+ virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0;
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
- virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas) = 0;
- virtual void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas) = 0;
+ virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface) = 0;
virtual void update() = 0;
virtual void render_probes() = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index fcea8e4ffc..2c66b22089 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -74,7 +74,7 @@ void RendererSceneCull::camera_set_frustum(RID p_camera, float p_size, Vector2 p
camera->zfar = p_z_far;
}
-void RendererSceneCull::camera_set_transform(RID p_camera, const Transform &p_transform) {
+void RendererSceneCull::camera_set_transform(RID p_camera, const Transform3D &p_transform) {
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
camera->transform = p_transform.orthonormalized();
@@ -190,26 +190,26 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
}
- } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
+ } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_VOXEL_GI) && B->base_type == RS::INSTANCE_VOXEL_GI && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- geom->gi_probes.insert(B);
+ geom->voxel_gi_instances.insert(B);
if (A->dynamic_gi) {
- gi_probe->dynamic_geometries.insert(A);
+ voxel_gi->dynamic_geometries.insert(A);
} else {
- gi_probe->geometries.insert(A);
+ voxel_gi->geometries.insert(A);
}
if (A->scenario && A->array_index >= 0) {
InstanceData &idata = A->scenario->instance_data[A->array_index];
- idata.flags |= InstanceData::FLAG_GEOM_GI_PROBE_DIRTY;
+ idata.flags |= InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;
}
- } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
- gi_probe->lights.insert(A);
+ } else if (B->base_type == RS::INSTANCE_VOXEL_GI && A->base_type == RS::INSTANCE_LIGHT) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);
+ voxel_gi->lights.insert(A);
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
RSG::storage->particles_add_collision(A->base, collision->instance);
@@ -281,25 +281,25 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
}
- } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
+ } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_VOXEL_GI) && B->base_type == RS::INSTANCE_VOXEL_GI && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- geom->gi_probes.erase(B);
+ geom->voxel_gi_instances.erase(B);
if (A->dynamic_gi) {
- gi_probe->dynamic_geometries.erase(A);
+ voxel_gi->dynamic_geometries.erase(A);
} else {
- gi_probe->geometries.erase(A);
+ voxel_gi->geometries.erase(A);
}
if (A->scenario && A->array_index >= 0) {
InstanceData &idata = A->scenario->instance_data[A->array_index];
- idata.flags |= InstanceData::FLAG_GEOM_GI_PROBE_DIRTY;
+ idata.flags |= InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;
}
- } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
- gi_probe->lights.erase(A);
+ } else if (B->base_type == RS::INSTANCE_VOXEL_GI && A->base_type == RS::INSTANCE_LIGHT) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);
+ voxel_gi->lights.erase(A);
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
RSG::storage->particles_remove_collision(A->base, collision->instance);
@@ -323,6 +323,7 @@ void RendererSceneCull::scenario_initialize(RID p_rid) {
scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool);
scenario->instance_data.set_page_pool(&instance_data_page_pool);
+ scenario->instance_visibility.set_page_pool(&instance_visibility_data_page_pool);
RendererSceneOcclusionCull::get_singleton()->add_scenario(p_rid);
@@ -369,6 +370,37 @@ RID RendererSceneCull::scenario_get_environment(RID p_scenario) {
return scenario->environment;
}
+void RendererSceneCull::scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport) {
+ Scenario *scenario = scenario_owner.getornull(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ if (!scenario->viewport_visibility_masks.has(p_viewport)) {
+ return;
+ }
+
+ uint64_t mask = scenario->viewport_visibility_masks[p_viewport];
+ scenario->used_viewport_visibility_bits &= ~mask;
+ scenario->viewport_visibility_masks.erase(p_viewport);
+}
+
+void RendererSceneCull::scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport) {
+ Scenario *scenario = scenario_owner.getornull(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ ERR_FAIL_COND(scenario->viewport_visibility_masks.has(p_viewport));
+
+ uint64_t new_mask = 1;
+ while (new_mask & scenario->used_viewport_visibility_bits) {
+ new_mask <<= 1;
+ }
+
+ if (new_mask == 0) {
+ ERR_PRINT("Only 64 viewports per scenario allowed when using visibility ranges.");
+ new_mask = ((uint64_t)1) << 63;
+ }
+
+ scenario->viewport_visibility_masks[p_viewport] = new_mask;
+ scenario->used_viewport_visibility_bits |= new_mask;
+}
+
/* INSTANCING API */
void RendererSceneCull::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
@@ -494,23 +526,23 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
scene_render->free(lightmap_data->instance);
} break;
- case RS::INSTANCE_GI_PROBE: {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
+ case RS::INSTANCE_VOXEL_GI: {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);
#ifdef DEBUG_ENABLED
- if (gi_probe->geometries.size()) {
- ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe.");
+ if (voxel_gi->geometries.size()) {
+ ERR_PRINT("BUG, indexing did not unpair geometries from VoxelGI.");
}
#endif
#ifdef DEBUG_ENABLED
- if (gi_probe->lights.size()) {
- ERR_PRINT("BUG, indexing did not unpair lights from GIProbe.");
+ if (voxel_gi->lights.size()) {
+ ERR_PRINT("BUG, indexing did not unpair lights from VoxelGI.");
}
#endif
- if (gi_probe->update_element.in_list()) {
- gi_probe_update_list.remove(&gi_probe->update_element);
+ if (voxel_gi->update_element.in_list()) {
+ voxel_gi_update_list.remove(&voxel_gi->update_element);
}
- scene_render->free(gi_probe->probe_instance);
+ scene_render->free(voxel_gi->probe_instance);
} break;
case RS::INSTANCE_OCCLUDER: {
@@ -602,16 +634,16 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base_data = lightmap_data;
lightmap_data->instance = scene_render->lightmap_instance_create(p_base);
} break;
- case RS::INSTANCE_GI_PROBE: {
- InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData);
- instance->base_data = gi_probe;
- gi_probe->owner = instance;
+ case RS::INSTANCE_VOXEL_GI: {
+ InstanceVoxelGIData *voxel_gi = memnew(InstanceVoxelGIData);
+ instance->base_data = voxel_gi;
+ voxel_gi->owner = instance;
- if (scenario && !gi_probe->update_element.in_list()) {
- gi_probe_update_list.add(&gi_probe->update_element);
+ if (scenario && !voxel_gi->update_element.in_list()) {
+ voxel_gi_update_list.add(&voxel_gi->update_element);
}
- gi_probe->probe_instance = scene_render->gi_probe_instance_create(p_base);
+ voxel_gi->probe_instance = scene_render->voxel_gi_instance_create(p_base);
} break;
case RS::INSTANCE_OCCLUDER: {
@@ -668,22 +700,22 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
case RS::INSTANCE_PARTICLES_COLLISION: {
heightfield_particle_colliders_update_list.erase(instance);
} break;
- case RS::INSTANCE_GI_PROBE: {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
+ case RS::INSTANCE_VOXEL_GI: {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);
#ifdef DEBUG_ENABLED
- if (gi_probe->geometries.size()) {
- ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe.");
+ if (voxel_gi->geometries.size()) {
+ ERR_PRINT("BUG, indexing did not unpair geometries from VoxelGI.");
}
#endif
#ifdef DEBUG_ENABLED
- if (gi_probe->lights.size()) {
- ERR_PRINT("BUG, indexing did not unpair lights from GIProbe.");
+ if (voxel_gi->lights.size()) {
+ ERR_PRINT("BUG, indexing did not unpair lights from VoxelGI.");
}
#endif
- if (gi_probe->update_element.in_list()) {
- gi_probe_update_list.remove(&gi_probe->update_element);
+ if (voxel_gi->update_element.in_list()) {
+ voxel_gi_update_list.remove(&voxel_gi->update_element);
}
} break;
case RS::INSTANCE_OCCLUDER: {
@@ -714,10 +746,10 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
light->D = scenario->directional_lights.push_back(instance);
}
} break;
- case RS::INSTANCE_GI_PROBE: {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
- if (!gi_probe->update_element.in_list()) {
- gi_probe_update_list.add(&gi_probe->update_element);
+ case RS::INSTANCE_VOXEL_GI: {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);
+ if (!voxel_gi->update_element.in_list()) {
+ voxel_gi_update_list.add(&voxel_gi->update_element);
}
} break;
case RS::INSTANCE_OCCLUDER: {
@@ -746,7 +778,7 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
}
}
-void RendererSceneCull::instance_set_transform(RID p_instance, const Transform &p_transform) {
+void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D &p_transform) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
@@ -1103,10 +1135,142 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
}
}
-void RendererSceneCull::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
+void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
+ Instance *instance = instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ instance->visibility_range_begin = p_min;
+ instance->visibility_range_end = p_max;
+ instance->visibility_range_begin_margin = p_min_margin;
+ instance->visibility_range_end_margin = p_max_margin;
+
+ _update_instance_visibility_dependencies(instance);
+
+ if (instance->scenario && instance->visibility_index != -1) {
+ InstanceVisibilityData &vd = instance->scenario->instance_visibility[instance->visibility_index];
+ vd.range_begin = instance->visibility_range_begin;
+ vd.range_end = instance->visibility_range_end;
+ vd.range_begin_margin = instance->visibility_range_begin_margin;
+ vd.range_end_margin = instance->visibility_range_end_margin;
+ }
}
-void RendererSceneCull::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) {
+void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_parent_instance) {
+ Instance *instance = instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ Instance *old_parent = instance->visibility_parent;
+ if (old_parent) {
+ if ((1 << old_parent->base_type) & RS::INSTANCE_GEOMETRY_MASK && old_parent->base_data) {
+ InstanceGeometryData *old_parent_geom = static_cast<InstanceGeometryData *>(old_parent->base_data);
+ old_parent_geom->visibility_dependencies.erase(instance);
+ _update_instance_visibility_depth(old_parent);
+ }
+ instance->visibility_parent = nullptr;
+ }
+
+ Instance *parent = instance_owner.getornull(p_parent_instance);
+ ERR_FAIL_COND(p_parent_instance.is_valid() && !parent);
+
+ if (parent) {
+ if ((1 << parent->base_type) & RS::INSTANCE_GEOMETRY_MASK && parent->base_data) {
+ InstanceGeometryData *parent_geom = static_cast<InstanceGeometryData *>(parent->base_data);
+ parent_geom->visibility_dependencies.insert(instance);
+ _update_instance_visibility_depth(parent);
+ }
+ instance->visibility_parent = parent;
+ }
+
+ _update_instance_visibility_dependencies(instance);
+}
+
+void RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {
+ bool cycle_detected = false;
+ Set<Instance *> traversed_nodes;
+
+ {
+ Instance *instance = p_instance;
+ while (instance && ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ if (!geom->visibility_dependencies.is_empty()) {
+ uint32_t depth = 0;
+ for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
+ if (((1 << E->get()->base_type) & RS::INSTANCE_GEOMETRY_MASK) == 0 || !E->get()->base_data) {
+ continue;
+ }
+ InstanceGeometryData *child_geom = static_cast<InstanceGeometryData *>(E->get()->base_data);
+ depth = MAX(depth, child_geom->visibility_dependencies_depth);
+ }
+ geom->visibility_dependencies_depth = depth + 1;
+ } else {
+ geom->visibility_dependencies_depth = 0;
+ }
+
+ if (instance->scenario && instance->visibility_index != -1) {
+ instance->scenario->instance_visibility.move(instance->visibility_index, geom->visibility_dependencies_depth);
+ }
+
+ traversed_nodes.insert(instance);
+
+ instance = instance->visibility_parent;
+ if (traversed_nodes.has(instance)) {
+ cycle_detected = true;
+ break;
+ }
+ }
+ }
+
+ if (cycle_detected) {
+ ERR_PRINT("Cycle detected in the visibility dependecies tree.");
+ for (Set<Instance *>::Element *E = traversed_nodes.front(); E; E = E->next()) {
+ Instance *instance = E->get();
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ geom->visibility_dependencies_depth = 0;
+ if (instance->scenario && instance->visibility_index != -1) {
+ instance->scenario->instance_visibility.move(instance->visibility_index, geom->visibility_dependencies_depth);
+ }
+ }
+ }
+}
+
+void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_instance) {
+ bool is_geometry_instance = ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) && p_instance->base_data;
+ bool has_visibility_range = p_instance->visibility_range_begin > 0.0 || p_instance->visibility_range_end > 0.0;
+ bool needs_visibility_cull = has_visibility_range && is_geometry_instance && p_instance->array_index != -1;
+
+ if (!needs_visibility_cull && p_instance->visibility_index != -1) {
+ p_instance->scenario->instance_visibility.remove(p_instance->visibility_index);
+ p_instance->visibility_index = -1;
+ } else if (needs_visibility_cull && p_instance->visibility_index == -1) {
+ InstanceVisibilityData vd;
+ vd.instance = p_instance;
+ vd.range_begin = p_instance->visibility_range_begin;
+ vd.range_end = p_instance->visibility_range_end;
+ vd.range_begin_margin = p_instance->visibility_range_begin_margin;
+ vd.range_end_margin = p_instance->visibility_range_end_margin;
+ vd.position = p_instance->transformed_aabb.get_position() + p_instance->transformed_aabb.get_size() / 2.0f;
+ vd.array_index = p_instance->array_index;
+
+ InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ p_instance->scenario->instance_visibility.insert(vd, geom_data->visibility_dependencies_depth);
+ }
+
+ if (p_instance->scenario && p_instance->array_index != -1) {
+ p_instance->scenario->instance_data[p_instance->array_index].visibility_index = p_instance->visibility_index;
+
+ InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ if ((has_visibility_range || p_instance->visibility_parent) && (p_instance->visibility_index == -1 || (geom_data && geom_data->visibility_dependencies_depth == 0))) {
+ p_instance->scenario->instance_data[p_instance->array_index].flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
+ } else {
+ p_instance->scenario->instance_data[p_instance->array_index].flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
+ }
+
+ if (p_instance->visibility_parent) {
+ p_instance->scenario->instance_data[p_instance->array_index].parent_array_index = p_instance->visibility_parent->array_index;
+ } else {
+ p_instance->scenario->instance_data[p_instance->array_index].parent_array_index = -1;
+ }
+ }
}
void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) {
@@ -1253,10 +1417,10 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data);
scene_render->lightmap_instance_set_transform(lightmap->instance, p_instance->transform);
- } else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data);
+ } else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(p_instance->base_data);
- scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform);
+ scene_render->voxel_gi_instance_set_transform_to_data(voxel_gi->probe_instance, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
@@ -1352,12 +1516,23 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
idata.layer_mask = p_instance->layer_mask;
idata.flags = p_instance->base_type; //changing it means de-indexing, so this never needs to be changed later
idata.base_rid = p_instance->base;
+ idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1;
+ idata.visibility_index = p_instance->visibility_index;
+
switch (p_instance->base_type) {
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
case RS::INSTANCE_IMMEDIATE:
case RS::INSTANCE_PARTICLES: {
- idata.instance_geometry = static_cast<InstanceGeometryData *>(p_instance->base_data)->geometry_instance;
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ idata.instance_geometry = geom->geometry_instance;
+
+ for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;
+ }
+ }
} break;
case RS::INSTANCE_LIGHT: {
idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance.get_id();
@@ -1371,8 +1546,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
case RS::INSTANCE_LIGHTMAP: {
idata.instance_data_rid = static_cast<InstanceLightmapData *>(p_instance->base_data)->instance.get_id();
} break;
- case RS::INSTANCE_GI_PROBE: {
- idata.instance_data_rid = static_cast<InstanceGIProbeData *>(p_instance->base_data)->probe_instance.get_id();
+ case RS::INSTANCE_VOXEL_GI: {
+ idata.instance_data_rid = static_cast<InstanceVoxelGIData *>(p_instance->base_data)->probe_instance.get_id();
} break;
default: {
}
@@ -1404,6 +1579,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
p_instance->scenario->instance_data.push_back(idata);
p_instance->scenario->instance_aabbs.push_back(InstanceBounds(p_instance->transformed_aabb));
+ _update_instance_visibility_dependencies(p_instance);
} else {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, bvh_aabb);
@@ -1413,6 +1589,10 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
p_instance->scenario->instance_aabbs[p_instance->array_index] = InstanceBounds(p_instance->transformed_aabb);
}
+ if (p_instance->visibility_index != -1) {
+ p_instance->scenario->instance_visibility[p_instance->visibility_index].position = p_instance->transformed_aabb.get_position() + p_instance->transformed_aabb.get_size() / 2.0f;
+ }
+
//move instance and repair
pair_pass++;
@@ -1425,7 +1605,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
pair.pair_mask |= 1 << RS::INSTANCE_LIGHT;
- pair.pair_mask |= 1 << RS::INSTANCE_GI_PROBE;
+ pair.pair_mask |= 1 << RS::INSTANCE_VOXEL_GI;
pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP;
if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
pair.pair_mask |= 1 << RS::INSTANCE_PARTICLES_COLLISION;
@@ -1439,7 +1619,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
if (RSG::storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) {
- pair.pair_mask |= (1 << RS::INSTANCE_GI_PROBE);
+ pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI);
pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
}
} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) {
@@ -1451,7 +1631,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
pair.pair_mask = (1 << RS::INSTANCE_PARTICLES);
pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
- } else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
+ } else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) {
//lights and geometries
pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT);
pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
@@ -1486,9 +1666,24 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
//replace this by last
int32_t swap_with_index = p_instance->scenario->instance_data.size() - 1;
if (swap_with_index != p_instance->array_index) {
- p_instance->scenario->instance_data[swap_with_index].instance->array_index = p_instance->array_index; //swap
+ Instance *swapped_instance = p_instance->scenario->instance_data[swap_with_index].instance;
+ swapped_instance->array_index = p_instance->array_index; //swap
p_instance->scenario->instance_data[p_instance->array_index] = p_instance->scenario->instance_data[swap_with_index];
p_instance->scenario->instance_aabbs[p_instance->array_index] = p_instance->scenario->instance_aabbs[swap_with_index];
+
+ if (swapped_instance->visibility_index != -1) {
+ swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index;
+ }
+
+ if ((1 << swapped_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(swapped_instance->base_data);
+ for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance != p_instance && dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;
+ }
+ }
+ }
}
// pop last
@@ -1504,8 +1699,17 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0);
scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, nullptr, 0);
+ scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0);
+
+ for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
+ }
+ }
}
+
+ _update_instance_visibility_dependencies(p_instance);
}
void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
@@ -1566,8 +1770,8 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
new_aabb = RSG::storage->decal_get_aabb(p_instance->base);
} break;
- case RenderingServer::INSTANCE_GI_PROBE: {
- new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base);
+ case RenderingServer::INSTANCE_VOXEL_GI: {
+ new_aabb = RSG::storage->voxel_gi_get_bounds(p_instance->base);
} break;
case RenderingServer::INSTANCE_LIGHTMAP: {
@@ -1605,7 +1809,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
continue; //we are inside, ignore exteriors
}
- Transform to_bounds = lightmap->transform.affine_inverse();
+ Transform3D to_bounds = lightmap->transform.affine_inverse();
Vector3 center = p_instance->transform.xform(p_instance->aabb.position + p_instance->aabb.size * 0.5); //use aabb center
Vector3 lm_pos = to_bounds.xform(center);
@@ -1666,10 +1870,10 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, p_instance->lightmap_sh.ptr());
}
-void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
+void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
- Transform light_transform = p_instance->transform;
+ Transform3D light_transform = p_instance->transform;
light_transform.orthonormalize(); //scale does not count on lights
real_t max_distance = p_cam_projection.get_z_far();
@@ -1745,7 +1949,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
// obtain the light frustum ranges (given endpoints)
- Transform transform = light_transform; //discard scale and stabilize light
+ Transform3D transform = light_transform; //discard scale and stabilize light
Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized();
Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized();
@@ -1944,7 +2148,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
Vector2 uv_scale(1.0 / (x_max_cam - x_min_cam), 1.0 / (y_max_cam - y_min_cam));
- Transform ortho_transform;
+ Transform3D ortho_transform;
ortho_transform.basis = transform.basis;
ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;
@@ -1961,10 +2165,10 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
}
}
-bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_lod_threshold) {
+bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_lod_threshold) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
- Transform light_transform = p_instance->transform;
+ Transform3D light_transform = p_instance->transform;
light_transform.orthonormalize(); //scale does not count on lights
bool animated_material_found = false;
@@ -2071,7 +2275,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
Vector3(0, -1, 0)
};
- Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
+ Transform3D xform = light_transform * Transform3D().looking_at(view_normals[i], view_up[i]);
Vector<Plane> planes = cm.get_projection_planes(xform);
@@ -2186,153 +2390,159 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return animated_material_found;
}
-void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
-// render to mono camera
+void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface) {
#ifndef _3D_DISABLED
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
- /* STEP 1 - SETUP CAMERA */
- CameraMatrix camera_matrix;
- bool ortho = false;
-
- switch (camera->type) {
- case Camera::ORTHOGONAL: {
- camera_matrix.set_orthogonal(
- camera->size,
- p_viewport_size.width / (float)p_viewport_size.height,
- camera->znear,
- camera->zfar,
- camera->vaspect);
- ortho = true;
- } break;
- case Camera::PERSPECTIVE: {
- camera_matrix.set_perspective(
- camera->fov,
- p_viewport_size.width / (float)p_viewport_size.height,
- camera->znear,
- camera->zfar,
- camera->vaspect);
- ortho = false;
+ RendererSceneRender::CameraData camera_data;
+
+ // Setup Camera(s)
+ if (p_xr_interface.is_null()) {
+ // Normal camera
+ Transform3D transform = camera->transform;
+ CameraMatrix projection;
+ bool vaspect = camera->vaspect;
+ bool is_ortogonal = false;
+
+ switch (camera->type) {
+ case Camera::ORTHOGONAL: {
+ projection.set_orthogonal(
+ camera->size,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect);
+ is_ortogonal = true;
+ } break;
+ case Camera::PERSPECTIVE: {
+ projection.set_perspective(
+ camera->fov,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect);
- } break;
- case Camera::FRUSTUM: {
- camera_matrix.set_frustum(
- camera->size,
- p_viewport_size.width / (float)p_viewport_size.height,
- camera->offset,
- camera->znear,
- camera->zfar,
- camera->vaspect);
- ortho = false;
- } break;
+ } break;
+ case Camera::FRUSTUM: {
+ projection.set_frustum(
+ camera->size,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->offset,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect);
+ } break;
+ }
+
+ camera_data.set_camera(transform, projection, is_ortogonal, vaspect);
+ } else {
+ // Setup our camera for our XR interface.
+ // We can support multiple views here each with their own camera
+ Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS];
+ CameraMatrix projections[RendererSceneRender::MAX_RENDER_VIEWS];
+
+ uint32_t view_count = p_xr_interface->get_view_count();
+ ERR_FAIL_COND_MSG(view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported");
+
+ float aspect = p_viewport_size.width / (float)p_viewport_size.height;
+
+ Transform3D world_origin = XRServer::get_singleton()->get_world_origin();
+
+ // We ignore our camera position, it will have been positioned with a slightly old tracking position.
+ // Instead we take our origin point and have our XR interface add fresh tracking data! Whoohoo!
+ for (uint32_t v = 0; v < view_count; v++) {
+ transforms[v] = p_xr_interface->get_transform_for_view(v, world_origin);
+ projections[v] = p_xr_interface->get_projection_for_view(v, aspect, camera->znear, camera->zfar);
+ }
+
+ if (view_count == 1) {
+ camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect);
+ } else if (view_count == 2) {
+ camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect);
+ } else {
+ // this won't be called (see fail check above) but keeping this comment to indicate we may support more then 2 views in the future...
+ }
}
RID environment = _render_get_environment(p_camera, p_scenario);
RENDER_TIMESTAMP("Update occlusion buffer")
- RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera->transform, camera_matrix, ortho, RendererThreadPool::singleton->thread_work_pool);
+ // For now just cull on the first camera
+ RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_ortogonal, RendererThreadPool::singleton->thread_work_pool);
- _render_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
+ _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
#endif
}
-void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
- // render for AR/VR interface
-#if 0
- Camera *camera = camera_owner.getornull(p_camera);
- ERR_FAIL_COND(!camera);
+void RendererSceneCull::_visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data) {
+ uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t bin_from = p_thread * cull_data->cull_count / total_threads;
+ uint32_t bin_to = (p_thread + 1 == total_threads) ? cull_data->cull_count : ((p_thread + 1) * cull_data->cull_count / total_threads);
- /* SETUP CAMERA, we are ignoring type and FOV here */
- float aspect = p_viewport_size.width / (float)p_viewport_size.height;
- CameraMatrix camera_matrix = p_interface->get_projection_for_eye(p_eye, aspect, camera->znear, camera->zfar);
+ _visibility_cull(*cull_data, cull_data->cull_offset + bin_from, cull_data->cull_offset + bin_to);
+}
- // We also ignore our camera position, it will have been positioned with a slightly old tracking position.
- // Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo!
- Transform world_origin = XRServer::get_singleton()->get_world_origin();
- Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin);
+void RendererSceneCull::_visibility_cull(const VisibilityCullData &cull_data, uint64_t p_from, uint64_t p_to) {
+ Scenario *scenario = cull_data.scenario;
+ for (unsigned int i = p_from; i < p_to; i++) {
+ InstanceVisibilityData &vd = scenario->instance_visibility[i];
+ InstanceData &idata = scenario->instance_data[vd.array_index];
- RID environment = _render_get_environment(p_camera, p_scenario);
+ if (idata.parent_array_index >= 0) {
+ uint32_t parent_flags = scenario->instance_data[idata.parent_array_index].flags;
+ if ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN) || (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE) == 0) {
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ continue;
+ }
+ }
- // For stereo render we only prepare for our left eye and then reuse the outcome for our right eye
- if (p_eye == XRInterface::EYE_LEFT) {
- // Center our transform, we assume basis is equal.
- Transform mono_transform = cam_transform;
- Transform right_transform = p_interface->get_transform_for_eye(XRInterface::EYE_RIGHT, world_origin);
- mono_transform.origin += right_transform.origin;
- mono_transform.origin *= 0.5;
-
- // We need to combine our projection frustums for culling.
- // Ideally we should use our clipping planes for this and combine them,
- // however our shadow map logic uses our projection matrix.
- // Note: as our left and right frustums should be mirrored, we don't need our right projection matrix.
-
- // - get some base values we need
- float eye_dist = (mono_transform.origin - cam_transform.origin).length();
- float z_near = camera_matrix.get_z_near(); // get our near plane
- float z_far = camera_matrix.get_z_far(); // get our far plane
- float width = (2.0 * z_near) / camera_matrix.matrix[0][0];
- float x_shift = width * camera_matrix.matrix[2][0];
- float height = (2.0 * z_near) / camera_matrix.matrix[1][1];
- float y_shift = height * camera_matrix.matrix[2][1];
-
- // printf("Eye_dist = %f, Near = %f, Far = %f, Width = %f, Shift = %f\n", eye_dist, z_near, z_far, width, x_shift);
-
- // - calculate our near plane size (horizontal only, right_near is mirrored)
- float left_near = -eye_dist - ((width - x_shift) * 0.5);
-
- // - calculate our far plane size (horizontal only, right_far is mirrored)
- float left_far = -eye_dist - (z_far * (width - x_shift) * 0.5 / z_near);
- float left_far_right_eye = eye_dist - (z_far * (width + x_shift) * 0.5 / z_near);
- if (left_far > left_far_right_eye) {
- // on displays smaller then double our iod, the right eye far frustrum can overtake the left eyes.
- left_far = left_far_right_eye;
- }
-
- // - figure out required z-shift
- float slope = (left_far - left_near) / (z_far - z_near);
- float z_shift = (left_near / slope) - z_near;
-
- // - figure out new vertical near plane size (this will be slightly oversized thanks to our z-shift)
- float top_near = (height - y_shift) * 0.5;
- top_near += (top_near / z_near) * z_shift;
- float bottom_near = -(height + y_shift) * 0.5;
- bottom_near += (bottom_near / z_near) * z_shift;
-
- // printf("Left_near = %f, Left_far = %f, Top_near = %f, Bottom_near = %f, Z_shift = %f\n", left_near, left_far, top_near, bottom_near, z_shift);
-
- // - generate our frustum
- CameraMatrix combined_matrix;
- combined_matrix.set_frustum(left_near, -left_near, bottom_near, top_near, z_near + z_shift, z_far + z_shift);
-
- // and finally move our camera back
- Transform apply_z_shift;
- apply_z_shift.origin = Vector3(0.0, 0.0, z_shift); // z negative is forward so this moves it backwards
- mono_transform *= apply_z_shift;
-
- // now prepare our scene with our adjusted transform projection matrix
- _prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
- } else if (p_eye == XRInterface::EYE_MONO) {
- // For mono render, prepare as per usual
- _prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
- }
-
- // And render our scene...
- _render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
-#endif
-};
+ int range_check = _visibility_range_check(vd, cull_data.camera_position, cull_data.viewport_mask);
+
+ if (range_check == -1) {
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ } else if (range_check == 1) {
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ } else {
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ }
+ }
+}
+
+int RendererSceneCull::_visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask) {
+ float dist = p_camera_pos.distance_to(r_vis_data.position);
-void RendererSceneCull::_frustum_cull_threaded(uint32_t p_thread, CullData *cull_data) {
+ bool in_range_last_frame = p_viewport_mask & r_vis_data.viewport_state;
+ float begin_offset = in_range_last_frame ? -r_vis_data.range_begin_margin : r_vis_data.range_begin_margin;
+ float end_offset = in_range_last_frame ? r_vis_data.range_end_margin : -r_vis_data.range_end_margin;
+
+ if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end + end_offset) {
+ r_vis_data.viewport_state &= ~p_viewport_mask;
+ return -1;
+ } else if (r_vis_data.range_begin > 0.0f && dist < r_vis_data.range_begin + begin_offset) {
+ r_vis_data.viewport_state &= ~p_viewport_mask;
+ return 1;
+ } else {
+ r_vis_data.viewport_state |= p_viewport_mask;
+ return 0;
+ }
+}
+
+void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {
uint32_t cull_total = cull_data->scenario->instance_data.size();
uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
uint32_t cull_from = p_thread * cull_total / total_threads;
uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads);
- _frustum_cull(*cull_data, frustum_cull_result_threads[p_thread], cull_from, cull_to);
+ _scene_cull(*cull_data, scene_cull_result_threads[p_thread], cull_from, cull_to);
}
-void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to) {
+void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to) {
uint64_t frame_number = RSG::rasterizer->get_frame_number();
float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
@@ -2341,183 +2551,198 @@ void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cu
RID instance_pair_buffer[MAX_INSTANCE_PAIRS];
- Transform inv_cam_transform = cull_data.cam_transform.inverse();
+ Transform3D inv_cam_transform = cull_data.cam_transform.inverse();
float z_near = cull_data.camera_matrix->get_z_near();
for (uint64_t i = p_from; i < p_to; i++) {
bool mesh_visible = false;
- if (cull_data.scenario->instance_aabbs[i].in_frustum(cull_data.cull->frustum) && (cull_data.occlusion_buffer == nullptr || cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING ||
- !cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))) {
- InstanceData &idata = cull_data.scenario->instance_data[i];
- uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
-
- if ((cull_data.visible_layers & idata.layer_mask) == 0) {
- //failure
- } else if (base_type == RS::INSTANCE_LIGHT) {
- cull_result.lights.push_back(idata.instance);
- cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));
- if (cull_data.shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
- scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
- }
+ InstanceData &idata = cull_data.scenario->instance_data[i];
+ uint32_t visibility_flags = idata.flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN);
+ int32_t visibility_check = -1;
+
+#define HIDDEN_BY_VISIBILITY_CHECKS (visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE || visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN)
+#define LAYER_CHECK (cull_data.visible_layers & idata.layer_mask)
+#define IN_FRUSTUM(f) (cull_data.scenario->instance_aabbs[i].in_frustum(f))
+#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_cull_data->viewport_mask) == 0)
+#define VIS_PARENT_CHECK ((idata.parent_array_index == -1) || ((cull_data.scenario->instance_data[idata.parent_array_index].flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE))
+#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)
+#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))
+
+ if (!HIDDEN_BY_VISIBILITY_CHECKS) {
+ if (LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) {
+ uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
+ if (base_type == RS::INSTANCE_LIGHT) {
+ cull_result.lights.push_back(idata.instance);
+ cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));
+ if (cull_data.shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
+ scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
+ }
- } else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
- if (cull_data.render_reflection_probe != idata.instance) {
- //avoid entering The Matrix
+ } else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
+ if (cull_data.render_reflection_probe != idata.instance) {
+ //avoid entering The Matrix
- if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {
- InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
- cull_data.cull->lock.lock();
- if (!reflection_probe->update_list.in_list()) {
- reflection_probe->render_step = 0;
- reflection_probe_render_list.add_last(&reflection_probe->update_list);
+ if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
+ cull_data.cull->lock.lock();
+ if (!reflection_probe->update_list.in_list()) {
+ reflection_probe->render_step = 0;
+ reflection_probe_render_list.add_last(&reflection_probe->update_list);
+ }
+ cull_data.cull->lock.unlock();
+
+ idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
}
- cull_data.cull->lock.unlock();
- idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
+ if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {
+ cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid));
+ }
}
-
- if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {
- cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid));
+ } else if (base_type == RS::INSTANCE_DECAL) {
+ cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid));
+
+ } else if (base_type == RS::INSTANCE_VOXEL_GI) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(idata.instance->base_data);
+ cull_data.cull->lock.lock();
+ if (!voxel_gi->update_element.in_list()) {
+ voxel_gi_update_list.add(&voxel_gi->update_element);
}
- }
- } else if (base_type == RS::INSTANCE_DECAL) {
- cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid));
-
- } else if (base_type == RS::INSTANCE_GI_PROBE) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(idata.instance->base_data);
- cull_data.cull->lock.lock();
- if (!gi_probe->update_element.in_list()) {
- gi_probe_update_list.add(&gi_probe->update_element);
- }
- cull_data.cull->lock.unlock();
- cull_result.gi_probes.push_back(RID::from_uint64(idata.instance_data_rid));
+ cull_data.cull->lock.unlock();
+ cull_result.voxel_gi_instances.push_back(RID::from_uint64(idata.instance_data_rid));
- } else if (base_type == RS::INSTANCE_LIGHTMAP) {
- cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));
- } else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
- bool keep = true;
-
- if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) {
- RenderingServerDefault::redraw_request();
- }
+ } else if (base_type == RS::INSTANCE_LIGHTMAP) {
+ cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));
+ } else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
+ bool keep = true;
- if (base_type == RS::INSTANCE_MESH) {
- mesh_visible = true;
- } else if (base_type == RS::INSTANCE_PARTICLES) {
- //particles visible? process them
- if (RSG::storage->particles_is_inactive(idata.base_rid)) {
- //but if nothing is going on, don't do it.
- keep = false;
- } else {
- cull_data.cull->lock.lock();
- RSG::storage->particles_request_process(idata.base_rid);
- cull_data.cull->lock.unlock();
- RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
- //particles visible? request redraw
+ if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) {
RenderingServerDefault::redraw_request();
}
- }
-
- if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
- InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
- instance_pair_buffer[idx++] = light->instance;
- if (idx == MAX_INSTANCE_PAIRS) {
- break;
+ if (base_type == RS::INSTANCE_MESH) {
+ mesh_visible = true;
+ } else if (base_type == RS::INSTANCE_PARTICLES) {
+ //particles visible? process them
+ if (RSG::storage->particles_is_inactive(idata.base_rid)) {
+ //but if nothing is going on, don't do it.
+ keep = false;
+ } else {
+ cull_data.cull->lock.lock();
+ RSG::storage->particles_request_process(idata.base_rid);
+ cull_data.cull->lock.unlock();
+ RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
+ //particles visible? request redraw
+ RenderingServerDefault::redraw_request();
}
}
- scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
- }
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
- if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- uint32_t idx = 0;
+ for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
+ InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
+ instance_pair_buffer[idx++] = light->instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
+ }
+
+ scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
+ }
- for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
- InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
- instance_pair_buffer[idx++] = reflection_probe->instance;
- if (idx == MAX_INSTANCE_PAIRS) {
- break;
+ for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
+
+ instance_pair_buffer[idx++] = reflection_probe->instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
}
- }
- scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
- }
+ scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
+ }
- if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- uint32_t idx = 0;
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) {
- InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->get()->base_data);
+ for (Set<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->get()->base_data);
- instance_pair_buffer[idx++] = decal->instance;
- if (idx == MAX_INSTANCE_PAIRS) {
- break;
+ instance_pair_buffer[idx++] = decal->instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
}
+ scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
}
- scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx);
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
- }
- if (idata.flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
+ if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
+ for (Set<Instance *>::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->get()->base_data);
- instance_pair_buffer[idx++] = gi_probe->probe_instance;
- if (idx == MAX_INSTANCE_PAIRS) {
- break;
+ instance_pair_buffer[idx++] = voxel_gi->probe_instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
}
- }
- scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
- }
+ scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
+ }
- if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- Color *sh = idata.instance->lightmap_sh.ptrw();
- const Color *target_sh = idata.instance->lightmap_target_sh.ptr();
- for (uint32_t j = 0; j < 9; j++) {
- sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
+ if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ Color *sh = idata.instance->lightmap_sh.ptrw();
+ const Color *target_sh = idata.instance->lightmap_target_sh.ptr();
+ for (uint32_t j = 0; j < 9; j++) {
+ sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
+ }
+ scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
+ idata.instance->last_frame_pass = frame_number;
}
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
- idata.instance->last_frame_pass = frame_number;
- }
- if (keep) {
- cull_result.geometry_instances.push_back(idata.instance_geometry);
+ if (keep) {
+ cull_result.geometry_instances.push_back(idata.instance_geometry);
+ }
}
}
- }
- for (uint32_t j = 0; j < cull_data.cull->shadow_count; j++) {
- for (uint32_t k = 0; k < cull_data.cull->shadows[j].cascade_count; k++) {
- if (cull_data.scenario->instance_aabbs[i].in_frustum(cull_data.cull->shadows[j].cascades[k].frustum)) {
- InstanceData &idata = cull_data.scenario->instance_data[i];
- uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
+ for (uint32_t j = 0; j < cull_data.cull->shadow_count; j++) {
+ for (uint32_t k = 0; k < cull_data.cull->shadows[j].cascade_count; k++) {
+ if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {
+ uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
- if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) {
- cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
- mesh_visible = true;
+ if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) {
+ cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
+ mesh_visible = true;
+ }
}
}
}
}
+#undef HIDDEN_BY_VISIBILITY_CHECKS
+#undef LAYER_CHECK
+#undef IN_FRUSTUM
+#undef VIS_RANGE_CHECK
+#undef VIS_PARENT_CHECK
+#undef VIS_CHECK
+#undef OCCLUSION_CULLED
+
for (uint32_t j = 0; j < cull_data.cull->sdfgi.region_count; j++) {
if (cull_data.scenario->instance_aabbs[i].in_aabb(cull_data.cull->sdfgi.region_aabb[j])) {
- InstanceData &idata = cull_data.scenario->instance_data[i];
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
if (base_type == RS::INSTANCE_LIGHT) {
@@ -2544,11 +2769,7 @@ void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cu
}
}
-void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows) {
- // Note, in stereo rendering:
- // - p_cam_transform will be a transform in the middle of our two eyes
- // - p_cam_projection is a wider frustrum that encompasses both eyes
-
+void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows) {
Instance *render_reflection_probe = instance_owner.getornull(p_reflection_probe); //if null, not rendering to it
Scenario *scenario = scenario_owner.getornull(p_scenario);
@@ -2559,16 +2780,44 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
if (p_render_buffers.is_valid()) {
//no rendering code here, this is only to set up what needs to be done, request regions, etc.
- scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not)
+ scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not)
+ }
+
+ RENDER_TIMESTAMP("Visibility Dependencies");
+
+ VisibilityCullData visibility_cull_data;
+ if (scenario->instance_visibility.get_bin_count() > 0) {
+ if (!scenario->viewport_visibility_masks.has(p_viewport)) {
+ scenario_add_viewport_visibility_mask(scenario->self, p_viewport);
+ }
+
+ visibility_cull_data.scenario = scenario;
+ visibility_cull_data.viewport_mask = scenario->viewport_visibility_masks[p_viewport];
+ visibility_cull_data.camera_position = p_camera_data->main_transform.origin;
+
+ for (int i = scenario->instance_visibility.get_bin_count() - 1; i > 0; i--) { // We skip bin 0
+ visibility_cull_data.cull_offset = scenario->instance_visibility.get_bin_start(i);
+ visibility_cull_data.cull_count = scenario->instance_visibility.get_bin_size(i);
+
+ if (visibility_cull_data.cull_count == 0) {
+ continue;
+ }
+
+ if (visibility_cull_data.cull_count > thread_cull_threshold) {
+ RendererThreadPool::singleton->thread_work_pool.do_work(RendererThreadPool::singleton->thread_work_pool.get_thread_count(), this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data);
+ } else {
+ _visibility_cull(visibility_cull_data, visibility_cull_data.cull_offset, visibility_cull_data.cull_offset + visibility_cull_data.cull_count);
+ }
+ }
}
- RENDER_TIMESTAMP("Frustum Culling");
+ RENDER_TIMESTAMP("Culling");
- //rasterizer->set_camera(camera->transform, camera_matrix,ortho);
+ //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_ortogonal);
- Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
+ Vector<Plane> planes = p_camera_data->main_projection.get_projection_planes(p_camera_data->main_transform);
- Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized());
+ Plane near_plane(p_camera_data->main_transform.origin, -p_camera_data->main_transform.basis.get_axis(2).normalized());
/* STEP 2 - CULL */
@@ -2606,7 +2855,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
scene_render->set_directional_shadow_count(lights_with_shadow.size());
for (int i = 0; i < lights_with_shadow.size(); i++) {
- _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect);
+ _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect);
}
}
@@ -2635,7 +2884,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
}
}
- frustum_cull_result.clear();
+ scene_cull_result.clear();
{
uint64_t cull_from = 0;
@@ -2647,30 +2896,30 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
cull_data.cull = &cull;
cull_data.scenario = scenario;
cull_data.shadow_atlas = p_shadow_atlas;
- cull_data.cam_transform = p_cam_transform;
+ cull_data.cam_transform = p_camera_data->main_transform;
cull_data.visible_layers = p_visible_layers;
cull_data.render_reflection_probe = render_reflection_probe;
cull_data.occlusion_buffer = RendererSceneOcclusionCull::get_singleton()->buffer_get_ptr(p_viewport);
- cull_data.camera_matrix = &p_cam_projection;
+ cull_data.camera_matrix = &p_camera_data->main_projection;
//#define DEBUG_CULL_TIME
#ifdef DEBUG_CULL_TIME
uint64_t time_from = OS::get_singleton()->get_ticks_usec();
#endif
if (cull_to > thread_cull_threshold) {
//multiple threads
- for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
- frustum_cull_result_threads[i].clear();
+ for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
+ scene_cull_result_threads[i].clear();
}
- RendererThreadPool::singleton->thread_work_pool.do_work(frustum_cull_result_threads.size(), this, &RendererSceneCull::_frustum_cull_threaded, &cull_data);
+ RendererThreadPool::singleton->thread_work_pool.do_work(scene_cull_result_threads.size(), this, &RendererSceneCull::_scene_cull_threaded, &cull_data);
- for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
- frustum_cull_result.append_from(frustum_cull_result_threads[i]);
+ for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
+ scene_cull_result.append_from(scene_cull_result_threads[i]);
}
} else {
//single threaded
- _frustum_cull(cull_data, frustum_cull_result, cull_from, cull_to);
+ _scene_cull(cull_data, scene_cull_result, cull_from, cull_to);
}
#ifdef DEBUG_CULL_TIME
@@ -2681,9 +2930,9 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
print_line("time taken: " + rtos(time_avg / time_count));
#endif
- if (frustum_cull_result.mesh_instances.size()) {
- for (uint64_t i = 0; i < frustum_cull_result.mesh_instances.size(); i++) {
- RSG::storage->mesh_instance_check_for_update(frustum_cull_result.mesh_instances[i]);
+ if (scene_cull_result.mesh_instances.size()) {
+ for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) {
+ RSG::storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);
}
RSG::storage->update_mesh_instances();
}
@@ -2707,14 +2956,14 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
}
render_shadow_data[max_shadows_used].light = cull.shadows[i].light_instance;
render_shadow_data[max_shadows_used].pass = j;
- render_shadow_data[max_shadows_used].instances.merge_unordered(frustum_cull_result.directional_shadows[i].cascade_geometry_instances[j]);
+ render_shadow_data[max_shadows_used].instances.merge_unordered(scene_cull_result.directional_shadows[i].cascade_geometry_instances[j]);
max_shadows_used++;
}
}
// Positional Shadowss
- for (uint32_t i = 0; i < (uint32_t)frustum_cull_result.lights.size(); i++) {
- Instance *ins = frustum_cull_result.lights[i];
+ for (uint32_t i = 0; i < (uint32_t)scene_cull_result.lights.size(); i++) {
+ Instance *ins = scene_cull_result.lights[i];
if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
continue;
@@ -2726,12 +2975,12 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
{ //compute coverage
- Transform cam_xf = p_cam_transform;
- float zn = p_cam_projection.get_z_near();
+ Transform3D cam_xf = p_camera_data->main_transform;
+ float zn = p_camera_data->main_projection.get_z_near();
Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane
// near plane half width and height
- Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents();
+ Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
switch (RSG::storage->light_get_type(ins->base)) {
case RS::LIGHT_OMNI: {
@@ -2743,7 +2992,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
ins->transform.origin + cam_xf.basis.get_axis(0) * radius
};
- if (!p_cam_orthogonal) {
+ if (!p_camera_data->is_ortogonal) {
//if using perspetive, map them to near plane
for (int j = 0; j < 2; j++) {
if (p.distance_to(points[j]) < 0) {
@@ -2771,7 +3020,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
base + cam_xf.basis.get_axis(0) * w
};
- if (!p_cam_orthogonal) {
+ if (!p_camera_data->is_ortogonal) {
//if using perspetive, map them to near plane
for (int j = 0; j < 2; j++) {
if (p.distance_to(points[j]) < 0) {
@@ -2802,7 +3051,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {
//must redraw!
RENDER_TIMESTAMP(">Rendering Light " + itos(i));
- light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
RENDER_TIMESTAMP("<Rendering Light " + itos(i));
} else {
light->shadow_dirty = redraw;
@@ -2818,13 +3067,13 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
if (cull.sdfgi.region_count > 0) {
//update regions
for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
- render_sdfgi_data[i].instances.merge_unordered(frustum_cull_result.sdfgi_region_geometry_instances[i]);
+ render_sdfgi_data[i].instances.merge_unordered(scene_cull_result.sdfgi_region_geometry_instances[i]);
render_sdfgi_data[i].region = i;
}
//check if static lights were culled
bool static_lights_culled = false;
for (uint32_t i = 0; i < cull.sdfgi.cascade_light_count; i++) {
- if (frustum_cull_result.sdfgi_cascade_lights[i].size()) {
+ if (scene_cull_result.sdfgi_cascade_lights[i].size()) {
static_lights_culled = true;
break;
}
@@ -2833,7 +3082,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
if (static_lights_culled) {
sdfgi_update_data.static_cascade_count = cull.sdfgi.cascade_light_count;
sdfgi_update_data.static_cascade_indices = cull.sdfgi.cascade_light_index;
- sdfgi_update_data.static_positional_lights = frustum_cull_result.sdfgi_cascade_lights;
+ sdfgi_update_data.static_positional_lights = scene_cull_result.sdfgi_cascade_lights;
sdfgi_update_data.update_static = true;
}
}
@@ -2847,7 +3096,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
//append the directional lights to the lights culled
for (int i = 0; i < directional_lights.size(); i++) {
- frustum_cull_result.light_instances.push_back(directional_lights[i]);
+ scene_cull_result.light_instances.push_back(directional_lights[i]);
}
RID camera_effects;
@@ -2864,7 +3113,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
}
RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, frustum_cull_result.geometry_instances, frustum_cull_result.light_instances, frustum_cull_result.reflections, frustum_cull_result.gi_probes, frustum_cull_result.decals, frustum_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data);
+ scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data);
for (uint32_t i = 0; i < max_shadows_used; i++) {
render_shadow_data[i].instances.clear();
@@ -2875,7 +3124,7 @@ void RendererSceneCull::_render_scene(const Transform &p_cam_transform, const Ca
render_sdfgi_data[i].instances.clear();
}
- // virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
+ // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@@ -2911,7 +3160,11 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
environment = scenario->fallback_environment;
}
RENDER_TIMESTAMP("Render Empty Scene ");
- scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+
+ RendererSceneRender::CameraData camera_data;
+ camera_data.set_camera(Transform3D(), CameraMatrix(), true, false);
+
+ scene_render->render_scene(p_render_buffers, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -2961,10 +3214,10 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
CameraMatrix cm;
cm.set_perspective(90, 1, 0.01, max_distance);
- Transform local_view;
+ Transform3D local_view;
local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]);
- Transform xform = p_instance->transform * local_view;
+ Transform3D xform = p_instance->transform * local_view;
RID shadow_atlas;
@@ -2981,7 +3234,10 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
}
RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
- _render_scene(xform, cm, false, false, RID(), environment, RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, lod_threshold, use_shadows);
+ RendererSceneRender::CameraData camera_data;
+ camera_data.set_camera(xform, cm, false, false);
+
+ _render_scene(&camera_data, RID(), environment, RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, lod_threshold, use_shadows);
} else {
//do roughness postprocess step until it believes it's done
@@ -3033,18 +3289,18 @@ void RendererSceneCull::render_probes() {
ref_probe = next;
}
- /* GI PROBES */
+ /* VOXEL GIS */
- SelfList<InstanceGIProbeData> *gi_probe = gi_probe_update_list.first();
+ SelfList<InstanceVoxelGIData> *voxel_gi = voxel_gi_update_list.first();
- if (gi_probe) {
+ if (voxel_gi) {
RENDER_TIMESTAMP("Render GI Probes");
}
- while (gi_probe) {
- SelfList<InstanceGIProbeData> *next = gi_probe->next();
+ while (voxel_gi) {
+ SelfList<InstanceVoxelGIData> *next = voxel_gi->next();
- InstanceGIProbeData *probe = gi_probe->self();
+ InstanceVoxelGIData *probe = voxel_gi->self();
//Instance *instance_probe = probe->owner;
//check if probe must be setup, but don't do if on the lighting thread
@@ -3053,7 +3309,7 @@ void RendererSceneCull::render_probes() {
int cache_count = 0;
{
int light_cache_size = probe->light_cache.size();
- const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr();
+ const InstanceVoxelGIData::LightCache *caches = probe->light_cache.ptr();
const RID *instance_caches = probe->light_instances.ptr();
int idx = 0; //must count visible lights
@@ -3068,7 +3324,7 @@ void RendererSceneCull::render_probes() {
} else if (idx >= light_cache_size) {
cache_dirty = true;
} else {
- const InstanceGIProbeData::LightCache *cache = &caches[idx];
+ const InstanceVoxelGIData::LightCache *cache = &caches[idx];
if (
instance_caches[idx] != instance_light->instance ||
@@ -3100,7 +3356,7 @@ void RendererSceneCull::render_probes() {
} else if (idx >= light_cache_size) {
cache_dirty = true;
} else {
- const InstanceGIProbeData::LightCache *cache = &caches[idx];
+ const InstanceVoxelGIData::LightCache *cache = &caches[idx];
if (
instance_caches[idx] != instance_light->instance ||
@@ -3129,14 +3385,14 @@ void RendererSceneCull::render_probes() {
cache_count = idx;
}
- bool update_lights = scene_render->gi_probe_needs_update(probe->probe_instance);
+ bool update_lights = scene_render->voxel_gi_needs_update(probe->probe_instance);
if (cache_dirty) {
probe->light_cache.resize(cache_count);
probe->light_instances.resize(cache_count);
if (cache_count) {
- InstanceGIProbeData::LightCache *caches = probe->light_cache.ptrw();
+ InstanceVoxelGIData::LightCache *caches = probe->light_cache.ptrw();
RID *instance_caches = probe->light_instances.ptrw();
int idx = 0; //must count visible lights
@@ -3147,7 +3403,7 @@ void RendererSceneCull::render_probes() {
continue;
}
- InstanceGIProbeData::LightCache *cache = &caches[idx];
+ InstanceVoxelGIData::LightCache *cache = &caches[idx];
instance_caches[idx] = instance_light->instance;
cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
@@ -3170,7 +3426,7 @@ void RendererSceneCull::render_probes() {
continue;
}
- InstanceGIProbeData::LightCache *cache = &caches[idx];
+ InstanceVoxelGIData::LightCache *cache = &caches[idx];
instance_caches[idx] = instance_light->instance;
cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
@@ -3192,7 +3448,7 @@ void RendererSceneCull::render_probes() {
update_lights = true;
}
- frustum_cull_result.geometry_instances.clear();
+ scene_cull_result.geometry_instances.clear();
RID instance_pair_buffer[MAX_INSTANCE_PAIRS];
@@ -3203,30 +3459,30 @@ void RendererSceneCull::render_probes() {
}
InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;
- if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY)) {
+ if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY)) {
uint32_t idx = 0;
- for (Set<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
- InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
+ for (Set<Instance *>::Element *F = geom->voxel_gi_instances.front(); F; F = F->next()) {
+ InstanceVoxelGIData *voxel_gi2 = static_cast<InstanceVoxelGIData *>(F->get()->base_data);
- instance_pair_buffer[idx++] = gi_probe2->probe_instance;
+ instance_pair_buffer[idx++] = voxel_gi2->probe_instance;
if (idx == MAX_INSTANCE_PAIRS) {
break;
}
}
- scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
- ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
+ ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
- frustum_cull_result.geometry_instances.push_back(geom->geometry_instance);
+ scene_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
- scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, frustum_cull_result.geometry_instances);
+ scene_render->voxel_gi_update(probe->probe_instance, update_lights, probe->light_instances, scene_cull_result.geometry_instances);
- gi_probe_update_list.remove(gi_probe);
+ voxel_gi_update_list.remove(voxel_gi);
- gi_probe = next;
+ voxel_gi = next;
}
}
@@ -3237,7 +3493,7 @@ void RendererSceneCull::render_particle_colliders() {
if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
//update heightfield
instance_cull_result.clear();
- frustum_cull_result.geometry_instances.clear();
+ scene_cull_result.geometry_instances.clear();
struct CullAABB {
PagedArray<Instance *> *result;
@@ -3259,10 +3515,10 @@ void RendererSceneCull::render_particle_colliders() {
continue;
}
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- frustum_cull_result.geometry_instances.push_back(geom->geometry_instance);
+ scene_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
- scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, frustum_cull_result.geometry_instances);
+ scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, scene_cull_result.geometry_instances);
}
heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front());
}
@@ -3551,6 +3807,7 @@ bool RendererSceneCull::free(RID p_rid) {
}
scenario->instance_aabbs.reset();
scenario->instance_data.reset();
+ scenario->instance_visibility.reset();
scene_render->free(scenario->reflection_probe_shadow_atlas);
scene_render->free(scenario->reflection_atlas);
@@ -3619,10 +3876,10 @@ RendererSceneCull::RendererSceneCull() {
render_sdfgi_data[i].instances.set_page_pool(&geometry_instance_cull_page_pool);
}
- frustum_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
- frustum_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
- for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
- frustum_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
+ scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
+ scene_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
+ scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
}
indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");
@@ -3643,11 +3900,11 @@ RendererSceneCull::~RendererSceneCull() {
render_sdfgi_data[i].instances.reset();
}
- frustum_cull_result.reset();
- for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
- frustum_cull_result_threads[i].reset();
+ scene_cull_result.reset();
+ for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
+ scene_cull_result_threads[i].reset();
}
- frustum_cull_result_threads.clear();
+ scene_cull_result_threads.clear();
if (dummy_occlusion_culling) {
memdelete(dummy_occlusion_culling);
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index a61b04afc8..bdfbea95a2 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -31,6 +31,7 @@
#ifndef RENDERING_SERVER_SCENE_CULL_H
#define RENDERING_SERVER_SCENE_CULL_H
+#include "core/templates/bin_sorted_array.h"
#include "core/templates/pass_func.h"
#include "servers/rendering/renderer_compositor.h"
@@ -82,7 +83,7 @@ public:
RID env;
RID effects;
- Transform transform;
+ Transform3D transform;
Camera() {
visible_layers = 0xFFFFFFFF;
@@ -104,7 +105,7 @@ public:
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
- virtual void camera_set_transform(RID p_camera, const Transform &p_transform);
+ virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform);
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers);
virtual void camera_set_environment(RID p_camera, RID p_env);
virtual void camera_set_camera_effects(RID p_camera, RID p_fx);
@@ -253,12 +254,15 @@ public:
FLAG_GEOM_LIGHTING_DIRTY = (1 << 11),
FLAG_GEOM_REFLECTION_DIRTY = (1 << 12),
FLAG_GEOM_DECAL_DIRTY = (1 << 13),
- FLAG_GEOM_GI_PROBE_DIRTY = (1 << 14),
+ FLAG_GEOM_VOXEL_GI_DIRTY = (1 << 14),
FLAG_LIGHTMAP_CAPTURE = (1 << 15),
FLAG_USES_BAKED_LIGHT = (1 << 16),
FLAG_USES_MESH_INSTANCE = (1 << 17),
FLAG_REFLECTION_PROBE_DIRTY = (1 << 18),
FLAG_IGNORE_OCCLUSION_CULLING = (1 << 19),
+ FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK = (3 << 20), // 2 bits, overlaps with the other vis. dependency flags
+ FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE = (1 << 20),
+ FLAG_VISIBILITY_DEPENDENCY_HIDDEN = (1 << 21),
};
uint32_t flags = 0;
@@ -269,10 +273,33 @@ public:
RendererSceneRender::GeometryInstance *instance_geometry;
};
Instance *instance = nullptr;
+ int32_t parent_array_index = -1;
+ int32_t visibility_index = -1;
+ };
+
+ struct InstanceVisibilityData {
+ uint64_t viewport_state = 0;
+ int32_t array_index = -1;
+ Vector3 position;
+ Instance *instance = nullptr;
+ float range_begin = 0.0f;
+ float range_end = 0.0f;
+ float range_begin_margin = 0.0f;
+ float range_end_margin = 0.0f;
+ };
+
+ class VisibilityArray : public BinSortedArray<InstanceVisibilityData> {
+ _FORCE_INLINE_ virtual void _update_idx(InstanceVisibilityData &r_element, uint64_t p_idx) {
+ r_element.instance->visibility_index = p_idx;
+ if (r_element.instance->scenario && r_element.instance->array_index != -1) {
+ r_element.instance->scenario->instance_data[r_element.instance->array_index].visibility_index = p_idx;
+ }
+ }
};
PagedArrayPool<InstanceBounds> instance_aabb_page_pool;
PagedArrayPool<InstanceData> instance_data_page_pool;
+ PagedArrayPool<InstanceVisibilityData> instance_visibility_data_page_pool;
struct Scenario {
enum IndexerType {
@@ -292,6 +319,8 @@ public:
RID camera_effects;
RID reflection_probe_shadow_atlas;
RID reflection_atlas;
+ uint64_t used_viewport_visibility_bits;
+ Map<RID, uint64_t> viewport_visibility_masks;
SelfList<Instance>::List instances;
@@ -299,11 +328,13 @@ public:
PagedArray<InstanceBounds> instance_aabbs;
PagedArray<InstanceData> instance_data;
+ VisibilityArray instance_visibility;
Scenario() {
indexers[INDEXER_GEOMETRY].set_index(INDEXER_GEOMETRY);
indexers[INDEXER_VOLUMES].set_index(INDEXER_VOLUMES);
debug = RS::SCENARIO_DEBUG_DISABLED;
+ used_viewport_visibility_bits = 0;
}
};
@@ -326,6 +357,8 @@ public:
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count);
virtual bool is_scenario(RID p_scenario) const;
virtual RID scenario_get_environment(RID p_scenario);
+ virtual void scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport);
+ virtual void scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport);
/* INSTANCING API */
@@ -353,7 +386,7 @@ public:
RID mesh_instance; //only used for meshes and when skeleton/blendshapes exist
- Transform transform;
+ Transform3D transform;
float lod_bias;
@@ -399,6 +432,12 @@ public:
//scenario stuff
DynamicBVH::ID indexer_id;
int32_t array_index;
+ int32_t visibility_index = -1;
+ float visibility_range_begin;
+ float visibility_range_end;
+ float visibility_range_begin_margin;
+ float visibility_range_end_margin;
+ Instance *visibility_parent = nullptr;
Scenario *scenario;
SelfList<Instance> scenario_item;
@@ -412,12 +451,6 @@ public:
float extra_margin;
ObjectID object_id;
- float lod_begin;
- float lod_end;
- float lod_begin_hysteresis;
- float lod_end_hysteresis;
- RID lod_instance;
-
Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior
uint64_t last_frame_pass;
@@ -495,10 +528,10 @@ public:
visible = true;
- lod_begin = 0;
- lod_end = 0;
- lod_begin_hysteresis = 0;
- lod_end_hysteresis = 0;
+ visibility_range_begin = 0;
+ visibility_range_end = 0;
+ visibility_range_begin_margin = 0;
+ visibility_range_end_margin = 0;
last_frame_pass = 0;
version = 1;
@@ -535,8 +568,10 @@ public:
Set<Instance *> decals;
Set<Instance *> reflection_probes;
- Set<Instance *> gi_probes;
+ Set<Instance *> voxel_gi_instances;
Set<Instance *> lightmap_captures;
+ Set<Instance *> visibility_dependencies;
+ uint32_t visibility_dependencies_depth = 0;
InstanceGeometryData() {
can_cast_shadows = true;
@@ -599,7 +634,7 @@ public:
}
};
- struct InstanceGIProbeData : public InstanceBaseData {
+ struct InstanceVoxelGIData : public InstanceBaseData {
Instance *owner;
Set<Instance *> geometries;
@@ -609,7 +644,7 @@ public:
struct LightCache {
RS::LightType type;
- Transform transform;
+ Transform3D transform;
Color color;
float energy;
float bake_energy;
@@ -629,16 +664,16 @@ public:
bool invalid;
uint32_t base_version;
- SelfList<InstanceGIProbeData> update_element;
+ SelfList<InstanceVoxelGIData> update_element;
- InstanceGIProbeData() :
+ InstanceVoxelGIData() :
update_element(this) {
invalid = true;
base_version = 0;
}
};
- SelfList<InstanceGIProbeData>::List gi_probe_update_list;
+ SelfList<InstanceVoxelGIData>::List voxel_gi_update_list;
struct InstanceLightmapData : public InstanceBaseData {
RID instance;
@@ -717,14 +752,14 @@ public:
PagedArray<Instance *> instance_cull_result;
PagedArray<Instance *> instance_shadow_cull_result;
- struct FrustumCullResult {
+ struct InstanceCullResult {
PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances;
PagedArray<Instance *> lights;
PagedArray<RID> light_instances;
PagedArray<RID> lightmaps;
PagedArray<RID> reflections;
PagedArray<RID> decals;
- PagedArray<RID> gi_probes;
+ PagedArray<RID> voxel_gi_instances;
PagedArray<RID> mesh_instances;
struct DirectionalShadow {
@@ -741,7 +776,7 @@ public:
lightmaps.clear();
reflections.clear();
decals.clear();
- gi_probes.clear();
+ voxel_gi_instances.clear();
mesh_instances.clear();
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
@@ -765,7 +800,7 @@ public:
lightmaps.reset();
reflections.reset();
decals.reset();
- gi_probes.reset();
+ voxel_gi_instances.reset();
mesh_instances.reset();
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
@@ -782,14 +817,14 @@ public:
}
}
- void append_from(FrustumCullResult &p_cull_result) {
+ void append_from(InstanceCullResult &p_cull_result) {
geometry_instances.merge_unordered(p_cull_result.geometry_instances);
lights.merge_unordered(p_cull_result.lights);
light_instances.merge_unordered(p_cull_result.light_instances);
lightmaps.merge_unordered(p_cull_result.lightmaps);
reflections.merge_unordered(p_cull_result.reflections);
decals.merge_unordered(p_cull_result.decals);
- gi_probes.merge_unordered(p_cull_result.gi_probes);
+ voxel_gi_instances.merge_unordered(p_cull_result.voxel_gi_instances);
mesh_instances.merge_unordered(p_cull_result.mesh_instances);
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
@@ -814,7 +849,7 @@ public:
lightmaps.set_page_pool(p_rid_pool);
reflections.set_page_pool(p_rid_pool);
decals.set_page_pool(p_rid_pool);
- gi_probes.set_page_pool(p_rid_pool);
+ voxel_gi_instances.set_page_pool(p_rid_pool);
mesh_instances.set_page_pool(p_rid_pool);
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
@@ -832,8 +867,8 @@ public:
}
};
- FrustumCullResult frustum_cull_result;
- LocalVector<FrustumCullResult> frustum_cull_result_threads;
+ InstanceCullResult scene_cull_result;
+ LocalVector<InstanceCullResult> scene_cull_result_threads;
RendererSceneRender::RenderShadowData render_shadow_data[MAX_UPDATE_SHADOWS];
uint32_t max_shadows_used = 0;
@@ -845,7 +880,7 @@ public:
RID_PtrOwner<Instance, true> instance_owner;
- uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecesary on clustered
+ uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecessary on clustered
virtual RID instance_allocate();
virtual void instance_initialize(RID p_rid);
@@ -853,7 +888,7 @@ public:
virtual void instance_set_base(RID p_instance, RID p_base);
virtual void instance_set_scenario(RID p_instance, RID p_scenario);
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask);
- virtual void instance_set_transform(RID p_instance, const Transform &p_transform);
+ virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform);
virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id);
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material);
@@ -866,6 +901,11 @@ public:
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin);
+ virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance);
+
+ void _update_instance_visibility_depth(Instance *p_instance);
+ void _update_instance_visibility_dependencies(Instance *p_instance);
+
// don't use these in a game!
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const;
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
@@ -875,8 +915,8 @@ public:
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting);
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
- virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
- virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
+
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
@@ -893,9 +933,9 @@ public:
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
void _unpair_instance(Instance *p_instance);
- void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
+ void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
- _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold);
RID _render_get_environment(RID p_camera, RID p_scenario);
@@ -906,7 +946,7 @@ public:
Frustum frustum;
CameraMatrix projection;
- Transform transform;
+ Transform3D transform;
real_t zfar;
real_t split;
real_t shadow_texel_size;
@@ -937,26 +977,39 @@ public:
Frustum frustum;
} cull;
+ struct VisibilityCullData {
+ uint64_t viewport_mask;
+ Scenario *scenario;
+ Vector3 camera_position;
+ uint32_t cull_offset;
+ uint32_t cull_count;
+ };
+
+ void _visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data);
+ void _visibility_cull(const VisibilityCullData &cull_data, uint64_t p_from, uint64_t p_to);
+ _FORCE_INLINE_ void _visibility_cull(const VisibilityCullData &cull_data, uint64_t p_idx);
+ _FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask);
+
struct CullData {
Cull *cull;
Scenario *scenario;
RID shadow_atlas;
- Transform cam_transform;
+ Transform3D cam_transform;
uint32_t visible_layers;
Instance *render_reflection_probe;
const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer;
const CameraMatrix *camera_matrix;
+ const VisibilityCullData *visibility_cull_data;
};
- void _frustum_cull_threaded(uint32_t p_thread, CullData *cull_data);
- void _frustum_cull(CullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to);
+ void _scene_cull_threaded(uint32_t p_thread, CullData *cull_data);
+ void _scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
- void _render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true);
+ void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
- void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas);
- void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas);
+ void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface);
void update_dirty_instances();
void render_particle_colliders();
@@ -975,7 +1028,7 @@ public:
#define PASSBASE scene_render
PASS2(directional_shadow_atlas_set_size, int, bool)
- PASS1(gi_probe_set_quality, RS::GIProbeQuality)
+ PASS1(voxel_gi_set_quality, RS::VoxelGIQuality)
/* SKY API */
@@ -1054,7 +1107,7 @@ public:
/* Render Buffers */
PASS0R(RID, render_buffers_create)
- PASS7(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool)
+ PASS8(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
PASS1(gi_set_use_half_resolution, bool)
/* Shadow Atlas */
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 390bbaa64b..1d0f53c0bf 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -60,7 +60,7 @@ public:
void update_mips();
- _FORCE_INLINE_ bool is_occluded(const float p_bounds[6], const Vector3 &p_cam_position, const Transform &p_cam_inv_transform, const CameraMatrix &p_cam_projection, float p_near) const {
+ _FORCE_INLINE_ bool is_occluded(const float p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, float p_near) const {
if (is_empty()) {
return false;
}
@@ -171,7 +171,7 @@ public:
virtual void add_scenario(RID p_scenario) {}
virtual void remove_scenario(RID p_scenario) {}
- virtual void scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform &p_xform, bool p_enabled) { _print_warining(); }
+ virtual void scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform3D &p_xform, bool p_enabled) { _print_warining(); }
virtual void scenario_remove_instance(RID p_scenario, RID p_instance) { _print_warining(); }
virtual void add_buffer(RID p_buffer) { _print_warining(); }
@@ -181,7 +181,7 @@ public:
}
virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) { _print_warining(); }
virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) { _print_warining(); }
- virtual void buffer_update(RID p_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {}
+ virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {}
virtual RID buffer_get_debug_texture(RID p_buffer) {
_print_warining();
return RID();
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index f27bdc6798..3aa97f4084 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -29,3 +29,153 @@
/*************************************************************************/
#include "renderer_scene_render.h"
+
+void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect) {
+ view_count = 1;
+ is_ortogonal = p_is_ortogonal;
+ vaspect = p_vaspect;
+
+ main_transform = p_transform;
+ main_projection = p_projection;
+
+ view_offset[0] = Transform3D();
+ view_projection[0] = p_projection;
+}
+
+void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect) {
+ ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view");
+
+ view_count = p_view_count;
+ is_ortogonal = p_is_ortogonal;
+ vaspect = p_vaspect;
+ Vector<Plane> planes[2];
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Figure out our center transform
+
+ // 1. obtain our planes
+ for (uint32_t v = 0; v < view_count; v++) {
+ planes[v] = p_projections[v].get_projection_planes(p_transforms[v]);
+ }
+
+ // 2. average and normalize plane normals to obtain z vector, cross them to obtain y vector, and from there the x vector for combined camera basis.
+ Vector3 n0 = planes[0][CameraMatrix::PLANE_LEFT].normal;
+ Vector3 n1 = planes[1][CameraMatrix::PLANE_RIGHT].normal;
+ Vector3 z = (n0 + n1).normalized();
+ Vector3 y = n0.cross(n1).normalized();
+ Vector3 x = y.cross(z).normalized();
+ y = z.cross(x).normalized();
+ main_transform.basis.set(x, y, z);
+
+ // 3. create a horizon plane with one of the eyes and the up vector as normal.
+ Plane horizon(p_transforms[0].origin, y);
+
+ // 4. Intersect horizon, left and right to obtain the combined camera origin.
+ ERR_FAIL_COND_MSG(
+ !horizon.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin");
+
+ // handy to have the inverse of the transform we just build
+ Transform3D main_transform_inv = main_transform.inverse();
+
+ // 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
+ Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5;
+ Plane far(far_center, -z);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Figure out our top/bottom planes
+
+ // 6. Intersect far and left planes with top planes from both eyes, save the point with highest y as top_left.
+ Vector3 top_left, other;
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector");
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/left/top vector");
+ if (y.dot(top_left) < y.dot(other)) {
+ top_left = other;
+ }
+
+ // 7. Intersect far and left planes with bottom planes from both eyes, save the point with lowest y as bottom_left.
+ Vector3 bottom_left;
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector");
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector");
+ if (y.dot(other) < y.dot(bottom_left)) {
+ bottom_left = other;
+ }
+
+ // 8. Intersect far and right planes with top planes from both eyes, save the point with highest y as top_right.
+ Vector3 top_right;
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector");
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/right/top vector");
+ if (y.dot(top_right) < y.dot(other)) {
+ top_right = other;
+ }
+
+ // 9. Intersect far and right planes with bottom planes from both eyes, save the point with lowest y as bottom_right.
+ Vector3 bottom_right;
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector");
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector");
+ if (y.dot(other) < y.dot(bottom_right)) {
+ bottom_right = other;
+ }
+
+ // 10. Create top plane with these points: camera origin, top_left, top_right
+ Plane top(main_transform.origin, top_left, top_right);
+
+ // 11. Create bottom plane with these points: camera origin, bottom_left, bottom_right
+ Plane bottom(main_transform.origin, bottom_left, bottom_right);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Figure out our near plane points
+
+ // 12. Create a near plane using -camera z and the eye further along in that axis.
+ Plane near;
+ Vector3 neg_z = -z;
+ if (neg_z.dot(p_transforms[1].origin) < neg_z.dot(p_transforms[0].origin)) {
+ near = Plane(p_transforms[0].origin, neg_z);
+ } else {
+ near = Plane(p_transforms[1].origin, neg_z);
+ }
+
+ // 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec
+ Vector3 min_vec;
+ ERR_FAIL_COND_MSG(
+ !near.intersect_3(bottom, planes[0][CameraMatrix::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector");
+ ERR_FAIL_COND_MSG(
+ !near.intersect_3(bottom, planes[1][CameraMatrix::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector");
+ if (x.dot(other) < x.dot(min_vec)) {
+ min_vec = other;
+ }
+
+ Vector3 max_vec;
+ ERR_FAIL_COND_MSG(
+ !near.intersect_3(top, planes[0][CameraMatrix::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector");
+ ERR_FAIL_COND_MSG(
+ !near.intersect_3(top, planes[1][CameraMatrix::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector");
+ if (x.dot(max_vec) < x.dot(other)) {
+ max_vec = other;
+ }
+
+ // 14. transform these points by the inverse camera to obtain local_min_vec and local_max_vec
+ Vector3 local_min_vec = main_transform_inv.xform(min_vec);
+ Vector3 local_max_vec = main_transform_inv.xform(max_vec);
+
+ // 15. get x and y from these to obtain left, top, right bottom for the frustum. Get the distance from near plane to camera origin to obtain near, and the distance from the far plane to the camer origin to obtain far.
+ float z_near = -near.distance_to(main_transform.origin);
+ float z_far = -far.distance_to(main_transform.origin);
+
+ // 16. Use this to build the combined camera matrix.
+ main_projection.set_frustum(local_min_vec.x, local_max_vec.x, local_min_vec.y, local_max_vec.y, z_near, z_far);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // 3. Copy our view data
+ for (uint32_t v = 0; v < view_count; v++) {
+ view_offset[v] = p_transforms[v] * main_transform_inv;
+ view_projection[v] = p_projections[v] * CameraMatrix(view_offset[v]);
+ }
+}
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 3f28fac549..3682122dd3 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -39,7 +39,8 @@ class RendererSceneRender {
public:
enum {
MAX_DIRECTIONAL_LIGHTS = 8,
- MAX_DIRECTIONAL_LIGHT_CASCADES = 4
+ MAX_DIRECTIONAL_LIGHT_CASCADES = 4,
+ MAX_RENDER_VIEWS = 2
};
struct GeometryInstance {
@@ -51,7 +52,7 @@ public:
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0;
virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0;
virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0;
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0;
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
@@ -65,7 +66,7 @@ public:
virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
- virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) = 0;
+ virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0;
@@ -161,9 +162,9 @@ public:
virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
virtual RID light_instance_create(RID p_light) = 0;
- virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
+ virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
virtual bool light_instances_can_render_shadow_cube() const {
return true;
@@ -174,7 +175,7 @@ public:
virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0;
virtual RID reflection_probe_instance_create(RID p_probe) = 0;
- virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
@@ -182,17 +183,17 @@ public:
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
virtual RID decal_instance_create(RID p_decal) = 0;
- virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform) = 0;
+ virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) = 0;
virtual RID lightmap_instance_create(RID p_lightmap) = 0;
- virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) = 0;
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) = 0;
- virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
- virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
- virtual bool gi_probe_needs_update(RID p_probe) const = 0;
- virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0;
+ virtual RID voxel_gi_instance_create(RID p_voxel_gi) = 0;
+ virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) = 0;
+ virtual bool voxel_gi_needs_update(RID p_probe) const = 0;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0;
- virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
+ virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0;
struct RenderShadowData {
RID light;
@@ -216,17 +217,34 @@ public:
uint32_t positional_light_count;
};
- virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) = 0;
+ struct CameraData {
+ // flags
+ uint32_t view_count;
+ bool is_ortogonal;
+ bool vaspect;
- virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
+ // Main/center projection
+ Transform3D main_transform;
+ CameraMatrix main_projection;
+
+ Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS];
+ CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+
+ void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect);
+ void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect);
+ };
+
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) = 0;
+
+ virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
virtual void set_time(double p_time, double p_step) = 0;
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index cc4ff5d55e..e6b9ac15ff 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -268,14 +268,14 @@ public:
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
- virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0;
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0;
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
- virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
@@ -313,8 +313,8 @@ public:
virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
- virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0;
- virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0;
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
@@ -413,53 +413,53 @@ public:
virtual AABB decal_get_aabb(RID p_decal) const = 0;
- /* GI PROBE API */
+ /* VOXEL GI API */
- virtual RID gi_probe_allocate() = 0;
- virtual void gi_probe_initialize(RID p_rid) = 0;
+ virtual RID voxel_gi_allocate() = 0;
+ virtual void voxel_gi_initialize(RID p_rid) = 0;
- virtual void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
+ virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
- virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
- virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
- virtual Vector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const = 0;
- virtual Vector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const = 0;
- virtual Vector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const = 0;
+ virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const = 0;
+ virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const = 0;
- virtual Vector<int> gi_probe_get_level_counts(RID p_gi_probe) const = 0;
- virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0;
+ virtual Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const = 0;
+ virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0;
- virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0;
- virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_propagation(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0;
- virtual float gi_probe_get_energy(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
+ virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0;
- virtual float gi_probe_get_ao(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) = 0;
+ virtual float voxel_gi_get_ao(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0;
- virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) = 0;
+ virtual float voxel_gi_get_ao_size(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0;
- virtual float gi_probe_get_bias(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
+ virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0;
- virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0;
- virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) = 0;
+ virtual bool voxel_gi_is_interior(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0;
- virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) = 0;
+ virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0;
- virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) = 0;
+ virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const = 0;
- virtual uint32_t gi_probe_get_version(RID p_probe) = 0;
+ virtual uint32_t voxel_gi_get_version(RID p_probe) = 0;
/* LIGHTMAP */
@@ -507,10 +507,10 @@ public:
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
virtual void particles_set_trails(RID p_particles, bool p_enable, float p_length) = 0;
- virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform> &p_bind_poses) = 0;
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
virtual void particles_restart(RID p_particles) = 0;
- virtual void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
+ virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0;
virtual bool particles_is_inactive(RID p_particles) const = 0;
@@ -524,7 +524,7 @@ public:
virtual AABB particles_get_current_aabb(RID p_particles) = 0;
virtual AABB particles_get_aabb(RID p_particles) const = 0;
- virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0;
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0;
virtual int particles_get_draw_passes(RID p_particles) const = 0;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
@@ -534,6 +534,8 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
+ virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
+
virtual void update_particles() = 0;
/* PARTICLES COLLISION */
@@ -557,7 +559,7 @@ public:
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision) = 0;
- virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) = 0;
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
/* GLOBAL VARIABLES */
@@ -588,7 +590,7 @@ public:
virtual RID render_target_create() = 0;
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
- virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
virtual RID render_target_get_texture(RID p_render_target) = 0;
virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
@@ -603,6 +605,7 @@ public:
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
+ virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
virtual bool free(RID p_rid) = 0;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index f7be6c6c60..34bdb15c62 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -71,11 +71,11 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
return xf;
}
-void RendererViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye) {
+void RendererViewport::_draw_3d(Viewport *p_viewport) {
RENDER_TIMESTAMP(">Begin Rendering 3D Scene");
Ref<XRInterface> xr_interface;
- if (XRServer::get_singleton() != nullptr) {
+ if (p_viewport->use_xr && XRServer::get_singleton() != nullptr) {
xr_interface = XRServer::get_singleton()->get_primary_interface();
}
@@ -95,15 +95,12 @@ void RendererViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye) {
}
float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width);
- if (p_viewport->use_xr && xr_interface.is_valid()) {
- RSG::scene->render_camera(p_viewport->render_buffers, xr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas);
- } else {
- RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas);
- }
+ RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface);
+
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
-void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye) {
+void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_count) {
if (p_viewport->measure_render_time) {
String rt_id = "vp_begin_" + itos(p_viewport->self.get_id());
RSG::storage->capture_timestamp(rt_id);
@@ -139,13 +136,13 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
//wants to draw 3D but there is no render buffer, create
p_viewport->render_buffers = RSG::scene->render_buffers_create();
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding);
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_view_count);
}
RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
if (!scenario_draw_canvas_bg && can_draw_3d) {
- _draw_3d(p_viewport, p_eye);
+ _draw_3d(p_viewport);
}
if (!p_viewport->hide_canvas) {
@@ -186,8 +183,11 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
}
RSG::canvas_render->render_sdf(p_viewport->render_target, occluders);
+ RSG::storage->render_target_mark_sdf_enabled(p_viewport->render_target, true);
p_viewport->sdf_active = false; // if used, gets set active again
+ } else {
+ RSG::storage->render_target_mark_sdf_enabled(p_viewport->render_target, false);
}
Rect2 shadow_rect;
@@ -322,7 +322,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
Vector2 point = clip_rect.position + clip_rect.size * signs[j];
if (sign_cmp == light_dir_sign) {
- //both point in same direction, plot offseted
+ //both point in same direction, plot offsetted
points[point_count++] = point + light_dir * cull_distance;
} else if (sign_cmp.x == light_dir_sign.x || sign_cmp.y == light_dir_sign.y) {
int next_j = (j + 1) % 4;
@@ -389,7 +389,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
- _draw_3d(p_viewport, p_eye);
+ _draw_3d(p_viewport);
}
scenario_draw_canvas_bg = false;
}
@@ -430,7 +430,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
- _draw_3d(p_viewport, p_eye);
+ _draw_3d(p_viewport);
}
scenario_draw_canvas_bg = false;
@@ -441,7 +441,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
- _draw_3d(p_viewport, p_eye);
+ _draw_3d(p_viewport);
}
}
}
@@ -478,7 +478,7 @@ void RendererViewport::draw_viewports() {
//sort viewports
active_viewports.sort_custom<ViewportSort>();
- Map<DisplayServer::WindowID, Vector<RendererCompositor::BlitToScreen>> blit_to_screen_list;
+ Map<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;
//draw viewports
RENDER_TIMESTAMP(">Render Viewports");
@@ -532,52 +532,54 @@ void RendererViewport::draw_viewports() {
RENDER_TIMESTAMP(">Rendering Viewport " + itos(i));
RSG::storage->render_target_set_as_unused(vp->render_target);
-#if 0
- // TODO fix up this code after we change our commit_for_eye to accept our new render targets
-
if (vp->use_xr && xr_interface.is_valid()) {
- // override our size, make sure it matches our required size
+ // override our size, make sure it matches our required size and is created as a stereo target
vp->size = xr_interface->get_render_targetsize();
- RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y);
-
- // render mono or left eye first
- XRInterface::Eyes leftOrMono = xr_interface->is_stereo() ? XRInterface::EYE_LEFT : XRInterface::EYE_MONO;
+ uint32_t view_count = xr_interface->get_view_count();
+ RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
- // check for an external texture destination for our left eye/mono
- // TODO investigate how we're going to make external textures work
- RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
+ // check for an external texture destination (disabled for now, not yet supported)
+ // RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
+ RSG::storage->render_target_set_external_texture(vp->render_target, 0);
- // set our render target as current
- RSG::rasterizer->set_current_render_target(vp->render_target);
+ // render...
+ RSG::scene->set_debug_draw_mode(vp->debug_draw);
+ RSG::storage->render_info_begin_capture();
- // and draw left eye/mono
- _draw_viewport(vp, leftOrMono);
- xr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect);
+ // and draw viewport
+ _draw_viewport(vp, view_count);
- // render right eye
- if (leftOrMono == XRInterface::EYE_LEFT) {
- // check for an external texture destination for our right eye
- RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(XRInterface::EYE_RIGHT));
+ // measure
+ RSG::storage->render_info_end_capture();
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_OBJECTS_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_VERTICES_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_MATERIAL_CHANGES_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SHADER_CHANGES_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SURFACE_CHANGES_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_DRAW_CALLS_IN_FRAME);
- // commit for eye may have changed the render target
- RSG::rasterizer->set_current_render_target(vp->render_target);
+ // commit our eyes
+ Vector<BlitToScreen> blits = xr_interface->commit_views(vp->render_target, vp->viewport_to_screen_rect);
+ if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) {
+ if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
+ blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
+ }
- _draw_viewport(vp, XRInterface::EYE_RIGHT);
- xr_interface->commit_for_eye(XRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect);
+ for (int b = 0; b < blits.size(); b++) {
+ blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
+ }
}
// and for our frame timing, mark when we've finished committing our eyes
XRServer::get_singleton()->_mark_commit();
} else {
-#endif
- {
RSG::storage->render_target_set_external_texture(vp->render_target, 0);
RSG::scene->set_debug_draw_mode(vp->debug_draw);
RSG::storage->render_info_begin_capture();
// render standard mono camera
- _draw_viewport(vp);
+ _draw_viewport(vp, 1);
RSG::storage->render_info_end_capture();
vp->render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_OBJECTS_IN_FRAME);
@@ -589,7 +591,7 @@ void RendererViewport::draw_viewports() {
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !RSG::rasterizer->is_low_end())) {
//copy to screen if set as such
- RendererCompositor::BlitToScreen blit;
+ BlitToScreen blit;
blit.render_target = vp->render_target;
if (vp->viewport_to_screen_rect != Rect2()) {
blit.rect = vp->viewport_to_screen_rect;
@@ -599,7 +601,7 @@ void RendererViewport::draw_viewports() {
}
if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
- blit_to_screen_list[vp->viewport_to_screen] = Vector<RendererCompositor::BlitToScreen>();
+ blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
}
blit_to_screen_list[vp->viewport_to_screen].push_back(blit);
@@ -618,7 +620,7 @@ void RendererViewport::draw_viewports() {
//this needs to be called to make screen swapping more efficient
RSG::rasterizer->prepare_for_blitting_render_targets();
- for (Map<int, Vector<RendererCompositor::BlitToScreen>>::Element *E = blit_to_screen_list.front(); E; E = E->next()) {
+ for (Map<int, Vector<BlitToScreen>>::Element *E = blit_to_screen_list.front(); E; E = E->next()) {
RSG::rasterizer->blit_render_targets_to_screen(E->key(), E->get().ptr(), E->get().size());
}
}
@@ -643,7 +645,29 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
+ if (viewport->use_xr == p_use_xr) {
+ return;
+ }
+
viewport->use_xr = p_use_xr;
+ if (viewport->render_buffers.is_valid()) {
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding, viewport->get_view_count());
+ }
+}
+
+uint32_t RendererViewport::Viewport::get_view_count() {
+ uint32_t view_count = 1;
+
+ if (use_xr && XRServer::get_singleton() != nullptr) {
+ Ref<XRInterface> xr_interface;
+
+ xr_interface = XRServer::get_singleton()->get_primary_interface();
+ if (xr_interface.is_valid()) {
+ view_count = xr_interface->get_view_count();
+ }
+ }
+
+ return view_count;
}
void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
@@ -653,13 +677,14 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
ERR_FAIL_COND(!viewport);
viewport->size = Size2(p_width, p_height);
- RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height);
+ uint32_t view_count = viewport->get_view_count();
+ RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
if (viewport->render_buffers.is_valid()) {
if (p_width == 0 || p_height == 0) {
RSG::scene->free(viewport->render_buffers);
viewport->render_buffers = RID();
} else {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding);
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding, view_count);
}
}
@@ -701,7 +726,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// If using GLES2 we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
- RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y);
+ RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
RSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
}
@@ -711,7 +736,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
+ RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
}
viewport->viewport_to_screen_rect = Rect2();
@@ -730,7 +755,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if disabled, reset render_target size and position
if (!p_enable) {
RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
+ RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
}
RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
@@ -738,7 +763,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
- RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y);
+ RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
RSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
}
}
@@ -799,6 +824,10 @@ void RendererViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
+ if (viewport->scenario.is_valid()) {
+ RSG::scene->scenario_remove_viewport_visibility_mask(viewport->scenario, p_viewport);
+ }
+
viewport->scenario = p_scenario;
if (viewport->use_occlusion_culling) {
RendererSceneOcclusionCull::get_singleton()->buffer_set_scenario(p_viewport, p_scenario);
@@ -889,7 +918,7 @@ void RendererViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa
}
viewport->msaa = p_msaa;
if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding);
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding, viewport->get_view_count());
}
}
@@ -902,7 +931,7 @@ void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::Viewport
}
viewport->screen_space_aa = p_mode;
if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding);
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding, viewport->get_view_count());
}
}
@@ -915,7 +944,7 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
}
viewport->use_debanding = p_use_debanding;
if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding);
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding, viewport->get_view_count());
}
}
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 5c372e8c9a..ffda9ad8f0 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -164,6 +164,8 @@ public:
time_gpu_begin = 0;
time_gpu_end = 0;
}
+
+ uint32_t get_view_count();
};
HashMap<String, RID> timestamp_vp_map;
@@ -187,8 +189,8 @@ public:
Vector<Viewport *> active_viewports;
private:
- void _draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye);
- void _draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye = XRInterface::EYE_MONO);
+ void _draw_3d(Viewport *p_viewport);
+ void _draw_viewport(Viewport *p_viewport, uint32_t p_view_count = 1);
int occlusion_rays_per_thread = 512;
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index e6ad001807..056cec4c1f 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -40,6 +40,7 @@ RenderingDevice *RenderingDevice::get_singleton() {
RenderingDevice::ShaderCompileFunction RenderingDevice::compile_function = nullptr;
RenderingDevice::ShaderCacheFunction RenderingDevice::cache_function = nullptr;
+RenderingDevice::ShaderGetCacheKeyFunction RenderingDevice::get_cache_key_function = nullptr;
void RenderingDevice::shader_set_compile_function(ShaderCompileFunction p_function) {
compile_function = p_function;
@@ -49,6 +50,10 @@ void RenderingDevice::shader_set_cache_function(ShaderCacheFunction p_function)
cache_function = p_function;
}
+void RenderingDevice::shader_set_get_cache_key_function(ShaderGetCacheKeyFunction p_function) {
+ get_cache_key_function = p_function;
+}
+
Vector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, bool p_allow_cache) {
if (p_allow_cache && cache_function) {
Vector<uint8_t> cache = cache_function(p_stage, p_source_code, p_language);
@@ -62,6 +67,13 @@ Vector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage,
return compile_function(p_stage, p_source_code, p_language, r_error, &device_capabilities);
}
+String RenderingDevice::shader_get_cache_key() const {
+ if (get_cache_key_function) {
+ return get_cache_key_function(&device_capabilities);
+ }
+ return String();
+}
+
RID RenderingDevice::_texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data) {
ERR_FAIL_COND_V(p_format.is_null(), RID());
ERR_FAIL_COND_V(p_view.is_null(), RID());
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index d86c44a206..c13dc01dd7 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -103,12 +103,14 @@ public:
bool supports_multiview = false; // If true this device supports multiview options
};
+ typedef String (*ShaderGetCacheKeyFunction)(const Capabilities *p_capabilities);
typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);
typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
private:
static ShaderCompileFunction compile_function;
static ShaderCacheFunction cache_function;
+ static ShaderGetCacheKeyFunction get_cache_key_function;
static RenderingDevice *singleton;
@@ -514,11 +516,11 @@ public:
typedef int64_t FramebufferFormatID;
// This ID is warranted to be unique for the same formats, does not need to be freed
- virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format) = 0;
+ virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1) = 0;
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1) = 0;
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0;
- virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0;
+ virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID) = 0;
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0;
@@ -635,9 +637,11 @@ public:
const Capabilities *get_device_capabilities() const { return &device_capabilities; };
virtual Vector<uint8_t> shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true);
+ virtual String shader_get_cache_key() const;
static void shader_set_compile_function(ShaderCompileFunction p_function);
static void shader_set_cache_function(ShaderCacheFunction p_function);
+ static void shader_set_get_cache_key_function(ShaderGetCacheKeyFunction p_function);
struct ShaderStageData {
ShaderStage shader_stage;
@@ -982,7 +986,7 @@ public:
enum InitialAction {
INITIAL_ACTION_CLEAR, //start rendering and clear the whole framebuffer (region or not) (supply params)
INITIAL_ACTION_CLEAR_REGION, //start rendering and clear the framebuffer in the specified region (supply params)
- INITIAL_ACTION_CLEAR_REGION_CONTINUE, //countinue rendering and clear the framebuffer in the specified region (supply params)
+ INITIAL_ACTION_CLEAR_REGION_CONTINUE, //continue rendering and clear the framebuffer in the specified region (supply params)
INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared)
INITIAL_ACTION_DROP, //start rendering, ignore what is there, just write above it
INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action previously)
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index e43c3669b5..912674e309 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -51,8 +51,8 @@
ClassDB::bind_method(D_METHOD("get_" _MKSTR(m_sub) "_" _MKSTR(m_member)), &m_class::get_##m_sub##_##m_member); \
ADD_PROPERTY(PropertyInfo(m_variant_type, _MKSTR(m_sub) "_" _MKSTR(m_member)), "set_" _MKSTR(m_sub) "_" _MKSTR(m_member), "get_" _MKSTR(m_sub) "_" _MKSTR(m_member))
-class RDTextureFormat : public Reference {
- GDCLASS(RDTextureFormat, Reference)
+class RDTextureFormat : public RefCounted {
+ GDCLASS(RDTextureFormat, RefCounted)
friend class RenderingDevice;
RD::TextureFormat base;
@@ -87,8 +87,8 @@ protected:
}
};
-class RDTextureView : public Reference {
- GDCLASS(RDTextureView, Reference)
+class RDTextureView : public RefCounted {
+ GDCLASS(RDTextureView, RefCounted)
friend class RenderingDevice;
@@ -110,8 +110,8 @@ protected:
}
};
-class RDAttachmentFormat : public Reference {
- GDCLASS(RDAttachmentFormat, Reference)
+class RDAttachmentFormat : public RefCounted {
+ GDCLASS(RDAttachmentFormat, RefCounted)
friend class RenderingDevice;
RD::AttachmentFormat base;
@@ -128,8 +128,8 @@ protected:
}
};
-class RDSamplerState : public Reference {
- GDCLASS(RDSamplerState, Reference)
+class RDSamplerState : public RefCounted {
+ GDCLASS(RDSamplerState, RefCounted)
friend class RenderingDevice;
RD::SamplerState base;
@@ -171,8 +171,8 @@ protected:
}
};
-class RDVertexAttribute : public Reference {
- GDCLASS(RDVertexAttribute, Reference)
+class RDVertexAttribute : public RefCounted {
+ GDCLASS(RDVertexAttribute, RefCounted)
friend class RenderingDevice;
RD::VertexAttribute base;
@@ -192,8 +192,8 @@ protected:
RD_BIND(Variant::INT, RDVertexAttribute, frequency);
}
};
-class RDShaderSource : public Reference {
- GDCLASS(RDShaderSource, Reference)
+class RDShaderSource : public RefCounted {
+ GDCLASS(RDShaderSource, RefCounted)
String source[RD::SHADER_STAGE_MAX];
RD::ShaderLanguage language = RD::SHADER_LANGUAGE_GLSL;
@@ -386,8 +386,8 @@ protected:
}
};
-class RDUniform : public Reference {
- GDCLASS(RDUniform, Reference)
+class RDUniform : public RefCounted {
+ GDCLASS(RDUniform, RefCounted)
friend class RenderingDevice;
RD::Uniform base;
@@ -424,8 +424,8 @@ protected:
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_ids", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_ids", "get_ids");
}
};
-class RDPipelineRasterizationState : public Reference {
- GDCLASS(RDPipelineRasterizationState, Reference)
+class RDPipelineRasterizationState : public RefCounted {
+ GDCLASS(RDPipelineRasterizationState, RefCounted)
friend class RenderingDevice;
RD::PipelineRasterizationState base;
@@ -459,8 +459,8 @@ protected:
}
};
-class RDPipelineMultisampleState : public Reference {
- GDCLASS(RDPipelineMultisampleState, Reference)
+class RDPipelineMultisampleState : public RefCounted {
+ GDCLASS(RDPipelineMultisampleState, RefCounted)
friend class RenderingDevice;
RD::PipelineMultisampleState base;
@@ -490,8 +490,8 @@ protected:
}
};
-class RDPipelineDepthStencilState : public Reference {
- GDCLASS(RDPipelineDepthStencilState, Reference)
+class RDPipelineDepthStencilState : public RefCounted {
+ GDCLASS(RDPipelineDepthStencilState, RefCounted)
friend class RenderingDevice;
RD::PipelineDepthStencilState base;
@@ -549,8 +549,8 @@ protected:
}
};
-class RDPipelineColorBlendStateAttachment : public Reference {
- GDCLASS(RDPipelineColorBlendStateAttachment, Reference)
+class RDPipelineColorBlendStateAttachment : public RefCounted {
+ GDCLASS(RDPipelineColorBlendStateAttachment, RefCounted)
friend class RenderingDevice;
RD::PipelineColorBlendState::Attachment base;
@@ -594,8 +594,8 @@ protected:
}
};
-class RDPipelineColorBlendState : public Reference {
- GDCLASS(RDPipelineColorBlendState, Reference)
+class RDPipelineColorBlendState : public RefCounted {
+ GDCLASS(RDPipelineColorBlendState, RefCounted)
friend class RenderingDevice;
RD::PipelineColorBlendState base;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index c6fe6a07e0..cd66cd0716 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -358,7 +358,7 @@ void RenderingServerDefault::_thread_loop() {
draw_thread_up.set();
while (!exit.is_set()) {
// flush commands one by one, until exit is requested
- command_queue.wait_and_flush_one();
+ command_queue.wait_and_flush();
}
command_queue.flush_all(); // flush all
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index bf47d497b6..e4d319ed6c 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -314,7 +314,7 @@ public:
FUNC1RC(int, multimesh_get_instance_count, RID)
FUNC2(multimesh_set_mesh, RID, RID)
- FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
+ FUNC3(multimesh_instance_set_transform, RID, int, const Transform3D &)
FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
FUNC3(multimesh_instance_set_color, RID, int, const Color &)
FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &)
@@ -322,7 +322,7 @@ public:
FUNC1RC(RID, multimesh_get_mesh, RID)
FUNC1RC(AABB, multimesh_get_aabb, RID)
- FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
+ FUNC2RC(Transform3D, multimesh_instance_get_transform, RID, int)
FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
FUNC2RC(Color, multimesh_instance_get_color, RID, int)
FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
@@ -353,8 +353,8 @@ public:
FUNCRIDSPLIT(skeleton)
FUNC3(skeleton_allocate_data, RID, int, bool)
FUNC1RC(int, skeleton_get_bone_count, RID)
- FUNC3(skeleton_bone_set_transform, RID, int, const Transform &)
- FUNC2RC(Transform, skeleton_bone_get_transform, RID, int)
+ FUNC3(skeleton_bone_set_transform, RID, int, const Transform3D &)
+ FUNC2RC(Transform3D, skeleton_bone_get_transform, RID, int)
FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
@@ -418,47 +418,47 @@ public:
/* BAKED LIGHT API */
- FUNCRIDSPLIT(gi_probe)
+ FUNCRIDSPLIT(voxel_gi)
- FUNC8(gi_probe_allocate_data, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
+ FUNC8(voxel_gi_allocate_data, RID, const Transform3D &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
- FUNC1RC(AABB, gi_probe_get_bounds, RID)
- FUNC1RC(Vector3i, gi_probe_get_octree_size, RID)
- FUNC1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
- FUNC1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
- FUNC1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
- FUNC1RC(Vector<int>, gi_probe_get_level_counts, RID)
- FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
+ FUNC1RC(AABB, voxel_gi_get_bounds, RID)
+ FUNC1RC(Vector3i, voxel_gi_get_octree_size, RID)
+ FUNC1RC(Vector<uint8_t>, voxel_gi_get_octree_cells, RID)
+ FUNC1RC(Vector<uint8_t>, voxel_gi_get_data_cells, RID)
+ FUNC1RC(Vector<uint8_t>, voxel_gi_get_distance_field, RID)
+ FUNC1RC(Vector<int>, voxel_gi_get_level_counts, RID)
+ FUNC1RC(Transform3D, voxel_gi_get_to_cell_xform, RID)
- FUNC2(gi_probe_set_dynamic_range, RID, float)
- FUNC1RC(float, gi_probe_get_dynamic_range, RID)
+ FUNC2(voxel_gi_set_dynamic_range, RID, float)
+ FUNC1RC(float, voxel_gi_get_dynamic_range, RID)
- FUNC2(gi_probe_set_propagation, RID, float)
- FUNC1RC(float, gi_probe_get_propagation, RID)
+ FUNC2(voxel_gi_set_propagation, RID, float)
+ FUNC1RC(float, voxel_gi_get_propagation, RID)
- FUNC2(gi_probe_set_energy, RID, float)
- FUNC1RC(float, gi_probe_get_energy, RID)
+ FUNC2(voxel_gi_set_energy, RID, float)
+ FUNC1RC(float, voxel_gi_get_energy, RID)
- FUNC2(gi_probe_set_ao, RID, float)
- FUNC1RC(float, gi_probe_get_ao, RID)
+ FUNC2(voxel_gi_set_ao, RID, float)
+ FUNC1RC(float, voxel_gi_get_ao, RID)
- FUNC2(gi_probe_set_ao_size, RID, float)
- FUNC1RC(float, gi_probe_get_ao_size, RID)
+ FUNC2(voxel_gi_set_ao_size, RID, float)
+ FUNC1RC(float, voxel_gi_get_ao_size, RID)
- FUNC2(gi_probe_set_bias, RID, float)
- FUNC1RC(float, gi_probe_get_bias, RID)
+ FUNC2(voxel_gi_set_bias, RID, float)
+ FUNC1RC(float, voxel_gi_get_bias, RID)
- FUNC2(gi_probe_set_normal_bias, RID, float)
- FUNC1RC(float, gi_probe_get_normal_bias, RID)
+ FUNC2(voxel_gi_set_normal_bias, RID, float)
+ FUNC1RC(float, voxel_gi_get_normal_bias, RID)
- FUNC2(gi_probe_set_interior, RID, bool)
- FUNC1RC(bool, gi_probe_is_interior, RID)
+ FUNC2(voxel_gi_set_interior, RID, bool)
+ FUNC1RC(bool, voxel_gi_is_interior, RID)
- FUNC2(gi_probe_set_use_two_bounces, RID, bool)
- FUNC1RC(bool, gi_probe_is_using_two_bounces, RID)
+ FUNC2(voxel_gi_set_use_two_bounces, RID, bool)
+ FUNC1RC(bool, voxel_gi_is_using_two_bounces, RID)
- FUNC2(gi_probe_set_anisotropy_strength, RID, float)
- FUNC1RC(float, gi_probe_get_anisotropy_strength, RID)
+ FUNC2(voxel_gi_set_anisotropy_strength, RID, float)
+ FUNC1RC(float, voxel_gi_get_anisotropy_strength, RID)
/* LIGHTMAP */
@@ -496,11 +496,11 @@ public:
FUNC2(particles_set_fractional_delta, RID, bool)
FUNC1R(bool, particles_is_inactive, RID)
FUNC3(particles_set_trails, RID, bool, float)
- FUNC2(particles_set_trail_bind_poses, RID, const Vector<Transform> &)
+ FUNC2(particles_set_trail_bind_poses, RID, const Vector<Transform3D> &)
FUNC1(particles_request_process, RID)
FUNC1(particles_restart, RID)
- FUNC6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t)
+ FUNC6(particles_emit, RID, const Transform3D &, const Vector3 &, const Color &, const Color &, uint32_t)
FUNC2(particles_set_subemitter, RID, RID)
FUNC2(particles_set_collision_base_size, RID, float)
@@ -512,7 +512,7 @@ public:
FUNC3(particles_set_draw_pass_mesh, RID, int, RID)
FUNC1R(AABB, particles_get_current_aabb, RID)
- FUNC2(particles_set_emission_transform, RID, const Transform &)
+ FUNC2(particles_set_emission_transform, RID, const Transform3D &)
/* PARTICLES COLLISION */
@@ -541,7 +541,7 @@ public:
FUNC4(camera_set_perspective, RID, float, float, float)
FUNC4(camera_set_orthogonal, RID, float, float, float)
FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
- FUNC2(camera_set_transform, RID, const Transform &)
+ FUNC2(camera_set_transform, RID, const Transform3D &)
FUNC2(camera_set_cull_mask, RID, uint32_t)
FUNC2(camera_set_environment, RID, RID)
FUNC2(camera_set_camera_effects, RID, RID)
@@ -624,7 +624,7 @@ public:
#define server_name RSG::scene
FUNC2(directional_shadow_atlas_set_size, int, bool)
- FUNC1(gi_probe_set_quality, GIProbeQuality)
+ FUNC1(voxel_gi_set_quality, VoxelGIQuality)
/* SKY API */
@@ -714,7 +714,7 @@ public:
FUNC2(instance_set_base, RID, RID)
FUNC2(instance_set_scenario, RID, RID)
FUNC2(instance_set_layer_mask, RID, uint32_t)
- FUNC2(instance_set_transform, RID, const Transform &)
+ FUNC2(instance_set_transform, RID, const Transform3D &)
FUNC2(instance_attach_object_instance_id, RID, ObjectID)
FUNC3(instance_set_blend_shape_weight, RID, int, float)
FUNC3(instance_set_surface_override_material, RID, int, RID)
@@ -726,6 +726,7 @@ public:
FUNC2(instance_set_exterior, RID, bool)
FUNC2(instance_set_extra_visibility_margin, RID, real_t)
+ FUNC2(instance_set_visibility_parent, RID, RID)
// don't use these in a game!
FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
@@ -736,8 +737,7 @@ public:
FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
FUNC2(instance_geometry_set_material_override, RID, RID)
- FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
- FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
+ FUNC5(instance_geometry_set_visibility_range, RID, float, float, float, float)
FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
FUNC2(instance_geometry_set_lod_bias, RID, float)
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index a81306b97d..8ed774f8e7 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -33,6 +33,8 @@
#include "core/string/print_string.h"
#include "servers/rendering_server.h"
+#define HAS_WARNING(flag) (warning_flags & flag)
+
static bool _is_text_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
@@ -901,6 +903,8 @@ bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) {
void ShaderLanguage::clear() {
current_function = StringName();
+ last_name = StringName();
+ last_type = IDENTIFIER_MAX;
completion_type = COMPLETION_NONE;
completion_block = nullptr;
@@ -908,12 +912,22 @@ void ShaderLanguage::clear() {
completion_class = SubClassTag::TAG_GLOBAL;
completion_struct = StringName();
+#ifdef DEBUG_ENABLED
+ used_constants.clear();
+ used_varyings.clear();
+ used_uniforms.clear();
+ used_functions.clear();
+ used_structs.clear();
+ warnings.clear();
+#endif // DEBUG_ENABLED
+
error_line = 0;
tk_line = 1;
char_idx = 0;
error_set = false;
error_str = "";
last_const = false;
+ pass_array = false;
while (nodes) {
Node *n = nodes;
nodes = nodes->next;
@@ -921,6 +935,35 @@ void ShaderLanguage::clear() {
}
}
+#ifdef DEBUG_ENABLED
+void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, IdentifierType p_type) {
+ switch (p_type) {
+ case IdentifierType::IDENTIFIER_CONSTANT:
+ if (HAS_WARNING(ShaderWarning::UNUSED_CONSTANT_FLAG) && used_constants.has(p_identifier)) {
+ used_constants[p_identifier].used = true;
+ }
+ break;
+ case IdentifierType::IDENTIFIER_VARYING:
+ if (HAS_WARNING(ShaderWarning::UNUSED_VARYING_FLAG) && used_varyings.has(p_identifier)) {
+ used_varyings[p_identifier].used = true;
+ }
+ break;
+ case IdentifierType::IDENTIFIER_UNIFORM:
+ if (HAS_WARNING(ShaderWarning::UNUSED_UNIFORM_FLAG) && used_uniforms.has(p_identifier)) {
+ used_uniforms[p_identifier].used = true;
+ }
+ break;
+ case IdentifierType::IDENTIFIER_FUNCTION:
+ if (HAS_WARNING(ShaderWarning::UNUSED_FUNCTION_FLAG) && used_functions.has(p_identifier)) {
+ used_functions[p_identifier].used = true;
+ }
+ break;
+ default:
+ break;
+ }
+}
+#endif // DEBUG_ENABLED
+
bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) {
if (p_function_info.built_ins.has(p_identifier)) {
if (r_data_type) {
@@ -932,7 +975,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_type) {
*r_type = IDENTIFIER_BUILTIN_VAR;
}
-
return true;
}
@@ -946,7 +988,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_type) {
*r_type = IDENTIFIER_FUNCTION;
}
-
return true;
}
@@ -963,16 +1004,15 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_array_size) {
*r_array_size = p_block->variables[p_identifier].array_size;
}
- if (r_type) {
- *r_type = IDENTIFIER_LOCAL_VAR;
- }
if (r_struct_name) {
*r_struct_name = p_block->variables[p_identifier].struct_name;
}
if (r_constant_value) {
*r_constant_value = p_block->variables[p_identifier].value;
}
-
+ if (r_type) {
+ *r_type = IDENTIFIER_LOCAL_VAR;
+ }
return true;
}
@@ -994,15 +1034,18 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_data_type) {
*r_data_type = function->arguments[i].type;
}
- if (r_type) {
- *r_type = IDENTIFIER_FUNCTION_ARGUMENT;
- }
if (r_struct_name) {
*r_struct_name = function->arguments[i].type_str;
}
+ if (r_array_size) {
+ *r_array_size = function->arguments[i].array_size;
+ }
if (r_is_const) {
*r_is_const = function->arguments[i].is_const;
}
+ if (r_type) {
+ *r_type = IDENTIFIER_FUNCTION_ARGUMENT;
+ }
return true;
}
}
@@ -1041,9 +1084,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_array_size) {
*r_array_size = shader->constants[p_identifier].array_size;
}
- if (r_type) {
- *r_type = IDENTIFIER_CONSTANT;
- }
if (r_struct_name) {
*r_struct_name = shader->constants[p_identifier].type_str;
}
@@ -1052,6 +1092,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
*r_constant_value = shader->constants[p_identifier].initializer->values[0];
}
}
+ if (r_type) {
+ *r_type = IDENTIFIER_CONSTANT;
+ }
return true;
}
@@ -1064,6 +1107,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_data_type) {
*r_data_type = shader->functions[i].function->return_type;
}
+ if (r_array_size) {
+ *r_array_size = shader->functions[i].function->return_array_size;
+ }
if (r_type) {
*r_type = IDENTIFIER_FUNCTION;
}
@@ -1074,13 +1120,18 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
return false;
}
-bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type) {
+bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type, int *r_ret_size) {
bool valid = false;
DataType ret_type = TYPE_VOID;
+ int ret_size = 0;
switch (p_op->op) {
case OP_EQUAL:
case OP_NOT_EQUAL: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
valid = na == nb;
@@ -1090,6 +1141,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_LESS_EQUAL:
case OP_GREATER:
case OP_GREATER_EQUAL: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1099,6 +1154,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} break;
case OP_AND:
case OP_OR: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1107,6 +1166,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} break;
case OP_NOT: {
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na == TYPE_BOOL;
ret_type = TYPE_BOOL;
@@ -1117,6 +1180,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_POST_INCREMENT:
case OP_POST_DECREMENT:
case OP_NEGATE: {
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na > TYPE_BOOL && na < TYPE_MAT2;
ret_type = na;
@@ -1125,6 +1192,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_SUB:
case OP_MUL:
case OP_DIV: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1193,6 +1264,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
* component-wise.
*/
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1245,6 +1320,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_ASSIGN_SHIFT_RIGHT:
case OP_SHIFT_LEFT:
case OP_SHIFT_RIGHT: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1293,6 +1372,18 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
} break;
case OP_ASSIGN: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa != sb) {
+ break; // don't accept arrays if their sizes are not equal
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
if (na == TYPE_STRUCT || nb == TYPE_STRUCT) {
@@ -1301,11 +1392,24 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
valid = na == nb;
}
ret_type = na;
+ ret_size = sa;
} break;
case OP_ASSIGN_ADD:
case OP_ASSIGN_SUB:
case OP_ASSIGN_MUL:
case OP_ASSIGN_DIV: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa > 0 || sb > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1373,6 +1477,18 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
* must match.
*/
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa > 0 || sb > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1427,17 +1543,34 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
} break;
case OP_BIT_INVERT: { //unaries
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na >= TYPE_INT && na < TYPE_FLOAT;
ret_type = na;
} break;
case OP_SELECT_IF: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[1]->is_indexed()) {
+ sa = p_op->arguments[1]->get_array_size();
+ }
+ if (!p_op->arguments[2]->is_indexed()) {
+ sb = p_op->arguments[2]->get_array_size();
+ }
+ if (sa != sb) {
+ break; // don't accept arrays if their sizes are not equal
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
DataType nc = p_op->arguments[2]->get_datatype();
valid = na == TYPE_BOOL && (nb == nc);
ret_type = nb;
+ ret_size = sa;
} break;
default: {
ERR_FAIL_V(false);
@@ -1447,6 +1580,9 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
if (r_ret_type) {
*r_ret_type = ret_type;
}
+ if (r_ret_size) {
+ *r_ret_size = ret_size;
+ }
return valid;
}
@@ -2182,6 +2318,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
Vector<DataType> args;
Vector<StringName> args2;
+ Vector<int> args3;
ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::TYPE_VARIABLE, false);
@@ -2190,6 +2327,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
for (int i = 1; i < p_func->arguments.size(); i++) {
args.push_back(p_func->arguments[i]->get_datatype());
args2.push_back(p_func->arguments[i]->get_datatype_name());
+ args3.push_back(p_func->arguments[i]->get_array_size());
}
int argcount = args.size();
@@ -2457,6 +2595,11 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
} else {
func_arg_name = get_datatype_name(pfunc->arguments[j].type);
}
+ if (pfunc->arguments[j].array_size > 0) {
+ func_arg_name += "[";
+ func_arg_name += itos(pfunc->arguments[j].array_size);
+ func_arg_name += "]";
+ }
arg_list += func_arg_name;
}
}
@@ -2469,21 +2612,32 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool fail = false;
for (int j = 0; j < args.size(); j++) {
- if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
+ if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && args3[j] == 0 && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
//all good, but it needs implicit conversion later
- } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str)) {
+ } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) || args3[j] != pfunc->arguments[j].array_size) {
String func_arg_name;
if (pfunc->arguments[j].type == TYPE_STRUCT) {
func_arg_name = pfunc->arguments[j].type_str;
} else {
func_arg_name = get_datatype_name(pfunc->arguments[j].type);
}
+ if (pfunc->arguments[j].array_size > 0) {
+ func_arg_name += "[";
+ func_arg_name += itos(pfunc->arguments[j].array_size);
+ func_arg_name += "]";
+ }
String arg_name;
if (args[j] == TYPE_STRUCT) {
arg_name = args2[j];
} else {
arg_name = get_datatype_name(args[j]);
}
+ if (args3[j] > 0) {
+ arg_name += "[";
+ arg_name += itos(args3[j]);
+ arg_name += "]";
+ }
+
_set_error(vformat("Invalid argument for \"%s(%s)\" function: argument %s should be %s but is %s.", String(name), arg_list, j + 1, func_arg_name, arg_name));
fail = true;
break;
@@ -2529,16 +2683,45 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
return false;
}
-bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) const {
- if (a->get_datatype() != b->get_datatype()) {
- return false;
+bool ShaderLanguage::_compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b) {
+ bool result = true;
+
+ if (p_datatype_a == TYPE_STRUCT || p_datatype_b == TYPE_STRUCT) {
+ if (p_datatype_name_a != p_datatype_name_b) {
+ result = false;
+ }
+ } else {
+ if (p_datatype_a != p_datatype_b) {
+ result = false;
+ }
}
- if (a->get_datatype() == TYPE_STRUCT || b->get_datatype() == TYPE_STRUCT) {
- if (a->get_datatype_name() != b->get_datatype_name()) {
- return false;
+
+ if (p_array_size_a != p_array_size_b) {
+ result = false;
+ }
+
+ if (!result) {
+ String type_name = p_datatype_a == TYPE_STRUCT ? p_datatype_name_a : get_datatype_name(p_datatype_a);
+ if (p_array_size_a > 0) {
+ type_name += "[";
+ type_name += itos(p_array_size_a);
+ type_name += "]";
}
+
+ String type_name2 = p_datatype_b == TYPE_STRUCT ? p_datatype_name_b : get_datatype_name(p_datatype_b);
+ if (p_array_size_b > 0) {
+ type_name2 += "[";
+ type_name2 += itos(p_array_size_b);
+ type_name2 += "]";
+ }
+
+ _set_error("Invalid assignment of '" + type_name2 + "' to '" + type_name + "'");
}
- return true;
+ return result;
+}
+
+bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) {
+ return _compare_datatypes(a->get_datatype(), a->get_datatype_name(), a->get_array_size(), b->get_datatype(), b->get_datatype_name(), b->get_array_size());
}
bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg) {
@@ -2758,7 +2941,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
p[2][0] = p_value[8].real;
p[2][1] = p_value[9].real;
p[2][2] = p_value[10].real;
- Transform t = Transform(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
+ Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
value = Variant(t);
break;
}
@@ -2857,7 +3040,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
pi.type = Variant::BASIS;
break;
case ShaderLanguage::TYPE_MAT4:
- pi.type = Variant::TRANSFORM;
+ pi.type = Variant::TRANSFORM3D;
break;
case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_ISAMPLER2D:
@@ -3186,7 +3369,7 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
switch (p_node->type) {
case Node::TYPE_OPERATOR: {
OperatorNode *op_node = (OperatorNode *)p_node;
- for (int i = (1 ? op_node->op == OP_CALL : 0); i < op_node->arguments.size(); i++) {
+ for (int i = int(op_node->op == OP_CALL); i < op_node->arguments.size(); i++) {
if (!_check_node_constness(op_node->arguments[i])) {
return false;
}
@@ -3349,11 +3532,12 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
ERR_FAIL_V(false); //bug? function not found
}
-ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size) {
+ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info) {
DataType type = TYPE_VOID;
String struct_name = "";
int array_size = 0;
bool auto_size = false;
+ bool undefined_size = false;
Token tk = _get_token();
if (tk.type == TK_CURLY_BRACKET_OPEN) {
@@ -3374,6 +3558,137 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
TkPos pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
+ undefined_size = true;
+ tk = _get_token();
+ } else {
+ _set_tkpos(pos);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size = cnode->values[0].sint;
+ if (array_size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return nullptr;
+ } else {
+ tk = _get_token();
+ }
+ }
+ } else {
+ _set_error("Expected '['");
+ return nullptr;
+ }
+ }
+
+ ArrayConstructNode *an = alloc_node<ArrayConstructNode>();
+
+ if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
+ int idx = 0;
+ while (true) {
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n) {
+ return nullptr;
+ }
+
+ // define type by using the first member
+ if (auto_size && idx == 0) {
+ type = n->get_datatype();
+ if (type == TYPE_STRUCT) {
+ struct_name = n->get_datatype_name();
+ }
+ } else {
+ if (!_compare_datatypes(type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
+ return nullptr;
+ }
+ }
+
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ an->initializer.push_back(n);
+ } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else {
+ if (auto_size) {
+ _set_error("Expected '}' or ','");
+ } else {
+ _set_error("Expected ')' or ','");
+ }
+ return nullptr;
+ }
+ idx++;
+ }
+ if (!auto_size && !undefined_size && an->initializer.size() != array_size) {
+ _set_error("Array size mismatch");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected array initialization!");
+ return nullptr;
+ }
+
+ an->datatype = type;
+ an->struct_name = struct_name;
+ return an;
+}
+
+ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size) {
+ DataType type = TYPE_VOID;
+ String struct_name = "";
+ int array_size = 0;
+ bool auto_size = false;
+ TkPos prev_pos = _get_tkpos();
+ Token tk = _get_token();
+
+ if (tk.type == TK_CURLY_BRACKET_OPEN) {
+ auto_size = true;
+ } else {
+ if (shader->structs.has(tk.text)) {
+ type = TYPE_STRUCT;
+ struct_name = tk.text;
+ } else {
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_tkpos(prev_pos);
+
+ pass_array = true;
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ pass_array = false;
+
+ if (!n) {
+ _set_error("Invalid data type for array");
+ return nullptr;
+ }
+
+ if (!_compare_datatypes(p_type, p_struct_name, p_array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
+ return nullptr;
+ }
+ return n;
+ }
+ type = get_token_datatype(tk.type);
+ }
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ TkPos pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_CLOSE) {
array_size = p_array_size;
tk = _get_token();
} else {
@@ -3445,8 +3760,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
return nullptr;
}
- if (p_type != n->get_datatype() || p_struct_name != n->get_datatype_name()) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'");
+ if (!_compare_datatypes(p_type, p_struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
return nullptr;
}
@@ -3546,50 +3860,73 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//make sure void is not used in expression
_set_error("Void value not allowed in Expression");
return nullptr;
- } else if (is_token_nonvoid_datatype(tk.type)) {
- //basic type constructor
+ } else if (is_token_nonvoid_datatype(tk.type) || tk.type == TK_CURLY_BRACKET_OPEN) {
+ if (tk.type == TK_CURLY_BRACKET_OPEN) {
+ //array constructor
- OperatorNode *func = alloc_node<OperatorNode>();
- func->op = OP_CONSTRUCT;
+ _set_tkpos(prepos);
+ expr = _parse_array_constructor(p_block, p_function_info);
+ } else {
+ DataType datatype;
+ DataPrecision precision;
+ bool precision_defined = false;
- if (is_token_precision(tk.type)) {
- func->return_precision_cache = get_token_precision(tk.type);
+ if (is_token_precision(tk.type)) {
+ precision = get_token_precision(tk.type);
+ precision_defined = true;
+ tk = _get_token();
+ }
+
+ datatype = get_token_datatype(tk.type);
tk = _get_token();
- }
- VariableNode *funcname = alloc_node<VariableNode>();
- funcname->name = get_datatype_name(get_token_datatype(tk.type));
- func->arguments.push_back(funcname);
+ if (tk.type == TK_BRACKET_OPEN) {
+ //array constructor
- tk = _get_token();
- if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after type name");
- return nullptr;
- }
+ _set_tkpos(prepos);
+ expr = _parse_array_constructor(p_block, p_function_info);
+ } else {
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after type name");
+ return nullptr;
+ }
+ //basic type constructor
- int carg = -1;
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op = OP_CONSTRUCT;
- bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
+ if (precision_defined) {
+ func->return_precision_cache = precision;
+ }
- if (carg >= 0) {
- completion_type = COMPLETION_CALL_ARGUMENTS;
- completion_line = tk_line;
- completion_block = p_block;
- completion_function = funcname->name;
- completion_argument = carg;
- }
+ VariableNode *funcname = alloc_node<VariableNode>();
+ funcname->name = get_datatype_name(datatype);
+ func->arguments.push_back(funcname);
- if (!ok) {
- return nullptr;
- }
+ int carg = -1;
- if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) {
- _set_error("No matching constructor found for: '" + String(funcname->name) + "'");
- return nullptr;
- }
+ bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
+
+ if (carg >= 0) {
+ completion_type = COMPLETION_CALL_ARGUMENTS;
+ completion_line = tk_line;
+ completion_block = p_block;
+ completion_function = funcname->name;
+ completion_argument = carg;
+ }
- expr = _reduce_expression(p_block, func);
+ if (!ok) {
+ return nullptr;
+ }
+
+ if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) {
+ _set_error("No matching constructor found for: '" + String(funcname->name) + "'");
+ return nullptr;
+ }
+ expr = _reduce_expression(p_block, func);
+ }
+ }
} else if (tk.type == TK_IDENTIFIER) {
_set_tkpos(prepos);
@@ -3602,6 +3939,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (shader->structs.has(identifier)) {
pstruct = shader->structs[identifier].shader_struct;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(identifier)) {
+ used_structs[identifier].used = true;
+ }
+#endif // DEBUG_ENABLED
struct_init = true;
}
@@ -3632,11 +3974,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!nexpr) {
return nullptr;
}
- Node *node = pstruct->members[i];
if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) {
- String type_name = nexpr->get_datatype() == TYPE_STRUCT ? nexpr->get_datatype_name() : get_datatype_name(nexpr->get_datatype());
- String type_name2 = node->get_datatype() == TYPE_STRUCT ? node->get_datatype_name() : get_datatype_name(node->get_datatype());
- _set_error("Invalid assignment of '" + type_name + "' to '" + type_name2 + "'");
return nullptr;
}
}
@@ -3658,7 +3996,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = func;
- } else { //a function
+ } else { //a function call
const StringName &name = identifier;
@@ -3670,7 +4008,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
int carg = -1;
+ pass_array = true;
bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
+ pass_array = false;
// Check if block has a variable with the same name as function to prevent shader crash.
ShaderLanguage::BlockNode *bnode = p_block;
@@ -3723,6 +4063,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
FunctionNode *call_function = shader->functions[function_index].function;
if (call_function) {
+ func->return_cache = call_function->get_datatype();
+ func->struct_name = call_function->get_datatype_name();
+ func->return_array_size = call_function->get_array_size();
+
//get current base function
FunctionNode *base_function = nullptr;
{
@@ -3825,11 +4169,17 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
}
expr = func;
+#ifdef DEBUG_ENABLED
+ if (check_warnings) {
+ _parse_used_identifier(name, IdentifierType::IDENTIFIER_FUNCTION);
+ }
+#endif // DEBUG_ENABLED
}
} else {
//an identifier
- last_const = false;
+ last_name = identifier;
+ last_type = IDENTIFIER_MAX;
_set_tkpos(pos);
DataType data_type;
@@ -3874,12 +4224,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
}
}
- last_const = is_const;
if (ident_type == IDENTIFIER_FUNCTION) {
_set_error("Can't use function as identifier: " + String(identifier));
return nullptr;
}
+ if (is_const) {
+ last_type = IDENTIFIER_CONSTANT;
+ } else {
+ last_type = ident_type;
+ }
}
Node *index_expression = nullptr;
@@ -3887,60 +4241,61 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *assign_expression = nullptr;
if (array_size > 0) {
- tk = _get_token();
-
- if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) {
- _set_error("Expected '[','.' or '='");
- return nullptr;
- }
+ if (!pass_array) {
+ tk = _get_token();
- if (tk.type == TK_OP_ASSIGN) {
- if (is_const) {
- _set_error("Constants cannot be modified.");
+ if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) {
+ _set_error("Expected '[','.' or '='");
return nullptr;
}
- assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
- if (!assign_expression) {
- return nullptr;
- }
- } else if (tk.type == TK_PERIOD) {
- completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
- call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
- if (!call_expression) {
- return nullptr;
- }
- data_type = call_expression->get_datatype();
- } else { // indexing
- index_expression = _parse_and_reduce_expression(p_block, p_function_info);
- if (!index_expression) {
- return nullptr;
- }
+ if (tk.type == TK_OP_ASSIGN) {
+ if (is_const) {
+ _set_error("Constants cannot be modified.");
+ return nullptr;
+ }
+ assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
+ if (!assign_expression) {
+ return nullptr;
+ }
+ } else if (tk.type == TK_PERIOD) {
+ completion_class = TAG_ARRAY;
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (!call_expression) {
+ return nullptr;
+ }
+ data_type = call_expression->get_datatype();
+ } else { // indexing
+ index_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!index_expression) {
+ return nullptr;
+ }
- if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
- _set_error("Only integer expressions are allowed for indexing");
- return nullptr;
- }
+ if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
+ _set_error("Only integer expressions are allowed for indexing");
+ return nullptr;
+ }
- if (index_expression->type == Node::TYPE_CONSTANT) {
- ConstantNode *cnode = (ConstantNode *)index_expression;
- if (cnode) {
- if (!cnode->values.is_empty()) {
- int value = cnode->values[0].sint;
- if (value < 0 || value >= array_size) {
- _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
- return nullptr;
+ if (index_expression->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cnode = (ConstantNode *)index_expression;
+ if (cnode) {
+ if (!cnode->values.is_empty()) {
+ int value = cnode->values[0].sint;
+ if (value < 0 || value >= array_size) {
+ _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
+ return nullptr;
+ }
}
}
}
- }
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return nullptr;
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return nullptr;
+ }
}
}
@@ -3952,8 +4307,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
arrname->call_expression = call_expression;
arrname->assign_expression = assign_expression;
arrname->is_const = is_const;
+ arrname->array_size = array_size;
expr = arrname;
-
} else {
VariableNode *varname = alloc_node<VariableNode>();
varname->name = identifier;
@@ -3962,6 +4317,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
varname->struct_name = struct_name;
expr = varname;
}
+#ifdef DEBUG_ENABLED
+ if (check_warnings) {
+ _parse_used_identifier(identifier, ident_type);
+ }
+#endif // DEBUG_ENABLED
}
} else if (tk.type == TK_OP_ADD) {
continue; //this one does nothing
@@ -4012,6 +4372,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
DataType dt = expr->get_datatype();
String st = expr->get_datatype_name();
+ if (!expr->is_indexed() && expr->get_array_size() > 0) {
+ completion_class = TAG_ARRAY;
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (!call_expression) {
+ return nullptr;
+ }
+ expr = call_expression;
+ break;
+ }
+
StringName identifier;
if (_get_completable_identifier(p_block, dt == TYPE_STRUCT ? COMPLETION_STRUCT : COMPLETION_INDEX, identifier)) {
if (dt == TYPE_STRUCT) {
@@ -4288,10 +4660,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
mn->has_swizzling_duplicates = repeated;
if (array_size > 0) {
+ TkPos prev_pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
- if (last_const) {
- last_const = false;
+ if (last_type == IDENTIFIER_CONSTANT) {
_set_error("Constants cannot be modified.");
return nullptr;
}
@@ -4301,8 +4673,15 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
mn->assign_expression = assign_expression;
} else if (tk.type == TK_PERIOD) {
- _set_error("Nested array length() is not yet implemented");
- return nullptr;
+ completion_class = TAG_ARRAY;
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (!call_expression) {
+ return nullptr;
+ }
+ mn->datatype = call_expression->get_datatype();
+ mn->call_expression = call_expression;
} else if (tk.type == TK_BRACKET_OPEN) {
Node *index_expression = _parse_and_reduce_expression(p_block, p_function_info);
if (!index_expression) {
@@ -4333,13 +4712,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
mn->index_expression = index_expression;
-
} else {
- _set_error("Expected '[','.' or '='");
- return nullptr;
+ if (!pass_array) {
+ _set_error("Expected '[','.' or '='");
+ return nullptr;
+ }
+ _set_tkpos(prev_pos);
}
}
-
expr = mn;
//todo
@@ -4364,117 +4744,130 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
DataType member_type = TYPE_VOID;
+ String member_struct_name;
- switch (expr->get_datatype()) {
- case TYPE_BVEC2:
- case TYPE_VEC2:
- case TYPE_IVEC2:
- case TYPE_UVEC2:
- case TYPE_MAT2:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 2) {
- _set_error("Index out of range (0-1)");
- return nullptr;
+ if (expr->get_array_size() > 0) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= (uint32_t)expr->get_array_size()) {
+ _set_error(vformat("Index [%s] out of range [%s..%s]", index_constant, 0, expr->get_array_size() - 1));
+ return nullptr;
+ }
+ member_type = expr->get_datatype();
+ if (member_type == TYPE_STRUCT) {
+ member_struct_name = expr->get_datatype_name();
+ }
+ } else {
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC2:
+ case TYPE_VEC2:
+ case TYPE_IVEC2:
+ case TYPE_UVEC2:
+ case TYPE_MAT2:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 2) {
+ _set_error("Index out of range (0-1)");
+ return nullptr;
+ }
}
- }
- switch (expr->get_datatype()) {
- case TYPE_BVEC2:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC2:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC2:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC2:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT2:
- member_type = TYPE_VEC2;
- break;
- default:
- break;
- }
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC2:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC2:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC2:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC2:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT2:
+ member_type = TYPE_VEC2;
+ break;
+ default:
+ break;
+ }
- break;
- case TYPE_BVEC3:
- case TYPE_VEC3:
- case TYPE_IVEC3:
- case TYPE_UVEC3:
- case TYPE_MAT3:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 3) {
- _set_error("Index out of range (0-2)");
- return nullptr;
+ break;
+ case TYPE_BVEC3:
+ case TYPE_VEC3:
+ case TYPE_IVEC3:
+ case TYPE_UVEC3:
+ case TYPE_MAT3:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 3) {
+ _set_error("Index out of range (0-2)");
+ return nullptr;
+ }
}
- }
- switch (expr->get_datatype()) {
- case TYPE_BVEC3:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC3:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC3:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC3:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT3:
- member_type = TYPE_VEC3;
- break;
- default:
- break;
- }
- break;
- case TYPE_BVEC4:
- case TYPE_VEC4:
- case TYPE_IVEC4:
- case TYPE_UVEC4:
- case TYPE_MAT4:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 4) {
- _set_error("Index out of range (0-3)");
- return nullptr;
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC3:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC3:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC3:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC3:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT3:
+ member_type = TYPE_VEC3;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TYPE_BVEC4:
+ case TYPE_VEC4:
+ case TYPE_IVEC4:
+ case TYPE_UVEC4:
+ case TYPE_MAT4:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 4) {
+ _set_error("Index out of range (0-3)");
+ return nullptr;
+ }
}
- }
- switch (expr->get_datatype()) {
- case TYPE_BVEC4:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC4:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC4:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC4:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT4:
- member_type = TYPE_VEC4;
- break;
- default:
- break;
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC4:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC4:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC4:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC4:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT4:
+ member_type = TYPE_VEC4;
+ break;
+ default:
+ break;
+ }
+ break;
+ default: {
+ _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed");
+ return nullptr;
}
- break;
- default: {
- _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed");
- return nullptr;
}
}
-
OperatorNode *op = alloc_node<OperatorNode>();
op->op = OP_INDEX;
op->return_cache = member_type;
+ op->struct_name = member_struct_name;
op->arguments.push_back(expr);
op->arguments.push_back(index);
expr = op;
@@ -4490,7 +4883,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
op->op = tk.type == TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT;
op->arguments.push_back(expr);
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
_set_error("Invalid base type for increment/decrement operator");
return nullptr;
}
@@ -4641,9 +5034,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
bool unary = false;
bool ternary = false;
+ Operator op = expression[i].op;
int priority;
- switch (expression[i].op) {
+ switch (op) {
case OP_EQUAL:
priority = 8;
break;
@@ -4764,6 +5158,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_V(nullptr); //unexpected operator
}
+#if DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::FLOAT_COMPARISON_FLAG) && (op == OP_EQUAL || op == OP_NOT_EQUAL) && expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT) {
+ _add_line_warning(ShaderWarning::FLOAT_COMPARISON);
+ }
+#endif // DEBUG_ENABLED
+
if (priority < min_priority) {
// < is used for left to right (default)
// <= is used for right to left
@@ -4801,13 +5201,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.write[i].is_op = false;
expression.write[i].node = op;
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int j = 0; j < op->arguments.size(); j++) {
if (j > 0) {
at += " and ";
}
at += get_datatype_name(op->arguments[j]->get_datatype());
+ if (!op->arguments[j]->is_indexed() && op->arguments[j]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[j]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
@@ -4834,13 +5239,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.write[next_op - 1].is_op = false;
expression.write[next_op - 1].node = op;
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int i = 0; i < op->arguments.size(); i++) {
if (i > 0) {
at += " and ";
}
at += get_datatype_name(op->arguments[i]->get_datatype());
+ if (!op->arguments[i]->is_indexed() && op->arguments[i]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[i]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid argument to ternary ?: operator: " + at);
return nullptr;
@@ -4887,7 +5297,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//replace all 3 nodes by this operator and make it an expression
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int i = 0; i < op->arguments.size(); i++) {
if (i > 0) {
@@ -4898,6 +5308,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else {
at += get_datatype_name(op->arguments[i]->get_datatype());
}
+ if (!op->arguments[i]->is_indexed() && op->arguments[i]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[i]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid arguments to operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
@@ -5154,6 +5569,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ArrayDeclarationNode::Declaration decl;
decl.name = name;
decl.size = 0U;
+ decl.single_expression = false;
pos = _get_tkpos();
tk = _get_token();
@@ -5220,179 +5636,205 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
+ TkPos prev_pos = _get_tkpos();
tk = _get_token();
- if (tk.type != TK_CURLY_BRACKET_OPEN) {
- if (unknown_size) {
- _set_error("Expected '{'");
- return ERR_PARSE_ERROR;
- }
-
- full_def = true;
+ if (tk.type == TK_IDENTIFIER) { // a function call array initialization
+ _set_tkpos(prev_pos);
+ pass_array = true;
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ pass_array = false;
- DataPrecision precision2 = PRECISION_DEFAULT;
- if (is_token_precision(tk.type)) {
- precision2 = get_token_precision(tk.type);
- tk = _get_token();
- if (shader->structs.has(tk.text)) {
- _set_error("Precision modifier cannot be used on structs.");
- return ERR_PARSE_ERROR;
+ if (!n) {
+ _set_error("Expected correct array initializer!");
+ return ERR_PARSE_ERROR;
+ } else {
+ if (unknown_size) {
+ decl.size = n->get_array_size();
+ var.array_size = n->get_array_size();
}
- if (!is_token_nonvoid_datatype(tk.type)) {
- _set_error("Expected datatype after precision");
+
+ if (!_compare_datatypes(var.type, var.struct_name, var.array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
return ERR_PARSE_ERROR;
}
- }
- DataType type2;
- StringName struct_name2 = "";
+ decl.single_expression = true;
+ decl.initializer.push_back(n);
+ }
- if (shader->structs.has(tk.text)) {
- type2 = TYPE_STRUCT;
- struct_name2 = tk.text;
- } else {
- if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for array");
+ tk = _get_token();
+ } else {
+ if (tk.type != TK_CURLY_BRACKET_OPEN) {
+ if (unknown_size) {
+ _set_error("Expected '{'");
return ERR_PARSE_ERROR;
}
- type2 = get_token_datatype(tk.type);
- }
- int array_size2 = 0;
+ full_def = true;
- tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos2 = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- array_size2 = var.array_size;
+ DataPrecision precision2 = PRECISION_DEFAULT;
+ if (is_token_precision(tk.type)) {
+ precision2 = get_token_precision(tk.type);
tk = _get_token();
- } else {
- _set_tkpos(pos2);
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
+ if (shader->structs.has(tk.text)) {
+ _set_error("Precision modifier cannot be used on structs.");
+ return ERR_PARSE_ERROR;
+ }
+ if (!is_token_nonvoid_datatype(tk.type)) {
+ _set_error("Expected datatype after precision");
return ERR_PARSE_ERROR;
}
+ }
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size2 = cnode->values[0].sint;
- if (array_size2 <= 0) {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected single integer constant > 0");
+ DataType type2;
+ StringName struct_name2 = "";
+
+ if (shader->structs.has(tk.text)) {
+ type2 = TYPE_STRUCT;
+ struct_name2 = tk.text;
+ } else {
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for array");
return ERR_PARSE_ERROR;
}
+ type2 = get_token_datatype(tk.type);
+ }
+ int array_size2 = 0;
+
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ TkPos pos2 = _get_tkpos();
tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
+ if (tk.type == TK_BRACKET_CLOSE) {
+ array_size2 = var.array_size;
+ tk = _get_token();
} else {
+ _set_tkpos(pos2);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size2 = cnode->values[0].sint;
+ if (array_size2 <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ } else {
+ tk = _get_token();
+ }
}
- }
- } else {
- _set_error("Expected '['");
- return ERR_PARSE_ERROR;
- }
-
- if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) {
- String error_str = "Cannot convert from '";
- if (precision2 != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision2);
- error_str += " ";
- }
- if (type2 == TYPE_STRUCT) {
- error_str += struct_name2;
} else {
- error_str += get_datatype_name(type2);
- }
- error_str += "[";
- error_str += itos(array_size2);
- error_str += "]'";
- error_str += " to '";
- if (precision != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision);
- error_str += " ";
+ _set_error("Expected '['");
+ return ERR_PARSE_ERROR;
}
- if (type == TYPE_STRUCT) {
- error_str += struct_name;
- } else {
- error_str += get_datatype_name(type);
+
+ if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) {
+ String error_str = "Cannot convert from '";
+ if (precision2 != PRECISION_DEFAULT) {
+ error_str += get_precision_name(precision2);
+ error_str += " ";
+ }
+ if (type2 == TYPE_STRUCT) {
+ error_str += struct_name2;
+ } else {
+ error_str += get_datatype_name(type2);
+ }
+ error_str += "[";
+ error_str += itos(array_size2);
+ error_str += "]'";
+ error_str += " to '";
+ if (precision != PRECISION_DEFAULT) {
+ error_str += get_precision_name(precision);
+ error_str += " ";
+ }
+ if (type == TYPE_STRUCT) {
+ error_str += struct_name;
+ } else {
+ error_str += get_datatype_name(type);
+ }
+ error_str += "[";
+ error_str += itos(var.array_size);
+ error_str += "]'";
+ _set_error(error_str);
+ return ERR_PARSE_ERROR;
}
- error_str += "[";
- error_str += itos(var.array_size);
- error_str += "]'";
- _set_error(error_str);
- return ERR_PARSE_ERROR;
}
- }
- bool curly = tk.type == TK_CURLY_BRACKET_OPEN;
+ bool curly = tk.type == TK_CURLY_BRACKET_OPEN;
- if (unknown_size) {
- if (!curly) {
- _set_error("Expected '{'");
- return ERR_PARSE_ERROR;
- }
- } else {
- if (full_def) {
- if (curly) {
- _set_error("Expected '('");
+ if (unknown_size) {
+ if (!curly) {
+ _set_error("Expected '{'");
return ERR_PARSE_ERROR;
}
+ } else {
+ if (full_def) {
+ if (curly) {
+ _set_error("Expected '('");
+ return ERR_PARSE_ERROR;
+ }
+ }
}
- }
- if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
- while (true) {
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n) {
- return ERR_PARSE_ERROR;
- }
+ if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
+ while (true) {
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n) {
+ return ERR_PARSE_ERROR;
+ }
- if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
- _set_error("Expected constant expression");
- return ERR_PARSE_ERROR;
- }
+ if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ _set_error("Expected constant expression");
+ return ERR_PARSE_ERROR;
+ }
- if (var.type != n->get_datatype() || struct_name != n->get_datatype_name()) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? struct_name : get_datatype_name(var.type)) + "'");
- return ERR_PARSE_ERROR;
- }
+ if (!_compare_datatypes(var.type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
+ return ERR_PARSE_ERROR;
+ }
- tk = _get_token();
- if (tk.type == TK_COMMA) {
- decl.initializer.push_back(n);
- continue;
- } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
- decl.initializer.push_back(n);
- break;
- } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
- decl.initializer.push_back(n);
- break;
- } else {
- if (curly) {
- _set_error("Expected '}' or ','");
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ decl.initializer.push_back(n);
+ continue;
+ } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
+ decl.initializer.push_back(n);
+ break;
+ } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ decl.initializer.push_back(n);
+ break;
} else {
- _set_error("Expected ')' or ','");
+ if (curly) {
+ _set_error("Expected '}' or ','");
+ } else {
+ _set_error("Expected ')' or ','");
+ }
+ return ERR_PARSE_ERROR;
}
+ }
+ if (unknown_size) {
+ decl.size = decl.initializer.size();
+ var.array_size = decl.initializer.size();
+ } else if (decl.initializer.size() != var.array_size) {
+ _set_error("Array size mismatch");
return ERR_PARSE_ERROR;
}
+ tk = _get_token();
}
- if (unknown_size) {
- decl.size = decl.initializer.size();
- var.array_size = decl.initializer.size();
- } else if (decl.initializer.size() != var.array_size) {
- _set_error("Array size mismatch");
- return ERR_PARSE_ERROR;
- }
- tk = _get_token();
}
} else {
if (unknown_size) {
@@ -5445,8 +5887,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
- if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'");
+ if (!_compare_datatypes(var.type, var.struct_name, var.array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
return ERR_PARSE_ERROR;
}
tk = _get_token();
@@ -5476,7 +5917,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
p_block->statements.push_back(vardecl);
p_block->variables[name] = var;
-
if (tk.type == TK_COMMA) {
if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) {
_set_error("Multiple declarations in 'for' loop are not implemented yet.");
@@ -5908,6 +6348,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
String return_struct_name = String(b->parent_function->return_struct_name);
+ String array_size_string;
+
+ if (b->parent_function->return_array_size > 0) {
+ array_size_string = "[" + itos(b->parent_function->return_array_size) + "]";
+ }
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
flow->flow_op = FLOW_OP_RETURN;
@@ -5917,18 +6362,21 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_SEMICOLON) {
//all is good
if (b->parent_function->return_type != TYPE_VOID) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + "'");
+ _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
return ERR_PARSE_ERROR;
}
} else {
_set_tkpos(pos); //rollback, wants expression
+
+ pass_array = true;
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
if (!expr) {
return ERR_PARSE_ERROR;
}
+ pass_array = false;
- if (b->parent_function->return_type != expr->get_datatype() || return_struct_name != expr->get_datatype_name()) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + "'");
+ if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) {
+ _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
return ERR_PARSE_ERROR;
}
@@ -6306,7 +6754,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
shader->structs[st.name] = st;
shader->vstructs.push_back(st); // struct's order is important!
-
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG)) {
+ used_structs.insert(st.name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
} break;
case TK_GLOBAL: {
tk = _get_token();
@@ -6653,6 +7105,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
shader->uniforms[name] = uniform2;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_UNIFORM_FLAG)) {
+ used_uniforms.insert(name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
+
//reset scope for next uniform
uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
@@ -6696,6 +7154,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
shader->varyings[name] = varying;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_VARYING_FLAG)) {
+ used_varyings.insert(name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
}
} break;
@@ -6708,6 +7171,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataPrecision precision = PRECISION_DEFAULT;
DataType type;
StringName name;
+ int return_array_size = 0;
if (tk.type == TK_CONST) {
is_constant = true;
@@ -6745,10 +7209,33 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
TkPos prev_pos = _get_tkpos();
tk = _get_token();
+
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Cannot use arrays as return types");
- return ERR_PARSE_ERROR;
+ bool error = false;
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT) {
+ return_array_size = (int)tk.constant;
+ if (return_array_size > 0) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ prev_pos = _get_tkpos();
}
+
_set_tkpos(prev_pos);
_get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name);
@@ -6962,8 +7449,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (constant.type != n->get_datatype() || n->get_datatype_name() != struct_name) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (is_struct ? String(struct_name) : get_datatype_name(constant.type)) + "'");
+ if (!_compare_datatypes(constant.type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
return ERR_PARSE_ERROR;
}
@@ -7024,8 +7510,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
- if (type != expr->get_datatype() || expr->get_datatype_name() != struct_name) {
- _set_error("Invalid assignment of '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' to '" + (is_struct ? String(struct_name) : get_datatype_name(type)) + "'");
+ if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) {
return ERR_PARSE_ERROR;
}
}
@@ -7042,6 +7527,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
shader->constants[name] = constant;
shader->vconstants.push_back(constant);
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_CONSTANT_FLAG)) {
+ used_constants.insert(name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
if (tk.type == TK_COMMA) {
tk = _get_token();
@@ -7100,9 +7590,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
func_node->return_type = type;
func_node->return_struct_name = struct_name;
func_node->return_precision = precision;
+ func_node->return_array_size = return_array_size;
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
+ } else {
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_FUNCTION_FLAG)) {
+ used_functions.insert(name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
}
func_node->body = alloc_node<BlockNode>();
@@ -7147,6 +7644,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
StringName param_struct_name;
DataPrecision pprecision = PRECISION_DEFAULT;
bool use_precision = false;
+ int array_size = 0;
if (is_token_precision(tk.type)) {
pprecision = get_token_precision(tk.type);
@@ -7193,8 +7691,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Arrays as parameters are not implemented yet");
- return ERR_PARSE_ERROR;
+ bool error = false;
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT) {
+ array_size = (int)tk.constant;
+
+ if (array_size > 0) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
}
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier for argument name");
@@ -7228,14 +7747,41 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
arg.tex_argument_repeat = REPEAT_DEFAULT;
arg.is_const = is_const;
- func_node->arguments.push_back(arg);
-
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Arrays as parameters are not implemented yet");
- return ERR_PARSE_ERROR;
+ if (array_size > 0) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
+ bool error = false;
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT) {
+ array_size = (int)tk.constant;
+
+ if (array_size > 0) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
}
+ arg.array_size = array_size;
+ func_node->arguments.push_back(arg);
+
if (tk.type == TK_COMMA) {
tk = _get_token();
//do none and go on
@@ -7436,6 +7982,33 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
return String();
}
+#ifdef DEBUG_ENABLED
+void ShaderLanguage::_check_warning_accums() {
+ for (Map<ShaderWarning::Code, Map<StringName, Usage> *>::Element *E = warnings_check_map.front(); E; E = E->next()) {
+ for (const Map<StringName, Usage>::Element *U = (*E->get()).front(); U; U = U->next()) {
+ if (!U->get().used) {
+ _add_warning(E->key(), U->get().decl_line, U->key());
+ }
+ }
+ }
+}
+List<ShaderWarning>::Element *ShaderLanguage::get_warnings_ptr() {
+ return warnings.front();
+}
+void ShaderLanguage::enable_warning_checking(bool p_enabled) {
+ check_warnings = p_enabled;
+}
+bool ShaderLanguage::is_warning_checking_enabled() const {
+ return check_warnings;
+}
+void ShaderLanguage::set_warning_flags(uint32_t p_flags) {
+ warning_flags = p_flags;
+}
+uint32_t ShaderLanguage::get_warning_flags() const {
+ return warning_flags;
+}
+#endif // DEBUG_ENABLED
+
Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) {
clear();
@@ -7448,6 +8021,12 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi
shader = alloc_node<ShaderNode>();
Error err = _parse_shader(p_functions, p_render_modes, p_shader_types);
+#ifdef DEBUG_ENABLED
+ if (check_warnings) {
+ _check_warning_accums();
+ }
+#endif // DEBUG_ENABLED
+
if (err != OK) {
return err;
}
@@ -7625,6 +8204,13 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
String calltip;
calltip += get_datatype_name(shader->functions[i].function->return_type);
+
+ if (shader->functions[i].function->return_array_size > 0) {
+ calltip += "[";
+ calltip += itos(shader->functions[i].function->return_array_size);
+ calltip += "]";
+ }
+
calltip += " ";
calltip += shader->functions[i].name;
calltip += "(";
@@ -7656,6 +8242,12 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += " ";
calltip += shader->functions[i].function->arguments[j].name;
+ if (shader->functions[i].function->arguments[j].array_size > 0) {
+ calltip += "[";
+ calltip += itos(shader->functions[i].function->arguments[j].array_size);
+ calltip += "]";
+ }
+
if (j == completion_argument) {
calltip += char32_t(0xFFFF);
}
@@ -7857,6 +8449,14 @@ ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() {
ShaderLanguage::ShaderLanguage() {
nodes = nullptr;
completion_class = TAG_GLOBAL;
+
+#if DEBUG_ENABLED
+ warnings_check_map.insert(ShaderWarning::UNUSED_CONSTANT, &used_constants);
+ warnings_check_map.insert(ShaderWarning::UNUSED_FUNCTION, &used_functions);
+ warnings_check_map.insert(ShaderWarning::UNUSED_STRUCT, &used_structs);
+ warnings_check_map.insert(ShaderWarning::UNUSED_UNIFORM, &used_uniforms);
+ warnings_check_map.insert(ShaderWarning::UNUSED_VARYING, &used_varyings);
+#endif // DEBUG_ENABLED
}
ShaderLanguage::~ShaderLanguage() {
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index e00f4dce19..4120e04ee1 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -39,6 +39,10 @@
#include "core/typedefs.h"
#include "core/variant/variant.h"
+#ifdef DEBUG_ENABLED
+#include "shader_warnings.h"
+#endif // DEBUG_ENABLED
+
class ShaderLanguage {
public:
struct TkPos {
@@ -365,6 +369,8 @@ public:
virtual DataType get_datatype() const { return TYPE_VOID; }
virtual String get_datatype_name() const { return ""; }
+ virtual int get_array_size() const { return 0; }
+ virtual bool is_indexed() const { return false; }
Node(Type t) :
type(t) {}
@@ -384,11 +390,15 @@ public:
struct OperatorNode : public Node {
DataType return_cache = TYPE_VOID;
DataPrecision return_precision_cache = PRECISION_DEFAULT;
+ int return_array_size = 0;
Operator op = OP_EQUAL;
StringName struct_name;
Vector<Node *> arguments;
- virtual DataType get_datatype() const { return return_cache; }
- virtual String get_datatype_name() const { return String(struct_name); }
+
+ virtual DataType get_datatype() const override { return return_cache; }
+ virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual int get_array_size() const override { return return_array_size; }
+ virtual bool is_indexed() const override { return op == OP_INDEX; }
OperatorNode() :
Node(TYPE_OPERATOR) {}
@@ -398,10 +408,11 @@ public:
DataType datatype_cache = TYPE_VOID;
StringName name;
StringName struct_name;
- virtual DataType get_datatype() const { return datatype_cache; }
- virtual String get_datatype_name() const { return String(struct_name); }
bool is_const = false;
+ virtual DataType get_datatype() const override { return datatype_cache; }
+ virtual String get_datatype_name() const override { return String(struct_name); }
+
VariableNode() :
Node(TYPE_VARIABLE) {}
};
@@ -416,9 +427,9 @@ public:
StringName name;
Node *initializer;
};
-
Vector<Declaration> declarations;
- virtual DataType get_datatype() const { return datatype; }
+
+ virtual DataType get_datatype() const override { return datatype; }
VariableDeclarationNode() :
Node(TYPE_VARIABLE_DECLARATION) {}
@@ -432,9 +443,12 @@ public:
Node *call_expression = nullptr;
Node *assign_expression = nullptr;
bool is_const = false;
+ int array_size = 0;
- virtual DataType get_datatype() const { return datatype_cache; }
- virtual String get_datatype_name() const { return String(struct_name); }
+ virtual DataType get_datatype() const override { return datatype_cache; }
+ virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
+ virtual bool is_indexed() const override { return index_expression != nullptr; }
ArrayNode() :
Node(TYPE_ARRAY) {}
@@ -445,6 +459,10 @@ public:
String struct_name;
Vector<Node *> initializer;
+ virtual DataType get_datatype() const override { return datatype; }
+ virtual String get_datatype_name() const override { return struct_name; }
+ virtual int get_array_size() const override { return initializer.size(); }
+
ArrayConstructNode() :
Node(TYPE_ARRAY_CONSTRUCT) {}
};
@@ -460,10 +478,11 @@ public:
StringName name;
uint32_t size;
Vector<Node *> initializer;
+ bool single_expression;
};
-
Vector<Declaration> declarations;
- virtual DataType get_datatype() const { return datatype; }
+
+ virtual DataType get_datatype() const override { return datatype; }
ArrayDeclarationNode() :
Node(TYPE_ARRAY_DECLARATION) {}
@@ -483,8 +502,10 @@ public:
Vector<Value> values;
Vector<ArrayDeclarationNode::Declaration> array_declarations;
- virtual DataType get_datatype() const { return datatype; }
- virtual String get_datatype_name() const { return struct_name; }
+
+ virtual DataType get_datatype() const override { return datatype; }
+ virtual String get_datatype_name() const override { return struct_name; }
+ virtual int get_array_size() const override { return array_size; }
ConstantNode() :
Node(TYPE_CONSTANT) {}
@@ -546,10 +567,13 @@ public:
Node *owner = nullptr;
Node *index_expression = nullptr;
Node *assign_expression = nullptr;
+ Node *call_expression = nullptr;
bool has_swizzling_duplicates = false;
- virtual DataType get_datatype() const { return datatype; }
- virtual String get_datatype_name() const { return String(struct_name); }
+ virtual DataType get_datatype() const override { return datatype; }
+ virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual int get_array_size() const override { return array_size; }
+ virtual bool is_indexed() const override { return index_expression != nullptr || call_expression != nullptr; }
MemberNode() :
Node(TYPE_MEMBER) {}
@@ -575,6 +599,7 @@ public:
bool tex_builtin_check;
StringName tex_builtin;
bool is_const;
+ int array_size;
Map<StringName, Set<int>> tex_argument_connect;
};
@@ -583,10 +608,15 @@ public:
DataType return_type = TYPE_VOID;
StringName return_struct_name;
DataPrecision return_precision = PRECISION_DEFAULT;
+ int return_array_size = 0;
Vector<Argument> arguments;
BlockNode *body = nullptr;
bool can_discard = false;
+ virtual DataType get_datatype() const override { return return_type; }
+ virtual String get_datatype_name() const override { return String(return_struct_name); }
+ virtual int get_array_size() const override { return return_array_size; }
+
FunctionNode() :
Node(TYPE_FUNCTION) {}
};
@@ -802,12 +832,44 @@ private:
String error_str;
int error_line;
+#ifdef DEBUG_ENABLED
+ struct Usage {
+ int decl_line;
+ bool used = false;
+ Usage(int p_decl_line = -1) {
+ decl_line = p_decl_line;
+ }
+ };
+
+ Map<StringName, Usage> used_constants;
+ Map<StringName, Usage> used_varyings;
+ Map<StringName, Usage> used_uniforms;
+ Map<StringName, Usage> used_functions;
+ Map<StringName, Usage> used_structs;
+ Map<ShaderWarning::Code, Map<StringName, Usage> *> warnings_check_map;
+
+ List<ShaderWarning> warnings;
+
+ bool check_warnings = false;
+ uint32_t warning_flags;
+
+ void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "") {
+ warnings.push_back(ShaderWarning(p_code, tk_line, p_subject));
+ }
+ void _add_warning(ShaderWarning::Code p_code, int p_line, const StringName &p_subject = "") {
+ warnings.push_back(ShaderWarning(p_code, p_line, p_subject));
+ }
+ void _check_warning_accums();
+#endif // DEBUG_ENABLED
+
String code;
int char_idx;
int tk_line;
StringName current_function;
bool last_const = false;
+ bool pass_array = false;
+ StringName last_name;
VaryingFunctionNames varying_function_names;
@@ -848,12 +910,18 @@ private:
IDENTIFIER_LOCAL_VAR,
IDENTIFIER_BUILTIN_VAR,
IDENTIFIER_CONSTANT,
+ IDENTIFIER_MAX,
};
+ IdentifierType last_type = IDENTIFIER_MAX;
+
bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr, ConstantNode::Value *r_constant_value = nullptr);
+#ifdef DEBUG_ENABLED
+ void _parse_used_identifier(const StringName &p_identifier, IdentifierType p_type);
+#endif // DEBUG_ENABLED
bool _is_operator_assign(Operator p_op) const;
bool _validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message = nullptr);
- bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr);
+ bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr, int *r_ret_size = nullptr);
struct BuiltinFuncDef {
enum { MAX_ARGS = 5 };
@@ -884,7 +952,8 @@ private:
static const BuiltinFuncOutArgs builtin_func_out_args[];
Error _validate_datatype(DataType p_type);
- bool _compare_datatypes_in_nodes(Node *a, Node *b) const;
+ bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
+ bool _compare_datatypes_in_nodes(Node *a, Node *b);
bool _validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
bool _parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg = nullptr);
@@ -895,6 +964,7 @@ private:
bool _check_node_constness(const Node *p_node) const;
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
+ Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size);
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
@@ -909,6 +979,16 @@ private:
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
public:
+#ifdef DEBUG_ENABLED
+ List<ShaderWarning>::Element *get_warnings_ptr();
+
+ void enable_warning_checking(bool p_enabled);
+ bool is_warning_checking_enabled() const;
+
+ void set_warning_flags(uint32_t p_flags);
+ uint32_t get_warning_flags() const;
+#endif // DEBUG_ENABLED
+
//static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
void clear();
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 0bf68b9e0f..c4e7511374 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "shader_types.h"
+#include "core/math/math_defs.h"
const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) {
return shader_modes[p_mode].functions;
@@ -54,6 +55,9 @@ ShaderTypes::ShaderTypes() {
/*************** SPATIAL ***********************/
shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
@@ -88,6 +92,10 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
+
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = constt(ShaderLanguage::TYPE_BOOL);
@@ -120,13 +128,17 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_ROUGHNESS_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_ROUGHNESS_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
+
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
@@ -200,7 +212,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert");
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_oren_nayar");
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_burley");
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_toon");
@@ -227,6 +238,9 @@ ShaderTypes::ShaderTypes() {
/************ CANVAS ITEM **************************/
shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
@@ -317,6 +331,9 @@ ShaderTypes::ShaderTypes() {
/************ PARTICLES **************************/
shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3;
@@ -381,6 +398,9 @@ ShaderTypes::ShaderTypes() {
/************ SKY **************************/
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp
new file mode 100644
index 0000000000..aa11b4e397
--- /dev/null
+++ b/servers/rendering/shader_warnings.cpp
@@ -0,0 +1,131 @@
+/*************************************************************************/
+/* shader_warnings.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "shader_warnings.h"
+#include "core/variant/variant.h"
+
+#ifdef DEBUG_ENABLED
+
+ShaderWarning::Code ShaderWarning::get_code() const {
+ return code;
+}
+
+int ShaderWarning::get_line() const {
+ return line;
+}
+
+const StringName &ShaderWarning::get_subject() const {
+ return subject;
+}
+
+String ShaderWarning::get_message() const {
+ switch (code) {
+ case FLOAT_COMPARISON:
+ return vformat("Direct floating-point comparison (this may not evaluate to `true` as you expect). Instead, use `abs(a - b) < 0.0001` for an approximate but predictable comparison.");
+ case UNUSED_CONSTANT:
+ return vformat("The const '%s' is declared but never used.", subject);
+ case UNUSED_FUNCTION:
+ return vformat("The function '%s' is declared but never used.", subject);
+ case UNUSED_STRUCT:
+ return vformat("The struct '%s' is declared but never used.", subject);
+ case UNUSED_UNIFORM:
+ return vformat("The uniform '%s' is declared but never used.", subject);
+ case UNUSED_VARYING:
+ return vformat("The varying '%s' is declared but never used.", subject);
+ default:
+ break;
+ }
+ return String();
+}
+
+String ShaderWarning::get_name() const {
+ return get_name_from_code(code);
+}
+
+String ShaderWarning::get_name_from_code(Code p_code) {
+ ERR_FAIL_INDEX_V(p_code, WARNING_MAX, String());
+
+ static const char *names[] = {
+ "FLOAT_COMPARISON",
+ "UNUSED_CONSTANT",
+ "UNUSED_FUNCTION",
+ "UNUSED_STRUCT",
+ "UNUSED_UNIFORM",
+ "UNUSED_VARYING",
+ };
+
+ static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
+
+ return names[(int)p_code];
+}
+
+ShaderWarning::Code ShaderWarning::get_code_from_name(const String &p_name) {
+ for (int i = 0; i < WARNING_MAX; i++) {
+ if (get_name_from_code((Code)i) == p_name) {
+ return (Code)i;
+ }
+ }
+
+ ERR_FAIL_V_MSG(WARNING_MAX, "Invalid shader warning name: " + p_name);
+}
+
+static Map<int, uint32_t> *code_to_flags_map = nullptr;
+
+static void init_code_to_flags_map() {
+ code_to_flags_map = memnew((Map<int, uint32_t>));
+ code_to_flags_map->insert(ShaderWarning::FLOAT_COMPARISON, ShaderWarning::FLOAT_COMPARISON_FLAG);
+ code_to_flags_map->insert(ShaderWarning::UNUSED_CONSTANT, ShaderWarning::UNUSED_CONSTANT_FLAG);
+ code_to_flags_map->insert(ShaderWarning::UNUSED_FUNCTION, ShaderWarning::UNUSED_FUNCTION_FLAG);
+ code_to_flags_map->insert(ShaderWarning::UNUSED_STRUCT, ShaderWarning::UNUSED_STRUCT_FLAG);
+ code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG);
+ code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG);
+}
+
+ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) {
+ uint32_t result = 0U;
+
+ if (code_to_flags_map == nullptr) {
+ init_code_to_flags_map();
+ }
+
+ for (Map<Code, bool>::Element *E = p_map.front(); E; E = E->next()) {
+ if (E->get()) {
+ ERR_FAIL_COND_V(!code_to_flags_map->has((int)E->key()), ShaderWarning::NONE_FLAG);
+ result |= (*code_to_flags_map)[(int)E->key()];
+ }
+ }
+ return (CodeFlags)result;
+}
+
+ShaderWarning::ShaderWarning(Code p_code, int p_line, const StringName &p_subject) :
+ code(p_code), line(p_line), subject(p_subject) {
+}
+
+#endif // DEBUG_ENABLED
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
new file mode 100644
index 0000000000..c40aeefa2d
--- /dev/null
+++ b/servers/rendering/shader_warnings.h
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* shader_warnings.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SHADER_WARNINGS
+#define SHADER_WARNINGS
+
+#ifdef DEBUG_ENABLED
+
+#include "core/string/string_name.h"
+#include "core/templates/list.h"
+#include "core/templates/map.h"
+
+class ShaderWarning {
+public:
+ enum Code {
+ FLOAT_COMPARISON,
+ UNUSED_CONSTANT,
+ UNUSED_FUNCTION,
+ UNUSED_STRUCT,
+ UNUSED_UNIFORM,
+ UNUSED_VARYING,
+ WARNING_MAX,
+ };
+
+ enum CodeFlags : uint32_t {
+ NONE_FLAG = 0U,
+ FLOAT_COMPARISON_FLAG = 1U,
+ UNUSED_CONSTANT_FLAG = 2U,
+ UNUSED_FUNCTION_FLAG = 4U,
+ UNUSED_STRUCT_FLAG = 8U,
+ UNUSED_UNIFORM_FLAG = 16U,
+ UNUSED_VARYING_FLAG = 32U,
+ };
+
+private:
+ Code code;
+ int line;
+ StringName subject;
+
+public:
+ Code get_code() const;
+ int get_line() const;
+ const StringName &get_subject() const;
+ String get_message() const;
+ String get_name() const;
+
+ static String get_name_from_code(Code p_code);
+ static Code get_code_from_name(const String &p_name);
+ static CodeFlags get_flags_from_codemap(const Map<Code, bool> &p_map);
+
+ ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "");
+};
+
+#endif // DEBUG_ENABLED
+
+#endif // SHADER_WARNINGS
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 49990407e3..f25f255321 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -422,7 +422,9 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
- value |= CLAMP(int((src[i * 4 + 3] * 0.5 + 0.5) * 1023.0), 0, 1023) << 30;
+ if (src[i * 4 + 3] > 0) {
+ value |= 3 << 30;
+ }
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
}
@@ -873,10 +875,10 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
} else if (i == RS::ARRAY_BONES) {
switch (p_arrays[i].get_type()) {
case Variant::PACKED_INT32_ARRAY: {
- Vector<Vector3> vertexes = p_arrays[RS::ARRAY_VERTEX];
+ Vector<Vector3> vertices = p_arrays[RS::ARRAY_VERTEX];
Vector<int32_t> bones = p_arrays[i];
int32_t bone_8_group_count = bones.size() / (ARRAY_WEIGHTS_SIZE * 2);
- int32_t vertex_count = vertexes.size();
+ int32_t vertex_count = vertices.size();
if (vertex_count == bone_8_group_count) {
format |= RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
}
@@ -1569,32 +1571,32 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask);
#ifndef _MSC_VER
-#warning TODO all giprobe methods need re-binding
+#warning TODO all voxel_gi methods need re-binding
#endif
#if 0
- ClassDB::bind_method(D_METHOD("gi_probe_create"), &RenderingServer::gi_probe_create);
- ClassDB::bind_method(D_METHOD("gi_probe_set_bounds", "probe", "bounds"), &RenderingServer::gi_probe_set_bounds);
- ClassDB::bind_method(D_METHOD("gi_probe_get_bounds", "probe"), &RenderingServer::gi_probe_get_bounds);
- ClassDB::bind_method(D_METHOD("gi_probe_set_cell_size", "probe", "range"), &RenderingServer::gi_probe_set_cell_size);
- ClassDB::bind_method(D_METHOD("gi_probe_get_cell_size", "probe"), &RenderingServer::gi_probe_get_cell_size);
- ClassDB::bind_method(D_METHOD("gi_probe_set_to_cell_xform", "probe", "xform"), &RenderingServer::gi_probe_set_to_cell_xform);
- ClassDB::bind_method(D_METHOD("gi_probe_get_to_cell_xform", "probe"), &RenderingServer::gi_probe_get_to_cell_xform);
- ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_data", "probe", "data"), &RenderingServer::gi_probe_set_dynamic_data);
- ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_data", "probe"), &RenderingServer::gi_probe_get_dynamic_data);
- ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_range", "probe", "range"), &RenderingServer::gi_probe_set_dynamic_range);
- ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_range", "probe"), &RenderingServer::gi_probe_get_dynamic_range);
- ClassDB::bind_method(D_METHOD("gi_probe_set_energy", "probe", "energy"), &RenderingServer::gi_probe_set_energy);
- ClassDB::bind_method(D_METHOD("gi_probe_get_energy", "probe"), &RenderingServer::gi_probe_get_energy);
- ClassDB::bind_method(D_METHOD("gi_probe_set_bias", "probe", "bias"), &RenderingServer::gi_probe_set_bias);
- ClassDB::bind_method(D_METHOD("gi_probe_get_bias", "probe"), &RenderingServer::gi_probe_get_bias);
- ClassDB::bind_method(D_METHOD("gi_probe_set_normal_bias", "probe", "bias"), &RenderingServer::gi_probe_set_normal_bias);
- ClassDB::bind_method(D_METHOD("gi_probe_get_normal_bias", "probe"), &RenderingServer::gi_probe_get_normal_bias);
- ClassDB::bind_method(D_METHOD("gi_probe_set_propagation", "probe", "propagation"), &RenderingServer::gi_probe_set_propagation);
- ClassDB::bind_method(D_METHOD("gi_probe_get_propagation", "probe"), &RenderingServer::gi_probe_get_propagation);
- ClassDB::bind_method(D_METHOD("gi_probe_set_interior", "probe", "enable"), &RenderingServer::gi_probe_set_interior);
- ClassDB::bind_method(D_METHOD("gi_probe_is_interior", "probe"), &RenderingServer::gi_probe_is_interior);
- ClassDB::bind_method(D_METHOD("gi_probe_set_compress", "probe", "enable"), &RenderingServer::gi_probe_set_compress);
- ClassDB::bind_method(D_METHOD("gi_probe_is_compressed", "probe"), &RenderingServer::gi_probe_is_compressed);
+ ClassDB::bind_method(D_METHOD("voxel_gi_create"), &RenderingServer::voxel_gi_create);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_bounds", "probe", "bounds"), &RenderingServer::voxel_gi_set_bounds);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_bounds", "probe"), &RenderingServer::voxel_gi_get_bounds);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_cell_size", "probe", "range"), &RenderingServer::voxel_gi_set_cell_size);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_cell_size", "probe"), &RenderingServer::voxel_gi_get_cell_size);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_to_cell_xform", "probe", "xform"), &RenderingServer::voxel_gi_set_to_cell_xform);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_to_cell_xform", "probe"), &RenderingServer::voxel_gi_get_to_cell_xform);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_dynamic_data", "probe", "data"), &RenderingServer::voxel_gi_set_dynamic_data);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_dynamic_data", "probe"), &RenderingServer::voxel_gi_get_dynamic_data);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_dynamic_range", "probe", "range"), &RenderingServer::voxel_gi_set_dynamic_range);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_dynamic_range", "probe"), &RenderingServer::voxel_gi_get_dynamic_range);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_energy", "probe", "energy"), &RenderingServer::voxel_gi_set_energy);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_energy", "probe"), &RenderingServer::voxel_gi_get_energy);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_bias", "probe", "bias"), &RenderingServer::voxel_gi_set_bias);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_bias", "probe"), &RenderingServer::voxel_gi_get_bias);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_normal_bias", "probe", "bias"), &RenderingServer::voxel_gi_set_normal_bias);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_normal_bias", "probe"), &RenderingServer::voxel_gi_get_normal_bias);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_propagation", "probe", "propagation"), &RenderingServer::voxel_gi_set_propagation);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_propagation", "probe"), &RenderingServer::voxel_gi_get_propagation);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_interior", "probe", "enable"), &RenderingServer::voxel_gi_set_interior);
+ ClassDB::bind_method(D_METHOD("voxel_gi_is_interior", "probe"), &RenderingServer::voxel_gi_is_interior);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_compress", "probe", "enable"), &RenderingServer::voxel_gi_set_compress);
+ ClassDB::bind_method(D_METHOD("voxel_gi_is_compressed", "probe"), &RenderingServer::voxel_gi_is_compressed);
#endif
/*
ClassDB::bind_method(D_METHOD("lightmap_create()"), &RenderingServer::lightmap_capture_create);
@@ -1723,11 +1725,11 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &RenderingServer::instance_attach_skeleton);
ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &RenderingServer::instance_set_exterior);
ClassDB::bind_method(D_METHOD("instance_set_extra_visibility_margin", "instance", "margin"), &RenderingServer::instance_set_extra_visibility_margin);
+ ClassDB::bind_method(D_METHOD("instance_set_visibility_parent", "instance", "parent"), &RenderingServer::instance_set_visibility_parent);
ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &RenderingServer::instance_geometry_set_flag);
ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &RenderingServer::instance_geometry_set_cast_shadows_setting);
ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &RenderingServer::instance_geometry_set_material_override);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_draw_range", "instance", "min", "max", "min_margin", "max_margin"), &RenderingServer::instance_geometry_set_draw_range);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_as_instance_lod", "instance", "as_lod_of_instance"), &RenderingServer::instance_geometry_set_as_instance_lod);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_visibility_range", "instance", "min", "max", "min_margin", "max_margin"), &RenderingServer::instance_geometry_set_visibility_range);
ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &RenderingServer::_instances_cull_aabb_bind, DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &RenderingServer::_instances_cull_ray_bind, DEFVAL(RID()));
@@ -2022,9 +2024,9 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OVERDRAW);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_WIREFRAME);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER);
- BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO);
- BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING);
- BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE);
@@ -2117,7 +2119,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(INSTANCE_LIGHT);
BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE);
BIND_ENUM_CONSTANT(INSTANCE_DECAL);
- BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE);
+ BIND_ENUM_CONSTANT(INSTANCE_VOXEL_GI);
BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP);
BIND_ENUM_CONSTANT(INSTANCE_OCCLUDER);
BIND_ENUM_CONSTANT(INSTANCE_MAX);
@@ -2282,6 +2284,10 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2", true);
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_pvrtc", false);
+ GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false);
+ GLOBAL_DEF("rendering/textures/lossless_compression/webp_compression_level", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/lossless_compression/webp_compression_level", PropertyInfo(Variant::INT, "rendering/textures/lossless_compression/webp_compression_level", PROPERTY_HINT_RANGE, "0,9,1"));
+
GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::FLOAT, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"));
@@ -2306,6 +2312,12 @@ RenderingServer::RenderingServer() {
"rendering/vulkan/rendering/back_end",
PROPERTY_HINT_ENUM, "ForwardClustered,ForwardMobile"));
+ GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true);
+ GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true);
+ GLOBAL_DEF("rendering/shader_compiler/shader_cache/use_zstd_compression", true);
+ GLOBAL_DEF("rendering/shader_compiler/shader_cache/strip_debug", false);
+ GLOBAL_DEF("rendering/shader_compiler/shader_cache/strip_debug.release", true);
+
GLOBAL_DEF("rendering/reflections/sky_reflections/roughness_layers", 8);
GLOBAL_DEF("rendering/reflections/sky_reflections/texture_array_reflections", true);
GLOBAL_DEF("rendering/reflections/sky_reflections/texture_array_reflections.mobile", false);
@@ -2318,9 +2330,9 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false);
- GLOBAL_DEF("rendering/global_illumination/gi_probes/anisotropic", false);
- GLOBAL_DEF("rendering/global_illumination/gi_probes/quality", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/global_illumination/gi_probes/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)"));
+ GLOBAL_DEF("rendering/global_illumination/voxel_gi/anisotropic", false);
+ GLOBAL_DEF("rendering/global_illumination/voxel_gi/quality", 1);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/voxel_gi/quality", PropertyInfo(Variant::INT, "rendering/global_illumination/voxel_gi/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)"));
GLOBAL_DEF("rendering/shading/overrides/force_vertex_shading", false);
GLOBAL_DEF("rendering/shading/overrides/force_vertex_shading.mobile", true);
@@ -2408,6 +2420,8 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/limits/cluster_builder/max_clustered_elements", 512);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/cluster_builder/max_clustered_elements", PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1"));
+
+ GLOBAL_DEF_RST("rendering/xr/enabled", false);
}
RenderingServer::~RenderingServer() {
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 0c1a010f73..1806f1da18 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -371,7 +371,7 @@ public:
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
- virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0;
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0;
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
@@ -379,7 +379,7 @@ public:
virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
- virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
@@ -411,8 +411,8 @@ public:
virtual RID skeleton_create() = 0;
virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
- virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0;
- virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0;
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
@@ -548,56 +548,56 @@ public:
virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
- /* GI PROBE API */
+ /* VOXEL GI API */
- virtual RID gi_probe_create() = 0;
+ virtual RID voxel_gi_create() = 0;
- virtual void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
+ virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
- virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
- virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
- virtual Vector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const = 0;
- virtual Vector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const = 0;
- virtual Vector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const = 0;
- virtual Vector<int> gi_probe_get_level_counts(RID p_gi_probe) const = 0;
- virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0;
+ virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const = 0;
+ virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const = 0;
+ virtual Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const = 0;
+ virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0;
- virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0;
- virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_propagation(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0;
- virtual float gi_probe_get_energy(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
+ virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0;
- virtual float gi_probe_get_ao(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) = 0;
+ virtual float voxel_gi_get_ao(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0;
- virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) = 0;
+ virtual float voxel_gi_get_ao_size(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0;
- virtual float gi_probe_get_bias(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
+ virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0;
- virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0;
- virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) = 0;
+ virtual bool voxel_gi_is_interior(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0;
- virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) = 0;
+ virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0;
- virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0;
- virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0;
+ virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) = 0;
+ virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const = 0;
- enum GIProbeQuality {
- GI_PROBE_QUALITY_LOW,
- GI_PROBE_QUALITY_HIGH,
+ enum VoxelGIQuality {
+ VOXEL_GI_QUALITY_LOW,
+ VOXEL_GI_QUALITY_HIGH,
};
- virtual void gi_probe_set_quality(GIProbeQuality) = 0;
+ virtual void voxel_gi_set_quality(VoxelGIQuality) = 0;
/* LIGHTMAP */
@@ -651,7 +651,7 @@ public:
virtual void particles_set_transform_align(RID p_particles, ParticlesTransformAlign p_transform_align) = 0;
virtual void particles_set_trails(RID p_particles, bool p_enable, float p_length_sec) = 0;
- virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform> &p_bind_poses) = 0;
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
virtual bool particles_is_inactive(RID p_particles) = 0;
virtual void particles_request_process(RID p_particles) = 0;
@@ -667,11 +667,12 @@ public:
PARTICLES_EMIT_FLAG_CUSTOM = 16
};
- virtual void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
+ virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
enum ParticlesDrawOrder {
PARTICLES_DRAW_ORDER_INDEX,
PARTICLES_DRAW_ORDER_LIFETIME,
+ PARTICLES_DRAW_ORDER_REVERSE_LIFETIME,
PARTICLES_DRAW_ORDER_VIEW_DEPTH,
};
@@ -682,7 +683,7 @@ public:
virtual AABB particles_get_current_aabb(RID p_particles) = 0;
- virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; //this is only used for 2D, in 3D it's automatic
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; //this is only used for 2D, in 3D it's automatic
/* PARTICLES COLLISION API */
@@ -727,7 +728,7 @@ public:
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0;
- virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0;
+ virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform) = 0;
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
virtual void camera_set_camera_effects(RID p_camera, RID p_camera_effects) = 0;
@@ -881,9 +882,9 @@ public:
VIEWPORT_DEBUG_DRAW_OVERDRAW,
VIEWPORT_DEBUG_DRAW_WIREFRAME,
VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER,
- VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO,
- VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING,
- VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION,
+ VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO,
+ VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING,
+ VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION,
VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS,
VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE,
@@ -1144,7 +1145,7 @@ public:
INSTANCE_LIGHT,
INSTANCE_REFLECTION_PROBE,
INSTANCE_DECAL,
- INSTANCE_GI_PROBE,
+ INSTANCE_VOXEL_GI,
INSTANCE_LIGHTMAP,
INSTANCE_OCCLUDER,
INSTANCE_MAX,
@@ -1159,7 +1160,7 @@ public:
virtual void instance_set_base(RID p_instance, RID p_base) = 0;
virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0;
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0;
- virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
+ virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0;
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0;
virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) = 0;
@@ -1171,6 +1172,7 @@ public:
virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0;
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
+ virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance) = 0;
// don't use these in a game!
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0;
@@ -1200,8 +1202,7 @@ public:
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0;
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
- virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
- virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 8b03565291..daed612b02 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -987,7 +987,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
while (i < ranges.size()) {
int j = i + 1;
while (j < ranges.size()) {
- if (Math::is_equal_approx(ranges[i].y, ranges[j].x, UNIT_EPSILON)) {
+ if (Math::is_equal_approx(ranges[i].y, ranges[j].x, (real_t)UNIT_EPSILON)) {
ranges.write[i].y = ranges[j].y;
ranges.remove(j);
continue;
diff --git a/servers/text_server.h b/servers/text_server.h
index 7fcfb91151..138ceb9356 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -31,7 +31,7 @@
#ifndef TEXT_SERVER_H
#define TEXT_SERVER_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/os.h"
#include "core/templates/rid.h"
#include "core/variant/variant.h"
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 9148631899..09e8e12f8b 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "xr_interface.h"
+#include "servers/rendering/renderer_compositor.h"
void XRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_name"), &XRInterface::get_name);
@@ -45,7 +46,7 @@ void XRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tracking_status"), &XRInterface::get_tracking_status);
ClassDB::bind_method(D_METHOD("get_render_targetsize"), &XRInterface::get_render_targetsize);
- ClassDB::bind_method(D_METHOD("is_stereo"), &XRInterface::is_stereo);
+ ClassDB::bind_method(D_METHOD("get_view_count"), &XRInterface::get_view_count);
ADD_GROUP("Interface", "interface_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_is_primary", "is_primary");
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 8039018f35..6031bd7003 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -35,6 +35,9 @@
#include "core/os/thread_safe.h"
#include "servers/xr_server.h"
+// forward declaration
+struct BlitToScreen;
+
/**
@author Bastiaan Olij <mux213@gmail.com>
@@ -47,8 +50,8 @@
Note that we may make this into a fully instantiable class for GDNative support.
*/
-class XRInterface : public Reference {
- GDCLASS(XRInterface, Reference);
+class XRInterface : public RefCounted {
+ GDCLASS(XRInterface, RefCounted);
public:
enum Capabilities { /* purely meta data, provides some info about what this interface supports */
@@ -105,17 +108,22 @@ public:
/** rendering and internal **/
virtual Size2 get_render_targetsize() = 0; /* returns the recommended render target size per eye for this device */
- virtual bool is_stereo() = 0; /* returns true if this interface requires stereo rendering (for VR HMDs) or mono rendering (for mobile AR) */
- virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) = 0; /* get each eyes camera transform, also implement EYE_MONO */
- virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each eyes projection matrix */
- virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye); /* if applicable return external texture to render to */
- virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */
+ virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */
+ virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
+ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
+ virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each view projection matrix */
+
+ virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* commit rendered views to the XR interface */
virtual void process() = 0;
virtual void notification(int p_what) = 0;
XRInterface();
~XRInterface();
+
+ // deprecated
+ virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye); /* if applicable return external texture to render to */
+ virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp
index 5341390045..e9383db941 100644
--- a/servers/xr/xr_positional_tracker.cpp
+++ b/servers/xr/xr_positional_tracker.cpp
@@ -194,8 +194,8 @@ void XRPositionalTracker::set_tracker_hand(const XRPositionalTracker::TrackerHan
};
};
-Transform XRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const {
- Transform new_transform;
+Transform3D XRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const {
+ Transform3D new_transform;
new_transform.basis = get_orientation();
new_transform.origin = get_position();
diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h
index a5c6459471..5577582929 100644
--- a/servers/xr/xr_positional_tracker.h
+++ b/servers/xr/xr_positional_tracker.h
@@ -43,8 +43,8 @@
This is where potentially additional AR/VR interfaces may be active as there are AR/VR SDKs that solely deal with positional tracking.
*/
-class XRPositionalTracker : public Reference {
- GDCLASS(XRPositionalTracker, Reference);
+class XRPositionalTracker : public RefCounted {
+ GDCLASS(XRPositionalTracker, RefCounted);
_THREAD_SAFE_CLASS_
public:
@@ -93,7 +93,7 @@ public:
void set_mesh(const Ref<Mesh> &p_mesh);
Ref<Mesh> get_mesh() const;
- Transform get_transform(bool p_adjust_by_reference_frame) const;
+ Transform3D get_transform(bool p_adjust_by_reference_frame) const;
XRPositionalTracker();
~XRPositionalTracker() {}
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index 5678071857..b12fff319d 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -101,25 +101,25 @@ void XRServer::set_world_scale(real_t p_world_scale) {
world_scale = p_world_scale;
};
-Transform XRServer::get_world_origin() const {
+Transform3D XRServer::get_world_origin() const {
return world_origin;
};
-void XRServer::set_world_origin(const Transform &p_world_origin) {
+void XRServer::set_world_origin(const Transform3D &p_world_origin) {
world_origin = p_world_origin;
};
-Transform XRServer::get_reference_frame() const {
+Transform3D XRServer::get_reference_frame() const {
return reference_frame;
};
void XRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) {
if (primary_interface != nullptr) {
// clear our current reference frame or we'll end up double adjusting it
- reference_frame = Transform();
+ reference_frame = Transform3D();
// requesting our EYE_MONO transform should return our current HMD position
- Transform new_reference_frame = primary_interface->get_transform_for_eye(XRInterface::EYE_MONO, Transform());
+ Transform3D new_reference_frame = primary_interface->get_camera_transform();
// remove our tilt
if (p_rotation_mode == 1) {
@@ -145,10 +145,10 @@ void XRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) {
};
};
-Transform XRServer::get_hmd_transform() {
- Transform hmd_transform;
+Transform3D XRServer::get_hmd_transform() {
+ Transform3D hmd_transform;
if (primary_interface != nullptr) {
- hmd_transform = primary_interface->get_transform_for_eye(XRInterface::EYE_MONO, hmd_transform);
+ hmd_transform = primary_interface->get_camera_transform();
};
return hmd_transform;
};
diff --git a/servers/xr_server.h b/servers/xr_server.h
index 46243d7fd0..25431844c2 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -31,7 +31,7 @@
#ifndef XR_SERVER_H
#define XR_SERVER_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/os/os.h"
#include "core/os/thread_safe.h"
#include "core/templates/rid.h"
@@ -82,8 +82,8 @@ private:
Ref<XRInterface> primary_interface; /* we'll identify one interface as primary, this will be used by our viewports */
real_t world_scale; /* scale by which we multiply our tracker positions */
- Transform world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */
- Transform reference_frame; /* our reference frame */
+ Transform3D world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */
+ Transform3D reference_frame; /* our reference frame */
uint64_t last_process_usec; /* for frame timing, usec when we did our processing */
uint64_t last_commit_usec; /* for frame timing, usec when we finished committing both eyes */
@@ -122,8 +122,8 @@ public:
Note: this should not be used in AR and should be ignored by an AR based interface as it would throw what you're looking at in the real world
and in the virtual world out of sync
*/
- Transform get_world_origin() const;
- void set_world_origin(const Transform &p_world_origin);
+ Transform3D get_world_origin() const;
+ void set_world_origin(const Transform3D &p_world_origin);
/*
center_on_hmd calculates a new reference frame. This ensures the HMD is positioned to 0,0,0 facing 0,0,-1 (need to verify this direction)
@@ -135,13 +135,13 @@ public:
Note: this should not be used in AR and should be ignored by an AR based interface as it would throw what you're looking at in the real world
and in the virtual world out of sync
*/
- Transform get_reference_frame() const;
+ Transform3D get_reference_frame() const;
void center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height);
/*
get_hmd_transform gets our hmd transform (centered between eyes) with most up to date tracking, relative to the origin
*/
- Transform get_hmd_transform();
+ Transform3D get_hmd_transform();
/*
Interfaces are objects that 'glue' Godot to an AR or VR SDK such as the Oculus SDK, OpenVR, OpenHMD, etc.
diff --git a/tests/test_aabb.h b/tests/test_aabb.h
index 517c4dcefd..39e3c6e45b 100644
--- a/tests/test_aabb.h
+++ b/tests/test_aabb.h
@@ -50,8 +50,8 @@ TEST_CASE("[AABB] Constructor methods") {
TEST_CASE("[AABB] String conversion") {
CHECK_MESSAGE(
- String(AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6))) == "-1.5, 2, -2.5 - 4, 5, 6",
- "The string representation shouild match the expected value.");
+ String(AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6))) == "[P: (-1.5, 2, -2.5), S: (4, 5, 6)]",
+ "The string representation should match the expected value.");
}
TEST_CASE("[AABB] Basic getters") {
diff --git a/tests/test_class_db.h b/tests/test_class_db.h
index 9ef4569c14..75785fa5ed 100644
--- a/tests/test_class_db.h
+++ b/tests/test_class_db.h
@@ -97,7 +97,7 @@ struct ExposedClass {
bool is_singleton = false;
bool is_instantiable = false;
- bool is_reference = false;
+ bool is_ref_counted = false;
ClassDB::APIType api_type;
@@ -131,7 +131,7 @@ struct ExposedClass {
struct NamesCache {
StringName variant_type = StaticCString::create("Variant");
StringName object_class = StaticCString::create("Object");
- StringName reference_class = StaticCString::create("Reference");
+ StringName ref_counted_class = StaticCString::create("RefCounted");
StringName string_type = StaticCString::create("String");
StringName string_name_type = StaticCString::create("StringName");
StringName node_path_type = StaticCString::create("NodePath");
@@ -240,10 +240,10 @@ bool arg_default_value_is_assignable_to_type(const Context &p_context, const Var
p_arg_type.name == p_context.names_cache.node_path_type;
case Variant::NODE_PATH:
return p_arg_type.name == p_context.names_cache.node_path_type;
- case Variant::TRANSFORM:
+ case Variant::TRANSFORM3D:
case Variant::TRANSFORM2D:
case Variant::BASIS:
- case Variant::QUAT:
+ case Variant::QUATERNION:
case Variant::PLANE:
case Variant::AABB:
case Variant::COLOR:
@@ -516,7 +516,7 @@ void add_exposed_classes(Context &r_context) {
exposed_class.api_type = api_type;
exposed_class.is_singleton = Engine::get_singleton()->has_singleton(class_name);
exposed_class.is_instantiable = class_info->creation_func && !exposed_class.is_singleton;
- exposed_class.is_reference = ClassDB::is_parent_class(class_name, "Reference");
+ exposed_class.is_ref_counted = ClassDB::is_parent_class(class_name, "RefCounted");
exposed_class.base = ClassDB::get_parent_class(class_name);
// Add properties
@@ -611,7 +611,7 @@ void add_exposed_classes(Context &r_context) {
method.return_type.name = return_info.class_name;
bool bad_reference_hint = !method.is_virtual && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE &&
- ClassDB::is_parent_class(return_info.class_name, r_context.names_cache.reference_class);
+ ClassDB::is_parent_class(return_info.class_name, r_context.names_cache.ref_counted_class);
TEST_COND(bad_reference_hint, "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'.", " Are you returning a reference type by pointer? Method: '",
exposed_class.name, ".", method.name, "'.");
} else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
@@ -665,7 +665,7 @@ void add_exposed_classes(Context &r_context) {
TEST_COND(exposed_class.find_property_by_name(method.name),
"Method name conflicts with property: '", String(class_name), ".", String(method.name), "'.");
- // Classes starting with an underscore are ignored unless they're used as a property setter or getter
+ // Methods starting with an underscore are ignored unless they're virtual or used as a property setter or getter.
if (!method.is_virtual && String(method.name)[0] == '_') {
for (const List<PropertyData>::Element *F = exposed_class.properties.front(); F; F = F->next()) {
const PropertyData &prop = F->get();
@@ -678,6 +678,10 @@ void add_exposed_classes(Context &r_context) {
} else {
exposed_class.methods.push_back(method);
}
+
+ if (method.is_virtual) {
+ TEST_COND(String(method.name)[0] != '_', "Virtual method ", String(method.name), " does not start with underscore.");
+ }
}
// Add signals
diff --git a/tests/test_color.h b/tests/test_color.h
index eb8d7dcbd4..bffa890ae2 100644
--- a/tests/test_color.h
+++ b/tests/test_color.h
@@ -101,13 +101,13 @@ TEST_CASE("[Color] Reading methods") {
const Color dark_blue = Color(0, 0, 0.5, 0.4);
CHECK_MESSAGE(
- Math::is_equal_approx(dark_blue.get_h(), 240 / 360.0),
+ Math::is_equal_approx(dark_blue.get_h(), 240.0f / 360.0f),
"The returned HSV hue should match the expected value.");
CHECK_MESSAGE(
- Math::is_equal_approx(dark_blue.get_s(), 1),
+ Math::is_equal_approx(dark_blue.get_s(), 1.0f),
"The returned HSV saturation should match the expected value.");
CHECK_MESSAGE(
- Math::is_equal_approx(dark_blue.get_v(), 0.5),
+ Math::is_equal_approx(dark_blue.get_v(), 0.5f),
"The returned HSV value should match the expected value.");
}
@@ -140,7 +140,7 @@ TEST_CASE("[Color] Conversion methods") {
cyan.to_rgba64() == 0x0000'ffff'ffff'ffff,
"The returned 64-bit BGR number should match the expected value.");
CHECK_MESSAGE(
- String(cyan) == "0, 1, 1, 1",
+ String(cyan) == "(0, 1, 1, 1)",
"The string representation should match the expected value.");
}
diff --git a/tests/test_command_queue.h b/tests/test_command_queue.h
index 2f0f62f5c8..f0d4569942 100644
--- a/tests/test_command_queue.h
+++ b/tests/test_command_queue.h
@@ -127,20 +127,20 @@ public:
int func1_count = 0;
- void func1(Transform t) {
+ void func1(Transform3D t) {
func1_count++;
}
- void func2(Transform t, float f) {
+ void func2(Transform3D t, float f) {
func1_count++;
}
- void func3(Transform t1, Transform t2, Transform t3, Transform t4, Transform t5, Transform t6) {
+ void func3(Transform3D t1, Transform3D t2, Transform3D t3, Transform3D t4, Transform3D t5, Transform3D t6) {
func1_count++;
}
- Transform func1r(Transform t) {
+ Transform3D func1r(Transform3D t) {
func1_count++;
return t;
}
- Transform func2r(Transform t, float f) {
+ Transform3D func2r(Transform3D t, float f) {
func1_count++;
return t;
}
@@ -156,7 +156,7 @@ public:
command_queue.flush_all();
}
for (int i = 0; i < message_count_to_read; i++) {
- command_queue.wait_and_flush_one();
+ command_queue.wait_and_flush();
}
message_count_to_read = 0;
@@ -175,8 +175,8 @@ public:
during_writing = false;
writer_threadwork.thread_wait_for_work();
while (!exit_threads) {
- Transform tr;
- Transform otr;
+ Transform3D tr;
+ Transform3D otr;
float f = 1;
during_writing = true;
for (int i = 0; i < message_types_to_write.size(); i++) {
@@ -276,50 +276,6 @@ TEST_CASE("[CommandQueue] Test Queue Basics") {
ProjectSettings::get_singleton()->property_get_revert(COMMAND_QUEUE_SETTING));
}
-TEST_CASE("[CommandQueue] Test Waiting at Queue Full") {
- const char *COMMAND_QUEUE_SETTING = "memory/limits/command_queue/multithreading_queue_size_kb";
- ProjectSettings::get_singleton()->set_setting(COMMAND_QUEUE_SETTING, 1);
- SharedThreadState sts;
- sts.init_threads();
-
- int msgs_to_add = 24; // a queue of size 1kB fundamentally cannot fit 24 matrices.
- for (int i = 0; i < msgs_to_add; i++) {
- sts.add_msg_to_write(SharedThreadState::TEST_MSG_FUNC1_TRANSFORM);
- }
- sts.writer_threadwork.main_start_work();
- // If we call main_wait_for_done, we will deadlock. So instead...
- sts.message_count_to_read = 1;
- sts.reader_threadwork.main_start_work();
- sts.reader_threadwork.main_wait_for_done();
- CHECK_MESSAGE(sts.func1_count == 1,
- "Reader should have read one message");
- CHECK_MESSAGE(sts.during_writing,
- "Writer thread should still be blocked on writing.");
- sts.message_count_to_read = msgs_to_add - 3;
- sts.reader_threadwork.main_start_work();
- sts.reader_threadwork.main_wait_for_done();
- CHECK_MESSAGE(sts.func1_count >= msgs_to_add - 3,
- "Reader should have read most messages");
- sts.writer_threadwork.main_wait_for_done();
- CHECK_MESSAGE(sts.during_writing == false,
- "Writer thread should no longer be blocked on writing.");
- sts.message_count_to_read = 2;
- sts.reader_threadwork.main_start_work();
- sts.reader_threadwork.main_wait_for_done();
- sts.message_count_to_read = -1;
- sts.reader_threadwork.main_start_work();
- sts.reader_threadwork.main_wait_for_done();
- CHECK_MESSAGE(sts.func1_count == msgs_to_add,
- "Reader should have read all messages");
-
- sts.destroy_threads();
-
- CHECK_MESSAGE(sts.func1_count == msgs_to_add,
- "Reader should have read no additional messages after join");
- ProjectSettings::get_singleton()->set_setting(COMMAND_QUEUE_SETTING,
- ProjectSettings::get_singleton()->property_get_revert(COMMAND_QUEUE_SETTING));
-}
-
TEST_CASE("[CommandQueue] Test Queue Wrapping to same spot.") {
const char *COMMAND_QUEUE_SETTING = "memory/limits/command_queue/multithreading_queue_size_kb";
ProjectSettings::get_singleton()->set_setting(COMMAND_QUEUE_SETTING, 1);
diff --git a/tests/test_curve.h b/tests/test_curve.h
index 019941a7ce..3055cfd97b 100644
--- a/tests/test_curve.h
+++ b/tests/test_curve.h
@@ -83,13 +83,13 @@ TEST_CASE("[Curve] Custom curve with free tangents") {
Math::is_equal_approx(curve->interpolate(-0.1), 0),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.1), 0.352),
+ Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.352),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.4), 0.352),
+ Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.352),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.7), 0.896),
+ Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.896),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
Math::is_equal_approx(curve->interpolate(1), 1),
@@ -102,13 +102,13 @@ TEST_CASE("[Curve] Custom curve with free tangents") {
Math::is_equal_approx(curve->interpolate_baked(-0.1), 0),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.1), 0.352),
+ Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.352),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.4), 0.352),
+ Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.352),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.7), 0.896),
+ Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.896),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
Math::is_equal_approx(curve->interpolate_baked(1), 1),
@@ -172,13 +172,13 @@ TEST_CASE("[Curve] Custom curve with linear tangents") {
Math::is_equal_approx(curve->interpolate(-0.1), 0),
"Custom linear curve should return the expected value at offset -0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.1), 0.4),
+ Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.4),
"Custom linear curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.4), 0.4),
+ Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.4),
"Custom linear curve should return the expected value at offset 0.4.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.7), 0.8),
+ Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8),
"Custom linear curve should return the expected value at offset 0.7.");
CHECK_MESSAGE(
Math::is_equal_approx(curve->interpolate(1), 1),
@@ -191,13 +191,13 @@ TEST_CASE("[Curve] Custom curve with linear tangents") {
Math::is_equal_approx(curve->interpolate_baked(-0.1), 0),
"Custom linear curve should return the expected baked value at offset -0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.1), 0.4),
+ Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.4),
"Custom linear curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.4), 0.4),
+ Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.4),
"Custom linear curve should return the expected baked value at offset 0.4.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.7), 0.8),
+ Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8),
"Custom linear curve should return the expected baked value at offset 0.7.");
CHECK_MESSAGE(
Math::is_equal_approx(curve->interpolate_baked(1), 1),
@@ -210,10 +210,10 @@ TEST_CASE("[Curve] Custom curve with linear tangents") {
curve->remove_point(10);
ERR_PRINT_ON;
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.7), 0.8),
+ Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8),
"Custom free curve should return the expected value at offset 0.7 after removing point at invalid index 10.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.7), 0.8),
+ Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8),
"Custom free curve should return the expected baked value at offset 0.7 after removing point at invalid index 10.");
}
} // namespace TestCurve
diff --git a/tests/test_expression.h b/tests/test_expression.h
index 0ef60d1a19..cb1d29389f 100644
--- a/tests/test_expression.h
+++ b/tests/test_expression.h
@@ -83,42 +83,42 @@ TEST_CASE("[Expression] Floating-point arithmetic") {
expression.parse("-123.456") == OK,
"Float identity should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), -123.456),
+ Math::is_equal_approx(double(expression.execute()), -123.456),
"Float identity should return the expected result.");
CHECK_MESSAGE(
expression.parse("2.0 + 3.0") == OK,
"Float addition should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 5),
+ Math::is_equal_approx(double(expression.execute()), 5),
"Float addition should return the expected result.");
CHECK_MESSAGE(
expression.parse("3.0 / 10") == OK,
"Float / integer division should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 0.3),
+ Math::is_equal_approx(double(expression.execute()), 0.3),
"Float / integer division should return the expected result.");
CHECK_MESSAGE(
expression.parse("3 / 10.0") == OK,
"Basic integer / float division should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 0.3),
+ Math::is_equal_approx(double(expression.execute()), 0.3),
"Basic integer / float division should return the expected result.");
CHECK_MESSAGE(
expression.parse("3.0 / 10.0") == OK,
"Float / float division should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 0.3),
+ Math::is_equal_approx(double(expression.execute()), 0.3),
"Float / float division should return the expected result.");
CHECK_MESSAGE(
expression.parse("2.5 * (6.0 + 14.25) / 2.0 - 5.12345") == OK,
"Float multiplication-addition-subtraction-division should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 20.18905),
+ Math::is_equal_approx(double(expression.execute()), 20.18905),
"Float multiplication-addition-subtraction-division should return the expected result.");
}
@@ -129,7 +129,7 @@ TEST_CASE("[Expression] Scientific notation") {
expression.parse("2.e5") == OK,
"The expression should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 200'000),
+ Math::is_equal_approx(double(expression.execute()), 200'000),
"The expression should return the expected result.");
// The middle "e" is ignored here.
@@ -137,14 +137,14 @@ TEST_CASE("[Expression] Scientific notation") {
expression.parse("2e5") == OK,
"The expression should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 25),
+ Math::is_equal_approx(double(expression.execute()), 25),
"The expression should return the expected result.");
CHECK_MESSAGE(
expression.parse("2e.5") == OK,
"The expression should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 2),
+ Math::is_equal_approx(double(expression.execute()), 2),
"The expression should return the expected result.");
}
@@ -176,14 +176,14 @@ TEST_CASE("[Expression] Built-in functions") {
expression.parse("snapped(sin(0.5), 0.01)") == OK,
"The expression should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(float(expression.execute()), 0.48),
+ Math::is_equal_approx(double(expression.execute()), 0.48),
"`snapped(sin(0.5), 0.01)` should return the expected result.");
CHECK_MESSAGE(
expression.parse("pow(2.0, -2500)") == OK,
"The expression should parse successfully.");
CHECK_MESSAGE(
- Math::is_zero_approx(float(expression.execute())),
+ Math::is_zero_approx(double(expression.execute())),
"`pow(2.0, -2500)` should return the expected result (asymptotically zero).");
}
@@ -410,7 +410,7 @@ TEST_CASE("[Expression] Unusual expressions") {
"The expression should parse successfully.");
ERR_PRINT_OFF;
CHECK_MESSAGE(
- Math::is_inf(float(expression.execute())),
+ Math::is_inf(double(expression.execute())),
"`-25.4 / 0` should return inf.");
ERR_PRINT_ON;
diff --git a/tests/test_file_access.h b/tests/test_file_access.h
index 00a314644c..cb74e08a0d 100644
--- a/tests/test_file_access.h
+++ b/tests/test_file_access.h
@@ -31,7 +31,7 @@
#ifndef TEST_FILE_ACCESS_H
#define TEST_FILE_ACCESS_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "test_utils.h"
namespace TestFileAccess {
diff --git a/tests/test_geometry_2d.h b/tests/test_geometry_2d.h
index c9313f3625..32d4114a1c 100644
--- a/tests/test_geometry_2d.h
+++ b/tests/test_geometry_2d.h
@@ -50,7 +50,7 @@ TEST_CASE("[Geometry2D] Point in circle") {
CHECK(Geometry2D::is_point_in_circle(Vector2(7, -42), Vector2(4, -40), 3.7));
CHECK_FALSE(Geometry2D::is_point_in_circle(Vector2(7, -42), Vector2(4, -40), 3.5));
- // This tests points on the edge of the circle. They are treated as beeing inside the circle.
+ // This tests points on the edge of the circle. They are treated as being inside the circle.
// In `is_point_in_triangle` and `is_point_in_polygon` they are treated as being outside, so in order the make
// the behaviour consistent this may change in the future (see issue #44717 and PR #44274).
CHECK(Geometry2D::is_point_in_circle(Vector2(1.0, 0.0), Vector2(0, 0), 1.0));
@@ -65,7 +65,7 @@ TEST_CASE("[Geometry2D] Point in triangle") {
CHECK(Geometry2D::is_point_in_triangle(Vector2(-3, -2.5), Vector2(-1, -4), Vector2(-3, -2), Vector2(-5, -4)));
CHECK_FALSE(Geometry2D::is_point_in_triangle(Vector2(0, 0), Vector2(1, 4), Vector2(3, 2), Vector2(5, 4)));
- // This tests points on the edge of the triangle. They are treated as beeing outside the triangle.
+ // This tests points on the edge of the triangle. They are treated as being outside the triangle.
// In `is_point_in_circle` they are treated as being inside, so in order the make
// the behaviour consistent this may change in the future (see issue #44717 and PR #44274).
CHECK_FALSE(Geometry2D::is_point_in_triangle(Vector2(1, 1), Vector2(-1, 1), Vector2(0, -1), Vector2(1, 1)));
@@ -95,7 +95,7 @@ TEST_CASE("[Geometry2D] Point in polygon") {
CHECK(Geometry2D::is_point_in_polygon(Vector2(370, 55), p));
CHECK(Geometry2D::is_point_in_polygon(Vector2(-160, 190), p));
- // This tests points on the edge of the polygon. They are treated as beeing outside the polygon.
+ // This tests points on the edge of the polygon. They are treated as being outside the polygon.
// In `is_point_in_circle` they are treated as being inside, so in order the make
// the behaviour consistent this may change in the future (see issue #44717 and PR #44274).
CHECK_FALSE(Geometry2D::is_point_in_polygon(Vector2(68, 112), p));
@@ -227,7 +227,7 @@ TEST_CASE("[Geometry2D] Polygon intersection") {
CHECK(r[0][2].is_equal_approx(Point2(160.52632, 92.63157)));
}
- SUBCASE("[Geometry2D] Intersection with one polygon beeing completly inside the other polygon") {
+ SUBCASE("[Geometry2D] Intersection with one polygon being completely inside the other polygon") {
b.push_back(Point2(80, 100));
b.push_back(Point2(50, 50));
b.push_back(Point2(150, 50));
diff --git a/tests/test_image.h b/tests/test_image.h
index d73717f5b7..99c2a9380d 100644
--- a/tests/test_image.h
+++ b/tests/test_image.h
@@ -101,8 +101,8 @@ TEST_CASE("[Image] Saving and loading") {
Ref<Image> image_bmp = memnew(Image());
FileAccessRef f_bmp = FileAccess::open(TestUtils::get_data_path("images/icon.bmp"), FileAccess::READ, &err);
PackedByteArray data_bmp;
- data_bmp.resize(f_bmp->get_len() + 1);
- f_bmp->get_buffer(data_bmp.ptrw(), f_bmp->get_len());
+ data_bmp.resize(f_bmp->get_length() + 1);
+ f_bmp->get_buffer(data_bmp.ptrw(), f_bmp->get_length());
CHECK_MESSAGE(
image_bmp->load_bmp_from_buffer(data_bmp) == OK,
"The BMP image should load successfully.");
@@ -111,8 +111,8 @@ TEST_CASE("[Image] Saving and loading") {
Ref<Image> image_jpg = memnew(Image());
FileAccessRef f_jpg = FileAccess::open(TestUtils::get_data_path("images/icon.jpg"), FileAccess::READ, &err);
PackedByteArray data_jpg;
- data_jpg.resize(f_jpg->get_len() + 1);
- f_jpg->get_buffer(data_jpg.ptrw(), f_jpg->get_len());
+ data_jpg.resize(f_jpg->get_length() + 1);
+ f_jpg->get_buffer(data_jpg.ptrw(), f_jpg->get_length());
CHECK_MESSAGE(
image_jpg->load_jpg_from_buffer(data_jpg) == OK,
"The JPG image should load successfully.");
@@ -121,8 +121,8 @@ TEST_CASE("[Image] Saving and loading") {
Ref<Image> image_webp = memnew(Image());
FileAccessRef f_webp = FileAccess::open(TestUtils::get_data_path("images/icon.webp"), FileAccess::READ, &err);
PackedByteArray data_webp;
- data_webp.resize(f_webp->get_len() + 1);
- f_webp->get_buffer(data_webp.ptrw(), f_webp->get_len());
+ data_webp.resize(f_webp->get_length() + 1);
+ f_webp->get_buffer(data_webp.ptrw(), f_webp->get_length());
CHECK_MESSAGE(
image_webp->load_webp_from_buffer(data_webp) == OK,
"The WEBP image should load successfully.");
@@ -131,8 +131,8 @@ TEST_CASE("[Image] Saving and loading") {
Ref<Image> image_png = memnew(Image());
FileAccessRef f_png = FileAccess::open(TestUtils::get_data_path("images/icon.png"), FileAccess::READ, &err);
PackedByteArray data_png;
- data_png.resize(f_png->get_len() + 1);
- f_png->get_buffer(data_png.ptrw(), f_png->get_len());
+ data_png.resize(f_png->get_length() + 1);
+ f_png->get_buffer(data_png.ptrw(), f_png->get_length());
CHECK_MESSAGE(
image_png->load_png_from_buffer(data_png) == OK,
"The PNG image should load successfully.");
@@ -141,8 +141,8 @@ TEST_CASE("[Image] Saving and loading") {
Ref<Image> image_tga = memnew(Image());
FileAccessRef f_tga = FileAccess::open(TestUtils::get_data_path("images/icon.tga"), FileAccess::READ, &err);
PackedByteArray data_tga;
- data_tga.resize(f_tga->get_len() + 1);
- f_tga->get_buffer(data_tga.ptrw(), f_tga->get_len());
+ data_tga.resize(f_tga->get_length() + 1);
+ f_tga->get_buffer(data_tga.ptrw(), f_tga->get_length());
CHECK_MESSAGE(
image_tga->load_tga_from_buffer(data_tga) == OK,
"The TGA image should load successfully.");
diff --git a/tests/test_json.h b/tests/test_json.h
index e652a8fced..f1cb4799dc 100644
--- a/tests/test_json.h
+++ b/tests/test_json.h
@@ -80,7 +80,7 @@ TEST_CASE("[JSON] Parsing single data types") {
err_line == 0,
"Parsing an integer number as JSON should parse successfully.");
CHECK_MESSAGE(
- Math::is_equal_approx(result, 123'456),
+ (int)result == 123'456,
"Parsing an integer number as JSON should return the expected value.");
json.parse("0.123456", result, err_str, err_line);
@@ -155,7 +155,7 @@ TEST_CASE("[JSON] Parsing objects (dictionaries)") {
dictionary["bugs"] == Variant(),
"The parsed JSON should contain the expected values.");
CHECK_MESSAGE(
- Math::is_equal_approx(Dictionary(dictionary["apples"])["blue"], -20),
+ (int)Dictionary(dictionary["apples"])["blue"] == -20,
"The parsed JSON should contain the expected values.");
CHECK_MESSAGE(
dictionary["empty_object"].hash() == Dictionary().hash(),
diff --git a/tests/test_macros.h b/tests/test_macros.h
index a13f3abbe7..a1f1932db4 100644
--- a/tests/test_macros.h
+++ b/tests/test_macros.h
@@ -91,10 +91,10 @@ DOCTEST_STRINGIFY_VARIANT(Vector3);
DOCTEST_STRINGIFY_VARIANT(Vector3i);
DOCTEST_STRINGIFY_VARIANT(Transform2D);
DOCTEST_STRINGIFY_VARIANT(Plane);
-DOCTEST_STRINGIFY_VARIANT(Quat);
+DOCTEST_STRINGIFY_VARIANT(Quaternion);
DOCTEST_STRINGIFY_VARIANT(AABB);
DOCTEST_STRINGIFY_VARIANT(Basis);
-DOCTEST_STRINGIFY_VARIANT(Transform);
+DOCTEST_STRINGIFY_VARIANT(Transform3D);
DOCTEST_STRINGIFY_VARIANT(::Color); // Disambiguate from `doctest::Color`.
DOCTEST_STRINGIFY_VARIANT(StringName);
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index d06d604532..d0466d1e2d 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -74,8 +74,11 @@
#include "test_shader_lang.h"
#include "test_string.h"
#include "test_text_server.h"
+#include "test_time.h"
+#include "test_translation.h"
#include "test_validate_testing.h"
#include "test_variant.h"
+#include "test_vector.h"
#include "test_xml_parser.h"
#include "modules/modules_tests.gen.h"
@@ -119,24 +122,27 @@ int test_main(int argc, char *argv[]) {
test_args.push_back(arg);
}
}
- // Convert Godot command line arguments back to standard arguments.
- char **doctest_args = new char *[test_args.size()];
- for (int x = 0; x < test_args.size(); x++) {
- // Operation to convert Godot string to non wchar string.
- CharString cs = test_args[x].utf8();
- const char *str = cs.get_data();
- // Allocate the string copy.
- doctest_args[x] = new char[strlen(str) + 1];
- // Copy this into memory.
- memcpy(doctest_args[x], str, strlen(str) + 1);
- }
- test_context.applyCommandLine(test_args.size(), doctest_args);
+ if (test_args.size() > 0) {
+ // Convert Godot command line arguments back to standard arguments.
+ char **doctest_args = new char *[test_args.size()];
+ for (int x = 0; x < test_args.size(); x++) {
+ // Operation to convert Godot string to non wchar string.
+ CharString cs = test_args[x].utf8();
+ const char *str = cs.get_data();
+ // Allocate the string copy.
+ doctest_args[x] = new char[strlen(str) + 1];
+ // Copy this into memory.
+ memcpy(doctest_args[x], str, strlen(str) + 1);
+ }
+
+ test_context.applyCommandLine(test_args.size(), doctest_args);
- for (int x = 0; x < test_args.size(); x++) {
- delete[] doctest_args[x];
+ for (int x = 0; x < test_args.size(); x++) {
+ delete[] doctest_args[x];
+ }
+ delete[] doctest_args;
}
- delete[] doctest_args;
return test_context.run();
}
diff --git a/tests/test_math.cpp b/tests/test_math.cpp
index 26c2aa2088..67d9a52539 100644
--- a/tests/test_math.cpp
+++ b/tests/test_math.cpp
@@ -30,13 +30,13 @@
#include "test_math.h"
+#include "core/io/file_access.h"
#include "core/math/basis.h"
#include "core/math/camera_matrix.h"
#include "core/math/delaunay_3d.h"
#include "core/math/geometry_2d.h"
#include "core/math/math_funcs.h"
-#include "core/math/transform.h"
-#include "core/os/file_access.h"
+#include "core/math/transform_3d.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -529,8 +529,8 @@ MainLoop *test() {
ERR_FAIL_COND_V_MSG(!fa, nullptr, "Could not open file: " + test);
Vector<uint8_t> buf;
- int flen = fa->get_len();
- buf.resize(fa->get_len() + 1);
+ uint64_t flen = fa->get_length();
+ buf.resize(fa->get_length() + 1);
fa->get_buffer(buf.ptrw(), flen);
buf.write[flen] = 0;
@@ -599,13 +599,13 @@ MainLoop *test() {
Basis m2(v2, a2);
- Quat q = m;
- Quat q2 = m2;
+ Quaternion q = m;
+ Quaternion q2 = m2;
Basis m3 = m.inverse() * m2;
- Quat q3 = (q.inverse() * q2); //.normalized();
+ Quaternion q3 = (q.inverse() * q2); //.normalized();
- print_line(Quat(m3));
+ print_line(Quaternion(m3));
print_line(q3);
print_line("before v: " + v + " a: " + rtos(a));
diff --git a/tests/test_object.h b/tests/test_object.h
index 142d76553d..b7eedc2670 100644
--- a/tests/test_object.h
+++ b/tests/test_object.h
@@ -93,35 +93,8 @@ public:
Ref<Script> get_script() const override {
return Ref<Script>();
}
- Vector<ScriptNetData> get_rpc_methods() const override {
- return Vector<ScriptNetData>();
- }
- uint16_t get_rpc_method_id(const StringName &p_method) const override {
- return 0;
- }
- StringName get_rpc_method(uint16_t p_id) const override {
- return StringName();
- }
- MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const override {
- return MultiplayerAPI::RPC_MODE_PUPPET;
- }
- MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override {
- return MultiplayerAPI::RPC_MODE_PUPPET;
- }
- Vector<ScriptNetData> get_rset_properties() const override {
- return Vector<ScriptNetData>();
- }
- uint16_t get_rset_property_id(const StringName &p_variable) const override {
- return 0;
- }
- StringName get_rset_property(uint16_t p_id) const override {
- return StringName();
- }
- MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const override {
- return MultiplayerAPI::RPC_MODE_PUPPET;
- }
- MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override {
- return MultiplayerAPI::RPC_MODE_PUPPET;
+ const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override {
+ return Vector<MultiplayerAPI::RPCConfig>();
}
ScriptLanguage *get_language() override {
return nullptr;
@@ -192,8 +165,8 @@ TEST_CASE("[Object] Construction") {
Object object;
CHECK_MESSAGE(
- !object.is_reference(),
- "Object is not a Reference.");
+ !object.is_ref_counted(),
+ "Object is not a RefCounted.");
Object *p_db = ObjectDB::get_instance(object.get_instance_id());
CHECK_MESSAGE(
diff --git a/tests/test_pck_packer.h b/tests/test_pck_packer.h
index 8e4721b821..06e4e64963 100644
--- a/tests/test_pck_packer.h
+++ b/tests/test_pck_packer.h
@@ -62,10 +62,10 @@ TEST_CASE("[PCKPacker] Pack an empty PCK file") {
err == OK,
"The generated empty PCK file should be opened successfully.");
CHECK_MESSAGE(
- f->get_len() >= 100,
+ f->get_length() >= 100,
"The generated empty PCK file shouldn't be too small (it should have the PCK header).");
CHECK_MESSAGE(
- f->get_len() <= 500,
+ f->get_length() <= 500,
"The generated empty PCK file shouldn't be too large.");
}
@@ -103,10 +103,10 @@ TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") {
err == OK,
"The generated non-empty PCK file should be opened successfully.");
CHECK_MESSAGE(
- f->get_len() >= 25000,
+ f->get_length() >= 25000,
"The generated non-empty PCK file should be large enough to actually hold the contents specified above.");
CHECK_MESSAGE(
- f->get_len() <= 35000,
+ f->get_length() <= 35000,
"The generated non-empty PCK file shouldn't be too large.");
}
} // namespace TestPCKPacker
diff --git a/tests/test_physics_2d.cpp b/tests/test_physics_2d.cpp
index 25b2871890..a9e2e92b34 100644
--- a/tests/test_physics_2d.cpp
+++ b/tests/test_physics_2d.cpp
@@ -320,7 +320,7 @@ public:
ps->space_set_active(space, true);
ps->set_active(true);
ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, Vector2(0, 1));
- ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, 98);
+ ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, 980);
{
RID vp = vs->viewport_create();
diff --git a/tests/test_physics_3d.cpp b/tests/test_physics_3d.cpp
index ac8078a0a8..4488e4bf64 100644
--- a/tests/test_physics_3d.cpp
+++ b/tests/test_physics_3d.cpp
@@ -30,8 +30,8 @@
#include "test_physics_3d.h"
+#include "core/math/convex_hull.h"
#include "core/math/math_funcs.h"
-#include "core/math/quick_hull.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -70,14 +70,14 @@ class TestPhysics3DMainLoop : public MainLoop {
void body_changed_transform(Object *p_state, RID p_visual_instance) {
PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state;
RenderingServer *vs = RenderingServer::get_singleton();
- Transform t = state->get_transform();
+ Transform3D t = state->get_transform();
vs->instance_set_transform(p_visual_instance, t);
}
bool quit;
protected:
- RID create_body(PhysicsServer3D::ShapeType p_shape, PhysicsServer3D::BodyMode p_body, const Transform p_location, bool p_active_default = true, const Transform &p_shape_xform = Transform()) {
+ RID create_body(PhysicsServer3D::ShapeType p_shape, PhysicsServer3D::BodyMode p_body, const Transform3D p_location, bool p_active_default = true, const Transform3D &p_shape_xform = Transform3D()) {
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
@@ -169,7 +169,7 @@ protected:
RID convex_mesh = vs->mesh_create();
Geometry3D::MeshData convex_data = Geometry3D::build_convex_mesh(convex_planes);
- QuickHull::build(convex_data.vertices, convex_data);
+ ConvexHullComputer::convex_hull(convex_data.vertices, convex_data);
vs->mesh_add_surface_from_mesh_data(convex_mesh, convex_data);
type_mesh_map[PhysicsServer3D::SHAPE_CONVEX_POLYGON] = convex_mesh;
@@ -179,7 +179,7 @@ protected:
type_shape_map[PhysicsServer3D::SHAPE_CONVEX_POLYGON] = convex_shape;
}
- void make_trimesh(Vector<Vector3> p_faces, const Transform &p_xform = Transform()) {
+ void make_trimesh(Vector<Vector3> p_faces, const Transform3D &p_xform = Transform3D()) {
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
RID trimesh_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON);
@@ -209,12 +209,12 @@ protected:
ps->body_set_space(tribody, space);
//todo set space
ps->body_add_shape(tribody, trimesh_shape);
- Transform tritrans = p_xform;
+ Transform3D tritrans = p_xform;
ps->body_set_state(tribody, PhysicsServer3D::BODY_STATE_TRANSFORM, tritrans);
vs->instance_set_transform(triins, tritrans);
}
- void make_grid(int p_width, int p_height, real_t p_cellsize, real_t p_cellheight, const Transform &p_xform = Transform()) {
+ void make_grid(int p_width, int p_height, real_t p_cellsize, real_t p_cellheight, const Transform3D &p_xform = Transform3D()) {
Vector<Vector<real_t>> grid;
grid.resize(p_width);
@@ -261,7 +261,7 @@ public:
if (mover.is_valid()) {
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
- Transform t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM);
+ Transform3D t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM);
t.origin += Vector3(x, y, 0);
ps->body_set_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM, t);
@@ -287,7 +287,7 @@ public:
scenario = vs->scenario_create();
vs->light_set_shadow(lightaux, true);
light = vs->instance_create2(lightaux, scenario);
- Transform t;
+ Transform3D t;
t.rotate(Vector3(1.0, 0, 0), 0.6);
vs->instance_set_transform(light, t);
@@ -304,9 +304,9 @@ public:
vs->viewport_set_scenario(viewport, scenario);
vs->camera_set_perspective(camera, 60, 0.1, 40.0);
- vs->camera_set_transform(camera, Transform(Basis(), Vector3(0, 9, 12)));
+ vs->camera_set_transform(camera, Transform3D(Basis(), Vector3(0, 9, 12)));
- Transform gxf;
+ Transform3D gxf;
gxf.basis.scale(Vector3(1.4, 0.4, 1.4));
gxf.origin = Vector3(-2, 1, -2);
make_grid(5, 5, 2.5, 1, gxf);
@@ -317,12 +317,12 @@ public:
if (mover.is_valid()) {
static real_t joy_speed = 10;
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
- Transform t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM);
+ Transform3D t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM);
t.origin += Vector3(joy_speed * joy_direction.x * p_time, -joy_speed * joy_direction.y * p_time, 0);
ps->body_set_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM, t);
};
- Transform cameratr;
+ Transform3D cameratr;
cameratr.rotate(Vector3(0, 1, 0), ofs_x);
cameratr.rotate(Vector3(1, 0, 0), -ofs_y);
cameratr.translate(Vector3(0, 2, 8));
@@ -355,20 +355,20 @@ public:
Dictionary capsule_params;
capsule_params["radius"] = 0.5;
capsule_params["height"] = 1;
- Transform shape_xform;
+ Transform3D shape_xform;
shape_xform.rotate(Vector3(1, 0, 0), Math_PI / 2.0);
//shape_xform.origin=Vector3(1,1,1);
ps->shape_set_data(capsule_shape, capsule_params);
RID mesh_instance = vs->instance_create2(capsule_mesh, scenario);
character = ps->body_create();
- ps->body_set_mode(character, PhysicsServer3D::BODY_MODE_CHARACTER);
+ ps->body_set_mode(character, PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED);
ps->body_set_space(character, space);
//todo add space
ps->body_add_shape(character, capsule_shape);
ps->body_set_force_integration_callback(character, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance);
- ps->body_set_state(character, PhysicsServer3D::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(-2, 5, -2)));
+ ps->body_set_state(character, PhysicsServer3D::BODY_STATE_TRANSFORM, Transform3D(Basis(), Vector3(-2, 5, -2)));
bodies.push_back(character);
}
@@ -383,19 +383,19 @@ public:
PhysicsServer3D::ShapeType type = shape_idx[i % 4];
- Transform t;
+ Transform3D t;
t.origin = Vector3(0.0 * i, 3.5 + 1.1 * i, 0.7 + 0.0 * i);
t.basis.rotate(Vector3(0.2, -1, 0), Math_PI / 2 * 0.6);
- create_body(type, PhysicsServer3D::BODY_MODE_RIGID, t);
+ create_body(type, PhysicsServer3D::BODY_MODE_DYNAMIC, t);
}
create_static_plane(Plane(Vector3(0, 1, 0), -1));
}
void test_activate() {
- create_body(PhysicsServer3D::SHAPE_BOX, PhysicsServer3D::BODY_MODE_RIGID, Transform(Basis(), Vector3(0, 2, 0)), true);
+ create_body(PhysicsServer3D::SHAPE_BOX, PhysicsServer3D::BODY_MODE_DYNAMIC, Transform3D(Basis(), Vector3(0, 2, 0)), true);
create_static_plane(Plane(Vector3(0, 1, 0), -1));
}
diff --git a/tests/test_rect2.h b/tests/test_rect2.h
index b94a8b7d05..c5740167db 100644
--- a/tests/test_rect2.h
+++ b/tests/test_rect2.h
@@ -61,7 +61,7 @@ TEST_CASE("[Rect2] Constructor methods") {
TEST_CASE("[Rect2] String conversion") {
// Note: This also depends on the Vector2 string representation.
CHECK_MESSAGE(
- String(Rect2(0, 100, 1280, 720)) == "0, 100, 1280, 720",
+ String(Rect2(0, 100, 1280, 720)) == "[P: (0, 100), S: (1280, 720)]",
"The string representation should match the expected value.");
}
@@ -144,7 +144,7 @@ TEST_CASE("[Rect2] Absolute coordinates") {
"abs() should return the expected Rect2.");
}
-TEST_CASE("[Rect2] Intersecton") {
+TEST_CASE("[Rect2] Intersection") {
CHECK_MESSAGE(
Rect2(0, 100, 1280, 720).intersection(Rect2(0, 300, 100, 100)).is_equal_approx(Rect2(0, 300, 100, 100)),
"intersection() with fully enclosed Rect2 should return the expected result.");
@@ -273,7 +273,7 @@ TEST_CASE("[Rect2i] Constructor methods") {
TEST_CASE("[Rect2i] String conversion") {
// Note: This also depends on the Vector2 string representation.
CHECK_MESSAGE(
- String(Rect2i(0, 100, 1280, 720)) == "0, 100, 1280, 720",
+ String(Rect2i(0, 100, 1280, 720)) == "[P: (0, 100), S: (1280, 720)]",
"The string representation should match the expected value.");
}
@@ -312,19 +312,19 @@ TEST_CASE("[Rect2i] Basic setters") {
TEST_CASE("[Rect2i] Area getters") {
CHECK_MESSAGE(
- Math::is_equal_approx(Rect2i(0, 100, 1280, 720).get_area(), 921'600),
+ Rect2i(0, 100, 1280, 720).get_area() == 921'600,
"get_area() should return the expected value.");
CHECK_MESSAGE(
- Math::is_equal_approx(Rect2i(0, 100, -1280, -720).get_area(), 921'600),
+ Rect2i(0, 100, -1280, -720).get_area() == 921'600,
"get_area() should return the expected value.");
CHECK_MESSAGE(
- Math::is_equal_approx(Rect2i(0, 100, 1280, -720).get_area(), -921'600),
+ Rect2i(0, 100, 1280, -720).get_area() == -921'600,
"get_area() should return the expected value.");
CHECK_MESSAGE(
- Math::is_equal_approx(Rect2i(0, 100, -1280, 720).get_area(), -921'600),
+ Rect2i(0, 100, -1280, 720).get_area() == -921'600,
"get_area() should return the expected value.");
CHECK_MESSAGE(
- Math::is_zero_approx(Rect2i(0, 100, 0, 720).get_area()),
+ Rect2i(0, 100, 0, 720).get_area() == 0,
"get_area() should return the expected value.");
CHECK_MESSAGE(
diff --git a/tests/test_render.cpp b/tests/test_render.cpp
index 72b2840098..fe223ca258 100644
--- a/tests/test_render.cpp
+++ b/tests/test_render.cpp
@@ -30,8 +30,8 @@
#include "test_render.h"
+#include "core/math/convex_hull.h"
#include "core/math/math_funcs.h"
-#include "core/math/quick_hull.h"
#include "core/os/keyboard.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
@@ -53,7 +53,7 @@ class TestMainLoop : public MainLoop {
struct InstanceInfo {
RID instance;
- Transform base;
+ Transform3D base;
Vector3 rot_axis;
};
@@ -118,7 +118,7 @@ public:
vts.push_back(Vector3(-1, -1, -1));
Geometry3D::MeshData md;
- Error err = QuickHull::build(vts, md);
+ Error err = ConvexHullComputer::convex_hull(vts, md);
print_line("ERR: " + itos(err));
test_cube = vs->mesh_create();
vs->mesh_add_surface_from_mesh_data(test_cube, md);
@@ -165,7 +165,7 @@ public:
vs->viewport_set_active(viewport, true);
vs->viewport_attach_camera(viewport, camera);
vs->viewport_set_scenario(viewport, scenario);
- vs->camera_set_transform(camera, Transform(Basis(), Vector3(0, 3, 30)));
+ vs->camera_set_transform(camera, Transform3D(Basis(), Vector3(0, 3, 30)));
vs->camera_set_perspective(camera, 60, 0.1, 1000);
/*
@@ -182,7 +182,7 @@ public:
vs->light_set_color(lightaux, Color(1.0, 1.0, 1.0));
//vs->light_set_shadow( lightaux, true );
light = vs->instance_create2(lightaux, scenario);
- Transform lla;
+ Transform3D lla;
//lla.set_look_at(Vector3(),Vector3(1, -1, 1));
lla.set_look_at(Vector3(), Vector3(0.0, -0.836026, -0.548690));
@@ -201,7 +201,7 @@ public:
}
virtual bool iteration(float p_time) {
RenderingServer *vs = RenderingServer::get_singleton();
- //Transform t;
+ //Transform3D t;
//t.rotate(Vector3(0, 1, 0), ofs);
//t.translate(Vector3(0,0,20 ));
//vs->camera_set_transform(camera, t);
@@ -211,7 +211,7 @@ public:
//return quit;
for (List<InstanceInfo>::Element *E = instances.front(); E; E = E->next()) {
- Transform pre(Basis(E->get().rot_axis, ofs), Vector3());
+ Transform3D pre(Basis(E->get().rot_axis, ofs), Vector3());
vs->instance_set_transform(E->get().instance, pre * E->get().base);
/*
if( !E->next() ) {
diff --git a/tests/test_shader_lang.cpp b/tests/test_shader_lang.cpp
index 2169350c02..ad763b344e 100644
--- a/tests/test_shader_lang.cpp
+++ b/tests/test_shader_lang.cpp
@@ -30,7 +30,7 @@
#include "test_shader_lang.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
diff --git a/tests/test_string.h b/tests/test_string.h
index 486c17dbbd..7f404a34e8 100644
--- a/tests/test_string.h
+++ b/tests/test_string.h
@@ -299,6 +299,7 @@ TEST_CASE("[String] hex_encode_buffer") {
TEST_CASE("[String] Substr") {
String s = "Killer Baby";
CHECK(s.substr(3, 4) == "ler ");
+ CHECK(s.substr(3) == "ler Baby");
}
TEST_CASE("[String] Find") {
@@ -1129,7 +1130,7 @@ TEST_CASE("[String] Path functions") {
CHECK(String(path[i]).get_basename() == base_name[i]);
CHECK(String(path[i]).get_extension() == ext[i]);
CHECK(String(path[i]).get_file() == file[i]);
- CHECK(String(path[i]).is_abs_path() == abs[i]);
+ CHECK(String(path[i]).is_absolute_path() == abs[i]);
CHECK(String(path[i]).is_rel_path() != abs[i]);
CHECK(String(path[i]).simplify_path().get_base_dir().plus_file(file[i]) == String(path[i]).simplify_path());
}
@@ -1252,8 +1253,10 @@ TEST_CASE("[String] Trim") {
TEST_CASE("[String] Right/Left") {
String s = "aaaTestbbb";
// ^
- CHECK(s.right(6) == "tbbb");
+ CHECK(s.right(6) == "estbbb");
+ CHECK(s.right(-6) == "tbbb");
CHECK(s.left(6) == "aaaTes");
+ CHECK(s.left(-6) == "aaaT");
}
TEST_CASE("[String] Repeat") {
diff --git a/tests/test_time.h b/tests/test_time.h
new file mode 100644
index 0000000000..28f1cb2f20
--- /dev/null
+++ b/tests/test_time.h
@@ -0,0 +1,145 @@
+/*************************************************************************/
+/* test_time.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEST_TIME_H
+#define TEST_TIME_H
+
+#include "core/os/time.h"
+
+#include "thirdparty/doctest/doctest.h"
+
+#define YEAR_KEY "year"
+#define MONTH_KEY "month"
+#define DAY_KEY "day"
+#define WEEKDAY_KEY "weekday"
+#define HOUR_KEY "hour"
+#define MINUTE_KEY "minute"
+#define SECOND_KEY "second"
+#define DST_KEY "dst"
+
+namespace TestTime {
+
+TEST_CASE("[Time] Unix time conversion to/from datetime string") {
+ const Time *time = Time::get_singleton();
+
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("1970-01-01T00:00:00") == 0, "Time get_unix_time_from_datetime_string: The timestamp for Unix epoch is zero.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("1970-01-01 00:00:00") == 0, "Time get_unix_time_from_datetime_string: The timestamp for Unix epoch with space is zero.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("1970-01-01") == 0, "Time get_unix_time_from_datetime_string: The timestamp for Unix epoch without time is zero.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("00:00:00") == 0, "Time get_unix_time_from_datetime_string: The timestamp for zero time without date is zero.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("1969-12-31T23:59:59") == -1, "Time get_unix_time_from_datetime_string: The timestamp for just before Unix epoch is negative one.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("1234-05-06T07:08:09") == -23215049511, "Time get_unix_time_from_datetime_string: The timestamp for an arbitrary datetime is as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("1234-05-06 07:08:09") == -23215049511, "Time get_unix_time_from_datetime_string: The timestamp for an arbitrary datetime with space is as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("1234-05-06") == -23215075200, "Time get_unix_time_from_datetime_string: The timestamp for an arbitrary date without time is as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("07:08:09") == 25689, "Time get_unix_time_from_datetime_string: The timestamp for an arbitrary time without date is as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("2014-02-09T22:10:30") == 1391983830, "Time get_unix_time_from_datetime_string: The timestamp for GODOT IS OPEN SOURCE is as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("2014-02-09 22:10:30") == 1391983830, "Time get_unix_time_from_datetime_string: The timestamp for GODOT IS OPEN SOURCE with space is as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("2014-02-09") == 1391904000, "Time get_unix_time_from_datetime_string: The date for GODOT IS OPEN SOURCE without time is as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("22:10:30") == 79830, "Time get_unix_time_from_datetime_string: The time for GODOT IS OPEN SOURCE without date is as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("-1000000000-01-01T00:00:00") == -31557014167219200, "Time get_unix_time_from_datetime_string: In the year negative a billion, Japan might not have been here.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string("1000000-01-01T00:00:00") == 31494784780800, "Time get_unix_time_from_datetime_string: The timestamp for the year a million is as expected.");
+
+ CHECK_MESSAGE(time->get_datetime_string_from_unix_time(0) == "1970-01-01T00:00:00", "Time get_datetime_string_from_unix_time: The timestamp string for Unix epoch is zero.");
+ CHECK_MESSAGE(time->get_datetime_string_from_unix_time(0, true) == "1970-01-01 00:00:00", "Time get_datetime_string_from_unix_time: The timestamp string for Unix epoch with space is zero.");
+ CHECK_MESSAGE(time->get_date_string_from_unix_time(0) == "1970-01-01", "Time get_date_string_from_unix_time: The date string for zero is Unix epoch date.");
+ CHECK_MESSAGE(time->get_time_string_from_unix_time(0) == "00:00:00", "Time get_time_string_from_unix_time: The date for zero zero is Unix epoch date.");
+ CHECK_MESSAGE(time->get_datetime_string_from_unix_time(-1) == "1969-12-31T23:59:59", "Time get_time_string_from_unix_time: The timestamp string for just before Unix epoch is as expected.");
+ CHECK_MESSAGE(time->get_datetime_string_from_unix_time(-23215049511) == "1234-05-06T07:08:09", "Time get_datetime_string_from_unix_time: The timestamp for an arbitrary datetime is as expected.");
+ CHECK_MESSAGE(time->get_datetime_string_from_unix_time(-23215049511, true) == "1234-05-06 07:08:09", "Time get_datetime_string_from_unix_time: The timestamp for an arbitrary datetime with space is as expected.");
+ CHECK_MESSAGE(time->get_date_string_from_unix_time(-23215075200) == "1234-05-06", "Time get_date_string_from_unix_time: The timestamp for an arbitrary date without time is as expected.");
+ CHECK_MESSAGE(time->get_time_string_from_unix_time(25689) == "07:08:09", "Time get_time_string_from_unix_time: The timestamp for an arbitrary time without date is as expected.");
+ CHECK_MESSAGE(time->get_datetime_string_from_unix_time(1391983830) == "2014-02-09T22:10:30", "Time get_datetime_string_from_unix_time: The timestamp for GODOT IS OPEN SOURCE is as expected.");
+ CHECK_MESSAGE(time->get_datetime_string_from_unix_time(1391983830, true) == "2014-02-09 22:10:30", "Time get_datetime_string_from_unix_time: The timestamp for GODOT IS OPEN SOURCE with space is as expected.");
+ CHECK_MESSAGE(time->get_date_string_from_unix_time(1391904000) == "2014-02-09", "Time get_date_string_from_unix_time: The date for GODOT IS OPEN SOURCE without time is as expected.");
+ CHECK_MESSAGE(time->get_time_string_from_unix_time(79830) == "22:10:30", "Time get_time_string_from_unix_time: The time for GODOT IS OPEN SOURCE without date is as expected.");
+ CHECK_MESSAGE(time->get_datetime_string_from_unix_time(31494784780800) == "1000000-01-01T00:00:00", "Time get_datetime_string_from_unix_time: The timestamp for the year a million is as expected.");
+}
+
+TEST_CASE("[Time] Datetime dictionary conversion methods") {
+ const Time *time = Time::get_singleton();
+
+ Dictionary datetime;
+ datetime[YEAR_KEY] = 2014;
+ datetime[MONTH_KEY] = 2;
+ datetime[DAY_KEY] = 9;
+ datetime[WEEKDAY_KEY] = Time::Weekday::WEEKDAY_SUNDAY;
+ datetime[HOUR_KEY] = 22;
+ datetime[MINUTE_KEY] = 10;
+ datetime[SECOND_KEY] = 30;
+
+ Dictionary date_only;
+ date_only[YEAR_KEY] = 2014;
+ date_only[MONTH_KEY] = 2;
+ date_only[DAY_KEY] = 9;
+ date_only[WEEKDAY_KEY] = Time::Weekday::WEEKDAY_SUNDAY;
+
+ Dictionary time_only;
+ time_only[HOUR_KEY] = 22;
+ time_only[MINUTE_KEY] = 10;
+ time_only[SECOND_KEY] = 30;
+
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_dict(datetime) == 1391983830, "Time get_unix_time_from_datetime_dict: The datetime dictionary for GODOT IS OPEN SOURCE is converted to a timestamp as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_dict(date_only) == 1391904000, "Time get_unix_time_from_datetime_dict: The date dictionary for GODOT IS OPEN SOURCE is converted to a timestamp as expected.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_dict(time_only) == 79830, "Time get_unix_time_from_datetime_dict: The time dictionary for GODOT IS OPEN SOURCE is converted to a timestamp as expected.");
+
+ CHECK_MESSAGE(time->get_datetime_dict_from_unix_time(1391983830).hash() == datetime.hash(), "Time get_datetime_dict_from_unix_time: The datetime timestamp for GODOT IS OPEN SOURCE is converted to a dictionary as expected.");
+ CHECK_MESSAGE(time->get_date_dict_from_unix_time(1391904000).hash() == date_only.hash(), "Time get_date_dict_from_unix_time: The date timestamp for GODOT IS OPEN SOURCE is converted to a dictionary as expected.");
+ CHECK_MESSAGE(time->get_time_dict_from_unix_time(79830).hash() == time_only.hash(), "Time get_time_dict_from_unix_time: The time timestamp for GODOT IS OPEN SOURCE is converted to a dictionary as expected.");
+
+ CHECK_MESSAGE((Time::Weekday)(int)time->get_datetime_dict_from_unix_time(0)[WEEKDAY_KEY] == Time::Weekday::WEEKDAY_THURSDAY, "Time get_datetime_dict_from_unix_time: The weekday for the Unix epoch is a Thursday as expected.");
+ CHECK_MESSAGE((Time::Weekday)(int)time->get_datetime_dict_from_unix_time(1391983830)[WEEKDAY_KEY] == Time::Weekday::WEEKDAY_SUNDAY, "Time get_datetime_dict_from_unix_time: The weekday for GODOT IS OPEN SOURCE is a Sunday as expected.");
+
+ CHECK_MESSAGE(time->get_datetime_dict_from_string("2014-02-09T22:10:30").hash() == datetime.hash(), "Time get_datetime_dict_from_string: The dictionary from string for GODOT IS OPEN SOURCE works as expected.");
+ CHECK_MESSAGE(!time->get_datetime_dict_from_string("2014-02-09T22:10:30", false).has(WEEKDAY_KEY), "Time get_datetime_dict_from_string: The dictionary from string for GODOT IS OPEN SOURCE without weekday doesn't contain the weekday key as expected.");
+ CHECK_MESSAGE(time->get_datetime_string_from_dict(datetime) == "2014-02-09T22:10:30", "Time get_datetime_string_from_dict: The string from dictionary for GODOT IS OPEN SOURCE works as expected.");
+ CHECK_MESSAGE(time->get_datetime_string_from_dict(time->get_datetime_dict_from_string("2014-02-09T22:10:30")) == "2014-02-09T22:10:30", "Time get_datetime_string_from_dict: The round-trip string to dict to string GODOT IS OPEN SOURCE works as expected.");
+ CHECK_MESSAGE(time->get_datetime_string_from_dict(time->get_datetime_dict_from_string("2014-02-09 22:10:30"), true) == "2014-02-09 22:10:30", "Time get_datetime_string_from_dict: The round-trip string to dict to string GODOT IS OPEN SOURCE with spaces works as expected.");
+}
+
+TEST_CASE("[Time] System time methods") {
+ const Time *time = Time::get_singleton();
+
+ const uint64_t ticks_msec = time->get_ticks_msec();
+ const uint64_t ticks_usec = time->get_ticks_usec();
+
+ CHECK_MESSAGE(time->get_unix_time_from_system() > 1000000000, "Time get_unix_time_from_system: The timestamp from system time doesn't fail and is very positive.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_dict(time->get_datetime_dict_from_system()) > 1000000000, "Time get_datetime_string_from_system: The timestamp from system time doesn't fail and is very positive.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_dict(time->get_date_dict_from_system()) > 1000000000, "Time get_datetime_string_from_system: The date from system time doesn't fail and is very positive.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_dict(time->get_time_dict_from_system()) < 86400, "Time get_datetime_string_from_system: The time from system time doesn't fail and is within the acceptable range.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string(time->get_datetime_string_from_system()) > 1000000000, "Time get_datetime_string_from_system: The timestamp from system time doesn't fail and is very positive.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string(time->get_date_string_from_system()) > 1000000000, "Time get_datetime_string_from_system: The date from system time doesn't fail and is very positive.");
+ CHECK_MESSAGE(time->get_unix_time_from_datetime_string(time->get_time_string_from_system()) < 86400, "Time get_datetime_string_from_system: The time from system time doesn't fail and is within the acceptable range.");
+
+ CHECK_MESSAGE(time->get_ticks_msec() >= ticks_msec, "Time get_ticks_msec: The value has not decreased.");
+ CHECK_MESSAGE(time->get_ticks_usec() > ticks_usec, "Time get_ticks_usec: The value has increased.");
+}
+
+} // namespace TestTime
+
+#endif // TEST_TIME_H
diff --git a/tests/test_translation.h b/tests/test_translation.h
new file mode 100644
index 0000000000..52ff49bf9b
--- /dev/null
+++ b/tests/test_translation.h
@@ -0,0 +1,150 @@
+/*************************************************************************/
+/* test_translation.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEST_TRANSLATION_H
+#define TEST_TRANSLATION_H
+
+#include "core/string/optimized_translation.h"
+#include "core/string/translation.h"
+#include "core/string/translation_po.h"
+
+#include "thirdparty/doctest/doctest.h"
+
+namespace TestTranslation {
+
+TEST_CASE("[Translation] Messages") {
+ Ref<Translation> translation = memnew(Translation);
+ translation->set_locale("fr");
+ translation->add_message("Hello", "Bonjour");
+ CHECK(translation->get_message("Hello") == "Bonjour");
+
+ translation->erase_message("Hello");
+ // The message no longer exists, so it returns an empty string instead.
+ CHECK(translation->get_message("Hello") == "");
+
+ List<StringName> messages;
+ translation->get_message_list(&messages);
+ CHECK(translation->get_message_count() == 0);
+ CHECK(messages.size() == 0);
+
+ translation->add_message("Hello2", "Bonjour2");
+ translation->add_message("Hello3", "Bonjour3");
+ messages.clear();
+ translation->get_message_list(&messages);
+ CHECK(translation->get_message_count() == 2);
+ CHECK(messages.size() == 2);
+ // Messages are stored in a Map, don't assume ordering.
+ CHECK(messages.find("Hello2"));
+ CHECK(messages.find("Hello3"));
+}
+
+TEST_CASE("[TranslationPO] Messages with context") {
+ Ref<TranslationPO> translation = memnew(TranslationPO);
+ translation->set_locale("fr");
+ translation->add_message("Hello", "Bonjour");
+ translation->add_message("Hello", "Salut", "friendly");
+ CHECK(translation->get_message("Hello") == "Bonjour");
+ CHECK(translation->get_message("Hello", "friendly") == "Salut");
+ CHECK(translation->get_message("Hello", "nonexistent_context") == "");
+
+ // Only remove the message for the default context, not the "friendly" context.
+ translation->erase_message("Hello");
+ // The message no longer exists, so it returns an empty string instead.
+ CHECK(translation->get_message("Hello") == "");
+ CHECK(translation->get_message("Hello", "friendly") == "Salut");
+ CHECK(translation->get_message("Hello", "nonexistent_context") == "");
+
+ List<StringName> messages;
+ translation->get_message_list(&messages);
+
+ // `get_message_count()` takes all contexts into account.
+ CHECK(translation->get_message_count() == 1);
+ // Only the default context is taken into account.
+ // Since "Hello" is now only present in a non-default context, it is not counted in the list of messages.
+ CHECK(messages.size() == 0);
+
+ translation->add_message("Hello2", "Bonjour2");
+ translation->add_message("Hello2", "Salut2", "friendly");
+ translation->add_message("Hello3", "Bonjour3");
+ messages.clear();
+ translation->get_message_list(&messages);
+
+ // `get_message_count()` takes all contexts into account.
+ CHECK(translation->get_message_count() == 4);
+ // Only the default context is taken into account.
+ CHECK(messages.size() == 2);
+ // Messages are stored in a Map, don't assume ordering.
+ CHECK(messages.find("Hello2"));
+ CHECK(messages.find("Hello3"));
+}
+
+TEST_CASE("[TranslationPO] Plural messages") {
+ Ref<TranslationPO> translation = memnew(TranslationPO);
+ translation->set_locale("fr");
+ translation->set_plural_rule("Plural-Forms: nplurals=2; plural=(n >= 2);");
+ CHECK(translation->get_plural_forms() == 2);
+
+ PackedStringArray plurals;
+ plurals.push_back("Il y a %d pomme");
+ plurals.push_back("Il y a %d pommes");
+ translation->add_plural_message("There are %d apples", plurals);
+ ERR_PRINT_OFF;
+ // This is invalid, as the number passed to `get_plural_message()` may not be negative.
+ CHECK(vformat(translation->get_plural_message("There are %d apples", "", -1), -1) == "");
+ ERR_PRINT_ON;
+ CHECK(vformat(translation->get_plural_message("There are %d apples", "", 0), 0) == "Il y a 0 pomme");
+ CHECK(vformat(translation->get_plural_message("There are %d apples", "", 1), 1) == "Il y a 1 pomme");
+ CHECK(vformat(translation->get_plural_message("There are %d apples", "", 2), 2) == "Il y a 2 pommes");
+}
+
+TEST_CASE("[OptimizedTranslation] Generate from Translation and read messages") {
+ Ref<Translation> translation = memnew(Translation);
+ translation->set_locale("fr");
+ translation->add_message("Hello", "Bonjour");
+ translation->add_message("Hello2", "Bonjour2");
+ translation->add_message("Hello3", "Bonjour3");
+
+ Ref<OptimizedTranslation> optimized_translation = memnew(OptimizedTranslation);
+ optimized_translation->generate(translation);
+ CHECK(optimized_translation->get_message("Hello") == "Bonjour");
+ CHECK(optimized_translation->get_message("Hello2") == "Bonjour2");
+ CHECK(optimized_translation->get_message("Hello3") == "Bonjour3");
+ CHECK(optimized_translation->get_message("DoesNotExist") == "");
+
+ List<StringName> messages;
+ // `get_message_list()` can't return the list of messages stored in an OptimizedTranslation.
+ optimized_translation->get_message_list(&messages);
+ CHECK(optimized_translation->get_message_count() == 0);
+ CHECK(messages.size() == 0);
+}
+
+} // namespace TestTranslation
+
+#endif // TEST_TRANSLATION_H
diff --git a/tests/test_validate_testing.h b/tests/test_validate_testing.h
index 6d3eea724c..f301047509 100644
--- a/tests/test_validate_testing.h
+++ b/tests/test_validate_testing.h
@@ -84,7 +84,7 @@ TEST_SUITE("Validate tests") {
Plane plane(Vector3(1, 1, 1), 1.0);
INFO(plane);
- Quat quat(Vector3(0.5, 1.0, 2.0));
+ Quaternion quat(Vector3(0.5, 1.0, 2.0));
INFO(quat);
AABB aabb(Vector3(), Vector3(100, 100, 100));
@@ -93,7 +93,7 @@ TEST_SUITE("Validate tests") {
Basis basis(quat);
INFO(basis);
- Transform trans(basis);
+ Transform3D trans(basis);
INFO(trans);
Color color(1, 0.5, 0.2, 0.3);
diff --git a/tests/test_vector.h b/tests/test_vector.h
new file mode 100644
index 0000000000..02c56e59f6
--- /dev/null
+++ b/tests/test_vector.h
@@ -0,0 +1,496 @@
+/*************************************************************************/
+/* test_vector.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEST_VECTOR_H
+#define TEST_VECTOR_H
+
+#include "core/templates/vector.h"
+
+#include "tests/test_macros.h"
+
+namespace TestVector {
+
+TEST_CASE("[Vector] Push back and append") {
+ Vector<int> vector;
+ vector.push_back(0);
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ // Alias for `push_back`.
+ vector.append(4);
+
+ CHECK(vector[0] == 0);
+ CHECK(vector[1] == 1);
+ CHECK(vector[2] == 2);
+ CHECK(vector[3] == 3);
+ CHECK(vector[4] == 4);
+}
+
+TEST_CASE("[Vector] Append array") {
+ Vector<int> vector;
+ vector.push_back(1);
+ vector.push_back(2);
+
+ Vector<int> vector_other;
+ vector_other.push_back(128);
+ vector_other.push_back(129);
+ vector.append_array(vector_other);
+
+ CHECK(vector.size() == 4);
+ CHECK(vector[0] == 1);
+ CHECK(vector[1] == 2);
+ CHECK(vector[2] == 128);
+ CHECK(vector[3] == 129);
+}
+
+TEST_CASE("[Vector] Insert") {
+ Vector<int> vector;
+ vector.insert(0, 2);
+ vector.insert(0, 8);
+ vector.insert(2, 5);
+ vector.insert(1, 5);
+ vector.insert(0, -2);
+
+ CHECK(vector.size() == 5);
+ CHECK(vector[0] == -2);
+ CHECK(vector[1] == 8);
+ CHECK(vector[2] == 5);
+ CHECK(vector[3] == 2);
+ CHECK(vector[4] == 5);
+}
+
+TEST_CASE("[Vector] Ordered insert") {
+ Vector<int> vector;
+ vector.ordered_insert(2);
+ vector.ordered_insert(8);
+ vector.ordered_insert(5);
+ vector.ordered_insert(5);
+ vector.ordered_insert(-2);
+
+ CHECK(vector.size() == 5);
+ CHECK(vector[0] == -2);
+ CHECK(vector[1] == 2);
+ CHECK(vector[2] == 5);
+ CHECK(vector[3] == 5);
+ CHECK(vector[4] == 8);
+}
+
+TEST_CASE("[Vector] Insert + Ordered insert") {
+ Vector<int> vector;
+ vector.ordered_insert(2);
+ vector.ordered_insert(8);
+ vector.insert(0, 5);
+ vector.ordered_insert(5);
+ vector.insert(1, -2);
+
+ CHECK(vector.size() == 5);
+ CHECK(vector[0] == 5);
+ CHECK(vector[1] == -2);
+ CHECK(vector[2] == 2);
+ CHECK(vector[3] == 5);
+ CHECK(vector[4] == 8);
+}
+
+TEST_CASE("[Vector] Fill large array and modify it") {
+ Vector<int> vector;
+ vector.resize(1'000'000);
+ vector.fill(0x60d07);
+
+ vector.write[200] = 0;
+ CHECK(vector.size() == 1'000'000);
+ CHECK(vector[0] == 0x60d07);
+ CHECK(vector[200] == 0);
+ CHECK(vector[499'999] == 0x60d07);
+ CHECK(vector[999'999] == 0x60d07);
+ vector.remove(200);
+ CHECK(vector[200] == 0x60d07);
+
+ vector.clear();
+ CHECK(vector.size() == 0);
+}
+
+TEST_CASE("[Vector] Copy creation") {
+ Vector<int> vector;
+ vector.push_back(0);
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ vector.push_back(4);
+
+ Vector<int> vector_other = Vector<int>(vector);
+ vector_other.remove(0);
+ CHECK(vector_other[0] == 1);
+ CHECK(vector_other[1] == 2);
+ CHECK(vector_other[2] == 3);
+ CHECK(vector_other[3] == 4);
+
+ // Make sure the original vector isn't modified.
+ CHECK(vector[0] == 0);
+ CHECK(vector[1] == 1);
+ CHECK(vector[2] == 2);
+ CHECK(vector[3] == 3);
+ CHECK(vector[4] == 4);
+}
+
+TEST_CASE("[Vector] Duplicate") {
+ Vector<int> vector;
+ vector.push_back(0);
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ vector.push_back(4);
+
+ Vector<int> vector_other = vector.duplicate();
+ vector_other.remove(0);
+ CHECK(vector_other[0] == 1);
+ CHECK(vector_other[1] == 2);
+ CHECK(vector_other[2] == 3);
+ CHECK(vector_other[3] == 4);
+
+ // Make sure the original vector isn't modified.
+ CHECK(vector[0] == 0);
+ CHECK(vector[1] == 1);
+ CHECK(vector[2] == 2);
+ CHECK(vector[3] == 3);
+ CHECK(vector[4] == 4);
+}
+
+TEST_CASE("[Vector] Get, set") {
+ Vector<int> vector;
+ vector.push_back(0);
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ vector.push_back(4);
+
+ CHECK(vector.get(0) == 0);
+ CHECK(vector.get(1) == 1);
+ vector.set(2, 256);
+ CHECK(vector.get(2) == 256);
+ CHECK(vector.get(3) == 3);
+
+ ERR_PRINT_OFF;
+ // Invalid (but should not crash): setting out of bounds.
+ vector.set(6, 500);
+ ERR_PRINT_ON;
+
+ CHECK(vector.get(4) == 4);
+}
+
+TEST_CASE("[Vector] To byte array") {
+ Vector<int> vector;
+ vector.push_back(0);
+ vector.push_back(-1);
+ vector.push_back(2008);
+ vector.push_back(999999999);
+
+ Vector<uint8_t> byte_array = vector.to_byte_array();
+ CHECK(byte_array.size() == 16);
+ // vector[0]
+ CHECK(byte_array[0] == 0);
+ CHECK(byte_array[1] == 0);
+ CHECK(byte_array[2] == 0);
+ CHECK(byte_array[3] == 0);
+
+ // vector[1]
+ CHECK(byte_array[4] == 255);
+ CHECK(byte_array[5] == 255);
+ CHECK(byte_array[6] == 255);
+ CHECK(byte_array[7] == 255);
+
+ // vector[2]
+ CHECK(byte_array[8] == 216);
+ CHECK(byte_array[9] == 7);
+ CHECK(byte_array[10] == 0);
+ CHECK(byte_array[11] == 0);
+
+ // vector[3]
+ CHECK(byte_array[12] == 255);
+ CHECK(byte_array[13] == 201);
+ CHECK(byte_array[14] == 154);
+ CHECK(byte_array[15] == 59);
+}
+
+TEST_CASE("[Vector] Subarray") {
+ Vector<int> vector;
+ vector.push_back(0);
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ vector.push_back(4);
+
+ Vector<int> subarray1 = vector.subarray(1, 2);
+ CHECK(subarray1.size() == 2);
+ CHECK(subarray1[0] == 1);
+ CHECK(subarray1[1] == 2);
+
+ Vector<int> subarray2 = vector.subarray(1, -1);
+ CHECK(subarray2.size() == 4);
+ CHECK(subarray2[0] == 1);
+ CHECK(subarray2[1] == 2);
+ CHECK(subarray2[2] == 3);
+ CHECK(subarray2[3] == 4);
+
+ Vector<int> subarray3 = vector.subarray(-2, -1);
+ CHECK(subarray3.size() == 2);
+ CHECK(subarray3[0] == 3);
+ CHECK(subarray3[1] == 4);
+
+ Vector<int> subarray4 = vector.subarray(-3, 3);
+ CHECK(subarray4.size() == 2);
+ CHECK(subarray4[0] == 2);
+ CHECK(subarray4[1] == 3);
+}
+
+TEST_CASE("[Vector] Find, has") {
+ Vector<int> vector;
+ vector.push_back(3);
+ vector.push_back(1);
+ vector.push_back(4);
+ vector.push_back(0);
+ vector.push_back(2);
+
+ CHECK(vector[0] == 3);
+ CHECK(vector[1] == 1);
+ CHECK(vector[2] == 4);
+ CHECK(vector[3] == 0);
+ CHECK(vector[4] == 2);
+
+ CHECK(vector.find(0) == 3);
+ CHECK(vector.find(1) == 1);
+ CHECK(vector.find(2) == 4);
+ CHECK(vector.find(3) == 0);
+ CHECK(vector.find(4) == 2);
+
+ CHECK(vector.find(-1) == -1);
+ CHECK(vector.find(5) == -1);
+
+ CHECK(vector.has(0));
+ CHECK(vector.has(1));
+ CHECK(vector.has(2));
+ CHECK(vector.has(3));
+ CHECK(vector.has(4));
+
+ CHECK(!vector.has(-1));
+ CHECK(!vector.has(5));
+}
+
+TEST_CASE("[Vector] Remove") {
+ Vector<int> vector;
+ vector.push_back(0);
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ vector.push_back(4);
+
+ vector.remove(0);
+
+ CHECK(vector[0] == 1);
+ CHECK(vector[1] == 2);
+ CHECK(vector[2] == 3);
+ CHECK(vector[3] == 4);
+
+ vector.remove(2);
+
+ CHECK(vector[0] == 1);
+ CHECK(vector[1] == 2);
+ CHECK(vector[2] == 4);
+
+ vector.remove(1);
+
+ CHECK(vector[0] == 1);
+ CHECK(vector[1] == 4);
+
+ vector.remove(0);
+
+ CHECK(vector[0] == 4);
+}
+
+TEST_CASE("[Vector] Remove and find") {
+ Vector<int> vector;
+ vector.push_back(0);
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ vector.push_back(4);
+
+ CHECK(vector.size() == 5);
+
+ vector.remove(0);
+
+ CHECK(vector.size() == 4);
+
+ CHECK(vector.find(0) == -1);
+ CHECK(vector.find(1) != -1);
+ CHECK(vector.find(2) != -1);
+ CHECK(vector.find(3) != -1);
+ CHECK(vector.find(4) != -1);
+
+ vector.remove(vector.find(3));
+
+ CHECK(vector.size() == 3);
+
+ CHECK(vector.find(3) == -1);
+ CHECK(vector.find(1) != -1);
+ CHECK(vector.find(2) != -1);
+ CHECK(vector.find(4) != -1);
+
+ vector.remove(vector.find(2));
+
+ CHECK(vector.size() == 2);
+
+ CHECK(vector.find(2) == -1);
+ CHECK(vector.find(1) != -1);
+ CHECK(vector.find(4) != -1);
+
+ vector.remove(vector.find(4));
+
+ CHECK(vector.size() == 1);
+
+ CHECK(vector.find(4) == -1);
+ CHECK(vector.find(1) != -1);
+
+ vector.remove(0);
+
+ CHECK(vector.is_empty());
+ CHECK(vector.size() == 0);
+}
+
+TEST_CASE("[Vector] Erase") {
+ Vector<int> vector;
+ vector.push_back(1);
+ vector.push_back(3);
+ vector.push_back(0);
+ vector.push_back(2);
+ vector.push_back(4);
+
+ CHECK(vector.find(2) == 3);
+
+ vector.erase(2);
+
+ CHECK(vector.find(2) == -1);
+ CHECK(vector.size() == 4);
+}
+
+TEST_CASE("[Vector] Size, resize, reserve") {
+ Vector<int> vector;
+ CHECK(vector.is_empty());
+ CHECK(vector.size() == 0);
+
+ vector.resize(10);
+
+ CHECK(vector.size() == 10);
+
+ vector.resize(5);
+
+ CHECK(vector.size() == 5);
+
+ vector.remove(0);
+ vector.remove(0);
+ vector.remove(0);
+
+ CHECK(vector.size() == 2);
+
+ vector.clear();
+
+ CHECK(vector.size() == 0);
+ CHECK(vector.is_empty());
+
+ vector.push_back(0);
+ vector.push_back(0);
+ vector.push_back(0);
+
+ CHECK(vector.size() == 3);
+
+ vector.push_back(0);
+
+ CHECK(vector.size() == 4);
+}
+
+TEST_CASE("[Vector] Sort") {
+ Vector<int> vector;
+ vector.push_back(2);
+ vector.push_back(8);
+ vector.push_back(-4);
+ vector.push_back(5);
+ vector.sort();
+
+ CHECK(vector.size() == 4);
+ CHECK(vector[0] == -4);
+ CHECK(vector[1] == 2);
+ CHECK(vector[2] == 5);
+ CHECK(vector[3] == 8);
+}
+
+TEST_CASE("[Vector] Sort custom") {
+ Vector<String> vector;
+ vector.push_back("world");
+ vector.push_back("World");
+ vector.push_back("Hello");
+ vector.push_back("10Hello");
+ vector.push_back("12Hello");
+ vector.push_back("01Hello");
+ vector.push_back("1Hello");
+ vector.push_back(".Hello");
+ vector.sort_custom<NaturalNoCaseComparator>();
+
+ CHECK(vector.size() == 8);
+ CHECK(vector[0] == ".Hello");
+ CHECK(vector[1] == "01Hello");
+ CHECK(vector[2] == "1Hello");
+ CHECK(vector[3] == "10Hello");
+ CHECK(vector[4] == "12Hello");
+ CHECK(vector[5] == "Hello");
+ CHECK(vector[6] == "world");
+ CHECK(vector[7] == "World");
+}
+
+TEST_CASE("[Vector] Operators") {
+ Vector<int> vector;
+ vector.push_back(2);
+ vector.push_back(8);
+ vector.push_back(-4);
+ vector.push_back(5);
+
+ Vector<int> vector_other;
+ vector_other.push_back(2);
+ vector_other.push_back(8);
+ vector_other.push_back(-4);
+ vector_other.push_back(5);
+
+ CHECK(vector == vector_other);
+
+ vector_other.push_back(10);
+ CHECK(vector != vector_other);
+}
+
+} // namespace TestVector
+
+#endif // TEST_VECTOR_H
diff --git a/thirdparty/README.md b/thirdparty/README.md
index c6d8d06ee5..03a2ddf5e4 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -61,10 +61,10 @@ Files extracted from upstream source:
Extracted from .zip provided. Extracted license and header only.
-## embree-aarch64
+## embree
-- Upstream: https://github.com/lighttransport/embree-aarch64
-- Version: 3.12.1 (6ef362f99af80c9dfe8dd2bfc582d9067897edc6, 2020)
+- Upstream: https://github.com/embree/embree
+- Version: 3.13.0 (7c53133eb21424f7f0ae1e25bf357e358feaf6ab, 2021)
- License: Apache 2.0
Files extracted from upstream:
@@ -72,8 +72,8 @@ Files extracted from upstream:
- All cpp files listed in `modules/raycast/godot_update_embree.py`
- All header files in the directories listed in `modules/raycast/godot_update_embree.py`
-The `modules/raycast/godot_update_embree.py`script can be used to pull the
-relevant files from the latest Embree-aarch64 release and apply some automatic changes.
+The `modules/raycast/godot_update_embree.py` script can be used to pull the
+relevant files from the latest Embree release and apply some automatic changes.
Some changes have been made in order to remove exceptions and fix minor build errors.
They are marked with `// -- GODOT start --` and `// -- GODOT end --`
@@ -137,6 +137,10 @@ Files extracted from upstream source:
* Upstream: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/
* Version: ? (pre-2014 commit when DroidSansJapanese.ttf was obsoleted)
* License: Apache 2.0
+- `OpenSans_SemiBold.ttf`:
+ * Upstream: https://fonts.google.com/specimen/Open+Sans
+ * Version: 1.10 (downloaded from Google Fonts in February 2021)
+ * License: Apache 2.0
- `Tamsyn*.png`:
* Upstream: http://www.fial.com/~scott/tamsyn-font/
* Version: 1.11 (2015)
@@ -363,7 +367,7 @@ File extracted from upstream release tarball:
## meshoptimizer
- Upstream: https://github.com/zeux/meshoptimizer
-- Version: 0.16 (95893c0566646434dd675b708d293fcb2d526d08, 2021)
+- Version: git (f5d83e879c48f8664783a69b4f50711d27549b66, 2021)
- License: MIT
Files extracted from upstream repository:
@@ -371,6 +375,9 @@ Files extracted from upstream repository:
- All files in `src/`.
- `LICENSE.md`.
+An [experimental upstream feature](https://github.com/zeux/meshoptimizer/tree/simplify-attr),
+has been backported, see patch in `patches` directory.
+
## miniupnpc
@@ -462,6 +469,10 @@ Collection of single-file libraries used in Godot components.
* Version: git (2f625846a775501fb69456567409a8b12f10ea25, 2012)
* License: BSD-3-Clause
* Modifications: use `const char*` instead of `char*` for input string
+- `smolv.h`
+ * Upstream: https://github.com/aras-p/smol-v
+ * Version: git (4b52c165c13763051a18e80ffbc2ee436314ceb2, 2020)
+ * License: Public Domain or MIT
- `stb_rect_pack.h`
* Upstream: https://github.com/nothings/stb
* Version: 1.00 (2bb4a0accd4003c1db4c24533981e01b1adfd656, 2019)
@@ -724,3 +735,4 @@ Files extracted from upstream source:
- lib/{common/,compress/,decompress/,zstd.h}
- LICENSE
+
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_any_of.h b/thirdparty/embree-aarch64/common/algorithms/parallel_any_of.h
deleted file mode 100644
index 01f1f80f6c..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_any_of.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include <functional>
-#include "parallel_reduce.h"
-
-namespace embree
-{
-
- template<typename Index, class UnaryPredicate>
- __forceinline bool parallel_any_of (Index first, Index last, UnaryPredicate pred)
- {
- bool ret = false;
-
-#if defined(TASKING_TBB)
-#if TBB_INTERFACE_VERSION >= 12002
- tbb::task_group_context context;
- tbb::parallel_for(tbb::blocked_range<size_t>{first, last}, [&ret,pred,&context](const tbb::blocked_range<size_t>& r) {
- if (context.is_group_execution_cancelled()) return;
- for (size_t i = r.begin(); i != r.end(); ++i) {
- if (pred(i)) {
- ret = true;
- context.cancel_group_execution();
- }
- }
- });
-#else
- tbb::parallel_for(tbb::blocked_range<size_t>{first, last}, [&ret,pred](const tbb::blocked_range<size_t>& r) {
- if (tbb::task::self().is_cancelled()) return;
- for (size_t i = r.begin(); i != r.end(); ++i) {
- if (pred(i)) {
- ret = true;
- tbb::task::self().cancel_group_execution();
- }
- }
- });
-#endif
-#else
- ret = parallel_reduce (first, last, false, [pred](const range<size_t>& r)->bool {
- bool localret = false;
- for (auto i=r.begin(); i<r.end(); ++i) {
- localret |= pred(i);
- }
- return localret;
- },
- std::bit_or<bool>()
- );
-#endif
-
- return ret;
- }
-
-} // end namespace
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_filter.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_filter.cpp
deleted file mode 100644
index acddc0ff81..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_filter.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_filter.h"
-#include "../sys/regression.h"
-#include <map>
-
-namespace embree
-{
- struct parallel_filter_regression_test : public RegressionTest
- {
- parallel_filter_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
- auto pred = [&]( uint32_t v ) { return (v & 0x3) == 0; };
-
- for (size_t N=10; N<1000000; N=size_t(2.1*N))
- {
- size_t N0 = rand() % N;
-
- /* initialize array with random numbers */
- std::vector<uint32_t> src(N);
- std::map<uint32_t,int> m;
- for (size_t i=0; i<N; i++) src[i] = rand();
-
- /* count elements up */
- for (size_t i=N0; i<N; i++)
- if (pred(src[i]))
- m[src[i]] = 0;
- for (size_t i=N0; i<N; i++)
- if (pred(src[i]))
- m[src[i]]++;
-
- /* filter array */
- //size_t M = sequential_filter(src.data(),N0,N,pred);
- size_t M = parallel_filter(src.data(),N0,N,size_t(1024),pred);
-
- /* check if filtered data is correct */
- for (size_t i=N0; i<M; i++) {
- passed &= pred(src[i]);
- m[src[i]]--;
- }
- for (size_t i=N0; i<M; i++)
- passed &= (m[src[i]] == 0);
- }
-
- return passed;
- }
- };
-
- parallel_filter_regression_test parallel_filter_regression("parallel_filter_regression");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_filter.h b/thirdparty/embree-aarch64/common/algorithms/parallel_filter.h
deleted file mode 100644
index 5823fc631f..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_filter.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "parallel_for.h"
-
-namespace embree
-{
- template<typename Ty, typename Index, typename Predicate>
- inline Index sequential_filter( Ty* data, const Index first, const Index last, const Predicate& predicate)
- {
- Index j = first;
- for (Index i=first; i<last; i++)
- if (predicate(data[i]))
- data[j++] = data[i];
-
- return j;
- }
-
- template<typename Ty, typename Index, typename Predicate>
- inline Index parallel_filter( Ty* data, const Index begin, const Index end, const Index minStepSize, const Predicate& predicate)
- {
- /* sequential fallback */
- if (end-begin <= minStepSize)
- return sequential_filter(data,begin,end,predicate);
-
- /* calculate number of tasks to use */
- enum { MAX_TASKS = 64 };
- const Index numThreads = TaskScheduler::threadCount();
- const Index numBlocks = (end-begin+minStepSize-1)/minStepSize;
- const Index taskCount = min(numThreads,numBlocks,(Index)MAX_TASKS);
-
- /* filter blocks */
- Index nused[MAX_TASKS];
- Index nfree[MAX_TASKS];
- parallel_for(taskCount, [&](const Index taskIndex)
- {
- const Index i0 = begin+(taskIndex+0)*(end-begin)/taskCount;
- const Index i1 = begin+(taskIndex+1)*(end-begin)/taskCount;
- const Index i2 = sequential_filter(data,i0,i1,predicate);
- nused[taskIndex] = i2-i0;
- nfree[taskIndex] = i1-i2;
- });
-
- /* calculate offsets */
- Index sused=0;
- Index sfree=0;
- Index pfree[MAX_TASKS];
- for (Index i=0; i<taskCount; i++)
- {
- sused+=nused[i];
- Index cfree = nfree[i]; pfree[i] = sfree; sfree+=cfree;
- }
-
- /* return if we did not filter out any element */
- assert(sfree <= end-begin);
- assert(sused <= end-begin);
- if (sused == end-begin)
- return end;
-
- /* otherwise we have to copy misplaced elements around */
- parallel_for(taskCount, [&](const Index taskIndex)
- {
- /* destination to write elements to */
- Index dst = begin+(taskIndex+0)*(end-begin)/taskCount+nused[taskIndex];
- Index dst_end = min(dst+nfree[taskIndex],begin+sused);
- if (dst_end <= dst) return;
-
- /* range of misplaced elements to copy to destination */
- Index r0 = pfree[taskIndex];
- Index r1 = r0+dst_end-dst;
-
- /* find range in misplaced elements in back to front order */
- Index k0=0;
- for (Index i=taskCount-1; i>0; i--)
- {
- if (k0 > r1) break;
- Index k1 = k0+nused[i];
- Index src = begin+(i+0)*(end-begin)/taskCount+nused[i];
- for (Index i=max(r0,k0); i<min(r1,k1); i++) {
- Index isrc = src-i+k0-1;
- assert(dst >= begin && dst < end);
- assert(isrc >= begin && isrc < end);
- data[dst++] = data[isrc];
- }
- k0 = k1;
- }
- });
-
- return begin+sused;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_for.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_for.cpp
deleted file mode 100644
index ef070ebc4d..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_for.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_for.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- struct parallel_for_regression_test : public RegressionTest
- {
- parallel_for_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
-
- const size_t M = 10;
- for (size_t N=10; N<10000000; N=size_t(2.1*N))
- {
- /* sequentially calculate sum of squares */
- size_t sum0 = 0;
- for (size_t i=0; i<N; i++) {
- sum0 += i*i;
- }
-
- /* parallel calculation of sum of squares */
- for (size_t m=0; m<M; m++)
- {
- std::atomic<size_t> sum1(0);
- parallel_for( size_t(0), size_t(N), size_t(1024), [&](const range<size_t>& r)
- {
- size_t s = 0;
- for (size_t i=r.begin(); i<r.end(); i++)
- s += i*i;
- sum1 += s;
- });
- passed = sum0 == sum1;
- }
- }
-
- return passed;
- }
- };
-
- parallel_for_regression_test parallel_for_regression("parallel_for_regression_test");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_for.h b/thirdparty/embree-aarch64/common/algorithms/parallel_for.h
deleted file mode 100644
index 51d296fb16..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_for.h
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../tasking/taskscheduler.h"
-#include "../sys/array.h"
-#include "../math/math.h"
-#include "../math/range.h"
-
-#if defined(TASKING_GCD) && defined(BUILD_IOS)
-#include <dispatch/dispatch.h>
-#include <algorithm>
-#include <type_traits>
-#endif
-
-namespace embree
-{
- /* parallel_for without range */
- template<typename Index, typename Func>
- __forceinline void parallel_for( const Index N, const Func& func)
- {
-#if defined(TASKING_INTERNAL)
- if (N) {
- TaskScheduler::spawn(Index(0),N,Index(1),[&] (const range<Index>& r) {
- assert(r.size() == 1);
- func(r.begin());
- });
- if (!TaskScheduler::wait())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- }
-#elif defined(TASKING_GCD) && defined(BUILD_IOS)
-
- const size_t baselineNumBlocks = (TaskScheduler::threadCount() > 1)? TaskScheduler::threadCount() : 1;
- const size_t length = N;
- const size_t blockSize = (length + baselineNumBlocks-1) / baselineNumBlocks;
- const size_t numBlocks = (length + blockSize-1) / blockSize;
-
- dispatch_apply(numBlocks, DISPATCH_APPLY_AUTO, ^(size_t currentBlock) {
-
- const size_t start = (currentBlock * blockSize);
- const size_t blockLength = std::min(length - start, blockSize);
- const size_t end = start + blockLength;
-
- for(size_t i=start; i < end; i++)
- {
- func(i);
- }
- });
-
-#elif defined(TASKING_TBB)
- #if TBB_INTERFACE_VERSION >= 12002
- tbb::task_group_context context;
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- },context);
- if (context.is_group_execution_cancelled())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- #else
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- });
- if (tbb::task::self().is_cancelled())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- #endif
-
-#elif defined(TASKING_PPL)
- concurrency::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- });
-#else
-# error "no tasking system enabled"
-#endif
- }
-
- /* parallel for with range and granulatity */
- template<typename Index, typename Func>
- __forceinline void parallel_for( const Index first, const Index last, const Index minStepSize, const Func& func)
- {
- assert(first <= last);
-#if defined(TASKING_INTERNAL)
- TaskScheduler::spawn(first,last,minStepSize,func);
- if (!TaskScheduler::wait())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
-
-#elif defined(TASKING_GCD) && defined(BUILD_IOS)
-
- const size_t baselineNumBlocks = (TaskScheduler::threadCount() > 1)? 4*TaskScheduler::threadCount() : 1;
- const size_t length = last - first;
- const size_t blockSizeByThreads = (length + baselineNumBlocks-1) / baselineNumBlocks;
- size_t blockSize = std::max<size_t>(minStepSize,blockSizeByThreads);
- blockSize += blockSize % 4;
-
- const size_t numBlocks = (length + blockSize-1) / blockSize;
-
- dispatch_apply(numBlocks, DISPATCH_APPLY_AUTO, ^(size_t currentBlock) {
-
- const size_t start = first + (currentBlock * blockSize);
- const size_t end = std::min<size_t>(last, start + blockSize);
-
- func( embree::range<Index>(start,end) );
- });
-
-
-#elif defined(TASKING_TBB)
- #if TBB_INTERFACE_VERSION >= 12002
- tbb::task_group_context context;
- tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
- func(range<Index>(r.begin(),r.end()));
- },context);
- if (context.is_group_execution_cancelled())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- #else
- tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
- func(range<Index>(r.begin(),r.end()));
- });
- if (tbb::task::self().is_cancelled())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- #endif
-
-#elif defined(TASKING_PPL)
- concurrency::parallel_for(first, last, Index(1) /*minStepSize*/, [&](Index i) {
- func(range<Index>(i,i+1));
- });
-
-#else
-# error "no tasking system enabled"
-#endif
- }
-
- /* parallel for with range */
- template<typename Index, typename Func>
- __forceinline void parallel_for( const Index first, const Index last, const Func& func)
- {
- assert(first <= last);
- parallel_for(first,last,(Index)1,func);
- }
-
-#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION > 4001)
-
- template<typename Index, typename Func>
- __forceinline void parallel_for_static( const Index N, const Func& func)
- {
- #if TBB_INTERFACE_VERSION >= 12002
- tbb::task_group_context context;
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- },tbb::simple_partitioner(),context);
- if (context.is_group_execution_cancelled())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- #else
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- },tbb::simple_partitioner());
- if (tbb::task::self().is_cancelled())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- #endif
- }
-
- typedef tbb::affinity_partitioner affinity_partitioner;
-
- template<typename Index, typename Func>
- __forceinline void parallel_for_affinity( const Index N, const Func& func, tbb::affinity_partitioner& ap)
- {
- #if TBB_INTERFACE_VERSION >= 12002
- tbb::task_group_context context;
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- },ap,context);
- if (context.is_group_execution_cancelled())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- #else
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- },ap);
- if (tbb::task::self().is_cancelled())
- // -- GODOT start --
- // throw std::runtime_error("task cancelled");
- abort();
- // -- GODOT end --
- #endif
- }
-
-#else
-
- template<typename Index, typename Func>
- __forceinline void parallel_for_static( const Index N, const Func& func)
- {
- parallel_for(N,func);
- }
-
- struct affinity_partitioner {
- };
-
- template<typename Index, typename Func>
- __forceinline void parallel_for_affinity( const Index N, const Func& func, affinity_partitioner& ap)
- {
- parallel_for(N,func);
- }
-
-#endif
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_for_for.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_for_for.cpp
deleted file mode 100644
index 0337611b35..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_for_for.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_for_for.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- struct parallel_for_for_regression_test : public RegressionTest
- {
- parallel_for_for_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
-
- /* create vector with random numbers */
- size_t sum0 = 0;
- size_t K = 0;
- const size_t M = 1000;
- std::vector<std::vector<size_t>* > array2(M);
- for (size_t i=0; i<M; i++) {
- const size_t N = rand() % 1024;
- K+=N;
- array2[i] = new std::vector<size_t>(N);
- for (size_t j=0; j<N; j++)
- sum0 += (*array2[i])[j] = rand();
- }
-
- /* array to test global index */
- std::vector<atomic<size_t>> verify_k(K);
- for (size_t i=0; i<K; i++) verify_k[i].store(0);
-
- /* add all numbers using parallel_for_for */
- std::atomic<size_t> sum1(0);
- parallel_for_for( array2, size_t(1), [&](std::vector<size_t>* v, const range<size_t>& r, size_t k) -> size_t
- {
- size_t s = 0;
- for (size_t i=r.begin(); i<r.end(); i++) {
- s += (*v)[i];
- verify_k[k++]++;
- }
- sum1 += s;
- return sum1;
- });
- passed &= (sum0 == sum1);
-
- /* check global index */
- for (size_t i=0; i<K; i++)
- passed &= (verify_k[i] == 1);
-
- /* delete vectors again */
- for (size_t i=0; i<array2.size(); i++)
- delete array2[i];
-
- return passed;
- }
- };
-
- parallel_for_for_regression_test parallel_for_for_regression("parallel_for_for_regression_test");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_for_for.h b/thirdparty/embree-aarch64/common/algorithms/parallel_for_for.h
deleted file mode 100644
index 852b8a0900..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_for_for.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "parallel_for.h"
-
-namespace embree
-{
- template<typename ArrayArray, typename Func>
- __forceinline void sequential_for_for( ArrayArray& array2, const size_t minStepSize, const Func& func )
- {
- size_t k=0;
- for (size_t i=0; i!=array2.size(); ++i) {
- const size_t N = array2[i]->size();
- if (N) func(array2[i],range<size_t>(0,N),k);
- k+=N;
- }
- }
-
- class ParallelForForState
- {
- public:
-
- enum { MAX_TASKS = 64 };
-
- __forceinline ParallelForForState ()
- : taskCount(0) {}
-
- template<typename ArrayArray>
- __forceinline ParallelForForState (ArrayArray& array2, const size_t minStepSize) {
- init(array2,minStepSize);
- }
-
- template<typename ArrayArray>
- __forceinline void init ( ArrayArray& array2, const size_t minStepSize )
- {
- /* first calculate total number of elements */
- size_t N = 0;
- for (size_t i=0; i<array2.size(); i++) {
- N += array2[i] ? array2[i]->size() : 0;
- }
- this->N = N;
-
- /* calculate number of tasks to use */
- const size_t numThreads = TaskScheduler::threadCount();
- const size_t numBlocks = (N+minStepSize-1)/minStepSize;
- taskCount = max(size_t(1),min(numThreads,numBlocks,size_t(ParallelForForState::MAX_TASKS)));
-
- /* calculate start (i,j) for each task */
- size_t taskIndex = 0;
- i0[taskIndex] = 0;
- j0[taskIndex] = 0;
- size_t k0 = (++taskIndex)*N/taskCount;
- for (size_t i=0, k=0; taskIndex < taskCount; i++)
- {
- assert(i<array2.size());
- size_t j=0, M = array2[i] ? array2[i]->size() : 0;
- while (j<M && k+M-j >= k0 && taskIndex < taskCount) {
- assert(taskIndex<taskCount);
- i0[taskIndex] = i;
- j0[taskIndex] = j += k0-k;
- k=k0;
- k0 = (++taskIndex)*N/taskCount;
- }
- k+=M-j;
- }
- }
-
- __forceinline size_t size() const {
- return N;
- }
-
- public:
- size_t i0[MAX_TASKS];
- size_t j0[MAX_TASKS];
- size_t taskCount;
- size_t N;
- };
-
- template<typename ArrayArray, typename Func>
- __forceinline void parallel_for_for( ArrayArray& array2, const size_t minStepSize, const Func& func )
- {
- ParallelForForState state(array2,minStepSize);
-
- parallel_for(state.taskCount, [&](const size_t taskIndex)
- {
- /* calculate range */
- const size_t k0 = (taskIndex+0)*state.size()/state.taskCount;
- const size_t k1 = (taskIndex+1)*state.size()/state.taskCount;
- size_t i0 = state.i0[taskIndex];
- size_t j0 = state.j0[taskIndex];
-
- /* iterate over arrays */
- size_t k=k0;
- for (size_t i=i0; k<k1; i++) {
- const size_t N = array2[i] ? array2[i]->size() : 0;
- const size_t r0 = j0, r1 = min(N,r0+k1-k);
- if (r1 > r0) func(array2[i],range<size_t>(r0,r1),k);
- k+=r1-r0; j0 = 0;
- }
- });
- }
-
- template<typename ArrayArray, typename Func>
- __forceinline void parallel_for_for( ArrayArray& array2, const Func& func )
- {
- parallel_for_for(array2,1,func);
- }
-
- template<typename ArrayArray, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_for_for_reduce( ArrayArray& array2, const size_t minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
- {
- ParallelForForState state(array2,minStepSize);
- Value temp[ParallelForForState::MAX_TASKS];
-
- for (size_t i=0; i<state.taskCount; i++)
- temp[i] = identity;
-
- parallel_for(state.taskCount, [&](const size_t taskIndex)
- {
- /* calculate range */
- const size_t k0 = (taskIndex+0)*state.size()/state.taskCount;
- const size_t k1 = (taskIndex+1)*state.size()/state.taskCount;
- size_t i0 = state.i0[taskIndex];
- size_t j0 = state.j0[taskIndex];
-
- /* iterate over arrays */
- size_t k=k0;
- for (size_t i=i0; k<k1; i++) {
- const size_t N = array2[i] ? array2[i]->size() : 0;
- const size_t r0 = j0, r1 = min(N,r0+k1-k);
- if (r1 > r0) temp[taskIndex] = reduction(temp[taskIndex],func(array2[i],range<size_t>(r0,r1),k));
- k+=r1-r0; j0 = 0;
- }
- });
-
- Value ret = identity;
- for (size_t i=0; i<state.taskCount; i++)
- ret = reduction(ret,temp[i]);
- return ret;
- }
-
- template<typename ArrayArray, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_for_for_reduce( ArrayArray& array2, const Value& identity, const Func& func, const Reduction& reduction)
- {
- return parallel_for_for_reduce(array2,1,identity,func,reduction);
- }
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_for_for_prefix_sum.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_for_for_prefix_sum.cpp
deleted file mode 100644
index 0169d8e481..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_for_for_prefix_sum.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_for_for_prefix_sum.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- struct parallel_for_for_prefix_sum_regression_test : public RegressionTest
- {
- parallel_for_for_prefix_sum_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
-
- /* create vector with random numbers */
- const size_t M = 10;
- std::vector<atomic<size_t>> flattened;
- typedef std::vector<std::vector<size_t>* > ArrayArray;
- ArrayArray array2(M);
- size_t K = 0;
- for (size_t i=0; i<M; i++) {
- const size_t N = rand() % 10;
- K += N;
- array2[i] = new std::vector<size_t>(N);
- for (size_t j=0; j<N; j++)
- (*array2[i])[j] = rand() % 10;
- }
-
- /* array to test global index */
- std::vector<atomic<size_t>> verify_k(K);
- for (size_t i=0; i<K; i++) verify_k[i].store(0);
-
- ParallelForForPrefixSumState<size_t> state(array2,size_t(1));
-
- /* dry run only counts */
- size_t S = parallel_for_for_prefix_sum0( state, array2, size_t(0), [&](std::vector<size_t>* v, const range<size_t>& r, size_t k, size_t i) -> size_t
- {
- size_t s = 0;
- for (size_t i=r.begin(); i<r.end(); i++) {
- s += (*v)[i];
- verify_k[k++]++;
- }
- return s;
- }, [](size_t v0, size_t v1) { return v0+v1; });
-
- /* create properly sized output array */
- flattened.resize(S);
- for (auto& a : flattened) a.store(0);
-
- /* now we actually fill the flattened array */
- parallel_for_for_prefix_sum1( state, array2, size_t(0), [&](std::vector<size_t>* v, const range<size_t>& r, size_t k, size_t i, const size_t base) -> size_t
- {
- size_t s = 0;
- for (size_t i=r.begin(); i<r.end(); i++) {
- for (size_t j=0; j<(*v)[i]; j++) {
- flattened[base+s+j]++;
- }
- s += (*v)[i];
- verify_k[k++]++;
- }
- return s;
- }, [](size_t v0, size_t v1) { return v0+v1; });
-
- /* check global index */
- for (size_t i=0; i<K; i++)
- passed &= (verify_k[i] == 2);
-
- /* check if each element was assigned exactly once */
- for (size_t i=0; i<flattened.size(); i++)
- passed &= (flattened[i] == 1);
-
- /* delete arrays again */
- for (size_t i=0; i<array2.size(); i++)
- delete array2[i];
-
- return passed;
- }
- };
-
- parallel_for_for_prefix_sum_regression_test parallel_for_for_prefix_sum_regression("parallel_for_for_prefix_sum_regression_test");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_for_for_prefix_sum.h b/thirdparty/embree-aarch64/common/algorithms/parallel_for_for_prefix_sum.h
deleted file mode 100644
index d2671d8a6a..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_for_for_prefix_sum.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "parallel_for_for.h"
-#include "parallel_prefix_sum.h"
-
-namespace embree
-{
- template<typename Value>
- struct ParallelForForPrefixSumState : public ParallelForForState
- {
- __forceinline ParallelForForPrefixSumState () {}
-
- template<typename ArrayArray>
- __forceinline ParallelForForPrefixSumState (ArrayArray& array2, const size_t minStepSize)
- : ParallelForForState(array2,minStepSize) {}
-
- ParallelPrefixSumState<Value> prefix_state;
- };
-
- template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2, Index minStepSize,
- const Value& identity, const Func& func, const Reduction& reduction)
- {
- /* calculate number of tasks to use */
- const size_t taskCount = state.taskCount;
- /* perform parallel prefix sum */
- parallel_for(taskCount, [&](const size_t taskIndex)
- {
- const size_t k0 = (taskIndex+0)*state.size()/taskCount;
- const size_t k1 = (taskIndex+1)*state.size()/taskCount;
- size_t i0 = state.i0[taskIndex];
- size_t j0 = state.j0[taskIndex];
-
- /* iterate over arrays */
- size_t k=k0;
- Value N=identity;
- for (size_t i=i0; k<k1; i++) {
- const size_t size = array2[i] ? array2[i]->size() : 0;
- const size_t r0 = j0, r1 = min(size,r0+k1-k);
- if (r1 > r0) N = reduction(N, func(array2[i],range<Index>((Index)r0,(Index)r1),(Index)k,(Index)i));
- k+=r1-r0; j0 = 0;
- }
- state.prefix_state.counts[taskIndex] = N;
- });
-
- /* calculate prefix sum */
- Value sum=identity;
- for (size_t i=0; i<taskCount; i++)
- {
- const Value c = state.prefix_state.counts[i];
- state.prefix_state.sums[i] = sum;
- sum=reduction(sum,c);
- }
-
- return sum;
- }
-
- template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2, Index minStepSize,
- const Value& identity, const Func& func, const Reduction& reduction)
- {
- /* calculate number of tasks to use */
- const size_t taskCount = state.taskCount;
- /* perform parallel prefix sum */
- parallel_for(taskCount, [&](const size_t taskIndex)
- {
- const size_t k0 = (taskIndex+0)*state.size()/taskCount;
- const size_t k1 = (taskIndex+1)*state.size()/taskCount;
- size_t i0 = state.i0[taskIndex];
- size_t j0 = state.j0[taskIndex];
-
- /* iterate over arrays */
- size_t k=k0;
- Value N=identity;
- for (size_t i=i0; k<k1; i++) {
- const size_t size = array2[i] ? array2[i]->size() : 0;
- const size_t r0 = j0, r1 = min(size,r0+k1-k);
- if (r1 > r0) N = reduction(N, func(array2[i],range<Index>((Index)r0,(Index)r1),(Index)k,(Index)i,reduction(state.prefix_state.sums[taskIndex],N)));
- k+=r1-r0; j0 = 0;
- }
- state.prefix_state.counts[taskIndex] = N;
- });
-
- /* calculate prefix sum */
- Value sum=identity;
- for (size_t i=0; i<taskCount; i++)
- {
- const Value c = state.prefix_state.counts[i];
- state.prefix_state.sums[i] = sum;
- sum=reduction(sum,c);
- }
-
- return sum;
- }
-
- template<typename ArrayArray, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2,
- const Value& identity, const Func& func, const Reduction& reduction)
- {
- return parallel_for_for_prefix_sum0(state,array2,size_t(1),identity,func,reduction);
- }
-
- template<typename ArrayArray, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2,
- const Value& identity, const Func& func, const Reduction& reduction)
- {
- return parallel_for_for_prefix_sum1(state,array2,size_t(1),identity,func,reduction);
- }
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_map.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_map.cpp
deleted file mode 100644
index 09dc303f81..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_map.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_map.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- struct parallel_map_regression_test : public RegressionTest
- {
- parallel_map_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
-
- /* create key/value vectors with random numbers */
- const size_t N = 10000;
- std::vector<uint32_t> keys(N);
- std::vector<uint32_t> vals(N);
- for (size_t i=0; i<N; i++) keys[i] = 2*unsigned(i)*647382649;
- for (size_t i=0; i<N; i++) std::swap(keys[i],keys[rand()%N]);
- for (size_t i=0; i<N; i++) vals[i] = 2*rand();
-
- /* create map */
- parallel_map<uint32_t,uint32_t> map;
- map.init(keys,vals);
-
- /* check that all keys are properly mapped */
- for (size_t i=0; i<N; i++) {
- const uint32_t* val = map.lookup(keys[i]);
- passed &= val && (*val == vals[i]);
- }
-
- /* check that these keys are not in the map */
- for (size_t i=0; i<N; i++) {
- passed &= !map.lookup(keys[i]+1);
- }
-
- return passed;
- }
- };
-
- parallel_map_regression_test parallel_map_regression("parallel_map_regression_test");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_map.h b/thirdparty/embree-aarch64/common/algorithms/parallel_map.h
deleted file mode 100644
index 02e1a8f8d0..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_map.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "parallel_sort.h"
-
-namespace embree
-{
- /*! implementation of a key/value map with parallel construction */
- template<typename Key, typename Val>
- class parallel_map
- {
- /* key/value pair to build the map */
- struct KeyValue
- {
- __forceinline KeyValue () {}
-
- __forceinline KeyValue (const Key key, const Val val)
- : key(key), val(val) {}
-
- __forceinline operator Key() const {
- return key;
- }
-
- public:
- Key key;
- Val val;
- };
-
- public:
-
- /*! parallel map constructors */
- parallel_map () {}
-
- /*! construction from pair of vectors */
- template<typename KeyVector, typename ValVector>
- parallel_map (const KeyVector& keys, const ValVector& values) { init(keys,values); }
-
- /*! initialized the parallel map from a vector with keys and values */
- template<typename KeyVector, typename ValVector>
- void init(const KeyVector& keys, const ValVector& values)
- {
- /* reserve sufficient space for all data */
- assert(keys.size() == values.size());
- vec.resize(keys.size());
-
- /* generate key/value pairs */
- parallel_for( size_t(0), keys.size(), size_t(4*4096), [&](const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++)
- vec[i] = KeyValue((Key)keys[i],values[i]);
- });
-
- /* perform parallel radix sort of the key/value pairs */
- std::vector<KeyValue> temp(keys.size());
- radix_sort<KeyValue,Key>(vec.data(),temp.data(),keys.size());
- }
-
- /*! Returns a pointer to the value associated with the specified key. The pointer will be nullptr of the key is not contained in the map. */
- __forceinline const Val* lookup(const Key& key) const
- {
- typename std::vector<KeyValue>::const_iterator i = std::lower_bound(vec.begin(), vec.end(), key);
- if (i == vec.end()) return nullptr;
- if (i->key != key) return nullptr;
- return &i->val;
- }
-
- /*! If the key is in the map, the function returns the value associated with the key, otherwise it returns the default value. */
- __forceinline Val lookup(const Key& key, const Val& def) const
- {
- typename std::vector<KeyValue>::const_iterator i = std::lower_bound(vec.begin(), vec.end(), key);
- if (i == vec.end()) return def;
- if (i->key != key) return def;
- return i->val;
- }
-
- /*! clears all state */
- void clear() {
- vec.clear();
- }
-
- private:
- std::vector<KeyValue> vec; //!< vector containing sorted elements
- };
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_partition.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_partition.cpp
deleted file mode 100644
index eb20c4465d..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_partition.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_partition.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- struct parallel_partition_regression_test : public RegressionTest
- {
- parallel_partition_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
-
- for (size_t i=0; i<100; i++)
- {
- /* create random permutation */
- size_t N = std::rand() % 1000000;
- std::vector<unsigned> array(N);
- for (unsigned i=0; i<N; i++) array[i] = i;
- for (auto& v : array) std::swap(v,array[std::rand()%array.size()]);
- size_t split = std::rand() % (N+1);
-
- /* perform parallel partitioning */
- size_t left_sum = 0, right_sum = 0;
- size_t mid = parallel_partitioning(array.data(),0,array.size(),0,left_sum,right_sum,
- [&] ( size_t i ) { return i < split; },
- [] ( size_t& sum, unsigned v) { sum += v; },
- [] ( size_t& sum, size_t v) { sum += v; },
- 128);
-
- /*serial_partitioning(array.data(),0,array.size(),left_sum,right_sum,
- [&] ( size_t i ) { return i < split; },
- [] ( size_t& left_sum, int v) { left_sum += v; });*/
-
- /* verify result */
- passed &= mid == split;
- passed &= left_sum == split*(split-1)/2;
- passed &= right_sum == N*(N-1)/2-left_sum;
- for (size_t i=0; i<split; i++) passed &= array[i] < split;
- for (size_t i=split; i<N; i++) passed &= array[i] >= split;
- }
-
- return passed;
- }
- };
-
- parallel_partition_regression_test parallel_partition_regression("parallel_partition_regression_test");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_partition.h b/thirdparty/embree-aarch64/common/algorithms/parallel_partition.h
deleted file mode 100644
index 3b3ad7c854..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_partition.h
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "parallel_for.h"
-#include "../math/range.h"
-
-namespace embree
-{
- /* serial partitioning */
- template<typename T, typename V, typename IsLeft, typename Reduction_T>
- __forceinline size_t serial_partitioning(T* array,
- const size_t begin,
- const size_t end,
- V& leftReduction,
- V& rightReduction,
- const IsLeft& is_left,
- const Reduction_T& reduction_t)
- {
- T* l = array + begin;
- T* r = array + end - 1;
-
- while(1)
- {
- /* *l < pivot */
- while (likely(l <= r && is_left(*l) ))
- {
- //prefetchw(l+4); // FIXME: enable?
- reduction_t(leftReduction,*l);
- ++l;
- }
- /* *r >= pivot) */
- while (likely(l <= r && !is_left(*r)))
- {
- //prefetchw(r-4); FIXME: enable?
- reduction_t(rightReduction,*r);
- --r;
- }
- if (r<l) break;
-
- reduction_t(leftReduction ,*r);
- reduction_t(rightReduction,*l);
- xchg(*l,*r);
- l++; r--;
- }
-
- return l - array;
- }
-
- template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
- class __aligned(64) parallel_partition_task
- {
- ALIGNED_CLASS_(64);
- private:
-
- static const size_t MAX_TASKS = 64;
-
- T* array;
- size_t N;
- const IsLeft& is_left;
- const Reduction_T& reduction_t;
- const Reduction_V& reduction_v;
- const Vi& identity;
-
- size_t numTasks;
- __aligned(64) size_t counter_start[MAX_TASKS+1];
- __aligned(64) size_t counter_left[MAX_TASKS+1];
- __aligned(64) range<ssize_t> leftMisplacedRanges[MAX_TASKS];
- __aligned(64) range<ssize_t> rightMisplacedRanges[MAX_TASKS];
- __aligned(64) V leftReductions[MAX_TASKS];
- __aligned(64) V rightReductions[MAX_TASKS];
-
- public:
-
- __forceinline parallel_partition_task(T* array,
- const size_t N,
- const Vi& identity,
- const IsLeft& is_left,
- const Reduction_T& reduction_t,
- const Reduction_V& reduction_v,
- const size_t BLOCK_SIZE)
-
- : array(array), N(N), is_left(is_left), reduction_t(reduction_t), reduction_v(reduction_v), identity(identity),
- numTasks(min((N+BLOCK_SIZE-1)/BLOCK_SIZE,min(TaskScheduler::threadCount(),MAX_TASKS))) {}
-
- __forceinline const range<ssize_t>* findStartRange(size_t& index, const range<ssize_t>* const r, const size_t numRanges)
- {
- size_t i = 0;
- while(index >= (size_t)r[i].size())
- {
- assert(i < numRanges);
- index -= (size_t)r[i].size();
- i++;
- }
- return &r[i];
- }
-
- __forceinline void swapItemsInMisplacedRanges(const size_t numLeftMisplacedRanges,
- const size_t numRightMisplacedRanges,
- const size_t startID,
- const size_t endID)
- {
- size_t leftLocalIndex = startID;
- size_t rightLocalIndex = startID;
- const range<ssize_t>* l_range = findStartRange(leftLocalIndex,leftMisplacedRanges,numLeftMisplacedRanges);
- const range<ssize_t>* r_range = findStartRange(rightLocalIndex,rightMisplacedRanges,numRightMisplacedRanges);
-
- size_t l_left = l_range->size() - leftLocalIndex;
- size_t r_left = r_range->size() - rightLocalIndex;
- T *__restrict__ l = &array[l_range->begin() + leftLocalIndex];
- T *__restrict__ r = &array[r_range->begin() + rightLocalIndex];
- size_t size = endID - startID;
- size_t items = min(size,min(l_left,r_left));
-
- while (size)
- {
- if (unlikely(l_left == 0))
- {
- l_range++;
- l_left = l_range->size();
- l = &array[l_range->begin()];
- items = min(size,min(l_left,r_left));
- }
-
- if (unlikely(r_left == 0))
- {
- r_range++;
- r_left = r_range->size();
- r = &array[r_range->begin()];
- items = min(size,min(l_left,r_left));
- }
-
- size -= items;
- l_left -= items;
- r_left -= items;
-
- while(items) {
- items--;
- xchg(*l++,*r++);
- }
- }
- }
-
- __forceinline size_t partition(V& leftReduction, V& rightReduction)
- {
- /* partition the individual ranges for each task */
- parallel_for(numTasks,[&] (const size_t taskID) {
- const size_t startID = (taskID+0)*N/numTasks;
- const size_t endID = (taskID+1)*N/numTasks;
- V local_left(identity);
- V local_right(identity);
- const size_t mid = serial_partitioning(array,startID,endID,local_left,local_right,is_left,reduction_t);
- counter_start[taskID] = startID;
- counter_left [taskID] = mid-startID;
- leftReductions[taskID] = local_left;
- rightReductions[taskID] = local_right;
- });
- counter_start[numTasks] = N;
- counter_left[numTasks] = 0;
-
- /* finalize the reductions */
- for (size_t i=0; i<numTasks; i++) {
- reduction_v(leftReduction,leftReductions[i]);
- reduction_v(rightReduction,rightReductions[i]);
- }
-
- /* calculate mid point for partitioning */
- size_t mid = counter_left[0];
- for (size_t i=1; i<numTasks; i++)
- mid += counter_left[i];
- const range<ssize_t> globalLeft (0,mid);
- const range<ssize_t> globalRight(mid,N);
-
- /* calculate all left and right ranges that are on the wrong global side */
- size_t numMisplacedRangesLeft = 0;
- size_t numMisplacedRangesRight = 0;
- size_t numMisplacedItemsLeft = 0;
- size_t numMisplacedItemsRight = 0;
-
- for (size_t i=0; i<numTasks; i++)
- {
- const range<ssize_t> left_range (counter_start[i], counter_start[i] + counter_left[i]);
- const range<ssize_t> right_range(counter_start[i] + counter_left[i], counter_start[i+1]);
- const range<ssize_t> left_misplaced = globalLeft. intersect(right_range);
- const range<ssize_t> right_misplaced = globalRight.intersect(left_range);
-
- if (!left_misplaced.empty())
- {
- numMisplacedItemsLeft += left_misplaced.size();
- leftMisplacedRanges[numMisplacedRangesLeft++] = left_misplaced;
- }
-
- if (!right_misplaced.empty())
- {
- numMisplacedItemsRight += right_misplaced.size();
- rightMisplacedRanges[numMisplacedRangesRight++] = right_misplaced;
- }
- }
- assert( numMisplacedItemsLeft == numMisplacedItemsRight );
-
- /* if no items are misplaced we are done */
- if (numMisplacedItemsLeft == 0)
- return mid;
-
- /* otherwise we copy the items to the right place in parallel */
- parallel_for(numTasks,[&] (const size_t taskID) {
- const size_t startID = (taskID+0)*numMisplacedItemsLeft/numTasks;
- const size_t endID = (taskID+1)*numMisplacedItemsLeft/numTasks;
- swapItemsInMisplacedRanges(numMisplacedRangesLeft,numMisplacedRangesRight,startID,endID);
- });
-
- return mid;
- }
- };
-
- template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
- __noinline size_t parallel_partitioning(T* array,
- const size_t begin,
- const size_t end,
- const Vi &identity,
- V &leftReduction,
- V &rightReduction,
- const IsLeft& is_left,
- const Reduction_T& reduction_t,
- const Reduction_V& reduction_v,
- size_t BLOCK_SIZE = 128)
- {
- /* fall back to single threaded partitioning for small N */
- if (unlikely(end-begin < BLOCK_SIZE))
- return serial_partitioning(array,begin,end,leftReduction,rightReduction,is_left,reduction_t);
-
- /* otherwise use parallel code */
- else {
- typedef parallel_partition_task<T,V,Vi,IsLeft,Reduction_T,Reduction_V> partition_task;
- std::unique_ptr<partition_task> p(new partition_task(&array[begin],end-begin,identity,is_left,reduction_t,reduction_v,BLOCK_SIZE));
- return begin+p->partition(leftReduction,rightReduction);
- }
- }
-
- template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
- __noinline size_t parallel_partitioning(T* array,
- const size_t begin,
- const size_t end,
- const Vi &identity,
- V &leftReduction,
- V &rightReduction,
- const IsLeft& is_left,
- const Reduction_T& reduction_t,
- const Reduction_V& reduction_v,
- size_t BLOCK_SIZE,
- size_t PARALLEL_THRESHOLD)
- {
- /* fall back to single threaded partitioning for small N */
- if (unlikely(end-begin < PARALLEL_THRESHOLD))
- return serial_partitioning(array,begin,end,leftReduction,rightReduction,is_left,reduction_t);
-
- /* otherwise use parallel code */
- else {
- typedef parallel_partition_task<T,V,Vi,IsLeft,Reduction_T,Reduction_V> partition_task;
- std::unique_ptr<partition_task> p(new partition_task(&array[begin],end-begin,identity,is_left,reduction_t,reduction_v,BLOCK_SIZE));
- return begin+p->partition(leftReduction,rightReduction);
- }
- }
-
-
- template<typename T, typename IsLeft>
- inline size_t parallel_partitioning(T* array,
- const size_t begin,
- const size_t end,
- const IsLeft& is_left,
- size_t BLOCK_SIZE = 128)
- {
- size_t leftReduction = 0;
- size_t rightReduction = 0;
- return parallel_partitioning(
- array,begin,end,0,leftReduction,rightReduction,is_left,
- [] (size_t& t,const T& ref) { },
- [] (size_t& t0,size_t& t1) { },
- BLOCK_SIZE);
- }
-
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_prefix_sum.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_prefix_sum.cpp
deleted file mode 100644
index 685952c3dc..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_prefix_sum.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_prefix_sum.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- struct parallel_prefix_sum_regression_test : public RegressionTest
- {
- parallel_prefix_sum_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
- const size_t M = 10;
-
- for (size_t N=10; N<10000000; N=size_t(2.1*N))
- {
- /* initialize array with random numbers */
- uint32_t sum0 = 0;
- std::vector<uint32_t> src(N);
- for (size_t i=0; i<N; i++) {
- sum0 += src[i] = rand();
- }
-
- /* calculate parallel prefix sum */
- std::vector<uint32_t> dst(N);
- for (auto& v : dst) v = 0;
-
- for (size_t i=0; i<M; i++) {
- uint32_t sum1 = parallel_prefix_sum(src,dst,N,0,std::plus<uint32_t>());
- passed &= (sum0 == sum1);
- }
-
- /* check if prefix sum is correct */
- for (size_t i=0, sum=0; i<N; sum+=src[i++])
- passed &= ((uint32_t)sum == dst[i]);
- }
-
- return passed;
- }
- };
-
- parallel_prefix_sum_regression_test parallel_prefix_sum_regression("parallel_prefix_sum_regression");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_prefix_sum.h b/thirdparty/embree-aarch64/common/algorithms/parallel_prefix_sum.h
deleted file mode 100644
index 117c7a79b0..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_prefix_sum.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "parallel_for.h"
-
-namespace embree
-{
- template<typename Value>
- struct ParallelPrefixSumState
- {
- enum { MAX_TASKS = 64 };
- Value counts[MAX_TASKS];
- Value sums [MAX_TASKS];
- };
-
- template<typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_prefix_sum( ParallelPrefixSumState<Value>& state, Index first, Index last, Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction)
- {
- /* calculate number of tasks to use */
- const size_t numThreads = TaskScheduler::threadCount();
- const size_t numBlocks = (last-first+minStepSize-1)/minStepSize;
- const size_t taskCount = min(numThreads,numBlocks,size_t(ParallelPrefixSumState<Value>::MAX_TASKS));
-
- /* perform parallel prefix sum */
- parallel_for(taskCount, [&](const size_t taskIndex)
- {
- const size_t i0 = first+(taskIndex+0)*(last-first)/taskCount;
- const size_t i1 = first+(taskIndex+1)*(last-first)/taskCount;
- state.counts[taskIndex] = func(range<size_t>(i0,i1),state.sums[taskIndex]);
- });
-
- /* calculate prefix sum */
- Value sum=identity;
- for (size_t i=0; i<taskCount; i++)
- {
- const Value c = state.counts[i];
- state.sums[i] = sum;
- sum=reduction(sum,c);
- }
-
- return sum;
- }
-
- /*! parallel calculation of prefix sums */
- template<typename SrcArray, typename DstArray, typename Value, typename Add>
- __forceinline Value parallel_prefix_sum(const SrcArray& src, DstArray& dst, size_t N, const Value& identity, const Add& add, const size_t SINGLE_THREAD_THRESHOLD = 4096)
- {
- /* perform single threaded prefix operation for small N */
- if (N < SINGLE_THREAD_THRESHOLD)
- {
- Value sum=identity;
- for (size_t i=0; i<N; sum=add(sum,src[i++])) dst[i] = sum;
- return sum;
- }
-
- /* perform parallel prefix operation for large N */
- else
- {
- ParallelPrefixSumState<Value> state;
-
- /* initial run just sets up start values for subtasks */
- parallel_prefix_sum( state, size_t(0), size_t(N), size_t(1024), identity, [&](const range<size_t>& r, const Value& sum) -> Value {
-
- Value s = identity;
- for (size_t i=r.begin(); i<r.end(); i++) s = add(s,src[i]);
- return s;
-
- }, add);
-
- /* final run calculates prefix sum */
- return parallel_prefix_sum( state, size_t(0), size_t(N), size_t(1024), identity, [&](const range<size_t>& r, const Value& sum) -> Value {
-
- Value s = identity;
- for (size_t i=r.begin(); i<r.end(); i++) {
- dst[i] = add(sum,s);
- s = add(s,src[i]);
- }
- return s;
-
- }, add);
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.cpp
deleted file mode 100644
index 331fe4288e..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_reduce.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- struct parallel_reduce_regression_test : public RegressionTest
- {
- parallel_reduce_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
-
- const size_t M = 10;
- for (size_t N=10; N<10000000; N=size_t(2.1*N))
- {
- /* sequentially calculate sum of squares */
- size_t sum0 = 0;
- for (size_t i=0; i<N; i++) {
- sum0 += i*i;
- }
-
- /* parallel calculation of sum of squares */
- for (size_t m=0; m<M; m++)
- {
- size_t sum1 = parallel_reduce( size_t(0), size_t(N), size_t(1024), size_t(0), [&](const range<size_t>& r) -> size_t
- {
- size_t s = 0;
- for (size_t i=r.begin(); i<r.end(); i++)
- s += i*i;
- return s;
- },
- [](const size_t v0, const size_t v1) {
- return v0+v1;
- });
- passed = sum0 == sum1;
- }
- }
- return passed;
- }
- };
-
- parallel_reduce_regression_test parallel_reduce_regression("parallel_reduce_regression_test");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.h b/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.h
deleted file mode 100644
index 0daf94e50e..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "parallel_for.h"
-
-namespace embree
-{
- template<typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value sequential_reduce( const Index first, const Index last, const Value& identity, const Func& func, const Reduction& reduction )
- {
- return func(range<Index>(first,last));
- }
-
- template<typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value sequential_reduce( const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
- {
- return func(range<Index>(first,last));
- }
-
- template<typename Index, typename Value, typename Func, typename Reduction>
- __noinline Value parallel_reduce_internal( Index taskCount, const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
- {
- const Index maxTasks = 512;
- const Index threadCount = (Index) TaskScheduler::threadCount();
- taskCount = min(taskCount,threadCount,maxTasks);
-
- /* parallel invokation of all tasks */
- dynamic_large_stack_array(Value,values,taskCount,8192); // consumes at most 8192 bytes on the stack
- parallel_for(taskCount, [&](const Index taskIndex) {
- const Index k0 = first+(taskIndex+0)*(last-first)/taskCount;
- const Index k1 = first+(taskIndex+1)*(last-first)/taskCount;
- values[taskIndex] = func(range<Index>(k0,k1));
- });
-
- /* perform reduction over all tasks */
- Value v = identity;
- for (Index i=0; i<taskCount; i++) v = reduction(v,values[i]);
- return v;
- }
-
- template<typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_reduce( const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
- {
-#if defined(TASKING_INTERNAL) || (defined(TASKING_GCD) && defined(BUILD_IOS))
-
- /* fast path for small number of iterations */
- Index taskCount = (last-first+minStepSize-1)/minStepSize;
- if (likely(taskCount == 1)) {
- return func(range<Index>(first,last));
- }
- return parallel_reduce_internal(taskCount,first,last,minStepSize,identity,func,reduction);
-
-#elif defined(TASKING_TBB)
- #if TBB_INTERFACE_VERSION >= 12002
- tbb::task_group_context context;
- const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
- [&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
- reduction,context);
- // -- GODOT start --
- // if (context.is_group_execution_cancelled())
- // throw std::runtime_error("task cancelled");
- // -- GODOT end --
- return v;
- #else
- const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
- [&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
- reduction);
- // -- GODOT start --
- // if (tbb::task::self().is_cancelled())
- // throw std::runtime_error("task cancelled");
- // -- GODOT end --
- return v;
- #endif
-#else // TASKING_PPL
- struct AlignedValue
- {
- char storage[__alignof(Value)+sizeof(Value)];
- static uintptr_t alignUp(uintptr_t p, size_t a) { return p + (~(p - 1) % a); };
- Value* getValuePtr() { return reinterpret_cast<Value*>(alignUp(uintptr_t(storage), __alignof(Value))); }
- const Value* getValuePtr() const { return reinterpret_cast<Value*>(alignUp(uintptr_t(storage), __alignof(Value))); }
- AlignedValue(const Value& v) { new(getValuePtr()) Value(v); }
- AlignedValue(const AlignedValue& v) { new(getValuePtr()) Value(*v.getValuePtr()); }
- AlignedValue(const AlignedValue&& v) { new(getValuePtr()) Value(*v.getValuePtr()); };
- AlignedValue& operator = (const AlignedValue& v) { *getValuePtr() = *v.getValuePtr(); return *this; };
- AlignedValue& operator = (const AlignedValue&& v) { *getValuePtr() = *v.getValuePtr(); return *this; };
- operator Value() const { return *getValuePtr(); }
- };
-
- struct Iterator_Index
- {
- Index v;
- typedef std::forward_iterator_tag iterator_category;
- typedef AlignedValue value_type;
- typedef Index difference_type;
- typedef Index distance_type;
- typedef AlignedValue* pointer;
- typedef AlignedValue& reference;
- __forceinline Iterator_Index() {}
- __forceinline Iterator_Index(Index v) : v(v) {}
- __forceinline bool operator== (Iterator_Index other) { return v == other.v; }
- __forceinline bool operator!= (Iterator_Index other) { return v != other.v; }
- __forceinline Iterator_Index operator++() { return Iterator_Index(++v); }
- __forceinline Iterator_Index operator++(int) { return Iterator_Index(v++); }
- };
-
- auto range_reduction = [&](Iterator_Index begin, Iterator_Index end, const AlignedValue& start) {
- assert(begin.v < end.v);
- return reduction(start, func(range<Index>(begin.v, end.v)));
- };
- const Value v = concurrency::parallel_reduce(Iterator_Index(first), Iterator_Index(last), AlignedValue(identity), range_reduction, reduction);
- return v;
-#endif
- }
-
- template<typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_reduce( const Index first, const Index last, const Index minStepSize, const Index parallel_threshold, const Value& identity, const Func& func, const Reduction& reduction )
- {
- if (likely(last-first < parallel_threshold)) {
- return func(range<Index>(first,last));
- } else {
- return parallel_reduce(first,last,minStepSize,identity,func,reduction);
- }
- }
-
- template<typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_reduce( const range<Index> range, const Index minStepSize, const Index parallel_threshold, const Value& identity, const Func& func, const Reduction& reduction )
- {
- return parallel_reduce(range.begin(),range.end(),minStepSize,parallel_threshold,identity,func,reduction);
- }
-
- template<typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_reduce( const Index first, const Index last, const Value& identity, const Func& func, const Reduction& reduction )
- {
- auto funcr = [&] ( const range<Index> r ) {
- Value v = identity;
- for (Index i=r.begin(); i<r.end(); i++)
- v = reduction(v,func(i));
- return v;
- };
- return parallel_reduce(first,last,Index(1),identity,funcr,reduction);
- }
-
- template<typename Index, typename Value, typename Func, typename Reduction>
- __forceinline Value parallel_reduce( const range<Index> range, const Value& identity, const Func& func, const Reduction& reduction )
- {
- return parallel_reduce(range.begin(),range.end(),Index(1),identity,func,reduction);
- }
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_set.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_set.cpp
deleted file mode 100644
index 20b639c1c9..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_set.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_set.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- struct parallel_set_regression_test : public RegressionTest
- {
- parallel_set_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
-
- /* create vector with random numbers */
- const size_t N = 10000;
- std::vector<uint32_t> unsorted(N);
- for (size_t i=0; i<N; i++) unsorted[i] = 2*rand();
-
- /* created set from numbers */
- parallel_set<uint32_t> sorted;
- sorted.init(unsorted);
-
- /* check that all elements are in the set */
- for (size_t i=0; i<N; i++) {
- passed &= sorted.lookup(unsorted[i]);
- }
-
- /* check that these elements are not in the set */
- for (size_t i=0; i<N; i++) {
- passed &= !sorted.lookup(unsorted[i]+1);
- }
-
- return passed;
- }
- };
-
- parallel_set_regression_test parallel_set_regression("parallel_set_regression_test");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_set.h b/thirdparty/embree-aarch64/common/algorithms/parallel_set.h
deleted file mode 100644
index 640beba7ec..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_set.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "parallel_sort.h"
-
-namespace embree
-{
- /* implementation of a set of values with parallel construction */
- template<typename T>
- class parallel_set
- {
- public:
-
- /*! default constructor for the parallel set */
- parallel_set () {}
-
- /*! construction from vector */
- template<typename Vector>
- parallel_set (const Vector& in) { init(in); }
-
- /*! initialized the parallel set from a vector */
- template<typename Vector>
- void init(const Vector& in)
- {
- /* copy data to internal vector */
- vec.resize(in.size());
- parallel_for( size_t(0), in.size(), size_t(4*4096), [&](const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++)
- vec[i] = in[i];
- });
-
- /* sort the data */
- std::vector<T> temp(in.size());
- radix_sort<T>(vec.data(),temp.data(),vec.size());
- }
-
- /*! tests if some element is in the set */
- __forceinline bool lookup(const T& elt) const {
- return std::binary_search(vec.begin(), vec.end(), elt);
- }
-
- /*! clears all state */
- void clear() {
- vec.clear();
- }
-
- private:
- std::vector<T> vec; //!< vector containing sorted elements
- };
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_sort.cpp b/thirdparty/embree-aarch64/common/algorithms/parallel_sort.cpp
deleted file mode 100644
index 5e7ec79ac1..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_sort.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "parallel_sort.h"
-#include "../sys/regression.h"
-
-namespace embree
-{
- template<typename Key>
- struct RadixSortRegressionTest : public RegressionTest
- {
- RadixSortRegressionTest(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
- const size_t M = 10;
-
- for (size_t N=10; N<1000000; N=size_t(2.1*N))
- {
- std::vector<Key> src(N); memset(src.data(),0,N*sizeof(Key));
- std::vector<Key> tmp(N); memset(tmp.data(),0,N*sizeof(Key));
- for (size_t i=0; i<N; i++) src[i] = uint64_t(rand())*uint64_t(rand());
-
- /* calculate checksum */
- Key sum0 = 0; for (size_t i=0; i<N; i++) sum0 += src[i];
-
- /* sort numbers */
- for (size_t i=0; i<M; i++) {
- radix_sort<Key>(src.data(),tmp.data(),N);
- }
-
- /* calculate checksum */
- Key sum1 = 0; for (size_t i=0; i<N; i++) sum1 += src[i];
- if (sum0 != sum1) passed = false;
-
- /* check if numbers are sorted */
- for (size_t i=1; i<N; i++)
- passed &= src[i-1] <= src[i];
- }
-
- return passed;
- }
- };
-
- RadixSortRegressionTest<uint32_t> test_u32("RadixSortRegressionTestU32");
- RadixSortRegressionTest<uint64_t> test_u64("RadixSortRegressionTestU64");
-}
diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_sort.h b/thirdparty/embree-aarch64/common/algorithms/parallel_sort.h
deleted file mode 100644
index a758227c1b..0000000000
--- a/thirdparty/embree-aarch64/common/algorithms/parallel_sort.h
+++ /dev/null
@@ -1,457 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../simd/simd.h"
-#include "parallel_for.h"
-#if defined(TASKING_GCD) && defined(BUILD_IOS)
-#include "../sys/alloc.h"
-#endif
-#include <algorithm>
-
-namespace embree
-{
- template<class T>
- __forceinline void insertionsort_ascending(T *__restrict__ array, const size_t length)
- {
- for(size_t i = 1;i<length;++i)
- {
- T v = array[i];
- size_t j = i;
- while(j > 0 && v < array[j-1])
- {
- array[j] = array[j-1];
- --j;
- }
- array[j] = v;
- }
- }
-
- template<class T>
- __forceinline void insertionsort_decending(T *__restrict__ array, const size_t length)
- {
- for(size_t i = 1;i<length;++i)
- {
- T v = array[i];
- size_t j = i;
- while(j > 0 && v > array[j-1])
- {
- array[j] = array[j-1];
- --j;
- }
- array[j] = v;
- }
- }
-
- template<class T>
- void quicksort_ascending(T *__restrict__ t,
- const ssize_t begin,
- const ssize_t end)
- {
- if (likely(begin < end))
- {
- const T pivotvalue = t[begin];
- ssize_t left = begin - 1;
- ssize_t right = end + 1;
-
- while(1)
- {
- while (t[--right] > pivotvalue);
- while (t[++left] < pivotvalue);
-
- if (left >= right) break;
-
- const T temp = t[right];
- t[right] = t[left];
- t[left] = temp;
- }
-
- const int pivot = right;
- quicksort_ascending(t, begin, pivot);
- quicksort_ascending(t, pivot + 1, end);
- }
- }
-
- template<class T>
- void quicksort_decending(T *__restrict__ t,
- const ssize_t begin,
- const ssize_t end)
- {
- if (likely(begin < end))
- {
- const T pivotvalue = t[begin];
- ssize_t left = begin - 1;
- ssize_t right = end + 1;
-
- while(1)
- {
- while (t[--right] < pivotvalue);
- while (t[++left] > pivotvalue);
-
- if (left >= right) break;
-
- const T temp = t[right];
- t[right] = t[left];
- t[left] = temp;
- }
-
- const int pivot = right;
- quicksort_decending(t, begin, pivot);
- quicksort_decending(t, pivot + 1, end);
- }
- }
-
-
- template<class T, ssize_t THRESHOLD>
- void quicksort_insertionsort_ascending(T *__restrict__ t,
- const ssize_t begin,
- const ssize_t end)
- {
- if (likely(begin < end))
- {
- const ssize_t size = end-begin+1;
- if (likely(size <= THRESHOLD))
- {
- insertionsort_ascending<T>(&t[begin],size);
- }
- else
- {
- const T pivotvalue = t[begin];
- ssize_t left = begin - 1;
- ssize_t right = end + 1;
-
- while(1)
- {
- while (t[--right] > pivotvalue);
- while (t[++left] < pivotvalue);
-
- if (left >= right) break;
-
- const T temp = t[right];
- t[right] = t[left];
- t[left] = temp;
- }
-
- const ssize_t pivot = right;
- quicksort_insertionsort_ascending<T,THRESHOLD>(t, begin, pivot);
- quicksort_insertionsort_ascending<T,THRESHOLD>(t, pivot + 1, end);
- }
- }
- }
-
-
- template<class T, ssize_t THRESHOLD>
- void quicksort_insertionsort_decending(T *__restrict__ t,
- const ssize_t begin,
- const ssize_t end)
- {
- if (likely(begin < end))
- {
- const ssize_t size = end-begin+1;
- if (likely(size <= THRESHOLD))
- {
- insertionsort_decending<T>(&t[begin],size);
- }
- else
- {
-
- const T pivotvalue = t[begin];
- ssize_t left = begin - 1;
- ssize_t right = end + 1;
-
- while(1)
- {
- while (t[--right] < pivotvalue);
- while (t[++left] > pivotvalue);
-
- if (left >= right) break;
-
- const T temp = t[right];
- t[right] = t[left];
- t[left] = temp;
- }
-
- const ssize_t pivot = right;
- quicksort_insertionsort_decending<T,THRESHOLD>(t, begin, pivot);
- quicksort_insertionsort_decending<T,THRESHOLD>(t, pivot + 1, end);
- }
- }
- }
-
- template<typename T>
- static void radixsort32(T* const morton, const size_t num, const unsigned int shift = 3*8)
- {
- static const unsigned int BITS = 8;
- static const unsigned int BUCKETS = (1 << BITS);
- static const unsigned int CMP_SORT_THRESHOLD = 16;
-
- __aligned(64) unsigned int count[BUCKETS];
-
- /* clear buckets */
- for (size_t i=0;i<BUCKETS;i++) count[i] = 0;
-
- /* count buckets */
-#if defined(__INTEL_COMPILER)
-#pragma nounroll
-#endif
- for (size_t i=0;i<num;i++)
- count[(unsigned(morton[i]) >> shift) & (BUCKETS-1)]++;
-
- /* prefix sums */
- __aligned(64) unsigned int head[BUCKETS];
- __aligned(64) unsigned int tail[BUCKETS];
-
- head[0] = 0;
- for (size_t i=1; i<BUCKETS; i++)
- head[i] = head[i-1] + count[i-1];
-
- for (size_t i=0; i<BUCKETS-1; i++)
- tail[i] = head[i+1];
-
- tail[BUCKETS-1] = head[BUCKETS-1] + count[BUCKETS-1];
-
- assert(tail[BUCKETS-1] == head[BUCKETS-1] + count[BUCKETS-1]);
- assert(tail[BUCKETS-1] == num);
-
- /* in-place swap */
- for (size_t i=0;i<BUCKETS;i++)
- {
- /* process bucket */
- while(head[i] < tail[i])
- {
- T v = morton[head[i]];
- while(1)
- {
- const size_t b = (unsigned(v) >> shift) & (BUCKETS-1);
- if (b == i) break;
- std::swap(v,morton[head[b]++]);
- }
- assert((unsigned(v) >> shift & (BUCKETS-1)) == i);
- morton[head[i]++] = v;
- }
- }
- if (shift == 0) return;
-
- size_t offset = 0;
- for (size_t i=0;i<BUCKETS;i++)
- if (count[i])
- {
-
- for (size_t j=offset;j<offset+count[i]-1;j++)
- assert(((unsigned(morton[j]) >> shift) & (BUCKETS-1)) == i);
-
- if (unlikely(count[i] < CMP_SORT_THRESHOLD))
- insertionsort_ascending(morton + offset, count[i]);
- else
- radixsort32(morton + offset, count[i], shift-BITS);
-
- for (size_t j=offset;j<offset+count[i]-1;j++)
- assert(morton[j] <= morton[j+1]);
-
- offset += count[i];
- }
- }
-
- template<typename Ty, typename Key>
- class ParallelRadixSort
- {
- static const size_t MAX_TASKS = 64;
- static const size_t BITS = 8;
- static const size_t BUCKETS = (1 << BITS);
- typedef unsigned int TyRadixCount[BUCKETS];
-
- template<typename T>
- static bool compare(const T& v0, const T& v1) {
- return (Key)v0 < (Key)v1;
- }
-
- private:
- ParallelRadixSort (const ParallelRadixSort& other) DELETED; // do not implement
- ParallelRadixSort& operator= (const ParallelRadixSort& other) DELETED; // do not implement
-
-
- public:
- ParallelRadixSort (Ty* const src, Ty* const tmp, const size_t N)
- : radixCount(nullptr), src(src), tmp(tmp), N(N) {}
-
- void sort(const size_t blockSize)
- {
- assert(blockSize > 0);
-
- /* perform single threaded sort for small N */
- if (N<=blockSize) // handles also special case of 0!
- {
- /* do inplace sort inside destination array */
- std::sort(src,src+N,compare<Ty>);
- }
-
- /* perform parallel sort for large N */
- else
- {
- const size_t numThreads = min((N+blockSize-1)/blockSize,TaskScheduler::threadCount(),size_t(MAX_TASKS));
- tbbRadixSort(numThreads);
- }
- }
-
- ~ParallelRadixSort()
- {
- alignedFree(radixCount);
- radixCount = nullptr;
- }
-
- private:
-
- void tbbRadixIteration0(const Key shift,
- const Ty* __restrict const src,
- Ty* __restrict const dst,
- const size_t threadIndex, const size_t threadCount)
- {
- const size_t startID = (threadIndex+0)*N/threadCount;
- const size_t endID = (threadIndex+1)*N/threadCount;
-
- /* mask to extract some number of bits */
- const Key mask = BUCKETS-1;
-
- /* count how many items go into the buckets */
- for (size_t i=0; i<BUCKETS; i++)
- radixCount[threadIndex][i] = 0;
-
- /* iterate over src array and count buckets */
- unsigned int * __restrict const count = radixCount[threadIndex];
-#if defined(__INTEL_COMPILER)
-#pragma nounroll
-#endif
- for (size_t i=startID; i<endID; i++) {
-#if defined(__X86_64__) || defined(__aarch64__)
- const size_t index = ((size_t)(Key)src[i] >> (size_t)shift) & (size_t)mask;
-#else
- const Key index = ((Key)src[i] >> shift) & mask;
-#endif
- count[index]++;
- }
- }
-
- void tbbRadixIteration1(const Key shift,
- const Ty* __restrict const src,
- Ty* __restrict const dst,
- const size_t threadIndex, const size_t threadCount)
- {
- const size_t startID = (threadIndex+0)*N/threadCount;
- const size_t endID = (threadIndex+1)*N/threadCount;
-
- /* mask to extract some number of bits */
- const Key mask = BUCKETS-1;
-
- /* calculate total number of items for each bucket */
- __aligned(64) unsigned int total[BUCKETS];
- /*
- for (size_t i=0; i<BUCKETS; i++)
- total[i] = 0;
- */
- for (size_t i=0; i<BUCKETS; i+=VSIZEX)
- vintx::store(&total[i], zero);
-
- for (size_t i=0; i<threadCount; i++)
- {
- /*
- for (size_t j=0; j<BUCKETS; j++)
- total[j] += radixCount[i][j];
- */
- for (size_t j=0; j<BUCKETS; j+=VSIZEX)
- vintx::store(&total[j], vintx::load(&total[j]) + vintx::load(&radixCount[i][j]));
- }
-
- /* calculate start offset of each bucket */
- __aligned(64) unsigned int offset[BUCKETS];
- offset[0] = 0;
- for (size_t i=1; i<BUCKETS; i++)
- offset[i] = offset[i-1] + total[i-1];
-
- /* calculate start offset of each bucket for this thread */
- for (size_t i=0; i<threadIndex; i++)
- {
- /*
- for (size_t j=0; j<BUCKETS; j++)
- offset[j] += radixCount[i][j];
- */
- for (size_t j=0; j<BUCKETS; j+=VSIZEX)
- vintx::store(&offset[j], vintx::load(&offset[j]) + vintx::load(&radixCount[i][j]));
- }
-
- /* copy items into their buckets */
-#if defined(__INTEL_COMPILER)
-#pragma nounroll
-#endif
- for (size_t i=startID; i<endID; i++) {
- const Ty elt = src[i];
-#if defined(__X86_64__) || defined(__aarch64__)
- const size_t index = ((size_t)(Key)src[i] >> (size_t)shift) & (size_t)mask;
-#else
- const size_t index = ((Key)src[i] >> shift) & mask;
-#endif
- dst[offset[index]++] = elt;
- }
- }
-
- void tbbRadixIteration(const Key shift, const bool last,
- const Ty* __restrict src, Ty* __restrict dst,
- const size_t numTasks)
- {
- affinity_partitioner ap;
- parallel_for_affinity(numTasks,[&] (size_t taskIndex) { tbbRadixIteration0(shift,src,dst,taskIndex,numTasks); },ap);
- parallel_for_affinity(numTasks,[&] (size_t taskIndex) { tbbRadixIteration1(shift,src,dst,taskIndex,numTasks); },ap);
- }
-
- void tbbRadixSort(const size_t numTasks)
- {
- radixCount = (TyRadixCount*) alignedMalloc(MAX_TASKS*sizeof(TyRadixCount),64);
-
- if (sizeof(Key) == sizeof(uint32_t)) {
- tbbRadixIteration(0*BITS,0,src,tmp,numTasks);
- tbbRadixIteration(1*BITS,0,tmp,src,numTasks);
- tbbRadixIteration(2*BITS,0,src,tmp,numTasks);
- tbbRadixIteration(3*BITS,1,tmp,src,numTasks);
- }
- else if (sizeof(Key) == sizeof(uint64_t))
- {
- tbbRadixIteration(0*BITS,0,src,tmp,numTasks);
- tbbRadixIteration(1*BITS,0,tmp,src,numTasks);
- tbbRadixIteration(2*BITS,0,src,tmp,numTasks);
- tbbRadixIteration(3*BITS,0,tmp,src,numTasks);
- tbbRadixIteration(4*BITS,0,src,tmp,numTasks);
- tbbRadixIteration(5*BITS,0,tmp,src,numTasks);
- tbbRadixIteration(6*BITS,0,src,tmp,numTasks);
- tbbRadixIteration(7*BITS,1,tmp,src,numTasks);
- }
- }
-
- private:
- TyRadixCount* radixCount;
- Ty* const src;
- Ty* const tmp;
- const size_t N;
- };
-
- template<typename Ty>
- void radix_sort(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192)
- {
- ParallelRadixSort<Ty,Ty>(src,tmp,N).sort(blockSize);
- }
-
- template<typename Ty, typename Key>
- void radix_sort(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192)
- {
- ParallelRadixSort<Ty,Key>(src,tmp,N).sort(blockSize);
- }
-
- template<typename Ty>
- void radix_sort_u32(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192) {
- radix_sort<Ty,uint32_t>(src,tmp,N,blockSize);
- }
-
- template<typename Ty>
- void radix_sort_u64(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192) {
- radix_sort<Ty,uint64_t>(src,tmp,N,blockSize);
- }
-}
diff --git a/thirdparty/embree-aarch64/common/lexers/parsestream.h b/thirdparty/embree-aarch64/common/lexers/parsestream.h
deleted file mode 100644
index db46dc114f..0000000000
--- a/thirdparty/embree-aarch64/common/lexers/parsestream.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "stringstream.h"
-#include "../sys/filename.h"
-#include "../math/vec2.h"
-#include "../math/vec3.h"
-#include "../math/col3.h"
-#include "../math/color.h"
-
-namespace embree
-{
- /*! helper class for simple command line parsing */
- class ParseStream : public Stream<std::string>
- {
- public:
- ParseStream (const Ref<Stream<std::string> >& cin) : cin(cin) {}
-
- ParseStream (const Ref<Stream<int> >& cin, const std::string& seps = "\n\t\r ",
- const std::string& endl = "", bool multiLine = false)
- : cin(new StringStream(cin,seps,endl,multiLine)) {}
-
- public:
- ParseLocation location() { return cin->loc(); }
- std::string next() { return cin->get(); }
-
- void force(const std::string& next) {
- std::string token = getString();
- if (token != next)
- THROW_RUNTIME_ERROR("token \""+next+"\" expected but token \""+token+"\" found");
- }
-
- std::string getString() {
- return get();
- }
-
- FileName getFileName() {
- return FileName(get());
- }
-
- int getInt () {
- return atoi(get().c_str());
- }
-
- Vec2i getVec2i() {
- int x = atoi(get().c_str());
- int y = atoi(get().c_str());
- return Vec2i(x,y);
- }
-
- Vec3ia getVec3ia() {
- int x = atoi(get().c_str());
- int y = atoi(get().c_str());
- int z = atoi(get().c_str());
- return Vec3ia(x,y,z);
- }
-
- float getFloat() {
- return (float)atof(get().c_str());
- }
-
- Vec2f getVec2f() {
- float x = (float)atof(get().c_str());
- float y = (float)atof(get().c_str());
- return Vec2f(x,y);
- }
-
- Vec3f getVec3f() {
- float x = (float)atof(get().c_str());
- float y = (float)atof(get().c_str());
- float z = (float)atof(get().c_str());
- return Vec3f(x,y,z);
- }
-
- Vec3fa getVec3fa() {
- float x = (float)atof(get().c_str());
- float y = (float)atof(get().c_str());
- float z = (float)atof(get().c_str());
- return Vec3fa(x,y,z);
- }
-
- Col3f getCol3f() {
- float x = (float)atof(get().c_str());
- float y = (float)atof(get().c_str());
- float z = (float)atof(get().c_str());
- return Col3f(x,y,z);
- }
-
- Color getColor() {
- float r = (float)atof(get().c_str());
- float g = (float)atof(get().c_str());
- float b = (float)atof(get().c_str());
- return Color(r,g,b);
- }
-
- private:
- Ref<Stream<std::string> > cin;
- };
-}
diff --git a/thirdparty/embree-aarch64/common/lexers/stream.h b/thirdparty/embree-aarch64/common/lexers/stream.h
deleted file mode 100644
index 3f75677e68..0000000000
--- a/thirdparty/embree-aarch64/common/lexers/stream.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/ref.h"
-#include "../sys/filename.h"
-#include "../sys/string.h"
-
-#include <vector>
-#include <iostream>
-#include <cstdio>
-#include <string.h>
-
-namespace embree
-{
- /*! stores the location of a stream element in the source */
- class ParseLocation
- {
- public:
- ParseLocation () : lineNumber(-1), colNumber(-1) {}
- ParseLocation (std::shared_ptr<std::string> fileName, ssize_t lineNumber, ssize_t colNumber, ssize_t /*charNumber*/)
- : fileName(fileName), lineNumber(lineNumber), colNumber(colNumber) {}
-
- std::string str() const
- {
- std::string str = "unknown";
- if (fileName) str = *fileName;
- if (lineNumber >= 0) str += " line " + toString(lineNumber);
- if (lineNumber >= 0 && colNumber >= 0) str += " character " + toString(colNumber);
- return str;
- }
-
- private:
- std::shared_ptr<std::string> fileName; /// name of the file (or stream) the token is from
- ssize_t lineNumber; /// the line number the token is from
- ssize_t colNumber; /// the character number in the current line
- };
-
- /*! a stream class templated over the stream elements */
- template<typename T> class Stream : public RefCount
- {
- enum { BUF_SIZE = 1024 };
-
- private:
- virtual T next() = 0;
- virtual ParseLocation location() = 0;
- __forceinline std::pair<T,ParseLocation> nextHelper() {
- ParseLocation l = location();
- T v = next();
- return std::pair<T,ParseLocation>(v,l);
- }
- __forceinline void push_back(const std::pair<T,ParseLocation>& v) {
- if (past+future == BUF_SIZE) pop_front();
- size_t end = (start+past+future++)%BUF_SIZE;
- buffer[end] = v;
- }
- __forceinline void pop_front() {
- if (past == 0) THROW_RUNTIME_ERROR("stream buffer empty");
- start = (start+1)%BUF_SIZE; past--;
- }
- public:
- Stream () : start(0), past(0), future(0), buffer(BUF_SIZE) {}
- virtual ~Stream() {}
-
- public:
-
- const ParseLocation& loc() {
- if (future == 0) push_back(nextHelper());
- return buffer[(start+past)%BUF_SIZE].second;
- }
- T get() {
- if (future == 0) push_back(nextHelper());
- T t = buffer[(start+past)%BUF_SIZE].first;
- past++; future--;
- return t;
- }
- const T& peek() {
- if (future == 0) push_back(nextHelper());
- return buffer[(start+past)%BUF_SIZE].first;
- }
- const T& unget(size_t n = 1) {
- if (past < n) THROW_RUNTIME_ERROR ("cannot unget that many items");
- past -= n; future += n;
- return peek();
- }
- void drop() {
- if (future == 0) push_back(nextHelper());
- past++; future--;
- }
- private:
- size_t start,past,future;
- std::vector<std::pair<T,ParseLocation> > buffer;
- };
-
- /*! warps an iostream stream */
- class StdStream : public Stream<int>
- {
- public:
- StdStream (std::istream& cin, const std::string& name = "std::stream")
- : cin(cin), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}
- ~StdStream() {}
- ParseLocation location() {
- return ParseLocation(name,lineNumber,colNumber,charNumber);
- }
- int next() {
- int c = cin.get();
- if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;
- charNumber++;
- return c;
- }
- private:
- std::istream& cin;
- ssize_t lineNumber; /// the line number the token is from
- ssize_t colNumber; /// the character number in the current line
- ssize_t charNumber; /// the character in the file
- std::shared_ptr<std::string> name; /// name of buffer
- };
-
- /*! creates a stream from a file */
- class FileStream : public Stream<int>
- {
- public:
-
- FileStream (FILE* file, const std::string& name = "file")
- : file(file), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}
-
- FileStream (const FileName& fileName)
- : lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(fileName.str())))
- {
- file = fopen(fileName.c_str(),"r");
- if (file == nullptr) THROW_RUNTIME_ERROR("cannot open file " + fileName.str());
- }
- ~FileStream() { if (file) fclose(file); }
-
- public:
- ParseLocation location() {
- return ParseLocation(name,lineNumber,colNumber,charNumber);
- }
-
- int next() {
- int c = fgetc(file);
- if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;
- charNumber++;
- return c;
- }
-
- private:
- FILE* file;
- ssize_t lineNumber; /// the line number the token is from
- ssize_t colNumber; /// the character number in the current line
- ssize_t charNumber; /// the character in the file
- std::shared_ptr<std::string> name; /// name of buffer
- };
-
- /*! creates a stream from a string */
- class StrStream : public Stream<int>
- {
- public:
-
- StrStream (const char* str)
- : str(str), lineNumber(1), colNumber(0), charNumber(0) {}
-
- public:
- ParseLocation location() {
- return ParseLocation(std::shared_ptr<std::string>(),lineNumber,colNumber,charNumber);
- }
-
- int next() {
- int c = str[charNumber];
- if (c == 0) return EOF;
- if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;
- charNumber++;
- return c;
- }
-
- private:
- const char* str;
- ssize_t lineNumber; /// the line number the token is from
- ssize_t colNumber; /// the character number in the current line
- ssize_t charNumber; /// the character in the file
- };
-
- /*! creates a character stream from a command line */
- class CommandLineStream : public Stream<int>
- {
- public:
- CommandLineStream (int argc, char** argv, const std::string& name = "command line")
- : i(0), j(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name)))
- {
- if (argc > 0) {
- for (size_t i=0; argv[0][i] && i<1024; i++) charNumber++;
- charNumber++;
- }
- for (ssize_t k=1; k<argc; k++) args.push_back(argv[k]);
- }
- ~CommandLineStream() {}
- public:
- ParseLocation location() {
- return ParseLocation(name,0,charNumber,charNumber);
- }
- int next() {
- if (i == args.size()) return EOF;
- if (j == args[i].size()) { i++; j=0; charNumber++; return ' '; }
- charNumber++;
- return args[i][j++];
- }
- private:
- size_t i,j;
- std::vector<std::string> args;
- ssize_t charNumber; /// the character in the file
- std::shared_ptr<std::string> name; /// name of buffer
- };
-}
diff --git a/thirdparty/embree-aarch64/common/lexers/streamfilters.h b/thirdparty/embree-aarch64/common/lexers/streamfilters.h
deleted file mode 100644
index 25580a77b8..0000000000
--- a/thirdparty/embree-aarch64/common/lexers/streamfilters.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "stream.h"
-
-namespace embree
-{
- /* removes all line comments from a stream */
- class LineCommentFilter : public Stream<int>
- {
- public:
- LineCommentFilter (const FileName& fileName, const std::string& lineComment)
- : cin(new FileStream(fileName)), lineComment(lineComment) {}
- LineCommentFilter (Ref<Stream<int> > cin, const std::string& lineComment)
- : cin(cin), lineComment(lineComment) {}
-
- ParseLocation location() { return cin->loc(); }
-
- int next()
- {
- /* look if the line comment starts here */
- for (size_t j=0; j<lineComment.size(); j++) {
- if (cin->peek() != lineComment[j]) { cin->unget(j); goto not_found; }
- cin->get();
- }
- /* eat all characters until the end of the line (or file) */
- while (cin->peek() != '\n' && cin->peek() != EOF) cin->get();
-
- not_found:
- return cin->get();
- }
-
- private:
- Ref<Stream<int> > cin;
- std::string lineComment;
- };
-}
diff --git a/thirdparty/embree-aarch64/common/lexers/stringstream.cpp b/thirdparty/embree-aarch64/common/lexers/stringstream.cpp
deleted file mode 100644
index 98dc80ad59..0000000000
--- a/thirdparty/embree-aarch64/common/lexers/stringstream.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "stringstream.h"
-
-namespace embree
-{
- static const std::string stringChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _.,+-=:/*\\";
-
- /* creates map for fast categorization of characters */
- static void createCharMap(bool map[256], const std::string& chrs) {
- for (size_t i=0; i<256; i++) map[i] = false;
- for (size_t i=0; i<chrs.size(); i++) map[uint8_t(chrs[i])] = true;
- }
-
- /* simple tokenizer */
- StringStream::StringStream(const Ref<Stream<int> >& cin, const std::string& seps, const std::string& endl, bool multiLine)
- : cin(cin), endl(endl), multiLine(multiLine)
- {
- createCharMap(isSepMap,seps);
- createCharMap(isValidCharMap,stringChars);
- }
-
- std::string StringStream::next()
- {
- /* skip separators */
- while (cin->peek() != EOF) {
- if (endl != "" && cin->peek() == '\n') { cin->drop(); return endl; }
- if (multiLine && cin->peek() == '\\') {
- cin->drop();
- if (cin->peek() == '\n') { cin->drop(); continue; }
- cin->unget();
- }
- if (!isSeparator(cin->peek())) break;
- cin->drop();
- }
-
- /* parse everything until the next separator */
- std::vector<char> str; str.reserve(64);
- while (cin->peek() != EOF && !isSeparator(cin->peek())) {
- int c = cin->get();
- // -- GODOT start --
- // if (!isValidChar(c)) throw std::runtime_error("invalid character "+std::string(1,c)+" in input");
- if (!isValidChar(c)) abort();
- // -- GODOT end --
- str.push_back((char)c);
- }
- str.push_back(0);
- return std::string(str.data());
- }
-}
diff --git a/thirdparty/embree-aarch64/common/lexers/stringstream.h b/thirdparty/embree-aarch64/common/lexers/stringstream.h
deleted file mode 100644
index e6dbd4aecc..0000000000
--- a/thirdparty/embree-aarch64/common/lexers/stringstream.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "stream.h"
-
-namespace embree
-{
- /*! simple tokenizer that produces a string stream */
- class StringStream : public Stream<std::string>
- {
- public:
- StringStream(const Ref<Stream<int> >& cin, const std::string& seps = "\n\t\r ",
- const std::string& endl = "", bool multiLine = false);
- public:
- ParseLocation location() { return cin->loc(); }
- std::string next();
- private:
- __forceinline bool isSeparator(unsigned int c) const { return c<256 && isSepMap[c]; }
- __forceinline bool isValidChar(unsigned int c) const { return c<256 && isValidCharMap[c]; }
- private:
- Ref<Stream<int> > cin; /*! source character stream */
- bool isSepMap[256]; /*! map for fast classification of separators */
- bool isValidCharMap[256]; /*! map for valid characters */
- std::string endl; /*! the token of the end of line */
- bool multiLine; /*! whether to parse lines wrapped with \ */
- };
-}
diff --git a/thirdparty/embree-aarch64/common/lexers/tokenstream.cpp b/thirdparty/embree-aarch64/common/lexers/tokenstream.cpp
deleted file mode 100644
index d05be65862..0000000000
--- a/thirdparty/embree-aarch64/common/lexers/tokenstream.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "tokenstream.h"
-#include "../math/math.h"
-
-namespace embree
-{
- /* shorthands for common sets of characters */
- const std::string TokenStream::alpha = "abcdefghijklmnopqrstuvwxyz";
- const std::string TokenStream::ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- const std::string TokenStream::numbers = "0123456789";
- const std::string TokenStream::separators = "\n\t\r ";
- const std::string TokenStream::stringChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _.,+-=:/*\\";
-
- /* creates map for fast categorization of characters */
- static void createCharMap(bool map[256], const std::string& chrs) {
- for (size_t i=0; i<256; i++) map[i] = false;
- for (size_t i=0; i<chrs.size(); i++) map[uint8_t(chrs[i])] = true;
- }
-
- /* build full tokenizer that takes list of valid characters and keywords */
- TokenStream::TokenStream(const Ref<Stream<int> >& cin, //< stream to read from
- const std::string& alpha, //< valid characters for identifiers
- const std::string& seps, //< characters that act as separators
- const std::vector<std::string>& symbols) //< symbols
- : cin(cin), symbols(symbols)
- {
- createCharMap(isAlphaMap,alpha);
- createCharMap(isSepMap,seps);
- createCharMap(isStringCharMap,stringChars);
- }
-
- bool TokenStream::decDigits(std::string& str_o)
- {
- bool ok = false;
- std::string str;
- if (cin->peek() == '+' || cin->peek() == '-') str += (char)cin->get();
- while (isDigit(cin->peek())) { ok = true; str += (char)cin->get(); }
- if (ok) str_o += str;
- else cin->unget(str.size());
- return ok;
- }
-
- bool TokenStream::decDigits1(std::string& str_o)
- {
- bool ok = false;
- std::string str;
- while (isDigit(cin->peek())) { ok = true; str += (char)cin->get(); }
- if (ok) str_o += str; else cin->unget(str.size());
- return ok;
- }
-
- bool TokenStream::trySymbol(const std::string& symbol)
- {
- size_t pos = 0;
- while (pos < symbol.size()) {
- if (symbol[pos] != cin->peek()) { cin->unget(pos); return false; }
- cin->drop(); pos++;
- }
- return true;
- }
-
- bool TokenStream::trySymbols(Token& token, const ParseLocation& loc)
- {
- for (size_t i=0; i<symbols.size(); i++) {
- if (!trySymbol(symbols[i])) continue;
- token = Token(symbols[i],Token::TY_SYMBOL,loc);
- return true;
- }
- return false;
- }
-
- bool TokenStream::tryFloat(Token& token, const ParseLocation& loc)
- {
- bool ok = false;
- std::string str;
- if (trySymbol("nan")) {
- token = Token(float(nan));
- return true;
- }
- if (trySymbol("+inf")) {
- token = Token(float(pos_inf));
- return true;
- }
- if (trySymbol("-inf")) {
- token = Token(float(neg_inf));
- return true;
- }
-
- if (decDigits(str))
- {
- if (cin->peek() == '.') {
- str += (char)cin->get();
- decDigits(str);
- if (cin->peek() == 'e' || cin->peek() == 'E') {
- str += (char)cin->get();
- if (decDigits(str)) ok = true; // 1.[2]E2
- }
- else ok = true; // 1.[2]
- }
- else if (cin->peek() == 'e' || cin->peek() == 'E') {
- str += (char)cin->get();
- if (decDigits(str)) ok = true; // 1E2
- }
- }
- else
- {
- if (cin->peek() == '.') {
- str += (char)cin->get();
- if (decDigits(str)) {
- if (cin->peek() == 'e' || cin->peek() == 'E') {
- str += (char)cin->get();
- if (decDigits(str)) ok = true; // .3E2
- }
- else ok = true; // .3
- }
- }
- }
- if (ok) {
- token = Token((float)atof(str.c_str()),loc);
- }
- else cin->unget(str.size());
- return ok;
- }
-
- bool TokenStream::tryInt(Token& token, const ParseLocation& loc) {
- std::string str;
- if (decDigits(str)) {
- token = Token(atoi(str.c_str()),loc);
- return true;
- }
- return false;
- }
-
- bool TokenStream::tryString(Token& token, const ParseLocation& loc)
- {
- std::string str;
- if (cin->peek() != '\"') return false;
- cin->drop();
- while (cin->peek() != '\"') {
- const int c = cin->get();
- if (!isStringChar(c)) THROW_RUNTIME_ERROR("invalid string character "+std::string(1,c)+" at "+loc.str());
- str += (char)c;
- }
- cin->drop();
- token = Token(str,Token::TY_STRING,loc);
- return true;
- }
-
- bool TokenStream::tryIdentifier(Token& token, const ParseLocation& loc)
- {
- std::string str;
- if (!isAlpha(cin->peek())) return false;
- str += (char)cin->get();
- while (isAlphaNum(cin->peek())) str += (char)cin->get();
- token = Token(str,Token::TY_IDENTIFIER,loc);
- return true;
- }
-
- void TokenStream::skipSeparators()
- {
- /* skip separators */
- while (cin->peek() != EOF && isSeparator(cin->peek()))
- cin->drop();
- }
-
- Token TokenStream::next()
- {
- Token token;
- skipSeparators();
- ParseLocation loc = cin->loc();
- if (trySymbols (token,loc)) return token; /**< try to parse a symbol */
- if (tryFloat (token,loc)) return token; /**< try to parse float */
- if (tryInt (token,loc)) return token; /**< try to parse integer */
- if (tryString (token,loc)) return token; /**< try to parse string */
- if (tryIdentifier(token,loc)) return token; /**< try to parse identifier */
- if (cin->peek() == EOF ) return Token(loc); /**< return EOF token */
- return Token((char)cin->get(),loc); /**< return invalid character token */
- }
-}
diff --git a/thirdparty/embree-aarch64/common/lexers/tokenstream.h b/thirdparty/embree-aarch64/common/lexers/tokenstream.h
deleted file mode 100644
index 72a7b4f2f3..0000000000
--- a/thirdparty/embree-aarch64/common/lexers/tokenstream.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "stream.h"
-#include <string>
-#include <vector>
-
-namespace embree
-{
- /*! token class */
- class Token
- {
- public:
-
- enum Type { TY_EOF, TY_CHAR, TY_INT, TY_FLOAT, TY_IDENTIFIER, TY_STRING, TY_SYMBOL };
-
- Token ( const ParseLocation& loc = ParseLocation()) : ty(TY_EOF ), loc(loc) {}
- Token (char c, const ParseLocation& loc = ParseLocation()) : ty(TY_CHAR ), c(c), loc(loc) {}
- Token (int i, const ParseLocation& loc = ParseLocation()) : ty(TY_INT ), i(i), loc(loc) {}
- Token (float f,const ParseLocation& loc = ParseLocation()) : ty(TY_FLOAT), f(f), loc(loc) {}
- Token (std::string str, Type ty, const ParseLocation& loc = ParseLocation()) : ty(ty), str(str), loc(loc) {}
-
- static Token Eof() { return Token(); }
- static Token Sym(std::string str) { return Token(str,TY_SYMBOL); }
- static Token Str(std::string str) { return Token(str,TY_STRING); }
- static Token Id (std::string str) { return Token(str,TY_IDENTIFIER); }
-
- char Char() const {
- if (ty == TY_CHAR) return c;
- THROW_RUNTIME_ERROR(loc.str()+": character expected");
- }
-
- int Int() const {
- if (ty == TY_INT) return i;
- THROW_RUNTIME_ERROR(loc.str()+": integer expected");
- }
-
- float Float(bool cast = true) const {
- if (ty == TY_FLOAT) return f;
- if (ty == TY_INT && cast) return (float)i;
- THROW_RUNTIME_ERROR(loc.str()+": float expected");
- }
-
- std::string Identifier() const {
- if (ty == TY_IDENTIFIER) return str;
- THROW_RUNTIME_ERROR(loc.str()+": identifier expected");
- }
-
- std::string String() const {
- if (ty == TY_STRING) return str;
- THROW_RUNTIME_ERROR(loc.str()+": string expected");
- }
-
- std::string Symbol() const {
- if (ty == TY_SYMBOL) return str;
- THROW_RUNTIME_ERROR(loc.str()+": symbol expected");
- }
-
- const ParseLocation& Location() const { return loc; }
-
- friend bool operator==(const Token& a, const Token& b)
- {
- if (a.ty != b.ty) return false;
- if (a.ty == TY_CHAR) return a.c == b.c;
- if (a.ty == TY_INT) return a.i == b.i;
- if (a.ty == TY_FLOAT) return a.f == b.f;
- if (a.ty == TY_IDENTIFIER) return a.str == b.str;
- if (a.ty == TY_STRING) return a.str == b.str;
- if (a.ty == TY_SYMBOL) return a.str == b.str;
- return true;
- }
-
- friend bool operator!=(const Token& a, const Token& b) {
- return !(a == b);
- }
-
- friend bool operator <( const Token& a, const Token& b ) {
- if (a.ty != b.ty) return (int)a.ty < (int)b.ty;
- if (a.ty == TY_CHAR) return a.c < b.c;
- if (a.ty == TY_INT) return a.i < b.i;
- if (a.ty == TY_FLOAT) return a.f < b.f;
- if (a.ty == TY_IDENTIFIER) return a.str < b.str;
- if (a.ty == TY_STRING) return a.str < b.str;
- if (a.ty == TY_SYMBOL) return a.str < b.str;
- return false;
- }
-
- friend std::ostream& operator<<(std::ostream& cout, const Token& t)
- {
- if (t.ty == TY_EOF) return cout << "eof";
- if (t.ty == TY_CHAR) return cout << "Char(" << t.c << ")";
- if (t.ty == TY_INT) return cout << "Int(" << t.i << ")";
- if (t.ty == TY_FLOAT) return cout << "Float(" << t.f << ")";
- if (t.ty == TY_IDENTIFIER) return cout << "Id(" << t.str << ")";
- if (t.ty == TY_STRING) return cout << "String(" << t.str << ")";
- if (t.ty == TY_SYMBOL) return cout << "Symbol(" << t.str << ")";
- return cout << "unknown";
- }
-
- private:
- Type ty; //< the type of the token
- union {
- char c; //< data for char tokens
- int i; //< data for int tokens
- float f; //< data for float tokens
- };
- std::string str; //< data for string and identifier tokens
- ParseLocation loc; //< the location the token is from
- };
-
- /*! build full tokenizer that takes list of valid characters and keywords */
- class TokenStream : public Stream<Token>
- {
- public:
-
- /*! shorthands for common sets of characters */
- static const std::string alpha;
- static const std::string ALPHA;
- static const std::string numbers;
- static const std::string separators;
- static const std::string stringChars;
-
- public:
- TokenStream(const Ref<Stream<int> >& cin,
- const std::string& alpha, //< valid characters for identifiers
- const std::string& seps, //< characters that act as separators
- const std::vector<std::string>& symbols = std::vector<std::string>()); //< symbols
- public:
- ParseLocation location() { return cin->loc(); }
- Token next();
- bool trySymbol(const std::string& symbol);
-
- private:
- void skipSeparators();
- bool decDigits(std::string& str);
- bool decDigits1(std::string& str);
- bool trySymbols(Token& token, const ParseLocation& loc);
- bool tryFloat(Token& token, const ParseLocation& loc);
- bool tryInt(Token& token, const ParseLocation& loc);
- bool tryString(Token& token, const ParseLocation& loc);
- bool tryIdentifier(Token& token, const ParseLocation& loc);
-
- Ref<Stream<int> > cin;
- bool isSepMap[256];
- bool isAlphaMap[256];
- bool isStringCharMap[256];
- std::vector<std::string> symbols;
-
- /*! checks if a character is a separator */
- __forceinline bool isSeparator(unsigned int c) const { return c<256 && isSepMap[c]; }
-
- /*! checks if a character is a number */
- __forceinline bool isDigit(unsigned int c) const { return c >= '0' && c <= '9'; }
-
- /*! checks if a character is valid inside a string */
- __forceinline bool isStringChar(unsigned int c) const { return c<256 && isStringCharMap[c]; }
-
- /*! checks if a character is legal for an identifier */
- __forceinline bool isAlpha(unsigned int c) const { return c<256 && isAlphaMap[c]; }
- __forceinline bool isAlphaNum(unsigned int c) const { return isAlpha(c) || isDigit(c); }
- };
-}
diff --git a/thirdparty/embree-aarch64/common/math/AVX2NEON.h b/thirdparty/embree-aarch64/common/math/AVX2NEON.h
deleted file mode 100644
index e8698ac56d..0000000000
--- a/thirdparty/embree-aarch64/common/math/AVX2NEON.h
+++ /dev/null
@@ -1,986 +0,0 @@
-#pragma once
-
-#include "SSE2NEON.h"
-
-
-#define AVX2NEON_ABI static inline __attribute__((always_inline))
-
-
-struct __m256d;
-
-struct __m256 {
- __m128 lo,hi;
- __m256() {}
-};
-
-
-
-
-struct __m256i {
- __m128i lo,hi;
- explicit __m256i(const __m256 a) : lo(__m128i(a.lo)),hi(__m128i(a.hi)) {}
- operator __m256() const {__m256 res; res.lo = __m128(lo);res.hi = __m128(hi); return res;}
- __m256i() {}
-};
-
-
-
-
-struct __m256d {
- float64x2_t lo,hi;
- __m256d() {}
- __m256d(const __m256& a) : lo(float64x2_t(a.lo)),hi(float64x2_t(a.hi)) {}
- __m256d(const __m256i& a) : lo(float64x2_t(a.lo)),hi(float64x2_t(a.hi)) {}
-};
-
-#define UNARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a) {type res;res.lo=basic_func(a.lo);res.hi=basic_func(a.hi);return res;}
-
-
-#define BINARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a,const type& b) {type res;res.lo=basic_func(a.lo,b.lo);res.hi=basic_func(a.hi,b.hi);return res;}
-#define BINARY_AVX_OP_CAST(type,func,basic_func,bdst,bsrc) AVX2NEON_ABI type func(const type& a,const type& b) {type res;res.lo=bdst(basic_func(bsrc(a.lo),bsrc(b.lo)));res.hi=bdst(basic_func(bsrc(a.hi),bsrc(b.hi)));return res;}
-
-#define TERNARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a,const type& b,const type& c) {type res;res.lo=basic_func(a.lo,b.lo,c.lo);res.hi=basic_func(a.hi,b.hi,c.hi);return res;}
-
-
-#define CAST_SIMD_TYPE(to,name,from,basic_dst) AVX2NEON_ABI to name(const from& a) { to res; res.lo = basic_dst(a.lo); res.hi=basic_dst(a.hi); return res;}
-
-
-
-#define _mm_stream_load_si128 _mm_load_si128
-#define _mm256_stream_load_si256 _mm256_load_si256
-
-
-AVX2NEON_ABI
-__m128 _mm_blend_ps (__m128 a, __m128 b, const int imm8)
-{
- __m128 res;
- for (int i=0;i<4;i++)
- {
- if (imm8 & (1<<i))
- {
- res[i] = b[i];
- }
- else{
- res[i] = a[i];
- }
- }
-
- return res;
-}
-
-AVX2NEON_ABI
-__m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
-{
- __m128i res;
- for (int i=0;i<4;i++)
- {
- if (imm8 & (1<<i))
- {
- res[i] = b[i];
- }
- else{
- res[i] = a[i];
- }
- }
- return res;
-}
-
-AVX2NEON_ABI
-__m128 _mm_cmpngt_ps (__m128 a, __m128 b)
-{
- return __m128(vmvnq_s32(__m128i(_mm_cmpgt_ps(a,b))));
-}
-
-
-AVX2NEON_ABI
-__m128i _mm_loadl_epi64 (__m128i const* mem_addr)
-{
- int64x2_t y;
- y[0] = *(int64_t *)mem_addr;
- y[1] = 0;
- return __m128i(y);
-}
-
-AVX2NEON_ABI
-int _mm_movemask_popcnt(__m128 a)
-{
- return __builtin_popcount(_mm_movemask_ps(a));
-}
-
-AVX2NEON_ABI
-__m128 _mm_maskload_ps (float const * mem_addr, __m128i mask)
-{
- __m128 res;
- for (int i=0;i<4;i++) {
- if (mask[i] & 0x80000000) res[i] = mem_addr[i]; else res[i] = 0;
- }
- return res;
-}
-
-AVX2NEON_ABI
-void _mm_maskstore_ps (float * mem_addr, __m128i mask, __m128 a)
-{
- for (int i=0;i<4;i++) {
- if (mask[i] & 0x80000000) mem_addr[i] = a[i];
- }
-}
-
-AVX2NEON_ABI
-void _mm_maskstore_epi32 (int * mem_addr, __m128i mask, __m128i a)
-{
- for (int i=0;i<4;i++) {
- if (mask[i] & 0x80000000) mem_addr[i] = a[i];
- }
-}
-
-AVX2NEON_ABI
-__m128 _mm_fnmsub_ps (__m128 a, __m128 b, __m128 c)
-{
- return vnegq_f32(vfmaq_f32(c,a,b));
-}
-
-#define _mm_fnmsub_ss _mm_fnmsub_ps
-
-AVX2NEON_ABI
-__m128 _mm_fnmadd_ps (__m128 a, __m128 b, __m128 c)
-{
- return vfmsq_f32(c,a,b);
-}
-
-#define _mm_fnmadd_ss _mm_fnmadd_ps
-
-
-AVX2NEON_ABI
-__m128 _mm_broadcast_ss (float const * mem_addr)
-{
- return vdupq_n_f32(*mem_addr);
-}
-
-
-AVX2NEON_ABI
-__m128 _mm_fmsub_ps (__m128 a, __m128 b, __m128 c)
-{
- return vfmaq_f32(vnegq_f32(c),a,b);
-}
-
-#define _mm_fmsub_ss _mm_fmsub_ps
-#define _mm_fmadd_ps _mm_madd_ps
-#define _mm_fmadd_ss _mm_madd_ps
-
-
-
-template<int code>
-AVX2NEON_ABI float32x4_t dpps_neon(const float32x4_t& a,const float32x4_t& b)
-{
- float v;
- v = 0;
- v += (code & 0x10) ? a[0]*b[0] : 0;
- v += (code & 0x20) ? a[1]*b[1] : 0;
- v += (code & 0x40) ? a[2]*b[2] : 0;
- v += (code & 0x80) ? a[3]*b[3] : 0;
- float32x4_t res;
- res[0] = (code & 0x1) ? v : 0;
- res[1] = (code & 0x2) ? v : 0;
- res[2] = (code & 0x4) ? v : 0;
- res[3] = (code & 0x8) ? v : 0;
- return res;
-}
-
-template<>
-inline float32x4_t dpps_neon<0x7f>(const float32x4_t& a,const float32x4_t& b)
-{
- float v;
- float32x4_t m = _mm_mul_ps(a,b);
- m[3] = 0;
- v = vaddvq_f32(m);
- return _mm_set1_ps(v);
-}
-
-template<>
-inline float32x4_t dpps_neon<0xff>(const float32x4_t& a,const float32x4_t& b)
-{
- float v;
- float32x4_t m = _mm_mul_ps(a,b);
- v = vaddvq_f32(m);
- return _mm_set1_ps(v);
-}
-
-#define _mm_dp_ps(a,b,c) dpps_neon<c>((a),(b))
-
-
-
-AVX2NEON_ABI
-__m128 _mm_cmpnge_ps (__m128 a, __m128 b)
-{
- return __m128(vmvnq_s32(__m128i(_mm_cmpge_ps(a,b))));
-}
-
-
-AVX2NEON_ABI
-__m128 _mm_permutevar_ps (__m128 a, __m128i b)
-{
- __m128 x;
- for (int i=0;i<4;i++)
- {
- x[i] = a[b[i&3]];
- }
- return x;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_setzero_si256()
-{
- __m256i res;
- res.lo = res.hi = vdupq_n_s32(0);
- return res;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_setzero_ps()
-{
- __m256 res;
- res.lo = res.hi = vdupq_n_f32(0.0f);
- return res;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_undefined_si256()
-{
- return _mm256_setzero_si256();
-}
-
-AVX2NEON_ABI
-__m256 _mm256_undefined_ps()
-{
- return _mm256_setzero_ps();
-}
-
-CAST_SIMD_TYPE(__m256d,_mm256_castps_pd,__m256,float64x2_t)
-CAST_SIMD_TYPE(__m256i,_mm256_castps_si256,__m256,__m128i)
-CAST_SIMD_TYPE(__m256, _mm256_castsi256_ps, __m256i,__m128)
-CAST_SIMD_TYPE(__m256, _mm256_castpd_ps ,__m256d,__m128)
-CAST_SIMD_TYPE(__m256d, _mm256_castsi256_pd, __m256i,float64x2_t)
-CAST_SIMD_TYPE(__m256i, _mm256_castpd_si256, __m256d,__m128i)
-
-
-
-
-AVX2NEON_ABI
-__m128 _mm256_castps256_ps128 (__m256 a)
-{
- return a.lo;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_castsi128_si256 (__m128i a)
-{
- __m256i res;
- res.lo = a ;
- res.hi = vdupq_n_s32(0);
- return res;
-}
-
-AVX2NEON_ABI
-__m128i _mm256_castsi256_si128 (__m256i a)
-{
- return a.lo;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_castps128_ps256 (__m128 a)
-{
- __m256 res;
- res.lo = a;
- res.hi = vdupq_n_f32(0);
- return res;
-}
-
-
-AVX2NEON_ABI
-__m256 _mm256_broadcast_ss (float const * mem_addr)
-{
- __m256 res;
- res.lo = res.hi = vdupq_n_f32(*mem_addr);
- return res;
-}
-
-
-
-AVX2NEON_ABI
-__m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
-{
- __m128i lo = {e0,e1,e2,e3}, hi = {e4,e5,e6,e7};
- __m256i res;
- res.lo = lo; res.hi = hi;
- return res;
-
-}
-
-AVX2NEON_ABI
-__m256i _mm256_set1_epi32 (int a)
-{
- __m256i res;
- res.lo = res.hi = vdupq_n_s32(a);
- return res;
-}
-
-
-
-
-AVX2NEON_ABI
-int _mm256_movemask_ps(const __m256& v)
-{
- return (_mm_movemask_ps(v.hi) << 4) | _mm_movemask_ps(v.lo);
-}
-
-template<int imm8>
-AVX2NEON_ABI
-__m256 __mm256_permute_ps (const __m256& a)
-{
- __m256 res;
- res.lo = _mm_shuffle_ps(a.lo,a.lo,imm8);
- res.hi = _mm_shuffle_ps(a.hi,a.hi,imm8);
- return res;
-
-}
-
-#define _mm256_permute_ps(a,c) __mm256_permute_ps<c>(a)
-
-
-template<int imm8>
-AVX2NEON_ABI
-__m256 __mm256_shuffle_ps (const __m256 a,const __m256& b)
-{
- __m256 res;
- res.lo = _mm_shuffle_ps(a.lo,b.lo,imm8);
- res.hi = _mm_shuffle_ps(a.hi,b.hi,imm8);
- return res;
-
-}
-
-#define _mm256_shuffle_ps(a,b,c) __mm256_shuffle_ps<c>(a,b)
-
-AVX2NEON_ABI
-__m256i _mm256_set1_epi64x (long long a)
-{
- __m256i res;
- int64x2_t t = vdupq_n_s64(a);
- res.lo = res.hi = __m128i(t);
- return res;
-}
-
-
-AVX2NEON_ABI
-__m256 _mm256_permute2f128_ps (__m256 a, __m256 b, int imm8)
-{
- __m256 res;
- __m128 tmp;
- switch (imm8 & 0x7)
- {
- case 0: tmp = a.lo; break;
- case 1: tmp = a.hi; break;
- case 2: tmp = b.lo; break;
- case 3: tmp = b.hi; break;
- }
- if (imm8 & 0x8)
- tmp = _mm_setzero_ps();
-
-
-
- res.lo = tmp;
- imm8 >>= 4;
-
- switch (imm8 & 0x7)
- {
- case 0: tmp = a.lo; break;
- case 1: tmp = a.hi; break;
- case 2: tmp = b.lo; break;
- case 3: tmp = b.hi; break;
- }
- if (imm8 & 0x8)
- tmp = _mm_setzero_ps();
-
- res.hi = tmp;
-
- return res;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_moveldup_ps (__m256 a)
-{
- __m256 res;
- res.lo[0] = res.lo[1] = a.lo[0];
- res.lo[2] = res.lo[3] = a.lo[2];
- res.hi[0] = res.hi[1] = a.hi[0];
- res.hi[2] = res.hi[3] = a.hi[2];
- return res;
-
-}
-
-AVX2NEON_ABI
-__m256 _mm256_movehdup_ps (__m256 a)
-{
- __m256 res;
- res.lo[0] = res.lo[1] = a.lo[1];
- res.lo[2] = res.lo[3] = a.lo[3];
- res.hi[0] = res.hi[1] = a.hi[1];
- res.hi[2] = res.hi[3] = a.hi[3];
- return res;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
-{
- __m256 res = a;
- if (imm8 & 1) res.hi = b;
- else res.lo = b;
- return res;
-}
-
-
-AVX2NEON_ABI
-__m128 _mm256_extractf128_ps (__m256 a, const int imm8)
-{
- if (imm8 & 1) return a.hi;
- return a.lo;
-}
-
-
-AVX2NEON_ABI
-__m256d _mm256_movedup_pd (__m256d a)
-{
- __m256d res;
- res.hi = a.hi;
- res.lo[0] = res.lo[1] = a.lo[0];
- return res;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_abs_epi32(__m256i a)
-{
- __m256i res;
- res.lo = vabsq_s32(a.lo);
- res.hi = vabsq_s32(a.hi);
- return res;
-}
-
-UNARY_AVX_OP(__m256,_mm256_sqrt_ps,_mm_sqrt_ps)
-UNARY_AVX_OP(__m256,_mm256_rsqrt_ps,_mm_rsqrt_ps)
-UNARY_AVX_OP(__m256,_mm256_rcp_ps,_mm_rcp_ps)
-UNARY_AVX_OP(__m256,_mm256_floor_ps,vrndmq_f32)
-UNARY_AVX_OP(__m256,_mm256_ceil_ps,vrndpq_f32)
-
-
-BINARY_AVX_OP(__m256i,_mm256_add_epi32,_mm_add_epi32)
-BINARY_AVX_OP(__m256i,_mm256_sub_epi32,_mm_sub_epi32)
-BINARY_AVX_OP(__m256i,_mm256_mullo_epi32,_mm_mullo_epi32)
-
-BINARY_AVX_OP(__m256i,_mm256_min_epi32,_mm_min_epi32)
-BINARY_AVX_OP(__m256i,_mm256_max_epi32,_mm_max_epi32)
-BINARY_AVX_OP_CAST(__m256i,_mm256_min_epu32,vminq_u32,__m128i,uint32x4_t)
-BINARY_AVX_OP_CAST(__m256i,_mm256_max_epu32,vmaxq_u32,__m128i,uint32x4_t)
-
-BINARY_AVX_OP(__m256,_mm256_min_ps,_mm_min_ps)
-BINARY_AVX_OP(__m256,_mm256_max_ps,_mm_max_ps)
-
-BINARY_AVX_OP(__m256,_mm256_add_ps,_mm_add_ps)
-BINARY_AVX_OP(__m256,_mm256_mul_ps,_mm_mul_ps)
-BINARY_AVX_OP(__m256,_mm256_sub_ps,_mm_sub_ps)
-BINARY_AVX_OP(__m256,_mm256_div_ps,_mm_div_ps)
-
-BINARY_AVX_OP(__m256,_mm256_and_ps,_mm_and_ps)
-BINARY_AVX_OP(__m256,_mm256_andnot_ps,_mm_andnot_ps)
-BINARY_AVX_OP(__m256,_mm256_or_ps,_mm_or_ps)
-BINARY_AVX_OP(__m256,_mm256_xor_ps,_mm_xor_ps)
-
-BINARY_AVX_OP_CAST(__m256d,_mm256_and_pd,vandq_s64,float64x2_t,int64x2_t)
-BINARY_AVX_OP_CAST(__m256d,_mm256_or_pd,vorrq_s64,float64x2_t,int64x2_t)
-BINARY_AVX_OP_CAST(__m256d,_mm256_xor_pd,veorq_s64,float64x2_t,int64x2_t)
-
-
-
-BINARY_AVX_OP(__m256i,_mm256_and_si256,_mm_and_si128)
-BINARY_AVX_OP(__m256i,_mm256_or_si256,_mm_or_si128)
-BINARY_AVX_OP(__m256i,_mm256_xor_si256,_mm_xor_si128)
-
-
-BINARY_AVX_OP(__m256,_mm256_unpackhi_ps,_mm_unpackhi_ps)
-BINARY_AVX_OP(__m256,_mm256_unpacklo_ps,_mm_unpacklo_ps)
-TERNARY_AVX_OP(__m256,_mm256_blendv_ps,_mm_blendv_ps)
-
-
-TERNARY_AVX_OP(__m256,_mm256_fmadd_ps,_mm_fmadd_ps)
-TERNARY_AVX_OP(__m256,_mm256_fnmadd_ps,_mm_fnmadd_ps)
-TERNARY_AVX_OP(__m256,_mm256_fmsub_ps,_mm_fmsub_ps)
-TERNARY_AVX_OP(__m256,_mm256_fnmsub_ps,_mm_fnmsub_ps)
-
-
-BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi32,_mm_unpackhi_epi32)
-BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi32,_mm_unpacklo_epi32)
-
-
-BINARY_AVX_OP(__m256i,_mm256_cmpeq_epi32,_mm_cmpeq_epi32)
-BINARY_AVX_OP(__m256i,_mm256_cmpgt_epi32,_mm_cmpgt_epi32)
-BINARY_AVX_OP(__m256,_mm256_cmpeq_ps,_mm_cmpeq_ps)
-BINARY_AVX_OP(__m256,_mm256_cmpneq_ps,_mm_cmpneq_ps)
-BINARY_AVX_OP(__m256,_mm256_cmpnlt_ps,_mm_cmpnlt_ps)
-BINARY_AVX_OP(__m256,_mm256_cmpngt_ps,_mm_cmpngt_ps)
-BINARY_AVX_OP(__m256,_mm256_cmpge_ps,_mm_cmpge_ps)
-BINARY_AVX_OP(__m256,_mm256_cmpnge_ps,_mm_cmpnge_ps)
-BINARY_AVX_OP(__m256,_mm256_cmplt_ps,_mm_cmplt_ps)
-BINARY_AVX_OP(__m256,_mm256_cmple_ps,_mm_cmple_ps)
-BINARY_AVX_OP(__m256,_mm256_cmpgt_ps,_mm_cmpgt_ps)
-BINARY_AVX_OP(__m256,_mm256_cmpnle_ps,_mm_cmpnle_ps)
-
-
-AVX2NEON_ABI
-__m256i _mm256_cvtps_epi32 (__m256 a)
-{
- __m256i res;
- res.lo = _mm_cvtps_epi32(a.lo);
- res.hi = _mm_cvtps_epi32(a.hi);
- return res;
-
-}
-
-AVX2NEON_ABI
-__m256i _mm256_cvttps_epi32 (__m256 a)
-{
- __m256i res;
- res.lo = _mm_cvttps_epi32(a.lo);
- res.hi = _mm_cvttps_epi32(a.hi);
- return res;
-
-}
-
-AVX2NEON_ABI
-__m256 _mm256_loadu_ps (float const * mem_addr)
-{
- __m256 res;
- res.lo = *(__m128 *)(mem_addr + 0);
- res.hi = *(__m128 *)(mem_addr + 4);
- return res;
-}
-#define _mm256_load_ps _mm256_loadu_ps
-
-
-AVX2NEON_ABI
-int _mm256_testz_ps (const __m256& a, const __m256& b)
-{
- __m256 t = a;
- if (&a != &b)
- t = _mm256_and_ps(a,b);
-
- __m128i l = vshrq_n_s32(__m128i(t.lo),31);
- __m128i h = vshrq_n_s32(__m128i(t.hi),31);
- return vaddvq_s32(vaddq_s32(l,h)) == 0;
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_set_epi64x (int64_t e3, int64_t e2, int64_t e1, int64_t e0)
-{
- __m256i res;
- int64x2_t t0 = {e0,e1};
- int64x2_t t1 = {e2,e3};
- res.lo = __m128i(t0);
- res.hi = __m128i(t1);
- return res;
-}
-
-AVX2NEON_ABI
-__m256d _mm256_setzero_pd ()
-{
- __m256d res;
- res.lo = res.hi = vdupq_n_f64(0);
- return res;
-}
-
-AVX2NEON_ABI
-int _mm256_movemask_pd (__m256d a)
-{
- int res = 0;
- uint64x2_t x;
- x = uint64x2_t(a.lo);
- res |= (x[0] >> 63) ? 1 : 0;
- res |= (x[0] >> 63) ? 2 : 0;
- x = uint64x2_t(a.hi);
- res |= (x[0] >> 63) ? 4 : 0;
- res |= (x[0] >> 63) ? 8 : 0;
- return res;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
-{
- __m256i res;
- res.lo = __m128i(vceqq_s64(int64x2_t(a.lo),int64x2_t(b.lo)));
- res.hi = __m128i(vceqq_s64(int64x2_t(a.hi),int64x2_t(b.hi)));
- return res;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_cmpeq_pd (__m256d a, __m256d b)
-{
- __m256i res;
- res.lo = __m128i(vceqq_f64(a.lo,b.lo));
- res.hi = __m128i(vceqq_f64(a.hi,b.hi));
- return res;
-}
-
-
-AVX2NEON_ABI
-int _mm256_testz_pd (const __m256d& a, const __m256d& b)
-{
- __m256d t = a;
-
- if (&a != &b)
- t = _mm256_and_pd(a,b);
-
- return _mm256_movemask_pd(t) == 0;
-}
-
-AVX2NEON_ABI
-__m256d _mm256_blendv_pd (__m256d a, __m256d b, __m256d mask)
-{
- __m256d res;
- uint64x2_t t = uint64x2_t(mask.lo);
- res.lo[0] = (t[0] >> 63) ? b.lo[0] : a.lo[0];
- res.lo[1] = (t[1] >> 63) ? b.lo[1] : a.lo[1];
- t = uint64x2_t(mask.hi);
- res.hi[0] = (t[0] >> 63) ? b.hi[0] : a.hi[0];
- res.hi[1] = (t[1] >> 63) ? b.hi[1] : a.hi[1];
- return res;
-}
-
-template<int imm8>
-__m256 __mm256_dp_ps (__m256 a, __m256 b)
-{
- __m256 res;
- res.lo = _mm_dp_ps(a.lo,b.lo,imm8);
- res.hi = _mm_dp_ps(a.hi,b.hi,imm8);
- return res;
-}
-
-#define _mm256_dp_ps(a,b,c) __mm256_dp_ps<c>(a,b)
-
-AVX2NEON_ABI
-double _mm256_permute4x64_pd_select(__m256d a, const int imm8)
-{
- switch (imm8 & 3) {
- case 0:
- return a.lo[0];
- case 1:
- return a.lo[1];
- case 2:
- return a.hi[0];
- case 3:
- return a.hi[1];
- }
- __builtin_unreachable();
- return 0;
-}
-
-AVX2NEON_ABI
-__m256d _mm256_permute4x64_pd (__m256d a, const int imm8)
-{
- __m256d res;
- res.lo[0] = _mm256_permute4x64_pd_select(a,imm8 >> 0);
- res.lo[1] = _mm256_permute4x64_pd_select(a,imm8 >> 2);
- res.hi[0] = _mm256_permute4x64_pd_select(a,imm8 >> 4);
- res.hi[1] = _mm256_permute4x64_pd_select(a,imm8 >> 6);
-
- return res;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
-{
- return __m256i(_mm256_insertf128_ps((__m256)a,(__m128)b,imm8));
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_loadu_si256 (__m256i const * mem_addr)
-{
- __m256i res;
- res.lo = *(__m128i *)((int32_t *)mem_addr + 0);
- res.hi = *(__m128i *)((int32_t *)mem_addr + 4);
- return res;
-}
-
-#define _mm256_load_si256 _mm256_loadu_si256
-
-AVX2NEON_ABI
-void _mm256_storeu_ps (float * mem_addr, __m256 a)
-{
- *(__m128 *)(mem_addr + 0) = a.lo;
- *(__m128 *)(mem_addr + 4) = a.hi;
-
-}
-
-#define _mm256_store_ps _mm256_storeu_ps
-#define _mm256_stream_ps _mm256_storeu_ps
-
-
-AVX2NEON_ABI
-void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
-{
- *(__m128i *)((int *)mem_addr + 0) = a.lo;
- *(__m128i *)((int *)mem_addr + 4) = a.hi;
-
-}
-
-#define _mm256_store_si256 _mm256_storeu_si256
-
-
-
-AVX2NEON_ABI
-__m256 _mm256_maskload_ps (float const * mem_addr, __m256i mask)
-{
- __m256 res;
- res.lo = _mm_maskload_ps(mem_addr,mask.lo);
- res.hi = _mm_maskload_ps(mem_addr + 4,mask.hi);
- return res;
-
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_cvtepu8_epi32 (__m128i a)
-{
- __m256i res;
- uint8x16_t x = uint8x16_t(a);
- for (int i=0;i<4;i++)
- {
- res.lo[i] = x[i];
- res.hi[i] = x[i+4];
- }
- return res;
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_cvtepi8_epi32 (__m128i a)
-{
- __m256i res;
- int8x16_t x = int8x16_t(a);
- for (int i=0;i<4;i++)
- {
- res.lo[i] = x[i];
- res.hi[i] = x[i+4];
- }
- return res;
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_cvtepu16_epi32 (__m128i a)
-{
- __m256i res;
- uint16x8_t x = uint16x8_t(a);
- for (int i=0;i<4;i++)
- {
- res.lo[i] = x[i];
- res.hi[i] = x[i+4];
- }
- return res;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_cvtepi16_epi32 (__m128i a)
-{
- __m256i res;
- int16x8_t x = int16x8_t(a);
- for (int i=0;i<4;i++)
- {
- res.lo[i] = x[i];
- res.hi[i] = x[i+4];
- }
- return res;
-}
-
-
-
-AVX2NEON_ABI
-void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
-{
- _mm_maskstore_epi32(mem_addr,mask.lo,a.lo);
- _mm_maskstore_epi32(mem_addr + 4,mask.hi,a.hi);
-}
-
-AVX2NEON_ABI
-__m256i _mm256_slli_epi32 (__m256i a, int imm8)
-{
- __m256i res;
- res.lo = _mm_slli_epi32(a.lo,imm8);
- res.hi = _mm_slli_epi32(a.hi,imm8);
- return res;
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_srli_epi32 (__m256i a, int imm8)
-{
- __m256i res;
- res.lo = _mm_srli_epi32(a.lo,imm8);
- res.hi = _mm_srli_epi32(a.hi,imm8);
- return res;
-}
-
-AVX2NEON_ABI
-__m256i _mm256_srai_epi32 (__m256i a, int imm8)
-{
- __m256i res;
- res.lo = _mm_srai_epi32(a.lo,imm8);
- res.hi = _mm_srai_epi32(a.hi,imm8);
- return res;
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
-{
- __m256i res;
- res.lo = vshlq_s32(a.lo,count.lo);
- res.hi = vshlq_s32(a.hi,count.hi);
- return res;
-
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_srav_epi32 (__m256i a, __m256i count)
-{
- __m256i res;
- res.lo = vshlq_s32(a.lo,vnegq_s32(count.lo));
- res.hi = vshlq_s32(a.hi,vnegq_s32(count.hi));
- return res;
-
-}
-
-AVX2NEON_ABI
-__m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
-{
- __m256i res;
- res.lo = __m128i(vshlq_u32(uint32x4_t(a.lo),vnegq_s32(count.lo)));
- res.hi = __m128i(vshlq_u32(uint32x4_t(a.hi),vnegq_s32(count.hi)));
- return res;
-
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8)
-{
- return __m256i(_mm256_permute2f128_ps(__m256(a),__m256(b),imm8));
-}
-
-
-AVX2NEON_ABI
-__m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
-{
- if (imm8 & 1) return a.hi;
- return a.lo;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_set1_ps(float x)
-{
- __m256 res;
- res.lo = res.hi = vdupq_n_f32(x);
- return res;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_set_ps (float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0)
-{
- __m256 res;
- res.lo = _mm_set_ps(e3,e2,e1,e0);
- res.hi = _mm_set_ps(e7,e6,e5,e4);
- return res;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_broadcast_ps (__m128 const * mem_addr)
-{
- __m256 res;
- res.lo = res.hi = *mem_addr;
- return res;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_cvtepi32_ps (__m256i a)
-{
- __m256 res;
- res.lo = _mm_cvtepi32_ps(a.lo);
- res.hi = _mm_cvtepi32_ps(a.hi);
- return res;
-}
-AVX2NEON_ABI
-void _mm256_maskstore_ps (float * mem_addr, __m256i mask, __m256 a)
-{
- for (int i=0;i<4;i++) {
- if (mask.lo[i] & 0x80000000) mem_addr[i] = a.lo[i];
- if (mask.hi[i] & 0x80000000) mem_addr[i+4] = a.hi[i];
- }
-}
-
-AVX2NEON_ABI
-__m256d _mm256_andnot_pd (__m256d a, __m256d b)
-{
- __m256d res;
- res.lo = float64x2_t(_mm_andnot_ps(__m128(a.lo),__m128(b.lo)));
- res.hi = float64x2_t(_mm_andnot_ps(__m128(a.hi),__m128(b.hi)));
- return res;
-}
-
-AVX2NEON_ABI
-__m256 _mm256_blend_ps (__m256 a, __m256 b, const int imm8)
-{
- __m256 res;
- res.lo = _mm_blend_ps(a.lo,b.lo,imm8 & 0xf);
- res.hi = _mm_blend_ps(a.hi,b.hi,imm8 >> 4);
- return res;
-
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
-{
- __m256i res;
- res.lo = _mm_blend_epi32(a.lo,b.lo,imm8 & 0xf);
- res.hi = _mm_blend_epi32(a.hi,b.hi,imm8 >> 4);
- return res;
-
-}
-
-AVX2NEON_ABI
-__m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
-{
- __m256i res;
- for (int i=0;i<4;i++)
- {
- res.lo[i] = *(int *)((char *) base_addr + (vindex.lo[i]*scale));
- res.hi[i] = *(int *)((char *) base_addr + (vindex.hi[i]*scale));
- }
- return res;
-}
-
-
-AVX2NEON_ABI
-__m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
-{
- __m256i res = _mm256_setzero_si256();
- for (int i=0;i<4;i++)
- {
- if (mask.lo[i] >> 31) res.lo[i] = *(int *)((char *) base_addr + (vindex.lo[i]*scale));
- if (mask.hi[i] >> 31) res.hi[i] = *(int *)((char *) base_addr + (vindex.hi[i]*scale));
- }
-
- return res;
-
-}
-
-
diff --git a/thirdparty/embree-aarch64/common/math/SSE2NEON.h b/thirdparty/embree-aarch64/common/math/SSE2NEON.h
deleted file mode 100644
index 2013151d31..0000000000
--- a/thirdparty/embree-aarch64/common/math/SSE2NEON.h
+++ /dev/null
@@ -1,1753 +0,0 @@
-#ifndef SSE2NEON_H
-#define SSE2NEON_H
-
-// This header file provides a simple API translation layer
-// between SSE intrinsics to their corresponding ARM NEON versions
-//
-// This header file does not (yet) translate *all* of the SSE intrinsics.
-// Since this is in support of a specific porting effort, I have only
-// included the intrinsics I needed to get my port to work.
-//
-// Questions/Comments/Feedback send to: jratcliffscarab@gmail.com
-//
-// If you want to improve or add to this project, send me an
-// email and I will probably approve your access to the depot.
-//
-// Project is located here:
-//
-// https://github.com/jratcliff63367/sse2neon
-//
-// Show your appreciation for open source by sending me a bitcoin tip to the following
-// address.
-//
-// TipJar: 1PzgWDSyq4pmdAXRH8SPUtta4SWGrt4B1p :
-// https://blockchain.info/address/1PzgWDSyq4pmdAXRH8SPUtta4SWGrt4B1p
-//
-//
-// Contributors to this project are:
-//
-// John W. Ratcliff : jratcliffscarab@gmail.com
-// Brandon Rowlett : browlett@nvidia.com
-// Ken Fast : kfast@gdeb.com
-// Eric van Beurden : evanbeurden@nvidia.com
-//
-//
-// *********************************************************************************************************************
-// Release notes for January 20, 2017 version:
-//
-// The unit tests have been refactored. They no longer assert on an error, instead they return a pass/fail condition
-// The unit-tests now test 10,000 random float and int values against each intrinsic.
-//
-// SSE2NEON now supports 95 SSE intrinsics. 39 of them have formal unit tests which have been implemented and
-// fully tested on NEON/ARM. The remaining 56 still need unit tests implemented.
-//
-// A struct is now defined in this header file called 'SIMDVec' which can be used by applications which
-// attempt to access the contents of an _m128 struct directly. It is important to note that accessing the __m128
-// struct directly is bad coding practice by Microsoft: @see: https://msdn.microsoft.com/en-us/library/ayeb3ayc.aspx
-//
-// However, some legacy source code may try to access the contents of an __m128 struct directly so the developer
-// can use the SIMDVec as an alias for it. Any casting must be done manually by the developer, as you cannot
-// cast or otherwise alias the base NEON data type for intrinsic operations.
-//
-// A bug was found with the _mm_shuffle_ps intrinsic. If the shuffle permutation was not one of the ones with
-// a custom/unique implementation causing it to fall through to the default shuffle implementation it was failing
-// to return the correct value. This is now fixed.
-//
-// A bug was found with the _mm_cvtps_epi32 intrinsic. This converts floating point values to integers.
-// It was not honoring the correct rounding mode. In SSE the default rounding mode when converting from float to int
-// is to use 'round to even' otherwise known as 'bankers rounding'. ARMv7 did not support this feature but ARMv8 does.
-// As it stands today, this header file assumes ARMv8. If you are trying to target really old ARM devices, you may get
-// a build error.
-//
-// Support for a number of new intrinsics was added, however, none of them yet have unit-tests to 100% confirm they are
-// producing the correct results on NEON. These unit tests will be added as soon as possible.
-//
-// Here is the list of new instrinsics which have been added:
-//
-// _mm_cvtss_f32 : extracts the lower order floating point value from the parameter
-// _mm_add_ss : adds the scalar single - precision floating point values of a and b
-// _mm_div_ps : Divides the four single - precision, floating - point values of a and b.
-// _mm_div_ss : Divides the scalar single - precision floating point value of a by b.
-// _mm_sqrt_ss : Computes the approximation of the square root of the scalar single - precision floating point value of in.
-// _mm_rsqrt_ps : Computes the approximations of the reciprocal square roots of the four single - precision floating point values of in.
-// _mm_comilt_ss : Compares the lower single - precision floating point scalar values of a and b using a less than operation
-// _mm_comigt_ss : Compares the lower single - precision floating point scalar values of a and b using a greater than operation.
-// _mm_comile_ss : Compares the lower single - precision floating point scalar values of a and b using a less than or equal operation.
-// _mm_comige_ss : Compares the lower single - precision floating point scalar values of a and b using a greater than or equal operation.
-// _mm_comieq_ss : Compares the lower single - precision floating point scalar values of a and b using an equality operation.
-// _mm_comineq_s : Compares the lower single - precision floating point scalar values of a and b using an inequality operation
-// _mm_unpackhi_epi8 : Interleaves the upper 8 signed or unsigned 8 - bit integers in a with the upper 8 signed or unsigned 8 - bit integers in b.
-// _mm_unpackhi_epi16: Interleaves the upper 4 signed or unsigned 16 - bit integers in a with the upper 4 signed or unsigned 16 - bit integers in b.
-//
-// *********************************************************************************************************************
-/*
-** The MIT license:
-**
-** Permission is hereby granted, free of charge, to any person obtaining a copy
-** of this software and associated documentation files (the "Software"), to deal
-** in the Software without restriction, including without limitation the rights
-** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-** copies of the Software, and to permit persons to whom the Software is furnished
-** to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be included in all
-** copies or substantial portions of the Software.
-
-** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#pragma once
-
-#define GCC 1
-#define ENABLE_CPP_VERSION 0
-
-// enable precise emulation of _mm_min_ps and _mm_max_ps?
-// This would slow down the computation a bit, but gives consistent result with x86 SSE2.
-// (e.g. would solve a hole or NaN pixel in the rendering result)
-#define USE_PRECISE_MINMAX_IMPLEMENTATION (1)
-
-#if GCC
-#define FORCE_INLINE inline __attribute__((always_inline))
-#define ALIGN_STRUCT(x) __attribute__((aligned(x)))
-#else
-#define FORCE_INLINE inline
-#define ALIGN_STRUCT(x) __declspec(align(x))
-#endif
-
-#include <stdint.h>
-#include "arm_neon.h"
-#if defined(__aarch64__)
-#include "constants.h"
-#endif
-
-
-#if !defined(__has_builtin)
-#define __has_builtin(x) (0)
-#endif
-
-/*******************************************************/
-/* MACRO for shuffle parameter for _mm_shuffle_ps(). */
-/* Argument fp3 is a digit[0123] that represents the fp*/
-/* from argument "b" of mm_shuffle_ps that will be */
-/* placed in fp3 of result. fp2 is the same for fp2 in */
-/* result. fp1 is a digit[0123] that represents the fp */
-/* from argument "a" of mm_shuffle_ps that will be */
-/* places in fp1 of result. fp0 is the same for fp0 of */
-/* result */
-/*******************************************************/
-#if defined(__aarch64__)
-#define _MN_SHUFFLE(fp3,fp2,fp1,fp0) ( (uint8x16_t){ (((fp3)*4)+0), (((fp3)*4)+1), (((fp3)*4)+2), (((fp3)*4)+3), (((fp2)*4)+0), (((fp2)*4)+1), (((fp2)*4)+2), (((fp2)*4)+3), (((fp1)*4)+0), (((fp1)*4)+1), (((fp1)*4)+2), (((fp1)*4)+3), (((fp0)*4)+0), (((fp0)*4)+1), (((fp0)*4)+2), (((fp0)*4)+3) } )
-#define _MF_SHUFFLE(fp3,fp2,fp1,fp0) ( (uint8x16_t){ (((fp3)*4)+0), (((fp3)*4)+1), (((fp3)*4)+2), (((fp3)*4)+3), (((fp2)*4)+0), (((fp2)*4)+1), (((fp2)*4)+2), (((fp2)*4)+3), (((fp1)*4)+16+0), (((fp1)*4)+16+1), (((fp1)*4)+16+2), (((fp1)*4)+16+3), (((fp0)*4)+16+0), (((fp0)*4)+16+1), (((fp0)*4)+16+2), (((fp0)*4)+16+3) } )
-#endif
-
-#define _MM_SHUFFLE(fp3,fp2,fp1,fp0) (((fp3) << 6) | ((fp2) << 4) | \
- ((fp1) << 2) | ((fp0)))
-
-typedef float32x4_t __m128;
-typedef int32x4_t __m128i;
-
-// union intended to allow direct access to an __m128 variable using the names that the MSVC
-// compiler provides. This union should really only be used when trying to access the members
-// of the vector as integer values. GCC/clang allow native access to the float members through
-// a simple array access operator (in C since 4.6, in C++ since 4.8).
-//
-// Ideally direct accesses to SIMD vectors should not be used since it can cause a performance
-// hit. If it really is needed however, the original __m128 variable can be aliased with a
-// pointer to this union and used to access individual components. The use of this union should
-// be hidden behind a macro that is used throughout the codebase to access the members instead
-// of always declaring this type of variable.
-typedef union ALIGN_STRUCT(16) SIMDVec
-{
- float m128_f32[4]; // as floats - do not to use this. Added for convenience.
- int8_t m128_i8[16]; // as signed 8-bit integers.
- int16_t m128_i16[8]; // as signed 16-bit integers.
- int32_t m128_i32[4]; // as signed 32-bit integers.
- int64_t m128_i64[2]; // as signed 64-bit integers.
- uint8_t m128_u8[16]; // as unsigned 8-bit integers.
- uint16_t m128_u16[8]; // as unsigned 16-bit integers.
- uint32_t m128_u32[4]; // as unsigned 32-bit integers.
- uint64_t m128_u64[2]; // as unsigned 64-bit integers.
- double m128_f64[2]; // as signed double
-} SIMDVec;
-
-// ******************************************
-// CPU stuff
-// ******************************************
-
-typedef SIMDVec __m128d;
-
-#include <stdlib.h>
-
-#ifndef _MM_MASK_MASK
-#define _MM_MASK_MASK 0x1f80
-#define _MM_MASK_DIV_ZERO 0x200
-#define _MM_FLUSH_ZERO_ON 0x8000
-#define _MM_DENORMALS_ZERO_ON 0x40
-#define _MM_MASK_DENORM 0x100
-#endif
-#define _MM_SET_EXCEPTION_MASK(x)
-#define _MM_SET_FLUSH_ZERO_MODE(x)
-#define _MM_SET_DENORMALS_ZERO_MODE(x)
-
-FORCE_INLINE void _mm_pause()
-{
-}
-
-FORCE_INLINE void _mm_mfence()
-{
- __sync_synchronize();
-}
-
-#define _MM_HINT_T0 3
-#define _MM_HINT_T1 2
-#define _MM_HINT_T2 1
-#define _MM_HINT_NTA 0
-
-FORCE_INLINE void _mm_prefetch(const void* ptr, unsigned int level)
-{
- __builtin_prefetch(ptr);
-
-}
-
-FORCE_INLINE void* _mm_malloc(int size, int align)
-{
- void *ptr;
- // align must be multiple of sizeof(void *) for posix_memalign.
- if (align < sizeof(void *)) {
- align = sizeof(void *);
- }
-
- if ((align % sizeof(void *)) != 0) {
- // fallback to malloc
- ptr = malloc(size);
- } else {
- if (posix_memalign(&ptr, align, size)) {
- return 0;
- }
- }
-
- return ptr;
-}
-
-FORCE_INLINE void _mm_free(void* ptr)
-{
- free(ptr);
-}
-
-FORCE_INLINE int _mm_getcsr()
-{
- return 0;
-}
-
-FORCE_INLINE void _mm_setcsr(int val)
-{
- return;
-}
-
-// ******************************************
-// Set/get methods
-// ******************************************
-
-// extracts the lower order floating point value from the parameter : https://msdn.microsoft.com/en-us/library/bb514059%28v=vs.120%29.aspx?f=255&MSPPError=-2147217396
-#if defined(__aarch64__)
-FORCE_INLINE float _mm_cvtss_f32(const __m128& x)
-{
- return x[0];
-}
-#else
-FORCE_INLINE float _mm_cvtss_f32(__m128 a)
-{
- return vgetq_lane_f32(a, 0);
-}
-#endif
-
-// Sets the 128-bit value to zero https://msdn.microsoft.com/en-us/library/vstudio/ys7dw0kh(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_setzero_si128()
-{
- return vdupq_n_s32(0);
-}
-
-// Clears the four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/tk1t2tbz(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_setzero_ps(void)
-{
- return vdupq_n_f32(0);
-}
-
-// Sets the four single-precision, floating-point values to w. https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_set1_ps(float _w)
-{
- return vdupq_n_f32(_w);
-}
-
-// Sets the four single-precision, floating-point values to w. https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_set_ps1(float _w)
-{
- return vdupq_n_f32(_w);
-}
-
-// Sets the four single-precision, floating-point values to the four inputs. https://msdn.microsoft.com/en-us/library/vstudio/afh0zf75(v=vs.100).aspx
-#if defined(__aarch64__)
-FORCE_INLINE __m128 _mm_set_ps(const float w, const float z, const float y, const float x)
-{
- float32x4_t t = { x, y, z, w };
- return t;
-}
-
-// Sets the four single-precision, floating-point values to the four inputs in reverse order. https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_setr_ps(const float w, const float z , const float y , const float x )
-{
- float32x4_t t = { w, z, y, x };
- return t;
-}
-#else
-FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x)
-{
- float __attribute__((aligned(16))) data[4] = { x, y, z, w };
- return vld1q_f32(data);
-}
-
-// Sets the four single-precision, floating-point values to the four inputs in reverse order. https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_setr_ps(float w, float z , float y , float x )
-{
- float __attribute__ ((aligned (16))) data[4] = { w, z, y, x };
- return vld1q_f32(data);
-}
-#endif
-
-// Sets the 4 signed 32-bit integer values to i. https://msdn.microsoft.com/en-us/library/vstudio/h4xscxat(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_set1_epi32(int _i)
-{
- return vdupq_n_s32(_i);
-}
-
-//Set the first lane to of 4 signed single-position, floating-point number to w
-#if defined(__aarch64__)
-FORCE_INLINE __m128 _mm_set_ss(float _w)
-{
- float32x4_t res = {_w, 0, 0, 0};
- return res;
-}
-
-// Sets the 4 signed 32-bit integer values. https://msdn.microsoft.com/en-us/library/vstudio/019beekt(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0)
-{
- int32x4_t t = {i0,i1,i2,i3};
- return t;
-}
-#else
-FORCE_INLINE __m128 _mm_set_ss(float _w)
-{
- __m128 val = _mm_setzero_ps();
- return vsetq_lane_f32(_w, val, 0);
-}
-
-// Sets the 4 signed 32-bit integer values. https://msdn.microsoft.com/en-us/library/vstudio/019beekt(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0)
-{
- int32_t __attribute__((aligned(16))) data[4] = { i0, i1, i2, i3 };
- return vld1q_s32(data);
-}
-#endif
-
-// Stores four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx
-FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
-{
- vst1q_f32(p, a);
-}
-
-// Stores four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx
-FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a)
-{
- vst1q_f32(p, a);
-}
-
-FORCE_INLINE void _mm_storeu_si128(__m128i *p, __m128i a)
-{
- vst1q_s32((int32_t*) p,a);
-}
-
-// Stores four 32-bit integer values as (as a __m128i value) at the address p. https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
-FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a )
-{
- vst1q_s32((int32_t*) p,a);
-}
-
-// Stores the lower single - precision, floating - point value. https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx
-FORCE_INLINE void _mm_store_ss(float *p, __m128 a)
-{
- vst1q_lane_f32(p, a, 0);
-}
-
-// Reads the lower 64 bits of b and stores them into the lower 64 bits of a. https://msdn.microsoft.com/en-us/library/hhwf428f%28v=vs.90%29.aspx
-FORCE_INLINE void _mm_storel_epi64(__m128i* a, __m128i b)
-{
- *a = (__m128i)vsetq_lane_s64((int64_t)vget_low_s32(b), *(int64x2_t*)a, 0);
-}
-
-// Loads a single single-precision, floating-point value, copying it into all four words https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_load1_ps(const float * p)
-{
- return vld1q_dup_f32(p);
-}
-
-// Loads four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_load_ps(const float * p)
-{
- return vld1q_f32(p);
-}
-
-// Loads four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx
-FORCE_INLINE __m128 _mm_loadu_ps(const float * p)
-{
- // for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are equivalent for neon
- return vld1q_f32(p);
-}
-
-// Loads an single - precision, floating - point value into the low word and clears the upper three words. https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx
-FORCE_INLINE __m128 _mm_load_ss(const float * p)
-{
- __m128 result = vdupq_n_f32(0);
- return vsetq_lane_f32(*p, result, 0);
-}
-
-FORCE_INLINE __m128i _mm_loadu_si128(__m128i *p)
-{
- return (__m128i)vld1q_s32((const int32_t*) p);
-}
-
-
-// ******************************************
-// Logic/Binary operations
-// ******************************************
-
-// Compares for inequality. https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b)
-{
- return (__m128)vmvnq_s32((__m128i)vceqq_f32(a, b));
-}
-
-// Computes the bitwise AND-NOT of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b)
-{
- return (__m128)vbicq_s32((__m128i)b, (__m128i)a); // *NOTE* argument swap
-}
-
-// Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the 128-bit value in a. https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b)
-{
- return (__m128i)vbicq_s32(b, a); // *NOTE* argument swap
-}
-
-// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b)
-{
- return (__m128i)vandq_s32(a, b);
-}
-
-// Computes the bitwise AND of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b)
-{
- return (__m128)vandq_s32((__m128i)a, (__m128i)b);
-}
-
-// Computes the bitwise OR of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b)
-{
- return (__m128)vorrq_s32((__m128i)a, (__m128i)b);
-}
-
-// Computes bitwise EXOR (exclusive-or) of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b)
-{
- return (__m128)veorq_s32((__m128i)a, (__m128i)b);
-}
-
-// Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_or_si128(__m128i a, __m128i b)
-{
- return (__m128i)vorrq_s32(a, b);
-}
-
-// Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b)
-{
- return veorq_s32(a, b);
-}
-
-// NEON does not provide this method
-// Creates a 4-bit mask from the most significant bits of the four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/4490ys29(v=vs.100).aspx
-FORCE_INLINE int _mm_movemask_ps(__m128 a)
-{
-#if ENABLE_CPP_VERSION // I am not yet convinced that the NEON version is faster than the C version of this
- uint32x4_t &ia = *(uint32x4_t *)&a;
- return (ia[0] >> 31) | ((ia[1] >> 30) & 2) | ((ia[2] >> 29) & 4) | ((ia[3] >> 28) & 8);
-#else
-
-#if defined(__aarch64__)
- uint32x4_t t2 = vandq_u32(vreinterpretq_u32_f32(a), embree::movemask_mask);
- return vaddvq_u32(t2);
-#else
- static const uint32x4_t movemask = { 1, 2, 4, 8 };
- static const uint32x4_t highbit = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
- uint32x4_t t0 = vreinterpretq_u32_f32(a);
- uint32x4_t t1 = vtstq_u32(t0, highbit);
- uint32x4_t t2 = vandq_u32(t1, movemask);
- uint32x2_t t3 = vorr_u32(vget_low_u32(t2), vget_high_u32(t2));
- return vget_lane_u32(t3, 0) | vget_lane_u32(t3, 1);
-#endif
-
-#endif
-}
-
-#if defined(__aarch64__)
-FORCE_INLINE int _mm_movemask_popcnt_ps(__m128 a)
-{
- uint32x4_t t2 = vandq_u32(vreinterpretq_u32_f32(a), embree::movemask_mask);
- t2 = vreinterpretq_u32_u8(vcntq_u8(vreinterpretq_u8_u32(t2)));
- return vaddvq_u32(t2);
-
-}
-#endif
-
-// Takes the upper 64 bits of a and places it in the low end of the result
-// Takes the lower 64 bits of b and places it into the high end of the result.
-FORCE_INLINE __m128 _mm_shuffle_ps_1032(__m128 a, __m128 b)
-{
- return vcombine_f32(vget_high_f32(a), vget_low_f32(b));
-}
-
-// takes the lower two 32-bit values from a and swaps them and places in high end of result
-// takes the higher two 32 bit values from b and swaps them and places in low end of result.
-FORCE_INLINE __m128 _mm_shuffle_ps_2301(__m128 a, __m128 b)
-{
- return vcombine_f32(vrev64_f32(vget_low_f32(a)), vrev64_f32(vget_high_f32(b)));
-}
-
-// keeps the low 64 bits of b in the low and puts the high 64 bits of a in the high
-FORCE_INLINE __m128 _mm_shuffle_ps_3210(__m128 a, __m128 b)
-{
- return vcombine_f32(vget_low_f32(a), vget_high_f32(b));
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_0011(__m128 a, __m128 b)
-{
- return vcombine_f32(vdup_n_f32(vgetq_lane_f32(a, 1)), vdup_n_f32(vgetq_lane_f32(b, 0)));
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_0022(__m128 a, __m128 b)
-{
- return vcombine_f32(vdup_n_f32(vgetq_lane_f32(a, 2)), vdup_n_f32(vgetq_lane_f32(b, 0)));
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_2200(__m128 a, __m128 b)
-{
- return vcombine_f32(vdup_n_f32(vgetq_lane_f32(a, 0)), vdup_n_f32(vgetq_lane_f32(b, 2)));
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_3202(__m128 a, __m128 b)
-{
- float32_t a0 = vgetq_lane_f32(a, 0);
- float32_t a2 = vgetq_lane_f32(a, 2);
- float32x2_t aVal = vdup_n_f32(a2);
- aVal = vset_lane_f32(a0, aVal, 1);
- return vcombine_f32(aVal, vget_high_f32(b));
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_1133(__m128 a, __m128 b)
-{
- return vcombine_f32(vdup_n_f32(vgetq_lane_f32(a, 3)), vdup_n_f32(vgetq_lane_f32(b, 1)));
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_2010(__m128 a, __m128 b)
-{
- float32_t b0 = vgetq_lane_f32(b, 0);
- float32_t b2 = vgetq_lane_f32(b, 2);
- float32x2_t bVal = vdup_n_f32(b0);
- bVal = vset_lane_f32(b2, bVal, 1);
- return vcombine_f32(vget_low_f32(a), bVal);
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_2001(__m128 a, __m128 b)
-{
- float32_t b0 = vgetq_lane_f32(b, 0);
- float32_t b2 = vgetq_lane_f32(b, 2);
- float32x2_t bVal = vdup_n_f32(b0);
- bVal = vset_lane_f32(b2, bVal, 1);
- return vcombine_f32(vrev64_f32(vget_low_f32(a)), bVal);
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b)
-{
- float32_t b0 = vgetq_lane_f32(b, 0);
- float32_t b2 = vgetq_lane_f32(b, 2);
- float32x2_t bVal = vdup_n_f32(b0);
- bVal = vset_lane_f32(b2, bVal, 1);
- return vcombine_f32(vget_high_f32(a), bVal);
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_0321(__m128 a, __m128 b)
-{
- float32x2_t a21 = vget_high_f32(vextq_f32(a, a, 3));
- float32x2_t b03 = vget_low_f32(vextq_f32(b, b, 3));
- return vcombine_f32(a21, b03);
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_2103(__m128 a, __m128 b)
-{
- float32x2_t a03 = vget_low_f32(vextq_f32(a, a, 3));
- float32x2_t b21 = vget_high_f32(vextq_f32(b, b, 3));
- return vcombine_f32(a03, b21);
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_1010(__m128 a, __m128 b)
-{
- float32x2_t a10 = vget_low_f32(a);
- float32x2_t b10 = vget_low_f32(b);
- return vcombine_f32(a10, b10);
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_1001(__m128 a, __m128 b)
-{
- float32x2_t a01 = vrev64_f32(vget_low_f32(a));
- float32x2_t b10 = vget_low_f32(b);
- return vcombine_f32(a01, b10);
-}
-
-FORCE_INLINE __m128 _mm_shuffle_ps_0101(__m128 a, __m128 b)
-{
- float32x2_t a01 = vrev64_f32(vget_low_f32(a));
- float32x2_t b01 = vrev64_f32(vget_low_f32(b));
- return vcombine_f32(a01, b01);
-}
-
-// NEON does not support a general purpose permute intrinsic
-// Currently I am not sure whether the C implementation is faster or slower than the NEON version.
-// Note, this has to be expanded as a template because the shuffle value must be an immediate value.
-// The same is true on SSE as well.
-// Selects four specific single-precision, floating-point values from a and b, based on the mask i. https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx
-template <int i>
-FORCE_INLINE __m128 _mm_shuffle_ps_default(const __m128& a, const __m128& b)
-{
-#if ENABLE_CPP_VERSION // I am not convinced that the NEON version is faster than the C version yet.
- __m128 ret;
- ret[0] = a[i & 0x3];
- ret[1] = a[(i >> 2) & 0x3];
- ret[2] = b[(i >> 4) & 0x03];
- ret[3] = b[(i >> 6) & 0x03];
- return ret;
-#else
-# if __has_builtin(__builtin_shufflevector)
- return __builtin_shufflevector( \
- a, b, (i) & (0x3), ((i) >> 2) & 0x3,
- (((i) >> 4) & 0x3) + 4, (((i) >> 6) & 0x3) + 4);
-# else
- const int i0 = (i >> 0)&0x3;
- const int i1 = (i >> 2)&0x3;
- const int i2 = (i >> 4)&0x3;
- const int i3 = (i >> 6)&0x3;
-
- if (&a == &b)
- {
- if (i0 == i1 && i0 == i2 && i0 == i3)
- {
- return (float32x4_t)vdupq_laneq_f32(a,i0);
- }
- static const uint8_t tbl[16] = {
- (i0*4) + 0,(i0*4) + 1,(i0*4) + 2,(i0*4) + 3,
- (i1*4) + 0,(i1*4) + 1,(i1*4) + 2,(i1*4) + 3,
- (i2*4) + 0,(i2*4) + 1,(i2*4) + 2,(i2*4) + 3,
- (i3*4) + 0,(i3*4) + 1,(i3*4) + 2,(i3*4) + 3
- };
-
- return (float32x4_t)vqtbl1q_s8(int8x16_t(b),*(uint8x16_t *)tbl);
-
- }
- else
- {
-
- static const uint8_t tbl[16] = {
- (i0*4) + 0,(i0*4) + 1,(i0*4) + 2,(i0*4) + 3,
- (i1*4) + 0,(i1*4) + 1,(i1*4) + 2,(i1*4) + 3,
- (i2*4) + 0 + 16,(i2*4) + 1 + 16,(i2*4) + 2 + 16,(i2*4) + 3 + 16,
- (i3*4) + 0 + 16,(i3*4) + 1 + 16,(i3*4) + 2 + 16,(i3*4) + 3 + 16
- };
-
- return float32x4_t(vqtbl2q_s8((int8x16x2_t){int8x16_t(a),int8x16_t(b)},*(uint8x16_t *)tbl));
- }
-# endif //builtin(shufflevector)
-#endif
-}
-
-template <int i >
-FORCE_INLINE __m128 _mm_shuffle_ps_function(const __m128& a, const __m128& b)
-{
- switch (i)
- {
- case _MM_SHUFFLE(1, 0, 3, 2):
- return _mm_shuffle_ps_1032(a, b);
- break;
- case _MM_SHUFFLE(2, 3, 0, 1):
- return _mm_shuffle_ps_2301(a, b);
- break;
- case _MM_SHUFFLE(3, 2, 1, 0):
- return _mm_shuffle_ps_3210(a, b);
- break;
- case _MM_SHUFFLE(0, 0, 1, 1):
- return _mm_shuffle_ps_0011(a, b);
- break;
- case _MM_SHUFFLE(0, 0, 2, 2):
- return _mm_shuffle_ps_0022(a, b);
- break;
- case _MM_SHUFFLE(2, 2, 0, 0):
- return _mm_shuffle_ps_2200(a, b);
- break;
- case _MM_SHUFFLE(3, 2, 0, 2):
- return _mm_shuffle_ps_3202(a, b);
- break;
- case _MM_SHUFFLE(1, 1, 3, 3):
- return _mm_shuffle_ps_1133(a, b);
- break;
- case _MM_SHUFFLE(2, 0, 1, 0):
- return _mm_shuffle_ps_2010(a, b);
- break;
- case _MM_SHUFFLE(2, 0, 0, 1):
- return _mm_shuffle_ps_2001(a, b);
- break;
- case _MM_SHUFFLE(2, 0, 3, 2):
- return _mm_shuffle_ps_2032(a, b);
- break;
- case _MM_SHUFFLE(0, 3, 2, 1):
- return _mm_shuffle_ps_0321(a, b);
- break;
- case _MM_SHUFFLE(2, 1, 0, 3):
- return _mm_shuffle_ps_2103(a, b);
- break;
- case _MM_SHUFFLE(1, 0, 1, 0):
- return _mm_shuffle_ps_1010(a, b);
- break;
- case _MM_SHUFFLE(1, 0, 0, 1):
- return _mm_shuffle_ps_1001(a, b);
- break;
- case _MM_SHUFFLE(0, 1, 0, 1):
- return _mm_shuffle_ps_0101(a, b);
- break;
- }
- return _mm_shuffle_ps_default<i>(a, b);
-}
-
-# if __has_builtin(__builtin_shufflevector)
-#define _mm_shuffle_ps(a,b,i) _mm_shuffle_ps_default<i>(a,b)
-# else
-#define _mm_shuffle_ps(a,b,i) _mm_shuffle_ps_function<i>(a,b)
-#endif
-
-// Takes the upper 64 bits of a and places it in the low end of the result
-// Takes the lower 64 bits of b and places it into the high end of the result.
-FORCE_INLINE __m128i _mm_shuffle_epi_1032(__m128i a, __m128i b)
-{
- return vcombine_s32(vget_high_s32(a), vget_low_s32(b));
-}
-
-// takes the lower two 32-bit values from a and swaps them and places in low end of result
-// takes the higher two 32 bit values from b and swaps them and places in high end of result.
-FORCE_INLINE __m128i _mm_shuffle_epi_2301(__m128i a, __m128i b)
-{
- return vcombine_s32(vrev64_s32(vget_low_s32(a)), vrev64_s32(vget_high_s32(b)));
-}
-
-// shift a right by 32 bits, and put the lower 32 bits of a into the upper 32 bits of b
-// when a and b are the same, rotates the least significant 32 bits into the most signficant 32 bits, and shifts the rest down
-FORCE_INLINE __m128i _mm_shuffle_epi_0321(__m128i a, __m128i b)
-{
- return vextq_s32(a, b, 1);
-}
-
-// shift a left by 32 bits, and put the upper 32 bits of b into the lower 32 bits of a
-// when a and b are the same, rotates the most significant 32 bits into the least signficant 32 bits, and shifts the rest up
-FORCE_INLINE __m128i _mm_shuffle_epi_2103(__m128i a, __m128i b)
-{
- return vextq_s32(a, b, 3);
-}
-
-// gets the lower 64 bits of a, and places it in the upper 64 bits
-// gets the lower 64 bits of b and places it in the lower 64 bits
-FORCE_INLINE __m128i _mm_shuffle_epi_1010(__m128i a, __m128i b)
-{
- return vcombine_s32(vget_low_s32(a), vget_low_s32(a));
-}
-
-// gets the lower 64 bits of a, and places it in the upper 64 bits
-// gets the lower 64 bits of b, swaps the 0 and 1 elements, and places it in the lower 64 bits
-FORCE_INLINE __m128i _mm_shuffle_epi_1001(__m128i a, __m128i b)
-{
- return vcombine_s32(vrev64_s32(vget_low_s32(a)), vget_low_s32(b));
-}
-
-// gets the lower 64 bits of a, swaps the 0 and 1 elements and places it in the upper 64 bits
-// gets the lower 64 bits of b, swaps the 0 and 1 elements, and places it in the lower 64 bits
-FORCE_INLINE __m128i _mm_shuffle_epi_0101(__m128i a, __m128i b)
-{
- return vcombine_s32(vrev64_s32(vget_low_s32(a)), vrev64_s32(vget_low_s32(b)));
-}
-
-FORCE_INLINE __m128i _mm_shuffle_epi_2211(__m128i a, __m128i b)
-{
- return vcombine_s32(vdup_n_s32(vgetq_lane_s32(a, 1)), vdup_n_s32(vgetq_lane_s32(b, 2)));
-}
-
-FORCE_INLINE __m128i _mm_shuffle_epi_0122(__m128i a, __m128i b)
-{
- return vcombine_s32(vdup_n_s32(vgetq_lane_s32(a, 2)), vrev64_s32(vget_low_s32(b)));
-}
-
-FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a, __m128i b)
-{
- return vcombine_s32(vget_high_s32(a), vdup_n_s32(vgetq_lane_s32(b, 3)));
-}
-
-template <int i >
-FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __m128i b)
-{
-#if ENABLE_CPP_VERSION
- __m128i ret;
- ret[0] = a[i & 0x3];
- ret[1] = a[(i >> 2) & 0x3];
- ret[2] = b[(i >> 4) & 0x03];
- ret[3] = b[(i >> 6) & 0x03];
- return ret;
-#else
- __m128i ret = vmovq_n_s32(vgetq_lane_s32(a, i & 0x3));
- ret = vsetq_lane_s32(vgetq_lane_s32(a, (i >> 2) & 0x3), ret, 1);
- ret = vsetq_lane_s32(vgetq_lane_s32(b, (i >> 4) & 0x3), ret, 2);
- ret = vsetq_lane_s32(vgetq_lane_s32(b, (i >> 6) & 0x3), ret, 3);
- return ret;
-#endif
-}
-
-template <int i >
-FORCE_INLINE __m128i _mm_shuffle_epi32_function(__m128i a, __m128i b)
-{
- switch (i)
- {
- case _MM_SHUFFLE(1, 0, 3, 2): return _mm_shuffle_epi_1032(a, b); break;
- case _MM_SHUFFLE(2, 3, 0, 1): return _mm_shuffle_epi_2301(a, b); break;
- case _MM_SHUFFLE(0, 3, 2, 1): return _mm_shuffle_epi_0321(a, b); break;
- case _MM_SHUFFLE(2, 1, 0, 3): return _mm_shuffle_epi_2103(a, b); break;
- case _MM_SHUFFLE(1, 0, 1, 0): return _mm_shuffle_epi_1010(a, b); break;
- case _MM_SHUFFLE(1, 0, 0, 1): return _mm_shuffle_epi_1001(a, b); break;
- case _MM_SHUFFLE(0, 1, 0, 1): return _mm_shuffle_epi_0101(a, b); break;
- case _MM_SHUFFLE(2, 2, 1, 1): return _mm_shuffle_epi_2211(a, b); break;
- case _MM_SHUFFLE(0, 1, 2, 2): return _mm_shuffle_epi_0122(a, b); break;
- case _MM_SHUFFLE(3, 3, 3, 2): return _mm_shuffle_epi_3332(a, b); break;
- default: return _mm_shuffle_epi32_default<i>(a, b);
- }
-}
-
-template <int i >
-FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a)
-{
- return vdupq_n_s32(vgetq_lane_s32(a, i));
-}
-
-template <int i>
-FORCE_INLINE __m128i _mm_shuffle_epi32_single(__m128i a)
-{
- switch (i)
- {
- case _MM_SHUFFLE(0, 0, 0, 0): return _mm_shuffle_epi32_splat<0>(a); break;
- case _MM_SHUFFLE(1, 1, 1, 1): return _mm_shuffle_epi32_splat<1>(a); break;
- case _MM_SHUFFLE(2, 2, 2, 2): return _mm_shuffle_epi32_splat<2>(a); break;
- case _MM_SHUFFLE(3, 3, 3, 3): return _mm_shuffle_epi32_splat<3>(a); break;
- default: return _mm_shuffle_epi32_function<i>(a, a);
- }
-}
-
-// Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm. https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx
-#define _mm_shuffle_epi32(a,i) _mm_shuffle_epi32_single<i>(a)
-
-template <int i>
-FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a)
-{
- int16x8_t ret = (int16x8_t)a;
- int16x4_t highBits = vget_high_s16(ret);
- ret = vsetq_lane_s16(vget_lane_s16(highBits, i & 0x3), ret, 4);
- ret = vsetq_lane_s16(vget_lane_s16(highBits, (i >> 2) & 0x3), ret, 5);
- ret = vsetq_lane_s16(vget_lane_s16(highBits, (i >> 4) & 0x3), ret, 6);
- ret = vsetq_lane_s16(vget_lane_s16(highBits, (i >> 6) & 0x3), ret, 7);
- return (__m128i)ret;
-}
-
-// Shuffles the upper 4 signed or unsigned 16 - bit integers in a as specified by imm. https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx
-#define _mm_shufflehi_epi16(a,i) _mm_shufflehi_epi16_function<i>(a)
-
-// Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while shifting in zeros. : https://msdn.microsoft.com/en-us/library/z2k3bbtb%28v=vs.90%29.aspx
-//#define _mm_slli_epi32(a, imm) (__m128i)vshlq_n_s32(a,imm)
-
-// Based on SIMDe
-FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, const int imm8)
-{
-#if defined(__aarch64__)
- const int32x4_t s = vdupq_n_s32(imm8);
- return vshlq_s32(a, s);
-#else
- int32_t __attribute__((aligned(16))) data[4];
- vst1q_s32(data, a);
- const int s = (imm8 > 31) ? 0 : imm8;
- data[0] = data[0] << s;
- data[1] = data[1] << s;
- data[2] = data[2] << s;
- data[3] = data[3] << s;
-
- return vld1q_s32(data);
-#endif
-}
-
-
-//Shifts the 4 signed or unsigned 32-bit integers in a right by count bits while shifting in zeros. https://msdn.microsoft.com/en-us/library/w486zcfa(v=vs.100).aspx
-//#define _mm_srli_epi32( a, imm ) (__m128i)vshrq_n_u32((uint32x4_t)a, imm)
-
-// Based on SIMDe
-FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, const int imm8)
-{
-#if defined(__aarch64__)
- const int shift = (imm8 > 31) ? 0 : imm8; // Unfortunately, we need to check for this case for embree.
- const int32x4_t s = vdupq_n_s32(-shift);
- return vreinterpretq_s32_u32(vshlq_u32(vreinterpretq_u32_s32(a), s));
-#else
- int32_t __attribute__((aligned(16))) data[4];
- vst1q_s32(data, a);
-
- const int s = (imm8 > 31) ? 0 : imm8;
-
- data[0] = data[0] >> s;
- data[1] = data[1] >> s;
- data[2] = data[2] >> s;
- data[3] = data[3] >> s;
-
- return vld1q_s32(data);
-#endif
-}
-
-
-// Shifts the 4 signed 32 - bit integers in a right by count bits while shifting in the sign bit. https://msdn.microsoft.com/en-us/library/z1939387(v=vs.100).aspx
-//#define _mm_srai_epi32( a, imm ) vshrq_n_s32(a, imm)
-
-// Based on SIMDe
-FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, const int imm8)
-{
-#if defined(__aarch64__)
- const int32x4_t s = vdupq_n_s32(-imm8);
- return vshlq_s32(a, s);
-#else
- int32_t __attribute__((aligned(16))) data[4];
- vst1q_s32(data, a);
- const uint32_t m = (uint32_t) ((~0U) << (32 - imm8));
-
- for (int i = 0; i < 4; i++) {
- uint32_t is_neg = ((uint32_t) (((data[i]) >> 31)));
- data[i] = (data[i] >> imm8) | (m * is_neg);
- }
-
- return vld1q_s32(data);
-#endif
-}
-
-// Shifts the 128 - bit value in a right by imm bytes while shifting in zeros.imm must be an immediate. https://msdn.microsoft.com/en-us/library/305w28yz(v=vs.100).aspx
-//#define _mm_srli_si128( a, imm ) (__m128i)vmaxq_s8((int8x16_t)a, vextq_s8((int8x16_t)a, vdupq_n_s8(0), imm))
-#define _mm_srli_si128( a, imm ) (__m128i)vextq_s8((int8x16_t)a, vdupq_n_s8(0), (imm))
-
-// Shifts the 128-bit value in a left by imm bytes while shifting in zeros. imm must be an immediate. https://msdn.microsoft.com/en-us/library/34d3k2kt(v=vs.100).aspx
-#define _mm_slli_si128( a, imm ) (__m128i)vextq_s8(vdupq_n_s8(0), (int8x16_t)a, 16 - (imm))
-
-// NEON does not provide a version of this function, here is an article about some ways to repro the results.
-// http://stackoverflow.com/questions/11870910/sse-mm-movemask-epi8-equivalent-method-for-arm-neon
-// Creates a 16-bit mask from the most significant bits of the 16 signed or unsigned 8-bit integers in a and zero extends the upper bits. https://msdn.microsoft.com/en-us/library/vstudio/s090c8fk(v=vs.100).aspx
-FORCE_INLINE int _mm_movemask_epi8(__m128i _a)
-{
- uint8x16_t input = (uint8x16_t)_a;
- const int8_t __attribute__((aligned(16))) xr[8] = { -7, -6, -5, -4, -3, -2, -1, 0 };
- uint8x8_t mask_and = vdup_n_u8(0x80);
- int8x8_t mask_shift = vld1_s8(xr);
-
- uint8x8_t lo = vget_low_u8(input);
- uint8x8_t hi = vget_high_u8(input);
-
- lo = vand_u8(lo, mask_and);
- lo = vshl_u8(lo, mask_shift);
-
- hi = vand_u8(hi, mask_and);
- hi = vshl_u8(hi, mask_shift);
-
- lo = vpadd_u8(lo, lo);
- lo = vpadd_u8(lo, lo);
- lo = vpadd_u8(lo, lo);
-
- hi = vpadd_u8(hi, hi);
- hi = vpadd_u8(hi, hi);
- hi = vpadd_u8(hi, hi);
-
- return ((hi[0] << 8) | (lo[0] & 0xFF));
-}
-
-
-// ******************************************
-// Math operations
-// ******************************************
-
-// Subtracts the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/1zad2k61(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b)
-{
- return vsubq_f32(a, b);
-}
-
-FORCE_INLINE __m128 _mm_sub_ss(__m128 a, __m128 b)
-{
- return vsubq_f32(a, b);
-}
-
-// Subtracts the 4 signed or unsigned 32-bit integers of b from the 4 signed or unsigned 32-bit integers of a. https://msdn.microsoft.com/en-us/library/vstudio/fhh866h0(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_sub_epi32(__m128i a, __m128i b)
-{
- return vsubq_s32(a, b);
-}
-
-// Adds the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/c9848chc(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b)
-{
- return vaddq_f32(a, b);
-}
-
-// adds the scalar single-precision floating point values of a and b. https://msdn.microsoft.com/en-us/library/be94x2y6(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_add_ss(__m128 a, __m128 b)
-{
- const float32_t b0 = vgetq_lane_f32(b, 0);
- float32x4_t value = vdupq_n_f32(0);
-
- //the upper values in the result must be the remnants of <a>.
- value = vsetq_lane_f32(b0, value, 0);
- return vaddq_f32(a, value);
-}
-
-// Adds the 4 signed or unsigned 32-bit integers in a to the 4 signed or unsigned 32-bit integers in b. https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b)
-{
- return vaddq_s32(a, b);
-}
-
-// Adds the 8 signed or unsigned 16-bit integers in a to the 8 signed or unsigned 16-bit integers in b. https://msdn.microsoft.com/en-us/library/fceha5k4(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_add_epi16(__m128i a, __m128i b)
-{
- return (__m128i)vaddq_s16((int16x8_t)a, (int16x8_t)b);
-}
-
-// Multiplies the 8 signed or unsigned 16-bit integers from a by the 8 signed or unsigned 16-bit integers from b. https://msdn.microsoft.com/en-us/library/vstudio/9ks1472s(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b)
-{
- return (__m128i)vmulq_s16((int16x8_t)a, (int16x8_t)b);
-}
-
-// Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or unsigned 32-bit integers from b. https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_mullo_epi32 (__m128i a, __m128i b)
-{
- return (__m128i)vmulq_s32((int32x4_t)a,(int32x4_t)b);
-}
-
-// Multiplies the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b)
-{
- return vmulq_f32(a, b);
-}
-
-FORCE_INLINE __m128 _mm_mul_ss(__m128 a, __m128 b)
-{
- return vmulq_f32(a, b);
-}
-
-// Computes the approximations of reciprocals of the four single-precision, floating-point values of a. https://msdn.microsoft.com/en-us/library/vstudio/796k1tty(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_rcp_ps(__m128 in)
-{
-#if defined(BUILD_IOS)
- return vdivq_f32(vdupq_n_f32(1.0f),in);
-
-#endif
- // Get an initial estimate of 1/in.
- float32x4_t reciprocal = vrecpeq_f32(in);
-
- // We only return estimated 1/in.
- // Newton-Raphon iteration shold be done in the outside of _mm_rcp_ps().
-
- // TODO(LTE): We could delete these ifdef?
- reciprocal = vmulq_f32(vrecpsq_f32(in, reciprocal), reciprocal);
- reciprocal = vmulq_f32(vrecpsq_f32(in, reciprocal), reciprocal);
- return reciprocal;
-
-}
-
-FORCE_INLINE __m128 _mm_rcp_ss(__m128 in)
-{
- float32x4_t value;
- float32x4_t result = in;
-
- value = _mm_rcp_ps(in);
- return vsetq_lane_f32(vgetq_lane_f32(value, 0), result, 0);
-}
-
-// Divides the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/edaw8147(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_div_ps(__m128 a, __m128 b)
-{
-#if defined(BUILD_IOS)
- return vdivq_f32(a,b);
-#else
- float32x4_t reciprocal = _mm_rcp_ps(b);
-
- reciprocal = vmulq_f32(vrecpsq_f32(b, reciprocal), reciprocal);
- reciprocal = vmulq_f32(vrecpsq_f32(b, reciprocal), reciprocal);
-
- // Add one more round of newton-raphson since NEON's reciprocal estimation has less accuracy compared to SSE2's rcp.
- reciprocal = vmulq_f32(vrecpsq_f32(b, reciprocal), reciprocal);
-
- // Another round for safety
- reciprocal = vmulq_f32(vrecpsq_f32(b, reciprocal), reciprocal);
-
-
- return vmulq_f32(a, reciprocal);
-#endif
-}
-
-// Divides the scalar single-precision floating point value of a by b. https://msdn.microsoft.com/en-us/library/4y73xa49(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_div_ss(__m128 a, __m128 b)
-{
- float32x4_t value;
- float32x4_t result = a;
- value = _mm_div_ps(a, b);
- return vsetq_lane_f32(vgetq_lane_f32(value, 0), result, 0);
-}
-
-// Computes the approximations of the reciprocal square roots of the four single-precision floating point values of in. https://msdn.microsoft.com/en-us/library/22hfsh53(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_rsqrt_ps(__m128 in)
-{
-
- float32x4_t value = vrsqrteq_f32(in);
-
- // TODO: We must debug and ensure that rsqrt(0) and rsqrt(-0) yield proper values.
- // Related code snippets can be found here: https://cpp.hotexamples.com/examples/-/-/vrsqrteq_f32/cpp-vrsqrteq_f32-function-examples.html
- // If we adapt this function, we might be able to avoid special zero treatment in _mm_sqrt_ps
-
- value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(in, value), value));
- value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(in, value), value));
-
- // one more round to get better precision
- value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(in, value), value));
-
- // another round for safety
- value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(in, value), value));
-
- return value;
-}
-
-FORCE_INLINE __m128 _mm_rsqrt_ss(__m128 in)
-{
- float32x4_t result = in;
-
- __m128 value = _mm_rsqrt_ps(in);
-
- return vsetq_lane_f32(vgetq_lane_f32(value, 0), result, 0);
-}
-
-
-// Computes the approximations of square roots of the four single-precision, floating-point values of a. First computes reciprocal square roots and then reciprocals of the four values. https://msdn.microsoft.com/en-us/library/vstudio/8z67bwwk(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in)
-{
-#if defined(BUILD_IOS)
- return vsqrtq_f32(in);
-#else
- __m128 reciprocal = _mm_rsqrt_ps(in);
-
- // We must treat sqrt(in == 0) in a special way. At this point reciprocal contains gargabe due to vrsqrteq_f32(0) returning +inf.
- // We assign 0 to reciprocal wherever required.
- const float32x4_t vzero = vdupq_n_f32(0.0f);
- const uint32x4_t mask = vceqq_f32(in, vzero);
- reciprocal = vbslq_f32(mask, vzero, reciprocal);
-
- // sqrt(x) = x * (1 / sqrt(x))
- return vmulq_f32(in, reciprocal);
-#endif
-}
-
-// Computes the approximation of the square root of the scalar single-precision floating point value of in. https://msdn.microsoft.com/en-us/library/ahfsc22d(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_sqrt_ss(__m128 in)
-{
- float32x4_t value;
- float32x4_t result = in;
-
- value = _mm_sqrt_ps(in);
- return vsetq_lane_f32(vgetq_lane_f32(value, 0), result, 0);
-}
-
-
-// Computes the maximums of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/ff5d607a(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_max_ps(__m128 a, __m128 b)
-{
-#if USE_PRECISE_MINMAX_IMPLEMENTATION
- return vbslq_f32(vcltq_f32(b,a),a,b);
-#else
- // Faster, but would give inconsitent rendering(e.g. holes, NaN pixels)
- return vmaxq_f32(a, b);
-#endif
-}
-
-// Computes the minima of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/wh13kadz(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_min_ps(__m128 a, __m128 b)
-{
-#if USE_PRECISE_MINMAX_IMPLEMENTATION
- return vbslq_f32(vcltq_f32(a,b),a,b);
-#else
- // Faster, but would give inconsitent rendering(e.g. holes, NaN pixels)
- return vminq_f32(a, b);
-#endif
-}
-
-// Computes the maximum of the two lower scalar single-precision floating point values of a and b. https://msdn.microsoft.com/en-us/library/s6db5esz(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_max_ss(__m128 a, __m128 b)
-{
- float32x4_t value;
- float32x4_t result = a;
-
- value = _mm_max_ps(a, b);
- return vsetq_lane_f32(vgetq_lane_f32(value, 0), result, 0);
-}
-
-// Computes the minimum of the two lower scalar single-precision floating point values of a and b. https://msdn.microsoft.com/en-us/library/0a9y7xaa(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_min_ss(__m128 a, __m128 b)
-{
- float32x4_t value;
- float32x4_t result = a;
-
-
- value = _mm_min_ps(a, b);
- return vsetq_lane_f32(vgetq_lane_f32(value, 0), result, 0);
-}
-
-// Computes the pairwise minima of the 8 signed 16-bit integers from a and the 8 signed 16-bit integers from b. https://msdn.microsoft.com/en-us/library/vstudio/6te997ew(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_min_epi16(__m128i a, __m128i b)
-{
- return (__m128i)vminq_s16((int16x8_t)a, (int16x8_t)b);
-}
-
-// epi versions of min/max
-// Computes the pariwise maximums of the four signed 32-bit integer values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/bb514055(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_max_epi32(__m128i a, __m128i b )
-{
- return vmaxq_s32(a,b);
-}
-
-// Computes the pariwise minima of the four signed 32-bit integer values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/bb531476(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b )
-{
- return vminq_s32(a,b);
-}
-
-// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit integers from b. https://msdn.microsoft.com/en-us/library/vstudio/59hddw1d(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b)
-{
- int16x8_t ret = vqdmulhq_s16((int16x8_t)a, (int16x8_t)b);
- ret = vshrq_n_s16(ret, 1);
- return (__m128i)ret;
-}
-
-// Computes pairwise add of each argument as single-precision, floating-point values a and b.
-//https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx
-FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b )
-{
-#if defined(__aarch64__)
- return vpaddq_f32(a,b);
-#else
-// This does not work, no vpaddq...
-// return (__m128) vpaddq_f32(a,b);
- //
- // get two f32x2_t values from a
- // do vpadd
- // put result in low half of f32x4 result
- //
- // get two f32x2_t values from b
- // do vpadd
- // put result in high half of f32x4 result
- //
- // combine
- return vcombine_f32( vpadd_f32( vget_low_f32(a), vget_high_f32(a) ), vpadd_f32( vget_low_f32(b), vget_high_f32(b) ) );
-#endif
-}
-
-// ******************************************
-// Compare operations
-// ******************************************
-
-// Compares for less than https://msdn.microsoft.com/en-us/library/vstudio/f330yhc8(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmplt_ps(__m128 a, __m128 b)
-{
- return (__m128)vcltq_f32(a, b);
-}
-
-FORCE_INLINE __m128 _mm_cmpnlt_ps(__m128 a, __m128 b)
-{
- return (__m128) vmvnq_s32((__m128i)_mm_cmplt_ps(a,b));
-}
-
-// Compares for greater than. https://msdn.microsoft.com/en-us/library/vstudio/11dy102s(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmpgt_ps(__m128 a, __m128 b)
-{
- return (__m128)vcgtq_f32(a, b);
-}
-
-FORCE_INLINE __m128 _mm_cmpnle_ps(__m128 a, __m128 b)
-{
- return (__m128) _mm_cmpgt_ps(a,b);
-}
-
-
-// Compares for greater than or equal. https://msdn.microsoft.com/en-us/library/vstudio/fs813y2t(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b)
-{
- return (__m128)vcgeq_f32(a, b);
-}
-
-// Compares for less than or equal. https://msdn.microsoft.com/en-us/library/vstudio/1s75w83z(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b)
-{
- return (__m128)vcleq_f32(a, b);
-}
-
-// Compares for equality. https://msdn.microsoft.com/en-us/library/vstudio/36aectz5(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cmpeq_ps(__m128 a, __m128 b)
-{
- return (__m128)vceqq_f32(a, b);
-}
-
-// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers in b for less than. https://msdn.microsoft.com/en-us/library/vstudio/4ak0bf5d(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cmplt_epi32(__m128i a, __m128i b)
-{
- return (__m128i)vcltq_s32(a, b);
-}
-
-FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i a, __m128i b)
-{
- return (__m128i) vceqq_s32(a,b);
-}
-
-// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers in b for greater than. https://msdn.microsoft.com/en-us/library/vstudio/1s9f2z0y(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b)
-{
- return (__m128i)vcgtq_s32(a, b);
-}
-
-// Compares the four 32-bit floats in a and b to check if any values are NaN. Ordered compare between each value returns true for "orderable" and false for "not orderable" (NaN). https://msdn.microsoft.com/en-us/library/vstudio/0h9w00fx(v=vs.100).aspx
-// see also:
-// http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean
-// http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics
-FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b )
-{
- // Note: NEON does not have ordered compare builtin
- // Need to compare a eq a and b eq b to check for NaN
- // Do AND of results to get final
- return (__m128) vreinterpretq_f32_u32( vandq_u32( vceqq_f32(a,a), vceqq_f32(b,b) ) );
-}
-
-// Compares the lower single-precision floating point scalar values of a and b using a less than operation. : https://msdn.microsoft.com/en-us/library/2kwe606b(v=vs.90).aspx
-FORCE_INLINE int _mm_comilt_ss(__m128 a, __m128 b)
-{
- uint32x4_t value;
-
- value = vcltq_f32(a, b);
- return vgetq_lane_u32(value, 0);
-}
-
-// Compares the lower single-precision floating point scalar values of a and b using a greater than operation. : https://msdn.microsoft.com/en-us/library/b0738e0t(v=vs.100).aspx
-FORCE_INLINE int _mm_comigt_ss(__m128 a, __m128 b)
-{
- uint32x4_t value;
-
- value = vcgtq_f32(a, b);
- return vgetq_lane_u32(value, 0);
-}
-
-// Compares the lower single-precision floating point scalar values of a and b using a less than or equal operation. : https://msdn.microsoft.com/en-us/library/1w4t7c57(v=vs.90).aspx
-FORCE_INLINE int _mm_comile_ss(__m128 a, __m128 b)
-{
- uint32x4_t value;
-
- value = vcleq_f32(a, b);
- return vgetq_lane_u32(value, 0);
-}
-
-// Compares the lower single-precision floating point scalar values of a and b using a greater than or equal operation. : https://msdn.microsoft.com/en-us/library/8t80des6(v=vs.100).aspx
-FORCE_INLINE int _mm_comige_ss(__m128 a, __m128 b)
-{
- uint32x4_t value;
-
- value = vcgeq_f32(a, b);
- return vgetq_lane_u32(value, 0);
-}
-
-// Compares the lower single-precision floating point scalar values of a and b using an equality operation. : https://msdn.microsoft.com/en-us/library/93yx2h2b(v=vs.100).aspx
-FORCE_INLINE int _mm_comieq_ss(__m128 a, __m128 b)
-{
- uint32x4_t value;
-
- value = vceqq_f32(a, b);
- return vgetq_lane_u32(value, 0);
-}
-
-// Compares the lower single-precision floating point scalar values of a and b using an inequality operation. : https://msdn.microsoft.com/en-us/library/bafh5e0a(v=vs.90).aspx
-FORCE_INLINE int _mm_comineq_ss(__m128 a, __m128 b)
-{
- uint32x4_t value;
-
- value = vceqq_f32(a, b);
- return !vgetq_lane_u32(value, 0);
-}
-
-// according to the documentation, these intrinsics behave the same as the non-'u' versions. We'll just alias them here.
-#define _mm_ucomilt_ss _mm_comilt_ss
-#define _mm_ucomile_ss _mm_comile_ss
-#define _mm_ucomigt_ss _mm_comigt_ss
-#define _mm_ucomige_ss _mm_comige_ss
-#define _mm_ucomieq_ss _mm_comieq_ss
-#define _mm_ucomineq_ss _mm_comineq_ss
-
-// ******************************************
-// Conversions
-// ******************************************
-
-// Converts the four single-precision, floating-point values of a to signed 32-bit integer values using truncate. https://msdn.microsoft.com/en-us/library/vstudio/1h005y6x(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a)
-{
- return vcvtq_s32_f32(a);
-}
-
-// Converts the four signed 32-bit integer values of a to single-precision, floating-point values https://msdn.microsoft.com/en-us/library/vstudio/36bwxcx5(v=vs.100).aspx
-FORCE_INLINE __m128 _mm_cvtepi32_ps(__m128i a)
-{
- return vcvtq_f32_s32(a);
-}
-
-// Converts the four single-precision, floating-point values of a to signed 32-bit integer values. https://msdn.microsoft.com/en-us/library/vstudio/xdc42k5e(v=vs.100).aspx
-// *NOTE*. The default rounding mode on SSE is 'round to even', which ArmV7 does not support!
-// It is supported on ARMv8 however.
-FORCE_INLINE __m128i _mm_cvtps_epi32(__m128 a)
-{
-#if 1
- return vcvtnq_s32_f32(a);
-#else
- __m128 half = vdupq_n_f32(0.5f);
- const __m128 sign = vcvtq_f32_u32((vshrq_n_u32(vreinterpretq_u32_f32(a), 31)));
- const __m128 aPlusHalf = vaddq_f32(a, half);
- const __m128 aRound = vsubq_f32(aPlusHalf, sign);
- return vcvtq_s32_f32(aRound);
-#endif
-}
-
-// Moves the least significant 32 bits of a to a 32-bit integer. https://msdn.microsoft.com/en-us/library/5z7a9642%28v=vs.90%29.aspx
-FORCE_INLINE int _mm_cvtsi128_si32(__m128i a)
-{
- return vgetq_lane_s32(a, 0);
-}
-
-// Moves 32-bit integer a to the least significant 32 bits of an __m128 object, zero extending the upper bits. https://msdn.microsoft.com/en-us/library/ct3539ha%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_cvtsi32_si128(int a)
-{
- __m128i result = vdupq_n_s32(0);
- return vsetq_lane_s32(a, result, 0);
-}
-
-
-// Applies a type cast to reinterpret four 32-bit floating point values passed in as a 128-bit parameter as packed 32-bit integers. https://msdn.microsoft.com/en-us/library/bb514099.aspx
-FORCE_INLINE __m128i _mm_castps_si128(__m128 a)
-{
-#if defined(__aarch64__)
- return (__m128i)a;
-#else
- return *(const __m128i *)&a;
-#endif
-}
-
-// Applies a type cast to reinterpret four 32-bit integers passed in as a 128-bit parameter as packed 32-bit floating point values. https://msdn.microsoft.com/en-us/library/bb514029.aspx
-FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a)
-{
-#if defined(__aarch64__)
- return (__m128)a;
-#else
- return *(const __m128 *)&a;
-#endif
-}
-
-// Loads 128-bit value. : https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx
-FORCE_INLINE __m128i _mm_load_si128(const __m128i *p)
-{
- return vld1q_s32((int32_t *)p);
-}
-
-FORCE_INLINE __m128d _mm_castps_pd(const __m128 a)
-{
- return *(const __m128d *)&a;
-}
-
-FORCE_INLINE __m128d _mm_castsi128_pd(__m128i a)
-{
- return *(const __m128d *)&a;
-}
-// ******************************************
-// Miscellaneous Operations
-// ******************************************
-
-// Packs the 16 signed 16-bit integers from a and b into 8-bit integers and saturates. https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b)
-{
- return (__m128i)vcombine_s8(vqmovn_s16((int16x8_t)a), vqmovn_s16((int16x8_t)b));
-}
-
-// Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned integers and saturates. https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b)
-{
- return (__m128i)vcombine_u8(vqmovun_s16((int16x8_t)a), vqmovun_s16((int16x8_t)b));
-}
-
-// Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers and saturates. https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b)
-{
- return (__m128i)vcombine_s16(vqmovn_s32(a), vqmovn_s32(b));
-}
-
-// Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower 8 signed or unsigned 8-bit integers in b. https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_unpacklo_epi8(__m128i a, __m128i b)
-{
- int8x8_t a1 = (int8x8_t)vget_low_s16((int16x8_t)a);
- int8x8_t b1 = (int8x8_t)vget_low_s16((int16x8_t)b);
-
- int8x8x2_t result = vzip_s8(a1, b1);
-
- return (__m128i)vcombine_s8(result.val[0], result.val[1]);
-}
-
-// Interleaves the lower 4 signed or unsigned 16-bit integers in a with the lower 4 signed or unsigned 16-bit integers in b. https://msdn.microsoft.com/en-us/library/btxb17bw%28v=vs.90%29.aspx
-FORCE_INLINE __m128i _mm_unpacklo_epi16(__m128i a, __m128i b)
-{
- int16x4_t a1 = vget_low_s16((int16x8_t)a);
- int16x4_t b1 = vget_low_s16((int16x8_t)b);
-
- int16x4x2_t result = vzip_s16(a1, b1);
-
- return (__m128i)vcombine_s16(result.val[0], result.val[1]);
-}
-
-// Interleaves the lower 2 signed or unsigned 32 - bit integers in a with the lower 2 signed or unsigned 32 - bit integers in b. https://msdn.microsoft.com/en-us/library/x8atst9d(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_unpacklo_epi32(__m128i a, __m128i b)
-{
- int32x2_t a1 = vget_low_s32(a);
- int32x2_t b1 = vget_low_s32(b);
-
- int32x2x2_t result = vzip_s32(a1, b1);
-
- return vcombine_s32(result.val[0], result.val[1]);
-}
-
-// Selects and interleaves the lower two single-precision, floating-point values from a and b. https://msdn.microsoft.com/en-us/library/25st103b%28v=vs.90%29.aspx
-FORCE_INLINE __m128 _mm_unpacklo_ps(__m128 a, __m128 b)
-{
- float32x2x2_t result = vzip_f32(vget_low_f32(a), vget_low_f32(b));
- return vcombine_f32(result.val[0], result.val[1]);
-}
-
-// Selects and interleaves the upper two single-precision, floating-point values from a and b. https://msdn.microsoft.com/en-us/library/skccxx7d%28v=vs.90%29.aspx
-FORCE_INLINE __m128 _mm_unpackhi_ps(__m128 a, __m128 b)
-{
- float32x2x2_t result = vzip_f32(vget_high_f32(a), vget_high_f32(b));
- return vcombine_f32(result.val[0], result.val[1]);
-}
-
-// Interleaves the upper 8 signed or unsigned 8-bit integers in a with the upper 8 signed or unsigned 8-bit integers in b. https://msdn.microsoft.com/en-us/library/t5h7783k(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_unpackhi_epi8(__m128i a, __m128i b)
-{
- int8x8_t a1 = (int8x8_t)vget_high_s16((int16x8_t)a);
- int8x8_t b1 = (int8x8_t)vget_high_s16((int16x8_t)b);
-
- int8x8x2_t result = vzip_s8(a1, b1);
-
- return (__m128i)vcombine_s8(result.val[0], result.val[1]);
-}
-
-// Interleaves the upper 4 signed or unsigned 16-bit integers in a with the upper 4 signed or unsigned 16-bit integers in b. https://msdn.microsoft.com/en-us/library/03196cz7(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_unpackhi_epi16(__m128i a, __m128i b)
-{
- int16x4_t a1 = vget_high_s16((int16x8_t)a);
- int16x4_t b1 = vget_high_s16((int16x8_t)b);
-
- int16x4x2_t result = vzip_s16(a1, b1);
-
- return (__m128i)vcombine_s16(result.val[0], result.val[1]);
-}
-
-// Interleaves the upper 2 signed or unsigned 32-bit integers in a with the upper 2 signed or unsigned 32-bit integers in b. https://msdn.microsoft.com/en-us/library/65sa7cbs(v=vs.100).aspx
-FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b)
-{
- int32x2_t a1 = vget_high_s32(a);
- int32x2_t b1 = vget_high_s32(b);
-
- int32x2x2_t result = vzip_s32(a1, b1);
-
- return vcombine_s32(result.val[0], result.val[1]);
-}
-
-// Extracts the selected signed or unsigned 16-bit integer from a and zero extends. https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx
-#define _mm_extract_epi16( a, imm ) vgetq_lane_s16((int16x8_t)a, imm)
-
-// ******************************************
-// Streaming Extensions
-// ******************************************
-
-// Guarantees that every preceding store is globally visible before any subsequent store. https://msdn.microsoft.com/en-us/library/5h2w73d1%28v=vs.90%29.aspx
-FORCE_INLINE void _mm_sfence(void)
-{
- __sync_synchronize();
-}
-
-// Stores the data in a to the address p without polluting the caches. If the cache line containing address p is already in the cache, the cache will be updated.Address p must be 16 - byte aligned. https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx
-FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a)
-{
- *p = a;
-}
-
-// Cache line containing p is flushed and invalidated from all caches in the coherency domain. : https://msdn.microsoft.com/en-us/library/ba08y07y(v=vs.100).aspx
-FORCE_INLINE void _mm_clflush(void const*p)
-{
- // no corollary for Neon?
-}
-
-FORCE_INLINE __m128i _mm_set_epi64x(int64_t a, int64_t b)
-{
- // Stick to the flipped behavior of x86.
- int64_t __attribute__((aligned(16))) data[2] = { b, a };
- return (__m128i)vld1q_s64(data);
-}
-
-FORCE_INLINE __m128i _mm_set1_epi64x(int64_t _i)
-{
- return (__m128i)vmovq_n_s64(_i);
-}
-
-#if defined(__aarch64__)
-FORCE_INLINE __m128 _mm_blendv_ps(__m128 a, __m128 b, __m128 c)
-{
- int32x4_t mask = vshrq_n_s32(__m128i(c),31);
- return vbslq_f32( uint32x4_t(mask), b, a);
-}
-
-FORCE_INLINE __m128i _mm_load4epu8_epi32(__m128i *ptr)
-{
- uint8x8_t t0 = vld1_u8((uint8_t*)ptr);
- uint16x8_t t1 = vmovl_u8(t0);
- uint32x4_t t2 = vmovl_u16(vget_low_u16(t1));
- return vreinterpretq_s32_u32(t2);
-}
-
-FORCE_INLINE __m128i _mm_load4epu16_epi32(__m128i *ptr)
-{
- uint16x8_t t0 = vld1q_u16((uint16_t*)ptr);
- uint32x4_t t1 = vmovl_u16(vget_low_u16(t0));
- return vreinterpretq_s32_u32(t1);
-}
-
-FORCE_INLINE __m128i _mm_load4epi8_f32(__m128i *ptr)
-{
- int8x8_t t0 = vld1_s8((int8_t*)ptr);
- int16x8_t t1 = vmovl_s8(t0);
- int32x4_t t2 = vmovl_s16(vget_low_s16(t1));
- float32x4_t t3 = vcvtq_f32_s32(t2);
- return vreinterpretq_s32_f32(t3);
-}
-
-FORCE_INLINE __m128i _mm_load4epu8_f32(__m128i *ptr)
-{
- uint8x8_t t0 = vld1_u8((uint8_t*)ptr);
- uint16x8_t t1 = vmovl_u8(t0);
- uint32x4_t t2 = vmovl_u16(vget_low_u16(t1));
- return vreinterpretq_s32_u32(t2);
-}
-
-FORCE_INLINE __m128i _mm_load4epi16_f32(__m128i *ptr)
-{
- int16x8_t t0 = vld1q_s16((int16_t*)ptr);
- int32x4_t t1 = vmovl_s16(vget_low_s16(t0));
- float32x4_t t2 = vcvtq_f32_s32(t1);
- return vreinterpretq_s32_f32(t2);
-}
-
-FORCE_INLINE __m128i _mm_packus_epi32(__m128i a, __m128i b)
-{
- return (__m128i)vcombine_u8(vqmovun_s16((int16x8_t)a), vqmovun_s16((int16x8_t)b));
-}
-
-FORCE_INLINE __m128i _mm_stream_load_si128(__m128i* ptr)
-{
- // No non-temporal load on a single register on ARM.
- return vreinterpretq_s32_u8(vld1q_u8((uint8_t*)ptr));
-}
-
-FORCE_INLINE void _mm_stream_ps(float* ptr, __m128i a)
-{
- // No non-temporal store on a single register on ARM.
- vst1q_f32((float*)ptr, vreinterpretq_f32_s32(a));
-}
-
-FORCE_INLINE __m128i _mm_min_epu32(__m128i a, __m128i b)
-{
- return vreinterpretq_s32_u32(vminq_u32(vreinterpretq_u32_s32(a), vreinterpretq_u32_s32(b)));
-}
-
-FORCE_INLINE __m128i _mm_max_epu32(__m128i a, __m128i b)
-{
- return vreinterpretq_s32_u32(vmaxq_u32(vreinterpretq_u32_s32(a), vreinterpretq_u32_s32(b)));
-}
-
-FORCE_INLINE __m128 _mm_abs_ps(__m128 a)
-{
- return vabsq_f32(a);
-}
-
-FORCE_INLINE __m128 _mm_madd_ps(__m128 a, __m128 b, __m128 c)
-{
- return vmlaq_f32(c, a, b);
-}
-
-FORCE_INLINE __m128 _mm_msub_ps(__m128 a, __m128 b, __m128 c)
-{
- return vmlsq_f32(c, a, b);
-}
-
-FORCE_INLINE __m128i _mm_abs_epi32(__m128i a)
-{
- return vabsq_s32(a);
-}
-#endif //defined(__aarch64__)
-
-// Count the number of bits set to 1 in unsigned 32-bit integer a, and
-// return that count in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u32
-FORCE_INLINE int _mm_popcnt_u32(unsigned int a)
-{
- return (int)vaddlv_u8(vcnt_u8(vcreate_u8((uint64_t)a)));
-}
-
-// Count the number of bits set to 1 in unsigned 64-bit integer a, and
-// return that count in dst.
-// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u64
-FORCE_INLINE int64_t _mm_popcnt_u64(uint64_t a)
-{
- return (int64_t)vaddlv_u8(vcnt_u8(vcreate_u8(a)));
-}
-
-#endif
diff --git a/thirdparty/embree-aarch64/common/math/affinespace.h b/thirdparty/embree-aarch64/common/math/affinespace.h
deleted file mode 100644
index 32452fbe72..0000000000
--- a/thirdparty/embree-aarch64/common/math/affinespace.h
+++ /dev/null
@@ -1,361 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "linearspace2.h"
-#include "linearspace3.h"
-#include "quaternion.h"
-#include "bbox.h"
-#include "vec4.h"
-
-namespace embree
-{
- #define VectorT typename L::Vector
- #define ScalarT typename L::Vector::Scalar
-
- ////////////////////////////////////////////////////////////////////////////////
- // Affine Space
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename L>
- struct AffineSpaceT
- {
- L l; /*< linear part of affine space */
- VectorT p; /*< affine part of affine space */
-
- ////////////////////////////////////////////////////////////////////////////////
- // Constructors, Assignment, Cast, Copy Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline AffineSpaceT ( ) { }
- __forceinline AffineSpaceT ( const AffineSpaceT& other ) { l = other.l; p = other.p; }
- __forceinline AffineSpaceT ( const L & other ) { l = other ; p = VectorT(zero); }
- __forceinline AffineSpaceT& operator=( const AffineSpaceT& other ) { l = other.l; p = other.p; return *this; }
-
- __forceinline AffineSpaceT( const VectorT& vx, const VectorT& vy, const VectorT& vz, const VectorT& p ) : l(vx,vy,vz), p(p) {}
- __forceinline AffineSpaceT( const L& l, const VectorT& p ) : l(l), p(p) {}
-
- template<typename L1> __forceinline AffineSpaceT( const AffineSpaceT<L1>& s ) : l(s.l), p(s.p) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- // Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline AffineSpaceT( ZeroTy ) : l(zero), p(zero) {}
- __forceinline AffineSpaceT( OneTy ) : l(one), p(zero) {}
-
- /*! return matrix for scaling */
- static __forceinline AffineSpaceT scale(const VectorT& s) { return L::scale(s); }
-
- /*! return matrix for translation */
- static __forceinline AffineSpaceT translate(const VectorT& p) { return AffineSpaceT(one,p); }
-
- /*! return matrix for rotation, only in 2D */
- static __forceinline AffineSpaceT rotate(const ScalarT& r) { return L::rotate(r); }
-
- /*! return matrix for rotation around arbitrary point (2D) or axis (3D) */
- static __forceinline AffineSpaceT rotate(const VectorT& u, const ScalarT& r) { return L::rotate(u,r); }
-
- /*! return matrix for rotation around arbitrary axis and point, only in 3D */
- static __forceinline AffineSpaceT rotate(const VectorT& p, const VectorT& u, const ScalarT& r) { return translate(+p) * rotate(u,r) * translate(-p); }
-
- /*! return matrix for looking at given point, only in 3D */
- static __forceinline AffineSpaceT lookat(const VectorT& eye, const VectorT& point, const VectorT& up) {
- VectorT Z = normalize(point-eye);
- VectorT U = normalize(cross(up,Z));
- VectorT V = normalize(cross(Z,U));
- return AffineSpaceT(L(U,V,Z),eye);
- }
-
- };
-
- // template specialization to get correct identity matrix for type AffineSpace3fa
- template<>
- __forceinline AffineSpaceT<LinearSpace3ff>::AffineSpaceT( OneTy ) : l(one), p(0.f, 0.f, 0.f, 1.f) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- // Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename L> __forceinline AffineSpaceT<L> operator -( const AffineSpaceT<L>& a ) { return AffineSpaceT<L>(-a.l,-a.p); }
- template<typename L> __forceinline AffineSpaceT<L> operator +( const AffineSpaceT<L>& a ) { return AffineSpaceT<L>(+a.l,+a.p); }
- template<typename L> __forceinline AffineSpaceT<L> rcp( const AffineSpaceT<L>& a ) { L il = rcp(a.l); return AffineSpaceT<L>(il,-(il*a.p)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename L> __forceinline const AffineSpaceT<L> operator +( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return AffineSpaceT<L>(a.l+b.l,a.p+b.p); }
- template<typename L> __forceinline const AffineSpaceT<L> operator -( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return AffineSpaceT<L>(a.l-b.l,a.p-b.p); }
-
- template<typename L> __forceinline const AffineSpaceT<L> operator *( const ScalarT & a, const AffineSpaceT<L>& b ) { return AffineSpaceT<L>(a*b.l,a*b.p); }
- template<typename L> __forceinline const AffineSpaceT<L> operator *( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return AffineSpaceT<L>(a.l*b.l,a.l*b.p+a.p); }
- template<typename L> __forceinline const AffineSpaceT<L> operator /( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a * rcp(b); }
- template<typename L> __forceinline const AffineSpaceT<L> operator /( const AffineSpaceT<L>& a, const ScalarT & b ) { return a * rcp(b); }
-
- template<typename L> __forceinline AffineSpaceT<L>& operator *=( AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a = a * b; }
- template<typename L> __forceinline AffineSpaceT<L>& operator *=( AffineSpaceT<L>& a, const ScalarT & b ) { return a = a * b; }
- template<typename L> __forceinline AffineSpaceT<L>& operator /=( AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a = a / b; }
- template<typename L> __forceinline AffineSpaceT<L>& operator /=( AffineSpaceT<L>& a, const ScalarT & b ) { return a = a / b; }
-
- template<typename L> __forceinline VectorT xfmPoint (const AffineSpaceT<L>& m, const VectorT& p) { return madd(VectorT(p.x),m.l.vx,madd(VectorT(p.y),m.l.vy,madd(VectorT(p.z),m.l.vz,m.p))); }
- template<typename L> __forceinline VectorT xfmVector(const AffineSpaceT<L>& m, const VectorT& v) { return xfmVector(m.l,v); }
- template<typename L> __forceinline VectorT xfmNormal(const AffineSpaceT<L>& m, const VectorT& n) { return xfmNormal(m.l,n); }
-
- __forceinline const BBox<Vec3fa> xfmBounds(const AffineSpaceT<LinearSpace3<Vec3fa> >& m, const BBox<Vec3fa>& b)
- {
- BBox3fa dst = empty;
- const Vec3fa p0(b.lower.x,b.lower.y,b.lower.z); dst.extend(xfmPoint(m,p0));
- const Vec3fa p1(b.lower.x,b.lower.y,b.upper.z); dst.extend(xfmPoint(m,p1));
- const Vec3fa p2(b.lower.x,b.upper.y,b.lower.z); dst.extend(xfmPoint(m,p2));
- const Vec3fa p3(b.lower.x,b.upper.y,b.upper.z); dst.extend(xfmPoint(m,p3));
- const Vec3fa p4(b.upper.x,b.lower.y,b.lower.z); dst.extend(xfmPoint(m,p4));
- const Vec3fa p5(b.upper.x,b.lower.y,b.upper.z); dst.extend(xfmPoint(m,p5));
- const Vec3fa p6(b.upper.x,b.upper.y,b.lower.z); dst.extend(xfmPoint(m,p6));
- const Vec3fa p7(b.upper.x,b.upper.y,b.upper.z); dst.extend(xfmPoint(m,p7));
- return dst;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename L> __forceinline bool operator ==( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a.l == b.l && a.p == b.p; }
- template<typename L> __forceinline bool operator !=( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a.l != b.l || a.p != b.p; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename L> __forceinline AffineSpaceT<L> select ( const typename L::Vector::Scalar::Bool& s, const AffineSpaceT<L>& t, const AffineSpaceT<L>& f ) {
- return AffineSpaceT<L>(select(s,t.l,f.l),select(s,t.p,f.p));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename L> static embree_ostream operator<<(embree_ostream cout, const AffineSpaceT<L>& m) {
- return cout << "{ l = " << m.l << ", p = " << m.p << " }";
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Template Instantiations
- ////////////////////////////////////////////////////////////////////////////////
-
- typedef AffineSpaceT<LinearSpace2f> AffineSpace2f;
- typedef AffineSpaceT<LinearSpace3f> AffineSpace3f;
- typedef AffineSpaceT<LinearSpace3fa> AffineSpace3fa;
- typedef AffineSpaceT<LinearSpace3fx> AffineSpace3fx;
- typedef AffineSpaceT<LinearSpace3ff> AffineSpace3ff;
- typedef AffineSpaceT<Quaternion3f > OrthonormalSpace3f;
-
- template<int N> using AffineSpace3vf = AffineSpaceT<LinearSpace3<Vec3<vfloat<N>>>>;
- typedef AffineSpaceT<LinearSpace3<Vec3<vfloat<4>>>> AffineSpace3vf4;
- typedef AffineSpaceT<LinearSpace3<Vec3<vfloat<8>>>> AffineSpace3vf8;
- typedef AffineSpaceT<LinearSpace3<Vec3<vfloat<16>>>> AffineSpace3vf16;
-
- template<int N> using AffineSpace3vff = AffineSpaceT<LinearSpace3<Vec4<vfloat<N>>>>;
- typedef AffineSpaceT<LinearSpace3<Vec4<vfloat<4>>>> AffineSpace3vfa4;
- typedef AffineSpaceT<LinearSpace3<Vec4<vfloat<8>>>> AffineSpace3vfa8;
- typedef AffineSpaceT<LinearSpace3<Vec4<vfloat<16>>>> AffineSpace3vfa16;
-
- //////////////////////////////////////////////////////////////////////////////
- /// Interpolation
- //////////////////////////////////////////////////////////////////////////////
- template<typename T, typename R>
- __forceinline AffineSpaceT<T> lerp(const AffineSpaceT<T>& M0,
- const AffineSpaceT<T>& M1,
- const R& t)
- {
- return AffineSpaceT<T>(lerp(M0.l,M1.l,t),lerp(M0.p,M1.p,t));
- }
-
- // slerp interprets the 16 floats of the matrix M = D * R * S as components of
- // three matrizes (D, R, S) that are interpolated individually.
- template<typename T> __forceinline AffineSpaceT<LinearSpace3<Vec3<T>>>
- slerp(const AffineSpaceT<LinearSpace3<Vec4<T>>>& M0,
- const AffineSpaceT<LinearSpace3<Vec4<T>>>& M1,
- const T& t)
- {
- QuaternionT<T> q0(M0.p.w, M0.l.vx.w, M0.l.vy.w, M0.l.vz.w);
- QuaternionT<T> q1(M1.p.w, M1.l.vx.w, M1.l.vy.w, M1.l.vz.w);
- QuaternionT<T> q = slerp(q0, q1, t);
-
- AffineSpaceT<LinearSpace3<Vec3<T>>> S = lerp(M0, M1, t);
- AffineSpaceT<LinearSpace3<Vec3<T>>> D(one);
- D.p.x = S.l.vx.y;
- D.p.y = S.l.vx.z;
- D.p.z = S.l.vy.z;
- S.l.vx.y = 0;
- S.l.vx.z = 0;
- S.l.vy.z = 0;
-
- AffineSpaceT<LinearSpace3<Vec3<T>>> R = LinearSpace3<Vec3<T>>(q);
- return D * R * S;
- }
-
- // this is a specialized version for Vec3fa because that does
- // not play along nicely with the other templated Vec3/Vec4 types
- __forceinline AffineSpace3fa slerp(const AffineSpace3ff& M0,
- const AffineSpace3ff& M1,
- const float& t)
- {
- Quaternion3f q0(M0.p.w, M0.l.vx.w, M0.l.vy.w, M0.l.vz.w);
- Quaternion3f q1(M1.p.w, M1.l.vx.w, M1.l.vy.w, M1.l.vz.w);
- Quaternion3f q = slerp(q0, q1, t);
-
- AffineSpace3fa S = lerp(M0, M1, t);
- AffineSpace3fa D(one);
- D.p.x = S.l.vx.y;
- D.p.y = S.l.vx.z;
- D.p.z = S.l.vy.z;
- S.l.vx.y = 0;
- S.l.vx.z = 0;
- S.l.vy.z = 0;
-
- AffineSpace3fa R = LinearSpace3fa(q);
- return D * R * S;
- }
-
- __forceinline AffineSpace3fa quaternionDecompositionToAffineSpace(const AffineSpace3ff& qd)
- {
- // compute affine transform from quaternion decomposition
- Quaternion3f q(qd.p.w, qd.l.vx.w, qd.l.vy.w, qd.l.vz.w);
- AffineSpace3fa M = qd;
- AffineSpace3fa D(one);
- D.p.x = M.l.vx.y;
- D.p.y = M.l.vx.z;
- D.p.z = M.l.vy.z;
- M.l.vx.y = 0;
- M.l.vx.z = 0;
- M.l.vy.z = 0;
- AffineSpace3fa R = LinearSpace3fa(q);
- return D * R * M;
- }
-
- __forceinline void quaternionDecomposition(const AffineSpace3ff& qd, Vec3fa& T, Quaternion3f& q, AffineSpace3fa& S)
- {
- q = Quaternion3f(qd.p.w, qd.l.vx.w, qd.l.vy.w, qd.l.vz.w);
- S = qd;
- T.x = qd.l.vx.y;
- T.y = qd.l.vx.z;
- T.z = qd.l.vy.z;
- S.l.vx.y = 0;
- S.l.vx.z = 0;
- S.l.vy.z = 0;
- }
-
- __forceinline AffineSpace3fx quaternionDecomposition(Vec3fa const& T, Quaternion3f const& q, AffineSpace3fa const& S)
- {
- AffineSpace3ff M = S;
- M.l.vx.w = q.i;
- M.l.vy.w = q.j;
- M.l.vz.w = q.k;
- M.p.w = q.r;
- M.l.vx.y = T.x;
- M.l.vx.z = T.y;
- M.l.vy.z = T.z;
- return M;
- }
-
- struct __aligned(16) QuaternionDecomposition
- {
- float scale_x = 1.f;
- float scale_y = 1.f;
- float scale_z = 1.f;
- float skew_xy = 0.f;
- float skew_xz = 0.f;
- float skew_yz = 0.f;
- float shift_x = 0.f;
- float shift_y = 0.f;
- float shift_z = 0.f;
- float quaternion_r = 1.f;
- float quaternion_i = 0.f;
- float quaternion_j = 0.f;
- float quaternion_k = 0.f;
- float translation_x = 0.f;
- float translation_y = 0.f;
- float translation_z = 0.f;
- };
-
- __forceinline QuaternionDecomposition quaternionDecomposition(AffineSpace3ff const& M)
- {
- QuaternionDecomposition qd;
- qd.scale_x = M.l.vx.x;
- qd.scale_y = M.l.vy.y;
- qd.scale_z = M.l.vz.z;
- qd.shift_x = M.p.x;
- qd.shift_y = M.p.y;
- qd.shift_z = M.p.z;
- qd.translation_x = M.l.vx.y;
- qd.translation_y = M.l.vx.z;
- qd.translation_z = M.l.vy.z;
- qd.skew_xy = M.l.vy.x;
- qd.skew_xz = M.l.vz.x;
- qd.skew_yz = M.l.vz.y;
- qd.quaternion_r = M.p.w;
- qd.quaternion_i = M.l.vx.w;
- qd.quaternion_j = M.l.vy.w;
- qd.quaternion_k = M.l.vz.w;
- return qd;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /*
- * ! Template Specialization for 2D: return matrix for rotation around point
- * (rotation around arbitrarty vector is not meaningful in 2D)
- */
- template<> __forceinline
- AffineSpace2f AffineSpace2f::rotate(const Vec2f& p, const float& r) {
- return translate(+p)*AffineSpace2f(LinearSpace2f::rotate(r))*translate(-p);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Similarity Transform
- //
- // checks, if M is a similarity transformation, i.e if there exists a factor D
- // such that for all x,y: distance(Mx, My) = D * distance(x, y)
- ////////////////////////////////////////////////////////////////////////////////
- __forceinline bool similarityTransform(const AffineSpace3fa& M, float* D)
- {
- if (D) *D = 0.f;
- if (abs(dot(M.l.vx, M.l.vy)) > 1e-5f) return false;
- if (abs(dot(M.l.vx, M.l.vz)) > 1e-5f) return false;
- if (abs(dot(M.l.vy, M.l.vz)) > 1e-5f) return false;
-
- const float D_x = dot(M.l.vx, M.l.vx);
- const float D_y = dot(M.l.vy, M.l.vy);
- const float D_z = dot(M.l.vz, M.l.vz);
-
- if (abs(D_x - D_y) > 1e-5f ||
- abs(D_x - D_z) > 1e-5f ||
- abs(D_y - D_z) > 1e-5f)
- return false;
-
- if (D) *D = sqrtf(D_x);
- return true;
- }
-
- __forceinline void AffineSpace3fa_store_unaligned(const AffineSpace3fa &source, AffineSpace3fa* ptr)
- {
- Vec3fa::storeu(&ptr->l.vx, source.l.vx);
- Vec3fa::storeu(&ptr->l.vy, source.l.vy);
- Vec3fa::storeu(&ptr->l.vz, source.l.vz);
- Vec3fa::storeu(&ptr->p, source.p);
- }
-
- __forceinline AffineSpace3fa AffineSpace3fa_load_unaligned(AffineSpace3fa* ptr)
- {
- AffineSpace3fa space;
- space.l.vx = Vec3fa::loadu(&ptr->l.vx);
- space.l.vy = Vec3fa::loadu(&ptr->l.vy);
- space.l.vz = Vec3fa::loadu(&ptr->l.vz);
- space.p = Vec3fa::loadu(&ptr->p);
- return space;
- }
-
- #undef VectorT
- #undef ScalarT
-}
diff --git a/thirdparty/embree-aarch64/common/math/bbox.h b/thirdparty/embree-aarch64/common/math/bbox.h
deleted file mode 100644
index 29bb13912b..0000000000
--- a/thirdparty/embree-aarch64/common/math/bbox.h
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "vec2.h"
-#include "vec3.h"
-
-namespace embree
-{
- namespace internal {
-
- template <typename T> __forceinline T divideByTwo(const T& v) { return v / T(2); }
- template <> __forceinline float divideByTwo<float>(const float& v) { return v * 0.5f; }
- template <> __forceinline double divideByTwo<double>(const double& v) { return v * 0.5; }
-
- } // namespace internal
- template<typename T>
- struct BBox
- {
- T lower, upper;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline BBox ( ) { }
- template<typename T1>
- __forceinline BBox ( const BBox<T1>& other ) : lower(other.lower), upper(other.upper) {}
- __forceinline BBox& operator=( const BBox& other ) { lower = other.lower; upper = other.upper; return *this; }
-
- __forceinline BBox ( const T& v ) : lower(v), upper(v) {}
- __forceinline BBox ( const T& lower, const T& upper ) : lower(lower), upper(upper) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Extending Bounds
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const BBox& extend(const BBox& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }
- __forceinline const BBox& extend(const T & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }
-
- /*! tests if box is empty */
- __forceinline bool empty() const { for (int i=0; i<T::N; i++) if (lower[i] > upper[i]) return true; return false; }
-
- /*! computes the size of the box */
- __forceinline T size() const { return upper - lower; }
-
- /*! computes the center of the box */
- __forceinline T center() const { return internal::divideByTwo<T>(lower+upper); }
-
- /*! computes twice the center of the box */
- __forceinline T center2() const { return lower+upper; }
-
- /*! merges two boxes */
- __forceinline static const BBox merge (const BBox& a, const BBox& b) {
- return BBox(min(a.lower, b.lower), max(a.upper, b.upper));
- }
-
- /*! enlarge box by some scaling factor */
- __forceinline BBox enlarge_by(const float a) const {
- return BBox(lower - T(a)*abs(lower), upper + T(a)*abs(upper));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline BBox( EmptyTy ) : lower(pos_inf), upper(neg_inf) {}
- __forceinline BBox( FullTy ) : lower(neg_inf), upper(pos_inf) {}
- __forceinline BBox( FalseTy ) : lower(pos_inf), upper(neg_inf) {}
- __forceinline BBox( TrueTy ) : lower(neg_inf), upper(pos_inf) {}
- __forceinline BBox( NegInfTy ): lower(pos_inf), upper(neg_inf) {}
- __forceinline BBox( PosInfTy ): lower(neg_inf), upper(pos_inf) {}
- };
-
- template<> __forceinline bool BBox<float>::empty() const {
- return lower > upper;
- }
-
-#if defined(__SSE__) || defined(__ARM_NEON)
- template<> __forceinline bool BBox<Vec3fa>::empty() const {
- return !all(le_mask(lower,upper));
- }
- template<> __forceinline bool BBox<Vec3fx>::empty() const {
- return !all(le_mask(lower,upper));
- }
-#endif
-
- /*! tests if box is finite */
- __forceinline bool isvalid( const BBox<Vec3fa>& v ) {
- return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)));
- }
-
- /*! tests if box is finite and non-empty*/
- __forceinline bool isvalid_non_empty( const BBox<Vec3fa>& v ) {
- return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)) & le_mask(v.lower,v.upper));
- }
-
- /*! tests if box has finite entries */
- __forceinline bool is_finite( const BBox<Vec3fa>& b) {
- return is_finite(b.lower) && is_finite(b.upper);
- }
-
- /*! test if point contained in box */
- __forceinline bool inside ( const BBox<Vec3fa>& b, const Vec3fa& p ) { return all(ge_mask(p,b.lower) & le_mask(p,b.upper)); }
-
- /*! computes the center of the box */
- template<typename T> __forceinline const T center2(const BBox<T>& box) { return box.lower + box.upper; }
- template<typename T> __forceinline const T center (const BBox<T>& box) { return internal::divideByTwo<T>(center2(box)); }
-
- /*! computes the volume of a bounding box */
- __forceinline float volume ( const BBox<Vec3fa>& b ) { return reduce_mul(b.size()); }
- __forceinline float safeVolume( const BBox<Vec3fa>& b ) { if (b.empty()) return 0.0f; else return volume(b); }
-
- /*! computes the volume of a bounding box */
- __forceinline float volume( const BBox<Vec3f>& b ) { return reduce_mul(b.size()); }
-
- /*! computes the surface area of a bounding box */
- template<typename T> __forceinline const T area( const BBox<Vec2<T> >& b ) { const Vec2<T> d = b.size(); return d.x*d.y; }
-
- template<typename T> __forceinline const T halfArea( const BBox<Vec3<T> >& b ) { return halfArea(b.size()); }
- template<typename T> __forceinline const T area( const BBox<Vec3<T> >& b ) { return T(2)*halfArea(b); }
-
- __forceinline float halfArea( const BBox<Vec3fa>& b ) { return halfArea(b.size()); }
- __forceinline float area( const BBox<Vec3fa>& b ) { return 2.0f*halfArea(b); }
-
- __forceinline float halfArea( const BBox<Vec3fx>& b ) { return halfArea(b.size()); }
- __forceinline float area( const BBox<Vec3fx>& b ) { return 2.0f*halfArea(b); }
-
- template<typename Vec> __forceinline float safeArea( const BBox<Vec>& b ) { if (b.empty()) return 0.0f; else return area(b); }
-
- template<typename T> __forceinline float expectedApproxHalfArea(const BBox<T>& box) {
- return halfArea(box);
- }
-
- /*! merges bounding boxes and points */
- template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const T& b ) { return BBox<T>(min(a.lower, b ), max(a.upper, b )); }
- template<typename T> __forceinline const BBox<T> merge( const T& a, const BBox<T>& b ) { return BBox<T>(min(a , b.lower), max(a , b.upper)); }
- template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(min(a.lower, b.lower), max(a.upper, b.upper)); }
-
- /*! Merges three boxes. */
- template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return merge(a,merge(b,c)); }
-
- /*! Merges four boxes. */
- template<typename T> __forceinline BBox<T> merge(const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d) {
- return merge(merge(a,b),merge(c,d));
- }
-
- /*! Comparison Operators */
- template<typename T> __forceinline bool operator==( const BBox<T>& a, const BBox<T>& b ) { return a.lower == b.lower && a.upper == b.upper; }
- template<typename T> __forceinline bool operator!=( const BBox<T>& a, const BBox<T>& b ) { return a.lower != b.lower || a.upper != b.upper; }
-
- /*! scaling */
- template<typename T> __forceinline BBox<T> operator *( const float& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
- template<typename T> __forceinline BBox<T> operator *( const T& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
-
- /*! translations */
- template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower+b.lower,a.upper+b.upper); }
- template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower-b.lower,a.upper-b.upper); }
- template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower+b ,a.upper+b ); }
- template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower-b ,a.upper-b ); }
-
- /*! extension */
- template<typename T> __forceinline BBox<T> enlarge(const BBox<T>& a, const T& b) { return BBox<T>(a.lower-b, a.upper+b); }
-
- /*! intersect bounding boxes */
- template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(max(a.lower, b.lower), min(a.upper, b.upper)); }
- template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return intersect(a,intersect(b,c)); }
- template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d ) { return intersect(intersect(a,b),intersect(c,d)); }
-
- /*! subtract bounds from each other */
- template<typename T> __forceinline void subtract(const BBox<T>& a, const BBox<T>& b, BBox<T>& c, BBox<T>& d)
- {
- c.lower = a.lower;
- c.upper = min(a.upper,b.lower);
- d.lower = max(a.lower,b.upper);
- d.upper = a.upper;
- }
-
- /*! tests if bounding boxes (and points) are disjoint (empty intersection) */
- template<typename T> __inline bool disjoint( const BBox<T>& a, const BBox<T>& b ) { return intersect(a,b).empty(); }
- template<typename T> __inline bool disjoint( const BBox<T>& a, const T& b ) { return disjoint(a,BBox<T>(b)); }
- template<typename T> __inline bool disjoint( const T& a, const BBox<T>& b ) { return disjoint(BBox<T>(a),b); }
-
- /*! tests if bounding boxes (and points) are conjoint (non-empty intersection) */
- template<typename T> __inline bool conjoint( const BBox<T>& a, const BBox<T>& b ) { return !intersect(a,b).empty(); }
- template<typename T> __inline bool conjoint( const BBox<T>& a, const T& b ) { return conjoint(a,BBox<T>(b)); }
- template<typename T> __inline bool conjoint( const T& a, const BBox<T>& b ) { return conjoint(BBox<T>(a),b); }
-
- /*! subset relation */
- template<typename T> __inline bool subset( const BBox<T>& a, const BBox<T>& b )
- {
- for ( size_t i = 0; i < T::N; i++ ) if ( a.lower[i] < b.lower[i] ) return false;
- for ( size_t i = 0; i < T::N; i++ ) if ( a.upper[i] > b.upper[i] ) return false;
- return true;
- }
-
- template<> __inline bool subset( const BBox<Vec3fa>& a, const BBox<Vec3fa>& b ) {
- return all(ge_mask(a.lower,b.lower)) & all(le_mask(a.upper,b.upper));
- }
-
- template<> __inline bool subset( const BBox<Vec3fx>& a, const BBox<Vec3fx>& b ) {
- return all(ge_mask(a.lower,b.lower)) & all(le_mask(a.upper,b.upper));
- }
-
- /*! blending */
- template<typename T>
- __forceinline BBox<T> lerp(const BBox<T>& b0, const BBox<T>& b1, const float t) {
- return BBox<T>(lerp(b0.lower,b1.lower,t),lerp(b0.upper,b1.upper,t));
- }
-
- /*! output operator */
- template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const BBox<T>& box) {
- return cout << "[" << box.lower << "; " << box.upper << "]";
- }
-
- /*! default template instantiations */
- typedef BBox<float> BBox1f;
- typedef BBox<Vec2f> BBox2f;
- typedef BBox<Vec2fa> BBox2fa;
- typedef BBox<Vec3f> BBox3f;
- typedef BBox<Vec3fa> BBox3fa;
- typedef BBox<Vec3fx> BBox3fx;
- typedef BBox<Vec3ff> BBox3ff;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// SSE / AVX / MIC specializations
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined (__SSE__) || defined(__ARM_NEON)
-#include "../simd/sse.h"
-#endif
-
-#if defined (__AVX__)
-#include "../simd/avx.h"
-#endif
-
-#if defined(__AVX512F__)
-#include "../simd/avx512.h"
-#endif
-
-namespace embree
-{
- template<int N>
- __forceinline BBox<Vec3<vfloat<N>>> transpose(const BBox3fa* bounds);
-
- template<>
- __forceinline BBox<Vec3<vfloat4>> transpose<4>(const BBox3fa* bounds)
- {
- BBox<Vec3<vfloat4>> dest;
-
- transpose((vfloat4&)bounds[0].lower,
- (vfloat4&)bounds[1].lower,
- (vfloat4&)bounds[2].lower,
- (vfloat4&)bounds[3].lower,
- dest.lower.x,
- dest.lower.y,
- dest.lower.z);
-
- transpose((vfloat4&)bounds[0].upper,
- (vfloat4&)bounds[1].upper,
- (vfloat4&)bounds[2].upper,
- (vfloat4&)bounds[3].upper,
- dest.upper.x,
- dest.upper.y,
- dest.upper.z);
-
- return dest;
- }
-
-#if defined(__AVX__)
- template<>
- __forceinline BBox<Vec3<vfloat8>> transpose<8>(const BBox3fa* bounds)
- {
- BBox<Vec3<vfloat8>> dest;
-
- transpose((vfloat4&)bounds[0].lower,
- (vfloat4&)bounds[1].lower,
- (vfloat4&)bounds[2].lower,
- (vfloat4&)bounds[3].lower,
- (vfloat4&)bounds[4].lower,
- (vfloat4&)bounds[5].lower,
- (vfloat4&)bounds[6].lower,
- (vfloat4&)bounds[7].lower,
- dest.lower.x,
- dest.lower.y,
- dest.lower.z);
-
- transpose((vfloat4&)bounds[0].upper,
- (vfloat4&)bounds[1].upper,
- (vfloat4&)bounds[2].upper,
- (vfloat4&)bounds[3].upper,
- (vfloat4&)bounds[4].upper,
- (vfloat4&)bounds[5].upper,
- (vfloat4&)bounds[6].upper,
- (vfloat4&)bounds[7].upper,
- dest.upper.x,
- dest.upper.y,
- dest.upper.z);
-
- return dest;
- }
-#endif
-
- template<int N>
- __forceinline BBox3fa merge(const BBox3fa* bounds);
-
- template<>
- __forceinline BBox3fa merge<4>(const BBox3fa* bounds)
- {
- const Vec3fa lower = min(min(bounds[0].lower,bounds[1].lower),
- min(bounds[2].lower,bounds[3].lower));
- const Vec3fa upper = max(max(bounds[0].upper,bounds[1].upper),
- max(bounds[2].upper,bounds[3].upper));
- return BBox3fa(lower,upper);
- }
-
-#if defined(__AVX__)
- template<>
- __forceinline BBox3fa merge<8>(const BBox3fa* bounds)
- {
- const Vec3fa lower = min(min(min(bounds[0].lower,bounds[1].lower),min(bounds[2].lower,bounds[3].lower)),
- min(min(bounds[4].lower,bounds[5].lower),min(bounds[6].lower,bounds[7].lower)));
- const Vec3fa upper = max(max(max(bounds[0].upper,bounds[1].upper),max(bounds[2].upper,bounds[3].upper)),
- max(max(bounds[4].upper,bounds[5].upper),max(bounds[6].upper,bounds[7].upper)));
- return BBox3fa(lower,upper);
- }
-#endif
-}
-
diff --git a/thirdparty/embree-aarch64/common/math/col3.h b/thirdparty/embree-aarch64/common/math/col3.h
deleted file mode 100644
index f52015fb88..0000000000
--- a/thirdparty/embree-aarch64/common/math/col3.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "math.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// RGB Color Class
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> struct Col3
- {
- T r, g, b;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Col3 ( ) { }
- __forceinline Col3 ( const Col3& other ) { r = other.r; g = other.g; b = other.b; }
- __forceinline Col3& operator=( const Col3& other ) { r = other.r; g = other.g; b = other.b; return *this; }
-
- __forceinline explicit Col3 (const T& v) : r(v), g(v), b(v) {}
- __forceinline Col3 (const T& r, const T& g, const T& b) : r(r), g(g), b(b) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Col3 (ZeroTy) : r(zero) , g(zero) , b(zero) {}
- __forceinline Col3 (OneTy) : r(one) , g(one) , b(one) {}
- __forceinline Col3 (PosInfTy) : r(pos_inf), g(pos_inf), b(pos_inf) {}
- __forceinline Col3 (NegInfTy) : r(neg_inf), g(neg_inf), b(neg_inf) {}
- };
-
- /*! output operator */
- template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Col3<T>& a) {
- return cout << "(" << a.r << ", " << a.g << ", " << a.b << ")";
- }
-
- /*! default template instantiations */
- typedef Col3<uint8_t > Col3uc;
- typedef Col3<float > Col3f;
-}
diff --git a/thirdparty/embree-aarch64/common/math/col4.h b/thirdparty/embree-aarch64/common/math/col4.h
deleted file mode 100644
index 90df293f8e..0000000000
--- a/thirdparty/embree-aarch64/common/math/col4.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "math.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// RGBA Color Class
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> struct Col4
- {
- T r, g, b, a;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Col4 ( ) { }
- __forceinline Col4 ( const Col4& other ) { r = other.r; g = other.g; b = other.b; a = other.a; }
- __forceinline Col4& operator=( const Col4& other ) { r = other.r; g = other.g; b = other.b; a = other.a; return *this; }
-
- __forceinline explicit Col4 (const T& v) : r(v), g(v), b(v), a(v) {}
- __forceinline Col4 (const T& r, const T& g, const T& b, const T& a) : r(r), g(g), b(b), a(a) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Col4 (ZeroTy) : r(zero) , g(zero) , b(zero) , a(zero) {}
- __forceinline Col4 (OneTy) : r(one) , g(one) , b(one) , a(one) {}
- __forceinline Col4 (PosInfTy) : r(pos_inf), g(pos_inf), b(pos_inf), a(pos_inf) {}
- __forceinline Col4 (NegInfTy) : r(neg_inf), g(neg_inf), b(neg_inf), a(neg_inf) {}
- };
-
- /*! output operator */
- template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Col4<T>& a) {
- return cout << "(" << a.r << ", " << a.g << ", " << a.b << ", " << a.a << ")";
- }
-
- /*! default template instantiations */
- typedef Col4<uint8_t > Col4uc;
- typedef Col4<float > Col4f;
-}
diff --git a/thirdparty/embree-aarch64/common/math/color.h b/thirdparty/embree-aarch64/common/math/color.h
deleted file mode 100644
index c3083e4fc0..0000000000
--- a/thirdparty/embree-aarch64/common/math/color.h
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "constants.h"
-#include "col3.h"
-#include "col4.h"
-
-#include "../simd/sse.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// SSE RGBA Color Class
- ////////////////////////////////////////////////////////////////////////////////
-
- struct Color4
- {
- union {
- __m128 m128;
- struct { float r,g,b,a; };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Color4 () {}
- __forceinline Color4 ( const __m128 a ) : m128(a) {}
-
- __forceinline explicit Color4 (const float v) : m128(_mm_set1_ps(v)) {}
- __forceinline Color4 (const float r, const float g, const float b, const float a) : m128(_mm_set_ps(a,b,g,r)) {}
-
- __forceinline explicit Color4 ( const Col3uc& other ) { m128 = _mm_mul_ps(_mm_set_ps(255.0f,other.b,other.g,other.r),_mm_set1_ps(one_over_255)); }
- __forceinline explicit Color4 ( const Col3f& other ) { m128 = _mm_set_ps(1.0f,other.b,other.g,other.r); }
- __forceinline explicit Color4 ( const Col4uc& other ) { m128 = _mm_mul_ps(_mm_set_ps(other.a,other.b,other.g,other.r),_mm_set1_ps(one_over_255)); }
- __forceinline explicit Color4 ( const Col4f& other ) { m128 = _mm_set_ps(other.a,other.b,other.g,other.r); }
-
- __forceinline Color4 ( const Color4& other ) : m128(other.m128) {}
- __forceinline Color4& operator=( const Color4& other ) { m128 = other.m128; return *this; }
-
- __forceinline operator const __m128&() const { return m128; }
- __forceinline operator __m128&() { return m128; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Set
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline void set(Col3f& d) const { d.r = r; d.g = g; d.b = b; }
- __forceinline void set(Col4f& d) const { d.r = r; d.g = g; d.b = b; d.a = a; }
- __forceinline void set(Col3uc& d) const
- {
- vfloat4 s = clamp(vfloat4(m128))*255.0f;
- d.r = (uint8_t)(s[0]);
- d.g = (uint8_t)(s[1]);
- d.b = (uint8_t)(s[2]);
- }
- __forceinline void set(Col4uc& d) const
- {
- vfloat4 s = clamp(vfloat4(m128))*255.0f;
- d.r = (uint8_t)(s[0]);
- d.g = (uint8_t)(s[1]);
- d.b = (uint8_t)(s[2]);
- d.a = (uint8_t)(s[3]);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Color4( ZeroTy ) : m128(_mm_set1_ps(0.0f)) {}
- __forceinline Color4( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
- __forceinline Color4( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
- __forceinline Color4( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// SSE RGB Color Class
- ////////////////////////////////////////////////////////////////////////////////
-
- struct Color
- {
- union {
- __m128 m128;
- struct { float r,g,b; };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Color () {}
- __forceinline Color ( const __m128 a ) : m128(a) {}
-
- __forceinline explicit Color (const float v) : m128(_mm_set1_ps(v)) {}
- __forceinline Color (const float r, const float g, const float b) : m128(_mm_set_ps(0.0f,b,g,r)) {}
-
- __forceinline Color ( const Color& other ) : m128(other.m128) {}
- __forceinline Color& operator=( const Color& other ) { m128 = other.m128; return *this; }
-
- __forceinline Color ( const Color4& other ) : m128(other.m128) {}
- __forceinline Color& operator=( const Color4& other ) { m128 = other.m128; return *this; }
-
- __forceinline operator const __m128&() const { return m128; }
- __forceinline operator __m128&() { return m128; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Set
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline void set(Col3f& d) const { d.r = r; d.g = g; d.b = b; }
- __forceinline void set(Col4f& d) const { d.r = r; d.g = g; d.b = b; d.a = 1.0f; }
- __forceinline void set(Col3uc& d) const
- {
- vfloat4 s = clamp(vfloat4(m128))*255.0f;
- d.r = (uint8_t)(s[0]);
- d.g = (uint8_t)(s[1]);
- d.b = (uint8_t)(s[2]);
- }
- __forceinline void set(Col4uc& d) const
- {
- vfloat4 s = clamp(vfloat4(m128))*255.0f;
- d.r = (uint8_t)(s[0]);
- d.g = (uint8_t)(s[1]);
- d.b = (uint8_t)(s[2]);
- d.a = 255;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Color( ZeroTy ) : m128(_mm_set1_ps(0.0f)) {}
- __forceinline Color( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
- __forceinline Color( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
- __forceinline Color( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const Color operator +( const Color& a ) { return a; }
- __forceinline const Color operator -( const Color& a ) {
- const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
- return _mm_xor_ps(a.m128, mask);
- }
- __forceinline const Color abs ( const Color& a ) {
- const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
- return _mm_and_ps(a.m128, mask);
- }
- __forceinline const Color rcp ( const Color& a )
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- __m128 reciprocal = _mm_rcp_ps(a.m128);
- reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
- reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
- return (const Color)reciprocal;
-#else
-#if defined(__AVX512VL__)
- const Color r = _mm_rcp14_ps(a.m128);
-#else
- const Color r = _mm_rcp_ps(a.m128);
-#endif
- return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
-#endif //defined(__aarch64__) && defined(BUILD_IOS)
- }
- __forceinline const Color rsqrt( const Color& a )
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- __m128 r = _mm_rsqrt_ps(a.m128);
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
- return r;
-#else
-
-#if defined(__AVX512VL__)
- __m128 r = _mm_rsqrt14_ps(a.m128);
-#else
- __m128 r = _mm_rsqrt_ps(a.m128);
-#endif
- return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
-
-#endif //defined(__aarch64__) && defined(BUILD_IOS)
- }
- __forceinline const Color sqrt ( const Color& a ) { return _mm_sqrt_ps(a.m128); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const Color operator +( const Color& a, const Color& b ) { return _mm_add_ps(a.m128, b.m128); }
- __forceinline const Color operator -( const Color& a, const Color& b ) { return _mm_sub_ps(a.m128, b.m128); }
- __forceinline const Color operator *( const Color& a, const Color& b ) { return _mm_mul_ps(a.m128, b.m128); }
- __forceinline const Color operator *( const Color& a, const float b ) { return a * Color(b); }
- __forceinline const Color operator *( const float a, const Color& b ) { return Color(a) * b; }
- __forceinline const Color operator /( const Color& a, const Color& b ) { return a * rcp(b); }
- __forceinline const Color operator /( const Color& a, const float b ) { return a * rcp(b); }
-
- __forceinline const Color min( const Color& a, const Color& b ) { return _mm_min_ps(a.m128,b.m128); }
- __forceinline const Color max( const Color& a, const Color& b ) { return _mm_max_ps(a.m128,b.m128); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const Color operator+=(Color& a, const Color& b) { return a = a + b; }
- __forceinline const Color operator-=(Color& a, const Color& b) { return a = a - b; }
- __forceinline const Color operator*=(Color& a, const Color& b) { return a = a * b; }
- __forceinline const Color operator/=(Color& a, const Color& b) { return a = a / b; }
- __forceinline const Color operator*=(Color& a, const float b ) { return a = a * b; }
- __forceinline const Color operator/=(Color& a, const float b ) { return a = a / b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline float reduce_add(const Color& v) { return v.r+v.g+v.b; }
- __forceinline float reduce_mul(const Color& v) { return v.r*v.g*v.b; }
- __forceinline float reduce_min(const Color& v) { return min(v.r,v.g,v.b); }
- __forceinline float reduce_max(const Color& v) { return max(v.r,v.g,v.b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator ==( const Color& a, const Color& b ) { return (_mm_movemask_ps(_mm_cmpeq_ps (a.m128, b.m128)) & 7) == 7; }
- __forceinline bool operator !=( const Color& a, const Color& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 7) != 0; }
- __forceinline bool operator < ( const Color& a, const Color& b ) {
- if (a.r != b.r) return a.r < b.r;
- if (a.g != b.g) return a.g < b.g;
- if (a.b != b.b) return a.b < b.b;
- return false;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const Color select( bool s, const Color& t, const Color& f ) {
- __m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
- return blendv_ps(f, t, mask);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Special Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- /*! computes luminance of a color */
- __forceinline float luminance (const Color& a) { return madd(0.212671f,a.r,madd(0.715160f,a.g,0.072169f*a.b)); }
-
- /*! output operator */
- __forceinline embree_ostream operator<<(embree_ostream cout, const Color& a) {
- return cout << "(" << a.r << ", " << a.g << ", " << a.b << ")";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/math/constants.cpp b/thirdparty/embree-aarch64/common/math/constants.cpp
deleted file mode 100644
index eeff131664..0000000000
--- a/thirdparty/embree-aarch64/common/math/constants.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#if defined(__aarch64__)
-#include <arm_neon.h>
-#endif
-
-#include "constants.h"
-
-namespace embree
-{
- TrueTy True;
- FalseTy False;
- ZeroTy zero;
- OneTy one;
- NegInfTy neg_inf;
- PosInfTy inf;
- PosInfTy pos_inf;
- NaNTy nan;
- UlpTy ulp;
- PiTy pi;
- OneOverPiTy one_over_pi;
- TwoPiTy two_pi;
- OneOverTwoPiTy one_over_two_pi;
- FourPiTy four_pi;
- OneOverFourPiTy one_over_four_pi;
- StepTy step;
- ReverseStepTy reverse_step;
- EmptyTy empty;
- UndefinedTy undefined;
-
-#if defined(__aarch64__)
-const uint32x4_t movemask_mask = { 1, 2, 4, 8 };
-const uint32x4_t vzero = { 0, 0, 0, 0 };
-const uint32x4_t v0x80000000 = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
-const uint32x4_t v0x7fffffff = { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff };
-const uint32x4_t v000F = { 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF };
-const uint32x4_t v00F0 = { 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000 };
-const uint32x4_t v00FF = { 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF };
-const uint32x4_t v0F00 = { 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000 };
-const uint32x4_t v0F0F = { 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF };
-const uint32x4_t v0FF0 = { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 };
-const uint32x4_t v0FFF = { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
-const uint32x4_t vF000 = { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 };
-const uint32x4_t vF00F = { 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF };
-const uint32x4_t vF0F0 = { 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000 };
-const uint32x4_t vF0FF = { 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF };
-const uint32x4_t vFF00 = { 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 };
-const uint32x4_t vFF0F = { 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF };
-const uint32x4_t vFFF0 = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 };
-const uint32x4_t vFFFF = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
-const uint8x16_t v0022 = {0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11};
-const uint8x16_t v1133 = {4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15};
-const uint8x16_t v0101 = {0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7};
-const float32x4_t vOne = { 1.0f, 1.0f, 1.0f, 1.0f };
-const float32x4_t vmOne = { -1.0f, -1.0f, -1.0f, -1.0f };
-const float32x4_t vInf = { INFINITY, INFINITY, INFINITY, INFINITY };
-const float32x4_t vmInf = { -INFINITY, -INFINITY, -INFINITY, -INFINITY };
-#endif
-
-}
diff --git a/thirdparty/embree-aarch64/common/math/constants.h b/thirdparty/embree-aarch64/common/math/constants.h
deleted file mode 100644
index e80abec80f..0000000000
--- a/thirdparty/embree-aarch64/common/math/constants.h
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-
-#include <limits>
-
-#define _USE_MATH_DEFINES
-#include <math.h> // using cmath causes issues under Windows
-#include <cfloat>
-#include <climits>
-
-// Math constants may not be defined in libcxx + mingw + strict C++ standard
-#if defined(__MINGW32__)
-
-// TODO(LTE): use constexpr
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-#ifndef M_1_PI
-#define M_1_PI 0.31830988618379067154
-#endif
-
-#endif // __MINGW32__
-
-namespace embree
-{
- static MAYBE_UNUSED const float one_over_255 = 1.0f/255.0f;
- static MAYBE_UNUSED const float min_rcp_input = 1E-18f; // for abs(x) >= min_rcp_input the newton raphson rcp calculation does not fail
-
- /* we consider floating point numbers in that range as valid input numbers */
- static MAYBE_UNUSED float FLT_LARGE = 1.844E18f;
-
- struct TrueTy {
- __forceinline operator bool( ) const { return true; }
- };
-
- extern MAYBE_UNUSED TrueTy True;
-
- struct FalseTy {
- __forceinline operator bool( ) const { return false; }
- };
-
- extern MAYBE_UNUSED FalseTy False;
-
- struct ZeroTy
- {
- __forceinline operator double ( ) const { return 0; }
- __forceinline operator float ( ) const { return 0; }
- __forceinline operator long long( ) const { return 0; }
- __forceinline operator unsigned long long( ) const { return 0; }
- __forceinline operator long ( ) const { return 0; }
- __forceinline operator unsigned long ( ) const { return 0; }
- __forceinline operator int ( ) const { return 0; }
- __forceinline operator unsigned int ( ) const { return 0; }
- __forceinline operator short ( ) const { return 0; }
- __forceinline operator unsigned short ( ) const { return 0; }
- __forceinline operator int8_t ( ) const { return 0; }
- __forceinline operator uint8_t ( ) const { return 0; }
- };
-
- extern MAYBE_UNUSED ZeroTy zero;
-
- struct OneTy
- {
- __forceinline operator double ( ) const { return 1; }
- __forceinline operator float ( ) const { return 1; }
- __forceinline operator long long( ) const { return 1; }
- __forceinline operator unsigned long long( ) const { return 1; }
- __forceinline operator long ( ) const { return 1; }
- __forceinline operator unsigned long ( ) const { return 1; }
- __forceinline operator int ( ) const { return 1; }
- __forceinline operator unsigned int ( ) const { return 1; }
- __forceinline operator short ( ) const { return 1; }
- __forceinline operator unsigned short ( ) const { return 1; }
- __forceinline operator int8_t ( ) const { return 1; }
- __forceinline operator uint8_t ( ) const { return 1; }
- };
-
- extern MAYBE_UNUSED OneTy one;
-
- struct NegInfTy
- {
- __forceinline operator double ( ) const { return -std::numeric_limits<double>::infinity(); }
- __forceinline operator float ( ) const { return -std::numeric_limits<float>::infinity(); }
- __forceinline operator long long( ) const { return std::numeric_limits<long long>::min(); }
- __forceinline operator unsigned long long( ) const { return std::numeric_limits<unsigned long long>::min(); }
- __forceinline operator long ( ) const { return std::numeric_limits<long>::min(); }
- __forceinline operator unsigned long ( ) const { return std::numeric_limits<unsigned long>::min(); }
- __forceinline operator int ( ) const { return std::numeric_limits<int>::min(); }
- __forceinline operator unsigned int ( ) const { return std::numeric_limits<unsigned int>::min(); }
- __forceinline operator short ( ) const { return std::numeric_limits<short>::min(); }
- __forceinline operator unsigned short ( ) const { return std::numeric_limits<unsigned short>::min(); }
- __forceinline operator int8_t ( ) const { return std::numeric_limits<int8_t>::min(); }
- __forceinline operator uint8_t ( ) const { return std::numeric_limits<uint8_t>::min(); }
-
- };
-
- extern MAYBE_UNUSED NegInfTy neg_inf;
-
- struct PosInfTy
- {
- __forceinline operator double ( ) const { return std::numeric_limits<double>::infinity(); }
- __forceinline operator float ( ) const { return std::numeric_limits<float>::infinity(); }
- __forceinline operator long long( ) const { return std::numeric_limits<long long>::max(); }
- __forceinline operator unsigned long long( ) const { return std::numeric_limits<unsigned long long>::max(); }
- __forceinline operator long ( ) const { return std::numeric_limits<long>::max(); }
- __forceinline operator unsigned long ( ) const { return std::numeric_limits<unsigned long>::max(); }
- __forceinline operator int ( ) const { return std::numeric_limits<int>::max(); }
- __forceinline operator unsigned int ( ) const { return std::numeric_limits<unsigned int>::max(); }
- __forceinline operator short ( ) const { return std::numeric_limits<short>::max(); }
- __forceinline operator unsigned short ( ) const { return std::numeric_limits<unsigned short>::max(); }
- __forceinline operator int8_t ( ) const { return std::numeric_limits<int8_t>::max(); }
- __forceinline operator uint8_t ( ) const { return std::numeric_limits<uint8_t>::max(); }
- };
-
- extern MAYBE_UNUSED PosInfTy inf;
- extern MAYBE_UNUSED PosInfTy pos_inf;
-
- struct NaNTy
- {
- __forceinline operator double( ) const { return std::numeric_limits<double>::quiet_NaN(); }
- __forceinline operator float ( ) const { return std::numeric_limits<float>::quiet_NaN(); }
- };
-
- extern MAYBE_UNUSED NaNTy nan;
-
- struct UlpTy
- {
- __forceinline operator double( ) const { return std::numeric_limits<double>::epsilon(); }
- __forceinline operator float ( ) const { return std::numeric_limits<float>::epsilon(); }
- };
-
- extern MAYBE_UNUSED UlpTy ulp;
-
- struct PiTy
- {
- __forceinline operator double( ) const { return double(M_PI); }
- __forceinline operator float ( ) const { return float(M_PI); }
- };
-
- extern MAYBE_UNUSED PiTy pi;
-
- struct OneOverPiTy
- {
- __forceinline operator double( ) const { return double(M_1_PI); }
- __forceinline operator float ( ) const { return float(M_1_PI); }
- };
-
- extern MAYBE_UNUSED OneOverPiTy one_over_pi;
-
- struct TwoPiTy
- {
- __forceinline operator double( ) const { return double(2.0*M_PI); }
- __forceinline operator float ( ) const { return float(2.0*M_PI); }
- };
-
- extern MAYBE_UNUSED TwoPiTy two_pi;
-
- struct OneOverTwoPiTy
- {
- __forceinline operator double( ) const { return double(0.5*M_1_PI); }
- __forceinline operator float ( ) const { return float(0.5*M_1_PI); }
- };
-
- extern MAYBE_UNUSED OneOverTwoPiTy one_over_two_pi;
-
- struct FourPiTy
- {
- __forceinline operator double( ) const { return double(4.0*M_PI); }
- __forceinline operator float ( ) const { return float(4.0*M_PI); }
- };
-
- extern MAYBE_UNUSED FourPiTy four_pi;
-
- struct OneOverFourPiTy
- {
- __forceinline operator double( ) const { return double(0.25*M_1_PI); }
- __forceinline operator float ( ) const { return float(0.25*M_1_PI); }
- };
-
- extern MAYBE_UNUSED OneOverFourPiTy one_over_four_pi;
-
- struct StepTy {
- };
-
- extern MAYBE_UNUSED StepTy step;
-
- struct ReverseStepTy {
- };
-
- extern MAYBE_UNUSED ReverseStepTy reverse_step;
-
- struct EmptyTy {
- };
-
- extern MAYBE_UNUSED EmptyTy empty;
-
- struct FullTy {
- };
-
- extern MAYBE_UNUSED FullTy full;
-
- struct UndefinedTy {
- };
-
- extern MAYBE_UNUSED UndefinedTy undefined;
-
-#if defined(__aarch64__)
- extern const uint32x4_t movemask_mask;
- extern const uint32x4_t vzero;
- extern const uint32x4_t v0x80000000;
- extern const uint32x4_t v0x7fffffff;
- extern const uint32x4_t v000F;
- extern const uint32x4_t v00F0;
- extern const uint32x4_t v00FF;
- extern const uint32x4_t v0F00;
- extern const uint32x4_t v0F0F;
- extern const uint32x4_t v0FF0;
- extern const uint32x4_t v0FFF;
- extern const uint32x4_t vF000;
- extern const uint32x4_t vF00F;
- extern const uint32x4_t vF0F0;
- extern const uint32x4_t vF0FF;
- extern const uint32x4_t vFF00;
- extern const uint32x4_t vFF0F;
- extern const uint32x4_t vFFF0;
- extern const uint32x4_t vFFFF;
- extern const uint8x16_t v0022;
- extern const uint8x16_t v1133;
- extern const uint8x16_t v0101;
- extern const float32x4_t vOne;
- extern const float32x4_t vmOne;
- extern const float32x4_t vInf;
- extern const float32x4_t vmInf;
-#endif
-}
diff --git a/thirdparty/embree-aarch64/common/math/interval.h b/thirdparty/embree-aarch64/common/math/interval.h
deleted file mode 100644
index f06478e881..0000000000
--- a/thirdparty/embree-aarch64/common/math/interval.h
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "vec2.h"
-#include "vec3.h"
-#include "bbox.h"
-
-namespace embree
-{
- template<typename V>
- struct Interval
- {
- V lower, upper;
-
- __forceinline Interval() {}
- __forceinline Interval ( const Interval& other ) { lower = other.lower; upper = other.upper; }
- __forceinline Interval& operator=( const Interval& other ) { lower = other.lower; upper = other.upper; return *this; }
-
- __forceinline Interval(const V& a) : lower(a), upper(a) {}
- __forceinline Interval(const V& lower, const V& upper) : lower(lower), upper(upper) {}
- __forceinline Interval(const BBox<V>& a) : lower(a.lower), upper(a.upper) {}
-
- /*! tests if box is empty */
- //__forceinline bool empty() const { return lower > upper; }
-
- /*! computes the size of the interval */
- __forceinline V size() const { return upper - lower; }
-
- __forceinline V center() const { return 0.5f*(lower+upper); }
-
- __forceinline const Interval& extend(const Interval& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }
- __forceinline const Interval& extend(const V & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }
-
- __forceinline friend Interval operator +( const Interval& a, const Interval& b ) {
- return Interval(a.lower+b.lower,a.upper+b.upper);
- }
-
- __forceinline friend Interval operator -( const Interval& a, const Interval& b ) {
- return Interval(a.lower-b.upper,a.upper-b.lower);
- }
-
- __forceinline friend Interval operator -( const Interval& a, const V& b ) {
- return Interval(a.lower-b,a.upper-b);
- }
-
- __forceinline friend Interval operator *( const Interval& a, const Interval& b )
- {
- const V ll = a.lower*b.lower;
- const V lu = a.lower*b.upper;
- const V ul = a.upper*b.lower;
- const V uu = a.upper*b.upper;
- return Interval(min(ll,lu,ul,uu),max(ll,lu,ul,uu));
- }
-
- __forceinline friend Interval merge( const Interval& a, const Interval& b) {
- return Interval(min(a.lower,b.lower),max(a.upper,b.upper));
- }
-
- __forceinline friend Interval merge( const Interval& a, const Interval& b, const Interval& c) {
- return merge(merge(a,b),c);
- }
-
- __forceinline friend Interval merge( const Interval& a, const Interval& b, const Interval& c, const Interval& d) {
- return merge(merge(a,b),merge(c,d));
- }
-
- /*! intersect bounding boxes */
- __forceinline friend const Interval intersect( const Interval& a, const Interval& b ) { return Interval(max(a.lower, b.lower), min(a.upper, b.upper)); }
- __forceinline friend const Interval intersect( const Interval& a, const Interval& b, const Interval& c ) { return intersect(a,intersect(b,c)); }
- __forceinline friend const Interval intersect( const Interval& a, const Interval& b, const Interval& c, const Interval& d ) { return intersect(intersect(a,b),intersect(c,d)); }
-
- friend embree_ostream operator<<(embree_ostream cout, const Interval& a) {
- return cout << "[" << a.lower << ", " << a.upper << "]";
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Interval( EmptyTy ) : lower(pos_inf), upper(neg_inf) {}
- __forceinline Interval( FullTy ) : lower(neg_inf), upper(pos_inf) {}
- };
-
- __forceinline bool isEmpty(const Interval<float>& v) {
- return v.lower > v.upper;
- }
-
- __forceinline vboolx isEmpty(const Interval<vfloatx>& v) {
- return v.lower > v.upper;
- }
-
- /*! subset relation */
- template<typename T> __forceinline bool subset( const Interval<T>& a, const Interval<T>& b ) {
- return (a.lower > b.lower) && (a.upper < b.upper);
- }
-
- template<typename T> __forceinline bool subset( const Vec2<Interval<T>>& a, const Vec2<Interval<T>>& b ) {
- return subset(a.x,b.x) && subset(a.y,b.y);
- }
-
- template<typename T> __forceinline const Vec2<Interval<T>> intersect( const Vec2<Interval<T>>& a, const Vec2<Interval<T>>& b ) {
- return Vec2<Interval<T>>(intersect(a.x,b.x),intersect(a.y,b.y));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Interval<T> select ( bool s, const Interval<T>& t, const Interval<T>& f ) {
- return Interval<T>(select(s,t.lower,f.lower),select(s,t.upper,f.upper));
- }
-
- template<typename T> __forceinline Interval<T> select ( const typename T::Bool& s, const Interval<T>& t, const Interval<T>& f ) {
- return Interval<T>(select(s,t.lower,f.lower),select(s,t.upper,f.upper));
- }
-
- __forceinline int numRoots(const Interval<float>& p0, const Interval<float>& p1)
- {
- float eps = 1E-4f;
- bool neg0 = p0.lower < eps; bool pos0 = p0.upper > -eps;
- bool neg1 = p1.lower < eps; bool pos1 = p1.upper > -eps;
- return (neg0 && pos1) || (pos0 && neg1) || (neg0 && pos0) || (neg1 && pos1);
- }
-
- typedef Interval<float> Interval1f;
- typedef Vec2<Interval<float>> Interval2f;
- typedef Vec3<Interval<float>> Interval3f;
-
-inline void swap(float& a, float& b) { float tmp = a; a = b; b = tmp; }
-
-inline Interval1f shift(const Interval1f& v, float shift) { return Interval1f(v.lower + shift, v.upper + shift); }
-
-#define TWO_PI (2.0*M_PI)
-inline Interval1f sin(Interval1f interval)
-{
- if (interval.upper-interval.lower >= M_PI) { return Interval1f(-1.0, 1.0); }
- if (interval.upper > TWO_PI) { interval = shift(interval, -TWO_PI*floor(interval.upper/TWO_PI)); }
- if (interval.lower < 0) { interval = shift(interval, -TWO_PI*floor(interval.lower/TWO_PI)); }
- float sinLower = sin(interval.lower);
- float sinUpper = sin(interval.upper);
- if (sinLower > sinUpper) swap(sinLower, sinUpper);
- if (interval.lower < M_PI / 2.0 && interval.upper > M_PI / 2.0) sinUpper = 1.0;
- if (interval.lower < 3.0 * M_PI / 2.0 && interval.upper > 3.0 * M_PI / 2.0) sinLower = -1.0;
- return Interval1f(sinLower, sinUpper);
-}
-
-inline Interval1f cos(Interval1f interval)
-{
- if (interval.upper-interval.lower >= M_PI) { return Interval1f(-1.0, 1.0); }
- if (interval.upper > TWO_PI) { interval = shift(interval, -TWO_PI*floor(interval.upper/TWO_PI)); }
- if (interval.lower < 0) { interval = shift(interval, -TWO_PI*floor(interval.lower/TWO_PI)); }
- float cosLower = cos(interval.lower);
- float cosUpper = cos(interval.upper);
- if (cosLower > cosUpper) swap(cosLower, cosUpper);
- if (interval.lower < M_PI && interval.upper > M_PI) cosLower = -1.0;
- return Interval1f(cosLower, cosUpper);
-}
-#undef TWO_PI
-}
diff --git a/thirdparty/embree-aarch64/common/math/lbbox.h b/thirdparty/embree-aarch64/common/math/lbbox.h
deleted file mode 100644
index 95df4a918d..0000000000
--- a/thirdparty/embree-aarch64/common/math/lbbox.h
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bbox.h"
-#include "range.h"
-
-namespace embree
-{
- template<typename T>
- __forceinline std::pair<T,T> globalLinear(const std::pair<T,T>& v, const BBox1f& dt)
- {
- const float rcp_dt_size = float(1.0f)/dt.size();
- const T g0 = lerp(v.first,v.second,-dt.lower*rcp_dt_size);
- const T g1 = lerp(v.first,v.second,(1.0f-dt.lower)*rcp_dt_size);
- return std::make_pair(g0,g1);
- }
-
- template<typename T>
- struct LBBox
- {
- public:
- __forceinline LBBox () {}
-
- template<typename T1>
- __forceinline LBBox ( const LBBox<T1>& other )
- : bounds0(other.bounds0), bounds1(other.bounds1) {}
-
- __forceinline LBBox& operator= ( const LBBox& other ) {
- bounds0 = other.bounds0; bounds1 = other.bounds1; return *this;
- }
-
- __forceinline LBBox (EmptyTy)
- : bounds0(EmptyTy()), bounds1(EmptyTy()) {}
-
- __forceinline explicit LBBox ( const BBox<T>& bounds)
- : bounds0(bounds), bounds1(bounds) { }
-
- __forceinline LBBox ( const BBox<T>& bounds0, const BBox<T>& bounds1)
- : bounds0(bounds0), bounds1(bounds1) { }
-
- LBBox ( const avector<BBox<T>>& bounds )
- {
- assert(bounds.size());
- BBox<T> b0 = bounds.front();
- BBox<T> b1 = bounds.back();
- for (size_t i=1; i<bounds.size()-1; i++) {
- const float f = float(i)/float(bounds.size()-1);
- const BBox<T> bt = lerp(b0,b1,f);
- const T dlower = min(bounds[i].lower-bt.lower,T(zero));
- const T dupper = max(bounds[i].upper-bt.upper,T(zero));
- b0.lower += dlower; b1.lower += dlower;
- b0.upper += dupper; b1.upper += dupper;
- }
- bounds0 = b0;
- bounds1 = b1;
- }
-
- /*! calculates the linear bounds of a primitive for the specified time range */
- template<typename BoundsFunc>
- __forceinline LBBox(const BoundsFunc& bounds, const BBox1f& time_range, float numTimeSegments)
- {
- const float lower = time_range.lower*numTimeSegments;
- const float upper = time_range.upper*numTimeSegments;
- const float ilowerf = floor(lower);
- const float iupperf = ceil(upper);
- const int ilower = (int)ilowerf;
- const int iupper = (int)iupperf;
-
- const BBox<T> blower0 = bounds(ilower);
- const BBox<T> bupper1 = bounds(iupper);
-
- if (iupper-ilower == 1) {
- bounds0 = lerp(blower0, bupper1, lower-ilowerf);
- bounds1 = lerp(bupper1, blower0, iupperf-upper);
- return;
- }
-
- const BBox<T> blower1 = bounds(ilower+1);
- const BBox<T> bupper0 = bounds(iupper-1);
- BBox<T> b0 = lerp(blower0, blower1, lower-ilowerf);
- BBox<T> b1 = lerp(bupper1, bupper0, iupperf-upper);
-
- for (int i = ilower+1; i < iupper; i++)
- {
- const float f = (float(i)/numTimeSegments - time_range.lower) / time_range.size();
- const BBox<T> bt = lerp(b0, b1, f);
- const BBox<T> bi = bounds(i);
- const T dlower = min(bi.lower-bt.lower, T(zero));
- const T dupper = max(bi.upper-bt.upper, T(zero));
- b0.lower += dlower; b1.lower += dlower;
- b0.upper += dupper; b1.upper += dupper;
- }
-
- bounds0 = b0;
- bounds1 = b1;
- }
-
- /*! calculates the linear bounds of a primitive for the specified time range */
- template<typename BoundsFunc>
- __forceinline LBBox(const BoundsFunc& bounds, const BBox1f& time_range_in, const BBox1f& geom_time_range, float geom_time_segments)
- {
- /* normalize global time_range_in to local geom_time_range */
- const BBox1f time_range((time_range_in.lower-geom_time_range.lower)/geom_time_range.size(),
- (time_range_in.upper-geom_time_range.lower)/geom_time_range.size());
-
- const float lower = time_range.lower*geom_time_segments;
- const float upper = time_range.upper*geom_time_segments;
- const float ilowerf = floor(lower);
- const float iupperf = ceil(upper);
- const float ilowerfc = max(0.0f,ilowerf);
- const float iupperfc = min(iupperf,geom_time_segments);
- const int ilowerc = (int)ilowerfc;
- const int iupperc = (int)iupperfc;
- assert(iupperc-ilowerc > 0);
-
- /* this larger iteration range guarantees that we process borders of geom_time_range is (partially) inside time_range_in */
- const int ilower_iter = max(-1,(int)ilowerf);
- const int iupper_iter = min((int)iupperf,(int)geom_time_segments+1);
-
- const BBox<T> blower0 = bounds(ilowerc);
- const BBox<T> bupper1 = bounds(iupperc);
- if (iupper_iter-ilower_iter == 1) {
- bounds0 = lerp(blower0, bupper1, max(0.0f,lower-ilowerfc));
- bounds1 = lerp(bupper1, blower0, max(0.0f,iupperfc-upper));
- return;
- }
-
- const BBox<T> blower1 = bounds(ilowerc+1);
- const BBox<T> bupper0 = bounds(iupperc-1);
- BBox<T> b0 = lerp(blower0, blower1, max(0.0f,lower-ilowerfc));
- BBox<T> b1 = lerp(bupper1, bupper0, max(0.0f,iupperfc-upper));
-
- for (int i = ilower_iter+1; i < iupper_iter; i++)
- {
- const float f = (float(i)/geom_time_segments - time_range.lower) / time_range.size();
- const BBox<T> bt = lerp(b0, b1, f);
- const BBox<T> bi = bounds(i);
- const T dlower = min(bi.lower-bt.lower, T(zero));
- const T dupper = max(bi.upper-bt.upper, T(zero));
- b0.lower += dlower; b1.lower += dlower;
- b0.upper += dupper; b1.upper += dupper;
- }
-
- bounds0 = b0;
- bounds1 = b1;
- }
-
- /*! calculates the linear bounds of a primitive for the specified time range */
- template<typename BoundsFunc>
- __forceinline LBBox(const BoundsFunc& bounds, const range<int>& time_range, int numTimeSegments)
- {
- const int ilower = time_range.begin();
- const int iupper = time_range.end();
-
- BBox<T> b0 = bounds(ilower);
- BBox<T> b1 = bounds(iupper);
-
- if (iupper-ilower == 1)
- {
- bounds0 = b0;
- bounds1 = b1;
- return;
- }
-
- for (int i = ilower+1; i<iupper; i++)
- {
- const float f = float(i - time_range.begin()) / float(time_range.size());
- const BBox<T> bt = lerp(b0, b1, f);
- const BBox<T> bi = bounds(i);
- const T dlower = min(bi.lower-bt.lower, T(zero));
- const T dupper = max(bi.upper-bt.upper, T(zero));
- b0.lower += dlower; b1.lower += dlower;
- b0.upper += dupper; b1.upper += dupper;
- }
-
- bounds0 = b0;
- bounds1 = b1;
- }
-
- public:
-
- __forceinline bool empty() const {
- return bounds().empty();
- }
-
- __forceinline BBox<T> bounds () const {
- return merge(bounds0,bounds1);
- }
-
- __forceinline BBox<T> interpolate( const float t ) const {
- return lerp(bounds0,bounds1,t);
- }
-
- __forceinline LBBox<T> interpolate( const BBox1f& dt ) const {
- return LBBox<T>(interpolate(dt.lower),interpolate(dt.upper));
- }
-
- __forceinline void extend( const LBBox& other ) {
- bounds0.extend(other.bounds0);
- bounds1.extend(other.bounds1);
- }
-
- __forceinline float expectedHalfArea() const;
-
- __forceinline float expectedHalfArea(const BBox1f& dt) const {
- return interpolate(dt).expectedHalfArea();
- }
-
- __forceinline float expectedApproxHalfArea() const {
- return 0.5f*(halfArea(bounds0) + halfArea(bounds1));
- }
-
- /* calculates bounds for [0,1] time range from bounds in dt time range */
- __forceinline LBBox global(const BBox1f& dt) const
- {
- const float rcp_dt_size = 1.0f/dt.size();
- const BBox<T> b0 = interpolate(-dt.lower*rcp_dt_size);
- const BBox<T> b1 = interpolate((1.0f-dt.lower)*rcp_dt_size);
- return LBBox(b0,b1);
- }
-
- /*! Comparison Operators */
- //template<typename TT> friend __forceinline bool operator==( const LBBox<TT>& a, const LBBox<TT>& b ) { return a.bounds0 == b.bounds0 && a.bounds1 == b.bounds1; }
- //template<typename TT> friend __forceinline bool operator!=( const LBBox<TT>& a, const LBBox<TT>& b ) { return a.bounds0 != b.bounds0 || a.bounds1 != b.bounds1; }
- friend __forceinline bool operator==( const LBBox& a, const LBBox& b ) { return a.bounds0 == b.bounds0 && a.bounds1 == b.bounds1; }
- friend __forceinline bool operator!=( const LBBox& a, const LBBox& b ) { return a.bounds0 != b.bounds0 || a.bounds1 != b.bounds1; }
-
- /*! output operator */
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const LBBox& box) {
- return cout << "LBBox { " << box.bounds0 << "; " << box.bounds1 << " }";
- }
-
- public:
- BBox<T> bounds0, bounds1;
- };
-
- /*! tests if box is finite */
- template<typename T>
- __forceinline bool isvalid( const LBBox<T>& v ) {
- return isvalid(v.bounds0) && isvalid(v.bounds1);
- }
-
- template<typename T>
- __forceinline bool isvalid_non_empty( const LBBox<T>& v ) {
- return isvalid_non_empty(v.bounds0) && isvalid_non_empty(v.bounds1);
- }
-
- template<typename T>
- __forceinline T expectedArea(const T& a0, const T& a1, const T& b0, const T& b1)
- {
- const T da = a1-a0;
- const T db = b1-b0;
- return a0*b0+(a0*db+da*b0)*T(0.5f) + da*db*T(1.0f/3.0f);
- }
-
- template<> __forceinline float LBBox<Vec3fa>::expectedHalfArea() const
- {
- const Vec3fa d0 = bounds0.size();
- const Vec3fa d1 = bounds1.size();
- return reduce_add(expectedArea(Vec3fa(d0.x,d0.y,d0.z),
- Vec3fa(d1.x,d1.y,d1.z),
- Vec3fa(d0.y,d0.z,d0.x),
- Vec3fa(d1.y,d1.z,d1.x)));
- }
-
- template<typename T>
- __forceinline float expectedApproxHalfArea(const LBBox<T>& box) {
- return box.expectedApproxHalfArea();
- }
-
- template<typename T>
- __forceinline LBBox<T> merge(const LBBox<T>& a, const LBBox<T>& b) {
- return LBBox<T>(merge(a.bounds0, b.bounds0), merge(a.bounds1, b.bounds1));
- }
-
- /*! subset relation */
- template<typename T> __inline bool subset( const LBBox<T>& a, const LBBox<T>& b ) {
- return subset(a.bounds0,b.bounds0) && subset(a.bounds1,b.bounds1);
- }
-
- /*! default template instantiations */
- typedef LBBox<float> LBBox1f;
- typedef LBBox<Vec2f> LBBox2f;
- typedef LBBox<Vec3f> LBBox3f;
- typedef LBBox<Vec3fa> LBBox3fa;
- typedef LBBox<Vec3fx> LBBox3fx;
-}
diff --git a/thirdparty/embree-aarch64/common/math/linearspace2.h b/thirdparty/embree-aarch64/common/math/linearspace2.h
deleted file mode 100644
index b9a382962c..0000000000
--- a/thirdparty/embree-aarch64/common/math/linearspace2.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "vec2.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// 2D Linear Transform (2x2 Matrix)
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> struct LinearSpace2
- {
- typedef T Vector;
- typedef typename T::Scalar Scalar;
-
- /*! default matrix constructor */
- __forceinline LinearSpace2 ( ) {}
- __forceinline LinearSpace2 ( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; }
- __forceinline LinearSpace2& operator=( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; return *this; }
-
- template<typename L1> __forceinline LinearSpace2( const LinearSpace2<L1>& s ) : vx(s.vx), vy(s.vy) {}
-
- /*! matrix construction from column vectors */
- __forceinline LinearSpace2(const Vector& vx, const Vector& vy)
- : vx(vx), vy(vy) {}
-
- /*! matrix construction from row mayor data */
- __forceinline LinearSpace2(const Scalar& m00, const Scalar& m01,
- const Scalar& m10, const Scalar& m11)
- : vx(m00,m10), vy(m01,m11) {}
-
- /*! compute the determinant of the matrix */
- __forceinline const Scalar det() const { return vx.x*vy.y - vx.y*vy.x; }
-
- /*! compute adjoint matrix */
- __forceinline const LinearSpace2 adjoint() const { return LinearSpace2(vy.y,-vy.x,-vx.y,vx.x); }
-
- /*! compute inverse matrix */
- __forceinline const LinearSpace2 inverse() const { return adjoint()/det(); }
-
- /*! compute transposed matrix */
- __forceinline const LinearSpace2 transposed() const { return LinearSpace2(vx.x,vx.y,vy.x,vy.y); }
-
- /*! returns first row of matrix */
- __forceinline Vector row0() const { return Vector(vx.x,vy.x); }
-
- /*! returns second row of matrix */
- __forceinline Vector row1() const { return Vector(vx.y,vy.y); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline LinearSpace2( ZeroTy ) : vx(zero), vy(zero) {}
- __forceinline LinearSpace2( OneTy ) : vx(one, zero), vy(zero, one) {}
-
- /*! return matrix for scaling */
- static __forceinline LinearSpace2 scale(const Vector& s) {
- return LinearSpace2(s.x, 0,
- 0 , s.y);
- }
-
- /*! return matrix for rotation */
- static __forceinline LinearSpace2 rotate(const Scalar& r) {
- Scalar s = sin(r), c = cos(r);
- return LinearSpace2(c, -s,
- s, c);
- }
-
- /*! return closest orthogonal matrix (i.e. a general rotation including reflection) */
- LinearSpace2 orthogonal() const
- {
- LinearSpace2 m = *this;
-
- // mirrored?
- Scalar mirror(one);
- if (m.det() < Scalar(zero)) {
- m.vx = -m.vx;
- mirror = -mirror;
- }
-
- // rotation
- for (int i = 0; i < 99; i++) {
- const LinearSpace2 m_next = 0.5 * (m + m.transposed().inverse());
- const LinearSpace2 d = m_next - m;
- m = m_next;
- // norm^2 of difference small enough?
- if (max(dot(d.vx, d.vx), dot(d.vy, d.vy)) < 1e-8)
- break;
- }
-
- // rotation * mirror_x
- return LinearSpace2(mirror*m.vx, m.vy);
- }
-
- public:
-
- /*! the column vectors of the matrix */
- Vector vx,vy;
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- // Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline LinearSpace2<T> operator -( const LinearSpace2<T>& a ) { return LinearSpace2<T>(-a.vx,-a.vy); }
- template<typename T> __forceinline LinearSpace2<T> operator +( const LinearSpace2<T>& a ) { return LinearSpace2<T>(+a.vx,+a.vy); }
- template<typename T> __forceinline LinearSpace2<T> rcp ( const LinearSpace2<T>& a ) { return a.inverse(); }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline LinearSpace2<T> operator +( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx+b.vx,a.vy+b.vy); }
- template<typename T> __forceinline LinearSpace2<T> operator -( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx-b.vx,a.vy-b.vy); }
-
- template<typename T> __forceinline LinearSpace2<T> operator*(const typename T::Scalar & a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
- template<typename T> __forceinline T operator*(const LinearSpace2<T>& a, const T & b) { return b.x*a.vx + b.y*a.vy; }
- template<typename T> __forceinline LinearSpace2<T> operator*(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
-
- template<typename T> __forceinline LinearSpace2<T> operator/(const LinearSpace2<T>& a, const typename T::Scalar & b) { return LinearSpace2<T>(a.vx/b, a.vy/b); }
- template<typename T> __forceinline LinearSpace2<T> operator/(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return a * rcp(b); }
-
- template<typename T> __forceinline LinearSpace2<T>& operator *=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a * b; }
- template<typename T> __forceinline LinearSpace2<T>& operator /=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a / b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline bool operator ==( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx == b.vx && a.vy == b.vy; }
- template<typename T> __forceinline bool operator !=( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx != b.vx || a.vy != b.vy; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> static embree_ostream operator<<(embree_ostream cout, const LinearSpace2<T>& m) {
- return cout << "{ vx = " << m.vx << ", vy = " << m.vy << "}";
- }
-
- /*! Shortcuts for common linear spaces. */
- typedef LinearSpace2<Vec2f> LinearSpace2f;
- typedef LinearSpace2<Vec2fa> LinearSpace2fa;
-}
diff --git a/thirdparty/embree-aarch64/common/math/linearspace3.h b/thirdparty/embree-aarch64/common/math/linearspace3.h
deleted file mode 100644
index 12b5bb776b..0000000000
--- a/thirdparty/embree-aarch64/common/math/linearspace3.h
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "vec3.h"
-#include "quaternion.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// 3D Linear Transform (3x3 Matrix)
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> struct LinearSpace3
- {
- typedef T Vector;
- typedef typename T::Scalar Scalar;
-
- /*! default matrix constructor */
- __forceinline LinearSpace3 ( ) {}
- __forceinline LinearSpace3 ( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; }
- __forceinline LinearSpace3& operator=( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; return *this; }
-
- template<typename L1> __forceinline LinearSpace3( const LinearSpace3<L1>& s ) : vx(s.vx), vy(s.vy), vz(s.vz) {}
-
- /*! matrix construction from column vectors */
- __forceinline LinearSpace3(const Vector& vx, const Vector& vy, const Vector& vz)
- : vx(vx), vy(vy), vz(vz) {}
-
- /*! construction from quaternion */
- __forceinline LinearSpace3( const QuaternionT<Scalar>& q )
- : vx((q.r*q.r + q.i*q.i - q.j*q.j - q.k*q.k), 2.0f*(q.i*q.j + q.r*q.k), 2.0f*(q.i*q.k - q.r*q.j))
- , vy(2.0f*(q.i*q.j - q.r*q.k), (q.r*q.r - q.i*q.i + q.j*q.j - q.k*q.k), 2.0f*(q.j*q.k + q.r*q.i))
- , vz(2.0f*(q.i*q.k + q.r*q.j), 2.0f*(q.j*q.k - q.r*q.i), (q.r*q.r - q.i*q.i - q.j*q.j + q.k*q.k)) {}
-
- /*! matrix construction from row mayor data */
- __forceinline LinearSpace3(const Scalar& m00, const Scalar& m01, const Scalar& m02,
- const Scalar& m10, const Scalar& m11, const Scalar& m12,
- const Scalar& m20, const Scalar& m21, const Scalar& m22)
- : vx(m00,m10,m20), vy(m01,m11,m21), vz(m02,m12,m22) {}
-
- /*! compute the determinant of the matrix */
- __forceinline const Scalar det() const { return dot(vx,cross(vy,vz)); }
-
- /*! compute adjoint matrix */
- __forceinline const LinearSpace3 adjoint() const { return LinearSpace3(cross(vy,vz),cross(vz,vx),cross(vx,vy)).transposed(); }
-
- /*! compute inverse matrix */
- __forceinline const LinearSpace3 inverse() const { return adjoint()/det(); }
-
- /*! compute transposed matrix */
- __forceinline const LinearSpace3 transposed() const { return LinearSpace3(vx.x,vx.y,vx.z,vy.x,vy.y,vy.z,vz.x,vz.y,vz.z); }
-
- /*! returns first row of matrix */
- __forceinline Vector row0() const { return Vector(vx.x,vy.x,vz.x); }
-
- /*! returns second row of matrix */
- __forceinline Vector row1() const { return Vector(vx.y,vy.y,vz.y); }
-
- /*! returns third row of matrix */
- __forceinline Vector row2() const { return Vector(vx.z,vy.z,vz.z); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline LinearSpace3( ZeroTy ) : vx(zero), vy(zero), vz(zero) {}
- __forceinline LinearSpace3( OneTy ) : vx(one, zero, zero), vy(zero, one, zero), vz(zero, zero, one) {}
-
- /*! return matrix for scaling */
- static __forceinline LinearSpace3 scale(const Vector& s) {
- return LinearSpace3(s.x, 0, 0,
- 0 , s.y, 0,
- 0 , 0, s.z);
- }
-
- /*! return matrix for rotation around arbitrary axis */
- static __forceinline LinearSpace3 rotate(const Vector& _u, const Scalar& r) {
- Vector u = normalize(_u);
- Scalar s = sin(r), c = cos(r);
- return LinearSpace3(u.x*u.x+(1-u.x*u.x)*c, u.x*u.y*(1-c)-u.z*s, u.x*u.z*(1-c)+u.y*s,
- u.x*u.y*(1-c)+u.z*s, u.y*u.y+(1-u.y*u.y)*c, u.y*u.z*(1-c)-u.x*s,
- u.x*u.z*(1-c)-u.y*s, u.y*u.z*(1-c)+u.x*s, u.z*u.z+(1-u.z*u.z)*c);
- }
-
- public:
-
- /*! the column vectors of the matrix */
- Vector vx,vy,vz;
- };
-
- /*! compute transposed matrix */
- template<> __forceinline const LinearSpace3<Vec3fa> LinearSpace3<Vec3fa>::transposed() const {
- vfloat4 rx,ry,rz; transpose((vfloat4&)vx,(vfloat4&)vy,(vfloat4&)vz,vfloat4(zero),rx,ry,rz);
- return LinearSpace3<Vec3fa>(Vec3fa(rx),Vec3fa(ry),Vec3fa(rz));
- }
-
- template<typename T>
- __forceinline const LinearSpace3<T> transposed(const LinearSpace3<T>& xfm) {
- return xfm.transposed();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline LinearSpace3<T> operator -( const LinearSpace3<T>& a ) { return LinearSpace3<T>(-a.vx,-a.vy,-a.vz); }
- template<typename T> __forceinline LinearSpace3<T> operator +( const LinearSpace3<T>& a ) { return LinearSpace3<T>(+a.vx,+a.vy,+a.vz); }
- template<typename T> __forceinline LinearSpace3<T> rcp ( const LinearSpace3<T>& a ) { return a.inverse(); }
-
- /* constructs a coordinate frame form a normalized normal */
- template<typename T> __forceinline LinearSpace3<T> frame(const T& N)
- {
- const T dx0(0,N.z,-N.y);
- const T dx1(-N.z,0,N.x);
- const T dx = normalize(select(dot(dx0,dx0) > dot(dx1,dx1),dx0,dx1));
- const T dy = normalize(cross(N,dx));
- return LinearSpace3<T>(dx,dy,N);
- }
-
- /* constructs a coordinate frame from a normal and approximate x-direction */
- template<typename T> __forceinline LinearSpace3<T> frame(const T& N, const T& dxi)
- {
- if (abs(dot(dxi,N)) > 0.99f) return frame(N); // fallback in case N and dxi are very parallel
- const T dx = normalize(cross(dxi,N));
- const T dy = normalize(cross(N,dx));
- return LinearSpace3<T>(dx,dy,N);
- }
-
- /* clamps linear space to range -1 to +1 */
- template<typename T> __forceinline LinearSpace3<T> clamp(const LinearSpace3<T>& space) {
- return LinearSpace3<T>(clamp(space.vx,T(-1.0f),T(1.0f)),
- clamp(space.vy,T(-1.0f),T(1.0f)),
- clamp(space.vz,T(-1.0f),T(1.0f)));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline LinearSpace3<T> operator +( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return LinearSpace3<T>(a.vx+b.vx,a.vy+b.vy,a.vz+b.vz); }
- template<typename T> __forceinline LinearSpace3<T> operator -( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return LinearSpace3<T>(a.vx-b.vx,a.vy-b.vy,a.vz-b.vz); }
-
- template<typename T> __forceinline LinearSpace3<T> operator*(const typename T::Scalar & a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
- template<typename T> __forceinline T operator*(const LinearSpace3<T>& a, const T & b) { return madd(T(b.x),a.vx,madd(T(b.y),a.vy,T(b.z)*a.vz)); }
- template<typename T> __forceinline LinearSpace3<T> operator*(const LinearSpace3<T>& a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
-
- template<typename T> __forceinline LinearSpace3<T> operator/(const LinearSpace3<T>& a, const typename T::Scalar & b) { return LinearSpace3<T>(a.vx/b, a.vy/b, a.vz/b); }
- template<typename T> __forceinline LinearSpace3<T> operator/(const LinearSpace3<T>& a, const LinearSpace3<T>& b) { return a * rcp(b); }
-
- template<typename T> __forceinline LinearSpace3<T>& operator *=( LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a = a * b; }
- template<typename T> __forceinline LinearSpace3<T>& operator /=( LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a = a / b; }
-
- template<typename T> __forceinline T xfmPoint (const LinearSpace3<T>& s, const T & a) { return madd(T(a.x),s.vx,madd(T(a.y),s.vy,T(a.z)*s.vz)); }
- template<typename T> __forceinline T xfmVector(const LinearSpace3<T>& s, const T & a) { return madd(T(a.x),s.vx,madd(T(a.y),s.vy,T(a.z)*s.vz)); }
- template<typename T> __forceinline T xfmNormal(const LinearSpace3<T>& s, const T & a) { return xfmVector(s.inverse().transposed(),a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline bool operator ==( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx == b.vx && a.vy == b.vy && a.vz == b.vz; }
- template<typename T> __forceinline bool operator !=( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx != b.vx || a.vy != b.vy || a.vz != b.vz; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline LinearSpace3<T> select ( const typename T::Scalar::Bool& s, const LinearSpace3<T>& t, const LinearSpace3<T>& f ) {
- return LinearSpace3<T>(select(s,t.vx,f.vx),select(s,t.vy,f.vy),select(s,t.vz,f.vz));
- }
-
- /*! blending */
- template<typename T>
- __forceinline LinearSpace3<T> lerp(const LinearSpace3<T>& l0, const LinearSpace3<T>& l1, const float t)
- {
- return LinearSpace3<T>(lerp(l0.vx,l1.vx,t),
- lerp(l0.vy,l1.vy,t),
- lerp(l0.vz,l1.vz,t));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> static embree_ostream operator<<(embree_ostream cout, const LinearSpace3<T>& m) {
- return cout << "{ vx = " << m.vx << ", vy = " << m.vy << ", vz = " << m.vz << "}";
- }
-
- /*! Shortcuts for common linear spaces. */
- typedef LinearSpace3<Vec3f> LinearSpace3f;
- typedef LinearSpace3<Vec3fa> LinearSpace3fa;
- typedef LinearSpace3<Vec3fx> LinearSpace3fx;
- typedef LinearSpace3<Vec3ff> LinearSpace3ff;
-
- template<int N> using LinearSpace3vf = LinearSpace3<Vec3<vfloat<N>>>;
- typedef LinearSpace3<Vec3<vfloat<4>>> LinearSpace3vf4;
- typedef LinearSpace3<Vec3<vfloat<8>>> LinearSpace3vf8;
- typedef LinearSpace3<Vec3<vfloat<16>>> LinearSpace3vf16;
-
- /*! blending */
- template<typename T, typename S>
- __forceinline LinearSpace3<T> lerp(const LinearSpace3<T>& l0,
- const LinearSpace3<T>& l1,
- const S& t)
- {
- return LinearSpace3<T>(lerp(l0.vx,l1.vx,t),
- lerp(l0.vy,l1.vy,t),
- lerp(l0.vz,l1.vz,t));
- }
-
-}
diff --git a/thirdparty/embree-aarch64/common/math/math.h b/thirdparty/embree-aarch64/common/math/math.h
deleted file mode 100644
index 6d54abd44d..0000000000
--- a/thirdparty/embree-aarch64/common/math/math.h
+++ /dev/null
@@ -1,451 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/intrinsics.h"
-#include "constants.h"
-#include <cmath>
-
-#if defined(__ARM_NEON)
-#include "SSE2NEON.h"
-#if defined(NEON_AVX2_EMULATION)
-#include "AVX2NEON.h"
-#endif
-#else
-#include <emmintrin.h>
-#include <xmmintrin.h>
-#include <immintrin.h>
-#endif
-
-#if defined(__WIN32__) && !defined(__MINGW32__)
-#if (__MSV_VER <= 1700)
-namespace std
-{
- __forceinline bool isinf ( const float x ) { return _finite(x) == 0; }
- __forceinline bool isnan ( const float x ) { return _isnan(x) != 0; }
- __forceinline bool isfinite (const float x) { return _finite(x) != 0; }
-}
-#endif
-#endif
-
-namespace embree
-{
- __forceinline bool isvalid ( const float& v ) {
- return (v > -FLT_LARGE) & (v < +FLT_LARGE);
- }
-
- __forceinline int cast_f2i(float f) {
- union { float f; int i; } v; v.f = f; return v.i;
- }
-
- __forceinline float cast_i2f(int i) {
- union { float f; int i; } v; v.i = i; return v.f;
- }
-
- __forceinline int toInt (const float& a) { return int(a); }
- __forceinline float toFloat(const int& a) { return float(a); }
-
-#if defined(__WIN32__) && !defined(__MINGW32__)
- __forceinline bool finite ( const float x ) { return _finite(x) != 0; }
-#endif
-
- __forceinline float sign ( const float x ) { return x<0?-1.0f:1.0f; }
- __forceinline float sqr ( const float x ) { return x*x; }
-
- __forceinline float rcp ( const float x )
- {
-#if defined(__aarch64__)
- // Move scalar to vector register and do rcp.
- __m128 a;
- a[0] = x;
- float32x4_t reciprocal = vrecpeq_f32(a);
- reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal);
- reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal);
- return reciprocal[0];
-#else
-
- const __m128 a = _mm_set_ss(x);
-
-#if defined(__AVX512VL__)
- const __m128 r = _mm_rcp14_ss(_mm_set_ss(0.0f),a);
-#else
- const __m128 r = _mm_rcp_ss(a);
-#endif
-
-#if defined(__AVX2__)
- return _mm_cvtss_f32(_mm_mul_ss(r,_mm_fnmadd_ss(r, a, _mm_set_ss(2.0f))));
-#else
- return _mm_cvtss_f32(_mm_mul_ss(r,_mm_sub_ss(_mm_set_ss(2.0f), _mm_mul_ss(r, a))));
-#endif
-
-#endif //defined(__aarch64__)
- }
-
- __forceinline float signmsk ( const float x ) {
-#if defined(__aarch64__)
- // FP and Neon shares same vector register in arm64
- __m128 a;
- __m128i b;
- a[0] = x;
- b[0] = 0x80000000;
- a = _mm_and_ps(a, vreinterpretq_f32_s32(b));
- return a[0];
-#else
- return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
-#endif
- }
- __forceinline float xorf( const float x, const float y ) {
-#if defined(__aarch64__)
- // FP and Neon shares same vector register in arm64
- __m128 a;
- __m128 b;
- a[0] = x;
- b[0] = y;
- a = _mm_xor_ps(a, b);
- return a[0];
-#else
- return _mm_cvtss_f32(_mm_xor_ps(_mm_set_ss(x),_mm_set_ss(y)));
-#endif
- }
- __forceinline float andf( const float x, const unsigned y ) {
-#if defined(__aarch64__)
- // FP and Neon shares same vector register in arm64
- __m128 a;
- __m128i b;
- a[0] = x;
- b[0] = y;
- a = _mm_and_ps(a, vreinterpretq_f32_s32(b));
- return a[0];
-#else
- return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(y))));
-#endif
- }
- __forceinline float rsqrt( const float x )
- {
-#if defined(__aarch64__)
- // FP and Neon shares same vector register in arm64
- __m128 a;
- a[0] = x;
- __m128 value = _mm_rsqrt_ps(a);
- value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(a, value), value));
- value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(a, value), value));
- return value[0];
-#else
-
- const __m128 a = _mm_set_ss(x);
-#if defined(__AVX512VL__)
- const __m128 r = _mm_rsqrt14_ss(_mm_set_ss(0.0f),a);
-#else
- const __m128 r = _mm_rsqrt_ss(a);
-#endif
- const __m128 c = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r),
- _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)));
- return _mm_cvtss_f32(c);
-#endif
- }
-
-#if defined(__WIN32__) && (__MSC_VER <= 1700) && !defined(__MINGW32__)
- __forceinline float nextafter(float x, float y) { if ((x<y) == (x>0)) return x*(1.1f+float(ulp)); else return x*(0.9f-float(ulp)); }
- __forceinline double nextafter(double x, double y) { return _nextafter(x, y); }
- __forceinline int roundf(float f) { return (int)(f + 0.5f); }
-#else
- __forceinline float nextafter(float x, float y) { return ::nextafterf(x, y); }
- __forceinline double nextafter(double x, double y) { return ::nextafter(x, y); }
-#endif
-
- __forceinline float abs ( const float x ) { return ::fabsf(x); }
- __forceinline float acos ( const float x ) { return ::acosf (x); }
- __forceinline float asin ( const float x ) { return ::asinf (x); }
- __forceinline float atan ( const float x ) { return ::atanf (x); }
- __forceinline float atan2( const float y, const float x ) { return ::atan2f(y, x); }
- __forceinline float cos ( const float x ) { return ::cosf (x); }
- __forceinline float cosh ( const float x ) { return ::coshf (x); }
- __forceinline float exp ( const float x ) { return ::expf (x); }
- __forceinline float fmod ( const float x, const float y ) { return ::fmodf (x, y); }
- __forceinline float log ( const float x ) { return ::logf (x); }
- __forceinline float log10( const float x ) { return ::log10f(x); }
- __forceinline float pow ( const float x, const float y ) { return ::powf (x, y); }
- __forceinline float sin ( const float x ) { return ::sinf (x); }
- __forceinline float sinh ( const float x ) { return ::sinhf (x); }
- __forceinline float sqrt ( const float x ) { return ::sqrtf (x); }
- __forceinline float tan ( const float x ) { return ::tanf (x); }
- __forceinline float tanh ( const float x ) { return ::tanhf (x); }
- __forceinline float floor( const float x ) { return ::floorf (x); }
- __forceinline float ceil ( const float x ) { return ::ceilf (x); }
- __forceinline float frac ( const float x ) { return x-floor(x); }
-
- __forceinline double abs ( const double x ) { return ::fabs(x); }
- __forceinline double sign ( const double x ) { return x<0?-1.0:1.0; }
- __forceinline double acos ( const double x ) { return ::acos (x); }
- __forceinline double asin ( const double x ) { return ::asin (x); }
- __forceinline double atan ( const double x ) { return ::atan (x); }
- __forceinline double atan2( const double y, const double x ) { return ::atan2(y, x); }
- __forceinline double cos ( const double x ) { return ::cos (x); }
- __forceinline double cosh ( const double x ) { return ::cosh (x); }
- __forceinline double exp ( const double x ) { return ::exp (x); }
- __forceinline double fmod ( const double x, const double y ) { return ::fmod (x, y); }
- __forceinline double log ( const double x ) { return ::log (x); }
- __forceinline double log10( const double x ) { return ::log10(x); }
- __forceinline double pow ( const double x, const double y ) { return ::pow (x, y); }
- __forceinline double rcp ( const double x ) { return 1.0/x; }
- __forceinline double rsqrt( const double x ) { return 1.0/::sqrt(x); }
- __forceinline double sin ( const double x ) { return ::sin (x); }
- __forceinline double sinh ( const double x ) { return ::sinh (x); }
- __forceinline double sqr ( const double x ) { return x*x; }
- __forceinline double sqrt ( const double x ) { return ::sqrt (x); }
- __forceinline double tan ( const double x ) { return ::tan (x); }
- __forceinline double tanh ( const double x ) { return ::tanh (x); }
- __forceinline double floor( const double x ) { return ::floor (x); }
- __forceinline double ceil ( const double x ) { return ::ceil (x); }
-
-#if defined(__aarch64__)
- __forceinline float mini(float a, float b) {
- // FP and Neon shares same vector register in arm64
- __m128 x;
- __m128 y;
- x[0] = a;
- y[0] = b;
- x = _mm_min_ps(x, y);
- return x[0];
- }
-#elif defined(__SSE4_1__)
- __forceinline float mini(float a, float b) {
- const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
- const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
- const __m128i ci = _mm_min_epi32(ai,bi);
- return _mm_cvtss_f32(_mm_castsi128_ps(ci));
- }
-#endif
-
-#if defined(__aarch64__)
- __forceinline float maxi(float a, float b) {
- // FP and Neon shares same vector register in arm64
- __m128 x;
- __m128 y;
- x[0] = a;
- y[0] = b;
- x = _mm_max_ps(x, y);
- return x[0];
- }
-#elif defined(__SSE4_1__)
- __forceinline float maxi(float a, float b) {
- const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
- const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
- const __m128i ci = _mm_max_epi32(ai,bi);
- return _mm_cvtss_f32(_mm_castsi128_ps(ci));
- }
-#endif
-
- template<typename T>
- __forceinline T twice(const T& a) { return a+a; }
-
- __forceinline int min(int a, int b) { return a<b ? a:b; }
- __forceinline unsigned min(unsigned a, unsigned b) { return a<b ? a:b; }
- __forceinline int64_t min(int64_t a, int64_t b) { return a<b ? a:b; }
- __forceinline float min(float a, float b) { return a<b ? a:b; }
- __forceinline double min(double a, double b) { return a<b ? a:b; }
-#if defined(__X86_64__) || defined(__aarch64__)
- __forceinline size_t min(size_t a, size_t b) { return a<b ? a:b; }
-#endif
-
- template<typename T> __forceinline T min(const T& a, const T& b, const T& c) { return min(min(a,b),c); }
- template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d) { return min(min(a,b),min(c,d)); }
- template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d, const T& e) { return min(min(min(a,b),min(c,d)),e); }
-
- template<typename T> __forceinline T mini(const T& a, const T& b, const T& c) { return mini(mini(a,b),c); }
- template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d) { return mini(mini(a,b),mini(c,d)); }
- template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d, const T& e) { return mini(mini(mini(a,b),mini(c,d)),e); }
-
- __forceinline int max(int a, int b) { return a<b ? b:a; }
- __forceinline unsigned max(unsigned a, unsigned b) { return a<b ? b:a; }
- __forceinline int64_t max(int64_t a, int64_t b) { return a<b ? b:a; }
- __forceinline float max(float a, float b) { return a<b ? b:a; }
- __forceinline double max(double a, double b) { return a<b ? b:a; }
-#if defined(__X86_64__) || defined(__aarch64__)
- __forceinline size_t max(size_t a, size_t b) { return a<b ? b:a; }
-#endif
-
- template<typename T> __forceinline T max(const T& a, const T& b, const T& c) { return max(max(a,b),c); }
- template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d) { return max(max(a,b),max(c,d)); }
- template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d, const T& e) { return max(max(max(a,b),max(c,d)),e); }
-
- template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c) { return maxi(maxi(a,b),c); }
- template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d) { return maxi(maxi(a,b),maxi(c,d)); }
- template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d, const T& e) { return maxi(maxi(maxi(a,b),maxi(c,d)),e); }
-
-#if defined(__MACOSX__)
- __forceinline ssize_t min(ssize_t a, ssize_t b) { return a<b ? a:b; }
- __forceinline ssize_t max(ssize_t a, ssize_t b) { return a<b ? b:a; }
-#endif
-
-#if defined(__MACOSX__) && !defined(__INTEL_COMPILER)
- __forceinline void sincosf(float x, float *sin, float *cos) {
- __sincosf(x,sin,cos);
- }
-#endif
-
-#if defined(__WIN32__) || defined(__FreeBSD__)
- __forceinline void sincosf(float x, float *s, float *c) {
- *s = sinf(x); *c = cosf(x);
- }
-#endif
-
- template<typename T> __forceinline T clamp(const T& x, const T& lower = T(zero), const T& upper = T(one)) { return max(min(x,upper),lower); }
- template<typename T> __forceinline T clampz(const T& x, const T& upper) { return max(T(zero), min(x,upper)); }
-
- template<typename T> __forceinline T deg2rad ( const T& x ) { return x * T(1.74532925199432957692e-2f); }
- template<typename T> __forceinline T rad2deg ( const T& x ) { return x * T(5.72957795130823208768e1f); }
- template<typename T> __forceinline T sin2cos ( const T& x ) { return sqrt(max(T(zero),T(one)-x*x)); }
- template<typename T> __forceinline T cos2sin ( const T& x ) { return sin2cos(x); }
-
-#if defined(__AVX2__)
- __forceinline float madd ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fmadd_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
- __forceinline float msub ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fmsub_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
- __forceinline float nmadd ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fnmadd_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
- __forceinline float nmsub ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fnmsub_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
-#elif defined (__aarch64__) && defined(__clang__)
-#pragma clang fp contract(fast)
-
-
-__forceinline float madd ( const float a, const float b, const float c) { return a*b + c; }
-__forceinline float msub ( const float a, const float b, const float c) { return a*b - c; }
-__forceinline float nmadd ( const float a, const float b, const float c) { return c - a*b; }
-__forceinline float nmsub ( const float a, const float b, const float c) { return -(c + a*b); }
-
-#pragma clang fp contract(on)
-#else
- __forceinline float madd ( const float a, const float b, const float c) { return a*b+c; }
- __forceinline float msub ( const float a, const float b, const float c) { return a*b-c; }
- __forceinline float nmadd ( const float a, const float b, const float c) { return -a*b+c;}
- __forceinline float nmsub ( const float a, const float b, const float c) { return -a*b-c; }
-#endif
-
- /*! random functions */
- template<typename T> T random() { return T(0); }
-#if defined(_WIN32)
- template<> __forceinline int random() { return int(rand()) ^ (int(rand()) << 8) ^ (int(rand()) << 16); }
- template<> __forceinline uint32_t random() { return uint32_t(rand()) ^ (uint32_t(rand()) << 8) ^ (uint32_t(rand()) << 16); }
-#else
- template<> __forceinline int random() { return int(rand()); }
- template<> __forceinline uint32_t random() { return uint32_t(rand()) ^ (uint32_t(rand()) << 16); }
-#endif
- template<> __forceinline float random() { return rand()/float(RAND_MAX); }
- template<> __forceinline double random() { return rand()/double(RAND_MAX); }
-
-#if _WIN32
- __forceinline double drand48() {
- return double(rand())/double(RAND_MAX);
- }
-
- __forceinline void srand48(long seed) {
- return srand(seed);
- }
-#endif
-
- /*! selects */
- __forceinline bool select(bool s, bool t , bool f) { return s ? t : f; }
- __forceinline int select(bool s, int t, int f) { return s ? t : f; }
- __forceinline float select(bool s, float t, float f) { return s ? t : f; }
-
- __forceinline bool all(bool s) { return s; }
-
- __forceinline float lerp(const float v0, const float v1, const float t) {
- return madd(1.0f-t,v0,t*v1);
- }
-
- template<typename T>
- __forceinline T lerp2(const float x0, const float x1, const float x2, const float x3, const T& u, const T& v) {
- return madd((1.0f-u),madd((1.0f-v),T(x0),v*T(x2)),u*madd((1.0f-v),T(x1),v*T(x3)));
- }
-
- /*! exchange */
- template<typename T> __forceinline void xchg ( T& a, T& b ) { const T tmp = a; a = b; b = tmp; }
-
-
- template<typename T> __forceinline T prod_diff(const T& a,const T& b,const T& c,const T& d) {
-#if 1//!defined(__aarch64__)
- return msub(a,b,c*d);
-#else
- return nmadd(c,d,a*b);
-#endif
- }
-
- /*! bit reverse operation */
- template<class T>
- __forceinline T bitReverse(const T& vin)
- {
- T v = vin;
- v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
- v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
- v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
- v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
- v = ( v >> 16 ) | ( v << 16);
- return v;
- }
-
- /*! bit interleave operation */
- template<class T>
- __forceinline T bitInterleave(const T& xin, const T& yin, const T& zin)
- {
- T x = xin, y = yin, z = zin;
- x = (x | (x << 16)) & 0x030000FF;
- x = (x | (x << 8)) & 0x0300F00F;
- x = (x | (x << 4)) & 0x030C30C3;
- x = (x | (x << 2)) & 0x09249249;
-
- y = (y | (y << 16)) & 0x030000FF;
- y = (y | (y << 8)) & 0x0300F00F;
- y = (y | (y << 4)) & 0x030C30C3;
- y = (y | (y << 2)) & 0x09249249;
-
- z = (z | (z << 16)) & 0x030000FF;
- z = (z | (z << 8)) & 0x0300F00F;
- z = (z | (z << 4)) & 0x030C30C3;
- z = (z | (z << 2)) & 0x09249249;
-
- return x | (y << 1) | (z << 2);
- }
-
-#if defined(__AVX2__) && !defined(__aarch64__)
-
- template<>
- __forceinline unsigned int bitInterleave(const unsigned int &xi, const unsigned int& yi, const unsigned int& zi)
- {
- const unsigned int xx = pdep(xi,0x49249249 /* 0b01001001001001001001001001001001 */ );
- const unsigned int yy = pdep(yi,0x92492492 /* 0b10010010010010010010010010010010 */);
- const unsigned int zz = pdep(zi,0x24924924 /* 0b00100100100100100100100100100100 */);
- return xx | yy | zz;
- }
-
-#endif
-
- /*! bit interleave operation for 64bit data types*/
- template<class T>
- __forceinline T bitInterleave64(const T& xin, const T& yin, const T& zin){
- T x = xin & 0x1fffff;
- T y = yin & 0x1fffff;
- T z = zin & 0x1fffff;
-
- x = (x | x << 32) & 0x1f00000000ffff;
- x = (x | x << 16) & 0x1f0000ff0000ff;
- x = (x | x << 8) & 0x100f00f00f00f00f;
- x = (x | x << 4) & 0x10c30c30c30c30c3;
- x = (x | x << 2) & 0x1249249249249249;
-
- y = (y | y << 32) & 0x1f00000000ffff;
- y = (y | y << 16) & 0x1f0000ff0000ff;
- y = (y | y << 8) & 0x100f00f00f00f00f;
- y = (y | y << 4) & 0x10c30c30c30c30c3;
- y = (y | y << 2) & 0x1249249249249249;
-
- z = (z | z << 32) & 0x1f00000000ffff;
- z = (z | z << 16) & 0x1f0000ff0000ff;
- z = (z | z << 8) & 0x100f00f00f00f00f;
- z = (z | z << 4) & 0x10c30c30c30c30c3;
- z = (z | z << 2) & 0x1249249249249249;
-
- return x | (y << 1) | (z << 2);
- }
-}
diff --git a/thirdparty/embree-aarch64/common/math/obbox.h b/thirdparty/embree-aarch64/common/math/obbox.h
deleted file mode 100644
index 032b56904e..0000000000
--- a/thirdparty/embree-aarch64/common/math/obbox.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bbox.h"
-#include "linearspace3.h"
-
-namespace embree
-{
- /*! Oriented bounding box */
- template<typename T>
- struct OBBox
- {
- public:
-
- __forceinline OBBox () {}
-
- __forceinline OBBox (EmptyTy)
- : space(one), bounds(empty) {}
-
- __forceinline OBBox (const BBox<T>& bounds)
- : space(one), bounds(bounds) {}
-
- __forceinline OBBox (const LinearSpace3<T>& space, const BBox<T>& bounds)
- : space(space), bounds(bounds) {}
-
- friend embree_ostream operator<<(embree_ostream cout, const OBBox& p) {
- return cout << "{ space = " << p.space << ", bounds = " << p.bounds << "}";
- }
-
- public:
- LinearSpace3<T> space; //!< orthonormal transformation
- BBox<T> bounds; //!< bounds in transformed space
- };
-
- typedef OBBox<Vec3f> OBBox3f;
- typedef OBBox<Vec3fa> OBBox3fa;
-}
diff --git a/thirdparty/embree-aarch64/common/math/quaternion.h b/thirdparty/embree-aarch64/common/math/quaternion.h
deleted file mode 100644
index 20c69bc62f..0000000000
--- a/thirdparty/embree-aarch64/common/math/quaternion.h
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "vec3.h"
-#include "vec4.h"
-
-#include "transcendental.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////
- // Quaternion Struct
- ////////////////////////////////////////////////////////////////
-
- template<typename T>
- struct QuaternionT
- {
- typedef Vec3<T> Vector;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline QuaternionT () { }
- __forceinline QuaternionT ( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; }
- __forceinline QuaternionT& operator=( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; return *this; }
-
- __forceinline QuaternionT( const T& r ) : r(r), i(zero), j(zero), k(zero) {}
- __forceinline explicit QuaternionT( const Vec3<T>& v ) : r(zero), i(v.x), j(v.y), k(v.z) {}
- __forceinline explicit QuaternionT( const Vec4<T>& v ) : r(v.x), i(v.y), j(v.z), k(v.w) {}
- __forceinline QuaternionT( const T& r, const T& i, const T& j, const T& k ) : r(r), i(i), j(j), k(k) {}
- __forceinline QuaternionT( const T& r, const Vec3<T>& v ) : r(r), i(v.x), j(v.y), k(v.z) {}
-
- __inline QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz );
- __inline QuaternionT( const T& yaw, const T& pitch, const T& roll );
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline QuaternionT( ZeroTy ) : r(zero), i(zero), j(zero), k(zero) {}
- __forceinline QuaternionT( OneTy ) : r( one), i(zero), j(zero), k(zero) {}
-
- /*! return quaternion for rotation around arbitrary axis */
- static __forceinline QuaternionT rotate(const Vec3<T>& u, const T& r) {
- return QuaternionT<T>(cos(T(0.5)*r),sin(T(0.5)*r)*normalize(u));
- }
-
- /*! returns the rotation axis of the quaternion as a vector */
- __forceinline Vec3<T> v( ) const { return Vec3<T>(i, j, k); }
-
- public:
- T r, i, j, k;
- };
-
- template<typename T> __forceinline QuaternionT<T> operator *( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a * b.r, a * b.i, a * b.j, a * b.k); }
- template<typename T> __forceinline QuaternionT<T> operator *( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r * b, a.i * b, a.j * b, a.k * b); }
-
- ////////////////////////////////////////////////////////////////
- // Unary Operators
- ////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a ) { return QuaternionT<T>(+a.r, +a.i, +a.j, +a.k); }
- template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a ) { return QuaternionT<T>(-a.r, -a.i, -a.j, -a.k); }
- template<typename T> __forceinline QuaternionT<T> conj ( const QuaternionT<T>& a ) { return QuaternionT<T>(a.r, -a.i, -a.j, -a.k); }
- template<typename T> __forceinline T abs ( const QuaternionT<T>& a ) { return sqrt(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
- template<typename T> __forceinline QuaternionT<T> rcp ( const QuaternionT<T>& a ) { return conj(a)*rcp(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
- template<typename T> __forceinline QuaternionT<T> normalize ( const QuaternionT<T>& a ) { return a*rsqrt(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
-
- // evaluates a*q-r
- template<typename T> __forceinline QuaternionT<T>
- msub(const T& a, const QuaternionT<T>& q, const QuaternionT<T>& p)
- {
- return QuaternionT<T>(msub(a, q.r, p.r),
- msub(a, q.i, p.i),
- msub(a, q.j, p.j),
- msub(a, q.k, p.k));
- }
- // evaluates a*q-r
- template<typename T> __forceinline QuaternionT<T>
- madd (const T& a, const QuaternionT<T>& q, const QuaternionT<T>& p)
- {
- return QuaternionT<T>(madd(a, q.r, p.r),
- madd(a, q.i, p.i),
- madd(a, q.j, p.j),
- madd(a, q.k, p.k));
- }
-
- ////////////////////////////////////////////////////////////////
- // Binary Operators
- ////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline QuaternionT<T> operator +( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a + b.r, b.i, b.j, b.k); }
- template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r + b, a.i, a.j, a.k); }
- template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return QuaternionT<T>(a.r + b.r, a.i + b.i, a.j + b.j, a.k + b.k); }
- template<typename T> __forceinline QuaternionT<T> operator -( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a - b.r, -b.i, -b.j, -b.k); }
- template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r - b, a.i, a.j, a.k); }
- template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return QuaternionT<T>(a.r - b.r, a.i - b.i, a.j - b.j, a.k - b.k); }
-
- template<typename T> __forceinline Vec3<T> operator *( const QuaternionT<T>& a, const Vec3<T> & b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
- template<typename T> __forceinline QuaternionT<T> operator *( const QuaternionT<T>& a, const QuaternionT<T>& b ) {
- return QuaternionT<T>(a.r*b.r - a.i*b.i - a.j*b.j - a.k*b.k,
- a.r*b.i + a.i*b.r + a.j*b.k - a.k*b.j,
- a.r*b.j - a.i*b.k + a.j*b.r + a.k*b.i,
- a.r*b.k + a.i*b.j - a.j*b.i + a.k*b.r);
- }
- template<typename T> __forceinline QuaternionT<T> operator /( const T & a, const QuaternionT<T>& b ) { return a*rcp(b); }
- template<typename T> __forceinline QuaternionT<T> operator /( const QuaternionT<T>& a, const T & b ) { return a*rcp(b); }
- template<typename T> __forceinline QuaternionT<T> operator /( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a*rcp(b); }
-
- template<typename T> __forceinline QuaternionT<T>& operator +=( QuaternionT<T>& a, const T & b ) { return a = a+b; }
- template<typename T> __forceinline QuaternionT<T>& operator +=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a+b; }
- template<typename T> __forceinline QuaternionT<T>& operator -=( QuaternionT<T>& a, const T & b ) { return a = a-b; }
- template<typename T> __forceinline QuaternionT<T>& operator -=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a-b; }
- template<typename T> __forceinline QuaternionT<T>& operator *=( QuaternionT<T>& a, const T & b ) { return a = a*b; }
- template<typename T> __forceinline QuaternionT<T>& operator *=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a*b; }
- template<typename T> __forceinline QuaternionT<T>& operator /=( QuaternionT<T>& a, const T & b ) { return a = a*rcp(b); }
- template<typename T> __forceinline QuaternionT<T>& operator /=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a*rcp(b); }
-
- template<typename T, typename M> __forceinline QuaternionT<T>
- select(const M& m, const QuaternionT<T>& q, const QuaternionT<T>& p)
- {
- return QuaternionT<T>(select(m, q.r, p.r),
- select(m, q.i, p.i),
- select(m, q.j, p.j),
- select(m, q.k, p.k));
- }
-
-
- template<typename T> __forceinline Vec3<T> xfmPoint ( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
- template<typename T> __forceinline Vec3<T> xfmVector( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
- template<typename T> __forceinline Vec3<T> xfmNormal( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
-
- template<typename T> __forceinline T dot(const QuaternionT<T>& a, const QuaternionT<T>& b) { return a.r*b.r + a.i*b.i + a.j*b.j + a.k*b.k; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline bool operator ==( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a.r == b.r && a.i == b.i && a.j == b.j && a.k == b.k; }
- template<typename T> __forceinline bool operator !=( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a.r != b.r || a.i != b.i || a.j != b.j || a.k != b.k; }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Orientation Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> QuaternionT<T>::QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz )
- {
- if ( vx.x + vy.y + vz.z >= T(zero) )
- {
- const T t = T(one) + (vx.x + vy.y + vz.z);
- const T s = rsqrt(t)*T(0.5f);
- r = t*s;
- i = (vy.z - vz.y)*s;
- j = (vz.x - vx.z)*s;
- k = (vx.y - vy.x)*s;
- }
- else if ( vx.x >= max(vy.y, vz.z) )
- {
- const T t = (T(one) + vx.x) - (vy.y + vz.z);
- const T s = rsqrt(t)*T(0.5f);
- r = (vy.z - vz.y)*s;
- i = t*s;
- j = (vx.y + vy.x)*s;
- k = (vz.x + vx.z)*s;
- }
- else if ( vy.y >= vz.z ) // if ( vy.y >= max(vz.z, vx.x) )
- {
- const T t = (T(one) + vy.y) - (vz.z + vx.x);
- const T s = rsqrt(t)*T(0.5f);
- r = (vz.x - vx.z)*s;
- i = (vx.y + vy.x)*s;
- j = t*s;
- k = (vy.z + vz.y)*s;
- }
- else //if ( vz.z >= max(vy.y, vx.x) )
- {
- const T t = (T(one) + vz.z) - (vx.x + vy.y);
- const T s = rsqrt(t)*T(0.5f);
- r = (vx.y - vy.x)*s;
- i = (vz.x + vx.z)*s;
- j = (vy.z + vz.y)*s;
- k = t*s;
- }
- }
-
- template<typename T> QuaternionT<T>::QuaternionT( const T& yaw, const T& pitch, const T& roll )
- {
- const T cya = cos(yaw *T(0.5f));
- const T cpi = cos(pitch*T(0.5f));
- const T cro = cos(roll *T(0.5f));
- const T sya = sin(yaw *T(0.5f));
- const T spi = sin(pitch*T(0.5f));
- const T sro = sin(roll *T(0.5f));
- r = cro*cya*cpi + sro*sya*spi;
- i = cro*cya*spi + sro*sya*cpi;
- j = cro*sya*cpi - sro*cya*spi;
- k = sro*cya*cpi - cro*sya*spi;
- }
-
- //////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- //////////////////////////////////////////////////////////////////////////////
-
- template<typename T> static embree_ostream operator<<(embree_ostream cout, const QuaternionT<T>& q) {
- return cout << "{ r = " << q.r << ", i = " << q.i << ", j = " << q.j << ", k = " << q.k << " }";
- }
-
- /*! default template instantiations */
- typedef QuaternionT<float> Quaternion3f;
- typedef QuaternionT<double> Quaternion3d;
-
- template<int N> using Quaternion3vf = QuaternionT<vfloat<N>>;
- typedef QuaternionT<vfloat<4>> Quaternion3vf4;
- typedef QuaternionT<vfloat<8>> Quaternion3vf8;
- typedef QuaternionT<vfloat<16>> Quaternion3vf16;
-
- //////////////////////////////////////////////////////////////////////////////
- /// Interpolation
- //////////////////////////////////////////////////////////////////////////////
- template<typename T>
- __forceinline QuaternionT<T>lerp(const QuaternionT<T>& q0,
- const QuaternionT<T>& q1,
- const T& factor)
- {
- QuaternionT<T> q;
- q.r = lerp(q0.r, q1.r, factor);
- q.i = lerp(q0.i, q1.i, factor);
- q.j = lerp(q0.j, q1.j, factor);
- q.k = lerp(q0.k, q1.k, factor);
- return q;
- }
-
- template<typename T>
- __forceinline QuaternionT<T> slerp(const QuaternionT<T>& q0,
- const QuaternionT<T>& q1_,
- const T& t)
- {
- T cosTheta = dot(q0, q1_);
- QuaternionT<T> q1 = select(cosTheta < 0.f, -q1_, q1_);
- cosTheta = select(cosTheta < 0.f, -cosTheta, cosTheta);
- if (unlikely(all(cosTheta > 0.9995f))) {
- return normalize(lerp(q0, q1, t));
- }
- const T phi = t * fastapprox::acos(cosTheta);
- T sinPhi, cosPhi;
- fastapprox::sincos(phi, sinPhi, cosPhi);
- QuaternionT<T> qperp = sinPhi * normalize(msub(cosTheta, q0, q1));
- return msub(cosPhi, q0, qperp);
- }
-}
diff --git a/thirdparty/embree-aarch64/common/math/range.h b/thirdparty/embree-aarch64/common/math/range.h
deleted file mode 100644
index 762d9cd9ea..0000000000
--- a/thirdparty/embree-aarch64/common/math/range.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../math/math.h"
-
-namespace embree
-{
- template<typename Ty>
- struct range
- {
- __forceinline range() {}
-
- __forceinline range(const Ty& begin)
- : _begin(begin), _end(begin+1) {}
-
- __forceinline range(const Ty& begin, const Ty& end)
- : _begin(begin), _end(end) {}
-
- __forceinline range(const range& other)
- : _begin(other._begin), _end(other._end) {}
-
- template<typename T1>
- __forceinline range(const range<T1>& other)
- : _begin(Ty(other._begin)), _end(Ty(other._end)) {}
-
- template<typename T1>
- __forceinline range& operator =(const range<T1>& other) {
- _begin = other._begin;
- _end = other._end;
- return *this;
- }
-
- __forceinline Ty begin() const {
- return _begin;
- }
-
- __forceinline Ty end() const {
- return _end;
- }
-
- __forceinline range intersect(const range& r) const {
- return range (max(_begin,r._begin),min(_end,r._end));
- }
-
- __forceinline Ty size() const {
- return _end - _begin;
- }
-
- __forceinline bool empty() const {
- return _end <= _begin;
- }
-
- __forceinline Ty center() const {
- return (_begin + _end)/2;
- }
-
- __forceinline std::pair<range,range> split() const
- {
- const Ty _center = center();
- return std::make_pair(range(_begin,_center),range(_center,_end));
- }
-
- __forceinline void split(range& left_o, range& right_o) const
- {
- const Ty _center = center();
- left_o = range(_begin,_center);
- right_o = range(_center,_end);
- }
-
- __forceinline friend bool operator< (const range& r0, const range& r1) {
- return r0.size() < r1.size();
- }
-
- friend embree_ostream operator<<(embree_ostream cout, const range& r) {
- return cout << "range [" << r.begin() << ", " << r.end() << "]";
- }
-
- Ty _begin, _end;
- };
-
- template<typename Ty>
- range<Ty> make_range(const Ty& begin, const Ty& end) {
- return range<Ty>(begin,end);
- }
-
- template<typename Ty>
- struct extended_range : public range<Ty>
- {
- __forceinline extended_range () {}
-
- __forceinline extended_range (const Ty& begin)
- : range<Ty>(begin), _ext_end(begin+1) {}
-
- __forceinline extended_range (const Ty& begin, const Ty& end)
- : range<Ty>(begin,end), _ext_end(end) {}
-
- __forceinline extended_range (const Ty& begin, const Ty& end, const Ty& ext_end)
- : range<Ty>(begin,end), _ext_end(ext_end) {}
-
- __forceinline Ty ext_end() const {
- return _ext_end;
- }
-
- __forceinline Ty ext_size() const {
- return _ext_end - range<Ty>::_begin;
- }
-
- __forceinline Ty ext_range_size() const {
- return _ext_end - range<Ty>::_end;
- }
-
- __forceinline bool has_ext_range() const {
- assert(_ext_end >= range<Ty>::_end);
- return (_ext_end - range<Ty>::_end) > 0;
- }
-
- __forceinline void set_ext_range(const size_t ext_end){
- assert(ext_end >= range<Ty>::_end);
- _ext_end = ext_end;
- }
-
- __forceinline void move_right(const size_t plus){
- range<Ty>::_begin += plus;
- range<Ty>::_end += plus;
- _ext_end += plus;
- }
-
- friend embree_ostream operator<<(embree_ostream cout, const extended_range& r) {
- return cout << "extended_range [" << r.begin() << ", " << r.end() << " (" << r.ext_end() << ")]";
- }
-
- Ty _ext_end;
- };
-}
diff --git a/thirdparty/embree-aarch64/common/math/transcendental.h b/thirdparty/embree-aarch64/common/math/transcendental.h
deleted file mode 100644
index 6855d82b53..0000000000
--- a/thirdparty/embree-aarch64/common/math/transcendental.h
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-// Transcendental functions from "ispc": https://github.com/ispc/ispc/
-// Most of the transcendental implementations in ispc code come from
-// Solomon Boulos's "syrah": https://github.com/boulos/syrah/
-
-#include "../simd/simd.h"
-
-namespace embree
-{
-
-namespace fastapprox
-{
-
-template <typename T>
-__forceinline T sin(const T &v)
-{
- static const float piOverTwoVec = 1.57079637050628662109375;
- static const float twoOverPiVec = 0.636619746685028076171875;
- auto scaled = v * twoOverPiVec;
- auto kReal = floor(scaled);
- auto k = toInt(kReal);
-
- // Reduced range version of x
- auto x = v - kReal * piOverTwoVec;
- auto kMod4 = k & 3;
- auto sinUseCos = (kMod4 == 1 | kMod4 == 3);
- auto flipSign = (kMod4 > 1);
-
- // These coefficients are from sollya with fpminimax(sin(x)/x, [|0, 2,
- // 4, 6, 8, 10|], [|single...|], [0;Pi/2]);
- static const float sinC2 = -0.16666667163372039794921875;
- static const float sinC4 = +8.333347737789154052734375e-3;
- static const float sinC6 = -1.9842604524455964565277099609375e-4;
- static const float sinC8 = +2.760012648650445044040679931640625e-6;
- static const float sinC10 = -2.50293279435709337121807038784027099609375e-8;
-
- static const float cosC2 = -0.5;
- static const float cosC4 = +4.166664183139801025390625e-2;
- static const float cosC6 = -1.388833043165504932403564453125e-3;
- static const float cosC8 = +2.47562347794882953166961669921875e-5;
- static const float cosC10 = -2.59630184018533327616751194000244140625e-7;
-
- auto outside = select(sinUseCos, 1., x);
- auto c2 = select(sinUseCos, T(cosC2), T(sinC2));
- auto c4 = select(sinUseCos, T(cosC4), T(sinC4));
- auto c6 = select(sinUseCos, T(cosC6), T(sinC6));
- auto c8 = select(sinUseCos, T(cosC8), T(sinC8));
- auto c10 = select(sinUseCos, T(cosC10), T(sinC10));
-
- auto x2 = x * x;
- auto formula = x2 * c10 + c8;
- formula = x2 * formula + c6;
- formula = x2 * formula + c4;
- formula = x2 * formula + c2;
- formula = x2 * formula + 1.;
- formula *= outside;
-
- formula = select(flipSign, -formula, formula);
- return formula;
-}
-
-template <typename T>
-__forceinline T cos(const T &v)
-{
- static const float piOverTwoVec = 1.57079637050628662109375;
- static const float twoOverPiVec = 0.636619746685028076171875;
- auto scaled = v * twoOverPiVec;
- auto kReal = floor(scaled);
- auto k = toInt(kReal);
-
- // Reduced range version of x
- auto x = v - kReal * piOverTwoVec;
-
- auto kMod4 = k & 3;
- auto cosUseCos = (kMod4 == 0 | kMod4 == 2);
- auto flipSign = (kMod4 == 1 | kMod4 == 2);
-
- const float sinC2 = -0.16666667163372039794921875;
- const float sinC4 = +8.333347737789154052734375e-3;
- const float sinC6 = -1.9842604524455964565277099609375e-4;
- const float sinC8 = +2.760012648650445044040679931640625e-6;
- const float sinC10 = -2.50293279435709337121807038784027099609375e-8;
-
- const float cosC2 = -0.5;
- const float cosC4 = +4.166664183139801025390625e-2;
- const float cosC6 = -1.388833043165504932403564453125e-3;
- const float cosC8 = +2.47562347794882953166961669921875e-5;
- const float cosC10 = -2.59630184018533327616751194000244140625e-7;
-
- auto outside = select(cosUseCos, 1., x);
- auto c2 = select(cosUseCos, T(cosC2), T(sinC2));
- auto c4 = select(cosUseCos, T(cosC4), T(sinC4));
- auto c6 = select(cosUseCos, T(cosC6), T(sinC6));
- auto c8 = select(cosUseCos, T(cosC8), T(sinC8));
- auto c10 = select(cosUseCos, T(cosC10), T(sinC10));
-
- auto x2 = x * x;
- auto formula = x2 * c10 + c8;
- formula = x2 * formula + c6;
- formula = x2 * formula + c4;
- formula = x2 * formula + c2;
- formula = x2 * formula + 1.;
- formula *= outside;
-
- formula = select(flipSign, -formula, formula);
- return formula;
-}
-
-template <typename T>
-__forceinline void sincos(const T &v, T &sinResult, T &cosResult)
-{
- const float piOverTwoVec = 1.57079637050628662109375;
- const float twoOverPiVec = 0.636619746685028076171875;
- auto scaled = v * twoOverPiVec;
- auto kReal = floor(scaled);
- auto k = toInt(kReal);
-
- // Reduced range version of x
- auto x = v - kReal * piOverTwoVec;
- auto kMod4 = k & 3;
- auto cosUseCos = ((kMod4 == 0) | (kMod4 == 2));
- auto sinUseCos = ((kMod4 == 1) | (kMod4 == 3));
- auto sinFlipSign = (kMod4 > 1);
- auto cosFlipSign = ((kMod4 == 1) | (kMod4 == 2));
-
- const float oneVec = +1.;
- const float sinC2 = -0.16666667163372039794921875;
- const float sinC4 = +8.333347737789154052734375e-3;
- const float sinC6 = -1.9842604524455964565277099609375e-4;
- const float sinC8 = +2.760012648650445044040679931640625e-6;
- const float sinC10 = -2.50293279435709337121807038784027099609375e-8;
-
- const float cosC2 = -0.5;
- const float cosC4 = +4.166664183139801025390625e-2;
- const float cosC6 = -1.388833043165504932403564453125e-3;
- const float cosC8 = +2.47562347794882953166961669921875e-5;
- const float cosC10 = -2.59630184018533327616751194000244140625e-7;
-
- auto x2 = x * x;
-
- auto sinFormula = x2 * sinC10 + sinC8;
- auto cosFormula = x2 * cosC10 + cosC8;
- sinFormula = x2 * sinFormula + sinC6;
- cosFormula = x2 * cosFormula + cosC6;
-
- sinFormula = x2 * sinFormula + sinC4;
- cosFormula = x2 * cosFormula + cosC4;
-
- sinFormula = x2 * sinFormula + sinC2;
- cosFormula = x2 * cosFormula + cosC2;
-
- sinFormula = x2 * sinFormula + oneVec;
- cosFormula = x2 * cosFormula + oneVec;
-
- sinFormula *= x;
-
- sinResult = select(sinUseCos, cosFormula, sinFormula);
- cosResult = select(cosUseCos, cosFormula, sinFormula);
-
- sinResult = select(sinFlipSign, -sinResult, sinResult);
- cosResult = select(cosFlipSign, -cosResult, cosResult);
-}
-
-template <typename T>
-__forceinline T tan(const T &v)
-{
- const float piOverFourVec = 0.785398185253143310546875;
- const float fourOverPiVec = 1.27323949337005615234375;
-
- auto xLt0 = v < 0.;
- auto y = select(xLt0, -v, v);
- auto scaled = y * fourOverPiVec;
-
- auto kReal = floor(scaled);
- auto k = toInt(kReal);
-
- auto x = y - kReal * piOverFourVec;
-
- // If k & 1, x -= Pi/4
- auto needOffset = (k & 1) != 0;
- x = select(needOffset, x - piOverFourVec, x);
-
- // If k & 3 == (0 or 3) let z = tan_In...(y) otherwise z = -cot_In0To...
- auto kMod4 = k & 3;
- auto useCotan = (kMod4 == 1) | (kMod4 == 2);
-
- const float oneVec = 1.0;
-
- const float tanC2 = +0.33333075046539306640625;
- const float tanC4 = +0.13339905440807342529296875;
- const float tanC6 = +5.3348250687122344970703125e-2;
- const float tanC8 = +2.46033705770969390869140625e-2;
- const float tanC10 = +2.892402000725269317626953125e-3;
- const float tanC12 = +9.500005282461643218994140625e-3;
-
- const float cotC2 = -0.3333333432674407958984375;
- const float cotC4 = -2.222204394638538360595703125e-2;
- const float cotC6 = -2.11752182804048061370849609375e-3;
- const float cotC8 = -2.0846328698098659515380859375e-4;
- const float cotC10 = -2.548247357481159269809722900390625e-5;
- const float cotC12 = -3.5257363606433500535786151885986328125e-7;
-
- auto x2 = x * x;
- T z;
- if (any(useCotan))
- {
- auto cotVal = x2 * cotC12 + cotC10;
- cotVal = x2 * cotVal + cotC8;
- cotVal = x2 * cotVal + cotC6;
- cotVal = x2 * cotVal + cotC4;
- cotVal = x2 * cotVal + cotC2;
- cotVal = x2 * cotVal + oneVec;
- // The equation is for x * cot(x) but we need -x * cot(x) for the tan part.
- cotVal /= -x;
- z = cotVal;
- }
- auto useTan = !useCotan;
- if (any(useTan))
- {
- auto tanVal = x2 * tanC12 + tanC10;
- tanVal = x2 * tanVal + tanC8;
- tanVal = x2 * tanVal + tanC6;
- tanVal = x2 * tanVal + tanC4;
- tanVal = x2 * tanVal + tanC2;
- tanVal = x2 * tanVal + oneVec;
- // Equation was for tan(x)/x
- tanVal *= x;
- z = select(useTan, tanVal, z);
- }
- return select(xLt0, -z, z);
-}
-
-template <typename T>
-__forceinline T asin(const T &x0)
-{
- auto isneg = (x0 < 0.f);
- auto x = abs(x0);
- auto isnan = (x > 1.f);
-
- // sollya
- // fpminimax(((asin(x)-pi/2)/-sqrt(1-x)), [|0,1,2,3,4,5|],[|single...|],
- // [1e-20;.9999999999999999]);
- // avg error: 1.1105439e-06, max error 1.3187528e-06
- auto v = 1.57079517841339111328125f +
- x * (-0.21450997889041900634765625f +
- x * (8.78556668758392333984375e-2f +
- x * (-4.489909112453460693359375e-2f +
- x * (1.928029954433441162109375e-2f +
- x * (-4.3095736764371395111083984375e-3f)))));
-
- v *= -sqrt(1.f - x);
- v = v + 1.57079637050628662109375f;
-
- v = select(v < 0.f, T(0.f), v);
- v = select(isneg, -v, v);
- v = select(isnan, T(cast_i2f(0x7fc00000)), v);
-
- return v;
-}
-
-template <typename T>
-__forceinline T acos(const T &v)
-{
- return 1.57079637050628662109375f - asin(v);
-}
-
-template <typename T>
-__forceinline T atan(const T &v)
-{
- const float piOverTwoVec = 1.57079637050628662109375;
- // atan(-x) = -atan(x) (so flip from negative to positive first)
- // If x > 1 -> atan(x) = Pi/2 - atan(1/x)
- auto xNeg = v < 0.f;
- auto xFlipped = select(xNeg, -v, v);
-
- auto xGt1 = xFlipped > 1.;
- auto x = select(xGt1, rcpSafe(xFlipped), xFlipped);
-
- // These coefficients approximate atan(x)/x
- const float atanC0 = +0.99999988079071044921875;
- const float atanC2 = -0.3333191573619842529296875;
- const float atanC4 = +0.199689209461212158203125;
- const float atanC6 = -0.14015688002109527587890625;
- const float atanC8 = +9.905083477497100830078125e-2;
- const float atanC10 = -5.93664981424808502197265625e-2;
- const float atanC12 = +2.417283318936824798583984375e-2;
- const float atanC14 = -4.6721356920897960662841796875e-3;
-
- auto x2 = x * x;
- auto result = x2 * atanC14 + atanC12;
- result = x2 * result + atanC10;
- result = x2 * result + atanC8;
- result = x2 * result + atanC6;
- result = x2 * result + atanC4;
- result = x2 * result + atanC2;
- result = x2 * result + atanC0;
- result *= x;
-
- result = select(xGt1, piOverTwoVec - result, result);
- result = select(xNeg, -result, result);
- return result;
-}
-
-template <typename T>
-__forceinline T atan2(const T &y, const T &x)
-{
- const float piVec = 3.1415926536;
- // atan2(y, x) =
- //
- // atan2(y > 0, x = +-0) -> Pi/2
- // atan2(y < 0, x = +-0) -> -Pi/2
- // atan2(y = +-0, x < +0) -> +-Pi
- // atan2(y = +-0, x >= +0) -> +-0
- //
- // atan2(y >= 0, x < 0) -> Pi + atan(y/x)
- // atan2(y < 0, x < 0) -> -Pi + atan(y/x)
- // atan2(y, x > 0) -> atan(y/x)
- //
- // and then a bunch of code for dealing with infinities.
- auto yOverX = y * rcpSafe(x);
- auto atanArg = atan(yOverX);
- auto xLt0 = x < 0.f;
- auto yLt0 = y < 0.f;
- auto offset = select(xLt0,
- select(yLt0, T(-piVec), T(piVec)), 0.f);
- return offset + atanArg;
-}
-
-template <typename T>
-__forceinline T exp(const T &v)
-{
- const float ln2Part1 = 0.6931457519;
- const float ln2Part2 = 1.4286067653e-6;
- const float oneOverLn2 = 1.44269502162933349609375;
-
- auto scaled = v * oneOverLn2;
- auto kReal = floor(scaled);
- auto k = toInt(kReal);
-
- // Reduced range version of x
- auto x = v - kReal * ln2Part1;
- x -= kReal * ln2Part2;
-
- // These coefficients are for e^x in [0, ln(2)]
- const float one = 1.;
- const float c2 = 0.4999999105930328369140625;
- const float c3 = 0.166668415069580078125;
- const float c4 = 4.16539050638675689697265625e-2;
- const float c5 = 8.378830738365650177001953125e-3;
- const float c6 = 1.304379315115511417388916015625e-3;
- const float c7 = 2.7555381529964506626129150390625e-4;
-
- auto result = x * c7 + c6;
- result = x * result + c5;
- result = x * result + c4;
- result = x * result + c3;
- result = x * result + c2;
- result = x * result + one;
- result = x * result + one;
-
- // Compute 2^k (should differ for float and double, but I'll avoid
- // it for now and just do floats)
- const int fpbias = 127;
- auto biasedN = k + fpbias;
- auto overflow = kReal > fpbias;
- // Minimum exponent is -126, so if k is <= -127 (k + 127 <= 0)
- // we've got underflow. -127 * ln(2) -> -88.02. So the most
- // negative float input that doesn't result in zero is like -88.
- auto underflow = kReal <= -fpbias;
- const int infBits = 0x7f800000;
- biasedN <<= 23;
- // Reinterpret this thing as float
- auto twoToTheN = asFloat(biasedN);
- // Handle both doubles and floats (hopefully eliding the copy for float)
- auto elemtype2n = twoToTheN;
- result *= elemtype2n;
- result = select(overflow, cast_i2f(infBits), result);
- result = select(underflow, 0., result);
- return result;
-}
-
-// Range reduction for logarithms takes log(x) -> log(2^n * y) -> n
-// * log(2) + log(y) where y is the reduced range (usually in [1/2, 1)).
-template <typename T, typename R>
-__forceinline void __rangeReduceLog(const T &input,
- T &reduced,
- R &exponent)
-{
- auto intVersion = asInt(input);
- // single precision = SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
- // exponent mask = 0111 1111 1000 0000 0000 0000 0000 0000
- // 0x7 0xF 0x8 0x0 0x0 0x0 0x0 0x0
- // non-exponent = 1000 0000 0111 1111 1111 1111 1111 1111
- // = 0x8 0x0 0x7 0xF 0xF 0xF 0xF 0xF
-
- //const int exponentMask(0x7F800000)
- static const int nonexponentMask = 0x807FFFFF;
-
- // We want the reduced version to have an exponent of -1 which is
- // -1 + 127 after biasing or 126
- static const int exponentNeg1 = (126l << 23);
- // NOTE(boulos): We don't need to mask anything out since we know
- // the sign bit has to be 0. If it's 1, we need to return infinity/nan
- // anyway (log(x), x = +-0 -> infinity, x < 0 -> NaN).
- auto biasedExponent = intVersion >> 23; // This number is [0, 255] but it means [-127, 128]
-
- auto offsetExponent = biasedExponent + 1; // Treat the number as if it were 2^{e+1} * (1.m)/2
- exponent = offsetExponent - 127; // get the real value
-
- // Blend the offset_exponent with the original input (do this in
- // int for now, until I decide if float can have & and &not)
- auto blended = (intVersion & nonexponentMask) | (exponentNeg1);
- reduced = asFloat(blended);
-}
-
-template <typename T> struct ExponentType { };
-template <int N> struct ExponentType<vfloat<N>> { typedef vint<N> Ty; };
-template <> struct ExponentType<float> { typedef int Ty; };
-
-template <typename T>
-__forceinline T log(const T &v)
-{
- T reduced;
- typename ExponentType<T>::Ty exponent;
-
- const int nanBits = 0x7fc00000;
- const int negInfBits = 0xFF800000;
- const float nan = cast_i2f(nanBits);
- const float negInf = cast_i2f(negInfBits);
- auto useNan = v < 0.;
- auto useInf = v == 0.;
- auto exceptional = useNan | useInf;
- const float one = 1.0;
-
- auto patched = select(exceptional, one, v);
- __rangeReduceLog(patched, reduced, exponent);
-
- const float ln2 = 0.693147182464599609375;
-
- auto x1 = one - reduced;
- const float c1 = +0.50000095367431640625;
- const float c2 = +0.33326041698455810546875;
- const float c3 = +0.2519190013408660888671875;
- const float c4 = +0.17541764676570892333984375;
- const float c5 = +0.3424419462680816650390625;
- const float c6 = -0.599632322788238525390625;
- const float c7 = +1.98442304134368896484375;
- const float c8 = -2.4899270534515380859375;
- const float c9 = +1.7491014003753662109375;
-
- auto result = x1 * c9 + c8;
- result = x1 * result + c7;
- result = x1 * result + c6;
- result = x1 * result + c5;
- result = x1 * result + c4;
- result = x1 * result + c3;
- result = x1 * result + c2;
- result = x1 * result + c1;
- result = x1 * result + one;
-
- // Equation was for -(ln(red)/(1-red))
- result *= -x1;
- result += toFloat(exponent) * ln2;
-
- return select(exceptional,
- select(useNan, T(nan), T(negInf)),
- result);
-}
-
-template <typename T>
-__forceinline T pow(const T &x, const T &y)
-{
- auto x1 = abs(x);
- auto z = exp(y * log(x1));
-
- // Handle special cases
- const float twoOver23 = 8388608.0f;
- auto yInt = y == round(y);
- auto yOddInt = select(yInt, asInt(abs(y) + twoOver23) << 31, 0); // set sign bit
-
- // x == 0
- z = select(x == 0.0f,
- select(y < 0.0f, T(inf) | signmsk(x),
- select(y == 0.0f, T(1.0f), asFloat(yOddInt) & x)), z);
-
- // x < 0
- auto xNegative = x < 0.0f;
- if (any(xNegative))
- {
- auto z1 = z | asFloat(yOddInt);
- z1 = select(yInt, z1, std::numeric_limits<float>::quiet_NaN());
- z = select(xNegative, z1, z);
- }
-
- auto xFinite = isfinite(x);
- auto yFinite = isfinite(y);
- if (all(xFinite & yFinite))
- return z;
-
- // x finite and y infinite
- z = select(andn(xFinite, yFinite),
- select(x1 == 1.0f, 1.0f,
- select((x1 > 1.0f) ^ (y < 0.0f), inf, T(0.0f))), z);
-
- // x infinite
- z = select(xFinite, z,
- select(y == 0.0f, 1.0f,
- select(y < 0.0f, T(0.0f), inf) | (asFloat(yOddInt) & x)));
-
- return z;
-}
-
-template <typename T>
-__forceinline T pow(const T &x, float y)
-{
- return pow(x, T(y));
-}
-
-} // namespace fastapprox
-
-} // namespace embree
diff --git a/thirdparty/embree-aarch64/common/math/vec2.h b/thirdparty/embree-aarch64/common/math/vec2.h
deleted file mode 100644
index a619459e9c..0000000000
--- a/thirdparty/embree-aarch64/common/math/vec2.h
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "math.h"
-
-namespace embree
-{
- struct Vec2fa;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Generic 2D vector Class
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> struct Vec2
- {
- enum { N = 2 };
- union {
- struct { T x, y; };
-#if !(defined(__WIN32__) && _MSC_VER == 1800) // workaround for older VS 2013 compiler
- T components[N];
-#endif
- };
-
- typedef T Scalar;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec2( ) {}
- __forceinline explicit Vec2( const T& a ) : x(a), y(a) {}
- __forceinline Vec2( const T& x, const T& y ) : x(x), y(y) {}
-
- __forceinline Vec2( const Vec2& other ) { x = other.x; y = other.y; }
- __forceinline Vec2( const Vec2fa& other );
-
- template<typename T1> __forceinline Vec2( const Vec2<T1>& a ) : x(T(a.x)), y(T(a.y)) {}
- template<typename T1> __forceinline Vec2& operator =( const Vec2<T1>& other ) { x = other.x; y = other.y; return *this; }
-
- __forceinline Vec2& operator =( const Vec2& other ) { x = other.x; y = other.y; return *this; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec2( ZeroTy ) : x(zero), y(zero) {}
- __forceinline Vec2( OneTy ) : x(one), y(one) {}
- __forceinline Vec2( PosInfTy ) : x(pos_inf), y(pos_inf) {}
- __forceinline Vec2( NegInfTy ) : x(neg_inf), y(neg_inf) {}
-
-#if defined(__WIN32__) && _MSC_VER == 1800 // workaround for older VS 2013 compiler
- __forceinline const T& operator [](const size_t axis) const { assert(axis < 2); return (&x)[axis]; }
- __forceinline T& operator [](const size_t axis) { assert(axis < 2); return (&x)[axis]; }
-#else
- __forceinline const T& operator [](const size_t axis) const { assert(axis < 2); return components[axis]; }
- __forceinline T& operator [](const size_t axis ) { assert(axis < 2); return components[axis]; }
-#endif
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a ) { return Vec2<T>(+a.x, +a.y); }
- template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a ) { return Vec2<T>(-a.x, -a.y); }
- template<typename T> __forceinline Vec2<T> abs ( const Vec2<T>& a ) { return Vec2<T>(abs (a.x), abs (a.y)); }
- template<typename T> __forceinline Vec2<T> rcp ( const Vec2<T>& a ) { return Vec2<T>(rcp (a.x), rcp (a.y)); }
- template<typename T> __forceinline Vec2<T> rsqrt ( const Vec2<T>& a ) { return Vec2<T>(rsqrt(a.x), rsqrt(a.y)); }
- template<typename T> __forceinline Vec2<T> sqrt ( const Vec2<T>& a ) { return Vec2<T>(sqrt (a.x), sqrt (a.y)); }
- template<typename T> __forceinline Vec2<T> frac ( const Vec2<T>& a ) { return Vec2<T>(frac (a.x), frac (a.y)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x + b.x, a.y + b.y); }
- template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x + b , a.y + b ); }
- template<typename T> __forceinline Vec2<T> operator +( const T& a, const Vec2<T>& b ) { return Vec2<T>(a + b.x, a + b.y); }
- template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x - b.x, a.y - b.y); }
- template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x - b , a.y - b ); }
- template<typename T> __forceinline Vec2<T> operator -( const T& a, const Vec2<T>& b ) { return Vec2<T>(a - b.x, a - b.y); }
- template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x * b.x, a.y * b.y); }
- template<typename T> __forceinline Vec2<T> operator *( const T& a, const Vec2<T>& b ) { return Vec2<T>(a * b.x, a * b.y); }
- template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x * b , a.y * b ); }
- template<typename T> __forceinline Vec2<T> operator /( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x / b.x, a.y / b.y); }
- template<typename T> __forceinline Vec2<T> operator /( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x / b , a.y / b ); }
- template<typename T> __forceinline Vec2<T> operator /( const T& a, const Vec2<T>& b ) { return Vec2<T>(a / b.x, a / b.y); }
-
- template<typename T> __forceinline Vec2<T> min(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(min(a.x, b.x), min(a.y, b.y)); }
- template<typename T> __forceinline Vec2<T> max(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(max(a.x, b.x), max(a.y, b.y)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec2<T> madd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y) ); }
- template<typename T> __forceinline Vec2<T> msub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y) ); }
- template<typename T> __forceinline Vec2<T> nmadd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y) ); }
- template<typename T> __forceinline Vec2<T> nmsub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y) ); }
-
- template<typename T> __forceinline Vec2<T> madd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a,b.x,c.x), madd(a,b.y,c.y) ); }
- template<typename T> __forceinline Vec2<T> msub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a,b.x,c.x), msub(a,b.y,c.y) ); }
- template<typename T> __forceinline Vec2<T> nmadd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y) ); }
- template<typename T> __forceinline Vec2<T> nmsub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y) ); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec2<T>& operator +=( Vec2<T>& a, const Vec2<T>& b ) { a.x += b.x; a.y += b.y; return a; }
- template<typename T> __forceinline Vec2<T>& operator -=( Vec2<T>& a, const Vec2<T>& b ) { a.x -= b.x; a.y -= b.y; return a; }
- template<typename T> __forceinline Vec2<T>& operator *=( Vec2<T>& a, const T& b ) { a.x *= b ; a.y *= b ; return a; }
- template<typename T> __forceinline Vec2<T>& operator /=( Vec2<T>& a, const T& b ) { a.x /= b ; a.y /= b ; return a; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline T reduce_add( const Vec2<T>& a ) { return a.x + a.y; }
- template<typename T> __forceinline T reduce_mul( const Vec2<T>& a ) { return a.x * a.y; }
- template<typename T> __forceinline T reduce_min( const Vec2<T>& a ) { return min(a.x, a.y); }
- template<typename T> __forceinline T reduce_max( const Vec2<T>& a ) { return max(a.x, a.y); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline bool operator ==( const Vec2<T>& a, const Vec2<T>& b ) { return a.x == b.x && a.y == b.y; }
- template<typename T> __forceinline bool operator !=( const Vec2<T>& a, const Vec2<T>& b ) { return a.x != b.x || a.y != b.y; }
- template<typename T> __forceinline bool operator < ( const Vec2<T>& a, const Vec2<T>& b ) {
- if (a.x != b.x) return a.x < b.x;
- if (a.y != b.y) return a.y < b.y;
- return false;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Shift Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec2<T> shift_right_1( const Vec2<T>& a ) {
- return Vec2<T>(shift_right_1(a.x),shift_right_1(a.y));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline T dot ( const Vec2<T>& a, const Vec2<T>& b ) { return madd(a.x,b.x,a.y*b.y); }
- template<typename T> __forceinline Vec2<T> cross ( const Vec2<T>& a ) { return Vec2<T>(-a.y,a.x); }
- template<typename T> __forceinline T length ( const Vec2<T>& a ) { return sqrt(dot(a,a)); }
- template<typename T> __forceinline Vec2<T> normalize( const Vec2<T>& a ) { return a*rsqrt(dot(a,a)); }
- template<typename T> __forceinline T distance ( const Vec2<T>& a, const Vec2<T>& b ) { return length(a-b); }
- template<typename T> __forceinline T det ( const Vec2<T>& a, const Vec2<T>& b ) { return a.x*b.y - a.y*b.x; }
-
- template<typename T> __forceinline Vec2<T> normalize_safe( const Vec2<T>& a ) {
- const T d = dot(a,a); return select(d == T( zero ),a, a*rsqrt(d) );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec2<T> select ( bool s, const Vec2<T>& t, const Vec2<T>& f ) {
- return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y));
- }
-
- template<typename T> __forceinline Vec2<T> select ( const Vec2<bool>& s, const Vec2<T>& t, const Vec2<T>& f ) {
- return Vec2<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y));
- }
-
- template<typename T> __forceinline Vec2<T> select ( const typename T::Bool& s, const Vec2<T>& t, const Vec2<T>& f ) {
- return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y));
- }
-
- template<typename T>
- __forceinline Vec2<T> lerp(const Vec2<T>& v0, const Vec2<T>& v1, const T& t) {
- return madd(Vec2<T>(T(1.0f)-t),v0,t*v1);
- }
-
- template<typename T> __forceinline int maxDim ( const Vec2<T>& a )
- {
- const Vec2<T> b = abs(a);
- if (b.x > b.y) return 0;
- else return 1;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Vec2<T>& a) {
- return cout << "(" << a.x << ", " << a.y << ")";
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Default template instantiations
- ////////////////////////////////////////////////////////////////////////////////
-
- typedef Vec2<bool > Vec2b;
- typedef Vec2<int > Vec2i;
- typedef Vec2<float> Vec2f;
-}
-
-#include "vec2fa.h"
-
-#if defined(__SSE__) || defined(__ARM_NEON)
-#include "../simd/sse.h"
-#endif
-
-#if defined(__AVX__)
-#include "../simd/avx.h"
-#endif
-
-#if defined(__AVX512F__)
-#include "../simd/avx512.h"
-#endif
-
-namespace embree
-{
- template<> __forceinline Vec2<float>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
-
-#if defined(__SSE__) || defined(__ARM_NEON)
- template<> __forceinline Vec2<vfloat4>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
-#endif
-
-#if defined(__AVX__)
- template<> __forceinline Vec2<vfloat8>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
-#endif
-
-#if defined(__AVX512F__)
- template<> __forceinline Vec2<vfloat16>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
-#endif
-}
diff --git a/thirdparty/embree-aarch64/common/math/vec2fa.h b/thirdparty/embree-aarch64/common/math/vec2fa.h
deleted file mode 100644
index 451ecd556c..0000000000
--- a/thirdparty/embree-aarch64/common/math/vec2fa.h
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/alloc.h"
-#include "math.h"
-#include "../simd/sse.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// SSE Vec2fa Type
- ////////////////////////////////////////////////////////////////////////////////
-
- struct __aligned(16) Vec2fa
- {
- ALIGNED_STRUCT_(16);
-
- typedef float Scalar;
- enum { N = 2 };
- union {
- __m128 m128;
- struct { float x,y,az,aw; };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec2fa( ) {}
- __forceinline Vec2fa( const __m128 a ) : m128(a) {}
-
- __forceinline Vec2fa ( const Vec2<float>& other ) { x = other.x; y = other.y; }
- __forceinline Vec2fa& operator =( const Vec2<float>& other ) { x = other.x; y = other.y; return *this; }
-
- __forceinline Vec2fa ( const Vec2fa& other ) { m128 = other.m128; }
- __forceinline Vec2fa& operator =( const Vec2fa& other ) { m128 = other.m128; return *this; }
-
- __forceinline explicit Vec2fa( const float a ) : m128(_mm_set1_ps(a)) {}
- __forceinline Vec2fa( const float x, const float y) : m128(_mm_set_ps(y, y, y, x)) {}
-
- __forceinline explicit Vec2fa( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
-
- __forceinline operator const __m128&() const { return m128; }
- __forceinline operator __m128&() { return m128; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline Vec2fa load( const void* const a ) {
- return Vec2fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, 0, -1, -1))));
- }
-
- static __forceinline Vec2fa loadu( const void* const a ) {
- return Vec2fa(_mm_and_ps(_mm_loadu_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, 0, -1, -1))));
- }
-
- static __forceinline void storeu ( void* ptr, const Vec2fa& v ) {
- _mm_storeu_ps((float*)ptr,v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec2fa( ZeroTy ) : m128(_mm_setzero_ps()) {}
- __forceinline Vec2fa( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
- __forceinline Vec2fa( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
- __forceinline Vec2fa( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const float& operator []( const size_t index ) const { assert(index < 2); return (&x)[index]; }
- __forceinline float& operator []( const size_t index ) { assert(index < 2); return (&x)[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec2fa operator +( const Vec2fa& a ) { return a; }
- __forceinline Vec2fa operator -( const Vec2fa& a ) {
- const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
- return _mm_xor_ps(a.m128, mask);
- }
- __forceinline Vec2fa abs ( const Vec2fa& a ) {
- const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
- return _mm_and_ps(a.m128, mask);
- }
- __forceinline Vec2fa sign ( const Vec2fa& a ) {
- return blendv_ps(Vec2fa(one), -Vec2fa(one), _mm_cmplt_ps (a,Vec2fa(zero)));
- }
-
- __forceinline Vec2fa rcp ( const Vec2fa& a )
- {
-#if defined(__aarch64__)
- __m128 reciprocal = _mm_rcp_ps(a.m128);
- reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
- reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
- return (const Vec2fa)reciprocal;
-#else
-#if defined(__AVX512VL__)
- const Vec2fa r = _mm_rcp14_ps(a.m128);
-#else
- const Vec2fa r = _mm_rcp_ps(a.m128);
-#endif
-
-#if defined(__AVX2__)
- const Vec2fa res = _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f)));
-#else
- const Vec2fa res = _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a)));
- //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
-#endif
-
- return res;
-#endif //defined(__aarch64__)
- }
-
- __forceinline Vec2fa sqrt ( const Vec2fa& a ) { return _mm_sqrt_ps(a.m128); }
- __forceinline Vec2fa sqr ( const Vec2fa& a ) { return _mm_mul_ps(a,a); }
-
- __forceinline Vec2fa rsqrt( const Vec2fa& a )
- {
-#if defined(__aarch64__)
- __m128 r = _mm_rsqrt_ps(a.m128);
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
- return r;
-#else
-
-#if defined(__AVX512VL__)
- __m128 r = _mm_rsqrt14_ps(a.m128);
-#else
- __m128 r = _mm_rsqrt_ps(a.m128);
-#endif
- return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
-
-#endif
- }
-
- __forceinline Vec2fa zero_fix(const Vec2fa& a) {
- return blendv_ps(a, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
- }
- __forceinline Vec2fa rcp_safe(const Vec2fa& a) {
- return rcp(zero_fix(a));
- }
- __forceinline Vec2fa log ( const Vec2fa& a ) {
- return Vec2fa(logf(a.x),logf(a.y));
- }
-
- __forceinline Vec2fa exp ( const Vec2fa& a ) {
- return Vec2fa(expf(a.x),expf(a.y));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec2fa operator +( const Vec2fa& a, const Vec2fa& b ) { return _mm_add_ps(a.m128, b.m128); }
- __forceinline Vec2fa operator -( const Vec2fa& a, const Vec2fa& b ) { return _mm_sub_ps(a.m128, b.m128); }
- __forceinline Vec2fa operator *( const Vec2fa& a, const Vec2fa& b ) { return _mm_mul_ps(a.m128, b.m128); }
- __forceinline Vec2fa operator *( const Vec2fa& a, const float b ) { return a * Vec2fa(b); }
- __forceinline Vec2fa operator *( const float a, const Vec2fa& b ) { return Vec2fa(a) * b; }
- __forceinline Vec2fa operator /( const Vec2fa& a, const Vec2fa& b ) { return _mm_div_ps(a.m128,b.m128); }
- __forceinline Vec2fa operator /( const Vec2fa& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
- __forceinline Vec2fa operator /( const float a, const Vec2fa& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
-
- __forceinline Vec2fa min( const Vec2fa& a, const Vec2fa& b ) { return _mm_min_ps(a.m128,b.m128); }
- __forceinline Vec2fa max( const Vec2fa& a, const Vec2fa& b ) { return _mm_max_ps(a.m128,b.m128); }
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
- __forceinline Vec2fa mini(const Vec2fa& a, const Vec2fa& b) {
- const vint4 ai = _mm_castps_si128(a);
- const vint4 bi = _mm_castps_si128(b);
- const vint4 ci = _mm_min_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-#endif
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
- __forceinline Vec2fa maxi(const Vec2fa& a, const Vec2fa& b) {
- const vint4 ai = _mm_castps_si128(a);
- const vint4 bi = _mm_castps_si128(b);
- const vint4 ci = _mm_max_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-#endif
-
- __forceinline Vec2fa pow ( const Vec2fa& a, const float& b ) {
- return Vec2fa(powf(a.x,b),powf(a.y,b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX2__)
- __forceinline Vec2fa madd ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return _mm_fmadd_ps(a,b,c); }
- __forceinline Vec2fa msub ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return _mm_fmsub_ps(a,b,c); }
- __forceinline Vec2fa nmadd ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return _mm_fnmadd_ps(a,b,c); }
- __forceinline Vec2fa nmsub ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return _mm_fnmsub_ps(a,b,c); }
-#else
- __forceinline Vec2fa madd ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return a*b+c; }
- __forceinline Vec2fa msub ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return a*b-c; }
- __forceinline Vec2fa nmadd ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return -a*b+c;}
- __forceinline Vec2fa nmsub ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return -a*b-c; }
-#endif
-
- __forceinline Vec2fa madd ( const float a, const Vec2fa& b, const Vec2fa& c) { return madd(Vec2fa(a),b,c); }
- __forceinline Vec2fa msub ( const float a, const Vec2fa& b, const Vec2fa& c) { return msub(Vec2fa(a),b,c); }
- __forceinline Vec2fa nmadd ( const float a, const Vec2fa& b, const Vec2fa& c) { return nmadd(Vec2fa(a),b,c); }
- __forceinline Vec2fa nmsub ( const float a, const Vec2fa& b, const Vec2fa& c) { return nmsub(Vec2fa(a),b,c); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec2fa& operator +=( Vec2fa& a, const Vec2fa& b ) { return a = a + b; }
- __forceinline Vec2fa& operator -=( Vec2fa& a, const Vec2fa& b ) { return a = a - b; }
- __forceinline Vec2fa& operator *=( Vec2fa& a, const Vec2fa& b ) { return a = a * b; }
- __forceinline Vec2fa& operator *=( Vec2fa& a, const float b ) { return a = a * b; }
- __forceinline Vec2fa& operator /=( Vec2fa& a, const Vec2fa& b ) { return a = a / b; }
- __forceinline Vec2fa& operator /=( Vec2fa& a, const float b ) { return a = a / b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline float reduce_add(const Vec2fa& v) { return v.x+v.y; }
- __forceinline float reduce_mul(const Vec2fa& v) { return v.x*v.y; }
- __forceinline float reduce_min(const Vec2fa& v) { return min(v.x,v.y); }
- __forceinline float reduce_max(const Vec2fa& v) { return max(v.x,v.y); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator ==( const Vec2fa& a, const Vec2fa& b ) { return (_mm_movemask_ps(_mm_cmpeq_ps (a.m128, b.m128)) & 3) == 3; }
- __forceinline bool operator !=( const Vec2fa& a, const Vec2fa& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 3) != 0; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__SSE4_1__)
- __forceinline float dot ( const Vec2fa& a, const Vec2fa& b ) {
- return _mm_cvtss_f32(_mm_dp_ps(a,b,0x3F));
- }
-#else
- __forceinline float dot ( const Vec2fa& a, const Vec2fa& b ) {
- return reduce_add(a*b);
- }
-#endif
-
- __forceinline Vec2fa cross ( const Vec2fa& a ) {
- return Vec2fa(-a.y,a.x);
- }
-
- __forceinline float sqr_length ( const Vec2fa& a ) { return dot(a,a); }
- __forceinline float rcp_length ( const Vec2fa& a ) { return rsqrt(dot(a,a)); }
- __forceinline float rcp_length2( const Vec2fa& a ) { return rcp(dot(a,a)); }
- __forceinline float length ( const Vec2fa& a ) { return sqrt(dot(a,a)); }
- __forceinline Vec2fa normalize( const Vec2fa& a ) { return a*rsqrt(dot(a,a)); }
- __forceinline float distance ( const Vec2fa& a, const Vec2fa& b ) { return length(a-b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec2fa select( bool s, const Vec2fa& t, const Vec2fa& f ) {
- __m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
- return blendv_ps(f, t, mask);
- }
-
- __forceinline Vec2fa lerp(const Vec2fa& v0, const Vec2fa& v1, const float t) {
- return madd(1.0f-t,v0,t*v1);
- }
-
- __forceinline int maxDim ( const Vec2fa& a )
- {
- const Vec2fa b = abs(a);
- if (b.x > b.y) return 0;
- else return 1;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Rounding Functions
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__aarch64__)
-__forceinline Vec2fa floor(const Vec2fa& a) { return vrndmq_f32(a); }
-__forceinline Vec2fa ceil (const Vec2fa& a) { return vrndpq_f32(a); }
-//__forceinline Vec2fa trunc(const Vec2fa& a) { return vrndq_f32(a); }
-#elif defined (__SSE4_1__)
- //__forceinline Vec2fa trunc( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
- __forceinline Vec2fa floor( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
- __forceinline Vec2fa ceil ( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
-#else
- //__forceinline Vec2fa trunc( const Vec2fa& a ) { return Vec2fa(truncf(a.x),truncf(a.y),truncf(a.z)); }
- __forceinline Vec2fa floor( const Vec2fa& a ) { return Vec2fa(floorf(a.x),floorf(a.y)); }
- __forceinline Vec2fa ceil ( const Vec2fa& a ) { return Vec2fa(ceilf (a.x),ceilf (a.y)); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator<<(embree_ostream cout, const Vec2fa& a) {
- return cout << "(" << a.x << ", " << a.y << ")";
- }
-
- typedef Vec2fa Vec2fa_t;
-}
diff --git a/thirdparty/embree-aarch64/common/math/vec3.h b/thirdparty/embree-aarch64/common/math/vec3.h
deleted file mode 100644
index 1870321715..0000000000
--- a/thirdparty/embree-aarch64/common/math/vec3.h
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "math.h"
-
-namespace embree
-{
- struct Vec3fa;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Generic 3D vector Class
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> struct Vec3
- {
- enum { N = 3 };
-
- union {
- struct {
- T x, y, z;
- };
-#if !(defined(__WIN32__) && _MSC_VER == 1800) // workaround for older VS 2013 compiler
- T components[N];
-#endif
- };
-
- typedef T Scalar;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3( ) {}
- __forceinline explicit Vec3( const T& a ) : x(a), y(a), z(a) {}
- __forceinline Vec3( const T& x, const T& y, const T& z ) : x(x), y(y), z(z) {}
-
- __forceinline Vec3( const Vec3& other ) { x = other.x; y = other.y; z = other.z; }
- __forceinline Vec3( const Vec3fa& other );
-
- template<typename T1> __forceinline Vec3( const Vec3<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)) {}
- template<typename T1> __forceinline Vec3& operator =(const Vec3<T1>& other) { x = other.x; y = other.y; z = other.z; return *this; }
-
- __forceinline Vec3& operator =(const Vec3& other) { x = other.x; y = other.y; z = other.z; return *this; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3( ZeroTy ) : x(zero), y(zero), z(zero) {}
- __forceinline Vec3( OneTy ) : x(one), y(one), z(one) {}
- __forceinline Vec3( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf) {}
- __forceinline Vec3( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf) {}
-
-#if defined(__WIN32__) && (_MSC_VER == 1800) // workaround for older VS 2013 compiler
- __forceinline const T& operator []( const size_t axis ) const { assert(axis < 3); return (&x)[axis]; }
- __forceinline T& operator []( const size_t axis ) { assert(axis < 3); return (&x)[axis]; }
-#else
- __forceinline const T& operator [](const size_t axis) const { assert(axis < 3); return components[axis]; }
- __forceinline T& operator [](const size_t axis) { assert(axis < 3); return components[axis]; }
-#endif
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec3<T> operator +( const Vec3<T>& a ) { return Vec3<T>(+a.x, +a.y, +a.z); }
- template<typename T> __forceinline Vec3<T> operator -( const Vec3<T>& a ) { return Vec3<T>(-a.x, -a.y, -a.z); }
- template<typename T> __forceinline Vec3<T> abs ( const Vec3<T>& a ) { return Vec3<T>(abs (a.x), abs (a.y), abs (a.z)); }
- template<typename T> __forceinline Vec3<T> rcp ( const Vec3<T>& a ) { return Vec3<T>(rcp (a.x), rcp (a.y), rcp (a.z)); }
- template<typename T> __forceinline Vec3<T> rsqrt ( const Vec3<T>& a ) { return Vec3<T>(rsqrt(a.x), rsqrt(a.y), rsqrt(a.z)); }
- template<typename T> __forceinline Vec3<T> sqrt ( const Vec3<T>& a ) { return Vec3<T>(sqrt (a.x), sqrt (a.y), sqrt (a.z)); }
-
- template<typename T> __forceinline Vec3<T> zero_fix( const Vec3<T>& a )
- {
- return Vec3<T>(select(abs(a.x)<min_rcp_input,T(min_rcp_input),a.x),
- select(abs(a.y)<min_rcp_input,T(min_rcp_input),a.y),
- select(abs(a.z)<min_rcp_input,T(min_rcp_input),a.z));
- }
- template<typename T> __forceinline Vec3<T> rcp_safe(const Vec3<T>& a) { return rcp(zero_fix(a)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec3<T> operator +( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x + b.x, a.y + b.y, a.z + b.z); }
- template<typename T> __forceinline Vec3<T> operator -( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x - b.x, a.y - b.y, a.z - b.z); }
- template<typename T> __forceinline Vec3<T> operator *( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x * b.x, a.y * b.y, a.z * b.z); }
- template<typename T> __forceinline Vec3<T> operator *( const T& a, const Vec3<T>& b ) { return Vec3<T>(a * b.x, a * b.y, a * b.z); }
- template<typename T> __forceinline Vec3<T> operator *( const Vec3<T>& a, const T& b ) { return Vec3<T>(a.x * b , a.y * b , a.z * b ); }
- template<typename T> __forceinline Vec3<T> operator /( const Vec3<T>& a, const T& b ) { return Vec3<T>(a.x / b , a.y / b , a.z / b ); }
- template<typename T> __forceinline Vec3<T> operator /( const T& a, const Vec3<T>& b ) { return Vec3<T>(a / b.x, a / b.y, a / b.z); }
- template<typename T> __forceinline Vec3<T> operator /( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x / b.x, a.y / b.y, a.z / b.z); }
-
- template<typename T> __forceinline Vec3<T> min(const Vec3<T>& a, const Vec3<T>& b) { return Vec3<T>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); }
- template<typename T> __forceinline Vec3<T> max(const Vec3<T>& a, const Vec3<T>& b) { return Vec3<T>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); }
-
- template<typename T> __forceinline Vec3<T> operator >>( const Vec3<T>& a, const int b ) { return Vec3<T>(a.x >> b, a.y >> b, a.z >> b); }
- template<typename T> __forceinline Vec3<T> operator <<( const Vec3<T>& a, const int b ) { return Vec3<T>(a.x << b, a.y << b, a.z << b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec3<T> madd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z)); }
- template<typename T> __forceinline Vec3<T> msub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z)); }
- template<typename T> __forceinline Vec3<T> nmadd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z));}
- template<typename T> __forceinline Vec3<T> nmsub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z)); }
-
- template<typename T> __forceinline Vec3<T> madd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z)); }
- template<typename T> __forceinline Vec3<T> msub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z)); }
- template<typename T> __forceinline Vec3<T> nmadd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z));}
- template<typename T> __forceinline Vec3<T> nmsub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const T b ) { a.x += b; a.y += b; a.z += b; return a; }
- template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const Vec3<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
- template<typename T> __forceinline Vec3<T>& operator -=( Vec3<T>& a, const Vec3<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
- template<typename T> __forceinline Vec3<T>& operator *=( Vec3<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; return a; }
- template<typename T> __forceinline Vec3<T>& operator /=( Vec3<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; return a; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline T reduce_add( const Vec3<T>& a ) { return a.x + a.y + a.z; }
- template<typename T> __forceinline T reduce_mul( const Vec3<T>& a ) { return a.x * a.y * a.z; }
- template<typename T> __forceinline T reduce_min( const Vec3<T>& a ) { return min(a.x, a.y, a.z); }
- template<typename T> __forceinline T reduce_max( const Vec3<T>& a ) { return max(a.x, a.y, a.z); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline bool operator ==( const Vec3<T>& a, const Vec3<T>& b ) { return a.x == b.x && a.y == b.y && a.z == b.z; }
- template<typename T> __forceinline bool operator !=( const Vec3<T>& a, const Vec3<T>& b ) { return a.x != b.x || a.y != b.y || a.z != b.z; }
- template<typename T> __forceinline bool operator < ( const Vec3<T>& a, const Vec3<T>& b ) {
- if (a.x != b.x) return a.x < b.x;
- if (a.y != b.y) return a.y < b.y;
- if (a.z != b.z) return a.z < b.z;
- return false;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Shift Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec3<T> shift_right_1( const Vec3<T>& a ) {
- return Vec3<T>(shift_right_1(a.x),shift_right_1(a.y),shift_right_1(a.z));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec3<T> select ( bool s, const Vec3<T>& t, const Vec3<T>& f ) {
- return Vec3<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z));
- }
-
- template<typename T> __forceinline Vec3<T> select ( const Vec3<bool>& s, const Vec3<T>& t, const Vec3<T>& f ) {
- return Vec3<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z));
- }
-
- template<typename T> __forceinline Vec3<T> select ( const typename T::Bool& s, const Vec3<T>& t, const Vec3<T>& f ) {
- return Vec3<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z));
- }
-
- template<typename T>
- __forceinline Vec3<T> lerp(const Vec3<T>& v0, const Vec3<T>& v1, const T& t) {
- return madd(Vec3<T>(T(1.0f)-t),v0,t*v1);
- }
-
- template<typename T> __forceinline int maxDim ( const Vec3<T>& a )
- {
- const Vec3<T> b = abs(a);
- if (b.x > b.y) {
- if (b.x > b.z) return 0; else return 2;
- } else {
- if (b.y > b.z) return 1; else return 2;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec3<bool> eq_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x==b.x,a.y==b.y,a.z==b.z); }
- template<typename T> __forceinline Vec3<bool> neq_mask(const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x!=b.x,a.y!=b.y,a.z!=b.z); }
- template<typename T> __forceinline Vec3<bool> lt_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x< b.x,a.y< b.y,a.z< b.z); }
- template<typename T> __forceinline Vec3<bool> le_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x<=b.x,a.y<=b.y,a.z<=b.z); }
- template<typename T> __forceinline Vec3<bool> gt_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x> b.x,a.y> b.y,a.z> b.z); }
- template<typename T> __forceinline Vec3<bool> ge_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x>=b.x,a.y>=b.y,a.z>=b.z); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline T sqr ( const Vec3<T>& a ) { return dot(a,a); }
- template<typename T> __forceinline T dot ( const Vec3<T>& a, const Vec3<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,a.z*b.z)); }
- template<typename T> __forceinline T length ( const Vec3<T>& a ) { return sqrt(sqr(a)); }
- template<typename T> __forceinline T rcp_length( const Vec3<T>& a ) { return rsqrt(sqr(a)); }
- template<typename T> __forceinline Vec3<T> normalize( const Vec3<T>& a ) { return a*rsqrt(sqr(a)); }
- template<typename T> __forceinline T distance ( const Vec3<T>& a, const Vec3<T>& b ) { return length(a-b); }
- template<typename T> __forceinline Vec3<T> cross ( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(prod_diff(a.y,b.z,a.z,b.y), prod_diff(a.z,b.x,a.x,b.z), prod_diff(a.x,b.y,a.y,b.x)); }
- template<typename T> __forceinline Vec3<T> stable_triangle_normal( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c )
- {
- const T ab_x = a.z*b.y, ab_y = a.x*b.z, ab_z = a.y*b.x;
- const T bc_x = b.z*c.y, bc_y = b.x*c.z, bc_z = b.y*c.x;
- const Vec3<T> cross_ab(msub(a.y,b.z,ab_x), msub(a.z,b.x,ab_y), msub(a.x,b.y,ab_z));
- const Vec3<T> cross_bc(msub(b.y,c.z,bc_x), msub(b.z,c.x,bc_y), msub(b.x,c.y,bc_z));
- const auto sx = abs(ab_x) < abs(bc_x);
- const auto sy = abs(ab_y) < abs(bc_y);
- const auto sz = abs(ab_z) < abs(bc_z);
- return Vec3<T>(select(sx,cross_ab.x,cross_bc.x),
- select(sy,cross_ab.y,cross_bc.y),
- select(sz,cross_ab.z,cross_bc.z));
- }
-
- template<typename T> __forceinline T sum ( const Vec3<T>& a ) { return a.x+a.y+a.z; }
-
- template<typename T> __forceinline T halfArea ( const Vec3<T>& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
- template<typename T> __forceinline T area ( const Vec3<T>& d ) { return 2.0f*halfArea(d); }
-
- template<typename T> __forceinline Vec3<T> normalize_safe( const Vec3<T>& a ) {
- const T d = dot(a,a); return select(d == T( zero ), a , a*rsqrt(d) );
- }
-
- template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& P, const Vec3<T>& Q0, const Vec3<T>& Q1)
- {
- const Vec3<T> N = cross(P-Q0,Q1-Q0);
- const Vec3<T> D = Q1-Q0;
- return dot(N,N)*rcp(dot(D,D));
- }
-
- template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& PmQ0, const Vec3<T>& Q1mQ0)
- {
- const Vec3<T> N = cross(PmQ0,Q1mQ0);
- const Vec3<T> D = Q1mQ0;
- return dot(N,N)*rcp(dot(D,D));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3<T>& a) {
- return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
- }
-
- typedef Vec3<bool > Vec3b;
- typedef Vec3<int > Vec3i;
- typedef Vec3<float> Vec3f;
-}
-
-#include "vec3ba.h"
-#include "vec3ia.h"
-#include "vec3fa.h"
-
-////////////////////////////////////////////////////////////////////////////////
-/// SSE / AVX / MIC specializations
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__SSE__) || defined(__ARM_NEON)
-#include "../simd/sse.h"
-#endif
-
-#if defined(__AVX__)
-#include "../simd/avx.h"
-#endif
-
-#if defined(__AVX512F__)
-#include "../simd/avx512.h"
-#endif
-
-namespace embree
-{
- template<typename Out, typename In>
- __forceinline Vec3<Out> broadcast(const Vec3<In>& a, const size_t k) {
- return Vec3<Out>(Out(a.x[k]), Out(a.y[k]), Out(a.z[k]));
- }
-
- template<> __forceinline Vec3<float>::Vec3(const Vec3fa& a) { x = a.x; y = a.y; z = a.z; }
-
-#if defined(__AVX__)
- template<> __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
- x = a.x; y = a.y; z = a.z;
- }
-#elif defined(__SSE__) || defined(__ARM_NEON)
- template<>
- __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
- const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
- }
-#endif
-
-#if defined(__SSE__) || defined(__ARM_NEON)
- __forceinline Vec3<vfloat4> broadcast4f(const Vec3<vfloat4>& a, const size_t k) {
- return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
- }
-
- template<>
- __forceinline Vec3<vfloat4> broadcast<vfloat4,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
- return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline Vec3<vfloat4> shuffle(const Vec3<vfloat4>& b) {
- return Vec3<vfloat4>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
- }
-#endif
-
-#if defined(__AVX__)
- template<>
- __forceinline Vec3<vfloat8>::Vec3(const Vec3fa& a) {
- x = a.x; y = a.y; z = a.z;
- }
- __forceinline Vec3<vfloat4> broadcast4f(const Vec3<vfloat8>& a, const size_t k) {
- return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
- }
- __forceinline Vec3<vfloat8> broadcast8f(const Vec3<vfloat4>& a, const size_t k) {
- return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
- }
- __forceinline Vec3<vfloat8> broadcast8f(const Vec3<vfloat8>& a, const size_t k) {
- return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
- }
-
- template<>
- __forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
- return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
- }
- template<>
- __forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat8>(const Vec3<vfloat8>& a, const size_t k) {
- return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline Vec3<vfloat8> shuffle(const Vec3<vfloat8>& b) {
- return Vec3<vfloat8>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
- }
-#endif
-
-#if defined(__AVX512F__)
- template<> __forceinline Vec3<vfloat16>::Vec3(const Vec3fa& a) : x(a.x), y(a.y), z(a.z) {}
-#endif
-}
diff --git a/thirdparty/embree-aarch64/common/math/vec3ba.h b/thirdparty/embree-aarch64/common/math/vec3ba.h
deleted file mode 100644
index 90f31739c2..0000000000
--- a/thirdparty/embree-aarch64/common/math/vec3ba.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/alloc.h"
-#include "math.h"
-#include "../simd/sse.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// SSE Vec3ba Type
- ////////////////////////////////////////////////////////////////////////////////
-
- struct __aligned(16) Vec3ba
- {
- ALIGNED_STRUCT_(16);
-
- union {
- __m128 m128;
- struct { int x,y,z; };
- };
-
- typedef int Scalar;
- enum { N = 3 };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ba( ) {}
- __forceinline Vec3ba( const __m128 input ) : m128(input) {}
- __forceinline Vec3ba( const Vec3ba& other ) : m128(other.m128) {}
- __forceinline Vec3ba& operator =(const Vec3ba& other) { m128 = other.m128; return *this; }
-
- __forceinline explicit Vec3ba( bool a )
- : m128(mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
- __forceinline Vec3ba( bool a, bool b, bool c)
- : m128(mm_lookupmask_ps[(size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
-
- __forceinline operator const __m128&() const { return m128; }
- __forceinline operator __m128&() { return m128; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ba( FalseTy ) : m128(_mm_setzero_ps()) {}
- __forceinline Vec3ba( TrueTy ) : m128(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const int& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
- __forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
- };
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ba operator !( const Vec3ba& a ) { return _mm_xor_ps(a.m128, Vec3ba(embree::True)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return _mm_and_ps(a.m128, b.m128); }
- __forceinline Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return _mm_or_ps (a.m128, b.m128); }
- __forceinline Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return _mm_xor_ps(a.m128, b.m128); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ba& operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
- __forceinline Vec3ba& operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
- __forceinline Vec3ba& operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator ==( const Vec3ba& a, const Vec3ba& b ) {
- return (_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_castps_si128(a.m128), _mm_castps_si128(b.m128)))) & 7) == 7;
- }
- __forceinline bool operator !=( const Vec3ba& a, const Vec3ba& b ) {
- return (_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_castps_si128(a.m128), _mm_castps_si128(b.m128)))) & 7) != 7;
- }
- __forceinline bool operator < ( const Vec3ba& a, const Vec3ba& b ) {
- if (a.x != b.x) return a.x < b.x;
- if (a.y != b.y) return a.y < b.y;
- if (a.z != b.z) return a.z < b.z;
- return false;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool reduce_and( const Vec3ba& a ) { return (_mm_movemask_ps(a) & 0x7) == 0x7; }
- __forceinline bool reduce_or ( const Vec3ba& a ) { return (_mm_movemask_ps(a) & 0x7) != 0x0; }
-
- __forceinline bool all ( const Vec3ba& b ) { return (_mm_movemask_ps(b) & 0x7) == 0x7; }
- __forceinline bool any ( const Vec3ba& b ) { return (_mm_movemask_ps(b) & 0x7) != 0x0; }
- __forceinline bool none ( const Vec3ba& b ) { return (_mm_movemask_ps(b) & 0x7) == 0x0; }
-
- __forceinline size_t movemask(const Vec3ba& a) { return _mm_movemask_ps(a) & 0x7; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3ba& a) {
- return cout << "(" << (a.x ? "1" : "0") << ", " << (a.y ? "1" : "0") << ", " << (a.z ? "1" : "0") << ")";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/math/vec3fa.h b/thirdparty/embree-aarch64/common/math/vec3fa.h
deleted file mode 100644
index 6163cfb596..0000000000
--- a/thirdparty/embree-aarch64/common/math/vec3fa.h
+++ /dev/null
@@ -1,810 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/alloc.h"
-#include "math.h"
-#include "../simd/sse.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// SSE Vec3fa Type
- ////////////////////////////////////////////////////////////////////////////////
-
- struct __aligned(16) Vec3fa
- {
- ALIGNED_STRUCT_(16);
-
- typedef float Scalar;
- enum { N = 3 };
- union {
- __m128 m128;
- struct { float x,y,z; };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fa( ) {}
- __forceinline Vec3fa( const __m128 a ) : m128(a) {}
-
- __forceinline Vec3fa ( const Vec3<float>& other ) { m128 = _mm_set_ps(0, other.z, other.y, other.x); }
- //__forceinline Vec3fa& operator =( const Vec3<float>& other ) { m128 = _mm_set_ps(0, other.z, other.y, other.x); return *this; }
-
- __forceinline Vec3fa ( const Vec3fa& other ) { m128 = other.m128; }
- __forceinline Vec3fa& operator =( const Vec3fa& other ) { m128 = other.m128; return *this; }
-
- __forceinline explicit Vec3fa( const float a ) : m128(_mm_set1_ps(a)) {}
- __forceinline Vec3fa( const float x, const float y, const float z) : m128(_mm_set_ps(0, z, y, x)) {}
-
- __forceinline explicit Vec3fa( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
-
- __forceinline explicit operator const vfloat4() const { return vfloat4(m128); }
- __forceinline explicit operator const vint4() const { return vint4(_mm_cvtps_epi32(m128)); }
- __forceinline explicit operator const Vec2fa() const { return Vec2fa(m128); }
- __forceinline explicit operator const Vec3ia() const { return Vec3ia(_mm_cvtps_epi32(m128)); }
-
- //__forceinline operator const __m128&() const { return m128; }
- //__forceinline operator __m128&() { return m128; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline Vec3fa load( const void* const a ) {
-#if defined(__aarch64__)
- __m128 t = _mm_load_ps((float*)a);
- t[3] = 0.0f;
- return Vec3fa(t);
-#else
- return Vec3fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
-#endif
- }
-
- static __forceinline Vec3fa loadu( const void* const a ) {
- return Vec3fa(_mm_loadu_ps((float*)a));
- }
-
- static __forceinline void storeu ( void* ptr, const Vec3fa& v ) {
- _mm_storeu_ps((float*)ptr,v.m128);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fa( ZeroTy ) : m128(_mm_setzero_ps()) {}
- __forceinline Vec3fa( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
- __forceinline Vec3fa( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
- __forceinline Vec3fa( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const float& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
- __forceinline float& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fa operator +( const Vec3fa& a ) { return a; }
- __forceinline Vec3fa operator -( const Vec3fa& a ) {
-#if defined(__aarch64__)
- return vnegq_f32(a.m128);
-#else
- const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
-
- return _mm_xor_ps(a.m128, mask);
-#endif
- }
- __forceinline Vec3fa abs ( const Vec3fa& a ) {
-#if defined(__aarch64__)
- return _mm_abs_ps(a.m128);
-#else
- const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
- return _mm_and_ps(a.m128, mask);
-#endif
- }
- __forceinline Vec3fa sign ( const Vec3fa& a ) {
-#if defined(__aarch64__)
- Vec3fa r = blendv_ps(vOne, vmOne, _mm_cmplt_ps (a.m128,vdupq_n_f32(0.0f)));
- return r;
-#else
- return blendv_ps(Vec3fa(one).m128, (-Vec3fa(one)).m128, _mm_cmplt_ps (a.m128,Vec3fa(zero).m128));
-#endif
- }
-
- __forceinline Vec3fa rcp ( const Vec3fa& a )
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- return vdivq_f32(vdupq_n_f32(1.0f),a.m128);
-#elif defined(__aarch64__)
- __m128 reciprocal = _mm_rcp_ps(a.m128);
- reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
- reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal);
- return (const Vec3fa)reciprocal;
-#else
-
-#if defined(__AVX512VL__)
- const Vec3fa r = _mm_rcp14_ps(a.m128);
-#else
- const Vec3fa r = _mm_rcp_ps(a.m128);
-#endif
-
-#if defined(__AVX2__)
- const Vec3fa res = _mm_mul_ps(r.m128,_mm_fnmadd_ps(r.m128, a.m128, vfloat4(2.0f)));
-#else
- const Vec3fa res = _mm_mul_ps(r.m128,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r.m128, a.m128)));
- //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
-#endif
-
- return res;
-#endif //defined(__aarch64__)
- }
-
- __forceinline Vec3fa sqrt ( const Vec3fa& a ) { return _mm_sqrt_ps(a.m128); }
- __forceinline Vec3fa sqr ( const Vec3fa& a ) { return _mm_mul_ps(a.m128,a.m128); }
-
- __forceinline Vec3fa rsqrt( const Vec3fa& a )
- {
-#if defined(__aarch64__)
- __m128 r = _mm_rsqrt_ps(a.m128);
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r));
- return r;
-#else
-
-#if defined(__AVX512VL__)
- __m128 r = _mm_rsqrt14_ps(a.m128);
-#else
- __m128 r = _mm_rsqrt_ps(a.m128);
-#endif
- return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a.m128, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
-#endif
- }
-
- __forceinline Vec3fa zero_fix(const Vec3fa& a) {
- return blendv_ps(a.m128, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
- }
- __forceinline Vec3fa rcp_safe(const Vec3fa& a) {
- return rcp(zero_fix(a));
- }
- __forceinline Vec3fa log ( const Vec3fa& a ) {
- return Vec3fa(logf(a.x),logf(a.y),logf(a.z));
- }
-
- __forceinline Vec3fa exp ( const Vec3fa& a ) {
- return Vec3fa(expf(a.x),expf(a.y),expf(a.z));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fa operator +( const Vec3fa& a, const Vec3fa& b ) { return _mm_add_ps(a.m128, b.m128); }
- __forceinline Vec3fa operator -( const Vec3fa& a, const Vec3fa& b ) { return _mm_sub_ps(a.m128, b.m128); }
- __forceinline Vec3fa operator *( const Vec3fa& a, const Vec3fa& b ) { return _mm_mul_ps(a.m128, b.m128); }
- __forceinline Vec3fa operator *( const Vec3fa& a, const float b ) { return a * Vec3fa(b); }
- __forceinline Vec3fa operator *( const float a, const Vec3fa& b ) { return Vec3fa(a) * b; }
- __forceinline Vec3fa operator /( const Vec3fa& a, const Vec3fa& b ) { return _mm_div_ps(a.m128,b.m128); }
- __forceinline Vec3fa operator /( const Vec3fa& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
- __forceinline Vec3fa operator /( const float a, const Vec3fa& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
-
- __forceinline Vec3fa min( const Vec3fa& a, const Vec3fa& b ) { return _mm_min_ps(a.m128,b.m128); }
- __forceinline Vec3fa max( const Vec3fa& a, const Vec3fa& b ) { return _mm_max_ps(a.m128,b.m128); }
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
- __forceinline Vec3fa mini(const Vec3fa& a, const Vec3fa& b) {
- const vint4 ai = _mm_castps_si128(a.m128);
- const vint4 bi = _mm_castps_si128(b.m128);
- const vint4 ci = _mm_min_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-#endif
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
- __forceinline Vec3fa maxi(const Vec3fa& a, const Vec3fa& b) {
- const vint4 ai = _mm_castps_si128(a.m128);
- const vint4 bi = _mm_castps_si128(b.m128);
- const vint4 ci = _mm_max_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-#endif
-
- __forceinline Vec3fa pow ( const Vec3fa& a, const float& b ) {
- return Vec3fa(powf(a.x,b),powf(a.y,b),powf(a.z,b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX2__)
- __forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fmadd_ps(a.m128,b.m128,c.m128); }
- __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fmsub_ps(a.m128,b.m128,c.m128); }
- __forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fnmadd_ps(a.m128,b.m128,c.m128); }
- __forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fnmsub_ps(a.m128,b.m128,c.m128); }
-#else
-
-#if defined(__aarch64__)
- __forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) {
- return _mm_madd_ps(a.m128, b.m128, c.m128); //a*b+c;
- }
- __forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) {
- return _mm_msub_ps(a.m128, b.m128, c.m128); //-a*b+c;
- }
- __forceinline Vec3fa nmsub( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) {
- Vec3fa t = _mm_madd_ps(a.m128, b.m128, c.m128);
- return -t;
- }
- __forceinline Vec3fa msub( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) {
- return _mm_madd_ps(a.m128,b.m128,vnegq_f32(c.m128)); //a*b-c
- }
-
-#else
- __forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b+c; }
- __forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b+c;}
- __forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b-c; }
- __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b-c; }
-#endif
-
-#endif
-
- __forceinline Vec3fa madd ( const float a, const Vec3fa& b, const Vec3fa& c) { return madd(Vec3fa(a),b,c); }
- __forceinline Vec3fa msub ( const float a, const Vec3fa& b, const Vec3fa& c) { return msub(Vec3fa(a),b,c); }
- __forceinline Vec3fa nmadd ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmadd(Vec3fa(a),b,c); }
- __forceinline Vec3fa nmsub ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmsub(Vec3fa(a),b,c); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fa& operator +=( Vec3fa& a, const Vec3fa& b ) { return a = a + b; }
- __forceinline Vec3fa& operator -=( Vec3fa& a, const Vec3fa& b ) { return a = a - b; }
- __forceinline Vec3fa& operator *=( Vec3fa& a, const Vec3fa& b ) { return a = a * b; }
- __forceinline Vec3fa& operator *=( Vec3fa& a, const float b ) { return a = a * b; }
- __forceinline Vec3fa& operator /=( Vec3fa& a, const Vec3fa& b ) { return a = a / b; }
- __forceinline Vec3fa& operator /=( Vec3fa& a, const float b ) { return a = a / b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-#if defined(__aarch64__) && defined(BUILD_IOS)
- __forceinline float reduce_add(const Vec3fa& v) {
- float32x4_t t = v.m128;
- t[3] = 0.0f;
- return vaddvq_f32(t);
- }
-
- __forceinline float reduce_mul(const Vec3fa& v) { return v.x*v.y*v.z; }
- __forceinline float reduce_min(const Vec3fa& v) {
- float32x4_t t = v.m128;
- t[3] = t[2];
- return vminvq_f32(t);
- }
- __forceinline float reduce_max(const Vec3fa& v) {
- float32x4_t t = v.m128;
- t[3] = t[2];
- return vmaxvq_f32(t);
- }
-#else
- __forceinline float reduce_add(const Vec3fa& v) {
- const vfloat4 a(v.m128);
- const vfloat4 b = shuffle<1>(a);
- const vfloat4 c = shuffle<2>(a);
- return _mm_cvtss_f32(a+b+c);
- }
-
- __forceinline float reduce_mul(const Vec3fa& v) { return v.x*v.y*v.z; }
- __forceinline float reduce_min(const Vec3fa& v) { return min(v.x,v.y,v.z); }
- __forceinline float reduce_max(const Vec3fa& v) { return max(v.x,v.y,v.z); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator ==( const Vec3fa& a, const Vec3fa& b ) { return (_mm_movemask_ps(_mm_cmpeq_ps (a.m128, b.m128)) & 7) == 7; }
- __forceinline bool operator !=( const Vec3fa& a, const Vec3fa& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 7) != 0; }
-
- __forceinline Vec3ba eq_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpeq_ps (a.m128, b.m128); }
- __forceinline Vec3ba neq_mask(const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpneq_ps(a.m128, b.m128); }
- __forceinline Vec3ba lt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmplt_ps (a.m128, b.m128); }
- __forceinline Vec3ba le_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmple_ps (a.m128, b.m128); }
- #if defined(__aarch64__)
- __forceinline Vec3ba gt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpgt_ps (a.m128, b.m128); }
- __forceinline Vec3ba ge_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpge_ps (a.m128, b.m128); }
-#else
- __forceinline Vec3ba gt_mask(const Vec3fa& a, const Vec3fa& b) { return _mm_cmpnle_ps(a.m128, b.m128); }
- __forceinline Vec3ba ge_mask(const Vec3fa& a, const Vec3fa& b) { return _mm_cmpnlt_ps(a.m128, b.m128); }
-#endif
-
- __forceinline bool isvalid ( const Vec3fa& v ) {
- return all(gt_mask(v,Vec3fa(-FLT_LARGE)) & lt_mask(v,Vec3fa(+FLT_LARGE)));
- }
-
- __forceinline bool is_finite ( const Vec3fa& a ) {
- return all(ge_mask(a,Vec3fa(-FLT_MAX)) & le_mask(a,Vec3fa(+FLT_MAX)));
- }
-
- __forceinline bool isvalid4 ( const Vec3fa& v ) {
- return all((vfloat4(v.m128) > vfloat4(-FLT_LARGE)) & (vfloat4(v.m128) < vfloat4(+FLT_LARGE)));
- }
-
- __forceinline bool is_finite4 ( const Vec3fa& a ) {
- return all((vfloat4(a.m128) >= vfloat4(-FLT_MAX)) & (vfloat4(a.m128) <= vfloat4(+FLT_MAX)));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__SSE4_1__)
- __forceinline float dot ( const Vec3fa& a, const Vec3fa& b ) {
- return _mm_cvtss_f32(_mm_dp_ps(a.m128,b.m128,0x7F));
- }
-#else
- __forceinline float dot ( const Vec3fa& a, const Vec3fa& b ) {
- return reduce_add(a*b);
- }
-#endif
-
- __forceinline Vec3fa cross ( const Vec3fa& a, const Vec3fa& b )
- {
- vfloat4 a0 = vfloat4(a.m128);
- vfloat4 b0 = shuffle<1,2,0,3>(vfloat4(b.m128));
- vfloat4 a1 = shuffle<1,2,0,3>(vfloat4(a.m128));
- vfloat4 b1 = vfloat4(b.m128);
- return Vec3fa(shuffle<1,2,0,3>(prod_diff(a0,b0,a1,b1)));
- }
-
- __forceinline float sqr_length ( const Vec3fa& a ) { return dot(a,a); }
- __forceinline float rcp_length ( const Vec3fa& a ) { return rsqrt(dot(a,a)); }
- __forceinline float rcp_length2( const Vec3fa& a ) { return rcp(dot(a,a)); }
- __forceinline float length ( const Vec3fa& a ) { return sqrt(dot(a,a)); }
- __forceinline Vec3fa normalize( const Vec3fa& a ) { return a*rsqrt(dot(a,a)); }
- __forceinline float distance ( const Vec3fa& a, const Vec3fa& b ) { return length(a-b); }
- __forceinline float halfArea ( const Vec3fa& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
- __forceinline float area ( const Vec3fa& d ) { return 2.0f*halfArea(d); }
-
- __forceinline Vec3fa normalize_safe( const Vec3fa& a ) {
- const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
- }
-
- /*! differentiated normalization */
- __forceinline Vec3fa dnormalize(const Vec3fa& p, const Vec3fa& dp)
- {
- const float pp = dot(p,p);
- const float pdp = dot(p,dp);
- return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fa select( bool s, const Vec3fa& t, const Vec3fa& f ) {
- __m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
- return blendv_ps(f.m128, t.m128, mask);
- }
-
- __forceinline Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
- return blendv_ps(f.m128, t.m128, s);
- }
-
- __forceinline Vec3fa lerp(const Vec3fa& v0, const Vec3fa& v1, const float t) {
- return madd(1.0f-t,v0,t*v1);
- }
-
- __forceinline int maxDim ( const Vec3fa& a )
- {
- const Vec3fa b = abs(a);
- if (b.x > b.y) {
- if (b.x > b.z) return 0; else return 2;
- } else {
- if (b.y > b.z) return 1; else return 2;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Rounding Functions
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__aarch64__)
- __forceinline Vec3fa floor(const Vec3fa& a) { return vrndmq_f32(a.m128); }
- __forceinline Vec3fa ceil (const Vec3fa& a) { return vrndpq_f32(a.m128); }
- __forceinline Vec3fa trunc(const Vec3fa& a) { return vrndq_f32(a.m128); }
-#elif defined (__SSE4_1__)
- __forceinline Vec3fa trunc( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEAREST_INT); }
- __forceinline Vec3fa floor( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEG_INF ); }
- __forceinline Vec3fa ceil ( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_POS_INF ); }
-#else
- __forceinline Vec3fa trunc( const Vec3fa& a ) { return Vec3fa(truncf(a.x),truncf(a.y),truncf(a.z)); }
- __forceinline Vec3fa floor( const Vec3fa& a ) { return Vec3fa(floorf(a.x),floorf(a.y),floorf(a.z)); }
- __forceinline Vec3fa ceil ( const Vec3fa& a ) { return Vec3fa(ceilf (a.x),ceilf (a.y),ceilf (a.z)); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3fa& a) {
- return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
- }
-
- typedef Vec3fa Vec3fa_t;
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// SSE Vec3fx Type
- ////////////////////////////////////////////////////////////////////////////////
-
- struct __aligned(16) Vec3fx
- {
- ALIGNED_STRUCT_(16);
-
- typedef float Scalar;
- enum { N = 3 };
- union {
- __m128 m128;
- struct { float x,y,z; union { int a; unsigned u; float w; }; };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fx( ) {}
- __forceinline Vec3fx( const __m128 a ) : m128(a) {}
-
- __forceinline explicit Vec3fx(const Vec3fa& v) : m128(v.m128) {}
- __forceinline operator Vec3fa () const { return Vec3fa(m128); }
-
- __forceinline explicit Vec3fx ( const Vec3<float>& other ) { m128 = _mm_set_ps(0, other.z, other.y, other.x); }
- //__forceinline Vec3fx& operator =( const Vec3<float>& other ) { m128 = _mm_set_ps(0, other.z, other.y, other.x); return *this; }
-
- __forceinline Vec3fx ( const Vec3fx& other ) { m128 = other.m128; }
-
- __forceinline Vec3fx& operator =( const Vec3fx& other ) { m128 = other.m128; return *this; }
-
- __forceinline explicit Vec3fx( const float a ) : m128(_mm_set1_ps(a)) {}
- __forceinline Vec3fx( const float x, const float y, const float z) : m128(_mm_set_ps(0, z, y, x)) {}
-
- __forceinline Vec3fx( const Vec3fa& other, const int a1) { m128 = other.m128; a = a1; }
- __forceinline Vec3fx( const Vec3fa& other, const unsigned a1) { m128 = other.m128; u = a1; }
- __forceinline Vec3fx( const Vec3fa& other, const float w1) {
-#if defined (__aarch64__)
- m128 = other.m128; m128[3] = w1;
-#elif defined (__SSE4_1__)
- m128 = _mm_insert_ps(other.m128, _mm_set_ss(w1),3 << 4);
-#else
- const vint4 mask(-1,-1,-1,0);
- m128 = select(vboolf4(_mm_castsi128_ps(mask)),vfloat4(other.m128),vfloat4(w1));
-#endif
- }
- //__forceinline Vec3fx( const float x, const float y, const float z, const int a) : x(x), y(y), z(z), a(a) {} // not working properly!
- //__forceinline Vec3fx( const float x, const float y, const float z, const unsigned a) : x(x), y(y), z(z), u(a) {} // not working properly!
- __forceinline Vec3fx( const float x, const float y, const float z, const float w) : m128(_mm_set_ps(w, z, y, x)) {}
-
- //__forceinline explicit Vec3fx( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
-
- __forceinline explicit operator const vfloat4() const { return vfloat4(m128); }
- __forceinline explicit operator const vint4() const { return vint4(_mm_cvtps_epi32(m128)); }
- __forceinline explicit operator const Vec2fa() const { return Vec2fa(m128); }
- __forceinline explicit operator const Vec3ia() const { return Vec3ia(_mm_cvtps_epi32(m128)); }
-
- //__forceinline operator const __m128&() const { return m128; }
- //__forceinline operator __m128&() { return m128; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline Vec3fx load( const void* const a ) {
- return Vec3fx(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
- }
-
- static __forceinline Vec3fx loadu( const void* const a ) {
- return Vec3fx(_mm_loadu_ps((float*)a));
- }
-
- static __forceinline void storeu ( void* ptr, const Vec3fx& v ) {
- _mm_storeu_ps((float*)ptr,v.m128);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fx( ZeroTy ) : m128(_mm_setzero_ps()) {}
- __forceinline Vec3fx( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
- __forceinline Vec3fx( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
- __forceinline Vec3fx( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const float& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
- __forceinline float& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fx operator +( const Vec3fx& a ) { return a; }
- __forceinline Vec3fx operator -( const Vec3fx& a ) {
- const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
- return _mm_xor_ps(a.m128, mask);
- }
- __forceinline Vec3fx abs ( const Vec3fx& a ) {
- const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
- return _mm_and_ps(a.m128, mask);
- }
- __forceinline Vec3fx sign ( const Vec3fx& a ) {
- return blendv_ps(Vec3fx(one).m128, (-Vec3fx(one)).m128, _mm_cmplt_ps (a.m128,Vec3fx(zero).m128));
- }
-
- __forceinline Vec3fx rcp ( const Vec3fx& a )
- {
-#if defined(__AVX512VL__)
- const Vec3fx r = _mm_rcp14_ps(a.m128);
-#else
- const Vec3fx r = _mm_rcp_ps(a.m128);
-#endif
-
-#if defined(__AVX2__)
- const Vec3fx res = _mm_mul_ps(r.m128,_mm_fnmadd_ps(r.m128, a.m128, vfloat4(2.0f)));
-#else
- const Vec3fx res = _mm_mul_ps(r.m128,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r.m128, a.m128)));
- //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
-#endif
-
- return res;
- }
-
- __forceinline Vec3fx sqrt ( const Vec3fx& a ) { return _mm_sqrt_ps(a.m128); }
- __forceinline Vec3fx sqr ( const Vec3fx& a ) { return _mm_mul_ps(a.m128,a.m128); }
-
- __forceinline Vec3fx rsqrt( const Vec3fx& a )
- {
-#if defined(__AVX512VL__)
- __m128 r = _mm_rsqrt14_ps(a.m128);
-#else
- __m128 r = _mm_rsqrt_ps(a.m128);
-#endif
- return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a.m128, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
- }
-
- __forceinline Vec3fx zero_fix(const Vec3fx& a) {
- return blendv_ps(a.m128, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
- }
- __forceinline Vec3fx rcp_safe(const Vec3fx& a) {
- return rcp(zero_fix(a));
- }
- __forceinline Vec3fx log ( const Vec3fx& a ) {
- return Vec3fx(logf(a.x),logf(a.y),logf(a.z));
- }
-
- __forceinline Vec3fx exp ( const Vec3fx& a ) {
- return Vec3fx(expf(a.x),expf(a.y),expf(a.z));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fx operator +( const Vec3fx& a, const Vec3fx& b ) { return _mm_add_ps(a.m128, b.m128); }
- __forceinline Vec3fx operator -( const Vec3fx& a, const Vec3fx& b ) { return _mm_sub_ps(a.m128, b.m128); }
- __forceinline Vec3fx operator *( const Vec3fx& a, const Vec3fx& b ) { return _mm_mul_ps(a.m128, b.m128); }
- __forceinline Vec3fx operator *( const Vec3fx& a, const float b ) { return a * Vec3fx(b); }
- __forceinline Vec3fx operator *( const float a, const Vec3fx& b ) { return Vec3fx(a) * b; }
- __forceinline Vec3fx operator /( const Vec3fx& a, const Vec3fx& b ) { return _mm_div_ps(a.m128,b.m128); }
- __forceinline Vec3fx operator /( const Vec3fx& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
- __forceinline Vec3fx operator /( const float a, const Vec3fx& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
-
- __forceinline Vec3fx min( const Vec3fx& a, const Vec3fx& b ) { return _mm_min_ps(a.m128,b.m128); }
- __forceinline Vec3fx max( const Vec3fx& a, const Vec3fx& b ) { return _mm_max_ps(a.m128,b.m128); }
-
-#if defined(__SSE4_1__) || defined(__aarch64__)
- __forceinline Vec3fx mini(const Vec3fx& a, const Vec3fx& b) {
- const vint4 ai = _mm_castps_si128(a.m128);
- const vint4 bi = _mm_castps_si128(b.m128);
- const vint4 ci = _mm_min_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-#endif
-
-#if defined(__SSE4_1__) || defined(__aarch64__)
- __forceinline Vec3fx maxi(const Vec3fx& a, const Vec3fx& b) {
- const vint4 ai = _mm_castps_si128(a.m128);
- const vint4 bi = _mm_castps_si128(b.m128);
- const vint4 ci = _mm_max_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-#endif
-
- __forceinline Vec3fx pow ( const Vec3fx& a, const float& b ) {
- return Vec3fx(powf(a.x,b),powf(a.y,b),powf(a.z,b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX2__)
- __forceinline Vec3fx madd ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return _mm_fmadd_ps(a.m128,b.m128,c.m128); }
- __forceinline Vec3fx msub ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return _mm_fmsub_ps(a.m128,b.m128,c.m128); }
- __forceinline Vec3fx nmadd ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return _mm_fnmadd_ps(a.m128,b.m128,c.m128); }
- __forceinline Vec3fx nmsub ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return _mm_fnmsub_ps(a.m128,b.m128,c.m128); }
-#else
- __forceinline Vec3fx madd ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return a*b+c; }
- __forceinline Vec3fx msub ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return a*b-c; }
- __forceinline Vec3fx nmadd ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return -a*b+c;}
- __forceinline Vec3fx nmsub ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return -a*b-c; }
-#endif
-
- __forceinline Vec3fx madd ( const float a, const Vec3fx& b, const Vec3fx& c) { return madd(Vec3fx(a),b,c); }
- __forceinline Vec3fx msub ( const float a, const Vec3fx& b, const Vec3fx& c) { return msub(Vec3fx(a),b,c); }
- __forceinline Vec3fx nmadd ( const float a, const Vec3fx& b, const Vec3fx& c) { return nmadd(Vec3fx(a),b,c); }
- __forceinline Vec3fx nmsub ( const float a, const Vec3fx& b, const Vec3fx& c) { return nmsub(Vec3fx(a),b,c); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fx& operator +=( Vec3fx& a, const Vec3fx& b ) { return a = a + b; }
- __forceinline Vec3fx& operator -=( Vec3fx& a, const Vec3fx& b ) { return a = a - b; }
- __forceinline Vec3fx& operator *=( Vec3fx& a, const Vec3fx& b ) { return a = a * b; }
- __forceinline Vec3fx& operator *=( Vec3fx& a, const float b ) { return a = a * b; }
- __forceinline Vec3fx& operator /=( Vec3fx& a, const Vec3fx& b ) { return a = a / b; }
- __forceinline Vec3fx& operator /=( Vec3fx& a, const float b ) { return a = a / b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline float reduce_add(const Vec3fx& v) {
- const vfloat4 a(v.m128);
- const vfloat4 b = shuffle<1>(a);
- const vfloat4 c = shuffle<2>(a);
- return _mm_cvtss_f32(a+b+c);
- }
-
- __forceinline float reduce_mul(const Vec3fx& v) { return v.x*v.y*v.z; }
- __forceinline float reduce_min(const Vec3fx& v) { return min(v.x,v.y,v.z); }
- __forceinline float reduce_max(const Vec3fx& v) { return max(v.x,v.y,v.z); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator ==( const Vec3fx& a, const Vec3fx& b ) { return (_mm_movemask_ps(_mm_cmpeq_ps (a.m128, b.m128)) & 7) == 7; }
- __forceinline bool operator !=( const Vec3fx& a, const Vec3fx& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 7) != 0; }
-
- __forceinline Vec3ba eq_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmpeq_ps (a.m128, b.m128); }
- __forceinline Vec3ba neq_mask(const Vec3fx& a, const Vec3fx& b ) { return _mm_cmpneq_ps(a.m128, b.m128); }
- __forceinline Vec3ba lt_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmplt_ps (a.m128, b.m128); }
- __forceinline Vec3ba le_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmple_ps (a.m128, b.m128); }
- __forceinline Vec3ba gt_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmpnle_ps(a.m128, b.m128); }
- __forceinline Vec3ba ge_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); }
-
- __forceinline bool isvalid ( const Vec3fx& v ) {
- return all(gt_mask(v,Vec3fx(-FLT_LARGE)) & lt_mask(v,Vec3fx(+FLT_LARGE)));
- }
-
- __forceinline bool is_finite ( const Vec3fx& a ) {
- return all(ge_mask(a,Vec3fx(-FLT_MAX)) & le_mask(a,Vec3fx(+FLT_MAX)));
- }
-
- __forceinline bool isvalid4 ( const Vec3fx& v ) {
- return all((vfloat4(v.m128) > vfloat4(-FLT_LARGE)) & (vfloat4(v.m128) < vfloat4(+FLT_LARGE)));
- }
-
- __forceinline bool is_finite4 ( const Vec3fx& a ) {
- return all((vfloat4(a.m128) >= vfloat4(-FLT_MAX)) & (vfloat4(a.m128) <= vfloat4(+FLT_MAX)));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__SSE4_1__)
- __forceinline float dot ( const Vec3fx& a, const Vec3fx& b ) {
- return _mm_cvtss_f32(_mm_dp_ps(a.m128,b.m128,0x7F));
- }
-#else
- __forceinline float dot ( const Vec3fx& a, const Vec3fx& b ) {
- return reduce_add(a*b);
- }
-#endif
-
- __forceinline Vec3fx cross ( const Vec3fx& a, const Vec3fx& b )
- {
- vfloat4 a0 = vfloat4(a.m128);
- vfloat4 b0 = shuffle<1,2,0,3>(vfloat4(b.m128));
- vfloat4 a1 = shuffle<1,2,0,3>(vfloat4(a.m128));
- vfloat4 b1 = vfloat4(b.m128);
- return Vec3fx(shuffle<1,2,0,3>(msub(a0,b0,a1*b1)));
- }
-
- __forceinline float sqr_length ( const Vec3fx& a ) { return dot(a,a); }
- __forceinline float rcp_length ( const Vec3fx& a ) { return rsqrt(dot(a,a)); }
- __forceinline float rcp_length2( const Vec3fx& a ) { return rcp(dot(a,a)); }
- __forceinline float length ( const Vec3fx& a ) { return sqrt(dot(a,a)); }
- __forceinline Vec3fx normalize( const Vec3fx& a ) { return a*rsqrt(dot(a,a)); }
- __forceinline float distance ( const Vec3fx& a, const Vec3fx& b ) { return length(a-b); }
- __forceinline float halfArea ( const Vec3fx& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
- __forceinline float area ( const Vec3fx& d ) { return 2.0f*halfArea(d); }
-
- __forceinline Vec3fx normalize_safe( const Vec3fx& a ) {
- const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
- }
-
- /*! differentiated normalization */
- __forceinline Vec3fx dnormalize(const Vec3fx& p, const Vec3fx& dp)
- {
- const float pp = dot(p,p);
- const float pdp = dot(p,dp);
- return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3fx select( bool s, const Vec3fx& t, const Vec3fx& f ) {
- __m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
- return blendv_ps(f.m128, t.m128, mask);
- }
-
- __forceinline Vec3fx select( const Vec3ba& s, const Vec3fx& t, const Vec3fx& f ) {
- return blendv_ps(f.m128, t.m128, s);
- }
-
- __forceinline Vec3fx lerp(const Vec3fx& v0, const Vec3fx& v1, const float t) {
- return madd(1.0f-t,v0,t*v1);
- }
-
- __forceinline int maxDim ( const Vec3fx& a )
- {
- const Vec3fx b = abs(a);
- if (b.x > b.y) {
- if (b.x > b.z) return 0; else return 2;
- } else {
- if (b.y > b.z) return 1; else return 2;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Rounding Functions
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined (__SSE4_1__) && !defined(__aarch64__)
- __forceinline Vec3fx trunc( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEAREST_INT); }
- __forceinline Vec3fx floor( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEG_INF ); }
- __forceinline Vec3fx ceil ( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_POS_INF ); }
-#else
- __forceinline Vec3fx trunc( const Vec3fx& a ) { return Vec3fx(truncf(a.x),truncf(a.y),truncf(a.z)); }
- __forceinline Vec3fx floor( const Vec3fx& a ) { return Vec3fx(floorf(a.x),floorf(a.y),floorf(a.z)); }
- __forceinline Vec3fx ceil ( const Vec3fx& a ) { return Vec3fx(ceilf (a.x),ceilf (a.y),ceilf (a.z)); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3fx& a) {
- return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
- }
-
-
- typedef Vec3fx Vec3ff;
-}
diff --git a/thirdparty/embree-aarch64/common/math/vec3ia.h b/thirdparty/embree-aarch64/common/math/vec3ia.h
deleted file mode 100644
index 737f67fd72..0000000000
--- a/thirdparty/embree-aarch64/common/math/vec3ia.h
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/alloc.h"
-#include "math.h"
-#include "../simd/sse.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// SSE Vec3ia Type
- ////////////////////////////////////////////////////////////////////////////////
-
- struct __aligned(16) Vec3ia
- {
- ALIGNED_STRUCT_(16);
-
- union {
- __m128i m128;
- struct { int x,y,z; };
- };
-
- typedef int Scalar;
- enum { N = 3 };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ia( ) {}
- __forceinline Vec3ia( const __m128i a ) : m128(a) {}
- __forceinline Vec3ia( const Vec3ia& other ) : m128(other.m128) {}
- __forceinline Vec3ia& operator =(const Vec3ia& other) { m128 = other.m128; return *this; }
-
- __forceinline explicit Vec3ia( const int a ) : m128(_mm_set1_epi32(a)) {}
- __forceinline Vec3ia( const int x, const int y, const int z) : m128(_mm_set_epi32(z, z, y, x)) {}
- __forceinline explicit Vec3ia( const __m128 a ) : m128(_mm_cvtps_epi32(a)) {}
-
- __forceinline operator const __m128i&() const { return m128; }
- __forceinline operator __m128i&() { return m128; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ia( ZeroTy ) : m128(_mm_setzero_si128()) {}
- __forceinline Vec3ia( OneTy ) : m128(_mm_set1_epi32(1)) {}
- __forceinline Vec3ia( PosInfTy ) : m128(_mm_set1_epi32(pos_inf)) {}
- __forceinline Vec3ia( NegInfTy ) : m128(_mm_set1_epi32(neg_inf)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const int& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
- __forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
- };
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ia operator +( const Vec3ia& a ) { return a; }
- __forceinline Vec3ia operator -( const Vec3ia& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
-#if (defined(__aarch64__))
- __forceinline Vec3ia abs ( const Vec3ia& a ) { return vabsq_s32(a.m128); }
-#elif defined(__SSSE3__)
- __forceinline Vec3ia abs ( const Vec3ia& a ) { return _mm_abs_epi32(a.m128); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ia operator +( const Vec3ia& a, const Vec3ia& b ) { return _mm_add_epi32(a.m128, b.m128); }
- __forceinline Vec3ia operator +( const Vec3ia& a, const int b ) { return a+Vec3ia(b); }
- __forceinline Vec3ia operator +( const int a, const Vec3ia& b ) { return Vec3ia(a)+b; }
-
- __forceinline Vec3ia operator -( const Vec3ia& a, const Vec3ia& b ) { return _mm_sub_epi32(a.m128, b.m128); }
- __forceinline Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); }
- __forceinline Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; }
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
- __forceinline Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
- __forceinline Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); }
- __forceinline Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; }
-#endif
-
- __forceinline Vec3ia operator &( const Vec3ia& a, const Vec3ia& b ) { return _mm_and_si128(a.m128, b.m128); }
- __forceinline Vec3ia operator &( const Vec3ia& a, const int b ) { return a & Vec3ia(b); }
- __forceinline Vec3ia operator &( const int a, const Vec3ia& b ) { return Vec3ia(a) & b; }
-
- __forceinline Vec3ia operator |( const Vec3ia& a, const Vec3ia& b ) { return _mm_or_si128(a.m128, b.m128); }
- __forceinline Vec3ia operator |( const Vec3ia& a, const int b ) { return a | Vec3ia(b); }
- __forceinline Vec3ia operator |( const int a, const Vec3ia& b ) { return Vec3ia(a) | b; }
-
- __forceinline Vec3ia operator ^( const Vec3ia& a, const Vec3ia& b ) { return _mm_xor_si128(a.m128, b.m128); }
- __forceinline Vec3ia operator ^( const Vec3ia& a, const int b ) { return a ^ Vec3ia(b); }
- __forceinline Vec3ia operator ^( const int a, const Vec3ia& b ) { return Vec3ia(a) ^ b; }
-
-#if !defined(__ARM_NEON)
- __forceinline Vec3ia operator <<( const Vec3ia& a, const int n ) { return _mm_slli_epi32(a.m128, n); }
- __forceinline Vec3ia operator >>( const Vec3ia& a, const int n ) { return _mm_srai_epi32(a.m128, n); }
-
- __forceinline Vec3ia sll ( const Vec3ia& a, const int b ) { return _mm_slli_epi32(a.m128, b); }
- __forceinline Vec3ia sra ( const Vec3ia& a, const int b ) { return _mm_srai_epi32(a.m128, b); }
- __forceinline Vec3ia srl ( const Vec3ia& a, const int b ) { return _mm_srli_epi32(a.m128, b); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ia& operator +=( Vec3ia& a, const Vec3ia& b ) { return a = a + b; }
- __forceinline Vec3ia& operator +=( Vec3ia& a, const int& b ) { return a = a + b; }
-
- __forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia& b ) { return a = a - b; }
- __forceinline Vec3ia& operator -=( Vec3ia& a, const int& b ) { return a = a - b; }
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
- __forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia& b ) { return a = a * b; }
- __forceinline Vec3ia& operator *=( Vec3ia& a, const int& b ) { return a = a * b; }
-#endif
-
- __forceinline Vec3ia& operator &=( Vec3ia& a, const Vec3ia& b ) { return a = a & b; }
- __forceinline Vec3ia& operator &=( Vec3ia& a, const int& b ) { return a = a & b; }
-
- __forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia& b ) { return a = a | b; }
- __forceinline Vec3ia& operator |=( Vec3ia& a, const int& b ) { return a = a | b; }
-
-#if !defined(__ARM_NEON)
- __forceinline Vec3ia& operator <<=( Vec3ia& a, const int& b ) { return a = a << b; }
- __forceinline Vec3ia& operator >>=( Vec3ia& a, const int& b ) { return a = a >> b; }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-#if defined(__aarch64__)
- __forceinline int reduce_add(const Vec3ia& v) {
- int32x4_t t = v.m128;
- t[3] = 0;
- return vaddvq_s32(t);
-
- }
- __forceinline int reduce_mul(const Vec3ia& v) { return v.x*v.y*v.z; }
- __forceinline int reduce_min(const Vec3ia& v) {
- int32x4_t t = (__m128i)blendv_ps((__m128)v0x7fffffff, (__m128)v.m128, (__m128)vFFF0);
- return vminvq_s32(t);
-
- }
- __forceinline int reduce_max(const Vec3ia& v) {
- int32x4_t t = (__m128i)blendv_ps((__m128)v0x80000000, (__m128)v.m128, (__m128)vFFF0);
- return vmaxvq_s32(t);
-
- }
-#else
- __forceinline int reduce_add(const Vec3ia& v) { return v.x+v.y+v.z; }
- __forceinline int reduce_mul(const Vec3ia& v) { return v.x*v.y*v.z; }
- __forceinline int reduce_min(const Vec3ia& v) { return min(v.x,v.y,v.z); }
- __forceinline int reduce_max(const Vec3ia& v) { return max(v.x,v.y,v.z); }
-#endif
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator ==( const Vec3ia& a, const Vec3ia& b ) { return (_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(a.m128, b.m128))) & 7) == 7; }
- __forceinline bool operator !=( const Vec3ia& a, const Vec3ia& b ) { return (_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(a.m128, b.m128))) & 7) != 7; }
- __forceinline bool operator < ( const Vec3ia& a, const Vec3ia& b ) {
- if (a.x != b.x) return a.x < b.x;
- if (a.y != b.y) return a.y < b.y;
- if (a.z != b.z) return a.z < b.z;
- return false;
- }
-
- __forceinline Vec3ba eq_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32 (a.m128, b.m128)); }
- __forceinline Vec3ba lt_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmplt_epi32 (a.m128, b.m128)); }
- __forceinline Vec3ba gt_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmpgt_epi32 (a.m128, b.m128)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
-#if defined(__aarch64__) || defined(__SSE4_1__)
- return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
-#else
- return _mm_or_si128(_mm_and_si128(_mm_castps_si128(m), t), _mm_andnot_si128(_mm_castps_si128(m), f));
-#endif
- }
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
- __forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return _mm_min_epi32(a.m128,b.m128); }
- __forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return _mm_max_epi32(a.m128,b.m128); }
-#else
- __forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return select(lt_mask(a,b),a,b); }
- __forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return select(gt_mask(a,b),a,b); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3ia& a) {
- return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/math/vec4.h b/thirdparty/embree-aarch64/common/math/vec4.h
deleted file mode 100644
index d16542f507..0000000000
--- a/thirdparty/embree-aarch64/common/math/vec4.h
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "math.h"
-#include "vec3.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// Generic 4D vector Class
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> struct Vec4
- {
- enum { N = 4 };
- union {
- struct { T x, y, z, w; };
-#if !(defined(__WIN32__) && _MSC_VER == 1800) // workaround for older VS 2013 compiler
- T components[N];
-#endif
- };
-
- typedef T Scalar;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Construction
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec4( ) {}
- __forceinline explicit Vec4( const T& a ) : x(a), y(a), z(a), w(a) {}
- __forceinline Vec4( const T& x, const T& y, const T& z, const T& w ) : x(x), y(y), z(z), w(w) {}
- __forceinline Vec4( const Vec3<T>& xyz, const T& w ) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
-
- __forceinline Vec4( const Vec4& other ) { x = other.x; y = other.y; z = other.z; w = other.w; }
- __forceinline Vec4( const Vec3fx& other );
-
- template<typename T1> __forceinline Vec4( const Vec4<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)), w(T(a.w)) {}
- template<typename T1> __forceinline Vec4& operator =(const Vec4<T1>& other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; }
-
- __forceinline Vec4& operator =(const Vec4& other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; }
-
- __forceinline operator Vec3<T> () const { return Vec3<T>(x,y,z); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec4( ZeroTy ) : x(zero), y(zero), z(zero), w(zero) {}
- __forceinline Vec4( OneTy ) : x(one), y(one), z(one), w(one) {}
- __forceinline Vec4( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf), w(pos_inf) {}
- __forceinline Vec4( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf), w(neg_inf) {}
-
-#if defined(__WIN32__) && (_MSC_VER == 1800) // workaround for older VS 2013 compiler
- __forceinline const T& operator [](const size_t axis) const { assert(axis < 4); return (&x)[axis]; }
- __forceinline T& operator [](const size_t axis) { assert(axis < 4); return (&x)[axis]; }
-#else
- __forceinline const T& operator [](const size_t axis ) const { assert(axis < 4); return components[axis]; }
- __forceinline T& operator [](const size_t axis) { assert(axis < 4); return components[axis]; }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Swizzles
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Vec3<T> xyz() const { return Vec3<T>(x, y, z); }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec4<T> operator +( const Vec4<T>& a ) { return Vec4<T>(+a.x, +a.y, +a.z, +a.w); }
- template<typename T> __forceinline Vec4<T> operator -( const Vec4<T>& a ) { return Vec4<T>(-a.x, -a.y, -a.z, -a.w); }
- template<typename T> __forceinline Vec4<T> abs ( const Vec4<T>& a ) { return Vec4<T>(abs (a.x), abs (a.y), abs (a.z), abs (a.w)); }
- template<typename T> __forceinline Vec4<T> rcp ( const Vec4<T>& a ) { return Vec4<T>(rcp (a.x), rcp (a.y), rcp (a.z), rcp (a.w)); }
- template<typename T> __forceinline Vec4<T> rsqrt ( const Vec4<T>& a ) { return Vec4<T>(rsqrt(a.x), rsqrt(a.y), rsqrt(a.z), rsqrt(a.w)); }
- template<typename T> __forceinline Vec4<T> sqrt ( const Vec4<T>& a ) { return Vec4<T>(sqrt (a.x), sqrt (a.y), sqrt (a.z), sqrt (a.w)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec4<T> operator +( const Vec4<T>& a, const Vec4<T>& b ) { return Vec4<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); }
- template<typename T> __forceinline Vec4<T> operator -( const Vec4<T>& a, const Vec4<T>& b ) { return Vec4<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); }
- template<typename T> __forceinline Vec4<T> operator *( const Vec4<T>& a, const Vec4<T>& b ) { return Vec4<T>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); }
- template<typename T> __forceinline Vec4<T> operator *( const T& a, const Vec4<T>& b ) { return Vec4<T>(a * b.x, a * b.y, a * b.z, a * b.w); }
- template<typename T> __forceinline Vec4<T> operator *( const Vec4<T>& a, const T& b ) { return Vec4<T>(a.x * b , a.y * b , a.z * b , a.w * b ); }
- template<typename T> __forceinline Vec4<T> operator /( const Vec4<T>& a, const Vec4<T>& b ) { return Vec4<T>(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); }
- template<typename T> __forceinline Vec4<T> operator /( const Vec4<T>& a, const T& b ) { return Vec4<T>(a.x / b , a.y / b , a.z / b , a.w / b ); }
- template<typename T> __forceinline Vec4<T> operator /( const T& a, const Vec4<T>& b ) { return Vec4<T>(a / b.x, a / b.y, a / b.z, a / b.w); }
-
- template<typename T> __forceinline Vec4<T> min(const Vec4<T>& a, const Vec4<T>& b) { return Vec4<T>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w)); }
- template<typename T> __forceinline Vec4<T> max(const Vec4<T>& a, const Vec4<T>& b) { return Vec4<T>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec4<T> madd ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z), madd(a.w,b.w,c.w)); }
- template<typename T> __forceinline Vec4<T> msub ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z), msub(a.w,b.w,c.w)); }
- template<typename T> __forceinline Vec4<T> nmadd ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z),nmadd(a.w,b.w,c.w)); }
- template<typename T> __forceinline Vec4<T> nmsub ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z),nmsub(a.w,b.w,c.w)); }
-
- template<typename T> __forceinline Vec4<T> madd ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z), madd(a,b.w,c.w)); }
- template<typename T> __forceinline Vec4<T> msub ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z), msub(a,b.w,c.w)); }
- template<typename T> __forceinline Vec4<T> nmadd ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z),nmadd(a,b.w,c.w)); }
- template<typename T> __forceinline Vec4<T> nmsub ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z),nmsub(a,b.w,c.w)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec4<T>& operator +=( Vec4<T>& a, const Vec4<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w; return a; }
- template<typename T> __forceinline Vec4<T>& operator -=( Vec4<T>& a, const Vec4<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; a.w -= b.w; return a; }
- template<typename T> __forceinline Vec4<T>& operator *=( Vec4<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; a.w *= b ; return a; }
- template<typename T> __forceinline Vec4<T>& operator /=( Vec4<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; a.w /= b ; return a; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline T reduce_add( const Vec4<T>& a ) { return a.x + a.y + a.z + a.w; }
- template<typename T> __forceinline T reduce_mul( const Vec4<T>& a ) { return a.x * a.y * a.z * a.w; }
- template<typename T> __forceinline T reduce_min( const Vec4<T>& a ) { return min(a.x, a.y, a.z, a.w); }
- template<typename T> __forceinline T reduce_max( const Vec4<T>& a ) { return max(a.x, a.y, a.z, a.w); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline bool operator ==( const Vec4<T>& a, const Vec4<T>& b ) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
- template<typename T> __forceinline bool operator !=( const Vec4<T>& a, const Vec4<T>& b ) { return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w; }
- template<typename T> __forceinline bool operator < ( const Vec4<T>& a, const Vec4<T>& b ) {
- if (a.x != b.x) return a.x < b.x;
- if (a.y != b.y) return a.y < b.y;
- if (a.z != b.z) return a.z < b.z;
- if (a.w != b.w) return a.w < b.w;
- return false;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Shift Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec4<T> shift_right_1( const Vec4<T>& a ) {
- return Vec4<T>(shift_right_1(a.x),shift_right_1(a.y),shift_right_1(a.z),shift_right_1(a.w));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline T dot ( const Vec4<T>& a, const Vec4<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,madd(a.z,b.z,a.w*b.w))); }
-
- template<typename T> __forceinline T length ( const Vec4<T>& a ) { return sqrt(dot(a,a)); }
- template<typename T> __forceinline Vec4<T> normalize( const Vec4<T>& a ) { return a*rsqrt(dot(a,a)); }
- template<typename T> __forceinline T distance ( const Vec4<T>& a, const Vec4<T>& b ) { return length(a-b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline Vec4<T> select ( bool s, const Vec4<T>& t, const Vec4<T>& f ) {
- return Vec4<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z),select(s,t.w,f.w));
- }
-
- template<typename T> __forceinline Vec4<T> select ( const Vec4<bool>& s, const Vec4<T>& t, const Vec4<T>& f ) {
- return Vec4<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z),select(s.w,t.w,f.w));
- }
-
- template<typename T> __forceinline Vec4<T> select ( const typename T::Bool& s, const Vec4<T>& t, const Vec4<T>& f ) {
- return Vec4<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z),select(s,t.w,f.w));
- }
-
- template<typename T>
- __forceinline Vec4<T> lerp(const Vec4<T>& v0, const Vec4<T>& v1, const T& t) {
- return madd(Vec4<T>(T(1.0f)-t),v0,t*v1);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Vec4<T>& a) {
- return cout << "(" << a.x << ", " << a.y << ", " << a.z << ", " << a.w << ")";
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Default template instantiations
- ////////////////////////////////////////////////////////////////////////////////
-
- typedef Vec4<bool > Vec4b;
- typedef Vec4<uint8_t > Vec4uc;
- typedef Vec4<int > Vec4i;
- typedef Vec4<float > Vec4f;
-}
-
-#include "vec3ba.h"
-#include "vec3ia.h"
-#include "vec3fa.h"
-
-////////////////////////////////////////////////////////////////////////////////
-/// SSE / AVX / MIC specializations
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__SSE__) || defined(__ARM_NEON)
-#include "../simd/sse.h"
-#endif
-
-#if defined __AVX__
-#include "../simd/avx.h"
-#endif
-
-#if defined __AVX512F__
-#include "../simd/avx512.h"
-#endif
-
-namespace embree
-{
- template<> __forceinline Vec4<float>::Vec4( const Vec3fx& a ) { x = a.x; y = a.y; z = a.z; w = a.w; }
-
-#if defined(__AVX__)
- template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fx& a ) {
- x = a.x; y = a.y; z = a.z; w = a.w;
- }
-#elif defined(__SSE__) || defined(__ARM_NEON)
- template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fx& a ) {
- const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); w = shuffle<3,3,3,3>(v);
- }
-#endif
-
-#if defined(__SSE__) || defined(__ARM_NEON)
- __forceinline Vec4<vfloat4> broadcast4f( const Vec4<vfloat4>& a, const size_t k ) {
- return Vec4<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]), vfloat4::broadcast(&a.w[k]));
- }
-#endif
-
-#if defined(__AVX__)
- template<> __forceinline Vec4<vfloat8>::Vec4( const Vec3fx& a ) {
- x = a.x; y = a.y; z = a.z; w = a.w;
- }
- __forceinline Vec4<vfloat4> broadcast4f( const Vec4<vfloat8>& a, const size_t k ) {
- return Vec4<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]), vfloat4::broadcast(&a.w[k]));
- }
- __forceinline Vec4<vfloat8> broadcast8f( const Vec4<vfloat4>& a, const size_t k ) {
- return Vec4<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]), vfloat8::broadcast(&a.w[k]));
- }
- __forceinline Vec4<vfloat8> broadcast8f( const Vec4<vfloat8>& a, const size_t k ) {
- return Vec4<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]), vfloat8::broadcast(&a.w[k]));
- }
-#endif
-
-#if defined(__AVX512F__)
- template<> __forceinline Vec4<vfloat16>::Vec4( const Vec3fx& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
-#endif
-}
diff --git a/thirdparty/embree-aarch64/common/simd/avx.h b/thirdparty/embree-aarch64/common/simd/avx.h
deleted file mode 100644
index c840e41805..0000000000
--- a/thirdparty/embree-aarch64/common/simd/avx.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "sse.h"
-
-#if defined(__AVX512VL__)
-#include "vboolf8_avx512.h"
-#include "vboold4_avx512.h"
-#else
-#include "vboolf8_avx.h"
-#include "vboold4_avx.h"
-#endif
-
-#if defined(__AVX2__)
-#include "vint8_avx2.h"
-#include "vuint8_avx2.h"
-#if defined(__X86_64__)
-#include "vllong4_avx2.h"
-#endif
-#else
-#include "vint8_avx.h"
-#include "vuint8_avx.h"
-#endif
-#include "vfloat8_avx.h"
-#if defined(__X86_64__)
-#include "vdouble4_avx.h"
-#endif
-
-#if defined(__AVX512F__)
-#include "avx512.h"
-#endif
-
diff --git a/thirdparty/embree-aarch64/common/simd/avx512.h b/thirdparty/embree-aarch64/common/simd/avx512.h
deleted file mode 100644
index 25414ab5b1..0000000000
--- a/thirdparty/embree-aarch64/common/simd/avx512.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/intrinsics.h"
-#include "../math/constants.h"
-#include "../sys/alloc.h"
-#include "varying.h"
-
-#include "vboolf16_avx512.h"
-#include "vint16_avx512.h"
-#include "vuint16_avx512.h"
-#include "vfloat16_avx512.h"
-
-#include "vboold8_avx512.h"
-#include "vllong8_avx512.h"
-#include "vdouble8_avx512.h"
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// Prefetching
- ////////////////////////////////////////////////////////////////////////////////
-
-#define PFHINT_L1 0
-#define PFHINT_L2 1
-#define PFHINT_NT 2
-
- template<const unsigned int mode>
- __forceinline void prefetch(const void * __restrict__ const m)
- {
- if (mode == PFHINT_L1)
- _mm_prefetch((const char*)m,_MM_HINT_T0);
- else if (mode == PFHINT_L2)
- _mm_prefetch((const char*)m,_MM_HINT_T1);
- else if (mode == PFHINT_NT)
- _mm_prefetch((const char*)m,_MM_HINT_NTA);
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/simd.h b/thirdparty/embree-aarch64/common/simd/simd.h
deleted file mode 100644
index 647851110b..0000000000
--- a/thirdparty/embree-aarch64/common/simd/simd.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../math/math.h"
-
-/* include SSE wrapper classes */
-#if defined(__SSE__) || defined(__ARM_NEON)
-# include "sse.h"
-#endif
-
-/* include AVX wrapper classes */
-#if defined(__AVX__)
-# include "avx.h"
-#endif
-
-/* include AVX512 wrapper classes */
-#if defined (__AVX512F__)
-# include "avx512.h"
-#endif
-
-namespace embree
-{
- template <int N>
- __forceinline vbool<N> isfinite(const vfloat<N>& v)
- {
- return (v >= vfloat<N>(-std::numeric_limits<float>::max()))
- & (v <= vfloat<N>( std::numeric_limits<float>::max()));
- }
-
- /* foreach unique */
- template<typename vbool, typename vint, typename Closure>
- __forceinline void foreach_unique(const vbool& valid0, const vint& vi, const Closure& closure)
- {
- vbool valid1 = valid0;
- while (any(valid1)) {
- const int j = int(bsf(movemask(valid1)));
- const int i = vi[j];
- const vbool valid2 = valid1 & (i == vi);
- valid1 = andn(valid1, valid2);
- closure(valid2, i);
- }
- }
-
- /* returns the next unique value i in vi and the corresponding valid_i mask */
- template<typename vbool, typename vint>
- __forceinline int next_unique(vbool& valid, const vint& vi, /*out*/ vbool& valid_i)
- {
- assert(any(valid));
- const int j = int(bsf(movemask(valid)));
- const int i = vi[j];
- valid_i = valid & (i == vi);
- valid = andn(valid, valid_i);
- return i;
- }
-
- /* foreach unique index */
- template<typename vbool, typename vint, typename Closure>
- __forceinline void foreach_unique_index(const vbool& valid0, const vint& vi, const Closure& closure)
- {
- vbool valid1 = valid0;
- while (any(valid1)) {
- const int j = int(bsf(movemask(valid1)));
- const int i = vi[j];
- const vbool valid2 = valid1 & (i == vi);
- valid1 = andn(valid1, valid2);
- closure(valid2, i, j);
- }
- }
-
- /* returns the index of the next unique value i in vi and the corresponding valid_i mask */
- template<typename vbool, typename vint>
- __forceinline int next_unique_index(vbool& valid, const vint& vi, /*out*/ vbool& valid_i)
- {
- assert(any(valid));
- const int j = int(bsf(movemask(valid)));
- const int i = vi[j];
- valid_i = valid & (i == vi);
- valid = andn(valid, valid_i);
- return j;
- }
-
- template<typename Closure>
- __forceinline void foreach2(int x0, int x1, int y0, int y1, const Closure& closure)
- {
- __aligned(64) int U[2*VSIZEX];
- __aligned(64) int V[2*VSIZEX];
- int index = 0;
- for (int y=y0; y<y1; y++) {
- const bool lasty = y+1>=y1;
- const vintx vy = y;
- for (int x=x0; x<x1; ) { //x+=VSIZEX) {
- const bool lastx = x+VSIZEX >= x1;
- vintx vx = x+vintx(step);
- vintx::storeu(&U[index], vx);
- vintx::storeu(&V[index], vy);
- const int dx = min(x1-x,VSIZEX);
- index += dx;
- x += dx;
- if (index >= VSIZEX || (lastx && lasty)) {
- const vboolx valid = vintx(step) < vintx(index);
- closure(valid, vintx::load(U), vintx::load(V));
- x-= max(0, index-VSIZEX);
- index = 0;
- }
- }
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/sse.cpp b/thirdparty/embree-aarch64/common/simd/sse.cpp
deleted file mode 100644
index 1732cfa421..0000000000
--- a/thirdparty/embree-aarch64/common/simd/sse.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "sse.h"
-
-namespace embree
-{
- const __m128 mm_lookupmask_ps[16] = {
- _mm_castsi128_ps(_mm_set_epi32( 0, 0, 0, 0)),
- _mm_castsi128_ps(_mm_set_epi32( 0, 0, 0,-1)),
- _mm_castsi128_ps(_mm_set_epi32( 0, 0,-1, 0)),
- _mm_castsi128_ps(_mm_set_epi32( 0, 0,-1,-1)),
- _mm_castsi128_ps(_mm_set_epi32( 0,-1, 0, 0)),
- _mm_castsi128_ps(_mm_set_epi32( 0,-1, 0,-1)),
- _mm_castsi128_ps(_mm_set_epi32( 0,-1,-1, 0)),
- _mm_castsi128_ps(_mm_set_epi32( 0,-1,-1,-1)),
- _mm_castsi128_ps(_mm_set_epi32(-1, 0, 0, 0)),
- _mm_castsi128_ps(_mm_set_epi32(-1, 0, 0,-1)),
- _mm_castsi128_ps(_mm_set_epi32(-1, 0,-1, 0)),
- _mm_castsi128_ps(_mm_set_epi32(-1, 0,-1,-1)),
- _mm_castsi128_ps(_mm_set_epi32(-1,-1, 0, 0)),
- _mm_castsi128_ps(_mm_set_epi32(-1,-1, 0,-1)),
- _mm_castsi128_ps(_mm_set_epi32(-1,-1,-1, 0)),
- _mm_castsi128_ps(_mm_set_epi32(-1,-1,-1,-1))
- };
-
- const __m128d mm_lookupmask_pd[4] = {
- _mm_castsi128_pd(_mm_set_epi32( 0, 0, 0, 0)),
- _mm_castsi128_pd(_mm_set_epi32( 0, 0,-1,-1)),
- _mm_castsi128_pd(_mm_set_epi32(-1,-1, 0, 0)),
- _mm_castsi128_pd(_mm_set_epi32(-1,-1,-1,-1))
- };
-
-}
diff --git a/thirdparty/embree-aarch64/common/simd/sse.h b/thirdparty/embree-aarch64/common/simd/sse.h
deleted file mode 100644
index 6bc818b55b..0000000000
--- a/thirdparty/embree-aarch64/common/simd/sse.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/intrinsics.h"
-#include "../sys/alloc.h"
-#include "../math/constants.h"
-#include "varying.h"
-
-namespace embree
-{
-#if (defined(__aarch64__) && defined(BUILD_IOS)) || defined(__SSE4_1__)
- __forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
- return _mm_blendv_ps(f,t,mask);
- }
-#else
- __forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
- return _mm_or_ps(_mm_and_ps(mask, t), _mm_andnot_ps(mask, f));
- }
-#endif
-
- extern const __m128 mm_lookupmask_ps[16];
- extern const __m128d mm_lookupmask_pd[4];
-}
-
-#if defined(__AVX512VL__)
-#include "vboolf4_avx512.h"
-#else
-#include "vboolf4_sse2.h"
-#endif
-#include "vint4_sse2.h"
-#include "vuint4_sse2.h"
-#include "vfloat4_sse2.h"
diff --git a/thirdparty/embree-aarch64/common/simd/varying.h b/thirdparty/embree-aarch64/common/simd/varying.h
deleted file mode 100644
index 9a46817da9..0000000000
--- a/thirdparty/embree-aarch64/common/simd/varying.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-
-namespace embree
-{
- /* Varying numeric types */
- template<int N>
- struct vfloat
- {
- union { float f[N]; int i[N]; };
- __forceinline const float& operator [](size_t index) const { assert(index < N); return f[index]; }
- __forceinline float& operator [](size_t index) { assert(index < N); return f[index]; }
- };
-
- template<int N>
- struct vdouble
- {
- union { double f[N]; long long i[N]; };
- __forceinline const double& operator [](size_t index) const { assert(index < N); return f[index]; }
- __forceinline double& operator [](size_t index) { assert(index < N); return f[index]; }
- };
-
- template<int N>
- struct vint
- {
- int i[N];
- __forceinline const int& operator [](size_t index) const { assert(index < N); return i[index]; }
- __forceinline int& operator [](size_t index) { assert(index < N); return i[index]; }
- };
-
- template<int N>
- struct vuint
- {
- unsigned int i[N];
- __forceinline const unsigned int& operator [](size_t index) const { assert(index < N); return i[index]; }
- __forceinline unsigned int& operator [](size_t index) { assert(index < N); return i[index]; }
- };
-
- template<int N>
- struct vllong
- {
- long long i[N];
- __forceinline const long long& operator [](size_t index) const { assert(index < N); return i[index]; }
- __forceinline long long& operator [](size_t index) { assert(index < N); return i[index]; }
- };
-
- /* Varying bool types */
- template<int N> struct vboolf { int i[N]; }; // for float/int
- template<int N> struct vboold { long long i[N]; }; // for double/long long
-
- /* Aliases to default types */
- template<int N> using vreal = vfloat<N>;
- template<int N> using vbool = vboolf<N>;
-
- /* Varying size constants */
-#if defined(__AVX512VL__) // SKX
- const int VSIZEX = 8; // default size
- const int VSIZEL = 16; // large size
-#elif defined(__AVX512F__) // KNL
- const int VSIZEX = 16;
- const int VSIZEL = 16;
-#elif defined(__AVX__)
- const int VSIZEX = 8;
- const int VSIZEL = 8;
-#else
- const int VSIZEX = 4;
- const int VSIZEL = 4;
-#endif
-
- /* Extends varying size N to optimal or up to max(N, N2) */
- template<int N, int N2 = VSIZEX>
- struct vextend
- {
-#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
- /* use 16-wide SIMD calculations on KNL even for 4 and 8 wide SIMD */
- static const int size = (N2 == VSIZEX) ? VSIZEX : N;
- #define SIMD_MODE(N) N, 16
-#else
- /* calculate with same SIMD width otherwise */
- static const int size = N;
- #define SIMD_MODE(N) N, N
-#endif
- };
-
- /* 4-wide shortcuts */
- typedef vfloat<4> vfloat4;
- typedef vdouble<4> vdouble4;
- typedef vreal<4> vreal4;
- typedef vint<4> vint4;
- typedef vuint<4> vuint4;
- typedef vllong<4> vllong4;
- typedef vbool<4> vbool4;
- typedef vboolf<4> vboolf4;
- typedef vboold<4> vboold4;
-
- /* 8-wide shortcuts */
- typedef vfloat<8> vfloat8;
- typedef vdouble<8> vdouble8;
- typedef vreal<8> vreal8;
- typedef vint<8> vint8;
- typedef vuint<8> vuint8;
- typedef vllong<8> vllong8;
- typedef vbool<8> vbool8;
- typedef vboolf<8> vboolf8;
- typedef vboold<8> vboold8;
-
- /* 16-wide shortcuts */
- typedef vfloat<16> vfloat16;
- typedef vdouble<16> vdouble16;
- typedef vreal<16> vreal16;
- typedef vint<16> vint16;
- typedef vuint<16> vuint16;
- typedef vllong<16> vllong16;
- typedef vbool<16> vbool16;
- typedef vboolf<16> vboolf16;
- typedef vboold<16> vboold16;
-
- /* Default shortcuts */
- typedef vfloat<VSIZEX> vfloatx;
- typedef vdouble<VSIZEX> vdoublex;
- typedef vreal<VSIZEX> vrealx;
- typedef vint<VSIZEX> vintx;
- typedef vuint<VSIZEX> vuintx;
- typedef vllong<VSIZEX> vllongx;
- typedef vbool<VSIZEX> vboolx;
- typedef vboolf<VSIZEX> vboolfx;
- typedef vboold<VSIZEX> vbooldx;
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vboold4_avx.h b/thirdparty/embree-aarch64/common/simd/vboold4_avx.h
deleted file mode 100644
index 6505ee56f3..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vboold4_avx.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 4-wide AVX bool type for 64bit data types*/
- template<>
- struct vboold<4>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboold4 Bool;
-
- enum { size = 4 }; // number of SIMD elements
- union { // data
- __m256d v;
- struct { __m128d vl,vh; };
- long long i[4];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold() {}
- __forceinline vboold(const vboold4& a) { v = a.v; }
- __forceinline vboold4& operator =(const vboold4& a) { v = a.v; return *this; }
-
- __forceinline vboold(__m256d a) : v(a) {}
- __forceinline vboold(__m256i a) : v(_mm256_castsi256_pd(a)) {}
-
- __forceinline operator const __m256() const { return _mm256_castpd_ps(v); }
- __forceinline operator const __m256i() const { return _mm256_castpd_si256(v); }
- __forceinline operator const __m256d() const { return v; }
-
- __forceinline vboold(int a)
- {
- assert(a >= 0 && a <= 255);
-#if defined (__AVX2__)
- const __m256i mask = _mm256_set_epi64x(0x8, 0x4, 0x2, 0x1);
- const __m256i b = _mm256_set1_epi64x(a);
- const __m256i c = _mm256_and_si256(b,mask);
- v = _mm256_castsi256_pd(_mm256_cmpeq_epi64(c,mask));
-#else
- vl = mm_lookupmask_pd[a & 0x3];
- vh = mm_lookupmask_pd[a >> 2];
-#endif
- }
-
- __forceinline vboold(__m128d a, __m128d b) : vl(a), vh(b) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold(FalseTy) : v(_mm256_setzero_pd()) {}
-#if !defined(__aarch64__)
- __forceinline vboold(TrueTy) : v(_mm256_cmp_pd(_mm256_setzero_pd(), _mm256_setzero_pd(), _CMP_EQ_OQ)) {}
-#else
- __forceinline vboold(TrueTy) : v(_mm256_cmpeq_pd(_mm256_setzero_pd(), _mm256_setzero_pd())) {}
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator [](size_t index) const { assert(index < 4); return (_mm256_movemask_pd(v) >> index) & 1; }
- __forceinline long long& operator [](size_t index) { assert(index < 4); return i[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold4 operator !(const vboold4& a) { return _mm256_xor_pd(a, vboold4(embree::True)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold4 operator &(const vboold4& a, const vboold4& b) { return _mm256_and_pd(a, b); }
- __forceinline vboold4 operator |(const vboold4& a, const vboold4& b) { return _mm256_or_pd (a, b); }
- __forceinline vboold4 operator ^(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(a, b); }
-
- __forceinline vboold4 andn(const vboold4& a, const vboold4& b) { return _mm256_andnot_pd(b, a); }
-
- __forceinline vboold4& operator &=(vboold4& a, const vboold4& b) { return a = a & b; }
- __forceinline vboold4& operator |=(vboold4& a, const vboold4& b) { return a = a | b; }
- __forceinline vboold4& operator ^=(vboold4& a, const vboold4& b) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold4 operator !=(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(a, b); }
- __forceinline vboold4 operator ==(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(_mm256_xor_pd(a,b),vboold4(embree::True)); }
-
- __forceinline vboold4 select(const vboold4& mask, const vboold4& t, const vboold4& f) {
- return _mm256_blendv_pd(f, t, mask);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(__aarch64__)
- __forceinline vboold4 unpacklo(const vboold4& a, const vboold4& b) { return _mm256_unpacklo_pd(a, b); }
- __forceinline vboold4 unpackhi(const vboold4& a, const vboold4& b) { return _mm256_unpackhi_pd(a, b); }
-#endif
-
-#if defined(__AVX2__)
- template<int i0, int i1, int i2, int i3>
- __forceinline vboold4 shuffle(const vboold4& v) {
- return _mm256_permute4x64_pd(v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
- template<int i>
- __forceinline vboold4 shuffle(const vboold4& v) {
- return _mm256_permute4x64_pd(v, _MM_SHUFFLE(i, i, i, i));
- }
-#endif
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool reduce_and(const vboold4& a) { return _mm256_movemask_pd(a) == (unsigned int)0xf; }
- __forceinline bool reduce_or (const vboold4& a) { return !_mm256_testz_pd(a,a); }
-
- __forceinline bool all (const vboold4& a) { return _mm256_movemask_pd(a) == (unsigned int)0xf; }
- __forceinline bool any (const vboold4& a) { return !_mm256_testz_pd(a,a); }
- __forceinline bool none(const vboold4& a) { return _mm256_testz_pd(a,a) != 0; }
-
- __forceinline bool all (const vboold4& valid, const vboold4& b) { return all((!valid) | b); }
- __forceinline bool any (const vboold4& valid, const vboold4& b) { return any(valid & b); }
- __forceinline bool none(const vboold4& valid, const vboold4& b) { return none(valid & b); }
-
- __forceinline unsigned int movemask(const vboold4& a) { return _mm256_movemask_pd(a); }
- __forceinline size_t popcnt (const vboold4& a) { return popcnt((size_t)_mm256_movemask_pd(a)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Get/Set Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool get(const vboold4& a, size_t index) { return a[index]; }
- __forceinline void set (vboold4& a, size_t index) { a[index] = -1; }
- __forceinline void clear(vboold4& a, size_t index) { a[index] = 0; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vboold4& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
- << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vboold4_avx512.h b/thirdparty/embree-aarch64/common/simd/vboold4_avx512.h
deleted file mode 100644
index 4fe730d713..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vboold4_avx512.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 4-wide AVX-512 bool type */
- template<>
- struct vboold<4>
- {
- typedef vboold4 Bool;
- typedef vint4 Int;
-
- enum { size = 4 }; // number of SIMD elements
- __mmask8 v; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold() {}
- __forceinline vboold(const vboold4& t) { v = t.v; }
- __forceinline vboold4& operator =(const vboold4& f) { v = f.v; return *this; }
-
- __forceinline vboold(const __mmask8 &t) { v = t; }
- __forceinline operator __mmask8() const { return v; }
-
- __forceinline vboold(bool b) { v = b ? 0xf : 0x0; }
- __forceinline vboold(int t) { v = (__mmask8)t; }
- __forceinline vboold(unsigned int t) { v = (__mmask8)t; }
-
- /* return int8 mask */
- __forceinline __m128i mask8() const {
- return _mm_movm_epi8(v);
- }
-
- /* return int32 mask */
- __forceinline __m128i mask32() const {
- return _mm_movm_epi32(v);
- }
-
- /* return int64 mask */
- __forceinline __m256i mask64() const {
- return _mm256_movm_epi64(v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold(FalseTy) : v(0x0) {}
- __forceinline vboold(TrueTy) : v(0xf) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator [](size_t index) const {
- assert(index < 4); return (mm512_mask2int(v) >> index) & 1;
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold4 operator !(const vboold4& a) { return _mm512_kandn(a, 0xf); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold4 operator &(const vboold4& a, const vboold4& b) { return _mm512_kand(a, b); }
- __forceinline vboold4 operator |(const vboold4& a, const vboold4& b) { return _mm512_kor(a, b); }
- __forceinline vboold4 operator ^(const vboold4& a, const vboold4& b) { return _mm512_kxor(a, b); }
-
- __forceinline vboold4 andn(const vboold4& a, const vboold4& b) { return _mm512_kandn(b, a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold4& operator &=(vboold4& a, const vboold4& b) { return a = a & b; }
- __forceinline vboold4& operator |=(vboold4& a, const vboold4& b) { return a = a | b; }
- __forceinline vboold4& operator ^=(vboold4& a, const vboold4& b) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold4 operator !=(const vboold4& a, const vboold4& b) { return _mm512_kxor(a, b); }
- __forceinline vboold4 operator ==(const vboold4& a, const vboold4& b) { return _mm512_kand(_mm512_kxnor(a, b), 0xf); }
-
- __forceinline vboold4 select(const vboold4& s, const vboold4& a, const vboold4& b) {
- return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline int all (const vboold4& a) { return a.v == 0xf; }
- __forceinline int any (const vboold4& a) { return _mm512_kortestz(a, a) == 0; }
- __forceinline int none(const vboold4& a) { return _mm512_kortestz(a, a) != 0; }
-
- __forceinline int all (const vboold4& valid, const vboold4& b) { return all((!valid) | b); }
- __forceinline int any (const vboold4& valid, const vboold4& b) { return any(valid & b); }
- __forceinline int none(const vboold4& valid, const vboold4& b) { return none(valid & b); }
-
- __forceinline size_t movemask(const vboold4& a) { return _mm512_kmov(a); }
- __forceinline size_t popcnt (const vboold4& a) { return popcnt(a.v); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Conversion Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline unsigned int toInt(const vboold4& a) { return mm512_mask2int(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Get/Set Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool get(const vboold4& a, size_t index) { assert(index < 4); return (toInt(a) >> index) & 1; }
- __forceinline void set(vboold4& a, size_t index) { assert(index < 4); a |= 1 << index; }
- __forceinline void clear(vboold4& a, size_t index) { assert(index < 4); a = andn(a, 1 << index); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vboold4& a)
- {
- cout << "<";
- for (size_t i=0; i<4; i++) {
- if ((a.v >> i) & 1) cout << "1"; else cout << "0";
- }
- return cout << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vboold8_avx512.h b/thirdparty/embree-aarch64/common/simd/vboold8_avx512.h
deleted file mode 100644
index fdf3f00de5..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vboold8_avx512.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX-512 bool type */
- template<>
- struct vboold<8>
- {
- typedef vboold8 Bool;
- typedef vint8 Int;
-
- enum { size = 8 }; // number of SIMD elements
- __mmask8 v; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold() {}
- __forceinline vboold(const vboold8& t) { v = t.v; }
- __forceinline vboold8& operator =(const vboold8& f) { v = f.v; return *this; }
-
- __forceinline vboold(const __mmask8& t) { v = t; }
- __forceinline operator __mmask8() const { return v; }
-
- __forceinline vboold(bool b) { v = b ? 0xff : 0x00; }
- __forceinline vboold(int t) { v = (__mmask8)t; }
- __forceinline vboold(unsigned int t) { v = (__mmask8)t; }
-
- /* return int8 mask */
- __forceinline __m128i mask8() const {
-#if defined(__AVX512BW__)
- return _mm_movm_epi8(v);
-#else
- const __m512i f = _mm512_set1_epi64(0);
- const __m512i t = _mm512_set1_epi64(-1);
- const __m512i m = _mm512_mask_or_epi64(f,v,t,t);
- return _mm512_cvtepi64_epi8(m);
-#endif
- }
-
- /* return int64 mask */
- __forceinline __m512i mask64() const {
-#if defined(__AVX512DQ__)
- return _mm512_movm_epi64(v);
-#else
- const __m512i f = _mm512_set1_epi64(0);
- const __m512i t = _mm512_set1_epi64(-1);
- return _mm512_mask_or_epi64(f,v,t,t);
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold(FalseTy) : v(0x00) {}
- __forceinline vboold(TrueTy) : v(0xff) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator [](size_t index) const {
- assert(index < 8); return (mm512_mask2int(v) >> index) & 1;
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold8 operator !(const vboold8& a) { return _mm512_knot(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold8 operator &(const vboold8& a, const vboold8& b) { return _mm512_kand(a, b); }
- __forceinline vboold8 operator |(const vboold8& a, const vboold8& b) { return _mm512_kor(a, b); }
- __forceinline vboold8 operator ^(const vboold8& a, const vboold8& b) { return _mm512_kxor(a, b); }
-
- __forceinline vboold8 andn(const vboold8& a, const vboold8& b) { return _mm512_kandn(b, a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold8& operator &=(vboold8& a, const vboold8& b) { return a = a & b; }
- __forceinline vboold8& operator |=(vboold8& a, const vboold8& b) { return a = a | b; }
- __forceinline vboold8& operator ^=(vboold8& a, const vboold8& b) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold8 operator !=(const vboold8& a, const vboold8& b) { return _mm512_kxor(a, b); }
- __forceinline vboold8 operator ==(const vboold8& a, const vboold8& b) { return _mm512_kxnor(a, b); }
-
- __forceinline vboold8 select(const vboold8& s, const vboold8& a, const vboold8& b) {
- return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline int all (const vboold8& a) { return a.v == 0xff; }
- __forceinline int any (const vboold8& a) { return _mm512_kortestz(a, a) == 0; }
- __forceinline int none(const vboold8& a) { return _mm512_kortestz(a, a) != 0; }
-
- __forceinline int all (const vboold8& valid, const vboold8& b) { return all((!valid) | b); }
- __forceinline int any (const vboold8& valid, const vboold8& b) { return any(valid & b); }
- __forceinline int none(const vboold8& valid, const vboold8& b) { return none(valid & b); }
-
- __forceinline size_t movemask(const vboold8& a) { return _mm512_kmov(a); }
- __forceinline size_t popcnt (const vboold8& a) { return popcnt(a.v); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Conversion Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline unsigned int toInt(const vboold8& a) { return mm512_mask2int(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Get/Set Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool get(const vboold8& a, size_t index) { assert(index < 8); return (toInt(a) >> index) & 1; }
- __forceinline void set(vboold8& a, size_t index) { assert(index < 8); a |= 1 << index; }
- __forceinline void clear(vboold8& a, size_t index) { assert(index < 8); a = andn(a, 1 << index); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vboold8& a)
- {
- cout << "<";
- for (size_t i=0; i<8; i++) {
- if ((a.v >> i) & 1) cout << "1"; else cout << "0";
- }
- return cout << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vboolf16_avx512.h b/thirdparty/embree-aarch64/common/simd/vboolf16_avx512.h
deleted file mode 100644
index 238cdc8eb9..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vboolf16_avx512.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 16-wide AVX-512 bool type */
- template<>
- struct vboolf<16>
- {
- typedef vboolf16 Bool;
- typedef vint16 Int;
- typedef vfloat16 Float;
-
- enum { size = 16 }; // number of SIMD elements
- __mmask16 v; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf() {}
- __forceinline vboolf(const vboolf16& t) { v = t.v; }
- __forceinline vboolf16& operator =(const vboolf16& f) { v = f.v; return *this; }
-
- __forceinline vboolf(const __mmask16& t) { v = t; }
- __forceinline operator __mmask16() const { return v; }
-
- __forceinline vboolf(bool b) { v = b ? 0xFFFF : 0x0000; }
- __forceinline vboolf(int t) { v = (__mmask16)t; }
- __forceinline vboolf(unsigned int t) { v = (__mmask16)t; }
-
- /* return int8 mask */
- __forceinline __m128i mask8() const {
-#if defined(__AVX512BW__)
- return _mm_movm_epi8(v);
-#else
- const __m512i f = _mm512_set1_epi32(0);
- const __m512i t = _mm512_set1_epi32(-1);
- const __m512i m = _mm512_mask_or_epi32(f,v,t,t);
- return _mm512_cvtepi32_epi8(m);
-#endif
- }
-
- /* return int32 mask */
- __forceinline __m512i mask32() const {
-#if defined(__AVX512DQ__)
- return _mm512_movm_epi32(v);
-#else
- const __m512i f = _mm512_set1_epi32(0);
- const __m512i t = _mm512_set1_epi32(-1);
- return _mm512_mask_or_epi32(f,v,t,t);
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf(FalseTy) : v(0x0000) {}
- __forceinline vboolf(TrueTy) : v(0xffff) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator [](size_t index) const {
- assert(index < 16); return (mm512_mask2int(v) >> index) & 1;
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16 operator !(const vboolf16& a) { return _mm512_knot(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16 operator &(const vboolf16& a, const vboolf16& b) { return _mm512_kand(a,b); }
- __forceinline vboolf16 operator |(const vboolf16& a, const vboolf16& b) { return _mm512_kor(a,b); }
- __forceinline vboolf16 operator ^(const vboolf16& a, const vboolf16& b) { return _mm512_kxor(a,b); }
-
- __forceinline vboolf16 andn(const vboolf16& a, const vboolf16& b) { return _mm512_kandn(b,a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16& operator &=(vboolf16& a, const vboolf16& b) { return a = a & b; }
- __forceinline vboolf16& operator |=(vboolf16& a, const vboolf16& b) { return a = a | b; }
- __forceinline vboolf16& operator ^=(vboolf16& a, const vboolf16& b) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16 operator !=(const vboolf16& a, const vboolf16& b) { return _mm512_kxor(a, b); }
- __forceinline vboolf16 operator ==(const vboolf16& a, const vboolf16& b) { return _mm512_kxnor(a, b); }
-
- __forceinline vboolf16 select(const vboolf16& s, const vboolf16& a, const vboolf16& b) {
- return _mm512_kor(_mm512_kand(s,a),_mm512_kandn(s,b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline int all (const vboolf16& a) { return _mm512_kortestc(a,a) != 0; }
- __forceinline int any (const vboolf16& a) { return _mm512_kortestz(a,a) == 0; }
- __forceinline int none(const vboolf16& a) { return _mm512_kortestz(a,a) != 0; }
-
- __forceinline int all (const vboolf16& valid, const vboolf16& b) { return all((!valid) | b); }
- __forceinline int any (const vboolf16& valid, const vboolf16& b) { return any(valid & b); }
- __forceinline int none(const vboolf16& valid, const vboolf16& b) { return none(valid & b); }
-
- __forceinline size_t movemask(const vboolf16& a) { return _mm512_kmov(a); }
- __forceinline size_t popcnt (const vboolf16& a) { return popcnt(a.v); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Convertion Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline unsigned int toInt (const vboolf16& a) { return mm512_mask2int(a); }
- __forceinline vboolf16 toMask(const int& a) { return mm512_int2mask(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Get/Set Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool get(const vboolf16& a, size_t index) { assert(index < 16); return (toInt(a) >> index) & 1; }
- __forceinline void set(vboolf16& a, size_t index) { assert(index < 16); a |= 1 << index; }
- __forceinline void clear(vboolf16& a, size_t index) { assert(index < 16); a = andn(a, 1 << index); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf16& a)
- {
- cout << "<";
- for (size_t i=0; i<16; i++) {
- if ((a.v >> i) & 1) cout << "1"; else cout << "0";
- }
- return cout << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vboolf4_avx512.h b/thirdparty/embree-aarch64/common/simd/vboolf4_avx512.h
deleted file mode 100644
index 2ae4c4470e..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vboolf4_avx512.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 4-wide AVX-512 bool type */
- template<>
- struct vboolf<4>
- {
- typedef vboolf4 Bool;
- typedef vint4 Int;
-
- enum { size = 4 }; // number of SIMD elements
- __mmask8 v; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf() {}
- __forceinline vboolf(const vboolf4& t) { v = t.v; }
- __forceinline vboolf4& operator =(const vboolf4& f) { v = f.v; return *this; }
-
- __forceinline vboolf(const __mmask8 &t) { v = t; }
- __forceinline operator __mmask8() const { return v; }
-
- __forceinline vboolf(bool b) { v = b ? 0xf : 0x0; }
- __forceinline vboolf(int t) { v = (__mmask8)t; }
- __forceinline vboolf(unsigned int t) { v = (__mmask8)t; }
-
- __forceinline vboolf(bool a, bool b, bool c, bool d)
- : v((__mmask8)((int(d) << 3) | (int(c) << 2) | (int(b) << 1) | int(a))) {}
-
- /* return int8 mask */
- __forceinline __m128i mask8() const {
- return _mm_movm_epi8(v);
- }
-
- /* return int32 mask */
- __forceinline __m128i mask32() const {
- return _mm_movm_epi32(v);
- }
-
- /* return int64 mask */
- __forceinline __m256i mask64() const {
- return _mm256_movm_epi64(v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf(FalseTy) : v(0x0) {}
- __forceinline vboolf(TrueTy) : v(0xf) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator [](size_t index) const {
- assert(index < 4); return (mm512_mask2int(v) >> index) & 1;
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4 operator !(const vboolf4& a) { return _mm512_kandn(a, 0xf); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4 operator &(const vboolf4& a, const vboolf4& b) { return _mm512_kand(a, b); }
- __forceinline vboolf4 operator |(const vboolf4& a, const vboolf4& b) { return _mm512_kor(a, b); }
- __forceinline vboolf4 operator ^(const vboolf4& a, const vboolf4& b) { return _mm512_kxor(a, b); }
-
- __forceinline vboolf4 andn(const vboolf4& a, const vboolf4& b) { return _mm512_kandn(b, a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4& operator &=(vboolf4& a, const vboolf4& b) { return a = a & b; }
- __forceinline vboolf4& operator |=(vboolf4& a, const vboolf4& b) { return a = a | b; }
- __forceinline vboolf4& operator ^=(vboolf4& a, const vboolf4& b) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4 operator !=(const vboolf4& a, const vboolf4& b) { return _mm512_kxor(a, b); }
- __forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm512_kand(_mm512_kxnor(a, b), 0xf); }
-
- __forceinline vboolf4 select(const vboolf4& s, const vboolf4& a, const vboolf4& b) {
- return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline int all (const vboolf4& a) { return a.v == 0xf; }
- __forceinline int any (const vboolf4& a) { return _mm512_kortestz(a, a) == 0; }
- __forceinline int none(const vboolf4& a) { return _mm512_kortestz(a, a) != 0; }
-
- __forceinline int all (const vboolf4& valid, const vboolf4& b) { return all((!valid) | b); }
- __forceinline int any (const vboolf4& valid, const vboolf4& b) { return any(valid & b); }
- __forceinline int none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
-
- __forceinline size_t movemask(const vboolf4& a) { return _mm512_kmov(a); }
- __forceinline size_t popcnt (const vboolf4& a) { return popcnt(a.v); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Conversion Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline unsigned int toInt(const vboolf4& a) { return mm512_mask2int(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Get/Set Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool get(const vboolf4& a, size_t index) { assert(index < 4); return (toInt(a) >> index) & 1; }
- __forceinline void set(vboolf4& a, size_t index) { assert(index < 4); a |= 1 << index; }
- __forceinline void clear(vboolf4& a, size_t index) { assert(index < 4); a = andn(a, 1 << index); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf4& a)
- {
- cout << "<";
- for (size_t i=0; i<4; i++) {
- if ((a.v >> i) & 1) cout << "1"; else cout << "0";
- }
- return cout << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vboolf4_sse2.h b/thirdparty/embree-aarch64/common/simd/vboolf4_sse2.h
deleted file mode 100644
index ed53b3c783..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vboolf4_sse2.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 4-wide SSE bool type */
- template<>
- struct vboolf<4>
- {
- ALIGNED_STRUCT_(16);
-
- typedef vboolf4 Bool;
- typedef vint4 Int;
- typedef vfloat4 Float;
-
- enum { size = 4 }; // number of SIMD elements
- union { __m128 v; int i[4]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf() {}
- __forceinline vboolf(const vboolf4& other) { v = other.v; }
- __forceinline vboolf4& operator =(const vboolf4& other) { v = other.v; return *this; }
-
- __forceinline vboolf(__m128 input) : v(input) {}
- __forceinline operator const __m128&() const { return v; }
- __forceinline operator const __m128i() const { return _mm_castps_si128(v); }
- __forceinline operator const __m128d() const { return _mm_castps_pd(v); }
-
- __forceinline vboolf(bool a)
- : v(mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
- __forceinline vboolf(bool a, bool b)
- : v(mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
- __forceinline vboolf(bool a, bool b, bool c, bool d)
- : v(mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
-#if defined(__aarch64__) && defined(BUILD_IOS)
- __forceinline vboolf(int mask) { v = mm_lookupmask_ps[mask]; }
- __forceinline vboolf(unsigned int mask) { v = mm_lookupmask_ps[mask]; }
-#else
- __forceinline vboolf(int mask) { assert(mask >= 0 && mask < 16); v = mm_lookupmask_ps[mask]; }
- __forceinline vboolf(unsigned int mask) { assert(mask < 16); v = mm_lookupmask_ps[mask]; }
-#endif
- /* return int32 mask */
- __forceinline __m128i mask32() const {
- return _mm_castps_si128(v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf(FalseTy) : v(_mm_setzero_ps()) {}
- __forceinline vboolf(TrueTy) : v(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__aarch64__) && defined(BUILD_IOS)
- __forceinline bool operator [](size_t index) const { return (_mm_movemask_ps(v) >> index) & 1; }
- __forceinline int& operator [](size_t index) { return i[index]; }
-#else
- __forceinline bool operator [](size_t index) const { assert(index < 4); return (_mm_movemask_ps(v) >> index) & 1; }
- __forceinline int& operator [](size_t index) { assert(index < 4); return i[index]; }
-#endif
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4 operator !(const vboolf4& a) { return _mm_xor_ps(a, vboolf4(embree::True)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4 operator &(const vboolf4& a, const vboolf4& b) { return _mm_and_ps(a, b); }
- __forceinline vboolf4 operator |(const vboolf4& a, const vboolf4& b) { return _mm_or_ps (a, b); }
- __forceinline vboolf4 operator ^(const vboolf4& a, const vboolf4& b) { return _mm_xor_ps(a, b); }
-
- __forceinline vboolf4 andn(const vboolf4& a, const vboolf4& b) { return _mm_andnot_ps(b, a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4& operator &=(vboolf4& a, const vboolf4& b) { return a = a & b; }
- __forceinline vboolf4& operator |=(vboolf4& a, const vboolf4& b) { return a = a | b; }
- __forceinline vboolf4& operator ^=(vboolf4& a, const vboolf4& b) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4 operator !=(const vboolf4& a, const vboolf4& b) { return _mm_xor_ps(a, b); }
- __forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
-
- __forceinline vboolf4 select(const vboolf4& m, const vboolf4& t, const vboolf4& f) {
-#if (defined(__aarch64__) && defined(BUILD_IOS)) || defined(__SSE4_1__)
- return _mm_blendv_ps(f, t, m);
-#else
- return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf4 unpacklo(const vboolf4& a, const vboolf4& b) { return _mm_unpacklo_ps(a, b); }
- __forceinline vboolf4 unpackhi(const vboolf4& a, const vboolf4& b) { return _mm_unpackhi_ps(a, b); }
-
-#if defined(__aarch64__)
- template<int i0, int i1, int i2, int i3>
- __forceinline vboolf4 shuffle(const vboolf4& v) {
- return vreinterpretq_f32_u8(vqtbl1q_u8( vreinterpretq_u8_s32(v), _MN_SHUFFLE(i0, i1, i2, i3)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) {
- return vreinterpretq_f32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
- }
-#else
- template<int i0, int i1, int i2, int i3>
- __forceinline vboolf4 shuffle(const vboolf4& v) {
- return _mm_castsi128_ps(_mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) {
- return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-#endif
-
- template<int i0>
- __forceinline vboolf4 shuffle(const vboolf4& v) {
- return shuffle<i0,i0,i0,i0>(v);
- }
-
-#if defined(__SSE3__)
- template<> __forceinline vboolf4 shuffle<0, 0, 2, 2>(const vboolf4& v) { return _mm_moveldup_ps(v); }
- template<> __forceinline vboolf4 shuffle<1, 1, 3, 3>(const vboolf4& v) { return _mm_movehdup_ps(v); }
- template<> __forceinline vboolf4 shuffle<0, 1, 0, 1>(const vboolf4& v) { return _mm_castpd_ps(_mm_movedup_pd(v)); }
-#endif
-
-#if defined(__SSE4_1__) && !defined(__aarch64__)
- template<int dst, int src, int clr> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
- template<int dst, int src> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return insert<dst, src, 0>(a, b); }
- template<int dst> __forceinline vboolf4 insert(const vboolf4& a, const bool b) { return insert<dst, 0>(a, vboolf4(b)); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool reduce_and(const vboolf4& a) { return _mm_movemask_ps(a) == 0xf; }
- __forceinline bool reduce_or (const vboolf4& a) { return _mm_movemask_ps(a) != 0x0; }
-
- __forceinline bool all (const vboolf4& b) { return _mm_movemask_ps(b) == 0xf; }
- __forceinline bool any (const vboolf4& b) { return _mm_movemask_ps(b) != 0x0; }
- __forceinline bool none(const vboolf4& b) { return _mm_movemask_ps(b) == 0x0; }
-
- __forceinline bool all (const vboolf4& valid, const vboolf4& b) { return all((!valid) | b); }
- __forceinline bool any (const vboolf4& valid, const vboolf4& b) { return any(valid & b); }
- __forceinline bool none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
-
- __forceinline size_t movemask(const vboolf4& a) { return _mm_movemask_ps(a); }
-#if defined(__aarch64__) && defined(BUILD_IOS)
-__forceinline size_t popcnt(const vboolf4& a) { return _mm_movemask_popcnt_ps(a); }
-#else
-#if defined(__SSE4_2__)
- __forceinline size_t popcnt(const vboolf4& a) { return popcnt((size_t)_mm_movemask_ps(a)); }
-#else
- __forceinline size_t popcnt(const vboolf4& a) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); }
-#endif
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Get/Set Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool get(const vboolf4& a, size_t index) { return a[index]; }
- __forceinline void set(vboolf4& a, size_t index) { a[index] = -1; }
- __forceinline void clear(vboolf4& a, size_t index) { a[index] = 0; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf4& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vboolf8_avx.h b/thirdparty/embree-aarch64/common/simd/vboolf8_avx.h
deleted file mode 100644
index 4f64741b55..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vboolf8_avx.h
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX bool type */
- template<>
- struct vboolf<8>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboolf8 Bool;
- typedef vint8 Int;
- typedef vfloat8 Float;
-
- enum { size = 8 }; // number of SIMD elements
- union { // data
- __m256 v;
- struct { __m128 vl,vh; };
- int i[8];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf() {}
- __forceinline vboolf(const vboolf8& a) { v = a.v; }
- __forceinline vboolf8& operator =(const vboolf8& a) { v = a.v; return *this; }
-
- __forceinline vboolf(__m256 a) : v(a) {}
- __forceinline operator const __m256&() const { return v; }
- __forceinline operator const __m256i() const { return _mm256_castps_si256(v); }
- __forceinline operator const __m256d() const { return _mm256_castps_pd(v); }
-
- __forceinline vboolf(int a)
- {
- assert(a >= 0 && a <= 255);
-#if defined (__AVX2__)
- const __m256i mask = _mm256_set_epi32(0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1);
- const __m256i b = _mm256_set1_epi32(a);
- const __m256i c = _mm256_and_si256(b,mask);
- v = _mm256_castsi256_ps(_mm256_cmpeq_epi32(c,mask));
-#else
- vl = mm_lookupmask_ps[a & 0xF];
- vh = mm_lookupmask_ps[a >> 4];
-#endif
- }
-
- __forceinline vboolf(const vboolf4& a) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
- __forceinline vboolf(const vboolf4& a, const vboolf4& b) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
- __forceinline vboolf(__m128 a, __m128 b) : vl(a), vh(b) {}
-
- __forceinline vboolf(bool a) : v(vboolf8(vboolf4(a), vboolf4(a))) {}
- __forceinline vboolf(bool a, bool b) : v(vboolf8(vboolf4(a), vboolf4(b))) {}
- __forceinline vboolf(bool a, bool b, bool c, bool d) : v(vboolf8(vboolf4(a,b), vboolf4(c,d))) {}
- __forceinline vboolf(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h) : v(vboolf8(vboolf4(a,b,c,d), vboolf4(e,f,g,h))) {}
-
- /* return int32 mask */
- __forceinline __m256i mask32() const {
- return _mm256_castps_si256(v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf(FalseTy) : v(_mm256_setzero_ps()) {}
-#if !defined(__aarch64__)
- __forceinline vboolf(TrueTy) : v(_mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OQ)) {}
-#else
- __forceinline vboolf(TrueTy) : v(_mm256_cmpeq_ps(_mm256_setzero_ps(), _mm256_setzero_ps())) {}
-#endif
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator [](size_t index) const { assert(index < 8); return (_mm256_movemask_ps(v) >> index) & 1; }
- __forceinline int& operator [](size_t index) { assert(index < 8); return i[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 operator !(const vboolf8& a) { return _mm256_xor_ps(a, vboolf8(embree::True)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 operator &(const vboolf8& a, const vboolf8& b) { return _mm256_and_ps(a, b); }
- __forceinline vboolf8 operator |(const vboolf8& a, const vboolf8& b) { return _mm256_or_ps (a, b); }
- __forceinline vboolf8 operator ^(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(a, b); }
-
- __forceinline vboolf8 andn(const vboolf8& a, const vboolf8& b) { return _mm256_andnot_ps(b, a); }
-
- __forceinline vboolf8& operator &=(vboolf8& a, const vboolf8& b) { return a = a & b; }
- __forceinline vboolf8& operator |=(vboolf8& a, const vboolf8& b) { return a = a | b; }
- __forceinline vboolf8& operator ^=(vboolf8& a, const vboolf8& b) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 operator !=(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(a, b); }
- __forceinline vboolf8 operator ==(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(_mm256_xor_ps(a,b),vboolf8(embree::True)); }
-
- __forceinline vboolf8 select(const vboolf8& mask, const vboolf8& t, const vboolf8& f) {
- return _mm256_blendv_ps(f, t, mask);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 unpacklo(const vboolf8& a, const vboolf8& b) { return _mm256_unpacklo_ps(a, b); }
- __forceinline vboolf8 unpackhi(const vboolf8& a, const vboolf8& b) { return _mm256_unpackhi_ps(a, b); }
-
- template<int i>
- __forceinline vboolf8 shuffle(const vboolf8& v) {
- return _mm256_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
- }
-
- template<int i0, int i1>
- __forceinline vboolf8 shuffle4(const vboolf8& v) {
- return _mm256_permute2f128_ps(v, v, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1>
- __forceinline vboolf8 shuffle4(const vboolf8& a, const vboolf8& b) {
- return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vboolf8 shuffle(const vboolf8& v) {
- return _mm256_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vboolf8 shuffle(const vboolf8& a, const vboolf8& b) {
- return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
- template<> __forceinline vboolf8 shuffle<0, 0, 2, 2>(const vboolf8& v) { return _mm256_moveldup_ps(v); }
- template<> __forceinline vboolf8 shuffle<1, 1, 3, 3>(const vboolf8& v) { return _mm256_movehdup_ps(v); }
- template<> __forceinline vboolf8 shuffle<0, 1, 0, 1>(const vboolf8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); }
-
- template<int i> __forceinline vboolf8 insert4(const vboolf8& a, const vboolf4& b) { return _mm256_insertf128_ps(a, b, i); }
- template<int i> __forceinline vboolf4 extract4 (const vboolf8& a) { return _mm256_extractf128_ps(a, i); }
- template<> __forceinline vboolf4 extract4<0>(const vboolf8& a) { return _mm256_castps256_ps128(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool reduce_and(const vboolf8& a) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
- __forceinline bool reduce_or (const vboolf8& a) { return !_mm256_testz_ps(a,a); }
-
- __forceinline bool all (const vboolf8& a) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
- __forceinline bool any (const vboolf8& a) { return !_mm256_testz_ps(a,a); }
- __forceinline bool none(const vboolf8& a) { return _mm256_testz_ps(a,a) != 0; }
-
- __forceinline bool all (const vboolf8& valid, const vboolf8& b) { return all((!valid) | b); }
- __forceinline bool any (const vboolf8& valid, const vboolf8& b) { return any(valid & b); }
- __forceinline bool none(const vboolf8& valid, const vboolf8& b) { return none(valid & b); }
-
- __forceinline unsigned int movemask(const vboolf8& a) { return _mm256_movemask_ps(a); }
- __forceinline size_t popcnt (const vboolf8& a) { return popcnt((size_t)_mm256_movemask_ps(a)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Get/Set Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool get(const vboolf8& a, size_t index) { return a[index]; }
- __forceinline void set(vboolf8& a, size_t index) { a[index] = -1; }
- __forceinline void clear(vboolf8& a, size_t index) { a[index] = 0; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf8& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
- << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vboolf8_avx512.h b/thirdparty/embree-aarch64/common/simd/vboolf8_avx512.h
deleted file mode 100644
index 2a52b554c7..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vboolf8_avx512.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX-512 bool type */
- template<>
- struct vboolf<8>
- {
- typedef vboolf8 Bool;
- typedef vint8 Int;
-
- enum { size = 8 }; // number of SIMD elements
- __mmask8 v; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf() {}
- __forceinline vboolf(const vboolf8& t) { v = t.v; }
- __forceinline vboolf8& operator =(const vboolf8& f) { v = f.v; return *this; }
-
- __forceinline vboolf(const __mmask8 &t) { v = t; }
- __forceinline operator __mmask8() const { return v; }
-
- __forceinline vboolf(bool b) { v = b ? 0xff : 0x00; }
- __forceinline vboolf(int t) { v = (__mmask8)t; }
- __forceinline vboolf(unsigned int t) { v = (__mmask8)t; }
-
- __forceinline vboolf(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h)
- : v((__mmask8)((int(h) << 7) | (int(g) << 6) | (int(f) << 5) | (int(e) << 4) | (int(d) << 3) | (int(c) << 2) | (int(b) << 1) | int(a))) {}
-
- /* return int8 mask */
- __forceinline __m128i mask8() const {
- return _mm_movm_epi8(v);
- }
-
- /* return int32 mask */
- __forceinline __m256i mask32() const {
- return _mm256_movm_epi32(v);
- }
-
- /* return int64 mask */
- __forceinline __m512i mask64() const {
- return _mm512_movm_epi64(v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf(FalseTy) : v(0x00) {}
- __forceinline vboolf(TrueTy) : v(0xff) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator [](size_t index) const {
- assert(index < 8); return (mm512_mask2int(v) >> index) & 1;
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 operator !(const vboolf8& a) { return _mm512_knot(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 operator &(const vboolf8& a, const vboolf8& b) { return _mm512_kand(a, b); }
- __forceinline vboolf8 operator |(const vboolf8& a, const vboolf8& b) { return _mm512_kor(a, b); }
- __forceinline vboolf8 operator ^(const vboolf8& a, const vboolf8& b) { return _mm512_kxor(a, b); }
-
- __forceinline vboolf8 andn(const vboolf8& a, const vboolf8& b) { return _mm512_kandn(b, a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8& operator &=(vboolf8& a, const vboolf8& b) { return a = a & b; }
- __forceinline vboolf8& operator |=(vboolf8& a, const vboolf8& b) { return a = a | b; }
- __forceinline vboolf8& operator ^=(vboolf8& a, const vboolf8& b) { return a = a ^ b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 operator !=(const vboolf8& a, const vboolf8& b) { return _mm512_kxor(a, b); }
- __forceinline vboolf8 operator ==(const vboolf8& a, const vboolf8& b) { return _mm512_kxnor(a, b); }
-
- __forceinline vboolf8 select(const vboolf8& s, const vboolf8& a, const vboolf8& b) {
- return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reduction Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline int all (const vboolf8& a) { return a.v == 0xff; }
- __forceinline int any (const vboolf8& a) { return _mm512_kortestz(a, a) == 0; }
- __forceinline int none(const vboolf8& a) { return _mm512_kortestz(a, a) != 0; }
-
- __forceinline int all (const vboolf8& valid, const vboolf8& b) { return all((!valid) | b); }
- __forceinline int any (const vboolf8& valid, const vboolf8& b) { return any(valid & b); }
- __forceinline int none(const vboolf8& valid, const vboolf8& b) { return none(valid & b); }
-
- __forceinline size_t movemask(const vboolf8& a) { return _mm512_kmov(a); }
- __forceinline size_t popcnt (const vboolf8& a) { return popcnt(a.v); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Conversion Operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline unsigned int toInt(const vboolf8& a) { return mm512_mask2int(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Get/Set Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool get(const vboolf8& a, size_t index) { assert(index < 8); return (toInt(a) >> index) & 1; }
- __forceinline void set(vboolf8& a, size_t index) { assert(index < 8); a |= 1 << index; }
- __forceinline void clear(vboolf8& a, size_t index) { assert(index < 8); a = andn(a, 1 << index); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf8& a)
- {
- cout << "<";
- for (size_t i=0; i<8; i++) {
- if ((a.v >> i) & 1) cout << "1"; else cout << "0";
- }
- return cout << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vdouble4_avx.h b/thirdparty/embree-aarch64/common/simd/vdouble4_avx.h
deleted file mode 100644
index 1f65b45d7e..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vdouble4_avx.h
+++ /dev/null
@@ -1,324 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 4-wide AVX 64-bit double type */
- template<>
- struct vdouble<4>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboold4 Bool;
-
- enum { size = 4 }; // number of SIMD elements
- union { // data
- __m256d v;
- double i[4];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble() {}
- __forceinline vdouble(const vdouble4& t) { v = t.v; }
- __forceinline vdouble4& operator =(const vdouble4& f) { v = f.v; return *this; }
-
- __forceinline vdouble(const __m256d& t) { v = t; }
- __forceinline operator __m256d() const { return v; }
-
- __forceinline vdouble(double i) {
- v = _mm256_set1_pd(i);
- }
-
- __forceinline vdouble(double a, double b, double c, double d) {
- v = _mm256_set_pd(d,c,b,a);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble(ZeroTy) : v(_mm256_setzero_pd()) {}
- __forceinline vdouble(OneTy) : v(_mm256_set1_pd(1)) {}
- __forceinline vdouble(StepTy) : v(_mm256_set_pd(3.0,2.0,1.0,0.0)) {}
- __forceinline vdouble(ReverseStepTy) : v(_mm256_setr_pd(3.0,2.0,1.0,0.0)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline void store_nt(double *__restrict__ ptr, const vdouble4& a) {
- _mm256_stream_pd(ptr, a);
- }
-
- static __forceinline vdouble4 loadu(const double* addr) {
- return _mm256_loadu_pd(addr);
- }
-
- static __forceinline vdouble4 load(const vdouble4* addr) {
- return _mm256_load_pd((double*)addr);
- }
-
- static __forceinline vdouble4 load(const double* addr) {
- return _mm256_load_pd(addr);
- }
-
- static __forceinline void store(double* ptr, const vdouble4& v) {
- _mm256_store_pd(ptr, v);
- }
-
- static __forceinline void storeu(double* ptr, const vdouble4& v) {
- _mm256_storeu_pd(ptr, v);
- }
-
- static __forceinline vdouble4 broadcast(const void* a) { return _mm256_set1_pd(*(double*)a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline double& operator [](size_t index) { assert(index < 4); return i[index]; }
- __forceinline const double& operator [](size_t index) const { assert(index < 4); return i[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX2__)
- __forceinline vdouble4 asDouble(const vllong4& a) { return _mm256_castsi256_pd(a); }
- __forceinline vllong4 asLLong (const vdouble4& a) { return _mm256_castpd_si256(a); }
-#endif
-
- __forceinline vdouble4 operator +(const vdouble4& a) { return a; }
- __forceinline vdouble4 operator -(const vdouble4& a) { return _mm256_sub_pd(_mm256_setzero_pd(), a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble4 operator +(const vdouble4& a, const vdouble4& b) { return _mm256_add_pd(a, b); }
- __forceinline vdouble4 operator +(const vdouble4& a, double b) { return a + vdouble4(b); }
- __forceinline vdouble4 operator +(double a, const vdouble4& b) { return vdouble4(a) + b; }
-
- __forceinline vdouble4 operator -(const vdouble4& a, const vdouble4& b) { return _mm256_sub_pd(a, b); }
- __forceinline vdouble4 operator -(const vdouble4& a, double b) { return a - vdouble4(b); }
- __forceinline vdouble4 operator -(double a, const vdouble4& b) { return vdouble4(a) - b; }
-
- __forceinline vdouble4 operator *(const vdouble4& a, const vdouble4& b) { return _mm256_mul_pd(a, b); }
- __forceinline vdouble4 operator *(const vdouble4& a, double b) { return a * vdouble4(b); }
- __forceinline vdouble4 operator *(double a, const vdouble4& b) { return vdouble4(a) * b; }
-
- __forceinline vdouble4 operator &(const vdouble4& a, const vdouble4& b) { return _mm256_and_pd(a, b); }
- __forceinline vdouble4 operator &(const vdouble4& a, double b) { return a & vdouble4(b); }
- __forceinline vdouble4 operator &(double a, const vdouble4& b) { return vdouble4(a) & b; }
-
- __forceinline vdouble4 operator |(const vdouble4& a, const vdouble4& b) { return _mm256_or_pd(a, b); }
- __forceinline vdouble4 operator |(const vdouble4& a, double b) { return a | vdouble4(b); }
- __forceinline vdouble4 operator |(double a, const vdouble4& b) { return vdouble4(a) | b; }
-
- __forceinline vdouble4 operator ^(const vdouble4& a, const vdouble4& b) { return _mm256_xor_pd(a, b); }
- __forceinline vdouble4 operator ^(const vdouble4& a, double b) { return a ^ vdouble4(b); }
- __forceinline vdouble4 operator ^(double a, const vdouble4& b) { return vdouble4(a) ^ b; }
-
- __forceinline vdouble4 min(const vdouble4& a, const vdouble4& b) { return _mm256_min_pd(a, b); }
- __forceinline vdouble4 min(const vdouble4& a, double b) { return min(a,vdouble4(b)); }
- __forceinline vdouble4 min(double a, const vdouble4& b) { return min(vdouble4(a),b); }
-
- __forceinline vdouble4 max(const vdouble4& a, const vdouble4& b) { return _mm256_max_pd(a, b); }
- __forceinline vdouble4 max(const vdouble4& a, double b) { return max(a,vdouble4(b)); }
- __forceinline vdouble4 max(double a, const vdouble4& b) { return max(vdouble4(a),b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__FMA__)
- __forceinline vdouble4 madd (const vdouble4& a, const vdouble4& b, const vdouble4& c) { return _mm256_fmadd_pd(a,b,c); }
- __forceinline vdouble4 msub (const vdouble4& a, const vdouble4& b, const vdouble4& c) { return _mm256_fmsub_pd(a,b,c); }
- __forceinline vdouble4 nmadd(const vdouble4& a, const vdouble4& b, const vdouble4& c) { return _mm256_fnmadd_pd(a,b,c); }
- __forceinline vdouble4 nmsub(const vdouble4& a, const vdouble4& b, const vdouble4& c) { return _mm256_fnmsub_pd(a,b,c); }
-#else
- __forceinline vdouble4 madd (const vdouble4& a, const vdouble4& b, const vdouble4& c) { return a*b+c; }
- __forceinline vdouble4 msub (const vdouble4& a, const vdouble4& b, const vdouble4& c) { return a*b-c; }
- __forceinline vdouble4 nmadd(const vdouble4& a, const vdouble4& b, const vdouble4& c) { return -a*b+c;}
- __forceinline vdouble4 nmsub(const vdouble4& a, const vdouble4& b, const vdouble4& c) { return -a*b-c; }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble4& operator +=(vdouble4& a, const vdouble4& b) { return a = a + b; }
- __forceinline vdouble4& operator +=(vdouble4& a, double b) { return a = a + b; }
-
- __forceinline vdouble4& operator -=(vdouble4& a, const vdouble4& b) { return a = a - b; }
- __forceinline vdouble4& operator -=(vdouble4& a, double b) { return a = a - b; }
-
- __forceinline vdouble4& operator *=(vdouble4& a, const vdouble4& b) { return a = a * b; }
- __forceinline vdouble4& operator *=(vdouble4& a, double b) { return a = a * b; }
-
- __forceinline vdouble4& operator &=(vdouble4& a, const vdouble4& b) { return a = a & b; }
- __forceinline vdouble4& operator &=(vdouble4& a, double b) { return a = a & b; }
-
- __forceinline vdouble4& operator |=(vdouble4& a, const vdouble4& b) { return a = a | b; }
- __forceinline vdouble4& operator |=(vdouble4& a, double b) { return a = a | b; }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_EQ); }
- __forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_NE); }
- __forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_LT); }
- __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_GE); }
- __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_GT); }
- __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_LE); }
-#elif !defined(__aarch64__)
- __forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_EQ_OQ); }
- __forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NEQ_UQ); }
- __forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_LT_OS); }
- __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NLT_US); }
- __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NLE_US); }
- __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_LE_OS); }
-#else
- __forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmpeq_pd(a, b); }
- __forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmpneq_pd(a, b); }
- __forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmplt_pd(a, b); }
- __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmpnlt_pd(a, b); }
- __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmpnle_pd(a, b); }
- __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmple_pd(a, b); }
-#endif
-
- __forceinline vboold4 operator ==(const vdouble4& a, double b) { return a == vdouble4(b); }
- __forceinline vboold4 operator ==(double a, const vdouble4& b) { return vdouble4(a) == b; }
-
- __forceinline vboold4 operator !=(const vdouble4& a, double b) { return a != vdouble4(b); }
- __forceinline vboold4 operator !=(double a, const vdouble4& b) { return vdouble4(a) != b; }
-
- __forceinline vboold4 operator < (const vdouble4& a, double b) { return a < vdouble4(b); }
- __forceinline vboold4 operator < (double a, const vdouble4& b) { return vdouble4(a) < b; }
-
- __forceinline vboold4 operator >=(const vdouble4& a, double b) { return a >= vdouble4(b); }
- __forceinline vboold4 operator >=(double a, const vdouble4& b) { return vdouble4(a) >= b; }
-
- __forceinline vboold4 operator > (const vdouble4& a, double b) { return a > vdouble4(b); }
- __forceinline vboold4 operator > (double a, const vdouble4& b) { return vdouble4(a) > b; }
-
- __forceinline vboold4 operator <=(const vdouble4& a, double b) { return a <= vdouble4(b); }
- __forceinline vboold4 operator <=(double a, const vdouble4& b) { return vdouble4(a) <= b; }
-
- __forceinline vboold4 eq(const vdouble4& a, const vdouble4& b) { return a == b; }
- __forceinline vboold4 ne(const vdouble4& a, const vdouble4& b) { return a != b; }
- __forceinline vboold4 lt(const vdouble4& a, const vdouble4& b) { return a < b; }
- __forceinline vboold4 ge(const vdouble4& a, const vdouble4& b) { return a >= b; }
- __forceinline vboold4 gt(const vdouble4& a, const vdouble4& b) { return a > b; }
- __forceinline vboold4 le(const vdouble4& a, const vdouble4& b) { return a <= b; }
-
-#if defined(__AVX512VL__)
- __forceinline vboold4 eq(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_EQ); }
- __forceinline vboold4 ne(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_NE); }
- __forceinline vboold4 lt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_LT); }
- __forceinline vboold4 ge(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_GE); }
- __forceinline vboold4 gt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_GT); }
- __forceinline vboold4 le(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_LE); }
-#else
- __forceinline vboold4 eq(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a == b); }
- __forceinline vboold4 ne(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a != b); }
- __forceinline vboold4 lt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a < b); }
- __forceinline vboold4 ge(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a >= b); }
- __forceinline vboold4 gt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a > b); }
- __forceinline vboold4 le(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a <= b); }
-#endif
-
- __forceinline vdouble4 select(const vboold4& m, const vdouble4& t, const vdouble4& f) {
-#if defined(__AVX512VL__)
- return _mm256_mask_blend_pd(m, f, t);
-#else
- return _mm256_blendv_pd(f, t, m);
-#endif
- }
-
- __forceinline void xchg(const vboold4& m, vdouble4& a, vdouble4& b) {
- const vdouble4 c = a; a = select(m,b,a); b = select(m,c,b);
- }
-
- __forceinline vboold4 test(const vdouble4& a, const vdouble4& b) {
-#if defined(__AVX512VL__)
- return _mm256_test_epi64_mask(_mm256_castpd_si256(a),_mm256_castpd_si256(b));
-#else
- return _mm256_testz_si256(_mm256_castpd_si256(a),_mm256_castpd_si256(b));
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int i0, int i1>
- __forceinline vdouble4 shuffle(const vdouble4& v) {
- return _mm256_permute_pd(v, (i1 << 3) | (i0 << 2) | (i1 << 1) | i0);
- }
-
- template<int i>
- __forceinline vdouble4 shuffle(const vdouble4& v) {
- return shuffle<i, i>(v);
- }
-
- template<int i0, int i1>
- __forceinline vdouble4 shuffle2(const vdouble4& v) {
- return _mm256_permute2f128_pd(v, v, (i1 << 4) | i0);
- }
-
- __forceinline double toScalar(const vdouble4& v) {
- return _mm_cvtsd_f64(_mm256_castpd256_pd128(v));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble4 vreduce_min2(const vdouble4& x) { return min(x, shuffle<1,0>(x)); }
- __forceinline vdouble4 vreduce_min (const vdouble4& y) { const vdouble4 x = vreduce_min2(y); return min(x, shuffle2<1,0>(x)); }
-
- __forceinline vdouble4 vreduce_max2(const vdouble4& x) { return max(x,shuffle<1,0>(x)); }
- __forceinline vdouble4 vreduce_max (const vdouble4& y) { const vdouble4 x = vreduce_max2(y); return max(x, shuffle2<1,0>(x)); }
-
- __forceinline vdouble4 vreduce_and2(const vdouble4& x) { return x & shuffle<1,0>(x); }
- __forceinline vdouble4 vreduce_and (const vdouble4& y) { const vdouble4 x = vreduce_and2(y); return x & shuffle2<1,0>(x); }
-
- __forceinline vdouble4 vreduce_or2(const vdouble4& x) { return x | shuffle<1,0>(x); }
- __forceinline vdouble4 vreduce_or (const vdouble4& y) { const vdouble4 x = vreduce_or2(y); return x | shuffle2<1,0>(x); }
-
- __forceinline vdouble4 vreduce_add2(const vdouble4& x) { return x + shuffle<1,0>(x); }
- __forceinline vdouble4 vreduce_add (const vdouble4& y) { const vdouble4 x = vreduce_add2(y); return x + shuffle2<1,0>(x); }
-
- __forceinline double reduce_add(const vdouble4& a) { return toScalar(vreduce_add(a)); }
- __forceinline double reduce_min(const vdouble4& a) { return toScalar(vreduce_min(a)); }
- __forceinline double reduce_max(const vdouble4& a) { return toScalar(vreduce_max(a)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Memory load and store operations
- ////////////////////////////////////////////////////////////////////////////////
-
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vdouble4& v)
- {
- cout << "<" << v[0];
- for (size_t i=1; i<4; i++) cout << ", " << v[i];
- cout << ">";
- return cout;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vdouble8_avx512.h b/thirdparty/embree-aarch64/common/simd/vdouble8_avx512.h
deleted file mode 100644
index 4eec7d2f6a..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vdouble8_avx512.h
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX-512 64-bit double type */
- template<>
- struct vdouble<8>
- {
- ALIGNED_STRUCT_(64);
-
- typedef vboold8 Bool;
-
- enum { size = 8 }; // number of SIMD elements
- union { // data
- __m512d v;
- double i[8];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble() {}
- __forceinline vdouble(const vdouble8& t) { v = t.v; }
- __forceinline vdouble8& operator =(const vdouble8& f) { v = f.v; return *this; }
-
- __forceinline vdouble(const __m512d& t) { v = t; }
- __forceinline operator __m512d() const { return v; }
- __forceinline operator __m256d() const { return _mm512_castpd512_pd256(v); }
-
- __forceinline vdouble(double i) {
- v = _mm512_set1_pd(i);
- }
-
- __forceinline vdouble(double a, double b, double c, double d) {
- v = _mm512_set4_pd(d,c,b,a);
- }
-
- __forceinline vdouble(double a0, double a1, double a2, double a3,
- double a4, double a5, double a6, double a7)
- {
- v = _mm512_set_pd(a7,a6,a5,a4,a3,a2,a1,a0);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble(ZeroTy) : v(_mm512_setzero_pd()) {}
- __forceinline vdouble(OneTy) : v(_mm512_set1_pd(1)) {}
- __forceinline vdouble(StepTy) : v(_mm512_set_pd(7.0,6.0,5.0,4.0,3.0,2.0,1.0,0.0)) {}
- __forceinline vdouble(ReverseStepTy) : v(_mm512_setr_pd(7.0,6.0,5.0,4.0,3.0,2.0,1.0,0.0)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline void store_nt(void *__restrict__ ptr, const vdouble8& a) {
- _mm512_stream_pd((double*)ptr, a);
- }
-
- static __forceinline vdouble8 loadu(const void* addr) {
- return _mm512_loadu_pd((double*)addr);
- }
-
- static __forceinline vdouble8 load(const vdouble8* addr) {
- return _mm512_load_pd((double*)addr);
- }
-
- static __forceinline vdouble8 load(const double* addr) {
- return _mm512_load_pd(addr);
- }
-
- static __forceinline void store(void* ptr, const vdouble8& v) {
- _mm512_store_pd(ptr, v);
- }
-
- static __forceinline void storeu(void* ptr, const vdouble8& v) {
- _mm512_storeu_pd(ptr, v);
- }
-
- static __forceinline void storeu(const vboold8& mask, double* ptr, const vdouble8& f) {
- _mm512_mask_storeu_pd(ptr, mask, f);
- }
-
- static __forceinline void store(const vboold8& mask, void* addr, const vdouble8& v2) {
- _mm512_mask_store_pd(addr, mask, v2);
- }
-
- /* pass by value to avoid compiler generating inefficient code */
- static __forceinline void storeu_compact(const vboold8 mask,void * addr, const vdouble8& reg) {
- _mm512_mask_compressstoreu_pd(addr, mask, reg);
- }
-
- static __forceinline vdouble8 compact64bit(const vboold8& mask, vdouble8& v) {
- return _mm512_mask_compress_pd(v, mask, v);
- }
-
- static __forceinline vdouble8 compact(const vboold8& mask, vdouble8& v) {
- return _mm512_mask_compress_pd(v, mask, v);
- }
-
- static __forceinline vdouble8 compact(const vboold8& mask, const vdouble8& a, vdouble8& b) {
- return _mm512_mask_compress_pd(a, mask, b);
- }
-
- static __forceinline vdouble8 broadcast(const void* a) { return _mm512_set1_pd(*(double*)a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline double& operator [](size_t index) { assert(index < 8); return i[index]; }
- __forceinline const double& operator [](size_t index) const { assert(index < 8); return i[index]; }
-
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble8 asDouble(const vllong8& a) { return _mm512_castsi512_pd(a); }
- __forceinline vllong8 asLLong (const vdouble8& a) { return _mm512_castpd_si512(a); }
-
- __forceinline vdouble8 operator +(const vdouble8& a) { return a; }
- __forceinline vdouble8 operator -(const vdouble8& a) { return _mm512_sub_pd(_mm512_setzero_pd(), a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble8 operator +(const vdouble8& a, const vdouble8& b) { return _mm512_add_pd(a, b); }
- __forceinline vdouble8 operator +(const vdouble8& a, double b) { return a + vdouble8(b); }
- __forceinline vdouble8 operator +(double a, const vdouble8& b) { return vdouble8(a) + b; }
-
- __forceinline vdouble8 operator -(const vdouble8& a, const vdouble8& b) { return _mm512_sub_pd(a, b); }
- __forceinline vdouble8 operator -(const vdouble8& a, double b) { return a - vdouble8(b); }
- __forceinline vdouble8 operator -(double a, const vdouble8& b) { return vdouble8(a) - b; }
-
- __forceinline vdouble8 operator *(const vdouble8& a, const vdouble8& b) { return _mm512_mul_pd(a, b); }
- __forceinline vdouble8 operator *(const vdouble8& a, double b) { return a * vdouble8(b); }
- __forceinline vdouble8 operator *(double a, const vdouble8& b) { return vdouble8(a) * b; }
-
- __forceinline vdouble8 operator &(const vdouble8& a, const vdouble8& b) { return _mm512_and_pd(a, b); }
- __forceinline vdouble8 operator &(const vdouble8& a, double b) { return a & vdouble8(b); }
- __forceinline vdouble8 operator &(double a, const vdouble8& b) { return vdouble8(a) & b; }
-
- __forceinline vdouble8 operator |(const vdouble8& a, const vdouble8& b) { return _mm512_or_pd(a, b); }
- __forceinline vdouble8 operator |(const vdouble8& a, double b) { return a | vdouble8(b); }
- __forceinline vdouble8 operator |(double a, const vdouble8& b) { return vdouble8(a) | b; }
-
- __forceinline vdouble8 operator ^(const vdouble8& a, const vdouble8& b) { return _mm512_xor_pd(a, b); }
- __forceinline vdouble8 operator ^(const vdouble8& a, double b) { return a ^ vdouble8(b); }
- __forceinline vdouble8 operator ^(double a, const vdouble8& b) { return vdouble8(a) ^ b; }
-
- __forceinline vdouble8 operator <<(const vdouble8& a, const unsigned int n) { return _mm512_castsi512_pd(_mm512_slli_epi64(_mm512_castpd_si512(a), n)); }
- __forceinline vdouble8 operator >>(const vdouble8& a, const unsigned int n) { return _mm512_castsi512_pd(_mm512_srai_epi64(_mm512_castpd_si512(a), n)); }
-
- __forceinline vdouble8 operator <<(const vdouble8& a, const vllong8& n) { return _mm512_castsi512_pd(_mm512_sllv_epi64(_mm512_castpd_si512(a), n)); }
- __forceinline vdouble8 operator >>(const vdouble8& a, const vllong8& n) { return _mm512_castsi512_pd(_mm512_srav_epi64(_mm512_castpd_si512(a), n)); }
-
- __forceinline vdouble8 sll (const vdouble8& a, const unsigned int b) { return _mm512_castsi512_pd(_mm512_slli_epi64(_mm512_castpd_si512(a), b)); }
- __forceinline vdouble8 sra (const vdouble8& a, const unsigned int b) { return _mm512_castsi512_pd(_mm512_srai_epi64(_mm512_castpd_si512(a), b)); }
- __forceinline vdouble8 srl (const vdouble8& a, const unsigned int b) { return _mm512_castsi512_pd(_mm512_srli_epi64(_mm512_castpd_si512(a), b)); }
-
- __forceinline vdouble8 min(const vdouble8& a, const vdouble8& b) { return _mm512_min_pd(a, b); }
- __forceinline vdouble8 min(const vdouble8& a, double b) { return min(a,vdouble8(b)); }
- __forceinline vdouble8 min(double a, const vdouble8& b) { return min(vdouble8(a),b); }
-
- __forceinline vdouble8 max(const vdouble8& a, const vdouble8& b) { return _mm512_max_pd(a, b); }
- __forceinline vdouble8 max(const vdouble8& a, double b) { return max(a,vdouble8(b)); }
- __forceinline vdouble8 max(double a, const vdouble8& b) { return max(vdouble8(a),b); }
-
- __forceinline vdouble8 mask_add(const vboold8& mask, vdouble8& c, const vdouble8& a, const vdouble8& b) { return _mm512_mask_add_pd(c,mask,a,b); }
- __forceinline vdouble8 mask_sub(const vboold8& mask, vdouble8& c, const vdouble8& a, const vdouble8& b) { return _mm512_mask_sub_pd(c,mask,a,b); }
-
- __forceinline vdouble8 mask_and(const vboold8& m,vdouble8& c, const vdouble8& a, const vdouble8& b) { return _mm512_mask_and_pd(c,m,a,b); }
- __forceinline vdouble8 mask_or (const vboold8& m,vdouble8& c, const vdouble8& a, const vdouble8& b) { return _mm512_mask_or_pd(c,m,a,b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble8 madd (const vdouble8& a, const vdouble8& b, const vdouble8& c) { return _mm512_fmadd_pd(a,b,c); }
- __forceinline vdouble8 msub (const vdouble8& a, const vdouble8& b, const vdouble8& c) { return _mm512_fmsub_pd(a,b,c); }
- __forceinline vdouble8 nmadd(const vdouble8& a, const vdouble8& b, const vdouble8& c) { return _mm512_fnmadd_pd(a,b,c); }
- __forceinline vdouble8 nmsub(const vdouble8& a, const vdouble8& b, const vdouble8& c) { return _mm512_fnmsub_pd(a,b,c); }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble8& operator +=(vdouble8& a, const vdouble8& b) { return a = a + b; }
- __forceinline vdouble8& operator +=(vdouble8& a, double b) { return a = a + b; }
-
- __forceinline vdouble8& operator -=(vdouble8& a, const vdouble8& b) { return a = a - b; }
- __forceinline vdouble8& operator -=(vdouble8& a, double b) { return a = a - b; }
-
- __forceinline vdouble8& operator *=(vdouble8& a, const vdouble8& b) { return a = a * b; }
- __forceinline vdouble8& operator *=(vdouble8& a, double b) { return a = a * b; }
-
- __forceinline vdouble8& operator &=(vdouble8& a, const vdouble8& b) { return a = a & b; }
- __forceinline vdouble8& operator &=(vdouble8& a, double b) { return a = a & b; }
-
- __forceinline vdouble8& operator |=(vdouble8& a, const vdouble8& b) { return a = a | b; }
- __forceinline vdouble8& operator |=(vdouble8& a, double b) { return a = a | b; }
-
- __forceinline vdouble8& operator <<=(vdouble8& a, const double b) { return a = a << b; }
- __forceinline vdouble8& operator >>=(vdouble8& a, const double b) { return a = a >> b; }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold8 operator ==(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboold8 operator ==(const vdouble8& a, double b) { return a == vdouble8(b); }
- __forceinline vboold8 operator ==(double a, const vdouble8& b) { return vdouble8(a) == b; }
-
- __forceinline vboold8 operator !=(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboold8 operator !=(const vdouble8& a, double b) { return a != vdouble8(b); }
- __forceinline vboold8 operator !=(double a, const vdouble8& b) { return vdouble8(a) != b; }
-
- __forceinline vboold8 operator < (const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboold8 operator < (const vdouble8& a, double b) { return a < vdouble8(b); }
- __forceinline vboold8 operator < (double a, const vdouble8& b) { return vdouble8(a) < b; }
-
- __forceinline vboold8 operator >=(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboold8 operator >=(const vdouble8& a, double b) { return a >= vdouble8(b); }
- __forceinline vboold8 operator >=(double a, const vdouble8& b) { return vdouble8(a) >= b; }
-
- __forceinline vboold8 operator > (const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboold8 operator > (const vdouble8& a, double b) { return a > vdouble8(b); }
- __forceinline vboold8 operator > (double a, const vdouble8& b) { return vdouble8(a) > b; }
-
- __forceinline vboold8 operator <=(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_LE); }
- __forceinline vboold8 operator <=(const vdouble8& a, double b) { return a <= vdouble8(b); }
- __forceinline vboold8 operator <=(double a, const vdouble8& b) { return vdouble8(a) <= b; }
-
- __forceinline vboold8 eq(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboold8 ne(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboold8 lt(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboold8 ge(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboold8 gt(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboold8 le(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_LE); }
-
- __forceinline vboold8 eq(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_EQ); }
- __forceinline vboold8 ne(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_NE); }
- __forceinline vboold8 lt(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_LT); }
- __forceinline vboold8 ge(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_GE); }
- __forceinline vboold8 gt(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_GT); }
- __forceinline vboold8 le(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_LE); }
-
- __forceinline vdouble8 select(const vboold8& m, const vdouble8& t, const vdouble8& f) {
- return _mm512_mask_or_pd(f,m,t,t);
- }
-
- __forceinline void xchg(const vboold8& m, vdouble8& a, vdouble8& b) {
- const vdouble8 c = a; a = select(m,b,a); b = select(m,c,b);
- }
-
- __forceinline vboold8 test(const vboold8& m, const vdouble8& a, const vdouble8& b) {
- return _mm512_mask_test_epi64_mask(m,_mm512_castpd_si512(a),_mm512_castpd_si512(b));
- }
-
- __forceinline vboold8 test(const vdouble8& a, const vdouble8& b) {
- return _mm512_test_epi64_mask(_mm512_castpd_si512(a),_mm512_castpd_si512(b));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int i0, int i1>
- __forceinline vdouble8 shuffle(const vdouble8& v) {
- return _mm512_permute_pd(v, (i1 << 7) | (i0 << 6) | (i1 << 5) | (i0 << 4) | (i1 << 3) | (i0 << 2) | (i1 << 1) | i0);
- }
-
- template<int i>
- __forceinline vdouble8 shuffle(const vdouble8& v) {
- return shuffle<i, i>(v);
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vdouble8 shuffle(const vdouble8& v) {
- return _mm512_permutex_pd(v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
- template<int i0, int i1>
- __forceinline vdouble8 shuffle4(const vdouble8& v) {
- return _mm512_shuffle_f64x2(v, v, _MM_SHUFFLE(i1*2+1, i1*2, i0*2+1, i0*2));
- }
-
- template<int i>
- __forceinline vdouble8 shuffle4(const vdouble8& v) {
- return shuffle4<i, i>(v);
- }
-
- template<int i>
- __forceinline vdouble8 align_shift_right(const vdouble8& a, const vdouble8& b) {
- return _mm512_castsi512_pd(_mm512_alignr_epi64(_mm512_castpd_si512(a), _mm512_castpd_si512(b), i));
- }
-
- __forceinline double toScalar(const vdouble8& v) {
- return _mm_cvtsd_f64(_mm512_castpd512_pd128(v));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble8 vreduce_add2(vdouble8 x) { return x + shuffle<1,0,3,2>(x); }
- __forceinline vdouble8 vreduce_add4(vdouble8 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
- __forceinline vdouble8 vreduce_add (vdouble8 x) { x = vreduce_add4(x); return x + shuffle4<1,0>(x); }
-
- __forceinline vdouble8 vreduce_min2(vdouble8 x) { return min(x, shuffle<1,0,3,2>(x)); }
- __forceinline vdouble8 vreduce_min4(vdouble8 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
- __forceinline vdouble8 vreduce_min (vdouble8 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0>(x)); }
-
- __forceinline vdouble8 vreduce_max2(vdouble8 x) { return max(x, shuffle<1,0,3,2>(x)); }
- __forceinline vdouble8 vreduce_max4(vdouble8 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
- __forceinline vdouble8 vreduce_max (vdouble8 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0>(x)); }
-
- __forceinline double reduce_add(const vdouble8& v) { return toScalar(vreduce_add(v)); }
- __forceinline double reduce_min(const vdouble8& v) { return toScalar(vreduce_min(v)); }
- __forceinline double reduce_max(const vdouble8& v) { return toScalar(vreduce_max(v)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Memory load and store operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vdouble8 permute(const vdouble8& v, const vllong8& index) {
- return _mm512_permutexvar_pd(index, v);
- }
-
- __forceinline vdouble8 reverse(const vdouble8& a) {
- return permute(a, vllong8(reverse_step));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vdouble8& v)
- {
- cout << "<" << v[0];
- for (size_t i=1; i<8; i++) cout << ", " << v[i];
- cout << ">";
- return cout;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vfloat16_avx512.h b/thirdparty/embree-aarch64/common/simd/vfloat16_avx512.h
deleted file mode 100644
index aed2419b77..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vfloat16_avx512.h
+++ /dev/null
@@ -1,771 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 16-wide AVX-512 float type */
- template<>
- struct vfloat<16>
- {
- ALIGNED_STRUCT_(64);
-
- typedef vboolf16 Bool;
- typedef vint16 Int;
- typedef vfloat16 Float;
-
- enum { size = 16 }; // number of SIMD elements
- union { // data
- __m512 v;
- float f[16];
- int i[16];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat() {}
- __forceinline vfloat(const vfloat16& t) { v = t; }
- __forceinline vfloat16& operator =(const vfloat16& f) { v = f.v; return *this; }
-
- __forceinline vfloat(const __m512& t) { v = t; }
- __forceinline operator __m512() const { return v; }
- __forceinline operator __m256() const { return _mm512_castps512_ps256(v); }
- __forceinline operator __m128() const { return _mm512_castps512_ps128(v); }
-
- __forceinline vfloat(float f) {
- v = _mm512_set1_ps(f);
- }
-
- __forceinline vfloat(float a, float b, float c, float d) {
- v = _mm512_set4_ps(a, b, c, d);
- }
-
- __forceinline vfloat(const vfloat4& i) {
- v = _mm512_broadcast_f32x4(i);
- }
-
- __forceinline vfloat(const vfloat4& a, const vfloat4& b, const vfloat4& c, const vfloat4& d) {
- v = _mm512_castps128_ps512(a);
- v = _mm512_insertf32x4(v, b, 1);
- v = _mm512_insertf32x4(v, c, 2);
- v = _mm512_insertf32x4(v, d, 3);
- }
-
- __forceinline vfloat(const vboolf16& mask, const vfloat4& a, const vfloat4& b) {
- v = _mm512_broadcast_f32x4(a);
- v = _mm512_mask_broadcast_f32x4(v,mask,b);
- }
-
- __forceinline vfloat(const vfloat8& i) {
- v = _mm512_castpd_ps(_mm512_broadcast_f64x4(_mm256_castps_pd(i)));
- }
-
- __forceinline vfloat(const vfloat8& a, const vfloat8& b) {
- v = _mm512_castps256_ps512(a);
-#if defined(__AVX512DQ__)
- v = _mm512_insertf32x8(v, b, 1);
-#else
- v = _mm512_castpd_ps(_mm512_insertf64x4(_mm512_castps_pd(v), _mm256_castps_pd(b), 1));
-#endif
- }
-
- /* WARNING: due to f64x4 the mask is considered as an 8bit mask */
- __forceinline vfloat(const vboolf16& mask, const vfloat8& a, const vfloat8& b) {
- __m512d aa = _mm512_broadcast_f64x4(_mm256_castps_pd(a));
- aa = _mm512_mask_broadcast_f64x4(aa,mask,_mm256_castps_pd(b));
- v = _mm512_castpd_ps(aa);
- }
-
- __forceinline explicit vfloat(const vint16& a) {
- v = _mm512_cvtepi32_ps(a);
- }
-
- __forceinline explicit vfloat(const vuint16& a) {
- v = _mm512_cvtepu32_ps(a);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat(ZeroTy) : v(_mm512_setzero_ps()) {}
- __forceinline vfloat(OneTy) : v(_mm512_set1_ps(1.0f)) {}
- __forceinline vfloat(PosInfTy) : v(_mm512_set1_ps(pos_inf)) {}
- __forceinline vfloat(NegInfTy) : v(_mm512_set1_ps(neg_inf)) {}
- __forceinline vfloat(StepTy) : v(_mm512_set_ps(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
- __forceinline vfloat(NaNTy) : v(_mm512_set1_ps(nan)) {}
- __forceinline vfloat(UndefinedTy) : v(_mm512_undefined_ps()) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vfloat16 load (const void* ptr) { return _mm512_load_ps((float*)ptr); }
- static __forceinline vfloat16 loadu(const void* ptr) { return _mm512_loadu_ps((float*)ptr); }
-
- static __forceinline vfloat16 load (const vboolf16& mask, const void* ptr) { return _mm512_mask_load_ps (_mm512_setzero_ps(),mask,(float*)ptr); }
- static __forceinline vfloat16 loadu(const vboolf16& mask, const void* ptr) { return _mm512_mask_loadu_ps(_mm512_setzero_ps(),mask,(float*)ptr); }
-
- static __forceinline void store (void* ptr, const vfloat16& v) { _mm512_store_ps ((float*)ptr,v); }
- static __forceinline void storeu(void* ptr, const vfloat16& v) { _mm512_storeu_ps((float*)ptr,v); }
-
- static __forceinline void store (const vboolf16& mask, void* ptr, const vfloat16& v) { _mm512_mask_store_ps ((float*)ptr,mask,v); }
- static __forceinline void storeu(const vboolf16& mask, void* ptr, const vfloat16& v) { _mm512_mask_storeu_ps((float*)ptr,mask,v); }
-
- static __forceinline void store_nt(void* __restrict__ ptr, const vfloat16& a) {
- _mm512_stream_ps((float*)ptr,a);
- }
-
- static __forceinline vfloat16 broadcast(const float* f) {
- return _mm512_set1_ps(*f);
- }
-
- static __forceinline vfloat16 compact(const vboolf16& mask, vfloat16 &v) {
- return _mm512_mask_compress_ps(v, mask, v);
- }
- static __forceinline vfloat16 compact(const vboolf16& mask, vfloat16 &a, const vfloat16& b) {
- return _mm512_mask_compress_ps(a, mask, b);
- }
-
- static __forceinline vfloat16 expand(const vboolf16& mask, const vfloat16& a, vfloat16& b) {
- return _mm512_mask_expand_ps(b, mask, a);
- }
-
- static __forceinline vfloat16 loadu_compact(const vboolf16& mask, const void* ptr) {
- return _mm512_mask_expandloadu_ps(_mm512_setzero_ps(), mask, (float*)ptr);
- }
-
- static __forceinline void storeu_compact(const vboolf16& mask, float *addr, const vfloat16 reg) {
- _mm512_mask_compressstoreu_ps(addr, mask, reg);
- }
-
- static __forceinline void storeu_compact_single(const vboolf16& mask, float * addr, const vfloat16& reg) {
- //_mm512_mask_compressstoreu_ps(addr,mask,reg);
- *addr = mm512_cvtss_f32(_mm512_mask_compress_ps(reg, mask, reg));
- }
-
- template<int scale = 4>
- static __forceinline vfloat16 gather(const float* ptr, const vint16& index) {
- return _mm512_i32gather_ps(index, ptr, scale);
- }
-
- template<int scale = 4>
- static __forceinline vfloat16 gather(const vboolf16& mask, const float* ptr, const vint16& index) {
- vfloat16 r = zero;
- return _mm512_mask_i32gather_ps(r, mask, index, ptr, scale);
- }
-
- template<int scale = 4>
- static __forceinline void scatter(float* ptr, const vint16& index, const vfloat16& v) {
- _mm512_i32scatter_ps(ptr, index, v, scale);
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf16& mask, float* ptr, const vint16& index, const vfloat16& v) {
- _mm512_mask_i32scatter_ps(ptr, mask, index, v, scale);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline float& operator [](size_t index) { assert(index < 16); return f[index]; }
- __forceinline const float& operator [](size_t index) const { assert(index < 16); return f[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16 asFloat(const vint16& a) { return _mm512_castsi512_ps(a); }
- __forceinline vint16 asInt (const vfloat16& a) { return _mm512_castps_si512(a); }
- __forceinline vuint16 asUInt (const vfloat16& a) { return _mm512_castps_si512(a); }
-
- __forceinline vint16 toInt (const vfloat16& a) { return vint16(a); }
- __forceinline vfloat16 toFloat(const vint16& a) { return vfloat16(a); }
-
- __forceinline vfloat16 operator +(const vfloat16& a) { return a; }
- __forceinline vfloat16 operator -(const vfloat16& a) { return _mm512_mul_ps(a,vfloat16(-1)); }
-
- __forceinline vfloat16 abs (const vfloat16& a) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x7FFFFFFF))); }
- __forceinline vfloat16 signmsk(const vfloat16& a) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x80000000))); }
-
- __forceinline vfloat16 rcp(const vfloat16& a) {
-#if defined(__AVX512ER__)
- return _mm512_rcp28_ps(a);
-#else
- const vfloat16 r = _mm512_rcp14_ps(a);
- return _mm512_mul_ps(r, _mm512_fnmadd_ps(r, a, vfloat16(2.0f)));
-#endif
- }
-
- __forceinline vfloat16 sqr (const vfloat16& a) { return _mm512_mul_ps(a,a); }
- __forceinline vfloat16 sqrt(const vfloat16& a) { return _mm512_sqrt_ps(a); }
-
- __forceinline vfloat16 rsqrt(const vfloat16& a)
- {
-#if defined(__AVX512VL__)
- const vfloat16 r = _mm512_rsqrt14_ps(a);
- return _mm512_fmadd_ps(_mm512_set1_ps(1.5f), r,
- _mm512_mul_ps(_mm512_mul_ps(_mm512_mul_ps(a, _mm512_set1_ps(-0.5f)), r), _mm512_mul_ps(r, r)));
-#else
- return _mm512_rsqrt28_ps(a);
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16 operator +(const vfloat16& a, const vfloat16& b) { return _mm512_add_ps(a, b); }
- __forceinline vfloat16 operator +(const vfloat16& a, float b) { return a + vfloat16(b); }
- __forceinline vfloat16 operator +(float a, const vfloat16& b) { return vfloat16(a) + b; }
-
- __forceinline vfloat16 operator -(const vfloat16& a, const vfloat16& b) { return _mm512_sub_ps(a, b); }
- __forceinline vfloat16 operator -(const vfloat16& a, float b) { return a - vfloat16(b); }
- __forceinline vfloat16 operator -(float a, const vfloat16& b) { return vfloat16(a) - b; }
-
- __forceinline vfloat16 operator *(const vfloat16& a, const vfloat16& b) { return _mm512_mul_ps(a, b); }
- __forceinline vfloat16 operator *(const vfloat16& a, float b) { return a * vfloat16(b); }
- __forceinline vfloat16 operator *(float a, const vfloat16& b) { return vfloat16(a) * b; }
-
- __forceinline vfloat16 operator /(const vfloat16& a, const vfloat16& b) { return _mm512_div_ps(a,b); }
- __forceinline vfloat16 operator /(const vfloat16& a, float b) { return a/vfloat16(b); }
- __forceinline vfloat16 operator /(float a, const vfloat16& b) { return vfloat16(a)/b; }
-
- __forceinline vfloat16 operator &(const vfloat16& a, const vfloat16& b) { return _mm512_and_ps(a,b); }
- __forceinline vfloat16 operator |(const vfloat16& a, const vfloat16& b) { return _mm512_or_ps(a,b); }
- __forceinline vfloat16 operator ^(const vfloat16& a, const vfloat16& b) {
- return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b)));
- }
-
- __forceinline vfloat16 min(const vfloat16& a, const vfloat16& b) {
- return _mm512_min_ps(a,b);
- }
- __forceinline vfloat16 min(const vfloat16& a, float b) {
- return _mm512_min_ps(a,vfloat16(b));
- }
- __forceinline vfloat16 min(const float& a, const vfloat16& b) {
- return _mm512_min_ps(vfloat16(a),b);
- }
-
- __forceinline vfloat16 max(const vfloat16& a, const vfloat16& b) {
- return _mm512_max_ps(a,b);
- }
- __forceinline vfloat16 max(const vfloat16& a, float b) {
- return _mm512_max_ps(a,vfloat16(b));
- }
- __forceinline vfloat16 max(const float& a, const vfloat16& b) {
- return _mm512_max_ps(vfloat16(a),b);
- }
-
- __forceinline vfloat16 mask_add(const vboolf16& mask, const vfloat16& c, const vfloat16& a, const vfloat16& b) { return _mm512_mask_add_ps (c,mask,a,b); }
- __forceinline vfloat16 mask_min(const vboolf16& mask, const vfloat16& c, const vfloat16& a, const vfloat16& b) {
- return _mm512_mask_min_ps(c,mask,a,b);
- };
- __forceinline vfloat16 mask_max(const vboolf16& mask, const vfloat16& c, const vfloat16& a, const vfloat16& b) {
- return _mm512_mask_max_ps(c,mask,a,b);
- };
-
- __forceinline vfloat16 mini(const vfloat16& a, const vfloat16& b) {
-#if !defined(__AVX512ER__) // SKX
- const vint16 ai = _mm512_castps_si512(a);
- const vint16 bi = _mm512_castps_si512(b);
- const vint16 ci = _mm512_min_epi32(ai,bi);
- return _mm512_castsi512_ps(ci);
-#else // KNL
- return min(a,b);
-#endif
- }
-
- __forceinline vfloat16 maxi(const vfloat16& a, const vfloat16& b) {
-#if !defined(__AVX512ER__) // SKX
- const vint16 ai = _mm512_castps_si512(a);
- const vint16 bi = _mm512_castps_si512(b);
- const vint16 ci = _mm512_max_epi32(ai,bi);
- return _mm512_castsi512_ps(ci);
-#else // KNL
- return max(a,b);
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16 madd (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmadd_ps(a,b,c); }
- __forceinline vfloat16 msub (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmsub_ps(a,b,c); }
- __forceinline vfloat16 nmadd(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fnmadd_ps(a,b,c); }
- __forceinline vfloat16 nmsub(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fnmsub_ps(a,b,c); }
-
- __forceinline vfloat16 mask_msub(const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_fmsub_ps(a,mask,b,c); }
-
- __forceinline vfloat16 madd231 (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmadd_ps(c,b,a); }
- __forceinline vfloat16 msub213 (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmsub_ps(a,b,c); }
- __forceinline vfloat16 msub231 (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmsub_ps(c,b,a); }
- __forceinline vfloat16 msubr231(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fnmadd_ps(c,b,a); }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Operators with rounding
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16 madd_round_down(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmadd_round_ps(a,b,c,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); }
- __forceinline vfloat16 madd_round_up (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmadd_round_ps(a,b,c,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); }
-
- __forceinline vfloat16 mul_round_down(const vfloat16& a, const vfloat16& b) { return _mm512_mul_round_ps(a,b,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); }
- __forceinline vfloat16 mul_round_up (const vfloat16& a, const vfloat16& b) { return _mm512_mul_round_ps(a,b,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); }
-
- __forceinline vfloat16 add_round_down(const vfloat16& a, const vfloat16& b) { return _mm512_add_round_ps(a,b,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); }
- __forceinline vfloat16 add_round_up (const vfloat16& a, const vfloat16& b) { return _mm512_add_round_ps(a,b,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); }
-
- __forceinline vfloat16 sub_round_down(const vfloat16& a, const vfloat16& b) { return _mm512_sub_round_ps(a,b,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); }
- __forceinline vfloat16 sub_round_up (const vfloat16& a, const vfloat16& b) { return _mm512_sub_round_ps(a,b,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); }
-
- __forceinline vfloat16 div_round_down(const vfloat16& a, const vfloat16& b) { return _mm512_div_round_ps(a,b,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); }
- __forceinline vfloat16 div_round_up (const vfloat16& a, const vfloat16& b) { return _mm512_div_round_ps(a,b,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); }
-
- __forceinline vfloat16 mask_msub_round_down(const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_fmsub_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); }
- __forceinline vfloat16 mask_msub_round_up (const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_fmsub_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); }
-
- __forceinline vfloat16 mask_mul_round_down(const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_mul_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); }
- __forceinline vfloat16 mask_mul_round_up (const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_mul_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); }
-
- __forceinline vfloat16 mask_sub_round_down(const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_sub_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); }
- __forceinline vfloat16 mask_sub_round_up (const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_sub_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16& operator +=(vfloat16& a, const vfloat16& b) { return a = a + b; }
- __forceinline vfloat16& operator +=(vfloat16& a, float b) { return a = a + b; }
-
- __forceinline vfloat16& operator -=(vfloat16& a, const vfloat16& b) { return a = a - b; }
- __forceinline vfloat16& operator -=(vfloat16& a, float b) { return a = a - b; }
-
- __forceinline vfloat16& operator *=(vfloat16& a, const vfloat16& b) { return a = a * b; }
- __forceinline vfloat16& operator *=(vfloat16& a, float b) { return a = a * b; }
-
- __forceinline vfloat16& operator /=(vfloat16& a, const vfloat16& b) { return a = a / b; }
- __forceinline vfloat16& operator /=(vfloat16& a, float b) { return a = a / b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16 operator ==(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 operator ==(const vfloat16& a, float b) { return a == vfloat16(b); }
- __forceinline vboolf16 operator ==(float a, const vfloat16& b) { return vfloat16(a) == b; }
-
- __forceinline vboolf16 operator !=(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 operator !=(const vfloat16& a, float b) { return a != vfloat16(b); }
- __forceinline vboolf16 operator !=(float a, const vfloat16& b) { return vfloat16(a) != b; }
-
- __forceinline vboolf16 operator < (const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 operator < (const vfloat16& a, float b) { return a < vfloat16(b); }
- __forceinline vboolf16 operator < (float a, const vfloat16& b) { return vfloat16(a) < b; }
-
- __forceinline vboolf16 operator >=(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 operator >=(const vfloat16& a, float b) { return a >= vfloat16(b); }
- __forceinline vboolf16 operator >=(float a, const vfloat16& b) { return vfloat16(a) >= b; }
-
- __forceinline vboolf16 operator > (const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 operator > (const vfloat16& a, float b) { return a > vfloat16(b); }
- __forceinline vboolf16 operator > (float a, const vfloat16& b) { return vfloat16(a) > b; }
-
- __forceinline vboolf16 operator <=(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
- __forceinline vboolf16 operator <=(const vfloat16& a, float b) { return a <= vfloat16(b); }
- __forceinline vboolf16 operator <=(float a, const vfloat16& b) { return vfloat16(a) <= b; }
-
- __forceinline vboolf16 eq(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 ne(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 lt(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 ge(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 gt(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 le(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
-
- __forceinline vboolf16 eq(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 ne(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 lt(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 ge(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 gt(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 le(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LE); }
-
- __forceinline vfloat16 select(const vboolf16& s, const vfloat16& t, const vfloat16& f) {
- return _mm512_mask_blend_ps(s, f, t);
- }
-
- __forceinline vfloat16 lerp(const vfloat16& a, const vfloat16& b, const vfloat16& t) {
- return madd(t,b-a,a);
- }
-
- __forceinline void xchg(vboolf16 m, vfloat16& a, vfloat16& b)
- {
- vfloat16 c = a;
- a = select(m,b,a);
- b = select(m,c,b);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Rounding Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16 floor(const vfloat16& a) {
- return _mm512_floor_ps(a);
- }
- __forceinline vfloat16 ceil (const vfloat16& a) {
- return _mm512_ceil_ps(a);
- }
- __forceinline vfloat16 round (const vfloat16& a) {
- return _mm512_roundscale_ps(a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
- }
- __forceinline vint16 floori (const vfloat16& a) {
- return _mm512_cvt_roundps_epi32(a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16 unpacklo(const vfloat16& a, const vfloat16& b) { return _mm512_unpacklo_ps(a, b); }
- __forceinline vfloat16 unpackhi(const vfloat16& a, const vfloat16& b) { return _mm512_unpackhi_ps(a, b); }
-
- template<int i>
- __forceinline vfloat16 shuffle(const vfloat16& v) {
- return _mm512_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vfloat16 shuffle(const vfloat16& v) {
- return _mm512_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
- template<int i>
- __forceinline vfloat16 shuffle4(const vfloat16& v) {
- return _mm512_shuffle_f32x4(v, v ,_MM_SHUFFLE(i, i, i, i));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vfloat16 shuffle4(const vfloat16& v) {
- return _mm512_shuffle_f32x4(v, v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
- __forceinline vfloat16 interleave_even(const vfloat16& a, const vfloat16& b) {
- return _mm512_castsi512_ps(_mm512_mask_shuffle_epi32(_mm512_castps_si512(a), mm512_int2mask(0xaaaa), _mm512_castps_si512(b), (_MM_PERM_ENUM)0xb1));
- }
-
- __forceinline vfloat16 interleave_odd(const vfloat16& a, const vfloat16& b) {
- return _mm512_castsi512_ps(_mm512_mask_shuffle_epi32(_mm512_castps_si512(b), mm512_int2mask(0x5555), _mm512_castps_si512(a), (_MM_PERM_ENUM)0xb1));
- }
-
- __forceinline vfloat16 interleave2_even(const vfloat16& a, const vfloat16& b) {
- /* mask should be 8-bit but is 16-bit to reuse for interleave_even */
- return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(a), mm512_int2mask(0xaaaa), _mm512_castps_si512(b), (_MM_PERM_ENUM)0xb1));
- }
-
- __forceinline vfloat16 interleave2_odd(const vfloat16& a, const vfloat16& b) {
- /* mask should be 8-bit but is 16-bit to reuse for interleave_odd */
- return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(b), mm512_int2mask(0x5555), _mm512_castps_si512(a), (_MM_PERM_ENUM)0xb1));
- }
-
- __forceinline vfloat16 interleave4_even(const vfloat16& a, const vfloat16& b) {
- return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(a), mm512_int2mask(0xcc), _mm512_castps_si512(b), (_MM_PERM_ENUM)0x4e));
- }
-
- __forceinline vfloat16 interleave4_odd(const vfloat16& a, const vfloat16& b) {
- return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(b), mm512_int2mask(0x33), _mm512_castps_si512(a), (_MM_PERM_ENUM)0x4e));
- }
-
- __forceinline vfloat16 permute(vfloat16 v, __m512i index) {
- return _mm512_castsi512_ps(_mm512_permutexvar_epi32(index, _mm512_castps_si512(v)));
- }
-
- __forceinline vfloat16 reverse(const vfloat16& v) {
- return permute(v,_mm512_setr_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0));
- }
-
- template<int i>
- __forceinline vfloat16 align_shift_right(const vfloat16& a, const vfloat16& b) {
- return _mm512_castsi512_ps(_mm512_alignr_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b),i));
- };
-
- template<int i>
- __forceinline vfloat16 mask_align_shift_right(const vboolf16& mask, vfloat16& c, const vfloat16& a, const vfloat16& b) {
- return _mm512_castsi512_ps(_mm512_mask_alignr_epi32(_mm512_castps_si512(c),mask,_mm512_castps_si512(a),_mm512_castps_si512(b),i));
- };
-
- __forceinline vfloat16 shift_left_1(const vfloat16& a) {
- vfloat16 z = zero;
- return mask_align_shift_right<15>(0xfffe,z,a,a);
- }
-
- __forceinline vfloat16 shift_right_1(const vfloat16& x) {
- return align_shift_right<1>(zero,x);
- }
-
- __forceinline float toScalar(const vfloat16& v) { return mm512_cvtss_f32(v); }
-
-
- template<int i> __forceinline vfloat16 insert4(const vfloat16& a, const vfloat4& b) { return _mm512_insertf32x4(a, b, i); }
-
- template<int N, int i>
- vfloat<N> extractN(const vfloat16& v);
-
- template<> __forceinline vfloat4 extractN<4,0>(const vfloat16& v) { return _mm512_castps512_ps128(v); }
- template<> __forceinline vfloat4 extractN<4,1>(const vfloat16& v) { return _mm512_extractf32x4_ps(v, 1); }
- template<> __forceinline vfloat4 extractN<4,2>(const vfloat16& v) { return _mm512_extractf32x4_ps(v, 2); }
- template<> __forceinline vfloat4 extractN<4,3>(const vfloat16& v) { return _mm512_extractf32x4_ps(v, 3); }
-
- template<> __forceinline vfloat8 extractN<8,0>(const vfloat16& v) { return _mm512_castps512_ps256(v); }
- template<> __forceinline vfloat8 extractN<8,1>(const vfloat16& v) { return _mm512_extractf32x8_ps(v, 1); }
-
- template<int i> __forceinline vfloat4 extract4 (const vfloat16& v) { return _mm512_extractf32x4_ps(v, i); }
- template<> __forceinline vfloat4 extract4<0>(const vfloat16& v) { return _mm512_castps512_ps128(v); }
-
- template<int i> __forceinline vfloat8 extract8 (const vfloat16& v) { return _mm512_extractf32x8_ps(v, i); }
- template<> __forceinline vfloat8 extract8<0>(const vfloat16& v) { return _mm512_castps512_ps256(v); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Transpose
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline void transpose(const vfloat16& r0, const vfloat16& r1, const vfloat16& r2, const vfloat16& r3,
- vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3)
- {
-#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
- vfloat16 a0a1_c0c1 = interleave_even(r0, r1);
- vfloat16 a2a3_c2c3 = interleave_even(r2, r3);
- vfloat16 b0b1_d0d1 = interleave_odd (r0, r1);
- vfloat16 b2b3_d2d3 = interleave_odd (r2, r3);
-
- c0 = interleave2_even(a0a1_c0c1, a2a3_c2c3);
- c1 = interleave2_even(b0b1_d0d1, b2b3_d2d3);
- c2 = interleave2_odd (a0a1_c0c1, a2a3_c2c3);
- c3 = interleave2_odd (b0b1_d0d1, b2b3_d2d3);
-#else
- vfloat16 a0a2_b0b2 = unpacklo(r0, r2);
- vfloat16 c0c2_d0d2 = unpackhi(r0, r2);
- vfloat16 a1a3_b1b3 = unpacklo(r1, r3);
- vfloat16 c1c3_d1d3 = unpackhi(r1, r3);
-
- c0 = unpacklo(a0a2_b0b2, a1a3_b1b3);
- c1 = unpackhi(a0a2_b0b2, a1a3_b1b3);
- c2 = unpacklo(c0c2_d0d2, c1c3_d1d3);
- c3 = unpackhi(c0c2_d0d2, c1c3_d1d3);
-#endif
- }
-
- __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3,
- const vfloat4& r4, const vfloat4& r5, const vfloat4& r6, const vfloat4& r7,
- const vfloat4& r8, const vfloat4& r9, const vfloat4& r10, const vfloat4& r11,
- const vfloat4& r12, const vfloat4& r13, const vfloat4& r14, const vfloat4& r15,
- vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3)
- {
- return transpose(vfloat16(r0, r4, r8, r12), vfloat16(r1, r5, r9, r13), vfloat16(r2, r6, r10, r14), vfloat16(r3, r7, r11, r15),
- c0, c1, c2, c3);
- }
-
- __forceinline void transpose(const vfloat16& r0, const vfloat16& r1, const vfloat16& r2, const vfloat16& r3,
- const vfloat16& r4, const vfloat16& r5, const vfloat16& r6, const vfloat16& r7,
- vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3,
- vfloat16& c4, vfloat16& c5, vfloat16& c6, vfloat16& c7)
- {
- vfloat16 a0a1a2a3_e0e1e2e3, b0b1b2b3_f0f1f2f3, c0c1c2c3_g0g1g2g3, d0d1d2d3_h0h1h2h3;
- transpose(r0, r1, r2, r3, a0a1a2a3_e0e1e2e3, b0b1b2b3_f0f1f2f3, c0c1c2c3_g0g1g2g3, d0d1d2d3_h0h1h2h3);
-
- vfloat16 a4a5a6a7_e4e5e6e7, b4b5b6b7_f4f5f6f7, c4c5c6c7_g4g5g6g7, d4d5d6d7_h4h5h6h7;
- transpose(r4, r5, r6, r7, a4a5a6a7_e4e5e6e7, b4b5b6b7_f4f5f6f7, c4c5c6c7_g4g5g6g7, d4d5d6d7_h4h5h6h7);
-
- c0 = interleave4_even(a0a1a2a3_e0e1e2e3, a4a5a6a7_e4e5e6e7);
- c1 = interleave4_even(b0b1b2b3_f0f1f2f3, b4b5b6b7_f4f5f6f7);
- c2 = interleave4_even(c0c1c2c3_g0g1g2g3, c4c5c6c7_g4g5g6g7);
- c3 = interleave4_even(d0d1d2d3_h0h1h2h3, d4d5d6d7_h4h5h6h7);
- c4 = interleave4_odd (a0a1a2a3_e0e1e2e3, a4a5a6a7_e4e5e6e7);
- c5 = interleave4_odd (b0b1b2b3_f0f1f2f3, b4b5b6b7_f4f5f6f7);
- c6 = interleave4_odd (c0c1c2c3_g0g1g2g3, c4c5c6c7_g4g5g6g7);
- c7 = interleave4_odd (d0d1d2d3_h0h1h2h3, d4d5d6d7_h4h5h6h7);
- }
-
- __forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3,
- const vfloat8& r4, const vfloat8& r5, const vfloat8& r6, const vfloat8& r7,
- const vfloat8& r8, const vfloat8& r9, const vfloat8& r10, const vfloat8& r11,
- const vfloat8& r12, const vfloat8& r13, const vfloat8& r14, const vfloat8& r15,
- vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3,
- vfloat16& c4, vfloat16& c5, vfloat16& c6, vfloat16& c7)
- {
- return transpose(vfloat16(r0, r8), vfloat16(r1, r9), vfloat16(r2, r10), vfloat16(r3, r11),
- vfloat16(r4, r12), vfloat16(r5, r13), vfloat16(r6, r14), vfloat16(r7, r15),
- c0, c1, c2, c3, c4, c5, c6, c7);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16 vreduce_add2(vfloat16 x) { return x + shuffle<1,0,3,2>(x); }
- __forceinline vfloat16 vreduce_add4(vfloat16 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
- __forceinline vfloat16 vreduce_add8(vfloat16 x) { x = vreduce_add4(x); return x + shuffle4<1,0,3,2>(x); }
- __forceinline vfloat16 vreduce_add (vfloat16 x) { x = vreduce_add8(x); return x + shuffle4<2,3,0,1>(x); }
-
- __forceinline vfloat16 vreduce_min2(vfloat16 x) { return min(x, shuffle<1,0,3,2>(x)); }
- __forceinline vfloat16 vreduce_min4(vfloat16 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
- __forceinline vfloat16 vreduce_min8(vfloat16 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0,3,2>(x)); }
- __forceinline vfloat16 vreduce_min (vfloat16 x) { x = vreduce_min8(x); return min(x, shuffle4<2,3,0,1>(x)); }
-
- __forceinline vfloat16 vreduce_max2(vfloat16 x) { return max(x, shuffle<1,0,3,2>(x)); }
- __forceinline vfloat16 vreduce_max4(vfloat16 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
- __forceinline vfloat16 vreduce_max8(vfloat16 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0,3,2>(x)); }
- __forceinline vfloat16 vreduce_max (vfloat16 x) { x = vreduce_max8(x); return max(x, shuffle4<2,3,0,1>(x)); }
-
- __forceinline float reduce_add(const vfloat16& v) { return toScalar(vreduce_add(v)); }
- __forceinline float reduce_min(const vfloat16& v) { return toScalar(vreduce_min(v)); }
- __forceinline float reduce_max(const vfloat16& v) { return toScalar(vreduce_max(v)); }
-
- __forceinline size_t select_min(const vfloat16& v) {
- return bsf(_mm512_kmov(_mm512_cmp_epi32_mask(_mm512_castps_si512(v),_mm512_castps_si512(vreduce_min(v)),_MM_CMPINT_EQ)));
- }
-
- __forceinline size_t select_max(const vfloat16& v) {
- return bsf(_mm512_kmov(_mm512_cmp_epi32_mask(_mm512_castps_si512(v),_mm512_castps_si512(vreduce_max(v)),_MM_CMPINT_EQ)));
- }
-
- __forceinline size_t select_min(const vboolf16& valid, const vfloat16& v)
- {
- const vfloat16 a = select(valid,v,vfloat16(pos_inf));
- const vbool16 valid_min = valid & (a == vreduce_min(a));
- return bsf(movemask(any(valid_min) ? valid_min : valid));
- }
-
- __forceinline size_t select_max(const vboolf16& valid, const vfloat16& v)
- {
- const vfloat16 a = select(valid,v,vfloat16(neg_inf));
- const vbool16 valid_max = valid & (a == vreduce_max(a));
- return bsf(movemask(any(valid_max) ? valid_max : valid));
- }
-
- __forceinline vfloat16 prefix_sum(const vfloat16& a)
- {
- const vfloat16 z(zero);
- vfloat16 v = a;
- v = v + align_shift_right<16-1>(v,z);
- v = v + align_shift_right<16-2>(v,z);
- v = v + align_shift_right<16-4>(v,z);
- v = v + align_shift_right<16-8>(v,z);
- return v;
- }
-
- __forceinline vfloat16 reverse_prefix_sum(const vfloat16& a)
- {
- const vfloat16 z(zero);
- vfloat16 v = a;
- v = v + align_shift_right<1>(z,v);
- v = v + align_shift_right<2>(z,v);
- v = v + align_shift_right<4>(z,v);
- v = v + align_shift_right<8>(z,v);
- return v;
- }
-
- __forceinline vfloat16 prefix_min(const vfloat16& a)
- {
- const vfloat16 z(pos_inf);
- vfloat16 v = a;
- v = min(v,align_shift_right<16-1>(v,z));
- v = min(v,align_shift_right<16-2>(v,z));
- v = min(v,align_shift_right<16-4>(v,z));
- v = min(v,align_shift_right<16-8>(v,z));
- return v;
- }
-
- __forceinline vfloat16 prefix_max(const vfloat16& a)
- {
- const vfloat16 z(neg_inf);
- vfloat16 v = a;
- v = max(v,align_shift_right<16-1>(v,z));
- v = max(v,align_shift_right<16-2>(v,z));
- v = max(v,align_shift_right<16-4>(v,z));
- v = max(v,align_shift_right<16-8>(v,z));
- return v;
- }
-
-
- __forceinline vfloat16 reverse_prefix_min(const vfloat16& a)
- {
- const vfloat16 z(pos_inf);
- vfloat16 v = a;
- v = min(v,align_shift_right<1>(z,v));
- v = min(v,align_shift_right<2>(z,v));
- v = min(v,align_shift_right<4>(z,v));
- v = min(v,align_shift_right<8>(z,v));
- return v;
- }
-
- __forceinline vfloat16 reverse_prefix_max(const vfloat16& a)
- {
- const vfloat16 z(neg_inf);
- vfloat16 v = a;
- v = max(v,align_shift_right<1>(z,v));
- v = max(v,align_shift_right<2>(z,v));
- v = max(v,align_shift_right<4>(z,v));
- v = max(v,align_shift_right<8>(z,v));
- return v;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Memory load and store operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat16 loadAOS4to16f(const float& x, const float& y, const float& z)
- {
- vfloat16 f = zero;
- f = select(0x1111,vfloat16::broadcast(&x),f);
- f = select(0x2222,vfloat16::broadcast(&y),f);
- f = select(0x4444,vfloat16::broadcast(&z),f);
- return f;
- }
-
- __forceinline vfloat16 loadAOS4to16f(unsigned int index,
- const vfloat16& x,
- const vfloat16& y,
- const vfloat16& z)
- {
- vfloat16 f = zero;
- f = select(0x1111,vfloat16::broadcast((float*)&x + index),f);
- f = select(0x2222,vfloat16::broadcast((float*)&y + index),f);
- f = select(0x4444,vfloat16::broadcast((float*)&z + index),f);
- return f;
- }
-
- __forceinline vfloat16 loadAOS4to16f(unsigned int index,
- const vfloat16& x,
- const vfloat16& y,
- const vfloat16& z,
- const vfloat16& fill)
- {
- vfloat16 f = fill;
- f = select(0x1111,vfloat16::broadcast((float*)&x + index),f);
- f = select(0x2222,vfloat16::broadcast((float*)&y + index),f);
- f = select(0x4444,vfloat16::broadcast((float*)&z + index),f);
- return f;
- }
-
- __forceinline vfloat16 rcp_safe(const vfloat16& a) {
- return rcp(select(a != vfloat16(zero), a, vfloat16(min_rcp_input)));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vfloat16& v)
- {
- cout << "<" << v[0];
- for (int i=1; i<16; i++) cout << ", " << v[i];
- cout << ">";
- return cout;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vfloat4_sse2.h b/thirdparty/embree-aarch64/common/simd/vfloat4_sse2.h
deleted file mode 100644
index 5732c0fbc8..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vfloat4_sse2.h
+++ /dev/null
@@ -1,925 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 4-wide SSE float type */
- template<>
- struct vfloat<4>
- {
- ALIGNED_STRUCT_(16);
-
- typedef vboolf4 Bool;
- typedef vint4 Int;
- typedef vfloat4 Float;
-
- enum { size = 4 }; // number of SIMD elements
- union { __m128 v; float f[4]; int i[4]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat() {}
- __forceinline vfloat(const vfloat4& other) { v = other.v; }
- __forceinline vfloat4& operator =(const vfloat4& other) { v = other.v; return *this; }
-
- __forceinline vfloat(__m128 a) : v(a) {}
- __forceinline operator const __m128&() const { return v; }
- __forceinline operator __m128&() { return v; }
-
- __forceinline vfloat(float a) : v(_mm_set1_ps(a)) {}
- __forceinline vfloat(float a, float b, float c, float d) : v(_mm_set_ps(d, c, b, a)) {}
-
- __forceinline explicit vfloat(const vint4& a) : v(_mm_cvtepi32_ps(a)) {}
-#if defined(__aarch64__)
- __forceinline explicit vfloat(const vuint4& x) {
- v = vcvtq_f32_u32(vreinterpretq_u32_s32(x.v));
- }
-#else
- __forceinline explicit vfloat(const vuint4& x) {
- const __m128i a = _mm_and_si128(x,_mm_set1_epi32(0x7FFFFFFF));
- const __m128i b = _mm_and_si128(_mm_srai_epi32(x,31),_mm_set1_epi32(0x4F000000)); //0x4F000000 = 2^31
- const __m128 af = _mm_cvtepi32_ps(a);
- const __m128 bf = _mm_castsi128_ps(b);
- v = _mm_add_ps(af,bf);
- }
-#endif
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat(ZeroTy) : v(_mm_setzero_ps()) {}
- __forceinline vfloat(OneTy) : v(_mm_set1_ps(1.0f)) {}
- __forceinline vfloat(PosInfTy) : v(_mm_set1_ps(pos_inf)) {}
- __forceinline vfloat(NegInfTy) : v(_mm_set1_ps(neg_inf)) {}
- __forceinline vfloat(StepTy) : v(_mm_set_ps(3.0f, 2.0f, 1.0f, 0.0f)) {}
- __forceinline vfloat(NaNTy) : v(_mm_set1_ps(nan)) {}
- __forceinline vfloat(UndefinedTy) : v(_mm_undefined_ps()) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vfloat4 load (const void* a) { return _mm_load_ps((float*)a); }
- static __forceinline vfloat4 loadu(const void* a) { return _mm_loadu_ps((float*)a); }
-
- static __forceinline void store (void* ptr, const vfloat4& v) { _mm_store_ps((float*)ptr,v); }
- static __forceinline void storeu(void* ptr, const vfloat4& v) { _mm_storeu_ps((float*)ptr,v); }
-
-#if defined(__AVX512VL__)
-
- static __forceinline vfloat4 compact(const vboolf4& mask, vfloat4 &v) {
- return _mm_mask_compress_ps(v, mask, v);
- }
- static __forceinline vfloat4 compact(const vboolf4& mask, vfloat4 &a, const vfloat4& b) {
- return _mm_mask_compress_ps(a, mask, b);
- }
-
- static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return _mm_mask_load_ps (_mm_setzero_ps(),mask,(float*)ptr); }
- static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return _mm_mask_loadu_ps(_mm_setzero_ps(),mask,(float*)ptr); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vfloat4& v) { _mm_mask_store_ps ((float*)ptr,mask,v); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vfloat4& v) { _mm_mask_storeu_ps((float*)ptr,mask,v); }
-#elif defined(__AVX__)
- static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return _mm_maskload_ps((float*)ptr,mask); }
- static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return _mm_maskload_ps((float*)ptr,mask); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vfloat4& v) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,v); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vfloat4& v) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,v); }
-#else
- static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return _mm_and_ps(_mm_load_ps ((float*)ptr),mask); }
- static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return _mm_and_ps(_mm_loadu_ps((float*)ptr),mask); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vfloat4& v) { store (ptr,select(mask,v,load (ptr))); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vfloat4& v) { storeu(ptr,select(mask,v,loadu(ptr))); }
-#endif
-
-#if defined(__AVX__)
- static __forceinline vfloat4 broadcast(const void* a) { return _mm_broadcast_ss((float*)a); }
-#else
- static __forceinline vfloat4 broadcast(const void* a) { return _mm_set1_ps(*(float*)a); }
-#endif
-
- static __forceinline vfloat4 load_nt (const float* ptr) {
-#if defined (__SSE4_1__)
- return _mm_castsi128_ps(_mm_stream_load_si128((__m128i*)ptr));
-#else
- return _mm_load_ps(ptr);
-#endif
- }
-
-#if defined(__aarch64__)
- static __forceinline vfloat4 load(const int8_t* ptr) {
- return __m128(_mm_load4epi8_f32(((__m128i*)ptr)));
- }
-#elif defined(__SSE4_1__)
- static __forceinline vfloat4 load(const int8_t* ptr) {
- return _mm_cvtepi32_ps(_mm_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr)));
- }
-#else
- static __forceinline vfloat4 load(const int8_t* ptr) {
- return vfloat4(ptr[0],ptr[1],ptr[2],ptr[3]);
- }
-#endif
-
-#if defined(__aarch64__)
- static __forceinline vfloat4 load(const uint8_t* ptr) {
- return __m128(_mm_load4epu8_f32(((__m128i*)ptr)));
- }
-#elif defined(__SSE4_1__)
- static __forceinline vfloat4 load(const uint8_t* ptr) {
- return _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
- }
-#else
- static __forceinline vfloat4 load(const uint8_t* ptr) {
- //return _mm_cvtpu8_ps(*(__m64*)ptr); // don't enable, will use MMX instructions
- return vfloat4(ptr[0],ptr[1],ptr[2],ptr[3]);
- }
-#endif
-
-#if defined(__aarch64__)
- static __forceinline vfloat4 load(const short* ptr) {
- return __m128(_mm_load4epi16_f32(((__m128i*)ptr)));
- }
-#elif defined(__SSE4_1__)
- static __forceinline vfloat4 load(const short* ptr) {
- return _mm_cvtepi32_ps(_mm_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr)));
- }
-#else
- static __forceinline vfloat4 load(const short* ptr) {
- return vfloat4(ptr[0],ptr[1],ptr[2],ptr[3]);
- }
-#endif
-
- static __forceinline vfloat4 load(const unsigned short* ptr) {
- return _mm_mul_ps(vfloat4(vint4::load(ptr)),vfloat4(1.0f/65535.0f));
- }
-
- static __forceinline void store_nt(void* ptr, const vfloat4& v)
- {
-#if defined (__SSE4_1__)
-#if defined(__aarch64__)
- _mm_stream_ps((float*)ptr,vreinterpretq_s32_f32(v.v));
-#else
- _mm_stream_ps((float*)ptr,v);
-#endif
-#else
- _mm_store_ps((float*)ptr,v);
-#endif
- }
-
- template<int scale = 4>
- static __forceinline vfloat4 gather(const float* ptr, const vint4& index) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return _mm_i32gather_ps(ptr, index, scale);
-#else
- return vfloat4(
- *(float*)(((int8_t*)ptr)+scale*index[0]),
- *(float*)(((int8_t*)ptr)+scale*index[1]),
- *(float*)(((int8_t*)ptr)+scale*index[2]),
- *(float*)(((int8_t*)ptr)+scale*index[3]));
-#endif
- }
-
- template<int scale = 4>
- static __forceinline vfloat4 gather(const vboolf4& mask, const float* ptr, const vint4& index) {
- vfloat4 r = zero;
-#if defined(__AVX512VL__)
- return _mm_mmask_i32gather_ps(r, mask, index, ptr, scale);
-#elif defined(__AVX2__) && !defined(__aarch64__)
- return _mm_mask_i32gather_ps(r, ptr, index, mask, scale);
-#else
- if (likely(mask[0])) r[0] = *(float*)(((int8_t*)ptr)+scale*index[0]);
- if (likely(mask[1])) r[1] = *(float*)(((int8_t*)ptr)+scale*index[1]);
- if (likely(mask[2])) r[2] = *(float*)(((int8_t*)ptr)+scale*index[2]);
- if (likely(mask[3])) r[3] = *(float*)(((int8_t*)ptr)+scale*index[3]);
- return r;
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(void* ptr, const vint4& index, const vfloat4& v)
- {
-#if defined(__AVX512VL__)
- _mm_i32scatter_ps((float*)ptr, index, v, scale);
-#else
- *(float*)(((int8_t*)ptr)+scale*index[0]) = v[0];
- *(float*)(((int8_t*)ptr)+scale*index[1]) = v[1];
- *(float*)(((int8_t*)ptr)+scale*index[2]) = v[2];
- *(float*)(((int8_t*)ptr)+scale*index[3]) = v[3];
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf4& mask, void* ptr, const vint4& index, const vfloat4& v)
- {
-#if defined(__AVX512VL__)
- _mm_mask_i32scatter_ps((float*)ptr ,mask, index, v, scale);
-#else
- if (likely(mask[0])) *(float*)(((int8_t*)ptr)+scale*index[0]) = v[0];
- if (likely(mask[1])) *(float*)(((int8_t*)ptr)+scale*index[1]) = v[1];
- if (likely(mask[2])) *(float*)(((int8_t*)ptr)+scale*index[2]) = v[2];
- if (likely(mask[3])) *(float*)(((int8_t*)ptr)+scale*index[3]) = v[3];
-#endif
- }
-
- static __forceinline void store(const vboolf4& mask, int8_t* ptr, const vint4& ofs, const vfloat4& v) {
- scatter<1>(mask,ptr,ofs,v);
- }
- static __forceinline void store(const vboolf4& mask, float* ptr, const vint4& ofs, const vfloat4& v) {
- scatter<4>(mask,ptr,ofs,v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const float& operator [](size_t index) const { assert(index < 4); return f[index]; }
- __forceinline float& operator [](size_t index) { assert(index < 4); return f[index]; }
-
- friend __forceinline vfloat4 select(const vboolf4& m, const vfloat4& t, const vfloat4& f) {
-#if defined(__AVX512VL__)
- return _mm_mask_blend_ps(m, f, t);
-#elif defined(__SSE4_1__) || (defined(__aarch64__))
- return _mm_blendv_ps(f, t, m);
-#else
- return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
-#endif
- }
- };
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat4 asFloat(const vint4& a) { return _mm_castsi128_ps(a); }
- __forceinline vint4 asInt (const vfloat4& a) { return _mm_castps_si128(a); }
- __forceinline vuint4 asUInt (const vfloat4& a) { return _mm_castps_si128(a); }
-
- __forceinline vint4 toInt (const vfloat4& a) { return vint4(a); }
- __forceinline vfloat4 toFloat(const vint4& a) { return vfloat4(a); }
-
- __forceinline vfloat4 operator +(const vfloat4& a) { return a; }
-#if defined(__aarch64__)
- __forceinline vfloat4 operator -(const vfloat4& a) {
- return vnegq_f32(a);
- }
-#else
- __forceinline vfloat4 operator -(const vfloat4& a) { return _mm_xor_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
-#endif
-
-#if defined(__aarch64__)
- __forceinline vfloat4 abs(const vfloat4& a) { return _mm_abs_ps(a); }
-#else
- __forceinline vfloat4 abs(const vfloat4& a) { return _mm_and_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); }
-#endif
-
-#if defined(__AVX512VL__)
- __forceinline vfloat4 sign(const vfloat4& a) { return _mm_mask_blend_ps(_mm_cmp_ps_mask(a, vfloat4(zero), _CMP_LT_OQ), vfloat4(one), -vfloat4(one)); }
-#else
- __forceinline vfloat4 sign(const vfloat4& a) { return blendv_ps(vfloat4(one), -vfloat4(one), _mm_cmplt_ps(a, vfloat4(zero))); }
-#endif
-
-#if defined(__aarch64__)
- __forceinline vfloat4 signmsk(const vfloat4& a) { return _mm_and_ps(a, vreinterpretq_f32_u32(v0x80000000)); }
-#else
- __forceinline vfloat4 signmsk(const vfloat4& a) { return _mm_and_ps(a,_mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
-#endif
-
- __forceinline vfloat4 rcp(const vfloat4& a)
- {
-#if defined(__aarch64__)
-#if defined(BUILD_IOS)
- return vfloat4(vdivq_f32(vdupq_n_f32(1.0f),a.v));
-#else //BUILD_IOS
- __m128 reciprocal = _mm_rcp_ps(a);
- reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal);
- reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal);
- // +1 round since NEON's reciprocal estimate instruction has less accuracy than SSE2's rcp.
- reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal);
- return (const vfloat4)reciprocal;
-#endif // BUILD_IOS
-#else
-
-#if defined(__AVX512VL__)
- const vfloat4 r = _mm_rcp14_ps(a);
-#else
- const vfloat4 r = _mm_rcp_ps(a);
-#endif
-
-#if defined(__AVX2__)
- return _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f)));
-#else
- return _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a)));
-#endif
-
-#endif //defined(__aarch64__)
- }
- __forceinline vfloat4 sqr (const vfloat4& a) { return _mm_mul_ps(a,a); }
- __forceinline vfloat4 sqrt(const vfloat4& a) { return _mm_sqrt_ps(a); }
-
- __forceinline vfloat4 rsqrt(const vfloat4& a)
- {
-#if defined(__aarch64__)
- vfloat4 r = _mm_rsqrt_ps(a);
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r));
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r));
- r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r));
- return r;
-#else
-
-#if defined(__AVX512VL__)
- const vfloat4 r = _mm_rsqrt14_ps(a);
-#else
- const vfloat4 r = _mm_rsqrt_ps(a);
-#endif
-
-#if defined(__AVX2__)
- return _mm_fmadd_ps(_mm_set1_ps(1.5f), r,
- _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
-#else
- return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f), r),
- _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
-#endif
-
-#endif
- }
-
- __forceinline vboolf4 isnan(const vfloat4& a) {
-#if defined(__aarch64__)
- const vfloat4 b = _mm_and_ps(a, vreinterpretq_f32_u32(v0x7fffffff));
-#else
- const vfloat4 b = _mm_and_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)));
-#endif
-#if defined(__AVX512VL__)
- return _mm_cmp_epi32_mask(_mm_castps_si128(b), _mm_set1_epi32(0x7f800000), _MM_CMPINT_GT);
-#else
- return _mm_castsi128_ps(_mm_cmpgt_epi32(_mm_castps_si128(b), _mm_set1_epi32(0x7f800000)));
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat4 operator +(const vfloat4& a, const vfloat4& b) { return _mm_add_ps(a, b); }
- __forceinline vfloat4 operator +(const vfloat4& a, float b) { return a + vfloat4(b); }
- __forceinline vfloat4 operator +(float a, const vfloat4& b) { return vfloat4(a) + b; }
-
- __forceinline vfloat4 operator -(const vfloat4& a, const vfloat4& b) { return _mm_sub_ps(a, b); }
- __forceinline vfloat4 operator -(const vfloat4& a, float b) { return a - vfloat4(b); }
- __forceinline vfloat4 operator -(float a, const vfloat4& b) { return vfloat4(a) - b; }
-
- __forceinline vfloat4 operator *(const vfloat4& a, const vfloat4& b) { return _mm_mul_ps(a, b); }
- __forceinline vfloat4 operator *(const vfloat4& a, float b) { return a * vfloat4(b); }
- __forceinline vfloat4 operator *(float a, const vfloat4& b) { return vfloat4(a) * b; }
-
- __forceinline vfloat4 operator /(const vfloat4& a, const vfloat4& b) { return _mm_div_ps(a,b); }
- __forceinline vfloat4 operator /(const vfloat4& a, float b) { return a/vfloat4(b); }
- __forceinline vfloat4 operator /(float a, const vfloat4& b) { return vfloat4(a)/b; }
-
- __forceinline vfloat4 operator &(const vfloat4& a, const vfloat4& b) { return _mm_and_ps(a,b); }
- __forceinline vfloat4 operator |(const vfloat4& a, const vfloat4& b) { return _mm_or_ps(a,b); }
- __forceinline vfloat4 operator ^(const vfloat4& a, const vfloat4& b) { return _mm_xor_ps(a,b); }
- __forceinline vfloat4 operator ^(const vfloat4& a, const vint4& b) { return _mm_xor_ps(a,_mm_castsi128_ps(b)); }
-
- __forceinline vfloat4 min(const vfloat4& a, const vfloat4& b) { return _mm_min_ps(a,b); }
- __forceinline vfloat4 min(const vfloat4& a, float b) { return _mm_min_ps(a,vfloat4(b)); }
- __forceinline vfloat4 min(float a, const vfloat4& b) { return _mm_min_ps(vfloat4(a),b); }
-
- __forceinline vfloat4 max(const vfloat4& a, const vfloat4& b) { return _mm_max_ps(a,b); }
- __forceinline vfloat4 max(const vfloat4& a, float b) { return _mm_max_ps(a,vfloat4(b)); }
- __forceinline vfloat4 max(float a, const vfloat4& b) { return _mm_max_ps(vfloat4(a),b); }
-
-#if defined(__SSE4_1__) || defined(__aarch64__)
-
- __forceinline vfloat4 mini(const vfloat4& a, const vfloat4& b) {
- const vint4 ai = _mm_castps_si128(a);
- const vint4 bi = _mm_castps_si128(b);
- const vint4 ci = _mm_min_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-
- __forceinline vfloat4 maxi(const vfloat4& a, const vfloat4& b) {
- const vint4 ai = _mm_castps_si128(a);
- const vint4 bi = _mm_castps_si128(b);
- const vint4 ci = _mm_max_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-
- __forceinline vfloat4 minui(const vfloat4& a, const vfloat4& b) {
- const vint4 ai = _mm_castps_si128(a);
- const vint4 bi = _mm_castps_si128(b);
- const vint4 ci = _mm_min_epu32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-
- __forceinline vfloat4 maxui(const vfloat4& a, const vfloat4& b) {
- const vint4 ai = _mm_castps_si128(a);
- const vint4 bi = _mm_castps_si128(b);
- const vint4 ci = _mm_max_epu32(ai,bi);
- return _mm_castsi128_ps(ci);
- }
-#else
- __forceinline vfloat4 mini(const vfloat4& a, const vfloat4& b) {
- return min(a,b);
- }
-
- __forceinline vfloat4 maxi(const vfloat4& a, const vfloat4& b) {
- return max(a,b);
- }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX2__)
- __forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fmadd_ps(a,b,c); }
- __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fmsub_ps(a,b,c); }
- __forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmadd_ps(a,b,c); }
- __forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmsub_ps(a,b,c); }
-#else
-
-#if defined(__aarch64__)
- __forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) {
- return _mm_madd_ps(a, b, c); //a*b+c;
- }
- __forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) {
- return _mm_msub_ps(a, b, c); //-a*b+c;
- }
- __forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) {
- return vnegq_f32(vfmaq_f32(c,a, b));
- }
-#else
- __forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b+c; }
- __forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return -a*b+c;}
- __forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return -a*b-c; }
-#endif
- __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b-c; }
-
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat4& operator +=(vfloat4& a, const vfloat4& b) { return a = a + b; }
- __forceinline vfloat4& operator +=(vfloat4& a, float b) { return a = a + b; }
-
- __forceinline vfloat4& operator -=(vfloat4& a, const vfloat4& b) { return a = a - b; }
- __forceinline vfloat4& operator -=(vfloat4& a, float b) { return a = a - b; }
-
- __forceinline vfloat4& operator *=(vfloat4& a, const vfloat4& b) { return a = a * b; }
- __forceinline vfloat4& operator *=(vfloat4& a, float b) { return a = a * b; }
-
- __forceinline vfloat4& operator /=(vfloat4& a, const vfloat4& b) { return a = a / b; }
- __forceinline vfloat4& operator /=(vfloat4& a, float b) { return a = a / b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboolf4 operator ==(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_EQ); }
- __forceinline vboolf4 operator !=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_NE); }
- __forceinline vboolf4 operator < (const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_LT); }
- __forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_GE); }
- __forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_GT); }
- __forceinline vboolf4 operator <=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_LE); }
-#else
- __forceinline vboolf4 operator ==(const vfloat4& a, const vfloat4& b) { return _mm_cmpeq_ps (a, b); }
- __forceinline vboolf4 operator !=(const vfloat4& a, const vfloat4& b) { return _mm_cmpneq_ps(a, b); }
- __forceinline vboolf4 operator < (const vfloat4& a, const vfloat4& b) { return _mm_cmplt_ps (a, b); }
-#if defined(__aarch64__)
- __forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmpge_ps (a, b); }
- __forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmpgt_ps (a, b); }
-#else
- __forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmpnlt_ps(a, b); }
- __forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmpnle_ps(a, b); }
-#endif
- __forceinline vboolf4 operator <=(const vfloat4& a, const vfloat4& b) { return _mm_cmple_ps (a, b); }
-#endif
-
- __forceinline vboolf4 operator ==(const vfloat4& a, float b) { return a == vfloat4(b); }
- __forceinline vboolf4 operator ==(float a, const vfloat4& b) { return vfloat4(a) == b; }
-
- __forceinline vboolf4 operator !=(const vfloat4& a, float b) { return a != vfloat4(b); }
- __forceinline vboolf4 operator !=(float a, const vfloat4& b) { return vfloat4(a) != b; }
-
- __forceinline vboolf4 operator < (const vfloat4& a, float b) { return a < vfloat4(b); }
- __forceinline vboolf4 operator < (float a, const vfloat4& b) { return vfloat4(a) < b; }
-
- __forceinline vboolf4 operator >=(const vfloat4& a, float b) { return a >= vfloat4(b); }
- __forceinline vboolf4 operator >=(float a, const vfloat4& b) { return vfloat4(a) >= b; }
-
- __forceinline vboolf4 operator > (const vfloat4& a, float b) { return a > vfloat4(b); }
- __forceinline vboolf4 operator > (float a, const vfloat4& b) { return vfloat4(a) > b; }
-
- __forceinline vboolf4 operator <=(const vfloat4& a, float b) { return a <= vfloat4(b); }
- __forceinline vboolf4 operator <=(float a, const vfloat4& b) { return vfloat4(a) <= b; }
-
- __forceinline vboolf4 eq(const vfloat4& a, const vfloat4& b) { return a == b; }
- __forceinline vboolf4 ne(const vfloat4& a, const vfloat4& b) { return a != b; }
- __forceinline vboolf4 lt(const vfloat4& a, const vfloat4& b) { return a < b; }
- __forceinline vboolf4 ge(const vfloat4& a, const vfloat4& b) { return a >= b; }
- __forceinline vboolf4 gt(const vfloat4& a, const vfloat4& b) { return a > b; }
- __forceinline vboolf4 le(const vfloat4& a, const vfloat4& b) { return a <= b; }
-
-#if defined(__AVX512VL__)
- __forceinline vboolf4 eq(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); }
- __forceinline vboolf4 ne(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); }
- __forceinline vboolf4 lt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); }
- __forceinline vboolf4 ge(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); }
- __forceinline vboolf4 gt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); }
- __forceinline vboolf4 le(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); }
-#else
- __forceinline vboolf4 eq(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a == b); }
- __forceinline vboolf4 ne(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a != b); }
- __forceinline vboolf4 lt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a < b); }
- __forceinline vboolf4 ge(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a >= b); }
- __forceinline vboolf4 gt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a > b); }
- __forceinline vboolf4 le(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a <= b); }
-#endif
-
- template<int mask>
- __forceinline vfloat4 select(const vfloat4& t, const vfloat4& f)
- {
-#if defined(__SSE4_1__)
- return _mm_blend_ps(f, t, mask);
-#else
- return select(vboolf4(mask), t, f);
-#endif
- }
-
-#if defined(__aarch64__)
- template<> __forceinline vfloat4 select<0>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vzero));
- }
- template<> __forceinline vfloat4 select<1>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(v000F));
- }
- template<> __forceinline vfloat4 select<2>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(v00F0));
- }
- template<> __forceinline vfloat4 select<3>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(v00FF));
- }
- template<> __forceinline vfloat4 select<4>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(v0F00));
- }
- template<> __forceinline vfloat4 select<5>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(v0F0F));
- }
- template<> __forceinline vfloat4 select<6>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(v0FF0));
- }
- template<> __forceinline vfloat4 select<7>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(v0FFF));
- }
- template<> __forceinline vfloat4 select<8>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vF000));
- }
- template<> __forceinline vfloat4 select<9>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vF00F));
- }
- template<> __forceinline vfloat4 select<10>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vF0F0));
- }
- template<> __forceinline vfloat4 select<11>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vF0FF));
- }
- template<> __forceinline vfloat4 select<12>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vFF00));
- }
- template<> __forceinline vfloat4 select<13>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vFF0F));
- }
- template<> __forceinline vfloat4 select<14>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vFFF0));
- }
- template<> __forceinline vfloat4 select<15>(const vfloat4& t, const vfloat4& f) {
- return _mm_blendv_ps(f, t, vreinterpretq_f32_u32(vFFFF));
- }
-#endif
-
- __forceinline vfloat4 lerp(const vfloat4& a, const vfloat4& b, const vfloat4& t) {
- return madd(t,b-a,a);
- }
-
- __forceinline bool isvalid(const vfloat4& v) {
- return all((v > vfloat4(-FLT_LARGE)) & (v < vfloat4(+FLT_LARGE)));
- }
-
- __forceinline bool is_finite(const vfloat4& a) {
- return all((a >= vfloat4(-FLT_MAX)) & (a <= vfloat4(+FLT_MAX)));
- }
-
- __forceinline bool is_finite(const vboolf4& valid, const vfloat4& a) {
- return all(valid, (a >= vfloat4(-FLT_MAX)) & (a <= vfloat4(+FLT_MAX)));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Rounding Functions
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__aarch64__)
- __forceinline vfloat4 floor(const vfloat4& a) { return vrndmq_f32(a.v); } // towards -inf
- __forceinline vfloat4 ceil (const vfloat4& a) { return vrndpq_f32(a.v); } // toward +inf
- __forceinline vfloat4 trunc(const vfloat4& a) { return vrndq_f32(a.v); } // towards 0
- __forceinline vfloat4 round(const vfloat4& a) { return vrndnq_f32(a.v); } // to nearest, ties to even. NOTE(LTE): arm clang uses vrndnq, old gcc uses vrndqn?
-#elif defined (__SSE4_1__)
- __forceinline vfloat4 floor(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
- __forceinline vfloat4 ceil (const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
- __forceinline vfloat4 trunc(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_ZERO ); }
- __forceinline vfloat4 round(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); } // (even) https://www.felixcloutier.com/x86/roundpd
-#else
- __forceinline vfloat4 floor(const vfloat4& a) { return vfloat4(floorf(a[0]),floorf(a[1]),floorf(a[2]),floorf(a[3])); }
- __forceinline vfloat4 ceil (const vfloat4& a) { return vfloat4(ceilf (a[0]),ceilf (a[1]),ceilf (a[2]),ceilf (a[3])); }
- __forceinline vfloat4 trunc(const vfloat4& a) { return vfloat4(truncf(a[0]),truncf(a[1]),truncf(a[2]),truncf(a[3])); }
- __forceinline vfloat4 round(const vfloat4& a) { return vfloat4(roundf(a[0]),roundf(a[1]),roundf(a[2]),roundf(a[3])); }
-#endif
- __forceinline vfloat4 frac(const vfloat4& a) { return a-floor(a); }
-
- __forceinline vint4 floori(const vfloat4& a) {
-#if defined(__aarch64__)
- return vcvtq_s32_f32(floor(a));
-#elif defined(__SSE4_1__)
- return vint4(floor(a));
-#else
- return vint4(a-vfloat4(0.5f));
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat4 unpacklo(const vfloat4& a, const vfloat4& b) { return _mm_unpacklo_ps(a, b); }
- __forceinline vfloat4 unpackhi(const vfloat4& a, const vfloat4& b) { return _mm_unpackhi_ps(a, b); }
-
-#if defined(__aarch64__)
- template<int i0, int i1, int i2, int i3>
- __forceinline vfloat4 shuffle(const vfloat4& v) {
- return vreinterpretq_f32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3)));
- }
- template<int i0, int i1, int i2, int i3>
- __forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) {
- return vreinterpretq_f32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
- }
-#else
- template<int i0, int i1, int i2, int i3>
- __forceinline vfloat4 shuffle(const vfloat4& v) {
- return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) {
- return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-#endif
-
-#if defined (__SSSE3__)
- __forceinline vfloat4 shuffle8(const vfloat4& a, const vint4& shuf) {
- return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf));
- }
-#endif
-
-#if defined(__aarch64__)
- template<> __forceinline vfloat4 shuffle<0, 0, 2, 2>(const vfloat4& v) { return __m128(vqtbl1q_u8( uint8x16_t(v.v), v0022 )); }
- template<> __forceinline vfloat4 shuffle<1, 1, 3, 3>(const vfloat4& v) { return __m128(vqtbl1q_u8( uint8x16_t(v.v), v1133)); }
- template<> __forceinline vfloat4 shuffle<0, 1, 0, 1>(const vfloat4& v) { return __m128(vqtbl1q_u8( uint8x16_t(v.v), v0101)); }
-#elif defined(__SSE3__)
- template<> __forceinline vfloat4 shuffle<0, 0, 2, 2>(const vfloat4& v) { return _mm_moveldup_ps(v); }
- template<> __forceinline vfloat4 shuffle<1, 1, 3, 3>(const vfloat4& v) { return _mm_movehdup_ps(v); }
- template<> __forceinline vfloat4 shuffle<0, 1, 0, 1>(const vfloat4& v) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(v))); }
-#endif
-
- template<int i>
- __forceinline vfloat4 shuffle(const vfloat4& v) {
- return shuffle<i,i,i,i>(v);
- }
-
-#if defined(__aarch64__)
- template<int i> __forceinline float extract(const vfloat4& a);
- template<> __forceinline float extract<0>(const vfloat4& b) {
- return b[0];
- }
- template<> __forceinline float extract<1>(const vfloat4& b) {
- return b[1];
- }
- template<> __forceinline float extract<2>(const vfloat4& b) {
- return b[2];
- }
- template<> __forceinline float extract<3>(const vfloat4& b) {
- return b[3];
- }
-#elif defined (__SSE4_1__) && !defined(__GNUC__)
- template<int i> __forceinline float extract(const vfloat4& a) { return _mm_cvtss_f32(_mm_extract_ps(a,i)); }
- template<> __forceinline float extract<0>(const vfloat4& a) { return _mm_cvtss_f32(a); }
-#else
- template<int i> __forceinline float extract(const vfloat4& a) { return _mm_cvtss_f32(shuffle<i,i,i,i>(a)); }
- template<> __forceinline float extract<0>(const vfloat4& a) { return _mm_cvtss_f32(a); }
-#endif
-
-
-#if defined(__aarch64__)
- template<int dst> __forceinline vfloat4 insert(const vfloat4& a, float b);
- template<> __forceinline vfloat4 insert<0>(const vfloat4& a, float b)
- {
- vfloat4 c = a;
- c[0] = b;
- return c;
- }
- template<> __forceinline vfloat4 insert<1>(const vfloat4& a, float b)
- {
- vfloat4 c = a;
- c[1] = b;
- return c;
- }
- template<> __forceinline vfloat4 insert<2>(const vfloat4& a, float b)
- {
- vfloat4 c = a;
- c[2] = b;
- return c;
- }
- template<> __forceinline vfloat4 insert<3>(const vfloat4& a, float b)
- {
- vfloat4 c = a;
- c[3] = b;
- return c;
- }
-#elif defined (__SSE4_1__)
- template<int dst, int src, int clr> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
- template<int dst, int src> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return insert<dst, src, 0>(a, b); }
- template<int dst> __forceinline vfloat4 insert(const vfloat4& a, const float b) { return insert<dst, 0>(a, _mm_set_ss(b)); }
-#else
- template<int dst, int src> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { vfloat4 c = a; c[dst&3] = b[src&3]; return c; }
- template<int dst> __forceinline vfloat4 insert(const vfloat4& a, float b) { vfloat4 c = a; c[dst&3] = b; return c; }
-#endif
-
-#if defined(__aarch64__)
- __forceinline float toScalar(const vfloat4& v) {
- return v[0];
- }
-#else
- __forceinline float toScalar(const vfloat4& v) { return _mm_cvtss_f32(v); }
-#endif
- __forceinline vfloat4 broadcast4f(const vfloat4& a, size_t k) {
- return vfloat4::broadcast(&a[k]);
- }
-
- __forceinline vfloat4 shift_right_1(const vfloat4& x) {
- return _mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(x), 4));
- }
-
-#if defined (__AVX2__)
- __forceinline vfloat4 permute(const vfloat4 &a, const __m128i &index) {
- return _mm_permutevar_ps(a,index);
- }
-
- __forceinline vfloat4 broadcast1f(const void* a) { return _mm_broadcast_ss((float*)a); }
-
-#endif
-
-#if defined(__AVX512VL__)
- template<int i>
- __forceinline vfloat4 align_shift_right(const vfloat4& a, const vfloat4& b) {
- return _mm_castsi128_ps(_mm_alignr_epi32(_mm_castps_si128(a), _mm_castps_si128(b), i));
- }
-#endif
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Sorting Network
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat4 sort_ascending(const vfloat4& v)
- {
- const vfloat4 a0 = v;
- const vfloat4 b0 = shuffle<1,0,3,2>(a0);
- const vfloat4 c0 = min(a0,b0);
- const vfloat4 d0 = max(a0,b0);
- const vfloat4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
- const vfloat4 b1 = shuffle<2,3,0,1>(a1);
- const vfloat4 c1 = min(a1,b1);
- const vfloat4 d1 = max(a1,b1);
- const vfloat4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
- const vfloat4 b2 = shuffle<0,2,1,3>(a2);
- const vfloat4 c2 = min(a2,b2);
- const vfloat4 d2 = max(a2,b2);
- const vfloat4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
- return a3;
- }
-
- __forceinline vfloat4 sort_descending(const vfloat4& v)
- {
- const vfloat4 a0 = v;
- const vfloat4 b0 = shuffle<1,0,3,2>(a0);
- const vfloat4 c0 = max(a0,b0);
- const vfloat4 d0 = min(a0,b0);
- const vfloat4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
- const vfloat4 b1 = shuffle<2,3,0,1>(a1);
- const vfloat4 c1 = max(a1,b1);
- const vfloat4 d1 = min(a1,b1);
- const vfloat4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
- const vfloat4 b2 = shuffle<0,2,1,3>(a2);
- const vfloat4 c2 = max(a2,b2);
- const vfloat4 d2 = min(a2,b2);
- const vfloat4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
- return a3;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Transpose
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, vfloat4& c0, vfloat4& c1, vfloat4& c2, vfloat4& c3)
- {
- vfloat4 l02 = unpacklo(r0,r2);
- vfloat4 h02 = unpackhi(r0,r2);
- vfloat4 l13 = unpacklo(r1,r3);
- vfloat4 h13 = unpackhi(r1,r3);
- c0 = unpacklo(l02,l13);
- c1 = unpackhi(l02,l13);
- c2 = unpacklo(h02,h13);
- c3 = unpackhi(h02,h13);
- }
-
- __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, vfloat4& c0, vfloat4& c1, vfloat4& c2)
- {
- vfloat4 l02 = unpacklo(r0,r2);
- vfloat4 h02 = unpackhi(r0,r2);
- vfloat4 l13 = unpacklo(r1,r3);
- vfloat4 h13 = unpackhi(r1,r3);
- c0 = unpacklo(l02,l13);
- c1 = unpackhi(l02,l13);
- c2 = unpacklo(h02,h13);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-#if defined(__aarch64__)
- __forceinline vfloat4 vreduce_min(const vfloat4& v) { float h = vminvq_f32(v); return vdupq_n_f32(h); }
- __forceinline vfloat4 vreduce_max(const vfloat4& v) { float h = vmaxvq_f32(v); return vdupq_n_f32(h); }
- __forceinline vfloat4 vreduce_add(const vfloat4& v) { float h = vaddvq_f32(v); return vdupq_n_f32(h); }
-#else
- __forceinline vfloat4 vreduce_min(const vfloat4& v) { vfloat4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
- __forceinline vfloat4 vreduce_max(const vfloat4& v) { vfloat4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
- __forceinline vfloat4 vreduce_add(const vfloat4& v) { vfloat4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
-#endif
-
-#if defined(__aarch64__)
- __forceinline float reduce_min(const vfloat4& v) { return vminvq_f32(v); }
- __forceinline float reduce_max(const vfloat4& v) { return vmaxvq_f32(v); }
- __forceinline float reduce_add(const vfloat4& v) { return vaddvq_f32(v); }
-#else
- __forceinline float reduce_min(const vfloat4& v) { return _mm_cvtss_f32(vreduce_min(v)); }
- __forceinline float reduce_max(const vfloat4& v) { return _mm_cvtss_f32(vreduce_max(v)); }
- __forceinline float reduce_add(const vfloat4& v) { return _mm_cvtss_f32(vreduce_add(v)); }
-#endif
-
- __forceinline size_t select_min(const vboolf4& valid, const vfloat4& v)
- {
- const vfloat4 a = select(valid,v,vfloat4(pos_inf));
- const vbool4 valid_min = valid & (a == vreduce_min(a));
- return bsf(movemask(any(valid_min) ? valid_min : valid));
- }
- __forceinline size_t select_max(const vboolf4& valid, const vfloat4& v)
- {
- const vfloat4 a = select(valid,v,vfloat4(neg_inf));
- const vbool4 valid_max = valid & (a == vreduce_max(a));
- return bsf(movemask(any(valid_max) ? valid_max : valid));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline float dot(const vfloat4& a, const vfloat4& b) {
- return reduce_add(a*b);
- }
-
- __forceinline vfloat4 cross(const vfloat4& a, const vfloat4& b)
- {
- const vfloat4 a0 = a;
- const vfloat4 b0 = shuffle<1,2,0,3>(b);
- const vfloat4 a1 = shuffle<1,2,0,3>(a);
- const vfloat4 b1 = b;
- return shuffle<1,2,0,3>(prod_diff(a0,b0,a1,b1));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vfloat4& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
- }
-
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vfloat8_avx.h b/thirdparty/embree-aarch64/common/simd/vfloat8_avx.h
deleted file mode 100644
index 3c7e4a8cdc..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vfloat8_avx.h
+++ /dev/null
@@ -1,847 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX float type */
- template<>
- struct vfloat<8>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboolf8 Bool;
- typedef vint8 Int;
- typedef vfloat8 Float;
-
- enum { size = 8 }; // number of SIMD elements
- union { __m256 v; float f[8]; int i[8]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat() {}
- __forceinline vfloat(const vfloat8& other) { v = other.v; }
- __forceinline vfloat8& operator =(const vfloat8& other) { v = other.v; return *this; }
-
- __forceinline vfloat(__m256 a) : v(a) {}
- __forceinline operator const __m256&() const { return v; }
- __forceinline operator __m256&() { return v; }
-
- __forceinline explicit vfloat(const vfloat4& a) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
- __forceinline vfloat(const vfloat4& a, const vfloat4& b) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
-
- __forceinline explicit vfloat(const int8_t* a) : v(_mm256_loadu_ps((const float*)a)) {}
- __forceinline vfloat(float a) : v(_mm256_set1_ps(a)) {}
- __forceinline vfloat(float a, float b) : v(_mm256_set_ps(b, a, b, a, b, a, b, a)) {}
- __forceinline vfloat(float a, float b, float c, float d) : v(_mm256_set_ps(d, c, b, a, d, c, b, a)) {}
- __forceinline vfloat(float a, float b, float c, float d, float e, float f, float g, float h) : v(_mm256_set_ps(h, g, f, e, d, c, b, a)) {}
-
- __forceinline explicit vfloat(__m256i a) : v(_mm256_cvtepi32_ps(a)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat(ZeroTy) : v(_mm256_setzero_ps()) {}
- __forceinline vfloat(OneTy) : v(_mm256_set1_ps(1.0f)) {}
- __forceinline vfloat(PosInfTy) : v(_mm256_set1_ps(pos_inf)) {}
- __forceinline vfloat(NegInfTy) : v(_mm256_set1_ps(neg_inf)) {}
- __forceinline vfloat(StepTy) : v(_mm256_set_ps(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f)) {}
- __forceinline vfloat(NaNTy) : v(_mm256_set1_ps(nan)) {}
- __forceinline vfloat(UndefinedTy) : v(_mm256_undefined_ps()) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vfloat8 broadcast(const void* a) {
- return _mm256_broadcast_ss((float*)a);
- }
-
- static __forceinline vfloat8 broadcast2(const float* a, const float* b) {
-#if defined(__INTEL_COMPILER)
- const vfloat8 v0 = _mm256_broadcast_ss(a);
- const vfloat8 v1 = _mm256_broadcast_ss(b);
- return _mm256_blend_ps(v1, v0, 0xf);
-#else
- return _mm256_set_ps(*b,*b,*b,*b,*a,*a,*a,*a);
-#endif
- }
-
- static __forceinline vfloat8 broadcast4f(const vfloat4* ptr) {
- return _mm256_broadcast_ps((__m128*)ptr);
- }
-
- static __forceinline vfloat8 load(const int8_t* ptr) {
-#if defined(__AVX2__)
- return _mm256_cvtepi32_ps(_mm256_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr)));
-#else
- return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
-#endif
- }
-
- static __forceinline vfloat8 load(const uint8_t* ptr) {
-#if defined(__AVX2__)
- return _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
-#else
- return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
-#endif
- }
-
- static __forceinline vfloat8 load(const short* ptr) {
-#if defined(__AVX2__)
- return _mm256_cvtepi32_ps(_mm256_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr)));
-#else
- return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
-#endif
- }
-
- static __forceinline vfloat8 load (const void* ptr) { return _mm256_load_ps((float*)ptr); }
- static __forceinline vfloat8 loadu(const void* ptr) { return _mm256_loadu_ps((float*)ptr); }
-
- static __forceinline void store (void* ptr, const vfloat8& v) { return _mm256_store_ps((float*)ptr,v); }
- static __forceinline void storeu(void* ptr, const vfloat8& v) { return _mm256_storeu_ps((float*)ptr,v); }
-
-#if defined(__AVX512VL__)
-
- static __forceinline vfloat8 compact(const vboolf8& mask, vfloat8 &v) {
- return _mm256_mask_compress_ps(v, mask, v);
- }
- static __forceinline vfloat8 compact(const vboolf8& mask, vfloat8 &a, const vfloat8& b) {
- return _mm256_mask_compress_ps(a, mask, b);
- }
-
- static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_ps (_mm256_setzero_ps(),mask,(float*)ptr); }
- static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_ps(_mm256_setzero_ps(),mask,(float*)ptr); }
-
- static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_store_ps ((float*)ptr,mask,v); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_storeu_ps((float*)ptr,mask,v); }
-#elif defined(__aarch64__)
- static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask.v); }
- static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask.v); }
-
- static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask.v,v); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask.v,v); }
-#else
- static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask); }
- static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask); }
-
- static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,v); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,v); }
-#endif
-
-#if defined(__AVX2__)
- static __forceinline vfloat8 load_nt(void* ptr) {
- return _mm256_castsi256_ps(_mm256_stream_load_si256((__m256i*)ptr));
- }
-#endif
-
- static __forceinline void store_nt(void* ptr, const vfloat8& v) {
- _mm256_stream_ps((float*)ptr,v);
- }
-
- template<int scale = 4>
- static __forceinline vfloat8 gather(const float* ptr, const vint8& index) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return _mm256_i32gather_ps(ptr, index ,scale);
-#else
- return vfloat8(
- *(float*)(((int8_t*)ptr)+scale*index[0]),
- *(float*)(((int8_t*)ptr)+scale*index[1]),
- *(float*)(((int8_t*)ptr)+scale*index[2]),
- *(float*)(((int8_t*)ptr)+scale*index[3]),
- *(float*)(((int8_t*)ptr)+scale*index[4]),
- *(float*)(((int8_t*)ptr)+scale*index[5]),
- *(float*)(((int8_t*)ptr)+scale*index[6]),
- *(float*)(((int8_t*)ptr)+scale*index[7]));
-#endif
- }
-
- template<int scale = 4>
- static __forceinline vfloat8 gather(const vboolf8& mask, const float* ptr, const vint8& index) {
- vfloat8 r = zero;
-#if defined(__AVX512VL__)
- return _mm256_mmask_i32gather_ps(r, mask, index, ptr, scale);
-#elif defined(__AVX2__) && !defined(__aarch64__)
- return _mm256_mask_i32gather_ps(r, ptr, index, mask, scale);
-#else
- if (likely(mask[0])) r[0] = *(float*)(((int8_t*)ptr)+scale*index[0]);
- if (likely(mask[1])) r[1] = *(float*)(((int8_t*)ptr)+scale*index[1]);
- if (likely(mask[2])) r[2] = *(float*)(((int8_t*)ptr)+scale*index[2]);
- if (likely(mask[3])) r[3] = *(float*)(((int8_t*)ptr)+scale*index[3]);
- if (likely(mask[4])) r[4] = *(float*)(((int8_t*)ptr)+scale*index[4]);
- if (likely(mask[5])) r[5] = *(float*)(((int8_t*)ptr)+scale*index[5]);
- if (likely(mask[6])) r[6] = *(float*)(((int8_t*)ptr)+scale*index[6]);
- if (likely(mask[7])) r[7] = *(float*)(((int8_t*)ptr)+scale*index[7]);
- return r;
- #endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(void* ptr, const vint8& ofs, const vfloat8& v)
- {
-#if defined(__AVX512VL__)
- _mm256_i32scatter_ps((float*)ptr, ofs, v, scale);
-#else
- *(float*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- *(float*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- *(float*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- *(float*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- *(float*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- *(float*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- *(float*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- *(float*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vfloat8& v)
- {
-#if defined(__AVX512VL__)
- _mm256_mask_i32scatter_ps((float*)ptr, mask, ofs, v, scale);
-#else
- if (likely(mask[0])) *(float*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- if (likely(mask[1])) *(float*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- if (likely(mask[2])) *(float*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- if (likely(mask[3])) *(float*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- if (likely(mask[4])) *(float*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- if (likely(mask[5])) *(float*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- if (likely(mask[6])) *(float*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- if (likely(mask[7])) *(float*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
-#endif
- }
-
- static __forceinline void store(const vboolf8& mask, int8_t* ptr, const vint8& ofs, const vfloat8& v) {
- scatter<1>(mask,ptr,ofs,v);
- }
- static __forceinline void store(const vboolf8& mask, float* ptr, const vint8& ofs, const vfloat8& v) {
- scatter<4>(mask,ptr,ofs,v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const float& operator [](size_t index) const { assert(index < 8); return f[index]; }
- __forceinline float& operator [](size_t index) { assert(index < 8); return f[index]; }
- };
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat8 asFloat(const vint8& a) { return _mm256_castsi256_ps(a); }
- __forceinline vint8 asInt (const vfloat8& a) { return _mm256_castps_si256(a); }
-
- __forceinline vint8 toInt (const vfloat8& a) { return vint8(a); }
- __forceinline vfloat8 toFloat(const vint8& a) { return vfloat8(a); }
-
- __forceinline vfloat8 operator +(const vfloat8& a) { return a; }
-#if !defined(__aarch64__)
- __forceinline vfloat8 operator -(const vfloat8& a) {
- const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
- return _mm256_xor_ps(a, mask);
- }
-#else
- __forceinline vfloat8 operator -(const vfloat8& a) {
- __m256 res;
- res.lo = vnegq_f32(a.v.lo);
- res.hi = vnegq_f32(a.v.hi);
- return res;
-}
-#endif
-
-#if !defined(__aarch64__)
-__forceinline vfloat8 abs(const vfloat8& a) {
- const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff));
- return _mm256_and_ps(a, mask);
-}
-#else
-__forceinline vfloat8 abs(const vfloat8& a) {
- __m256 res;
- res.lo = vabsq_f32(a.v.lo);
- res.hi = vabsq_f32(a.v.hi);
- return res;
-}
-#endif
-
-#if !defined(__aarch64__)
- __forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmp_ps(a, vfloat8(zero), _CMP_NGE_UQ)); }
-#else
- __forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmplt_ps(a, vfloat8(zero))); }
-#endif
- __forceinline vfloat8 signmsk(const vfloat8& a) { return _mm256_and_ps(a,_mm256_castsi256_ps(_mm256_set1_epi32(0x80000000))); }
-
-
- static __forceinline vfloat8 rcp(const vfloat8& a)
- {
-#if defined(BUILD_IOS) && defined(__aarch64__)
- // ios devices are faster doing full divide, no need for NR fixup
- vfloat8 ret;
- const float32x4_t one = vdupq_n_f32(1.0f);
- ret.v.lo = vdivq_f32(one, a.v.lo);
- ret.v.hi = vdivq_f32(one, a.v.hi);
- return ret;
-#endif
-
-#if defined(__AVX512VL__)
- const vfloat8 r = _mm256_rcp14_ps(a);
-#else
- const vfloat8 r = _mm256_rcp_ps(a);
-#endif
-
-#if defined(__AVX2__) //&& !defined(aarch64)
- return _mm256_mul_ps(r, _mm256_fnmadd_ps(r, a, vfloat8(2.0f)));
-#else
- return _mm256_mul_ps(r, _mm256_sub_ps(vfloat8(2.0f), _mm256_mul_ps(r, a)));
-#endif
- }
- __forceinline vfloat8 sqr (const vfloat8& a) { return _mm256_mul_ps(a,a); }
- __forceinline vfloat8 sqrt(const vfloat8& a) { return _mm256_sqrt_ps(a); }
-
- static __forceinline vfloat8 rsqrt(const vfloat8& a)
- {
-#if defined(__AVX512VL__)
- const vfloat8 r = _mm256_rsqrt14_ps(a);
-#else
- const vfloat8 r = _mm256_rsqrt_ps(a);
-#endif
-
-#if defined(__AVX2__)
- return _mm256_fmadd_ps(_mm256_set1_ps(1.5f), r,
- _mm256_mul_ps(_mm256_mul_ps(_mm256_mul_ps(a, _mm256_set1_ps(-0.5f)), r), _mm256_mul_ps(r, r)));
-#else
- return _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(1.5f), r),
- _mm256_mul_ps(_mm256_mul_ps(_mm256_mul_ps(a, _mm256_set1_ps(-0.5f)), r), _mm256_mul_ps(r, r)));
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat8 operator +(const vfloat8& a, const vfloat8& b) { return _mm256_add_ps(a, b); }
- __forceinline vfloat8 operator +(const vfloat8& a, float b) { return a + vfloat8(b); }
- __forceinline vfloat8 operator +(float a, const vfloat8& b) { return vfloat8(a) + b; }
-
- __forceinline vfloat8 operator -(const vfloat8& a, const vfloat8& b) { return _mm256_sub_ps(a, b); }
- __forceinline vfloat8 operator -(const vfloat8& a, float b) { return a - vfloat8(b); }
- __forceinline vfloat8 operator -(float a, const vfloat8& b) { return vfloat8(a) - b; }
-
- __forceinline vfloat8 operator *(const vfloat8& a, const vfloat8& b) { return _mm256_mul_ps(a, b); }
- __forceinline vfloat8 operator *(const vfloat8& a, float b) { return a * vfloat8(b); }
- __forceinline vfloat8 operator *(float a, const vfloat8& b) { return vfloat8(a) * b; }
-
- __forceinline vfloat8 operator /(const vfloat8& a, const vfloat8& b) { return _mm256_div_ps(a, b); }
- __forceinline vfloat8 operator /(const vfloat8& a, float b) { return a / vfloat8(b); }
- __forceinline vfloat8 operator /(float a, const vfloat8& b) { return vfloat8(a) / b; }
-
- __forceinline vfloat8 operator &(const vfloat8& a, const vfloat8& b) { return _mm256_and_ps(a,b); }
- __forceinline vfloat8 operator |(const vfloat8& a, const vfloat8& b) { return _mm256_or_ps(a,b); }
- __forceinline vfloat8 operator ^(const vfloat8& a, const vfloat8& b) { return _mm256_xor_ps(a,b); }
- __forceinline vfloat8 operator ^(const vfloat8& a, const vint8& b) { return _mm256_xor_ps(a,_mm256_castsi256_ps(b)); }
-
- __forceinline vfloat8 min(const vfloat8& a, const vfloat8& b) { return _mm256_min_ps(a, b); }
- __forceinline vfloat8 min(const vfloat8& a, float b) { return _mm256_min_ps(a, vfloat8(b)); }
- __forceinline vfloat8 min(float a, const vfloat8& b) { return _mm256_min_ps(vfloat8(a), b); }
-
- __forceinline vfloat8 max(const vfloat8& a, const vfloat8& b) { return _mm256_max_ps(a, b); }
- __forceinline vfloat8 max(const vfloat8& a, float b) { return _mm256_max_ps(a, vfloat8(b)); }
- __forceinline vfloat8 max(float a, const vfloat8& b) { return _mm256_max_ps(vfloat8(a), b); }
-
- /* need "static __forceinline for MSVC, otherwise we'll link the wrong version in debug mode */
-#if defined(__AVX2__)
-
- static __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) {
- const vint8 ai = _mm256_castps_si256(a);
- const vint8 bi = _mm256_castps_si256(b);
- const vint8 ci = _mm256_min_epi32(ai,bi);
- return _mm256_castsi256_ps(ci);
- }
-
- static __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) {
- const vint8 ai = _mm256_castps_si256(a);
- const vint8 bi = _mm256_castps_si256(b);
- const vint8 ci = _mm256_max_epi32(ai,bi);
- return _mm256_castsi256_ps(ci);
- }
-
- static __forceinline vfloat8 minui(const vfloat8& a, const vfloat8& b) {
- const vint8 ai = _mm256_castps_si256(a);
- const vint8 bi = _mm256_castps_si256(b);
- const vint8 ci = _mm256_min_epu32(ai,bi);
- return _mm256_castsi256_ps(ci);
- }
-
- static __forceinline vfloat8 maxui(const vfloat8& a, const vfloat8& b) {
- const vint8 ai = _mm256_castps_si256(a);
- const vint8 bi = _mm256_castps_si256(b);
- const vint8 ci = _mm256_max_epu32(ai,bi);
- return _mm256_castsi256_ps(ci);
- }
-
-#else
-
- static __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) {
- return asFloat(min(asInt(a),asInt(b)));
- }
-
- static __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) {
- return asFloat(max(asInt(a),asInt(b)));
- }
-
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Ternary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX2__)
- static __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmadd_ps(a,b,c); }
- static __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmsub_ps(a,b,c); }
- static __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmadd_ps(a,b,c); }
- static __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmsub_ps(a,b,c); }
-#else
- static __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b+c; }
- static __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b-c; }
- static __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b+c;}
- static __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b-c; }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat8& operator +=(vfloat8& a, const vfloat8& b) { return a = a + b; }
- __forceinline vfloat8& operator +=(vfloat8& a, float b) { return a = a + b; }
-
- __forceinline vfloat8& operator -=(vfloat8& a, const vfloat8& b) { return a = a - b; }
- __forceinline vfloat8& operator -=(vfloat8& a, float b) { return a = a - b; }
-
- __forceinline vfloat8& operator *=(vfloat8& a, const vfloat8& b) { return a = a * b; }
- __forceinline vfloat8& operator *=(vfloat8& a, float b) { return a = a * b; }
-
- __forceinline vfloat8& operator /=(vfloat8& a, const vfloat8& b) { return a = a / b; }
- __forceinline vfloat8& operator /=(vfloat8& a, float b) { return a = a / b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_EQ); }
- static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_NE); }
- static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LT); }
- static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GE); }
- static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GT); }
- static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LE); }
-
- static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
- return _mm256_mask_blend_ps(m, f, t);
- }
-#elif !defined(__aarch64__)
- __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); }
- __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); }
- __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LT_OS); }
- __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); }
- __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); }
- __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LE_OS); }
-
- __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
- return _mm256_blendv_ps(f, t, m);
- }
-#else
- __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmpeq_ps(a, b); }
- __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmpneq_ps(a, b); }
- __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmplt_ps(a, b); }
- __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmpge_ps(a, b); }
- __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmpgt_ps(a, b); }
- __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmple_ps(a, b); }
-
- __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
- return _mm256_blendv_ps(f, t, m);
- }
-
-#endif
-
- template<int mask>
- __forceinline vfloat8 select(const vfloat8& t, const vfloat8& f) {
- return _mm256_blend_ps(f, t, mask);
- }
-
- __forceinline vboolf8 operator ==(const vfloat8& a, const float& b) { return a == vfloat8(b); }
- __forceinline vboolf8 operator ==(const float& a, const vfloat8& b) { return vfloat8(a) == b; }
-
- __forceinline vboolf8 operator !=(const vfloat8& a, const float& b) { return a != vfloat8(b); }
- __forceinline vboolf8 operator !=(const float& a, const vfloat8& b) { return vfloat8(a) != b; }
-
- __forceinline vboolf8 operator < (const vfloat8& a, const float& b) { return a < vfloat8(b); }
- __forceinline vboolf8 operator < (const float& a, const vfloat8& b) { return vfloat8(a) < b; }
-
- __forceinline vboolf8 operator >=(const vfloat8& a, const float& b) { return a >= vfloat8(b); }
- __forceinline vboolf8 operator >=(const float& a, const vfloat8& b) { return vfloat8(a) >= b; }
-
- __forceinline vboolf8 operator > (const vfloat8& a, const float& b) { return a > vfloat8(b); }
- __forceinline vboolf8 operator > (const float& a, const vfloat8& b) { return vfloat8(a) > b; }
-
- __forceinline vboolf8 operator <=(const vfloat8& a, const float& b) { return a <= vfloat8(b); }
- __forceinline vboolf8 operator <=(const float& a, const vfloat8& b) { return vfloat8(a) <= b; }
-
- __forceinline vboolf8 eq(const vfloat8& a, const vfloat8& b) { return a == b; }
- __forceinline vboolf8 ne(const vfloat8& a, const vfloat8& b) { return a != b; }
- __forceinline vboolf8 lt(const vfloat8& a, const vfloat8& b) { return a < b; }
- __forceinline vboolf8 ge(const vfloat8& a, const vfloat8& b) { return a >= b; }
- __forceinline vboolf8 gt(const vfloat8& a, const vfloat8& b) { return a > b; }
- __forceinline vboolf8 le(const vfloat8& a, const vfloat8& b) { return a <= b; }
-
-#if defined(__AVX512VL__)
- static __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); }
- static __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); }
- static __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); }
- static __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); }
- static __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); }
- static __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); }
-#else
- static __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a == b); }
- static __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a != b); }
- static __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a < b); }
- static __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a >= b); }
- static __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a > b); }
- static __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a <= b); }
-#endif
-
- __forceinline vfloat8 lerp(const vfloat8& a, const vfloat8& b, const vfloat8& t) {
- return madd(t,b-a,a);
- }
-
- __forceinline bool isvalid (const vfloat8& v) {
- return all((v > vfloat8(-FLT_LARGE)) & (v < vfloat8(+FLT_LARGE)));
- }
-
- __forceinline bool is_finite (const vfloat8& a) {
- return all((a >= vfloat8(-FLT_MAX)) & (a <= vfloat8(+FLT_MAX)));
- }
-
- __forceinline bool is_finite (const vboolf8& valid, const vfloat8& a) {
- return all(valid, (a >= vfloat8(-FLT_MAX)) & (a <= vfloat8(+FLT_MAX)));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Rounding Functions
- ////////////////////////////////////////////////////////////////////////////////
-
-#if !defined(__aarch64__)
- __forceinline vfloat8 floor(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
- __forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); }
- __forceinline vfloat8 trunc(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_ZERO ); }
- __forceinline vfloat8 round(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
-#else
- __forceinline vfloat8 floor(const vfloat8& a) { return _mm256_floor_ps(a); }
- __forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_ceil_ps(a); }
-#endif
-
-
- __forceinline vfloat8 frac (const vfloat8& a) { return a-floor(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat8 unpacklo(const vfloat8& a, const vfloat8& b) { return _mm256_unpacklo_ps(a, b); }
- __forceinline vfloat8 unpackhi(const vfloat8& a, const vfloat8& b) { return _mm256_unpackhi_ps(a, b); }
-
- template<int i>
- __forceinline vfloat8 shuffle(const vfloat8& v) {
- return _mm256_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
- }
-
- template<int i0, int i1>
- __forceinline vfloat8 shuffle4(const vfloat8& v) {
- return _mm256_permute2f128_ps(v, v, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1>
- __forceinline vfloat8 shuffle4(const vfloat8& a, const vfloat8& b) {
- return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vfloat8 shuffle(const vfloat8& v) {
- return _mm256_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vfloat8 shuffle(const vfloat8& a, const vfloat8& b) {
- return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
-#if !defined(__aarch64__)
- template<> __forceinline vfloat8 shuffle<0, 0, 2, 2>(const vfloat8& v) { return _mm256_moveldup_ps(v); }
- template<> __forceinline vfloat8 shuffle<1, 1, 3, 3>(const vfloat8& v) { return _mm256_movehdup_ps(v); }
- template<> __forceinline vfloat8 shuffle<0, 1, 0, 1>(const vfloat8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); }
-#endif
-
- __forceinline vfloat8 broadcast(const float* ptr) { return _mm256_broadcast_ss(ptr); }
- template<size_t i> __forceinline vfloat8 insert4(const vfloat8& a, const vfloat4& b) { return _mm256_insertf128_ps(a, b, i); }
- template<size_t i> __forceinline vfloat4 extract4 (const vfloat8& a) { return _mm256_extractf128_ps(a, i); }
- template<> __forceinline vfloat4 extract4<0>(const vfloat8& a) { return _mm256_castps256_ps128(a); }
-
- __forceinline float toScalar(const vfloat8& v) { return _mm_cvtss_f32(_mm256_castps256_ps128(v)); }
-
- __forceinline vfloat8 assign(const vfloat4& a) { return _mm256_castps128_ps256(a); }
-
-#if defined (__AVX2__) && !defined(__aarch64__)
- __forceinline vfloat8 permute(const vfloat8& a, const __m256i& index) {
- return _mm256_permutevar8x32_ps(a, index);
- }
-#endif
-
-#if defined(__AVX512VL__)
- template<int i>
- static __forceinline vfloat8 align_shift_right(const vfloat8& a, const vfloat8& b) {
- return _mm256_castsi256_ps(_mm256_alignr_epi32(_mm256_castps_si256(a), _mm256_castps_si256(b), i));
- }
-#endif
-
-#if defined (__AVX_I__)
- template<const int mode>
- static __forceinline vint4 convert_to_hf16(const vfloat8& a) {
- return _mm256_cvtps_ph(a, mode);
- }
-
- static __forceinline vfloat8 convert_from_hf16(const vint4& a) {
- return _mm256_cvtph_ps(a);
- }
-#endif
-
- __forceinline vfloat4 broadcast4f(const vfloat8& a, const size_t k) {
- return vfloat4::broadcast(&a[k]);
- }
-
- __forceinline vfloat8 broadcast8f(const vfloat8& a, const size_t k) {
- return vfloat8::broadcast(&a[k]);
- }
-
-#if defined(__AVX512VL__)
- static __forceinline vfloat8 shift_right_1(const vfloat8& x) {
- return align_shift_right<1>(zero,x);
- }
-#else
- static __forceinline vfloat8 shift_right_1(const vfloat8& x) {
- const vfloat8 t0 = shuffle<1,2,3,0>(x);
- const vfloat8 t1 = shuffle4<1,0>(t0);
- return _mm256_blend_ps(t0,t1,0x88);
- }
-#endif
-
- __forceinline vint8 floori(const vfloat8& a) {
- return vint8(floor(a));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Transpose
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3)
- {
- vfloat8 l02 = unpacklo(r0,r2);
- vfloat8 h02 = unpackhi(r0,r2);
- vfloat8 l13 = unpacklo(r1,r3);
- vfloat8 h13 = unpackhi(r1,r3);
- c0 = unpacklo(l02,l13);
- c1 = unpackhi(l02,l13);
- c2 = unpacklo(h02,h13);
- c3 = unpackhi(h02,h13);
- }
-
- __forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, vfloat8& c0, vfloat8& c1, vfloat8& c2)
- {
- vfloat8 l02 = unpacklo(r0,r2);
- vfloat8 h02 = unpackhi(r0,r2);
- vfloat8 l13 = unpacklo(r1,r3);
- vfloat8 h13 = unpackhi(r1,r3);
- c0 = unpacklo(l02,l13);
- c1 = unpackhi(l02,l13);
- c2 = unpacklo(h02,h13);
- }
-
- __forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, const vfloat8& r4, const vfloat8& r5, const vfloat8& r6, const vfloat8& r7,
- vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3, vfloat8& c4, vfloat8& c5, vfloat8& c6, vfloat8& c7)
- {
- vfloat8 h0,h1,h2,h3; transpose(r0,r1,r2,r3,h0,h1,h2,h3);
- vfloat8 h4,h5,h6,h7; transpose(r4,r5,r6,r7,h4,h5,h6,h7);
- c0 = shuffle4<0,2>(h0,h4);
- c1 = shuffle4<0,2>(h1,h5);
- c2 = shuffle4<0,2>(h2,h6);
- c3 = shuffle4<0,2>(h3,h7);
- c4 = shuffle4<1,3>(h0,h4);
- c5 = shuffle4<1,3>(h1,h5);
- c6 = shuffle4<1,3>(h2,h6);
- c7 = shuffle4<1,3>(h3,h7);
- }
-
- __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, const vfloat4& r4, const vfloat4& r5, const vfloat4& r6, const vfloat4& r7,
- vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3)
- {
- transpose(vfloat8(r0,r4), vfloat8(r1,r5), vfloat8(r2,r6), vfloat8(r3,r7), c0, c1, c2, c3);
- }
-
- __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, const vfloat4& r4, const vfloat4& r5, const vfloat4& r6, const vfloat4& r7,
- vfloat8& c0, vfloat8& c1, vfloat8& c2)
- {
- transpose(vfloat8(r0,r4), vfloat8(r1,r5), vfloat8(r2,r6), vfloat8(r3,r7), c0, c1, c2);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-#if !defined(__aarch64__)
- __forceinline vfloat8 vreduce_min2(const vfloat8& v) { return min(v,shuffle<1,0,3,2>(v)); }
- __forceinline vfloat8 vreduce_min4(const vfloat8& v) { vfloat8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
- __forceinline vfloat8 vreduce_min (const vfloat8& v) { vfloat8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
-
- __forceinline vfloat8 vreduce_max2(const vfloat8& v) { return max(v,shuffle<1,0,3,2>(v)); }
- __forceinline vfloat8 vreduce_max4(const vfloat8& v) { vfloat8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
- __forceinline vfloat8 vreduce_max (const vfloat8& v) { vfloat8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
-
- __forceinline vfloat8 vreduce_add2(const vfloat8& v) { return v + shuffle<1,0,3,2>(v); }
- __forceinline vfloat8 vreduce_add4(const vfloat8& v) { vfloat8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
- __forceinline vfloat8 vreduce_add (const vfloat8& v) { vfloat8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
-
- __forceinline float reduce_min(const vfloat8& v) { return toScalar(vreduce_min(v)); }
- __forceinline float reduce_max(const vfloat8& v) { return toScalar(vreduce_max(v)); }
- __forceinline float reduce_add(const vfloat8& v) { return toScalar(vreduce_add(v)); }
-#else
- __forceinline float reduce_min(const vfloat8& v) { return vminvq_f32(_mm_min_ps(v.v.lo,v.v.hi)); }
- __forceinline float reduce_max(const vfloat8& v) { return vmaxvq_f32(_mm_max_ps(v.v.lo,v.v.hi)); }
- __forceinline vfloat8 vreduce_min(const vfloat8& v) { return vfloat8(reduce_min(v)); }
- __forceinline vfloat8 vreduce_max(const vfloat8& v) { return vfloat8(reduce_max(v)); }
- __forceinline float reduce_add(const vfloat8& v) { return vaddvq_f32(_mm_add_ps(v.v.lo,v.v.hi)); }
-
-#endif
- __forceinline size_t select_min(const vboolf8& valid, const vfloat8& v)
- {
- const vfloat8 a = select(valid,v,vfloat8(pos_inf));
- const vbool8 valid_min = valid & (a == vreduce_min(a));
- return bsf(movemask(any(valid_min) ? valid_min : valid));
- }
-
- __forceinline size_t select_max(const vboolf8& valid, const vfloat8& v)
- {
- const vfloat8 a = select(valid,v,vfloat8(neg_inf));
- const vbool8 valid_max = valid & (a == vreduce_max(a));
- return bsf(movemask(any(valid_max) ? valid_max : valid));
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Euclidian Space Operators (pairs of Vec3fa's)
- ////////////////////////////////////////////////////////////////////////////////
-
- //__forceinline vfloat8 dot(const vfloat8& a, const vfloat8& b) {
- // return vreduce_add4(a*b);
- //}
-
- __forceinline vfloat8 dot(const vfloat8& a, const vfloat8& b) {
- return _mm256_dp_ps(a,b,0x7F);
- }
-
- __forceinline vfloat8 cross(const vfloat8& a, const vfloat8& b)
- {
- const vfloat8 a0 = a;
- const vfloat8 b0 = shuffle<1,2,0,3>(b);
- const vfloat8 a1 = shuffle<1,2,0,3>(a);
- const vfloat8 b1 = b;
- return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
- }
-
- //__forceinline float sqr_length (const vfloat<8>& a) { return dot(a,a); }
- //__forceinline float rcp_length (const vfloat<8>& a) { return rsqrt(dot(a,a)); }
- //__forceinline float rcp_length2(const vfloat<8>& a) { return rcp(dot(a,a)); }
- //__forceinline float length (const vfloat<8>& a) { return sqrt(dot(a,a)); }
- __forceinline vfloat<8> normalize(const vfloat<8>& a) { return a*rsqrt(dot(a,a)); }
- //__forceinline float distance(const vfloat<8>& a, const vfloat<8>& b) { return length(a-b); }
- //__forceinline float halfArea(const vfloat<8>& d) { return madd(d.x,(d.y+d.z),d.y*d.z); }
- //__forceinline float area (const vfloat<8>& d) { return 2.0f*halfArea(d); }
- //__forceinline vfloat<8> reflect(const vfloat<8>& V, const vfloat<8>& N) { return 2.0f*dot(V,N)*N-V; }
-
- //__forceinline vfloat<8> normalize_safe(const vfloat<8>& a) {
- // const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
- //}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// In Register Sorting
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vfloat8 sort_ascending(const vfloat8& v)
- {
- const vfloat8 a0 = v;
- const vfloat8 b0 = shuffle<1,0,3,2>(a0);
- const vfloat8 c0 = min(a0,b0);
- const vfloat8 d0 = max(a0,b0);
- const vfloat8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
- const vfloat8 b1 = shuffle<2,3,0,1>(a1);
- const vfloat8 c1 = min(a1,b1);
- const vfloat8 d1 = max(a1,b1);
- const vfloat8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
- const vfloat8 b2 = shuffle<1,0,3,2>(a2);
- const vfloat8 c2 = min(a2,b2);
- const vfloat8 d2 = max(a2,b2);
- const vfloat8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
- const vfloat8 b3 = shuffle4<1,0>(a3);
- const vfloat8 c3 = min(a3,b3);
- const vfloat8 d3 = max(a3,b3);
- const vfloat8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
- const vfloat8 b4 = shuffle<2,3,0,1>(a4);
- const vfloat8 c4 = min(a4,b4);
- const vfloat8 d4 = max(a4,b4);
- const vfloat8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
- const vfloat8 b5 = shuffle<1,0,3,2>(a5);
- const vfloat8 c5 = min(a5,b5);
- const vfloat8 d5 = max(a5,b5);
- const vfloat8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
- return a6;
- }
-
- __forceinline vfloat8 sort_descending(const vfloat8& v)
- {
- const vfloat8 a0 = v;
- const vfloat8 b0 = shuffle<1,0,3,2>(a0);
- const vfloat8 c0 = max(a0,b0);
- const vfloat8 d0 = min(a0,b0);
- const vfloat8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
- const vfloat8 b1 = shuffle<2,3,0,1>(a1);
- const vfloat8 c1 = max(a1,b1);
- const vfloat8 d1 = min(a1,b1);
- const vfloat8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
- const vfloat8 b2 = shuffle<1,0,3,2>(a2);
- const vfloat8 c2 = max(a2,b2);
- const vfloat8 d2 = min(a2,b2);
- const vfloat8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
- const vfloat8 b3 = shuffle4<1,0>(a3);
- const vfloat8 c3 = max(a3,b3);
- const vfloat8 d3 = min(a3,b3);
- const vfloat8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
- const vfloat8 b4 = shuffle<2,3,0,1>(a4);
- const vfloat8 c4 = max(a4,b4);
- const vfloat8 d4 = min(a4,b4);
- const vfloat8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
- const vfloat8 b5 = shuffle<1,0,3,2>(a5);
- const vfloat8 c5 = max(a5,b5);
- const vfloat8 d5 = min(a5,b5);
- const vfloat8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
- return a6;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vfloat8& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vint16_avx512.h b/thirdparty/embree-aarch64/common/simd/vint16_avx512.h
deleted file mode 100644
index 3249bc2b45..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vint16_avx512.h
+++ /dev/null
@@ -1,490 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 16-wide AVX-512 integer type */
- template<>
- struct vint<16>
- {
- ALIGNED_STRUCT_(64);
-
- typedef vboolf16 Bool;
- typedef vint16 Int;
- typedef vfloat16 Float;
-
- enum { size = 16 }; // number of SIMD elements
- union { // data
- __m512i v;
- int i[16];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint() {}
- __forceinline vint(const vint16& t) { v = t.v; }
- __forceinline vint16& operator =(const vint16& f) { v = f.v; return *this; }
-
- __forceinline vint(const __m512i& t) { v = t; }
- __forceinline operator __m512i() const { return v; }
- __forceinline operator __m256i() const { return _mm512_castsi512_si256(v); }
-
- __forceinline vint(int i) {
- v = _mm512_set1_epi32(i);
- }
-
- __forceinline vint(int a, int b, int c, int d) {
- v = _mm512_set4_epi32(d,c,b,a);
- }
-
- __forceinline vint(int a0 , int a1 , int a2 , int a3,
- int a4 , int a5 , int a6 , int a7,
- int a8 , int a9 , int a10, int a11,
- int a12, int a13, int a14, int a15)
- {
- v = _mm512_set_epi32(a15,a14,a13,a12,a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0);
- }
-
- __forceinline vint(const vint4& i) {
- v = _mm512_broadcast_i32x4(i);
- }
-
- __forceinline vint(const vint4& a, const vint4& b, const vint4& c, const vint4& d) {
- v = _mm512_castsi128_si512(a);
- v = _mm512_inserti32x4(v, b, 1);
- v = _mm512_inserti32x4(v, c, 2);
- v = _mm512_inserti32x4(v, d, 3);
- }
-
- __forceinline vint(const vint8& i) {
- v = _mm512_castps_si512(_mm512_castpd_ps(_mm512_broadcast_f64x4(_mm256_castsi256_pd(i))));
- }
-
- __forceinline vint(const vint8& a, const vint8& b) {
- v = _mm512_castsi256_si512(a);
- v = _mm512_inserti64x4(v, b, 1);
- }
-
- __forceinline explicit vint(const __m512& f) {
- v = _mm512_cvtps_epi32(f);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint(ZeroTy) : v(_mm512_setzero_epi32()) {}
- __forceinline vint(OneTy) : v(_mm512_set1_epi32(1)) {}
- __forceinline vint(PosInfTy) : v(_mm512_set1_epi32(pos_inf)) {}
- __forceinline vint(NegInfTy) : v(_mm512_set1_epi32(neg_inf)) {}
- __forceinline vint(StepTy) : v(_mm512_set_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
- __forceinline vint(ReverseStepTy) : v(_mm512_setr_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vint16 load (const void* addr) { return _mm512_load_si512((int*)addr); }
-
- static __forceinline vint16 load(const uint8_t* ptr) { return _mm512_cvtepu8_epi32(_mm_load_si128((__m128i*)ptr)); }
- static __forceinline vint16 load(const unsigned short* ptr) { return _mm512_cvtepu16_epi32(_mm256_load_si256((__m256i*)ptr)); }
-
- static __forceinline vint16 loadu(const uint8_t* ptr) { return _mm512_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)); }
- static __forceinline vint16 loadu(const unsigned short* ptr) { return _mm512_cvtepu16_epi32(_mm256_loadu_si256((__m256i*)ptr)); }
-
- static __forceinline vint16 loadu(const void* addr) { return _mm512_loadu_si512(addr); }
-
- static __forceinline vint16 load (const vboolf16& mask, const void* addr) { return _mm512_mask_load_epi32 (_mm512_setzero_epi32(),mask,addr); }
- static __forceinline vint16 loadu(const vboolf16& mask, const void* addr) { return _mm512_mask_loadu_epi32(_mm512_setzero_epi32(),mask,addr); }
-
- static __forceinline void store (void* ptr, const vint16& v) { _mm512_store_si512 (ptr,v); }
- static __forceinline void storeu(void* ptr, const vint16& v) { _mm512_storeu_si512(ptr,v); }
-
- static __forceinline void store (const vboolf16& mask, void* addr, const vint16& v2) { _mm512_mask_store_epi32(addr,mask,v2); }
- static __forceinline void storeu(const vboolf16& mask, void* ptr, const vint16& f) { _mm512_mask_storeu_epi32((int*)ptr,mask,f); }
-
- static __forceinline void store_nt(void* __restrict__ ptr, const vint16& a) { _mm512_stream_si512((__m512i*)ptr,a); }
-
- /* pass by value to avoid compiler generating inefficient code */
- static __forceinline void storeu_compact(const vboolf16 mask, void* addr, vint16 reg) {
- _mm512_mask_compressstoreu_epi32(addr,mask,reg);
- }
-
- static __forceinline void storeu_compact_single(const vboolf16 mask, void* addr, vint16 reg) {
- //_mm512_mask_compressstoreu_epi32(addr,mask,reg);
- *(float*)addr = mm512_cvtss_f32(_mm512_mask_compress_ps(_mm512_castsi512_ps(reg),mask,_mm512_castsi512_ps(reg)));
- }
-
- static __forceinline vint16 compact64bit(const vboolf16& mask, vint16 &v) {
- return _mm512_mask_compress_epi64(v,mask,v);
- }
-
- static __forceinline vint16 compact(const vboolf16& mask, vint16 &v) {
- return _mm512_mask_compress_epi32(v,mask,v);
- }
-
- static __forceinline vint16 compact(const vboolf16& mask, const vint16 &a, vint16 &b) {
- return _mm512_mask_compress_epi32(a,mask,b);
- }
-
- static __forceinline vint16 expand(const vboolf16& mask, const vint16& a, vint16& b) {
- return _mm512_mask_expand_epi32(b,mask,a);
- }
-
- template<int scale = 4>
- static __forceinline vint16 gather(const int* ptr, const vint16& index) {
- return _mm512_i32gather_epi32(index,ptr,scale);
- }
-
- template<int scale = 4>
- static __forceinline vint16 gather(const vboolf16& mask, const int* ptr, const vint16& index) {
- return _mm512_mask_i32gather_epi32(_mm512_undefined_epi32(),mask,index,ptr,scale);
- }
-
- template<int scale = 4>
- static __forceinline vint16 gather(const vboolf16& mask, vint16& dest, const int* ptr, const vint16& index) {
- return _mm512_mask_i32gather_epi32(dest,mask,index,ptr,scale);
- }
-
- template<int scale = 4>
- static __forceinline void scatter(int* ptr, const vint16& index, const vint16& v) {
- _mm512_i32scatter_epi32((int*)ptr,index,v,scale);
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf16& mask, int* ptr, const vint16& index, const vint16& v) {
- _mm512_mask_i32scatter_epi32((int*)ptr,mask,index,v,scale);
- }
-
- static __forceinline vint16 broadcast64bit(size_t v) {
- return _mm512_set1_epi64(v);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline int& operator [](size_t index) { assert(index < 16); return i[index]; }
- __forceinline const int& operator [](size_t index) const { assert(index < 16); return i[index]; }
-
- __forceinline unsigned int uint (size_t index) const { assert(index < 16); return ((unsigned int*)i)[index]; }
- __forceinline size_t& uint64_t(size_t index) const { assert(index < 8); return ((size_t*)i)[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16 asBool(const vint16& a) { return _mm512_movepi32_mask(a); }
-
- __forceinline vint16 operator +(const vint16& a) { return a; }
- __forceinline vint16 operator -(const vint16& a) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint16 operator +(const vint16& a, const vint16& b) { return _mm512_add_epi32(a, b); }
- __forceinline vint16 operator +(const vint16& a, int b) { return a + vint16(b); }
- __forceinline vint16 operator +(int a, const vint16& b) { return vint16(a) + b; }
-
- __forceinline vint16 operator -(const vint16& a, const vint16& b) { return _mm512_sub_epi32(a, b); }
- __forceinline vint16 operator -(const vint16& a, int b) { return a - vint16(b); }
- __forceinline vint16 operator -(int a, const vint16& b) { return vint16(a) - b; }
-
- __forceinline vint16 operator *(const vint16& a, const vint16& b) { return _mm512_mullo_epi32(a, b); }
- __forceinline vint16 operator *(const vint16& a, int b) { return a * vint16(b); }
- __forceinline vint16 operator *(int a, const vint16& b) { return vint16(a) * b; }
-
- __forceinline vint16 operator &(const vint16& a, const vint16& b) { return _mm512_and_epi32(a, b); }
- __forceinline vint16 operator &(const vint16& a, int b) { return a & vint16(b); }
- __forceinline vint16 operator &(int a, const vint16& b) { return vint16(a) & b; }
-
- __forceinline vint16 operator |(const vint16& a, const vint16& b) { return _mm512_or_epi32(a, b); }
- __forceinline vint16 operator |(const vint16& a, int b) { return a | vint16(b); }
- __forceinline vint16 operator |(int a, const vint16& b) { return vint16(a) | b; }
-
- __forceinline vint16 operator ^(const vint16& a, const vint16& b) { return _mm512_xor_epi32(a, b); }
- __forceinline vint16 operator ^(const vint16& a, int b) { return a ^ vint16(b); }
- __forceinline vint16 operator ^(int a, const vint16& b) { return vint16(a) ^ b; }
-
- __forceinline vint16 operator <<(const vint16& a, int n) { return _mm512_slli_epi32(a, n); }
- __forceinline vint16 operator >>(const vint16& a, int n) { return _mm512_srai_epi32(a, n); }
-
- __forceinline vint16 operator <<(const vint16& a, const vint16& n) { return _mm512_sllv_epi32(a, n); }
- __forceinline vint16 operator >>(const vint16& a, const vint16& n) { return _mm512_srav_epi32(a, n); }
-
- __forceinline vint16 sll (const vint16& a, int b) { return _mm512_slli_epi32(a, b); }
- __forceinline vint16 sra (const vint16& a, int b) { return _mm512_srai_epi32(a, b); }
- __forceinline vint16 srl (const vint16& a, int b) { return _mm512_srli_epi32(a, b); }
-
- __forceinline vint16 min(const vint16& a, const vint16& b) { return _mm512_min_epi32(a, b); }
- __forceinline vint16 min(const vint16& a, int b) { return min(a,vint16(b)); }
- __forceinline vint16 min(int a, const vint16& b) { return min(vint16(a),b); }
-
- __forceinline vint16 max(const vint16& a, const vint16& b) { return _mm512_max_epi32(a, b); }
- __forceinline vint16 max(const vint16& a, int b) { return max(a,vint16(b)); }
- __forceinline vint16 max(int a, const vint16& b) { return max(vint16(a),b); }
-
- __forceinline vint16 umin(const vint16& a, const vint16& b) { return _mm512_min_epu32(a, b); }
- __forceinline vint16 umax(const vint16& a, const vint16& b) { return _mm512_max_epu32(a, b); }
-
- __forceinline vint16 mask_add(const vboolf16& mask, vint16& c, const vint16& a, const vint16& b) { return _mm512_mask_add_epi32(c,mask,a,b); }
- __forceinline vint16 mask_sub(const vboolf16& mask, vint16& c, const vint16& a, const vint16& b) { return _mm512_mask_sub_epi32(c,mask,a,b); }
-
- __forceinline vint16 mask_and(const vboolf16& m, vint16& c, const vint16& a, const vint16& b) { return _mm512_mask_and_epi32(c,m,a,b); }
- __forceinline vint16 mask_or (const vboolf16& m, vint16& c, const vint16& a, const vint16& b) { return _mm512_mask_or_epi32(c,m,a,b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint16& operator +=(vint16& a, const vint16& b) { return a = a + b; }
- __forceinline vint16& operator +=(vint16& a, int b) { return a = a + b; }
-
- __forceinline vint16& operator -=(vint16& a, const vint16& b) { return a = a - b; }
- __forceinline vint16& operator -=(vint16& a, int b) { return a = a - b; }
-
- __forceinline vint16& operator *=(vint16& a, const vint16& b) { return a = a * b; }
- __forceinline vint16& operator *=(vint16& a, int b) { return a = a * b; }
-
- __forceinline vint16& operator &=(vint16& a, const vint16& b) { return a = a & b; }
- __forceinline vint16& operator &=(vint16& a, int b) { return a = a & b; }
-
- __forceinline vint16& operator |=(vint16& a, const vint16& b) { return a = a | b; }
- __forceinline vint16& operator |=(vint16& a, int b) { return a = a | b; }
-
- __forceinline vint16& operator <<=(vint16& a, int b) { return a = a << b; }
- __forceinline vint16& operator >>=(vint16& a, int b) { return a = a >> b; }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16 operator ==(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 operator ==(const vint16& a, int b) { return a == vint16(b); }
- __forceinline vboolf16 operator ==(int a, const vint16& b) { return vint16(a) == b; }
-
- __forceinline vboolf16 operator !=(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 operator !=(const vint16& a, int b) { return a != vint16(b); }
- __forceinline vboolf16 operator !=(int a, const vint16& b) { return vint16(a) != b; }
-
- __forceinline vboolf16 operator < (const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 operator < (const vint16& a, int b) { return a < vint16(b); }
- __forceinline vboolf16 operator < (int a, const vint16& b) { return vint16(a) < b; }
-
- __forceinline vboolf16 operator >=(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 operator >=(const vint16& a, int b) { return a >= vint16(b); }
- __forceinline vboolf16 operator >=(int a, const vint16& b) { return vint16(a) >= b; }
-
- __forceinline vboolf16 operator > (const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 operator > (const vint16& a, int b) { return a > vint16(b); }
- __forceinline vboolf16 operator > (int a, const vint16& b) { return vint16(a) > b; }
-
- __forceinline vboolf16 operator <=(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
- __forceinline vboolf16 operator <=(const vint16& a, int b) { return a <= vint16(b); }
- __forceinline vboolf16 operator <=(int a, const vint16& b) { return vint16(a) <= b; }
-
- __forceinline vboolf16 eq(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 ne(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 lt(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 ge(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 gt(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 le(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
- __forceinline vboolf16 uint_le(const vint16& a, const vint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
- __forceinline vboolf16 uint_gt(const vint16& a, const vint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
-
- __forceinline vboolf16 eq(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 ne(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 lt(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 ge(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 gt(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 le(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LE); }
- __forceinline vboolf16 uint_le(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_LE); }
- __forceinline vboolf16 uint_gt(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_GT); }
-
-
- __forceinline vint16 select(const vboolf16& m, const vint16& t, const vint16& f) {
- return _mm512_mask_or_epi32(f,m,t,t);
- }
-
- __forceinline void xchg(const vboolf16& m, vint16& a, vint16& b) {
- const vint16 c = a; a = select(m,b,a); b = select(m,c,b);
- }
-
- __forceinline vboolf16 test(const vboolf16& m, const vint16& a, const vint16& b) {
- return _mm512_mask_test_epi32_mask(m,a,b);
- }
-
- __forceinline vboolf16 test(const vint16& a, const vint16& b) {
- return _mm512_test_epi32_mask(a,b);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint16 unpacklo(const vint16& a, const vint16& b) { return _mm512_unpacklo_epi32(a, b); }
- __forceinline vint16 unpackhi(const vint16& a, const vint16& b) { return _mm512_unpackhi_epi32(a, b); }
-
- template<int i>
- __forceinline vint16 shuffle(const vint16& v) {
- return _mm512_castps_si512(_mm512_permute_ps(_mm512_castsi512_ps(v), _MM_SHUFFLE(i, i, i, i)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vint16 shuffle(const vint16& v) {
- return _mm512_castps_si512(_mm512_permute_ps(_mm512_castsi512_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i>
- __forceinline vint16 shuffle4(const vint16& v) {
- return _mm512_castps_si512(_mm512_shuffle_f32x4(_mm512_castsi512_ps(v), _mm512_castsi512_ps(v), _MM_SHUFFLE(i, i, i, i)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vint16 shuffle4(const vint16& v) {
- return _mm512_castps_si512(_mm512_shuffle_f32x4(_mm512_castsi512_ps(v), _mm512_castsi512_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i>
- __forceinline vint16 align_shift_right(const vint16& a, const vint16& b) {
- return _mm512_alignr_epi32(a, b, i);
- };
-
- __forceinline int toScalar(const vint16& v) {
- return _mm_cvtsi128_si32(_mm512_castsi512_si128(v));
- }
-
- template<int i> __forceinline vint16 insert4(const vint16& a, const vint4& b) { return _mm512_inserti32x4(a, b, i); }
-
- __forceinline size_t extract64bit(const vint16& v) {
- return _mm_cvtsi128_si64(_mm512_castsi512_si128(v));
- }
-
- template<int N, int i>
- vint<N> extractN(const vint16& v);
-
- template<> __forceinline vint4 extractN<4,0>(const vint16& v) { return _mm512_castsi512_si128(v); }
- template<> __forceinline vint4 extractN<4,1>(const vint16& v) { return _mm512_extracti32x4_epi32(v, 1); }
- template<> __forceinline vint4 extractN<4,2>(const vint16& v) { return _mm512_extracti32x4_epi32(v, 2); }
- template<> __forceinline vint4 extractN<4,3>(const vint16& v) { return _mm512_extracti32x4_epi32(v, 3); }
-
- template<> __forceinline vint8 extractN<8,0>(const vint16& v) { return _mm512_castsi512_si256(v); }
- template<> __forceinline vint8 extractN<8,1>(const vint16& v) { return _mm512_extracti32x8_epi32(v, 1); }
-
- template<int i> __forceinline vint4 extract4 (const vint16& v) { return _mm512_extracti32x4_epi32(v, i); }
- template<> __forceinline vint4 extract4<0>(const vint16& v) { return _mm512_castsi512_si128(v); }
-
- template<int i> __forceinline vint8 extract8 (const vint16& v) { return _mm512_extracti32x8_epi32(v, i); }
- template<> __forceinline vint8 extract8<0>(const vint16& v) { return _mm512_castsi512_si256(v); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint16 vreduce_min2(vint16 x) { return min(x, shuffle<1,0,3,2>(x)); }
- __forceinline vint16 vreduce_min4(vint16 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
- __forceinline vint16 vreduce_min8(vint16 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0,3,2>(x)); }
- __forceinline vint16 vreduce_min (vint16 x) { x = vreduce_min8(x); return min(x, shuffle4<2,3,0,1>(x)); }
-
- __forceinline vint16 vreduce_max2(vint16 x) { return max(x, shuffle<1,0,3,2>(x)); }
- __forceinline vint16 vreduce_max4(vint16 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
- __forceinline vint16 vreduce_max8(vint16 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0,3,2>(x)); }
- __forceinline vint16 vreduce_max (vint16 x) { x = vreduce_max8(x); return max(x, shuffle4<2,3,0,1>(x)); }
-
- __forceinline vint16 vreduce_and2(vint16 x) { return x & shuffle<1,0,3,2>(x); }
- __forceinline vint16 vreduce_and4(vint16 x) { x = vreduce_and2(x); return x & shuffle<2,3,0,1>(x); }
- __forceinline vint16 vreduce_and8(vint16 x) { x = vreduce_and4(x); return x & shuffle4<1,0,3,2>(x); }
- __forceinline vint16 vreduce_and (vint16 x) { x = vreduce_and8(x); return x & shuffle4<2,3,0,1>(x); }
-
- __forceinline vint16 vreduce_or2(vint16 x) { return x | shuffle<1,0,3,2>(x); }
- __forceinline vint16 vreduce_or4(vint16 x) { x = vreduce_or2(x); return x | shuffle<2,3,0,1>(x); }
- __forceinline vint16 vreduce_or8(vint16 x) { x = vreduce_or4(x); return x | shuffle4<1,0,3,2>(x); }
- __forceinline vint16 vreduce_or (vint16 x) { x = vreduce_or8(x); return x | shuffle4<2,3,0,1>(x); }
-
- __forceinline vint16 vreduce_add2(vint16 x) { return x + shuffle<1,0,3,2>(x); }
- __forceinline vint16 vreduce_add4(vint16 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
- __forceinline vint16 vreduce_add8(vint16 x) { x = vreduce_add4(x); return x + shuffle4<1,0,3,2>(x); }
- __forceinline vint16 vreduce_add (vint16 x) { x = vreduce_add8(x); return x + shuffle4<2,3,0,1>(x); }
-
- __forceinline int reduce_min(const vint16& v) { return toScalar(vreduce_min(v)); }
- __forceinline int reduce_max(const vint16& v) { return toScalar(vreduce_max(v)); }
- __forceinline int reduce_and(const vint16& v) { return toScalar(vreduce_and(v)); }
- __forceinline int reduce_or (const vint16& v) { return toScalar(vreduce_or (v)); }
- __forceinline int reduce_add(const vint16& v) { return toScalar(vreduce_add(v)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Memory load and store operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint16 conflict(const vint16& index)
- {
- return _mm512_conflict_epi32(index);
- }
-
- __forceinline vint16 conflict(const vboolf16& mask, vint16& dest, const vint16& index)
- {
- return _mm512_mask_conflict_epi32(dest,mask,index);
- }
-
- __forceinline vint16 convert_uint32_t(const __m512& f) {
- return _mm512_cvtps_epu32(f);
- }
-
- __forceinline vint16 permute(vint16 v, vint16 index) {
- return _mm512_permutexvar_epi32(index,v);
- }
-
- __forceinline vint16 reverse(const vint16 &a) {
- return permute(a,vint16(reverse_step));
- }
-
- __forceinline vint16 prefix_sum(const vint16& a)
- {
- const vint16 z(zero);
- vint16 v = a;
- v = v + align_shift_right<16-1>(v,z);
- v = v + align_shift_right<16-2>(v,z);
- v = v + align_shift_right<16-4>(v,z);
- v = v + align_shift_right<16-8>(v,z);
- return v;
- }
-
- __forceinline vint16 reverse_prefix_sum(const vint16& a)
- {
- const vint16 z(zero);
- vint16 v = a;
- v = v + align_shift_right<1>(z,v);
- v = v + align_shift_right<2>(z,v);
- v = v + align_shift_right<4>(z,v);
- v = v + align_shift_right<8>(z,v);
- return v;
- }
-
- /* this should use a vbool8 and a vint8_64...*/
- template<int scale = 1, int hint = _MM_HINT_T0>
- __forceinline void gather_prefetch64(const void* base_addr, const vbool16& mask, const vint16& offset)
- {
-#if defined(__AVX512PF__)
- _mm512_mask_prefetch_i64gather_pd(offset, mask, base_addr, scale, hint);
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vint16& v)
- {
- cout << "<" << v[0];
- for (int i=1; i<16; i++) cout << ", " << v[i];
- cout << ">";
- return cout;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vint4_sse2.h b/thirdparty/embree-aarch64/common/simd/vint4_sse2.h
deleted file mode 100644
index 96f105a7c5..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vint4_sse2.h
+++ /dev/null
@@ -1,681 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../math/math.h"
-
-namespace embree
-{
- /* 4-wide SSE integer type */
- template<>
- struct vint<4>
- {
- ALIGNED_STRUCT_(16);
-
- typedef vboolf4 Bool;
- typedef vint4 Int;
- typedef vfloat4 Float;
-
- enum { size = 4 }; // number of SIMD elements
- union { __m128i v; int i[4]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint() {}
- __forceinline vint(const vint4& a) { v = a.v; }
- __forceinline vint4& operator =(const vint4& a) { v = a.v; return *this; }
-
- __forceinline vint(__m128i a) : v(a) {}
- __forceinline operator const __m128i&() const { return v; }
- __forceinline operator __m128i&() { return v; }
-
- __forceinline vint(int a) : v(_mm_set1_epi32(a)) {}
- __forceinline vint(int a, int b, int c, int d) : v(_mm_set_epi32(d, c, b, a)) {}
-
- __forceinline explicit vint(__m128 a) : v(_mm_cvtps_epi32(a)) {}
-#if defined(__AVX512VL__)
- __forceinline explicit vint(const vboolf4& a) : v(_mm_movm_epi32(a)) {}
-#else
- __forceinline explicit vint(const vboolf4& a) : v(_mm_castps_si128((__m128)a)) {}
-#endif
-
- __forceinline vint(long long a, long long b) : v(_mm_set_epi64x(b,a)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint(ZeroTy) : v(_mm_setzero_si128()) {}
- __forceinline vint(OneTy) : v(_mm_set_epi32(1, 1, 1, 1)) {}
- __forceinline vint(PosInfTy) : v(_mm_set_epi32(pos_inf, pos_inf, pos_inf, pos_inf)) {}
- __forceinline vint(NegInfTy) : v(_mm_set_epi32(neg_inf, neg_inf, neg_inf, neg_inf)) {}
- __forceinline vint(StepTy) : v(_mm_set_epi32(3, 2, 1, 0)) {}
- __forceinline vint(ReverseStepTy) : v(_mm_set_epi32(0, 1, 2, 3)) {}
-
- __forceinline vint(TrueTy) { v = _mm_cmpeq_epi32(v,v); }
- __forceinline vint(UndefinedTy) : v(_mm_castps_si128(_mm_undefined_ps())) {}
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vint4 load (const void* a) { return _mm_load_si128((__m128i*)a); }
- static __forceinline vint4 loadu(const void* a) { return _mm_loadu_si128((__m128i*)a); }
-
- static __forceinline void store (void* ptr, const vint4& v) { _mm_store_si128((__m128i*)ptr,v); }
- static __forceinline void storeu(void* ptr, const vint4& v) { _mm_storeu_si128((__m128i*)ptr,v); }
-
-#if defined(__AVX512VL__)
-
- static __forceinline vint4 compact(const vboolf4& mask, vint4 &v) {
- return _mm_mask_compress_epi32(v, mask, v);
- }
- static __forceinline vint4 compact(const vboolf4& mask, vint4 &a, const vint4& b) {
- return _mm_mask_compress_epi32(a, mask, b);
- }
-
- static __forceinline vint4 load (const vboolf4& mask, const void* ptr) { return _mm_mask_load_epi32 (_mm_setzero_si128(),mask,ptr); }
- static __forceinline vint4 loadu(const vboolf4& mask, const void* ptr) { return _mm_mask_loadu_epi32(_mm_setzero_si128(),mask,ptr); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vint4& v) { _mm_mask_store_epi32 (ptr,mask,v); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vint4& v) { _mm_mask_storeu_epi32(ptr,mask,v); }
-#elif defined(__AVX__)
- static __forceinline vint4 load (const vbool4& mask, const void* a) { return _mm_castps_si128(_mm_maskload_ps((float*)a,mask)); }
- static __forceinline vint4 loadu(const vbool4& mask, const void* a) { return _mm_castps_si128(_mm_maskload_ps((float*)a,mask)); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vint4& i) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i)); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vint4& i) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i)); }
-#else
- static __forceinline vint4 load (const vbool4& mask, const void* a) { return _mm_and_si128(_mm_load_si128 ((__m128i*)a),mask); }
- static __forceinline vint4 loadu(const vbool4& mask, const void* a) { return _mm_and_si128(_mm_loadu_si128((__m128i*)a),mask); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vint4& i) { store (ptr,select(mask,i,load (ptr))); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vint4& i) { storeu(ptr,select(mask,i,loadu(ptr))); }
-#endif
-
-
-#if defined(__aarch64__)
- static __forceinline vint4 load(const uint8_t* ptr) {
- return _mm_load4epu8_epi32(((__m128i*)ptr));
- }
- static __forceinline vint4 loadu(const uint8_t* ptr) {
- return _mm_load4epu8_epi32(((__m128i*)ptr));
- }
-#elif defined(__SSE4_1__)
- static __forceinline vint4 load(const uint8_t* ptr) {
- return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
- }
-
- static __forceinline vint4 loadu(const uint8_t* ptr) {
- return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
- }
-#else
-
- static __forceinline vint4 load(const uint8_t* ptr) {
- return vint4(ptr[0],ptr[1],ptr[2],ptr[3]);
- }
-
- static __forceinline vint4 loadu(const uint8_t* ptr) {
- return vint4(ptr[0],ptr[1],ptr[2],ptr[3]);
- }
-
-#endif
-
- static __forceinline vint4 load(const unsigned short* ptr) {
-#if defined(__aarch64__)
- return __m128i(vmovl_u16(vld1_u16(ptr)));
-#elif defined (__SSE4_1__)
- return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr));
-#else
- return vint4(ptr[0],ptr[1],ptr[2],ptr[3]);
-#endif
- }
-
- static __forceinline void store(uint8_t* ptr, const vint4& v) {
-#if defined(__aarch64__)
- int32x4_t x = v;
- uint16x4_t y = vqmovn_u32(uint32x4_t(x));
- uint8x8_t z = vqmovn_u16(vcombine_u16(y, y));
- vst1_lane_u32((uint32_t *)ptr,uint32x2_t(z), 0);
-#elif defined(__SSE4_1__)
- __m128i x = v;
- x = _mm_packus_epi32(x, x);
- x = _mm_packus_epi16(x, x);
- *(int*)ptr = _mm_cvtsi128_si32(x);
-#else
- for (size_t i=0;i<4;i++)
- ptr[i] = (uint8_t)v[i];
-#endif
- }
-
- static __forceinline void store(unsigned short* ptr, const vint4& v) {
-#if defined(__aarch64__)
- uint32x4_t x = uint32x4_t(v.v);
- uint16x4_t y = vqmovn_u32(x);
- vst1_u16(ptr, y);
-#else
- for (size_t i=0;i<4;i++)
- ptr[i] = (unsigned short)v[i];
-#endif
- }
-
- static __forceinline vint4 load_nt(void* ptr) {
-#if defined(__aarch64__) || defined(__SSE4_1__)
- return _mm_stream_load_si128((__m128i*)ptr);
-#else
- return _mm_load_si128((__m128i*)ptr);
-#endif
- }
-
- static __forceinline void store_nt(void* ptr, const vint4& v) {
-#if !defined(__aarch64__) && defined(__SSE4_1__)
- _mm_stream_ps((float*)ptr, _mm_castsi128_ps(v));
-#else
- _mm_store_si128((__m128i*)ptr,v);
-#endif
- }
-
- template<int scale = 4>
- static __forceinline vint4 gather(const int* ptr, const vint4& index) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return _mm_i32gather_epi32(ptr, index, scale);
-#else
- return vint4(
- *(int*)(((int8_t*)ptr)+scale*index[0]),
- *(int*)(((int8_t*)ptr)+scale*index[1]),
- *(int*)(((int8_t*)ptr)+scale*index[2]),
- *(int*)(((int8_t*)ptr)+scale*index[3]));
-#endif
- }
-
- template<int scale = 4>
- static __forceinline vint4 gather(const vboolf4& mask, const int* ptr, const vint4& index) {
- vint4 r = zero;
-#if defined(__AVX512VL__)
- return _mm_mmask_i32gather_epi32(r, mask, index, ptr, scale);
-#elif defined(__AVX2__) && !defined(__aarch64__)
- return _mm_mask_i32gather_epi32(r, ptr, index, mask, scale);
-#else
- if (likely(mask[0])) r[0] = *(int*)(((int8_t*)ptr)+scale*index[0]);
- if (likely(mask[1])) r[1] = *(int*)(((int8_t*)ptr)+scale*index[1]);
- if (likely(mask[2])) r[2] = *(int*)(((int8_t*)ptr)+scale*index[2]);
- if (likely(mask[3])) r[3] = *(int*)(((int8_t*)ptr)+scale*index[3]);
- return r;
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(void* ptr, const vint4& index, const vint4& v)
- {
-#if defined(__AVX512VL__)
- _mm_i32scatter_epi32((int*)ptr, index, v, scale);
-#else
- *(int*)(((int8_t*)ptr)+scale*index[0]) = v[0];
- *(int*)(((int8_t*)ptr)+scale*index[1]) = v[1];
- *(int*)(((int8_t*)ptr)+scale*index[2]) = v[2];
- *(int*)(((int8_t*)ptr)+scale*index[3]) = v[3];
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf4& mask, void* ptr, const vint4& index, const vint4& v)
- {
-#if defined(__AVX512VL__)
- _mm_mask_i32scatter_epi32((int*)ptr, mask, index, v, scale);
-#else
- if (likely(mask[0])) *(int*)(((int8_t*)ptr)+scale*index[0]) = v[0];
- if (likely(mask[1])) *(int*)(((int8_t*)ptr)+scale*index[1]) = v[1];
- if (likely(mask[2])) *(int*)(((int8_t*)ptr)+scale*index[2]) = v[2];
- if (likely(mask[3])) *(int*)(((int8_t*)ptr)+scale*index[3]) = v[3];
-#endif
- }
-
-#if defined(__x86_64__) || defined(__aarch64__)
- static __forceinline vint4 broadcast64(long long a) { return _mm_set1_epi64x(a); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const int& operator [](size_t index) const { assert(index < 4); return i[index]; }
- __forceinline int& operator [](size_t index) { assert(index < 4); return i[index]; }
-
- friend __forceinline vint4 select(const vboolf4& m, const vint4& t, const vint4& f) {
-#if defined(__AVX512VL__)
- return _mm_mask_blend_epi32(m, (__m128i)f, (__m128i)t);
-#elif defined(__aarch64__)
- return _mm_castps_si128(_mm_blendv_ps((__m128)f.v,(__m128) t.v, (__m128)m.v));
-#elif defined(__SSE4_1__)
- return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
-#else
- return _mm_or_si128(_mm_and_si128(m, t), _mm_andnot_si128(m, f));
-#endif
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboolf4 asBool(const vint4& a) { return _mm_movepi32_mask(a); }
-#else
- __forceinline vboolf4 asBool(const vint4& a) { return _mm_castsi128_ps(a); }
-#endif
-
- __forceinline vint4 operator +(const vint4& a) { return a; }
- __forceinline vint4 operator -(const vint4& a) { return _mm_sub_epi32(_mm_setzero_si128(), a); }
-#if defined(__aarch64__)
- __forceinline vint4 abs(const vint4& a) { return vabsq_s32(a.v); }
-#elif defined(__SSSE3__)
- __forceinline vint4 abs(const vint4& a) { return _mm_abs_epi32(a); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint4 operator +(const vint4& a, const vint4& b) { return _mm_add_epi32(a, b); }
- __forceinline vint4 operator +(const vint4& a, int b) { return a + vint4(b); }
- __forceinline vint4 operator +(int a, const vint4& b) { return vint4(a) + b; }
-
- __forceinline vint4 operator -(const vint4& a, const vint4& b) { return _mm_sub_epi32(a, b); }
- __forceinline vint4 operator -(const vint4& a, int b) { return a - vint4(b); }
- __forceinline vint4 operator -(int a, const vint4& b) { return vint4(a) - b; }
-
-#if (defined(__aarch64__)) || defined(__SSE4_1__)
- __forceinline vint4 operator *(const vint4& a, const vint4& b) { return _mm_mullo_epi32(a, b); }
-#else
- __forceinline vint4 operator *(const vint4& a, const vint4& b) { return vint4(a[0]*b[0],a[1]*b[1],a[2]*b[2],a[3]*b[3]); }
-#endif
- __forceinline vint4 operator *(const vint4& a, int b) { return a * vint4(b); }
- __forceinline vint4 operator *(int a, const vint4& b) { return vint4(a) * b; }
-
- __forceinline vint4 operator &(const vint4& a, const vint4& b) { return _mm_and_si128(a, b); }
- __forceinline vint4 operator &(const vint4& a, int b) { return a & vint4(b); }
- __forceinline vint4 operator &(int a, const vint4& b) { return vint4(a) & b; }
-
- __forceinline vint4 operator |(const vint4& a, const vint4& b) { return _mm_or_si128(a, b); }
- __forceinline vint4 operator |(const vint4& a, int b) { return a | vint4(b); }
- __forceinline vint4 operator |(int a, const vint4& b) { return vint4(a) | b; }
-
- __forceinline vint4 operator ^(const vint4& a, const vint4& b) { return _mm_xor_si128(a, b); }
- __forceinline vint4 operator ^(const vint4& a, int b) { return a ^ vint4(b); }
- __forceinline vint4 operator ^(int a, const vint4& b) { return vint4(a) ^ b; }
-
- __forceinline vint4 operator <<(const vint4& a, const int n) { return _mm_slli_epi32(a, n); }
- __forceinline vint4 operator >>(const vint4& a, const int n) { return _mm_srai_epi32(a, n); }
-
- __forceinline vint4 sll (const vint4& a, int b) { return _mm_slli_epi32(a, b); }
- __forceinline vint4 sra (const vint4& a, int b) { return _mm_srai_epi32(a, b); }
- __forceinline vint4 srl (const vint4& a, int b) { return _mm_srli_epi32(a, b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint4& operator +=(vint4& a, const vint4& b) { return a = a + b; }
- __forceinline vint4& operator +=(vint4& a, int b) { return a = a + b; }
-
- __forceinline vint4& operator -=(vint4& a, const vint4& b) { return a = a - b; }
- __forceinline vint4& operator -=(vint4& a, int b) { return a = a - b; }
-
-#if (defined(__aarch64__)) || defined(__SSE4_1__)
- __forceinline vint4& operator *=(vint4& a, const vint4& b) { return a = a * b; }
- __forceinline vint4& operator *=(vint4& a, int b) { return a = a * b; }
-#endif
-
- __forceinline vint4& operator &=(vint4& a, const vint4& b) { return a = a & b; }
- __forceinline vint4& operator &=(vint4& a, int b) { return a = a & b; }
-
- __forceinline vint4& operator |=(vint4& a, const vint4& b) { return a = a | b; }
- __forceinline vint4& operator |=(vint4& a, int b) { return a = a | b; }
-
- __forceinline vint4& operator <<=(vint4& a, int b) { return a = a << b; }
- __forceinline vint4& operator >>=(vint4& a, int b) { return a = a >> b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboolf4 operator ==(const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf4 operator !=(const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboolf4 operator < (const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboolf4 operator >=(const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboolf4 operator > (const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboolf4 operator <=(const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
-#else
- __forceinline vboolf4 operator ==(const vint4& a, const vint4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
- __forceinline vboolf4 operator !=(const vint4& a, const vint4& b) { return !(a == b); }
- __forceinline vboolf4 operator < (const vint4& a, const vint4& b) { return _mm_castsi128_ps(_mm_cmplt_epi32(a, b)); }
- __forceinline vboolf4 operator >=(const vint4& a, const vint4& b) { return !(a < b); }
- __forceinline vboolf4 operator > (const vint4& a, const vint4& b) { return _mm_castsi128_ps(_mm_cmpgt_epi32(a, b)); }
- __forceinline vboolf4 operator <=(const vint4& a, const vint4& b) { return !(a > b); }
-#endif
-
- __forceinline vboolf4 operator ==(const vint4& a, int b) { return a == vint4(b); }
- __forceinline vboolf4 operator ==(int a, const vint4& b) { return vint4(a) == b; }
-
- __forceinline vboolf4 operator !=(const vint4& a, int b) { return a != vint4(b); }
- __forceinline vboolf4 operator !=(int a, const vint4& b) { return vint4(a) != b; }
-
- __forceinline vboolf4 operator < (const vint4& a, int b) { return a < vint4(b); }
- __forceinline vboolf4 operator < (int a, const vint4& b) { return vint4(a) < b; }
-
- __forceinline vboolf4 operator >=(const vint4& a, int b) { return a >= vint4(b); }
- __forceinline vboolf4 operator >=(int a, const vint4& b) { return vint4(a) >= b; }
-
- __forceinline vboolf4 operator > (const vint4& a, int b) { return a > vint4(b); }
- __forceinline vboolf4 operator > (int a, const vint4& b) { return vint4(a) > b; }
-
- __forceinline vboolf4 operator <=(const vint4& a, int b) { return a <= vint4(b); }
- __forceinline vboolf4 operator <=(int a, const vint4& b) { return vint4(a) <= b; }
-
- __forceinline vboolf4 eq(const vint4& a, const vint4& b) { return a == b; }
- __forceinline vboolf4 ne(const vint4& a, const vint4& b) { return a != b; }
- __forceinline vboolf4 lt(const vint4& a, const vint4& b) { return a < b; }
- __forceinline vboolf4 ge(const vint4& a, const vint4& b) { return a >= b; }
- __forceinline vboolf4 gt(const vint4& a, const vint4& b) { return a > b; }
- __forceinline vboolf4 le(const vint4& a, const vint4& b) { return a <= b; }
-
-#if defined(__AVX512VL__)
- __forceinline vboolf4 eq(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_EQ); }
- __forceinline vboolf4 ne(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_NE); }
- __forceinline vboolf4 lt(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); }
- __forceinline vboolf4 ge(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GE); }
- __forceinline vboolf4 gt(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GT); }
- __forceinline vboolf4 le(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LE); }
-#else
- __forceinline vboolf4 eq(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a == b); }
- __forceinline vboolf4 ne(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a != b); }
- __forceinline vboolf4 lt(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a < b); }
- __forceinline vboolf4 ge(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a >= b); }
- __forceinline vboolf4 gt(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a > b); }
- __forceinline vboolf4 le(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a <= b); }
-#endif
-
- template<int mask>
- __forceinline vint4 select(const vint4& t, const vint4& f) {
-#if defined(__SSE4_1__)
- return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), mask));
-#else
- return select(vboolf4(mask), t, f);
-#endif
- }
-
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
- __forceinline vint4 min(const vint4& a, const vint4& b) { return _mm_min_epi32(a, b); }
- __forceinline vint4 max(const vint4& a, const vint4& b) { return _mm_max_epi32(a, b); }
-
- __forceinline vint4 umin(const vint4& a, const vint4& b) { return _mm_min_epu32(a, b); }
- __forceinline vint4 umax(const vint4& a, const vint4& b) { return _mm_max_epu32(a, b); }
-
-#else
- __forceinline vint4 min(const vint4& a, const vint4& b) { return select(a < b,a,b); }
- __forceinline vint4 max(const vint4& a, const vint4& b) { return select(a < b,b,a); }
-#endif
-
- __forceinline vint4 min(const vint4& a, int b) { return min(a,vint4(b)); }
- __forceinline vint4 min(int a, const vint4& b) { return min(vint4(a),b); }
- __forceinline vint4 max(const vint4& a, int b) { return max(a,vint4(b)); }
- __forceinline vint4 max(int a, const vint4& b) { return max(vint4(a),b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint4 unpacklo(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
- __forceinline vint4 unpackhi(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
-
-#if defined(__aarch64__)
- template<int i0, int i1, int i2, int i3>
- __forceinline vint4 shuffle(const vint4& v) {
- return vreinterpretq_s32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3)));
- }
- template<int i0, int i1, int i2, int i3>
- __forceinline vint4 shuffle(const vint4& a, const vint4& b) {
- return vreinterpretq_s32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
- }
-#else
- template<int i0, int i1, int i2, int i3>
- __forceinline vint4 shuffle(const vint4& v) {
- return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
- template<int i0, int i1, int i2, int i3>
- __forceinline vint4 shuffle(const vint4& a, const vint4& b) {
- return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-#endif
-#if defined(__SSE3__)
- template<> __forceinline vint4 shuffle<0, 0, 2, 2>(const vint4& v) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(v))); }
- template<> __forceinline vint4 shuffle<1, 1, 3, 3>(const vint4& v) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(v))); }
- template<> __forceinline vint4 shuffle<0, 1, 0, 1>(const vint4& v) { return _mm_castpd_si128(_mm_movedup_pd (_mm_castsi128_pd(v))); }
-#endif
-
- template<int i>
- __forceinline vint4 shuffle(const vint4& v) {
- return shuffle<i,i,i,i>(v);
- }
-
-#if defined(__aarch64__)
- template<int src> __forceinline int extract(const vint4& b);
- template<int dst> __forceinline vint4 insert(const vint4& a, const int b);
-#elif defined(__SSE4_1__)
- template<int src> __forceinline int extract(const vint4& b) { return _mm_extract_epi32(b, src); }
- template<int dst> __forceinline vint4 insert(const vint4& a, const int b) { return _mm_insert_epi32(a, b, dst); }
-#else
- template<int src> __forceinline int extract(const vint4& b) { return b[src&3]; }
- template<int dst> __forceinline vint4 insert(const vint4& a, int b) { vint4 c = a; c[dst&3] = b; return c; }
-#endif
-
-#if defined(__aarch64__)
- template<> __forceinline int extract<0>(const vint4& b) {
- return b.v[0];
- }
- template<> __forceinline int extract<1>(const vint4& b) {
- return b.v[1];
- }
- template<> __forceinline int extract<2>(const vint4& b) {
- return b.v[2];
- }
- template<> __forceinline int extract<3>(const vint4& b) {
- return b.v[3];
- }
- template<> __forceinline vint4 insert<0>(const vint4& a, int b)
- {
- vint4 c = a;
- c[0] = b;
- return c;
- }
- template<> __forceinline vint4 insert<1>(const vint4& a, int b)
- {
- vint4 c = a;
- c[1] = b;
- return c;
- }
- template<> __forceinline vint4 insert<2>(const vint4& a, int b)
- {
- vint4 c = a;
- c[2] = b;
- return c;
- }
- template<> __forceinline vint4 insert<3>(const vint4& a, int b)
- {
- vint4 c = a;
- c[3] = b;
- return c;
- }
-
- __forceinline int toScalar(const vint4& v) {
- return v[0];
- }
-
- __forceinline size_t toSizeT(const vint4& v) {
- uint64x2_t x = uint64x2_t(v.v);
- return x[0];
- }
-#else
- template<> __forceinline int extract<0>(const vint4& b) { return _mm_cvtsi128_si32(b); }
-
- __forceinline int toScalar(const vint4& v) { return _mm_cvtsi128_si32(v); }
-
- __forceinline size_t toSizeT(const vint4& v) {
-#if defined(__WIN32__) && !defined(__X86_64__) // win32 workaround
- return toScalar(v);
-#elif defined(__ARM_NEON)
- // FIXME(LTE): Do we need a swap(i.e. use lane 1)?
- return vgetq_lane_u64(*(reinterpret_cast<const uint64x2_t *>(&v)), 0);
-#else
- return _mm_cvtsi128_si64(v);
-#endif
- }
-#endif
-
-#if defined(__AVX512VL__)
-
- __forceinline vint4 permute(const vint4 &a, const vint4 &index) {
- return _mm_castps_si128(_mm_permutevar_ps(_mm_castsi128_ps(a),index));
- }
-
- template<int i>
- __forceinline vint4 align_shift_right(const vint4& a, const vint4& b) {
- return _mm_alignr_epi32(a, b, i);
- }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__aarch64__) || defined(__SSE4_1__)
-
-#if defined(__aarch64__)
- __forceinline vint4 vreduce_min(const vint4& v) { int h = vminvq_s32(v); return vdupq_n_s32(h); }
- __forceinline vint4 vreduce_max(const vint4& v) { int h = vmaxvq_s32(v); return vdupq_n_s32(h); }
- __forceinline vint4 vreduce_add(const vint4& v) { int h = vaddvq_s32(v); return vdupq_n_s32(h); }
-
- __forceinline int reduce_min(const vint4& v) { return vminvq_s32(v); }
- __forceinline int reduce_max(const vint4& v) { return vmaxvq_s32(v); }
- __forceinline int reduce_add(const vint4& v) { return vaddvq_s32(v); }
-#else
- __forceinline vint4 vreduce_min(const vint4& v) { vint4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
- __forceinline vint4 vreduce_max(const vint4& v) { vint4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
- __forceinline vint4 vreduce_add(const vint4& v) { vint4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
-
- __forceinline int reduce_min(const vint4& v) { return toScalar(vreduce_min(v)); }
- __forceinline int reduce_max(const vint4& v) { return toScalar(vreduce_max(v)); }
- __forceinline int reduce_add(const vint4& v) { return toScalar(vreduce_add(v)); }
-#endif
-
- __forceinline size_t select_min(const vint4& v) { return bsf(movemask(v == vreduce_min(v))); }
- __forceinline size_t select_max(const vint4& v) { return bsf(movemask(v == vreduce_max(v))); }
-
- __forceinline size_t select_min(const vboolf4& valid, const vint4& v) { const vint4 a = select(valid,v,vint4(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
- __forceinline size_t select_max(const vboolf4& valid, const vint4& v) { const vint4 a = select(valid,v,vint4(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
-
-#else
-
- __forceinline int reduce_min(const vint4& v) { return min(v[0],v[1],v[2],v[3]); }
- __forceinline int reduce_max(const vint4& v) { return max(v[0],v[1],v[2],v[3]); }
- __forceinline int reduce_add(const vint4& v) { return v[0]+v[1]+v[2]+v[3]; }
-
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Sorting networks
- ////////////////////////////////////////////////////////////////////////////////
-
-#if (defined(__aarch64__)) || defined(__SSE4_1__)
-
- __forceinline vint4 usort_ascending(const vint4& v)
- {
- const vint4 a0 = v;
- const vint4 b0 = shuffle<1,0,3,2>(a0);
- const vint4 c0 = umin(a0,b0);
- const vint4 d0 = umax(a0,b0);
- const vint4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
- const vint4 b1 = shuffle<2,3,0,1>(a1);
- const vint4 c1 = umin(a1,b1);
- const vint4 d1 = umax(a1,b1);
- const vint4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
- const vint4 b2 = shuffle<0,2,1,3>(a2);
- const vint4 c2 = umin(a2,b2);
- const vint4 d2 = umax(a2,b2);
- const vint4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
- return a3;
- }
-
- __forceinline vint4 usort_descending(const vint4& v)
- {
- const vint4 a0 = v;
- const vint4 b0 = shuffle<1,0,3,2>(a0);
- const vint4 c0 = umax(a0,b0);
- const vint4 d0 = umin(a0,b0);
- const vint4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
- const vint4 b1 = shuffle<2,3,0,1>(a1);
- const vint4 c1 = umax(a1,b1);
- const vint4 d1 = umin(a1,b1);
- const vint4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
- const vint4 b2 = shuffle<0,2,1,3>(a2);
- const vint4 c2 = umax(a2,b2);
- const vint4 d2 = umin(a2,b2);
- const vint4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
- return a3;
- }
-
-#else
-
- __forceinline vint4 usort_ascending(const vint4& v)
- {
- const vint4 a0 = v-vint4(0x80000000);
- const vint4 b0 = shuffle<1,0,3,2>(a0);
- const vint4 c0 = min(a0,b0);
- const vint4 d0 = max(a0,b0);
- const vint4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
- const vint4 b1 = shuffle<2,3,0,1>(a1);
- const vint4 c1 = min(a1,b1);
- const vint4 d1 = max(a1,b1);
- const vint4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
- const vint4 b2 = shuffle<0,2,1,3>(a2);
- const vint4 c2 = min(a2,b2);
- const vint4 d2 = max(a2,b2);
- const vint4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
- return a3+vint4(0x80000000);
- }
-
- __forceinline vint4 usort_descending(const vint4& v)
- {
- const vint4 a0 = v-vint4(0x80000000);
- const vint4 b0 = shuffle<1,0,3,2>(a0);
- const vint4 c0 = max(a0,b0);
- const vint4 d0 = min(a0,b0);
- const vint4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
- const vint4 b1 = shuffle<2,3,0,1>(a1);
- const vint4 c1 = max(a1,b1);
- const vint4 d1 = min(a1,b1);
- const vint4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
- const vint4 b2 = shuffle<0,2,1,3>(a2);
- const vint4 c2 = max(a2,b2);
- const vint4 d2 = min(a2,b2);
- const vint4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
- return a3+vint4(0x80000000);
- }
-
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vint4& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
- }
-}
-
diff --git a/thirdparty/embree-aarch64/common/simd/vint8_avx.h b/thirdparty/embree-aarch64/common/simd/vint8_avx.h
deleted file mode 100644
index 25a771284d..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vint8_avx.h
+++ /dev/null
@@ -1,464 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX integer type */
- template<>
- struct vint<8>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboolf8 Bool;
- typedef vint8 Int;
- typedef vfloat8 Float;
-
- enum { size = 8 }; // number of SIMD elements
- union { // data
- __m256i v;
- struct { __m128i vl,vh; };
- int i[8];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint() {}
- __forceinline vint(const vint8& a) { v = a.v; }
- __forceinline vint8& operator =(const vint8& a) { v = a.v; return *this; }
-
- __forceinline vint(__m256i a) : v(a) {}
- __forceinline operator const __m256i&() const { return v; }
- __forceinline operator __m256i&() { return v; }
-
- __forceinline explicit vint(const vint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
- __forceinline vint(const vint4& a, const vint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
- __forceinline vint(const __m128i& a, const __m128i& b) : vl(a), vh(b) {}
-
- __forceinline explicit vint(const int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
- __forceinline vint(int a) : v(_mm256_set1_epi32(a)) {}
- __forceinline vint(int a, int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
- __forceinline vint(int a, int b, int c, int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
- __forceinline vint(int a, int b, int c, int d, int e, int f, int g, int vh) : v(_mm256_set_epi32(vh, g, f, e, d, c, b, a)) {}
-
- __forceinline explicit vint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint(ZeroTy) : v(_mm256_setzero_si256()) {}
- __forceinline vint(OneTy) : v(_mm256_set_epi32(1,1,1,1,1,1,1,1)) {}
- __forceinline vint(PosInfTy) : v(_mm256_set_epi32(pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf)) {}
- __forceinline vint(NegInfTy) : v(_mm256_set_epi32(neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf)) {}
- __forceinline vint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
- __forceinline vint(ReverseStepTy) : v(_mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7)) {}
- __forceinline vint(UndefinedTy) : v(_mm256_undefined_si256()) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vint8 load (const void* a) { return _mm256_castps_si256(_mm256_load_ps((float*)a)); }
- static __forceinline vint8 loadu(const void* a) { return _mm256_castps_si256(_mm256_loadu_ps((float*)a)); }
-
- static __forceinline vint8 load (const vboolf8& mask, const void* a) { return _mm256_castps_si256(_mm256_maskload_ps((float*)a,mask)); }
- static __forceinline vint8 loadu(const vboolf8& mask, const void* a) { return _mm256_castps_si256(_mm256_maskload_ps((float*)a,mask)); }
-
- static __forceinline void store (void* ptr, const vint8& f) { _mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f)); }
- static __forceinline void storeu(void* ptr, const vint8& f) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f)); }
-
-#if !defined(__aarch64__)
- static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
-#else
- static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask.v,_mm256_castsi256_ps(f)); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask.v,_mm256_castsi256_ps(f)); }
-#endif
-
- static __forceinline void store_nt(void* ptr, const vint8& v) {
- _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
- }
-
- static __forceinline vint8 load(const uint8_t* ptr) {
- vint4 il = vint4::load(ptr+0);
- vint4 ih = vint4::load(ptr+4);
- return vint8(il,ih);
- }
-
- static __forceinline vint8 loadu(const uint8_t* ptr) {
- vint4 il = vint4::loadu(ptr+0);
- vint4 ih = vint4::loadu(ptr+4);
- return vint8(il,ih);
- }
-
- static __forceinline vint8 load(const unsigned short* ptr) {
- vint4 il = vint4::load(ptr+0);
- vint4 ih = vint4::load(ptr+4);
- return vint8(il,ih);
- }
-
- static __forceinline vint8 loadu(const unsigned short* ptr) {
- vint4 il = vint4::loadu(ptr+0);
- vint4 ih = vint4::loadu(ptr+4);
- return vint8(il,ih);
- }
-
- static __forceinline void store(uint8_t* ptr, const vint8& i) {
- vint4 il(i.vl);
- vint4 ih(i.vh);
- vint4::store(ptr + 0,il);
- vint4::store(ptr + 4,ih);
- }
-
- static __forceinline void store(unsigned short* ptr, const vint8& v) {
- for (size_t i=0;i<8;i++)
- ptr[i] = (unsigned short)v[i];
- }
-
- template<int scale = 4>
- static __forceinline vint8 gather(const int* ptr, const vint8& index) {
- return vint8(
- *(int*)(((int8_t*)ptr)+scale*index[0]),
- *(int*)(((int8_t*)ptr)+scale*index[1]),
- *(int*)(((int8_t*)ptr)+scale*index[2]),
- *(int*)(((int8_t*)ptr)+scale*index[3]),
- *(int*)(((int8_t*)ptr)+scale*index[4]),
- *(int*)(((int8_t*)ptr)+scale*index[5]),
- *(int*)(((int8_t*)ptr)+scale*index[6]),
- *(int*)(((int8_t*)ptr)+scale*index[7]));
- }
-
- template<int scale = 4>
- static __forceinline vint8 gather(const vboolf8& mask, const int* ptr, const vint8& index) {
- vint8 r = zero;
- if (likely(mask[0])) r[0] = *(int*)(((int8_t*)ptr)+scale*index[0]);
- if (likely(mask[1])) r[1] = *(int*)(((int8_t*)ptr)+scale*index[1]);
- if (likely(mask[2])) r[2] = *(int*)(((int8_t*)ptr)+scale*index[2]);
- if (likely(mask[3])) r[3] = *(int*)(((int8_t*)ptr)+scale*index[3]);
- if (likely(mask[4])) r[4] = *(int*)(((int8_t*)ptr)+scale*index[4]);
- if (likely(mask[5])) r[5] = *(int*)(((int8_t*)ptr)+scale*index[5]);
- if (likely(mask[6])) r[6] = *(int*)(((int8_t*)ptr)+scale*index[6]);
- if (likely(mask[7])) r[7] = *(int*)(((int8_t*)ptr)+scale*index[7]);
- return r;
- }
-
- template<int scale = 4>
- static __forceinline void scatter(void* ptr, const vint8& ofs, const vint8& v)
- {
- *(int*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- *(int*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- *(int*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- *(int*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- *(int*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- *(int*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- *(int*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- *(int*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vint8& v)
- {
- if (likely(mask[0])) *(int*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- if (likely(mask[1])) *(int*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- if (likely(mask[2])) *(int*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- if (likely(mask[3])) *(int*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- if (likely(mask[4])) *(int*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- if (likely(mask[5])) *(int*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- if (likely(mask[6])) *(int*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- if (likely(mask[7])) *(int*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
- }
-
-
- static __forceinline vint8 broadcast64(const long long& a) { return _mm256_set1_epi64x(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const int& operator [](size_t index) const { assert(index < 8); return i[index]; }
- __forceinline int& operator [](size_t index) { assert(index < 8); return i[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 asBool(const vint8& a) { return _mm256_castsi256_ps(a); }
-
- __forceinline vint8 operator +(const vint8& a) { return a; }
- __forceinline vint8 operator -(const vint8& a) { return vint8(_mm_sub_epi32(_mm_setzero_si128(), a.vl), _mm_sub_epi32(_mm_setzero_si128(), a.vh)); }
- __forceinline vint8 abs (const vint8& a) { return vint8(_mm_abs_epi32(a.vl), _mm_abs_epi32(a.vh)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8 operator +(const vint8& a, const vint8& b) { return vint8(_mm_add_epi32(a.vl, b.vl), _mm_add_epi32(a.vh, b.vh)); }
- __forceinline vint8 operator +(const vint8& a, int b) { return a + vint8(b); }
- __forceinline vint8 operator +(int a, const vint8& b) { return vint8(a) + b; }
-
- __forceinline vint8 operator -(const vint8& a, const vint8& b) { return vint8(_mm_sub_epi32(a.vl, b.vl), _mm_sub_epi32(a.vh, b.vh)); }
- __forceinline vint8 operator -(const vint8& a, int b) { return a - vint8(b); }
- __forceinline vint8 operator -(int a, const vint8& b) { return vint8(a) - b; }
-
- __forceinline vint8 operator *(const vint8& a, const vint8& b) { return vint8(_mm_mullo_epi32(a.vl, b.vl), _mm_mullo_epi32(a.vh, b.vh)); }
- __forceinline vint8 operator *(const vint8& a, int b) { return a * vint8(b); }
- __forceinline vint8 operator *(int a, const vint8& b) { return vint8(a) * b; }
-
- __forceinline vint8 operator &(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_and_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
- __forceinline vint8 operator &(const vint8& a, int b) { return a & vint8(b); }
- __forceinline vint8 operator &(int a, const vint8& b) { return vint8(a) & b; }
-
- __forceinline vint8 operator |(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_or_ps (_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
- __forceinline vint8 operator |(const vint8& a, int b) { return a | vint8(b); }
- __forceinline vint8 operator |(int a, const vint8& b) { return vint8(a) | b; }
-
- __forceinline vint8 operator ^(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
- __forceinline vint8 operator ^(const vint8& a, int b) { return a ^ vint8(b); }
- __forceinline vint8 operator ^(int a, const vint8& b) { return vint8(a) ^ b; }
-
- __forceinline vint8 operator <<(const vint8& a, int n) { return vint8(_mm_slli_epi32(a.vl, n), _mm_slli_epi32(a.vh, n)); }
- __forceinline vint8 operator >>(const vint8& a, int n) { return vint8(_mm_srai_epi32(a.vl, n), _mm_srai_epi32(a.vh, n)); }
-
- __forceinline vint8 sll (const vint8& a, int b) { return vint8(_mm_slli_epi32(a.vl, b), _mm_slli_epi32(a.vh, b)); }
- __forceinline vint8 sra (const vint8& a, int b) { return vint8(_mm_srai_epi32(a.vl, b), _mm_srai_epi32(a.vh, b)); }
- __forceinline vint8 srl (const vint8& a, int b) { return vint8(_mm_srli_epi32(a.vl, b), _mm_srli_epi32(a.vh, b)); }
-
- __forceinline vint8 min(const vint8& a, const vint8& b) { return vint8(_mm_min_epi32(a.vl, b.vl), _mm_min_epi32(a.vh, b.vh)); }
- __forceinline vint8 min(const vint8& a, int b) { return min(a,vint8(b)); }
- __forceinline vint8 min(int a, const vint8& b) { return min(vint8(a),b); }
-
- __forceinline vint8 max(const vint8& a, const vint8& b) { return vint8(_mm_max_epi32(a.vl, b.vl), _mm_max_epi32(a.vh, b.vh)); }
- __forceinline vint8 max(const vint8& a, int b) { return max(a,vint8(b)); }
- __forceinline vint8 max(int a, const vint8& b) { return max(vint8(a),b); }
-
- __forceinline vint8 umin(const vint8& a, const vint8& b) { return vint8(_mm_min_epu32(a.vl, b.vl), _mm_min_epu32(a.vh, b.vh)); }
- __forceinline vint8 umin(const vint8& a, int b) { return umin(a,vint8(b)); }
- __forceinline vint8 umin(int a, const vint8& b) { return umin(vint8(a),b); }
-
- __forceinline vint8 umax(const vint8& a, const vint8& b) { return vint8(_mm_max_epu32(a.vl, b.vl), _mm_max_epu32(a.vh, b.vh)); }
- __forceinline vint8 umax(const vint8& a, int b) { return umax(a,vint8(b)); }
- __forceinline vint8 umax(int a, const vint8& b) { return umax(vint8(a),b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8& operator +=(vint8& a, const vint8& b) { return a = a + b; }
- __forceinline vint8& operator +=(vint8& a, int b) { return a = a + b; }
-
- __forceinline vint8& operator -=(vint8& a, const vint8& b) { return a = a - b; }
- __forceinline vint8& operator -=(vint8& a, int b) { return a = a - b; }
-
- __forceinline vint8& operator *=(vint8& a, const vint8& b) { return a = a * b; }
- __forceinline vint8& operator *=(vint8& a, int b) { return a = a * b; }
-
- __forceinline vint8& operator &=(vint8& a, const vint8& b) { return a = a & b; }
- __forceinline vint8& operator &=(vint8& a, int b) { return a = a & b; }
-
- __forceinline vint8& operator |=(vint8& a, const vint8& b) { return a = a | b; }
- __forceinline vint8& operator |=(vint8& a, int b) { return a = a | b; }
-
- __forceinline vint8& operator <<=(vint8& a, int b) { return a = a << b; }
- __forceinline vint8& operator >>=(vint8& a, int b) { return a = a >> b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmpeq_epi32 (a.vl, b.vl)),
- _mm_castsi128_ps(_mm_cmpeq_epi32 (a.vh, b.vh))); }
- __forceinline vboolf8 operator ==(const vint8& a, int b) { return a == vint8(b); }
- __forceinline vboolf8 operator ==(int a, const vint8& b) { return vint8(a) == b; }
-
- __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return !(a == b); }
- __forceinline vboolf8 operator !=(const vint8& a, int b) { return a != vint8(b); }
- __forceinline vboolf8 operator !=(int a, const vint8& b) { return vint8(a) != b; }
-
- __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmplt_epi32 (a.vl, b.vl)),
- _mm_castsi128_ps(_mm_cmplt_epi32 (a.vh, b.vh))); }
- __forceinline vboolf8 operator < (const vint8& a, int b) { return a < vint8(b); }
- __forceinline vboolf8 operator < (int a, const vint8& b) { return vint8(a) < b; }
-
- __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return !(a < b); }
- __forceinline vboolf8 operator >=(const vint8& a, int b) { return a >= vint8(b); }
- __forceinline vboolf8 operator >=(int a, const vint8& b) { return vint8(a) >= b; }
-
- __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmpgt_epi32 (a.vl, b.vl)),
- _mm_castsi128_ps(_mm_cmpgt_epi32 (a.vh, b.vh))); }
- __forceinline vboolf8 operator > (const vint8& a, int b) { return a > vint8(b); }
- __forceinline vboolf8 operator > (int a, const vint8& b) { return vint8(a) > b; }
-
- __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return !(a > b); }
- __forceinline vboolf8 operator <=(const vint8& a, int b) { return a <= vint8(b); }
- __forceinline vboolf8 operator <=(int a, const vint8& b) { return vint8(a) <= b; }
-
- __forceinline vboolf8 eq(const vint8& a, const vint8& b) { return a == b; }
- __forceinline vboolf8 ne(const vint8& a, const vint8& b) { return a != b; }
- __forceinline vboolf8 lt(const vint8& a, const vint8& b) { return a < b; }
- __forceinline vboolf8 ge(const vint8& a, const vint8& b) { return a >= b; }
- __forceinline vboolf8 gt(const vint8& a, const vint8& b) { return a > b; }
- __forceinline vboolf8 le(const vint8& a, const vint8& b) { return a <= b; }
-
- __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a == b); }
- __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a != b); }
- __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a < b); }
- __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a >= b); }
- __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a > b); }
- __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a <= b); }
-
- __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) {
- return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
- }
-
- __forceinline vint8 notand(const vboolf8& m, const vint8& f) {
- return _mm256_castps_si256(_mm256_andnot_ps(m, _mm256_castsi256_ps(f)));
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8 unpacklo(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_unpacklo_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
- __forceinline vint8 unpackhi(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_unpackhi_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
-
- template<int i>
- __forceinline vint8 shuffle(const vint8& v) {
- return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
- }
-
- template<int i0, int i1>
- __forceinline vint8 shuffle4(const vint8& v) {
- return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1>
- __forceinline vint8 shuffle4(const vint8& a, const vint8& b) {
- return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vint8 shuffle(const vint8& v) {
- return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vint8 shuffle(const vint8& a, const vint8& b) {
- return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<> __forceinline vint8 shuffle<0, 0, 2, 2>(const vint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
- template<> __forceinline vint8 shuffle<1, 1, 3, 3>(const vint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
- template<> __forceinline vint8 shuffle<0, 1, 0, 1>(const vint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
-
- __forceinline vint8 broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
- template<int i> __forceinline vint8 insert4(const vint8& a, const vint4& b) { return _mm256_insertf128_si256(a, b, i); }
- template<int i> __forceinline vint4 extract4(const vint8& a) { return _mm256_extractf128_si256(a, i); }
- template<> __forceinline vint4 extract4<0>(const vint8& a) { return _mm256_castsi256_si128(a); }
-
- __forceinline int toScalar(const vint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8 vreduce_min2(const vint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
- __forceinline vint8 vreduce_min4(const vint8& v) { vint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
- __forceinline vint8 vreduce_min (const vint8& v) { vint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
-
- __forceinline vint8 vreduce_max2(const vint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
- __forceinline vint8 vreduce_max4(const vint8& v) { vint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
- __forceinline vint8 vreduce_max (const vint8& v) { vint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
-
- __forceinline vint8 vreduce_add2(const vint8& v) { return v + shuffle<1,0,3,2>(v); }
- __forceinline vint8 vreduce_add4(const vint8& v) { vint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
- __forceinline vint8 vreduce_add (const vint8& v) { vint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
-
- __forceinline int reduce_min(const vint8& v) { return toScalar(vreduce_min(v)); }
- __forceinline int reduce_max(const vint8& v) { return toScalar(vreduce_max(v)); }
- __forceinline int reduce_add(const vint8& v) { return toScalar(vreduce_add(v)); }
-
- __forceinline size_t select_min(const vint8& v) { return bsf(movemask(v == vreduce_min(v))); }
- __forceinline size_t select_max(const vint8& v) { return bsf(movemask(v == vreduce_max(v))); }
-
- __forceinline size_t select_min(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
- __forceinline size_t select_max(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Sorting networks
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8 usort_ascending(const vint8& v)
- {
- const vint8 a0 = v;
- const vint8 b0 = shuffle<1,0,3,2>(a0);
- const vint8 c0 = umin(a0,b0);
- const vint8 d0 = umax(a0,b0);
- const vint8 a1 = select(0x99 /* 0b10011001 */,c0,d0);
- const vint8 b1 = shuffle<2,3,0,1>(a1);
- const vint8 c1 = umin(a1,b1);
- const vint8 d1 = umax(a1,b1);
- const vint8 a2 = select(0xc3 /* 0b11000011 */,c1,d1);
- const vint8 b2 = shuffle<1,0,3,2>(a2);
- const vint8 c2 = umin(a2,b2);
- const vint8 d2 = umax(a2,b2);
- const vint8 a3 = select(0xa5 /* 0b10100101 */,c2,d2);
- const vint8 b3 = shuffle4<1,0>(a3);
- const vint8 c3 = umin(a3,b3);
- const vint8 d3 = umax(a3,b3);
- const vint8 a4 = select(0xf /* 0b00001111 */,c3,d3);
- const vint8 b4 = shuffle<2,3,0,1>(a4);
- const vint8 c4 = umin(a4,b4);
- const vint8 d4 = umax(a4,b4);
- const vint8 a5 = select(0x33 /* 0b00110011 */,c4,d4);
- const vint8 b5 = shuffle<1,0,3,2>(a5);
- const vint8 c5 = umin(a5,b5);
- const vint8 d5 = umax(a5,b5);
- const vint8 a6 = select(0x55 /* 0b01010101 */,c5,d5);
- return a6;
- }
-
- __forceinline vint8 usort_descending(const vint8& v)
- {
- const vint8 a0 = v;
- const vint8 b0 = shuffle<1,0,3,2>(a0);
- const vint8 c0 = umax(a0,b0);
- const vint8 d0 = umin(a0,b0);
- const vint8 a1 = select(0x99 /* 0b10011001 */,c0,d0);
- const vint8 b1 = shuffle<2,3,0,1>(a1);
- const vint8 c1 = umax(a1,b1);
- const vint8 d1 = umin(a1,b1);
- const vint8 a2 = select(0xc3 /* 0b11000011 */,c1,d1);
- const vint8 b2 = shuffle<1,0,3,2>(a2);
- const vint8 c2 = umax(a2,b2);
- const vint8 d2 = umin(a2,b2);
- const vint8 a3 = select(0xa5 /* 0b10100101 */,c2,d2);
- const vint8 b3 = shuffle4<1,0>(a3);
- const vint8 c3 = umax(a3,b3);
- const vint8 d3 = umin(a3,b3);
- const vint8 a4 = select(0xf /* 0b00001111 */,c3,d3);
- const vint8 b4 = shuffle<2,3,0,1>(a4);
- const vint8 c4 = umax(a4,b4);
- const vint8 d4 = umin(a4,b4);
- const vint8 a5 = select(0x33 /* 0b00110011 */,c4,d4);
- const vint8 b5 = shuffle<1,0,3,2>(a5);
- const vint8 c5 = umax(a5,b5);
- const vint8 d5 = umin(a5,b5);
- const vint8 a6 = select(0x55 /* 0b01010101 */,c5,d5);
- return a6;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vint8& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vint8_avx2.h b/thirdparty/embree-aarch64/common/simd/vint8_avx2.h
deleted file mode 100644
index 4937d972cf..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vint8_avx2.h
+++ /dev/null
@@ -1,512 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX integer type */
- template<>
- struct vint<8>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboolf8 Bool;
- typedef vint8 Int;
- typedef vfloat8 Float;
-
- enum { size = 8 }; // number of SIMD elements
- union { // data
- __m256i v;
- int i[8];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint() {}
- __forceinline vint(const vint8& a) { v = a.v; }
- __forceinline vint8& operator =(const vint8& a) { v = a.v; return *this; }
-
- __forceinline vint(__m256i a) : v(a) {}
- __forceinline operator const __m256i&() const { return v; }
- __forceinline operator __m256i&() { return v; }
-
- __forceinline explicit vint(const vint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
- __forceinline vint(const vint4& a, const vint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
- __forceinline vint(const __m128i& a, const __m128i& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
-
- __forceinline explicit vint(const int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
- __forceinline vint(int a) : v(_mm256_set1_epi32(a)) {}
- __forceinline vint(int a, int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
- __forceinline vint(int a, int b, int c, int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
- __forceinline vint(int a, int b, int c, int d, int e, int f, int g, int h) : v(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
-
- __forceinline explicit vint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
-
-#if defined(__AVX512VL__)
- __forceinline explicit vint(const vboolf8& a) : v(_mm256_movm_epi32(a)) {}
-#else
- __forceinline explicit vint(const vboolf8& a) : v(_mm256_castps_si256((__m256)a)) {}
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint(ZeroTy) : v(_mm256_setzero_si256()) {}
- __forceinline vint(OneTy) : v(_mm256_set1_epi32(1)) {}
- __forceinline vint(PosInfTy) : v(_mm256_set1_epi32(pos_inf)) {}
- __forceinline vint(NegInfTy) : v(_mm256_set1_epi32(neg_inf)) {}
- __forceinline vint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
- __forceinline vint(ReverseStepTy) : v(_mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7)) {}
- __forceinline vint(UndefinedTy) : v(_mm256_undefined_si256()) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vint8 load(const uint8_t* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
- static __forceinline vint8 loadu(const uint8_t* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
- static __forceinline vint8 load(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_load_si128((__m128i*)ptr)); }
- static __forceinline vint8 loadu(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr)); }
-
- static __forceinline vint8 load(const void* ptr) { return _mm256_load_si256((__m256i*)ptr); }
- static __forceinline vint8 loadu(const void* ptr) { return _mm256_loadu_si256((__m256i*)ptr); }
-
- static __forceinline void store (void* ptr, const vint8& v) { _mm256_store_si256((__m256i*)ptr,v); }
- static __forceinline void storeu(void* ptr, const vint8& v) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(v)); }
-
-#if defined(__AVX512VL__)
-
- static __forceinline vint8 compact(const vboolf8& mask, vint8 &v) {
- return _mm256_mask_compress_epi32(v, mask, v);
- }
- static __forceinline vint8 compact(const vboolf8& mask, vint8 &a, const vint8& b) {
- return _mm256_mask_compress_epi32(a, mask, b);
- }
-
- static __forceinline vint8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_epi32 (_mm256_setzero_si256(),mask,ptr); }
- static __forceinline vint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_epi32(_mm256_setzero_si256(),mask,ptr); }
-
- static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& v) { _mm256_mask_store_epi32 (ptr,mask,v); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& v) { _mm256_mask_storeu_epi32(ptr,mask,v); }
-#else
- static __forceinline vint8 load (const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
- static __forceinline vint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
-
- static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
-#endif
-
- static __forceinline vint8 load_nt(void* ptr) {
- return _mm256_stream_load_si256((__m256i*)ptr);
- }
-
- static __forceinline void store_nt(void* ptr, const vint8& v) {
- _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
- }
-
- static __forceinline void store(uint8_t* ptr, const vint8& i)
- {
- for (size_t j=0; j<8; j++)
- ptr[j] = i[j];
- }
-
- static __forceinline void store(unsigned short* ptr, const vint8& v) {
- for (size_t i=0;i<8;i++)
- ptr[i] = (unsigned short)v[i];
- }
-
- template<int scale = 4>
- static __forceinline vint8 gather(const int *const ptr, const vint8& index) {
- return _mm256_i32gather_epi32(ptr, index, scale);
- }
-
- template<int scale = 4>
- static __forceinline vint8 gather(const vboolf8& mask, const int *const ptr, const vint8& index) {
- vint8 r = zero;
-#if defined(__AVX512VL__)
- return _mm256_mmask_i32gather_epi32(r, mask, index, ptr, scale);
-#else
- return _mm256_mask_i32gather_epi32(r, ptr, index, mask, scale);
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(void* ptr, const vint8& ofs, const vint8& v)
- {
-#if defined(__AVX512VL__)
- _mm256_i32scatter_epi32((int*)ptr, ofs, v, scale);
-#else
- *(int*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- *(int*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- *(int*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- *(int*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- *(int*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- *(int*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- *(int*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- *(int*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vint8& v)
- {
-#if defined(__AVX512VL__)
- _mm256_mask_i32scatter_epi32((int*)ptr, mask, ofs, v, scale);
-#else
- if (likely(mask[0])) *(int*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- if (likely(mask[1])) *(int*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- if (likely(mask[2])) *(int*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- if (likely(mask[3])) *(int*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- if (likely(mask[4])) *(int*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- if (likely(mask[5])) *(int*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- if (likely(mask[6])) *(int*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- if (likely(mask[7])) *(int*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
-#endif
- }
-
- static __forceinline vint8 broadcast64(const long long &a) { return _mm256_set1_epi64x(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const int& operator [](size_t index) const { assert(index < 8); return i[index]; }
- __forceinline int& operator [](size_t index) { assert(index < 8); return i[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- static __forceinline vboolf8 asBool(const vint8& a) { return _mm256_movepi32_mask(a); }
-#else
- static __forceinline vboolf8 asBool(const vint8& a) { return _mm256_castsi256_ps(a); }
-#endif
-
- __forceinline vint8 operator +(const vint8& a) { return a; }
- __forceinline vint8 operator -(const vint8& a) { return _mm256_sub_epi32(_mm256_setzero_si256(), a); }
- __forceinline vint8 abs (const vint8& a) { return _mm256_abs_epi32(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8 operator +(const vint8& a, const vint8& b) { return _mm256_add_epi32(a, b); }
- __forceinline vint8 operator +(const vint8& a, int b) { return a + vint8(b); }
- __forceinline vint8 operator +(int a, const vint8& b) { return vint8(a) + b; }
-
- __forceinline vint8 operator -(const vint8& a, const vint8& b) { return _mm256_sub_epi32(a, b); }
- __forceinline vint8 operator -(const vint8& a, int b) { return a - vint8(b); }
- __forceinline vint8 operator -(int a, const vint8& b) { return vint8(a) - b; }
-
- __forceinline vint8 operator *(const vint8& a, const vint8& b) { return _mm256_mullo_epi32(a, b); }
- __forceinline vint8 operator *(const vint8& a, int b) { return a * vint8(b); }
- __forceinline vint8 operator *(int a, const vint8& b) { return vint8(a) * b; }
-
- __forceinline vint8 operator &(const vint8& a, const vint8& b) { return _mm256_and_si256(a, b); }
- __forceinline vint8 operator &(const vint8& a, int b) { return a & vint8(b); }
- __forceinline vint8 operator &(int a, const vint8& b) { return vint8(a) & b; }
-
- __forceinline vint8 operator |(const vint8& a, const vint8& b) { return _mm256_or_si256(a, b); }
- __forceinline vint8 operator |(const vint8& a, int b) { return a | vint8(b); }
- __forceinline vint8 operator |(int a, const vint8& b) { return vint8(a) | b; }
-
- __forceinline vint8 operator ^(const vint8& a, const vint8& b) { return _mm256_xor_si256(a, b); }
- __forceinline vint8 operator ^(const vint8& a, int b) { return a ^ vint8(b); }
- __forceinline vint8 operator ^(int a, const vint8& b) { return vint8(a) ^ b; }
-
- __forceinline vint8 operator <<(const vint8& a, int n) { return _mm256_slli_epi32(a, n); }
- __forceinline vint8 operator >>(const vint8& a, int n) { return _mm256_srai_epi32(a, n); }
-
- __forceinline vint8 operator <<(const vint8& a, const vint8& n) { return _mm256_sllv_epi32(a, n); }
- __forceinline vint8 operator >>(const vint8& a, const vint8& n) { return _mm256_srav_epi32(a, n); }
-
- __forceinline vint8 sll(const vint8& a, int b) { return _mm256_slli_epi32(a, b); }
- __forceinline vint8 sra(const vint8& a, int b) { return _mm256_srai_epi32(a, b); }
- __forceinline vint8 srl(const vint8& a, int b) { return _mm256_srli_epi32(a, b); }
-
- __forceinline vint8 sll(const vint8& a, const vint8& b) { return _mm256_sllv_epi32(a, b); }
- __forceinline vint8 sra(const vint8& a, const vint8& b) { return _mm256_srav_epi32(a, b); }
- __forceinline vint8 srl(const vint8& a, const vint8& b) { return _mm256_srlv_epi32(a, b); }
-
- __forceinline vint8 min(const vint8& a, const vint8& b) { return _mm256_min_epi32(a, b); }
- __forceinline vint8 min(const vint8& a, int b) { return min(a,vint8(b)); }
- __forceinline vint8 min(int a, const vint8& b) { return min(vint8(a),b); }
-
- __forceinline vint8 max(const vint8& a, const vint8& b) { return _mm256_max_epi32(a, b); }
- __forceinline vint8 max(const vint8& a, int b) { return max(a,vint8(b)); }
- __forceinline vint8 max(int a, const vint8& b) { return max(vint8(a),b); }
-
- __forceinline vint8 umin(const vint8& a, const vint8& b) { return _mm256_min_epu32(a, b); }
- __forceinline vint8 umax(const vint8& a, const vint8& b) { return _mm256_max_epu32(a, b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8& operator +=(vint8& a, const vint8& b) { return a = a + b; }
- __forceinline vint8& operator +=(vint8& a, int b) { return a = a + b; }
-
- __forceinline vint8& operator -=(vint8& a, const vint8& b) { return a = a - b; }
- __forceinline vint8& operator -=(vint8& a, int b) { return a = a - b; }
-
- __forceinline vint8& operator *=(vint8& a, const vint8& b) { return a = a * b; }
- __forceinline vint8& operator *=(vint8& a, int b) { return a = a * b; }
-
- __forceinline vint8& operator &=(vint8& a, const vint8& b) { return a = a & b; }
- __forceinline vint8& operator &=(vint8& a, int b) { return a = a & b; }
-
- __forceinline vint8& operator |=(vint8& a, const vint8& b) { return a = a | b; }
- __forceinline vint8& operator |=(vint8& a, int b) { return a = a | b; }
-
- __forceinline vint8& operator <<=(vint8& a, const int b) { return a = a << b; }
- __forceinline vint8& operator >>=(vint8& a, const int b) { return a = a >> b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- static __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
- static __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
- static __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
- static __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
- static __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
- static __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
-
- static __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) {
- return _mm256_mask_blend_epi32(m, (__m256i)f, (__m256i)t);
- }
-#else
- static __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b)); }
- static __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return !(a == b); }
- static __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32(b, a)); }
- static __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return !(a < b); }
- static __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32(a, b)); }
- static __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return !(a > b); }
-
- static __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) {
- return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
- }
-#endif
-
- template<int mask>
- __forceinline vint8 select(const vint8& t, const vint8& f) {
- return _mm256_blend_epi32(f, t, mask);
- }
-
- __forceinline vboolf8 operator ==(const vint8& a, int b) { return a == vint8(b); }
- __forceinline vboolf8 operator ==(int a, const vint8& b) { return vint8(a) == b; }
-
- __forceinline vboolf8 operator !=(const vint8& a, int b) { return a != vint8(b); }
- __forceinline vboolf8 operator !=(int a, const vint8& b) { return vint8(a) != b; }
-
- __forceinline vboolf8 operator < (const vint8& a, int b) { return a < vint8(b); }
- __forceinline vboolf8 operator < (int a, const vint8& b) { return vint8(a) < b; }
-
- __forceinline vboolf8 operator >=(const vint8& a, int b) { return a >= vint8(b); }
- __forceinline vboolf8 operator >=(int a, const vint8& b) { return vint8(a) >= b; }
-
- __forceinline vboolf8 operator > (const vint8& a, int b) { return a > vint8(b); }
- __forceinline vboolf8 operator > (int a, const vint8& b) { return vint8(a) > b; }
-
- __forceinline vboolf8 operator <=(const vint8& a, int b) { return a <= vint8(b); }
- __forceinline vboolf8 operator <=(int a, const vint8& b) { return vint8(a) <= b; }
-
- __forceinline vboolf8 eq(const vint8& a, const vint8& b) { return a == b; }
- __forceinline vboolf8 ne(const vint8& a, const vint8& b) { return a != b; }
- __forceinline vboolf8 lt(const vint8& a, const vint8& b) { return a < b; }
- __forceinline vboolf8 ge(const vint8& a, const vint8& b) { return a >= b; }
- __forceinline vboolf8 gt(const vint8& a, const vint8& b) { return a > b; }
- __forceinline vboolf8 le(const vint8& a, const vint8& b) { return a <= b; }
-
-#if defined(__AVX512VL__)
- static __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_EQ); }
- static __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_NE); }
- static __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); }
- static __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GE); }
- static __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GT); }
- static __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LE); }
-#else
- static __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a == b); }
- static __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a != b); }
- static __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a < b); }
- static __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a >= b); }
- static __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a > b); }
- static __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a <= b); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8 unpacklo(const vint8& a, const vint8& b) { return _mm256_unpacklo_epi32(a, b); }
- __forceinline vint8 unpackhi(const vint8& a, const vint8& b) { return _mm256_unpackhi_epi32(a, b); }
-
- template<int i>
- __forceinline vint8 shuffle(const vint8& v) {
- return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
- }
-
- template<int i0, int i1>
- __forceinline vint8 shuffle4(const vint8& v) {
- return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1>
- __forceinline vint8 shuffle4(const vint8& a, const vint8& b) {
- return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vint8 shuffle(const vint8& v) {
- return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vint8 shuffle(const vint8& a, const vint8& b) {
- return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<> __forceinline vint8 shuffle<0, 0, 2, 2>(const vint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
- template<> __forceinline vint8 shuffle<1, 1, 3, 3>(const vint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
- template<> __forceinline vint8 shuffle<0, 1, 0, 1>(const vint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
-
- __forceinline vint8 broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
-
- template<int i> __forceinline vint8 insert4(const vint8& a, const vint4& b) { return _mm256_insertf128_si256(a, b, i); }
- template<int i> __forceinline vint4 extract4(const vint8& a) { return _mm256_extractf128_si256(a, i); }
- template<> __forceinline vint4 extract4<0>(const vint8& a) { return _mm256_castsi256_si128(a); }
-
- __forceinline int toScalar(const vint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
-
-#if !defined(__aarch64__)
-
-__forceinline vint8 permute(const vint8& v, const __m256i& index) {
- return _mm256_permutevar8x32_epi32(v, index);
- }
-
- __forceinline vint8 shuffle(const vint8& v, const __m256i& index) {
- return _mm256_castps_si256(_mm256_permutevar_ps(_mm256_castsi256_ps(v), index));
- }
-
-
-
- template<int i>
- static __forceinline vint8 align_shift_right(const vint8& a, const vint8& b) {
-#if defined(__AVX512VL__)
- return _mm256_alignr_epi32(a, b, i);
-#else
- return _mm256_alignr_epi8(a, b, 4*i);
-#endif
- }
-
-#endif
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8 vreduce_min2(const vint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
- __forceinline vint8 vreduce_min4(const vint8& v) { vint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
- __forceinline vint8 vreduce_min (const vint8& v) { vint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
-
- __forceinline vint8 vreduce_max2(const vint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
- __forceinline vint8 vreduce_max4(const vint8& v) { vint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
- __forceinline vint8 vreduce_max (const vint8& v) { vint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
-
- __forceinline vint8 vreduce_add2(const vint8& v) { return v + shuffle<1,0,3,2>(v); }
- __forceinline vint8 vreduce_add4(const vint8& v) { vint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
- __forceinline vint8 vreduce_add (const vint8& v) { vint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
-
- __forceinline int reduce_min(const vint8& v) { return toScalar(vreduce_min(v)); }
- __forceinline int reduce_max(const vint8& v) { return toScalar(vreduce_max(v)); }
- __forceinline int reduce_add(const vint8& v) { return toScalar(vreduce_add(v)); }
-
- __forceinline size_t select_min(const vint8& v) { return bsf(movemask(v == vreduce_min(v))); }
- __forceinline size_t select_max(const vint8& v) { return bsf(movemask(v == vreduce_max(v))); }
-
- __forceinline size_t select_min(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
- __forceinline size_t select_max(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
-
-
- __forceinline vint8 assign(const vint4& a) { return _mm256_castsi128_si256(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Sorting networks
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vint8 usort_ascending(const vint8& v)
- {
- const vint8 a0 = v;
- const vint8 b0 = shuffle<1,0,3,2>(a0);
- const vint8 c0 = umin(a0,b0);
- const vint8 d0 = umax(a0,b0);
- const vint8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
- const vint8 b1 = shuffle<2,3,0,1>(a1);
- const vint8 c1 = umin(a1,b1);
- const vint8 d1 = umax(a1,b1);
- const vint8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
- const vint8 b2 = shuffle<1,0,3,2>(a2);
- const vint8 c2 = umin(a2,b2);
- const vint8 d2 = umax(a2,b2);
- const vint8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
- const vint8 b3 = shuffle4<1,0>(a3);
- const vint8 c3 = umin(a3,b3);
- const vint8 d3 = umax(a3,b3);
- const vint8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
- const vint8 b4 = shuffle<2,3,0,1>(a4);
- const vint8 c4 = umin(a4,b4);
- const vint8 d4 = umax(a4,b4);
- const vint8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
- const vint8 b5 = shuffle<1,0,3,2>(a5);
- const vint8 c5 = umin(a5,b5);
- const vint8 d5 = umax(a5,b5);
- const vint8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
- return a6;
- }
-
- __forceinline vint8 usort_descending(const vint8& v)
- {
- const vint8 a0 = v;
- const vint8 b0 = shuffle<1,0,3,2>(a0);
- const vint8 c0 = umax(a0,b0);
- const vint8 d0 = umin(a0,b0);
- const vint8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
- const vint8 b1 = shuffle<2,3,0,1>(a1);
- const vint8 c1 = umax(a1,b1);
- const vint8 d1 = umin(a1,b1);
- const vint8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
- const vint8 b2 = shuffle<1,0,3,2>(a2);
- const vint8 c2 = umax(a2,b2);
- const vint8 d2 = umin(a2,b2);
- const vint8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
- const vint8 b3 = shuffle4<1,0>(a3);
- const vint8 c3 = umax(a3,b3);
- const vint8 d3 = umin(a3,b3);
- const vint8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
- const vint8 b4 = shuffle<2,3,0,1>(a4);
- const vint8 c4 = umax(a4,b4);
- const vint8 d4 = umin(a4,b4);
- const vint8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
- const vint8 b5 = shuffle<1,0,3,2>(a5);
- const vint8 c5 = umax(a5,b5);
- const vint8 d5 = umin(a5,b5);
- const vint8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
- return a6;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vint8& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vllong4_avx2.h b/thirdparty/embree-aarch64/common/simd/vllong4_avx2.h
deleted file mode 100644
index de3ebc16a7..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vllong4_avx2.h
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 4-wide AVX2 64-bit long long type */
- template<>
- struct vllong<4>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboold4 Bool;
-
- enum { size = 4 }; // number of SIMD elements
- union { // data
- __m256i v;
- long long i[4];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong() {}
- __forceinline vllong(const vllong4& t) { v = t.v; }
- __forceinline vllong4& operator =(const vllong4& f) { v = f.v; return *this; }
-
- __forceinline vllong(const __m256i& t) { v = t; }
- __forceinline operator __m256i() const { return v; }
- __forceinline operator __m256d() const { return _mm256_castsi256_pd(v); }
-
-
- __forceinline vllong(long long i) {
- v = _mm256_set1_epi64x(i);
- }
-
- __forceinline vllong(long long a, long long b, long long c, long long d) {
- v = _mm256_set_epi64x(d,c,b,a);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong(ZeroTy) : v(_mm256_setzero_si256()) {}
- __forceinline vllong(OneTy) : v(_mm256_set1_epi64x(1)) {}
- __forceinline vllong(StepTy) : v(_mm256_set_epi64x(3,2,1,0)) {}
- __forceinline vllong(ReverseStepTy) : v(_mm256_set_epi64x(0,1,2,3)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline void store_nt(void* __restrict__ ptr, const vllong4& a) {
- _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(a));
- }
-
- static __forceinline vllong4 loadu(const void* addr)
- {
- return _mm256_loadu_si256((__m256i*)addr);
- }
-
- static __forceinline vllong4 load(const vllong4* addr) {
- return _mm256_load_si256((__m256i*)addr);
- }
-
- static __forceinline vllong4 load(const long long* addr) {
- return _mm256_load_si256((__m256i*)addr);
- }
-
- static __forceinline void store(void* ptr, const vllong4& v) {
- _mm256_store_si256((__m256i*)ptr,v);
- }
-
- static __forceinline void storeu(void* ptr, const vllong4& v) {
- _mm256_storeu_si256((__m256i*)ptr,v);
- }
-
- static __forceinline void storeu(const vboold4& mask, long long* ptr, const vllong4& f) {
-#if defined(__AVX512VL__)
- _mm256_mask_storeu_epi64(ptr,mask,f);
-#else
- _mm256_maskstore_pd((double*)ptr,mask,_mm256_castsi256_pd(f));
-#endif
- }
-
- static __forceinline void store(const vboold4& mask, void* ptr, const vllong4& f) {
-#if defined(__AVX512VL__)
- _mm256_mask_store_epi64(ptr,mask,f);
-#else
- _mm256_maskstore_pd((double*)ptr,mask,_mm256_castsi256_pd(f));
-#endif
- }
-
- static __forceinline vllong4 broadcast64bit(size_t v) {
- return _mm256_set1_epi64x(v);
- }
-
- static __forceinline size_t extract64bit(const vllong4& v)
- {
- return _mm_cvtsi128_si64(_mm256_castsi256_si128(v));
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline long long& operator [](size_t index) { assert(index < 4); return i[index]; }
- __forceinline const long long& operator [](size_t index) const { assert(index < 4); return i[index]; }
-
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong4 select(const vboold4& m, const vllong4& t, const vllong4& f) {
- #if defined(__AVX512VL__)
- return _mm256_mask_blend_epi64(m, f, t);
- #else
- return _mm256_castpd_si256(_mm256_blendv_pd(_mm256_castsi256_pd(f), _mm256_castsi256_pd(t), m));
- #endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboold4 asBool(const vllong4& a) { return _mm256_movepi64_mask(a); }
-#else
- __forceinline vboold4 asBool(const vllong4& a) { return _mm256_castsi256_pd(a); }
-#endif
-
- __forceinline vllong4 operator +(const vllong4& a) { return a; }
- __forceinline vllong4 operator -(const vllong4& a) { return _mm256_sub_epi64(_mm256_setzero_si256(), a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong4 operator +(const vllong4& a, const vllong4& b) { return _mm256_add_epi64(a, b); }
- __forceinline vllong4 operator +(const vllong4& a, long long b) { return a + vllong4(b); }
- __forceinline vllong4 operator +(long long a, const vllong4& b) { return vllong4(a) + b; }
-
- __forceinline vllong4 operator -(const vllong4& a, const vllong4& b) { return _mm256_sub_epi64(a, b); }
- __forceinline vllong4 operator -(const vllong4& a, long long b) { return a - vllong4(b); }
- __forceinline vllong4 operator -(long long a, const vllong4& b) { return vllong4(a) - b; }
-
- /* only low 32bit part */
- __forceinline vllong4 operator *(const vllong4& a, const vllong4& b) { return _mm256_mul_epi32(a, b); }
- __forceinline vllong4 operator *(const vllong4& a, long long b) { return a * vllong4(b); }
- __forceinline vllong4 operator *(long long a, const vllong4& b) { return vllong4(a) * b; }
-
- __forceinline vllong4 operator &(const vllong4& a, const vllong4& b) { return _mm256_and_si256(a, b); }
- __forceinline vllong4 operator &(const vllong4& a, long long b) { return a & vllong4(b); }
- __forceinline vllong4 operator &(long long a, const vllong4& b) { return vllong4(a) & b; }
-
- __forceinline vllong4 operator |(const vllong4& a, const vllong4& b) { return _mm256_or_si256(a, b); }
- __forceinline vllong4 operator |(const vllong4& a, long long b) { return a | vllong4(b); }
- __forceinline vllong4 operator |(long long a, const vllong4& b) { return vllong4(a) | b; }
-
- __forceinline vllong4 operator ^(const vllong4& a, const vllong4& b) { return _mm256_xor_si256(a, b); }
- __forceinline vllong4 operator ^(const vllong4& a, long long b) { return a ^ vllong4(b); }
- __forceinline vllong4 operator ^(long long a, const vllong4& b) { return vllong4(a) ^ b; }
-
- __forceinline vllong4 operator <<(const vllong4& a, long long n) { return _mm256_slli_epi64(a, (int)n); }
- //__forceinline vllong4 operator >>(const vllong4& a, long long n) { return _mm256_srai_epi64(a, n); }
-
- __forceinline vllong4 operator <<(const vllong4& a, const vllong4& n) { return _mm256_sllv_epi64(a, n); }
- //__forceinline vllong4 operator >>(const vllong4& a, const vllong4& n) { return _mm256_srav_epi64(a, n); }
- //__forceinline vllong4 sra(const vllong4& a, long long b) { return _mm256_srai_epi64(a, b); }
-
- __forceinline vllong4 srl(const vllong4& a, long long b) { return _mm256_srli_epi64(a, (int)b); }
-
- //__forceinline vllong4 min(const vllong4& a, const vllong4& b) { return _mm256_min_epi64(a, b); }
- //__forceinline vllong4 min(const vllong4& a, long long b) { return min(a,vllong4(b)); }
- //__forceinline vllong4 min(long long a, const vllong4& b) { return min(vllong4(a),b); }
-
- //__forceinline vllong4 max(const vllong4& a, const vllong4& b) { return _mm256_max_epi64(a, b); }
- //__forceinline vllong4 max(const vllong4& a, long long b) { return max(a,vllong4(b)); }
- //__forceinline vllong4 max(long long a, const vllong4& b) { return max(vllong4(a),b); }
-
-#if defined(__AVX512VL__)
- __forceinline vllong4 mask_and(const vboold4& m, const vllong4& c, const vllong4& a, const vllong4& b) { return _mm256_mask_and_epi64(c,m,a,b); }
- __forceinline vllong4 mask_or (const vboold4& m, const vllong4& c, const vllong4& a, const vllong4& b) { return _mm256_mask_or_epi64(c,m,a,b); }
-#else
- __forceinline vllong4 mask_and(const vboold4& m, const vllong4& c, const vllong4& a, const vllong4& b) { return select(m, a & b, c); }
- __forceinline vllong4 mask_or (const vboold4& m, const vllong4& c, const vllong4& a, const vllong4& b) { return select(m, a | b, c); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong4& operator +=(vllong4& a, const vllong4& b) { return a = a + b; }
- __forceinline vllong4& operator +=(vllong4& a, long long b) { return a = a + b; }
-
- __forceinline vllong4& operator -=(vllong4& a, const vllong4& b) { return a = a - b; }
- __forceinline vllong4& operator -=(vllong4& a, long long b) { return a = a - b; }
-
- __forceinline vllong4& operator *=(vllong4& a, const vllong4& b) { return a = a * b; }
- __forceinline vllong4& operator *=(vllong4& a, long long b) { return a = a * b; }
-
- __forceinline vllong4& operator &=(vllong4& a, const vllong4& b) { return a = a & b; }
- __forceinline vllong4& operator &=(vllong4& a, long long b) { return a = a & b; }
-
- __forceinline vllong4& operator |=(vllong4& a, const vllong4& b) { return a = a | b; }
- __forceinline vllong4& operator |=(vllong4& a, long long b) { return a = a | b; }
-
- __forceinline vllong4& operator <<=(vllong4& a, long long b) { return a = a << b; }
- //__forceinline vllong4& operator >>=(vllong4& a, long long b) { return a = a >> b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboold4 operator ==(const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboold4 operator !=(const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboold4 operator < (const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboold4 operator >=(const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboold4 operator > (const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboold4 operator <=(const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_LE); }
-#else
- __forceinline vboold4 operator ==(const vllong4& a, const vllong4& b) { return _mm256_cmpeq_epi64(a,b); }
- __forceinline vboold4 operator !=(const vllong4& a, const vllong4& b) { return !(a == b); }
- __forceinline vboold4 operator > (const vllong4& a, const vllong4& b) { return _mm256_cmpgt_epi64(a,b); }
- __forceinline vboold4 operator < (const vllong4& a, const vllong4& b) { return _mm256_cmpgt_epi64(b,a); }
- __forceinline vboold4 operator >=(const vllong4& a, const vllong4& b) { return !(a < b); }
- __forceinline vboold4 operator <=(const vllong4& a, const vllong4& b) { return !(a > b); }
-#endif
-
- __forceinline vboold4 operator ==(const vllong4& a, long long b) { return a == vllong4(b); }
- __forceinline vboold4 operator ==(long long a, const vllong4& b) { return vllong4(a) == b; }
-
- __forceinline vboold4 operator !=(const vllong4& a, long long b) { return a != vllong4(b); }
- __forceinline vboold4 operator !=(long long a, const vllong4& b) { return vllong4(a) != b; }
-
- __forceinline vboold4 operator > (const vllong4& a, long long b) { return a > vllong4(b); }
- __forceinline vboold4 operator > (long long a, const vllong4& b) { return vllong4(a) > b; }
-
- __forceinline vboold4 operator < (const vllong4& a, long long b) { return a < vllong4(b); }
- __forceinline vboold4 operator < (long long a, const vllong4& b) { return vllong4(a) < b; }
-
- __forceinline vboold4 operator >=(const vllong4& a, long long b) { return a >= vllong4(b); }
- __forceinline vboold4 operator >=(long long a, const vllong4& b) { return vllong4(a) >= b; }
-
- __forceinline vboold4 operator <=(const vllong4& a, long long b) { return a <= vllong4(b); }
- __forceinline vboold4 operator <=(long long a, const vllong4& b) { return vllong4(a) <= b; }
-
- __forceinline vboold4 eq(const vllong4& a, const vllong4& b) { return a == b; }
- __forceinline vboold4 ne(const vllong4& a, const vllong4& b) { return a != b; }
- __forceinline vboold4 lt(const vllong4& a, const vllong4& b) { return a < b; }
- __forceinline vboold4 ge(const vllong4& a, const vllong4& b) { return a >= b; }
- __forceinline vboold4 gt(const vllong4& a, const vllong4& b) { return a > b; }
- __forceinline vboold4 le(const vllong4& a, const vllong4& b) { return a <= b; }
-
-#if defined(__AVX512VL__)
- __forceinline vboold4 eq(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_EQ); }
- __forceinline vboold4 ne(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_NE); }
- __forceinline vboold4 lt(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_LT); }
- __forceinline vboold4 ge(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_GE); }
- __forceinline vboold4 gt(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_GT); }
- __forceinline vboold4 le(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_LE); }
-#else
- __forceinline vboold4 eq(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a == b); }
- __forceinline vboold4 ne(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a != b); }
- __forceinline vboold4 lt(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a < b); }
- __forceinline vboold4 ge(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a >= b); }
- __forceinline vboold4 gt(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a > b); }
- __forceinline vboold4 le(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a <= b); }
-#endif
-
- __forceinline void xchg(const vboold4& m, vllong4& a, vllong4& b) {
- const vllong4 c = a; a = select(m,b,a); b = select(m,c,b);
- }
-
- __forceinline vboold4 test(const vllong4& a, const vllong4& b) {
-#if defined(__AVX512VL__)
- return _mm256_test_epi64_mask(a,b);
-#else
- return _mm256_testz_si256(a,b);
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int i0, int i1>
- __forceinline vllong4 shuffle(const vllong4& v) {
- return _mm256_castpd_si256(_mm256_permute_pd(_mm256_castsi256_pd(v), (i1 << 3) | (i0 << 2) | (i1 << 1) | i0));
- }
-
- template<int i>
- __forceinline vllong4 shuffle(const vllong4& v) {
- return shuffle<i, i>(v);
- }
-
- template<int i0, int i1>
- __forceinline vllong4 shuffle2(const vllong4& v) {
- return _mm256_castpd_si256(_mm256_permute2f128_pd(_mm256_castsi256_pd(v), _mm256_castsi256_pd(v), (i1 << 4) | i0));
- }
-
- __forceinline long long toScalar(const vllong4& v) {
- return _mm_cvtsi128_si64(_mm256_castsi256_si128(v));
- }
-
-#if defined(__AVX512VL__)
- __forceinline vllong4 permute(const vllong4& a, const __m256i& index) {
- // workaround for GCC 7.x
-#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
- return _mm256_permutex2var_epi64(a,index,a);
-#else
- return _mm256_permutexvar_epi64(index,a);
-#endif
- }
-
- __forceinline vllong4 permutex2var(const vllong4& index, const vllong4& a, const vllong4& b) {
- return _mm256_permutex2var_epi64(a,index,b);
- }
-
-#endif
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
-
- __forceinline vllong4 vreduce_and2(const vllong4& x) { return x & shuffle<1,0>(x); }
- __forceinline vllong4 vreduce_and (const vllong4& y) { const vllong4 x = vreduce_and2(y); return x & shuffle2<1,0>(x); }
-
- __forceinline vllong4 vreduce_or2(const vllong4& x) { return x | shuffle<1,0>(x); }
- __forceinline vllong4 vreduce_or (const vllong4& y) { const vllong4 x = vreduce_or2(y); return x | shuffle2<1,0>(x); }
-
- __forceinline vllong4 vreduce_add2(const vllong4& x) { return x + shuffle<1,0>(x); }
- __forceinline vllong4 vreduce_add (const vllong4& y) { const vllong4 x = vreduce_add2(y); return x + shuffle2<1,0>(x); }
-
- __forceinline long long reduce_add(const vllong4& a) { return toScalar(vreduce_add(a)); }
- __forceinline long long reduce_or (const vllong4& a) { return toScalar(vreduce_or(a)); }
- __forceinline long long reduce_and(const vllong4& a) { return toScalar(vreduce_and(a)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vllong4& v)
- {
- cout << "<" << v[0];
- for (size_t i=1; i<4; i++) cout << ", " << v[i];
- cout << ">";
- return cout;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vllong8_avx512.h b/thirdparty/embree-aarch64/common/simd/vllong8_avx512.h
deleted file mode 100644
index 76dddd8991..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vllong8_avx512.h
+++ /dev/null
@@ -1,381 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX-512 64-bit long long type */
- template<>
- struct vllong<8>
- {
- ALIGNED_STRUCT_(64);
-
- typedef vboold8 Bool;
-
- enum { size = 8 }; // number of SIMD elements
- union { // data
- __m512i v;
- long long i[8];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong() {}
- __forceinline vllong(const vllong8& t) { v = t.v; }
- __forceinline vllong8& operator =(const vllong8& f) { v = f.v; return *this; }
-
- __forceinline vllong(const __m512i& t) { v = t; }
- __forceinline operator __m512i() const { return v; }
- __forceinline operator __m256i() const { return _mm512_castsi512_si256(v); }
-
- __forceinline vllong(long long i) {
- v = _mm512_set1_epi64(i);
- }
-
- __forceinline vllong(long long a, long long b, long long c, long long d) {
- v = _mm512_set4_epi64(d,c,b,a);
- }
-
- __forceinline vllong(long long a0, long long a1, long long a2, long long a3,
- long long a4, long long a5, long long a6, long long a7)
- {
- v = _mm512_set_epi64(a7,a6,a5,a4,a3,a2,a1,a0);
- }
-
- __forceinline vllong(const vllong<4>& i) {
- v = _mm512_broadcast_i64x4(i);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong(ZeroTy) : v(_mm512_setzero_epi32()) {}
- __forceinline vllong(OneTy) : v(_mm512_set1_epi64(1)) {}
- __forceinline vllong(StepTy) : v(_mm512_set_epi64(7,6,5,4,3,2,1,0)) {}
- __forceinline vllong(ReverseStepTy) : v(_mm512_setr_epi64(7,6,5,4,3,2,1,0)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline void store_nt(void* __restrict__ ptr, const vllong8& a) {
- _mm512_stream_si512((__m512i*)ptr,a);
- }
-
- static __forceinline vllong8 loadu(const void* addr) {
- return _mm512_loadu_si512(addr);
- }
-
- static __forceinline vllong8 load(const vllong8* addr) {
- return _mm512_load_si512(addr);
- }
-
- static __forceinline vllong8 load(const long long* addr) {
- return _mm512_load_si512(addr);
- }
-
- static __forceinline vllong8 load(const uint8_t* ptr) {
- return _mm512_cvtepu8_epi64(*(__m128i*)ptr);
- }
-
- static __forceinline void store(void* ptr, const vllong8& v) {
- _mm512_store_si512(ptr,v);
- }
-
- static __forceinline void storeu(void* ptr, const vllong8& v) {
- _mm512_storeu_si512(ptr,v);
- }
-
- static __forceinline void storeu(const vboold8& mask, long long* ptr, const vllong8& f) {
- _mm512_mask_storeu_epi64(ptr,mask,f);
- }
-
- static __forceinline void store(const vboold8& mask, void* addr, const vllong8& v2) {
- _mm512_mask_store_epi64(addr,mask,v2);
- }
-
- /* pass by value to avoid compiler generating inefficient code */
- static __forceinline void storeu_compact(const vboold8 mask, void* addr, const vllong8& reg) {
- _mm512_mask_compressstoreu_epi64(addr,mask,reg);
- }
-
- static __forceinline vllong8 compact64bit(const vboold8& mask, vllong8& v) {
- return _mm512_mask_compress_epi64(v,mask,v);
- }
-
- static __forceinline vllong8 compact64bit(const vboold8& mask, vllong8& dest, const vllong8& source) {
- return _mm512_mask_compress_epi64(dest,mask,source);
- }
-
- static __forceinline vllong8 compact(const vboold8& mask, vllong8& v) {
- return _mm512_mask_compress_epi64(v,mask,v);
- }
-
- static __forceinline vllong8 compact(const vboold8& mask, const vllong8& a, vllong8& b) {
- return _mm512_mask_compress_epi64(a,mask,b);
- }
-
- static __forceinline vllong8 expand(const vboold8& mask, const vllong8& a, vllong8& b) {
- return _mm512_mask_expand_epi64(b,mask,a);
- }
-
- static __forceinline vllong8 broadcast64bit(size_t v) {
- return _mm512_set1_epi64(v);
- }
-
- static __forceinline size_t extract64bit(const vllong8& v)
- {
- return _mm_cvtsi128_si64(_mm512_castsi512_si128(v));
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline long long& operator [](size_t index) { assert(index < 8); return i[index]; }
- __forceinline const long long& operator [](size_t index) const { assert(index < 8); return i[index]; }
-
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold8 asBool(const vllong8& a) { return _mm512_movepi64_mask(a); }
-
- __forceinline vllong8 operator +(const vllong8& a) { return a; }
- __forceinline vllong8 operator -(const vllong8& a) { return _mm512_sub_epi64(_mm512_setzero_epi32(), a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong8 operator +(const vllong8& a, const vllong8& b) { return _mm512_add_epi64(a, b); }
- __forceinline vllong8 operator +(const vllong8& a, long long b) { return a + vllong8(b); }
- __forceinline vllong8 operator +(long long a, const vllong8& b) { return vllong8(a) + b; }
-
- __forceinline vllong8 operator -(const vllong8& a, const vllong8& b) { return _mm512_sub_epi64(a, b); }
- __forceinline vllong8 operator -(const vllong8& a, long long b) { return a - vllong8(b); }
- __forceinline vllong8 operator -(long long a, const vllong8& b) { return vllong8(a) - b; }
-
- __forceinline vllong8 operator *(const vllong8& a, const vllong8& b) { return _mm512_mullo_epi64(a, b); }
- __forceinline vllong8 operator *(const vllong8& a, long long b) { return a * vllong8(b); }
- __forceinline vllong8 operator *(long long a, const vllong8& b) { return vllong8(a) * b; }
-
- __forceinline vllong8 operator &(const vllong8& a, const vllong8& b) { return _mm512_and_epi64(a, b); }
- __forceinline vllong8 operator &(const vllong8& a, long long b) { return a & vllong8(b); }
- __forceinline vllong8 operator &(long long a, const vllong8& b) { return vllong8(a) & b; }
-
- __forceinline vllong8 operator |(const vllong8& a, const vllong8& b) { return _mm512_or_epi64(a, b); }
- __forceinline vllong8 operator |(const vllong8& a, long long b) { return a | vllong8(b); }
- __forceinline vllong8 operator |(long long a, const vllong8& b) { return vllong8(a) | b; }
-
- __forceinline vllong8 operator ^(const vllong8& a, const vllong8& b) { return _mm512_xor_epi64(a, b); }
- __forceinline vllong8 operator ^(const vllong8& a, long long b) { return a ^ vllong8(b); }
- __forceinline vllong8 operator ^(long long a, const vllong8& b) { return vllong8(a) ^ b; }
-
- __forceinline vllong8 operator <<(const vllong8& a, long long n) { return _mm512_slli_epi64(a, n); }
- __forceinline vllong8 operator >>(const vllong8& a, long long n) { return _mm512_srai_epi64(a, n); }
-
- __forceinline vllong8 operator <<(const vllong8& a, const vllong8& n) { return _mm512_sllv_epi64(a, n); }
- __forceinline vllong8 operator >>(const vllong8& a, const vllong8& n) { return _mm512_srav_epi64(a, n); }
-
- __forceinline vllong8 sll (const vllong8& a, long long b) { return _mm512_slli_epi64(a, b); }
- __forceinline vllong8 sra (const vllong8& a, long long b) { return _mm512_srai_epi64(a, b); }
- __forceinline vllong8 srl (const vllong8& a, long long b) { return _mm512_srli_epi64(a, b); }
-
- __forceinline vllong8 min(const vllong8& a, const vllong8& b) { return _mm512_min_epi64(a, b); }
- __forceinline vllong8 min(const vllong8& a, long long b) { return min(a,vllong8(b)); }
- __forceinline vllong8 min(long long a, const vllong8& b) { return min(vllong8(a),b); }
-
- __forceinline vllong8 max(const vllong8& a, const vllong8& b) { return _mm512_max_epi64(a, b); }
- __forceinline vllong8 max(const vllong8& a, long long b) { return max(a,vllong8(b)); }
- __forceinline vllong8 max(long long a, const vllong8& b) { return max(vllong8(a),b); }
-
- __forceinline vllong8 mask_add(const vboold8& m, const vllong8& c, const vllong8& a, const vllong8& b) { return _mm512_mask_add_epi64(c,m,a,b); }
- __forceinline vllong8 mask_sub(const vboold8& m, const vllong8& c, const vllong8& a, const vllong8& b) { return _mm512_mask_sub_epi64(c,m,a,b); }
-
- __forceinline vllong8 mask_and(const vboold8& m, const vllong8& c, const vllong8& a, const vllong8& b) { return _mm512_mask_and_epi64(c,m,a,b); }
- __forceinline vllong8 mask_or (const vboold8& m, const vllong8& c, const vllong8& a, const vllong8& b) { return _mm512_mask_or_epi64(c,m,a,b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong8& operator +=(vllong8& a, const vllong8& b) { return a = a + b; }
- __forceinline vllong8& operator +=(vllong8& a, long long b) { return a = a + b; }
-
- __forceinline vllong8& operator -=(vllong8& a, const vllong8& b) { return a = a - b; }
- __forceinline vllong8& operator -=(vllong8& a, long long b) { return a = a - b; }
-
- __forceinline vllong8& operator *=(vllong8& a, const vllong8& b) { return a = a * b; }
- __forceinline vllong8& operator *=(vllong8& a, long long b) { return a = a * b; }
-
- __forceinline vllong8& operator &=(vllong8& a, const vllong8& b) { return a = a & b; }
- __forceinline vllong8& operator &=(vllong8& a, long long b) { return a = a & b; }
-
- __forceinline vllong8& operator |=(vllong8& a, const vllong8& b) { return a = a | b; }
- __forceinline vllong8& operator |=(vllong8& a, long long b) { return a = a | b; }
-
- __forceinline vllong8& operator <<=(vllong8& a, long long b) { return a = a << b; }
- __forceinline vllong8& operator >>=(vllong8& a, long long b) { return a = a >> b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboold8 operator ==(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboold8 operator ==(const vllong8& a, long long b) { return a == vllong8(b); }
- __forceinline vboold8 operator ==(long long a, const vllong8& b) { return vllong8(a) == b; }
-
- __forceinline vboold8 operator !=(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboold8 operator !=(const vllong8& a, long long b) { return a != vllong8(b); }
- __forceinline vboold8 operator !=(long long a, const vllong8& b) { return vllong8(a) != b; }
-
- __forceinline vboold8 operator < (const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboold8 operator < (const vllong8& a, long long b) { return a < vllong8(b); }
- __forceinline vboold8 operator < (long long a, const vllong8& b) { return vllong8(a) < b; }
-
- __forceinline vboold8 operator >=(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboold8 operator >=(const vllong8& a, long long b) { return a >= vllong8(b); }
- __forceinline vboold8 operator >=(long long a, const vllong8& b) { return vllong8(a) >= b; }
-
- __forceinline vboold8 operator > (const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboold8 operator > (const vllong8& a, long long b) { return a > vllong8(b); }
- __forceinline vboold8 operator > (long long a, const vllong8& b) { return vllong8(a) > b; }
-
- __forceinline vboold8 operator <=(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_LE); }
- __forceinline vboold8 operator <=(const vllong8& a, long long b) { return a <= vllong8(b); }
- __forceinline vboold8 operator <=(long long a, const vllong8& b) { return vllong8(a) <= b; }
-
- __forceinline vboold8 eq(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboold8 ne(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboold8 lt(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboold8 ge(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboold8 gt(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboold8 le(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_LE); }
-
- __forceinline vboold8 eq(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_EQ); }
- __forceinline vboold8 ne(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_NE); }
- __forceinline vboold8 lt(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_LT); }
- __forceinline vboold8 ge(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_GE); }
- __forceinline vboold8 gt(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_GT); }
- __forceinline vboold8 le(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_LE); }
-
- __forceinline vllong8 select(const vboold8& m, const vllong8& t, const vllong8& f) {
- return _mm512_mask_or_epi64(f,m,t,t);
- }
-
- __forceinline void xchg(const vboold8& m, vllong8& a, vllong8& b) {
- const vllong8 c = a; a = select(m,b,a); b = select(m,c,b);
- }
-
- __forceinline vboold8 test(const vboold8& m, const vllong8& a, const vllong8& b) {
- return _mm512_mask_test_epi64_mask(m,a,b);
- }
-
- __forceinline vboold8 test(const vllong8& a, const vllong8& b) {
- return _mm512_test_epi64_mask(a,b);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int i0, int i1>
- __forceinline vllong8 shuffle(const vllong8& v) {
- return _mm512_castpd_si512(_mm512_permute_pd(_mm512_castsi512_pd(v), (i1 << 7) | (i0 << 6) | (i1 << 5) | (i0 << 4) | (i1 << 3) | (i0 << 2) | (i1 << 1) | i0));
- }
-
- template<int i>
- __forceinline vllong8 shuffle(const vllong8& v) {
- return shuffle<i, i>(v);
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vllong8 shuffle(const vllong8& v) {
- return _mm512_permutex_epi64(v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
-
- template<int i0, int i1>
- __forceinline vllong8 shuffle4(const vllong8& v) {
- return _mm512_shuffle_i64x2(v, v, _MM_SHUFFLE(i1*2+1, i1*2, i0*2+1, i0*2));
- }
-
- template<int i>
- __forceinline vllong8 shuffle4(const vllong8& v) {
- return shuffle4<i, i>(v);
- }
-
- template<int i>
- __forceinline vllong8 align_shift_right(const vllong8& a, const vllong8& b) {
- return _mm512_alignr_epi64(a, b, i);
- };
-
- __forceinline long long toScalar(const vllong8& v) {
- return _mm_cvtsi128_si64(_mm512_castsi512_si128(v));
- }
-
- __forceinline vllong8 zeroExtend32Bit(const __m512i& a) {
- return _mm512_cvtepu32_epi64(_mm512_castsi512_si256(a));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong8 vreduce_min2(vllong8 x) { return min(x, shuffle<1,0,3,2>(x)); }
- __forceinline vllong8 vreduce_min4(vllong8 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
- __forceinline vllong8 vreduce_min (vllong8 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0>(x)); }
-
- __forceinline vllong8 vreduce_max2(vllong8 x) { return max(x, shuffle<1,0,3,2>(x)); }
- __forceinline vllong8 vreduce_max4(vllong8 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
- __forceinline vllong8 vreduce_max (vllong8 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0>(x)); }
-
- __forceinline vllong8 vreduce_and2(vllong8 x) { return x & shuffle<1,0,3,2>(x); }
- __forceinline vllong8 vreduce_and4(vllong8 x) { x = vreduce_and2(x); return x & shuffle<2,3,0,1>(x); }
- __forceinline vllong8 vreduce_and (vllong8 x) { x = vreduce_and4(x); return x & shuffle4<1,0>(x); }
-
- __forceinline vllong8 vreduce_or2(vllong8 x) { return x | shuffle<1,0,3,2>(x); }
- __forceinline vllong8 vreduce_or4(vllong8 x) { x = vreduce_or2(x); return x | shuffle<2,3,0,1>(x); }
- __forceinline vllong8 vreduce_or (vllong8 x) { x = vreduce_or4(x); return x | shuffle4<1,0>(x); }
-
- __forceinline vllong8 vreduce_add2(vllong8 x) { return x + shuffle<1,0,3,2>(x); }
- __forceinline vllong8 vreduce_add4(vllong8 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
- __forceinline vllong8 vreduce_add (vllong8 x) { x = vreduce_add4(x); return x + shuffle4<1,0>(x); }
-
- __forceinline long long reduce_min(const vllong8& v) { return toScalar(vreduce_min(v)); }
- __forceinline long long reduce_max(const vllong8& v) { return toScalar(vreduce_max(v)); }
- __forceinline long long reduce_and(const vllong8& v) { return toScalar(vreduce_and(v)); }
- __forceinline long long reduce_or (const vllong8& v) { return toScalar(vreduce_or (v)); }
- __forceinline long long reduce_add(const vllong8& v) { return toScalar(vreduce_add(v)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Memory load and store operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vllong8 permute(const vllong8& v, const vllong8& index) {
- return _mm512_permutexvar_epi64(index,v);
- }
-
- __forceinline vllong8 reverse(const vllong8& a) {
- return permute(a,vllong8(reverse_step));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vllong8& v)
- {
- cout << "<" << v[0];
- for (size_t i=1; i<8; i++) cout << ", " << v[i];
- cout << ">";
- return cout;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vuint16_avx512.h b/thirdparty/embree-aarch64/common/simd/vuint16_avx512.h
deleted file mode 100644
index 39752611bb..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vuint16_avx512.h
+++ /dev/null
@@ -1,443 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 16-wide AVX-512 unsigned integer type */
- template<>
- struct vuint<16>
- {
- ALIGNED_STRUCT_(64);
-
- typedef vboolf16 Bool;
- typedef vuint16 UInt;
- typedef vfloat16 Float;
-
- enum { size = 16 }; // number of SIMD elements
- union { // data
- __m512i v;
- unsigned int i[16];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint() {}
- __forceinline vuint(const vuint16& t) { v = t.v; }
- __forceinline vuint16& operator =(const vuint16& f) { v = f.v; return *this; }
-
- __forceinline vuint(const __m512i& t) { v = t; }
- __forceinline operator __m512i() const { return v; }
- __forceinline operator __m256i() const { return _mm512_castsi512_si256(v); }
-
- __forceinline vuint(unsigned int i) {
- v = _mm512_set1_epi32(i);
- }
-
- __forceinline vuint(const vuint4& i) {
- v = _mm512_broadcast_i32x4(i);
- }
-
- __forceinline vuint(const vuint8& i) {
- v = _mm512_castps_si512(_mm512_castpd_ps(_mm512_broadcast_f64x4(_mm256_castsi256_pd(i))));
- }
-
- __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) {
- v = _mm512_set4_epi32(d,c,b,a);
- }
-
- __forceinline vuint(unsigned int a0 , unsigned int a1 , unsigned int a2 , unsigned int a3,
- unsigned int a4 , unsigned int a5 , unsigned int a6 , unsigned int a7,
- unsigned int a8 , unsigned int a9 , unsigned int a10, unsigned int a11,
- unsigned int a12, unsigned int a13, unsigned int a14, unsigned int a15)
- {
- v = _mm512_set_epi32(a15,a14,a13,a12,a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0);
- }
-
- __forceinline explicit vuint(const __m512& f) {
- v = _mm512_cvtps_epu32(f);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint(ZeroTy) : v(_mm512_setzero_epi32()) {}
- __forceinline vuint(OneTy) : v(_mm512_set1_epi32(1)) {}
- __forceinline vuint(StepTy) : v(_mm512_set_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
- __forceinline vuint(ReverseStepTy) : v(_mm512_setr_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline void store_nt(void* __restrict__ ptr, const vuint16& a) {
- _mm512_stream_si512((__m512i*)ptr,a);
- }
-
- static __forceinline vuint16 loadu(const void* addr)
- {
- return _mm512_loadu_si512(addr);
- }
-
- static __forceinline vuint16 loadu(const uint8_t* ptr) { return _mm512_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)); }
- static __forceinline vuint16 loadu(const unsigned short* ptr) { return _mm512_cvtepu16_epi32(_mm256_loadu_si256((__m256i*)ptr)); }
-
- static __forceinline vuint16 load(const vuint16* addr) {
- return _mm512_load_si512(addr);
- }
-
- static __forceinline vuint16 load(const unsigned int* addr) {
- return _mm512_load_si512(addr);
- }
-
- static __forceinline vuint16 load(unsigned short* ptr) { return _mm512_cvtepu16_epi32(*(__m256i*)ptr); }
-
-
- static __forceinline void store(void* ptr, const vuint16& v) {
- _mm512_store_si512(ptr,v);
- }
-
- static __forceinline void storeu(void* ptr, const vuint16& v) {
- _mm512_storeu_si512(ptr,v);
- }
-
- static __forceinline void storeu(const vboolf16& mask, void* ptr, const vuint16& f) {
- _mm512_mask_storeu_epi32(ptr,mask,f);
- }
-
- static __forceinline void store(const vboolf16& mask, void* addr, const vuint16& v2) {
- _mm512_mask_store_epi32(addr,mask,v2);
- }
-
- /* pass by value to avoid compiler generating inefficient code */
- static __forceinline void storeu_compact(const vboolf16 mask, void* addr, const vuint16 reg) {
- _mm512_mask_compressstoreu_epi32(addr,mask,reg);
- }
-
- static __forceinline void storeu_compact_single(const vboolf16 mask, void* addr, vuint16 reg) {
- //_mm512_mask_compressstoreu_epi32(addr,mask,reg);
- *(float*)addr = mm512_cvtss_f32(_mm512_mask_compress_ps(_mm512_castsi512_ps(reg),mask,_mm512_castsi512_ps(reg)));
- }
-
- static __forceinline vuint16 compact64bit(const vboolf16& mask, vuint16& v) {
- return _mm512_mask_compress_epi64(v,mask,v);
- }
-
- static __forceinline vuint16 compact(const vboolf16& mask, vuint16& v) {
- return _mm512_mask_compress_epi32(v,mask,v);
- }
-
- static __forceinline vuint16 compact(const vboolf16& mask, const vuint16& a, vuint16& b) {
- return _mm512_mask_compress_epi32(a,mask,b);
- }
-
- static __forceinline vuint16 expand(const vboolf16& mask, const vuint16& a, vuint16& b) {
- return _mm512_mask_expand_epi32(b,mask,a);
- }
-
- template<int scale = 4>
- static __forceinline vuint16 gather(const unsigned int* ptr, const vint16& index) {
- return _mm512_i32gather_epi32(index,ptr,scale);
- }
-
- template<int scale = 4>
- static __forceinline vuint16 gather(const vboolf16& mask, const unsigned int* ptr, const vint16& index) {
- return _mm512_mask_i32gather_epi32(_mm512_undefined_epi32(),mask,index,ptr,scale);
- }
-
- template<int scale = 4>
- static __forceinline vuint16 gather(const vboolf16& mask, vuint16& dest, const unsigned int* ptr, const vint16& index) {
- return _mm512_mask_i32gather_epi32(dest,mask,index,ptr,scale);
- }
-
- template<int scale = 4>
- static __forceinline void scatter(unsigned int* ptr, const vint16& index, const vuint16& v) {
- _mm512_i32scatter_epi32((int*)ptr,index,v,scale);
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf16& mask, unsigned int* ptr, const vint16& index, const vuint16& v) {
- _mm512_mask_i32scatter_epi32((int*)ptr,mask,index,v,scale);
- }
-
- static __forceinline vuint16 broadcast64bit(size_t v) {
- return _mm512_set1_epi64(v);
- }
-
- static __forceinline size_t extract64bit(const vuint16& v)
- {
- return _mm_cvtsi128_si64(_mm512_castsi512_si128(v));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline unsigned int& operator [](size_t index) { assert(index < 16); return i[index]; }
- __forceinline const unsigned int& operator [](size_t index) const { assert(index < 16); return i[index]; }
-
- __forceinline unsigned int uint (size_t index) const { assert(index < 16); return ((unsigned int*)i)[index]; }
- __forceinline size_t& uint64_t(size_t index) const { assert(index < 8); return ((size_t*)i)[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16 asBool(const vuint16& a) { return _mm512_movepi32_mask(a); }
-
- __forceinline vuint16 operator +(const vuint16& a) { return a; }
- __forceinline vuint16 operator -(const vuint16& a) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint16 operator +(const vuint16& a, const vuint16& b) { return _mm512_add_epi32(a, b); }
- __forceinline vuint16 operator +(const vuint16& a, unsigned int b) { return a + vuint16(b); }
- __forceinline vuint16 operator +(unsigned int a, const vuint16& b) { return vuint16(a) + b; }
-
- __forceinline vuint16 operator -(const vuint16& a, const vuint16& b) { return _mm512_sub_epi32(a, b); }
- __forceinline vuint16 operator -(const vuint16& a, unsigned int b) { return a - vuint16(b); }
- __forceinline vuint16 operator -(unsigned int a, const vuint16& b) { return vuint16(a) - b; }
-
- __forceinline vuint16 operator *(const vuint16& a, const vuint16& b) { return _mm512_mul_epu32(a, b); }
- __forceinline vuint16 operator *(const vuint16& a, unsigned int b) { return a * vuint16(b); }
- __forceinline vuint16 operator *(unsigned int a, const vuint16& b) { return vuint16(a) * b; }
-
- __forceinline vuint16 operator &(const vuint16& a, const vuint16& b) { return _mm512_and_epi32(a, b); }
- __forceinline vuint16 operator &(const vuint16& a, unsigned int b) { return a & vuint16(b); }
- __forceinline vuint16 operator &(unsigned int a, const vuint16& b) { return vuint16(a) & b; }
-
- __forceinline vuint16 operator |(const vuint16& a, const vuint16& b) { return _mm512_or_epi32(a, b); }
- __forceinline vuint16 operator |(const vuint16& a, unsigned int b) { return a | vuint16(b); }
- __forceinline vuint16 operator |(unsigned int a, const vuint16& b) { return vuint16(a) | b; }
-
- __forceinline vuint16 operator ^(const vuint16& a, const vuint16& b) { return _mm512_xor_epi32(a, b); }
- __forceinline vuint16 operator ^(const vuint16& a, unsigned int b) { return a ^ vuint16(b); }
- __forceinline vuint16 operator ^(unsigned int a, const vuint16& b) { return vuint16(a) ^ b; }
-
- __forceinline vuint16 operator <<(const vuint16& a, unsigned int n) { return _mm512_slli_epi32(a, n); }
- __forceinline vuint16 operator >>(const vuint16& a, unsigned int n) { return _mm512_srli_epi32(a, n); }
-
- __forceinline vuint16 operator <<(const vuint16& a, const vuint16& n) { return _mm512_sllv_epi32(a, n); }
- __forceinline vuint16 operator >>(const vuint16& a, const vuint16& n) { return _mm512_srlv_epi32(a, n); }
-
- __forceinline vuint16 sll (const vuint16& a, unsigned int b) { return _mm512_slli_epi32(a, b); }
- __forceinline vuint16 sra (const vuint16& a, unsigned int b) { return _mm512_srai_epi32(a, b); }
- __forceinline vuint16 srl (const vuint16& a, unsigned int b) { return _mm512_srli_epi32(a, b); }
-
- __forceinline vuint16 min(const vuint16& a, const vuint16& b) { return _mm512_min_epu32(a, b); }
- __forceinline vuint16 min(const vuint16& a, unsigned int b) { return min(a,vuint16(b)); }
- __forceinline vuint16 min(unsigned int a, const vuint16& b) { return min(vuint16(a),b); }
-
- __forceinline vuint16 max(const vuint16& a, const vuint16& b) { return _mm512_max_epu32(a, b); }
- __forceinline vuint16 max(const vuint16& a, unsigned int b) { return max(a,vuint16(b)); }
- __forceinline vuint16 max(unsigned int a, const vuint16& b) { return max(vuint16(a),b); }
-
- __forceinline vuint16 mask_add(const vboolf16& mask, vuint16& c, const vuint16& a, const vuint16& b) { return _mm512_mask_add_epi32(c,mask,a,b); }
- __forceinline vuint16 mask_sub(const vboolf16& mask, vuint16& c, const vuint16& a, const vuint16& b) { return _mm512_mask_sub_epi32(c,mask,a,b); }
-
- __forceinline vuint16 mask_and(const vboolf16& m, vuint16& c, const vuint16& a, const vuint16& b) { return _mm512_mask_and_epi32(c,m,a,b); }
- __forceinline vuint16 mask_or (const vboolf16& m, vuint16& c, const vuint16& a, const vuint16& b) { return _mm512_mask_or_epi32(c,m,a,b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint16& operator +=(vuint16& a, const vuint16& b) { return a = a + b; }
- __forceinline vuint16& operator +=(vuint16& a, unsigned int b) { return a = a + b; }
-
- __forceinline vuint16& operator -=(vuint16& a, const vuint16& b) { return a = a - b; }
- __forceinline vuint16& operator -=(vuint16& a, unsigned int b) { return a = a - b; }
-
- __forceinline vuint16& operator *=(vuint16& a, const vuint16& b) { return a = a * b; }
- __forceinline vuint16& operator *=(vuint16& a, unsigned int b) { return a = a * b; }
-
- __forceinline vuint16& operator &=(vuint16& a, const vuint16& b) { return a = a & b; }
- __forceinline vuint16& operator &=(vuint16& a, unsigned int b) { return a = a & b; }
-
- __forceinline vuint16& operator |=(vuint16& a, const vuint16& b) { return a = a | b; }
- __forceinline vuint16& operator |=(vuint16& a, unsigned int b) { return a = a | b; }
-
- __forceinline vuint16& operator <<=(vuint16& a, unsigned int b) { return a = a << b; }
- __forceinline vuint16& operator >>=(vuint16& a, unsigned int b) { return a = a >> b; }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf16 operator ==(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 operator ==(const vuint16& a, unsigned int b) { return a == vuint16(b); }
- __forceinline vboolf16 operator ==(unsigned int a, const vuint16& b) { return vuint16(a) == b; }
-
- __forceinline vboolf16 operator !=(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 operator !=(const vuint16& a, unsigned int b) { return a != vuint16(b); }
- __forceinline vboolf16 operator !=(unsigned int a, const vuint16& b) { return vuint16(a) != b; }
-
- __forceinline vboolf16 operator < (const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 operator < (const vuint16& a, unsigned int b) { return a < vuint16(b); }
- __forceinline vboolf16 operator < (unsigned int a, const vuint16& b) { return vuint16(a) < b; }
-
- __forceinline vboolf16 operator >=(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 operator >=(const vuint16& a, unsigned int b) { return a >= vuint16(b); }
- __forceinline vboolf16 operator >=(unsigned int a, const vuint16& b) { return vuint16(a) >= b; }
-
- __forceinline vboolf16 operator > (const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 operator > (const vuint16& a, unsigned int b) { return a > vuint16(b); }
- __forceinline vboolf16 operator > (unsigned int a, const vuint16& b) { return vuint16(a) > b; }
-
- __forceinline vboolf16 operator <=(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
- __forceinline vboolf16 operator <=(const vuint16& a, unsigned int b) { return a <= vuint16(b); }
- __forceinline vboolf16 operator <=(unsigned int a, const vuint16& b) { return vuint16(a) <= b; }
-
- __forceinline vboolf16 eq(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 ne(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 lt(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 ge(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 gt(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 le(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
-
- __forceinline vboolf16 eq(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf16 ne(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_NE); }
- __forceinline vboolf16 lt(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_LT); }
- __forceinline vboolf16 ge(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_GE); }
- __forceinline vboolf16 gt(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_GT); }
- __forceinline vboolf16 le(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_LE); }
-
-
- __forceinline vuint16 select(const vboolf16& m, const vuint16& t, const vuint16& f) {
- return _mm512_mask_or_epi32(f,m,t,t);
- }
-
- __forceinline void xchg(const vboolf16& m, vuint16& a, vuint16& b) {
- const vuint16 c = a; a = select(m,b,a); b = select(m,c,b);
- }
-
- __forceinline vboolf16 test(const vboolf16& m, const vuint16& a, const vuint16& b) {
- return _mm512_mask_test_epi32_mask(m,a,b);
- }
-
- __forceinline vboolf16 test(const vuint16& a, const vuint16& b) {
- return _mm512_test_epi32_mask(a,b);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int i>
- __forceinline vuint16 shuffle(const vuint16& v) {
- return _mm512_castps_si512(_mm512_permute_ps(_mm512_castsi512_ps(v), _MM_SHUFFLE(i, i, i, i)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint16 shuffle(const vuint16& v) {
- return _mm512_castps_si512(_mm512_permute_ps(_mm512_castsi512_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i>
- __forceinline vuint16 shuffle4(const vuint16& v) {
- return _mm512_castps_si512(_mm512_shuffle_f32x4(_mm512_castsi512_ps(v), _mm512_castsi512_ps(v) ,_MM_SHUFFLE(i, i, i, i)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint16 shuffle4(const vuint16& v) {
- return _mm512_castps_si512(_mm512_shuffle_f32x4(_mm512_castsi512_ps(v), _mm512_castsi512_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i>
- __forceinline vuint16 align_shift_right(const vuint16& a, const vuint16& b) {
- return _mm512_alignr_epi32(a, b, i);
- };
-
- __forceinline unsigned int toScalar(const vuint16& v) {
- return _mm_cvtsi128_si32(_mm512_castsi512_si128(v));
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint16 vreduce_min2(vuint16 x) { return min(x, shuffle<1,0,3,2>(x)); }
- __forceinline vuint16 vreduce_min4(vuint16 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
- __forceinline vuint16 vreduce_min8(vuint16 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0,3,2>(x)); }
- __forceinline vuint16 vreduce_min (vuint16 x) { x = vreduce_min8(x); return min(x, shuffle4<2,3,0,1>(x)); }
-
- __forceinline vuint16 vreduce_max2(vuint16 x) { return max(x, shuffle<1,0,3,2>(x)); }
- __forceinline vuint16 vreduce_max4(vuint16 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
- __forceinline vuint16 vreduce_max8(vuint16 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0,3,2>(x)); }
- __forceinline vuint16 vreduce_max (vuint16 x) { x = vreduce_max8(x); return max(x, shuffle4<2,3,0,1>(x)); }
-
- __forceinline vuint16 vreduce_and2(vuint16 x) { return x & shuffle<1,0,3,2>(x); }
- __forceinline vuint16 vreduce_and4(vuint16 x) { x = vreduce_and2(x); return x & shuffle<2,3,0,1>(x); }
- __forceinline vuint16 vreduce_and8(vuint16 x) { x = vreduce_and4(x); return x & shuffle4<1,0,3,2>(x); }
- __forceinline vuint16 vreduce_and (vuint16 x) { x = vreduce_and8(x); return x & shuffle4<2,3,0,1>(x); }
-
- __forceinline vuint16 vreduce_or2(vuint16 x) { return x | shuffle<1,0,3,2>(x); }
- __forceinline vuint16 vreduce_or4(vuint16 x) { x = vreduce_or2(x); return x | shuffle<2,3,0,1>(x); }
- __forceinline vuint16 vreduce_or8(vuint16 x) { x = vreduce_or4(x); return x | shuffle4<1,0,3,2>(x); }
- __forceinline vuint16 vreduce_or (vuint16 x) { x = vreduce_or8(x); return x | shuffle4<2,3,0,1>(x); }
-
- __forceinline vuint16 vreduce_add2(vuint16 x) { return x + shuffle<1,0,3,2>(x); }
- __forceinline vuint16 vreduce_add4(vuint16 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
- __forceinline vuint16 vreduce_add8(vuint16 x) { x = vreduce_add4(x); return x + shuffle4<1,0,3,2>(x); }
- __forceinline vuint16 vreduce_add (vuint16 x) { x = vreduce_add8(x); return x + shuffle4<2,3,0,1>(x); }
-
- __forceinline unsigned int reduce_min(const vuint16& v) { return toScalar(vreduce_min(v)); }
- __forceinline unsigned int reduce_max(const vuint16& v) { return toScalar(vreduce_max(v)); }
- __forceinline unsigned int reduce_and(const vuint16& v) { return toScalar(vreduce_and(v)); }
- __forceinline unsigned int reduce_or (const vuint16& v) { return toScalar(vreduce_or (v)); }
- __forceinline unsigned int reduce_add(const vuint16& v) { return toScalar(vreduce_add(v)); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Memory load and store operations
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint16 permute(vuint16 v, vuint16 index) {
- return _mm512_permutexvar_epi32(index,v);
- }
-
- __forceinline vuint16 reverse(const vuint16& a) {
- return permute(a,vuint16(reverse_step));
- }
-
- __forceinline vuint16 prefix_sum(const vuint16& a)
- {
- const vuint16 z(zero);
- vuint16 v = a;
- v = v + align_shift_right<16-1>(v,z);
- v = v + align_shift_right<16-2>(v,z);
- v = v + align_shift_right<16-4>(v,z);
- v = v + align_shift_right<16-8>(v,z);
- return v;
- }
-
- __forceinline vuint16 reverse_prefix_sum(const vuint16& a)
- {
- const vuint16 z(zero);
- vuint16 v = a;
- v = v + align_shift_right<1>(z,v);
- v = v + align_shift_right<2>(z,v);
- v = v + align_shift_right<4>(z,v);
- v = v + align_shift_right<8>(z,v);
- return v;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vuint16& v)
- {
- cout << "<" << v[0];
- for (int i=1; i<16; i++) cout << ", " << v[i];
- cout << ">";
- return cout;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vuint4_sse2.h b/thirdparty/embree-aarch64/common/simd/vuint4_sse2.h
deleted file mode 100644
index a3f393ebf2..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vuint4_sse2.h
+++ /dev/null
@@ -1,499 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../math/math.h"
-
-namespace embree
-{
- /* 4-wide SSE integer type */
- template<>
- struct vuint<4>
- {
- ALIGNED_STRUCT_(16);
-
- typedef vboolf4 Bool;
- typedef vuint4 Int;
- typedef vfloat4 Float;
-
- enum { size = 4 }; // number of SIMD elements
- union { __m128i v; unsigned int i[4]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint() {}
- __forceinline vuint(const vuint4& a) { v = a.v; }
- __forceinline vuint4& operator =(const vuint4& a) { v = a.v; return *this; }
-
- __forceinline vuint(const __m128i a) : v(a) {}
- __forceinline operator const __m128i&() const { return v; }
- __forceinline operator __m128i&() { return v; }
-
-
- __forceinline vuint(unsigned int a) : v(_mm_set1_epi32(a)) {}
- __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) : v(_mm_set_epi32(d, c, b, a)) {}
-
-#if defined(__AVX512VL__)
- __forceinline explicit vuint(__m128 a) : v(_mm_cvtps_epu32(a)) {}
-#endif
-
-#if defined(__AVX512VL__)
- __forceinline explicit vuint(const vboolf4& a) : v(_mm_movm_epi32(a)) {}
-#else
- __forceinline explicit vuint(const vboolf4& a) : v(_mm_castps_si128((__m128)a)) {}
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint(ZeroTy) : v(_mm_setzero_si128()) {}
- __forceinline vuint(OneTy) : v(_mm_set1_epi32(1)) {}
- __forceinline vuint(PosInfTy) : v(_mm_set1_epi32(unsigned(pos_inf))) {}
- __forceinline vuint(StepTy) : v(_mm_set_epi32(3, 2, 1, 0)) {}
- __forceinline vuint(TrueTy) { v = _mm_cmpeq_epi32(v,v); }
- __forceinline vuint(UndefinedTy) : v(_mm_castps_si128(_mm_undefined_ps())) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vuint4 load (const void* a) { return _mm_load_si128((__m128i*)a); }
- static __forceinline vuint4 loadu(const void* a) { return _mm_loadu_si128((__m128i*)a); }
-
- static __forceinline void store (void* ptr, const vuint4& v) { _mm_store_si128((__m128i*)ptr,v); }
- static __forceinline void storeu(void* ptr, const vuint4& v) { _mm_storeu_si128((__m128i*)ptr,v); }
-
-#if defined(__AVX512VL__)
- static __forceinline vuint4 load (const vboolf4& mask, const void* ptr) { return _mm_mask_load_epi32 (_mm_setzero_si128(),mask,ptr); }
- static __forceinline vuint4 loadu(const vboolf4& mask, const void* ptr) { return _mm_mask_loadu_epi32(_mm_setzero_si128(),mask,ptr); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vuint4& v) { _mm_mask_store_epi32 (ptr,mask,v); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vuint4& v) { _mm_mask_storeu_epi32(ptr,mask,v); }
-#elif defined(__AVX__)
- static __forceinline vuint4 load (const vbool4& mask, const void* a) { return _mm_castps_si128(_mm_maskload_ps((float*)a,mask)); }
- static __forceinline vuint4 loadu(const vbool4& mask, const void* a) { return _mm_castps_si128(_mm_maskload_ps((float*)a,mask)); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vuint4& i) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i)); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vuint4& i) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i)); }
-#else
- static __forceinline vuint4 load (const vbool4& mask, const void* a) { return _mm_and_si128(_mm_load_si128 ((__m128i*)a),mask); }
- static __forceinline vuint4 loadu(const vbool4& mask, const void* a) { return _mm_and_si128(_mm_loadu_si128((__m128i*)a),mask); }
-
- static __forceinline void store (const vboolf4& mask, void* ptr, const vuint4& i) { store (ptr,select(mask,i,load (ptr))); }
- static __forceinline void storeu(const vboolf4& mask, void* ptr, const vuint4& i) { storeu(ptr,select(mask,i,loadu(ptr))); }
-#endif
-
-#if defined(__aarch64__)
- static __forceinline vuint4 load(const uint8_t* ptr) {
- return _mm_load4epu8_epi32(((__m128i*)ptr));
- }
- static __forceinline vuint4 loadu(const uint8_t* ptr) {
- return _mm_load4epu8_epi32(((__m128i*)ptr));
- }
-#elif defined(__SSE4_1__)
- static __forceinline vuint4 load(const uint8_t* ptr) {
- return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
- }
-
- static __forceinline vuint4 loadu(const uint8_t* ptr) {
- return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
- }
-
-#endif
-
- static __forceinline vuint4 load(const unsigned short* ptr) {
-#if defined(__aarch64__)
- return _mm_load4epu16_epi32(((__m128i*)ptr));
-#elif defined (__SSE4_1__)
- return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr));
-#else
- return vuint4(ptr[0],ptr[1],ptr[2],ptr[3]);
-#endif
- }
-
- static __forceinline void store_uint8(uint8_t* ptr, const vuint4& v) {
-#if defined(__aarch64__)
- uint32x4_t x = uint32x4_t(v.v);
- uint16x4_t y = vqmovn_u32(x);
- uint8x8_t z = vqmovn_u16(vcombine_u16(y, y));
- vst1_lane_u32((uint32_t *)ptr, uint32x2_t(z), 0);
-#elif defined(__SSE4_1__)
- __m128i x = v;
- x = _mm_packus_epi32(x, x);
- x = _mm_packus_epi16(x, x);
- *(unsigned*)ptr = _mm_cvtsi128_si32(x);
-#else
- for (size_t i=0;i<4;i++)
- ptr[i] = (uint8_t)v[i];
-#endif
- }
-
- static __forceinline void store_uint8(unsigned short* ptr, const vuint4& v) {
-#if defined(__aarch64__)
- uint32x4_t x = (uint32x4_t)v.v;
- uint16x4_t y = vqmovn_u32(x);
- vst1_u16(ptr, y);
-#else
- for (size_t i=0;i<4;i++)
- ptr[i] = (unsigned short)v[i];
-#endif
- }
-
- static __forceinline vuint4 load_nt(void* ptr) {
-#if (defined(__aarch64__)) || defined(__SSE4_1__)
- return _mm_stream_load_si128((__m128i*)ptr);
-#else
- return _mm_load_si128((__m128i*)ptr);
-#endif
- }
-
- static __forceinline void store_nt(void* ptr, const vuint4& v) {
-#if !defined(__aarch64__) && defined(__SSE4_1__)
- _mm_stream_ps((float*)ptr, _mm_castsi128_ps(v));
-#else
- _mm_store_si128((__m128i*)ptr,v);
-#endif
- }
-
- template<int scale = 4>
- static __forceinline vuint4 gather(const unsigned int* ptr, const vint4& index) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return _mm_i32gather_epi32((const int*)ptr, index, scale);
-#else
- return vuint4(
- *(unsigned int*)(((int8_t*)ptr)+scale*index[0]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[1]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[2]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[3]));
-#endif
- }
-
- template<int scale = 4>
- static __forceinline vuint4 gather(const vboolf4& mask, const unsigned int* ptr, const vint4& index) {
- vuint4 r = zero;
-#if defined(__AVX512VL__)
- return _mm_mmask_i32gather_epi32(r, mask, index, ptr, scale);
-#elif defined(__AVX2__) && !defined(__aarch64__)
- return _mm_mask_i32gather_epi32(r, (const int*)ptr, index, mask, scale);
-#else
- if (likely(mask[0])) r[0] = *(unsigned int*)(((int8_t*)ptr)+scale*index[0]);
- if (likely(mask[1])) r[1] = *(unsigned int*)(((int8_t*)ptr)+scale*index[1]);
- if (likely(mask[2])) r[2] = *(unsigned int*)(((int8_t*)ptr)+scale*index[2]);
- if (likely(mask[3])) r[3] = *(unsigned int*)(((int8_t*)ptr)+scale*index[3]);
- return r;
-#endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const unsigned int& operator [](size_t index) const { assert(index < 4); return i[index]; }
- __forceinline unsigned int& operator [](size_t index) { assert(index < 4); return i[index]; }
-
- friend __forceinline vuint4 select(const vboolf4& m, const vuint4& t, const vuint4& f) {
-#if defined(__AVX512VL__)
- return _mm_mask_blend_epi32(m, (__m128i)f, (__m128i)t);
-#elif defined(__SSE4_1__)
- return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
-#else
- return _mm_or_si128(_mm_and_si128(m, t), _mm_andnot_si128(m, f));
-#endif
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboolf4 asBool(const vuint4& a) { return _mm_movepi32_mask(a); }
-#else
- __forceinline vboolf4 asBool(const vuint4& a) { return _mm_castsi128_ps(a); }
-#endif
-
- __forceinline vuint4 operator +(const vuint4& a) { return a; }
- __forceinline vuint4 operator -(const vuint4& a) { return _mm_sub_epi32(_mm_setzero_si128(), a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint4 operator +(const vuint4& a, const vuint4& b) { return _mm_add_epi32(a, b); }
- __forceinline vuint4 operator +(const vuint4& a, unsigned int b) { return a + vuint4(b); }
- __forceinline vuint4 operator +(unsigned int a, const vuint4& b) { return vuint4(a) + b; }
-
- __forceinline vuint4 operator -(const vuint4& a, const vuint4& b) { return _mm_sub_epi32(a, b); }
- __forceinline vuint4 operator -(const vuint4& a, unsigned int b) { return a - vuint4(b); }
- __forceinline vuint4 operator -(unsigned int a, const vuint4& b) { return vuint4(a) - b; }
-
-//#if defined(__SSE4_1__)
-// __forceinline vuint4 operator *(const vuint4& a, const vuint4& b) { return _mm_mullo_epu32(a, b); }
-//#else
-// __forceinline vuint4 operator *(const vuint4& a, const vuint4& b) { return vuint4(a[0]*b[0],a[1]*b[1],a[2]*b[2],a[3]*b[3]); }
-//#endif
-// __forceinline vuint4 operator *(const vuint4& a, unsigned int b) { return a * vuint4(b); }
-// __forceinline vuint4 operator *(unsigned int a, const vuint4& b) { return vuint4(a) * b; }
-
- __forceinline vuint4 operator &(const vuint4& a, const vuint4& b) { return _mm_and_si128(a, b); }
- __forceinline vuint4 operator &(const vuint4& a, unsigned int b) { return a & vuint4(b); }
- __forceinline vuint4 operator &(unsigned int a, const vuint4& b) { return vuint4(a) & b; }
-
- __forceinline vuint4 operator |(const vuint4& a, const vuint4& b) { return _mm_or_si128(a, b); }
- __forceinline vuint4 operator |(const vuint4& a, unsigned int b) { return a | vuint4(b); }
- __forceinline vuint4 operator |(unsigned int a, const vuint4& b) { return vuint4(a) | b; }
-
- __forceinline vuint4 operator ^(const vuint4& a, const vuint4& b) { return _mm_xor_si128(a, b); }
- __forceinline vuint4 operator ^(const vuint4& a, unsigned int b) { return a ^ vuint4(b); }
- __forceinline vuint4 operator ^(unsigned int a, const vuint4& b) { return vuint4(a) ^ b; }
-
- __forceinline vuint4 operator <<(const vuint4& a, unsigned int n) { return _mm_slli_epi32(a, n); }
- __forceinline vuint4 operator >>(const vuint4& a, unsigned int n) { return _mm_srli_epi32(a, n); }
-
- __forceinline vuint4 sll (const vuint4& a, unsigned int b) { return _mm_slli_epi32(a, b); }
- __forceinline vuint4 sra (const vuint4& a, unsigned int b) { return _mm_srai_epi32(a, b); }
- __forceinline vuint4 srl (const vuint4& a, unsigned int b) { return _mm_srli_epi32(a, b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint4& operator +=(vuint4& a, const vuint4& b) { return a = a + b; }
- __forceinline vuint4& operator +=(vuint4& a, unsigned int b) { return a = a + b; }
-
- __forceinline vuint4& operator -=(vuint4& a, const vuint4& b) { return a = a - b; }
- __forceinline vuint4& operator -=(vuint4& a, unsigned int b) { return a = a - b; }
-
-//#if defined(__SSE4_1__)
-// __forceinline vuint4& operator *=(vuint4& a, const vuint4& b) { return a = a * b; }
-// __forceinline vuint4& operator *=(vuint4& a, unsigned int b) { return a = a * b; }
-//#endif
-
- __forceinline vuint4& operator &=(vuint4& a, const vuint4& b) { return a = a & b; }
- __forceinline vuint4& operator &=(vuint4& a, unsigned int b) { return a = a & b; }
-
- __forceinline vuint4& operator |=(vuint4& a, const vuint4& b) { return a = a | b; }
- __forceinline vuint4& operator |=(vuint4& a, unsigned int b) { return a = a | b; }
-
- __forceinline vuint4& operator <<=(vuint4& a, unsigned int b) { return a = a << b; }
- __forceinline vuint4& operator >>=(vuint4& a, unsigned int b) { return a = a >> b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboolf4 operator ==(const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf4 operator !=(const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
- //__forceinline vboolf4 operator < (const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
- //__forceinline vboolf4 operator >=(const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
- //__forceinline vboolf4 operator > (const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
- //__forceinline vboolf4 operator <=(const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
-#else
- __forceinline vboolf4 operator ==(const vuint4& a, const vuint4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
- __forceinline vboolf4 operator !=(const vuint4& a, const vuint4& b) { return !(a == b); }
- //__forceinline vboolf4 operator < (const vuint4& a, const vuint4& b) { return _mm_castsi128_ps(_mm_cmplt_epu32(a, b)); }
- //__forceinline vboolf4 operator >=(const vuint4& a, const vuint4& b) { return !(a < b); }
- //__forceinline vboolf4 operator > (const vuint4& a, const vuint4& b) { return _mm_castsi128_ps(_mm_cmpgt_epu32(a, b)); }
- //__forceinline vboolf4 operator <=(const vuint4& a, const vuint4& b) { return !(a > b); }
-#endif
-
- __forceinline vboolf4 operator ==(const vuint4& a, unsigned int b) { return a == vuint4(b); }
- __forceinline vboolf4 operator ==(unsigned int a, const vuint4& b) { return vuint4(a) == b; }
-
- __forceinline vboolf4 operator !=(const vuint4& a, unsigned int b) { return a != vuint4(b); }
- __forceinline vboolf4 operator !=(unsigned int a, const vuint4& b) { return vuint4(a) != b; }
-
- //__forceinline vboolf4 operator < (const vuint4& a, unsigned int b) { return a < vuint4(b); }
- //__forceinline vboolf4 operator < (unsigned int a, const vuint4& b) { return vuint4(a) < b; }
-
- //__forceinline vboolf4 operator >=(const vuint4& a, unsigned int b) { return a >= vuint4(b); }
- //__forceinline vboolf4 operator >=(unsigned int a, const vuint4& b) { return vuint4(a) >= b; }
-
- //__forceinline vboolf4 operator > (const vuint4& a, unsigned int b) { return a > vuint4(b); }
- //__forceinline vboolf4 operator > (unsigned int a, const vuint4& b) { return vuint4(a) > b; }
-
- //__forceinline vboolf4 operator <=(const vuint4& a, unsigned int b) { return a <= vuint4(b); }
- //__forceinline vboolf4 operator <=(unsigned int a, const vuint4& b) { return vuint4(a) <= b; }
-
- __forceinline vboolf4 eq(const vuint4& a, const vuint4& b) { return a == b; }
- __forceinline vboolf4 ne(const vuint4& a, const vuint4& b) { return a != b; }
- //__forceinline vboolf4 lt(const vuint4& a, const vuint4& b) { return a < b; }
- //__forceinline vboolf4 ge(const vuint4& a, const vuint4& b) { return a >= b; }
- //__forceinline vboolf4 gt(const vuint4& a, const vuint4& b) { return a > b; }
- //__forceinline vboolf4 le(const vuint4& a, const vuint4& b) { return a <= b; }
-
-#if defined(__AVX512VL__)
- __forceinline vboolf4 eq(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_EQ); }
- __forceinline vboolf4 ne(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_NE); }
- //__forceinline vboolf4 lt(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LT); }
- //__forceinline vboolf4 ge(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GE); }
- //__forceinline vboolf4 gt(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GT); }
- //__forceinline vboolf4 le(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LE); }
-#else
- __forceinline vboolf4 eq(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a == b); }
- __forceinline vboolf4 ne(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a != b); }
- //__forceinline vboolf4 lt(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a < b); }
- //__forceinline vboolf4 ge(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a >= b); }
- //__forceinline vboolf4 gt(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a > b); }
- //__forceinline vboolf4 le(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a <= b); }
-#endif
-
- template<int mask>
- __forceinline vuint4 select(const vuint4& t, const vuint4& f) {
-#if defined(__SSE4_1__)
- return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), mask));
-#else
- return select(vboolf4(mask), t, f);
-#endif
- }
-
-/*#if defined(__SSE4_1__)
- __forceinline vuint4 min(const vuint4& a, const vuint4& b) { return _mm_min_epu32(a, b); }
- __forceinline vuint4 max(const vuint4& a, const vuint4& b) { return _mm_max_epu32(a, b); }
-
-#else
- __forceinline vuint4 min(const vuint4& a, const vuint4& b) { return select(a < b,a,b); }
- __forceinline vuint4 max(const vuint4& a, const vuint4& b) { return select(a < b,b,a); }
-#endif
-
- __forceinline vuint4 min(const vuint4& a, unsigned int b) { return min(a,vuint4(b)); }
- __forceinline vuint4 min(unsigned int a, const vuint4& b) { return min(vuint4(a),b); }
- __forceinline vuint4 max(const vuint4& a, unsigned int b) { return max(a,vuint4(b)); }
- __forceinline vuint4 max(unsigned int a, const vuint4& b) { return max(vuint4(a),b); }*/
-
- ////////////////////////////////////////////////////////////////////////////////
- // Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint4 unpacklo(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
- __forceinline vuint4 unpackhi(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
-
-#if defined(__aarch64__)
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint4 shuffle(const vuint4& v) {
- return vreinterpretq_s32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3)));
- }
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint4 shuffle(const vuint4& a, const vuint4& b) {
- return vreinterpretq_s32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3)));
- }
-#else
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint4 shuffle(const vuint4& v) {
- return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0));
- }
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint4 shuffle(const vuint4& a, const vuint4& b) {
- return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-#endif
-#if defined(__SSE3__)
- template<> __forceinline vuint4 shuffle<0, 0, 2, 2>(const vuint4& v) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(v))); }
- template<> __forceinline vuint4 shuffle<1, 1, 3, 3>(const vuint4& v) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(v))); }
- template<> __forceinline vuint4 shuffle<0, 1, 0, 1>(const vuint4& v) { return _mm_castpd_si128(_mm_movedup_pd (_mm_castsi128_pd(v))); }
-#endif
-
- template<int i>
- __forceinline vuint4 shuffle(const vuint4& v) {
- return shuffle<i,i,i,i>(v);
- }
-
-#if defined(__aarch64__)
- template<int src> __forceinline unsigned int extract(const vuint4& b);
- template<int dst> __forceinline vuint4 insert(const vuint4& a, const unsigned b);
-#elif defined(__SSE4_1__)
- template<int src> __forceinline unsigned int extract(const vuint4& b) { return _mm_extract_epi32(b, src); }
- template<int dst> __forceinline vuint4 insert(const vuint4& a, const unsigned b) { return _mm_insert_epi32(a, b, dst); }
-#else
- template<int src> __forceinline unsigned int extract(const vuint4& b) { return b[src&3]; }
- template<int dst> __forceinline vuint4 insert(const vuint4& a, const unsigned b) { vuint4 c = a; c[dst&3] = b; return c; }
-#endif
-
-#if defined(__aarch64__)
- template<> __forceinline unsigned int extract<0>(const vuint4& b) {
- return b[0];
- }
- template<> __forceinline unsigned int extract<1>(const vuint4& b) {
- return b[1];
- }
- template<> __forceinline unsigned int extract<2>(const vuint4& b) {
- return b[2];
- }
- template<> __forceinline unsigned int extract<3>(const vuint4& b) {
- return b[3];
- }
-
- template<> __forceinline vuint4 insert<0>(const vuint4& a, unsigned b){
- vuint4 c = a;
- c[0] = b;
- return c;
- }
- template<> __forceinline vuint4 insert<1>(const vuint4& a, unsigned b){
- vuint4 c = a;
- c[1] = b;
- return c;
- }
- template<> __forceinline vuint4 insert<2>(const vuint4& a, unsigned b){
- vuint4 c = a;
- c[2] = b;
- return c;
- }
- template<> __forceinline vuint4 insert<3>(const vuint4& a, unsigned b){
- vuint4 c = a;
- c[3] = b;
- return c;
- }
-
- __forceinline unsigned int toScalar(const vuint4& v) {
- return v[0];
- }
-#else
- template<> __forceinline unsigned int extract<0>(const vuint4& b) { return _mm_cvtsi128_si32(b); }
-
- __forceinline unsigned int toScalar(const vuint4& v) { return _mm_cvtsi128_si32(v); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
-#if 0
-#if defined(__SSE4_1__)
-
- __forceinline vuint4 vreduce_min(const vuint4& v) { vuint4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
- __forceinline vuint4 vreduce_max(const vuint4& v) { vuint4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
- __forceinline vuint4 vreduce_add(const vuint4& v) { vuint4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
-
- __forceinline unsigned int reduce_min(const vuint4& v) { return toScalar(vreduce_min(v)); }
- __forceinline unsigned int reduce_max(const vuint4& v) { return toScalar(vreduce_max(v)); }
- __forceinline unsigned int reduce_add(const vuint4& v) { return toScalar(vreduce_add(v)); }
-
- __forceinline size_t select_min(const vuint4& v) { return bsf(movemask(v == vreduce_min(v))); }
- __forceinline size_t select_max(const vuint4& v) { return bsf(movemask(v == vreduce_max(v))); }
-
- //__forceinline size_t select_min(const vboolf4& valid, const vuint4& v) { const vuint4 a = select(valid,v,vuint4(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
- //__forceinline size_t select_max(const vboolf4& valid, const vuint4& v) { const vuint4 a = select(valid,v,vuint4(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
-
-#else
-
- __forceinline unsigned int reduce_min(const vuint4& v) { return min(v[0],v[1],v[2],v[3]); }
- __forceinline unsigned int reduce_max(const vuint4& v) { return max(v[0],v[1],v[2],v[3]); }
- __forceinline unsigned int reduce_add(const vuint4& v) { return v[0]+v[1]+v[2]+v[3]; }
-
-#endif
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vuint4& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
- }
-}
-
diff --git a/thirdparty/embree-aarch64/common/simd/vuint8_avx.h b/thirdparty/embree-aarch64/common/simd/vuint8_avx.h
deleted file mode 100644
index d4e86ae92d..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vuint8_avx.h
+++ /dev/null
@@ -1,379 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX integer type */
- template<>
- struct vuint<8>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboolf8 Bool;
- typedef vuint8 Int;
- typedef vfloat8 Float;
-
- enum { size = 8 }; // number of SIMD elements
- union { // data
- __m256i v;
- struct { __m128i vl,vh; };
- unsigned int i[8];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint() {}
- __forceinline vuint(const vuint8& a) { v = a.v; }
- __forceinline vuint8& operator =(const vuint8& a) { v = a.v; return *this; }
-
- __forceinline vuint(__m256i a) : v(a) {}
- __forceinline operator const __m256i&() const { return v; }
- __forceinline operator __m256i&() { return v; }
-
- __forceinline explicit vuint(const vuint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
- __forceinline vuint(const vuint4& a, const vuint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
- __forceinline vuint(const __m128i& a, const __m128i& b) : vl(a), vh(b) {}
-
- __forceinline explicit vuint(const unsigned int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
- __forceinline vuint(unsigned int a) : v(_mm256_set1_epi32(a)) {}
- __forceinline vuint(unsigned int a, unsigned int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
- __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
- __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f, unsigned int g, unsigned int vh) : v(_mm256_set_epi32(vh, g, f, e, d, c, b, a)) {}
-
- __forceinline explicit vuint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint(ZeroTy) : v(_mm256_setzero_si256()) {}
- __forceinline vuint(OneTy) : v(_mm256_set1_epi32(1)) {}
- __forceinline vuint(PosInfTy) : v(_mm256_set1_epi32(0xFFFFFFFF)) {}
- __forceinline vuint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
- __forceinline vuint(UndefinedTy) : v(_mm256_undefined_si256()) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vuint8 load (const void* a) { return _mm256_castps_si256(_mm256_load_ps((float*)a)); }
- static __forceinline vuint8 loadu(const void* a) { return _mm256_castps_si256(_mm256_loadu_ps((float*)a)); }
-
- static __forceinline vuint8 load (const vboolf8& mask, const void* a) { return _mm256_castps_si256(_mm256_maskload_ps((float*)a,mask)); }
- static __forceinline vuint8 loadu(const vboolf8& mask, const void* a) { return _mm256_castps_si256(_mm256_maskload_ps((float*)a,mask)); }
-
- static __forceinline void store (void* ptr, const vuint8& f) { _mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f)); }
- static __forceinline void storeu(void* ptr, const vuint8& f) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f)); }
-
-#if !defined(__aarch64__)
- static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
-#else
- static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask.v,_mm256_castsi256_ps(f)); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask.v,_mm256_castsi256_ps(f)); }
-#endif
- static __forceinline void store_nt(void* ptr, const vuint8& v) {
- _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
- }
-
- static __forceinline vuint8 load(const uint8_t* ptr) {
- vuint4 il = vuint4::load(ptr+0);
- vuint4 ih = vuint4::load(ptr+4);
- return vuint8(il,ih);
- }
-
- static __forceinline vuint8 loadu(const uint8_t* ptr) {
- vuint4 il = vuint4::loadu(ptr+0);
- vuint4 ih = vuint4::loadu(ptr+4);
- return vuint8(il,ih);
- }
-
- static __forceinline vuint8 load(const unsigned short* ptr) {
- vuint4 il = vuint4::load(ptr+0);
- vuint4 ih = vuint4::load(ptr+4);
- return vuint8(il,ih);
- }
-
- static __forceinline vuint8 loadu(const unsigned short* ptr) {
- vuint4 il = vuint4::loadu(ptr+0);
- vuint4 ih = vuint4::loadu(ptr+4);
- return vuint8(il,ih);
- }
-
- static __forceinline void store(uint8_t* ptr, const vuint8& i) {
- vuint4 il(i.vl);
- vuint4 ih(i.vh);
- vuint4::store(ptr + 0,il);
- vuint4::store(ptr + 4,ih);
- }
-
- static __forceinline void store(unsigned short* ptr, const vuint8& v) {
- for (size_t i=0;i<8;i++)
- ptr[i] = (unsigned short)v[i];
- }
-
- template<int scale = 4>
- static __forceinline vuint8 gather(const unsigned int* ptr, const vint8& index) {
- return vuint8(
- *(unsigned int*)(((int8_t*)ptr)+scale*index[0]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[1]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[2]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[3]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[4]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[5]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[6]),
- *(unsigned int*)(((int8_t*)ptr)+scale*index[7]));
- }
-
- template<int scale = 4>
- static __forceinline vuint8 gather(const vboolf8& mask, const unsigned int* ptr, const vint8& index) {
- vuint8 r = zero;
- if (likely(mask[0])) r[0] = *(unsigned int*)(((int8_t*)ptr)+scale*index[0]);
- if (likely(mask[1])) r[1] = *(unsigned int*)(((int8_t*)ptr)+scale*index[1]);
- if (likely(mask[2])) r[2] = *(unsigned int*)(((int8_t*)ptr)+scale*index[2]);
- if (likely(mask[3])) r[3] = *(unsigned int*)(((int8_t*)ptr)+scale*index[3]);
- if (likely(mask[4])) r[4] = *(unsigned int*)(((int8_t*)ptr)+scale*index[4]);
- if (likely(mask[5])) r[5] = *(unsigned int*)(((int8_t*)ptr)+scale*index[5]);
- if (likely(mask[6])) r[6] = *(unsigned int*)(((int8_t*)ptr)+scale*index[6]);
- if (likely(mask[7])) r[7] = *(unsigned int*)(((int8_t*)ptr)+scale*index[7]);
- return r;
- }
-
- template<int scale = 4>
- static __forceinline void scatter(void* ptr, const vint8& ofs, const vuint8& v)
- {
- *(unsigned int*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- *(unsigned int*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- *(unsigned int*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- *(unsigned int*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- *(unsigned int*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- *(unsigned int*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- *(unsigned int*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- *(unsigned int*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vuint8& v)
- {
- if (likely(mask[0])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- if (likely(mask[1])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- if (likely(mask[2])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- if (likely(mask[3])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- if (likely(mask[4])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- if (likely(mask[5])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- if (likely(mask[6])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- if (likely(mask[7])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
- }
-
-
- static __forceinline vuint8 broadcast64(const long long& a) { return _mm256_set1_epi64x(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const unsigned int& operator [](size_t index) const { assert(index < 8); return i[index]; }
- __forceinline unsigned int& operator [](size_t index) { assert(index < 8); return i[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 asBool(const vuint8& a) { return _mm256_castsi256_ps(a); }
-
- __forceinline vuint8 operator +(const vuint8& a) { return a; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint8 operator +(const vuint8& a, const vuint8& b) { return vuint8(_mm_add_epi32(a.vl, b.vl), _mm_add_epi32(a.vh, b.vh)); }
- __forceinline vuint8 operator +(const vuint8& a, unsigned int b) { return a + vuint8(b); }
- __forceinline vuint8 operator +(unsigned int a, const vuint8& b) { return vuint8(a) + b; }
-
- __forceinline vuint8 operator -(const vuint8& a, const vuint8& b) { return vuint8(_mm_sub_epi32(a.vl, b.vl), _mm_sub_epi32(a.vh, b.vh)); }
- __forceinline vuint8 operator -(const vuint8& a, unsigned int b) { return a - vuint8(b); }
- __forceinline vuint8 operator -(unsigned int a, const vuint8& b) { return vuint8(a) - b; }
-
- //__forceinline vuint8 operator *(const vuint8& a, const vuint8& b) { return vuint8(_mm_mullo_epu32(a.vl, b.vl), _mm_mullo_epu32(a.vh, b.vh)); }
- //__forceinline vuint8 operator *(const vuint8& a, unsigned int b) { return a * vuint8(b); }
- //__forceinline vuint8 operator *(unsigned int a, const vuint8& b) { return vuint8(a) * b; }
-
- __forceinline vuint8 operator &(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_and_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
- __forceinline vuint8 operator &(const vuint8& a, unsigned int b) { return a & vuint8(b); }
- __forceinline vuint8 operator &(unsigned int a, const vuint8& b) { return vuint8(a) & b; }
-
- __forceinline vuint8 operator |(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_or_ps (_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
- __forceinline vuint8 operator |(const vuint8& a, unsigned int b) { return a | vuint8(b); }
- __forceinline vuint8 operator |(unsigned int a, const vuint8& b) { return vuint8(a) | b; }
-
- __forceinline vuint8 operator ^(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
- __forceinline vuint8 operator ^(const vuint8& a, unsigned int b) { return a ^ vuint8(b); }
- __forceinline vuint8 operator ^(unsigned int a, const vuint8& b) { return vuint8(a) ^ b; }
-
- __forceinline vuint8 operator <<(const vuint8& a, unsigned int n) { return vuint8(_mm_slli_epi32(a.vl, n), _mm_slli_epi32(a.vh, n)); }
- __forceinline vuint8 operator >>(const vuint8& a, unsigned int n) { return vuint8(_mm_srai_epi32(a.vl, n), _mm_srli_epi32(a.vh, n)); }
-
- __forceinline vuint8 sll (const vuint8& a, unsigned int b) { return vuint8(_mm_slli_epi32(a.vl, b), _mm_slli_epi32(a.vh, b)); }
- __forceinline vuint8 sra (const vuint8& a, unsigned int b) { return vuint8(_mm_srai_epi32(a.vl, b), _mm_srai_epi32(a.vh, b)); }
- __forceinline vuint8 srl (const vuint8& a, unsigned int b) { return vuint8(_mm_srli_epi32(a.vl, b), _mm_srli_epi32(a.vh, b)); }
-
- __forceinline vuint8 min(const vuint8& a, const vuint8& b) { return vuint8(_mm_min_epu32(a.vl, b.vl), _mm_min_epu32(a.vh, b.vh)); }
- __forceinline vuint8 min(const vuint8& a, unsigned int b) { return min(a,vuint8(b)); }
- __forceinline vuint8 min(unsigned int a, const vuint8& b) { return min(vuint8(a),b); }
-
- __forceinline vuint8 max(const vuint8& a, const vuint8& b) { return vuint8(_mm_max_epu32(a.vl, b.vl), _mm_max_epu32(a.vh, b.vh)); }
- __forceinline vuint8 max(const vuint8& a, unsigned int b) { return max(a,vuint8(b)); }
- __forceinline vuint8 max(unsigned int a, const vuint8& b) { return max(vuint8(a),b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint8& operator +=(vuint8& a, const vuint8& b) { return a = a + b; }
- __forceinline vuint8& operator +=(vuint8& a, unsigned int b) { return a = a + b; }
-
- __forceinline vuint8& operator -=(vuint8& a, const vuint8& b) { return a = a - b; }
- __forceinline vuint8& operator -=(vuint8& a, unsigned int b) { return a = a - b; }
-
- //__forceinline vuint8& operator *=(vuint8& a, const vuint8& b) { return a = a * b; }
- //__forceinline vuint8& operator *=(vuint8& a, unsigned int b) { return a = a * b; }
-
- __forceinline vuint8& operator &=(vuint8& a, const vuint8& b) { return a = a & b; }
- __forceinline vuint8& operator &=(vuint8& a, unsigned int b) { return a = a & b; }
-
- __forceinline vuint8& operator |=(vuint8& a, const vuint8& b) { return a = a | b; }
- __forceinline vuint8& operator |=(vuint8& a, unsigned int b) { return a = a | b; }
-
- __forceinline vuint8& operator <<=(vuint8& a, unsigned int b) { return a = a << b; }
- __forceinline vuint8& operator >>=(vuint8& a, unsigned int b) { return a = a >> b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vboolf8 operator ==(const vuint8& a, const vuint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmpeq_epi32 (a.vl, b.vl)),
- _mm_castsi128_ps(_mm_cmpeq_epi32 (a.vh, b.vh))); }
- __forceinline vboolf8 operator ==(const vuint8& a, unsigned int b) { return a == vuint8(b); }
- __forceinline vboolf8 operator ==(unsigned int a, const vuint8& b) { return vuint8(a) == b; }
-
- __forceinline vboolf8 operator !=(const vuint8& a, const vuint8& b) { return !(a == b); }
- __forceinline vboolf8 operator !=(const vuint8& a, unsigned int b) { return a != vuint8(b); }
- __forceinline vboolf8 operator !=(unsigned int a, const vuint8& b) { return vuint8(a) != b; }
-
- //__forceinline vboolf8 operator < (const vuint8& a, const vuint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmplt_epu32 (a.vl, b.vl)),
- // _mm_castsi128_ps(_mm_cmplt_epu32 (a.vh, b.vh))); }
- //__forceinline vboolf8 operator < (const vuint8& a, unsigned int b) { return a < vuint8(b); }
- //__forceinline vboolf8 operator < (unsigned int a, const vuint8& b) { return vuint8(a) < b; }
-
- //__forceinline vboolf8 operator >=(const vuint8& a, const vuint8& b) { return !(a < b); }
- //__forceinline vboolf8 operator >=(const vuint8& a, unsigned int b) { return a >= vuint8(b); }
- //__forceinline vboolf8 operator >=(unsigned int a, const vuint8& b) { return vuint8(a) >= b; }
-
- //__forceinline vboolf8 operator > (const vuint8& a, const vuint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmpgt_epu32 (a.vl, b.vl)),
- // _mm_castsi128_ps(_mm_cmpgt_epu32 (a.vh, b.vh))); }
- //__forceinline vboolf8 operator > (const vuint8& a, unsigned int b) { return a > vuint8(b); }
- //__forceinline vboolf8 operator > (unsigned int a, const vuint8& b) { return vuint8(a) > b; }
-
- //__forceinline vboolf8 operator <=(const vuint8& a, const vuint8& b) { return !(a > b); }
- //__forceinline vboolf8 operator <=(const vuint8& a, unsigned int b) { return a <= vuint8(b); }
- //__forceinline vboolf8 operator <=(unsigned int a, const vuint8& b) { return vuint8(a) <= b; }
-
- __forceinline vboolf8 eq(const vuint8& a, const vuint8& b) { return a == b; }
- __forceinline vboolf8 ne(const vuint8& a, const vuint8& b) { return a != b; }
-
- __forceinline vboolf8 eq(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a == b); }
- __forceinline vboolf8 ne(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a != b); }
-
- __forceinline vuint8 select(const vboolf8& m, const vuint8& t, const vuint8& f) {
- return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
- }
-
- __forceinline vuint8 notand(const vboolf8& m, const vuint8& f) {
- return _mm256_castps_si256(_mm256_andnot_ps(m, _mm256_castsi256_ps(f)));
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint8 unpacklo(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_unpacklo_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
- __forceinline vuint8 unpackhi(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_unpackhi_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
-
- template<int i>
- __forceinline vuint8 shuffle(const vuint8& v) {
- return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
- }
-
- template<int i0, int i1>
- __forceinline vuint8 shuffle4(const vuint8& v) {
- return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1>
- __forceinline vuint8 shuffle4(const vuint8& a, const vuint8& b) {
- return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint8 shuffle(const vuint8& v) {
- return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint8 shuffle(const vuint8& a, const vuint8& b) {
- return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<> __forceinline vuint8 shuffle<0, 0, 2, 2>(const vuint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
- template<> __forceinline vuint8 shuffle<1, 1, 3, 3>(const vuint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
- template<> __forceinline vuint8 shuffle<0, 1, 0, 1>(const vuint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
-
- __forceinline vuint8 broadcast(const unsigned int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
- template<int i> __forceinline vuint8 insert4(const vuint8& a, const vuint4& b) { return _mm256_insertf128_si256(a, b, i); }
- template<int i> __forceinline vuint4 extract4(const vuint8& a) { return _mm256_extractf128_si256(a, i); }
- template<> __forceinline vuint4 extract4<0>(const vuint8& a) { return _mm256_castsi256_si128(a); }
-
- __forceinline int toScalar(const vuint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- //__forceinline vuint8 vreduce_min2(const vuint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
- //__forceinline vuint8 vreduce_min4(const vuint8& v) { vuint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
- //__forceinline vuint8 vreduce_min (const vuint8& v) { vuint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
-
- //__forceinline vuint8 vreduce_max2(const vuint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
- //__forceinline vuint8 vreduce_max4(const vuint8& v) { vuint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
- //__forceinline vuint8 vreduce_max (const vuint8& v) { vuint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
-
- __forceinline vuint8 vreduce_add2(const vuint8& v) { return v + shuffle<1,0,3,2>(v); }
- __forceinline vuint8 vreduce_add4(const vuint8& v) { vuint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
- __forceinline vuint8 vreduce_add (const vuint8& v) { vuint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
-
- //__forceinline int reduce_min(const vuint8& v) { return toScalar(vreduce_min(v)); }
- //__forceinline int reduce_max(const vuint8& v) { return toScalar(vreduce_max(v)); }
- __forceinline int reduce_add(const vuint8& v) { return toScalar(vreduce_add(v)); }
-
- //__forceinline size_t select_min(const vuint8& v) { return bsf(movemask(v == vreduce_min(v))); }
- //__forceinline size_t select_max(const vuint8& v) { return bsf(movemask(v == vreduce_max(v))); }
-
- //__forceinline size_t select_min(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
- //__forceinline size_t select_max(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vuint8& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/simd/vuint8_avx2.h b/thirdparty/embree-aarch64/common/simd/vuint8_avx2.h
deleted file mode 100644
index b2a965448d..0000000000
--- a/thirdparty/embree-aarch64/common/simd/vuint8_avx2.h
+++ /dev/null
@@ -1,439 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* 8-wide AVX integer type */
- template<>
- struct vuint<8>
- {
- ALIGNED_STRUCT_(32);
-
- typedef vboolf8 Bool;
- typedef vuint8 Int;
- typedef vfloat8 Float;
-
- enum { size = 8 }; // number of SIMD elements
- union { // data
- __m256i v;
- unsigned int i[8];
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint() {}
- __forceinline vuint(const vuint8& a) { v = a.v; }
- __forceinline vuint8& operator =(const vuint8& a) { v = a.v; return *this; }
-
- __forceinline vuint(__m256i a) : v(a) {}
- __forceinline operator const __m256i&() const { return v; }
- __forceinline operator __m256i&() { return v; }
-
- __forceinline explicit vuint(const vuint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
- __forceinline vuint(const vuint4& a, const vuint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
- __forceinline vuint(const __m128i& a, const __m128i& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
-
- __forceinline explicit vuint(const unsigned int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
- __forceinline vuint(unsigned int a) : v(_mm256_set1_epi32(a)) {}
- __forceinline vuint(unsigned int a, unsigned int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
- __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
- __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f, unsigned int g, unsigned int h) : v(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
-
- __forceinline explicit vuint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
-
-#if defined(__AVX512VL__)
- __forceinline explicit vuint(const vboolf8& a) : v(_mm256_movm_epi32(a)) {}
-#else
- __forceinline explicit vuint(const vboolf8& a) : v(_mm256_castps_si256((__m256)a)) {}
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint(ZeroTy) : v(_mm256_setzero_si256()) {}
- __forceinline vuint(OneTy) : v(_mm256_set1_epi32(1)) {}
- __forceinline vuint(PosInfTy) : v(_mm256_set1_epi32(pos_inf)) {}
- __forceinline vuint(NegInfTy) : v(_mm256_set1_epi32(neg_inf)) {}
- __forceinline vuint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
- __forceinline vuint(UndefinedTy) : v(_mm256_undefined_si256()) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
- static __forceinline vuint8 load(const uint8_t* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
- static __forceinline vuint8 loadu(const uint8_t* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
- static __forceinline vuint8 load(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_load_si128((__m128i*)ptr)); }
- static __forceinline vuint8 loadu(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr)); }
-
- static __forceinline vuint8 load(const void* ptr) { return _mm256_load_si256((__m256i*)ptr); }
- static __forceinline vuint8 loadu(const void* ptr) { return _mm256_loadu_si256((__m256i*)ptr); }
-
- static __forceinline void store (void* ptr, const vuint8& v) { _mm256_store_si256((__m256i*)ptr,v); }
- static __forceinline void storeu(void* ptr, const vuint8& v) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(v)); }
-
-#if defined(__AVX512VL__)
-
- static __forceinline vuint8 compact(const vboolf8& mask, vuint8 &v) {
- return _mm256_mask_compress_epi32(v, mask, v);
- }
- static __forceinline vuint8 compact(const vboolf8& mask, vuint8 &a, const vuint8& b) {
- return _mm256_mask_compress_epi32(a, mask, b);
- }
-
- static __forceinline vuint8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_epi32 (_mm256_setzero_si256(),mask,ptr); }
- static __forceinline vuint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_epi32(_mm256_setzero_si256(),mask,ptr); }
-
- static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_mask_store_epi32 (ptr,mask,v); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_mask_storeu_epi32(ptr,mask,v); }
-#else
- static __forceinline vuint8 load (const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
- static __forceinline vuint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
-
- static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
- static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
-#endif
-
- static __forceinline vuint8 load_nt(void* ptr) {
- return _mm256_stream_load_si256((__m256i*)ptr);
- }
-
- static __forceinline void store_nt(void* ptr, const vuint8& v) {
- _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
- }
-
- static __forceinline void store(uint8_t* ptr, const vuint8& i)
- {
- for (size_t j=0; j<8; j++)
- ptr[j] = i[j];
- }
-
- static __forceinline void store(unsigned short* ptr, const vuint8& v) {
- for (size_t i=0;i<8;i++)
- ptr[i] = (unsigned short)v[i];
- }
-
- template<int scale = 4>
- static __forceinline vuint8 gather(const unsigned int *const ptr, const vint8& index) {
- return _mm256_i32gather_epi32((const int*) ptr, index, scale);
- }
-
- template<int scale = 4>
- static __forceinline vuint8 gather(const vboolf8& mask, const unsigned int *const ptr, const vint8& index) {
- vuint8 r = zero;
-#if defined(__AVX512VL__)
- return _mm256_mmask_i32gather_epi32(r, mask, index, (const int*) ptr, scale);
-#else
- return _mm256_mask_i32gather_epi32(r, (const int*) ptr, index, mask, scale);
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(void* ptr, const vint8& ofs, const vuint8& v)
- {
-#if defined(__AVX512VL__)
- _mm256_i32scatter_epi32((int*)ptr, ofs, v, scale);
-#else
- *(unsigned int*)(((int8_t*)ptr) + scale * ofs[0]) = v[0];
- *(unsigned int*)(((int8_t*)ptr) + scale * ofs[1]) = v[1];
- *(unsigned int*)(((int8_t*)ptr) + scale * ofs[2]) = v[2];
- *(unsigned int*)(((int8_t*)ptr) + scale * ofs[3]) = v[3];
- *(unsigned int*)(((int8_t*)ptr) + scale * ofs[4]) = v[4];
- *(unsigned int*)(((int8_t*)ptr) + scale * ofs[5]) = v[5];
- *(unsigned int*)(((int8_t*)ptr) + scale * ofs[6]) = v[6];
- *(unsigned int*)(((int8_t*)ptr) + scale * ofs[7]) = v[7];
-#endif
- }
-
- template<int scale = 4>
- static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vuint8& v)
- {
-#if defined(__AVX512VL__)
- _mm256_mask_i32scatter_epi32((int*)ptr, mask, ofs, v, scale);
-#else
- if (likely(mask[0])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[0]) = v[0];
- if (likely(mask[1])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[1]) = v[1];
- if (likely(mask[2])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[2]) = v[2];
- if (likely(mask[3])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[3]) = v[3];
- if (likely(mask[4])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[4]) = v[4];
- if (likely(mask[5])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[5]) = v[5];
- if (likely(mask[6])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[6]) = v[6];
- if (likely(mask[7])) *(unsigned int*)(((int8_t*)ptr)+scale*ofs[7]) = v[7];
-#endif
- }
-
- static __forceinline vuint8 broadcast64(const long long &a) { return _mm256_set1_epi64x(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const unsigned int& operator [](size_t index) const { assert(index < 8); return i[index]; }
- __forceinline unsigned int& operator [](size_t index) { assert(index < 8); return i[index]; }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Unary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboolf8 asBool(const vuint8& a) { return _mm256_movepi32_mask(a); }
-#else
- __forceinline vboolf8 asBool(const vuint8& a) { return _mm256_castsi256_ps(a); }
-#endif
-
- __forceinline vuint8 operator +(const vuint8& a) { return a; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Binary Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint8 operator +(const vuint8& a, const vuint8& b) { return _mm256_add_epi32(a, b); }
- __forceinline vuint8 operator +(const vuint8& a, unsigned int b) { return a + vuint8(b); }
- __forceinline vuint8 operator +(unsigned int a, const vuint8& b) { return vuint8(a) + b; }
-
- __forceinline vuint8 operator -(const vuint8& a, const vuint8& b) { return _mm256_sub_epi32(a, b); }
- __forceinline vuint8 operator -(const vuint8& a, unsigned int b) { return a - vuint8(b); }
- __forceinline vuint8 operator -(unsigned int a, const vuint8& b) { return vuint8(a) - b; }
-
- //__forceinline vuint8 operator *(const vuint8& a, const vuint8& b) { return _mm256_mullo_epu32(a, b); }
- //__forceinline vuint8 operator *(const vuint8& a, unsigned int b) { return a * vuint8(b); }
- //__forceinline vuint8 operator *(unsigned int a, const vuint8& b) { return vuint8(a) * b; }
-
- __forceinline vuint8 operator &(const vuint8& a, const vuint8& b) { return _mm256_and_si256(a, b); }
- __forceinline vuint8 operator &(const vuint8& a, unsigned int b) { return a & vuint8(b); }
- __forceinline vuint8 operator &(unsigned int a, const vuint8& b) { return vuint8(a) & b; }
-
- __forceinline vuint8 operator |(const vuint8& a, const vuint8& b) { return _mm256_or_si256(a, b); }
- __forceinline vuint8 operator |(const vuint8& a, unsigned int b) { return a | vuint8(b); }
- __forceinline vuint8 operator |(unsigned int a, const vuint8& b) { return vuint8(a) | b; }
-
- __forceinline vuint8 operator ^(const vuint8& a, const vuint8& b) { return _mm256_xor_si256(a, b); }
- __forceinline vuint8 operator ^(const vuint8& a, unsigned int b) { return a ^ vuint8(b); }
- __forceinline vuint8 operator ^(unsigned int a, const vuint8& b) { return vuint8(a) ^ b; }
-
- __forceinline vuint8 operator <<(const vuint8& a, unsigned int n) { return _mm256_slli_epi32(a, n); }
- __forceinline vuint8 operator >>(const vuint8& a, unsigned int n) { return _mm256_srli_epi32(a, n); }
-
- __forceinline vuint8 operator <<(const vuint8& a, const vuint8& n) { return _mm256_sllv_epi32(a, n); }
- __forceinline vuint8 operator >>(const vuint8& a, const vuint8& n) { return _mm256_srlv_epi32(a, n); }
-
- __forceinline vuint8 sll(const vuint8& a, unsigned int b) { return _mm256_slli_epi32(a, b); }
- __forceinline vuint8 sra(const vuint8& a, unsigned int b) { return _mm256_srai_epi32(a, b); }
- __forceinline vuint8 srl(const vuint8& a, unsigned int b) { return _mm256_srli_epi32(a, b); }
-
- __forceinline vuint8 sll(const vuint8& a, const vuint8& b) { return _mm256_sllv_epi32(a, b); }
- __forceinline vuint8 sra(const vuint8& a, const vuint8& b) { return _mm256_srav_epi32(a, b); }
- __forceinline vuint8 srl(const vuint8& a, const vuint8& b) { return _mm256_srlv_epi32(a, b); }
-
- __forceinline vuint8 min(const vuint8& a, const vuint8& b) { return _mm256_min_epu32(a, b); }
- __forceinline vuint8 min(const vuint8& a, unsigned int b) { return min(a,vuint8(b)); }
- __forceinline vuint8 min(unsigned int a, const vuint8& b) { return min(vuint8(a),b); }
-
- __forceinline vuint8 max(const vuint8& a, const vuint8& b) { return _mm256_max_epu32(a, b); }
- __forceinline vuint8 max(const vuint8& a, unsigned int b) { return max(a,vuint8(b)); }
- __forceinline vuint8 max(unsigned int a, const vuint8& b) { return max(vuint8(a),b); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Assignment Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint8& operator +=(vuint8& a, const vuint8& b) { return a = a + b; }
- __forceinline vuint8& operator +=(vuint8& a, unsigned int b) { return a = a + b; }
-
- __forceinline vuint8& operator -=(vuint8& a, const vuint8& b) { return a = a - b; }
- __forceinline vuint8& operator -=(vuint8& a, unsigned int b) { return a = a - b; }
-
- //__forceinline vuint8& operator *=(vuint8& a, const vuint8& b) { return a = a * b; }
- //__forceinline vuint8& operator *=(vuint8& a, unsigned int b) { return a = a * b; }
-
- __forceinline vuint8& operator &=(vuint8& a, const vuint8& b) { return a = a & b; }
- __forceinline vuint8& operator &=(vuint8& a, unsigned int b) { return a = a & b; }
-
- __forceinline vuint8& operator |=(vuint8& a, const vuint8& b) { return a = a | b; }
- __forceinline vuint8& operator |=(vuint8& a, unsigned int b) { return a = a | b; }
-
- __forceinline vuint8& operator <<=(vuint8& a, const unsigned int b) { return a = a << b; }
- __forceinline vuint8& operator >>=(vuint8& a, const unsigned int b) { return a = a >> b; }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Comparison Operators + Select
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__AVX512VL__)
- __forceinline vboolf8 operator ==(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
- __forceinline vboolf8 operator !=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
- __forceinline vboolf8 operator < (const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
- __forceinline vboolf8 operator >=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
- __forceinline vboolf8 operator > (const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
- __forceinline vboolf8 operator <=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
-
- __forceinline vuint8 select(const vboolf8& m, const vuint8& t, const vuint8& f) {
- return _mm256_mask_blend_epi32(m, (__m256i)f, (__m256i)t);
- }
-#else
- __forceinline vboolf8 operator ==(const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b)); }
- __forceinline vboolf8 operator !=(const vuint8& a, const vuint8& b) { return !(a == b); }
- //__forceinline vboolf8 operator < (const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epu32(b, a)); }
- //__forceinline vboolf8 operator >=(const vuint8& a, const vuint8& b) { return !(a < b); }
- //__forceinline vboolf8 operator > (const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epu32(a, b)); }
- //__forceinline vboolf8 operator <=(const vuint8& a, const vuint8& b) { return !(a > b); }
-
- __forceinline vuint8 select(const vboolf8& m, const vuint8& t, const vuint8& f) {
- return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
- }
-#endif
-
- template<int mask>
- __forceinline vuint8 select(const vuint8& t, const vuint8& f) {
- return _mm256_blend_epi32(f, t, mask);
- }
-
- __forceinline vboolf8 operator ==(const vuint8& a, unsigned int b) { return a == vuint8(b); }
- __forceinline vboolf8 operator ==(unsigned int a, const vuint8& b) { return vuint8(a) == b; }
-
- __forceinline vboolf8 operator !=(const vuint8& a, unsigned int b) { return a != vuint8(b); }
- __forceinline vboolf8 operator !=(unsigned int a, const vuint8& b) { return vuint8(a) != b; }
-
- //__forceinline vboolf8 operator < (const vuint8& a, unsigned int b) { return a < vuint8(b); }
- //__forceinline vboolf8 operator < (unsigned int a, const vuint8& b) { return vuint8(a) < b; }
-
- //__forceinline vboolf8 operator >=(const vuint8& a, unsigned int b) { return a >= vuint8(b); }
- //__forceinline vboolf8 operator >=(unsigned int a, const vuint8& b) { return vuint8(a) >= b; }
-
- //__forceinline vboolf8 operator > (const vuint8& a, unsigned int b) { return a > vuint8(b); }
- //__forceinline vboolf8 operator > (unsigned int a, const vuint8& b) { return vuint8(a) > b; }
-
- //__forceinline vboolf8 operator <=(const vuint8& a, unsigned int b) { return a <= vuint8(b); }
- //__forceinline vboolf8 operator <=(unsigned int a, const vuint8& b) { return vuint8(a) <= b; }
-
- __forceinline vboolf8 eq(const vuint8& a, const vuint8& b) { return a == b; }
- __forceinline vboolf8 ne(const vuint8& a, const vuint8& b) { return a != b; }
- //__forceinline vboolf8 lt(const vuint8& a, const vuint8& b) { return a < b; }
- //__forceinline vboolf8 ge(const vuint8& a, const vuint8& b) { return a >= b; }
- //__forceinline vboolf8 gt(const vuint8& a, const vuint8& b) { return a > b; }
- //__forceinline vboolf8 le(const vuint8& a, const vuint8& b) { return a <= b; }
-
-#if defined(__AVX512VL__)
- __forceinline vboolf8 eq(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_EQ); }
- __forceinline vboolf8 ne(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_NE); }
- __forceinline vboolf8 lt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LT); }
- __forceinline vboolf8 ge(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GE); }
- __forceinline vboolf8 gt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GT); }
- __forceinline vboolf8 le(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LE); }
-#else
- __forceinline vboolf8 eq(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a == b); }
- __forceinline vboolf8 ne(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a != b); }
- //__forceinline vboolf8 lt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a < b); }
- //__forceinline vboolf8 ge(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a >= b); }
- //__forceinline vboolf8 gt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a > b); }
- //__forceinline vboolf8 le(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a <= b); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Movement/Shifting/Shuffling Functions
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline vuint8 unpacklo(const vuint8& a, const vuint8& b) { return _mm256_unpacklo_epi32(a, b); }
- __forceinline vuint8 unpackhi(const vuint8& a, const vuint8& b) { return _mm256_unpackhi_epi32(a, b); }
-
- template<int i>
- __forceinline vuint8 shuffle(const vuint8& v) {
- return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
- }
-
- template<int i0, int i1>
- __forceinline vuint8 shuffle4(const vuint8& v) {
- return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1>
- __forceinline vuint8 shuffle4(const vuint8& a, const vuint8& b) {
- return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint8 shuffle(const vuint8& v) {
- return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<int i0, int i1, int i2, int i3>
- __forceinline vuint8 shuffle(const vuint8& a, const vuint8& b) {
- return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
- }
-
- template<> __forceinline vuint8 shuffle<0, 0, 2, 2>(const vuint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
- template<> __forceinline vuint8 shuffle<1, 1, 3, 3>(const vuint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
- template<> __forceinline vuint8 shuffle<0, 1, 0, 1>(const vuint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
-
- __forceinline vuint8 broadcast(const unsigned int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
-
- template<int i> __forceinline vuint8 insert4(const vuint8& a, const vuint4& b) { return _mm256_insertf128_si256(a, b, i); }
- template<int i> __forceinline vuint4 extract4(const vuint8& a) { return _mm256_extractf128_si256(a, i); }
- template<> __forceinline vuint4 extract4<0>(const vuint8& a) { return _mm256_castsi256_si128(a); }
-
- __forceinline int toScalar(const vuint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
-
-#if !defined(__aarch64__)
-
- __forceinline vuint8 permute(const vuint8& v, const __m256i& index) {
- return _mm256_permutevar8x32_epi32(v, index);
- }
-
- __forceinline vuint8 shuffle(const vuint8& v, const __m256i& index) {
- return _mm256_castps_si256(_mm256_permutevar_ps(_mm256_castsi256_ps(v), index));
- }
-
- template<int i>
- __forceinline vuint8 align_shift_right(const vuint8& a, const vuint8& b) {
-#if defined(__AVX512VL__)
- return _mm256_alignr_epi32(a, b, i);
-#else
- return _mm256_alignr_epi8(a, b, 4*i);
-#endif
- }
-
-#endif
-
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reductions
- ////////////////////////////////////////////////////////////////////////////////
-
- //__forceinline vuint8 vreduce_min2(const vuint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
- //__forceinline vuint8 vreduce_min4(const vuint8& v) { vuint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
- //__forceinline vuint8 vreduce_min (const vuint8& v) { vuint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
-
- //__forceinline vuint8 vreduce_max2(const vuint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
- //__forceinline vuint8 vreduce_max4(const vuint8& v) { vuint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
- //__forceinline vuint8 vreduce_max (const vuint8& v) { vuint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
-
- __forceinline vuint8 vreduce_add2(const vuint8& v) { return v + shuffle<1,0,3,2>(v); }
- __forceinline vuint8 vreduce_add4(const vuint8& v) { vuint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
- __forceinline vuint8 vreduce_add (const vuint8& v) { vuint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
-
- //__forceinline int reduce_min(const vuint8& v) { return toScalar(vreduce_min(v)); }
- //__forceinline int reduce_max(const vuint8& v) { return toScalar(vreduce_max(v)); }
- __forceinline int reduce_add(const vuint8& v) { return toScalar(vreduce_add(v)); }
-
- //__forceinline size_t select_min(const vuint8& v) { return bsf(movemask(v == vreduce_min(v))); }
- //__forceinline size_t select_max(const vuint8& v) { return bsf(movemask(v == vreduce_max(v))); }
-
- //__forceinline size_t select_min(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
- //__forceinline size_t select_max(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
-
- __forceinline vuint8 assign(const vuint4& a) { return _mm256_castsi128_si256(a); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Output Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline embree_ostream operator <<(embree_ostream cout, const vuint8& a) {
- return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
- }
-}
diff --git a/thirdparty/embree-aarch64/common/sys/alloc.cpp b/thirdparty/embree-aarch64/common/sys/alloc.cpp
deleted file mode 100644
index 12f143f131..0000000000
--- a/thirdparty/embree-aarch64/common/sys/alloc.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "alloc.h"
-#include "intrinsics.h"
-#include "sysinfo.h"
-#include "mutex.h"
-
-////////////////////////////////////////////////////////////////////////////////
-/// All Platforms
-////////////////////////////////////////////////////////////////////////////////
-
-namespace embree
-{
- void* alignedMalloc(size_t size, size_t align)
- {
- if (size == 0)
- return nullptr;
-
- assert((align & (align-1)) == 0);
- void* ptr = _mm_malloc(size,align);
-
- if (size != 0 && ptr == nullptr)
- // -- GODOT start --
- // throw std::bad_alloc();
- abort();
- // -- GODOT end --
-
- return ptr;
- }
-
- void alignedFree(void* ptr)
- {
- if (ptr)
- _mm_free(ptr);
- }
-
- static bool huge_pages_enabled = false;
- static MutexSys os_init_mutex;
-
- __forceinline bool isHugePageCandidate(const size_t bytes)
- {
- if (!huge_pages_enabled)
- return false;
-
- /* use huge pages only when memory overhead is low */
- const size_t hbytes = (bytes+PAGE_SIZE_2M-1) & ~size_t(PAGE_SIZE_2M-1);
- return 66*(hbytes-bytes) < bytes; // at most 1.5% overhead
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// Windows Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#ifdef _WIN32
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <malloc.h>
-
-namespace embree
-{
- bool win_enable_selockmemoryprivilege (bool verbose)
- {
- HANDLE hToken;
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
- if (verbose) std::cout << "WARNING: OpenProcessToken failed while trying to enable SeLockMemoryPrivilege: " << GetLastError() << std::endl;
- return false;
- }
-
- TOKEN_PRIVILEGES tp;
- tp.PrivilegeCount = 1;
- tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
- if (!LookupPrivilegeValueW(nullptr, L"SeLockMemoryPrivilege", &tp.Privileges[0].Luid)) {
- if (verbose) std::cout << "WARNING: LookupPrivilegeValue failed while trying to enable SeLockMemoryPrivilege: " << GetLastError() << std::endl;
- return false;
- }
-
- SetLastError(ERROR_SUCCESS);
- if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), nullptr, 0)) {
- if (verbose) std::cout << "WARNING: AdjustTokenPrivileges failed while trying to enable SeLockMemoryPrivilege" << std::endl;
- return false;
- }
-
- if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
- if (verbose) std::cout << "WARNING: AdjustTokenPrivileges failed to enable SeLockMemoryPrivilege: Add SeLockMemoryPrivilege for current user and run process in elevated mode (Run as administrator)." << std::endl;
- return false;
- }
-
- return true;
- }
-
- bool os_init(bool hugepages, bool verbose)
- {
- Lock<MutexSys> lock(os_init_mutex);
-
- if (!hugepages) {
- huge_pages_enabled = false;
- return true;
- }
-
- if (GetLargePageMinimum() != PAGE_SIZE_2M) {
- huge_pages_enabled = false;
- return false;
- }
-
- huge_pages_enabled = true;
- return true;
- }
-
- void* os_malloc(size_t bytes, bool& hugepages)
- {
- if (bytes == 0) {
- hugepages = false;
- return nullptr;
- }
-
- /* try direct huge page allocation first */
- if (isHugePageCandidate(bytes))
- {
- int flags = MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES;
- char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
- if (ptr != nullptr) {
- hugepages = true;
- return ptr;
- }
- }
-
- /* fall back to 4k pages */
- int flags = MEM_COMMIT | MEM_RESERVE;
- char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
- // -- GODOT start --
- // if (ptr == nullptr) throw std::bad_alloc();
- if (ptr == nullptr) abort();
- // -- GODOT end --
- hugepages = false;
- return ptr;
- }
-
- size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages)
- {
- if (hugepages) // decommitting huge pages seems not to work under Windows
- return bytesOld;
-
- const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
- bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
- bytesOld = (bytesOld+pageSize-1) & ~(pageSize-1);
- if (bytesNew >= bytesOld)
- return bytesOld;
-
- if (!VirtualFree((char*)ptr+bytesNew,bytesOld-bytesNew,MEM_DECOMMIT))
- // -- GODOT start --
- // throw std::bad_alloc();
- abort();
- // -- GODOT end --
-
- return bytesNew;
- }
-
- void os_free(void* ptr, size_t bytes, bool hugepages)
- {
- if (bytes == 0)
- return;
-
- if (!VirtualFree(ptr,0,MEM_RELEASE))
- // -- GODOT start --
- // throw std::bad_alloc();
- abort();
- // -- GODOT end --
- }
-
- void os_advise(void *ptr, size_t bytes)
- {
- }
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Unix Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__UNIX__)
-
-#include <sys/mman.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sstream>
-
-#if defined(__MACOSX__)
-#include <mach/vm_statistics.h>
-#endif
-
-namespace embree
-{
- bool os_init(bool hugepages, bool verbose)
- {
- Lock<MutexSys> lock(os_init_mutex);
-
- if (!hugepages) {
- huge_pages_enabled = false;
- return true;
- }
-
-#if defined(__LINUX__)
-
- int hugepagesize = 0;
-
- std::ifstream file;
- file.open("/proc/meminfo",std::ios::in);
- if (!file.is_open()) {
- if (verbose) std::cout << "WARNING: Could not open /proc/meminfo. Huge page support cannot get enabled!" << std::endl;
- huge_pages_enabled = false;
- return false;
- }
-
- std::string line;
- while (getline(file,line))
- {
- std::stringstream sline(line);
- while (!sline.eof() && sline.peek() == ' ') sline.ignore();
- std::string tag; getline(sline,tag,' ');
- while (!sline.eof() && sline.peek() == ' ') sline.ignore();
- std::string val; getline(sline,val,' ');
- while (!sline.eof() && sline.peek() == ' ') sline.ignore();
- std::string unit; getline(sline,unit,' ');
- if (tag == "Hugepagesize:" && unit == "kB") {
- hugepagesize = std::stoi(val)*1024;
- break;
- }
- }
-
- if (hugepagesize != PAGE_SIZE_2M)
- {
- if (verbose) std::cout << "WARNING: Only 2MB huge pages supported. Huge page support cannot get enabled!" << std::endl;
- huge_pages_enabled = false;
- return false;
- }
-#endif
-
- huge_pages_enabled = true;
- return true;
- }
-
- void* os_malloc(size_t bytes, bool& hugepages)
- {
- if (bytes == 0) {
- hugepages = false;
- return nullptr;
- }
-
- /* try direct huge page allocation first */
- if (isHugePageCandidate(bytes))
- {
-#if defined(__MACOSX__)
- void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
- if (ptr != MAP_FAILED) {
- hugepages = true;
- return ptr;
- }
-#elif defined(MAP_HUGETLB)
- void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_HUGETLB, -1, 0);
- if (ptr != MAP_FAILED) {
- hugepages = true;
- return ptr;
- }
-#endif
- }
-
- /* fallback to 4k pages */
- void* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
- // -- GODOT start --
- // if (ptr == MAP_FAILED) throw std::bad_alloc();
- if (ptr == MAP_FAILED) abort();
- // -- GODOT end --
- hugepages = false;
-
- /* advise huge page hint for THP */
- os_advise(ptr,bytes);
- return ptr;
- }
-
- size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages)
- {
- const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
- bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
- bytesOld = (bytesOld+pageSize-1) & ~(pageSize-1);
- if (bytesNew >= bytesOld)
- return bytesOld;
-
- if (munmap((char*)ptr+bytesNew,bytesOld-bytesNew) == -1)
- // -- GODOT start --
- // throw std::bad_alloc();
- abort();
- // -- GODOT end --
-
- return bytesNew;
- }
-
- void os_free(void* ptr, size_t bytes, bool hugepages)
- {
- if (bytes == 0)
- return;
-
- /* for hugepages we need to also align the size */
- const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
- bytes = (bytes+pageSize-1) & ~(pageSize-1);
- if (munmap(ptr,bytes) == -1)
- // -- GODOT start --
- // throw std::bad_alloc();
- abort();
- // -- GODOT end --
- }
-
- /* hint for transparent huge pages (THP) */
- void os_advise(void* pptr, size_t bytes)
- {
-#if defined(MADV_HUGEPAGE)
- madvise(pptr,bytes,MADV_HUGEPAGE);
-#endif
- }
-}
-
-#endif
diff --git a/thirdparty/embree-aarch64/common/sys/alloc.h b/thirdparty/embree-aarch64/common/sys/alloc.h
deleted file mode 100644
index 5898ecda70..0000000000
--- a/thirdparty/embree-aarch64/common/sys/alloc.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-#include <vector>
-#include <set>
-
-namespace embree
-{
-#define ALIGNED_STRUCT_(align) \
- void* operator new(size_t size) { return alignedMalloc(size,align); } \
- void operator delete(void* ptr) { alignedFree(ptr); } \
- void* operator new[](size_t size) { return alignedMalloc(size,align); } \
- void operator delete[](void* ptr) { alignedFree(ptr); }
-
-#define ALIGNED_CLASS_(align) \
- public: \
- ALIGNED_STRUCT_(align) \
- private:
-
- /*! aligned allocation */
- void* alignedMalloc(size_t size, size_t align);
- void alignedFree(void* ptr);
-
- /*! allocator that performs aligned allocations */
- template<typename T, size_t alignment>
- struct aligned_allocator
- {
- typedef T value_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- __forceinline pointer allocate( size_type n ) {
- return (pointer) alignedMalloc(n*sizeof(value_type),alignment);
- }
-
- __forceinline void deallocate( pointer p, size_type n ) {
- return alignedFree(p);
- }
-
- __forceinline void construct( pointer p, const_reference val ) {
- new (p) T(val);
- }
-
- __forceinline void destroy( pointer p ) {
- p->~T();
- }
- };
-
- /*! allocates pages directly from OS */
- bool win_enable_selockmemoryprivilege(bool verbose);
- bool os_init(bool hugepages, bool verbose);
- void* os_malloc (size_t bytes, bool& hugepages);
- size_t os_shrink (void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages);
- void os_free (void* ptr, size_t bytes, bool hugepages);
- void os_advise (void* ptr, size_t bytes);
-
- /*! allocator that performs OS allocations */
- template<typename T>
- struct os_allocator
- {
- typedef T value_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- __forceinline os_allocator ()
- : hugepages(false) {}
-
- __forceinline pointer allocate( size_type n ) {
- return (pointer) os_malloc(n*sizeof(value_type),hugepages);
- }
-
- __forceinline void deallocate( pointer p, size_type n ) {
- return os_free(p,n*sizeof(value_type),hugepages);
- }
-
- __forceinline void construct( pointer p, const_reference val ) {
- new (p) T(val);
- }
-
- __forceinline void destroy( pointer p ) {
- p->~T();
- }
-
- bool hugepages;
- };
-
- /*! allocator for IDs */
- template<typename T, size_t max_id>
- struct IDPool
- {
- typedef T value_type;
-
- IDPool ()
- : nextID(0) {}
-
- T allocate()
- {
- /* return ID from list */
- if (!IDs.empty())
- {
- T id = *IDs.begin();
- IDs.erase(IDs.begin());
- return id;
- }
-
- /* allocate new ID */
- else
- {
- if (size_t(nextID)+1 > max_id)
- return -1;
-
- return nextID++;
- }
- }
-
- /* adds an ID provided by the user */
- bool add(T id)
- {
- if (id > max_id)
- return false;
-
- /* check if ID should be in IDs set */
- if (id < nextID) {
- auto p = IDs.find(id);
- if (p == IDs.end()) return false;
- IDs.erase(p);
- return true;
- }
-
- /* otherwise increase ID set */
- else
- {
- for (T i=nextID; i<id; i++) {
- IDs.insert(i);
- }
- nextID = id+1;
- return true;
- }
- }
-
- void deallocate( T id )
- {
- assert(id < nextID);
- MAYBE_UNUSED auto done = IDs.insert(id).second;
- assert(done);
- }
-
- private:
- std::set<T> IDs; //!< stores deallocated IDs to be reused
- T nextID; //!< next ID to use when IDs vector is empty
- };
-}
-
diff --git a/thirdparty/embree-aarch64/common/sys/array.h b/thirdparty/embree-aarch64/common/sys/array.h
deleted file mode 100644
index 77722a39f6..0000000000
--- a/thirdparty/embree-aarch64/common/sys/array.h
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-#include "alloc.h"
-
-namespace embree
-{
- /*! static array with static size */
- template<typename T, size_t N>
- class array_t
- {
- public:
-
- /********************** Iterators ****************************/
-
- __forceinline T* begin() const { return items; };
- __forceinline T* end () const { return items+N; };
-
-
- /********************** Capacity ****************************/
-
- __forceinline bool empty () const { return N == 0; }
- __forceinline size_t size () const { return N; }
- __forceinline size_t max_size () const { return N; }
-
-
- /******************** Element access **************************/
-
- __forceinline T& operator[](size_t i) { assert(i < N); return items[i]; }
- __forceinline const T& operator[](size_t i) const { assert(i < N); return items[i]; }
-
- __forceinline T& at(size_t i) { assert(i < N); return items[i]; }
- __forceinline const T& at(size_t i) const { assert(i < N); return items[i]; }
-
- __forceinline T& front() const { assert(N > 0); return items[0]; };
- __forceinline T& back () const { assert(N > 0); return items[N-1]; };
-
- __forceinline T* data() { return items; };
- __forceinline const T* data() const { return items; };
-
- private:
- T items[N];
- };
-
- /*! static array with dynamic size */
- template<typename T, size_t N>
- class darray_t
- {
- public:
-
- __forceinline darray_t () : M(0) {}
-
- __forceinline darray_t (const T& v) : M(0) {
- for (size_t i=0; i<N; i++) items[i] = v;
- }
-
- /********************** Iterators ****************************/
-
- __forceinline T* begin() const { return items; };
- __forceinline T* end () const { return items+M; };
-
-
- /********************** Capacity ****************************/
-
- __forceinline bool empty () const { return M == 0; }
- __forceinline size_t size () const { return M; }
- __forceinline size_t capacity () const { return N; }
- __forceinline size_t max_size () const { return N; }
-
- void resize(size_t new_size) {
- assert(new_size < max_size());
- M = new_size;
- }
-
- /******************** Modifiers **************************/
-
- __forceinline void push_back(const T& v)
- {
- assert(M+1 < max_size());
- items[M++] = v;
- }
-
- __forceinline void pop_back()
- {
- assert(!empty());
- M--;
- }
-
- __forceinline void clear() {
- M = 0;
- }
-
- /******************** Element access **************************/
-
- __forceinline T& operator[](size_t i) { assert(i < M); return items[i]; }
- __forceinline const T& operator[](size_t i) const { assert(i < M); return items[i]; }
-
- __forceinline T& at(size_t i) { assert(i < M); return items[i]; }
- __forceinline const T& at(size_t i) const { assert(i < M); return items[i]; }
-
- __forceinline T& front() const { assert(M > 0); return items[0]; };
- __forceinline T& back () const { assert(M > 0); return items[M-1]; };
-
- __forceinline T* data() { return items; };
- __forceinline const T* data() const { return items; };
-
- private:
- size_t M;
- T items[N];
- };
-
- /*! dynamic sized array that is allocated on the stack */
-#define dynamic_large_stack_array(Ty,Name,N,max_stack_bytes) StackArray<Ty,max_stack_bytes> Name(N)
- template<typename Ty, size_t max_stack_bytes>
- struct __aligned(64) StackArray
- {
- __forceinline StackArray (const size_t N)
- : N(N)
- {
- if (N*sizeof(Ty) <= max_stack_bytes)
- data = &arr[0];
- else
- data = (Ty*) alignedMalloc(N*sizeof(Ty),64);
- }
-
- __forceinline ~StackArray () {
- if (data != &arr[0]) alignedFree(data);
- }
-
- __forceinline operator Ty* () { return data; }
- __forceinline operator const Ty* () const { return data; }
-
- __forceinline Ty& operator[](const int i) { assert(i>=0 && i<N); return data[i]; }
- __forceinline const Ty& operator[](const int i) const { assert(i>=0 && i<N); return data[i]; }
-
- __forceinline Ty& operator[](const unsigned i) { assert(i<N); return data[i]; }
- __forceinline const Ty& operator[](const unsigned i) const { assert(i<N); return data[i]; }
-
-#if defined(__X86_64__) || defined(__aarch64__)
- __forceinline Ty& operator[](const size_t i) { assert(i<N); return data[i]; }
- __forceinline const Ty& operator[](const size_t i) const { assert(i<N); return data[i]; }
-#endif
-
- private:
- Ty arr[max_stack_bytes/sizeof(Ty)];
- Ty* data;
- size_t N;
-
- private:
- StackArray (const StackArray& other) DELETED; // do not implement
- StackArray& operator= (const StackArray& other) DELETED; // do not implement
-
- };
-
- /*! dynamic sized array that is allocated on the stack */
- template<typename Ty, size_t max_stack_elements, size_t max_total_elements>
- struct __aligned(64) DynamicStackArray
- {
- __forceinline DynamicStackArray ()
- : data(&arr[0]) {}
-
- __forceinline ~DynamicStackArray ()
- {
- if (!isStackAllocated())
- delete[] data;
- }
-
- __forceinline bool isStackAllocated() const {
- return data == &arr[0];
- }
-
- __forceinline size_t size() const
- {
- if (isStackAllocated()) return max_stack_elements;
- else return max_total_elements;
- }
-
- __forceinline void resize(size_t M)
- {
- assert(M <= max_total_elements);
- if (likely(M <= max_stack_elements)) return;
- if (likely(!isStackAllocated())) return;
-
- data = new Ty[max_total_elements];
-
- for (size_t i=0; i<max_stack_elements; i++)
- data[i] = arr[i];
- }
-
- __forceinline operator Ty* () { return data; }
- __forceinline operator const Ty* () const { return data; }
-
- __forceinline Ty& operator[](const int i) { assert(i>=0 && i<max_total_elements); resize(i+1); return data[i]; }
- __forceinline Ty& operator[](const unsigned i) { assert(i<max_total_elements); resize(i+1); return data[i]; }
-
-#if defined(__X86_64__) || defined(__aarch64__)
- __forceinline Ty& operator[](const size_t i) { assert(i<max_total_elements); resize(i+1); return data[i]; }
-#endif
-
- __forceinline DynamicStackArray (const DynamicStackArray& other)
- : data(&arr[0])
- {
- for (size_t i=0; i<other.size(); i++)
- this->operator[] (i) = other[i];
- }
-
- DynamicStackArray& operator= (const DynamicStackArray& other)
- {
- for (size_t i=0; i<other.size(); i++)
- this->operator[] (i) = other[i];
-
- return *this;
- }
-
- private:
- Ty arr[max_stack_elements];
- Ty* data;
- };
-}
diff --git a/thirdparty/embree-aarch64/common/sys/atomic.h b/thirdparty/embree-aarch64/common/sys/atomic.h
deleted file mode 100644
index ebfb8552c3..0000000000
--- a/thirdparty/embree-aarch64/common/sys/atomic.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include <atomic>
-#include "intrinsics.h"
-
-namespace embree
-{
-/* compiler memory barriers */
-#if defined(__INTEL_COMPILER)
-//#define __memory_barrier() __memory_barrier()
-#elif defined(__GNUC__) || defined(__clang__)
-# define __memory_barrier() asm volatile("" ::: "memory")
-#elif defined(_MSC_VER)
-# define __memory_barrier() _ReadWriteBarrier()
-#endif
-
- template <typename T>
- struct atomic : public std::atomic<T>
- {
- atomic () {}
-
- atomic (const T& a)
- : std::atomic<T>(a) {}
-
- atomic (const atomic<T>& a) {
- this->store(a.load());
- }
-
- atomic& operator=(const atomic<T>& other) {
- this->store(other.load());
- return *this;
- }
- };
-
- template<typename T>
- __forceinline void atomic_min(std::atomic<T>& aref, const T& bref)
- {
- const T b = bref.load();
- while (true) {
- T a = aref.load();
- if (a <= b) break;
- if (aref.compare_exchange_strong(a,b)) break;
- }
- }
-
- template<typename T>
- __forceinline void atomic_max(std::atomic<T>& aref, const T& bref)
- {
- const T b = bref.load();
- while (true) {
- T a = aref.load();
- if (a >= b) break;
- if (aref.compare_exchange_strong(a,b)) break;
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/common/sys/barrier.cpp b/thirdparty/embree-aarch64/common/sys/barrier.cpp
deleted file mode 100644
index 0061d18db2..0000000000
--- a/thirdparty/embree-aarch64/common/sys/barrier.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "barrier.h"
-#include "condition.h"
-#include "regression.h"
-#include "thread.h"
-
-#if defined (__WIN32__)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-namespace embree
-{
- struct BarrierSysImplementation
- {
- __forceinline BarrierSysImplementation (size_t N)
- : i(0), enterCount(0), exitCount(0), barrierSize(0)
- {
- events[0] = CreateEvent(nullptr, TRUE, FALSE, nullptr);
- events[1] = CreateEvent(nullptr, TRUE, FALSE, nullptr);
- init(N);
- }
-
- __forceinline ~BarrierSysImplementation ()
- {
- CloseHandle(events[0]);
- CloseHandle(events[1]);
- }
-
- __forceinline void init(size_t N)
- {
- barrierSize = N;
- enterCount.store(N);
- exitCount.store(N);
- }
-
- __forceinline void wait()
- {
- /* every thread entering the barrier decrements this count */
- size_t i0 = i;
- size_t cnt0 = enterCount--;
-
- /* all threads except the last one are wait in the barrier */
- if (cnt0 > 1)
- {
- if (WaitForSingleObject(events[i0], INFINITE) != WAIT_OBJECT_0)
- THROW_RUNTIME_ERROR("WaitForSingleObjects failed");
- }
-
- /* the last thread starts all threads waiting at the barrier */
- else
- {
- i = 1-i;
- enterCount.store(barrierSize);
- if (SetEvent(events[i0]) == 0)
- THROW_RUNTIME_ERROR("SetEvent failed");
- }
-
- /* every thread leaving the barrier decrements this count */
- size_t cnt1 = exitCount--;
-
- /* the last thread that left the barrier resets the event again */
- if (cnt1 == 1)
- {
- exitCount.store(barrierSize);
- if (ResetEvent(events[i0]) == 0)
- THROW_RUNTIME_ERROR("ResetEvent failed");
- }
- }
-
- public:
- HANDLE events[2];
- atomic<size_t> i;
- atomic<size_t> enterCount;
- atomic<size_t> exitCount;
- size_t barrierSize;
- };
-}
-
-#else
-
-namespace embree
-{
- struct BarrierSysImplementation
- {
- __forceinline BarrierSysImplementation (size_t N)
- : count(0), barrierSize(0)
- {
- init(N);
- }
-
- __forceinline void init(size_t N)
- {
- assert(count == 0);
- count = 0;
- barrierSize = N;
- }
-
- __forceinline void wait()
- {
- mutex.lock();
- count++;
-
- if (count == barrierSize) {
- count = 0;
- cond.notify_all();
- mutex.unlock();
- return;
- }
-
- cond.wait(mutex);
- mutex.unlock();
- return;
- }
-
- public:
- MutexSys mutex;
- ConditionSys cond;
- volatile size_t count;
- volatile size_t barrierSize;
- };
-}
-
-#endif
-
-namespace embree
-{
- BarrierSys::BarrierSys (size_t N) {
- opaque = new BarrierSysImplementation(N);
- }
-
- BarrierSys::~BarrierSys () {
- delete (BarrierSysImplementation*) opaque;
- }
-
- void BarrierSys::init(size_t count) {
- ((BarrierSysImplementation*) opaque)->init(count);
- }
-
- void BarrierSys::wait() {
- ((BarrierSysImplementation*) opaque)->wait();
- }
-
- LinearBarrierActive::LinearBarrierActive (size_t N)
- : count0(nullptr), count1(nullptr), mode(0), flag0(0), flag1(0), threadCount(0)
- {
- if (N == 0) N = getNumberOfLogicalThreads();
- init(N);
- }
-
- LinearBarrierActive::~LinearBarrierActive()
- {
- delete[] count0;
- delete[] count1;
- }
-
- void LinearBarrierActive::init(size_t N)
- {
- if (threadCount != N) {
- threadCount = N;
- if (count0) delete[] count0; count0 = new unsigned char[N];
- if (count1) delete[] count1; count1 = new unsigned char[N];
- }
- mode = 0;
- flag0 = 0;
- flag1 = 0;
- for (size_t i=0; i<N; i++) count0[i] = 0;
- for (size_t i=0; i<N; i++) count1[i] = 0;
- }
-
- void LinearBarrierActive::wait (const size_t threadIndex)
- {
- if (mode == 0)
- {
- if (threadIndex == 0)
- {
- for (size_t i=0; i<threadCount; i++)
- count1[i] = 0;
-
- for (size_t i=1; i<threadCount; i++)
- {
- while (likely(count0[i] == 0))
- pause_cpu();
- }
- mode = 1;
- flag1 = 0;
- __memory_barrier();
- flag0 = 1;
- }
- else
- {
- count0[threadIndex] = 1;
- {
- while (likely(flag0 == 0))
- pause_cpu();
- }
-
- }
- }
- else
- {
- if (threadIndex == 0)
- {
- for (size_t i=0; i<threadCount; i++)
- count0[i] = 0;
-
- for (size_t i=1; i<threadCount; i++)
- {
- while (likely(count1[i] == 0))
- pause_cpu();
- }
-
- mode = 0;
- flag0 = 0;
- __memory_barrier();
- flag1 = 1;
- }
- else
- {
- count1[threadIndex] = 1;
- {
- while (likely(flag1 == 0))
- pause_cpu();
- }
- }
- }
- }
-
- struct barrier_sys_regression_test : public RegressionTest
- {
- BarrierSys barrier;
- std::atomic<size_t> threadID;
- std::atomic<size_t> numFailed;
- std::vector<size_t> threadResults;
-
- barrier_sys_regression_test()
- : RegressionTest("barrier_sys_regression_test"), threadID(0), numFailed(0)
- {
- registerRegressionTest(this);
- }
-
- static void thread_alloc(barrier_sys_regression_test* This)
- {
- size_t tid = This->threadID++;
- for (size_t j=0; j<1000; j++)
- {
- This->barrier.wait();
- This->threadResults[tid] = tid;
- This->barrier.wait();
- }
- }
-
- bool run ()
- {
- threadID.store(0);
- numFailed.store(0);
-
- size_t numThreads = getNumberOfLogicalThreads();
- threadResults.resize(numThreads);
- barrier.init(numThreads+1);
-
- /* create threads */
- std::vector<thread_t> threads;
- for (size_t i=0; i<numThreads; i++)
- threads.push_back(createThread((thread_func)thread_alloc,this));
-
- /* run test */
- for (size_t i=0; i<1000; i++)
- {
- for (size_t i=0; i<numThreads; i++) threadResults[i] = 0;
- barrier.wait();
- barrier.wait();
- for (size_t i=0; i<numThreads; i++) numFailed += threadResults[i] != i;
- }
-
- /* destroy threads */
- for (size_t i=0; i<numThreads; i++)
- join(threads[i]);
-
- return numFailed == 0;
- }
- };
-
- barrier_sys_regression_test barrier_sys_regression_test;
-}
-
-
diff --git a/thirdparty/embree-aarch64/common/sys/barrier.h b/thirdparty/embree-aarch64/common/sys/barrier.h
deleted file mode 100644
index 89607b8685..0000000000
--- a/thirdparty/embree-aarch64/common/sys/barrier.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "intrinsics.h"
-#include "sysinfo.h"
-#include "atomic.h"
-
-namespace embree
-{
- /*! system barrier using operating system */
- class BarrierSys
- {
- public:
-
- /*! construction / destruction */
- BarrierSys (size_t N = 0);
- ~BarrierSys ();
-
- private:
- /*! class in non-copyable */
- BarrierSys (const BarrierSys& other) DELETED; // do not implement
- BarrierSys& operator= (const BarrierSys& other) DELETED; // do not implement
-
- public:
- /*! intializes the barrier with some number of threads */
- void init(size_t count);
-
- /*! lets calling thread wait in barrier */
- void wait();
-
- private:
- void* opaque;
- };
-
- /*! fast active barrier using atomitc counter */
- struct BarrierActive
- {
- public:
- BarrierActive ()
- : cntr(0) {}
-
- void reset() {
- cntr.store(0);
- }
-
- void wait (size_t numThreads)
- {
- cntr++;
- while (cntr.load() != numThreads)
- pause_cpu();
- }
-
- private:
- std::atomic<size_t> cntr;
- };
-
- /*! fast active barrier that does not require initialization to some number of threads */
- struct BarrierActiveAutoReset
- {
- public:
- BarrierActiveAutoReset ()
- : cntr0(0), cntr1(0) {}
-
- void wait (size_t threadCount)
- {
- cntr0.fetch_add(1);
- while (cntr0 != threadCount) pause_cpu();
- cntr1.fetch_add(1);
- while (cntr1 != threadCount) pause_cpu();
- cntr0.fetch_add(-1);
- while (cntr0 != 0) pause_cpu();
- cntr1.fetch_add(-1);
- while (cntr1 != 0) pause_cpu();
- }
-
- private:
- std::atomic<size_t> cntr0;
- std::atomic<size_t> cntr1;
- };
-
- class LinearBarrierActive
- {
- public:
-
- /*! construction and destruction */
- LinearBarrierActive (size_t threadCount = 0);
- ~LinearBarrierActive();
-
- private:
- /*! class in non-copyable */
- LinearBarrierActive (const LinearBarrierActive& other) DELETED; // do not implement
- LinearBarrierActive& operator= (const LinearBarrierActive& other) DELETED; // do not implement
-
- public:
- /*! intializes the barrier with some number of threads */
- void init(size_t threadCount);
-
- /*! thread with threadIndex waits in the barrier */
- void wait (const size_t threadIndex);
-
- private:
- volatile unsigned char* count0;
- volatile unsigned char* count1;
- volatile unsigned int mode;
- volatile unsigned int flag0;
- volatile unsigned int flag1;
- volatile size_t threadCount;
- };
-}
-
diff --git a/thirdparty/embree-aarch64/common/sys/condition.cpp b/thirdparty/embree-aarch64/common/sys/condition.cpp
deleted file mode 100644
index 0e7ca7af39..0000000000
--- a/thirdparty/embree-aarch64/common/sys/condition.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "condition.h"
-
-#if defined(__WIN32__) && !defined(PTHREADS_WIN32)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-namespace embree
-{
- struct ConditionImplementation
- {
- __forceinline ConditionImplementation () {
- InitializeConditionVariable(&cond);
- }
-
- __forceinline ~ConditionImplementation () {
- }
-
- __forceinline void wait(MutexSys& mutex_in) {
- SleepConditionVariableCS(&cond, (LPCRITICAL_SECTION)mutex_in.mutex, INFINITE);
- }
-
- __forceinline void notify_all() {
- WakeAllConditionVariable(&cond);
- }
-
- public:
- CONDITION_VARIABLE cond;
- };
-}
-#endif
-
-#if defined(__UNIX__) || defined(PTHREADS_WIN32)
-#include <pthread.h>
-namespace embree
-{
- struct ConditionImplementation
- {
- __forceinline ConditionImplementation () {
- pthread_cond_init(&cond,nullptr);
- }
-
- __forceinline ~ConditionImplementation() {
- pthread_cond_destroy(&cond);
- }
-
- __forceinline void wait(MutexSys& mutex) {
- pthread_cond_wait(&cond, (pthread_mutex_t*)mutex.mutex);
- }
-
- __forceinline void notify_all() {
- pthread_cond_broadcast(&cond);
- }
-
- public:
- pthread_cond_t cond;
- };
-}
-#endif
-
-namespace embree
-{
- ConditionSys::ConditionSys () {
- cond = new ConditionImplementation;
- }
-
- ConditionSys::~ConditionSys() {
- delete (ConditionImplementation*) cond;
- }
-
- void ConditionSys::wait(MutexSys& mutex) {
- ((ConditionImplementation*) cond)->wait(mutex);
- }
-
- void ConditionSys::notify_all() {
- ((ConditionImplementation*) cond)->notify_all();
- }
-}
diff --git a/thirdparty/embree-aarch64/common/sys/condition.h b/thirdparty/embree-aarch64/common/sys/condition.h
deleted file mode 100644
index 7a3a05aa81..0000000000
--- a/thirdparty/embree-aarch64/common/sys/condition.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "mutex.h"
-
-namespace embree
-{
- class ConditionSys
- {
- public:
- ConditionSys();
- ~ConditionSys();
- void wait( class MutexSys& mutex );
- void notify_all();
-
- template<typename Predicate>
- __forceinline void wait( class MutexSys& mutex, const Predicate& pred )
- {
- while (!pred()) wait(mutex);
- }
-
- private:
- ConditionSys (const ConditionSys& other) DELETED; // do not implement
- ConditionSys& operator= (const ConditionSys& other) DELETED; // do not implement
-
- protected:
- void* cond;
- };
-}
diff --git a/thirdparty/embree-aarch64/common/sys/filename.cpp b/thirdparty/embree-aarch64/common/sys/filename.cpp
deleted file mode 100644
index 86182c1afb..0000000000
--- a/thirdparty/embree-aarch64/common/sys/filename.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "filename.h"
-#include "sysinfo.h"
-
-namespace embree
-{
-#ifdef __WIN32__
- const char path_sep = '\\';
-#else
- const char path_sep = '/';
-#endif
-
- /*! create an empty filename */
- FileName::FileName () {}
-
- /*! create a valid filename from a string */
- FileName::FileName (const char* in) {
- filename = in;
- for (size_t i=0; i<filename.size(); i++)
- if (filename[i] == '\\' || filename[i] == '/')
- filename[i] = path_sep;
- while (!filename.empty() && filename[filename.size()-1] == path_sep)
- filename.resize(filename.size()-1);
- }
-
- /*! create a valid filename from a string */
- FileName::FileName (const std::string& in) {
- filename = in;
- for (size_t i=0; i<filename.size(); i++)
- if (filename[i] == '\\' || filename[i] == '/')
- filename[i] = path_sep;
- while (!filename.empty() && filename[filename.size()-1] == path_sep)
- filename.resize(filename.size()-1);
- }
-
- /*! returns path to home folder */
- FileName FileName::homeFolder()
- {
-#ifdef __WIN32__
- const char* home = getenv("UserProfile");
-#else
- const char* home = getenv("HOME");
-#endif
- if (home) return home;
- return "";
- }
-
- /*! returns path to executable */
- FileName FileName::executableFolder() {
- return FileName(getExecutableFileName()).path();
- }
-
- /*! returns the path */
- FileName FileName::path() const {
- size_t pos = filename.find_last_of(path_sep);
- if (pos == std::string::npos) return FileName();
- return filename.substr(0,pos);
- }
-
- /*! returns the basename */
- std::string FileName::base() const {
- size_t pos = filename.find_last_of(path_sep);
- if (pos == std::string::npos) return filename;
- return filename.substr(pos+1);
- }
-
- /*! returns the extension */
- std::string FileName::ext() const {
- size_t pos = filename.find_last_of('.');
- if (pos == std::string::npos) return "";
- return filename.substr(pos+1);
- }
-
- /*! returns the extension */
- FileName FileName::dropExt() const {
- size_t pos = filename.find_last_of('.');
- if (pos == std::string::npos) return filename;
- return filename.substr(0,pos);
- }
-
- /*! returns the basename without extension */
- std::string FileName::name() const {
- size_t start = filename.find_last_of(path_sep);
- if (start == std::string::npos) start = 0; else start++;
- size_t end = filename.find_last_of('.');
- if (end == std::string::npos || end < start) end = filename.size();
- return filename.substr(start, end - start);
- }
-
- /*! replaces the extension */
- FileName FileName::setExt(const std::string& ext) const {
- size_t start = filename.find_last_of(path_sep);
- if (start == std::string::npos) start = 0; else start++;
- size_t end = filename.find_last_of('.');
- if (end == std::string::npos || end < start) return FileName(filename+ext);
- return FileName(filename.substr(0,end)+ext);
- }
-
- /*! adds the extension */
- FileName FileName::addExt(const std::string& ext) const {
- return FileName(filename+ext);
- }
-
- /*! concatenates two filenames to this/other */
- FileName FileName::operator +( const FileName& other ) const {
- if (filename == "") return FileName(other);
- else return FileName(filename + path_sep + other.filename);
- }
-
- /*! concatenates two filenames to this/other */
- FileName FileName::operator +( const std::string& other ) const {
- return operator+(FileName(other));
- }
-
- /*! removes the base from a filename (if possible) */
- FileName FileName::operator -( const FileName& base ) const {
- size_t pos = filename.find_first_of(base);
- if (pos == std::string::npos) return *this;
- return FileName(filename.substr(pos+1));
- }
-
- /*! == operator */
- bool operator== (const FileName& a, const FileName& b) {
- return a.filename == b.filename;
- }
-
- /*! != operator */
- bool operator!= (const FileName& a, const FileName& b) {
- return a.filename != b.filename;
- }
-
- /*! output operator */
- std::ostream& operator<<(std::ostream& cout, const FileName& filename) {
- return cout << filename.filename;
- }
-}
diff --git a/thirdparty/embree-aarch64/common/sys/filename.h b/thirdparty/embree-aarch64/common/sys/filename.h
deleted file mode 100644
index 58f881b14d..0000000000
--- a/thirdparty/embree-aarch64/common/sys/filename.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-
-namespace embree
-{
- /*! Convenience class for handling file names and paths. */
- class FileName
- {
- public:
-
- /*! create an empty filename */
- FileName ();
-
- /*! create a valid filename from a string */
- FileName (const char* filename);
-
- /*! create a valid filename from a string */
- FileName (const std::string& filename);
-
- /*! returns path to home folder */
- static FileName homeFolder();
-
- /*! returns path to executable */
- static FileName executableFolder();
-
- /*! auto convert into a string */
- operator std::string() const { return filename; }
-
- /*! returns a string of the filename */
- const std::string str() const { return filename; }
-
- /*! returns a c-string of the filename */
- const char* c_str() const { return filename.c_str(); }
-
- /*! returns the path of a filename */
- FileName path() const;
-
- /*! returns the file of a filename */
- std::string base() const;
-
- /*! returns the base of a filename without extension */
- std::string name() const;
-
- /*! returns the file extension */
- std::string ext() const;
-
- /*! drops the file extension */
- FileName dropExt() const;
-
- /*! replaces the file extension */
- FileName setExt(const std::string& ext = "") const;
-
- /*! adds file extension */
- FileName addExt(const std::string& ext = "") const;
-
- /*! concatenates two filenames to this/other */
- FileName operator +( const FileName& other ) const;
-
- /*! concatenates two filenames to this/other */
- FileName operator +( const std::string& other ) const;
-
- /*! removes the base from a filename (if possible) */
- FileName operator -( const FileName& base ) const;
-
- /*! == operator */
- friend bool operator==(const FileName& a, const FileName& b);
-
- /*! != operator */
- friend bool operator!=(const FileName& a, const FileName& b);
-
- /*! output operator */
- friend embree_ostream operator<<(embree_ostream cout, const FileName& filename);
-
- private:
- std::string filename;
- };
-}
diff --git a/thirdparty/embree-aarch64/common/sys/intrinsics.h b/thirdparty/embree-aarch64/common/sys/intrinsics.h
deleted file mode 100644
index 44cdbd8f0f..0000000000
--- a/thirdparty/embree-aarch64/common/sys/intrinsics.h
+++ /dev/null
@@ -1,559 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-
-#if defined(__WIN32__)
-#include <intrin.h>
-#endif
-
-#if defined(__ARM_NEON)
-#include "../math/SSE2NEON.h"
-#if defined(NEON_AVX2_EMULATION)
-#include "../math/AVX2NEON.h"
-#endif
-#else
-#include <immintrin.h>
-#endif
-
-#if defined(__BMI__) && defined(__GNUC__) && !defined(__INTEL_COMPILER)
- #if !defined(_tzcnt_u32)
- #define _tzcnt_u32 __tzcnt_u32
- #endif
- #if !defined(_tzcnt_u64)
- #define _tzcnt_u64 __tzcnt_u64
- #endif
-#endif
-
-#if defined(__aarch64__)
-#if !defined(_lzcnt_u32)
- #define _lzcnt_u32 __builtin_clz
-#endif
-#if !defined(_lzcnt_u32)
- #define _lzcnt_u32 __builtin_clzll
-#endif
-#else
-#if defined(__LZCNT__)
- #if !defined(_lzcnt_u32)
- #define _lzcnt_u32 __lzcnt32
- #endif
- #if !defined(_lzcnt_u64)
- #define _lzcnt_u64 __lzcnt64
- #endif
-#endif
-#endif
-
-#if defined(__WIN32__)
-# ifndef NOMINMAX
-# define NOMINMAX
-# endif
-# include <windows.h>
-#endif
-
-/* normally defined in pmmintrin.h, but we always need this */
-#if !defined(_MM_SET_DENORMALS_ZERO_MODE)
-#define _MM_DENORMALS_ZERO_ON (0x0040)
-#define _MM_DENORMALS_ZERO_OFF (0x0000)
-#define _MM_DENORMALS_ZERO_MASK (0x0040)
-#define _MM_SET_DENORMALS_ZERO_MODE(x) (_mm_setcsr((_mm_getcsr() & ~_MM_DENORMALS_ZERO_MASK) | (x)))
-#endif
-
-namespace embree
-{
-
-////////////////////////////////////////////////////////////////////////////////
-/// Windows Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__WIN32__)
-
- __forceinline size_t read_tsc()
- {
- LARGE_INTEGER li;
- QueryPerformanceCounter(&li);
- return (size_t)li.QuadPart;
- }
-
- __forceinline int bsf(int v) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return _tzcnt_u32(v);
-#else
- unsigned long r = 0; _BitScanForward(&r,v); return r;
-#endif
- }
-
- __forceinline unsigned bsf(unsigned v) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return _tzcnt_u32(v);
-#else
- unsigned long r = 0; _BitScanForward(&r,v); return r;
-#endif
- }
-
-#if defined(__X86_64__)
- __forceinline size_t bsf(size_t v) {
-#if defined(__AVX2__)
- return _tzcnt_u64(v);
-#else
- unsigned long r = 0; _BitScanForward64(&r,v); return r;
-#endif
- }
-#endif
-
- __forceinline int bscf(int& v)
- {
- int i = bsf(v);
- v &= v-1;
- return i;
- }
-
- __forceinline unsigned bscf(unsigned& v)
- {
- unsigned i = bsf(v);
- v &= v-1;
- return i;
- }
-
-#if defined(__X86_64__)
- __forceinline size_t bscf(size_t& v)
- {
- size_t i = bsf(v);
- v &= v-1;
- return i;
- }
-#endif
-
- __forceinline int bsr(int v) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return 31 - _lzcnt_u32(v);
-#else
- unsigned long r = 0; _BitScanReverse(&r,v); return r;
-#endif
- }
-
- __forceinline unsigned bsr(unsigned v) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return 31 - _lzcnt_u32(v);
-#else
- unsigned long r = 0; _BitScanReverse(&r,v); return r;
-#endif
- }
-
-#if defined(__X86_64__)
- __forceinline size_t bsr(size_t v) {
-#if defined(__AVX2__)
- return 63 -_lzcnt_u64(v);
-#else
- unsigned long r = 0; _BitScanReverse64(&r, v); return r;
-#endif
- }
-#endif
-
- __forceinline int lzcnt(const int x)
- {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return _lzcnt_u32(x);
-#else
- if (unlikely(x == 0)) return 32;
- return 31 - bsr(x);
-#endif
- }
-
- __forceinline int btc(int v, int i) {
- long r = v; _bittestandcomplement(&r,i); return r;
- }
-
- __forceinline int bts(int v, int i) {
- long r = v; _bittestandset(&r,i); return r;
- }
-
- __forceinline int btr(int v, int i) {
- long r = v; _bittestandreset(&r,i); return r;
- }
-
-#if defined(__X86_64__)
-
- __forceinline size_t btc(size_t v, size_t i) {
- size_t r = v; _bittestandcomplement64((__int64*)&r,i); return r;
- }
-
- __forceinline size_t bts(size_t v, size_t i) {
- __int64 r = v; _bittestandset64(&r,i); return r;
- }
-
- __forceinline size_t btr(size_t v, size_t i) {
- __int64 r = v; _bittestandreset64(&r,i); return r;
- }
-
-#endif
-
- __forceinline int32_t atomic_cmpxchg(volatile int32_t* p, const int32_t c, const int32_t v) {
- return _InterlockedCompareExchange((volatile long*)p,v,c);
- }
-
-////////////////////////////////////////////////////////////////////////////////
-/// Unix Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#else
-
-#if defined(__i386__) && defined(__PIC__)
-
- __forceinline void __cpuid(int out[4], int op)
- {
- asm volatile ("xchg{l}\t{%%}ebx, %1\n\t"
- "cpuid\n\t"
- "xchg{l}\t{%%}ebx, %1\n\t"
- : "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3])
- : "0"(op));
- }
-
- __forceinline void __cpuid_count(int out[4], int op1, int op2)
- {
- asm volatile ("xchg{l}\t{%%}ebx, %1\n\t"
- "cpuid\n\t"
- "xchg{l}\t{%%}ebx, %1\n\t"
- : "=a" (out[0]), "=r" (out[1]), "=c" (out[2]), "=d" (out[3])
- : "0" (op1), "2" (op2));
- }
-
-#else
-
- __forceinline void __cpuid(int out[4], int op) {
-#if defined(__ARM_NEON)
- if (op == 0) { // Get CPU name
- out[0] = 0x41524d20;
- out[1] = 0x41524d20;
- out[2] = 0x41524d20;
- out[3] = 0x41524d20;
- }
-#else
- asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op));
-#endif
- }
-
-#if !defined(__ARM_NEON)
- __forceinline void __cpuid_count(int out[4], int op1, int op2) {
- asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op1), "c"(op2));
- }
-#endif
-
-#endif
-
- __forceinline uint64_t read_tsc() {
-#if defined(__ARM_NEON)
- return 0; // FIXME(LTE): mimic rdtsc
-#else
- uint32_t high,low;
- asm volatile ("rdtsc" : "=d"(high), "=a"(low));
- return (((uint64_t)high) << 32) + (uint64_t)low;
-#endif
- }
-
- __forceinline int bsf(int v) {
-#if defined(__ARM_NEON)
- return __builtin_ctz(v);
-#else
-#if defined(__AVX2__)
- return _tzcnt_u32(v);
-#else
- int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
-#endif
-#endif
- }
-
-#if defined(__X86_64__) || defined(__aarch64__)
- __forceinline unsigned bsf(unsigned v)
- {
-#if defined(__ARM_NEON)
- return __builtin_ctz(v);
-#else
-#if defined(__AVX2__)
- return _tzcnt_u32(v);
-#else
- unsigned r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
-#endif
-#endif
- }
-#endif
-
- __forceinline size_t bsf(size_t v) {
-#if defined(__AVX2__) && !defined(__aarch64__)
-#if defined(__X86_64__)
- return _tzcnt_u64(v);
-#else
- return _tzcnt_u32(v);
-#endif
-#elif defined(__ARM_NEON)
- return __builtin_ctzl(v);
-#else
- size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
-#endif
- }
-
- __forceinline int bscf(int& v)
- {
- int i = bsf(v);
- v &= v-1;
- return i;
- }
-
-#if defined(__X86_64__) || defined(__aarch64__)
- __forceinline unsigned int bscf(unsigned int& v)
- {
- unsigned int i = bsf(v);
- v &= v-1;
- return i;
- }
-#endif
-
- __forceinline size_t bscf(size_t& v)
- {
- size_t i = bsf(v);
- v &= v-1;
- return i;
- }
-
- __forceinline int bsr(int v) {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return 31 - _lzcnt_u32(v);
-#elif defined(__ARM_NEON)
- return __builtin_clz(v)^31;
-#else
- int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
-#endif
- }
-
-#if defined(__X86_64__) || defined(__aarch64__)
- __forceinline unsigned bsr(unsigned v) {
-#if defined(__AVX2__)
- return 31 - _lzcnt_u32(v);
-#elif defined(__ARM_NEON)
- return __builtin_clz(v)^31;
-#else
- unsigned r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
-#endif
- }
-#endif
-
- __forceinline size_t bsr(size_t v) {
-#if defined(__AVX2__) && !defined(__aarch64__)
-#if defined(__X86_64__)
- return 63 - _lzcnt_u64(v);
-#else
- return 31 - _lzcnt_u32(v);
-#endif
-#elif defined(__aarch64__)
- return (sizeof(v) * 8 - 1) - __builtin_clzl(v);
-#else
- size_t r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
-#endif
- }
-
- __forceinline int lzcnt(const int x)
- {
-#if defined(__AVX2__) && !defined(__aarch64__)
- return _lzcnt_u32(x);
-#else
- if (unlikely(x == 0)) return 32;
- return 31 - bsr(x);
-#endif
- }
-
- __forceinline size_t blsr(size_t v) {
-#if defined(__AVX2__) && !defined(__aarch64__)
-#if defined(__INTEL_COMPILER)
- return _blsr_u64(v);
-#else
-#if defined(__X86_64__)
- return __blsr_u64(v);
-#else
- return __blsr_u32(v);
-#endif
-#endif
-#else
- return v & (v-1);
-#endif
- }
-
- __forceinline int btc(int v, int i) {
-#if defined(__aarch64__)
- // _bittestandcomplement(long *a, long b) {
- // unsigned char x = (*a >> b) & 1;
- // *a = *a ^ (1 << b);
- // return x;
-
- // We only need `*a`
- return (v ^ (1 << i));
-#else
- int r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r;
-#endif
- }
-
- __forceinline int bts(int v, int i) {
-#if defined(__aarch64__)
- // _bittestandset(long *a, long b) {
- // unsigned char x = (*a >> b) & 1;
- // *a = *a | (1 << b);
- // return x;
- return (v | (v << i));
-#else
- int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
-#endif
- }
-
- __forceinline int btr(int v, int i) {
-#if defined(__aarch64__)
- // _bittestandreset(long *a, long b) {
- // unsigned char x = (*a >> b) & 1;
- // *a = *a & ~(1 << b);
- // return x;
- return (v & ~(v << i));
-#else
- int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
-#endif
- }
-
- __forceinline size_t btc(size_t v, size_t i) {
-#if defined(__aarch64__)
- return (v ^ (1 << i));
-#else
- size_t r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r;
-#endif
- }
-
- __forceinline size_t bts(size_t v, size_t i) {
-#if defined(__aarch64__)
- return (v | (v << i));
-#else
- size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
-#endif
- }
-
- __forceinline size_t btr(size_t v, size_t i) {
-#if defined(__ARM_NEON)
- return (v & ~(v << i));
-#else
- size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
-#endif
- }
-
- __forceinline int32_t atomic_cmpxchg(int32_t volatile* value, int32_t comparand, const int32_t input) {
- return __sync_val_compare_and_swap(value, comparand, input);
- }
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// All Platforms
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__clang__) || defined(__GNUC__)
-#if !defined(_mm_undefined_ps)
- __forceinline __m128 _mm_undefined_ps() { return _mm_setzero_ps(); }
-#endif
-#if !defined(_mm_undefined_si128)
- __forceinline __m128i _mm_undefined_si128() { return _mm_setzero_si128(); }
-#endif
-#if !defined(_mm256_undefined_ps) && defined(__AVX__)
- __forceinline __m256 _mm256_undefined_ps() { return _mm256_setzero_ps(); }
-#endif
-#if !defined(_mm256_undefined_si256) && defined(__AVX__)
- __forceinline __m256i _mm256_undefined_si256() { return _mm256_setzero_si256(); }
-#endif
-#if !defined(_mm512_undefined_ps) && defined(__AVX512F__)
- __forceinline __m512 _mm512_undefined_ps() { return _mm512_setzero_ps(); }
-#endif
-#if !defined(_mm512_undefined_epi32) && defined(__AVX512F__)
- __forceinline __m512i _mm512_undefined_epi32() { return _mm512_setzero_si512(); }
-#endif
-#endif
-
-#if defined(__SSE4_2__) || defined(__ARM_NEON)
-
- __forceinline int popcnt(int in) {
- return _mm_popcnt_u32(in);
- }
-
- __forceinline unsigned popcnt(unsigned in) {
- return _mm_popcnt_u32(in);
- }
-
-#if defined(__X86_64__) || defined(__ARM_NEON)
- __forceinline size_t popcnt(size_t in) {
- return _mm_popcnt_u64(in);
- }
-#endif
-
-#endif
-
- __forceinline uint64_t rdtsc()
- {
- int dummy[4];
- __cpuid(dummy,0);
- uint64_t clock = read_tsc();
- __cpuid(dummy,0);
- return clock;
- }
-
- __forceinline void pause_cpu(const size_t N = 8)
- {
- for (size_t i=0; i<N; i++)
- _mm_pause();
- }
-
- /* prefetches */
- __forceinline void prefetchL1 (const void* ptr) { _mm_prefetch((const char*)ptr,_MM_HINT_T0); }
- __forceinline void prefetchL2 (const void* ptr) { _mm_prefetch((const char*)ptr,_MM_HINT_T1); }
- __forceinline void prefetchL3 (const void* ptr) { _mm_prefetch((const char*)ptr,_MM_HINT_T2); }
- __forceinline void prefetchNTA(const void* ptr) { _mm_prefetch((const char*)ptr,_MM_HINT_NTA); }
- __forceinline void prefetchEX (const void* ptr) {
-#if defined(__INTEL_COMPILER)
- _mm_prefetch((const char*)ptr,_MM_HINT_ET0);
-#else
- _mm_prefetch((const char*)ptr,_MM_HINT_T0);
-#endif
- }
-
- __forceinline void prefetchL1EX(const void* ptr) {
- prefetchEX(ptr);
- }
-
- __forceinline void prefetchL2EX(const void* ptr) {
- prefetchEX(ptr);
- }
-#if defined(__AVX2__) && !defined(__aarch64__)
- __forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); }
- __forceinline unsigned int pdep(unsigned int a, unsigned int b) { return _pdep_u32(a, b); }
-#if defined(__X86_64__)
- __forceinline size_t pext(size_t a, size_t b) { return _pext_u64(a, b); }
- __forceinline size_t pdep(size_t a, size_t b) { return _pdep_u64(a, b); }
-#endif
-#endif
-
-#if defined(__AVX512F__)
-#if defined(__INTEL_COMPILER)
- __forceinline float mm512_cvtss_f32(__m512 v) {
- return _mm512_cvtss_f32(v);
- }
- __forceinline int mm512_mask2int(__mmask16 k1) {
- return _mm512_mask2int(k1);
- }
- __forceinline __mmask16 mm512_int2mask(int mask) {
- return _mm512_int2mask(mask);
- }
-#else
- __forceinline float mm512_cvtss_f32(__m512 v) { // FIXME: _mm512_cvtss_f32 neither supported by clang v4.0.0 nor GCC 6.3
- return _mm_cvtss_f32(_mm512_castps512_ps128(v));
- }
- __forceinline int mm512_mask2int(__mmask16 k1) { // FIXME: _mm512_mask2int not yet supported by GCC 6.3
- return (int)k1;
- }
- __forceinline __mmask16 mm512_int2mask(int mask) { // FIXME: _mm512_int2mask not yet supported by GCC 6.3
- return (__mmask16)mask;
- }
-#endif
-#endif
-}
diff --git a/thirdparty/embree-aarch64/common/sys/library.cpp b/thirdparty/embree-aarch64/common/sys/library.cpp
deleted file mode 100644
index 899267a1e4..0000000000
--- a/thirdparty/embree-aarch64/common/sys/library.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "library.h"
-#include "sysinfo.h"
-#include "filename.h"
-
-////////////////////////////////////////////////////////////////////////////////
-/// Windows Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__WIN32__)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-namespace embree
-{
- /* opens a shared library */
- lib_t openLibrary(const std::string& file)
- {
- std::string fullName = file+".dll";
- FileName executable = getExecutableFileName();
- HANDLE handle = LoadLibrary((executable.path() + fullName).c_str());
- return lib_t(handle);
- }
-
- /* returns address of a symbol from the library */
- void* getSymbol(lib_t lib, const std::string& sym) {
- return reinterpret_cast<void *>(GetProcAddress(HMODULE(lib),sym.c_str()));
- }
-
- /* closes the shared library */
- void closeLibrary(lib_t lib) {
- FreeLibrary(HMODULE(lib));
- }
-}
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Unix Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__UNIX__)
-
-#include <dlfcn.h>
-
-namespace embree
-{
- /* opens a shared library */
- lib_t openLibrary(const std::string& file)
- {
-#if defined(__MACOSX__)
- std::string fullName = "lib"+file+".dylib";
-#else
- std::string fullName = "lib"+file+".so";
-#endif
- void* lib = dlopen(fullName.c_str(), RTLD_NOW);
- if (lib) return lib_t(lib);
- FileName executable = getExecutableFileName();
- lib = dlopen((executable.path() + fullName).c_str(),RTLD_NOW);
- if (lib == nullptr) {
- const char* error = dlerror();
- if (error) {
- THROW_RUNTIME_ERROR(error);
- } else {
- THROW_RUNTIME_ERROR("could not load library "+executable.str());
- }
- }
- return lib_t(lib);
- }
-
- /* returns address of a symbol from the library */
- void* getSymbol(lib_t lib, const std::string& sym) {
- return dlsym(lib,sym.c_str());
- }
-
- /* closes the shared library */
- void closeLibrary(lib_t lib) {
- dlclose(lib);
- }
-}
-#endif
diff --git a/thirdparty/embree-aarch64/common/sys/library.h b/thirdparty/embree-aarch64/common/sys/library.h
deleted file mode 100644
index c2164e9fbe..0000000000
--- a/thirdparty/embree-aarch64/common/sys/library.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-
-namespace embree
-{
- /*! type for shared library */
- typedef struct opaque_lib_t* lib_t;
-
- /*! loads a shared library */
- lib_t openLibrary(const std::string& file);
-
- /*! returns address of a symbol from the library */
- void* getSymbol(lib_t lib, const std::string& sym);
-
- /*! unloads a shared library */
- void closeLibrary(lib_t lib);
-}
diff --git a/thirdparty/embree-aarch64/common/sys/mutex.cpp b/thirdparty/embree-aarch64/common/sys/mutex.cpp
deleted file mode 100644
index 11779bc9b9..0000000000
--- a/thirdparty/embree-aarch64/common/sys/mutex.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "mutex.h"
-#include "regression.h"
-
-#if defined(__WIN32__) && !defined(PTHREADS_WIN32)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-namespace embree
-{
- MutexSys::MutexSys() { mutex = new CRITICAL_SECTION; InitializeCriticalSection((CRITICAL_SECTION*)mutex); }
- MutexSys::~MutexSys() { DeleteCriticalSection((CRITICAL_SECTION*)mutex); delete (CRITICAL_SECTION*)mutex; }
- void MutexSys::lock() { EnterCriticalSection((CRITICAL_SECTION*)mutex); }
- bool MutexSys::try_lock() { return TryEnterCriticalSection((CRITICAL_SECTION*)mutex) != 0; }
- void MutexSys::unlock() { LeaveCriticalSection((CRITICAL_SECTION*)mutex); }
-}
-#endif
-
-#if defined(__UNIX__) || defined(PTHREADS_WIN32)
-#include <pthread.h>
-namespace embree
-{
- /*! system mutex using pthreads */
- MutexSys::MutexSys()
- {
- mutex = new pthread_mutex_t;
- if (pthread_mutex_init((pthread_mutex_t*)mutex, nullptr) != 0)
- THROW_RUNTIME_ERROR("pthread_mutex_init failed");
- }
-
- MutexSys::~MutexSys()
- {
- MAYBE_UNUSED bool ok = pthread_mutex_destroy((pthread_mutex_t*)mutex) == 0;
- assert(ok);
- delete (pthread_mutex_t*)mutex;
- mutex = nullptr;
- }
-
- void MutexSys::lock()
- {
- if (pthread_mutex_lock((pthread_mutex_t*)mutex) != 0)
- THROW_RUNTIME_ERROR("pthread_mutex_lock failed");
- }
-
- bool MutexSys::try_lock() {
- return pthread_mutex_trylock((pthread_mutex_t*)mutex) == 0;
- }
-
- void MutexSys::unlock()
- {
- if (pthread_mutex_unlock((pthread_mutex_t*)mutex) != 0)
- THROW_RUNTIME_ERROR("pthread_mutex_unlock failed");
- }
-};
-#endif
diff --git a/thirdparty/embree-aarch64/common/sys/mutex.h b/thirdparty/embree-aarch64/common/sys/mutex.h
deleted file mode 100644
index 1164210f23..0000000000
--- a/thirdparty/embree-aarch64/common/sys/mutex.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-#include "intrinsics.h"
-#include "atomic.h"
-
-namespace embree
-{
- /*! system mutex */
- class MutexSys {
- friend struct ConditionImplementation;
- public:
- MutexSys();
- ~MutexSys();
-
- private:
- MutexSys (const MutexSys& other) DELETED; // do not implement
- MutexSys& operator= (const MutexSys& other) DELETED; // do not implement
-
- public:
- void lock();
- bool try_lock();
- void unlock();
-
- protected:
- void* mutex;
- };
-
- /*! spinning mutex */
- class SpinLock
- {
- public:
-
- SpinLock ()
- : flag(false) {}
-
- __forceinline bool isLocked() {
- return flag.load();
- }
-
- __forceinline void lock()
- {
- while (true)
- {
- while (flag.load())
- {
- _mm_pause();
- _mm_pause();
- }
-
- bool expected = false;
- if (flag.compare_exchange_strong(expected,true,std::memory_order_acquire))
- break;
- }
- }
-
- __forceinline bool try_lock()
- {
- bool expected = false;
- if (flag.load() != expected) {
- return false;
- }
- return flag.compare_exchange_strong(expected,true,std::memory_order_acquire);
- }
-
- __forceinline void unlock() {
- flag.store(false,std::memory_order_release);
- }
-
- __forceinline void wait_until_unlocked()
- {
- while(flag.load())
- {
- _mm_pause();
- _mm_pause();
- }
- }
-
- public:
- atomic<bool> flag;
- };
-
- /*! safe mutex lock and unlock helper */
- template<typename Mutex> class Lock {
- public:
- Lock (Mutex& mutex) : mutex(mutex), locked(true) { mutex.lock(); }
- Lock (Mutex& mutex, bool locked) : mutex(mutex), locked(locked) {}
- ~Lock() { if (locked) mutex.unlock(); }
- __forceinline void lock() { assert(!locked); locked = true; mutex.lock(); }
- __forceinline bool isLocked() const { return locked; }
- protected:
- Mutex& mutex;
- bool locked;
- };
-}
diff --git a/thirdparty/embree-aarch64/common/sys/platform.h b/thirdparty/embree-aarch64/common/sys/platform.h
deleted file mode 100644
index 737f14aa6e..0000000000
--- a/thirdparty/embree-aarch64/common/sys/platform.h
+++ /dev/null
@@ -1,387 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#define _CRT_SECURE_NO_WARNINGS
-
-#include <cstddef>
-#include <cassert>
-#include <cstdlib>
-#include <cstdio>
-#include <memory>
-#include <stdexcept>
-#include <iostream>
-#include <iomanip>
-#include <fstream>
-#include <string>
-#include <cstring>
-#include <stdint.h>
-#include <functional>
-
-////////////////////////////////////////////////////////////////////////////////
-/// detect platform
-////////////////////////////////////////////////////////////////////////////////
-
-/* detect 32 or 64 platform */
-#if defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
-#define __X86_64__
-#endif
-
-/* detect Linux platform */
-#if defined(linux) || defined(__linux__) || defined(__LINUX__)
-# if !defined(__LINUX__)
-# define __LINUX__
-# endif
-# if !defined(__UNIX__)
-# define __UNIX__
-# endif
-#endif
-
-/* detect FreeBSD platform */
-#if defined(__FreeBSD__) || defined(__FREEBSD__)
-# if !defined(__FREEBSD__)
-# define __FREEBSD__
-# endif
-# if !defined(__UNIX__)
-# define __UNIX__
-# endif
-#endif
-
-/* detect Windows 95/98/NT/2000/XP/Vista/7/8/10 platform */
-#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) && !defined(__CYGWIN__)
-# if !defined(__WIN32__)
-# define __WIN32__
-# endif
-#endif
-
-/* detect Cygwin platform */
-#if defined(__CYGWIN__)
-# if !defined(__UNIX__)
-# define __UNIX__
-# endif
-#endif
-
-/* detect MAC OS X platform */
-#if defined(__APPLE__) || defined(MACOSX) || defined(__MACOSX__)
-# if !defined(__MACOSX__)
-# define __MACOSX__
-# endif
-# if !defined(__UNIX__)
-# define __UNIX__
-# endif
-#endif
-
-/* try to detect other Unix systems */
-#if defined(__unix__) || defined (unix) || defined(__unix) || defined(_unix)
-# if !defined(__UNIX__)
-# define __UNIX__
-# endif
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Macros
-////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __WIN32__
-#define dll_export __declspec(dllexport)
-#define dll_import __declspec(dllimport)
-#else
-#define dll_export __attribute__ ((visibility ("default")))
-#define dll_import
-#endif
-
-#ifdef __WIN32__
-#if !defined(__noinline)
-#define __noinline __declspec(noinline)
-#endif
-//#define __forceinline __forceinline
-//#define __restrict __restrict
-#if defined(__INTEL_COMPILER)
-#define __restrict__ __restrict
-#else
-#define __restrict__ //__restrict // causes issues with MSVC
-#endif
-#if !defined(__thread)
-// NOTE: Require `-fms-extensions` for clang
-#define __thread __declspec(thread)
-#endif
-#if !defined(__aligned)
-#if defined(__MINGW32__)
-#define __aligned(...) __attribute__((aligned(__VA_ARGS__)))
-#else
-#define __aligned(...) __declspec(align(__VA_ARGS__))
-#endif
-#endif
-//#define __FUNCTION__ __FUNCTION__
-#define debugbreak() __debugbreak()
-
-#else
-#if !defined(__noinline)
-#define __noinline __attribute__((noinline))
-#endif
-#if !defined(__forceinline)
-#define __forceinline inline __attribute__((always_inline))
-#endif
-//#define __restrict __restrict
-//#define __thread __thread
-#if !defined(__aligned)
-#define __aligned(...) __attribute__((aligned(__VA_ARGS__)))
-#endif
-#if !defined(__FUNCTION__)
-#define __FUNCTION__ __PRETTY_FUNCTION__
-#endif
-#define debugbreak() asm ("int $3")
-#endif
-
-#if defined(__clang__) || defined(__GNUC__)
- #define MAYBE_UNUSED __attribute__((unused))
-#else
- #define MAYBE_UNUSED
-#endif
-
-#if defined(_MSC_VER) && (_MSC_VER < 1900) // before VS2015 deleted functions are not supported properly
- #define DELETED
-#else
- #define DELETED = delete
-#endif
-
-// -- GODOT start --
-#ifndef likely
-// -- GODOT end --
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
-#define likely(expr) (expr)
-#define unlikely(expr) (expr)
-#else
-#define likely(expr) __builtin_expect((bool)(expr),true )
-#define unlikely(expr) __builtin_expect((bool)(expr),false)
-#endif
-// -- GODOT start --
-#endif
-// -- GODOT end --
-
-////////////////////////////////////////////////////////////////////////////////
-/// Error handling and debugging
-////////////////////////////////////////////////////////////////////////////////
-
-/* debug printing macros */
-#define STRING(x) #x
-#define TOSTRING(x) STRING(x)
-#define PING embree_cout << __FILE__ << " (" << __LINE__ << "): " << __FUNCTION__ << embree_endl
-#define PRINT(x) embree_cout << STRING(x) << " = " << (x) << embree_endl
-#define PRINT2(x,y) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << embree_endl
-#define PRINT3(x,y,z) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << embree_endl
-#define PRINT4(x,y,z,w) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << embree_endl
-
-#if defined(DEBUG) // only report file and line in debug mode
- // -- GODOT start --
- // #define THROW_RUNTIME_ERROR(str)
- // throw std::runtime_error(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
- #define THROW_RUNTIME_ERROR(str) \
- printf(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)), abort();
- // -- GODOT end --
-#else
- // -- GODOT start --
- // #define THROW_RUNTIME_ERROR(str)
- // throw std::runtime_error(str);
- #define THROW_RUNTIME_ERROR(str) \
- abort();
- // -- GODOT end --
-#endif
-
-#define FATAL(x) THROW_RUNTIME_ERROR(x)
-#define WARNING(x) { std::cerr << "Warning: " << x << embree_endl << std::flush; }
-
-#define NOT_IMPLEMENTED FATAL(std::string(__FUNCTION__) + " not implemented")
-
-////////////////////////////////////////////////////////////////////////////////
-/// Basic types
-////////////////////////////////////////////////////////////////////////////////
-
-/* default floating-point type */
-namespace embree {
- typedef float real;
-}
-
-/* windows does not have ssize_t */
-#if defined(__WIN32__)
-#if defined(__X86_64__) || defined(__aarch64__)
-typedef int64_t ssize_t;
-#else
-typedef int32_t ssize_t;
-#endif
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Basic utility functions
-////////////////////////////////////////////////////////////////////////////////
-
-__forceinline std::string toString(long long value) {
- return std::to_string(value);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// Disable some compiler warnings
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__INTEL_COMPILER)
-//#pragma warning(disable:265 ) // floating-point operation result is out of range
-//#pragma warning(disable:383 ) // value copied to temporary, reference to temporary used
-//#pragma warning(disable:869 ) // parameter was never referenced
-//#pragma warning(disable:981 ) // operands are evaluated in unspecified order
-//#pragma warning(disable:1418) // external function definition with no prior declaration
-//#pragma warning(disable:1419) // external declaration in primary source file
-//#pragma warning(disable:1572) // floating-point equality and inequality comparisons are unreliable
-//#pragma warning(disable:94 ) // the size of an array must be greater than zero
-//#pragma warning(disable:1599) // declaration hides parameter
-//#pragma warning(disable:424 ) // extra ";" ignored
-#pragma warning(disable:2196) // routine is both "inline" and "noinline"
-//#pragma warning(disable:177 ) // label was declared but never referenced
-//#pragma warning(disable:114 ) // function was referenced but not defined
-//#pragma warning(disable:819 ) // template nesting depth does not match the previous declaration of function
-#pragma warning(disable:15335) // was not vectorized: vectorization possible but seems inefficient
-#endif
-
-#if defined(_MSC_VER)
-//#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union
-#pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning)
-//#pragma warning(disable:4267) // '=' : conversion from 'size_t' to 'unsigned long', possible loss of data
-#pragma warning(disable:4244) // 'argument' : conversion from 'ssize_t' to 'unsigned int', possible loss of data
-//#pragma warning(disable:4355) // 'this' : used in base member initializer list
-//#pragma warning(disable:391 ) // '<=' : signed / unsigned mismatch
-//#pragma warning(disable:4018) // '<' : signed / unsigned mismatch
-//#pragma warning(disable:4305) // 'initializing' : truncation from 'double' to 'float'
-//#pragma warning(disable:4068) // unknown pragma
-//#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
-//#pragma warning(disable:4838) // conversion from 'unsigned int' to 'const int' requires a narrowing conversion)
-//#pragma warning(disable:4227) // anachronism used : qualifiers on reference are ignored
-#pragma warning(disable:4503) // decorated name length exceeded, name was truncated
-#pragma warning(disable:4180) // qualifier applied to function type has no meaning; ignored
-#pragma warning(disable:4258) // definition from the for loop is ignored; the definition from the enclosing scope is used
-
-# if _MSC_VER < 1910 // prior to Visual studio 2017 (V141)
-# pragma warning(disable:4101) // warning C4101: 'x': unreferenced local variable // a compiler bug issues wrong warnings
-# pragma warning(disable:4789) // buffer '' of size 8 bytes will be overrun; 32 bytes will be written starting at offset 0
-# endif
-
-#endif
-
-#if defined(__clang__) && !defined(__INTEL_COMPILER)
-//#pragma clang diagnostic ignored "-Wunknown-pragmas"
-//#pragma clang diagnostic ignored "-Wunused-variable"
-//#pragma clang diagnostic ignored "-Wreorder"
-//#pragma clang diagnostic ignored "-Wmicrosoft"
-//#pragma clang diagnostic ignored "-Wunused-private-field"
-//#pragma clang diagnostic ignored "-Wunused-local-typedef"
-//#pragma clang diagnostic ignored "-Wunused-function"
-//#pragma clang diagnostic ignored "-Wnarrowing"
-//#pragma clang diagnostic ignored "-Wc++11-narrowing"
-//#pragma clang diagnostic ignored "-Wdeprecated-register"
-//#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
-#pragma GCC diagnostic ignored "-Wpragmas"
-//#pragma GCC diagnostic ignored "-Wnarrowing"
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-//#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-//#pragma GCC diagnostic ignored "-Warray-bounds"
-#pragma GCC diagnostic ignored "-Wattributes"
-#pragma GCC diagnostic ignored "-Wmisleading-indentation"
-#pragma GCC diagnostic ignored "-Wsign-compare"
-#pragma GCC diagnostic ignored "-Wparentheses"
-#endif
-
-#if defined(__clang__) && defined(__WIN32__)
-#pragma clang diagnostic ignored "-Wunused-parameter"
-#pragma clang diagnostic ignored "-Wmicrosoft-cast"
-#pragma clang diagnostic ignored "-Wmicrosoft-enum-value"
-#pragma clang diagnostic ignored "-Wmicrosoft-include"
-#pragma clang diagnostic ignored "-Wunused-function"
-#pragma clang diagnostic ignored "-Wunknown-pragmas"
-#endif
-
-/* disabling deprecated warning, please use only where use of deprecated Embree API functions is desired */
-#if defined(__WIN32__) && defined(__INTEL_COMPILER)
-#define DISABLE_DEPRECATED_WARNING __pragma(warning (disable: 1478)) // warning: function was declared deprecated
-#define ENABLE_DEPRECATED_WARNING __pragma(warning (enable: 1478)) // warning: function was declared deprecated
-#elif defined(__INTEL_COMPILER)
-#define DISABLE_DEPRECATED_WARNING _Pragma("warning (disable: 1478)") // warning: function was declared deprecated
-#define ENABLE_DEPRECATED_WARNING _Pragma("warning (enable : 1478)") // warning: function was declared deprecated
-#elif defined(__clang__)
-#define DISABLE_DEPRECATED_WARNING _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") // warning: xxx is deprecated
-#define ENABLE_DEPRECATED_WARNING _Pragma("clang diagnostic warning \"-Wdeprecated-declarations\"") // warning: xxx is deprecated
-#elif defined(__GNUC__)
-#define DISABLE_DEPRECATED_WARNING _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") // warning: xxx is deprecated
-#define ENABLE_DEPRECATED_WARNING _Pragma("GCC diagnostic warning \"-Wdeprecated-declarations\"") // warning: xxx is deprecated
-#elif defined(_MSC_VER)
-#define DISABLE_DEPRECATED_WARNING __pragma(warning (disable: 4996)) // warning: function was declared deprecated
-#define ENABLE_DEPRECATED_WARNING __pragma(warning (enable : 4996)) // warning: function was declared deprecated
-#endif
-
-/* embree output stream */
-#define embree_ostream std::ostream&
-#define embree_cout std::cout
-#define embree_cout_uniform std::cout
-#define embree_endl std::endl
-
-////////////////////////////////////////////////////////////////////////////////
-/// Some macros for static profiling
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined (__GNUC__)
-#define IACA_SSC_MARK( MARK_ID ) \
-__asm__ __volatile__ ( \
- "\n\t movl $"#MARK_ID", %%ebx" \
- "\n\t .byte 0x64, 0x67, 0x90" \
- : : : "memory" );
-
-#define IACA_UD_BYTES __asm__ __volatile__ ("\n\t .byte 0x0F, 0x0B");
-
-#else
-#define IACA_UD_BYTES {__asm _emit 0x0F \
- __asm _emit 0x0B}
-
-#define IACA_SSC_MARK(x) {__asm mov ebx, x\
- __asm _emit 0x64 \
- __asm _emit 0x67 \
- __asm _emit 0x90 }
-
-#define IACA_VC64_START __writegsbyte(111, 111);
-#define IACA_VC64_END __writegsbyte(222, 222);
-
-#endif
-
-#define IACA_START {IACA_UD_BYTES \
- IACA_SSC_MARK(111)}
-#define IACA_END {IACA_SSC_MARK(222) \
- IACA_UD_BYTES}
-
-namespace embree
-{
- template<typename Closure>
- struct OnScopeExitHelper
- {
- OnScopeExitHelper (const Closure f) : active(true), f(f) {}
- ~OnScopeExitHelper() { if (active) f(); }
- void deactivate() { active = false; }
- bool active;
- const Closure f;
- };
-
- template <typename Closure>
- OnScopeExitHelper<Closure> OnScopeExit(const Closure f) {
- return OnScopeExitHelper<Closure>(f);
- }
-
-#define STRING_JOIN2(arg1, arg2) DO_STRING_JOIN2(arg1, arg2)
-#define DO_STRING_JOIN2(arg1, arg2) arg1 ## arg2
-#define ON_SCOPE_EXIT(code) \
- auto STRING_JOIN2(on_scope_exit_, __LINE__) = OnScopeExit([&](){code;})
-
- template<typename Ty>
- std::unique_ptr<Ty> make_unique(Ty* ptr) {
- return std::unique_ptr<Ty>(ptr);
- }
-
-}
diff --git a/thirdparty/embree-aarch64/common/sys/ref.h b/thirdparty/embree-aarch64/common/sys/ref.h
deleted file mode 100644
index 24648e6234..0000000000
--- a/thirdparty/embree-aarch64/common/sys/ref.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "atomic.h"
-
-namespace embree
-{
- struct NullTy {
- };
-
- extern MAYBE_UNUSED NullTy null;
-
- class RefCount
- {
- public:
- RefCount(int val = 0) : refCounter(val) {}
- virtual ~RefCount() {};
-
- virtual RefCount* refInc() { refCounter.fetch_add(1); return this; }
- virtual void refDec() { if (refCounter.fetch_add(-1) == 1) delete this; }
- private:
- std::atomic<size_t> refCounter;
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Reference to single object
- ////////////////////////////////////////////////////////////////////////////////
-
- template<typename Type>
- class Ref
- {
- public:
- Type* ptr;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline Ref() : ptr(nullptr) {}
- __forceinline Ref(NullTy) : ptr(nullptr) {}
- __forceinline Ref(const Ref& input) : ptr(input.ptr) { if (ptr) ptr->refInc(); }
- __forceinline Ref(Ref&& input) : ptr(input.ptr) { input.ptr = nullptr; }
-
- __forceinline Ref(Type* const input) : ptr(input)
- {
- if (ptr)
- ptr->refInc();
- }
-
- __forceinline ~Ref()
- {
- if (ptr)
- ptr->refDec();
- }
-
- __forceinline Ref& operator =(const Ref& input)
- {
- if (input.ptr)
- input.ptr->refInc();
- if (ptr)
- ptr->refDec();
- ptr = input.ptr;
- return *this;
- }
-
- __forceinline Ref& operator =(Ref&& input)
- {
- if (ptr)
- ptr->refDec();
- ptr = input.ptr;
- input.ptr = nullptr;
- return *this;
- }
-
- __forceinline Ref& operator =(Type* const input)
- {
- if (input)
- input->refInc();
- if (ptr)
- ptr->refDec();
- ptr = input;
- return *this;
- }
-
- __forceinline Ref& operator =(NullTy)
- {
- if (ptr)
- ptr->refDec();
- ptr = nullptr;
- return *this;
- }
-
- __forceinline operator bool() const { return ptr != nullptr; }
-
- __forceinline const Type& operator *() const { return *ptr; }
- __forceinline Type& operator *() { return *ptr; }
- __forceinline const Type* operator ->() const { return ptr; }
- __forceinline Type* operator ->() { return ptr; }
-
- template<typename TypeOut>
- __forceinline Ref<TypeOut> cast() { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
- template<typename TypeOut>
- __forceinline const Ref<TypeOut> cast() const { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
-
- template<typename TypeOut>
- __forceinline Ref<TypeOut> dynamicCast() { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); }
- template<typename TypeOut>
- __forceinline const Ref<TypeOut> dynamicCast() const { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); }
- };
-
- template<typename Type> __forceinline bool operator < (const Ref<Type>& a, const Ref<Type>& b) { return a.ptr < b.ptr; }
-
- template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, NullTy ) { return a.ptr == nullptr; }
- template<typename Type> __forceinline bool operator ==(NullTy , const Ref<Type>& b) { return nullptr == b.ptr; }
- template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr == b.ptr; }
-
- template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, NullTy ) { return a.ptr != nullptr; }
- template<typename Type> __forceinline bool operator !=(NullTy , const Ref<Type>& b) { return nullptr != b.ptr; }
- template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr != b.ptr; }
-}
diff --git a/thirdparty/embree-aarch64/common/sys/regression.cpp b/thirdparty/embree-aarch64/common/sys/regression.cpp
deleted file mode 100644
index d95ff8dfe0..0000000000
--- a/thirdparty/embree-aarch64/common/sys/regression.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "regression.h"
-
-namespace embree
-{
- /* registerRegressionTest is invoked from static initializers, thus
- * we cannot have the regression_tests variable as global static
- * variable due to issues with static variable initialization
- * order. */
- std::vector<RegressionTest*>& get_regression_tests()
- {
- static std::vector<RegressionTest*> regression_tests;
- return regression_tests;
- }
-
- void registerRegressionTest(RegressionTest* test)
- {
- get_regression_tests().push_back(test);
- }
-
- RegressionTest* getRegressionTest(size_t index)
- {
- if (index >= get_regression_tests().size())
- return nullptr;
-
- return get_regression_tests()[index];
- }
-}
diff --git a/thirdparty/embree-aarch64/common/sys/regression.h b/thirdparty/embree-aarch64/common/sys/regression.h
deleted file mode 100644
index 632f8d92cf..0000000000
--- a/thirdparty/embree-aarch64/common/sys/regression.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-
-#include <vector>
-
-namespace embree
-{
- /*! virtual interface for all regression tests */
- struct RegressionTest
- {
- RegressionTest (std::string name) : name(name) {}
- virtual bool run() = 0;
- std::string name;
- };
-
- /*! registers a regression test */
- void registerRegressionTest(RegressionTest* test);
-
- /*! run all regression tests */
- RegressionTest* getRegressionTest(size_t index);
-}
diff --git a/thirdparty/embree-aarch64/common/sys/string.cpp b/thirdparty/embree-aarch64/common/sys/string.cpp
deleted file mode 100644
index 931244383e..0000000000
--- a/thirdparty/embree-aarch64/common/sys/string.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "string.h"
-
-#include <algorithm>
-#include <ctype.h>
-
-namespace embree
-{
- char to_lower(char c) { return char(tolower(int(c))); }
- char to_upper(char c) { return char(toupper(int(c))); }
- std::string toLowerCase(const std::string& s) { std::string dst(s); std::transform(dst.begin(), dst.end(), dst.begin(), to_lower); return dst; }
- std::string toUpperCase(const std::string& s) { std::string dst(s); std::transform(dst.begin(), dst.end(), dst.begin(), to_upper); return dst; }
-
- Vec2f string_to_Vec2f ( std::string str )
- {
- size_t next = 0;
- const float x = std::stof(str,&next); str = str.substr(next+1);
- const float y = std::stof(str,&next);
- return Vec2f(x,y);
- }
-
- Vec3f string_to_Vec3f ( std::string str )
- {
- size_t next = 0;
- const float x = std::stof(str,&next); str = str.substr(next+1);
- const float y = std::stof(str,&next); str = str.substr(next+1);
- const float z = std::stof(str,&next);
- return Vec3f(x,y,z);
- }
-
- Vec4f string_to_Vec4f ( std::string str )
- {
- size_t next = 0;
- const float x = std::stof(str,&next); str = str.substr(next+1);
- const float y = std::stof(str,&next); str = str.substr(next+1);
- const float z = std::stof(str,&next); str = str.substr(next+1);
- const float w = std::stof(str,&next);
- return Vec4f(x,y,z,w);
- }
-}
diff --git a/thirdparty/embree-aarch64/common/sys/string.h b/thirdparty/embree-aarch64/common/sys/string.h
deleted file mode 100644
index 2e9b0f88c3..0000000000
--- a/thirdparty/embree-aarch64/common/sys/string.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-#include "../math/vec2.h"
-#include "../math/vec3.h"
-#include "../math/vec4.h"
-
-namespace embree
-{
- class IOStreamStateRestorer
- {
- public:
- IOStreamStateRestorer(std::ostream& iostream)
- : iostream(iostream), flags(iostream.flags()), precision(iostream.precision()) {
- }
-
- ~IOStreamStateRestorer() {
- iostream.flags(flags);
- iostream.precision(precision);
- }
-
- private:
- std::ostream& iostream;
- std::ios::fmtflags flags;
- std::streamsize precision;
- };
-
- std::string toLowerCase(const std::string& s);
- std::string toUpperCase(const std::string& s);
-
- Vec2f string_to_Vec2f ( std::string str );
- Vec3f string_to_Vec3f ( std::string str );
- Vec4f string_to_Vec4f ( std::string str );
-}
diff --git a/thirdparty/embree-aarch64/common/sys/sysinfo.cpp b/thirdparty/embree-aarch64/common/sys/sysinfo.cpp
deleted file mode 100644
index 1d11436770..0000000000
--- a/thirdparty/embree-aarch64/common/sys/sysinfo.cpp
+++ /dev/null
@@ -1,676 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "sysinfo.h"
-#include "intrinsics.h"
-#include "string.h"
-#include "ref.h"
-#if defined(__FREEBSD__)
-#include <sys/cpuset.h>
-#include <pthread_np.h>
-typedef cpuset_t cpu_set_t;
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// All Platforms
-////////////////////////////////////////////////////////////////////////////////
-
-namespace embree
-{
- NullTy null;
-
- std::string getPlatformName()
- {
-#if defined(__LINUX__) && defined(__ANDROID__) && defined(__aarch64__) && defined(__ARM_NEON)
- return "Android Linux (aarch64 / arm64)";
-#elif defined(__LINUX__) && defined(__ANDROID__) && defined(__X86_64__)
- return "Android Linux (x64)";
-#elif defined(__LINUX__) && defined(__ANDROID__) && (defined(_X86_) || defined(__X86__) || defined(_M_IX86))
- return "Android Linux (x86)";
-#elif defined(__LINUX__) && !defined(__X86_64__)
- return "Linux (32bit)";
-#elif defined(__LINUX__) && defined(__X86_64__)
- return "Linux (64bit)";
-#elif defined(__FREEBSD__) && !defined(__X86_64__)
- return "FreeBSD (32bit)";
-#elif defined(__FREEBSD__) && defined(__X86_64__)
- return "FreeBSD (64bit)";
-#elif defined(__CYGWIN__) && !defined(__X86_64__)
- return "Cygwin (32bit)";
-#elif defined(__CYGWIN__) && defined(__X86_64__)
- return "Cygwin (64bit)";
-#elif defined(__WIN32__) && !defined(__X86_64__)
- return "Windows (32bit)";
-#elif defined(__WIN32__) && defined(__X86_64__)
- return "Windows (64bit)";
-#elif defined(TARGET_IPHONE_SIMULATOR) && defined(__X86_64__)
- return "iOS Simulator (x64)";
-#elif defined(TARGET_OS_IPHONE) && defined(__aarch64__) && defined(__ARM_NEON)
- return "iOS (aarch64 / arm64)";
-#elif defined(__MACOSX__) && !defined(__X86_64__)
- return "Mac OS X (32bit)";
-#elif defined(__MACOSX__) && defined(__X86_64__)
- return "Mac OS X (64bit)";
-#elif defined(__UNIX__) && defined(__aarch64__)
- return "Unix (aarch64)";
-#elif defined(__UNIX__) && !defined(__X86_64__)
- return "Unix (32bit)";
-#elif defined(__UNIX__) && defined(__X86_64__)
- return "Unix (64bit)";
-#else
- return "Unknown";
-#endif
- }
-
- std::string getCompilerName()
- {
-#if defined(__INTEL_COMPILER)
- int icc_mayor = __INTEL_COMPILER / 100 % 100;
- int icc_minor = __INTEL_COMPILER % 100;
- std::string version = "Intel Compiler ";
- version += toString(icc_mayor);
- version += "." + toString(icc_minor);
-#if defined(__INTEL_COMPILER_UPDATE)
- version += "." + toString(__INTEL_COMPILER_UPDATE);
-#endif
- return version;
-#elif defined(__clang__)
- return "CLANG " __clang_version__;
-#elif defined (__GNUC__)
- return "GCC " __VERSION__;
-#elif defined(_MSC_VER)
- std::string version = toString(_MSC_FULL_VER);
- version.insert(4,".");
- version.insert(9,".");
- version.insert(2,".");
- return "Visual C++ Compiler " + version;
-#else
- return "Unknown Compiler";
-#endif
- }
-
- std::string getCPUVendor()
- {
- int cpuinfo[4];
- __cpuid (cpuinfo, 0);
- int name[4];
- name[0] = cpuinfo[1];
- name[1] = cpuinfo[3];
- name[2] = cpuinfo[2];
- name[3] = 0;
- return (char*)name;
- }
-
- CPU getCPUModel()
- {
- if (getCPUVendor() != "GenuineIntel")
- return CPU::UNKNOWN;
-
- int out[4];
- __cpuid(out, 0);
- if (out[0] < 1) return CPU::UNKNOWN;
- __cpuid(out, 1);
-
- /* please see CPUID documentation for these formulas */
- uint32_t family_ID = (out[0] >> 8) & 0x0F;
- uint32_t extended_family_ID = (out[0] >> 20) & 0xFF;
-
- uint32_t model_ID = (out[0] >> 4) & 0x0F;
- uint32_t extended_model_ID = (out[0] >> 16) & 0x0F;
-
- uint32_t DisplayFamily = family_ID;
- if (family_ID == 0x0F)
- DisplayFamily += extended_family_ID;
-
- uint32_t DisplayModel = model_ID;
- if (family_ID == 0x06 || family_ID == 0x0F)
- DisplayModel += extended_model_ID << 4;
-
- uint32_t DisplayFamily_DisplayModel = (DisplayFamily << 8) + (DisplayModel << 0);
-
- // Data from Intel® 64 and IA-32 Architectures, Volume 4, Chapter 2, Table 2-1 (CPUID Signature Values of DisplayFamily_DisplayModel)
- if (DisplayFamily_DisplayModel == 0x067D) return CPU::CORE_ICE_LAKE;
- if (DisplayFamily_DisplayModel == 0x067E) return CPU::CORE_ICE_LAKE;
- if (DisplayFamily_DisplayModel == 0x068C) return CPU::CORE_TIGER_LAKE;
- if (DisplayFamily_DisplayModel == 0x06A5) return CPU::CORE_COMET_LAKE;
- if (DisplayFamily_DisplayModel == 0x06A6) return CPU::CORE_COMET_LAKE;
- if (DisplayFamily_DisplayModel == 0x0666) return CPU::CORE_CANNON_LAKE;
- if (DisplayFamily_DisplayModel == 0x068E) return CPU::CORE_KABY_LAKE;
- if (DisplayFamily_DisplayModel == 0x069E) return CPU::CORE_KABY_LAKE;
- if (DisplayFamily_DisplayModel == 0x066A) return CPU::XEON_ICE_LAKE;
- if (DisplayFamily_DisplayModel == 0x066C) return CPU::XEON_ICE_LAKE;
- if (DisplayFamily_DisplayModel == 0x0655) return CPU::XEON_SKY_LAKE;
- if (DisplayFamily_DisplayModel == 0x064E) return CPU::CORE_SKY_LAKE;
- if (DisplayFamily_DisplayModel == 0x065E) return CPU::CORE_SKY_LAKE;
- if (DisplayFamily_DisplayModel == 0x0656) return CPU::XEON_BROADWELL;
- if (DisplayFamily_DisplayModel == 0x064F) return CPU::XEON_BROADWELL;
- if (DisplayFamily_DisplayModel == 0x0647) return CPU::CORE_BROADWELL;
- if (DisplayFamily_DisplayModel == 0x063D) return CPU::CORE_BROADWELL;
- if (DisplayFamily_DisplayModel == 0x063F) return CPU::XEON_HASWELL;
- if (DisplayFamily_DisplayModel == 0x063C) return CPU::CORE_HASWELL;
- if (DisplayFamily_DisplayModel == 0x0645) return CPU::CORE_HASWELL;
- if (DisplayFamily_DisplayModel == 0x0646) return CPU::CORE_HASWELL;
- if (DisplayFamily_DisplayModel == 0x063E) return CPU::XEON_IVY_BRIDGE;
- if (DisplayFamily_DisplayModel == 0x063A) return CPU::CORE_IVY_BRIDGE;
- if (DisplayFamily_DisplayModel == 0x062D) return CPU::SANDY_BRIDGE;
- if (DisplayFamily_DisplayModel == 0x062F) return CPU::SANDY_BRIDGE;
- if (DisplayFamily_DisplayModel == 0x062A) return CPU::SANDY_BRIDGE;
- if (DisplayFamily_DisplayModel == 0x062E) return CPU::NEHALEM;
- if (DisplayFamily_DisplayModel == 0x0625) return CPU::NEHALEM;
- if (DisplayFamily_DisplayModel == 0x062C) return CPU::NEHALEM;
- if (DisplayFamily_DisplayModel == 0x061E) return CPU::NEHALEM;
- if (DisplayFamily_DisplayModel == 0x061F) return CPU::NEHALEM;
- if (DisplayFamily_DisplayModel == 0x061A) return CPU::NEHALEM;
- if (DisplayFamily_DisplayModel == 0x061D) return CPU::NEHALEM;
- if (DisplayFamily_DisplayModel == 0x0617) return CPU::CORE2;
- if (DisplayFamily_DisplayModel == 0x060F) return CPU::CORE2;
- if (DisplayFamily_DisplayModel == 0x060E) return CPU::CORE1;
-
- if (DisplayFamily_DisplayModel == 0x0685) return CPU::XEON_PHI_KNIGHTS_MILL;
- if (DisplayFamily_DisplayModel == 0x0657) return CPU::XEON_PHI_KNIGHTS_LANDING;
-
- return CPU::UNKNOWN;
- }
-
- std::string stringOfCPUModel(CPU model)
- {
- switch (model) {
- case CPU::XEON_ICE_LAKE : return "Xeon Ice Lake";
- case CPU::CORE_ICE_LAKE : return "Core Ice Lake";
- case CPU::CORE_TIGER_LAKE : return "Core Tiger Lake";
- case CPU::CORE_COMET_LAKE : return "Core Comet Lake";
- case CPU::CORE_CANNON_LAKE : return "Core Cannon Lake";
- case CPU::CORE_KABY_LAKE : return "Core Kaby Lake";
- case CPU::XEON_SKY_LAKE : return "Xeon Sky Lake";
- case CPU::CORE_SKY_LAKE : return "Core Sky Lake";
- case CPU::XEON_PHI_KNIGHTS_MILL : return "Xeon Phi Knights Mill";
- case CPU::XEON_PHI_KNIGHTS_LANDING: return "Xeon Phi Knights Landing";
- case CPU::XEON_BROADWELL : return "Xeon Broadwell";
- case CPU::CORE_BROADWELL : return "Core Broadwell";
- case CPU::XEON_HASWELL : return "Xeon Haswell";
- case CPU::CORE_HASWELL : return "Core Haswell";
- case CPU::XEON_IVY_BRIDGE : return "Xeon Ivy Bridge";
- case CPU::CORE_IVY_BRIDGE : return "Core Ivy Bridge";
- case CPU::SANDY_BRIDGE : return "Sandy Bridge";
- case CPU::NEHALEM : return "Nehalem";
- case CPU::CORE2 : return "Core2";
- case CPU::CORE1 : return "Core";
- case CPU::ARM : return "Arm";
- case CPU::UNKNOWN : return "Unknown CPU";
- }
- return "Unknown CPU (error)";
- }
-
-#if !defined(__ARM_NEON)
- /* constants to access destination registers of CPUID instruction */
- static const int EAX = 0;
- static const int EBX = 1;
- static const int ECX = 2;
- static const int EDX = 3;
-
- /* cpuid[eax=1].ecx */
- static const int CPU_FEATURE_BIT_SSE3 = 1 << 0;
- static const int CPU_FEATURE_BIT_SSSE3 = 1 << 9;
- static const int CPU_FEATURE_BIT_FMA3 = 1 << 12;
- static const int CPU_FEATURE_BIT_SSE4_1 = 1 << 19;
- static const int CPU_FEATURE_BIT_SSE4_2 = 1 << 20;
- //static const int CPU_FEATURE_BIT_MOVBE = 1 << 22;
- static const int CPU_FEATURE_BIT_POPCNT = 1 << 23;
- //static const int CPU_FEATURE_BIT_XSAVE = 1 << 26;
- static const int CPU_FEATURE_BIT_OXSAVE = 1 << 27;
- static const int CPU_FEATURE_BIT_AVX = 1 << 28;
- static const int CPU_FEATURE_BIT_F16C = 1 << 29;
- static const int CPU_FEATURE_BIT_RDRAND = 1 << 30;
-
- /* cpuid[eax=1].edx */
- static const int CPU_FEATURE_BIT_SSE = 1 << 25;
- static const int CPU_FEATURE_BIT_SSE2 = 1 << 26;
-
- /* cpuid[eax=0x80000001].ecx */
- static const int CPU_FEATURE_BIT_LZCNT = 1 << 5;
-
- /* cpuid[eax=7,ecx=0].ebx */
- static const int CPU_FEATURE_BIT_BMI1 = 1 << 3;
- static const int CPU_FEATURE_BIT_AVX2 = 1 << 5;
- static const int CPU_FEATURE_BIT_BMI2 = 1 << 8;
- static const int CPU_FEATURE_BIT_AVX512F = 1 << 16; // AVX512F (foundation)
- static const int CPU_FEATURE_BIT_AVX512DQ = 1 << 17; // AVX512DQ (doubleword and quadword instructions)
- static const int CPU_FEATURE_BIT_AVX512PF = 1 << 26; // AVX512PF (prefetch gather/scatter instructions)
- static const int CPU_FEATURE_BIT_AVX512ER = 1 << 27; // AVX512ER (exponential and reciprocal instructions)
- static const int CPU_FEATURE_BIT_AVX512CD = 1 << 28; // AVX512CD (conflict detection instructions)
- static const int CPU_FEATURE_BIT_AVX512BW = 1 << 30; // AVX512BW (byte and word instructions)
- static const int CPU_FEATURE_BIT_AVX512VL = 1 << 31; // AVX512VL (vector length extensions)
- static const int CPU_FEATURE_BIT_AVX512IFMA = 1 << 21; // AVX512IFMA (integer fused multiple-add instructions)
-
- /* cpuid[eax=7,ecx=0].ecx */
- static const int CPU_FEATURE_BIT_AVX512VBMI = 1 << 1; // AVX512VBMI (vector bit manipulation instructions)
-#endif
-
-#if !defined(__ARM_NEON)
- __noinline int64_t get_xcr0()
- {
- // https://github.com/opencv/opencv/blob/master/modules/core/src/system.cpp#L466
-#if defined (__WIN32__) && defined(_XCR_XFEATURE_ENABLED_MASK)
- int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32
- xcr0 = _xgetbv(0);
- return xcr0;
-#else
- int xcr0 = 0;
- __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
- return xcr0;
-#endif
- }
-#endif
-
- int getCPUFeatures()
- {
-#if defined(__ARM_NEON)
- int cpu_features = CPU_FEATURE_NEON|CPU_FEATURE_SSE|CPU_FEATURE_SSE2;
-#if defined(NEON_AVX2_EMULATION)
- cpu_features |= CPU_FEATURE_SSE3|CPU_FEATURE_SSSE3|CPU_FEATURE_SSE42;
- cpu_features |= CPU_FEATURE_XMM_ENABLED;
- cpu_features |= CPU_FEATURE_YMM_ENABLED;
- cpu_features |= CPU_FEATURE_SSE41 | CPU_FEATURE_RDRAND | CPU_FEATURE_F16C;
- cpu_features |= CPU_FEATURE_POPCNT;
- cpu_features |= CPU_FEATURE_AVX;
- cpu_features |= CPU_FEATURE_AVX2;
- cpu_features |= CPU_FEATURE_FMA3;
- cpu_features |= CPU_FEATURE_LZCNT;
- cpu_features |= CPU_FEATURE_BMI1;
- cpu_features |= CPU_FEATURE_BMI2;
- cpu_features |= CPU_FEATURE_NEON_2X;
-
-
-
-#endif
- return cpu_features;
-
-#else
- /* cache CPU features access */
- static int cpu_features = 0;
- if (cpu_features)
- return cpu_features;
-
- /* get number of CPUID leaves */
- int cpuid_leaf0[4];
- __cpuid(cpuid_leaf0, 0x00000000);
- unsigned nIds = cpuid_leaf0[EAX];
-
- /* get number of extended CPUID leaves */
- int cpuid_leafe[4];
- __cpuid(cpuid_leafe, 0x80000000);
- unsigned nExIds = cpuid_leafe[EAX];
-
- /* get CPUID leaves for EAX = 1,7, and 0x80000001 */
- int cpuid_leaf_1[4] = { 0,0,0,0 };
- int cpuid_leaf_7[4] = { 0,0,0,0 };
- int cpuid_leaf_e1[4] = { 0,0,0,0 };
- if (nIds >= 1) __cpuid (cpuid_leaf_1,0x00000001);
-#if _WIN32
-#if _MSC_VER && (_MSC_FULL_VER < 160040219)
-#else
- if (nIds >= 7) __cpuidex(cpuid_leaf_7,0x00000007,0);
-#endif
-#else
- if (nIds >= 7) __cpuid_count(cpuid_leaf_7,0x00000007,0);
-#endif
- if (nExIds >= 0x80000001) __cpuid(cpuid_leaf_e1,0x80000001);
-
- /* detect if OS saves XMM, YMM, and ZMM states */
- bool xmm_enabled = true;
- bool ymm_enabled = false;
- bool zmm_enabled = false;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_OXSAVE) {
- int64_t xcr0 = get_xcr0();
- xmm_enabled = ((xcr0 & 0x02) == 0x02); /* checks if xmm are enabled in XCR0 */
- ymm_enabled = xmm_enabled && ((xcr0 & 0x04) == 0x04); /* checks if ymm state are enabled in XCR0 */
- zmm_enabled = ymm_enabled && ((xcr0 & 0xE0) == 0xE0); /* checks if OPMASK state, upper 256-bit of ZMM0-ZMM15 and ZMM16-ZMM31 state are enabled in XCR0 */
- }
- if (xmm_enabled) cpu_features |= CPU_FEATURE_XMM_ENABLED;
- if (ymm_enabled) cpu_features |= CPU_FEATURE_YMM_ENABLED;
- if (zmm_enabled) cpu_features |= CPU_FEATURE_ZMM_ENABLED;
-
- if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE ) cpu_features |= CPU_FEATURE_SSE;
- if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE2 ) cpu_features |= CPU_FEATURE_SSE2;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE3 ) cpu_features |= CPU_FEATURE_SSE3;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSSE3 ) cpu_features |= CPU_FEATURE_SSSE3;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_1) cpu_features |= CPU_FEATURE_SSE41;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_2) cpu_features |= CPU_FEATURE_SSE42;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_POPCNT) cpu_features |= CPU_FEATURE_POPCNT;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_AVX ) cpu_features |= CPU_FEATURE_AVX;
-
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_F16C ) cpu_features |= CPU_FEATURE_F16C;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_RDRAND) cpu_features |= CPU_FEATURE_RDRAND;
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX2 ) cpu_features |= CPU_FEATURE_AVX2;
- if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_FMA3 ) cpu_features |= CPU_FEATURE_FMA3;
- if (cpuid_leaf_e1[ECX] & CPU_FEATURE_BIT_LZCNT) cpu_features |= CPU_FEATURE_LZCNT;
- if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI1 ) cpu_features |= CPU_FEATURE_BMI1;
- if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI2 ) cpu_features |= CPU_FEATURE_BMI2;
-
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512F ) cpu_features |= CPU_FEATURE_AVX512F;
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512DQ ) cpu_features |= CPU_FEATURE_AVX512DQ;
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512PF ) cpu_features |= CPU_FEATURE_AVX512PF;
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512ER ) cpu_features |= CPU_FEATURE_AVX512ER;
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512CD ) cpu_features |= CPU_FEATURE_AVX512CD;
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512BW ) cpu_features |= CPU_FEATURE_AVX512BW;
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512IFMA) cpu_features |= CPU_FEATURE_AVX512IFMA;
- if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512VL ) cpu_features |= CPU_FEATURE_AVX512VL;
- if (cpuid_leaf_7[ECX] & CPU_FEATURE_BIT_AVX512VBMI) cpu_features |= CPU_FEATURE_AVX512VBMI;
-
- return cpu_features;
-#endif
- }
-
- std::string stringOfCPUFeatures(int features)
- {
- std::string str;
- if (features & CPU_FEATURE_XMM_ENABLED) str += "XMM ";
- if (features & CPU_FEATURE_YMM_ENABLED) str += "YMM ";
- if (features & CPU_FEATURE_ZMM_ENABLED) str += "ZMM ";
- if (features & CPU_FEATURE_SSE ) str += "SSE ";
- if (features & CPU_FEATURE_SSE2 ) str += "SSE2 ";
- if (features & CPU_FEATURE_SSE3 ) str += "SSE3 ";
- if (features & CPU_FEATURE_SSSE3 ) str += "SSSE3 ";
- if (features & CPU_FEATURE_SSE41 ) str += "SSE4.1 ";
- if (features & CPU_FEATURE_SSE42 ) str += "SSE4.2 ";
- if (features & CPU_FEATURE_POPCNT) str += "POPCNT ";
- if (features & CPU_FEATURE_AVX ) str += "AVX ";
- if (features & CPU_FEATURE_F16C ) str += "F16C ";
- if (features & CPU_FEATURE_RDRAND) str += "RDRAND ";
- if (features & CPU_FEATURE_AVX2 ) str += "AVX2 ";
- if (features & CPU_FEATURE_FMA3 ) str += "FMA3 ";
- if (features & CPU_FEATURE_LZCNT ) str += "LZCNT ";
- if (features & CPU_FEATURE_BMI1 ) str += "BMI1 ";
- if (features & CPU_FEATURE_BMI2 ) str += "BMI2 ";
- if (features & CPU_FEATURE_AVX512F) str += "AVX512F ";
- if (features & CPU_FEATURE_AVX512DQ) str += "AVX512DQ ";
- if (features & CPU_FEATURE_AVX512PF) str += "AVX512PF ";
- if (features & CPU_FEATURE_AVX512ER) str += "AVX512ER ";
- if (features & CPU_FEATURE_AVX512CD) str += "AVX512CD ";
- if (features & CPU_FEATURE_AVX512BW) str += "AVX512BW ";
- if (features & CPU_FEATURE_AVX512VL) str += "AVX512VL ";
- if (features & CPU_FEATURE_AVX512IFMA) str += "AVX512IFMA ";
- if (features & CPU_FEATURE_AVX512VBMI) str += "AVX512VBMI ";
- if (features & CPU_FEATURE_NEON) str += "NEON ";
- if (features & CPU_FEATURE_NEON_2X) str += "2xNEON ";
- return str;
- }
-
- std::string stringOfISA (int isa)
- {
- if (isa == SSE) return "SSE";
- if (isa == SSE2) return "SSE2";
- if (isa == SSE3) return "SSE3";
- if (isa == SSSE3) return "SSSE3";
- if (isa == SSE41) return "SSE4.1";
- if (isa == SSE42) return "SSE4.2";
- if (isa == AVX) return "AVX";
- if (isa == AVX2) return "AVX2";
- if (isa == AVX512KNL) return "AVX512KNL";
- if (isa == AVX512SKX) return "AVX512SKX";
- if (isa == NEON) return "NEON";
- if (isa == NEON_2X) return "2xNEON";
- return "UNKNOWN";
- }
-
- bool hasISA(int features, int isa) {
- return (features & isa) == isa;
- }
-
- std::string supportedTargetList (int features)
- {
- std::string v;
- if (hasISA(features,SSE)) v += "SSE ";
- if (hasISA(features,SSE2)) v += "SSE2 ";
- if (hasISA(features,SSE3)) v += "SSE3 ";
- if (hasISA(features,SSSE3)) v += "SSSE3 ";
- if (hasISA(features,SSE41)) v += "SSE4.1 ";
- if (hasISA(features,SSE42)) v += "SSE4.2 ";
- if (hasISA(features,AVX)) v += "AVX ";
- if (hasISA(features,AVXI)) v += "AVXI ";
- if (hasISA(features,AVX2)) v += "AVX2 ";
- if (hasISA(features,AVX512KNL)) v += "AVX512KNL ";
- if (hasISA(features,AVX512SKX)) v += "AVX512SKX ";
- if (hasISA(features,NEON)) v += "NEON ";
- if (hasISA(features,NEON_2X)) v += "2xNEON ";
- return v;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// Windows Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__WIN32__)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <psapi.h>
-
-namespace embree
-{
- std::string getExecutableFileName() {
- char filename[1024];
- if (!GetModuleFileName(nullptr, filename, sizeof(filename)))
- return std::string();
- return std::string(filename);
- }
-
- unsigned int getNumberOfLogicalThreads()
- {
- static int nThreads = -1;
- if (nThreads != -1) return nThreads;
-
- typedef WORD (WINAPI *GetActiveProcessorGroupCountFunc)();
- typedef DWORD (WINAPI *GetActiveProcessorCountFunc)(WORD);
- HMODULE hlib = LoadLibrary("Kernel32");
- GetActiveProcessorGroupCountFunc pGetActiveProcessorGroupCount = (GetActiveProcessorGroupCountFunc)GetProcAddress(hlib, "GetActiveProcessorGroupCount");
- GetActiveProcessorCountFunc pGetActiveProcessorCount = (GetActiveProcessorCountFunc) GetProcAddress(hlib, "GetActiveProcessorCount");
-
- if (pGetActiveProcessorGroupCount && pGetActiveProcessorCount)
- {
- int groups = pGetActiveProcessorGroupCount();
- int totalProcessors = 0;
- for (int i = 0; i < groups; i++)
- totalProcessors += pGetActiveProcessorCount(i);
- nThreads = totalProcessors;
- }
- else
- {
- SYSTEM_INFO sysinfo;
- GetSystemInfo(&sysinfo);
- nThreads = sysinfo.dwNumberOfProcessors;
- }
- assert(nThreads);
- return nThreads;
- }
-
- int getTerminalWidth()
- {
- HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
- if (handle == INVALID_HANDLE_VALUE) return 80;
- CONSOLE_SCREEN_BUFFER_INFO info;
- memset(&info,0,sizeof(info));
- GetConsoleScreenBufferInfo(handle, &info);
- return info.dwSize.X;
- }
-
- double getSeconds()
- {
- LARGE_INTEGER freq, val;
- QueryPerformanceFrequency(&freq);
- QueryPerformanceCounter(&val);
- return (double)val.QuadPart / (double)freq.QuadPart;
- }
-
- void sleepSeconds(double t) {
- Sleep(DWORD(1000.0*t));
- }
-
- size_t getVirtualMemoryBytes()
- {
- PROCESS_MEMORY_COUNTERS info;
- GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
- return (size_t)info.QuotaPeakPagedPoolUsage;
- }
-
- size_t getResidentMemoryBytes()
- {
- PROCESS_MEMORY_COUNTERS info;
- GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
- return (size_t)info.WorkingSetSize;
- }
-}
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Linux Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__LINUX__)
-
-#include <stdio.h>
-#include <unistd.h>
-
-namespace embree
-{
- std::string getExecutableFileName()
- {
- std::string pid = "/proc/" + toString(getpid()) + "/exe";
- char buf[4096];
- memset(buf,0,sizeof(buf));
- if (readlink(pid.c_str(), buf, sizeof(buf)-1) == -1)
- return std::string();
- return std::string(buf);
- }
-
- size_t getVirtualMemoryBytes()
- {
- size_t virt, resident, shared;
- std::ifstream buffer("/proc/self/statm");
- buffer >> virt >> resident >> shared;
- return virt*sysconf(_SC_PAGE_SIZE);
- }
-
- size_t getResidentMemoryBytes()
- {
- size_t virt, resident, shared;
- std::ifstream buffer("/proc/self/statm");
- buffer >> virt >> resident >> shared;
- return resident*sysconf(_SC_PAGE_SIZE);
- }
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// FreeBSD Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined (__FreeBSD__)
-
-#include <sys/sysctl.h>
-
-namespace embree
-{
- std::string getExecutableFileName()
- {
- const int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
- char buf[4096];
- memset(buf,0,sizeof(buf));
- size_t len = sizeof(buf)-1;
- if (sysctl(mib, 4, buf, &len, 0x0, 0) == -1)
- return std::string();
- return std::string(buf);
- }
-
- size_t getVirtualMemoryBytes() {
- return 0;
- }
-
- size_t getResidentMemoryBytes() {
- return 0;
- }
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Mac OS X Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__MACOSX__)
-
-#include <mach-o/dyld.h>
-
-namespace embree
-{
- std::string getExecutableFileName()
- {
- char buf[4096];
- uint32_t size = sizeof(buf);
- if (_NSGetExecutablePath(buf, &size) != 0)
- return std::string();
- return std::string(buf);
- }
-
- size_t getVirtualMemoryBytes() {
- return 0;
- }
-
- size_t getResidentMemoryBytes() {
- return 0;
- }
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Unix Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__UNIX__)
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <pthread.h>
-
-namespace embree
-{
- unsigned int getNumberOfLogicalThreads()
- {
- static int nThreads = -1;
- if (nThreads != -1) return nThreads;
-
-#if defined(__MACOSX__) || defined(__ANDROID__)
- nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container
- assert(nThreads);
-#else
- cpu_set_t set;
- if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)
- nThreads = CPU_COUNT(&set);
-#endif
-
- assert(nThreads);
- return nThreads;
- }
-
- int getTerminalWidth()
- {
- struct winsize info;
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &info) < 0) return 80;
- return info.ws_col;
- }
-
- double getSeconds() {
- struct timeval tp; gettimeofday(&tp,nullptr);
- return double(tp.tv_sec) + double(tp.tv_usec)/1E6;
- }
-
- void sleepSeconds(double t) {
- usleep(1000000.0*t);
- }
-}
-#endif
-
diff --git a/thirdparty/embree-aarch64/common/sys/sysinfo.h b/thirdparty/embree-aarch64/common/sys/sysinfo.h
deleted file mode 100644
index 8e313a59b3..0000000000
--- a/thirdparty/embree-aarch64/common/sys/sysinfo.h
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#define CACHELINE_SIZE 64
-
-#if !defined(PAGE_SIZE)
- #define PAGE_SIZE 4096
-#endif
-
-#define PAGE_SIZE_2M (2*1024*1024)
-#define PAGE_SIZE_4K (4*1024)
-
-#include "platform.h"
-
-/* define isa namespace and ISA bitvector */
-#if defined (__AVX512VL__)
-# define isa avx512skx
-# define ISA AVX512SKX
-# define ISA_STR "AVX512SKX"
-#elif defined (__AVX512F__)
-# define isa avx512knl
-# define ISA AVX512KNL
-# define ISA_STR "AVX512KNL"
-#elif defined (__AVX2__)
-# define isa avx2
-# define ISA AVX2
-# define ISA_STR "AVX2"
-#elif defined(__AVXI__)
-# define isa avxi
-# define ISA AVXI
-# define ISA_STR "AVXI"
-#elif defined(__AVX__)
-# define isa avx
-# define ISA AVX
-# define ISA_STR "AVX"
-#elif defined (__SSE4_2__)
-# define isa sse42
-# define ISA SSE42
-# define ISA_STR "SSE4.2"
-//#elif defined (__SSE4_1__) // we demote this to SSE2, MacOSX code compiles with SSE41 by default with XCode 11
-//# define isa sse41
-//# define ISA SSE41
-//# define ISA_STR "SSE4.1"
-//#elif defined(__SSSE3__) // we demote this to SSE2, MacOSX code compiles with SSSE3 by default with ICC
-//# define isa ssse3
-//# define ISA SSSE3
-//# define ISA_STR "SSSE3"
-//#elif defined(__SSE3__) // we demote this to SSE2, MacOSX code compiles with SSE3 by default with clang
-//# define isa sse3
-//# define ISA SSE3
-//# define ISA_STR "SSE3"
-#elif defined(__SSE2__) || defined(__SSE3__) || defined(__SSSE3__)
-# define isa sse2
-# define ISA SSE2
-# define ISA_STR "SSE2"
-#elif defined(__SSE__)
-# define isa sse
-# define ISA SSE
-# define ISA_STR "SSE"
-#elif defined(__ARM_NEON)
-// NOTE(LTE): Use sse2 for `isa` for the compatibility at the moment.
-#define isa sse2
-#define ISA NEON
-#define ISA_STR "NEON"
-#else
-#error Unknown ISA
-#endif
-
-namespace embree
-{
- enum class CPU
- {
- XEON_ICE_LAKE,
- CORE_ICE_LAKE,
- CORE_TIGER_LAKE,
- CORE_COMET_LAKE,
- CORE_CANNON_LAKE,
- CORE_KABY_LAKE,
- XEON_SKY_LAKE,
- CORE_SKY_LAKE,
- XEON_PHI_KNIGHTS_MILL,
- XEON_PHI_KNIGHTS_LANDING,
- XEON_BROADWELL,
- CORE_BROADWELL,
- XEON_HASWELL,
- CORE_HASWELL,
- XEON_IVY_BRIDGE,
- CORE_IVY_BRIDGE,
- SANDY_BRIDGE,
- NEHALEM,
- CORE2,
- CORE1,
- ARM,
- UNKNOWN,
- };
-
- /*! get the full path to the running executable */
- std::string getExecutableFileName();
-
- /*! return platform name */
- std::string getPlatformName();
-
- /*! get the full name of the compiler */
- std::string getCompilerName();
-
- /*! return the name of the CPU */
- std::string getCPUVendor();
-
- /*! get microprocessor model */
- CPU getCPUModel();
-
- /*! converts CPU model into string */
- std::string stringOfCPUModel(CPU model);
-
- /*! CPU features */
- static const int CPU_FEATURE_SSE = 1 << 0;
- static const int CPU_FEATURE_SSE2 = 1 << 1;
- static const int CPU_FEATURE_SSE3 = 1 << 2;
- static const int CPU_FEATURE_SSSE3 = 1 << 3;
- static const int CPU_FEATURE_SSE41 = 1 << 4;
- static const int CPU_FEATURE_SSE42 = 1 << 5;
- static const int CPU_FEATURE_POPCNT = 1 << 6;
- static const int CPU_FEATURE_AVX = 1 << 7;
- static const int CPU_FEATURE_F16C = 1 << 8;
- static const int CPU_FEATURE_RDRAND = 1 << 9;
- static const int CPU_FEATURE_AVX2 = 1 << 10;
- static const int CPU_FEATURE_FMA3 = 1 << 11;
- static const int CPU_FEATURE_LZCNT = 1 << 12;
- static const int CPU_FEATURE_BMI1 = 1 << 13;
- static const int CPU_FEATURE_BMI2 = 1 << 14;
- static const int CPU_FEATURE_AVX512F = 1 << 16;
- static const int CPU_FEATURE_AVX512DQ = 1 << 17;
- static const int CPU_FEATURE_AVX512PF = 1 << 18;
- static const int CPU_FEATURE_AVX512ER = 1 << 19;
- static const int CPU_FEATURE_AVX512CD = 1 << 20;
- static const int CPU_FEATURE_AVX512BW = 1 << 21;
- static const int CPU_FEATURE_AVX512VL = 1 << 22;
- static const int CPU_FEATURE_AVX512IFMA = 1 << 23;
- static const int CPU_FEATURE_AVX512VBMI = 1 << 24;
- static const int CPU_FEATURE_XMM_ENABLED = 1 << 25;
- static const int CPU_FEATURE_YMM_ENABLED = 1 << 26;
- static const int CPU_FEATURE_ZMM_ENABLED = 1 << 27;
- static const int CPU_FEATURE_NEON = 1 << 28;
- static const int CPU_FEATURE_NEON_2X = 1 << 29;
-
- /*! get CPU features */
- int getCPUFeatures();
-
- /*! convert CPU features into a string */
- std::string stringOfCPUFeatures(int features);
-
- /*! creates a string of all supported targets that are supported */
- std::string supportedTargetList (int isa);
-
- /*! ISAs */
- static const int SSE = CPU_FEATURE_SSE | CPU_FEATURE_XMM_ENABLED;
- static const int SSE2 = SSE | CPU_FEATURE_SSE2;
- static const int SSE3 = SSE2 | CPU_FEATURE_SSE3;
- static const int SSSE3 = SSE3 | CPU_FEATURE_SSSE3;
- static const int SSE41 = SSSE3 | CPU_FEATURE_SSE41;
- static const int SSE42 = SSE41 | CPU_FEATURE_SSE42 | CPU_FEATURE_POPCNT;
- static const int AVX = SSE42 | CPU_FEATURE_AVX | CPU_FEATURE_YMM_ENABLED;
- static const int AVXI = AVX | CPU_FEATURE_F16C | CPU_FEATURE_RDRAND;
- static const int AVX2 = AVXI | CPU_FEATURE_AVX2 | CPU_FEATURE_FMA3 | CPU_FEATURE_BMI1 | CPU_FEATURE_BMI2 | CPU_FEATURE_LZCNT;
- static const int AVX512KNL = AVX2 | CPU_FEATURE_AVX512F | CPU_FEATURE_AVX512PF | CPU_FEATURE_AVX512ER | CPU_FEATURE_AVX512CD | CPU_FEATURE_ZMM_ENABLED;
- static const int AVX512SKX = AVX2 | CPU_FEATURE_AVX512F | CPU_FEATURE_AVX512DQ | CPU_FEATURE_AVX512CD | CPU_FEATURE_AVX512BW | CPU_FEATURE_AVX512VL | CPU_FEATURE_ZMM_ENABLED;
- static const int NEON = CPU_FEATURE_NEON | CPU_FEATURE_SSE | CPU_FEATURE_SSE2;
- static const int NEON_2X = CPU_FEATURE_NEON_2X | AVX2;
-
- /*! converts ISA bitvector into a string */
- std::string stringOfISA(int features);
-
- /*! return the number of logical threads of the system */
- unsigned int getNumberOfLogicalThreads();
-
- /*! returns the size of the terminal window in characters */
- int getTerminalWidth();
-
- /*! returns performance counter in seconds */
- double getSeconds();
-
- /*! sleeps the specified number of seconds */
- void sleepSeconds(double t);
-
- /*! returns virtual address space occupied by process */
- size_t getVirtualMemoryBytes();
-
- /*! returns resident memory required by process */
- size_t getResidentMemoryBytes();
-}
diff --git a/thirdparty/embree-aarch64/common/sys/thread.cpp b/thirdparty/embree-aarch64/common/sys/thread.cpp
deleted file mode 100644
index f9ea5b7d96..0000000000
--- a/thirdparty/embree-aarch64/common/sys/thread.cpp
+++ /dev/null
@@ -1,429 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "thread.h"
-#include "sysinfo.h"
-#include "string.h"
-
-#include <iostream>
-#if defined(__ARM_NEON)
-#include "../math/SSE2NEON.h"
-#else
-#include <xmmintrin.h>
-#endif
-
-#if defined(PTHREADS_WIN32)
-#pragma comment (lib, "pthreadVC.lib")
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Windows Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__WIN32__)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-namespace embree
-{
- /*! set the affinity of a given thread */
- void setAffinity(HANDLE thread, ssize_t affinity)
- {
- typedef WORD (WINAPI *GetActiveProcessorGroupCountFunc)();
- typedef DWORD (WINAPI *GetActiveProcessorCountFunc)(WORD);
- typedef BOOL (WINAPI *SetThreadGroupAffinityFunc)(HANDLE, const GROUP_AFFINITY *, PGROUP_AFFINITY);
- typedef BOOL (WINAPI *SetThreadIdealProcessorExFunc)(HANDLE, PPROCESSOR_NUMBER, PPROCESSOR_NUMBER);
- HMODULE hlib = LoadLibrary("Kernel32");
- GetActiveProcessorGroupCountFunc pGetActiveProcessorGroupCount = (GetActiveProcessorGroupCountFunc)GetProcAddress(hlib, "GetActiveProcessorGroupCount");
- GetActiveProcessorCountFunc pGetActiveProcessorCount = (GetActiveProcessorCountFunc)GetProcAddress(hlib, "GetActiveProcessorCount");
- SetThreadGroupAffinityFunc pSetThreadGroupAffinity = (SetThreadGroupAffinityFunc)GetProcAddress(hlib, "SetThreadGroupAffinity");
- SetThreadIdealProcessorExFunc pSetThreadIdealProcessorEx = (SetThreadIdealProcessorExFunc)GetProcAddress(hlib, "SetThreadIdealProcessorEx");
- if (pGetActiveProcessorGroupCount && pGetActiveProcessorCount && pSetThreadGroupAffinity && pSetThreadIdealProcessorEx)
- {
- int groups = pGetActiveProcessorGroupCount();
- int totalProcessors = 0, group = 0, number = 0;
- for (int i = 0; i<groups; i++) {
- int processors = pGetActiveProcessorCount(i);
- if (totalProcessors + processors > affinity) {
- group = i;
- number = (int)affinity - totalProcessors;
- break;
- }
- totalProcessors += processors;
- }
-
- GROUP_AFFINITY groupAffinity;
- groupAffinity.Group = (WORD)group;
- groupAffinity.Mask = (KAFFINITY)(uint64_t(1) << number);
- groupAffinity.Reserved[0] = 0;
- groupAffinity.Reserved[1] = 0;
- groupAffinity.Reserved[2] = 0;
- if (!pSetThreadGroupAffinity(thread, &groupAffinity, nullptr))
- WARNING("SetThreadGroupAffinity failed"); // on purpose only a warning
-
- PROCESSOR_NUMBER processorNumber;
- processorNumber.Group = group;
- processorNumber.Number = number;
- processorNumber.Reserved = 0;
- if (!pSetThreadIdealProcessorEx(thread, &processorNumber, nullptr))
- WARNING("SetThreadIdealProcessorEx failed"); // on purpose only a warning
- }
- else
- {
- if (!SetThreadAffinityMask(thread, DWORD_PTR(uint64_t(1) << affinity)))
- WARNING("SetThreadAffinityMask failed"); // on purpose only a warning
- if (SetThreadIdealProcessor(thread, (DWORD)affinity) == (DWORD)-1)
- WARNING("SetThreadIdealProcessor failed"); // on purpose only a warning
- }
- }
-
- /*! set affinity of the calling thread */
- void setAffinity(ssize_t affinity) {
- setAffinity(GetCurrentThread(), affinity);
- }
-
- struct ThreadStartupData
- {
- public:
- ThreadStartupData (thread_func f, void* arg)
- : f(f), arg(arg) {}
- public:
- thread_func f;
- void* arg;
- };
-
- DWORD WINAPI threadStartup(LPVOID ptr)
- {
- ThreadStartupData* parg = (ThreadStartupData*) ptr;
- _mm_setcsr(_mm_getcsr() | /*FTZ:*/ (1<<15) | /*DAZ:*/ (1<<6));
- parg->f(parg->arg);
- delete parg;
- parg = nullptr;
- return 0;
- }
-
-#if !defined(PTHREADS_WIN32)
-
- /*! creates a hardware thread running on specific core */
- thread_t createThread(thread_func f, void* arg, size_t stack_size, ssize_t threadID)
- {
- HANDLE thread = CreateThread(nullptr, stack_size, threadStartup, new ThreadStartupData(f,arg), 0, nullptr);
- if (thread == nullptr) FATAL("CreateThread failed");
- if (threadID >= 0) setAffinity(thread, threadID);
- return thread_t(thread);
- }
-
- /*! the thread calling this function gets yielded */
- void yield() {
- SwitchToThread();
- }
-
- /*! waits until the given thread has terminated */
- void join(thread_t tid) {
- WaitForSingleObject(HANDLE(tid), INFINITE);
- CloseHandle(HANDLE(tid));
- }
-
- /*! creates thread local storage */
- tls_t createTls() {
- return tls_t(size_t(TlsAlloc()));
- }
-
- /*! set the thread local storage pointer */
- void setTls(tls_t tls, void* const ptr) {
- TlsSetValue(DWORD(size_t(tls)), ptr);
- }
-
- /*! return the thread local storage pointer */
- void* getTls(tls_t tls) {
- return TlsGetValue(DWORD(size_t(tls)));
- }
-
- /*! destroys thread local storage identifier */
- void destroyTls(tls_t tls) {
- TlsFree(DWORD(size_t(tls)));
- }
-#endif
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Linux Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__LINUX__)
-
-#include <fstream>
-#include <sstream>
-#include <algorithm>
-
-#if defined(__ANDROID__)
-#include <pthread.h>
-#endif
-
-namespace embree
-{
- static MutexSys mutex;
- static std::vector<size_t> threadIDs;
-
-#if !defined(__ANDROID__) // TODO(LTE): Implement for Android target
- /* changes thread ID mapping such that we first fill up all thread on one core */
- size_t mapThreadID(size_t threadID)
- {
- Lock<MutexSys> lock(mutex);
-
- if (threadIDs.size() == 0)
- {
- /* parse thread/CPU topology */
- for (size_t cpuID=0;;cpuID++)
- {
- std::fstream fs;
- std::string cpu = std::string("/sys/devices/system/cpu/cpu") + std::to_string((long long)cpuID) + std::string("/topology/thread_siblings_list");
- fs.open (cpu.c_str(), std::fstream::in);
- if (fs.fail()) break;
-
- int i;
- while (fs >> i)
- {
- if (std::none_of(threadIDs.begin(),threadIDs.end(),[&] (int id) { return id == i; }))
- threadIDs.push_back(i);
- if (fs.peek() == ',')
- fs.ignore();
- }
- fs.close();
- }
-
-#if 0
- for (size_t i=0;i<threadIDs.size();i++)
- std::cout << i << " -> " << threadIDs[i] << std::endl;
-#endif
-
- /* verify the mapping and do not use it if the mapping has errors */
- for (size_t i=0;i<threadIDs.size();i++) {
- for (size_t j=0;j<threadIDs.size();j++) {
- if (i != j && threadIDs[i] == threadIDs[j]) {
- threadIDs.clear();
- }
- }
- }
- }
-
- /* re-map threadIDs if mapping is available */
- size_t ID = threadID;
- if (threadID < threadIDs.size())
- ID = threadIDs[threadID];
-
- /* find correct thread to affinitize to */
- cpu_set_t set;
- if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)
- {
- for (int i=0, j=0; i<CPU_SETSIZE; i++)
- {
- if (!CPU_ISSET(i,&set)) continue;
-
- if (j == ID) {
- ID = i;
- break;
- }
- j++;
- }
- }
-
- return ID;
- }
-#endif
-
- /*! set affinity of the calling thread */
- void setAffinity(ssize_t affinity)
- {
-#if defined(__ANDROID__)
- // TODO(LTE): Implement
-#else
- cpu_set_t cset;
- CPU_ZERO(&cset);
- size_t threadID = mapThreadID(affinity);
- CPU_SET(threadID, &cset);
-
- pthread_setaffinity_np(pthread_self(), sizeof(cset), &cset);
-#endif
- }
-}
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// FreeBSD Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__FreeBSD__)
-
-#include <pthread_np.h>
-
-namespace embree
-{
- /*! set affinity of the calling thread */
- void setAffinity(ssize_t affinity)
- {
- cpuset_t cset;
- CPU_ZERO(&cset);
- CPU_SET(affinity, &cset);
-
- pthread_setaffinity_np(pthread_self(), sizeof(cset), &cset);
- }
-}
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// MacOSX Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__MACOSX__)
-
-#include <mach/thread_act.h>
-#include <mach/thread_policy.h>
-#include <mach/mach_init.h>
-
-namespace embree
-{
- /*! set affinity of the calling thread */
- void setAffinity(ssize_t affinity)
- {
- thread_affinity_policy ap;
- ap.affinity_tag = affinity;
- if (thread_policy_set(mach_thread_self(),THREAD_AFFINITY_POLICY,(thread_policy_t)&ap,THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS)
- WARNING("setting thread affinity failed"); // on purpose only a warning
- }
-}
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-/// Unix Platform
-////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__UNIX__) || defined(PTHREADS_WIN32)
-
-#include <pthread.h>
-#include <sched.h>
-
-#if defined(__USE_NUMA__)
-#include <numa.h>
-#endif
-
-namespace embree
-{
- struct ThreadStartupData
- {
- public:
- ThreadStartupData (thread_func f, void* arg, int affinity)
- : f(f), arg(arg), affinity(affinity) {}
- public:
- thread_func f;
- void* arg;
- ssize_t affinity;
- };
-
- static void* threadStartup(ThreadStartupData* parg)
- {
- _mm_setcsr(_mm_getcsr() | /*FTZ:*/ (1<<15) | /*DAZ:*/ (1<<6));
-
- /*! Mac OS X does not support setting affinity at thread creation time */
-#if defined(__MACOSX__)
- if (parg->affinity >= 0)
- setAffinity(parg->affinity);
-#endif
-
- parg->f(parg->arg);
- delete parg;
- parg = nullptr;
- return nullptr;
- }
-
- /*! creates a hardware thread running on specific core */
- thread_t createThread(thread_func f, void* arg, size_t stack_size, ssize_t threadID)
- {
- /* set stack size */
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- if (stack_size > 0) pthread_attr_setstacksize (&attr, stack_size);
-
- /* create thread */
- pthread_t* tid = new pthread_t;
- if (pthread_create(tid,&attr,(void*(*)(void*))threadStartup,new ThreadStartupData(f,arg,threadID)) != 0) {
- pthread_attr_destroy(&attr);
- delete tid;
- FATAL("pthread_create failed");
- }
- pthread_attr_destroy(&attr);
-
- /* set affinity */
-#if defined(__LINUX__) && !defined(__ANDROID__)
- if (threadID >= 0) {
- cpu_set_t cset;
- CPU_ZERO(&cset);
- threadID = mapThreadID(threadID);
- CPU_SET(threadID, &cset);
- pthread_setaffinity_np(*tid, sizeof(cset), &cset);
- }
-#elif defined(__FreeBSD__)
- if (threadID >= 0) {
- cpuset_t cset;
- CPU_ZERO(&cset);
- CPU_SET(threadID, &cset);
- pthread_setaffinity_np(*tid, sizeof(cset), &cset);
- }
-#endif
-
- return thread_t(tid);
- }
-
- /*! the thread calling this function gets yielded */
- void yield() {
- sched_yield();
- }
-
- /*! waits until the given thread has terminated */
- void join(thread_t tid) {
- if (pthread_join(*(pthread_t*)tid, nullptr) != 0)
- FATAL("pthread_join failed");
- delete (pthread_t*)tid;
- }
-
- /*! creates thread local storage */
- tls_t createTls()
- {
- pthread_key_t* key = new pthread_key_t;
- if (pthread_key_create(key,nullptr) != 0) {
- delete key;
- FATAL("pthread_key_create failed");
- }
-
- return tls_t(key);
- }
-
- /*! return the thread local storage pointer */
- void* getTls(tls_t tls)
- {
- assert(tls);
- return pthread_getspecific(*(pthread_key_t*)tls);
- }
-
- /*! set the thread local storage pointer */
- void setTls(tls_t tls, void* const ptr)
- {
- assert(tls);
- if (pthread_setspecific(*(pthread_key_t*)tls, ptr) != 0)
- FATAL("pthread_setspecific failed");
- }
-
- /*! destroys thread local storage identifier */
- void destroyTls(tls_t tls)
- {
- assert(tls);
- if (pthread_key_delete(*(pthread_key_t*)tls) != 0)
- FATAL("pthread_key_delete failed");
- delete (pthread_key_t*)tls;
- }
-}
-
-#endif
diff --git a/thirdparty/embree-aarch64/common/sys/thread.h b/thirdparty/embree-aarch64/common/sys/thread.h
deleted file mode 100644
index 45da6e6a70..0000000000
--- a/thirdparty/embree-aarch64/common/sys/thread.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "platform.h"
-#include "mutex.h"
-#include "alloc.h"
-#include "vector.h"
-#include <vector>
-
-namespace embree
-{
- /*! type for thread */
- typedef struct opaque_thread_t* thread_t;
-
- /*! signature of thread start function */
- typedef void (*thread_func)(void*);
-
- /*! creates a hardware thread running on specific logical thread */
- thread_t createThread(thread_func f, void* arg, size_t stack_size = 0, ssize_t threadID = -1);
-
- /*! set affinity of the calling thread */
- void setAffinity(ssize_t affinity);
-
- /*! the thread calling this function gets yielded */
- void yield();
-
- /*! waits until the given thread has terminated */
- void join(thread_t tid);
-
- /*! type for handle to thread local storage */
- typedef struct opaque_tls_t* tls_t;
-
- /*! creates thread local storage */
- tls_t createTls();
-
- /*! set the thread local storage pointer */
- void setTls(tls_t tls, void* const ptr);
-
- /*! return the thread local storage pointer */
- void* getTls(tls_t tls);
-
- /*! destroys thread local storage identifier */
- void destroyTls(tls_t tls);
-}
diff --git a/thirdparty/embree-aarch64/common/sys/vector.h b/thirdparty/embree-aarch64/common/sys/vector.h
deleted file mode 100644
index e41794de7c..0000000000
--- a/thirdparty/embree-aarch64/common/sys/vector.h
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "alloc.h"
-#include <algorithm>
-
-namespace embree
-{
- template<typename T, typename allocator>
- class vector_t
- {
- public:
- typedef T value_type;
- typedef T* iterator;
- typedef const T* const_iterator;
-
- __forceinline vector_t ()
- : size_active(0), size_alloced(0), items(nullptr) {}
-
- __forceinline explicit vector_t (size_t sz)
- : size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }
-
- template<typename M>
- __forceinline explicit vector_t (M alloc, size_t sz)
- : alloc(alloc), size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }
-
- __forceinline ~vector_t() {
- clear();
- }
-
- __forceinline vector_t (const vector_t& other)
- {
- size_active = other.size_active;
- size_alloced = other.size_alloced;
- items = alloc.allocate(size_alloced);
- for (size_t i=0; i<size_active; i++)
- ::new (&items[i]) value_type(other.items[i]);
- }
-
- __forceinline vector_t (vector_t&& other)
- : alloc(std::move(other.alloc))
- {
- size_active = other.size_active; other.size_active = 0;
- size_alloced = other.size_alloced; other.size_alloced = 0;
- items = other.items; other.items = nullptr;
- }
-
- __forceinline vector_t& operator=(const vector_t& other)
- {
- resize(other.size_active);
- for (size_t i=0; i<size_active; i++)
- items[i] = value_type(other.items[i]);
- return *this;
- }
-
- __forceinline vector_t& operator=(vector_t&& other)
- {
- clear();
- alloc = std::move(other.alloc);
- size_active = other.size_active; other.size_active = 0;
- size_alloced = other.size_alloced; other.size_alloced = 0;
- items = other.items; other.items = nullptr;
- return *this;
- }
-
- /********************** Iterators ****************************/
-
- __forceinline iterator begin() { return items; };
- __forceinline const_iterator begin() const { return items; };
-
- __forceinline iterator end () { return items+size_active; };
- __forceinline const_iterator end () const { return items+size_active; };
-
-
- /********************** Capacity ****************************/
-
- __forceinline bool empty () const { return size_active == 0; }
- __forceinline size_t size () const { return size_active; }
- __forceinline size_t capacity () const { return size_alloced; }
-
-
- __forceinline void resize(size_t new_size) {
- internal_resize(new_size,internal_grow_size(new_size));
- }
-
- __forceinline void reserve(size_t new_alloced)
- {
- /* do nothing if container already large enough */
- if (new_alloced <= size_alloced)
- return;
-
- /* resize exact otherwise */
- internal_resize(size_active,new_alloced);
- }
-
- __forceinline void shrink_to_fit() {
- internal_resize(size_active,size_active);
- }
-
- /******************** Element access **************************/
-
- __forceinline T& operator[](size_t i) { assert(i < size_active); return items[i]; }
- __forceinline const T& operator[](size_t i) const { assert(i < size_active); return items[i]; }
-
- __forceinline T& at(size_t i) { assert(i < size_active); return items[i]; }
- __forceinline const T& at(size_t i) const { assert(i < size_active); return items[i]; }
-
- __forceinline T& front() const { assert(size_active > 0); return items[0]; };
- __forceinline T& back () const { assert(size_active > 0); return items[size_active-1]; };
-
- __forceinline T* data() { return items; };
- __forceinline const T* data() const { return items; };
-
-
- /******************** Modifiers **************************/
-
- __forceinline void push_back(const T& nt)
- {
- const T v = nt; // need local copy as input reference could point to this vector
- internal_resize(size_active,internal_grow_size(size_active+1));
- ::new (&items[size_active++]) T(v);
- }
-
- __forceinline void pop_back()
- {
- assert(!empty());
- size_active--;
- alloc.destroy(&items[size_active]);
- }
-
- __forceinline void clear()
- {
- /* destroy elements */
- for (size_t i=0; i<size_active; i++)
- alloc.destroy(&items[i]);
-
- /* free memory */
- alloc.deallocate(items,size_alloced);
- items = nullptr;
- size_active = size_alloced = 0;
- }
-
- /******************** Comparisons **************************/
-
- friend bool operator== (const vector_t& a, const vector_t& b)
- {
- if (a.size() != b.size()) return false;
- for (size_t i=0; i<a.size(); i++)
- if (a[i] != b[i])
- return false;
- return true;
- }
-
- friend bool operator!= (const vector_t& a, const vector_t& b) {
- return !(a==b);
- }
-
- private:
-
- __forceinline void internal_resize_init(size_t new_active)
- {
- assert(size_active == 0);
- assert(size_alloced == 0);
- assert(items == nullptr);
- if (new_active == 0) return;
- items = alloc.allocate(new_active);
- for (size_t i=0; i<new_active; i++) ::new (&items[i]) T();
- size_active = new_active;
- size_alloced = new_active;
- }
-
- __forceinline void internal_resize(size_t new_active, size_t new_alloced)
- {
- assert(new_active <= new_alloced);
-
- /* destroy elements */
- if (new_active < size_active)
- {
- for (size_t i=new_active; i<size_active; i++)
- alloc.destroy(&items[i]);
- size_active = new_active;
- }
-
- /* only reallocate if necessary */
- if (new_alloced == size_alloced) {
- for (size_t i=size_active; i<new_active; i++) ::new (&items[i]) T;
- size_active = new_active;
- return;
- }
-
- /* reallocate and copy items */
- T* old_items = items;
- items = alloc.allocate(new_alloced);
- for (size_t i=0; i<size_active; i++) {
- ::new (&items[i]) T(std::move(old_items[i]));
- alloc.destroy(&old_items[i]);
- }
-
- for (size_t i=size_active; i<new_active; i++) {
- ::new (&items[i]) T;
- }
-
- alloc.deallocate(old_items,size_alloced);
- size_active = new_active;
- size_alloced = new_alloced;
- }
-
- __forceinline size_t internal_grow_size(size_t new_alloced)
- {
- /* do nothing if container already large enough */
- if (new_alloced <= size_alloced)
- return size_alloced;
-
- /* resize to next power of 2 otherwise */
- size_t new_size_alloced = size_alloced;
- while (new_size_alloced < new_alloced) {
- new_size_alloced = std::max(size_t(1),2*new_size_alloced);
- }
- return new_size_alloced;
- }
-
- private:
- allocator alloc;
- size_t size_active; // number of valid items
- size_t size_alloced; // number of items allocated
- T* items; // data array
- };
-
- /*! vector class that performs standard allocations */
- template<typename T>
- using vector = vector_t<T,std::allocator<T>>;
-
- /*! vector class that performs aligned allocations */
- template<typename T>
- using avector = vector_t<T,aligned_allocator<T,std::alignment_of<T>::value> >;
-
- /*! vector class that performs OS allocations */
- template<typename T>
- using ovector = vector_t<T,os_allocator<T> >;
-}
diff --git a/thirdparty/embree-aarch64/common/tasking/taskscheduler.h b/thirdparty/embree-aarch64/common/tasking/taskscheduler.h
deleted file mode 100644
index 9940e068d0..0000000000
--- a/thirdparty/embree-aarch64/common/tasking/taskscheduler.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#if defined(TASKING_INTERNAL)
-# include "taskschedulerinternal.h"
-#elif defined(TASKING_GCD) && defined(BUILD_IOS)
-# include "taskschedulergcd.h"
-#elif defined(TASKING_TBB)
-# include "taskschedulertbb.h"
-#elif defined(TASKING_PPL)
-# include "taskschedulerppl.h"
-#else
-# error "no tasking system enabled"
-#endif
-
diff --git a/thirdparty/embree-aarch64/common/tasking/taskschedulergcd.h b/thirdparty/embree-aarch64/common/tasking/taskschedulergcd.h
deleted file mode 100644
index d31f8bb478..0000000000
--- a/thirdparty/embree-aarch64/common/tasking/taskschedulergcd.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/alloc.h"
-#include "../sys/barrier.h"
-#include "../sys/thread.h"
-#include "../sys/mutex.h"
-#include "../sys/condition.h"
-#include "../sys/ref.h"
-
-#include <dispatch/dispatch.h>
-
-namespace embree
-{
- struct TaskScheduler
- {
- /*! initializes the task scheduler */
- static void create(size_t numThreads, bool set_affinity, bool start_threads);
-
- /*! destroys the task scheduler again */
- static void destroy() {}
-
- /* returns the ID of the current thread */
- static __forceinline size_t threadID()
- {
- return threadIndex();
- }
-
- /* returns the index (0..threadCount-1) of the current thread */
- static __forceinline size_t threadIndex()
- {
- currentThreadIndex = (currentThreadIndex + 1) % GCDNumThreads;
- return currentThreadIndex;
- }
-
- /* returns the total number of threads */
- static __forceinline size_t threadCount()
- {
- return GCDNumThreads;
- }
-
- private:
- static size_t GCDNumThreads;
- static size_t currentThreadIndex;
-
- };
-
-};
-
diff --git a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.cpp b/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.cpp
deleted file mode 100644
index ebf656d1a0..0000000000
--- a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "taskschedulerinternal.h"
-#include "../math/math.h"
-#include "../sys/sysinfo.h"
-#include <algorithm>
-
-namespace embree
-{
- RTC_NAMESPACE_BEGIN
-
- static MutexSys g_mutex;
- size_t TaskScheduler::g_numThreads = 0;
- __thread TaskScheduler* TaskScheduler::g_instance = nullptr;
- std::vector<Ref<TaskScheduler>> g_instance_vector;
- __thread TaskScheduler::Thread* TaskScheduler::thread_local_thread = nullptr;
- TaskScheduler::ThreadPool* TaskScheduler::threadPool = nullptr;
-
- template<typename Predicate, typename Body>
- __forceinline void TaskScheduler::steal_loop(Thread& thread, const Predicate& pred, const Body& body)
- {
- while (true)
- {
- /*! some rounds that yield */
- for (size_t i=0; i<32; i++)
- {
- /*! some spinning rounds */
- const size_t threadCount = thread.threadCount();
- for (size_t j=0; j<1024; j+=threadCount)
- {
- if (!pred()) return;
- if (thread.scheduler->steal_from_other_threads(thread)) {
- i=j=0;
- body();
- }
- }
- yield();
- }
- }
- }
-
- /*! run this task */
- void TaskScheduler::Task::run_internal (Thread& thread) // FIXME: avoid as many dll_exports as possible
- {
- /* try to run if not already stolen */
- if (try_switch_state(INITIALIZED,DONE))
- {
- Task* prevTask = thread.task;
- thread.task = this;
- // -- GODOT start --
- // try {
- // if (thread.scheduler->cancellingException == nullptr)
- closure->execute();
- // } catch (...) {
- // if (thread.scheduler->cancellingException == nullptr)
- // thread.scheduler->cancellingException = std::current_exception();
- // }
- // -- GODOT end --
- thread.task = prevTask;
- add_dependencies(-1);
- }
-
- /* steal until all dependencies have completed */
- steal_loop(thread,
- [&] () { return dependencies>0; },
- [&] () { while (thread.tasks.execute_local_internal(thread,this)); });
-
- /* now signal our parent task that we are finished */
- if (parent)
- parent->add_dependencies(-1);
- }
-
- /*! run this task */
- dll_export void TaskScheduler::Task::run (Thread& thread) {
- run_internal(thread);
- }
-
- bool TaskScheduler::TaskQueue::execute_local_internal(Thread& thread, Task* parent)
- {
- /* stop if we run out of local tasks or reach the waiting task */
- if (right == 0 || &tasks[right-1] == parent)
- return false;
-
- /* execute task */
- size_t oldRight = right;
- tasks[right-1].run_internal(thread);
- if (right != oldRight) {
- THROW_RUNTIME_ERROR("you have to wait for spawned subtasks");
- }
-
- /* pop task and closure from stack */
- right--;
- if (tasks[right].stackPtr != size_t(-1))
- stackPtr = tasks[right].stackPtr;
-
- /* also move left pointer */
- if (left >= right) left.store(right.load());
-
- return right != 0;
- }
-
- dll_export bool TaskScheduler::TaskQueue::execute_local(Thread& thread, Task* parent) {
- return execute_local_internal(thread,parent);
- }
-
- bool TaskScheduler::TaskQueue::steal(Thread& thread)
- {
- size_t l = left;
- size_t r = right;
- if (l < r)
- {
- l = left++;
- if (l >= r)
- return false;
- }
- else
- return false;
-
- if (!tasks[l].try_steal(thread.tasks.tasks[thread.tasks.right]))
- return false;
-
- thread.tasks.right++;
- return true;
- }
-
- /* we steal from the left */
- size_t TaskScheduler::TaskQueue::getTaskSizeAtLeft()
- {
- if (left >= right) return 0;
- return tasks[left].N;
- }
-
- void threadPoolFunction(std::pair<TaskScheduler::ThreadPool*,size_t>* pair)
- {
- TaskScheduler::ThreadPool* pool = pair->first;
- size_t threadIndex = pair->second;
- delete pair;
- pool->thread_loop(threadIndex);
- }
-
- TaskScheduler::ThreadPool::ThreadPool(bool set_affinity)
- : numThreads(0), numThreadsRunning(0), set_affinity(set_affinity), running(false) {}
-
- dll_export void TaskScheduler::ThreadPool::startThreads()
- {
- if (running) return;
- setNumThreads(numThreads,true);
- }
-
- void TaskScheduler::ThreadPool::setNumThreads(size_t newNumThreads, bool startThreads)
- {
- Lock<MutexSys> lock(g_mutex);
- assert(newNumThreads);
- newNumThreads = min(newNumThreads, (size_t) getNumberOfLogicalThreads());
-
- // We are observing a few % gain by increasing number threads by 2 on aarch64.
-#if defined(__aarch64__) && defined(BUILD_IOS)
- numThreads = newNumThreads*2;
-#else
- numThreads = newNumThreads;
-#endif
- numThreads = newNumThreads;
- if (!startThreads && !running) return;
- running = true;
- size_t numThreadsActive = numThreadsRunning;
-
- mutex.lock();
- numThreadsRunning = newNumThreads;
- mutex.unlock();
- condition.notify_all();
-
- /* start new threads */
- for (size_t t=numThreadsActive; t<numThreads; t++)
- {
- if (t == 0) continue;
- auto pair = new std::pair<TaskScheduler::ThreadPool*,size_t>(this,t);
- threads.push_back(createThread((thread_func)threadPoolFunction,pair,4*1024*1024,set_affinity ? t : -1));
- }
-
- /* stop some threads if we reduce the number of threads */
- for (ssize_t t=numThreadsActive-1; t>=ssize_t(numThreadsRunning); t--) {
- if (t == 0) continue;
- embree::join(threads.back());
- threads.pop_back();
- }
- }
-
- TaskScheduler::ThreadPool::~ThreadPool()
- {
- /* leave all taskschedulers */
- mutex.lock();
- numThreadsRunning = 0;
- mutex.unlock();
- condition.notify_all();
-
- /* wait for threads to terminate */
- for (size_t i=0; i<threads.size(); i++)
- embree::join(threads[i]);
- }
-
- dll_export void TaskScheduler::ThreadPool::add(const Ref<TaskScheduler>& scheduler)
- {
- mutex.lock();
- schedulers.push_back(scheduler);
- mutex.unlock();
- condition.notify_all();
- }
-
- dll_export void TaskScheduler::ThreadPool::remove(const Ref<TaskScheduler>& scheduler)
- {
- Lock<MutexSys> lock(mutex);
- for (std::list<Ref<TaskScheduler> >::iterator it = schedulers.begin(); it != schedulers.end(); it++) {
- if (scheduler == *it) {
- schedulers.erase(it);
- return;
- }
- }
- }
-
- void TaskScheduler::ThreadPool::thread_loop(size_t globalThreadIndex)
- {
- while (globalThreadIndex < numThreadsRunning)
- {
- Ref<TaskScheduler> scheduler = NULL;
- ssize_t threadIndex = -1;
- {
- Lock<MutexSys> lock(mutex);
- condition.wait(mutex, [&] () { return globalThreadIndex >= numThreadsRunning || !schedulers.empty(); });
- if (globalThreadIndex >= numThreadsRunning) break;
- scheduler = schedulers.front();
- threadIndex = scheduler->allocThreadIndex();
- }
- scheduler->thread_loop(threadIndex);
- }
- }
-
- TaskScheduler::TaskScheduler()
- : threadCounter(0), anyTasksRunning(0), hasRootTask(false)
- {
- threadLocal.resize(2*getNumberOfLogicalThreads()); // FIXME: this has to be 2x as in the compatibility join mode with rtcCommitScene the worker threads also join. When disallowing rtcCommitScene to join a build we can remove the 2x.
- for (size_t i=0; i<threadLocal.size(); i++)
- threadLocal[i].store(nullptr);
- }
-
- TaskScheduler::~TaskScheduler()
- {
- assert(threadCounter == 0);
- }
-
- dll_export size_t TaskScheduler::threadID()
- {
- Thread* thread = TaskScheduler::thread();
- if (thread) return thread->threadIndex;
- else return 0;
- }
-
- dll_export size_t TaskScheduler::threadIndex()
- {
- Thread* thread = TaskScheduler::thread();
- if (thread) return thread->threadIndex;
- else return 0;
- }
-
- dll_export size_t TaskScheduler::threadCount() {
- return threadPool->size();
- }
-
- dll_export TaskScheduler* TaskScheduler::instance()
- {
- if (g_instance == NULL) {
- Lock<MutexSys> lock(g_mutex);
- g_instance = new TaskScheduler;
- g_instance_vector.push_back(g_instance);
- }
- return g_instance;
- }
-
- void TaskScheduler::create(size_t numThreads, bool set_affinity, bool start_threads)
- {
- if (!threadPool) threadPool = new TaskScheduler::ThreadPool(set_affinity);
- threadPool->setNumThreads(numThreads,start_threads);
- }
-
- void TaskScheduler::destroy() {
- delete threadPool; threadPool = nullptr;
- }
-
- dll_export ssize_t TaskScheduler::allocThreadIndex()
- {
- size_t threadIndex = threadCounter++;
- assert(threadIndex < threadLocal.size());
- return threadIndex;
- }
-
- void TaskScheduler::join()
- {
- mutex.lock();
- size_t threadIndex = allocThreadIndex();
- condition.wait(mutex, [&] () { return hasRootTask.load(); });
- mutex.unlock();
- // -- GODOT start --
- // std::exception_ptr except = thread_loop(threadIndex);
- // if (except != nullptr) std::rethrow_exception(except);
- thread_loop(threadIndex);
- // -- GODOT end --
- }
-
- void TaskScheduler::reset() {
- hasRootTask = false;
- }
-
- void TaskScheduler::wait_for_threads(size_t threadCount)
- {
- while (threadCounter < threadCount-1)
- pause_cpu();
- }
-
- dll_export TaskScheduler::Thread* TaskScheduler::thread() {
- return thread_local_thread;
- }
-
- dll_export TaskScheduler::Thread* TaskScheduler::swapThread(Thread* thread)
- {
- Thread* old = thread_local_thread;
- thread_local_thread = thread;
- return old;
- }
-
- dll_export bool TaskScheduler::wait()
- {
- Thread* thread = TaskScheduler::thread();
- if (thread == nullptr) return true;
- while (thread->tasks.execute_local_internal(*thread,thread->task)) {};
- return thread->scheduler->cancellingException == nullptr;
- }
-
-// -- GODOT start --
-// std::exception_ptr TaskScheduler::thread_loop(size_t threadIndex)
- void TaskScheduler::thread_loop(size_t threadIndex)
-// -- GODOT end --
- {
- /* allocate thread structure */
- std::unique_ptr<Thread> mthread(new Thread(threadIndex,this)); // too large for stack allocation
- Thread& thread = *mthread;
- threadLocal[threadIndex].store(&thread);
- Thread* oldThread = swapThread(&thread);
-
- /* main thread loop */
- while (anyTasksRunning)
- {
- steal_loop(thread,
- [&] () { return anyTasksRunning > 0; },
- [&] () {
- anyTasksRunning++;
- while (thread.tasks.execute_local_internal(thread,nullptr));
- anyTasksRunning--;
- });
- }
- threadLocal[threadIndex].store(nullptr);
- swapThread(oldThread);
-
- /* remember exception to throw */
- // -- GODOT start --
- // std::exception_ptr except = nullptr;
- // if (cancellingException != nullptr) except = cancellingException;
- // -- GODOT end --
- /* wait for all threads to terminate */
- threadCounter--;
-#if defined(__WIN32__)
- size_t loopIndex = 1;
-#endif
-#define LOOP_YIELD_THRESHOLD (4096)
- while (threadCounter > 0) {
-#if defined(__WIN32__)
- if ((loopIndex % LOOP_YIELD_THRESHOLD) == 0)
- yield();
- else
- _mm_pause();
- loopIndex++;
-#else
- yield();
-#endif
- }
- // -- GODOT start --
- // return except;
- return;
- // -- GODOT end --
- }
-
- bool TaskScheduler::steal_from_other_threads(Thread& thread)
- {
- const size_t threadIndex = thread.threadIndex;
- const size_t threadCount = this->threadCounter;
-
- for (size_t i=1; i<threadCount; i++)
- {
- pause_cpu(32);
- size_t otherThreadIndex = threadIndex+i;
- if (otherThreadIndex >= threadCount) otherThreadIndex -= threadCount;
-
- Thread* othread = threadLocal[otherThreadIndex].load();
- if (!othread)
- continue;
-
- if (othread->tasks.steal(thread))
- return true;
- }
-
- return false;
- }
-
- dll_export void TaskScheduler::startThreads() {
- threadPool->startThreads();
- }
-
- dll_export void TaskScheduler::addScheduler(const Ref<TaskScheduler>& scheduler) {
- threadPool->add(scheduler);
- }
-
- dll_export void TaskScheduler::removeScheduler(const Ref<TaskScheduler>& scheduler) {
- threadPool->remove(scheduler);
- }
-
- RTC_NAMESPACE_END
-}
diff --git a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h b/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h
deleted file mode 100644
index 8bd70b2b8c..0000000000
--- a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h
+++ /dev/null
@@ -1,386 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/alloc.h"
-#include "../sys/barrier.h"
-#include "../sys/thread.h"
-#include "../sys/mutex.h"
-#include "../sys/condition.h"
-#include "../sys/ref.h"
-#include "../sys/atomic.h"
-#include "../math/range.h"
-#include "../../include/embree3/rtcore.h"
-
-#include <list>
-
-namespace embree
-{
-
- /* The tasking system exports some symbols to be used by the tutorials. Thus we
- hide is also in the API namespace when requested. */
- RTC_NAMESPACE_BEGIN
-
- struct TaskScheduler : public RefCount
- {
- ALIGNED_STRUCT_(64);
- friend class Device;
-
- static const size_t TASK_STACK_SIZE = 4*1024; //!< task structure stack
- static const size_t CLOSURE_STACK_SIZE = 512*1024; //!< stack for task closures
-
- struct Thread;
-
- /*! virtual interface for all tasks */
- struct TaskFunction {
- virtual void execute() = 0;
- };
-
- /*! builds a task interface from a closure */
- template<typename Closure>
- struct ClosureTaskFunction : public TaskFunction
- {
- Closure closure;
- __forceinline ClosureTaskFunction (const Closure& closure) : closure(closure) {}
- void execute() { closure(); };
- };
-
- struct __aligned(64) Task
- {
- /*! states a task can be in */
- enum { DONE, INITIALIZED };
-
- /*! switch from one state to another */
- __forceinline void switch_state(int from, int to)
- {
- __memory_barrier();
- MAYBE_UNUSED bool success = state.compare_exchange_strong(from,to);
- assert(success);
- }
-
- /*! try to switch from one state to another */
- __forceinline bool try_switch_state(int from, int to) {
- __memory_barrier();
- return state.compare_exchange_strong(from,to);
- }
-
- /*! increment/decrement dependency counter */
- void add_dependencies(int n) {
- dependencies+=n;
- }
-
- /*! initialize all tasks to DONE state by default */
- __forceinline Task()
- : state(DONE) {}
-
- /*! construction of new task */
- __forceinline Task (TaskFunction* closure, Task* parent, size_t stackPtr, size_t N)
- : dependencies(1), stealable(true), closure(closure), parent(parent), stackPtr(stackPtr), N(N)
- {
- if (parent) parent->add_dependencies(+1);
- switch_state(DONE,INITIALIZED);
- }
-
- /*! construction of stolen task, stealing thread will decrement initial dependency */
- __forceinline Task (TaskFunction* closure, Task* parent)
- : dependencies(1), stealable(false), closure(closure), parent(parent), stackPtr(-1), N(1)
- {
- switch_state(DONE,INITIALIZED);
- }
-
- /*! try to steal this task */
- bool try_steal(Task& child)
- {
- if (!stealable) return false;
- if (!try_switch_state(INITIALIZED,DONE)) return false;
- new (&child) Task(closure, this);
- return true;
- }
-
- /*! run this task */
- dll_export void run(Thread& thread);
-
- void run_internal(Thread& thread);
-
- public:
- std::atomic<int> state; //!< state this task is in
- std::atomic<int> dependencies; //!< dependencies to wait for
- std::atomic<bool> stealable; //!< true if task can be stolen
- TaskFunction* closure; //!< the closure to execute
- Task* parent; //!< parent task to signal when we are finished
- size_t stackPtr; //!< stack location where closure is stored
- size_t N; //!< approximative size of task
- };
-
- struct TaskQueue
- {
- TaskQueue ()
- : left(0), right(0), stackPtr(0) {}
-
- __forceinline void* alloc(size_t bytes, size_t align = 64)
- {
- size_t ofs = bytes + ((align - stackPtr) & (align-1));
- if (stackPtr + ofs > CLOSURE_STACK_SIZE)
- // -- GODOT start --
- // throw std::runtime_error("closure stack overflow");
- abort();
- // -- GODOT end --
- stackPtr += ofs;
- return &stack[stackPtr-bytes];
- }
-
- template<typename Closure>
- __forceinline void push_right(Thread& thread, const size_t size, const Closure& closure)
- {
- if (right >= TASK_STACK_SIZE)
- // -- GODOT start --
- // throw std::runtime_error("task stack overflow");
- abort();
- // -- GODOT end --
-
- /* allocate new task on right side of stack */
- size_t oldStackPtr = stackPtr;
- TaskFunction* func = new (alloc(sizeof(ClosureTaskFunction<Closure>))) ClosureTaskFunction<Closure>(closure);
- /* gcc 8 or later fails to compile without explicit .load() */
- new (&(tasks[right.load()])) Task(func,thread.task,oldStackPtr,size);
- right++;
-
- /* also move left pointer */
- if (left >= right-1) left = right-1;
- }
-
- dll_export bool execute_local(Thread& thread, Task* parent);
- bool execute_local_internal(Thread& thread, Task* parent);
- bool steal(Thread& thread);
- size_t getTaskSizeAtLeft();
-
- bool empty() { return right == 0; }
-
- public:
-
- /* task stack */
- Task tasks[TASK_STACK_SIZE];
- __aligned(64) std::atomic<size_t> left; //!< threads steal from left
- __aligned(64) std::atomic<size_t> right; //!< new tasks are added to the right
-
- /* closure stack */
- __aligned(64) char stack[CLOSURE_STACK_SIZE];
- size_t stackPtr;
- };
-
- /*! thread local structure for each thread */
- struct Thread
- {
- ALIGNED_STRUCT_(64);
-
- Thread (size_t threadIndex, const Ref<TaskScheduler>& scheduler)
- : threadIndex(threadIndex), task(nullptr), scheduler(scheduler) {}
-
- __forceinline size_t threadCount() {
- return scheduler->threadCounter;
- }
-
- size_t threadIndex; //!< ID of this thread
- TaskQueue tasks; //!< local task queue
- Task* task; //!< current active task
- Ref<TaskScheduler> scheduler; //!< pointer to task scheduler
- };
-
- /*! pool of worker threads */
- struct ThreadPool
- {
- ThreadPool (bool set_affinity);
- ~ThreadPool ();
-
- /*! starts the threads */
- dll_export void startThreads();
-
- /*! sets number of threads to use */
- void setNumThreads(size_t numThreads, bool startThreads = false);
-
- /*! adds a task scheduler object for scheduling */
- dll_export void add(const Ref<TaskScheduler>& scheduler);
-
- /*! remove the task scheduler object again */
- dll_export void remove(const Ref<TaskScheduler>& scheduler);
-
- /*! returns number of threads of the thread pool */
- size_t size() const { return numThreads; }
-
- /*! main loop for all threads */
- void thread_loop(size_t threadIndex);
-
- private:
- std::atomic<size_t> numThreads;
- std::atomic<size_t> numThreadsRunning;
- bool set_affinity;
- std::atomic<bool> running;
- std::vector<thread_t> threads;
-
- private:
- MutexSys mutex;
- ConditionSys condition;
- std::list<Ref<TaskScheduler> > schedulers;
- };
-
- TaskScheduler ();
- ~TaskScheduler ();
-
- /*! initializes the task scheduler */
- static void create(size_t numThreads, bool set_affinity, bool start_threads);
-
- /*! destroys the task scheduler again */
- static void destroy();
-
- /*! lets new worker threads join the tasking system */
- void join();
- void reset();
-
- /*! let a worker thread allocate a thread index */
- dll_export ssize_t allocThreadIndex();
-
- /*! wait for some number of threads available (threadCount includes main thread) */
- void wait_for_threads(size_t threadCount);
-
- /*! thread loop for all worker threads */
- // -- GODOT start --
- // std::exception_ptr thread_loop(size_t threadIndex);
- void thread_loop(size_t threadIndex);
- // -- GODOT end --
-
- /*! steals a task from a different thread */
- bool steal_from_other_threads(Thread& thread);
-
- template<typename Predicate, typename Body>
- static void steal_loop(Thread& thread, const Predicate& pred, const Body& body);
-
- /* spawn a new task at the top of the threads task stack */
- template<typename Closure>
- void spawn_root(const Closure& closure, size_t size = 1, bool useThreadPool = true)
- {
- if (useThreadPool) startThreads();
-
- size_t threadIndex = allocThreadIndex();
- std::unique_ptr<Thread> mthread(new Thread(threadIndex,this)); // too large for stack allocation
- Thread& thread = *mthread;
- assert(threadLocal[threadIndex].load() == nullptr);
- threadLocal[threadIndex] = &thread;
- Thread* oldThread = swapThread(&thread);
- thread.tasks.push_right(thread,size,closure);
- {
- Lock<MutexSys> lock(mutex);
- anyTasksRunning++;
- hasRootTask = true;
- condition.notify_all();
- }
-
- if (useThreadPool) addScheduler(this);
-
- while (thread.tasks.execute_local(thread,nullptr));
- anyTasksRunning--;
- if (useThreadPool) removeScheduler(this);
-
- threadLocal[threadIndex] = nullptr;
- swapThread(oldThread);
-
- /* remember exception to throw */
- std::exception_ptr except = nullptr;
- if (cancellingException != nullptr) except = cancellingException;
-
- /* wait for all threads to terminate */
- threadCounter--;
- while (threadCounter > 0) yield();
- cancellingException = nullptr;
-
- /* re-throw proper exception */
- if (except != nullptr)
- std::rethrow_exception(except);
- }
-
- /* spawn a new task at the top of the threads task stack */
- template<typename Closure>
- static __forceinline void spawn(size_t size, const Closure& closure)
- {
- Thread* thread = TaskScheduler::thread();
- if (likely(thread != nullptr)) thread->tasks.push_right(*thread,size,closure);
- else instance()->spawn_root(closure,size);
- }
-
- /* spawn a new task at the top of the threads task stack */
- template<typename Closure>
- static __forceinline void spawn(const Closure& closure) {
- spawn(1,closure);
- }
-
- /* spawn a new task set */
- template<typename Index, typename Closure>
- static void spawn(const Index begin, const Index end, const Index blockSize, const Closure& closure)
- {
- spawn(end-begin, [=]()
- {
- if (end-begin <= blockSize) {
- return closure(range<Index>(begin,end));
- }
- const Index center = (begin+end)/2;
- spawn(begin,center,blockSize,closure);
- spawn(center,end ,blockSize,closure);
- wait();
- });
- }
-
- /* work on spawned subtasks and wait until all have finished */
- dll_export static bool wait();
-
- /* returns the ID of the current thread */
- dll_export static size_t threadID();
-
- /* returns the index (0..threadCount-1) of the current thread */
- dll_export static size_t threadIndex();
-
- /* returns the total number of threads */
- dll_export static size_t threadCount();
-
- private:
-
- /* returns the thread local task list of this worker thread */
- dll_export static Thread* thread();
-
- /* sets the thread local task list of this worker thread */
- dll_export static Thread* swapThread(Thread* thread);
-
- /*! returns the taskscheduler object to be used by the master thread */
- dll_export static TaskScheduler* instance();
-
- /*! starts the threads */
- dll_export static void startThreads();
-
- /*! adds a task scheduler object for scheduling */
- dll_export static void addScheduler(const Ref<TaskScheduler>& scheduler);
-
- /*! remove the task scheduler object again */
- dll_export static void removeScheduler(const Ref<TaskScheduler>& scheduler);
-
- private:
- std::vector<atomic<Thread*>> threadLocal;
- std::atomic<size_t> threadCounter;
- std::atomic<size_t> anyTasksRunning;
- std::atomic<bool> hasRootTask;
- std::exception_ptr cancellingException;
- MutexSys mutex;
- ConditionSys condition;
-
- private:
- static size_t g_numThreads;
- static __thread TaskScheduler* g_instance;
- static __thread Thread* thread_local_thread;
- static ThreadPool* threadPool;
- };
-
- RTC_NAMESPACE_END
-
-#if defined(RTC_NAMESPACE)
- using RTC_NAMESPACE::TaskScheduler;
-#endif
-}
diff --git a/thirdparty/embree-aarch64/common/tasking/taskschedulerppl.h b/thirdparty/embree-aarch64/common/tasking/taskschedulerppl.h
deleted file mode 100644
index 776f98cdac..0000000000
--- a/thirdparty/embree-aarch64/common/tasking/taskschedulerppl.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/alloc.h"
-#include "../sys/barrier.h"
-#include "../sys/thread.h"
-#include "../sys/mutex.h"
-#include "../sys/condition.h"
-#include "../sys/ref.h"
-
-#if !defined(__WIN32__)
-#error PPL tasking system only available under windows
-#endif
-
-#include <ppl.h>
-
-namespace embree
-{
- struct TaskScheduler
- {
- /*! initializes the task scheduler */
- static void create(size_t numThreads, bool set_affinity, bool start_threads);
-
- /*! destroys the task scheduler again */
- static void destroy();
-
- /* returns the ID of the current thread */
- static __forceinline size_t threadID() {
- return GetCurrentThreadId();
- }
-
- /* returns the index (0..threadCount-1) of the current thread */
- /* FIXME: threadIndex is NOT supported by PPL! */
- static __forceinline size_t threadIndex() {
- return 0;
- }
-
- /* returns the total number of threads */
- static __forceinline size_t threadCount() {
- return GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS) + 1;
- }
- };
-};
diff --git a/thirdparty/embree-aarch64/common/tasking/taskschedulertbb.h b/thirdparty/embree-aarch64/common/tasking/taskschedulertbb.h
deleted file mode 100644
index 98dba26871..0000000000
--- a/thirdparty/embree-aarch64/common/tasking/taskschedulertbb.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/alloc.h"
-#include "../sys/barrier.h"
-#include "../sys/thread.h"
-#include "../sys/mutex.h"
-#include "../sys/condition.h"
-#include "../sys/ref.h"
-
-#if defined(__WIN32__)
-# define NOMINMAX
-#endif
-
-// We need to define these to avoid implicit linkage against
-// tbb_debug.lib under Windows. When removing these lines debug build
-// under Windows fails.
-#define __TBB_NO_IMPLICIT_LINKAGE 1
-#define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1
-#define TBB_SUPPRESS_DEPRECATED_MESSAGES 1
-#define TBB_PREVIEW_ISOLATED_TASK_GROUP 1
-#include "tbb/tbb.h"
-#include "tbb/parallel_sort.h"
-
-namespace embree
-{
- struct TaskScheduler
- {
- /*! initializes the task scheduler */
- static void create(size_t numThreads, bool set_affinity, bool start_threads);
-
- /*! destroys the task scheduler again */
- static void destroy();
-
- /* returns the ID of the current thread */
- static __forceinline size_t threadID()
- {
- return threadIndex();
- }
-
- /* returns the index (0..threadCount-1) of the current thread */
- static __forceinline size_t threadIndex()
- {
-#if TBB_INTERFACE_VERSION >= 9100
- return tbb::this_task_arena::current_thread_index();
-#elif TBB_INTERFACE_VERSION >= 9000
- return tbb::task_arena::current_thread_index();
-#else
- return 0;
-#endif
- }
-
- /* returns the total number of threads */
- static __forceinline size_t threadCount() {
-#if TBB_INTERFACE_VERSION >= 9100
- return tbb::this_task_arena::max_concurrency();
-#else
- return tbb::task_scheduler_init::default_num_threads();
-#endif
- }
-
- };
-
-};
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore.h b/thirdparty/embree-aarch64/include/embree3/rtcore.h
deleted file mode 100644
index 5830bb5880..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore_config.h"
-#include "rtcore_common.h"
-#include "rtcore_device.h"
-#include "rtcore_buffer.h"
-#include "rtcore_ray.h"
-#include "rtcore_geometry.h"
-#include "rtcore_scene.h"
-#include "rtcore_builder.h"
-#include "rtcore_quaternion.h"
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_buffer.h b/thirdparty/embree-aarch64/include/embree3/rtcore_buffer.h
deleted file mode 100644
index 400b604aa5..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_buffer.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore_device.h"
-
-RTC_NAMESPACE_BEGIN
-
-/* Types of buffers */
-enum RTCBufferType
-{
- RTC_BUFFER_TYPE_INDEX = 0,
- RTC_BUFFER_TYPE_VERTEX = 1,
- RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE = 2,
- RTC_BUFFER_TYPE_NORMAL = 3,
- RTC_BUFFER_TYPE_TANGENT = 4,
- RTC_BUFFER_TYPE_NORMAL_DERIVATIVE = 5,
-
- RTC_BUFFER_TYPE_GRID = 8,
-
- RTC_BUFFER_TYPE_FACE = 16,
- RTC_BUFFER_TYPE_LEVEL = 17,
- RTC_BUFFER_TYPE_EDGE_CREASE_INDEX = 18,
- RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT = 19,
- RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX = 20,
- RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT = 21,
- RTC_BUFFER_TYPE_HOLE = 22,
-
- RTC_BUFFER_TYPE_FLAGS = 32
-};
-
-/* Opaque buffer type */
-typedef struct RTCBufferTy* RTCBuffer;
-
-/* Creates a new buffer. */
-RTC_API RTCBuffer rtcNewBuffer(RTCDevice device, size_t byteSize);
-
-/* Creates a new shared buffer. */
-RTC_API RTCBuffer rtcNewSharedBuffer(RTCDevice device, void* ptr, size_t byteSize);
-
-/* Returns a pointer to the buffer data. */
-RTC_API void* rtcGetBufferData(RTCBuffer buffer);
-
-/* Retains the buffer (increments the reference count). */
-RTC_API void rtcRetainBuffer(RTCBuffer buffer);
-
-/* Releases the buffer (decrements the reference count). */
-RTC_API void rtcReleaseBuffer(RTCBuffer buffer);
-
-RTC_NAMESPACE_END
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_builder.h b/thirdparty/embree-aarch64/include/embree3/rtcore_builder.h
deleted file mode 100644
index d62a7f72cc..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_builder.h
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore_scene.h"
-
-RTC_NAMESPACE_BEGIN
-
-/* Opaque BVH type */
-typedef struct RTCBVHTy* RTCBVH;
-
-/* Input build primitives for the builder */
-struct RTC_ALIGN(32) RTCBuildPrimitive
-{
- float lower_x, lower_y, lower_z;
- unsigned int geomID;
- float upper_x, upper_y, upper_z;
- unsigned int primID;
-};
-
-/* Opaque thread local allocator type */
-typedef struct RTCThreadLocalAllocatorTy* RTCThreadLocalAllocator;
-
-/* Callback to create a node */
-typedef void* (*RTCCreateNodeFunction) (RTCThreadLocalAllocator allocator, unsigned int childCount, void* userPtr);
-
-/* Callback to set the pointer to all children */
-typedef void (*RTCSetNodeChildrenFunction) (void* nodePtr, void** children, unsigned int childCount, void* userPtr);
-
-/* Callback to set the bounds of all children */
-typedef void (*RTCSetNodeBoundsFunction) (void* nodePtr, const struct RTCBounds** bounds, unsigned int childCount, void* userPtr);
-
-/* Callback to create a leaf node */
-typedef void* (*RTCCreateLeafFunction) (RTCThreadLocalAllocator allocator, const struct RTCBuildPrimitive* primitives, size_t primitiveCount, void* userPtr);
-
-/* Callback to split a build primitive */
-typedef void (*RTCSplitPrimitiveFunction) (const struct RTCBuildPrimitive* primitive, unsigned int dimension, float position, struct RTCBounds* leftBounds, struct RTCBounds* rightBounds, void* userPtr);
-
-/* Build flags */
-enum RTCBuildFlags
-{
- RTC_BUILD_FLAG_NONE = 0,
- RTC_BUILD_FLAG_DYNAMIC = (1 << 0),
-};
-
-enum RTCBuildConstants
-{
- RTC_BUILD_MAX_PRIMITIVES_PER_LEAF = 32
-};
-
-/* Input for builders */
-struct RTCBuildArguments
-{
- size_t byteSize;
-
- enum RTCBuildQuality buildQuality;
- enum RTCBuildFlags buildFlags;
- unsigned int maxBranchingFactor;
- unsigned int maxDepth;
- unsigned int sahBlockSize;
- unsigned int minLeafSize;
- unsigned int maxLeafSize;
- float traversalCost;
- float intersectionCost;
-
- RTCBVH bvh;
- struct RTCBuildPrimitive* primitives;
- size_t primitiveCount;
- size_t primitiveArrayCapacity;
-
- RTCCreateNodeFunction createNode;
- RTCSetNodeChildrenFunction setNodeChildren;
- RTCSetNodeBoundsFunction setNodeBounds;
- RTCCreateLeafFunction createLeaf;
- RTCSplitPrimitiveFunction splitPrimitive;
- RTCProgressMonitorFunction buildProgress;
- void* userPtr;
-};
-
-/* Returns the default build settings. */
-RTC_FORCEINLINE struct RTCBuildArguments rtcDefaultBuildArguments()
-{
- struct RTCBuildArguments args;
- args.byteSize = sizeof(args);
- args.buildQuality = RTC_BUILD_QUALITY_MEDIUM;
- args.buildFlags = RTC_BUILD_FLAG_NONE;
- args.maxBranchingFactor = 2;
- args.maxDepth = 32;
- args.sahBlockSize = 1;
- args.minLeafSize = 1;
- args.maxLeafSize = RTC_BUILD_MAX_PRIMITIVES_PER_LEAF;
- args.traversalCost = 1.0f;
- args.intersectionCost = 1.0f;
- args.bvh = NULL;
- args.primitives = NULL;
- args.primitiveCount = 0;
- args.primitiveArrayCapacity = 0;
- args.createNode = NULL;
- args.setNodeChildren = NULL;
- args.setNodeBounds = NULL;
- args.createLeaf = NULL;
- args.splitPrimitive = NULL;
- args.buildProgress = NULL;
- args.userPtr = NULL;
- return args;
-}
-
-/* Creates a new BVH. */
-RTC_API RTCBVH rtcNewBVH(RTCDevice device);
-
-/* Builds a BVH. */
-RTC_API void* rtcBuildBVH(const struct RTCBuildArguments* args);
-
-/* Allocates memory using the thread local allocator. */
-RTC_API void* rtcThreadLocalAlloc(RTCThreadLocalAllocator allocator, size_t bytes, size_t align);
-
-/* Retains the BVH (increments reference count). */
-RTC_API void rtcRetainBVH(RTCBVH bvh);
-
-/* Releases the BVH (decrements reference count). */
-RTC_API void rtcReleaseBVH(RTCBVH bvh);
-
-RTC_NAMESPACE_END
-
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_common.h b/thirdparty/embree-aarch64/include/embree3/rtcore_common.h
deleted file mode 100644
index 890e06faa3..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_common.h
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include <stddef.h>
-#include <sys/types.h>
-#include <stdbool.h>
-
-#include "rtcore_config.h"
-
-RTC_NAMESPACE_BEGIN
-
-#if defined(_WIN32)
-#if defined(_M_X64)
-typedef long long ssize_t;
-#else
-typedef int ssize_t;
-#endif
-#endif
-
-#if defined(_WIN32) && !defined(__MINGW32__)
-# define RTC_ALIGN(...) __declspec(align(__VA_ARGS__))
-#else
-# define RTC_ALIGN(...) __attribute__((aligned(__VA_ARGS__)))
-#endif
-
-#if !defined (RTC_DEPRECATED)
-#ifdef __GNUC__
- #define RTC_DEPRECATED __attribute__((deprecated))
-#elif defined(_MSC_VER)
- #define RTC_DEPRECATED __declspec(deprecated)
-#else
- #define RTC_DEPRECATED
-#endif
-#endif
-
-#if defined(_WIN32)
-# define RTC_FORCEINLINE __forceinline
-#else
-# define RTC_FORCEINLINE inline __attribute__((always_inline))
-#endif
-
-/* Invalid geometry ID */
-#define RTC_INVALID_GEOMETRY_ID ((unsigned int)-1)
-
-/* Maximum number of time steps */
-#define RTC_MAX_TIME_STEP_COUNT 129
-
-/* Formats of buffers and other data structures */
-enum RTCFormat
-{
- RTC_FORMAT_UNDEFINED = 0,
-
- /* 8-bit unsigned integer */
- RTC_FORMAT_UCHAR = 0x1001,
- RTC_FORMAT_UCHAR2,
- RTC_FORMAT_UCHAR3,
- RTC_FORMAT_UCHAR4,
-
- /* 8-bit signed integer */
- RTC_FORMAT_CHAR = 0x2001,
- RTC_FORMAT_CHAR2,
- RTC_FORMAT_CHAR3,
- RTC_FORMAT_CHAR4,
-
- /* 16-bit unsigned integer */
- RTC_FORMAT_USHORT = 0x3001,
- RTC_FORMAT_USHORT2,
- RTC_FORMAT_USHORT3,
- RTC_FORMAT_USHORT4,
-
- /* 16-bit signed integer */
- RTC_FORMAT_SHORT = 0x4001,
- RTC_FORMAT_SHORT2,
- RTC_FORMAT_SHORT3,
- RTC_FORMAT_SHORT4,
-
- /* 32-bit unsigned integer */
- RTC_FORMAT_UINT = 0x5001,
- RTC_FORMAT_UINT2,
- RTC_FORMAT_UINT3,
- RTC_FORMAT_UINT4,
-
- /* 32-bit signed integer */
- RTC_FORMAT_INT = 0x6001,
- RTC_FORMAT_INT2,
- RTC_FORMAT_INT3,
- RTC_FORMAT_INT4,
-
- /* 64-bit unsigned integer */
- RTC_FORMAT_ULLONG = 0x7001,
- RTC_FORMAT_ULLONG2,
- RTC_FORMAT_ULLONG3,
- RTC_FORMAT_ULLONG4,
-
- /* 64-bit signed integer */
- RTC_FORMAT_LLONG = 0x8001,
- RTC_FORMAT_LLONG2,
- RTC_FORMAT_LLONG3,
- RTC_FORMAT_LLONG4,
-
- /* 32-bit float */
- RTC_FORMAT_FLOAT = 0x9001,
- RTC_FORMAT_FLOAT2,
- RTC_FORMAT_FLOAT3,
- RTC_FORMAT_FLOAT4,
- RTC_FORMAT_FLOAT5,
- RTC_FORMAT_FLOAT6,
- RTC_FORMAT_FLOAT7,
- RTC_FORMAT_FLOAT8,
- RTC_FORMAT_FLOAT9,
- RTC_FORMAT_FLOAT10,
- RTC_FORMAT_FLOAT11,
- RTC_FORMAT_FLOAT12,
- RTC_FORMAT_FLOAT13,
- RTC_FORMAT_FLOAT14,
- RTC_FORMAT_FLOAT15,
- RTC_FORMAT_FLOAT16,
-
- /* 32-bit float matrix (row-major order) */
- RTC_FORMAT_FLOAT2X2_ROW_MAJOR = 0x9122,
- RTC_FORMAT_FLOAT2X3_ROW_MAJOR = 0x9123,
- RTC_FORMAT_FLOAT2X4_ROW_MAJOR = 0x9124,
- RTC_FORMAT_FLOAT3X2_ROW_MAJOR = 0x9132,
- RTC_FORMAT_FLOAT3X3_ROW_MAJOR = 0x9133,
- RTC_FORMAT_FLOAT3X4_ROW_MAJOR = 0x9134,
- RTC_FORMAT_FLOAT4X2_ROW_MAJOR = 0x9142,
- RTC_FORMAT_FLOAT4X3_ROW_MAJOR = 0x9143,
- RTC_FORMAT_FLOAT4X4_ROW_MAJOR = 0x9144,
-
- /* 32-bit float matrix (column-major order) */
- RTC_FORMAT_FLOAT2X2_COLUMN_MAJOR = 0x9222,
- RTC_FORMAT_FLOAT2X3_COLUMN_MAJOR = 0x9223,
- RTC_FORMAT_FLOAT2X4_COLUMN_MAJOR = 0x9224,
- RTC_FORMAT_FLOAT3X2_COLUMN_MAJOR = 0x9232,
- RTC_FORMAT_FLOAT3X3_COLUMN_MAJOR = 0x9233,
- RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR = 0x9234,
- RTC_FORMAT_FLOAT4X2_COLUMN_MAJOR = 0x9242,
- RTC_FORMAT_FLOAT4X3_COLUMN_MAJOR = 0x9243,
- RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR = 0x9244,
-
- /* special 12-byte format for grids */
- RTC_FORMAT_GRID = 0xA001
-};
-
-/* Build quality levels */
-enum RTCBuildQuality
-{
- RTC_BUILD_QUALITY_LOW = 0,
- RTC_BUILD_QUALITY_MEDIUM = 1,
- RTC_BUILD_QUALITY_HIGH = 2,
- RTC_BUILD_QUALITY_REFIT = 3,
-};
-
-/* Axis-aligned bounding box representation */
-struct RTC_ALIGN(16) RTCBounds
-{
- float lower_x, lower_y, lower_z, align0;
- float upper_x, upper_y, upper_z, align1;
-};
-
-/* Linear axis-aligned bounding box representation */
-struct RTC_ALIGN(16) RTCLinearBounds
-{
- struct RTCBounds bounds0;
- struct RTCBounds bounds1;
-};
-
-/* Intersection context flags */
-enum RTCIntersectContextFlags
-{
- RTC_INTERSECT_CONTEXT_FLAG_NONE = 0,
- RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT = (0 << 0), // optimize for incoherent rays
- RTC_INTERSECT_CONTEXT_FLAG_COHERENT = (1 << 0) // optimize for coherent rays
-};
-
-/* Arguments for RTCFilterFunctionN */
-struct RTCFilterFunctionNArguments
-{
- int* valid;
- void* geometryUserPtr;
- struct RTCIntersectContext* context;
- struct RTCRayN* ray;
- struct RTCHitN* hit;
- unsigned int N;
-};
-
-/* Filter callback function */
-typedef void (*RTCFilterFunctionN)(const struct RTCFilterFunctionNArguments* args);
-
-/* Intersection context passed to intersect/occluded calls */
-struct RTCIntersectContext
-{
- enum RTCIntersectContextFlags flags; // intersection flags
- RTCFilterFunctionN filter; // filter function to execute
-
-#if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
- unsigned int instStackSize; // Number of instances currently on the stack.
-#endif
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // The current stack of instance ids.
-
-#if RTC_MIN_WIDTH
- float minWidthDistanceFactor; // curve radius is set to this factor times distance to ray origin
-#endif
-};
-
-/* Initializes an intersection context. */
-RTC_FORCEINLINE void rtcInitIntersectContext(struct RTCIntersectContext* context)
-{
- unsigned l = 0;
- context->flags = RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT;
- context->filter = NULL;
-
-#if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
- context->instStackSize = 0;
-#endif
- for (; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- context->instID[l] = RTC_INVALID_GEOMETRY_ID;
-
-#if RTC_MIN_WIDTH
- context->minWidthDistanceFactor = 0.0f;
-#endif
-}
-
-/* Point query structure for closest point query */
-struct RTC_ALIGN(16) RTCPointQuery
-{
- float x; // x coordinate of the query point
- float y; // y coordinate of the query point
- float z; // z coordinate of the query point
- float time; // time of the point query
- float radius; // radius of the point query
-};
-
-/* Structure of a packet of 4 query points */
-struct RTC_ALIGN(16) RTCPointQuery4
-{
- float x[4]; // x coordinate of the query point
- float y[4]; // y coordinate of the query point
- float z[4]; // z coordinate of the query point
- float time[4]; // time of the point query
- float radius[4]; // radius of the point query
-};
-
-/* Structure of a packet of 8 query points */
-struct RTC_ALIGN(32) RTCPointQuery8
-{
- float x[8]; // x coordinate of the query point
- float y[8]; // y coordinate of the query point
- float z[8]; // z coordinate of the query point
- float time[8]; // time of the point query
- float radius[8]; // radius ofr the point query
-};
-
-/* Structure of a packet of 16 query points */
-struct RTC_ALIGN(64) RTCPointQuery16
-{
- float x[16]; // x coordinate of the query point
- float y[16]; // y coordinate of the query point
- float z[16]; // z coordinate of the query point
- float time[16]; // time of the point quey
- float radius[16]; // radius of the point query
-};
-
-struct RTCPointQueryN;
-
-struct RTC_ALIGN(16) RTCPointQueryContext
-{
- // accumulated 4x4 column major matrices from world space to instance space.
- // undefined if size == 0.
- float world2inst[RTC_MAX_INSTANCE_LEVEL_COUNT][16];
-
- // accumulated 4x4 column major matrices from instance space to world space.
- // undefined if size == 0.
- float inst2world[RTC_MAX_INSTANCE_LEVEL_COUNT][16];
-
- // instance ids.
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT];
-
- // number of instances currently on the stack.
- unsigned int instStackSize;
-};
-
-/* Initializes an intersection context. */
-RTC_FORCEINLINE void rtcInitPointQueryContext(struct RTCPointQueryContext* context)
-{
- context->instStackSize = 0;
- context->instID[0] = RTC_INVALID_GEOMETRY_ID;
-}
-
-struct RTC_ALIGN(16) RTCPointQueryFunctionArguments
-{
- // The (world space) query object that was passed as an argument of rtcPointQuery. The
- // radius of the query can be decreased inside the callback to shrink the
- // search domain. Increasing the radius or modifying the time or position of
- // the query results in undefined behaviour.
- struct RTCPointQuery* query;
-
- // Used for user input/output data. Will not be read or modified internally.
- void* userPtr;
-
- // primitive and geometry ID of primitive
- unsigned int primID;
- unsigned int geomID;
-
- // the context with transformation and instance ID stack
- struct RTCPointQueryContext* context;
-
- // If the current instance transform M (= context->world2inst[context->instStackSize])
- // is a similarity matrix, i.e there is a constant factor similarityScale such that,
- // for all x,y: dist(Mx, My) = similarityScale * dist(x, y),
- // The similarity scale is 0, if the current instance transform is not a
- // similarity transform and vice versa. The similarity scale allows to compute
- // distance information in instance space and scale the distances into world
- // space by dividing with the similarity scale, for example, to update the
- // query radius. If the current instance transform is not a similarity
- // transform (similarityScale = 0), the distance computation has to be
- // performed in world space to ensure correctness. if there is no instance
- // transform (context->instStackSize == 0), the similarity scale is 1.
- float similarityScale;
-};
-
-typedef bool (*RTCPointQueryFunction)(struct RTCPointQueryFunctionArguments* args);
-
-RTC_NAMESPACE_END
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_config.h b/thirdparty/embree-aarch64/include/embree3/rtcore_config.h
deleted file mode 100644
index 337d4e9487..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_config.h
+++ /dev/null
@@ -1,57 +0,0 @@
-
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#define RTC_VERSION_MAJOR 3
-#define RTC_VERSION_MINOR 12
-#define RTC_VERSION_PATCH 1
-#define RTC_VERSION 31201
-#define RTC_VERSION_STRING "3.12.1"
-
-#define RTC_MAX_INSTANCE_LEVEL_COUNT 1
-
-#define EMBREE_MIN_WIDTH 0
-#define RTC_MIN_WIDTH EMBREE_MIN_WIDTH
-
-#define EMBREE_STATIC_LIB
-/* #undef EMBREE_API_NAMESPACE */
-
-#if defined(EMBREE_API_NAMESPACE)
-# define RTC_NAMESPACE
-# define RTC_NAMESPACE_BEGIN namespace {
-# define RTC_NAMESPACE_END }
-# define RTC_NAMESPACE_USE using namespace ;
-# define RTC_API_EXTERN_C
-# undef EMBREE_API_NAMESPACE
-#else
-# define RTC_NAMESPACE_BEGIN
-# define RTC_NAMESPACE_END
-# define RTC_NAMESPACE_USE
-# if defined(__cplusplus)
-# define RTC_API_EXTERN_C extern "C"
-# else
-# define RTC_API_EXTERN_C
-# endif
-#endif
-
-#if defined(ISPC)
-# define RTC_API_IMPORT extern "C" unmasked
-# define RTC_API_EXPORT extern "C" unmasked
-#elif defined(EMBREE_STATIC_LIB)
-# define RTC_API_IMPORT RTC_API_EXTERN_C
-# define RTC_API_EXPORT RTC_API_EXTERN_C
-#elif defined(_WIN32)
-# define RTC_API_IMPORT RTC_API_EXTERN_C __declspec(dllimport)
-# define RTC_API_EXPORT RTC_API_EXTERN_C __declspec(dllexport)
-#else
-# define RTC_API_IMPORT RTC_API_EXTERN_C
-# define RTC_API_EXPORT RTC_API_EXTERN_C __attribute__ ((visibility ("default")))
-#endif
-
-#if defined(RTC_EXPORT_API)
-# define RTC_API RTC_API_EXPORT
-#else
-# define RTC_API RTC_API_IMPORT
-#endif
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_device.h b/thirdparty/embree-aarch64/include/embree3/rtcore_device.h
deleted file mode 100644
index 594e2b755d..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_device.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore_common.h"
-
-RTC_NAMESPACE_BEGIN
-
-/* Opaque device type */
-typedef struct RTCDeviceTy* RTCDevice;
-
-/* Creates a new Embree device. */
-RTC_API RTCDevice rtcNewDevice(const char* config);
-
-/* Retains the Embree device (increments the reference count). */
-RTC_API void rtcRetainDevice(RTCDevice device);
-
-/* Releases an Embree device (decrements the reference count). */
-RTC_API void rtcReleaseDevice(RTCDevice device);
-
-/* Device properties */
-enum RTCDeviceProperty
-{
- RTC_DEVICE_PROPERTY_VERSION = 0,
- RTC_DEVICE_PROPERTY_VERSION_MAJOR = 1,
- RTC_DEVICE_PROPERTY_VERSION_MINOR = 2,
- RTC_DEVICE_PROPERTY_VERSION_PATCH = 3,
-
- RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED = 32,
- RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED = 33,
- RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED = 34,
- RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED = 35,
-
- RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED = 63,
- RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED = 64,
- RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED = 65,
- RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED = 66,
- RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED = 67,
- RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED = 68,
-
- RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED = 96,
- RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED = 97,
- RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED = 98,
- RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED = 99,
- RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED = 100,
- RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED = 101,
-
- RTC_DEVICE_PROPERTY_TASKING_SYSTEM = 128,
- RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED = 129,
- RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED = 130
-};
-
-/* Gets a device property. */
-RTC_API ssize_t rtcGetDeviceProperty(RTCDevice device, enum RTCDeviceProperty prop);
-
-/* Sets a device property. */
-RTC_API void rtcSetDeviceProperty(RTCDevice device, const enum RTCDeviceProperty prop, ssize_t value);
-
-/* Error codes */
-enum RTCError
-{
- RTC_ERROR_NONE = 0,
- RTC_ERROR_UNKNOWN = 1,
- RTC_ERROR_INVALID_ARGUMENT = 2,
- RTC_ERROR_INVALID_OPERATION = 3,
- RTC_ERROR_OUT_OF_MEMORY = 4,
- RTC_ERROR_UNSUPPORTED_CPU = 5,
- RTC_ERROR_CANCELLED = 6
-};
-
-/* Returns the error code. */
-RTC_API enum RTCError rtcGetDeviceError(RTCDevice device);
-
-/* Error callback function */
-typedef void (*RTCErrorFunction)(void* userPtr, enum RTCError code, const char* str);
-
-/* Sets the error callback function. */
-RTC_API void rtcSetDeviceErrorFunction(RTCDevice device, RTCErrorFunction error, void* userPtr);
-
-/* Memory monitor callback function */
-typedef bool (*RTCMemoryMonitorFunction)(void* ptr, ssize_t bytes, bool post);
-
-/* Sets the memory monitor callback function. */
-RTC_API void rtcSetDeviceMemoryMonitorFunction(RTCDevice device, RTCMemoryMonitorFunction memoryMonitor, void* userPtr);
-
-RTC_NAMESPACE_END
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_geometry.h b/thirdparty/embree-aarch64/include/embree3/rtcore_geometry.h
deleted file mode 100644
index c70f1b0e5c..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_geometry.h
+++ /dev/null
@@ -1,383 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore_buffer.h"
-#include "rtcore_quaternion.h"
-
-RTC_NAMESPACE_BEGIN
-
-/* Opaque scene type */
-typedef struct RTCSceneTy* RTCScene;
-
-/* Opaque geometry type */
-typedef struct RTCGeometryTy* RTCGeometry;
-
-/* Types of geometries */
-enum RTCGeometryType
-{
- RTC_GEOMETRY_TYPE_TRIANGLE = 0, // triangle mesh
- RTC_GEOMETRY_TYPE_QUAD = 1, // quad (triangle pair) mesh
- RTC_GEOMETRY_TYPE_GRID = 2, // grid mesh
-
- RTC_GEOMETRY_TYPE_SUBDIVISION = 8, // Catmull-Clark subdivision surface
-
- RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE = 15, // Cone linear curves - discontinuous at edge boundaries
- RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE = 16, // Round (rounded cone like) linear curves
- RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE = 17, // flat (ribbon-like) linear curves
-
- RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE = 24, // round (tube-like) Bezier curves
- RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE = 25, // flat (ribbon-like) Bezier curves
- RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE = 26, // flat normal-oriented Bezier curves
-
- RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE = 32, // round (tube-like) B-spline curves
- RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE = 33, // flat (ribbon-like) B-spline curves
- RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE = 34, // flat normal-oriented B-spline curves
-
- RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE = 40, // round (tube-like) Hermite curves
- RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE = 41, // flat (ribbon-like) Hermite curves
- RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE = 42, // flat normal-oriented Hermite curves
-
- RTC_GEOMETRY_TYPE_SPHERE_POINT = 50,
- RTC_GEOMETRY_TYPE_DISC_POINT = 51,
- RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT = 52,
-
- RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE = 58, // round (tube-like) Catmull-Rom curves
- RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE = 59, // flat (ribbon-like) Catmull-Rom curves
- RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE = 60, // flat normal-oriented Catmull-Rom curves
-
- RTC_GEOMETRY_TYPE_USER = 120, // user-defined geometry
- RTC_GEOMETRY_TYPE_INSTANCE = 121 // scene instance
-};
-
-/* Interpolation modes for subdivision surfaces */
-enum RTCSubdivisionMode
-{
- RTC_SUBDIVISION_MODE_NO_BOUNDARY = 0,
- RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY = 1,
- RTC_SUBDIVISION_MODE_PIN_CORNERS = 2,
- RTC_SUBDIVISION_MODE_PIN_BOUNDARY = 3,
- RTC_SUBDIVISION_MODE_PIN_ALL = 4,
-};
-
-/* Curve segment flags */
-enum RTCCurveFlags
-{
- RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0), // left segments exists
- RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1) // right segment exists
-};
-
-/* Arguments for RTCBoundsFunction */
-struct RTCBoundsFunctionArguments
-{
- void* geometryUserPtr;
- unsigned int primID;
- unsigned int timeStep;
- struct RTCBounds* bounds_o;
-};
-
-/* Bounding callback function */
-typedef void (*RTCBoundsFunction)(const struct RTCBoundsFunctionArguments* args);
-
-/* Arguments for RTCIntersectFunctionN */
-struct RTCIntersectFunctionNArguments
-{
- int* valid;
- void* geometryUserPtr;
- unsigned int primID;
- struct RTCIntersectContext* context;
- struct RTCRayHitN* rayhit;
- unsigned int N;
- unsigned int geomID;
-};
-
-/* Intersection callback function */
-typedef void (*RTCIntersectFunctionN)(const struct RTCIntersectFunctionNArguments* args);
-
-/* Arguments for RTCOccludedFunctionN */
-struct RTCOccludedFunctionNArguments
-{
- int* valid;
- void* geometryUserPtr;
- unsigned int primID;
- struct RTCIntersectContext* context;
- struct RTCRayN* ray;
- unsigned int N;
- unsigned int geomID;
-};
-
-/* Occlusion callback function */
-typedef void (*RTCOccludedFunctionN)(const struct RTCOccludedFunctionNArguments* args);
-
-/* Arguments for RTCDisplacementFunctionN */
-struct RTCDisplacementFunctionNArguments
-{
- void* geometryUserPtr;
- RTCGeometry geometry;
- unsigned int primID;
- unsigned int timeStep;
- const float* u;
- const float* v;
- const float* Ng_x;
- const float* Ng_y;
- const float* Ng_z;
- float* P_x;
- float* P_y;
- float* P_z;
- unsigned int N;
-};
-
-/* Displacement mapping callback function */
-typedef void (*RTCDisplacementFunctionN)(const struct RTCDisplacementFunctionNArguments* args);
-
-/* Creates a new geometry of specified type. */
-RTC_API RTCGeometry rtcNewGeometry(RTCDevice device, enum RTCGeometryType type);
-
-/* Retains the geometry (increments the reference count). */
-RTC_API void rtcRetainGeometry(RTCGeometry geometry);
-
-/* Releases the geometry (decrements the reference count) */
-RTC_API void rtcReleaseGeometry(RTCGeometry geometry);
-
-/* Commits the geometry. */
-RTC_API void rtcCommitGeometry(RTCGeometry geometry);
-
-
-/* Enables the geometry. */
-RTC_API void rtcEnableGeometry(RTCGeometry geometry);
-
-/* Disables the geometry. */
-RTC_API void rtcDisableGeometry(RTCGeometry geometry);
-
-
-/* Sets the number of motion blur time steps of the geometry. */
-RTC_API void rtcSetGeometryTimeStepCount(RTCGeometry geometry, unsigned int timeStepCount);
-
-/* Sets the motion blur time range of the geometry. */
-RTC_API void rtcSetGeometryTimeRange(RTCGeometry geometry, float startTime, float endTime);
-
-/* Sets the number of vertex attributes of the geometry. */
-RTC_API void rtcSetGeometryVertexAttributeCount(RTCGeometry geometry, unsigned int vertexAttributeCount);
-
-/* Sets the ray mask of the geometry. */
-RTC_API void rtcSetGeometryMask(RTCGeometry geometry, unsigned int mask);
-
-/* Sets the build quality of the geometry. */
-RTC_API void rtcSetGeometryBuildQuality(RTCGeometry geometry, enum RTCBuildQuality quality);
-
-/* Sets the maximal curve or point radius scale allowed by min-width feature. */
-RTC_API void rtcSetGeometryMaxRadiusScale(RTCGeometry geometry, float maxRadiusScale);
-
-
-/* Sets a geometry buffer. */
-RTC_API void rtcSetGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot, enum RTCFormat format, RTCBuffer buffer, size_t byteOffset, size_t byteStride, size_t itemCount);
-
-/* Sets a shared geometry buffer. */
-RTC_API void rtcSetSharedGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot, enum RTCFormat format, const void* ptr, size_t byteOffset, size_t byteStride, size_t itemCount);
-
-/* Creates and sets a new geometry buffer. */
-RTC_API void* rtcSetNewGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot, enum RTCFormat format, size_t byteStride, size_t itemCount);
-
-/* Returns the pointer to the data of a buffer. */
-RTC_API void* rtcGetGeometryBufferData(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot);
-
-/* Updates a geometry buffer. */
-RTC_API void rtcUpdateGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot);
-
-
-/* Sets the intersection filter callback function of the geometry. */
-RTC_API void rtcSetGeometryIntersectFilterFunction(RTCGeometry geometry, RTCFilterFunctionN filter);
-
-/* Sets the occlusion filter callback function of the geometry. */
-RTC_API void rtcSetGeometryOccludedFilterFunction(RTCGeometry geometry, RTCFilterFunctionN filter);
-
-/* Sets the user-defined data pointer of the geometry. */
-RTC_API void rtcSetGeometryUserData(RTCGeometry geometry, void* ptr);
-
-/* Gets the user-defined data pointer of the geometry. */
-RTC_API void* rtcGetGeometryUserData(RTCGeometry geometry);
-
-/* Set the point query callback function of a geometry. */
-RTC_API void rtcSetGeometryPointQueryFunction(RTCGeometry geometry, RTCPointQueryFunction pointQuery);
-
-/* Sets the number of primitives of a user geometry. */
-RTC_API void rtcSetGeometryUserPrimitiveCount(RTCGeometry geometry, unsigned int userPrimitiveCount);
-
-/* Sets the bounding callback function to calculate bounding boxes for user primitives. */
-RTC_API void rtcSetGeometryBoundsFunction(RTCGeometry geometry, RTCBoundsFunction bounds, void* userPtr);
-
-/* Set the intersect callback function of a user geometry. */
-RTC_API void rtcSetGeometryIntersectFunction(RTCGeometry geometry, RTCIntersectFunctionN intersect);
-
-/* Set the occlusion callback function of a user geometry. */
-RTC_API void rtcSetGeometryOccludedFunction(RTCGeometry geometry, RTCOccludedFunctionN occluded);
-
-/* Invokes the intersection filter from the intersection callback function. */
-RTC_API void rtcFilterIntersection(const struct RTCIntersectFunctionNArguments* args, const struct RTCFilterFunctionNArguments* filterArgs);
-
-/* Invokes the occlusion filter from the occlusion callback function. */
-RTC_API void rtcFilterOcclusion(const struct RTCOccludedFunctionNArguments* args, const struct RTCFilterFunctionNArguments* filterArgs);
-
-
-/* Sets the instanced scene of an instance geometry. */
-RTC_API void rtcSetGeometryInstancedScene(RTCGeometry geometry, RTCScene scene);
-
-/* Sets the transformation of an instance for the specified time step. */
-RTC_API void rtcSetGeometryTransform(RTCGeometry geometry, unsigned int timeStep, enum RTCFormat format, const void* xfm);
-
-/* Sets the transformation quaternion of an instance for the specified time step. */
-RTC_API void rtcSetGeometryTransformQuaternion(RTCGeometry geometry, unsigned int timeStep, const struct RTCQuaternionDecomposition* qd);
-
-/* Returns the interpolated transformation of an instance for the specified time. */
-RTC_API void rtcGetGeometryTransform(RTCGeometry geometry, float time, enum RTCFormat format, void* xfm);
-
-
-/* Sets the uniform tessellation rate of the geometry. */
-RTC_API void rtcSetGeometryTessellationRate(RTCGeometry geometry, float tessellationRate);
-
-/* Sets the number of topologies of a subdivision surface. */
-RTC_API void rtcSetGeometryTopologyCount(RTCGeometry geometry, unsigned int topologyCount);
-
-/* Sets the subdivision interpolation mode. */
-RTC_API void rtcSetGeometrySubdivisionMode(RTCGeometry geometry, unsigned int topologyID, enum RTCSubdivisionMode mode);
-
-/* Binds a vertex attribute to a topology of the geometry. */
-RTC_API void rtcSetGeometryVertexAttributeTopology(RTCGeometry geometry, unsigned int vertexAttributeID, unsigned int topologyID);
-
-/* Sets the displacement callback function of a subdivision surface. */
-RTC_API void rtcSetGeometryDisplacementFunction(RTCGeometry geometry, RTCDisplacementFunctionN displacement);
-
-/* Returns the first half edge of a face. */
-RTC_API unsigned int rtcGetGeometryFirstHalfEdge(RTCGeometry geometry, unsigned int faceID);
-
-/* Returns the face the half edge belongs to. */
-RTC_API unsigned int rtcGetGeometryFace(RTCGeometry geometry, unsigned int edgeID);
-
-/* Returns next half edge. */
-RTC_API unsigned int rtcGetGeometryNextHalfEdge(RTCGeometry geometry, unsigned int edgeID);
-
-/* Returns previous half edge. */
-RTC_API unsigned int rtcGetGeometryPreviousHalfEdge(RTCGeometry geometry, unsigned int edgeID);
-
-/* Returns opposite half edge. */
-RTC_API unsigned int rtcGetGeometryOppositeHalfEdge(RTCGeometry geometry, unsigned int topologyID, unsigned int edgeID);
-
-
-/* Arguments for rtcInterpolate */
-struct RTCInterpolateArguments
-{
- RTCGeometry geometry;
- unsigned int primID;
- float u;
- float v;
- enum RTCBufferType bufferType;
- unsigned int bufferSlot;
- float* P;
- float* dPdu;
- float* dPdv;
- float* ddPdudu;
- float* ddPdvdv;
- float* ddPdudv;
- unsigned int valueCount;
-};
-
-/* Interpolates vertex data to some u/v location and optionally calculates all derivatives. */
-RTC_API void rtcInterpolate(const struct RTCInterpolateArguments* args);
-
-/* Interpolates vertex data to some u/v location. */
-RTC_FORCEINLINE void rtcInterpolate0(RTCGeometry geometry, unsigned int primID, float u, float v, enum RTCBufferType bufferType, unsigned int bufferSlot, float* P, unsigned int valueCount)
-{
- struct RTCInterpolateArguments args;
- args.geometry = geometry;
- args.primID = primID;
- args.u = u;
- args.v = v;
- args.bufferType = bufferType;
- args.bufferSlot = bufferSlot;
- args.P = P;
- args.dPdu = NULL;
- args.dPdv = NULL;
- args.ddPdudu = NULL;
- args.ddPdvdv = NULL;
- args.ddPdudv = NULL;
- args.valueCount = valueCount;
- rtcInterpolate(&args);
-}
-
-/* Interpolates vertex data to some u/v location and calculates first order derivatives. */
-RTC_FORCEINLINE void rtcInterpolate1(RTCGeometry geometry, unsigned int primID, float u, float v, enum RTCBufferType bufferType, unsigned int bufferSlot,
- float* P, float* dPdu, float* dPdv, unsigned int valueCount)
-{
- struct RTCInterpolateArguments args;
- args.geometry = geometry;
- args.primID = primID;
- args.u = u;
- args.v = v;
- args.bufferType = bufferType;
- args.bufferSlot = bufferSlot;
- args.P = P;
- args.dPdu = dPdu;
- args.dPdv = dPdv;
- args.ddPdudu = NULL;
- args.ddPdvdv = NULL;
- args.ddPdudv = NULL;
- args.valueCount = valueCount;
- rtcInterpolate(&args);
-}
-
-/* Interpolates vertex data to some u/v location and calculates first and second order derivatives. */
-RTC_FORCEINLINE void rtcInterpolate2(RTCGeometry geometry, unsigned int primID, float u, float v, enum RTCBufferType bufferType, unsigned int bufferSlot,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, unsigned int valueCount)
-{
- struct RTCInterpolateArguments args;
- args.geometry = geometry;
- args.primID = primID;
- args.u = u;
- args.v = v;
- args.bufferType = bufferType;
- args.bufferSlot = bufferSlot;
- args.P = P;
- args.dPdu = dPdu;
- args.dPdv = dPdv;
- args.ddPdudu = ddPdudu;
- args.ddPdvdv = ddPdvdv;
- args.ddPdudv = ddPdudv;
- args.valueCount = valueCount;
- rtcInterpolate(&args);
-}
-
-/* Arguments for rtcInterpolateN */
-struct RTCInterpolateNArguments
-{
- RTCGeometry geometry;
- const void* valid;
- const unsigned int* primIDs;
- const float* u;
- const float* v;
- unsigned int N;
- enum RTCBufferType bufferType;
- unsigned int bufferSlot;
- float* P;
- float* dPdu;
- float* dPdv;
- float* ddPdudu;
- float* ddPdvdv;
- float* ddPdudv;
- unsigned int valueCount;
-};
-
-/* Interpolates vertex data to an array of u/v locations. */
-RTC_API void rtcInterpolateN(const struct RTCInterpolateNArguments* args);
-
-/* RTCGrid primitive for grid mesh */
-struct RTCGrid
-{
- unsigned int startVertexID;
- unsigned int stride;
- unsigned short width,height; // max is a 32k x 32k grid
-};
-
-RTC_NAMESPACE_END
-
-
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_quaternion.h b/thirdparty/embree-aarch64/include/embree3/rtcore_quaternion.h
deleted file mode 100644
index 449cdedfdc..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_quaternion.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore_common.h"
-
-RTC_NAMESPACE_BEGIN
-
-/*
- * Structure for transformation respresentation as a matrix decomposition using
- * a quaternion
- */
-struct RTC_ALIGN(16) RTCQuaternionDecomposition
-{
- float scale_x;
- float scale_y;
- float scale_z;
- float skew_xy;
- float skew_xz;
- float skew_yz;
- float shift_x;
- float shift_y;
- float shift_z;
- float quaternion_r;
- float quaternion_i;
- float quaternion_j;
- float quaternion_k;
- float translation_x;
- float translation_y;
- float translation_z;
-};
-
-RTC_FORCEINLINE void rtcInitQuaternionDecomposition(struct RTCQuaternionDecomposition* qdecomp)
-{
- qdecomp->scale_x = 1.f;
- qdecomp->scale_y = 1.f;
- qdecomp->scale_z = 1.f;
- qdecomp->skew_xy = 0.f;
- qdecomp->skew_xz = 0.f;
- qdecomp->skew_yz = 0.f;
- qdecomp->shift_x = 0.f;
- qdecomp->shift_y = 0.f;
- qdecomp->shift_z = 0.f;
- qdecomp->quaternion_r = 1.f;
- qdecomp->quaternion_i = 0.f;
- qdecomp->quaternion_j = 0.f;
- qdecomp->quaternion_k = 0.f;
- qdecomp->translation_x = 0.f;
- qdecomp->translation_y = 0.f;
- qdecomp->translation_z = 0.f;
-}
-
-RTC_FORCEINLINE void rtcQuaternionDecompositionSetQuaternion(
- struct RTCQuaternionDecomposition* qdecomp,
- float r, float i, float j, float k)
-{
- qdecomp->quaternion_r = r;
- qdecomp->quaternion_i = i;
- qdecomp->quaternion_j = j;
- qdecomp->quaternion_k = k;
-}
-
-RTC_FORCEINLINE void rtcQuaternionDecompositionSetScale(
- struct RTCQuaternionDecomposition* qdecomp,
- float scale_x, float scale_y, float scale_z)
-{
- qdecomp->scale_x = scale_x;
- qdecomp->scale_y = scale_y;
- qdecomp->scale_z = scale_z;
-}
-
-RTC_FORCEINLINE void rtcQuaternionDecompositionSetSkew(
- struct RTCQuaternionDecomposition* qdecomp,
- float skew_xy, float skew_xz, float skew_yz)
-{
- qdecomp->skew_xy = skew_xy;
- qdecomp->skew_xz = skew_xz;
- qdecomp->skew_yz = skew_yz;
-}
-
-RTC_FORCEINLINE void rtcQuaternionDecompositionSetShift(
- struct RTCQuaternionDecomposition* qdecomp,
- float shift_x, float shift_y, float shift_z)
-{
- qdecomp->shift_x = shift_x;
- qdecomp->shift_y = shift_y;
- qdecomp->shift_z = shift_z;
-}
-
-RTC_FORCEINLINE void rtcQuaternionDecompositionSetTranslation(
- struct RTCQuaternionDecomposition* qdecomp,
- float translation_x, float translation_y, float translation_z)
-{
- qdecomp->translation_x = translation_x;
- qdecomp->translation_y = translation_y;
- qdecomp->translation_z = translation_z;
-}
-
-RTC_NAMESPACE_END
-
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_ray.h b/thirdparty/embree-aarch64/include/embree3/rtcore_ray.h
deleted file mode 100644
index 1ae3309ef1..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_ray.h
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore_common.h"
-
-RTC_NAMESPACE_BEGIN
-
-/* Ray structure for a single ray */
-struct RTC_ALIGN(16) RTCRay
-{
- float org_x; // x coordinate of ray origin
- float org_y; // y coordinate of ray origin
- float org_z; // z coordinate of ray origin
- float tnear; // start of ray segment
-
- float dir_x; // x coordinate of ray direction
- float dir_y; // y coordinate of ray direction
- float dir_z; // z coordinate of ray direction
- float time; // time of this ray for motion blur
-
- float tfar; // end of ray segment (set to hit distance)
- unsigned int mask; // ray mask
- unsigned int id; // ray ID
- unsigned int flags; // ray flags
-};
-
-/* Hit structure for a single ray */
-struct RTC_ALIGN(16) RTCHit
-{
- float Ng_x; // x coordinate of geometry normal
- float Ng_y; // y coordinate of geometry normal
- float Ng_z; // z coordinate of geometry normal
-
- float u; // barycentric u coordinate of hit
- float v; // barycentric v coordinate of hit
-
- unsigned int primID; // primitive ID
- unsigned int geomID; // geometry ID
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
-};
-
-/* Combined ray/hit structure for a single ray */
-struct RTCRayHit
-{
- struct RTCRay ray;
- struct RTCHit hit;
-};
-
-/* Ray structure for a packet of 4 rays */
-struct RTC_ALIGN(16) RTCRay4
-{
- float org_x[4];
- float org_y[4];
- float org_z[4];
- float tnear[4];
-
- float dir_x[4];
- float dir_y[4];
- float dir_z[4];
- float time[4];
-
- float tfar[4];
- unsigned int mask[4];
- unsigned int id[4];
- unsigned int flags[4];
-};
-
-/* Hit structure for a packet of 4 rays */
-struct RTC_ALIGN(16) RTCHit4
-{
- float Ng_x[4];
- float Ng_y[4];
- float Ng_z[4];
-
- float u[4];
- float v[4];
-
- unsigned int primID[4];
- unsigned int geomID[4];
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT][4];
-};
-
-/* Combined ray/hit structure for a packet of 4 rays */
-struct RTCRayHit4
-{
- struct RTCRay4 ray;
- struct RTCHit4 hit;
-};
-
-/* Ray structure for a packet of 8 rays */
-struct RTC_ALIGN(32) RTCRay8
-{
- float org_x[8];
- float org_y[8];
- float org_z[8];
- float tnear[8];
-
- float dir_x[8];
- float dir_y[8];
- float dir_z[8];
- float time[8];
-
- float tfar[8];
- unsigned int mask[8];
- unsigned int id[8];
- unsigned int flags[8];
-};
-
-/* Hit structure for a packet of 8 rays */
-struct RTC_ALIGN(32) RTCHit8
-{
- float Ng_x[8];
- float Ng_y[8];
- float Ng_z[8];
-
- float u[8];
- float v[8];
-
- unsigned int primID[8];
- unsigned int geomID[8];
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT][8];
-};
-
-/* Combined ray/hit structure for a packet of 8 rays */
-struct RTCRayHit8
-{
- struct RTCRay8 ray;
- struct RTCHit8 hit;
-};
-
-/* Ray structure for a packet of 16 rays */
-struct RTC_ALIGN(64) RTCRay16
-{
- float org_x[16];
- float org_y[16];
- float org_z[16];
- float tnear[16];
-
- float dir_x[16];
- float dir_y[16];
- float dir_z[16];
- float time[16];
-
- float tfar[16];
- unsigned int mask[16];
- unsigned int id[16];
- unsigned int flags[16];
-};
-
-/* Hit structure for a packet of 16 rays */
-struct RTC_ALIGN(64) RTCHit16
-{
- float Ng_x[16];
- float Ng_y[16];
- float Ng_z[16];
-
- float u[16];
- float v[16];
-
- unsigned int primID[16];
- unsigned int geomID[16];
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT][16];
-};
-
-/* Combined ray/hit structure for a packet of 16 rays */
-struct RTCRayHit16
-{
- struct RTCRay16 ray;
- struct RTCHit16 hit;
-};
-
-/* Ray structure for a packet/stream of N rays in pointer SOA layout */
-struct RTCRayNp
-{
- float* org_x;
- float* org_y;
- float* org_z;
- float* tnear;
-
- float* dir_x;
- float* dir_y;
- float* dir_z;
- float* time;
-
- float* tfar;
- unsigned int* mask;
- unsigned int* id;
- unsigned int* flags;
-};
-
-/* Hit structure for a packet/stream of N rays in pointer SOA layout */
-struct RTCHitNp
-{
- float* Ng_x;
- float* Ng_y;
- float* Ng_z;
-
- float* u;
- float* v;
-
- unsigned int* primID;
- unsigned int* geomID;
- unsigned int* instID[RTC_MAX_INSTANCE_LEVEL_COUNT];
-};
-
-/* Combined ray/hit structure for a packet/stream of N rays in pointer SOA layout */
-struct RTCRayHitNp
-{
- struct RTCRayNp ray;
- struct RTCHitNp hit;
-};
-
-struct RTCRayN;
-struct RTCHitN;
-struct RTCRayHitN;
-
-#if defined(__cplusplus)
-
-/* Helper functions to access ray packets of runtime size N */
-RTC_FORCEINLINE float& RTCRayN_org_x(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[0*N+i]; }
-RTC_FORCEINLINE float& RTCRayN_org_y(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[1*N+i]; }
-RTC_FORCEINLINE float& RTCRayN_org_z(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[2*N+i]; }
-RTC_FORCEINLINE float& RTCRayN_tnear(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[3*N+i]; }
-
-RTC_FORCEINLINE float& RTCRayN_dir_x(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[4*N+i]; }
-RTC_FORCEINLINE float& RTCRayN_dir_y(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[5*N+i]; }
-RTC_FORCEINLINE float& RTCRayN_dir_z(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[6*N+i]; }
-RTC_FORCEINLINE float& RTCRayN_time (RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[7*N+i]; }
-
-RTC_FORCEINLINE float& RTCRayN_tfar (RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[8*N+i]; }
-RTC_FORCEINLINE unsigned int& RTCRayN_mask (RTCRayN* ray, unsigned int N, unsigned int i) { return ((unsigned*)ray)[9*N+i]; }
-RTC_FORCEINLINE unsigned int& RTCRayN_id (RTCRayN* ray, unsigned int N, unsigned int i) { return ((unsigned*)ray)[10*N+i]; }
-RTC_FORCEINLINE unsigned int& RTCRayN_flags(RTCRayN* ray, unsigned int N, unsigned int i) { return ((unsigned*)ray)[11*N+i]; }
-
-/* Helper functions to access hit packets of runtime size N */
-RTC_FORCEINLINE float& RTCHitN_Ng_x(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[0*N+i]; }
-RTC_FORCEINLINE float& RTCHitN_Ng_y(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[1*N+i]; }
-RTC_FORCEINLINE float& RTCHitN_Ng_z(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[2*N+i]; }
-
-RTC_FORCEINLINE float& RTCHitN_u(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[3*N+i]; }
-RTC_FORCEINLINE float& RTCHitN_v(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[4*N+i]; }
-
-RTC_FORCEINLINE unsigned int& RTCHitN_primID(RTCHitN* hit, unsigned int N, unsigned int i) { return ((unsigned*)hit)[5*N+i]; }
-RTC_FORCEINLINE unsigned int& RTCHitN_geomID(RTCHitN* hit, unsigned int N, unsigned int i) { return ((unsigned*)hit)[6*N+i]; }
-RTC_FORCEINLINE unsigned int& RTCHitN_instID(RTCHitN* hit, unsigned int N, unsigned int i, unsigned int l) { return ((unsigned*)hit)[7*N+i+N*l]; }
-
-/* Helper functions to extract RTCRayN and RTCHitN from RTCRayHitN */
-RTC_FORCEINLINE RTCRayN* RTCRayHitN_RayN(RTCRayHitN* rayhit, unsigned int N) { return (RTCRayN*)&((float*)rayhit)[0*N]; }
-RTC_FORCEINLINE RTCHitN* RTCRayHitN_HitN(RTCRayHitN* rayhit, unsigned int N) { return (RTCHitN*)&((float*)rayhit)[12*N]; }
-
-/* Helper structure for a ray packet of compile-time size N */
-template<int N>
-struct RTCRayNt
-{
- float org_x[N];
- float org_y[N];
- float org_z[N];
- float tnear[N];
-
- float dir_x[N];
- float dir_y[N];
- float dir_z[N];
- float time[N];
-
- float tfar[N];
- unsigned int mask[N];
- unsigned int id[N];
- unsigned int flags[N];
-};
-
-/* Helper structure for a hit packet of compile-time size N */
-template<int N>
-struct RTCHitNt
-{
- float Ng_x[N];
- float Ng_y[N];
- float Ng_z[N];
-
- float u[N];
- float v[N];
-
- unsigned int primID[N];
- unsigned int geomID[N];
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT][N];
-};
-
-/* Helper structure for a combined ray/hit packet of compile-time size N */
-template<int N>
-struct RTCRayHitNt
-{
- RTCRayNt<N> ray;
- RTCHitNt<N> hit;
-};
-
-RTC_FORCEINLINE RTCRay rtcGetRayFromRayN(RTCRayN* rayN, unsigned int N, unsigned int i)
-{
- RTCRay ray;
- ray.org_x = RTCRayN_org_x(rayN,N,i);
- ray.org_y = RTCRayN_org_y(rayN,N,i);
- ray.org_z = RTCRayN_org_z(rayN,N,i);
- ray.tnear = RTCRayN_tnear(rayN,N,i);
- ray.dir_x = RTCRayN_dir_x(rayN,N,i);
- ray.dir_y = RTCRayN_dir_y(rayN,N,i);
- ray.dir_z = RTCRayN_dir_z(rayN,N,i);
- ray.time = RTCRayN_time(rayN,N,i);
- ray.tfar = RTCRayN_tfar(rayN,N,i);
- ray.mask = RTCRayN_mask(rayN,N,i);
- ray.id = RTCRayN_id(rayN,N,i);
- ray.flags = RTCRayN_flags(rayN,N,i);
- return ray;
-}
-
-RTC_FORCEINLINE RTCHit rtcGetHitFromHitN(RTCHitN* hitN, unsigned int N, unsigned int i)
-{
- RTCHit hit;
- hit.Ng_x = RTCHitN_Ng_x(hitN,N,i);
- hit.Ng_y = RTCHitN_Ng_y(hitN,N,i);
- hit.Ng_z = RTCHitN_Ng_z(hitN,N,i);
- hit.u = RTCHitN_u(hitN,N,i);
- hit.v = RTCHitN_v(hitN,N,i);
- hit.primID = RTCHitN_primID(hitN,N,i);
- hit.geomID = RTCHitN_geomID(hitN,N,i);
- for (unsigned int l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; l++)
- hit.instID[l] = RTCHitN_instID(hitN,N,i,l);
- return hit;
-}
-
-RTC_FORCEINLINE void rtcCopyHitToHitN(RTCHitN* hitN, const RTCHit* hit, unsigned int N, unsigned int i)
-{
- RTCHitN_Ng_x(hitN,N,i) = hit->Ng_x;
- RTCHitN_Ng_y(hitN,N,i) = hit->Ng_y;
- RTCHitN_Ng_z(hitN,N,i) = hit->Ng_z;
- RTCHitN_u(hitN,N,i) = hit->u;
- RTCHitN_v(hitN,N,i) = hit->v;
- RTCHitN_primID(hitN,N,i) = hit->primID;
- RTCHitN_geomID(hitN,N,i) = hit->geomID;
- for (unsigned int l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; l++)
- RTCHitN_instID(hitN,N,i,l) = hit->instID[l];
-}
-
-RTC_FORCEINLINE RTCRayHit rtcGetRayHitFromRayHitN(RTCRayHitN* rayhitN, unsigned int N, unsigned int i)
-{
- RTCRayHit rh;
-
- RTCRayN* ray = RTCRayHitN_RayN(rayhitN,N);
- rh.ray.org_x = RTCRayN_org_x(ray,N,i);
- rh.ray.org_y = RTCRayN_org_y(ray,N,i);
- rh.ray.org_z = RTCRayN_org_z(ray,N,i);
- rh.ray.tnear = RTCRayN_tnear(ray,N,i);
- rh.ray.dir_x = RTCRayN_dir_x(ray,N,i);
- rh.ray.dir_y = RTCRayN_dir_y(ray,N,i);
- rh.ray.dir_z = RTCRayN_dir_z(ray,N,i);
- rh.ray.time = RTCRayN_time(ray,N,i);
- rh.ray.tfar = RTCRayN_tfar(ray,N,i);
- rh.ray.mask = RTCRayN_mask(ray,N,i);
- rh.ray.id = RTCRayN_id(ray,N,i);
- rh.ray.flags = RTCRayN_flags(ray,N,i);
-
- RTCHitN* hit = RTCRayHitN_HitN(rayhitN,N);
- rh.hit.Ng_x = RTCHitN_Ng_x(hit,N,i);
- rh.hit.Ng_y = RTCHitN_Ng_y(hit,N,i);
- rh.hit.Ng_z = RTCHitN_Ng_z(hit,N,i);
- rh.hit.u = RTCHitN_u(hit,N,i);
- rh.hit.v = RTCHitN_v(hit,N,i);
- rh.hit.primID = RTCHitN_primID(hit,N,i);
- rh.hit.geomID = RTCHitN_geomID(hit,N,i);
- for (unsigned int l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; l++)
- rh.hit.instID[l] = RTCHitN_instID(hit,N,i,l);
-
- return rh;
-}
-
-#endif
-
-RTC_NAMESPACE_END
-
diff --git a/thirdparty/embree-aarch64/include/embree3/rtcore_scene.h b/thirdparty/embree-aarch64/include/embree3/rtcore_scene.h
deleted file mode 100644
index 0cd6401593..0000000000
--- a/thirdparty/embree-aarch64/include/embree3/rtcore_scene.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore_device.h"
-
-RTC_NAMESPACE_BEGIN
-
-/* Forward declarations for ray structures */
-struct RTCRayHit;
-struct RTCRayHit4;
-struct RTCRayHit8;
-struct RTCRayHit16;
-struct RTCRayHitNp;
-
-/* Scene flags */
-enum RTCSceneFlags
-{
- RTC_SCENE_FLAG_NONE = 0,
- RTC_SCENE_FLAG_DYNAMIC = (1 << 0),
- RTC_SCENE_FLAG_COMPACT = (1 << 1),
- RTC_SCENE_FLAG_ROBUST = (1 << 2),
- RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION = (1 << 3)
-};
-
-/* Creates a new scene. */
-RTC_API RTCScene rtcNewScene(RTCDevice device);
-
-/* Returns the device the scene got created in. The reference count of
- * the device is incremented by this function. */
-RTC_API RTCDevice rtcGetSceneDevice(RTCScene hscene);
-
-/* Retains the scene (increments the reference count). */
-RTC_API void rtcRetainScene(RTCScene scene);
-
-/* Releases the scene (decrements the reference count). */
-RTC_API void rtcReleaseScene(RTCScene scene);
-
-
-/* Attaches the geometry to a scene. */
-RTC_API unsigned int rtcAttachGeometry(RTCScene scene, RTCGeometry geometry);
-
-/* Attaches the geometry to a scene using the specified geometry ID. */
-RTC_API void rtcAttachGeometryByID(RTCScene scene, RTCGeometry geometry, unsigned int geomID);
-
-/* Detaches the geometry from the scene. */
-RTC_API void rtcDetachGeometry(RTCScene scene, unsigned int geomID);
-
-/* Gets a geometry handle from the scene. */
-RTC_API RTCGeometry rtcGetGeometry(RTCScene scene, unsigned int geomID);
-
-
-/* Commits the scene. */
-RTC_API void rtcCommitScene(RTCScene scene);
-
-/* Commits the scene from multiple threads. */
-RTC_API void rtcJoinCommitScene(RTCScene scene);
-
-
-/* Progress monitor callback function */
-typedef bool (*RTCProgressMonitorFunction)(void* ptr, double n);
-
-/* Sets the progress monitor callback function of the scene. */
-RTC_API void rtcSetSceneProgressMonitorFunction(RTCScene scene, RTCProgressMonitorFunction progress, void* ptr);
-
-/* Sets the build quality of the scene. */
-RTC_API void rtcSetSceneBuildQuality(RTCScene scene, enum RTCBuildQuality quality);
-
-/* Sets the scene flags. */
-RTC_API void rtcSetSceneFlags(RTCScene scene, enum RTCSceneFlags flags);
-
-/* Returns the scene flags. */
-RTC_API enum RTCSceneFlags rtcGetSceneFlags(RTCScene scene);
-
-/* Returns the axis-aligned bounds of the scene. */
-RTC_API void rtcGetSceneBounds(RTCScene scene, struct RTCBounds* bounds_o);
-
-/* Returns the linear axis-aligned bounds of the scene. */
-RTC_API void rtcGetSceneLinearBounds(RTCScene scene, struct RTCLinearBounds* bounds_o);
-
-
-/* Perform a closest point query of the scene. */
-RTC_API bool rtcPointQuery(RTCScene scene, struct RTCPointQuery* query, struct RTCPointQueryContext* context, RTCPointQueryFunction queryFunc, void* userPtr);
-
-/* Perform a closest point query with a packet of 4 points with the scene. */
-RTC_API bool rtcPointQuery4(const int* valid, RTCScene scene, struct RTCPointQuery4* query, struct RTCPointQueryContext* context, RTCPointQueryFunction queryFunc, void** userPtr);
-
-/* Perform a closest point query with a packet of 4 points with the scene. */
-RTC_API bool rtcPointQuery8(const int* valid, RTCScene scene, struct RTCPointQuery8* query, struct RTCPointQueryContext* context, RTCPointQueryFunction queryFunc, void** userPtr);
-
-/* Perform a closest point query with a packet of 4 points with the scene. */
-RTC_API bool rtcPointQuery16(const int* valid, RTCScene scene, struct RTCPointQuery16* query, struct RTCPointQueryContext* context, RTCPointQueryFunction queryFunc, void** userPtr);
-
-/* Intersects a single ray with the scene. */
-RTC_API void rtcIntersect1(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit* rayhit);
-
-/* Intersects a packet of 4 rays with the scene. */
-RTC_API void rtcIntersect4(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit4* rayhit);
-
-/* Intersects a packet of 8 rays with the scene. */
-RTC_API void rtcIntersect8(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit8* rayhit);
-
-/* Intersects a packet of 16 rays with the scene. */
-RTC_API void rtcIntersect16(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit16* rayhit);
-
-/* Intersects a stream of M rays with the scene. */
-RTC_API void rtcIntersect1M(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit* rayhit, unsigned int M, size_t byteStride);
-
-/* Intersects a stream of pointers to M rays with the scene. */
-RTC_API void rtcIntersect1Mp(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit** rayhit, unsigned int M);
-
-/* Intersects a stream of M ray packets of size N in SOA format with the scene. */
-RTC_API void rtcIntersectNM(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHitN* rayhit, unsigned int N, unsigned int M, size_t byteStride);
-
-/* Intersects a stream of M ray packets of size N in SOA format with the scene. */
-RTC_API void rtcIntersectNp(RTCScene scene, struct RTCIntersectContext* context, const struct RTCRayHitNp* rayhit, unsigned int N);
-
-/* Tests a single ray for occlusion with the scene. */
-RTC_API void rtcOccluded1(RTCScene scene, struct RTCIntersectContext* context, struct RTCRay* ray);
-
-/* Tests a packet of 4 rays for occlusion occluded with the scene. */
-RTC_API void rtcOccluded4(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRay4* ray);
-
-/* Tests a packet of 8 rays for occlusion with the scene. */
-RTC_API void rtcOccluded8(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRay8* ray);
-
-/* Tests a packet of 16 rays for occlusion with the scene. */
-RTC_API void rtcOccluded16(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRay16* ray);
-
-/* Tests a stream of M rays for occlusion with the scene. */
-RTC_API void rtcOccluded1M(RTCScene scene, struct RTCIntersectContext* context, struct RTCRay* ray, unsigned int M, size_t byteStride);
-
-/* Tests a stream of pointers to M rays for occlusion with the scene. */
-RTC_API void rtcOccluded1Mp(RTCScene scene, struct RTCIntersectContext* context, struct RTCRay** ray, unsigned int M);
-
-/* Tests a stream of M ray packets of size N in SOA format for occlusion with the scene. */
-RTC_API void rtcOccludedNM(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayN* ray, unsigned int N, unsigned int M, size_t byteStride);
-
-/* Tests a stream of M ray packets of size N in SOA format for occlusion with the scene. */
-RTC_API void rtcOccludedNp(RTCScene scene, struct RTCIntersectContext* context, const struct RTCRayNp* ray, unsigned int N);
-
-/*! collision callback */
-struct RTCCollision { unsigned int geomID0; unsigned int primID0; unsigned int geomID1; unsigned int primID1; };
-typedef void (*RTCCollideFunc) (void* userPtr, struct RTCCollision* collisions, unsigned int num_collisions);
-
-/*! Performs collision detection of two scenes */
-RTC_API void rtcCollide (RTCScene scene0, RTCScene scene1, RTCCollideFunc callback, void* userPtr);
-
-#if defined(__cplusplus)
-
-/* Helper for easily combining scene flags */
-inline RTCSceneFlags operator|(RTCSceneFlags a, RTCSceneFlags b) {
- return (RTCSceneFlags)((size_t)a | (size_t)b);
-}
-
-#endif
-
-RTC_NAMESPACE_END
-
diff --git a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_hair.h b/thirdparty/embree-aarch64/kernels/builders/bvh_builder_hair.h
deleted file mode 100644
index 755ce255fb..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_hair.h
+++ /dev/null
@@ -1,411 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../bvh/bvh.h"
-#include "../geometry/primitive.h"
-#include "../builders/bvh_builder_sah.h"
-#include "../builders/heuristic_binning_array_aligned.h"
-#include "../builders/heuristic_binning_array_unaligned.h"
-#include "../builders/heuristic_strand_array.h"
-
-#define NUM_HAIR_OBJECT_BINS 32
-
-namespace embree
-{
- namespace isa
- {
- struct BVHBuilderHair
- {
- /*! settings for builder */
- struct Settings
- {
- /*! default settings */
- Settings ()
- : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(7), finished_range_threshold(inf) {}
-
- public:
- size_t branchingFactor; //!< branching factor of BVH to build
- size_t maxDepth; //!< maximum depth of BVH to build
- size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
- size_t minLeafSize; //!< minimum size of a leaf
- size_t maxLeafSize; //!< maximum size of a leaf
- size_t finished_range_threshold; //!< finished range threshold
- };
-
- template<typename NodeRef,
- typename CreateAllocFunc,
- typename CreateAABBNodeFunc,
- typename SetAABBNodeFunc,
- typename CreateOBBNodeFunc,
- typename SetOBBNodeFunc,
- typename CreateLeafFunc,
- typename ProgressMonitor,
- typename ReportFinishedRangeFunc>
-
- class BuilderT
- {
- ALIGNED_CLASS_(16);
- friend struct BVHBuilderHair;
-
- typedef FastAllocator::CachedAllocator Allocator;
- typedef HeuristicArrayBinningSAH<PrimRef,NUM_HAIR_OBJECT_BINS> HeuristicBinningSAH;
- typedef UnalignedHeuristicArrayBinningSAH<PrimRef,NUM_HAIR_OBJECT_BINS> UnalignedHeuristicBinningSAH;
- typedef HeuristicStrandSplit HeuristicStrandSplitSAH;
-
- static const size_t MAX_BRANCHING_FACTOR = 8; //!< maximum supported BVH branching factor
- static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree if we are that many levels before the maximum tree depth
- static const size_t SINGLE_THREADED_THRESHOLD = 4096; //!< threshold to switch to single threaded build
-
- static const size_t travCostAligned = 1;
- static const size_t travCostUnaligned = 5;
- static const size_t intCost = 6;
-
- BuilderT (Scene* scene,
- PrimRef* prims,
- const CreateAllocFunc& createAlloc,
- const CreateAABBNodeFunc& createAABBNode,
- const SetAABBNodeFunc& setAABBNode,
- const CreateOBBNodeFunc& createOBBNode,
- const SetOBBNodeFunc& setOBBNode,
- const CreateLeafFunc& createLeaf,
- const ProgressMonitor& progressMonitor,
- const ReportFinishedRangeFunc& reportFinishedRange,
- const Settings settings)
-
- : cfg(settings),
- prims(prims),
- createAlloc(createAlloc),
- createAABBNode(createAABBNode),
- setAABBNode(setAABBNode),
- createOBBNode(createOBBNode),
- setOBBNode(setOBBNode),
- createLeaf(createLeaf),
- progressMonitor(progressMonitor),
- reportFinishedRange(reportFinishedRange),
- alignedHeuristic(prims), unalignedHeuristic(scene,prims), strandHeuristic(scene,prims) {}
-
- /*! checks if all primitives are from the same geometry */
- __forceinline bool sameGeometry(const PrimInfoRange& range)
- {
- if (range.size() == 0) return true;
- unsigned int firstGeomID = prims[range.begin()].geomID();
- for (size_t i=range.begin()+1; i<range.end(); i++) {
- if (prims[i].geomID() != firstGeomID){
- return false;
- }
- }
- return true;
- }
-
- /*! creates a large leaf that could be larger than supported by the BVH */
- NodeRef createLargeLeaf(size_t depth, const PrimInfoRange& pinfo, Allocator alloc)
- {
- /* this should never occur but is a fatal error */
- if (depth > cfg.maxDepth)
- throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
-
- /* create leaf for few primitives */
- if (pinfo.size() <= cfg.maxLeafSize && sameGeometry(pinfo))
- return createLeaf(prims,pinfo,alloc);
-
- /* fill all children by always splitting the largest one */
- PrimInfoRange children[MAX_BRANCHING_FACTOR];
- unsigned numChildren = 1;
- children[0] = pinfo;
-
- do {
-
- /* find best child with largest bounding box area */
- int bestChild = -1;
- size_t bestSize = 0;
- for (unsigned i=0; i<numChildren; i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].size() <= cfg.maxLeafSize && sameGeometry(children[i]))
- continue;
-
- /* remember child with largest size */
- if (children[i].size() > bestSize) {
- bestSize = children[i].size();
- bestChild = i;
- }
- }
- if (bestChild == -1) break;
-
- /*! split best child into left and right child */
- __aligned(64) PrimInfoRange left, right;
- if (!sameGeometry(children[bestChild])) {
- alignedHeuristic.splitByGeometry(children[bestChild],left,right);
- } else {
- alignedHeuristic.splitFallback(children[bestChild],left,right);
- }
-
- /* add new children left and right */
- children[bestChild] = children[numChildren-1];
- children[numChildren-1] = left;
- children[numChildren+0] = right;
- numChildren++;
-
- } while (numChildren < cfg.branchingFactor);
-
- /* create node */
- auto node = createAABBNode(alloc);
-
- for (size_t i=0; i<numChildren; i++) {
- const NodeRef child = createLargeLeaf(depth+1,children[i],alloc);
- setAABBNode(node,i,child,children[i].geomBounds);
- }
-
- return node;
- }
-
- /*! performs split */
- __noinline void split(const PrimInfoRange& pinfo, PrimInfoRange& linfo, PrimInfoRange& rinfo, bool& aligned) // FIXME: not inlined as ICC otherwise uses much stack
- {
- /* variable to track the SAH of the best splitting approach */
- float bestSAH = inf;
- const size_t blocks = (pinfo.size()+(1ull<<cfg.logBlockSize)-1ull) >> cfg.logBlockSize;
- const float leafSAH = intCost*float(blocks)*halfArea(pinfo.geomBounds);
-
- /* try standard binning in aligned space */
- float alignedObjectSAH = inf;
- HeuristicBinningSAH::Split alignedObjectSplit;
- if (aligned) {
- alignedObjectSplit = alignedHeuristic.find(pinfo,cfg.logBlockSize);
- alignedObjectSAH = travCostAligned*halfArea(pinfo.geomBounds) + intCost*alignedObjectSplit.splitSAH();
- bestSAH = min(alignedObjectSAH,bestSAH);
- }
-
- /* try standard binning in unaligned space */
- UnalignedHeuristicBinningSAH::Split unalignedObjectSplit;
- LinearSpace3fa uspace;
- float unalignedObjectSAH = inf;
- if (bestSAH > 0.7f*leafSAH) {
- uspace = unalignedHeuristic.computeAlignedSpace(pinfo);
- const PrimInfoRange sinfo = unalignedHeuristic.computePrimInfo(pinfo,uspace);
- unalignedObjectSplit = unalignedHeuristic.find(sinfo,cfg.logBlockSize,uspace);
- unalignedObjectSAH = travCostUnaligned*halfArea(pinfo.geomBounds) + intCost*unalignedObjectSplit.splitSAH();
- bestSAH = min(unalignedObjectSAH,bestSAH);
- }
-
- /* try splitting into two strands */
- HeuristicStrandSplitSAH::Split strandSplit;
- float strandSAH = inf;
- if (bestSAH > 0.7f*leafSAH && pinfo.size() <= 256) {
- strandSplit = strandHeuristic.find(pinfo,cfg.logBlockSize);
- strandSAH = travCostUnaligned*halfArea(pinfo.geomBounds) + intCost*strandSplit.splitSAH();
- bestSAH = min(strandSAH,bestSAH);
- }
-
- /* fallback if SAH heuristics failed */
- if (unlikely(!std::isfinite(bestSAH)))
- {
- alignedHeuristic.deterministic_order(pinfo);
- alignedHeuristic.splitFallback(pinfo,linfo,rinfo);
- }
-
- /* perform aligned split if this is best */
- else if (bestSAH == alignedObjectSAH) {
- alignedHeuristic.split(alignedObjectSplit,pinfo,linfo,rinfo);
- }
-
- /* perform unaligned split if this is best */
- else if (bestSAH == unalignedObjectSAH) {
- unalignedHeuristic.split(unalignedObjectSplit,uspace,pinfo,linfo,rinfo);
- aligned = false;
- }
-
- /* perform strand split if this is best */
- else if (bestSAH == strandSAH) {
- strandHeuristic.split(strandSplit,pinfo,linfo,rinfo);
- aligned = false;
- }
-
- /* can never happen */
- else
- assert(false);
- }
-
- /*! recursive build */
- NodeRef recurse(size_t depth, const PrimInfoRange& pinfo, Allocator alloc, bool toplevel, bool alloc_barrier)
- {
- /* get thread local allocator */
- if (!alloc)
- alloc = createAlloc();
-
- /* call memory monitor function to signal progress */
- if (toplevel && pinfo.size() <= SINGLE_THREADED_THRESHOLD)
- progressMonitor(pinfo.size());
-
- PrimInfoRange children[MAX_BRANCHING_FACTOR];
-
- /* create leaf node */
- if (depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || pinfo.size() <= cfg.minLeafSize) {
- alignedHeuristic.deterministic_order(pinfo);
- return createLargeLeaf(depth,pinfo,alloc);
- }
-
- /* fill all children by always splitting the one with the largest surface area */
- size_t numChildren = 1;
- children[0] = pinfo;
- bool aligned = true;
-
- do {
-
- /* find best child with largest bounding box area */
- ssize_t bestChild = -1;
- float bestArea = neg_inf;
- for (size_t i=0; i<numChildren; i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].size() <= cfg.minLeafSize)
- continue;
-
- /* remember child with largest area */
- if (area(children[i].geomBounds) > bestArea) {
- bestArea = area(children[i].geomBounds);
- bestChild = i;
- }
- }
- if (bestChild == -1) break;
-
- /*! split best child into left and right child */
- PrimInfoRange left, right;
- split(children[bestChild],left,right,aligned);
-
- /* add new children left and right */
- children[bestChild] = children[numChildren-1];
- children[numChildren-1] = left;
- children[numChildren+0] = right;
- numChildren++;
-
- } while (numChildren < cfg.branchingFactor);
-
- NodeRef node;
-
- /* create aligned node */
- if (aligned)
- {
- node = createAABBNode(alloc);
-
- /* spawn tasks or ... */
- if (pinfo.size() > SINGLE_THREADED_THRESHOLD)
- {
- parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- const bool child_alloc_barrier = pinfo.size() > cfg.finished_range_threshold && children[i].size() <= cfg.finished_range_threshold;
- setAABBNode(node,i,recurse(depth+1,children[i],nullptr,true,child_alloc_barrier),children[i].geomBounds);
- _mm_mfence(); // to allow non-temporal stores during build
- }
- });
- }
- /* ... continue sequentially */
- else {
- for (size_t i=0; i<numChildren; i++) {
- const bool child_alloc_barrier = pinfo.size() > cfg.finished_range_threshold && children[i].size() <= cfg.finished_range_threshold;
- setAABBNode(node,i,recurse(depth+1,children[i],alloc,false,child_alloc_barrier),children[i].geomBounds);
- }
- }
- }
-
- /* create unaligned node */
- else
- {
- node = createOBBNode(alloc);
-
- /* spawn tasks or ... */
- if (pinfo.size() > SINGLE_THREADED_THRESHOLD)
- {
- parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpace(children[i]);
- const PrimInfoRange sinfo = unalignedHeuristic.computePrimInfo(children[i],space);
- const OBBox3fa obounds(space,sinfo.geomBounds);
- const bool child_alloc_barrier = pinfo.size() > cfg.finished_range_threshold && children[i].size() <= cfg.finished_range_threshold;
- setOBBNode(node,i,recurse(depth+1,children[i],nullptr,true,child_alloc_barrier),obounds);
- _mm_mfence(); // to allow non-temporal stores during build
- }
- });
- }
- /* ... continue sequentially */
- else
- {
- for (size_t i=0; i<numChildren; i++) {
- const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpace(children[i]);
- const PrimInfoRange sinfo = unalignedHeuristic.computePrimInfo(children[i],space);
- const OBBox3fa obounds(space,sinfo.geomBounds);
- const bool child_alloc_barrier = pinfo.size() > cfg.finished_range_threshold && children[i].size() <= cfg.finished_range_threshold;
- setOBBNode(node,i,recurse(depth+1,children[i],alloc,false,child_alloc_barrier),obounds);
- }
- }
- }
-
- /* reports a finished range of primrefs */
- if (unlikely(alloc_barrier))
- reportFinishedRange(pinfo);
-
- return node;
- }
-
- private:
- Settings cfg;
- PrimRef* prims;
- const CreateAllocFunc& createAlloc;
- const CreateAABBNodeFunc& createAABBNode;
- const SetAABBNodeFunc& setAABBNode;
- const CreateOBBNodeFunc& createOBBNode;
- const SetOBBNodeFunc& setOBBNode;
- const CreateLeafFunc& createLeaf;
- const ProgressMonitor& progressMonitor;
- const ReportFinishedRangeFunc& reportFinishedRange;
-
- private:
- HeuristicBinningSAH alignedHeuristic;
- UnalignedHeuristicBinningSAH unalignedHeuristic;
- HeuristicStrandSplitSAH strandHeuristic;
- };
-
- template<typename NodeRef,
- typename CreateAllocFunc,
- typename CreateAABBNodeFunc,
- typename SetAABBNodeFunc,
- typename CreateOBBNodeFunc,
- typename SetOBBNodeFunc,
- typename CreateLeafFunc,
- typename ProgressMonitor,
- typename ReportFinishedRangeFunc>
-
- static NodeRef build (const CreateAllocFunc& createAlloc,
- const CreateAABBNodeFunc& createAABBNode,
- const SetAABBNodeFunc& setAABBNode,
- const CreateOBBNodeFunc& createOBBNode,
- const SetOBBNodeFunc& setOBBNode,
- const CreateLeafFunc& createLeaf,
- const ProgressMonitor& progressMonitor,
- const ReportFinishedRangeFunc& reportFinishedRange,
- Scene* scene,
- PrimRef* prims,
- const PrimInfo& pinfo,
- const Settings settings)
- {
- typedef BuilderT<NodeRef,
- CreateAllocFunc,
- CreateAABBNodeFunc,SetAABBNodeFunc,
- CreateOBBNodeFunc,SetOBBNodeFunc,
- CreateLeafFunc,ProgressMonitor,
- ReportFinishedRangeFunc> Builder;
-
- Builder builder(scene,prims,createAlloc,
- createAABBNode,setAABBNode,
- createOBBNode,setOBBNode,
- createLeaf,progressMonitor,reportFinishedRange,settings);
-
- NodeRef root = builder.recurse(1,pinfo,nullptr,true,false);
- _mm_mfence(); // to allow non-temporal stores during build
- return root;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_morton.h b/thirdparty/embree-aarch64/kernels/builders/bvh_builder_morton.h
deleted file mode 100644
index 92be2f7e65..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_morton.h
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/builder.h"
-#include "../../common/algorithms/parallel_reduce.h"
-
-namespace embree
-{
- namespace isa
- {
- struct BVHBuilderMorton
- {
- static const size_t MAX_BRANCHING_FACTOR = 8; //!< maximum supported BVH branching factor
- static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree of we are that many levels before the maximum tree depth
-
- /*! settings for morton builder */
- struct Settings
- {
- /*! default settings */
- Settings ()
- : branchingFactor(2), maxDepth(32), minLeafSize(1), maxLeafSize(7), singleThreadThreshold(1024) {}
-
- /*! initialize settings from API settings */
- Settings (const RTCBuildArguments& settings)
- : branchingFactor(2), maxDepth(32), minLeafSize(1), maxLeafSize(7), singleThreadThreshold(1024)
- {
- if (RTC_BUILD_ARGUMENTS_HAS(settings,maxBranchingFactor)) branchingFactor = settings.maxBranchingFactor;
- if (RTC_BUILD_ARGUMENTS_HAS(settings,maxDepth )) maxDepth = settings.maxDepth;
- if (RTC_BUILD_ARGUMENTS_HAS(settings,minLeafSize )) minLeafSize = settings.minLeafSize;
- if (RTC_BUILD_ARGUMENTS_HAS(settings,maxLeafSize )) maxLeafSize = settings.maxLeafSize;
-
- minLeafSize = min(minLeafSize,maxLeafSize);
- }
-
- Settings (size_t branchingFactor, size_t maxDepth, size_t minLeafSize, size_t maxLeafSize, size_t singleThreadThreshold)
- : branchingFactor(branchingFactor), maxDepth(maxDepth), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize), singleThreadThreshold(singleThreadThreshold)
- {
- minLeafSize = min(minLeafSize,maxLeafSize);
- }
-
- public:
- size_t branchingFactor; //!< branching factor of BVH to build
- size_t maxDepth; //!< maximum depth of BVH to build
- size_t minLeafSize; //!< minimum size of a leaf
- size_t maxLeafSize; //!< maximum size of a leaf
- size_t singleThreadThreshold; //!< threshold when we switch to single threaded build
- };
-
- /*! Build primitive consisting of morton code and primitive ID. */
- struct __aligned(8) BuildPrim
- {
- union {
- struct {
- unsigned int code; //!< morton code
- unsigned int index; //!< i'th primitive
- };
- uint64_t t;
- };
-
- /*! interface for radix sort */
- __forceinline operator unsigned() const { return code; }
-
- /*! interface for standard sort */
- __forceinline bool operator<(const BuildPrim &m) const { return code < m.code; }
- };
-
- /*! maps bounding box to morton code */
- struct MortonCodeMapping
- {
- static const size_t LATTICE_BITS_PER_DIM = 10;
- static const size_t LATTICE_SIZE_PER_DIM = size_t(1) << LATTICE_BITS_PER_DIM;
-
- vfloat4 base;
- vfloat4 scale;
-
- __forceinline MortonCodeMapping(const BBox3fa& bounds)
- {
- base = (vfloat4)bounds.lower;
- const vfloat4 diag = (vfloat4)bounds.upper - (vfloat4)bounds.lower;
- scale = select(diag > vfloat4(1E-19f), rcp(diag) * vfloat4(LATTICE_SIZE_PER_DIM * 0.99f),vfloat4(0.0f));
- }
-
- __forceinline const vint4 bin (const BBox3fa& box) const
- {
- const vfloat4 lower = (vfloat4)box.lower;
- const vfloat4 upper = (vfloat4)box.upper;
- const vfloat4 centroid = lower+upper;
- return vint4((centroid-base)*scale);
- }
-
- __forceinline unsigned int code (const BBox3fa& box) const
- {
- const vint4 binID = bin(box);
- const unsigned int x = extract<0>(binID);
- const unsigned int y = extract<1>(binID);
- const unsigned int z = extract<2>(binID);
- const unsigned int xyz = bitInterleave(x,y,z);
- return xyz;
- }
- };
-
-#if defined (__AVX2__)
-
- /*! for AVX2 there is a fast scalar bitInterleave */
- struct MortonCodeGenerator
- {
- __forceinline MortonCodeGenerator(const MortonCodeMapping& mapping, BuildPrim* dest)
- : mapping(mapping), dest(dest) {}
-
- __forceinline void operator() (const BBox3fa& b, const unsigned index)
- {
- dest->index = index;
- dest->code = mapping.code(b);
- dest++;
- }
-
- public:
- const MortonCodeMapping mapping;
- BuildPrim* dest;
- size_t currentID;
- };
-
-#else
-
- /*! before AVX2 is it better to use the SSE version of bitInterleave */
- struct MortonCodeGenerator
- {
- __forceinline MortonCodeGenerator(const MortonCodeMapping& mapping, BuildPrim* dest)
- : mapping(mapping), dest(dest), currentID(0), slots(0), ax(0), ay(0), az(0), ai(0) {}
-
- __forceinline ~MortonCodeGenerator()
- {
- if (slots != 0)
- {
- const vint4 code = bitInterleave(ax,ay,az);
- for (size_t i=0; i<slots; i++) {
- dest[currentID-slots+i].index = ai[i];
- dest[currentID-slots+i].code = code[i];
- }
- }
- }
-
- __forceinline void operator() (const BBox3fa& b, const unsigned index)
- {
- const vint4 binID = mapping.bin(b);
- ax[slots] = extract<0>(binID);
- ay[slots] = extract<1>(binID);
- az[slots] = extract<2>(binID);
- ai[slots] = index;
- slots++;
- currentID++;
-
- if (slots == 4)
- {
- const vint4 code = bitInterleave(ax,ay,az);
- vint4::storeu(&dest[currentID-4],unpacklo(code,ai));
- vint4::storeu(&dest[currentID-2],unpackhi(code,ai));
- slots = 0;
- }
- }
-
- public:
- const MortonCodeMapping mapping;
- BuildPrim* dest;
- size_t currentID;
- size_t slots;
- vint4 ax, ay, az, ai;
- };
-
-#endif
-
- template<
- typename ReductionTy,
- typename Allocator,
- typename CreateAllocator,
- typename CreateNodeFunc,
- typename SetNodeBoundsFunc,
- typename CreateLeafFunc,
- typename CalculateBounds,
- typename ProgressMonitor>
-
- class BuilderT : private Settings
- {
- ALIGNED_CLASS_(16);
-
- public:
-
- BuilderT (CreateAllocator& createAllocator,
- CreateNodeFunc& createNode,
- SetNodeBoundsFunc& setBounds,
- CreateLeafFunc& createLeaf,
- CalculateBounds& calculateBounds,
- ProgressMonitor& progressMonitor,
- const Settings& settings)
-
- : Settings(settings),
- createAllocator(createAllocator),
- createNode(createNode),
- setBounds(setBounds),
- createLeaf(createLeaf),
- calculateBounds(calculateBounds),
- progressMonitor(progressMonitor),
- morton(nullptr) {}
-
- ReductionTy createLargeLeaf(size_t depth, const range<unsigned>& current, Allocator alloc)
- {
- /* this should never occur but is a fatal error */
- if (depth > maxDepth)
- throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
-
- /* create leaf for few primitives */
- if (current.size() <= maxLeafSize)
- return createLeaf(current,alloc);
-
- /* fill all children by always splitting the largest one */
- range<unsigned> children[MAX_BRANCHING_FACTOR];
- size_t numChildren = 1;
- children[0] = current;
-
- do {
-
- /* find best child with largest number of primitives */
- size_t bestChild = -1;
- size_t bestSize = 0;
- for (size_t i=0; i<numChildren; i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].size() <= maxLeafSize)
- continue;
-
- /* remember child with largest size */
- if (children[i].size() > bestSize) {
- bestSize = children[i].size();
- bestChild = i;
- }
- }
- if (bestChild == size_t(-1)) break;
-
- /*! split best child into left and right child */
- auto split = children[bestChild].split();
-
- /* add new children left and right */
- children[bestChild] = children[numChildren-1];
- children[numChildren-1] = split.first;
- children[numChildren+0] = split.second;
- numChildren++;
-
- } while (numChildren < branchingFactor);
-
- /* create node */
- auto node = createNode(alloc,numChildren);
-
- /* recurse into each child */
- ReductionTy bounds[MAX_BRANCHING_FACTOR];
- for (size_t i=0; i<numChildren; i++)
- bounds[i] = createLargeLeaf(depth+1,children[i],alloc);
-
- return setBounds(node,bounds,numChildren);
- }
-
- /*! recreates morton codes when reaching a region where all codes are identical */
- __noinline void recreateMortonCodes(const range<unsigned>& current) const
- {
- /* fast path for small ranges */
- if (likely(current.size() < 1024))
- {
- /*! recalculate centroid bounds */
- BBox3fa centBounds(empty);
- for (size_t i=current.begin(); i<current.end(); i++)
- centBounds.extend(center2(calculateBounds(morton[i])));
-
- /* recalculate morton codes */
- MortonCodeMapping mapping(centBounds);
- for (size_t i=current.begin(); i<current.end(); i++)
- morton[i].code = mapping.code(calculateBounds(morton[i]));
-
- /* sort morton codes */
- std::sort(morton+current.begin(),morton+current.end());
- }
- else
- {
- /*! recalculate centroid bounds */
- auto calculateCentBounds = [&] ( const range<unsigned>& r ) {
- BBox3fa centBounds = empty;
- for (size_t i=r.begin(); i<r.end(); i++)
- centBounds.extend(center2(calculateBounds(morton[i])));
- return centBounds;
- };
- const BBox3fa centBounds = parallel_reduce(current.begin(), current.end(), unsigned(1024),
- BBox3fa(empty), calculateCentBounds, BBox3fa::merge);
-
- /* recalculate morton codes */
- MortonCodeMapping mapping(centBounds);
- parallel_for(current.begin(), current.end(), unsigned(1024), [&] ( const range<unsigned>& r ) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- morton[i].code = mapping.code(calculateBounds(morton[i]));
- }
- });
-
- /*! sort morton codes */
-#if defined(TASKING_TBB)
- tbb::parallel_sort(morton+current.begin(),morton+current.end());
-#else
- radixsort32(morton+current.begin(),current.size());
-#endif
- }
- }
-
- __forceinline void split(const range<unsigned>& current, range<unsigned>& left, range<unsigned>& right) const
- {
- const unsigned int code_start = morton[current.begin()].code;
- const unsigned int code_end = morton[current.end()-1].code;
- unsigned int bitpos = lzcnt(code_start^code_end);
-
- /* if all items mapped to same morton code, then re-create new morton codes for the items */
- if (unlikely(bitpos == 32))
- {
- recreateMortonCodes(current);
- const unsigned int code_start = morton[current.begin()].code;
- const unsigned int code_end = morton[current.end()-1].code;
- bitpos = lzcnt(code_start^code_end);
-
- /* if the morton code is still the same, goto fall back split */
- if (unlikely(bitpos == 32)) {
- current.split(left,right);
- return;
- }
- }
-
- /* split the items at the topmost different morton code bit */
- const unsigned int bitpos_diff = 31-bitpos;
- const unsigned int bitmask = 1 << bitpos_diff;
-
- /* find location where bit differs using binary search */
- unsigned begin = current.begin();
- unsigned end = current.end();
- while (begin + 1 != end) {
- const unsigned mid = (begin+end)/2;
- const unsigned bit = morton[mid].code & bitmask;
- if (bit == 0) begin = mid; else end = mid;
- }
- unsigned center = end;
-#if defined(DEBUG)
- for (unsigned int i=begin; i<center; i++) assert((morton[i].code & bitmask) == 0);
- for (unsigned int i=center; i<end; i++) assert((morton[i].code & bitmask) == bitmask);
-#endif
-
- left = make_range(current.begin(),center);
- right = make_range(center,current.end());
- }
-
- ReductionTy recurse(size_t depth, const range<unsigned>& current, Allocator alloc, bool toplevel)
- {
- /* get thread local allocator */
- if (!alloc)
- alloc = createAllocator();
-
- /* call memory monitor function to signal progress */
- if (toplevel && current.size() <= singleThreadThreshold)
- progressMonitor(current.size());
-
- /* create leaf node */
- if (unlikely(depth+MIN_LARGE_LEAF_LEVELS >= maxDepth || current.size() <= minLeafSize))
- return createLargeLeaf(depth,current,alloc);
-
- /* fill all children by always splitting the one with the largest surface area */
- range<unsigned> children[MAX_BRANCHING_FACTOR];
- split(current,children[0],children[1]);
- size_t numChildren = 2;
-
- while (numChildren < branchingFactor)
- {
- /* find best child with largest number of primitives */
- int bestChild = -1;
- unsigned bestItems = 0;
- for (unsigned int i=0; i<numChildren; i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].size() <= minLeafSize)
- continue;
-
- /* remember child with largest area */
- if (children[i].size() > bestItems) {
- bestItems = children[i].size();
- bestChild = i;
- }
- }
- if (bestChild == -1) break;
-
- /*! split best child into left and right child */
- range<unsigned> left, right;
- split(children[bestChild],left,right);
-
- /* add new children left and right */
- children[bestChild] = children[numChildren-1];
- children[numChildren-1] = left;
- children[numChildren+0] = right;
- numChildren++;
- }
-
- /* create leaf node if no split is possible */
- if (unlikely(numChildren == 1))
- return createLeaf(current,alloc);
-
- /* allocate node */
- auto node = createNode(alloc,numChildren);
-
- /* process top parts of tree parallel */
- ReductionTy bounds[MAX_BRANCHING_FACTOR];
- if (current.size() > singleThreadThreshold)
- {
- /*! parallel_for is faster than spawing sub-tasks */
- parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- bounds[i] = recurse(depth+1,children[i],nullptr,true);
- _mm_mfence(); // to allow non-temporal stores during build
- }
- });
- }
-
- /* finish tree sequentially */
- else
- {
- for (size_t i=0; i<numChildren; i++)
- bounds[i] = recurse(depth+1,children[i],alloc,false);
- }
-
- return setBounds(node,bounds,numChildren);
- }
-
- /* build function */
- ReductionTy build(BuildPrim* src, BuildPrim* tmp, size_t numPrimitives)
- {
- /* sort morton codes */
- morton = src;
- radix_sort_u32(src,tmp,numPrimitives,singleThreadThreshold);
-
- /* build BVH */
- const ReductionTy root = recurse(1, range<unsigned>(0,(unsigned)numPrimitives), nullptr, true);
- _mm_mfence(); // to allow non-temporal stores during build
- return root;
- }
-
- public:
- CreateAllocator& createAllocator;
- CreateNodeFunc& createNode;
- SetNodeBoundsFunc& setBounds;
- CreateLeafFunc& createLeaf;
- CalculateBounds& calculateBounds;
- ProgressMonitor& progressMonitor;
-
- public:
- BuildPrim* morton;
- };
-
-
- template<
- typename ReductionTy,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename SetBoundsFunc,
- typename CreateLeafFunc,
- typename CalculateBoundsFunc,
- typename ProgressMonitor>
-
- static ReductionTy build(CreateAllocFunc createAllocator,
- CreateNodeFunc createNode,
- SetBoundsFunc setBounds,
- CreateLeafFunc createLeaf,
- CalculateBoundsFunc calculateBounds,
- ProgressMonitor progressMonitor,
- BuildPrim* src,
- BuildPrim* tmp,
- size_t numPrimitives,
- const Settings& settings)
- {
- typedef BuilderT<
- ReductionTy,
- decltype(createAllocator()),
- CreateAllocFunc,
- CreateNodeFunc,
- SetBoundsFunc,
- CreateLeafFunc,
- CalculateBoundsFunc,
- ProgressMonitor> Builder;
-
- Builder builder(createAllocator,
- createNode,
- setBounds,
- createLeaf,
- calculateBounds,
- progressMonitor,
- settings);
-
- return builder.build(src,tmp,numPrimitives);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_msmblur.h b/thirdparty/embree-aarch64/kernels/builders/bvh_builder_msmblur.h
deleted file mode 100644
index 4c138dacdb..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_msmblur.h
+++ /dev/null
@@ -1,692 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#define MBLUR_NUM_TEMPORAL_BINS 2
-#define MBLUR_NUM_OBJECT_BINS 32
-
-#include "../bvh/bvh.h"
-#include "../common/primref_mb.h"
-#include "heuristic_binning_array_aligned.h"
-#include "heuristic_timesplit_array.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename T>
- struct SharedVector
- {
- __forceinline SharedVector() {}
-
- __forceinline SharedVector(T* ptr, size_t refCount = 1)
- : prims(ptr), refCount(refCount) {}
-
- __forceinline void incRef() {
- refCount++;
- }
-
- __forceinline void decRef()
- {
- if (--refCount == 0)
- delete prims;
- }
-
- T* prims;
- size_t refCount;
- };
-
- template<typename BuildRecord, int MAX_BRANCHING_FACTOR>
- struct LocalChildListT
- {
- typedef SharedVector<mvector<PrimRefMB>> SharedPrimRefVector;
-
- __forceinline LocalChildListT (const BuildRecord& record)
- : numChildren(1), numSharedPrimVecs(1)
- {
- /* the local root will be freed in the ancestor where it was created (thus refCount is 2) */
- children[0] = record;
- primvecs[0] = new (&sharedPrimVecs[0]) SharedPrimRefVector(record.prims.prims, 2);
- }
-
- __forceinline ~LocalChildListT()
- {
- for (size_t i = 0; i < numChildren; i++)
- primvecs[i]->decRef();
- }
-
- __forceinline BuildRecord& operator[] ( const size_t i ) {
- return children[i];
- }
-
- __forceinline size_t size() const {
- return numChildren;
- }
-
- __forceinline void split(ssize_t bestChild, const BuildRecord& lrecord, const BuildRecord& rrecord, std::unique_ptr<mvector<PrimRefMB>> new_vector)
- {
- SharedPrimRefVector* bsharedPrimVec = primvecs[bestChild];
- if (lrecord.prims.prims == bsharedPrimVec->prims) {
- primvecs[bestChild] = bsharedPrimVec;
- bsharedPrimVec->incRef();
- }
- else {
- primvecs[bestChild] = new (&sharedPrimVecs[numSharedPrimVecs++]) SharedPrimRefVector(lrecord.prims.prims);
- }
-
- if (rrecord.prims.prims == bsharedPrimVec->prims) {
- primvecs[numChildren] = bsharedPrimVec;
- bsharedPrimVec->incRef();
- }
- else {
- primvecs[numChildren] = new (&sharedPrimVecs[numSharedPrimVecs++]) SharedPrimRefVector(rrecord.prims.prims);
- }
- bsharedPrimVec->decRef();
- new_vector.release();
-
- children[bestChild] = lrecord;
- children[numChildren] = rrecord;
- numChildren++;
- }
-
- public:
- array_t<BuildRecord,MAX_BRANCHING_FACTOR> children;
- array_t<SharedPrimRefVector*,MAX_BRANCHING_FACTOR> primvecs;
- size_t numChildren;
-
- array_t<SharedPrimRefVector,2*MAX_BRANCHING_FACTOR> sharedPrimVecs;
- size_t numSharedPrimVecs;
- };
-
- template<typename Mesh>
- struct RecalculatePrimRef
- {
- Scene* scene;
-
- __forceinline RecalculatePrimRef (Scene* scene)
- : scene(scene) {}
-
- __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const
- {
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const Mesh* mesh = scene->get<Mesh>(geomID);
- const LBBox3fa lbounds = mesh->linearBounds(primID, time_range);
- const range<int> tbounds = mesh->timeSegmentRange(time_range);
- return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
- }
-
- // __noinline is workaround for ICC16 bug under MacOSX
- __noinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const
- {
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const Mesh* mesh = scene->get<Mesh>(geomID);
- const LBBox3fa lbounds = mesh->linearBounds(space, primID, time_range);
- const range<int> tbounds = mesh->timeSegmentRange(time_range);
- return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
- }
-
- __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
- return scene->get<Mesh>(prim.geomID())->linearBounds(prim.primID(), time_range);
- }
-
- // __noinline is workaround for ICC16 bug under MacOSX
- __noinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const {
- return scene->get<Mesh>(prim.geomID())->linearBounds(space, prim.primID(), time_range);
- }
- };
-
- struct VirtualRecalculatePrimRef
- {
- Scene* scene;
-
- __forceinline VirtualRecalculatePrimRef (Scene* scene)
- : scene(scene) {}
-
- __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const
- {
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const Geometry* mesh = scene->get(geomID);
- const LBBox3fa lbounds = mesh->vlinearBounds(primID, time_range);
- const range<int> tbounds = mesh->timeSegmentRange(time_range);
- return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
- }
-
- __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const
- {
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const Geometry* mesh = scene->get(geomID);
- const LBBox3fa lbounds = mesh->vlinearBounds(space, primID, time_range);
- const range<int> tbounds = mesh->timeSegmentRange(time_range);
- return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
- }
-
- __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
- return scene->get(prim.geomID())->vlinearBounds(prim.primID(), time_range);
- }
-
- __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const {
- return scene->get(prim.geomID())->vlinearBounds(space, prim.primID(), time_range);
- }
- };
-
- struct BVHBuilderMSMBlur
- {
- /*! settings for msmblur builder */
- struct Settings
- {
- /*! default settings */
- Settings ()
- : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8),
- travCost(1.0f), intCost(1.0f), singleLeafTimeSegment(false),
- singleThreadThreshold(1024) {}
-
-
- Settings (size_t sahBlockSize, size_t minLeafSize, size_t maxLeafSize, float travCost, float intCost, size_t singleThreadThreshold)
- : branchingFactor(2), maxDepth(32), logBlockSize(bsr(sahBlockSize)), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize),
- travCost(travCost), intCost(intCost), singleThreadThreshold(singleThreadThreshold)
- {
- minLeafSize = min(minLeafSize,maxLeafSize);
- }
-
- public:
- size_t branchingFactor; //!< branching factor of BVH to build
- size_t maxDepth; //!< maximum depth of BVH to build
- size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
- size_t minLeafSize; //!< minimum size of a leaf
- size_t maxLeafSize; //!< maximum size of a leaf
- float travCost; //!< estimated cost of one traversal step
- float intCost; //!< estimated cost of one primitive intersection
- bool singleLeafTimeSegment; //!< split time to single time range
- size_t singleThreadThreshold; //!< threshold when we switch to single threaded build
- };
-
- struct BuildRecord
- {
- public:
- __forceinline BuildRecord () {}
-
- __forceinline BuildRecord (size_t depth)
- : depth(depth) {}
-
- __forceinline BuildRecord (const SetMB& prims, size_t depth)
- : depth(depth), prims(prims) {}
-
- __forceinline friend bool operator< (const BuildRecord& a, const BuildRecord& b) {
- return a.prims.size() < b.prims.size();
- }
-
- __forceinline size_t size() const {
- return prims.size();
- }
-
- public:
- size_t depth; //!< Depth of the root of this subtree.
- SetMB prims; //!< The list of primitives.
- };
-
- struct BuildRecordSplit : public BuildRecord
- {
- __forceinline BuildRecordSplit () {}
-
- __forceinline BuildRecordSplit (size_t depth)
- : BuildRecord(depth) {}
-
- __forceinline BuildRecordSplit (const BuildRecord& record, const BinSplit<MBLUR_NUM_OBJECT_BINS>& split)
- : BuildRecord(record), split(split) {}
-
- BinSplit<MBLUR_NUM_OBJECT_BINS> split;
- };
-
- template<
- typename NodeRef,
- typename RecalculatePrimRef,
- typename Allocator,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename SetNodeFunc,
- typename CreateLeafFunc,
- typename ProgressMonitor>
-
- class BuilderT
- {
- ALIGNED_CLASS_(16);
- static const size_t MAX_BRANCHING_FACTOR = 16; //!< maximum supported BVH branching factor
- static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree if we are that many levels before the maximum tree depth
-
- typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
- typedef BinSplit<MBLUR_NUM_OBJECT_BINS> Split;
- typedef mvector<PrimRefMB>* PrimRefVector;
- typedef SharedVector<mvector<PrimRefMB>> SharedPrimRefVector;
- typedef LocalChildListT<BuildRecord,MAX_BRANCHING_FACTOR> LocalChildList;
- typedef LocalChildListT<BuildRecordSplit,MAX_BRANCHING_FACTOR> LocalChildListSplit;
-
- public:
-
- BuilderT (MemoryMonitorInterface* device,
- const RecalculatePrimRef recalculatePrimRef,
- const CreateAllocFunc createAlloc,
- const CreateNodeFunc createNode,
- const SetNodeFunc setNode,
- const CreateLeafFunc createLeaf,
- const ProgressMonitor progressMonitor,
- const Settings& settings)
- : cfg(settings),
- heuristicObjectSplit(),
- heuristicTemporalSplit(device, recalculatePrimRef),
- recalculatePrimRef(recalculatePrimRef), createAlloc(createAlloc), createNode(createNode), setNode(setNode), createLeaf(createLeaf),
- progressMonitor(progressMonitor)
- {
- if (cfg.branchingFactor > MAX_BRANCHING_FACTOR)
- throw_RTCError(RTC_ERROR_UNKNOWN,"bvh_builder: branching factor too large");
- }
-
- /*! finds the best split */
- const Split find(const SetMB& set)
- {
- /* first try standard object split */
- const Split object_split = heuristicObjectSplit.find(set,cfg.logBlockSize);
- const float object_split_sah = object_split.splitSAH();
-
- /* test temporal splits only when object split was bad */
- const float leaf_sah = set.leafSAH(cfg.logBlockSize);
- if (object_split_sah < 0.50f*leaf_sah)
- return object_split;
-
- /* do temporal splits only if the the time range is big enough */
- if (set.time_range.size() > 1.01f/float(set.max_num_time_segments))
- {
- const Split temporal_split = heuristicTemporalSplit.find(set,cfg.logBlockSize);
- const float temporal_split_sah = temporal_split.splitSAH();
-
- /* take temporal split if it improved SAH */
- if (temporal_split_sah < object_split_sah)
- return temporal_split;
- }
-
- return object_split;
- }
-
- /*! array partitioning */
- __forceinline std::unique_ptr<mvector<PrimRefMB>> split(const Split& split, const SetMB& set, SetMB& lset, SetMB& rset)
- {
- /* perform object split */
- if (likely(split.data == Split::SPLIT_OBJECT)) {
- heuristicObjectSplit.split(split,set,lset,rset);
- }
- /* perform temporal split */
- else if (likely(split.data == Split::SPLIT_TEMPORAL)) {
- return heuristicTemporalSplit.split(split,set,lset,rset);
- }
- /* perform fallback split */
- else if (unlikely(split.data == Split::SPLIT_FALLBACK)) {
- set.deterministic_order();
- splitFallback(set,lset,rset);
- }
- /* split by geometry */
- else if (unlikely(split.data == Split::SPLIT_GEOMID)) {
- set.deterministic_order();
- splitByGeometry(set,lset,rset);
- }
- else
- assert(false);
-
- return std::unique_ptr<mvector<PrimRefMB>>();
- }
-
- /*! finds the best fallback split */
- __noinline Split findFallback(const SetMB& set)
- {
- /* split if primitives are not from same geometry */
- if (!sameGeometry(set))
- return Split(0.0f,Split::SPLIT_GEOMID);
-
- /* if a leaf can only hold a single time-segment, we might have to do additional temporal splits */
- if (cfg.singleLeafTimeSegment)
- {
- /* test if one primitive has more than one time segment in time range, if so split time */
- for (size_t i=set.begin(); i<set.end(); i++)
- {
- const PrimRefMB& prim = (*set.prims)[i];
- const range<int> itime_range = prim.timeSegmentRange(set.time_range);
- const int localTimeSegments = itime_range.size();
- assert(localTimeSegments > 0);
- if (localTimeSegments > 1) {
- const int icenter = (itime_range.begin() + itime_range.end())/2;
- const float splitTime = prim.timeStep(icenter);
- return Split(0.0f,(unsigned)Split::SPLIT_TEMPORAL,0,splitTime);
- }
- }
- }
-
- /* otherwise return fallback split */
- return Split(0.0f,Split::SPLIT_FALLBACK);
- }
-
- /*! performs fallback split */
- void splitFallback(const SetMB& set, SetMB& lset, SetMB& rset)
- {
- mvector<PrimRefMB>& prims = *set.prims;
-
- const size_t begin = set.begin();
- const size_t end = set.end();
- const size_t center = (begin + end)/2;
-
- PrimInfoMB linfo = empty;
- for (size_t i=begin; i<center; i++)
- linfo.add_primref(prims[i]);
-
- PrimInfoMB rinfo = empty;
- for (size_t i=center; i<end; i++)
- rinfo.add_primref(prims[i]);
-
- new (&lset) SetMB(linfo,set.prims,range<size_t>(begin,center),set.time_range);
- new (&rset) SetMB(rinfo,set.prims,range<size_t>(center,end ),set.time_range);
- }
-
- /*! checks if all primitives are from the same geometry */
- __forceinline bool sameGeometry(const SetMB& set)
- {
- if (set.size() == 0) return true;
- mvector<PrimRefMB>& prims = *set.prims;
- const size_t begin = set.begin();
- const size_t end = set.end();
- unsigned int firstGeomID = prims[begin].geomID();
- for (size_t i=begin+1; i<end; i++) {
- if (prims[i].geomID() != firstGeomID){
- return false;
- }
- }
- return true;
- }
-
- /* split by geometry ID */
- void splitByGeometry(const SetMB& set, SetMB& lset, SetMB& rset)
- {
- assert(set.size() > 1);
-
- mvector<PrimRefMB>& prims = *set.prims;
- const size_t begin = set.begin();
- const size_t end = set.end();
-
- PrimInfoMB left(empty);
- PrimInfoMB right(empty);
- unsigned int geomID = prims[begin].geomID();
- size_t center = serial_partitioning(prims.data(),begin,end,left,right,
- [&] ( const PrimRefMB& prim ) { return prim.geomID() == geomID; },
- [ ] ( PrimInfoMB& dst, const PrimRefMB& prim ) { dst.add_primref(prim); });
-
- new (&lset) SetMB(left, set.prims,range<size_t>(begin,center),set.time_range);
- new (&rset) SetMB(right,set.prims,range<size_t>(center,end ),set.time_range);
- }
-
- const NodeRecordMB4D createLargeLeaf(const BuildRecord& in, Allocator alloc)
- {
- /* this should never occur but is a fatal error */
- if (in.depth > cfg.maxDepth)
- throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
-
- /* replace already found split by fallback split */
- const BuildRecordSplit current(BuildRecord(in.prims,in.depth),findFallback(in.prims));
-
- /* special case when directly creating leaf without any splits that could shrink time_range */
- bool force_split = false;
- if (current.depth == 1 && current.size() > 0)
- {
- BBox1f c = empty;
- BBox1f p = current.prims.time_range;
- for (size_t i=current.prims.begin(); i<current.prims.end(); i++) {
- mvector<PrimRefMB>& prims = *current.prims.prims;
- c.extend(prims[i].time_range);
- }
-
- force_split = c.lower > p.lower || c.upper < p.upper;
- }
-
- /* create leaf for few primitives */
- if (current.size() <= cfg.maxLeafSize && current.split.data < Split::SPLIT_ENFORCE && !force_split)
- return createLeaf(current,alloc);
-
- /* fill all children by always splitting the largest one */
- bool hasTimeSplits = false;
- NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
- LocalChildListSplit children(current);
-
- do {
- /* find best child with largest bounding box area */
- size_t bestChild = -1;
- size_t bestSize = 0;
- for (size_t i=0; i<children.size(); i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].size() <= cfg.maxLeafSize && children[i].split.data < Split::SPLIT_ENFORCE && !force_split)
- continue;
-
- force_split = false;
-
- /* remember child with largest size */
- if (children[i].size() > bestSize) {
- bestSize = children[i].size();
- bestChild = i;
- }
- }
- if (bestChild == -1) break;
-
- /* perform best found split */
- BuildRecordSplit& brecord = children[bestChild];
- BuildRecordSplit lrecord(current.depth+1);
- BuildRecordSplit rrecord(current.depth+1);
- std::unique_ptr<mvector<PrimRefMB>> new_vector = split(brecord.split,brecord.prims,lrecord.prims,rrecord.prims);
- hasTimeSplits |= new_vector != nullptr;
-
- /* find new splits */
- lrecord.split = findFallback(lrecord.prims);
- rrecord.split = findFallback(rrecord.prims);
- children.split(bestChild,lrecord,rrecord,std::move(new_vector));
-
- } while (children.size() < cfg.branchingFactor);
-
- /* detect time_ranges that have shrunken */
- for (size_t i=0; i<children.size(); i++) {
- const BBox1f c = children[i].prims.time_range;
- const BBox1f p = in.prims.time_range;
- hasTimeSplits |= c.lower > p.lower || c.upper < p.upper;
- }
-
- /* create node */
- auto node = createNode(children.children.data(),children.numChildren,alloc,hasTimeSplits);
-
- /* recurse into each child and perform reduction */
- LBBox3fa gbounds = empty;
- for (size_t i=0; i<children.size(); i++) {
- values[i] = createLargeLeaf(children[i],alloc);
- gbounds.extend(values[i].lbounds);
- }
-
- setNode(current,children.children.data(),node,values,children.numChildren);
-
- /* calculate geometry bounds of this node */
- if (hasTimeSplits)
- return NodeRecordMB4D(node,current.prims.linearBounds(recalculatePrimRef),current.prims.time_range);
- else
- return NodeRecordMB4D(node,gbounds,current.prims.time_range);
- }
-
- const NodeRecordMB4D recurse(const BuildRecord& current, Allocator alloc, bool toplevel)
- {
- /* get thread local allocator */
- if (!alloc)
- alloc = createAlloc();
-
- /* call memory monitor function to signal progress */
- if (toplevel && current.size() <= cfg.singleThreadThreshold)
- progressMonitor(current.size());
-
- /*! find best split */
- const Split csplit = find(current.prims);
-
- /*! compute leaf and split cost */
- const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.logBlockSize);
- const float splitSAH = cfg.travCost*current.prims.halfArea()+cfg.intCost*csplit.splitSAH();
- assert((current.size() == 0) || ((leafSAH >= 0) && (splitSAH >= 0)));
-
- /*! create a leaf node when threshold reached or SAH tells us to stop */
- if (current.size() <= cfg.minLeafSize || current.depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || (current.size() <= cfg.maxLeafSize && leafSAH <= splitSAH)) {
- current.prims.deterministic_order();
- return createLargeLeaf(current,alloc);
- }
-
- /*! perform initial split */
- SetMB lprims,rprims;
- std::unique_ptr<mvector<PrimRefMB>> new_vector = split(csplit,current.prims,lprims,rprims);
- bool hasTimeSplits = new_vector != nullptr;
- NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
- LocalChildList children(current);
- {
- BuildRecord lrecord(lprims,current.depth+1);
- BuildRecord rrecord(rprims,current.depth+1);
- children.split(0,lrecord,rrecord,std::move(new_vector));
- }
-
- /*! split until node is full or SAH tells us to stop */
- while (children.size() < cfg.branchingFactor)
- {
- /*! find best child to split */
- float bestArea = neg_inf;
- ssize_t bestChild = -1;
- for (size_t i=0; i<children.size(); i++)
- {
- if (children[i].size() <= cfg.minLeafSize) continue;
- if (expectedApproxHalfArea(children[i].prims.geomBounds) > bestArea) {
- bestChild = i; bestArea = expectedApproxHalfArea(children[i].prims.geomBounds);
- }
- }
- if (bestChild == -1) break;
-
- /* perform split */
- BuildRecord& brecord = children[bestChild];
- BuildRecord lrecord(current.depth+1);
- BuildRecord rrecord(current.depth+1);
- Split csplit = find(brecord.prims);
- std::unique_ptr<mvector<PrimRefMB>> new_vector = split(csplit,brecord.prims,lrecord.prims,rrecord.prims);
- hasTimeSplits |= new_vector != nullptr;
- children.split(bestChild,lrecord,rrecord,std::move(new_vector));
- }
-
- /* detect time_ranges that have shrunken */
- for (size_t i=0; i<children.size(); i++) {
- const BBox1f c = children[i].prims.time_range;
- const BBox1f p = current.prims.time_range;
- hasTimeSplits |= c.lower > p.lower || c.upper < p.upper;
- }
-
- /* sort buildrecords for simpler shadow ray traversal */
- //std::sort(&children[0],&children[children.size()],std::greater<BuildRecord>()); // FIXME: reduces traversal performance of bvh8.triangle4 (need to verified) !!
-
- /*! create an inner node */
- auto node = createNode(children.children.data(), children.numChildren, alloc, hasTimeSplits);
- LBBox3fa gbounds = empty;
-
- /* spawn tasks */
- if (unlikely(current.size() > cfg.singleThreadThreshold))
- {
- /*! parallel_for is faster than spawing sub-tasks */
- parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- values[i] = recurse(children[i],nullptr,true);
- _mm_mfence(); // to allow non-temporal stores during build
- }
- });
-
- /*! merge bounding boxes */
- for (size_t i=0; i<children.size(); i++)
- gbounds.extend(values[i].lbounds);
- }
- /* recurse into each child */
- else
- {
- //for (size_t i=0; i<children.size(); i++)
- for (ssize_t i=children.size()-1; i>=0; i--) {
- values[i] = recurse(children[i],alloc,false);
- gbounds.extend(values[i].lbounds);
- }
- }
-
- setNode(current,children.children.data(),node,values,children.numChildren);
-
- /* calculate geometry bounds of this node */
- if (unlikely(hasTimeSplits))
- return NodeRecordMB4D(node,current.prims.linearBounds(recalculatePrimRef),current.prims.time_range);
- else
- return NodeRecordMB4D(node,gbounds,current.prims.time_range);
- }
-
- /*! builder entry function */
- __forceinline const NodeRecordMB4D operator() (mvector<PrimRefMB>& prims, const PrimInfoMB& pinfo)
- {
- const SetMB set(pinfo,&prims);
- auto ret = recurse(BuildRecord(set,1),nullptr,true);
- _mm_mfence(); // to allow non-temporal stores during build
- return ret;
- }
-
- private:
- Settings cfg;
- HeuristicArrayBinningMB<PrimRefMB,MBLUR_NUM_OBJECT_BINS> heuristicObjectSplit;
- HeuristicMBlurTemporalSplit<PrimRefMB,RecalculatePrimRef,MBLUR_NUM_TEMPORAL_BINS> heuristicTemporalSplit;
- const RecalculatePrimRef recalculatePrimRef;
- const CreateAllocFunc createAlloc;
- const CreateNodeFunc createNode;
- const SetNodeFunc setNode;
- const CreateLeafFunc createLeaf;
- const ProgressMonitor progressMonitor;
- };
-
- template<typename NodeRef,
- typename RecalculatePrimRef,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename SetNodeFunc,
- typename CreateLeafFunc,
- typename ProgressMonitorFunc>
-
- static const BVHNodeRecordMB4D<NodeRef> build(mvector<PrimRefMB>& prims,
- const PrimInfoMB& pinfo,
- MemoryMonitorInterface* device,
- const RecalculatePrimRef recalculatePrimRef,
- const CreateAllocFunc createAlloc,
- const CreateNodeFunc createNode,
- const SetNodeFunc setNode,
- const CreateLeafFunc createLeaf,
- const ProgressMonitorFunc progressMonitor,
- const Settings& settings)
- {
- typedef BuilderT<
- NodeRef,
- RecalculatePrimRef,
- decltype(createAlloc()),
- CreateAllocFunc,
- CreateNodeFunc,
- SetNodeFunc,
- CreateLeafFunc,
- ProgressMonitorFunc> Builder;
-
- Builder builder(device,
- recalculatePrimRef,
- createAlloc,
- createNode,
- setNode,
- createLeaf,
- progressMonitor,
- settings);
-
-
- return builder(prims,pinfo);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_msmblur_hair.h b/thirdparty/embree-aarch64/kernels/builders/bvh_builder_msmblur_hair.h
deleted file mode 100644
index e477c313a3..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_msmblur_hair.h
+++ /dev/null
@@ -1,526 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../bvh/bvh.h"
-#include "../geometry/primitive.h"
-#include "../builders/bvh_builder_msmblur.h"
-#include "../builders/heuristic_binning_array_aligned.h"
-#include "../builders/heuristic_binning_array_unaligned.h"
-#include "../builders/heuristic_timesplit_array.h"
-
-namespace embree
-{
- namespace isa
- {
- struct BVHBuilderHairMSMBlur
- {
- /*! settings for msmblur builder */
- struct Settings
- {
- /*! default settings */
- Settings ()
- : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8) {}
-
- public:
- size_t branchingFactor; //!< branching factor of BVH to build
- size_t maxDepth; //!< maximum depth of BVH to build
- size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
- size_t minLeafSize; //!< minimum size of a leaf
- size_t maxLeafSize; //!< maximum size of a leaf
- };
-
- struct BuildRecord
- {
- public:
- __forceinline BuildRecord () {}
-
- __forceinline BuildRecord (size_t depth)
- : depth(depth) {}
-
- __forceinline BuildRecord (const SetMB& prims, size_t depth)
- : depth(depth), prims(prims) {}
-
- __forceinline size_t size() const {
- return prims.size();
- }
-
- public:
- size_t depth; //!< depth of the root of this subtree
- SetMB prims; //!< the list of primitives
- };
-
- template<typename NodeRef,
- typename RecalculatePrimRef,
- typename CreateAllocFunc,
- typename CreateAABBNodeMBFunc,
- typename SetAABBNodeMBFunc,
- typename CreateOBBNodeMBFunc,
- typename SetOBBNodeMBFunc,
- typename CreateLeafFunc,
- typename ProgressMonitor>
-
- class BuilderT
- {
- ALIGNED_CLASS_(16);
-
- static const size_t MAX_BRANCHING_FACTOR = 8; //!< maximum supported BVH branching factor
- static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree if we are that many levels before the maximum tree depth
- static const size_t SINGLE_THREADED_THRESHOLD = 4096; //!< threshold to switch to single threaded build
-
- typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
- typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
-
- typedef FastAllocator::CachedAllocator Allocator;
- typedef LocalChildListT<BuildRecord,MAX_BRANCHING_FACTOR> LocalChildList;
-
- typedef HeuristicMBlurTemporalSplit<PrimRefMB,RecalculatePrimRef,MBLUR_NUM_TEMPORAL_BINS> HeuristicTemporal;
- typedef HeuristicArrayBinningMB<PrimRefMB,MBLUR_NUM_OBJECT_BINS> HeuristicBinning;
- typedef UnalignedHeuristicArrayBinningMB<PrimRefMB,MBLUR_NUM_OBJECT_BINS> UnalignedHeuristicBinning;
-
- public:
-
- BuilderT (Scene* scene,
- const RecalculatePrimRef& recalculatePrimRef,
- const CreateAllocFunc& createAlloc,
- const CreateAABBNodeMBFunc& createAABBNodeMB,
- const SetAABBNodeMBFunc& setAABBNodeMB,
- const CreateOBBNodeMBFunc& createOBBNodeMB,
- const SetOBBNodeMBFunc& setOBBNodeMB,
- const CreateLeafFunc& createLeaf,
- const ProgressMonitor& progressMonitor,
- const Settings settings)
-
- : cfg(settings),
- scene(scene),
- recalculatePrimRef(recalculatePrimRef),
- createAlloc(createAlloc),
- createAABBNodeMB(createAABBNodeMB), setAABBNodeMB(setAABBNodeMB),
- createOBBNodeMB(createOBBNodeMB), setOBBNodeMB(setOBBNodeMB),
- createLeaf(createLeaf),
- progressMonitor(progressMonitor),
- unalignedHeuristic(scene),
- temporalSplitHeuristic(scene->device,recalculatePrimRef) {}
-
- private:
-
- /*! checks if all primitives are from the same geometry */
- __forceinline bool sameGeometry(const SetMB& set)
- {
- mvector<PrimRefMB>& prims = *set.prims;
- unsigned int firstGeomID = prims[set.begin()].geomID();
- for (size_t i=set.begin()+1; i<set.end(); i++) {
- if (prims[i].geomID() != firstGeomID){
- return false;
- }
- }
- return true;
- }
-
- /*! performs some split if SAH approaches fail */
- void splitFallback(const SetMB& set, SetMB& lset, SetMB& rset)
- {
- mvector<PrimRefMB>& prims = *set.prims;
-
- const size_t begin = set.begin();
- const size_t end = set.end();
- const size_t center = (begin + end)/2;
-
- PrimInfoMB linfo = empty;
- for (size_t i=begin; i<center; i++)
- linfo.add_primref(prims[i]);
-
- PrimInfoMB rinfo = empty;
- for (size_t i=center; i<end; i++)
- rinfo.add_primref(prims[i]);
-
- new (&lset) SetMB(linfo,set.prims,range<size_t>(begin,center),set.time_range);
- new (&rset) SetMB(rinfo,set.prims,range<size_t>(center,end ),set.time_range);
- }
-
- void splitByGeometry(const SetMB& set, SetMB& lset, SetMB& rset)
- {
- assert(set.size() > 1);
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfoMB linfo(empty);
- PrimInfoMB rinfo(empty);
- unsigned int geomID = (*set.prims)[begin].geomID();
- size_t center = serial_partitioning(set.prims->data(),begin,end,linfo,rinfo,
- [&] ( const PrimRefMB& prim ) { return prim.geomID() == geomID; },
- [ ] ( PrimInfoMB& a, const PrimRefMB& ref ) { a.add_primref(ref); });
-
- new (&lset) SetMB(linfo,set.prims,range<size_t>(begin,center),set.time_range);
- new (&rset) SetMB(rinfo,set.prims,range<size_t>(center,end ),set.time_range);
- }
-
- /*! creates a large leaf that could be larger than supported by the BVH */
- NodeRecordMB4D createLargeLeaf(BuildRecord& current, Allocator alloc)
- {
- /* this should never occur but is a fatal error */
- if (current.depth > cfg.maxDepth)
- throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
-
- /* special case when directly creating leaf without any splits that could shrink time_range */
- bool force_split = false;
- if (current.depth == 1 && current.size() > 0)
- {
- BBox1f c = empty;
- BBox1f p = current.prims.time_range;
- for (size_t i=current.prims.begin(); i<current.prims.end(); i++) {
- mvector<PrimRefMB>& prims = *current.prims.prims;
- c.extend(prims[i].time_range);
- }
-
- force_split = c.lower > p.lower || c.upper < p.upper;
- }
-
- /* create leaf for few primitives */
- if (current.size() <= cfg.maxLeafSize && sameGeometry(current.prims) && !force_split)
- return createLeaf(current.prims,alloc);
-
- /* fill all children by always splitting the largest one */
- LocalChildList children(current);
- NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
-
- do {
-
- /* find best child with largest bounding box area */
- int bestChild = -1;
- size_t bestSize = 0;
- for (unsigned i=0; i<children.size(); i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].size() <= cfg.maxLeafSize && sameGeometry(children[i].prims) && !force_split)
- continue;
-
- force_split = false;
-
- /* remember child with largest size */
- if (children[i].size() > bestSize) {
- bestSize = children[i].size();
- bestChild = i;
- }
- }
- if (bestChild == -1) break;
-
- /*! split best child into left and right child */
- BuildRecord left(current.depth+1);
- BuildRecord right(current.depth+1);
- if (!sameGeometry(children[bestChild].prims)) {
- splitByGeometry(children[bestChild].prims,left.prims,right.prims);
- } else {
- splitFallback(children[bestChild].prims,left.prims,right.prims);
- }
- children.split(bestChild,left,right,std::unique_ptr<mvector<PrimRefMB>>());
-
- } while (children.size() < cfg.branchingFactor);
-
-
- /* detect time_ranges that have shrunken */
- bool timesplit = false;
- for (size_t i=0; i<children.size(); i++) {
- const BBox1f c = children[i].prims.time_range;
- const BBox1f p = current.prims.time_range;
- timesplit |= c.lower > p.lower || c.upper < p.upper;
- }
-
- /* create node */
- NodeRef node = createAABBNodeMB(children.children.data(),children.numChildren,alloc,timesplit);
-
- LBBox3fa bounds = empty;
- for (size_t i=0; i<children.size(); i++) {
- values[i] = createLargeLeaf(children[i],alloc);
- bounds.extend(values[i].lbounds);
- }
-
- setAABBNodeMB(current,children.children.data(),node,values,children.numChildren);
-
- if (timesplit)
- bounds = current.prims.linearBounds(recalculatePrimRef);
-
- return NodeRecordMB4D(node,bounds,current.prims.time_range);
- }
-
- /*! performs split */
- std::unique_ptr<mvector<PrimRefMB>> split(const BuildRecord& current, BuildRecord& lrecord, BuildRecord& rrecord, bool& aligned, bool& timesplit)
- {
- /* variable to track the SAH of the best splitting approach */
- float bestSAH = inf;
- const float leafSAH = current.prims.leafSAH(cfg.logBlockSize);
-
- /* perform standard binning in aligned space */
- HeuristicBinning::Split alignedObjectSplit = alignedHeuristic.find(current.prims,cfg.logBlockSize);
- float alignedObjectSAH = alignedObjectSplit.splitSAH();
- bestSAH = min(alignedObjectSAH,bestSAH);
-
- /* perform standard binning in unaligned space */
- UnalignedHeuristicBinning::Split unalignedObjectSplit;
- LinearSpace3fa uspace;
- float unalignedObjectSAH = inf;
- if (alignedObjectSAH > 0.7f*leafSAH) {
- uspace = unalignedHeuristic.computeAlignedSpaceMB(scene,current.prims);
- const SetMB sset = current.prims.primInfo(recalculatePrimRef,uspace);
- unalignedObjectSplit = unalignedHeuristic.find(sset,cfg.logBlockSize,uspace);
- unalignedObjectSAH = 1.3f*unalignedObjectSplit.splitSAH(); // makes unaligned splits more expensive
- bestSAH = min(unalignedObjectSAH,bestSAH);
- }
-
- /* do temporal splits only if previous approaches failed to produce good SAH and the the time range is large enough */
- float temporal_split_sah = inf;
- typename HeuristicTemporal::Split temporal_split;
- if (bestSAH > 0.5f*leafSAH) {
- if (current.prims.time_range.size() > 1.01f/float(current.prims.max_num_time_segments)) {
- temporal_split = temporalSplitHeuristic.find(current.prims,cfg.logBlockSize);
- temporal_split_sah = temporal_split.splitSAH();
- bestSAH = min(temporal_split_sah,bestSAH);
- }
- }
-
- /* perform fallback split if SAH heuristics failed */
- if (unlikely(!std::isfinite(bestSAH))) {
- current.prims.deterministic_order();
- splitFallback(current.prims,lrecord.prims,rrecord.prims);
- }
- /* perform aligned split if this is best */
- else if (likely(bestSAH == alignedObjectSAH)) {
- alignedHeuristic.split(alignedObjectSplit,current.prims,lrecord.prims,rrecord.prims);
- }
- /* perform unaligned split if this is best */
- else if (likely(bestSAH == unalignedObjectSAH)) {
- unalignedHeuristic.split(unalignedObjectSplit,uspace,current.prims,lrecord.prims,rrecord.prims);
- aligned = false;
- }
- /* perform temporal split if this is best */
- else if (likely(bestSAH == temporal_split_sah)) {
- timesplit = true;
- return temporalSplitHeuristic.split(temporal_split,current.prims,lrecord.prims,rrecord.prims);
- }
- else
- assert(false);
-
- return std::unique_ptr<mvector<PrimRefMB>>();
- }
-
- /*! recursive build */
- NodeRecordMB4D recurse(BuildRecord& current, Allocator alloc, bool toplevel)
- {
- /* get thread local allocator */
- if (!alloc)
- alloc = createAlloc();
-
- /* call memory monitor function to signal progress */
- if (toplevel && current.size() <= SINGLE_THREADED_THRESHOLD)
- progressMonitor(current.size());
-
- /* create leaf node */
- if (current.depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || current.size() <= cfg.minLeafSize) {
- current.prims.deterministic_order();
- return createLargeLeaf(current,alloc);
- }
-
- /* fill all children by always splitting the one with the largest surface area */
- NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
- LocalChildList children(current);
- bool aligned = true;
- bool timesplit = false;
-
- do {
-
- /* find best child with largest bounding box area */
- ssize_t bestChild = -1;
- float bestArea = neg_inf;
- for (size_t i=0; i<children.size(); i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].size() <= cfg.minLeafSize)
- continue;
-
- /* remember child with largest area */
- const float A = children[i].prims.halfArea();
- if (A > bestArea) {
- bestArea = children[i].prims.halfArea();
- bestChild = i;
- }
- }
- if (bestChild == -1) break;
-
- /*! split best child into left and right child */
- BuildRecord left(current.depth+1);
- BuildRecord right(current.depth+1);
- std::unique_ptr<mvector<PrimRefMB>> new_vector = split(children[bestChild],left,right,aligned,timesplit);
- children.split(bestChild,left,right,std::move(new_vector));
-
- } while (children.size() < cfg.branchingFactor);
-
- /* detect time_ranges that have shrunken */
- for (size_t i=0; i<children.size(); i++) {
- const BBox1f c = children[i].prims.time_range;
- const BBox1f p = current.prims.time_range;
- timesplit |= c.lower > p.lower || c.upper < p.upper;
- }
-
- /* create time split node */
- if (timesplit)
- {
- const NodeRef node = createAABBNodeMB(children.children.data(),children.numChildren,alloc,true);
-
- /* spawn tasks or ... */
- if (current.size() > SINGLE_THREADED_THRESHOLD)
- {
- parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- values[i] = recurse(children[i],nullptr,true);
- _mm_mfence(); // to allow non-temporal stores during build
- }
- });
- }
- /* ... continue sequential */
- else {
- for (size_t i=0; i<children.size(); i++) {
- values[i] = recurse(children[i],alloc,false);
- }
- }
-
- setAABBNodeMB(current,children.children.data(),node,values,children.numChildren);
-
- const LBBox3fa bounds = current.prims.linearBounds(recalculatePrimRef);
- return NodeRecordMB4D(node,bounds,current.prims.time_range);
- }
-
- /* create aligned node */
- else if (aligned)
- {
- const NodeRef node = createAABBNodeMB(children.children.data(),children.numChildren,alloc,true);
-
- /* spawn tasks or ... */
- if (current.size() > SINGLE_THREADED_THRESHOLD)
- {
- LBBox3fa cbounds[MAX_BRANCHING_FACTOR];
- parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- values[i] = recurse(children[i],nullptr,true);
- cbounds[i] = values[i].lbounds;
- _mm_mfence(); // to allow non-temporal stores during build
- }
- });
-
- LBBox3fa bounds = empty;
- for (size_t i=0; i<children.size(); i++)
- bounds.extend(cbounds[i]);
- setAABBNodeMB(current,children.children.data(),node,values,children.numChildren);
- return NodeRecordMB4D(node,bounds,current.prims.time_range);
- }
- /* ... continue sequentially */
- else
- {
- LBBox3fa bounds = empty;
- for (size_t i=0; i<children.size(); i++) {
- values[i] = recurse(children[i],alloc,false);
- bounds.extend(values[i].lbounds);
- }
- setAABBNodeMB(current,children.children.data(),node,values,children.numChildren);
- return NodeRecordMB4D(node,bounds,current.prims.time_range);
- }
- }
-
- /* create unaligned node */
- else
- {
- const NodeRef node = createOBBNodeMB(alloc);
-
- /* spawn tasks or ... */
- if (current.size() > SINGLE_THREADED_THRESHOLD)
- {
- parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpaceMB(scene,children[i].prims);
- const LBBox3fa lbounds = children[i].prims.linearBounds(recalculatePrimRef,space);
- const auto child = recurse(children[i],nullptr,true);
- setOBBNodeMB(node,i,child.ref,space,lbounds,children[i].prims.time_range);
- _mm_mfence(); // to allow non-temporal stores during build
- }
- });
- }
- /* ... continue sequentially */
- else
- {
- for (size_t i=0; i<children.size(); i++) {
- const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpaceMB(scene,children[i].prims);
- const LBBox3fa lbounds = children[i].prims.linearBounds(recalculatePrimRef,space);
- const auto child = recurse(children[i],alloc,false);
- setOBBNodeMB(node,i,child.ref,space,lbounds,children[i].prims.time_range);
- }
- }
-
- const LBBox3fa bounds = current.prims.linearBounds(recalculatePrimRef);
- return NodeRecordMB4D(node,bounds,current.prims.time_range);
- }
- }
-
- public:
-
- /*! entry point into builder */
- NodeRecordMB4D operator() (mvector<PrimRefMB>& prims, const PrimInfoMB& pinfo)
- {
- BuildRecord record(SetMB(pinfo,&prims),1);
- auto root = recurse(record,nullptr,true);
- _mm_mfence(); // to allow non-temporal stores during build
- return root;
- }
-
- private:
- Settings cfg;
- Scene* scene;
- const RecalculatePrimRef& recalculatePrimRef;
- const CreateAllocFunc& createAlloc;
- const CreateAABBNodeMBFunc& createAABBNodeMB;
- const SetAABBNodeMBFunc& setAABBNodeMB;
- const CreateOBBNodeMBFunc& createOBBNodeMB;
- const SetOBBNodeMBFunc& setOBBNodeMB;
- const CreateLeafFunc& createLeaf;
- const ProgressMonitor& progressMonitor;
-
- private:
- HeuristicBinning alignedHeuristic;
- UnalignedHeuristicBinning unalignedHeuristic;
- HeuristicTemporal temporalSplitHeuristic;
- };
-
- template<typename NodeRef,
- typename RecalculatePrimRef,
- typename CreateAllocFunc,
- typename CreateAABBNodeMBFunc,
- typename SetAABBNodeMBFunc,
- typename CreateOBBNodeMBFunc,
- typename SetOBBNodeMBFunc,
- typename CreateLeafFunc,
- typename ProgressMonitor>
-
- static BVHNodeRecordMB4D<NodeRef> build (Scene* scene, mvector<PrimRefMB>& prims, const PrimInfoMB& pinfo,
- const RecalculatePrimRef& recalculatePrimRef,
- const CreateAllocFunc& createAlloc,
- const CreateAABBNodeMBFunc& createAABBNodeMB,
- const SetAABBNodeMBFunc& setAABBNodeMB,
- const CreateOBBNodeMBFunc& createOBBNodeMB,
- const SetOBBNodeMBFunc& setOBBNodeMB,
- const CreateLeafFunc& createLeaf,
- const ProgressMonitor& progressMonitor,
- const Settings settings)
- {
- typedef BuilderT<NodeRef,RecalculatePrimRef,CreateAllocFunc,
- CreateAABBNodeMBFunc,SetAABBNodeMBFunc,
- CreateOBBNodeMBFunc,SetOBBNodeMBFunc,
- CreateLeafFunc,ProgressMonitor> Builder;
-
- Builder builder(scene,recalculatePrimRef,createAlloc,
- createAABBNodeMB,setAABBNodeMB,
- createOBBNodeMB,setOBBNodeMB,
- createLeaf,progressMonitor,settings);
-
- return builder(prims,pinfo);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_sah.h b/thirdparty/embree-aarch64/kernels/builders/bvh_builder_sah.h
deleted file mode 100644
index 3f7e678a10..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/bvh_builder_sah.h
+++ /dev/null
@@ -1,669 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "heuristic_binning_array_aligned.h"
-#include "heuristic_spatial_array.h"
-#include "heuristic_openmerge_array.h"
-
-#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
-# define NUM_OBJECT_BINS 16
-# define NUM_SPATIAL_BINS 16
-#else
-# define NUM_OBJECT_BINS 32
-# define NUM_SPATIAL_BINS 16
-#endif
-
-namespace embree
-{
- namespace isa
- {
- MAYBE_UNUSED static const float travCost = 1.0f;
- MAYBE_UNUSED static const size_t DEFAULT_SINGLE_THREAD_THRESHOLD = 1024;
-
- struct GeneralBVHBuilder
- {
- static const size_t MAX_BRANCHING_FACTOR = 16; //!< maximum supported BVH branching factor
- static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree of we are that many levels before the maximum tree depth
-
-
- /*! settings for SAH builder */
- struct Settings
- {
- /*! default settings */
- Settings ()
- : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(7),
- travCost(1.0f), intCost(1.0f), singleThreadThreshold(1024), primrefarrayalloc(inf) {}
-
- /*! initialize settings from API settings */
- Settings (const RTCBuildArguments& settings)
- : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(7),
- travCost(1.0f), intCost(1.0f), singleThreadThreshold(1024), primrefarrayalloc(inf)
- {
- if (RTC_BUILD_ARGUMENTS_HAS(settings,maxBranchingFactor)) branchingFactor = settings.maxBranchingFactor;
- if (RTC_BUILD_ARGUMENTS_HAS(settings,maxDepth )) maxDepth = settings.maxDepth;
- if (RTC_BUILD_ARGUMENTS_HAS(settings,sahBlockSize )) logBlockSize = bsr(static_cast<size_t>(settings.sahBlockSize));
- if (RTC_BUILD_ARGUMENTS_HAS(settings,minLeafSize )) minLeafSize = settings.minLeafSize;
- if (RTC_BUILD_ARGUMENTS_HAS(settings,maxLeafSize )) maxLeafSize = settings.maxLeafSize;
- if (RTC_BUILD_ARGUMENTS_HAS(settings,traversalCost )) travCost = settings.traversalCost;
- if (RTC_BUILD_ARGUMENTS_HAS(settings,intersectionCost )) intCost = settings.intersectionCost;
-
- minLeafSize = min(minLeafSize,maxLeafSize);
- }
-
- Settings (size_t sahBlockSize, size_t minLeafSize, size_t maxLeafSize, float travCost, float intCost, size_t singleThreadThreshold, size_t primrefarrayalloc = inf)
- : branchingFactor(2), maxDepth(32), logBlockSize(bsr(sahBlockSize)), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize),
- travCost(travCost), intCost(intCost), singleThreadThreshold(singleThreadThreshold), primrefarrayalloc(primrefarrayalloc)
- {
- minLeafSize = min(minLeafSize,maxLeafSize);
- }
-
- public:
- size_t branchingFactor; //!< branching factor of BVH to build
- size_t maxDepth; //!< maximum depth of BVH to build
- size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
- size_t minLeafSize; //!< minimum size of a leaf
- size_t maxLeafSize; //!< maximum size of a leaf
- float travCost; //!< estimated cost of one traversal step
- float intCost; //!< estimated cost of one primitive intersection
- size_t singleThreadThreshold; //!< threshold when we switch to single threaded build
- size_t primrefarrayalloc; //!< builder uses prim ref array to allocate nodes and leaves when a subtree of that size is finished
- };
-
- /*! recursive state of builder */
- template<typename Set, typename Split>
- struct BuildRecordT
- {
- public:
- __forceinline BuildRecordT () {}
-
- __forceinline BuildRecordT (size_t depth)
- : depth(depth), alloc_barrier(false), prims(empty) {}
-
- __forceinline BuildRecordT (size_t depth, const Set& prims)
- : depth(depth), alloc_barrier(false), prims(prims) {}
-
- __forceinline BBox3fa bounds() const { return prims.geomBounds; }
-
- __forceinline friend bool operator< (const BuildRecordT& a, const BuildRecordT& b) { return a.prims.size() < b.prims.size(); }
- __forceinline friend bool operator> (const BuildRecordT& a, const BuildRecordT& b) { return a.prims.size() > b.prims.size(); }
-
- __forceinline size_t size() const { return prims.size(); }
-
- public:
- size_t depth; //!< Depth of the root of this subtree.
- bool alloc_barrier; //!< barrier used to reuse primref-array blocks to allocate nodes
- Set prims; //!< The list of primitives.
- };
-
- template<typename PrimRef, typename Set>
- struct DefaultCanCreateLeafFunc
- {
- __forceinline bool operator()(const PrimRef*, const Set&) const { return true; }
- };
-
- template<typename PrimRef, typename Set>
- struct DefaultCanCreateLeafSplitFunc
- {
- __forceinline void operator()(PrimRef*, const Set&, Set&, Set&) const { }
- };
-
- template<typename BuildRecord,
- typename Heuristic,
- typename Set,
- typename PrimRef,
- typename ReductionTy,
- typename Allocator,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename UpdateNodeFunc,
- typename CreateLeafFunc,
- typename CanCreateLeafFunc,
- typename CanCreateLeafSplitFunc,
- typename ProgressMonitor>
-
- class BuilderT
- {
- friend struct GeneralBVHBuilder;
-
- BuilderT (PrimRef* prims,
- Heuristic& heuristic,
- const CreateAllocFunc& createAlloc,
- const CreateNodeFunc& createNode,
- const UpdateNodeFunc& updateNode,
- const CreateLeafFunc& createLeaf,
- const CanCreateLeafFunc& canCreateLeaf,
- const CanCreateLeafSplitFunc& canCreateLeafSplit,
- const ProgressMonitor& progressMonitor,
- const Settings& settings) :
- cfg(settings),
- prims(prims),
- heuristic(heuristic),
- createAlloc(createAlloc),
- createNode(createNode),
- updateNode(updateNode),
- createLeaf(createLeaf),
- canCreateLeaf(canCreateLeaf),
- canCreateLeafSplit(canCreateLeafSplit),
- progressMonitor(progressMonitor)
- {
- if (cfg.branchingFactor > MAX_BRANCHING_FACTOR)
- throw_RTCError(RTC_ERROR_UNKNOWN,"bvh_builder: branching factor too large");
- }
-
- const ReductionTy createLargeLeaf(const BuildRecord& current, Allocator alloc)
- {
- /* this should never occur but is a fatal error */
- if (current.depth > cfg.maxDepth)
- throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
-
- /* create leaf for few primitives */
- if (current.prims.size() <= cfg.maxLeafSize && canCreateLeaf(prims,current.prims))
- return createLeaf(prims,current.prims,alloc);
-
- /* fill all children by always splitting the largest one */
- ReductionTy values[MAX_BRANCHING_FACTOR];
- BuildRecord children[MAX_BRANCHING_FACTOR];
- size_t numChildren = 1;
- children[0] = current;
- do {
-
- /* find best child with largest bounding box area */
- size_t bestChild = -1;
- size_t bestSize = 0;
- for (size_t i=0; i<numChildren; i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].prims.size() <= cfg.maxLeafSize && canCreateLeaf(prims,children[i].prims))
- continue;
-
- /* remember child with largest size */
- if (children[i].prims.size() > bestSize) {
- bestSize = children[i].prims.size();
- bestChild = i;
- }
- }
- if (bestChild == (size_t)-1) break;
-
- /*! split best child into left and right child */
- BuildRecord left(current.depth+1);
- BuildRecord right(current.depth+1);
- if (!canCreateLeaf(prims,children[bestChild].prims)) {
- canCreateLeafSplit(prims,children[bestChild].prims,left.prims,right.prims);
- } else {
- heuristic.splitFallback(children[bestChild].prims,left.prims,right.prims);
- }
-
- /* add new children left and right */
- children[bestChild] = children[numChildren-1];
- children[numChildren-1] = left;
- children[numChildren+0] = right;
- numChildren++;
-
- } while (numChildren < cfg.branchingFactor);
-
- /* set barrier for primrefarrayalloc */
- if (unlikely(current.size() > cfg.primrefarrayalloc))
- for (size_t i=0; i<numChildren; i++)
- children[i].alloc_barrier = children[i].size() <= cfg.primrefarrayalloc;
-
- /* create node */
- auto node = createNode(children,numChildren,alloc);
-
- /* recurse into each child and perform reduction */
- for (size_t i=0; i<numChildren; i++)
- values[i] = createLargeLeaf(children[i],alloc);
-
- /* perform reduction */
- return updateNode(current,children,node,values,numChildren);
- }
-
- const ReductionTy recurse(BuildRecord& current, Allocator alloc, bool toplevel)
- {
- /* get thread local allocator */
- if (!alloc)
- alloc = createAlloc();
-
- /* call memory monitor function to signal progress */
- if (toplevel && current.size() <= cfg.singleThreadThreshold)
- progressMonitor(current.size());
-
- /*! find best split */
- auto split = heuristic.find(current.prims,cfg.logBlockSize);
-
- /*! compute leaf and split cost */
- const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.logBlockSize);
- const float splitSAH = cfg.travCost*halfArea(current.prims.geomBounds)+cfg.intCost*split.splitSAH();
- assert((current.prims.size() == 0) || ((leafSAH >= 0) && (splitSAH >= 0)));
-
- /*! create a leaf node when threshold reached or SAH tells us to stop */
- if (current.prims.size() <= cfg.minLeafSize || current.depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || (current.prims.size() <= cfg.maxLeafSize && leafSAH <= splitSAH)) {
- heuristic.deterministic_order(current.prims);
- return createLargeLeaf(current,alloc);
- }
-
- /*! perform initial split */
- Set lprims,rprims;
- heuristic.split(split,current.prims,lprims,rprims);
-
- /*! initialize child list with initial split */
- ReductionTy values[MAX_BRANCHING_FACTOR];
- BuildRecord children[MAX_BRANCHING_FACTOR];
- children[0] = BuildRecord(current.depth+1,lprims);
- children[1] = BuildRecord(current.depth+1,rprims);
- size_t numChildren = 2;
-
- /*! split until node is full or SAH tells us to stop */
- while (numChildren < cfg.branchingFactor)
- {
- /*! find best child to split */
- float bestArea = neg_inf;
- ssize_t bestChild = -1;
- for (size_t i=0; i<numChildren; i++)
- {
- /* ignore leaves as they cannot get split */
- if (children[i].prims.size() <= cfg.minLeafSize) continue;
-
- /* find child with largest surface area */
- if (halfArea(children[i].prims.geomBounds) > bestArea) {
- bestChild = i;
- bestArea = halfArea(children[i].prims.geomBounds);
- }
- }
- if (bestChild == -1) break;
-
- /* perform best found split */
- BuildRecord& brecord = children[bestChild];
- BuildRecord lrecord(current.depth+1);
- BuildRecord rrecord(current.depth+1);
- auto split = heuristic.find(brecord.prims,cfg.logBlockSize);
- heuristic.split(split,brecord.prims,lrecord.prims,rrecord.prims);
- children[bestChild ] = lrecord;
- children[numChildren] = rrecord;
- numChildren++;
- }
-
- /* set barrier for primrefarrayalloc */
- if (unlikely(current.size() > cfg.primrefarrayalloc))
- for (size_t i=0; i<numChildren; i++)
- children[i].alloc_barrier = children[i].size() <= cfg.primrefarrayalloc;
-
- /* sort buildrecords for faster shadow ray traversal */
- std::sort(&children[0],&children[numChildren],std::greater<BuildRecord>());
-
- /*! create an inner node */
- auto node = createNode(children,numChildren,alloc);
-
- /* spawn tasks */
- if (current.size() > cfg.singleThreadThreshold)
- {
- /*! parallel_for is faster than spawing sub-tasks */
- parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) { // FIXME: no range here
- for (size_t i=r.begin(); i<r.end(); i++) {
- values[i] = recurse(children[i],nullptr,true);
- _mm_mfence(); // to allow non-temporal stores during build
- }
- });
-
- return updateNode(current,children,node,values,numChildren);
- }
- /* recurse into each child */
- else
- {
- for (size_t i=0; i<numChildren; i++)
- values[i] = recurse(children[i],alloc,false);
-
- return updateNode(current,children,node,values,numChildren);
- }
- }
-
- private:
- Settings cfg;
- PrimRef* prims;
- Heuristic& heuristic;
- const CreateAllocFunc& createAlloc;
- const CreateNodeFunc& createNode;
- const UpdateNodeFunc& updateNode;
- const CreateLeafFunc& createLeaf;
- const CanCreateLeafFunc& canCreateLeaf;
- const CanCreateLeafSplitFunc& canCreateLeafSplit;
- const ProgressMonitor& progressMonitor;
- };
-
- template<
- typename ReductionTy,
- typename Heuristic,
- typename Set,
- typename PrimRef,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename UpdateNodeFunc,
- typename CreateLeafFunc,
- typename ProgressMonitor>
-
- __noinline static ReductionTy build(Heuristic& heuristic,
- PrimRef* prims,
- const Set& set,
- CreateAllocFunc createAlloc,
- CreateNodeFunc createNode, UpdateNodeFunc updateNode,
- const CreateLeafFunc& createLeaf,
- const ProgressMonitor& progressMonitor,
- const Settings& settings)
- {
- typedef BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
-
- typedef BuilderT<
- BuildRecord,
- Heuristic,
- Set,
- PrimRef,
- ReductionTy,
- decltype(createAlloc()),
- CreateAllocFunc,
- CreateNodeFunc,
- UpdateNodeFunc,
- CreateLeafFunc,
- DefaultCanCreateLeafFunc<PrimRef, Set>,
- DefaultCanCreateLeafSplitFunc<PrimRef, Set>,
- ProgressMonitor> Builder;
-
- /* instantiate builder */
- Builder builder(prims,
- heuristic,
- createAlloc,
- createNode,
- updateNode,
- createLeaf,
- DefaultCanCreateLeafFunc<PrimRef, Set>(),
- DefaultCanCreateLeafSplitFunc<PrimRef, Set>(),
- progressMonitor,
- settings);
-
- /* build hierarchy */
- BuildRecord record(1,set);
- const ReductionTy root = builder.recurse(record,nullptr,true);
- _mm_mfence(); // to allow non-temporal stores during build
- return root;
- }
-
- template<
- typename ReductionTy,
- typename Heuristic,
- typename Set,
- typename PrimRef,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename UpdateNodeFunc,
- typename CreateLeafFunc,
- typename CanCreateLeafFunc,
- typename CanCreateLeafSplitFunc,
- typename ProgressMonitor>
-
- __noinline static ReductionTy build(Heuristic& heuristic,
- PrimRef* prims,
- const Set& set,
- CreateAllocFunc createAlloc,
- CreateNodeFunc createNode, UpdateNodeFunc updateNode,
- const CreateLeafFunc& createLeaf,
- const CanCreateLeafFunc& canCreateLeaf,
- const CanCreateLeafSplitFunc& canCreateLeafSplit,
- const ProgressMonitor& progressMonitor,
- const Settings& settings)
- {
- typedef BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
-
- typedef BuilderT<
- BuildRecord,
- Heuristic,
- Set,
- PrimRef,
- ReductionTy,
- decltype(createAlloc()),
- CreateAllocFunc,
- CreateNodeFunc,
- UpdateNodeFunc,
- CreateLeafFunc,
- CanCreateLeafFunc,
- CanCreateLeafSplitFunc,
- ProgressMonitor> Builder;
-
- /* instantiate builder */
- Builder builder(prims,
- heuristic,
- createAlloc,
- createNode,
- updateNode,
- createLeaf,
- canCreateLeaf,
- canCreateLeafSplit,
- progressMonitor,
- settings);
-
- /* build hierarchy */
- BuildRecord record(1,set);
- const ReductionTy root = builder.recurse(record,nullptr,true);
- _mm_mfence(); // to allow non-temporal stores during build
- return root;
- }
- };
-
- /* SAH builder that operates on an array of BuildRecords */
- struct BVHBuilderBinnedSAH
- {
- typedef PrimInfoRange Set;
- typedef HeuristicArrayBinningSAH<PrimRef,NUM_OBJECT_BINS> Heuristic;
- typedef GeneralBVHBuilder::BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
- typedef GeneralBVHBuilder::Settings Settings;
-
- /*! special builder that propagates reduction over the tree */
- template<
- typename ReductionTy,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename UpdateNodeFunc,
- typename CreateLeafFunc,
- typename ProgressMonitor>
-
- static ReductionTy build(CreateAllocFunc createAlloc,
- CreateNodeFunc createNode, UpdateNodeFunc updateNode,
- const CreateLeafFunc& createLeaf,
- const ProgressMonitor& progressMonitor,
- PrimRef* prims, const PrimInfo& pinfo,
- const Settings& settings)
- {
- Heuristic heuristic(prims);
- return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
- heuristic,
- prims,
- PrimInfoRange(0,pinfo.size(),pinfo),
- createAlloc,
- createNode,
- updateNode,
- createLeaf,
- progressMonitor,
- settings);
- }
-
- /*! special builder that propagates reduction over the tree */
- template<
- typename ReductionTy,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename UpdateNodeFunc,
- typename CreateLeafFunc,
- typename CanCreateLeafFunc,
- typename CanCreateLeafSplitFunc,
- typename ProgressMonitor>
-
- static ReductionTy build(CreateAllocFunc createAlloc,
- CreateNodeFunc createNode, UpdateNodeFunc updateNode,
- const CreateLeafFunc& createLeaf,
- const CanCreateLeafFunc& canCreateLeaf,
- const CanCreateLeafSplitFunc& canCreateLeafSplit,
- const ProgressMonitor& progressMonitor,
- PrimRef* prims, const PrimInfo& pinfo,
- const Settings& settings)
- {
- Heuristic heuristic(prims);
- return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
- heuristic,
- prims,
- PrimInfoRange(0,pinfo.size(),pinfo),
- createAlloc,
- createNode,
- updateNode,
- createLeaf,
- canCreateLeaf,
- canCreateLeafSplit,
- progressMonitor,
- settings);
- }
- };
-
- /* Spatial SAH builder that operates on an double-buffered array of BuildRecords */
- struct BVHBuilderBinnedFastSpatialSAH
- {
- typedef PrimInfoExtRange Set;
- typedef Split2<BinSplit<NUM_OBJECT_BINS>,SpatialBinSplit<NUM_SPATIAL_BINS> > Split;
- typedef GeneralBVHBuilder::BuildRecordT<Set,Split> BuildRecord;
- typedef GeneralBVHBuilder::Settings Settings;
-
- static const unsigned int GEOMID_MASK = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
- static const unsigned int SPLITS_MASK = 0xFFFFFFFF << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
-
- template<typename ReductionTy, typename UserCreateLeaf>
- struct CreateLeafExt
- {
- __forceinline CreateLeafExt (const UserCreateLeaf userCreateLeaf)
- : userCreateLeaf(userCreateLeaf) {}
-
- // __noinline is workaround for ICC2016 compiler bug
- template<typename Allocator>
- __noinline ReductionTy operator() (PrimRef* prims, const range<size_t>& range, Allocator alloc) const
- {
- for (size_t i=range.begin(); i<range.end(); i++)
- prims[i].lower.u &= GEOMID_MASK;
-
- return userCreateLeaf(prims,range,alloc);
- }
-
- const UserCreateLeaf userCreateLeaf;
- };
-
- /*! special builder that propagates reduction over the tree */
- template<
- typename ReductionTy,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename UpdateNodeFunc,
- typename CreateLeafFunc,
- typename SplitPrimitiveFunc,
- typename ProgressMonitor>
-
- static ReductionTy build(CreateAllocFunc createAlloc,
- CreateNodeFunc createNode,
- UpdateNodeFunc updateNode,
- const CreateLeafFunc& createLeaf,
- SplitPrimitiveFunc splitPrimitive,
- ProgressMonitor progressMonitor,
- PrimRef* prims,
- const size_t extSize,
- const PrimInfo& pinfo,
- const Settings& settings)
- {
- typedef HeuristicArraySpatialSAH<SplitPrimitiveFunc,PrimRef,NUM_OBJECT_BINS,NUM_SPATIAL_BINS> Heuristic;
- Heuristic heuristic(splitPrimitive,prims,pinfo);
-
- /* calculate total surface area */ // FIXME: this sum is not deterministic
- const float A = (float) parallel_reduce(size_t(0),pinfo.size(),0.0, [&] (const range<size_t>& r) -> double {
-
- double A = 0.0f;
- for (size_t i=r.begin(); i<r.end(); i++)
- {
- PrimRef& prim = prims[i];
- A += area(prim.bounds());
- }
- return A;
- },std::plus<double>());
-
-
- /* calculate maximum number of spatial splits per primitive */
- const unsigned int maxSplits = ((size_t)1 << RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)-1;
- const float f = 10.0f;
-
- const float invA = 1.0f / A;
- parallel_for( size_t(0), pinfo.size(), [&](const range<size_t>& r) {
-
- for (size_t i=r.begin(); i<r.end(); i++)
- {
- PrimRef& prim = prims[i];
- assert((prim.geomID() & SPLITS_MASK) == 0);
- // FIXME: is there a better general heuristic ?
- const float nf = ceilf(f*pinfo.size()*area(prim.bounds()) * invA);
- unsigned int n = 4+min((int)maxSplits-4, max(1, (int)(nf)));
- prim.lower.u |= n << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
- }
- });
-
- return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
- heuristic,
- prims,
- PrimInfoExtRange(0,pinfo.size(),extSize,pinfo),
- createAlloc,
- createNode,
- updateNode,
- CreateLeafExt<ReductionTy,CreateLeafFunc>(createLeaf),
- progressMonitor,
- settings);
- }
- };
-
- /* Open/Merge SAH builder that operates on an array of BuildRecords */
- struct BVHBuilderBinnedOpenMergeSAH
- {
- static const size_t NUM_OBJECT_BINS_HQ = 32;
- typedef PrimInfoExtRange Set;
- typedef BinSplit<NUM_OBJECT_BINS_HQ> Split;
- typedef GeneralBVHBuilder::BuildRecordT<Set,Split> BuildRecord;
- typedef GeneralBVHBuilder::Settings Settings;
-
- /*! special builder that propagates reduction over the tree */
- template<
- typename ReductionTy,
- typename BuildRef,
- typename CreateAllocFunc,
- typename CreateNodeFunc,
- typename UpdateNodeFunc,
- typename CreateLeafFunc,
- typename NodeOpenerFunc,
- typename ProgressMonitor>
-
- static ReductionTy build(CreateAllocFunc createAlloc,
- CreateNodeFunc createNode,
- UpdateNodeFunc updateNode,
- const CreateLeafFunc& createLeaf,
- NodeOpenerFunc nodeOpenerFunc,
- ProgressMonitor progressMonitor,
- BuildRef* prims,
- const size_t extSize,
- const PrimInfo& pinfo,
- const Settings& settings)
- {
- typedef HeuristicArrayOpenMergeSAH<NodeOpenerFunc,BuildRef,NUM_OBJECT_BINS_HQ> Heuristic;
- Heuristic heuristic(nodeOpenerFunc,prims,settings.branchingFactor);
-
- return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,BuildRef>(
- heuristic,
- prims,
- PrimInfoExtRange(0,pinfo.size(),extSize,pinfo),
- createAlloc,
- createNode,
- updateNode,
- createLeaf,
- progressMonitor,
- settings);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/heuristic_binning.h b/thirdparty/embree-aarch64/kernels/builders/heuristic_binning.h
deleted file mode 100644
index a4d3b68e46..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/heuristic_binning.h
+++ /dev/null
@@ -1,972 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "priminfo.h"
-#include "../../common/algorithms/parallel_reduce.h"
-#include "../../common/algorithms/parallel_partition.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! mapping into bins */
- template<size_t BINS>
- struct BinMapping
- {
- public:
- __forceinline BinMapping() {}
-
- /*! calculates the mapping */
- __forceinline BinMapping(size_t N, const BBox3fa& centBounds)
- {
- num = min(BINS,size_t(4.0f + 0.05f*N));
- assert(num >= 1);
- const vfloat4 eps = 1E-34f;
- const vfloat4 diag = max(eps, (vfloat4) centBounds.size());
- scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
- ofs = (vfloat4) centBounds.lower;
- }
-
- /*! calculates the mapping */
- __forceinline BinMapping(const BBox3fa& centBounds)
- {
- num = BINS;
- const vfloat4 eps = 1E-34f;
- const vfloat4 diag = max(eps, (vfloat4) centBounds.size());
- scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
- ofs = (vfloat4) centBounds.lower;
- }
-
- /*! calculates the mapping */
- template<typename PrimInfo>
- __forceinline BinMapping(const PrimInfo& pinfo)
- {
- const vfloat4 eps = 1E-34f;
- num = min(BINS,size_t(4.0f + 0.05f*pinfo.size()));
- const vfloat4 diag = max(eps,(vfloat4) pinfo.centBounds.size());
- scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
- ofs = (vfloat4) pinfo.centBounds.lower;
- }
-
- /*! returns number of bins */
- __forceinline size_t size() const { return num; }
-
- /*! slower but safe binning */
- __forceinline Vec3ia bin(const Vec3fa& p) const
- {
- const vint4 i = floori((vfloat4(p)-ofs)*scale);
-#if 1
- assert(i[0] >= 0 && (size_t)i[0] < num);
- assert(i[1] >= 0 && (size_t)i[1] < num);
- assert(i[2] >= 0 && (size_t)i[2] < num);
- return Vec3ia(i);
-#else
- return Vec3ia(clamp(i,vint4(0),vint4(num-1)));
-#endif
- }
-
- /*! faster but unsafe binning */
- __forceinline Vec3ia bin_unsafe(const Vec3fa& p) const {
- return Vec3ia(floori((vfloat4(p)-ofs)*scale));
- }
-
- /*! faster but unsafe binning */
- template<typename PrimRef>
- __forceinline Vec3ia bin_unsafe(const PrimRef& p) const {
- return bin_unsafe(p.binCenter());
- }
-
- /*! faster but unsafe binning */
- template<typename PrimRef, typename BinBoundsAndCenter>
- __forceinline Vec3ia bin_unsafe(const PrimRef& p, const BinBoundsAndCenter& binBoundsAndCenter) const {
- return bin_unsafe(binBoundsAndCenter.binCenter(p));
- }
-
- template<typename PrimRef>
- __forceinline bool bin_unsafe(const PrimRef& ref,
- const vint4& vSplitPos,
- const vbool4& splitDimMask) const // FIXME: rename to isLeft
- {
- return any(((vint4)bin_unsafe(center2(ref.bounds())) < vSplitPos) & splitDimMask);
- }
- /*! calculates left spatial position of bin */
- __forceinline float pos(const size_t bin, const size_t dim) const {
- return madd(float(bin),1.0f / scale[dim],ofs[dim]);
- }
-
- /*! returns true if the mapping is invalid in some dimension */
- __forceinline bool invalid(const size_t dim) const {
- return scale[dim] == 0.0f;
- }
-
- /*! stream output */
- friend embree_ostream operator<<(embree_ostream cout, const BinMapping& mapping) {
- return cout << "BinMapping { num = " << mapping.num << ", ofs = " << mapping.ofs << ", scale = " << mapping.scale << "}";
- }
-
- public:
- size_t num;
- vfloat4 ofs,scale; //!< linear function that maps to bin ID
- };
-
- /*! stores all information to perform some split */
- template<size_t BINS>
- struct BinSplit
- {
- enum
- {
- SPLIT_OBJECT = 0,
- SPLIT_FALLBACK = 1,
- SPLIT_ENFORCE = 2, // splits with larger ID are enforced in createLargeLeaf even if we could create a leaf already
- SPLIT_TEMPORAL = 2,
- SPLIT_GEOMID = 3,
- };
-
- /*! construct an invalid split by default */
- __forceinline BinSplit()
- : sah(inf), dim(-1), pos(0), data(0) {}
-
- __forceinline BinSplit(float sah, unsigned data, int dim = 0, float fpos = 0)
- : sah(sah), dim(dim), fpos(fpos), data(data) {}
-
- /*! constructs specified split */
- __forceinline BinSplit(float sah, int dim, int pos, const BinMapping<BINS>& mapping)
- : sah(sah), dim(dim), pos(pos), data(0), mapping(mapping) {}
-
- /*! tests if this split is valid */
- __forceinline bool valid() const { return dim != -1; }
-
- /*! calculates surface area heuristic for performing the split */
- __forceinline float splitSAH() const { return sah; }
-
- /*! stream output */
- friend embree_ostream operator<<(embree_ostream cout, const BinSplit& split) {
- return cout << "BinSplit { sah = " << split.sah << ", dim = " << split.dim << ", pos = " << split.pos << "}";
- }
-
- public:
- float sah; //!< SAH cost of the split
- int dim; //!< split dimension
- union { int pos; float fpos; }; //!< bin index for splitting
- unsigned int data; //!< extra optional split data
- BinMapping<BINS> mapping; //!< mapping into bins
- };
-
- /*! stores extended information about the split */
- template<typename BBox>
- struct SplitInfoT
- {
-
- __forceinline SplitInfoT () {}
-
- __forceinline SplitInfoT (size_t leftCount, const BBox& leftBounds, size_t rightCount, const BBox& rightBounds)
- : leftCount(leftCount), rightCount(rightCount), leftBounds(leftBounds), rightBounds(rightBounds) {}
-
- public:
- size_t leftCount,rightCount;
- BBox leftBounds,rightBounds;
- };
-
- typedef SplitInfoT<BBox3fa> SplitInfo;
- typedef SplitInfoT<LBBox3fa> SplitInfo2;
-
- /*! stores all binning information */
- template<size_t BINS, typename PrimRef, typename BBox>
- struct __aligned(64) BinInfoT
- {
- typedef BinSplit<BINS> Split;
- typedef vbool4 vbool;
- typedef vint4 vint;
- typedef vfloat4 vfloat;
-
- __forceinline BinInfoT() {
- }
-
- __forceinline BinInfoT(EmptyTy) {
- clear();
- }
-
- /*! bin access function */
- __forceinline BBox &bounds(const size_t binID, const size_t dimID) { return _bounds[binID][dimID]; }
- __forceinline const BBox &bounds(const size_t binID, const size_t dimID) const { return _bounds[binID][dimID]; }
-
- __forceinline unsigned int &counts(const size_t binID, const size_t dimID) { return _counts[binID][dimID]; }
- __forceinline const unsigned int &counts(const size_t binID, const size_t dimID) const { return _counts[binID][dimID]; }
-
- __forceinline vuint4 &counts(const size_t binID) { return _counts[binID]; }
- __forceinline const vuint4 &counts(const size_t binID) const { return _counts[binID]; }
-
- /*! clears the bin info */
- __forceinline void clear()
- {
- for (size_t i=0; i<BINS; i++) {
- bounds(i,0) = bounds(i,1) = bounds(i,2) = empty;
- counts(i) = vuint4(zero);
- }
- }
-
- /*! bins an array of primitives */
- __forceinline void bin (const PrimRef* prims, size_t N, const BinMapping<BINS>& mapping)
- {
- if (unlikely(N == 0)) return;
- size_t i;
- for (i=0; i<N-1; i+=2)
- {
- /*! map even and odd primitive to bin */
- BBox prim0; Vec3fa center0;
- prims[i+0].binBoundsAndCenter(prim0,center0);
- const vint4 bin0 = (vint4)mapping.bin(center0);
-
- BBox prim1; Vec3fa center1;
- prims[i+1].binBoundsAndCenter(prim1,center1);
- const vint4 bin1 = (vint4)mapping.bin(center1);
-
- /*! increase bounds for bins for even primitive */
- const unsigned int b00 = extract<0>(bin0); bounds(b00,0).extend(prim0);
- const unsigned int b01 = extract<1>(bin0); bounds(b01,1).extend(prim0);
- const unsigned int b02 = extract<2>(bin0); bounds(b02,2).extend(prim0);
- const unsigned int s0 = (unsigned int)prims[i+0].size();
- counts(b00,0)+=s0;
- counts(b01,1)+=s0;
- counts(b02,2)+=s0;
-
- /*! increase bounds of bins for odd primitive */
- const unsigned int b10 = extract<0>(bin1); bounds(b10,0).extend(prim1);
- const unsigned int b11 = extract<1>(bin1); bounds(b11,1).extend(prim1);
- const unsigned int b12 = extract<2>(bin1); bounds(b12,2).extend(prim1);
- const unsigned int s1 = (unsigned int)prims[i+1].size();
- counts(b10,0)+=s1;
- counts(b11,1)+=s1;
- counts(b12,2)+=s1;
- }
- /*! for uneven number of primitives */
- if (i < N)
- {
- /*! map primitive to bin */
- BBox prim0; Vec3fa center0;
- prims[i].binBoundsAndCenter(prim0,center0);
- const vint4 bin0 = (vint4)mapping.bin(center0);
-
- /*! increase bounds of bins */
- const unsigned int s0 = (unsigned int)prims[i].size();
- const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
- const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
- const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
- }
- }
-
- /*! bins an array of primitives */
- template<typename BinBoundsAndCenter>
- __forceinline void bin (const PrimRef* prims, size_t N, const BinMapping<BINS>& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
- {
- if (N == 0) return;
-
- size_t i;
- for (i=0; i<N-1; i+=2)
- {
- /*! map even and odd primitive to bin */
- BBox prim0; Vec3fa center0; binBoundsAndCenter.binBoundsAndCenter(prims[i+0],prim0,center0);
- const vint4 bin0 = (vint4)mapping.bin(center0);
- BBox prim1; Vec3fa center1; binBoundsAndCenter.binBoundsAndCenter(prims[i+1],prim1,center1);
- const vint4 bin1 = (vint4)mapping.bin(center1);
-
- /*! increase bounds for bins for even primitive */
- const unsigned int s0 = prims[i+0].size();
- const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
- const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
- const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
-
- /*! increase bounds of bins for odd primitive */
- const unsigned int s1 = prims[i+1].size();
- const int b10 = extract<0>(bin1); counts(b10,0)+=s1; bounds(b10,0).extend(prim1);
- const int b11 = extract<1>(bin1); counts(b11,1)+=s1; bounds(b11,1).extend(prim1);
- const int b12 = extract<2>(bin1); counts(b12,2)+=s1; bounds(b12,2).extend(prim1);
- }
-
- /*! for uneven number of primitives */
- if (i < N)
- {
- /*! map primitive to bin */
- BBox prim0; Vec3fa center0; binBoundsAndCenter.binBoundsAndCenter(prims[i+0],prim0,center0);
- const vint4 bin0 = (vint4)mapping.bin(center0);
-
- /*! increase bounds of bins */
- const unsigned int s0 = prims[i+0].size();
- const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
- const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
- const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
- }
- }
-
- __forceinline void bin(const PrimRef* prims, size_t begin, size_t end, const BinMapping<BINS>& mapping) {
- bin(prims+begin,end-begin,mapping);
- }
-
- template<typename BinBoundsAndCenter>
- __forceinline void bin(const PrimRef* prims, size_t begin, size_t end, const BinMapping<BINS>& mapping, const BinBoundsAndCenter& binBoundsAndCenter) {
- bin<BinBoundsAndCenter>(prims+begin,end-begin,mapping,binBoundsAndCenter);
- }
-
- /*! merges in other binning information */
- __forceinline void merge (const BinInfoT& other, size_t numBins)
- {
-
- for (size_t i=0; i<numBins; i++)
- {
- counts(i) += other.counts(i);
- bounds(i,0).extend(other.bounds(i,0));
- bounds(i,1).extend(other.bounds(i,1));
- bounds(i,2).extend(other.bounds(i,2));
- }
- }
-
- /*! reduces binning information */
- static __forceinline const BinInfoT reduce (const BinInfoT& a, const BinInfoT& b, const size_t numBins = BINS)
- {
- BinInfoT c;
- for (size_t i=0; i<numBins; i++)
- {
- c.counts(i) = a.counts(i)+b.counts(i);
- c.bounds(i,0) = embree::merge(a.bounds(i,0),b.bounds(i,0));
- c.bounds(i,1) = embree::merge(a.bounds(i,1),b.bounds(i,1));
- c.bounds(i,2) = embree::merge(a.bounds(i,2),b.bounds(i,2));
- }
- return c;
- }
-
- /*! finds the best split by scanning binning information */
- __forceinline Split best(const BinMapping<BINS>& mapping, const size_t blocks_shift) const
- {
- /* sweep from right to left and compute parallel prefix of merged bounds */
- vfloat4 rAreas[BINS];
- vuint4 rCounts[BINS];
- vuint4 count = 0; BBox bx = empty; BBox by = empty; BBox bz = empty;
- for (size_t i=mapping.size()-1; i>0; i--)
- {
- count += counts(i);
- rCounts[i] = count;
- bx.extend(bounds(i,0)); rAreas[i][0] = expectedApproxHalfArea(bx);
- by.extend(bounds(i,1)); rAreas[i][1] = expectedApproxHalfArea(by);
- bz.extend(bounds(i,2)); rAreas[i][2] = expectedApproxHalfArea(bz);
- rAreas[i][3] = 0.0f;
- }
- /* sweep from left to right and compute SAH */
- vuint4 blocks_add = (1 << blocks_shift)-1;
- vuint4 ii = 1; vfloat4 vbestSAH = pos_inf; vuint4 vbestPos = 0;
- count = 0; bx = empty; by = empty; bz = empty;
- for (size_t i=1; i<mapping.size(); i++, ii+=1)
- {
- count += counts(i-1);
- bx.extend(bounds(i-1,0)); float Ax = expectedApproxHalfArea(bx);
- by.extend(bounds(i-1,1)); float Ay = expectedApproxHalfArea(by);
- bz.extend(bounds(i-1,2)); float Az = expectedApproxHalfArea(bz);
- const vfloat4 lArea = vfloat4(Ax,Ay,Az,Az);
- const vfloat4 rArea = rAreas[i];
- const vuint4 lCount = (count +blocks_add) >> (unsigned int)(blocks_shift); // if blocks_shift >=1 then lCount < 4B and could be represented with an vint4, which would allow for faster vfloat4 conversions.
- const vuint4 rCount = (rCounts[i]+blocks_add) >> (unsigned int)(blocks_shift);
- const vfloat4 sah = madd(lArea,vfloat4(lCount),rArea*vfloat4(rCount));
- //const vfloat4 sah = madd(lArea,vfloat4(vint4(lCount)),rArea*vfloat4(vint4(rCount)));
-
- vbestPos = select(sah < vbestSAH,ii ,vbestPos);
- vbestSAH = select(sah < vbestSAH,sah,vbestSAH);
- }
-
- /* find best dimension */
- float bestSAH = inf;
- int bestDim = -1;
- int bestPos = 0;
- for (int dim=0; dim<3; dim++)
- {
- /* ignore zero sized dimensions */
- if (unlikely(mapping.invalid(dim)))
- continue;
-
- /* test if this is a better dimension */
- if (vbestSAH[dim] < bestSAH && vbestPos[dim] != 0) {
- bestDim = dim;
- bestPos = vbestPos[dim];
- bestSAH = vbestSAH[dim];
- }
- }
- return Split(bestSAH,bestDim,bestPos,mapping);
- }
-
- /*! calculates extended split information */
- __forceinline void getSplitInfo(const BinMapping<BINS>& mapping, const Split& split, SplitInfoT<BBox>& info) const
- {
- if (split.dim == -1) {
- new (&info) SplitInfoT<BBox>(0,empty,0,empty);
- return;
- }
-
- size_t leftCount = 0;
- BBox leftBounds = empty;
- for (size_t i=0; i<(size_t)split.pos; i++) {
- leftCount += counts(i,split.dim);
- leftBounds.extend(bounds(i,split.dim));
- }
- size_t rightCount = 0;
- BBox rightBounds = empty;
- for (size_t i=split.pos; i<mapping.size(); i++) {
- rightCount += counts(i,split.dim);
- rightBounds.extend(bounds(i,split.dim));
- }
- new (&info) SplitInfoT<BBox>(leftCount,leftBounds,rightCount,rightBounds);
- }
-
- /*! gets the number of primitives left of the split */
- __forceinline size_t getLeftCount(const BinMapping<BINS>& mapping, const Split& split) const
- {
- if (unlikely(split.dim == -1)) return -1;
-
- size_t leftCount = 0;
- for (size_t i = 0; i < (size_t)split.pos; i++) {
- leftCount += counts(i, split.dim);
- }
- return leftCount;
- }
-
- /*! gets the number of primitives right of the split */
- __forceinline size_t getRightCount(const BinMapping<BINS>& mapping, const Split& split) const
- {
- if (unlikely(split.dim == -1)) return -1;
-
- size_t rightCount = 0;
- for (size_t i = (size_t)split.pos; i<mapping.size(); i++) {
- rightCount += counts(i, split.dim);
- }
- return rightCount;
- }
-
- private:
- BBox _bounds[BINS][3]; //!< geometry bounds for each bin in each dimension
- vuint4 _counts[BINS]; //!< counts number of primitives that map into the bins
- };
-
-#if defined(__AVX512ER__) // KNL
-
- /*! mapping into bins */
- template<>
- struct BinMapping<16>
- {
- public:
- __forceinline BinMapping() {}
-
- /*! calculates the mapping */
- template<typename PrimInfo>
- __forceinline BinMapping(const PrimInfo& pinfo)
- {
- num = 16;
- const vfloat4 eps = 1E-34f;
- const vfloat4 diag = max(eps,(vfloat4) pinfo.centBounds.size());
- scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
- ofs = (vfloat4) pinfo.centBounds.lower;
- scale16 = scale;
- ofs16 = ofs;
- }
-
- /*! returns number of bins */
- __forceinline size_t size() const { return num; }
-
- __forceinline vint16 bin16(const Vec3fa& p) const {
- return vint16(vint4(floori((vfloat4(p)-ofs)*scale)));
- }
-
- __forceinline vint16 bin16(const vfloat16& p) const {
- return floori((p-ofs16)*scale16);
- }
-
- __forceinline int bin_unsafe(const PrimRef& ref,
- const vint16& vSplitPos,
- const vbool16& splitDimMask) const // FIXME: rename to isLeft
- {
- const vfloat16 lower(*(vfloat4*)&ref.lower);
- const vfloat16 upper(*(vfloat4*)&ref.upper);
- const vfloat16 p = lower + upper;
- const vint16 i = floori((p-ofs16)*scale16);
- return lt(splitDimMask,i,vSplitPos);
- }
-
- /*! returns true if the mapping is invalid in some dimension */
- __forceinline bool invalid(const size_t dim) const {
- return scale[dim] == 0.0f;
- }
-
- public:
- size_t num;
- vfloat4 ofs,scale; //!< linear function that maps to bin ID
- vfloat16 ofs16,scale16; //!< linear function that maps to bin ID
- };
-
- /* 16 bins in-register binner */
- template<typename PrimRef>
- struct __aligned(64) BinInfoT<16,PrimRef,BBox3fa>
- {
- typedef BinSplit<16> Split;
- typedef vbool16 vbool;
- typedef vint16 vint;
- typedef vfloat16 vfloat;
-
- __forceinline BinInfoT() {
- }
-
- __forceinline BinInfoT(EmptyTy) {
- clear();
- }
-
- /*! clears the bin info */
- __forceinline void clear()
- {
- lower[0] = lower[1] = lower[2] = pos_inf;
- upper[0] = upper[1] = upper[2] = neg_inf;
- count[0] = count[1] = count[2] = 0;
- }
-
-
- static __forceinline vfloat16 prefix_area_rl(const vfloat16 min_x,
- const vfloat16 min_y,
- const vfloat16 min_z,
- const vfloat16 max_x,
- const vfloat16 max_y,
- const vfloat16 max_z)
- {
- const vfloat16 r_min_x = reverse_prefix_min(min_x);
- const vfloat16 r_min_y = reverse_prefix_min(min_y);
- const vfloat16 r_min_z = reverse_prefix_min(min_z);
- const vfloat16 r_max_x = reverse_prefix_max(max_x);
- const vfloat16 r_max_y = reverse_prefix_max(max_y);
- const vfloat16 r_max_z = reverse_prefix_max(max_z);
- const vfloat16 dx = r_max_x - r_min_x;
- const vfloat16 dy = r_max_y - r_min_y;
- const vfloat16 dz = r_max_z - r_min_z;
- const vfloat16 area_rl = madd(dx,dy,madd(dx,dz,dy*dz));
- return area_rl;
- }
-
- static __forceinline vfloat16 prefix_area_lr(const vfloat16 min_x,
- const vfloat16 min_y,
- const vfloat16 min_z,
- const vfloat16 max_x,
- const vfloat16 max_y,
- const vfloat16 max_z)
- {
- const vfloat16 r_min_x = prefix_min(min_x);
- const vfloat16 r_min_y = prefix_min(min_y);
- const vfloat16 r_min_z = prefix_min(min_z);
- const vfloat16 r_max_x = prefix_max(max_x);
- const vfloat16 r_max_y = prefix_max(max_y);
- const vfloat16 r_max_z = prefix_max(max_z);
- const vfloat16 dx = r_max_x - r_min_x;
- const vfloat16 dy = r_max_y - r_min_y;
- const vfloat16 dz = r_max_z - r_min_z;
- const vfloat16 area_lr = madd(dx,dy,madd(dx,dz,dy*dz));
- return area_lr;
- }
-
-
- /*! bins an array of primitives */
- __forceinline void bin (const PrimRef* prims, size_t N, const BinMapping<16>& mapping)
- {
- if (unlikely(N == 0)) return;
-
- const vfloat16 init_min(pos_inf);
- const vfloat16 init_max(neg_inf);
-
- vfloat16 min_x0,min_x1,min_x2;
- vfloat16 min_y0,min_y1,min_y2;
- vfloat16 min_z0,min_z1,min_z2;
- vfloat16 max_x0,max_x1,max_x2;
- vfloat16 max_y0,max_y1,max_y2;
- vfloat16 max_z0,max_z1,max_z2;
- vuint16 count0,count1,count2;
-
- min_x0 = init_min;
- min_x1 = init_min;
- min_x2 = init_min;
- min_y0 = init_min;
- min_y1 = init_min;
- min_y2 = init_min;
- min_z0 = init_min;
- min_z1 = init_min;
- min_z2 = init_min;
-
- max_x0 = init_max;
- max_x1 = init_max;
- max_x2 = init_max;
- max_y0 = init_max;
- max_y1 = init_max;
- max_y2 = init_max;
- max_z0 = init_max;
- max_z1 = init_max;
- max_z2 = init_max;
-
- count0 = zero;
- count1 = zero;
- count2 = zero;
-
- const vint16 step16(step);
- size_t i;
- for (i=0; i<N-1; i+=2)
- {
- /*! map even and odd primitive to bin */
- const BBox3fa primA = prims[i+0].bounds();
- const vfloat16 centerA = vfloat16((vfloat4)primA.lower) + vfloat16((vfloat4)primA.upper);
- const vint16 binA = mapping.bin16(centerA);
-
- const BBox3fa primB = prims[i+1].bounds();
- const vfloat16 centerB = vfloat16((vfloat4)primB.lower) + vfloat16((vfloat4)primB.upper);
- const vint16 binB = mapping.bin16(centerB);
-
- /* A */
- {
- const vfloat16 b_min_x = prims[i+0].lower.x;
- const vfloat16 b_min_y = prims[i+0].lower.y;
- const vfloat16 b_min_z = prims[i+0].lower.z;
- const vfloat16 b_max_x = prims[i+0].upper.x;
- const vfloat16 b_max_y = prims[i+0].upper.y;
- const vfloat16 b_max_z = prims[i+0].upper.z;
-
- const vint16 bin0 = shuffle<0>(binA);
- const vint16 bin1 = shuffle<1>(binA);
- const vint16 bin2 = shuffle<2>(binA);
-
- const vbool16 m_update_x = step16 == bin0;
- const vbool16 m_update_y = step16 == bin1;
- const vbool16 m_update_z = step16 == bin2;
-
- assert(popcnt((size_t)m_update_x) == 1);
- assert(popcnt((size_t)m_update_y) == 1);
- assert(popcnt((size_t)m_update_z) == 1);
-
- min_x0 = mask_min(m_update_x,min_x0,min_x0,b_min_x);
- min_y0 = mask_min(m_update_x,min_y0,min_y0,b_min_y);
- min_z0 = mask_min(m_update_x,min_z0,min_z0,b_min_z);
- // ------------------------------------------------------------------------
- max_x0 = mask_max(m_update_x,max_x0,max_x0,b_max_x);
- max_y0 = mask_max(m_update_x,max_y0,max_y0,b_max_y);
- max_z0 = mask_max(m_update_x,max_z0,max_z0,b_max_z);
- // ------------------------------------------------------------------------
- min_x1 = mask_min(m_update_y,min_x1,min_x1,b_min_x);
- min_y1 = mask_min(m_update_y,min_y1,min_y1,b_min_y);
- min_z1 = mask_min(m_update_y,min_z1,min_z1,b_min_z);
- // ------------------------------------------------------------------------
- max_x1 = mask_max(m_update_y,max_x1,max_x1,b_max_x);
- max_y1 = mask_max(m_update_y,max_y1,max_y1,b_max_y);
- max_z1 = mask_max(m_update_y,max_z1,max_z1,b_max_z);
- // ------------------------------------------------------------------------
- min_x2 = mask_min(m_update_z,min_x2,min_x2,b_min_x);
- min_y2 = mask_min(m_update_z,min_y2,min_y2,b_min_y);
- min_z2 = mask_min(m_update_z,min_z2,min_z2,b_min_z);
- // ------------------------------------------------------------------------
- max_x2 = mask_max(m_update_z,max_x2,max_x2,b_max_x);
- max_y2 = mask_max(m_update_z,max_y2,max_y2,b_max_y);
- max_z2 = mask_max(m_update_z,max_z2,max_z2,b_max_z);
- // ------------------------------------------------------------------------
- count0 = mask_add(m_update_x,count0,count0,vuint16(1));
- count1 = mask_add(m_update_y,count1,count1,vuint16(1));
- count2 = mask_add(m_update_z,count2,count2,vuint16(1));
- }
-
-
- /* B */
- {
- const vfloat16 b_min_x = prims[i+1].lower.x;
- const vfloat16 b_min_y = prims[i+1].lower.y;
- const vfloat16 b_min_z = prims[i+1].lower.z;
- const vfloat16 b_max_x = prims[i+1].upper.x;
- const vfloat16 b_max_y = prims[i+1].upper.y;
- const vfloat16 b_max_z = prims[i+1].upper.z;
-
- const vint16 bin0 = shuffle<0>(binB);
- const vint16 bin1 = shuffle<1>(binB);
- const vint16 bin2 = shuffle<2>(binB);
-
- const vbool16 m_update_x = step16 == bin0;
- const vbool16 m_update_y = step16 == bin1;
- const vbool16 m_update_z = step16 == bin2;
-
- assert(popcnt((size_t)m_update_x) == 1);
- assert(popcnt((size_t)m_update_y) == 1);
- assert(popcnt((size_t)m_update_z) == 1);
-
- min_x0 = mask_min(m_update_x,min_x0,min_x0,b_min_x);
- min_y0 = mask_min(m_update_x,min_y0,min_y0,b_min_y);
- min_z0 = mask_min(m_update_x,min_z0,min_z0,b_min_z);
- // ------------------------------------------------------------------------
- max_x0 = mask_max(m_update_x,max_x0,max_x0,b_max_x);
- max_y0 = mask_max(m_update_x,max_y0,max_y0,b_max_y);
- max_z0 = mask_max(m_update_x,max_z0,max_z0,b_max_z);
- // ------------------------------------------------------------------------
- min_x1 = mask_min(m_update_y,min_x1,min_x1,b_min_x);
- min_y1 = mask_min(m_update_y,min_y1,min_y1,b_min_y);
- min_z1 = mask_min(m_update_y,min_z1,min_z1,b_min_z);
- // ------------------------------------------------------------------------
- max_x1 = mask_max(m_update_y,max_x1,max_x1,b_max_x);
- max_y1 = mask_max(m_update_y,max_y1,max_y1,b_max_y);
- max_z1 = mask_max(m_update_y,max_z1,max_z1,b_max_z);
- // ------------------------------------------------------------------------
- min_x2 = mask_min(m_update_z,min_x2,min_x2,b_min_x);
- min_y2 = mask_min(m_update_z,min_y2,min_y2,b_min_y);
- min_z2 = mask_min(m_update_z,min_z2,min_z2,b_min_z);
- // ------------------------------------------------------------------------
- max_x2 = mask_max(m_update_z,max_x2,max_x2,b_max_x);
- max_y2 = mask_max(m_update_z,max_y2,max_y2,b_max_y);
- max_z2 = mask_max(m_update_z,max_z2,max_z2,b_max_z);
- // ------------------------------------------------------------------------
- count0 = mask_add(m_update_x,count0,count0,vuint16(1));
- count1 = mask_add(m_update_y,count1,count1,vuint16(1));
- count2 = mask_add(m_update_z,count2,count2,vuint16(1));
- }
-
- }
-
- if (i < N)
- {
- const BBox3fa prim0 = prims[i].bounds();
- const vfloat16 center0 = vfloat16((vfloat4)prim0.lower) + vfloat16((vfloat4)prim0.upper);
- const vint16 bin = mapping.bin16(center0);
-
- const vfloat16 b_min_x = prims[i].lower.x;
- const vfloat16 b_min_y = prims[i].lower.y;
- const vfloat16 b_min_z = prims[i].lower.z;
- const vfloat16 b_max_x = prims[i].upper.x;
- const vfloat16 b_max_y = prims[i].upper.y;
- const vfloat16 b_max_z = prims[i].upper.z;
-
- const vint16 bin0 = shuffle<0>(bin);
- const vint16 bin1 = shuffle<1>(bin);
- const vint16 bin2 = shuffle<2>(bin);
-
- const vbool16 m_update_x = step16 == bin0;
- const vbool16 m_update_y = step16 == bin1;
- const vbool16 m_update_z = step16 == bin2;
-
- assert(popcnt((size_t)m_update_x) == 1);
- assert(popcnt((size_t)m_update_y) == 1);
- assert(popcnt((size_t)m_update_z) == 1);
-
- min_x0 = mask_min(m_update_x,min_x0,min_x0,b_min_x);
- min_y0 = mask_min(m_update_x,min_y0,min_y0,b_min_y);
- min_z0 = mask_min(m_update_x,min_z0,min_z0,b_min_z);
- // ------------------------------------------------------------------------
- max_x0 = mask_max(m_update_x,max_x0,max_x0,b_max_x);
- max_y0 = mask_max(m_update_x,max_y0,max_y0,b_max_y);
- max_z0 = mask_max(m_update_x,max_z0,max_z0,b_max_z);
- // ------------------------------------------------------------------------
- min_x1 = mask_min(m_update_y,min_x1,min_x1,b_min_x);
- min_y1 = mask_min(m_update_y,min_y1,min_y1,b_min_y);
- min_z1 = mask_min(m_update_y,min_z1,min_z1,b_min_z);
- // ------------------------------------------------------------------------
- max_x1 = mask_max(m_update_y,max_x1,max_x1,b_max_x);
- max_y1 = mask_max(m_update_y,max_y1,max_y1,b_max_y);
- max_z1 = mask_max(m_update_y,max_z1,max_z1,b_max_z);
- // ------------------------------------------------------------------------
- min_x2 = mask_min(m_update_z,min_x2,min_x2,b_min_x);
- min_y2 = mask_min(m_update_z,min_y2,min_y2,b_min_y);
- min_z2 = mask_min(m_update_z,min_z2,min_z2,b_min_z);
- // ------------------------------------------------------------------------
- max_x2 = mask_max(m_update_z,max_x2,max_x2,b_max_x);
- max_y2 = mask_max(m_update_z,max_y2,max_y2,b_max_y);
- max_z2 = mask_max(m_update_z,max_z2,max_z2,b_max_z);
- // ------------------------------------------------------------------------
- count0 = mask_add(m_update_x,count0,count0,vuint16(1));
- count1 = mask_add(m_update_y,count1,count1,vuint16(1));
- count2 = mask_add(m_update_z,count2,count2,vuint16(1));
- }
-
- lower[0] = Vec3vf16( min_x0, min_y0, min_z0 );
- lower[1] = Vec3vf16( min_x1, min_y1, min_z1 );
- lower[2] = Vec3vf16( min_x2, min_y2, min_z2 );
-
- upper[0] = Vec3vf16( max_x0, max_y0, max_z0 );
- upper[1] = Vec3vf16( max_x1, max_y1, max_z1 );
- upper[2] = Vec3vf16( max_x2, max_y2, max_z2 );
-
- count[0] = count0;
- count[1] = count1;
- count[2] = count2;
- }
-
- __forceinline void bin(const PrimRef* prims, size_t begin, size_t end, const BinMapping<16>& mapping) {
- bin(prims+begin,end-begin,mapping);
- }
-
- /*! merges in other binning information */
- __forceinline void merge (const BinInfoT& other, size_t numBins)
- {
- for (size_t i=0; i<3; i++)
- {
- lower[i] = min(lower[i],other.lower[i]);
- upper[i] = max(upper[i],other.upper[i]);
- count[i] += other.count[i];
- }
- }
-
- /*! reducesr binning information */
- static __forceinline const BinInfoT reduce (const BinInfoT& a, const BinInfoT& b)
- {
- BinInfoT c;
- for (size_t i=0; i<3; i++)
- {
- c.counts[i] = a.counts[i] + b.counts[i];
- c.lower[i] = min(a.lower[i],b.lower[i]);
- c.upper[i] = max(a.upper[i],b.upper[i]);
- }
- return c;
- }
-
- /*! finds the best split by scanning binning information */
- __forceinline Split best(const BinMapping<16>& mapping, const size_t blocks_shift) const
- {
- /* find best dimension */
- float bestSAH = inf;
- int bestDim = -1;
- int bestPos = 0;
- const vuint16 blocks_add = (1 << blocks_shift)-1;
- const vfloat16 inf(pos_inf);
- for (size_t dim=0; dim<3; dim++)
- {
- /* ignore zero sized dimensions */
- if (unlikely(mapping.invalid(dim)))
- continue;
-
- const vfloat16 rArea16 = prefix_area_rl(lower[dim].x,lower[dim].y,lower[dim].z, upper[dim].x,upper[dim].y,upper[dim].z);
- const vfloat16 lArea16 = prefix_area_lr(lower[dim].x,lower[dim].y,lower[dim].z, upper[dim].x,upper[dim].y,upper[dim].z);
- const vuint16 lCount16 = prefix_sum(count[dim]);
- const vuint16 rCount16 = reverse_prefix_sum(count[dim]);
-
- /* compute best split in this dimension */
- const vfloat16 leftArea = lArea16;
- const vfloat16 rightArea = align_shift_right<1>(zero,rArea16);
- const vuint16 lC = lCount16;
- const vuint16 rC = align_shift_right<1>(zero,rCount16);
- const vuint16 leftCount = ( lC + blocks_add) >> blocks_shift;
- const vuint16 rightCount = ( rC + blocks_add) >> blocks_shift;
- const vbool16 valid = (leftArea < inf) & (rightArea < inf) & vbool16(0x7fff); // handles inf entries
- const vfloat16 sah = select(valid,madd(leftArea,vfloat16(leftCount),rightArea*vfloat16(rightCount)),vfloat16(pos_inf));
- /* test if this is a better dimension */
- if (any(sah < vfloat16(bestSAH)))
- {
- const size_t index = select_min(sah);
- assert(index < 15);
- assert(sah[index] < bestSAH);
- bestDim = dim;
- bestPos = index+1;
- bestSAH = sah[index];
- }
- }
-
- return Split(bestSAH,bestDim,bestPos,mapping);
-
- }
-
- /*! calculates extended split information */
- __forceinline void getSplitInfo(const BinMapping<16>& mapping, const Split& split, SplitInfo& info) const
- {
- if (split.dim == -1) {
- new (&info) SplitInfo(0,empty,0,empty);
- return;
- }
- // FIXME: horizontal reduction!
-
- size_t leftCount = 0;
- BBox3fa leftBounds = empty;
- for (size_t i=0; i<(size_t)split.pos; i++) {
- leftCount += count[split.dim][i];
- Vec3fa bounds_lower(lower[split.dim].x[i],lower[split.dim].y[i],lower[split.dim].z[i]);
- Vec3fa bounds_upper(upper[split.dim].x[i],upper[split.dim].y[i],upper[split.dim].z[i]);
- leftBounds.extend(BBox3fa(bounds_lower,bounds_upper));
- }
- size_t rightCount = 0;
- BBox3fa rightBounds = empty;
- for (size_t i=split.pos; i<mapping.size(); i++) {
- rightCount += count[split.dim][i];
- Vec3fa bounds_lower(lower[split.dim].x[i],lower[split.dim].y[i],lower[split.dim].z[i]);
- Vec3fa bounds_upper(upper[split.dim].x[i],upper[split.dim].y[i],upper[split.dim].z[i]);
- rightBounds.extend(BBox3fa(bounds_lower,bounds_upper));
- }
- new (&info) SplitInfo(leftCount,leftBounds,rightCount,rightBounds);
- }
-
- /*! gets the number of primitives left of the split */
- __forceinline size_t getLeftCount(const BinMapping<16>& mapping, const Split& split) const
- {
- if (unlikely(split.dim == -1)) return -1;
-
- size_t leftCount = 0;
- for (size_t i = 0; i < (size_t)split.pos; i++) {
- leftCount += count[split.dim][i];
- }
- return leftCount;
- }
-
- /*! gets the number of primitives right of the split */
- __forceinline size_t getRightCount(const BinMapping<16>& mapping, const Split& split) const
- {
- if (unlikely(split.dim == -1)) return -1;
-
- size_t rightCount = 0;
- for (size_t i = (size_t)split.pos; i<mapping.size(); i++) {
- rightCount += count[split.dim][i];
- }
- return rightCount;
- }
-
- private:
- Vec3vf16 lower[3];
- Vec3vf16 upper[3];
- vuint16 count[3];
- };
-#endif
- }
-
- template<typename BinInfoT, typename BinMapping, typename PrimRef>
- __forceinline void bin_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, const BinMapping& mapping)
- {
- if (likely(end-begin < parallelThreshold)) {
- binner.bin(prims,begin,end,mapping);
- } else {
- binner = parallel_reduce(begin,end,blockSize,binner,
- [&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping); return binner; },
- [&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
- }
- }
-
- template<typename BinBoundsAndCenter, typename BinInfoT, typename BinMapping, typename PrimRef>
- __forceinline void bin_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, const BinMapping& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
- {
- if (likely(end-begin < parallelThreshold)) {
- binner.bin(prims,begin,end,mapping,binBoundsAndCenter);
- } else {
- binner = parallel_reduce(begin,end,blockSize,binner,
- [&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping, binBoundsAndCenter); return binner; },
- [&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
- }
- }
-
- template<bool parallel, typename BinInfoT, typename BinMapping, typename PrimRef>
- __forceinline void bin_serial_or_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, const BinMapping& mapping)
- {
- if (!parallel) {
- binner.bin(prims,begin,end,mapping);
- } else {
- binner = parallel_reduce(begin,end,blockSize,binner,
- [&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping); return binner; },
- [&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
- }
- }
-
- template<bool parallel, typename BinBoundsAndCenter, typename BinInfoT, typename BinMapping, typename PrimRef>
- __forceinline void bin_serial_or_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, const BinMapping& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
- {
- if (!parallel) {
- binner.bin(prims,begin,end,mapping,binBoundsAndCenter);
- } else {
- binner = parallel_reduce(begin,end,blockSize,binner,
- [&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping, binBoundsAndCenter); return binner; },
- [&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/heuristic_binning_array_aligned.h b/thirdparty/embree-aarch64/kernels/builders/heuristic_binning_array_aligned.h
deleted file mode 100644
index a4c272f015..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/heuristic_binning_array_aligned.h
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "heuristic_binning.h"
-
-namespace embree
-{
- namespace isa
- {
- struct PrimInfoRange : public CentGeomBBox3fa, public range<size_t>
- {
- __forceinline PrimInfoRange () {
- }
-
- __forceinline PrimInfoRange(const PrimInfo& pinfo)
- : CentGeomBBox3fa(pinfo), range<size_t>(pinfo.begin,pinfo.end) {}
-
- __forceinline PrimInfoRange(EmptyTy)
- : CentGeomBBox3fa(EmptyTy()), range<size_t>(0,0) {}
-
- __forceinline PrimInfoRange (size_t begin, size_t end, const CentGeomBBox3fa& centGeomBounds)
- : CentGeomBBox3fa(centGeomBounds), range<size_t>(begin,end) {}
-
- __forceinline float leafSAH() const {
- return expectedApproxHalfArea(geomBounds)*float(size());
- }
-
- __forceinline float leafSAH(size_t block_shift) const {
- return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
- }
- };
-
- /*! Performs standard object binning */
- template<typename PrimRef, size_t BINS>
- struct HeuristicArrayBinningSAH
- {
- typedef BinSplit<BINS> Split;
- typedef BinInfoT<BINS,PrimRef,BBox3fa> Binner;
- typedef range<size_t> Set;
-
-#if defined(__AVX512ER__) // KNL
- static const size_t PARALLEL_THRESHOLD = 4*768;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 768;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 768;
-#else
- static const size_t PARALLEL_THRESHOLD = 3 * 1024;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
-#endif
- __forceinline HeuristicArrayBinningSAH ()
- : prims(nullptr) {}
-
- /*! remember prim array */
- __forceinline HeuristicArrayBinningSAH (PrimRef* prims)
- : prims(prims) {}
-
- /*! finds the best split */
- __noinline const Split find(const PrimInfoRange& pinfo, const size_t logBlockSize)
- {
- if (likely(pinfo.size() < PARALLEL_THRESHOLD))
- return find_template<false>(pinfo,logBlockSize);
- else
- return find_template<true>(pinfo,logBlockSize);
- }
-
- template<bool parallel>
- __forceinline const Split find_template(const PrimInfoRange& pinfo, const size_t logBlockSize)
- {
- Binner binner(empty);
- const BinMapping<BINS> mapping(pinfo);
- bin_serial_or_parallel<parallel>(binner,prims,pinfo.begin(),pinfo.end(),PARALLEL_FIND_BLOCK_SIZE,mapping);
- return binner.best(mapping,logBlockSize);
- }
-
- /*! array partitioning */
- __forceinline void split(const Split& split, const PrimInfoRange& pinfo, PrimInfoRange& linfo, PrimInfoRange& rinfo)
- {
- if (likely(pinfo.size() < PARALLEL_THRESHOLD))
- split_template<false>(split,pinfo,linfo,rinfo);
- else
- split_template<true>(split,pinfo,linfo,rinfo);
- }
-
- template<bool parallel>
- __forceinline void split_template(const Split& split, const PrimInfoRange& set, PrimInfoRange& lset, PrimInfoRange& rset)
- {
- if (!split.valid()) {
- deterministic_order(set);
- return splitFallback(set,lset,rset);
- }
-
- const size_t begin = set.begin();
- const size_t end = set.end();
- CentGeomBBox3fa local_left(empty);
- CentGeomBBox3fa local_right(empty);
- const unsigned int splitPos = split.pos;
- const unsigned int splitDim = split.dim;
- const unsigned int splitDimMask = (unsigned int)1 << splitDim;
-
- const typename Binner::vint vSplitPos(splitPos);
- const typename Binner::vbool vSplitMask(splitDimMask);
- auto isLeft = [&] (const PrimRef &ref) { return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask); };
-
- size_t center = 0;
- if (!parallel)
- center = serial_partitioning(prims,begin,end,local_left,local_right,isLeft,
- [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend_center2(ref); });
- else
- center = parallel_partitioning(
- prims,begin,end,EmptyTy(),local_left,local_right,isLeft,
- [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend_center2(ref); },
- [] (CentGeomBBox3fa& pinfo0,const CentGeomBBox3fa& pinfo1) { pinfo0.merge(pinfo1); },
- PARALLEL_PARTITION_BLOCK_SIZE);
-
- new (&lset) PrimInfoRange(begin,center,local_left);
- new (&rset) PrimInfoRange(center,end,local_right);
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
- }
-
- void deterministic_order(const PrimInfoRange& pinfo)
- {
- /* required as parallel partition destroys original primitive order */
- std::sort(&prims[pinfo.begin()],&prims[pinfo.end()]);
- }
-
- void splitFallback(const PrimInfoRange& pinfo, PrimInfoRange& linfo, PrimInfoRange& rinfo)
- {
- const size_t begin = pinfo.begin();
- const size_t end = pinfo.end();
- const size_t center = (begin + end)/2;
-
- CentGeomBBox3fa left(empty);
- for (size_t i=begin; i<center; i++)
- left.extend_center2(prims[i]);
- new (&linfo) PrimInfoRange(begin,center,left);
-
- CentGeomBBox3fa right(empty);
- for (size_t i=center; i<end; i++)
- right.extend_center2(prims[i]);
- new (&rinfo) PrimInfoRange(center,end,right);
- }
-
- void splitByGeometry(const range<size_t>& range, PrimInfoRange& linfo, PrimInfoRange& rinfo)
- {
- assert(range.size() > 1);
- CentGeomBBox3fa left(empty);
- CentGeomBBox3fa right(empty);
- unsigned int geomID = prims[range.begin()].geomID();
- size_t center = serial_partitioning(prims,range.begin(),range.end(),left,right,
- [&] ( const PrimRef& prim ) { return prim.geomID() == geomID; },
- [ ] ( CentGeomBBox3fa& a, const PrimRef& ref ) { a.extend_center2(ref); });
-
- new (&linfo) PrimInfoRange(range.begin(),center,left);
- new (&rinfo) PrimInfoRange(center,range.end(),right);
- }
-
- private:
- PrimRef* const prims;
- };
-
- /*! Performs standard object binning */
- template<typename PrimRefMB, size_t BINS>
- struct HeuristicArrayBinningMB
- {
- typedef BinSplit<BINS> Split;
- typedef typename PrimRefMB::BBox BBox;
- typedef BinInfoT<BINS,PrimRefMB,BBox> ObjectBinner;
- static const size_t PARALLEL_THRESHOLD = 3 * 1024;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
-
- /*! finds the best split */
- const Split find(const SetMB& set, const size_t logBlockSize)
- {
- ObjectBinner binner(empty);
- const BinMapping<BINS> mapping(set.size(),set.centBounds);
- bin_parallel(binner,set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,mapping);
- Split osplit = binner.best(mapping,logBlockSize);
- osplit.sah *= set.time_range.size();
- if (!osplit.valid()) osplit.data = Split::SPLIT_FALLBACK; // use fallback split
- return osplit;
- }
-
- /*! array partitioning */
- __forceinline void split(const Split& split, const SetMB& set, SetMB& lset, SetMB& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfoMB left = empty;
- PrimInfoMB right = empty;
- const vint4 vSplitPos(split.pos);
- const vbool4 vSplitMask(1 << split.dim);
- auto isLeft = [&] (const PrimRefMB &ref) { return any(((vint4)split.mapping.bin_unsafe(ref) < vSplitPos) & vSplitMask); };
- auto reduction = [] (PrimInfoMB& pinfo, const PrimRefMB& ref) { pinfo.add_primref(ref); };
- auto reduction2 = [] (PrimInfoMB& pinfo0,const PrimInfoMB& pinfo1) { pinfo0.merge(pinfo1); };
- size_t center = parallel_partitioning(set.prims->data(),begin,end,EmptyTy(),left,right,isLeft,reduction,reduction2,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD);
- new (&lset) SetMB(left, set.prims,range<size_t>(begin,center),set.time_range);
- new (&rset) SetMB(right,set.prims,range<size_t>(center,end ),set.time_range);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/heuristic_binning_array_unaligned.h b/thirdparty/embree-aarch64/kernels/builders/heuristic_binning_array_unaligned.h
deleted file mode 100644
index 1370244586..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/heuristic_binning_array_unaligned.h
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "heuristic_binning.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Performs standard object binning */
- template<typename PrimRef, size_t BINS>
- struct UnalignedHeuristicArrayBinningSAH
- {
- typedef BinSplit<BINS> Split;
- typedef BinInfoT<BINS,PrimRef,BBox3fa> Binner;
- typedef range<size_t> Set;
-
- __forceinline UnalignedHeuristicArrayBinningSAH () // FIXME: required?
- : scene(nullptr), prims(nullptr) {}
-
- /*! remember prim array */
- __forceinline UnalignedHeuristicArrayBinningSAH (Scene* scene, PrimRef* prims)
- : scene(scene), prims(prims) {}
-
- const LinearSpace3fa computeAlignedSpace(const range<size_t>& set)
- {
- Vec3fa axis(0,0,1);
- uint64_t bestGeomPrimID = -1;
-
- /*! find curve with minimum ID that defines valid direction */
- for (size_t i=set.begin(); i<set.end(); i++)
- {
- const unsigned int geomID = prims[i].geomID();
- const unsigned int primID = prims[i].primID();
- const uint64_t geomprimID = prims[i].ID64();
- if (geomprimID >= bestGeomPrimID) continue;
- const Vec3fa axis1 = scene->get(geomID)->computeDirection(primID);
- if (sqr_length(axis1) > 1E-18f) {
- axis = normalize(axis1);
- bestGeomPrimID = geomprimID;
- }
- }
- return frame(axis).transposed();
- }
-
- const PrimInfo computePrimInfo(const range<size_t>& set, const LinearSpace3fa& space)
- {
- auto computeBounds = [&](const range<size_t>& r) -> CentGeomBBox3fa
- {
- CentGeomBBox3fa bounds(empty);
- for (size_t i=r.begin(); i<r.end(); i++) {
- Geometry* mesh = scene->get(prims[i].geomID());
- bounds.extend(mesh->vbounds(space,prims[i].primID()));
- }
- return bounds;
- };
-
- const CentGeomBBox3fa bounds = parallel_reduce(set.begin(), set.end(), size_t(1024), size_t(4096),
- CentGeomBBox3fa(empty), computeBounds, CentGeomBBox3fa::merge2);
-
- return PrimInfo(set.begin(),set.end(),bounds);
- }
-
- struct BinBoundsAndCenter
- {
- __forceinline BinBoundsAndCenter(Scene* scene, const LinearSpace3fa& space)
- : scene(scene), space(space) {}
-
- /*! returns center for binning */
- __forceinline Vec3fa binCenter(const PrimRef& ref) const
- {
- Geometry* mesh = (Geometry*) scene->get(ref.geomID());
- BBox3fa bounds = mesh->vbounds(space,ref.primID());
- return embree::center2(bounds);
- }
-
- /*! returns bounds and centroid used for binning */
- __forceinline void binBoundsAndCenter(const PrimRef& ref, BBox3fa& bounds_o, Vec3fa& center_o) const
- {
- Geometry* mesh = (Geometry*) scene->get(ref.geomID());
- BBox3fa bounds = mesh->vbounds(space,ref.primID());
- bounds_o = bounds;
- center_o = embree::center2(bounds);
- }
-
- private:
- Scene* scene;
- const LinearSpace3fa space;
- };
-
- /*! finds the best split */
- __forceinline const Split find(const PrimInfoRange& pinfo, const size_t logBlockSize, const LinearSpace3fa& space)
- {
- if (likely(pinfo.size() < 10000))
- return find_template<false>(pinfo,logBlockSize,space);
- else
- return find_template<true>(pinfo,logBlockSize,space);
- }
-
- /*! finds the best split */
- template<bool parallel>
- const Split find_template(const PrimInfoRange& set, const size_t logBlockSize, const LinearSpace3fa& space)
- {
- Binner binner(empty);
- const BinMapping<BINS> mapping(set);
- BinBoundsAndCenter binBoundsAndCenter(scene,space);
- bin_serial_or_parallel<parallel>(binner,prims,set.begin(),set.end(),size_t(4096),mapping,binBoundsAndCenter);
- return binner.best(mapping,logBlockSize);
- }
-
- /*! array partitioning */
- __forceinline void split(const Split& split, const LinearSpace3fa& space, const Set& set, PrimInfoRange& lset, PrimInfoRange& rset)
- {
- if (likely(set.size() < 10000))
- split_template<false>(split,space,set,lset,rset);
- else
- split_template<true>(split,space,set,lset,rset);
- }
-
- /*! array partitioning */
- template<bool parallel>
- __forceinline void split_template(const Split& split, const LinearSpace3fa& space, const Set& set, PrimInfoRange& lset, PrimInfoRange& rset)
- {
- if (!split.valid()) {
- deterministic_order(set);
- return splitFallback(set,lset,rset);
- }
-
- const size_t begin = set.begin();
- const size_t end = set.end();
- CentGeomBBox3fa local_left(empty);
- CentGeomBBox3fa local_right(empty);
- const int splitPos = split.pos;
- const int splitDim = split.dim;
- BinBoundsAndCenter binBoundsAndCenter(scene,space);
-
- size_t center = 0;
- if (likely(set.size() < 10000))
- center = serial_partitioning(prims,begin,end,local_left,local_right,
- [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,binBoundsAndCenter)[splitDim] < splitPos; },
- [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend_center2(ref); });
- else
- center = parallel_partitioning(prims,begin,end,EmptyTy(),local_left,local_right,
- [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,binBoundsAndCenter)[splitDim] < splitPos; },
- [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend_center2(ref); },
- [] (CentGeomBBox3fa& pinfo0,const CentGeomBBox3fa& pinfo1) { pinfo0.merge(pinfo1); },
- 128);
-
- new (&lset) PrimInfoRange(begin,center,local_left);
- new (&rset) PrimInfoRange(center,end,local_right);
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
- }
-
- void deterministic_order(const range<size_t>& set)
- {
- /* required as parallel partition destroys original primitive order */
- std::sort(&prims[set.begin()],&prims[set.end()]);
- }
-
- void splitFallback(const range<size_t>& set, PrimInfoRange& lset, PrimInfoRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- const size_t center = (begin + end)/2;
-
- CentGeomBBox3fa left(empty);
- for (size_t i=begin; i<center; i++)
- left.extend_center2(prims[i]);
- new (&lset) PrimInfoRange(begin,center,left);
-
- CentGeomBBox3fa right(empty);
- for (size_t i=center; i<end; i++)
- right.extend_center2(prims[i]);
- new (&rset) PrimInfoRange(center,end,right);
- }
-
- private:
- Scene* const scene;
- PrimRef* const prims;
- };
-
- /*! Performs standard object binning */
- template<typename PrimRefMB, size_t BINS>
- struct UnalignedHeuristicArrayBinningMB
- {
- typedef BinSplit<BINS> Split;
- typedef typename PrimRefMB::BBox BBox;
- typedef BinInfoT<BINS,PrimRefMB,BBox> ObjectBinner;
-
- static const size_t PARALLEL_THRESHOLD = 3 * 1024;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
-
- UnalignedHeuristicArrayBinningMB(Scene* scene)
- : scene(scene) {}
-
- const LinearSpace3fa computeAlignedSpaceMB(Scene* scene, const SetMB& set)
- {
- Vec3fa axis0(0,0,1);
- uint64_t bestGeomPrimID = -1;
-
- /*! find curve with minimum ID that defines valid direction */
- for (size_t i=set.begin(); i<set.end(); i++)
- {
- const PrimRefMB& prim = (*set.prims)[i];
- const unsigned int geomID = prim.geomID();
- const unsigned int primID = prim.primID();
- const uint64_t geomprimID = prim.ID64();
- if (geomprimID >= bestGeomPrimID) continue;
-
- const Geometry* mesh = scene->get(geomID);
- const range<int> tbounds = mesh->timeSegmentRange(set.time_range);
- if (tbounds.size() == 0) continue;
-
- const size_t t = (tbounds.begin()+tbounds.end())/2;
- const Vec3fa axis1 = mesh->computeDirection(primID,t);
- if (sqr_length(axis1) > 1E-18f) {
- axis0 = normalize(axis1);
- bestGeomPrimID = geomprimID;
- }
- }
-
- return frame(axis0).transposed();
- }
-
- struct BinBoundsAndCenter
- {
- __forceinline BinBoundsAndCenter(Scene* scene, BBox1f time_range, const LinearSpace3fa& space)
- : scene(scene), time_range(time_range), space(space) {}
-
- /*! returns center for binning */
- template<typename PrimRef>
- __forceinline Vec3fa binCenter(const PrimRef& ref) const
- {
- Geometry* mesh = scene->get(ref.geomID());
- LBBox3fa lbounds = mesh->vlinearBounds(space,ref.primID(),time_range);
- return center2(lbounds.interpolate(0.5f));
- }
-
- /*! returns bounds and centroid used for binning */
- __noinline void binBoundsAndCenter (const PrimRefMB& ref, BBox3fa& bounds_o, Vec3fa& center_o) const // __noinline is workaround for ICC16 bug under MacOSX
- {
- Geometry* mesh = scene->get(ref.geomID());
- LBBox3fa lbounds = mesh->vlinearBounds(space,ref.primID(),time_range);
- bounds_o = lbounds.interpolate(0.5f);
- center_o = center2(bounds_o);
- }
-
- /*! returns bounds and centroid used for binning */
- __noinline void binBoundsAndCenter (const PrimRefMB& ref, LBBox3fa& bounds_o, Vec3fa& center_o) const // __noinline is workaround for ICC16 bug under MacOSX
- {
- Geometry* mesh = scene->get(ref.geomID());
- LBBox3fa lbounds = mesh->vlinearBounds(space,ref.primID(),time_range);
- bounds_o = lbounds;
- center_o = center2(lbounds.interpolate(0.5f));
- }
-
- private:
- Scene* scene;
- BBox1f time_range;
- const LinearSpace3fa space;
- };
-
- /*! finds the best split */
- const Split find(const SetMB& set, const size_t logBlockSize, const LinearSpace3fa& space)
- {
- BinBoundsAndCenter binBoundsAndCenter(scene,set.time_range,space);
- ObjectBinner binner(empty);
- const BinMapping<BINS> mapping(set.size(),set.centBounds);
- bin_parallel(binner,set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,mapping,binBoundsAndCenter);
- Split osplit = binner.best(mapping,logBlockSize);
- osplit.sah *= set.time_range.size();
- if (!osplit.valid()) osplit.data = Split::SPLIT_FALLBACK; // use fallback split
- return osplit;
- }
-
- /*! array partitioning */
- __forceinline void split(const Split& split, const LinearSpace3fa& space, const SetMB& set, SetMB& lset, SetMB& rset)
- {
- BinBoundsAndCenter binBoundsAndCenter(scene,set.time_range,space);
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfoMB left = empty;
- PrimInfoMB right = empty;
- const vint4 vSplitPos(split.pos);
- const vbool4 vSplitMask(1 << split.dim);
- auto isLeft = [&] (const PrimRefMB &ref) { return any(((vint4)split.mapping.bin_unsafe(ref,binBoundsAndCenter) < vSplitPos) & vSplitMask); };
- auto reduction = [] (PrimInfoMB& pinfo, const PrimRefMB& ref) { pinfo.add_primref(ref); };
- auto reduction2 = [] (PrimInfoMB& pinfo0,const PrimInfoMB& pinfo1) { pinfo0.merge(pinfo1); };
- size_t center = parallel_partitioning(set.prims->data(),begin,end,EmptyTy(),left,right,isLeft,reduction,reduction2,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD);
- new (&lset) SetMB(left,set.prims,range<size_t>(begin,center),set.time_range);
- new (&rset) SetMB(right,set.prims,range<size_t>(center,end ),set.time_range);
- }
-
- private:
- Scene* scene;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/heuristic_openmerge_array.h b/thirdparty/embree-aarch64/kernels/builders/heuristic_openmerge_array.h
deleted file mode 100644
index 21f18c0208..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/heuristic_openmerge_array.h
+++ /dev/null
@@ -1,443 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-// TODO:
-// - adjust parallel build thresholds
-// - openNodesBasedOnExtend should consider max extended size
-
-#pragma once
-
-#include "heuristic_binning.h"
-#include "heuristic_spatial.h"
-
-/* stop opening of all bref.geomIDs are the same */
-#define EQUAL_GEOMID_STOP_CRITERIA 1
-
-/* 10% spatial extend threshold */
-#define MAX_EXTEND_THRESHOLD 0.1f
-
-/* maximum is 8 children */
-#define MAX_OPENED_CHILD_NODES 8
-
-/* open until all build refs are below threshold size in one step */
-#define USE_LOOP_OPENING 0
-
-namespace embree
-{
- namespace isa
- {
- /*! Performs standard object binning */
- template<typename NodeOpenerFunc, typename PrimRef, size_t OBJECT_BINS>
- struct HeuristicArrayOpenMergeSAH
- {
- typedef BinSplit<OBJECT_BINS> Split;
- typedef BinInfoT<OBJECT_BINS,PrimRef,BBox3fa> Binner;
-
- static const size_t PARALLEL_THRESHOLD = 1024;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 512;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
-
- static const size_t MOVE_STEP_SIZE = 64;
- static const size_t CREATE_SPLITS_STEP_SIZE = 128;
-
- __forceinline HeuristicArrayOpenMergeSAH ()
- : prims0(nullptr) {}
-
- /*! remember prim array */
- __forceinline HeuristicArrayOpenMergeSAH (const NodeOpenerFunc& nodeOpenerFunc, PrimRef* prims0, size_t max_open_size)
- : prims0(prims0), nodeOpenerFunc(nodeOpenerFunc), max_open_size(max_open_size)
- {
- assert(max_open_size <= MAX_OPENED_CHILD_NODES);
- }
-
- struct OpenHeuristic
- {
- __forceinline OpenHeuristic( const PrimInfoExtRange& pinfo )
- {
- const Vec3fa diag = pinfo.geomBounds.size();
- dim = maxDim(diag);
- assert(diag[dim] > 0.0f);
- inv_max_extend = 1.0f / diag[dim];
- }
-
- __forceinline bool operator () ( PrimRef& prim ) const {
- return !prim.node.isLeaf() && prim.bounds().size()[dim] * inv_max_extend > MAX_EXTEND_THRESHOLD;
- }
-
- private:
- size_t dim;
- float inv_max_extend;
- };
-
- /*! compute extended ranges */
- __forceinline void setExtentedRanges(const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset, const size_t lweight, const size_t rweight)
- {
- assert(set.ext_range_size() > 0);
- const float left_factor = (float)lweight / (lweight + rweight);
- const size_t ext_range_size = set.ext_range_size();
- const size_t left_ext_range_size = min((size_t)(floorf(left_factor * ext_range_size)),ext_range_size);
- const size_t right_ext_range_size = ext_range_size - left_ext_range_size;
- lset.set_ext_range(lset.end() + left_ext_range_size);
- rset.set_ext_range(rset.end() + right_ext_range_size);
- }
-
- /*! move ranges */
- __forceinline void moveExtentedRange(const PrimInfoExtRange& set, const PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t left_ext_range_size = lset.ext_range_size();
- const size_t right_size = rset.size();
-
- /* has the left child an extended range? */
- if (left_ext_range_size > 0)
- {
- /* left extended range smaller than right range ? */
- if (left_ext_range_size < right_size)
- {
- /* only move a small part of the beginning of the right range to the end */
- parallel_for( rset.begin(), rset.begin()+left_ext_range_size, MOVE_STEP_SIZE, [&](const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++)
- prims0[i+right_size] = prims0[i];
- });
- }
- else
- {
- /* no overlap, move entire right range to new location, can be made fully parallel */
- parallel_for( rset.begin(), rset.end(), MOVE_STEP_SIZE, [&](const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++)
- prims0[i+left_ext_range_size] = prims0[i];
- });
- }
- /* update right range */
- assert(rset.ext_end() + left_ext_range_size == set.ext_end());
- rset.move_right(left_ext_range_size);
- }
- }
-
- /* estimates the extra space required when opening, and checks if all primitives are from same geometry */
- __noinline std::pair<size_t,bool> getProperties(const PrimInfoExtRange& set)
- {
- const OpenHeuristic heuristic(set);
- const unsigned int geomID = prims0[set.begin()].geomID();
-
- auto body = [&] (const range<size_t>& r) -> std::pair<size_t,bool> {
- bool commonGeomID = true;
- size_t opens = 0;
- for (size_t i=r.begin(); i<r.end(); i++) {
- commonGeomID &= prims0[i].geomID() == geomID;
- if (heuristic(prims0[i]))
- opens += prims0[i].node.getN()-1; // coarse approximation
- }
- return std::pair<size_t,bool>(opens,commonGeomID);
- };
- auto reduction = [&] (const std::pair<size_t,bool>& b0, const std::pair<size_t,bool>& b1) -> std::pair<size_t,bool> {
- return std::pair<size_t,bool>(b0.first+b1.first,b0.second && b1.second);
- };
- return parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,std::pair<size_t,bool>(0,true),body,reduction);
- }
-
- // FIXME: should consider maximum available extended size
- __noinline void openNodesBasedOnExtend(PrimInfoExtRange& set)
- {
- const OpenHeuristic heuristic(set);
- const size_t ext_range_start = set.end();
-
- if (false && set.size() < PARALLEL_THRESHOLD)
- {
- size_t extra_elements = 0;
- for (size_t i=set.begin(); i<set.end(); i++)
- {
- if (heuristic(prims0[i]))
- {
- PrimRef tmp[MAX_OPENED_CHILD_NODES];
- const size_t n = nodeOpenerFunc(prims0[i],tmp);
- assert(extra_elements + n-1 <= set.ext_range_size());
- for (size_t j=0; j<n; j++)
- set.extend_center2(tmp[j]);
-
- prims0[i] = tmp[0];
- for (size_t j=1; j<n; j++)
- prims0[ext_range_start+extra_elements+j-1] = tmp[j];
- extra_elements += n-1;
- }
- }
- set._end += extra_elements;
- }
- else
- {
- std::atomic<size_t> ext_elements;
- ext_elements.store(0);
- PrimInfo info = parallel_reduce( set.begin(), set.end(), CREATE_SPLITS_STEP_SIZE, PrimInfo(empty), [&](const range<size_t>& r) -> PrimInfo {
- PrimInfo info(empty);
- for (size_t i=r.begin(); i<r.end(); i++)
- if (heuristic(prims0[i]))
- {
- PrimRef tmp[MAX_OPENED_CHILD_NODES];
- const size_t n = nodeOpenerFunc(prims0[i],tmp);
- const size_t ID = ext_elements.fetch_add(n-1);
- assert(ID + n-1 <= set.ext_range_size());
-
- for (size_t j=0; j<n; j++)
- info.extend_center2(tmp[j]);
-
- prims0[i] = tmp[0];
- for (size_t j=1; j<n; j++)
- prims0[ext_range_start+ID+j-1] = tmp[j];
- }
- return info;
- }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
- set.centBounds.extend(info.centBounds);
- assert(ext_elements.load() <= set.ext_range_size());
- set._end += ext_elements.load();
- }
- }
-
- __noinline void openNodesBasedOnExtendLoop(PrimInfoExtRange& set, const size_t est_new_elements)
- {
- const OpenHeuristic heuristic(set);
- size_t next_iteration_extra_elements = est_new_elements;
-
- while (next_iteration_extra_elements <= set.ext_range_size())
- {
- next_iteration_extra_elements = 0;
- size_t extra_elements = 0;
- const size_t ext_range_start = set.end();
-
- for (size_t i=set.begin(); i<set.end(); i++)
- {
- if (heuristic(prims0[i]))
- {
- PrimRef tmp[MAX_OPENED_CHILD_NODES];
- const size_t n = nodeOpenerFunc(prims0[i],tmp);
- assert(extra_elements + n-1 <= set.ext_range_size());
- for (size_t j=0;j<n;j++)
- set.extend_center2(tmp[j]);
-
- prims0[i] = tmp[0];
- for (size_t j=1;j<n;j++)
- prims0[ext_range_start+extra_elements+j-1] = tmp[j];
- extra_elements += n-1;
-
- for (size_t j=0; j<n; j++)
- if (heuristic(tmp[j]))
- next_iteration_extra_elements += tmp[j].node.getN()-1; // coarse approximation
-
- }
- }
- assert( extra_elements <= set.ext_range_size());
- set._end += extra_elements;
-
- for (size_t i=set.begin();i<set.end();i++)
- assert(prims0[i].numPrimitives() > 0);
-
- if (unlikely(next_iteration_extra_elements == 0)) break;
- }
- }
-
- __noinline const Split find(PrimInfoExtRange& set, const size_t logBlockSize)
- {
- /* single element */
- if (set.size() <= 1)
- return Split();
-
- /* disable opening if there is no overlap */
- const size_t D = 4;
- if (unlikely(set.has_ext_range() && set.size() <= D))
- {
- bool disjoint = true;
- for (size_t j=set.begin(); j<set.end()-1; j++) {
- for (size_t i=set.begin()+1; i<set.end(); i++) {
- if (conjoint(prims0[j].bounds(),prims0[i].bounds())) {
- disjoint = false; break;
- }
- }
- }
- if (disjoint) set.set_ext_range(set.end()); /* disables opening */
- }
-
- std::pair<size_t,bool> p(0,false);
-
- /* disable opening when all primitives are from same geometry */
- if (unlikely(set.has_ext_range()))
- {
- p = getProperties(set);
-#if EQUAL_GEOMID_STOP_CRITERIA == 1
- if (p.second) set.set_ext_range(set.end()); /* disable opening */
-#endif
- }
-
- /* open nodes when we have sufficient space available */
- if (unlikely(set.has_ext_range()))
- {
-#if USE_LOOP_OPENING == 1
- openNodesBasedOnExtendLoop(set,p.first);
-#else
- if (p.first <= set.ext_range_size())
- openNodesBasedOnExtend(set);
-#endif
-
- /* disable opening when unsufficient space for opening a node available */
- if (set.ext_range_size() < max_open_size-1)
- set.set_ext_range(set.end()); /* disable opening */
- }
-
- /* find best split */
- return object_find(set,logBlockSize);
- }
-
-
- /*! finds the best object split */
- __forceinline const Split object_find(const PrimInfoExtRange& set,const size_t logBlockSize)
- {
- if (set.size() < PARALLEL_THRESHOLD) return sequential_object_find(set,logBlockSize);
- else return parallel_object_find (set,logBlockSize);
- }
-
- /*! finds the best object split */
- __noinline const Split sequential_object_find(const PrimInfoExtRange& set, const size_t logBlockSize)
- {
- Binner binner(empty);
- const BinMapping<OBJECT_BINS> mapping(set.centBounds);
- binner.bin(prims0,set.begin(),set.end(),mapping);
- return binner.best(mapping,logBlockSize);
- }
-
- /*! finds the best split */
- __noinline const Split parallel_object_find(const PrimInfoExtRange& set, const size_t logBlockSize)
- {
- Binner binner(empty);
- const BinMapping<OBJECT_BINS> mapping(set.centBounds);
- const BinMapping<OBJECT_BINS>& _mapping = mapping; // CLANG 3.4 parser bug workaround
- auto body = [&] (const range<size_t>& r) -> Binner {
- Binner binner(empty); binner.bin(prims0+r.begin(),r.size(),_mapping); return binner;
- };
- auto reduction = [&] (const Binner& b0, const Binner& b1) -> Binner {
- Binner r = b0; r.merge(b1,_mapping.size()); return r;
- };
- binner = parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,binner,body,reduction);
- return binner.best(mapping,logBlockSize);
- }
-
- /*! array partitioning */
- __noinline void split(const Split& split, const PrimInfoExtRange& set_i, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- PrimInfoExtRange set = set_i;
-
- /* valid split */
- if (unlikely(!split.valid())) {
- deterministic_order(set);
- splitFallback(set,lset,rset);
- return;
- }
-
- std::pair<size_t,size_t> ext_weights(0,0);
-
- /* object split */
- if (likely(set.size() < PARALLEL_THRESHOLD))
- ext_weights = sequential_object_split(split,set,lset,rset);
- else
- ext_weights = parallel_object_split(split,set,lset,rset);
-
- /* if we have an extended range, set extended child ranges and move right split range */
- if (unlikely(set.has_ext_range()))
- {
- setExtentedRanges(set,lset,rset,ext_weights.first,ext_weights.second);
- moveExtentedRange(set,lset,rset);
- }
- }
-
- /*! array partitioning */
- std::pair<size_t,size_t> sequential_object_split(const Split& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfo local_left(empty);
- PrimInfo local_right(empty);
- const unsigned int splitPos = split.pos;
- const unsigned int splitDim = split.dim;
- const unsigned int splitDimMask = (unsigned int)1 << splitDim;
-
- const vint4 vSplitPos(splitPos);
- const vbool4 vSplitMask( (int)splitDimMask );
-
- size_t center = serial_partitioning(prims0,
- begin,end,local_left,local_right,
- [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask); },
- [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref); });
-
- new (&lset) PrimInfoExtRange(begin,center,center,local_left);
- new (&rset) PrimInfoExtRange(center,end,end,local_right);
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
- return std::pair<size_t,size_t>(local_left.size(),local_right.size());
- }
-
- /*! array partitioning */
- __noinline std::pair<size_t,size_t> parallel_object_split(const Split& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfo left(empty);
- PrimInfo right(empty);
- const unsigned int splitPos = split.pos;
- const unsigned int splitDim = split.dim;
- const unsigned int splitDimMask = (unsigned int)1 << splitDim;
-
- const vint4 vSplitPos(splitPos);
- const vbool4 vSplitMask( (int)splitDimMask );
- auto isLeft = [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask); };
-
- const size_t center = parallel_partitioning(
- prims0,begin,end,EmptyTy(),left,right,isLeft,
- [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref); },
- [] (PrimInfo& pinfo0,const PrimInfo& pinfo1) { pinfo0.merge(pinfo1); },
- PARALLEL_PARTITION_BLOCK_SIZE);
-
- new (&lset) PrimInfoExtRange(begin,center,center,left);
- new (&rset) PrimInfoExtRange(center,end,end,right);
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
-
- return std::pair<size_t,size_t>(left.size(),right.size());
- }
-
- void deterministic_order(const extended_range<size_t>& set)
- {
- /* required as parallel partition destroys original primitive order */
- std::sort(&prims0[set.begin()],&prims0[set.end()]);
- }
-
- __forceinline void splitFallback(const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- const size_t center = (begin + end)/2;
-
- PrimInfo left(empty);
- for (size_t i=begin; i<center; i++)
- left.add_center2(prims0[i]);
-
- const size_t lweight = left.end;
-
- PrimInfo right(empty);
- for (size_t i=center; i<end; i++)
- right.add_center2(prims0[i]);
-
- const size_t rweight = right.end;
- new (&lset) PrimInfoExtRange(begin,center,center,left);
- new (&rset) PrimInfoExtRange(center,end,end,right);
-
- /* if we have an extended range */
- if (set.has_ext_range())
- {
- setExtentedRanges(set,lset,rset,lweight,rweight);
- moveExtentedRange(set,lset,rset);
- }
- }
-
- private:
- PrimRef* const prims0;
- const NodeOpenerFunc& nodeOpenerFunc;
- size_t max_open_size;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/heuristic_spatial.h b/thirdparty/embree-aarch64/kernels/builders/heuristic_spatial.h
deleted file mode 100644
index d8ca6cb92c..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/heuristic_spatial.h
+++ /dev/null
@@ -1,414 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/scene.h"
-#include "priminfo.h"
-
-namespace embree
-{
- static const unsigned int RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS = 5;
-
- namespace isa
- {
-
- /*! mapping into bins */
- template<size_t BINS>
- struct SpatialBinMapping
- {
- public:
- __forceinline SpatialBinMapping() {}
-
- /*! calculates the mapping */
- __forceinline SpatialBinMapping(const CentGeomBBox3fa& pinfo)
- {
- const vfloat4 lower = (vfloat4) pinfo.geomBounds.lower;
- const vfloat4 upper = (vfloat4) pinfo.geomBounds.upper;
- const vfloat4 eps = 128.0f*vfloat4(ulp)*max(abs(lower),abs(upper));
- const vfloat4 diag = max(eps,(vfloat4) pinfo.geomBounds.size());
- scale = select(upper-lower <= eps,vfloat4(0.0f),vfloat4(BINS)/diag);
- ofs = (vfloat4) pinfo.geomBounds.lower;
- inv_scale = 1.0f / scale;
- }
-
- /*! slower but safe binning */
- __forceinline vint4 bin(const Vec3fa& p) const
- {
- const vint4 i = floori((vfloat4(p)-ofs)*scale);
- return clamp(i,vint4(0),vint4(BINS-1));
- }
-
- __forceinline std::pair<vint4,vint4> bin(const BBox3fa& b) const
- {
-#if defined(__AVX__)
- const vfloat8 ofs8(ofs);
- const vfloat8 scale8(scale);
- const vint8 lu = floori((vfloat8::loadu(&b)-ofs8)*scale8);
- const vint8 c_lu = clamp(lu,vint8(zero),vint8(BINS-1));
- return std::pair<vint4,vint4>(extract4<0>(c_lu),extract4<1>(c_lu));
-#else
- const vint4 lower = floori((vfloat4(b.lower)-ofs)*scale);
- const vint4 upper = floori((vfloat4(b.upper)-ofs)*scale);
- const vint4 c_lower = clamp(lower,vint4(0),vint4(BINS-1));
- const vint4 c_upper = clamp(upper,vint4(0),vint4(BINS-1));
- return std::pair<vint4,vint4>(c_lower,c_upper);
-#endif
- }
-
-
- /*! calculates left spatial position of bin */
- __forceinline float pos(const size_t bin, const size_t dim) const {
- return madd(float(bin),inv_scale[dim],ofs[dim]);
- }
-
- /*! calculates left spatial position of bin */
- template<size_t N>
- __forceinline vfloat<N> posN(const vfloat<N> bin, const size_t dim) const {
- return madd(bin,vfloat<N>(inv_scale[dim]),vfloat<N>(ofs[dim]));
- }
-
- /*! returns true if the mapping is invalid in some dimension */
- __forceinline bool invalid(const size_t dim) const {
- return scale[dim] == 0.0f;
- }
-
- public:
- vfloat4 ofs,scale,inv_scale; //!< linear function that maps to bin ID
- };
-
- /*! stores all information required to perform some split */
- template<size_t BINS>
- struct SpatialBinSplit
- {
- /*! construct an invalid split by default */
- __forceinline SpatialBinSplit()
- : sah(inf), dim(-1), pos(0), left(-1), right(-1), factor(1.0f) {}
-
- /*! constructs specified split */
- __forceinline SpatialBinSplit(float sah, int dim, int pos, const SpatialBinMapping<BINS>& mapping)
- : sah(sah), dim(dim), pos(pos), left(-1), right(-1), factor(1.0f), mapping(mapping) {}
-
- /*! constructs specified split */
- __forceinline SpatialBinSplit(float sah, int dim, int pos, int left, int right, float factor, const SpatialBinMapping<BINS>& mapping)
- : sah(sah), dim(dim), pos(pos), left(left), right(right), factor(factor), mapping(mapping) {}
-
- /*! tests if this split is valid */
- __forceinline bool valid() const { return dim != -1; }
-
- /*! calculates surface area heuristic for performing the split */
- __forceinline float splitSAH() const { return sah; }
-
- /*! stream output */
- friend embree_ostream operator<<(embree_ostream cout, const SpatialBinSplit& split) {
- return cout << "SpatialBinSplit { sah = " << split.sah << ", dim = " << split.dim << ", pos = " << split.pos << ", left = " << split.left << ", right = " << split.right << ", factor = " << split.factor << "}";
- }
-
- public:
- float sah; //!< SAH cost of the split
- int dim; //!< split dimension
- int pos; //!< split position
- int left; //!< number of elements on the left side
- int right; //!< number of elements on the right side
- float factor; //!< factor splitting the extended range
- SpatialBinMapping<BINS> mapping; //!< mapping into bins
- };
-
- /*! stores all binning information */
- template<size_t BINS, typename PrimRef>
- struct __aligned(64) SpatialBinInfo
- {
- SpatialBinInfo() {
- }
-
- __forceinline SpatialBinInfo(EmptyTy) {
- clear();
- }
-
- /*! clears the bin info */
- __forceinline void clear()
- {
- for (size_t i=0; i<BINS; i++) {
- bounds[i][0] = bounds[i][1] = bounds[i][2] = empty;
- numBegin[i] = numEnd[i] = 0;
- }
- }
-
- /*! adds binning data */
- __forceinline void add(const size_t dim,
- const size_t beginID,
- const size_t endID,
- const size_t binID,
- const BBox3fa &b,
- const size_t n = 1)
- {
- assert(beginID < BINS);
- assert(endID < BINS);
- assert(binID < BINS);
-
- numBegin[beginID][dim]+=(unsigned int)n;
- numEnd [endID][dim]+=(unsigned int)n;
- bounds [binID][dim].extend(b);
- }
-
- /*! extends binning bounds */
- __forceinline void extend(const size_t dim,
- const size_t binID,
- const BBox3fa &b)
- {
- assert(binID < BINS);
- bounds [binID][dim].extend(b);
- }
-
- /*! bins an array of triangles */
- template<typename SplitPrimitive>
- __forceinline void bin(const SplitPrimitive& splitPrimitive, const PrimRef* prims, size_t N, const SpatialBinMapping<BINS>& mapping)
- {
- for (size_t i=0; i<N; i++)
- {
- const PrimRef prim = prims[i];
- unsigned splits = prim.geomID() >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
-
- if (unlikely(splits == 1))
- {
- const vint4 bin = mapping.bin(center(prim.bounds()));
- for (size_t dim=0; dim<3; dim++)
- {
- assert(bin[dim] >= (int)0 && bin[dim] < (int)BINS);
- numBegin[bin[dim]][dim]++;
- numEnd [bin[dim]][dim]++;
- bounds [bin[dim]][dim].extend(prim.bounds());
- }
- }
- else
- {
- const vint4 bin0 = mapping.bin(prim.bounds().lower);
- const vint4 bin1 = mapping.bin(prim.bounds().upper);
-
- for (size_t dim=0; dim<3; dim++)
- {
- size_t bin;
- PrimRef rest = prim;
- size_t l = bin0[dim];
- size_t r = bin1[dim];
-
- // same bin optimization
- if (likely(l == r))
- {
- numBegin[l][dim]++;
- numEnd [l][dim]++;
- bounds [l][dim].extend(prim.bounds());
- continue;
- }
-
- for (bin=(size_t)bin0[dim]; bin<(size_t)bin1[dim]; bin++)
- {
- const float pos = mapping.pos(bin+1,dim);
-
- PrimRef left,right;
- splitPrimitive(rest,(int)dim,pos,left,right);
- if (unlikely(left.bounds().empty())) l++;
- bounds[bin][dim].extend(left.bounds());
- rest = right;
- }
- if (unlikely(rest.bounds().empty())) r--;
- numBegin[l][dim]++;
- numEnd [r][dim]++;
- bounds [bin][dim].extend(rest.bounds());
- }
- }
- }
- }
-
- /*! bins a range of primitives inside an array */
- template<typename SplitPrimitive>
- void bin(const SplitPrimitive& splitPrimitive, const PrimRef* prims, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping) {
- bin(splitPrimitive,prims+begin,end-begin,mapping);
- }
-
- /*! bins an array of primitives */
- template<typename PrimitiveSplitterFactory>
- __forceinline void bin2(const PrimitiveSplitterFactory& splitterFactory, const PrimRef* source, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping)
- {
- for (size_t i=begin; i<end; i++)
- {
- const PrimRef &prim = source[i];
- const vint4 bin0 = mapping.bin(prim.bounds().lower);
- const vint4 bin1 = mapping.bin(prim.bounds().upper);
-
- for (size_t dim=0; dim<3; dim++)
- {
- if (unlikely(mapping.invalid(dim)))
- continue;
-
- size_t bin;
- size_t l = bin0[dim];
- size_t r = bin1[dim];
-
- // same bin optimization
- if (likely(l == r))
- {
- add(dim,l,l,l,prim.bounds());
- continue;
- }
- const size_t bin_start = bin0[dim];
- const size_t bin_end = bin1[dim];
- BBox3fa rest = prim.bounds();
- const auto splitter = splitterFactory(prim);
- for (bin=bin_start; bin<bin_end; bin++)
- {
- const float pos = mapping.pos(bin+1,dim);
- BBox3fa left,right;
- splitter(rest,dim,pos,left,right);
- if (unlikely(left.empty())) l++;
- extend(dim,bin,left);
- rest = right;
- }
- if (unlikely(rest.empty())) r--;
- add(dim,l,r,bin,rest);
- }
- }
- }
-
-
-
- /*! bins an array of primitives */
- __forceinline void binSubTreeRefs(const PrimRef* source, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping)
- {
- for (size_t i=begin; i<end; i++)
- {
- const PrimRef &prim = source[i];
- const vint4 bin0 = mapping.bin(prim.bounds().lower);
- const vint4 bin1 = mapping.bin(prim.bounds().upper);
-
- for (size_t dim=0; dim<3; dim++)
- {
- if (unlikely(mapping.invalid(dim)))
- continue;
-
- const size_t l = bin0[dim];
- const size_t r = bin1[dim];
-
- const unsigned int n = prim.primID();
-
- // same bin optimization
- if (likely(l == r))
- {
- add(dim,l,l,l,prim.bounds(),n);
- continue;
- }
- const size_t bin_start = bin0[dim];
- const size_t bin_end = bin1[dim];
- for (size_t bin=bin_start; bin<bin_end; bin++)
- add(dim,l,r,bin,prim.bounds(),n);
- }
- }
- }
-
- /*! merges in other binning information */
- void merge (const SpatialBinInfo& other)
- {
- for (size_t i=0; i<BINS; i++)
- {
- numBegin[i] += other.numBegin[i];
- numEnd [i] += other.numEnd [i];
- bounds[i][0].extend(other.bounds[i][0]);
- bounds[i][1].extend(other.bounds[i][1]);
- bounds[i][2].extend(other.bounds[i][2]);
- }
- }
-
- /*! merges in other binning information */
- static __forceinline const SpatialBinInfo reduce (const SpatialBinInfo& a, const SpatialBinInfo& b)
- {
- SpatialBinInfo c(empty);
- for (size_t i=0; i<BINS; i++)
- {
- c.numBegin[i] += a.numBegin[i]+b.numBegin[i];
- c.numEnd [i] += a.numEnd [i]+b.numEnd [i];
- c.bounds[i][0] = embree::merge(a.bounds[i][0],b.bounds[i][0]);
- c.bounds[i][1] = embree::merge(a.bounds[i][1],b.bounds[i][1]);
- c.bounds[i][2] = embree::merge(a.bounds[i][2],b.bounds[i][2]);
- }
- return c;
- }
-
- /*! finds the best split by scanning binning information */
- SpatialBinSplit<BINS> best(const SpatialBinMapping<BINS>& mapping, const size_t blocks_shift) const
- {
- /* sweep from right to left and compute parallel prefix of merged bounds */
- vfloat4 rAreas[BINS];
- vuint4 rCounts[BINS];
- vuint4 count = 0; BBox3fa bx = empty; BBox3fa by = empty; BBox3fa bz = empty;
- for (size_t i=BINS-1; i>0; i--)
- {
- count += numEnd[i];
- rCounts[i] = count;
- bx.extend(bounds[i][0]); rAreas[i][0] = halfArea(bx);
- by.extend(bounds[i][1]); rAreas[i][1] = halfArea(by);
- bz.extend(bounds[i][2]); rAreas[i][2] = halfArea(bz);
- rAreas[i][3] = 0.0f;
- }
-
- /* sweep from left to right and compute SAH */
- vuint4 blocks_add = (1 << blocks_shift)-1;
- vuint4 ii = 1; vfloat4 vbestSAH = pos_inf; vuint4 vbestPos = 0; vuint4 vbestlCount = 0; vuint4 vbestrCount = 0;
- count = 0; bx = empty; by = empty; bz = empty;
- for (size_t i=1; i<BINS; i++, ii+=1)
- {
- count += numBegin[i-1];
- bx.extend(bounds[i-1][0]); float Ax = halfArea(bx);
- by.extend(bounds[i-1][1]); float Ay = halfArea(by);
- bz.extend(bounds[i-1][2]); float Az = halfArea(bz);
- const vfloat4 lArea = vfloat4(Ax,Ay,Az,Az);
- const vfloat4 rArea = rAreas[i];
- const vuint4 lCount = (count +blocks_add) >> (unsigned int)(blocks_shift);
- const vuint4 rCount = (rCounts[i]+blocks_add) >> (unsigned int)(blocks_shift);
- const vfloat4 sah = madd(lArea,vfloat4(lCount),rArea*vfloat4(rCount));
- // const vfloat4 sah = madd(lArea,vfloat4(vint4(lCount)),rArea*vfloat4(vint4(rCount)));
- const vbool4 mask = sah < vbestSAH;
- vbestPos = select(mask,ii ,vbestPos);
- vbestSAH = select(mask,sah,vbestSAH);
- vbestlCount = select(mask,count,vbestlCount);
- vbestrCount = select(mask,rCounts[i],vbestrCount);
- }
-
- /* find best dimension */
- float bestSAH = inf;
- int bestDim = -1;
- int bestPos = 0;
- unsigned int bestlCount = 0;
- unsigned int bestrCount = 0;
- for (int dim=0; dim<3; dim++)
- {
- /* ignore zero sized dimensions */
- if (unlikely(mapping.invalid(dim)))
- continue;
-
- /* test if this is a better dimension */
- if (vbestSAH[dim] < bestSAH && vbestPos[dim] != 0) {
- bestDim = dim;
- bestPos = vbestPos[dim];
- bestSAH = vbestSAH[dim];
- bestlCount = vbestlCount[dim];
- bestrCount = vbestrCount[dim];
- }
- }
- assert(bestSAH >= 0.0f);
-
- /* return invalid split if no split found */
- if (bestDim == -1)
- return SpatialBinSplit<BINS>(inf,-1,0,mapping);
-
- /* return best found split */
- return SpatialBinSplit<BINS>(bestSAH,bestDim,bestPos,bestlCount,bestrCount,1.0f,mapping);
- }
-
- private:
- BBox3fa bounds[BINS][3]; //!< geometry bounds for each bin in each dimension
- vuint4 numBegin[BINS]; //!< number of primitives starting in bin
- vuint4 numEnd[BINS]; //!< number of primitives ending in bin
- };
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/builders/heuristic_spatial_array.h b/thirdparty/embree-aarch64/kernels/builders/heuristic_spatial_array.h
deleted file mode 100644
index 911dcf950c..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/heuristic_spatial_array.h
+++ /dev/null
@@ -1,552 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "heuristic_binning.h"
-#include "heuristic_spatial.h"
-
-namespace embree
-{
- namespace isa
- {
-#if 0
-#define SPATIAL_ASPLIT_OVERLAP_THRESHOLD 0.2f
-#define SPATIAL_ASPLIT_SAH_THRESHOLD 0.95f
-#define SPATIAL_ASPLIT_AREA_THRESHOLD 0.0f
-#else
-#define SPATIAL_ASPLIT_OVERLAP_THRESHOLD 0.1f
-#define SPATIAL_ASPLIT_SAH_THRESHOLD 0.99f
-#define SPATIAL_ASPLIT_AREA_THRESHOLD 0.000005f
-#endif
-
- struct PrimInfoExtRange : public CentGeomBBox3fa, public extended_range<size_t>
- {
- __forceinline PrimInfoExtRange() {
- }
-
- __forceinline PrimInfoExtRange(EmptyTy)
- : CentGeomBBox3fa(EmptyTy()), extended_range<size_t>(0,0,0) {}
-
- __forceinline PrimInfoExtRange(size_t begin, size_t end, size_t ext_end, const CentGeomBBox3fa& centGeomBounds)
- : CentGeomBBox3fa(centGeomBounds), extended_range<size_t>(begin,end,ext_end) {}
-
- __forceinline float leafSAH() const {
- return expectedApproxHalfArea(geomBounds)*float(size());
- }
-
- __forceinline float leafSAH(size_t block_shift) const {
- return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
- }
- };
-
- template<typename ObjectSplit, typename SpatialSplit>
- struct Split2
- {
- __forceinline Split2 () {}
-
- __forceinline Split2 (const Split2& other)
- {
- spatial = other.spatial;
- sah = other.sah;
- if (spatial) spatialSplit() = other.spatialSplit();
- else objectSplit() = other.objectSplit();
- }
-
- __forceinline Split2& operator= (const Split2& other)
- {
- spatial = other.spatial;
- sah = other.sah;
- if (spatial) spatialSplit() = other.spatialSplit();
- else objectSplit() = other.objectSplit();
- return *this;
- }
-
- __forceinline ObjectSplit& objectSplit() { return *( ObjectSplit*)data; }
- __forceinline const ObjectSplit& objectSplit() const { return *(const ObjectSplit*)data; }
-
- __forceinline SpatialSplit& spatialSplit() { return *( SpatialSplit*)data; }
- __forceinline const SpatialSplit& spatialSplit() const { return *(const SpatialSplit*)data; }
-
- __forceinline Split2 (const ObjectSplit& objectSplit, float sah)
- : spatial(false), sah(sah)
- {
- new (data) ObjectSplit(objectSplit);
- }
-
- __forceinline Split2 (const SpatialSplit& spatialSplit, float sah)
- : spatial(true), sah(sah)
- {
- new (data) SpatialSplit(spatialSplit);
- }
-
- __forceinline float splitSAH() const {
- return sah;
- }
-
- __forceinline bool valid() const {
- return sah < float(inf);
- }
-
- public:
- __aligned(64) char data[sizeof(ObjectSplit) > sizeof(SpatialSplit) ? sizeof(ObjectSplit) : sizeof(SpatialSplit)];
- bool spatial;
- float sah;
- };
-
- /*! Performs standard object binning */
- template<typename PrimitiveSplitterFactory, typename PrimRef, size_t OBJECT_BINS, size_t SPATIAL_BINS>
- struct HeuristicArraySpatialSAH
- {
- typedef BinSplit<OBJECT_BINS> ObjectSplit;
- typedef BinInfoT<OBJECT_BINS,PrimRef,BBox3fa> ObjectBinner;
-
- typedef SpatialBinSplit<SPATIAL_BINS> SpatialSplit;
- typedef SpatialBinInfo<SPATIAL_BINS,PrimRef> SpatialBinner;
-
- //typedef extended_range<size_t> Set;
- typedef Split2<ObjectSplit,SpatialSplit> Split;
-
-#if defined(__AVX512ER__) // KNL
- static const size_t PARALLEL_THRESHOLD = 3*1024;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 768;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
-#else
- static const size_t PARALLEL_THRESHOLD = 3*1024;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
-#endif
-
- static const size_t MOVE_STEP_SIZE = 64;
- static const size_t CREATE_SPLITS_STEP_SIZE = 64;
-
- __forceinline HeuristicArraySpatialSAH ()
- : prims0(nullptr) {}
-
- /*! remember prim array */
- __forceinline HeuristicArraySpatialSAH (const PrimitiveSplitterFactory& splitterFactory, PrimRef* prims0, const CentGeomBBox3fa& root_info)
- : prims0(prims0), splitterFactory(splitterFactory), root_info(root_info) {}
-
-
- /*! compute extended ranges */
- __noinline void setExtentedRanges(const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset, const size_t lweight, const size_t rweight)
- {
- assert(set.ext_range_size() > 0);
- const float left_factor = (float)lweight / (lweight + rweight);
- const size_t ext_range_size = set.ext_range_size();
- const size_t left_ext_range_size = min((size_t)(floorf(left_factor * ext_range_size)),ext_range_size);
- const size_t right_ext_range_size = ext_range_size - left_ext_range_size;
- lset.set_ext_range(lset.end() + left_ext_range_size);
- rset.set_ext_range(rset.end() + right_ext_range_size);
- }
-
- /*! move ranges */
- __noinline void moveExtentedRange(const PrimInfoExtRange& set, const PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t left_ext_range_size = lset.ext_range_size();
- const size_t right_size = rset.size();
-
- /* has the left child an extended range? */
- if (left_ext_range_size > 0)
- {
- /* left extended range smaller than right range ? */
- if (left_ext_range_size < right_size)
- {
- /* only move a small part of the beginning of the right range to the end */
- parallel_for( rset.begin(), rset.begin()+left_ext_range_size, MOVE_STEP_SIZE, [&](const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++)
- prims0[i+right_size] = prims0[i];
- });
- }
- else
- {
- /* no overlap, move entire right range to new location, can be made fully parallel */
- parallel_for( rset.begin(), rset.end(), MOVE_STEP_SIZE, [&](const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++)
- prims0[i+left_ext_range_size] = prims0[i];
- });
- }
- /* update right range */
- assert(rset.ext_end() + left_ext_range_size == set.ext_end());
- rset.move_right(left_ext_range_size);
- }
- }
-
- /*! finds the best split */
- const Split find(const PrimInfoExtRange& set, const size_t logBlockSize)
- {
- SplitInfo oinfo;
- const ObjectSplit object_split = object_find(set,logBlockSize,oinfo);
- const float object_split_sah = object_split.splitSAH();
-
- if (unlikely(set.has_ext_range()))
- {
- const BBox3fa overlap = intersect(oinfo.leftBounds, oinfo.rightBounds);
-
- /* do only spatial splits if the child bounds overlap */
- if (safeArea(overlap) >= SPATIAL_ASPLIT_AREA_THRESHOLD*safeArea(root_info.geomBounds) &&
- safeArea(overlap) >= SPATIAL_ASPLIT_OVERLAP_THRESHOLD*safeArea(set.geomBounds))
- {
- const SpatialSplit spatial_split = spatial_find(set, logBlockSize);
- const float spatial_split_sah = spatial_split.splitSAH();
-
- /* valid spatial split, better SAH and number of splits do not exceed extended range */
- if (spatial_split_sah < SPATIAL_ASPLIT_SAH_THRESHOLD*object_split_sah &&
- spatial_split.left + spatial_split.right - set.size() <= set.ext_range_size())
- {
- return Split(spatial_split,spatial_split_sah);
- }
- }
- }
-
- return Split(object_split,object_split_sah);
- }
-
- /*! finds the best object split */
- __forceinline const ObjectSplit object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
- {
- if (set.size() < PARALLEL_THRESHOLD) return sequential_object_find(set,logBlockSize,info);
- else return parallel_object_find (set,logBlockSize,info);
- }
-
- /*! finds the best object split */
- __noinline const ObjectSplit sequential_object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
- {
- ObjectBinner binner(empty);
- const BinMapping<OBJECT_BINS> mapping(set);
- binner.bin(prims0,set.begin(),set.end(),mapping);
- ObjectSplit s = binner.best(mapping,logBlockSize);
- binner.getSplitInfo(mapping, s, info);
- return s;
- }
-
- /*! finds the best split */
- __noinline const ObjectSplit parallel_object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
- {
- ObjectBinner binner(empty);
- const BinMapping<OBJECT_BINS> mapping(set);
- const BinMapping<OBJECT_BINS>& _mapping = mapping; // CLANG 3.4 parser bug workaround
- binner = parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,binner,
- [&] (const range<size_t>& r) -> ObjectBinner { ObjectBinner binner(empty); binner.bin(prims0+r.begin(),r.size(),_mapping); return binner; },
- [&] (const ObjectBinner& b0, const ObjectBinner& b1) -> ObjectBinner { ObjectBinner r = b0; r.merge(b1,_mapping.size()); return r; });
- ObjectSplit s = binner.best(mapping,logBlockSize);
- binner.getSplitInfo(mapping, s, info);
- return s;
- }
-
- /*! finds the best spatial split */
- __forceinline const SpatialSplit spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
- {
- if (set.size() < PARALLEL_THRESHOLD) return sequential_spatial_find(set, logBlockSize);
- else return parallel_spatial_find (set, logBlockSize);
- }
-
- /*! finds the best spatial split */
- __noinline const SpatialSplit sequential_spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
- {
- SpatialBinner binner(empty);
- const SpatialBinMapping<SPATIAL_BINS> mapping(set);
- binner.bin2(splitterFactory,prims0,set.begin(),set.end(),mapping);
- /* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/
- return binner.best(mapping,logBlockSize); //,set.ext_size());
- }
-
- __noinline const SpatialSplit parallel_spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
- {
- SpatialBinner binner(empty);
- const SpatialBinMapping<SPATIAL_BINS> mapping(set);
- const SpatialBinMapping<SPATIAL_BINS>& _mapping = mapping; // CLANG 3.4 parser bug workaround
- binner = parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,binner,
- [&] (const range<size_t>& r) -> SpatialBinner {
- SpatialBinner binner(empty);
- binner.bin2(splitterFactory,prims0,r.begin(),r.end(),_mapping);
- return binner; },
- [&] (const SpatialBinner& b0, const SpatialBinner& b1) -> SpatialBinner { return SpatialBinner::reduce(b0,b1); });
- /* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/
- return binner.best(mapping,logBlockSize); //,set.ext_size());
- }
-
-
- /*! subdivides primitives based on a spatial split */
- __noinline void create_spatial_splits(PrimInfoExtRange& set, const SpatialSplit& split, const SpatialBinMapping<SPATIAL_BINS> &mapping)
- {
- assert(set.has_ext_range());
- const size_t max_ext_range_size = set.ext_range_size();
- const size_t ext_range_start = set.end();
-
- /* atomic counter for number of primref splits */
- std::atomic<size_t> ext_elements;
- ext_elements.store(0);
-
- const float fpos = split.mapping.pos(split.pos,split.dim);
-
- const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
-
- parallel_for( set.begin(), set.end(), CREATE_SPLITS_STEP_SIZE, [&](const range<size_t>& r) {
- for (size_t i=r.begin();i<r.end();i++)
- {
- const unsigned int splits = prims0[i].geomID() >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
-
- if (likely(splits <= 1)) continue; /* todo: does this ever happen ? */
-
- //int bin0 = split.mapping.bin(prims0[i].lower)[split.dim];
- //int bin1 = split.mapping.bin(prims0[i].upper)[split.dim];
- //if (unlikely(bin0 < split.pos && bin1 >= split.pos))
- if (unlikely(prims0[i].lower[split.dim] < fpos && prims0[i].upper[split.dim] > fpos))
- {
- assert(splits > 1);
-
- PrimRef left,right;
- const auto splitter = splitterFactory(prims0[i]);
- splitter(prims0[i],split.dim,fpos,left,right);
-
- // no empty splits
- if (unlikely(left.bounds().empty() || right.bounds().empty())) continue;
-
- left.lower.u = (left.lower.u & mask) | ((splits-1) << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS));
- right.lower.u = (right.lower.u & mask) | ((splits-1) << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS));
-
- const size_t ID = ext_elements.fetch_add(1);
-
- /* break if the number of subdivided elements are greater than the maximum allowed size */
- if (unlikely(ID >= max_ext_range_size))
- break;
-
- /* only write within the correct bounds */
- assert(ID < max_ext_range_size);
- prims0[i] = left;
- prims0[ext_range_start+ID] = right;
- }
- }
- });
-
- const size_t numExtElements = min(max_ext_range_size,ext_elements.load());
- assert(set.end()+numExtElements<=set.ext_end());
- set._end += numExtElements;
- }
-
- /*! array partitioning */
- void split(const Split& split, const PrimInfoExtRange& set_i, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- PrimInfoExtRange set = set_i;
-
- /* valid split */
- if (unlikely(!split.valid())) {
- deterministic_order(set);
- return splitFallback(set,lset,rset);
- }
-
- std::pair<size_t,size_t> ext_weights(0,0);
-
- if (unlikely(split.spatial))
- {
- create_spatial_splits(set,split.spatialSplit(), split.spatialSplit().mapping);
-
- /* spatial split */
- if (likely(set.size() < PARALLEL_THRESHOLD))
- ext_weights = sequential_spatial_split(split.spatialSplit(),set,lset,rset);
- else
- ext_weights = parallel_spatial_split(split.spatialSplit(),set,lset,rset);
- }
- else
- {
- /* object split */
- if (likely(set.size() < PARALLEL_THRESHOLD))
- ext_weights = sequential_object_split(split.objectSplit(),set,lset,rset);
- else
- ext_weights = parallel_object_split(split.objectSplit(),set,lset,rset);
- }
-
- /* if we have an extended range, set extended child ranges and move right split range */
- if (unlikely(set.has_ext_range()))
- {
- setExtentedRanges(set,lset,rset,ext_weights.first,ext_weights.second);
- moveExtentedRange(set,lset,rset);
- }
- }
-
- /*! array partitioning */
- std::pair<size_t,size_t> sequential_object_split(const ObjectSplit& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfo local_left(empty);
- PrimInfo local_right(empty);
- const unsigned int splitPos = split.pos;
- const unsigned int splitDim = split.dim;
- const unsigned int splitDimMask = (unsigned int)1 << splitDim;
-
- const typename ObjectBinner::vint vSplitPos(splitPos);
- const typename ObjectBinner::vbool vSplitMask(splitDimMask);
- size_t center = serial_partitioning(prims0,
- begin,end,local_left,local_right,
- [&] (const PrimRef& ref) {
- return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask);
- },
- [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); });
- const size_t left_weight = local_left.end;
- const size_t right_weight = local_right.end;
-
- new (&lset) PrimInfoExtRange(begin,center,center,local_left);
- new (&rset) PrimInfoExtRange(center,end,end,local_right);
-
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
- return std::pair<size_t,size_t>(left_weight,right_weight);
- }
-
-
- /*! array partitioning */
- __noinline std::pair<size_t,size_t> sequential_spatial_split(const SpatialSplit& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfo local_left(empty);
- PrimInfo local_right(empty);
- const unsigned int splitPos = split.pos;
- const unsigned int splitDim = split.dim;
- const unsigned int splitDimMask = (unsigned int)1 << splitDim;
-
- /* init spatial mapping */
- const SpatialBinMapping<SPATIAL_BINS> &mapping = split.mapping;
- const vint4 vSplitPos(splitPos);
- const vbool4 vSplitMask( (int)splitDimMask );
-
- size_t center = serial_partitioning(prims0,
- begin,end,local_left,local_right,
- [&] (const PrimRef& ref) {
- const Vec3fa c = ref.bounds().center();
- return any(((vint4)mapping.bin(c) < vSplitPos) & vSplitMask);
- },
- [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); });
-
- const size_t left_weight = local_left.end;
- const size_t right_weight = local_right.end;
-
- new (&lset) PrimInfoExtRange(begin,center,center,local_left);
- new (&rset) PrimInfoExtRange(center,end,end,local_right);
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
- return std::pair<size_t,size_t>(left_weight,right_weight);
- }
-
-
-
- /*! array partitioning */
- __noinline std::pair<size_t,size_t> parallel_object_split(const ObjectSplit& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfo left(empty);
- PrimInfo right(empty);
- const unsigned int splitPos = split.pos;
- const unsigned int splitDim = split.dim;
- const unsigned int splitDimMask = (unsigned int)1 << splitDim;
-
- const typename ObjectBinner::vint vSplitPos(splitPos);
- const typename ObjectBinner::vbool vSplitMask(splitDimMask);
- auto isLeft = [&] (const PrimRef &ref) { return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask); };
-
- const size_t center = parallel_partitioning(
- prims0,begin,end,EmptyTy(),left,right,isLeft,
- [] (PrimInfo &pinfo,const PrimRef &ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); },
- [] (PrimInfo &pinfo0,const PrimInfo &pinfo1) { pinfo0.merge(pinfo1); },
- PARALLEL_PARTITION_BLOCK_SIZE);
-
- const size_t left_weight = left.end;
- const size_t right_weight = right.end;
-
- left.begin = begin; left.end = center;
- right.begin = center; right.end = end;
-
- new (&lset) PrimInfoExtRange(begin,center,center,left);
- new (&rset) PrimInfoExtRange(center,end,end,right);
-
- assert(area(left.geomBounds) >= 0.0f);
- assert(area(right.geomBounds) >= 0.0f);
- return std::pair<size_t,size_t>(left_weight,right_weight);
- }
-
- /*! array partitioning */
- __noinline std::pair<size_t,size_t> parallel_spatial_split(const SpatialSplit& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- PrimInfo left(empty);
- PrimInfo right(empty);
- const unsigned int splitPos = split.pos;
- const unsigned int splitDim = split.dim;
- const unsigned int splitDimMask = (unsigned int)1 << splitDim;
-
- /* init spatial mapping */
- const SpatialBinMapping<SPATIAL_BINS>& mapping = split.mapping;
- const vint4 vSplitPos(splitPos);
- const vbool4 vSplitMask( (int)splitDimMask );
-
- auto isLeft = [&] (const PrimRef &ref) {
- const Vec3fa c = ref.bounds().center();
- return any(((vint4)mapping.bin(c) < vSplitPos) & vSplitMask); };
-
- const size_t center = parallel_partitioning(
- prims0,begin,end,EmptyTy(),left,right,isLeft,
- [] (PrimInfo &pinfo,const PrimRef &ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); },
- [] (PrimInfo &pinfo0,const PrimInfo &pinfo1) { pinfo0.merge(pinfo1); },
- PARALLEL_PARTITION_BLOCK_SIZE);
-
- const size_t left_weight = left.end;
- const size_t right_weight = right.end;
-
- left.begin = begin; left.end = center;
- right.begin = center; right.end = end;
-
- new (&lset) PrimInfoExtRange(begin,center,center,left);
- new (&rset) PrimInfoExtRange(center,end,end,right);
-
- assert(area(left.geomBounds) >= 0.0f);
- assert(area(right.geomBounds) >= 0.0f);
- return std::pair<size_t,size_t>(left_weight,right_weight);
- }
-
- void deterministic_order(const PrimInfoExtRange& set)
- {
- /* required as parallel partition destroys original primitive order */
- std::sort(&prims0[set.begin()],&prims0[set.end()]);
- }
-
- void splitFallback(const PrimInfoExtRange& set,
- PrimInfoExtRange& lset,
- PrimInfoExtRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- const size_t center = (begin + end)/2;
-
- PrimInfo left(empty);
- for (size_t i=begin; i<center; i++) {
- left.add_center2(prims0[i],prims0[i].lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS));
- }
- const size_t lweight = left.end;
-
- PrimInfo right(empty);
- for (size_t i=center; i<end; i++) {
- right.add_center2(prims0[i],prims0[i].lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS));
- }
- const size_t rweight = right.end;
-
- new (&lset) PrimInfoExtRange(begin,center,center,left);
- new (&rset) PrimInfoExtRange(center,end,end,right);
-
- /* if we have an extended range */
- if (set.has_ext_range()) {
- setExtentedRanges(set,lset,rset,lweight,rweight);
- moveExtentedRange(set,lset,rset);
- }
- }
-
- private:
- PrimRef* const prims0;
- const PrimitiveSplitterFactory& splitterFactory;
- const CentGeomBBox3fa& root_info;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/heuristic_strand_array.h b/thirdparty/embree-aarch64/kernels/builders/heuristic_strand_array.h
deleted file mode 100644
index ede0d04c78..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/heuristic_strand_array.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "priminfo.h"
-#include "../../common/algorithms/parallel_reduce.h"
-#include "../../common/algorithms/parallel_partition.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Performs standard object binning */
- struct HeuristicStrandSplit
- {
- typedef range<size_t> Set;
-
- static const size_t PARALLEL_THRESHOLD = 10000;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 4096;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 64;
-
- /*! stores all information to perform some split */
- struct Split
- {
- /*! construct an invalid split by default */
- __forceinline Split()
- : sah(inf), axis0(zero), axis1(zero) {}
-
- /*! constructs specified split */
- __forceinline Split(const float sah, const Vec3fa& axis0, const Vec3fa& axis1)
- : sah(sah), axis0(axis0), axis1(axis1) {}
-
- /*! calculates standard surface area heuristic for the split */
- __forceinline float splitSAH() const { return sah; }
-
- /*! test if this split is valid */
- __forceinline bool valid() const { return sah != float(inf); }
-
- public:
- float sah; //!< SAH cost of the split
- Vec3fa axis0, axis1; //!< axis the two strands are aligned into
- };
-
- __forceinline HeuristicStrandSplit () // FIXME: required?
- : scene(nullptr), prims(nullptr) {}
-
- /*! remember prim array */
- __forceinline HeuristicStrandSplit (Scene* scene, PrimRef* prims)
- : scene(scene), prims(prims) {}
-
- __forceinline const Vec3fa direction(const PrimRef& prim) {
- return scene->get(prim.geomID())->computeDirection(prim.primID());
- }
-
- __forceinline const BBox3fa bounds(const PrimRef& prim) {
- return scene->get(prim.geomID())->vbounds(prim.primID());
- }
-
- __forceinline const BBox3fa bounds(const LinearSpace3fa& space, const PrimRef& prim) {
- return scene->get(prim.geomID())->vbounds(space,prim.primID());
- }
-
- /*! finds the best split */
- const Split find(const range<size_t>& set, size_t logBlockSize)
- {
- Vec3fa axis0(0,0,1);
- uint64_t bestGeomPrimID = -1;
-
- /* curve with minimum ID determines first axis */
- for (size_t i=set.begin(); i<set.end(); i++)
- {
- const uint64_t geomprimID = prims[i].ID64();
- if (geomprimID >= bestGeomPrimID) continue;
- const Vec3fa axis = direction(prims[i]);
- if (sqr_length(axis) > 1E-18f) {
- axis0 = normalize(axis);
- bestGeomPrimID = geomprimID;
- }
- }
-
- /* find 2nd axis that is most misaligned with first axis and has minimum ID */
- float bestCos = 1.0f;
- Vec3fa axis1 = axis0;
- bestGeomPrimID = -1;
- for (size_t i=set.begin(); i<set.end(); i++)
- {
- const uint64_t geomprimID = prims[i].ID64();
- Vec3fa axisi = direction(prims[i]);
- float leni = length(axisi);
- if (leni == 0.0f) continue;
- axisi /= leni;
- float cos = abs(dot(axisi,axis0));
- if ((cos == bestCos && (geomprimID < bestGeomPrimID)) || cos < bestCos) {
- bestCos = cos; axis1 = axisi;
- bestGeomPrimID = geomprimID;
- }
- }
-
- /* partition the two strands */
- size_t lnum = 0, rnum = 0;
- BBox3fa lbounds = empty, rbounds = empty;
- const LinearSpace3fa space0 = frame(axis0).transposed();
- const LinearSpace3fa space1 = frame(axis1).transposed();
-
- for (size_t i=set.begin(); i<set.end(); i++)
- {
- PrimRef& prim = prims[i];
- const Vec3fa axisi = normalize(direction(prim));
- const float cos0 = abs(dot(axisi,axis0));
- const float cos1 = abs(dot(axisi,axis1));
-
- if (cos0 > cos1) { lnum++; lbounds.extend(bounds(space0,prim)); }
- else { rnum++; rbounds.extend(bounds(space1,prim)); }
- }
-
- /*! return an invalid split if we do not partition */
- if (lnum == 0 || rnum == 0)
- return Split(inf,axis0,axis1);
-
- /*! calculate sah for the split */
- const size_t lblocks = (lnum+(1ull<<logBlockSize)-1ull) >> logBlockSize;
- const size_t rblocks = (rnum+(1ull<<logBlockSize)-1ull) >> logBlockSize;
- const float sah = madd(float(lblocks),halfArea(lbounds),float(rblocks)*halfArea(rbounds));
- return Split(sah,axis0,axis1);
- }
-
- /*! array partitioning */
- void split(const Split& split, const PrimInfoRange& set, PrimInfoRange& lset, PrimInfoRange& rset)
- {
- if (!split.valid()) {
- deterministic_order(set);
- return splitFallback(set,lset,rset);
- }
-
- const size_t begin = set.begin();
- const size_t end = set.end();
- CentGeomBBox3fa local_left(empty);
- CentGeomBBox3fa local_right(empty);
-
- auto primOnLeftSide = [&] (const PrimRef& prim) -> bool {
- const Vec3fa axisi = normalize(direction(prim));
- const float cos0 = abs(dot(axisi,split.axis0));
- const float cos1 = abs(dot(axisi,split.axis1));
- return cos0 > cos1;
- };
-
- auto mergePrimBounds = [this] (CentGeomBBox3fa& pinfo,const PrimRef& ref) {
- pinfo.extend(bounds(ref));
- };
-
- size_t center = serial_partitioning(prims,begin,end,local_left,local_right,primOnLeftSide,mergePrimBounds);
-
- new (&lset) PrimInfoRange(begin,center,local_left);
- new (&rset) PrimInfoRange(center,end,local_right);
- assert(area(lset.geomBounds) >= 0.0f);
- assert(area(rset.geomBounds) >= 0.0f);
- }
-
- void deterministic_order(const Set& set)
- {
- /* required as parallel partition destroys original primitive order */
- std::sort(&prims[set.begin()],&prims[set.end()]);
- }
-
- void splitFallback(const Set& set, PrimInfoRange& lset, PrimInfoRange& rset)
- {
- const size_t begin = set.begin();
- const size_t end = set.end();
- const size_t center = (begin + end)/2;
-
- CentGeomBBox3fa left(empty);
- for (size_t i=begin; i<center; i++)
- left.extend(bounds(prims[i]));
- new (&lset) PrimInfoRange(begin,center,left);
-
- CentGeomBBox3fa right(empty);
- for (size_t i=center; i<end; i++)
- right.extend(bounds(prims[i]));
- new (&rset) PrimInfoRange(center,end,right);
- }
-
- private:
- Scene* const scene;
- PrimRef* const prims;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/heuristic_timesplit_array.h b/thirdparty/embree-aarch64/kernels/builders/heuristic_timesplit_array.h
deleted file mode 100644
index c999941a11..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/heuristic_timesplit_array.h
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/primref_mb.h"
-#include "../../common/algorithms/parallel_filter.h"
-
-#define MBLUR_TIME_SPLIT_THRESHOLD 1.25f
-
-namespace embree
-{
- namespace isa
- {
- /*! Performs standard object binning */
- template<typename PrimRefMB, typename RecalculatePrimRef, size_t BINS>
- struct HeuristicMBlurTemporalSplit
- {
- typedef BinSplit<MBLUR_NUM_OBJECT_BINS> Split;
- typedef mvector<PrimRefMB>* PrimRefVector;
- typedef typename PrimRefMB::BBox BBox;
-
- static const size_t PARALLEL_THRESHOLD = 3 * 1024;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
-
- HeuristicMBlurTemporalSplit (MemoryMonitorInterface* device, const RecalculatePrimRef& recalculatePrimRef)
- : device(device), recalculatePrimRef(recalculatePrimRef) {}
-
- struct TemporalBinInfo
- {
- __forceinline TemporalBinInfo () {
- }
-
- __forceinline TemporalBinInfo (EmptyTy)
- {
- for (size_t i=0; i<BINS-1; i++)
- {
- count0[i] = count1[i] = 0;
- bounds0[i] = bounds1[i] = empty;
- }
- }
-
- void bin(const PrimRefMB* prims, size_t begin, size_t end, BBox1f time_range, const SetMB& set, const RecalculatePrimRef& recalculatePrimRef)
- {
- for (int b=0; b<BINS-1; b++)
- {
- const float t = float(b+1)/float(BINS);
- const float ct = lerp(time_range.lower,time_range.upper,t);
- const float center_time = set.align_time(ct);
- if (center_time <= time_range.lower) continue;
- if (center_time >= time_range.upper) continue;
- const BBox1f dt0(time_range.lower,center_time);
- const BBox1f dt1(center_time,time_range.upper);
-
- /* find linear bounds for both time segments */
- for (size_t i=begin; i<end; i++)
- {
- if (prims[i].time_range_overlap(dt0))
- {
- const LBBox3fa bn0 = recalculatePrimRef.linearBounds(prims[i],dt0);
-#if MBLUR_BIN_LBBOX
- bounds0[b].extend(bn0);
-#else
- bounds0[b].extend(bn0.interpolate(0.5f));
-#endif
- count0[b] += prims[i].timeSegmentRange(dt0).size();
- }
-
- if (prims[i].time_range_overlap(dt1))
- {
- const LBBox3fa bn1 = recalculatePrimRef.linearBounds(prims[i],dt1);
-#if MBLUR_BIN_LBBOX
- bounds1[b].extend(bn1);
-#else
- bounds1[b].extend(bn1.interpolate(0.5f));
-#endif
- count1[b] += prims[i].timeSegmentRange(dt1).size();
- }
- }
- }
- }
-
- __forceinline void bin_parallel(const PrimRefMB* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, BBox1f time_range, const SetMB& set, const RecalculatePrimRef& recalculatePrimRef)
- {
- if (likely(end-begin < parallelThreshold)) {
- bin(prims,begin,end,time_range,set,recalculatePrimRef);
- }
- else
- {
- auto bin = [&](const range<size_t>& r) -> TemporalBinInfo {
- TemporalBinInfo binner(empty); binner.bin(prims, r.begin(), r.end(), time_range, set, recalculatePrimRef); return binner;
- };
- *this = parallel_reduce(begin,end,blockSize,TemporalBinInfo(empty),bin,merge2);
- }
- }
-
- /*! merges in other binning information */
- __forceinline void merge (const TemporalBinInfo& other)
- {
- for (size_t i=0; i<BINS-1; i++)
- {
- count0[i] += other.count0[i];
- count1[i] += other.count1[i];
- bounds0[i].extend(other.bounds0[i]);
- bounds1[i].extend(other.bounds1[i]);
- }
- }
-
- static __forceinline const TemporalBinInfo merge2(const TemporalBinInfo& a, const TemporalBinInfo& b) {
- TemporalBinInfo r = a; r.merge(b); return r;
- }
-
- Split best(int logBlockSize, BBox1f time_range, const SetMB& set)
- {
- float bestSAH = inf;
- float bestPos = 0.0f;
- for (int b=0; b<BINS-1; b++)
- {
- float t = float(b+1)/float(BINS);
- float ct = lerp(time_range.lower,time_range.upper,t);
- const float center_time = set.align_time(ct);
- if (center_time <= time_range.lower) continue;
- if (center_time >= time_range.upper) continue;
- const BBox1f dt0(time_range.lower,center_time);
- const BBox1f dt1(center_time,time_range.upper);
-
- /* calculate sah */
- const size_t lCount = (count0[b]+(size_t(1) << logBlockSize)-1) >> int(logBlockSize);
- const size_t rCount = (count1[b]+(size_t(1) << logBlockSize)-1) >> int(logBlockSize);
- float sah0 = expectedApproxHalfArea(bounds0[b])*float(lCount)*dt0.size();
- float sah1 = expectedApproxHalfArea(bounds1[b])*float(rCount)*dt1.size();
- if (unlikely(lCount == 0)) sah0 = 0.0f; // happens for initial splits when objects not alive over entire shutter time
- if (unlikely(rCount == 0)) sah1 = 0.0f;
- const float sah = sah0+sah1;
- if (sah < bestSAH) {
- bestSAH = sah;
- bestPos = center_time;
- }
- }
- return Split(bestSAH*MBLUR_TIME_SPLIT_THRESHOLD,(unsigned)Split::SPLIT_TEMPORAL,0,bestPos);
- }
-
- public:
- size_t count0[BINS-1];
- size_t count1[BINS-1];
- BBox bounds0[BINS-1];
- BBox bounds1[BINS-1];
- };
-
- /*! finds the best split */
- const Split find(const SetMB& set, const size_t logBlockSize)
- {
- assert(set.size() > 0);
- TemporalBinInfo binner(empty);
- binner.bin_parallel(set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,set.time_range,set,recalculatePrimRef);
- Split tsplit = binner.best((int)logBlockSize,set.time_range,set);
- if (!tsplit.valid()) tsplit.data = Split::SPLIT_FALLBACK; // use fallback split
- return tsplit;
- }
-
- __forceinline std::unique_ptr<mvector<PrimRefMB>> split(const Split& tsplit, const SetMB& set, SetMB& lset, SetMB& rset)
- {
- assert(tsplit.sah != float(inf));
- assert(tsplit.fpos > set.time_range.lower);
- assert(tsplit.fpos < set.time_range.upper);
-
- float center_time = tsplit.fpos;
- const BBox1f time_range0(set.time_range.lower,center_time);
- const BBox1f time_range1(center_time,set.time_range.upper);
- mvector<PrimRefMB>& prims = *set.prims;
-
- /* calculate primrefs for first time range */
- std::unique_ptr<mvector<PrimRefMB>> new_vector(new mvector<PrimRefMB>(device, set.size()));
- PrimRefVector lprims = new_vector.get();
-
- auto reduction_func0 = [&] (const range<size_t>& r) {
- PrimInfoMB pinfo = empty;
- for (size_t i=r.begin(); i<r.end(); i++)
- {
- if (likely(prims[i].time_range_overlap(time_range0)))
- {
- const PrimRefMB& prim = recalculatePrimRef(prims[i],time_range0);
- (*lprims)[i-set.begin()] = prim;
- pinfo.add_primref(prim);
- }
- else
- {
- (*lprims)[i-set.begin()] = prims[i];
- }
- }
- return pinfo;
- };
- PrimInfoMB linfo = parallel_reduce(set.object_range,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD,PrimInfoMB(empty),reduction_func0,PrimInfoMB::merge2);
-
- /* primrefs for first time range are in lprims[0 .. set.size()) */
- /* some primitives may need to be filtered out */
- if (linfo.size() != set.size())
- linfo.object_range._end = parallel_filter(lprims->data(), size_t(0), set.size(), size_t(1024),
- [&](const PrimRefMB& prim) { return prim.time_range_overlap(time_range0); });
-
- lset = SetMB(linfo,lprims,time_range0);
-
- /* calculate primrefs for second time range */
- auto reduction_func1 = [&] (const range<size_t>& r) {
- PrimInfoMB pinfo = empty;
- for (size_t i=r.begin(); i<r.end(); i++)
- {
- if (likely(prims[i].time_range_overlap(time_range1)))
- {
- const PrimRefMB& prim = recalculatePrimRef(prims[i],time_range1);
- prims[i] = prim;
- pinfo.add_primref(prim);
- }
- }
- return pinfo;
- };
- PrimInfoMB rinfo = parallel_reduce(set.object_range,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD,PrimInfoMB(empty),reduction_func1,PrimInfoMB::merge2);
- rinfo.object_range = range<size_t>(set.begin(), set.begin() + rinfo.size());
-
- /* primrefs for second time range are in prims[set.begin() .. set.end()) */
- /* some primitives may need to be filtered out */
- if (rinfo.size() != set.size())
- rinfo.object_range._end = parallel_filter(prims.data(), set.begin(), set.end(), size_t(1024),
- [&](const PrimRefMB& prim) { return prim.time_range_overlap(time_range1); });
-
- rset = SetMB(rinfo,&prims,time_range1);
-
- return new_vector;
- }
-
- private:
- MemoryMonitorInterface* device; // device to report memory usage to
- const RecalculatePrimRef recalculatePrimRef;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/priminfo.h b/thirdparty/embree-aarch64/kernels/builders/priminfo.h
deleted file mode 100644
index 06c1388742..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/priminfo.h
+++ /dev/null
@@ -1,362 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-#include "../common/primref.h"
-#include "../common/primref_mb.h"
-
-namespace embree
-{
- // FIXME: maybe there's a better place for this util fct
- __forceinline float areaProjectedTriangle(const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2)
- {
- const Vec3fa e0 = v1-v0;
- const Vec3fa e1 = v2-v0;
- const Vec3fa d = cross(e0,e1);
- return fabs(d.x) + fabs(d.y) + fabs(d.z);
- }
-
- //namespace isa
- //{
- template<typename BBox>
- class CentGeom
- {
- public:
- __forceinline CentGeom () {}
-
- __forceinline CentGeom (EmptyTy)
- : geomBounds(empty), centBounds(empty) {}
-
- __forceinline CentGeom (const BBox& geomBounds, const BBox3fa& centBounds)
- : geomBounds(geomBounds), centBounds(centBounds) {}
-
- template<typename PrimRef>
- __forceinline void extend_primref(const PrimRef& prim)
- {
- BBox bounds; Vec3fa center;
- prim.binBoundsAndCenter(bounds,center);
- geomBounds.extend(bounds);
- centBounds.extend(center);
- }
-
- template<typename PrimRef>
- __forceinline void extend_center2(const PrimRef& prim)
- {
- BBox3fa bounds = prim.bounds();
- geomBounds.extend(bounds);
- centBounds.extend(bounds.center2());
- }
-
- __forceinline void extend(const BBox& geomBounds_) {
- geomBounds.extend(geomBounds_);
- centBounds.extend(center2(geomBounds_));
- }
-
- __forceinline void merge(const CentGeom& other)
- {
- geomBounds.extend(other.geomBounds);
- centBounds.extend(other.centBounds);
- }
-
- static __forceinline const CentGeom merge2(const CentGeom& a, const CentGeom& b) {
- CentGeom r = a; r.merge(b); return r;
- }
-
- public:
- BBox geomBounds; //!< geometry bounds of primitives
- BBox3fa centBounds; //!< centroid bounds of primitives
- };
-
- typedef CentGeom<BBox3fa> CentGeomBBox3fa;
-
- /*! stores bounding information for a set of primitives */
- template<typename BBox>
- class PrimInfoT : public CentGeom<BBox>
- {
- public:
- using CentGeom<BBox>::geomBounds;
- using CentGeom<BBox>::centBounds;
-
- __forceinline PrimInfoT () {}
-
- __forceinline PrimInfoT (EmptyTy)
- : CentGeom<BBox>(empty), begin(0), end(0) {}
-
- __forceinline PrimInfoT (size_t begin, size_t end, const CentGeomBBox3fa& centGeomBounds)
- : CentGeom<BBox>(centGeomBounds), begin(begin), end(end) {}
-
- template<typename PrimRef>
- __forceinline void add_primref(const PrimRef& prim)
- {
- CentGeom<BBox>::extend_primref(prim);
- end++;
- }
-
- template<typename PrimRef>
- __forceinline void add_center2(const PrimRef& prim) {
- CentGeom<BBox>::extend_center2(prim);
- end++;
- }
-
- template<typename PrimRef>
- __forceinline void add_center2(const PrimRef& prim, const size_t i) {
- CentGeom<BBox>::extend_center2(prim);
- end+=i;
- }
-
- /*__forceinline void add(const BBox& geomBounds_) {
- CentGeom<BBox>::extend(geomBounds_);
- end++;
- }
-
- __forceinline void add(const BBox& geomBounds_, const size_t i) {
- CentGeom<BBox>::extend(geomBounds_);
- end+=i;
- }*/
-
- __forceinline void merge(const PrimInfoT& other)
- {
- CentGeom<BBox>::merge(other);
- begin += other.begin;
- end += other.end;
- }
-
- static __forceinline const PrimInfoT merge(const PrimInfoT& a, const PrimInfoT& b) {
- PrimInfoT r = a; r.merge(b); return r;
- }
-
- /*! returns the number of primitives */
- __forceinline size_t size() const {
- return end-begin;
- }
-
- __forceinline float halfArea() {
- return expectedApproxHalfArea(geomBounds);
- }
-
- __forceinline float leafSAH() const {
- return expectedApproxHalfArea(geomBounds)*float(size());
- //return halfArea(geomBounds)*blocks(num);
- }
-
- __forceinline float leafSAH(size_t block_shift) const {
- return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
- //return halfArea(geomBounds)*float((num+3) >> 2);
- //return halfArea(geomBounds)*blocks(num);
- }
-
- /*! stream output */
- friend embree_ostream operator<<(embree_ostream cout, const PrimInfoT& pinfo) {
- return cout << "PrimInfo { begin = " << pinfo.begin << ", end = " << pinfo.end << ", geomBounds = " << pinfo.geomBounds << ", centBounds = " << pinfo.centBounds << "}";
- }
-
- public:
- size_t begin,end; //!< number of primitives
- };
-
- typedef PrimInfoT<BBox3fa> PrimInfo;
- //typedef PrimInfoT<LBBox3fa> PrimInfoMB;
-
- /*! stores bounding information for a set of primitives */
- template<typename BBox>
- class PrimInfoMBT : public CentGeom<BBox>
- {
- public:
- using CentGeom<BBox>::geomBounds;
- using CentGeom<BBox>::centBounds;
-
- __forceinline PrimInfoMBT () {
- }
-
- __forceinline PrimInfoMBT (EmptyTy)
- : CentGeom<BBox>(empty), object_range(0,0), num_time_segments(0), max_num_time_segments(0), max_time_range(0.0f,1.0f), time_range(1.0f,0.0f) {}
-
- __forceinline PrimInfoMBT (size_t begin, size_t end)
- : CentGeom<BBox>(empty), object_range(begin,end), num_time_segments(0), max_num_time_segments(0), max_time_range(0.0f,1.0f), time_range(1.0f,0.0f) {}
-
- template<typename PrimRef>
- __forceinline void add_primref(const PrimRef& prim)
- {
- CentGeom<BBox>::extend_primref(prim);
- time_range.extend(prim.time_range);
- object_range._end++;
- num_time_segments += prim.size();
- if (max_num_time_segments < prim.totalTimeSegments()) {
- max_num_time_segments = prim.totalTimeSegments();
- max_time_range = prim.time_range;
- }
- }
-
- __forceinline void merge(const PrimInfoMBT& other)
- {
- CentGeom<BBox>::merge(other);
- time_range.extend(other.time_range);
- object_range._begin += other.object_range.begin();
- object_range._end += other.object_range.end();
- num_time_segments += other.num_time_segments;
- if (max_num_time_segments < other.max_num_time_segments) {
- max_num_time_segments = other.max_num_time_segments;
- max_time_range = other.max_time_range;
- }
- }
-
- static __forceinline const PrimInfoMBT merge2(const PrimInfoMBT& a, const PrimInfoMBT& b) {
- PrimInfoMBT r = a; r.merge(b); return r;
- }
-
- __forceinline size_t begin() const {
- return object_range.begin();
- }
-
- __forceinline size_t end() const {
- return object_range.end();
- }
-
- /*! returns the number of primitives */
- __forceinline size_t size() const {
- return object_range.size();
- }
-
- __forceinline float halfArea() const {
- return time_range.size()*expectedApproxHalfArea(geomBounds);
- }
-
- __forceinline float leafSAH() const {
- return time_range.size()*expectedApproxHalfArea(geomBounds)*float(num_time_segments);
- }
-
- __forceinline float leafSAH(size_t block_shift) const {
- return time_range.size()*expectedApproxHalfArea(geomBounds)*float((num_time_segments+(size_t(1)<<block_shift)-1) >> block_shift);
- }
-
- __forceinline float align_time(float ct) const
- {
- //return roundf(ct * float(numTimeSegments)) / float(numTimeSegments);
- float t0 = (ct-max_time_range.lower)/max_time_range.size();
- float t1 = roundf(t0 * float(max_num_time_segments)) / float(max_num_time_segments);
- return t1*max_time_range.size()+max_time_range.lower;
- }
-
- /*! stream output */
- friend embree_ostream operator<<(embree_ostream cout, const PrimInfoMBT& pinfo)
- {
- return cout << "PrimInfo { " <<
- "object_range = " << pinfo.object_range <<
- ", time_range = " << pinfo.time_range <<
- ", time_segments = " << pinfo.num_time_segments <<
- ", geomBounds = " << pinfo.geomBounds <<
- ", centBounds = " << pinfo.centBounds <<
- "}";
- }
-
- public:
- range<size_t> object_range; //!< primitive range
- size_t num_time_segments; //!< total number of time segments of all added primrefs
- size_t max_num_time_segments; //!< maximum number of time segments of a primitive
- BBox1f max_time_range; //!< time range of primitive with max_num_time_segments
- BBox1f time_range; //!< merged time range of primitives when merging prims, or additionally clipped with build time range when used in SetMB
- };
-
- typedef PrimInfoMBT<typename PrimRefMB::BBox> PrimInfoMB;
-
- struct SetMB : public PrimInfoMB
- {
- static const size_t PARALLEL_THRESHOLD = 3 * 1024;
- static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
- static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
-
- typedef mvector<PrimRefMB>* PrimRefVector;
-
- __forceinline SetMB() {}
-
- __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims)
- : PrimInfoMB(pinfo_i), prims(prims) {}
-
- __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, range<size_t> object_range_in, BBox1f time_range_in)
- : PrimInfoMB(pinfo_i), prims(prims)
- {
- object_range = object_range_in;
- time_range = intersect(time_range,time_range_in);
- }
-
- __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, BBox1f time_range_in)
- : PrimInfoMB(pinfo_i), prims(prims)
- {
- time_range = intersect(time_range,time_range_in);
- }
-
- void deterministic_order() const
- {
- /* required as parallel partition destroys original primitive order */
- PrimRefMB* prim = prims->data();
- std::sort(&prim[object_range.begin()],&prim[object_range.end()]);
- }
-
- template<typename RecalculatePrimRef>
- __forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef) const
- {
- auto reduce = [&](const range<size_t>& r) -> LBBox3fa
- {
- LBBox3fa cbounds(empty);
- for (size_t j = r.begin(); j < r.end(); j++)
- {
- PrimRefMB& ref = (*prims)[j];
- const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range);
- cbounds.extend(bn);
- };
- return cbounds;
- };
-
- return parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD, LBBox3fa(empty),
- reduce,
- [&](const LBBox3fa& b0, const LBBox3fa& b1) -> LBBox3fa { return embree::merge(b0, b1); });
- }
-
- template<typename RecalculatePrimRef>
- __forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
- {
- auto reduce = [&](const range<size_t>& r) -> LBBox3fa
- {
- LBBox3fa cbounds(empty);
- for (size_t j = r.begin(); j < r.end(); j++)
- {
- PrimRefMB& ref = (*prims)[j];
- const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range, space);
- cbounds.extend(bn);
- };
- return cbounds;
- };
-
- return parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD, LBBox3fa(empty),
- reduce,
- [&](const LBBox3fa& b0, const LBBox3fa& b1) -> LBBox3fa { return embree::merge(b0, b1); });
- }
-
- template<typename RecalculatePrimRef>
- const SetMB primInfo(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
- {
- auto computePrimInfo = [&](const range<size_t>& r) -> PrimInfoMB
- {
- PrimInfoMB pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- PrimRefMB& ref = (*prims)[j];
- PrimRefMB ref1 = recalculatePrimRef(ref,time_range,space);
- pinfo.add_primref(ref1);
- };
- return pinfo;
- };
-
- const PrimInfoMB pinfo = parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD,
- PrimInfoMB(empty), computePrimInfo, PrimInfoMB::merge2);
-
- return SetMB(pinfo,prims,object_range,time_range);
- }
-
- public:
- PrimRefVector prims;
- };
-//}
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/primrefgen.cpp b/thirdparty/embree-aarch64/kernels/builders/primrefgen.cpp
deleted file mode 100644
index e23de3df28..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/primrefgen.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "primrefgen.h"
-#include "primrefgen_presplit.h"
-
-#include "../../common/algorithms/parallel_for_for.h"
-#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
-
-namespace embree
-{
- namespace isa
- {
- PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
- {
- ParallelPrefixSumState<PrimInfo> pstate;
-
- /* first try */
- progressMonitor(0);
- PrimInfo pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
- return geometry->createPrimRefArray(prims,r,r.begin(),geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != prims.size())
- {
- progressMonitor(0);
- pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
- return geometry->createPrimRefArray(prims,r,base.size(),geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
- return pinfo;
- }
-
- PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
- {
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator2 iter(scene,types,mblur);
-
- /* first try */
- progressMonitor(0);
- pstate.init(iter,size_t(1024));
- PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
- return mesh->createPrimRefArray(prims,r,k,(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != prims.size())
- {
- progressMonitor(0);
- pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
- return mesh->createPrimRefArray(prims,r,base.size(),(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
- return pinfo;
- }
-
- PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
- {
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator2 iter(scene,types,true);
-
- /* first try */
- progressMonitor(0);
- pstate.init(iter,size_t(1024));
- PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
- return mesh->createPrimRefArrayMB(prims,itime,r,k,(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != prims.size())
- {
- progressMonitor(0);
- pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
- return mesh->createPrimRefArrayMB(prims,itime,r,base.size(),(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
- return pinfo;
- }
-
- PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
- {
- ParallelForForPrefixSumState<PrimInfoMB> pstate;
- Scene::Iterator2 iter(scene,types,true);
-
- /* first try */
- progressMonitor(0);
- pstate.init(iter,size_t(1024));
- PrimInfoMB pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfoMB {
- return mesh->createPrimRefMBArray(prims,t0t1,r,k,(unsigned)geomID);
- }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != prims.size())
- {
- progressMonitor(0);
- pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
- return mesh->createPrimRefMBArray(prims,t0t1,r,base.size(),(unsigned)geomID);
- }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
- }
-
- /* the BVH starts with that time range, even though primitives might have smaller/larger time range */
- pinfo.time_range = t0t1;
- return pinfo;
- }
-
- template<typename Mesh>
- size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor)
- {
- size_t numPrimitives = morton.size();
-
- /* compute scene bounds */
- std::pair<size_t,BBox3fa> cb_empty(0,empty);
- auto cb = parallel_reduce
- ( size_t(0), numPrimitives, size_t(1024), cb_empty, [&](const range<size_t>& r) -> std::pair<size_t,BBox3fa>
- {
- size_t num = 0;
- BBox3fa bounds = empty;
-
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa prim_bounds = empty;
- if (unlikely(!mesh->buildBounds(j,&prim_bounds))) continue;
- bounds.extend(center2(prim_bounds));
- num++;
- }
- return std::make_pair(num,bounds);
- }, [] (const std::pair<size_t,BBox3fa>& a, const std::pair<size_t,BBox3fa>& b) {
- return std::make_pair(a.first + b.first,merge(a.second,b.second));
- });
-
-
- size_t numPrimitivesGen = cb.first;
- const BBox3fa centBounds = cb.second;
-
- /* compute morton codes */
- if (likely(numPrimitivesGen == numPrimitives))
- {
- /* fast path if all primitives were valid */
- BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
- parallel_for( size_t(0), numPrimitives, size_t(1024), [&](const range<size_t>& r) -> void {
- BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
- for (size_t j=r.begin(); j<r.end(); j++)
- generator(mesh->bounds(j),unsigned(j));
- });
- }
- else
- {
- /* slow path, fallback in case some primitives were invalid */
- ParallelPrefixSumState<size_t> pstate;
- BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
- parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {
- size_t num = 0;
- BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (unlikely(!mesh->buildBounds(j,&bounds))) continue;
- generator(bounds,unsigned(j));
- num++;
- }
- return num;
- }, std::plus<size_t>());
-
- parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {
- size_t num = 0;
- BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[base]);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(j,&bounds)) continue;
- generator(bounds,unsigned(j));
- num++;
- }
- return num;
- }, std::plus<size_t>());
- }
- return numPrimitivesGen;
- }
-
- // ====================================================================================================
- // ====================================================================================================
- // ====================================================================================================
-
- // template for grid meshes
-
-#if 0
- template<>
- PrimInfo createPrimRefArray<GridMesh,false>(Scene* scene, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
- {
- PING;
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator<GridMesh,false> iter(scene);
-
- /* first try */
- progressMonitor(0);
- pstate.init(iter,size_t(1024));
- PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k) -> PrimInfo
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(j,&bounds)) continue;
- const PrimRef prim(bounds,mesh->geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != prims.size())
- {
- progressMonitor(0);
- pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, const PrimInfo& base) -> PrimInfo
- {
- k = base.size();
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(j,&bounds)) continue;
- const PrimRef prim(bounds,mesh->geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
- return pinfo;
- }
-#endif
-
- // ====================================================================================================
- // ====================================================================================================
- // ====================================================================================================
-
- IF_ENABLED_TRIS (template size_t createMortonCodeArray<TriangleMesh>(TriangleMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
- IF_ENABLED_QUADS(template size_t createMortonCodeArray<QuadMesh>(QuadMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
- IF_ENABLED_USER (template size_t createMortonCodeArray<UserGeometry>(UserGeometry* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
- IF_ENABLED_INSTANCE (template size_t createMortonCodeArray<Instance>(Instance* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/primrefgen.h b/thirdparty/embree-aarch64/kernels/builders/primrefgen.h
deleted file mode 100644
index 9919c945c3..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/primrefgen.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/scene.h"
-#include "../common/primref.h"
-#include "../common/primref_mb.h"
-#include "priminfo.h"
-#include "bvh_builder_morton.h"
-
-namespace embree
-{
- namespace isa
- {
- PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor);
-
- PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor);
-
- PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime = 0);
-
- PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f));
-
- template<typename Mesh>
- size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor);
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/builders/primrefgen_presplit.h b/thirdparty/embree-aarch64/kernels/builders/primrefgen_presplit.h
deleted file mode 100644
index 8bdb38b955..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/primrefgen_presplit.h
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../builders/primrefgen.h"
-#include "../builders/heuristic_spatial.h"
-#include "../builders/splitter.h"
-
-#include "../../common/algorithms/parallel_for_for.h"
-#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
-
-#define DBG_PRESPLIT(x)
-#define CHECK_PRESPLIT(x)
-
-#define GRID_SIZE 1024
-#define MAX_PRESPLITS_PER_PRIMITIVE_LOG 5
-#define MAX_PRESPLITS_PER_PRIMITIVE (1<<MAX_PRESPLITS_PER_PRIMITIVE_LOG)
-#define PRIORITY_CUTOFF_THRESHOLD 1.0f
-#define PRIORITY_SPLIT_POS_WEIGHT 1.5f
-
-namespace embree
-{
- namespace isa
- {
-
- struct PresplitItem
- {
- union {
- float priority;
- unsigned int data;
- };
- unsigned int index;
-
- __forceinline operator unsigned() const
- {
- return reinterpret_cast<const unsigned&>(priority);
- }
- __forceinline bool operator < (const PresplitItem& item) const
- {
- return (priority < item.priority);
- }
-
- template<typename Mesh>
- __forceinline static float compute_priority(const PrimRef &ref, Scene *scene, const Vec2i &mc)
- {
- const unsigned int geomID = ref.geomID();
- const unsigned int primID = ref.primID();
- const float area_aabb = area(ref.bounds());
- const float area_prim = ((Mesh*)scene->get(geomID))->projectedPrimitiveArea(primID);
- const unsigned int diff = 31 - lzcnt(mc.x^mc.y);
- assert(area_prim <= area_aabb);
- //const float priority = powf((area_aabb - area_prim) * powf(PRIORITY_SPLIT_POS_WEIGHT,(float)diff),1.0f/4.0f);
- const float priority = sqrtf(sqrtf( (area_aabb - area_prim) * powf(PRIORITY_SPLIT_POS_WEIGHT,(float)diff) ));
- assert(priority >= 0.0f && priority < FLT_LARGE);
- return priority;
- }
-
-
- };
-
- inline std::ostream &operator<<(std::ostream &cout, const PresplitItem& item) {
- return cout << "index " << item.index << " priority " << item.priority;
- };
-
- template<typename SplitterFactory>
- void splitPrimitive(SplitterFactory &Splitter,
- const PrimRef &prim,
- const unsigned int geomID,
- const unsigned int primID,
- const unsigned int split_level,
- const Vec3fa &grid_base,
- const float grid_scale,
- const float grid_extend,
- PrimRef subPrims[MAX_PRESPLITS_PER_PRIMITIVE],
- unsigned int& numSubPrims)
- {
- assert(split_level <= MAX_PRESPLITS_PER_PRIMITIVE_LOG);
- if (split_level == 0)
- {
- assert(numSubPrims < MAX_PRESPLITS_PER_PRIMITIVE);
- subPrims[numSubPrims++] = prim;
- }
- else
- {
- const Vec3fa lower = prim.lower;
- const Vec3fa upper = prim.upper;
- const Vec3fa glower = (lower-grid_base)*Vec3fa(grid_scale)+Vec3fa(0.2f);
- const Vec3fa gupper = (upper-grid_base)*Vec3fa(grid_scale)-Vec3fa(0.2f);
- Vec3ia ilower(floor(glower));
- Vec3ia iupper(floor(gupper));
-
- /* this ignores dimensions that are empty */
- iupper = (Vec3ia)(select(vint4(glower) >= vint4(gupper),vint4(ilower),vint4(iupper)));
-
- /* compute a morton code for the lower and upper grid coordinates. */
- const unsigned int lower_code = bitInterleave(ilower.x,ilower.y,ilower.z);
- const unsigned int upper_code = bitInterleave(iupper.x,iupper.y,iupper.z);
-
- /* if all bits are equal then we cannot split */
- if(unlikely(lower_code == upper_code))
- {
- assert(numSubPrims < MAX_PRESPLITS_PER_PRIMITIVE);
- subPrims[numSubPrims++] = prim;
- return;
- }
-
- /* compute octree level and dimension to perform the split in */
- const unsigned int diff = 31 - lzcnt(lower_code^upper_code);
- const unsigned int level = diff / 3;
- const unsigned int dim = diff % 3;
-
- /* now we compute the grid position of the split */
- const unsigned int isplit = iupper[dim] & ~((1<<level)-1);
-
- /* compute world space position of split */
- const float inv_grid_size = 1.0f / GRID_SIZE;
- const float fsplit = grid_base[dim] + isplit * inv_grid_size * grid_extend;
-
- assert(prim.lower[dim] <= fsplit &&
- prim.upper[dim] >= fsplit);
-
- /* split primitive */
- const auto splitter = Splitter(prim);
- BBox3fa left,right;
- splitter(prim.bounds(),dim,fsplit,left,right);
- assert(!left.empty());
- assert(!right.empty());
-
-
- splitPrimitive(Splitter,PrimRef(left ,geomID,primID),geomID,primID,split_level-1,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
- splitPrimitive(Splitter,PrimRef(right,geomID,primID),geomID,primID,split_level-1,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
- }
- }
-
-
- template<typename Mesh, typename SplitterFactory>
- PrimInfo createPrimRefArray_presplit(Geometry* geometry, unsigned int geomID, size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
- {
- ParallelPrefixSumState<PrimInfo> pstate;
-
- /* first try */
- progressMonitor(0);
- PrimInfo pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
- return geometry->createPrimRefArray(prims,r,r.begin(),geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != numPrimRefs)
- {
- progressMonitor(0);
- pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
- return geometry->createPrimRefArray(prims,r,base.size(),geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
- return pinfo;
- }
-
- __forceinline Vec2i computeMC(const Vec3fa &grid_base, const float grid_scale, const PrimRef &ref)
- {
- const Vec3fa lower = ref.lower;
- const Vec3fa upper = ref.upper;
- const Vec3fa glower = (lower-grid_base)*Vec3fa(grid_scale)+Vec3fa(0.2f);
- const Vec3fa gupper = (upper-grid_base)*Vec3fa(grid_scale)-Vec3fa(0.2f);
- Vec3ia ilower(floor(glower));
- Vec3ia iupper(floor(gupper));
-
- /* this ignores dimensions that are empty */
- iupper = (Vec3ia)select(vint4(glower) >= vint4(gupper),vint4(ilower),vint4(iupper));
-
- /* compute a morton code for the lower and upper grid coordinates. */
- const unsigned int lower_code = bitInterleave(ilower.x,ilower.y,ilower.z);
- const unsigned int upper_code = bitInterleave(iupper.x,iupper.y,iupper.z);
- return Vec2i(lower_code,upper_code);
- }
-
- template<typename Mesh, typename SplitterFactory>
- PrimInfo createPrimRefArray_presplit(Scene* scene, Geometry::GTypeMask types, bool mblur, size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
- {
- static const size_t MIN_STEP_SIZE = 128;
-
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator2 iter(scene,types,mblur);
-
- /* first try */
- progressMonitor(0);
- pstate.init(iter,size_t(1024));
- PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
- return mesh->createPrimRefArray(prims,r,k,(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != numPrimRefs)
- {
- progressMonitor(0);
- pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
- return mesh->createPrimRefArray(prims,r,base.size(),(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
-
- /* use correct number of primitives */
- size_t numPrimitives = pinfo.size();
- const size_t alloc_numPrimitives = prims.size();
- const size_t numSplitPrimitivesBudget = alloc_numPrimitives - numPrimitives;
-
- /* set up primitive splitter */
- SplitterFactory Splitter(scene);
-
-
- DBG_PRESPLIT(
- const size_t org_numPrimitives = pinfo.size();
- PRINT(numPrimitives);
- PRINT(alloc_numPrimitives);
- PRINT(numSplitPrimitivesBudget);
- );
-
- /* allocate double buffer presplit items */
- const size_t presplit_allocation_size = sizeof(PresplitItem)*alloc_numPrimitives;
- PresplitItem *presplitItem = (PresplitItem*)alignedMalloc(presplit_allocation_size,64);
- PresplitItem *tmp_presplitItem = (PresplitItem*)alignedMalloc(presplit_allocation_size,64);
-
- /* compute grid */
- const Vec3fa grid_base = pinfo.geomBounds.lower;
- const Vec3fa grid_diag = pinfo.geomBounds.size();
- const float grid_extend = max(grid_diag.x,max(grid_diag.y,grid_diag.z));
- const float grid_scale = grid_extend == 0.0f ? 0.0f : GRID_SIZE / grid_extend;
-
- /* init presplit items and get total sum */
- const float psum = parallel_reduce( size_t(0), numPrimitives, size_t(MIN_STEP_SIZE), 0.0f, [&](const range<size_t>& r) -> float {
- float sum = 0.0f;
- for (size_t i=r.begin(); i<r.end(); i++)
- {
- presplitItem[i].index = (unsigned int)i;
- const Vec2i mc = computeMC(grid_base,grid_scale,prims[i]);
- /* if all bits are equal then we cannot split */
- presplitItem[i].priority = (mc.x != mc.y) ? PresplitItem::compute_priority<Mesh>(prims[i],scene,mc) : 0.0f;
- /* FIXME: sum undeterministic */
- sum += presplitItem[i].priority;
- }
- return sum;
- },[](const float& a, const float& b) -> float { return a+b; });
-
- /* compute number of splits per primitive */
- const float inv_psum = 1.0f / psum;
- parallel_for( size_t(0), numPrimitives, size_t(MIN_STEP_SIZE), [&](const range<size_t>& r) -> void {
- for (size_t i=r.begin(); i<r.end(); i++)
- {
- if (presplitItem[i].priority > 0.0f)
- {
- const float rel_p = (float)numSplitPrimitivesBudget * presplitItem[i].priority * inv_psum;
- if (rel_p >= PRIORITY_CUTOFF_THRESHOLD) // need at least a split budget that generates two sub-prims
- {
- presplitItem[i].priority = max(min(ceilf(logf(rel_p)/logf(2.0f)),(float)MAX_PRESPLITS_PER_PRIMITIVE_LOG),1.0f);
- //presplitItem[i].priority = min(floorf(logf(rel_p)/logf(2.0f)),(float)MAX_PRESPLITS_PER_PRIMITIVE_LOG);
- assert(presplitItem[i].priority >= 0.0f && presplitItem[i].priority <= (float)MAX_PRESPLITS_PER_PRIMITIVE_LOG);
- }
- else
- presplitItem[i].priority = 0.0f;
- }
- }
- });
-
- auto isLeft = [&] (const PresplitItem &ref) { return ref.priority < PRIORITY_CUTOFF_THRESHOLD; };
- size_t center = parallel_partitioning(presplitItem,0,numPrimitives,isLeft,1024);
-
- /* anything to split ? */
- if (center < numPrimitives)
- {
- const size_t numPrimitivesToSplit = numPrimitives - center;
- assert(presplitItem[center].priority >= 1.0f);
-
- /* sort presplit items in ascending order */
- radix_sort_u32(presplitItem + center,tmp_presplitItem + center,numPrimitivesToSplit,1024);
-
- CHECK_PRESPLIT(
- parallel_for( size_t(center+1), numPrimitives, size_t(MIN_STEP_SIZE), [&](const range<size_t>& r) -> void {
- for (size_t i=r.begin(); i<r.end(); i++)
- assert(presplitItem[i-1].priority <= presplitItem[i].priority);
- });
- );
-
- unsigned int *const primOffset0 = (unsigned int*)tmp_presplitItem;
- unsigned int *const primOffset1 = (unsigned int*)tmp_presplitItem + numPrimitivesToSplit;
-
- /* compute actual number of sub-primitives generated within the [center;numPrimitives-1] range */
- const size_t totalNumSubPrims = parallel_reduce( size_t(center), numPrimitives, size_t(MIN_STEP_SIZE), size_t(0), [&](const range<size_t>& t) -> size_t {
- size_t sum = 0;
- for (size_t i=t.begin(); i<t.end(); i++)
- {
- PrimRef subPrims[MAX_PRESPLITS_PER_PRIMITIVE];
- assert(presplitItem[i].priority >= 1.0f);
- const unsigned int primrefID = presplitItem[i].index;
- const float prio = presplitItem[i].priority;
- const unsigned int geomID = prims[primrefID].geomID();
- const unsigned int primID = prims[primrefID].primID();
- const unsigned int split_levels = (unsigned int)prio;
- unsigned int numSubPrims = 0;
- splitPrimitive(Splitter,prims[primrefID],geomID,primID,split_levels,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
- assert(numSubPrims);
- numSubPrims--; // can reuse slot
- sum+=numSubPrims;
- presplitItem[i].data = (numSubPrims << MAX_PRESPLITS_PER_PRIMITIVE_LOG) | split_levels;
- primOffset0[i-center] = numSubPrims;
- }
- return sum;
- },[](const size_t& a, const size_t& b) -> size_t { return a+b; });
-
- /* if we are over budget, need to shrink the range */
- if (totalNumSubPrims > numSplitPrimitivesBudget)
- {
- size_t new_center = numPrimitives-1;
- size_t sum = 0;
- for (;new_center>=center;new_center--)
- {
- const unsigned int numSubPrims = presplitItem[new_center].data >> MAX_PRESPLITS_PER_PRIMITIVE_LOG;
- if (unlikely(sum + numSubPrims >= numSplitPrimitivesBudget)) break;
- sum += numSubPrims;
- }
- new_center++;
- center = new_center;
- }
-
- /* parallel prefix sum to compute offsets for storing sub-primitives */
- const unsigned int offset = parallel_prefix_sum(primOffset0,primOffset1,numPrimitivesToSplit,(unsigned int)0,std::plus<unsigned int>());
-
- /* iterate over range, and split primitives into sub primitives and append them to prims array */
- parallel_for( size_t(center), numPrimitives, size_t(MIN_STEP_SIZE), [&](const range<size_t>& rn) -> void {
- for (size_t j=rn.begin(); j<rn.end(); j++)
- {
- PrimRef subPrims[MAX_PRESPLITS_PER_PRIMITIVE];
- const unsigned int primrefID = presplitItem[j].index;
- const unsigned int geomID = prims[primrefID].geomID();
- const unsigned int primID = prims[primrefID].primID();
- const unsigned int split_levels = presplitItem[j].data & ((unsigned int)(1 << MAX_PRESPLITS_PER_PRIMITIVE_LOG)-1);
-
- assert(split_levels);
- assert(split_levels <= MAX_PRESPLITS_PER_PRIMITIVE_LOG);
- unsigned int numSubPrims = 0;
- splitPrimitive(Splitter,prims[primrefID],geomID,primID,split_levels,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
- const size_t newID = numPrimitives + primOffset1[j-center];
- assert(newID+numSubPrims <= alloc_numPrimitives);
- prims[primrefID] = subPrims[0];
- for (size_t i=1;i<numSubPrims;i++)
- prims[newID+i-1] = subPrims[i];
- }
- });
-
- numPrimitives += offset;
- DBG_PRESPLIT(
- PRINT(pinfo.size());
- PRINT(numPrimitives);
- PRINT((float)numPrimitives/org_numPrimitives));
- }
-
- /* recompute centroid bounding boxes */
- pinfo = parallel_reduce(size_t(0),numPrimitives,size_t(MIN_STEP_SIZE),PrimInfo(empty),[&] (const range<size_t>& r) -> PrimInfo {
- PrimInfo p(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- p.add_center2(prims[j]);
- return p;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- assert(pinfo.size() == numPrimitives);
-
- /* free double buffer presplit items */
- alignedFree(tmp_presplitItem);
- alignedFree(presplitItem);
- return pinfo;
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/builders/splitter.h b/thirdparty/embree-aarch64/kernels/builders/splitter.h
deleted file mode 100644
index dbd6cf07c7..0000000000
--- a/thirdparty/embree-aarch64/kernels/builders/splitter.h
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/scene.h"
-#include "../common/primref.h"
-
-namespace embree
-{
- namespace isa
- {
- template<size_t N>
- __forceinline void splitPolygon(const BBox3fa& bounds,
- const size_t dim,
- const float pos,
- const Vec3fa (&v)[N+1],
- const Vec3fa (&inv_length)[N],
- BBox3fa& left_o,
- BBox3fa& right_o)
- {
- BBox3fa left = empty, right = empty;
- /* clip triangle to left and right box by processing all edges */
- for (size_t i=0; i<N; i++)
- {
- const Vec3fa &v0 = v[i];
- const Vec3fa &v1 = v[i+1];
- const float v0d = v0[dim];
- const float v1d = v1[dim];
-
- if (v0d <= pos) left. extend(v0); // this point is on left side
- if (v0d >= pos) right.extend(v0); // this point is on right side
-
- if ((v0d < pos && pos < v1d) || (v1d < pos && pos < v0d)) // the edge crosses the splitting location
- {
- assert((v1d-v0d) != 0.0f);
- const Vec3fa c = madd(Vec3fa((pos-v0d)*inv_length[i][dim]),v1-v0,v0);
- left.extend(c);
- right.extend(c);
- }
- }
-
- /* clip against current bounds */
- left_o = intersect(left,bounds);
- right_o = intersect(right,bounds);
- }
-
- template<size_t N>
- __forceinline void splitPolygon(const PrimRef& prim,
- const size_t dim,
- const float pos,
- const Vec3fa (&v)[N+1],
- PrimRef& left_o,
- PrimRef& right_o)
- {
- BBox3fa left = empty, right = empty;
- for (size_t i=0; i<N; i++)
- {
- const Vec3fa &v0 = v[i];
- const Vec3fa &v1 = v[i+1];
- const float v0d = v0[dim];
- const float v1d = v1[dim];
-
- if (v0d <= pos) left. extend(v0); // this point is on left side
- if (v0d >= pos) right.extend(v0); // this point is on right side
-
- if ((v0d < pos && pos < v1d) || (v1d < pos && pos < v0d)) // the edge crosses the splitting location
- {
- assert((v1d-v0d) != 0.0f);
- const float inv_length = 1.0f/(v1d-v0d);
- const Vec3fa c = madd(Vec3fa((pos-v0d)*inv_length),v1-v0,v0);
- left.extend(c);
- right.extend(c);
- }
- }
-
- /* clip against current bounds */
- new (&left_o ) PrimRef(intersect(left ,prim.bounds()),prim.geomID(), prim.primID());
- new (&right_o) PrimRef(intersect(right,prim.bounds()),prim.geomID(), prim.primID());
- }
-
- struct TriangleSplitter
- {
- __forceinline TriangleSplitter(const Scene* scene, const PrimRef& prim)
- {
- const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
- const TriangleMesh* mesh = (const TriangleMesh*) scene->get(prim.geomID() & mask );
- TriangleMesh::Triangle tri = mesh->triangle(prim.primID());
- v[0] = mesh->vertex(tri.v[0]);
- v[1] = mesh->vertex(tri.v[1]);
- v[2] = mesh->vertex(tri.v[2]);
- v[3] = mesh->vertex(tri.v[0]);
- inv_length[0] = Vec3fa(1.0f) / (v[1]-v[0]);
- inv_length[1] = Vec3fa(1.0f) / (v[2]-v[1]);
- inv_length[2] = Vec3fa(1.0f) / (v[0]-v[2]);
- }
-
- __forceinline void operator() (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const {
- splitPolygon<3>(prim,dim,pos,v,left_o,right_o);
- }
-
- __forceinline void operator() (const BBox3fa& prim, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const {
- splitPolygon<3>(prim,dim,pos,v,inv_length,left_o,right_o);
- }
-
- private:
- Vec3fa v[4];
- Vec3fa inv_length[3];
- };
-
- struct TriangleSplitterFactory
- {
- __forceinline TriangleSplitterFactory(const Scene* scene)
- : scene(scene) {}
-
- __forceinline TriangleSplitter operator() (const PrimRef& prim) const {
- return TriangleSplitter(scene,prim);
- }
-
- private:
- const Scene* scene;
- };
-
- struct QuadSplitter
- {
- __forceinline QuadSplitter(const Scene* scene, const PrimRef& prim)
- {
- const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
- const QuadMesh* mesh = (const QuadMesh*) scene->get(prim.geomID() & mask );
- QuadMesh::Quad quad = mesh->quad(prim.primID());
- v[0] = mesh->vertex(quad.v[0]);
- v[1] = mesh->vertex(quad.v[1]);
- v[2] = mesh->vertex(quad.v[2]);
- v[3] = mesh->vertex(quad.v[3]);
- v[4] = mesh->vertex(quad.v[0]);
- inv_length[0] = Vec3fa(1.0f) / (v[1]-v[0]);
- inv_length[1] = Vec3fa(1.0f) / (v[2]-v[1]);
- inv_length[2] = Vec3fa(1.0f) / (v[3]-v[2]);
- inv_length[3] = Vec3fa(1.0f) / (v[0]-v[3]);
- }
-
- __forceinline void operator() (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const {
- splitPolygon<4>(prim,dim,pos,v,left_o,right_o);
- }
-
- __forceinline void operator() (const BBox3fa& prim, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const {
- splitPolygon<4>(prim,dim,pos,v,inv_length,left_o,right_o);
- }
-
- private:
- Vec3fa v[5];
- Vec3fa inv_length[4];
- };
-
- struct QuadSplitterFactory
- {
- __forceinline QuadSplitterFactory(const Scene* scene)
- : scene(scene) {}
-
- __forceinline QuadSplitter operator() (const PrimRef& prim) const {
- return QuadSplitter(scene,prim);
- }
-
- private:
- const Scene* scene;
- };
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh.cpp
deleted file mode 100644
index bd102bd6ef..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh.h"
-#include "bvh_statistics.h"
-
-namespace embree
-{
- template<int N>
- BVHN<N>::BVHN (const PrimitiveType& primTy, Scene* scene)
- : AccelData((N==4) ? AccelData::TY_BVH4 : (N==8) ? AccelData::TY_BVH8 : AccelData::TY_UNKNOWN),
- primTy(&primTy), device(scene->device), scene(scene),
- root(emptyNode), alloc(scene->device,scene->isStaticAccel()), numPrimitives(0), numVertices(0)
- {
- }
-
- template<int N>
- BVHN<N>::~BVHN ()
- {
- for (size_t i=0; i<objects.size(); i++)
- delete objects[i];
- }
-
- template<int N>
- void BVHN<N>::clear()
- {
- set(BVHN::emptyNode,empty,0);
- alloc.clear();
- }
-
- template<int N>
- void BVHN<N>::set (NodeRef root, const LBBox3fa& bounds, size_t numPrimitives)
- {
- this->root = root;
- this->bounds = bounds;
- this->numPrimitives = numPrimitives;
- }
-
- template<int N>
- void BVHN<N>::clearBarrier(NodeRef& node)
- {
- if (node.isBarrier())
- node.clearBarrier();
- else if (!node.isLeaf()) {
- BaseNode* n = node.baseNode(); // FIXME: flags should be stored in BVH
- for (size_t c=0; c<N; c++)
- clearBarrier(n->child(c));
- }
- }
-
- template<int N>
- void BVHN<N>::layoutLargeNodes(size_t num)
- {
-#if defined(__X86_64__) || defined(__aarch64__) // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues
- struct NodeArea
- {
- __forceinline NodeArea() {}
-
- __forceinline NodeArea(NodeRef& node, const BBox3fa& bounds)
- : node(&node), A(node.isLeaf() ? float(neg_inf) : area(bounds)) {}
-
- __forceinline bool operator< (const NodeArea& other) const {
- return this->A < other.A;
- }
-
- NodeRef* node;
- float A;
- };
- std::vector<NodeArea> lst;
- lst.reserve(num);
- lst.push_back(NodeArea(root,empty));
-
- while (lst.size() < num)
- {
- std::pop_heap(lst.begin(), lst.end());
- NodeArea n = lst.back(); lst.pop_back();
- if (!n.node->isAABBNode()) break;
- AABBNode* node = n.node->getAABBNode();
- for (size_t i=0; i<N; i++) {
- if (node->child(i) == BVHN::emptyNode) continue;
- lst.push_back(NodeArea(node->child(i),node->bounds(i)));
- std::push_heap(lst.begin(), lst.end());
- }
- }
-
- for (size_t i=0; i<lst.size(); i++)
- lst[i].node->setBarrier();
-
- root = layoutLargeNodesRecursion(root,alloc.getCachedAllocator());
-#endif
- }
-
- template<int N>
- typename BVHN<N>::NodeRef BVHN<N>::layoutLargeNodesRecursion(NodeRef& node, const FastAllocator::CachedAllocator& allocator)
- {
- if (node.isBarrier()) {
- node.clearBarrier();
- return node;
- }
- else if (node.isAABBNode())
- {
- AABBNode* oldnode = node.getAABBNode();
- AABBNode* newnode = (BVHN::AABBNode*) allocator.malloc0(sizeof(BVHN::AABBNode),byteNodeAlignment);
- *newnode = *oldnode;
- for (size_t c=0; c<N; c++)
- newnode->child(c) = layoutLargeNodesRecursion(oldnode->child(c),allocator);
- return encodeNode(newnode);
- }
- else return node;
- }
-
- template<int N>
- double BVHN<N>::preBuild(const std::string& builderName)
- {
- if (builderName == "")
- return inf;
-
- if (device->verbosity(2))
- {
- Lock<MutexSys> lock(g_printMutex);
- std::cout << "building BVH" << N << (builderName.find("MBlur") != std::string::npos ? "MB" : "") << "<" << primTy->name() << "> using " << builderName << " ..." << std::endl << std::flush;
- }
-
- double t0 = 0.0;
- if (device->benchmark || device->verbosity(2)) t0 = getSeconds();
- return t0;
- }
-
- template<int N>
- void BVHN<N>::postBuild(double t0)
- {
- if (t0 == double(inf))
- return;
-
- double dt = 0.0;
- if (device->benchmark || device->verbosity(2))
- dt = getSeconds()-t0;
-
- std::unique_ptr<BVHNStatistics<N>> stat;
-
- /* print statistics */
- if (device->verbosity(2))
- {
- if (!stat) stat.reset(new BVHNStatistics<N>(this));
- const size_t usedBytes = alloc.getUsedBytes();
- Lock<MutexSys> lock(g_printMutex);
- std::cout << "finished BVH" << N << "<" << primTy->name() << "> : " << 1000.0f*dt << "ms, " << 1E-6*double(numPrimitives)/dt << " Mprim/s, " << 1E-9*double(usedBytes)/dt << " GB/s" << std::endl;
-
- if (device->verbosity(2))
- std::cout << stat->str();
-
- if (device->verbosity(2))
- {
- FastAllocator::AllStatistics stat(&alloc);
- for (size_t i=0; i<objects.size(); i++)
- if (objects[i])
- stat = stat + FastAllocator::AllStatistics(&objects[i]->alloc);
-
- stat.print(numPrimitives);
- }
-
- if (device->verbosity(3))
- {
- alloc.print_blocks();
- for (size_t i=0; i<objects.size(); i++)
- if (objects[i])
- objects[i]->alloc.print_blocks();
- }
-
- std::cout << std::flush;
- }
-
- /* benchmark mode */
- if (device->benchmark)
- {
- if (!stat) stat.reset(new BVHNStatistics<N>(this));
- Lock<MutexSys> lock(g_printMutex);
- std::cout << "BENCHMARK_BUILD " << dt << " " << double(numPrimitives)/dt << " " << stat->sah() << " " << stat->bytesUsed() << " BVH" << N << "<" << primTy->name() << ">" << std::endl << std::flush;
- }
- }
-
-#if defined(__AVX__)
- template class BVHN<8>;
-#endif
-
-#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42) || defined(__aarch64__)
- template class BVHN<4>;
-#endif
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh.h b/thirdparty/embree-aarch64/kernels/bvh/bvh.h
deleted file mode 100644
index 8fdf912e52..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh.h
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-/* include all node types */
-#include "bvh_node_aabb.h"
-#include "bvh_node_aabb_mb.h"
-#include "bvh_node_aabb_mb4d.h"
-#include "bvh_node_obb.h"
-#include "bvh_node_obb_mb.h"
-#include "bvh_node_qaabb.h"
-
-namespace embree
-{
- /*! flags used to enable specific node types in intersectors */
- enum BVHNodeFlags
- {
- BVH_FLAG_ALIGNED_NODE = 0x00001,
- BVH_FLAG_ALIGNED_NODE_MB = 0x00010,
- BVH_FLAG_UNALIGNED_NODE = 0x00100,
- BVH_FLAG_UNALIGNED_NODE_MB = 0x01000,
- BVH_FLAG_QUANTIZED_NODE = 0x100000,
- BVH_FLAG_ALIGNED_NODE_MB4D = 0x1000000,
-
- /* short versions */
- BVH_AN1 = BVH_FLAG_ALIGNED_NODE,
- BVH_AN2 = BVH_FLAG_ALIGNED_NODE_MB,
- BVH_AN2_AN4D = BVH_FLAG_ALIGNED_NODE_MB | BVH_FLAG_ALIGNED_NODE_MB4D,
- BVH_UN1 = BVH_FLAG_UNALIGNED_NODE,
- BVH_UN2 = BVH_FLAG_UNALIGNED_NODE_MB,
- BVH_MB = BVH_FLAG_ALIGNED_NODE_MB | BVH_FLAG_UNALIGNED_NODE_MB | BVH_FLAG_ALIGNED_NODE_MB4D,
- BVH_AN1_UN1 = BVH_FLAG_ALIGNED_NODE | BVH_FLAG_UNALIGNED_NODE,
- BVH_AN2_UN2 = BVH_FLAG_ALIGNED_NODE_MB | BVH_FLAG_UNALIGNED_NODE_MB,
- BVH_AN2_AN4D_UN2 = BVH_FLAG_ALIGNED_NODE_MB | BVH_FLAG_ALIGNED_NODE_MB4D | BVH_FLAG_UNALIGNED_NODE_MB,
- BVH_QN1 = BVH_FLAG_QUANTIZED_NODE
- };
-
- /*! Multi BVH with N children. Each node stores the bounding box of
- * it's N children as well as N child references. */
- template<int N>
- class BVHN : public AccelData
- {
- ALIGNED_CLASS_(16);
- public:
-
- /*! forward declaration of node ref type */
- typedef NodeRefPtr<N> NodeRef;
- typedef BaseNode_t<NodeRef,N> BaseNode;
- typedef AABBNode_t<NodeRef,N> AABBNode;
- typedef AABBNodeMB_t<NodeRef,N> AABBNodeMB;
- typedef AABBNodeMB4D_t<NodeRef,N> AABBNodeMB4D;
- typedef OBBNode_t<NodeRef,N> OBBNode;
- typedef OBBNodeMB_t<NodeRef,N> OBBNodeMB;
- typedef QuantizedBaseNode_t<N> QuantizedBaseNode;
- typedef QuantizedBaseNodeMB_t<N> QuantizedBaseNodeMB;
- typedef QuantizedNode_t<NodeRef,N> QuantizedNode;
-
- /*! Number of bytes the nodes and primitives are minimally aligned to.*/
- static const size_t byteAlignment = 16;
- static const size_t byteNodeAlignment = 4*N;
-
- /*! Empty node */
- static const size_t emptyNode = NodeRef::emptyNode;
-
- /*! Invalid node, used as marker in traversal */
- static const size_t invalidNode = NodeRef::invalidNode;
- static const size_t popRay = NodeRef::popRay;
-
- /*! Maximum depth of the BVH. */
- static const size_t maxBuildDepth = 32;
- static const size_t maxBuildDepthLeaf = maxBuildDepth+8;
- static const size_t maxDepth = 2*maxBuildDepthLeaf; // 2x because of two level builder
-
- /*! Maximum number of primitive blocks in a leaf. */
- static const size_t maxLeafBlocks = NodeRef::maxLeafBlocks;
-
- public:
-
- /*! Builder interface to create allocator */
- struct CreateAlloc : public FastAllocator::Create {
- __forceinline CreateAlloc (BVHN* bvh) : FastAllocator::Create(&bvh->alloc) {}
- };
-
- typedef BVHNodeRecord<NodeRef> NodeRecord;
- typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
- typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
-
- public:
-
- /*! BVHN default constructor. */
- BVHN (const PrimitiveType& primTy, Scene* scene);
-
- /*! BVHN destruction */
- ~BVHN ();
-
- /*! clears the acceleration structure */
- void clear();
-
- /*! sets BVH members after build */
- void set (NodeRef root, const LBBox3fa& bounds, size_t numPrimitives);
-
- /*! Clears the barrier bits of a subtree. */
- void clearBarrier(NodeRef& node);
-
- /*! lays out num large nodes of the BVH */
- void layoutLargeNodes(size_t num);
- NodeRef layoutLargeNodesRecursion(NodeRef& node, const FastAllocator::CachedAllocator& allocator);
-
- /*! called by all builders before build starts */
- double preBuild(const std::string& builderName);
-
- /*! called by all builders after build ended */
- void postBuild(double t0);
-
- /*! allocator class */
- struct Allocator {
- BVHN* bvh;
- Allocator (BVHN* bvh) : bvh(bvh) {}
- __forceinline void* operator() (size_t bytes) const {
- return bvh->alloc._threadLocal()->malloc(&bvh->alloc,bytes);
- }
- };
-
- /*! post build cleanup */
- void cleanup() {
- alloc.cleanup();
- }
-
- public:
-
- /*! Encodes a node */
- static __forceinline NodeRef encodeNode(AABBNode* node) { return NodeRef::encodeNode(node); }
- static __forceinline NodeRef encodeNode(AABBNodeMB* node) { return NodeRef::encodeNode(node); }
- static __forceinline NodeRef encodeNode(AABBNodeMB4D* node) { return NodeRef::encodeNode(node); }
- static __forceinline NodeRef encodeNode(OBBNode* node) { return NodeRef::encodeNode(node); }
- static __forceinline NodeRef encodeNode(OBBNodeMB* node) { return NodeRef::encodeNode(node); }
- static __forceinline NodeRef encodeLeaf(void* tri, size_t num) { return NodeRef::encodeLeaf(tri,num); }
- static __forceinline NodeRef encodeTypedLeaf(void* ptr, size_t ty) { return NodeRef::encodeTypedLeaf(ptr,ty); }
-
- public:
-
- /*! Prefetches the node this reference points to */
- __forceinline static void prefetch(const NodeRef ref, int types=0)
- {
-#if defined(__AVX512PF__) // MIC
- if (types != BVH_FLAG_QUANTIZED_NODE) {
- prefetchL2(((char*)ref.ptr)+0*64);
- prefetchL2(((char*)ref.ptr)+1*64);
- if ((N >= 8) || (types > BVH_FLAG_ALIGNED_NODE)) {
- prefetchL2(((char*)ref.ptr)+2*64);
- prefetchL2(((char*)ref.ptr)+3*64);
- }
- if ((N >= 8) && (types > BVH_FLAG_ALIGNED_NODE)) {
- /* KNL still needs L2 prefetches for large nodes */
- prefetchL2(((char*)ref.ptr)+4*64);
- prefetchL2(((char*)ref.ptr)+5*64);
- prefetchL2(((char*)ref.ptr)+6*64);
- prefetchL2(((char*)ref.ptr)+7*64);
- }
- }
- else
- {
- /* todo: reduce if 32bit offsets are enabled */
- prefetchL2(((char*)ref.ptr)+0*64);
- prefetchL2(((char*)ref.ptr)+1*64);
- prefetchL2(((char*)ref.ptr)+2*64);
- }
-#else
- if (types != BVH_FLAG_QUANTIZED_NODE) {
- prefetchL1(((char*)ref.ptr)+0*64);
- prefetchL1(((char*)ref.ptr)+1*64);
- if ((N >= 8) || (types > BVH_FLAG_ALIGNED_NODE)) {
- prefetchL1(((char*)ref.ptr)+2*64);
- prefetchL1(((char*)ref.ptr)+3*64);
- }
- if ((N >= 8) && (types > BVH_FLAG_ALIGNED_NODE)) {
- /* deactivate for large nodes on Xeon, as it introduces regressions */
- //prefetchL1(((char*)ref.ptr)+4*64);
- //prefetchL1(((char*)ref.ptr)+5*64);
- //prefetchL1(((char*)ref.ptr)+6*64);
- //prefetchL1(((char*)ref.ptr)+7*64);
- }
- }
- else
- {
- /* todo: reduce if 32bit offsets are enabled */
- prefetchL1(((char*)ref.ptr)+0*64);
- prefetchL1(((char*)ref.ptr)+1*64);
- prefetchL1(((char*)ref.ptr)+2*64);
- }
-#endif
- }
-
- __forceinline static void prefetchW(const NodeRef ref, int types=0)
- {
- embree::prefetchEX(((char*)ref.ptr)+0*64);
- embree::prefetchEX(((char*)ref.ptr)+1*64);
- if ((N >= 8) || (types > BVH_FLAG_ALIGNED_NODE)) {
- embree::prefetchEX(((char*)ref.ptr)+2*64);
- embree::prefetchEX(((char*)ref.ptr)+3*64);
- }
- if ((N >= 8) && (types > BVH_FLAG_ALIGNED_NODE)) {
- embree::prefetchEX(((char*)ref.ptr)+4*64);
- embree::prefetchEX(((char*)ref.ptr)+5*64);
- embree::prefetchEX(((char*)ref.ptr)+6*64);
- embree::prefetchEX(((char*)ref.ptr)+7*64);
- }
- }
-
- /*! bvh type information */
- public:
- const PrimitiveType* primTy; //!< primitive type stored in the BVH
-
- /*! bvh data */
- public:
- Device* device; //!< device pointer
- Scene* scene; //!< scene pointer
- NodeRef root; //!< root node
- FastAllocator alloc; //!< allocator used to allocate nodes
-
- /*! statistics data */
- public:
- size_t numPrimitives; //!< number of primitives the BVH is build over
- size_t numVertices; //!< number of vertices the BVH references
-
- /*! data arrays for special builders */
- public:
- std::vector<BVHN*> objects;
- vector_t<char,aligned_allocator<char,32>> subdiv_patches;
- };
-
- typedef BVHN<4> BVH4;
- typedef BVHN<8> BVH8;
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh4_factory.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh4_factory.cpp
deleted file mode 100644
index 23f4f63d45..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh4_factory.cpp
+++ /dev/null
@@ -1,1325 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh4_factory.h"
-#include "../bvh/bvh.h"
-
-#include "../geometry/curveNv.h"
-#include "../geometry/curveNi.h"
-#include "../geometry/curveNi_mb.h"
-#include "../geometry/linei.h"
-#include "../geometry/triangle.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/trianglev_mb.h"
-#include "../geometry/trianglei.h"
-#include "../geometry/quadv.h"
-#include "../geometry/quadi.h"
-#include "../geometry/subdivpatch1.h"
-#include "../geometry/object.h"
-#include "../geometry/instance.h"
-#include "../geometry/subgrid.h"
-#include "../common/accelinstance.h"
-
-namespace embree
-{
- DECLARE_SYMBOL2(Accel::Collider,BVH4ColliderUserGeom);
-
- DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector4i,void);
- DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8i,void);
- DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector4v,void);
- DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8v,void);
- DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector4iMB,void);
- DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8iMB,void);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersector1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersector1MB);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersectorRobust1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersectorRobust1MB);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4Intersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vIntersector1Pluecker);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vMBIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iMBIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vMBIntersector1Pluecker);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iMBIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4vIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4iIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4vIntersector1Pluecker);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4iIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4iMBIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4iMBIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,QBVH4Triangle4iIntersector1Pluecker);
- DECLARE_SYMBOL2(Accel::Intersector1,QBVH4Quad4iIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4SubdivPatch1Intersector1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4SubdivPatch1MBIntersector1);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4VirtualIntersector1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4VirtualMBIntersector1);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4InstanceIntersector1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4InstanceMBIntersector1);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4GridIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4GridMBIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH4GridIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersector4Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersector4HybridMB);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersectorRobust4Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersectorRobust4HybridMB);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4Intersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4Intersector4HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vIntersector4HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vMBIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iMBIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vMBIntersector4HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iMBIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4iIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4iIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4iMBIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4iMBIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4SubdivPatch1Intersector4);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4SubdivPatch1MBIntersector4);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4VirtualIntersector4Chunk);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4VirtualMBIntersector4Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4InstanceIntersector4Chunk);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4InstanceMBIntersector4Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4GridIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4GridMBIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH4GridIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersector8Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersector8HybridMB);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersectorRobust8Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersectorRobust8HybridMB);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4Intersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4Intersector8HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vIntersector8HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vMBIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iMBIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vMBIntersector8HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iMBIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4iIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4iIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4iMBIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4iMBIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4SubdivPatch1Intersector8);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4SubdivPatch1MBIntersector8);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4VirtualIntersector8Chunk);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4VirtualMBIntersector8Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4InstanceIntersector8Chunk);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4InstanceMBIntersector8Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4GridIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4GridMBIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH4GridIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersector16Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersector16HybridMB);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersectorRobust16Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersectorRobust16HybridMB);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4Intersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4Intersector16HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vIntersector16HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vMBIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iMBIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vMBIntersector16HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iMBIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4iIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4iIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4iMBIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4iMBIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4SubdivPatch1Intersector16);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4SubdivPatch1MBIntersector16);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4VirtualIntersector16Chunk);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4VirtualMBIntersector16Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4InstanceIntersector16Chunk);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4InstanceMBIntersector16Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4GridIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4GridMBIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH4GridIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4IntersectorStreamPacketFallback);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4IntersectorStreamMoeller);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4IntersectorStreamMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4iIntersectorStreamMoeller);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4vIntersectorStreamPluecker);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4iIntersectorStreamPluecker);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4vIntersectorStreamMoeller);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4vIntersectorStreamMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4iIntersectorStreamMoeller);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4vIntersectorStreamPluecker);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4iIntersectorStreamPluecker);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4VirtualIntersectorStream);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH4InstanceIntersectorStream);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4MeshSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4vMeshSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4Curve4vBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Curve4iBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4OBBCurve4iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Curve8iBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4OBBCurve8iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4QuantizedTriangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4QuantizedQuad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4SceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
- DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMBSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4GridSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4GridMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4SubdivPatch1BuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4SubdivPatch1MBBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4MeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshRefitSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
-
- BVH4Factory::BVH4Factory(int bfeatures, int ifeatures)
- {
- SELECT_SYMBOL_DEFAULT_AVX_AVX2(ifeatures,BVH4ColliderUserGeom);
-
- selectBuilders(bfeatures);
- selectIntersectors(ifeatures);
- }
-
- void BVH4Factory::selectBuilders(int features)
- {
- IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelTriangle4MeshSAH));
- IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelTriangle4iMeshSAH));
- IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelTriangle4vMeshSAH));
- IF_ENABLED_QUADS (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelQuadMeshSAH));
- IF_ENABLED_USER (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelVirtualSAH));
- IF_ENABLED_INSTANCE (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelInstanceSAH));
-
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Curve4vBuilder_OBB_New));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Curve4iBuilder_OBB_New));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4OBBCurve4iMBBuilder_OBB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH4Curve8iBuilder_OBB_New));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH4OBBCurve8iMBBuilder_OBB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Triangle4SceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Triangle4vSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Triangle4iSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4iMBSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4vMBSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4QuantizedTriangle4iSceneBuilderSAH));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Quad4vSceneBuilderSAH));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Quad4iSceneBuilderSAH));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4iMBSceneBuilderSAH));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4QuantizedQuad4iSceneBuilderSAH));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4SceneBuilderFastSpatialSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4vSceneBuilderFastSpatialSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4iSceneBuilderFastSpatialSAH));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4vSceneBuilderFastSpatialSAH));
-
- IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4VirtualSceneBuilderSAH));
- IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4VirtualMBSceneBuilderSAH));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4InstanceSceneBuilderSAH));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4InstanceMBSceneBuilderSAH));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4GridSceneBuilderSAH));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4GridMBSceneBuilderSAH));
-
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4SubdivPatch1BuilderSAH));
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4SubdivPatch1MBBuilderSAH));
- }
-
- void BVH4Factory::selectIntersectors(int features)
- {
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector4i));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8i));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector4v));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8v));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector4iMB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8iMB));
-
- /* select intersectors1 */
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector1));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector1MB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust1));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust1MB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4Intersector1Moeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,BVH4Triangle4iIntersector1Moeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,BVH4Triangle4vIntersector1Pluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,BVH4Triangle4iIntersector1Pluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector1Moeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector1Moeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector1Pluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector1Pluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector1Moeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector1Moeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector1Pluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector1Pluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector1Pluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector1Moeller));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,QBVH4Triangle4iIntersector1Pluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,QBVH4Quad4iIntersector1Pluecker));
-
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1Intersector1));
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1MBIntersector1));
-
- IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4VirtualIntersector1));
- IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4VirtualMBIntersector1));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4InstanceIntersector1));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4InstanceMBIntersector1));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector1Moeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridMBIntersector1Moeller))
- IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector1Pluecker));
-
-#if defined (EMBREE_RAY_PACKETS)
-
- /* select intersectors4 */
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector4Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector4HybridMB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust4Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust4HybridMB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4Intersector4HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4Intersector4HybridMoellerNoFilter));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iIntersector4HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vIntersector4HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iIntersector4HybridPluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector4HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector4HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector4HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector4HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector4HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector4HybridMoellerNoFilter));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector4HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector4HybridPluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector4HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector4HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector4HybridPluecker));
-
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1Intersector4));
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1MBIntersector4));
-
- IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4VirtualIntersector4Chunk));
- IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4VirtualMBIntersector4Chunk));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4InstanceIntersector4Chunk));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4InstanceMBIntersector4Chunk));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector4HybridMoeller));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector4HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridMBIntersector4HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector4HybridPluecker));
-
- /* select intersectors8 */
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector8Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector8HybridMB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust8Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust8HybridMB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4Intersector8HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4Intersector8HybridMoellerNoFilter));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iIntersector8HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vIntersector8HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iIntersector8HybridPluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector8HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector8HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector8HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector8HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector8HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector8HybridMoellerNoFilter));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector8HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector8HybridPluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector8HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector8HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector8HybridPluecker));
-
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1Intersector8));
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1MBIntersector8));
-
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4VirtualIntersector8Chunk));
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4VirtualMBIntersector8Chunk));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4InstanceIntersector8Chunk));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4InstanceMBIntersector8Chunk));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector8HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4GridMBIntersector8HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector8HybridPluecker));
-
- /* select intersectors16 */
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4OBBVirtualCurveIntersector16Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4OBBVirtualCurveIntersector16HybridMB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust16Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust16HybridMB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4Intersector16HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4Intersector16HybridMoellerNoFilter));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4iIntersector16HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4vIntersector16HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4iIntersector16HybridPluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4vMBIntersector16HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4iMBIntersector16HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4vMBIntersector16HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4iMBIntersector16HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersector16HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersector16HybridMoellerNoFilter));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4iIntersector16HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersector16HybridPluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4iIntersector16HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4iMBIntersector16HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4iMBIntersector16HybridPluecker));
-
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4SubdivPatch1Intersector16));
- IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4SubdivPatch1MBIntersector16));
-
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4VirtualIntersector16Chunk));
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4VirtualMBIntersector16Chunk));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4InstanceIntersector16Chunk));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4InstanceMBIntersector16Chunk));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4GridIntersector16HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4GridMBIntersector16HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4GridIntersector16HybridPluecker));
-
- /* select stream intersectors */
- SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4IntersectorStreamPacketFallback);
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4IntersectorStreamMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4IntersectorStreamMoellerNoFilter));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4iIntersectorStreamMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4vIntersectorStreamPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4iIntersectorStreamPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersectorStreamMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersectorStreamMoellerNoFilter));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4iIntersectorStreamMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersectorStreamPluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4iIntersectorStreamPluecker));
-
- IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4VirtualIntersectorStream));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4InstanceIntersectorStream));
-
-#endif
- }
-
- Accel::Intersectors BVH4Factory::BVH4OBBVirtualCurveIntersectors(BVH4* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.leafIntersector = leafIntersector;
- intersectors.intersector1 = BVH4OBBVirtualCurveIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4OBBVirtualCurveIntersector4Hybrid();
- intersectors.intersector8 = BVH4OBBVirtualCurveIntersector8Hybrid();
- intersectors.intersector16 = BVH4OBBVirtualCurveIntersector16Hybrid();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.leafIntersector = leafIntersector;
- intersectors.intersector1 = BVH4OBBVirtualCurveIntersectorRobust1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4OBBVirtualCurveIntersectorRobust4Hybrid();
- intersectors.intersector8 = BVH4OBBVirtualCurveIntersectorRobust8Hybrid();
- intersectors.intersector16 = BVH4OBBVirtualCurveIntersectorRobust16Hybrid();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- default: assert(false);
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH4Factory::BVH4OBBVirtualCurveIntersectorsMB(BVH4* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.leafIntersector = leafIntersector;
- intersectors.intersector1 = BVH4OBBVirtualCurveIntersector1MB();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4OBBVirtualCurveIntersector4HybridMB();
- intersectors.intersector8 = BVH4OBBVirtualCurveIntersector8HybridMB();
- intersectors.intersector16 = BVH4OBBVirtualCurveIntersector16HybridMB();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.leafIntersector = leafIntersector;
- intersectors.intersector1 = BVH4OBBVirtualCurveIntersectorRobust1MB();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4OBBVirtualCurveIntersectorRobust4HybridMB();
- intersectors.intersector8 = BVH4OBBVirtualCurveIntersectorRobust8HybridMB();
- intersectors.intersector16 = BVH4OBBVirtualCurveIntersectorRobust16HybridMB();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- default: assert(false);
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH4Factory::BVH4Triangle4Intersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- assert(ivariant == IntersectVariant::FAST);
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Triangle4Intersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4_filter = BVH4Triangle4Intersector4HybridMoeller();
- intersectors.intersector4_nofilter = BVH4Triangle4Intersector4HybridMoellerNoFilter();
- intersectors.intersector8_filter = BVH4Triangle4Intersector8HybridMoeller();
- intersectors.intersector8_nofilter = BVH4Triangle4Intersector8HybridMoellerNoFilter();
- intersectors.intersector16_filter = BVH4Triangle4Intersector16HybridMoeller();
- intersectors.intersector16_nofilter = BVH4Triangle4Intersector16HybridMoellerNoFilter();
- intersectors.intersectorN_filter = BVH4Triangle4IntersectorStreamMoeller();
- intersectors.intersectorN_nofilter = BVH4Triangle4IntersectorStreamMoellerNoFilter();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4Triangle4vIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- assert(ivariant == IntersectVariant::ROBUST);
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Triangle4vIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Triangle4vIntersector4HybridPluecker();
- intersectors.intersector8 = BVH4Triangle4vIntersector8HybridPluecker();
- intersectors.intersector16 = BVH4Triangle4vIntersector16HybridPluecker();
- intersectors.intersectorN = BVH4Triangle4vIntersectorStreamPluecker();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4Triangle4iIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Triangle4iIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Triangle4iIntersector4HybridMoeller();
- intersectors.intersector8 = BVH4Triangle4iIntersector8HybridMoeller();
- intersectors.intersector16 = BVH4Triangle4iIntersector16HybridMoeller();
- intersectors.intersectorN = BVH4Triangle4iIntersectorStreamMoeller();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Triangle4iIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Triangle4iIntersector4HybridPluecker();
- intersectors.intersector8 = BVH4Triangle4iIntersector8HybridPluecker();
- intersectors.intersector16 = BVH4Triangle4iIntersector16HybridPluecker();
- intersectors.intersectorN = BVH4Triangle4iIntersectorStreamPluecker();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH4Factory::BVH4Triangle4vMBIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Triangle4vMBIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Triangle4vMBIntersector4HybridMoeller();
- intersectors.intersector8 = BVH4Triangle4vMBIntersector8HybridMoeller();
- intersectors.intersector16 = BVH4Triangle4vMBIntersector16HybridMoeller();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Triangle4vMBIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Triangle4vMBIntersector4HybridPluecker();
- intersectors.intersector8 = BVH4Triangle4vMBIntersector8HybridPluecker();
- intersectors.intersector16 = BVH4Triangle4vMBIntersector16HybridPluecker();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH4Factory::BVH4Triangle4iMBIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Triangle4iMBIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Triangle4iMBIntersector4HybridMoeller();
- intersectors.intersector8 = BVH4Triangle4iMBIntersector8HybridMoeller();
- intersectors.intersector16 = BVH4Triangle4iMBIntersector16HybridMoeller();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Triangle4iMBIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Triangle4iMBIntersector4HybridPluecker();
- intersectors.intersector8 = BVH4Triangle4iMBIntersector8HybridPluecker();
- intersectors.intersector16 = BVH4Triangle4iMBIntersector16HybridPluecker();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH4Factory::BVH4Quad4vIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Quad4vIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4_filter = BVH4Quad4vIntersector4HybridMoeller();
- intersectors.intersector4_nofilter = BVH4Quad4vIntersector4HybridMoellerNoFilter();
- intersectors.intersector8_filter = BVH4Quad4vIntersector8HybridMoeller();
- intersectors.intersector8_nofilter = BVH4Quad4vIntersector8HybridMoellerNoFilter();
- intersectors.intersector16_filter = BVH4Quad4vIntersector16HybridMoeller();
- intersectors.intersector16_nofilter = BVH4Quad4vIntersector16HybridMoellerNoFilter();
- intersectors.intersectorN_filter = BVH4Quad4vIntersectorStreamMoeller();
- intersectors.intersectorN_nofilter = BVH4Quad4vIntersectorStreamMoellerNoFilter();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Quad4vIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Quad4vIntersector4HybridPluecker();
- intersectors.intersector8 = BVH4Quad4vIntersector8HybridPluecker();
- intersectors.intersector16 = BVH4Quad4vIntersector16HybridPluecker();
- intersectors.intersectorN = BVH4Quad4vIntersectorStreamPluecker();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH4Factory::BVH4Quad4iIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Quad4iIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Quad4iIntersector4HybridMoeller();
- intersectors.intersector8 = BVH4Quad4iIntersector8HybridMoeller();
- intersectors.intersector16= BVH4Quad4iIntersector16HybridMoeller();
- intersectors.intersectorN = BVH4Quad4iIntersectorStreamMoeller();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Quad4iIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Quad4iIntersector4HybridPluecker();
- intersectors.intersector8 = BVH4Quad4iIntersector8HybridPluecker();
- intersectors.intersector16= BVH4Quad4iIntersector16HybridPluecker();
- intersectors.intersectorN = BVH4Quad4iIntersectorStreamPluecker();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH4Factory::BVH4Quad4iMBIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Quad4iMBIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Quad4iMBIntersector4HybridMoeller();
- intersectors.intersector8 = BVH4Quad4iMBIntersector8HybridMoeller();
- intersectors.intersector16= BVH4Quad4iMBIntersector16HybridMoeller();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4Quad4iMBIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4Quad4iMBIntersector4HybridPluecker();
- intersectors.intersector8 = BVH4Quad4iMBIntersector8HybridPluecker();
- intersectors.intersector16= BVH4Quad4iMBIntersector16HybridPluecker();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH4Factory::QBVH4Triangle4iIntersectors(BVH4* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = QBVH4Triangle4iIntersector1Pluecker();
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::QBVH4Quad4iIntersectors(BVH4* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = QBVH4Quad4iIntersector1Pluecker();
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4UserGeometryIntersectors(BVH4* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4VirtualIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4VirtualIntersector4Chunk();
- intersectors.intersector8 = BVH4VirtualIntersector8Chunk();
- intersectors.intersector16 = BVH4VirtualIntersector16Chunk();
- intersectors.intersectorN = BVH4VirtualIntersectorStream();
-#endif
- intersectors.collider = BVH4ColliderUserGeom();
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4UserGeometryMBIntersectors(BVH4* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4VirtualMBIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4VirtualMBIntersector4Chunk();
- intersectors.intersector8 = BVH4VirtualMBIntersector8Chunk();
- intersectors.intersector16 = BVH4VirtualMBIntersector16Chunk();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4InstanceIntersectors(BVH4* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4InstanceIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4InstanceIntersector4Chunk();
- intersectors.intersector8 = BVH4InstanceIntersector8Chunk();
- intersectors.intersector16 = BVH4InstanceIntersector16Chunk();
- intersectors.intersectorN = BVH4InstanceIntersectorStream();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4InstanceMBIntersectors(BVH4* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4InstanceMBIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4InstanceMBIntersector4Chunk();
- intersectors.intersector8 = BVH4InstanceMBIntersector8Chunk();
- intersectors.intersector16 = BVH4InstanceMBIntersector16Chunk();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4SubdivPatch1Intersectors(BVH4* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4SubdivPatch1Intersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4SubdivPatch1Intersector4();
- intersectors.intersector8 = BVH4SubdivPatch1Intersector8();
- intersectors.intersector16 = BVH4SubdivPatch1Intersector16();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4SubdivPatch1MBIntersectors(BVH4* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4SubdivPatch1MBIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4SubdivPatch1MBIntersector4();
- intersectors.intersector8 = BVH4SubdivPatch1MBIntersector8();
- intersectors.intersector16 = BVH4SubdivPatch1MBIntersector16();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
-
- Accel* BVH4Factory::BVH4OBBVirtualCurve4i(Scene* scene, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Curve4i::type,scene);
- Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectors(accel,VirtualCurveIntersector4i(),ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->hair_builder == "default" ) builder = BVH4Curve4iBuilder_OBB_New(accel,scene,0);
- else if (scene->device->hair_builder == "sah" ) builder = BVH4Curve4iBuilder_OBB_New(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve4i>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
-#if defined(EMBREE_TARGET_SIMD8)
- Accel* BVH4Factory::BVH4OBBVirtualCurve8i(Scene* scene, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Curve8i::type,scene);
- Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectors(accel,VirtualCurveIntersector8i(),ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->hair_builder == "default" ) builder = BVH4Curve8iBuilder_OBB_New(accel,scene,0);
- else if (scene->device->hair_builder == "sah" ) builder = BVH4Curve8iBuilder_OBB_New(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve8i>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-#endif
-
- Accel* BVH4Factory::BVH4OBBVirtualCurve4v(Scene* scene, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Curve4v::type,scene);
- Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectors(accel,VirtualCurveIntersector4v(),ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->hair_builder == "default" ) builder = BVH4Curve4vBuilder_OBB_New(accel,scene,0);
- else if (scene->device->hair_builder == "sah" ) builder = BVH4Curve4vBuilder_OBB_New(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve4v>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4OBBVirtualCurve4iMB(Scene* scene, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Curve4iMB::type,scene);
- Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectorsMB(accel,VirtualCurveIntersector4iMB(),ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->hair_builder == "default" ) builder = BVH4OBBCurve4iMBBuilder_OBB(accel,scene,0);
- else if (scene->device->hair_builder == "sah" ) builder = BVH4OBBCurve4iMBBuilder_OBB(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve4iMB>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
-#if defined(EMBREE_TARGET_SIMD8)
- Accel* BVH4Factory::BVH4OBBVirtualCurve8iMB(Scene* scene, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Curve8iMB::type,scene);
- Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectorsMB(accel,VirtualCurveIntersector8iMB(), ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->hair_builder == "default" ) builder = BVH4OBBCurve8iMBBuilder_OBB(accel,scene,0);
- else if (scene->device->hair_builder == "sah" ) builder = BVH4OBBCurve8iMBBuilder_OBB(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve8iMB>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-#endif
-
- Accel* BVH4Factory::BVH4Triangle4(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Triangle4::type,scene);
-
- Accel::Intersectors intersectors;
- if (scene->device->tri_traverser == "default") intersectors = BVH4Triangle4Intersectors(accel,ivariant);
- else if (scene->device->tri_traverser == "fast" ) intersectors = BVH4Triangle4Intersectors(accel,IntersectVariant::FAST);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser+" for BVH4<Triangle4>");
-
- Builder* builder = nullptr;
- if (scene->device->tri_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4Triangle4SceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelTriangle4MeshSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: builder = BVH4Triangle4SceneBuilderFastSpatialSAH(accel,scene,0); break;
- }
- }
- else if (scene->device->tri_builder == "sah" ) builder = BVH4Triangle4SceneBuilderSAH(accel,scene,0);
- else if (scene->device->tri_builder == "sah_fast_spatial" ) builder = BVH4Triangle4SceneBuilderFastSpatialSAH(accel,scene,0);
- else if (scene->device->tri_builder == "sah_presplit") builder = BVH4Triangle4SceneBuilderSAH(accel,scene,MODE_HIGH_QUALITY);
- else if (scene->device->tri_builder == "dynamic" ) builder = BVH4BuilderTwoLevelTriangle4MeshSAH(accel,scene,false);
- else if (scene->device->tri_builder == "morton" ) builder = BVH4BuilderTwoLevelTriangle4MeshSAH(accel,scene,true);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH4<Triangle4>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4Triangle4v(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Triangle4v::type,scene);
-
- Accel::Intersectors intersectors;
- if (scene->device->tri_traverser == "default") intersectors = BVH4Triangle4vIntersectors(accel,ivariant);
- else if (scene->device->tri_traverser == "fast" ) intersectors = BVH4Triangle4vIntersectors(accel,IntersectVariant::FAST);
- else if (scene->device->tri_traverser == "robust" ) intersectors = BVH4Triangle4vIntersectors(accel,IntersectVariant::ROBUST);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser+" for BVH4<Triangle4>");
-
- Builder* builder = nullptr;
- if (scene->device->tri_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4Triangle4vSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelTriangle4vMeshSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: builder = BVH4Triangle4vSceneBuilderFastSpatialSAH(accel,scene,0); break;
- }
- }
- else if (scene->device->tri_builder == "sah" ) builder = BVH4Triangle4vSceneBuilderSAH(accel,scene,0);
- else if (scene->device->tri_builder == "sah_fast_spatial" ) builder = BVH4Triangle4vSceneBuilderFastSpatialSAH(accel,scene,0);
- else if (scene->device->tri_builder == "sah_presplit") builder = BVH4Triangle4vSceneBuilderSAH(accel,scene,MODE_HIGH_QUALITY);
- else if (scene->device->tri_builder == "dynamic" ) builder = BVH4BuilderTwoLevelTriangle4vMeshSAH(accel,scene,false);
- else if (scene->device->tri_builder == "morton" ) builder = BVH4BuilderTwoLevelTriangle4vMeshSAH(accel,scene,true);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH4<Triangle4v>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4Triangle4i(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Triangle4i::type,scene);
-
- Accel::Intersectors intersectors;
- if (scene->device->tri_traverser == "default") intersectors = BVH4Triangle4iIntersectors(accel,ivariant);
- else if (scene->device->tri_traverser == "fast" ) intersectors = BVH4Triangle4iIntersectors(accel,IntersectVariant::FAST);
- else if (scene->device->tri_traverser == "robust" ) intersectors = BVH4Triangle4iIntersectors(accel,IntersectVariant::ROBUST);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser+" for BVH4<Triangle4i>");
-
- Builder* builder = nullptr;
- if (scene->device->tri_builder == "default" ) {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4Triangle4iSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelTriangle4iMeshSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: builder = BVH4Triangle4iSceneBuilderFastSpatialSAH(accel,scene,0); break;
- }
- }
- else if (scene->device->tri_builder == "sah" ) builder = BVH4Triangle4iSceneBuilderSAH(accel,scene,0);
- else if (scene->device->tri_builder == "sah_fast_spatial" ) builder = BVH4Triangle4iSceneBuilderFastSpatialSAH(accel,scene,0);
- else if (scene->device->tri_builder == "sah_presplit") builder = BVH4Triangle4iSceneBuilderSAH(accel,scene,MODE_HIGH_QUALITY);
- else if (scene->device->tri_builder == "dynamic" ) builder = BVH4BuilderTwoLevelTriangle4iMeshSAH(accel,scene,false);
- else if (scene->device->tri_builder == "morton" ) builder = BVH4BuilderTwoLevelTriangle4iMeshSAH(accel,scene,true);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH4<Triangle4i>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4Triangle4iMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Triangle4i::type,scene);
-
- Accel::Intersectors intersectors;
- if (scene->device->tri_traverser_mb == "default") intersectors = BVH4Triangle4iMBIntersectors(accel,ivariant);
- else if (scene->device->tri_traverser_mb == "fast" ) intersectors = BVH4Triangle4iMBIntersectors(accel,IntersectVariant::FAST);
- else if (scene->device->tri_traverser_mb == "robust" ) intersectors = BVH4Triangle4iMBIntersectors(accel,IntersectVariant::ROBUST);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser_mb+" for BVH4<Triangle4iMB>");
-
- Builder* builder = nullptr;
- if (scene->device->tri_builder_mb == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4Triangle4iMBSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->tri_builder_mb == "internal_time_splits") builder = BVH4Triangle4iMBSceneBuilderSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder_mb+" for BVH4<Triangle4iMB>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4Triangle4vMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Triangle4vMB::type,scene);
-
- Accel::Intersectors intersectors;
- if (scene->device->tri_traverser_mb == "default") intersectors = BVH4Triangle4vMBIntersectors(accel,ivariant);
- else if (scene->device->tri_traverser_mb == "fast" ) intersectors = BVH4Triangle4vMBIntersectors(accel,IntersectVariant::FAST);
- else if (scene->device->tri_traverser_mb == "robust" ) intersectors = BVH4Triangle4vMBIntersectors(accel,IntersectVariant::ROBUST);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser_mb+" for BVH4<Triangle4vMB>");
-
- Builder* builder = nullptr;
- if (scene->device->tri_builder_mb == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4Triangle4vMBSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->tri_builder_mb == "internal_time_splits") builder = BVH4Triangle4vMBSceneBuilderSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder_mb+" for BVH4<Triangle4vMB>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4Quad4v(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Quad4v::type,scene);
- Accel::Intersectors intersectors = BVH4Quad4vIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->quad_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4Quad4vSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelQuadMeshSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: builder = BVH4Quad4vSceneBuilderFastSpatialSAH(accel,scene,0); break;
- }
- }
- else if (scene->device->quad_builder == "sah" ) builder = BVH4Quad4vSceneBuilderSAH(accel,scene,0);
- else if (scene->device->quad_builder == "sah_fast_spatial" ) builder = BVH4Quad4vSceneBuilderFastSpatialSAH(accel,scene,0);
- else if (scene->device->quad_builder == "dynamic" ) builder = BVH4BuilderTwoLevelQuadMeshSAH(accel,scene,false);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for BVH4<Quad4v>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4Quad4i(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Quad4i::type,scene);
- Accel::Intersectors intersectors = BVH4Quad4iIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->quad_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4Quad4iSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
- case BuildVariant::HIGH_QUALITY: assert(false); break; // FIXME: implement
- }
- }
- else if (scene->device->quad_builder == "sah") builder = BVH4Quad4iSceneBuilderSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for BVH4<Quad4i>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4Quad4iMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(Quad4i::type,scene);
- Accel::Intersectors intersectors = BVH4Quad4iMBIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->quad_builder_mb == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4Quad4iMBSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->quad_builder_mb == "sah") builder = BVH4Quad4iMBSceneBuilderSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder_mb+" for BVH4<Quad4iMB>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4QuantizedQuad4i(Scene* scene)
- {
- BVH4* accel = new BVH4(Quad4i::type,scene);
- Builder* builder = BVH4QuantizedQuad4iSceneBuilderSAH(accel,scene,0);
- Accel::Intersectors intersectors = QBVH4Quad4iIntersectors(accel);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4QuantizedTriangle4i(Scene* scene)
- {
- BVH4* accel = new BVH4(Triangle4i::type,scene);
- Builder* builder = BVH4QuantizedTriangle4iSceneBuilderSAH(accel,scene,0);
- Accel::Intersectors intersectors = QBVH4Triangle4iIntersectors(accel);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4SubdivPatch1(Scene* scene)
- {
- BVH4* accel = new BVH4(SubdivPatch1::type,scene);
- Accel::Intersectors intersectors = BVH4SubdivPatch1Intersectors(accel);
- Builder* builder = BVH4SubdivPatch1BuilderSAH(accel,scene,0);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4SubdivPatch1MB(Scene* scene)
- {
- BVH4* accel = new BVH4(SubdivPatch1::type,scene);
- Accel::Intersectors intersectors = BVH4SubdivPatch1MBIntersectors(accel);
- Builder* builder = BVH4SubdivPatch1MBBuilderSAH(accel,scene,0);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4UserGeometry(Scene* scene, BuildVariant bvariant)
- {
- BVH4* accel = new BVH4(Object::type,scene);
- Accel::Intersectors intersectors = BVH4UserGeometryIntersectors(accel);
-
- Builder* builder = nullptr;
- if (scene->device->object_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4VirtualSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelVirtualSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->object_builder == "sah") builder = BVH4VirtualSceneBuilderSAH(accel,scene,0);
- else if (scene->device->object_builder == "dynamic") builder = BVH4BuilderTwoLevelVirtualSAH(accel,scene,false);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH4<Object>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4UserGeometryMB(Scene* scene)
- {
- BVH4* accel = new BVH4(Object::type,scene);
- Accel::Intersectors intersectors = BVH4UserGeometryMBIntersectors(accel);
- Builder* builder = BVH4VirtualMBSceneBuilderSAH(accel,scene,0);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4Instance(Scene* scene, bool isExpensive, BuildVariant bvariant)
- {
- BVH4* accel = new BVH4(InstancePrimitive::type,scene);
- Accel::Intersectors intersectors = BVH4InstanceIntersectors(accel);
- auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE_CHEAP;
- // Builder* builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype);
-
- Builder* builder = nullptr;
- if (scene->device->object_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype); break;
- case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelInstanceSAH(accel,scene,gtype,false); break;
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->object_builder == "sah") builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype);
- else if (scene->device->object_builder == "dynamic") builder = BVH4BuilderTwoLevelInstanceSAH(accel,scene,gtype,false);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH4<Object>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4InstanceMB(Scene* scene, bool isExpensive)
- {
- BVH4* accel = new BVH4(InstancePrimitive::type,scene);
- Accel::Intersectors intersectors = BVH4InstanceMBIntersectors(accel);
- auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE_CHEAP;
- Builder* builder = BVH4InstanceMBSceneBuilderSAH(accel,scene,gtype);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel::Intersectors BVH4Factory::BVH4GridIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- if (ivariant == IntersectVariant::FAST)
- {
- intersectors.intersector1 = BVH4GridIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4GridIntersector4HybridMoeller();
- intersectors.intersector8 = BVH4GridIntersector8HybridMoeller();
- intersectors.intersector16 = BVH4GridIntersector16HybridMoeller();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- }
- else /* if (ivariant == IntersectVariant::ROBUST) */
- {
- intersectors.intersector1 = BVH4GridIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4GridIntersector4HybridPluecker();
- intersectors.intersector8 = BVH4GridIntersector8HybridPluecker();
- intersectors.intersector16 = BVH4GridIntersector16HybridPluecker();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- }
- return intersectors;
- }
-
- Accel::Intersectors BVH4Factory::BVH4GridMBIntersectors(BVH4* bvh, IntersectVariant ivariant)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH4GridMBIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH4GridMBIntersector4HybridMoeller();
- intersectors.intersector8 = BVH4GridMBIntersector8HybridMoeller();
- intersectors.intersector16 = BVH4GridMBIntersector16HybridMoeller();
- intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
-
- Accel* BVH4Factory::BVH4Grid(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(SubGridQBVH4::type,scene);
- Accel::Intersectors intersectors = BVH4GridIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->object_builder == "default") {
- builder = BVH4GridSceneBuilderSAH(accel,scene,0);
- }
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->grid_builder+" for BVH4<GridMesh>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH4Factory::BVH4GridMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH4* accel = new BVH4(SubGridQBVH4::type,scene);
- Accel::Intersectors intersectors = BVH4GridMBIntersectors(accel,ivariant);
- Builder* builder = nullptr;
- if (scene->device->object_builder == "default") {
- builder = BVH4GridMBSceneBuilderSAH(accel,scene,0);
- }
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->grid_builder+" for BVH4MB<GridMesh>");
- return new AccelInstance(accel,builder,intersectors);
- }
-
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh4_factory.h b/thirdparty/embree-aarch64/kernels/bvh/bvh4_factory.h
deleted file mode 100644
index a68227b41f..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh4_factory.h
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_factory.h"
-
-namespace embree
-{
- /*! BVH4 instantiations */
- class BVH4Factory : public BVHFactory
- {
- public:
- BVH4Factory(int bfeatures, int ifeatures);
-
- public:
- Accel* BVH4OBBVirtualCurve4i(Scene* scene, IntersectVariant ivariant);
- Accel* BVH4OBBVirtualCurve4v(Scene* scene, IntersectVariant ivariant);
- Accel* BVH4OBBVirtualCurve8i(Scene* scene, IntersectVariant ivariant);
- Accel* BVH4OBBVirtualCurve4iMB(Scene* scene, IntersectVariant ivariant);
- Accel* BVH4OBBVirtualCurve8iMB(Scene* scene, IntersectVariant ivariant);
- DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector4i);
- DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8i);
- DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector4v);
- DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8v);
- DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector4iMB);
- DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8iMB);
-
- Accel* BVH4Triangle4 (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH4Triangle4v (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::ROBUST);
- Accel* BVH4Triangle4i (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH4Triangle4vMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH4Triangle4iMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
-
- Accel* BVH4Quad4v (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH4Quad4i (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH4Quad4iMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
-
- Accel* BVH4QuantizedTriangle4i(Scene* scene);
- Accel* BVH4QuantizedQuad4i(Scene* scene);
-
- Accel* BVH4SubdivPatch1(Scene* scene);
- Accel* BVH4SubdivPatch1MB(Scene* scene);
-
- Accel* BVH4UserGeometry(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC);
- Accel* BVH4UserGeometryMB(Scene* scene);
-
- Accel* BVH4Instance(Scene* scene, bool isExpensive, BuildVariant bvariant = BuildVariant::STATIC);
- Accel* BVH4InstanceMB(Scene* scene, bool isExpensive);
-
- Accel* BVH4Grid(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH4GridMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
-
- private:
- void selectBuilders(int features);
- void selectIntersectors(int features);
-
- private:
- Accel::Intersectors BVH4OBBVirtualCurveIntersectors(BVH4* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant);
- Accel::Intersectors BVH4OBBVirtualCurveIntersectorsMB(BVH4* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant);
-
- Accel::Intersectors BVH4Triangle4Intersectors(BVH4* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH4Triangle4vIntersectors(BVH4* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH4Triangle4iIntersectors(BVH4* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH4Triangle4iMBIntersectors(BVH4* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH4Triangle4vMBIntersectors(BVH4* bvh, IntersectVariant ivariant);
-
- Accel::Intersectors BVH4Quad4vIntersectors(BVH4* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH4Quad4iIntersectors(BVH4* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH4Quad4iMBIntersectors(BVH4* bvh, IntersectVariant ivariant);
-
- Accel::Intersectors QBVH4Quad4iIntersectors(BVH4* bvh);
- Accel::Intersectors QBVH4Triangle4iIntersectors(BVH4* bvh);
-
- Accel::Intersectors BVH4UserGeometryIntersectors(BVH4* bvh);
- Accel::Intersectors BVH4UserGeometryMBIntersectors(BVH4* bvh);
-
- Accel::Intersectors BVH4InstanceIntersectors(BVH4* bvh);
- Accel::Intersectors BVH4InstanceMBIntersectors(BVH4* bvh);
-
- Accel::Intersectors BVH4SubdivPatch1Intersectors(BVH4* bvh);
- Accel::Intersectors BVH4SubdivPatch1MBIntersectors(BVH4* bvh);
-
- Accel::Intersectors BVH4GridIntersectors(BVH4* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH4GridMBIntersectors(BVH4* bvh, IntersectVariant ivariant);
-
- private:
-
- DEFINE_SYMBOL2(Accel::Collider,BVH4ColliderUserGeom);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersector1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersector1MB);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersectorRobust1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersectorRobust1MB);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4Intersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vIntersector1Pluecker);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vMBIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iMBIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vMBIntersector1Pluecker);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iMBIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4vIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4iIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4vIntersector1Pluecker);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4iIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4iMBIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4iMBIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,QBVH4Triangle4iIntersector1Pluecker);
- DEFINE_SYMBOL2(Accel::Intersector1,QBVH4Quad4iIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4SubdivPatch1Intersector1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4SubdivPatch1MBIntersector1);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4VirtualIntersector1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4VirtualMBIntersector1);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4InstanceIntersector1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4InstanceMBIntersector1);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4GridIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4GridMBIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH4GridIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersector4Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersector4HybridMB);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersectorRobust4Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersectorRobust4HybridMB);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4Intersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4Intersector4HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vIntersector4HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vMBIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iMBIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vMBIntersector4HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iMBIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4iIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4iIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4iMBIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4iMBIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4SubdivPatch1Intersector4);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4SubdivPatch1MBIntersector4);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4VirtualIntersector4Chunk);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4VirtualMBIntersector4Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4InstanceIntersector4Chunk);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4InstanceMBIntersector4Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4GridIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4GridMBIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH4GridIntersector4HybridPluecker);
-
- // ==============
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersector8Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersector8HybridMB);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersectorRobust8Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersectorRobust8HybridMB);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4Intersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4Intersector8HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vIntersector8HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vMBIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iMBIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vMBIntersector8HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iMBIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4iIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4iIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4iMBIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4iMBIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4SubdivPatch1Intersector8);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4SubdivPatch1MBIntersector8);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4VirtualIntersector8Chunk);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4VirtualMBIntersector8Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4InstanceIntersector8Chunk);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4InstanceMBIntersector8Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4GridIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4GridMBIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH4GridIntersector8HybridPluecker);
-
- // ==============
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersector16Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersector16HybridMB);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersectorRobust16Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersectorRobust16HybridMB);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4Intersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4Intersector16HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vIntersector16HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vMBIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iMBIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vMBIntersector16HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iMBIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4iIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4iIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4iMBIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4iMBIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4SubdivPatch1Intersector16);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4SubdivPatch1MBIntersector16);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4VirtualIntersector16Chunk);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4VirtualMBIntersector16Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4InstanceIntersector16Chunk);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4InstanceMBIntersector16Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4GridIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4GridMBIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH4GridIntersector16HybridPluecker);
-
- // ==============
-
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4IntersectorStreamPacketFallback);
-
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4IntersectorStreamMoeller);
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4IntersectorStreamMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4iIntersectorStreamMoeller);
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4vIntersectorStreamPluecker);
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4iIntersectorStreamPluecker);
-
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4vIntersectorStreamMoeller);
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4vIntersectorStreamMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4iIntersectorStreamMoeller);
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4vIntersectorStreamPluecker);
- DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4iIntersectorStreamPluecker);
-
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH4VirtualIntersectorStream);
-
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH4InstanceIntersectorStream);
-
- // SAH scene builders
- private:
- DEFINE_ISA_FUNCTION(Builder*,BVH4Curve4vBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Curve4iBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4OBBCurve4iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Curve8iBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4OBBCurve8iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4vMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4QuantizedTriangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH4Quad4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Quad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Quad4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4QuantizedQuad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH4SubdivPatch1BuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4SubdivPatch1MBBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH4VirtualSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4VirtualMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH4InstanceSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
- DEFINE_ISA_FUNCTION(Builder*,BVH4InstanceMBSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH4GridSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4GridMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- // spatial scene builder
- private:
- DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4SceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4iSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH4Quad4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
-
- // twolevel scene builders
- private:
- DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4MeshSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4vMeshSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool);
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh8_factory.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh8_factory.cpp
deleted file mode 100644
index 9fe057c392..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh8_factory.cpp
+++ /dev/null
@@ -1,1165 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "../common/isa.h" // to define EMBREE_TARGET_SIMD8
-
-#if defined (EMBREE_TARGET_SIMD8)
-
-#include "bvh8_factory.h"
-#include "../bvh/bvh.h"
-
-#include "../geometry/curveNv.h"
-#include "../geometry/curveNi.h"
-#include "../geometry/curveNi_mb.h"
-#include "../geometry/linei.h"
-#include "../geometry/triangle.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/trianglev_mb.h"
-#include "../geometry/trianglei.h"
-#include "../geometry/quadv.h"
-#include "../geometry/quadi.h"
-#include "../geometry/subdivpatch1.h"
-#include "../geometry/object.h"
-#include "../geometry/instance.h"
-#include "../geometry/subgrid.h"
-#include "../common/accelinstance.h"
-
-namespace embree
-{
- DECLARE_SYMBOL2(Accel::Collider,BVH8ColliderUserGeom);
-
- DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8v,void);
- DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8iMB,void);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersector1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersector1MB);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersectorRobust1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersectorRobust1MB);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4Intersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vIntersector1Pluecker);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vIntersector1Woop);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vMBIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iMBIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vMBIntersector1Pluecker);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iMBIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4vIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4iIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4vIntersector1Pluecker);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4iIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4iMBIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4iMBIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,QBVH8Triangle4iIntersector1Pluecker);
- DECLARE_SYMBOL2(Accel::Intersector1,QBVH8Triangle4Intersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,QBVH8Quad4iIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8VirtualIntersector1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8VirtualMBIntersector1);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8InstanceIntersector1);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8InstanceMBIntersector1);
-
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8GridIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8GridMBIntersector1Moeller);
- DECLARE_SYMBOL2(Accel::Intersector1,BVH8GridIntersector1Pluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersector4Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersector4HybridMB);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersectorRobust4Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersectorRobust4HybridMB);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4Intersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4Intersector4HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vIntersector4HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vMBIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iMBIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vMBIntersector4HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iMBIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4iIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4iIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4iMBIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4iMBIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8VirtualIntersector4Chunk);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8VirtualMBIntersector4Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8InstanceIntersector4Chunk);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8InstanceMBIntersector4Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8GridIntersector4HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector4,BVH8GridIntersector4HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersector8Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersector8HybridMB);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersectorRobust8Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersectorRobust8HybridMB);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4Intersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4Intersector8HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vIntersector8HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vMBIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iMBIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vMBIntersector8HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iMBIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4iIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4iIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4iMBIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4iMBIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8VirtualIntersector8Chunk);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8VirtualMBIntersector8Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8InstanceIntersector8Chunk);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8InstanceMBIntersector8Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8GridIntersector8HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector8,BVH8GridIntersector8HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersector16Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersector16HybridMB);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersectorRobust16Hybrid);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersectorRobust16HybridMB);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4Intersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4Intersector16HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vIntersector16HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vMBIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iMBIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vMBIntersector16HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iMBIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4iIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridPluecker);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4iIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4iMBIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4iMBIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8VirtualIntersector16Chunk);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8VirtualMBIntersector16Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8InstanceIntersector16Chunk);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8InstanceMBIntersector16Chunk);
-
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8GridIntersector16HybridMoeller);
- DECLARE_SYMBOL2(Accel::Intersector16,BVH8GridIntersector16HybridPluecker);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8IntersectorStreamPacketFallback);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoeller);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamMoeller);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4vIntersectorStreamPluecker);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamPluecker);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamMoeller);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamMoellerNoFilter);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4iIntersectorStreamMoeller);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamPluecker);
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4iIntersectorStreamPluecker);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8VirtualIntersectorStream);
-
- DECLARE_SYMBOL2(Accel::IntersectorN,BVH8InstanceIntersectorStream);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH8Curve8vBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8OBBCurve8iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8QuantizedTriangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8QuantizedTriangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8QuantizedQuad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
- DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMBSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4SceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8GridSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8GridMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4MeshSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4vMeshSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool);
- DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool);
-
- BVH8Factory::BVH8Factory(int bfeatures, int ifeatures)
- {
- SELECT_SYMBOL_INIT_AVX(ifeatures,BVH8ColliderUserGeom);
-
- selectBuilders(bfeatures);
- selectIntersectors(ifeatures);
- }
-
- void BVH8Factory::selectBuilders(int features)
- {
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH8Curve8vBuilder_OBB_New));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH8OBBCurve8iMBBuilder_OBB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4SceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4vSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4iSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4iMBSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4vMBSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedTriangle4iSceneBuilderSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedTriangle4SceneBuilderSAH));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Quad4vSceneBuilderSAH));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Quad4iSceneBuilderSAH));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Quad4iMBSceneBuilderSAH));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedQuad4iSceneBuilderSAH));
-
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX(features,BVH8VirtualSceneBuilderSAH));
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX(features,BVH8VirtualMBSceneBuilderSAH));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX(features,BVH8InstanceSceneBuilderSAH));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX(features,BVH8InstanceMBSceneBuilderSAH));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX(features,BVH8GridSceneBuilderSAH));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX(features,BVH8GridMBSceneBuilderSAH));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4SceneBuilderFastSpatialSAH));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4vSceneBuilderFastSpatialSAH));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Quad4vSceneBuilderFastSpatialSAH));
-
- IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelTriangle4MeshSAH));
- IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelTriangle4vMeshSAH));
- IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelTriangle4iMeshSAH));
- IF_ENABLED_QUADS (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelQuadMeshSAH));
- IF_ENABLED_USER (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelVirtualSAH));
- IF_ENABLED_INSTANCE (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelInstanceSAH));
- }
-
- void BVH8Factory::selectIntersectors(int features)
- {
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8v));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8iMB));
-
- /* select intersectors1 */
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersector1));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersector1MB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust1));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust1MB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4Intersector1Moeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersector1Moeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vIntersector1Pluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersector1Pluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vIntersector1Woop));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vMBIntersector1Moeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iMBIntersector1Moeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vMBIntersector1Pluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iMBIntersector1Pluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector1Moeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersector1Moeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector1Pluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersector1Pluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iMBIntersector1Moeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iMBIntersector1Pluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,QBVH8Triangle4iIntersector1Pluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,QBVH8Triangle4Intersector1Moeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,QBVH8Quad4iIntersector1Pluecker));
-
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8VirtualIntersector1));
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8VirtualMBIntersector1));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8InstanceIntersector1));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8InstanceMBIntersector1));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector1Moeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridMBIntersector1Moeller))
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector1Pluecker));
-
-#if defined (EMBREE_RAY_PACKETS)
-
- /* select intersectors4 */
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersector4Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersector4HybridMB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust4Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust4HybridMB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4Intersector4HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4Intersector4HybridMoellerNoFilter));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iIntersector4HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vIntersector4HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iIntersector4HybridPluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vMBIntersector4HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iMBIntersector4HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vMBIntersector4HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iMBIntersector4HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector4HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector4HybridMoellerNoFilter));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4iIntersector4HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector4HybridPluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4iIntersector4HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector4HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector4HybridPluecker));
-
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8VirtualIntersector4Chunk));
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8VirtualMBIntersector4Chunk));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8InstanceIntersector4Chunk));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8InstanceMBIntersector4Chunk));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector4HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector4HybridPluecker));
-
- /* select intersectors8 */
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersector8Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersector8HybridMB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust8Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust8HybridMB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4Intersector8HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4Intersector8HybridMoellerNoFilter));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iIntersector8HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vIntersector8HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iIntersector8HybridPluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vMBIntersector8HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iMBIntersector8HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vMBIntersector8HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iMBIntersector8HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector8HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector8HybridMoellerNoFilter));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4iIntersector8HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector8HybridPluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4iIntersector8HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector8HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector8HybridPluecker));
-
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8VirtualIntersector8Chunk));
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8VirtualMBIntersector8Chunk));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8InstanceIntersector8Chunk));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8InstanceMBIntersector8Chunk));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector8HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector8HybridPluecker));
-
- /* select intersectors16 */
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersector16Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersector16HybridMB));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust16Hybrid));
- IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust16HybridMB));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4Intersector16HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4Intersector16HybridMoellerNoFilter));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersector16HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4vIntersector16HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersector16HybridPluecker));
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4vMBIntersector16HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4iMBIntersector16HybridMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4vMBIntersector16HybridPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4iMBIntersector16HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector16HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector16HybridMoellerNoFilter));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersector16HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector16HybridPluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersector16HybridPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4iMBIntersector16HybridMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4iMBIntersector16HybridPluecker));
-
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8VirtualIntersector16Chunk));
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8VirtualMBIntersector16Chunk));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8InstanceIntersector16Chunk));
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8InstanceMBIntersector16Chunk));
-
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8GridIntersector16HybridMoeller));
- IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8GridIntersector16HybridPluecker));
-
- /* select stream intersectors */
-
- SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8IntersectorStreamPacketFallback);
-
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4IntersectorStreamMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4IntersectorStreamMoellerNoFilter));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersectorStreamMoeller));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vIntersectorStreamPluecker));
- IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersectorStreamPluecker));
-
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersectorStreamMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersectorStreamMoellerNoFilter));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersectorStreamMoeller));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersectorStreamPluecker));
- IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersectorStreamPluecker));
-
- IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8VirtualIntersectorStream));
-
- IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8InstanceIntersectorStream));
-
-#endif
- }
-
- Accel::Intersectors BVH8Factory::BVH8OBBVirtualCurveIntersectors(BVH8* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.leafIntersector = leafIntersector;
- intersectors.intersector1 = BVH8OBBVirtualCurveIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8OBBVirtualCurveIntersector4Hybrid();
- intersectors.intersector8 = BVH8OBBVirtualCurveIntersector8Hybrid();
- intersectors.intersector16 = BVH8OBBVirtualCurveIntersector16Hybrid();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.leafIntersector = leafIntersector;
- intersectors.intersector1 = BVH8OBBVirtualCurveIntersectorRobust1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8OBBVirtualCurveIntersectorRobust4Hybrid();
- intersectors.intersector8 = BVH8OBBVirtualCurveIntersectorRobust8Hybrid();
- intersectors.intersector16 = BVH8OBBVirtualCurveIntersectorRobust16Hybrid();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- default: assert(false);
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH8Factory::BVH8OBBVirtualCurveIntersectorsMB(BVH8* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.leafIntersector = leafIntersector;
- intersectors.intersector1 = BVH8OBBVirtualCurveIntersector1MB();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8OBBVirtualCurveIntersector4HybridMB();
- intersectors.intersector8 = BVH8OBBVirtualCurveIntersector8HybridMB();
- intersectors.intersector16 = BVH8OBBVirtualCurveIntersector16HybridMB();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.leafIntersector = leafIntersector;
- intersectors.intersector1 = BVH8OBBVirtualCurveIntersectorRobust1MB();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8OBBVirtualCurveIntersectorRobust4HybridMB();
- intersectors.intersector8 = BVH8OBBVirtualCurveIntersectorRobust8HybridMB();
- intersectors.intersector16 = BVH8OBBVirtualCurveIntersectorRobust16HybridMB();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- default: assert(false);
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH8Factory::BVH8Triangle4Intersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- assert(ivariant == IntersectVariant::FAST);
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Triangle4Intersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4_filter = BVH8Triangle4Intersector4HybridMoeller();
- intersectors.intersector4_nofilter = BVH8Triangle4Intersector4HybridMoellerNoFilter();
- intersectors.intersector8_filter = BVH8Triangle4Intersector8HybridMoeller();
- intersectors.intersector8_nofilter = BVH8Triangle4Intersector8HybridMoellerNoFilter();
- intersectors.intersector16_filter = BVH8Triangle4Intersector16HybridMoeller();
- intersectors.intersector16_nofilter = BVH8Triangle4Intersector16HybridMoellerNoFilter();
- intersectors.intersectorN_filter = BVH8Triangle4IntersectorStreamMoeller();
- intersectors.intersectorN_nofilter = BVH8Triangle4IntersectorStreamMoellerNoFilter();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::BVH8Triangle4vIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
-#define ENABLE_WOOP_TEST 0
-#if ENABLE_WOOP_TEST == 0
- //assert(ivariant == IntersectVariant::ROBUST);
- intersectors.intersector1 = BVH8Triangle4vIntersector1Pluecker();
-#else
- intersectors.intersector1 = BVH8Triangle4vIntersector1Woop();
-#endif
-
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Triangle4vIntersector4HybridPluecker();
- intersectors.intersector8 = BVH8Triangle4vIntersector8HybridPluecker();
- intersectors.intersector16 = BVH8Triangle4vIntersector16HybridPluecker();
- intersectors.intersectorN = BVH8Triangle4vIntersectorStreamPluecker();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::BVH8Triangle4iIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Triangle4iIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Triangle4iIntersector4HybridMoeller();
- intersectors.intersector8 = BVH8Triangle4iIntersector8HybridMoeller();
- intersectors.intersector16 = BVH8Triangle4iIntersector16HybridMoeller();
- intersectors.intersectorN = BVH8Triangle4iIntersectorStreamMoeller();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Triangle4iIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Triangle4iIntersector4HybridPluecker();
- intersectors.intersector8 = BVH8Triangle4iIntersector8HybridPluecker();
- intersectors.intersector16 = BVH8Triangle4iIntersector16HybridPluecker();
- intersectors.intersectorN = BVH8Triangle4iIntersectorStreamPluecker();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH8Factory::BVH8Triangle4vMBIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Triangle4vMBIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Triangle4vMBIntersector4HybridMoeller();
- intersectors.intersector8 = BVH8Triangle4vMBIntersector8HybridMoeller();
- intersectors.intersector16 = BVH8Triangle4vMBIntersector16HybridMoeller();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Triangle4vMBIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Triangle4vMBIntersector4HybridPluecker();
- intersectors.intersector8 = BVH8Triangle4vMBIntersector8HybridPluecker();
- intersectors.intersector16 = BVH8Triangle4vMBIntersector16HybridPluecker();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH8Factory::BVH8Triangle4iMBIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Triangle4iMBIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Triangle4iMBIntersector4HybridMoeller();
- intersectors.intersector8 = BVH8Triangle4iMBIntersector8HybridMoeller();
- intersectors.intersector16 = BVH8Triangle4iMBIntersector16HybridMoeller();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Triangle4iMBIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Triangle4iMBIntersector4HybridPluecker();
- intersectors.intersector8 = BVH8Triangle4iMBIntersector8HybridPluecker();
- intersectors.intersector16 = BVH8Triangle4iMBIntersector16HybridPluecker();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH8Factory::BVH8Quad4vIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Quad4vIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4_filter = BVH8Quad4vIntersector4HybridMoeller();
- intersectors.intersector4_nofilter = BVH8Quad4vIntersector4HybridMoellerNoFilter();
- intersectors.intersector8_filter = BVH8Quad4vIntersector8HybridMoeller();
- intersectors.intersector8_nofilter = BVH8Quad4vIntersector8HybridMoellerNoFilter();
- intersectors.intersector16_filter = BVH8Quad4vIntersector16HybridMoeller();
- intersectors.intersector16_nofilter = BVH8Quad4vIntersector16HybridMoellerNoFilter();
- intersectors.intersectorN_filter = BVH8Quad4vIntersectorStreamMoeller();
- intersectors.intersectorN_nofilter = BVH8Quad4vIntersectorStreamMoellerNoFilter();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Quad4vIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Quad4vIntersector4HybridPluecker();
- intersectors.intersector8 = BVH8Quad4vIntersector8HybridPluecker();
- intersectors.intersector16 = BVH8Quad4vIntersector16HybridPluecker();
- intersectors.intersectorN = BVH8Quad4vIntersectorStreamPluecker();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH8Factory::BVH8Quad4iIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Quad4iIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Quad4iIntersector4HybridMoeller();
- intersectors.intersector8 = BVH8Quad4iIntersector8HybridMoeller();
- intersectors.intersector16 = BVH8Quad4iIntersector16HybridMoeller();
- intersectors.intersectorN = BVH8Quad4iIntersectorStreamMoeller();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Quad4iIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Quad4iIntersector4HybridPluecker();
- intersectors.intersector8 = BVH8Quad4iIntersector8HybridPluecker();
- intersectors.intersector16 = BVH8Quad4iIntersector16HybridPluecker();
- intersectors.intersectorN = BVH8Quad4iIntersectorStreamPluecker();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH8Factory::BVH8Quad4iMBIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- switch (ivariant) {
- case IntersectVariant::FAST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Quad4iMBIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Quad4iMBIntersector4HybridMoeller();
- intersectors.intersector8 = BVH8Quad4iMBIntersector8HybridMoeller();
- intersectors.intersector16 = BVH8Quad4iMBIntersector16HybridMoeller();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- case IntersectVariant::ROBUST:
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8Quad4iMBIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8Quad4iMBIntersector4HybridPluecker();
- intersectors.intersector8 = BVH8Quad4iMBIntersector8HybridPluecker();
- intersectors.intersector16 = BVH8Quad4iMBIntersector16HybridPluecker();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
- }
- return Accel::Intersectors();
- }
-
- Accel::Intersectors BVH8Factory::QBVH8Triangle4iIntersectors(BVH8* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = QBVH8Triangle4iIntersector1Pluecker();
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::QBVH8Triangle4Intersectors(BVH8* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = QBVH8Triangle4Intersector1Moeller();
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::QBVH8Quad4iIntersectors(BVH8* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = QBVH8Quad4iIntersector1Pluecker();
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::BVH8UserGeometryIntersectors(BVH8* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8VirtualIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8VirtualIntersector4Chunk();
- intersectors.intersector8 = BVH8VirtualIntersector8Chunk();
- intersectors.intersector16 = BVH8VirtualIntersector16Chunk();
- intersectors.intersectorN = BVH8VirtualIntersectorStream();
-#endif
- intersectors.collider = BVH8ColliderUserGeom();
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::BVH8UserGeometryMBIntersectors(BVH8* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8VirtualMBIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8VirtualMBIntersector4Chunk();
- intersectors.intersector8 = BVH8VirtualMBIntersector8Chunk();
- intersectors.intersector16 = BVH8VirtualMBIntersector16Chunk();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::BVH8InstanceIntersectors(BVH8* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8InstanceIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8InstanceIntersector4Chunk();
- intersectors.intersector8 = BVH8InstanceIntersector8Chunk();
- intersectors.intersector16 = BVH8InstanceIntersector16Chunk();
- intersectors.intersectorN = BVH8InstanceIntersectorStream();
-#endif
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::BVH8InstanceMBIntersectors(BVH8* bvh)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8InstanceMBIntersector1();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8InstanceMBIntersector4Chunk();
- intersectors.intersector8 = BVH8InstanceMBIntersector8Chunk();
- intersectors.intersector16 = BVH8InstanceMBIntersector16Chunk();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- return intersectors;
- }
-
- Accel* BVH8Factory::BVH8OBBVirtualCurve8v(Scene* scene, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Curve8v::type,scene);
- Accel::Intersectors intersectors = BVH8OBBVirtualCurveIntersectors(accel,VirtualCurveIntersector8v(),ivariant);
- Builder* builder = BVH8Curve8vBuilder_OBB_New(accel,scene,0);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8OBBVirtualCurve8iMB(Scene* scene, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Curve8iMB::type,scene);
- Accel::Intersectors intersectors = BVH8OBBVirtualCurveIntersectorsMB(accel,VirtualCurveIntersector8iMB(),ivariant);
- Builder* builder = BVH8OBBCurve8iMBBuilder_OBB(accel,scene,0);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Triangle4(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Triangle4::type,scene);
- Accel::Intersectors intersectors= BVH8Triangle4Intersectors(accel,ivariant);
- Builder* builder = nullptr;
- if (scene->device->tri_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8Triangle4SceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelTriangle4MeshSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: builder = BVH8Triangle4SceneBuilderFastSpatialSAH(accel,scene,0); break;
- }
- }
- else if (scene->device->tri_builder == "sah" ) builder = BVH8Triangle4SceneBuilderSAH(accel,scene,0);
- else if (scene->device->tri_builder == "sah_fast_spatial") builder = BVH8Triangle4SceneBuilderFastSpatialSAH(accel,scene,0);
- else if (scene->device->tri_builder == "sah_presplit") builder = BVH8Triangle4SceneBuilderSAH(accel,scene,MODE_HIGH_QUALITY);
- else if (scene->device->tri_builder == "dynamic" ) builder = BVH8BuilderTwoLevelTriangle4MeshSAH(accel,scene,false);
- else if (scene->device->tri_builder == "morton" ) builder = BVH8BuilderTwoLevelTriangle4MeshSAH(accel,scene,true);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH8<Triangle4>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Triangle4v(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Triangle4v::type,scene);
- Accel::Intersectors intersectors= BVH8Triangle4vIntersectors(accel,ivariant);
- Builder* builder = nullptr;
- if (scene->device->tri_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8Triangle4vSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelTriangle4vMeshSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: builder = BVH8Triangle4vSceneBuilderFastSpatialSAH(accel,scene,0); break;
- }
- }
- else if (scene->device->tri_builder == "sah_fast_spatial") builder = BVH8Triangle4SceneBuilderFastSpatialSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH8<Triangle4v>");
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Triangle4i(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Triangle4i::type,scene);
- Accel::Intersectors intersectors = BVH8Triangle4iIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->tri_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8Triangle4iSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelTriangle4iMeshSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: assert(false); break; // FIXME: implement
- }
- }
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH8<Triangle4i>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Triangle4iMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Triangle4i::type,scene);
- Accel::Intersectors intersectors = BVH8Triangle4iMBIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->tri_builder_mb == "default") { // FIXME: implement
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8Triangle4iMBSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->tri_builder_mb == "internal_time_splits") builder = BVH8Triangle4iMBSceneBuilderSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder_mb+" for BVH8<Triangle4iMB>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Triangle4vMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Triangle4vMB::type,scene);
- Accel::Intersectors intersectors= BVH8Triangle4vMBIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->tri_builder_mb == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8Triangle4vMBSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->tri_builder_mb == "internal_time_splits") builder = BVH8Triangle4vMBSceneBuilderSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder_mb+" for BVH8<Triangle4vMB>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8QuantizedTriangle4i(Scene* scene)
- {
- BVH8* accel = new BVH8(Triangle4i::type,scene);
- Accel::Intersectors intersectors = QBVH8Triangle4iIntersectors(accel);
- Builder* builder = BVH8QuantizedTriangle4iSceneBuilderSAH(accel,scene,0);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8QuantizedTriangle4(Scene* scene)
- {
- BVH8* accel = new BVH8(Triangle4::type,scene);
- Accel::Intersectors intersectors = QBVH8Triangle4Intersectors(accel);
- Builder* builder = BVH8QuantizedTriangle4SceneBuilderSAH(accel,scene,0);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Quad4v(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Quad4v::type,scene);
- Accel::Intersectors intersectors = BVH8Quad4vIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->quad_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8Quad4vSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelQuadMeshSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: builder = BVH8Quad4vSceneBuilderFastSpatialSAH(accel,scene,0); break;
- }
- }
- else if (scene->device->quad_builder == "dynamic" ) builder = BVH8BuilderTwoLevelQuadMeshSAH(accel,scene,false);
- else if (scene->device->quad_builder == "morton" ) builder = BVH8BuilderTwoLevelQuadMeshSAH(accel,scene,true);
- else if (scene->device->quad_builder == "sah_fast_spatial" ) builder = BVH8Quad4vSceneBuilderFastSpatialSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for BVH8<Quad4v>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Quad4i(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Quad4i::type,scene);
- Accel::Intersectors intersectors = BVH8Quad4iIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->quad_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8Quad4iSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
- case BuildVariant::HIGH_QUALITY: assert(false); break; // FIXME: implement
- }
- }
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for BVH8<Quad4i>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Quad4iMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(Quad4i::type,scene);
- Accel::Intersectors intersectors = BVH8Quad4iMBIntersectors(accel,ivariant);
-
- Builder* builder = nullptr;
- if (scene->device->quad_builder_mb == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8Quad4iMBSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder_mb+" for BVH8<Quad4i>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8QuantizedQuad4i(Scene* scene)
- {
- BVH8* accel = new BVH8(Quad4i::type,scene);
- Accel::Intersectors intersectors = QBVH8Quad4iIntersectors(accel);
- Builder* builder = nullptr;
- if (scene->device->quad_builder == "default" ) builder = BVH8QuantizedQuad4iSceneBuilderSAH(accel,scene,0);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for QBVH8<Quad4i>");
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8UserGeometry(Scene* scene, BuildVariant bvariant)
- {
- BVH8* accel = new BVH8(Object::type,scene);
- Accel::Intersectors intersectors = BVH8UserGeometryIntersectors(accel);
-
- Builder* builder = nullptr;
- if (scene->device->object_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8VirtualSceneBuilderSAH(accel,scene,0); break;
- case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelVirtualSAH(accel,scene,false); break;
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->object_builder == "sah") builder = BVH8VirtualSceneBuilderSAH(accel,scene,0);
- else if (scene->device->object_builder == "dynamic") builder = BVH8BuilderTwoLevelVirtualSAH(accel,scene,false);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH8<Object>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8UserGeometryMB(Scene* scene)
- {
- BVH8* accel = new BVH8(Object::type,scene);
- Accel::Intersectors intersectors = BVH8UserGeometryMBIntersectors(accel);
- Builder* builder = BVH8VirtualMBSceneBuilderSAH(accel,scene,0);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8Instance(Scene* scene, bool isExpensive, BuildVariant bvariant)
- {
- BVH8* accel = new BVH8(InstancePrimitive::type,scene);
- Accel::Intersectors intersectors = BVH8InstanceIntersectors(accel);
- auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE;
- // Builder* builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype);
-
- Builder* builder = nullptr;
- if (scene->device->object_builder == "default") {
- switch (bvariant) {
- case BuildVariant::STATIC : builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype);; break;
- case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelInstanceSAH(accel,scene,gtype,false); break;
- case BuildVariant::HIGH_QUALITY: assert(false); break;
- }
- }
- else if (scene->device->object_builder == "sah") builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype);
- else if (scene->device->object_builder == "dynamic") builder = BVH8BuilderTwoLevelInstanceSAH(accel,scene,gtype,false);
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH8<Object>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8InstanceMB(Scene* scene, bool isExpensive)
- {
- BVH8* accel = new BVH8(InstancePrimitive::type,scene);
- Accel::Intersectors intersectors = BVH8InstanceMBIntersectors(accel);
- auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE;
- Builder* builder = BVH8InstanceMBSceneBuilderSAH(accel,scene,gtype);
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel::Intersectors BVH8Factory::BVH8GridIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- if (ivariant == IntersectVariant::FAST)
- {
- intersectors.intersector1 = BVH8GridIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8GridIntersector4HybridMoeller();
- intersectors.intersector8 = BVH8GridIntersector8HybridMoeller();
- intersectors.intersector16 = BVH8GridIntersector16HybridMoeller();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- }
- else /* if (ivariant == IntersectVariant::ROBUST) */
- {
- intersectors.intersector1 = BVH8GridIntersector1Pluecker();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = BVH8GridIntersector4HybridPluecker();
- intersectors.intersector8 = BVH8GridIntersector8HybridPluecker();
- intersectors.intersector16 = BVH8GridIntersector16HybridPluecker();
- intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
-#endif
- }
- return intersectors;
- }
-
- Accel::Intersectors BVH8Factory::BVH8GridMBIntersectors(BVH8* bvh, IntersectVariant ivariant)
- {
- Accel::Intersectors intersectors;
- intersectors.ptr = bvh;
- intersectors.intersector1 = BVH8GridMBIntersector1Moeller();
-#if defined (EMBREE_RAY_PACKETS)
- intersectors.intersector4 = nullptr;
- intersectors.intersector8 = nullptr;
- intersectors.intersector16 = nullptr;
- intersectors.intersectorN = nullptr;
-#endif
- return intersectors;
- }
-
- Accel* BVH8Factory::BVH8Grid(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(SubGridQBVH8::type,scene);
- Accel::Intersectors intersectors = BVH8GridIntersectors(accel,ivariant);
- Builder* builder = nullptr;
- if (scene->device->grid_builder == "default") {
- builder = BVH8GridSceneBuilderSAH(accel,scene,0);
- }
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH4<GridMesh>");
-
- return new AccelInstance(accel,builder,intersectors);
- }
-
- Accel* BVH8Factory::BVH8GridMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
- {
- BVH8* accel = new BVH8(SubGridQBVH8::type,scene);
- Accel::Intersectors intersectors = BVH8GridMBIntersectors(accel,ivariant);
- Builder* builder = nullptr;
- if (scene->device->grid_builder_mb == "default") {
- builder = BVH8GridMBSceneBuilderSAH(accel,scene,0);
- }
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH8MB<GridMesh>");
- return new AccelInstance(accel,builder,intersectors);
- }
-}
-
-#endif
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh8_factory.h b/thirdparty/embree-aarch64/kernels/bvh/bvh8_factory.h
deleted file mode 100644
index b92188e7d3..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh8_factory.h
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_factory.h"
-
-namespace embree
-{
- /*! BVH8 instantiations */
- class BVH8Factory : public BVHFactory
- {
- public:
- BVH8Factory(int bfeatures, int ifeatures);
-
- public:
- Accel* BVH8OBBVirtualCurve8v(Scene* scene, IntersectVariant ivariant);
- Accel* BVH8OBBVirtualCurve8iMB(Scene* scene, IntersectVariant ivariant);
- DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8v);
- DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8iMB);
-
- Accel* BVH8Triangle4 (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH8Triangle4v (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH8Triangle4i (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH8Triangle4vMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH8Triangle4iMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
-
- Accel* BVH8Quad4v (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH8Quad4i (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH8Quad4iMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
-
- Accel* BVH8QuantizedTriangle4i(Scene* scene);
- Accel* BVH8QuantizedTriangle4(Scene* scene);
- Accel* BVH8QuantizedQuad4i(Scene* scene);
-
- Accel* BVH8UserGeometry(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC);
- Accel* BVH8UserGeometryMB(Scene* scene);
-
- Accel* BVH8Instance(Scene* scene, bool isExpensive, BuildVariant bvariant = BuildVariant::STATIC);
- Accel* BVH8InstanceMB(Scene* scene, bool isExpensive);
-
- Accel* BVH8Grid(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
- Accel* BVH8GridMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
-
- private:
- void selectBuilders(int features);
- void selectIntersectors(int features);
-
- private:
- Accel::Intersectors BVH8OBBVirtualCurveIntersectors(BVH8* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant);
- Accel::Intersectors BVH8OBBVirtualCurveIntersectorsMB(BVH8* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant);
-
- Accel::Intersectors BVH8Triangle4Intersectors(BVH8* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH8Triangle4vIntersectors(BVH8* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH8Triangle4iIntersectors(BVH8* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH8Triangle4iMBIntersectors(BVH8* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH8Triangle4vMBIntersectors(BVH8* bvh, IntersectVariant ivariant);
-
- Accel::Intersectors BVH8Quad4vIntersectors(BVH8* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH8Quad4iIntersectors(BVH8* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH8Quad4iMBIntersectors(BVH8* bvh, IntersectVariant ivariant);
-
- Accel::Intersectors QBVH8Triangle4iIntersectors(BVH8* bvh);
- Accel::Intersectors QBVH8Triangle4Intersectors(BVH8* bvh);
- Accel::Intersectors QBVH8Quad4iIntersectors(BVH8* bvh);
-
- Accel::Intersectors BVH8UserGeometryIntersectors(BVH8* bvh);
- Accel::Intersectors BVH8UserGeometryMBIntersectors(BVH8* bvh);
-
- Accel::Intersectors BVH8InstanceIntersectors(BVH8* bvh);
- Accel::Intersectors BVH8InstanceMBIntersectors(BVH8* bvh);
-
- Accel::Intersectors BVH8GridIntersectors(BVH8* bvh, IntersectVariant ivariant);
- Accel::Intersectors BVH8GridMBIntersectors(BVH8* bvh, IntersectVariant ivariant);
-
- private:
- DEFINE_SYMBOL2(Accel::Collider,BVH8ColliderUserGeom);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersector1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersector1MB);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersectorRobust1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersectorRobust1MB);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4Intersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vIntersector1Pluecker);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vMBIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iMBIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vMBIntersector1Pluecker);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iMBIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vIntersector1Woop);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4vIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4iIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4vIntersector1Pluecker);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4iIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4iMBIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4iMBIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,QBVH8Triangle4iIntersector1Pluecker);
- DEFINE_SYMBOL2(Accel::Intersector1,QBVH8Triangle4Intersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,QBVH8Quad4iIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8VirtualIntersector1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8VirtualMBIntersector1);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8InstanceIntersector1);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8InstanceMBIntersector1);
-
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8GridIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8GridMBIntersector1Moeller);
- DEFINE_SYMBOL2(Accel::Intersector1,BVH8GridIntersector1Pluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersector4Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersector4HybridMB);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersectorRobust4Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersectorRobust4HybridMB);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4Intersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4Intersector4HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vIntersector4HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vMBIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iMBIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vMBIntersector4HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iMBIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4iIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4iIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4iMBIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4iMBIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8VirtualIntersector4Chunk);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8VirtualMBIntersector4Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8InstanceIntersector4Chunk);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8InstanceMBIntersector4Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8GridIntersector4HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector4,BVH8GridIntersector4HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersector8Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersector8HybridMB);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersectorRobust8Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersectorRobust8HybridMB);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4Intersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4Intersector8HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vIntersector8HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vMBIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iMBIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vMBIntersector8HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iMBIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4iIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4iIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4iMBIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4iMBIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8VirtualIntersector8Chunk);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8VirtualMBIntersector8Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8InstanceIntersector8Chunk);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8InstanceMBIntersector8Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8GridIntersector8HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector8,BVH8GridIntersector8HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersector16Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersector16HybridMB);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersectorRobust16Hybrid);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersectorRobust16HybridMB);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4Intersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4Intersector16HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vIntersector16HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vMBIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iMBIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vMBIntersector16HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iMBIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4iIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridPluecker);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4iIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4iMBIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4iMBIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8VirtualIntersector16Chunk);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8VirtualMBIntersector16Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8InstanceIntersector16Chunk);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8InstanceMBIntersector16Chunk);
-
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8GridIntersector16HybridMoeller);
- DEFINE_SYMBOL2(Accel::Intersector16,BVH8GridIntersector16HybridPluecker);
-
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8IntersectorStreamPacketFallback);
-
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoeller);
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamMoeller);
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4vIntersectorStreamPluecker);
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamPluecker);
-
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamMoeller);
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamMoellerNoFilter);
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4iIntersectorStreamMoeller);
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamPluecker);
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4iIntersectorStreamPluecker);
-
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8VirtualIntersectorStream);
-
- DEFINE_SYMBOL2(Accel::IntersectorN,BVH8InstanceIntersectorStream);
-
- // SAH scene builders
- private:
- DEFINE_ISA_FUNCTION(Builder*,BVH8Curve8vBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8OBBCurve8iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4vMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8QuantizedTriangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8QuantizedTriangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH8Quad4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8Quad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8Quad4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8QuantizedQuad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH8VirtualSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8VirtualMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH8InstanceSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
- DEFINE_ISA_FUNCTION(Builder*,BVH8InstanceMBSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
-
- DEFINE_ISA_FUNCTION(Builder*,BVH8GridSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8GridMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
-
- // SAH spatial scene builders
- private:
- DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4SceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
- DEFINE_ISA_FUNCTION(Builder*,BVH8Quad4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
-
- // twolevel scene builders
- private:
- DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4MeshSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4vMeshSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool);
- DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool);
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder.cpp
deleted file mode 100644
index e832537ec5..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh_builder.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int N>
- typename BVHN<N>::NodeRef BVHNBuilderVirtual<N>::BVHNBuilderV::build(FastAllocator* allocator, BuildProgressMonitor& progressFunc, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings)
- {
- auto createLeafFunc = [&] (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) -> NodeRef {
- return createLeaf(prims,set,alloc);
- };
-
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxBuildDepthLeaf;
- return BVHBuilderBinnedSAH::build<NodeRef>
- (FastAllocator::Create(allocator),typename BVH::AABBNode::Create2(),typename BVH::AABBNode::Set3(allocator,prims),createLeafFunc,progressFunc,prims,pinfo,settings);
- }
-
-
- template<int N>
- typename BVHN<N>::NodeRef BVHNBuilderQuantizedVirtual<N>::BVHNBuilderV::build(FastAllocator* allocator, BuildProgressMonitor& progressFunc, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings)
- {
- auto createLeafFunc = [&] (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) -> NodeRef {
- return createLeaf(prims,set,alloc);
- };
-
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxBuildDepthLeaf;
- return BVHBuilderBinnedSAH::build<NodeRef>
- (FastAllocator::Create(allocator),typename BVH::QuantizedNode::Create2(),typename BVH::QuantizedNode::Set2(),createLeafFunc,progressFunc,prims,pinfo,settings);
- }
-
- template<int N>
- typename BVHN<N>::NodeRecordMB BVHNBuilderMblurVirtual<N>::BVHNBuilderV::build(FastAllocator* allocator, BuildProgressMonitor& progressFunc, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings, const BBox1f& timeRange)
- {
- auto createLeafFunc = [&] (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) -> NodeRecordMB {
- return createLeaf(prims,set,alloc);
- };
-
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxBuildDepthLeaf;
- return BVHBuilderBinnedSAH::build<NodeRecordMB>
- (FastAllocator::Create(allocator),typename BVH::AABBNodeMB::Create(),typename BVH::AABBNodeMB::SetTimeRange(timeRange),createLeafFunc,progressFunc,prims,pinfo,settings);
- }
-
- template struct BVHNBuilderVirtual<4>;
- template struct BVHNBuilderQuantizedVirtual<4>;
- template struct BVHNBuilderMblurVirtual<4>;
-
-#if defined(__AVX__)
- template struct BVHNBuilderVirtual<8>;
- template struct BVHNBuilderQuantizedVirtual<8>;
- template struct BVHNBuilderMblurVirtual<8>;
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder.h
deleted file mode 100644
index 1b86bb45ad..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh.h"
-#include "../builders/bvh_builder_sah.h"
-
-namespace embree
-{
- namespace isa
- {
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
- template<int N>
- struct BVHNBuilderVirtual
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef FastAllocator::CachedAllocator Allocator;
-
- struct BVHNBuilderV {
- NodeRef build(FastAllocator* allocator, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings);
- virtual NodeRef createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) = 0;
- };
-
- template<typename CreateLeafFunc>
- struct BVHNBuilderT : public BVHNBuilderV
- {
- BVHNBuilderT (CreateLeafFunc createLeafFunc)
- : createLeafFunc(createLeafFunc) {}
-
- NodeRef createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) {
- return createLeafFunc(prims,set,alloc);
- }
-
- private:
- CreateLeafFunc createLeafFunc;
- };
-
- template<typename CreateLeafFunc>
- static NodeRef build(FastAllocator* allocator, CreateLeafFunc createLeaf, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings) {
- return BVHNBuilderT<CreateLeafFunc>(createLeaf).build(allocator,progress,prims,pinfo,settings);
- }
- };
-
- template<int N>
- struct BVHNBuilderQuantizedVirtual
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef FastAllocator::CachedAllocator Allocator;
-
- struct BVHNBuilderV {
- NodeRef build(FastAllocator* allocator, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings);
- virtual NodeRef createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) = 0;
- };
-
- template<typename CreateLeafFunc>
- struct BVHNBuilderT : public BVHNBuilderV
- {
- BVHNBuilderT (CreateLeafFunc createLeafFunc)
- : createLeafFunc(createLeafFunc) {}
-
- NodeRef createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) {
- return createLeafFunc(prims,set,alloc);
- }
-
- private:
- CreateLeafFunc createLeafFunc;
- };
-
- template<typename CreateLeafFunc>
- static NodeRef build(FastAllocator* allocator, CreateLeafFunc createLeaf, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings) {
- return BVHNBuilderT<CreateLeafFunc>(createLeaf).build(allocator,progress,prims,pinfo,settings);
- }
- };
-
- template<int N>
- struct BVHNBuilderMblurVirtual
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::AABBNodeMB AABBNodeMB;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecordMB NodeRecordMB;
- typedef FastAllocator::CachedAllocator Allocator;
-
- struct BVHNBuilderV {
- NodeRecordMB build(FastAllocator* allocator, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings, const BBox1f& timeRange);
- virtual NodeRecordMB createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) = 0;
- };
-
- template<typename CreateLeafFunc>
- struct BVHNBuilderT : public BVHNBuilderV
- {
- BVHNBuilderT (CreateLeafFunc createLeafFunc)
- : createLeafFunc(createLeafFunc) {}
-
- NodeRecordMB createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) {
- return createLeafFunc(prims,set,alloc);
- }
-
- private:
- CreateLeafFunc createLeafFunc;
- };
-
- template<typename CreateLeafFunc>
- static NodeRecordMB build(FastAllocator* allocator, CreateLeafFunc createLeaf, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings, const BBox1f& timeRange) {
- return BVHNBuilderT<CreateLeafFunc>(createLeaf).build(allocator,progress,prims,pinfo,settings,timeRange);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_morton.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_morton.cpp
deleted file mode 100644
index 64759c1294..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_morton.cpp
+++ /dev/null
@@ -1,531 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh.h"
-#include "bvh_statistics.h"
-#include "bvh_rotate.h"
-#include "../common/profile.h"
-#include "../../common/algorithms/parallel_prefix_sum.h"
-
-#include "../builders/primrefgen.h"
-#include "../builders/bvh_builder_morton.h"
-
-#include "../geometry/triangle.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/trianglei.h"
-#include "../geometry/quadv.h"
-#include "../geometry/quadi.h"
-#include "../geometry/object.h"
-#include "../geometry/instance.h"
-
-#if defined(__X86_64__) || defined(__aarch64__)
-# define ROTATE_TREE 1 // specifies number of tree rotation rounds to perform
-#else
-# define ROTATE_TREE 0 // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues
-#endif
-
-namespace embree
-{
- namespace isa
- {
- template<int N>
- struct SetBVHNBounds
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecord NodeRecord;
- typedef typename BVH::AABBNode AABBNode;
-
- BVH* bvh;
- __forceinline SetBVHNBounds (BVH* bvh) : bvh(bvh) {}
-
- __forceinline NodeRecord operator() (NodeRef ref, const NodeRecord* children, size_t num)
- {
- AABBNode* node = ref.getAABBNode();
-
- BBox3fa res = empty;
- for (size_t i=0; i<num; i++) {
- const BBox3fa b = children[i].bounds;
- res.extend(b);
- node->setRef(i,children[i].ref);
- node->setBounds(i,b);
- }
-
- BBox3fx result = (BBox3fx&)res;
-#if ROTATE_TREE
- if (N == 4)
- {
- size_t n = 0;
- for (size_t i=0; i<num; i++)
- n += children[i].bounds.lower.a;
-
- if (n >= 4096) {
- for (size_t i=0; i<num; i++) {
- if (children[i].bounds.lower.a < 4096) {
- for (int j=0; j<ROTATE_TREE; j++)
- BVHNRotate<N>::rotate(node->child(i));
- node->child(i).setBarrier();
- }
- }
- }
- result.lower.a = unsigned(n);
- }
-#endif
-
- return NodeRecord(ref,result);
- }
- };
-
- template<int N, typename Primitive>
- struct CreateMortonLeaf;
-
- template<int N>
- struct CreateMortonLeaf<N,Triangle4>
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecord NodeRecord;
-
- __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
- : mesh(mesh), morton(morton), geomID_(geomID) {}
-
- __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
- {
- vfloat4 lower(pos_inf);
- vfloat4 upper(neg_inf);
- size_t items = current.size();
- size_t start = current.begin();
- assert(items<=4);
-
- /* allocate leaf node */
- Triangle4* accel = (Triangle4*) alloc.malloc1(sizeof(Triangle4),BVH::byteAlignment);
- NodeRef ref = BVH::encodeLeaf((char*)accel,1);
- vuint4 vgeomID = -1, vprimID = -1;
- Vec3vf4 v0 = zero, v1 = zero, v2 = zero;
- const TriangleMesh* __restrict__ const mesh = this->mesh;
-
- for (size_t i=0; i<items; i++)
- {
- const unsigned int primID = morton[start+i].index;
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- const Vec3fa& p0 = mesh->vertex(tri.v[0]);
- const Vec3fa& p1 = mesh->vertex(tri.v[1]);
- const Vec3fa& p2 = mesh->vertex(tri.v[2]);
- lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
- upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
- vgeomID [i] = geomID_;
- vprimID [i] = primID;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- }
-
- Triangle4::store_nt(accel,Triangle4(v0,v1,v2,vgeomID,vprimID));
- BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
-#if ROTATE_TREE
- if (N == 4)
- box_o.lower.a = unsigned(current.size());
-#endif
- return NodeRecord(ref,box_o);
- }
-
- private:
- TriangleMesh* mesh;
- BVHBuilderMorton::BuildPrim* morton;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- };
-
- template<int N>
- struct CreateMortonLeaf<N,Triangle4v>
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecord NodeRecord;
-
- __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
- : mesh(mesh), morton(morton), geomID_(geomID) {}
-
- __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
- {
- vfloat4 lower(pos_inf);
- vfloat4 upper(neg_inf);
- size_t items = current.size();
- size_t start = current.begin();
- assert(items<=4);
-
- /* allocate leaf node */
- Triangle4v* accel = (Triangle4v*) alloc.malloc1(sizeof(Triangle4v),BVH::byteAlignment);
- NodeRef ref = BVH::encodeLeaf((char*)accel,1);
- vuint4 vgeomID = -1, vprimID = -1;
- Vec3vf4 v0 = zero, v1 = zero, v2 = zero;
- const TriangleMesh* __restrict__ mesh = this->mesh;
-
- for (size_t i=0; i<items; i++)
- {
- const unsigned int primID = morton[start+i].index;
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- const Vec3fa& p0 = mesh->vertex(tri.v[0]);
- const Vec3fa& p1 = mesh->vertex(tri.v[1]);
- const Vec3fa& p2 = mesh->vertex(tri.v[2]);
- lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
- upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
- vgeomID [i] = geomID_;
- vprimID [i] = primID;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- }
- Triangle4v::store_nt(accel,Triangle4v(v0,v1,v2,vgeomID,vprimID));
- BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
-#if ROTATE_TREE
- if (N == 4)
- box_o.lower.a = current.size();
-#endif
- return NodeRecord(ref,box_o);
- }
- private:
- TriangleMesh* mesh;
- BVHBuilderMorton::BuildPrim* morton;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- };
-
- template<int N>
- struct CreateMortonLeaf<N,Triangle4i>
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecord NodeRecord;
-
- __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
- : mesh(mesh), morton(morton), geomID_(geomID) {}
-
- __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
- {
- vfloat4 lower(pos_inf);
- vfloat4 upper(neg_inf);
- size_t items = current.size();
- size_t start = current.begin();
- assert(items<=4);
-
- /* allocate leaf node */
- Triangle4i* accel = (Triangle4i*) alloc.malloc1(sizeof(Triangle4i),BVH::byteAlignment);
- NodeRef ref = BVH::encodeLeaf((char*)accel,1);
-
- vuint4 v0 = zero, v1 = zero, v2 = zero;
- vuint4 vgeomID = -1, vprimID = -1;
- const TriangleMesh* __restrict__ const mesh = this->mesh;
-
- for (size_t i=0; i<items; i++)
- {
- const unsigned int primID = morton[start+i].index;
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- const Vec3fa& p0 = mesh->vertex(tri.v[0]);
- const Vec3fa& p1 = mesh->vertex(tri.v[1]);
- const Vec3fa& p2 = mesh->vertex(tri.v[2]);
- lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
- upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
- vgeomID[i] = geomID_;
- vprimID[i] = primID;
- unsigned int int_stride = mesh->vertices0.getStride()/4;
- v0[i] = tri.v[0] * int_stride;
- v1[i] = tri.v[1] * int_stride;
- v2[i] = tri.v[2] * int_stride;
- }
-
- for (size_t i=items; i<4; i++)
- {
- vgeomID[i] = vgeomID[0];
- vprimID[i] = -1;
- v0[i] = 0;
- v1[i] = 0;
- v2[i] = 0;
- }
- Triangle4i::store_nt(accel,Triangle4i(v0,v1,v2,vgeomID,vprimID));
- BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
-#if ROTATE_TREE
- if (N == 4)
- box_o.lower.a = current.size();
-#endif
- return NodeRecord(ref,box_o);
- }
- private:
- TriangleMesh* mesh;
- BVHBuilderMorton::BuildPrim* morton;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- };
-
- template<int N>
- struct CreateMortonLeaf<N,Quad4v>
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecord NodeRecord;
-
- __forceinline CreateMortonLeaf (QuadMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
- : mesh(mesh), morton(morton), geomID_(geomID) {}
-
- __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
- {
- vfloat4 lower(pos_inf);
- vfloat4 upper(neg_inf);
- size_t items = current.size();
- size_t start = current.begin();
- assert(items<=4);
-
- /* allocate leaf node */
- Quad4v* accel = (Quad4v*) alloc.malloc1(sizeof(Quad4v),BVH::byteAlignment);
- NodeRef ref = BVH::encodeLeaf((char*)accel,1);
-
- vuint4 vgeomID = -1, vprimID = -1;
- Vec3vf4 v0 = zero, v1 = zero, v2 = zero, v3 = zero;
- const QuadMesh* __restrict__ mesh = this->mesh;
-
- for (size_t i=0; i<items; i++)
- {
- const unsigned int primID = morton[start+i].index;
- const QuadMesh::Quad& tri = mesh->quad(primID);
- const Vec3fa& p0 = mesh->vertex(tri.v[0]);
- const Vec3fa& p1 = mesh->vertex(tri.v[1]);
- const Vec3fa& p2 = mesh->vertex(tri.v[2]);
- const Vec3fa& p3 = mesh->vertex(tri.v[3]);
- lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2,(vfloat4)p3);
- upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2,(vfloat4)p3);
- vgeomID [i] = geomID_;
- vprimID [i] = primID;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- v3.x[i] = p3.x; v3.y[i] = p3.y; v3.z[i] = p3.z;
- }
- Quad4v::store_nt(accel,Quad4v(v0,v1,v2,v3,vgeomID,vprimID));
- BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
-#if ROTATE_TREE
- if (N == 4)
- box_o.lower.a = current.size();
-#endif
- return NodeRecord(ref,box_o);
- }
- private:
- QuadMesh* mesh;
- BVHBuilderMorton::BuildPrim* morton;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- };
-
- template<int N>
- struct CreateMortonLeaf<N,Object>
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecord NodeRecord;
-
- __forceinline CreateMortonLeaf (UserGeometry* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
- : mesh(mesh), morton(morton), geomID_(geomID) {}
-
- __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
- {
- vfloat4 lower(pos_inf);
- vfloat4 upper(neg_inf);
- size_t items = current.size();
- size_t start = current.begin();
-
- /* allocate leaf node */
- Object* accel = (Object*) alloc.malloc1(items*sizeof(Object),BVH::byteAlignment);
- NodeRef ref = BVH::encodeLeaf((char*)accel,items);
- const UserGeometry* mesh = this->mesh;
-
- BBox3fa bounds = empty;
- for (size_t i=0; i<items; i++)
- {
- const unsigned int index = morton[start+i].index;
- const unsigned int primID = index;
- bounds.extend(mesh->bounds(primID));
- new (&accel[i]) Object(geomID_,primID);
- }
-
- BBox3fx box_o = (BBox3fx&)bounds;
-#if ROTATE_TREE
- if (N == 4)
- box_o.lower.a = current.size();
-#endif
- return NodeRecord(ref,box_o);
- }
- private:
- UserGeometry* mesh;
- BVHBuilderMorton::BuildPrim* morton;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- };
-
- template<int N>
- struct CreateMortonLeaf<N,InstancePrimitive>
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecord NodeRecord;
-
- __forceinline CreateMortonLeaf (Instance* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
- : mesh(mesh), morton(morton), geomID_(geomID) {}
-
- __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
- {
- vfloat4 lower(pos_inf);
- vfloat4 upper(neg_inf);
- size_t items = current.size();
- size_t start = current.begin();
- assert(items <= 1);
-
- /* allocate leaf node */
- InstancePrimitive* accel = (InstancePrimitive*) alloc.malloc1(items*sizeof(InstancePrimitive),BVH::byteAlignment);
- NodeRef ref = BVH::encodeLeaf((char*)accel,items);
- const Instance* instance = this->mesh;
-
- BBox3fa bounds = empty;
- for (size_t i=0; i<items; i++)
- {
- const unsigned int primID = morton[start+i].index;
- bounds.extend(instance->bounds(primID));
- new (&accel[i]) InstancePrimitive(instance, geomID_);
- }
-
- BBox3fx box_o = (BBox3fx&)bounds;
-#if ROTATE_TREE
- if (N == 4)
- box_o.lower.a = current.size();
-#endif
- return NodeRecord(ref,box_o);
- }
- private:
- Instance* mesh;
- BVHBuilderMorton::BuildPrim* morton;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- };
-
- template<typename Mesh>
- struct CalculateMeshBounds
- {
- __forceinline CalculateMeshBounds (Mesh* mesh)
- : mesh(mesh) {}
-
- __forceinline const BBox3fa operator() (const BVHBuilderMorton::BuildPrim& morton) {
- return mesh->bounds(morton.index);
- }
-
- private:
- Mesh* mesh;
- };
-
- template<int N, typename Mesh, typename Primitive>
- class BVHNMeshBuilderMorton : public Builder
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::AABBNode AABBNode;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecord NodeRecord;
-
- public:
-
- BVHNMeshBuilderMorton (BVH* bvh, Mesh* mesh, unsigned int geomID, const size_t minLeafSize, const size_t maxLeafSize, const size_t singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD)
- : bvh(bvh), mesh(mesh), morton(bvh->device,0), settings(N,BVH::maxBuildDepth,minLeafSize,min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks),singleThreadThreshold), geomID_(geomID) {}
-
- /* build function */
- void build()
- {
- /* we reset the allocator when the mesh size changed */
- if (mesh->numPrimitives != numPreviousPrimitives) {
- bvh->alloc.clear();
- morton.clear();
- }
- size_t numPrimitives = mesh->size();
- numPreviousPrimitives = numPrimitives;
-
- /* skip build for empty scene */
- if (numPrimitives == 0) {
- bvh->set(BVH::emptyNode,empty,0);
- return;
- }
-
- /* preallocate arrays */
- morton.resize(numPrimitives);
- size_t bytesEstimated = numPrimitives*sizeof(AABBNode)/(4*N) + size_t(1.2f*Primitive::blocks(numPrimitives)*sizeof(Primitive));
- size_t bytesMortonCodes = numPrimitives*sizeof(BVHBuilderMorton::BuildPrim);
- bytesEstimated = max(bytesEstimated,bytesMortonCodes); // the first allocation block is reused to sort the morton codes
- bvh->alloc.init(bytesMortonCodes,bytesMortonCodes,bytesEstimated);
-
- /* create morton code array */
- BVHBuilderMorton::BuildPrim* dest = (BVHBuilderMorton::BuildPrim*) bvh->alloc.specialAlloc(bytesMortonCodes);
- size_t numPrimitivesGen = createMortonCodeArray<Mesh>(mesh,morton,bvh->scene->progressInterface);
-
- /* create BVH */
- SetBVHNBounds<N> setBounds(bvh);
- CreateMortonLeaf<N,Primitive> createLeaf(mesh,geomID_,morton.data());
- CalculateMeshBounds<Mesh> calculateBounds(mesh);
- auto root = BVHBuilderMorton::build<NodeRecord>(
- typename BVH::CreateAlloc(bvh),
- typename BVH::AABBNode::Create(),
- setBounds,createLeaf,calculateBounds,bvh->scene->progressInterface,
- morton.data(),dest,numPrimitivesGen,settings);
-
- bvh->set(root.ref,LBBox3fa(root.bounds),numPrimitives);
-
-#if ROTATE_TREE
- if (N == 4)
- {
- for (int i=0; i<ROTATE_TREE; i++)
- BVHNRotate<N>::rotate(bvh->root);
- bvh->clearBarrier(bvh->root);
- }
-#endif
-
- /* clear temporary data for static geometry */
- if (bvh->scene->isStaticAccel()) {
- morton.clear();
- }
- bvh->cleanup();
- }
-
- void clear() {
- morton.clear();
- }
-
- private:
- BVH* bvh;
- Mesh* mesh;
- mvector<BVHBuilderMorton::BuildPrim> morton;
- BVHBuilderMorton::Settings settings;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- unsigned int numPreviousPrimitives = 0;
- };
-
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- Builder* BVH4Triangle4MeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4> ((BVH4*)bvh,mesh,geomID,4,4); }
- Builder* BVH4Triangle4vMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4v>((BVH4*)bvh,mesh,geomID,4,4); }
- Builder* BVH4Triangle4iMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4i>((BVH4*)bvh,mesh,geomID,4,4); }
-#if defined(__AVX__)
- Builder* BVH8Triangle4MeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4> ((BVH8*)bvh,mesh,geomID,4,4); }
- Builder* BVH8Triangle4vMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4v>((BVH8*)bvh,mesh,geomID,4,4); }
- Builder* BVH8Triangle4iMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4i>((BVH8*)bvh,mesh,geomID,4,4); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_QUAD)
- Builder* BVH4Quad4vMeshBuilderMortonGeneral (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,QuadMesh,Quad4v>((BVH4*)bvh,mesh,geomID,4,4); }
-#if defined(__AVX__)
- Builder* BVH8Quad4vMeshBuilderMortonGeneral (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,QuadMesh,Quad4v>((BVH8*)bvh,mesh,geomID,4,4); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_USER)
- Builder* BVH4VirtualMeshBuilderMortonGeneral (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,UserGeometry,Object>((BVH4*)bvh,mesh,geomID,1,BVH4::maxLeafBlocks); }
-#if defined(__AVX__)
- Builder* BVH8VirtualMeshBuilderMortonGeneral (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,UserGeometry,Object>((BVH8*)bvh,mesh,geomID,1,BVH4::maxLeafBlocks); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- Builder* BVH4InstanceMeshBuilderMortonGeneral (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,Instance,InstancePrimitive>((BVH4*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); }
-#if defined(__AVX__)
- Builder* BVH8InstanceMeshBuilderMortonGeneral (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,Instance,InstancePrimitive>((BVH8*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); }
-#endif
-#endif
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah.cpp
deleted file mode 100644
index cf5b2eb47f..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah.cpp
+++ /dev/null
@@ -1,640 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh.h"
-#include "bvh_builder.h"
-#include "../builders/primrefgen.h"
-#include "../builders/splitter.h"
-
-#include "../geometry/linei.h"
-#include "../geometry/triangle.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/trianglev_mb.h"
-#include "../geometry/trianglei.h"
-#include "../geometry/quadv.h"
-#include "../geometry/quadi.h"
-#include "../geometry/object.h"
-#include "../geometry/instance.h"
-#include "../geometry/subgrid.h"
-
-#include "../common/state.h"
-#include "../../common/algorithms/parallel_for_for.h"
-#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
-
-#define PROFILE 0
-#define PROFILE_RUNS 20
-
-namespace embree
-{
- namespace isa
- {
- template<int N, typename Primitive>
- struct CreateLeaf
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
-
- __forceinline CreateLeaf (BVH* bvh) : bvh(bvh) {}
-
- __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
- {
- size_t n = set.size();
- size_t items = Primitive::blocks(n);
- size_t start = set.begin();
- Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
- typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
- for (size_t i=0; i<items; i++) {
- accel[i].fill(prims,start,set.end(),bvh->scene);
- }
- return node;
- }
-
- BVH* bvh;
- };
-
-
- template<int N, typename Primitive>
- struct CreateLeafQuantized
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
-
- __forceinline CreateLeafQuantized (BVH* bvh) : bvh(bvh) {}
-
- __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
- {
- size_t n = set.size();
- size_t items = Primitive::blocks(n);
- size_t start = set.begin();
- Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
- typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
- for (size_t i=0; i<items; i++) {
- accel[i].fill(prims,start,set.end(),bvh->scene);
- }
- return node;
- }
-
- BVH* bvh;
- };
-
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
- template<int N, typename Primitive>
- struct BVHNBuilderSAH : public Builder
- {
- typedef BVHN<N> BVH;
- typedef typename BVHN<N>::NodeRef NodeRef;
-
- BVH* bvh;
- Scene* scene;
- Geometry* mesh;
- mvector<PrimRef> prims;
- GeneralBVHBuilder::Settings settings;
- Geometry::GTypeMask gtype_;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max ();
- bool primrefarrayalloc;
- unsigned int numPreviousPrimitives = 0;
-
- BVHNBuilderSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize,
- const Geometry::GTypeMask gtype, bool primrefarrayalloc = false)
- : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0),
- settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), primrefarrayalloc(primrefarrayalloc) {}
-
- BVHNBuilderSAH (BVH* bvh, Geometry* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
- : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), geomID_(geomID), primrefarrayalloc(false) {}
-
- // FIXME: shrink bvh->alloc in destructor here and in other builders too
-
- void build()
- {
- /* we reset the allocator when the mesh size changed */
- if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
- bvh->alloc.clear();
- }
-
- /* if we use the primrefarray for allocations we have to take it back from the BVH */
- if (settings.primrefarrayalloc != size_t(inf))
- bvh->alloc.unshare(prims);
-
- /* skip build for empty scene */
- const size_t numPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(gtype_,false);
- numPreviousPrimitives = numPrimitives;
- if (numPrimitives == 0) {
- bvh->clear();
- prims.clear();
- return;
- }
-
- double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + "BuilderSAH");
-
-#if PROFILE
- profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
-#endif
-
- /* create primref array */
- if (primrefarrayalloc) {
- settings.primrefarrayalloc = numPrimitives/1000;
- if (settings.primrefarrayalloc < 1000)
- settings.primrefarrayalloc = inf;
- }
-
- /* enable os_malloc for two level build */
- if (mesh)
- bvh->alloc.setOSallocation(true);
-
- /* initialize allocator */
- const size_t node_bytes = numPrimitives*sizeof(typename BVH::AABBNodeMB)/(4*N);
- const size_t leaf_bytes = size_t(1.2*Primitive::blocks(numPrimitives)*sizeof(Primitive));
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
- prims.resize(numPrimitives);
-
- PrimInfo pinfo = mesh ?
- createPrimRefArray(mesh,geomID_,prims,bvh->scene->progressInterface) :
- createPrimRefArray(scene,gtype_,false,prims,bvh->scene->progressInterface);
-
- /* pinfo might has zero size due to invalid geometry */
- if (unlikely(pinfo.size() == 0))
- {
- bvh->clear();
- prims.clear();
- return;
- }
-
- /* call BVH builder */
- NodeRef root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeaf<N,Primitive>(bvh),bvh->scene->progressInterface,prims.data(),pinfo,settings);
- bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
- bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
-
-#if PROFILE
- });
-#endif
-
- /* if we allocated using the primrefarray we have to keep it alive */
- if (settings.primrefarrayalloc != size_t(inf))
- bvh->alloc.share(prims);
-
- /* for static geometries we can do some cleanups */
- else if (scene && scene->isStaticAccel()) {
- prims.clear();
- }
- bvh->cleanup();
- bvh->postBuild(t0);
- }
-
- void clear() {
- prims.clear();
- }
- };
-
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
- template<int N, typename Primitive>
- struct BVHNBuilderSAHQuantized : public Builder
- {
- typedef BVHN<N> BVH;
- typedef typename BVHN<N>::NodeRef NodeRef;
-
- BVH* bvh;
- Scene* scene;
- Geometry* mesh;
- mvector<PrimRef> prims;
- GeneralBVHBuilder::Settings settings;
- Geometry::GTypeMask gtype_;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- unsigned int numPreviousPrimitives = 0;
-
- BVHNBuilderSAHQuantized (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
- : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype) {}
-
- BVHNBuilderSAHQuantized (BVH* bvh, Geometry* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
- : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), geomID_(geomID) {}
-
- // FIXME: shrink bvh->alloc in destructor here and in other builders too
-
- void build()
- {
- /* we reset the allocator when the mesh size changed */
- if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
- bvh->alloc.clear();
- }
-
- /* skip build for empty scene */
- const size_t numPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(gtype_,false);
- numPreviousPrimitives = numPrimitives;
- if (numPrimitives == 0) {
- prims.clear();
- bvh->clear();
- return;
- }
-
- double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::QBVH" + toString(N) + "BuilderSAH");
-
-#if PROFILE
- profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
-#endif
- /* create primref array */
- prims.resize(numPrimitives);
- PrimInfo pinfo = mesh ?
- createPrimRefArray(mesh,geomID_,prims,bvh->scene->progressInterface) :
- createPrimRefArray(scene,gtype_,false,prims,bvh->scene->progressInterface);
-
- /* enable os_malloc for two level build */
- if (mesh)
- bvh->alloc.setOSallocation(true);
-
- /* call BVH builder */
- const size_t node_bytes = numPrimitives*sizeof(typename BVH::QuantizedNode)/(4*N);
- const size_t leaf_bytes = size_t(1.2*Primitive::blocks(numPrimitives)*sizeof(Primitive));
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
- NodeRef root = BVHNBuilderQuantizedVirtual<N>::build(&bvh->alloc,CreateLeafQuantized<N,Primitive>(bvh),bvh->scene->progressInterface,prims.data(),pinfo,settings);
- bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
- //bvh->layoutLargeNodes(pinfo.size()*0.005f); // FIXME: COPY LAYOUT FOR LARGE NODES !!!
-#if PROFILE
- });
-#endif
-
- /* clear temporary data for static geometry */
- if (scene && scene->isStaticAccel()) {
- prims.clear();
- }
- bvh->cleanup();
- bvh->postBuild(t0);
- }
-
- void clear() {
- prims.clear();
- }
- };
-
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
-
- template<int N, typename Primitive>
- struct CreateLeafGrid
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
-
- __forceinline CreateLeafGrid (BVH* bvh, const SubGridBuildData * const sgrids) : bvh(bvh),sgrids(sgrids) {}
-
- __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
- {
- const size_t items = set.size(); //Primitive::blocks(n);
- const size_t start = set.begin();
-
- /* collect all subsets with unique geomIDs */
- assert(items <= N);
- unsigned int geomIDs[N];
- unsigned int num_geomIDs = 1;
- geomIDs[0] = prims[start].geomID();
-
- for (size_t i=1;i<items;i++)
- {
- bool found = false;
- const unsigned int new_geomID = prims[start+i].geomID();
- for (size_t j=0;j<num_geomIDs;j++)
- if (new_geomID == geomIDs[j])
- { found = true; break; }
- if (!found)
- geomIDs[num_geomIDs++] = new_geomID;
- }
-
- /* allocate all leaf memory in one single block */
- SubGridQBVHN<N>* accel = (SubGridQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridQBVHN<N>),BVH::byteAlignment);
- typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,num_geomIDs);
-
- for (size_t g=0;g<num_geomIDs;g++)
- {
- unsigned int x[N];
- unsigned int y[N];
- unsigned int primID[N];
- BBox3fa bounds[N];
- unsigned int pos = 0;
- for (size_t i=0;i<items;i++)
- {
- if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
-
- const SubGridBuildData& sgrid_bd = sgrids[prims[start+i].primID()];
- x[pos] = sgrid_bd.sx;
- y[pos] = sgrid_bd.sy;
- primID[pos] = sgrid_bd.primID;
- bounds[pos] = prims[start+i].bounds();
- pos++;
- }
- assert(pos <= N);
- new (&accel[g]) SubGridQBVHN<N>(x,y,primID,bounds,geomIDs[g],pos);
- }
-
- return node;
- }
-
- BVH* bvh;
- const SubGridBuildData * const sgrids;
- };
-
-
- template<int N>
- struct BVHNBuilderSAHGrid : public Builder
- {
- typedef BVHN<N> BVH;
- typedef typename BVHN<N>::NodeRef NodeRef;
-
- BVH* bvh;
- Scene* scene;
- GridMesh* mesh;
- mvector<PrimRef> prims;
- mvector<SubGridBuildData> sgrids;
- GeneralBVHBuilder::Settings settings;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- unsigned int numPreviousPrimitives = 0;
-
- BVHNBuilderSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
- : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0), sgrids(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD) {}
-
- BVHNBuilderSAHGrid (BVH* bvh, GridMesh* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
- : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), sgrids(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), geomID_(geomID) {}
-
- void build()
- {
- /* we reset the allocator when the mesh size changed */
- if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
- bvh->alloc.clear();
- }
-
- /* if we use the primrefarray for allocations we have to take it back from the BVH */
- if (settings.primrefarrayalloc != size_t(inf))
- bvh->alloc.unshare(prims);
-
- const size_t numGridPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(GridMesh::geom_type,false);
- numPreviousPrimitives = numGridPrimitives;
-
- PrimInfo pinfo(empty);
- size_t numPrimitives = 0;
-
- if (!mesh)
- {
- /* first run to get #primitives */
-
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator<GridMesh,false> iter(scene);
-
- pstate.init(iter,size_t(1024));
-
- /* iterate over all meshes in the scene */
- pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j)) continue;
- BBox3fa bounds = empty;
- const PrimRef prim(bounds,(unsigned)geomID,(unsigned)j);
- if (!mesh->valid(j)) continue;
- pinfo.add_center2(prim,mesh->getNumSubGrids(j));
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- numPrimitives = pinfo.size();
-
- /* resize arrays */
- sgrids.resize(numPrimitives);
- prims.resize(numPrimitives);
-
- /* second run to fill primrefs and SubGridBuildData arrays */
- pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
- k = base.size();
- size_t p_index = k;
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j)) continue;
- const GridMesh::Grid &g = mesh->grid(j);
- for (unsigned int y=0; y<g.resY-1u; y+=2)
- for (unsigned int x=0; x<g.resX-1u; x+=2)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(g,x,y,bounds)) continue; // get bounds of subgrid
- const PrimRef prim(bounds,(unsigned)geomID,(unsigned)p_index);
- pinfo.add_center2(prim);
- sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
- prims[p_index++] = prim;
- }
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- assert(pinfo.size() == numPrimitives);
- }
- else
- {
- ParallelPrefixSumState<PrimInfo> pstate;
- /* iterate over all grids in a single mesh */
- pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j)) continue;
- BBox3fa bounds = empty;
- const PrimRef prim(bounds,geomID_,unsigned(j));
- pinfo.add_center2(prim,mesh->getNumSubGrids(j));
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- numPrimitives = pinfo.size();
- /* resize arrays */
- sgrids.resize(numPrimitives);
- prims.resize(numPrimitives);
-
- /* second run to fill primrefs and SubGridBuildData arrays */
- pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
- {
-
- size_t p_index = base.size();
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j)) continue;
- const GridMesh::Grid &g = mesh->grid(j);
- for (unsigned int y=0; y<g.resY-1u; y+=2)
- for (unsigned int x=0; x<g.resX-1u; x+=2)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(g,x,y,bounds)) continue; // get bounds of subgrid
- const PrimRef prim(bounds,geomID_,unsigned(p_index));
- pinfo.add_center2(prim);
- sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
- prims[p_index++] = prim;
- }
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- }
-
- /* no primitives */
- if (numPrimitives == 0) {
- bvh->clear();
- prims.clear();
- sgrids.clear();
- return;
- }
-
- double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + "BuilderSAH");
-
- /* create primref array */
- settings.primrefarrayalloc = numPrimitives/1000;
- if (settings.primrefarrayalloc < 1000)
- settings.primrefarrayalloc = inf;
-
- /* enable os_malloc for two level build */
- if (mesh)
- bvh->alloc.setOSallocation(true);
-
- /* initialize allocator */
- const size_t node_bytes = numPrimitives*sizeof(typename BVH::AABBNodeMB)/(4*N);
- const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
-
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
-
- /* pinfo might has zero size due to invalid geometry */
- if (unlikely(pinfo.size() == 0))
- {
- bvh->clear();
- sgrids.clear();
- prims.clear();
- return;
- }
-
- /* call BVH builder */
- NodeRef root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeafGrid<N,SubGridQBVHN<N>>(bvh,sgrids.data()),bvh->scene->progressInterface,prims.data(),pinfo,settings);
- bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
- bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
-
- /* clear temporary array */
- sgrids.clear();
-
- /* if we allocated using the primrefarray we have to keep it alive */
- if (settings.primrefarrayalloc != size_t(inf))
- bvh->alloc.share(prims);
-
- /* for static geometries we can do some cleanups */
- else if (scene && scene->isStaticAccel()) {
- prims.clear();
- }
- bvh->cleanup();
- bvh->postBuild(t0);
- }
-
- void clear() {
- prims.clear();
- }
- };
-
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4v>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH4Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4i>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
-
- Builder* BVH4Triangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH4Triangle4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4v>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH4Triangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type,true); }
-
-
- Builder* BVH4QuantizedTriangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
-#if defined(__AVX__)
- Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH8Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4v>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH8Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4i>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
-
- Builder* BVH8Triangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH8Triangle4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4v>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH8Triangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type,true); }
- Builder* BVH8QuantizedTriangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
- Builder* BVH8QuantizedTriangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Triangle4>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
-
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_QUAD)
- Builder* BVH4Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Quad4v>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
- Builder* BVH4Quad4iMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Quad4i>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
- Builder* BVH4Quad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Quad4v>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
- Builder* BVH4Quad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type,true); }
- Builder* BVH4QuantizedQuad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Quad4v>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
- Builder* BVH4QuantizedQuad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
-
-#if defined(__AVX__)
- Builder* BVH8Quad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Quad4v>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
- Builder* BVH8Quad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type,true); }
- Builder* BVH8QuantizedQuad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Quad4v>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
- Builder* BVH8QuantizedQuad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
- Builder* BVH8Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Quad4v>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
-
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_USER)
-
- Builder* BVH4VirtualSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
- int minLeafSize = scene->device->object_accel_min_leaf_size;
- int maxLeafSize = scene->device->object_accel_max_leaf_size;
- return new BVHNBuilderSAH<4,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,UserGeometry::geom_type);
- }
-
- Builder* BVH4VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) {
- return new BVHNBuilderSAH<4,Object>((BVH4*)bvh,mesh,geomID,4,1.0f,1,inf,UserGeometry::geom_type);
- }
-#if defined(__AVX__)
-
- Builder* BVH8VirtualSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
- int minLeafSize = scene->device->object_accel_min_leaf_size;
- int maxLeafSize = scene->device->object_accel_max_leaf_size;
- return new BVHNBuilderSAH<8,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,UserGeometry::geom_type);
- }
-
- Builder* BVH8VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) {
- return new BVHNBuilderSAH<8,Object>((BVH8*)bvh,mesh,geomID,8,1.0f,1,inf,UserGeometry::geom_type);
- }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- Builder* BVH4InstanceSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderSAH<4,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }
- Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) {
- return new BVHNBuilderSAH<4,InstancePrimitive>((BVH4*)bvh,mesh,geomID,4,1.0f,1,inf,gtype);
- }
-#if defined(__AVX__)
- Builder* BVH8InstanceSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderSAH<8,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }
- Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) {
- return new BVHNBuilderSAH<8,InstancePrimitive>((BVH8*)bvh,mesh,geomID,8,1.0f,1,inf,gtype);
- }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_GRID)
- Builder* BVH4GridMeshBuilderSAH (void* bvh, GridMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAHGrid<4>((BVH4*)bvh,mesh,geomID,4,1.0f,4,4,mode); }
- Builder* BVH4GridSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4,mode); } // FIXME: check whether cost factors are correct
-
-#if defined(__AVX__)
- Builder* BVH8GridMeshBuilderSAH (void* bvh, GridMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAHGrid<8>((BVH8*)bvh,mesh,geomID,8,1.0f,8,8,mode); }
- Builder* BVH8GridSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8,mode); } // FIXME: check whether cost factors are correct
-#endif
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah_mb.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah_mb.cpp
deleted file mode 100644
index 9c01553ec6..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah_mb.cpp
+++ /dev/null
@@ -1,705 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh.h"
-#include "bvh_builder.h"
-#include "../builders/bvh_builder_msmblur.h"
-
-#include "../builders/primrefgen.h"
-#include "../builders/splitter.h"
-
-#include "../geometry/linei.h"
-#include "../geometry/triangle.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/trianglev_mb.h"
-#include "../geometry/trianglei.h"
-#include "../geometry/quadv.h"
-#include "../geometry/quadi.h"
-#include "../geometry/object.h"
-#include "../geometry/instance.h"
-#include "../geometry/subgrid.h"
-
-#include "../common/state.h"
-
-// FIXME: remove after removing BVHNBuilderMBlurRootTimeSplitsSAH
-#include "../../common/algorithms/parallel_for_for.h"
-#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
-
-
-namespace embree
-{
- namespace isa
- {
-
-#if 0
- template<int N, typename Primitive>
- struct CreateMBlurLeaf
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecordMB NodeRecordMB;
-
- __forceinline CreateMBlurLeaf (BVH* bvh, PrimRef* prims, size_t time) : bvh(bvh), prims(prims), time(time) {}
-
- __forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
- {
- size_t items = Primitive::blocks(set.size());
- size_t start = set.begin();
- for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
- Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
- NodeRef node = bvh->encodeLeaf((char*)accel,items);
-
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<items; i++)
- allBounds.extend(accel[i].fillMB(prims, start, set.end(), bvh->scene, time));
-
- return NodeRecordMB(node,allBounds);
- }
-
- BVH* bvh;
- PrimRef* prims;
- size_t time;
- };
-#endif
-
- template<int N, typename Mesh, typename Primitive>
- struct CreateMSMBlurLeaf
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
-
- __forceinline CreateMSMBlurLeaf (BVH* bvh) : bvh(bvh) {}
-
- __forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
- {
- size_t items = Primitive::blocks(current.prims.size());
- size_t start = current.prims.begin();
- size_t end = current.prims.end();
- for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
- Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteNodeAlignment);
- NodeRef node = bvh->encodeLeaf((char*)accel,items);
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<items; i++)
- allBounds.extend(accel[i].fillMB(current.prims.prims->data(), start, current.prims.end(), bvh->scene, current.prims.time_range));
- return NodeRecordMB4D(node,allBounds,current.prims.time_range);
- }
-
- BVH* bvh;
- };
-
- /* Motion blur BVH with 4D nodes and internal time splits */
- template<int N, typename Mesh, typename Primitive>
- struct BVHNBuilderMBlurSAH : public Builder
- {
- typedef BVHN<N> BVH;
- typedef typename BVHN<N>::NodeRef NodeRef;
- typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
- typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;
-
- BVH* bvh;
- Scene* scene;
- const size_t sahBlockSize;
- const float intCost;
- const size_t minLeafSize;
- const size_t maxLeafSize;
- const Geometry::GTypeMask gtype_;
-
- BVHNBuilderMBlurSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
- : bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks)), gtype_(gtype) {}
-
- void build()
- {
- /* skip build for empty scene */
- const size_t numPrimitives = scene->getNumPrimitives(gtype_,true);
- if (numPrimitives == 0) { bvh->clear(); return; }
-
- double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAH");
-
-#if PROFILE
- profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
-#endif
-
- //const size_t numTimeSteps = scene->getNumTimeSteps<typename Mesh::type_t,true>();
- //const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
-
- /*if (numTimeSegments == 1)
- buildSingleSegment(numPrimitives);
- else*/
- buildMultiSegment(numPrimitives);
-
-#if PROFILE
- });
-#endif
-
- /* clear temporary data for static geometry */
- bvh->cleanup();
- bvh->postBuild(t0);
- }
-
-#if 0 // No longer compatible when time_ranges are present for geometries. Would have to create temporal nodes sometimes, and put only a single geometry into leaf.
- void buildSingleSegment(size_t numPrimitives)
- {
- /* create primref array */
- mvector<PrimRef> prims(scene->device,numPrimitives);
- const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,prims,bvh->scene->progressInterface,0);
- /* early out if no valid primitives */
- if (pinfo.size() == 0) { bvh->clear(); return; }
- /* estimate acceleration structure size */
- const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);
- const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
-
- /* settings for BVH build */
- GeneralBVHBuilder::Settings settings;
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxBuildDepthLeaf;
- settings.logBlockSize = bsr(sahBlockSize);
- settings.minLeafSize = min(minLeafSize,maxLeafSize);
- settings.maxLeafSize = maxLeafSize;
- settings.travCost = travCost;
- settings.intCost = intCost;
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
-
- /* build hierarchy */
- auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>
- (typename BVH::CreateAlloc(bvh),typename BVH::AABBNodeMB::Create(),typename BVH::AABBNodeMB::Set(),
- CreateMBlurLeaf<N,Primitive>(bvh,prims.data(),0),bvh->scene->progressInterface,
- prims.data(),pinfo,settings);
-
- bvh->set(root.ref,root.lbounds,pinfo.size());
- }
-#endif
-
- void buildMultiSegment(size_t numPrimitives)
- {
- /* create primref array */
- mvector<PrimRefMB> prims(scene->device,numPrimitives);
- PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,prims,bvh->scene->progressInterface);
-
- /* early out if no valid primitives */
- if (pinfo.size() == 0) { bvh->clear(); return; }
-
- /* estimate acceleration structure size */
- const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);
- const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(Primitive));
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
-
- /* settings for BVH build */
- BVHBuilderMSMBlur::Settings settings;
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxDepth;
- settings.logBlockSize = bsr(sahBlockSize);
- settings.minLeafSize = min(minLeafSize,maxLeafSize);
- settings.maxLeafSize = maxLeafSize;
- settings.travCost = travCost;
- settings.intCost = intCost;
- settings.singleLeafTimeSegment = Primitive::singleTimeSegment;
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
-
- /* build hierarchy */
- auto root =
- BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
- RecalculatePrimRef<Mesh>(scene),
- typename BVH::CreateAlloc(bvh),
- typename BVH::AABBNodeMB4D::Create(),
- typename BVH::AABBNodeMB4D::Set(),
- CreateMSMBlurLeaf<N,Mesh,Primitive>(bvh),
- bvh->scene->progressInterface,
- settings);
-
- bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
- }
-
- void clear() {
- }
- };
-
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
- struct GridRecalculatePrimRef
- {
- Scene* scene;
- const SubGridBuildData * const sgrids;
-
- __forceinline GridRecalculatePrimRef (Scene* scene, const SubGridBuildData * const sgrids)
- : scene(scene), sgrids(sgrids) {}
-
- __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const
- {
- const unsigned int geomID = prim.geomID();
- const GridMesh* mesh = scene->get<GridMesh>(geomID);
- const unsigned int buildID = prim.primID();
- const SubGridBuildData &subgrid = sgrids[buildID];
- const unsigned int primID = subgrid.primID;
- const size_t x = subgrid.x();
- const size_t y = subgrid.y();
- const LBBox3fa lbounds = mesh->linearBounds(mesh->grid(primID),x,y,time_range);
- const unsigned num_time_segments = mesh->numTimeSegments();
- const range<int> tbounds = mesh->timeSegmentRange(time_range);
- return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, num_time_segments, geomID, buildID);
- }
-
- __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
- const unsigned int geomID = prim.geomID();
- const GridMesh* mesh = scene->get<GridMesh>(geomID);
- const unsigned int buildID = prim.primID();
- const SubGridBuildData &subgrid = sgrids[buildID];
- const unsigned int primID = subgrid.primID;
- const size_t x = subgrid.x();
- const size_t y = subgrid.y();
- return mesh->linearBounds(mesh->grid(primID),x,y,time_range);
- }
-
- };
-
- template<int N>
- struct CreateMSMBlurLeafGrid
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
-
- __forceinline CreateMSMBlurLeafGrid (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids) : scene(scene), bvh(bvh), sgrids(sgrids) {}
-
- __forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
- {
- const size_t items = current.prims.size();
- const size_t start = current.prims.begin();
-
- const PrimRefMB* prims = current.prims.prims->data();
- /* collect all subsets with unique geomIDs */
- assert(items <= N);
- unsigned int geomIDs[N];
- unsigned int num_geomIDs = 1;
- geomIDs[0] = prims[start].geomID();
-
- for (size_t i=1;i<items;i++)
- {
- bool found = false;
- const unsigned int new_geomID = prims[start+i].geomID();
- for (size_t j=0;j<num_geomIDs;j++)
- if (new_geomID == geomIDs[j])
- { found = true; break; }
- if (!found)
- geomIDs[num_geomIDs++] = new_geomID;
- }
-
- /* allocate all leaf memory in one single block */
- SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);
- typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);
-
- LBBox3fa allBounds = empty;
-
- for (size_t g=0;g<num_geomIDs;g++)
- {
- const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);
- unsigned int x[N];
- unsigned int y[N];
- unsigned int primID[N];
- BBox3fa bounds0[N];
- BBox3fa bounds1[N];
- unsigned int pos = 0;
- for (size_t i=0;i<items;i++)
- {
- if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
-
- const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];
- x[pos] = sgrid_bd.sx;
- y[pos] = sgrid_bd.sy;
- primID[pos] = sgrid_bd.primID;
- const size_t x = sgrid_bd.x();
- const size_t y = sgrid_bd.y();
- LBBox3fa newBounds = mesh->linearBounds(mesh->grid(sgrid_bd.primID),x,y,current.prims.time_range);
- allBounds.extend(newBounds);
- bounds0[pos] = newBounds.bounds0;
- bounds1[pos] = newBounds.bounds1;
- pos++;
- }
- assert(pos <= N);
- new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],current.prims.time_range.lower,1.0f/current.prims.time_range.size(),pos);
- }
- return NodeRecordMB4D(node,allBounds,current.prims.time_range);
- }
-
- Scene *scene;
- BVH* bvh;
- const SubGridBuildData * const sgrids;
- };
-
-#if 0
- template<int N>
- struct CreateLeafGridMB
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::NodeRecordMB NodeRecordMB;
-
- __forceinline CreateLeafGridMB (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids)
- : scene(scene), bvh(bvh), sgrids(sgrids) {}
-
- __forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
- {
- const size_t items = set.size();
- const size_t start = set.begin();
-
- /* collect all subsets with unique geomIDs */
- assert(items <= N);
- unsigned int geomIDs[N];
- unsigned int num_geomIDs = 1;
- geomIDs[0] = prims[start].geomID();
-
- for (size_t i=1;i<items;i++)
- {
- bool found = false;
- const unsigned int new_geomID = prims[start+i].geomID();
- for (size_t j=0;j<num_geomIDs;j++)
- if (new_geomID == geomIDs[j])
- { found = true; break; }
- if (!found)
- geomIDs[num_geomIDs++] = new_geomID;
- }
-
- /* allocate all leaf memory in one single block */
- SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);
- typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);
-
- LBBox3fa allBounds = empty;
-
- for (size_t g=0;g<num_geomIDs;g++)
- {
- const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);
-
- unsigned int x[N];
- unsigned int y[N];
- unsigned int primID[N];
- BBox3fa bounds0[N];
- BBox3fa bounds1[N];
- unsigned int pos = 0;
- for (size_t i=0;i<items;i++)
- {
- if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
-
- const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];
- x[pos] = sgrid_bd.sx;
- y[pos] = sgrid_bd.sy;
- primID[pos] = sgrid_bd.primID;
- const size_t x = sgrid_bd.x();
- const size_t y = sgrid_bd.y();
- bool MAYBE_UNUSED valid0 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,0,bounds0[pos]);
- bool MAYBE_UNUSED valid1 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,1,bounds1[pos]);
- assert(valid0);
- assert(valid1);
- allBounds.extend(LBBox3fa(bounds0[pos],bounds1[pos]));
- pos++;
- }
- new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],0.0f,1.0f,pos);
- }
- return NodeRecordMB(node,allBounds);
- }
-
- Scene *scene;
- BVH* bvh;
- const SubGridBuildData * const sgrids;
- };
-#endif
-
-
- /* Motion blur BVH with 4D nodes and internal time splits */
- template<int N>
- struct BVHNBuilderMBlurSAHGrid : public Builder
- {
- typedef BVHN<N> BVH;
- typedef typename BVHN<N>::NodeRef NodeRef;
- typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
- typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;
-
- BVH* bvh;
- Scene* scene;
- const size_t sahBlockSize;
- const float intCost;
- const size_t minLeafSize;
- const size_t maxLeafSize;
- mvector<SubGridBuildData> sgrids;
-
-
- BVHNBuilderMBlurSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize)
- : bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,BVH::maxLeafBlocks)), sgrids(scene->device,0) {}
-
-
- PrimInfo createPrimRefArrayMBlurGrid(Scene* scene, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
- {
- /* first run to get #primitives */
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator<GridMesh,true> iter(scene);
-
- pstate.init(iter,size_t(1024));
-
- /* iterate over all meshes in the scene */
- PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
-
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j,range<size_t>(0,1))) continue;
- BBox3fa bounds = empty;
- const PrimRef prim(bounds,unsigned(geomID),unsigned(j));
- pinfo.add_center2(prim,mesh->getNumSubGrids(j));
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- size_t numPrimitives = pinfo.size();
- if (numPrimitives == 0) return pinfo;
-
- /* resize arrays */
- sgrids.resize(numPrimitives);
- prims.resize(numPrimitives);
-
- /* second run to fill primrefs and SubGridBuildData arrays */
- pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
-
- k = base.size();
- size_t p_index = k;
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- const GridMesh::Grid &g = mesh->grid(j);
- if (!mesh->valid(j,range<size_t>(0,1))) continue;
-
- for (unsigned int y=0; y<g.resY-1u; y+=2)
- for (unsigned int x=0; x<g.resX-1u; x+=2)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(g,x,y,itime,bounds)) continue; // get bounds of subgrid
- const PrimRef prim(bounds,unsigned(geomID),unsigned(p_index));
- pinfo.add_center2(prim);
- sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
- prims[p_index++] = prim;
- }
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- assert(pinfo.size() == numPrimitives);
- return pinfo;
- }
-
- PrimInfoMB createPrimRefArrayMSMBlurGrid(Scene* scene, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f))
- {
- /* first run to get #primitives */
- ParallelForForPrefixSumState<PrimInfoMB> pstate;
- Scene::Iterator<GridMesh,true> iter(scene);
-
- pstate.init(iter,size_t(1024));
- /* iterate over all meshes in the scene */
- PrimInfoMB pinfoMB = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t /*geomID*/) -> PrimInfoMB {
-
- PrimInfoMB pinfoMB(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
- LBBox3fa bounds(empty);
- PrimInfoMB gridMB(0,mesh->getNumSubGrids(j));
- pinfoMB.merge(gridMB);
- }
- return pinfoMB;
- }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
-
- size_t numPrimitives = pinfoMB.size();
- if (numPrimitives == 0) return pinfoMB;
-
- /* resize arrays */
- sgrids.resize(numPrimitives);
- prims.resize(numPrimitives);
- /* second run to fill primrefs and SubGridBuildData arrays */
- pinfoMB = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
-
- k = base.size();
- size_t p_index = k;
- PrimInfoMB pinfoMB(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
- const GridMesh::Grid &g = mesh->grid(j);
-
- for (unsigned int y=0; y<g.resY-1u; y+=2)
- for (unsigned int x=0; x<g.resX-1u; x+=2)
- {
- const PrimRefMB prim(mesh->linearBounds(g,x,y,t0t1),mesh->numTimeSegments(),mesh->time_range,mesh->numTimeSegments(),unsigned(geomID),unsigned(p_index));
- pinfoMB.add_primref(prim);
- sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
- prims[p_index++] = prim;
- }
- }
- return pinfoMB;
- }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
-
- assert(pinfoMB.size() == numPrimitives);
- pinfoMB.time_range = t0t1;
- return pinfoMB;
- }
-
- void build()
- {
- /* skip build for empty scene */
- const size_t numPrimitives = scene->getNumPrimitives(GridMesh::geom_type,true);
- if (numPrimitives == 0) { bvh->clear(); return; }
-
- double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAHGrid");
-
- //const size_t numTimeSteps = scene->getNumTimeSteps<GridMesh,true>();
- //const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
- //if (numTimeSegments == 1)
- // buildSingleSegment(numPrimitives);
- //else
- buildMultiSegment(numPrimitives);
-
- /* clear temporary data for static geometry */
- bvh->cleanup();
- bvh->postBuild(t0);
- }
-
-#if 0
- void buildSingleSegment(size_t numPrimitives)
- {
- /* create primref array */
- mvector<PrimRef> prims(scene->device,numPrimitives);
- const PrimInfo pinfo = createPrimRefArrayMBlurGrid(scene,prims,bvh->scene->progressInterface,0);
- /* early out if no valid primitives */
- if (pinfo.size() == 0) { bvh->clear(); return; }
-
- /* estimate acceleration structure size */
- const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);
- //TODO: check leaf_bytes
- const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
-
- /* settings for BVH build */
- GeneralBVHBuilder::Settings settings;
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxBuildDepthLeaf;
- settings.logBlockSize = bsr(sahBlockSize);
- settings.minLeafSize = min(minLeafSize,maxLeafSize);
- settings.maxLeafSize = maxLeafSize;
- settings.travCost = travCost;
- settings.intCost = intCost;
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
-
- /* build hierarchy */
- auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>
- (typename BVH::CreateAlloc(bvh),
- typename BVH::AABBNodeMB::Create(),
- typename BVH::AABBNodeMB::Set(),
- CreateLeafGridMB<N>(scene,bvh,sgrids.data()),
- bvh->scene->progressInterface,
- prims.data(),pinfo,settings);
-
- bvh->set(root.ref,root.lbounds,pinfo.size());
- }
-#endif
-
- void buildMultiSegment(size_t numPrimitives)
- {
- /* create primref array */
- mvector<PrimRefMB> prims(scene->device,numPrimitives);
- PrimInfoMB pinfo = createPrimRefArrayMSMBlurGrid(scene,prims,bvh->scene->progressInterface);
-
- /* early out if no valid primitives */
- if (pinfo.size() == 0) { bvh->clear(); return; }
-
-
-
- GridRecalculatePrimRef recalculatePrimRef(scene,sgrids.data());
-
- /* estimate acceleration structure size */
- const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);
- //FIXME: check leaf_bytes
- //const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(SubGridQBVHN<N>));
- const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
-
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
-
- /* settings for BVH build */
- BVHBuilderMSMBlur::Settings settings;
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxDepth;
- settings.logBlockSize = bsr(sahBlockSize);
- settings.minLeafSize = min(minLeafSize,maxLeafSize);
- settings.maxLeafSize = maxLeafSize;
- settings.travCost = travCost;
- settings.intCost = intCost;
- settings.singleLeafTimeSegment = false;
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
-
- /* build hierarchy */
- auto root =
- BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
- recalculatePrimRef,
- typename BVH::CreateAlloc(bvh),
- typename BVH::AABBNodeMB4D::Create(),
- typename BVH::AABBNodeMB4D::Set(),
- CreateMSMBlurLeafGrid<N>(scene,bvh,sgrids.data()),
- bvh->scene->progressInterface,
- settings);
- bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
- }
-
- void clear() {
- }
- };
-
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- Builder* BVH4Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
- Builder* BVH4Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4vMB>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
-#if defined(__AVX__)
- Builder* BVH8Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
- Builder* BVH8Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4vMB>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_QUAD)
- Builder* BVH4Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,QuadMesh,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); }
-#if defined(__AVX__)
- Builder* BVH8Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,QuadMesh,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_USER)
- Builder* BVH4VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
- int minLeafSize = scene->device->object_accel_mb_min_leaf_size;
- int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;
- return new BVHNBuilderMBlurSAH<4,UserGeometry,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);
- }
-#if defined(__AVX__)
- Builder* BVH8VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
- int minLeafSize = scene->device->object_accel_mb_min_leaf_size;
- int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;
- return new BVHNBuilderMBlurSAH<8,UserGeometry,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);
- }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- Builder* BVH4InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }
-#if defined(__AVX__)
- Builder* BVH8InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_GRID)
- Builder* BVH4GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4); }
-#if defined(__AVX__)
- Builder* BVH8GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8); }
-#endif
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah_spatial.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah_spatial.cpp
deleted file mode 100644
index 285b38c39d..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_sah_spatial.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh.h"
-#include "bvh_builder.h"
-
-#include "../builders/primrefgen.h"
-#include "../builders/primrefgen_presplit.h"
-#include "../builders/splitter.h"
-
-#include "../geometry/linei.h"
-#include "../geometry/triangle.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/trianglev_mb.h"
-#include "../geometry/trianglei.h"
-#include "../geometry/quadv.h"
-#include "../geometry/quadi.h"
-#include "../geometry/object.h"
-#include "../geometry/instance.h"
-#include "../geometry/subgrid.h"
-
-#include "../common/state.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int N, typename Primitive>
- struct CreateLeafSpatial
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
-
- __forceinline CreateLeafSpatial (BVH* bvh) : bvh(bvh) {}
-
- __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
- {
- size_t n = set.size();
- size_t items = Primitive::blocks(n);
- size_t start = set.begin();
- Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
- typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
- for (size_t i=0; i<items; i++) {
- accel[i].fill(prims,start,set.end(),bvh->scene);
- }
- return node;
- }
-
- BVH* bvh;
- };
-
- template<int N, typename Mesh, typename Primitive, typename Splitter>
- struct BVHNBuilderFastSpatialSAH : public Builder
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- BVH* bvh;
- Scene* scene;
- Mesh* mesh;
- mvector<PrimRef> prims0;
- GeneralBVHBuilder::Settings settings;
- const float splitFactor;
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
- unsigned int numPreviousPrimitives = 0;
-
- BVHNBuilderFastSpatialSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
- : bvh(bvh), scene(scene), mesh(nullptr), prims0(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD),
- splitFactor(scene->device->max_spatial_split_replications) {}
-
- BVHNBuilderFastSpatialSAH (BVH* bvh, Mesh* mesh, const unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
- : bvh(bvh), scene(nullptr), mesh(mesh), prims0(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD),
- splitFactor(scene->device->max_spatial_split_replications), geomID_(geomID) {}
-
- // FIXME: shrink bvh->alloc in destructor here and in other builders too
-
- void build()
- {
- /* we reset the allocator when the mesh size changed */
- if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
- bvh->alloc.clear();
- }
-
- /* skip build for empty scene */
- const size_t numOriginalPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(Mesh::geom_type,false);
- numPreviousPrimitives = numOriginalPrimitives;
- if (numOriginalPrimitives == 0) {
- prims0.clear();
- bvh->clear();
- return;
- }
-
- const unsigned int maxGeomID = mesh ? geomID_ : scene->getMaxGeomID<Mesh,false>();
- const bool usePreSplits = scene->device->useSpatialPreSplits || (maxGeomID >= ((unsigned int)1 << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)));
- double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + (usePreSplits ? "BuilderFastSpatialPresplitSAH" : "BuilderFastSpatialSAH"));
-
- /* create primref array */
- const size_t numSplitPrimitives = max(numOriginalPrimitives,size_t(splitFactor*numOriginalPrimitives));
- prims0.resize(numSplitPrimitives);
-
- /* enable os_malloc for two level build */
- if (mesh)
- bvh->alloc.setOSallocation(true);
-
- NodeRef root(0);
- PrimInfo pinfo;
-
-
- if (likely(usePreSplits))
- {
- /* spatial presplit SAH BVH builder */
- pinfo = mesh ?
- createPrimRefArray_presplit<Mesh,Splitter>(mesh,maxGeomID,numOriginalPrimitives,prims0,bvh->scene->progressInterface) :
- createPrimRefArray_presplit<Mesh,Splitter>(scene,Mesh::geom_type,false,numOriginalPrimitives,prims0,bvh->scene->progressInterface);
-
- const size_t node_bytes = pinfo.size()*sizeof(typename BVH::AABBNode)/(4*N);
- const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
-
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxBuildDepthLeaf;
-
- /* call BVH builder */
- root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeafSpatial<N,Primitive>(bvh),bvh->scene->progressInterface,prims0.data(),pinfo,settings);
- }
- else
- {
- /* standard spatial split SAH BVH builder */
- pinfo = mesh ?
- createPrimRefArray(mesh,geomID_,/*numSplitPrimitives,*/prims0,bvh->scene->progressInterface) :
- createPrimRefArray(scene,Mesh::geom_type,false,/*numSplitPrimitives,*/prims0,bvh->scene->progressInterface);
-
- Splitter splitter(scene);
-
- const size_t node_bytes = pinfo.size()*sizeof(typename BVH::AABBNode)/(4*N);
- const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
- settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
-
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxBuildDepthLeaf;
-
- /* call BVH builder */
- root = BVHBuilderBinnedFastSpatialSAH::build<NodeRef>(
- typename BVH::CreateAlloc(bvh),
- typename BVH::AABBNode::Create2(),
- typename BVH::AABBNode::Set2(),
- CreateLeafSpatial<N,Primitive>(bvh),
- splitter,
- bvh->scene->progressInterface,
- prims0.data(),
- numSplitPrimitives,
- pinfo,settings);
-
- /* ==================== */
- }
-
- bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
- bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
-
- /* clear temporary data for static geometry */
- if (scene && scene->isStaticAccel()) {
- prims0.clear();
- }
- bvh->cleanup();
- bvh->postBuild(t0);
- }
-
- void clear() {
- prims0.clear();
- }
- };
-
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
-
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
-
- Builder* BVH4Triangle4SceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
- Builder* BVH4Triangle4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4v,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
- Builder* BVH4Triangle4iSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4i,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
-
-#if defined(__AVX__)
- Builder* BVH8Triangle4SceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,TriangleMesh,Triangle4,TriangleSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
- Builder* BVH8Triangle4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,TriangleMesh,Triangle4v,TriangleSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_QUAD)
- Builder* BVH4Quad4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,QuadMesh,Quad4v,QuadSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
-
-#if defined(__AVX__)
- Builder* BVH8Quad4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,QuadMesh,Quad4v,QuadSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
-#endif
-
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel.cpp
deleted file mode 100644
index 1a78f347ac..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh_builder_twolevel.h"
-#include "bvh_statistics.h"
-#include "../builders/bvh_builder_sah.h"
-#include "../common/scene_line_segments.h"
-#include "../common/scene_triangle_mesh.h"
-#include "../common/scene_quad_mesh.h"
-
-#define PROFILE 0
-
-namespace embree
-{
- namespace isa
- {
- template<int N, typename Mesh, typename Primitive>
- BVHNBuilderTwoLevel<N,Mesh,Primitive>::BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder, const size_t singleThreadThreshold)
- : bvh(bvh), scene(scene), refs(scene->device,0), prims(scene->device,0), singleThreadThreshold(singleThreadThreshold), gtype(gtype), useMortonBuilder_(useMortonBuilder) {}
-
- template<int N, typename Mesh, typename Primitive>
- BVHNBuilderTwoLevel<N,Mesh,Primitive>::~BVHNBuilderTwoLevel () {
- }
-
- // ===========================================================================
- // ===========================================================================
- // ===========================================================================
-
- template<int N, typename Mesh, typename Primitive>
- void BVHNBuilderTwoLevel<N,Mesh,Primitive>::build()
- {
- /* delete some objects */
- size_t num = scene->size();
- if (num < bvh->objects.size()) {
- parallel_for(num, bvh->objects.size(), [&] (const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- builders[i].reset();
- delete bvh->objects[i]; bvh->objects[i] = nullptr;
- }
- });
- }
-
-#if PROFILE
- while(1)
-#endif
- {
- /* reset memory allocator */
- bvh->alloc.reset();
-
- /* skip build for empty scene */
- const size_t numPrimitives = scene->getNumPrimitives(gtype,false);
-
- if (numPrimitives == 0) {
- prims.resize(0);
- bvh->set(BVH::emptyNode,empty,0);
- return;
- }
-
- /* calculate the size of the entire BVH */
- const size_t numLeafBlocks = Primitive::blocks(numPrimitives);
- const size_t node_bytes = 2*numLeafBlocks*sizeof(typename BVH::AABBNode)/N;
- const size_t leaf_bytes = size_t(1.2*numLeafBlocks*sizeof(Primitive));
- bvh->alloc.init_estimate(node_bytes+leaf_bytes);
-
- double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderTwoLevel");
-
- /* resize object array if scene got larger */
- if (bvh->objects.size() < num) bvh->objects.resize(num);
- if (builders.size() < num) builders.resize(num);
- resizeRefsList ();
- nextRef.store(0);
-
- /* create acceleration structures */
- parallel_for(size_t(0), num, [&] (const range<size_t>& r)
- {
- for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
- {
- Mesh* mesh = scene->getSafe<Mesh>(objectID);
-
- /* ignore meshes we do not support */
- if (mesh == nullptr || mesh->numTimeSteps != 1)
- continue;
-
- if (isSmallGeometry(mesh)) {
- setupSmallBuildRefBuilder (objectID, mesh);
- } else {
- setupLargeBuildRefBuilder (objectID, mesh);
- }
- }
- });
-
- /* parallel build of acceleration structures */
- parallel_for(size_t(0), num, [&] (const range<size_t>& r)
- {
- for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
- {
- /* ignore if no triangle mesh or not enabled */
- Mesh* mesh = scene->getSafe<Mesh>(objectID);
- if (mesh == nullptr || !mesh->isEnabled() || mesh->numTimeSteps != 1)
- continue;
-
- builders[objectID]->attachBuildRefs (this);
- }
- });
-
-
-#if PROFILE
- double d0 = getSeconds();
-#endif
- /* fast path for single geometry scenes */
- if (nextRef == 1) {
- bvh->set(refs[0].node,LBBox3fa(refs[0].bounds()),numPrimitives);
- }
-
- else
- {
- /* open all large nodes */
- refs.resize(nextRef);
-
- /* this probably needs some more tuning */
- const size_t extSize = max(max((size_t)SPLIT_MIN_EXT_SPACE,refs.size()*SPLIT_MEMORY_RESERVE_SCALE),size_t((float)numPrimitives / SPLIT_MEMORY_RESERVE_FACTOR));
-
-#if !ENABLE_DIRECT_SAH_MERGE_BUILDER
-
-#if ENABLE_OPEN_SEQUENTIAL
- open_sequential(extSize);
-#endif
- /* compute PrimRefs */
- prims.resize(refs.size());
-#endif
-
-#if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL
- tbb::task_arena limited(min(32,(int)TaskScheduler::threadCount()));
- limited.execute([&]
-#endif
- {
-#if ENABLE_DIRECT_SAH_MERGE_BUILDER
-
- const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(), PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {
-
- PrimInfo pinfo(empty);
- for (size_t i=r.begin(); i<r.end(); i++) {
- pinfo.add_center2(refs[i]);
- }
- return pinfo;
- }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
-
-#else
- const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(), PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {
-
- PrimInfo pinfo(empty);
- for (size_t i=r.begin(); i<r.end(); i++) {
- pinfo.add_center2(refs[i]);
- prims[i] = PrimRef(refs[i].bounds(),(size_t)refs[i].node);
- }
- return pinfo;
- }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
-#endif
-
- /* skip if all objects where empty */
- if (pinfo.size() == 0)
- bvh->set(BVH::emptyNode,empty,0);
-
- /* otherwise build toplevel hierarchy */
- else
- {
- /* settings for BVH build */
- GeneralBVHBuilder::Settings settings;
- settings.branchingFactor = N;
- settings.maxDepth = BVH::maxBuildDepthLeaf;
- settings.logBlockSize = bsr(N);
- settings.minLeafSize = 1;
- settings.maxLeafSize = 1;
- settings.travCost = 1.0f;
- settings.intCost = 1.0f;
- settings.singleThreadThreshold = singleThreadThreshold;
-
-#if ENABLE_DIRECT_SAH_MERGE_BUILDER
-
- refs.resize(extSize);
-
- NodeRef root = BVHBuilderBinnedOpenMergeSAH::build<NodeRef,BuildRef>(
- typename BVH::CreateAlloc(bvh),
- typename BVH::AABBNode::Create2(),
- typename BVH::AABBNode::Set2(),
-
- [&] (const BuildRef* refs, const range<size_t>& range, const FastAllocator::CachedAllocator& alloc) -> NodeRef {
- assert(range.size() == 1);
- return (NodeRef) refs[range.begin()].node;
- },
- [&] (BuildRef &bref, BuildRef *refs) -> size_t {
- return openBuildRef(bref,refs);
- },
- [&] (size_t dn) { bvh->scene->progressMonitor(0); },
- refs.data(),extSize,pinfo,settings);
-#else
- NodeRef root = BVHBuilderBinnedSAH::build<NodeRef>(
- typename BVH::CreateAlloc(bvh),
- typename BVH::AABBNode::Create2(),
- typename BVH::AABBNode::Set2(),
-
- [&] (const PrimRef* prims, const range<size_t>& range, const FastAllocator::CachedAllocator& alloc) -> NodeRef {
- assert(range.size() == 1);
- return (NodeRef) prims[range.begin()].ID();
- },
- [&] (size_t dn) { bvh->scene->progressMonitor(0); },
- prims.data(),pinfo,settings);
-#endif
-
-
- bvh->set(root,LBBox3fa(pinfo.geomBounds),numPrimitives);
- }
- }
-#if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL
- );
-#endif
-
- }
-
- bvh->alloc.cleanup();
- bvh->postBuild(t0);
-#if PROFILE
- double d1 = getSeconds();
- std::cout << "TOP_LEVEL OPENING/REBUILD TIME " << 1000.0*(d1-d0) << " ms" << std::endl;
-#endif
- }
-
- }
-
- template<int N, typename Mesh, typename Primitive>
- void BVHNBuilderTwoLevel<N,Mesh,Primitive>::deleteGeometry(size_t geomID)
- {
- if (geomID >= bvh->objects.size()) return;
- if (builders[geomID]) builders[geomID].reset();
- delete bvh->objects [geomID]; bvh->objects [geomID] = nullptr;
- }
-
- template<int N, typename Mesh, typename Primitive>
- void BVHNBuilderTwoLevel<N,Mesh,Primitive>::clear()
- {
- for (size_t i=0; i<bvh->objects.size(); i++)
- if (bvh->objects[i]) bvh->objects[i]->clear();
-
- for (size_t i=0; i<builders.size(); i++)
- if (builders[i]) builders[i].reset();
-
- refs.clear();
- }
-
- template<int N, typename Mesh, typename Primitive>
- void BVHNBuilderTwoLevel<N,Mesh,Primitive>::open_sequential(const size_t extSize)
- {
- if (refs.size() == 0)
- return;
-
- refs.reserve(extSize);
-
-#if 1
- for (size_t i=0;i<refs.size();i++)
- {
- NodeRef ref = refs[i].node;
- if (ref.isAABBNode())
- BVH::prefetch(ref);
- }
-#endif
-
- std::make_heap(refs.begin(),refs.end());
- while (refs.size()+N-1 <= extSize)
- {
- std::pop_heap (refs.begin(),refs.end());
- NodeRef ref = refs.back().node;
- if (ref.isLeaf()) break;
- refs.pop_back();
-
- AABBNode* node = ref.getAABBNode();
- for (size_t i=0; i<N; i++) {
- if (node->child(i) == BVH::emptyNode) continue;
- refs.push_back(BuildRef(node->bounds(i),node->child(i)));
-
-#if 1
- NodeRef ref_pre = node->child(i);
- if (ref_pre.isAABBNode())
- ref_pre.prefetch();
-#endif
- std::push_heap (refs.begin(),refs.end());
- }
- }
- }
-
- template<int N, typename Mesh, typename Primitive>
- void BVHNBuilderTwoLevel<N,Mesh,Primitive>::setupSmallBuildRefBuilder (size_t objectID, Mesh const * const /*mesh*/)
- {
- if (builders[objectID] == nullptr || // new mesh
- dynamic_cast<RefBuilderSmall*>(builders[objectID].get()) == nullptr) // size change resulted in large->small change
- {
- builders[objectID].reset (new RefBuilderSmall(objectID));
- }
- }
-
- template<int N, typename Mesh, typename Primitive>
- void BVHNBuilderTwoLevel<N,Mesh,Primitive>::setupLargeBuildRefBuilder (size_t objectID, Mesh const * const mesh)
- {
- if (bvh->objects[objectID] == nullptr || // new mesh
- builders[objectID]->meshQualityChanged (mesh->quality) || // changed build quality
- dynamic_cast<RefBuilderLarge*>(builders[objectID].get()) == nullptr) // size change resulted in small->large change
- {
- Builder* builder = nullptr;
- delete bvh->objects[objectID];
- createMeshAccel(objectID, builder);
- builders[objectID].reset (new RefBuilderLarge(objectID, builder, mesh->quality));
- }
- }
-
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- Builder* BVH4BuilderTwoLevelTriangle4MeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
- }
- Builder* BVH4BuilderTwoLevelTriangle4vMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4v>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
- }
- Builder* BVH4BuilderTwoLevelTriangle4iMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
- }
-#endif
-
-#if defined(EMBREE_GEOMETRY_QUAD)
- Builder* BVH4BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<4,QuadMesh,Quad4v>((BVH4*)bvh,scene,QuadMesh::geom_type,useMortonBuilder);
- }
-#endif
-
-#if defined(EMBREE_GEOMETRY_USER)
- Builder* BVH4BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<4,UserGeometry,Object>((BVH4*)bvh,scene,UserGeometry::geom_type,useMortonBuilder);
- }
-#endif
-
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- Builder* BVH4BuilderTwoLevelInstanceSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,gtype,useMortonBuilder);
- }
-#endif
-
-#if defined(__AVX__)
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- Builder* BVH8BuilderTwoLevelTriangle4MeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
- }
- Builder* BVH8BuilderTwoLevelTriangle4vMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4v>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
- }
- Builder* BVH8BuilderTwoLevelTriangle4iMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
- }
-#endif
-
-#if defined(EMBREE_GEOMETRY_QUAD)
- Builder* BVH8BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<8,QuadMesh,Quad4v>((BVH8*)bvh,scene,QuadMesh::geom_type,useMortonBuilder);
- }
-#endif
-
-#if defined(EMBREE_GEOMETRY_USER)
- Builder* BVH8BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<8,UserGeometry,Object>((BVH8*)bvh,scene,UserGeometry::geom_type,useMortonBuilder);
- }
-#endif
-
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- Builder* BVH8BuilderTwoLevelInstanceSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder) {
- return new BVHNBuilderTwoLevel<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,gtype,useMortonBuilder);
- }
-#endif
-
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel.h
deleted file mode 100644
index 8f57c3b406..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel.h
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include <type_traits>
-
-#include "bvh_builder_twolevel_internal.h"
-#include "bvh.h"
-#include "../common/primref.h"
-#include "../builders/priminfo.h"
-#include "../builders/primrefgen.h"
-
-/* new open/merge builder */
-#define ENABLE_DIRECT_SAH_MERGE_BUILDER 1
-#define ENABLE_OPEN_SEQUENTIAL 0
-#define SPLIT_MEMORY_RESERVE_FACTOR 1000
-#define SPLIT_MEMORY_RESERVE_SCALE 2
-#define SPLIT_MIN_EXT_SPACE 1000
-
-namespace embree
-{
- namespace isa
- {
- template<int N, typename Mesh, typename Primitive>
- class BVHNBuilderTwoLevel : public Builder
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::AABBNode AABBNode;
- typedef typename BVH::NodeRef NodeRef;
-
- __forceinline static bool isSmallGeometry(Mesh* mesh) {
- return mesh->size() <= 4;
- }
-
- public:
-
- typedef void (*createMeshAccelTy)(Scene* scene, unsigned int geomID, AccelData*& accel, Builder*& builder);
-
- struct BuildRef : public PrimRef
- {
- public:
- __forceinline BuildRef () {}
-
- __forceinline BuildRef (const BBox3fa& bounds, NodeRef node)
- : PrimRef(bounds,(size_t)node), node(node)
- {
- if (node.isLeaf())
- bounds_area = 0.0f;
- else
- bounds_area = area(this->bounds());
- }
-
- /* used by the open/merge bvh builder */
- __forceinline BuildRef (const BBox3fa& bounds, NodeRef node, const unsigned int geomID, const unsigned int numPrimitives)
- : PrimRef(bounds,geomID,numPrimitives), node(node)
- {
- /* important for relative buildref ordering */
- if (node.isLeaf())
- bounds_area = 0.0f;
- else
- bounds_area = area(this->bounds());
- }
-
- __forceinline size_t size() const {
- return primID();
- }
-
- friend bool operator< (const BuildRef& a, const BuildRef& b) {
- return a.bounds_area < b.bounds_area;
- }
-
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const BuildRef& ref) {
- return cout << "{ lower = " << ref.lower << ", upper = " << ref.upper << ", center2 = " << ref.center2() << ", geomID = " << ref.geomID() << ", numPrimitives = " << ref.numPrimitives() << ", bounds_area = " << ref.bounds_area << " }";
- }
-
- __forceinline unsigned int numPrimitives() const { return primID(); }
-
- public:
- NodeRef node;
- float bounds_area;
- };
-
-
- __forceinline size_t openBuildRef(BuildRef &bref, BuildRef *const refs) {
- if (bref.node.isLeaf())
- {
- refs[0] = bref;
- return 1;
- }
- NodeRef ref = bref.node;
- unsigned int geomID = bref.geomID();
- unsigned int numPrims = max((unsigned int)bref.numPrimitives() / N,(unsigned int)1);
- AABBNode* node = ref.getAABBNode();
- size_t n = 0;
- for (size_t i=0; i<N; i++) {
- if (node->child(i) == BVH::emptyNode) continue;
- refs[i] = BuildRef(node->bounds(i),node->child(i),geomID,numPrims);
- n++;
- }
- assert(n > 1);
- return n;
- }
-
- /*! Constructor. */
- BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, Geometry::GTypeMask gtype = Mesh::geom_type, bool useMortonBuilder = false, const size_t singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD);
-
- /*! Destructor */
- ~BVHNBuilderTwoLevel ();
-
- /*! builder entry point */
- void build();
- void deleteGeometry(size_t geomID);
- void clear();
-
- void open_sequential(const size_t extSize);
-
- private:
-
- class RefBuilderBase {
- public:
- virtual ~RefBuilderBase () {}
- virtual void attachBuildRefs (BVHNBuilderTwoLevel* builder) = 0;
- virtual bool meshQualityChanged (RTCBuildQuality currQuality) = 0;
- };
-
- class RefBuilderSmall : public RefBuilderBase {
- public:
-
- RefBuilderSmall (size_t objectID)
- : objectID_ (objectID) {}
-
- void attachBuildRefs (BVHNBuilderTwoLevel* topBuilder) {
-
- Mesh* mesh = topBuilder->scene->template getSafe<Mesh>(objectID_);
- size_t meshSize = mesh->size();
- assert(isSmallGeometry(mesh));
-
- mvector<PrimRef> prefs(topBuilder->scene->device, meshSize);
- auto pinfo = createPrimRefArray(mesh,objectID_,prefs,topBuilder->bvh->scene->progressInterface);
-
- size_t begin=0;
- while (begin < pinfo.size())
- {
- Primitive* accel = (Primitive*) topBuilder->bvh->alloc.getCachedAllocator().malloc1(sizeof(Primitive),BVH::byteAlignment);
- typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,1);
- accel->fill(prefs.data(),begin,pinfo.size(),topBuilder->bvh->scene);
-
- /* create build primitive */
-#if ENABLE_DIRECT_SAH_MERGE_BUILDER
- topBuilder->refs[topBuilder->nextRef++] = BVHNBuilderTwoLevel::BuildRef(pinfo.geomBounds,node,(unsigned int)objectID_,1);
-#else
- topBuilder->refs[topBuilder->nextRef++] = BVHNBuilderTwoLevel::BuildRef(pinfo.geomBounds,node);
-#endif
- }
- assert(begin == pinfo.size());
- }
-
- bool meshQualityChanged (RTCBuildQuality /*currQuality*/) {
- return false;
- }
-
- size_t objectID_;
- };
-
- class RefBuilderLarge : public RefBuilderBase {
- public:
-
- RefBuilderLarge (size_t objectID, const Ref<Builder>& builder, RTCBuildQuality quality)
- : objectID_ (objectID), builder_ (builder), quality_ (quality) {}
-
- void attachBuildRefs (BVHNBuilderTwoLevel* topBuilder)
- {
- BVH* object = topBuilder->getBVH(objectID_); assert(object);
-
- /* build object if it got modified */
- if (topBuilder->isGeometryModified(objectID_))
- builder_->build();
-
- /* create build primitive */
- if (!object->getBounds().empty())
- {
-#if ENABLE_DIRECT_SAH_MERGE_BUILDER
- Mesh* mesh = topBuilder->getMesh(objectID_);
- topBuilder->refs[topBuilder->nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root,(unsigned int)objectID_,(unsigned int)mesh->size());
-#else
- topBuilder->refs[topBuilder->nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root);
-#endif
- }
- }
-
- bool meshQualityChanged (RTCBuildQuality currQuality) {
- return currQuality != quality_;
- }
-
- private:
- size_t objectID_;
- Ref<Builder> builder_;
- RTCBuildQuality quality_;
- };
-
- void setupLargeBuildRefBuilder (size_t objectID, Mesh const * const mesh);
- void setupSmallBuildRefBuilder (size_t objectID, Mesh const * const mesh);
-
- BVH* getBVH (size_t objectID) {
- return this->bvh->objects[objectID];
- }
- Mesh* getMesh (size_t objectID) {
- return this->scene->template getSafe<Mesh>(objectID);
- }
- bool isGeometryModified (size_t objectID) {
- return this->scene->isGeometryModified(objectID);
- }
-
- void resizeRefsList ()
- {
- size_t num = parallel_reduce (size_t(0), scene->size(), size_t(0),
- [this](const range<size_t>& r)->size_t {
- size_t c = 0;
- for (auto i=r.begin(); i<r.end(); ++i) {
- Mesh* mesh = scene->getSafe<Mesh>(i);
- if (mesh == nullptr || mesh->numTimeSteps != 1)
- continue;
- size_t meshSize = mesh->size();
- c += isSmallGeometry(mesh) ? Primitive::blocks(meshSize) : 1;
- }
- return c;
- },
- std::plus<size_t>()
- );
-
- if (refs.size() < num) {
- refs.resize(num);
- }
- }
-
- void createMeshAccel (size_t geomID, Builder*& builder)
- {
- bvh->objects[geomID] = new BVH(Primitive::type,scene);
- BVH* accel = bvh->objects[geomID];
- auto mesh = scene->getSafe<Mesh>(geomID);
- if (nullptr == mesh) {
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"geomID does not return correct type");
- return;
- }
-
- __internal_two_level_builder__::MeshBuilder<N,Mesh,Primitive>()(accel, mesh, geomID, this->gtype, this->useMortonBuilder_, builder);
- }
-
- using BuilderList = std::vector<std::unique_ptr<RefBuilderBase>>;
-
- BuilderList builders;
- BVH* bvh;
- Scene* scene;
- mvector<BuildRef> refs;
- mvector<PrimRef> prims;
- std::atomic<int> nextRef;
- const size_t singleThreadThreshold;
- Geometry::GTypeMask gtype;
- bool useMortonBuilder_ = false;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel_internal.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel_internal.h
deleted file mode 100644
index 1c1ae8d6a7..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_builder_twolevel_internal.h
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-#include "../geometry/triangle.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/trianglei.h"
-#include "../geometry/quadv.h"
-#include "../geometry/quadi.h"
-#include "../geometry/object.h"
-#include "../geometry/instance.h"
-
-namespace embree
-{
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4MeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4MeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4MeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshBuilderMortonGeneral,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshBuilderSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshRefitSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshBuilderMortonGeneral,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshBuilderSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshBuilderMortonGeneral,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshBuilderSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshRefitSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t)
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vMeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vMeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iMeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iMeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vMeshBuilderMortonGeneral,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vMeshBuilderSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vMeshRefitSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshBuilderMortonGeneral,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshBuilderSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshBuilderMortonGeneral,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshBuilderSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t);
- DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshRefitSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t)
-
- namespace isa
- {
-
- namespace __internal_two_level_builder__ {
-
- template<int N, typename Mesh, typename Primitive>
- struct MortonBuilder {};
- template<>
- struct MortonBuilder<4,TriangleMesh,Triangle4> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<4,TriangleMesh,Triangle4v> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<4,TriangleMesh,Triangle4i> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<4,QuadMesh,Quad4v> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<4,UserGeometry,Object> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<4,Instance,InstancePrimitive> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshBuilderMortonGeneral(bvh,mesh,gtype,geomID,0);}
- };
- template<>
- struct MortonBuilder<8,TriangleMesh,Triangle4> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<8,TriangleMesh,Triangle4v> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<8,TriangleMesh,Triangle4i> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<8,QuadMesh,Quad4v> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<8,UserGeometry,Object> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
- };
- template<>
- struct MortonBuilder<8,Instance,InstancePrimitive> {
- MortonBuilder () {}
- Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshBuilderMortonGeneral(bvh,mesh,gtype,geomID,0);}
- };
-
- template<int N, typename Mesh, typename Primitive>
- struct SAHBuilder {};
- template<>
- struct SAHBuilder<4,TriangleMesh,Triangle4> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<4,TriangleMesh,Triangle4v> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<4,TriangleMesh,Triangle4i> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<4,QuadMesh,Quad4v> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<4,UserGeometry,Object> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<4,Instance,InstancePrimitive> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshBuilderSAH(bvh,mesh,gtype,geomID,0);}
- };
- template<>
- struct SAHBuilder<8,TriangleMesh,Triangle4> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<8,TriangleMesh,Triangle4v> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<8,TriangleMesh,Triangle4i> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<8,QuadMesh,Quad4v> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<8,UserGeometry,Object> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshBuilderSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct SAHBuilder<8,Instance,InstancePrimitive> {
- SAHBuilder () {}
- Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshBuilderSAH(bvh,mesh,gtype,geomID,0);}
- };
-
- template<int N, typename Mesh, typename Primitive>
- struct RefitBuilder {};
- template<>
- struct RefitBuilder<4,TriangleMesh,Triangle4> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<4,TriangleMesh,Triangle4v> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<4,TriangleMesh,Triangle4i> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<4,QuadMesh,Quad4v> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<4,UserGeometry,Object> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<4,Instance,InstancePrimitive> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshRefitSAH(bvh,mesh,gtype,geomID,0);}
- };
- template<>
- struct RefitBuilder<8,TriangleMesh,Triangle4> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<8,TriangleMesh,Triangle4v> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<8,TriangleMesh,Triangle4i> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<8,QuadMesh,Quad4v> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<8,UserGeometry,Object> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshRefitSAH(bvh,mesh,geomID,0);}
- };
- template<>
- struct RefitBuilder<8,Instance,InstancePrimitive> {
- RefitBuilder () {}
- Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshRefitSAH(bvh,mesh,gtype,geomID,0);}
- };
-
- template<int N, typename Mesh, typename Primitive>
- struct MeshBuilder {
- MeshBuilder () {}
- void operator () (void* bvh, Mesh* mesh, size_t geomID, Geometry::GTypeMask gtype, bool useMortonBuilder, Builder*& builder) {
- if(useMortonBuilder) {
- builder = MortonBuilder<N,Mesh,Primitive>()(bvh,mesh,geomID,gtype);
- return;
- }
- switch (mesh->quality) {
- case RTC_BUILD_QUALITY_LOW: builder = MortonBuilder<N,Mesh,Primitive>()(bvh,mesh,geomID,gtype); break;
- case RTC_BUILD_QUALITY_MEDIUM:
- case RTC_BUILD_QUALITY_HIGH: builder = SAHBuilder<N,Mesh,Primitive>()(bvh,mesh,geomID,gtype); break;
- case RTC_BUILD_QUALITY_REFIT: builder = RefitBuilder<N,Mesh,Primitive>()(bvh,mesh,geomID,gtype); break;
- default: throw_RTCError(RTC_ERROR_UNKNOWN,"invalid build quality");
- }
- }
- };
- }
- }
-} \ No newline at end of file
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_collider.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_collider.cpp
deleted file mode 100644
index a27be8bae8..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_collider.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh_collider.h"
-#include "../geometry/triangle_triangle_intersector.h"
-
-namespace embree
-{
- namespace isa
- {
-#define CSTAT(x)
-
- size_t parallel_depth_threshold = 3;
- CSTAT(std::atomic<size_t> bvh_collide_traversal_steps(0));
- CSTAT(std::atomic<size_t> bvh_collide_leaf_pairs(0));
- CSTAT(std::atomic<size_t> bvh_collide_leaf_iterations(0));
- CSTAT(std::atomic<size_t> bvh_collide_prim_intersections1(0));
- CSTAT(std::atomic<size_t> bvh_collide_prim_intersections2(0));
- CSTAT(std::atomic<size_t> bvh_collide_prim_intersections3(0));
- CSTAT(std::atomic<size_t> bvh_collide_prim_intersections4(0));
- CSTAT(std::atomic<size_t> bvh_collide_prim_intersections5(0));
- CSTAT(std::atomic<size_t> bvh_collide_prim_intersections(0));
-
- struct Collision
- {
- __forceinline Collision() {}
-
- __forceinline Collision (unsigned geomID0, unsigned primID0, unsigned geomID1, unsigned primID1)
- : geomID0(geomID0), primID0(primID0), geomID1(geomID1), primID1(primID1) {}
-
- unsigned geomID0;
- unsigned primID0;
- unsigned geomID1;
- unsigned primID1;
- };
-
- template<int N>
- __forceinline size_t overlap(const BBox3fa& box0, const typename BVHN<N>::AABBNode& node1)
- {
- const vfloat<N> lower_x = max(vfloat<N>(box0.lower.x),node1.lower_x);
- const vfloat<N> lower_y = max(vfloat<N>(box0.lower.y),node1.lower_y);
- const vfloat<N> lower_z = max(vfloat<N>(box0.lower.z),node1.lower_z);
- const vfloat<N> upper_x = min(vfloat<N>(box0.upper.x),node1.upper_x);
- const vfloat<N> upper_y = min(vfloat<N>(box0.upper.y),node1.upper_y);
- const vfloat<N> upper_z = min(vfloat<N>(box0.upper.z),node1.upper_z);
- return movemask((lower_x <= upper_x) & (lower_y <= upper_y) & (lower_z <= upper_z));
- }
-
- template<int N>
- __forceinline size_t overlap(const BBox3fa& box0, const BBox<Vec3<vfloat<N>>>& box1)
- {
- const vfloat<N> lower_x = max(vfloat<N>(box0.lower.x),box1.lower.x);
- const vfloat<N> lower_y = max(vfloat<N>(box0.lower.y),box1.lower.y);
- const vfloat<N> lower_z = max(vfloat<N>(box0.lower.z),box1.lower.z);
- const vfloat<N> upper_x = min(vfloat<N>(box0.upper.x),box1.upper.x);
- const vfloat<N> upper_y = min(vfloat<N>(box0.upper.y),box1.upper.y);
- const vfloat<N> upper_z = min(vfloat<N>(box0.upper.z),box1.upper.z);
- return movemask((lower_x <= upper_x) & (lower_y <= upper_y) & (lower_z <= upper_z));
- }
-
- template<int N>
- __forceinline size_t overlap(const BBox<Vec3<vfloat<N>>>& box0, size_t i, const BBox<Vec3<vfloat<N>>>& box1)
- {
- const vfloat<N> lower_x = max(vfloat<N>(box0.lower.x[i]),box1.lower.x);
- const vfloat<N> lower_y = max(vfloat<N>(box0.lower.y[i]),box1.lower.y);
- const vfloat<N> lower_z = max(vfloat<N>(box0.lower.z[i]),box1.lower.z);
- const vfloat<N> upper_x = min(vfloat<N>(box0.upper.x[i]),box1.upper.x);
- const vfloat<N> upper_y = min(vfloat<N>(box0.upper.y[i]),box1.upper.y);
- const vfloat<N> upper_z = min(vfloat<N>(box0.upper.z[i]),box1.upper.z);
- return movemask((lower_x <= upper_x) & (lower_y <= upper_y) & (lower_z <= upper_z));
- }
-
- bool intersect_triangle_triangle (Scene* scene0, unsigned geomID0, unsigned primID0, Scene* scene1, unsigned geomID1, unsigned primID1)
- {
- CSTAT(bvh_collide_prim_intersections1++);
- const TriangleMesh* mesh0 = scene0->get<TriangleMesh>(geomID0);
- const TriangleMesh* mesh1 = scene1->get<TriangleMesh>(geomID1);
- const TriangleMesh::Triangle& tri0 = mesh0->triangle(primID0);
- const TriangleMesh::Triangle& tri1 = mesh1->triangle(primID1);
-
- /* special culling for scene intersection with itself */
- if (scene0 == scene1 && geomID0 == geomID1)
- {
- /* ignore self intersections */
- if (primID0 == primID1)
- return false;
- }
- CSTAT(bvh_collide_prim_intersections2++);
-
- if (scene0 == scene1 && geomID0 == geomID1)
- {
- /* ignore intersection with topological neighbors */
- const vint4 t0(tri0.v[0],tri0.v[1],tri0.v[2],tri0.v[2]);
- if (any(vint4(tri1.v[0]) == t0)) return false;
- if (any(vint4(tri1.v[1]) == t0)) return false;
- if (any(vint4(tri1.v[2]) == t0)) return false;
- }
- CSTAT(bvh_collide_prim_intersections3++);
-
- const Vec3fa a0 = mesh0->vertex(tri0.v[0]);
- const Vec3fa a1 = mesh0->vertex(tri0.v[1]);
- const Vec3fa a2 = mesh0->vertex(tri0.v[2]);
- const Vec3fa b0 = mesh1->vertex(tri1.v[0]);
- const Vec3fa b1 = mesh1->vertex(tri1.v[1]);
- const Vec3fa b2 = mesh1->vertex(tri1.v[2]);
-
- return TriangleTriangleIntersector::intersect_triangle_triangle(a0,a1,a2,b0,b1,b2);
- }
-
- template<int N>
- __forceinline void BVHNColliderUserGeom<N>::processLeaf(NodeRef node0, NodeRef node1)
- {
- Collision collisions[16];
- size_t num_collisions = 0;
-
- size_t N0; Object* leaf0 = (Object*) node0.leaf(N0);
- size_t N1; Object* leaf1 = (Object*) node1.leaf(N1);
- for (size_t i=0; i<N0; i++) {
- for (size_t j=0; j<N1; j++) {
- const unsigned geomID0 = leaf0[i].geomID();
- const unsigned primID0 = leaf0[i].primID();
- const unsigned geomID1 = leaf1[j].geomID();
- const unsigned primID1 = leaf1[j].primID();
- if (this->scene0 == this->scene1 && geomID0 == geomID1 && primID0 == primID1) continue;
- collisions[num_collisions++] = Collision(geomID0,primID0,geomID1,primID1);
- if (num_collisions == 16) {
- this->callback(this->userPtr,(RTCCollision*)&collisions,num_collisions);
- num_collisions = 0;
- }
- }
- }
- if (num_collisions)
- this->callback(this->userPtr,(RTCCollision*)&collisions,num_collisions);
- }
-
- template<int N>
- void BVHNCollider<N>::collide_recurse(NodeRef ref0, const BBox3fa& bounds0, NodeRef ref1, const BBox3fa& bounds1, size_t depth0, size_t depth1)
- {
- CSTAT(bvh_collide_traversal_steps++);
- if (unlikely(ref0.isLeaf())) {
- if (unlikely(ref1.isLeaf())) {
- CSTAT(bvh_collide_leaf_pairs++);
- processLeaf(ref0,ref1);
- return;
- } else goto recurse_node1;
-
- } else {
- if (unlikely(ref1.isLeaf())) {
- goto recurse_node0;
- } else {
- if (area(bounds0) > area(bounds1)) {
- goto recurse_node0;
- }
- else {
- goto recurse_node1;
- }
- }
- }
-
- {
- recurse_node0:
- AABBNode* node0 = ref0.getAABBNode();
- size_t mask = overlap<N>(bounds1,*node0);
- //for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
- //for (size_t i=0; i<N; i++) {
-#if 0
- if (depth0 < parallel_depth_threshold)
- {
- parallel_for(size_t(N), [&] ( size_t i ) {
- if (mask & ( 1 << i)) {
- BVHN<N>::prefetch(node0->child(i),BVH_FLAG_ALIGNED_NODE);
- collide_recurse(node0->child(i),node0->bounds(i),ref1,bounds1,depth0+1,depth1);
- }
- });
- }
- else
-#endif
- {
- for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
- BVHN<N>::prefetch(node0->child(i),BVH_FLAG_ALIGNED_NODE);
- collide_recurse(node0->child(i),node0->bounds(i),ref1,bounds1,depth0+1,depth1);
- }
- }
- return;
- }
-
- {
- recurse_node1:
- AABBNode* node1 = ref1.getAABBNode();
- size_t mask = overlap<N>(bounds0,*node1);
- //for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
- //for (size_t i=0; i<N; i++) {
-#if 0
- if (depth1 < parallel_depth_threshold)
- {
- parallel_for(size_t(N), [&] ( size_t i ) {
- if (mask & ( 1 << i)) {
- BVHN<N>::prefetch(node1->child(i),BVH_FLAG_ALIGNED_NODE);
- collide_recurse(ref0,bounds0,node1->child(i),node1->bounds(i),depth0,depth1+1);
- }
- });
- }
- else
-#endif
- {
- for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
- BVHN<N>::prefetch(node1->child(i),BVH_FLAG_ALIGNED_NODE);
- collide_recurse(ref0,bounds0,node1->child(i),node1->bounds(i),depth0,depth1+1);
- }
- }
- return;
- }
- }
-
- template<int N>
- void BVHNCollider<N>::split(const CollideJob& job, jobvector& jobs)
- {
- if (unlikely(job.ref0.isLeaf())) {
- if (unlikely(job.ref1.isLeaf())) {
- jobs.push_back(job);
- return;
- } else goto recurse_node1;
- } else {
- if (unlikely(job.ref1.isLeaf())) {
- goto recurse_node0;
- } else {
- if (area(job.bounds0) > area(job.bounds1)) {
- goto recurse_node0;
- }
- else {
- goto recurse_node1;
- }
- }
- }
-
- {
- recurse_node0:
- const AABBNode* node0 = job.ref0.getAABBNode();
- size_t mask = overlap<N>(job.bounds1,*node0);
- for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
- jobs.push_back(CollideJob(node0->child(i),node0->bounds(i),job.depth0+1,job.ref1,job.bounds1,job.depth1));
- }
- return;
- }
-
- {
- recurse_node1:
- const AABBNode* node1 = job.ref1.getAABBNode();
- size_t mask = overlap<N>(job.bounds0,*node1);
- for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
- jobs.push_back(CollideJob(job.ref0,job.bounds0,job.depth0,node1->child(i),node1->bounds(i),job.depth1+1));
- }
- return;
- }
- }
-
- template<int N>
- void BVHNCollider<N>::collide_recurse_entry(NodeRef ref0, const BBox3fa& bounds0, NodeRef ref1, const BBox3fa& bounds1)
- {
- CSTAT(bvh_collide_traversal_steps = 0);
- CSTAT(bvh_collide_leaf_pairs = 0);
- CSTAT(bvh_collide_leaf_iterations = 0);
- CSTAT(bvh_collide_prim_intersections1 = 0);
- CSTAT(bvh_collide_prim_intersections2 = 0);
- CSTAT(bvh_collide_prim_intersections3 = 0);
- CSTAT(bvh_collide_prim_intersections4 = 0);
- CSTAT(bvh_collide_prim_intersections5 = 0);
- CSTAT(bvh_collide_prim_intersections = 0);
-#if 0
- collide_recurse(ref0,bounds0,ref1,bounds1,0,0);
-#else
- const int M = 2048;
- jobvector jobs[2];
- jobs[0].reserve(M);
- jobs[1].reserve(M);
- jobs[0].push_back(CollideJob(ref0,bounds0,0,ref1,bounds1,0));
- int source = 0;
- int target = 1;
-
- /* try to split job until job list is full */
- while (jobs[source].size()+8 <= M)
- {
- for (size_t i=0; i<jobs[source].size(); i++)
- {
- const CollideJob& job = jobs[source][i];
- size_t remaining = jobs[source].size()-i;
- if (jobs[target].size()+remaining+8 > M) {
- jobs[target].push_back(job);
- } else {
- split(job,jobs[target]);
- }
- }
-
- /* stop splitting jobs if we reached only leaves and cannot make progress anymore */
- if (jobs[target].size() == jobs[source].size())
- break;
-
- jobs[source].resize(0);
- std::swap(source,target);
- }
-
- /* parallel processing of all jobs */
- parallel_for(size_t(jobs[source].size()), [&] ( size_t i ) {
- CollideJob& j = jobs[source][i];
- collide_recurse(j.ref0,j.bounds0,j.ref1,j.bounds1,j.depth0,j.depth1);
- });
-
-
-#endif
- CSTAT(PRINT(bvh_collide_traversal_steps));
- CSTAT(PRINT(bvh_collide_leaf_pairs));
- CSTAT(PRINT(bvh_collide_leaf_iterations));
- CSTAT(PRINT(bvh_collide_prim_intersections1));
- CSTAT(PRINT(bvh_collide_prim_intersections2));
- CSTAT(PRINT(bvh_collide_prim_intersections3));
- CSTAT(PRINT(bvh_collide_prim_intersections4));
- CSTAT(PRINT(bvh_collide_prim_intersections5));
- CSTAT(PRINT(bvh_collide_prim_intersections));
- }
-
- template<int N>
- void BVHNColliderUserGeom<N>::collide(BVH* __restrict__ bvh0, BVH* __restrict__ bvh1, RTCCollideFunc callback, void* userPtr)
- {
- BVHNColliderUserGeom<N>(bvh0->scene,bvh1->scene,callback,userPtr).
- collide_recurse_entry(bvh0->root,bvh0->bounds.bounds(),bvh1->root,bvh1->bounds.bounds());
- }
-
-#if defined (EMBREE_LOWEST_ISA)
- struct collision_regression_test : public RegressionTest
- {
- collision_regression_test(const char* name) : RegressionTest(name) {
- registerRegressionTest(this);
- }
-
- bool run ()
- {
- bool passed = true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(-0.008815f, 0.041848f, -2.49875e-06f), Vec3fa(-0.008276f, 0.053318f, -2.49875e-06f), Vec3fa(0.003023f, 0.048969f, -2.49875e-06f),
- Vec3fa(0.00245f, 0.037612f, -2.49875e-06f), Vec3fa(0.01434f, 0.042634f, -2.49875e-06f), Vec3fa(0.013499f, 0.031309f, -2.49875e-06f)) == false;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,1),Vec3fa(1,0,1),Vec3fa(0,1,1)) == false;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,1),Vec3fa(1,0,0),Vec3fa(0,1,0)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,0),Vec3fa(1,0,1),Vec3fa(0,1,1)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,0.1f,0),Vec3fa(1,0,1),Vec3fa(0,1,1)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,0.1f,-0.1f),Vec3fa(1,0,1),Vec3fa(0,1,1)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,0),Vec3fa(0.5f,0,0),Vec3fa(0,0.5f,0)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,0.1f,0),Vec3fa(0.5f,0,0),Vec3fa(0,0.5f,0)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,0.1f,0),Vec3fa(0.5f,0.1f,0),Vec3fa(0.1f,0.5f,0)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,-0.1f,0),Vec3fa(0.5f,0.1f,0),Vec3fa(0.1f,0.5f,0)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(-0.1f,0.1f,0),Vec3fa(0.5f,0.1f,0),Vec3fa(0.1f,0.5f,0)) == true;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0),
- Vec3fa(-1,1,0) + Vec3fa(0,0,0),Vec3fa(-1,1,0) + Vec3fa(0.1f,0,0),Vec3fa(-1,1,0) + Vec3fa(0,0.1f,0)) == false;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0),
- Vec3fa( 2,0.5f,0) + Vec3fa(0,0,0),Vec3fa( 2,0.5f,0) + Vec3fa(0.1f,0,0),Vec3fa( 2,0.5f,0) + Vec3fa(0,0.1f,0)) == false;
- passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0),
- Vec3fa(0.5f,-2.0f,0) + Vec3fa(0,0,0),Vec3fa(0.5f,-2.0f,0) + Vec3fa(0.1f,0,0),Vec3fa(0.5f,-2.0f,0) + Vec3fa(0,0.1f,0)) == false;
- return passed;
- }
- };
-
- collision_regression_test collision_regression("collision_regression_test");
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Collider Definitions
- ////////////////////////////////////////////////////////////////////////////////
-
- DEFINE_COLLIDER(BVH4ColliderUserGeom,BVHNColliderUserGeom<4>);
-
-#if defined(__AVX__)
- DEFINE_COLLIDER(BVH8ColliderUserGeom,BVHNColliderUserGeom<8>);
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_collider.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_collider.h
deleted file mode 100644
index ac4f99c96a..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_collider.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/object.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int N>
- class BVHNCollider
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::AABBNode AABBNode;
-
- struct CollideJob
- {
- CollideJob () {}
-
- CollideJob (NodeRef ref0, const BBox3fa& bounds0, size_t depth0,
- NodeRef ref1, const BBox3fa& bounds1, size_t depth1)
- : ref0(ref0), bounds0(bounds0), depth0(depth0), ref1(ref1), bounds1(bounds1), depth1(depth1) {}
-
- NodeRef ref0;
- BBox3fa bounds0;
- size_t depth0;
- NodeRef ref1;
- BBox3fa bounds1;
- size_t depth1;
- };
-
- typedef vector_t<CollideJob, aligned_allocator<CollideJob,16>> jobvector;
-
- void split(const CollideJob& job, jobvector& jobs);
-
- public:
- __forceinline BVHNCollider (Scene* scene0, Scene* scene1, RTCCollideFunc callback, void* userPtr)
- : scene0(scene0), scene1(scene1), callback(callback), userPtr(userPtr) {}
-
- public:
- virtual void processLeaf(NodeRef leaf0, NodeRef leaf1) = 0;
- void collide_recurse(NodeRef node0, const BBox3fa& bounds0, NodeRef node1, const BBox3fa& bounds1, size_t depth0, size_t depth1);
- void collide_recurse_entry(NodeRef node0, const BBox3fa& bounds0, NodeRef node1, const BBox3fa& bounds1);
-
- protected:
- Scene* scene0;
- Scene* scene1;
- RTCCollideFunc callback;
- void* userPtr;
- };
-
- template<int N>
- class BVHNColliderUserGeom : public BVHNCollider<N>
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::AABBNode AABBNode;
-
- __forceinline BVHNColliderUserGeom (Scene* scene0, Scene* scene1, RTCCollideFunc callback, void* userPtr)
- : BVHNCollider<N>(scene0,scene1,callback,userPtr) {}
-
- virtual void processLeaf(NodeRef leaf0, NodeRef leaf1);
- public:
- static void collide(BVH* __restrict__ bvh0, BVH* __restrict__ bvh1, RTCCollideFunc callback, void* userPtr);
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_factory.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_factory.h
deleted file mode 100644
index 54021ca6eb..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_factory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../bvh/bvh.h"
-#include "../common/isa.h"
-#include "../common/accel.h"
-#include "../common/scene.h"
-#include "../geometry/curve_intersector_virtual.h"
-
-namespace embree
-{
- /*! BVH instantiations */
- class BVHFactory
- {
- public:
- enum class BuildVariant { STATIC, DYNAMIC, HIGH_QUALITY };
- enum class IntersectVariant { FAST, ROBUST };
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1.cpp
deleted file mode 100644
index ea6adc2717..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh_intersector1.h"
-#include "node_intersector1.h"
-#include "bvh_traverser1.h"
-
-#include "../geometry/intersector_iterators.h"
-#include "../geometry/triangle_intersector.h"
-#include "../geometry/trianglev_intersector.h"
-#include "../geometry/trianglev_mb_intersector.h"
-#include "../geometry/trianglei_intersector.h"
-#include "../geometry/quadv_intersector.h"
-#include "../geometry/quadi_intersector.h"
-#include "../geometry/curveNv_intersector.h"
-#include "../geometry/curveNi_intersector.h"
-#include "../geometry/curveNi_mb_intersector.h"
-#include "../geometry/linei_intersector.h"
-#include "../geometry/subdivpatch1_intersector.h"
-#include "../geometry/object_intersector.h"
-#include "../geometry/instance_intersector.h"
-#include "../geometry/subgrid_intersector.h"
-#include "../geometry/subgrid_mb_intersector.h"
-#include "../geometry/curve_intersector_virtual.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int N, int types, bool robust, typename PrimitiveIntersector1>
- void BVHNIntersector1<N, types, robust, PrimitiveIntersector1>::intersect(const Accel::Intersectors* __restrict__ This,
- RayHit& __restrict__ ray,
- IntersectContext* __restrict__ context)
- {
- const BVH* __restrict__ bvh = (const BVH*)This->ptr;
-
- /* we may traverse an empty BVH in case all geometry was invalid */
- if (bvh->root == BVH::emptyNode)
- return;
-
- /* perform per ray precalculations required by the primitive intersector */
- Precalculations pre(ray, bvh);
-
- /* stack state */
- StackItemT<NodeRef> stack[stackSize]; // stack of nodes
- StackItemT<NodeRef>* stackPtr = stack+1; // current stack pointer
- StackItemT<NodeRef>* stackEnd = stack+stackSize;
- stack[0].ptr = bvh->root;
- stack[0].dist = neg_inf;
-
- if (bvh->root == BVH::emptyNode)
- return;
-
- /* filter out invalid rays */
-#if defined(EMBREE_IGNORE_INVALID_RAYS)
- if (!ray.valid()) return;
-#endif
- /* verify correct input */
- assert(ray.valid());
- assert(ray.tnear() >= 0.0f);
- assert(!(types & BVH_MB) || (ray.time() >= 0.0f && ray.time() <= 1.0f));
-
- /* load the ray into SIMD registers */
- TravRay<N,Nx,robust> tray(ray.org, ray.dir, max(ray.tnear(), 0.0f), max(ray.tfar, 0.0f));
-
- /* initialize the node traverser */
- BVHNNodeTraverser1Hit<N, Nx, types> nodeTraverser;
-
- /* pop loop */
- while (true) pop:
- {
- /* pop next node */
- if (unlikely(stackPtr == stack)) break;
- stackPtr--;
- NodeRef cur = NodeRef(stackPtr->ptr);
-
- /* if popped node is too far, pop next one */
-#if defined(__AVX512ER__)
- /* much faster on KNL */
- if (unlikely(any(vfloat<Nx>(*(float*)&stackPtr->dist) > tray.tfar)))
- continue;
-#else
- if (unlikely(*(float*)&stackPtr->dist > ray.tfar))
- continue;
-#endif
-
- /* downtraversal loop */
- while (true)
- {
- /* intersect node */
- size_t mask; vfloat<Nx> tNear;
- STAT3(normal.trav_nodes,1,1,1);
- bool nodeIntersected = BVHNNodeIntersector1<N, Nx, types, robust>::intersect(cur, tray, ray.time(), tNear, mask);
- if (unlikely(!nodeIntersected)) { STAT3(normal.trav_nodes,-1,-1,-1); break; }
-
- /* if no child is hit, pop next node */
- if (unlikely(mask == 0))
- goto pop;
-
- /* select next child and push other children */
- nodeTraverser.traverseClosestHit(cur, mask, tNear, stackPtr, stackEnd);
- }
-
- /* this is a leaf node */
- assert(cur != BVH::emptyNode);
- STAT3(normal.trav_leaves,1,1,1);
- size_t num; Primitive* prim = (Primitive*)cur.leaf(num);
- size_t lazy_node = 0;
- PrimitiveIntersector1::intersect(This, pre, ray, context, prim, num, tray, lazy_node);
- tray.tfar = ray.tfar;
-
- /* push lazy node onto stack */
- if (unlikely(lazy_node)) {
- stackPtr->ptr = lazy_node;
- stackPtr->dist = neg_inf;
- stackPtr++;
- }
- }
- }
-
- template<int N, int types, bool robust, typename PrimitiveIntersector1>
- void BVHNIntersector1<N, types, robust, PrimitiveIntersector1>::occluded(const Accel::Intersectors* __restrict__ This,
- Ray& __restrict__ ray,
- IntersectContext* __restrict__ context)
- {
- const BVH* __restrict__ bvh = (const BVH*)This->ptr;
-
- /* we may traverse an empty BVH in case all geometry was invalid */
- if (bvh->root == BVH::emptyNode)
- return;
-
- /* early out for already occluded rays */
- if (unlikely(ray.tfar < 0.0f))
- return;
-
- /* perform per ray precalculations required by the primitive intersector */
- Precalculations pre(ray, bvh);
-
- /* stack state */
- NodeRef stack[stackSize]; // stack of nodes that still need to get traversed
- NodeRef* stackPtr = stack+1; // current stack pointer
- NodeRef* stackEnd = stack+stackSize;
- stack[0] = bvh->root;
-
- /* filter out invalid rays */
-#if defined(EMBREE_IGNORE_INVALID_RAYS)
- if (!ray.valid()) return;
-#endif
-
- /* verify correct input */
- assert(ray.valid());
- assert(ray.tnear() >= 0.0f);
- assert(!(types & BVH_MB) || (ray.time() >= 0.0f && ray.time() <= 1.0f));
-
- /* load the ray into SIMD registers */
- TravRay<N,Nx,robust> tray(ray.org, ray.dir, max(ray.tnear(), 0.0f), max(ray.tfar, 0.0f));
-
- /* initialize the node traverser */
- BVHNNodeTraverser1Hit<N, Nx, types> nodeTraverser;
-
- /* pop loop */
- while (true) pop:
- {
- /* pop next node */
- if (unlikely(stackPtr == stack)) break;
- stackPtr--;
- NodeRef cur = (NodeRef)*stackPtr;
-
- /* downtraversal loop */
- while (true)
- {
- /* intersect node */
- size_t mask; vfloat<Nx> tNear;
- STAT3(shadow.trav_nodes,1,1,1);
- bool nodeIntersected = BVHNNodeIntersector1<N, Nx, types, robust>::intersect(cur, tray, ray.time(), tNear, mask);
- if (unlikely(!nodeIntersected)) { STAT3(shadow.trav_nodes,-1,-1,-1); break; }
-
- /* if no child is hit, pop next node */
- if (unlikely(mask == 0))
- goto pop;
-
- /* select next child and push other children */
- nodeTraverser.traverseAnyHit(cur, mask, tNear, stackPtr, stackEnd);
- }
-
- /* this is a leaf node */
- assert(cur != BVH::emptyNode);
- STAT3(shadow.trav_leaves,1,1,1);
- size_t num; Primitive* prim = (Primitive*)cur.leaf(num);
- size_t lazy_node = 0;
- if (PrimitiveIntersector1::occluded(This, pre, ray, context, prim, num, tray, lazy_node)) {
- ray.tfar = neg_inf;
- break;
- }
-
- /* push lazy node onto stack */
- if (unlikely(lazy_node)) {
- *stackPtr = (NodeRef)lazy_node;
- stackPtr++;
- }
- }
- }
-
- template<int N, int types, bool robust, typename PrimitiveIntersector1>
- struct PointQueryDispatch
- {
- typedef typename PrimitiveIntersector1::Precalculations Precalculations;
- typedef typename PrimitiveIntersector1::Primitive Primitive;
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::AABBNode AABBNode;
- typedef typename BVH::AABBNodeMB4D AABBNodeMB4D;
-
- static const size_t stackSize = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store
-
- /* right now AVX512KNL SIMD extension only for standard node types */
- static const size_t Nx = (types == BVH_AN1 || types == BVH_QN1) ? vextend<N>::size : N;
-
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context)
- {
- const BVH* __restrict__ bvh = (const BVH*)This->ptr;
-
- /* we may traverse an empty BVH in case all geometry was invalid */
- if (bvh->root == BVH::emptyNode)
- return false;
-
- /* stack state */
- StackItemT<NodeRef> stack[stackSize]; // stack of nodes
- StackItemT<NodeRef>* stackPtr = stack+1; // current stack pointer
- StackItemT<NodeRef>* stackEnd = stack+stackSize;
- stack[0].ptr = bvh->root;
- stack[0].dist = neg_inf;
-
- /* verify correct input */
- assert(!(types & BVH_MB) || (query->time >= 0.0f && query->time <= 1.0f));
-
- /* load the point query into SIMD registers */
- TravPointQuery<N> tquery(query->p, context->query_radius);
-
- /* initialize the node traverser */
- BVHNNodeTraverser1Hit<N, N, types> nodeTraverser;
-
- bool changed = false;
- float cull_radius = context->query_type == POINT_QUERY_TYPE_SPHERE
- ? query->radius * query->radius
- : dot(context->query_radius, context->query_radius);
-
- /* pop loop */
- while (true) pop:
- {
- /* pop next node */
- if (unlikely(stackPtr == stack)) break;
- stackPtr--;
- NodeRef cur = NodeRef(stackPtr->ptr);
-
- /* if popped node is too far, pop next one */
- if (unlikely(*(float*)&stackPtr->dist > cull_radius))
- continue;
-
- /* downtraversal loop */
- while (true)
- {
- /* intersect node */
- size_t mask; vfloat<N> tNear;
- STAT3(point_query.trav_nodes,1,1,1);
- bool nodeIntersected;
- if (likely(context->query_type == POINT_QUERY_TYPE_SPHERE)) {
- nodeIntersected = BVHNNodePointQuerySphere1<N, types>::pointQuery(cur, tquery, query->time, tNear, mask);
- } else {
- nodeIntersected = BVHNNodePointQueryAABB1 <N, types>::pointQuery(cur, tquery, query->time, tNear, mask);
- }
- if (unlikely(!nodeIntersected)) { STAT3(point_query.trav_nodes,-1,-1,-1); break; }
-
- /* if no child is hit, pop next node */
- if (unlikely(mask == 0))
- goto pop;
-
- /* select next child and push other children */
- nodeTraverser.traverseClosestHit(cur, mask, tNear, stackPtr, stackEnd);
- }
-
- /* this is a leaf node */
- assert(cur != BVH::emptyNode);
- STAT3(point_query.trav_leaves,1,1,1);
- size_t num; Primitive* prim = (Primitive*)cur.leaf(num);
- size_t lazy_node = 0;
- if (PrimitiveIntersector1::pointQuery(This, query, context, prim, num, tquery, lazy_node))
- {
- changed = true;
- tquery.rad = context->query_radius;
- cull_radius = context->query_type == POINT_QUERY_TYPE_SPHERE
- ? query->radius * query->radius
- : dot(context->query_radius, context->query_radius);
- }
-
- /* push lazy node onto stack */
- if (unlikely(lazy_node)) {
- stackPtr->ptr = lazy_node;
- stackPtr->dist = neg_inf;
- stackPtr++;
- }
- }
- return changed;
- }
- };
-
- /* disable point queries for not yet supported geometry types */
- template<int N, int types, bool robust>
- struct PointQueryDispatch<N, types, robust, VirtualCurveIntersector1> {
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
- };
-
- template<int N, int types, bool robust>
- struct PointQueryDispatch<N, types, robust, SubdivPatch1Intersector1> {
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
- };
-
- template<int N, int types, bool robust>
- struct PointQueryDispatch<N, types, robust, SubdivPatch1MBIntersector1> {
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
- };
-
- template<int N, int types, bool robust, typename PrimitiveIntersector1>
- bool BVHNIntersector1<N, types, robust, PrimitiveIntersector1>::pointQuery(
- const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context)
- {
- return PointQueryDispatch<N, types, robust, PrimitiveIntersector1>::pointQuery(This, query, context);
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1.h
deleted file mode 100644
index 1a269c319a..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-#include "../common/ray.h"
-#include "../common/point_query.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! BVH single ray intersector. */
- template<int N, int types, bool robust, typename PrimitiveIntersector1>
- class BVHNIntersector1
- {
- /* shortcuts for frequently used types */
- typedef typename PrimitiveIntersector1::Precalculations Precalculations;
- typedef typename PrimitiveIntersector1::Primitive Primitive;
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::AABBNode AABBNode;
- typedef typename BVH::AABBNodeMB4D AABBNodeMB4D;
-
- static const size_t stackSize = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store
-
- /* right now AVX512KNL SIMD extension only for standard node types */
- static const size_t Nx = (types == BVH_AN1 || types == BVH_QN1) ? vextend<N>::size : N;
-
- public:
- static void intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context);
- static void occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context);
- static bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context);
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1_bvh4.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1_bvh4.cpp
deleted file mode 100644
index 989f7354fd..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector1_bvh4.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh_intersector1.cpp"
-
-namespace embree
-{
- namespace isa
- {
- int getISA() {
- return VerifyMultiTargetLinking::getISA();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// BVH4Intersector1 Definitions
- ////////////////////////////////////////////////////////////////////////////////
-
- IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersector1,BVHNIntersector1<4 COMMA BVH_AN1_UN1 COMMA false COMMA VirtualCurveIntersector1 >));
- IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersector1MB,BVHNIntersector1<4 COMMA BVH_AN2_AN4D_UN2 COMMA false COMMA VirtualCurveIntersector1 >));
-
- IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersectorRobust1,BVHNIntersector1<4 COMMA BVH_AN1_UN1 COMMA true COMMA VirtualCurveIntersector1 >));
- IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersectorRobust1MB,BVHNIntersector1<4 COMMA BVH_AN2_AN4D_UN2 COMMA true COMMA VirtualCurveIntersector1 >));
-
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4Intersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<TriangleMIntersector1Moeller <SIMD_MODE(4) COMMA true> > >));
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<TriangleMiIntersector1Moeller <SIMD_MODE(4) COMMA true> > >));
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1<TriangleMvIntersector1Pluecker<SIMD_MODE(4) COMMA true> > >));
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1<TriangleMiIntersector1Pluecker<SIMD_MODE(4) COMMA true> > >));
-
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<TriangleMvMBIntersector1Moeller <SIMD_MODE(4) COMMA true> > >));
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<TriangleMiMBIntersector1Moeller <SIMD_MODE(4) COMMA true> > >));
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1<TriangleMvMBIntersector1Pluecker<SIMD_MODE(4) COMMA true> > >));
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1<TriangleMiMBIntersector1Pluecker<SIMD_MODE(4) COMMA true> > >));
-
- IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4vIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<QuadMvIntersector1Moeller <4 COMMA true> > >));
- IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<QuadMiIntersector1Moeller <4 COMMA true> > >));
- IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4vIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1<QuadMvIntersector1Pluecker<4 COMMA true> > >));
- IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1<QuadMiIntersector1Pluecker<4 COMMA true> > >));
-
- IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<QuadMiMBIntersector1Moeller <4 COMMA true> > >));
- IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1<QuadMiMBIntersector1Pluecker<4 COMMA true> > >));
-
- IF_ENABLED_SUBDIV(DEFINE_INTERSECTOR1(BVH4SubdivPatch1Intersector1,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA SubdivPatch1Intersector1>));
- IF_ENABLED_SUBDIV(DEFINE_INTERSECTOR1(BVH4SubdivPatch1MBIntersector1,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA SubdivPatch1MBIntersector1>));
-
- IF_ENABLED_USER(DEFINE_INTERSECTOR1(BVH4VirtualIntersector1,BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<ObjectIntersector1<false>> >));
- IF_ENABLED_USER(DEFINE_INTERSECTOR1(BVH4VirtualMBIntersector1,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<ObjectIntersector1<true>> >));
-
- IF_ENABLED_INSTANCE(DEFINE_INTERSECTOR1(BVH4InstanceIntersector1,BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<InstanceIntersector1> >));
- IF_ENABLED_INSTANCE(DEFINE_INTERSECTOR1(BVH4InstanceMBIntersector1,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<InstanceIntersector1MB> >));
-
- IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(QBVH4Triangle4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1<TriangleMiIntersector1Pluecker<SIMD_MODE(4) COMMA true> > >));
- IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(QBVH4Quad4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1<QuadMiIntersector1Pluecker<4 COMMA true> > >));
-
- IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridIntersector1Moeller,BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA SubGridIntersector1Moeller<4 COMMA true> >));
- IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridMBIntersector1Moeller,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA SubGridMBIntersector1Pluecker<4 COMMA true> >));
-
- IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA SubGridIntersector1Pluecker<4 COMMA true> >));
- //IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA SubGridMBIntersector1Pluecker<4 COMMA true> >));
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_hybrid.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_hybrid.h
deleted file mode 100644
index d764cc928d..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_hybrid.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-#include "../common/ray.h"
-#include "../common/stack_item.h"
-#include "node_intersector_frustum.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int K, bool robust>
- struct TravRayK;
-
- /*! BVH hybrid packet intersector. Switches between packet and single ray traversal (optional). */
- template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK, bool single = true>
- class BVHNIntersectorKHybrid
- {
- /* right now AVX512KNL SIMD extension only for standard node types */
- static const size_t Nx = types == BVH_AN1 ? vextend<N>::size : N;
-
- /* shortcuts for frequently used types */
- typedef typename PrimitiveIntersectorK::Precalculations Precalculations;
- typedef typename PrimitiveIntersectorK::Primitive Primitive;
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::BaseNode BaseNode;
- typedef typename BVH::AABBNode AABBNode;
-
- static const size_t stackSizeSingle = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store
- static const size_t stackSizeChunk = 1+(N-1)*BVH::maxDepth;
-
- static const size_t switchThresholdIncoherent = \
- (K==4) ? 3 :
- (K==8) ? ((N==4) ? 5 : 7) :
- (K==16) ? 14 : // 14 seems to work best for KNL due to better ordered chunk traversal
- 0;
-
- private:
- static void intersect1(Accel::Intersectors* This, const BVH* bvh, NodeRef root, size_t k, Precalculations& pre,
- RayHitK<K>& ray, const TravRayK<K, robust>& tray, IntersectContext* context);
- static bool occluded1(Accel::Intersectors* This, const BVH* bvh, NodeRef root, size_t k, Precalculations& pre,
- RayK<K>& ray, const TravRayK<K, robust>& tray, IntersectContext* context);
-
- public:
- static void intersect(vint<K>* valid, Accel::Intersectors* This, RayHitK<K>& ray, IntersectContext* context);
- static void occluded (vint<K>* valid, Accel::Intersectors* This, RayK<K>& ray, IntersectContext* context);
-
- static void intersectCoherent(vint<K>* valid, Accel::Intersectors* This, RayHitK<K>& ray, IntersectContext* context);
- static void occludedCoherent (vint<K>* valid, Accel::Intersectors* This, RayK<K>& ray, IntersectContext* context);
-
- };
-
- /*! BVH packet intersector. */
- template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK>
- class BVHNIntersectorKChunk : public BVHNIntersectorKHybrid<N, K, types, robust, PrimitiveIntersectorK, false> {};
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_stream.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_stream.h
deleted file mode 100644
index 83d1fb4d3d..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_stream.h
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "node_intersector_packet_stream.h"
-#include "node_intersector_frustum.h"
-#include "bvh_traverser_stream.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! BVH ray stream intersector. */
- template<int N, int Nx, int types, bool robust, typename PrimitiveIntersector>
- class BVHNIntersectorStream
- {
- static const int Nxd = (Nx == N) ? N : Nx/2;
-
- /* shortcuts for frequently used types */
- template<int K> using PrimitiveIntersectorK = typename PrimitiveIntersector::template Type<K>;
- template<int K> using PrimitiveK = typename PrimitiveIntersectorK<K>::PrimitiveK;
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::BaseNode BaseNode;
- typedef typename BVH::AABBNode AABBNode;
- typedef typename BVH::AABBNodeMB AABBNodeMB;
-
- template<int K>
- __forceinline static size_t initPacketsAndFrustum(RayK<K>** inputPackets, size_t numOctantRays,
- TravRayKStream<K, robust>* packets, Frustum<robust>& frustum, bool& commonOctant)
- {
- const size_t numPackets = (numOctantRays+K-1)/K;
-
- Vec3vf<K> tmp_min_rdir(pos_inf);
- Vec3vf<K> tmp_max_rdir(neg_inf);
- Vec3vf<K> tmp_min_org(pos_inf);
- Vec3vf<K> tmp_max_org(neg_inf);
- vfloat<K> tmp_min_dist(pos_inf);
- vfloat<K> tmp_max_dist(neg_inf);
-
- size_t m_active = 0;
- for (size_t i = 0; i < numPackets; i++)
- {
- const vfloat<K> tnear = inputPackets[i]->tnear();
- const vfloat<K> tfar = inputPackets[i]->tfar;
- vbool<K> m_valid = (tnear <= tfar) & (tnear >= 0.0f);
-
-#if defined(EMBREE_IGNORE_INVALID_RAYS)
- m_valid &= inputPackets[i]->valid();
-#endif
-
- m_active |= (size_t)movemask(m_valid) << (i*K);
-
- vfloat<K> packet_min_dist = max(tnear, 0.0f);
- vfloat<K> packet_max_dist = select(m_valid, tfar, neg_inf);
- tmp_min_dist = min(tmp_min_dist, packet_min_dist);
- tmp_max_dist = max(tmp_max_dist, packet_max_dist);
-
- const Vec3vf<K>& org = inputPackets[i]->org;
- const Vec3vf<K>& dir = inputPackets[i]->dir;
-
- new (&packets[i]) TravRayKStream<K, robust>(org, dir, packet_min_dist, packet_max_dist);
-
- tmp_min_rdir = min(tmp_min_rdir, select(m_valid, packets[i].rdir, Vec3vf<K>(pos_inf)));
- tmp_max_rdir = max(tmp_max_rdir, select(m_valid, packets[i].rdir, Vec3vf<K>(neg_inf)));
- tmp_min_org = min(tmp_min_org , select(m_valid,org , Vec3vf<K>(pos_inf)));
- tmp_max_org = max(tmp_max_org , select(m_valid,org , Vec3vf<K>(neg_inf)));
- }
-
- m_active &= (numOctantRays == (8 * sizeof(size_t))) ? (size_t)-1 : (((size_t)1 << numOctantRays)-1);
-
-
- const Vec3fa reduced_min_rdir(reduce_min(tmp_min_rdir.x),
- reduce_min(tmp_min_rdir.y),
- reduce_min(tmp_min_rdir.z));
-
- const Vec3fa reduced_max_rdir(reduce_max(tmp_max_rdir.x),
- reduce_max(tmp_max_rdir.y),
- reduce_max(tmp_max_rdir.z));
-
- const Vec3fa reduced_min_origin(reduce_min(tmp_min_org.x),
- reduce_min(tmp_min_org.y),
- reduce_min(tmp_min_org.z));
-
- const Vec3fa reduced_max_origin(reduce_max(tmp_max_org.x),
- reduce_max(tmp_max_org.y),
- reduce_max(tmp_max_org.z));
-
- commonOctant =
- (reduced_max_rdir.x < 0.0f || reduced_min_rdir.x >= 0.0f) &&
- (reduced_max_rdir.y < 0.0f || reduced_min_rdir.y >= 0.0f) &&
- (reduced_max_rdir.z < 0.0f || reduced_min_rdir.z >= 0.0f);
-
- const float frustum_min_dist = reduce_min(tmp_min_dist);
- const float frustum_max_dist = reduce_max(tmp_max_dist);
-
- frustum.init(reduced_min_origin, reduced_max_origin,
- reduced_min_rdir, reduced_max_rdir,
- frustum_min_dist, frustum_max_dist,
- N);
-
- return m_active;
- }
-
- template<int K>
- __forceinline static size_t intersectAABBNodePacket(size_t m_active,
- const TravRayKStream<K,robust>* packets,
- const AABBNode* __restrict__ node,
- size_t boxID,
- const NearFarPrecalculations& nf)
- {
- assert(m_active);
- const size_t startPacketID = bsf(m_active) / K;
- const size_t endPacketID = bsr(m_active) / K;
- size_t m_trav_active = 0;
- for (size_t i = startPacketID; i <= endPacketID; i++)
- {
- const size_t m_hit = intersectNodeK<N>(node, boxID, packets[i], nf);
- m_trav_active |= m_hit << (i*K);
- }
- return m_trav_active;
- }
-
- template<int K>
- __forceinline static size_t traverseCoherentStream(size_t m_active,
- TravRayKStream<K, robust>* packets,
- const AABBNode* __restrict__ node,
- const Frustum<robust>& frustum,
- size_t* maskK,
- vfloat<Nx>& dist)
- {
- size_t m_node_hit = intersectNodeFrustum<N,Nx>(node, frustum, dist);
- const size_t first_index = bsf(m_active);
- const size_t first_packetID = first_index / K;
- const size_t first_rayID = first_index % K;
- size_t m_first_hit = intersectNode1<N,Nx>(node, packets[first_packetID], first_rayID, frustum.nf);
-
- /* this make traversal independent of the ordering of rays */
- size_t m_node = m_node_hit ^ m_first_hit;
- while (unlikely(m_node))
- {
- const size_t boxID = bscf(m_node);
- const size_t m_current = m_active & intersectAABBNodePacket(m_active, packets, node, boxID, frustum.nf);
- m_node_hit ^= m_current ? (size_t)0 : ((size_t)1 << boxID);
- maskK[boxID] = m_current;
- }
- return m_node_hit;
- }
-
- // TODO: explicit 16-wide path for KNL
- template<int K>
- __forceinline static vint<Nx> traverseIncoherentStream(size_t m_active,
- TravRayKStreamFast<K>* __restrict__ packets,
- const AABBNode* __restrict__ node,
- const NearFarPrecalculations& nf,
- const int shiftTable[32])
- {
- const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
- const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
- const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
- const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
- const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
- const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
- assert(m_active);
- vint<Nx> vmask(zero);
- do
- {
- STAT3(shadow.trav_nodes,1,1,1);
- const size_t rayID = bscf(m_active);
- assert(rayID < MAX_INTERNAL_STREAM_SIZE);
- TravRayKStream<K,robust> &p = packets[rayID / K];
- const size_t i = rayID % K;
- const vint<Nx> bitmask(shiftTable[rayID]);
-
-#if defined (__aarch64__)
- const vfloat<Nx> tNearX = madd(bminX, p.rdir.x[i], p.neg_org_rdir.x[i]);
- const vfloat<Nx> tNearY = madd(bminY, p.rdir.y[i], p.neg_org_rdir.y[i]);
- const vfloat<Nx> tNearZ = madd(bminZ, p.rdir.z[i], p.neg_org_rdir.z[i]);
- const vfloat<Nx> tFarX = madd(bmaxX, p.rdir.x[i], p.neg_org_rdir.x[i]);
- const vfloat<Nx> tFarY = madd(bmaxY, p.rdir.y[i], p.neg_org_rdir.y[i]);
- const vfloat<Nx> tFarZ = madd(bmaxZ, p.rdir.z[i], p.neg_org_rdir.z[i]);
-#else
- const vfloat<Nx> tNearX = msub(bminX, p.rdir.x[i], p.org_rdir.x[i]);
- const vfloat<Nx> tNearY = msub(bminY, p.rdir.y[i], p.org_rdir.y[i]);
- const vfloat<Nx> tNearZ = msub(bminZ, p.rdir.z[i], p.org_rdir.z[i]);
- const vfloat<Nx> tFarX = msub(bmaxX, p.rdir.x[i], p.org_rdir.x[i]);
- const vfloat<Nx> tFarY = msub(bmaxY, p.rdir.y[i], p.org_rdir.y[i]);
- const vfloat<Nx> tFarZ = msub(bmaxZ, p.rdir.z[i], p.org_rdir.z[i]);
-#endif
-
- const vfloat<Nx> tNear = maxi(tNearX, tNearY, tNearZ, vfloat<Nx>(p.tnear[i]));
- const vfloat<Nx> tFar = mini(tFarX , tFarY , tFarZ, vfloat<Nx>(p.tfar[i]));
-
-#if defined(__AVX512ER__)
- const vboolx m_node((1 << N)-1);
- const vbool<Nx> hit_mask = le(m_node, tNear, tFar);
- vmask = mask_or(hit_mask, vmask, vmask, bitmask);
-#else
- const vbool<Nx> hit_mask = tNear <= tFar;
-#if defined(__AVX2__)
- vmask = vmask | (bitmask & vint<Nx>(hit_mask));
-#else
- vmask = select(hit_mask, vmask | bitmask, vmask);
-#endif
-#endif
- } while(m_active);
- return vmask;
- }
-
- template<int K>
- __forceinline static vint<Nx> traverseIncoherentStream(size_t m_active,
- TravRayKStreamRobust<K>* __restrict__ packets,
- const AABBNode* __restrict__ node,
- const NearFarPrecalculations& nf,
- const int shiftTable[32])
- {
- const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
- const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
- const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
- const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
- const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
- const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
- assert(m_active);
- vint<Nx> vmask(zero);
- do
- {
- STAT3(shadow.trav_nodes,1,1,1);
- const size_t rayID = bscf(m_active);
- assert(rayID < MAX_INTERNAL_STREAM_SIZE);
- TravRayKStream<K,robust> &p = packets[rayID / K];
- const size_t i = rayID % K;
- const vint<Nx> bitmask(shiftTable[rayID]);
- const vfloat<Nx> tNearX = (bminX - p.org.x[i]) * p.rdir.x[i];
- const vfloat<Nx> tNearY = (bminY - p.org.y[i]) * p.rdir.y[i];
- const vfloat<Nx> tNearZ = (bminZ - p.org.z[i]) * p.rdir.z[i];
- const vfloat<Nx> tFarX = (bmaxX - p.org.x[i]) * p.rdir.x[i];
- const vfloat<Nx> tFarY = (bmaxY - p.org.y[i]) * p.rdir.y[i];
- const vfloat<Nx> tFarZ = (bmaxZ - p.org.z[i]) * p.rdir.z[i];
- const vfloat<Nx> tNear = maxi(tNearX, tNearY, tNearZ, vfloat<Nx>(p.tnear[i]));
- const vfloat<Nx> tFar = mini(tFarX , tFarY , tFarZ, vfloat<Nx>(p.tfar[i]));
- const float round_down = 1.0f-2.0f*float(ulp);
- const float round_up = 1.0f+2.0f*float(ulp);
-#if defined(__AVX512ER__)
- const vboolx m_node((1 << N)-1);
- const vbool<Nx> hit_mask = le(m_node, round_down*tNear, round_up*tFar);
- vmask = mask_or(hit_mask, vmask, vmask, bitmask);
-#else
- const vbool<Nx> hit_mask = round_down*tNear <= round_up*tFar;
-#if defined(__AVX2__)
- vmask = vmask | (bitmask & vint<Nx>(hit_mask));
-#else
- vmask = select(hit_mask, vmask | bitmask, vmask);
-#endif
-#endif
- } while(m_active);
- return vmask;
- }
-
-
- static const size_t stackSizeSingle = 1+(N-1)*BVH::maxDepth;
-
- public:
- static void intersect(Accel::Intersectors* This, RayHitN** inputRays, size_t numRays, IntersectContext* context);
- static void occluded (Accel::Intersectors* This, RayN** inputRays, size_t numRays, IntersectContext* context);
-
- private:
- template<int K>
- static void intersectCoherent(Accel::Intersectors* This, RayHitK<K>** inputRays, size_t numRays, IntersectContext* context);
-
- template<int K>
- static void occludedCoherent(Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
-
- template<int K>
- static void occludedIncoherent(Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
- };
-
-
- /*! BVH ray stream intersector with direct fallback to packets. */
- template<int N, int Nx>
- class BVHNIntersectorStreamPacketFallback
- {
- public:
- static void intersect(Accel::Intersectors* This, RayHitN** inputRays, size_t numRays, IntersectContext* context);
- static void occluded (Accel::Intersectors* This, RayN** inputRays, size_t numRays, IntersectContext* context);
-
- private:
- template<int K>
- static void intersectK(Accel::Intersectors* This, RayHitK<K>** inputRays, size_t numRays, IntersectContext* context);
-
- template<int K>
- static void occludedK(Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_stream_filters.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_stream_filters.h
deleted file mode 100644
index cdeb923637..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_intersector_stream_filters.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-#include "../common/ray.h"
-#include "../common/scene.h"
-
-namespace embree
-{
- namespace isa
- {
- class RayStreamFilter
- {
- public:
- static void intersectAOS(Scene* scene, RTCRayHit* rays, size_t N, size_t stride, IntersectContext* context);
- static void intersectAOP(Scene* scene, RTCRayHit** rays, size_t N, IntersectContext* context);
- static void intersectSOA(Scene* scene, char* rays, size_t N, size_t numPackets, size_t stride, IntersectContext* context);
- static void intersectSOP(Scene* scene, const RTCRayHitNp* rays, size_t N, IntersectContext* context);
-
- static void occludedAOS(Scene* scene, RTCRay* rays, size_t N, size_t stride, IntersectContext* context);
- static void occludedAOP(Scene* scene, RTCRay** rays, size_t N, IntersectContext* context);
- static void occludedSOA(Scene* scene, char* rays, size_t N, size_t numPackets, size_t stride, IntersectContext* context);
- static void occludedSOP(Scene* scene, const RTCRayNp* rays, size_t N, IntersectContext* context);
-
- private:
- template<int K, bool intersect>
- static void filterAOS(Scene* scene, void* rays, size_t N, size_t stride, IntersectContext* context);
-
- template<int K, bool intersect>
- static void filterAOP(Scene* scene, void** rays, size_t N, IntersectContext* context);
-
- template<int K, bool intersect>
- static void filterSOA(Scene* scene, char* rays, size_t N, size_t numPackets, size_t stride, IntersectContext* context);
-
- template<int K, bool intersect>
- static void filterSOP(Scene* scene, const void* rays, size_t N, IntersectContext* context);
- };
- }
-};
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb.h
deleted file mode 100644
index baa4a8d805..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb.h
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_node_base.h"
-
-namespace embree
-{
- /*! BVHN AABBNode */
- template<typename NodeRef, int N>
- struct AABBNode_t : public BaseNode_t<NodeRef, N>
- {
- using BaseNode_t<NodeRef,N>::children;
-
- struct Create
- {
- __forceinline NodeRef operator() (const FastAllocator::CachedAllocator& alloc, size_t numChildren = 0) const
- {
- AABBNode_t* node = (AABBNode_t*) alloc.malloc0(sizeof(AABBNode_t),NodeRef::byteNodeAlignment); node->clear();
- return NodeRef::encodeNode(node);
- }
- };
-
- struct Set
- {
- __forceinline void operator() (NodeRef node, size_t i, NodeRef child, const BBox3fa& bounds) const {
- node.getAABBNode()->setRef(i,child);
- node.getAABBNode()->setBounds(i,bounds);
- }
- };
-
- struct Create2
- {
- template<typename BuildRecord>
- __forceinline NodeRef operator() (BuildRecord* children, const size_t num, const FastAllocator::CachedAllocator& alloc) const
- {
- AABBNode_t* node = (AABBNode_t*) alloc.malloc0(sizeof(AABBNode_t), NodeRef::byteNodeAlignment); node->clear();
- for (size_t i=0; i<num; i++) node->setBounds(i,children[i].bounds());
- return NodeRef::encodeNode(node);
- }
- };
-
- struct Set2
- {
- template<typename BuildRecord>
- __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
- {
- AABBNode_t* node = ref.getAABBNode();
- for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
- return ref;
- }
- };
-
- struct Set3
- {
- Set3 (FastAllocator* allocator, PrimRef* prims)
- : allocator(allocator), prims(prims) {}
-
- template<typename BuildRecord>
- __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
- {
- AABBNode_t* node = ref.getAABBNode();
- for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
-
- if (unlikely(precord.alloc_barrier))
- {
- PrimRef* begin = &prims[precord.prims.begin()];
- PrimRef* end = &prims[precord.prims.end()]; // FIXME: extended end for spatial split builder!!!!!
- size_t bytes = (size_t)end - (size_t)begin;
- allocator->addBlock(begin,bytes);
- }
-
- return ref;
- }
-
- FastAllocator* const allocator;
- PrimRef* const prims;
- };
-
- /*! Clears the node. */
- __forceinline void clear() {
- lower_x = lower_y = lower_z = pos_inf;
- upper_x = upper_y = upper_z = neg_inf;
- BaseNode_t<NodeRef,N>::clear();
- }
-
- /*! Sets bounding box and ID of child. */
- __forceinline void setRef(size_t i, const NodeRef& ref) {
- assert(i < N);
- children[i] = ref;
- }
-
- /*! Sets bounding box of child. */
- __forceinline void setBounds(size_t i, const BBox3fa& bounds)
- {
- assert(i < N);
- lower_x[i] = bounds.lower.x; lower_y[i] = bounds.lower.y; lower_z[i] = bounds.lower.z;
- upper_x[i] = bounds.upper.x; upper_y[i] = bounds.upper.y; upper_z[i] = bounds.upper.z;
- }
-
- /*! Sets bounding box and ID of child. */
- __forceinline void set(size_t i, const NodeRef& ref, const BBox3fa& bounds) {
- setBounds(i,bounds);
- children[i] = ref;
- }
-
- /*! Returns bounds of node. */
- __forceinline BBox3fa bounds() const {
- const Vec3fa lower(reduce_min(lower_x),reduce_min(lower_y),reduce_min(lower_z));
- const Vec3fa upper(reduce_max(upper_x),reduce_max(upper_y),reduce_max(upper_z));
- return BBox3fa(lower,upper);
- }
-
- /*! Returns bounds of specified child. */
- __forceinline BBox3fa bounds(size_t i) const
- {
- assert(i < N);
- const Vec3fa lower(lower_x[i],lower_y[i],lower_z[i]);
- const Vec3fa upper(upper_x[i],upper_y[i],upper_z[i]);
- return BBox3fa(lower,upper);
- }
-
- /*! Returns extent of bounds of specified child. */
- __forceinline Vec3fa extend(size_t i) const {
- return bounds(i).size();
- }
-
- /*! Returns bounds of all children (implemented later as specializations) */
- __forceinline void bounds(BBox<vfloat4>& bounds0, BBox<vfloat4>& bounds1, BBox<vfloat4>& bounds2, BBox<vfloat4>& bounds3) const;
-
- /*! swap two children of the node */
- __forceinline void swap(size_t i, size_t j)
- {
- assert(i<N && j<N);
- std::swap(children[i],children[j]);
- std::swap(lower_x[i],lower_x[j]);
- std::swap(lower_y[i],lower_y[j]);
- std::swap(lower_z[i],lower_z[j]);
- std::swap(upper_x[i],upper_x[j]);
- std::swap(upper_y[i],upper_y[j]);
- std::swap(upper_z[i],upper_z[j]);
- }
-
- /*! swap the children of two nodes */
- __forceinline static void swap(AABBNode_t* a, size_t i, AABBNode_t* b, size_t j)
- {
- assert(i<N && j<N);
- std::swap(a->children[i],b->children[j]);
- std::swap(a->lower_x[i],b->lower_x[j]);
- std::swap(a->lower_y[i],b->lower_y[j]);
- std::swap(a->lower_z[i],b->lower_z[j]);
- std::swap(a->upper_x[i],b->upper_x[j]);
- std::swap(a->upper_y[i],b->upper_y[j]);
- std::swap(a->upper_z[i],b->upper_z[j]);
- }
-
- /*! compacts a node (moves empty children to the end) */
- __forceinline static void compact(AABBNode_t* a)
- {
- /* find right most filled node */
- ssize_t j=N;
- for (j=j-1; j>=0; j--)
- if (a->child(j) != NodeRef::emptyNode)
- break;
-
- /* replace empty nodes with filled nodes */
- for (ssize_t i=0; i<j; i++) {
- if (a->child(i) == NodeRef::emptyNode) {
- a->swap(i,j);
- for (j=j-1; j>i; j--)
- if (a->child(j) != NodeRef::emptyNode)
- break;
- }
- }
- }
-
- /*! Returns reference to specified child */
- __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
- __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
-
- /*! output operator */
- friend embree_ostream operator<<(embree_ostream o, const AABBNode_t& n)
- {
- o << "AABBNode { " << embree_endl;
- o << " lower_x " << n.lower_x << embree_endl;
- o << " upper_x " << n.upper_x << embree_endl;
- o << " lower_y " << n.lower_y << embree_endl;
- o << " upper_y " << n.upper_y << embree_endl;
- o << " lower_z " << n.lower_z << embree_endl;
- o << " upper_z " << n.upper_z << embree_endl;
- o << " children = ";
- for (size_t i=0; i<N; i++) o << n.children[i] << " ";
- o << embree_endl;
- o << "}" << embree_endl;
- return o;
- }
-
- public:
- vfloat<N> lower_x; //!< X dimension of lower bounds of all N children.
- vfloat<N> upper_x; //!< X dimension of upper bounds of all N children.
- vfloat<N> lower_y; //!< Y dimension of lower bounds of all N children.
- vfloat<N> upper_y; //!< Y dimension of upper bounds of all N children.
- vfloat<N> lower_z; //!< Z dimension of lower bounds of all N children.
- vfloat<N> upper_z; //!< Z dimension of upper bounds of all N children.
- };
-
- template<>
- __forceinline void AABBNode_t<NodeRefPtr<4>,4>::bounds(BBox<vfloat4>& bounds0, BBox<vfloat4>& bounds1, BBox<vfloat4>& bounds2, BBox<vfloat4>& bounds3) const {
- transpose(lower_x,lower_y,lower_z,vfloat4(zero),bounds0.lower,bounds1.lower,bounds2.lower,bounds3.lower);
- transpose(upper_x,upper_y,upper_z,vfloat4(zero),bounds0.upper,bounds1.upper,bounds2.upper,bounds3.upper);
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb_mb.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb_mb.h
deleted file mode 100644
index 501f4bce5b..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb_mb.h
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_node_base.h"
-
-namespace embree
-{
- /*! Motion Blur AABBNode */
- template<typename NodeRef, int N>
- struct AABBNodeMB_t : public BaseNode_t<NodeRef, N>
- {
- using BaseNode_t<NodeRef,N>::children;
- typedef BVHNodeRecord<NodeRef> NodeRecord;
- typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
- typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
-
- struct Create
- {
- template<typename BuildRecord>
- __forceinline NodeRef operator() (BuildRecord* children, const size_t num, const FastAllocator::CachedAllocator& alloc) const
- {
- AABBNodeMB_t* node = (AABBNodeMB_t*) alloc.malloc0(sizeof(AABBNodeMB_t),NodeRef::byteNodeAlignment); node->clear();
- return NodeRef::encodeNode(node);
- }
- };
-
- struct Set
- {
- template<typename BuildRecord>
- __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
- {
- AABBNodeMB_t* node = ref.getAABBNodeMB();
-
- LBBox3fa bounds = empty;
- for (size_t i=0; i<num; i++) {
- node->setRef(i,children[i].ref);
- node->setBounds(i,children[i].lbounds);
- bounds.extend(children[i].lbounds);
- }
- return NodeRecordMB(ref,bounds);
- }
- };
-
- struct SetTimeRange
- {
- __forceinline SetTimeRange(BBox1f tbounds) : tbounds(tbounds) {}
-
- template<typename BuildRecord>
- __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
- {
- AABBNodeMB_t* node = ref.getAABBNodeMB();
-
- LBBox3fa bounds = empty;
- for (size_t i=0; i<num; i++) {
- node->setRef(i, children[i].ref);
- node->setBounds(i, children[i].lbounds, tbounds);
- bounds.extend(children[i].lbounds);
- }
- return NodeRecordMB(ref,bounds);
- }
-
- BBox1f tbounds;
- };
-
- /*! Clears the node. */
- __forceinline void clear() {
- lower_x = lower_y = lower_z = vfloat<N>(pos_inf);
- upper_x = upper_y = upper_z = vfloat<N>(neg_inf);
- lower_dx = lower_dy = lower_dz = vfloat<N>(0.0f);
- upper_dx = upper_dy = upper_dz = vfloat<N>(0.0f);
- BaseNode_t<NodeRef,N>::clear();
- }
-
- /*! Sets ID of child. */
- __forceinline void setRef(size_t i, NodeRef ref) {
- children[i] = ref;
- }
-
- /*! Sets bounding box of child. */
- __forceinline void setBounds(size_t i, const BBox3fa& bounds0_i, const BBox3fa& bounds1_i)
- {
- /*! for empty bounds we have to avoid inf-inf=nan */
- BBox3fa bounds0(min(bounds0_i.lower,Vec3fa(+FLT_MAX)),max(bounds0_i.upper,Vec3fa(-FLT_MAX)));
- BBox3fa bounds1(min(bounds1_i.lower,Vec3fa(+FLT_MAX)),max(bounds1_i.upper,Vec3fa(-FLT_MAX)));
- bounds0 = bounds0.enlarge_by(4.0f*float(ulp));
- bounds1 = bounds1.enlarge_by(4.0f*float(ulp));
- Vec3fa dlower = bounds1.lower-bounds0.lower;
- Vec3fa dupper = bounds1.upper-bounds0.upper;
-
- lower_x[i] = bounds0.lower.x; lower_y[i] = bounds0.lower.y; lower_z[i] = bounds0.lower.z;
- upper_x[i] = bounds0.upper.x; upper_y[i] = bounds0.upper.y; upper_z[i] = bounds0.upper.z;
-
- lower_dx[i] = dlower.x; lower_dy[i] = dlower.y; lower_dz[i] = dlower.z;
- upper_dx[i] = dupper.x; upper_dy[i] = dupper.y; upper_dz[i] = dupper.z;
- }
-
- /*! Sets bounding box of child. */
- __forceinline void setBounds(size_t i, const LBBox3fa& bounds) {
- setBounds(i, bounds.bounds0, bounds.bounds1);
- }
-
- /*! Sets bounding box of child. */
- __forceinline void setBounds(size_t i, const LBBox3fa& bounds, const BBox1f& tbounds) {
- setBounds(i, bounds.global(tbounds));
- }
-
- /*! Sets bounding box and ID of child. */
- __forceinline void set(size_t i, NodeRef ref, const BBox3fa& bounds) {
- lower_x[i] = bounds.lower.x; lower_y[i] = bounds.lower.y; lower_z[i] = bounds.lower.z;
- upper_x[i] = bounds.upper.x; upper_y[i] = bounds.upper.y; upper_z[i] = bounds.upper.z;
- children[i] = ref;
- }
-
- /*! Sets bounding box and ID of child. */
- __forceinline void set(size_t i, const NodeRecordMB4D& child)
- {
- setRef(i, child.ref);
- setBounds(i, child.lbounds, child.dt);
- }
-
- /*! Return bounding box for time 0 */
- __forceinline BBox3fa bounds0(size_t i) const {
- return BBox3fa(Vec3fa(lower_x[i],lower_y[i],lower_z[i]),
- Vec3fa(upper_x[i],upper_y[i],upper_z[i]));
- }
-
- /*! Return bounding box for time 1 */
- __forceinline BBox3fa bounds1(size_t i) const {
- return BBox3fa(Vec3fa(lower_x[i]+lower_dx[i],lower_y[i]+lower_dy[i],lower_z[i]+lower_dz[i]),
- Vec3fa(upper_x[i]+upper_dx[i],upper_y[i]+upper_dy[i],upper_z[i]+upper_dz[i]));
- }
-
- /*! Returns bounds of node. */
- __forceinline BBox3fa bounds() const {
- return BBox3fa(Vec3fa(reduce_min(min(lower_x,lower_x+lower_dx)),
- reduce_min(min(lower_y,lower_y+lower_dy)),
- reduce_min(min(lower_z,lower_z+lower_dz))),
- Vec3fa(reduce_max(max(upper_x,upper_x+upper_dx)),
- reduce_max(max(upper_y,upper_y+upper_dy)),
- reduce_max(max(upper_z,upper_z+upper_dz))));
- }
-
- /*! Return bounding box of child i */
- __forceinline BBox3fa bounds(size_t i) const {
- return merge(bounds0(i),bounds1(i));
- }
-
- /*! Return linear bounding box of child i */
- __forceinline LBBox3fa lbounds(size_t i) const {
- return LBBox3fa(bounds0(i),bounds1(i));
- }
-
- /*! Return bounding box of child i at specified time */
- __forceinline BBox3fa bounds(size_t i, float time) const {
- return lerp(bounds0(i),bounds1(i),time);
- }
-
- /*! Returns the expected surface area when randomly sampling the time. */
- __forceinline float expectedHalfArea(size_t i) const {
- return lbounds(i).expectedHalfArea();
- }
-
- /*! Returns the expected surface area when randomly sampling the time. */
- __forceinline float expectedHalfArea(size_t i, const BBox1f& t0t1) const {
- return lbounds(i).expectedHalfArea(t0t1);
- }
-
- /*! swap two children of the node */
- __forceinline void swap(size_t i, size_t j)
- {
- assert(i<N && j<N);
- std::swap(children[i],children[j]);
-
- std::swap(lower_x[i],lower_x[j]);
- std::swap(upper_x[i],upper_x[j]);
- std::swap(lower_y[i],lower_y[j]);
- std::swap(upper_y[i],upper_y[j]);
- std::swap(lower_z[i],lower_z[j]);
- std::swap(upper_z[i],upper_z[j]);
-
- std::swap(lower_dx[i],lower_dx[j]);
- std::swap(upper_dx[i],upper_dx[j]);
- std::swap(lower_dy[i],lower_dy[j]);
- std::swap(upper_dy[i],upper_dy[j]);
- std::swap(lower_dz[i],lower_dz[j]);
- std::swap(upper_dz[i],upper_dz[j]);
- }
-
- /*! compacts a node (moves empty children to the end) */
- __forceinline static void compact(AABBNodeMB_t* a)
- {
- /* find right most filled node */
- ssize_t j=N;
- for (j=j-1; j>=0; j--)
- if (a->child(j) != NodeRef::emptyNode)
- break;
-
- /* replace empty nodes with filled nodes */
- for (ssize_t i=0; i<j; i++) {
- if (a->child(i) == NodeRef::emptyNode) {
- a->swap(i,j);
- for (j=j-1; j>i; j--)
- if (a->child(j) != NodeRef::emptyNode)
- break;
- }
- }
- }
-
- /*! Returns reference to specified child */
- __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
- __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
-
- /*! stream output operator */
- friend embree_ostream operator<<(embree_ostream cout, const AABBNodeMB_t& n)
- {
- cout << "AABBNodeMB {" << embree_endl;
- for (size_t i=0; i<N; i++)
- {
- const BBox3fa b0 = n.bounds0(i);
- const BBox3fa b1 = n.bounds1(i);
- cout << " child" << i << " { " << embree_endl;
- cout << " bounds0 = " << b0 << ", " << embree_endl;
- cout << " bounds1 = " << b1 << ", " << embree_endl;
- cout << " }";
- }
- cout << "}";
- return cout;
- }
-
- public:
- vfloat<N> lower_x; //!< X dimension of lower bounds of all N children.
- vfloat<N> upper_x; //!< X dimension of upper bounds of all N children.
- vfloat<N> lower_y; //!< Y dimension of lower bounds of all N children.
- vfloat<N> upper_y; //!< Y dimension of upper bounds of all N children.
- vfloat<N> lower_z; //!< Z dimension of lower bounds of all N children.
- vfloat<N> upper_z; //!< Z dimension of upper bounds of all N children.
-
- vfloat<N> lower_dx; //!< X dimension of lower bounds of all N children.
- vfloat<N> upper_dx; //!< X dimension of upper bounds of all N children.
- vfloat<N> lower_dy; //!< Y dimension of lower bounds of all N children.
- vfloat<N> upper_dy; //!< Y dimension of upper bounds of all N children.
- vfloat<N> lower_dz; //!< Z dimension of lower bounds of all N children.
- vfloat<N> upper_dz; //!< Z dimension of upper bounds of all N children.
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb_mb4d.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb_mb4d.h
deleted file mode 100644
index e968bbbc39..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_aabb_mb4d.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_node_aabb_mb.h"
-
-namespace embree
-{
- /*! Aligned 4D Motion Blur Node */
- template<typename NodeRef, int N>
- struct AABBNodeMB4D_t : public AABBNodeMB_t<NodeRef, N>
- {
- using BaseNode_t<NodeRef,N>::children;
- using AABBNodeMB_t<NodeRef,N>::set;
-
- typedef BVHNodeRecord<NodeRef> NodeRecord;
- typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
- typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
-
- struct Create
- {
- template<typename BuildRecord>
- __forceinline NodeRef operator() (BuildRecord*, const size_t, const FastAllocator::CachedAllocator& alloc, bool hasTimeSplits = true) const
- {
- if (hasTimeSplits)
- {
- AABBNodeMB4D_t* node = (AABBNodeMB4D_t*) alloc.malloc0(sizeof(AABBNodeMB4D_t),NodeRef::byteNodeAlignment); node->clear();
- return NodeRef::encodeNode(node);
- }
- else
- {
- AABBNodeMB_t<NodeRef,N>* node = (AABBNodeMB_t<NodeRef,N>*) alloc.malloc0(sizeof(AABBNodeMB_t<NodeRef,N>),NodeRef::byteNodeAlignment); node->clear();
- return NodeRef::encodeNode(node);
- }
- }
- };
-
- struct Set
- {
- template<typename BuildRecord>
- __forceinline void operator() (const BuildRecord&, const BuildRecord*, NodeRef ref, NodeRecordMB4D* children, const size_t num) const
- {
- if (likely(ref.isAABBNodeMB())) {
- for (size_t i=0; i<num; i++)
- ref.getAABBNodeMB()->set(i, children[i]);
- } else {
- for (size_t i=0; i<num; i++)
- ref.getAABBNodeMB4D()->set(i, children[i]);
- }
- }
- };
-
- /*! Clears the node. */
- __forceinline void clear() {
- lower_t = vfloat<N>(pos_inf);
- upper_t = vfloat<N>(neg_inf);
- AABBNodeMB_t<NodeRef,N>::clear();
- }
-
- /*! Sets bounding box of child. */
- __forceinline void setBounds(size_t i, const LBBox3fa& bounds, const BBox1f& tbounds)
- {
- AABBNodeMB_t<NodeRef,N>::setBounds(i, bounds.global(tbounds));
- lower_t[i] = tbounds.lower;
- upper_t[i] = tbounds.upper == 1.0f ? 1.0f+float(ulp) : tbounds.upper;
- }
-
- /*! Sets bounding box and ID of child. */
- __forceinline void set(size_t i, const NodeRecordMB4D& child) {
- AABBNodeMB_t<NodeRef,N>::setRef(i,child.ref);
- setBounds(i, child.lbounds, child.dt);
- }
-
- /*! Returns the expected surface area when randomly sampling the time. */
- __forceinline float expectedHalfArea(size_t i) const {
- return AABBNodeMB_t<NodeRef,N>::lbounds(i).expectedHalfArea(timeRange(i));
- }
-
- /*! returns time range for specified child */
- __forceinline BBox1f timeRange(size_t i) const {
- return BBox1f(lower_t[i],upper_t[i]);
- }
-
- /*! stream output operator */
- friend embree_ostream operator<<(embree_ostream cout, const AABBNodeMB4D_t& n)
- {
- cout << "AABBNodeMB4D {" << embree_endl;
- for (size_t i=0; i<N; i++)
- {
- const BBox3fa b0 = n.bounds0(i);
- const BBox3fa b1 = n.bounds1(i);
- cout << " child" << i << " { " << embree_endl;
- cout << " bounds0 = " << lerp(b0,b1,n.lower_t[i]) << ", " << embree_endl;
- cout << " bounds1 = " << lerp(b0,b1,n.upper_t[i]) << ", " << embree_endl;
- cout << " time_bounds = " << n.lower_t[i] << ", " << n.upper_t[i] << embree_endl;
- cout << " }";
- }
- cout << "}";
- return cout;
- }
-
- public:
- vfloat<N> lower_t; //!< time dimension of lower bounds of all N children
- vfloat<N> upper_t; //!< time dimension of upper bounds of all N children
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_base.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_node_base.h
deleted file mode 100644
index 8268f3b932..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_base.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_node_ref.h"
-
-namespace embree
-{
-
- /*! BVHN Base Node */
- template<typename NodeRef, int N>
- struct BaseNode_t
- {
- /*! Clears the node. */
- __forceinline void clear()
- {
- for (size_t i=0; i<N; i++)
- children[i] = NodeRef::emptyNode;
- }
-
- /*! Returns reference to specified child */
- __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
- __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
-
- /*! verifies the node */
- __forceinline bool verify() const
- {
- for (size_t i=0; i<N; i++) {
- if (child(i) == NodeRef::emptyNode) {
- for (; i<N; i++) {
- if (child(i) != NodeRef::emptyNode)
- return false;
- }
- break;
- }
- }
- return true;
- }
-
- NodeRef children[N]; //!< Pointer to the N children (can be a node or leaf)
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_obb.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_node_obb.h
deleted file mode 100644
index fa7cc08211..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_obb.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_node_base.h"
-
-namespace embree
-{
- /*! Node with unaligned bounds */
- template<typename NodeRef, int N>
- struct OBBNode_t : public BaseNode_t<NodeRef, N>
- {
- using BaseNode_t<NodeRef,N>::children;
-
- struct Create
- {
- __forceinline NodeRef operator() (const FastAllocator::CachedAllocator& alloc) const
- {
- OBBNode_t* node = (OBBNode_t*) alloc.malloc0(sizeof(OBBNode_t),NodeRef::byteNodeAlignment); node->clear();
- return NodeRef::encodeNode(node);
- }
- };
-
- struct Set
- {
- __forceinline void operator() (NodeRef node, size_t i, NodeRef child, const OBBox3fa& bounds) const {
- node.ungetAABBNode()->setRef(i,child);
- node.ungetAABBNode()->setBounds(i,bounds);
- }
- };
-
- /*! Clears the node. */
- __forceinline void clear()
- {
- naabb.l.vx = Vec3fa(nan);
- naabb.l.vy = Vec3fa(nan);
- naabb.l.vz = Vec3fa(nan);
- naabb.p = Vec3fa(nan);
- BaseNode_t<NodeRef,N>::clear();
- }
-
- /*! Sets bounding box. */
- __forceinline void setBounds(size_t i, const OBBox3fa& b)
- {
- assert(i < N);
-
- AffineSpace3fa space = b.space;
- space.p -= b.bounds.lower;
- space = AffineSpace3fa::scale(1.0f/max(Vec3fa(1E-19f),b.bounds.upper-b.bounds.lower))*space;
-
- naabb.l.vx.x[i] = space.l.vx.x;
- naabb.l.vx.y[i] = space.l.vx.y;
- naabb.l.vx.z[i] = space.l.vx.z;
-
- naabb.l.vy.x[i] = space.l.vy.x;
- naabb.l.vy.y[i] = space.l.vy.y;
- naabb.l.vy.z[i] = space.l.vy.z;
-
- naabb.l.vz.x[i] = space.l.vz.x;
- naabb.l.vz.y[i] = space.l.vz.y;
- naabb.l.vz.z[i] = space.l.vz.z;
-
- naabb.p.x[i] = space.p.x;
- naabb.p.y[i] = space.p.y;
- naabb.p.z[i] = space.p.z;
- }
-
- /*! Sets ID of child. */
- __forceinline void setRef(size_t i, const NodeRef& ref) {
- assert(i < N);
- children[i] = ref;
- }
-
- /*! Returns the extent of the bounds of the ith child */
- __forceinline Vec3fa extent(size_t i) const {
- assert(i<N);
- const Vec3fa vx(naabb.l.vx.x[i],naabb.l.vx.y[i],naabb.l.vx.z[i]);
- const Vec3fa vy(naabb.l.vy.x[i],naabb.l.vy.y[i],naabb.l.vy.z[i]);
- const Vec3fa vz(naabb.l.vz.x[i],naabb.l.vz.y[i],naabb.l.vz.z[i]);
- return rsqrt(vx*vx + vy*vy + vz*vz);
- }
-
- /*! Returns reference to specified child */
- __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
- __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
-
- /*! output operator */
- friend embree_ostream operator<<(embree_ostream o, const OBBNode_t& n)
- {
- o << "UnAABBNode { " << n.naabb << " } " << embree_endl;
- return o;
- }
-
- public:
- AffineSpace3vf<N> naabb; //!< non-axis aligned bounding boxes (bounds are [0,1] in specified space)
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_obb_mb.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_node_obb_mb.h
deleted file mode 100644
index 834cf5ec28..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_obb_mb.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_node_base.h"
-
-namespace embree
-{
- template<typename NodeRef, int N>
- struct OBBNodeMB_t : public BaseNode_t<NodeRef, N>
- {
- using BaseNode_t<NodeRef,N>::children;
-
- struct Create
- {
- __forceinline NodeRef operator() (const FastAllocator::CachedAllocator& alloc) const
- {
- OBBNodeMB_t* node = (OBBNodeMB_t*) alloc.malloc0(sizeof(OBBNodeMB_t),NodeRef::byteNodeAlignment); node->clear();
- return NodeRef::encodeNode(node);
- }
- };
-
- struct Set
- {
- __forceinline void operator() (NodeRef node, size_t i, NodeRef child, const LinearSpace3fa& space, const LBBox3fa& lbounds, const BBox1f dt) const {
- node.ungetAABBNodeMB()->setRef(i,child);
- node.ungetAABBNodeMB()->setBounds(i,space,lbounds.global(dt));
- }
- };
-
- /*! Clears the node. */
- __forceinline void clear()
- {
- space0 = one;
- //b0.lower = b0.upper = Vec3fa(nan);
- b1.lower = b1.upper = Vec3fa(nan);
- BaseNode_t<NodeRef,N>::clear();
- }
-
- /*! Sets space and bounding boxes. */
- __forceinline void setBounds(size_t i, const AffineSpace3fa& space, const LBBox3fa& lbounds) {
- setBounds(i,space,lbounds.bounds0,lbounds.bounds1);
- }
-
- /*! Sets space and bounding boxes. */
- __forceinline void setBounds(size_t i, const AffineSpace3fa& s0, const BBox3fa& a, const BBox3fa& c)
- {
- assert(i < N);
-
- AffineSpace3fa space = s0;
- space.p -= a.lower;
- Vec3fa scale = 1.0f/max(Vec3fa(1E-19f),a.upper-a.lower);
- space = AffineSpace3fa::scale(scale)*space;
- BBox3fa a1((a.lower-a.lower)*scale,(a.upper-a.lower)*scale);
- BBox3fa c1((c.lower-a.lower)*scale,(c.upper-a.lower)*scale);
-
- space0.l.vx.x[i] = space.l.vx.x; space0.l.vx.y[i] = space.l.vx.y; space0.l.vx.z[i] = space.l.vx.z;
- space0.l.vy.x[i] = space.l.vy.x; space0.l.vy.y[i] = space.l.vy.y; space0.l.vy.z[i] = space.l.vy.z;
- space0.l.vz.x[i] = space.l.vz.x; space0.l.vz.y[i] = space.l.vz.y; space0.l.vz.z[i] = space.l.vz.z;
- space0.p .x[i] = space.p .x; space0.p .y[i] = space.p .y; space0.p .z[i] = space.p .z;
-
- /*b0.lower.x[i] = a1.lower.x; b0.lower.y[i] = a1.lower.y; b0.lower.z[i] = a1.lower.z;
- b0.upper.x[i] = a1.upper.x; b0.upper.y[i] = a1.upper.y; b0.upper.z[i] = a1.upper.z;*/
-
- b1.lower.x[i] = c1.lower.x; b1.lower.y[i] = c1.lower.y; b1.lower.z[i] = c1.lower.z;
- b1.upper.x[i] = c1.upper.x; b1.upper.y[i] = c1.upper.y; b1.upper.z[i] = c1.upper.z;
- }
-
- /*! Sets ID of child. */
- __forceinline void setRef(size_t i, const NodeRef& ref) {
- assert(i < N);
- children[i] = ref;
- }
-
- /*! Returns the extent of the bounds of the ith child */
- __forceinline Vec3fa extent0(size_t i) const {
- assert(i < N);
- const Vec3fa vx(space0.l.vx.x[i],space0.l.vx.y[i],space0.l.vx.z[i]);
- const Vec3fa vy(space0.l.vy.x[i],space0.l.vy.y[i],space0.l.vy.z[i]);
- const Vec3fa vz(space0.l.vz.x[i],space0.l.vz.y[i],space0.l.vz.z[i]);
- return rsqrt(vx*vx + vy*vy + vz*vz);
- }
-
- public:
- AffineSpace3vf<N> space0;
- //BBox3vf<N> b0; // these are the unit bounds
- BBox3vf<N> b1;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_qaabb.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_node_qaabb.h
deleted file mode 100644
index 5212821f3f..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_qaabb.h
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh_node_base.h"
-
-namespace embree
-{
- /*! BVHN Quantized Node */
- template<int N>
- struct __aligned(8) QuantizedBaseNode_t
- {
- typedef unsigned char T;
- static const T MIN_QUAN = 0;
- static const T MAX_QUAN = 255;
-
- /*! Clears the node. */
- __forceinline void clear() {
- for (size_t i=0; i<N; i++) lower_x[i] = lower_y[i] = lower_z[i] = MAX_QUAN;
- for (size_t i=0; i<N; i++) upper_x[i] = upper_y[i] = upper_z[i] = MIN_QUAN;
- }
-
- /*! Returns bounds of specified child. */
- __forceinline BBox3fa bounds(size_t i) const
- {
- assert(i < N);
- const Vec3fa lower(madd(scale.x,(float)lower_x[i],start.x),
- madd(scale.y,(float)lower_y[i],start.y),
- madd(scale.z,(float)lower_z[i],start.z));
- const Vec3fa upper(madd(scale.x,(float)upper_x[i],start.x),
- madd(scale.y,(float)upper_y[i],start.y),
- madd(scale.z,(float)upper_z[i],start.z));
- return BBox3fa(lower,upper);
- }
-
- /*! Returns extent of bounds of specified child. */
- __forceinline Vec3fa extent(size_t i) const {
- return bounds(i).size();
- }
-
- static __forceinline void init_dim(const vfloat<N> &lower,
- const vfloat<N> &upper,
- T lower_quant[N],
- T upper_quant[N],
- float &start,
- float &scale)
- {
- /* quantize bounds */
- const vbool<N> m_valid = lower != vfloat<N>(pos_inf);
- const float minF = reduce_min(lower);
- const float maxF = reduce_max(upper);
- float diff = (1.0f+2.0f*float(ulp))*(maxF - minF);
- float decode_scale = diff / float(MAX_QUAN);
- if (decode_scale == 0.0f) decode_scale = 2.0f*FLT_MIN; // result may have been flushed to zero
- assert(madd(decode_scale,float(MAX_QUAN),minF) >= maxF);
- const float encode_scale = diff > 0 ? (float(MAX_QUAN) / diff) : 0.0f;
- vint<N> ilower = max(vint<N>(floor((lower - vfloat<N>(minF))*vfloat<N>(encode_scale))),MIN_QUAN);
- vint<N> iupper = min(vint<N>(ceil ((upper - vfloat<N>(minF))*vfloat<N>(encode_scale))),MAX_QUAN);
-
- /* lower/upper correction */
- vbool<N> m_lower_correction = (madd(vfloat<N>(ilower),decode_scale,minF)) > lower;
- vbool<N> m_upper_correction = (madd(vfloat<N>(iupper),decode_scale,minF)) < upper;
- ilower = max(select(m_lower_correction,ilower-1,ilower),MIN_QUAN);
- iupper = min(select(m_upper_correction,iupper+1,iupper),MAX_QUAN);
-
- /* disable invalid lanes */
- ilower = select(m_valid,ilower,MAX_QUAN);
- iupper = select(m_valid,iupper,MIN_QUAN);
-
- /* store as uchar to memory */
- vint<N>::store(lower_quant,ilower);
- vint<N>::store(upper_quant,iupper);
- start = minF;
- scale = decode_scale;
-
-#if defined(DEBUG)
- vfloat<N> extract_lower( vint<N>::loadu(lower_quant) );
- vfloat<N> extract_upper( vint<N>::loadu(upper_quant) );
- vfloat<N> final_extract_lower = madd(extract_lower,decode_scale,minF);
- vfloat<N> final_extract_upper = madd(extract_upper,decode_scale,minF);
- assert( (movemask(final_extract_lower <= lower ) & movemask(m_valid)) == movemask(m_valid));
- assert( (movemask(final_extract_upper >= upper ) & movemask(m_valid)) == movemask(m_valid));
-#endif
- }
-
- __forceinline void init_dim(AABBNode_t<NodeRefPtr<N>,N>& node)
- {
- init_dim(node.lower_x,node.upper_x,lower_x,upper_x,start.x,scale.x);
- init_dim(node.lower_y,node.upper_y,lower_y,upper_y,start.y,scale.y);
- init_dim(node.lower_z,node.upper_z,lower_z,upper_z,start.z,scale.z);
- }
-
- __forceinline vbool<N> validMask() const { return vint<N>::loadu(lower_x) <= vint<N>::loadu(upper_x); }
-
-#if defined(__AVX512F__) // KNL
- __forceinline vbool16 validMask16() const { return le(0xff,vint<16>::loadu(lower_x),vint<16>::loadu(upper_x)); }
-#endif
- __forceinline vfloat<N> dequantizeLowerX() const { return madd(vfloat<N>(vint<N>::loadu(lower_x)),scale.x,vfloat<N>(start.x)); }
-
- __forceinline vfloat<N> dequantizeUpperX() const { return madd(vfloat<N>(vint<N>::loadu(upper_x)),scale.x,vfloat<N>(start.x)); }
-
- __forceinline vfloat<N> dequantizeLowerY() const { return madd(vfloat<N>(vint<N>::loadu(lower_y)),scale.y,vfloat<N>(start.y)); }
-
- __forceinline vfloat<N> dequantizeUpperY() const { return madd(vfloat<N>(vint<N>::loadu(upper_y)),scale.y,vfloat<N>(start.y)); }
-
- __forceinline vfloat<N> dequantizeLowerZ() const { return madd(vfloat<N>(vint<N>::loadu(lower_z)),scale.z,vfloat<N>(start.z)); }
-
- __forceinline vfloat<N> dequantizeUpperZ() const { return madd(vfloat<N>(vint<N>::loadu(upper_z)),scale.z,vfloat<N>(start.z)); }
-
- template <int M>
- __forceinline vfloat<M> dequantize(const size_t offset) const { return vfloat<M>(vint<M>::loadu(all_planes+offset)); }
-
-#if defined(__AVX512F__)
- __forceinline vfloat16 dequantizeLowerUpperX(const vint16 &p) const { return madd(vfloat16(permute(vint<16>::loadu(lower_x),p)),scale.x,vfloat16(start.x)); }
- __forceinline vfloat16 dequantizeLowerUpperY(const vint16 &p) const { return madd(vfloat16(permute(vint<16>::loadu(lower_y),p)),scale.y,vfloat16(start.y)); }
- __forceinline vfloat16 dequantizeLowerUpperZ(const vint16 &p) const { return madd(vfloat16(permute(vint<16>::loadu(lower_z),p)),scale.z,vfloat16(start.z)); }
-#endif
-
- union {
- struct {
- T lower_x[N]; //!< 8bit discretized X dimension of lower bounds of all N children
- T upper_x[N]; //!< 8bit discretized X dimension of upper bounds of all N children
- T lower_y[N]; //!< 8bit discretized Y dimension of lower bounds of all N children
- T upper_y[N]; //!< 8bit discretized Y dimension of upper bounds of all N children
- T lower_z[N]; //!< 8bit discretized Z dimension of lower bounds of all N children
- T upper_z[N]; //!< 8bit discretized Z dimension of upper bounds of all N children
- };
- T all_planes[6*N];
- };
-
- Vec3f start;
- Vec3f scale;
-
- friend embree_ostream operator<<(embree_ostream o, const QuantizedBaseNode_t& n)
- {
- o << "QuantizedBaseNode { " << embree_endl;
- o << " start " << n.start << embree_endl;
- o << " scale " << n.scale << embree_endl;
- o << " lower_x " << vuint<N>::loadu(n.lower_x) << embree_endl;
- o << " upper_x " << vuint<N>::loadu(n.upper_x) << embree_endl;
- o << " lower_y " << vuint<N>::loadu(n.lower_y) << embree_endl;
- o << " upper_y " << vuint<N>::loadu(n.upper_y) << embree_endl;
- o << " lower_z " << vuint<N>::loadu(n.lower_z) << embree_endl;
- o << " upper_z " << vuint<N>::loadu(n.upper_z) << embree_endl;
- o << "}" << embree_endl;
- return o;
- }
-
- };
-
- template<typename NodeRef, int N>
- struct __aligned(8) QuantizedNode_t : public BaseNode_t<NodeRef, N>, QuantizedBaseNode_t<N>
- {
- using BaseNode_t<NodeRef,N>::children;
- using QuantizedBaseNode_t<N>::lower_x;
- using QuantizedBaseNode_t<N>::upper_x;
- using QuantizedBaseNode_t<N>::lower_y;
- using QuantizedBaseNode_t<N>::upper_y;
- using QuantizedBaseNode_t<N>::lower_z;
- using QuantizedBaseNode_t<N>::upper_z;
- using QuantizedBaseNode_t<N>::start;
- using QuantizedBaseNode_t<N>::scale;
- using QuantizedBaseNode_t<N>::init_dim;
-
- __forceinline void setRef(size_t i, const NodeRef& ref) {
- assert(i < N);
- children[i] = ref;
- }
-
- struct Create2
- {
- template<typename BuildRecord>
- __forceinline NodeRef operator() (BuildRecord* children, const size_t n, const FastAllocator::CachedAllocator& alloc) const
- {
- __aligned(64) AABBNode_t<NodeRef,N> node;
- node.clear();
- for (size_t i=0; i<n; i++) {
- node.setBounds(i,children[i].bounds());
- }
- QuantizedNode_t *qnode = (QuantizedNode_t*) alloc.malloc0(sizeof(QuantizedNode_t), NodeRef::byteAlignment);
- qnode->init(node);
-
- return (size_t)qnode | NodeRef::tyQuantizedNode;
- }
- };
-
- struct Set2
- {
- template<typename BuildRecord>
- __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
- {
- QuantizedNode_t* node = ref.quantizedNode();
- for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
- return ref;
- }
- };
-
- __forceinline void init(AABBNode_t<NodeRef,N>& node)
- {
- for (size_t i=0;i<N;i++) children[i] = NodeRef::emptyNode;
- init_dim(node);
- }
-
- };
-
- /*! BVHN Quantized Node */
- template<int N>
- struct __aligned(8) QuantizedBaseNodeMB_t
- {
- QuantizedBaseNode_t<N> node0;
- QuantizedBaseNode_t<N> node1;
-
- /*! Clears the node. */
- __forceinline void clear() {
- node0.clear();
- node1.clear();
- }
-
- /*! Returns bounds of specified child. */
- __forceinline BBox3fa bounds(size_t i) const
- {
- assert(i < N);
- BBox3fa bounds0 = node0.bounds(i);
- BBox3fa bounds1 = node1.bounds(i);
- bounds0.extend(bounds1);
- return bounds0;
- }
-
- /*! Returns extent of bounds of specified child. */
- __forceinline Vec3fa extent(size_t i) const {
- return bounds(i).size();
- }
-
- __forceinline vbool<N> validMask() const { return node0.validMask(); }
-
- template<typename T>
- __forceinline vfloat<N> dequantizeLowerX(const T t) const { return lerp(node0.dequantizeLowerX(),node1.dequantizeLowerX(),t); }
- template<typename T>
- __forceinline vfloat<N> dequantizeUpperX(const T t) const { return lerp(node0.dequantizeUpperX(),node1.dequantizeUpperX(),t); }
- template<typename T>
- __forceinline vfloat<N> dequantizeLowerY(const T t) const { return lerp(node0.dequantizeLowerY(),node1.dequantizeLowerY(),t); }
- template<typename T>
- __forceinline vfloat<N> dequantizeUpperY(const T t) const { return lerp(node0.dequantizeUpperY(),node1.dequantizeUpperY(),t); }
- template<typename T>
- __forceinline vfloat<N> dequantizeLowerZ(const T t) const { return lerp(node0.dequantizeLowerZ(),node1.dequantizeLowerZ(),t); }
- template<typename T>
- __forceinline vfloat<N> dequantizeUpperZ(const T t) const { return lerp(node0.dequantizeUpperZ(),node1.dequantizeUpperZ(),t); }
-
-
- template<int M>
- __forceinline vfloat<M> dequantizeLowerX(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeLowerX()[i]),vfloat<M>(node1.dequantizeLowerX()[i]),t); }
- template<int M>
- __forceinline vfloat<M> dequantizeUpperX(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeUpperX()[i]),vfloat<M>(node1.dequantizeUpperX()[i]),t); }
- template<int M>
- __forceinline vfloat<M> dequantizeLowerY(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeLowerY()[i]),vfloat<M>(node1.dequantizeLowerY()[i]),t); }
- template<int M>
- __forceinline vfloat<M> dequantizeUpperY(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeUpperY()[i]),vfloat<M>(node1.dequantizeUpperY()[i]),t); }
- template<int M>
- __forceinline vfloat<M> dequantizeLowerZ(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeLowerZ()[i]),vfloat<M>(node1.dequantizeLowerZ()[i]),t); }
- template<int M>
- __forceinline vfloat<M> dequantizeUpperZ(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeUpperZ()[i]),vfloat<M>(node1.dequantizeUpperZ()[i]),t); }
-
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_ref.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_node_ref.h
deleted file mode 100644
index 0f6d4dac7e..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_node_ref.h
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-#include "../common/alloc.h"
-#include "../common/accel.h"
-#include "../common/device.h"
-#include "../common/scene.h"
-#include "../geometry/primitive.h"
-#include "../common/ray.h"
-
-namespace embree
-{
- /* BVH node reference with bounds */
- template<typename NodeRef>
- struct BVHNodeRecord
- {
- __forceinline BVHNodeRecord() {}
- __forceinline BVHNodeRecord(NodeRef ref, const BBox3fa& bounds) : ref(ref), bounds((BBox3fx)bounds) {}
- __forceinline BVHNodeRecord(NodeRef ref, const BBox3fx& bounds) : ref(ref), bounds(bounds) {}
-
- NodeRef ref;
- BBox3fx bounds;
- };
-
- template<typename NodeRef>
- struct BVHNodeRecordMB
- {
- __forceinline BVHNodeRecordMB() {}
- __forceinline BVHNodeRecordMB(NodeRef ref, const LBBox3fa& lbounds) : ref(ref), lbounds(lbounds) {}
-
- NodeRef ref;
- LBBox3fa lbounds;
- };
-
- template<typename NodeRef>
- struct BVHNodeRecordMB4D
- {
- __forceinline BVHNodeRecordMB4D() {}
- __forceinline BVHNodeRecordMB4D(NodeRef ref, const LBBox3fa& lbounds, const BBox1f& dt) : ref(ref), lbounds(lbounds), dt(dt) {}
-
- NodeRef ref;
- LBBox3fa lbounds;
- BBox1f dt;
- };
-
- template<typename NodeRef, int N> struct BaseNode_t;
- template<typename NodeRef, int N> struct AABBNode_t;
- template<typename NodeRef, int N> struct AABBNodeMB_t;
- template<typename NodeRef, int N> struct AABBNodeMB4D_t;
- template<typename NodeRef, int N> struct OBBNode_t;
- template<typename NodeRef, int N> struct OBBNodeMB_t;
- template<typename NodeRef, int N> struct QuantizedNode_t;
- template<typename NodeRef, int N> struct QuantizedNodeMB_t;
-
- /*! Pointer that points to a node or a list of primitives */
- template<int N>
- struct NodeRefPtr
- {
- //template<int NN> friend class BVHN;
-
- /*! Number of bytes the nodes and primitives are minimally aligned to.*/
- static const size_t byteAlignment = 16;
- static const size_t byteNodeAlignment = 4*N;
-
- /*! highest address bit is used as barrier for some algorithms */
- static const size_t barrier_mask = (1LL << (8*sizeof(size_t)-1));
-
- /*! Masks the bits that store the number of items per leaf. */
- static const size_t align_mask = byteAlignment-1;
- static const size_t items_mask = byteAlignment-1;
-
- /*! different supported node types */
- static const size_t tyAABBNode = 0;
- static const size_t tyAABBNodeMB = 1;
- static const size_t tyAABBNodeMB4D = 6;
- static const size_t tyOBBNode = 2;
- static const size_t tyOBBNodeMB = 3;
- static const size_t tyQuantizedNode = 5;
- static const size_t tyLeaf = 8;
-
- /*! Empty node */
- static const size_t emptyNode = tyLeaf;
-
- /*! Invalid node, used as marker in traversal */
- static const size_t invalidNode = (((size_t)-1) & (~items_mask)) | (tyLeaf+0);
- static const size_t popRay = (((size_t)-1) & (~items_mask)) | (tyLeaf+1);
-
- /*! Maximum number of primitive blocks in a leaf. */
- static const size_t maxLeafBlocks = items_mask-tyLeaf;
-
- /*! Default constructor */
- __forceinline NodeRefPtr () {}
-
- /*! Construction from integer */
- __forceinline NodeRefPtr (size_t ptr) : ptr(ptr) {}
-
- /*! Cast to size_t */
- __forceinline operator size_t() const { return ptr; }
-
- /*! Sets the barrier bit. */
- __forceinline void setBarrier() {
-#if defined(__X86_64__) || defined(__aarch64__)
- assert(!isBarrier());
- ptr |= barrier_mask;
-#else
- assert(false);
-#endif
- }
-
- /*! Clears the barrier bit. */
- __forceinline void clearBarrier() {
-#if defined(__X86_64__) || defined(__aarch64__)
- ptr &= ~barrier_mask;
-#else
- assert(false);
-#endif
- }
-
- /*! Checks if this is an barrier. A barrier tells the top level tree rotations how deep to enter the tree. */
- __forceinline bool isBarrier() const { return (ptr & barrier_mask) != 0; }
-
- /*! checks if this is a leaf */
- __forceinline size_t isLeaf() const { return ptr & tyLeaf; }
-
- /*! returns node type */
- __forceinline int type() const { return ptr & (size_t)align_mask; }
-
- /*! checks if this is a node */
- __forceinline int isAABBNode() const { return (ptr & (size_t)align_mask) == tyAABBNode; }
-
- /*! checks if this is a motion blur node */
- __forceinline int isAABBNodeMB() const { return (ptr & (size_t)align_mask) == tyAABBNodeMB; }
-
- /*! checks if this is a 4D motion blur node */
- __forceinline int isAABBNodeMB4D() const { return (ptr & (size_t)align_mask) == tyAABBNodeMB4D; }
-
- /*! checks if this is a node with unaligned bounding boxes */
- __forceinline int isOBBNode() const { return (ptr & (size_t)align_mask) == tyOBBNode; }
-
- /*! checks if this is a motion blur node with unaligned bounding boxes */
- __forceinline int isOBBNodeMB() const { return (ptr & (size_t)align_mask) == tyOBBNodeMB; }
-
- /*! checks if this is a quantized node */
- __forceinline int isQuantizedNode() const { return (ptr & (size_t)align_mask) == tyQuantizedNode; }
-
- /*! Encodes a node */
- static __forceinline NodeRefPtr encodeNode(AABBNode_t<NodeRefPtr,N>* node) {
- assert(!((size_t)node & align_mask));
- return NodeRefPtr((size_t) node);
- }
-
- static __forceinline NodeRefPtr encodeNode(AABBNodeMB_t<NodeRefPtr,N>* node) {
- assert(!((size_t)node & align_mask));
- return NodeRefPtr((size_t) node | tyAABBNodeMB);
- }
-
- static __forceinline NodeRefPtr encodeNode(AABBNodeMB4D_t<NodeRefPtr,N>* node) {
- assert(!((size_t)node & align_mask));
- return NodeRefPtr((size_t) node | tyAABBNodeMB4D);
- }
-
- /*! Encodes an unaligned node */
- static __forceinline NodeRefPtr encodeNode(OBBNode_t<NodeRefPtr,N>* node) {
- return NodeRefPtr((size_t) node | tyOBBNode);
- }
-
- /*! Encodes an unaligned motion blur node */
- static __forceinline NodeRefPtr encodeNode(OBBNodeMB_t<NodeRefPtr,N>* node) {
- return NodeRefPtr((size_t) node | tyOBBNodeMB);
- }
-
- /*! Encodes a leaf */
- static __forceinline NodeRefPtr encodeLeaf(void* tri, size_t num) {
- assert(!((size_t)tri & align_mask));
- assert(num <= maxLeafBlocks);
- return NodeRefPtr((size_t)tri | (tyLeaf+min(num,(size_t)maxLeafBlocks)));
- }
-
- /*! Encodes a leaf */
- static __forceinline NodeRefPtr encodeTypedLeaf(void* ptr, size_t ty) {
- assert(!((size_t)ptr & align_mask));
- return NodeRefPtr((size_t)ptr | (tyLeaf+ty));
- }
-
- /*! returns base node pointer */
- __forceinline BaseNode_t<NodeRefPtr,N>* baseNode()
- {
- assert(!isLeaf());
- return (BaseNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask);
- }
- __forceinline const BaseNode_t<NodeRefPtr,N>* baseNode() const
- {
- assert(!isLeaf());
- return (const BaseNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask);
- }
-
- /*! returns node pointer */
- __forceinline AABBNode_t<NodeRefPtr,N>* getAABBNode() { assert(isAABBNode()); return ( AABBNode_t<NodeRefPtr,N>*)ptr; }
- __forceinline const AABBNode_t<NodeRefPtr,N>* getAABBNode() const { assert(isAABBNode()); return (const AABBNode_t<NodeRefPtr,N>*)ptr; }
-
- /*! returns motion blur node pointer */
- __forceinline AABBNodeMB_t<NodeRefPtr,N>* getAABBNodeMB() { assert(isAABBNodeMB() || isAABBNodeMB4D()); return ( AABBNodeMB_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
- __forceinline const AABBNodeMB_t<NodeRefPtr,N>* getAABBNodeMB() const { assert(isAABBNodeMB() || isAABBNodeMB4D()); return (const AABBNodeMB_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
-
- /*! returns 4D motion blur node pointer */
- __forceinline AABBNodeMB4D_t<NodeRefPtr,N>* getAABBNodeMB4D() { assert(isAABBNodeMB4D()); return ( AABBNodeMB4D_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
- __forceinline const AABBNodeMB4D_t<NodeRefPtr,N>* getAABBNodeMB4D() const { assert(isAABBNodeMB4D()); return (const AABBNodeMB4D_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
-
- /*! returns unaligned node pointer */
- __forceinline OBBNode_t<NodeRefPtr,N>* ungetAABBNode() { assert(isOBBNode()); return ( OBBNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
- __forceinline const OBBNode_t<NodeRefPtr,N>* ungetAABBNode() const { assert(isOBBNode()); return (const OBBNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
-
- /*! returns unaligned motion blur node pointer */
- __forceinline OBBNodeMB_t<NodeRefPtr,N>* ungetAABBNodeMB() { assert(isOBBNodeMB()); return ( OBBNodeMB_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
- __forceinline const OBBNodeMB_t<NodeRefPtr,N>* ungetAABBNodeMB() const { assert(isOBBNodeMB()); return (const OBBNodeMB_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
-
- /*! returns quantized node pointer */
- __forceinline QuantizedNode_t<NodeRefPtr,N>* quantizedNode() { assert(isQuantizedNode()); return ( QuantizedNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask ); }
- __forceinline const QuantizedNode_t<NodeRefPtr,N>* quantizedNode() const { assert(isQuantizedNode()); return (const QuantizedNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask ); }
-
- /*! returns leaf pointer */
- __forceinline char* leaf(size_t& num) const {
- assert(isLeaf());
- num = (ptr & (size_t)items_mask)-tyLeaf;
- return (char*)(ptr & ~(size_t)align_mask);
- }
-
- /*! clear all bit flags */
- __forceinline void clearFlags() {
- ptr &= ~(size_t)align_mask;
- }
-
- /*! returns the wideness */
- __forceinline size_t getN() const { return N; }
-
- public:
- size_t ptr;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_refit.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_refit.cpp
deleted file mode 100644
index a273c21e8b..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_refit.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh_refit.h"
-#include "bvh_statistics.h"
-
-#include "../geometry/linei.h"
-#include "../geometry/triangle.h"
-#include "../geometry/trianglev.h"
-#include "../geometry/trianglei.h"
-#include "../geometry/quadv.h"
-#include "../geometry/object.h"
-#include "../geometry/instance.h"
-
-namespace embree
-{
- namespace isa
- {
- static const size_t SINGLE_THREAD_THRESHOLD = 4*1024;
-
- template<int N>
- __forceinline bool compare(const typename BVHN<N>::NodeRef* a, const typename BVHN<N>::NodeRef* b)
- {
- size_t sa = *(size_t*)&a->node()->lower_x;
- size_t sb = *(size_t*)&b->node()->lower_x;
- return sa < sb;
- }
-
- template<int N>
- BVHNRefitter<N>::BVHNRefitter (BVH* bvh, const LeafBoundsInterface& leafBounds)
- : bvh(bvh), leafBounds(leafBounds), numSubTrees(0)
- {
- }
-
- template<int N>
- void BVHNRefitter<N>::refit()
- {
- if (bvh->numPrimitives <= SINGLE_THREAD_THRESHOLD) {
- bvh->bounds = LBBox3fa(recurse_bottom(bvh->root));
- }
- else
- {
- BBox3fa subTreeBounds[MAX_NUM_SUB_TREES];
- numSubTrees = 0;
- gather_subtree_refs(bvh->root,numSubTrees,0);
- if (numSubTrees)
- parallel_for(size_t(0), numSubTrees, size_t(1), [&](const range<size_t>& r) {
- for (size_t i=r.begin(); i<r.end(); i++) {
- NodeRef& ref = subTrees[i];
- subTreeBounds[i] = recurse_bottom(ref);
- }
- });
-
- numSubTrees = 0;
- bvh->bounds = LBBox3fa(refit_toplevel(bvh->root,numSubTrees,subTreeBounds,0));
- }
- }
-
- template<int N>
- void BVHNRefitter<N>::gather_subtree_refs(NodeRef& ref,
- size_t &subtrees,
- const size_t depth)
- {
- if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)
- {
- assert(subtrees < MAX_NUM_SUB_TREES);
- subTrees[subtrees++] = ref;
- return;
- }
-
- if (ref.isAABBNode())
- {
- AABBNode* node = ref.getAABBNode();
- for (size_t i=0; i<N; i++) {
- NodeRef& child = node->child(i);
- if (unlikely(child == BVH::emptyNode)) continue;
- gather_subtree_refs(child,subtrees,depth+1);
- }
- }
- }
-
- template<int N>
- BBox3fa BVHNRefitter<N>::refit_toplevel(NodeRef& ref,
- size_t &subtrees,
- const BBox3fa *const subTreeBounds,
- const size_t depth)
- {
- if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)
- {
- assert(subtrees < MAX_NUM_SUB_TREES);
- assert(subTrees[subtrees] == ref);
- return subTreeBounds[subtrees++];
- }
-
- if (ref.isAABBNode())
- {
- AABBNode* node = ref.getAABBNode();
- BBox3fa bounds[N];
-
- for (size_t i=0; i<N; i++)
- {
- NodeRef& child = node->child(i);
-
- if (unlikely(child == BVH::emptyNode))
- bounds[i] = BBox3fa(empty);
- else
- bounds[i] = refit_toplevel(child,subtrees,subTreeBounds,depth+1);
- }
-
- BBox3vf<N> boundsT = transpose<N>(bounds);
-
- /* set new bounds */
- node->lower_x = boundsT.lower.x;
- node->lower_y = boundsT.lower.y;
- node->lower_z = boundsT.lower.z;
- node->upper_x = boundsT.upper.x;
- node->upper_y = boundsT.upper.y;
- node->upper_z = boundsT.upper.z;
-
- return merge<N>(bounds);
- }
- else
- return leafBounds.leafBounds(ref);
- }
-
- // =========================================================
- // =========================================================
- // =========================================================
-
-
- template<int N>
- BBox3fa BVHNRefitter<N>::recurse_bottom(NodeRef& ref)
- {
- /* this is a leaf node */
- if (unlikely(ref.isLeaf()))
- return leafBounds.leafBounds(ref);
-
- /* recurse if this is an internal node */
- AABBNode* node = ref.getAABBNode();
-
- /* enable exclusive prefetch for >= AVX platforms */
-#if defined(__AVX__)
- BVH::prefetchW(ref);
-#endif
- BBox3fa bounds[N];
-
- for (size_t i=0; i<N; i++)
- if (unlikely(node->child(i) == BVH::emptyNode))
- {
- bounds[i] = BBox3fa(empty);
- }
- else
- bounds[i] = recurse_bottom(node->child(i));
-
- /* AOS to SOA transform */
- BBox3vf<N> boundsT = transpose<N>(bounds);
-
- /* set new bounds */
- node->lower_x = boundsT.lower.x;
- node->lower_y = boundsT.lower.y;
- node->lower_z = boundsT.lower.z;
- node->upper_x = boundsT.upper.x;
- node->upper_y = boundsT.upper.y;
- node->upper_z = boundsT.upper.z;
-
- return merge<N>(bounds);
- }
-
- template<int N, typename Mesh, typename Primitive>
- BVHNRefitT<N,Mesh,Primitive>::BVHNRefitT (BVH* bvh, Builder* builder, Mesh* mesh, size_t mode)
- : bvh(bvh), builder(builder), refitter(new BVHNRefitter<N>(bvh,*(typename BVHNRefitter<N>::LeafBoundsInterface*)this)), mesh(mesh), topologyVersion(0) {}
-
- template<int N, typename Mesh, typename Primitive>
- void BVHNRefitT<N,Mesh,Primitive>::clear()
- {
- if (builder)
- builder->clear();
- }
-
- template<int N, typename Mesh, typename Primitive>
- void BVHNRefitT<N,Mesh,Primitive>::build()
- {
- if (mesh->topologyChanged(topologyVersion)) {
- topologyVersion = mesh->getTopologyVersion();
- builder->build();
- }
- else
- refitter->refit();
- }
-
- template class BVHNRefitter<4>;
-#if defined(__AVX__)
- template class BVHNRefitter<8>;
-#endif
-
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
- Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
- Builder* BVH4Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
-
- Builder* BVH4Triangle4MeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4> ((BVH4*)accel,BVH4Triangle4MeshBuilderSAH (accel,mesh,geomID,mode),mesh,mode); }
- Builder* BVH4Triangle4vMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4v>((BVH4*)accel,BVH4Triangle4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
- Builder* BVH4Triangle4iMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4i>((BVH4*)accel,BVH4Triangle4iMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
-#if defined(__AVX__)
- Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
- Builder* BVH8Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
- Builder* BVH8Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
-
- Builder* BVH8Triangle4MeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4> ((BVH8*)accel,BVH8Triangle4MeshBuilderSAH (accel,mesh,geomID,mode),mesh,mode); }
- Builder* BVH8Triangle4vMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4v>((BVH8*)accel,BVH8Triangle4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
- Builder* BVH8Triangle4iMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4i>((BVH8*)accel,BVH8Triangle4iMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_QUAD)
- Builder* BVH4Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode);
- Builder* BVH4Quad4vMeshRefitSAH (void* accel, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,QuadMesh,Quad4v>((BVH4*)accel,BVH4Quad4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
-
-#if defined(__AVX__)
- Builder* BVH8Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode);
- Builder* BVH8Quad4vMeshRefitSAH (void* accel, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,QuadMesh,Quad4v>((BVH8*)accel,BVH8Quad4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
-#endif
-
-#endif
-
-#if defined(EMBREE_GEOMETRY_USER)
- Builder* BVH4VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode);
- Builder* BVH4VirtualMeshRefitSAH (void* accel, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,UserGeometry,Object>((BVH4*)accel,BVH4VirtualMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
-
-#if defined(__AVX__)
- Builder* BVH8VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode);
- Builder* BVH8VirtualMeshRefitSAH (void* accel, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,UserGeometry,Object>((BVH8*)accel,BVH8VirtualMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
-#endif
-#endif
-
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);
- Builder* BVH4InstanceMeshRefitSAH (void* accel, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,Instance,InstancePrimitive>((BVH4*)accel,BVH4InstanceMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); }
-
-#if defined(__AVX__)
- Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);
- Builder* BVH8InstanceMeshRefitSAH (void* accel, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,Instance,InstancePrimitive>((BVH8*)accel,BVH8InstanceMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); }
-#endif
-#endif
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_refit.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_refit.h
deleted file mode 100644
index 4aa9bdd7cc..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_refit.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../bvh/bvh.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int N>
- class BVHNRefitter
- {
- public:
-
- /*! Type shortcuts */
- typedef BVHN<N> BVH;
- typedef typename BVH::AABBNode AABBNode;
- typedef typename BVH::NodeRef NodeRef;
-
- struct LeafBoundsInterface {
- virtual const BBox3fa leafBounds(NodeRef& ref) const = 0;
- };
-
- public:
-
- /*! Constructor. */
- BVHNRefitter (BVH* bvh, const LeafBoundsInterface& leafBounds);
-
- /*! refits the BVH */
- void refit();
-
- private:
- /* single-threaded subtree extraction based on BVH depth */
- void gather_subtree_refs(NodeRef& ref,
- size_t &subtrees,
- const size_t depth = 0);
-
- /* single-threaded top-level refit */
- BBox3fa refit_toplevel(NodeRef& ref,
- size_t &subtrees,
- const BBox3fa *const subTreeBounds,
- const size_t depth = 0);
-
- /* single-threaded subtree refit */
- BBox3fa recurse_bottom(NodeRef& ref);
-
- public:
- BVH* bvh; //!< BVH to refit
- const LeafBoundsInterface& leafBounds; //!< calculates bounds of leaves
-
- static const size_t MAX_SUB_TREE_EXTRACTION_DEPTH = (N==4) ? 4 : (N==8) ? 3 : 3;
- static const size_t MAX_NUM_SUB_TREES = (N==4) ? 256 : (N==8) ? 512 : N*N*N; // N ^ MAX_SUB_TREE_EXTRACTION_DEPTH
- size_t numSubTrees;
- NodeRef subTrees[MAX_NUM_SUB_TREES];
- };
-
- template<int N, typename Mesh, typename Primitive>
- class BVHNRefitT : public Builder, public BVHNRefitter<N>::LeafBoundsInterface
- {
- public:
-
- /*! Type shortcuts */
- typedef BVHN<N> BVH;
- typedef typename BVH::AABBNode AABBNode;
- typedef typename BVH::NodeRef NodeRef;
-
- public:
- BVHNRefitT (BVH* bvh, Builder* builder, Mesh* mesh, size_t mode);
-
- virtual void build();
-
- virtual void clear();
-
- virtual const BBox3fa leafBounds (NodeRef& ref) const
- {
- size_t num; char* prim = ref.leaf(num);
- if (unlikely(ref == BVH::emptyNode)) return empty;
-
- BBox3fa bounds = empty;
- for (size_t i=0; i<num; i++)
- bounds.extend(((Primitive*)prim)[i].update(mesh));
- return bounds;
- }
-
- private:
- BVH* bvh;
- std::unique_ptr<Builder> builder;
- std::unique_ptr<BVHNRefitter<N>> refitter;
- Mesh* mesh;
- unsigned int topologyVersion;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_rotate.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_rotate.cpp
deleted file mode 100644
index 2bb431bf0e..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_rotate.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh_rotate.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Computes half surface area of box. */
- __forceinline float halfArea3f(const BBox<vfloat4>& box) {
- const vfloat4 d = box.size();
- const vfloat4 a = d*shuffle<1,2,0,3>(d);
- return a[0]+a[1]+a[2];
- }
-
- size_t BVHNRotate<4>::rotate(NodeRef parentRef, size_t depth)
- {
- /*! nothing to rotate if we reached a leaf node. */
- if (parentRef.isBarrier()) return 0;
- if (parentRef.isLeaf()) return 0;
- AABBNode* parent = parentRef.getAABBNode();
-
- /*! rotate all children first */
- vint4 cdepth;
- for (size_t c=0; c<4; c++)
- cdepth[c] = (int)rotate(parent->child(c),depth+1);
-
- /* compute current areas of all children */
- vfloat4 sizeX = parent->upper_x-parent->lower_x;
- vfloat4 sizeY = parent->upper_y-parent->lower_y;
- vfloat4 sizeZ = parent->upper_z-parent->lower_z;
- vfloat4 childArea = madd(sizeX,(sizeY + sizeZ),sizeY*sizeZ);
-
- /*! get node bounds */
- BBox<vfloat4> child1_0,child1_1,child1_2,child1_3;
- parent->bounds(child1_0,child1_1,child1_2,child1_3);
-
- /*! Find best rotation. We pick a first child (child1) and a sub-child
- (child2child) of a different second child (child2), and swap child1
- and child2child. We perform the best such swap. */
- float bestArea = 0;
- size_t bestChild1 = -1, bestChild2 = -1, bestChild2Child = -1;
- for (size_t c2=0; c2<4; c2++)
- {
- /*! ignore leaf nodes as we cannot descent into them */
- if (parent->child(c2).isBarrier()) continue;
- if (parent->child(c2).isLeaf()) continue;
- AABBNode* child2 = parent->child(c2).getAABBNode();
-
- /*! transpose child bounds */
- BBox<vfloat4> child2c0,child2c1,child2c2,child2c3;
- child2->bounds(child2c0,child2c1,child2c2,child2c3);
-
- /*! put child1_0 at each child2 position */
- float cost00 = halfArea3f(merge(child1_0,child2c1,child2c2,child2c3));
- float cost01 = halfArea3f(merge(child2c0,child1_0,child2c2,child2c3));
- float cost02 = halfArea3f(merge(child2c0,child2c1,child1_0,child2c3));
- float cost03 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_0));
- vfloat4 cost0 = vfloat4(cost00,cost01,cost02,cost03);
- vfloat4 min0 = vreduce_min(cost0);
- int pos0 = (int)bsf(movemask(min0 == cost0));
-
- /*! put child1_1 at each child2 position */
- float cost10 = halfArea3f(merge(child1_1,child2c1,child2c2,child2c3));
- float cost11 = halfArea3f(merge(child2c0,child1_1,child2c2,child2c3));
- float cost12 = halfArea3f(merge(child2c0,child2c1,child1_1,child2c3));
- float cost13 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_1));
- vfloat4 cost1 = vfloat4(cost10,cost11,cost12,cost13);
- vfloat4 min1 = vreduce_min(cost1);
- int pos1 = (int)bsf(movemask(min1 == cost1));
-
- /*! put child1_2 at each child2 position */
- float cost20 = halfArea3f(merge(child1_2,child2c1,child2c2,child2c3));
- float cost21 = halfArea3f(merge(child2c0,child1_2,child2c2,child2c3));
- float cost22 = halfArea3f(merge(child2c0,child2c1,child1_2,child2c3));
- float cost23 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_2));
- vfloat4 cost2 = vfloat4(cost20,cost21,cost22,cost23);
- vfloat4 min2 = vreduce_min(cost2);
- int pos2 = (int)bsf(movemask(min2 == cost2));
-
- /*! put child1_3 at each child2 position */
- float cost30 = halfArea3f(merge(child1_3,child2c1,child2c2,child2c3));
- float cost31 = halfArea3f(merge(child2c0,child1_3,child2c2,child2c3));
- float cost32 = halfArea3f(merge(child2c0,child2c1,child1_3,child2c3));
- float cost33 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_3));
- vfloat4 cost3 = vfloat4(cost30,cost31,cost32,cost33);
- vfloat4 min3 = vreduce_min(cost3);
- int pos3 = (int)bsf(movemask(min3 == cost3));
-
- /*! find best other child */
- vfloat4 area0123 = vfloat4(extract<0>(min0),extract<0>(min1),extract<0>(min2),extract<0>(min3)) - vfloat4(childArea[c2]);
- int pos[4] = { pos0,pos1,pos2,pos3 };
- const size_t mbd = BVH4::maxBuildDepth;
- vbool4 valid = vint4(int(depth+1))+cdepth <= vint4(mbd); // only select swaps that fulfill depth constraints
- valid &= vint4(int(c2)) != vint4(step);
- if (none(valid)) continue;
- size_t c1 = select_min(valid,area0123);
- float area = area0123[c1];
- if (c1 == c2) continue; // can happen if bounds are NANs
-
- /*! accept a swap when it reduces cost and is not swapping a node with itself */
- if (area < bestArea) {
- bestArea = area;
- bestChild1 = c1;
- bestChild2 = c2;
- bestChild2Child = pos[c1];
- }
- }
-
- /*! if we did not find a swap that improves the SAH then do nothing */
- if (bestChild1 == size_t(-1)) return 1+reduce_max(cdepth);
-
- /*! perform the best found tree rotation */
- AABBNode* child2 = parent->child(bestChild2).getAABBNode();
- AABBNode::swap(parent,bestChild1,child2,bestChild2Child);
- parent->setBounds(bestChild2,child2->bounds());
- AABBNode::compact(parent);
- AABBNode::compact(child2);
-
- /*! This returned depth is conservative as the child that was
- * pulled up in the tree could have been on the critical path. */
- cdepth[bestChild1]++; // bestChild1 was pushed down one level
- return 1+reduce_max(cdepth);
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_rotate.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_rotate.h
deleted file mode 100644
index 009bef339e..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_rotate.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int N>
- class BVHNRotate
- {
- typedef typename BVHN<N>::NodeRef NodeRef;
-
- public:
- static const bool enabled = false;
-
- static __forceinline size_t rotate(NodeRef parentRef, size_t depth = 1) { return 0; }
- static __forceinline void restructure(NodeRef ref, size_t depth = 1) {}
- };
-
- /* BVH4 tree rotations */
- template<>
- class BVHNRotate<4>
- {
- typedef BVH4::AABBNode AABBNode;
- typedef BVH4::NodeRef NodeRef;
-
- public:
- static const bool enabled = true;
-
- static size_t rotate(NodeRef parentRef, size_t depth = 1);
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.cpp
deleted file mode 100644
index aa56035026..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "bvh_statistics.h"
-#include "../../common/algorithms/parallel_reduce.h"
-
-namespace embree
-{
- template<int N>
- BVHNStatistics<N>::BVHNStatistics (BVH* bvh) : bvh(bvh)
- {
- double A = max(0.0f,bvh->getLinearBounds().expectedHalfArea());
- stat = statistics(bvh->root,A,BBox1f(0.0f,1.0f));
- }
-
- template<int N>
- std::string BVHNStatistics<N>::str()
- {
- std::ostringstream stream;
- stream.setf(std::ios::fixed, std::ios::floatfield);
- stream << " primitives = " << bvh->numPrimitives << ", vertices = " << bvh->numVertices << ", depth = " << stat.depth << std::endl;
- size_t totalBytes = stat.bytes(bvh);
- double totalSAH = stat.sah(bvh);
- stream << " total : sah = " << std::setw(7) << std::setprecision(3) << totalSAH << " (100.00%), ";
- stream << "#bytes = " << std::setw(7) << std::setprecision(2) << totalBytes/1E6 << " MB (100.00%), ";
- stream << "#nodes = " << std::setw(7) << stat.size() << " (" << std::setw(6) << std::setprecision(2) << 100.0*stat.fillRate(bvh) << "% filled), ";
- stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(totalBytes)/double(bvh->numPrimitives) << std::endl;
- if (stat.statAABBNodes.numNodes ) stream << " getAABBNodes : " << stat.statAABBNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
- if (stat.statOBBNodes.numNodes ) stream << " ungetAABBNodes : " << stat.statOBBNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
- if (stat.statAABBNodesMB.numNodes ) stream << " getAABBNodesMB : " << stat.statAABBNodesMB.toString(bvh,totalSAH,totalBytes) << std::endl;
- if (stat.statAABBNodesMB4D.numNodes) stream << " getAABBNodesMB4D : " << stat.statAABBNodesMB4D.toString(bvh,totalSAH,totalBytes) << std::endl;
- if (stat.statOBBNodesMB.numNodes) stream << " ungetAABBNodesMB : " << stat.statOBBNodesMB.toString(bvh,totalSAH,totalBytes) << std::endl;
- if (stat.statQuantizedNodes.numNodes ) stream << " quantizedNodes : " << stat.statQuantizedNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
- if (true) stream << " leaves : " << stat.statLeaf.toString(bvh,totalSAH,totalBytes) << std::endl;
- if (true) stream << " histogram : " << stat.statLeaf.histToString() << std::endl;
- return stream.str();
- }
-
- template<int N>
- typename BVHNStatistics<N>::Statistics BVHNStatistics<N>::statistics(NodeRef node, const double A, const BBox1f t0t1)
- {
- Statistics s;
- assert(t0t1.size() > 0.0f);
- double dt = max(0.0f,t0t1.size());
- if (node.isAABBNode())
- {
- AABBNode* n = node.getAABBNode();
- s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
- if (n->child(i) == BVH::emptyNode) return Statistics();
- const double Ai = max(0.0f,halfArea(n->extend(i)));
- Statistics s = statistics(n->child(i),Ai,t0t1);
- s.statAABBNodes.numChildren++;
- return s;
- }, Statistics::add);
- s.statAABBNodes.numNodes++;
- s.statAABBNodes.nodeSAH += dt*A;
- s.depth++;
- }
- else if (node.isOBBNode())
- {
- OBBNode* n = node.ungetAABBNode();
- s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
- if (n->child(i) == BVH::emptyNode) return Statistics();
- const double Ai = max(0.0f,halfArea(n->extent(i)));
- Statistics s = statistics(n->child(i),Ai,t0t1);
- s.statOBBNodes.numChildren++;
- return s;
- }, Statistics::add);
- s.statOBBNodes.numNodes++;
- s.statOBBNodes.nodeSAH += dt*A;
- s.depth++;
- }
- else if (node.isAABBNodeMB())
- {
- AABBNodeMB* n = node.getAABBNodeMB();
- s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
- if (n->child(i) == BVH::emptyNode) return Statistics();
- const double Ai = max(0.0f,n->expectedHalfArea(i,t0t1));
- Statistics s = statistics(n->child(i),Ai,t0t1);
- s.statAABBNodesMB.numChildren++;
- return s;
- }, Statistics::add);
- s.statAABBNodesMB.numNodes++;
- s.statAABBNodesMB.nodeSAH += dt*A;
- s.depth++;
- }
- else if (node.isAABBNodeMB4D())
- {
- AABBNodeMB4D* n = node.getAABBNodeMB4D();
- s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
- if (n->child(i) == BVH::emptyNode) return Statistics();
- const BBox1f t0t1i = intersect(t0t1,n->timeRange(i));
- assert(!t0t1i.empty());
- const double Ai = n->AABBNodeMB::expectedHalfArea(i,t0t1i);
- Statistics s = statistics(n->child(i),Ai,t0t1i);
- s.statAABBNodesMB4D.numChildren++;
- return s;
- }, Statistics::add);
- s.statAABBNodesMB4D.numNodes++;
- s.statAABBNodesMB4D.nodeSAH += dt*A;
- s.depth++;
- }
- else if (node.isOBBNodeMB())
- {
- OBBNodeMB* n = node.ungetAABBNodeMB();
- s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
- if (n->child(i) == BVH::emptyNode) return Statistics();
- const double Ai = max(0.0f,halfArea(n->extent0(i)));
- Statistics s = statistics(n->child(i),Ai,t0t1);
- s.statOBBNodesMB.numChildren++;
- return s;
- }, Statistics::add);
- s.statOBBNodesMB.numNodes++;
- s.statOBBNodesMB.nodeSAH += dt*A;
- s.depth++;
- }
- else if (node.isQuantizedNode())
- {
- QuantizedNode* n = node.quantizedNode();
- s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
- if (n->child(i) == BVH::emptyNode) return Statistics();
- const double Ai = max(0.0f,halfArea(n->extent(i)));
- Statistics s = statistics(n->child(i),Ai,t0t1);
- s.statQuantizedNodes.numChildren++;
- return s;
- }, Statistics::add);
- s.statQuantizedNodes.numNodes++;
- s.statQuantizedNodes.nodeSAH += dt*A;
- s.depth++;
- }
- else if (node.isLeaf())
- {
- size_t num; const char* tri = node.leaf(num);
- if (num)
- {
- for (size_t i=0; i<num; i++)
- {
- const size_t bytes = bvh->primTy->getBytes(tri);
- s.statLeaf.numPrimsActive += bvh->primTy->sizeActive(tri);
- s.statLeaf.numPrimsTotal += bvh->primTy->sizeTotal(tri);
- s.statLeaf.numBytes += bytes;
- tri+=bytes;
- }
- s.statLeaf.numLeaves++;
- s.statLeaf.numPrimBlocks += num;
- s.statLeaf.leafSAH += dt*A*num;
- if (num-1 < Statistics::LeafStat::NHIST) {
- s.statLeaf.numPrimBlocksHistogram[num-1]++;
- }
- }
- }
- else {
- // -- GODOT start --
- // throw std::runtime_error("not supported node type in bvh_statistics");
- abort();
- // -- GODOT end --
- }
- return s;
- }
-
-#if defined(__AVX__)
- template class BVHNStatistics<8>;
-#endif
-
-#if !defined(__AVX__) || (!defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)) || defined(__aarch64__)
- template class BVHNStatistics<4>;
-#endif
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.h
deleted file mode 100644
index 73dfc6fbcc..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.h
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-#include <sstream>
-
-namespace embree
-{
- template<int N>
- class BVHNStatistics
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::AABBNode AABBNode;
- typedef typename BVH::OBBNode OBBNode;
- typedef typename BVH::AABBNodeMB AABBNodeMB;
- typedef typename BVH::AABBNodeMB4D AABBNodeMB4D;
- typedef typename BVH::OBBNodeMB OBBNodeMB;
- typedef typename BVH::QuantizedNode QuantizedNode;
-
- typedef typename BVH::NodeRef NodeRef;
-
- struct Statistics
- {
- template<typename Node>
- struct NodeStat
- {
- NodeStat ( double nodeSAH = 0,
- size_t numNodes = 0,
- size_t numChildren = 0)
- : nodeSAH(nodeSAH),
- numNodes(numNodes),
- numChildren(numChildren) {}
-
- double sah(BVH* bvh) const {
- return nodeSAH/bvh->getLinearBounds().expectedHalfArea();
- }
-
- size_t bytes() const {
- return numNodes*sizeof(Node);
- }
-
- size_t size() const {
- return numNodes;
- }
-
- double fillRateNom () const { return double(numChildren); }
- double fillRateDen () const { return double(numNodes*N); }
- double fillRate () const { return fillRateNom()/fillRateDen(); }
-
- __forceinline friend NodeStat operator+ ( const NodeStat& a, const NodeStat& b)
- {
- return NodeStat(a.nodeSAH + b.nodeSAH,
- a.numNodes+b.numNodes,
- a.numChildren+b.numChildren);
- }
-
- std::string toString(BVH* bvh, double sahTotal, size_t bytesTotal) const
- {
- std::ostringstream stream;
- stream.setf(std::ios::fixed, std::ios::floatfield);
- stream << "sah = " << std::setw(7) << std::setprecision(3) << sah(bvh);
- stream << " (" << std::setw(6) << std::setprecision(2) << 100.0*sah(bvh)/sahTotal << "%), ";
- stream << "#bytes = " << std::setw(7) << std::setprecision(2) << bytes()/1E6 << " MB ";
- stream << "(" << std::setw(6) << std::setprecision(2) << 100.0*double(bytes())/double(bytesTotal) << "%), ";
- stream << "#nodes = " << std::setw(7) << numNodes << " (" << std::setw(6) << std::setprecision(2) << 100.0*fillRate() << "% filled), ";
- stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytes())/double(bvh->numPrimitives);
- return stream.str();
- }
-
- public:
- double nodeSAH;
- size_t numNodes;
- size_t numChildren;
- };
-
- struct LeafStat
- {
- static const int NHIST = 8;
-
- LeafStat ( double leafSAH = 0.0f,
- size_t numLeaves = 0,
- size_t numPrimsActive = 0,
- size_t numPrimsTotal = 0,
- size_t numPrimBlocks = 0,
- size_t numBytes = 0)
- : leafSAH(leafSAH),
- numLeaves(numLeaves),
- numPrimsActive(numPrimsActive),
- numPrimsTotal(numPrimsTotal),
- numPrimBlocks(numPrimBlocks),
- numBytes(numBytes)
- {
- for (size_t i=0; i<NHIST; i++)
- numPrimBlocksHistogram[i] = 0;
- }
-
- double sah(BVH* bvh) const {
- return leafSAH/bvh->getLinearBounds().expectedHalfArea();
- }
-
- size_t bytes(BVH* bvh) const {
- return numBytes;
- }
-
- size_t size() const {
- return numLeaves;
- }
-
- double fillRateNom (BVH* bvh) const { return double(numPrimsActive); }
- double fillRateDen (BVH* bvh) const { return double(numPrimsTotal); }
- double fillRate (BVH* bvh) const { return fillRateNom(bvh)/fillRateDen(bvh); }
-
- __forceinline friend LeafStat operator+ ( const LeafStat& a, const LeafStat& b)
- {
- LeafStat stat(a.leafSAH + b.leafSAH,
- a.numLeaves+b.numLeaves,
- a.numPrimsActive+b.numPrimsActive,
- a.numPrimsTotal+b.numPrimsTotal,
- a.numPrimBlocks+b.numPrimBlocks,
- a.numBytes+b.numBytes);
- for (size_t i=0; i<NHIST; i++) {
- stat.numPrimBlocksHistogram[i] += a.numPrimBlocksHistogram[i];
- stat.numPrimBlocksHistogram[i] += b.numPrimBlocksHistogram[i];
- }
- return stat;
- }
-
- std::string toString(BVH* bvh, double sahTotal, size_t bytesTotal) const
- {
- std::ostringstream stream;
- stream.setf(std::ios::fixed, std::ios::floatfield);
- stream << "sah = " << std::setw(7) << std::setprecision(3) << sah(bvh);
- stream << " (" << std::setw(6) << std::setprecision(2) << 100.0*sah(bvh)/sahTotal << "%), ";
- stream << "#bytes = " << std::setw(7) << std::setprecision(2) << double(bytes(bvh))/1E6 << " MB ";
- stream << "(" << std::setw(6) << std::setprecision(2) << 100.0*double(bytes(bvh))/double(bytesTotal) << "%), ";
- stream << "#nodes = " << std::setw(7) << numLeaves << " (" << std::setw(6) << std::setprecision(2) << 100.0*fillRate(bvh) << "% filled), ";
- stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytes(bvh))/double(bvh->numPrimitives);
- return stream.str();
- }
-
- std::string histToString() const
- {
- std::ostringstream stream;
- stream.setf(std::ios::fixed, std::ios::floatfield);
- for (size_t i=0; i<NHIST; i++)
- stream << std::setw(6) << std::setprecision(2) << 100.0f*float(numPrimBlocksHistogram[i])/float(numLeaves) << "% ";
- return stream.str();
- }
-
- public:
- double leafSAH; //!< SAH of the leaves only
- size_t numLeaves; //!< Number of leaf nodes.
- size_t numPrimsActive; //!< Number of active primitives (
- size_t numPrimsTotal; //!< Number of active and inactive primitives
- size_t numPrimBlocks; //!< Number of primitive blocks.
- size_t numBytes; //!< Number of bytes of leaves.
- size_t numPrimBlocksHistogram[8];
- };
-
- public:
- Statistics (size_t depth = 0,
- LeafStat statLeaf = LeafStat(),
- NodeStat<AABBNode> statAABBNodes = NodeStat<AABBNode>(),
- NodeStat<OBBNode> statOBBNodes = NodeStat<OBBNode>(),
- NodeStat<AABBNodeMB> statAABBNodesMB = NodeStat<AABBNodeMB>(),
- NodeStat<AABBNodeMB4D> statAABBNodesMB4D = NodeStat<AABBNodeMB4D>(),
- NodeStat<OBBNodeMB> statOBBNodesMB = NodeStat<OBBNodeMB>(),
- NodeStat<QuantizedNode> statQuantizedNodes = NodeStat<QuantizedNode>())
-
- : depth(depth),
- statLeaf(statLeaf),
- statAABBNodes(statAABBNodes),
- statOBBNodes(statOBBNodes),
- statAABBNodesMB(statAABBNodesMB),
- statAABBNodesMB4D(statAABBNodesMB4D),
- statOBBNodesMB(statOBBNodesMB),
- statQuantizedNodes(statQuantizedNodes) {}
-
- double sah(BVH* bvh) const
- {
- return statLeaf.sah(bvh) +
- statAABBNodes.sah(bvh) +
- statOBBNodes.sah(bvh) +
- statAABBNodesMB.sah(bvh) +
- statAABBNodesMB4D.sah(bvh) +
- statOBBNodesMB.sah(bvh) +
- statQuantizedNodes.sah(bvh);
- }
-
- size_t bytes(BVH* bvh) const {
- return statLeaf.bytes(bvh) +
- statAABBNodes.bytes() +
- statOBBNodes.bytes() +
- statAABBNodesMB.bytes() +
- statAABBNodesMB4D.bytes() +
- statOBBNodesMB.bytes() +
- statQuantizedNodes.bytes();
- }
-
- size_t size() const
- {
- return statLeaf.size() +
- statAABBNodes.size() +
- statOBBNodes.size() +
- statAABBNodesMB.size() +
- statAABBNodesMB4D.size() +
- statOBBNodesMB.size() +
- statQuantizedNodes.size();
- }
-
- double fillRate (BVH* bvh) const
- {
- double nom = statLeaf.fillRateNom(bvh) +
- statAABBNodes.fillRateNom() +
- statOBBNodes.fillRateNom() +
- statAABBNodesMB.fillRateNom() +
- statAABBNodesMB4D.fillRateNom() +
- statOBBNodesMB.fillRateNom() +
- statQuantizedNodes.fillRateNom();
- double den = statLeaf.fillRateDen(bvh) +
- statAABBNodes.fillRateDen() +
- statOBBNodes.fillRateDen() +
- statAABBNodesMB.fillRateDen() +
- statAABBNodesMB4D.fillRateDen() +
- statOBBNodesMB.fillRateDen() +
- statQuantizedNodes.fillRateDen();
- return nom/den;
- }
-
- friend Statistics operator+ ( const Statistics& a, const Statistics& b )
- {
- return Statistics(max(a.depth,b.depth),
- a.statLeaf + b.statLeaf,
- a.statAABBNodes + b.statAABBNodes,
- a.statOBBNodes + b.statOBBNodes,
- a.statAABBNodesMB + b.statAABBNodesMB,
- a.statAABBNodesMB4D + b.statAABBNodesMB4D,
- a.statOBBNodesMB + b.statOBBNodesMB,
- a.statQuantizedNodes + b.statQuantizedNodes);
- }
-
- static Statistics add ( const Statistics& a, const Statistics& b ) {
- return a+b;
- }
-
- public:
- size_t depth;
- LeafStat statLeaf;
- NodeStat<AABBNode> statAABBNodes;
- NodeStat<OBBNode> statOBBNodes;
- NodeStat<AABBNodeMB> statAABBNodesMB;
- NodeStat<AABBNodeMB4D> statAABBNodesMB4D;
- NodeStat<OBBNodeMB> statOBBNodesMB;
- NodeStat<QuantizedNode> statQuantizedNodes;
- };
-
- public:
-
- /* Constructor gathers statistics. */
- BVHNStatistics (BVH* bvh);
-
- /*! Convert statistics into a string */
- std::string str();
-
- double sah() const {
- return stat.sah(bvh);
- }
-
- size_t bytesUsed() const {
- return stat.bytes(bvh);
- }
-
- private:
- Statistics statistics(NodeRef node, const double A, const BBox1f dt);
-
- private:
- BVH* bvh;
- Statistics stat;
- };
-
- typedef BVHNStatistics<4> BVH4Statistics;
- typedef BVHNStatistics<8> BVH8Statistics;
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_traverser1.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_traverser1.h
deleted file mode 100644
index 7f17084b81..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_traverser1.h
+++ /dev/null
@@ -1,676 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-#include "node_intersector1.h"
-#include "../common/stack_item.h"
-
-#define NEW_SORTING_CODE 1
-
-namespace embree
-{
- namespace isa
- {
- /*! BVH regular node traversal for single rays. */
- template<int N, int Nx, int types>
- class BVHNNodeTraverser1Hit;
-
- /*! Helper functions for fast sorting using AVX512 instructions. */
-#if defined(__AVX512ER__)
-
- /* KNL code path */
- __forceinline void isort_update(vfloat16 &dist, vllong8 &ptr, const vfloat16 &d, const vllong8 &p)
- {
- const vfloat16 dist_shift = align_shift_right<15>(dist,dist);
- const vllong8 ptr_shift = align_shift_right<7>(ptr,ptr);
- const vbool16 m_geq = d >= dist;
- const vbool16 m_geq_shift = m_geq << 1;
- dist = select(m_geq,d,dist);
- ptr = select(vboold8(m_geq),p,ptr);
- dist = select(m_geq_shift,dist_shift,dist);
- ptr = select(vboold8(m_geq_shift),ptr_shift,ptr);
- }
-
- __forceinline void isort_quick_update(vfloat16 &dist, vllong8 &ptr, const vfloat16 &d, const vllong8 &p)
- {
- //dist = align_shift_right<15>(dist,d);
- //ptr = align_shift_right<7>(ptr,p);
- dist = align_shift_right<15>(dist,permute(d,vint16(zero)));
- ptr = align_shift_right<7>(ptr,permute(p,vllong8(zero)));
- }
-
- template<int N, int Nx, int types, class NodeRef, class BaseNode>
- __forceinline void traverseClosestHitAVX512(NodeRef& cur,
- size_t mask,
- const vfloat<Nx>& tNear,
- StackItemT<NodeRef>*& stackPtr,
- StackItemT<NodeRef>* stackEnd)
- {
- assert(mask != 0);
- const BaseNode* node = cur.baseNode();
-
- vllong8 children( vllong<N>::loadu((void*)node->children) );
- children = vllong8::compact((int)mask,children);
- vfloat16 distance = tNear;
- distance = vfloat16::compact((int)mask,distance,tNear);
-
- cur = toScalar(children);
- BVHN<N>::prefetch(cur,types);
-
- mask &= mask-1;
- if (likely(mask == 0)) return;
-
- /* 2 hits: order A0 B0 */
- const vllong8 c0(children);
- const vfloat16 d0(distance);
- children = align_shift_right<1>(children,children);
- distance = align_shift_right<1>(distance,distance);
- const vllong8 c1(children);
- const vfloat16 d1(distance);
-
- cur = toScalar(children);
- BVHN<N>::prefetch(cur,types);
-
- /* a '<' keeps the order for equal distances, scenes like powerplant largely benefit from it */
- const vboolf16 m_dist = d0 < d1;
- const vfloat16 dist_A0 = select(m_dist, d0, d1);
- const vfloat16 dist_B0 = select(m_dist, d1, d0);
- const vllong8 ptr_A0 = select(vboold8(m_dist), c0, c1);
- const vllong8 ptr_B0 = select(vboold8(m_dist), c1, c0);
-
- mask &= mask-1;
- if (likely(mask == 0)) {
- cur = toScalar(ptr_A0);
- stackPtr[0].ptr = toScalar(ptr_B0);
- *(float*)&stackPtr[0].dist = toScalar(dist_B0);
- stackPtr++;
- return;
- }
-
- /* 3 hits: order A1 B1 C1 */
-
- children = align_shift_right<1>(children,children);
- distance = align_shift_right<1>(distance,distance);
-
- const vllong8 c2(children);
- const vfloat16 d2(distance);
-
- cur = toScalar(children);
- BVHN<N>::prefetch(cur,types);
-
- const vboolf16 m_dist1 = dist_A0 <= d2;
- const vfloat16 dist_tmp_B1 = select(m_dist1, d2, dist_A0);
- const vllong8 ptr_A1 = select(vboold8(m_dist1), ptr_A0, c2);
- const vllong8 ptr_tmp_B1 = select(vboold8(m_dist1), c2, ptr_A0);
-
- const vboolf16 m_dist2 = dist_B0 <= dist_tmp_B1;
- const vfloat16 dist_B1 = select(m_dist2, dist_B0 , dist_tmp_B1);
- const vfloat16 dist_C1 = select(m_dist2, dist_tmp_B1, dist_B0);
- const vllong8 ptr_B1 = select(vboold8(m_dist2), ptr_B0, ptr_tmp_B1);
- const vllong8 ptr_C1 = select(vboold8(m_dist2), ptr_tmp_B1, ptr_B0);
-
- mask &= mask-1;
- if (likely(mask == 0)) {
- cur = toScalar(ptr_A1);
- stackPtr[0].ptr = toScalar(ptr_C1);
- *(float*)&stackPtr[0].dist = toScalar(dist_C1);
- stackPtr[1].ptr = toScalar(ptr_B1);
- *(float*)&stackPtr[1].dist = toScalar(dist_B1);
- stackPtr+=2;
- return;
- }
-
- /* 4 hits: order A2 B2 C2 D2 */
-
- const vfloat16 dist_A1 = select(m_dist1, dist_A0, d2);
-
- children = align_shift_right<1>(children,children);
- distance = align_shift_right<1>(distance,distance);
-
- const vllong8 c3(children);
- const vfloat16 d3(distance);
-
- cur = toScalar(children);
- BVHN<N>::prefetch(cur,types);
-
- const vboolf16 m_dist3 = dist_A1 <= d3;
- const vfloat16 dist_tmp_B2 = select(m_dist3, d3, dist_A1);
- const vllong8 ptr_A2 = select(vboold8(m_dist3), ptr_A1, c3);
- const vllong8 ptr_tmp_B2 = select(vboold8(m_dist3), c3, ptr_A1);
-
- const vboolf16 m_dist4 = dist_B1 <= dist_tmp_B2;
- const vfloat16 dist_B2 = select(m_dist4, dist_B1 , dist_tmp_B2);
- const vfloat16 dist_tmp_C2 = select(m_dist4, dist_tmp_B2, dist_B1);
- const vllong8 ptr_B2 = select(vboold8(m_dist4), ptr_B1, ptr_tmp_B2);
- const vllong8 ptr_tmp_C2 = select(vboold8(m_dist4), ptr_tmp_B2, ptr_B1);
-
- const vboolf16 m_dist5 = dist_C1 <= dist_tmp_C2;
- const vfloat16 dist_C2 = select(m_dist5, dist_C1 , dist_tmp_C2);
- const vfloat16 dist_D2 = select(m_dist5, dist_tmp_C2, dist_C1);
- const vllong8 ptr_C2 = select(vboold8(m_dist5), ptr_C1, ptr_tmp_C2);
- const vllong8 ptr_D2 = select(vboold8(m_dist5), ptr_tmp_C2, ptr_C1);
-
- mask &= mask-1;
- if (likely(mask == 0)) {
- cur = toScalar(ptr_A2);
- stackPtr[0].ptr = toScalar(ptr_D2);
- *(float*)&stackPtr[0].dist = toScalar(dist_D2);
- stackPtr[1].ptr = toScalar(ptr_C2);
- *(float*)&stackPtr[1].dist = toScalar(dist_C2);
- stackPtr[2].ptr = toScalar(ptr_B2);
- *(float*)&stackPtr[2].dist = toScalar(dist_B2);
- stackPtr+=3;
- return;
- }
-
- /* >=5 hits: reverse to descending order for writing to stack */
-
- const size_t hits = 4 + popcnt(mask);
- const vfloat16 dist_A2 = select(m_dist3, dist_A1, d3);
- vfloat16 dist(neg_inf);
- vllong8 ptr(zero);
-
-
- isort_quick_update(dist,ptr,dist_A2,ptr_A2);
- isort_quick_update(dist,ptr,dist_B2,ptr_B2);
- isort_quick_update(dist,ptr,dist_C2,ptr_C2);
- isort_quick_update(dist,ptr,dist_D2,ptr_D2);
-
- do {
-
- children = align_shift_right<1>(children,children);
- distance = align_shift_right<1>(distance,distance);
-
- cur = toScalar(children);
- BVHN<N>::prefetch(cur,types);
-
- const vfloat16 new_dist(permute(distance,vint16(zero)));
- const vllong8 new_ptr(permute(children,vllong8(zero)));
-
- mask &= mask-1;
- isort_update(dist,ptr,new_dist,new_ptr);
-
- } while(mask);
-
- const vboold8 m_stack_ptr(0x55); // 10101010 (lsb -> msb)
- const vboolf16 m_stack_dist(0x4444); // 0010001000100010 (lsb -> msb)
-
- /* extract current noderef */
- cur = toScalar(permute(ptr,vllong8(hits-1)));
- /* rearrange pointers to beginning of 16 bytes block */
- vllong8 stackElementA0;
- stackElementA0 = vllong8::expand(m_stack_ptr,ptr,stackElementA0);
- /* put distances in between */
- vuint16 stackElementA1((__m512i)stackElementA0);
- stackElementA1 = vuint16::expand(m_stack_dist,asUInt(dist),stackElementA1);
- /* write out first 4 x 16 bytes block to stack */
- vuint16::storeu(stackPtr,stackElementA1);
- /* get upper half of dist and ptr */
- dist = align_shift_right<4>(dist,dist);
- ptr = align_shift_right<4>(ptr,ptr);
- /* assemble and write out second block */
- vllong8 stackElementB0;
- stackElementB0 = vllong8::expand(m_stack_ptr,ptr,stackElementB0);
- vuint16 stackElementB1((__m512i)stackElementB0);
- stackElementB1 = vuint16::expand(m_stack_dist,asUInt(dist),stackElementB1);
- vuint16::storeu(stackPtr + 4,stackElementB1);
- /* increase stack pointer */
- stackPtr += hits-1;
- }
-#endif
-
-#if defined(__AVX512VL__) // SKX
-
- template<int N>
- __forceinline void isort_update(vint<N> &dist, const vint<N> &d)
- {
- const vint<N> dist_shift = align_shift_right<N-1>(dist,dist);
- const vboolf<N> m_geq = d >= dist;
- const vboolf<N> m_geq_shift = m_geq << 1;
- dist = select(m_geq,d,dist);
- dist = select(m_geq_shift,dist_shift,dist);
- }
-
- template<int N>
- __forceinline void isort_quick_update(vint<N> &dist, const vint<N> &d) {
- dist = align_shift_right<N-1>(dist,permute(d,vint<N>(zero)));
- }
-
- __forceinline size_t permuteExtract(const vint8& index, const vllong4& n0, const vllong4& n1) {
- return toScalar(permutex2var((__m256i)index,n0,n1));
- }
-
- __forceinline float permuteExtract(const vint8& index, const vfloat8& n) {
- return toScalar(permute(n,index));
- }
-
-#endif
-
- /* Specialization for BVH4. */
- template<int Nx, int types>
- class BVHNNodeTraverser1Hit<4, Nx, types>
- {
- typedef BVH4 BVH;
- typedef BVH4::NodeRef NodeRef;
- typedef BVH4::BaseNode BaseNode;
-
-
- public:
- /* Traverses a node with at least one hit child. Optimized for finding the closest hit (intersection). */
- static __forceinline void traverseClosestHit(NodeRef& cur,
- size_t mask,
- const vfloat<Nx>& tNear,
- StackItemT<NodeRef>*& stackPtr,
- StackItemT<NodeRef>* stackEnd)
- {
- assert(mask != 0);
-#if defined(__AVX512ER__)
- traverseClosestHitAVX512<4,Nx,types,NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd);
-#else
- const BaseNode* node = cur.baseNode();
-
- /*! one child is hit, continue with that child */
- size_t r = bscf(mask);
- cur = node->child(r);
- BVH::prefetch(cur,types);
- if (likely(mask == 0)) {
- assert(cur != BVH::emptyNode);
- return;
- }
-
- /*! two children are hit, push far child, and continue with closer child */
- NodeRef c0 = cur;
- const unsigned int d0 = ((unsigned int*)&tNear)[r];
- r = bscf(mask);
- NodeRef c1 = node->child(r);
- BVH::prefetch(c1,types);
- const unsigned int d1 = ((unsigned int*)&tNear)[r];
- assert(c0 != BVH::emptyNode);
- assert(c1 != BVH::emptyNode);
- if (likely(mask == 0)) {
- assert(stackPtr < stackEnd);
- if (d0 < d1) { stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++; cur = c0; return; }
- else { stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++; cur = c1; return; }
- }
-
-#if NEW_SORTING_CODE == 1
- vint4 s0((size_t)c0,(size_t)d0);
- vint4 s1((size_t)c1,(size_t)d1);
- r = bscf(mask);
- NodeRef c2 = node->child(r); BVH::prefetch(c2,types); unsigned int d2 = ((unsigned int*)&tNear)[r];
- vint4 s2((size_t)c2,(size_t)d2);
- /* 3 hits */
- if (likely(mask == 0)) {
- StackItemT<NodeRef>::sort3(s0,s1,s2);
- *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1;
- cur = toSizeT(s2);
- stackPtr+=2;
- return;
- }
- r = bscf(mask);
- NodeRef c3 = node->child(r); BVH::prefetch(c3,types); unsigned int d3 = ((unsigned int*)&tNear)[r];
- vint4 s3((size_t)c3,(size_t)d3);
- /* 4 hits */
- StackItemT<NodeRef>::sort4(s0,s1,s2,s3);
- *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1; *(vint4*)&stackPtr[2] = s2;
- cur = toSizeT(s3);
- stackPtr+=3;
-#else
- /*! Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there. */
- assert(stackPtr < stackEnd);
- stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++;
- assert(stackPtr < stackEnd);
- stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++;
-
- /*! three children are hit, push all onto stack and sort 3 stack items, continue with closest child */
- assert(stackPtr < stackEnd);
- r = bscf(mask);
- NodeRef c = node->child(r); BVH::prefetch(c,types); unsigned int d = ((unsigned int*)&tNear)[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
- assert(c != BVH::emptyNode);
- if (likely(mask == 0)) {
- sort(stackPtr[-1],stackPtr[-2],stackPtr[-3]);
- cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
- return;
- }
-
- /*! four children are hit, push all onto stack and sort 4 stack items, continue with closest child */
- assert(stackPtr < stackEnd);
- r = bscf(mask);
- c = node->child(r); BVH::prefetch(c,types); d = *(unsigned int*)&tNear[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
- assert(c != BVH::emptyNode);
- sort(stackPtr[-1],stackPtr[-2],stackPtr[-3],stackPtr[-4]);
- cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
-#endif
-#endif
- }
-
- /* Traverses a node with at least one hit child. Optimized for finding any hit (occlusion). */
- static __forceinline void traverseAnyHit(NodeRef& cur,
- size_t mask,
- const vfloat<Nx>& tNear,
- NodeRef*& stackPtr,
- NodeRef* stackEnd)
- {
- const BaseNode* node = cur.baseNode();
-
- /*! one child is hit, continue with that child */
- size_t r = bscf(mask);
- cur = node->child(r);
- BVH::prefetch(cur,types);
-
- /* simpler in sequence traversal order */
- assert(cur != BVH::emptyNode);
- if (likely(mask == 0)) return;
- assert(stackPtr < stackEnd);
- *stackPtr = cur; stackPtr++;
-
- for (; ;)
- {
- r = bscf(mask);
- cur = node->child(r); BVH::prefetch(cur,types);
- assert(cur != BVH::emptyNode);
- if (likely(mask == 0)) return;
- assert(stackPtr < stackEnd);
- *stackPtr = cur; stackPtr++;
- }
- }
- };
-
- /* Specialization for BVH8. */
- template<int Nx, int types>
- class BVHNNodeTraverser1Hit<8, Nx, types>
- {
- typedef BVH8 BVH;
- typedef BVH8::NodeRef NodeRef;
- typedef BVH8::BaseNode BaseNode;
-
-#if defined(__AVX512VL__)
- template<class NodeRef, class BaseNode>
- static __forceinline void traverseClosestHitAVX512VL8(NodeRef& cur,
- size_t mask,
- const vfloat8& tNear,
- StackItemT<NodeRef>*& stackPtr,
- StackItemT<NodeRef>* stackEnd)
- {
- assert(mask != 0);
- const BaseNode* node = cur.baseNode();
- const vllong4 n0 = vllong4::loadu((vllong4*)&node->children[0]);
- const vllong4 n1 = vllong4::loadu((vllong4*)&node->children[4]);
- vint8 distance_i = (asInt(tNear) & 0xfffffff8) | vint8(step);
- distance_i = vint8::compact((int)mask,distance_i,distance_i);
- cur = permuteExtract(distance_i,n0,n1);
- BVH::prefetch(cur,types);
-
- mask &= mask-1;
- if (likely(mask == 0)) return;
-
- /* 2 hits: order A0 B0 */
- const vint8 d0(distance_i);
- const vint8 d1(shuffle<1>(distance_i));
- cur = permuteExtract(d1,n0,n1);
- BVH::prefetch(cur,types);
-
- const vint8 dist_A0 = min(d0, d1);
- const vint8 dist_B0 = max(d0, d1);
- assert(dist_A0[0] < dist_B0[0]);
-
- mask &= mask-1;
- if (likely(mask == 0)) {
- cur = permuteExtract(dist_A0,n0,n1);
- stackPtr[0].ptr = permuteExtract(dist_B0,n0,n1);
- *(float*)&stackPtr[0].dist = permuteExtract(dist_B0,tNear);
- stackPtr++;
- return;
- }
-
- /* 3 hits: order A1 B1 C1 */
-
- const vint8 d2(shuffle<2>(distance_i));
- cur = permuteExtract(d2,n0,n1);
- BVH::prefetch(cur,types);
-
- const vint8 dist_A1 = min(dist_A0,d2);
- const vint8 dist_tmp_B1 = max(dist_A0,d2);
- const vint8 dist_B1 = min(dist_B0,dist_tmp_B1);
- const vint8 dist_C1 = max(dist_B0,dist_tmp_B1);
- assert(dist_A1[0] < dist_B1[0]);
- assert(dist_B1[0] < dist_C1[0]);
-
- mask &= mask-1;
- if (likely(mask == 0)) {
- cur = permuteExtract(dist_A1,n0,n1);
- stackPtr[0].ptr = permuteExtract(dist_C1,n0,n1);
- *(float*)&stackPtr[0].dist = permuteExtract(dist_C1,tNear);
- stackPtr[1].ptr = permuteExtract(dist_B1,n0,n1);
- *(float*)&stackPtr[1].dist = permuteExtract(dist_B1,tNear);
- stackPtr+=2;
- return;
- }
-
- /* 4 hits: order A2 B2 C2 D2 */
-
- const vint8 d3(shuffle<3>(distance_i));
- cur = permuteExtract(d3,n0,n1);
- BVH::prefetch(cur,types);
-
- const vint8 dist_A2 = min(dist_A1,d3);
- const vint8 dist_tmp_B2 = max(dist_A1,d3);
- const vint8 dist_B2 = min(dist_B1,dist_tmp_B2);
- const vint8 dist_tmp_C2 = max(dist_B1,dist_tmp_B2);
- const vint8 dist_C2 = min(dist_C1,dist_tmp_C2);
- const vint8 dist_D2 = max(dist_C1,dist_tmp_C2);
- assert(dist_A2[0] < dist_B2[0]);
- assert(dist_B2[0] < dist_C2[0]);
- assert(dist_C2[0] < dist_D2[0]);
-
- mask &= mask-1;
- if (likely(mask == 0)) {
- cur = permuteExtract(dist_A2,n0,n1);
- stackPtr[0].ptr = permuteExtract(dist_D2,n0,n1);
- *(float*)&stackPtr[0].dist = permuteExtract(dist_D2,tNear);
- stackPtr[1].ptr = permuteExtract(dist_C2,n0,n1);
- *(float*)&stackPtr[1].dist = permuteExtract(dist_C2,tNear);
- stackPtr[2].ptr = permuteExtract(dist_B2,n0,n1);
- *(float*)&stackPtr[2].dist = permuteExtract(dist_B2,tNear);
- stackPtr+=3;
- return;
- }
-
- /* >=5 hits: reverse to descending order for writing to stack */
-
- distance_i = align_shift_right<3>(distance_i,distance_i);
- const size_t hits = 4 + popcnt(mask);
- vint8 dist(INT_MIN); // this will work with -0.0f (0x80000000) as distance, isort_update uses >= to insert
-
- isort_quick_update(dist,dist_A2);
- isort_quick_update(dist,dist_B2);
- isort_quick_update(dist,dist_C2);
- isort_quick_update(dist,dist_D2);
-
- do {
-
- distance_i = align_shift_right<1>(distance_i,distance_i);
- cur = permuteExtract(distance_i,n0,n1);
- BVH::prefetch(cur,types);
- const vint8 new_dist(permute(distance_i,vint8(zero)));
- mask &= mask-1;
- isort_update(dist,new_dist);
-
- } while(mask);
-
- for (size_t i=0; i<7; i++)
- assert(dist[i+0]>=dist[i+1]);
-
- for (size_t i=0;i<hits-1;i++)
- {
- stackPtr->ptr = permuteExtract(dist,n0,n1);
- *(float*)&stackPtr->dist = permuteExtract(dist,tNear);
- dist = align_shift_right<1>(dist,dist);
- stackPtr++;
- }
- cur = permuteExtract(dist,n0,n1);
- }
-#endif
-
- public:
- static __forceinline void traverseClosestHit(NodeRef& cur,
- size_t mask,
- const vfloat<Nx>& tNear,
- StackItemT<NodeRef>*& stackPtr,
- StackItemT<NodeRef>* stackEnd)
- {
- assert(mask != 0);
-#if defined(__AVX512ER__)
- traverseClosestHitAVX512<8,Nx,types,NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd);
-#elif defined(__AVX512VL__)
- traverseClosestHitAVX512VL8<NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd);
-#else
-
- const BaseNode* node = cur.baseNode();
-
- /*! one child is hit, continue with that child */
- size_t r = bscf(mask);
- cur = node->child(r);
- BVH::prefetch(cur,types);
- if (likely(mask == 0)) {
- assert(cur != BVH::emptyNode);
- return;
- }
-
- /*! two children are hit, push far child, and continue with closer child */
- NodeRef c0 = cur;
- const unsigned int d0 = ((unsigned int*)&tNear)[r];
- r = bscf(mask);
- NodeRef c1 = node->child(r);
- BVH::prefetch(c1,types);
- const unsigned int d1 = ((unsigned int*)&tNear)[r];
-
- assert(c0 != BVH::emptyNode);
- assert(c1 != BVH::emptyNode);
- if (likely(mask == 0)) {
- assert(stackPtr < stackEnd);
- if (d0 < d1) { stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++; cur = c0; return; }
- else { stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++; cur = c1; return; }
- }
-#if NEW_SORTING_CODE == 1
- vint4 s0((size_t)c0,(size_t)d0);
- vint4 s1((size_t)c1,(size_t)d1);
-
- r = bscf(mask);
- NodeRef c2 = node->child(r); BVH::prefetch(c2,types); unsigned int d2 = ((unsigned int*)&tNear)[r];
- vint4 s2((size_t)c2,(size_t)d2);
- /* 3 hits */
- if (likely(mask == 0)) {
- StackItemT<NodeRef>::sort3(s0,s1,s2);
- *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1;
- cur = toSizeT(s2);
- stackPtr+=2;
- return;
- }
- r = bscf(mask);
- NodeRef c3 = node->child(r); BVH::prefetch(c3,types); unsigned int d3 = ((unsigned int*)&tNear)[r];
- vint4 s3((size_t)c3,(size_t)d3);
- /* 4 hits */
- if (likely(mask == 0)) {
- StackItemT<NodeRef>::sort4(s0,s1,s2,s3);
- *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1; *(vint4*)&stackPtr[2] = s2;
- cur = toSizeT(s3);
- stackPtr+=3;
- return;
- }
- *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1; *(vint4*)&stackPtr[2] = s2; *(vint4*)&stackPtr[3] = s3;
- /*! fallback case if more than 4 children are hit */
- StackItemT<NodeRef>* stackFirst = stackPtr;
- stackPtr+=4;
- while (1)
- {
- assert(stackPtr < stackEnd);
- r = bscf(mask);
- NodeRef c = node->child(r); BVH::prefetch(c,types); unsigned int d = *(unsigned int*)&tNear[r];
- const vint4 s((size_t)c,(size_t)d);
- *(vint4*)stackPtr++ = s;
- assert(c != BVH::emptyNode);
- if (unlikely(mask == 0)) break;
- }
- sort(stackFirst,stackPtr);
- cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
-#else
- /*! Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there. */
- assert(stackPtr < stackEnd);
- stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++;
- assert(stackPtr < stackEnd);
- stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++;
-
- /*! three children are hit, push all onto stack and sort 3 stack items, continue with closest child */
- assert(stackPtr < stackEnd);
- r = bscf(mask);
- NodeRef c = node->child(r); BVH::prefetch(c,types); unsigned int d = ((unsigned int*)&tNear)[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
- assert(c != BVH::emptyNode);
- if (likely(mask == 0)) {
- sort(stackPtr[-1],stackPtr[-2],stackPtr[-3]);
- cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
- return;
- }
-
- /*! four children are hit, push all onto stack and sort 4 stack items, continue with closest child */
- assert(stackPtr < stackEnd);
- r = bscf(mask);
- c = node->child(r); BVH::prefetch(c,types); d = *(unsigned int*)&tNear[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
- assert(c != BVH::emptyNode);
- if (likely(mask == 0)) {
- sort(stackPtr[-1],stackPtr[-2],stackPtr[-3],stackPtr[-4]);
- cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
- return;
- }
- /*! fallback case if more than 4 children are hit */
- StackItemT<NodeRef>* stackFirst = stackPtr-4;
- while (1)
- {
- assert(stackPtr < stackEnd);
- r = bscf(mask);
- c = node->child(r); BVH::prefetch(c,types); d = *(unsigned int*)&tNear[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
- assert(c != BVH::emptyNode);
- if (unlikely(mask == 0)) break;
- }
- sort(stackFirst,stackPtr);
- cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
-#endif
-#endif
- }
-
- static __forceinline void traverseAnyHit(NodeRef& cur,
- size_t mask,
- const vfloat<Nx>& tNear,
- NodeRef*& stackPtr,
- NodeRef* stackEnd)
- {
- const BaseNode* node = cur.baseNode();
-
- /*! one child is hit, continue with that child */
- size_t r = bscf(mask);
- cur = node->child(r);
- BVH::prefetch(cur,types);
-
- /* simpler in sequence traversal order */
- assert(cur != BVH::emptyNode);
- if (likely(mask == 0)) return;
- assert(stackPtr < stackEnd);
- *stackPtr = cur; stackPtr++;
-
- for (; ;)
- {
- r = bscf(mask);
- cur = node->child(r); BVH::prefetch(cur,types);
- assert(cur != BVH::emptyNode);
- if (likely(mask == 0)) return;
- assert(stackPtr < stackEnd);
- *stackPtr = cur; stackPtr++;
- }
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_traverser_stream.h b/thirdparty/embree-aarch64/kernels/bvh/bvh_traverser_stream.h
deleted file mode 100644
index 9c603babf0..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/bvh_traverser_stream.h
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-#include "../common/ray.h"
-#include "../common/stack_item.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int N, int Nx, int types>
- class BVHNNodeTraverserStreamHitCoherent
- {
- typedef BVHN<N> BVH;
- typedef typename BVH::NodeRef NodeRef;
- typedef typename BVH::BaseNode BaseNode;
-
- public:
- template<class T>
- static __forceinline void traverseClosestHit(NodeRef& cur,
- size_t& m_trav_active,
- const vbool<Nx>& vmask,
- const vfloat<Nx>& tNear,
- const T* const tMask,
- StackItemMaskCoherent*& stackPtr)
- {
- const NodeRef parent = cur;
- size_t mask = movemask(vmask);
- assert(mask != 0);
- const BaseNode* node = cur.baseNode();
-
- /*! one child is hit, continue with that child */
- const size_t r0 = bscf(mask);
- assert(r0 < 8);
- cur = node->child(r0);
- BVHN<N>::prefetch(cur,types);
- m_trav_active = tMask[r0];
- assert(cur != BVH::emptyNode);
- if (unlikely(mask == 0)) return;
-
- const unsigned int* const tNear_i = (unsigned int*)&tNear;
-
- /*! two children are hit, push far child, and continue with closer child */
- NodeRef c0 = cur;
- unsigned int d0 = tNear_i[r0];
- const size_t r1 = bscf(mask);
- assert(r1 < 8);
- NodeRef c1 = node->child(r1);
- BVHN<N>::prefetch(c1,types);
- unsigned int d1 = tNear_i[r1];
-
- assert(c0 != BVH::emptyNode);
- assert(c1 != BVH::emptyNode);
- if (likely(mask == 0)) {
- if (d0 < d1) {
- assert(tNear[r1] >= 0.0f);
- stackPtr->mask = tMask[r1];
- stackPtr->parent = parent;
- stackPtr->child = c1;
- stackPtr++;
- cur = c0;
- m_trav_active = tMask[r0];
- return;
- }
- else {
- assert(tNear[r0] >= 0.0f);
- stackPtr->mask = tMask[r0];
- stackPtr->parent = parent;
- stackPtr->child = c0;
- stackPtr++;
- cur = c1;
- m_trav_active = tMask[r1];
- return;
- }
- }
-
- /*! slow path for more than two hits */
- size_t hits = movemask(vmask);
- const vint<Nx> dist_i = select(vmask, (asInt(tNear) & 0xfffffff8) | vint<Nx>(step), 0);
- #if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
- const vint<N> tmp = extractN<N,0>(dist_i);
- const vint<Nx> dist_i_sorted = usort_descending(tmp);
- #else
- const vint<Nx> dist_i_sorted = usort_descending(dist_i);
- #endif
- const vint<Nx> sorted_index = dist_i_sorted & 7;
-
- size_t i = 0;
- for (;;)
- {
- const unsigned int index = sorted_index[i];
- assert(index < 8);
- cur = node->child(index);
- m_trav_active = tMask[index];
- assert(m_trav_active);
- BVHN<N>::prefetch(cur,types);
- bscf(hits);
- if (unlikely(hits==0)) break;
- i++;
- assert(cur != BVH::emptyNode);
- assert(tNear[index] >= 0.0f);
- stackPtr->mask = m_trav_active;
- stackPtr->parent = parent;
- stackPtr->child = cur;
- stackPtr++;
- }
- }
-
- template<class T>
- static __forceinline void traverseAnyHit(NodeRef& cur,
- size_t& m_trav_active,
- const vbool<Nx>& vmask,
- const T* const tMask,
- StackItemMaskCoherent*& stackPtr)
- {
- const NodeRef parent = cur;
- size_t mask = movemask(vmask);
- assert(mask != 0);
- const BaseNode* node = cur.baseNode();
-
- /*! one child is hit, continue with that child */
- size_t r = bscf(mask);
- cur = node->child(r);
- BVHN<N>::prefetch(cur,types);
- m_trav_active = tMask[r];
-
- /* simple in order sequence */
- assert(cur != BVH::emptyNode);
- if (likely(mask == 0)) return;
- stackPtr->mask = m_trav_active;
- stackPtr->parent = parent;
- stackPtr->child = cur;
- stackPtr++;
-
- for (; ;)
- {
- r = bscf(mask);
- cur = node->child(r);
- BVHN<N>::prefetch(cur,types);
- m_trav_active = tMask[r];
- assert(cur != BVH::emptyNode);
- if (likely(mask == 0)) return;
- stackPtr->mask = m_trav_active;
- stackPtr->parent = parent;
- stackPtr->child = cur;
- stackPtr++;
- }
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/node_intersector.h b/thirdparty/embree-aarch64/kernels/bvh/node_intersector.h
deleted file mode 100644
index a978c0c459..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/node_intersector.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bvh.h"
-
-namespace embree
-{
- namespace isa
- {
- struct NearFarPrecalculations
- {
- size_t nearX, nearY, nearZ;
- size_t farX, farY, farZ;
-
- __forceinline NearFarPrecalculations() {}
-
- __forceinline NearFarPrecalculations(const Vec3fa& dir, size_t N)
- {
- const size_t size = sizeof(float)*N;
- nearX = (dir.x < 0.0f) ? 1*size : 0*size;
- nearY = (dir.y < 0.0f) ? 3*size : 2*size;
- nearZ = (dir.z < 0.0f) ? 5*size : 4*size;
- farX = nearX ^ size;
- farY = nearY ^ size;
- farZ = nearZ ^ size;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/node_intersector1.h b/thirdparty/embree-aarch64/kernels/bvh/node_intersector1.h
deleted file mode 100644
index aa0d4ba4d7..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/node_intersector1.h
+++ /dev/null
@@ -1,1788 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "node_intersector.h"
-
-#if defined(__AVX2__)
-#define __FMA_X4__
-#endif
-
-#if defined(__aarch64__)
-#define __FMA_X4__
-#endif
-
-
-namespace embree
-{
- namespace isa
- {
- //////////////////////////////////////////////////////////////////////////////////////
- // Ray structure used in single-ray traversal
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int Nx, bool robust>
- struct TravRayBase;
-
- /* Base (without tnear and tfar) */
- template<int N, int Nx>
- struct TravRayBase<N,Nx,false>
- {
- __forceinline TravRayBase() {}
-
- __forceinline TravRayBase(const Vec3fa& ray_org, const Vec3fa& ray_dir)
- : org_xyz(ray_org), dir_xyz(ray_dir)
- {
- const Vec3fa ray_rdir = rcp_safe(ray_dir);
- org = Vec3vf<N>(ray_org.x,ray_org.y,ray_org.z);
- dir = Vec3vf<N>(ray_dir.x,ray_dir.y,ray_dir.z);
- rdir = Vec3vf<N>(ray_rdir.x,ray_rdir.y,ray_rdir.z);
-#if defined(__FMA_X4__)
- const Vec3fa ray_org_rdir = ray_org*ray_rdir;
-#if !defined(__aarch64__)
- org_rdir = Vec3vf<N>(ray_org_rdir.x,ray_org_rdir.y,ray_org_rdir.z);
-#else
- //for aarch64, we do not have msub equal instruction, so we negeate orig and use madd
- //x86 will use msub
- neg_org_rdir = Vec3vf<N>(-ray_org_rdir.x,-ray_org_rdir.y,-ray_org_rdir.z);
-#endif
-#endif
- nearX = ray_rdir.x >= 0.0f ? 0*sizeof(vfloat<N>) : 1*sizeof(vfloat<N>);
- nearY = ray_rdir.y >= 0.0f ? 2*sizeof(vfloat<N>) : 3*sizeof(vfloat<N>);
- nearZ = ray_rdir.z >= 0.0f ? 4*sizeof(vfloat<N>) : 5*sizeof(vfloat<N>);
- farX = nearX ^ sizeof(vfloat<N>);
- farY = nearY ^ sizeof(vfloat<N>);
- farZ = nearZ ^ sizeof(vfloat<N>);
-
-#if defined(__AVX512ER__) // KNL+
- /* optimization works only for 8-wide BVHs with 16-wide SIMD */
- const vint<16> id(step);
- const vint<16> id2 = align_shift_right<16/2>(id, id);
- permX = select(vfloat<16>(dir.x) >= 0.0f, id, id2);
- permY = select(vfloat<16>(dir.y) >= 0.0f, id, id2);
- permZ = select(vfloat<16>(dir.z) >= 0.0f, id, id2);
-#endif
-
- }
-
- template<int K>
- __forceinline TravRayBase(size_t k, const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir,
- const Vec3vf<K>& ray_rdir, const Vec3vi<K>& nearXYZ,
- size_t flip = sizeof(vfloat<N>))
- {
- org = Vec3vf<Nx>(ray_org.x[k], ray_org.y[k], ray_org.z[k]);
- dir = Vec3vf<Nx>(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]);
- rdir = Vec3vf<Nx>(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]);
-#if defined(__FMA_X4__)
-#if !defined(__aarch64__)
- org_rdir = org*rdir;
-#else
- neg_org_rdir = -(org*rdir);
-#endif
-#endif
- nearX = nearXYZ.x[k];
- nearY = nearXYZ.y[k];
- nearZ = nearXYZ.z[k];
- farX = nearX ^ flip;
- farY = nearY ^ flip;
- farZ = nearZ ^ flip;
-
-#if defined(__AVX512ER__) // KNL+
- /* optimization works only for 8-wide BVHs with 16-wide SIMD */
- const vint<16> id(step);
- const vint<16> id2 = align_shift_right<16/2>(id, id);
- permX = select(vfloat<16>(dir.x) >= 0.0f, id, id2);
- permY = select(vfloat<16>(dir.y) >= 0.0f, id, id2);
- permZ = select(vfloat<16>(dir.z) >= 0.0f, id, id2);
-#endif
- }
-
- Vec3fa org_xyz, dir_xyz;
- Vec3vf<Nx> org, dir, rdir;
-#if defined(__FMA_X4__)
-#if !defined(__aarch64__)
- Vec3vf<Nx> org_rdir;
-#else
- //aarch64 version are keeping negation of the org_rdir and use madd
- //x86 uses msub
- Vec3vf<Nx> neg_org_rdir;
-#endif
-#endif
-#if defined(__AVX512ER__) // KNL+
- vint16 permX, permY, permZ;
-#endif
-
- size_t nearX, nearY, nearZ;
- size_t farX, farY, farZ;
- };
-
- /* Base (without tnear and tfar) */
- template<int N, int Nx>
- struct TravRayBase<N,Nx,true>
- {
- __forceinline TravRayBase() {}
-
- __forceinline TravRayBase(const Vec3fa& ray_org, const Vec3fa& ray_dir)
- : org_xyz(ray_org), dir_xyz(ray_dir)
- {
- const float round_down = 1.0f-3.0f*float(ulp);
- const float round_up = 1.0f+3.0f*float(ulp);
- const Vec3fa ray_rdir = 1.0f/zero_fix(ray_dir);
- const Vec3fa ray_rdir_near = round_down*ray_rdir;
- const Vec3fa ray_rdir_far = round_up *ray_rdir;
- org = Vec3vf<N>(ray_org.x,ray_org.y,ray_org.z);
- dir = Vec3vf<N>(ray_dir.x,ray_dir.y,ray_dir.z);
- rdir_near = Vec3vf<N>(ray_rdir_near.x,ray_rdir_near.y,ray_rdir_near.z);
- rdir_far = Vec3vf<N>(ray_rdir_far .x,ray_rdir_far .y,ray_rdir_far .z);
- nearX = ray_rdir_near.x >= 0.0f ? 0*sizeof(vfloat<N>) : 1*sizeof(vfloat<N>);
- nearY = ray_rdir_near.y >= 0.0f ? 2*sizeof(vfloat<N>) : 3*sizeof(vfloat<N>);
- nearZ = ray_rdir_near.z >= 0.0f ? 4*sizeof(vfloat<N>) : 5*sizeof(vfloat<N>);
- farX = nearX ^ sizeof(vfloat<N>);
- farY = nearY ^ sizeof(vfloat<N>);
- farZ = nearZ ^ sizeof(vfloat<N>);
-
-#if defined(__AVX512ER__) // KNL+
- /* optimization works only for 8-wide BVHs with 16-wide SIMD */
- const vint<16> id(step);
- const vint<16> id2 = align_shift_right<16/2>(id, id);
- permX = select(vfloat<16>(dir.x) >= 0.0f, id, id2);
- permY = select(vfloat<16>(dir.y) >= 0.0f, id, id2);
- permZ = select(vfloat<16>(dir.z) >= 0.0f, id, id2);
-#endif
- }
-
- template<int K>
- __forceinline TravRayBase(size_t k, const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir,
- const Vec3vf<K>& ray_rdir, const Vec3vi<K>& nearXYZ,
- size_t flip = sizeof(vfloat<N>))
- {
- const vfloat<Nx> round_down = 1.0f-3.0f*float(ulp);
- const vfloat<Nx> round_up = 1.0f+3.0f*float(ulp);
- org = Vec3vf<Nx>(ray_org.x[k], ray_org.y[k], ray_org.z[k]);
- dir = Vec3vf<Nx>(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]);
- rdir_near = round_down*Vec3vf<Nx>(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]);
- rdir_far = round_up *Vec3vf<Nx>(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]);
-
- nearX = nearXYZ.x[k];
- nearY = nearXYZ.y[k];
- nearZ = nearXYZ.z[k];
- farX = nearX ^ flip;
- farY = nearY ^ flip;
- farZ = nearZ ^ flip;
-
-#if defined(__AVX512ER__) // KNL+
- /* optimization works only for 8-wide BVHs with 16-wide SIMD */
- const vint<16> id(step);
- const vint<16> id2 = align_shift_right<16/2>(id, id);
- permX = select(vfloat<16>(dir.x) >= 0.0f, id, id2);
- permY = select(vfloat<16>(dir.y) >= 0.0f, id, id2);
- permZ = select(vfloat<16>(dir.z) >= 0.0f, id, id2);
-#endif
- }
-
- Vec3fa org_xyz, dir_xyz;
- Vec3vf<Nx> org, dir, rdir_near, rdir_far;
-#if defined(__AVX512ER__) // KNL+
- vint16 permX, permY, permZ;
-#endif
-
- size_t nearX, nearY, nearZ;
- size_t farX, farY, farZ;
- };
-
- /* Full (with tnear and tfar) */
- template<int N, int Nx, bool robust>
- struct TravRay : TravRayBase<N,Nx,robust>
- {
- __forceinline TravRay() {}
-
- __forceinline TravRay(const Vec3fa& ray_org, const Vec3fa& ray_dir, float ray_tnear, float ray_tfar)
- : TravRayBase<N,Nx,robust>(ray_org, ray_dir),
- tnear(ray_tnear), tfar(ray_tfar) {}
-
- template<int K>
- __forceinline TravRay(size_t k, const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir,
- const Vec3vf<K>& ray_rdir, const Vec3vi<K>& nearXYZ,
- float ray_tnear, float ray_tfar,
- size_t flip = sizeof(vfloat<N>))
- : TravRayBase<N,Nx,robust>(k, ray_org, ray_dir, ray_rdir, nearXYZ, flip),
- tnear(ray_tnear), tfar(ray_tfar) {}
-
- vfloat<Nx> tnear;
- vfloat<Nx> tfar;
- };
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Point Query structure used in single-ray traversal
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N>
- struct TravPointQuery
- {
- __forceinline TravPointQuery() {}
-
- __forceinline TravPointQuery(const Vec3fa& query_org, const Vec3fa& query_rad)
- {
- org = Vec3vf<N>(query_org.x, query_org.y, query_org.z);
- rad = Vec3vf<N>(query_rad.x, query_rad.y, query_rad.z);
- }
-
- __forceinline vfloat<N> const& tfar() const {
- return rad.x;
- }
-
- Vec3vf<N> org, rad;
- };
-
- //////////////////////////////////////////////////////////////////////////////////////
- // point query
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N>
- __forceinline size_t pointQuerySphereDistAndMask(
- const TravPointQuery<N>& query, vfloat<N>& dist, vfloat<N> const& minX, vfloat<N> const& maxX,
- vfloat<N> const& minY, vfloat<N> const& maxY, vfloat<N> const& minZ, vfloat<N> const& maxZ)
- {
- const vfloat<N> vX = min(max(query.org.x, minX), maxX) - query.org.x;
- const vfloat<N> vY = min(max(query.org.y, minY), maxY) - query.org.y;
- const vfloat<N> vZ = min(max(query.org.z, minZ), maxZ) - query.org.z;
- dist = vX * vX + vY * vY + vZ * vZ;
- const vbool<N> vmask = dist <= query.tfar()*query.tfar();
- const vbool<N> valid = minX <= maxX;
- return movemask(vmask) & movemask(valid);
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::AABBNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
- {
- const vfloat<N> minX = vfloat<N>::load((float*)((const char*)&node->lower_x));
- const vfloat<N> minY = vfloat<N>::load((float*)((const char*)&node->lower_y));
- const vfloat<N> minZ = vfloat<N>::load((float*)((const char*)&node->lower_z));
- const vfloat<N> maxX = vfloat<N>::load((float*)((const char*)&node->upper_x));
- const vfloat<N> maxY = vfloat<N>::load((float*)((const char*)&node->upper_y));
- const vfloat<N> maxZ = vfloat<N>::load((float*)((const char*)&node->upper_z));
- return pointQuerySphereDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ);
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::AABBNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- const vfloat<N>* pMinX = (const vfloat<N>*)((const char*)&node->lower_x);
- const vfloat<N>* pMinY = (const vfloat<N>*)((const char*)&node->lower_y);
- const vfloat<N>* pMinZ = (const vfloat<N>*)((const char*)&node->lower_z);
- const vfloat<N>* pMaxX = (const vfloat<N>*)((const char*)&node->upper_x);
- const vfloat<N>* pMaxY = (const vfloat<N>*)((const char*)&node->upper_y);
- const vfloat<N>* pMaxZ = (const vfloat<N>*)((const char*)&node->upper_z);
- const vfloat<N> minX = madd(time,pMinX[6],vfloat<N>(pMinX[0]));
- const vfloat<N> minY = madd(time,pMinY[6],vfloat<N>(pMinY[0]));
- const vfloat<N> minZ = madd(time,pMinZ[6],vfloat<N>(pMinZ[0]));
- const vfloat<N> maxX = madd(time,pMaxX[6],vfloat<N>(pMaxX[0]));
- const vfloat<N> maxY = madd(time,pMaxY[6],vfloat<N>(pMaxY[0]));
- const vfloat<N> maxZ = madd(time,pMaxZ[6],vfloat<N>(pMaxZ[0]));
- return pointQuerySphereDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ);
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeSphereMB4D(const typename BVHN<N>::NodeRef ref, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
- size_t mask = pointQueryNodeSphere(node, query, time, dist);
-
- if (unlikely(ref.isAABBNodeMB4D())) {
- const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
- const vbool<N> vmask = (node1->lower_t <= time) & (time < node1->upper_t);
- mask &= movemask(vmask);
- }
-
- return mask;
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::QuantizedBaseNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
- {
- const vfloat<N> start_x(node->start.x);
- const vfloat<N> scale_x(node->scale.x);
- const vfloat<N> minX = madd(node->template dequantize<N>((0*sizeof(vfloat<N>)) >> 2),scale_x,start_x);
- const vfloat<N> maxX = madd(node->template dequantize<N>((1*sizeof(vfloat<N>)) >> 2),scale_x,start_x);
- const vfloat<N> start_y(node->start.y);
- const vfloat<N> scale_y(node->scale.y);
- const vfloat<N> minY = madd(node->template dequantize<N>((2*sizeof(vfloat<N>)) >> 2),scale_y,start_y);
- const vfloat<N> maxY = madd(node->template dequantize<N>((3*sizeof(vfloat<N>)) >> 2),scale_y,start_y);
- const vfloat<N> start_z(node->start.z);
- const vfloat<N> scale_z(node->scale.z);
- const vfloat<N> minZ = madd(node->template dequantize<N>((4*sizeof(vfloat<N>)) >> 2),scale_z,start_z);
- const vfloat<N> maxZ = madd(node->template dequantize<N>((5*sizeof(vfloat<N>)) >> 2),scale_z,start_z);
- return pointQuerySphereDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ) & movemask(node->validMask());
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- const vfloat<N> minX = node->dequantizeLowerX(time);
- const vfloat<N> maxX = node->dequantizeUpperX(time);
- const vfloat<N> minY = node->dequantizeLowerY(time);
- const vfloat<N> maxY = node->dequantizeUpperY(time);
- const vfloat<N> minZ = node->dequantizeLowerZ(time);
- const vfloat<N> maxZ = node->dequantizeUpperZ(time);
- return pointQuerySphereDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ) & movemask(node->validMask());
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::OBBNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
- {
- // TODO: point query - implement
- const vbool<N> vmask = vbool<N>(true);
- const size_t mask = movemask(vmask) & ((1<<N)-1);
- dist = vfloat<N>(0.0f);
- return mask;
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::OBBNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- // TODO: point query - implement
- const vbool<N> vmask = vbool<N>(true);
- const size_t mask = movemask(vmask) & ((1<<N)-1);
- dist = vfloat<N>(0.0f);
- return mask;
- }
-
- template<int N>
- __forceinline size_t pointQueryAABBDistAndMask(
- const TravPointQuery<N>& query, vfloat<N>& dist, vfloat<N> const& minX, vfloat<N> const& maxX,
- vfloat<N> const& minY, vfloat<N> const& maxY, vfloat<N> const& minZ, vfloat<N> const& maxZ)
- {
- const vfloat<N> vX = min(max(query.org.x, minX), maxX) - query.org.x;
- const vfloat<N> vY = min(max(query.org.y, minY), maxY) - query.org.y;
- const vfloat<N> vZ = min(max(query.org.z, minZ), maxZ) - query.org.z;
- dist = vX * vX + vY * vY + vZ * vZ;
- const vbool<N> valid = minX <= maxX;
- const vbool<N> vmask = !((maxX < query.org.x - query.rad.x) | (minX > query.org.x + query.rad.x) |
- (maxY < query.org.y - query.rad.y) | (minY > query.org.y + query.rad.y) |
- (maxZ < query.org.z - query.rad.z) | (minZ > query.org.z + query.rad.z));
- return movemask(vmask) & movemask(valid);
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::AABBNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
- {
- const vfloat<N> minX = vfloat<N>::load((float*)((const char*)&node->lower_x));
- const vfloat<N> minY = vfloat<N>::load((float*)((const char*)&node->lower_y));
- const vfloat<N> minZ = vfloat<N>::load((float*)((const char*)&node->lower_z));
- const vfloat<N> maxX = vfloat<N>::load((float*)((const char*)&node->upper_x));
- const vfloat<N> maxY = vfloat<N>::load((float*)((const char*)&node->upper_y));
- const vfloat<N> maxZ = vfloat<N>::load((float*)((const char*)&node->upper_z));
- return pointQueryAABBDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ);
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::AABBNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- const vfloat<N>* pMinX = (const vfloat<N>*)((const char*)&node->lower_x);
- const vfloat<N>* pMinY = (const vfloat<N>*)((const char*)&node->lower_y);
- const vfloat<N>* pMinZ = (const vfloat<N>*)((const char*)&node->lower_z);
- const vfloat<N>* pMaxX = (const vfloat<N>*)((const char*)&node->upper_x);
- const vfloat<N>* pMaxY = (const vfloat<N>*)((const char*)&node->upper_y);
- const vfloat<N>* pMaxZ = (const vfloat<N>*)((const char*)&node->upper_z);
- const vfloat<N> minX = madd(time,pMinX[6],vfloat<N>(pMinX[0]));
- const vfloat<N> minY = madd(time,pMinY[6],vfloat<N>(pMinY[0]));
- const vfloat<N> minZ = madd(time,pMinZ[6],vfloat<N>(pMinZ[0]));
- const vfloat<N> maxX = madd(time,pMaxX[6],vfloat<N>(pMaxX[0]));
- const vfloat<N> maxY = madd(time,pMaxY[6],vfloat<N>(pMaxY[0]));
- const vfloat<N> maxZ = madd(time,pMaxZ[6],vfloat<N>(pMaxZ[0]));
- return pointQueryAABBDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ);
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeAABBMB4D(const typename BVHN<N>::NodeRef ref, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
- size_t mask = pointQueryNodeAABB(node, query, time, dist);
-
- if (unlikely(ref.isAABBNodeMB4D())) {
- const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
- const vbool<N> vmask = (node1->lower_t <= time) & (time < node1->upper_t);
- mask &= movemask(vmask);
- }
-
- return mask;
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::QuantizedBaseNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat<N> start_x(node->start.x);
- const vfloat<N> scale_x(node->scale.x);
- const vfloat<N> minX = madd(node->template dequantize<N>((0*sizeof(vfloat<N>)) >> 2),scale_x,start_x);
- const vfloat<N> maxX = madd(node->template dequantize<N>((1*sizeof(vfloat<N>)) >> 2),scale_x,start_x);
- const vfloat<N> start_y(node->start.y);
- const vfloat<N> scale_y(node->scale.y);
- const vfloat<N> minY = madd(node->template dequantize<N>((2*sizeof(vfloat<N>)) >> 2),scale_y,start_y);
- const vfloat<N> maxY = madd(node->template dequantize<N>((3*sizeof(vfloat<N>)) >> 2),scale_y,start_y);
- const vfloat<N> start_z(node->start.z);
- const vfloat<N> scale_z(node->scale.z);
- const vfloat<N> minZ = madd(node->template dequantize<N>((4*sizeof(vfloat<N>)) >> 2),scale_z,start_z);
- const vfloat<N> maxZ = madd(node->template dequantize<N>((5*sizeof(vfloat<N>)) >> 2),scale_z,start_z);
- return pointQueryAABBDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ) & mvalid;
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat<N> minX = node->dequantizeLowerX(time);
- const vfloat<N> maxX = node->dequantizeUpperX(time);
- const vfloat<N> minY = node->dequantizeLowerY(time);
- const vfloat<N> maxY = node->dequantizeUpperY(time);
- const vfloat<N> minZ = node->dequantizeLowerZ(time);
- const vfloat<N> maxZ = node->dequantizeUpperZ(time);
- return pointQueryAABBDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ) & mvalid;
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::OBBNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
- {
- // TODO: point query - implement
- const vbool<N> vmask = vbool<N>(true);
- const size_t mask = movemask(vmask) & ((1<<N)-1);
- dist = vfloat<N>(0.0f);
- return mask;
- }
-
- template<int N>
- __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::OBBNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- // TODO: point query - implement
- const vbool<N> vmask = vbool<N>(true);
- const size_t mask = movemask(vmask) & ((1<<N)-1);
- dist = vfloat<N>(0.0f);
- return mask;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast AABBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int Nx, bool robust>
- __forceinline size_t intersectNode(const typename BVHN<N>::AABBNode* node, const TravRay<N,Nx,robust>& ray, vfloat<Nx>& dist);
-
- template<>
- __forceinline size_t intersectNode<4,4>(const typename BVH4::AABBNode* node, const TravRay<4,4,false>& ray, vfloat4& dist)
- {
-#if defined(__FMA_X4__)
-#if defined(__aarch64__)
- const vfloat4 tNearX = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat4 tNearY = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat4 tNearZ = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat4 tFarX = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat4 tFarY = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat4 tFarZ = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.neg_org_rdir.z);
-#else
- const vfloat4 tNearX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
- const vfloat4 tNearY = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
- const vfloat4 tNearZ = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z);
- const vfloat4 tFarX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x);
- const vfloat4 tFarY = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y);
- const vfloat4 tFarZ = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z);
-#endif
-#else
- const vfloat4 tNearX = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
- const vfloat4 tNearY = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
- const vfloat4 tNearZ = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir.z;
- const vfloat4 tFarX = (vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir.x;
- const vfloat4 tFarY = (vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir.y;
- const vfloat4 tFarZ = (vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir.z;
-#endif
-
-#if defined(__aarch64__)
- const vfloat4 tNear = maxi(tNearX, tNearY, tNearZ, ray.tnear);
- const vfloat4 tFar = mini(tFarX, tFarY, tFarZ, ray.tfar);
- const vbool4 vmask = asInt(tNear) <= asInt(tFar);
- const size_t mask = movemask(vmask);
-#elif defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW
- const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool4 vmask = asInt(tNear) > asInt(tFar);
- const size_t mask = movemask(vmask) ^ ((1<<4)-1);
-#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool4 vmask = asInt(tNear) <= asInt(tFar);
- const size_t mask = movemask(vmask);
-#else
- const vfloat4 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat4 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool4 vmask = tNear <= tFar;
- const size_t mask = movemask(vmask);
-#endif
- dist = tNear;
- return mask;
- }
-
-#if defined(__AVX__)
-
- template<>
- __forceinline size_t intersectNode<8,8>(const typename BVH8::AABBNode* node, const TravRay<8,8,false>& ray, vfloat8& dist)
- {
-#if defined(__AVX2__)
-#if defined(__aarch64__)
- const vfloat8 tNearX = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat8 tNearY = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat8 tNearZ = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat8 tFarX = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat8 tFarY = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat8 tFarZ = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.neg_org_rdir.z);
-#else
- const vfloat8 tNearX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
- const vfloat8 tNearY = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
- const vfloat8 tNearZ = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z);
- const vfloat8 tFarX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x);
- const vfloat8 tFarY = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y);
- const vfloat8 tFarZ = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z);
-#endif
-
-#else
- const vfloat8 tNearX = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
- const vfloat8 tNearY = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
- const vfloat8 tNearZ = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir.z;
- const vfloat8 tFarX = (vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir.x;
- const vfloat8 tFarY = (vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir.y;
- const vfloat8 tFarZ = (vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir.z;
-#endif
-
-#if defined(__AVX2__) && !defined(__AVX512F__) // HSW
- const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool8 vmask = asInt(tNear) > asInt(tFar);
- const size_t mask = movemask(vmask) ^ ((1<<8)-1);
-#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool8 vmask = asInt(tNear) <= asInt(tFar);
- const size_t mask = movemask(vmask);
-#else
- const vfloat8 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat8 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool8 vmask = tNear <= tFar;
- const size_t mask = movemask(vmask);
-#endif
- dist = tNear;
- return mask;
- }
-
-#endif
-
-#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
-
- template<>
- __forceinline size_t intersectNode<4,16>(const typename BVH4::AABBNode* node, const TravRay<4,16,false>& ray, vfloat16& dist)
- {
- const vfloat16 tNearX = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
- const vfloat16 tNearY = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
- const vfloat16 tNearZ = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z);
- const vfloat16 tFarX = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x);
- const vfloat16 tFarY = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y);
- const vfloat16 tFarZ = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z);
- const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool16 vmask = le(vbool16(0xf),tNear,tFar);
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
- template<>
- __forceinline size_t intersectNode<8,16>(const typename BVH8::AABBNode* node, const TravRay<8,16,false>& ray, vfloat16& dist)
- {
- const vllong8 invalid((size_t)BVH8::emptyNode);
- const vboold8 m_valid(invalid != vllong8::loadu(node->children));
- const vfloat16 bminmaxX = permute(vfloat16::load((const float*)&node->lower_x), ray.permX);
- const vfloat16 bminmaxY = permute(vfloat16::load((const float*)&node->lower_y), ray.permY);
- const vfloat16 bminmaxZ = permute(vfloat16::load((const float*)&node->lower_z), ray.permZ);
- const vfloat16 tNearFarX = msub(bminmaxX, ray.rdir.x, ray.org_rdir.x);
- const vfloat16 tNearFarY = msub(bminmaxY, ray.rdir.y, ray.org_rdir.y);
- const vfloat16 tNearFarZ = msub(bminmaxZ, ray.rdir.z, ray.org_rdir.z);
- const vfloat16 tNear = max(tNearFarX, tNearFarY, tNearFarZ, ray.tnear);
- const vfloat16 tFar = min(tNearFarX, tNearFarY, tNearFarZ, ray.tfar);
- const vbool16 vmask = le(vboolf16(m_valid),tNear,align_shift_right<8>(tFar, tFar));
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
-#endif
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Robust AABBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int Nx>
- __forceinline size_t intersectNodeRobust(const typename BVHN<N>::AABBNode* node, const TravRay<N,Nx,true>& ray, vfloat<Nx>& dist)
- {
- const vfloat<N> tNearX = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir_near.x;
- const vfloat<N> tNearY = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir_near.y;
- const vfloat<N> tNearZ = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir_near.z;
- const vfloat<N> tFarX = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir_far.x;
- const vfloat<N> tFarY = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir_far.y;
- const vfloat<N> tFarZ = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir_far.z;
- const vfloat<N> tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat<N> tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool<N> vmask = tNear <= tFar;
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
-#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
-
- template<>
- __forceinline size_t intersectNodeRobust<4,16>(const typename BVHN<4>::AABBNode* node, const TravRay<4,16,true>& ray, vfloat<16>& dist)
- {
- const vfloat16 tNearX = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir_near.x;
- const vfloat16 tNearY = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir_near.y;
- const vfloat16 tNearZ = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir_near.z;
- const vfloat16 tFarX = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir_far.x;
- const vfloat16 tFarY = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir_far.y;
- const vfloat16 tFarZ = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir_far.z;
- const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool16 vmask = le((1 << 4)-1,tNear,tFar);
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
- template<>
- __forceinline size_t intersectNodeRobust<8,16>(const typename BVHN<8>::AABBNode* node, const TravRay<8,16,true>& ray, vfloat<16>& dist)
- {
- const vfloat16 tNearX = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir_near.x;
- const vfloat16 tNearY = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir_near.y;
- const vfloat16 tNearZ = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir_near.z;
- const vfloat16 tFarX = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir_far.x;
- const vfloat16 tFarY = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir_far.y;
- const vfloat16 tFarZ = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir_far.z;
- const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool16 vmask = le((1 << 8)-1,tNear,tFar);
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
-#endif
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast AABBNodeMB intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N>
- __forceinline size_t intersectNode(const typename BVHN<N>::AABBNodeMB* node, const TravRay<N,N,false>& ray, const float time, vfloat<N>& dist)
- {
- const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
- const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
- const vfloat<N>* pNearZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearZ);
- const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
- const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
- const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
-#if defined(__FMA_X4__)
-#if defined(__aarch64__)
- const vfloat<N> tNearX = madd(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<N> tNearY = madd(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<N> tNearZ = madd(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<N> tFarX = madd(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<N> tFarY = madd(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<N> tFarZ = madd(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.neg_org_rdir.z);
-#else
- const vfloat<N> tNearX = msub(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.org_rdir.x);
- const vfloat<N> tNearY = msub(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.org_rdir.y);
- const vfloat<N> tNearZ = msub(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.org_rdir.z);
- const vfloat<N> tFarX = msub(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.org_rdir.x);
- const vfloat<N> tFarY = msub(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.org_rdir.y);
- const vfloat<N> tFarZ = msub(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.org_rdir.z);
-#endif
-#else
- const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir.x;
- const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir.y;
- const vfloat<N> tNearZ = (madd(time,pNearZ[6],vfloat<N>(pNearZ[0])) - ray.org.z) * ray.rdir.z;
- const vfloat<N> tFarX = (madd(time,pFarX [6],vfloat<N>(pFarX [0])) - ray.org.x) * ray.rdir.x;
- const vfloat<N> tFarY = (madd(time,pFarY [6],vfloat<N>(pFarY [0])) - ray.org.y) * ray.rdir.y;
- const vfloat<N> tFarZ = (madd(time,pFarZ [6],vfloat<N>(pFarZ [0])) - ray.org.z) * ray.rdir.z;
-#endif
-#if defined(__FMA_X4__) && !defined(__AVX512F__) // HSW
- const vfloat<N> tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat<N> tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool<N> vmask = asInt(tNear) > asInt(tFar);
- const size_t mask = movemask(vmask) ^ ((1<<N)-1);
-#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vfloat<N> tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat<N> tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool<N> vmask = asInt(tNear) <= asInt(tFar);
- const size_t mask = movemask(vmask);
-#else
- const vfloat<N> tNear = max(ray.tnear,tNearX,tNearY,tNearZ);
- const vfloat<N> tFar = min(ray.tfar, tFarX ,tFarY ,tFarZ );
- const vbool<N> vmask = tNear <= tFar;
- const size_t mask = movemask(vmask);
-#endif
- dist = tNear;
- return mask;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Robust AABBNodeMB intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N>
- __forceinline size_t intersectNodeRobust(const typename BVHN<N>::AABBNodeMB* node, const TravRay<N,N,true>& ray, const float time, vfloat<N>& dist)
- {
- const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
- const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
- const vfloat<N>* pNearZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearZ);
- const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir_near.x;
- const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir_near.y;
- const vfloat<N> tNearZ = (madd(time,pNearZ[6],vfloat<N>(pNearZ[0])) - ray.org.z) * ray.rdir_near.z;
- const vfloat<N> tNear = max(ray.tnear,tNearX,tNearY,tNearZ);
- const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
- const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
- const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
- const vfloat<N> tFarX = (madd(time,pFarX[6],vfloat<N>(pFarX[0])) - ray.org.x) * ray.rdir_far.x;
- const vfloat<N> tFarY = (madd(time,pFarY[6],vfloat<N>(pFarY[0])) - ray.org.y) * ray.rdir_far.y;
- const vfloat<N> tFarZ = (madd(time,pFarZ[6],vfloat<N>(pFarZ[0])) - ray.org.z) * ray.rdir_far.z;
- const vfloat<N> tFar = min(ray.tfar,tFarX,tFarY,tFarZ);
- const size_t mask = movemask(tNear <= tFar);
- dist = tNear;
- return mask;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast AABBNodeMB4D intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N>
- __forceinline size_t intersectNodeMB4D(const typename BVHN<N>::NodeRef ref, const TravRay<N,N,false>& ray, const float time, vfloat<N>& dist)
- {
- const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
-
- const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
- const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
- const vfloat<N>* pNearZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearZ);
- const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
- const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
- const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
-#if defined (__FMA_X4__)
-#if defined(__aarch64__)
- const vfloat<N> tNearX = madd(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<N> tNearY = madd(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<N> tNearZ = madd(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<N> tFarX = madd(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<N> tFarY = madd(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<N> tFarZ = madd(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.neg_org_rdir.z);
-#else
- const vfloat<N> tNearX = msub(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.org_rdir.x);
- const vfloat<N> tNearY = msub(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.org_rdir.y);
- const vfloat<N> tNearZ = msub(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.org_rdir.z);
- const vfloat<N> tFarX = msub(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.org_rdir.x);
- const vfloat<N> tFarY = msub(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.org_rdir.y);
- const vfloat<N> tFarZ = msub(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.org_rdir.z);
-#endif
-#else
- const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir.x;
- const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir.y;
- const vfloat<N> tNearZ = (madd(time,pNearZ[6],vfloat<N>(pNearZ[0])) - ray.org.z) * ray.rdir.z;
- const vfloat<N> tFarX = (madd(time,pFarX [6],vfloat<N>(pFarX [0])) - ray.org.x) * ray.rdir.x;
- const vfloat<N> tFarY = (madd(time,pFarY [6],vfloat<N>(pFarY [0])) - ray.org.y) * ray.rdir.y;
- const vfloat<N> tFarZ = (madd(time,pFarZ [6],vfloat<N>(pFarZ [0])) - ray.org.z) * ray.rdir.z;
-#endif
-#if defined(__FMA_X4__) && !defined(__AVX512F__)
- const vfloat<N> tNear = maxi(maxi(tNearX,tNearY),maxi(tNearZ,ray.tnear));
- const vfloat<N> tFar = mini(mini(tFarX ,tFarY ),mini(tFarZ ,ray.tfar ));
-#else
- const vfloat<N> tNear = max(ray.tnear,tNearX,tNearY,tNearZ);
- const vfloat<N> tFar = min(ray.tfar, tFarX ,tFarY ,tFarZ );
-#endif
- vbool<N> vmask = tNear <= tFar;
- if (unlikely(ref.isAABBNodeMB4D())) {
- const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
- vmask &= (node1->lower_t <= time) & (time < node1->upper_t);
- }
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Robust AABBNodeMB4D intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N>
- __forceinline size_t intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const TravRay<N,N,true>& ray, const float time, vfloat<N>& dist)
- {
- const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
-
- const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
- const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
- const vfloat<N>* pNearZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearZ);
- const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir_near.x;
- const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir_near.y;
- const vfloat<N> tNearZ = (madd(time,pNearZ[6],vfloat<N>(pNearZ[0])) - ray.org.z) * ray.rdir_near.z;
- const vfloat<N> tNear = max(ray.tnear,tNearX,tNearY,tNearZ);
- const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
- const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
- const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
- const vfloat<N> tFarX = (madd(time,pFarX[6],vfloat<N>(pFarX[0])) - ray.org.x) * ray.rdir_far.x;
- const vfloat<N> tFarY = (madd(time,pFarY[6],vfloat<N>(pFarY[0])) - ray.org.y) * ray.rdir_far.y;
- const vfloat<N> tFarZ = (madd(time,pFarZ[6],vfloat<N>(pFarZ[0])) - ray.org.z) * ray.rdir_far.z;
- const vfloat<N> tFar = min(ray.tfar,tFarX,tFarY,tFarZ);
- vbool<N> vmask = tNear <= tFar;
- if (unlikely(ref.isAABBNodeMB4D())) {
- const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
- vmask &= (node1->lower_t <= time) & (time < node1->upper_t);
- }
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast QuantizedBaseNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int Nx, bool robust>
- __forceinline size_t intersectNode(const typename BVHN<N>::QuantizedBaseNode* node, const TravRay<N,Nx,robust>& ray, vfloat<Nx>& dist);
-
- template<>
- __forceinline size_t intersectNode<4,4>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,4,false>& ray, vfloat4& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat4 start_x(node->start.x);
- const vfloat4 scale_x(node->scale.x);
- const vfloat4 lower_x = madd(node->dequantize<4>(ray.nearX >> 2),scale_x,start_x);
- const vfloat4 upper_x = madd(node->dequantize<4>(ray.farX >> 2),scale_x,start_x);
- const vfloat4 start_y(node->start.y);
- const vfloat4 scale_y(node->scale.y);
- const vfloat4 lower_y = madd(node->dequantize<4>(ray.nearY >> 2),scale_y,start_y);
- const vfloat4 upper_y = madd(node->dequantize<4>(ray.farY >> 2),scale_y,start_y);
- const vfloat4 start_z(node->start.z);
- const vfloat4 scale_z(node->scale.z);
- const vfloat4 lower_z = madd(node->dequantize<4>(ray.nearZ >> 2),scale_z,start_z);
- const vfloat4 upper_z = madd(node->dequantize<4>(ray.farZ >> 2),scale_z,start_z);
-
-#if defined(__FMA_X4__)
-#if defined(__aarch64__)
- const vfloat4 tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat4 tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat4 tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat4 tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat4 tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat4 tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);
-#else
- const vfloat4 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat4 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat4 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat4 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat4 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat4 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
-#endif
-#else
- const vfloat4 tNearX = (lower_x - ray.org.x) * ray.rdir.x;
- const vfloat4 tNearY = (lower_y - ray.org.y) * ray.rdir.y;
- const vfloat4 tNearZ = (lower_z - ray.org.z) * ray.rdir.z;
- const vfloat4 tFarX = (upper_x - ray.org.x) * ray.rdir.x;
- const vfloat4 tFarY = (upper_y - ray.org.y) * ray.rdir.y;
- const vfloat4 tFarZ = (upper_z - ray.org.z) * ray.rdir.z;
-#endif
-
-#if (defined(__aarch64__) && defined(BUILD_IOS)) || defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW
- const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool4 vmask = asInt(tNear) > asInt(tFar);
- const size_t mask = movemask(vmask) ^ ((1<<4)-1);
-#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool4 vmask = asInt(tNear) <= asInt(tFar);
- const size_t mask = movemask(vmask);
-#else
- const vfloat4 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat4 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool4 vmask = tNear <= tFar;
- const size_t mask = movemask(vmask);
-#endif
- dist = tNear;
- return mask & mvalid;
- }
-
- template<>
- __forceinline size_t intersectNode<4,4>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,4,true>& ray, vfloat4& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat4 start_x(node->start.x);
- const vfloat4 scale_x(node->scale.x);
- const vfloat4 lower_x = madd(node->dequantize<4>(ray.nearX >> 2),scale_x,start_x);
- const vfloat4 upper_x = madd(node->dequantize<4>(ray.farX >> 2),scale_x,start_x);
- const vfloat4 start_y(node->start.y);
- const vfloat4 scale_y(node->scale.y);
- const vfloat4 lower_y = madd(node->dequantize<4>(ray.nearY >> 2),scale_y,start_y);
- const vfloat4 upper_y = madd(node->dequantize<4>(ray.farY >> 2),scale_y,start_y);
- const vfloat4 start_z(node->start.z);
- const vfloat4 scale_z(node->scale.z);
- const vfloat4 lower_z = madd(node->dequantize<4>(ray.nearZ >> 2),scale_z,start_z);
- const vfloat4 upper_z = madd(node->dequantize<4>(ray.farZ >> 2),scale_z,start_z);
-
- const vfloat4 tNearX = (lower_x - ray.org.x) * ray.rdir_near.x;
- const vfloat4 tNearY = (lower_y - ray.org.y) * ray.rdir_near.y;
- const vfloat4 tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z;
- const vfloat4 tFarX = (upper_x - ray.org.x) * ray.rdir_far.x;
- const vfloat4 tFarY = (upper_y - ray.org.y) * ray.rdir_far.y;
- const vfloat4 tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z;
-
- const vfloat4 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat4 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool4 vmask = tNear <= tFar;
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask & mvalid;
- }
-
-
-#if defined(__AVX__)
-
- template<>
- __forceinline size_t intersectNode<8,8>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,8,false>& ray, vfloat8& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat8 start_x(node->start.x);
- const vfloat8 scale_x(node->scale.x);
- const vfloat8 lower_x = madd(node->dequantize<8>(ray.nearX >> 2),scale_x,start_x);
- const vfloat8 upper_x = madd(node->dequantize<8>(ray.farX >> 2),scale_x,start_x);
- const vfloat8 start_y(node->start.y);
- const vfloat8 scale_y(node->scale.y);
- const vfloat8 lower_y = madd(node->dequantize<8>(ray.nearY >> 2),scale_y,start_y);
- const vfloat8 upper_y = madd(node->dequantize<8>(ray.farY >> 2),scale_y,start_y);
- const vfloat8 start_z(node->start.z);
- const vfloat8 scale_z(node->scale.z);
- const vfloat8 lower_z = madd(node->dequantize<8>(ray.nearZ >> 2),scale_z,start_z);
- const vfloat8 upper_z = madd(node->dequantize<8>(ray.farZ >> 2),scale_z,start_z);
-
-#if defined(__AVX2__)
-#if defined(__aarch64__)
- const vfloat8 tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat8 tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat8 tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat8 tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat8 tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat8 tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);
-#else
- const vfloat8 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat8 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat8 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat8 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat8 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat8 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
-#endif
-#else
- const vfloat8 tNearX = (lower_x - ray.org.x) * ray.rdir.x;
- const vfloat8 tNearY = (lower_y - ray.org.y) * ray.rdir.y;
- const vfloat8 tNearZ = (lower_z - ray.org.z) * ray.rdir.z;
- const vfloat8 tFarX = (upper_x - ray.org.x) * ray.rdir.x;
- const vfloat8 tFarY = (upper_y - ray.org.y) * ray.rdir.y;
- const vfloat8 tFarZ = (upper_z - ray.org.z) * ray.rdir.z;
-#endif
-
-#if defined(__AVX2__) && !defined(__AVX512F__) // HSW
- const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool8 vmask = asInt(tNear) > asInt(tFar);
- const size_t mask = movemask(vmask) ^ ((1<<8)-1);
-#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool8 vmask = asInt(tNear) <= asInt(tFar);
- const size_t mask = movemask(vmask);
-#else
- const vfloat8 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat8 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool8 vmask = tNear <= tFar;
- const size_t mask = movemask(vmask);
-#endif
- dist = tNear;
- return mask & mvalid;
- }
-
- template<>
- __forceinline size_t intersectNode<8,8>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,8,true>& ray, vfloat8& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat8 start_x(node->start.x);
- const vfloat8 scale_x(node->scale.x);
- const vfloat8 lower_x = madd(node->dequantize<8>(ray.nearX >> 2),scale_x,start_x);
- const vfloat8 upper_x = madd(node->dequantize<8>(ray.farX >> 2),scale_x,start_x);
- const vfloat8 start_y(node->start.y);
- const vfloat8 scale_y(node->scale.y);
- const vfloat8 lower_y = madd(node->dequantize<8>(ray.nearY >> 2),scale_y,start_y);
- const vfloat8 upper_y = madd(node->dequantize<8>(ray.farY >> 2),scale_y,start_y);
- const vfloat8 start_z(node->start.z);
- const vfloat8 scale_z(node->scale.z);
- const vfloat8 lower_z = madd(node->dequantize<8>(ray.nearZ >> 2),scale_z,start_z);
- const vfloat8 upper_z = madd(node->dequantize<8>(ray.farZ >> 2),scale_z,start_z);
-
- const vfloat8 tNearX = (lower_x - ray.org.x) * ray.rdir_near.x;
- const vfloat8 tNearY = (lower_y - ray.org.y) * ray.rdir_near.y;
- const vfloat8 tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z;
- const vfloat8 tFarX = (upper_x - ray.org.x) * ray.rdir_far.x;
- const vfloat8 tFarY = (upper_y - ray.org.y) * ray.rdir_far.y;
- const vfloat8 tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z;
-
- const vfloat8 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat8 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool8 vmask = tNear <= tFar;
- const size_t mask = movemask(vmask);
-
- dist = tNear;
- return mask & mvalid;
- }
-
-
-#endif
-
-#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
-
- template<>
- __forceinline size_t intersectNode<4,16>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,16,false>& ray, vfloat16& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat16 start_x(node->start.x);
- const vfloat16 scale_x(node->scale.x);
- const vfloat16 lower_x = madd(vfloat16(node->dequantize<4>(ray.nearX >> 2)),scale_x,start_x);
- const vfloat16 upper_x = madd(vfloat16(node->dequantize<4>(ray.farX >> 2)),scale_x,start_x);
- const vfloat16 start_y(node->start.y);
- const vfloat16 scale_y(node->scale.y);
- const vfloat16 lower_y = madd(vfloat16(node->dequantize<4>(ray.nearY >> 2)),scale_y,start_y);
- const vfloat16 upper_y = madd(vfloat16(node->dequantize<4>(ray.farY >> 2)),scale_y,start_y);
- const vfloat16 start_z(node->start.z);
- const vfloat16 scale_z(node->scale.z);
- const vfloat16 lower_z = madd(vfloat16(node->dequantize<4>(ray.nearZ >> 2)),scale_z,start_z);
- const vfloat16 upper_z = madd(vfloat16(node->dequantize<4>(ray.farZ >> 2)),scale_z,start_z);
-
- const vfloat16 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat16 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat16 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat16 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat16 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat16 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool16 vmask = le(vbool16(0xf),tNear,tFar);
- const size_t mask = movemask(vmask) & mvalid;
- dist = tNear;
- return mask;
- }
-
- template<>
- __forceinline size_t intersectNode<4,16>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,16,true>& ray, vfloat16& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat16 start_x(node->start.x);
- const vfloat16 scale_x(node->scale.x);
- const vfloat16 lower_x = madd(vfloat16(node->dequantize<4>(ray.nearX >> 2)),scale_x,start_x);
- const vfloat16 upper_x = madd(vfloat16(node->dequantize<4>(ray.farX >> 2)),scale_x,start_x);
- const vfloat16 start_y(node->start.y);
- const vfloat16 scale_y(node->scale.y);
- const vfloat16 lower_y = madd(vfloat16(node->dequantize<4>(ray.nearY >> 2)),scale_y,start_y);
- const vfloat16 upper_y = madd(vfloat16(node->dequantize<4>(ray.farY >> 2)),scale_y,start_y);
- const vfloat16 start_z(node->start.z);
- const vfloat16 scale_z(node->scale.z);
- const vfloat16 lower_z = madd(vfloat16(node->dequantize<4>(ray.nearZ >> 2)),scale_z,start_z);
- const vfloat16 upper_z = madd(vfloat16(node->dequantize<4>(ray.farZ >> 2)),scale_z,start_z);
-
- const vfloat16 tNearX = (lower_x - ray.org.x) * ray.rdir_near.x;
- const vfloat16 tNearY = (lower_y - ray.org.y) * ray.rdir_near.y;
- const vfloat16 tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z;
- const vfloat16 tFarX = (upper_x - ray.org.x) * ray.rdir_far.x;
- const vfloat16 tFarY = (upper_y - ray.org.y) * ray.rdir_far.y;
- const vfloat16 tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z;
-
- const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
- const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
- const vbool16 vmask = le(vbool16(0xf),tNear,tFar);
- const size_t mask = movemask(vmask) & mvalid;
- dist = tNear;
- return mask;
- }
-
- template<>
- __forceinline size_t intersectNode<8,16>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,16,false>& ray, vfloat16& dist)
- {
- const vbool16 m_valid(node->validMask16());
- const vfloat16 bminmaxX = node->dequantizeLowerUpperX(ray.permX);
- const vfloat16 bminmaxY = node->dequantizeLowerUpperY(ray.permY);
- const vfloat16 bminmaxZ = node->dequantizeLowerUpperZ(ray.permZ);
- const vfloat16 tNearFarX = msub(bminmaxX, ray.rdir.x, ray.org_rdir.x);
- const vfloat16 tNearFarY = msub(bminmaxY, ray.rdir.y, ray.org_rdir.y);
- const vfloat16 tNearFarZ = msub(bminmaxZ, ray.rdir.z, ray.org_rdir.z);
- const vfloat16 tNear = max(tNearFarX, tNearFarY, tNearFarZ, ray.tnear);
- const vfloat16 tFar = min(tNearFarX, tNearFarY, tNearFarZ, ray.tfar);
- const vbool16 vmask = le(m_valid,tNear,align_shift_right<8>(tFar, tFar));
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
- template<>
- __forceinline size_t intersectNode<8,16>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,16,true>& ray, vfloat16& dist)
- {
- const vbool16 m_valid(node->validMask16());
- const vfloat16 bminmaxX = node->dequantizeLowerUpperX(ray.permX);
- const vfloat16 bminmaxY = node->dequantizeLowerUpperY(ray.permY);
- const vfloat16 bminmaxZ = node->dequantizeLowerUpperZ(ray.permZ);
- const vfloat16 tNearFarX = (bminmaxX - ray.org.x) * ray.rdir_far.x; // FIXME: this is not conservative !!!!!!!!!
- const vfloat16 tNearFarY = (bminmaxY - ray.org.y) * ray.rdir_far.y;
- const vfloat16 tNearFarZ = (bminmaxZ - ray.org.z) * ray.rdir_far.z;
- const vfloat16 tNear = max(tNearFarX, tNearFarY, tNearFarZ, ray.tnear);
- const vfloat16 tFar = min(tNearFarX, tNearFarY, tNearFarZ, ray.tfar);
- const vbool16 vmask = le(m_valid,tNear,align_shift_right<8>(tFar, tFar));
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
-
-#endif
-
-
- template<int N, int Nx>
- __forceinline size_t intersectNode(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravRay<N,Nx,false>& ray, const float time, vfloat<N>& dist)
- {
- const vboolf<N> mvalid = node->validMask();
- const vfloat<N> lower_x = node->dequantizeLowerX(time);
- const vfloat<N> upper_x = node->dequantizeUpperX(time);
- const vfloat<N> lower_y = node->dequantizeLowerY(time);
- const vfloat<N> upper_y = node->dequantizeUpperY(time);
- const vfloat<N> lower_z = node->dequantizeLowerZ(time);
- const vfloat<N> upper_z = node->dequantizeUpperZ(time);
-#if defined(__FMA_X4__)
-#if defined(__aarch64__)
- const vfloat<N> tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<N> tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<N> tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<N> tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<N> tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<N> tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);
-#else
- const vfloat<N> tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat<N> tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat<N> tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat<N> tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat<N> tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat<N> tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
-#endif
-#else
- const vfloat<N> tNearX = (lower_x - ray.org.x) * ray.rdir.x;
- const vfloat<N> tNearY = (lower_y - ray.org.y) * ray.rdir.y;
- const vfloat<N> tNearZ = (lower_z - ray.org.z) * ray.rdir.z;
- const vfloat<N> tFarX = (upper_x - ray.org.x) * ray.rdir.x;
- const vfloat<N> tFarY = (upper_y - ray.org.y) * ray.rdir.y;
- const vfloat<N> tFarZ = (upper_z - ray.org.z) * ray.rdir.z;
-#endif
-
- const vfloat<N> tminX = mini(tNearX,tFarX);
- const vfloat<N> tmaxX = maxi(tNearX,tFarX);
- const vfloat<N> tminY = mini(tNearY,tFarY);
- const vfloat<N> tmaxY = maxi(tNearY,tFarY);
- const vfloat<N> tminZ = mini(tNearZ,tFarZ);
- const vfloat<N> tmaxZ = maxi(tNearZ,tFarZ);
- const vfloat<N> tNear = maxi(tminX,tminY,tminZ,ray.tnear);
- const vfloat<N> tFar = mini(tmaxX,tmaxY,tmaxZ,ray.tfar);
-#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vbool<N> vmask = le(mvalid,asInt(tNear),asInt(tFar));
-#else
- const vbool<N> vmask = (asInt(tNear) <= asInt(tFar)) & mvalid;
-#endif
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
- template<int N, int Nx>
- __forceinline size_t intersectNode(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravRay<N,Nx,true>& ray, const float time, vfloat<N>& dist)
- {
- const vboolf<N> mvalid = node->validMask();
- const vfloat<N> lower_x = node->dequantizeLowerX(time);
- const vfloat<N> upper_x = node->dequantizeUpperX(time);
- const vfloat<N> lower_y = node->dequantizeLowerY(time);
- const vfloat<N> upper_y = node->dequantizeUpperY(time);
- const vfloat<N> lower_z = node->dequantizeLowerZ(time);
- const vfloat<N> upper_z = node->dequantizeUpperZ(time);
- const vfloat<N> tNearX = (lower_x - ray.org.x) * ray.rdir_near.x;
- const vfloat<N> tNearY = (lower_y - ray.org.y) * ray.rdir_near.y;
- const vfloat<N> tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z;
- const vfloat<N> tFarX = (upper_x - ray.org.x) * ray.rdir_far.x;
- const vfloat<N> tFarY = (upper_y - ray.org.y) * ray.rdir_far.y;
- const vfloat<N> tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z;
-
- const vfloat<N> tminX = mini(tNearX,tFarX);
- const vfloat<N> tmaxX = maxi(tNearX,tFarX);
- const vfloat<N> tminY = mini(tNearY,tFarY);
- const vfloat<N> tmaxY = maxi(tNearY,tFarY);
- const vfloat<N> tminZ = mini(tNearZ,tFarZ);
- const vfloat<N> tmaxZ = maxi(tNearZ,tFarZ);
- const vfloat<N> tNear = maxi(tminX,tminY,tminZ,ray.tnear);
- const vfloat<N> tFar = mini(tmaxX,tmaxY,tmaxZ,ray.tfar);
-#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vbool<N> vmask = le(mvalid,asInt(tNear),asInt(tFar));
-#else
- const vbool<N> vmask = (asInt(tNear) <= asInt(tFar)) & mvalid;
-#endif
- const size_t mask = movemask(vmask);
- dist = tNear;
- return mask;
- }
-
-
-#if defined(__AVX512ER__)
- // for KNL
- template<>
- __forceinline size_t intersectNode<4,16>(const typename BVHN<4>::QuantizedBaseNodeMB* node, const TravRay<4,16,false>& ray, const float time, vfloat<4>& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat16 lower_x = node->dequantizeLowerX(time);
- const vfloat16 upper_x = node->dequantizeUpperX(time);
- const vfloat16 lower_y = node->dequantizeLowerY(time);
- const vfloat16 upper_y = node->dequantizeUpperY(time);
- const vfloat16 lower_z = node->dequantizeLowerZ(time);
- const vfloat16 upper_z = node->dequantizeUpperZ(time);
-
- const vfloat16 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat16 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat16 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat16 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat16 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat16 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
-
- const vfloat16 tminX = min(tNearX,tFarX);
- const vfloat16 tmaxX = max(tNearX,tFarX);
- const vfloat16 tminY = min(tNearY,tFarY);
- const vfloat16 tmaxY = max(tNearY,tFarY);
- const vfloat16 tminZ = min(tNearZ,tFarZ);
- const vfloat16 tmaxZ = max(tNearZ,tFarZ);
- const vfloat16 tNear = max(tminX,tminY,tminZ,ray.tnear);
- const vfloat16 tFar = min(tmaxX,tmaxY,tmaxZ,ray.tfar );
- const vbool16 vmask = tNear <= tFar;
- const size_t mask = movemask(vmask) & mvalid;
- dist = extractN<4,0>(tNear);
- return mask;
- }
-
-
- // for KNL
- template<>
- __forceinline size_t intersectNode<4,16>(const typename BVHN<4>::QuantizedBaseNodeMB* node, const TravRay<4,16,true>& ray, const float time, vfloat<4>& dist)
- {
- const size_t mvalid = movemask(node->validMask());
- const vfloat16 lower_x = node->dequantizeLowerX(time);
- const vfloat16 upper_x = node->dequantizeUpperX(time);
- const vfloat16 lower_y = node->dequantizeLowerY(time);
- const vfloat16 upper_y = node->dequantizeUpperY(time);
- const vfloat16 lower_z = node->dequantizeLowerZ(time);
- const vfloat16 upper_z = node->dequantizeUpperZ(time);
-
- const vfloat16 tNearX = (lower_x - ray.org.x) * ray.rdir_near.x;
- const vfloat16 tNearY = (lower_y - ray.org.y) * ray.rdir_near.y;
- const vfloat16 tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z;
- const vfloat16 tFarX = (upper_x - ray.org.x) * ray.rdir_far.x;
- const vfloat16 tFarY = (upper_y - ray.org.y) * ray.rdir_far.y;
- const vfloat16 tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z;
-
- const vfloat16 tminX = min(tNearX,tFarX);
- const vfloat16 tmaxX = max(tNearX,tFarX);
- const vfloat16 tminY = min(tNearY,tFarY);
- const vfloat16 tmaxY = max(tNearY,tFarY);
- const vfloat16 tminZ = min(tNearZ,tFarZ);
- const vfloat16 tmaxZ = max(tNearZ,tFarZ);
- const vfloat16 tNear = max(tminX,tminY,tminZ,ray.tnear);
- const vfloat16 tFar = min(tmaxX,tmaxY,tmaxZ,ray.tfar );
- const vbool16 vmask = tNear <= tFar;
- const size_t mask = movemask(vmask) & mvalid;
- dist = extractN<4,0>(tNear);
- return mask;
- }
-
-#endif
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast OBBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, bool robust>
- __forceinline size_t intersectNode(const typename BVHN<N>::OBBNode* node, const TravRay<N,N,robust>& ray, vfloat<N>& dist)
- {
- const Vec3vf<N> dir = xfmVector(node->naabb,ray.dir);
- //const Vec3vf<N> nrdir = Vec3vf<N>(vfloat<N>(-1.0f))/dir;
- const Vec3vf<N> nrdir = Vec3vf<N>(vfloat<N>(-1.0f))*rcp_safe(dir);
- const Vec3vf<N> org = xfmPoint(node->naabb,ray.org);
- const Vec3vf<N> tLowerXYZ = org * nrdir; // (Vec3fa(zero) - org) * rdir;
- const Vec3vf<N> tUpperXYZ = tLowerXYZ - nrdir; // (Vec3fa(one ) - org) * rdir;
-
- const vfloat<N> tNearX = mini(tLowerXYZ.x,tUpperXYZ.x);
- const vfloat<N> tNearY = mini(tLowerXYZ.y,tUpperXYZ.y);
- const vfloat<N> tNearZ = mini(tLowerXYZ.z,tUpperXYZ.z);
- const vfloat<N> tFarX = maxi(tLowerXYZ.x,tUpperXYZ.x);
- const vfloat<N> tFarY = maxi(tLowerXYZ.y,tUpperXYZ.y);
- const vfloat<N> tFarZ = maxi(tLowerXYZ.z,tUpperXYZ.z);
- vfloat<N> tNear = max(ray.tnear, tNearX,tNearY,tNearZ);
- vfloat<N> tFar = min(ray.tfar, tFarX ,tFarY ,tFarZ );
- if (robust) {
- tNear = tNear*vfloat<N>(1.0f-3.0f*float(ulp));
- tFar = tFar *vfloat<N>(1.0f+3.0f*float(ulp));
- }
- const vbool<N> vmask = tNear <= tFar;
- dist = tNear;
- return movemask(vmask);
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast OBBNodeMB intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, bool robust>
- __forceinline size_t intersectNode(const typename BVHN<N>::OBBNodeMB* node, const TravRay<N,N,robust>& ray, const float time, vfloat<N>& dist)
- {
- const AffineSpace3vf<N> xfm = node->space0;
- const Vec3vf<N> b0_lower = zero;
- const Vec3vf<N> b0_upper = one;
- const Vec3vf<N> lower = lerp(b0_lower,node->b1.lower,vfloat<N>(time));
- const Vec3vf<N> upper = lerp(b0_upper,node->b1.upper,vfloat<N>(time));
-
- const BBox3vf<N> bounds(lower,upper);
- const Vec3vf<N> dir = xfmVector(xfm,ray.dir);
- const Vec3vf<N> rdir = rcp_safe(dir);
- const Vec3vf<N> org = xfmPoint(xfm,ray.org);
-
- const Vec3vf<N> tLowerXYZ = (bounds.lower - org) * rdir;
- const Vec3vf<N> tUpperXYZ = (bounds.upper - org) * rdir;
-
- const vfloat<N> tNearX = mini(tLowerXYZ.x,tUpperXYZ.x);
- const vfloat<N> tNearY = mini(tLowerXYZ.y,tUpperXYZ.y);
- const vfloat<N> tNearZ = mini(tLowerXYZ.z,tUpperXYZ.z);
- const vfloat<N> tFarX = maxi(tLowerXYZ.x,tUpperXYZ.x);
- const vfloat<N> tFarY = maxi(tLowerXYZ.y,tUpperXYZ.y);
- const vfloat<N> tFarZ = maxi(tLowerXYZ.z,tUpperXYZ.z);
- vfloat<N> tNear = max(ray.tnear, tNearX,tNearY,tNearZ);
- vfloat<N> tFar = min(ray.tfar, tFarX ,tFarY ,tFarZ );
- if (robust) {
- tNear = tNear*vfloat<N>(1.0f-3.0f*float(ulp));
- tFar = tFar *vfloat<N>(1.0f+3.0f*float(ulp));
- }
- const vbool<N> vmask = tNear <= tFar;
- dist = tNear;
- return movemask(vmask);
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Node intersectors used in point query raversal
- //////////////////////////////////////////////////////////////////////////////////////
-
- /*! Computes traversal information for N nodes with 1 point query */
- template<int N, int types>
- struct BVHNNodePointQuerySphere1;
-
- template<int N>
- struct BVHNNodePointQuerySphere1<N, BVH_AN1>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = pointQueryNodeSphere(node.getAABBNode(), query, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQuerySphere1<N, BVH_AN2>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = pointQueryNodeSphere(node.getAABBNodeMB(), query, time, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQuerySphere1<N, BVH_AN2_AN4D>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = pointQueryNodeSphereMB4D<N>(node, query, time, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQuerySphere1<N, BVH_AN1_UN1>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (likely(node.isAABBNode())) mask = pointQueryNodeSphere(node.getAABBNode(), query, dist);
- else if (unlikely(node.isOBBNode())) mask = pointQueryNodeSphere(node.ungetAABBNode(), query, dist);
- else return false;
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQuerySphere1<N, BVH_AN2_UN2>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (likely(node.isAABBNodeMB())) mask = pointQueryNodeSphere(node.getAABBNodeMB(), query, time, dist);
- else if (unlikely(node.isOBBNodeMB())) mask = pointQueryNodeSphere(node.ungetAABBNodeMB(), query, time, dist);
- else return false;
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQuerySphere1<N, BVH_AN2_AN4D_UN2>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- if (unlikely(node.isOBBNodeMB())) mask = pointQueryNodeSphere(node.ungetAABBNodeMB(), query, time, dist);
- else mask = pointQueryNodeSphereMB4D(node, query, time, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQuerySphere1<N, BVH_QN1>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = pointQueryNodeSphere((const typename BVHN<N>::QuantizedNode*)node.quantizedNode(), query, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNQuantizedBaseNodePointQuerySphere1
- {
- static __forceinline size_t pointQuery(const typename BVHN<N>::QuantizedBaseNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
- {
- return pointQueryNodeSphere(node,query,dist);
- }
-
- static __forceinline size_t pointQuery(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- return pointQueryNodeSphere(node,query,time,dist);
- }
- };
-
- /*! Computes traversal information for N nodes with 1 point query */
- template<int N, int types>
- struct BVHNNodePointQueryAABB1;
-
- template<int N>
- struct BVHNNodePointQueryAABB1<N, BVH_AN1>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = pointQueryNodeAABB(node.getAABBNode(), query, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQueryAABB1<N, BVH_AN2>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = pointQueryNodeAABB(node.getAABBNodeMB(), query, time, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQueryAABB1<N, BVH_AN2_AN4D>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = pointQueryNodeAABBMB4D<N>(node, query, time, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQueryAABB1<N, BVH_AN1_UN1>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (likely(node.isAABBNode())) mask = pointQueryNodeAABB(node.getAABBNode(), query, dist);
- else if (unlikely(node.isOBBNode())) mask = pointQueryNodeAABB(node.ungetAABBNode(), query, dist);
- else return false;
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQueryAABB1<N, BVH_AN2_UN2>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (likely(node.isAABBNodeMB())) mask = pointQueryNodeAABB(node.getAABBNodeMB(), query, time, dist);
- else if (unlikely(node.isOBBNodeMB())) mask = pointQueryNodeAABB(node.ungetAABBNodeMB(), query, time, dist);
- else return false;
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQueryAABB1<N, BVH_AN2_AN4D_UN2>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- if (unlikely(node.isOBBNodeMB())) mask = pointQueryNodeAABB(node.ungetAABBNodeMB(), query, time, dist);
- else mask = pointQueryNodeAABBMB4D(node, query, time, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNNodePointQueryAABB1<N, BVH_QN1>
- {
- static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = pointQueryNodeAABB((const typename BVHN<N>::QuantizedNode*)node.quantizedNode(), query, dist);
- return true;
- }
- };
-
- template<int N>
- struct BVHNQuantizedBaseNodePointQueryAABB1
- {
- static __forceinline size_t pointQuery(const typename BVHN<N>::QuantizedBaseNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
- {
- return pointQueryNodeAABB(node,query,dist);
- }
-
- static __forceinline size_t pointQuery(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
- {
- return pointQueryNodeAABB(node,query,time,dist);
- }
- };
-
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Node intersectors used in ray traversal
- //////////////////////////////////////////////////////////////////////////////////////
-
- /*! Intersects N nodes with 1 ray */
- template<int N, int Nx, int types, bool robust>
- struct BVHNNodeIntersector1;
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN1, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,false>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = intersectNode(node.getAABBNode(), ray, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN1, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,true>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = intersectNodeRobust(node.getAABBNode(), ray, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN2, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,false>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = intersectNode(node.getAABBNodeMB(), ray, time, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN2, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,true>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = intersectNodeRobust(node.getAABBNodeMB(), ray, time, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN2_AN4D, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,false>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = intersectNodeMB4D<N>(node, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN2_AN4D, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,true>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = intersectNodeMB4DRobust<N>(node, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN1_UN1, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,false>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (likely(node.isAABBNode())) mask = intersectNode(node.getAABBNode(), ray, dist);
- else if (unlikely(node.isOBBNode())) mask = intersectNode(node.ungetAABBNode(), ray, dist);
- else return false;
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN1_UN1, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,true>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (likely(node.isAABBNode())) mask = intersectNodeRobust(node.getAABBNode(), ray, dist);
- else if (unlikely(node.isOBBNode())) mask = intersectNode(node.ungetAABBNode(), ray, dist);
- else return false;
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN2_UN2, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,false>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (likely(node.isAABBNodeMB())) mask = intersectNode(node.getAABBNodeMB(), ray, time, dist);
- else if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist);
- else return false;
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN2_UN2, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,true>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (likely(node.isAABBNodeMB())) mask = intersectNodeRobust(node.getAABBNodeMB(), ray, time, dist);
- else if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist);
- else return false;
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN2_AN4D_UN2, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,false>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist);
- else mask = intersectNodeMB4D(node, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_AN2_AN4D_UN2, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,true>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist);
- else mask = intersectNodeMB4DRobust(node, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_QN1, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,false>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = intersectNode((const typename BVHN<N>::QuantizedNode*)node.quantizedNode(), ray, dist);
- return true;
- }
- };
-
- template<int N, int Nx>
- struct BVHNNodeIntersector1<N, Nx, BVH_QN1, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx,true>& ray, float time, vfloat<Nx>& dist, size_t& mask)
- {
- if (unlikely(node.isLeaf())) return false;
- mask = intersectNodeRobust((const typename BVHN<N>::QuantizedNode*)node.quantizedNode(), ray, dist);
- return true;
- }
- };
-
- /*! Intersects N nodes with K rays */
- template<int N, int Nx, bool robust>
- struct BVHNQuantizedBaseNodeIntersector1;
-
- template<int N, int Nx>
- struct BVHNQuantizedBaseNodeIntersector1<N, Nx, false>
- {
- static __forceinline size_t intersect(const typename BVHN<N>::QuantizedBaseNode* node, const TravRay<N,Nx,false>& ray, vfloat<Nx>& dist)
- {
- return intersectNode(node,ray,dist);
- }
-
- static __forceinline size_t intersect(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravRay<N,Nx,false>& ray, const float time, vfloat<N>& dist)
- {
- return intersectNode(node,ray,time,dist);
- }
-
- };
-
- template<int N, int Nx>
- struct BVHNQuantizedBaseNodeIntersector1<N, Nx, true>
- {
- static __forceinline size_t intersect(const typename BVHN<N>::QuantizedBaseNode* node, const TravRay<N,Nx,true>& ray, vfloat<Nx>& dist)
- {
- return intersectNode(node,ray,dist);
- }
-
- static __forceinline size_t intersect(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravRay<N,Nx,true>& ray, const float time, vfloat<N>& dist)
- {
- return intersectNode(node,ray,time,dist);
- }
-
- };
-
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/node_intersector_frustum.h b/thirdparty/embree-aarch64/kernels/bvh/node_intersector_frustum.h
deleted file mode 100644
index 800ac8b478..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/node_intersector_frustum.h
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "node_intersector.h"
-
-namespace embree
-{
- namespace isa
- {
- //////////////////////////////////////////////////////////////////////////////////////
- // Frustum structure used in hybrid and stream traversal
- //////////////////////////////////////////////////////////////////////////////////////
-
- /*
- Optimized frustum test. We calculate t=(p-org)/dir in ray/box
- intersection. We assume the rays are split by octant, thus
- dir intervals are either positive or negative in each
- dimension.
-
- Case 1: dir.min >= 0 && dir.max >= 0:
- t_min = (p_min - org_max) / dir_max = (p_min - org_max)*rdir_min = p_min*rdir_min - org_max*rdir_min
- t_max = (p_max - org_min) / dir_min = (p_max - org_min)*rdir_max = p_max*rdir_max - org_min*rdir_max
-
- Case 2: dir.min < 0 && dir.max < 0:
- t_min = (p_max - org_min) / dir_min = (p_max - org_min)*rdir_max = p_max*rdir_max - org_min*rdir_max
- t_max = (p_min - org_max) / dir_max = (p_min - org_max)*rdir_min = p_min*rdir_min - org_max*rdir_min
- */
-
- template<bool robust>
- struct Frustum;
-
- /* Fast variant */
- template<>
- struct Frustum<false>
- {
- __forceinline Frustum() {}
-
- template<int K>
- __forceinline Frustum(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
- {
- init(valid, org, rdir, ray_tnear, ray_tfar, N);
- }
-
- template<int K>
- __forceinline void init(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
- {
- const Vec3fa reduced_min_org(reduce_min(select(valid, org.x, pos_inf)),
- reduce_min(select(valid, org.y, pos_inf)),
- reduce_min(select(valid, org.z, pos_inf)));
-
- const Vec3fa reduced_max_org(reduce_max(select(valid, org.x, neg_inf)),
- reduce_max(select(valid, org.y, neg_inf)),
- reduce_max(select(valid, org.z, neg_inf)));
-
- const Vec3fa reduced_min_rdir(reduce_min(select(valid, rdir.x, pos_inf)),
- reduce_min(select(valid, rdir.y, pos_inf)),
- reduce_min(select(valid, rdir.z, pos_inf)));
-
- const Vec3fa reduced_max_rdir(reduce_max(select(valid, rdir.x, neg_inf)),
- reduce_max(select(valid, rdir.y, neg_inf)),
- reduce_max(select(valid, rdir.z, neg_inf)));
-
- const float reduced_min_dist = reduce_min(select(valid, ray_tnear, vfloat<K>(pos_inf)));
- const float reduced_max_dist = reduce_max(select(valid, ray_tfar , vfloat<K>(neg_inf)));
-
- init(reduced_min_org, reduced_max_org, reduced_min_rdir, reduced_max_rdir, reduced_min_dist, reduced_max_dist, N);
- }
-
- __forceinline void init(const Vec3fa& reduced_min_org,
- const Vec3fa& reduced_max_org,
- const Vec3fa& reduced_min_rdir,
- const Vec3fa& reduced_max_rdir,
- float reduced_min_dist,
- float reduced_max_dist,
- int N)
- {
- const Vec3ba pos_rdir = ge_mask(reduced_min_rdir, Vec3fa(zero));
-
- min_rdir = select(pos_rdir, reduced_min_rdir, reduced_max_rdir);
- max_rdir = select(pos_rdir, reduced_max_rdir, reduced_min_rdir);
-
-#if defined (__aarch64__)
- neg_min_org_rdir = -(min_rdir * select(pos_rdir, reduced_max_org, reduced_min_org));
- neg_max_org_rdir = -(max_rdir * select(pos_rdir, reduced_min_org, reduced_max_org));
-#else
- min_org_rdir = min_rdir * select(pos_rdir, reduced_max_org, reduced_min_org);
- max_org_rdir = max_rdir * select(pos_rdir, reduced_min_org, reduced_max_org);
-#endif
- min_dist = reduced_min_dist;
- max_dist = reduced_max_dist;
-
- nf = NearFarPrecalculations(min_rdir, N);
- }
-
- template<int K>
- __forceinline void updateMaxDist(const vfloat<K>& ray_tfar)
- {
- max_dist = reduce_max(ray_tfar);
- }
-
- NearFarPrecalculations nf;
-
- Vec3fa min_rdir;
- Vec3fa max_rdir;
-
-#if defined (__aarch64__)
- Vec3fa neg_min_org_rdir;
- Vec3fa neg_max_org_rdir;
-#else
- Vec3fa min_org_rdir;
- Vec3fa max_org_rdir;
-#endif
- float min_dist;
- float max_dist;
- };
-
- typedef Frustum<false> FrustumFast;
-
- /* Robust variant */
- template<>
- struct Frustum<true>
- {
- __forceinline Frustum() {}
-
- template<int K>
- __forceinline Frustum(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
- {
- init(valid, org, rdir, ray_tnear, ray_tfar, N);
- }
-
- template<int K>
- __forceinline void init(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
- {
- const Vec3fa reduced_min_org(reduce_min(select(valid, org.x, pos_inf)),
- reduce_min(select(valid, org.y, pos_inf)),
- reduce_min(select(valid, org.z, pos_inf)));
-
- const Vec3fa reduced_max_org(reduce_max(select(valid, org.x, neg_inf)),
- reduce_max(select(valid, org.y, neg_inf)),
- reduce_max(select(valid, org.z, neg_inf)));
-
- const Vec3fa reduced_min_rdir(reduce_min(select(valid, rdir.x, pos_inf)),
- reduce_min(select(valid, rdir.y, pos_inf)),
- reduce_min(select(valid, rdir.z, pos_inf)));
-
- const Vec3fa reduced_max_rdir(reduce_max(select(valid, rdir.x, neg_inf)),
- reduce_max(select(valid, rdir.y, neg_inf)),
- reduce_max(select(valid, rdir.z, neg_inf)));
-
- const float reduced_min_dist = reduce_min(select(valid, ray_tnear, vfloat<K>(pos_inf)));
- const float reduced_max_dist = reduce_max(select(valid, ray_tfar , vfloat<K>(neg_inf)));
-
- init(reduced_min_org, reduced_max_org, reduced_min_rdir, reduced_max_rdir, reduced_min_dist, reduced_max_dist, N);
- }
-
- __forceinline void init(const Vec3fa& reduced_min_org,
- const Vec3fa& reduced_max_org,
- const Vec3fa& reduced_min_rdir,
- const Vec3fa& reduced_max_rdir,
- float reduced_min_dist,
- float reduced_max_dist,
- int N)
- {
- const Vec3ba pos_rdir = ge_mask(reduced_min_rdir, Vec3fa(zero));
- min_rdir = select(pos_rdir, reduced_min_rdir, reduced_max_rdir);
- max_rdir = select(pos_rdir, reduced_max_rdir, reduced_min_rdir);
-
- min_org = select(pos_rdir, reduced_max_org, reduced_min_org);
- max_org = select(pos_rdir, reduced_min_org, reduced_max_org);
-
- min_dist = reduced_min_dist;
- max_dist = reduced_max_dist;
-
- nf = NearFarPrecalculations(min_rdir, N);
- }
-
- template<int K>
- __forceinline void updateMaxDist(const vfloat<K>& ray_tfar)
- {
- max_dist = reduce_max(ray_tfar);
- }
-
- NearFarPrecalculations nf;
-
- Vec3fa min_rdir;
- Vec3fa max_rdir;
-
- Vec3fa min_org;
- Vec3fa max_org;
-
- float min_dist;
- float max_dist;
- };
-
- typedef Frustum<true> FrustumRobust;
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast AABBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int Nx>
- __forceinline size_t intersectNodeFrustum(const typename BVHN<N>::AABBNode* __restrict__ node,
- const FrustumFast& frustum, vfloat<Nx>& dist)
- {
- const vfloat<Nx> bminX = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearX);
- const vfloat<Nx> bminY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearY);
- const vfloat<Nx> bminZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearZ);
- const vfloat<Nx> bmaxX = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farX);
- const vfloat<Nx> bmaxY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farY);
- const vfloat<Nx> bmaxZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farZ);
-
-#if defined (__aarch64__)
- const vfloat<Nx> fminX = madd(bminX, vfloat<Nx>(frustum.min_rdir.x), vfloat<Nx>(frustum.neg_min_org_rdir.x));
- const vfloat<Nx> fminY = madd(bminY, vfloat<Nx>(frustum.min_rdir.y), vfloat<Nx>(frustum.neg_min_org_rdir.y));
- const vfloat<Nx> fminZ = madd(bminZ, vfloat<Nx>(frustum.min_rdir.z), vfloat<Nx>(frustum.neg_min_org_rdir.z));
- const vfloat<Nx> fmaxX = madd(bmaxX, vfloat<Nx>(frustum.max_rdir.x), vfloat<Nx>(frustum.neg_max_org_rdir.x));
- const vfloat<Nx> fmaxY = madd(bmaxY, vfloat<Nx>(frustum.max_rdir.y), vfloat<Nx>(frustum.neg_max_org_rdir.y));
- const vfloat<Nx> fmaxZ = madd(bmaxZ, vfloat<Nx>(frustum.max_rdir.z), vfloat<Nx>(frustum.neg_max_org_rdir.z));
-#else
- const vfloat<Nx> fminX = msub(bminX, vfloat<Nx>(frustum.min_rdir.x), vfloat<Nx>(frustum.min_org_rdir.x));
- const vfloat<Nx> fminY = msub(bminY, vfloat<Nx>(frustum.min_rdir.y), vfloat<Nx>(frustum.min_org_rdir.y));
- const vfloat<Nx> fminZ = msub(bminZ, vfloat<Nx>(frustum.min_rdir.z), vfloat<Nx>(frustum.min_org_rdir.z));
- const vfloat<Nx> fmaxX = msub(bmaxX, vfloat<Nx>(frustum.max_rdir.x), vfloat<Nx>(frustum.max_org_rdir.x));
- const vfloat<Nx> fmaxY = msub(bmaxY, vfloat<Nx>(frustum.max_rdir.y), vfloat<Nx>(frustum.max_org_rdir.y));
- const vfloat<Nx> fmaxZ = msub(bmaxZ, vfloat<Nx>(frustum.max_rdir.z), vfloat<Nx>(frustum.max_org_rdir.z));
-#endif
- const vfloat<Nx> fmin = maxi(fminX, fminY, fminZ, vfloat<Nx>(frustum.min_dist));
- dist = fmin;
- const vfloat<Nx> fmax = mini(fmaxX, fmaxY, fmaxZ, vfloat<Nx>(frustum.max_dist));
- const vbool<Nx> vmask_node_hit = fmin <= fmax;
- size_t m_node = movemask(vmask_node_hit) & (((size_t)1 << N)-1);
- return m_node;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Robust AABBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int Nx>
- __forceinline size_t intersectNodeFrustum(const typename BVHN<N>::AABBNode* __restrict__ node,
- const FrustumRobust& frustum, vfloat<Nx>& dist)
- {
- const vfloat<Nx> bminX = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearX);
- const vfloat<Nx> bminY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearY);
- const vfloat<Nx> bminZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearZ);
- const vfloat<Nx> bmaxX = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farX);
- const vfloat<Nx> bmaxY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farY);
- const vfloat<Nx> bmaxZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farZ);
-
- const vfloat<Nx> fminX = (bminX - vfloat<Nx>(frustum.min_org.x)) * vfloat<Nx>(frustum.min_rdir.x);
- const vfloat<Nx> fminY = (bminY - vfloat<Nx>(frustum.min_org.y)) * vfloat<Nx>(frustum.min_rdir.y);
- const vfloat<Nx> fminZ = (bminZ - vfloat<Nx>(frustum.min_org.z)) * vfloat<Nx>(frustum.min_rdir.z);
- const vfloat<Nx> fmaxX = (bmaxX - vfloat<Nx>(frustum.max_org.x)) * vfloat<Nx>(frustum.max_rdir.x);
- const vfloat<Nx> fmaxY = (bmaxY - vfloat<Nx>(frustum.max_org.y)) * vfloat<Nx>(frustum.max_rdir.y);
- const vfloat<Nx> fmaxZ = (bmaxZ - vfloat<Nx>(frustum.max_org.z)) * vfloat<Nx>(frustum.max_rdir.z);
-
- const float round_down = 1.0f-2.0f*float(ulp); // FIXME: use per instruction rounding for AVX512
- const float round_up = 1.0f+2.0f*float(ulp);
- const vfloat<Nx> fmin = max(fminX, fminY, fminZ, vfloat<Nx>(frustum.min_dist));
- dist = fmin;
- const vfloat<Nx> fmax = min(fmaxX, fmaxY, fmaxZ, vfloat<Nx>(frustum.max_dist));
- const vbool<Nx> vmask_node_hit = (round_down*fmin <= round_up*fmax);
- size_t m_node = movemask(vmask_node_hit) & (((size_t)1 << N)-1);
- return m_node;
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/node_intersector_packet.h b/thirdparty/embree-aarch64/kernels/bvh/node_intersector_packet.h
deleted file mode 100644
index 0543e56f8e..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/node_intersector_packet.h
+++ /dev/null
@@ -1,843 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "node_intersector.h"
-
-namespace embree
-{
- namespace isa
- {
- //////////////////////////////////////////////////////////////////////////////////////
- // Ray packet structure used in hybrid traversal
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int K, bool robust>
- struct TravRayK;
-
- /* Fast variant */
- template<int K>
- struct TravRayK<K, false>
- {
- __forceinline TravRayK() {}
-
- __forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)
- {
- init(ray_org, ray_dir, N);
- }
-
- __forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
- {
- init(ray_org, ray_dir, N);
- tnear = ray_tnear;
- tfar = ray_tfar;
- }
-
- __forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)
- {
- org = ray_org;
- dir = ray_dir;
- rdir = rcp_safe(ray_dir);
-#if defined(__aarch64__)
- neg_org_rdir = -(org * rdir);
-#elif defined(__AVX2__)
- org_rdir = org * rdir;
-#endif
- if (N)
- {
- const int size = sizeof(float)*N;
- nearXYZ.x = select(rdir.x >= 0.0f, vint<K>(0*size), vint<K>(1*size));
- nearXYZ.y = select(rdir.y >= 0.0f, vint<K>(2*size), vint<K>(3*size));
- nearXYZ.z = select(rdir.z >= 0.0f, vint<K>(4*size), vint<K>(5*size));
- }
- }
-
- Vec3vf<K> org;
- Vec3vf<K> dir;
- Vec3vf<K> rdir;
-#if defined(__aarch64__)
- Vec3vf<K> neg_org_rdir;
-#elif defined(__AVX2__)
- Vec3vf<K> org_rdir;
-#endif
- Vec3vi<K> nearXYZ;
- vfloat<K> tnear;
- vfloat<K> tfar;
- };
-
- template<int K>
- using TravRayKFast = TravRayK<K, false>;
-
- /* Robust variant */
- template<int K>
- struct TravRayK<K, true>
- {
- __forceinline TravRayK() {}
-
- __forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)
- {
- init(ray_org, ray_dir, N);
- }
-
- __forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
- {
- init(ray_org, ray_dir, N);
- tnear = ray_tnear;
- tfar = ray_tfar;
- }
-
- __forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)
- {
- org = ray_org;
- dir = ray_dir;
- rdir = vfloat<K>(1.0f)/(zero_fix(ray_dir));
-
- if (N)
- {
- const int size = sizeof(float)*N;
- nearXYZ.x = select(rdir.x >= 0.0f, vint<K>(0*size), vint<K>(1*size));
- nearXYZ.y = select(rdir.y >= 0.0f, vint<K>(2*size), vint<K>(3*size));
- nearXYZ.z = select(rdir.z >= 0.0f, vint<K>(4*size), vint<K>(5*size));
- }
- }
-
- Vec3vf<K> org;
- Vec3vf<K> dir;
- Vec3vf<K> rdir;
- Vec3vi<K> nearXYZ;
- vfloat<K> tnear;
- vfloat<K> tfar;
- };
-
- template<int K>
- using TravRayKRobust = TravRayK<K, true>;
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast AABBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K>
- __forceinline vbool<K> intersectNodeK(const typename BVHN<N>::AABBNode* node, size_t i,
- const TravRayKFast<K>& ray, vfloat<K>& dist)
-
- {
-#if defined(__aarch64__)
- const vfloat<K> lclipMinX = madd(node->lower_x[i], ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMinY = madd(node->lower_y[i], ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMinZ = madd(node->lower_z[i], ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<K> lclipMaxX = madd(node->upper_x[i], ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMaxY = madd(node->upper_y[i], ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMaxZ = madd(node->upper_z[i], ray.rdir.z, ray.neg_org_rdir.z);
-#elif defined(__AVX2__)
- const vfloat<K> lclipMinX = msub(node->lower_x[i], ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMinY = msub(node->lower_y[i], ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMinZ = msub(node->lower_z[i], ray.rdir.z, ray.org_rdir.z);
- const vfloat<K> lclipMaxX = msub(node->upper_x[i], ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMaxY = msub(node->upper_y[i], ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMaxZ = msub(node->upper_z[i], ray.rdir.z, ray.org_rdir.z);
- #else
- const vfloat<K> lclipMinX = (node->lower_x[i] - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (node->lower_y[i] - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (node->lower_z[i] - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (node->upper_x[i] - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (node->upper_y[i] - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (node->upper_z[i] - ray.org.z) * ray.rdir.z;
- #endif
-
- #if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- if (K == 16)
- {
- /* use mixed float/int min/max */
- const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
- dist = lnearP;
- return lhit;
- }
- else
- #endif
- {
- const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
- #if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
- #else
- const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
- #endif
- dist = lnearP;
- return lhit;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Robust AABBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K>
- __forceinline vbool<K> intersectNodeKRobust(const typename BVHN<N>::AABBNode* node, size_t i,
- const TravRayKRobust<K>& ray, vfloat<K>& dist)
- {
- // FIXME: use per instruction rounding for AVX512
- const vfloat<K> lclipMinX = (node->lower_x[i] - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (node->lower_y[i] - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (node->lower_z[i] - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (node->upper_x[i] - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (node->upper_y[i] - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (node->upper_z[i] - ray.org.z) * ray.rdir.z;
- const float round_up = 1.0f+3.0f*float(ulp);
- const float round_down = 1.0f-3.0f*float(ulp);
- const vfloat<K> lnearP = round_down*max(max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY)), min(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = round_up *min(min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY)), max(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);
- dist = lnearP;
- return lhit;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast AABBNodeMB intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K>
- __forceinline vbool<K> intersectNodeK(const typename BVHN<N>::AABBNodeMB* node, const size_t i,
- const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist)
- {
- const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));
- const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));
- const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));
- const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));
- const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
- const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
-
-#if defined(__aarch64__)
- const vfloat<K> lclipMinX = madd(vlower_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMinY = madd(vlower_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMinZ = madd(vlower_z, ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<K> lclipMaxX = madd(vupper_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMaxY = madd(vupper_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMaxZ = madd(vupper_z, ray.rdir.z, ray.neg_org_rdir.z);
-#elif defined(__AVX2__)
- const vfloat<K> lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat<K> lclipMaxX = msub(vupper_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMaxY = msub(vupper_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMaxZ = msub(vupper_z, ray.rdir.z, ray.org_rdir.z);
-#else
- const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;
-#endif
-
-#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- if (K == 16)
- {
- /* use mixed float/int min/max */
- const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
- dist = lnearP;
- return lhit;
- }
- else
-#endif
- {
- const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
-#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
-#else
- const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
-#endif
- dist = lnearP;
- return lhit;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Robust AABBNodeMB intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K>
- __forceinline vbool<K> intersectNodeKRobust(const typename BVHN<N>::AABBNodeMB* node, const size_t i,
- const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist)
- {
- const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));
- const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));
- const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));
- const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));
- const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
- const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
-
- const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;
-
- const float round_up = 1.0f+3.0f*float(ulp);
- const float round_down = 1.0f-3.0f*float(ulp);
-
-#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- if (K == 16)
- {
- const vfloat<K> lnearP = round_down*maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = round_up *mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
- dist = lnearP;
- return lhit;
- }
- else
-#endif
- {
- const vfloat<K> lnearP = round_down*maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = round_up *mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
- dist = lnearP;
- return lhit;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast AABBNodeMB4D intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K>
- __forceinline vbool<K> intersectNodeKMB4D(const typename BVHN<N>::NodeRef ref, const size_t i,
- const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist)
- {
- const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
-
- const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));
- const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));
- const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));
- const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));
- const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
- const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
-
-#if defined(__aarch64__)
- const vfloat<K> lclipMinX = madd(vlower_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMinY = madd(vlower_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMinZ = madd(vlower_z, ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<K> lclipMaxX = madd(vupper_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMaxY = madd(vupper_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMaxZ = madd(vupper_z, ray.rdir.z, ray.neg_org_rdir.z);
-#elif defined(__AVX2__)
- const vfloat<K> lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat<K> lclipMaxX = msub(vupper_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMaxY = msub(vupper_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMaxZ = msub(vupper_z, ray.rdir.z, ray.org_rdir.z);
-#else
- const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;
-#endif
-
- const vfloat<K> lnearP = maxi(maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY)), mini(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = mini(mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY)), maxi(lclipMinZ, lclipMaxZ));
- vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
- if (unlikely(ref.isAABBNodeMB4D())) {
- const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
- lhit = lhit & (vfloat<K>(node1->lower_t[i]) <= time) & (time < vfloat<K>(node1->upper_t[i]));
- }
- dist = lnearP;
- return lhit;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Robust AABBNodeMB4D intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K>
- __forceinline vbool<K> intersectNodeKMB4DRobust(const typename BVHN<N>::NodeRef ref, const size_t i,
- const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist)
- {
- const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
-
- const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));
- const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));
- const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));
- const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));
- const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
- const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
-
- const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;
-
- const float round_up = 1.0f+3.0f*float(ulp);
- const float round_down = 1.0f-3.0f*float(ulp);
- const vfloat<K> lnearP = round_down*maxi(maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY)), mini(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = round_up *mini(mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY)), maxi(lclipMinZ, lclipMaxZ));
- vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
-
- if (unlikely(ref.isAABBNodeMB4D())) {
- const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
- lhit = lhit & (vfloat<K>(node1->lower_t[i]) <= time) & (time < vfloat<K>(node1->upper_t[i]));
- }
- dist = lnearP;
- return lhit;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast OBBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K, bool robust>
- __forceinline vbool<K> intersectNodeK(const typename BVHN<N>::OBBNode* node, const size_t i,
- const TravRayK<K,robust>& ray, vfloat<K>& dist)
- {
- const AffineSpace3vf<K> naabb(Vec3f(node->naabb.l.vx.x[i], node->naabb.l.vx.y[i], node->naabb.l.vx.z[i]),
- Vec3f(node->naabb.l.vy.x[i], node->naabb.l.vy.y[i], node->naabb.l.vy.z[i]),
- Vec3f(node->naabb.l.vz.x[i], node->naabb.l.vz.y[i], node->naabb.l.vz.z[i]),
- Vec3f(node->naabb.p .x[i], node->naabb.p .y[i], node->naabb.p .z[i]));
-
- const Vec3vf<K> dir = xfmVector(naabb, ray.dir);
- const Vec3vf<K> nrdir = Vec3vf<K>(vfloat<K>(-1.0f)) * rcp_safe(dir); // FIXME: negate instead of mul with -1?
- const Vec3vf<K> org = xfmPoint(naabb, ray.org);
-
- const vfloat<K> lclipMinX = org.x * nrdir.x; // (Vec3fa(zero) - org) * rdir;
- const vfloat<K> lclipMinY = org.y * nrdir.y;
- const vfloat<K> lclipMinZ = org.z * nrdir.z;
- const vfloat<K> lclipMaxX = lclipMinX - nrdir.x; // (Vec3fa(one) - org) * rdir;
- const vfloat<K> lclipMaxY = lclipMinY - nrdir.y;
- const vfloat<K> lclipMaxZ = lclipMinZ - nrdir.z;
-
- vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
- vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
- if (robust) {
- lnearP = lnearP*vfloat<K>(1.0f-3.0f*float(ulp));
- lfarP = lfarP *vfloat<K>(1.0f+3.0f*float(ulp));
- }
- const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
- dist = lnearP;
- return lhit;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast OBBNodeMB intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K, bool robust>
- __forceinline vbool<K> intersectNodeK(const typename BVHN<N>::OBBNodeMB* node, const size_t i,
- const TravRayK<K,robust>& ray, const vfloat<K>& time, vfloat<K>& dist)
- {
- const AffineSpace3vf<K> xfm(Vec3f(node->space0.l.vx.x[i], node->space0.l.vx.y[i], node->space0.l.vx.z[i]),
- Vec3f(node->space0.l.vy.x[i], node->space0.l.vy.y[i], node->space0.l.vy.z[i]),
- Vec3f(node->space0.l.vz.x[i], node->space0.l.vz.y[i], node->space0.l.vz.z[i]),
- Vec3f(node->space0.p .x[i], node->space0.p .y[i], node->space0.p .z[i]));
-
- const Vec3vf<K> b0_lower = zero;
- const Vec3vf<K> b0_upper = one;
- const Vec3vf<K> b1_lower(node->b1.lower.x[i], node->b1.lower.y[i], node->b1.lower.z[i]);
- const Vec3vf<K> b1_upper(node->b1.upper.x[i], node->b1.upper.y[i], node->b1.upper.z[i]);
- const Vec3vf<K> lower = lerp(b0_lower, b1_lower, time);
- const Vec3vf<K> upper = lerp(b0_upper, b1_upper, time);
-
- const Vec3vf<K> dir = xfmVector(xfm, ray.dir);
- const Vec3vf<K> rdir = rcp_safe(dir);
- const Vec3vf<K> org = xfmPoint(xfm, ray.org);
-
- const vfloat<K> lclipMinX = (lower.x - org.x) * rdir.x;
- const vfloat<K> lclipMinY = (lower.y - org.y) * rdir.y;
- const vfloat<K> lclipMinZ = (lower.z - org.z) * rdir.z;
- const vfloat<K> lclipMaxX = (upper.x - org.x) * rdir.x;
- const vfloat<K> lclipMaxY = (upper.y - org.y) * rdir.y;
- const vfloat<K> lclipMaxZ = (upper.z - org.z) * rdir.z;
-
- vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
- vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
- if (robust) {
- lnearP = lnearP*vfloat<K>(1.0f-3.0f*float(ulp));
- lfarP = lfarP *vfloat<K>(1.0f+3.0f*float(ulp));
- }
-
- const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
- dist = lnearP;
- return lhit;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////////////////////
- // QuantizedBaseNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int K>
- __forceinline vbool<K> intersectQuantizedNodeK(const typename BVHN<N>::QuantizedBaseNode* node, size_t i,
- const TravRayK<K,false>& ray, vfloat<K>& dist)
-
- {
- assert(movemask(node->validMask()) & ((size_t)1 << i));
- const vfloat<N> lower_x = node->dequantizeLowerX();
- const vfloat<N> upper_x = node->dequantizeUpperX();
- const vfloat<N> lower_y = node->dequantizeLowerY();
- const vfloat<N> upper_y = node->dequantizeUpperY();
- const vfloat<N> lower_z = node->dequantizeLowerZ();
- const vfloat<N> upper_z = node->dequantizeUpperZ();
-
- #if defined(__aarch64__)
- const vfloat<K> lclipMinX = madd(lower_x[i], ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMinY = madd(lower_y[i], ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMinZ = madd(lower_z[i], ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<K> lclipMaxX = madd(upper_x[i], ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMaxY = madd(upper_y[i], ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMaxZ = madd(upper_z[i], ray.rdir.z, ray.neg_org_rdir.z);
- #elif defined(__AVX2__)
- const vfloat<K> lclipMinX = msub(lower_x[i], ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMinY = msub(lower_y[i], ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMinZ = msub(lower_z[i], ray.rdir.z, ray.org_rdir.z);
- const vfloat<K> lclipMaxX = msub(upper_x[i], ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMaxY = msub(upper_y[i], ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMaxZ = msub(upper_z[i], ray.rdir.z, ray.org_rdir.z);
- #else
- const vfloat<K> lclipMinX = (lower_x[i] - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (lower_y[i] - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (lower_z[i] - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (upper_x[i] - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (upper_y[i] - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (upper_z[i] - ray.org.z) * ray.rdir.z;
- #endif
-
- #if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- if (K == 16)
- {
- /* use mixed float/int min/max */
- const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
- dist = lnearP;
- return lhit;
- }
- else
- #endif
- {
- const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
- #if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX
- const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
- #else
- const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
- #endif
- dist = lnearP;
- return lhit;
- }
- }
-
- template<int N, int K>
- __forceinline vbool<K> intersectQuantizedNodeK(const typename BVHN<N>::QuantizedBaseNode* node, size_t i,
- const TravRayK<K,true>& ray, vfloat<K>& dist)
-
- {
- assert(movemask(node->validMask()) & ((size_t)1 << i));
- const vfloat<N> lower_x = node->dequantizeLowerX();
- const vfloat<N> upper_x = node->dequantizeUpperX();
- const vfloat<N> lower_y = node->dequantizeLowerY();
- const vfloat<N> upper_y = node->dequantizeUpperY();
- const vfloat<N> lower_z = node->dequantizeLowerZ();
- const vfloat<N> upper_z = node->dequantizeUpperZ();
-
- const vfloat<K> lclipMinX = (lower_x[i] - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (lower_y[i] - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (lower_z[i] - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (upper_x[i] - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (upper_y[i] - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (upper_z[i] - ray.org.z) * ray.rdir.z;
-
- const float round_up = 1.0f+3.0f*float(ulp);
- const float round_down = 1.0f-3.0f*float(ulp);
-
- const vfloat<K> lnearP = round_down*max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = round_up *min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);
- dist = lnearP;
- return lhit;
- }
-
- template<int N, int K>
- __forceinline vbool<K> intersectQuantizedNodeMBK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,
- const TravRayK<K,false>& ray, const vfloat<K>& time, vfloat<K>& dist)
-
- {
- assert(movemask(node->validMask()) & ((size_t)1 << i));
-
- const vfloat<K> lower_x = node->dequantizeLowerX(i,time);
- const vfloat<K> upper_x = node->dequantizeUpperX(i,time);
- const vfloat<K> lower_y = node->dequantizeLowerY(i,time);
- const vfloat<K> upper_y = node->dequantizeUpperY(i,time);
- const vfloat<K> lower_z = node->dequantizeLowerZ(i,time);
- const vfloat<K> upper_z = node->dequantizeUpperZ(i,time);
-
-#if defined(__aarch64__)
- const vfloat<K> lclipMinX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMinY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMinZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<K> lclipMaxX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> lclipMaxY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> lclipMaxZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);
-#elif defined(__AVX2__)
- const vfloat<K> lclipMinX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMinY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMinZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
- const vfloat<K> lclipMaxX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> lclipMaxY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> lclipMaxZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
-#else
- const vfloat<K> lclipMinX = (lower_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (lower_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (lower_z - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (upper_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (upper_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (upper_z - ray.org.z) * ray.rdir.z;
- #endif
- const vfloat<K> lnearP = max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);
- dist = lnearP;
- return lhit;
- }
-
-
- template<int N, int K>
- __forceinline vbool<K> intersectQuantizedNodeMBK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,
- const TravRayK<K,true>& ray, const vfloat<K>& time, vfloat<K>& dist)
-
- {
- assert(movemask(node->validMask()) & ((size_t)1 << i));
-
- const vfloat<K> lower_x = node->dequantizeLowerX(i,time);
- const vfloat<K> upper_x = node->dequantizeUpperX(i,time);
- const vfloat<K> lower_y = node->dequantizeLowerY(i,time);
- const vfloat<K> upper_y = node->dequantizeUpperY(i,time);
- const vfloat<K> lower_z = node->dequantizeLowerZ(i,time);
- const vfloat<K> upper_z = node->dequantizeUpperZ(i,time);
-
- const vfloat<K> lclipMinX = (lower_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMinY = (lower_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMinZ = (lower_z - ray.org.z) * ray.rdir.z;
- const vfloat<K> lclipMaxX = (upper_x - ray.org.x) * ray.rdir.x;
- const vfloat<K> lclipMaxY = (upper_y - ray.org.y) * ray.rdir.y;
- const vfloat<K> lclipMaxZ = (upper_z - ray.org.z) * ray.rdir.z;
-
- const float round_up = 1.0f+3.0f*float(ulp);
- const float round_down = 1.0f-3.0f*float(ulp);
-
- const vfloat<K> lnearP = round_down*max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
- const vfloat<K> lfarP = round_up *min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
- const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);
- dist = lnearP;
- return lhit;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Node intersectors used in hybrid traversal
- //////////////////////////////////////////////////////////////////////////////////////
-
- /*! Intersects N nodes with K rays */
- template<int N, int K, int types, bool robust>
- struct BVHNNodeIntersectorK;
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN1, false>
- {
- /* vmask is both an input and an output parameter! Its initial value should be the parent node
- hit mask, which is used for correctly computing the current hit mask. The parent hit mask
- is actually required only for motion blur node intersections (because different rays may
- have different times), so for regular nodes vmask is simply overwritten. */
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- vmask = intersectNodeK<N,K>(node.getAABBNode(), i, ray, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN1, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- vmask = intersectNodeKRobust<N,K>(node.getAABBNode(), i, ray, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN2, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- vmask = intersectNodeK<N,K>(node.getAABBNodeMB(), i, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN2, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- vmask = intersectNodeKRobust<N,K>(node.getAABBNodeMB(), i, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN1_UN1, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- if (likely(node.isAABBNode())) vmask = intersectNodeK<N,K>(node.getAABBNode(), i, ray, dist);
- else /*if (unlikely(node.isOBBNode()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNode(), i, ray, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN1_UN1, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- if (likely(node.isAABBNode())) vmask = intersectNodeKRobust<N,K>(node.getAABBNode(), i, ray, dist);
- else /*if (unlikely(node.isOBBNode()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNode(), i, ray, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN2_UN2, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- if (likely(node.isAABBNodeMB())) vmask = intersectNodeK<N,K>(node.getAABBNodeMB(), i, ray, time, dist);
- else /*if (unlikely(node.isOBBNodeMB()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN2_UN2, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- if (likely(node.isAABBNodeMB())) vmask = intersectNodeKRobust<N,K>(node.getAABBNodeMB(), i, ray, time, dist);
- else /*if (unlikely(node.isOBBNodeMB()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- vmask &= intersectNodeKMB4D<N,K>(node, i, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- vmask &= intersectNodeKMB4DRobust<N,K>(node, i, ray, time, dist);
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D_UN2, false>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- if (likely(node.isAABBNodeMB() || node.isAABBNodeMB4D())) {
- vmask &= intersectNodeKMB4D<N,K>(node, i, ray, time, dist);
- } else /*if (unlikely(node.isOBBNodeMB()))*/ {
- assert(node.isOBBNodeMB());
- vmask &= intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);
- }
- return true;
- }
- };
-
- template<int N, int K>
- struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D_UN2, true>
- {
- static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
- const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
- {
- if (likely(node.isAABBNodeMB() || node.isAABBNodeMB4D())) {
- vmask &= intersectNodeKMB4DRobust<N,K>(node, i, ray, time, dist);
- } else /*if (unlikely(node.isOBBNodeMB()))*/ {
- assert(node.isOBBNodeMB());
- vmask &= intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);
- }
- return true;
- }
- };
-
-
- /*! Intersects N nodes with K rays */
- template<int N, int K, bool robust>
- struct BVHNQuantizedBaseNodeIntersectorK;
-
- template<int N, int K>
- struct BVHNQuantizedBaseNodeIntersectorK<N, K, false>
- {
- static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNode* node, const size_t i,
- const TravRayK<K,false>& ray, vfloat<K>& dist)
- {
- return intersectQuantizedNodeK<N,K>(node,i,ray,dist);
- }
-
- static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,
- const TravRayK<K,false>& ray, const vfloat<K>& time, vfloat<K>& dist)
- {
- return intersectQuantizedNodeMBK<N,K>(node,i,ray,time,dist);
- }
-
- };
-
- template<int N, int K>
- struct BVHNQuantizedBaseNodeIntersectorK<N, K, true>
- {
- static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNode* node, const size_t i,
- const TravRayK<K,true>& ray, vfloat<K>& dist)
- {
- return intersectQuantizedNodeK<N,K>(node,i,ray,dist);
- }
-
- static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,
- const TravRayK<K,true>& ray, const vfloat<K>& time, vfloat<K>& dist)
- {
- return intersectQuantizedNodeMBK<N,K>(node,i,ray,time,dist);
- }
- };
-
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/bvh/node_intersector_packet_stream.h b/thirdparty/embree-aarch64/kernels/bvh/node_intersector_packet_stream.h
deleted file mode 100644
index f379b57aea..0000000000
--- a/thirdparty/embree-aarch64/kernels/bvh/node_intersector_packet_stream.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "node_intersector.h"
-
-namespace embree
-{
- namespace isa
- {
- //////////////////////////////////////////////////////////////////////////////////////
- // Ray packet structure used in stream traversal
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int K, bool robust>
- struct TravRayKStream;
-
- /* Fast variant */
- template<int K>
- struct TravRayKStream<K, false>
- {
- __forceinline TravRayKStream() {}
-
- __forceinline TravRayKStream(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar)
- {
- init(ray_org, ray_dir);
- tnear = ray_tnear;
- tfar = ray_tfar;
- }
-
- __forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir)
- {
- rdir = rcp_safe(ray_dir);
-#if defined(__aarch64__)
- neg_org_rdir = -(ray_org * rdir);
-#else
- org_rdir = ray_org * rdir;
-#endif
- }
-
- Vec3vf<K> rdir;
-#if defined(__aarch64__)
- Vec3vf<K> neg_org_rdir;
-#else
- Vec3vf<K> org_rdir;
-#endif
- vfloat<K> tnear;
- vfloat<K> tfar;
- };
-
- template<int K>
- using TravRayKStreamFast = TravRayKStream<K, false>;
-
- /* Robust variant */
- template<int K>
- struct TravRayKStream<K, true>
- {
- __forceinline TravRayKStream() {}
-
- __forceinline TravRayKStream(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar)
- {
- init(ray_org, ray_dir);
- tnear = ray_tnear;
- tfar = ray_tfar;
- }
-
- __forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir)
- {
- rdir = vfloat<K>(1.0f)/(zero_fix(ray_dir));
- org = ray_org;
- }
-
- Vec3vf<K> rdir;
- Vec3vf<K> org;
- vfloat<K> tnear;
- vfloat<K> tfar;
- };
-
- template<int K>
- using TravRayKStreamRobust = TravRayKStream<K, true>;
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Fast AABBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int Nx, int K>
- __forceinline size_t intersectNode1(const typename BVHN<N>::AABBNode* __restrict__ node,
- const TravRayKStreamFast<K>& ray, size_t k, const NearFarPrecalculations& nf)
- {
- const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
- const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
- const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
- const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
- const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
- const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
-
-#if defined (__aarch64__)
- const vfloat<Nx> rminX = madd(bminX, vfloat<Nx>(ray.rdir.x[k]), vfloat<Nx>(ray.neg_org_rdir.x[k]));
- const vfloat<Nx> rminY = madd(bminY, vfloat<Nx>(ray.rdir.y[k]), vfloat<Nx>(ray.neg_org_rdir.y[k]));
- const vfloat<Nx> rminZ = madd(bminZ, vfloat<Nx>(ray.rdir.z[k]), vfloat<Nx>(ray.neg_org_rdir.z[k]));
- const vfloat<Nx> rmaxX = madd(bmaxX, vfloat<Nx>(ray.rdir.x[k]), vfloat<Nx>(ray.neg_org_rdir.x[k]));
- const vfloat<Nx> rmaxY = madd(bmaxY, vfloat<Nx>(ray.rdir.y[k]), vfloat<Nx>(ray.neg_org_rdir.y[k]));
- const vfloat<Nx> rmaxZ = madd(bmaxZ, vfloat<Nx>(ray.rdir.z[k]), vfloat<Nx>(ray.neg_org_rdir.z[k]));
-#else
- const vfloat<Nx> rminX = msub(bminX, vfloat<Nx>(ray.rdir.x[k]), vfloat<Nx>(ray.org_rdir.x[k]));
- const vfloat<Nx> rminY = msub(bminY, vfloat<Nx>(ray.rdir.y[k]), vfloat<Nx>(ray.org_rdir.y[k]));
- const vfloat<Nx> rminZ = msub(bminZ, vfloat<Nx>(ray.rdir.z[k]), vfloat<Nx>(ray.org_rdir.z[k]));
- const vfloat<Nx> rmaxX = msub(bmaxX, vfloat<Nx>(ray.rdir.x[k]), vfloat<Nx>(ray.org_rdir.x[k]));
- const vfloat<Nx> rmaxY = msub(bmaxY, vfloat<Nx>(ray.rdir.y[k]), vfloat<Nx>(ray.org_rdir.y[k]));
- const vfloat<Nx> rmaxZ = msub(bmaxZ, vfloat<Nx>(ray.rdir.z[k]), vfloat<Nx>(ray.org_rdir.z[k]));
-#endif
- const vfloat<Nx> rmin = maxi(rminX, rminY, rminZ, vfloat<Nx>(ray.tnear[k]));
- const vfloat<Nx> rmax = mini(rmaxX, rmaxY, rmaxZ, vfloat<Nx>(ray.tfar[k]));
-
- const vbool<Nx> vmask_first_hit = rmin <= rmax;
-
- return movemask(vmask_first_hit) & (((size_t)1 << N)-1);
- }
-
- template<int N, int K>
- __forceinline size_t intersectNodeK(const typename BVHN<N>::AABBNode* __restrict__ node, size_t i,
- const TravRayKStreamFast<K>& ray, const NearFarPrecalculations& nf)
- {
- char* ptr = (char*)&node->lower_x + i*sizeof(float);
- const vfloat<K> bminX = *(const float*)(ptr + nf.nearX);
- const vfloat<K> bminY = *(const float*)(ptr + nf.nearY);
- const vfloat<K> bminZ = *(const float*)(ptr + nf.nearZ);
- const vfloat<K> bmaxX = *(const float*)(ptr + nf.farX);
- const vfloat<K> bmaxY = *(const float*)(ptr + nf.farY);
- const vfloat<K> bmaxZ = *(const float*)(ptr + nf.farZ);
-
-#if defined (__aarch64__)
- const vfloat<K> rminX = madd(bminX, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> rminY = madd(bminY, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> rminZ = madd(bminZ, ray.rdir.z, ray.neg_org_rdir.z);
- const vfloat<K> rmaxX = madd(bmaxX, ray.rdir.x, ray.neg_org_rdir.x);
- const vfloat<K> rmaxY = madd(bmaxY, ray.rdir.y, ray.neg_org_rdir.y);
- const vfloat<K> rmaxZ = madd(bmaxZ, ray.rdir.z, ray.neg_org_rdir.z);
-#else
- const vfloat<K> rminX = msub(bminX, ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> rminY = msub(bminY, ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> rminZ = msub(bminZ, ray.rdir.z, ray.org_rdir.z);
- const vfloat<K> rmaxX = msub(bmaxX, ray.rdir.x, ray.org_rdir.x);
- const vfloat<K> rmaxY = msub(bmaxY, ray.rdir.y, ray.org_rdir.y);
- const vfloat<K> rmaxZ = msub(bmaxZ, ray.rdir.z, ray.org_rdir.z);
-#endif
-
- const vfloat<K> rmin = maxi(rminX, rminY, rminZ, ray.tnear);
- const vfloat<K> rmax = mini(rmaxX, rmaxY, rmaxZ, ray.tfar);
-
- const vbool<K> vmask_first_hit = rmin <= rmax;
-
- return movemask(vmask_first_hit);
- }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Robust AABBNode intersection
- //////////////////////////////////////////////////////////////////////////////////////
-
- template<int N, int Nx, int K>
- __forceinline size_t intersectNode1(const typename BVHN<N>::AABBNode* __restrict__ node,
- const TravRayKStreamRobust<K>& ray, size_t k, const NearFarPrecalculations& nf)
- {
- const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
- const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
- const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
- const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
- const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
- const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
-
- const vfloat<Nx> rminX = (bminX - vfloat<Nx>(ray.org.x[k])) * vfloat<Nx>(ray.rdir.x[k]);
- const vfloat<Nx> rminY = (bminY - vfloat<Nx>(ray.org.y[k])) * vfloat<Nx>(ray.rdir.y[k]);
- const vfloat<Nx> rminZ = (bminZ - vfloat<Nx>(ray.org.z[k])) * vfloat<Nx>(ray.rdir.z[k]);
- const vfloat<Nx> rmaxX = (bmaxX - vfloat<Nx>(ray.org.x[k])) * vfloat<Nx>(ray.rdir.x[k]);
- const vfloat<Nx> rmaxY = (bmaxY - vfloat<Nx>(ray.org.y[k])) * vfloat<Nx>(ray.rdir.y[k]);
- const vfloat<Nx> rmaxZ = (bmaxZ - vfloat<Nx>(ray.org.z[k])) * vfloat<Nx>(ray.rdir.z[k]);
- const float round_up = 1.0f+3.0f*float(ulp); // FIXME: use per instruction rounding for AVX512
- const vfloat<Nx> rmin = max(rminX, rminY, rminZ, vfloat<Nx>(ray.tnear[k]));
- const vfloat<Nx> rmax = round_up *min(rmaxX, rmaxY, rmaxZ, vfloat<Nx>(ray.tfar[k]));
-
- const vbool<Nx> vmask_first_hit = rmin <= rmax;
-
- return movemask(vmask_first_hit) & (((size_t)1 << N)-1);
- }
-
- template<int N, int K>
- __forceinline size_t intersectNodeK(const typename BVHN<N>::AABBNode* __restrict__ node, size_t i,
- const TravRayKStreamRobust<K>& ray, const NearFarPrecalculations& nf)
- {
- char *ptr = (char*)&node->lower_x + i*sizeof(float);
- const vfloat<K> bminX = *(const float*)(ptr + nf.nearX);
- const vfloat<K> bminY = *(const float*)(ptr + nf.nearY);
- const vfloat<K> bminZ = *(const float*)(ptr + nf.nearZ);
- const vfloat<K> bmaxX = *(const float*)(ptr + nf.farX);
- const vfloat<K> bmaxY = *(const float*)(ptr + nf.farY);
- const vfloat<K> bmaxZ = *(const float*)(ptr + nf.farZ);
-
- const vfloat<K> rminX = (bminX - ray.org.x) * ray.rdir.x;
- const vfloat<K> rminY = (bminY - ray.org.y) * ray.rdir.y;
- const vfloat<K> rminZ = (bminZ - ray.org.z) * ray.rdir.z;
- const vfloat<K> rmaxX = (bmaxX - ray.org.x) * ray.rdir.x;
- const vfloat<K> rmaxY = (bmaxY - ray.org.y) * ray.rdir.y;
- const vfloat<K> rmaxZ = (bmaxZ - ray.org.z) * ray.rdir.z;
-
- const float round_up = 1.0f+3.0f*float(ulp);
- const vfloat<K> rmin = max(rminX, rminY, rminZ, vfloat<K>(ray.tnear));
- const vfloat<K> rmax = round_up * min(rmaxX, rmaxY, rmaxZ, vfloat<K>(ray.tfar));
-
- const vbool<K> vmask_first_hit = rmin <= rmax;
-
- return movemask(vmask_first_hit);
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/accel.h b/thirdparty/embree-aarch64/kernels/common/accel.h
deleted file mode 100644
index c038d3cf21..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/accel.h
+++ /dev/null
@@ -1,556 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "ray.h"
-#include "point_query.h"
-#include "context.h"
-
-namespace embree
-{
- class Scene;
-
- /*! Base class for the acceleration structure data. */
- class AccelData : public RefCount
- {
- ALIGNED_CLASS_(16);
- public:
- enum Type { TY_UNKNOWN = 0, TY_ACCELN = 1, TY_ACCEL_INSTANCE = 2, TY_BVH4 = 3, TY_BVH8 = 4 };
-
- public:
- AccelData (const Type type)
- : bounds(empty), type(type) {}
-
- /*! notifies the acceleration structure about the deletion of some geometry */
- virtual void deleteGeometry(size_t geomID) {};
-
- /*! clears the acceleration structure data */
- virtual void clear() = 0;
-
- /*! returns normal bounds */
- __forceinline BBox3fa getBounds() const {
- return bounds.bounds();
- }
-
- /*! returns bounds for some time */
- __forceinline BBox3fa getBounds(float t) const {
- return bounds.interpolate(t);
- }
-
- /*! returns linear bounds */
- __forceinline LBBox3fa getLinearBounds() const {
- return bounds;
- }
-
- /*! checks if acceleration structure is empty */
- __forceinline bool isEmpty() const {
- return bounds.bounds0.lower.x == float(pos_inf);
- }
-
- public:
- LBBox3fa bounds; // linear bounds
- Type type;
- };
-
- /*! Base class for all intersectable and buildable acceleration structures. */
- class Accel : public AccelData
- {
- ALIGNED_CLASS_(16);
- public:
-
- struct Intersectors;
-
- /*! Type of collide function */
- typedef void (*CollideFunc)(void* bvh0, void* bvh1, RTCCollideFunc callback, void* userPtr);
-
- /*! Type of point query function */
- typedef bool(*PointQueryFunc)(Intersectors* This, /*!< this pointer to accel */
- PointQuery* query, /*!< point query for lookup */
- PointQueryContext* context); /*!< point query context */
-
- /*! Type of intersect function pointer for single rays. */
- typedef void (*IntersectFunc)(Intersectors* This, /*!< this pointer to accel */
- RTCRayHit& ray, /*!< ray to intersect */
- IntersectContext* context);
-
- /*! Type of intersect function pointer for ray packets of size 4. */
- typedef void (*IntersectFunc4)(const void* valid, /*!< pointer to valid mask */
- Intersectors* This, /*!< this pointer to accel */
- RTCRayHit4& ray, /*!< ray packet to intersect */
- IntersectContext* context);
-
- /*! Type of intersect function pointer for ray packets of size 8. */
- typedef void (*IntersectFunc8)(const void* valid, /*!< pointer to valid mask */
- Intersectors* This, /*!< this pointer to accel */
- RTCRayHit8& ray, /*!< ray packet to intersect */
- IntersectContext* context);
-
- /*! Type of intersect function pointer for ray packets of size 16. */
- typedef void (*IntersectFunc16)(const void* valid, /*!< pointer to valid mask */
- Intersectors* This, /*!< this pointer to accel */
- RTCRayHit16& ray, /*!< ray packet to intersect */
- IntersectContext* context);
-
- /*! Type of intersect function pointer for ray packets of size N. */
- typedef void (*IntersectFuncN)(Intersectors* This, /*!< this pointer to accel */
- RTCRayHitN** ray, /*!< ray stream to intersect */
- const size_t N, /*!< number of rays in stream */
- IntersectContext* context /*!< layout flags */);
-
-
- /*! Type of occlusion function pointer for single rays. */
- typedef void (*OccludedFunc) (Intersectors* This, /*!< this pointer to accel */
- RTCRay& ray, /*!< ray to test occlusion */
- IntersectContext* context);
-
- /*! Type of occlusion function pointer for ray packets of size 4. */
- typedef void (*OccludedFunc4) (const void* valid, /*!< pointer to valid mask */
- Intersectors* This, /*!< this pointer to accel */
- RTCRay4& ray, /*!< ray packet to test occlusion. */
- IntersectContext* context);
-
- /*! Type of occlusion function pointer for ray packets of size 8. */
- typedef void (*OccludedFunc8) (const void* valid, /*!< pointer to valid mask */
- Intersectors* This, /*!< this pointer to accel */
- RTCRay8& ray, /*!< ray packet to test occlusion. */
- IntersectContext* context);
-
- /*! Type of occlusion function pointer for ray packets of size 16. */
- typedef void (*OccludedFunc16) (const void* valid, /*!< pointer to valid mask */
- Intersectors* This, /*!< this pointer to accel */
- RTCRay16& ray, /*!< ray packet to test occlusion. */
- IntersectContext* context);
-
- /*! Type of intersect function pointer for ray packets of size N. */
- typedef void (*OccludedFuncN)(Intersectors* This, /*!< this pointer to accel */
- RTCRayN** ray, /*!< ray stream to test occlusion */
- const size_t N, /*!< number of rays in stream */
- IntersectContext* context /*!< layout flags */);
- typedef void (*ErrorFunc) ();
-
- struct Collider
- {
- Collider (ErrorFunc error = nullptr)
- : collide((CollideFunc)error), name(nullptr) {}
-
- Collider (CollideFunc collide, const char* name)
- : collide(collide), name(name) {}
-
- operator bool() const { return name; }
-
- public:
- CollideFunc collide;
- const char* name;
- };
-
- struct Intersector1
- {
- Intersector1 (ErrorFunc error = nullptr)
- : intersect((IntersectFunc)error), occluded((OccludedFunc)error), name(nullptr) {}
-
- Intersector1 (IntersectFunc intersect, OccludedFunc occluded, const char* name)
- : intersect(intersect), occluded(occluded), pointQuery(nullptr), name(name) {}
-
- Intersector1 (IntersectFunc intersect, OccludedFunc occluded, PointQueryFunc pointQuery, const char* name)
- : intersect(intersect), occluded(occluded), pointQuery(pointQuery), name(name) {}
-
- operator bool() const { return name; }
-
- public:
- static const char* type;
- IntersectFunc intersect;
- OccludedFunc occluded;
- PointQueryFunc pointQuery;
- const char* name;
- };
-
- struct Intersector4
- {
- Intersector4 (ErrorFunc error = nullptr)
- : intersect((IntersectFunc4)error), occluded((OccludedFunc4)error), name(nullptr) {}
-
- Intersector4 (IntersectFunc4 intersect, OccludedFunc4 occluded, const char* name)
- : intersect(intersect), occluded(occluded), name(name) {}
-
- operator bool() const { return name; }
-
- public:
- static const char* type;
- IntersectFunc4 intersect;
- OccludedFunc4 occluded;
- const char* name;
- };
-
- struct Intersector8
- {
- Intersector8 (ErrorFunc error = nullptr)
- : intersect((IntersectFunc8)error), occluded((OccludedFunc8)error), name(nullptr) {}
-
- Intersector8 (IntersectFunc8 intersect, OccludedFunc8 occluded, const char* name)
- : intersect(intersect), occluded(occluded), name(name) {}
-
- operator bool() const { return name; }
-
- public:
- static const char* type;
- IntersectFunc8 intersect;
- OccludedFunc8 occluded;
- const char* name;
- };
-
- struct Intersector16
- {
- Intersector16 (ErrorFunc error = nullptr)
- : intersect((IntersectFunc16)error), occluded((OccludedFunc16)error), name(nullptr) {}
-
- Intersector16 (IntersectFunc16 intersect, OccludedFunc16 occluded, const char* name)
- : intersect(intersect), occluded(occluded), name(name) {}
-
- operator bool() const { return name; }
-
- public:
- static const char* type;
- IntersectFunc16 intersect;
- OccludedFunc16 occluded;
- const char* name;
- };
-
- struct IntersectorN
- {
- IntersectorN (ErrorFunc error = nullptr)
- : intersect((IntersectFuncN)error), occluded((OccludedFuncN)error), name(nullptr) {}
-
- IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name)
- : intersect(intersect), occluded(occluded), name(name) {}
-
- operator bool() const { return name; }
-
- public:
- static const char* type;
- IntersectFuncN intersect;
- OccludedFuncN occluded;
- const char* name;
- };
-
- struct Intersectors
- {
- Intersectors()
- : ptr(nullptr), leafIntersector(nullptr), collider(nullptr), intersector1(nullptr), intersector4(nullptr), intersector8(nullptr), intersector16(nullptr), intersectorN(nullptr) {}
-
- Intersectors (ErrorFunc error)
- : ptr(nullptr), leafIntersector(nullptr), collider(error), intersector1(error), intersector4(error), intersector8(error), intersector16(error), intersectorN(error) {}
-
- void print(size_t ident)
- {
- if (collider.name) {
- for (size_t i=0; i<ident; i++) std::cout << " ";
- std::cout << "collider = " << collider.name << std::endl;
- }
- if (intersector1.name) {
- for (size_t i=0; i<ident; i++) std::cout << " ";
- std::cout << "intersector1 = " << intersector1.name << std::endl;
- }
- if (intersector4.name) {
- for (size_t i=0; i<ident; i++) std::cout << " ";
- std::cout << "intersector4 = " << intersector4.name << std::endl;
- }
- if (intersector8.name) {
- for (size_t i=0; i<ident; i++) std::cout << " ";
- std::cout << "intersector8 = " << intersector8.name << std::endl;
- }
- if (intersector16.name) {
- for (size_t i=0; i<ident; i++) std::cout << " ";
- std::cout << "intersector16 = " << intersector16.name << std::endl;
- }
- if (intersectorN.name) {
- for (size_t i=0; i<ident; i++) std::cout << " ";
- std::cout << "intersectorN = " << intersectorN.name << std::endl;
- }
- }
-
- void select(bool filter)
- {
- if (intersector4_filter) {
- if (filter) intersector4 = intersector4_filter;
- else intersector4 = intersector4_nofilter;
- }
- if (intersector8_filter) {
- if (filter) intersector8 = intersector8_filter;
- else intersector8 = intersector8_nofilter;
- }
- if (intersector16_filter) {
- if (filter) intersector16 = intersector16_filter;
- else intersector16 = intersector16_nofilter;
- }
- if (intersectorN_filter) {
- if (filter) intersectorN = intersectorN_filter;
- else intersectorN = intersectorN_nofilter;
- }
- }
-
- __forceinline bool pointQuery (PointQuery* query, PointQueryContext* context) {
- assert(intersector1.pointQuery);
- return intersector1.pointQuery(this,query,context);
- }
-
- /*! collides two scenes */
- __forceinline void collide (Accel* scene0, Accel* scene1, RTCCollideFunc callback, void* userPtr) {
- assert(collider.collide);
- collider.collide(scene0->intersectors.ptr,scene1->intersectors.ptr,callback,userPtr);
- }
-
- /*! Intersects a single ray with the scene. */
- __forceinline void intersect (RTCRayHit& ray, IntersectContext* context) {
- assert(intersector1.intersect);
- intersector1.intersect(this,ray,context);
- }
-
- /*! Intersects a packet of 4 rays with the scene. */
- __forceinline void intersect4 (const void* valid, RTCRayHit4& ray, IntersectContext* context) {
- assert(intersector4.intersect);
- intersector4.intersect(valid,this,ray,context);
- }
-
- /*! Intersects a packet of 8 rays with the scene. */
- __forceinline void intersect8 (const void* valid, RTCRayHit8& ray, IntersectContext* context) {
- assert(intersector8.intersect);
- intersector8.intersect(valid,this,ray,context);
- }
-
- /*! Intersects a packet of 16 rays with the scene. */
- __forceinline void intersect16 (const void* valid, RTCRayHit16& ray, IntersectContext* context) {
- assert(intersector16.intersect);
- intersector16.intersect(valid,this,ray,context);
- }
-
- /*! Intersects a stream of N rays in SOA layout with the scene. */
- __forceinline void intersectN (RTCRayHitN** rayN, const size_t N, IntersectContext* context)
- {
- assert(intersectorN.intersect);
- intersectorN.intersect(this,rayN,N,context);
- }
-
-#if defined(__SSE__) || defined(__ARM_NEON)
- __forceinline void intersect(const vbool4& valid, RayHitK<4>& ray, IntersectContext* context) {
- const vint<4> mask = valid.mask32();
- intersect4(&mask,(RTCRayHit4&)ray,context);
- }
-#endif
-#if defined(__AVX__)
- __forceinline void intersect(const vbool8& valid, RayHitK<8>& ray, IntersectContext* context) {
- const vint<8> mask = valid.mask32();
- intersect8(&mask,(RTCRayHit8&)ray,context);
- }
-#endif
-#if defined(__AVX512F__)
- __forceinline void intersect(const vbool16& valid, RayHitK<16>& ray, IntersectContext* context) {
- const vint<16> mask = valid.mask32();
- intersect16(&mask,(RTCRayHit16&)ray,context);
- }
-#endif
-
- template<int K>
- __forceinline void intersectN (RayHitK<K>** rayN, const size_t N, IntersectContext* context)
- {
- intersectN((RTCRayHitN**)rayN,N,context);
- }
-
- /*! Tests if single ray is occluded by the scene. */
- __forceinline void occluded (RTCRay& ray, IntersectContext* context) {
- assert(intersector1.occluded);
- intersector1.occluded(this,ray,context);
- }
-
- /*! Tests if a packet of 4 rays is occluded by the scene. */
- __forceinline void occluded4 (const void* valid, RTCRay4& ray, IntersectContext* context) {
- assert(intersector4.occluded);
- intersector4.occluded(valid,this,ray,context);
- }
-
- /*! Tests if a packet of 8 rays is occluded by the scene. */
- __forceinline void occluded8 (const void* valid, RTCRay8& ray, IntersectContext* context) {
- assert(intersector8.occluded);
- intersector8.occluded(valid,this,ray,context);
- }
-
- /*! Tests if a packet of 16 rays is occluded by the scene. */
- __forceinline void occluded16 (const void* valid, RTCRay16& ray, IntersectContext* context) {
- assert(intersector16.occluded);
- intersector16.occluded(valid,this,ray,context);
- }
-
- /*! Tests if a stream of N rays in SOA layout is occluded by the scene. */
- __forceinline void occludedN (RTCRayN** rayN, const size_t N, IntersectContext* context)
- {
- assert(intersectorN.occluded);
- intersectorN.occluded(this,rayN,N,context);
- }
-
-#if defined(__SSE__) || defined(__ARM_NEON)
- __forceinline void occluded(const vbool4& valid, RayK<4>& ray, IntersectContext* context) {
- const vint<4> mask = valid.mask32();
- occluded4(&mask,(RTCRay4&)ray,context);
- }
-#endif
-#if defined(__AVX__)
- __forceinline void occluded(const vbool8& valid, RayK<8>& ray, IntersectContext* context) {
- const vint<8> mask = valid.mask32();
- occluded8(&mask,(RTCRay8&)ray,context);
- }
-#endif
-#if defined(__AVX512F__)
- __forceinline void occluded(const vbool16& valid, RayK<16>& ray, IntersectContext* context) {
- const vint<16> mask = valid.mask32();
- occluded16(&mask,(RTCRay16&)ray,context);
- }
-#endif
-
- template<int K>
- __forceinline void occludedN (RayK<K>** rayN, const size_t N, IntersectContext* context)
- {
- occludedN((RTCRayN**)rayN,N,context);
- }
-
- /*! Tests if single ray is occluded by the scene. */
- __forceinline void intersect(RTCRay& ray, IntersectContext* context) {
- occluded(ray, context);
- }
-
- /*! Tests if a packet of K rays is occluded by the scene. */
- template<int K>
- __forceinline void intersect(const vbool<K>& valid, RayK<K>& ray, IntersectContext* context) {
- occluded(valid, ray, context);
- }
-
- /*! Tests if a packet of N rays in SOA layout is occluded by the scene. */
- template<int K>
- __forceinline void intersectN(RayK<K>** rayN, const size_t N, IntersectContext* context) {
- occludedN(rayN, N, context);
- }
-
- public:
- AccelData* ptr;
- void* leafIntersector;
- Collider collider;
- Intersector1 intersector1;
- Intersector4 intersector4;
- Intersector4 intersector4_filter;
- Intersector4 intersector4_nofilter;
- Intersector8 intersector8;
- Intersector8 intersector8_filter;
- Intersector8 intersector8_nofilter;
- Intersector16 intersector16;
- Intersector16 intersector16_filter;
- Intersector16 intersector16_nofilter;
- IntersectorN intersectorN;
- IntersectorN intersectorN_filter;
- IntersectorN intersectorN_nofilter;
- };
-
- public:
-
- /*! Construction */
- Accel (const AccelData::Type type)
- : AccelData(type) {}
-
- /*! Construction */
- Accel (const AccelData::Type type, const Intersectors& intersectors)
- : AccelData(type), intersectors(intersectors) {}
-
- /*! Virtual destructor */
- virtual ~Accel() {}
-
- /*! makes the acceleration structure immutable */
- virtual void immutable () {}
-
- /*! build acceleration structure */
- virtual void build () = 0;
-
- public:
- Intersectors intersectors;
- };
-
-#define DEFINE_COLLIDER(symbol,collider) \
- Accel::Collider symbol() { \
- return Accel::Collider((Accel::CollideFunc)collider::collide, \
- TOSTRING(isa) "::" TOSTRING(symbol)); \
- }
-
-#define DEFINE_INTERSECTOR1(symbol,intersector) \
- Accel::Intersector1 symbol() { \
- return Accel::Intersector1((Accel::IntersectFunc )intersector::intersect, \
- (Accel::OccludedFunc )intersector::occluded, \
- (Accel::PointQueryFunc)intersector::pointQuery,\
- TOSTRING(isa) "::" TOSTRING(symbol)); \
- }
-
-#define DEFINE_INTERSECTOR4(symbol,intersector) \
- Accel::Intersector4 symbol() { \
- return Accel::Intersector4((Accel::IntersectFunc4)intersector::intersect, \
- (Accel::OccludedFunc4)intersector::occluded, \
- TOSTRING(isa) "::" TOSTRING(symbol)); \
- }
-
-#define DEFINE_INTERSECTOR8(symbol,intersector) \
- Accel::Intersector8 symbol() { \
- return Accel::Intersector8((Accel::IntersectFunc8)intersector::intersect, \
- (Accel::OccludedFunc8)intersector::occluded, \
- TOSTRING(isa) "::" TOSTRING(symbol)); \
- }
-
-#define DEFINE_INTERSECTOR16(symbol,intersector) \
- Accel::Intersector16 symbol() { \
- return Accel::Intersector16((Accel::IntersectFunc16)intersector::intersect, \
- (Accel::OccludedFunc16)intersector::occluded, \
- TOSTRING(isa) "::" TOSTRING(symbol)); \
- }
-
-#define DEFINE_INTERSECTORN(symbol,intersector) \
- Accel::IntersectorN symbol() { \
- return Accel::IntersectorN((Accel::IntersectFuncN)intersector::intersect, \
- (Accel::OccludedFuncN)intersector::occluded, \
- TOSTRING(isa) "::" TOSTRING(symbol)); \
- }
-
- /* ray stream filter interface */
- typedef void (*intersectStreamAOS_func)(Scene* scene, RTCRayHit* _rayN, const size_t N, const size_t stride, IntersectContext* context);
- typedef void (*intersectStreamAOP_func)(Scene* scene, RTCRayHit** _rayN, const size_t N, IntersectContext* context);
- typedef void (*intersectStreamSOA_func)(Scene* scene, char* rayN, const size_t N, const size_t streams, const size_t stream_offset, IntersectContext* context);
- typedef void (*intersectStreamSOP_func)(Scene* scene, const RTCRayHitNp* rayN, const size_t N, IntersectContext* context);
-
- typedef void (*occludedStreamAOS_func)(Scene* scene, RTCRay* _rayN, const size_t N, const size_t stride, IntersectContext* context);
- typedef void (*occludedStreamAOP_func)(Scene* scene, RTCRay** _rayN, const size_t N, IntersectContext* context);
- typedef void (*occludedStreamSOA_func)(Scene* scene, char* rayN, const size_t N, const size_t streams, const size_t stream_offset, IntersectContext* context);
- typedef void (*occludedStreamSOP_func)(Scene* scene, const RTCRayNp* rayN, const size_t N, IntersectContext* context);
-
- struct RayStreamFilterFuncs
- {
- RayStreamFilterFuncs()
- : intersectAOS(nullptr), intersectAOP(nullptr), intersectSOA(nullptr), intersectSOP(nullptr),
- occludedAOS(nullptr), occludedAOP(nullptr), occludedSOA(nullptr), occludedSOP(nullptr) {}
-
- RayStreamFilterFuncs(void (*ptr) ())
- : intersectAOS((intersectStreamAOS_func) ptr), intersectAOP((intersectStreamAOP_func) ptr), intersectSOA((intersectStreamSOA_func) ptr), intersectSOP((intersectStreamSOP_func) ptr),
- occludedAOS((occludedStreamAOS_func) ptr), occludedAOP((occludedStreamAOP_func) ptr), occludedSOA((occludedStreamSOA_func) ptr), occludedSOP((occludedStreamSOP_func) ptr) {}
-
- RayStreamFilterFuncs(intersectStreamAOS_func intersectAOS, intersectStreamAOP_func intersectAOP, intersectStreamSOA_func intersectSOA, intersectStreamSOP_func intersectSOP,
- occludedStreamAOS_func occludedAOS, occludedStreamAOP_func occludedAOP, occludedStreamSOA_func occludedSOA, occludedStreamSOP_func occludedSOP)
- : intersectAOS(intersectAOS), intersectAOP(intersectAOP), intersectSOA(intersectSOA), intersectSOP(intersectSOP),
- occludedAOS(occludedAOS), occludedAOP(occludedAOP), occludedSOA(occludedSOA), occludedSOP(occludedSOP) {}
-
- public:
- intersectStreamAOS_func intersectAOS;
- intersectStreamAOP_func intersectAOP;
- intersectStreamSOA_func intersectSOA;
- intersectStreamSOP_func intersectSOP;
-
- occludedStreamAOS_func occludedAOS;
- occludedStreamAOP_func occludedAOP;
- occludedStreamSOA_func occludedSOA;
- occludedStreamSOP_func occludedSOP;
- };
-
- typedef RayStreamFilterFuncs (*RayStreamFilterFuncsType)();
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/accelinstance.h b/thirdparty/embree-aarch64/kernels/common/accelinstance.h
deleted file mode 100644
index d74b96df3f..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/accelinstance.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "accel.h"
-#include "builder.h"
-
-namespace embree
-{
- class AccelInstance : public Accel
- {
- public:
- AccelInstance (AccelData* accel, Builder* builder, Intersectors& intersectors)
- : Accel(AccelData::TY_ACCEL_INSTANCE,intersectors), accel(accel), builder(builder) {}
-
- void immutable () {
- builder.reset(nullptr);
- }
-
- public:
- void build () {
- if (builder) builder->build();
- bounds = accel->bounds;
- }
-
- void deleteGeometry(size_t geomID) {
- if (accel ) accel->deleteGeometry(geomID);
- if (builder) builder->deleteGeometry(geomID);
- }
-
- void clear() {
- if (accel) accel->clear();
- if (builder) builder->clear();
- }
-
- private:
- std::unique_ptr<AccelData> accel;
- std::unique_ptr<Builder> builder;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/acceln.cpp b/thirdparty/embree-aarch64/kernels/common/acceln.cpp
deleted file mode 100644
index aadb4a64ef..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/acceln.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "acceln.h"
-#include "ray.h"
-#include "../../include/embree3/rtcore_ray.h"
-#include "../../common/algorithms/parallel_for.h"
-
-namespace embree
-{
- AccelN::AccelN()
- : Accel(AccelData::TY_ACCELN), accels() {}
-
- AccelN::~AccelN()
- {
- for (size_t i=0; i<accels.size(); i++)
- delete accels[i];
- }
-
- void AccelN::accels_add(Accel* accel)
- {
- assert(accel);
- accels.push_back(accel);
- }
-
- void AccelN::accels_init()
- {
- for (size_t i=0; i<accels.size(); i++)
- delete accels[i];
-
- accels.clear();
- }
-
- bool AccelN::pointQuery (Accel::Intersectors* This_in, PointQuery* query, PointQueryContext* context)
- {
- bool changed = false;
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++)
- if (!This->accels[i]->isEmpty())
- changed |= This->accels[i]->intersectors.pointQuery(query,context);
- return changed;
- }
-
- void AccelN::intersect (Accel::Intersectors* This_in, RTCRayHit& ray, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++)
- if (!This->accels[i]->isEmpty())
- This->accels[i]->intersectors.intersect(ray,context);
- }
-
- void AccelN::intersect4 (const void* valid, Accel::Intersectors* This_in, RTCRayHit4& ray, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++)
- if (!This->accels[i]->isEmpty())
- This->accels[i]->intersectors.intersect4(valid,ray,context);
- }
-
- void AccelN::intersect8 (const void* valid, Accel::Intersectors* This_in, RTCRayHit8& ray, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++)
- if (!This->accels[i]->isEmpty())
- This->accels[i]->intersectors.intersect8(valid,ray,context);
- }
-
- void AccelN::intersect16 (const void* valid, Accel::Intersectors* This_in, RTCRayHit16& ray, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++)
- if (!This->accels[i]->isEmpty())
- This->accels[i]->intersectors.intersect16(valid,ray,context);
- }
-
- void AccelN::intersectN (Accel::Intersectors* This_in, RTCRayHitN** ray, const size_t N, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++)
- if (!This->accels[i]->isEmpty())
- This->accels[i]->intersectors.intersectN(ray,N,context);
- }
-
- void AccelN::occluded (Accel::Intersectors* This_in, RTCRay& ray, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++) {
- if (This->accels[i]->isEmpty()) continue;
- This->accels[i]->intersectors.occluded(ray,context);
- if (ray.tfar < 0.0f) break;
- }
- }
-
- void AccelN::occluded4 (const void* valid, Accel::Intersectors* This_in, RTCRay4& ray, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++) {
- if (This->accels[i]->isEmpty()) continue;
- This->accels[i]->intersectors.occluded4(valid,ray,context);
-#if defined(__SSE2__) || defined(__ARM_NEON)
- vbool4 valid0 = asBool(((vint4*)valid)[0]);
- vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
- if (unlikely(none(valid0 & hit0))) break;
-#endif
- }
- }
-
- void AccelN::occluded8 (const void* valid, Accel::Intersectors* This_in, RTCRay8& ray, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++) {
- if (This->accels[i]->isEmpty()) continue;
- This->accels[i]->intersectors.occluded8(valid,ray,context);
-#if defined(__SSE2__) || defined(__ARM_NEON) // FIXME: use higher ISA
- vbool4 valid0 = asBool(((vint4*)valid)[0]);
- vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
- vbool4 valid1 = asBool(((vint4*)valid)[1]);
- vbool4 hit1 = ((vfloat4*)ray.tfar)[1] >= vfloat4(zero);
- if (unlikely((none((valid0 & hit0) | (valid1 & hit1))))) break;
-#endif
- }
- }
-
- void AccelN::occluded16 (const void* valid, Accel::Intersectors* This_in, RTCRay16& ray, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- for (size_t i=0; i<This->accels.size(); i++) {
- if (This->accels[i]->isEmpty()) continue;
- This->accels[i]->intersectors.occluded16(valid,ray,context);
-#if defined(__SSE2__) || defined(__ARM_NEON) // FIXME: use higher ISA
- vbool4 valid0 = asBool(((vint4*)valid)[0]);
- vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
- vbool4 valid1 = asBool(((vint4*)valid)[1]);
- vbool4 hit1 = ((vfloat4*)ray.tfar)[1] >= vfloat4(zero);
- vbool4 valid2 = asBool(((vint4*)valid)[2]);
- vbool4 hit2 = ((vfloat4*)ray.tfar)[2] >= vfloat4(zero);
- vbool4 valid3 = asBool(((vint4*)valid)[3]);
- vbool4 hit3 = ((vfloat4*)ray.tfar)[3] >= vfloat4(zero);
- if (unlikely((none((valid0 & hit0) | (valid1 & hit1) | (valid2 & hit2) | (valid3 & hit3))))) break;
-#endif
- }
- }
-
- void AccelN::occludedN (Accel::Intersectors* This_in, RTCRayN** ray, const size_t N, IntersectContext* context)
- {
- AccelN* This = (AccelN*)This_in->ptr;
- size_t M = N;
- for (size_t i=0; i<This->accels.size(); i++)
- if (!This->accels[i]->isEmpty())
- This->accels[i]->intersectors.occludedN(ray,M,context);
- }
-
- void AccelN::accels_print(size_t ident)
- {
- for (size_t i=0; i<accels.size(); i++)
- {
- for (size_t j=0; j<ident; j++) std::cout << " ";
- std::cout << "accels[" << i << "]" << std::endl;
- accels[i]->intersectors.print(ident+2);
- }
- }
-
- void AccelN::accels_immutable()
- {
- for (size_t i=0; i<accels.size(); i++)
- accels[i]->immutable();
- }
-
- void AccelN::accels_build ()
- {
- /* reduce memory consumption */
- accels.shrink_to_fit();
-
- /* build all acceleration structures in parallel */
- parallel_for (accels.size(), [&] (size_t i) {
- accels[i]->build();
- });
-
- /* create list of non-empty acceleration structures */
- bool valid1 = true;
- bool valid4 = true;
- bool valid8 = true;
- bool valid16 = true;
- for (size_t i=0; i<accels.size(); i++) {
- valid1 &= (bool) accels[i]->intersectors.intersector1;
- valid4 &= (bool) accels[i]->intersectors.intersector4;
- valid8 &= (bool) accels[i]->intersectors.intersector8;
- valid16 &= (bool) accels[i]->intersectors.intersector16;
- }
-
- if (accels.size() == 1) {
- type = accels[0]->type; // FIXME: should just assign entire Accel
- bounds = accels[0]->bounds;
- intersectors = accels[0]->intersectors;
- }
- else
- {
- type = AccelData::TY_ACCELN;
- intersectors.ptr = this;
- intersectors.intersector1 = Intersector1(&intersect,&occluded,&pointQuery,valid1 ? "AccelN::intersector1": nullptr);
- intersectors.intersector4 = Intersector4(&intersect4,&occluded4,valid4 ? "AccelN::intersector4" : nullptr);
- intersectors.intersector8 = Intersector8(&intersect8,&occluded8,valid8 ? "AccelN::intersector8" : nullptr);
- intersectors.intersector16 = Intersector16(&intersect16,&occluded16,valid16 ? "AccelN::intersector16": nullptr);
- intersectors.intersectorN = IntersectorN(&intersectN,&occludedN,"AccelN::intersectorN");
-
- /*! calculate bounds */
- bounds = empty;
- for (size_t i=0; i<accels.size(); i++)
- bounds.extend(accels[i]->bounds);
- }
- }
-
- void AccelN::accels_select(bool filter)
- {
- for (size_t i=0; i<accels.size(); i++)
- accels[i]->intersectors.select(filter);
- }
-
- void AccelN::accels_deleteGeometry(size_t geomID)
- {
- for (size_t i=0; i<accels.size(); i++)
- accels[i]->deleteGeometry(geomID);
- }
-
- void AccelN::accels_clear()
- {
- for (size_t i=0; i<accels.size(); i++) {
- accels[i]->clear();
- }
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/common/acceln.h b/thirdparty/embree-aarch64/kernels/common/acceln.h
deleted file mode 100644
index 2edd98f647..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/acceln.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "accel.h"
-
-namespace embree
-{
- /*! merges N acceleration structures together, by processing them in order */
- class AccelN : public Accel
- {
- public:
- AccelN ();
- ~AccelN();
-
- public:
- void accels_add(Accel* accel);
- void accels_init();
-
- public:
- static bool pointQuery (Accel::Intersectors* This, PointQuery* query, PointQueryContext* context);
-
- public:
- static void intersect (Accel::Intersectors* This, RTCRayHit& ray, IntersectContext* context);
- static void intersect4 (const void* valid, Accel::Intersectors* This, RTCRayHit4& ray, IntersectContext* context);
- static void intersect8 (const void* valid, Accel::Intersectors* This, RTCRayHit8& ray, IntersectContext* context);
- static void intersect16 (const void* valid, Accel::Intersectors* This, RTCRayHit16& ray, IntersectContext* context);
- static void intersectN (Accel::Intersectors* This, RTCRayHitN** ray, const size_t N, IntersectContext* context);
-
- public:
- static void occluded (Accel::Intersectors* This, RTCRay& ray, IntersectContext* context);
- static void occluded4 (const void* valid, Accel::Intersectors* This, RTCRay4& ray, IntersectContext* context);
- static void occluded8 (const void* valid, Accel::Intersectors* This, RTCRay8& ray, IntersectContext* context);
- static void occluded16 (const void* valid, Accel::Intersectors* This, RTCRay16& ray, IntersectContext* context);
- static void occludedN (Accel::Intersectors* This, RTCRayN** ray, const size_t N, IntersectContext* context);
-
- public:
- void accels_print(size_t ident);
- void accels_immutable();
- void accels_build ();
- void accels_select(bool filter);
- void accels_deleteGeometry(size_t geomID);
- void accels_clear ();
-
- public:
- std::vector<Accel*> accels;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/accelset.cpp b/thirdparty/embree-aarch64/kernels/common/accelset.cpp
deleted file mode 100644
index 79be1c4301..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/accelset.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "accelset.h"
-#include "scene.h"
-
-namespace embree
-{
- AccelSet::AccelSet (Device* device, Geometry::GType gtype, size_t numItems, size_t numTimeSteps)
- : Geometry(device,gtype,(unsigned int)numItems,(unsigned int)numTimeSteps), boundsFunc(nullptr) {}
-
- AccelSet::IntersectorN::IntersectorN (ErrorFunc error)
- : intersect((IntersectFuncN)error), occluded((OccludedFuncN)error), name(nullptr) {}
-
- AccelSet::IntersectorN::IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name)
- : intersect(intersect), occluded(occluded), name(name) {}
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/accelset.h b/thirdparty/embree-aarch64/kernels/common/accelset.h
deleted file mode 100644
index 3774b2accb..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/accelset.h
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "builder.h"
-#include "geometry.h"
-#include "ray.h"
-#include "hit.h"
-
-namespace embree
-{
- struct IntersectFunctionNArguments;
- struct OccludedFunctionNArguments;
-
- typedef void (*ReportIntersectionFunc) (IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
- typedef void (*ReportOcclusionFunc) (OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
-
- struct IntersectFunctionNArguments : public RTCIntersectFunctionNArguments
- {
- IntersectContext* internal_context;
- Geometry* geometry;
- ReportIntersectionFunc report;
- };
-
- struct OccludedFunctionNArguments : public RTCOccludedFunctionNArguments
- {
- IntersectContext* internal_context;
- Geometry* geometry;
- ReportOcclusionFunc report;
- };
-
- /*! Base class for set of acceleration structures. */
- class AccelSet : public Geometry
- {
- public:
- typedef RTCIntersectFunctionN IntersectFuncN;
- typedef RTCOccludedFunctionN OccludedFuncN;
- typedef void (*ErrorFunc) ();
-
- struct IntersectorN
- {
- IntersectorN (ErrorFunc error = nullptr) ;
- IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name);
-
- operator bool() const { return name; }
-
- public:
- static const char* type;
- IntersectFuncN intersect;
- OccludedFuncN occluded;
- const char* name;
- };
-
- public:
-
- /*! construction */
- AccelSet (Device* device, Geometry::GType gtype, size_t items, size_t numTimeSteps);
-
- /*! makes the acceleration structure immutable */
- virtual void immutable () {}
-
- /*! build accel */
- virtual void build () = 0;
-
- /*! check if the i'th primitive is valid between the specified time range */
- __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
- {
- for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
- if (!isvalid_non_empty(bounds(i,itime))) return false;
-
- return true;
- }
-
- /*! Calculates the bounds of an item */
- __forceinline BBox3fa bounds(size_t i, size_t itime = 0) const
- {
- BBox3fa box;
- assert(i < size());
- RTCBoundsFunctionArguments args;
- args.geometryUserPtr = userPtr;
- args.primID = (unsigned int)i;
- args.timeStep = (unsigned int)itime;
- args.bounds_o = (RTCBounds*)&box;
- boundsFunc(&args);
- return box;
- }
-
- /*! calculates the linear bounds of the i'th item at the itime'th time segment */
- __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const
- {
- BBox3fa box[2];
- assert(i < size());
- RTCBoundsFunctionArguments args;
- args.geometryUserPtr = userPtr;
- args.primID = (unsigned int)i;
- args.timeStep = (unsigned int)(itime+0);
- args.bounds_o = (RTCBounds*)&box[0];
- boundsFunc(&args);
- args.timeStep = (unsigned int)(itime+1);
- args.bounds_o = (RTCBounds*)&box[1];
- boundsFunc(&args);
- return LBBox3fa(box[0],box[1]);
- }
-
- /*! calculates the build bounds of the i'th item, if it's valid */
- __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
- {
- const BBox3fa b = bounds(i);
- if (bbox) *bbox = b;
- return isvalid_non_empty(b);
- }
-
- /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
- __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
- {
- const LBBox3fa bounds = linearBounds(i,itime);
- bbox = bounds.bounds0; // use bounding box of first timestep to build BVH
- return isvalid_non_empty(bounds);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
- return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const {
- if (!valid(i, timeSegmentRange(time_range))) return false;
- bbox = linearBounds(i, time_range);
- return true;
- }
-
- /* gets version info of topology */
- unsigned int getTopologyVersion() const {
- return numPrimitives;
- }
-
- /* returns true if topology changed */
- bool topologyChanged(unsigned int otherVersion) const {
- return numPrimitives != otherVersion;
- }
-
- public:
-
- /*! Intersects a single ray with the scene. */
- __forceinline void intersect (RayHit& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
- {
- assert(primID < size());
- assert(intersectorN.intersect);
-
- int mask = -1;
- IntersectFunctionNArguments args;
- args.valid = &mask;
- args.geometryUserPtr = userPtr;
- args.context = context->user;
- args.rayhit = (RTCRayHitN*)&ray;
- args.N = 1;
- args.geomID = geomID;
- args.primID = primID;
- args.internal_context = context;
- args.geometry = this;
- args.report = report;
-
- intersectorN.intersect(&args);
- }
-
- /*! Tests if single ray is occluded by the scene. */
- __forceinline void occluded (Ray& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
- {
- assert(primID < size());
- assert(intersectorN.occluded);
-
- int mask = -1;
- OccludedFunctionNArguments args;
- args.valid = &mask;
- args.geometryUserPtr = userPtr;
- args.context = context->user;
- args.ray = (RTCRayN*)&ray;
- args.N = 1;
- args.geomID = geomID;
- args.primID = primID;
- args.internal_context = context;
- args.geometry = this;
- args.report = report;
-
- intersectorN.occluded(&args);
- }
-
- /*! Intersects a packet of K rays with the scene. */
- template<int K>
- __forceinline void intersect (const vbool<K>& valid, RayHitK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
- {
- assert(primID < size());
- assert(intersectorN.intersect);
-
- vint<K> mask = valid.mask32();
- IntersectFunctionNArguments args;
- args.valid = (int*)&mask;
- args.geometryUserPtr = userPtr;
- args.context = context->user;
- args.rayhit = (RTCRayHitN*)&ray;
- args.N = K;
- args.geomID = geomID;
- args.primID = primID;
- args.internal_context = context;
- args.geometry = this;
- args.report = report;
-
- intersectorN.intersect(&args);
- }
-
- /*! Tests if a packet of K rays is occluded by the scene. */
- template<int K>
- __forceinline void occluded (const vbool<K>& valid, RayK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
- {
- assert(primID < size());
- assert(intersectorN.occluded);
-
- vint<K> mask = valid.mask32();
- OccludedFunctionNArguments args;
- args.valid = (int*)&mask;
- args.geometryUserPtr = userPtr;
- args.context = context->user;
- args.ray = (RTCRayN*)&ray;
- args.N = K;
- args.geomID = geomID;
- args.primID = primID;
- args.internal_context = context;
- args.geometry = this;
- args.report = report;
-
- intersectorN.occluded(&args);
- }
-
- public:
- RTCBoundsFunction boundsFunc;
- IntersectorN intersectorN;
- };
-
-#define DEFINE_SET_INTERSECTORN(symbol,intersector) \
- AccelSet::IntersectorN symbol() { \
- return AccelSet::IntersectorN(intersector::intersect, \
- intersector::occluded, \
- TOSTRING(isa) "::" TOSTRING(symbol)); \
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/alloc.cpp b/thirdparty/embree-aarch64/kernels/common/alloc.cpp
deleted file mode 100644
index 6fa406f03a..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/alloc.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "alloc.h"
-#include "../../common/sys/thread.h"
-#if defined(__aarch64__) && defined(BUILD_IOS)
-#include "../../common/sys/barrier.h"
-#endif
-
-namespace embree
-{
- __thread FastAllocator::ThreadLocal2* FastAllocator::thread_local_allocator2 = nullptr;
- SpinLock FastAllocator::s_thread_local_allocators_lock;
- std::vector<std::unique_ptr<FastAllocator::ThreadLocal2>> FastAllocator::s_thread_local_allocators;
-
- struct fast_allocator_regression_test : public RegressionTest
- {
- BarrierSys barrier;
- std::atomic<size_t> numFailed;
- std::unique_ptr<FastAllocator> alloc;
-
- fast_allocator_regression_test()
- : RegressionTest("fast_allocator_regression_test"), numFailed(0)
- {
- registerRegressionTest(this);
- }
-
- static void thread_alloc(fast_allocator_regression_test* This)
- {
- FastAllocator::CachedAllocator threadalloc = This->alloc->getCachedAllocator();
-
- size_t* ptrs[1000];
- for (size_t j=0; j<1000; j++)
- {
- This->barrier.wait();
- for (size_t i=0; i<1000; i++) {
- ptrs[i] = (size_t*) threadalloc.malloc0(sizeof(size_t)+(i%32));
- *ptrs[i] = size_t(threadalloc.talloc0) + i;
- }
- for (size_t i=0; i<1000; i++) {
- if (*ptrs[i] != size_t(threadalloc.talloc0) + i)
- This->numFailed++;
- }
- This->barrier.wait();
- }
- }
-
- bool run ()
- {
- alloc = make_unique(new FastAllocator(nullptr,false));
- numFailed.store(0);
-
- size_t numThreads = getNumberOfLogicalThreads();
- barrier.init(numThreads+1);
-
- /* create threads */
- std::vector<thread_t> threads;
- for (size_t i=0; i<numThreads; i++)
- threads.push_back(createThread((thread_func)thread_alloc,this));
-
- /* run test */
- for (size_t i=0; i<1000; i++)
- {
- alloc->reset();
- barrier.wait();
- barrier.wait();
- }
-
- /* destroy threads */
- for (size_t i=0; i<numThreads; i++)
- join(threads[i]);
-
- alloc = nullptr;
-
- return numFailed == 0;
- }
- };
-
- fast_allocator_regression_test fast_allocator_regression;
-}
-
-
diff --git a/thirdparty/embree-aarch64/kernels/common/alloc.h b/thirdparty/embree-aarch64/kernels/common/alloc.h
deleted file mode 100644
index 488fa707ef..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/alloc.h
+++ /dev/null
@@ -1,1006 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "device.h"
-#include "scene.h"
-#include "primref.h"
-
-#if defined(__aarch64__) && defined(BUILD_IOS)
-#include <mutex>
-#endif
-
-namespace embree
-{
- class FastAllocator
- {
- /*! maximum supported alignment */
- static const size_t maxAlignment = 64;
-
- /*! maximum allocation size */
-
- /* default settings */
- //static const size_t defaultBlockSize = 4096;
-#define maxAllocationSize size_t(2*1024*1024-maxAlignment)
-
- static const size_t MAX_THREAD_USED_BLOCK_SLOTS = 8;
-
- public:
-
- struct ThreadLocal2;
- enum AllocationType { ALIGNED_MALLOC, EMBREE_OS_MALLOC, SHARED, ANY_TYPE };
-
- /*! Per thread structure holding the current memory block. */
- struct __aligned(64) ThreadLocal
- {
- ALIGNED_CLASS_(64);
- public:
-
- /*! Constructor for usage with ThreadLocalData */
- __forceinline ThreadLocal (ThreadLocal2* parent)
- : parent(parent), ptr(nullptr), cur(0), end(0), allocBlockSize(0), bytesUsed(0), bytesWasted(0) {}
-
- /*! initialize allocator */
- void init(FastAllocator* alloc)
- {
- ptr = nullptr;
- cur = end = 0;
- bytesUsed = 0;
- bytesWasted = 0;
- allocBlockSize = 0;
- if (alloc) allocBlockSize = alloc->defaultBlockSize;
- }
-
- /* Allocate aligned memory from the threads memory block. */
- __forceinline void* malloc(FastAllocator* alloc, size_t bytes, size_t align = 16)
- {
- /* bind the thread local allocator to the proper FastAllocator*/
- parent->bind(alloc);
-
- assert(align <= maxAlignment);
- bytesUsed += bytes;
-
- /* try to allocate in local block */
- size_t ofs = (align - cur) & (align-1);
- cur += bytes + ofs;
- if (likely(cur <= end)) { bytesWasted += ofs; return &ptr[cur - bytes]; }
- cur -= bytes + ofs;
-
- /* if allocation is too large allocate with parent allocator */
- if (4*bytes > allocBlockSize) {
- return alloc->malloc(bytes,maxAlignment,false);
- }
-
- /* get new partial block if allocation failed */
- size_t blockSize = allocBlockSize;
- ptr = (char*) alloc->malloc(blockSize,maxAlignment,true);
- bytesWasted += end-cur;
- cur = 0; end = blockSize;
-
- /* retry allocation */
- ofs = (align - cur) & (align-1);
- cur += bytes + ofs;
- if (likely(cur <= end)) { bytesWasted += ofs; return &ptr[cur - bytes]; }
- cur -= bytes + ofs;
-
- /* get new full block if allocation failed */
- blockSize = allocBlockSize;
- ptr = (char*) alloc->malloc(blockSize,maxAlignment,false);
- bytesWasted += end-cur;
- cur = 0; end = blockSize;
-
- /* retry allocation */
- ofs = (align - cur) & (align-1);
- cur += bytes + ofs;
- if (likely(cur <= end)) { bytesWasted += ofs; return &ptr[cur - bytes]; }
- cur -= bytes + ofs;
-
- /* should never happen as large allocations get handled specially above */
- assert(false);
- return nullptr;
- }
-
-
- /*! returns amount of used bytes */
- __forceinline size_t getUsedBytes() const { return bytesUsed; }
-
- /*! returns amount of free bytes */
- __forceinline size_t getFreeBytes() const { return end-cur; }
-
- /*! returns amount of wasted bytes */
- __forceinline size_t getWastedBytes() const { return bytesWasted; }
-
- private:
- ThreadLocal2* parent;
- char* ptr; //!< pointer to memory block
- size_t cur; //!< current location of the allocator
- size_t end; //!< end of the memory block
- size_t allocBlockSize; //!< block size for allocations
- size_t bytesUsed; //!< number of total bytes allocated
- size_t bytesWasted; //!< number of bytes wasted
- };
-
- /*! Two thread local structures. */
- struct __aligned(64) ThreadLocal2
- {
- ALIGNED_CLASS_(64);
- public:
-
- __forceinline ThreadLocal2()
- : alloc(nullptr), alloc0(this), alloc1(this) {}
-
- /*! bind to fast allocator */
- __forceinline void bind(FastAllocator* alloc_i)
- {
- assert(alloc_i);
- if (alloc.load() == alloc_i) return;
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(mutex);
-#else
- Lock<SpinLock> lock(mutex);
-#endif
- //if (alloc.load() == alloc_i) return; // not required as only one thread calls bind
- if (alloc.load()) {
- alloc.load()->bytesUsed += alloc0.getUsedBytes() + alloc1.getUsedBytes();
- alloc.load()->bytesFree += alloc0.getFreeBytes() + alloc1.getFreeBytes();
- alloc.load()->bytesWasted += alloc0.getWastedBytes() + alloc1.getWastedBytes();
- }
- alloc0.init(alloc_i);
- alloc1.init(alloc_i);
- alloc.store(alloc_i);
- alloc_i->join(this);
- }
-
- /*! unbind to fast allocator */
- void unbind(FastAllocator* alloc_i)
- {
- assert(alloc_i);
- if (alloc.load() != alloc_i) return;
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(mutex);
-#else
- Lock<SpinLock> lock(mutex);
-#endif
- if (alloc.load() != alloc_i) return; // required as a different thread calls unbind
- alloc.load()->bytesUsed += alloc0.getUsedBytes() + alloc1.getUsedBytes();
- alloc.load()->bytesFree += alloc0.getFreeBytes() + alloc1.getFreeBytes();
- alloc.load()->bytesWasted += alloc0.getWastedBytes() + alloc1.getWastedBytes();
- alloc0.init(nullptr);
- alloc1.init(nullptr);
- alloc.store(nullptr);
- }
-
- public:
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::mutex mutex;
-#else
- SpinLock mutex; //!< required as unbind is called from other threads
-#endif
- std::atomic<FastAllocator*> alloc; //!< parent allocator
- ThreadLocal alloc0;
- ThreadLocal alloc1;
- };
-
- FastAllocator (Device* device, bool osAllocation)
- : device(device), slotMask(0), usedBlocks(nullptr), freeBlocks(nullptr), use_single_mode(false), defaultBlockSize(PAGE_SIZE), estimatedSize(0),
- growSize(PAGE_SIZE), maxGrowSize(maxAllocationSize), log2_grow_size_scale(0), bytesUsed(0), bytesFree(0), bytesWasted(0), atype(osAllocation ? EMBREE_OS_MALLOC : ALIGNED_MALLOC),
- primrefarray(device,0)
- {
- for (size_t i=0; i<MAX_THREAD_USED_BLOCK_SLOTS; i++)
- {
- threadUsedBlocks[i] = nullptr;
- threadBlocks[i] = nullptr;
- assert(!slotMutex[i].isLocked());
- }
- }
-
- ~FastAllocator () {
- clear();
- }
-
- /*! returns the device attached to this allocator */
- Device* getDevice() {
- return device;
- }
-
- void share(mvector<PrimRef>& primrefarray_i) {
- primrefarray = std::move(primrefarray_i);
- }
-
- void unshare(mvector<PrimRef>& primrefarray_o)
- {
- reset(); // this removes blocks that are allocated inside the shared primref array
- primrefarray_o = std::move(primrefarray);
- }
-
- /*! returns first fast thread local allocator */
- __forceinline ThreadLocal* _threadLocal() {
- return &threadLocal2()->alloc0;
- }
-
- void setOSallocation(bool flag)
- {
- atype = flag ? EMBREE_OS_MALLOC : ALIGNED_MALLOC;
- }
-
- private:
-
- /*! returns both fast thread local allocators */
- __forceinline ThreadLocal2* threadLocal2()
- {
- ThreadLocal2* alloc = thread_local_allocator2;
- if (alloc == nullptr) {
- thread_local_allocator2 = alloc = new ThreadLocal2;
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(s_thread_local_allocators_lock);
-#else
- Lock<SpinLock> lock(s_thread_local_allocators_lock);
-#endif
- s_thread_local_allocators.push_back(make_unique(alloc));
- }
- return alloc;
- }
-
- public:
-
- __forceinline void join(ThreadLocal2* alloc)
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(s_thread_local_allocators_lock);
-#else
- Lock<SpinLock> lock(thread_local_allocators_lock);
-#endif
- thread_local_allocators.push_back(alloc);
- }
-
- public:
-
- struct CachedAllocator
- {
- __forceinline CachedAllocator(void* ptr)
- : alloc(nullptr), talloc0(nullptr), talloc1(nullptr)
- {
- assert(ptr == nullptr);
- }
-
- __forceinline CachedAllocator(FastAllocator* alloc, ThreadLocal2* talloc)
- : alloc(alloc), talloc0(&talloc->alloc0), talloc1(alloc->use_single_mode ? &talloc->alloc0 : &talloc->alloc1) {}
-
- __forceinline operator bool () const {
- return alloc != nullptr;
- }
-
- __forceinline void* operator() (size_t bytes, size_t align = 16) const {
- return talloc0->malloc(alloc,bytes,align);
- }
-
- __forceinline void* malloc0 (size_t bytes, size_t align = 16) const {
- return talloc0->malloc(alloc,bytes,align);
- }
-
- __forceinline void* malloc1 (size_t bytes, size_t align = 16) const {
- return talloc1->malloc(alloc,bytes,align);
- }
-
- public:
- FastAllocator* alloc;
- ThreadLocal* talloc0;
- ThreadLocal* talloc1;
- };
-
- __forceinline CachedAllocator getCachedAllocator() {
- return CachedAllocator(this,threadLocal2());
- }
-
- /*! Builder interface to create thread local allocator */
- struct Create
- {
- public:
- __forceinline Create (FastAllocator* allocator) : allocator(allocator) {}
- __forceinline CachedAllocator operator() () const { return allocator->getCachedAllocator(); }
-
- private:
- FastAllocator* allocator;
- };
-
- void internal_fix_used_blocks()
- {
- /* move thread local blocks to global block list */
- for (size_t i = 0; i < MAX_THREAD_USED_BLOCK_SLOTS; i++)
- {
- while (threadBlocks[i].load() != nullptr) {
- Block* nextUsedBlock = threadBlocks[i].load()->next;
- threadBlocks[i].load()->next = usedBlocks.load();
- usedBlocks = threadBlocks[i].load();
- threadBlocks[i] = nextUsedBlock;
- }
- threadBlocks[i] = nullptr;
- }
- }
-
- static const size_t threadLocalAllocOverhead = 20; //! 20 means 5% parallel allocation overhead through unfilled thread local blocks
-#if defined(__AVX512ER__) // KNL
- static const size_t mainAllocOverheadStatic = 15; //! 15 means 7.5% allocation overhead through unfilled main alloc blocks
-#else
- static const size_t mainAllocOverheadStatic = 20; //! 20 means 5% allocation overhead through unfilled main alloc blocks
-#endif
- static const size_t mainAllocOverheadDynamic = 8; //! 20 means 12.5% allocation overhead through unfilled main alloc blocks
-
- /* calculates a single threaded threshold for the builders such
- * that for small scenes the overhead of partly allocated blocks
- * per thread is low */
- size_t fixSingleThreadThreshold(size_t branchingFactor, size_t defaultThreshold, size_t numPrimitives, size_t bytesEstimated)
- {
- if (numPrimitives == 0 || bytesEstimated == 0)
- return defaultThreshold;
-
- /* calculate block size in bytes to fulfill threadLocalAllocOverhead constraint */
- const size_t single_mode_factor = use_single_mode ? 1 : 2;
- const size_t threadCount = TaskScheduler::threadCount();
- const size_t singleThreadBytes = single_mode_factor*threadLocalAllocOverhead*defaultBlockSize;
-
- /* if we do not have to limit number of threads use optimal thresdhold */
- if ( (bytesEstimated+(singleThreadBytes-1))/singleThreadBytes >= threadCount)
- return defaultThreshold;
-
- /* otherwise limit number of threads by calculating proper single thread threshold */
- else {
- double bytesPerPrimitive = double(bytesEstimated)/double(numPrimitives);
- return size_t(ceil(branchingFactor*singleThreadBytes/bytesPerPrimitive));
- }
- }
-
- __forceinline size_t alignSize(size_t i) {
- return (i+127)/128*128;
- }
-
- /*! initializes the grow size */
- __forceinline void initGrowSizeAndNumSlots(size_t bytesEstimated, bool fast)
- {
- /* we do not need single thread local allocator mode */
- use_single_mode = false;
-
- /* calculate growSize such that at most mainAllocationOverhead gets wasted when a block stays unused */
- size_t mainAllocOverhead = fast ? mainAllocOverheadDynamic : mainAllocOverheadStatic;
- size_t blockSize = alignSize(bytesEstimated/mainAllocOverhead);
- growSize = maxGrowSize = clamp(blockSize,size_t(1024),maxAllocationSize);
-
- /* if we reached the maxAllocationSize for growSize, we can
- * increase the number of allocation slots by still guaranteeing
- * the mainAllocationOverhead */
- slotMask = 0x0;
-
- if (MAX_THREAD_USED_BLOCK_SLOTS >= 2 && bytesEstimated > 2*mainAllocOverhead*growSize) slotMask = 0x1;
- if (MAX_THREAD_USED_BLOCK_SLOTS >= 4 && bytesEstimated > 4*mainAllocOverhead*growSize) slotMask = 0x3;
- if (MAX_THREAD_USED_BLOCK_SLOTS >= 8 && bytesEstimated > 8*mainAllocOverhead*growSize) slotMask = 0x7;
- if (MAX_THREAD_USED_BLOCK_SLOTS >= 8 && bytesEstimated > 16*mainAllocOverhead*growSize) { growSize *= 2; } /* if the overhead is tiny, double the growSize */
-
- /* set the thread local alloc block size */
- size_t defaultBlockSizeSwitch = PAGE_SIZE+maxAlignment;
-
- /* for sufficiently large scene we can increase the defaultBlockSize over the defaultBlockSizeSwitch size */
-#if 0 // we do not do this as a block size of 4160 if for some reason best for KNL
- const size_t threadCount = TaskScheduler::threadCount();
- const size_t single_mode_factor = use_single_mode ? 1 : 2;
- const size_t singleThreadBytes = single_mode_factor*threadLocalAllocOverhead*defaultBlockSizeSwitch;
- if (bytesEstimated+(singleThreadBytes-1))/singleThreadBytes >= threadCount)
- defaultBlockSize = min(max(defaultBlockSizeSwitch,bytesEstimated/(single_mode_factor*threadLocalAllocOverhead*threadCount)),growSize);
-
- /* otherwise we grow the defaultBlockSize up to defaultBlockSizeSwitch */
- else
-#endif
- defaultBlockSize = clamp(blockSize,size_t(1024),defaultBlockSizeSwitch);
-
- if (bytesEstimated == 0) {
- maxGrowSize = maxAllocationSize; // special mode if builder cannot estimate tree size
- defaultBlockSize = defaultBlockSizeSwitch;
- }
- log2_grow_size_scale = 0;
-
- if (device->alloc_main_block_size != 0) growSize = device->alloc_main_block_size;
- if (device->alloc_num_main_slots >= 1 ) slotMask = 0x0;
- if (device->alloc_num_main_slots >= 2 ) slotMask = 0x1;
- if (device->alloc_num_main_slots >= 4 ) slotMask = 0x3;
- if (device->alloc_num_main_slots >= 8 ) slotMask = 0x7;
- if (device->alloc_thread_block_size != 0) defaultBlockSize = device->alloc_thread_block_size;
- if (device->alloc_single_thread_alloc != -1) use_single_mode = device->alloc_single_thread_alloc;
- }
-
- /*! initializes the allocator */
- void init(size_t bytesAllocate, size_t bytesReserve, size_t bytesEstimate)
- {
- internal_fix_used_blocks();
- /* distribute the allocation to multiple thread block slots */
- slotMask = MAX_THREAD_USED_BLOCK_SLOTS-1; // FIXME: remove
- if (usedBlocks.load() || freeBlocks.load()) { reset(); return; }
- if (bytesReserve == 0) bytesReserve = bytesAllocate;
- freeBlocks = Block::create(device,bytesAllocate,bytesReserve,nullptr,atype);
- estimatedSize = bytesEstimate;
- initGrowSizeAndNumSlots(bytesEstimate,true);
- }
-
- /*! initializes the allocator */
- void init_estimate(size_t bytesEstimate)
- {
- internal_fix_used_blocks();
- if (usedBlocks.load() || freeBlocks.load()) { reset(); return; }
- /* single allocator mode ? */
- estimatedSize = bytesEstimate;
- //initGrowSizeAndNumSlots(bytesEstimate,false);
- initGrowSizeAndNumSlots(bytesEstimate,false);
-
- }
-
- /*! frees state not required after build */
- __forceinline void cleanup()
- {
- internal_fix_used_blocks();
-
- /* unbind all thread local allocators */
- for (auto alloc : thread_local_allocators) alloc->unbind(this);
- thread_local_allocators.clear();
- }
-
- /*! resets the allocator, memory blocks get reused */
- void reset ()
- {
- internal_fix_used_blocks();
-
- bytesUsed.store(0);
- bytesFree.store(0);
- bytesWasted.store(0);
-
- /* reset all used blocks and move them to begin of free block list */
- while (usedBlocks.load() != nullptr) {
- usedBlocks.load()->reset_block();
- Block* nextUsedBlock = usedBlocks.load()->next;
- usedBlocks.load()->next = freeBlocks.load();
- freeBlocks = usedBlocks.load();
- usedBlocks = nextUsedBlock;
- }
-
- /* remove all shared blocks as they are re-added during build */
- freeBlocks.store(Block::remove_shared_blocks(freeBlocks.load()));
-
- for (size_t i=0; i<MAX_THREAD_USED_BLOCK_SLOTS; i++)
- {
- threadUsedBlocks[i] = nullptr;
- threadBlocks[i] = nullptr;
- }
-
- /* unbind all thread local allocators */
- for (auto alloc : thread_local_allocators) alloc->unbind(this);
- thread_local_allocators.clear();
- }
-
- /*! frees all allocated memory */
- __forceinline void clear()
- {
- cleanup();
- bytesUsed.store(0);
- bytesFree.store(0);
- bytesWasted.store(0);
- if (usedBlocks.load() != nullptr) usedBlocks.load()->clear_list(device); usedBlocks = nullptr;
- if (freeBlocks.load() != nullptr) freeBlocks.load()->clear_list(device); freeBlocks = nullptr;
- for (size_t i=0; i<MAX_THREAD_USED_BLOCK_SLOTS; i++) {
- threadUsedBlocks[i] = nullptr;
- threadBlocks[i] = nullptr;
- }
- primrefarray.clear();
- }
-
- __forceinline size_t incGrowSizeScale()
- {
- size_t scale = log2_grow_size_scale.fetch_add(1)+1;
- return size_t(1) << min(size_t(16),scale);
- }
-
- /*! thread safe allocation of memory */
- void* malloc(size_t& bytes, size_t align, bool partial)
- {
- assert(align <= maxAlignment);
-
- while (true)
- {
- /* allocate using current block */
- size_t threadID = TaskScheduler::threadID();
- size_t slot = threadID & slotMask;
- Block* myUsedBlocks = threadUsedBlocks[slot];
- if (myUsedBlocks) {
- void* ptr = myUsedBlocks->malloc(device,bytes,align,partial);
- if (ptr) return ptr;
- }
-
- /* throw error if allocation is too large */
- if (bytes > maxAllocationSize)
- throw_RTCError(RTC_ERROR_UNKNOWN,"allocation is too large");
-
- /* parallel block creation in case of no freeBlocks, avoids single global mutex */
- if (likely(freeBlocks.load() == nullptr))
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(slotMutex[slot]);
-#else
- Lock<SpinLock> lock(slotMutex[slot]);
-#endif
- if (myUsedBlocks == threadUsedBlocks[slot]) {
- const size_t alignedBytes = (bytes+(align-1)) & ~(align-1);
- const size_t allocSize = max(min(growSize,maxGrowSize),alignedBytes);
- assert(allocSize >= bytes);
- threadBlocks[slot] = threadUsedBlocks[slot] = Block::create(device,allocSize,allocSize,threadBlocks[slot],atype); // FIXME: a large allocation might throw away a block here!
- // FIXME: a direct allocation should allocate inside the block here, and not in the next loop! a different thread could do some allocation and make the large allocation fail.
- }
- continue;
- }
-
- /* if this fails allocate new block */
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(mutex);
-#else
- Lock<SpinLock> lock(mutex);
-#endif
- if (myUsedBlocks == threadUsedBlocks[slot])
- {
- if (freeBlocks.load() != nullptr) {
- Block* nextFreeBlock = freeBlocks.load()->next;
- freeBlocks.load()->next = usedBlocks;
- __memory_barrier();
- usedBlocks = freeBlocks.load();
- threadUsedBlocks[slot] = freeBlocks.load();
- freeBlocks = nextFreeBlock;
- } else {
- const size_t allocSize = min(growSize*incGrowSizeScale(),maxGrowSize);
- usedBlocks = threadUsedBlocks[slot] = Block::create(device,allocSize,allocSize,usedBlocks,atype); // FIXME: a large allocation should get delivered directly, like above!
- }
- }
- }
- }
- }
-
- /*! add new block */
- void addBlock(void* ptr, ssize_t bytes)
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(mutex);
-#else
- Lock<SpinLock> lock(mutex);
-#endif
- const size_t sizeof_Header = offsetof(Block,data[0]);
- void* aptr = (void*) ((((size_t)ptr)+maxAlignment-1) & ~(maxAlignment-1));
- size_t ofs = (size_t) aptr - (size_t) ptr;
- bytes -= ofs;
- if (bytes < 4096) return; // ignore empty or very small blocks
- freeBlocks = new (aptr) Block(SHARED,bytes-sizeof_Header,bytes-sizeof_Header,freeBlocks,ofs);
- }
-
- /* special allocation only used from morton builder only a single time for each build */
- void* specialAlloc(size_t bytes)
- {
- assert(freeBlocks.load() != nullptr && freeBlocks.load()->getBlockAllocatedBytes() >= bytes);
- return freeBlocks.load()->ptr();
- }
-
- struct Statistics
- {
- Statistics ()
- : bytesUsed(0), bytesFree(0), bytesWasted(0) {}
-
- Statistics (size_t bytesUsed, size_t bytesFree, size_t bytesWasted)
- : bytesUsed(bytesUsed), bytesFree(bytesFree), bytesWasted(bytesWasted) {}
-
- Statistics (FastAllocator* alloc, AllocationType atype, bool huge_pages = false)
- : bytesUsed(0), bytesFree(0), bytesWasted(0)
- {
- Block* usedBlocks = alloc->usedBlocks.load();
- Block* freeBlocks = alloc->freeBlocks.load();
- if (usedBlocks) bytesUsed += usedBlocks->getUsedBytes(atype,huge_pages);
- if (freeBlocks) bytesFree += freeBlocks->getAllocatedBytes(atype,huge_pages);
- if (usedBlocks) bytesFree += usedBlocks->getFreeBytes(atype,huge_pages);
- if (freeBlocks) bytesWasted += freeBlocks->getWastedBytes(atype,huge_pages);
- if (usedBlocks) bytesWasted += usedBlocks->getWastedBytes(atype,huge_pages);
- }
-
- std::string str(size_t numPrimitives)
- {
- std::stringstream str;
- str.setf(std::ios::fixed, std::ios::floatfield);
- str << "used = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesUsed << " MB, "
- << "free = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesFree << " MB, "
- << "wasted = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesWasted << " MB, "
- << "total = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesAllocatedTotal() << " MB, "
- << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytesAllocatedTotal())/double(numPrimitives);
- return str.str();
- }
-
- friend Statistics operator+ ( const Statistics& a, const Statistics& b)
- {
- return Statistics(a.bytesUsed+b.bytesUsed,
- a.bytesFree+b.bytesFree,
- a.bytesWasted+b.bytesWasted);
- }
-
- size_t bytesAllocatedTotal() const {
- return bytesUsed + bytesFree + bytesWasted;
- }
-
- public:
- size_t bytesUsed;
- size_t bytesFree;
- size_t bytesWasted;
- };
-
- Statistics getStatistics(AllocationType atype, bool huge_pages = false) {
- return Statistics(this,atype,huge_pages);
- }
-
- size_t getUsedBytes() {
- return bytesUsed;
- }
-
- size_t getWastedBytes() {
- return bytesWasted;
- }
-
- struct AllStatistics
- {
- AllStatistics (FastAllocator* alloc)
-
- : bytesUsed(alloc->bytesUsed),
- bytesFree(alloc->bytesFree),
- bytesWasted(alloc->bytesWasted),
- stat_all(alloc,ANY_TYPE),
- stat_malloc(alloc,ALIGNED_MALLOC),
- stat_4K(alloc,EMBREE_OS_MALLOC,false),
- stat_2M(alloc,EMBREE_OS_MALLOC,true),
- stat_shared(alloc,SHARED) {}
-
- AllStatistics (size_t bytesUsed,
- size_t bytesFree,
- size_t bytesWasted,
- Statistics stat_all,
- Statistics stat_malloc,
- Statistics stat_4K,
- Statistics stat_2M,
- Statistics stat_shared)
-
- : bytesUsed(bytesUsed),
- bytesFree(bytesFree),
- bytesWasted(bytesWasted),
- stat_all(stat_all),
- stat_malloc(stat_malloc),
- stat_4K(stat_4K),
- stat_2M(stat_2M),
- stat_shared(stat_shared) {}
-
- friend AllStatistics operator+ (const AllStatistics& a, const AllStatistics& b)
- {
- return AllStatistics(a.bytesUsed+b.bytesUsed,
- a.bytesFree+b.bytesFree,
- a.bytesWasted+b.bytesWasted,
- a.stat_all + b.stat_all,
- a.stat_malloc + b.stat_malloc,
- a.stat_4K + b.stat_4K,
- a.stat_2M + b.stat_2M,
- a.stat_shared + b.stat_shared);
- }
-
- void print(size_t numPrimitives)
- {
- std::stringstream str0;
- str0.setf(std::ios::fixed, std::ios::floatfield);
- str0 << " alloc : "
- << "used = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesUsed << " MB, "
- << " "
- << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytesUsed)/double(numPrimitives);
- std::cout << str0.str() << std::endl;
-
- std::stringstream str1;
- str1.setf(std::ios::fixed, std::ios::floatfield);
- str1 << " alloc : "
- << "used = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesUsed << " MB, "
- << "free = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesFree << " MB, "
- << "wasted = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesWasted << " MB, "
- << "total = " << std::setw(7) << std::setprecision(3) << 1E-6f*(bytesUsed+bytesFree+bytesWasted) << " MB, "
- << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytesUsed+bytesFree+bytesWasted)/double(numPrimitives);
- std::cout << str1.str() << std::endl;
-
- std::cout << " total : " << stat_all.str(numPrimitives) << std::endl;
- std::cout << " 4K : " << stat_4K.str(numPrimitives) << std::endl;
- std::cout << " 2M : " << stat_2M.str(numPrimitives) << std::endl;
- std::cout << " malloc: " << stat_malloc.str(numPrimitives) << std::endl;
- std::cout << " shared: " << stat_shared.str(numPrimitives) << std::endl;
- }
-
- private:
- size_t bytesUsed;
- size_t bytesFree;
- size_t bytesWasted;
- Statistics stat_all;
- Statistics stat_malloc;
- Statistics stat_4K;
- Statistics stat_2M;
- Statistics stat_shared;
- };
-
- void print_blocks()
- {
- std::cout << " estimatedSize = " << estimatedSize << ", slotMask = " << slotMask << ", use_single_mode = " << use_single_mode << ", maxGrowSize = " << maxGrowSize << ", defaultBlockSize = " << defaultBlockSize << std::endl;
-
- std::cout << " used blocks = ";
- if (usedBlocks.load() != nullptr) usedBlocks.load()->print_list();
- std::cout << "[END]" << std::endl;
-
- std::cout << " free blocks = ";
- if (freeBlocks.load() != nullptr) freeBlocks.load()->print_list();
- std::cout << "[END]" << std::endl;
- }
-
- private:
-
- struct Block
- {
- static Block* create(MemoryMonitorInterface* device, size_t bytesAllocate, size_t bytesReserve, Block* next, AllocationType atype)
- {
- /* We avoid using os_malloc for small blocks as this could
- * cause a risk of fragmenting the virtual address space and
- * reach the limit of vm.max_map_count = 65k under Linux. */
- if (atype == EMBREE_OS_MALLOC && bytesAllocate < maxAllocationSize)
- atype = ALIGNED_MALLOC;
-
- /* we need to additionally allocate some header */
- const size_t sizeof_Header = offsetof(Block,data[0]);
- bytesAllocate = sizeof_Header+bytesAllocate;
- bytesReserve = sizeof_Header+bytesReserve;
-
- /* consume full 4k pages with using os_malloc */
- if (atype == EMBREE_OS_MALLOC) {
- bytesAllocate = ((bytesAllocate+PAGE_SIZE-1) & ~(PAGE_SIZE-1));
- bytesReserve = ((bytesReserve +PAGE_SIZE-1) & ~(PAGE_SIZE-1));
- }
-
- /* either use alignedMalloc or os_malloc */
- void *ptr = nullptr;
- if (atype == ALIGNED_MALLOC)
- {
- /* special handling for default block size */
- if (bytesAllocate == (2*PAGE_SIZE_2M))
- {
- const size_t alignment = maxAlignment;
- if (device) device->memoryMonitor(bytesAllocate+alignment,false);
- ptr = alignedMalloc(bytesAllocate,alignment);
-
- /* give hint to transparently convert these pages to 2MB pages */
- const size_t ptr_aligned_begin = ((size_t)ptr) & ~size_t(PAGE_SIZE_2M-1);
- os_advise((void*)(ptr_aligned_begin + 0),PAGE_SIZE_2M); // may fail if no memory mapped before block
- os_advise((void*)(ptr_aligned_begin + 1*PAGE_SIZE_2M),PAGE_SIZE_2M);
- os_advise((void*)(ptr_aligned_begin + 2*PAGE_SIZE_2M),PAGE_SIZE_2M); // may fail if no memory mapped after block
-
- return new (ptr) Block(ALIGNED_MALLOC,bytesAllocate-sizeof_Header,bytesAllocate-sizeof_Header,next,alignment);
- }
- else
- {
- const size_t alignment = maxAlignment;
- if (device) device->memoryMonitor(bytesAllocate+alignment,false);
- ptr = alignedMalloc(bytesAllocate,alignment);
- return new (ptr) Block(ALIGNED_MALLOC,bytesAllocate-sizeof_Header,bytesAllocate-sizeof_Header,next,alignment);
- }
- }
- else if (atype == EMBREE_OS_MALLOC)
- {
- if (device) device->memoryMonitor(bytesAllocate,false);
- bool huge_pages; ptr = os_malloc(bytesReserve,huge_pages);
- return new (ptr) Block(EMBREE_OS_MALLOC,bytesAllocate-sizeof_Header,bytesReserve-sizeof_Header,next,0,huge_pages);
- }
- else
- assert(false);
-
- return NULL;
- }
-
- Block (AllocationType atype, size_t bytesAllocate, size_t bytesReserve, Block* next, size_t wasted, bool huge_pages = false)
- : cur(0), allocEnd(bytesAllocate), reserveEnd(bytesReserve), next(next), wasted(wasted), atype(atype), huge_pages(huge_pages)
- {
- assert((((size_t)&data[0]) & (maxAlignment-1)) == 0);
- }
-
- static Block* remove_shared_blocks(Block* head)
- {
- Block** prev_next = &head;
- for (Block* block = head; block; block = block->next) {
- if (block->atype == SHARED) *prev_next = block->next;
- else prev_next = &block->next;
- }
- return head;
- }
-
- void clear_list(MemoryMonitorInterface* device)
- {
- Block* block = this;
- while (block) {
- Block* next = block->next;
- block->clear_block(device);
- block = next;
- }
- }
-
- void clear_block (MemoryMonitorInterface* device)
- {
- const size_t sizeof_Header = offsetof(Block,data[0]);
- const ssize_t sizeof_Alloced = wasted+sizeof_Header+getBlockAllocatedBytes();
-
- if (atype == ALIGNED_MALLOC) {
- alignedFree(this);
- if (device) device->memoryMonitor(-sizeof_Alloced,true);
- }
-
- else if (atype == EMBREE_OS_MALLOC) {
- size_t sizeof_This = sizeof_Header+reserveEnd;
- os_free(this,sizeof_This,huge_pages);
- if (device) device->memoryMonitor(-sizeof_Alloced,true);
- }
-
- else /* if (atype == SHARED) */ {
- }
- }
-
- void* malloc(MemoryMonitorInterface* device, size_t& bytes_in, size_t align, bool partial)
- {
- size_t bytes = bytes_in;
- assert(align <= maxAlignment);
- bytes = (bytes+(align-1)) & ~(align-1);
- if (unlikely(cur+bytes > reserveEnd && !partial)) return nullptr;
- const size_t i = cur.fetch_add(bytes);
- if (unlikely(i+bytes > reserveEnd && !partial)) return nullptr;
- if (unlikely(i > reserveEnd)) return nullptr;
- bytes_in = bytes = min(bytes,reserveEnd-i);
-
- if (i+bytes > allocEnd) {
- if (device) device->memoryMonitor(i+bytes-max(i,allocEnd),true);
- }
- return &data[i];
- }
-
- void* ptr() {
- return &data[cur];
- }
-
- void reset_block ()
- {
- allocEnd = max(allocEnd,(size_t)cur);
- cur = 0;
- }
-
- size_t getBlockUsedBytes() const {
- return min(size_t(cur),reserveEnd);
- }
-
- size_t getBlockFreeBytes() const {
- return getBlockAllocatedBytes() - getBlockUsedBytes();
- }
-
- size_t getBlockAllocatedBytes() const {
- return min(max(allocEnd,size_t(cur)),reserveEnd);
- }
-
- size_t getBlockWastedBytes() const {
- const size_t sizeof_Header = offsetof(Block,data[0]);
- return sizeof_Header + wasted;
- }
-
- size_t getBlockReservedBytes() const {
- return reserveEnd;
- }
-
- bool hasType(AllocationType atype_i, bool huge_pages_i) const
- {
- if (atype_i == ANY_TYPE ) return true;
- else if (atype == EMBREE_OS_MALLOC) return atype_i == atype && huge_pages_i == huge_pages;
- else return atype_i == atype;
- }
-
- size_t getUsedBytes(AllocationType atype, bool huge_pages = false) const {
- size_t bytes = 0;
- for (const Block* block = this; block; block = block->next) {
- if (!block->hasType(atype,huge_pages)) continue;
- bytes += block->getBlockUsedBytes();
- }
- return bytes;
- }
-
- size_t getFreeBytes(AllocationType atype, bool huge_pages = false) const {
- size_t bytes = 0;
- for (const Block* block = this; block; block = block->next) {
- if (!block->hasType(atype,huge_pages)) continue;
- bytes += block->getBlockFreeBytes();
- }
- return bytes;
- }
-
- size_t getWastedBytes(AllocationType atype, bool huge_pages = false) const {
- size_t bytes = 0;
- for (const Block* block = this; block; block = block->next) {
- if (!block->hasType(atype,huge_pages)) continue;
- bytes += block->getBlockWastedBytes();
- }
- return bytes;
- }
-
- size_t getAllocatedBytes(AllocationType atype, bool huge_pages = false) const {
- size_t bytes = 0;
- for (const Block* block = this; block; block = block->next) {
- if (!block->hasType(atype,huge_pages)) continue;
- bytes += block->getBlockAllocatedBytes();
- }
- return bytes;
- }
-
- void print_list ()
- {
- for (const Block* block = this; block; block = block->next)
- block->print_block();
- }
-
- void print_block() const
- {
- if (atype == ALIGNED_MALLOC) std::cout << "A";
- else if (atype == EMBREE_OS_MALLOC) std::cout << "O";
- else if (atype == SHARED) std::cout << "S";
- if (huge_pages) std::cout << "H";
- size_t bytesUsed = getBlockUsedBytes();
- size_t bytesFree = getBlockFreeBytes();
- size_t bytesWasted = getBlockWastedBytes();
- std::cout << "[" << bytesUsed << ", " << bytesFree << ", " << bytesWasted << "] ";
- }
-
- public:
- std::atomic<size_t> cur; //!< current location of the allocator
- std::atomic<size_t> allocEnd; //!< end of the allocated memory region
- std::atomic<size_t> reserveEnd; //!< end of the reserved memory region
- Block* next; //!< pointer to next block in list
- size_t wasted; //!< amount of memory wasted through block alignment
- AllocationType atype; //!< allocation mode of the block
- bool huge_pages; //!< whether the block uses huge pages
- char align[maxAlignment-5*sizeof(size_t)-sizeof(AllocationType)-sizeof(bool)]; //!< align data to maxAlignment
- char data[1]; //!< here starts memory to use for allocations
- };
-
- private:
- Device* device;
- SpinLock mutex;
- size_t slotMask;
- std::atomic<Block*> threadUsedBlocks[MAX_THREAD_USED_BLOCK_SLOTS];
- std::atomic<Block*> usedBlocks;
- std::atomic<Block*> freeBlocks;
-
- std::atomic<Block*> threadBlocks[MAX_THREAD_USED_BLOCK_SLOTS];
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::mutex slotMutex[MAX_THREAD_USED_BLOCK_SLOTS];
-#else
- SpinLock slotMutex[MAX_THREAD_USED_BLOCK_SLOTS];
-#endif
-
- bool use_single_mode;
- size_t defaultBlockSize;
- size_t estimatedSize;
- size_t growSize;
- size_t maxGrowSize;
- std::atomic<size_t> log2_grow_size_scale; //!< log2 of scaling factor for grow size // FIXME: remove
- std::atomic<size_t> bytesUsed;
- std::atomic<size_t> bytesFree;
- std::atomic<size_t> bytesWasted;
- static __thread ThreadLocal2* thread_local_allocator2;
- static SpinLock s_thread_local_allocators_lock;
- static std::vector<std::unique_ptr<ThreadLocal2>> s_thread_local_allocators;
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::mutex thread_local_allocators_lock;
-#else
- SpinLock thread_local_allocators_lock;
-#endif
- std::vector<ThreadLocal2*> thread_local_allocators;
- AllocationType atype;
- mvector<PrimRef> primrefarray; //!< primrefarray used to allocate nodes
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/buffer.h b/thirdparty/embree-aarch64/kernels/common/buffer.h
deleted file mode 100644
index 02d319c59d..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/buffer.h
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "device.h"
-
-namespace embree
-{
- /*! Implements an API data buffer object. This class may or may not own the data. */
- class Buffer : public RefCount
- {
- public:
- /*! Buffer construction */
- Buffer()
- : device(nullptr), ptr(nullptr), numBytes(0), shared(false) {}
-
- /*! Buffer construction */
- Buffer(Device* device, size_t numBytes_in, void* ptr_in = nullptr)
- : device(device), numBytes(numBytes_in)
- {
- device->refInc();
-
- if (ptr_in)
- {
- shared = true;
- ptr = (char*)ptr_in;
- }
- else
- {
- shared = false;
- alloc();
- }
- }
-
- /*! Buffer destruction */
- ~Buffer() {
- free();
- device->refDec();
- }
-
- /*! this class is not copyable */
- private:
- Buffer(const Buffer& other) DELETED; // do not implement
- Buffer& operator =(const Buffer& other) DELETED; // do not implement
-
- public:
- /* inits and allocates the buffer */
- void create(Device* device_in, size_t numBytes_in)
- {
- init(device_in, numBytes_in);
- alloc();
- }
-
- /* inits the buffer */
- void init(Device* device_in, size_t numBytes_in)
- {
- free();
- device = device_in;
- ptr = nullptr;
- numBytes = numBytes_in;
- shared = false;
- }
-
- /*! sets shared buffer */
- void set(Device* device_in, void* ptr_in, size_t numBytes_in)
- {
- free();
- device = device_in;
- ptr = (char*)ptr_in;
- if (numBytes_in != (size_t)-1)
- numBytes = numBytes_in;
- shared = true;
- }
-
- /*! allocated buffer */
- void alloc()
- {
- if (device)
- device->memoryMonitor(this->bytes(), false);
- size_t b = (this->bytes()+15) & ssize_t(-16);
- ptr = (char*)alignedMalloc(b,16);
- }
-
- /*! frees the buffer */
- void free()
- {
- if (shared) return;
- alignedFree(ptr);
- if (device)
- device->memoryMonitor(-ssize_t(this->bytes()), true);
- ptr = nullptr;
- }
-
- /*! gets buffer pointer */
- void* data()
- {
- /* report error if buffer is not existing */
- if (!device)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer specified");
-
- /* return buffer */
- return ptr;
- }
-
- /*! returns pointer to first element */
- __forceinline char* getPtr() const {
- return ptr;
- }
-
- /*! returns the number of bytes of the buffer */
- __forceinline size_t bytes() const {
- return numBytes;
- }
-
- /*! returns true of the buffer is not empty */
- __forceinline operator bool() const {
- return ptr;
- }
-
- public:
- Device* device; //!< device to report memory usage to
- char* ptr; //!< pointer to buffer data
- size_t numBytes; //!< number of bytes in the buffer
- bool shared; //!< set if memory is shared with application
- };
-
- /*! An untyped contiguous range of a buffer. This class does not own the buffer content. */
- class RawBufferView
- {
- public:
- /*! Buffer construction */
- RawBufferView()
- : ptr_ofs(nullptr), stride(0), num(0), format(RTC_FORMAT_UNDEFINED), modCounter(1), modified(true), userData(0) {}
-
- public:
- /*! sets the buffer view */
- void set(const Ref<Buffer>& buffer_in, size_t offset_in, size_t stride_in, size_t num_in, RTCFormat format_in)
- {
- if ((offset_in + stride_in * num_in) > (stride_in * buffer_in->numBytes))
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "buffer range out of bounds");
-
- ptr_ofs = buffer_in->ptr + offset_in;
- stride = stride_in;
- num = num_in;
- format = format_in;
- modCounter++;
- modified = true;
- buffer = buffer_in;
- }
-
- /*! returns pointer to the first element */
- __forceinline char* getPtr() const {
- return ptr_ofs;
- }
-
- /*! returns pointer to the i'th element */
- __forceinline char* getPtr(size_t i) const
- {
- assert(i<num);
- return ptr_ofs + i*stride;
- }
-
- /*! returns the number of elements of the buffer */
- __forceinline size_t size() const {
- return num;
- }
-
- /*! returns the number of bytes of the buffer */
- __forceinline size_t bytes() const {
- return num*stride;
- }
-
- /*! returns the buffer stride */
- __forceinline unsigned getStride() const
- {
- assert(stride <= unsigned(inf));
- return unsigned(stride);
- }
-
- /*! return the buffer format */
- __forceinline RTCFormat getFormat() const {
- return format;
- }
-
- /*! mark buffer as modified or unmodified */
- __forceinline void setModified() {
- modCounter++;
- modified = true;
- }
-
- /*! mark buffer as modified or unmodified */
- __forceinline bool isModified(unsigned int otherModCounter) const {
- return modCounter > otherModCounter;
- }
-
- /*! mark buffer as modified or unmodified */
- __forceinline bool isLocalModified() const {
- return modified;
- }
-
- /*! clear local modified flag */
- __forceinline void clearLocalModified() {
- modified = false;
- }
-
- /*! returns true of the buffer is not empty */
- __forceinline operator bool() const {
- return ptr_ofs;
- }
-
- /*! checks padding to 16 byte check, fails hard */
- __forceinline void checkPadding16() const
- {
- if (ptr_ofs && num)
- volatile int MAYBE_UNUSED w = *((int*)getPtr(size()-1)+3); // FIXME: is failing hard avoidable?
- }
-
- public:
- char* ptr_ofs; //!< base pointer plus offset
- size_t stride; //!< stride of the buffer in bytes
- size_t num; //!< number of elements in the buffer
- RTCFormat format; //!< format of the buffer
- unsigned int modCounter; //!< version ID of this buffer
- bool modified; //!< local modified data
- int userData; //!< special data
- Ref<Buffer> buffer; //!< reference to the parent buffer
- };
-
- /*! A typed contiguous range of a buffer. This class does not own the buffer content. */
- template<typename T>
- class BufferView : public RawBufferView
- {
- public:
- typedef T value_type;
-
- /*! access to the ith element of the buffer */
- __forceinline T& operator [](size_t i) { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
- __forceinline const T& operator [](size_t i) const { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
- };
-
- template<>
- class BufferView<Vec3fa> : public RawBufferView
- {
- public:
- typedef Vec3fa value_type;
-
- /*! access to the ith element of the buffer */
- __forceinline const Vec3fa operator [](size_t i) const
- {
- assert(i<num);
- return Vec3fa(vfloat4::loadu((float*)(ptr_ofs + i*stride)));
- }
-
- /*! writes the i'th element */
- __forceinline void store(size_t i, const Vec3fa& v)
- {
- assert(i<num);
- vfloat4::storeu((float*)(ptr_ofs + i*stride), (vfloat4)v);
- }
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/builder.h b/thirdparty/embree-aarch64/kernels/common/builder.h
deleted file mode 100644
index d2a1cfe3ce..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/builder.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "accel.h"
-
-namespace embree
-{
-#define MODE_HIGH_QUALITY (1<<8)
-
- /*! virtual interface for all hierarchy builders */
- class Builder : public RefCount {
- public:
-
- static const size_t DEFAULT_SINGLE_THREAD_THRESHOLD = 1024;
-
- /*! initiates the hierarchy builder */
- virtual void build() = 0;
-
- /*! notifies the builder about the deletion of some geometry */
- virtual void deleteGeometry(size_t geomID) {};
-
- /*! clears internal builder state */
- virtual void clear() = 0;
- };
-
- /*! virtual interface for progress monitor class */
- struct BuildProgressMonitor {
- virtual void operator() (size_t dn) const = 0;
- };
-
- /*! build the progress monitor interface from a closure */
- template<typename Closure>
- struct ProgressMonitorClosure : BuildProgressMonitor
- {
- public:
- ProgressMonitorClosure (const Closure& closure) : closure(closure) {}
- void operator() (size_t dn) const { closure(dn); }
- private:
- const Closure closure;
- };
- template<typename Closure> __forceinline const ProgressMonitorClosure<Closure> BuildProgressMonitorFromClosure(const Closure& closure) {
- return ProgressMonitorClosure<Closure>(closure);
- }
-
- struct LineSegments;
- struct TriangleMesh;
- struct QuadMesh;
- struct UserGeometry;
-
- class Scene;
-
- typedef void (*createLineSegmentsAccelTy)(Scene* scene, LineSegments* mesh, AccelData*& accel, Builder*& builder);
- typedef void (*createTriangleMeshAccelTy)(Scene* scene, unsigned int geomID, AccelData*& accel, Builder*& builder);
- typedef void (*createQuadMeshAccelTy)(Scene* scene, unsigned int geomID, AccelData*& accel, Builder*& builder);
- typedef void (*createUserGeometryAccelTy)(Scene* scene, unsigned int geomID, AccelData*& accel, Builder*& builder);
-
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/context.h b/thirdparty/embree-aarch64/kernels/common/context.h
deleted file mode 100644
index d0185a74f2..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/context.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "rtcore.h"
-#include "point_query.h"
-
-namespace embree
-{
- class Scene;
-
- struct IntersectContext
- {
- public:
- __forceinline IntersectContext(Scene* scene, RTCIntersectContext* user_context)
- : scene(scene), user(user_context) {}
-
- __forceinline bool hasContextFilter() const {
- return user->filter != nullptr;
- }
-
- __forceinline bool isCoherent() const {
- return embree::isCoherent(user->flags);
- }
-
- __forceinline bool isIncoherent() const {
- return embree::isIncoherent(user->flags);
- }
-
- public:
- Scene* scene;
- RTCIntersectContext* user;
- };
-
- template<int M, typename Geometry>
- __forceinline Vec4vf<M> enlargeRadiusToMinWidth(const IntersectContext* context, const Geometry* geom, const Vec3vf<M>& ray_org, const Vec4vf<M>& v)
- {
-#if RTC_MIN_WIDTH
- const vfloat<M> d = length(Vec3vf<M>(v) - ray_org);
- const vfloat<M> r = clamp(context->user->minWidthDistanceFactor*d, v.w, geom->maxRadiusScale*v.w);
- return Vec4vf<M>(v.x,v.y,v.z,r);
-#else
- return v;
-#endif
- }
-
- template<typename Geometry>
- __forceinline Vec3ff enlargeRadiusToMinWidth(const IntersectContext* context, const Geometry* geom, const Vec3fa& ray_org, const Vec3ff& v)
- {
-#if RTC_MIN_WIDTH
- const float d = length(Vec3fa(v) - ray_org);
- const float r = clamp(context->user->minWidthDistanceFactor*d, v.w, geom->maxRadiusScale*v.w);
- return Vec3ff(v.x,v.y,v.z,r);
-#else
- return v;
-#endif
- }
-
- enum PointQueryType
- {
- POINT_QUERY_TYPE_UNDEFINED = 0,
- POINT_QUERY_TYPE_SPHERE = 1,
- POINT_QUERY_TYPE_AABB = 2,
- };
-
- typedef bool (*PointQueryFunction)(struct RTCPointQueryFunctionArguments* args);
-
- struct PointQueryContext
- {
- public:
- __forceinline PointQueryContext(Scene* scene,
- PointQuery* query_ws,
- PointQueryType query_type,
- PointQueryFunction func,
- RTCPointQueryContext* userContext,
- float similarityScale,
- void* userPtr)
- : scene(scene)
- , query_ws(query_ws)
- , query_type(query_type)
- , func(func)
- , userContext(userContext)
- , similarityScale(similarityScale)
- , userPtr(userPtr)
- , primID(RTC_INVALID_GEOMETRY_ID)
- , geomID(RTC_INVALID_GEOMETRY_ID)
- , query_radius(query_ws->radius)
- {
- if (query_type == POINT_QUERY_TYPE_AABB) {
- assert(similarityScale == 0.f);
- updateAABB();
- }
- if (userContext->instStackSize == 0) {
- assert(similarityScale == 1.f);
- }
- }
-
- public:
- __forceinline void updateAABB()
- {
- if (likely(query_ws->radius == (float)inf || userContext->instStackSize == 0)) {
- query_radius = Vec3fa(query_ws->radius);
- return;
- }
-
- const AffineSpace3fa m = AffineSpace3fa_load_unaligned((AffineSpace3fa*)userContext->world2inst[userContext->instStackSize-1]);
- BBox3fa bbox(Vec3fa(-query_ws->radius), Vec3fa(query_ws->radius));
- bbox = xfmBounds(m, bbox);
- query_radius = 0.5f * (bbox.upper - bbox.lower);
- }
-
-public:
- Scene* scene;
-
- PointQuery* query_ws; // the original world space point query
- PointQueryType query_type;
- PointQueryFunction func;
- RTCPointQueryContext* userContext;
- const float similarityScale;
-
- void* userPtr;
-
- unsigned int primID;
- unsigned int geomID;
-
- Vec3fa query_radius; // used if the query is converted to an AABB internally
- };
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/common/default.h b/thirdparty/embree-aarch64/kernels/common/default.h
deleted file mode 100644
index 709119163b..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/default.h
+++ /dev/null
@@ -1,273 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../../common/sys/platform.h"
-#include "../../common/sys/sysinfo.h"
-#include "../../common/sys/thread.h"
-#include "../../common/sys/alloc.h"
-#include "../../common/sys/ref.h"
-#include "../../common/sys/intrinsics.h"
-#include "../../common/sys/atomic.h"
-#include "../../common/sys/mutex.h"
-#include "../../common/sys/vector.h"
-#include "../../common/sys/array.h"
-#include "../../common/sys/string.h"
-#include "../../common/sys/regression.h"
-#include "../../common/sys/vector.h"
-
-#include "../../common/math/math.h"
-#include "../../common/math/transcendental.h"
-#include "../../common/simd/simd.h"
-#include "../../common/math/vec2.h"
-#include "../../common/math/vec3.h"
-#include "../../common/math/vec4.h"
-#include "../../common/math/vec2fa.h"
-#include "../../common/math/vec3fa.h"
-#include "../../common/math/interval.h"
-#include "../../common/math/bbox.h"
-#include "../../common/math/obbox.h"
-#include "../../common/math/lbbox.h"
-#include "../../common/math/linearspace2.h"
-#include "../../common/math/linearspace3.h"
-#include "../../common/math/affinespace.h"
-#include "../../common/math/range.h"
-#include "../../common/lexers/tokenstream.h"
-
-#include "../../common/tasking/taskscheduler.h"
-
-#define COMMA ,
-
-#include "../config.h"
-#include "isa.h"
-#include "stat.h"
-#include "profile.h"
-#include "rtcore.h"
-#include "vector.h"
-#include "state.h"
-#include "instance_stack.h"
-
-#include <vector>
-#include <map>
-#include <algorithm>
-#include <functional>
-#include <utility>
-#include <sstream>
-
-#if !defined(_DEBUG) && defined(BUILD_IOS)
-#undef assert
-#define assert(_EXPR)
-#endif
-
-namespace embree
-{
- ////////////////////////////////////////////////////////////////////////////////
- /// Vec2 shortcuts
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int N> using Vec2vf = Vec2<vfloat<N>>;
- template<int N> using Vec2vd = Vec2<vdouble<N>>;
- template<int N> using Vec2vr = Vec2<vreal<N>>;
- template<int N> using Vec2vi = Vec2<vint<N>>;
- template<int N> using Vec2vl = Vec2<vllong<N>>;
- template<int N> using Vec2vb = Vec2<vbool<N>>;
- template<int N> using Vec2vbf = Vec2<vboolf<N>>;
- template<int N> using Vec2vbd = Vec2<vboold<N>>;
-
- typedef Vec2<vfloat4> Vec2vf4;
- typedef Vec2<vdouble4> Vec2vd4;
- typedef Vec2<vreal4> Vec2vr4;
- typedef Vec2<vint4> Vec2vi4;
- typedef Vec2<vllong4> Vec2vl4;
- typedef Vec2<vbool4> Vec2vb4;
- typedef Vec2<vboolf4> Vec2vbf4;
- typedef Vec2<vboold4> Vec2vbd4;
-
- typedef Vec2<vfloat8> Vec2vf8;
- typedef Vec2<vdouble8> Vec2vd8;
- typedef Vec2<vreal8> Vec2vr8;
- typedef Vec2<vint8> Vec2vi8;
- typedef Vec2<vllong8> Vec2vl8;
- typedef Vec2<vbool8> Vec2vb8;
- typedef Vec2<vboolf8> Vec2vbf8;
- typedef Vec2<vboold8> Vec2vbd8;
-
- typedef Vec2<vfloat16> Vec2vf16;
- typedef Vec2<vdouble16> Vec2vd16;
- typedef Vec2<vreal16> Vec2vr16;
- typedef Vec2<vint16> Vec2vi16;
- typedef Vec2<vllong16> Vec2vl16;
- typedef Vec2<vbool16> Vec2vb16;
- typedef Vec2<vboolf16> Vec2vbf16;
- typedef Vec2<vboold16> Vec2vbd16;
-
- typedef Vec2<vfloatx> Vec2vfx;
- typedef Vec2<vdoublex> Vec2vdx;
- typedef Vec2<vrealx> Vec2vrx;
- typedef Vec2<vintx> Vec2vix;
- typedef Vec2<vllongx> Vec2vlx;
- typedef Vec2<vboolx> Vec2vbx;
- typedef Vec2<vboolfx> Vec2vbfx;
- typedef Vec2<vbooldx> Vec2vbdx;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Vec3 shortcuts
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int N> using Vec3vf = Vec3<vfloat<N>>;
- template<int N> using Vec3vd = Vec3<vdouble<N>>;
- template<int N> using Vec3vr = Vec3<vreal<N>>;
- template<int N> using Vec3vi = Vec3<vint<N>>;
- template<int N> using Vec3vl = Vec3<vllong<N>>;
- template<int N> using Vec3vb = Vec3<vbool<N>>;
- template<int N> using Vec3vbf = Vec3<vboolf<N>>;
- template<int N> using Vec3vbd = Vec3<vboold<N>>;
-
- typedef Vec3<vfloat4> Vec3vf4;
- typedef Vec3<vdouble4> Vec3vd4;
- typedef Vec3<vreal4> Vec3vr4;
- typedef Vec3<vint4> Vec3vi4;
- typedef Vec3<vllong4> Vec3vl4;
- typedef Vec3<vbool4> Vec3vb4;
- typedef Vec3<vboolf4> Vec3vbf4;
- typedef Vec3<vboold4> Vec3vbd4;
-
- typedef Vec3<vfloat8> Vec3vf8;
- typedef Vec3<vdouble8> Vec3vd8;
- typedef Vec3<vreal8> Vec3vr8;
- typedef Vec3<vint8> Vec3vi8;
- typedef Vec3<vllong8> Vec3vl8;
- typedef Vec3<vbool8> Vec3vb8;
- typedef Vec3<vboolf8> Vec3vbf8;
- typedef Vec3<vboold8> Vec3vbd8;
-
- typedef Vec3<vfloat16> Vec3vf16;
- typedef Vec3<vdouble16> Vec3vd16;
- typedef Vec3<vreal16> Vec3vr16;
- typedef Vec3<vint16> Vec3vi16;
- typedef Vec3<vllong16> Vec3vl16;
- typedef Vec3<vbool16> Vec3vb16;
- typedef Vec3<vboolf16> Vec3vbf16;
- typedef Vec3<vboold16> Vec3vbd16;
-
- typedef Vec3<vfloatx> Vec3vfx;
- typedef Vec3<vdoublex> Vec3vdx;
- typedef Vec3<vrealx> Vec3vrx;
- typedef Vec3<vintx> Vec3vix;
- typedef Vec3<vllongx> Vec3vlx;
- typedef Vec3<vboolx> Vec3vbx;
- typedef Vec3<vboolfx> Vec3vbfx;
- typedef Vec3<vbooldx> Vec3vbdx;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Vec4 shortcuts
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int N> using Vec4vf = Vec4<vfloat<N>>;
- template<int N> using Vec4vd = Vec4<vdouble<N>>;
- template<int N> using Vec4vr = Vec4<vreal<N>>;
- template<int N> using Vec4vi = Vec4<vint<N>>;
- template<int N> using Vec4vl = Vec4<vllong<N>>;
- template<int N> using Vec4vb = Vec4<vbool<N>>;
- template<int N> using Vec4vbf = Vec4<vboolf<N>>;
- template<int N> using Vec4vbd = Vec4<vboold<N>>;
-
- typedef Vec4<vfloat4> Vec4vf4;
- typedef Vec4<vdouble4> Vec4vd4;
- typedef Vec4<vreal4> Vec4vr4;
- typedef Vec4<vint4> Vec4vi4;
- typedef Vec4<vllong4> Vec4vl4;
- typedef Vec4<vbool4> Vec4vb4;
- typedef Vec4<vboolf4> Vec4vbf4;
- typedef Vec4<vboold4> Vec4vbd4;
-
- typedef Vec4<vfloat8> Vec4vf8;
- typedef Vec4<vdouble8> Vec4vd8;
- typedef Vec4<vreal8> Vec4vr8;
- typedef Vec4<vint8> Vec4vi8;
- typedef Vec4<vllong8> Vec4vl8;
- typedef Vec4<vbool8> Vec4vb8;
- typedef Vec4<vboolf8> Vec4vbf8;
- typedef Vec4<vboold8> Vec4vbd8;
-
- typedef Vec4<vfloat16> Vec4vf16;
- typedef Vec4<vdouble16> Vec4vd16;
- typedef Vec4<vreal16> Vec4vr16;
- typedef Vec4<vint16> Vec4vi16;
- typedef Vec4<vllong16> Vec4vl16;
- typedef Vec4<vbool16> Vec4vb16;
- typedef Vec4<vboolf16> Vec4vbf16;
- typedef Vec4<vboold16> Vec4vbd16;
-
- typedef Vec4<vfloatx> Vec4vfx;
- typedef Vec4<vdoublex> Vec4vdx;
- typedef Vec4<vrealx> Vec4vrx;
- typedef Vec4<vintx> Vec4vix;
- typedef Vec4<vllongx> Vec4vlx;
- typedef Vec4<vboolx> Vec4vbx;
- typedef Vec4<vboolfx> Vec4vbfx;
- typedef Vec4<vbooldx> Vec4vbdx;
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Other shortcuts
- ////////////////////////////////////////////////////////////////////////////////
-
- template<int N> using BBox3vf = BBox<Vec3vf<N>>;
- typedef BBox<Vec3vf4> BBox3vf4;
- typedef BBox<Vec3vf8> BBox3vf8;
- typedef BBox<Vec3vf16> BBox3vf16;
-
- /* calculate time segment itime and fractional time ftime */
- __forceinline int getTimeSegment(float time, float numTimeSegments, float& ftime)
- {
- const float timeScaled = time * numTimeSegments;
- const float itimef = clamp(floorf(timeScaled), 0.0f, numTimeSegments-1.0f);
- ftime = timeScaled - itimef;
- return int(itimef);
- }
-
- __forceinline int getTimeSegment(float time, float start_time, float end_time, float numTimeSegments, float& ftime)
- {
- const float timeScaled = (time-start_time)/(end_time-start_time) * numTimeSegments;
- const float itimef = clamp(floorf(timeScaled), 0.0f, numTimeSegments-1.0f);
- ftime = timeScaled - itimef;
- return int(itimef);
- }
-
- template<int N>
- __forceinline vint<N> getTimeSegment(const vfloat<N>& time, const vfloat<N>& numTimeSegments, vfloat<N>& ftime)
- {
- const vfloat<N> timeScaled = time * numTimeSegments;
- const vfloat<N> itimef = clamp(floor(timeScaled), vfloat<N>(zero), numTimeSegments-1.0f);
- ftime = timeScaled - itimef;
- return vint<N>(itimef);
- }
-
- template<int N>
- __forceinline vint<N> getTimeSegment(const vfloat<N>& time, const vfloat<N>& start_time, const vfloat<N>& end_time, const vfloat<N>& numTimeSegments, vfloat<N>& ftime)
- {
- const vfloat<N> timeScaled = (time-start_time)/(end_time-start_time) * numTimeSegments;
- const vfloat<N> itimef = clamp(floor(timeScaled), vfloat<N>(zero), numTimeSegments-1.0f);
- ftime = timeScaled - itimef;
- return vint<N>(itimef);
- }
-
- /* calculate overlapping time segment range */
- __forceinline range<int> getTimeSegmentRange(const BBox1f& time_range, float numTimeSegments)
- {
- const float round_up = 1.0f+2.0f*float(ulp); // corrects inaccuracies to precisely match time step
- const float round_down = 1.0f-2.0f*float(ulp);
- const int itime_lower = (int)max(floor(round_up *time_range.lower*numTimeSegments), 0.0f);
- const int itime_upper = (int)min(ceil (round_down*time_range.upper*numTimeSegments), numTimeSegments);
- return make_range(itime_lower, itime_upper);
- }
-
- /* calculate overlapping time segment range */
- __forceinline range<int> getTimeSegmentRange(const BBox1f& range, BBox1f time_range, float numTimeSegments)
- {
- const float lower = (range.lower-time_range.lower)/time_range.size();
- const float upper = (range.upper-time_range.lower)/time_range.size();
- return getTimeSegmentRange(BBox1f(lower,upper),numTimeSegments);
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/device.cpp b/thirdparty/embree-aarch64/kernels/common/device.cpp
deleted file mode 100644
index 16ec11b892..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/device.cpp
+++ /dev/null
@@ -1,567 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "device.h"
-#include "../hash.h"
-#include "scene_triangle_mesh.h"
-#include "scene_user_geometry.h"
-#include "scene_instance.h"
-#include "scene_curves.h"
-#include "scene_subdiv_mesh.h"
-
-#include "../subdiv/tessellation_cache.h"
-
-#include "acceln.h"
-#include "geometry.h"
-
-#include "../geometry/cylinder.h"
-
-#include "../bvh/bvh4_factory.h"
-#include "../bvh/bvh8_factory.h"
-
-#include "../../common/tasking/taskscheduler.h"
-#include "../../common/sys/alloc.h"
-
-namespace embree
-{
- /*! some global variables that can be set via rtcSetParameter1i for debugging purposes */
- ssize_t Device::debug_int0 = 0;
- ssize_t Device::debug_int1 = 0;
- ssize_t Device::debug_int2 = 0;
- ssize_t Device::debug_int3 = 0;
-
- DECLARE_SYMBOL2(RayStreamFilterFuncs,rayStreamFilterFuncs);
-
- static MutexSys g_mutex;
- static std::map<Device*,size_t> g_cache_size_map;
- static std::map<Device*,size_t> g_num_threads_map;
-
- Device::Device (const char* cfg)
- {
- /* check that CPU supports lowest ISA */
- if (!hasISA(ISA)) {
- throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"CPU does not support " ISA_STR);
- }
-
- /* set default frequency level for detected CPU */
- switch (getCPUModel()) {
- case CPU::UNKNOWN: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::XEON_ICE_LAKE: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::CORE_ICE_LAKE: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::CORE_TIGER_LAKE: frequency_level = FREQUENCY_SIMD128; break;
- case CPU::CORE_COMET_LAKE: frequency_level = FREQUENCY_SIMD128; break;
- case CPU::CORE_CANNON_LAKE:frequency_level = FREQUENCY_SIMD128; break;
- case CPU::CORE_KABY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
- case CPU::XEON_SKY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
- case CPU::CORE_SKY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
- case CPU::XEON_BROADWELL: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::CORE_BROADWELL: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::XEON_HASWELL: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::CORE_HASWELL: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::XEON_IVY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::CORE_IVY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::SANDY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
- case CPU::NEHALEM: frequency_level = FREQUENCY_SIMD128; break;
- case CPU::CORE2: frequency_level = FREQUENCY_SIMD128; break;
- case CPU::CORE1: frequency_level = FREQUENCY_SIMD128; break;
- }
-
- /* initialize global state */
-#if defined(EMBREE_CONFIG)
- State::parseString(EMBREE_CONFIG);
-#endif
- State::parseString(cfg);
- if (!ignore_config_files && FileName::executableFolder() != FileName(""))
- State::parseFile(FileName::executableFolder()+FileName(".embree" TOSTRING(RTC_VERSION_MAJOR)));
- if (!ignore_config_files && FileName::homeFolder() != FileName(""))
- State::parseFile(FileName::homeFolder()+FileName(".embree" TOSTRING(RTC_VERSION_MAJOR)));
- State::verify();
-
- /* check whether selected ISA is supported by the HW, as the user could have forced an unsupported ISA */
- if (!checkISASupport()) {
- throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"CPU does not support selected ISA");
- }
-
- /*! do some internal tests */
- assert(isa::Cylinder::verify());
-
- /*! enable huge page support if desired */
-#if defined(__WIN32__)
- if (State::enable_selockmemoryprivilege)
- State::hugepages_success &= win_enable_selockmemoryprivilege(State::verbosity(3));
-#endif
- State::hugepages_success &= os_init(State::hugepages,State::verbosity(3));
-
- /*! set tessellation cache size */
- setCacheSize( State::tessellation_cache_size );
-
- /*! enable some floating point exceptions to catch bugs */
- if (State::float_exceptions)
- {
- int exceptions = _MM_MASK_MASK;
- //exceptions &= ~_MM_MASK_INVALID;
- exceptions &= ~_MM_MASK_DENORM;
- exceptions &= ~_MM_MASK_DIV_ZERO;
- //exceptions &= ~_MM_MASK_OVERFLOW;
- //exceptions &= ~_MM_MASK_UNDERFLOW;
- //exceptions &= ~_MM_MASK_INEXACT;
- _MM_SET_EXCEPTION_MASK(exceptions);
- }
-
- /* print info header */
- if (State::verbosity(1))
- print();
- if (State::verbosity(2))
- State::print();
-
- /* register all algorithms */
- bvh4_factory = make_unique(new BVH4Factory(enabled_builder_cpu_features, enabled_cpu_features));
-
-#if defined(EMBREE_TARGET_SIMD8)
- bvh8_factory = make_unique(new BVH8Factory(enabled_builder_cpu_features, enabled_cpu_features));
-#endif
-
- /* setup tasking system */
- initTaskingSystem(numThreads);
-
- /* ray stream SOA to AOS conversion */
-#if defined(EMBREE_RAY_PACKETS)
- RayStreamFilterFuncsType rayStreamFilterFuncs;
- SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(enabled_cpu_features,rayStreamFilterFuncs);
- rayStreamFilters = rayStreamFilterFuncs();
-#endif
- }
-
- Device::~Device ()
- {
- setCacheSize(0);
- exitTaskingSystem();
- }
-
- std::string getEnabledTargets()
- {
- std::string v;
-#if defined(EMBREE_TARGET_SSE2)
- v += "SSE2 ";
-#endif
-#if defined(EMBREE_TARGET_SSE42)
- v += "SSE4.2 ";
-#endif
-#if defined(EMBREE_TARGET_AVX)
- v += "AVX ";
-#endif
-#if defined(EMBREE_TARGET_AVX2)
- v += "AVX2 ";
-#endif
-#if defined(EMBREE_TARGET_AVX512KNL)
- v += "AVX512KNL ";
-#endif
-#if defined(EMBREE_TARGET_AVX512SKX)
- v += "AVX512SKX ";
-#endif
- return v;
- }
-
- std::string getEmbreeFeatures()
- {
- std::string v;
-#if defined(EMBREE_RAY_MASK)
- v += "raymasks ";
-#endif
-#if defined (EMBREE_BACKFACE_CULLING)
- v += "backfaceculling ";
-#endif
-#if defined (EMBREE_BACKFACE_CULLING_CURVES)
- v += "backfacecullingcurves ";
-#endif
-#if defined(EMBREE_FILTER_FUNCTION)
- v += "intersection_filter ";
-#endif
-#if defined (EMBREE_COMPACT_POLYS)
- v += "compact_polys ";
-#endif
- return v;
- }
-
- void Device::print()
- {
- const int cpu_features = getCPUFeatures();
- std::cout << std::endl;
- std::cout << "Embree Ray Tracing Kernels " << RTC_VERSION_STRING << " (" << RTC_HASH << ")" << std::endl;
- std::cout << " Compiler : " << getCompilerName() << std::endl;
- std::cout << " Build : ";
-#if defined(DEBUG)
- std::cout << "Debug " << std::endl;
-#else
- std::cout << "Release " << std::endl;
-#endif
- std::cout << " Platform : " << getPlatformName() << std::endl;
- std::cout << " CPU : " << stringOfCPUModel(getCPUModel()) << " (" << getCPUVendor() << ")" << std::endl;
- std::cout << " Threads : " << getNumberOfLogicalThreads() << std::endl;
- std::cout << " ISA : " << stringOfCPUFeatures(cpu_features) << std::endl;
- std::cout << " Targets : " << supportedTargetList(cpu_features) << std::endl;
- const bool hasFTZ = _mm_getcsr() & _MM_FLUSH_ZERO_ON;
- const bool hasDAZ = _mm_getcsr() & _MM_DENORMALS_ZERO_ON;
- std::cout << " MXCSR : " << "FTZ=" << hasFTZ << ", DAZ=" << hasDAZ << std::endl;
- std::cout << " Config" << std::endl;
- std::cout << " Threads : " << (numThreads ? toString(numThreads) : std::string("default")) << std::endl;
- std::cout << " ISA : " << stringOfCPUFeatures(enabled_cpu_features) << std::endl;
- std::cout << " Targets : " << supportedTargetList(enabled_cpu_features) << " (supported)" << std::endl;
- std::cout << " " << getEnabledTargets() << " (compile time enabled)" << std::endl;
- std::cout << " Features: " << getEmbreeFeatures() << std::endl;
- std::cout << " Tasking : ";
-#if defined(TASKING_TBB)
- std::cout << "TBB" << TBB_VERSION_MAJOR << "." << TBB_VERSION_MINOR << " ";
- #if TBB_INTERFACE_VERSION >= 12002
- std::cout << "TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << TBB_runtime_interface_version() << " ";
- #else
- std::cout << "TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << tbb::TBB_runtime_interface_version() << " ";
- #endif
-#endif
-#if defined(TASKING_INTERNAL)
- std::cout << "internal_tasking_system ";
-#endif
-#if defined(TASKING_GCD) && defined(BUILD_IOS)
- std::cout << "GCD tasking system ";
-#endif
-#if defined(TASKING_PPL)
- std::cout << "PPL ";
-#endif
- std::cout << std::endl;
-
- /* check of FTZ and DAZ flags are set in CSR */
- if (!hasFTZ || !hasDAZ)
- {
-#if !defined(_DEBUG)
- if (State::verbosity(1))
-#endif
- {
- std::cout << std::endl;
- std::cout << "================================================================================" << std::endl;
- std::cout << " WARNING: \"Flush to Zero\" or \"Denormals are Zero\" mode not enabled " << std::endl
- << " in the MXCSR control and status register. This can have a severe " << std::endl
- << " performance impact. Please enable these modes for each application " << std::endl
- << " thread the following way:" << std::endl
- << std::endl
- << " #include \"xmmintrin.h\"" << std::endl
- << " #include \"pmmintrin.h\"" << std::endl
- << std::endl
- << " _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);" << std::endl
- << " _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);" << std::endl;
- std::cout << "================================================================================" << std::endl;
- std::cout << std::endl;
- }
- }
- std::cout << std::endl;
- }
-
- void Device::setDeviceErrorCode(RTCError error)
- {
- RTCError* stored_error = errorHandler.error();
- if (*stored_error == RTC_ERROR_NONE)
- *stored_error = error;
- }
-
- RTCError Device::getDeviceErrorCode()
- {
- RTCError* stored_error = errorHandler.error();
- RTCError error = *stored_error;
- *stored_error = RTC_ERROR_NONE;
- return error;
- }
-
- void Device::setThreadErrorCode(RTCError error)
- {
- RTCError* stored_error = g_errorHandler.error();
- if (*stored_error == RTC_ERROR_NONE)
- *stored_error = error;
- }
-
- RTCError Device::getThreadErrorCode()
- {
- RTCError* stored_error = g_errorHandler.error();
- RTCError error = *stored_error;
- *stored_error = RTC_ERROR_NONE;
- return error;
- }
-
- void Device::process_error(Device* device, RTCError error, const char* str)
- {
- /* store global error code when device construction failed */
- if (!device)
- return setThreadErrorCode(error);
-
- /* print error when in verbose mode */
- if (device->verbosity(1))
- {
- switch (error) {
- case RTC_ERROR_NONE : std::cerr << "Embree: No error"; break;
- case RTC_ERROR_UNKNOWN : std::cerr << "Embree: Unknown error"; break;
- case RTC_ERROR_INVALID_ARGUMENT : std::cerr << "Embree: Invalid argument"; break;
- case RTC_ERROR_INVALID_OPERATION: std::cerr << "Embree: Invalid operation"; break;
- case RTC_ERROR_OUT_OF_MEMORY : std::cerr << "Embree: Out of memory"; break;
- case RTC_ERROR_UNSUPPORTED_CPU : std::cerr << "Embree: Unsupported CPU"; break;
- default : std::cerr << "Embree: Invalid error code"; break;
- };
- if (str) std::cerr << ", (" << str << ")";
- std::cerr << std::endl;
- }
-
- /* call user specified error callback */
- if (device->error_function)
- device->error_function(device->error_function_userptr,error,str);
-
- /* record error code */
- device->setDeviceErrorCode(error);
- }
-
- void Device::memoryMonitor(ssize_t bytes, bool post)
- {
- if (State::memory_monitor_function && bytes != 0) {
- if (!State::memory_monitor_function(State::memory_monitor_userptr,bytes,post)) {
- if (bytes > 0) { // only throw exception when we allocate memory to never throw inside a destructor
- throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"memory monitor forced termination");
- }
- }
- }
- }
-
- size_t getMaxNumThreads()
- {
- size_t maxNumThreads = 0;
- for (std::map<Device*,size_t>::iterator i=g_num_threads_map.begin(); i != g_num_threads_map.end(); i++)
- maxNumThreads = max(maxNumThreads, (*i).second);
- if (maxNumThreads == 0)
- maxNumThreads = std::numeric_limits<size_t>::max();
- return maxNumThreads;
- }
-
- size_t getMaxCacheSize()
- {
- size_t maxCacheSize = 0;
- for (std::map<Device*,size_t>::iterator i=g_cache_size_map.begin(); i!= g_cache_size_map.end(); i++)
- maxCacheSize = max(maxCacheSize, (*i).second);
- return maxCacheSize;
- }
-
- void Device::setCacheSize(size_t bytes)
- {
-#if defined(EMBREE_GEOMETRY_SUBDIVISION)
- Lock<MutexSys> lock(g_mutex);
- if (bytes == 0) g_cache_size_map.erase(this);
- else g_cache_size_map[this] = bytes;
-
- size_t maxCacheSize = getMaxCacheSize();
- resizeTessellationCache(maxCacheSize);
-#endif
- }
-
- void Device::initTaskingSystem(size_t numThreads)
- {
- Lock<MutexSys> lock(g_mutex);
- if (numThreads == 0)
- g_num_threads_map[this] = std::numeric_limits<size_t>::max();
- else
- g_num_threads_map[this] = numThreads;
-
- /* create task scheduler */
- size_t maxNumThreads = getMaxNumThreads();
- TaskScheduler::create(maxNumThreads,State::set_affinity,State::start_threads);
-#if USE_TASK_ARENA
- const size_t nThreads = min(maxNumThreads,TaskScheduler::threadCount());
- const size_t uThreads = min(max(numUserThreads,(size_t)1),nThreads);
- arena = make_unique(new tbb::task_arena((int)nThreads,(unsigned int)uThreads));
-#endif
- }
-
- void Device::exitTaskingSystem()
- {
- Lock<MutexSys> lock(g_mutex);
- g_num_threads_map.erase(this);
-
- /* terminate tasking system */
- if (g_num_threads_map.size() == 0) {
- TaskScheduler::destroy();
- }
- /* or configure new number of threads */
- else {
- size_t maxNumThreads = getMaxNumThreads();
- TaskScheduler::create(maxNumThreads,State::set_affinity,State::start_threads);
- }
-#if USE_TASK_ARENA
- arena.reset();
-#endif
- }
-
- void Device::setProperty(const RTCDeviceProperty prop, ssize_t val)
- {
- /* hidden internal properties */
- switch ((size_t)prop)
- {
- case 1000000: debug_int0 = val; return;
- case 1000001: debug_int1 = val; return;
- case 1000002: debug_int2 = val; return;
- case 1000003: debug_int3 = val; return;
- }
-
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown writable property");
- }
-
- ssize_t Device::getProperty(const RTCDeviceProperty prop)
- {
- size_t iprop = (size_t)prop;
-
- /* get name of internal regression test */
- if (iprop >= 2000000 && iprop < 3000000)
- {
- RegressionTest* test = getRegressionTest(iprop-2000000);
- if (test) return (ssize_t) test->name.c_str();
- else return 0;
- }
-
- /* run internal regression test */
- if (iprop >= 3000000 && iprop < 4000000)
- {
- RegressionTest* test = getRegressionTest(iprop-3000000);
- if (test) return test->run();
- else return 0;
- }
-
- /* documented properties */
- switch (prop)
- {
- case RTC_DEVICE_PROPERTY_VERSION_MAJOR: return RTC_VERSION_MAJOR;
- case RTC_DEVICE_PROPERTY_VERSION_MINOR: return RTC_VERSION_MINOR;
- case RTC_DEVICE_PROPERTY_VERSION_PATCH: return RTC_VERSION_PATCH;
- case RTC_DEVICE_PROPERTY_VERSION : return RTC_VERSION;
-
-#if defined(EMBREE_TARGET_SIMD4) && defined(EMBREE_RAY_PACKETS)
- case RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED: return hasISA(SSE2);
-#else
- case RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_TARGET_SIMD8) && defined(EMBREE_RAY_PACKETS)
- case RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED: return hasISA(AVX);
-#else
- case RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_TARGET_SIMD16) && defined(EMBREE_RAY_PACKETS)
- case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return hasISA(AVX512KNL) | hasISA(AVX512SKX);
-#else
- case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_RAY_PACKETS)
- case RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_RAY_MASK)
- case RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_BACKFACE_CULLING)
- case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED: return 0;
-#endif
-
-#if defined(EMBREE_BACKFACE_CULLING_CURVES)
- case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 0;
-#endif
-
-#if defined(EMBREE_COMPACT_POLYS)
- case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 0;
-#endif
-
-#if defined(EMBREE_FILTER_FUNCTION)
- case RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_IGNORE_INVALID_RAYS)
- case RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED: return 0;
-#endif
-
-#if defined(TASKING_INTERNAL)
- case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 0;
-#endif
-
-#if defined(TASKING_TBB)
- case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 1;
-#endif
-
-#if defined(TASKING_PPL)
- case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 2;
-#endif
-
-#if defined(TASKING_GCD) && defined(BUILD_IOS)
- case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 3;
-#endif
-
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- case RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_GEOMETRY_QUAD)
- case RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_GEOMETRY_CURVE)
- case RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_GEOMETRY_SUBDIVISION)
- case RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_GEOMETRY_USER)
- case RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED: return 0;
-#endif
-
-#if defined(EMBREE_GEOMETRY_POINT)
- case RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED: return 0;
-#endif
-
-#if defined(TASKING_PPL)
- case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 0;
-#elif defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)
- case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 0;
-#else
- case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 1;
-#endif
-
-#if defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION
- case RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED: return 1;
-#else
- case RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED: return 0;
-#endif
-
- default: throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown readable property"); break;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/device.h b/thirdparty/embree-aarch64/kernels/common/device.h
deleted file mode 100644
index e9a81bb109..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/device.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "state.h"
-#include "accel.h"
-
-namespace embree
-{
- class BVH4Factory;
- class BVH8Factory;
-
- class Device : public State, public MemoryMonitorInterface
- {
- ALIGNED_CLASS_(16);
-
- public:
-
- /*! Device construction */
- Device (const char* cfg);
-
- /*! Device destruction */
- virtual ~Device ();
-
- /*! prints info about the device */
- void print();
-
- /*! sets the error code */
- void setDeviceErrorCode(RTCError error);
-
- /*! returns and clears the error code */
- RTCError getDeviceErrorCode();
-
- /*! sets the error code */
- static void setThreadErrorCode(RTCError error);
-
- /*! returns and clears the error code */
- static RTCError getThreadErrorCode();
-
- /*! processes error codes, do not call directly */
- static void process_error(Device* device, RTCError error, const char* str);
-
- /*! invokes the memory monitor callback */
- void memoryMonitor(ssize_t bytes, bool post);
-
- /*! sets the size of the software cache. */
- void setCacheSize(size_t bytes);
-
- /*! sets a property */
- void setProperty(const RTCDeviceProperty prop, ssize_t val);
-
- /*! gets a property */
- ssize_t getProperty(const RTCDeviceProperty prop);
-
- private:
-
- /*! initializes the tasking system */
- void initTaskingSystem(size_t numThreads);
-
- /*! shuts down the tasking system */
- void exitTaskingSystem();
-
- /*! some variables that can be set via rtcSetParameter1i for debugging purposes */
- public:
- static ssize_t debug_int0;
- static ssize_t debug_int1;
- static ssize_t debug_int2;
- static ssize_t debug_int3;
-
- public:
- std::unique_ptr<BVH4Factory> bvh4_factory;
-#if defined(EMBREE_TARGET_SIMD8)
- std::unique_ptr<BVH8Factory> bvh8_factory;
-#endif
-
-#if USE_TASK_ARENA
- std::unique_ptr<tbb::task_arena> arena;
-#endif
-
- /* ray streams filter */
- RayStreamFilterFuncs rayStreamFilters;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/geometry.cpp b/thirdparty/embree-aarch64/kernels/common/geometry.cpp
deleted file mode 100644
index b3aa8e3396..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/geometry.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "geometry.h"
-#include "scene.h"
-
-namespace embree
-{
- const char* Geometry::gtype_names[Geometry::GTY_END] =
- {
- "flat_linear_curve",
- "round_linear_curve",
- "oriented_linear_curve",
- "",
- "flat_bezier_curve",
- "round_bezier_curve",
- "oriented_bezier_curve",
- "",
- "flat_bspline_curve",
- "round_bspline_curve",
- "oriented_bspline_curve",
- "",
- "flat_hermite_curve",
- "round_hermite_curve",
- "oriented_hermite_curve",
- "",
- "flat_catmull_rom_curve",
- "round_catmull_rom_curve",
- "oriented_catmull_rom_curve",
- "",
- "triangles",
- "quads",
- "grid",
- "subdivs",
- "",
- "sphere",
- "disc",
- "oriented_disc",
- "",
- "usergeom",
- "instance_cheap",
- "instance_expensive",
- };
-
- Geometry::Geometry (Device* device, GType gtype, unsigned int numPrimitives, unsigned int numTimeSteps)
- : device(device), userPtr(nullptr),
- numPrimitives(numPrimitives), numTimeSteps(unsigned(numTimeSteps)), fnumTimeSegments(float(numTimeSteps-1)), time_range(0.0f,1.0f),
- mask(-1),
- gtype(gtype),
- gsubtype(GTY_SUBTYPE_DEFAULT),
- quality(RTC_BUILD_QUALITY_MEDIUM),
- state((unsigned)State::MODIFIED),
- enabled(true),
- intersectionFilterN(nullptr), occlusionFilterN(nullptr), pointQueryFunc(nullptr)
- {
- device->refInc();
- }
-
- Geometry::~Geometry()
- {
- device->refDec();
- }
-
- void Geometry::setNumPrimitives(unsigned int numPrimitives_in)
- {
- if (numPrimitives_in == numPrimitives) return;
-
- numPrimitives = numPrimitives_in;
-
- Geometry::update();
- }
-
- void Geometry::setNumTimeSteps (unsigned int numTimeSteps_in)
- {
- if (numTimeSteps_in == numTimeSteps) {
- return;
- }
-
- numTimeSteps = numTimeSteps_in;
- fnumTimeSegments = float(numTimeSteps_in-1);
-
- Geometry::update();
- }
-
- void Geometry::setTimeRange (const BBox1f range)
- {
- time_range = range;
- Geometry::update();
- }
-
- void Geometry::update()
- {
- ++modCounter_; // FIXME: required?
- state = (unsigned)State::MODIFIED;
- }
-
- void Geometry::commit()
- {
- ++modCounter_;
- state = (unsigned)State::COMMITTED;
- }
-
- void Geometry::preCommit()
- {
- if (State::MODIFIED == (State)state)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"geometry not committed");
- }
-
- void Geometry::postCommit()
- {
- }
-
- void Geometry::enable ()
- {
- if (isEnabled())
- return;
-
- enabled = true;
- ++modCounter_;
- }
-
- void Geometry::disable ()
- {
- if (isDisabled())
- return;
-
- enabled = false;
- ++modCounter_;
- }
-
- void Geometry::setUserData (void* ptr)
- {
- userPtr = ptr;
- }
-
- void Geometry::setIntersectionFilterFunctionN (RTCFilterFunctionN filter)
- {
- if (!(getTypeMask() & (MTY_TRIANGLE_MESH | MTY_QUAD_MESH | MTY_CURVES | MTY_SUBDIV_MESH | MTY_USER_GEOMETRY | MTY_GRID_MESH)))
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"filter functions not supported for this geometry");
-
- intersectionFilterN = filter;
- }
-
- void Geometry::setOcclusionFilterFunctionN (RTCFilterFunctionN filter)
- {
- if (!(getTypeMask() & (MTY_TRIANGLE_MESH | MTY_QUAD_MESH | MTY_CURVES | MTY_SUBDIV_MESH | MTY_USER_GEOMETRY | MTY_GRID_MESH)))
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"filter functions not supported for this geometry");
-
- occlusionFilterN = filter;
- }
-
- void Geometry::setPointQueryFunction (RTCPointQueryFunction func)
- {
- pointQueryFunc = func;
- }
-
- void Geometry::interpolateN(const RTCInterpolateNArguments* const args)
- {
- const void* valid_i = args->valid;
- const unsigned* primIDs = args->primIDs;
- const float* u = args->u;
- const float* v = args->v;
- unsigned int N = args->N;
- RTCBufferType bufferType = args->bufferType;
- unsigned int bufferSlot = args->bufferSlot;
- float* P = args->P;
- float* dPdu = args->dPdu;
- float* dPdv = args->dPdv;
- float* ddPdudu = args->ddPdudu;
- float* ddPdvdv = args->ddPdvdv;
- float* ddPdudv = args->ddPdudv;
- unsigned int valueCount = args->valueCount;
-
- if (valueCount > 256) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"maximally 256 floating point values can be interpolated per vertex");
- const int* valid = (const int*) valid_i;
-
- __aligned(64) float P_tmp[256];
- __aligned(64) float dPdu_tmp[256];
- __aligned(64) float dPdv_tmp[256];
- __aligned(64) float ddPdudu_tmp[256];
- __aligned(64) float ddPdvdv_tmp[256];
- __aligned(64) float ddPdudv_tmp[256];
-
- float* Pt = P ? P_tmp : nullptr;
- float* dPdut = nullptr, *dPdvt = nullptr;
- if (dPdu) { dPdut = dPdu_tmp; dPdvt = dPdv_tmp; }
- float* ddPdudut = nullptr, *ddPdvdvt = nullptr, *ddPdudvt = nullptr;
- if (ddPdudu) { ddPdudut = ddPdudu_tmp; ddPdvdvt = ddPdvdv_tmp; ddPdudvt = ddPdudv_tmp; }
-
- for (unsigned int i=0; i<N; i++)
- {
- if (valid && !valid[i]) continue;
-
- RTCInterpolateArguments iargs;
- iargs.primID = primIDs[i];
- iargs.u = u[i];
- iargs.v = v[i];
- iargs.bufferType = bufferType;
- iargs.bufferSlot = bufferSlot;
- iargs.P = Pt;
- iargs.dPdu = dPdut;
- iargs.dPdv = dPdvt;
- iargs.ddPdudu = ddPdudut;
- iargs.ddPdvdv = ddPdvdvt;
- iargs.ddPdudv = ddPdudvt;
- iargs.valueCount = valueCount;
- interpolate(&iargs);
-
- if (likely(P)) {
- for (unsigned int j=0; j<valueCount; j++)
- P[j*N+i] = Pt[j];
- }
- if (likely(dPdu))
- {
- for (unsigned int j=0; j<valueCount; j++) {
- dPdu[j*N+i] = dPdut[j];
- dPdv[j*N+i] = dPdvt[j];
- }
- }
- if (likely(ddPdudu))
- {
- for (unsigned int j=0; j<valueCount; j++) {
- ddPdudu[j*N+i] = ddPdudut[j];
- ddPdvdv[j*N+i] = ddPdvdvt[j];
- ddPdudv[j*N+i] = ddPdudvt[j];
- }
- }
- }
- }
-
- bool Geometry::pointQuery(PointQuery* query, PointQueryContext* context)
- {
- assert(context->primID < size());
-
- RTCPointQueryFunctionArguments args;
- args.query = (RTCPointQuery*)context->query_ws;
- args.userPtr = context->userPtr;
- args.primID = context->primID;
- args.geomID = context->geomID;
- args.context = context->userContext;
- args.similarityScale = context->similarityScale;
-
- bool update = false;
- if(context->func) update |= context->func(&args);
- if(pointQueryFunc) update |= pointQueryFunc(&args);
-
- if (update && context->userContext->instStackSize > 0)
- {
- // update point query
- if (context->query_type == POINT_QUERY_TYPE_AABB) {
- context->updateAABB();
- } else {
- assert(context->similarityScale > 0.f);
- query->radius = context->query_ws->radius * context->similarityScale;
- }
- }
- return update;
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/geometry.h b/thirdparty/embree-aarch64/kernels/common/geometry.h
deleted file mode 100644
index 953974bfd2..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/geometry.h
+++ /dev/null
@@ -1,582 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "device.h"
-#include "buffer.h"
-#include "../common/point_query.h"
-#include "../builders/priminfo.h"
-
-namespace embree
-{
- class Scene;
- class Geometry;
-
- struct GeometryCounts
- {
- __forceinline GeometryCounts()
- : numFilterFunctions(0),
- numTriangles(0), numMBTriangles(0),
- numQuads(0), numMBQuads(0),
- numBezierCurves(0), numMBBezierCurves(0),
- numLineSegments(0), numMBLineSegments(0),
- numSubdivPatches(0), numMBSubdivPatches(0),
- numUserGeometries(0), numMBUserGeometries(0),
- numInstancesCheap(0), numMBInstancesCheap(0),
- numInstancesExpensive(0), numMBInstancesExpensive(0),
- numGrids(0), numMBGrids(0),
- numPoints(0), numMBPoints(0) {}
-
- __forceinline size_t size() const {
- return numTriangles + numQuads + numBezierCurves + numLineSegments + numSubdivPatches + numUserGeometries + numInstancesCheap + numInstancesExpensive + numGrids + numPoints
- + numMBTriangles + numMBQuads + numMBBezierCurves + numMBLineSegments + numMBSubdivPatches + numMBUserGeometries + numMBInstancesCheap + numMBInstancesExpensive + numMBGrids + numMBPoints;
- }
-
- __forceinline unsigned int enabledGeometryTypesMask() const
- {
- unsigned int mask = 0;
- if (numTriangles) mask |= 1 << 0;
- if (numQuads) mask |= 1 << 1;
- if (numBezierCurves+numLineSegments) mask |= 1 << 2;
- if (numSubdivPatches) mask |= 1 << 3;
- if (numUserGeometries) mask |= 1 << 4;
- if (numInstancesCheap) mask |= 1 << 5;
- if (numInstancesExpensive) mask |= 1 << 6;
- if (numGrids) mask |= 1 << 7;
- if (numPoints) mask |= 1 << 8;
-
- unsigned int maskMB = 0;
- if (numMBTriangles) maskMB |= 1 << 0;
- if (numMBQuads) maskMB |= 1 << 1;
- if (numMBBezierCurves+numMBLineSegments) maskMB |= 1 << 2;
- if (numMBSubdivPatches) maskMB |= 1 << 3;
- if (numMBUserGeometries) maskMB |= 1 << 4;
- if (numMBInstancesCheap) maskMB |= 1 << 5;
- if (numMBInstancesExpensive) maskMB |= 1 << 6;
- if (numMBGrids) maskMB |= 1 << 7;
- if (numMBPoints) maskMB |= 1 << 8;
-
- return (mask<<8) + maskMB;
- }
-
- __forceinline GeometryCounts operator+ (GeometryCounts const & rhs) const
- {
- GeometryCounts ret;
- ret.numFilterFunctions = numFilterFunctions + rhs.numFilterFunctions;
- ret.numTriangles = numTriangles + rhs.numTriangles;
- ret.numMBTriangles = numMBTriangles + rhs.numMBTriangles;
- ret.numQuads = numQuads + rhs.numQuads;
- ret.numMBQuads = numMBQuads + rhs.numMBQuads;
- ret.numBezierCurves = numBezierCurves + rhs.numBezierCurves;
- ret.numMBBezierCurves = numMBBezierCurves + rhs.numMBBezierCurves;
- ret.numLineSegments = numLineSegments + rhs.numLineSegments;
- ret.numMBLineSegments = numMBLineSegments + rhs.numMBLineSegments;
- ret.numSubdivPatches = numSubdivPatches + rhs.numSubdivPatches;
- ret.numMBSubdivPatches = numMBSubdivPatches + rhs.numMBSubdivPatches;
- ret.numUserGeometries = numUserGeometries + rhs.numUserGeometries;
- ret.numMBUserGeometries = numMBUserGeometries + rhs.numMBUserGeometries;
- ret.numInstancesCheap = numInstancesCheap + rhs.numInstancesCheap;
- ret.numMBInstancesCheap = numMBInstancesCheap + rhs.numMBInstancesCheap;
- ret.numInstancesExpensive = numInstancesExpensive + rhs.numInstancesExpensive;
- ret.numMBInstancesExpensive = numMBInstancesExpensive + rhs.numMBInstancesExpensive;
- ret.numGrids = numGrids + rhs.numGrids;
- ret.numMBGrids = numMBGrids + rhs.numMBGrids;
- ret.numPoints = numPoints + rhs.numPoints;
- ret.numMBPoints = numMBPoints + rhs.numMBPoints;
-
- return ret;
- }
-
- size_t numFilterFunctions; //!< number of geometries with filter functions enabled
- size_t numTriangles; //!< number of enabled triangles
- size_t numMBTriangles; //!< number of enabled motion blured triangles
- size_t numQuads; //!< number of enabled quads
- size_t numMBQuads; //!< number of enabled motion blurred quads
- size_t numBezierCurves; //!< number of enabled curves
- size_t numMBBezierCurves; //!< number of enabled motion blurred curves
- size_t numLineSegments; //!< number of enabled line segments
- size_t numMBLineSegments; //!< number of enabled line motion blurred segments
- size_t numSubdivPatches; //!< number of enabled subdivision patches
- size_t numMBSubdivPatches; //!< number of enabled motion blured subdivision patches
- size_t numUserGeometries; //!< number of enabled user geometries
- size_t numMBUserGeometries; //!< number of enabled motion blurred user geometries
- size_t numInstancesCheap; //!< number of enabled cheap instances
- size_t numMBInstancesCheap; //!< number of enabled motion blurred cheap instances
- size_t numInstancesExpensive; //!< number of enabled expensive instances
- size_t numMBInstancesExpensive; //!< number of enabled motion blurred expensive instances
- size_t numGrids; //!< number of enabled grid geometries
- size_t numMBGrids; //!< number of enabled motion blurred grid geometries
- size_t numPoints; //!< number of enabled points
- size_t numMBPoints; //!< number of enabled motion blurred points
- };
-
- /*! Base class all geometries are derived from */
- class Geometry : public RefCount
- {
- friend class Scene;
- public:
-
- /*! type of geometry */
- enum GType
- {
- GTY_FLAT_LINEAR_CURVE = 0,
- GTY_ROUND_LINEAR_CURVE = 1,
- GTY_ORIENTED_LINEAR_CURVE = 2,
- GTY_CONE_LINEAR_CURVE = 3,
-
- GTY_FLAT_BEZIER_CURVE = 4,
- GTY_ROUND_BEZIER_CURVE = 5,
- GTY_ORIENTED_BEZIER_CURVE = 6,
-
- GTY_FLAT_BSPLINE_CURVE = 8,
- GTY_ROUND_BSPLINE_CURVE = 9,
- GTY_ORIENTED_BSPLINE_CURVE = 10,
-
- GTY_FLAT_HERMITE_CURVE = 12,
- GTY_ROUND_HERMITE_CURVE = 13,
- GTY_ORIENTED_HERMITE_CURVE = 14,
-
- GTY_FLAT_CATMULL_ROM_CURVE = 16,
- GTY_ROUND_CATMULL_ROM_CURVE = 17,
- GTY_ORIENTED_CATMULL_ROM_CURVE = 18,
-
- GTY_TRIANGLE_MESH = 20,
- GTY_QUAD_MESH = 21,
- GTY_GRID_MESH = 22,
- GTY_SUBDIV_MESH = 23,
-
- GTY_SPHERE_POINT = 25,
- GTY_DISC_POINT = 26,
- GTY_ORIENTED_DISC_POINT = 27,
-
- GTY_USER_GEOMETRY = 29,
- GTY_INSTANCE_CHEAP = 30,
- GTY_INSTANCE_EXPENSIVE = 31,
- GTY_END = 32,
-
- GTY_BASIS_LINEAR = 0,
- GTY_BASIS_BEZIER = 4,
- GTY_BASIS_BSPLINE = 8,
- GTY_BASIS_HERMITE = 12,
- GTY_BASIS_CATMULL_ROM = 16,
- GTY_BASIS_MASK = 28,
-
- GTY_SUBTYPE_FLAT_CURVE = 0,
- GTY_SUBTYPE_ROUND_CURVE = 1,
- GTY_SUBTYPE_ORIENTED_CURVE = 2,
- GTY_SUBTYPE_MASK = 3,
- };
-
- enum GSubType
- {
- GTY_SUBTYPE_DEFAULT= 0,
- GTY_SUBTYPE_INSTANCE_LINEAR = 0,
- GTY_SUBTYPE_INSTANCE_QUATERNION = 1
- };
-
- enum GTypeMask
- {
- MTY_FLAT_LINEAR_CURVE = 1ul << GTY_FLAT_LINEAR_CURVE,
- MTY_ROUND_LINEAR_CURVE = 1ul << GTY_ROUND_LINEAR_CURVE,
- MTY_CONE_LINEAR_CURVE = 1ul << GTY_CONE_LINEAR_CURVE,
- MTY_ORIENTED_LINEAR_CURVE = 1ul << GTY_ORIENTED_LINEAR_CURVE,
-
- MTY_FLAT_BEZIER_CURVE = 1ul << GTY_FLAT_BEZIER_CURVE,
- MTY_ROUND_BEZIER_CURVE = 1ul << GTY_ROUND_BEZIER_CURVE,
- MTY_ORIENTED_BEZIER_CURVE = 1ul << GTY_ORIENTED_BEZIER_CURVE,
-
- MTY_FLAT_BSPLINE_CURVE = 1ul << GTY_FLAT_BSPLINE_CURVE,
- MTY_ROUND_BSPLINE_CURVE = 1ul << GTY_ROUND_BSPLINE_CURVE,
- MTY_ORIENTED_BSPLINE_CURVE = 1ul << GTY_ORIENTED_BSPLINE_CURVE,
-
- MTY_FLAT_HERMITE_CURVE = 1ul << GTY_FLAT_HERMITE_CURVE,
- MTY_ROUND_HERMITE_CURVE = 1ul << GTY_ROUND_HERMITE_CURVE,
- MTY_ORIENTED_HERMITE_CURVE = 1ul << GTY_ORIENTED_HERMITE_CURVE,
-
- MTY_FLAT_CATMULL_ROM_CURVE = 1ul << GTY_FLAT_CATMULL_ROM_CURVE,
- MTY_ROUND_CATMULL_ROM_CURVE = 1ul << GTY_ROUND_CATMULL_ROM_CURVE,
- MTY_ORIENTED_CATMULL_ROM_CURVE = 1ul << GTY_ORIENTED_CATMULL_ROM_CURVE,
-
- MTY_CURVE2 = MTY_FLAT_LINEAR_CURVE | MTY_ROUND_LINEAR_CURVE | MTY_CONE_LINEAR_CURVE | MTY_ORIENTED_LINEAR_CURVE,
-
- MTY_CURVE4 = MTY_FLAT_BEZIER_CURVE | MTY_ROUND_BEZIER_CURVE | MTY_ORIENTED_BEZIER_CURVE |
- MTY_FLAT_BSPLINE_CURVE | MTY_ROUND_BSPLINE_CURVE | MTY_ORIENTED_BSPLINE_CURVE |
- MTY_FLAT_HERMITE_CURVE | MTY_ROUND_HERMITE_CURVE | MTY_ORIENTED_HERMITE_CURVE |
- MTY_FLAT_CATMULL_ROM_CURVE | MTY_ROUND_CATMULL_ROM_CURVE | MTY_ORIENTED_CATMULL_ROM_CURVE,
-
- MTY_SPHERE_POINT = 1ul << GTY_SPHERE_POINT,
- MTY_DISC_POINT = 1ul << GTY_DISC_POINT,
- MTY_ORIENTED_DISC_POINT = 1ul << GTY_ORIENTED_DISC_POINT,
-
- MTY_POINTS = MTY_SPHERE_POINT | MTY_DISC_POINT | MTY_ORIENTED_DISC_POINT,
-
- MTY_CURVES = MTY_CURVE2 | MTY_CURVE4 | MTY_POINTS,
-
- MTY_TRIANGLE_MESH = 1ul << GTY_TRIANGLE_MESH,
- MTY_QUAD_MESH = 1ul << GTY_QUAD_MESH,
- MTY_GRID_MESH = 1ul << GTY_GRID_MESH,
- MTY_SUBDIV_MESH = 1ul << GTY_SUBDIV_MESH,
- MTY_USER_GEOMETRY = 1ul << GTY_USER_GEOMETRY,
-
- MTY_INSTANCE_CHEAP = 1ul << GTY_INSTANCE_CHEAP,
- MTY_INSTANCE_EXPENSIVE = 1ul << GTY_INSTANCE_EXPENSIVE,
- MTY_INSTANCE = MTY_INSTANCE_CHEAP | MTY_INSTANCE_EXPENSIVE
- };
-
- static const char* gtype_names[GTY_END];
-
- enum class State : unsigned {
- MODIFIED = 0,
- COMMITTED = 1,
- };
-
- public:
-
- /*! Geometry constructor */
- Geometry (Device* device, GType gtype, unsigned int numPrimitives, unsigned int numTimeSteps);
-
- /*! Geometry destructor */
- virtual ~Geometry();
-
- public:
-
- /*! tests if geometry is enabled */
- __forceinline bool isEnabled() const { return enabled; }
-
- /*! tests if geometry is disabled */
- __forceinline bool isDisabled() const { return !isEnabled(); }
-
- /*! tests if that geometry has some filter function set */
- __forceinline bool hasFilterFunctions () const {
- return (intersectionFilterN != nullptr) || (occlusionFilterN != nullptr);
- }
-
- /*! returns geometry type */
- __forceinline GType getType() const { return gtype; }
-
- /*! returns curve type */
- __forceinline GType getCurveType() const { return (GType)(gtype & GTY_SUBTYPE_MASK); }
-
- /*! returns curve basis */
- __forceinline GType getCurveBasis() const { return (GType)(gtype & GTY_BASIS_MASK); }
-
- /*! returns geometry type mask */
- __forceinline GTypeMask getTypeMask() const { return (GTypeMask)(1 << gtype); }
-
- /*! returns number of primitives */
- __forceinline size_t size() const { return numPrimitives; }
-
- /*! sets the number of primitives */
- virtual void setNumPrimitives(unsigned int numPrimitives_in);
-
- /*! sets number of time steps */
- virtual void setNumTimeSteps (unsigned int numTimeSteps_in);
-
- /*! sets motion blur time range */
- void setTimeRange (const BBox1f range);
-
- /*! sets number of vertex attributes */
- virtual void setVertexAttributeCount (unsigned int N) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! sets number of topologies */
- virtual void setTopologyCount (unsigned int N) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! sets the build quality */
- void setBuildQuality(RTCBuildQuality quality_in)
- {
- this->quality = quality_in;
- Geometry::update();
- }
-
- /* calculate time segment itime and fractional time ftime */
- __forceinline int timeSegment(float time, float& ftime) const {
- return getTimeSegment(time,time_range.lower,time_range.upper,fnumTimeSegments,ftime);
- }
-
- template<int N>
- __forceinline vint<N> timeSegment(const vfloat<N>& time, vfloat<N>& ftime) const {
- return getTimeSegment(time,vfloat<N>(time_range.lower),vfloat<N>(time_range.upper),vfloat<N>(fnumTimeSegments),ftime);
- }
-
- /* calculate overlapping time segment range */
- __forceinline range<int> timeSegmentRange(const BBox1f& range) const {
- return getTimeSegmentRange(range,time_range,fnumTimeSegments);
- }
-
- /* returns time that corresponds to time step */
- __forceinline float timeStep(const int i) const {
- assert(i>=0 && i<(int)numTimeSteps);
- return time_range.lower + time_range.size()*float(i)/fnumTimeSegments;
- }
-
- /*! for all geometries */
- public:
-
- /*! Enable geometry. */
- virtual void enable();
-
- /*! Update geometry. */
- void update();
-
- /*! commit of geometry */
- virtual void commit();
-
- /*! Update geometry buffer. */
- virtual void updateBuffer(RTCBufferType type, unsigned int slot) {
- update(); // update everything for geometries not supporting this call
- }
-
- /*! Disable geometry. */
- virtual void disable();
-
- /*! Verify the geometry */
- virtual bool verify() { return true; }
-
- /*! called before every build */
- virtual void preCommit();
-
- /*! called after every build */
- virtual void postCommit();
-
- virtual void addElementsToCount (GeometryCounts & counts) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- };
-
- /*! sets constant tessellation rate for the geometry */
- virtual void setTessellationRate(float N) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Sets the maximal curve radius scale allowed by min-width feature. */
- virtual void setMaxRadiusScale(float s) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Set user data pointer. */
- virtual void setUserData(void* ptr);
-
- /*! Get user data pointer. */
- __forceinline void* getUserData() const {
- return userPtr;
- }
-
- /*! interpolates user data to the specified u/v location */
- virtual void interpolate(const RTCInterpolateArguments* const args) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! interpolates user data to the specified u/v locations */
- virtual void interpolateN(const RTCInterpolateNArguments* const args);
-
- /* point query api */
- bool pointQuery(PointQuery* query, PointQueryContext* context);
-
- /*! for subdivision surfaces only */
- public:
- virtual void setSubdivisionMode (unsigned topologyID, RTCSubdivisionMode mode) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- virtual void setVertexAttributeTopology(unsigned int vertexBufferSlot, unsigned int indexBufferSlot) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Set displacement function. */
- virtual void setDisplacementFunction (RTCDisplacementFunctionN filter) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- virtual unsigned int getFirstHalfEdge(unsigned int faceID) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- virtual unsigned int getFace(unsigned int edgeID) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- virtual unsigned int getNextHalfEdge(unsigned int edgeID) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- virtual unsigned int getPreviousHalfEdge(unsigned int edgeID) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- virtual unsigned int getOppositeHalfEdge(unsigned int topologyID, unsigned int edgeID) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! get fast access to first vertex buffer if applicable */
- virtual float * getCompactVertexArray () const {
- return nullptr;
- }
-
- /*! Returns the modified counter - how many times the geo has been modified */
- __forceinline unsigned int getModCounter () const {
- return modCounter_;
- }
-
- /*! for triangle meshes and bezier curves only */
- public:
-
-
- /*! Sets ray mask. */
- virtual void setMask(unsigned mask) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Sets specified buffer. */
- virtual void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Gets specified buffer. */
- virtual void* getBuffer(RTCBufferType type, unsigned int slot) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Set intersection filter function for ray packets of size N. */
- virtual void setIntersectionFilterFunctionN (RTCFilterFunctionN filterN);
-
- /*! Set occlusion filter function for ray packets of size N. */
- virtual void setOcclusionFilterFunctionN (RTCFilterFunctionN filterN);
-
- /*! for instances only */
- public:
-
- /*! Sets the instanced scene */
- virtual void setInstancedScene(const Ref<Scene>& scene) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Sets transformation of the instance */
- virtual void setTransform(const AffineSpace3fa& transform, unsigned int timeStep) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Sets transformation of the instance */
- virtual void setQuaternionDecomposition(const AffineSpace3ff& qd, unsigned int timeStep) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Returns the transformation of the instance */
- virtual AffineSpace3fa getTransform(float time) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! for user geometries only */
- public:
-
- /*! Set bounds function. */
- virtual void setBoundsFunction (RTCBoundsFunction bounds, void* userPtr) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Set intersect function for ray packets of size N. */
- virtual void setIntersectFunctionN (RTCIntersectFunctionN intersect) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Set occlusion function for ray packets of size N. */
- virtual void setOccludedFunctionN (RTCOccludedFunctionN occluded) {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
- }
-
- /*! Set point query function. */
- void setPointQueryFunction(RTCPointQueryFunction func);
-
- /*! returns number of time segments */
- __forceinline unsigned numTimeSegments () const {
- return numTimeSteps-1;
- }
-
- public:
-
- virtual PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"createPrimRefArray not implemented for this geometry");
- }
-
- virtual PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"createPrimRefMBArray not implemented for this geometry");
- }
-
- virtual PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"createPrimRefMBArray not implemented for this geometry");
- }
-
- virtual LinearSpace3fa computeAlignedSpace(const size_t primID) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"computeAlignedSpace not implemented for this geometry");
- }
-
- virtual LinearSpace3fa computeAlignedSpaceMB(const size_t primID, const BBox1f time_range) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"computeAlignedSpace not implemented for this geometry");
- }
-
- virtual Vec3fa computeDirection(unsigned int primID) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"computeDirection not implemented for this geometry");
- }
-
- virtual Vec3fa computeDirection(unsigned int primID, size_t time) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"computeDirection not implemented for this geometry");
- }
-
- virtual BBox3fa vbounds(size_t primID) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vbounds not implemented for this geometry");
- }
-
- virtual BBox3fa vbounds(const LinearSpace3fa& space, size_t primID) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vbounds not implemented for this geometry");
- }
-
- virtual BBox3fa vbounds(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vbounds not implemented for this geometry");
- }
-
- virtual LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vlinearBounds not implemented for this geometry");
- }
-
- virtual LBBox3fa vlinearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vlinearBounds not implemented for this geometry");
- }
-
- virtual LBBox3fa vlinearBounds(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vlinearBounds not implemented for this geometry");
- }
-
- public:
- __forceinline bool hasIntersectionFilter() const { return intersectionFilterN != nullptr; }
- __forceinline bool hasOcclusionFilter() const { return occlusionFilterN != nullptr; }
-
- public:
- Device* device; //!< device this geometry belongs to
-
- void* userPtr; //!< user pointer
- unsigned int numPrimitives; //!< number of primitives of this geometry
-
- unsigned int numTimeSteps; //!< number of time steps
- float fnumTimeSegments; //!< number of time segments (precalculation)
- BBox1f time_range; //!< motion blur time range
-
- unsigned int mask; //!< for masking out geometry
- unsigned int modCounter_ = 1; //!< counter for every modification - used to rebuild scenes when geo is modified
-
- struct {
- GType gtype : 8; //!< geometry type
- GSubType gsubtype : 8; //!< geometry subtype
- RTCBuildQuality quality : 3; //!< build quality for geometry
- unsigned state : 2;
- bool enabled : 1; //!< true if geometry is enabled
- };
-
- RTCFilterFunctionN intersectionFilterN;
- RTCFilterFunctionN occlusionFilterN;
- RTCPointQueryFunction pointQueryFunc;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/hit.h b/thirdparty/embree-aarch64/kernels/common/hit.h
deleted file mode 100644
index 32a198cdfe..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/hit.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "ray.h"
-#include "instance_stack.h"
-
-namespace embree
-{
- /* Hit structure for K hits */
- template<int K>
- struct HitK
- {
- /* Default construction does nothing */
- __forceinline HitK() {}
-
- /* Constructs a hit */
- __forceinline HitK(const RTCIntersectContext* context, const vuint<K>& geomID, const vuint<K>& primID, const vfloat<K>& u, const vfloat<K>& v, const Vec3vf<K>& Ng)
- : Ng(Ng), u(u), v(v), primID(primID), geomID(geomID)
- {
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- instID[l] = RTC_INVALID_GEOMETRY_ID;
- instance_id_stack::copy(context->instID, instID);
- }
-
- /* Returns the size of the hit */
- static __forceinline size_t size() { return K; }
-
- public:
- Vec3vf<K> Ng; // geometry normal
- vfloat<K> u; // barycentric u coordinate of hit
- vfloat<K> v; // barycentric v coordinate of hit
- vuint<K> primID; // primitive ID
- vuint<K> geomID; // geometry ID
- vuint<K> instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
- };
-
- /* Specialization for a single hit */
- template<>
- struct __aligned(16) HitK<1>
- {
- /* Default construction does nothing */
- __forceinline HitK() {}
-
- /* Constructs a hit */
- __forceinline HitK(const RTCIntersectContext* context, unsigned int geomID, unsigned int primID, float u, float v, const Vec3fa& Ng)
- : Ng(Ng.x,Ng.y,Ng.z), u(u), v(v), primID(primID), geomID(geomID)
- {
- instance_id_stack::copy(context->instID, instID);
- }
-
- /* Returns the size of the hit */
- static __forceinline size_t size() { return 1; }
-
- public:
- Vec3<float> Ng; // geometry normal
- float u; // barycentric u coordinate of hit
- float v; // barycentric v coordinate of hit
- unsigned int primID; // primitive ID
- unsigned int geomID; // geometry ID
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
- };
-
- /* Shortcuts */
- typedef HitK<1> Hit;
- typedef HitK<4> Hit4;
- typedef HitK<8> Hit8;
- typedef HitK<16> Hit16;
-
- /* Outputs hit to stream */
- template<int K>
- __forceinline embree_ostream operator<<(embree_ostream cout, const HitK<K>& ray)
- {
- cout << "{ " << embree_endl
- << " Ng = " << ray.Ng << embree_endl
- << " u = " << ray.u << embree_endl
- << " v = " << ray.v << embree_endl
- << " primID = " << ray.primID << embree_endl
- << " geomID = " << ray.geomID << embree_endl
- << " instID =";
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- {
- cout << " " << ray.instID[l];
- }
- cout << embree_endl;
- return cout << "}";
- }
-
- template<typename Hit>
- __forceinline void copyHitToRay(RayHit& ray, const Hit& hit)
- {
- ray.Ng = hit.Ng;
- ray.u = hit.u;
- ray.v = hit.v;
- ray.primID = hit.primID;
- ray.geomID = hit.geomID;
- instance_id_stack::copy(hit.instID, ray.instID);
- }
-
- template<int K>
- __forceinline void copyHitToRay(const vbool<K> &mask, RayHitK<K> &ray, const HitK<K> &hit)
- {
- vfloat<K>::storeu(mask,&ray.Ng.x, hit.Ng.x);
- vfloat<K>::storeu(mask,&ray.Ng.y, hit.Ng.y);
- vfloat<K>::storeu(mask,&ray.Ng.z, hit.Ng.z);
- vfloat<K>::storeu(mask,&ray.u, hit.u);
- vfloat<K>::storeu(mask,&ray.v, hit.v);
- vuint<K>::storeu(mask,&ray.primID, hit.primID);
- vuint<K>::storeu(mask,&ray.geomID, hit.geomID);
- instance_id_stack::copy(hit.instID, ray.instID, mask);
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/instance_stack.h b/thirdparty/embree-aarch64/kernels/common/instance_stack.h
deleted file mode 100644
index d7e3637f7b..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/instance_stack.h
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "rtcore.h"
-
-namespace embree {
-namespace instance_id_stack {
-
-static_assert(RTC_MAX_INSTANCE_LEVEL_COUNT > 0,
- "RTC_MAX_INSTANCE_LEVEL_COUNT must be greater than 0.");
-
-/*******************************************************************************
- * Instance ID stack manipulation.
- * This is used from the instance intersector.
- ******************************************************************************/
-
-/*
- * Push an instance to the stack.
- */
-RTC_FORCEINLINE bool push(RTCIntersectContext* context,
- unsigned instanceId)
-{
-#if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
- const bool spaceAvailable = context->instStackSize < RTC_MAX_INSTANCE_LEVEL_COUNT;
- /* We assert here because instances are silently dropped when the stack is full.
- This might be quite hard to find in production. */
- assert(spaceAvailable);
- if (likely(spaceAvailable))
- context->instID[context->instStackSize++] = instanceId;
- return spaceAvailable;
-#else
- const bool spaceAvailable = (context->instID[0] == RTC_INVALID_GEOMETRY_ID);
- assert(spaceAvailable);
- if (likely(spaceAvailable))
- context->instID[0] = instanceId;
- return spaceAvailable;
-#endif
-}
-
-
-/*
- * Pop the last instance pushed to the stack.
- * Do not call on an empty stack.
- */
-RTC_FORCEINLINE void pop(RTCIntersectContext* context)
-{
- assert(context);
-#if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
- assert(context->instStackSize > 0);
- context->instID[--context->instStackSize] = RTC_INVALID_GEOMETRY_ID;
-#else
- assert(context->instID[0] != RTC_INVALID_GEOMETRY_ID);
- context->instID[0] = RTC_INVALID_GEOMETRY_ID;
-#endif
-}
-
-/*******************************************************************************
- * Optimized instance id stack copy.
- * The copy() function at the bottom of this block will either copy full
- * stacks or copy only until the last valid element has been copied, depending
- * on RTC_MAX_INSTANCE_LEVEL_COUNT.
- ******************************************************************************/
-
-/*
- * Plain array assignment. This works for scalar->scalar,
- * scalar->vector, and vector->vector.
- */
-template <class Src, class Tgt>
-RTC_FORCEINLINE void level_copy(unsigned level, Src* src, Tgt* tgt)
-{
- tgt[level] = src[level];
-}
-
-/*
- * Masked SIMD vector->vector store.
- */
-template <int K>
-RTC_FORCEINLINE void level_copy(unsigned level, const vuint<K>* src, vuint<K>* tgt, const vbool<K>& mask)
-{
- vuint<K>::storeu(mask, tgt + level, src[level]);
-}
-
-/*
- * Masked scalar->SIMD vector store.
- */
-template <int K>
-RTC_FORCEINLINE void level_copy(unsigned level, const unsigned* src, vuint<K>* tgt, const vbool<K>& mask)
-{
- vuint<K>::store(mask, tgt + level, src[level]);
-}
-
-/*
- * Indexed assign from vector to scalar.
- */
-template <int K>
-RTC_FORCEINLINE void level_copy(unsigned level, const vuint<K>* src, unsigned* tgt, const size_t& idx)
-{
- tgt[level] = src[level][idx];
-}
-
-/*
- * Indexed assign from scalar to vector.
- */
-template <int K>
-RTC_FORCEINLINE void level_copy(unsigned level, const unsigned* src, vuint<K>* tgt, const size_t& idx)
-{
- tgt[level][idx] = src[level];
-}
-
-/*
- * Indexed assign from vector to vector.
- */
-template <int K>
-RTC_FORCEINLINE void level_copy(unsigned level, const vuint<K>* src, vuint<K>* tgt, const size_t& i, const size_t& j)
-{
- tgt[level][j] = src[level][i];
-}
-
-/*
- * Check if the given stack level is valid.
- * These are only used for large max stack sizes.
- */
-RTC_FORCEINLINE bool level_valid(unsigned level, const unsigned* stack)
-{
- return stack[level] != RTC_INVALID_GEOMETRY_ID;
-}
-RTC_FORCEINLINE bool level_valid(unsigned level, const unsigned* stack, const size_t& /*i*/)
-{
- return stack[level] != RTC_INVALID_GEOMETRY_ID;
-}
-template <int K>
-RTC_FORCEINLINE bool level_valid(unsigned level, const unsigned* stack, const vbool<K>& /*mask*/)
-{
- return stack[level] != RTC_INVALID_GEOMETRY_ID;
-}
-
-template <int K>
-RTC_FORCEINLINE bool level_valid(unsigned level, const vuint<K>* stack)
-{
- return any(stack[level] != RTC_INVALID_GEOMETRY_ID);
-}
-template <int K>
-RTC_FORCEINLINE bool level_valid(unsigned level, const vuint<K>* stack, const vbool<K>& mask)
-{
- return any(mask & (stack[level] != RTC_INVALID_GEOMETRY_ID));
-}
-
-template <int K>
-RTC_FORCEINLINE bool level_valid(unsigned level, const vuint<K>* stack, const size_t& i)
-{
- return stack[level][i] != RTC_INVALID_GEOMETRY_ID;
-}
-template <int K>
-RTC_FORCEINLINE bool level_valid(unsigned level, const vuint<K>* stack, const size_t& i, const size_t& /*j*/)
-{
- return stack[level][i] != RTC_INVALID_GEOMETRY_ID;
-}
-
-/*
- * Copy an instance ID stack.
- *
- * This function automatically selects a LevelFunctor from the above Assign
- * structs.
- */
-template <class Src, class Tgt, class... Args>
-RTC_FORCEINLINE void copy(Src src, Tgt tgt, Args&&... args)
-{
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
- /*
- * Avoid all loops for only one level.
- */
- level_copy(0, src, tgt, std::forward<Args>(args)...);
-
-#elif (RTC_MAX_INSTANCE_LEVEL_COUNT <= 4)
- /*
- * It is faster to avoid the valid test for low level counts.
- * Just copy the whole stack.
- */
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- level_copy(l, src, tgt, std::forward<Args>(args)...);
-
-#else
- /*
- * For general stack sizes, it pays off to test for validity.
- */
- bool valid = true;
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT && valid; ++l)
- {
- level_copy(l, src, tgt, std::forward<Args>(args)...);
- valid = level_valid(l, src, std::forward<Args>(args)...);
- }
-#endif
-}
-
-} // namespace instance_id_stack
-} // namespace embree
-
diff --git a/thirdparty/embree-aarch64/kernels/common/isa.h b/thirdparty/embree-aarch64/kernels/common/isa.h
deleted file mode 100644
index 63fb8d3351..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/isa.h
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../../common/sys/platform.h"
-#include "../../common/sys/sysinfo.h"
-
-namespace embree
-{
-#define DEFINE_SYMBOL2(type,name) \
- typedef type (*name##Func)(); \
- name##Func name;
-
-#define DECLARE_SYMBOL2(type,name) \
- namespace sse2 { extern type name(); } \
- namespace sse42 { extern type name(); } \
- namespace avx { extern type name(); } \
- namespace avx2 { extern type name(); } \
- namespace avx512knl { extern type name(); } \
- namespace avx512skx { extern type name(); } \
- void name##_error2() { throw_RTCError(RTC_ERROR_UNKNOWN,"internal error in ISA selection for " TOSTRING(name)); } \
- type name##_error() { return type(name##_error2); } \
- type name##_zero() { return type(nullptr); }
-
-#define DECLARE_ISA_FUNCTION(type,symbol,args) \
- namespace sse2 { extern type symbol(args); } \
- namespace sse42 { extern type symbol(args); } \
- namespace avx { extern type symbol(args); } \
- namespace avx2 { extern type symbol(args); } \
- namespace avx512knl { extern type symbol(args); } \
- namespace avx512skx { extern type symbol(args); } \
- inline type symbol##_error(args) { throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"function " TOSTRING(symbol) " not supported by your CPU"); } \
- typedef type (*symbol##Ty)(args); \
-
-#define DEFINE_ISA_FUNCTION(type,symbol,args) \
- typedef type (*symbol##Func)(args); \
- symbol##Func symbol;
-
-#define ZERO_SYMBOL(features,intersector) \
- intersector = intersector##_zero;
-
-#define INIT_SYMBOL(features,intersector) \
- intersector = decltype(intersector)(intersector##_error);
-
-#define SELECT_SYMBOL_DEFAULT(features,intersector) \
- intersector = isa::intersector;
-
-#if defined(__SSE__) || defined(__ARM_NEON)
-#if !defined(EMBREE_TARGET_SIMD4)
-#define EMBREE_TARGET_SIMD4
-#endif
-#endif
-
-#if defined(EMBREE_TARGET_SSE42)
-#define SELECT_SYMBOL_SSE42(features,intersector) \
- if ((features & SSE42) == SSE42) intersector = sse42::intersector;
-#else
-#define SELECT_SYMBOL_SSE42(features,intersector)
-#endif
-
-#if defined(EMBREE_TARGET_AVX) || defined(__AVX__)
-#if !defined(EMBREE_TARGET_SIMD8)
-#define EMBREE_TARGET_SIMD8
-#endif
-#if defined(__AVX__) // if default ISA is >= AVX we treat AVX target as default target
-#define SELECT_SYMBOL_AVX(features,intersector) \
- if ((features & ISA) == ISA) intersector = isa::intersector;
-#else
-#define SELECT_SYMBOL_AVX(features,intersector) \
- if ((features & AVX) == AVX) intersector = avx::intersector;
-#endif
-#else
-#define SELECT_SYMBOL_AVX(features,intersector)
-#endif
-
-#if defined(EMBREE_TARGET_AVX2)
-#if !defined(EMBREE_TARGET_SIMD8)
-#define EMBREE_TARGET_SIMD8
-#endif
-#define SELECT_SYMBOL_AVX2(features,intersector) \
- if ((features & AVX2) == AVX2) intersector = avx2::intersector;
-#else
-#define SELECT_SYMBOL_AVX2(features,intersector)
-#endif
-
-#if defined(EMBREE_TARGET_AVX512KNL)
-#if !defined(EMBREE_TARGET_SIMD16)
-#define EMBREE_TARGET_SIMD16
-#endif
-#define SELECT_SYMBOL_AVX512KNL(features,intersector) \
- if ((features & AVX512KNL) == AVX512KNL) intersector = avx512knl::intersector;
-#else
-#define SELECT_SYMBOL_AVX512KNL(features,intersector)
-#endif
-
-#if defined(EMBREE_TARGET_AVX512SKX)
-#if !defined(EMBREE_TARGET_SIMD16)
-#define EMBREE_TARGET_SIMD16
-#endif
-#define SELECT_SYMBOL_AVX512SKX(features,intersector) \
- if ((features & AVX512SKX) == AVX512SKX) intersector = avx512skx::intersector;
-#else
-#define SELECT_SYMBOL_AVX512SKX(features,intersector)
-#endif
-
-#define SELECT_SYMBOL_DEFAULT_SSE42(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_SSE42_AVX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_AVX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_AVX_AVX2(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL_AVX512SKX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_AVX_AVX512SKX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_INIT_AVX(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector);
-
-#define SELECT_SYMBOL_INIT_AVX_AVX2(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector);
-
-#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector);
-
-#define SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector);
-
-#define SELECT_SYMBOL_INIT_AVX_AVX512KNL_AVX512SKX(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector);
-
-#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_ZERO_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
- ZERO_SYMBOL(features,intersector); \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
- SELECT_SYMBOL_DEFAULT(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,intersector) \
- INIT_SYMBOL(features,intersector); \
- SELECT_SYMBOL_AVX512KNL(features,intersector); \
- SELECT_SYMBOL_AVX512SKX(features,intersector);
-
-#define SELECT_SYMBOL_SSE42_AVX_AVX2(features,intersector) \
- SELECT_SYMBOL_SSE42(features,intersector); \
- SELECT_SYMBOL_AVX(features,intersector); \
- SELECT_SYMBOL_AVX2(features,intersector);
-
- struct VerifyMultiTargetLinking {
- static __noinline int getISA(int depth = 5) {
- if (depth == 0) return ISA;
- else return getISA(depth-1);
- }
- };
- namespace sse2 { int getISA(); };
- namespace sse42 { int getISA(); };
- namespace avx { int getISA(); };
- namespace avx2 { int getISA(); };
- namespace avx512knl { int getISA(); };
- namespace avx512skx { int getISA(); };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/motion_derivative.h b/thirdparty/embree-aarch64/kernels/common/motion_derivative.h
deleted file mode 100644
index 82953f0e89..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/motion_derivative.h
+++ /dev/null
@@ -1,325 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../../common/math/affinespace.h"
-#include "../../common/math/interval.h"
-
-#include <functional>
-
-namespace embree {
-
-#define MOTION_DERIVATIVE_ROOT_EPSILON 1e-4f
-
-static void motion_derivative_coefficients(const float *p, float *coeff);
-
-struct MotionDerivativeCoefficients
-{
- float theta;
- float coeffs[3*8*7];
-
- MotionDerivativeCoefficients() {}
-
- // xfm0 and xfm1 are interpret as quaternion decomposition
- MotionDerivativeCoefficients(AffineSpace3ff const& xfm0, AffineSpace3ff const& xfm1)
- {
- // cosTheta of the two quaternions
- const float cosTheta = min(1.f, max(-1.f,
- xfm0.l.vx.w * xfm1.l.vx.w
- + xfm0.l.vy.w * xfm1.l.vy.w
- + xfm0.l.vz.w * xfm1.l.vz.w
- + xfm0.p.w * xfm1.p.w));
-
- theta = std::acos(cosTheta);
- Vec4f qperp(xfm1.p.w, xfm1.l.vx.w, xfm1.l.vy.w, xfm1.l.vz.w);
- if (cosTheta < 0.995f) {
- // compute perpendicular quaternion
- qperp.x = xfm1.p.w - cosTheta * xfm0.p.w;
- qperp.y = xfm1.l.vx.w - cosTheta * xfm0.l.vx.w;
- qperp.z = xfm1.l.vy.w - cosTheta * xfm0.l.vy.w;
- qperp.w = xfm1.l.vz.w - cosTheta * xfm0.l.vz.w;
- qperp = normalize(qperp);
- }
- const float p[33] = {
- theta,
- xfm0.l.vx.y, xfm0.l.vx.z, xfm0.l.vy.z, // translation component of xfm0
- xfm1.l.vx.y, xfm1.l.vx.z, xfm1.l.vy.z, // translation component of xfm1
- xfm0.p.w, xfm0.l.vx.w, xfm0.l.vy.w, xfm0.l.vz.w, // quaternion of xfm0
- qperp.x, qperp.y, qperp.z, qperp.w,
- xfm0.l.vx.x, xfm0.l.vy.x, xfm0.l.vz.x, xfm0.p.x, // scale/skew component of xfm0
- xfm0.l.vy.y, xfm0.l.vz.y, xfm0.p.y,
- xfm0.l.vz.z, xfm0.p.z,
- xfm1.l.vx.x, xfm1.l.vy.x, xfm1.l.vz.x, xfm1.p.x, // scale/skew component of xfm1
- xfm1.l.vy.y, xfm1.l.vz.y, xfm1.p.y,
- xfm1.l.vz.z, xfm1.p.z
- };
- motion_derivative_coefficients(p, coeffs);
- }
-};
-
-struct MotionDerivative
-{
- float twoTheta;
- float c[8];
-
- MotionDerivative(MotionDerivativeCoefficients const& mdc,
- int dim, Vec3fa const& p0, Vec3fa const& p1)
- : twoTheta(2.f*mdc.theta)
- {
- const float p[7] = { 1, p0.x, p0.y, p0.z, p1.x, p1.y, p1.z };
- for (int i = 0; i < 8; ++i) {
- c[i] = 0;
- for (int j = 0; j < 7; ++j) {
- c[i] += mdc.coeffs[8*7*dim + i*7 + j] * p[j];
- }
- }
- }
-
- template<typename T>
- struct EvalMotionDerivative
- {
- MotionDerivative const& md;
- float offset;
-
- EvalMotionDerivative(MotionDerivative const& md, float offset) : md(md), offset(offset) {}
-
- T operator()(T const& time) const {
- return md.c[0] + md.c[1] * time
- + (md.c[2] + md.c[3] * time + md.c[4] * time * time) * cos(md.twoTheta * time)
- + (md.c[5] + md.c[6] * time + md.c[7] * time * time) * sin(md.twoTheta * time)
- + offset;
- }
- };
-
- unsigned int findRoots(
- Interval1f const& interval,
- float offset,
- float* roots,
- unsigned int maxNumRoots)
- {
- unsigned int numRoots = 0;
- EvalMotionDerivative<Interval1f> eval(*this, offset);
- findRoots(eval, interval, numRoots, roots, maxNumRoots);
- return numRoots;
- }
-
- template<typename Eval>
- static void findRoots(
-
- Eval const& eval,
- Interval1f const& interval,
- unsigned int& numRoots,
- float* roots,
- unsigned int maxNumRoots)
- {
- Interval1f range = eval(interval);
- if (range.lower > 0 || range.upper < 0 || range.lower >= range.upper) return;
-
- const float split = 0.5f * (interval.upper + interval.lower);
- if (interval.upper-interval.lower < 1e-7f || abs(split-interval.lower) < 1e-7f || abs(split-interval.upper) < 1e-7f)
- {
- // check if the root already exists
- for (unsigned int k = 0; k < numRoots && k < maxNumRoots; ++k) {
- if (abs(roots[k]-split) < MOTION_DERIVATIVE_ROOT_EPSILON)
- return;
- }
- if (numRoots < maxNumRoots) {
- roots[numRoots++] = split;
- }
- if (numRoots > maxNumRoots) {
- printf("error: more roots than expected\n"); // FIXME: workaround for ICC2019.4 compiler bug under macOS
- return;
- }
- return;
- }
-
- findRoots(eval, Interval1f(interval.lower, split), numRoots, roots, maxNumRoots);
- findRoots(eval, Interval1f(split, interval.upper), numRoots, roots, maxNumRoots);
- }
-};
-
-/******************************************************************************
- * Code generated with sympy 1.4 *
- * See http://www.sympy.org/ for more information. *
- * *
- * see *
- * *
- * scripts/generate_motion_derivative_coefficients.py *
- * *
- * for how this code is generated *
- * *
- ******************************************************************************/
-static void motion_derivative_coefficients(const float *p, float *coeff)
-{
- coeff[0] = -p[1] + p[4] - p[7]*p[9]*p[23] + p[7]*p[9]*p[32] + p[7]*p[10]*p[21] - p[7]*p[10]*p[30] - p[8]*p[9]*p[21] + p[8]*p[9]*p[30] - p[8]*p[10]*p[23] + p[8]*p[10]*p[32] + p[9]*p[9]*p[18] - p[9]*p[9]*p[27] + p[10]*p[10]*p[18] - p[10]*p[10]*p[27] - p[11]*p[13]*p[23] + p[11]*p[13]*p[32] + p[11]*p[14]*p[21] - p[11]*p[14]*p[30] - p[12]*p[13]*p[21] + p[12]*p[13]*p[30] - p[12]*p[14]*p[23] + p[12]*p[14]*p[32] + p[13]*p[13]*p[18] - p[13]*p[13]*p[27] + p[14]*p[14]*p[18] - p[14]*p[14]*p[27] - p[18] + p[27];
- coeff[1] = 2*p[9]*p[9]*p[15] - p[9]*p[9]*p[24] + 2*p[10]*p[10]*p[15] - p[10]*p[10]*p[24] + 2*p[13]*p[13]*p[15] - p[13]*p[13]*p[24] + 2*p[14]*p[14]*p[15] - p[14]*p[14]*p[24] - 2*p[15] + p[24];
- coeff[2] = 2*p[7]*p[10]*p[19] - p[7]*p[10]*p[28] - 2*p[8]*p[9]*p[19] + p[8]*p[9]*p[28] + 2*p[9]*p[9]*p[16] - p[9]*p[9]*p[25] + 2*p[10]*p[10]*p[16] - p[10]*p[10]*p[25] + 2*p[11]*p[14]*p[19] - p[11]*p[14]*p[28] - 2*p[12]*p[13]*p[19] + p[12]*p[13]*p[28] + 2*p[13]*p[13]*p[16] - p[13]*p[13]*p[25] + 2*p[14]*p[14]*p[16] - p[14]*p[14]*p[25] - 2*p[16] + p[25];
- coeff[3] = -2*p[7]*p[9]*p[22] + p[7]*p[9]*p[31] + 2*p[7]*p[10]*p[20] - p[7]*p[10]*p[29] - 2*p[8]*p[9]*p[20] + p[8]*p[9]*p[29] - 2*p[8]*p[10]*p[22] + p[8]*p[10]*p[31] + 2*p[9]*p[9]*p[17] - p[9]*p[9]*p[26] + 2*p[10]*p[10]*p[17] - p[10]*p[10]*p[26] - 2*p[11]*p[13]*p[22] + p[11]*p[13]*p[31] + 2*p[11]*p[14]*p[20] - p[11]*p[14]*p[29] - 2*p[12]*p[13]*p[20] + p[12]*p[13]*p[29] - 2*p[12]*p[14]*p[22] + p[12]*p[14]*p[31] + 2*p[13]*p[13]*p[17] - p[13]*p[13]*p[26] + 2*p[14]*p[14]*p[17] - p[14]*p[14]*p[26] - 2*p[17] + p[26];
- coeff[4] = (-p[9]*p[9] - p[10]*p[10] - p[13]*p[13] - p[14]*p[14] + 1)*p[15];
- coeff[5] = -p[7]*p[10]*p[19] + p[8]*p[9]*p[19] - p[9]*p[9]*p[16] - p[10]*p[10]*p[16] - p[11]*p[14]*p[19] + p[12]*p[13]*p[19] - p[13]*p[13]*p[16] - p[14]*p[14]*p[16] + p[16];
- coeff[6] = p[7]*p[9]*p[22] - p[7]*p[10]*p[20] + p[8]*p[9]*p[20] + p[8]*p[10]*p[22] - p[9]*p[9]*p[17] - p[10]*p[10]*p[17] + p[11]*p[13]*p[22] - p[11]*p[14]*p[20] + p[12]*p[13]*p[20] + p[12]*p[14]*p[22] - p[13]*p[13]*p[17] - p[14]*p[14]*p[17] + p[17];
- coeff[7] = 0;
- coeff[8] = -2*p[9]*p[9]*p[15] + 2*p[9]*p[9]*p[24] - 2*p[10]*p[10]*p[15] + 2*p[10]*p[10]*p[24] - 2*p[13]*p[13]*p[15] + 2*p[13]*p[13]*p[24] - 2*p[14]*p[14]*p[15] + 2*p[14]*p[14]*p[24] + 2*p[15] - 2*p[24];
- coeff[9] = -2*p[7]*p[10]*p[19] + 2*p[7]*p[10]*p[28] + 2*p[8]*p[9]*p[19] - 2*p[8]*p[9]*p[28] - 2*p[9]*p[9]*p[16] + 2*p[9]*p[9]*p[25] - 2*p[10]*p[10]*p[16] + 2*p[10]*p[10]*p[25] - 2*p[11]*p[14]*p[19] + 2*p[11]*p[14]*p[28] + 2*p[12]*p[13]*p[19] - 2*p[12]*p[13]*p[28] - 2*p[13]*p[13]*p[16] + 2*p[13]*p[13]*p[25] - 2*p[14]*p[14]*p[16] + 2*p[14]*p[14]*p[25] + 2*p[16] - 2*p[25];
- coeff[10] = 2*p[7]*p[9]*p[22] - 2*p[7]*p[9]*p[31] - 2*p[7]*p[10]*p[20] + 2*p[7]*p[10]*p[29] + 2*p[8]*p[9]*p[20] - 2*p[8]*p[9]*p[29] + 2*p[8]*p[10]*p[22] - 2*p[8]*p[10]*p[31] - 2*p[9]*p[9]*p[17] + 2*p[9]*p[9]*p[26] - 2*p[10]*p[10]*p[17] + 2*p[10]*p[10]*p[26] + 2*p[11]*p[13]*p[22] - 2*p[11]*p[13]*p[31] - 2*p[11]*p[14]*p[20] + 2*p[11]*p[14]*p[29] + 2*p[12]*p[13]*p[20] - 2*p[12]*p[13]*p[29] + 2*p[12]*p[14]*p[22] - 2*p[12]*p[14]*p[31] - 2*p[13]*p[13]*p[17] + 2*p[13]*p[13]*p[26] - 2*p[14]*p[14]*p[17] + 2*p[14]*p[14]*p[26] + 2*p[17] - 2*p[26];
- coeff[11] = 2*p[9]*p[9]*p[15] - 2*p[9]*p[9]*p[24] + 2*p[10]*p[10]*p[15] - 2*p[10]*p[10]*p[24] + 2*p[13]*p[13]*p[15] - 2*p[13]*p[13]*p[24] + 2*p[14]*p[14]*p[15] - 2*p[14]*p[14]*p[24] - 2*p[15] + 2*p[24];
- coeff[12] = 2*p[7]*p[10]*p[19] - 2*p[7]*p[10]*p[28] - 2*p[8]*p[9]*p[19] + 2*p[8]*p[9]*p[28] + 2*p[9]*p[9]*p[16] - 2*p[9]*p[9]*p[25] + 2*p[10]*p[10]*p[16] - 2*p[10]*p[10]*p[25] + 2*p[11]*p[14]*p[19] - 2*p[11]*p[14]*p[28] - 2*p[12]*p[13]*p[19] + 2*p[12]*p[13]*p[28] + 2*p[13]*p[13]*p[16] - 2*p[13]*p[13]*p[25] + 2*p[14]*p[14]*p[16] - 2*p[14]*p[14]*p[25] - 2*p[16] + 2*p[25];
- coeff[13] = -2*p[7]*p[9]*p[22] + 2*p[7]*p[9]*p[31] + 2*p[7]*p[10]*p[20] - 2*p[7]*p[10]*p[29] - 2*p[8]*p[9]*p[20] + 2*p[8]*p[9]*p[29] - 2*p[8]*p[10]*p[22] + 2*p[8]*p[10]*p[31] + 2*p[9]*p[9]*p[17] - 2*p[9]*p[9]*p[26] + 2*p[10]*p[10]*p[17] - 2*p[10]*p[10]*p[26] - 2*p[11]*p[13]*p[22] + 2*p[11]*p[13]*p[31] + 2*p[11]*p[14]*p[20] - 2*p[11]*p[14]*p[29] - 2*p[12]*p[13]*p[20] + 2*p[12]*p[13]*p[29] - 2*p[12]*p[14]*p[22] + 2*p[12]*p[14]*p[31] + 2*p[13]*p[13]*p[17] - 2*p[13]*p[13]*p[26] + 2*p[14]*p[14]*p[17] - 2*p[14]*p[14]*p[26] - 2*p[17] + 2*p[26];
- coeff[14] = 2*p[0]*p[7]*p[11]*p[18] + 2*p[0]*p[7]*p[13]*p[23] - 2*p[0]*p[7]*p[14]*p[21] + 2*p[0]*p[8]*p[12]*p[18] + 2*p[0]*p[8]*p[13]*p[21] + 2*p[0]*p[8]*p[14]*p[23] + 2*p[0]*p[9]*p[11]*p[23] + 2*p[0]*p[9]*p[12]*p[21] - 2*p[0]*p[9]*p[13]*p[18] - 2*p[0]*p[10]*p[11]*p[21] + 2*p[0]*p[10]*p[12]*p[23] - 2*p[0]*p[10]*p[14]*p[18] - p[7]*p[9]*p[23] + p[7]*p[9]*p[32] + p[7]*p[10]*p[21] - p[7]*p[10]*p[30] - p[8]*p[9]*p[21] + p[8]*p[9]*p[30] - p[8]*p[10]*p[23] + p[8]*p[10]*p[32] + p[9]*p[9]*p[18] - p[9]*p[9]*p[27] + p[10]*p[10]*p[18] - p[10]*p[10]*p[27] + p[11]*p[13]*p[23] - p[11]*p[13]*p[32] - p[11]*p[14]*p[21] + p[11]*p[14]*p[30] + p[12]*p[13]*p[21] - p[12]*p[13]*p[30] + p[12]*p[14]*p[23] - p[12]*p[14]*p[32] - p[13]*p[13]*p[18] + p[13]*p[13]*p[27] - p[14]*p[14]*p[18] + p[14]*p[14]*p[27];
- coeff[15] = 2*p[0]*p[7]*p[11]*p[15] + 2*p[0]*p[8]*p[12]*p[15] - 2*p[0]*p[9]*p[13]*p[15] - 2*p[0]*p[10]*p[14]*p[15] + 2*p[9]*p[9]*p[15] - p[9]*p[9]*p[24] + 2*p[10]*p[10]*p[15] - p[10]*p[10]*p[24] - 2*p[13]*p[13]*p[15] + p[13]*p[13]*p[24] - 2*p[14]*p[14]*p[15] + p[14]*p[14]*p[24];
- coeff[16] = 2*p[0]*p[7]*p[11]*p[16] - 2*p[0]*p[7]*p[14]*p[19] + 2*p[0]*p[8]*p[12]*p[16] + 2*p[0]*p[8]*p[13]*p[19] + 2*p[0]*p[9]*p[12]*p[19] - 2*p[0]*p[9]*p[13]*p[16] - 2*p[0]*p[10]*p[11]*p[19] - 2*p[0]*p[10]*p[14]*p[16] + 2*p[7]*p[10]*p[19] - p[7]*p[10]*p[28] - 2*p[8]*p[9]*p[19] + p[8]*p[9]*p[28] + 2*p[9]*p[9]*p[16] - p[9]*p[9]*p[25] + 2*p[10]*p[10]*p[16] - p[10]*p[10]*p[25] - 2*p[11]*p[14]*p[19] + p[11]*p[14]*p[28] + 2*p[12]*p[13]*p[19] - p[12]*p[13]*p[28] - 2*p[13]*p[13]*p[16] + p[13]*p[13]*p[25] - 2*p[14]*p[14]*p[16] + p[14]*p[14]*p[25];
- coeff[17] = 2*p[0]*p[7]*p[11]*p[17] + 2*p[0]*p[7]*p[13]*p[22] - 2*p[0]*p[7]*p[14]*p[20] + 2*p[0]*p[8]*p[12]*p[17] + 2*p[0]*p[8]*p[13]*p[20] + 2*p[0]*p[8]*p[14]*p[22] + 2*p[0]*p[9]*p[11]*p[22] + 2*p[0]*p[9]*p[12]*p[20] - 2*p[0]*p[9]*p[13]*p[17] - 2*p[0]*p[10]*p[11]*p[20] + 2*p[0]*p[10]*p[12]*p[22] - 2*p[0]*p[10]*p[14]*p[17] - 2*p[7]*p[9]*p[22] + p[7]*p[9]*p[31] + 2*p[7]*p[10]*p[20] - p[7]*p[10]*p[29] - 2*p[8]*p[9]*p[20] + p[8]*p[9]*p[29] - 2*p[8]*p[10]*p[22] + p[8]*p[10]*p[31] + 2*p[9]*p[9]*p[17] - p[9]*p[9]*p[26] + 2*p[10]*p[10]*p[17] - p[10]*p[10]*p[26] + 2*p[11]*p[13]*p[22] - p[11]*p[13]*p[31] - 2*p[11]*p[14]*p[20] + p[11]*p[14]*p[29] + 2*p[12]*p[13]*p[20] - p[12]*p[13]*p[29] + 2*p[12]*p[14]*p[22] - p[12]*p[14]*p[31] - 2*p[13]*p[13]*p[17] + p[13]*p[13]*p[26] - 2*p[14]*p[14]*p[17] + p[14]*p[14]*p[26];
- coeff[18] = (-p[9]*p[9] - p[10]*p[10] + p[13]*p[13] + p[14]*p[14])*p[15];
- coeff[19] = -p[7]*p[10]*p[19] + p[8]*p[9]*p[19] - p[9]*p[9]*p[16] - p[10]*p[10]*p[16] + p[11]*p[14]*p[19] - p[12]*p[13]*p[19] + p[13]*p[13]*p[16] + p[14]*p[14]*p[16];
- coeff[20] = p[7]*p[9]*p[22] - p[7]*p[10]*p[20] + p[8]*p[9]*p[20] + p[8]*p[10]*p[22] - p[9]*p[9]*p[17] - p[10]*p[10]*p[17] - p[11]*p[13]*p[22] + p[11]*p[14]*p[20] - p[12]*p[13]*p[20] - p[12]*p[14]*p[22] + p[13]*p[13]*p[17] + p[14]*p[14]*p[17];
- coeff[21] = 2*(-p[7]*p[11]*p[18] + p[7]*p[11]*p[27] - p[7]*p[13]*p[23] + p[7]*p[13]*p[32] + p[7]*p[14]*p[21] - p[7]*p[14]*p[30] - p[8]*p[12]*p[18] + p[8]*p[12]*p[27] - p[8]*p[13]*p[21] + p[8]*p[13]*p[30] - p[8]*p[14]*p[23] + p[8]*p[14]*p[32] - p[9]*p[11]*p[23] + p[9]*p[11]*p[32] - p[9]*p[12]*p[21] + p[9]*p[12]*p[30] + p[9]*p[13]*p[18] - p[9]*p[13]*p[27] + p[10]*p[11]*p[21] - p[10]*p[11]*p[30] - p[10]*p[12]*p[23] + p[10]*p[12]*p[32] + p[10]*p[14]*p[18] - p[10]*p[14]*p[27])*p[0];
- coeff[22] = -4*p[0]*p[7]*p[11]*p[15] + 2*p[0]*p[7]*p[11]*p[24] - 4*p[0]*p[8]*p[12]*p[15] + 2*p[0]*p[8]*p[12]*p[24] + 4*p[0]*p[9]*p[13]*p[15] - 2*p[0]*p[9]*p[13]*p[24] + 4*p[0]*p[10]*p[14]*p[15] - 2*p[0]*p[10]*p[14]*p[24] - 2*p[9]*p[9]*p[15] + 2*p[9]*p[9]*p[24] - 2*p[10]*p[10]*p[15] + 2*p[10]*p[10]*p[24] + 2*p[13]*p[13]*p[15] - 2*p[13]*p[13]*p[24] + 2*p[14]*p[14]*p[15] - 2*p[14]*p[14]*p[24];
- coeff[23] = -4*p[0]*p[7]*p[11]*p[16] + 2*p[0]*p[7]*p[11]*p[25] + 4*p[0]*p[7]*p[14]*p[19] - 2*p[0]*p[7]*p[14]*p[28] - 4*p[0]*p[8]*p[12]*p[16] + 2*p[0]*p[8]*p[12]*p[25] - 4*p[0]*p[8]*p[13]*p[19] + 2*p[0]*p[8]*p[13]*p[28] - 4*p[0]*p[9]*p[12]*p[19] + 2*p[0]*p[9]*p[12]*p[28] + 4*p[0]*p[9]*p[13]*p[16] - 2*p[0]*p[9]*p[13]*p[25] + 4*p[0]*p[10]*p[11]*p[19] - 2*p[0]*p[10]*p[11]*p[28] + 4*p[0]*p[10]*p[14]*p[16] - 2*p[0]*p[10]*p[14]*p[25] - 2*p[7]*p[10]*p[19] + 2*p[7]*p[10]*p[28] + 2*p[8]*p[9]*p[19] - 2*p[8]*p[9]*p[28] - 2*p[9]*p[9]*p[16] + 2*p[9]*p[9]*p[25] - 2*p[10]*p[10]*p[16] + 2*p[10]*p[10]*p[25] + 2*p[11]*p[14]*p[19] - 2*p[11]*p[14]*p[28] - 2*p[12]*p[13]*p[19] + 2*p[12]*p[13]*p[28] + 2*p[13]*p[13]*p[16] - 2*p[13]*p[13]*p[25] + 2*p[14]*p[14]*p[16] - 2*p[14]*p[14]*p[25];
- coeff[24] = -4*p[0]*p[7]*p[11]*p[17] + 2*p[0]*p[7]*p[11]*p[26] - 4*p[0]*p[7]*p[13]*p[22] + 2*p[0]*p[7]*p[13]*p[31] + 4*p[0]*p[7]*p[14]*p[20] - 2*p[0]*p[7]*p[14]*p[29] - 4*p[0]*p[8]*p[12]*p[17] + 2*p[0]*p[8]*p[12]*p[26] - 4*p[0]*p[8]*p[13]*p[20] + 2*p[0]*p[8]*p[13]*p[29] - 4*p[0]*p[8]*p[14]*p[22] + 2*p[0]*p[8]*p[14]*p[31] - 4*p[0]*p[9]*p[11]*p[22] + 2*p[0]*p[9]*p[11]*p[31] - 4*p[0]*p[9]*p[12]*p[20] + 2*p[0]*p[9]*p[12]*p[29] + 4*p[0]*p[9]*p[13]*p[17] - 2*p[0]*p[9]*p[13]*p[26] + 4*p[0]*p[10]*p[11]*p[20] - 2*p[0]*p[10]*p[11]*p[29] - 4*p[0]*p[10]*p[12]*p[22] + 2*p[0]*p[10]*p[12]*p[31] + 4*p[0]*p[10]*p[14]*p[17] - 2*p[0]*p[10]*p[14]*p[26] + 2*p[7]*p[9]*p[22] - 2*p[7]*p[9]*p[31] - 2*p[7]*p[10]*p[20] + 2*p[7]*p[10]*p[29] + 2*p[8]*p[9]*p[20] - 2*p[8]*p[9]*p[29] + 2*p[8]*p[10]*p[22] - 2*p[8]*p[10]*p[31] - 2*p[9]*p[9]*p[17] + 2*p[9]*p[9]*p[26] - 2*p[10]*p[10]*p[17] + 2*p[10]*p[10]*p[26] - 2*p[11]*p[13]*p[22] + 2*p[11]*p[13]*p[31] + 2*p[11]*p[14]*p[20] - 2*p[11]*p[14]*p[29] - 2*p[12]*p[13]*p[20] + 2*p[12]*p[13]*p[29] - 2*p[12]*p[14]*p[22] + 2*p[12]*p[14]*p[31] + 2*p[13]*p[13]*p[17] - 2*p[13]*p[13]*p[26] + 2*p[14]*p[14]*p[17] - 2*p[14]*p[14]*p[26];
- coeff[25] = 2*p[0]*p[7]*p[11]*p[15] + 2*p[0]*p[8]*p[12]*p[15] - 2*p[0]*p[9]*p[13]*p[15] - 2*p[0]*p[10]*p[14]*p[15] + 2*p[9]*p[9]*p[15] - 2*p[9]*p[9]*p[24] + 2*p[10]*p[10]*p[15] - 2*p[10]*p[10]*p[24] - 2*p[13]*p[13]*p[15] + 2*p[13]*p[13]*p[24] - 2*p[14]*p[14]*p[15] + 2*p[14]*p[14]*p[24];
- coeff[26] = 2*p[0]*p[7]*p[11]*p[16] - 2*p[0]*p[7]*p[14]*p[19] + 2*p[0]*p[8]*p[12]*p[16] + 2*p[0]*p[8]*p[13]*p[19] + 2*p[0]*p[9]*p[12]*p[19] - 2*p[0]*p[9]*p[13]*p[16] - 2*p[0]*p[10]*p[11]*p[19] - 2*p[0]*p[10]*p[14]*p[16] + 2*p[7]*p[10]*p[19] - 2*p[7]*p[10]*p[28] - 2*p[8]*p[9]*p[19] + 2*p[8]*p[9]*p[28] + 2*p[9]*p[9]*p[16] - 2*p[9]*p[9]*p[25] + 2*p[10]*p[10]*p[16] - 2*p[10]*p[10]*p[25] - 2*p[11]*p[14]*p[19] + 2*p[11]*p[14]*p[28] + 2*p[12]*p[13]*p[19] - 2*p[12]*p[13]*p[28] - 2*p[13]*p[13]*p[16] + 2*p[13]*p[13]*p[25] - 2*p[14]*p[14]*p[16] + 2*p[14]*p[14]*p[25];
- coeff[27] = 2*p[0]*p[7]*p[11]*p[17] + 2*p[0]*p[7]*p[13]*p[22] - 2*p[0]*p[7]*p[14]*p[20] + 2*p[0]*p[8]*p[12]*p[17] + 2*p[0]*p[8]*p[13]*p[20] + 2*p[0]*p[8]*p[14]*p[22] + 2*p[0]*p[9]*p[11]*p[22] + 2*p[0]*p[9]*p[12]*p[20] - 2*p[0]*p[9]*p[13]*p[17] - 2*p[0]*p[10]*p[11]*p[20] + 2*p[0]*p[10]*p[12]*p[22] - 2*p[0]*p[10]*p[14]*p[17] - 2*p[7]*p[9]*p[22] + 2*p[7]*p[9]*p[31] + 2*p[7]*p[10]*p[20] - 2*p[7]*p[10]*p[29] - 2*p[8]*p[9]*p[20] + 2*p[8]*p[9]*p[29] - 2*p[8]*p[10]*p[22] + 2*p[8]*p[10]*p[31] + 2*p[9]*p[9]*p[17] - 2*p[9]*p[9]*p[26] + 2*p[10]*p[10]*p[17] - 2*p[10]*p[10]*p[26] + 2*p[11]*p[13]*p[22] - 2*p[11]*p[13]*p[31] - 2*p[11]*p[14]*p[20] + 2*p[11]*p[14]*p[29] + 2*p[12]*p[13]*p[20] - 2*p[12]*p[13]*p[29] + 2*p[12]*p[14]*p[22] - 2*p[12]*p[14]*p[31] - 2*p[13]*p[13]*p[17] + 2*p[13]*p[13]*p[26] - 2*p[14]*p[14]*p[17] + 2*p[14]*p[14]*p[26];
- coeff[28] = 0;
- coeff[29] = 2*(p[7]*p[11]*p[15] - p[7]*p[11]*p[24] + p[8]*p[12]*p[15] - p[8]*p[12]*p[24] - p[9]*p[13]*p[15] + p[9]*p[13]*p[24] - p[10]*p[14]*p[15] + p[10]*p[14]*p[24])*p[0];
- coeff[30] = 2*(p[7]*p[11]*p[16] - p[7]*p[11]*p[25] - p[7]*p[14]*p[19] + p[7]*p[14]*p[28] + p[8]*p[12]*p[16] - p[8]*p[12]*p[25] + p[8]*p[13]*p[19] - p[8]*p[13]*p[28] + p[9]*p[12]*p[19] - p[9]*p[12]*p[28] - p[9]*p[13]*p[16] + p[9]*p[13]*p[25] - p[10]*p[11]*p[19] + p[10]*p[11]*p[28] - p[10]*p[14]*p[16] + p[10]*p[14]*p[25])*p[0];
- coeff[31] = 2*(p[7]*p[11]*p[17] - p[7]*p[11]*p[26] + p[7]*p[13]*p[22] - p[7]*p[13]*p[31] - p[7]*p[14]*p[20] + p[7]*p[14]*p[29] + p[8]*p[12]*p[17] - p[8]*p[12]*p[26] + p[8]*p[13]*p[20] - p[8]*p[13]*p[29] + p[8]*p[14]*p[22] - p[8]*p[14]*p[31] + p[9]*p[11]*p[22] - p[9]*p[11]*p[31] + p[9]*p[12]*p[20] - p[9]*p[12]*p[29] - p[9]*p[13]*p[17] + p[9]*p[13]*p[26] - p[10]*p[11]*p[20] + p[10]*p[11]*p[29] + p[10]*p[12]*p[22] - p[10]*p[12]*p[31] - p[10]*p[14]*p[17] + p[10]*p[14]*p[26])*p[0];
- coeff[32] = 2*(-p[7]*p[11]*p[15] + p[7]*p[11]*p[24] - p[8]*p[12]*p[15] + p[8]*p[12]*p[24] + p[9]*p[13]*p[15] - p[9]*p[13]*p[24] + p[10]*p[14]*p[15] - p[10]*p[14]*p[24])*p[0];
- coeff[33] = 2*(-p[7]*p[11]*p[16] + p[7]*p[11]*p[25] + p[7]*p[14]*p[19] - p[7]*p[14]*p[28] - p[8]*p[12]*p[16] + p[8]*p[12]*p[25] - p[8]*p[13]*p[19] + p[8]*p[13]*p[28] - p[9]*p[12]*p[19] + p[9]*p[12]*p[28] + p[9]*p[13]*p[16] - p[9]*p[13]*p[25] + p[10]*p[11]*p[19] - p[10]*p[11]*p[28] + p[10]*p[14]*p[16] - p[10]*p[14]*p[25])*p[0];
- coeff[34] = 2*(-p[7]*p[11]*p[17] + p[7]*p[11]*p[26] - p[7]*p[13]*p[22] + p[7]*p[13]*p[31] + p[7]*p[14]*p[20] - p[7]*p[14]*p[29] - p[8]*p[12]*p[17] + p[8]*p[12]*p[26] - p[8]*p[13]*p[20] + p[8]*p[13]*p[29] - p[8]*p[14]*p[22] + p[8]*p[14]*p[31] - p[9]*p[11]*p[22] + p[9]*p[11]*p[31] - p[9]*p[12]*p[20] + p[9]*p[12]*p[29] + p[9]*p[13]*p[17] - p[9]*p[13]*p[26] + p[10]*p[11]*p[20] - p[10]*p[11]*p[29] - p[10]*p[12]*p[22] + p[10]*p[12]*p[31] + p[10]*p[14]*p[17] - p[10]*p[14]*p[26])*p[0];
- coeff[35] = -2*p[0]*p[7]*p[9]*p[23] + 2*p[0]*p[7]*p[10]*p[21] - 2*p[0]*p[8]*p[9]*p[21] - 2*p[0]*p[8]*p[10]*p[23] + 2*p[0]*p[9]*p[9]*p[18] + 2*p[0]*p[10]*p[10]*p[18] + 2*p[0]*p[11]*p[13]*p[23] - 2*p[0]*p[11]*p[14]*p[21] + 2*p[0]*p[12]*p[13]*p[21] + 2*p[0]*p[12]*p[14]*p[23] - 2*p[0]*p[13]*p[13]*p[18] - 2*p[0]*p[14]*p[14]*p[18] - p[7]*p[11]*p[18] + p[7]*p[11]*p[27] - p[7]*p[13]*p[23] + p[7]*p[13]*p[32] + p[7]*p[14]*p[21] - p[7]*p[14]*p[30] - p[8]*p[12]*p[18] + p[8]*p[12]*p[27] - p[8]*p[13]*p[21] + p[8]*p[13]*p[30] - p[8]*p[14]*p[23] + p[8]*p[14]*p[32] - p[9]*p[11]*p[23] + p[9]*p[11]*p[32] - p[9]*p[12]*p[21] + p[9]*p[12]*p[30] + p[9]*p[13]*p[18] - p[9]*p[13]*p[27] + p[10]*p[11]*p[21] - p[10]*p[11]*p[30] - p[10]*p[12]*p[23] + p[10]*p[12]*p[32] + p[10]*p[14]*p[18] - p[10]*p[14]*p[27];
- coeff[36] = 2*p[0]*p[9]*p[9]*p[15] + 2*p[0]*p[10]*p[10]*p[15] - 2*p[0]*p[13]*p[13]*p[15] - 2*p[0]*p[14]*p[14]*p[15] - 2*p[7]*p[11]*p[15] + p[7]*p[11]*p[24] - 2*p[8]*p[12]*p[15] + p[8]*p[12]*p[24] + 2*p[9]*p[13]*p[15] - p[9]*p[13]*p[24] + 2*p[10]*p[14]*p[15] - p[10]*p[14]*p[24];
- coeff[37] = 2*p[0]*p[7]*p[10]*p[19] - 2*p[0]*p[8]*p[9]*p[19] + 2*p[0]*p[9]*p[9]*p[16] + 2*p[0]*p[10]*p[10]*p[16] - 2*p[0]*p[11]*p[14]*p[19] + 2*p[0]*p[12]*p[13]*p[19] - 2*p[0]*p[13]*p[13]*p[16] - 2*p[0]*p[14]*p[14]*p[16] - 2*p[7]*p[11]*p[16] + p[7]*p[11]*p[25] + 2*p[7]*p[14]*p[19] - p[7]*p[14]*p[28] - 2*p[8]*p[12]*p[16] + p[8]*p[12]*p[25] - 2*p[8]*p[13]*p[19] + p[8]*p[13]*p[28] - 2*p[9]*p[12]*p[19] + p[9]*p[12]*p[28] + 2*p[9]*p[13]*p[16] - p[9]*p[13]*p[25] + 2*p[10]*p[11]*p[19] - p[10]*p[11]*p[28] + 2*p[10]*p[14]*p[16] - p[10]*p[14]*p[25];
- coeff[38] = -2*p[0]*p[7]*p[9]*p[22] + 2*p[0]*p[7]*p[10]*p[20] - 2*p[0]*p[8]*p[9]*p[20] - 2*p[0]*p[8]*p[10]*p[22] + 2*p[0]*p[9]*p[9]*p[17] + 2*p[0]*p[10]*p[10]*p[17] + 2*p[0]*p[11]*p[13]*p[22] - 2*p[0]*p[11]*p[14]*p[20] + 2*p[0]*p[12]*p[13]*p[20] + 2*p[0]*p[12]*p[14]*p[22] - 2*p[0]*p[13]*p[13]*p[17] - 2*p[0]*p[14]*p[14]*p[17] - 2*p[7]*p[11]*p[17] + p[7]*p[11]*p[26] - 2*p[7]*p[13]*p[22] + p[7]*p[13]*p[31] + 2*p[7]*p[14]*p[20] - p[7]*p[14]*p[29] - 2*p[8]*p[12]*p[17] + p[8]*p[12]*p[26] - 2*p[8]*p[13]*p[20] + p[8]*p[13]*p[29] - 2*p[8]*p[14]*p[22] + p[8]*p[14]*p[31] - 2*p[9]*p[11]*p[22] + p[9]*p[11]*p[31] - 2*p[9]*p[12]*p[20] + p[9]*p[12]*p[29] + 2*p[9]*p[13]*p[17] - p[9]*p[13]*p[26] + 2*p[10]*p[11]*p[20] - p[10]*p[11]*p[29] - 2*p[10]*p[12]*p[22] + p[10]*p[12]*p[31] + 2*p[10]*p[14]*p[17] - p[10]*p[14]*p[26];
- coeff[39] = (p[7]*p[11] + p[8]*p[12] - p[9]*p[13] - p[10]*p[14])*p[15];
- coeff[40] = p[7]*p[11]*p[16] - p[7]*p[14]*p[19] + p[8]*p[12]*p[16] + p[8]*p[13]*p[19] + p[9]*p[12]*p[19] - p[9]*p[13]*p[16] - p[10]*p[11]*p[19] - p[10]*p[14]*p[16];
- coeff[41] = p[7]*p[11]*p[17] + p[7]*p[13]*p[22] - p[7]*p[14]*p[20] + p[8]*p[12]*p[17] + p[8]*p[13]*p[20] + p[8]*p[14]*p[22] + p[9]*p[11]*p[22] + p[9]*p[12]*p[20] - p[9]*p[13]*p[17] - p[10]*p[11]*p[20] + p[10]*p[12]*p[22] - p[10]*p[14]*p[17];
- coeff[42] = 2*(p[7]*p[9]*p[23] - p[7]*p[9]*p[32] - p[7]*p[10]*p[21] + p[7]*p[10]*p[30] + p[8]*p[9]*p[21] - p[8]*p[9]*p[30] + p[8]*p[10]*p[23] - p[8]*p[10]*p[32] - p[9]*p[9]*p[18] + p[9]*p[9]*p[27] - p[10]*p[10]*p[18] + p[10]*p[10]*p[27] - p[11]*p[13]*p[23] + p[11]*p[13]*p[32] + p[11]*p[14]*p[21] - p[11]*p[14]*p[30] - p[12]*p[13]*p[21] + p[12]*p[13]*p[30] - p[12]*p[14]*p[23] + p[12]*p[14]*p[32] + p[13]*p[13]*p[18] - p[13]*p[13]*p[27] + p[14]*p[14]*p[18] - p[14]*p[14]*p[27])*p[0];
- coeff[43] = -4*p[0]*p[9]*p[9]*p[15] + 2*p[0]*p[9]*p[9]*p[24] - 4*p[0]*p[10]*p[10]*p[15] + 2*p[0]*p[10]*p[10]*p[24] + 4*p[0]*p[13]*p[13]*p[15] - 2*p[0]*p[13]*p[13]*p[24] + 4*p[0]*p[14]*p[14]*p[15] - 2*p[0]*p[14]*p[14]*p[24] + 2*p[7]*p[11]*p[15] - 2*p[7]*p[11]*p[24] + 2*p[8]*p[12]*p[15] - 2*p[8]*p[12]*p[24] - 2*p[9]*p[13]*p[15] + 2*p[9]*p[13]*p[24] - 2*p[10]*p[14]*p[15] + 2*p[10]*p[14]*p[24];
- coeff[44] = -4*p[0]*p[7]*p[10]*p[19] + 2*p[0]*p[7]*p[10]*p[28] + 4*p[0]*p[8]*p[9]*p[19] - 2*p[0]*p[8]*p[9]*p[28] - 4*p[0]*p[9]*p[9]*p[16] + 2*p[0]*p[9]*p[9]*p[25] - 4*p[0]*p[10]*p[10]*p[16] + 2*p[0]*p[10]*p[10]*p[25] + 4*p[0]*p[11]*p[14]*p[19] - 2*p[0]*p[11]*p[14]*p[28] - 4*p[0]*p[12]*p[13]*p[19] + 2*p[0]*p[12]*p[13]*p[28] + 4*p[0]*p[13]*p[13]*p[16] - 2*p[0]*p[13]*p[13]*p[25] + 4*p[0]*p[14]*p[14]*p[16] - 2*p[0]*p[14]*p[14]*p[25] + 2*p[7]*p[11]*p[16] - 2*p[7]*p[11]*p[25] - 2*p[7]*p[14]*p[19] + 2*p[7]*p[14]*p[28] + 2*p[8]*p[12]*p[16] - 2*p[8]*p[12]*p[25] + 2*p[8]*p[13]*p[19] - 2*p[8]*p[13]*p[28] + 2*p[9]*p[12]*p[19] - 2*p[9]*p[12]*p[28] - 2*p[9]*p[13]*p[16] + 2*p[9]*p[13]*p[25] - 2*p[10]*p[11]*p[19] + 2*p[10]*p[11]*p[28] - 2*p[10]*p[14]*p[16] + 2*p[10]*p[14]*p[25];
- coeff[45] = 4*p[0]*p[7]*p[9]*p[22] - 2*p[0]*p[7]*p[9]*p[31] - 4*p[0]*p[7]*p[10]*p[20] + 2*p[0]*p[7]*p[10]*p[29] + 4*p[0]*p[8]*p[9]*p[20] - 2*p[0]*p[8]*p[9]*p[29] + 4*p[0]*p[8]*p[10]*p[22] - 2*p[0]*p[8]*p[10]*p[31] - 4*p[0]*p[9]*p[9]*p[17] + 2*p[0]*p[9]*p[9]*p[26] - 4*p[0]*p[10]*p[10]*p[17] + 2*p[0]*p[10]*p[10]*p[26] - 4*p[0]*p[11]*p[13]*p[22] + 2*p[0]*p[11]*p[13]*p[31] + 4*p[0]*p[11]*p[14]*p[20] - 2*p[0]*p[11]*p[14]*p[29] - 4*p[0]*p[12]*p[13]*p[20] + 2*p[0]*p[12]*p[13]*p[29] - 4*p[0]*p[12]*p[14]*p[22] + 2*p[0]*p[12]*p[14]*p[31] + 4*p[0]*p[13]*p[13]*p[17] - 2*p[0]*p[13]*p[13]*p[26] + 4*p[0]*p[14]*p[14]*p[17] - 2*p[0]*p[14]*p[14]*p[26] + 2*p[7]*p[11]*p[17] - 2*p[7]*p[11]*p[26] + 2*p[7]*p[13]*p[22] - 2*p[7]*p[13]*p[31] - 2*p[7]*p[14]*p[20] + 2*p[7]*p[14]*p[29] + 2*p[8]*p[12]*p[17] - 2*p[8]*p[12]*p[26] + 2*p[8]*p[13]*p[20] - 2*p[8]*p[13]*p[29] + 2*p[8]*p[14]*p[22] - 2*p[8]*p[14]*p[31] + 2*p[9]*p[11]*p[22] - 2*p[9]*p[11]*p[31] + 2*p[9]*p[12]*p[20] - 2*p[9]*p[12]*p[29] - 2*p[9]*p[13]*p[17] + 2*p[9]*p[13]*p[26] - 2*p[10]*p[11]*p[20] + 2*p[10]*p[11]*p[29] + 2*p[10]*p[12]*p[22] - 2*p[10]*p[12]*p[31] - 2*p[10]*p[14]*p[17] + 2*p[10]*p[14]*p[26];
- coeff[46] = 2*p[0]*p[9]*p[9]*p[15] + 2*p[0]*p[10]*p[10]*p[15] - 2*p[0]*p[13]*p[13]*p[15] - 2*p[0]*p[14]*p[14]*p[15] - 2*p[7]*p[11]*p[15] + 2*p[7]*p[11]*p[24] - 2*p[8]*p[12]*p[15] + 2*p[8]*p[12]*p[24] + 2*p[9]*p[13]*p[15] - 2*p[9]*p[13]*p[24] + 2*p[10]*p[14]*p[15] - 2*p[10]*p[14]*p[24];
- coeff[47] = 2*p[0]*p[7]*p[10]*p[19] - 2*p[0]*p[8]*p[9]*p[19] + 2*p[0]*p[9]*p[9]*p[16] + 2*p[0]*p[10]*p[10]*p[16] - 2*p[0]*p[11]*p[14]*p[19] + 2*p[0]*p[12]*p[13]*p[19] - 2*p[0]*p[13]*p[13]*p[16] - 2*p[0]*p[14]*p[14]*p[16] - 2*p[7]*p[11]*p[16] + 2*p[7]*p[11]*p[25] + 2*p[7]*p[14]*p[19] - 2*p[7]*p[14]*p[28] - 2*p[8]*p[12]*p[16] + 2*p[8]*p[12]*p[25] - 2*p[8]*p[13]*p[19] + 2*p[8]*p[13]*p[28] - 2*p[9]*p[12]*p[19] + 2*p[9]*p[12]*p[28] + 2*p[9]*p[13]*p[16] - 2*p[9]*p[13]*p[25] + 2*p[10]*p[11]*p[19] - 2*p[10]*p[11]*p[28] + 2*p[10]*p[14]*p[16] - 2*p[10]*p[14]*p[25];
- coeff[48] = -2*p[0]*p[7]*p[9]*p[22] + 2*p[0]*p[7]*p[10]*p[20] - 2*p[0]*p[8]*p[9]*p[20] - 2*p[0]*p[8]*p[10]*p[22] + 2*p[0]*p[9]*p[9]*p[17] + 2*p[0]*p[10]*p[10]*p[17] + 2*p[0]*p[11]*p[13]*p[22] - 2*p[0]*p[11]*p[14]*p[20] + 2*p[0]*p[12]*p[13]*p[20] + 2*p[0]*p[12]*p[14]*p[22] - 2*p[0]*p[13]*p[13]*p[17] - 2*p[0]*p[14]*p[14]*p[17] - 2*p[7]*p[11]*p[17] + 2*p[7]*p[11]*p[26] - 2*p[7]*p[13]*p[22] + 2*p[7]*p[13]*p[31] + 2*p[7]*p[14]*p[20] - 2*p[7]*p[14]*p[29] - 2*p[8]*p[12]*p[17] + 2*p[8]*p[12]*p[26] - 2*p[8]*p[13]*p[20] + 2*p[8]*p[13]*p[29] - 2*p[8]*p[14]*p[22] + 2*p[8]*p[14]*p[31] - 2*p[9]*p[11]*p[22] + 2*p[9]*p[11]*p[31] - 2*p[9]*p[12]*p[20] + 2*p[9]*p[12]*p[29] + 2*p[9]*p[13]*p[17] - 2*p[9]*p[13]*p[26] + 2*p[10]*p[11]*p[20] - 2*p[10]*p[11]*p[29] - 2*p[10]*p[12]*p[22] + 2*p[10]*p[12]*p[31] + 2*p[10]*p[14]*p[17] - 2*p[10]*p[14]*p[26];
- coeff[49] = 0;
- coeff[50] = 2*(p[9]*p[9]*p[15] - p[9]*p[9]*p[24] + p[10]*p[10]*p[15] - p[10]*p[10]*p[24] - p[13]*p[13]*p[15] + p[13]*p[13]*p[24] - p[14]*p[14]*p[15] + p[14]*p[14]*p[24])*p[0];
- coeff[51] = 2*(p[7]*p[10]*p[19] - p[7]*p[10]*p[28] - p[8]*p[9]*p[19] + p[8]*p[9]*p[28] + p[9]*p[9]*p[16] - p[9]*p[9]*p[25] + p[10]*p[10]*p[16] - p[10]*p[10]*p[25] - p[11]*p[14]*p[19] + p[11]*p[14]*p[28] + p[12]*p[13]*p[19] - p[12]*p[13]*p[28] - p[13]*p[13]*p[16] + p[13]*p[13]*p[25] - p[14]*p[14]*p[16] + p[14]*p[14]*p[25])*p[0];
- coeff[52] = 2*(-p[7]*p[9]*p[22] + p[7]*p[9]*p[31] + p[7]*p[10]*p[20] - p[7]*p[10]*p[29] - p[8]*p[9]*p[20] + p[8]*p[9]*p[29] - p[8]*p[10]*p[22] + p[8]*p[10]*p[31] + p[9]*p[9]*p[17] - p[9]*p[9]*p[26] + p[10]*p[10]*p[17] - p[10]*p[10]*p[26] + p[11]*p[13]*p[22] - p[11]*p[13]*p[31] - p[11]*p[14]*p[20] + p[11]*p[14]*p[29] + p[12]*p[13]*p[20] - p[12]*p[13]*p[29] + p[12]*p[14]*p[22] - p[12]*p[14]*p[31] - p[13]*p[13]*p[17] + p[13]*p[13]*p[26] - p[14]*p[14]*p[17] + p[14]*p[14]*p[26])*p[0];
- coeff[53] = 2*(-p[9]*p[9]*p[15] + p[9]*p[9]*p[24] - p[10]*p[10]*p[15] + p[10]*p[10]*p[24] + p[13]*p[13]*p[15] - p[13]*p[13]*p[24] + p[14]*p[14]*p[15] - p[14]*p[14]*p[24])*p[0];
- coeff[54] = 2*(-p[7]*p[10]*p[19] + p[7]*p[10]*p[28] + p[8]*p[9]*p[19] - p[8]*p[9]*p[28] - p[9]*p[9]*p[16] + p[9]*p[9]*p[25] - p[10]*p[10]*p[16] + p[10]*p[10]*p[25] + p[11]*p[14]*p[19] - p[11]*p[14]*p[28] - p[12]*p[13]*p[19] + p[12]*p[13]*p[28] + p[13]*p[13]*p[16] - p[13]*p[13]*p[25] + p[14]*p[14]*p[16] - p[14]*p[14]*p[25])*p[0];
- coeff[55] = 2*(p[7]*p[9]*p[22] - p[7]*p[9]*p[31] - p[7]*p[10]*p[20] + p[7]*p[10]*p[29] + p[8]*p[9]*p[20] - p[8]*p[9]*p[29] + p[8]*p[10]*p[22] - p[8]*p[10]*p[31] - p[9]*p[9]*p[17] + p[9]*p[9]*p[26] - p[10]*p[10]*p[17] + p[10]*p[10]*p[26] - p[11]*p[13]*p[22] + p[11]*p[13]*p[31] + p[11]*p[14]*p[20] - p[11]*p[14]*p[29] - p[12]*p[13]*p[20] + p[12]*p[13]*p[29] - p[12]*p[14]*p[22] + p[12]*p[14]*p[31] + p[13]*p[13]*p[17] - p[13]*p[13]*p[26] + p[14]*p[14]*p[17] - p[14]*p[14]*p[26])*p[0];
- coeff[56] = -p[2] + p[5] + p[7]*p[8]*p[23] - p[7]*p[8]*p[32] - p[7]*p[10]*p[18] + p[7]*p[10]*p[27] + p[8]*p[8]*p[21] - p[8]*p[8]*p[30] - p[8]*p[9]*p[18] + p[8]*p[9]*p[27] - p[9]*p[10]*p[23] + p[9]*p[10]*p[32] + p[10]*p[10]*p[21] - p[10]*p[10]*p[30] + p[11]*p[12]*p[23] - p[11]*p[12]*p[32] - p[11]*p[14]*p[18] + p[11]*p[14]*p[27] + p[12]*p[12]*p[21] - p[12]*p[12]*p[30] - p[12]*p[13]*p[18] + p[12]*p[13]*p[27] - p[13]*p[14]*p[23] + p[13]*p[14]*p[32] + p[14]*p[14]*p[21] - p[14]*p[14]*p[30] - p[21] + p[30];
- coeff[57] = -2*p[7]*p[10]*p[15] + p[7]*p[10]*p[24] - 2*p[8]*p[9]*p[15] + p[8]*p[9]*p[24] - 2*p[11]*p[14]*p[15] + p[11]*p[14]*p[24] - 2*p[12]*p[13]*p[15] + p[12]*p[13]*p[24];
- coeff[58] = -2*p[7]*p[10]*p[16] + p[7]*p[10]*p[25] + 2*p[8]*p[8]*p[19] - p[8]*p[8]*p[28] - 2*p[8]*p[9]*p[16] + p[8]*p[9]*p[25] + 2*p[10]*p[10]*p[19] - p[10]*p[10]*p[28] - 2*p[11]*p[14]*p[16] + p[11]*p[14]*p[25] + 2*p[12]*p[12]*p[19] - p[12]*p[12]*p[28] - 2*p[12]*p[13]*p[16] + p[12]*p[13]*p[25] + 2*p[14]*p[14]*p[19] - p[14]*p[14]*p[28] - 2*p[19] + p[28];
- coeff[59] = 2*p[7]*p[8]*p[22] - p[7]*p[8]*p[31] - 2*p[7]*p[10]*p[17] + p[7]*p[10]*p[26] + 2*p[8]*p[8]*p[20] - p[8]*p[8]*p[29] - 2*p[8]*p[9]*p[17] + p[8]*p[9]*p[26] - 2*p[9]*p[10]*p[22] + p[9]*p[10]*p[31] + 2*p[10]*p[10]*p[20] - p[10]*p[10]*p[29] + 2*p[11]*p[12]*p[22] - p[11]*p[12]*p[31] - 2*p[11]*p[14]*p[17] + p[11]*p[14]*p[26] + 2*p[12]*p[12]*p[20] - p[12]*p[12]*p[29] - 2*p[12]*p[13]*p[17] + p[12]*p[13]*p[26] - 2*p[13]*p[14]*p[22] + p[13]*p[14]*p[31] + 2*p[14]*p[14]*p[20] - p[14]*p[14]*p[29] - 2*p[20] + p[29];
- coeff[60] = (p[7]*p[10] + p[8]*p[9] + p[11]*p[14] + p[12]*p[13])*p[15];
- coeff[61] = p[7]*p[10]*p[16] - p[8]*p[8]*p[19] + p[8]*p[9]*p[16] - p[10]*p[10]*p[19] + p[11]*p[14]*p[16] - p[12]*p[12]*p[19] + p[12]*p[13]*p[16] - p[14]*p[14]*p[19] + p[19];
- coeff[62] = -p[7]*p[8]*p[22] + p[7]*p[10]*p[17] - p[8]*p[8]*p[20] + p[8]*p[9]*p[17] + p[9]*p[10]*p[22] - p[10]*p[10]*p[20] - p[11]*p[12]*p[22] + p[11]*p[14]*p[17] - p[12]*p[12]*p[20] + p[12]*p[13]*p[17] + p[13]*p[14]*p[22] - p[14]*p[14]*p[20] + p[20];
- coeff[63] = 0;
- coeff[64] = 2*p[7]*p[10]*p[15] - 2*p[7]*p[10]*p[24] + 2*p[8]*p[9]*p[15] - 2*p[8]*p[9]*p[24] + 2*p[11]*p[14]*p[15] - 2*p[11]*p[14]*p[24] + 2*p[12]*p[13]*p[15] - 2*p[12]*p[13]*p[24];
- coeff[65] = 2*p[7]*p[10]*p[16] - 2*p[7]*p[10]*p[25] - 2*p[8]*p[8]*p[19] + 2*p[8]*p[8]*p[28] + 2*p[8]*p[9]*p[16] - 2*p[8]*p[9]*p[25] - 2*p[10]*p[10]*p[19] + 2*p[10]*p[10]*p[28] + 2*p[11]*p[14]*p[16] - 2*p[11]*p[14]*p[25] - 2*p[12]*p[12]*p[19] + 2*p[12]*p[12]*p[28] + 2*p[12]*p[13]*p[16] - 2*p[12]*p[13]*p[25] - 2*p[14]*p[14]*p[19] + 2*p[14]*p[14]*p[28] + 2*p[19] - 2*p[28];
- coeff[66] = -2*p[7]*p[8]*p[22] + 2*p[7]*p[8]*p[31] + 2*p[7]*p[10]*p[17] - 2*p[7]*p[10]*p[26] - 2*p[8]*p[8]*p[20] + 2*p[8]*p[8]*p[29] + 2*p[8]*p[9]*p[17] - 2*p[8]*p[9]*p[26] + 2*p[9]*p[10]*p[22] - 2*p[9]*p[10]*p[31] - 2*p[10]*p[10]*p[20] + 2*p[10]*p[10]*p[29] - 2*p[11]*p[12]*p[22] + 2*p[11]*p[12]*p[31] + 2*p[11]*p[14]*p[17] - 2*p[11]*p[14]*p[26] - 2*p[12]*p[12]*p[20] + 2*p[12]*p[12]*p[29] + 2*p[12]*p[13]*p[17] - 2*p[12]*p[13]*p[26] + 2*p[13]*p[14]*p[22] - 2*p[13]*p[14]*p[31] - 2*p[14]*p[14]*p[20] + 2*p[14]*p[14]*p[29] + 2*p[20] - 2*p[29];
- coeff[67] = -2*p[7]*p[10]*p[15] + 2*p[7]*p[10]*p[24] - 2*p[8]*p[9]*p[15] + 2*p[8]*p[9]*p[24] - 2*p[11]*p[14]*p[15] + 2*p[11]*p[14]*p[24] - 2*p[12]*p[13]*p[15] + 2*p[12]*p[13]*p[24];
- coeff[68] = -2*p[7]*p[10]*p[16] + 2*p[7]*p[10]*p[25] + 2*p[8]*p[8]*p[19] - 2*p[8]*p[8]*p[28] - 2*p[8]*p[9]*p[16] + 2*p[8]*p[9]*p[25] + 2*p[10]*p[10]*p[19] - 2*p[10]*p[10]*p[28] - 2*p[11]*p[14]*p[16] + 2*p[11]*p[14]*p[25] + 2*p[12]*p[12]*p[19] - 2*p[12]*p[12]*p[28] - 2*p[12]*p[13]*p[16] + 2*p[12]*p[13]*p[25] + 2*p[14]*p[14]*p[19] - 2*p[14]*p[14]*p[28] - 2*p[19] + 2*p[28];
- coeff[69] = 2*p[7]*p[8]*p[22] - 2*p[7]*p[8]*p[31] - 2*p[7]*p[10]*p[17] + 2*p[7]*p[10]*p[26] + 2*p[8]*p[8]*p[20] - 2*p[8]*p[8]*p[29] - 2*p[8]*p[9]*p[17] + 2*p[8]*p[9]*p[26] - 2*p[9]*p[10]*p[22] + 2*p[9]*p[10]*p[31] + 2*p[10]*p[10]*p[20] - 2*p[10]*p[10]*p[29] + 2*p[11]*p[12]*p[22] - 2*p[11]*p[12]*p[31] - 2*p[11]*p[14]*p[17] + 2*p[11]*p[14]*p[26] + 2*p[12]*p[12]*p[20] - 2*p[12]*p[12]*p[29] - 2*p[12]*p[13]*p[17] + 2*p[12]*p[13]*p[26] - 2*p[13]*p[14]*p[22] + 2*p[13]*p[14]*p[31] + 2*p[14]*p[14]*p[20] - 2*p[14]*p[14]*p[29] - 2*p[20] + 2*p[29];
- coeff[70] = 2*p[0]*p[7]*p[11]*p[21] - 2*p[0]*p[7]*p[12]*p[23] + 2*p[0]*p[7]*p[14]*p[18] - 2*p[0]*p[8]*p[11]*p[23] - 2*p[0]*p[8]*p[12]*p[21] + 2*p[0]*p[8]*p[13]*p[18] + 2*p[0]*p[9]*p[12]*p[18] + 2*p[0]*p[9]*p[13]*p[21] + 2*p[0]*p[9]*p[14]*p[23] + 2*p[0]*p[10]*p[11]*p[18] + 2*p[0]*p[10]*p[13]*p[23] - 2*p[0]*p[10]*p[14]*p[21] + p[7]*p[8]*p[23] - p[7]*p[8]*p[32] - p[7]*p[10]*p[18] + p[7]*p[10]*p[27] + p[8]*p[8]*p[21] - p[8]*p[8]*p[30] - p[8]*p[9]*p[18] + p[8]*p[9]*p[27] - p[9]*p[10]*p[23] + p[9]*p[10]*p[32] + p[10]*p[10]*p[21] - p[10]*p[10]*p[30] - p[11]*p[12]*p[23] + p[11]*p[12]*p[32] + p[11]*p[14]*p[18] - p[11]*p[14]*p[27] - p[12]*p[12]*p[21] + p[12]*p[12]*p[30] + p[12]*p[13]*p[18] - p[12]*p[13]*p[27] + p[13]*p[14]*p[23] - p[13]*p[14]*p[32] - p[14]*p[14]*p[21] + p[14]*p[14]*p[30];
- coeff[71] = 2*p[0]*p[7]*p[14]*p[15] + 2*p[0]*p[8]*p[13]*p[15] + 2*p[0]*p[9]*p[12]*p[15] + 2*p[0]*p[10]*p[11]*p[15] - 2*p[7]*p[10]*p[15] + p[7]*p[10]*p[24] - 2*p[8]*p[9]*p[15] + p[8]*p[9]*p[24] + 2*p[11]*p[14]*p[15] - p[11]*p[14]*p[24] + 2*p[12]*p[13]*p[15] - p[12]*p[13]*p[24];
- coeff[72] = 2*p[0]*p[7]*p[11]*p[19] + 2*p[0]*p[7]*p[14]*p[16] - 2*p[0]*p[8]*p[12]*p[19] + 2*p[0]*p[8]*p[13]*p[16] + 2*p[0]*p[9]*p[12]*p[16] + 2*p[0]*p[9]*p[13]*p[19] + 2*p[0]*p[10]*p[11]*p[16] - 2*p[0]*p[10]*p[14]*p[19] - 2*p[7]*p[10]*p[16] + p[7]*p[10]*p[25] + 2*p[8]*p[8]*p[19] - p[8]*p[8]*p[28] - 2*p[8]*p[9]*p[16] + p[8]*p[9]*p[25] + 2*p[10]*p[10]*p[19] - p[10]*p[10]*p[28] + 2*p[11]*p[14]*p[16] - p[11]*p[14]*p[25] - 2*p[12]*p[12]*p[19] + p[12]*p[12]*p[28] + 2*p[12]*p[13]*p[16] - p[12]*p[13]*p[25] - 2*p[14]*p[14]*p[19] + p[14]*p[14]*p[28];
- coeff[73] = 2*p[0]*p[7]*p[11]*p[20] - 2*p[0]*p[7]*p[12]*p[22] + 2*p[0]*p[7]*p[14]*p[17] - 2*p[0]*p[8]*p[11]*p[22] - 2*p[0]*p[8]*p[12]*p[20] + 2*p[0]*p[8]*p[13]*p[17] + 2*p[0]*p[9]*p[12]*p[17] + 2*p[0]*p[9]*p[13]*p[20] + 2*p[0]*p[9]*p[14]*p[22] + 2*p[0]*p[10]*p[11]*p[17] + 2*p[0]*p[10]*p[13]*p[22] - 2*p[0]*p[10]*p[14]*p[20] + 2*p[7]*p[8]*p[22] - p[7]*p[8]*p[31] - 2*p[7]*p[10]*p[17] + p[7]*p[10]*p[26] + 2*p[8]*p[8]*p[20] - p[8]*p[8]*p[29] - 2*p[8]*p[9]*p[17] + p[8]*p[9]*p[26] - 2*p[9]*p[10]*p[22] + p[9]*p[10]*p[31] + 2*p[10]*p[10]*p[20] - p[10]*p[10]*p[29] - 2*p[11]*p[12]*p[22] + p[11]*p[12]*p[31] + 2*p[11]*p[14]*p[17] - p[11]*p[14]*p[26] - 2*p[12]*p[12]*p[20] + p[12]*p[12]*p[29] + 2*p[12]*p[13]*p[17] - p[12]*p[13]*p[26] + 2*p[13]*p[14]*p[22] - p[13]*p[14]*p[31] - 2*p[14]*p[14]*p[20] + p[14]*p[14]*p[29];
- coeff[74] = (p[7]*p[10] + p[8]*p[9] - p[11]*p[14] - p[12]*p[13])*p[15];
- coeff[75] = p[7]*p[10]*p[16] - p[8]*p[8]*p[19] + p[8]*p[9]*p[16] - p[10]*p[10]*p[19] - p[11]*p[14]*p[16] + p[12]*p[12]*p[19] - p[12]*p[13]*p[16] + p[14]*p[14]*p[19];
- coeff[76] = -p[7]*p[8]*p[22] + p[7]*p[10]*p[17] - p[8]*p[8]*p[20] + p[8]*p[9]*p[17] + p[9]*p[10]*p[22] - p[10]*p[10]*p[20] + p[11]*p[12]*p[22] - p[11]*p[14]*p[17] + p[12]*p[12]*p[20] - p[12]*p[13]*p[17] - p[13]*p[14]*p[22] + p[14]*p[14]*p[20];
- coeff[77] = 2*(-p[7]*p[11]*p[21] + p[7]*p[11]*p[30] + p[7]*p[12]*p[23] - p[7]*p[12]*p[32] - p[7]*p[14]*p[18] + p[7]*p[14]*p[27] + p[8]*p[11]*p[23] - p[8]*p[11]*p[32] + p[8]*p[12]*p[21] - p[8]*p[12]*p[30] - p[8]*p[13]*p[18] + p[8]*p[13]*p[27] - p[9]*p[12]*p[18] + p[9]*p[12]*p[27] - p[9]*p[13]*p[21] + p[9]*p[13]*p[30] - p[9]*p[14]*p[23] + p[9]*p[14]*p[32] - p[10]*p[11]*p[18] + p[10]*p[11]*p[27] - p[10]*p[13]*p[23] + p[10]*p[13]*p[32] + p[10]*p[14]*p[21] - p[10]*p[14]*p[30])*p[0];
- coeff[78] = -4*p[0]*p[7]*p[14]*p[15] + 2*p[0]*p[7]*p[14]*p[24] - 4*p[0]*p[8]*p[13]*p[15] + 2*p[0]*p[8]*p[13]*p[24] - 4*p[0]*p[9]*p[12]*p[15] + 2*p[0]*p[9]*p[12]*p[24] - 4*p[0]*p[10]*p[11]*p[15] + 2*p[0]*p[10]*p[11]*p[24] + 2*p[7]*p[10]*p[15] - 2*p[7]*p[10]*p[24] + 2*p[8]*p[9]*p[15] - 2*p[8]*p[9]*p[24] - 2*p[11]*p[14]*p[15] + 2*p[11]*p[14]*p[24] - 2*p[12]*p[13]*p[15] + 2*p[12]*p[13]*p[24];
- coeff[79] = -4*p[0]*p[7]*p[11]*p[19] + 2*p[0]*p[7]*p[11]*p[28] - 4*p[0]*p[7]*p[14]*p[16] + 2*p[0]*p[7]*p[14]*p[25] + 4*p[0]*p[8]*p[12]*p[19] - 2*p[0]*p[8]*p[12]*p[28] - 4*p[0]*p[8]*p[13]*p[16] + 2*p[0]*p[8]*p[13]*p[25] - 4*p[0]*p[9]*p[12]*p[16] + 2*p[0]*p[9]*p[12]*p[25] - 4*p[0]*p[9]*p[13]*p[19] + 2*p[0]*p[9]*p[13]*p[28] - 4*p[0]*p[10]*p[11]*p[16] + 2*p[0]*p[10]*p[11]*p[25] + 4*p[0]*p[10]*p[14]*p[19] - 2*p[0]*p[10]*p[14]*p[28] + 2*p[7]*p[10]*p[16] - 2*p[7]*p[10]*p[25] - 2*p[8]*p[8]*p[19] + 2*p[8]*p[8]*p[28] + 2*p[8]*p[9]*p[16] - 2*p[8]*p[9]*p[25] - 2*p[10]*p[10]*p[19] + 2*p[10]*p[10]*p[28] - 2*p[11]*p[14]*p[16] + 2*p[11]*p[14]*p[25] + 2*p[12]*p[12]*p[19] - 2*p[12]*p[12]*p[28] - 2*p[12]*p[13]*p[16] + 2*p[12]*p[13]*p[25] + 2*p[14]*p[14]*p[19] - 2*p[14]*p[14]*p[28];
- coeff[80] = -4*p[0]*p[7]*p[11]*p[20] + 2*p[0]*p[7]*p[11]*p[29] + 4*p[0]*p[7]*p[12]*p[22] - 2*p[0]*p[7]*p[12]*p[31] - 4*p[0]*p[7]*p[14]*p[17] + 2*p[0]*p[7]*p[14]*p[26] + 4*p[0]*p[8]*p[11]*p[22] - 2*p[0]*p[8]*p[11]*p[31] + 4*p[0]*p[8]*p[12]*p[20] - 2*p[0]*p[8]*p[12]*p[29] - 4*p[0]*p[8]*p[13]*p[17] + 2*p[0]*p[8]*p[13]*p[26] - 4*p[0]*p[9]*p[12]*p[17] + 2*p[0]*p[9]*p[12]*p[26] - 4*p[0]*p[9]*p[13]*p[20] + 2*p[0]*p[9]*p[13]*p[29] - 4*p[0]*p[9]*p[14]*p[22] + 2*p[0]*p[9]*p[14]*p[31] - 4*p[0]*p[10]*p[11]*p[17] + 2*p[0]*p[10]*p[11]*p[26] - 4*p[0]*p[10]*p[13]*p[22] + 2*p[0]*p[10]*p[13]*p[31] + 4*p[0]*p[10]*p[14]*p[20] - 2*p[0]*p[10]*p[14]*p[29] - 2*p[7]*p[8]*p[22] + 2*p[7]*p[8]*p[31] + 2*p[7]*p[10]*p[17] - 2*p[7]*p[10]*p[26] - 2*p[8]*p[8]*p[20] + 2*p[8]*p[8]*p[29] + 2*p[8]*p[9]*p[17] - 2*p[8]*p[9]*p[26] + 2*p[9]*p[10]*p[22] - 2*p[9]*p[10]*p[31] - 2*p[10]*p[10]*p[20] + 2*p[10]*p[10]*p[29] + 2*p[11]*p[12]*p[22] - 2*p[11]*p[12]*p[31] - 2*p[11]*p[14]*p[17] + 2*p[11]*p[14]*p[26] + 2*p[12]*p[12]*p[20] - 2*p[12]*p[12]*p[29] - 2*p[12]*p[13]*p[17] + 2*p[12]*p[13]*p[26] - 2*p[13]*p[14]*p[22] + 2*p[13]*p[14]*p[31] + 2*p[14]*p[14]*p[20] - 2*p[14]*p[14]*p[29];
- coeff[81] = 2*p[0]*p[7]*p[14]*p[15] + 2*p[0]*p[8]*p[13]*p[15] + 2*p[0]*p[9]*p[12]*p[15] + 2*p[0]*p[10]*p[11]*p[15] - 2*p[7]*p[10]*p[15] + 2*p[7]*p[10]*p[24] - 2*p[8]*p[9]*p[15] + 2*p[8]*p[9]*p[24] + 2*p[11]*p[14]*p[15] - 2*p[11]*p[14]*p[24] + 2*p[12]*p[13]*p[15] - 2*p[12]*p[13]*p[24];
- coeff[82] = 2*p[0]*p[7]*p[11]*p[19] + 2*p[0]*p[7]*p[14]*p[16] - 2*p[0]*p[8]*p[12]*p[19] + 2*p[0]*p[8]*p[13]*p[16] + 2*p[0]*p[9]*p[12]*p[16] + 2*p[0]*p[9]*p[13]*p[19] + 2*p[0]*p[10]*p[11]*p[16] - 2*p[0]*p[10]*p[14]*p[19] - 2*p[7]*p[10]*p[16] + 2*p[7]*p[10]*p[25] + 2*p[8]*p[8]*p[19] - 2*p[8]*p[8]*p[28] - 2*p[8]*p[9]*p[16] + 2*p[8]*p[9]*p[25] + 2*p[10]*p[10]*p[19] - 2*p[10]*p[10]*p[28] + 2*p[11]*p[14]*p[16] - 2*p[11]*p[14]*p[25] - 2*p[12]*p[12]*p[19] + 2*p[12]*p[12]*p[28] + 2*p[12]*p[13]*p[16] - 2*p[12]*p[13]*p[25] - 2*p[14]*p[14]*p[19] + 2*p[14]*p[14]*p[28];
- coeff[83] = 2*p[0]*p[7]*p[11]*p[20] - 2*p[0]*p[7]*p[12]*p[22] + 2*p[0]*p[7]*p[14]*p[17] - 2*p[0]*p[8]*p[11]*p[22] - 2*p[0]*p[8]*p[12]*p[20] + 2*p[0]*p[8]*p[13]*p[17] + 2*p[0]*p[9]*p[12]*p[17] + 2*p[0]*p[9]*p[13]*p[20] + 2*p[0]*p[9]*p[14]*p[22] + 2*p[0]*p[10]*p[11]*p[17] + 2*p[0]*p[10]*p[13]*p[22] - 2*p[0]*p[10]*p[14]*p[20] + 2*p[7]*p[8]*p[22] - 2*p[7]*p[8]*p[31] - 2*p[7]*p[10]*p[17] + 2*p[7]*p[10]*p[26] + 2*p[8]*p[8]*p[20] - 2*p[8]*p[8]*p[29] - 2*p[8]*p[9]*p[17] + 2*p[8]*p[9]*p[26] - 2*p[9]*p[10]*p[22] + 2*p[9]*p[10]*p[31] + 2*p[10]*p[10]*p[20] - 2*p[10]*p[10]*p[29] - 2*p[11]*p[12]*p[22] + 2*p[11]*p[12]*p[31] + 2*p[11]*p[14]*p[17] - 2*p[11]*p[14]*p[26] - 2*p[12]*p[12]*p[20] + 2*p[12]*p[12]*p[29] + 2*p[12]*p[13]*p[17] - 2*p[12]*p[13]*p[26] + 2*p[13]*p[14]*p[22] - 2*p[13]*p[14]*p[31] - 2*p[14]*p[14]*p[20] + 2*p[14]*p[14]*p[29];
- coeff[84] = 0;
- coeff[85] = 2*(p[7]*p[14]*p[15] - p[7]*p[14]*p[24] + p[8]*p[13]*p[15] - p[8]*p[13]*p[24] + p[9]*p[12]*p[15] - p[9]*p[12]*p[24] + p[10]*p[11]*p[15] - p[10]*p[11]*p[24])*p[0];
- coeff[86] = 2*(p[7]*p[11]*p[19] - p[7]*p[11]*p[28] + p[7]*p[14]*p[16] - p[7]*p[14]*p[25] - p[8]*p[12]*p[19] + p[8]*p[12]*p[28] + p[8]*p[13]*p[16] - p[8]*p[13]*p[25] + p[9]*p[12]*p[16] - p[9]*p[12]*p[25] + p[9]*p[13]*p[19] - p[9]*p[13]*p[28] + p[10]*p[11]*p[16] - p[10]*p[11]*p[25] - p[10]*p[14]*p[19] + p[10]*p[14]*p[28])*p[0];
- coeff[87] = 2*(p[7]*p[11]*p[20] - p[7]*p[11]*p[29] - p[7]*p[12]*p[22] + p[7]*p[12]*p[31] + p[7]*p[14]*p[17] - p[7]*p[14]*p[26] - p[8]*p[11]*p[22] + p[8]*p[11]*p[31] - p[8]*p[12]*p[20] + p[8]*p[12]*p[29] + p[8]*p[13]*p[17] - p[8]*p[13]*p[26] + p[9]*p[12]*p[17] - p[9]*p[12]*p[26] + p[9]*p[13]*p[20] - p[9]*p[13]*p[29] + p[9]*p[14]*p[22] - p[9]*p[14]*p[31] + p[10]*p[11]*p[17] - p[10]*p[11]*p[26] + p[10]*p[13]*p[22] - p[10]*p[13]*p[31] - p[10]*p[14]*p[20] + p[10]*p[14]*p[29])*p[0];
- coeff[88] = 2*(-p[7]*p[14]*p[15] + p[7]*p[14]*p[24] - p[8]*p[13]*p[15] + p[8]*p[13]*p[24] - p[9]*p[12]*p[15] + p[9]*p[12]*p[24] - p[10]*p[11]*p[15] + p[10]*p[11]*p[24])*p[0];
- coeff[89] = 2*(-p[7]*p[11]*p[19] + p[7]*p[11]*p[28] - p[7]*p[14]*p[16] + p[7]*p[14]*p[25] + p[8]*p[12]*p[19] - p[8]*p[12]*p[28] - p[8]*p[13]*p[16] + p[8]*p[13]*p[25] - p[9]*p[12]*p[16] + p[9]*p[12]*p[25] - p[9]*p[13]*p[19] + p[9]*p[13]*p[28] - p[10]*p[11]*p[16] + p[10]*p[11]*p[25] + p[10]*p[14]*p[19] - p[10]*p[14]*p[28])*p[0];
- coeff[90] = 2*(-p[7]*p[11]*p[20] + p[7]*p[11]*p[29] + p[7]*p[12]*p[22] - p[7]*p[12]*p[31] - p[7]*p[14]*p[17] + p[7]*p[14]*p[26] + p[8]*p[11]*p[22] - p[8]*p[11]*p[31] + p[8]*p[12]*p[20] - p[8]*p[12]*p[29] - p[8]*p[13]*p[17] + p[8]*p[13]*p[26] - p[9]*p[12]*p[17] + p[9]*p[12]*p[26] - p[9]*p[13]*p[20] + p[9]*p[13]*p[29] - p[9]*p[14]*p[22] + p[9]*p[14]*p[31] - p[10]*p[11]*p[17] + p[10]*p[11]*p[26] - p[10]*p[13]*p[22] + p[10]*p[13]*p[31] + p[10]*p[14]*p[20] - p[10]*p[14]*p[29])*p[0];
- coeff[91] = 2*p[0]*p[7]*p[8]*p[23] - 2*p[0]*p[7]*p[10]*p[18] + 2*p[0]*p[8]*p[8]*p[21] - 2*p[0]*p[8]*p[9]*p[18] - 2*p[0]*p[9]*p[10]*p[23] + 2*p[0]*p[10]*p[10]*p[21] - 2*p[0]*p[11]*p[12]*p[23] + 2*p[0]*p[11]*p[14]*p[18] - 2*p[0]*p[12]*p[12]*p[21] + 2*p[0]*p[12]*p[13]*p[18] + 2*p[0]*p[13]*p[14]*p[23] - 2*p[0]*p[14]*p[14]*p[21] - p[7]*p[11]*p[21] + p[7]*p[11]*p[30] + p[7]*p[12]*p[23] - p[7]*p[12]*p[32] - p[7]*p[14]*p[18] + p[7]*p[14]*p[27] + p[8]*p[11]*p[23] - p[8]*p[11]*p[32] + p[8]*p[12]*p[21] - p[8]*p[12]*p[30] - p[8]*p[13]*p[18] + p[8]*p[13]*p[27] - p[9]*p[12]*p[18] + p[9]*p[12]*p[27] - p[9]*p[13]*p[21] + p[9]*p[13]*p[30] - p[9]*p[14]*p[23] + p[9]*p[14]*p[32] - p[10]*p[11]*p[18] + p[10]*p[11]*p[27] - p[10]*p[13]*p[23] + p[10]*p[13]*p[32] + p[10]*p[14]*p[21] - p[10]*p[14]*p[30];
- coeff[92] = -2*p[0]*p[7]*p[10]*p[15] - 2*p[0]*p[8]*p[9]*p[15] + 2*p[0]*p[11]*p[14]*p[15] + 2*p[0]*p[12]*p[13]*p[15] - 2*p[7]*p[14]*p[15] + p[7]*p[14]*p[24] - 2*p[8]*p[13]*p[15] + p[8]*p[13]*p[24] - 2*p[9]*p[12]*p[15] + p[9]*p[12]*p[24] - 2*p[10]*p[11]*p[15] + p[10]*p[11]*p[24];
- coeff[93] = -2*p[0]*p[7]*p[10]*p[16] + 2*p[0]*p[8]*p[8]*p[19] - 2*p[0]*p[8]*p[9]*p[16] + 2*p[0]*p[10]*p[10]*p[19] + 2*p[0]*p[11]*p[14]*p[16] - 2*p[0]*p[12]*p[12]*p[19] + 2*p[0]*p[12]*p[13]*p[16] - 2*p[0]*p[14]*p[14]*p[19] - 2*p[7]*p[11]*p[19] + p[7]*p[11]*p[28] - 2*p[7]*p[14]*p[16] + p[7]*p[14]*p[25] + 2*p[8]*p[12]*p[19] - p[8]*p[12]*p[28] - 2*p[8]*p[13]*p[16] + p[8]*p[13]*p[25] - 2*p[9]*p[12]*p[16] + p[9]*p[12]*p[25] - 2*p[9]*p[13]*p[19] + p[9]*p[13]*p[28] - 2*p[10]*p[11]*p[16] + p[10]*p[11]*p[25] + 2*p[10]*p[14]*p[19] - p[10]*p[14]*p[28];
- coeff[94] = 2*p[0]*p[7]*p[8]*p[22] - 2*p[0]*p[7]*p[10]*p[17] + 2*p[0]*p[8]*p[8]*p[20] - 2*p[0]*p[8]*p[9]*p[17] - 2*p[0]*p[9]*p[10]*p[22] + 2*p[0]*p[10]*p[10]*p[20] - 2*p[0]*p[11]*p[12]*p[22] + 2*p[0]*p[11]*p[14]*p[17] - 2*p[0]*p[12]*p[12]*p[20] + 2*p[0]*p[12]*p[13]*p[17] + 2*p[0]*p[13]*p[14]*p[22] - 2*p[0]*p[14]*p[14]*p[20] - 2*p[7]*p[11]*p[20] + p[7]*p[11]*p[29] + 2*p[7]*p[12]*p[22] - p[7]*p[12]*p[31] - 2*p[7]*p[14]*p[17] + p[7]*p[14]*p[26] + 2*p[8]*p[11]*p[22] - p[8]*p[11]*p[31] + 2*p[8]*p[12]*p[20] - p[8]*p[12]*p[29] - 2*p[8]*p[13]*p[17] + p[8]*p[13]*p[26] - 2*p[9]*p[12]*p[17] + p[9]*p[12]*p[26] - 2*p[9]*p[13]*p[20] + p[9]*p[13]*p[29] - 2*p[9]*p[14]*p[22] + p[9]*p[14]*p[31] - 2*p[10]*p[11]*p[17] + p[10]*p[11]*p[26] - 2*p[10]*p[13]*p[22] + p[10]*p[13]*p[31] + 2*p[10]*p[14]*p[20] - p[10]*p[14]*p[29];
- coeff[95] = (p[7]*p[14] + p[8]*p[13] + p[9]*p[12] + p[10]*p[11])*p[15];
- coeff[96] = p[7]*p[11]*p[19] + p[7]*p[14]*p[16] - p[8]*p[12]*p[19] + p[8]*p[13]*p[16] + p[9]*p[12]*p[16] + p[9]*p[13]*p[19] + p[10]*p[11]*p[16] - p[10]*p[14]*p[19];
- coeff[97] = p[7]*p[11]*p[20] - p[7]*p[12]*p[22] + p[7]*p[14]*p[17] - p[8]*p[11]*p[22] - p[8]*p[12]*p[20] + p[8]*p[13]*p[17] + p[9]*p[12]*p[17] + p[9]*p[13]*p[20] + p[9]*p[14]*p[22] + p[10]*p[11]*p[17] + p[10]*p[13]*p[22] - p[10]*p[14]*p[20];
- coeff[98] = 2*(-p[7]*p[8]*p[23] + p[7]*p[8]*p[32] + p[7]*p[10]*p[18] - p[7]*p[10]*p[27] - p[8]*p[8]*p[21] + p[8]*p[8]*p[30] + p[8]*p[9]*p[18] - p[8]*p[9]*p[27] + p[9]*p[10]*p[23] - p[9]*p[10]*p[32] - p[10]*p[10]*p[21] + p[10]*p[10]*p[30] + p[11]*p[12]*p[23] - p[11]*p[12]*p[32] - p[11]*p[14]*p[18] + p[11]*p[14]*p[27] + p[12]*p[12]*p[21] - p[12]*p[12]*p[30] - p[12]*p[13]*p[18] + p[12]*p[13]*p[27] - p[13]*p[14]*p[23] + p[13]*p[14]*p[32] + p[14]*p[14]*p[21] - p[14]*p[14]*p[30])*p[0];
- coeff[99] = 4*p[0]*p[7]*p[10]*p[15] - 2*p[0]*p[7]*p[10]*p[24] + 4*p[0]*p[8]*p[9]*p[15] - 2*p[0]*p[8]*p[9]*p[24] - 4*p[0]*p[11]*p[14]*p[15] + 2*p[0]*p[11]*p[14]*p[24] - 4*p[0]*p[12]*p[13]*p[15] + 2*p[0]*p[12]*p[13]*p[24] + 2*p[7]*p[14]*p[15] - 2*p[7]*p[14]*p[24] + 2*p[8]*p[13]*p[15] - 2*p[8]*p[13]*p[24] + 2*p[9]*p[12]*p[15] - 2*p[9]*p[12]*p[24] + 2*p[10]*p[11]*p[15] - 2*p[10]*p[11]*p[24];
- coeff[100] = 4*p[0]*p[7]*p[10]*p[16] - 2*p[0]*p[7]*p[10]*p[25] - 4*p[0]*p[8]*p[8]*p[19] + 2*p[0]*p[8]*p[8]*p[28] + 4*p[0]*p[8]*p[9]*p[16] - 2*p[0]*p[8]*p[9]*p[25] - 4*p[0]*p[10]*p[10]*p[19] + 2*p[0]*p[10]*p[10]*p[28] - 4*p[0]*p[11]*p[14]*p[16] + 2*p[0]*p[11]*p[14]*p[25] + 4*p[0]*p[12]*p[12]*p[19] - 2*p[0]*p[12]*p[12]*p[28] - 4*p[0]*p[12]*p[13]*p[16] + 2*p[0]*p[12]*p[13]*p[25] + 4*p[0]*p[14]*p[14]*p[19] - 2*p[0]*p[14]*p[14]*p[28] + 2*p[7]*p[11]*p[19] - 2*p[7]*p[11]*p[28] + 2*p[7]*p[14]*p[16] - 2*p[7]*p[14]*p[25] - 2*p[8]*p[12]*p[19] + 2*p[8]*p[12]*p[28] + 2*p[8]*p[13]*p[16] - 2*p[8]*p[13]*p[25] + 2*p[9]*p[12]*p[16] - 2*p[9]*p[12]*p[25] + 2*p[9]*p[13]*p[19] - 2*p[9]*p[13]*p[28] + 2*p[10]*p[11]*p[16] - 2*p[10]*p[11]*p[25] - 2*p[10]*p[14]*p[19] + 2*p[10]*p[14]*p[28];
- coeff[101] = -4*p[0]*p[7]*p[8]*p[22] + 2*p[0]*p[7]*p[8]*p[31] + 4*p[0]*p[7]*p[10]*p[17] - 2*p[0]*p[7]*p[10]*p[26] - 4*p[0]*p[8]*p[8]*p[20] + 2*p[0]*p[8]*p[8]*p[29] + 4*p[0]*p[8]*p[9]*p[17] - 2*p[0]*p[8]*p[9]*p[26] + 4*p[0]*p[9]*p[10]*p[22] - 2*p[0]*p[9]*p[10]*p[31] - 4*p[0]*p[10]*p[10]*p[20] + 2*p[0]*p[10]*p[10]*p[29] + 4*p[0]*p[11]*p[12]*p[22] - 2*p[0]*p[11]*p[12]*p[31] - 4*p[0]*p[11]*p[14]*p[17] + 2*p[0]*p[11]*p[14]*p[26] + 4*p[0]*p[12]*p[12]*p[20] - 2*p[0]*p[12]*p[12]*p[29] - 4*p[0]*p[12]*p[13]*p[17] + 2*p[0]*p[12]*p[13]*p[26] - 4*p[0]*p[13]*p[14]*p[22] + 2*p[0]*p[13]*p[14]*p[31] + 4*p[0]*p[14]*p[14]*p[20] - 2*p[0]*p[14]*p[14]*p[29] + 2*p[7]*p[11]*p[20] - 2*p[7]*p[11]*p[29] - 2*p[7]*p[12]*p[22] + 2*p[7]*p[12]*p[31] + 2*p[7]*p[14]*p[17] - 2*p[7]*p[14]*p[26] - 2*p[8]*p[11]*p[22] + 2*p[8]*p[11]*p[31] - 2*p[8]*p[12]*p[20] + 2*p[8]*p[12]*p[29] + 2*p[8]*p[13]*p[17] - 2*p[8]*p[13]*p[26] + 2*p[9]*p[12]*p[17] - 2*p[9]*p[12]*p[26] + 2*p[9]*p[13]*p[20] - 2*p[9]*p[13]*p[29] + 2*p[9]*p[14]*p[22] - 2*p[9]*p[14]*p[31] + 2*p[10]*p[11]*p[17] - 2*p[10]*p[11]*p[26] + 2*p[10]*p[13]*p[22] - 2*p[10]*p[13]*p[31] - 2*p[10]*p[14]*p[20] + 2*p[10]*p[14]*p[29];
- coeff[102] = -2*p[0]*p[7]*p[10]*p[15] - 2*p[0]*p[8]*p[9]*p[15] + 2*p[0]*p[11]*p[14]*p[15] + 2*p[0]*p[12]*p[13]*p[15] - 2*p[7]*p[14]*p[15] + 2*p[7]*p[14]*p[24] - 2*p[8]*p[13]*p[15] + 2*p[8]*p[13]*p[24] - 2*p[9]*p[12]*p[15] + 2*p[9]*p[12]*p[24] - 2*p[10]*p[11]*p[15] + 2*p[10]*p[11]*p[24];
- coeff[103] = -2*p[0]*p[7]*p[10]*p[16] + 2*p[0]*p[8]*p[8]*p[19] - 2*p[0]*p[8]*p[9]*p[16] + 2*p[0]*p[10]*p[10]*p[19] + 2*p[0]*p[11]*p[14]*p[16] - 2*p[0]*p[12]*p[12]*p[19] + 2*p[0]*p[12]*p[13]*p[16] - 2*p[0]*p[14]*p[14]*p[19] - 2*p[7]*p[11]*p[19] + 2*p[7]*p[11]*p[28] - 2*p[7]*p[14]*p[16] + 2*p[7]*p[14]*p[25] + 2*p[8]*p[12]*p[19] - 2*p[8]*p[12]*p[28] - 2*p[8]*p[13]*p[16] + 2*p[8]*p[13]*p[25] - 2*p[9]*p[12]*p[16] + 2*p[9]*p[12]*p[25] - 2*p[9]*p[13]*p[19] + 2*p[9]*p[13]*p[28] - 2*p[10]*p[11]*p[16] + 2*p[10]*p[11]*p[25] + 2*p[10]*p[14]*p[19] - 2*p[10]*p[14]*p[28];
- coeff[104] = 2*p[0]*p[7]*p[8]*p[22] - 2*p[0]*p[7]*p[10]*p[17] + 2*p[0]*p[8]*p[8]*p[20] - 2*p[0]*p[8]*p[9]*p[17] - 2*p[0]*p[9]*p[10]*p[22] + 2*p[0]*p[10]*p[10]*p[20] - 2*p[0]*p[11]*p[12]*p[22] + 2*p[0]*p[11]*p[14]*p[17] - 2*p[0]*p[12]*p[12]*p[20] + 2*p[0]*p[12]*p[13]*p[17] + 2*p[0]*p[13]*p[14]*p[22] - 2*p[0]*p[14]*p[14]*p[20] - 2*p[7]*p[11]*p[20] + 2*p[7]*p[11]*p[29] + 2*p[7]*p[12]*p[22] - 2*p[7]*p[12]*p[31] - 2*p[7]*p[14]*p[17] + 2*p[7]*p[14]*p[26] + 2*p[8]*p[11]*p[22] - 2*p[8]*p[11]*p[31] + 2*p[8]*p[12]*p[20] - 2*p[8]*p[12]*p[29] - 2*p[8]*p[13]*p[17] + 2*p[8]*p[13]*p[26] - 2*p[9]*p[12]*p[17] + 2*p[9]*p[12]*p[26] - 2*p[9]*p[13]*p[20] + 2*p[9]*p[13]*p[29] - 2*p[9]*p[14]*p[22] + 2*p[9]*p[14]*p[31] - 2*p[10]*p[11]*p[17] + 2*p[10]*p[11]*p[26] - 2*p[10]*p[13]*p[22] + 2*p[10]*p[13]*p[31] + 2*p[10]*p[14]*p[20] - 2*p[10]*p[14]*p[29];
- coeff[105] = 0;
- coeff[106] = 2*(-p[7]*p[10]*p[15] + p[7]*p[10]*p[24] - p[8]*p[9]*p[15] + p[8]*p[9]*p[24] + p[11]*p[14]*p[15] - p[11]*p[14]*p[24] + p[12]*p[13]*p[15] - p[12]*p[13]*p[24])*p[0];
- coeff[107] = 2*(-p[7]*p[10]*p[16] + p[7]*p[10]*p[25] + p[8]*p[8]*p[19] - p[8]*p[8]*p[28] - p[8]*p[9]*p[16] + p[8]*p[9]*p[25] + p[10]*p[10]*p[19] - p[10]*p[10]*p[28] + p[11]*p[14]*p[16] - p[11]*p[14]*p[25] - p[12]*p[12]*p[19] + p[12]*p[12]*p[28] + p[12]*p[13]*p[16] - p[12]*p[13]*p[25] - p[14]*p[14]*p[19] + p[14]*p[14]*p[28])*p[0];
- coeff[108] = 2*(p[7]*p[8]*p[22] - p[7]*p[8]*p[31] - p[7]*p[10]*p[17] + p[7]*p[10]*p[26] + p[8]*p[8]*p[20] - p[8]*p[8]*p[29] - p[8]*p[9]*p[17] + p[8]*p[9]*p[26] - p[9]*p[10]*p[22] + p[9]*p[10]*p[31] + p[10]*p[10]*p[20] - p[10]*p[10]*p[29] - p[11]*p[12]*p[22] + p[11]*p[12]*p[31] + p[11]*p[14]*p[17] - p[11]*p[14]*p[26] - p[12]*p[12]*p[20] + p[12]*p[12]*p[29] + p[12]*p[13]*p[17] - p[12]*p[13]*p[26] + p[13]*p[14]*p[22] - p[13]*p[14]*p[31] - p[14]*p[14]*p[20] + p[14]*p[14]*p[29])*p[0];
- coeff[109] = 2*(p[7]*p[10]*p[15] - p[7]*p[10]*p[24] + p[8]*p[9]*p[15] - p[8]*p[9]*p[24] - p[11]*p[14]*p[15] + p[11]*p[14]*p[24] - p[12]*p[13]*p[15] + p[12]*p[13]*p[24])*p[0];
- coeff[110] = 2*(p[7]*p[10]*p[16] - p[7]*p[10]*p[25] - p[8]*p[8]*p[19] + p[8]*p[8]*p[28] + p[8]*p[9]*p[16] - p[8]*p[9]*p[25] - p[10]*p[10]*p[19] + p[10]*p[10]*p[28] - p[11]*p[14]*p[16] + p[11]*p[14]*p[25] + p[12]*p[12]*p[19] - p[12]*p[12]*p[28] - p[12]*p[13]*p[16] + p[12]*p[13]*p[25] + p[14]*p[14]*p[19] - p[14]*p[14]*p[28])*p[0];
- coeff[111] = 2*(-p[7]*p[8]*p[22] + p[7]*p[8]*p[31] + p[7]*p[10]*p[17] - p[7]*p[10]*p[26] - p[8]*p[8]*p[20] + p[8]*p[8]*p[29] + p[8]*p[9]*p[17] - p[8]*p[9]*p[26] + p[9]*p[10]*p[22] - p[9]*p[10]*p[31] - p[10]*p[10]*p[20] + p[10]*p[10]*p[29] + p[11]*p[12]*p[22] - p[11]*p[12]*p[31] - p[11]*p[14]*p[17] + p[11]*p[14]*p[26] + p[12]*p[12]*p[20] - p[12]*p[12]*p[29] - p[12]*p[13]*p[17] + p[12]*p[13]*p[26] - p[13]*p[14]*p[22] + p[13]*p[14]*p[31] + p[14]*p[14]*p[20] - p[14]*p[14]*p[29])*p[0];
- coeff[112] = -p[3] + p[6] - p[7]*p[8]*p[21] + p[7]*p[8]*p[30] + p[7]*p[9]*p[18] - p[7]*p[9]*p[27] + p[8]*p[8]*p[23] - p[8]*p[8]*p[32] - p[8]*p[10]*p[18] + p[8]*p[10]*p[27] + p[9]*p[9]*p[23] - p[9]*p[9]*p[32] - p[9]*p[10]*p[21] + p[9]*p[10]*p[30] - p[11]*p[12]*p[21] + p[11]*p[12]*p[30] + p[11]*p[13]*p[18] - p[11]*p[13]*p[27] + p[12]*p[12]*p[23] - p[12]*p[12]*p[32] - p[12]*p[14]*p[18] + p[12]*p[14]*p[27] + p[13]*p[13]*p[23] - p[13]*p[13]*p[32] - p[13]*p[14]*p[21] + p[13]*p[14]*p[30] - p[23] + p[32];
- coeff[113] = 2*p[7]*p[9]*p[15] - p[7]*p[9]*p[24] - 2*p[8]*p[10]*p[15] + p[8]*p[10]*p[24] + 2*p[11]*p[13]*p[15] - p[11]*p[13]*p[24] - 2*p[12]*p[14]*p[15] + p[12]*p[14]*p[24];
- coeff[114] = -2*p[7]*p[8]*p[19] + p[7]*p[8]*p[28] + 2*p[7]*p[9]*p[16] - p[7]*p[9]*p[25] - 2*p[8]*p[10]*p[16] + p[8]*p[10]*p[25] - 2*p[9]*p[10]*p[19] + p[9]*p[10]*p[28] - 2*p[11]*p[12]*p[19] + p[11]*p[12]*p[28] + 2*p[11]*p[13]*p[16] - p[11]*p[13]*p[25] - 2*p[12]*p[14]*p[16] + p[12]*p[14]*p[25] - 2*p[13]*p[14]*p[19] + p[13]*p[14]*p[28];
- coeff[115] = -2*p[7]*p[8]*p[20] + p[7]*p[8]*p[29] + 2*p[7]*p[9]*p[17] - p[7]*p[9]*p[26] + 2*p[8]*p[8]*p[22] - p[8]*p[8]*p[31] - 2*p[8]*p[10]*p[17] + p[8]*p[10]*p[26] + 2*p[9]*p[9]*p[22] - p[9]*p[9]*p[31] - 2*p[9]*p[10]*p[20] + p[9]*p[10]*p[29] - 2*p[11]*p[12]*p[20] + p[11]*p[12]*p[29] + 2*p[11]*p[13]*p[17] - p[11]*p[13]*p[26] + 2*p[12]*p[12]*p[22] - p[12]*p[12]*p[31] - 2*p[12]*p[14]*p[17] + p[12]*p[14]*p[26] + 2*p[13]*p[13]*p[22] - p[13]*p[13]*p[31] - 2*p[13]*p[14]*p[20] + p[13]*p[14]*p[29] - 2*p[22] + p[31];
- coeff[116] = (-p[7]*p[9] + p[8]*p[10] - p[11]*p[13] + p[12]*p[14])*p[15];
- coeff[117] = p[7]*p[8]*p[19] - p[7]*p[9]*p[16] + p[8]*p[10]*p[16] + p[9]*p[10]*p[19] + p[11]*p[12]*p[19] - p[11]*p[13]*p[16] + p[12]*p[14]*p[16] + p[13]*p[14]*p[19];
- coeff[118] = p[7]*p[8]*p[20] - p[7]*p[9]*p[17] - p[8]*p[8]*p[22] + p[8]*p[10]*p[17] - p[9]*p[9]*p[22] + p[9]*p[10]*p[20] + p[11]*p[12]*p[20] - p[11]*p[13]*p[17] - p[12]*p[12]*p[22] + p[12]*p[14]*p[17] - p[13]*p[13]*p[22] + p[13]*p[14]*p[20] + p[22];
- coeff[119] = 0;
- coeff[120] = -2*p[7]*p[9]*p[15] + 2*p[7]*p[9]*p[24] + 2*p[8]*p[10]*p[15] - 2*p[8]*p[10]*p[24] - 2*p[11]*p[13]*p[15] + 2*p[11]*p[13]*p[24] + 2*p[12]*p[14]*p[15] - 2*p[12]*p[14]*p[24];
- coeff[121] = 2*p[7]*p[8]*p[19] - 2*p[7]*p[8]*p[28] - 2*p[7]*p[9]*p[16] + 2*p[7]*p[9]*p[25] + 2*p[8]*p[10]*p[16] - 2*p[8]*p[10]*p[25] + 2*p[9]*p[10]*p[19] - 2*p[9]*p[10]*p[28] + 2*p[11]*p[12]*p[19] - 2*p[11]*p[12]*p[28] - 2*p[11]*p[13]*p[16] + 2*p[11]*p[13]*p[25] + 2*p[12]*p[14]*p[16] - 2*p[12]*p[14]*p[25] + 2*p[13]*p[14]*p[19] - 2*p[13]*p[14]*p[28];
- coeff[122] = 2*p[7]*p[8]*p[20] - 2*p[7]*p[8]*p[29] - 2*p[7]*p[9]*p[17] + 2*p[7]*p[9]*p[26] - 2*p[8]*p[8]*p[22] + 2*p[8]*p[8]*p[31] + 2*p[8]*p[10]*p[17] - 2*p[8]*p[10]*p[26] - 2*p[9]*p[9]*p[22] + 2*p[9]*p[9]*p[31] + 2*p[9]*p[10]*p[20] - 2*p[9]*p[10]*p[29] + 2*p[11]*p[12]*p[20] - 2*p[11]*p[12]*p[29] - 2*p[11]*p[13]*p[17] + 2*p[11]*p[13]*p[26] - 2*p[12]*p[12]*p[22] + 2*p[12]*p[12]*p[31] + 2*p[12]*p[14]*p[17] - 2*p[12]*p[14]*p[26] - 2*p[13]*p[13]*p[22] + 2*p[13]*p[13]*p[31] + 2*p[13]*p[14]*p[20] - 2*p[13]*p[14]*p[29] + 2*p[22] - 2*p[31];
- coeff[123] = 2*p[7]*p[9]*p[15] - 2*p[7]*p[9]*p[24] - 2*p[8]*p[10]*p[15] + 2*p[8]*p[10]*p[24] + 2*p[11]*p[13]*p[15] - 2*p[11]*p[13]*p[24] - 2*p[12]*p[14]*p[15] + 2*p[12]*p[14]*p[24];
- coeff[124] = -2*p[7]*p[8]*p[19] + 2*p[7]*p[8]*p[28] + 2*p[7]*p[9]*p[16] - 2*p[7]*p[9]*p[25] - 2*p[8]*p[10]*p[16] + 2*p[8]*p[10]*p[25] - 2*p[9]*p[10]*p[19] + 2*p[9]*p[10]*p[28] - 2*p[11]*p[12]*p[19] + 2*p[11]*p[12]*p[28] + 2*p[11]*p[13]*p[16] - 2*p[11]*p[13]*p[25] - 2*p[12]*p[14]*p[16] + 2*p[12]*p[14]*p[25] - 2*p[13]*p[14]*p[19] + 2*p[13]*p[14]*p[28];
- coeff[125] = -2*p[7]*p[8]*p[20] + 2*p[7]*p[8]*p[29] + 2*p[7]*p[9]*p[17] - 2*p[7]*p[9]*p[26] + 2*p[8]*p[8]*p[22] - 2*p[8]*p[8]*p[31] - 2*p[8]*p[10]*p[17] + 2*p[8]*p[10]*p[26] + 2*p[9]*p[9]*p[22] - 2*p[9]*p[9]*p[31] - 2*p[9]*p[10]*p[20] + 2*p[9]*p[10]*p[29] - 2*p[11]*p[12]*p[20] + 2*p[11]*p[12]*p[29] + 2*p[11]*p[13]*p[17] - 2*p[11]*p[13]*p[26] + 2*p[12]*p[12]*p[22] - 2*p[12]*p[12]*p[31] - 2*p[12]*p[14]*p[17] + 2*p[12]*p[14]*p[26] + 2*p[13]*p[13]*p[22] - 2*p[13]*p[13]*p[31] - 2*p[13]*p[14]*p[20] + 2*p[13]*p[14]*p[29] - 2*p[22] + 2*p[31];
- coeff[126] = 2*p[0]*p[7]*p[11]*p[23] + 2*p[0]*p[7]*p[12]*p[21] - 2*p[0]*p[7]*p[13]*p[18] + 2*p[0]*p[8]*p[11]*p[21] - 2*p[0]*p[8]*p[12]*p[23] + 2*p[0]*p[8]*p[14]*p[18] - 2*p[0]*p[9]*p[11]*p[18] - 2*p[0]*p[9]*p[13]*p[23] + 2*p[0]*p[9]*p[14]*p[21] + 2*p[0]*p[10]*p[12]*p[18] + 2*p[0]*p[10]*p[13]*p[21] + 2*p[0]*p[10]*p[14]*p[23] - p[7]*p[8]*p[21] + p[7]*p[8]*p[30] + p[7]*p[9]*p[18] - p[7]*p[9]*p[27] + p[8]*p[8]*p[23] - p[8]*p[8]*p[32] - p[8]*p[10]*p[18] + p[8]*p[10]*p[27] + p[9]*p[9]*p[23] - p[9]*p[9]*p[32] - p[9]*p[10]*p[21] + p[9]*p[10]*p[30] + p[11]*p[12]*p[21] - p[11]*p[12]*p[30] - p[11]*p[13]*p[18] + p[11]*p[13]*p[27] - p[12]*p[12]*p[23] + p[12]*p[12]*p[32] + p[12]*p[14]*p[18] - p[12]*p[14]*p[27] - p[13]*p[13]*p[23] + p[13]*p[13]*p[32] + p[13]*p[14]*p[21] - p[13]*p[14]*p[30];
- coeff[127] = -2*p[0]*p[7]*p[13]*p[15] + 2*p[0]*p[8]*p[14]*p[15] - 2*p[0]*p[9]*p[11]*p[15] + 2*p[0]*p[10]*p[12]*p[15] + 2*p[7]*p[9]*p[15] - p[7]*p[9]*p[24] - 2*p[8]*p[10]*p[15] + p[8]*p[10]*p[24] - 2*p[11]*p[13]*p[15] + p[11]*p[13]*p[24] + 2*p[12]*p[14]*p[15] - p[12]*p[14]*p[24];
- coeff[128] = 2*p[0]*p[7]*p[12]*p[19] - 2*p[0]*p[7]*p[13]*p[16] + 2*p[0]*p[8]*p[11]*p[19] + 2*p[0]*p[8]*p[14]*p[16] - 2*p[0]*p[9]*p[11]*p[16] + 2*p[0]*p[9]*p[14]*p[19] + 2*p[0]*p[10]*p[12]*p[16] + 2*p[0]*p[10]*p[13]*p[19] - 2*p[7]*p[8]*p[19] + p[7]*p[8]*p[28] + 2*p[7]*p[9]*p[16] - p[7]*p[9]*p[25] - 2*p[8]*p[10]*p[16] + p[8]*p[10]*p[25] - 2*p[9]*p[10]*p[19] + p[9]*p[10]*p[28] + 2*p[11]*p[12]*p[19] - p[11]*p[12]*p[28] - 2*p[11]*p[13]*p[16] + p[11]*p[13]*p[25] + 2*p[12]*p[14]*p[16] - p[12]*p[14]*p[25] + 2*p[13]*p[14]*p[19] - p[13]*p[14]*p[28];
- coeff[129] = 2*p[0]*p[7]*p[11]*p[22] + 2*p[0]*p[7]*p[12]*p[20] - 2*p[0]*p[7]*p[13]*p[17] + 2*p[0]*p[8]*p[11]*p[20] - 2*p[0]*p[8]*p[12]*p[22] + 2*p[0]*p[8]*p[14]*p[17] - 2*p[0]*p[9]*p[11]*p[17] - 2*p[0]*p[9]*p[13]*p[22] + 2*p[0]*p[9]*p[14]*p[20] + 2*p[0]*p[10]*p[12]*p[17] + 2*p[0]*p[10]*p[13]*p[20] + 2*p[0]*p[10]*p[14]*p[22] - 2*p[7]*p[8]*p[20] + p[7]*p[8]*p[29] + 2*p[7]*p[9]*p[17] - p[7]*p[9]*p[26] + 2*p[8]*p[8]*p[22] - p[8]*p[8]*p[31] - 2*p[8]*p[10]*p[17] + p[8]*p[10]*p[26] + 2*p[9]*p[9]*p[22] - p[9]*p[9]*p[31] - 2*p[9]*p[10]*p[20] + p[9]*p[10]*p[29] + 2*p[11]*p[12]*p[20] - p[11]*p[12]*p[29] - 2*p[11]*p[13]*p[17] + p[11]*p[13]*p[26] - 2*p[12]*p[12]*p[22] + p[12]*p[12]*p[31] + 2*p[12]*p[14]*p[17] - p[12]*p[14]*p[26] - 2*p[13]*p[13]*p[22] + p[13]*p[13]*p[31] + 2*p[13]*p[14]*p[20] - p[13]*p[14]*p[29];
- coeff[130] = (-p[7]*p[9] + p[8]*p[10] + p[11]*p[13] - p[12]*p[14])*p[15];
- coeff[131] = p[7]*p[8]*p[19] - p[7]*p[9]*p[16] + p[8]*p[10]*p[16] + p[9]*p[10]*p[19] - p[11]*p[12]*p[19] + p[11]*p[13]*p[16] - p[12]*p[14]*p[16] - p[13]*p[14]*p[19];
- coeff[132] = p[7]*p[8]*p[20] - p[7]*p[9]*p[17] - p[8]*p[8]*p[22] + p[8]*p[10]*p[17] - p[9]*p[9]*p[22] + p[9]*p[10]*p[20] - p[11]*p[12]*p[20] + p[11]*p[13]*p[17] + p[12]*p[12]*p[22] - p[12]*p[14]*p[17] + p[13]*p[13]*p[22] - p[13]*p[14]*p[20];
- coeff[133] = 2*(-p[7]*p[11]*p[23] + p[7]*p[11]*p[32] - p[7]*p[12]*p[21] + p[7]*p[12]*p[30] + p[7]*p[13]*p[18] - p[7]*p[13]*p[27] - p[8]*p[11]*p[21] + p[8]*p[11]*p[30] + p[8]*p[12]*p[23] - p[8]*p[12]*p[32] - p[8]*p[14]*p[18] + p[8]*p[14]*p[27] + p[9]*p[11]*p[18] - p[9]*p[11]*p[27] + p[9]*p[13]*p[23] - p[9]*p[13]*p[32] - p[9]*p[14]*p[21] + p[9]*p[14]*p[30] - p[10]*p[12]*p[18] + p[10]*p[12]*p[27] - p[10]*p[13]*p[21] + p[10]*p[13]*p[30] - p[10]*p[14]*p[23] + p[10]*p[14]*p[32])*p[0];
- coeff[134] = 4*p[0]*p[7]*p[13]*p[15] - 2*p[0]*p[7]*p[13]*p[24] - 4*p[0]*p[8]*p[14]*p[15] + 2*p[0]*p[8]*p[14]*p[24] + 4*p[0]*p[9]*p[11]*p[15] - 2*p[0]*p[9]*p[11]*p[24] - 4*p[0]*p[10]*p[12]*p[15] + 2*p[0]*p[10]*p[12]*p[24] - 2*p[7]*p[9]*p[15] + 2*p[7]*p[9]*p[24] + 2*p[8]*p[10]*p[15] - 2*p[8]*p[10]*p[24] + 2*p[11]*p[13]*p[15] - 2*p[11]*p[13]*p[24] - 2*p[12]*p[14]*p[15] + 2*p[12]*p[14]*p[24];
- coeff[135] = -4*p[0]*p[7]*p[12]*p[19] + 2*p[0]*p[7]*p[12]*p[28] + 4*p[0]*p[7]*p[13]*p[16] - 2*p[0]*p[7]*p[13]*p[25] - 4*p[0]*p[8]*p[11]*p[19] + 2*p[0]*p[8]*p[11]*p[28] - 4*p[0]*p[8]*p[14]*p[16] + 2*p[0]*p[8]*p[14]*p[25] + 4*p[0]*p[9]*p[11]*p[16] - 2*p[0]*p[9]*p[11]*p[25] - 4*p[0]*p[9]*p[14]*p[19] + 2*p[0]*p[9]*p[14]*p[28] - 4*p[0]*p[10]*p[12]*p[16] + 2*p[0]*p[10]*p[12]*p[25] - 4*p[0]*p[10]*p[13]*p[19] + 2*p[0]*p[10]*p[13]*p[28] + 2*p[7]*p[8]*p[19] - 2*p[7]*p[8]*p[28] - 2*p[7]*p[9]*p[16] + 2*p[7]*p[9]*p[25] + 2*p[8]*p[10]*p[16] - 2*p[8]*p[10]*p[25] + 2*p[9]*p[10]*p[19] - 2*p[9]*p[10]*p[28] - 2*p[11]*p[12]*p[19] + 2*p[11]*p[12]*p[28] + 2*p[11]*p[13]*p[16] - 2*p[11]*p[13]*p[25] - 2*p[12]*p[14]*p[16] + 2*p[12]*p[14]*p[25] - 2*p[13]*p[14]*p[19] + 2*p[13]*p[14]*p[28];
- coeff[136] = -4*p[0]*p[7]*p[11]*p[22] + 2*p[0]*p[7]*p[11]*p[31] - 4*p[0]*p[7]*p[12]*p[20] + 2*p[0]*p[7]*p[12]*p[29] + 4*p[0]*p[7]*p[13]*p[17] - 2*p[0]*p[7]*p[13]*p[26] - 4*p[0]*p[8]*p[11]*p[20] + 2*p[0]*p[8]*p[11]*p[29] + 4*p[0]*p[8]*p[12]*p[22] - 2*p[0]*p[8]*p[12]*p[31] - 4*p[0]*p[8]*p[14]*p[17] + 2*p[0]*p[8]*p[14]*p[26] + 4*p[0]*p[9]*p[11]*p[17] - 2*p[0]*p[9]*p[11]*p[26] + 4*p[0]*p[9]*p[13]*p[22] - 2*p[0]*p[9]*p[13]*p[31] - 4*p[0]*p[9]*p[14]*p[20] + 2*p[0]*p[9]*p[14]*p[29] - 4*p[0]*p[10]*p[12]*p[17] + 2*p[0]*p[10]*p[12]*p[26] - 4*p[0]*p[10]*p[13]*p[20] + 2*p[0]*p[10]*p[13]*p[29] - 4*p[0]*p[10]*p[14]*p[22] + 2*p[0]*p[10]*p[14]*p[31] + 2*p[7]*p[8]*p[20] - 2*p[7]*p[8]*p[29] - 2*p[7]*p[9]*p[17] + 2*p[7]*p[9]*p[26] - 2*p[8]*p[8]*p[22] + 2*p[8]*p[8]*p[31] + 2*p[8]*p[10]*p[17] - 2*p[8]*p[10]*p[26] - 2*p[9]*p[9]*p[22] + 2*p[9]*p[9]*p[31] + 2*p[9]*p[10]*p[20] - 2*p[9]*p[10]*p[29] - 2*p[11]*p[12]*p[20] + 2*p[11]*p[12]*p[29] + 2*p[11]*p[13]*p[17] - 2*p[11]*p[13]*p[26] + 2*p[12]*p[12]*p[22] - 2*p[12]*p[12]*p[31] - 2*p[12]*p[14]*p[17] + 2*p[12]*p[14]*p[26] + 2*p[13]*p[13]*p[22] - 2*p[13]*p[13]*p[31] - 2*p[13]*p[14]*p[20] + 2*p[13]*p[14]*p[29];
- coeff[137] = -2*p[0]*p[7]*p[13]*p[15] + 2*p[0]*p[8]*p[14]*p[15] - 2*p[0]*p[9]*p[11]*p[15] + 2*p[0]*p[10]*p[12]*p[15] + 2*p[7]*p[9]*p[15] - 2*p[7]*p[9]*p[24] - 2*p[8]*p[10]*p[15] + 2*p[8]*p[10]*p[24] - 2*p[11]*p[13]*p[15] + 2*p[11]*p[13]*p[24] + 2*p[12]*p[14]*p[15] - 2*p[12]*p[14]*p[24];
- coeff[138] = 2*p[0]*p[7]*p[12]*p[19] - 2*p[0]*p[7]*p[13]*p[16] + 2*p[0]*p[8]*p[11]*p[19] + 2*p[0]*p[8]*p[14]*p[16] - 2*p[0]*p[9]*p[11]*p[16] + 2*p[0]*p[9]*p[14]*p[19] + 2*p[0]*p[10]*p[12]*p[16] + 2*p[0]*p[10]*p[13]*p[19] - 2*p[7]*p[8]*p[19] + 2*p[7]*p[8]*p[28] + 2*p[7]*p[9]*p[16] - 2*p[7]*p[9]*p[25] - 2*p[8]*p[10]*p[16] + 2*p[8]*p[10]*p[25] - 2*p[9]*p[10]*p[19] + 2*p[9]*p[10]*p[28] + 2*p[11]*p[12]*p[19] - 2*p[11]*p[12]*p[28] - 2*p[11]*p[13]*p[16] + 2*p[11]*p[13]*p[25] + 2*p[12]*p[14]*p[16] - 2*p[12]*p[14]*p[25] + 2*p[13]*p[14]*p[19] - 2*p[13]*p[14]*p[28];
- coeff[139] = 2*p[0]*p[7]*p[11]*p[22] + 2*p[0]*p[7]*p[12]*p[20] - 2*p[0]*p[7]*p[13]*p[17] + 2*p[0]*p[8]*p[11]*p[20] - 2*p[0]*p[8]*p[12]*p[22] + 2*p[0]*p[8]*p[14]*p[17] - 2*p[0]*p[9]*p[11]*p[17] - 2*p[0]*p[9]*p[13]*p[22] + 2*p[0]*p[9]*p[14]*p[20] + 2*p[0]*p[10]*p[12]*p[17] + 2*p[0]*p[10]*p[13]*p[20] + 2*p[0]*p[10]*p[14]*p[22] - 2*p[7]*p[8]*p[20] + 2*p[7]*p[8]*p[29] + 2*p[7]*p[9]*p[17] - 2*p[7]*p[9]*p[26] + 2*p[8]*p[8]*p[22] - 2*p[8]*p[8]*p[31] - 2*p[8]*p[10]*p[17] + 2*p[8]*p[10]*p[26] + 2*p[9]*p[9]*p[22] - 2*p[9]*p[9]*p[31] - 2*p[9]*p[10]*p[20] + 2*p[9]*p[10]*p[29] + 2*p[11]*p[12]*p[20] - 2*p[11]*p[12]*p[29] - 2*p[11]*p[13]*p[17] + 2*p[11]*p[13]*p[26] - 2*p[12]*p[12]*p[22] + 2*p[12]*p[12]*p[31] + 2*p[12]*p[14]*p[17] - 2*p[12]*p[14]*p[26] - 2*p[13]*p[13]*p[22] + 2*p[13]*p[13]*p[31] + 2*p[13]*p[14]*p[20] - 2*p[13]*p[14]*p[29];
- coeff[140] = 0;
- coeff[141] = 2*(-p[7]*p[13]*p[15] + p[7]*p[13]*p[24] + p[8]*p[14]*p[15] - p[8]*p[14]*p[24] - p[9]*p[11]*p[15] + p[9]*p[11]*p[24] + p[10]*p[12]*p[15] - p[10]*p[12]*p[24])*p[0];
- coeff[142] = 2*(p[7]*p[12]*p[19] - p[7]*p[12]*p[28] - p[7]*p[13]*p[16] + p[7]*p[13]*p[25] + p[8]*p[11]*p[19] - p[8]*p[11]*p[28] + p[8]*p[14]*p[16] - p[8]*p[14]*p[25] - p[9]*p[11]*p[16] + p[9]*p[11]*p[25] + p[9]*p[14]*p[19] - p[9]*p[14]*p[28] + p[10]*p[12]*p[16] - p[10]*p[12]*p[25] + p[10]*p[13]*p[19] - p[10]*p[13]*p[28])*p[0];
- coeff[143] = 2*(p[7]*p[11]*p[22] - p[7]*p[11]*p[31] + p[7]*p[12]*p[20] - p[7]*p[12]*p[29] - p[7]*p[13]*p[17] + p[7]*p[13]*p[26] + p[8]*p[11]*p[20] - p[8]*p[11]*p[29] - p[8]*p[12]*p[22] + p[8]*p[12]*p[31] + p[8]*p[14]*p[17] - p[8]*p[14]*p[26] - p[9]*p[11]*p[17] + p[9]*p[11]*p[26] - p[9]*p[13]*p[22] + p[9]*p[13]*p[31] + p[9]*p[14]*p[20] - p[9]*p[14]*p[29] + p[10]*p[12]*p[17] - p[10]*p[12]*p[26] + p[10]*p[13]*p[20] - p[10]*p[13]*p[29] + p[10]*p[14]*p[22] - p[10]*p[14]*p[31])*p[0];
- coeff[144] = 2*(p[7]*p[13]*p[15] - p[7]*p[13]*p[24] - p[8]*p[14]*p[15] + p[8]*p[14]*p[24] + p[9]*p[11]*p[15] - p[9]*p[11]*p[24] - p[10]*p[12]*p[15] + p[10]*p[12]*p[24])*p[0];
- coeff[145] = 2*(-p[7]*p[12]*p[19] + p[7]*p[12]*p[28] + p[7]*p[13]*p[16] - p[7]*p[13]*p[25] - p[8]*p[11]*p[19] + p[8]*p[11]*p[28] - p[8]*p[14]*p[16] + p[8]*p[14]*p[25] + p[9]*p[11]*p[16] - p[9]*p[11]*p[25] - p[9]*p[14]*p[19] + p[9]*p[14]*p[28] - p[10]*p[12]*p[16] + p[10]*p[12]*p[25] - p[10]*p[13]*p[19] + p[10]*p[13]*p[28])*p[0];
- coeff[146] = 2*(-p[7]*p[11]*p[22] + p[7]*p[11]*p[31] - p[7]*p[12]*p[20] + p[7]*p[12]*p[29] + p[7]*p[13]*p[17] - p[7]*p[13]*p[26] - p[8]*p[11]*p[20] + p[8]*p[11]*p[29] + p[8]*p[12]*p[22] - p[8]*p[12]*p[31] - p[8]*p[14]*p[17] + p[8]*p[14]*p[26] + p[9]*p[11]*p[17] - p[9]*p[11]*p[26] + p[9]*p[13]*p[22] - p[9]*p[13]*p[31] - p[9]*p[14]*p[20] + p[9]*p[14]*p[29] - p[10]*p[12]*p[17] + p[10]*p[12]*p[26] - p[10]*p[13]*p[20] + p[10]*p[13]*p[29] - p[10]*p[14]*p[22] + p[10]*p[14]*p[31])*p[0];
- coeff[147] = -2*p[0]*p[7]*p[8]*p[21] + 2*p[0]*p[7]*p[9]*p[18] + 2*p[0]*p[8]*p[8]*p[23] - 2*p[0]*p[8]*p[10]*p[18] + 2*p[0]*p[9]*p[9]*p[23] - 2*p[0]*p[9]*p[10]*p[21] + 2*p[0]*p[11]*p[12]*p[21] - 2*p[0]*p[11]*p[13]*p[18] - 2*p[0]*p[12]*p[12]*p[23] + 2*p[0]*p[12]*p[14]*p[18] - 2*p[0]*p[13]*p[13]*p[23] + 2*p[0]*p[13]*p[14]*p[21] - p[7]*p[11]*p[23] + p[7]*p[11]*p[32] - p[7]*p[12]*p[21] + p[7]*p[12]*p[30] + p[7]*p[13]*p[18] - p[7]*p[13]*p[27] - p[8]*p[11]*p[21] + p[8]*p[11]*p[30] + p[8]*p[12]*p[23] - p[8]*p[12]*p[32] - p[8]*p[14]*p[18] + p[8]*p[14]*p[27] + p[9]*p[11]*p[18] - p[9]*p[11]*p[27] + p[9]*p[13]*p[23] - p[9]*p[13]*p[32] - p[9]*p[14]*p[21] + p[9]*p[14]*p[30] - p[10]*p[12]*p[18] + p[10]*p[12]*p[27] - p[10]*p[13]*p[21] + p[10]*p[13]*p[30] - p[10]*p[14]*p[23] + p[10]*p[14]*p[32];
- coeff[148] = 2*p[0]*p[7]*p[9]*p[15] - 2*p[0]*p[8]*p[10]*p[15] - 2*p[0]*p[11]*p[13]*p[15] + 2*p[0]*p[12]*p[14]*p[15] + 2*p[7]*p[13]*p[15] - p[7]*p[13]*p[24] - 2*p[8]*p[14]*p[15] + p[8]*p[14]*p[24] + 2*p[9]*p[11]*p[15] - p[9]*p[11]*p[24] - 2*p[10]*p[12]*p[15] + p[10]*p[12]*p[24];
- coeff[149] = -2*p[0]*p[7]*p[8]*p[19] + 2*p[0]*p[7]*p[9]*p[16] - 2*p[0]*p[8]*p[10]*p[16] - 2*p[0]*p[9]*p[10]*p[19] + 2*p[0]*p[11]*p[12]*p[19] - 2*p[0]*p[11]*p[13]*p[16] + 2*p[0]*p[12]*p[14]*p[16] + 2*p[0]*p[13]*p[14]*p[19] - 2*p[7]*p[12]*p[19] + p[7]*p[12]*p[28] + 2*p[7]*p[13]*p[16] - p[7]*p[13]*p[25] - 2*p[8]*p[11]*p[19] + p[8]*p[11]*p[28] - 2*p[8]*p[14]*p[16] + p[8]*p[14]*p[25] + 2*p[9]*p[11]*p[16] - p[9]*p[11]*p[25] - 2*p[9]*p[14]*p[19] + p[9]*p[14]*p[28] - 2*p[10]*p[12]*p[16] + p[10]*p[12]*p[25] - 2*p[10]*p[13]*p[19] + p[10]*p[13]*p[28];
- coeff[150] = -2*p[0]*p[7]*p[8]*p[20] + 2*p[0]*p[7]*p[9]*p[17] + 2*p[0]*p[8]*p[8]*p[22] - 2*p[0]*p[8]*p[10]*p[17] + 2*p[0]*p[9]*p[9]*p[22] - 2*p[0]*p[9]*p[10]*p[20] + 2*p[0]*p[11]*p[12]*p[20] - 2*p[0]*p[11]*p[13]*p[17] - 2*p[0]*p[12]*p[12]*p[22] + 2*p[0]*p[12]*p[14]*p[17] - 2*p[0]*p[13]*p[13]*p[22] + 2*p[0]*p[13]*p[14]*p[20] - 2*p[7]*p[11]*p[22] + p[7]*p[11]*p[31] - 2*p[7]*p[12]*p[20] + p[7]*p[12]*p[29] + 2*p[7]*p[13]*p[17] - p[7]*p[13]*p[26] - 2*p[8]*p[11]*p[20] + p[8]*p[11]*p[29] + 2*p[8]*p[12]*p[22] - p[8]*p[12]*p[31] - 2*p[8]*p[14]*p[17] + p[8]*p[14]*p[26] + 2*p[9]*p[11]*p[17] - p[9]*p[11]*p[26] + 2*p[9]*p[13]*p[22] - p[9]*p[13]*p[31] - 2*p[9]*p[14]*p[20] + p[9]*p[14]*p[29] - 2*p[10]*p[12]*p[17] + p[10]*p[12]*p[26] - 2*p[10]*p[13]*p[20] + p[10]*p[13]*p[29] - 2*p[10]*p[14]*p[22] + p[10]*p[14]*p[31];
- coeff[151] = (-p[7]*p[13] + p[8]*p[14] - p[9]*p[11] + p[10]*p[12])*p[15];
- coeff[152] = p[7]*p[12]*p[19] - p[7]*p[13]*p[16] + p[8]*p[11]*p[19] + p[8]*p[14]*p[16] - p[9]*p[11]*p[16] + p[9]*p[14]*p[19] + p[10]*p[12]*p[16] + p[10]*p[13]*p[19];
- coeff[153] = p[7]*p[11]*p[22] + p[7]*p[12]*p[20] - p[7]*p[13]*p[17] + p[8]*p[11]*p[20] - p[8]*p[12]*p[22] + p[8]*p[14]*p[17] - p[9]*p[11]*p[17] - p[9]*p[13]*p[22] + p[9]*p[14]*p[20] + p[10]*p[12]*p[17] + p[10]*p[13]*p[20] + p[10]*p[14]*p[22];
- coeff[154] = 2*(p[7]*p[8]*p[21] - p[7]*p[8]*p[30] - p[7]*p[9]*p[18] + p[7]*p[9]*p[27] - p[8]*p[8]*p[23] + p[8]*p[8]*p[32] + p[8]*p[10]*p[18] - p[8]*p[10]*p[27] - p[9]*p[9]*p[23] + p[9]*p[9]*p[32] + p[9]*p[10]*p[21] - p[9]*p[10]*p[30] - p[11]*p[12]*p[21] + p[11]*p[12]*p[30] + p[11]*p[13]*p[18] - p[11]*p[13]*p[27] + p[12]*p[12]*p[23] - p[12]*p[12]*p[32] - p[12]*p[14]*p[18] + p[12]*p[14]*p[27] + p[13]*p[13]*p[23] - p[13]*p[13]*p[32] - p[13]*p[14]*p[21] + p[13]*p[14]*p[30])*p[0];
- coeff[155] = -4*p[0]*p[7]*p[9]*p[15] + 2*p[0]*p[7]*p[9]*p[24] + 4*p[0]*p[8]*p[10]*p[15] - 2*p[0]*p[8]*p[10]*p[24] + 4*p[0]*p[11]*p[13]*p[15] - 2*p[0]*p[11]*p[13]*p[24] - 4*p[0]*p[12]*p[14]*p[15] + 2*p[0]*p[12]*p[14]*p[24] - 2*p[7]*p[13]*p[15] + 2*p[7]*p[13]*p[24] + 2*p[8]*p[14]*p[15] - 2*p[8]*p[14]*p[24] - 2*p[9]*p[11]*p[15] + 2*p[9]*p[11]*p[24] + 2*p[10]*p[12]*p[15] - 2*p[10]*p[12]*p[24];
- coeff[156] = 4*p[0]*p[7]*p[8]*p[19] - 2*p[0]*p[7]*p[8]*p[28] - 4*p[0]*p[7]*p[9]*p[16] + 2*p[0]*p[7]*p[9]*p[25] + 4*p[0]*p[8]*p[10]*p[16] - 2*p[0]*p[8]*p[10]*p[25] + 4*p[0]*p[9]*p[10]*p[19] - 2*p[0]*p[9]*p[10]*p[28] - 4*p[0]*p[11]*p[12]*p[19] + 2*p[0]*p[11]*p[12]*p[28] + 4*p[0]*p[11]*p[13]*p[16] - 2*p[0]*p[11]*p[13]*p[25] - 4*p[0]*p[12]*p[14]*p[16] + 2*p[0]*p[12]*p[14]*p[25] - 4*p[0]*p[13]*p[14]*p[19] + 2*p[0]*p[13]*p[14]*p[28] + 2*p[7]*p[12]*p[19] - 2*p[7]*p[12]*p[28] - 2*p[7]*p[13]*p[16] + 2*p[7]*p[13]*p[25] + 2*p[8]*p[11]*p[19] - 2*p[8]*p[11]*p[28] + 2*p[8]*p[14]*p[16] - 2*p[8]*p[14]*p[25] - 2*p[9]*p[11]*p[16] + 2*p[9]*p[11]*p[25] + 2*p[9]*p[14]*p[19] - 2*p[9]*p[14]*p[28] + 2*p[10]*p[12]*p[16] - 2*p[10]*p[12]*p[25] + 2*p[10]*p[13]*p[19] - 2*p[10]*p[13]*p[28];
- coeff[157] = 4*p[0]*p[7]*p[8]*p[20] - 2*p[0]*p[7]*p[8]*p[29] - 4*p[0]*p[7]*p[9]*p[17] + 2*p[0]*p[7]*p[9]*p[26] - 4*p[0]*p[8]*p[8]*p[22] + 2*p[0]*p[8]*p[8]*p[31] + 4*p[0]*p[8]*p[10]*p[17] - 2*p[0]*p[8]*p[10]*p[26] - 4*p[0]*p[9]*p[9]*p[22] + 2*p[0]*p[9]*p[9]*p[31] + 4*p[0]*p[9]*p[10]*p[20] - 2*p[0]*p[9]*p[10]*p[29] - 4*p[0]*p[11]*p[12]*p[20] + 2*p[0]*p[11]*p[12]*p[29] + 4*p[0]*p[11]*p[13]*p[17] - 2*p[0]*p[11]*p[13]*p[26] + 4*p[0]*p[12]*p[12]*p[22] - 2*p[0]*p[12]*p[12]*p[31] - 4*p[0]*p[12]*p[14]*p[17] + 2*p[0]*p[12]*p[14]*p[26] + 4*p[0]*p[13]*p[13]*p[22] - 2*p[0]*p[13]*p[13]*p[31] - 4*p[0]*p[13]*p[14]*p[20] + 2*p[0]*p[13]*p[14]*p[29] + 2*p[7]*p[11]*p[22] - 2*p[7]*p[11]*p[31] + 2*p[7]*p[12]*p[20] - 2*p[7]*p[12]*p[29] - 2*p[7]*p[13]*p[17] + 2*p[7]*p[13]*p[26] + 2*p[8]*p[11]*p[20] - 2*p[8]*p[11]*p[29] - 2*p[8]*p[12]*p[22] + 2*p[8]*p[12]*p[31] + 2*p[8]*p[14]*p[17] - 2*p[8]*p[14]*p[26] - 2*p[9]*p[11]*p[17] + 2*p[9]*p[11]*p[26] - 2*p[9]*p[13]*p[22] + 2*p[9]*p[13]*p[31] + 2*p[9]*p[14]*p[20] - 2*p[9]*p[14]*p[29] + 2*p[10]*p[12]*p[17] - 2*p[10]*p[12]*p[26] + 2*p[10]*p[13]*p[20] - 2*p[10]*p[13]*p[29] + 2*p[10]*p[14]*p[22] - 2*p[10]*p[14]*p[31];
- coeff[158] = 2*p[0]*p[7]*p[9]*p[15] - 2*p[0]*p[8]*p[10]*p[15] - 2*p[0]*p[11]*p[13]*p[15] + 2*p[0]*p[12]*p[14]*p[15] + 2*p[7]*p[13]*p[15] - 2*p[7]*p[13]*p[24] - 2*p[8]*p[14]*p[15] + 2*p[8]*p[14]*p[24] + 2*p[9]*p[11]*p[15] - 2*p[9]*p[11]*p[24] - 2*p[10]*p[12]*p[15] + 2*p[10]*p[12]*p[24];
- coeff[159] = -2*p[0]*p[7]*p[8]*p[19] + 2*p[0]*p[7]*p[9]*p[16] - 2*p[0]*p[8]*p[10]*p[16] - 2*p[0]*p[9]*p[10]*p[19] + 2*p[0]*p[11]*p[12]*p[19] - 2*p[0]*p[11]*p[13]*p[16] + 2*p[0]*p[12]*p[14]*p[16] + 2*p[0]*p[13]*p[14]*p[19] - 2*p[7]*p[12]*p[19] + 2*p[7]*p[12]*p[28] + 2*p[7]*p[13]*p[16] - 2*p[7]*p[13]*p[25] - 2*p[8]*p[11]*p[19] + 2*p[8]*p[11]*p[28] - 2*p[8]*p[14]*p[16] + 2*p[8]*p[14]*p[25] + 2*p[9]*p[11]*p[16] - 2*p[9]*p[11]*p[25] - 2*p[9]*p[14]*p[19] + 2*p[9]*p[14]*p[28] - 2*p[10]*p[12]*p[16] + 2*p[10]*p[12]*p[25] - 2*p[10]*p[13]*p[19] + 2*p[10]*p[13]*p[28];
- coeff[160] = -2*p[0]*p[7]*p[8]*p[20] + 2*p[0]*p[7]*p[9]*p[17] + 2*p[0]*p[8]*p[8]*p[22] - 2*p[0]*p[8]*p[10]*p[17] + 2*p[0]*p[9]*p[9]*p[22] - 2*p[0]*p[9]*p[10]*p[20] + 2*p[0]*p[11]*p[12]*p[20] - 2*p[0]*p[11]*p[13]*p[17] - 2*p[0]*p[12]*p[12]*p[22] + 2*p[0]*p[12]*p[14]*p[17] - 2*p[0]*p[13]*p[13]*p[22] + 2*p[0]*p[13]*p[14]*p[20] - 2*p[7]*p[11]*p[22] + 2*p[7]*p[11]*p[31] - 2*p[7]*p[12]*p[20] + 2*p[7]*p[12]*p[29] + 2*p[7]*p[13]*p[17] - 2*p[7]*p[13]*p[26] - 2*p[8]*p[11]*p[20] + 2*p[8]*p[11]*p[29] + 2*p[8]*p[12]*p[22] - 2*p[8]*p[12]*p[31] - 2*p[8]*p[14]*p[17] + 2*p[8]*p[14]*p[26] + 2*p[9]*p[11]*p[17] - 2*p[9]*p[11]*p[26] + 2*p[9]*p[13]*p[22] - 2*p[9]*p[13]*p[31] - 2*p[9]*p[14]*p[20] + 2*p[9]*p[14]*p[29] - 2*p[10]*p[12]*p[17] + 2*p[10]*p[12]*p[26] - 2*p[10]*p[13]*p[20] + 2*p[10]*p[13]*p[29] - 2*p[10]*p[14]*p[22] + 2*p[10]*p[14]*p[31];
- coeff[161] = 0;
- coeff[162] = 2*(p[7]*p[9]*p[15] - p[7]*p[9]*p[24] - p[8]*p[10]*p[15] + p[8]*p[10]*p[24] - p[11]*p[13]*p[15] + p[11]*p[13]*p[24] + p[12]*p[14]*p[15] - p[12]*p[14]*p[24])*p[0];
- coeff[163] = 2*(-p[7]*p[8]*p[19] + p[7]*p[8]*p[28] + p[7]*p[9]*p[16] - p[7]*p[9]*p[25] - p[8]*p[10]*p[16] + p[8]*p[10]*p[25] - p[9]*p[10]*p[19] + p[9]*p[10]*p[28] + p[11]*p[12]*p[19] - p[11]*p[12]*p[28] - p[11]*p[13]*p[16] + p[11]*p[13]*p[25] + p[12]*p[14]*p[16] - p[12]*p[14]*p[25] + p[13]*p[14]*p[19] - p[13]*p[14]*p[28])*p[0];
- coeff[164] = 2*(-p[7]*p[8]*p[20] + p[7]*p[8]*p[29] + p[7]*p[9]*p[17] - p[7]*p[9]*p[26] + p[8]*p[8]*p[22] - p[8]*p[8]*p[31] - p[8]*p[10]*p[17] + p[8]*p[10]*p[26] + p[9]*p[9]*p[22] - p[9]*p[9]*p[31] - p[9]*p[10]*p[20] + p[9]*p[10]*p[29] + p[11]*p[12]*p[20] - p[11]*p[12]*p[29] - p[11]*p[13]*p[17] + p[11]*p[13]*p[26] - p[12]*p[12]*p[22] + p[12]*p[12]*p[31] + p[12]*p[14]*p[17] - p[12]*p[14]*p[26] - p[13]*p[13]*p[22] + p[13]*p[13]*p[31] + p[13]*p[14]*p[20] - p[13]*p[14]*p[29])*p[0];
- coeff[165] = 2*(-p[7]*p[9]*p[15] + p[7]*p[9]*p[24] + p[8]*p[10]*p[15] - p[8]*p[10]*p[24] + p[11]*p[13]*p[15] - p[11]*p[13]*p[24] - p[12]*p[14]*p[15] + p[12]*p[14]*p[24])*p[0];
- coeff[166] = 2*(p[7]*p[8]*p[19] - p[7]*p[8]*p[28] - p[7]*p[9]*p[16] + p[7]*p[9]*p[25] + p[8]*p[10]*p[16] - p[8]*p[10]*p[25] + p[9]*p[10]*p[19] - p[9]*p[10]*p[28] - p[11]*p[12]*p[19] + p[11]*p[12]*p[28] + p[11]*p[13]*p[16] - p[11]*p[13]*p[25] - p[12]*p[14]*p[16] + p[12]*p[14]*p[25] - p[13]*p[14]*p[19] + p[13]*p[14]*p[28])*p[0];
- coeff[167] = 2*(p[7]*p[8]*p[20] - p[7]*p[8]*p[29] - p[7]*p[9]*p[17] + p[7]*p[9]*p[26] - p[8]*p[8]*p[22] + p[8]*p[8]*p[31] + p[8]*p[10]*p[17] - p[8]*p[10]*p[26] - p[9]*p[9]*p[22] + p[9]*p[9]*p[31] + p[9]*p[10]*p[20] - p[9]*p[10]*p[29] - p[11]*p[12]*p[20] + p[11]*p[12]*p[29] + p[11]*p[13]*p[17] - p[11]*p[13]*p[26] + p[12]*p[12]*p[22] - p[12]*p[12]*p[31] - p[12]*p[14]*p[17] + p[12]*p[14]*p[26] + p[13]*p[13]*p[22] - p[13]*p[13]*p[31] - p[13]*p[14]*p[20] + p[13]*p[14]*p[29])*p[0];
-}
-
-} // namespace embree
diff --git a/thirdparty/embree-aarch64/kernels/common/point_query.h b/thirdparty/embree-aarch64/kernels/common/point_query.h
deleted file mode 100644
index 27d158ca3a..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/point_query.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-
-namespace embree
-{
- /* Point query structure for closest point query */
- template<int K>
- struct RTC_ALIGN(16) PointQueryK
- {
- /* Default construction does nothing */
- __forceinline PointQueryK() {}
-
- /* Constructs a ray from origin, direction, and ray segment. Near
- * has to be smaller than far */
- __forceinline PointQueryK(const Vec3vf<K>& p, const vfloat<K>& radius = inf, const vfloat<K>& time = zero)
- : p(p), time(time), radius(radius) {}
-
- /* Returns the size of the ray */
- static __forceinline size_t size() { return K; }
-
- /* Calculates if this is a valid ray that does not cause issues during traversal */
- __forceinline vbool<K> valid() const
- {
- const vbool<K> vx = (abs(p.x) <= vfloat<K>(FLT_LARGE));
- const vbool<K> vy = (abs(p.y) <= vfloat<K>(FLT_LARGE));
- const vbool<K> vz = (abs(p.z) <= vfloat<K>(FLT_LARGE));
- const vbool<K> vn = radius >= vfloat<K>(0);
- const vbool<K> vf = abs(time) < vfloat<K>(inf);
- return vx & vy & vz & vn & vf;
- }
-
- __forceinline void get(PointQueryK<1>* ray) const;
- __forceinline void get(size_t i, PointQueryK<1>& ray) const;
- __forceinline void set(const PointQueryK<1>* ray);
- __forceinline void set(size_t i, const PointQueryK<1>& ray);
-
- Vec3vf<K> p; // location of the query point
- vfloat<K> time; // time for motion blur
- vfloat<K> radius; // radius for the point query
- };
-
- /* Specialization for a single point query */
- template<>
- struct RTC_ALIGN(16) PointQueryK<1>
- {
- /* Default construction does nothing */
- __forceinline PointQueryK() {}
-
- /* Constructs a ray from origin, direction, and ray segment. Near
- * has to be smaller than far */
- __forceinline PointQueryK(const Vec3fa& p, float radius = inf, float time = zero)
- : p(p), time(time), radius(radius) {}
-
- /* Calculates if this is a valid ray that does not cause issues during traversal */
- __forceinline bool valid() const {
- return all(le_mask(abs(Vec3fa(p)), Vec3fa(FLT_LARGE)) & le_mask(Vec3fa(0.f), Vec3fa(radius))) && abs(time) < float(inf);
- }
-
- Vec3f p;
- float time;
- float radius;
- };
-
- /* Converts point query packet to single point query */
- template<int K>
- __forceinline void PointQueryK<K>::get(PointQueryK<1>* query) const
- {
- for (size_t i = 0; i < K; i++) // FIXME: use SIMD transpose
- {
- query[i].p.x = p.x[i];
- query[i].p.y = p.y[i];
- query[i].p.z = p.z[i];
- query[i].time = time[i];
- query[i].radius = radius[i];
- }
- }
-
- /* Extracts a single point query out of a point query packet*/
- template<int K>
- __forceinline void PointQueryK<K>::get(size_t i, PointQueryK<1>& query) const
- {
- query.p.x = p.x[i];
- query.p.y = p.y[i];
- query.p.z = p.z[i];
- query.radius = radius[i];
- query.time = time[i];
- }
-
- /* Converts single point query to point query packet */
- template<int K>
- __forceinline void PointQueryK<K>::set(const PointQueryK<1>* query)
- {
- for (size_t i = 0; i < K; i++)
- {
- p.x[i] = query[i].p.x;
- p.y[i] = query[i].p.y;
- p.z[i] = query[i].p.z;
- radius[i] = query[i].radius;
- time[i] = query[i].time;
- }
- }
-
- /* inserts a single point query into a point query packet element */
- template<int K>
- __forceinline void PointQueryK<K>::set(size_t i, const PointQueryK<1>& query)
- {
- p.x[i] = query.p.x;
- p.y[i] = query.p.y;
- p.z[i] = query.p.z;
- radius[i] = query.radius;
- time[i] = query.time;
- }
-
- /* Shortcuts */
- typedef PointQueryK<1> PointQuery;
- typedef PointQueryK<4> PointQuery4;
- typedef PointQueryK<8> PointQuery8;
- typedef PointQueryK<16> PointQuery16;
- struct PointQueryN;
-
- /* Outputs point query to stream */
- template<int K>
- __forceinline embree_ostream operator <<(embree_ostream cout, const PointQueryK<K>& query)
- {
- cout << "{ " << embree_endl
- << " p = " << query.p << embree_endl
- << " r = " << query.radius << embree_endl
- << " time = " << query.time << embree_endl
- << "}";
- return cout;
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/primref.h b/thirdparty/embree-aarch64/kernels/common/primref.h
deleted file mode 100644
index ce75c982bb..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/primref.h
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-
-namespace embree
-{
- /*! A primitive reference stores the bounds of the primitive and its ID. */
- struct __aligned(32) PrimRef
- {
- __forceinline PrimRef () {}
-
-#if defined(__AVX__)
- __forceinline PrimRef(const PrimRef& v) {
- vfloat8::store((float*)this,vfloat8::load((float*)&v));
- }
- __forceinline PrimRef& operator=(const PrimRef& v) {
- vfloat8::store((float*)this,vfloat8::load((float*)&v)); return *this;
- }
-#endif
-
- __forceinline PrimRef (const BBox3fa& bounds, unsigned int geomID, unsigned int primID)
- {
- lower = Vec3fx(bounds.lower, geomID);
- upper = Vec3fx(bounds.upper, primID);
- }
-
- __forceinline PrimRef (const BBox3fa& bounds, size_t id)
- {
-#if defined(__X86_64__) || defined(__aarch64__)
- lower = Vec3fx(bounds.lower, (unsigned)(id & 0xFFFFFFFF));
- upper = Vec3fx(bounds.upper, (unsigned)((id >> 32) & 0xFFFFFFFF));
-#else
- lower = Vec3fx(bounds.lower, (unsigned)id);
- upper = Vec3fx(bounds.upper, (unsigned)0);
-#endif
- }
-
- /*! calculates twice the center of the primitive */
- __forceinline const Vec3fa center2() const {
- return lower+upper;
- }
-
- /*! return the bounding box of the primitive */
- __forceinline const BBox3fa bounds() const {
- return BBox3fa(lower,upper);
- }
-
- /*! size for bin heuristic is 1 */
- __forceinline unsigned size() const {
- return 1;
- }
-
- /*! returns bounds and centroid used for binning */
- __forceinline void binBoundsAndCenter(BBox3fa& bounds_o, Vec3fa& center_o) const
- {
- bounds_o = bounds();
- center_o = embree::center2(bounds_o);
- }
-
- __forceinline unsigned& geomIDref() { // FIXME: remove !!!!!!!
- return lower.u;
- }
- __forceinline unsigned& primIDref() { // FIXME: remove !!!!!!!
- return upper.u;
- }
-
- /*! returns the geometry ID */
- __forceinline unsigned geomID() const {
- return lower.a;
- }
-
- /*! returns the primitive ID */
- __forceinline unsigned primID() const {
- return upper.a;
- }
-
- /*! returns an size_t sized ID */
- __forceinline size_t ID() const {
-#if defined(__X86_64__) || defined(__aarch64__)
- return size_t(lower.u) + (size_t(upper.u) << 32);
-#else
- return size_t(lower.u);
-#endif
- }
-
- /*! special function for operator< */
- __forceinline uint64_t ID64() const {
- return (((uint64_t)primID()) << 32) + (uint64_t)geomID();
- }
-
- /*! allows sorting the primrefs by ID */
- friend __forceinline bool operator<(const PrimRef& p0, const PrimRef& p1) {
- return p0.ID64() < p1.ID64();
- }
-
- /*! Outputs primitive reference to a stream. */
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRef& ref) {
- return cout << "{ lower = " << ref.lower << ", upper = " << ref.upper << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << " }";
- }
-
- public:
- Vec3fx lower; //!< lower bounds and geomID
- Vec3fx upper; //!< upper bounds and primID
- };
-
- /*! fast exchange for PrimRefs */
- __forceinline void xchg(PrimRef& a, PrimRef& b)
- {
-#if defined(__AVX__)
- const vfloat8 aa = vfloat8::load((float*)&a);
- const vfloat8 bb = vfloat8::load((float*)&b);
- vfloat8::store((float*)&a,bb);
- vfloat8::store((float*)&b,aa);
-#else
- std::swap(a,b);
-#endif
- }
-
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
- /************************************************************************************/
-
- struct SubGridBuildData {
- unsigned short sx,sy;
- unsigned int primID;
-
- __forceinline SubGridBuildData() {};
- __forceinline SubGridBuildData(const unsigned int sx, const unsigned int sy, const unsigned int primID) : sx(sx), sy(sy), primID(primID) {};
-
- __forceinline size_t x() const { return (size_t)sx & 0x7fff; }
- __forceinline size_t y() const { return (size_t)sy & 0x7fff; }
-
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/primref_mb.h b/thirdparty/embree-aarch64/kernels/common/primref_mb.h
deleted file mode 100644
index b6c1ad5712..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/primref_mb.h
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-
-#define MBLUR_BIN_LBBOX 1
-
-namespace embree
-{
-#if MBLUR_BIN_LBBOX
-
- /*! A primitive reference stores the bounds of the primitive and its ID. */
- struct PrimRefMB
- {
- typedef LBBox3fa BBox;
-
- __forceinline PrimRefMB () {}
-
- __forceinline PrimRefMB (const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, unsigned int geomID, unsigned int primID)
- : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
- {
- assert(activeTimeSegments > 0);
- lbounds.bounds0.lower.a = geomID;
- lbounds.bounds0.upper.a = primID;
- lbounds.bounds1.lower.a = activeTimeSegments;
- lbounds.bounds1.upper.a = totalTimeSegments;
- }
-
- __forceinline PrimRefMB (EmptyTy empty, const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
- : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
- {
- assert(activeTimeSegments > 0);
-#if defined(__X86_64__) || defined(__aarch64__)
- lbounds.bounds0.lower.a = id & 0xFFFFFFFF;
- lbounds.bounds0.upper.a = (id >> 32) & 0xFFFFFFFF;
-#else
- lbounds.bounds0.lower.a = id;
- lbounds.bounds0.upper.a = 0;
-#endif
- lbounds.bounds1.lower.a = activeTimeSegments;
- lbounds.bounds1.upper.a = totalTimeSegments;
- }
-
- __forceinline PrimRefMB (const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
- : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
- {
- assert(activeTimeSegments > 0);
-#if defined(__X86_64__) || defined(__aarch64__)
- lbounds.bounds0.lower.u = id & 0xFFFFFFFF;
- lbounds.bounds0.upper.u = (id >> 32) & 0xFFFFFFFF;
-#else
- lbounds.bounds0.lower.u = id;
- lbounds.bounds0.upper.u = 0;
-#endif
- lbounds.bounds1.lower.a = activeTimeSegments;
- lbounds.bounds1.upper.a = totalTimeSegments;
- }
-
- /*! returns bounds for binning */
- __forceinline LBBox3fa bounds() const {
- return lbounds;
- }
-
- /*! returns the number of time segments of this primref */
- __forceinline unsigned size() const {
- return lbounds.bounds1.lower.a;
- }
-
- __forceinline unsigned totalTimeSegments() const {
- return lbounds.bounds1.upper.a;
- }
-
- /* calculate overlapping time segment range */
- __forceinline range<int> timeSegmentRange(const BBox1f& range) const {
- return getTimeSegmentRange(range,time_range,float(totalTimeSegments()));
- }
-
- /* returns time that corresponds to time step */
- __forceinline float timeStep(const int i) const {
- assert(i>=0 && i<=(int)totalTimeSegments());
- return time_range.lower + time_range.size()*float(i)/float(totalTimeSegments());
- }
-
- /*! checks if time range overlaps */
- __forceinline bool time_range_overlap(const BBox1f& range) const
- {
- if (0.9999f*time_range.upper <= range.lower) return false;
- if (1.0001f*time_range.lower >= range.upper) return false;
- return true;
- }
-
- /*! returns center for binning */
- __forceinline Vec3fa binCenter() const {
- return center2(lbounds.interpolate(0.5f));
- }
-
- /*! returns bounds and centroid used for binning */
- __forceinline void binBoundsAndCenter(LBBox3fa& bounds_o, Vec3fa& center_o) const
- {
- bounds_o = bounds();
- center_o = binCenter();
- }
-
- /*! returns the geometry ID */
- __forceinline unsigned geomID() const {
- return lbounds.bounds0.lower.a;
- }
-
- /*! returns the primitive ID */
- __forceinline unsigned primID() const {
- return lbounds.bounds0.upper.a;
- }
-
- /*! returns an size_t sized ID */
- __forceinline size_t ID() const {
-#if defined(__X86_64__) || defined(__aarch64__)
- return size_t(lbounds.bounds0.lower.u) + (size_t(lbounds.bounds0.upper.u) << 32);
-#else
- return size_t(lbounds.bounds0.lower.u);
-#endif
- }
-
- /*! special function for operator< */
- __forceinline uint64_t ID64() const {
- return (((uint64_t)primID()) << 32) + (uint64_t)geomID();
- }
-
- /*! allows sorting the primrefs by ID */
- friend __forceinline bool operator<(const PrimRefMB& p0, const PrimRefMB& p1) {
- return p0.ID64() < p1.ID64();
- }
-
- /*! Outputs primitive reference to a stream. */
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRefMB& ref) {
- return cout << "{ time_range = " << ref.time_range << ", bounds = " << ref.bounds() << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << ", active_segments = " << ref.size() << ", total_segments = " << ref.totalTimeSegments() << " }";
- }
-
- public:
- LBBox3fx lbounds;
- BBox1f time_range; // entire geometry time range
- };
-
-#else
-
- /*! A primitive reference stores the bounds of the primitive and its ID. */
- struct __aligned(16) PrimRefMB
- {
- typedef BBox3fa BBox;
-
- __forceinline PrimRefMB () {}
-
- __forceinline PrimRefMB (const LBBox3fa& bounds, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, unsigned int geomID, unsigned int primID)
- : bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range)
- {
- assert(activeTimeSegments > 0);
- bbox.lower.a = geomID;
- bbox.upper.a = primID;
- }
-
- __forceinline PrimRefMB (EmptyTy empty, const LBBox3fa& bounds, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
- : bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range)
- {
- assert(activeTimeSegments > 0);
-#if defined(__X86_64__) || defined(__aarch64__)
- bbox.lower.u = id & 0xFFFFFFFF;
- bbox.upper.u = (id >> 32) & 0xFFFFFFFF;
-#else
- bbox.lower.u = id;
- bbox.upper.u = 0;
-#endif
- }
-
- /*! returns bounds for binning */
- __forceinline BBox3fa bounds() const {
- return bbox;
- }
-
- /*! returns the number of time segments of this primref */
- __forceinline unsigned int size() const {
- return _activeTimeSegments;
- }
-
- __forceinline unsigned int totalTimeSegments() const {
- return _totalTimeSegments;
- }
-
- /* calculate overlapping time segment range */
- __forceinline range<int> timeSegmentRange(const BBox1f& range) const {
- return getTimeSegmentRange(range,time_range,float(_totalTimeSegments));
- }
-
- /* returns time that corresponds to time step */
- __forceinline float timeStep(const int i) const {
- assert(i>=0 && i<=(int)_totalTimeSegments);
- return time_range.lower + time_range.size()*float(i)/float(_totalTimeSegments);
- }
-
- /*! checks if time range overlaps */
- __forceinline bool time_range_overlap(const BBox1f& range) const
- {
- if (0.9999f*time_range.upper <= range.lower) return false;
- if (1.0001f*time_range.lower >= range.upper) return false;
- return true;
- }
-
- /*! returns center for binning */
- __forceinline Vec3fa binCenter() const {
- return center2(bounds());
- }
-
- /*! returns bounds and centroid used for binning */
- __forceinline void binBoundsAndCenter(BBox3fa& bounds_o, Vec3fa& center_o) const
- {
- bounds_o = bounds();
- center_o = center2(bounds());
- }
-
- /*! returns the geometry ID */
- __forceinline unsigned int geomID() const {
- return bbox.lower.a;
- }
-
- /*! returns the primitive ID */
- __forceinline unsigned int primID() const {
- return bbox.upper.a;
- }
-
- /*! returns an size_t sized ID */
- __forceinline size_t ID() const {
-#if defined(__X86_64__) || defined(__aarch64__)
- return size_t(bbox.lower.u) + (size_t(bbox.upper.u) << 32);
-#else
- return size_t(bbox.lower.u);
-#endif
- }
-
- /*! special function for operator< */
- __forceinline uint64_t ID64() const {
- return (((uint64_t)primID()) << 32) + (uint64_t)geomID();
- }
-
- /*! allows sorting the primrefs by ID */
- friend __forceinline bool operator<(const PrimRefMB& p0, const PrimRefMB& p1) {
- return p0.ID64() < p1.ID64();
- }
-
- /*! Outputs primitive reference to a stream. */
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRefMB& ref) {
- return cout << "{ bounds = " << ref.bounds() << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << ", active_segments = " << ref.size() << ", total_segments = " << ref.totalTimeSegments() << " }";
- }
-
- public:
- BBox3fa bbox; // bounds, geomID, primID
- unsigned int _activeTimeSegments;
- unsigned int _totalTimeSegments;
- BBox1f time_range; // entire geometry time range
- };
-
-#endif
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/profile.h b/thirdparty/embree-aarch64/kernels/common/profile.h
deleted file mode 100644
index a7de36414d..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/profile.h
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-
-namespace embree
-{
- /*! helper structure for the implementation of the profile functions below */
- struct ProfileTimer
- {
- static const size_t N = 20;
-
- ProfileTimer () {}
-
- ProfileTimer (const size_t numSkip) : i(0), j(0), maxJ(0), numSkip(numSkip), t0(0)
- {
- for (size_t i=0; i<N; i++) names[i] = nullptr;
- for (size_t i=0; i<N; i++) dt_fst[i] = 0.0;
- for (size_t i=0; i<N; i++) dt_min[i] = pos_inf;
- for (size_t i=0; i<N; i++) dt_avg[i] = 0.0;
- for (size_t i=0; i<N; i++) dt_max[i] = neg_inf;
- }
-
- __forceinline void begin()
- {
- j=0;
- t0 = tj = getSeconds();
- }
-
- __forceinline void end() {
- absolute("total");
- i++;
- }
-
- __forceinline void operator() (const char* name) {
- relative(name);
- }
-
- __forceinline void absolute (const char* name)
- {
- const double t1 = getSeconds();
- const double dt = t1-t0;
- assert(names[j] == nullptr || names[j] == name);
- names[j] = name;
- if (i == 0) dt_fst[j] = dt;
- if (i>=numSkip) {
- dt_min[j] = min(dt_min[j],dt);
- dt_avg[j] = dt_avg[j] + dt;
- dt_max[j] = max(dt_max[j],dt);
- }
- j++;
- maxJ = max(maxJ,j);
- }
-
- __forceinline void relative (const char* name)
- {
- const double t1 = getSeconds();
- const double dt = t1-tj;
- tj = t1;
- assert(names[j] == nullptr || names[j] == name);
- names[j] = name;
- if (i == 0) dt_fst[j] = dt;
- if (i>=numSkip) {
- dt_min[j] = min(dt_min[j],dt);
- dt_avg[j] = dt_avg[j] + dt;
- dt_max[j] = max(dt_max[j],dt);
- }
- j++;
- maxJ = max(maxJ,j);
- }
-
- void print(size_t numElements)
- {
- for (size_t k=0; k<N; k++)
- dt_avg[k] /= double(i-numSkip);
-
- printf(" profile [M/s]:\n");
- for (size_t j=0; j<maxJ; j++)
- printf("%20s: fst = %7.2f M/s, min = %7.2f M/s, avg = %7.2f M/s, max = %7.2f M/s\n",
- names[j],numElements/dt_fst[j]*1E-6,numElements/dt_max[j]*1E-6,numElements/dt_avg[j]*1E-6,numElements/dt_min[j]*1E-6);
-
- printf(" profile [ms]:\n");
- for (size_t j=0; j<maxJ; j++)
- printf("%20s: fst = %7.2f ms, min = %7.2f ms, avg = %7.2f ms, max = %7.2fms\n",
- names[j],1000.0*dt_fst[j],1000.0*dt_min[j],1000.0*dt_avg[j],1000.0*dt_max[j]);
- }
-
- void print()
- {
- printf(" profile:\n");
-
- for (size_t k=0; k<N; k++)
- dt_avg[k] /= double(i-numSkip);
-
- for (size_t j=0; j<maxJ; j++) {
- printf("%20s: fst = %7.2f ms, min = %7.2f ms, avg = %7.2f ms, max = %7.2fms\n",
- names[j],1000.0*dt_fst[j],1000.0*dt_min[j],1000.0*dt_avg[j],1000.0*dt_max[j]);
- }
- }
-
- double avg() {
- return dt_avg[maxJ-1]/double(i-numSkip);
- }
-
- private:
- size_t i;
- size_t j;
- size_t maxJ;
- size_t numSkip;
- double t0;
- double tj;
- const char* names[N];
- double dt_fst[N];
- double dt_min[N];
- double dt_avg[N];
- double dt_max[N];
- };
-
- /*! This function executes some code block multiple times and measured sections of it.
- Use the following way:
-
- profile(1,10,1000,[&](ProfileTimer& timer) {
- // code
- timer("A");
- // code
- timer("B");
- });
- */
- template<typename Closure>
- void profile(const size_t numSkip, const size_t numIter, const size_t numElements, const Closure& closure)
- {
- ProfileTimer timer(numSkip);
-
- for (size_t i=0; i<numSkip+numIter; i++)
- {
- timer.begin();
- closure(timer);
- timer.end();
- }
- timer.print(numElements);
- }
-
- /*! similar as the function above, but the timer object comes externally */
- template<typename Closure>
- void profile(ProfileTimer& timer, const size_t numSkip, const size_t numIter, const size_t numElements, const Closure& closure)
- {
- timer = ProfileTimer(numSkip);
-
- for (size_t i=0; i<numSkip+numIter; i++)
- {
- timer.begin();
- closure(timer);
- timer.end();
- }
- timer.print(numElements);
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/ray.h b/thirdparty/embree-aarch64/kernels/common/ray.h
deleted file mode 100644
index 336d48942c..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/ray.h
+++ /dev/null
@@ -1,1517 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "instance_stack.h"
-
-// FIXME: if ray gets seperated into ray* and hit, uload4 needs to be adjusted
-
-namespace embree
-{
- static const size_t MAX_INTERNAL_STREAM_SIZE = 32;
-
- /* Ray structure for K rays */
- template<int K>
- struct RayK
- {
- /* Default construction does nothing */
- __forceinline RayK() {}
-
- /* Constructs a ray from origin, direction, and ray segment. Near
- * has to be smaller than far */
- __forceinline RayK(const Vec3vf<K>& org, const Vec3vf<K>& dir,
- const vfloat<K>& tnear = zero, const vfloat<K>& tfar = inf,
- const vfloat<K>& time = zero, const vint<K>& mask = -1, const vint<K>& id = 0, const vint<K>& flags = 0)
- : org(org), dir(dir), _tnear(tnear), tfar(tfar), _time(time), mask(mask), id(id), flags(flags) {}
-
- /* Returns the size of the ray */
- static __forceinline size_t size() { return K; }
-
- /* Calculates if this is a valid ray that does not cause issues during traversal */
- __forceinline vbool<K> valid() const
- {
- const vbool<K> vx = (abs(org.x) <= vfloat<K>(FLT_LARGE)) & (abs(dir.x) <= vfloat<K>(FLT_LARGE));
- const vbool<K> vy = (abs(org.y) <= vfloat<K>(FLT_LARGE)) & (abs(dir.y) <= vfloat<K>(FLT_LARGE));
- const vbool<K> vz = (abs(org.z) <= vfloat<K>(FLT_LARGE)) & (abs(dir.z) <= vfloat<K>(FLT_LARGE));
- const vbool<K> vn = abs(tnear()) <= vfloat<K>(inf);
- const vbool<K> vf = abs(tfar) <= vfloat<K>(inf);
- return vx & vy & vz & vn & vf;
- }
-
- __forceinline void get(RayK<1>* ray) const;
- __forceinline void get(size_t i, RayK<1>& ray) const;
- __forceinline void set(const RayK<1>* ray);
- __forceinline void set(size_t i, const RayK<1>& ray);
-
- __forceinline void copy(size_t dest, size_t source);
-
- __forceinline vint<K> octant() const
- {
- return select(dir.x < 0.0f, vint<K>(1), vint<K>(zero)) |
- select(dir.y < 0.0f, vint<K>(2), vint<K>(zero)) |
- select(dir.z < 0.0f, vint<K>(4), vint<K>(zero));
- }
-
- /* Ray data */
- Vec3vf<K> org; // ray origin
- vfloat<K> _tnear; // start of ray segment
- Vec3vf<K> dir; // ray direction
- vfloat<K> _time; // time of this ray for motion blur
- vfloat<K> tfar; // end of ray segment
- vint<K> mask; // used to mask out objects during traversal
- vint<K> id;
- vint<K> flags;
-
- __forceinline vfloat<K>& tnear() { return _tnear; }
- __forceinline vfloat<K>& time() { return _time; }
- __forceinline const vfloat<K>& tnear() const { return _tnear; }
- __forceinline const vfloat<K>& time() const { return _time; }
- };
-
- /* Ray+hit structure for K rays */
- template<int K>
- struct RayHitK : RayK<K>
- {
- using RayK<K>::org;
- using RayK<K>::_tnear;
- using RayK<K>::dir;
- using RayK<K>::_time;
- using RayK<K>::tfar;
- using RayK<K>::mask;
- using RayK<K>::id;
- using RayK<K>::flags;
-
- using RayK<K>::tnear;
- using RayK<K>::time;
-
- /* Default construction does nothing */
- __forceinline RayHitK() {}
-
- /* Constructs a ray from origin, direction, and ray segment. Near
- * has to be smaller than far */
- __forceinline RayHitK(const Vec3vf<K>& org, const Vec3vf<K>& dir,
- const vfloat<K>& tnear = zero, const vfloat<K>& tfar = inf,
- const vfloat<K>& time = zero, const vint<K>& mask = -1, const vint<K>& id = 0, const vint<K>& flags = 0)
- : RayK<K>(org, dir, tnear, tfar, time, mask, id, flags),
- geomID(RTC_INVALID_GEOMETRY_ID)
- {
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- instID[l] = RTC_INVALID_GEOMETRY_ID;
- }
-
- __forceinline RayHitK(const RayK<K>& ray)
- : RayK<K>(ray),
- geomID(RTC_INVALID_GEOMETRY_ID)
- {
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- instID[l] = RTC_INVALID_GEOMETRY_ID;
- }
-
- __forceinline RayHitK<K>& operator =(const RayK<K>& ray)
- {
- org = ray.org;
- _tnear = ray._tnear;
- dir = ray.dir;
- _time = ray._time;
- tfar = ray.tfar;
- mask = ray.mask;
- id = ray.id;
- flags = ray.flags;
-
- geomID = RTC_INVALID_GEOMETRY_ID;
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- instID[l] = RTC_INVALID_GEOMETRY_ID;
-
- return *this;
- }
-
- /* Calculates if the hit is valid */
- __forceinline void verifyHit(const vbool<K>& valid0) const
- {
- vbool<K> valid = valid0 & geomID != vuint<K>(RTC_INVALID_GEOMETRY_ID);
- const vbool<K> vt = (abs(tfar) <= vfloat<K>(FLT_LARGE)) | (tfar == vfloat<K>(neg_inf));
- const vbool<K> vu = (abs(u) <= vfloat<K>(FLT_LARGE));
- const vbool<K> vv = (abs(u) <= vfloat<K>(FLT_LARGE));
- const vbool<K> vnx = abs(Ng.x) <= vfloat<K>(FLT_LARGE);
- const vbool<K> vny = abs(Ng.y) <= vfloat<K>(FLT_LARGE);
- const vbool<K> vnz = abs(Ng.z) <= vfloat<K>(FLT_LARGE);
- if (any(valid & !vt)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid t");
- if (any(valid & !vu)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid u");
- if (any(valid & !vv)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid v");
- if (any(valid & !vnx)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid Ng.x");
- if (any(valid & !vny)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid Ng.y");
- if (any(valid & !vnz)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid Ng.z");
- }
-
- __forceinline void get(RayHitK<1>* ray) const;
- __forceinline void get(size_t i, RayHitK<1>& ray) const;
- __forceinline void set(const RayHitK<1>* ray);
- __forceinline void set(size_t i, const RayHitK<1>& ray);
-
- __forceinline void copy(size_t dest, size_t source);
-
- /* Hit data */
- Vec3vf<K> Ng; // geometry normal
- vfloat<K> u; // barycentric u coordinate of hit
- vfloat<K> v; // barycentric v coordinate of hit
- vuint<K> primID; // primitive ID
- vuint<K> geomID; // geometry ID
- vuint<K> instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
- };
-
- /* Specialization for a single ray */
- template<>
- struct RayK<1>
- {
- /* Default construction does nothing */
- __forceinline RayK() {}
-
- /* Constructs a ray from origin, direction, and ray segment. Near
- * has to be smaller than far */
- __forceinline RayK(const Vec3fa& org, const Vec3fa& dir, float tnear = zero, float tfar = inf, float time = zero, int mask = -1, int id = 0, int flags = 0)
- : org(org,tnear), dir(dir,time), tfar(tfar), mask(mask), id(id), flags(flags) {}
-
- /* Calculates if this is a valid ray that does not cause issues during traversal */
- __forceinline bool valid() const {
- return all(le_mask(abs(Vec3fa(org)), Vec3fa(FLT_LARGE)) & le_mask(abs(Vec3fa(dir)), Vec3fa(FLT_LARGE))) && abs(tnear()) <= float(inf) && abs(tfar) <= float(inf);
- }
-
- /* Ray data */
- Vec3ff org; // 3 floats for ray origin, 1 float for tnear
- //float tnear; // start of ray segment
- Vec3ff dir; // 3 floats for ray direction, 1 float for time
- // float time;
- float tfar; // end of ray segment
- int mask; // used to mask out objects during traversal
- int id; // ray ID
- int flags; // ray flags
-
- __forceinline float& tnear() { return org.w; };
- __forceinline const float& tnear() const { return org.w; };
-
- __forceinline float& time() { return dir.w; };
- __forceinline const float& time() const { return dir.w; };
-
- };
-
- template<>
- struct RayHitK<1> : RayK<1>
- {
- /* Default construction does nothing */
- __forceinline RayHitK() {}
-
- /* Constructs a ray from origin, direction, and ray segment. Near
- * has to be smaller than far */
- __forceinline RayHitK(const Vec3fa& org, const Vec3fa& dir, float tnear = zero, float tfar = inf, float time = zero, int mask = -1, int id = 0, int flags = 0)
- : RayK<1>(org, dir, tnear, tfar, time, mask, id, flags),
- geomID(RTC_INVALID_GEOMETRY_ID) {}
-
- __forceinline RayHitK(const RayK<1>& ray)
- : RayK<1>(ray),
- geomID(RTC_INVALID_GEOMETRY_ID) {}
-
- __forceinline RayHitK<1>& operator =(const RayK<1>& ray)
- {
- org = ray.org;
- dir = ray.dir;
- tfar = ray.tfar;
- mask = ray.mask;
- id = ray.id;
- flags = ray.flags;
-
- geomID = RTC_INVALID_GEOMETRY_ID;
-
- return *this;
- }
-
- /* Calculates if the hit is valid */
- __forceinline void verifyHit() const
- {
- if (geomID == RTC_INVALID_GEOMETRY_ID) return;
- const bool vt = (abs(tfar) <= FLT_LARGE) || (tfar == float(neg_inf));
- const bool vu = (abs(u) <= FLT_LARGE);
- const bool vv = (abs(u) <= FLT_LARGE);
- const bool vnx = abs(Ng.x) <= FLT_LARGE;
- const bool vny = abs(Ng.y) <= FLT_LARGE;
- const bool vnz = abs(Ng.z) <= FLT_LARGE;
- if (!vt) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid t");
- if (!vu) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid u");
- if (!vv) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid v");
- if (!vnx) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid Ng.x");
- if (!vny) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid Ng.y");
- if (!vnz) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid Ng.z");
- }
-
- /* Hit data */
- Vec3f Ng; // not normalized geometry normal
- float u; // barycentric u coordinate of hit
- float v; // barycentric v coordinate of hit
- unsigned int primID; // primitive ID
- unsigned int geomID; // geometry ID
- unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
- };
-
- /* Converts ray packet to single rays */
- template<int K>
- __forceinline void RayK<K>::get(RayK<1>* ray) const
- {
- for (size_t i = 0; i < K; i++) // FIXME: use SIMD transpose
- {
- ray[i].org.x = org.x[i]; ray[i].org.y = org.y[i]; ray[i].org.z = org.z[i]; ray[i].tnear() = tnear()[i];
- ray[i].dir.x = dir.x[i]; ray[i].dir.y = dir.y[i]; ray[i].dir.z = dir.z[i]; ray[i].time() = time()[i];
- ray[i].tfar = tfar[i]; ray[i].mask = mask[i]; ray[i].id = id[i]; ray[i].flags = flags[i];
- }
- }
-
- template<int K>
- __forceinline void RayHitK<K>::get(RayHitK<1>* ray) const
- {
- // FIXME: use SIMD transpose
- for (size_t i = 0; i < K; i++)
- get(i, ray[i]);
- }
-
- /* Extracts a single ray out of a ray packet*/
- template<int K>
- __forceinline void RayK<K>::get(size_t i, RayK<1>& ray) const
- {
- ray.org.x = org.x[i]; ray.org.y = org.y[i]; ray.org.z = org.z[i]; ray.tnear() = tnear()[i];
- ray.dir.x = dir.x[i]; ray.dir.y = dir.y[i]; ray.dir.z = dir.z[i]; ray.time() = time()[i];
- ray.tfar = tfar[i]; ray.mask = mask[i]; ray.id = id[i]; ray.flags = flags[i];
- }
-
- template<int K>
- __forceinline void RayHitK<K>::get(size_t i, RayHitK<1>& ray) const
- {
- ray.org.x = org.x[i]; ray.org.y = org.y[i]; ray.org.z = org.z[i]; ray.tnear() = tnear()[i];
- ray.dir.x = dir.x[i]; ray.dir.y = dir.y[i]; ray.dir.z = dir.z[i]; ray.tfar = tfar[i]; ray.time() = time()[i];
- ray.mask = mask[i]; ray.id = id[i]; ray.flags = flags[i];
- ray.Ng.x = Ng.x[i]; ray.Ng.y = Ng.y[i]; ray.Ng.z = Ng.z[i];
- ray.u = u[i]; ray.v = v[i];
- ray.primID = primID[i]; ray.geomID = geomID[i];
-
- instance_id_stack::copy(instID, ray.instID, i);
- }
-
- /* Converts single rays to ray packet */
- template<int K>
- __forceinline void RayK<K>::set(const RayK<1>* ray)
- {
- // FIXME: use SIMD transpose
- for (size_t i = 0; i < K; i++)
- set(i, ray[i]);
- }
-
- template<int K>
- __forceinline void RayHitK<K>::set(const RayHitK<1>* ray)
- {
- // FIXME: use SIMD transpose
- for (size_t i = 0; i < K; i++)
- set(i, ray[i]);
- }
-
- /* inserts a single ray into a ray packet element */
- template<int K>
- __forceinline void RayK<K>::set(size_t i, const RayK<1>& ray)
- {
- org.x[i] = ray.org.x; org.y[i] = ray.org.y; org.z[i] = ray.org.z; tnear()[i] = ray.tnear();
- dir.x[i] = ray.dir.x; dir.y[i] = ray.dir.y; dir.z[i] = ray.dir.z; time()[i] = ray.time();
- tfar[i] = ray.tfar; mask[i] = ray.mask; id[i] = ray.id; flags[i] = ray.flags;
- }
-
- template<int K>
- __forceinline void RayHitK<K>::set(size_t i, const RayHitK<1>& ray)
- {
- org.x[i] = ray.org.x; org.y[i] = ray.org.y; org.z[i] = ray.org.z; tnear()[i] = ray.tnear();
- dir.x[i] = ray.dir.x; dir.y[i] = ray.dir.y; dir.z[i] = ray.dir.z; time()[i] = ray.time();
- tfar[i] = ray.tfar; mask[i] = ray.mask; id[i] = ray.id; flags[i] = ray.flags;
- Ng.x[i] = ray.Ng.x; Ng.y[i] = ray.Ng.y; Ng.z[i] = ray.Ng.z;
- u[i] = ray.u; v[i] = ray.v;
- primID[i] = ray.primID; geomID[i] = ray.geomID;
-
- instance_id_stack::copy(ray.instID, instID, i);
- }
-
- /* copies a ray packet element into another element*/
- template<int K>
- __forceinline void RayK<K>::copy(size_t dest, size_t source)
- {
- org.x[dest] = org.x[source]; org.y[dest] = org.y[source]; org.z[dest] = org.z[source]; tnear()[dest] = tnear()[source];
- dir.x[dest] = dir.x[source]; dir.y[dest] = dir.y[source]; dir.z[dest] = dir.z[source]; time()[dest] = time()[source];
- tfar [dest] = tfar[source]; mask[dest] = mask[source]; id[dest] = id[source]; flags[dest] = flags[source];
- }
-
- template<int K>
- __forceinline void RayHitK<K>::copy(size_t dest, size_t source)
- {
- org.x[dest] = org.x[source]; org.y[dest] = org.y[source]; org.z[dest] = org.z[source]; tnear()[dest] = tnear()[source];
- dir.x[dest] = dir.x[source]; dir.y[dest] = dir.y[source]; dir.z[dest] = dir.z[source]; time()[dest] = time()[source];
- tfar [dest] = tfar[source]; mask[dest] = mask[source]; id[dest] = id[source]; flags[dest] = flags[source];
- Ng.x[dest] = Ng.x[source]; Ng.y[dest] = Ng.y[source]; Ng.z[dest] = Ng.z[source];
- u[dest] = u[source]; v[dest] = v[source];
- primID[dest] = primID[source]; geomID[dest] = geomID[source];
-
- instance_id_stack::copy(instID, instID, source, dest);
- }
-
- /* Shortcuts */
- typedef RayK<1> Ray;
- typedef RayK<4> Ray4;
- typedef RayK<8> Ray8;
- typedef RayK<16> Ray16;
- struct RayN;
-
- typedef RayHitK<1> RayHit;
- typedef RayHitK<4> RayHit4;
- typedef RayHitK<8> RayHit8;
- typedef RayHitK<16> RayHit16;
- struct RayHitN;
-
- template<int K, bool intersect>
- struct RayTypeHelper;
-
- template<int K>
- struct RayTypeHelper<K, true>
- {
- typedef RayHitK<K> Ty;
- };
-
- template<int K>
- struct RayTypeHelper<K, false>
- {
- typedef RayK<K> Ty;
- };
-
- template<bool intersect>
- using RayType = typename RayTypeHelper<1, intersect>::Ty;
-
- template<int K, bool intersect>
- using RayTypeK = typename RayTypeHelper<K, intersect>::Ty;
-
- /* Outputs ray to stream */
- template<int K>
- __forceinline embree_ostream operator <<(embree_ostream cout, const RayK<K>& ray)
- {
- return cout << "{ " << embree_endl
- << " org = " << ray.org << embree_endl
- << " dir = " << ray.dir << embree_endl
- << " near = " << ray.tnear() << embree_endl
- << " far = " << ray.tfar << embree_endl
- << " time = " << ray.time() << embree_endl
- << " mask = " << ray.mask << embree_endl
- << " id = " << ray.id << embree_endl
- << " flags = " << ray.flags << embree_endl
- << "}";
- }
-
- template<int K>
- __forceinline embree_ostream operator <<(embree_ostream cout, const RayHitK<K>& ray)
- {
- cout << "{ " << embree_endl
- << " org = " << ray.org << embree_endl
- << " dir = " << ray.dir << embree_endl
- << " near = " << ray.tnear() << embree_endl
- << " far = " << ray.tfar << embree_endl
- << " time = " << ray.time() << embree_endl
- << " mask = " << ray.mask << embree_endl
- << " id = " << ray.id << embree_endl
- << " flags = " << ray.flags << embree_endl
- << " Ng = " << ray.Ng
- << " u = " << ray.u << embree_endl
- << " v = " << ray.v << embree_endl
- << " primID = " << ray.primID << embree_endl
- << " geomID = " << ray.geomID << embree_endl
- << " instID =";
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- {
- cout << " " << ray.instID[l];
- }
- cout << embree_endl;
- return cout << "}";
- }
-
- struct RayStreamSOA
- {
- __forceinline RayStreamSOA(void* rays, size_t N)
- : ptr((char*)rays), N(N) {}
-
- /* ray data access functions */
- __forceinline float* org_x(size_t offset = 0) { return (float*)&ptr[0*4*N+offset]; } // x coordinate of ray origin
- __forceinline float* org_y(size_t offset = 0) { return (float*)&ptr[1*4*N+offset]; } // y coordinate of ray origin
- __forceinline float* org_z(size_t offset = 0) { return (float*)&ptr[2*4*N+offset]; }; // z coordinate of ray origin
- __forceinline float* tnear(size_t offset = 0) { return (float*)&ptr[3*4*N+offset]; }; // start of ray segment
-
- __forceinline float* dir_x(size_t offset = 0) { return (float*)&ptr[4*4*N+offset]; }; // x coordinate of ray direction
- __forceinline float* dir_y(size_t offset = 0) { return (float*)&ptr[5*4*N+offset]; }; // y coordinate of ray direction
- __forceinline float* dir_z(size_t offset = 0) { return (float*)&ptr[6*4*N+offset]; }; // z coordinate of ray direction
- __forceinline float* time (size_t offset = 0) { return (float*)&ptr[7*4*N+offset]; }; // time of this ray for motion blur
-
- __forceinline float* tfar (size_t offset = 0) { return (float*)&ptr[8*4*N+offset]; }; // end of ray segment (set to hit distance)
- __forceinline int* mask (size_t offset = 0) { return (int*)&ptr[9*4*N+offset]; }; // used to mask out objects during traversal (optional)
- __forceinline int* id (size_t offset = 0) { return (int*)&ptr[10*4*N+offset]; }; // id
- __forceinline int* flags(size_t offset = 0) { return (int*)&ptr[11*4*N+offset]; }; // flags
-
- /* hit data access functions */
- __forceinline float* Ng_x(size_t offset = 0) { return (float*)&ptr[12*4*N+offset]; }; // x coordinate of geometry normal
- __forceinline float* Ng_y(size_t offset = 0) { return (float*)&ptr[13*4*N+offset]; }; // y coordinate of geometry normal
- __forceinline float* Ng_z(size_t offset = 0) { return (float*)&ptr[14*4*N+offset]; }; // z coordinate of geometry normal
-
- __forceinline float* u(size_t offset = 0) { return (float*)&ptr[15*4*N+offset]; }; // barycentric u coordinate of hit
- __forceinline float* v(size_t offset = 0) { return (float*)&ptr[16*4*N+offset]; }; // barycentric v coordinate of hit
-
- __forceinline unsigned int* primID(size_t offset = 0) { return (unsigned int*)&ptr[17*4*N+offset]; }; // primitive ID
- __forceinline unsigned int* geomID(size_t offset = 0) { return (unsigned int*)&ptr[18*4*N+offset]; }; // geometry ID
- __forceinline unsigned int* instID(size_t level, size_t offset = 0) { return (unsigned int*)&ptr[19*4*N+level*4*N+offset]; }; // instance ID
-
- __forceinline Ray getRayByOffset(size_t offset)
- {
- Ray ray;
- ray.org.x = org_x(offset)[0];
- ray.org.y = org_y(offset)[0];
- ray.org.z = org_z(offset)[0];
- ray.tnear() = tnear(offset)[0];
- ray.dir.x = dir_x(offset)[0];
- ray.dir.y = dir_y(offset)[0];
- ray.dir.z = dir_z(offset)[0];
- ray.time() = time(offset)[0];
- ray.tfar = tfar(offset)[0];
- ray.mask = mask(offset)[0];
- ray.id = id(offset)[0];
- ray.flags = flags(offset)[0];
- return ray;
- }
-
- template<int K>
- __forceinline RayK<K> getRayByOffset(size_t offset)
- {
- RayK<K> ray;
- ray.org.x = vfloat<K>::loadu(org_x(offset));
- ray.org.y = vfloat<K>::loadu(org_y(offset));
- ray.org.z = vfloat<K>::loadu(org_z(offset));
- ray.tnear = vfloat<K>::loadu(tnear(offset));
- ray.dir.x = vfloat<K>::loadu(dir_x(offset));
- ray.dir.y = vfloat<K>::loadu(dir_y(offset));
- ray.dir.z = vfloat<K>::loadu(dir_z(offset));
- ray.time = vfloat<K>::loadu(time(offset));
- ray.tfar = vfloat<K>::loadu(tfar(offset));
- ray.mask = vint<K>::loadu(mask(offset));
- ray.id = vint<K>::loadu(id(offset));
- ray.flags = vint<K>::loadu(flags(offset));
- return ray;
- }
-
- template<int K>
- __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, size_t offset)
- {
- RayK<K> ray;
- ray.org.x = vfloat<K>::loadu(valid, org_x(offset));
- ray.org.y = vfloat<K>::loadu(valid, org_y(offset));
- ray.org.z = vfloat<K>::loadu(valid, org_z(offset));
- ray.tnear() = vfloat<K>::loadu(valid, tnear(offset));
- ray.dir.x = vfloat<K>::loadu(valid, dir_x(offset));
- ray.dir.y = vfloat<K>::loadu(valid, dir_y(offset));
- ray.dir.z = vfloat<K>::loadu(valid, dir_z(offset));
- ray.time() = vfloat<K>::loadu(valid, time(offset));
- ray.tfar = vfloat<K>::loadu(valid, tfar(offset));
-
-#if !defined(__AVX__)
- /* SSE: some ray members must be loaded with scalar instructions to ensure that we don't cause memory faults,
- because the SSE masked loads always access the entire vector */
- if (unlikely(!all(valid)))
- {
- ray.mask = zero;
- ray.id = zero;
- ray.flags = zero;
-
- for (size_t k = 0; k < K; k++)
- {
- if (likely(valid[k]))
- {
- ray.mask[k] = mask(offset)[k];
- ray.id[k] = id(offset)[k];
- ray.flags[k] = flags(offset)[k];
- }
- }
- }
- else
-#endif
- {
- ray.mask = vint<K>::loadu(valid, mask(offset));
- ray.id = vint<K>::loadu(valid, id(offset));
- ray.flags = vint<K>::loadu(valid, flags(offset));
- }
-
- return ray;
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, size_t offset, const RayHitK<K>& ray)
- {
- /*
- * valid_i: stores which of the input rays exist (do not access nonexistent rays!)
- * valid: stores which of the rays actually hit something.
- */
- vbool<K> valid = valid_i;
- valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
-
- if (likely(any(valid)))
- {
- vfloat<K>::storeu(valid, tfar(offset), ray.tfar);
- vfloat<K>::storeu(valid, Ng_x(offset), ray.Ng.x);
- vfloat<K>::storeu(valid, Ng_y(offset), ray.Ng.y);
- vfloat<K>::storeu(valid, Ng_z(offset), ray.Ng.z);
- vfloat<K>::storeu(valid, u(offset), ray.u);
- vfloat<K>::storeu(valid, v(offset), ray.v);
-
-#if !defined(__AVX__)
- /* SSE: some ray members must be stored with scalar instructions to ensure that we don't cause memory faults,
- because the SSE masked stores always access the entire vector */
- if (unlikely(!all(valid_i)))
- {
- for (size_t k = 0; k < K; k++)
- {
- if (likely(valid[k]))
- {
- primID(offset)[k] = ray.primID[k];
- geomID(offset)[k] = ray.geomID[k];
-
- instID(0, offset)[k] = ray.instID[0][k];
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && ray.instID[l-1][k] != RTC_INVALID_GEOMETRY_ID; ++l)
- instID(l, offset)[k] = ray.instID[l][k];
-#endif
- }
- }
- }
- else
-#endif
- {
- vuint<K>::storeu(valid, primID(offset), ray.primID);
- vuint<K>::storeu(valid, geomID(offset), ray.geomID);
-
- vuint<K>::storeu(valid, instID(0, offset), ray.instID[0]);
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
- vuint<K>::storeu(valid, instID(l, offset), ray.instID[l]);
-#endif
- }
- }
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, size_t offset, const RayK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.tfar < 0.0f);
-
- if (likely(any(valid)))
- vfloat<K>::storeu(valid, tfar(offset), ray.tfar);
- }
-
- __forceinline size_t getOctantByOffset(size_t offset)
- {
- const float dx = dir_x(offset)[0];
- const float dy = dir_y(offset)[0];
- const float dz = dir_z(offset)[0];
- const size_t octantID = (dx < 0.0f ? 1 : 0) + (dy < 0.0f ? 2 : 0) + (dz < 0.0f ? 4 : 0);
- return octantID;
- }
-
- __forceinline bool isValidByOffset(size_t offset)
- {
- const float nnear = tnear(offset)[0];
- const float ffar = tfar(offset)[0];
- return nnear <= ffar;
- }
-
- template<int K>
- __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, const vint<K>& offset)
- {
- RayK<K> ray;
-
-#if defined(__AVX2__)
- ray.org.x = vfloat<K>::template gather<1>(valid, org_x(), offset);
- ray.org.y = vfloat<K>::template gather<1>(valid, org_y(), offset);
- ray.org.z = vfloat<K>::template gather<1>(valid, org_z(), offset);
- ray.tnear() = vfloat<K>::template gather<1>(valid, tnear(), offset);
- ray.dir.x = vfloat<K>::template gather<1>(valid, dir_x(), offset);
- ray.dir.y = vfloat<K>::template gather<1>(valid, dir_y(), offset);
- ray.dir.z = vfloat<K>::template gather<1>(valid, dir_z(), offset);
- ray.time() = vfloat<K>::template gather<1>(valid, time(), offset);
- ray.tfar = vfloat<K>::template gather<1>(valid, tfar(), offset);
- ray.mask = vint<K>::template gather<1>(valid, mask(), offset);
- ray.id = vint<K>::template gather<1>(valid, id(), offset);
- ray.flags = vint<K>::template gather<1>(valid, flags(), offset);
-#else
- ray.org = zero;
- ray.tnear() = zero;
- ray.dir = zero;
- ray.time() = zero;
- ray.tfar = zero;
- ray.mask = zero;
- ray.id = zero;
- ray.flags = zero;
-
- for (size_t k = 0; k < K; k++)
- {
- if (likely(valid[k]))
- {
- const size_t ofs = offset[k];
-
- ray.org.x[k] = *org_x(ofs);
- ray.org.y[k] = *org_y(ofs);
- ray.org.z[k] = *org_z(ofs);
- ray.tnear()[k] = *tnear(ofs);
- ray.dir.x[k] = *dir_x(ofs);
- ray.dir.y[k] = *dir_y(ofs);
- ray.dir.z[k] = *dir_z(ofs);
- ray.time()[k] = *time(ofs);
- ray.tfar[k] = *tfar(ofs);
- ray.mask[k] = *mask(ofs);
- ray.id[k] = *id(ofs);
- ray.flags[k] = *flags(ofs);
- }
- }
-#endif
-
- return ray;
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayHitK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
-
- if (likely(any(valid)))
- {
-#if defined(__AVX512F__)
- vfloat<K>::template scatter<1>(valid, tfar(), offset, ray.tfar);
- vfloat<K>::template scatter<1>(valid, Ng_x(), offset, ray.Ng.x);
- vfloat<K>::template scatter<1>(valid, Ng_y(), offset, ray.Ng.y);
- vfloat<K>::template scatter<1>(valid, Ng_z(), offset, ray.Ng.z);
- vfloat<K>::template scatter<1>(valid, u(), offset, ray.u);
- vfloat<K>::template scatter<1>(valid, v(), offset, ray.v);
- vuint<K>::template scatter<1>(valid, primID(), offset, ray.primID);
- vuint<K>::template scatter<1>(valid, geomID(), offset, ray.geomID);
-
- vuint<K>::template scatter<1>(valid, instID(0), offset, ray.instID[0]);
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
- vuint<K>::template scatter<1>(valid, instID(l), offset, ray.instID[l]);
-#endif
-#else
- size_t valid_bits = movemask(valid);
- while (valid_bits != 0)
- {
- const size_t k = bscf(valid_bits);
- const size_t ofs = offset[k];
-
- *tfar(ofs) = ray.tfar[k];
-
- *Ng_x(ofs) = ray.Ng.x[k];
- *Ng_y(ofs) = ray.Ng.y[k];
- *Ng_z(ofs) = ray.Ng.z[k];
- *u(ofs) = ray.u[k];
- *v(ofs) = ray.v[k];
- *primID(ofs) = ray.primID[k];
- *geomID(ofs) = ray.geomID[k];
-
- *instID(0, ofs) = ray.instID[0][k];
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && ray.instID[l-1][k] != RTC_INVALID_GEOMETRY_ID; ++l)
- *instID(l, ofs) = ray.instID[l][k];
-#endif
- }
-#endif
- }
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.tfar < 0.0f);
-
- if (likely(any(valid)))
- {
-#if defined(__AVX512F__)
- vfloat<K>::template scatter<1>(valid, tfar(), offset, ray.tfar);
-#else
- size_t valid_bits = movemask(valid);
- while (valid_bits != 0)
- {
- const size_t k = bscf(valid_bits);
- const size_t ofs = offset[k];
-
- *tfar(ofs) = ray.tfar[k];
- }
-#endif
- }
- }
-
- char* __restrict__ ptr;
- size_t N;
- };
-
- template<size_t MAX_K>
- struct StackRayStreamSOA : public RayStreamSOA
- {
- __forceinline StackRayStreamSOA(size_t K)
- : RayStreamSOA(data, K) { assert(K <= MAX_K); }
-
- char data[MAX_K / 4 * sizeof(RayHit4)];
- };
-
-
- struct RayStreamSOP
- {
- template<class T>
- __forceinline void init(T& t)
- {
- org_x = (float*)&t.org.x;
- org_y = (float*)&t.org.y;
- org_z = (float*)&t.org.z;
- tnear = (float*)&t.tnear;
- dir_x = (float*)&t.dir.x;
- dir_y = (float*)&t.dir.y;
- dir_z = (float*)&t.dir.z;
- time = (float*)&t.time;
- tfar = (float*)&t.tfar;
- mask = (unsigned int*)&t.mask;
- id = (unsigned int*)&t.id;
- flags = (unsigned int*)&t.flags;
-
- Ng_x = (float*)&t.Ng.x;
- Ng_y = (float*)&t.Ng.y;
- Ng_z = (float*)&t.Ng.z;
- u = (float*)&t.u;
- v = (float*)&t.v;
- primID = (unsigned int*)&t.primID;
- geomID = (unsigned int*)&t.geomID;
-
- for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
- instID[l] = (unsigned int*)&t.instID[l];
- }
-
- __forceinline Ray getRayByOffset(size_t offset)
- {
- Ray ray;
- ray.org.x = *(float* __restrict__)((char*)org_x + offset);
- ray.org.y = *(float* __restrict__)((char*)org_y + offset);
- ray.org.z = *(float* __restrict__)((char*)org_z + offset);
- ray.dir.x = *(float* __restrict__)((char*)dir_x + offset);
- ray.dir.y = *(float* __restrict__)((char*)dir_y + offset);
- ray.dir.z = *(float* __restrict__)((char*)dir_z + offset);
- ray.tfar = *(float* __restrict__)((char*)tfar + offset);
- ray.tnear() = tnear ? *(float* __restrict__)((char*)tnear + offset) : 0.0f;
- ray.time() = time ? *(float* __restrict__)((char*)time + offset) : 0.0f;
- ray.mask = mask ? *(unsigned int* __restrict__)((char*)mask + offset) : -1;
- ray.id = id ? *(unsigned int* __restrict__)((char*)id + offset) : -1;
- ray.flags = flags ? *(unsigned int* __restrict__)((char*)flags + offset) : -1;
- return ray;
- }
-
- template<int K>
- __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, size_t offset)
- {
- RayK<K> ray;
- ray.org.x = vfloat<K>::loadu(valid, (float* __restrict__)((char*)org_x + offset));
- ray.org.y = vfloat<K>::loadu(valid, (float* __restrict__)((char*)org_y + offset));
- ray.org.z = vfloat<K>::loadu(valid, (float* __restrict__)((char*)org_z + offset));
- ray.dir.x = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_x + offset));
- ray.dir.y = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_y + offset));
- ray.dir.z = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_z + offset));
- ray.tfar = vfloat<K>::loadu(valid, (float* __restrict__)((char*)tfar + offset));
- ray.tnear() = tnear ? vfloat<K>::loadu(valid, (float* __restrict__)((char*)tnear + offset)) : 0.0f;
- ray.time() = time ? vfloat<K>::loadu(valid, (float* __restrict__)((char*)time + offset)) : 0.0f;
- ray.mask = mask ? vint<K>::loadu(valid, (const void* __restrict__)((char*)mask + offset)) : -1;
- ray.id = id ? vint<K>::loadu(valid, (const void* __restrict__)((char*)id + offset)) : -1;
- ray.flags = flags ? vint<K>::loadu(valid, (const void* __restrict__)((char*)flags + offset)) : -1;
- return ray;
- }
-
- template<int K>
- __forceinline Vec3vf<K> getDirByOffset(const vbool<K>& valid, size_t offset)
- {
- Vec3vf<K> dir;
- dir.x = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_x + offset));
- dir.y = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_y + offset));
- dir.z = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_z + offset));
- return dir;
- }
-
- __forceinline void setHitByOffset(size_t offset, const RayHit& ray)
- {
- if (ray.geomID != RTC_INVALID_GEOMETRY_ID)
- {
- *(float* __restrict__)((char*)tfar + offset) = ray.tfar;
-
- if (likely(Ng_x)) *(float* __restrict__)((char*)Ng_x + offset) = ray.Ng.x;
- if (likely(Ng_y)) *(float* __restrict__)((char*)Ng_y + offset) = ray.Ng.y;
- if (likely(Ng_z)) *(float* __restrict__)((char*)Ng_z + offset) = ray.Ng.z;
- *(float* __restrict__)((char*)u + offset) = ray.u;
- *(float* __restrict__)((char*)v + offset) = ray.v;
- *(unsigned int* __restrict__)((char*)geomID + offset) = ray.geomID;
- *(unsigned int* __restrict__)((char*)primID + offset) = ray.primID;
-
- if (likely(instID[0])) {
- *(unsigned int* __restrict__)((char*)instID[0] + offset) = ray.instID[0];
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID; ++l)
- *(unsigned int* __restrict__)((char*)instID[l] + offset) = ray.instID[l];
-#endif
- }
- }
- }
-
- __forceinline void setHitByOffset(size_t offset, const Ray& ray)
- {
- *(float* __restrict__)((char*)tfar + offset) = ray.tfar;
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, size_t offset, const RayHitK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
-
- if (likely(any(valid)))
- {
- vfloat<K>::storeu(valid, (float* __restrict__)((char*)tfar + offset), ray.tfar);
-
- if (likely(Ng_x)) vfloat<K>::storeu(valid, (float* __restrict__)((char*)Ng_x + offset), ray.Ng.x);
- if (likely(Ng_y)) vfloat<K>::storeu(valid, (float* __restrict__)((char*)Ng_y + offset), ray.Ng.y);
- if (likely(Ng_z)) vfloat<K>::storeu(valid, (float* __restrict__)((char*)Ng_z + offset), ray.Ng.z);
- vfloat<K>::storeu(valid, (float* __restrict__)((char*)u + offset), ray.u);
- vfloat<K>::storeu(valid, (float* __restrict__)((char*)v + offset), ray.v);
- vuint<K>::storeu(valid, (unsigned int* __restrict__)((char*)primID + offset), ray.primID);
- vuint<K>::storeu(valid, (unsigned int* __restrict__)((char*)geomID + offset), ray.geomID);
-
- if (likely(instID[0])) {
- vuint<K>::storeu(valid, (unsigned int* __restrict__)((char*)instID[0] + offset), ray.instID[0]);
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
- vuint<K>::storeu(valid, (unsigned int* __restrict__)((char*)instID[l] + offset), ray.instID[l]);
-#endif
- }
- }
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, size_t offset, const RayK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.tfar < 0.0f);
-
- if (likely(any(valid)))
- vfloat<K>::storeu(valid, (float* __restrict__)((char*)tfar + offset), ray.tfar);
- }
-
- __forceinline size_t getOctantByOffset(size_t offset)
- {
- const float dx = *(float* __restrict__)((char*)dir_x + offset);
- const float dy = *(float* __restrict__)((char*)dir_y + offset);
- const float dz = *(float* __restrict__)((char*)dir_z + offset);
- const size_t octantID = (dx < 0.0f ? 1 : 0) + (dy < 0.0f ? 2 : 0) + (dz < 0.0f ? 4 : 0);
- return octantID;
- }
-
- __forceinline bool isValidByOffset(size_t offset)
- {
- const float nnear = tnear ? *(float* __restrict__)((char*)tnear + offset) : 0.0f;
- const float ffar = *(float* __restrict__)((char*)tfar + offset);
- return nnear <= ffar;
- }
-
- template<int K>
- __forceinline vbool<K> isValidByOffset(const vbool<K>& valid, size_t offset)
- {
- const vfloat<K> nnear = tnear ? vfloat<K>::loadu(valid, (float* __restrict__)((char*)tnear + offset)) : 0.0f;
- const vfloat<K> ffar = vfloat<K>::loadu(valid, (float* __restrict__)((char*)tfar + offset));
- return nnear <= ffar;
- }
-
- template<int K>
- __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, const vint<K>& offset)
- {
- RayK<K> ray;
-
-#if defined(__AVX2__)
- ray.org.x = vfloat<K>::template gather<1>(valid, org_x, offset);
- ray.org.y = vfloat<K>::template gather<1>(valid, org_y, offset);
- ray.org.z = vfloat<K>::template gather<1>(valid, org_z, offset);
- ray.dir.x = vfloat<K>::template gather<1>(valid, dir_x, offset);
- ray.dir.y = vfloat<K>::template gather<1>(valid, dir_y, offset);
- ray.dir.z = vfloat<K>::template gather<1>(valid, dir_z, offset);
- ray.tfar = vfloat<K>::template gather<1>(valid, tfar, offset);
- ray.tnear() = tnear ? vfloat<K>::template gather<1>(valid, tnear, offset) : vfloat<K>(zero);
- ray.time() = time ? vfloat<K>::template gather<1>(valid, time, offset) : vfloat<K>(zero);
- ray.mask = mask ? vint<K>::template gather<1>(valid, (int*)mask, offset) : vint<K>(-1);
- ray.id = id ? vint<K>::template gather<1>(valid, (int*)id, offset) : vint<K>(-1);
- ray.flags = flags ? vint<K>::template gather<1>(valid, (int*)flags, offset) : vint<K>(-1);
-#else
- ray.org = zero;
- ray.tnear() = zero;
- ray.dir = zero;
- ray.tfar = zero;
- ray.time() = zero;
- ray.mask = zero;
- ray.id = zero;
- ray.flags = zero;
-
- for (size_t k = 0; k < K; k++)
- {
- if (likely(valid[k]))
- {
- const size_t ofs = offset[k];
-
- ray.org.x[k] = *(float* __restrict__)((char*)org_x + ofs);
- ray.org.y[k] = *(float* __restrict__)((char*)org_y + ofs);
- ray.org.z[k] = *(float* __restrict__)((char*)org_z + ofs);
- ray.dir.x[k] = *(float* __restrict__)((char*)dir_x + ofs);
- ray.dir.y[k] = *(float* __restrict__)((char*)dir_y + ofs);
- ray.dir.z[k] = *(float* __restrict__)((char*)dir_z + ofs);
- ray.tfar[k] = *(float* __restrict__)((char*)tfar + ofs);
- ray.tnear()[k] = tnear ? *(float* __restrict__)((char*)tnear + ofs) : 0.0f;
- ray.time()[k] = time ? *(float* __restrict__)((char*)time + ofs) : 0.0f;
- ray.mask[k] = mask ? *(int* __restrict__)((char*)mask + ofs) : -1;
- ray.id[k] = id ? *(int* __restrict__)((char*)id + ofs) : -1;
- ray.flags[k] = flags ? *(int* __restrict__)((char*)flags + ofs) : -1;
- }
- }
-#endif
-
- return ray;
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayHitK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
-
- if (likely(any(valid)))
- {
-#if defined(__AVX512F__)
- vfloat<K>::template scatter<1>(valid, tfar, offset, ray.tfar);
-
- if (likely(Ng_x)) vfloat<K>::template scatter<1>(valid, Ng_x, offset, ray.Ng.x);
- if (likely(Ng_y)) vfloat<K>::template scatter<1>(valid, Ng_y, offset, ray.Ng.y);
- if (likely(Ng_z)) vfloat<K>::template scatter<1>(valid, Ng_z, offset, ray.Ng.z);
- vfloat<K>::template scatter<1>(valid, u, offset, ray.u);
- vfloat<K>::template scatter<1>(valid, v, offset, ray.v);
- vuint<K>::template scatter<1>(valid, (unsigned int*)geomID, offset, ray.geomID);
- vuint<K>::template scatter<1>(valid, (unsigned int*)primID, offset, ray.primID);
-
- if (likely(instID[0])) {
- vuint<K>::template scatter<1>(valid, (unsigned int*)instID[0], offset, ray.instID[0]);
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
- vuint<K>::template scatter<1>(valid, (unsigned int*)instID[l], offset, ray.instID[l]);
-#endif
- }
-#else
- size_t valid_bits = movemask(valid);
- while (valid_bits != 0)
- {
- const size_t k = bscf(valid_bits);
- const size_t ofs = offset[k];
-
- *(float* __restrict__)((char*)tfar + ofs) = ray.tfar[k];
-
- if (likely(Ng_x)) *(float* __restrict__)((char*)Ng_x + ofs) = ray.Ng.x[k];
- if (likely(Ng_y)) *(float* __restrict__)((char*)Ng_y + ofs) = ray.Ng.y[k];
- if (likely(Ng_z)) *(float* __restrict__)((char*)Ng_z + ofs) = ray.Ng.z[k];
- *(float* __restrict__)((char*)u + ofs) = ray.u[k];
- *(float* __restrict__)((char*)v + ofs) = ray.v[k];
- *(unsigned int* __restrict__)((char*)primID + ofs) = ray.primID[k];
- *(unsigned int* __restrict__)((char*)geomID + ofs) = ray.geomID[k];
-
- if (likely(instID[0])) {
- *(unsigned int* __restrict__)((char*)instID[0] + ofs) = ray.instID[0][k];
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && ray.instID[l-1][k] != RTC_INVALID_GEOMETRY_ID; ++l)
- *(unsigned int* __restrict__)((char*)instID[l] + ofs) = ray.instID[l][k];
-#endif
- }
- }
-#endif
- }
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.tfar < 0.0f);
-
- if (likely(any(valid)))
- {
-#if defined(__AVX512F__)
- vfloat<K>::template scatter<1>(valid, tfar, offset, ray.tfar);
-#else
- size_t valid_bits = movemask(valid);
- while (valid_bits != 0)
- {
- const size_t k = bscf(valid_bits);
- const size_t ofs = offset[k];
-
- *(float* __restrict__)((char*)tfar + ofs) = ray.tfar[k];
- }
-#endif
- }
- }
-
- /* ray data */
- float* __restrict__ org_x; // x coordinate of ray origin
- float* __restrict__ org_y; // y coordinate of ray origin
- float* __restrict__ org_z; // z coordinate of ray origin
- float* __restrict__ tnear; // start of ray segment (optional)
-
- float* __restrict__ dir_x; // x coordinate of ray direction
- float* __restrict__ dir_y; // y coordinate of ray direction
- float* __restrict__ dir_z; // z coordinate of ray direction
- float* __restrict__ time; // time of this ray for motion blur (optional)
-
- float* __restrict__ tfar; // end of ray segment (set to hit distance)
- unsigned int* __restrict__ mask; // used to mask out objects during traversal (optional)
- unsigned int* __restrict__ id; // ray ID
- unsigned int* __restrict__ flags; // ray flags
-
- /* hit data */
- float* __restrict__ Ng_x; // x coordinate of geometry normal (optional)
- float* __restrict__ Ng_y; // y coordinate of geometry normal (optional)
- float* __restrict__ Ng_z; // z coordinate of geometry normal (optional)
-
- float* __restrict__ u; // barycentric u coordinate of hit
- float* __restrict__ v; // barycentric v coordinate of hit
-
- unsigned int* __restrict__ primID; // primitive ID
- unsigned int* __restrict__ geomID; // geometry ID
- unsigned int* __restrict__ instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID (optional)
- };
-
-
- struct RayStreamAOS
- {
- __forceinline RayStreamAOS(void* rays)
- : ptr((Ray*)rays) {}
-
- __forceinline Ray& getRayByOffset(size_t offset)
- {
- return *(Ray*)((char*)ptr + offset);
- }
-
- template<int K>
- __forceinline RayK<K> getRayByOffset(const vint<K>& offset);
-
- template<int K>
- __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, const vint<K>& offset)
- {
- const vint<K> valid_offset = select(valid, offset, vintx(zero));
- return getRayByOffset(valid_offset);
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayHitK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
-
- if (likely(any(valid)))
- {
-#if defined(__AVX512F__)
- vfloat<K>::template scatter<1>(valid, &ptr->tfar, offset, ray.tfar);
- vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->Ng.x, offset, ray.Ng.x);
- vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->Ng.y, offset, ray.Ng.y);
- vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->Ng.z, offset, ray.Ng.z);
- vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->u, offset, ray.u);
- vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->v, offset, ray.v);
- vuint<K>::template scatter<1>(valid, (unsigned int*)&((RayHit*)ptr)->primID, offset, ray.primID);
- vuint<K>::template scatter<1>(valid, (unsigned int*)&((RayHit*)ptr)->geomID, offset, ray.geomID);
-
- vuint<K>::template scatter<1>(valid, (unsigned int*)&((RayHit*)ptr)->instID[0], offset, ray.instID[0]);
-#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
- for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
- vuint<K>::template scatter<1>(valid, (unsigned int*)&((RayHit*)ptr)->instID[l], offset, ray.instID[l]);
-#endif
-#else
- size_t valid_bits = movemask(valid);
- while (valid_bits != 0)
- {
- const size_t k = bscf(valid_bits);
- RayHit* __restrict__ ray_k = (RayHit*)((char*)ptr + offset[k]);
- ray_k->tfar = ray.tfar[k];
- ray_k->Ng.x = ray.Ng.x[k];
- ray_k->Ng.y = ray.Ng.y[k];
- ray_k->Ng.z = ray.Ng.z[k];
- ray_k->u = ray.u[k];
- ray_k->v = ray.v[k];
- ray_k->primID = ray.primID[k];
- ray_k->geomID = ray.geomID[k];
-
- instance_id_stack::copy(ray.instID, ray_k->instID, k);
- }
-#endif
- }
- }
-
- template<int K>
- __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.tfar < 0.0f);
-
- if (likely(any(valid)))
- {
-#if defined(__AVX512F__)
- vfloat<K>::template scatter<1>(valid, &ptr->tfar, offset, ray.tfar);
-#else
- size_t valid_bits = movemask(valid);
- while (valid_bits != 0)
- {
- const size_t k = bscf(valid_bits);
- Ray* __restrict__ ray_k = (Ray*)((char*)ptr + offset[k]);
- ray_k->tfar = ray.tfar[k];
- }
-#endif
- }
- }
-
- Ray* __restrict__ ptr;
- };
-
- template<>
- __forceinline Ray4 RayStreamAOS::getRayByOffset(const vint4& offset)
- {
- Ray4 ray;
-
- /* load and transpose: org.x, org.y, org.z, tnear */
- const vfloat4 a0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[0]))->org);
- const vfloat4 a1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[1]))->org);
- const vfloat4 a2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[2]))->org);
- const vfloat4 a3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[3]))->org);
-
- transpose(a0,a1,a2,a3, ray.org.x, ray.org.y, ray.org.z, ray.tnear());
-
- /* load and transpose: dir.x, dir.y, dir.z, time */
- const vfloat4 b0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[0]))->dir);
- const vfloat4 b1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[1]))->dir);
- const vfloat4 b2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[2]))->dir);
- const vfloat4 b3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[3]))->dir);
-
- transpose(b0,b1,b2,b3, ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
-
- /* load and transpose: tfar, mask, id, flags */
- const vfloat4 c0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[0]))->tfar);
- const vfloat4 c1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[1]))->tfar);
- const vfloat4 c2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[2]))->tfar);
- const vfloat4 c3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[3]))->tfar);
-
- vfloat4 maskf, idf, flagsf;
- transpose(c0,c1,c2,c3, ray.tfar, maskf, idf, flagsf);
- ray.mask = asInt(maskf);
- ray.id = asInt(idf);
- ray.flags = asInt(flagsf);
-
- return ray;
- }
-
-#if defined(__AVX__)
- template<>
- __forceinline Ray8 RayStreamAOS::getRayByOffset(const vint8& offset)
- {
- Ray8 ray;
-
- /* load and transpose: org.x, org.y, org.z, tnear, dir.x, dir.y, dir.z, time */
- const vfloat8 ab0 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[0]))->org);
- const vfloat8 ab1 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[1]))->org);
- const vfloat8 ab2 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[2]))->org);
- const vfloat8 ab3 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[3]))->org);
- const vfloat8 ab4 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[4]))->org);
- const vfloat8 ab5 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[5]))->org);
- const vfloat8 ab6 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[6]))->org);
- const vfloat8 ab7 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[7]))->org);
-
- transpose(ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7, ray.org.x, ray.org.y, ray.org.z, ray.tnear(), ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
-
- /* load and transpose: tfar, mask, id, flags */
- const vfloat4 c0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[0]))->tfar);
- const vfloat4 c1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[1]))->tfar);
- const vfloat4 c2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[2]))->tfar);
- const vfloat4 c3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[3]))->tfar);
- const vfloat4 c4 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[4]))->tfar);
- const vfloat4 c5 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[5]))->tfar);
- const vfloat4 c6 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[6]))->tfar);
- const vfloat4 c7 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[7]))->tfar);
-
- vfloat8 maskf, idf, flagsf;
- transpose(c0,c1,c2,c3,c4,c5,c6,c7, ray.tfar, maskf, idf, flagsf);
- ray.mask = asInt(maskf);
- ray.id = asInt(idf);
- ray.flags = asInt(flagsf);
-
- return ray;
- }
-#endif
-
-#if defined(__AVX512F__)
- template<>
- __forceinline Ray16 RayStreamAOS::getRayByOffset(const vint16& offset)
- {
- Ray16 ray;
-
- /* load and transpose: org.x, org.y, org.z, tnear, dir.x, dir.y, dir.z, time */
- const vfloat8 ab0 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 0]))->org);
- const vfloat8 ab1 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 1]))->org);
- const vfloat8 ab2 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 2]))->org);
- const vfloat8 ab3 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 3]))->org);
- const vfloat8 ab4 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 4]))->org);
- const vfloat8 ab5 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 5]))->org);
- const vfloat8 ab6 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 6]))->org);
- const vfloat8 ab7 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 7]))->org);
- const vfloat8 ab8 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 8]))->org);
- const vfloat8 ab9 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 9]))->org);
- const vfloat8 ab10 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[10]))->org);
- const vfloat8 ab11 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[11]))->org);
- const vfloat8 ab12 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[12]))->org);
- const vfloat8 ab13 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[13]))->org);
- const vfloat8 ab14 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[14]))->org);
- const vfloat8 ab15 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[15]))->org);
-
- transpose(ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7,ab8,ab9,ab10,ab11,ab12,ab13,ab14,ab15,
- ray.org.x, ray.org.y, ray.org.z, ray.tnear(), ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
-
- /* load and transpose: tfar, mask, id, flags */
- const vfloat4 c0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 0]))->tfar);
- const vfloat4 c1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 1]))->tfar);
- const vfloat4 c2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 2]))->tfar);
- const vfloat4 c3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 3]))->tfar);
- const vfloat4 c4 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 4]))->tfar);
- const vfloat4 c5 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 5]))->tfar);
- const vfloat4 c6 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 6]))->tfar);
- const vfloat4 c7 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 7]))->tfar);
- const vfloat4 c8 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 8]))->tfar);
- const vfloat4 c9 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 9]))->tfar);
- const vfloat4 c10 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[10]))->tfar);
- const vfloat4 c11 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[11]))->tfar);
- const vfloat4 c12 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[12]))->tfar);
- const vfloat4 c13 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[13]))->tfar);
- const vfloat4 c14 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[14]))->tfar);
- const vfloat4 c15 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[15]))->tfar);
-
- vfloat16 maskf, idf, flagsf;
- transpose(c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,
- ray.tfar, maskf, idf, flagsf);
- ray.mask = asInt(maskf);
- ray.id = asInt(idf);
- ray.flags = asInt(flagsf);
-
- return ray;
- }
-#endif
-
-
- struct RayStreamAOP
- {
- __forceinline RayStreamAOP(void* rays)
- : ptr((Ray**)rays) {}
-
- __forceinline Ray& getRayByIndex(size_t index)
- {
- return *ptr[index];
- }
-
- template<int K>
- __forceinline RayK<K> getRayByIndex(const vint<K>& index);
-
- template<int K>
- __forceinline RayK<K> getRayByIndex(const vbool<K>& valid, const vint<K>& index)
- {
- const vint<K> valid_index = select(valid, index, vintx(zero));
- return getRayByIndex(valid_index);
- }
-
- template<int K>
- __forceinline void setHitByIndex(const vbool<K>& valid_i, const vint<K>& index, const RayHitK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
-
- if (likely(any(valid)))
- {
- size_t valid_bits = movemask(valid);
- while (valid_bits != 0)
- {
- const size_t k = bscf(valid_bits);
- RayHit* __restrict__ ray_k = (RayHit*)ptr[index[k]];
-
- ray_k->tfar = ray.tfar[k];
- ray_k->Ng.x = ray.Ng.x[k];
- ray_k->Ng.y = ray.Ng.y[k];
- ray_k->Ng.z = ray.Ng.z[k];
- ray_k->u = ray.u[k];
- ray_k->v = ray.v[k];
- ray_k->primID = ray.primID[k];
- ray_k->geomID = ray.geomID[k];
- instance_id_stack::copy(ray.instID, ray_k->instID, k);
- }
- }
- }
-
- template<int K>
- __forceinline void setHitByIndex(const vbool<K>& valid_i, const vint<K>& index, const RayK<K>& ray)
- {
- vbool<K> valid = valid_i;
- valid &= (ray.tfar < 0.0f);
-
- if (likely(any(valid)))
- {
- size_t valid_bits = movemask(valid);
- while (valid_bits != 0)
- {
- const size_t k = bscf(valid_bits);
- Ray* __restrict__ ray_k = ptr[index[k]];
-
- ray_k->tfar = ray.tfar[k];
- }
- }
- }
-
- Ray** __restrict__ ptr;
- };
-
- template<>
- __forceinline Ray4 RayStreamAOP::getRayByIndex(const vint4& index)
- {
- Ray4 ray;
-
- /* load and transpose: org.x, org.y, org.z, tnear */
- const vfloat4 a0 = vfloat4::loadu(&ptr[index[0]]->org);
- const vfloat4 a1 = vfloat4::loadu(&ptr[index[1]]->org);
- const vfloat4 a2 = vfloat4::loadu(&ptr[index[2]]->org);
- const vfloat4 a3 = vfloat4::loadu(&ptr[index[3]]->org);
-
- transpose(a0,a1,a2,a3, ray.org.x, ray.org.y, ray.org.z, ray.tnear());
-
- /* load and transpose: dir.x, dir.y, dir.z, time */
- const vfloat4 b0 = vfloat4::loadu(&ptr[index[0]]->dir);
- const vfloat4 b1 = vfloat4::loadu(&ptr[index[1]]->dir);
- const vfloat4 b2 = vfloat4::loadu(&ptr[index[2]]->dir);
- const vfloat4 b3 = vfloat4::loadu(&ptr[index[3]]->dir);
-
- transpose(b0,b1,b2,b3, ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
-
- /* load and transpose: tfar, mask, id, flags */
- const vfloat4 c0 = vfloat4::loadu(&ptr[index[0]]->tfar);
- const vfloat4 c1 = vfloat4::loadu(&ptr[index[1]]->tfar);
- const vfloat4 c2 = vfloat4::loadu(&ptr[index[2]]->tfar);
- const vfloat4 c3 = vfloat4::loadu(&ptr[index[3]]->tfar);
-
- vfloat4 maskf, idf, flagsf;
- transpose(c0,c1,c2,c3, ray.tfar, maskf, idf, flagsf);
- ray.mask = asInt(maskf);
- ray.id = asInt(idf);
- ray.flags = asInt(flagsf);
-
- return ray;
- }
-
-#if defined(__AVX__)
- template<>
- __forceinline Ray8 RayStreamAOP::getRayByIndex(const vint8& index)
- {
- Ray8 ray;
-
- /* load and transpose: org.x, org.y, org.z, tnear, dir.x, dir.y, dir.z, time */
- const vfloat8 ab0 = vfloat8::loadu(&ptr[index[0]]->org);
- const vfloat8 ab1 = vfloat8::loadu(&ptr[index[1]]->org);
- const vfloat8 ab2 = vfloat8::loadu(&ptr[index[2]]->org);
- const vfloat8 ab3 = vfloat8::loadu(&ptr[index[3]]->org);
- const vfloat8 ab4 = vfloat8::loadu(&ptr[index[4]]->org);
- const vfloat8 ab5 = vfloat8::loadu(&ptr[index[5]]->org);
- const vfloat8 ab6 = vfloat8::loadu(&ptr[index[6]]->org);
- const vfloat8 ab7 = vfloat8::loadu(&ptr[index[7]]->org);
-
- transpose(ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7, ray.org.x, ray.org.y, ray.org.z, ray.tnear(), ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
-
- /* load and transpose: tfar, mask, id, flags */
- const vfloat4 c0 = vfloat4::loadu(&ptr[index[0]]->tfar);
- const vfloat4 c1 = vfloat4::loadu(&ptr[index[1]]->tfar);
- const vfloat4 c2 = vfloat4::loadu(&ptr[index[2]]->tfar);
- const vfloat4 c3 = vfloat4::loadu(&ptr[index[3]]->tfar);
- const vfloat4 c4 = vfloat4::loadu(&ptr[index[4]]->tfar);
- const vfloat4 c5 = vfloat4::loadu(&ptr[index[5]]->tfar);
- const vfloat4 c6 = vfloat4::loadu(&ptr[index[6]]->tfar);
- const vfloat4 c7 = vfloat4::loadu(&ptr[index[7]]->tfar);
-
- vfloat8 maskf, idf, flagsf;
- transpose(c0,c1,c2,c3,c4,c5,c6,c7, ray.tfar, maskf, idf, flagsf);
- ray.mask = asInt(maskf);
- ray.id = asInt(idf);
- ray.flags = asInt(flagsf);
-
- return ray;
- }
-#endif
-
-#if defined(__AVX512F__)
- template<>
- __forceinline Ray16 RayStreamAOP::getRayByIndex(const vint16& index)
- {
- Ray16 ray;
-
- /* load and transpose: org.x, org.y, org.z, tnear, dir.x, dir.y, dir.z, time */
- const vfloat8 ab0 = vfloat8::loadu(&ptr[index[0]]->org);
- const vfloat8 ab1 = vfloat8::loadu(&ptr[index[1]]->org);
- const vfloat8 ab2 = vfloat8::loadu(&ptr[index[2]]->org);
- const vfloat8 ab3 = vfloat8::loadu(&ptr[index[3]]->org);
- const vfloat8 ab4 = vfloat8::loadu(&ptr[index[4]]->org);
- const vfloat8 ab5 = vfloat8::loadu(&ptr[index[5]]->org);
- const vfloat8 ab6 = vfloat8::loadu(&ptr[index[6]]->org);
- const vfloat8 ab7 = vfloat8::loadu(&ptr[index[7]]->org);
- const vfloat8 ab8 = vfloat8::loadu(&ptr[index[8]]->org);
- const vfloat8 ab9 = vfloat8::loadu(&ptr[index[9]]->org);
- const vfloat8 ab10 = vfloat8::loadu(&ptr[index[10]]->org);
- const vfloat8 ab11 = vfloat8::loadu(&ptr[index[11]]->org);
- const vfloat8 ab12 = vfloat8::loadu(&ptr[index[12]]->org);
- const vfloat8 ab13 = vfloat8::loadu(&ptr[index[13]]->org);
- const vfloat8 ab14 = vfloat8::loadu(&ptr[index[14]]->org);
- const vfloat8 ab15 = vfloat8::loadu(&ptr[index[15]]->org);
-
- transpose(ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7,ab8,ab9,ab10,ab11,ab12,ab13,ab14,ab15,
- ray.org.x, ray.org.y, ray.org.z, ray.tnear(), ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
-
- /* load and transpose: tfar, mask, id, flags */
- const vfloat4 c0 = vfloat4::loadu(&ptr[index[0]]->tfar);
- const vfloat4 c1 = vfloat4::loadu(&ptr[index[1]]->tfar);
- const vfloat4 c2 = vfloat4::loadu(&ptr[index[2]]->tfar);
- const vfloat4 c3 = vfloat4::loadu(&ptr[index[3]]->tfar);
- const vfloat4 c4 = vfloat4::loadu(&ptr[index[4]]->tfar);
- const vfloat4 c5 = vfloat4::loadu(&ptr[index[5]]->tfar);
- const vfloat4 c6 = vfloat4::loadu(&ptr[index[6]]->tfar);
- const vfloat4 c7 = vfloat4::loadu(&ptr[index[7]]->tfar);
- const vfloat4 c8 = vfloat4::loadu(&ptr[index[8]]->tfar);
- const vfloat4 c9 = vfloat4::loadu(&ptr[index[9]]->tfar);
- const vfloat4 c10 = vfloat4::loadu(&ptr[index[10]]->tfar);
- const vfloat4 c11 = vfloat4::loadu(&ptr[index[11]]->tfar);
- const vfloat4 c12 = vfloat4::loadu(&ptr[index[12]]->tfar);
- const vfloat4 c13 = vfloat4::loadu(&ptr[index[13]]->tfar);
- const vfloat4 c14 = vfloat4::loadu(&ptr[index[14]]->tfar);
- const vfloat4 c15 = vfloat4::loadu(&ptr[index[15]]->tfar);
-
- vfloat16 maskf, idf, flagsf;
- transpose(c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,
- ray.tfar, maskf, idf, flagsf);
-
- ray.mask = asInt(maskf);
- ray.id = asInt(idf);
- ray.flags = asInt(flagsf);
-
- return ray;
- }
-#endif
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/rtcore.cpp b/thirdparty/embree-aarch64/kernels/common/rtcore.cpp
deleted file mode 100644
index 625fbf6d4f..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/rtcore.cpp
+++ /dev/null
@@ -1,1799 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#define RTC_EXPORT_API
-
-#include "default.h"
-#include "device.h"
-#include "scene.h"
-#include "context.h"
-#include "../../include/embree3/rtcore_ray.h"
-
-#if defined(__aarch64__) && defined(BUILD_IOS)
-#include <mutex>
-#endif
-
-using namespace embree;
-
-RTC_NAMESPACE_BEGIN;
-
- /* mutex to make API thread safe */
-#if defined(__aarch64__) && defined(BUILD_IOS)
- static std::mutex g_mutex;
-#else
- static MutexSys g_mutex;
-#endif
-
- RTC_API RTCDevice rtcNewDevice(const char* config)
- {
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcNewDevice);
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(g_mutex);
-#else
- Lock<MutexSys> lock(g_mutex);
-#endif
- Device* device = new Device(config);
- return (RTCDevice) device->refInc();
- RTC_CATCH_END(nullptr);
- return (RTCDevice) nullptr;
- }
-
- RTC_API void rtcRetainDevice(RTCDevice hdevice)
- {
- Device* device = (Device*) hdevice;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcRetainDevice);
- RTC_VERIFY_HANDLE(hdevice);
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(g_mutex);
-#else
- Lock<MutexSys> lock(g_mutex);
-#endif
- device->refInc();
- RTC_CATCH_END(nullptr);
- }
-
- RTC_API void rtcReleaseDevice(RTCDevice hdevice)
- {
- Device* device = (Device*) hdevice;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcReleaseDevice);
- RTC_VERIFY_HANDLE(hdevice);
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(g_mutex);
-#else
- Lock<MutexSys> lock(g_mutex);
-#endif
- device->refDec();
- RTC_CATCH_END(nullptr);
- }
-
- RTC_API ssize_t rtcGetDeviceProperty(RTCDevice hdevice, RTCDeviceProperty prop)
- {
- Device* device = (Device*) hdevice;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetDeviceProperty);
- RTC_VERIFY_HANDLE(hdevice);
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(g_mutex);
-#else
- Lock<MutexSys> lock(g_mutex);
-#endif
- return device->getProperty(prop);
- RTC_CATCH_END(device);
- return 0;
- }
-
- RTC_API void rtcSetDeviceProperty(RTCDevice hdevice, const RTCDeviceProperty prop, ssize_t val)
- {
- Device* device = (Device*) hdevice;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetDeviceProperty);
- const bool internal_prop = (size_t)prop >= 1000000 && (size_t)prop < 1000004;
- if (!internal_prop) RTC_VERIFY_HANDLE(hdevice); // allow NULL device for special internal settings
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(g_mutex);
-#else
- Lock<MutexSys> lock(g_mutex);
-#endif
- device->setProperty(prop,val);
- RTC_CATCH_END(device);
- }
-
- RTC_API RTCError rtcGetDeviceError(RTCDevice hdevice)
- {
- Device* device = (Device*) hdevice;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetDeviceError);
- if (device == nullptr) return Device::getThreadErrorCode();
- else return device->getDeviceErrorCode();
- RTC_CATCH_END(device);
- return RTC_ERROR_UNKNOWN;
- }
-
- RTC_API void rtcSetDeviceErrorFunction(RTCDevice hdevice, RTCErrorFunction error, void* userPtr)
- {
- Device* device = (Device*) hdevice;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetDeviceErrorFunction);
- RTC_VERIFY_HANDLE(hdevice);
- device->setErrorFunction(error, userPtr);
- RTC_CATCH_END(device);
- }
-
- RTC_API void rtcSetDeviceMemoryMonitorFunction(RTCDevice hdevice, RTCMemoryMonitorFunction memoryMonitor, void* userPtr)
- {
- Device* device = (Device*) hdevice;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetDeviceMemoryMonitorFunction);
- device->setMemoryMonitorFunction(memoryMonitor, userPtr);
- RTC_CATCH_END(device);
- }
-
- RTC_API RTCBuffer rtcNewBuffer(RTCDevice hdevice, size_t byteSize)
- {
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcNewBuffer);
- RTC_VERIFY_HANDLE(hdevice);
- Buffer* buffer = new Buffer((Device*)hdevice, byteSize);
- return (RTCBuffer)buffer->refInc();
- RTC_CATCH_END((Device*)hdevice);
- return nullptr;
- }
-
- RTC_API RTCBuffer rtcNewSharedBuffer(RTCDevice hdevice, void* ptr, size_t byteSize)
- {
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcNewSharedBuffer);
- RTC_VERIFY_HANDLE(hdevice);
- Buffer* buffer = new Buffer((Device*)hdevice, byteSize, ptr);
- return (RTCBuffer)buffer->refInc();
- RTC_CATCH_END((Device*)hdevice);
- return nullptr;
- }
-
- RTC_API void* rtcGetBufferData(RTCBuffer hbuffer)
- {
- Buffer* buffer = (Buffer*)hbuffer;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetBufferData);
- RTC_VERIFY_HANDLE(hbuffer);
- return buffer->data();
- RTC_CATCH_END2(buffer);
- return nullptr;
- }
-
- RTC_API void rtcRetainBuffer(RTCBuffer hbuffer)
- {
- Buffer* buffer = (Buffer*)hbuffer;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcRetainBuffer);
- RTC_VERIFY_HANDLE(hbuffer);
- buffer->refInc();
- RTC_CATCH_END2(buffer);
- }
-
- RTC_API void rtcReleaseBuffer(RTCBuffer hbuffer)
- {
- Buffer* buffer = (Buffer*)hbuffer;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcReleaseBuffer);
- RTC_VERIFY_HANDLE(hbuffer);
- buffer->refDec();
- RTC_CATCH_END2(buffer);
- }
-
- RTC_API RTCScene rtcNewScene (RTCDevice hdevice)
- {
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcNewScene);
- RTC_VERIFY_HANDLE(hdevice);
- Scene* scene = new Scene((Device*)hdevice);
- return (RTCScene) scene->refInc();
- RTC_CATCH_END((Device*)hdevice);
- return nullptr;
- }
-
- RTC_API RTCDevice rtcGetSceneDevice(RTCScene hscene)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetSceneDevice);
- RTC_VERIFY_HANDLE(hscene);
- return (RTCDevice)scene->device->refInc(); // user will own one additional device reference
- RTC_CATCH_END2(scene);
- return (RTCDevice)nullptr;
- }
-
- RTC_API void rtcSetSceneProgressMonitorFunction(RTCScene hscene, RTCProgressMonitorFunction progress, void* ptr)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetSceneProgressMonitorFunction);
- RTC_VERIFY_HANDLE(hscene);
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(g_mutex);
-#else
- Lock<MutexSys> lock(g_mutex);
-#endif
- scene->setProgressMonitorFunction(progress,ptr);
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcSetSceneBuildQuality (RTCScene hscene, RTCBuildQuality quality)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetSceneBuildQuality);
- RTC_VERIFY_HANDLE(hscene);
- if (quality != RTC_BUILD_QUALITY_LOW &&
- quality != RTC_BUILD_QUALITY_MEDIUM &&
- quality != RTC_BUILD_QUALITY_HIGH)
- // -- GODOT start --
- // throw std::runtime_error("invalid build quality");
- abort();
- // -- GODOT end --
- scene->setBuildQuality(quality);
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcSetSceneFlags (RTCScene hscene, RTCSceneFlags flags)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetSceneFlags);
- RTC_VERIFY_HANDLE(hscene);
- scene->setSceneFlags(flags);
- RTC_CATCH_END2(scene);
- }
-
- RTC_API RTCSceneFlags rtcGetSceneFlags(RTCScene hscene)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetSceneFlags);
- RTC_VERIFY_HANDLE(hscene);
- return scene->getSceneFlags();
- RTC_CATCH_END2(scene);
- return RTC_SCENE_FLAG_NONE;
- }
-
- RTC_API void rtcCommitScene (RTCScene hscene)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcCommitScene);
- RTC_VERIFY_HANDLE(hscene);
- scene->commit(false);
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcJoinCommitScene (RTCScene hscene)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcJoinCommitScene);
- RTC_VERIFY_HANDLE(hscene);
- scene->commit(true);
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcGetSceneBounds(RTCScene hscene, RTCBounds* bounds_o)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetSceneBounds);
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- BBox3fa bounds = scene->bounds.bounds();
- bounds_o->lower_x = bounds.lower.x;
- bounds_o->lower_y = bounds.lower.y;
- bounds_o->lower_z = bounds.lower.z;
- bounds_o->align0 = 0;
- bounds_o->upper_x = bounds.upper.x;
- bounds_o->upper_y = bounds.upper.y;
- bounds_o->upper_z = bounds.upper.z;
- bounds_o->align1 = 0;
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcGetSceneLinearBounds(RTCScene hscene, RTCLinearBounds* bounds_o)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetSceneBounds);
- RTC_VERIFY_HANDLE(hscene);
- if (bounds_o == nullptr)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid destination pointer");
- if (scene->isModified())
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
-
- bounds_o->bounds0.lower_x = scene->bounds.bounds0.lower.x;
- bounds_o->bounds0.lower_y = scene->bounds.bounds0.lower.y;
- bounds_o->bounds0.lower_z = scene->bounds.bounds0.lower.z;
- bounds_o->bounds0.align0 = 0;
- bounds_o->bounds0.upper_x = scene->bounds.bounds0.upper.x;
- bounds_o->bounds0.upper_y = scene->bounds.bounds0.upper.y;
- bounds_o->bounds0.upper_z = scene->bounds.bounds0.upper.z;
- bounds_o->bounds0.align1 = 0;
- bounds_o->bounds1.lower_x = scene->bounds.bounds1.lower.x;
- bounds_o->bounds1.lower_y = scene->bounds.bounds1.lower.y;
- bounds_o->bounds1.lower_z = scene->bounds.bounds1.lower.z;
- bounds_o->bounds1.align0 = 0;
- bounds_o->bounds1.upper_x = scene->bounds.bounds1.upper.x;
- bounds_o->bounds1.upper_y = scene->bounds.bounds1.upper.y;
- bounds_o->bounds1.upper_z = scene->bounds.bounds1.upper.z;
- bounds_o->bounds1.align1 = 0;
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcCollide (RTCScene hscene0, RTCScene hscene1, RTCCollideFunc callback, void* userPtr)
- {
- Scene* scene0 = (Scene*) hscene0;
- Scene* scene1 = (Scene*) hscene1;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcCollide);
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene0);
- RTC_VERIFY_HANDLE(hscene1);
- if (scene0->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
- if (scene1->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
- if (scene0->device != scene1->device) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scenes are from different devices");
- auto nUserPrims0 = scene0->getNumPrimitives (Geometry::MTY_USER_GEOMETRY, false);
- auto nUserPrims1 = scene1->getNumPrimitives (Geometry::MTY_USER_GEOMETRY, false);
- if (scene0->numPrimitives() != nUserPrims0 && scene1->numPrimitives() != nUserPrims1) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scenes must only contain user geometries with a single timestep");
-#endif
- scene0->intersectors.collide(scene0,scene1,callback,userPtr);
- RTC_CATCH_END(scene0->device);
- }
-
- inline bool pointQuery(Scene* scene, RTCPointQuery* query, RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void* userPtr)
- {
- bool changed = false;
- if (userContext->instStackSize > 0)
- {
- const AffineSpace3fa transform = AffineSpace3fa_load_unaligned((AffineSpace3fa*)userContext->world2inst[userContext->instStackSize-1]);
-
- float similarityScale = 0.f;
- const bool similtude = similarityTransform(transform, &similarityScale);
- assert((similtude && similarityScale > 0) || (!similtude && similarityScale == 0.f));
-
- PointQuery query_inst;
- query_inst.p = xfmPoint(transform, Vec3fa(query->x, query->y, query->z));
- query_inst.radius = query->radius * similarityScale;
- query_inst.time = query->time;
-
- PointQueryContext context_inst(scene, (PointQuery*)query,
- similtude ? POINT_QUERY_TYPE_SPHERE : POINT_QUERY_TYPE_AABB,
- queryFunc, userContext, similarityScale, userPtr);
- changed = scene->intersectors.pointQuery((PointQuery*)&query_inst, &context_inst);
- }
- else
- {
- PointQueryContext context(scene, (PointQuery*)query,
- POINT_QUERY_TYPE_SPHERE, queryFunc, userContext, 1.f, userPtr);
- changed = scene->intersectors.pointQuery((PointQuery*)query, &context);
- }
- return changed;
- }
-
- RTC_API bool rtcPointQuery(RTCScene hscene, RTCPointQuery* query, RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void* userPtr)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcPointQuery);
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- RTC_VERIFY_HANDLE(userContext);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
- if (((size_t)query) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "query not aligned to 16 bytes");
- if (((size_t)userContext) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "context not aligned to 16 bytes");
-#endif
-
- return pointQuery(scene, query, userContext, queryFunc, userPtr);
- RTC_CATCH_END2_FALSE(scene);
- }
-
- RTC_API bool rtcPointQuery4 (const int* valid, RTCScene hscene, RTCPointQuery4* query, struct RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void** userPtrN)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcPointQuery4);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
- if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
- if (((size_t)query) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "query not aligned to 16 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(point_query.travs,cnt,cnt,cnt);
-
- bool changed = false;
- PointQuery4* query4 = (PointQuery4*)query;
- PointQuery query1;
- for (size_t i=0; i<4; i++) {
- if (!valid[i]) continue;
- query4->get(i,query1);
- changed |= pointQuery(scene, (RTCPointQuery*)&query1, userContext, queryFunc, userPtrN?userPtrN[i]:NULL);
- query4->set(i,query1);
- }
- return changed;
- RTC_CATCH_END2_FALSE(scene);
- }
-
- RTC_API bool rtcPointQuery8 (const int* valid, RTCScene hscene, RTCPointQuery8* query, struct RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void** userPtrN)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcPointQuery8);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
- if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
- if (((size_t)query) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "query not aligned to 16 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(point_query.travs,cnt,cnt,cnt);
-
- bool changed = false;
- PointQuery8* query8 = (PointQuery8*)query;
- PointQuery query1;
- for (size_t i=0; i<8; i++) {
- if (!valid[i]) continue;
- query8->get(i,query1);
- changed |= pointQuery(scene, (RTCPointQuery*)&query1, userContext, queryFunc, userPtrN?userPtrN[i]:NULL);
- query8->set(i,query1);
- }
- return changed;
- RTC_CATCH_END2_FALSE(scene);
- }
-
- RTC_API bool rtcPointQuery16 (const int* valid, RTCScene hscene, RTCPointQuery16* query, struct RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void** userPtrN)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcPointQuery16);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
- if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
- if (((size_t)query) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "query not aligned to 16 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(point_query.travs,cnt,cnt,cnt);
-
- bool changed = false;
- PointQuery16* query16 = (PointQuery16*)query;
- PointQuery query1;
- for (size_t i=0; i<16; i++) {
- if (!valid[i]) continue;
- PointQuery query1; query16->get(i,query1);
- changed |= pointQuery(scene, (RTCPointQuery*)&query1, userContext, queryFunc, userPtrN?userPtrN[i]:NULL);
- query16->set(i,query1);
- }
- return changed;
- RTC_CATCH_END2_FALSE(scene);
- }
-
- RTC_API void rtcIntersect1 (RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit* rayhit)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcIntersect1);
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)rayhit) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 16 bytes");
-#endif
- STAT3(normal.travs,1,1,1);
- IntersectContext context(scene,user_context);
- scene->intersectors.intersect(*rayhit,&context);
-#if defined(DEBUG)
- ((RayHit*)rayhit)->verifyHit();
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcIntersect4 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit4* rayhit)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcIntersect4);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
- if (((size_t)rayhit) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit not aligned to 16 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(normal.travs,cnt,cnt,cnt);
-
- IntersectContext context(scene,user_context);
-#if !defined(EMBREE_RAY_PACKETS)
- RayHit4* rayhit4 = (RayHit4*)rayhit;
- for (size_t i=0; i<4; i++) {
- if (!valid[i]) continue;
- RayHit ray1; rayhit4->get(i,ray1);
- scene->intersectors.intersect((RTCRayHit&)ray1,&context);
- rayhit4->set(i,ray1);
- }
-#else
- scene->intersectors.intersect4(valid,*rayhit,&context);
-#endif
-
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcIntersect8 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit8* rayhit)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcIntersect8);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)valid) & 0x1F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 32 bytes");
- if (((size_t)rayhit) & 0x1F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit not aligned to 32 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<8; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(normal.travs,cnt,cnt,cnt);
-
- IntersectContext context(scene,user_context);
-#if !defined(EMBREE_RAY_PACKETS)
- RayHit8* rayhit8 = (RayHit8*) rayhit;
- for (size_t i=0; i<8; i++) {
- if (!valid[i]) continue;
- RayHit ray1; rayhit8->get(i,ray1);
- scene->intersectors.intersect((RTCRayHit&)ray1,&context);
- rayhit8->set(i,ray1);
- }
-#else
- if (likely(scene->intersectors.intersector8))
- scene->intersectors.intersect8(valid,*rayhit,&context);
- else
- scene->device->rayStreamFilters.intersectSOA(scene,(char*)rayhit,8,1,sizeof(RTCRayHit8),&context);
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcIntersect16 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit16* rayhit)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcIntersect16);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)valid) & 0x3F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 64 bytes");
- if (((size_t)rayhit) & 0x3F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit not aligned to 64 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<16; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(normal.travs,cnt,cnt,cnt);
-
- IntersectContext context(scene,user_context);
-#if !defined(EMBREE_RAY_PACKETS)
- RayHit16* rayhit16 = (RayHit16*) rayhit;
- for (size_t i=0; i<16; i++) {
- if (!valid[i]) continue;
- RayHit ray1; rayhit16->get(i,ray1);
- scene->intersectors.intersect((RTCRayHit&)ray1,&context);
- rayhit16->set(i,ray1);
- }
-#else
- if (likely(scene->intersectors.intersector16))
- scene->intersectors.intersect16(valid,*rayhit,&context);
- else
- scene->device->rayStreamFilters.intersectSOA(scene,(char*)rayhit,16,1,sizeof(RTCRayHit16),&context);
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcIntersect1M (RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit* rayhit, unsigned int M, size_t byteStride)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcIntersect1M);
-
-#if defined (EMBREE_RAY_PACKETS)
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)rayhit ) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
-#endif
- STAT3(normal.travs,M,M,M);
- IntersectContext context(scene,user_context);
-
- /* fast codepath for single rays */
- if (likely(M == 1)) {
- if (likely(rayhit->ray.tnear <= rayhit->ray.tfar))
- scene->intersectors.intersect(*rayhit,&context);
- }
-
- /* codepath for streams */
- else {
- scene->device->rayStreamFilters.intersectAOS(scene,rayhit,M,byteStride,&context);
- }
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect1M not supported");
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcIntersect1Mp (RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit** rn, unsigned int M)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcIntersect1Mp);
-
-#if defined (EMBREE_RAY_PACKETS)
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)rn) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
-#endif
- STAT3(normal.travs,M,M,M);
- IntersectContext context(scene,user_context);
-
- /* fast codepath for single rays */
- if (likely(M == 1)) {
- if (likely(rn[0]->ray.tnear <= rn[0]->ray.tfar))
- scene->intersectors.intersect(*rn[0],&context);
- }
-
- /* codepath for streams */
- else {
- scene->device->rayStreamFilters.intersectAOP(scene,rn,M,&context);
- }
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect1Mp not supported");
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcIntersectNM (RTCScene hscene, RTCIntersectContext* user_context, struct RTCRayHitN* rayhit, unsigned int N, unsigned int M, size_t byteStride)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcIntersectNM);
-
-#if defined (EMBREE_RAY_PACKETS)
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)rayhit) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
-#endif
- STAT3(normal.travs,N*M,N*M,N*M);
- IntersectContext context(scene,user_context);
-
- /* code path for single ray streams */
- if (likely(N == 1))
- {
- /* fast code path for streams of size 1 */
- if (likely(M == 1)) {
- if (likely(((RTCRayHit*)rayhit)->ray.tnear <= ((RTCRayHit*)rayhit)->ray.tfar))
- scene->intersectors.intersect(*(RTCRayHit*)rayhit,&context);
- }
- /* normal codepath for single ray streams */
- else {
- scene->device->rayStreamFilters.intersectAOS(scene,(RTCRayHit*)rayhit,M,byteStride,&context);
- }
- }
- /* code path for ray packet streams */
- else {
- scene->device->rayStreamFilters.intersectSOA(scene,(char*)rayhit,N,M,byteStride,&context);
- }
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectNM not supported");
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcIntersectNp (RTCScene hscene, RTCIntersectContext* user_context, const RTCRayHitNp* rayhit, unsigned int N)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcIntersectNp);
-
-#if defined (EMBREE_RAY_PACKETS)
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)rayhit->ray.org_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.org_x not aligned to 4 bytes");
- if (((size_t)rayhit->ray.org_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.org_y not aligned to 4 bytes");
- if (((size_t)rayhit->ray.org_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.org_z not aligned to 4 bytes");
- if (((size_t)rayhit->ray.dir_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.dir_x not aligned to 4 bytes");
- if (((size_t)rayhit->ray.dir_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.dir_y not aligned to 4 bytes");
- if (((size_t)rayhit->ray.dir_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.dir_z not aligned to 4 bytes");
- if (((size_t)rayhit->ray.tnear ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.dir_x not aligned to 4 bytes");
- if (((size_t)rayhit->ray.tfar ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.tnear not aligned to 4 bytes");
- if (((size_t)rayhit->ray.time ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.time not aligned to 4 bytes");
- if (((size_t)rayhit->ray.mask ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.mask not aligned to 4 bytes");
- if (((size_t)rayhit->hit.Ng_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.Ng_x not aligned to 4 bytes");
- if (((size_t)rayhit->hit.Ng_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.Ng_y not aligned to 4 bytes");
- if (((size_t)rayhit->hit.Ng_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.Ng_z not aligned to 4 bytes");
- if (((size_t)rayhit->hit.u ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.u not aligned to 4 bytes");
- if (((size_t)rayhit->hit.v ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.v not aligned to 4 bytes");
- if (((size_t)rayhit->hit.geomID) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.geomID not aligned to 4 bytes");
- if (((size_t)rayhit->hit.primID) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.primID not aligned to 4 bytes");
- if (((size_t)rayhit->hit.instID) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.instID not aligned to 4 bytes");
-#endif
- STAT3(normal.travs,N,N,N);
- IntersectContext context(scene,user_context);
- scene->device->rayStreamFilters.intersectSOP(scene,rayhit,N,&context);
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectNp not supported");
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcOccluded1 (RTCScene hscene, RTCIntersectContext* user_context, RTCRay* ray)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcOccluded1);
- STAT3(shadow.travs,1,1,1);
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)ray) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 16 bytes");
-#endif
- IntersectContext context(scene,user_context);
- scene->intersectors.occluded(*ray,&context);
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcOccluded4 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRay4* ray)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcOccluded4);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
- if (((size_t)ray) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 16 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(shadow.travs,cnt,cnt,cnt);
-
- IntersectContext context(scene,user_context);
-#if !defined(EMBREE_RAY_PACKETS)
- Ray4* ray4 = (Ray4*) ray;
- for (size_t i=0; i<4; i++) {
- if (!valid[i]) continue;
- Ray ray1; ray4->get(i,ray1);
- scene->intersectors.occluded((RTCRay&)ray1,&context);
- ray4->set(i,ray1);
- }
-#else
- scene->intersectors.occluded4(valid,*ray,&context);
-#endif
-
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcOccluded8 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRay8* ray)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcOccluded8);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)valid) & 0x1F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 32 bytes");
- if (((size_t)ray) & 0x1F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 32 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<8; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(shadow.travs,cnt,cnt,cnt);
-
- IntersectContext context(scene,user_context);
-#if !defined(EMBREE_RAY_PACKETS)
- Ray8* ray8 = (Ray8*) ray;
- for (size_t i=0; i<8; i++) {
- if (!valid[i]) continue;
- Ray ray1; ray8->get(i,ray1);
- scene->intersectors.occluded((RTCRay&)ray1,&context);
- ray8->set(i,ray1);
- }
-#else
- if (likely(scene->intersectors.intersector8))
- scene->intersectors.occluded8(valid,*ray,&context);
- else
- scene->device->rayStreamFilters.occludedSOA(scene,(char*)ray,8,1,sizeof(RTCRay8),&context);
-#endif
-
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcOccluded16 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRay16* ray)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcOccluded16);
-
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)valid) & 0x3F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 64 bytes");
- if (((size_t)ray) & 0x3F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 64 bytes");
-#endif
- STAT(size_t cnt=0; for (size_t i=0; i<16; i++) cnt += ((int*)valid)[i] == -1;);
- STAT3(shadow.travs,cnt,cnt,cnt);
-
- IntersectContext context(scene,user_context);
-#if !defined(EMBREE_RAY_PACKETS)
- Ray16* ray16 = (Ray16*) ray;
- for (size_t i=0; i<16; i++) {
- if (!valid[i]) continue;
- Ray ray1; ray16->get(i,ray1);
- scene->intersectors.occluded((RTCRay&)ray1,&context);
- ray16->set(i,ray1);
- }
-#else
- if (likely(scene->intersectors.intersector16))
- scene->intersectors.occluded16(valid,*ray,&context);
- else
- scene->device->rayStreamFilters.occludedSOA(scene,(char*)ray,16,1,sizeof(RTCRay16),&context);
-#endif
-
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcOccluded1M(RTCScene hscene, RTCIntersectContext* user_context, RTCRay* ray, unsigned int M, size_t byteStride)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcOccluded1M);
-
-#if defined (EMBREE_RAY_PACKETS)
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)ray) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
-#endif
- STAT3(shadow.travs,M,M,M);
- IntersectContext context(scene,user_context);
- /* fast codepath for streams of size 1 */
- if (likely(M == 1)) {
- if (likely(ray->tnear <= ray->tfar))
- scene->intersectors.occluded (*ray,&context);
- }
- /* codepath for normal streams */
- else {
- scene->device->rayStreamFilters.occludedAOS(scene,ray,M,byteStride,&context);
- }
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcOccluded1M not supported");
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcOccluded1Mp(RTCScene hscene, RTCIntersectContext* user_context, RTCRay** ray, unsigned int M)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcOccluded1Mp);
-
-#if defined (EMBREE_RAY_PACKETS)
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)ray) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
-#endif
- STAT3(shadow.travs,M,M,M);
- IntersectContext context(scene,user_context);
-
- /* fast codepath for streams of size 1 */
- if (likely(M == 1)) {
- if (likely(ray[0]->tnear <= ray[0]->tfar))
- scene->intersectors.occluded (*ray[0],&context);
- }
- /* codepath for normal streams */
- else {
- scene->device->rayStreamFilters.occludedAOP(scene,ray,M,&context);
- }
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcOccluded1Mp not supported");
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcOccludedNM(RTCScene hscene, RTCIntersectContext* user_context, RTCRayN* ray, unsigned int N, unsigned int M, size_t byteStride)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcOccludedNM);
-
-#if defined (EMBREE_RAY_PACKETS)
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (byteStride < sizeof(RTCRayHit)) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"byteStride too small");
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)ray) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
-#endif
- STAT3(shadow.travs,N*M,N*N,N*N);
- IntersectContext context(scene,user_context);
-
- /* codepath for single rays */
- if (likely(N == 1))
- {
- /* fast path for streams of size 1 */
- if (likely(M == 1)) {
- if (likely(((RTCRay*)ray)->tnear <= ((RTCRay*)ray)->tfar))
- scene->intersectors.occluded (*(RTCRay*)ray,&context);
- }
- /* codepath for normal ray streams */
- else {
- scene->device->rayStreamFilters.occludedAOS(scene,(RTCRay*)ray,M,byteStride,&context);
- }
- }
- /* code path for ray packet streams */
- else {
- scene->device->rayStreamFilters.occludedSOA(scene,(char*)ray,N,M,byteStride,&context);
- }
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcOccludedNM not supported");
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcOccludedNp(RTCScene hscene, RTCIntersectContext* user_context, const RTCRayNp* ray, unsigned int N)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcOccludedNp);
-
-#if defined (EMBREE_RAY_PACKETS)
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
- if (((size_t)ray->org_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "org_x not aligned to 4 bytes");
- if (((size_t)ray->org_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "org_y not aligned to 4 bytes");
- if (((size_t)ray->org_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "org_z not aligned to 4 bytes");
- if (((size_t)ray->dir_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "dir_x not aligned to 4 bytes");
- if (((size_t)ray->dir_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "dir_y not aligned to 4 bytes");
- if (((size_t)ray->dir_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "dir_z not aligned to 4 bytes");
- if (((size_t)ray->tnear ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "dir_x not aligned to 4 bytes");
- if (((size_t)ray->tfar ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "tnear not aligned to 4 bytes");
- if (((size_t)ray->time ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "time not aligned to 4 bytes");
- if (((size_t)ray->mask ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 4 bytes");
-#endif
- STAT3(shadow.travs,N,N,N);
- IntersectContext context(scene,user_context);
- scene->device->rayStreamFilters.occludedSOP(scene,ray,N,&context);
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcOccludedNp not supported");
-#endif
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcRetainScene (RTCScene hscene)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcRetainScene);
- RTC_VERIFY_HANDLE(hscene);
- scene->refInc();
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcReleaseScene (RTCScene hscene)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcReleaseScene);
- RTC_VERIFY_HANDLE(hscene);
- scene->refDec();
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcSetGeometryInstancedScene(RTCGeometry hgeometry, RTCScene hscene)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- Ref<Scene> scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryInstancedScene);
- RTC_VERIFY_HANDLE(hgeometry);
- RTC_VERIFY_HANDLE(hscene);
- geometry->setInstancedScene(scene);
- RTC_CATCH_END2(geometry);
- }
-
- AffineSpace3fa loadTransform(RTCFormat format, const float* xfm)
- {
- AffineSpace3fa space = one;
- switch (format)
- {
- case RTC_FORMAT_FLOAT3X4_ROW_MAJOR:
- space = AffineSpace3fa(Vec3fa(xfm[ 0], xfm[ 4], xfm[ 8]),
- Vec3fa(xfm[ 1], xfm[ 5], xfm[ 9]),
- Vec3fa(xfm[ 2], xfm[ 6], xfm[10]),
- Vec3fa(xfm[ 3], xfm[ 7], xfm[11]));
- break;
-
- case RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR:
- space = AffineSpace3fa(Vec3fa(xfm[ 0], xfm[ 1], xfm[ 2]),
- Vec3fa(xfm[ 3], xfm[ 4], xfm[ 5]),
- Vec3fa(xfm[ 6], xfm[ 7], xfm[ 8]),
- Vec3fa(xfm[ 9], xfm[10], xfm[11]));
- break;
-
- case RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR:
- space = AffineSpace3fa(Vec3fa(xfm[ 0], xfm[ 1], xfm[ 2]),
- Vec3fa(xfm[ 4], xfm[ 5], xfm[ 6]),
- Vec3fa(xfm[ 8], xfm[ 9], xfm[10]),
- Vec3fa(xfm[12], xfm[13], xfm[14]));
- break;
-
- default:
- throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid matrix format");
- break;
- }
- return space;
- }
-
- void storeTransform(const AffineSpace3fa& space, RTCFormat format, float* xfm)
- {
- switch (format)
- {
- case RTC_FORMAT_FLOAT3X4_ROW_MAJOR:
- xfm[ 0] = space.l.vx.x; xfm[ 1] = space.l.vy.x; xfm[ 2] = space.l.vz.x; xfm[ 3] = space.p.x;
- xfm[ 4] = space.l.vx.y; xfm[ 5] = space.l.vy.y; xfm[ 6] = space.l.vz.y; xfm[ 7] = space.p.y;
- xfm[ 8] = space.l.vx.z; xfm[ 9] = space.l.vy.z; xfm[10] = space.l.vz.z; xfm[11] = space.p.z;
- break;
-
- case RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR:
- xfm[ 0] = space.l.vx.x; xfm[ 1] = space.l.vx.y; xfm[ 2] = space.l.vx.z;
- xfm[ 3] = space.l.vy.x; xfm[ 4] = space.l.vy.y; xfm[ 5] = space.l.vy.z;
- xfm[ 6] = space.l.vz.x; xfm[ 7] = space.l.vz.y; xfm[ 8] = space.l.vz.z;
- xfm[ 9] = space.p.x; xfm[10] = space.p.y; xfm[11] = space.p.z;
- break;
-
- case RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR:
- xfm[ 0] = space.l.vx.x; xfm[ 1] = space.l.vx.y; xfm[ 2] = space.l.vx.z; xfm[ 3] = 0.f;
- xfm[ 4] = space.l.vy.x; xfm[ 5] = space.l.vy.y; xfm[ 6] = space.l.vy.z; xfm[ 7] = 0.f;
- xfm[ 8] = space.l.vz.x; xfm[ 9] = space.l.vz.y; xfm[10] = space.l.vz.z; xfm[11] = 0.f;
- xfm[12] = space.p.x; xfm[13] = space.p.y; xfm[14] = space.p.z; xfm[15] = 1.f;
- break;
-
- default:
- throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid matrix format");
- break;
- }
- }
-
- RTC_API void rtcSetGeometryTransform(RTCGeometry hgeometry, unsigned int timeStep, RTCFormat format, const void* xfm)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryTransform);
- RTC_VERIFY_HANDLE(hgeometry);
- RTC_VERIFY_HANDLE(xfm);
- const AffineSpace3fa transform = loadTransform(format, (const float*)xfm);
- geometry->setTransform(transform, timeStep);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryTransformQuaternion(RTCGeometry hgeometry, unsigned int timeStep, const RTCQuaternionDecomposition* qd)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryTransformQuaternion);
- RTC_VERIFY_HANDLE(hgeometry);
- RTC_VERIFY_HANDLE(qd);
-
- AffineSpace3fx transform;
- transform.l.vx.x = qd->scale_x;
- transform.l.vy.y = qd->scale_y;
- transform.l.vz.z = qd->scale_z;
- transform.l.vy.x = qd->skew_xy;
- transform.l.vz.x = qd->skew_xz;
- transform.l.vz.y = qd->skew_yz;
- transform.l.vx.y = qd->translation_x;
- transform.l.vx.z = qd->translation_y;
- transform.l.vy.z = qd->translation_z;
- transform.p.x = qd->shift_x;
- transform.p.y = qd->shift_y;
- transform.p.z = qd->shift_z;
-
- // normalize quaternion
- Quaternion3f q(qd->quaternion_r, qd->quaternion_i, qd->quaternion_j, qd->quaternion_k);
- q = normalize(q);
- transform.l.vx.w = q.i;
- transform.l.vy.w = q.j;
- transform.l.vz.w = q.k;
- transform.p.w = q.r;
-
- geometry->setQuaternionDecomposition(transform, timeStep);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcGetGeometryTransform(RTCGeometry hgeometry, float time, RTCFormat format, void* xfm)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometryTransform);
- const AffineSpace3fa transform = geometry->getTransform(time);
- storeTransform(transform, format, (float*)xfm);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcFilterIntersection(const struct RTCIntersectFunctionNArguments* const args_i, const struct RTCFilterFunctionNArguments* filter_args)
- {
- IntersectFunctionNArguments* args = (IntersectFunctionNArguments*) args_i;
- args->report(args,filter_args);
- }
-
- RTC_API void rtcFilterOcclusion(const struct RTCOccludedFunctionNArguments* const args_i, const struct RTCFilterFunctionNArguments* filter_args)
- {
- OccludedFunctionNArguments* args = (OccludedFunctionNArguments*) args_i;
- args->report(args,filter_args);
- }
-
- RTC_API RTCGeometry rtcNewGeometry (RTCDevice hdevice, RTCGeometryType type)
- {
- Device* device = (Device*) hdevice;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcNewGeometry);
- RTC_VERIFY_HANDLE(hdevice);
-
- switch (type)
- {
- case RTC_GEOMETRY_TYPE_TRIANGLE:
- {
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- createTriangleMeshTy createTriangleMesh = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createTriangleMesh);
- Geometry* geom = createTriangleMesh(device);
- return (RTCGeometry) geom->refInc();
-#else
- throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_TRIANGLE is not supported");
-#endif
- }
-
- case RTC_GEOMETRY_TYPE_QUAD:
- {
-#if defined(EMBREE_GEOMETRY_QUAD)
- createQuadMeshTy createQuadMesh = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createQuadMesh);
- Geometry* geom = createQuadMesh(device);
- return (RTCGeometry) geom->refInc();
-#else
- throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_QUAD is not supported");
-#endif
- }
-
- case RTC_GEOMETRY_TYPE_SPHERE_POINT:
- case RTC_GEOMETRY_TYPE_DISC_POINT:
- case RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT:
- {
-#if defined(EMBREE_GEOMETRY_POINT)
- createPointsTy createPoints = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_builder_cpu_features, createPoints);
-
- Geometry *geom;
- switch(type) {
- case RTC_GEOMETRY_TYPE_SPHERE_POINT:
- geom = createPoints(device, Geometry::GTY_SPHERE_POINT);
- break;
- case RTC_GEOMETRY_TYPE_DISC_POINT:
- geom = createPoints(device, Geometry::GTY_DISC_POINT);
- break;
- case RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT:
- geom = createPoints(device, Geometry::GTY_ORIENTED_DISC_POINT);
- break;
- default:
- geom = nullptr;
- break;
- }
- return (RTCGeometry) geom->refInc();
-#else
- throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_POINT is not supported");
-#endif
- }
-
- case RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE:
- case RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE:
- case RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE:
-
- case RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE:
- case RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE:
- case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE:
-
- case RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE:
- case RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE:
- case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE:
-
- case RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE:
- case RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE:
- case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE:
-
- case RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE:
- case RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE:
- case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE:
- {
-#if defined(EMBREE_GEOMETRY_CURVE)
- createLineSegmentsTy createLineSegments = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createLineSegments);
- createCurvesTy createCurves = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createCurves);
-
- Geometry* geom;
- switch (type) {
- case RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_CONE_LINEAR_CURVE); break;
- case RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_ROUND_LINEAR_CURVE); break;
- case RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_FLAT_LINEAR_CURVE); break;
- //case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_ORIENTED_LINEAR_CURVE); break;
-
- case RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE : geom = createCurves(device,Geometry::GTY_ROUND_BEZIER_CURVE); break;
- case RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE : geom = createCurves(device,Geometry::GTY_FLAT_BEZIER_CURVE); break;
- case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE : geom = createCurves(device,Geometry::GTY_ORIENTED_BEZIER_CURVE); break;
-
- case RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE : geom = createCurves(device,Geometry::GTY_ROUND_BSPLINE_CURVE); break;
- case RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE : geom = createCurves(device,Geometry::GTY_FLAT_BSPLINE_CURVE); break;
- case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE : geom = createCurves(device,Geometry::GTY_ORIENTED_BSPLINE_CURVE); break;
-
- case RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE : geom = createCurves(device,Geometry::GTY_ROUND_HERMITE_CURVE); break;
- case RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE : geom = createCurves(device,Geometry::GTY_FLAT_HERMITE_CURVE); break;
- case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE : geom = createCurves(device,Geometry::GTY_ORIENTED_HERMITE_CURVE); break;
-
- case RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE : geom = createCurves(device,Geometry::GTY_ROUND_CATMULL_ROM_CURVE); break;
- case RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE : geom = createCurves(device,Geometry::GTY_FLAT_CATMULL_ROM_CURVE); break;
- case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE : geom = createCurves(device,Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE); break;
- default: geom = nullptr; break;
- }
- return (RTCGeometry) geom->refInc();
-#else
- throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_CURVE is not supported");
-#endif
- }
-
- case RTC_GEOMETRY_TYPE_SUBDIVISION:
- {
-#if defined(EMBREE_GEOMETRY_SUBDIVISION)
- createSubdivMeshTy createSubdivMesh = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX(device->enabled_cpu_features,createSubdivMesh);
- //SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createSubdivMesh); // FIXME: this does not work for some reason?
- Geometry* geom = createSubdivMesh(device);
- return (RTCGeometry) geom->refInc();
-#else
- throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_SUBDIVISION is not supported");
-#endif
- }
-
- case RTC_GEOMETRY_TYPE_USER:
- {
-#if defined(EMBREE_GEOMETRY_USER)
- createUserGeometryTy createUserGeometry = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createUserGeometry);
- Geometry* geom = createUserGeometry(device);
- return (RTCGeometry) geom->refInc();
-#else
- throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_USER is not supported");
-#endif
- }
-
- case RTC_GEOMETRY_TYPE_INSTANCE:
- {
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- createInstanceTy createInstance = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createInstance);
- Geometry* geom = createInstance(device);
- return (RTCGeometry) geom->refInc();
-#else
- throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_INSTANCE is not supported");
-#endif
- }
-
- case RTC_GEOMETRY_TYPE_GRID:
- {
-#if defined(EMBREE_GEOMETRY_GRID)
- createGridMeshTy createGridMesh = nullptr;
- SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createGridMesh);
- Geometry* geom = createGridMesh(device);
- return (RTCGeometry) geom->refInc();
-#else
- throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_GRID is not supported");
-#endif
- }
-
- default:
- throw_RTCError(RTC_ERROR_UNKNOWN,"invalid geometry type");
- }
-
- RTC_CATCH_END(device);
- return nullptr;
- }
-
- RTC_API void rtcSetGeometryUserPrimitiveCount(RTCGeometry hgeometry, unsigned int userPrimitiveCount)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryUserPrimitiveCount);
- RTC_VERIFY_HANDLE(hgeometry);
-
- if (unlikely(geometry->getType() != Geometry::GTY_USER_GEOMETRY))
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation only allowed for user geometries");
-
- geometry->setNumPrimitives(userPrimitiveCount);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryTimeStepCount(RTCGeometry hgeometry, unsigned int timeStepCount)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryTimeStepCount);
- RTC_VERIFY_HANDLE(hgeometry);
-
- if (timeStepCount > RTC_MAX_TIME_STEP_COUNT)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"number of time steps is out of range");
-
- geometry->setNumTimeSteps(timeStepCount);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryTimeRange(RTCGeometry hgeometry, float startTime, float endTime)
- {
- Ref<Geometry> geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryTimeRange);
- RTC_VERIFY_HANDLE(hgeometry);
-
- if (startTime > endTime)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"startTime has to be smaller or equal to the endTime");
-
- geometry->setTimeRange(BBox1f(startTime,endTime));
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryVertexAttributeCount(RTCGeometry hgeometry, unsigned int N)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryVertexAttributeCount);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setVertexAttributeCount(N);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryTopologyCount(RTCGeometry hgeometry, unsigned int N)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryTopologyCount);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setTopologyCount(N);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryBuildQuality (RTCGeometry hgeometry, RTCBuildQuality quality)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryBuildQuality);
- RTC_VERIFY_HANDLE(hgeometry);
- if (quality != RTC_BUILD_QUALITY_LOW &&
- quality != RTC_BUILD_QUALITY_MEDIUM &&
- quality != RTC_BUILD_QUALITY_HIGH &&
- quality != RTC_BUILD_QUALITY_REFIT)
- // -- GODOT start --
- // throw std::runtime_error("invalid build quality");
- abort();
- // -- GODOT end --
- geometry->setBuildQuality(quality);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryMaxRadiusScale(RTCGeometry hgeometry, float maxRadiusScale)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryMaxRadiusScale);
- RTC_VERIFY_HANDLE(hgeometry);
-#if RTC_MIN_WIDTH
- if (maxRadiusScale < 1.0f) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"maximal radius scale has to be larger or equal to 1");
- geometry->setMaxRadiusScale(maxRadiusScale);
-#else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"min-width feature is not enabled");
-#endif
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryMask (RTCGeometry hgeometry, unsigned int mask)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryMask);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setMask(mask);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometrySubdivisionMode (RTCGeometry hgeometry, unsigned topologyID, RTCSubdivisionMode mode)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometrySubdivisionMode);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setSubdivisionMode(topologyID,mode);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryVertexAttributeTopology(RTCGeometry hgeometry, unsigned int vertexAttributeID, unsigned int topologyID)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryVertexAttributeTopology);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setVertexAttributeTopology(vertexAttributeID, topologyID);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryBuffer(RTCGeometry hgeometry, RTCBufferType type, unsigned int slot, RTCFormat format, RTCBuffer hbuffer, size_t byteOffset, size_t byteStride, size_t itemCount)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- Ref<Buffer> buffer = (Buffer*)hbuffer;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryBuffer);
- RTC_VERIFY_HANDLE(hgeometry);
- RTC_VERIFY_HANDLE(hbuffer);
-
- if (geometry->device != buffer->device)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"inputs are from different devices");
-
- if (itemCount > 0xFFFFFFFFu)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"buffer too large");
-
- geometry->setBuffer(type, slot, format, buffer, byteOffset, byteStride, (unsigned int)itemCount);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetSharedGeometryBuffer(RTCGeometry hgeometry, RTCBufferType type, unsigned int slot, RTCFormat format, const void* ptr, size_t byteOffset, size_t byteStride, size_t itemCount)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetSharedGeometryBuffer);
- RTC_VERIFY_HANDLE(hgeometry);
-
- if (itemCount > 0xFFFFFFFFu)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"buffer too large");
-
- Ref<Buffer> buffer = new Buffer(geometry->device, itemCount*byteStride, (char*)ptr + byteOffset);
- geometry->setBuffer(type, slot, format, buffer, 0, byteStride, (unsigned int)itemCount);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void* rtcSetNewGeometryBuffer(RTCGeometry hgeometry, RTCBufferType type, unsigned int slot, RTCFormat format, size_t byteStride, size_t itemCount)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetNewGeometryBuffer);
- RTC_VERIFY_HANDLE(hgeometry);
-
- if (itemCount > 0xFFFFFFFFu)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"buffer too large");
-
- /* vertex buffers need to get overallocated slightly as elements are accessed using SSE loads */
- size_t bytes = itemCount*byteStride;
- if (type == RTC_BUFFER_TYPE_VERTEX || type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
- bytes += (16 - (byteStride%16))%16;
-
- Ref<Buffer> buffer = new Buffer(geometry->device, bytes);
- geometry->setBuffer(type, slot, format, buffer, 0, byteStride, (unsigned int)itemCount);
- return buffer->data();
- RTC_CATCH_END2(geometry);
- return nullptr;
- }
-
- RTC_API void* rtcGetGeometryBufferData(RTCGeometry hgeometry, RTCBufferType type, unsigned int slot)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometryBufferData);
- RTC_VERIFY_HANDLE(hgeometry);
- return geometry->getBuffer(type, slot);
- RTC_CATCH_END2(geometry);
- return nullptr;
- }
-
- RTC_API void rtcEnableGeometry (RTCGeometry hgeometry)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcEnableGeometry);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->enable();
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcUpdateGeometryBuffer (RTCGeometry hgeometry, RTCBufferType type, unsigned int slot)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcUpdateGeometryBuffer);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->updateBuffer(type, slot);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcDisableGeometry (RTCGeometry hgeometry)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcDisableGeometry);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->disable();
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryTessellationRate (RTCGeometry hgeometry, float tessellationRate)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryTessellationRate);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setTessellationRate(tessellationRate);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryUserData (RTCGeometry hgeometry, void* ptr)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryUserData);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setUserData(ptr);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void* rtcGetGeometryUserData (RTCGeometry hgeometry)
- {
- Geometry* geometry = (Geometry*) hgeometry; // no ref counting here!
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometryUserData);
- RTC_VERIFY_HANDLE(hgeometry);
- return geometry->getUserData();
- RTC_CATCH_END2(geometry);
- return nullptr;
- }
-
- RTC_API void rtcSetGeometryBoundsFunction (RTCGeometry hgeometry, RTCBoundsFunction bounds, void* userPtr)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryBoundsFunction);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setBoundsFunction(bounds,userPtr);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryDisplacementFunction (RTCGeometry hgeometry, RTCDisplacementFunctionN displacement)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryDisplacementFunction);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setDisplacementFunction(displacement);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryIntersectFunction (RTCGeometry hgeometry, RTCIntersectFunctionN intersect)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryIntersectFunction);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setIntersectFunctionN(intersect);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryPointQueryFunction(RTCGeometry hgeometry, RTCPointQueryFunction pointQuery)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryPointQueryFunction);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setPointQueryFunction(pointQuery);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API unsigned int rtcGetGeometryFirstHalfEdge(RTCGeometry hgeometry, unsigned int faceID)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometryFirstHalfEdge);
- return geometry->getFirstHalfEdge(faceID);
- RTC_CATCH_END2(geometry);
- return -1;
- }
-
- RTC_API unsigned int rtcGetGeometryFace(RTCGeometry hgeometry, unsigned int edgeID)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometryFace);
- return geometry->getFace(edgeID);
- RTC_CATCH_END2(geometry);
- return -1;
- }
-
- RTC_API unsigned int rtcGetGeometryNextHalfEdge(RTCGeometry hgeometry, unsigned int edgeID)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometryNextHalfEdge);
- return geometry->getNextHalfEdge(edgeID);
- RTC_CATCH_END2(geometry);
- return -1;
- }
-
- RTC_API unsigned int rtcGetGeometryPreviousHalfEdge(RTCGeometry hgeometry, unsigned int edgeID)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometryPreviousHalfEdge);
- return geometry->getPreviousHalfEdge(edgeID);
- RTC_CATCH_END2(geometry);
- return -1;
- }
-
- RTC_API unsigned int rtcGetGeometryOppositeHalfEdge(RTCGeometry hgeometry, unsigned int topologyID, unsigned int edgeID)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometryOppositeHalfEdge);
- return geometry->getOppositeHalfEdge(topologyID,edgeID);
- RTC_CATCH_END2(geometry);
- return -1;
- }
-
- RTC_API void rtcSetGeometryOccludedFunction (RTCGeometry hgeometry, RTCOccludedFunctionN occluded)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetOccludedFunctionN);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setOccludedFunctionN(occluded);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryIntersectFilterFunction (RTCGeometry hgeometry, RTCFilterFunctionN filter)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryIntersectFilterFunction);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setIntersectionFilterFunctionN(filter);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcSetGeometryOccludedFilterFunction (RTCGeometry hgeometry, RTCFilterFunctionN filter)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcSetGeometryOccludedFilterFunction);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->setOcclusionFilterFunctionN(filter);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcInterpolate(const RTCInterpolateArguments* const args)
- {
- Geometry* geometry = (Geometry*) args->geometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcInterpolate);
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(args->geometry);
-#endif
- geometry->interpolate(args);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcInterpolateN(const RTCInterpolateNArguments* const args)
- {
- Geometry* geometry = (Geometry*) args->geometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcInterpolateN);
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(args->geometry);
-#endif
- geometry->interpolateN(args);
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcCommitGeometry (RTCGeometry hgeometry)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcCommitGeometry);
- RTC_VERIFY_HANDLE(hgeometry);
- return geometry->commit();
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API unsigned int rtcAttachGeometry (RTCScene hscene, RTCGeometry hgeometry)
- {
- Scene* scene = (Scene*) hscene;
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcAttachGeometry);
- RTC_VERIFY_HANDLE(hscene);
- RTC_VERIFY_HANDLE(hgeometry);
- if (scene->device != geometry->device)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"inputs are from different devices");
- return scene->bind(RTC_INVALID_GEOMETRY_ID,geometry);
- RTC_CATCH_END2(scene);
- return -1;
- }
-
- RTC_API void rtcAttachGeometryByID (RTCScene hscene, RTCGeometry hgeometry, unsigned int geomID)
- {
- Scene* scene = (Scene*) hscene;
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcAttachGeometryByID);
- RTC_VERIFY_HANDLE(hscene);
- RTC_VERIFY_HANDLE(hgeometry);
- RTC_VERIFY_GEOMID(geomID);
- if (scene->device != geometry->device)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"inputs are from different devices");
- scene->bind(geomID,geometry);
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcDetachGeometry (RTCScene hscene, unsigned int geomID)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcDetachGeometry);
- RTC_VERIFY_HANDLE(hscene);
- RTC_VERIFY_GEOMID(geomID);
- scene->detachGeometry(geomID);
- RTC_CATCH_END2(scene);
- }
-
- RTC_API void rtcRetainGeometry (RTCGeometry hgeometry)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcRetainGeometry);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->refInc();
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API void rtcReleaseGeometry (RTCGeometry hgeometry)
- {
- Geometry* geometry = (Geometry*) hgeometry;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcReleaseGeometry);
- RTC_VERIFY_HANDLE(hgeometry);
- geometry->refDec();
- RTC_CATCH_END2(geometry);
- }
-
- RTC_API RTCGeometry rtcGetGeometry (RTCScene hscene, unsigned int geomID)
- {
- Scene* scene = (Scene*) hscene;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcGetGeometry);
-#if defined(DEBUG)
- RTC_VERIFY_HANDLE(hscene);
- RTC_VERIFY_GEOMID(geomID);
-#endif
- return (RTCGeometry) scene->get(geomID);
- RTC_CATCH_END2(scene);
- return nullptr;
- }
-
-RTC_NAMESPACE_END
diff --git a/thirdparty/embree-aarch64/kernels/common/rtcore.h b/thirdparty/embree-aarch64/kernels/common/rtcore.h
deleted file mode 100644
index 4b070e122b..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/rtcore.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../../include/embree3/rtcore.h"
-RTC_NAMESPACE_USE
-
-namespace embree
-{
- /*! decoding of intersection flags */
- __forceinline bool isCoherent (RTCIntersectContextFlags flags) { return (flags & RTC_INTERSECT_CONTEXT_FLAG_COHERENT) == RTC_INTERSECT_CONTEXT_FLAG_COHERENT; }
- __forceinline bool isIncoherent(RTCIntersectContextFlags flags) { return (flags & RTC_INTERSECT_CONTEXT_FLAG_COHERENT) == RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT; }
-
-#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR >= 8)
-# define USE_TASK_ARENA 1
-#else
-# define USE_TASK_ARENA 0
-#endif
-
-#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION >= 11009) // TBB 2019 Update 9
-# define TASKING_TBB_USE_TASK_ISOLATION 1
-#else
-# define TASKING_TBB_USE_TASK_ISOLATION 0
-#endif
-
-/*! Macros used in the rtcore API implementation */
-// -- GODOT start --
-// #define RTC_CATCH_BEGIN try {
-#define RTC_CATCH_BEGIN
-
-// #define RTC_CATCH_END(device) \
-// } catch (std::bad_alloc&) { \
-// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-// } catch (rtcore_error& e) { \
-// Device::process_error(device,e.error,e.what()); \
-// } catch (std::exception& e) { \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-// } catch (...) { \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-// }
-#define RTC_CATCH_END(device)
-
-// #define RTC_CATCH_END2(scene) \
-// } catch (std::bad_alloc&) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-// } catch (rtcore_error& e) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,e.error,e.what()); \
-// } catch (std::exception& e) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-// } catch (...) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-// }
-#define RTC_CATCH_END2(scene)
-
-// #define RTC_CATCH_END2_FALSE(scene) \
-// } catch (std::bad_alloc&) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-// return false; \
-// } catch (rtcore_error& e) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,e.error,e.what()); \
-// return false; \
-// } catch (std::exception& e) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-// return false; \
-// } catch (...) { \
-// Device* device = scene ? scene->device : nullptr; \
-// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-// return false; \
-// }
-#define RTC_CATCH_END2_FALSE(scene) return false;
-// -- GODOT end --
-
-#define RTC_VERIFY_HANDLE(handle) \
- if (handle == nullptr) { \
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"invalid argument"); \
- }
-
-#define RTC_VERIFY_GEOMID(id) \
- if (id == RTC_INVALID_GEOMETRY_ID) { \
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"invalid argument"); \
- }
-
-#define RTC_VERIFY_UPPER(id,upper) \
- if (id > upper) { \
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"invalid argument"); \
- }
-
-#define RTC_VERIFY_RANGE(id,lower,upper) \
- if (id < lower || id > upper) \
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"argument out of bounds");
-
-#if 0 // enable to debug print all API calls
-#define RTC_TRACE(x) std::cout << #x << std::endl;
-#else
-#define RTC_TRACE(x)
-#endif
-
-// -- GODOT begin --
-// /*! used to throw embree API errors */
-// struct rtcore_error : public std::exception
-// {
-// __forceinline rtcore_error(RTCError error, const std::string& str)
-// : error(error), str(str) {}
-//
-// ~rtcore_error() throw() {}
-//
-// const char* what () const throw () {
-// return str.c_str();
-// }
-//
-// RTCError error;
-// std::string str;
-// };
-// -- GODOT end --
-
-#if defined(DEBUG) // only report file and line in debug mode
- // -- GODOT begin --
- // #define throw_RTCError(error,str) \
- // throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
- #define throw_RTCError(error,str) \
- printf(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)), abort();
- // -- GODOT end --
-#else
- // -- GODOT begin --
- // #define throw_RTCError(error,str) \
- // throw rtcore_error(error,str);
- #define throw_RTCError(error,str) \
- abort();
- // -- GODOT end --
-#endif
-
-#define RTC_BUILD_ARGUMENTS_HAS(settings,member) \
- (settings.byteSize > (offsetof(RTCBuildArguments,member)+sizeof(settings.member)))
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/rtcore_builder.cpp b/thirdparty/embree-aarch64/kernels/common/rtcore_builder.cpp
deleted file mode 100644
index 6bb96bba07..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/rtcore_builder.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#define RTC_EXPORT_API
-
-#include "default.h"
-#include "device.h"
-#include "scene.h"
-#include "context.h"
-#include "alloc.h"
-
-#include "../builders/bvh_builder_sah.h"
-#include "../builders/bvh_builder_morton.h"
-
-namespace embree
-{
- namespace isa // FIXME: support more ISAs for builders
- {
- struct BVH : public RefCount
- {
- BVH (Device* device)
- : device(device), allocator(device,true), morton_src(device,0), morton_tmp(device,0)
- {
- device->refInc();
- }
-
- ~BVH() {
- device->refDec();
- }
-
- public:
- Device* device;
- FastAllocator allocator;
- mvector<BVHBuilderMorton::BuildPrim> morton_src;
- mvector<BVHBuilderMorton::BuildPrim> morton_tmp;
- };
-
- void* rtcBuildBVHMorton(const RTCBuildArguments* arguments)
- {
- BVH* bvh = (BVH*) arguments->bvh;
- RTCBuildPrimitive* prims_i = arguments->primitives;
- size_t primitiveCount = arguments->primitiveCount;
- RTCCreateNodeFunction createNode = arguments->createNode;
- RTCSetNodeChildrenFunction setNodeChildren = arguments->setNodeChildren;
- RTCSetNodeBoundsFunction setNodeBounds = arguments->setNodeBounds;
- RTCCreateLeafFunction createLeaf = arguments->createLeaf;
- RTCProgressMonitorFunction buildProgress = arguments->buildProgress;
- void* userPtr = arguments->userPtr;
-
- std::atomic<size_t> progress(0);
-
- /* initialize temporary arrays for morton builder */
- PrimRef* prims = (PrimRef*) prims_i;
- mvector<BVHBuilderMorton::BuildPrim>& morton_src = bvh->morton_src;
- mvector<BVHBuilderMorton::BuildPrim>& morton_tmp = bvh->morton_tmp;
- morton_src.resize(primitiveCount);
- morton_tmp.resize(primitiveCount);
-
- /* compute centroid bounds */
- const BBox3fa centBounds = parallel_reduce ( size_t(0), primitiveCount, BBox3fa(empty), [&](const range<size_t>& r) -> BBox3fa {
-
- BBox3fa bounds(empty);
- for (size_t i=r.begin(); i<r.end(); i++)
- bounds.extend(prims[i].bounds().center2());
- return bounds;
- }, BBox3fa::merge);
-
- /* compute morton codes */
- BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
- parallel_for ( size_t(0), primitiveCount, [&](const range<size_t>& r) {
- BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton_src[r.begin()]);
- for (size_t i=r.begin(); i<r.end(); i++) {
- generator(prims[i].bounds(),(unsigned) i);
- }
- });
-
- /* start morton build */
- std::pair<void*,BBox3fa> root = BVHBuilderMorton::build<std::pair<void*,BBox3fa>>(
-
- /* thread local allocator for fast allocations */
- [&] () -> FastAllocator::CachedAllocator {
- return bvh->allocator.getCachedAllocator();
- },
-
- /* lambda function that allocates BVH nodes */
- [&] ( const FastAllocator::CachedAllocator& alloc, size_t N ) -> void* {
- return createNode((RTCThreadLocalAllocator)&alloc, (unsigned int)N,userPtr);
- },
-
- /* lambda function that sets bounds */
- [&] (void* node, const std::pair<void*,BBox3fa>* children, size_t N) -> std::pair<void*,BBox3fa>
- {
- BBox3fa bounds = empty;
- void* childptrs[BVHBuilderMorton::MAX_BRANCHING_FACTOR];
- const RTCBounds* cbounds[BVHBuilderMorton::MAX_BRANCHING_FACTOR];
- for (size_t i=0; i<N; i++) {
- bounds.extend(children[i].second);
- childptrs[i] = children[i].first;
- cbounds[i] = (const RTCBounds*)&children[i].second;
- }
- setNodeBounds(node,cbounds,(unsigned int)N,userPtr);
- setNodeChildren(node,childptrs, (unsigned int)N,userPtr);
- return std::make_pair(node,bounds);
- },
-
- /* lambda function that creates BVH leaves */
- [&]( const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc) -> std::pair<void*,BBox3fa>
- {
- RTCBuildPrimitive localBuildPrims[RTC_BUILD_MAX_PRIMITIVES_PER_LEAF];
- BBox3fa bounds = empty;
- for (size_t i=0;i<current.size();i++)
- {
- const size_t id = morton_src[current.begin()+i].index;
- bounds.extend(prims[id].bounds());
- localBuildPrims[i] = prims_i[id];
- }
- void* node = createLeaf((RTCThreadLocalAllocator)&alloc,localBuildPrims,current.size(),userPtr);
- return std::make_pair(node,bounds);
- },
-
- /* lambda that calculates the bounds for some primitive */
- [&] (const BVHBuilderMorton::BuildPrim& morton) -> BBox3fa {
- return prims[morton.index].bounds();
- },
-
- /* progress monitor function */
- [&] (size_t dn) {
- if (!buildProgress) return true;
- const size_t n = progress.fetch_add(dn)+dn;
- const double f = std::min(1.0,double(n)/double(primitiveCount));
- return buildProgress(userPtr,f);
- },
-
- morton_src.data(),morton_tmp.data(),primitiveCount,
- *arguments);
-
- bvh->allocator.cleanup();
- return root.first;
- }
-
- void* rtcBuildBVHBinnedSAH(const RTCBuildArguments* arguments)
- {
- BVH* bvh = (BVH*) arguments->bvh;
- RTCBuildPrimitive* prims = arguments->primitives;
- size_t primitiveCount = arguments->primitiveCount;
- RTCCreateNodeFunction createNode = arguments->createNode;
- RTCSetNodeChildrenFunction setNodeChildren = arguments->setNodeChildren;
- RTCSetNodeBoundsFunction setNodeBounds = arguments->setNodeBounds;
- RTCCreateLeafFunction createLeaf = arguments->createLeaf;
- RTCProgressMonitorFunction buildProgress = arguments->buildProgress;
- void* userPtr = arguments->userPtr;
-
- std::atomic<size_t> progress(0);
-
- /* calculate priminfo */
- auto computeBounds = [&](const range<size_t>& r) -> CentGeomBBox3fa
- {
- CentGeomBBox3fa bounds(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- bounds.extend((BBox3fa&)prims[j]);
- return bounds;
- };
- const CentGeomBBox3fa bounds =
- parallel_reduce(size_t(0),primitiveCount,size_t(1024),size_t(1024),CentGeomBBox3fa(empty), computeBounds, CentGeomBBox3fa::merge2);
-
- const PrimInfo pinfo(0,primitiveCount,bounds);
-
- /* build BVH */
- void* root = BVHBuilderBinnedSAH::build<void*>(
-
- /* thread local allocator for fast allocations */
- [&] () -> FastAllocator::CachedAllocator {
- return bvh->allocator.getCachedAllocator();
- },
-
- /* lambda function that creates BVH nodes */
- [&](BVHBuilderBinnedSAH::BuildRecord* children, const size_t N, const FastAllocator::CachedAllocator& alloc) -> void*
- {
- void* node = createNode((RTCThreadLocalAllocator)&alloc, (unsigned int)N,userPtr);
- const RTCBounds* cbounds[GeneralBVHBuilder::MAX_BRANCHING_FACTOR];
- for (size_t i=0; i<N; i++) cbounds[i] = (const RTCBounds*) &children[i].prims.geomBounds;
- setNodeBounds(node,cbounds, (unsigned int)N,userPtr);
- return node;
- },
-
- /* lambda function that updates BVH nodes */
- [&](const BVHBuilderBinnedSAH::BuildRecord& precord, const BVHBuilderBinnedSAH::BuildRecord* crecords, void* node, void** children, const size_t N) -> void* {
- setNodeChildren(node,children, (unsigned int)N,userPtr);
- return node;
- },
-
- /* lambda function that creates BVH leaves */
- [&](const PrimRef* prims, const range<size_t>& range, const FastAllocator::CachedAllocator& alloc) -> void* {
- return createLeaf((RTCThreadLocalAllocator)&alloc,(RTCBuildPrimitive*)(prims+range.begin()),range.size(),userPtr);
- },
-
- /* progress monitor function */
- [&] (size_t dn) {
- if (!buildProgress) return true;
- const size_t n = progress.fetch_add(dn)+dn;
- const double f = std::min(1.0,double(n)/double(primitiveCount));
- return buildProgress(userPtr,f);
- },
-
- (PrimRef*)prims,pinfo,*arguments);
-
- bvh->allocator.cleanup();
- return root;
- }
-
- static __forceinline const std::pair<CentGeomBBox3fa,unsigned int> mergePair(const std::pair<CentGeomBBox3fa,unsigned int>& a, const std::pair<CentGeomBBox3fa,unsigned int>& b) {
- CentGeomBBox3fa centBounds = CentGeomBBox3fa::merge2(a.first,b.first);
- unsigned int maxGeomID = max(a.second,b.second);
- return std::pair<CentGeomBBox3fa,unsigned int>(centBounds,maxGeomID);
- }
-
- void* rtcBuildBVHSpatialSAH(const RTCBuildArguments* arguments)
- {
- BVH* bvh = (BVH*) arguments->bvh;
- RTCBuildPrimitive* prims = arguments->primitives;
- size_t primitiveCount = arguments->primitiveCount;
- RTCCreateNodeFunction createNode = arguments->createNode;
- RTCSetNodeChildrenFunction setNodeChildren = arguments->setNodeChildren;
- RTCSetNodeBoundsFunction setNodeBounds = arguments->setNodeBounds;
- RTCCreateLeafFunction createLeaf = arguments->createLeaf;
- RTCSplitPrimitiveFunction splitPrimitive = arguments->splitPrimitive;
- RTCProgressMonitorFunction buildProgress = arguments->buildProgress;
- void* userPtr = arguments->userPtr;
-
- std::atomic<size_t> progress(0);
-
- /* calculate priminfo */
-
- auto computeBounds = [&](const range<size_t>& r) -> std::pair<CentGeomBBox3fa,unsigned int>
- {
- CentGeomBBox3fa bounds(empty);
- unsigned maxGeomID = 0;
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- bounds.extend((BBox3fa&)prims[j]);
- maxGeomID = max(maxGeomID,prims[j].geomID);
- }
- return std::pair<CentGeomBBox3fa,unsigned int>(bounds,maxGeomID);
- };
-
-
- const std::pair<CentGeomBBox3fa,unsigned int> pair =
- parallel_reduce(size_t(0),primitiveCount,size_t(1024),size_t(1024),std::pair<CentGeomBBox3fa,unsigned int>(CentGeomBBox3fa(empty),0), computeBounds, mergePair);
-
- CentGeomBBox3fa bounds = pair.first;
- const unsigned int maxGeomID = pair.second;
-
- if (unlikely(maxGeomID >= ((unsigned int)1 << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS))))
- {
- /* fallback code for max geomID larger than threshold */
- return rtcBuildBVHBinnedSAH(arguments);
- }
-
- const PrimInfo pinfo(0,primitiveCount,bounds);
-
- /* function that splits a build primitive */
- struct Splitter
- {
- Splitter (RTCSplitPrimitiveFunction splitPrimitive, unsigned geomID, unsigned primID, void* userPtr)
- : splitPrimitive(splitPrimitive), geomID(geomID), primID(primID), userPtr(userPtr) {}
-
- __forceinline void operator() (PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const
- {
- prim.geomIDref() &= BVHBuilderBinnedFastSpatialSAH::GEOMID_MASK;
- splitPrimitive((RTCBuildPrimitive*)&prim,(unsigned)dim,pos,(RTCBounds*)&left_o,(RTCBounds*)&right_o,userPtr);
- left_o.geomIDref() = geomID; left_o.primIDref() = primID;
- right_o.geomIDref() = geomID; right_o.primIDref() = primID;
- }
-
- __forceinline void operator() (const BBox3fa& box, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const
- {
- PrimRef prim(box,geomID & BVHBuilderBinnedFastSpatialSAH::GEOMID_MASK,primID);
- splitPrimitive((RTCBuildPrimitive*)&prim,(unsigned)dim,pos,(RTCBounds*)&left_o,(RTCBounds*)&right_o,userPtr);
- }
-
- RTCSplitPrimitiveFunction splitPrimitive;
- unsigned geomID;
- unsigned primID;
- void* userPtr;
- };
-
- /* build BVH */
- void* root = BVHBuilderBinnedFastSpatialSAH::build<void*>(
-
- /* thread local allocator for fast allocations */
- [&] () -> FastAllocator::CachedAllocator {
- return bvh->allocator.getCachedAllocator();
- },
-
- /* lambda function that creates BVH nodes */
- [&] (BVHBuilderBinnedFastSpatialSAH::BuildRecord* children, const size_t N, const FastAllocator::CachedAllocator& alloc) -> void*
- {
- void* node = createNode((RTCThreadLocalAllocator)&alloc, (unsigned int)N,userPtr);
- const RTCBounds* cbounds[GeneralBVHBuilder::MAX_BRANCHING_FACTOR];
- for (size_t i=0; i<N; i++) cbounds[i] = (const RTCBounds*) &children[i].prims.geomBounds;
- setNodeBounds(node,cbounds, (unsigned int)N,userPtr);
- return node;
- },
-
- /* lambda function that updates BVH nodes */
- [&] (const BVHBuilderBinnedFastSpatialSAH::BuildRecord& precord, const BVHBuilderBinnedFastSpatialSAH::BuildRecord* crecords, void* node, void** children, const size_t N) -> void* {
- setNodeChildren(node,children, (unsigned int)N,userPtr);
- return node;
- },
-
- /* lambda function that creates BVH leaves */
- [&] (const PrimRef* prims, const range<size_t>& range, const FastAllocator::CachedAllocator& alloc) -> void* {
- return createLeaf((RTCThreadLocalAllocator)&alloc,(RTCBuildPrimitive*)(prims+range.begin()),range.size(),userPtr);
- },
-
- /* returns the splitter */
- [&] ( const PrimRef& prim ) -> Splitter {
- return Splitter(splitPrimitive,prim.geomID(),prim.primID(),userPtr);
- },
-
- /* progress monitor function */
- [&] (size_t dn) {
- if (!buildProgress) return true;
- const size_t n = progress.fetch_add(dn)+dn;
- const double f = std::min(1.0,double(n)/double(primitiveCount));
- return buildProgress(userPtr,f);
- },
-
- (PrimRef*)prims,
- arguments->primitiveArrayCapacity,
- pinfo,*arguments);
-
- bvh->allocator.cleanup();
- return root;
- }
- }
-}
-
-using namespace embree;
-using namespace embree::isa;
-
-RTC_NAMESPACE_BEGIN
-
- RTC_API RTCBVH rtcNewBVH(RTCDevice device)
- {
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcNewAllocator);
- RTC_VERIFY_HANDLE(device);
- BVH* bvh = new BVH((Device*)device);
- return (RTCBVH) bvh->refInc();
- RTC_CATCH_END((Device*)device);
- return nullptr;
- }
-
- RTC_API void* rtcBuildBVH(const RTCBuildArguments* arguments)
- {
- BVH* bvh = (BVH*) arguments->bvh;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcBuildBVH);
- RTC_VERIFY_HANDLE(bvh);
- RTC_VERIFY_HANDLE(arguments);
- RTC_VERIFY_HANDLE(arguments->createNode);
- RTC_VERIFY_HANDLE(arguments->setNodeChildren);
- RTC_VERIFY_HANDLE(arguments->setNodeBounds);
- RTC_VERIFY_HANDLE(arguments->createLeaf);
-
- if (arguments->primitiveArrayCapacity < arguments->primitiveCount)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"primitiveArrayCapacity must be greater or equal to primitiveCount")
-
- /* initialize the allocator */
- bvh->allocator.init_estimate(arguments->primitiveCount*sizeof(BBox3fa));
- bvh->allocator.reset();
-
- /* switch between differnet builders based on quality level */
- if (arguments->buildQuality == RTC_BUILD_QUALITY_LOW)
- return rtcBuildBVHMorton(arguments);
- else if (arguments->buildQuality == RTC_BUILD_QUALITY_MEDIUM)
- return rtcBuildBVHBinnedSAH(arguments);
- else if (arguments->buildQuality == RTC_BUILD_QUALITY_HIGH) {
- if (arguments->splitPrimitive == nullptr || arguments->primitiveArrayCapacity <= arguments->primitiveCount)
- return rtcBuildBVHBinnedSAH(arguments);
- else
- return rtcBuildBVHSpatialSAH(arguments);
- }
- else
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid build quality");
-
- /* if we are in dynamic mode, then do not clear temporary data */
- if (!(arguments->buildFlags & RTC_BUILD_FLAG_DYNAMIC))
- {
- bvh->morton_src.clear();
- bvh->morton_tmp.clear();
- }
-
- RTC_CATCH_END(bvh->device);
- return nullptr;
- }
-
- RTC_API void* rtcThreadLocalAlloc(RTCThreadLocalAllocator localAllocator, size_t bytes, size_t align)
- {
- FastAllocator::CachedAllocator* alloc = (FastAllocator::CachedAllocator*) localAllocator;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcThreadLocalAlloc);
- return alloc->malloc0(bytes,align);
- RTC_CATCH_END(alloc->alloc->getDevice());
- return nullptr;
- }
-
- RTC_API void rtcMakeStaticBVH(RTCBVH hbvh)
- {
- BVH* bvh = (BVH*) hbvh;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcStaticBVH);
- RTC_VERIFY_HANDLE(hbvh);
- bvh->morton_src.clear();
- bvh->morton_tmp.clear();
- RTC_CATCH_END(bvh->device);
- }
-
- RTC_API void rtcRetainBVH(RTCBVH hbvh)
- {
- BVH* bvh = (BVH*) hbvh;
- Device* device = bvh ? bvh->device : nullptr;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcRetainBVH);
- RTC_VERIFY_HANDLE(hbvh);
- bvh->refInc();
- RTC_CATCH_END(device);
- }
-
- RTC_API void rtcReleaseBVH(RTCBVH hbvh)
- {
- BVH* bvh = (BVH*) hbvh;
- Device* device = bvh ? bvh->device : nullptr;
- RTC_CATCH_BEGIN;
- RTC_TRACE(rtcReleaseBVH);
- RTC_VERIFY_HANDLE(hbvh);
- bvh->refDec();
- RTC_CATCH_END(device);
- }
-
-RTC_NAMESPACE_END
diff --git a/thirdparty/embree-aarch64/kernels/common/scene.cpp b/thirdparty/embree-aarch64/kernels/common/scene.cpp
deleted file mode 100644
index 1e23aeb415..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene.cpp
+++ /dev/null
@@ -1,976 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "scene.h"
-
-#include "../bvh/bvh4_factory.h"
-#include "../bvh/bvh8_factory.h"
-#include "../../common/algorithms/parallel_reduce.h"
-
-namespace embree
-{
- /* error raising rtcIntersect and rtcOccluded functions */
- void missing_rtcCommit() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed"); }
- void invalid_rtcIntersect1() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect and rtcOccluded not enabled"); }
- void invalid_rtcIntersect4() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect4 and rtcOccluded4 not enabled"); }
- void invalid_rtcIntersect8() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect8 and rtcOccluded8 not enabled"); }
- void invalid_rtcIntersect16() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect16 and rtcOccluded16 not enabled"); }
- void invalid_rtcIntersectN() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectN and rtcOccludedN not enabled"); }
-
- Scene::Scene (Device* device)
- : device(device),
- flags_modified(true), enabled_geometry_types(0),
- scene_flags(RTC_SCENE_FLAG_NONE),
- quality_flags(RTC_BUILD_QUALITY_MEDIUM),
- is_build(false), modified(true),
- progressInterface(this), progress_monitor_function(nullptr), progress_monitor_ptr(nullptr), progress_monitor_counter(0)
- {
- device->refInc();
-
- intersectors = Accel::Intersectors(missing_rtcCommit);
-
- /* one can overwrite flags through device for debugging */
- if (device->quality_flags != -1)
- quality_flags = (RTCBuildQuality) device->quality_flags;
- if (device->scene_flags != -1)
- scene_flags = (RTCSceneFlags) device->scene_flags;
- }
-
- Scene::~Scene() noexcept
- {
- device->refDec();
- }
-
- void Scene::printStatistics()
- {
- /* calculate maximum number of time segments */
- unsigned max_time_steps = 0;
- for (size_t i=0; i<size(); i++) {
- if (!get(i)) continue;
- max_time_steps = max(max_time_steps,get(i)->numTimeSteps);
- }
-
- /* initialize vectors*/
- std::vector<size_t> statistics[Geometry::GTY_END];
- for (size_t i=0; i<Geometry::GTY_END; i++)
- statistics[i].resize(max_time_steps);
-
- /* gather statistics */
- for (size_t i=0; i<size(); i++)
- {
- if (!get(i)) continue;
- int ty = get(i)->getType();
- assert(ty<Geometry::GTY_END);
- int timesegments = get(i)->numTimeSegments();
- assert((unsigned int)timesegments < max_time_steps);
- statistics[ty][timesegments] += get(i)->size();
- }
-
- /* print statistics */
- std::cout << std::setw(23) << "segments" << ": ";
- for (size_t t=0; t<max_time_steps; t++)
- std::cout << std::setw(10) << t;
- std::cout << std::endl;
-
- std::cout << "-------------------------";
- for (size_t t=0; t<max_time_steps; t++)
- std::cout << "----------";
- std::cout << std::endl;
-
- for (size_t p=0; p<Geometry::GTY_END; p++)
- {
- if (std::string(Geometry::gtype_names[p]) == "") continue;
- std::cout << std::setw(23) << Geometry::gtype_names[p] << ": ";
- for (size_t t=0; t<max_time_steps; t++)
- std::cout << std::setw(10) << statistics[p][t];
- std::cout << std::endl;
- }
- }
-
- void Scene::createTriangleAccel()
- {
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- if (device->tri_accel == "default")
- {
- if (quality_flags != RTC_BUILD_QUALITY_LOW)
- {
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
- switch (mode) {
- case /*0b00*/ 0:
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX())
- {
- if (quality_flags == RTC_BUILD_QUALITY_HIGH)
- accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
- else
- accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
- }
- else
-#endif
- {
- if (quality_flags == RTC_BUILD_QUALITY_HIGH)
- accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
- else
- accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
- }
- break;
-
- case /*0b01*/ 1:
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX())
- accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
- else
-#endif
- accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
-
- break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- else /* dynamic */
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX())
- {
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
- switch (mode) {
- case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- else
-#endif
- {
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
- switch (mode) {
- case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- }
- }
- else if (device->tri_accel == "bvh4.triangle4") accels_add(device->bvh4_factory->BVH4Triangle4 (this));
- else if (device->tri_accel == "bvh4.triangle4v") accels_add(device->bvh4_factory->BVH4Triangle4v(this));
- else if (device->tri_accel == "bvh4.triangle4i") accels_add(device->bvh4_factory->BVH4Triangle4i(this));
- else if (device->tri_accel == "qbvh4.triangle4i") accels_add(device->bvh4_factory->BVH4QuantizedTriangle4i(this));
-
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->tri_accel == "bvh8.triangle4") accels_add(device->bvh8_factory->BVH8Triangle4 (this));
- else if (device->tri_accel == "bvh8.triangle4v") accels_add(device->bvh8_factory->BVH8Triangle4v(this));
- else if (device->tri_accel == "bvh8.triangle4i") accels_add(device->bvh8_factory->BVH8Triangle4i(this));
- else if (device->tri_accel == "qbvh8.triangle4i") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4i(this));
- else if (device->tri_accel == "qbvh8.triangle4") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4(this));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown triangle acceleration structure "+device->tri_accel);
-#endif
- }
-
- void Scene::createTriangleMBAccel()
- {
-#if defined(EMBREE_GEOMETRY_TRIANGLE)
- if (device->tri_accel_mb == "default")
- {
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
-
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX2()) // BVH8 reduces performance on AVX only-machines
- {
- switch (mode) {
- case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- else
-#endif
- {
- switch (mode) {
- case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- }
- else if (device->tri_accel_mb == "bvh4.triangle4imb") accels_add(device->bvh4_factory->BVH4Triangle4iMB(this));
- else if (device->tri_accel_mb == "bvh4.triangle4vmb") accels_add(device->bvh4_factory->BVH4Triangle4vMB(this));
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->tri_accel_mb == "bvh8.triangle4imb") accels_add(device->bvh8_factory->BVH8Triangle4iMB(this));
- else if (device->tri_accel_mb == "bvh8.triangle4vmb") accels_add(device->bvh8_factory->BVH8Triangle4vMB(this));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur triangle acceleration structure "+device->tri_accel_mb);
-#endif
- }
-
- void Scene::createQuadAccel()
- {
-#if defined(EMBREE_GEOMETRY_QUAD)
- if (device->quad_accel == "default")
- {
- if (quality_flags != RTC_BUILD_QUALITY_LOW)
- {
- /* static */
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
- switch (mode) {
- case /*0b00*/ 0:
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX())
- {
- if (quality_flags == RTC_BUILD_QUALITY_HIGH)
- accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
- else
- accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
- }
- else
-#endif
- {
- if (quality_flags == RTC_BUILD_QUALITY_HIGH)
- accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
- else
- accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
- }
- break;
-
- case /*0b01*/ 1:
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX())
- accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
- else
-#endif
- accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
- break;
-
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- else /* dynamic */
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX())
- {
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
- switch (mode) {
- case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- else
-#endif
- {
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
- switch (mode) {
- case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- }
- }
- else if (device->quad_accel == "bvh4.quad4v") accels_add(device->bvh4_factory->BVH4Quad4v(this));
- else if (device->quad_accel == "bvh4.quad4i") accels_add(device->bvh4_factory->BVH4Quad4i(this));
- else if (device->quad_accel == "qbvh4.quad4i") accels_add(device->bvh4_factory->BVH4QuantizedQuad4i(this));
-
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->quad_accel == "bvh8.quad4v") accels_add(device->bvh8_factory->BVH8Quad4v(this));
- else if (device->quad_accel == "bvh8.quad4i") accels_add(device->bvh8_factory->BVH8Quad4i(this));
- else if (device->quad_accel == "qbvh8.quad4i") accels_add(device->bvh8_factory->BVH8QuantizedQuad4i(this));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad acceleration structure "+device->quad_accel);
-#endif
- }
-
- void Scene::createQuadMBAccel()
- {
-#if defined(EMBREE_GEOMETRY_QUAD)
- if (device->quad_accel_mb == "default")
- {
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
- switch (mode) {
- case /*0b00*/ 0:
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX())
- accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
- else
-#endif
- accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
- break;
-
- case /*0b01*/ 1:
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX())
- accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
- else
-#endif
- accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
- break;
-
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- else if (device->quad_accel_mb == "bvh4.quad4imb") accels_add(device->bvh4_factory->BVH4Quad4iMB(this));
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->quad_accel_mb == "bvh8.quad4imb") accels_add(device->bvh8_factory->BVH8Quad4iMB(this));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad motion blur acceleration structure "+device->quad_accel_mb);
-#endif
- }
-
- void Scene::createHairAccel()
- {
-#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
- if (device->hair_accel == "default")
- {
- int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX2()) // only enable on HSW machines, for SNB this codepath is slower
- {
- switch (mode) {
- case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::ROBUST)); break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- else
-#endif
- {
- switch (mode) {
- case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::ROBUST)); break;
- case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST)); break;
- case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::ROBUST)); break;
- }
- }
- }
- else if (device->hair_accel == "bvh4obb.virtualcurve4v" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST));
- else if (device->hair_accel == "bvh4obb.virtualcurve4i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST));
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->hair_accel == "bvh8obb.virtualcurve8v" ) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST));
- else if (device->hair_accel == "bvh4obb.virtualcurve8i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown hair acceleration structure "+device->hair_accel);
-#endif
- }
-
- void Scene::createHairMBAccel()
- {
-#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
- if (device->hair_accel_mb == "default")
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX2()) // only enable on HSW machines, on SNB this codepath is slower
- {
- if (isRobustAccel()) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::ROBUST));
- else accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
- }
- else
-#endif
- {
- if (isRobustAccel()) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::ROBUST));
- else accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));
- }
- }
- else if (device->hair_accel_mb == "bvh4.virtualcurve4imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));
-
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->hair_accel_mb == "bvh4.virtualcurve8imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
- else if (device->hair_accel_mb == "bvh8.virtualcurve8imb") accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur hair acceleration structure "+device->hair_accel_mb);
-#endif
- }
-
- void Scene::createSubdivAccel()
- {
-#if defined(EMBREE_GEOMETRY_SUBDIVISION)
- if (device->subdiv_accel == "default") {
- accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
- }
- else if (device->subdiv_accel == "bvh4.grid.eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
- else if (device->subdiv_accel == "bvh4.subdivpatch1eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv accel "+device->subdiv_accel);
-#endif
- }
-
- void Scene::createSubdivMBAccel()
- {
-#if defined(EMBREE_GEOMETRY_SUBDIVISION)
- if (device->subdiv_accel_mb == "default") {
- accels_add(device->bvh4_factory->BVH4SubdivPatch1MB(this));
- }
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv mblur accel "+device->subdiv_accel_mb);
-#endif
- }
-
- void Scene::createUserGeometryAccel()
- {
-#if defined(EMBREE_GEOMETRY_USER)
- if (device->object_accel == "default")
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX() && !isCompactAccel())
- {
- if (quality_flags != RTC_BUILD_QUALITY_LOW) {
- accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::STATIC));
- } else {
- accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));
- }
- }
- else
-#endif
- {
- if (quality_flags != RTC_BUILD_QUALITY_LOW) {
- accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::STATIC));
- } else {
- accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));
- }
- }
- }
- else if (device->object_accel == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometry(this));
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->object_accel == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometry(this));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry accel "+device->object_accel);
-#endif
- }
-
- void Scene::createUserGeometryMBAccel()
- {
-#if defined(EMBREE_GEOMETRY_USER)
- if (device->object_accel_mb == "default" ) {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX() && !isCompactAccel())
- accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));
- else
-#endif
- accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));
- }
- else if (device->object_accel_mb == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->object_accel_mb == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry mblur accel "+device->object_accel_mb);
-#endif
- }
-
- void Scene::createInstanceAccel()
- {
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- // if (device->object_accel == "default")
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX() && !isCompactAccel()) {
- if (quality_flags != RTC_BUILD_QUALITY_LOW) {
- accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::STATIC));
- } else {
- accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));
- }
- }
- else
-#endif
- {
- if (quality_flags != RTC_BUILD_QUALITY_LOW) {
- accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::STATIC));
- } else {
- accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));
- }
- }
- }
- // else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
-#endif
- }
-
- void Scene::createInstanceMBAccel()
- {
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- //if (device->instance_accel_mb == "default")
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX() && !isCompactAccel())
- accels_add(device->bvh8_factory->BVH8InstanceMB(this, false));
- else
-#endif
- accels_add(device->bvh4_factory->BVH4InstanceMB(this, false));
- }
- //else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
-#endif
- }
-
- void Scene::createInstanceExpensiveAccel()
- {
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- // if (device->object_accel == "default")
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX() && !isCompactAccel()) {
- if (quality_flags != RTC_BUILD_QUALITY_LOW) {
- accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::STATIC));
- } else {
- accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));
- }
- }
- else
-#endif
- {
- if (quality_flags != RTC_BUILD_QUALITY_LOW) {
- accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::STATIC));
- } else {
- accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));
- }
- }
- }
- // else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
-#endif
- }
-
- void Scene::createInstanceExpensiveMBAccel()
- {
-#if defined(EMBREE_GEOMETRY_INSTANCE)
- //if (device->instance_accel_mb == "default")
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX() && !isCompactAccel())
- accels_add(device->bvh8_factory->BVH8InstanceMB(this, true));
- else
-#endif
- accels_add(device->bvh4_factory->BVH4InstanceMB(this, true));
- }
- //else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
-#endif
- }
-
- void Scene::createGridAccel()
- {
- BVHFactory::IntersectVariant ivariant = isRobustAccel() ? BVHFactory::IntersectVariant::ROBUST : BVHFactory::IntersectVariant::FAST;
-#if defined(EMBREE_GEOMETRY_GRID)
- if (device->grid_accel == "default")
- {
-#if defined (EMBREE_TARGET_SIMD8)
- if (device->canUseAVX() && !isCompactAccel())
- {
- accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
- }
- else
-#endif
- {
- accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
- }
- }
- else if (device->grid_accel == "bvh4.grid") accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
-#if defined (EMBREE_TARGET_SIMD8)
- else if (device->grid_accel == "bvh8.grid") accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
-#endif
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid accel "+device->grid_accel);
-#endif
-
- }
-
- void Scene::createGridMBAccel()
- {
-#if defined(EMBREE_GEOMETRY_GRID)
- if (device->grid_accel_mb == "default")
- {
- accels_add(device->bvh4_factory->BVH4GridMB(this,BVHFactory::BuildVariant::STATIC));
- }
- else if (device->grid_accel_mb == "bvh4mb.grid") accels_add(device->bvh4_factory->BVH4GridMB(this));
- else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid mb accel "+device->grid_accel);
-#endif
-
- }
-
- void Scene::clear() {
- }
-
- unsigned Scene::bind(unsigned geomID, Ref<Geometry> geometry)
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(geometriesMutex);
-#else
- Lock<SpinLock> lock(geometriesMutex);
-#endif
- if (geomID == RTC_INVALID_GEOMETRY_ID) {
- geomID = id_pool.allocate();
- if (geomID == RTC_INVALID_GEOMETRY_ID)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"too many geometries inside scene");
- }
- else
- {
- if (!id_pool.add(geomID))
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID provided");
- }
- if (geomID >= geometries.size()) {
- geometries.resize(geomID+1);
- vertices.resize(geomID+1);
- geometryModCounters_.resize(geomID+1);
- }
- geometries[geomID] = geometry;
- geometryModCounters_[geomID] = 0;
- if (geometry->isEnabled()) {
- setModified ();
- }
- return geomID;
- }
-
- void Scene::detachGeometry(size_t geomID)
- {
-#if defined(__aarch64__) && defined(BUILD_IOS)
- std::scoped_lock lock(geometriesMutex);
-#else
- Lock<SpinLock> lock(geometriesMutex);
-#endif
-
- if (geomID >= geometries.size())
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID");
-
- Ref<Geometry>& geometry = geometries[geomID];
- if (geometry == null)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry");
-
- if (geometry->isEnabled()) {
- setModified ();
- }
- accels_deleteGeometry(unsigned(geomID));
- id_pool.deallocate((unsigned)geomID);
- geometries[geomID] = null;
- vertices[geomID] = nullptr;
- geometryModCounters_[geomID] = 0;
- }
-
- void Scene::updateInterface()
- {
- is_build = true;
- }
-
- void Scene::commit_task ()
- {
- checkIfModifiedAndSet ();
- if (!isModified()) {
- return;
- }
-
- /* print scene statistics */
- if (device->verbosity(2))
- printStatistics();
-
- progress_monitor_counter = 0;
-
- /* gather scene stats and call preCommit function of each geometry */
- this->world = parallel_reduce (size_t(0), geometries.size(), GeometryCounts (),
- [this](const range<size_t>& r)->GeometryCounts
- {
- GeometryCounts c;
- for (auto i=r.begin(); i<r.end(); ++i)
- {
- if (geometries[i] && geometries[i]->isEnabled())
- {
- geometries[i]->preCommit();
- geometries[i]->addElementsToCount (c);
- c.numFilterFunctions += (int) geometries[i]->hasFilterFunctions();
- }
- }
- return c;
- },
- std::plus<GeometryCounts>()
- );
-
- /* select acceleration structures to build */
- unsigned int new_enabled_geometry_types = world.enabledGeometryTypesMask();
- if (flags_modified || new_enabled_geometry_types != enabled_geometry_types)
- {
- accels_init();
-
- /* we need to make all geometries modified, otherwise two level builder will
- not rebuild currently not modified geometries */
- parallel_for(geometryModCounters_.size(), [&] ( const size_t i ) {
- geometryModCounters_[i] = 0;
- });
-
- if (getNumPrimitives(TriangleMesh::geom_type,false)) createTriangleAccel();
- if (getNumPrimitives(TriangleMesh::geom_type,true)) createTriangleMBAccel();
- if (getNumPrimitives(QuadMesh::geom_type,false)) createQuadAccel();
- if (getNumPrimitives(QuadMesh::geom_type,true)) createQuadMBAccel();
- if (getNumPrimitives(GridMesh::geom_type,false)) createGridAccel();
- if (getNumPrimitives(GridMesh::geom_type,true)) createGridMBAccel();
- if (getNumPrimitives(SubdivMesh::geom_type,false)) createSubdivAccel();
- if (getNumPrimitives(SubdivMesh::geom_type,true)) createSubdivMBAccel();
- if (getNumPrimitives(Geometry::MTY_CURVES,false)) createHairAccel();
- if (getNumPrimitives(Geometry::MTY_CURVES,true)) createHairMBAccel();
- if (getNumPrimitives(UserGeometry::geom_type,false)) createUserGeometryAccel();
- if (getNumPrimitives(UserGeometry::geom_type,true)) createUserGeometryMBAccel();
- if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,false)) createInstanceAccel();
- if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,true)) createInstanceMBAccel();
- if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,false)) createInstanceExpensiveAccel();
- if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,true)) createInstanceExpensiveMBAccel();
-
- flags_modified = false;
- enabled_geometry_types = new_enabled_geometry_types;
- }
-
- /* select fast code path if no filter function is present */
- accels_select(hasFilterFunction());
-
- /* build all hierarchies of this scene */
- accels_build();
-
- /* make static geometry immutable */
- if (!isDynamicAccel()) {
- accels_immutable();
- flags_modified = true; // in non-dynamic mode we have to re-create accels
- }
-
- /* call postCommit function of each geometry */
- parallel_for(geometries.size(), [&] ( const size_t i ) {
- if (geometries[i] && geometries[i]->isEnabled()) {
- geometries[i]->postCommit();
- vertices[i] = geometries[i]->getCompactVertexArray();
- geometryModCounters_[i] = geometries[i]->getModCounter();
- }
- });
-
- updateInterface();
-
- if (device->verbosity(2)) {
- std::cout << "created scene intersector" << std::endl;
- accels_print(2);
- std::cout << "selected scene intersector" << std::endl;
- intersectors.print(2);
- }
-
- setModified(false);
- }
-
- void Scene::setBuildQuality(RTCBuildQuality quality_flags_i)
- {
- if (quality_flags == quality_flags_i) return;
- quality_flags = quality_flags_i;
- flags_modified = true;
- }
-
- RTCBuildQuality Scene::getBuildQuality() const {
- return quality_flags;
- }
-
- void Scene::setSceneFlags(RTCSceneFlags scene_flags_i)
- {
- if (scene_flags == scene_flags_i) return;
- scene_flags = scene_flags_i;
- flags_modified = true;
- }
-
- RTCSceneFlags Scene::getSceneFlags() const {
- return scene_flags;
- }
-
-#if defined(TASKING_INTERNAL)
-
- void Scene::commit (bool join)
- {
- Lock<MutexSys> buildLock(buildMutex,false);
-
- /* allocates own taskscheduler for each build */
- Ref<TaskScheduler> scheduler = nullptr;
- {
- Lock<MutexSys> lock(schedulerMutex);
- scheduler = this->scheduler;
- if (scheduler == null) {
- buildLock.lock();
- this->scheduler = scheduler = new TaskScheduler;
- }
- }
-
- /* worker threads join build */
- if (!buildLock.isLocked())
- {
- if (!join)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"use rtcJoinCommitScene to join a build operation");
-
- scheduler->join();
- return;
- }
-
- /* initiate build */
- // -- GODOT start --
- // try {
- scheduler->spawn_root([&]() { commit_task(); Lock<MutexSys> lock(schedulerMutex); this->scheduler = nullptr; }, 1, !join);
- // }
- // catch (...) {
- // accels_clear();
- // updateInterface();
- // Lock<MutexSys> lock(schedulerMutex);
- // this->scheduler = nullptr;
- // throw;
- // }
- // -- GODOT end --
- }
-
-#endif
-
-#if defined(TASKING_TBB) || defined(TASKING_GCD)
-
- void Scene::commit (bool join)
- {
-#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)
- if (join)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with this TBB version");
-#endif
-
- /* try to obtain build lock */
- Lock<MutexSys> lock(buildMutex,buildMutex.try_lock());
-
- /* join hierarchy build */
- if (!lock.isLocked())
- {
-#if !TASKING_TBB_USE_TASK_ISOLATION
- if (!join)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invoking rtcCommitScene from multiple threads is not supported with this TBB version");
-#endif
-
- do {
-
-#if defined(TASKING_GCD)
- // Do Nothing
-#else
-#if USE_TASK_ARENA
- if (join) {
- device->arena->execute([&]{ group.wait(); });
- }
- else
-#endif
- {
- group.wait();
- }
-#endif
-
- pause_cpu();
- yield();
-
- } while (!buildMutex.try_lock());
-
- buildMutex.unlock();
- return;
- }
-
- /* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
- const unsigned int mxcsr = _mm_getcsr();
- _mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
-
- try {
-#if defined(TASKING_TBB)
-#if TBB_INTERFACE_VERSION_MAJOR < 8
- tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits);
-#else
- tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits | tbb::task_group_context::fp_settings );
-#endif
- //ctx.set_priority(tbb::priority_high);
-
-#if USE_TASK_ARENA
- if (join)
- {
- device->arena->execute([&]{
- group.run([&]{
- tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
- });
- group.wait();
- });
- }
- else
-#endif
- {
- group.run([&]{
- tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
- });
- group.wait();
- }
-
- /* reset MXCSR register again */
- _mm_setcsr(mxcsr);
-
-#elif defined(TASKING_GCD)
-
- commit_task();
-
-#endif // #if defined(TASKING_TBB)
-
- }
- catch (...)
- {
- /* reset MXCSR register again */
- _mm_setcsr(mxcsr);
-
- accels_clear();
- updateInterface();
- throw;
- }
- }
-#endif
-
-#if defined(TASKING_PPL)
-
- void Scene::commit (bool join)
- {
-#if defined(TASKING_PPL)
- if (join)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with PPL");
-#endif
-
- /* try to obtain build lock */
- Lock<MutexSys> lock(buildMutex);
-
- checkIfModifiedAndSet ();
- if (!isModified()) {
- return;
- }
-
- /* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
- const unsigned int mxcsr = _mm_getcsr();
- _mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
-
- try {
-
- group.run([&]{
- concurrency::parallel_for(size_t(0), size_t(1), size_t(1), [&](size_t) { commit_task(); });
- });
- group.wait();
-
- /* reset MXCSR register again */
- _mm_setcsr(mxcsr);
- }
- catch (...)
- {
- /* reset MXCSR register again */
- _mm_setcsr(mxcsr);
-
- accels_clear();
- updateInterface();
- throw;
- }
- }
-#endif
-
- void Scene::setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr)
- {
- progress_monitor_function = func;
- progress_monitor_ptr = ptr;
- }
-
- void Scene::progressMonitor(double dn)
- {
- if (progress_monitor_function) {
- size_t n = size_t(dn) + progress_monitor_counter.fetch_add(size_t(dn));
- if (!progress_monitor_function(progress_monitor_ptr, n / (double(numPrimitives())))) {
- throw_RTCError(RTC_ERROR_CANCELLED,"progress monitor forced termination");
- }
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene.h b/thirdparty/embree-aarch64/kernels/common/scene.h
deleted file mode 100644
index b41c6cde91..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene.h
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "device.h"
-#include "builder.h"
-#include "../../common/algorithms/parallel_any_of.h"
-#include "scene_triangle_mesh.h"
-#include "scene_quad_mesh.h"
-#include "scene_user_geometry.h"
-#include "scene_instance.h"
-#include "scene_curves.h"
-#include "scene_line_segments.h"
-#include "scene_subdiv_mesh.h"
-#include "scene_grid_mesh.h"
-#include "scene_points.h"
-#include "../subdiv/tessellation_cache.h"
-
-#include "acceln.h"
-#include "geometry.h"
-
-namespace embree
-{
- /*! Base class all scenes are derived from */
- class Scene : public AccelN
- {
- ALIGNED_CLASS_(std::alignment_of<Scene>::value);
-
- public:
- template<typename Ty, bool mblur = false>
- class Iterator
- {
- public:
- Iterator () {}
-
- Iterator (Scene* scene, bool all = false)
- : scene(scene), all(all) {}
-
- __forceinline Ty* at(const size_t i)
- {
- Geometry* geom = scene->geometries[i].ptr;
- if (geom == nullptr) return nullptr;
- if (!all && !geom->isEnabled()) return nullptr;
- const size_t mask = geom->getTypeMask() & Ty::geom_type;
- if (!(mask)) return nullptr;
- if ((geom->numTimeSteps != 1) != mblur) return nullptr;
- return (Ty*) geom;
- }
-
- __forceinline Ty* operator[] (const size_t i) {
- return at(i);
- }
-
- __forceinline size_t size() const {
- return scene->size();
- }
-
- __forceinline size_t numPrimitives() const {
- return scene->getNumPrimitives(Ty::geom_type,mblur);
- }
-
- __forceinline size_t maxPrimitivesPerGeometry()
- {
- size_t ret = 0;
- for (size_t i=0; i<scene->size(); i++) {
- Ty* mesh = at(i);
- if (mesh == nullptr) continue;
- ret = max(ret,mesh->size());
- }
- return ret;
- }
-
- __forceinline unsigned int maxGeomID()
- {
- unsigned int ret = 0;
- for (size_t i=0; i<scene->size(); i++) {
- Ty* mesh = at(i);
- if (mesh == nullptr) continue;
- ret = max(ret,(unsigned int)i);
- }
- return ret;
- }
-
- __forceinline unsigned maxTimeStepsPerGeometry()
- {
- unsigned ret = 0;
- for (size_t i=0; i<scene->size(); i++) {
- Ty* mesh = at(i);
- if (mesh == nullptr) continue;
- ret = max(ret,mesh->numTimeSteps);
- }
- return ret;
- }
-
- private:
- Scene* scene;
- bool all;
- };
-
- class Iterator2
- {
- public:
- Iterator2 () {}
-
- Iterator2 (Scene* scene, Geometry::GTypeMask typemask, bool mblur)
- : scene(scene), typemask(typemask), mblur(mblur) {}
-
- __forceinline Geometry* at(const size_t i)
- {
- Geometry* geom = scene->geometries[i].ptr;
- if (geom == nullptr) return nullptr;
- if (!geom->isEnabled()) return nullptr;
- if (!(geom->getTypeMask() & typemask)) return nullptr;
- if ((geom->numTimeSteps != 1) != mblur) return nullptr;
- return geom;
- }
-
- __forceinline Geometry* operator[] (const size_t i) {
- return at(i);
- }
-
- __forceinline size_t size() const {
- return scene->size();
- }
-
- private:
- Scene* scene;
- Geometry::GTypeMask typemask;
- bool mblur;
- };
-
- public:
-
- /*! Scene construction */
- Scene (Device* device);
-
- /*! Scene destruction */
- ~Scene () noexcept;
-
- private:
- /*! class is non-copyable */
- Scene (const Scene& other) DELETED; // do not implement
- Scene& operator= (const Scene& other) DELETED; // do not implement
-
- public:
- void createTriangleAccel();
- void createTriangleMBAccel();
- void createQuadAccel();
- void createQuadMBAccel();
- void createHairAccel();
- void createHairMBAccel();
- void createSubdivAccel();
- void createSubdivMBAccel();
- void createUserGeometryAccel();
- void createUserGeometryMBAccel();
- void createInstanceAccel();
- void createInstanceMBAccel();
- void createInstanceExpensiveAccel();
- void createInstanceExpensiveMBAccel();
- void createGridAccel();
- void createGridMBAccel();
-
- /*! prints statistics about the scene */
- void printStatistics();
-
- /*! clears the scene */
- void clear();
-
- /*! detaches some geometry */
- void detachGeometry(size_t geomID);
-
- void setBuildQuality(RTCBuildQuality quality_flags);
- RTCBuildQuality getBuildQuality() const;
-
- void setSceneFlags(RTCSceneFlags scene_flags);
- RTCSceneFlags getSceneFlags() const;
-
- void commit (bool join);
- void commit_task ();
- void build () {}
-
- void updateInterface();
-
- /* return number of geometries */
- __forceinline size_t size() const { return geometries.size(); }
-
- /* bind geometry to the scene */
- unsigned int bind (unsigned geomID, Ref<Geometry> geometry);
-
- /* determines if scene is modified */
- __forceinline bool isModified() const { return modified; }
-
- /* sets modified flag */
- __forceinline void setModified(bool f = true) {
- modified = f;
- }
-
- __forceinline bool isGeometryModified(size_t geomID)
- {
- Ref<Geometry>& g = geometries[geomID];
- if (!g) return false;
- return g->getModCounter() > geometryModCounters_[geomID];
- }
-
- protected:
-
- __forceinline void checkIfModifiedAndSet ()
- {
- if (isModified ()) return;
-
- auto geometryIsModified = [this](size_t geomID)->bool {
- return isGeometryModified(geomID);
- };
-
- if (parallel_any_of (size_t(0), geometries.size (), geometryIsModified)) {
- setModified ();
- }
- }
-
- public:
-
- /* get mesh by ID */
- __forceinline Geometry* get(size_t i) { assert(i < geometries.size()); return geometries[i].ptr; }
- __forceinline const Geometry* get(size_t i) const { assert(i < geometries.size()); return geometries[i].ptr; }
-
- template<typename Mesh>
- __forceinline Mesh* get(size_t i) {
- assert(i < geometries.size());
- assert(geometries[i]->getTypeMask() & Mesh::geom_type);
- return (Mesh*)geometries[i].ptr;
- }
- template<typename Mesh>
- __forceinline const Mesh* get(size_t i) const {
- assert(i < geometries.size());
- assert(geometries[i]->getTypeMask() & Mesh::geom_type);
- return (Mesh*)geometries[i].ptr;
- }
-
- template<typename Mesh>
- __forceinline Mesh* getSafe(size_t i) {
- assert(i < geometries.size());
- if (geometries[i] == null) return nullptr;
- if (!(geometries[i]->getTypeMask() & Mesh::geom_type)) return nullptr;
- else return (Mesh*) geometries[i].ptr;
- }
-
- __forceinline Ref<Geometry> get_locked(size_t i) {
- Lock<SpinLock> lock(geometriesMutex);
- assert(i < geometries.size());
- return geometries[i];
- }
-
- /* flag decoding */
- __forceinline bool isFastAccel() const { return !isCompactAccel() && !isRobustAccel(); }
- __forceinline bool isCompactAccel() const { return scene_flags & RTC_SCENE_FLAG_COMPACT; }
- __forceinline bool isRobustAccel() const { return scene_flags & RTC_SCENE_FLAG_ROBUST; }
- __forceinline bool isStaticAccel() const { return !(scene_flags & RTC_SCENE_FLAG_DYNAMIC); }
- __forceinline bool isDynamicAccel() const { return scene_flags & RTC_SCENE_FLAG_DYNAMIC; }
-
- __forceinline bool hasContextFilterFunction() const {
- return scene_flags & RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION;
- }
-
- __forceinline bool hasGeometryFilterFunction() {
- return world.numFilterFunctions != 0;
- }
-
- __forceinline bool hasFilterFunction() {
- return hasContextFilterFunction() || hasGeometryFilterFunction();
- }
-
- /* test if scene got already build */
- __forceinline bool isBuild() const { return is_build; }
-
- public:
- IDPool<unsigned,0xFFFFFFFE> id_pool;
- vector<Ref<Geometry>> geometries; //!< list of all user geometries
- vector<unsigned int> geometryModCounters_;
- vector<float*> vertices;
-
- public:
- Device* device;
-
- /* these are to detect if we need to recreate the acceleration structures */
- bool flags_modified;
- unsigned int enabled_geometry_types;
-
- RTCSceneFlags scene_flags;
- RTCBuildQuality quality_flags;
- MutexSys buildMutex;
- SpinLock geometriesMutex;
- bool is_build;
- private:
- bool modified; //!< true if scene got modified
-
- public:
-
- /*! global lock step task scheduler */
-#if defined(TASKING_INTERNAL)
- MutexSys schedulerMutex;
- Ref<TaskScheduler> scheduler;
-#elif defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION
- tbb::isolated_task_group group;
-#elif defined(TASKING_TBB)
- tbb::task_group group;
-#elif defined(TASKING_PPL)
- concurrency::task_group group;
-#endif
-
- public:
- struct BuildProgressMonitorInterface : public BuildProgressMonitor {
- BuildProgressMonitorInterface(Scene* scene)
- : scene(scene) {}
- void operator() (size_t dn) const { scene->progressMonitor(double(dn)); }
- private:
- Scene* scene;
- };
- BuildProgressMonitorInterface progressInterface;
- RTCProgressMonitorFunction progress_monitor_function;
- void* progress_monitor_ptr;
- std::atomic<size_t> progress_monitor_counter;
- void progressMonitor(double nprims);
- void setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr);
-
- private:
- GeometryCounts world; //!< counts for geometry
-
- public:
-
- __forceinline size_t numPrimitives() const {
- return world.size();
- }
-
- __forceinline size_t getNumPrimitives(Geometry::GTypeMask mask, bool mblur) const
- {
- size_t count = 0;
-
- if (mask & Geometry::MTY_TRIANGLE_MESH)
- count += mblur ? world.numMBTriangles : world.numTriangles;
-
- if (mask & Geometry::MTY_QUAD_MESH)
- count += mblur ? world.numMBQuads : world.numQuads;
-
- if (mask & Geometry::MTY_CURVE2)
- count += mblur ? world.numMBLineSegments : world.numLineSegments;
-
- if (mask & Geometry::MTY_CURVE4)
- count += mblur ? world.numMBBezierCurves : world.numBezierCurves;
-
- if (mask & Geometry::MTY_POINTS)
- count += mblur ? world.numMBPoints : world.numPoints;
-
- if (mask & Geometry::MTY_SUBDIV_MESH)
- count += mblur ? world.numMBSubdivPatches : world.numSubdivPatches;
-
- if (mask & Geometry::MTY_USER_GEOMETRY)
- count += mblur ? world.numMBUserGeometries : world.numUserGeometries;
-
- if (mask & Geometry::MTY_INSTANCE_CHEAP)
- count += mblur ? world.numMBInstancesCheap : world.numInstancesCheap;
-
- if (mask & Geometry::MTY_INSTANCE_EXPENSIVE)
- count += mblur ? world.numMBInstancesExpensive : world.numInstancesExpensive;
-
- if (mask & Geometry::MTY_GRID_MESH)
- count += mblur ? world.numMBGrids : world.numGrids;
-
- return count;
- }
-
- template<typename Mesh, bool mblur>
- __forceinline unsigned getNumTimeSteps()
- {
- if (!mblur)
- return 1;
-
- Scene::Iterator<Mesh,mblur> iter(this);
- return iter.maxTimeStepsPerGeometry();
- }
-
- template<typename Mesh, bool mblur>
- __forceinline unsigned int getMaxGeomID()
- {
- Scene::Iterator<Mesh,mblur> iter(this);
- return iter.maxGeomID();
- }
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_curves.h b/thirdparty/embree-aarch64/kernels/common/scene_curves.h
deleted file mode 100644
index 2649ab0e3e..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_curves.h
+++ /dev/null
@@ -1,341 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "geometry.h"
-#include "buffer.h"
-
-namespace embree
-{
- /*! represents an array of bicubic bezier curves */
- struct CurveGeometry : public Geometry
- {
- /*! type of this geometry */
- static const Geometry::GTypeMask geom_type = Geometry::MTY_CURVE4;
-
- public:
-
- /*! bezier curve construction */
- CurveGeometry (Device* device, Geometry::GType gtype);
-
- public:
- void setMask(unsigned mask);
- void setNumTimeSteps (unsigned int numTimeSteps);
- void setVertexAttributeCount (unsigned int N);
- void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
- void* getBuffer(RTCBufferType type, unsigned int slot);
- void updateBuffer(RTCBufferType type, unsigned int slot);
- void commit();
- bool verify();
- void setTessellationRate(float N);
- void setMaxRadiusScale(float s);
- void addElementsToCount (GeometryCounts & counts) const;
-
- public:
-
- /*! returns the number of vertices */
- __forceinline size_t numVertices() const {
- return vertices[0].size();
- }
-
- /*! returns the i'th curve */
- __forceinline const unsigned int& curve(size_t i) const {
- return curves[i];
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline Vec3ff vertex(size_t i) const {
- return vertices0[i];
- }
-
- /*! returns i'th normal of the first time step */
- __forceinline Vec3fa normal(size_t i) const {
- return normals0[i];
- }
-
- /*! returns i'th tangent of the first time step */
- __forceinline Vec3ff tangent(size_t i) const {
- return tangents0[i];
- }
-
- /*! returns i'th normal derivative of the first time step */
- __forceinline Vec3fa dnormal(size_t i) const {
- return dnormals0[i];
- }
-
- /*! returns i'th radius of the first time step */
- __forceinline float radius(size_t i) const {
- return vertices0[i].w;
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline Vec3ff vertex(size_t i, size_t itime) const {
- return vertices[itime][i];
- }
-
- /*! returns i'th normal of itime'th timestep */
- __forceinline Vec3fa normal(size_t i, size_t itime) const {
- return normals[itime][i];
- }
-
- /*! returns i'th tangent of itime'th timestep */
- __forceinline Vec3ff tangent(size_t i, size_t itime) const {
- return tangents[itime][i];
- }
-
- /*! returns i'th normal derivative of itime'th timestep */
- __forceinline Vec3fa dnormal(size_t i, size_t itime) const {
- return dnormals[itime][i];
- }
-
- /*! returns i'th radius of itime'th timestep */
- __forceinline float radius(size_t i, size_t itime) const {
- return vertices[itime][i].w;
- }
-
- /*! gathers the curve starting with i'th vertex */
- __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i) const
- {
- p0 = vertex(i+0);
- p1 = vertex(i+1);
- p2 = vertex(i+2);
- p3 = vertex(i+3);
- }
-
- /*! gathers the curve starting with i'th vertex of itime'th timestep */
- __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, size_t itime) const
- {
- p0 = vertex(i+0,itime);
- p1 = vertex(i+1,itime);
- p2 = vertex(i+2,itime);
- p3 = vertex(i+3,itime);
- }
-
- /*! gathers the curve starting with i'th vertex */
- __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i) const
- {
- p0 = vertex(i+0);
- p1 = vertex(i+1);
- p2 = vertex(i+2);
- p3 = vertex(i+3);
- n0 = normal(i+0);
- n1 = normal(i+1);
- n2 = normal(i+2);
- n3 = normal(i+3);
- }
-
- /*! gathers the curve starting with i'th vertex of itime'th timestep */
- __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, size_t itime) const
- {
- p0 = vertex(i+0,itime);
- p1 = vertex(i+1,itime);
- p2 = vertex(i+2,itime);
- p3 = vertex(i+3,itime);
- n0 = normal(i+0,itime);
- n1 = normal(i+1,itime);
- n2 = normal(i+2,itime);
- n3 = normal(i+3,itime);
- }
-
- /*! prefetches the curve starting with i'th vertex of itime'th timestep */
- __forceinline void prefetchL1_vertices(size_t i) const
- {
- prefetchL1(vertices0.getPtr(i)+0);
- prefetchL1(vertices0.getPtr(i)+64);
- }
-
- /*! prefetches the curve starting with i'th vertex of itime'th timestep */
- __forceinline void prefetchL2_vertices(size_t i) const
- {
- prefetchL2(vertices0.getPtr(i)+0);
- prefetchL2(vertices0.getPtr(i)+64);
- }
-
- /*! loads curve vertices for specified time */
- __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, float time) const
- {
- float ftime;
- const size_t itime = timeSegment(time, ftime);
-
- const float t0 = 1.0f - ftime;
- const float t1 = ftime;
- Vec3ff a0,a1,a2,a3;
- gather(a0,a1,a2,a3,i,itime);
- Vec3ff b0,b1,b2,b3;
- gather(b0,b1,b2,b3,i,itime+1);
- p0 = madd(Vec3ff(t0),a0,t1*b0);
- p1 = madd(Vec3ff(t0),a1,t1*b1);
- p2 = madd(Vec3ff(t0),a2,t1*b2);
- p3 = madd(Vec3ff(t0),a3,t1*b3);
- }
-
- /*! loads curve vertices for specified time */
- __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, float time) const
- {
- float ftime;
- const size_t itime = timeSegment(time, ftime);
-
- const float t0 = 1.0f - ftime;
- const float t1 = ftime;
- Vec3ff a0,a1,a2,a3; Vec3fa an0,an1,an2,an3;
- gather(a0,a1,a2,a3,an0,an1,an2,an3,i,itime);
- Vec3ff b0,b1,b2,b3; Vec3fa bn0,bn1,bn2,bn3;
- gather(b0,b1,b2,b3,bn0,bn1,bn2,bn3,i,itime+1);
- p0 = madd(Vec3ff(t0),a0,t1*b0);
- p1 = madd(Vec3ff(t0),a1,t1*b1);
- p2 = madd(Vec3ff(t0),a2,t1*b2);
- p3 = madd(Vec3ff(t0),a3,t1*b3);
- n0 = madd(Vec3ff(t0),an0,t1*bn0);
- n1 = madd(Vec3ff(t0),an1,t1*bn1);
- n2 = madd(Vec3ff(t0),an2,t1*bn2);
- n3 = madd(Vec3ff(t0),an3,t1*bn3);
- }
-
- template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
- __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const
- {
- Vec3ff v0,v1,v2,v3; Vec3fa n0,n1,n2,n3;
- unsigned int vertexID = curve(primID);
- gather(v0,v1,v2,v3,n0,n1,n2,n3,vertexID,itime);
- SourceCurve3ff ccurve(v0,v1,v2,v3);
- SourceCurve3fa ncurve(n0,n1,n2,n3);
- ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);
- return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
- }
-
- template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
- __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
- {
- float ftime;
- const size_t itime = timeSegment(time, ftime);
- const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+0);
- const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+1);
- return clerp(curve0,curve1,ftime);
- }
-
- /*! gathers the hermite curve starting with i'th vertex */
- __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i) const
- {
- p0 = vertex (i+0);
- p1 = vertex (i+1);
- t0 = tangent(i+0);
- t1 = tangent(i+1);
- }
-
- /*! gathers the hermite curve starting with i'th vertex of itime'th timestep */
- __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, size_t itime) const
- {
- p0 = vertex (i+0,itime);
- p1 = vertex (i+1,itime);
- t0 = tangent(i+0,itime);
- t1 = tangent(i+1,itime);
- }
-
- /*! loads curve vertices for specified time */
- __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, float time) const
- {
- float ftime;
- const size_t itime = timeSegment(time, ftime);
- const float f0 = 1.0f - ftime, f1 = ftime;
- Vec3ff ap0,at0,ap1,at1;
- gather_hermite(ap0,at0,ap1,at1,i,itime);
- Vec3ff bp0,bt0,bp1,bt1;
- gather_hermite(bp0,bt0,bp1,bt1,i,itime+1);
- p0 = madd(Vec3ff(f0),ap0,f1*bp0);
- t0 = madd(Vec3ff(f0),at0,f1*bt0);
- p1 = madd(Vec3ff(f0),ap1,f1*bp1);
- t1 = madd(Vec3ff(f0),at1,f1*bt1);
- }
-
- /*! gathers the hermite curve starting with i'th vertex */
- __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i) const
- {
- p0 = vertex (i+0);
- p1 = vertex (i+1);
- t0 = tangent(i+0);
- t1 = tangent(i+1);
- n0 = normal(i+0);
- n1 = normal(i+1);
- dn0 = dnormal(i+0);
- dn1 = dnormal(i+1);
- }
-
- /*! gathers the hermite curve starting with i'th vertex of itime'th timestep */
- __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, size_t itime) const
- {
- p0 = vertex (i+0,itime);
- p1 = vertex (i+1,itime);
- t0 = tangent(i+0,itime);
- t1 = tangent(i+1,itime);
- n0 = normal(i+0,itime);
- n1 = normal(i+1,itime);
- dn0 = dnormal(i+0,itime);
- dn1 = dnormal(i+1,itime);
- }
-
- /*! loads curve vertices for specified time */
- __forceinline void gather_hermite(Vec3ff& p0, Vec3fa& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3fa& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, float time) const
- {
- float ftime;
- const size_t itime = timeSegment(time, ftime);
- const float f0 = 1.0f - ftime, f1 = ftime;
- Vec3ff ap0,at0,ap1,at1; Vec3fa an0,adn0,an1,adn1;
- gather_hermite(ap0,at0,an0,adn0,ap1,at1,an1,adn1,i,itime);
- Vec3ff bp0,bt0,bp1,bt1; Vec3fa bn0,bdn0,bn1,bdn1;
- gather_hermite(bp0,bt0,bn0,bdn0,bp1,bt1,bn1,bdn1,i,itime+1);
- p0 = madd(Vec3ff(f0),ap0,f1*bp0);
- t0 = madd(Vec3ff(f0),at0,f1*bt0);
- n0 = madd(Vec3ff(f0),an0,f1*bn0);
- dn0= madd(Vec3ff(f0),adn0,f1*bdn0);
- p1 = madd(Vec3ff(f0),ap1,f1*bp1);
- t1 = madd(Vec3ff(f0),at1,f1*bt1);
- n1 = madd(Vec3ff(f0),an1,f1*bn1);
- dn1= madd(Vec3ff(f0),adn1,f1*bdn1);
- }
-
- template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
- __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const
- {
- Vec3ff v0,t0,v1,t1; Vec3fa n0,dn0,n1,dn1;
- unsigned int vertexID = curve(primID);
- gather_hermite(v0,t0,n0,dn0,v1,t1,n1,dn1,vertexID,itime);
-
- SourceCurve3ff ccurve(v0,t0,v1,t1);
- SourceCurve3fa ncurve(n0,dn0,n1,dn1);
- ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);
- return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
- }
-
- template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
- __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
- {
- float ftime;
- const size_t itime = timeSegment(time, ftime);
- const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+0);
- const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+1);
- return clerp(curve0,curve1,ftime);
- }
-
- private:
- void resizeBuffers(unsigned int numSteps);
-
- public:
- BufferView<unsigned int> curves; //!< array of curve indices
- BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
- BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
- BufferView<Vec3ff> tangents0; //!< fast access to first tangent buffer
- BufferView<Vec3fa> dnormals0; //!< fast access to first normal derivative buffer
- vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
- vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
- vector<BufferView<Vec3ff>> tangents; //!< tangent array for each timestep
- vector<BufferView<Vec3fa>> dnormals; //!< normal derivative array for each timestep
- BufferView<char> flags; //!< start, end flag per segment
- vector<BufferView<char>> vertexAttribs; //!< user buffers
- int tessellationRate; //!< tessellation rate for flat curve
- float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
- };
-
- DECLARE_ISA_FUNCTION(CurveGeometry*, createCurves, Device* COMMA Geometry::GType);
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_grid_mesh.h b/thirdparty/embree-aarch64/kernels/common/scene_grid_mesh.h
deleted file mode 100644
index c08658466a..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_grid_mesh.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "geometry.h"
-#include "buffer.h"
-
-namespace embree
-{
- /*! Grid Mesh */
- struct GridMesh : public Geometry
- {
- /*! type of this geometry */
- static const Geometry::GTypeMask geom_type = Geometry::MTY_GRID_MESH;
-
- /*! grid */
- struct Grid
- {
- unsigned int startVtxID;
- unsigned int lineVtxOffset;
- unsigned short resX,resY;
-
- /* border flags due to 3x3 vertex pattern */
- __forceinline unsigned int get3x3FlagsX(const unsigned int x) const
- {
- return (x + 2 >= (unsigned int)resX) ? (1<<15) : 0;
- }
-
- /* border flags due to 3x3 vertex pattern */
- __forceinline unsigned int get3x3FlagsY(const unsigned int y) const
- {
- return (y + 2 >= (unsigned int)resY) ? (1<<15) : 0;
- }
-
- /*! outputs grid structure */
- __forceinline friend embree_ostream operator<<(embree_ostream cout, const Grid& t) {
- return cout << "Grid { startVtxID " << t.startVtxID << ", lineVtxOffset " << t.lineVtxOffset << ", resX " << t.resX << ", resY " << t.resY << " }";
- }
- };
-
- public:
-
- /*! grid mesh construction */
- GridMesh (Device* device);
-
- /* geometry interface */
- public:
- void setMask(unsigned mask);
- void setNumTimeSteps (unsigned int numTimeSteps);
- void setVertexAttributeCount (unsigned int N);
- void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
- void* getBuffer(RTCBufferType type, unsigned int slot);
- void updateBuffer(RTCBufferType type, unsigned int slot);
- void commit();
- bool verify();
- void interpolate(const RTCInterpolateArguments* const args);
- void addElementsToCount (GeometryCounts & counts) const;
-
- __forceinline unsigned int getNumSubGrids(const size_t gridID)
- {
- const Grid &g = grid(gridID);
- return max((unsigned int)1,((unsigned int)g.resX >> 1) * ((unsigned int)g.resY >> 1));
- }
-
- /*! get fast access to first vertex buffer */
- __forceinline float * getCompactVertexArray () const {
- return (float*) vertices0.getPtr();
- }
-
- public:
-
- /*! returns number of vertices */
- __forceinline size_t numVertices() const {
- return vertices[0].size();
- }
-
- /*! returns i'th grid*/
- __forceinline const Grid& grid(size_t i) const {
- return grids[i];
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline const Vec3fa vertex(size_t i) const { // FIXME: check if this does a unaligned load
- return vertices0[i];
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline const char* vertexPtr(size_t i) const {
- return vertices0.getPtr(i);
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const Vec3fa vertex(size_t i, size_t itime) const {
- return vertices[itime][i];
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const char* vertexPtr(size_t i, size_t itime) const {
- return vertices[itime].getPtr(i);
- }
-
- /*! returns i'th vertex of the first timestep */
- __forceinline size_t grid_vertex_index(const Grid& g, size_t x, size_t y) const {
- assert(x < (size_t)g.resX);
- assert(y < (size_t)g.resY);
- return g.startVtxID + x + y * g.lineVtxOffset;
- }
-
- /*! returns i'th vertex of the first timestep */
- __forceinline const Vec3fa grid_vertex(const Grid& g, size_t x, size_t y) const {
- const size_t index = grid_vertex_index(g,x,y);
- return vertex(index);
- }
-
- /*! returns i'th vertex of the itime'th timestep */
- __forceinline const Vec3fa grid_vertex(const Grid& g, size_t x, size_t y, size_t itime) const {
- const size_t index = grid_vertex_index(g,x,y);
- return vertex(index,itime);
- }
-
- /*! calculates the build bounds of the i'th primitive, if it's valid */
- __forceinline bool buildBounds(const Grid& g, size_t sx, size_t sy, BBox3fa& bbox) const
- {
- BBox3fa b(empty);
- for (size_t t=0; t<numTimeSteps; t++)
- {
- for (size_t y=sy;y<min(sy+3,(size_t)g.resY);y++)
- for (size_t x=sx;x<min(sx+3,(size_t)g.resX);x++)
- {
- const Vec3fa v = grid_vertex(g,x,y,t);
- if (unlikely(!isvalid(v))) return false;
- b.extend(v);
- }
- }
-
- bbox = b;
- return true;
- }
-
- /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
- __forceinline bool buildBounds(const Grid& g, size_t sx, size_t sy, size_t itime, BBox3fa& bbox) const
- {
- assert(itime < numTimeSteps);
- BBox3fa b0(empty);
- for (size_t y=sy;y<min(sy+3,(size_t)g.resY);y++)
- for (size_t x=sx;x<min(sx+3,(size_t)g.resX);x++)
- {
- const Vec3fa v = grid_vertex(g,x,y,itime);
- if (unlikely(!isvalid(v))) return false;
- b0.extend(v);
- }
-
- /* use bounds of first time step in builder */
- bbox = b0;
- return true;
- }
-
- __forceinline bool valid(size_t gridID, size_t itime=0) const {
- return valid(gridID, make_range(itime, itime));
- }
-
- /*! check if the i'th primitive is valid between the specified time range */
- __forceinline bool valid(size_t gridID, const range<size_t>& itime_range) const
- {
- if (unlikely(gridID >= grids.size())) return false;
- const Grid &g = grid(gridID);
- if (unlikely(g.startVtxID + 0 >= vertices0.size())) return false;
- if (unlikely(g.startVtxID + (g.resY-1)*g.lineVtxOffset + g.resX-1 >= vertices0.size())) return false;
-
- for (size_t y=0;y<g.resY;y++)
- for (size_t x=0;x<g.resX;x++)
- for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
- if (!isvalid(grid_vertex(g,x,y,itime))) return false;
- return true;
- }
-
-
- __forceinline BBox3fa bounds(const Grid& g, size_t sx, size_t sy, size_t itime) const
- {
- BBox3fa box(empty);
- buildBounds(g,sx,sy,itime,box);
- return box;
- }
-
- __forceinline LBBox3fa linearBounds(const Grid& g, size_t sx, size_t sy, size_t itime) const {
- BBox3fa bounds0, bounds1;
- buildBounds(g,sx,sy,itime+0,bounds0);
- buildBounds(g,sx,sy,itime+1,bounds1);
- return LBBox3fa(bounds0,bounds1);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(const Grid& g, size_t sx, size_t sy, const BBox1f& dt) const {
- return LBBox3fa([&] (size_t itime) { return bounds(g,sx,sy,itime); }, dt, time_range, fnumTimeSegments);
- }
-
- public:
- BufferView<Grid> grids; //!< array of triangles
- BufferView<Vec3fa> vertices0; //!< fast access to first vertex buffer
- vector<BufferView<Vec3fa>> vertices; //!< vertex array for each timestep
- vector<RawBufferView> vertexAttribs; //!< vertex attributes
- };
-
- namespace isa
- {
- struct GridMeshISA : public GridMesh
- {
- GridMeshISA (Device* device)
- : GridMesh(device) {}
- };
- }
-
- DECLARE_ISA_FUNCTION(GridMesh*, createGridMesh, Device*);
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_instance.h b/thirdparty/embree-aarch64/kernels/common/scene_instance.h
deleted file mode 100644
index 7ff82a4fb8..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_instance.h
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "geometry.h"
-#include "accel.h"
-
-namespace embree
-{
- struct MotionDerivativeCoefficients;
-
- /*! Instanced acceleration structure */
- struct Instance : public Geometry
- {
- ALIGNED_STRUCT_(16);
- static const Geometry::GTypeMask geom_type = Geometry::MTY_INSTANCE;
-
- public:
- Instance (Device* device, Accel* object = nullptr, unsigned int numTimeSteps = 1);
- ~Instance();
-
- private:
- Instance (const Instance& other) DELETED; // do not implement
- Instance& operator= (const Instance& other) DELETED; // do not implement
-
- private:
- LBBox3fa nonlinearBounds(const BBox1f& time_range_in,
- const BBox1f& geom_time_range,
- float geom_time_segments) const;
-
- BBox3fa boundSegment(size_t itime,
- BBox3fa const& obbox0, BBox3fa const& obbox1,
- BBox3fa const& bbox0, BBox3fa const& bbox1,
- float t_min, float t_max) const;
-
- /* calculates the (correct) interpolated bounds */
- __forceinline BBox3fa bounds(size_t itime0, size_t itime1, float f) const
- {
- if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
- return xfmBounds(slerp(local2world[itime0], local2world[itime1], f),
- lerp(getObjectBounds(itime0), getObjectBounds(itime1), f));
- return xfmBounds(lerp(local2world[itime0], local2world[itime1], f),
- lerp(getObjectBounds(itime0), getObjectBounds(itime1), f));
- }
-
- public:
- virtual void setNumTimeSteps (unsigned int numTimeSteps) override;
- virtual void setInstancedScene(const Ref<Scene>& scene) override;
- virtual void setTransform(const AffineSpace3fa& local2world, unsigned int timeStep) override;
- virtual void setQuaternionDecomposition(const AffineSpace3ff& qd, unsigned int timeStep) override;
- virtual AffineSpace3fa getTransform(float time) override;
- virtual void setMask (unsigned mask) override;
- virtual void build() {}
- virtual void addElementsToCount (GeometryCounts & counts) const override;
- virtual void commit() override;
-
- public:
-
- /*! calculates the bounds of instance */
- __forceinline BBox3fa bounds(size_t i) const {
- assert(i == 0);
- if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
- return xfmBounds(quaternionDecompositionToAffineSpace(local2world[0]),object->bounds.bounds());
- return xfmBounds(local2world[0],object->bounds.bounds());
- }
-
- /*! gets the bounds of the instanced scene */
- __forceinline BBox3fa getObjectBounds(size_t itime) const {
- return object->getBounds(timeStep(itime));
- }
-
- /*! calculates the bounds of instance */
- __forceinline BBox3fa bounds(size_t i, size_t itime) const {
- assert(i == 0);
- if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
- return xfmBounds(quaternionDecompositionToAffineSpace(local2world[itime]),getObjectBounds(itime));
- return xfmBounds(local2world[itime],getObjectBounds(itime));
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(size_t i, const BBox1f& dt) const {
- assert(i == 0);
- LBBox3fa lbbox = nonlinearBounds(dt, time_range, fnumTimeSegments);
- return lbbox;
- }
-
- /*! calculates the build bounds of the i'th item, if it's valid */
- __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
- {
- assert(i==0);
- const BBox3fa b = bounds(i);
- if (bbox) *bbox = b;
- return isvalid(b);
- }
-
- /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
- __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
- {
- assert(i==0);
- const LBBox3fa bounds = linearBounds(i,itime);
- bbox = bounds.bounds ();
- return isvalid(bounds);
- }
-
- /* gets version info of topology */
- unsigned int getTopologyVersion() const {
- return numPrimitives;
- }
-
- /* returns true if topology changed */
- bool topologyChanged(unsigned int otherVersion) const {
- return numPrimitives != otherVersion;
- }
-
- /*! check if the i'th primitive is valid between the specified time range */
- __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
- {
- assert(i == 0);
- for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
- if (!isvalid(bounds(i,itime))) return false;
-
- return true;
- }
-
- __forceinline AffineSpace3fa getLocal2World() const
- {
- if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
- return quaternionDecompositionToAffineSpace(local2world[0]);
- return local2world[0];
- }
-
- __forceinline AffineSpace3fa getLocal2World(float t) const
- {
- float ftime; const unsigned int itime = timeSegment(t, ftime);
- if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
- return slerp(local2world[itime+0],local2world[itime+1],ftime);
- return lerp(local2world[itime+0],local2world[itime+1],ftime);
- }
-
- __forceinline AffineSpace3fa getWorld2Local() const {
- return world2local0;
- }
-
- __forceinline AffineSpace3fa getWorld2Local(float t) const {
- return rcp(getLocal2World(t));
- }
-
- template<int K>
- __forceinline AffineSpace3vf<K> getWorld2Local(const vbool<K>& valid, const vfloat<K>& t) const
- {
- if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
- return getWorld2LocalSlerp(valid, t);
- return getWorld2LocalLerp(valid, t);
- }
-
- private:
-
- template<int K>
- __forceinline AffineSpace3vf<K> getWorld2LocalSlerp(const vbool<K>& valid, const vfloat<K>& t) const
- {
- vfloat<K> ftime;
- const vint<K> itime_k = timeSegment(t, ftime);
- assert(any(valid));
- const size_t index = bsf(movemask(valid));
- const int itime = itime_k[index];
- if (likely(all(valid, itime_k == vint<K>(itime)))) {
- return rcp(slerp(AffineSpace3vff<K>(local2world[itime+0]),
- AffineSpace3vff<K>(local2world[itime+1]),
- ftime));
- }
- else {
- AffineSpace3vff<K> space0,space1;
- vbool<K> valid1 = valid;
- while (any(valid1)) {
- vbool<K> valid2;
- const int itime = next_unique(valid1, itime_k, valid2);
- space0 = select(valid2, AffineSpace3vff<K>(local2world[itime+0]), space0);
- space1 = select(valid2, AffineSpace3vff<K>(local2world[itime+1]), space1);
- }
- return rcp(slerp(space0, space1, ftime));
- }
- }
-
- template<int K>
- __forceinline AffineSpace3vf<K> getWorld2LocalLerp(const vbool<K>& valid, const vfloat<K>& t) const
- {
- vfloat<K> ftime;
- const vint<K> itime_k = timeSegment(t, ftime);
- assert(any(valid));
- const size_t index = bsf(movemask(valid));
- const int itime = itime_k[index];
- if (likely(all(valid, itime_k == vint<K>(itime)))) {
- return rcp(lerp(AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+0]),
- AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+1]),
- ftime));
- } else {
- AffineSpace3vf<K> space0,space1;
- vbool<K> valid1 = valid;
- while (any(valid1)) {
- vbool<K> valid2;
- const int itime = next_unique(valid1, itime_k, valid2);
- space0 = select(valid2, AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+0]), space0);
- space1 = select(valid2, AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+1]), space1);
- }
- return rcp(lerp(space0, space1, ftime));
- }
- }
-
- public:
- Accel* object; //!< pointer to instanced acceleration structure
- AffineSpace3ff* local2world; //!< transformation from local space to world space for each timestep (either normal matrix or quaternion decomposition)
- AffineSpace3fa world2local0; //!< transformation from world space to local space for timestep 0
- };
-
- namespace isa
- {
- struct InstanceISA : public Instance
- {
- InstanceISA (Device* device)
- : Instance(device) {}
-
- PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- assert(r.begin() == 0);
- assert(r.end() == 1);
-
- PrimInfo pinfo(empty);
- BBox3fa b = empty;
- if (!buildBounds(0,&b)) return pinfo;
- // const BBox3fa b = bounds(0);
- // if (!isvalid(b)) return pinfo;
-
- const PrimRef prim(b,geomID,unsigned(0));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- return pinfo;
- }
-
- PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- assert(r.begin() == 0);
- assert(r.end() == 1);
-
- PrimInfo pinfo(empty);
- BBox3fa b = empty;
- if (!buildBounds(0,&b)) return pinfo;
- // if (!valid(0,range<size_t>(itime))) return pinfo;
- // const PrimRef prim(linearBounds(0,itime).bounds(),geomID,unsigned(0));
- const PrimRef prim(b,geomID,unsigned(0));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- return pinfo;
- }
-
- PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- assert(r.begin() == 0);
- assert(r.end() == 1);
-
- PrimInfoMB pinfo(empty);
- if (!valid(0, timeSegmentRange(t0t1))) return pinfo;
- const PrimRefMB prim(linearBounds(0,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(0));
- pinfo.add_primref(prim);
- prims[k++] = prim;
- return pinfo;
- }
- };
- }
-
- DECLARE_ISA_FUNCTION(Instance*, createInstance, Device*);
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_line_segments.h b/thirdparty/embree-aarch64/kernels/common/scene_line_segments.h
deleted file mode 100644
index c0f9ee8f77..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_line_segments.h
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-#include "geometry.h"
-#include "buffer.h"
-
-namespace embree
-{
- /*! represents an array of line segments */
- struct LineSegments : public Geometry
- {
- /*! type of this geometry */
- static const Geometry::GTypeMask geom_type = Geometry::MTY_CURVE2;
-
- public:
-
- /*! line segments construction */
- LineSegments (Device* device, Geometry::GType gtype);
-
- public:
- void setMask (unsigned mask);
- void setNumTimeSteps (unsigned int numTimeSteps);
- void setVertexAttributeCount (unsigned int N);
- void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
- void* getBuffer(RTCBufferType type, unsigned int slot);
- void updateBuffer(RTCBufferType type, unsigned int slot);
- void commit();
- bool verify ();
- void interpolate(const RTCInterpolateArguments* const args);
- void setTessellationRate(float N);
- void setMaxRadiusScale(float s);
- void addElementsToCount (GeometryCounts & counts) const;
-
- public:
-
- /*! returns the number of vertices */
- __forceinline size_t numVertices() const {
- return vertices[0].size();
- }
-
- /*! returns the i'th segment */
- __forceinline const unsigned int& segment(size_t i) const {
- return segments[i];
- }
-
- /*! returns the segment to the left of the i'th segment */
- __forceinline bool segmentLeftExists(size_t i) const {
- assert (flags);
- return (flags[i] & RTC_CURVE_FLAG_NEIGHBOR_LEFT) != 0;
- }
-
- /*! returns the segment to the right of the i'th segment */
- __forceinline bool segmentRightExists(size_t i) const {
- assert (flags);
- return (flags[i] & RTC_CURVE_FLAG_NEIGHBOR_RIGHT) != 0;
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline Vec3ff vertex(size_t i) const {
- return vertices0[i];
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline const char* vertexPtr(size_t i) const {
- return vertices0.getPtr(i);
- }
-
- /*! returns i'th normal of the first time step */
- __forceinline Vec3fa normal(size_t i) const {
- return normals0[i];
- }
-
- /*! returns i'th radius of the first time step */
- __forceinline float radius(size_t i) const {
- return vertices0[i].w;
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline Vec3ff vertex(size_t i, size_t itime) const {
- return vertices[itime][i];
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const char* vertexPtr(size_t i, size_t itime) const {
- return vertices[itime].getPtr(i);
- }
-
- /*! returns i'th normal of itime'th timestep */
- __forceinline Vec3fa normal(size_t i, size_t itime) const {
- return normals[itime][i];
- }
-
- /*! returns i'th radius of itime'th timestep */
- __forceinline float radius(size_t i, size_t itime) const {
- return vertices[itime][i].w;
- }
-
- /*! calculates bounding box of i'th line segment */
- __forceinline BBox3fa bounds(const Vec3ff& v0, const Vec3ff& v1) const
- {
- const BBox3ff b = merge(BBox3ff(v0),BBox3ff(v1));
- return enlarge((BBox3fa)b,maxRadiusScale*Vec3fa(max(v0.w,v1.w)));
- }
-
- /*! calculates bounding box of i'th line segment */
- __forceinline BBox3fa bounds(size_t i) const
- {
- const unsigned int index = segment(i);
- const Vec3ff v0 = vertex(index+0);
- const Vec3ff v1 = vertex(index+1);
- return bounds(v0,v1);
- }
-
- /*! calculates bounding box of i'th line segment for the itime'th time step */
- __forceinline BBox3fa bounds(size_t i, size_t itime) const
- {
- const unsigned int index = segment(i);
- const Vec3ff v0 = vertex(index+0,itime);
- const Vec3ff v1 = vertex(index+1,itime);
- return bounds(v0,v1);
- }
-
- /*! calculates bounding box of i'th line segment */
- __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i) const
- {
- const unsigned int index = segment(i);
- const Vec3ff v0 = vertex(index+0);
- const Vec3ff v1 = vertex(index+1);
- const Vec3ff w0(xfmVector(space,(Vec3fa)v0),v0.w);
- const Vec3ff w1(xfmVector(space,(Vec3fa)v1),v1.w);
- return bounds(w0,w1);
- }
-
- /*! calculates bounding box of i'th line segment for the itime'th time step */
- __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i, size_t itime) const
- {
- const unsigned int index = segment(i);
- const Vec3ff v0 = vertex(index+0,itime);
- const Vec3ff v1 = vertex(index+1,itime);
- const Vec3ff w0(xfmVector(space,(Vec3fa)v0),v0.w);
- const Vec3ff w1(xfmVector(space,(Vec3fa)v1),v1.w);
- return bounds(w0,w1);
- }
-
- /*! check if the i'th primitive is valid at the itime'th timestep */
- __forceinline bool valid(size_t i, size_t itime) const {
- return valid(i, make_range(itime, itime));
- }
-
- /*! check if the i'th primitive is valid between the specified time range */
- __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
- {
- const unsigned int index = segment(i);
- if (index+1 >= numVertices()) return false;
-
- for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
- {
- const Vec3ff v0 = vertex(index+0,itime); if (unlikely(!isvalid4(v0))) return false;
- const Vec3ff v1 = vertex(index+1,itime); if (unlikely(!isvalid4(v1))) return false;
- if (min(v0.w,v1.w) < 0.0f) return false;
- }
- return true;
- }
-
- /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
- __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
- return LBBox3fa(bounds(i,itime+0),bounds(i,itime+1));
- }
-
- /*! calculates the build bounds of the i'th primitive, if it's valid */
- __forceinline bool buildBounds(size_t i, BBox3fa* bbox) const
- {
- if (!valid(i,0)) return false;
- *bbox = bounds(i);
- return true;
- }
-
- /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
- __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
- {
- if (!valid(i,itime+0) || !valid(i,itime+1)) return false;
- bbox = bounds(i,itime); // use bounds of first time step in builder
- return true;
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
- return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
- return LBBox3fa([&] (size_t itime) { return bounds(space, primID, itime); }, dt, time_range, fnumTimeSegments);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const
- {
- if (!valid(i, timeSegmentRange(time_range))) return false;
- bbox = linearBounds(i, time_range);
- return true;
- }
-
- /*! get fast access to first vertex buffer */
- __forceinline float * getCompactVertexArray () const {
- return (float*) vertices0.getPtr();
- }
-
- public:
- BufferView<unsigned int> segments; //!< array of line segment indices
- BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
- BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
- BufferView<char> flags; //!< start, end flag per segment
- vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
- vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
- vector<BufferView<char>> vertexAttribs; //!< user buffers
- int tessellationRate; //!< tessellation rate for bezier curve
- float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
- };
-
- namespace isa
- {
- struct LineSegmentsISA : public LineSegments
- {
- LineSegmentsISA (Device* device, Geometry::GType gtype)
- : LineSegments(device,gtype) {}
-
- Vec3fa computeDirection(unsigned int primID) const
- {
- const unsigned vtxID = segment(primID);
- const Vec3fa v0 = vertex(vtxID+0);
- const Vec3fa v1 = vertex(vtxID+1);
- return v1-v0;
- }
-
- Vec3fa computeDirection(unsigned int primID, size_t time) const
- {
- const unsigned vtxID = segment(primID);
- const Vec3fa v0 = vertex(vtxID+0,time);
- const Vec3fa v1 = vertex(vtxID+1,time);
- return v1-v0;
- }
-
- PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!buildBounds(j,&bounds)) continue;
- const PrimRef prim(bounds,geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!buildBounds(j,itime,bounds)) continue;
- const PrimRef prim(bounds,geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfoMB pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!valid(j, timeSegmentRange(t0t1))) continue;
- const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
- pinfo.add_primref(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- BBox3fa vbounds(size_t i) const {
- return bounds(i);
- }
-
- BBox3fa vbounds(const LinearSpace3fa& space, size_t i) const {
- return bounds(space,i);
- }
-
- LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const {
- return linearBounds(primID,time_range);
- }
-
- LBBox3fa vlinearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
- return linearBounds(space,primID,time_range);
- }
- };
- }
-
- DECLARE_ISA_FUNCTION(LineSegments*, createLineSegments, Device* COMMA Geometry::GType);
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_points.h b/thirdparty/embree-aarch64/kernels/common/scene_points.h
deleted file mode 100644
index 1d39ed07ba..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_points.h
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "buffer.h"
-#include "default.h"
-#include "geometry.h"
-
-namespace embree
-{
- /*! represents an array of points */
- struct Points : public Geometry
- {
- /*! type of this geometry */
- static const Geometry::GTypeMask geom_type = Geometry::MTY_POINTS;
-
- public:
- /*! line segments construction */
- Points(Device* device, Geometry::GType gtype);
-
- public:
- void setMask(unsigned mask);
- void setNumTimeSteps(unsigned int numTimeSteps);
- void setVertexAttributeCount(unsigned int N);
- void setBuffer(RTCBufferType type,
- unsigned int slot,
- RTCFormat format,
- const Ref<Buffer>& buffer,
- size_t offset,
- size_t stride,
- unsigned int num);
- void* getBuffer(RTCBufferType type, unsigned int slot);
- void updateBuffer(RTCBufferType type, unsigned int slot);
- void commit();
- bool verify();
- void setMaxRadiusScale(float s);
- void addElementsToCount (GeometryCounts & counts) const;
-
- public:
- /*! returns the number of vertices */
- __forceinline size_t numVertices() const {
- return vertices[0].size();
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline Vec3ff vertex(size_t i) const {
- return vertices0[i];
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline const char* vertexPtr(size_t i) const {
- return vertices0.getPtr(i);
- }
-
- /*! returns i'th normal of the first time step */
- __forceinline Vec3fa normal(size_t i) const {
- return normals0[i];
- }
-
- /*! returns i'th radius of the first time step */
- __forceinline float radius(size_t i) const {
- return vertices0[i].w;
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline Vec3ff vertex(size_t i, size_t itime) const {
- return vertices[itime][i];
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const char* vertexPtr(size_t i, size_t itime) const {
- return vertices[itime].getPtr(i);
- }
-
- /*! returns i'th normal of itime'th timestep */
- __forceinline Vec3fa normal(size_t i, size_t itime) const {
- return normals[itime][i];
- }
-
- /*! returns i'th radius of itime'th timestep */
- __forceinline float radius(size_t i, size_t itime) const {
- return vertices[itime][i].w;
- }
-
- /*! calculates bounding box of i'th line segment */
- __forceinline BBox3fa bounds(const Vec3ff& v0) const {
- return enlarge(BBox3fa(v0), maxRadiusScale*Vec3fa(v0.w));
- }
-
- /*! calculates bounding box of i'th line segment */
- __forceinline BBox3fa bounds(size_t i) const
- {
- const Vec3ff v0 = vertex(i);
- return bounds(v0);
- }
-
- /*! calculates bounding box of i'th line segment for the itime'th time step */
- __forceinline BBox3fa bounds(size_t i, size_t itime) const
- {
- const Vec3ff v0 = vertex(i, itime);
- return bounds(v0);
- }
-
- /*! calculates bounding box of i'th line segment */
- __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i) const
- {
- const Vec3ff v0 = vertex(i);
- const Vec3ff w0(xfmVector(space, (Vec3fa)v0), v0.w);
- return bounds(w0);
- }
-
- /*! calculates bounding box of i'th line segment for the itime'th time step */
- __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i, size_t itime) const
- {
- const Vec3ff v0 = vertex(i, itime);
- const Vec3ff w0(xfmVector(space, (Vec3fa)v0), v0.w);
- return bounds(w0);
- }
-
- /*! check if the i'th primitive is valid at the itime'th timestep */
- __forceinline bool valid(size_t i, size_t itime) const {
- return valid(i, make_range(itime, itime));
- }
-
- /*! check if the i'th primitive is valid between the specified time range */
- __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
- {
- const unsigned int index = (unsigned int)i;
- if (index >= numVertices())
- return false;
-
- for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) {
- const Vec3ff v0 = vertex(index + 0, itime);
- if (unlikely(!isvalid4(v0)))
- return false;
- if (v0.w < 0.0f)
- return false;
- }
- return true;
- }
-
- /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
- __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
- return LBBox3fa(bounds(i, itime + 0), bounds(i, itime + 1));
- }
-
- /*! calculates the build bounds of the i'th primitive, if it's valid */
- __forceinline bool buildBounds(size_t i, BBox3fa* bbox) const
- {
- if (!valid(i, 0))
- return false;
- *bbox = bounds(i);
- return true;
- }
-
- /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
- __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
- {
- if (!valid(i, itime + 0) || !valid(i, itime + 1))
- return false;
- bbox = bounds(i, itime); // use bounds of first time step in builder
- return true;
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
- return LBBox3fa([&](size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
- return LBBox3fa([&](size_t itime) { return bounds(space, primID, itime); }, dt, time_range, fnumTimeSegments);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const
- {
- if (!valid(i, timeSegmentRange(time_range))) return false;
- bbox = linearBounds(i, time_range);
- return true;
- }
-
- /*! get fast access to first vertex buffer */
- __forceinline float * getCompactVertexArray () const {
- return (float*) vertices0.getPtr();
- }
-
- public:
- BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
- BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
- vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
- vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
- vector<BufferView<char>> vertexAttribs; //!< user buffers
- float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
- };
-
- namespace isa
- {
- struct PointsISA : public Points
- {
- PointsISA(Device* device, Geometry::GType gtype) : Points(device, gtype) {}
-
- Vec3fa computeDirection(unsigned int primID) const
- {
- return Vec3fa(1, 0, 0);
- }
-
- Vec3fa computeDirection(unsigned int primID, size_t time) const
- {
- return Vec3fa(1, 0, 0);
- }
-
- PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j = r.begin(); j < r.end(); j++) {
- BBox3fa bounds = empty;
- if (!buildBounds(j, &bounds))
- continue;
- const PrimRef prim(bounds, geomID, unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j = r.begin(); j < r.end(); j++) {
- BBox3fa bounds = empty;
- if (!buildBounds(j, itime, bounds))
- continue;
- const PrimRef prim(bounds, geomID, unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims,
- const BBox1f& t0t1,
- const range<size_t>& r,
- size_t k,
- unsigned int geomID) const
- {
- PrimInfoMB pinfo(empty);
- for (size_t j = r.begin(); j < r.end(); j++) {
- if (!valid(j, timeSegmentRange(t0t1)))
- continue;
- const PrimRefMB prim(linearBounds(j, t0t1), this->numTimeSegments(), this->time_range, this->numTimeSegments(), geomID, unsigned(j));
- pinfo.add_primref(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- BBox3fa vbounds(size_t i) const
- {
- return bounds(i);
- }
-
- BBox3fa vbounds(const LinearSpace3fa& space, size_t i) const
- {
- return bounds(space, i);
- }
-
- LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const
- {
- return linearBounds(primID, time_range);
- }
-
- LBBox3fa vlinearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const
- {
- return linearBounds(space, primID, time_range);
- }
- };
- } // namespace isa
-
- DECLARE_ISA_FUNCTION(Points*, createPoints, Device* COMMA Geometry::GType);
-} // namespace embree
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_quad_mesh.h b/thirdparty/embree-aarch64/kernels/common/scene_quad_mesh.h
deleted file mode 100644
index d5bb054b14..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_quad_mesh.h
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "geometry.h"
-#include "buffer.h"
-
-namespace embree
-{
- /*! Quad Mesh */
- struct QuadMesh : public Geometry
- {
- /*! type of this geometry */
- static const Geometry::GTypeMask geom_type = Geometry::MTY_QUAD_MESH;
-
- /*! triangle indices */
- struct Quad
- {
- uint32_t v[4];
-
- /*! outputs triangle indices */
- __forceinline friend embree_ostream operator<<(embree_ostream cout, const Quad& q) {
- return cout << "Quad {" << q.v[0] << ", " << q.v[1] << ", " << q.v[2] << ", " << q.v[3] << " }";
- }
- };
-
- public:
-
- /*! quad mesh construction */
- QuadMesh (Device* device);
-
- /* geometry interface */
- public:
- void setMask(unsigned mask);
- void setNumTimeSteps (unsigned int numTimeSteps);
- void setVertexAttributeCount (unsigned int N);
- void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
- void* getBuffer(RTCBufferType type, unsigned int slot);
- void updateBuffer(RTCBufferType type, unsigned int slot);
- void commit();
- bool verify();
- void interpolate(const RTCInterpolateArguments* const args);
- void addElementsToCount (GeometryCounts & counts) const;
-
- public:
-
- /*! returns number of vertices */
- __forceinline size_t numVertices() const {
- return vertices[0].size();
- }
-
- /*! returns i'th quad */
- __forceinline const Quad& quad(size_t i) const {
- return quads[i];
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const Vec3fa vertex(size_t i) const {
- return vertices0[i];
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const char* vertexPtr(size_t i) const {
- return vertices0.getPtr(i);
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const Vec3fa vertex(size_t i, size_t itime) const {
- return vertices[itime][i];
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const char* vertexPtr(size_t i, size_t itime) const {
- return vertices[itime].getPtr(i);
- }
-
- /*! calculates the bounds of the i'th quad */
- __forceinline BBox3fa bounds(size_t i) const
- {
- const Quad& q = quad(i);
- const Vec3fa v0 = vertex(q.v[0]);
- const Vec3fa v1 = vertex(q.v[1]);
- const Vec3fa v2 = vertex(q.v[2]);
- const Vec3fa v3 = vertex(q.v[3]);
- return BBox3fa(min(v0,v1,v2,v3),max(v0,v1,v2,v3));
- }
-
- /*! calculates the bounds of the i'th quad at the itime'th timestep */
- __forceinline BBox3fa bounds(size_t i, size_t itime) const
- {
- const Quad& q = quad(i);
- const Vec3fa v0 = vertex(q.v[0],itime);
- const Vec3fa v1 = vertex(q.v[1],itime);
- const Vec3fa v2 = vertex(q.v[2],itime);
- const Vec3fa v3 = vertex(q.v[3],itime);
- return BBox3fa(min(v0,v1,v2,v3),max(v0,v1,v2,v3));
- }
-
- /*! check if the i'th primitive is valid at the itime'th timestep */
- __forceinline bool valid(size_t i, size_t itime) const {
- return valid(i, make_range(itime, itime));
- }
-
- /*! check if the i'th primitive is valid between the specified time range */
- __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
- {
- const Quad& q = quad(i);
- if (unlikely(q.v[0] >= numVertices())) return false;
- if (unlikely(q.v[1] >= numVertices())) return false;
- if (unlikely(q.v[2] >= numVertices())) return false;
- if (unlikely(q.v[3] >= numVertices())) return false;
-
- for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
- {
- if (!isvalid(vertex(q.v[0],itime))) return false;
- if (!isvalid(vertex(q.v[1],itime))) return false;
- if (!isvalid(vertex(q.v[2],itime))) return false;
- if (!isvalid(vertex(q.v[3],itime))) return false;
- }
-
- return true;
- }
-
- /*! calculates the linear bounds of the i'th quad at the itimeGlobal'th time segment */
- __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
- return LBBox3fa(bounds(i,itime+0),bounds(i,itime+1));
- }
-
- /*! calculates the build bounds of the i'th primitive, if it's valid */
- __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
- {
- const Quad& q = quad(i);
- if (q.v[0] >= numVertices()) return false;
- if (q.v[1] >= numVertices()) return false;
- if (q.v[2] >= numVertices()) return false;
- if (q.v[3] >= numVertices()) return false;
-
- for (unsigned int t=0; t<numTimeSteps; t++)
- {
- const Vec3fa v0 = vertex(q.v[0],t);
- const Vec3fa v1 = vertex(q.v[1],t);
- const Vec3fa v2 = vertex(q.v[2],t);
- const Vec3fa v3 = vertex(q.v[3],t);
-
- if (unlikely(!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3)))
- return false;
- }
-
- if (bbox)
- *bbox = bounds(i);
-
- return true;
- }
-
- /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
- __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
- {
- const Quad& q = quad(i);
- if (unlikely(q.v[0] >= numVertices())) return false;
- if (unlikely(q.v[1] >= numVertices())) return false;
- if (unlikely(q.v[2] >= numVertices())) return false;
- if (unlikely(q.v[3] >= numVertices())) return false;
-
- assert(itime+1 < numTimeSteps);
- const Vec3fa a0 = vertex(q.v[0],itime+0); if (unlikely(!isvalid(a0))) return false;
- const Vec3fa a1 = vertex(q.v[1],itime+0); if (unlikely(!isvalid(a1))) return false;
- const Vec3fa a2 = vertex(q.v[2],itime+0); if (unlikely(!isvalid(a2))) return false;
- const Vec3fa a3 = vertex(q.v[3],itime+0); if (unlikely(!isvalid(a3))) return false;
- const Vec3fa b0 = vertex(q.v[0],itime+1); if (unlikely(!isvalid(b0))) return false;
- const Vec3fa b1 = vertex(q.v[1],itime+1); if (unlikely(!isvalid(b1))) return false;
- const Vec3fa b2 = vertex(q.v[2],itime+1); if (unlikely(!isvalid(b2))) return false;
- const Vec3fa b3 = vertex(q.v[3],itime+1); if (unlikely(!isvalid(b3))) return false;
-
- /* use bounds of first time step in builder */
- bbox = BBox3fa(min(a0,a1,a2,a3),max(a0,a1,a2,a3));
- return true;
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
- return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline bool linearBounds(size_t i, const BBox1f& dt, LBBox3fa& bbox) const
- {
- if (!valid(i, timeSegmentRange(dt))) return false;
- bbox = linearBounds(i, dt);
- return true;
- }
-
- /*! get fast access to first vertex buffer */
- __forceinline float * getCompactVertexArray () const {
- return (float*) vertices0.getPtr();
- }
-
- /* gets version info of topology */
- unsigned int getTopologyVersion() const {
- return quads.modCounter;
- }
-
- /* returns true if topology changed */
- bool topologyChanged(unsigned int otherVersion) const {
- return quads.isModified(otherVersion); // || numPrimitivesChanged;
- }
-
- /* returns the projected area */
- __forceinline float projectedPrimitiveArea(const size_t i) const {
- const Quad& q = quad(i);
- const Vec3fa v0 = vertex(q.v[0]);
- const Vec3fa v1 = vertex(q.v[1]);
- const Vec3fa v2 = vertex(q.v[2]);
- const Vec3fa v3 = vertex(q.v[3]);
- return areaProjectedTriangle(v0,v1,v3) +
- areaProjectedTriangle(v1,v2,v3);
- }
-
- public:
- BufferView<Quad> quads; //!< array of quads
- BufferView<Vec3fa> vertices0; //!< fast access to first vertex buffer
- vector<BufferView<Vec3fa>> vertices; //!< vertex array for each timestep
- vector<BufferView<char>> vertexAttribs; //!< vertex attribute buffers
- };
-
- namespace isa
- {
- struct QuadMeshISA : public QuadMesh
- {
- QuadMeshISA (Device* device)
- : QuadMesh(device) {}
-
- PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!buildBounds(j,&bounds)) continue;
- const PrimRef prim(bounds,geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!buildBounds(j,itime,bounds)) continue;
- const PrimRef prim(bounds,geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfoMB pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!valid(j, timeSegmentRange(t0t1))) continue;
- const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
- pinfo.add_primref(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
- };
- }
-
- DECLARE_ISA_FUNCTION(QuadMesh*, createQuadMesh, Device*);
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_subdiv_mesh.h b/thirdparty/embree-aarch64/kernels/common/scene_subdiv_mesh.h
deleted file mode 100644
index d0246009db..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_subdiv_mesh.h
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "geometry.h"
-#include "buffer.h"
-#include "../subdiv/half_edge.h"
-#include "../subdiv/tessellation_cache.h"
-#include "../subdiv/catmullclark_coefficients.h"
-#include "../subdiv/patch.h"
-#include "../../common/algorithms/parallel_map.h"
-#include "../../common/algorithms/parallel_set.h"
-
-namespace embree
-{
- class SubdivMesh : public Geometry
- {
- ALIGNED_CLASS_(16);
- public:
-
- typedef HalfEdge::Edge Edge;
-
- /*! type of this geometry */
- static const Geometry::GTypeMask geom_type = Geometry::MTY_SUBDIV_MESH;
-
- /*! structure used to sort half edges using radix sort by their key */
- struct KeyHalfEdge
- {
- KeyHalfEdge() {}
-
- KeyHalfEdge (uint64_t key, HalfEdge* edge)
- : key(key), edge(edge) {}
-
- __forceinline operator uint64_t() const {
- return key;
- }
-
- friend __forceinline bool operator<(const KeyHalfEdge& e0, const KeyHalfEdge& e1) {
- return e0.key < e1.key;
- }
-
- public:
- uint64_t key;
- HalfEdge* edge;
- };
-
- public:
-
- /*! subdiv mesh construction */
- SubdivMesh(Device* device);
-
- public:
- void setMask (unsigned mask);
- void setSubdivisionMode (unsigned int topologyID, RTCSubdivisionMode mode);
- void setVertexAttributeTopology(unsigned int vertexAttribID, unsigned int topologyID);
- void setNumTimeSteps (unsigned int numTimeSteps);
- void setVertexAttributeCount (unsigned int N);
- void setTopologyCount (unsigned int N);
- void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
- void* getBuffer(RTCBufferType type, unsigned int slot);
- void updateBuffer(RTCBufferType type, unsigned int slot);
- void setTessellationRate(float N);
- bool verify();
- void commit();
- void addElementsToCount (GeometryCounts & counts) const;
- void setDisplacementFunction (RTCDisplacementFunctionN func);
- unsigned int getFirstHalfEdge(unsigned int faceID);
- unsigned int getFace(unsigned int edgeID);
- unsigned int getNextHalfEdge(unsigned int edgeID);
- unsigned int getPreviousHalfEdge(unsigned int edgeID);
- unsigned int getOppositeHalfEdge(unsigned int topologyID, unsigned int edgeID);
-
- public:
-
- /*! return the number of faces */
- size_t numFaces() const {
- return faceVertices.size();
- }
-
- /*! return the number of edges */
- size_t numEdges() const {
- return topology[0].vertexIndices.size();
- }
-
- /*! return the number of vertices */
- size_t numVertices() const {
- return vertices[0].size();
- }
-
- /*! calculates the bounds of the i'th subdivision patch at the j'th timestep */
- __forceinline BBox3fa bounds(size_t i, size_t j = 0) const {
- return topology[0].getHalfEdge(i)->bounds(vertices[j]);
- }
-
- /*! check if the i'th primitive is valid */
- __forceinline bool valid(size_t i) const {
- return topology[0].valid(i) && !invalidFace(i);
- }
-
- /*! check if the i'th primitive is valid for the j'th time range */
- __forceinline bool valid(size_t i, size_t j) const {
- return topology[0].valid(i) && !invalidFace(i,j);
- }
-
- /*! prints some statistics */
- void printStatistics();
-
- /*! initializes the half edge data structure */
- void initializeHalfEdgeStructures ();
-
- public:
-
- /*! returns the vertex buffer for some time step */
- __forceinline const BufferView<Vec3fa>& getVertexBuffer( const size_t t = 0 ) const {
- return vertices[t];
- }
-
- /* returns tessellation level of edge */
- __forceinline float getEdgeLevel(const size_t i) const
- {
- if (levels) return clamp(levels[i],1.0f,4096.0f); // FIXME: do we want to limit edge level?
- else return clamp(tessellationRate,1.0f,4096.0f); // FIXME: do we want to limit edge level?
- }
-
- public:
- RTCDisplacementFunctionN displFunc; //!< displacement function
-
- /*! all buffers in this section are provided by the application */
- public:
-
- /*! the topology contains all data that may differ when
- * interpolating different user data buffers */
- struct Topology
- {
- public:
-
- /*! Default topology construction */
- Topology () : halfEdges(nullptr,0) {}
-
- /*! Topology initialization */
- Topology (SubdivMesh* mesh);
-
- /*! make the class movable */
- public:
- Topology (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
- : mesh(std::move(other.mesh)),
- vertexIndices(std::move(other.vertexIndices)),
- subdiv_mode(std::move(other.subdiv_mode)),
- halfEdges(std::move(other.halfEdges)),
- halfEdges0(std::move(other.halfEdges0)),
- halfEdges1(std::move(other.halfEdges1)) {}
-
- Topology& operator= (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
- {
- mesh = std::move(other.mesh);
- vertexIndices = std::move(other.vertexIndices);
- subdiv_mode = std::move(other.subdiv_mode);
- halfEdges = std::move(other.halfEdges);
- halfEdges0 = std::move(other.halfEdges0);
- halfEdges1 = std::move(other.halfEdges1);
- return *this;
- }
-
- public:
- /*! check if the i'th primitive is valid in this topology */
- __forceinline bool valid(size_t i) const
- {
- if (unlikely(subdiv_mode == RTC_SUBDIVISION_MODE_NO_BOUNDARY)) {
- if (getHalfEdge(i)->faceHasBorder()) return false;
- }
- return true;
- }
-
- /*! updates the interpolation mode for the topology */
- void setSubdivisionMode (RTCSubdivisionMode mode);
-
- /*! marks all buffers as modified */
- void update ();
-
- /*! verifies index array */
- bool verify (size_t numVertices);
-
- /*! initializes the half edge data structure */
- void initializeHalfEdgeStructures ();
-
- private:
-
- /*! recalculates the half edges */
- void calculateHalfEdges();
-
- /*! updates half edges when recalculation is not necessary */
- void updateHalfEdges();
-
- /*! user input data */
- public:
-
- SubdivMesh* mesh;
-
- /*! indices of the vertices composing each face */
- BufferView<unsigned int> vertexIndices;
-
- /*! subdiv interpolation mode */
- RTCSubdivisionMode subdiv_mode;
-
- /*! generated data */
- public:
-
- /*! returns the start half edge for face f */
- __forceinline const HalfEdge* getHalfEdge ( const size_t f ) const {
- return &halfEdges[mesh->faceStartEdge[f]];
- }
-
- /*! Half edge structure, generated by initHalfEdgeStructures */
- mvector<HalfEdge> halfEdges;
-
- /*! the following data is only required during construction of the
- * half edge structure and can be cleared for static scenes */
- private:
-
- /*! two arrays used to sort the half edges */
- std::vector<KeyHalfEdge> halfEdges0;
- std::vector<KeyHalfEdge> halfEdges1;
- };
-
- /*! returns the start half edge for topology t and face f */
- __forceinline const HalfEdge* getHalfEdge ( const size_t t , const size_t f ) const {
- return topology[t].getHalfEdge(f);
- }
-
- /*! buffer containing the number of vertices for each face */
- BufferView<unsigned int> faceVertices;
-
- /*! array of topologies */
- vector<Topology> topology;
-
- /*! vertex buffer (one buffer for each time step) */
- vector<BufferView<Vec3fa>> vertices;
-
- /*! user data buffers */
- vector<RawBufferView> vertexAttribs;
-
- /*! edge crease buffer containing edges (pairs of vertices) that carry edge crease weights */
- BufferView<Edge> edge_creases;
-
- /*! edge crease weights for each edge of the edge_creases buffer */
- BufferView<float> edge_crease_weights;
-
- /*! vertex crease buffer containing all vertices that carry vertex crease weights */
- BufferView<unsigned int> vertex_creases;
-
- /*! vertex crease weights for each vertex of the vertex_creases buffer */
- BufferView<float> vertex_crease_weights;
-
- /*! subdivision level for each half edge of the vertexIndices buffer */
- BufferView<float> levels;
- float tessellationRate; // constant rate that is used when levels is not set
-
- /*! buffer that marks specific faces as holes */
- BufferView<unsigned> holes;
-
- /*! all data in this section is generated by initializeHalfEdgeStructures function */
- private:
-
- /*! number of half edges used by faces */
- size_t numHalfEdges;
-
- /*! fast lookup table to find the first half edge for some face */
- mvector<uint32_t> faceStartEdge;
-
- /*! fast lookup table to find the face for some half edge */
- mvector<uint32_t> halfEdgeFace;
-
- /*! set with all holes */
- parallel_set<uint32_t> holeSet;
-
- /*! fast lookup table to detect invalid faces */
- mvector<int8_t> invalid_face;
-
- /*! test if face i is invalid in timestep j */
- __forceinline int8_t& invalidFace(size_t i, size_t j = 0) { return invalid_face[i*numTimeSteps+j]; }
- __forceinline const int8_t& invalidFace(size_t i, size_t j = 0) const { return invalid_face[i*numTimeSteps+j]; }
-
- /*! interpolation cache */
- public:
- static __forceinline size_t numInterpolationSlots4(size_t stride) { return (stride+15)/16; }
- static __forceinline size_t numInterpolationSlots8(size_t stride) { return (stride+31)/32; }
- static __forceinline size_t interpolationSlot(size_t prim, size_t slot, size_t stride) {
- const size_t slots = numInterpolationSlots4(stride);
- assert(slot < slots);
- return slots*prim+slot;
- }
- std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_buffer_tags;
- std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_attrib_buffer_tags;
- std::vector<Patch3fa::Ref> patch_eval_trees;
-
- /*! the following data is only required during construction of the
- * half edge structure and can be cleared for static scenes */
- private:
-
- /*! map with all vertex creases */
- parallel_map<uint32_t,float> vertexCreaseMap;
-
- /*! map with all edge creases */
- parallel_map<uint64_t,float> edgeCreaseMap;
-
- protected:
-
- /*! counts number of geometry commits */
- size_t commitCounter;
- };
-
- namespace isa
- {
- struct SubdivMeshISA : public SubdivMesh
- {
- SubdivMeshISA (Device* device)
- : SubdivMesh(device) {}
-
- void interpolate(const RTCInterpolateArguments* const args);
- void interpolateN(const RTCInterpolateNArguments* const args);
- };
- }
-
- DECLARE_ISA_FUNCTION(SubdivMesh*, createSubdivMesh, Device*);
-};
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_triangle_mesh.cpp b/thirdparty/embree-aarch64/kernels/common/scene_triangle_mesh.cpp
deleted file mode 100644
index d1c2750f14..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_triangle_mesh.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "scene_triangle_mesh.h"
-#include "scene.h"
-
-namespace embree
-{
-#if defined(EMBREE_LOWEST_ISA)
-
- TriangleMesh::TriangleMesh (Device* device)
- : Geometry(device,GTY_TRIANGLE_MESH,0,1)
- {
- vertices.resize(numTimeSteps);
- }
-
- void TriangleMesh::setMask (unsigned mask)
- {
- this->mask = mask;
- Geometry::update();
- }
-
- void TriangleMesh::setNumTimeSteps (unsigned int numTimeSteps)
- {
- vertices.resize(numTimeSteps);
- Geometry::setNumTimeSteps(numTimeSteps);
- }
-
- void TriangleMesh::setVertexAttributeCount (unsigned int N)
- {
- vertexAttribs.resize(N);
- Geometry::update();
- }
-
- void TriangleMesh::setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num)
- {
- /* verify that all accesses are 4 bytes aligned */
- if (((size_t(buffer->getPtr()) + offset) & 0x3) || (stride & 0x3))
- throw_RTCError(RTC_ERROR_INVALID_OPERATION, "data must be 4 bytes aligned");
-
- if (type == RTC_BUFFER_TYPE_VERTEX)
- {
- if (format != RTC_FORMAT_FLOAT3)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex buffer format");
-
- /* if buffer is larger than 16GB the premultiplied index optimization does not work */
- if (stride*num > 16ll*1024ll*1024ll*1024ll)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION, "vertex buffer can be at most 16GB large");
-
- if (slot >= vertices.size())
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid vertex buffer slot");
-
- vertices[slot].set(buffer, offset, stride, num, format);
- vertices[slot].checkPadding16();
- vertices0 = vertices[0];
- }
- else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
- {
- if (format < RTC_FORMAT_FLOAT || format > RTC_FORMAT_FLOAT16)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex attribute buffer format");
-
- if (slot >= vertexAttribs.size())
- throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex attribute buffer slot");
-
- vertexAttribs[slot].set(buffer, offset, stride, num, format);
- vertexAttribs[slot].checkPadding16();
- }
- else if (type == RTC_BUFFER_TYPE_INDEX)
- {
- if (slot != 0)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
- if (format != RTC_FORMAT_UINT3)
- throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid index buffer format");
-
- triangles.set(buffer, offset, stride, num, format);
- setNumPrimitives(num);
- }
- else
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
- }
-
- void* TriangleMesh::getBuffer(RTCBufferType type, unsigned int slot)
- {
- if (type == RTC_BUFFER_TYPE_INDEX)
- {
- if (slot != 0)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
- return triangles.getPtr();
- }
- else if (type == RTC_BUFFER_TYPE_VERTEX)
- {
- if (slot >= vertices.size())
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
- return vertices[slot].getPtr();
- }
- else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
- {
- if (slot >= vertexAttribs.size())
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
- return vertexAttribs[slot].getPtr();
- }
- else
- {
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
- return nullptr;
- }
- }
-
- void TriangleMesh::updateBuffer(RTCBufferType type, unsigned int slot)
- {
- if (type == RTC_BUFFER_TYPE_INDEX)
- {
- if (slot != 0)
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
- triangles.setModified();
- }
- else if (type == RTC_BUFFER_TYPE_VERTEX)
- {
- if (slot >= vertices.size())
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
- vertices[slot].setModified();
- }
- else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
- {
- if (slot >= vertexAttribs.size())
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
- vertexAttribs[slot].setModified();
- }
- else
- {
- throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
- }
-
- Geometry::update();
- }
-
- void TriangleMesh::commit()
- {
- /* verify that stride of all time steps are identical */
- for (unsigned int t=0; t<numTimeSteps; t++)
- if (vertices[t].getStride() != vertices[0].getStride())
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"stride of vertex buffers have to be identical for each time step");
-
- Geometry::commit();
- }
-
- void TriangleMesh::addElementsToCount (GeometryCounts & counts) const
- {
- if (numTimeSteps == 1) counts.numTriangles += numPrimitives;
- else counts.numMBTriangles += numPrimitives;
- }
-
- bool TriangleMesh::verify()
- {
- /*! verify size of vertex arrays */
- if (vertices.size() == 0) return false;
- for (const auto& buffer : vertices)
- if (buffer.size() != numVertices())
- return false;
-
- /*! verify size of user vertex arrays */
- for (const auto& buffer : vertexAttribs)
- if (buffer.size() != numVertices())
- return false;
-
- /*! verify triangle indices */
- for (size_t i=0; i<size(); i++) {
- if (triangles[i].v[0] >= numVertices()) return false;
- if (triangles[i].v[1] >= numVertices()) return false;
- if (triangles[i].v[2] >= numVertices()) return false;
- }
-
- /*! verify vertices */
- for (const auto& buffer : vertices)
- for (size_t i=0; i<buffer.size(); i++)
- if (!isvalid(buffer[i]))
- return false;
-
- return true;
- }
-
- void TriangleMesh::interpolate(const RTCInterpolateArguments* const args)
- {
- unsigned int primID = args->primID;
- float u = args->u;
- float v = args->v;
- RTCBufferType bufferType = args->bufferType;
- unsigned int bufferSlot = args->bufferSlot;
- float* P = args->P;
- float* dPdu = args->dPdu;
- float* dPdv = args->dPdv;
- float* ddPdudu = args->ddPdudu;
- float* ddPdvdv = args->ddPdvdv;
- float* ddPdudv = args->ddPdudv;
- unsigned int valueCount = args->valueCount;
-
- /* calculate base pointer and stride */
- assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
- (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
- const char* src = nullptr;
- size_t stride = 0;
- if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
- src = vertexAttribs[bufferSlot].getPtr();
- stride = vertexAttribs[bufferSlot].getStride();
- } else {
- src = vertices[bufferSlot].getPtr();
- stride = vertices[bufferSlot].getStride();
- }
-
- for (unsigned int i=0; i<valueCount; i+=4)
- {
- size_t ofs = i*sizeof(float);
- const float w = 1.0f-u-v;
- const Triangle& tri = triangle(primID);
- const vbool4 valid = vint4((int)i)+vint4(step) < vint4(int(valueCount));
- const vfloat4 p0 = vfloat4::loadu(valid,(float*)&src[tri.v[0]*stride+ofs]);
- const vfloat4 p1 = vfloat4::loadu(valid,(float*)&src[tri.v[1]*stride+ofs]);
- const vfloat4 p2 = vfloat4::loadu(valid,(float*)&src[tri.v[2]*stride+ofs]);
-
- if (P) {
- vfloat4::storeu(valid,P+i,madd(w,p0,madd(u,p1,v*p2)));
- }
- if (dPdu) {
- assert(dPdu); vfloat4::storeu(valid,dPdu+i,p1-p0);
- assert(dPdv); vfloat4::storeu(valid,dPdv+i,p2-p0);
- }
- if (ddPdudu) {
- assert(ddPdudu); vfloat4::storeu(valid,ddPdudu+i,vfloat4(zero));
- assert(ddPdvdv); vfloat4::storeu(valid,ddPdvdv+i,vfloat4(zero));
- assert(ddPdudv); vfloat4::storeu(valid,ddPdudv+i,vfloat4(zero));
- }
- }
- }
-
-#endif
-
- namespace isa
- {
- TriangleMesh* createTriangleMesh(Device* device) {
- return new TriangleMeshISA(device);
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_triangle_mesh.h b/thirdparty/embree-aarch64/kernels/common/scene_triangle_mesh.h
deleted file mode 100644
index eaf2e1799a..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_triangle_mesh.h
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "geometry.h"
-#include "buffer.h"
-
-namespace embree
-{
- /*! Triangle Mesh */
- struct TriangleMesh : public Geometry
- {
- /*! type of this geometry */
- static const Geometry::GTypeMask geom_type = Geometry::MTY_TRIANGLE_MESH;
-
- /*! triangle indices */
- struct Triangle
- {
- uint32_t v[3];
-
- /*! outputs triangle indices */
- __forceinline friend embree_ostream operator<<(embree_ostream cout, const Triangle& t) {
- return cout << "Triangle { " << t.v[0] << ", " << t.v[1] << ", " << t.v[2] << " }";
- }
- };
-
- public:
-
- /*! triangle mesh construction */
- TriangleMesh (Device* device);
-
- /* geometry interface */
- public:
- void setMask(unsigned mask);
- void setNumTimeSteps (unsigned int numTimeSteps);
- void setVertexAttributeCount (unsigned int N);
- void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
- void* getBuffer(RTCBufferType type, unsigned int slot);
- void updateBuffer(RTCBufferType type, unsigned int slot);
- void commit();
- bool verify();
- void interpolate(const RTCInterpolateArguments* const args);
- void addElementsToCount (GeometryCounts & counts) const;
-
- public:
-
- /*! returns number of vertices */
- __forceinline size_t numVertices() const {
- return vertices[0].size();
- }
-
- /*! returns i'th triangle*/
- __forceinline const Triangle& triangle(size_t i) const {
- return triangles[i];
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline const Vec3fa vertex(size_t i) const {
- return vertices0[i];
- }
-
- /*! returns i'th vertex of the first time step */
- __forceinline const char* vertexPtr(size_t i) const {
- return vertices0.getPtr(i);
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const Vec3fa vertex(size_t i, size_t itime) const {
- return vertices[itime][i];
- }
-
- /*! returns i'th vertex of itime'th timestep */
- __forceinline const char* vertexPtr(size_t i, size_t itime) const {
- return vertices[itime].getPtr(i);
- }
-
- /*! calculates the bounds of the i'th triangle */
- __forceinline BBox3fa bounds(size_t i) const
- {
- const Triangle& tri = triangle(i);
- const Vec3fa v0 = vertex(tri.v[0]);
- const Vec3fa v1 = vertex(tri.v[1]);
- const Vec3fa v2 = vertex(tri.v[2]);
- return BBox3fa(min(v0,v1,v2),max(v0,v1,v2));
- }
-
- /*! calculates the bounds of the i'th triangle at the itime'th timestep */
- __forceinline BBox3fa bounds(size_t i, size_t itime) const
- {
- const Triangle& tri = triangle(i);
- const Vec3fa v0 = vertex(tri.v[0],itime);
- const Vec3fa v1 = vertex(tri.v[1],itime);
- const Vec3fa v2 = vertex(tri.v[2],itime);
- return BBox3fa(min(v0,v1,v2),max(v0,v1,v2));
- }
-
- /*! check if the i'th primitive is valid at the itime'th timestep */
- __forceinline bool valid(size_t i, size_t itime) const {
- return valid(i, make_range(itime, itime));
- }
-
- /*! check if the i'th primitive is valid between the specified time range */
- __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
- {
- const Triangle& tri = triangle(i);
- if (unlikely(tri.v[0] >= numVertices())) return false;
- if (unlikely(tri.v[1] >= numVertices())) return false;
- if (unlikely(tri.v[2] >= numVertices())) return false;
-
- for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
- {
- if (!isvalid(vertex(tri.v[0],itime))) return false;
- if (!isvalid(vertex(tri.v[1],itime))) return false;
- if (!isvalid(vertex(tri.v[2],itime))) return false;
- }
-
- return true;
- }
-
- /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
- __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
- return LBBox3fa(bounds(i,itime+0),bounds(i,itime+1));
- }
-
- /*! calculates the build bounds of the i'th primitive, if it's valid */
- __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
- {
- const Triangle& tri = triangle(i);
- if (unlikely(tri.v[0] >= numVertices())) return false;
- if (unlikely(tri.v[1] >= numVertices())) return false;
- if (unlikely(tri.v[2] >= numVertices())) return false;
-
- for (size_t t=0; t<numTimeSteps; t++)
- {
- const Vec3fa v0 = vertex(tri.v[0],t);
- const Vec3fa v1 = vertex(tri.v[1],t);
- const Vec3fa v2 = vertex(tri.v[2],t);
- if (unlikely(!isvalid(v0) || !isvalid(v1) || !isvalid(v2)))
- return false;
- }
-
- if (likely(bbox))
- *bbox = bounds(i);
-
- return true;
- }
-
- /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
- __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
- {
- const Triangle& tri = triangle(i);
- if (unlikely(tri.v[0] >= numVertices())) return false;
- if (unlikely(tri.v[1] >= numVertices())) return false;
- if (unlikely(tri.v[2] >= numVertices())) return false;
-
- assert(itime+1 < numTimeSteps);
- const Vec3fa a0 = vertex(tri.v[0],itime+0); if (unlikely(!isvalid(a0))) return false;
- const Vec3fa a1 = vertex(tri.v[1],itime+0); if (unlikely(!isvalid(a1))) return false;
- const Vec3fa a2 = vertex(tri.v[2],itime+0); if (unlikely(!isvalid(a2))) return false;
- const Vec3fa b0 = vertex(tri.v[0],itime+1); if (unlikely(!isvalid(b0))) return false;
- const Vec3fa b1 = vertex(tri.v[1],itime+1); if (unlikely(!isvalid(b1))) return false;
- const Vec3fa b2 = vertex(tri.v[2],itime+1); if (unlikely(!isvalid(b2))) return false;
-
- /* use bounds of first time step in builder */
- bbox = BBox3fa(min(a0,a1,a2),max(a0,a1,a2));
- return true;
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
- return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
- }
-
- /*! calculates the linear bounds of the i'th primitive for the specified time range */
- __forceinline bool linearBounds(size_t i, const BBox1f& dt, LBBox3fa& bbox) const {
- if (!valid(i, timeSegmentRange(dt))) return false;
- bbox = linearBounds(i, dt);
- return true;
- }
-
- /*! get fast access to first vertex buffer */
- __forceinline float * getCompactVertexArray () const {
- return (float*) vertices0.getPtr();
- }
-
- /* gets version info of topology */
- unsigned int getTopologyVersion() const {
- return triangles.modCounter;
- }
-
- /* returns true if topology changed */
- bool topologyChanged(unsigned int otherVersion) const {
- return triangles.isModified(otherVersion); // || numPrimitivesChanged;
- }
-
- /* returns the projected area */
- __forceinline float projectedPrimitiveArea(const size_t i) const {
- const Triangle& tri = triangle(i);
- const Vec3fa v0 = vertex(tri.v[0]);
- const Vec3fa v1 = vertex(tri.v[1]);
- const Vec3fa v2 = vertex(tri.v[2]);
- return areaProjectedTriangle(v0,v1,v2);
- }
-
- public:
- BufferView<Triangle> triangles; //!< array of triangles
- BufferView<Vec3fa> vertices0; //!< fast access to first vertex buffer
- vector<BufferView<Vec3fa>> vertices; //!< vertex array for each timestep
- vector<RawBufferView> vertexAttribs; //!< vertex attributes
- };
-
- namespace isa
- {
- struct TriangleMeshISA : public TriangleMesh
- {
- TriangleMeshISA (Device* device)
- : TriangleMesh(device) {}
-
- PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!buildBounds(j,&bounds)) continue;
- const PrimRef prim(bounds,geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!buildBounds(j,itime,bounds)) continue;
- const PrimRef prim(bounds,geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfoMB pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!valid(j, timeSegmentRange(t0t1))) continue;
- const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
- pinfo.add_primref(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
- };
- }
-
- DECLARE_ISA_FUNCTION(TriangleMesh*, createTriangleMesh, Device*);
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/scene_user_geometry.h b/thirdparty/embree-aarch64/kernels/common/scene_user_geometry.h
deleted file mode 100644
index 8d11ed6986..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/scene_user_geometry.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "accelset.h"
-
-namespace embree
-{
- /*! User geometry with user defined intersection functions */
- struct UserGeometry : public AccelSet
- {
- /*! type of this geometry */
- static const Geometry::GTypeMask geom_type = Geometry::MTY_USER_GEOMETRY;
-
- public:
- UserGeometry (Device* device, unsigned int items = 0, unsigned int numTimeSteps = 1);
- virtual void setMask (unsigned mask);
- virtual void setBoundsFunction (RTCBoundsFunction bounds, void* userPtr);
- virtual void setIntersectFunctionN (RTCIntersectFunctionN intersect);
- virtual void setOccludedFunctionN (RTCOccludedFunctionN occluded);
- virtual void build() {}
- virtual void addElementsToCount (GeometryCounts & counts) const;
- };
-
- namespace isa
- {
- struct UserGeometryISA : public UserGeometry
- {
- UserGeometryISA (Device* device)
- : UserGeometry(device) {}
-
- PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!buildBounds(j,&bounds)) continue;
- const PrimRef prim(bounds,geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!buildBounds(j,itime,bounds)) continue;
- const PrimRef prim(bounds,geomID,unsigned(j));
- pinfo.add_center2(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
-
- PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
- {
- PrimInfoMB pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!valid(j, timeSegmentRange(t0t1))) continue;
- const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
- pinfo.add_primref(prim);
- prims[k++] = prim;
- }
- return pinfo;
- }
- };
- }
-
- DECLARE_ISA_FUNCTION(UserGeometry*, createUserGeometry, Device*);
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/stack_item.h b/thirdparty/embree-aarch64/kernels/common/stack_item.h
deleted file mode 100644
index 533c385365..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/stack_item.h
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-
-namespace embree
-{
- /*! An item on the stack holds the node ID and distance of that node. */
- template<typename T>
- struct __aligned(16) StackItemT
- {
- /*! assert that the xchg function works */
- static_assert(sizeof(T) <= 12, "sizeof(T) <= 12 failed");
-
- __forceinline StackItemT() {}
-
- __forceinline StackItemT(T &ptr, unsigned &dist) : ptr(ptr), dist(dist) {}
-
- /*! use SSE instructions to swap stack items */
- __forceinline static void xchg(StackItemT& a, StackItemT& b)
- {
- const vfloat4 sse_a = vfloat4::load((float*)&a);
- const vfloat4 sse_b = vfloat4::load((float*)&b);
- vfloat4::store(&a,sse_b);
- vfloat4::store(&b,sse_a);
- }
-
- /*! Sort 2 stack items. */
- __forceinline friend void sort(StackItemT& s1, StackItemT& s2) {
- if (s2.dist < s1.dist) xchg(s2,s1);
- }
-
- /*! Sort 3 stack items. */
- __forceinline friend void sort(StackItemT& s1, StackItemT& s2, StackItemT& s3)
- {
- if (s2.dist < s1.dist) xchg(s2,s1);
- if (s3.dist < s2.dist) xchg(s3,s2);
- if (s2.dist < s1.dist) xchg(s2,s1);
- }
-
- /*! Sort 4 stack items. */
- __forceinline friend void sort(StackItemT& s1, StackItemT& s2, StackItemT& s3, StackItemT& s4)
- {
- if (s2.dist < s1.dist) xchg(s2,s1);
- if (s4.dist < s3.dist) xchg(s4,s3);
- if (s3.dist < s1.dist) xchg(s3,s1);
- if (s4.dist < s2.dist) xchg(s4,s2);
- if (s3.dist < s2.dist) xchg(s3,s2);
- }
-
- /*! use SSE instructions to swap stack items */
- __forceinline static void cmp_xchg(vint4& a, vint4& b)
- {
-#if defined(__AVX512VL__)
- const vboolf4 mask(shuffle<2,2,2,2>(b) < shuffle<2,2,2,2>(a));
-#else
- const vboolf4 mask0(b < a);
- const vboolf4 mask(shuffle<2,2,2,2>(mask0));
-#endif
- const vint4 c = select(mask,b,a);
- const vint4 d = select(mask,a,b);
- a = c;
- b = d;
- }
-
- /*! Sort 3 stack items. */
- __forceinline static void sort3(vint4& s1, vint4& s2, vint4& s3)
- {
- cmp_xchg(s2,s1);
- cmp_xchg(s3,s2);
- cmp_xchg(s2,s1);
- }
-
- /*! Sort 4 stack items. */
- __forceinline static void sort4(vint4& s1, vint4& s2, vint4& s3, vint4& s4)
- {
- cmp_xchg(s2,s1);
- cmp_xchg(s4,s3);
- cmp_xchg(s3,s1);
- cmp_xchg(s4,s2);
- cmp_xchg(s3,s2);
- }
-
-
- /*! Sort N stack items. */
- __forceinline friend void sort(StackItemT* begin, StackItemT* end)
- {
- for (StackItemT* i = begin+1; i != end; ++i)
- {
- const vfloat4 item = vfloat4::load((float*)i);
- const unsigned dist = i->dist;
- StackItemT* j = i;
-
- while ((j != begin) && ((j-1)->dist < dist))
- {
- vfloat4::store(j, vfloat4::load((float*)(j-1)));
- --j;
- }
-
- vfloat4::store(j, item);
- }
- }
-
- public:
- T ptr;
- unsigned dist;
- };
-
- /*! An item on the stack holds the node ID and active ray mask. */
- template<typename T>
- struct __aligned(8) StackItemMaskT
- {
- T ptr;
- size_t mask;
- };
-
- struct __aligned(8) StackItemMaskCoherent
- {
- size_t mask;
- size_t parent;
- size_t child;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/stat.cpp b/thirdparty/embree-aarch64/kernels/common/stat.cpp
deleted file mode 100644
index b73c3a8c76..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/stat.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "stat.h"
-
-namespace embree
-{
- Stat Stat::instance;
-
- Stat::Stat () {
- }
-
- Stat::~Stat ()
- {
-#ifdef EMBREE_STAT_COUNTERS
- Stat::print(std::cout);
-#endif
- }
-
- void Stat::print(std::ostream& cout)
- {
- Counters& cntrs = instance.cntrs;
- Counters::Data& data = instance.cntrs.code;
- //Counters::Data& data = instance.cntrs.active;
-
- /* print absolute numbers */
- cout << "--------- ABSOLUTE ---------" << std::endl;
- cout << " #normal_travs = " << float(data.normal.travs )*1E-6 << "M" << std::endl;
- cout << " #nodes = " << float(data.normal.trav_nodes )*1E-6 << "M" << std::endl;
- cout << " #nodes_xfm = " << float(data.normal.trav_xfm_nodes )*1E-6 << "M" << std::endl;
- cout << " #leaves = " << float(data.normal.trav_leaves )*1E-6 << "M" << std::endl;
- cout << " #prims = " << float(data.normal.trav_prims )*1E-6 << "M" << std::endl;
- cout << " #prim_hits = " << float(data.normal.trav_prim_hits )*1E-6 << "M" << std::endl;
-
- cout << " #stack nodes = " << float(data.normal.trav_stack_nodes )*1E-6 << "M" << std::endl;
- cout << " #stack pop = " << float(data.normal.trav_stack_pop )*1E-6 << "M" << std::endl;
-
- size_t normal_box_hits = 0;
- size_t weighted_box_hits = 0;
- for (size_t i=0;i<SIZE_HISTOGRAM;i++) {
- normal_box_hits += data.normal.trav_hit_boxes[i];
- weighted_box_hits += data.normal.trav_hit_boxes[i]*i;
- }
- cout << " #hit_boxes = " << normal_box_hits << " (total) distribution: ";
- float average = 0.0f;
- for (size_t i=0;i<SIZE_HISTOGRAM;i++)
- {
- float value = 100.0f * data.normal.trav_hit_boxes[i] / normal_box_hits;
- cout << "[" << i << "] " << value << " ";
- average += (float)i*data.normal.trav_hit_boxes[i] / normal_box_hits;
- }
- cout << " average = " << average << std::endl;
- for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.normal.trav_hit_boxes[i]*i / weighted_box_hits << " ";
- cout << std::endl;
-
- if (data.shadow.travs) {
- cout << " #shadow_travs = " << float(data.shadow.travs )*1E-6 << "M" << std::endl;
- cout << " #nodes = " << float(data.shadow.trav_nodes )*1E-6 << "M" << std::endl;
- cout << " #nodes_xfm = " << float(data.shadow.trav_xfm_nodes)*1E-6 << "M" << std::endl;
- cout << " #leaves = " << float(data.shadow.trav_leaves )*1E-6 << "M" << std::endl;
- cout << " #prims = " << float(data.shadow.trav_prims )*1E-6 << "M" << std::endl;
- cout << " #prim_hits = " << float(data.shadow.trav_prim_hits)*1E-6 << "M" << std::endl;
-
- cout << " #stack nodes = " << float(data.shadow.trav_stack_nodes )*1E-6 << "M" << std::endl;
- cout << " #stack pop = " << float(data.shadow.trav_stack_pop )*1E-6 << "M" << std::endl;
-
- size_t shadow_box_hits = 0;
- size_t weighted_shadow_box_hits = 0;
-
- for (size_t i=0;i<SIZE_HISTOGRAM;i++) {
- shadow_box_hits += data.shadow.trav_hit_boxes[i];
- weighted_shadow_box_hits += data.shadow.trav_hit_boxes[i]*i;
- }
- cout << " #hit_boxes = ";
- for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.shadow.trav_hit_boxes[i] / shadow_box_hits << " ";
- cout << std::endl;
- for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.shadow.trav_hit_boxes[i]*i / weighted_shadow_box_hits << " ";
- cout << std::endl;
- }
- cout << std::endl;
-
- /* print per traversal numbers */
- cout << "--------- PER TRAVERSAL ---------" << std::endl;
- float active_normal_travs = float(cntrs.active.normal.travs )/float(cntrs.all.normal.travs );
- float active_normal_trav_nodes = float(cntrs.active.normal.trav_nodes )/float(cntrs.all.normal.trav_nodes );
- float active_normal_trav_xfm_nodes = float(cntrs.active.normal.trav_xfm_nodes )/float(cntrs.all.normal.trav_xfm_nodes );
- float active_normal_trav_leaves = float(cntrs.active.normal.trav_leaves)/float(cntrs.all.normal.trav_leaves);
- float active_normal_trav_prims = float(cntrs.active.normal.trav_prims )/float(cntrs.all.normal.trav_prims );
- float active_normal_trav_prim_hits = float(cntrs.active.normal.trav_prim_hits )/float(cntrs.all.normal.trav_prim_hits );
- float active_normal_trav_stack_pop = float(cntrs.active.normal.trav_stack_pop )/float(cntrs.all.normal.trav_stack_pop );
-
- cout << " #normal_travs = " << float(cntrs.code.normal.travs )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_travs << "% active" << std::endl;
- cout << " #nodes = " << float(cntrs.code.normal.trav_nodes )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_nodes << "% active" << std::endl;
- cout << " #node_xfm = " << float(cntrs.code.normal.trav_xfm_nodes )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_xfm_nodes << "% active" << std::endl;
- cout << " #leaves = " << float(cntrs.code.normal.trav_leaves)/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_leaves << "% active" << std::endl;
- cout << " #prims = " << float(cntrs.code.normal.trav_prims )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_prims << "% active" << std::endl;
- cout << " #prim_hits = " << float(cntrs.code.normal.trav_prim_hits )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_prim_hits << "% active" << std::endl;
- cout << " #stack_pop = " << float(cntrs.code.normal.trav_stack_pop )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_stack_pop << "% active" << std::endl;
-
- if (cntrs.all.shadow.travs) {
- float active_shadow_travs = float(cntrs.active.shadow.travs )/float(cntrs.all.shadow.travs );
- float active_shadow_trav_nodes = float(cntrs.active.shadow.trav_nodes )/float(cntrs.all.shadow.trav_nodes );
- float active_shadow_trav_xfm_nodes = float(cntrs.active.shadow.trav_xfm_nodes )/float(cntrs.all.shadow.trav_xfm_nodes );
- float active_shadow_trav_leaves = float(cntrs.active.shadow.trav_leaves)/float(cntrs.all.shadow.trav_leaves);
- float active_shadow_trav_prims = float(cntrs.active.shadow.trav_prims )/float(cntrs.all.shadow.trav_prims );
- float active_shadow_trav_prim_hits = float(cntrs.active.shadow.trav_prim_hits )/float(cntrs.all.shadow.trav_prim_hits );
-
- cout << " #shadow_travs = " << float(cntrs.code.shadow.travs )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_travs << "% active" << std::endl;
- cout << " #nodes = " << float(cntrs.code.shadow.trav_nodes )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_nodes << "% active" << std::endl;
- cout << " #nodes_xfm = " << float(cntrs.code.shadow.trav_xfm_nodes )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_xfm_nodes << "% active" << std::endl;
- cout << " #leaves = " << float(cntrs.code.shadow.trav_leaves)/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_leaves << "% active" << std::endl;
- cout << " #prims = " << float(cntrs.code.shadow.trav_prims )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_prims << "% active" << std::endl;
- cout << " #prim_hits = " << float(cntrs.code.shadow.trav_prim_hits )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_prim_hits << "% active" << std::endl;
-
- }
- cout << std::endl;
-
- /* print user counters for performance tuning */
- cout << "--------- USER ---------" << std::endl;
- for (size_t i=0; i<10; i++)
- cout << "#user" << i << " = " << float(cntrs.user[i])/float(cntrs.all.normal.travs+cntrs.all.shadow.travs) << " per traversal" << std::endl;
-
- cout << "#user5/user3 " << 100.0f*float(cntrs.user[5])/float(cntrs.user[3]) << "%" << std::endl;
- cout << "#user6/user3 " << 100.0f*float(cntrs.user[6])/float(cntrs.user[3]) << "%" << std::endl;
- cout << "#user7/user3 " << 100.0f*float(cntrs.user[7])/float(cntrs.user[3]) << "%" << std::endl;
- cout << std::endl;
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/stat.h b/thirdparty/embree-aarch64/kernels/common/stat.h
deleted file mode 100644
index 3cda2bd014..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/stat.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-
-/* Macros to gather statistics */
-#ifdef EMBREE_STAT_COUNTERS
-# define STAT(x) x
-# define STAT3(s,x,y,z) \
- STAT(Stat::get().code .s+=x); \
- STAT(Stat::get().active.s+=y); \
- STAT(Stat::get().all .s+=z);
-# define STAT_USER(i,x) Stat::get().user[i]+=x;
-#else
-# define STAT(x)
-# define STAT3(s,x,y,z)
-# define STAT_USER(i,x)
-#endif
-
-namespace embree
-{
- /*! Gathers ray tracing statistics. We count 1) how often a code
- * location is reached, 2) how many SIMD lanes are active, 3) how
- * many SIMD lanes reach the code location */
- class Stat
- {
- public:
-
- static const size_t SIZE_HISTOGRAM = 64+1;
-
- /*! constructs stat counter class */
- Stat ();
-
- /*! destructs stat counter class */
- ~Stat ();
-
- class Counters
- {
- public:
- Counters () {
- clear();
- }
-
- void clear()
- {
- all.clear();
- active.clear();
- code.clear();
- for (auto& u : user) u.store(0);
- }
-
- public:
-
- /* per packet and per ray stastics */
- struct Data
- {
- void clear () {
- normal.clear();
- shadow.clear();
- point_query.clear();
- }
-
- /* normal and shadow ray statistics */
- struct
- {
- void clear()
- {
- travs.store(0);
- trav_nodes.store(0);
- trav_leaves.store(0);
- trav_prims.store(0);
- trav_prim_hits.store(0);
- for (auto& v : trav_hit_boxes) v.store(0);
- trav_stack_pop.store(0);
- trav_stack_nodes.store(0);
- trav_xfm_nodes.store(0);
- }
-
- public:
- std::atomic<size_t> travs;
- std::atomic<size_t> trav_nodes;
- std::atomic<size_t> trav_leaves;
- std::atomic<size_t> trav_prims;
- std::atomic<size_t> trav_prim_hits;
- std::atomic<size_t> trav_hit_boxes[SIZE_HISTOGRAM+1];
- std::atomic<size_t> trav_stack_pop;
- std::atomic<size_t> trav_stack_nodes;
- std::atomic<size_t> trav_xfm_nodes;
-
- } normal, shadow, point_query;
- } all, active, code;
-
- std::atomic<size_t> user[10];
- };
-
- public:
-
- static __forceinline Counters& get() {
- return instance.cntrs;
- }
-
- static void clear() {
- instance.cntrs.clear();
- }
-
- static void print(embree_ostream cout);
-
- private:
- Counters cntrs;
-
- private:
- static Stat instance;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/state.cpp b/thirdparty/embree-aarch64/kernels/common/state.cpp
deleted file mode 100644
index 51fc9b7826..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/state.cpp
+++ /dev/null
@@ -1,543 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "state.h"
-#include "../../common/lexers/streamfilters.h"
-
-namespace embree
-{
- MutexSys g_printMutex;
-
- State::ErrorHandler State::g_errorHandler;
-
- State::ErrorHandler::ErrorHandler()
- : thread_error(createTls()) {}
-
- State::ErrorHandler::~ErrorHandler()
- {
- Lock<MutexSys> lock(errors_mutex);
- for (size_t i=0; i<thread_errors.size(); i++)
- delete thread_errors[i];
- destroyTls(thread_error);
- thread_errors.clear();
- }
-
- RTCError* State::ErrorHandler::error()
- {
- RTCError* stored_error = (RTCError*) getTls(thread_error);
- if (stored_error) return stored_error;
-
- Lock<MutexSys> lock(errors_mutex);
- stored_error = new RTCError(RTC_ERROR_NONE);
- thread_errors.push_back(stored_error);
- setTls(thread_error,stored_error);
- return stored_error;
- }
-
- State::State ()
- : enabled_cpu_features(getCPUFeatures()),
- enabled_builder_cpu_features(enabled_cpu_features),
- frequency_level(FREQUENCY_SIMD256)
- {
- tri_accel = "default";
- tri_builder = "default";
- tri_traverser = "default";
-
- tri_accel_mb = "default";
- tri_builder_mb = "default";
- tri_traverser_mb = "default";
-
- quad_accel = "default";
- quad_builder = "default";
- quad_traverser = "default";
-
- quad_accel_mb = "default";
- quad_builder_mb = "default";
- quad_traverser_mb = "default";
-
- line_accel = "default";
- line_builder = "default";
- line_traverser = "default";
-
- line_accel_mb = "default";
- line_builder_mb = "default";
- line_traverser_mb = "default";
-
- hair_accel = "default";
- hair_builder = "default";
- hair_traverser = "default";
-
- hair_accel_mb = "default";
- hair_builder_mb = "default";
- hair_traverser_mb = "default";
-
- object_accel = "default";
- object_builder = "default";
- object_accel_min_leaf_size = 1;
- object_accel_max_leaf_size = 1;
-
- object_accel_mb = "default";
- object_builder_mb = "default";
- object_accel_mb_min_leaf_size = 1;
- object_accel_mb_max_leaf_size = 1;
-
- max_spatial_split_replications = 1.2f;
- useSpatialPreSplits = false;
-
- tessellation_cache_size = 128*1024*1024;
-
- subdiv_accel = "default";
- subdiv_accel_mb = "default";
-
- grid_accel = "default";
- grid_builder = "default";
- grid_accel_mb = "default";
- grid_builder_mb = "default";
-
- instancing_open_min = 0;
- instancing_block_size = 0;
- instancing_open_factor = 8.0f;
- instancing_open_max_depth = 32;
- instancing_open_max = 50000000;
-
- ignore_config_files = false;
- float_exceptions = false;
- quality_flags = -1;
- scene_flags = -1;
- verbose = 0;
- benchmark = 0;
-
- numThreads = 0;
- numUserThreads = 0;
-
-#if TASKING_INTERNAL
- set_affinity = true;
-#else
- set_affinity = false;
-#endif
- /* per default enable affinity on KNL */
- if (hasISA(AVX512KNL)) set_affinity = true;
-
- start_threads = false;
- enable_selockmemoryprivilege = false;
-#if defined(__LINUX__)
- hugepages = true;
-#else
- hugepages = false;
-#endif
- hugepages_success = true;
-
- alloc_main_block_size = 0;
- alloc_num_main_slots = 0;
- alloc_thread_block_size = 0;
- alloc_single_thread_alloc = -1;
-
- error_function = nullptr;
- error_function_userptr = nullptr;
-
- memory_monitor_function = nullptr;
- memory_monitor_userptr = nullptr;
- }
-
- State::~State() {
- }
-
- bool State::hasISA(const int isa) {
- return (enabled_cpu_features & isa) == isa;
- }
-
- bool State::checkISASupport() {
-#if defined(__ARM_NEON)
- /*
- * NEON CPU type is a mixture of NEON and SSE2
- */
-
- bool hasSSE2 = (getCPUFeatures() & enabled_cpu_features) & CPU_FEATURE_SSE2;
-
- /* this will be true when explicitly initialize Device with `isa=neon` config */
- bool hasNEON = (getCPUFeatures() & enabled_cpu_features) & CPU_FEATURE_NEON;
-
- return hasSSE2 || hasNEON;
-#else
- return (getCPUFeatures() & enabled_cpu_features) == enabled_cpu_features;
-#endif
- }
-
- void State::verify()
- {
- /* verify that calculations stay in range */
- assert(rcp(min_rcp_input)*FLT_LARGE+FLT_LARGE < 0.01f*FLT_MAX);
-
- /* here we verify that CPP files compiled for a specific ISA only
- * call that same or lower ISA version of non-inlined class member
- * functions */
-#if defined(DEBUG)
-#if defined(EMBREE_TARGET_SSE2)
-#if !defined(__ARM_NEON)
- assert(sse2::getISA() <= SSE2);
-#endif
-#endif
-#if defined(EMBREE_TARGET_SSE42)
- assert(sse42::getISA() <= SSE42);
-#endif
-#if defined(EMBREE_TARGET_AVX)
- assert(avx::getISA() <= AVX);
-#endif
-#if defined(EMBREE_TARGET_AVX2)
- assert(avx2::getISA() <= AVX2);
-#endif
-#if defined (EMBREE_TARGET_AVX512KNL)
- assert(avx512knl::getISA() <= AVX512KNL);
-#endif
-#if defined (EMBREE_TARGET_AVX512SKX)
- assert(avx512skx::getISA() <= AVX512SKX);
-#endif
-#endif
- }
-
- const char* symbols[3] = { "=", ",", "|" };
-
- bool State::parseFile(const FileName& fileName)
- {
- FILE* f = fopen(fileName.c_str(),"r");
- if (!f) return false;
- Ref<Stream<int> > file = new FileStream(f,fileName);
-
- std::vector<std::string> syms;
- for (size_t i=0; i<sizeof(symbols)/sizeof(void*); i++)
- syms.push_back(symbols[i]);
-
- Ref<TokenStream> cin = new TokenStream(new LineCommentFilter(file,"#"),
- TokenStream::alpha+TokenStream::ALPHA+TokenStream::numbers+"_.",
- TokenStream::separators,syms);
- parse(cin);
- return true;
- }
-
- void State::parseString(const char* cfg)
- {
- if (cfg == nullptr) return;
-
- std::vector<std::string> syms;
- for (size_t i=0; i<sizeof(symbols)/sizeof(void*); i++)
- syms.push_back(symbols[i]);
-
- Ref<TokenStream> cin = new TokenStream(new StrStream(cfg),
- TokenStream::alpha+TokenStream::ALPHA+TokenStream::numbers+"_.",
- TokenStream::separators,syms);
- parse(cin);
- }
-
- int string_to_cpufeatures(const std::string& isa)
- {
- if (isa == "sse" ) return SSE;
- else if (isa == "sse2") return SSE2;
- else if (isa == "sse3") return SSE3;
- else if (isa == "ssse3") return SSSE3;
- else if (isa == "sse41") return SSE41;
- else if (isa == "sse4.1") return SSE41;
- else if (isa == "sse42") return SSE42;
- else if (isa == "sse4.2") return SSE42;
- else if (isa == "avx") return AVX;
- else if (isa == "avxi") return AVXI;
- else if (isa == "avx2") return AVX2;
- else if (isa == "avx512knl") return AVX512KNL;
- else if (isa == "avx512skx") return AVX512SKX;
- else return SSE2;
- }
-
- void State::parse(Ref<TokenStream> cin)
- {
- /* parse until end of stream */
- while (cin->peek() != Token::Eof())
- {
- const Token tok = cin->get();
-
- if (tok == Token::Id("threads") && cin->trySymbol("="))
- numThreads = cin->get().Int();
-
- else if (tok == Token::Id("user_threads")&& cin->trySymbol("="))
- numUserThreads = cin->get().Int();
-
- else if (tok == Token::Id("set_affinity")&& cin->trySymbol("="))
- set_affinity = cin->get().Int();
-
- else if (tok == Token::Id("affinity")&& cin->trySymbol("="))
- set_affinity = cin->get().Int();
-
- else if (tok == Token::Id("start_threads")&& cin->trySymbol("="))
- start_threads = cin->get().Int();
-
- else if (tok == Token::Id("isa") && cin->trySymbol("=")) {
- std::string isa = toLowerCase(cin->get().Identifier());
- enabled_cpu_features = string_to_cpufeatures(isa);
- enabled_builder_cpu_features = enabled_cpu_features;
- }
-
- else if (tok == Token::Id("max_isa") && cin->trySymbol("=")) {
- std::string isa = toLowerCase(cin->get().Identifier());
- enabled_cpu_features &= string_to_cpufeatures(isa);
- enabled_builder_cpu_features &= enabled_cpu_features;
- }
-
- else if (tok == Token::Id("max_builder_isa") && cin->trySymbol("=")) {
- std::string isa = toLowerCase(cin->get().Identifier());
- enabled_builder_cpu_features &= string_to_cpufeatures(isa);
- }
-
- else if (tok == Token::Id("frequency_level") && cin->trySymbol("=")) {
- std::string freq = cin->get().Identifier();
- if (freq == "simd128") frequency_level = FREQUENCY_SIMD128;
- else if (freq == "simd256") frequency_level = FREQUENCY_SIMD256;
- else if (freq == "simd512") frequency_level = FREQUENCY_SIMD512;
- }
-
- else if (tok == Token::Id("enable_selockmemoryprivilege") && cin->trySymbol("=")) {
- enable_selockmemoryprivilege = cin->get().Int();
- }
- else if (tok == Token::Id("hugepages") && cin->trySymbol("=")) {
- hugepages = cin->get().Int();
- }
-
- else if (tok == Token::Id("ignore_config_files") && cin->trySymbol("="))
- ignore_config_files = cin->get().Int();
- else if (tok == Token::Id("float_exceptions") && cin->trySymbol("="))
- float_exceptions = cin->get().Int();
-
- else if ((tok == Token::Id("tri_accel") || tok == Token::Id("accel")) && cin->trySymbol("="))
- tri_accel = cin->get().Identifier();
- else if ((tok == Token::Id("tri_builder") || tok == Token::Id("builder")) && cin->trySymbol("="))
- tri_builder = cin->get().Identifier();
- else if ((tok == Token::Id("tri_traverser") || tok == Token::Id("traverser")) && cin->trySymbol("="))
- tri_traverser = cin->get().Identifier();
-
- else if ((tok == Token::Id("tri_accel_mb") || tok == Token::Id("accel_mb")) && cin->trySymbol("="))
- tri_accel_mb = cin->get().Identifier();
- else if ((tok == Token::Id("tri_builder_mb") || tok == Token::Id("builder_mb")) && cin->trySymbol("="))
- tri_builder_mb = cin->get().Identifier();
- else if ((tok == Token::Id("tri_traverser_mb") || tok == Token::Id("traverser_mb")) && cin->trySymbol("="))
- tri_traverser_mb = cin->get().Identifier();
-
- else if ((tok == Token::Id("quad_accel")) && cin->trySymbol("="))
- quad_accel = cin->get().Identifier();
- else if ((tok == Token::Id("quad_builder")) && cin->trySymbol("="))
- quad_builder = cin->get().Identifier();
- else if ((tok == Token::Id("quad_traverser")) && cin->trySymbol("="))
- quad_traverser = cin->get().Identifier();
-
- else if ((tok == Token::Id("quad_accel_mb")) && cin->trySymbol("="))
- quad_accel_mb = cin->get().Identifier();
- else if ((tok == Token::Id("quad_builder_mb")) && cin->trySymbol("="))
- quad_builder_mb = cin->get().Identifier();
- else if ((tok == Token::Id("quad_traverser_mb")) && cin->trySymbol("="))
- quad_traverser_mb = cin->get().Identifier();
-
- else if ((tok == Token::Id("line_accel")) && cin->trySymbol("="))
- line_accel = cin->get().Identifier();
- else if ((tok == Token::Id("line_builder")) && cin->trySymbol("="))
- line_builder = cin->get().Identifier();
- else if ((tok == Token::Id("line_traverser")) && cin->trySymbol("="))
- line_traverser = cin->get().Identifier();
-
- else if ((tok == Token::Id("line_accel_mb")) && cin->trySymbol("="))
- line_accel_mb = cin->get().Identifier();
- else if ((tok == Token::Id("line_builder_mb")) && cin->trySymbol("="))
- line_builder_mb = cin->get().Identifier();
- else if ((tok == Token::Id("line_traverser_mb")) && cin->trySymbol("="))
- line_traverser_mb = cin->get().Identifier();
-
- else if (tok == Token::Id("hair_accel") && cin->trySymbol("="))
- hair_accel = cin->get().Identifier();
- else if (tok == Token::Id("hair_builder") && cin->trySymbol("="))
- hair_builder = cin->get().Identifier();
- else if (tok == Token::Id("hair_traverser") && cin->trySymbol("="))
- hair_traverser = cin->get().Identifier();
-
- else if (tok == Token::Id("hair_accel_mb") && cin->trySymbol("="))
- hair_accel_mb = cin->get().Identifier();
- else if (tok == Token::Id("hair_builder_mb") && cin->trySymbol("="))
- hair_builder_mb = cin->get().Identifier();
- else if (tok == Token::Id("hair_traverser_mb") && cin->trySymbol("="))
- hair_traverser_mb = cin->get().Identifier();
-
- else if (tok == Token::Id("object_accel") && cin->trySymbol("="))
- object_accel = cin->get().Identifier();
- else if (tok == Token::Id("object_builder") && cin->trySymbol("="))
- object_builder = cin->get().Identifier();
- else if (tok == Token::Id("object_accel_min_leaf_size") && cin->trySymbol("="))
- object_accel_min_leaf_size = cin->get().Int();
- else if (tok == Token::Id("object_accel_max_leaf_size") && cin->trySymbol("="))
- object_accel_max_leaf_size = cin->get().Int();
-
- else if (tok == Token::Id("object_accel_mb") && cin->trySymbol("="))
- object_accel_mb = cin->get().Identifier();
- else if (tok == Token::Id("object_builder_mb") && cin->trySymbol("="))
- object_builder_mb = cin->get().Identifier();
- else if (tok == Token::Id("object_accel_mb_min_leaf_size") && cin->trySymbol("="))
- object_accel_mb_min_leaf_size = cin->get().Int();
- else if (tok == Token::Id("object_accel_mb_max_leaf_size") && cin->trySymbol("="))
- object_accel_mb_max_leaf_size = cin->get().Int();
-
- else if (tok == Token::Id("instancing_open_min") && cin->trySymbol("="))
- instancing_open_min = cin->get().Int();
- else if (tok == Token::Id("instancing_block_size") && cin->trySymbol("=")) {
- instancing_block_size = cin->get().Int();
- instancing_open_factor = 0.0f;
- }
- else if (tok == Token::Id("instancing_open_max_depth") && cin->trySymbol("="))
- instancing_open_max_depth = cin->get().Int();
- else if (tok == Token::Id("instancing_open_factor") && cin->trySymbol("=")) {
- instancing_block_size = 0;
- instancing_open_factor = cin->get().Float();
- }
- else if (tok == Token::Id("instancing_open_max") && cin->trySymbol("="))
- instancing_open_max = cin->get().Int();
-
- else if (tok == Token::Id("subdiv_accel") && cin->trySymbol("="))
- subdiv_accel = cin->get().Identifier();
- else if (tok == Token::Id("subdiv_accel_mb") && cin->trySymbol("="))
- subdiv_accel_mb = cin->get().Identifier();
-
- else if (tok == Token::Id("grid_accel") && cin->trySymbol("="))
- grid_accel = cin->get().Identifier();
- else if (tok == Token::Id("grid_accel_mb") && cin->trySymbol("="))
- grid_accel_mb = cin->get().Identifier();
-
- else if (tok == Token::Id("verbose") && cin->trySymbol("="))
- verbose = cin->get().Int();
- else if (tok == Token::Id("benchmark") && cin->trySymbol("="))
- benchmark = cin->get().Int();
-
- else if (tok == Token::Id("quality")) {
- if (cin->trySymbol("=")) {
- Token flag = cin->get();
- if (flag == Token::Id("low")) quality_flags = RTC_BUILD_QUALITY_LOW;
- else if (flag == Token::Id("medium")) quality_flags = RTC_BUILD_QUALITY_MEDIUM;
- else if (flag == Token::Id("high")) quality_flags = RTC_BUILD_QUALITY_HIGH;
- }
- }
-
- else if (tok == Token::Id("scene_flags")) {
- scene_flags = 0;
- if (cin->trySymbol("=")) {
- do {
- Token flag = cin->get();
- if (flag == Token::Id("dynamic") ) scene_flags |= RTC_SCENE_FLAG_DYNAMIC;
- else if (flag == Token::Id("compact")) scene_flags |= RTC_SCENE_FLAG_COMPACT;
- else if (flag == Token::Id("robust")) scene_flags |= RTC_SCENE_FLAG_ROBUST;
- } while (cin->trySymbol("|"));
- }
- }
-
- else if (tok == Token::Id("max_spatial_split_replications") && cin->trySymbol("="))
- max_spatial_split_replications = cin->get().Float();
-
- else if (tok == Token::Id("presplits") && cin->trySymbol("="))
- useSpatialPreSplits = cin->get().Int() != 0 ? true : false;
-
- else if (tok == Token::Id("tessellation_cache_size") && cin->trySymbol("="))
- tessellation_cache_size = size_t(cin->get().Float()*1024.0f*1024.0f);
- else if (tok == Token::Id("cache_size") && cin->trySymbol("="))
- tessellation_cache_size = size_t(cin->get().Float()*1024.0f*1024.0f);
-
- else if (tok == Token::Id("alloc_main_block_size") && cin->trySymbol("="))
- alloc_main_block_size = cin->get().Int();
- else if (tok == Token::Id("alloc_num_main_slots") && cin->trySymbol("="))
- alloc_num_main_slots = cin->get().Int();
- else if (tok == Token::Id("alloc_thread_block_size") && cin->trySymbol("="))
- alloc_thread_block_size = cin->get().Int();
- else if (tok == Token::Id("alloc_single_thread_alloc") && cin->trySymbol("="))
- alloc_single_thread_alloc = cin->get().Int();
-
- cin->trySymbol(","); // optional , separator
- }
- }
-
- bool State::verbosity(size_t N) {
- return N <= verbose;
- }
-
- void State::print()
- {
- std::cout << "general:" << std::endl;
- std::cout << " build threads = " << numThreads << std::endl;
- std::cout << " build user threads = " << numUserThreads << std::endl;
- std::cout << " start_threads = " << start_threads << std::endl;
- std::cout << " affinity = " << set_affinity << std::endl;
- std::cout << " frequency_level = ";
- switch (frequency_level) {
- case FREQUENCY_SIMD128: std::cout << "simd128" << std::endl; break;
- case FREQUENCY_SIMD256: std::cout << "simd256" << std::endl; break;
- case FREQUENCY_SIMD512: std::cout << "simd512" << std::endl; break;
- default: std::cout << "error" << std::endl; break;
- }
-
- std::cout << " hugepages = ";
- if (!hugepages) std::cout << "disabled" << std::endl;
- else if (hugepages_success) std::cout << "enabled" << std::endl;
- else std::cout << "failed" << std::endl;
-
- std::cout << " verbosity = " << verbose << std::endl;
- std::cout << " cache_size = " << float(tessellation_cache_size)*1E-6 << " MB" << std::endl;
- std::cout << " max_spatial_split_replications = " << max_spatial_split_replications << std::endl;
-
- std::cout << "triangles:" << std::endl;
- std::cout << " accel = " << tri_accel << std::endl;
- std::cout << " builder = " << tri_builder << std::endl;
- std::cout << " traverser = " << tri_traverser << std::endl;
-
- std::cout << "motion blur triangles:" << std::endl;
- std::cout << " accel = " << tri_accel_mb << std::endl;
- std::cout << " builder = " << tri_builder_mb << std::endl;
- std::cout << " traverser = " << tri_traverser_mb << std::endl;
-
- std::cout << "quads:" << std::endl;
- std::cout << " accel = " << quad_accel << std::endl;
- std::cout << " builder = " << quad_builder << std::endl;
- std::cout << " traverser = " << quad_traverser << std::endl;
-
- std::cout << "motion blur quads:" << std::endl;
- std::cout << " accel = " << quad_accel_mb << std::endl;
- std::cout << " builder = " << quad_builder_mb << std::endl;
- std::cout << " traverser = " << quad_traverser_mb << std::endl;
-
- std::cout << "line segments:" << std::endl;
- std::cout << " accel = " << line_accel << std::endl;
- std::cout << " builder = " << line_builder << std::endl;
- std::cout << " traverser = " << line_traverser << std::endl;
-
- std::cout << "motion blur line segments:" << std::endl;
- std::cout << " accel = " << line_accel_mb << std::endl;
- std::cout << " builder = " << line_builder_mb << std::endl;
- std::cout << " traverser = " << line_traverser_mb << std::endl;
-
- std::cout << "hair:" << std::endl;
- std::cout << " accel = " << hair_accel << std::endl;
- std::cout << " builder = " << hair_builder << std::endl;
- std::cout << " traverser = " << hair_traverser << std::endl;
-
- std::cout << "motion blur hair:" << std::endl;
- std::cout << " accel = " << hair_accel_mb << std::endl;
- std::cout << " builder = " << hair_builder_mb << std::endl;
- std::cout << " traverser = " << hair_traverser_mb << std::endl;
-
- std::cout << "subdivision surfaces:" << std::endl;
- std::cout << " accel = " << subdiv_accel << std::endl;
-
- std::cout << "grids:" << std::endl;
- std::cout << " accel = " << grid_accel << std::endl;
- std::cout << " builder = " << grid_builder << std::endl;
-
- std::cout << "motion blur grids:" << std::endl;
- std::cout << " accel = " << grid_accel_mb << std::endl;
- std::cout << " builder = " << grid_builder_mb << std::endl;
-
- std::cout << "object_accel:" << std::endl;
- std::cout << " min_leaf_size = " << object_accel_min_leaf_size << std::endl;
- std::cout << " max_leaf_size = " << object_accel_max_leaf_size << std::endl;
-
- std::cout << "object_accel_mb:" << std::endl;
- std::cout << " min_leaf_size = " << object_accel_mb_min_leaf_size << std::endl;
- std::cout << " max_leaf_size = " << object_accel_mb_max_leaf_size << std::endl;
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/state.h b/thirdparty/embree-aarch64/kernels/common/state.h
deleted file mode 100644
index d0fccc023f..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/state.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "default.h"
-
-namespace embree
-{
- /* mutex to make printing to cout thread safe */
- extern MutexSys g_printMutex;
-
- struct State : public RefCount
- {
- public:
- /*! state construction */
- State ();
-
- /*! state destruction */
- ~State();
-
- /*! verifies that state is correct */
- void verify();
-
- /*! parses state from a configuration file */
- bool parseFile(const FileName& fileName);
-
- /*! parses the state from a string */
- void parseString(const char* cfg);
-
- /*! parses the state from a stream */
- void parse(Ref<TokenStream> cin);
-
- /*! prints the state */
- void print();
-
- /*! checks if verbosity level is at least N */
- bool verbosity(size_t N);
-
- /*! checks if some particular ISA is enabled */
- bool hasISA(const int isa);
-
- /*! check whether selected ISA is supported by the HW */
- bool checkISASupport();
-
- public:
- std::string tri_accel; //!< acceleration structure to use for triangles
- std::string tri_builder; //!< builder to use for triangles
- std::string tri_traverser; //!< traverser to use for triangles
-
- public:
- std::string tri_accel_mb; //!< acceleration structure to use for motion blur triangles
- std::string tri_builder_mb; //!< builder to use for motion blur triangles
- std::string tri_traverser_mb; //!< traverser to use for triangles
-
- public:
- std::string quad_accel; //!< acceleration structure to use for quads
- std::string quad_builder; //!< builder to use for quads
- std::string quad_traverser; //!< traverser to use for quads
-
- public:
- std::string quad_accel_mb; //!< acceleration structure to use for motion blur quads
- std::string quad_builder_mb; //!< builder to use for motion blur quads
- std::string quad_traverser_mb; //!< traverser to use for motion blur quads
-
- public:
- std::string line_accel; //!< acceleration structure to use for line segments
- std::string line_builder; //!< builder to use for line segments
- std::string line_traverser; //!< traverser to use for line segments
-
- public:
- std::string line_accel_mb; //!< acceleration structure to use for motion blur line segments
- std::string line_builder_mb; //!< builder to use for motion blur line segments
- std::string line_traverser_mb; //!< traverser to use for motion blur line segments
-
- public:
- std::string hair_accel; //!< hair acceleration structure to use
- std::string hair_builder; //!< builder to use for hair
- std::string hair_traverser; //!< traverser to use for hair
-
- public:
- std::string hair_accel_mb; //!< acceleration structure to use for motion blur hair
- std::string hair_builder_mb; //!< builder to use for motion blur hair
- std::string hair_traverser_mb; //!< traverser to use for motion blur hair
-
- public:
- std::string object_accel; //!< acceleration structure for user geometries
- std::string object_builder; //!< builder for user geometries
- int object_accel_min_leaf_size; //!< minimum leaf size for object acceleration structure
- int object_accel_max_leaf_size; //!< maximum leaf size for object acceleration structure
-
- public:
- std::string object_accel_mb; //!< acceleration structure for user geometries
- std::string object_builder_mb; //!< builder for user geometries
- int object_accel_mb_min_leaf_size; //!< minimum leaf size for mblur object acceleration structure
- int object_accel_mb_max_leaf_size; //!< maximum leaf size for mblur object acceleration structure
-
- public:
- std::string subdiv_accel; //!< acceleration structure to use for subdivision surfaces
- std::string subdiv_accel_mb; //!< acceleration structure to use for subdivision surfaces
-
- public:
- std::string grid_accel; //!< acceleration structure to use for grids
- std::string grid_builder; //!< builder for grids
- std::string grid_accel_mb; //!< acceleration structure to use for motion blur grids
- std::string grid_builder_mb; //!< builder for motion blur grids
-
- public:
- float max_spatial_split_replications; //!< maximally replications*N many primitives in accel for spatial splits
- bool useSpatialPreSplits; //!< use spatial pre-splits instead of the full spatial split builder
- size_t tessellation_cache_size; //!< size of the shared tessellation cache
-
- public:
- size_t instancing_open_min; //!< instancing opens tree to minimally that number of subtrees
- size_t instancing_block_size; //!< instancing opens tree up to average block size of primitives
- float instancing_open_factor; //!< instancing opens tree up to x times the number of instances
- size_t instancing_open_max_depth; //!< maximum open depth for geometries
- size_t instancing_open_max; //!< instancing opens tree to maximally that number of subtrees
-
- public:
- bool ignore_config_files; //!< if true no more config files get parse
- bool float_exceptions; //!< enable floating point exceptions
- int quality_flags;
- int scene_flags;
- size_t verbose; //!< verbosity of output
- size_t benchmark; //!< true
-
- public:
- size_t numThreads; //!< number of threads to use in builders
- size_t numUserThreads; //!< number of user provided threads to use in builders
- bool set_affinity; //!< sets affinity for worker threads
- bool start_threads; //!< true when threads should be started at device creation time
- int enabled_cpu_features; //!< CPU ISA features to use
- int enabled_builder_cpu_features; //!< CPU ISA features to use for builders only
- enum FREQUENCY_LEVEL {
- FREQUENCY_SIMD128,
- FREQUENCY_SIMD256,
- FREQUENCY_SIMD512
- } frequency_level; //!< frequency level the app wants to run on (default is SIMD256)
- bool enable_selockmemoryprivilege; //!< configures the SeLockMemoryPrivilege under Windows to enable huge pages
- bool hugepages; //!< true if huge pages should get used
- bool hugepages_success; //!< status for enabling huge pages
-
- public:
- size_t alloc_main_block_size; //!< main allocation block size (shared between threads)
- int alloc_num_main_slots; //!< number of such shared blocks to be used to allocate
- size_t alloc_thread_block_size; //!< size of thread local allocator block size
- int alloc_single_thread_alloc; //!< in single mode nodes and leaves use same thread local allocator
-
- public:
-
- /*! checks if we can use AVX */
- bool canUseAVX() {
- return hasISA(AVX) && frequency_level != FREQUENCY_SIMD128;
- }
-
- /*! checks if we can use AVX2 */
- bool canUseAVX2() {
- return hasISA(AVX2) && frequency_level != FREQUENCY_SIMD128;
- }
-
- struct ErrorHandler
- {
- public:
- ErrorHandler();
- ~ErrorHandler();
- RTCError* error();
-
- public:
- tls_t thread_error;
- std::vector<RTCError*> thread_errors;
- MutexSys errors_mutex;
- };
- ErrorHandler errorHandler;
- static ErrorHandler g_errorHandler;
-
- public:
- void setErrorFunction(RTCErrorFunction fptr, void* uptr)
- {
- error_function = fptr;
- error_function_userptr = uptr;
- }
-
- RTCErrorFunction error_function;
- void* error_function_userptr;
-
- public:
- void setMemoryMonitorFunction(RTCMemoryMonitorFunction fptr, void* uptr)
- {
- memory_monitor_function = fptr;
- memory_monitor_userptr = uptr;
- }
-
- RTCMemoryMonitorFunction memory_monitor_function;
- void* memory_monitor_userptr;
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/common/vector.h b/thirdparty/embree-aarch64/kernels/common/vector.h
deleted file mode 100644
index b478762240..0000000000
--- a/thirdparty/embree-aarch64/kernels/common/vector.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "default.h"
-
-namespace embree
-{
- /*! invokes the memory monitor callback */
- struct MemoryMonitorInterface {
- virtual void memoryMonitor(ssize_t bytes, bool post) = 0;
- };
-
- /*! allocator that performs aligned monitored allocations */
- template<typename T, size_t alignment = 64>
- struct aligned_monitored_allocator
- {
- typedef T value_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- __forceinline aligned_monitored_allocator(MemoryMonitorInterface* device)
- : device(device), hugepages(false) {}
-
- __forceinline pointer allocate( size_type n )
- {
- if (n) {
- assert(device);
- device->memoryMonitor(n*sizeof(T),false);
- }
- if (n*sizeof(value_type) >= 14 * PAGE_SIZE_2M)
- {
- pointer p = (pointer) os_malloc(n*sizeof(value_type),hugepages);
- assert(p);
- return p;
- }
- return (pointer) alignedMalloc(n*sizeof(value_type),alignment);
- }
-
- __forceinline void deallocate( pointer p, size_type n )
- {
- if (p)
- {
- if (n*sizeof(value_type) >= 14 * PAGE_SIZE_2M)
- os_free(p,n*sizeof(value_type),hugepages);
- else
- alignedFree(p);
- }
- else assert(n == 0);
-
- if (n) {
- assert(device);
- device->memoryMonitor(-ssize_t(n)*sizeof(T),true);
- }
- }
-
- __forceinline void construct( pointer p, const_reference val ) {
- new (p) T(val);
- }
-
- __forceinline void destroy( pointer p ) {
- p->~T();
- }
-
- private:
- MemoryMonitorInterface* device;
- bool hugepages;
- };
-
- /*! monitored vector */
- template<typename T>
- using mvector = vector_t<T,aligned_monitored_allocator<T,std::alignment_of<T>::value> >;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/cone.h b/thirdparty/embree-aarch64/kernels/geometry/cone.h
deleted file mode 100644
index 961ef86160..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/cone.h
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-
-namespace embree
-{
- namespace isa
- {
- struct Cone
- {
- const Vec3fa p0; //!< start position of cone
- const Vec3fa p1; //!< end position of cone
- const float r0; //!< start radius of cone
- const float r1; //!< end radius of cone
-
- __forceinline Cone(const Vec3fa& p0, const float r0, const Vec3fa& p1, const float r1)
- : p0(p0), p1(p1), r0(r0), r1(r1) {}
-
- __forceinline bool intersect(const Vec3fa& org, const Vec3fa& dir,
- BBox1f& t_o,
- float& u0_o, Vec3fa& Ng0_o,
- float& u1_o, Vec3fa& Ng1_o) const
- {
- /* calculate quadratic equation to solve */
- const Vec3fa v0 = p0-org;
- const Vec3fa v1 = p1-org;
-
- const float rl = rcp_length(v1-v0);
- const Vec3fa P0 = v0, dP = (v1-v0)*rl;
- const float dr = (r1-r0)*rl;
- const Vec3fa O = -P0, dO = dir;
-
- const float dOdO = dot(dO,dO);
- const float OdO = dot(dO,O);
- const float OO = dot(O,O);
- const float dOz = dot(dP,dO);
- const float Oz = dot(dP,O);
-
- const float R = r0 + Oz*dr;
- const float A = dOdO - sqr(dOz) * (1.0f+sqr(dr));
- const float B = 2.0f * (OdO - dOz*(Oz + R*dr));
- const float C = OO - (sqr(Oz) + sqr(R));
-
- /* we miss the cone if determinant is smaller than zero */
- const float D = B*B - 4.0f*A*C;
- if (D < 0.0f) return false;
-
- /* special case for rays that are "parallel" to the cone */
- const float eps = float(1<<8)*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
- if (unlikely(abs(A) < eps))
- {
- /* cylinder case */
- if (abs(dr) < 16.0f*float(ulp)) {
- if (C <= 0.0f) { t_o = BBox1f(neg_inf,pos_inf); return true; }
- else { t_o = BBox1f(pos_inf,neg_inf); return false; }
- }
-
- /* cone case */
- else
- {
- /* if we hit the negative cone there cannot be a hit */
- const float t = -C/B;
- const float z0 = Oz+t*dOz;
- const float z0r = r0+z0*dr;
- if (z0r < 0.0f) return false;
-
- /* test if we start inside or outside the cone */
- if (dOz*dr > 0.0f) t_o = BBox1f(t,pos_inf);
- else t_o = BBox1f(neg_inf,t);
- }
- }
-
- /* standard case for "non-parallel" rays */
- else
- {
- const float Q = sqrt(D);
- const float rcp_2A = rcp(2.0f*A);
- t_o.lower = (-B-Q)*rcp_2A;
- t_o.upper = (-B+Q)*rcp_2A;
-
- /* standard case where both hits are on same cone */
- if (likely(A > 0.0f)) {
- const float z0 = Oz+t_o.lower*dOz;
- const float z0r = r0+z0*dr;
- if (z0r < 0.0f) return false;
- }
-
- /* special case where the hits are on the positive and negative cone */
- else
- {
- /* depending on the ray direction and the open direction
- * of the cone we have a hit from inside or outside the
- * cone */
- if (dOz*dr > 0) t_o.upper = pos_inf;
- else t_o.lower = neg_inf;
- }
- }
-
- /* calculates u and Ng for near hit */
- {
- u0_o = (Oz+t_o.lower*dOz)*rl;
- const Vec3fa Pr = t_o.lower*dir;
- const Vec3fa Pl = v0 + u0_o*(v1-v0);
- const Vec3fa R = normalize(Pr-Pl);
- const Vec3fa U = (p1-p0)+(r1-r0)*R;
- const Vec3fa V = cross(p1-p0,R);
- Ng0_o = cross(V,U);
- }
-
- /* calculates u and Ng for far hit */
- {
- u1_o = (Oz+t_o.upper*dOz)*rl;
- const Vec3fa Pr = t_o.upper*dir;
- const Vec3fa Pl = v0 + u1_o*(v1-v0);
- const Vec3fa R = normalize(Pr-Pl);
- const Vec3fa U = (p1-p0)+(r1-r0)*R;
- const Vec3fa V = cross(p1-p0,R);
- Ng1_o = cross(V,U);
- }
- return true;
- }
-
- __forceinline bool intersect(const Vec3fa& org, const Vec3fa& dir, BBox1f& t_o) const
- {
- float u0_o; Vec3fa Ng0_o; float u1_o; Vec3fa Ng1_o;
- return intersect(org,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
- }
-
- static bool verify(const size_t id, const Cone& cone, const Ray& ray, bool shouldhit, const float t0, const float t1)
- {
- float eps = 0.001f;
- BBox1f t; bool hit;
- hit = cone.intersect(ray.org,ray.dir,t);
-
- bool failed = hit != shouldhit;
- if (shouldhit) failed |= std::isinf(t0) ? t0 != t.lower : (t0 == -1E6) ? t.lower > -1E6f : abs(t0-t.lower) > eps;
- if (shouldhit) failed |= std::isinf(t1) ? t1 != t.upper : (t1 == +1E6) ? t.upper < +1E6f : abs(t1-t.upper) > eps;
- if (!failed) return true;
- embree_cout << "Cone test " << id << " failed: cone = " << cone << ", ray = " << ray << ", hit = " << hit << ", t = " << t << embree_endl;
- return false;
- }
-
- /* verify cone class */
- static bool verify()
- {
- bool passed = true;
- const Cone cone0(Vec3fa(0.0f,0.0f,0.0f),0.0f,Vec3fa(1.0f,0.0f,0.0f),1.0f);
- passed &= verify(0,cone0,Ray(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa(+1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,3.0f,pos_inf);
- passed &= verify(1,cone0,Ray(Vec3fa(+2.0f,1.0f,0.0f),Vec3fa(-1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,1.0f);
- passed &= verify(2,cone0,Ray(Vec3fa(-1.0f,0.0f,2.0f),Vec3fa(+0.0f,+0.0f,-1.0f),0.0f,float(inf)),false,0.0f,0.0f);
- passed &= verify(3,cone0,Ray(Vec3fa(+1.0f,0.0f,2.0f),Vec3fa(+0.0f,+0.0f,-1.0f),0.0f,float(inf)),true,1.0f,3.0f);
- passed &= verify(4,cone0,Ray(Vec3fa(-1.0f,0.0f,0.0f),Vec3fa(+1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,1.0f,pos_inf);
- passed &= verify(5,cone0,Ray(Vec3fa(+1.0f,0.0f,0.0f),Vec3fa(-1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,1.0f);
- passed &= verify(6,cone0,Ray(Vec3fa(+0.0f,0.0f,1.0f),Vec3fa(+0.0f,+0.0f,-1.0f),0.0f,float(inf)),true,1.0f,1.0f);
- passed &= verify(7,cone0,Ray(Vec3fa(+0.0f,1.0f,0.0f),Vec3fa(-1.0f,-1.0f,+0.0f),0.0f,float(inf)),false,0.0f,0.0f);
- passed &= verify(8,cone0,Ray(Vec3fa(+0.0f,1.0f,0.0f),Vec3fa(+1.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.5f,+1E6);
- passed &= verify(9,cone0,Ray(Vec3fa(+0.0f,1.0f,0.0f),Vec3fa(-1.0f,+1.0f,+0.0f),0.0f,float(inf)),true,-1E6,-0.5f);
- const Cone cone1(Vec3fa(0.0f,0.0f,0.0f),1.0f,Vec3fa(1.0f,0.0f,0.0f),0.0f);
- passed &= verify(10,cone1,Ray(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa(+1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,2.0f);
- passed &= verify(11,cone1,Ray(Vec3fa(-1.0f,0.0f,2.0f),Vec3fa(+0.0f,+0.0f,-1.0f),0.0f,float(inf)),true,0.0f,4.0f);
- const Cone cylinder(Vec3fa(0.0f,0.0f,0.0f),1.0f,Vec3fa(1.0f,0.0f,0.0f),1.0f);
- passed &= verify(12,cylinder,Ray(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
- passed &= verify(13,cylinder,Ray(Vec3fa(+2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
- passed &= verify(14,cylinder,Ray(Vec3fa(+2.0f,1.0f,2.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),false,0.0f,0.0f);
- passed &= verify(15,cylinder,Ray(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
- passed &= verify(16,cylinder,Ray(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
- passed &= verify(17,cylinder,Ray(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
- passed &= verify(18,cylinder,Ray(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
- return passed;
- }
-
- /*! output operator */
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const Cone& c) {
- return cout << "Cone { p0 = " << c.p0 << ", r0 = " << c.r0 << ", p1 = " << c.p1 << ", r1 = " << c.r1 << "}";
- }
- };
-
- template<int N>
- struct ConeN
- {
- typedef Vec3<vfloat<N>> Vec3vfN;
-
- const Vec3vfN p0; //!< start position of cone
- const Vec3vfN p1; //!< end position of cone
- const vfloat<N> r0; //!< start radius of cone
- const vfloat<N> r1; //!< end radius of cone
-
- __forceinline ConeN(const Vec3vfN& p0, const vfloat<N>& r0, const Vec3vfN& p1, const vfloat<N>& r1)
- : p0(p0), p1(p1), r0(r0), r1(r1) {}
-
- __forceinline Cone operator[] (const size_t i) const
- {
- assert(i<N);
- return Cone(Vec3fa(p0.x[i],p0.y[i],p0.z[i]),r0[i],Vec3fa(p1.x[i],p1.y[i],p1.z[i]),r1[i]);
- }
-
- __forceinline vbool<N> intersect(const Vec3fa& org, const Vec3fa& dir,
- BBox<vfloat<N>>& t_o,
- vfloat<N>& u0_o, Vec3vfN& Ng0_o,
- vfloat<N>& u1_o, Vec3vfN& Ng1_o) const
- {
- /* calculate quadratic equation to solve */
- const Vec3vfN v0 = p0-Vec3vfN(org);
- const Vec3vfN v1 = p1-Vec3vfN(org);
-
- const vfloat<N> rl = rcp_length(v1-v0);
- const Vec3vfN P0 = v0, dP = (v1-v0)*rl;
- const vfloat<N> dr = (r1-r0)*rl;
- const Vec3vfN O = -P0, dO = dir;
-
- const vfloat<N> dOdO = dot(dO,dO);
- const vfloat<N> OdO = dot(dO,O);
- const vfloat<N> OO = dot(O,O);
- const vfloat<N> dOz = dot(dP,dO);
- const vfloat<N> Oz = dot(dP,O);
-
- const vfloat<N> R = r0 + Oz*dr;
- const vfloat<N> A = dOdO - sqr(dOz) * (vfloat<N>(1.0f)+sqr(dr));
- const vfloat<N> B = 2.0f * (OdO - dOz*(Oz + R*dr));
- const vfloat<N> C = OO - (sqr(Oz) + sqr(R));
-
- /* we miss the cone if determinant is smaller than zero */
- const vfloat<N> D = B*B - 4.0f*A*C;
- vbool<N> valid = D >= 0.0f;
- if (none(valid)) return valid;
-
- /* special case for rays that are "parallel" to the cone */
- const vfloat<N> eps = float(1<<8)*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
- const vbool<N> validt = valid & (abs(A) < eps);
- const vbool<N> validf = valid & !(abs(A) < eps);
- if (unlikely(any(validt)))
- {
- const vboolx validtt = validt & (abs(dr) < 16.0f*float(ulp));
- const vboolx validtf = validt & (abs(dr) >= 16.0f*float(ulp));
-
- /* cylinder case */
- if (unlikely(any(validtt)))
- {
- t_o.lower = select(validtt, select(C <= 0.0f, vfloat<N>(neg_inf), vfloat<N>(pos_inf)), t_o.lower);
- t_o.upper = select(validtt, select(C <= 0.0f, vfloat<N>(pos_inf), vfloat<N>(neg_inf)), t_o.upper);
- valid &= !validtt | C <= 0.0f;
- }
-
- /* cone case */
- if (any(validtf))
- {
- /* if we hit the negative cone there cannot be a hit */
- const vfloat<N> t = -C/B;
- const vfloat<N> z0 = Oz+t*dOz;
- const vfloat<N> z0r = r0+z0*dr;
- valid &= !validtf | z0r >= 0.0f;
-
- /* test if we start inside or outside the cone */
- t_o.lower = select(validtf, select(dOz*dr > 0.0f, t, vfloat<N>(neg_inf)), t_o.lower);
- t_o.upper = select(validtf, select(dOz*dr > 0.0f, vfloat<N>(pos_inf), t), t_o.upper);
- }
- }
-
- /* standard case for "non-parallel" rays */
- if (likely(any(validf)))
- {
- const vfloat<N> Q = sqrt(D);
- const vfloat<N> rcp_2A = 0.5f*rcp(A);
- t_o.lower = select(validf, (-B-Q)*rcp_2A, t_o.lower);
- t_o.upper = select(validf, (-B+Q)*rcp_2A, t_o.upper);
-
- /* standard case where both hits are on same cone */
- const vbool<N> validft = validf & A>0.0f;
- const vbool<N> validff = validf & !(A>0.0f);
- if (any(validft)) {
- const vfloat<N> z0 = Oz+t_o.lower*dOz;
- const vfloat<N> z0r = r0+z0*dr;
- valid &= !validft | z0r >= 0.0f;
- }
-
- /* special case where the hits are on the positive and negative cone */
- if (any(validff)) {
- /* depending on the ray direction and the open direction
- * of the cone we have a hit from inside or outside the
- * cone */
- t_o.lower = select(validff, select(dOz*dr > 0.0f, t_o.lower, float(neg_inf)), t_o.lower);
- t_o.upper = select(validff, select(dOz*dr > 0.0f, float(pos_inf), t_o.upper), t_o.upper);
- }
- }
-
- /* calculates u and Ng for near hit */
- {
- u0_o = (Oz+t_o.lower*dOz)*rl;
- const Vec3vfN Pr = t_o.lower*Vec3vfN(dir);
- const Vec3vfN Pl = v0 + u0_o*(v1-v0);
- const Vec3vfN R = normalize(Pr-Pl);
- const Vec3vfN U = (p1-p0)+(r1-r0)*R;
- const Vec3vfN V = cross(p1-p0,R);
- Ng0_o = cross(V,U);
- }
-
- /* calculates u and Ng for far hit */
- {
- u1_o = (Oz+t_o.upper*dOz)*rl;
- const Vec3vfN Pr = t_o.lower*Vec3vfN(dir);
- const Vec3vfN Pl = v0 + u1_o*(v1-v0);
- const Vec3vfN R = normalize(Pr-Pl);
- const Vec3vfN U = (p1-p0)+(r1-r0)*R;
- const Vec3vfN V = cross(p1-p0,R);
- Ng1_o = cross(V,U);
- }
- return valid;
- }
-
- __forceinline vbool<N> intersect(const Vec3fa& org, const Vec3fa& dir, BBox<vfloat<N>>& t_o) const
- {
- vfloat<N> u0_o; Vec3vfN Ng0_o; vfloat<N> u1_o; Vec3vfN Ng1_o;
- return intersect(org,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
- }
- };
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/geometry/coneline_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/coneline_intersector.h
deleted file mode 100644
index 0902baff7d..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/coneline_intersector.h
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "curve_intersector_precalculations.h"
-
-namespace embree
-{
- namespace isa
- {
- namespace __coneline_internal
- {
- template<int M, typename Epilog, typename ray_tfar_func>
- static __forceinline bool intersectCone(const vbool<M>& valid_i,
- const Vec3vf<M>& ray_org_in, const Vec3vf<M>& ray_dir,
- const vfloat<M>& ray_tnear, const ray_tfar_func& ray_tfar,
- const Vec4vf<M>& v0, const Vec4vf<M>& v1,
- const vbool<M>& cL, const vbool<M>& cR,
- const Epilog& epilog)
- {
- vbool<M> valid = valid_i;
-
- /* move ray origin closer to make calculations numerically stable */
- const vfloat<M> dOdO = sqr(ray_dir);
- const vfloat<M> rcp_dOdO = rcp(dOdO);
- const Vec3vf<M> center = vfloat<M>(0.5f)*(v0.xyz()+v1.xyz());
- const vfloat<M> dt = dot(center-ray_org_in,ray_dir)*rcp_dOdO;
- const Vec3vf<M> ray_org = ray_org_in + dt*ray_dir;
-
- const Vec3vf<M> dP = v1.xyz() - v0.xyz();
- const Vec3vf<M> p0 = ray_org - v0.xyz();
- const Vec3vf<M> p1 = ray_org - v1.xyz();
-
- const vfloat<M> dPdP = sqr(dP);
- const vfloat<M> dP0 = dot(p0,dP);
- const vfloat<M> dP1 = dot(p1,dP);
- const vfloat<M> dOdP = dot(ray_dir,dP);
-
- // intersect cone body
- const vfloat<M> dr = v0.w - v1.w;
- const vfloat<M> hy = dPdP + sqr(dr);
- const vfloat<M> dO0 = dot(ray_dir,p0);
- const vfloat<M> OO = sqr(p0);
- const vfloat<M> dPdP2 = sqr(dPdP);
- const vfloat<M> dPdPr0 = dPdP*v0.w;
-
- const vfloat<M> A = dPdP2 - sqr(dOdP)*hy;
- const vfloat<M> B = dPdP2*dO0 - dP0*dOdP*hy + dPdPr0*(dr*dOdP);
- const vfloat<M> C = dPdP2*OO - sqr(dP0)*hy + dPdPr0*(2.0f*dr*dP0 - dPdPr0);
-
- const vfloat<M> D = B*B - A*C;
- valid &= D >= 0.0f;
- if (unlikely(none(valid))) {
- return false;
- }
-
- /* standard case for "non-parallel" rays */
- const vfloat<M> Q = sqrt(D);
- const vfloat<M> rcp_A = rcp(A);
- /* special case for rays that are "parallel" to the cone - assume miss */
- const vbool<M> isParallel = abs(A) <= min_rcp_input;
-
- vfloat<M> t_cone_lower = select (isParallel, neg_inf, (-B-Q)*rcp_A);
- vfloat<M> t_cone_upper = select (isParallel, pos_inf, (-B+Q)*rcp_A);
- const vfloat<M> y_lower = dP0 + t_cone_lower*dOdP;
- const vfloat<M> y_upper = dP0 + t_cone_upper*dOdP;
- t_cone_lower = select(valid & y_lower > 0.0f & y_lower < dPdP, t_cone_lower, pos_inf);
- t_cone_upper = select(valid & y_upper > 0.0f & y_upper < dPdP, t_cone_upper, neg_inf);
-
- const vbool<M> hitDisk0 = valid & cL;
- const vbool<M> hitDisk1 = valid & cR;
- const vfloat<M> rcp_dOdP = rcp(dOdP);
- const vfloat<M> t_disk0 = select (hitDisk0, select (sqr(p0*dOdP-ray_dir*dP0)<(sqr(v0.w)*sqr(dOdP)), -dP0*rcp_dOdP, pos_inf), pos_inf);
- const vfloat<M> t_disk1 = select (hitDisk1, select (sqr(p1*dOdP-ray_dir*dP1)<(sqr(v1.w)*sqr(dOdP)), -dP1*rcp_dOdP, pos_inf), pos_inf);
- const vfloat<M> t_disk_lower = min(t_disk0, t_disk1);
- const vfloat<M> t_disk_upper = max(t_disk0, t_disk1);
-
- const vfloat<M> t_lower = min(t_cone_lower, t_disk_lower);
- const vfloat<M> t_upper = max(t_cone_upper, select(t_lower==t_disk_lower,
- select(t_disk_upper==vfloat<M>(pos_inf),neg_inf,t_disk_upper),
- select(t_disk_lower==vfloat<M>(pos_inf),neg_inf,t_disk_lower)));
-
- const vbool<M> valid_lower = valid & ray_tnear <= dt+t_lower & dt+t_lower <= ray_tfar() & t_lower != vfloat<M>(pos_inf);
- const vbool<M> valid_upper = valid & ray_tnear <= dt+t_upper & dt+t_upper <= ray_tfar() & t_upper != vfloat<M>(neg_inf);
-
- const vbool<M> valid_first = valid_lower | valid_upper;
- if (unlikely(none(valid_first)))
- return false;
-
- const vfloat<M> t_first = select(valid_lower, t_lower, t_upper);
- const vfloat<M> y_first = select(valid_lower, y_lower, y_upper);
-
- const vfloat<M> rcp_dPdP = rcp(dPdP);
- const Vec3vf<M> dP2drr0dP = dPdP*dr*v0.w*dP;
- const Vec3vf<M> dPhy = dP*hy;
- const vbool<M> cone_hit_first = valid & (t_first == t_cone_lower | t_first == t_cone_upper);
- const vbool<M> disk0_hit_first = valid & (t_first == t_disk0);
- const Vec3vf<M> Ng_first = select(cone_hit_first, dPdP2*(p0+t_first*ray_dir)+dP2drr0dP-dPhy*y_first, select(disk0_hit_first, -dP, dP));
- const vfloat<M> u_first = select(cone_hit_first, y_first*rcp_dPdP, select(disk0_hit_first, vfloat<M>(zero), vfloat<M>(one)));
-
- /* invoke intersection filter for first hit */
- RoundLineIntersectorHitM<M> hit(u_first,zero,dt+t_first,Ng_first);
- const bool is_hit_first = epilog(valid_first, hit);
-
- /* check for possible second hits before potentially accepted hit */
- const vfloat<M> t_second = t_upper;
- const vfloat<M> y_second = y_upper;
- const vbool<M> valid_second = valid_lower & valid_upper & (dt+t_upper <= ray_tfar());
- if (unlikely(none(valid_second)))
- return is_hit_first;
-
- /* invoke intersection filter for second hit */
- const vbool<M> cone_hit_second = t_second == t_cone_lower | t_second == t_cone_upper;
- const vbool<M> disk0_hit_second = t_second == t_disk0;
- const Vec3vf<M> Ng_second = select(cone_hit_second, dPdP2*(p0+t_second*ray_dir)+dP2drr0dP-dPhy*y_second, select(disk0_hit_second, -dP, dP));
- const vfloat<M> u_second = select(cone_hit_second, y_second*rcp_dPdP, select(disk0_hit_first, vfloat<M>(zero), vfloat<M>(one)));
-
- hit = RoundLineIntersectorHitM<M>(u_second,zero,dt+t_second,Ng_second);
- const bool is_hit_second = epilog(valid_second, hit);
-
- return is_hit_first | is_hit_second;
- }
- }
-
- template<int M>
- struct ConeLineIntersectorHitM
- {
- __forceinline ConeLineIntersectorHitM() {}
-
- __forceinline ConeLineIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
- : vu(u), vv(v), vt(t), vNg(Ng) {}
-
- __forceinline void finalize() {}
-
- __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
- __forceinline float t (const size_t i) const { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- public:
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- template<int M>
- struct ConeCurveIntersector1
- {
- typedef CurvePrecalculations1 Precalculations;
-
- struct ray_tfar {
- Ray& ray;
- __forceinline ray_tfar(Ray& ray) : ray(ray) {}
- __forceinline vfloat<M> operator() () const { return ray.tfar; };
- };
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- Ray& ray,
- IntersectContext* context,
- const LineSegments* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
- const vbool<M>& cL, const vbool<M>& cR,
- const Epilog& epilog)
- {
- const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
- const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
- const vfloat<M> ray_tnear(ray.tnear());
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec4vf<M> v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i);
- return __coneline_internal::intersectCone(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray),v0,v1,cL,cR,epilog);
- }
- };
-
- template<int M, int K>
- struct ConeCurveIntersectorK
- {
- typedef CurvePrecalculationsK<K> Precalculations;
-
- struct ray_tfar {
- RayK<K>& ray;
- size_t k;
- __forceinline ray_tfar(RayK<K>& ray, size_t k) : ray(ray), k(k) {}
- __forceinline vfloat<M> operator() () const { return ray.tfar[k]; };
- };
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- RayK<K>& ray, size_t k,
- IntersectContext* context,
- const LineSegments* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
- const vbool<M>& cL, const vbool<M>& cR,
- const Epilog& epilog)
- {
- const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
- const vfloat<M> ray_tnear = ray.tnear()[k];
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec4vf<M> v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i);
- return __coneline_internal::intersectCone(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray,k),v0,v1,cL,cR,epilog);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/conelinei_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/conelinei_intersector.h
deleted file mode 100644
index d47218eb8b..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/conelinei_intersector.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "coneline_intersector.h"
-#include "intersector_epilog.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M, int Mx, bool filter>
- struct ConeCurveMiIntersector1
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1;
- vbool<M> cL,cR;
- line.gather(v0,v1,cL,cR,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- ConeCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Intersect1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1;
- vbool<M> cL,cR;
- line.gather(v0,v1,cL,cR,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- return ConeCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Occluded1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- return false;
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
- }
- };
-
- template<int M, int Mx, bool filter>
- struct ConeCurveMiMBIntersector1
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1;
- vbool<M> cL,cR;
- line.gather(v0,v1,cL,cR,geom,ray.time());
- const vbool<Mx> valid = line.template valid<Mx>();
- ConeCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Intersect1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1;
- vbool<M> cL,cR;
- line.gather(v0,v1,cL,cR,geom,ray.time());
- const vbool<Mx> valid = line.template valid<Mx>();
- return ConeCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Occluded1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- return false;
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct ConeCurveMiIntersectorK
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1;
- vbool<M> cL,cR;
- line.gather(v0,v1,cL,cR,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- ConeCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1;
- vbool<M> cL,cR;
- line.gather(v0,v1,cL,cR,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- return ConeCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct ConeCurveMiMBIntersectorK
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1;
- vbool<M> cL,cR;
- line.gather(v0,v1,cL,cR,geom,ray.time()[k]);
- const vbool<Mx> valid = line.template valid<Mx>();
- ConeCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1;
- vbool<M> cL,cR;
- line.gather(v0,v1,cL,cR,geom,ray.time()[k]);
- const vbool<Mx> valid = line.template valid<Mx>();
- return ConeCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curveNi.h b/thirdparty/embree-aarch64/kernels/geometry/curveNi.h
deleted file mode 100644
index 51384f1959..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curveNi.h
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-#include "curve_intersector_precalculations.h"
-
-namespace embree
-{
- template<int M>
- struct CurveNi
- {
- struct Type : public PrimitiveType {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* Returns maximum number of stored primitives */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+M-1)/M; }
-
- static __forceinline size_t bytes(size_t N)
- {
- const size_t f = N/M, r = N%M;
- static_assert(sizeof(CurveNi) == 22+25*M, "internal data layout issue");
- return f*sizeof(CurveNi) + (r!=0)*(22 + 25*r);
- }
-
- public:
-
- /*! Default constructor. */
- __forceinline CurveNi () {}
-
- /*! fill curve from curve list */
- __forceinline void fill(const PrimRef* prims, size_t& begin, size_t _end, Scene* scene)
- {
- size_t end = min(begin+M,_end);
- N = (uint8_t)(end-begin);
- const unsigned int geomID0 = prims[begin].geomID();
- this->geomID(N) = geomID0;
- ty = (uint8_t) scene->get(geomID0)->getType();
-
- /* encode all primitives */
- BBox3fa bounds = empty;
- for (size_t i=0; i<N; i++)
- {
- const PrimRef& prim = prims[begin+i];
- const unsigned int geomID = prim.geomID(); assert(geomID == geomID0);
- const unsigned int primID = prim.primID();
- bounds.extend(scene->get(geomID)->vbounds(primID));
- }
-
- /* calculate offset and scale */
- Vec3fa loffset = bounds.lower;
- float lscale = reduce_min(256.0f/(bounds.size()*sqrt(3.0f)));
- if (bounds.size() == Vec3fa(zero)) lscale = 0.0f;
- *this->offset(N) = loffset;
- *this->scale(N) = lscale;
-
- /* encode all primitives */
- for (size_t i=0; i<M && begin<end; i++, begin++)
- {
- const PrimRef& prim = prims[begin];
- const unsigned int geomID = prim.geomID();
- const unsigned int primID = prim.primID();
- const LinearSpace3fa space2 = scene->get(geomID)->computeAlignedSpace(primID);
-
- const LinearSpace3fa space3(trunc(126.0f*space2.vx),trunc(126.0f*space2.vy),trunc(126.0f*space2.vz));
- const BBox3fa bounds = scene->get(geomID)->vbounds(loffset,lscale,max(length(space3.vx),length(space3.vy),length(space3.vz)),space3.transposed(),primID);
-
- bounds_vx_x(N)[i] = (int8_t) space3.vx.x;
- bounds_vx_y(N)[i] = (int8_t) space3.vx.y;
- bounds_vx_z(N)[i] = (int8_t) space3.vx.z;
- bounds_vx_lower(N)[i] = (short) clamp(floor(bounds.lower.x),-32767.0f,32767.0f);
- bounds_vx_upper(N)[i] = (short) clamp(ceil (bounds.upper.x),-32767.0f,32767.0f);
- assert(-32767.0f <= floor(bounds.lower.x) && floor(bounds.lower.x) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.upper.x) && ceil (bounds.upper.x) <= 32767.0f);
-
- bounds_vy_x(N)[i] = (int8_t) space3.vy.x;
- bounds_vy_y(N)[i] = (int8_t) space3.vy.y;
- bounds_vy_z(N)[i] = (int8_t) space3.vy.z;
- bounds_vy_lower(N)[i] = (short) clamp(floor(bounds.lower.y),-32767.0f,32767.0f);
- bounds_vy_upper(N)[i] = (short) clamp(ceil (bounds.upper.y),-32767.0f,32767.0f);
- assert(-32767.0f <= floor(bounds.lower.y) && floor(bounds.lower.y) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.upper.y) && ceil (bounds.upper.y) <= 32767.0f);
-
- bounds_vz_x(N)[i] = (int8_t) space3.vz.x;
- bounds_vz_y(N)[i] = (int8_t) space3.vz.y;
- bounds_vz_z(N)[i] = (int8_t) space3.vz.z;
- bounds_vz_lower(N)[i] = (short) clamp(floor(bounds.lower.z),-32767.0f,32767.0f);
- bounds_vz_upper(N)[i] = (short) clamp(ceil (bounds.upper.z),-32767.0f,32767.0f);
- assert(-32767.0f <= floor(bounds.lower.z) && floor(bounds.lower.z) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.upper.z) && ceil (bounds.upper.z) <= 32767.0f);
-
- this->primID(N)[i] = primID;
- }
- }
-
- template<typename BVH, typename Allocator>
- __forceinline static typename BVH::NodeRef createLeaf (BVH* bvh, const PrimRef* prims, const range<size_t>& set, const Allocator& alloc)
- {
- size_t start = set.begin();
- size_t items = CurveNi::blocks(set.size());
- size_t numbytes = CurveNi::bytes(set.size());
- CurveNi* accel = (CurveNi*) alloc.malloc1(numbytes,BVH::byteAlignment);
- for (size_t i=0; i<items; i++) {
- accel[i].fill(prims,start,set.end(),bvh->scene);
- }
- return bvh->encodeLeaf((int8_t*)accel,items);
- };
-
- public:
-
- // 27.6 - 46 bytes per primitive
- uint8_t ty;
- uint8_t N;
- uint8_t data[4+25*M+16];
-
- /*
- struct Layout
- {
- unsigned int geomID;
- unsigned int primID[N];
-
- int8_t bounds_vx_x[N];
- int8_t bounds_vx_y[N];
- int8_t bounds_vx_z[N];
- short bounds_vx_lower[N];
- short bounds_vx_upper[N];
-
- int8_t bounds_vy_x[N];
- int8_t bounds_vy_y[N];
- int8_t bounds_vy_z[N];
- short bounds_vy_lower[N];
- short bounds_vy_upper[N];
-
- int8_t bounds_vz_x[N];
- int8_t bounds_vz_y[N];
- int8_t bounds_vz_z[N];
- short bounds_vz_lower[N];
- short bounds_vz_upper[N];
-
- Vec3f offset;
- float scale;
- };
- */
-
- __forceinline unsigned int& geomID(size_t N) { return *(unsigned int*)((int8_t*)this+2); }
- __forceinline const unsigned int& geomID(size_t N) const { return *(unsigned int*)((int8_t*)this+2); }
-
- __forceinline unsigned int* primID(size_t N) { return (unsigned int*)((int8_t*)this+6); }
- __forceinline const unsigned int* primID(size_t N) const { return (unsigned int*)((int8_t*)this+6); }
-
- __forceinline int8_t* bounds_vx_x(size_t N) { return (int8_t*)((int8_t*)this+6+4*N); }
- __forceinline const int8_t* bounds_vx_x(size_t N) const { return (int8_t*)((int8_t*)this+6+4*N); }
-
- __forceinline int8_t* bounds_vx_y(size_t N) { return (int8_t*)((int8_t*)this+6+5*N); }
- __forceinline const int8_t* bounds_vx_y(size_t N) const { return (int8_t*)((int8_t*)this+6+5*N); }
-
- __forceinline int8_t* bounds_vx_z(size_t N) { return (int8_t*)((int8_t*)this+6+6*N); }
- __forceinline const int8_t* bounds_vx_z(size_t N) const { return (int8_t*)((int8_t*)this+6+6*N); }
-
- __forceinline short* bounds_vx_lower(size_t N) { return (short*)((int8_t*)this+6+7*N); }
- __forceinline const short* bounds_vx_lower(size_t N) const { return (short*)((int8_t*)this+6+7*N); }
-
- __forceinline short* bounds_vx_upper(size_t N) { return (short*)((int8_t*)this+6+9*N); }
- __forceinline const short* bounds_vx_upper(size_t N) const { return (short*)((int8_t*)this+6+9*N); }
-
- __forceinline int8_t* bounds_vy_x(size_t N) { return (int8_t*)((int8_t*)this+6+11*N); }
- __forceinline const int8_t* bounds_vy_x(size_t N) const { return (int8_t*)((int8_t*)this+6+11*N); }
-
- __forceinline int8_t* bounds_vy_y(size_t N) { return (int8_t*)((int8_t*)this+6+12*N); }
- __forceinline const int8_t* bounds_vy_y(size_t N) const { return (int8_t*)((int8_t*)this+6+12*N); }
-
- __forceinline int8_t* bounds_vy_z(size_t N) { return (int8_t*)((int8_t*)this+6+13*N); }
- __forceinline const int8_t* bounds_vy_z(size_t N) const { return (int8_t*)((int8_t*)this+6+13*N); }
-
- __forceinline short* bounds_vy_lower(size_t N) { return (short*)((int8_t*)this+6+14*N); }
- __forceinline const short* bounds_vy_lower(size_t N) const { return (short*)((int8_t*)this+6+14*N); }
-
- __forceinline short* bounds_vy_upper(size_t N) { return (short*)((int8_t*)this+6+16*N); }
- __forceinline const short* bounds_vy_upper(size_t N) const { return (short*)((int8_t*)this+6+16*N); }
-
- __forceinline int8_t* bounds_vz_x(size_t N) { return (int8_t*)((int8_t*)this+6+18*N); }
- __forceinline const int8_t* bounds_vz_x(size_t N) const { return (int8_t*)((int8_t*)this+6+18*N); }
-
- __forceinline int8_t* bounds_vz_y(size_t N) { return (int8_t*)((int8_t*)this+6+19*N); }
- __forceinline const int8_t* bounds_vz_y(size_t N) const { return (int8_t*)((int8_t*)this+6+19*N); }
-
- __forceinline int8_t* bounds_vz_z(size_t N) { return (int8_t*)((int8_t*)this+6+20*N); }
- __forceinline const int8_t* bounds_vz_z(size_t N) const { return (int8_t*)((int8_t*)this+6+20*N); }
-
- __forceinline short* bounds_vz_lower(size_t N) { return (short*)((int8_t*)this+6+21*N); }
- __forceinline const short* bounds_vz_lower(size_t N) const { return (short*)((int8_t*)this+6+21*N); }
-
- __forceinline short* bounds_vz_upper(size_t N) { return (short*)((int8_t*)this+6+23*N); }
- __forceinline const short* bounds_vz_upper(size_t N) const { return (short*)((int8_t*)this+6+23*N); }
-
- __forceinline Vec3f* offset(size_t N) { return (Vec3f*)((int8_t*)this+6+25*N); }
- __forceinline const Vec3f* offset(size_t N) const { return (Vec3f*)((int8_t*)this+6+25*N); }
-
- __forceinline float* scale(size_t N) { return (float*)((int8_t*)this+6+25*N+12); }
- __forceinline const float* scale(size_t N) const { return (float*)((int8_t*)this+6+25*N+12); }
-
- __forceinline int8_t* end(size_t N) { return (int8_t*)this+6+25*N+16; }
- __forceinline const int8_t* end(size_t N) const { return (int8_t*)this+6+25*N+16; }
- };
-
- template<int M>
- typename CurveNi<M>::Type CurveNi<M>::type;
-
- typedef CurveNi<4> Curve4i;
- typedef CurveNi<8> Curve8i;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curveNi_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/curveNi_intersector.h
deleted file mode 100644
index 0f9038c9fc..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curveNi_intersector.h
+++ /dev/null
@@ -1,569 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curveNi.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct CurveNiIntersector1
- {
- typedef CurveNi<M> Primitive;
- typedef Vec3vf<M> Vec3vfM;
- typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline vbool<M> intersect(Ray& ray, const Primitive& prim, vfloat<M>& tNear_o)
- {
- const size_t N = prim.N;
- const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));
- const Vec3fa offset = Vec3fa(offset_scale);
- const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));
- const Vec3fa org1 = (ray.org-offset)*scale;
- const Vec3fa dir1 = ray.dir*scale;
-
- const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),
- vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),
- vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));
-
- const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));
- const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));
- const Vec3vfM rcp_dir2 = rcp_safe(dir2);
-
- const vfloat<M> t_lower_x = (vfloat<M>::load(prim.bounds_vx_lower(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
- const vfloat<M> t_upper_x = (vfloat<M>::load(prim.bounds_vx_upper(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
- const vfloat<M> t_lower_y = (vfloat<M>::load(prim.bounds_vy_lower(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
- const vfloat<M> t_upper_y = (vfloat<M>::load(prim.bounds_vy_upper(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
- const vfloat<M> t_lower_z = (vfloat<M>::load(prim.bounds_vz_lower(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
- const vfloat<M> t_upper_z = (vfloat<M>::load(prim.bounds_vz_upper(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
-
- const vfloat<M> round_up (1.0f+3.0f*float(ulp));
- const vfloat<M> round_down(1.0f-3.0f*float(ulp));
- const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()));
- const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar));
- tNear_o = tNear;
- return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- const unsigned int primID1 = prim.primID(N)[i1];
- geom->prefetchL1_vertices(geom->curve(primID1));
- if (mask1) {
- const size_t i2 = bsf(mask1);
- const unsigned int primID2 = prim.primID(N)[i2];
- geom->prefetchL2_vertices(geom->curve(primID2));
- }
- }
-
- Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- const unsigned int primID1 = prim.primID(N)[i1];
- geom->prefetchL1_vertices(geom->curve(primID1));
- if (mask1) {
- const size_t i2 = bsf(mask1);
- const unsigned int primID2 = prim.primID(N)[i2];
- geom->prefetchL2_vertices(geom->curve(primID2));
- }
- }
-
- if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_n(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
-
- unsigned int vertexID = geom->curve(primID);
- Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- const unsigned int primID1 = prim.primID(N)[i1];
- geom->prefetchL1_vertices(geom->curve(primID1));
- if (mask1) {
- const size_t i2 = bsf(mask1);
- const unsigned int primID2 = prim.primID(N)[i2];
- geom->prefetchL2_vertices(geom->curve(primID2));
- }
- }
-
- Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_n(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
-
- unsigned int vertexID = geom->curve(primID);
- Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- const unsigned int primID1 = prim.primID(N)[i1];
- geom->prefetchL1_vertices(geom->curve(primID1));
- if (mask1) {
- const size_t i2 = bsf(mask1);
- const unsigned int primID2 = prim.primID(N)[i2];
- geom->prefetchL2_vertices(geom->curve(primID2));
- }
- }
-
- if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_h(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));
- Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_h(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));
- if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_hn(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));
- Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_hn(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));
- if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
- };
-
- template<int M, int K>
- struct CurveNiIntersectorK
- {
- typedef CurveNi<M> Primitive;
- typedef Vec3vf<M> Vec3vfM;
- typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline vbool<M> intersect(RayK<K>& ray, const size_t k, const Primitive& prim, vfloat<M>& tNear_o)
- {
- const size_t N = prim.N;
- const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));
- const Vec3fa offset = Vec3fa(offset_scale);
- const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));
-
- const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
- const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
- const Vec3fa org1 = (ray_org-offset)*scale;
- const Vec3fa dir1 = ray_dir*scale;
-
- const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),
- vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),
- vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));
-
- const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));
- const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));
- const Vec3vfM rcp_dir2 = rcp_safe(dir2);
-
- const vfloat<M> t_lower_x = (vfloat<M>::load(prim.bounds_vx_lower(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
- const vfloat<M> t_upper_x = (vfloat<M>::load(prim.bounds_vx_upper(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
- const vfloat<M> t_lower_y = (vfloat<M>::load(prim.bounds_vy_lower(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
- const vfloat<M> t_upper_y = (vfloat<M>::load(prim.bounds_vy_upper(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
- const vfloat<M> t_lower_z = (vfloat<M>::load(prim.bounds_vz_lower(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
- const vfloat<M> t_upper_z = (vfloat<M>::load(prim.bounds_vz_upper(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
-
- const vfloat<M> round_up (1.0f+3.0f*float(ulp));
- const vfloat<M> round_down(1.0f-3.0f*float(ulp));
- const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()[k]));
- const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar[k]));
- tNear_o = tNear;
- return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- const unsigned int primID1 = prim.primID(N)[i1];
- geom->prefetchL1_vertices(geom->curve(primID1));
- if (mask1) {
- const size_t i2 = bsf(mask1);
- const unsigned int primID2 = prim.primID(N)[i2];
- geom->prefetchL2_vertices(geom->curve(primID2));
- }
- }
-
- Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- const unsigned int primID1 = prim.primID(N)[i1];
- geom->prefetchL1_vertices(geom->curve(primID1));
- if (mask1) {
- const size_t i2 = bsf(mask1);
- const unsigned int primID2 = prim.primID(N)[i2];
- geom->prefetchL2_vertices(geom->curve(primID2));
- }
- }
-
- if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_n(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
-
- unsigned int vertexID = geom->curve(primID);
- Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- const unsigned int primID1 = prim.primID(N)[i1];
- geom->prefetchL1_vertices(geom->curve(primID1));
- if (mask1) {
- const size_t i2 = bsf(mask1);
- const unsigned int primID2 = prim.primID(N)[i2];
- geom->prefetchL2_vertices(geom->curve(primID2));
- }
- }
-
- Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_n(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
-
- unsigned int vertexID = geom->curve(primID);
- Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- const unsigned int primID1 = prim.primID(N)[i1];
- geom->prefetchL1_vertices(geom->curve(primID1));
- if (mask1) {
- const size_t i2 = bsf(mask1);
- const unsigned int primID2 = prim.primID(N)[i2];
- geom->prefetchL2_vertices(geom->curve(primID2));
- }
- }
-
- if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_h(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));
- Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_h(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));
- if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_hn(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));
- Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_hn(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));
- if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curveNi_mb.h b/thirdparty/embree-aarch64/kernels/geometry/curveNi_mb.h
deleted file mode 100644
index 0cd8f833fd..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curveNi_mb.h
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-#include "curve_intersector_precalculations.h"
-
-namespace embree
-{
- template<int M>
- struct CurveNiMB
- {
- struct Type : public PrimitiveType {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* Returns maximum number of stored primitives */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+M-1)/M; }
-
- static __forceinline size_t bytes(size_t N)
- {
- const size_t f = N/M, r = N%M;
- static_assert(sizeof(CurveNiMB) == 6+37*M+24, "internal data layout issue");
- return f*sizeof(CurveNiMB) + (r!=0)*(6+37*r+24);
- }
-
- public:
-
- /*! Default constructor. */
- __forceinline CurveNiMB () {}
-
- /*! fill curve from curve list */
- __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t _end, Scene* scene, const BBox1f time_range)
- {
- size_t end = min(begin+M,_end);
- N = (uint8_t)(end-begin);
- const unsigned int geomID0 = prims[begin].geomID();
- this->geomID(N) = geomID0;
- ty = (uint8_t) scene->get(geomID0)->getType();
-
- /* encode all primitives */
- LBBox3fa lbounds = empty;
- for (size_t i=0; i<N; i++)
- {
- const PrimRefMB& prim = prims[begin+i];
- const unsigned int geomID = prim.geomID(); assert(geomID == geomID0);
- const unsigned int primID = prim.primID();
- lbounds.extend(scene->get(geomID)->vlinearBounds(primID,time_range));
- }
- BBox3fa bounds = lbounds.bounds();
-
- /* calculate offset and scale */
- Vec3fa loffset = bounds.lower;
- float lscale = reduce_min(256.0f/(bounds.size()*sqrt(3.0f)));
- if (bounds.size() == Vec3fa(zero)) lscale = 0.0f;
- *this->offset(N) = loffset;
- *this->scale(N) = lscale;
- this->time_offset(N) = time_range.lower;
- this->time_scale(N) = 1.0f/time_range.size();
-
- /* encode all primitives */
- for (size_t i=0; i<M && begin<end; i++, begin++)
- {
- const PrimRefMB& prim = prims[begin];
- const unsigned int geomID = prim.geomID();
- const unsigned int primID = prim.primID();
- const LinearSpace3fa space2 = scene->get(geomID)->computeAlignedSpaceMB(primID,time_range);
-
- const LinearSpace3fa space3(trunc(126.0f*space2.vx),trunc(126.0f*space2.vy),trunc(126.0f*space2.vz));
- const LBBox3fa bounds = scene->get(geomID)->vlinearBounds(loffset,lscale,max(length(space3.vx),length(space3.vy),length(space3.vz)),space3.transposed(),primID,time_range);
-
- // NOTE: this weird (int8_t) (short) cast works around VS2015 Win32 compiler bug
- bounds_vx_x(N)[i] = (int8_t) (short) space3.vx.x;
- bounds_vx_y(N)[i] = (int8_t) (short) space3.vx.y;
- bounds_vx_z(N)[i] = (int8_t) (short) space3.vx.z;
- bounds_vx_lower0(N)[i] = (short) clamp(floor(bounds.bounds0.lower.x),-32767.0f,32767.0f);
- bounds_vx_upper0(N)[i] = (short) clamp(ceil (bounds.bounds0.upper.x),-32767.0f,32767.0f);
- bounds_vx_lower1(N)[i] = (short) clamp(floor(bounds.bounds1.lower.x),-32767.0f,32767.0f);
- bounds_vx_upper1(N)[i] = (short) clamp(ceil (bounds.bounds1.upper.x),-32767.0f,32767.0f);
- assert(-32767.0f <= floor(bounds.bounds0.lower.x) && floor(bounds.bounds0.lower.x) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.bounds0.upper.x) && ceil (bounds.bounds0.upper.x) <= 32767.0f);
- assert(-32767.0f <= floor(bounds.bounds1.lower.x) && floor(bounds.bounds1.lower.x) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.bounds1.upper.x) && ceil (bounds.bounds1.upper.x) <= 32767.0f);
-
- bounds_vy_x(N)[i] = (int8_t) (short) space3.vy.x;
- bounds_vy_y(N)[i] = (int8_t) (short) space3.vy.y;
- bounds_vy_z(N)[i] = (int8_t) (short) space3.vy.z;
- bounds_vy_lower0(N)[i] = (short) clamp(floor(bounds.bounds0.lower.y),-32767.0f,32767.0f);
- bounds_vy_upper0(N)[i] = (short) clamp(ceil (bounds.bounds0.upper.y),-32767.0f,32767.0f);
- bounds_vy_lower1(N)[i] = (short) clamp(floor(bounds.bounds1.lower.y),-32767.0f,32767.0f);
- bounds_vy_upper1(N)[i] = (short) clamp(ceil (bounds.bounds1.upper.y),-32767.0f,32767.0f);
- assert(-32767.0f <= floor(bounds.bounds0.lower.y) && floor(bounds.bounds0.lower.y) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.bounds0.upper.y) && ceil (bounds.bounds0.upper.y) <= 32767.0f);
- assert(-32767.0f <= floor(bounds.bounds1.lower.y) && floor(bounds.bounds1.lower.y) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.bounds1.upper.y) && ceil (bounds.bounds1.upper.y) <= 32767.0f);
-
- bounds_vz_x(N)[i] = (int8_t) (short) space3.vz.x;
- bounds_vz_y(N)[i] = (int8_t) (short) space3.vz.y;
- bounds_vz_z(N)[i] = (int8_t) (short) space3.vz.z;
- bounds_vz_lower0(N)[i] = (short) clamp(floor(bounds.bounds0.lower.z),-32767.0f,32767.0f);
- bounds_vz_upper0(N)[i] = (short) clamp(ceil (bounds.bounds0.upper.z),-32767.0f,32767.0f);
- bounds_vz_lower1(N)[i] = (short) clamp(floor(bounds.bounds1.lower.z),-32767.0f,32767.0f);
- bounds_vz_upper1(N)[i] = (short) clamp(ceil (bounds.bounds1.upper.z),-32767.0f,32767.0f);
- assert(-32767.0f <= floor(bounds.bounds0.lower.z) && floor(bounds.bounds0.lower.z) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.bounds0.upper.z) && ceil (bounds.bounds0.upper.z) <= 32767.0f);
- assert(-32767.0f <= floor(bounds.bounds1.lower.z) && floor(bounds.bounds1.lower.z) <= 32767.0f);
- assert(-32767.0f <= ceil (bounds.bounds1.upper.z) && ceil (bounds.bounds1.upper.z) <= 32767.0f);
-
- this->primID(N)[i] = primID;
- }
-
- return lbounds;
- }
-
- template<typename BVH, typename SetMB, typename Allocator>
- __forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc)
- {
- size_t start = prims.begin();
- size_t end = prims.end();
- size_t items = CurveNiMB::blocks(prims.size());
- size_t numbytes = CurveNiMB::bytes(prims.size());
- CurveNiMB* accel = (CurveNiMB*) alloc.malloc1(numbytes,BVH::byteAlignment);
- const typename BVH::NodeRef node = bvh->encodeLeaf((int8_t*)accel,items);
-
- LBBox3fa bounds = empty;
- for (size_t i=0; i<items; i++)
- bounds.extend(accel[i].fillMB(prims.prims->data(),start,end,bvh->scene,prims.time_range));
-
- return typename BVH::NodeRecordMB4D(node,bounds,prims.time_range);
- };
-
-
- public:
-
- // 27.6 - 46 bytes per primitive
- uint8_t ty;
- uint8_t N;
- uint8_t data[4+37*M+24];
-
- /*
- struct Layout
- {
- unsigned int geomID;
- unsigned int primID[N];
-
- int8_t bounds_vx_x[N];
- int8_t bounds_vx_y[N];
- int8_t bounds_vx_z[N];
- short bounds_vx_lower0[N];
- short bounds_vx_upper0[N];
- short bounds_vx_lower1[N];
- short bounds_vx_upper1[N];
-
- int8_t bounds_vy_x[N];
- int8_t bounds_vy_y[N];
- int8_t bounds_vy_z[N];
- short bounds_vy_lower0[N];
- short bounds_vy_upper0[N];
- short bounds_vy_lower1[N];
- short bounds_vy_upper1[N];
-
- int8_t bounds_vz_x[N];
- int8_t bounds_vz_y[N];
- int8_t bounds_vz_z[N];
- short bounds_vz_lower0[N];
- short bounds_vz_upper0[N];
- short bounds_vz_lower1[N];
- short bounds_vz_upper1[N];
-
- Vec3f offset;
- float scale;
-
- float time_offset;
- float time_scale;
- };
- */
-
- __forceinline unsigned int& geomID(size_t N) { return *(unsigned int*)((int8_t*)this+2); }
- __forceinline const unsigned int& geomID(size_t N) const { return *(unsigned int*)((int8_t*)this+2); }
-
- __forceinline unsigned int* primID(size_t N) { return (unsigned int*)((int8_t*)this+6); }
- __forceinline const unsigned int* primID(size_t N) const { return (unsigned int*)((int8_t*)this+6); }
-
- __forceinline int8_t* bounds_vx_x(size_t N) { return (int8_t*)((int8_t*)this+6+4*N); }
- __forceinline const int8_t* bounds_vx_x(size_t N) const { return (int8_t*)((int8_t*)this+6+4*N); }
-
- __forceinline int8_t* bounds_vx_y(size_t N) { return (int8_t*)((int8_t*)this+6+5*N); }
- __forceinline const int8_t* bounds_vx_y(size_t N) const { return (int8_t*)((int8_t*)this+6+5*N); }
-
- __forceinline int8_t* bounds_vx_z(size_t N) { return (int8_t*)((int8_t*)this+6+6*N); }
- __forceinline const int8_t* bounds_vx_z(size_t N) const { return (int8_t*)((int8_t*)this+6+6*N); }
-
- __forceinline short* bounds_vx_lower0(size_t N) { return (short*)((int8_t*)this+6+7*N); }
- __forceinline const short* bounds_vx_lower0(size_t N) const { return (short*)((int8_t*)this+6+7*N); }
-
- __forceinline short* bounds_vx_upper0(size_t N) { return (short*)((int8_t*)this+6+9*N); }
- __forceinline const short* bounds_vx_upper0(size_t N) const { return (short*)((int8_t*)this+6+9*N); }
-
- __forceinline short* bounds_vx_lower1(size_t N) { return (short*)((int8_t*)this+6+11*N); }
- __forceinline const short* bounds_vx_lower1(size_t N) const { return (short*)((int8_t*)this+6+11*N); }
-
- __forceinline short* bounds_vx_upper1(size_t N) { return (short*)((int8_t*)this+6+13*N); }
- __forceinline const short* bounds_vx_upper1(size_t N) const { return (short*)((int8_t*)this+6+13*N); }
-
- __forceinline int8_t* bounds_vy_x(size_t N) { return (int8_t*)((int8_t*)this+6+15*N); }
- __forceinline const int8_t* bounds_vy_x(size_t N) const { return (int8_t*)((int8_t*)this+6+15*N); }
-
- __forceinline int8_t* bounds_vy_y(size_t N) { return (int8_t*)((int8_t*)this+6+16*N); }
- __forceinline const int8_t* bounds_vy_y(size_t N) const { return (int8_t*)((int8_t*)this+6+16*N); }
-
- __forceinline int8_t* bounds_vy_z(size_t N) { return (int8_t*)((int8_t*)this+6+17*N); }
- __forceinline const int8_t* bounds_vy_z(size_t N) const { return (int8_t*)((int8_t*)this+6+17*N); }
-
- __forceinline short* bounds_vy_lower0(size_t N) { return (short*)((int8_t*)this+6+18*N); }
- __forceinline const short* bounds_vy_lower0(size_t N) const { return (short*)((int8_t*)this+6+18*N); }
-
- __forceinline short* bounds_vy_upper0(size_t N) { return (short*)((int8_t*)this+6+20*N); }
- __forceinline const short* bounds_vy_upper0(size_t N) const { return (short*)((int8_t*)this+6+20*N); }
-
- __forceinline short* bounds_vy_lower1(size_t N) { return (short*)((int8_t*)this+6+22*N); }
- __forceinline const short* bounds_vy_lower1(size_t N) const { return (short*)((int8_t*)this+6+22*N); }
-
- __forceinline short* bounds_vy_upper1(size_t N) { return (short*)((int8_t*)this+6+24*N); }
- __forceinline const short* bounds_vy_upper1(size_t N) const { return (short*)((int8_t*)this+6+24*N); }
-
- __forceinline int8_t* bounds_vz_x(size_t N) { return (int8_t*)((int8_t*)this+6+26*N); }
- __forceinline const int8_t* bounds_vz_x(size_t N) const { return (int8_t*)((int8_t*)this+6+26*N); }
-
- __forceinline int8_t* bounds_vz_y(size_t N) { return (int8_t*)((int8_t*)this+6+27*N); }
- __forceinline const int8_t* bounds_vz_y(size_t N) const { return (int8_t*)((int8_t*)this+6+27*N); }
-
- __forceinline int8_t* bounds_vz_z(size_t N) { return (int8_t*)((int8_t*)this+6+28*N); }
- __forceinline const int8_t* bounds_vz_z(size_t N) const { return (int8_t*)((int8_t*)this+6+28*N); }
-
- __forceinline short* bounds_vz_lower0(size_t N) { return (short*)((int8_t*)this+6+29*N); }
- __forceinline const short* bounds_vz_lower0(size_t N) const { return (short*)((int8_t*)this+6+29*N); }
-
- __forceinline short* bounds_vz_upper0(size_t N) { return (short*)((int8_t*)this+6+31*N); }
- __forceinline const short* bounds_vz_upper0(size_t N) const { return (short*)((int8_t*)this+6+31*N); }
-
- __forceinline short* bounds_vz_lower1(size_t N) { return (short*)((int8_t*)this+6+33*N); }
- __forceinline const short* bounds_vz_lower1(size_t N) const { return (short*)((int8_t*)this+6+33*N); }
-
- __forceinline short* bounds_vz_upper1(size_t N) { return (short*)((int8_t*)this+6+35*N); }
- __forceinline const short* bounds_vz_upper1(size_t N) const { return (short*)((int8_t*)this+6+35*N); }
-
- __forceinline Vec3f* offset(size_t N) { return (Vec3f*)((int8_t*)this+6+37*N); }
- __forceinline const Vec3f* offset(size_t N) const { return (Vec3f*)((int8_t*)this+6+37*N); }
-
- __forceinline float* scale(size_t N) { return (float*)((int8_t*)this+6+37*N+12); }
- __forceinline const float* scale(size_t N) const { return (float*)((int8_t*)this+6+37*N+12); }
-
- __forceinline float& time_offset(size_t N) { return *(float*)((int8_t*)this+6+37*N+16); }
- __forceinline const float& time_offset(size_t N) const { return *(float*)((int8_t*)this+6+37*N+16); }
-
- __forceinline float& time_scale(size_t N) { return *(float*)((int8_t*)this+6+37*N+20); }
- __forceinline const float& time_scale(size_t N) const { return *(float*)((int8_t*)this+6+37*N+20); }
-
- __forceinline int8_t* end(size_t N) { return (int8_t*)this+6+37*N+24; }
- __forceinline const int8_t* end(size_t N) const { return (int8_t*)this+6+37*N+24; }
- };
-
- template<int M>
- typename CurveNiMB<M>::Type CurveNiMB<M>::type;
-
- typedef CurveNiMB<4> Curve4iMB;
- typedef CurveNiMB<8> Curve8iMB;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curveNi_mb_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/curveNi_mb_intersector.h
deleted file mode 100644
index 0cbc764668..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curveNi_mb_intersector.h
+++ /dev/null
@@ -1,516 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curveNi_mb.h"
-#include "../subdiv/linear_bezier_patch.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct CurveNiMBIntersector1
- {
- typedef CurveNiMB<M> Primitive;
- typedef Vec3vf<M> Vec3vfM;
- typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline vbool<M> intersect(Ray& ray, const Primitive& prim, vfloat<M>& tNear_o)
- {
- const size_t N = prim.N;
- const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));
- const Vec3fa offset = Vec3fa(offset_scale);
- const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));
- const Vec3fa org1 = (ray.org-offset)*scale;
- const Vec3fa dir1 = ray.dir*scale;
-
- const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),
- vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),
- vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));
-
- const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));
- const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));
- const Vec3vfM rcp_dir2 = rcp_safe(dir2);
-
- const vfloat<M> ltime = (ray.time()-prim.time_offset(N))*prim.time_scale(N);
- const vfloat<M> vx_lower0 = vfloat<M>::load(prim.bounds_vx_lower0(N));
- const vfloat<M> vx_lower1 = vfloat<M>::load(prim.bounds_vx_lower1(N));
- const vfloat<M> vx_lower = madd(ltime,vx_lower1-vx_lower0,vx_lower0);
- const vfloat<M> vx_upper0 = vfloat<M>::load(prim.bounds_vx_upper0(N));
- const vfloat<M> vx_upper1 = vfloat<M>::load(prim.bounds_vx_upper1(N));
- const vfloat<M> vx_upper = madd(ltime,vx_upper1-vx_upper0,vx_upper0);
-
- const vfloat<M> vy_lower0 = vfloat<M>::load(prim.bounds_vy_lower0(N));
- const vfloat<M> vy_lower1 = vfloat<M>::load(prim.bounds_vy_lower1(N));
- const vfloat<M> vy_lower = madd(ltime,vy_lower1-vy_lower0,vy_lower0);
- const vfloat<M> vy_upper0 = vfloat<M>::load(prim.bounds_vy_upper0(N));
- const vfloat<M> vy_upper1 = vfloat<M>::load(prim.bounds_vy_upper1(N));
- const vfloat<M> vy_upper = madd(ltime,vy_upper1-vy_upper0,vy_upper0);
-
- const vfloat<M> vz_lower0 = vfloat<M>::load(prim.bounds_vz_lower0(N));
- const vfloat<M> vz_lower1 = vfloat<M>::load(prim.bounds_vz_lower1(N));
- const vfloat<M> vz_lower = madd(ltime,vz_lower1-vz_lower0,vz_lower0);
- const vfloat<M> vz_upper0 = vfloat<M>::load(prim.bounds_vz_upper0(N));
- const vfloat<M> vz_upper1 = vfloat<M>::load(prim.bounds_vz_upper1(N));
- const vfloat<M> vz_upper = madd(ltime,vz_upper1-vz_upper0,vz_upper0);
-
- const vfloat<M> t_lower_x = (vx_lower-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
- const vfloat<M> t_upper_x = (vx_upper-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
- const vfloat<M> t_lower_y = (vy_lower-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
- const vfloat<M> t_upper_y = (vy_upper-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
- const vfloat<M> t_lower_z = (vz_lower-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
- const vfloat<M> t_upper_z = (vz_upper-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
-
- const vfloat<M> round_up (1.0f+3.0f*float(ulp));
- const vfloat<M> round_down(1.0f-3.0f*float(ulp));
- const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()));
- const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar));
- tNear_o = tNear;
- return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID),ray.time());
-
- Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID),ray.time());
-
- if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_n(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time());
- Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_n(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time());
-
- if (Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_h(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID),ray.time());
- Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_h(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID),ray.time());
- if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_hn(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time());
- Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_hn(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time());
- if (Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
- };
-
- template<int M, int K>
- struct CurveNiMBIntersectorK
- {
- typedef CurveNiMB<M> Primitive;
- typedef Vec3vf<M> Vec3vfM;
- typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline vbool<M> intersect(RayK<K>& ray, const size_t k, const Primitive& prim, vfloat<M>& tNear_o)
- {
- const size_t N = prim.N;
- const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));
- const Vec3fa offset = Vec3fa(offset_scale);
- const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));
-
- const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
- const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
- const Vec3fa org1 = (ray_org-offset)*scale;
- const Vec3fa dir1 = ray_dir*scale;
-
- const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),
- vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),
- vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));
-
- const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));
- const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));
- const Vec3vfM rcp_dir2 = rcp_safe(dir2);
-
- const vfloat<M> ltime = (ray.time()[k]-prim.time_offset(N))*prim.time_scale(N);
- const vfloat<M> vx_lower0 = vfloat<M>::load(prim.bounds_vx_lower0(N));
- const vfloat<M> vx_lower1 = vfloat<M>::load(prim.bounds_vx_lower1(N));
- const vfloat<M> vx_lower = madd(ltime,vx_lower1-vx_lower0,vx_lower0);
- const vfloat<M> vx_upper0 = vfloat<M>::load(prim.bounds_vx_upper0(N));
- const vfloat<M> vx_upper1 = vfloat<M>::load(prim.bounds_vx_upper1(N));
- const vfloat<M> vx_upper = madd(ltime,vx_upper1-vx_upper0,vx_upper0);
-
- const vfloat<M> vy_lower0 = vfloat<M>::load(prim.bounds_vy_lower0(N));
- const vfloat<M> vy_lower1 = vfloat<M>::load(prim.bounds_vy_lower1(N));
- const vfloat<M> vy_lower = madd(ltime,vy_lower1-vy_lower0,vy_lower0);
- const vfloat<M> vy_upper0 = vfloat<M>::load(prim.bounds_vy_upper0(N));
- const vfloat<M> vy_upper1 = vfloat<M>::load(prim.bounds_vy_upper1(N));
- const vfloat<M> vy_upper = madd(ltime,vy_upper1-vy_upper0,vy_upper0);
-
- const vfloat<M> vz_lower0 = vfloat<M>::load(prim.bounds_vz_lower0(N));
- const vfloat<M> vz_lower1 = vfloat<M>::load(prim.bounds_vz_lower1(N));
- const vfloat<M> vz_lower = madd(ltime,vz_lower1-vz_lower0,vz_lower0);
- const vfloat<M> vz_upper0 = vfloat<M>::load(prim.bounds_vz_upper0(N));
- const vfloat<M> vz_upper1 = vfloat<M>::load(prim.bounds_vz_upper1(N));
- const vfloat<M> vz_upper = madd(ltime,vz_upper1-vz_upper0,vz_upper0);
-
- const vfloat<M> t_lower_x = (vx_lower-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
- const vfloat<M> t_upper_x = (vx_upper-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
- const vfloat<M> t_lower_y = (vy_lower-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
- const vfloat<M> t_upper_y = (vy_upper-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
- const vfloat<M> t_lower_z = (vz_lower-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
- const vfloat<M> t_upper_z = (vz_upper-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
-
- const vfloat<M> round_up (1.0f+3.0f*float(ulp));
- const vfloat<M> round_down(1.0f-3.0f*float(ulp));
- const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()[k]));
- const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar[k]));
- tNear_o = tNear;
- return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
-
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID),ray.time()[k]);
-
- Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID),ray.time()[k]);
-
- if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_n(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
-
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]);
- Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_n(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]);
-
- if (Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_h(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
-
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID),ray.time()[k]);
- Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_h(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID),ray.time()[k]);
- if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_hn(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
-
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]);
- Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_hn(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
- const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]);
- if (Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curveNv.h b/thirdparty/embree-aarch64/kernels/geometry/curveNv.h
deleted file mode 100644
index 6eb5e30b39..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curveNv.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curveNi.h"
-
-namespace embree
-{
- template<int M>
- struct CurveNv : public CurveNi<M>
- {
- using CurveNi<M>::N;
-
- struct Type : public PrimitiveType {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* Returns maximum number of stored primitives */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+M-1)/M; }
-
- static __forceinline size_t bytes(size_t N)
- {
- const size_t f = N/M, r = N%M;
- static_assert(sizeof(CurveNv) == 22+25*M+4*16*M, "internal data layout issue");
- return f*sizeof(CurveNv) + (r!=0)*(22 + 25*r + 4*16*r);
- }
-
- public:
-
- /*! Default constructor. */
- __forceinline CurveNv () {}
-
- /*! fill curve from curve list */
- __forceinline void fill(const PrimRef* prims, size_t& begin, size_t _end, Scene* scene)
- {
- size_t end = min(begin+M,_end);
- size_t N = end-begin;
-
- /* encode all primitives */
- for (size_t i=0; i<N; i++)
- {
- const PrimRef& prim = prims[begin+i];
- const unsigned int geomID = prim.geomID();
- const unsigned int primID = prim.primID();
- CurveGeometry* mesh = (CurveGeometry*) scene->get(geomID);
- const unsigned vtxID = mesh->curve(primID);
- Vec3fa::storeu(&this->vertices(i,N)[0],mesh->vertex(vtxID+0));
- Vec3fa::storeu(&this->vertices(i,N)[1],mesh->vertex(vtxID+1));
- Vec3fa::storeu(&this->vertices(i,N)[2],mesh->vertex(vtxID+2));
- Vec3fa::storeu(&this->vertices(i,N)[3],mesh->vertex(vtxID+3));
- }
- }
-
- template<typename BVH, typename Allocator>
- __forceinline static typename BVH::NodeRef createLeaf (BVH* bvh, const PrimRef* prims, const range<size_t>& set, const Allocator& alloc)
- {
- if (set.size() == 0)
- return BVH::emptyNode;
-
- /* fall back to CurveNi for oriented curves */
- unsigned int geomID = prims[set.begin()].geomID();
- if (bvh->scene->get(geomID)->getCurveType() == Geometry::GTY_SUBTYPE_ORIENTED_CURVE) {
- return CurveNi<M>::createLeaf(bvh,prims,set,alloc);
- }
- if (bvh->scene->get(geomID)->getCurveBasis() == Geometry::GTY_BASIS_HERMITE) {
- return CurveNi<M>::createLeaf(bvh,prims,set,alloc);
- }
-
- size_t start = set.begin();
- size_t items = CurveNv::blocks(set.size());
- size_t numbytes = CurveNv::bytes(set.size());
- CurveNv* accel = (CurveNv*) alloc.malloc1(numbytes,BVH::byteAlignment);
- for (size_t i=0; i<items; i++) {
- accel[i].CurveNv<M>::fill(prims,start,set.end(),bvh->scene);
- accel[i].CurveNi<M>::fill(prims,start,set.end(),bvh->scene);
- }
- return bvh->encodeLeaf((char*)accel,items);
- };
-
- public:
- unsigned char data[4*16*M];
- __forceinline Vec3fa* vertices(size_t i, size_t N) { return (Vec3fa*)CurveNi<M>::end(N)+4*i; }
- __forceinline const Vec3fa* vertices(size_t i, size_t N) const { return (Vec3fa*)CurveNi<M>::end(N)+4*i; }
- };
-
- template<int M>
- typename CurveNv<M>::Type CurveNv<M>::type;
-
- typedef CurveNv<4> Curve4v;
- typedef CurveNv<8> Curve8v;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curveNv_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/curveNv_intersector.h
deleted file mode 100644
index e20da2882e..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curveNv_intersector.h
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curveNv.h"
-#include "curveNi_intersector.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct CurveNvIntersector1 : public CurveNiIntersector1<M>
- {
- typedef CurveNv<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = CurveNiIntersector1<M>::intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = (CurveGeometry*) context->scene->get(geomID);
- const Vec3ff a0 = Vec3ff::loadu(&prim.vertices(i,N)[0]);
- const Vec3ff a1 = Vec3ff::loadu(&prim.vertices(i,N)[1]);
- const Vec3ff a2 = Vec3ff::loadu(&prim.vertices(i,N)[2]);
- const Vec3ff a3 = Vec3ff::loadu(&prim.vertices(i,N)[3]);
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- prefetchL1(&prim.vertices(i1,N)[0]);
- prefetchL1(&prim.vertices(i1,N)[4]);
- if (mask1) {
- const size_t i2 = bsf(mask1);
- prefetchL2(&prim.vertices(i2,N)[0]);
- prefetchL2(&prim.vertices(i2,N)[4]);
- }
- }
-
- Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = CurveNiIntersector1<M>::intersect(ray,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = (CurveGeometry*) context->scene->get(geomID);
- const Vec3ff a0 = Vec3ff::loadu(&prim.vertices(i,N)[0]);
- const Vec3ff a1 = Vec3ff::loadu(&prim.vertices(i,N)[1]);
- const Vec3ff a2 = Vec3ff::loadu(&prim.vertices(i,N)[2]);
- const Vec3ff a3 = Vec3ff::loadu(&prim.vertices(i,N)[3]);
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- prefetchL1(&prim.vertices(i1,N)[0]);
- prefetchL1(&prim.vertices(i1,N)[4]);
- if (mask1) {
- const size_t i2 = bsf(mask1);
- prefetchL2(&prim.vertices(i2,N)[0]);
- prefetchL2(&prim.vertices(i2,N)[4]);
- }
- }
-
- if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar));
- }
- return false;
- }
- };
-
- template<int M, int K>
- struct CurveNvIntersectorK : public CurveNiIntersectorK<M,K>
- {
- typedef CurveNv<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- template<typename Intersector, typename Epilog>
- static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = CurveNiIntersectorK<M,K>::intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(normal.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = (CurveGeometry*) context->scene->get(geomID);
- const Vec3ff a0 = Vec3ff::loadu(&prim.vertices(i,N)[0]);
- const Vec3ff a1 = Vec3ff::loadu(&prim.vertices(i,N)[1]);
- const Vec3ff a2 = Vec3ff::loadu(&prim.vertices(i,N)[2]);
- const Vec3ff a3 = Vec3ff::loadu(&prim.vertices(i,N)[3]);
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- prefetchL1(&prim.vertices(i1,N)[0]);
- prefetchL1(&prim.vertices(i1,N)[4]);
- if (mask1) {
- const size_t i2 = bsf(mask1);
- prefetchL2(&prim.vertices(i2,N)[0]);
- prefetchL2(&prim.vertices(i2,N)[4]);
- }
- }
-
- Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID));
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- }
-
- template<typename Intersector, typename Epilog>
- static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
- {
- vfloat<M> tNear;
- vbool<M> valid = CurveNiIntersectorK<M,K>::intersect(ray,k,prim,tNear);
-
- const size_t N = prim.N;
- size_t mask = movemask(valid);
- while (mask)
- {
- const size_t i = bscf(mask);
- STAT3(shadow.trav_prims,1,1,1);
- const unsigned int geomID = prim.geomID(N);
- const unsigned int primID = prim.primID(N)[i];
- const CurveGeometry* geom = (CurveGeometry*) context->scene->get(geomID);
- const Vec3ff a0 = Vec3ff::loadu(&prim.vertices(i,N)[0]);
- const Vec3ff a1 = Vec3ff::loadu(&prim.vertices(i,N)[1]);
- const Vec3ff a2 = Vec3ff::loadu(&prim.vertices(i,N)[2]);
- const Vec3ff a3 = Vec3ff::loadu(&prim.vertices(i,N)[3]);
-
- size_t mask1 = mask;
- const size_t i1 = bscf(mask1);
- if (mask) {
- prefetchL1(&prim.vertices(i1,N)[0]);
- prefetchL1(&prim.vertices(i1,N)[4]);
- if (mask1) {
- const size_t i2 = bsf(mask1);
- prefetchL2(&prim.vertices(i2,N)[0]);
- prefetchL2(&prim.vertices(i2,N)[4]);
- }
- }
-
- if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)))
- return true;
-
- mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
- }
- return false;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector.h
deleted file mode 100644
index 204958f7cc..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-#include "../subdiv/bezier_curve.h"
-#include "../common/primref.h"
-#include "bezier_hair_intersector.h"
-#include "bezier_ribbon_intersector.h"
-#include "bezier_curve_intersector.h"
-#include "oriented_curve_intersector.h"
-#include "../bvh/node_intersector1.h"
-
-// FIXME: this file seems replicate of curve_intersector_virtual.h
-
-namespace embree
-{
- namespace isa
- {
- struct VirtualCurveIntersector1
- {
- typedef unsigned char Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
- leafIntersector.intersect<1>(&pre,&ray,context,prim);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
- return leafIntersector.occluded<1>(&pre,&ray,context,prim);
- }
- };
-
- template<int K>
- struct VirtualCurveIntersectorK
- {
- typedef unsigned char Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(const vbool<K>& valid_i, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
- size_t mask = movemask(valid_i);
- while (mask) leafIntersector.intersect<K>(&pre,&ray,bscf(mask),context,prim);
- }
-
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
- vbool<K> valid_o = false;
- size_t mask = movemask(valid_i);
- while (mask) {
- size_t k = bscf(mask);
- if (leafIntersector.occluded<K>(&pre,&ray,k,context,prim))
- set(valid_o, k);
- }
- return valid_o;
- }
-
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
- leafIntersector.intersect<K>(&pre,&ray,k,context,prim);
- }
-
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
- return leafIntersector.occluded<K>(&pre,&ray,k,context,prim);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_distance.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_distance.h
deleted file mode 100644
index 343cc8ff28..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_distance.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "curve_intersector_precalculations.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename NativeCurve3fa, int M>
- struct DistanceCurveHit
- {
- __forceinline DistanceCurveHit() {}
-
- __forceinline DistanceCurveHit(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const int i, const int N,
- const NativeCurve3fa& curve3D)
- : U(U), V(V), T(T), i(i), N(N), curve3D(curve3D), valid(valid) {}
-
- __forceinline void finalize()
- {
- vu = (vfloat<M>(step)+U+vfloat<M>(float(i)))*(1.0f/float(N));
- vv = V;
- vt = T;
- }
-
- __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
- __forceinline float t (const size_t i) const { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) const {
- return curve3D.eval_du(vu[i]);
- }
-
- public:
- vfloat<M> U;
- vfloat<M> V;
- vfloat<M> T;
- int i, N;
- NativeCurve3fa curve3D;
-
- public:
- vbool<M> valid;
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- };
-
- template<typename NativeCurve3fa>
- struct DistanceCurve1Intersector1
- {
- template<typename Epilog>
- __forceinline bool intersect(const CurvePrecalculations1& pre,Ray& ray,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2, const Vec3fa& v3,
- const Epilog& epilog)
- {
- const int N = geom->tessellationRate;
-
- /* transform control points into ray space */
- const NativeCurve3fa curve3Di(v0,v1,v2,v3);
- const NativeCurve3fa curve3D = enlargeRadiusToMinWidth(context,geom,ray.org,curve3Di);
- const NativeCurve3fa curve2D = curve3D.xfm_pr(pre.ray_space,ray.org);
-
- /* evaluate the bezier curve */
- vboolx valid = vfloatx(step) < vfloatx(float(N));
- const Vec4vfx p0 = curve2D.template eval0<VSIZEX>(0,N);
- const Vec4vfx p1 = curve2D.template eval1<VSIZEX>(0,N);
-
- /* approximative intersection with cone */
- const Vec4vfx v = p1-p0;
- const Vec4vfx w = -p0;
- const vfloatx d0 = madd(w.x,v.x,w.y*v.y);
- const vfloatx d1 = madd(v.x,v.x,v.y*v.y);
- const vfloatx u = clamp(d0*rcp(d1),vfloatx(zero),vfloatx(one));
- const Vec4vfx p = madd(u,v,p0);
- const vfloatx t = p.z*pre.depth_scale;
- const vfloatx d2 = madd(p.x,p.x,p.y*p.y);
- const vfloatx r = p.w;
- const vfloatx r2 = r*r;
- valid &= (d2 <= r2) & (vfloatx(ray.tnear()) <= t) & (t <= vfloatx(ray.tfar));
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
- valid &= t > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*pre.depth_scale; // ignore self intersections
-
- /* update hit information */
- bool ishit = false;
- if (unlikely(any(valid))) {
- DistanceCurveHit<NativeCurve3fa,VSIZEX> hit(valid,u,0.0f,t,0,N,curve3D);
- ishit = ishit | epilog(valid,hit);
- }
-
- if (unlikely(VSIZEX < N))
- {
- /* process SIMD-size many segments per iteration */
- for (int i=VSIZEX; i<N; i+=VSIZEX)
- {
- /* evaluate the bezier curve */
- vboolx valid = vintx(i)+vintx(step) < vintx(N);
- const Vec4vfx p0 = curve2D.template eval0<VSIZEX>(i,N);
- const Vec4vfx p1 = curve2D.template eval1<VSIZEX>(i,N);
-
- /* approximative intersection with cone */
- const Vec4vfx v = p1-p0;
- const Vec4vfx w = -p0;
- const vfloatx d0 = madd(w.x,v.x,w.y*v.y);
- const vfloatx d1 = madd(v.x,v.x,v.y*v.y);
- const vfloatx u = clamp(d0*rcp(d1),vfloatx(zero),vfloatx(one));
- const Vec4vfx p = madd(u,v,p0);
- const vfloatx t = p.z*pre.depth_scale;
- const vfloatx d2 = madd(p.x,p.x,p.y*p.y);
- const vfloatx r = p.w;
- const vfloatx r2 = r*r;
- valid &= (d2 <= r2) & (vfloatx(ray.tnear()) <= t) & (t <= vfloatx(ray.tfar));
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
- valid &= t > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*pre.depth_scale; // ignore self intersections
-
- /* update hit information */
- if (unlikely(any(valid))) {
- DistanceCurveHit<NativeCurve3fa,VSIZEX> hit(valid,u,0.0f,t,i,N,curve3D);
- ishit = ishit | epilog(valid,hit);
- }
- }
- }
- return ishit;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_oriented.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_oriented.h
deleted file mode 100644
index 47531027fc..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_oriented.h
+++ /dev/null
@@ -1,417 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "curve_intersector_precalculations.h"
-#include "curve_intersector_sweep.h"
-#include "../subdiv/linear_bezier_patch.h"
-
-#define DBG(x)
-
-namespace embree
-{
- namespace isa
- {
- template<typename Ray, typename Epilog>
- struct TensorLinearCubicBezierSurfaceIntersector
- {
- const LinearSpace3fa& ray_space;
- Ray& ray;
- TensorLinearCubicBezierSurface3fa curve3d;
- TensorLinearCubicBezierSurface2fa curve2d;
- float eps;
- const Epilog& epilog;
- bool isHit;
-
- __forceinline TensorLinearCubicBezierSurfaceIntersector (const LinearSpace3fa& ray_space, Ray& ray, const TensorLinearCubicBezierSurface3fa& curve3d, const Epilog& epilog)
- : ray_space(ray_space), ray(ray), curve3d(curve3d), epilog(epilog), isHit(false)
- {
- const TensorLinearCubicBezierSurface3fa curve3dray = curve3d.xfm(ray_space,ray.org);
- curve2d = TensorLinearCubicBezierSurface2fa(CubicBezierCurve2fa(curve3dray.L),CubicBezierCurve2fa(curve3dray.R));
- const BBox2fa b2 = curve2d.bounds();
- eps = 8.0f*float(ulp)*reduce_max(max(abs(b2.lower),abs(b2.upper)));
- }
-
- __forceinline Interval1f solve_linear(const float u0, const float u1, const float& p0, const float& p1)
- {
- if (p1 == p0) {
- if (p0 == 0.0f) return Interval1f(u0,u1);
- else return Interval1f(empty);
- }
- const float t = -p0/(p1-p0);
- const float tt = lerp(u0,u1,t);
- return Interval1f(tt);
- }
-
- __forceinline void solve_linear(const float u0, const float u1, const Interval1f& p0, const Interval1f& p1, Interval1f& u)
- {
- if (sign(p0.lower) != sign(p0.upper)) u.extend(u0);
- if (sign(p0.lower) != sign(p1.lower)) u.extend(solve_linear(u0,u1,p0.lower,p1.lower));
- if (sign(p0.upper) != sign(p1.upper)) u.extend(solve_linear(u0,u1,p0.upper,p1.upper));
- if (sign(p1.lower) != sign(p1.upper)) u.extend(u1);
- }
-
- __forceinline Interval1f bezier_clipping(const CubicBezierCurve<Interval1f>& curve)
- {
- Interval1f u = empty;
- solve_linear(0.0f/3.0f,1.0f/3.0f,curve.v0,curve.v1,u);
- solve_linear(0.0f/3.0f,2.0f/3.0f,curve.v0,curve.v2,u);
- solve_linear(0.0f/3.0f,3.0f/3.0f,curve.v0,curve.v3,u);
- solve_linear(1.0f/3.0f,2.0f/3.0f,curve.v1,curve.v2,u);
- solve_linear(1.0f/3.0f,3.0f/3.0f,curve.v1,curve.v3,u);
- solve_linear(2.0f/3.0f,3.0f/3.0f,curve.v2,curve.v3,u);
- return intersect(u,Interval1f(0.0f,1.0f));
- }
-
- __forceinline Interval1f bezier_clipping(const LinearBezierCurve<Interval1f>& curve)
- {
- Interval1f v = empty;
- solve_linear(0.0f,1.0f,curve.v0,curve.v1,v);
- return intersect(v,Interval1f(0.0f,1.0f));
- }
-
- __forceinline void solve_bezier_clipping(BBox1f cu, BBox1f cv, const TensorLinearCubicBezierSurface2fa& curve2)
- {
- BBox2fa bounds = curve2.bounds();
- if (bounds.upper.x < 0.0f) return;
- if (bounds.upper.y < 0.0f) return;
- if (bounds.lower.x > 0.0f) return;
- if (bounds.lower.y > 0.0f) return;
-
- if (max(cu.size(),cv.size()) < 1E-4f)
- {
- const float u = cu.center();
- const float v = cv.center();
- TensorLinearCubicBezierSurface1f curve_z = curve3d.xfm(ray_space.row2(),ray.org);
- const float t = curve_z.eval(u,v);
- if (ray.tnear() <= t && t <= ray.tfar) {
- const Vec3fa Ng = cross(curve3d.eval_du(u,v),curve3d.eval_dv(u,v));
- BezierCurveHit hit(t,u,v,Ng);
- isHit |= epilog(hit);
- }
- return;
- }
-
- const Vec2fa dv = curve2.axis_v();
- const TensorLinearCubicBezierSurface1f curve1v = curve2.xfm(dv);
- LinearBezierCurve<Interval1f> curve0v = curve1v.reduce_u();
- if (!curve0v.hasRoot()) return;
-
- const Interval1f v = bezier_clipping(curve0v);
- if (isEmpty(v)) return;
- TensorLinearCubicBezierSurface2fa curve2a = curve2.clip_v(v);
- cv = BBox1f(lerp(cv.lower,cv.upper,v.lower),lerp(cv.lower,cv.upper,v.upper));
-
- const Vec2fa du = curve2.axis_u();
- const TensorLinearCubicBezierSurface1f curve1u = curve2a.xfm(du);
- CubicBezierCurve<Interval1f> curve0u = curve1u.reduce_v();
- int roots = curve0u.maxRoots();
- if (roots == 0) return;
-
- if (roots == 1)
- {
- const Interval1f u = bezier_clipping(curve0u);
- if (isEmpty(u)) return;
- TensorLinearCubicBezierSurface2fa curve2b = curve2a.clip_u(u);
- cu = BBox1f(lerp(cu.lower,cu.upper,u.lower),lerp(cu.lower,cu.upper,u.upper));
- solve_bezier_clipping(cu,cv,curve2b);
- return;
- }
-
- TensorLinearCubicBezierSurface2fa curve2l, curve2r;
- curve2a.split_u(curve2l,curve2r);
- solve_bezier_clipping(BBox1f(cu.lower,cu.center()),cv,curve2l);
- solve_bezier_clipping(BBox1f(cu.center(),cu.upper),cv,curve2r);
- }
-
- __forceinline bool solve_bezier_clipping()
- {
- solve_bezier_clipping(BBox1f(0.0f,1.0f),BBox1f(0.0f,1.0f),curve2d);
- return isHit;
- }
-
- __forceinline void solve_newton_raphson(BBox1f cu, BBox1f cv)
- {
- Vec2fa uv(cu.center(),cv.center());
- const Vec2fa dfdu = curve2d.eval_du(uv.x,uv.y);
- const Vec2fa dfdv = curve2d.eval_dv(uv.x,uv.y);
- const LinearSpace2fa rcp_J = rcp(LinearSpace2fa(dfdu,dfdv));
- solve_newton_raphson_loop(cu,cv,uv,dfdu,dfdv,rcp_J);
- }
-
- __forceinline void solve_newton_raphson_loop(BBox1f cu, BBox1f cv, const Vec2fa& uv_in, const Vec2fa& dfdu, const Vec2fa& dfdv, const LinearSpace2fa& rcp_J)
- {
- Vec2fa uv = uv_in;
-
- for (size_t i=0; i<200; i++)
- {
- const Vec2fa f = curve2d.eval(uv.x,uv.y);
- const Vec2fa duv = rcp_J*f;
- uv -= duv;
-
- if (max(abs(f.x),abs(f.y)) < eps)
- {
- const float u = uv.x;
- const float v = uv.y;
- if (!(u >= 0.0f && u <= 1.0f)) return; // rejects NaNs
- if (!(v >= 0.0f && v <= 1.0f)) return; // rejects NaNs
- const TensorLinearCubicBezierSurface1f curve_z = curve3d.xfm(ray_space.row2(),ray.org);
- const float t = curve_z.eval(u,v);
- if (!(ray.tnear() <= t && t <= ray.tfar)) return; // rejects NaNs
- const Vec3fa Ng = cross(curve3d.eval_du(u,v),curve3d.eval_dv(u,v));
- BezierCurveHit hit(t,u,v,Ng);
- isHit |= epilog(hit);
- return;
- }
- }
- }
-
- __forceinline bool clip_v(BBox1f& cu, BBox1f& cv)
- {
- const Vec2fa dv = curve2d.eval_dv(cu.lower,cv.lower);
- const TensorLinearCubicBezierSurface1f curve1v = curve2d.xfm(dv).clip(cu,cv);
- LinearBezierCurve<Interval1f> curve0v = curve1v.reduce_u();
- if (!curve0v.hasRoot()) return false;
- Interval1f v = bezier_clipping(curve0v);
- if (isEmpty(v)) return false;
- v = intersect(v + Interval1f(-0.1f,+0.1f),Interval1f(0.0f,1.0f));
- cv = BBox1f(lerp(cv.lower,cv.upper,v.lower),lerp(cv.lower,cv.upper,v.upper));
- return true;
- }
-
- __forceinline bool solve_krawczyk(bool very_small, BBox1f& cu, BBox1f& cv)
- {
- /* perform bezier clipping in v-direction to get tight v-bounds */
- TensorLinearCubicBezierSurface2fa curve2 = curve2d.clip(cu,cv);
- const Vec2fa dv = curve2.axis_v();
- const TensorLinearCubicBezierSurface1f curve1v = curve2.xfm(dv);
- LinearBezierCurve<Interval1f> curve0v = curve1v.reduce_u();
- if (unlikely(!curve0v.hasRoot())) return true;
- Interval1f v = bezier_clipping(curve0v);
- if (unlikely(isEmpty(v))) return true;
- v = intersect(v + Interval1f(-0.1f,+0.1f),Interval1f(0.0f,1.0f));
- curve2 = curve2.clip_v(v);
- cv = BBox1f(lerp(cv.lower,cv.upper,v.lower),lerp(cv.lower,cv.upper,v.upper));
-
- /* perform one newton raphson iteration */
- Vec2fa c(cu.center(),cv.center());
- Vec2fa f,dfdu,dfdv; curve2d.eval(c.x,c.y,f,dfdu,dfdv);
- const LinearSpace2fa rcp_J = rcp(LinearSpace2fa(dfdu,dfdv));
- const Vec2fa c1 = c - rcp_J*f;
-
- /* calculate bounds of derivatives */
- const BBox2fa bounds_du = (1.0f/cu.size())*curve2.derivative_u().bounds();
- const BBox2fa bounds_dv = (1.0f/cv.size())*curve2.derivative_v().bounds();
-
- /* calculate krawczyk test */
- LinearSpace2<Vec2<Interval1f>> I(Interval1f(1.0f), Interval1f(0.0f),
- Interval1f(0.0f), Interval1f(1.0f));
-
- LinearSpace2<Vec2<Interval1f>> G(Interval1f(bounds_du.lower.x,bounds_du.upper.x), Interval1f(bounds_dv.lower.x,bounds_dv.upper.x),
- Interval1f(bounds_du.lower.y,bounds_du.upper.y), Interval1f(bounds_dv.lower.y,bounds_dv.upper.y));
-
- const LinearSpace2<Vec2f> rcp_J2(rcp_J);
- const LinearSpace2<Vec2<Interval1f>> rcp_Ji(rcp_J2);
-
- const Vec2<Interval1f> x(cu,cv);
- const Vec2<Interval1f> K = Vec2<Interval1f>(Vec2f(c1)) + (I - rcp_Ji*G)*(x-Vec2<Interval1f>(Vec2f(c)));
-
- /* test if there is no solution */
- const Vec2<Interval1f> KK = intersect(K,x);
- if (unlikely(isEmpty(KK.x) || isEmpty(KK.y))) return true;
-
- /* exit if convergence cannot get proven, but terminate if we are very small */
- if (unlikely(!subset(K,x) && !very_small)) return false;
-
- /* solve using newton raphson iteration of convergence is guarenteed */
- solve_newton_raphson_loop(cu,cv,c1,dfdu,dfdv,rcp_J);
- return true;
- }
-
- __forceinline void solve_newton_raphson_no_recursion(BBox1f cu, BBox1f cv)
- {
- if (!clip_v(cu,cv)) return;
- return solve_newton_raphson(cu,cv);
- }
-
- __forceinline void solve_newton_raphson_recursion(BBox1f cu, BBox1f cv)
- {
- unsigned int sptr = 0;
- const unsigned int stack_size = 4;
- unsigned int mask_stack[stack_size];
- BBox1f cu_stack[stack_size];
- BBox1f cv_stack[stack_size];
- goto entry;
-
- /* terminate if stack is empty */
- while (sptr)
- {
- /* pop from stack */
- {
- sptr--;
- size_t mask = mask_stack[sptr];
- cu = cu_stack[sptr];
- cv = cv_stack[sptr];
- const size_t i = bscf(mask);
- mask_stack[sptr] = mask;
- if (mask) sptr++; // there are still items on the stack
-
- /* process next element recurse into each hit curve segment */
- const float u0 = float(i+0)*(1.0f/(VSIZEX-1));
- const float u1 = float(i+1)*(1.0f/(VSIZEX-1));
- const BBox1f cui(lerp(cu.lower,cu.upper,u0),lerp(cu.lower,cu.upper,u1));
- cu = cui;
- }
-
-#if 0
- solve_newton_raphson_no_recursion(cu,cv);
- continue;
-
-#else
- /* we assume convergence for small u ranges and verify using krawczyk */
- if (cu.size() < 1.0f/6.0f) {
- const bool very_small = cu.size() < 0.001f || sptr >= stack_size;
- if (solve_krawczyk(very_small,cu,cv)) {
- continue;
- }
- }
-#endif
-
- entry:
-
- /* split the curve into VSIZEX-1 segments in u-direction */
- vboolx valid = true;
- TensorLinearCubicBezierSurface<Vec2vfx> subcurves = curve2d.clip_v(cv).vsplit_u(valid,cu);
-
- /* slabs test in u-direction */
- Vec2vfx ndv = cross(subcurves.axis_v());
- BBox<vfloatx> boundsv = subcurves.vxfm(ndv).bounds();
- valid &= boundsv.lower <= eps;
- valid &= boundsv.upper >= -eps;
- if (none(valid)) continue;
-
- /* slabs test in v-direction */
- Vec2vfx ndu = cross(subcurves.axis_u());
- BBox<vfloatx> boundsu = subcurves.vxfm(ndu).bounds();
- valid &= boundsu.lower <= eps;
- valid &= boundsu.upper >= -eps;
- if (none(valid)) continue;
-
- /* push valid segments to stack */
- assert(sptr < stack_size);
- mask_stack [sptr] = movemask(valid);
- cu_stack [sptr] = cu;
- cv_stack [sptr] = cv;
- sptr++;
- }
- }
-
- __forceinline bool solve_newton_raphson_main()
- {
- BBox1f vu(0.0f,1.0f);
- BBox1f vv(0.0f,1.0f);
- solve_newton_raphson_recursion(vu,vv);
- return isHit;
- }
- };
-
-
- template<template<typename Ty> class SourceCurve>
- struct OrientedCurve1Intersector1
- {
- //template<typename Ty> using Curve = SourceCurve<Ty>;
- typedef SourceCurve<Vec3ff> SourceCurve3ff;
- typedef SourceCurve<Vec3fa> SourceCurve3fa;
-
- __forceinline OrientedCurve1Intersector1() {}
-
- __forceinline OrientedCurve1Intersector1(const Ray& ray, const void* ptr) {}
-
- template<typename Epilog>
- __noinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const Vec3ff& v0i, const Vec3ff& v1i, const Vec3ff& v2i, const Vec3ff& v3i,
- const Vec3fa& n0i, const Vec3fa& n1i, const Vec3fa& n2i, const Vec3fa& n3i,
- const Epilog& epilog) const
- {
- STAT3(normal.trav_prims,1,1,1);
-
- SourceCurve3ff ccurve(v0i,v1i,v2i,v3i);
- SourceCurve3fa ncurve(n0i,n1i,n2i,n3i);
- ccurve = enlargeRadiusToMinWidth(context,geom,ray.org,ccurve);
- TensorLinearCubicBezierSurface3fa curve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
- //return TensorLinearCubicBezierSurfaceIntersector<Ray,Epilog>(pre.ray_space,ray,curve,epilog).solve_bezier_clipping();
- return TensorLinearCubicBezierSurfaceIntersector<Ray,Epilog>(pre.ray_space,ray,curve,epilog).solve_newton_raphson_main();
- }
-
- template<typename Epilog>
- __noinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const TensorLinearCubicBezierSurface3fa& curve, const Epilog& epilog) const
- {
- STAT3(normal.trav_prims,1,1,1);
- //return TensorLinearCubicBezierSurfaceIntersector<Ray,Epilog>(pre.ray_space,ray,curve,epilog).solve_bezier_clipping();
- return TensorLinearCubicBezierSurfaceIntersector<Ray,Epilog>(pre.ray_space,ray,curve,epilog).solve_newton_raphson_main();
- }
- };
-
- template<template<typename Ty> class SourceCurve, int K>
- struct OrientedCurve1IntersectorK
- {
- //template<typename Ty> using Curve = SourceCurve<Ty>;
- typedef SourceCurve<Vec3ff> SourceCurve3ff;
- typedef SourceCurve<Vec3fa> SourceCurve3fa;
-
- struct Ray1
- {
- __forceinline Ray1(RayK<K>& ray, size_t k)
- : org(ray.org.x[k],ray.org.y[k],ray.org.z[k]), dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]), _tnear(ray.tnear()[k]), tfar(ray.tfar[k]) {}
-
- Vec3fa org;
- Vec3fa dir;
- float _tnear;
- float& tfar;
-
- __forceinline float& tnear() { return _tnear; }
- //__forceinline float& tfar() { return _tfar; }
- __forceinline const float& tnear() const { return _tnear; }
- //__forceinline const float& tfar() const { return _tfar; }
- };
-
- template<typename Epilog>
- __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& vray, size_t k,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const Vec3ff& v0i, const Vec3ff& v1i, const Vec3ff& v2i, const Vec3ff& v3i,
- const Vec3fa& n0i, const Vec3fa& n1i, const Vec3fa& n2i, const Vec3fa& n3i,
- const Epilog& epilog)
- {
- STAT3(normal.trav_prims,1,1,1);
- Ray1 ray(vray,k);
- SourceCurve3ff ccurve(v0i,v1i,v2i,v3i);
- SourceCurve3fa ncurve(n0i,n1i,n2i,n3i);
- ccurve = enlargeRadiusToMinWidth(context,geom,ray.org,ccurve);
- TensorLinearCubicBezierSurface3fa curve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
- //return TensorLinearCubicBezierSurfaceIntersector<Ray1,Epilog>(pre.ray_space[k],ray,curve,epilog).solve_bezier_clipping();
- return TensorLinearCubicBezierSurfaceIntersector<Ray1,Epilog>(pre.ray_space[k],ray,curve,epilog).solve_newton_raphson_main();
- }
-
- template<typename Epilog>
- __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& vray, size_t k,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const TensorLinearCubicBezierSurface3fa& curve,
- const Epilog& epilog)
- {
- STAT3(normal.trav_prims,1,1,1);
- Ray1 ray(vray,k);
- //return TensorLinearCubicBezierSurfaceIntersector<Ray1,Epilog>(pre.ray_space[k],ray,curve,epilog).solve_bezier_clipping();
- return TensorLinearCubicBezierSurfaceIntersector<Ray1,Epilog>(pre.ray_space[k],ray,curve,epilog).solve_newton_raphson_main();
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_precalculations.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_precalculations.h
deleted file mode 100644
index 6e9fc91925..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_precalculations.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "../common/geometry.h"
-
-namespace embree
-{
- namespace isa
- {
- struct CurvePrecalculations1
- {
- float depth_scale;
- LinearSpace3fa ray_space;
-
- __forceinline CurvePrecalculations1() {}
-
- __forceinline CurvePrecalculations1(const Ray& ray, const void* ptr)
- {
- depth_scale = rsqrt(dot(ray.dir,ray.dir));
- LinearSpace3fa space = frame(depth_scale*ray.dir);
- space.vz *= depth_scale;
- ray_space = space.transposed();
- }
- };
-
- template<int K>
- struct CurvePrecalculationsK
- {
- vfloat<K> depth_scale;
- LinearSpace3fa ray_space[K];
-
- __forceinline CurvePrecalculationsK(const vbool<K>& valid, const RayK<K>& ray)
- {
- size_t mask = movemask(valid);
- depth_scale = rsqrt(dot(ray.dir,ray.dir));
- while (mask) {
- size_t k = bscf(mask);
- Vec3fa ray_dir_k = Vec3fa(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
- LinearSpace3fa ray_space_k = frame(depth_scale[k]*ray_dir_k);
- ray_space_k.vz *= depth_scale[k];
- ray_space[k] = ray_space_k.transposed();
- }
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_ribbon.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_ribbon.h
deleted file mode 100644
index a99cf99d56..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_ribbon.h
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "quad_intersector.h"
-#include "curve_intersector_precalculations.h"
-
-#define Bezier1Intersector1 RibbonCurve1Intersector1
-#define Bezier1IntersectorK RibbonCurve1IntersectorK
-
-namespace embree
-{
- namespace isa
- {
- template<typename NativeCurve3ff, int M>
- struct RibbonHit
- {
- __forceinline RibbonHit() {}
-
- __forceinline RibbonHit(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const int i, const int N,
- const NativeCurve3ff& curve3D)
- : U(U), V(V), T(T), i(i), N(N), curve3D(curve3D), valid(valid) {}
-
- __forceinline void finalize()
- {
- vu = (vfloat<M>(step)+U+vfloat<M>(float(i)))*(1.0f/float(N));
- vv = V;
- vt = T;
- }
-
- __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
- __forceinline float t (const size_t i) const { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) const {
- return curve3D.eval_du(vu[i]);
- }
-
- public:
- vfloat<M> U;
- vfloat<M> V;
- vfloat<M> T;
- int i, N;
- NativeCurve3ff curve3D;
-
- public:
- vbool<M> valid;
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- };
-
- /* calculate squared distance of point p0 to line p1->p2 */
- __forceinline std::pair<vfloatx,vfloatx> sqr_point_line_distance(const Vec2vfx& p0, const Vec2vfx& p1, const Vec2vfx& p2)
- {
- const vfloatx num = det(p2-p1,p1-p0);
- const vfloatx den2 = dot(p2-p1,p2-p1);
- return std::make_pair(num*num,den2);
- }
-
- /* performs culling against a cylinder */
- __forceinline vboolx cylinder_culling_test(const Vec2vfx& p0, const Vec2vfx& p1, const Vec2vfx& p2, const vfloatx& r)
- {
- const std::pair<vfloatx,vfloatx> d = sqr_point_line_distance(p0,p1,p2);
- return d.first <= r*r*d.second;
- }
-
- template<typename NativeCurve3ff, typename Epilog>
- __forceinline bool intersect_ribbon(const Vec3fa& ray_org, const Vec3fa& ray_dir, const float ray_tnear, const float& ray_tfar,
- const LinearSpace3fa& ray_space, const float& depth_scale,
- const NativeCurve3ff& curve3D, const int N,
- const Epilog& epilog)
- {
- /* transform control points into ray space */
- const NativeCurve3ff curve2D = curve3D.xfm_pr(ray_space,ray_org);
- float eps = 4.0f*float(ulp)*reduce_max(max(abs(curve2D.v0),abs(curve2D.v1),abs(curve2D.v2),abs(curve2D.v3)));
-
- /* evaluate the bezier curve */
- bool ishit = false;
- vboolx valid = vfloatx(step) < vfloatx(float(N));
- const Vec4vfx p0 = curve2D.template eval0<VSIZEX>(0,N);
- const Vec4vfx p1 = curve2D.template eval1<VSIZEX>(0,N);
- valid &= cylinder_culling_test(zero,Vec2vfx(p0.x,p0.y),Vec2vfx(p1.x,p1.y),max(p0.w,p1.w));
-
- if (any(valid))
- {
- Vec3vfx dp0dt = curve2D.template derivative0<VSIZEX>(0,N);
- Vec3vfx dp1dt = curve2D.template derivative1<VSIZEX>(0,N);
- dp0dt = select(reduce_max(abs(dp0dt)) < vfloatx(eps),Vec3vfx(p1-p0),dp0dt);
- dp1dt = select(reduce_max(abs(dp1dt)) < vfloatx(eps),Vec3vfx(p1-p0),dp1dt);
- const Vec3vfx n0(dp0dt.y,-dp0dt.x,0.0f);
- const Vec3vfx n1(dp1dt.y,-dp1dt.x,0.0f);
- const Vec3vfx nn0 = normalize(n0);
- const Vec3vfx nn1 = normalize(n1);
- const Vec3vfx lp0 = madd(p0.w,nn0,Vec3vfx(p0));
- const Vec3vfx lp1 = madd(p1.w,nn1,Vec3vfx(p1));
- const Vec3vfx up0 = nmadd(p0.w,nn0,Vec3vfx(p0));
- const Vec3vfx up1 = nmadd(p1.w,nn1,Vec3vfx(p1));
-
- vfloatx vu,vv,vt;
- vboolx valid0 = intersect_quad_backface_culling(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt);
-
- if (any(valid0))
- {
- /* ignore self intersections */
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f) {
- vfloatx r = lerp(p0.w, p1.w, vu);
- valid0 &= vt > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale;
- }
-
- if (any(valid0))
- {
- vv = madd(2.0f,vv,vfloatx(-1.0f));
- RibbonHit<NativeCurve3ff,VSIZEX> bhit(valid0,vu,vv,vt,0,N,curve3D);
- ishit |= epilog(bhit.valid,bhit);
- }
- }
- }
-
- if (unlikely(VSIZEX < N))
- {
- /* process SIMD-size many segments per iteration */
- for (int i=VSIZEX; i<N; i+=VSIZEX)
- {
- /* evaluate the bezier curve */
- vboolx valid = vintx(i)+vintx(step) < vintx(N);
- const Vec4vfx p0 = curve2D.template eval0<VSIZEX>(i,N);
- const Vec4vfx p1 = curve2D.template eval1<VSIZEX>(i,N);
- valid &= cylinder_culling_test(zero,Vec2vfx(p0.x,p0.y),Vec2vfx(p1.x,p1.y),max(p0.w,p1.w));
- if (none(valid)) continue;
-
- Vec3vfx dp0dt = curve2D.template derivative0<VSIZEX>(i,N);
- Vec3vfx dp1dt = curve2D.template derivative1<VSIZEX>(i,N);
- dp0dt = select(reduce_max(abs(dp0dt)) < vfloatx(eps),Vec3vfx(p1-p0),dp0dt);
- dp1dt = select(reduce_max(abs(dp1dt)) < vfloatx(eps),Vec3vfx(p1-p0),dp1dt);
- const Vec3vfx n0(dp0dt.y,-dp0dt.x,0.0f);
- const Vec3vfx n1(dp1dt.y,-dp1dt.x,0.0f);
- const Vec3vfx nn0 = normalize(n0);
- const Vec3vfx nn1 = normalize(n1);
- const Vec3vfx lp0 = madd(p0.w,nn0,Vec3vfx(p0));
- const Vec3vfx lp1 = madd(p1.w,nn1,Vec3vfx(p1));
- const Vec3vfx up0 = nmadd(p0.w,nn0,Vec3vfx(p0));
- const Vec3vfx up1 = nmadd(p1.w,nn1,Vec3vfx(p1));
-
- vfloatx vu,vv,vt;
- vboolx valid0 = intersect_quad_backface_culling(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt);
-
- if (any(valid0))
- {
- /* ignore self intersections */
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f) {
- vfloatx r = lerp(p0.w, p1.w, vu);
- valid0 &= vt > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale;
- }
-
- if (any(valid0))
- {
- vv = madd(2.0f,vv,vfloatx(-1.0f));
- RibbonHit<NativeCurve3ff,VSIZEX> bhit(valid0,vu,vv,vt,i,N,curve3D);
- ishit |= epilog(bhit.valid,bhit);
- }
- }
- }
- }
- return ishit;
- }
-
- template<template<typename Ty> class NativeCurve>
- struct RibbonCurve1Intersector1
- {
- typedef NativeCurve<Vec3ff> NativeCurve3ff;
-
- template<typename Epilog>
- __forceinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
- const Epilog& epilog)
- {
- const int N = geom->tessellationRate;
- NativeCurve3ff curve(v0,v1,v2,v3);
- curve = enlargeRadiusToMinWidth(context,geom,ray.org,curve);
- return intersect_ribbon<NativeCurve3ff>(ray.org,ray.dir,ray.tnear(),ray.tfar,
- pre.ray_space,pre.depth_scale,
- curve,N,
- epilog);
- }
- };
-
- template<template<typename Ty> class NativeCurve, int K>
- struct RibbonCurve1IntersectorK
- {
- typedef NativeCurve<Vec3ff> NativeCurve3ff;
-
- template<typename Epilog>
- __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& ray, size_t k,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
- const Epilog& epilog)
- {
- const int N = geom->tessellationRate;
- const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
- const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
- NativeCurve3ff curve(v0,v1,v2,v3);
- curve = enlargeRadiusToMinWidth(context,geom,ray_org,curve);
- return intersect_ribbon<NativeCurve3ff>(ray_org,ray_dir,ray.tnear()[k],ray.tfar[k],
- pre.ray_space[k],pre.depth_scale[k],
- curve,N,
- epilog);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_sweep.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_sweep.h
deleted file mode 100644
index 883cedc3d2..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_sweep.h
+++ /dev/null
@@ -1,362 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "cylinder.h"
-#include "plane.h"
-#include "line_intersector.h"
-#include "curve_intersector_precalculations.h"
-
-namespace embree
-{
- namespace isa
- {
- static const size_t numJacobianIterations = 5;
-#if defined(__AVX__)
- static const size_t numBezierSubdivisions = 2;
-#else
- static const size_t numBezierSubdivisions = 3;
-#endif
-
- struct BezierCurveHit
- {
- __forceinline BezierCurveHit() {}
-
- __forceinline BezierCurveHit(const float t, const float u, const Vec3fa& Ng)
- : t(t), u(u), v(0.0f), Ng(Ng) {}
-
- __forceinline BezierCurveHit(const float t, const float u, const float v, const Vec3fa& Ng)
- : t(t), u(u), v(v), Ng(Ng) {}
-
- __forceinline void finalize() {}
-
- public:
- float t;
- float u;
- float v;
- Vec3fa Ng;
- };
-
- template<typename NativeCurve3ff, typename Ray, typename Epilog>
- __forceinline bool intersect_bezier_iterative_debug(const Ray& ray, const float dt, const NativeCurve3ff& curve, size_t i,
- const vfloatx& u, const BBox<vfloatx>& tp, const BBox<vfloatx>& h0, const BBox<vfloatx>& h1,
- const Vec3vfx& Ng, const Vec4vfx& dP0du, const Vec4vfx& dP3du,
- const Epilog& epilog)
- {
- if (tp.lower[i]+dt > ray.tfar) return false;
- Vec3fa Ng_o = Vec3fa(Ng.x[i],Ng.y[i],Ng.z[i]);
- if (h0.lower[i] == tp.lower[i]) Ng_o = -Vec3fa(dP0du.x[i],dP0du.y[i],dP0du.z[i]);
- if (h1.lower[i] == tp.lower[i]) Ng_o = +Vec3fa(dP3du.x[i],dP3du.y[i],dP3du.z[i]);
- BezierCurveHit hit(tp.lower[i]+dt,u[i],Ng_o);
- return epilog(hit);
- }
-
- template<typename NativeCurve3ff, typename Ray, typename Epilog>
- __forceinline bool intersect_bezier_iterative_jacobian(const Ray& ray, const float dt, const NativeCurve3ff& curve, float u, float t, const Epilog& epilog)
- {
- const Vec3fa org = zero;
- const Vec3fa dir = ray.dir;
- const float length_ray_dir = length(dir);
-
- /* error of curve evaluations is propertional to largest coordinate */
- const BBox3ff box = curve.bounds();
- const float P_err = 16.0f*float(ulp)*reduce_max(max(abs(box.lower),abs(box.upper)));
-
- for (size_t i=0; i<numJacobianIterations; i++)
- {
- const Vec3fa Q = madd(Vec3fa(t),dir,org);
- //const Vec3fa dQdu = zero;
- const Vec3fa dQdt = dir;
- const float Q_err = 16.0f*float(ulp)*length_ray_dir*t; // works as org=zero here
-
- Vec3ff P,dPdu,ddPdu; curve.eval(u,P,dPdu,ddPdu);
- //const Vec3fa dPdt = zero;
-
- const Vec3fa R = Q-P;
- const float len_R = length(R); //reduce_max(abs(R));
- const float R_err = max(Q_err,P_err);
- const Vec3fa dRdu = /*dQdu*/-dPdu;
- const Vec3fa dRdt = dQdt;//-dPdt;
-
- const Vec3fa T = normalize(dPdu);
- const Vec3fa dTdu = dnormalize(dPdu,ddPdu);
- //const Vec3fa dTdt = zero;
- const float cos_err = P_err/length(dPdu);
-
- /* Error estimate for dot(R,T):
-
- dot(R,T) = cos(R,T) |R| |T|
- = (cos(R,T) +- cos_error) * (|R| +- |R|_err) * (|T| +- |T|_err)
- = cos(R,T)*|R|*|T|
- +- cos(R,T)*(|R|*|T|_err + |T|*|R|_err)
- +- cos_error*(|R| + |T|)
- +- lower order terms
- with cos(R,T) being in [0,1] and |T| = 1 we get:
- dot(R,T)_err = |R|*|T|_err + |R|_err = cos_error*(|R|+1)
- */
-
- const float f = dot(R,T);
- const float f_err = len_R*P_err + R_err + cos_err*(1.0f+len_R);
- const float dfdu = dot(dRdu,T) + dot(R,dTdu);
- const float dfdt = dot(dRdt,T);// + dot(R,dTdt);
-
- const float K = dot(R,R)-sqr(f);
- const float dKdu = /*2.0f*/(dot(R,dRdu)-f*dfdu);
- const float dKdt = /*2.0f*/(dot(R,dRdt)-f*dfdt);
- const float rsqrt_K = rsqrt(K);
-
- const float g = sqrt(K)-P.w;
- const float g_err = R_err + f_err + 16.0f*float(ulp)*box.upper.w;
- const float dgdu = /*0.5f*/dKdu*rsqrt_K-dPdu.w;
- const float dgdt = /*0.5f*/dKdt*rsqrt_K;//-dPdt.w;
-
- const LinearSpace2f J = LinearSpace2f(dfdu,dfdt,dgdu,dgdt);
- const Vec2f dut = rcp(J)*Vec2f(f,g);
- const Vec2f ut = Vec2f(u,t) - dut;
- u = ut.x; t = ut.y;
-
- if (abs(f) < f_err && abs(g) < g_err)
- {
- t+=dt;
- if (!(ray.tnear() <= t && t <= ray.tfar)) return false; // rejects NaNs
- if (!(u >= 0.0f && u <= 1.0f)) return false; // rejects NaNs
- const Vec3fa R = normalize(Q-P);
- const Vec3fa U = madd(Vec3fa(dPdu.w),R,dPdu);
- const Vec3fa V = cross(dPdu,R);
- BezierCurveHit hit(t,u,cross(V,U));
- return epilog(hit);
- }
- }
- return false;
- }
-
- template<typename NativeCurve3ff, typename Ray, typename Epilog>
- bool intersect_bezier_recursive_jacobian(const Ray& ray, const float dt, const NativeCurve3ff& curve,
- float u0, float u1, unsigned int depth, const Epilog& epilog)
- {
-#if defined(__AVX__)
- typedef vbool8 vboolx; // maximally 8-wide to work around KNL issues
- typedef vint8 vintx;
- typedef vfloat8 vfloatx;
-#else
- typedef vbool4 vboolx;
- typedef vint4 vintx;
- typedef vfloat4 vfloatx;
-#endif
- typedef Vec3<vfloatx> Vec3vfx;
- typedef Vec4<vfloatx> Vec4vfx;
-
- unsigned int maxDepth = numBezierSubdivisions;
- bool found = false;
- const Vec3fa org = zero;
- const Vec3fa dir = ray.dir;
-
- unsigned int sptr = 0;
- const unsigned int stack_size = numBezierSubdivisions+1; // +1 because of unstable workaround below
- struct StackEntry {
- vboolx valid;
- vfloatx tlower;
- float u0;
- float u1;
- unsigned int depth;
- };
- StackEntry stack[stack_size];
- goto entry;
-
- /* terminate if stack is empty */
- while (sptr)
- {
- /* pop from stack */
- {
- sptr--;
- vboolx valid = stack[sptr].valid;
- const vfloatx tlower = stack[sptr].tlower;
- valid &= tlower+dt <= ray.tfar;
- if (none(valid)) continue;
- u0 = stack[sptr].u0;
- u1 = stack[sptr].u1;
- depth = stack[sptr].depth;
- const size_t i = select_min(valid,tlower); clear(valid,i);
- stack[sptr].valid = valid;
- if (any(valid)) sptr++; // there are still items on the stack
-
- /* process next segment */
- const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(vfloatx::size-1)));
- u0 = vu0[i+0];
- u1 = vu0[i+1];
- }
- entry:
-
- /* subdivide curve */
- const float dscale = (u1-u0)*(1.0f/(3.0f*(vfloatx::size-1)));
- const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(vfloatx::size-1)));
- Vec4vfx P0, dP0du; curve.veval(vu0,P0,dP0du); dP0du = dP0du * Vec4vfx(dscale);
- const Vec4vfx P3 = shift_right_1(P0);
- const Vec4vfx dP3du = shift_right_1(dP0du);
- const Vec4vfx P1 = P0 + dP0du;
- const Vec4vfx P2 = P3 - dP3du;
-
- /* calculate bounding cylinders */
- const vfloatx rr1 = sqr_point_to_line_distance(Vec3vfx(dP0du),Vec3vfx(P3-P0));
- const vfloatx rr2 = sqr_point_to_line_distance(Vec3vfx(dP3du),Vec3vfx(P3-P0));
- const vfloatx maxr12 = sqrt(max(rr1,rr2));
- const vfloatx one_plus_ulp = 1.0f+2.0f*float(ulp);
- const vfloatx one_minus_ulp = 1.0f-2.0f*float(ulp);
- vfloatx r_outer = max(P0.w,P1.w,P2.w,P3.w)+maxr12;
- vfloatx r_inner = min(P0.w,P1.w,P2.w,P3.w)-maxr12;
- r_outer = one_plus_ulp*r_outer;
- r_inner = max(0.0f,one_minus_ulp*r_inner);
- const CylinderN<vfloatx::size> cylinder_outer(Vec3vfx(P0),Vec3vfx(P3),r_outer);
- const CylinderN<vfloatx::size> cylinder_inner(Vec3vfx(P0),Vec3vfx(P3),r_inner);
- vboolx valid = true; clear(valid,vfloatx::size-1);
-
- /* intersect with outer cylinder */
- BBox<vfloatx> tc_outer; vfloatx u_outer0; Vec3vfx Ng_outer0; vfloatx u_outer1; Vec3vfx Ng_outer1;
- valid &= cylinder_outer.intersect(org,dir,tc_outer,u_outer0,Ng_outer0,u_outer1,Ng_outer1);
- if (none(valid)) continue;
-
- /* intersect with cap-planes */
- BBox<vfloatx> tp(ray.tnear()-dt,ray.tfar-dt);
- tp = embree::intersect(tp,tc_outer);
- BBox<vfloatx> h0 = HalfPlaneN<vfloatx::size>(Vec3vfx(P0),+Vec3vfx(dP0du)).intersect(org,dir);
- tp = embree::intersect(tp,h0);
- BBox<vfloatx> h1 = HalfPlaneN<vfloatx::size>(Vec3vfx(P3),-Vec3vfx(dP3du)).intersect(org,dir);
- tp = embree::intersect(tp,h1);
- valid &= tp.lower <= tp.upper;
- if (none(valid)) continue;
-
- /* clamp and correct u parameter */
- u_outer0 = clamp(u_outer0,vfloatx(0.0f),vfloatx(1.0f));
- u_outer1 = clamp(u_outer1,vfloatx(0.0f),vfloatx(1.0f));
- u_outer0 = lerp(u0,u1,(vfloatx(step)+u_outer0)*(1.0f/float(vfloatx::size)));
- u_outer1 = lerp(u0,u1,(vfloatx(step)+u_outer1)*(1.0f/float(vfloatx::size)));
-
- /* intersect with inner cylinder */
- BBox<vfloatx> tc_inner;
- vfloatx u_inner0 = zero; Vec3vfx Ng_inner0 = zero; vfloatx u_inner1 = zero; Vec3vfx Ng_inner1 = zero;
- const vboolx valid_inner = cylinder_inner.intersect(org,dir,tc_inner,u_inner0,Ng_inner0,u_inner1,Ng_inner1);
-
- /* at the unstable area we subdivide deeper */
- const vboolx unstable0 = (!valid_inner) | (abs(dot(Vec3vfx(Vec3fa(ray.dir)),Ng_inner0)) < 0.3f);
- const vboolx unstable1 = (!valid_inner) | (abs(dot(Vec3vfx(Vec3fa(ray.dir)),Ng_inner1)) < 0.3f);
-
- /* subtract the inner interval from the current hit interval */
- BBox<vfloatx> tp0, tp1;
- subtract(tp,tc_inner,tp0,tp1);
- vboolx valid0 = valid & (tp0.lower <= tp0.upper);
- vboolx valid1 = valid & (tp1.lower <= tp1.upper);
- if (none(valid0 | valid1)) continue;
-
- /* iterate over all first hits front to back */
- const vintx termDepth0 = select(unstable0,vintx(maxDepth+1),vintx(maxDepth));
- vboolx recursion_valid0 = valid0 & (depth < termDepth0);
- valid0 &= depth >= termDepth0;
-
- while (any(valid0))
- {
- const size_t i = select_min(valid0,tp0.lower); clear(valid0,i);
- found = found | intersect_bezier_iterative_jacobian(ray,dt,curve,u_outer0[i],tp0.lower[i],epilog);
- //found = found | intersect_bezier_iterative_debug (ray,dt,curve,i,u_outer0,tp0,h0,h1,Ng_outer0,dP0du,dP3du,epilog);
- valid0 &= tp0.lower+dt <= ray.tfar;
- }
- valid1 &= tp1.lower+dt <= ray.tfar;
-
- /* iterate over all second hits front to back */
- const vintx termDepth1 = select(unstable1,vintx(maxDepth+1),vintx(maxDepth));
- vboolx recursion_valid1 = valid1 & (depth < termDepth1);
- valid1 &= depth >= termDepth1;
- while (any(valid1))
- {
- const size_t i = select_min(valid1,tp1.lower); clear(valid1,i);
- found = found | intersect_bezier_iterative_jacobian(ray,dt,curve,u_outer1[i],tp1.upper[i],epilog);
- //found = found | intersect_bezier_iterative_debug (ray,dt,curve,i,u_outer1,tp1,h0,h1,Ng_outer1,dP0du,dP3du,epilog);
- valid1 &= tp1.lower+dt <= ray.tfar;
- }
-
- /* push valid segments to stack */
- recursion_valid0 &= tp0.lower+dt <= ray.tfar;
- recursion_valid1 &= tp1.lower+dt <= ray.tfar;
- const vboolx recursion_valid = recursion_valid0 | recursion_valid1;
- if (any(recursion_valid))
- {
- assert(sptr < stack_size);
- stack[sptr].valid = recursion_valid;
- stack[sptr].tlower = select(recursion_valid0,tp0.lower,tp1.lower);
- stack[sptr].u0 = u0;
- stack[sptr].u1 = u1;
- stack[sptr].depth = depth+1;
- sptr++;
- }
- }
- return found;
- }
-
- template<template<typename Ty> class NativeCurve>
- struct SweepCurve1Intersector1
- {
- typedef NativeCurve<Vec3ff> NativeCurve3ff;
-
- template<typename Epilog>
- __noinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
- const Epilog& epilog)
- {
- STAT3(normal.trav_prims,1,1,1);
-
- /* move ray closer to make intersection stable */
- NativeCurve3ff curve0(v0,v1,v2,v3);
- curve0 = enlargeRadiusToMinWidth(context,geom,ray.org,curve0);
- const float dt = dot(curve0.center()-ray.org,ray.dir)*rcp(dot(ray.dir,ray.dir));
- const Vec3ff ref(madd(Vec3fa(dt),ray.dir,ray.org),0.0f);
- const NativeCurve3ff curve1 = curve0-ref;
- return intersect_bezier_recursive_jacobian(ray,dt,curve1,0.0f,1.0f,1,epilog);
- }
- };
-
- template<template<typename Ty> class NativeCurve, int K>
- struct SweepCurve1IntersectorK
- {
- typedef NativeCurve<Vec3ff> NativeCurve3ff;
-
- struct Ray1
- {
- __forceinline Ray1(RayK<K>& ray, size_t k)
- : org(ray.org.x[k],ray.org.y[k],ray.org.z[k]), dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]), _tnear(ray.tnear()[k]), tfar(ray.tfar[k]) {}
-
- Vec3fa org;
- Vec3fa dir;
- float _tnear;
- float& tfar;
-
- __forceinline float& tnear() { return _tnear; }
- //__forceinline float& tfar() { return _tfar; }
- __forceinline const float& tnear() const { return _tnear; }
- //__forceinline const float& tfar() const { return _tfar; }
-
- };
-
- template<typename Epilog>
- __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& vray, size_t k,
- IntersectContext* context,
- const CurveGeometry* geom, const unsigned int primID,
- const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
- const Epilog& epilog)
- {
- STAT3(normal.trav_prims,1,1,1);
- Ray1 ray(vray,k);
-
- /* move ray closer to make intersection stable */
- NativeCurve3ff curve0(v0,v1,v2,v3);
- curve0 = enlargeRadiusToMinWidth(context,geom,ray.org,curve0);
- const float dt = dot(curve0.center()-ray.org,ray.dir)*rcp(dot(ray.dir,ray.dir));
- const Vec3ff ref(madd(Vec3fa(dt),ray.dir,ray.org),0.0f);
- const NativeCurve3ff curve1 = curve0-ref;
- return intersect_bezier_recursive_jacobian(ray,dt,curve1,0.0f,1.0f,1,epilog);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual.h
deleted file mode 100644
index e1f4238130..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual.h
+++ /dev/null
@@ -1,671 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-#include "../subdiv/bezier_curve.h"
-#include "../common/primref.h"
-#include "curve_intersector_precalculations.h"
-#include "../bvh/node_intersector1.h"
-#include "../bvh/node_intersector_packet.h"
-
-#include "intersector_epilog.h"
-
-#include "../subdiv/bezier_curve.h"
-#include "../subdiv/bspline_curve.h"
-#include "../subdiv/hermite_curve.h"
-#include "../subdiv/catmullrom_curve.h"
-
-#include "spherei_intersector.h"
-#include "disci_intersector.h"
-
-#include "linei_intersector.h"
-#include "roundlinei_intersector.h"
-#include "conelinei_intersector.h"
-
-#include "curveNi_intersector.h"
-#include "curveNv_intersector.h"
-#include "curveNi_mb_intersector.h"
-
-#include "curve_intersector_distance.h"
-#include "curve_intersector_ribbon.h"
-#include "curve_intersector_oriented.h"
-#include "curve_intersector_sweep.h"
-
-namespace embree
-{
- struct VirtualCurveIntersector
- {
- typedef void (*Intersect1Ty)(void* pre, void* ray, IntersectContext* context, const void* primitive);
- typedef bool (*Occluded1Ty )(void* pre, void* ray, IntersectContext* context, const void* primitive);
-
- typedef void (*Intersect4Ty)(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
- typedef bool (*Occluded4Ty) (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
-
- typedef void (*Intersect8Ty)(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
- typedef bool (*Occluded8Ty) (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
-
- typedef void (*Intersect16Ty)(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
- typedef bool (*Occluded16Ty) (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
-
- public:
- struct Intersectors
- {
- Intersectors() {} // WARNING: Do not zero initialize this, as we otherwise get problems with thread unsafe local static variable initialization (e.g. on VS2013) in curve_intersector_virtual.cpp.
-
- template<int K> void intersect(void* pre, void* ray, IntersectContext* context, const void* primitive);
- template<int K> bool occluded (void* pre, void* ray, IntersectContext* context, const void* primitive);
-
- template<int K> void intersect(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
- template<int K> bool occluded (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
-
- public:
- Intersect1Ty intersect1;
- Occluded1Ty occluded1;
- Intersect4Ty intersect4;
- Occluded4Ty occluded4;
- Intersect8Ty intersect8;
- Occluded8Ty occluded8;
- Intersect16Ty intersect16;
- Occluded16Ty occluded16;
- };
-
- Intersectors vtbl[Geometry::GTY_END];
- };
-
- template<> __forceinline void VirtualCurveIntersector::Intersectors::intersect<1> (void* pre, void* ray, IntersectContext* context, const void* primitive) { assert(intersect1); intersect1(pre,ray,context,primitive); }
- template<> __forceinline bool VirtualCurveIntersector::Intersectors::occluded<1> (void* pre, void* ray, IntersectContext* context, const void* primitive) { assert(occluded1); return occluded1(pre,ray,context,primitive); }
-
- template<> __forceinline void VirtualCurveIntersector::Intersectors::intersect<4>(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(intersect4); intersect4(pre,ray,k,context,primitive); }
- template<> __forceinline bool VirtualCurveIntersector::Intersectors::occluded<4> (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(occluded4); return occluded4(pre,ray,k,context,primitive); }
-
-#if defined(__AVX__)
- template<> __forceinline void VirtualCurveIntersector::Intersectors::intersect<8>(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(intersect8); intersect8(pre,ray,k,context,primitive); }
- template<> __forceinline bool VirtualCurveIntersector::Intersectors::occluded<8> (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(occluded8); return occluded8(pre,ray,k,context,primitive); }
-#endif
-
-#if defined(__AVX512F__)
- template<> __forceinline void VirtualCurveIntersector::Intersectors::intersect<16>(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(intersect16); intersect16(pre,ray,k,context,primitive); }
- template<> __forceinline bool VirtualCurveIntersector::Intersectors::occluded<16> (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(occluded16); return occluded16(pre,ray,k,context,primitive); }
-#endif
-
- namespace isa
- {
- struct VirtualCurveIntersector1
- {
- typedef unsigned char Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
- leafIntersector.intersect<1>(&pre,&ray,context,prim);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
- return leafIntersector.occluded<1>(&pre,&ray,context,prim);
- }
- };
-
- template<int K>
- struct VirtualCurveIntersectorK
- {
- typedef unsigned char Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- template<bool robust>
- static __forceinline void intersect(const vbool<K>& valid_i, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
- size_t mask = movemask(valid_i);
- while (mask) leafIntersector.intersect<K>(&pre,&ray,bscf(mask),context,prim);
- }
-
- template<bool robust>
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
- vbool<K> valid_o = false;
- size_t mask = movemask(valid_i);
- while (mask) {
- size_t k = bscf(mask);
- if (leafIntersector.occluded<K>(&pre,&ray,k,context,prim))
- set(valid_o, k);
- }
- return valid_o;
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
- leafIntersector.intersect<K>(&pre,&ray,k,context,prim);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- assert(num == 1);
- RTCGeometryType ty = (RTCGeometryType)(*prim);
- assert(This->leafIntersector);
- VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
- return leafIntersector.occluded<K>(&pre,&ray,k,context,prim);
- }
- };
-
- template<int N>
- static VirtualCurveIntersector::Intersectors LinearRoundConeNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &RoundLinearCurveMiIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &RoundLinearCurveMiIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &RoundLinearCurveMiIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &RoundLinearCurveMiIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&RoundLinearCurveMiIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &RoundLinearCurveMiIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&RoundLinearCurveMiIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &RoundLinearCurveMiIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors LinearConeNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &ConeCurveMiIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &ConeCurveMiIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &ConeCurveMiIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &ConeCurveMiIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&ConeCurveMiIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &ConeCurveMiIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&ConeCurveMiIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &ConeCurveMiIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors LinearRoundConeNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &RoundLinearCurveMiMBIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &RoundLinearCurveMiMBIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &RoundLinearCurveMiMBIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &RoundLinearCurveMiMBIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&RoundLinearCurveMiMBIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &RoundLinearCurveMiMBIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&RoundLinearCurveMiMBIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &RoundLinearCurveMiMBIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors LinearConeNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &ConeCurveMiMBIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &ConeCurveMiMBIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &ConeCurveMiMBIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &ConeCurveMiMBIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&ConeCurveMiMBIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &ConeCurveMiMBIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&ConeCurveMiMBIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &ConeCurveMiMBIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
-
- template<int N>
- static VirtualCurveIntersector::Intersectors LinearRibbonNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &FlatLinearCurveMiIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &FlatLinearCurveMiIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &FlatLinearCurveMiIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &FlatLinearCurveMiIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&FlatLinearCurveMiIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &FlatLinearCurveMiIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&FlatLinearCurveMiIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &FlatLinearCurveMiIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors LinearRibbonNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &FlatLinearCurveMiMBIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &FlatLinearCurveMiMBIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &FlatLinearCurveMiMBIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &FlatLinearCurveMiMBIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&FlatLinearCurveMiMBIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &FlatLinearCurveMiMBIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&FlatLinearCurveMiMBIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &FlatLinearCurveMiMBIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors SphereNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &SphereMiIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &SphereMiIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &SphereMiIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &SphereMiIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&SphereMiIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &SphereMiIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&SphereMiIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &SphereMiIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors SphereNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &SphereMiMBIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &SphereMiMBIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &SphereMiMBIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &SphereMiMBIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&SphereMiMBIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &SphereMiMBIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&SphereMiMBIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &SphereMiMBIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors DiscNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &DiscMiIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &DiscMiIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &DiscMiIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &DiscMiIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&DiscMiIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &DiscMiIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&DiscMiIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &DiscMiIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors DiscNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &DiscMiMBIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &DiscMiMBIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &DiscMiMBIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &DiscMiMBIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&DiscMiMBIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &DiscMiMBIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&DiscMiMBIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &DiscMiMBIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors OrientedDiscNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &OrientedDiscMiIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &OrientedDiscMiIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &OrientedDiscMiIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &OrientedDiscMiIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&OrientedDiscMiIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &OrientedDiscMiIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&OrientedDiscMiIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &OrientedDiscMiIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<int N>
- static VirtualCurveIntersector::Intersectors OrientedDiscNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &OrientedDiscMiMBIntersector1<N,N,true>::intersect;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &OrientedDiscMiMBIntersector1<N,N,true>::occluded;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &OrientedDiscMiMBIntersectorK<N,N,4,true>::intersect;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &OrientedDiscMiMBIntersectorK<N,N,4,true>::occluded;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&OrientedDiscMiMBIntersectorK<N,N,8,true>::intersect;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &OrientedDiscMiMBIntersectorK<N,N,8,true>::occluded;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&OrientedDiscMiMBIntersectorK<N,N,16,true>::intersect;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &OrientedDiscMiMBIntersectorK<N,N,16,true>::occluded;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors RibbonNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_t<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_t <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &CurveNiIntersectorK<N,4>::template intersect_t<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_t <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_t<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_t <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_t<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_t <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors RibbonNvIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNvIntersector1<N>::template intersect_t<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNvIntersector1<N>::template occluded_t <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &CurveNvIntersectorK<N,4>::template intersect_t<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNvIntersectorK<N,4>::template occluded_t <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNvIntersectorK<N,8>::template intersect_t<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNvIntersectorK<N,8>::template occluded_t <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNvIntersectorK<N,16>::template intersect_t<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNvIntersectorK<N,16>::template occluded_t <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors RibbonNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_t<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_t <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &CurveNiMBIntersectorK<N,4>::template intersect_t<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_t <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_t<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_t <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_t<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_t <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors CurveNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_t<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_t <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_t<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_t <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_t<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_t <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_t<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_t <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors CurveNvIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNvIntersector1<N>::template intersect_t<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNvIntersector1<N>::template occluded_t <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNvIntersectorK<N,4>::template intersect_t<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNvIntersectorK<N,4>::template occluded_t <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNvIntersectorK<N,8>::template intersect_t<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNvIntersectorK<N,8>::template occluded_t <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNvIntersectorK<N,16>::template intersect_t<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNvIntersectorK<N,16>::template occluded_t <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors CurveNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_t<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_t <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_t<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_t <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_t<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_t <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_t<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_t <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors OrientedCurveNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_n<OrientedCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_n <OrientedCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_n<OrientedCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_n <OrientedCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_n<OrientedCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_n <OrientedCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_n<OrientedCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_n <OrientedCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors OrientedCurveNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_n<OrientedCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_n <OrientedCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_n<OrientedCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_n <OrientedCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_n<OrientedCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_n <OrientedCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_n<OrientedCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_n <OrientedCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors HermiteRibbonNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_h<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_h <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_h<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_h <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_h<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_h <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_h<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_h <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors HermiteRibbonNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_h<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_h <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_h<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_h <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_h<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_h <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_h<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_h <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors HermiteCurveNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_h<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_h <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_h<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_h <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_h<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_h <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_h<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_h <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors HermiteCurveNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_h<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_h <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_h<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_h <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_h<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_h <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_h<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_h <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors HermiteOrientedCurveNiIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_hn<OrientedCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_hn <OrientedCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_hn<OrientedCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_hn <OrientedCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_hn<OrientedCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_hn <OrientedCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_hn<OrientedCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_hn <OrientedCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
-
- template<template<typename Ty> class Curve, int N>
- static VirtualCurveIntersector::Intersectors HermiteOrientedCurveNiMBIntersectors()
- {
- VirtualCurveIntersector::Intersectors intersectors;
- intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_hn<OrientedCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
- intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_hn <OrientedCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
- intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_hn<OrientedCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
- intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_hn <OrientedCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
-#if defined(__AVX__)
- intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_hn<OrientedCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
- intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_hn <OrientedCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
-#endif
-#if defined(__AVX512F__)
- intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_hn<OrientedCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
- intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_hn <OrientedCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
-#endif
- return intersectors;
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_bezier_curve.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_bezier_curve.h
deleted file mode 100644
index 69cf612275..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_bezier_curve.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2020 Light Transport Entertainment Inc.
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curve_intersector_virtual.h"
-
-namespace embree
-{
- namespace isa
- {
- void AddVirtualCurveBezierCurveInterector4i(VirtualCurveIntersector &prim);
- void AddVirtualCurveBezierCurveInterector4v(VirtualCurveIntersector &prim);
- void AddVirtualCurveBezierCurveInterector4iMB(VirtualCurveIntersector &prim);
-#if defined(__AVX__)
- void AddVirtualCurveBezierCurveInterector8i(VirtualCurveIntersector &prim);
- void AddVirtualCurveBezierCurveInterector8v(VirtualCurveIntersector &prim);
- void AddVirtualCurveBezierCurveInterector8iMB(VirtualCurveIntersector &prim);
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_bspline_curve.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_bspline_curve.h
deleted file mode 100644
index d37e41098e..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_bspline_curve.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2020 Light Transport Entertainment Inc.
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curve_intersector_virtual.h"
-
-namespace embree
-{
- namespace isa
- {
- void AddVirtualCurveBSplineCurveInterector4i(VirtualCurveIntersector &prim);
- void AddVirtualCurveBSplineCurveInterector4v(VirtualCurveIntersector &prim);
- void AddVirtualCurveBSplineCurveInterector4iMB(VirtualCurveIntersector &prim);
-#if defined(__AVX__)
- void AddVirtualCurveBSplineCurveInterector8i(VirtualCurveIntersector &prim);
- void AddVirtualCurveBSplineCurveInterector8v(VirtualCurveIntersector &prim);
- void AddVirtualCurveBSplineCurveInterector8iMB(VirtualCurveIntersector &prim);
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_catmullrom_curve.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_catmullrom_curve.h
deleted file mode 100644
index a133a11d63..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_catmullrom_curve.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2020 Light Transport Entertainment Inc.
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curve_intersector_virtual.h"
-
-namespace embree
-{
- namespace isa
- {
- void AddVirtualCurveCatmullRomCurveInterector4i(VirtualCurveIntersector &prim);
- void AddVirtualCurveCatmullRomCurveInterector4v(VirtualCurveIntersector &prim);
- void AddVirtualCurveCatmullRomCurveInterector4iMB(VirtualCurveIntersector &prim);
-#if defined(__AVX__)
- void AddVirtualCurveCatmullRomCurveInterector8i(VirtualCurveIntersector &prim);
- void AddVirtualCurveCatmullRomCurveInterector8v(VirtualCurveIntersector &prim);
- void AddVirtualCurveCatmullRomCurveInterector8iMB(VirtualCurveIntersector &prim);
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_hermite_curve.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_hermite_curve.h
deleted file mode 100644
index 9aec35da45..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_hermite_curve.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2020 Light Transport Entertainment Inc.
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curve_intersector_virtual.h"
-
-namespace embree
-{
- namespace isa
- {
- void AddVirtualCurveHermiteCurveInterector4i(VirtualCurveIntersector &prim);
- void AddVirtualCurveHermiteCurveInterector4v(VirtualCurveIntersector &prim);
- void AddVirtualCurveHermiteCurveInterector4iMB(VirtualCurveIntersector &prim);
-#if defined(__AVX__)
- void AddVirtualCurveHermiteCurveInterector8i(VirtualCurveIntersector &prim);
- void AddVirtualCurveHermiteCurveInterector8v(VirtualCurveIntersector &prim);
- void AddVirtualCurveHermiteCurveInterector8iMB(VirtualCurveIntersector &prim);
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_linear_curve.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_linear_curve.h
deleted file mode 100644
index dd37d194f5..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_linear_curve.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2020 Light Transport Entertainment Inc.
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curve_intersector_virtual.h"
-
-namespace embree
-{
- namespace isa
- {
- void AddVirtualCurveLinearCurveInterector4i(VirtualCurveIntersector &prim);
- void AddVirtualCurveLinearCurveInterector4v(VirtualCurveIntersector &prim);
- void AddVirtualCurveLinearCurveInterector4iMB(VirtualCurveIntersector &prim);
-#if defined(__AVX__)
- void AddVirtualCurveLinearCurveInterector8i(VirtualCurveIntersector &prim);
- void AddVirtualCurveLinearCurveInterector8v(VirtualCurveIntersector &prim);
- void AddVirtualCurveLinearCurveInterector8iMB(VirtualCurveIntersector &prim);
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_point.h b/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_point.h
deleted file mode 100644
index fe5ceed840..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/curve_intersector_virtual_point.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2020 Light Transport Entertainment Inc.
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "curve_intersector_virtual.h"
-
-namespace embree
-{
- namespace isa
- {
- void AddVirtualCurvePointInterector4i(VirtualCurveIntersector &prim);
- void AddVirtualCurvePointInterector4v(VirtualCurveIntersector &prim);
- void AddVirtualCurvePointInterector4iMB(VirtualCurveIntersector &prim);
-
-#if defined (__AVX__)
- void AddVirtualCurvePointInterector8i(VirtualCurveIntersector &prim);
- void AddVirtualCurvePointInterector8v(VirtualCurveIntersector &prim);
- void AddVirtualCurvePointInterector8iMB(VirtualCurveIntersector &prim);
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/cylinder.h b/thirdparty/embree-aarch64/kernels/geometry/cylinder.h
deleted file mode 100644
index 39a582864c..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/cylinder.h
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-
-namespace embree
-{
- namespace isa
- {
- struct Cylinder
- {
- const Vec3fa p0; //!< start location
- const Vec3fa p1; //!< end position
- const float rr; //!< squared radius of cylinder
-
- __forceinline Cylinder(const Vec3fa& p0, const Vec3fa& p1, const float r)
- : p0(p0), p1(p1), rr(sqr(r)) {}
-
- __forceinline Cylinder(const Vec3fa& p0, const Vec3fa& p1, const float rr, bool)
- : p0(p0), p1(p1), rr(rr) {}
-
- __forceinline bool intersect(const Vec3fa& org,
- const Vec3fa& dir,
- BBox1f& t_o,
- float& u0_o, Vec3fa& Ng0_o,
- float& u1_o, Vec3fa& Ng1_o) const
- {
- /* calculate quadratic equation to solve */
- const float rl = rcp_length(p1-p0);
- const Vec3fa P0 = p0, dP = (p1-p0)*rl;
- const Vec3fa O = org-P0, dO = dir;
-
- const float dOdO = dot(dO,dO);
- const float OdO = dot(dO,O);
- const float OO = dot(O,O);
- const float dOz = dot(dP,dO);
- const float Oz = dot(dP,O);
-
- const float A = dOdO - sqr(dOz);
- const float B = 2.0f * (OdO - dOz*Oz);
- const float C = OO - sqr(Oz) - rr;
-
- /* we miss the cylinder if determinant is smaller than zero */
- const float D = B*B - 4.0f*A*C;
- if (D < 0.0f) {
- t_o = BBox1f(pos_inf,neg_inf);
- return false;
- }
-
- /* special case for rays that are parallel to the cylinder */
- const float eps = 16.0f*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
- if (abs(A) < eps)
- {
- if (C <= 0.0f) {
- t_o = BBox1f(neg_inf,pos_inf);
- return true;
- } else {
- t_o = BBox1f(pos_inf,neg_inf);
- return false;
- }
- }
-
- /* standard case for rays that are not parallel to the cylinder */
- const float Q = sqrt(D);
- const float rcp_2A = rcp(2.0f*A);
- const float t0 = (-B-Q)*rcp_2A;
- const float t1 = (-B+Q)*rcp_2A;
-
- /* calculates u and Ng for near hit */
- {
- u0_o = madd(t0,dOz,Oz)*rl;
- const Vec3fa Pr = t0*dir;
- const Vec3fa Pl = madd(u0_o,p1-p0,p0);
- Ng0_o = Pr-Pl;
- }
-
- /* calculates u and Ng for far hit */
- {
- u1_o = madd(t1,dOz,Oz)*rl;
- const Vec3fa Pr = t1*dir;
- const Vec3fa Pl = madd(u1_o,p1-p0,p0);
- Ng1_o = Pr-Pl;
- }
-
- t_o.lower = t0;
- t_o.upper = t1;
- return true;
- }
-
- __forceinline bool intersect(const Vec3fa& org_i, const Vec3fa& dir, BBox1f& t_o) const
- {
- float u0_o; Vec3fa Ng0_o;
- float u1_o; Vec3fa Ng1_o;
- return intersect(org_i,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
- }
-
- static bool verify(const size_t id, const Cylinder& cylinder, const RayHit& ray, bool shouldhit, const float t0, const float t1)
- {
- float eps = 0.001f;
- BBox1f t; bool hit;
- hit = cylinder.intersect(ray.org,ray.dir,t);
-
- bool failed = hit != shouldhit;
- if (shouldhit) failed |= std::isinf(t0) ? t0 != t.lower : abs(t0-t.lower) > eps;
- if (shouldhit) failed |= std::isinf(t1) ? t1 != t.upper : abs(t1-t.upper) > eps;
- if (!failed) return true;
- embree_cout << "Cylinder test " << id << " failed: cylinder = " << cylinder << ", ray = " << ray << ", hit = " << hit << ", t = " << t << embree_endl;
- return false;
- }
-
- /* verify cylinder class */
- static bool verify()
- {
- bool passed = true;
- const Cylinder cylinder(Vec3fa(0.0f,0.0f,0.0f),Vec3fa(1.0f,0.0f,0.0f),1.0f);
- passed &= verify(0,cylinder,RayHit(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
- passed &= verify(1,cylinder,RayHit(Vec3fa(+2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
- passed &= verify(2,cylinder,RayHit(Vec3fa(+2.0f,1.0f,2.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),false,0.0f,0.0f);
- passed &= verify(3,cylinder,RayHit(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
- passed &= verify(4,cylinder,RayHit(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
- passed &= verify(5,cylinder,RayHit(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
- passed &= verify(6,cylinder,RayHit(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
- return passed;
- }
-
- /*! output operator */
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const Cylinder& c) {
- return cout << "Cylinder { p0 = " << c.p0 << ", p1 = " << c.p1 << ", r = " << sqrtf(c.rr) << "}";
- }
- };
-
- template<int N>
- struct CylinderN
- {
- const Vec3vf<N> p0; //!< start location
- const Vec3vf<N> p1; //!< end position
- const vfloat<N> rr; //!< squared radius of cylinder
-
- __forceinline CylinderN(const Vec3vf<N>& p0, const Vec3vf<N>& p1, const vfloat<N>& r)
- : p0(p0), p1(p1), rr(sqr(r)) {}
-
- __forceinline CylinderN(const Vec3vf<N>& p0, const Vec3vf<N>& p1, const vfloat<N>& rr, bool)
- : p0(p0), p1(p1), rr(rr) {}
-
-
- __forceinline vbool<N> intersect(const Vec3fa& org, const Vec3fa& dir,
- BBox<vfloat<N>>& t_o,
- vfloat<N>& u0_o, Vec3vf<N>& Ng0_o,
- vfloat<N>& u1_o, Vec3vf<N>& Ng1_o) const
- {
- /* calculate quadratic equation to solve */
- const vfloat<N> rl = rcp_length(p1-p0);
- const Vec3vf<N> P0 = p0, dP = (p1-p0)*rl;
- const Vec3vf<N> O = Vec3vf<N>(org)-P0, dO = dir;
-
- const vfloat<N> dOdO = dot(dO,dO);
- const vfloat<N> OdO = dot(dO,O);
- const vfloat<N> OO = dot(O,O);
- const vfloat<N> dOz = dot(dP,dO);
- const vfloat<N> Oz = dot(dP,O);
-
- const vfloat<N> A = dOdO - sqr(dOz);
- const vfloat<N> B = 2.0f * (OdO - dOz*Oz);
- const vfloat<N> C = OO - sqr(Oz) - rr;
-
- /* we miss the cylinder if determinant is smaller than zero */
- const vfloat<N> D = B*B - 4.0f*A*C;
- vbool<N> valid = D >= 0.0f;
- if (none(valid)) {
- t_o = BBox<vfloat<N>>(empty);
- return valid;
- }
-
- /* standard case for rays that are not parallel to the cylinder */
- const vfloat<N> Q = sqrt(D);
- const vfloat<N> rcp_2A = rcp(2.0f*A);
- const vfloat<N> t0 = (-B-Q)*rcp_2A;
- const vfloat<N> t1 = (-B+Q)*rcp_2A;
-
- /* calculates u and Ng for near hit */
- {
- u0_o = madd(t0,dOz,Oz)*rl;
- const Vec3vf<N> Pr = t0*Vec3vf<N>(dir);
- const Vec3vf<N> Pl = madd(u0_o,p1-p0,p0);
- Ng0_o = Pr-Pl;
- }
-
- /* calculates u and Ng for far hit */
- {
- u1_o = madd(t1,dOz,Oz)*rl;
- const Vec3vf<N> Pr = t1*Vec3vf<N>(dir);
- const Vec3vf<N> Pl = madd(u1_o,p1-p0,p0);
- Ng1_o = Pr-Pl;
- }
-
- t_o.lower = select(valid, t0, vfloat<N>(pos_inf));
- t_o.upper = select(valid, t1, vfloat<N>(neg_inf));
-
- /* special case for rays that are parallel to the cylinder */
- const vfloat<N> eps = 16.0f*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
- vbool<N> validt = valid & (abs(A) < eps);
- if (unlikely(any(validt)))
- {
- vbool<N> inside = C <= 0.0f;
- t_o.lower = select(validt,select(inside,vfloat<N>(neg_inf),vfloat<N>(pos_inf)),t_o.lower);
- t_o.upper = select(validt,select(inside,vfloat<N>(pos_inf),vfloat<N>(neg_inf)),t_o.upper);
- valid &= !validt | inside;
- }
- return valid;
- }
-
- __forceinline vbool<N> intersect(const Vec3fa& org_i, const Vec3fa& dir, BBox<vfloat<N>>& t_o) const
- {
- vfloat<N> u0_o; Vec3vf<N> Ng0_o;
- vfloat<N> u1_o; Vec3vf<N> Ng1_o;
- return intersect(org_i,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
- }
- };
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/geometry/disc_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/disc_intersector.h
deleted file mode 100644
index e8305780e5..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/disc_intersector.h
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "../common/scene_points.h"
-#include "curve_intersector_precalculations.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct DiscIntersectorHitM
- {
- __forceinline DiscIntersectorHitM() {}
-
- __forceinline DiscIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
- : vu(u), vv(v), vt(t), vNg(Ng)
- {
- }
-
- __forceinline void finalize() {}
-
- __forceinline Vec2f uv(const size_t i) const
- {
- return Vec2f(vu[i], vv[i]);
- }
- __forceinline float t(const size_t i) const
- {
- return vt[i];
- }
- __forceinline Vec3fa Ng(const size_t i) const
- {
- return Vec3fa(vNg.x[i], vNg.y[i], vNg.z[i]);
- }
-
- public:
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- template<int M>
- struct DiscIntersector1
- {
- typedef CurvePrecalculations1 Precalculations;
-
- template<typename Epilog>
- static __forceinline bool intersect(
- const vbool<M>& valid_i,
- Ray& ray,
- IntersectContext* context,
- const Points* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i,
- const Epilog& epilog)
- {
- vbool<M> valid = valid_i;
-
- const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
- const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
- const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
-
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec3vf<M> center = v0.xyz();
- const vfloat<M> radius = v0.w;
-
- const Vec3vf<M> c0 = center - ray_org;
- const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
-
- valid &= (vfloat<M>(ray.tnear()) <= projC0) & (projC0 <= vfloat<M>(ray.tfar));
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
- valid &= projC0 > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR) * radius * pre.depth_scale; // ignore self intersections
- if (unlikely(none(valid)))
- return false;
-
- const Vec3vf<M> perp = c0 - projC0 * ray_dir;
- const vfloat<M> l2 = dot(perp, perp);
- const vfloat<M> r2 = radius * radius;
- valid &= (l2 <= r2);
- if (unlikely(none(valid)))
- return false;
-
- DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
- return epilog(valid, hit);
- }
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- Ray& ray,
- IntersectContext* context,
- const Points* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i,
- const Vec3vf<M>& normal,
- const Epilog& epilog)
- {
- vbool<M> valid = valid_i;
- const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
-
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec3vf<M> center = v0.xyz();
- const vfloat<M> radius = v0.w;
-
- vfloat<M> divisor = dot(Vec3vf<M>((Vec3fa)ray.dir), normal);
- const vbool<M> parallel = divisor == vfloat<M>(0.f);
- valid &= !parallel;
- divisor = select(parallel, 1.f, divisor); // prevent divide by zero
-
- vfloat<M> t = dot(center - Vec3vf<M>((Vec3fa)ray.org), Vec3vf<M>(normal)) / divisor;
-
- valid &= (vfloat<M>(ray.tnear()) <= t) & (t <= vfloat<M>(ray.tfar));
- if (unlikely(none(valid)))
- return false;
-
- Vec3vf<M> intersection = Vec3vf<M>((Vec3fa)ray.org) + Vec3vf<M>((Vec3fa)ray.dir) * t;
- vfloat<M> dist2 = dot(intersection - center, intersection - center);
- valid &= dist2 < radius * radius;
- if (unlikely(none(valid)))
- return false;
-
- DiscIntersectorHitM<M> hit(zero, zero, t, normal);
- return epilog(valid, hit);
- }
- };
-
- template<int M, int K>
- struct DiscIntersectorK
- {
- typedef CurvePrecalculationsK<K> Precalculations;
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- RayK<K>& ray,
- size_t k,
- IntersectContext* context,
- const Points* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i,
- const Epilog& epilog)
- {
- vbool<M> valid = valid_i;
-
- const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
- const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
-
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec3vf<M> center = v0.xyz();
- const vfloat<M> radius = v0.w;
-
- const Vec3vf<M> c0 = center - ray_org;
- const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
-
- valid &= (vfloat<M>(ray.tnear()[k]) <= projC0) & (projC0 <= vfloat<M>(ray.tfar[k]));
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
- valid &= projC0 > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR) * radius * pre.depth_scale[k]; // ignore self intersections
- if (unlikely(none(valid)))
- return false;
-
- const Vec3vf<M> perp = c0 - projC0 * ray_dir;
- const vfloat<M> l2 = dot(perp, perp);
- const vfloat<M> r2 = radius * radius;
- valid &= (l2 <= r2);
- if (unlikely(none(valid)))
- return false;
-
- DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
- return epilog(valid, hit);
- }
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- RayK<K>& ray,
- size_t k,
- IntersectContext* context,
- const Points* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i,
- const Vec3vf<M>& normal,
- const Epilog& epilog)
- {
- vbool<M> valid = valid_i;
- const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
-
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec3vf<M> center = v0.xyz();
- const vfloat<M> radius = v0.w;
-
- vfloat<M> divisor = dot(Vec3vf<M>(ray_dir), normal);
- const vbool<M> parallel = divisor == vfloat<M>(0.f);
- valid &= !parallel;
- divisor = select(parallel, 1.f, divisor); // prevent divide by zero
-
- vfloat<M> t = dot(center - Vec3vf<M>(ray_org), Vec3vf<M>(normal)) / divisor;
-
- valid &= (vfloat<M>(ray.tnear()[k]) <= t) & (t <= vfloat<M>(ray.tfar[k]));
- if (unlikely(none(valid)))
- return false;
-
- Vec3vf<M> intersection = Vec3vf<M>(ray_org) + Vec3vf<M>(ray_dir) * t;
- vfloat<M> dist2 = dot(intersection - center, intersection - center);
- valid &= dist2 < radius * radius;
- if (unlikely(none(valid)))
- return false;
-
- DiscIntersectorHitM<M> hit(zero, zero, t, normal);
- return epilog(valid, hit);
- }
- };
- } // namespace isa
-} // namespace embree
diff --git a/thirdparty/embree-aarch64/kernels/geometry/disci_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/disci_intersector.h
deleted file mode 100644
index e1dc3aa98e..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/disci_intersector.h
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "disc_intersector.h"
-#include "intersector_epilog.h"
-#include "pointi.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M, int Mx, bool filter>
- struct DiscMiIntersector1
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre,
- RayHit& ray,
- IntersectContext* context,
- const Primitive& Disc)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Disc.gather(v0, geom);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- DiscIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, Intersect1EpilogM<M, Mx, filter>(ray, context, Disc.geomID(), Disc.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre,
- Ray& ray,
- IntersectContext* context,
- const Primitive& Disc)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Disc.gather(v0, geom);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- return DiscIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, Occluded1EpilogM<M, Mx, filter>(ray, context, Disc.geomID(), Disc.primID()));
- }
- };
-
- template<int M, int Mx, bool filter>
- struct DiscMiMBIntersector1
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre,
- RayHit& ray,
- IntersectContext* context,
- const Primitive& Disc)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Disc.gather(v0, geom, ray.time());
- const vbool<Mx> valid = Disc.template valid<Mx>();
- DiscIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, Intersect1EpilogM<M, Mx, filter>(ray, context, Disc.geomID(), Disc.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre,
- Ray& ray,
- IntersectContext* context,
- const Primitive& Disc)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Disc.gather(v0, geom, ray.time());
- const vbool<Mx> valid = Disc.template valid<Mx>();
- return DiscIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, Occluded1EpilogM<M, Mx, filter>(ray, context, Disc.geomID(), Disc.primID()));
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct DiscMiIntersectorK
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(
- const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Disc.gather(v0, geom);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- DiscIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0,
- Intersect1KEpilogM<M, Mx, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
- }
-
- static __forceinline bool occluded(
- const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Disc.gather(v0, geom);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- return DiscIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0,
- Occluded1KEpilogM<M, Mx, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct DiscMiMBIntersectorK
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(
- const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Disc.gather(v0, geom, ray.time()[k]);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- DiscIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0,
- Intersect1KEpilogM<M, Mx, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
- }
-
- static __forceinline bool occluded(
- const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Disc.gather(v0, geom, ray.time()[k]);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- return DiscIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0, Occluded1KEpilogM<M, Mx, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
- }
- };
-
- template<int M, int Mx, bool filter>
- struct OrientedDiscMiIntersector1
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre,
- RayHit& ray,
- IntersectContext* context,
- const Primitive& Disc)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Vec3vf<M> n0;
- Disc.gather(v0, n0, geom);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- DiscIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, n0, Intersect1EpilogM<M, Mx, filter>(ray, context, Disc.geomID(), Disc.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre,
- Ray& ray,
- IntersectContext* context,
- const Primitive& Disc)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Vec3vf<M> n0;
- Disc.gather(v0, n0, geom);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- return DiscIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, n0, Occluded1EpilogM<M, Mx, filter>(ray, context, Disc.geomID(), Disc.primID()));
- }
- };
-
- template<int M, int Mx, bool filter>
- struct OrientedDiscMiMBIntersector1
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre,
- RayHit& ray,
- IntersectContext* context,
- const Primitive& Disc)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Vec3vf<M> n0;
- Disc.gather(v0, n0, geom, ray.time());
- const vbool<Mx> valid = Disc.template valid<Mx>();
- DiscIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, n0, Intersect1EpilogM<M, Mx, filter>(ray, context, Disc.geomID(), Disc.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre,
- Ray& ray,
- IntersectContext* context,
- const Primitive& Disc)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Vec3vf<M> n0;
- Disc.gather(v0, n0, geom, ray.time());
- const vbool<Mx> valid = Disc.template valid<Mx>();
- return DiscIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, n0, Occluded1EpilogM<M, Mx, filter>(ray, context, Disc.geomID(), Disc.primID()));
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct OrientedDiscMiIntersectorK
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(
- const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Vec3vf<M> n0;
- Disc.gather(v0, n0, geom);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- DiscIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0, n0,
- Intersect1KEpilogM<M, Mx, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
- }
-
- static __forceinline bool occluded(
- const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Vec3vf<M> n0;
- Disc.gather(v0, n0, geom);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- return DiscIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0, n0,
- Occluded1KEpilogM<M, Mx, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct OrientedDiscMiMBIntersectorK
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(
- const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Vec3vf<M> n0;
- Disc.gather(v0, n0, geom, ray.time()[k]);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- DiscIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0, n0,
- Intersect1KEpilogM<M, Mx, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
- }
-
- static __forceinline bool occluded(
- const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(Disc.geomID());
- Vec4vf<M> v0; Vec3vf<M> n0;
- Disc.gather(v0, n0, geom, ray.time()[k]);
- const vbool<Mx> valid = Disc.template valid<Mx>();
- return DiscIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0, n0,
- Occluded1KEpilogM<M, Mx, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
- }
- };
- } // namespace isa
-} // namespace embree
diff --git a/thirdparty/embree-aarch64/kernels/geometry/filter.h b/thirdparty/embree-aarch64/kernels/geometry/filter.h
deleted file mode 100644
index 4cdf7a395a..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/filter.h
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/geometry.h"
-#include "../common/ray.h"
-#include "../common/hit.h"
-#include "../common/context.h"
-
-namespace embree
-{
- namespace isa
- {
- __forceinline bool runIntersectionFilter1Helper(RTCFilterFunctionNArguments* args, const Geometry* const geometry, IntersectContext* context)
- {
- if (geometry->intersectionFilterN)
- {
- assert(context->scene->hasGeometryFilterFunction());
- geometry->intersectionFilterN(args);
-
- if (args->valid[0] == 0)
- return false;
- }
-
- if (context->user->filter) {
- assert(context->scene->hasContextFilterFunction());
- context->user->filter(args);
-
- if (args->valid[0] == 0)
- return false;
- }
-
- copyHitToRay(*(RayHit*)args->ray,*(Hit*)args->hit);
- return true;
- }
-
- __forceinline bool runIntersectionFilter1(const Geometry* const geometry, RayHit& ray, IntersectContext* context, Hit& hit)
- {
- RTCFilterFunctionNArguments args;
- int mask = -1;
- args.valid = &mask;
- args.geometryUserPtr = geometry->userPtr;
- args.context = context->user;
- args.ray = (RTCRayN*)&ray;
- args.hit = (RTCHitN*)&hit;
- args.N = 1;
- return runIntersectionFilter1Helper(&args,geometry,context);
- }
-
- __forceinline void reportIntersection1(IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args)
- {
-#if defined(EMBREE_FILTER_FUNCTION)
- IntersectContext* MAYBE_UNUSED context = args->internal_context;
- const Geometry* const geometry = args->geometry;
- if (geometry->intersectionFilterN) {
- assert(context->scene->hasGeometryFilterFunction());
- geometry->intersectionFilterN(filter_args);
- }
-
- //if (args->valid[0] == 0)
- // return;
-
- if (context->user->filter) {
- assert(context->scene->hasContextFilterFunction());
- context->user->filter(filter_args);
- }
-#endif
- }
-
- __forceinline bool runOcclusionFilter1Helper(RTCFilterFunctionNArguments* args, const Geometry* const geometry, IntersectContext* context)
- {
- if (geometry->occlusionFilterN)
- {
- assert(context->scene->hasGeometryFilterFunction());
- geometry->occlusionFilterN(args);
-
- if (args->valid[0] == 0)
- return false;
- }
-
- if (context->user->filter) {
- assert(context->scene->hasContextFilterFunction());
- context->user->filter(args);
-
- if (args->valid[0] == 0)
- return false;
- }
- return true;
- }
-
- __forceinline bool runOcclusionFilter1(const Geometry* const geometry, Ray& ray, IntersectContext* context, Hit& hit)
- {
- RTCFilterFunctionNArguments args;
- int mask = -1;
- args.valid = &mask;
- args.geometryUserPtr = geometry->userPtr;
- args.context = context->user;
- args.ray = (RTCRayN*)&ray;
- args.hit = (RTCHitN*)&hit;
- args.N = 1;
- return runOcclusionFilter1Helper(&args,geometry,context);
- }
-
- __forceinline void reportOcclusion1(OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args)
- {
-#if defined(EMBREE_FILTER_FUNCTION)
- IntersectContext* MAYBE_UNUSED context = args->internal_context;
- const Geometry* const geometry = args->geometry;
- if (geometry->occlusionFilterN) {
- assert(context->scene->hasGeometryFilterFunction());
- geometry->occlusionFilterN(filter_args);
- }
-
- //if (args->valid[0] == 0)
- // return false;
-
- if (context->user->filter) {
- assert(context->scene->hasContextFilterFunction());
- context->user->filter(filter_args);
- }
-#endif
- }
-
- template<int K>
- __forceinline vbool<K> runIntersectionFilterHelper(RTCFilterFunctionNArguments* args, const Geometry* const geometry, IntersectContext* context)
- {
- vint<K>* mask = (vint<K>*) args->valid;
- if (geometry->intersectionFilterN)
- {
- assert(context->scene->hasGeometryFilterFunction());
- geometry->intersectionFilterN(args);
- }
-
- vbool<K> valid_o = *mask != vint<K>(zero);
- if (none(valid_o)) return valid_o;
-
- if (context->user->filter) {
- assert(context->scene->hasContextFilterFunction());
- context->user->filter(args);
- }
-
- valid_o = *mask != vint<K>(zero);
- if (none(valid_o)) return valid_o;
-
- copyHitToRay(valid_o,*(RayHitK<K>*)args->ray,*(HitK<K>*)args->hit);
- return valid_o;
- }
-
- template<int K>
- __forceinline vbool<K> runIntersectionFilter(const vbool<K>& valid, const Geometry* const geometry, RayHitK<K>& ray, IntersectContext* context, HitK<K>& hit)
- {
- RTCFilterFunctionNArguments args;
- vint<K> mask = valid.mask32();
- args.valid = (int*)&mask;
- args.geometryUserPtr = geometry->userPtr;
- args.context = context->user;
- args.ray = (RTCRayN*)&ray;
- args.hit = (RTCHitN*)&hit;
- args.N = K;
- return runIntersectionFilterHelper<K>(&args,geometry,context);
- }
-
- template<int K>
- __forceinline vbool<K> runOcclusionFilterHelper(RTCFilterFunctionNArguments* args, const Geometry* const geometry, IntersectContext* context)
- {
- vint<K>* mask = (vint<K>*) args->valid;
- if (geometry->occlusionFilterN)
- {
- assert(context->scene->hasGeometryFilterFunction());
- geometry->occlusionFilterN(args);
- }
-
- vbool<K> valid_o = *mask != vint<K>(zero);
-
- if (none(valid_o)) return valid_o;
-
- if (context->user->filter) {
- assert(context->scene->hasContextFilterFunction());
- context->user->filter(args);
- }
-
- valid_o = *mask != vint<K>(zero);
-
- RayK<K>* ray = (RayK<K>*) args->ray;
- ray->tfar = select(valid_o, vfloat<K>(neg_inf), ray->tfar);
- return valid_o;
- }
-
- template<int K>
- __forceinline vbool<K> runOcclusionFilter(const vbool<K>& valid, const Geometry* const geometry, RayK<K>& ray, IntersectContext* context, HitK<K>& hit)
- {
- RTCFilterFunctionNArguments args;
- vint<K> mask = valid.mask32();
- args.valid = (int*)&mask;
- args.geometryUserPtr = geometry->userPtr;
- args.context = context->user;
- args.ray = (RTCRayN*)&ray;
- args.hit = (RTCHitN*)&hit;
- args.N = K;
- return runOcclusionFilterHelper<K>(&args,geometry,context);
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/grid_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/grid_intersector.h
deleted file mode 100644
index 46a0af0827..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/grid_intersector.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "grid_soa.h"
-#include "grid_soa_intersector1.h"
-#include "grid_soa_intersector_packet.h"
-#include "../common/ray.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename T>
- class SubdivPatch1Precalculations : public T
- {
- public:
- __forceinline SubdivPatch1Precalculations (const Ray& ray, const void* ptr)
- : T(ray,ptr) {}
- };
-
- template<int K, typename T>
- class SubdivPatch1PrecalculationsK : public T
- {
- public:
- __forceinline SubdivPatch1PrecalculationsK (const vbool<K>& valid, RayK<K>& ray)
- : T(valid,ray) {}
- };
-
- class Grid1Intersector1
- {
- public:
- typedef GridSOA Primitive;
- typedef Grid1Precalculations<GridSOAIntersector1::Precalculations> Precalculations;
-
- /*! Intersect a ray with the primitive. */
- static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
- {
- GridSOAIntersector1::intersect(pre,ray,context,prim,lazy_node);
- }
- static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, size_t& lazy_node) {
- intersect(pre,ray,context,prim,ty,lazy_node);
- }
-
- /*! Test if the ray is occluded by the primitive */
- static __forceinline bool occluded(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
- {
- GridSOAIntersector1::occluded(pre,ray,context,prim,lazy_node);
- }
- static __forceinline bool occluded(Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, size_t& lazy_node) {
- return occluded(pre,ray,context,prim,ty,lazy_node);
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t ty, size_t& lazy_node) {
- assert(false && "not implemented");
- return false;
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, size_t ty0, const Primitive* prim, size_t ty, size_t& lazy_node) {
- assert(false && "not implemented");
- return false;
- }
- };
-
- template <int K>
- struct GridIntersectorK
- {
- typedef GridSOA Primitive;
- typedef SubdivPatch1PrecalculationsK<K,typename GridSOAIntersectorK<K>::Precalculations> Precalculations;
-
-
- static __forceinline void intersect(const vbool<K>& valid, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
- {
- GridSOAIntersectorK<K>::intersect(valid,pre,ray,context,prim,lazy_node);
- }
-
- static __forceinline vbool<K> occluded(const vbool<K>& valid, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
- {
- GridSOAIntersectorK<K>::occluded(valid,pre,ray,context,prim,lazy_node);
- }
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
- {
- GridSOAIntersectorK<K>::intersect(pre,ray,k,context,prim,lazy_node);
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
- {
- GridSOAIntersectorK<K>::occluded(pre,ray,k,context,prim,lazy_node);
- }
- };
-
- typedef Grid1IntersectorK<4> SubdivPatch1Intersector4;
- typedef Grid1IntersectorK<8> SubdivPatch1Intersector8;
- typedef Grid1IntersectorK<16> SubdivPatch1Intersector16;
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/grid_soa.h b/thirdparty/embree-aarch64/kernels/geometry/grid_soa.h
deleted file mode 100644
index d3b275586c..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/grid_soa.h
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "../common/scene_subdiv_mesh.h"
-#include "../bvh/bvh.h"
-#include "../subdiv/tessellation.h"
-#include "../subdiv/tessellation_cache.h"
-#include "subdivpatch1.h"
-
-namespace embree
-{
- namespace isa
- {
- class GridSOA
- {
- public:
-
- /*! GridSOA constructor */
- GridSOA(const SubdivPatch1Base* patches, const unsigned time_steps,
- const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
- const SubdivMesh* const geom, const size_t totalBvhBytes, const size_t gridBytes, BBox3fa* bounds_o = nullptr);
-
- /*! Subgrid creation */
- template<typename Allocator>
- static GridSOA* create(const SubdivPatch1Base* patches, const unsigned time_steps,
- unsigned x0, unsigned x1, unsigned y0, unsigned y1,
- const Scene* scene, Allocator& alloc, BBox3fa* bounds_o = nullptr)
- {
- const unsigned width = x1-x0+1;
- const unsigned height = y1-y0+1;
- const GridRange range(0,width-1,0,height-1);
- size_t bvhBytes = 0;
- if (time_steps == 1)
- bvhBytes = getBVHBytes(range,sizeof(BVH4::AABBNode),0);
- else {
- bvhBytes = (time_steps-1)*getBVHBytes(range,sizeof(BVH4::AABBNodeMB),0);
- bvhBytes += getTemporalBVHBytes(make_range(0,int(time_steps-1)),sizeof(BVH4::AABBNodeMB4D));
- }
- const size_t gridBytes = 4*size_t(width)*size_t(height)*sizeof(float);
- size_t rootBytes = time_steps*sizeof(BVH4::NodeRef);
-#if !defined(__X86_64__) && !defined(__aarch64__)
- rootBytes += 4; // We read 2 elements behind the grid. As we store at least 8 root bytes after the grid we are fine in 64 bit mode. But in 32 bit mode we have to do additional padding.
-#endif
- void* data = alloc(offsetof(GridSOA,data)+bvhBytes+time_steps*gridBytes+rootBytes);
- assert(data);
- return new (data) GridSOA(patches,time_steps,x0,x1,y0,y1,patches->grid_u_res,patches->grid_v_res,scene->get<SubdivMesh>(patches->geomID()),bvhBytes,gridBytes,bounds_o);
- }
-
- /*! Grid creation */
- template<typename Allocator>
- static GridSOA* create(const SubdivPatch1Base* const patches, const unsigned time_steps,
- const Scene* scene, const Allocator& alloc, BBox3fa* bounds_o = nullptr)
- {
- return create(patches,time_steps,0,patches->grid_u_res-1,0,patches->grid_v_res-1,scene,alloc,bounds_o);
- }
-
- /*! returns reference to root */
- __forceinline BVH4::NodeRef& root(size_t t = 0) { return (BVH4::NodeRef&)data[rootOffset + t*sizeof(BVH4::NodeRef)]; }
- __forceinline const BVH4::NodeRef& root(size_t t = 0) const { return (BVH4::NodeRef&)data[rootOffset + t*sizeof(BVH4::NodeRef)]; }
-
- /*! returns pointer to BVH array */
- __forceinline int8_t* bvhData() { return &data[0]; }
- __forceinline const int8_t* bvhData() const { return &data[0]; }
-
- /*! returns pointer to Grid array */
- __forceinline float* gridData(size_t t = 0) { return (float*) &data[gridOffset + t*gridBytes]; }
- __forceinline const float* gridData(size_t t = 0) const { return (float*) &data[gridOffset + t*gridBytes]; }
-
- __forceinline void* encodeLeaf(size_t u, size_t v) {
- return (void*) (16*(v * width + u + 1)); // +1 to not create empty leaf
- }
- __forceinline float* decodeLeaf(size_t t, const void* ptr) {
- return gridData(t) + (((size_t) (ptr) >> 4) - 1);
- }
-
- /*! returns the size of the BVH over the grid in bytes */
- static size_t getBVHBytes(const GridRange& range, const size_t nodeBytes, const size_t leafBytes);
-
- /*! returns the size of the temporal BVH over the time range BVHs */
- static size_t getTemporalBVHBytes(const range<int> time_range, const size_t nodeBytes);
-
- /*! calculates bounding box of grid range */
- __forceinline BBox3fa calculateBounds(size_t time, const GridRange& range) const
- {
- const float* const grid_array = gridData(time);
- const float* const grid_x_array = grid_array + 0 * dim_offset;
- const float* const grid_y_array = grid_array + 1 * dim_offset;
- const float* const grid_z_array = grid_array + 2 * dim_offset;
-
- /* compute the bounds just for the range! */
- BBox3fa bounds( empty );
- for (unsigned v = range.v_start; v<=range.v_end; v++)
- {
- for (unsigned u = range.u_start; u<=range.u_end; u++)
- {
- const float x = grid_x_array[ v * width + u];
- const float y = grid_y_array[ v * width + u];
- const float z = grid_z_array[ v * width + u];
- bounds.extend( Vec3fa(x,y,z) );
- }
- }
- assert(is_finite(bounds));
- return bounds;
- }
-
- /*! Evaluates grid over patch and builds BVH4 tree over the grid. */
- std::pair<BVH4::NodeRef,BBox3fa> buildBVH(BBox3fa* bounds_o);
-
- /*! Create BVH4 tree over grid. */
- std::pair<BVH4::NodeRef,BBox3fa> buildBVH(const GridRange& range, size_t& allocator);
-
- /*! Evaluates grid over patch and builds MSMBlur BVH4 tree over the grid. */
- std::pair<BVH4::NodeRef,LBBox3fa> buildMSMBlurBVH(const range<int> time_range, BBox3fa* bounds_o);
-
- /*! Create MBlur BVH4 tree over grid. */
- std::pair<BVH4::NodeRef,LBBox3fa> buildMBlurBVH(size_t time, const GridRange& range, size_t& allocator);
-
- /*! Create MSMBlur BVH4 tree over grid. */
- std::pair<BVH4::NodeRef,LBBox3fa> buildMSMBlurBVH(const range<int> time_range, size_t& allocator, BBox3fa* bounds_o);
-
- template<typename Loader>
- struct MapUV
- {
- typedef typename Loader::vfloat vfloat;
- const float* const grid_uv;
- size_t line_offset;
- size_t lines;
-
- __forceinline MapUV(const float* const grid_uv, size_t line_offset, const size_t lines)
- : grid_uv(grid_uv), line_offset(line_offset), lines(lines) {}
-
- __forceinline void operator() (vfloat& u, vfloat& v) const {
- const Vec3<vfloat> tri_v012_uv = Loader::gather(grid_uv,line_offset,lines);
- const Vec2<vfloat> uv0 = GridSOA::decodeUV(tri_v012_uv[0]);
- const Vec2<vfloat> uv1 = GridSOA::decodeUV(tri_v012_uv[1]);
- const Vec2<vfloat> uv2 = GridSOA::decodeUV(tri_v012_uv[2]);
- const Vec2<vfloat> uv = u * uv1 + v * uv2 + (1.0f-u-v) * uv0;
- u = uv[0];v = uv[1];
- }
- };
-
- struct Gather2x3
- {
- enum { M = 4 };
- typedef vbool4 vbool;
- typedef vint4 vint;
- typedef vfloat4 vfloat;
-
- static __forceinline const Vec3vf4 gather(const float* const grid, const size_t line_offset, const size_t lines)
- {
- vfloat4 r0 = vfloat4::loadu(grid + 0*line_offset);
- vfloat4 r1 = vfloat4::loadu(grid + 1*line_offset); // this accesses 2 elements too much in case of 2x2 grid, but this is ok as we ensure enough padding after the grid
- if (unlikely(line_offset == 2))
- {
- r0 = shuffle<0,1,1,1>(r0);
- r1 = shuffle<0,1,1,1>(r1);
- }
- return Vec3vf4(unpacklo(r0,r1), // r00, r10, r01, r11
- shuffle<1,1,2,2>(r0), // r01, r01, r02, r02
- shuffle<0,1,1,2>(r1)); // r10, r11, r11, r12
- }
-
- static __forceinline void gather(const float* const grid_x,
- const float* const grid_y,
- const float* const grid_z,
- const size_t line_offset,
- const size_t lines,
- Vec3vf4& v0_o,
- Vec3vf4& v1_o,
- Vec3vf4& v2_o)
- {
- const Vec3vf4 tri_v012_x = gather(grid_x,line_offset,lines);
- const Vec3vf4 tri_v012_y = gather(grid_y,line_offset,lines);
- const Vec3vf4 tri_v012_z = gather(grid_z,line_offset,lines);
- v0_o = Vec3vf4(tri_v012_x[0],tri_v012_y[0],tri_v012_z[0]);
- v1_o = Vec3vf4(tri_v012_x[1],tri_v012_y[1],tri_v012_z[1]);
- v2_o = Vec3vf4(tri_v012_x[2],tri_v012_y[2],tri_v012_z[2]);
- }
- };
-
-#if defined (__AVX__)
- struct Gather3x3
- {
- enum { M = 8 };
- typedef vbool8 vbool;
- typedef vint8 vint;
- typedef vfloat8 vfloat;
-
- static __forceinline const Vec3vf8 gather(const float* const grid, const size_t line_offset, const size_t lines)
- {
- vfloat4 ra = vfloat4::loadu(grid + 0*line_offset);
- vfloat4 rb = vfloat4::loadu(grid + 1*line_offset); // this accesses 2 elements too much in case of 2x2 grid, but this is ok as we ensure enough padding after the grid
- vfloat4 rc;
- if (likely(lines > 2))
- rc = vfloat4::loadu(grid + 2*line_offset);
- else
- rc = rb;
-
- if (unlikely(line_offset == 2))
- {
- ra = shuffle<0,1,1,1>(ra);
- rb = shuffle<0,1,1,1>(rb);
- rc = shuffle<0,1,1,1>(rc);
- }
-
- const vfloat8 r0 = vfloat8(ra,rb);
- const vfloat8 r1 = vfloat8(rb,rc);
- return Vec3vf8(unpacklo(r0,r1), // r00, r10, r01, r11, r10, r20, r11, r21
- shuffle<1,1,2,2>(r0), // r01, r01, r02, r02, r11, r11, r12, r12
- shuffle<0,1,1,2>(r1)); // r10, r11, r11, r12, r20, r21, r21, r22
- }
-
- static __forceinline void gather(const float* const grid_x,
- const float* const grid_y,
- const float* const grid_z,
- const size_t line_offset,
- const size_t lines,
- Vec3vf8& v0_o,
- Vec3vf8& v1_o,
- Vec3vf8& v2_o)
- {
- const Vec3vf8 tri_v012_x = gather(grid_x,line_offset,lines);
- const Vec3vf8 tri_v012_y = gather(grid_y,line_offset,lines);
- const Vec3vf8 tri_v012_z = gather(grid_z,line_offset,lines);
- v0_o = Vec3vf8(tri_v012_x[0],tri_v012_y[0],tri_v012_z[0]);
- v1_o = Vec3vf8(tri_v012_x[1],tri_v012_y[1],tri_v012_z[1]);
- v2_o = Vec3vf8(tri_v012_x[2],tri_v012_y[2],tri_v012_z[2]);
- }
- };
-#endif
-
- template<typename vfloat>
- static __forceinline Vec2<vfloat> decodeUV(const vfloat& uv)
- {
- typedef typename vfloat::Int vint;
- const vint iu = asInt(uv) & 0xffff;
- const vint iv = srl(asInt(uv),16);
- const vfloat u = (vfloat)iu * vfloat(8.0f/0x10000);
- const vfloat v = (vfloat)iv * vfloat(8.0f/0x10000);
- return Vec2<vfloat>(u,v);
- }
-
- __forceinline unsigned int geomID() const {
- return _geomID;
- }
-
- __forceinline unsigned int primID() const {
- return _primID;
- }
-
- public:
- BVH4::NodeRef troot;
-#if !defined(__X86_64__) && !defined(__aarch64__)
- unsigned align1;
-#endif
- unsigned time_steps;
- unsigned width;
-
- unsigned height;
- unsigned dim_offset;
- unsigned _geomID;
- unsigned _primID;
-
- unsigned align2;
- unsigned gridOffset;
- unsigned gridBytes;
- unsigned rootOffset;
-
- int8_t data[1]; //!< after the struct we first store the BVH, then the grid, and finally the roots
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/grid_soa_intersector1.h b/thirdparty/embree-aarch64/kernels/geometry/grid_soa_intersector1.h
deleted file mode 100644
index 2ed922a5ae..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/grid_soa_intersector1.h
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "grid_soa.h"
-#include "../common/ray.h"
-#include "triangle_intersector_pluecker.h"
-
-namespace embree
-{
- namespace isa
- {
- class GridSOAIntersector1
- {
- public:
- typedef void Primitive;
-
- class Precalculations
- {
- public:
- __forceinline Precalculations (const Ray& ray, const void* ptr)
- : grid(nullptr) {}
-
- public:
- GridSOA* grid;
- int itime;
- float ftime;
- };
-
- template<typename Loader>
- static __forceinline void intersect(RayHit& ray,
- IntersectContext* context,
- const float* const grid_x,
- const size_t line_offset,
- const size_t lines,
- Precalculations& pre)
- {
- typedef typename Loader::vfloat vfloat;
- const size_t dim_offset = pre.grid->dim_offset;
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
- Vec3<vfloat> v0, v1, v2;
- Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,v0,v1,v2);
- GridSOA::MapUV<Loader> mapUV(grid_uv,line_offset,lines);
- PlueckerIntersector1<Loader::M> intersector(ray,nullptr);
- intersector.intersect(ray,v0,v1,v2,mapUV,Intersect1EpilogMU<Loader::M,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
- };
-
- template<typename Loader>
- static __forceinline bool occluded(Ray& ray,
- IntersectContext* context,
- const float* const grid_x,
- const size_t line_offset,
- const size_t lines,
- Precalculations& pre)
- {
- typedef typename Loader::vfloat vfloat;
- const size_t dim_offset = pre.grid->dim_offset;
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- Vec3<vfloat> v0, v1, v2;
- Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,v0,v1,v2);
-
- GridSOA::MapUV<Loader> mapUV(grid_uv,line_offset,lines);
- PlueckerIntersector1<Loader::M> intersector(ray,nullptr);
- return intersector.intersect(ray,v0,v1,v2,mapUV,Occluded1EpilogMU<Loader::M,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
- }
-
- /*! Intersect a ray with the primitive. */
- static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t line_offset = pre.grid->width;
- const size_t lines = pre.grid->height;
- const float* const grid_x = pre.grid->decodeLeaf(0,prim);
-
-#if defined(__AVX__)
- intersect<GridSOA::Gather3x3>( ray, context, grid_x, line_offset, lines, pre);
-#else
- intersect<GridSOA::Gather2x3>(ray, context, grid_x , line_offset, lines, pre);
- if (likely(lines > 2))
- intersect<GridSOA::Gather2x3>(ray, context, grid_x+line_offset, line_offset, lines, pre);
-#endif
- }
-
- /*! Test if the ray is occluded by the primitive */
- static __forceinline bool occluded(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t line_offset = pre.grid->width;
- const size_t lines = pre.grid->height;
- const float* const grid_x = pre.grid->decodeLeaf(0,prim);
-
-#if defined(__AVX__)
- return occluded<GridSOA::Gather3x3>( ray, context, grid_x, line_offset, lines, pre);
-#else
- if (occluded<GridSOA::Gather2x3>(ray, context, grid_x , line_offset, lines, pre)) return true;
- if (likely(lines > 2))
- if (occluded<GridSOA::Gather2x3>(ray, context, grid_x+line_offset, line_offset, lines, pre)) return true;
-#endif
- return false;
- }
- };
-
- class GridSOAMBIntersector1
- {
- public:
- typedef void Primitive;
- typedef GridSOAIntersector1::Precalculations Precalculations;
-
- template<typename Loader>
- static __forceinline void intersect(RayHit& ray, const float ftime,
- IntersectContext* context,
- const float* const grid_x,
- const size_t line_offset,
- const size_t lines,
- Precalculations& pre)
- {
- typedef typename Loader::vfloat vfloat;
- const size_t dim_offset = pre.grid->dim_offset;
- const size_t grid_offset = pre.grid->gridBytes >> 2;
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- Vec3<vfloat> a0, a1, a2;
- Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,a0,a1,a2);
-
- Vec3<vfloat> b0, b1, b2;
- Loader::gather(grid_x+grid_offset,grid_y+grid_offset,grid_z+grid_offset,line_offset,lines,b0,b1,b2);
-
- Vec3<vfloat> v0 = lerp(a0,b0,vfloat(ftime));
- Vec3<vfloat> v1 = lerp(a1,b1,vfloat(ftime));
- Vec3<vfloat> v2 = lerp(a2,b2,vfloat(ftime));
-
- GridSOA::MapUV<Loader> mapUV(grid_uv,line_offset,lines);
- PlueckerIntersector1<Loader::M> intersector(ray,nullptr);
- intersector.intersect(ray,v0,v1,v2,mapUV,Intersect1EpilogMU<Loader::M,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
- };
-
- template<typename Loader>
- static __forceinline bool occluded(Ray& ray, const float ftime,
- IntersectContext* context,
- const float* const grid_x,
- const size_t line_offset,
- const size_t lines,
- Precalculations& pre)
- {
- typedef typename Loader::vfloat vfloat;
- const size_t dim_offset = pre.grid->dim_offset;
- const size_t grid_offset = pre.grid->gridBytes >> 2;
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- Vec3<vfloat> a0, a1, a2;
- Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,a0,a1,a2);
-
- Vec3<vfloat> b0, b1, b2;
- Loader::gather(grid_x+grid_offset,grid_y+grid_offset,grid_z+grid_offset,line_offset,lines,b0,b1,b2);
-
- Vec3<vfloat> v0 = lerp(a0,b0,vfloat(ftime));
- Vec3<vfloat> v1 = lerp(a1,b1,vfloat(ftime));
- Vec3<vfloat> v2 = lerp(a2,b2,vfloat(ftime));
-
- GridSOA::MapUV<Loader> mapUV(grid_uv,line_offset,lines);
- PlueckerIntersector1<Loader::M> intersector(ray,nullptr);
- return intersector.intersect(ray,v0,v1,v2,mapUV,Occluded1EpilogMU<Loader::M,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
- }
-
- /*! Intersect a ray with the primitive. */
- static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t line_offset = pre.grid->width;
- const size_t lines = pre.grid->height;
- const float* const grid_x = pre.grid->decodeLeaf(pre.itime,prim);
-
-#if defined(__AVX__)
- intersect<GridSOA::Gather3x3>( ray, pre.ftime, context, grid_x, line_offset, lines, pre);
-#else
- intersect<GridSOA::Gather2x3>(ray, pre.ftime, context, grid_x, line_offset, lines, pre);
- if (likely(lines > 2))
- intersect<GridSOA::Gather2x3>(ray, pre.ftime, context, grid_x+line_offset, line_offset, lines, pre);
-#endif
- }
-
- /*! Test if the ray is occluded by the primitive */
- static __forceinline bool occluded(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t line_offset = pre.grid->width;
- const size_t lines = pre.grid->height;
- const float* const grid_x = pre.grid->decodeLeaf(pre.itime,prim);
-
-#if defined(__AVX__)
- return occluded<GridSOA::Gather3x3>( ray, pre.ftime, context, grid_x, line_offset, lines, pre);
-#else
- if (occluded<GridSOA::Gather2x3>(ray, pre.ftime, context, grid_x , line_offset, lines, pre)) return true;
- if (likely(lines > 2))
- if (occluded<GridSOA::Gather2x3>(ray, pre.ftime, context, grid_x+line_offset, line_offset, lines, pre)) return true;
-#endif
- return false;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/grid_soa_intersector_packet.h b/thirdparty/embree-aarch64/kernels/geometry/grid_soa_intersector_packet.h
deleted file mode 100644
index 41d66e1e28..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/grid_soa_intersector_packet.h
+++ /dev/null
@@ -1,445 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "grid_soa.h"
-#include "../common/ray.h"
-#include "triangle_intersector_pluecker.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int K>
- struct MapUV0
- {
- const float* const grid_uv;
- size_t ofs00, ofs01, ofs10, ofs11;
-
- __forceinline MapUV0(const float* const grid_uv, size_t ofs00, size_t ofs01, size_t ofs10, size_t ofs11)
- : grid_uv(grid_uv), ofs00(ofs00), ofs01(ofs01), ofs10(ofs10), ofs11(ofs11) {}
-
- __forceinline void operator() (vfloat<K>& u, vfloat<K>& v) const {
- const vfloat<K> uv00(grid_uv[ofs00]);
- const vfloat<K> uv01(grid_uv[ofs01]);
- const vfloat<K> uv10(grid_uv[ofs10]);
- const vfloat<K> uv11(grid_uv[ofs11]);
- const Vec2vf<K> uv0 = GridSOA::decodeUV(uv00);
- const Vec2vf<K> uv1 = GridSOA::decodeUV(uv01);
- const Vec2vf<K> uv2 = GridSOA::decodeUV(uv10);
- const Vec2vf<K> uv = madd(u,uv1,madd(v,uv2,(1.0f-u-v)*uv0));
- u = uv[0]; v = uv[1];
- }
- };
-
- template<int K>
- struct MapUV1
- {
- const float* const grid_uv;
- size_t ofs00, ofs01, ofs10, ofs11;
-
- __forceinline MapUV1(const float* const grid_uv, size_t ofs00, size_t ofs01, size_t ofs10, size_t ofs11)
- : grid_uv(grid_uv), ofs00(ofs00), ofs01(ofs01), ofs10(ofs10), ofs11(ofs11) {}
-
- __forceinline void operator() (vfloat<K>& u, vfloat<K>& v) const {
- const vfloat<K> uv00(grid_uv[ofs00]);
- const vfloat<K> uv01(grid_uv[ofs01]);
- const vfloat<K> uv10(grid_uv[ofs10]);
- const vfloat<K> uv11(grid_uv[ofs11]);
- const Vec2vf<K> uv0 = GridSOA::decodeUV(uv10);
- const Vec2vf<K> uv1 = GridSOA::decodeUV(uv01);
- const Vec2vf<K> uv2 = GridSOA::decodeUV(uv11);
- const Vec2vf<K> uv = madd(u,uv1,madd(v,uv2,(1.0f-u-v)*uv0));
- u = uv[0]; v = uv[1];
- }
- };
-
- template<int K>
- class GridSOAIntersectorK
- {
- public:
- typedef void Primitive;
-
- class Precalculations
- {
-#if defined(__AVX__)
- static const int M = 8;
-#else
- static const int M = 4;
-#endif
-
- public:
- __forceinline Precalculations (const vbool<K>& valid, const RayK<K>& ray)
- : grid(nullptr), intersector(valid,ray) {}
-
- public:
- GridSOA* grid;
- PlueckerIntersectorK<M,K> intersector; // FIXME: use quad intersector
- };
-
- /*! Intersect a ray with the primitive. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t dim_offset = pre.grid->dim_offset;
- const size_t line_offset = pre.grid->width;
- const float* const grid_x = pre.grid->decodeLeaf(0,prim);
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- const size_t max_x = pre.grid->width == 2 ? 1 : 2;
- const size_t max_y = pre.grid->height == 2 ? 1 : 2;
- for (size_t y=0; y<max_y; y++)
- {
- for (size_t x=0; x<max_x; x++)
- {
- const size_t ofs00 = (y+0)*line_offset+(x+0);
- const size_t ofs01 = (y+0)*line_offset+(x+1);
- const size_t ofs10 = (y+1)*line_offset+(x+0);
- const size_t ofs11 = (y+1)*line_offset+(x+1);
- const Vec3vf<K> p00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
- const Vec3vf<K> p01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
- const Vec3vf<K> p10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
- const Vec3vf<K> p11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
-
- pre.intersector.intersectK(valid_i,ray,p00,p01,p10,MapUV0<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),IntersectKEpilogMU<1,K,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
- pre.intersector.intersectK(valid_i,ray,p10,p01,p11,MapUV1<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),IntersectKEpilogMU<1,K,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
- }
- }
- }
-
- /*! Test if the ray is occluded by the primitive */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t dim_offset = pre.grid->dim_offset;
- const size_t line_offset = pre.grid->width;
- const float* const grid_x = pre.grid->decodeLeaf(0,prim);
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- vbool<K> valid = valid_i;
- const size_t max_x = pre.grid->width == 2 ? 1 : 2;
- const size_t max_y = pre.grid->height == 2 ? 1 : 2;
- for (size_t y=0; y<max_y; y++)
- {
- for (size_t x=0; x<max_x; x++)
- {
- const size_t ofs00 = (y+0)*line_offset+(x+0);
- const size_t ofs01 = (y+0)*line_offset+(x+1);
- const size_t ofs10 = (y+1)*line_offset+(x+0);
- const size_t ofs11 = (y+1)*line_offset+(x+1);
- const Vec3vf<K> p00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
- const Vec3vf<K> p01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
- const Vec3vf<K> p10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
- const Vec3vf<K> p11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
-
- pre.intersector.intersectK(valid,ray,p00,p01,p10,MapUV0<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),OccludedKEpilogMU<1,K,true>(valid,ray,context,pre.grid->geomID(),pre.grid->primID()));
- if (none(valid)) break;
- pre.intersector.intersectK(valid,ray,p10,p01,p11,MapUV1<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),OccludedKEpilogMU<1,K,true>(valid,ray,context,pre.grid->geomID(),pre.grid->primID()));
- if (none(valid)) break;
- }
- }
- return !valid;
- }
-
- template<typename Loader>
- static __forceinline void intersect(RayHitK<K>& ray, size_t k,
- IntersectContext* context,
- const float* const grid_x,
- const size_t line_offset,
- const size_t lines,
- Precalculations& pre)
- {
- typedef typename Loader::vfloat vfloat;
- const size_t dim_offset = pre.grid->dim_offset;
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
- Vec3<vfloat> v0, v1, v2; Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,v0,v1,v2);
- pre.intersector.intersect(ray,k,v0,v1,v2,GridSOA::MapUV<Loader>(grid_uv,line_offset,lines),Intersect1KEpilogMU<Loader::M,K,true>(ray,k,context,pre.grid->geomID(),pre.grid->primID()));
- };
-
- template<typename Loader>
- static __forceinline bool occluded(RayK<K>& ray, size_t k,
- IntersectContext* context,
- const float* const grid_x,
- const size_t line_offset,
- const size_t lines,
- Precalculations& pre)
- {
- typedef typename Loader::vfloat vfloat;
- const size_t dim_offset = pre.grid->dim_offset;
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
- Vec3<vfloat> v0, v1, v2; Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,v0,v1,v2);
- return pre.intersector.intersect(ray,k,v0,v1,v2,GridSOA::MapUV<Loader>(grid_uv,line_offset,lines),Occluded1KEpilogMU<Loader::M,K,true>(ray,k,context,pre.grid->geomID(),pre.grid->primID()));
- }
-
- /*! Intersect a ray with the primitive. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t line_offset = pre.grid->width;
- const size_t lines = pre.grid->height;
- const float* const grid_x = pre.grid->decodeLeaf(0,prim);
-#if defined(__AVX__)
- intersect<GridSOA::Gather3x3>( ray, k, context, grid_x, line_offset, lines, pre);
-#else
- intersect<GridSOA::Gather2x3>(ray, k, context, grid_x , line_offset, lines, pre);
- if (likely(lines > 2))
- intersect<GridSOA::Gather2x3>(ray, k, context, grid_x+line_offset, line_offset, lines, pre);
-#endif
- }
-
- /*! Test if the ray is occluded by the primitive */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t line_offset = pre.grid->width;
- const size_t lines = pre.grid->height;
- const float* const grid_x = pre.grid->decodeLeaf(0,prim);
-
-#if defined(__AVX__)
- return occluded<GridSOA::Gather3x3>( ray, k, context, grid_x, line_offset, lines, pre);
-#else
- if (occluded<GridSOA::Gather2x3>(ray, k, context, grid_x , line_offset, lines, pre)) return true;
- if (likely(lines > 2))
- if (occluded<GridSOA::Gather2x3>(ray, k, context, grid_x+line_offset, line_offset, lines, pre)) return true;
-#endif
- return false;
- }
- };
-
- template<int K>
- class GridSOAMBIntersectorK
- {
- public:
- typedef void Primitive;
- typedef typename GridSOAIntersectorK<K>::Precalculations Precalculations;
-
- /*! Intersect a ray with the primitive. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- vfloat<K> vftime;
- vint<K> vitime = getTimeSegment(ray.time(), vfloat<K>((float)(pre.grid->time_steps-1)), vftime);
-
- vbool<K> valid1 = valid_i;
- while (any(valid1)) {
- const size_t j = bsf(movemask(valid1));
- const int itime = vitime[j];
- const vbool<K> valid2 = valid1 & (itime == vitime);
- valid1 = valid1 & !valid2;
- intersect(valid2,pre,ray,vftime,itime,context,prim,lazy_node);
- }
- }
-
- /*! Intersect a ray with the primitive. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, const vfloat<K>& ftime, int itime, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t grid_offset = pre.grid->gridBytes >> 2;
- const size_t dim_offset = pre.grid->dim_offset;
- const size_t line_offset = pre.grid->width;
- const float* const grid_x = pre.grid->decodeLeaf(itime,prim);
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- const size_t max_x = pre.grid->width == 2 ? 1 : 2;
- const size_t max_y = pre.grid->height == 2 ? 1 : 2;
- for (size_t y=0; y<max_y; y++)
- {
- for (size_t x=0; x<max_x; x++)
- {
- size_t ofs00 = (y+0)*line_offset+(x+0);
- size_t ofs01 = (y+0)*line_offset+(x+1);
- size_t ofs10 = (y+1)*line_offset+(x+0);
- size_t ofs11 = (y+1)*line_offset+(x+1);
- const Vec3vf<K> a00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
- const Vec3vf<K> a01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
- const Vec3vf<K> a10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
- const Vec3vf<K> a11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
- ofs00 += grid_offset;
- ofs01 += grid_offset;
- ofs10 += grid_offset;
- ofs11 += grid_offset;
- const Vec3vf<K> b00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
- const Vec3vf<K> b01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
- const Vec3vf<K> b10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
- const Vec3vf<K> b11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
- const Vec3vf<K> p00 = lerp(a00,b00,ftime);
- const Vec3vf<K> p01 = lerp(a01,b01,ftime);
- const Vec3vf<K> p10 = lerp(a10,b10,ftime);
- const Vec3vf<K> p11 = lerp(a11,b11,ftime);
-
- pre.intersector.intersectK(valid_i,ray,p00,p01,p10,MapUV0<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),IntersectKEpilogMU<1,K,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
- pre.intersector.intersectK(valid_i,ray,p10,p01,p11,MapUV1<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),IntersectKEpilogMU<1,K,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
- }
- }
- }
-
- /*! Test if the ray is occluded by the primitive */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- vfloat<K> vftime;
- vint<K> vitime = getTimeSegment(ray.time(), vfloat<K>((float)(pre.grid->time_steps-1)), vftime);
-
- vbool<K> valid_o = valid_i;
- vbool<K> valid1 = valid_i;
- while (any(valid1)) {
- const int j = int(bsf(movemask(valid1)));
- const int itime = vitime[j];
- const vbool<K> valid2 = valid1 & (itime == vitime);
- valid1 = valid1 & !valid2;
- valid_o &= !valid2 | occluded(valid2,pre,ray,vftime,itime,context,prim,lazy_node);
- }
- return !valid_o;
- }
-
- /*! Test if the ray is occluded by the primitive */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, const vfloat<K>& ftime, int itime, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- const size_t grid_offset = pre.grid->gridBytes >> 2;
- const size_t dim_offset = pre.grid->dim_offset;
- const size_t line_offset = pre.grid->width;
- const float* const grid_x = pre.grid->decodeLeaf(itime,prim);
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- vbool<K> valid = valid_i;
- const size_t max_x = pre.grid->width == 2 ? 1 : 2;
- const size_t max_y = pre.grid->height == 2 ? 1 : 2;
- for (size_t y=0; y<max_y; y++)
- {
- for (size_t x=0; x<max_x; x++)
- {
- size_t ofs00 = (y+0)*line_offset+(x+0);
- size_t ofs01 = (y+0)*line_offset+(x+1);
- size_t ofs10 = (y+1)*line_offset+(x+0);
- size_t ofs11 = (y+1)*line_offset+(x+1);
- const Vec3vf<K> a00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
- const Vec3vf<K> a01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
- const Vec3vf<K> a10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
- const Vec3vf<K> a11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
- ofs00 += grid_offset;
- ofs01 += grid_offset;
- ofs10 += grid_offset;
- ofs11 += grid_offset;
- const Vec3vf<K> b00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
- const Vec3vf<K> b01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
- const Vec3vf<K> b10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
- const Vec3vf<K> b11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
- const Vec3vf<K> p00 = lerp(a00,b00,ftime);
- const Vec3vf<K> p01 = lerp(a01,b01,ftime);
- const Vec3vf<K> p10 = lerp(a10,b10,ftime);
- const Vec3vf<K> p11 = lerp(a11,b11,ftime);
-
- pre.intersector.intersectK(valid,ray,p00,p01,p10,MapUV0<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),OccludedKEpilogMU<1,K,true>(valid,ray,context,pre.grid->geomID(),pre.grid->primID()));
- if (none(valid)) break;
- pre.intersector.intersectK(valid,ray,p10,p01,p11,MapUV1<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),OccludedKEpilogMU<1,K,true>(valid,ray,context,pre.grid->geomID(),pre.grid->primID()));
- if (none(valid)) break;
- }
- }
- return valid;
- }
-
- template<typename Loader>
- static __forceinline void intersect(RayHitK<K>& ray, size_t k,
- const float ftime,
- IntersectContext* context,
- const float* const grid_x,
- const size_t line_offset,
- const size_t lines,
- Precalculations& pre)
- {
- typedef typename Loader::vfloat vfloat;
- const size_t grid_offset = pre.grid->gridBytes >> 2;
- const size_t dim_offset = pre.grid->dim_offset;
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- Vec3<vfloat> a0, a1, a2;
- Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,a0,a1,a2);
-
- Vec3<vfloat> b0, b1, b2;
- Loader::gather(grid_x+grid_offset,grid_y+grid_offset,grid_z+grid_offset,line_offset,lines,b0,b1,b2);
-
- Vec3<vfloat> v0 = lerp(a0,b0,vfloat(ftime));
- Vec3<vfloat> v1 = lerp(a1,b1,vfloat(ftime));
- Vec3<vfloat> v2 = lerp(a2,b2,vfloat(ftime));
-
- pre.intersector.intersect(ray,k,v0,v1,v2,GridSOA::MapUV<Loader>(grid_uv,line_offset,lines),Intersect1KEpilogMU<Loader::M,K,true>(ray,k,context,pre.grid->geomID(),pre.grid->primID()));
- };
-
- template<typename Loader>
- static __forceinline bool occluded(RayK<K>& ray, size_t k,
- const float ftime,
- IntersectContext* context,
- const float* const grid_x,
- const size_t line_offset,
- const size_t lines,
- Precalculations& pre)
- {
- typedef typename Loader::vfloat vfloat;
- const size_t grid_offset = pre.grid->gridBytes >> 2;
- const size_t dim_offset = pre.grid->dim_offset;
- const float* const grid_y = grid_x + 1 * dim_offset;
- const float* const grid_z = grid_x + 2 * dim_offset;
- const float* const grid_uv = grid_x + 3 * dim_offset;
-
- Vec3<vfloat> a0, a1, a2;
- Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,a0,a1,a2);
-
- Vec3<vfloat> b0, b1, b2;
- Loader::gather(grid_x+grid_offset,grid_y+grid_offset,grid_z+grid_offset,line_offset,lines,b0,b1,b2);
-
- Vec3<vfloat> v0 = lerp(a0,b0,vfloat(ftime));
- Vec3<vfloat> v1 = lerp(a1,b1,vfloat(ftime));
- Vec3<vfloat> v2 = lerp(a2,b2,vfloat(ftime));
-
- return pre.intersector.intersect(ray,k,v0,v1,v2,GridSOA::MapUV<Loader>(grid_uv,line_offset,lines),Occluded1KEpilogMU<Loader::M,K,true>(ray,k,context,pre.grid->geomID(),pre.grid->primID()));
- }
-
- /*! Intersect a ray with the primitive. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- float ftime;
- int itime = getTimeSegment(ray.time()[k], float(pre.grid->time_steps-1), ftime);
-
- const size_t line_offset = pre.grid->width;
- const size_t lines = pre.grid->height;
- const float* const grid_x = pre.grid->decodeLeaf(itime,prim);
-
-#if defined(__AVX__)
- intersect<GridSOA::Gather3x3>( ray, k, ftime, context, grid_x, line_offset, lines, pre);
-#else
- intersect<GridSOA::Gather2x3>(ray, k, ftime, context, grid_x, line_offset, lines, pre);
- if (likely(lines > 2))
- intersect<GridSOA::Gather2x3>(ray, k, ftime, context, grid_x+line_offset, line_offset, lines, pre);
-#endif
- }
-
- /*! Test if the ray is occluded by the primitive */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- float ftime;
- int itime = getTimeSegment(ray.time()[k], float(pre.grid->time_steps-1), ftime);
-
- const size_t line_offset = pre.grid->width;
- const size_t lines = pre.grid->height;
- const float* const grid_x = pre.grid->decodeLeaf(itime,prim);
-
-#if defined(__AVX__)
- return occluded<GridSOA::Gather3x3>( ray, k, ftime, context, grid_x, line_offset, lines, pre);
-#else
- if (occluded<GridSOA::Gather2x3>(ray, k, ftime, context, grid_x, line_offset, lines, pre)) return true;
- if (likely(lines > 2))
- if (occluded<GridSOA::Gather2x3>(ray, k, ftime, context, grid_x+line_offset, line_offset, lines, pre)) return true;
-#endif
- return false;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/instance.h b/thirdparty/embree-aarch64/kernels/geometry/instance.h
deleted file mode 100644
index 66893d581f..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/instance.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-#include "../common/scene_instance.h"
-
-namespace embree
-{
- struct InstancePrimitive
- {
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* primitive supports multiple time segments */
- static const bool singleTimeSegment = false;
-
- /* Returns maximum number of stored primitives */
- static __forceinline size_t max_size() { return 1; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return N; }
-
- public:
-
- InstancePrimitive (const Instance* instance, unsigned int instID)
- : instance(instance)
- , instID_(instID)
- {}
-
- __forceinline void fill(const PrimRef* prims, size_t& i, size_t end, Scene* scene)
- {
- assert(end-i == 1);
- const PrimRef& prim = prims[i]; i++;
- const unsigned int geomID = prim.geomID();
- const Instance* instance = scene->get<Instance>(geomID);
- new (this) InstancePrimitive(instance, geomID);
- }
-
- __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& i, size_t end, Scene* scene, size_t itime)
- {
- assert(end-i == 1);
- const PrimRef& prim = prims[i]; i++;
- const unsigned int geomID = prim.geomID();
- const Instance* instance = scene->get<Instance>(geomID);
- new (this) InstancePrimitive(instance,geomID);
- return instance->linearBounds(0,itime);
- }
-
- __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& i, size_t end, Scene* scene, const BBox1f time_range)
- {
- assert(end-i == 1);
- const PrimRefMB& prim = prims[i]; i++;
- const unsigned int geomID = prim.geomID();
- const Instance* instance = scene->get<Instance>(geomID);
- new (this) InstancePrimitive(instance,geomID);
- return instance->linearBounds(0,time_range);
- }
-
- /* Updates the primitive */
- __forceinline BBox3fa update(Instance* instance) {
- return instance->bounds(0);
- }
-
- public:
- const Instance* instance;
- const unsigned int instID_ = std::numeric_limits<unsigned int>::max ();
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/instance_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/instance_intersector.h
deleted file mode 100644
index 91731a39c5..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/instance_intersector.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "instance.h"
-#include "../common/ray.h"
-#include "../common/point_query.h"
-
-namespace embree
-{
- namespace isa
- {
- struct InstanceIntersector1
- {
- typedef InstancePrimitive Primitive;
-
- struct Precalculations {
- __forceinline Precalculations (const Ray& ray, const void *ptr) {}
- };
-
- static void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim);
- static bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim);
- static bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& prim);
- };
-
- struct InstanceIntersector1MB
- {
- typedef InstancePrimitive Primitive;
-
- struct Precalculations {
- __forceinline Precalculations (const Ray& ray, const void *ptr) {}
- };
-
- static void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim);
- static bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim);
- static bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& prim);
- };
-
- template<int K>
- struct InstanceIntersectorK
- {
- typedef InstancePrimitive Primitive;
-
- struct Precalculations {
- __forceinline Precalculations (const vbool<K>& valid, const RayK<K>& ray) {}
- };
-
- static void intersect(const vbool<K>& valid_i, const Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& prim);
- static vbool<K> occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& prim);
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
- intersect(vbool<K>(1<<int(k)),pre,ray,context,prim);
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
- occluded(vbool<K>(1<<int(k)),pre,ray,context,prim);
- return ray.tfar[k] < 0.0f;
- }
- };
-
- template<int K>
- struct InstanceIntersectorKMB
- {
- typedef InstancePrimitive Primitive;
-
- struct Precalculations {
- __forceinline Precalculations (const vbool<K>& valid, const RayK<K>& ray) {}
- };
-
- static void intersect(const vbool<K>& valid_i, const Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& prim);
- static vbool<K> occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& prim);
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
- intersect(vbool<K>(1<<int(k)),pre,ray,context,prim);
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
- occluded(vbool<K>(1<<int(k)),pre,ray,context,prim);
- return ray.tfar[k] < 0.0f;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/intersector_epilog.h b/thirdparty/embree-aarch64/kernels/geometry/intersector_epilog.h
deleted file mode 100644
index 0df49dd6e9..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/intersector_epilog.h
+++ /dev/null
@@ -1,1074 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "../common/context.h"
-#include "filter.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct UVIdentity {
- __forceinline void operator() (vfloat<M>& u, vfloat<M>& v) const {}
- };
-
-
- template<bool filter>
- struct Intersect1Epilog1
- {
- RayHit& ray;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline Intersect1Epilog1(RayHit& ray,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline bool operator() (Hit& hit) const
- {
- /* ray mask test */
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-#if defined(EMBREE_RAY_MASK)
- if ((geometry->mask & ray.mask) == 0) return false;
-#endif
- hit.finalize();
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
- HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
- const float old_t = ray.tfar;
- ray.tfar = hit.t;
- bool found = runIntersectionFilter1(geometry,ray,context,h);
- if (!found) ray.tfar = old_t;
- return found;
- }
- }
-#endif
-
- /* update hit information */
- ray.tfar = hit.t;
- ray.Ng = hit.Ng;
- ray.u = hit.u;
- ray.v = hit.v;
- ray.primID = primID;
- ray.geomID = geomID;
- instance_id_stack::copy(context->user->instID, ray.instID);
- return true;
- }
- };
-
- template<bool filter>
- struct Occluded1Epilog1
- {
- Ray& ray;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline Occluded1Epilog1(Ray& ray,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline bool operator() (Hit& hit) const
- {
- /* ray mask test */
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
-
-#if defined(EMBREE_RAY_MASK)
- if ((geometry->mask & ray.mask) == 0) return false;
-#endif
- hit.finalize();
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
- HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
- const float old_t = ray.tfar;
- ray.tfar = hit.t;
- const bool found = runOcclusionFilter1(geometry,ray,context,h);
- if (!found) ray.tfar = old_t;
- return found;
- }
- }
-#endif
- return true;
- }
- };
-
- template<int K, bool filter>
- struct Intersect1KEpilog1
- {
- RayHitK<K>& ray;
- size_t k;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline Intersect1KEpilog1(RayHitK<K>& ray, size_t k,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline bool operator() (Hit& hit) const
- {
- /* ray mask test */
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-#if defined(EMBREE_RAY_MASK)
- if ((geometry->mask & ray.mask[k]) == 0)
- return false;
-#endif
- hit.finalize();
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
- HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
- const float old_t = ray.tfar[k];
- ray.tfar[k] = hit.t;
- const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
- if (!found) ray.tfar[k] = old_t;
- return found;
- }
- }
-#endif
-
- /* update hit information */
- ray.tfar[k] = hit.t;
- ray.Ng.x[k] = hit.Ng.x;
- ray.Ng.y[k] = hit.Ng.y;
- ray.Ng.z[k] = hit.Ng.z;
- ray.u[k] = hit.u;
- ray.v[k] = hit.v;
- ray.primID[k] = primID;
- ray.geomID[k] = geomID;
- instance_id_stack::copy<const unsigned*, vuint<K>*, const size_t&>(context->user->instID, ray.instID, k);
- return true;
- }
- };
-
- template<int K, bool filter>
- struct Occluded1KEpilog1
- {
- RayK<K>& ray;
- size_t k;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline Occluded1KEpilog1(RayK<K>& ray, size_t k,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline bool operator() (Hit& hit) const
- {
- /* ray mask test */
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-#if defined(EMBREE_RAY_MASK)
- if ((geometry->mask & ray.mask[k]) == 0)
- return false;
-#endif
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
- hit.finalize();
- HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
- const float old_t = ray.tfar[k];
- ray.tfar[k] = hit.t;
- const bool found = any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h));
- if (!found) ray.tfar[k] = old_t;
- return found;
- }
- }
-#endif
- return true;
- }
- };
-
- template<int M, int Mx, bool filter>
- struct Intersect1EpilogM
- {
- RayHit& ray;
- IntersectContext* context;
- const vuint<M>& geomIDs;
- const vuint<M>& primIDs;
-
- __forceinline Intersect1EpilogM(RayHit& ray,
- IntersectContext* context,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs)
- : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<Mx>& valid_i, Hit& hit) const
- {
- Scene* scene MAYBE_UNUSED = context->scene;
- vbool<Mx> valid = valid_i;
- if (Mx > M) valid &= (1<<M)-1;
- hit.finalize();
- size_t i = select_min(valid,hit.vt);
- unsigned int geomID = geomIDs[i];
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
- bool foundhit = false;
- goto entry;
- while (true)
- {
- if (unlikely(none(valid))) return foundhit;
- i = select_min(valid,hit.vt);
-
- geomID = geomIDs[i];
- entry:
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
-#if defined(EMBREE_RAY_MASK)
- /* goto next hit if mask test fails */
- if ((geometry->mask & ray.mask) == 0) {
- clear(valid,i);
- continue;
- }
-#endif
-
-#if defined(EMBREE_FILTER_FUNCTION)
- /* call intersection filter function */
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
- const Vec2f uv = hit.uv(i);
- HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
- const float old_t = ray.tfar;
- ray.tfar = hit.t(i);
- const bool found = runIntersectionFilter1(geometry,ray,context,h);
- if (!found) ray.tfar = old_t;
- foundhit |= found;
- clear(valid,i);
- valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
- continue;
- }
- }
-#endif
- break;
- }
-#endif
-
- /* update hit information */
- const Vec2f uv = hit.uv(i);
- ray.tfar = hit.vt[i];
- ray.Ng.x = hit.vNg.x[i];
- ray.Ng.y = hit.vNg.y[i];
- ray.Ng.z = hit.vNg.z[i];
- ray.u = uv.x;
- ray.v = uv.y;
- ray.primID = primIDs[i];
- ray.geomID = geomID;
- instance_id_stack::copy(context->user->instID, ray.instID);
- return true;
-
- }
- };
-
-#if 0 && defined(__AVX512F__) // do not enable, this reduced frequency for BVH4
- template<int M, bool filter>
- struct Intersect1EpilogM<M,16,filter>
- {
- static const size_t Mx = 16;
- RayHit& ray;
- IntersectContext* context;
- const vuint<M>& geomIDs;
- const vuint<M>& primIDs;
-
- __forceinline Intersect1EpilogM(RayHit& ray,
- IntersectContext* context,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs)
- : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<Mx>& valid_i, Hit& hit) const
- {
- Scene* MAYBE_UNUSED scene = context->scene;
- vbool<Mx> valid = valid_i;
- if (Mx > M) valid &= (1<<M)-1;
- hit.finalize();
- size_t i = select_min(valid,hit.vt);
- unsigned int geomID = geomIDs[i];
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
- bool foundhit = false;
- goto entry;
- while (true)
- {
- if (unlikely(none(valid))) return foundhit;
- i = select_min(valid,hit.vt);
-
- geomID = geomIDs[i];
- entry:
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
-#if defined(EMBREE_RAY_MASK)
- /* goto next hit if mask test fails */
- if ((geometry->mask & ray.mask) == 0) {
- clear(valid,i);
- continue;
- }
-#endif
-
-#if defined(EMBREE_FILTER_FUNCTION)
- /* call intersection filter function */
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
- const Vec2f uv = hit.uv(i);
- HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
- const float old_t = ray.tfar;
- ray.tfar = hit.t(i);
- const bool found = runIntersectionFilter1(geometry,ray,context,h);
- if (!found) ray.tfar = old_t;
- foundhit |= found;
- clear(valid,i);
- valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
- continue;
- }
- }
-#endif
- break;
- }
-#endif
-
- vbool<Mx> finalMask(((unsigned int)1 << i));
- ray.update(finalMask,hit.vt,hit.vu,hit.vv,hit.vNg.x,hit.vNg.y,hit.vNg.z,geomID,primIDs);
- instance_id_stack::foreach([&](unsigned level)
- {
- ray.instID[level] = context->user->instID[level];
- return (context->user->instID[level] != RTC_INVALID_GEOMETRY_ID);
- });
- return true;
-
- }
- };
-#endif
-
- template<int M, int Mx, bool filter>
- struct Occluded1EpilogM
- {
- Ray& ray;
- IntersectContext* context;
- const vuint<M>& geomIDs;
- const vuint<M>& primIDs;
-
- __forceinline Occluded1EpilogM(Ray& ray,
- IntersectContext* context,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs)
- : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<Mx>& valid_i, Hit& hit) const
- {
- Scene* scene MAYBE_UNUSED = context->scene;
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
- if (unlikely(filter))
- hit.finalize(); /* called only once */
-
- vbool<Mx> valid = valid_i;
- if (Mx > M) valid &= (1<<M)-1;
- size_t m=movemask(valid);
- goto entry;
- while (true)
- {
- if (unlikely(m == 0)) return false;
- entry:
- size_t i=bsf(m);
-
- const unsigned int geomID = geomIDs[i];
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
-#if defined(EMBREE_RAY_MASK)
- /* goto next hit if mask test fails */
- if ((geometry->mask & ray.mask) == 0) {
- m=btc(m,i);
- continue;
- }
-#endif
-
-#if defined(EMBREE_FILTER_FUNCTION)
- /* if we have no filter then the test passed */
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
- {
- const Vec2f uv = hit.uv(i);
- HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
- const float old_t = ray.tfar;
- ray.tfar = hit.t(i);
- if (runOcclusionFilter1(geometry,ray,context,h)) return true;
- ray.tfar = old_t;
- m=btc(m,i);
- continue;
- }
- }
-#endif
- break;
- }
-#endif
-
- return true;
- }
- };
-
- template<int M, bool filter>
- struct Intersect1EpilogMU
- {
- RayHit& ray;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline Intersect1EpilogMU(RayHit& ray,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
- {
- /* ray mask test */
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-#if defined(EMBREE_RAY_MASK)
- if ((geometry->mask & ray.mask) == 0) return false;
-#endif
-
- vbool<M> valid = valid_i;
- hit.finalize();
-
- size_t i = select_min(valid,hit.vt);
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
- {
- bool foundhit = false;
- while (true)
- {
- /* call intersection filter function */
- Vec2f uv = hit.uv(i);
- const float old_t = ray.tfar;
- ray.tfar = hit.t(i);
- HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
- const bool found = runIntersectionFilter1(geometry,ray,context,h);
- if (!found) ray.tfar = old_t;
- foundhit |= found;
- clear(valid,i);
- valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
- if (unlikely(none(valid))) break;
- i = select_min(valid,hit.vt);
- }
- return foundhit;
- }
-#endif
-
- /* update hit information */
- const Vec2f uv = hit.uv(i);
- const Vec3fa Ng = hit.Ng(i);
- ray.tfar = hit.t(i);
- ray.Ng.x = Ng.x;
- ray.Ng.y = Ng.y;
- ray.Ng.z = Ng.z;
- ray.u = uv.x;
- ray.v = uv.y;
- ray.primID = primID;
- ray.geomID = geomID;
- instance_id_stack::copy(context->user->instID, ray.instID);
- return true;
- }
- };
-
- template<int M, bool filter>
- struct Occluded1EpilogMU
- {
- Ray& ray;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline Occluded1EpilogMU(Ray& ray,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<M>& valid, Hit& hit) const
- {
- /* ray mask test */
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-#if defined(EMBREE_RAY_MASK)
- if ((geometry->mask & ray.mask) == 0) return false;
-#endif
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
- {
- hit.finalize();
- for (size_t m=movemask(valid), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
- {
- const Vec2f uv = hit.uv(i);
- const float old_t = ray.tfar;
- ray.tfar = hit.t(i);
- HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
- if (runOcclusionFilter1(geometry,ray,context,h)) return true;
- ray.tfar = old_t;
- }
- return false;
- }
-#endif
- return true;
- }
- };
-
- template<int M, int K, bool filter>
- struct IntersectKEpilogM
- {
- RayHitK<K>& ray;
- IntersectContext* context;
- const vuint<M>& geomIDs;
- const vuint<M>& primIDs;
- const size_t i;
-
- __forceinline IntersectKEpilogM(RayHitK<K>& ray,
- IntersectContext* context,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs,
- size_t i)
- : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
-
- template<typename Hit>
- __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
- {
- Scene* scene MAYBE_UNUSED = context->scene;
-
- vfloat<K> u, v, t;
- Vec3vf<K> Ng;
- vbool<K> valid = valid_i;
-
- std::tie(u,v,t,Ng) = hit();
-
- const unsigned int geomID = geomIDs[i];
- const unsigned int primID = primIDs[i];
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
- /* ray masking test */
-#if defined(EMBREE_RAY_MASK)
- valid &= (geometry->mask & ray.mask) != 0;
- if (unlikely(none(valid))) return false;
-#endif
-
- /* occlusion filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
- HitK<K> h(context->user,geomID,primID,u,v,Ng);
- const vfloat<K> old_t = ray.tfar;
- ray.tfar = select(valid,t,ray.tfar);
- const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
- ray.tfar = select(m_accept,ray.tfar,old_t);
- return m_accept;
- }
- }
-#endif
-
- /* update hit information */
- vfloat<K>::store(valid,&ray.tfar,t);
- vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
- vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
- vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
- vfloat<K>::store(valid,&ray.u,u);
- vfloat<K>::store(valid,&ray.v,v);
- vuint<K>::store(valid,&ray.primID,primID);
- vuint<K>::store(valid,&ray.geomID,geomID);
- instance_id_stack::copy<const unsigned*, vuint<K>*, const vbool<K>&>(context->user->instID, ray.instID, valid);
- return valid;
- }
- };
-
- template<int M, int K, bool filter>
- struct OccludedKEpilogM
- {
- vbool<K>& valid0;
- RayK<K>& ray;
- IntersectContext* context;
- const vuint<M>& geomIDs;
- const vuint<M>& primIDs;
- const size_t i;
-
- __forceinline OccludedKEpilogM(vbool<K>& valid0,
- RayK<K>& ray,
- IntersectContext* context,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs,
- size_t i)
- : valid0(valid0), ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
-
- template<typename Hit>
- __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
- {
- vbool<K> valid = valid_i;
-
- /* ray masking test */
- Scene* scene MAYBE_UNUSED = context->scene;
- const unsigned int geomID = geomIDs[i];
- const unsigned int primID = primIDs[i];
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-#if defined(EMBREE_RAY_MASK)
- valid &= (geometry->mask & ray.mask) != 0;
- if (unlikely(none(valid))) return valid;
-#endif
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
- {
- vfloat<K> u, v, t;
- Vec3vf<K> Ng;
- std::tie(u,v,t,Ng) = hit();
- HitK<K> h(context->user,geomID,primID,u,v,Ng);
- const vfloat<K> old_t = ray.tfar;
- ray.tfar = select(valid,t,ray.tfar);
- valid = runOcclusionFilter(valid,geometry,ray,context,h);
- ray.tfar = select(valid,ray.tfar,old_t);
- }
- }
-#endif
-
- /* update occlusion */
- valid0 = valid0 & !valid;
- return valid;
- }
- };
-
- template<int M, int K, bool filter>
- struct IntersectKEpilogMU
- {
- RayHitK<K>& ray;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline IntersectKEpilogMU(RayHitK<K>& ray,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline vbool<K> operator() (const vbool<K>& valid_org, const Hit& hit) const
- {
- vbool<K> valid = valid_org;
- vfloat<K> u, v, t;
- Vec3vf<K> Ng;
- std::tie(u,v,t,Ng) = hit();
-
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
- /* ray masking test */
-#if defined(EMBREE_RAY_MASK)
- valid &= (geometry->mask & ray.mask) != 0;
- if (unlikely(none(valid))) return false;
-#endif
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
- HitK<K> h(context->user,geomID,primID,u,v,Ng);
- const vfloat<K> old_t = ray.tfar;
- ray.tfar = select(valid,t,ray.tfar);
- const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
- ray.tfar = select(m_accept,ray.tfar,old_t);
- return m_accept;
- }
- }
-#endif
-
- /* update hit information */
- vfloat<K>::store(valid,&ray.tfar,t);
- vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
- vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
- vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
- vfloat<K>::store(valid,&ray.u,u);
- vfloat<K>::store(valid,&ray.v,v);
- vuint<K>::store(valid,&ray.primID,primID);
- vuint<K>::store(valid,&ray.geomID,geomID);
- instance_id_stack::copy<const unsigned*, vuint<K>*, const vbool<K>&>(context->user->instID, ray.instID, valid);
-
- return valid;
- }
- };
-
- template<int M, int K, bool filter>
- struct OccludedKEpilogMU
- {
- vbool<K>& valid0;
- RayK<K>& ray;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline OccludedKEpilogMU(vbool<K>& valid0,
- RayK<K>& ray,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : valid0(valid0), ray(ray), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
- {
- vbool<K> valid = valid_i;
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
-#if defined(EMBREE_RAY_MASK)
- valid &= (geometry->mask & ray.mask) != 0;
- if (unlikely(none(valid))) return false;
-#endif
-
- /* occlusion filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
- {
- vfloat<K> u, v, t;
- Vec3vf<K> Ng;
- std::tie(u,v,t,Ng) = hit();
- HitK<K> h(context->user,geomID,primID,u,v,Ng);
- const vfloat<K> old_t = ray.tfar;
- ray.tfar = select(valid,t,ray.tfar);
- valid = runOcclusionFilter(valid,geometry,ray,context,h);
- ray.tfar = select(valid,ray.tfar,old_t);
- }
- }
-#endif
-
- /* update occlusion */
- valid0 = valid0 & !valid;
- return valid;
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct Intersect1KEpilogM
- {
- RayHitK<K>& ray;
- size_t k;
- IntersectContext* context;
- const vuint<M>& geomIDs;
- const vuint<M>& primIDs;
-
- __forceinline Intersect1KEpilogM(RayHitK<K>& ray, size_t k,
- IntersectContext* context,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs)
- : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<Mx>& valid_i, Hit& hit) const
- {
- Scene* scene MAYBE_UNUSED = context->scene;
- vbool<Mx> valid = valid_i;
- hit.finalize();
- if (Mx > M) valid &= (1<<M)-1;
- size_t i = select_min(valid,hit.vt);
- assert(i<M);
- unsigned int geomID = geomIDs[i];
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
- bool foundhit = false;
- goto entry;
- while (true)
- {
- if (unlikely(none(valid))) return foundhit;
- i = select_min(valid,hit.vt);
- assert(i<M);
- geomID = geomIDs[i];
- entry:
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
-#if defined(EMBREE_RAY_MASK)
- /* goto next hit if mask test fails */
- if ((geometry->mask & ray.mask[k]) == 0) {
- clear(valid,i);
- continue;
- }
-#endif
-
-#if defined(EMBREE_FILTER_FUNCTION)
- /* call intersection filter function */
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
- assert(i<M);
- const Vec2f uv = hit.uv(i);
- HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
- const float old_t = ray.tfar[k];
- ray.tfar[k] = hit.t(i);
- const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
- if (!found) ray.tfar[k] = old_t;
- foundhit = foundhit | found;
- clear(valid,i);
- valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
- continue;
- }
- }
-#endif
- break;
- }
-#endif
- assert(i<M);
- /* update hit information */
-#if 0 && defined(__AVX512F__) // do not enable, this reduced frequency for BVH4
- ray.updateK(i,k,hit.vt,hit.vu,hit.vv,vfloat<Mx>(hit.vNg.x),vfloat<Mx>(hit.vNg.y),vfloat<Mx>(hit.vNg.z),geomID,vuint<Mx>(primIDs));
-#else
- const Vec2f uv = hit.uv(i);
- ray.tfar[k] = hit.t(i);
- ray.Ng.x[k] = hit.vNg.x[i];
- ray.Ng.y[k] = hit.vNg.y[i];
- ray.Ng.z[k] = hit.vNg.z[i];
- ray.u[k] = uv.x;
- ray.v[k] = uv.y;
- ray.primID[k] = primIDs[i];
- ray.geomID[k] = geomID;
- instance_id_stack::copy<const unsigned*, vuint<K>*, const size_t&>(context->user->instID, ray.instID, k);
-#endif
- return true;
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct Occluded1KEpilogM
- {
- RayK<K>& ray;
- size_t k;
- IntersectContext* context;
- const vuint<M>& geomIDs;
- const vuint<M>& primIDs;
-
- __forceinline Occluded1KEpilogM(RayK<K>& ray, size_t k,
- IntersectContext* context,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs)
- : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<Mx>& valid_i, Hit& hit) const
- {
- Scene* scene MAYBE_UNUSED = context->scene;
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
- if (unlikely(filter))
- hit.finalize(); /* called only once */
-
- vbool<Mx> valid = valid_i;
- if (Mx > M) valid &= (1<<M)-1;
- size_t m=movemask(valid);
- goto entry;
- while (true)
- {
- if (unlikely(m == 0)) return false;
- entry:
- size_t i=bsf(m);
-
- const unsigned int geomID = geomIDs[i];
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-
-#if defined(EMBREE_RAY_MASK)
- /* goto next hit if mask test fails */
- if ((geometry->mask & ray.mask[k]) == 0) {
- m=btc(m,i);
- continue;
- }
-#endif
-
-#if defined(EMBREE_FILTER_FUNCTION)
- /* execute occlusion filer */
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
- {
- const Vec2f uv = hit.uv(i);
- const float old_t = ray.tfar[k];
- ray.tfar[k] = hit.t(i);
- HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
- if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
- ray.tfar[k] = old_t;
- m=btc(m,i);
- continue;
- }
- }
-#endif
- break;
- }
-#endif
- return true;
- }
- };
-
- template<int M, int K, bool filter>
- struct Intersect1KEpilogMU
- {
- RayHitK<K>& ray;
- size_t k;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline Intersect1KEpilogMU(RayHitK<K>& ray, size_t k,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
- {
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-#if defined(EMBREE_RAY_MASK)
- /* ray mask test */
- if ((geometry->mask & ray.mask[k]) == 0)
- return false;
-#endif
-
- /* finalize hit calculation */
- vbool<M> valid = valid_i;
- hit.finalize();
- size_t i = select_min(valid,hit.vt);
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
- {
- bool foundhit = false;
- while (true)
- {
- const Vec2f uv = hit.uv(i);
- const float old_t = ray.tfar[k];
- ray.tfar[k] = hit.t(i);
- HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
- const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
- if (!found) ray.tfar[k] = old_t;
- foundhit = foundhit | found;
- clear(valid,i);
- valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
- if (unlikely(none(valid))) break;
- i = select_min(valid,hit.vt);
- }
- return foundhit;
- }
- }
-#endif
-
- /* update hit information */
-#if 0 && defined(__AVX512F__) // do not enable, this reduced frequency for BVH4
- const Vec3fa Ng = hit.Ng(i);
- ray.updateK(i,k,hit.vt,hit.vu,hit.vv,vfloat<M>(Ng.x),vfloat<M>(Ng.y),vfloat<M>(Ng.z),geomID,vuint<M>(primID));
-#else
- const Vec2f uv = hit.uv(i);
- const Vec3fa Ng = hit.Ng(i);
- ray.tfar[k] = hit.t(i);
- ray.Ng.x[k] = Ng.x;
- ray.Ng.y[k] = Ng.y;
- ray.Ng.z[k] = Ng.z;
- ray.u[k] = uv.x;
- ray.v[k] = uv.y;
- ray.primID[k] = primID;
- ray.geomID[k] = geomID;
- instance_id_stack::copy<const unsigned*, vuint<K>*, const size_t&>(context->user->instID, ray.instID, k);
-#endif
- return true;
- }
- };
-
- template<int M, int K, bool filter>
- struct Occluded1KEpilogMU
- {
- RayK<K>& ray;
- size_t k;
- IntersectContext* context;
- const unsigned int geomID;
- const unsigned int primID;
-
- __forceinline Occluded1KEpilogMU(RayK<K>& ray, size_t k,
- IntersectContext* context,
- const unsigned int geomID,
- const unsigned int primID)
- : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
-
- template<typename Hit>
- __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
- {
- Scene* scene MAYBE_UNUSED = context->scene;
- Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
-#if defined(EMBREE_RAY_MASK)
- /* ray mask test */
- if ((geometry->mask & ray.mask[k]) == 0)
- return false;
-#endif
-
- /* intersection filter test */
-#if defined(EMBREE_FILTER_FUNCTION)
- if (filter) {
- if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
- {
- hit.finalize();
- for (size_t m=movemask(valid_i), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
- {
- const Vec2f uv = hit.uv(i);
- const float old_t = ray.tfar[k];
- ray.tfar[k] = hit.t(i);
- HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
- if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
- ray.tfar[k] = old_t;
- }
- return false;
- }
- }
-#endif
- return true;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/intersector_iterators.h b/thirdparty/embree-aarch64/kernels/geometry/intersector_iterators.h
deleted file mode 100644
index 5c1ba5cb61..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/intersector_iterators.h
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/scene.h"
-#include "../common/ray.h"
-#include "../common/point_query.h"
-#include "../bvh/node_intersector1.h"
-#include "../bvh/node_intersector_packet.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename Intersector>
- struct ArrayIntersector1
- {
- typedef typename Intersector::Primitive Primitive;
- typedef typename Intersector::Precalculations Precalculations;
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- for (size_t i=0; i<num; i++)
- Intersector::intersect(pre,ray,context,prim[i]);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- for (size_t i=0; i<num; i++) {
- if (Intersector::occluded(pre,ray,context,prim[i]))
- return true;
- }
- return false;
- }
-
- template<int N>
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t num, const TravPointQuery<N> &tquery, size_t& lazy_node)
- {
- bool changed = false;
- for (size_t i=0; i<num; i++)
- changed |= Intersector::pointQuery(query, context, prim[i]);
- return changed;
- }
-
- template<int K>
- static __forceinline void intersectK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
- {
- }
-
- template<int K>
- static __forceinline vbool<K> occludedK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
- {
- return valid;
- }
- };
-
- template<int K, typename Intersector>
- struct ArrayIntersectorK_1
- {
- typedef typename Intersector::Primitive Primitive;
- typedef typename Intersector::Precalculations Precalculations;
-
- template<bool robust>
- static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- for (size_t i=0; i<num; i++) {
- Intersector::intersect(valid,pre,ray,context,prim[i]);
- }
- }
-
- template<bool robust>
- static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- vbool<K> valid0 = valid;
- for (size_t i=0; i<num; i++) {
- valid0 &= !Intersector::occluded(valid0,pre,ray,context,prim[i]);
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- for (size_t i=0; i<num; i++) {
- Intersector::intersect(pre,ray,k,context,prim[i]);
- }
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- for (size_t i=0; i<num; i++) {
- if (Intersector::occluded(pre,ray,k,context,prim[i]))
- return true;
- }
- return false;
- }
- };
-
- // =============================================================================================
-
- template<int K, typename IntersectorK>
- struct ArrayIntersectorKStream
- {
- typedef typename IntersectorK::Primitive PrimitiveK;
- typedef typename IntersectorK::Precalculations PrecalculationsK;
-
- static __forceinline void intersectK(const vbool<K>& valid, const Accel::Intersectors* This, /* PrecalculationsK& pre, */ RayHitK<K>& ray, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
- {
- PrecalculationsK pre(valid,ray); // FIXME: might cause trouble
-
- for (size_t i=0; i<num; i++) {
- IntersectorK::intersect(valid,pre,ray,context,prim[i]);
- }
- }
-
- static __forceinline vbool<K> occludedK(const vbool<K>& valid, const Accel::Intersectors* This, /* PrecalculationsK& pre, */ RayK<K>& ray, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
- {
- PrecalculationsK pre(valid,ray); // FIXME: might cause trouble
- vbool<K> valid0 = valid;
- for (size_t i=0; i<num; i++) {
- valid0 &= !IntersectorK::occluded(valid0,pre,ray,context,prim[i]);
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- static __forceinline void intersect(const Accel::Intersectors* This, RayHitK<K>& ray, size_t k, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
- {
- PrecalculationsK pre(ray.tnear() <= ray.tfar,ray); // FIXME: might cause trouble
- for (size_t i=0; i<num; i++) {
- IntersectorK::intersect(pre,ray,k,context,prim[i]);
- }
- }
-
- static __forceinline bool occluded(const Accel::Intersectors* This, RayK<K>& ray, size_t k, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
- {
- PrecalculationsK pre(ray.tnear() <= ray.tfar,ray); // FIXME: might cause trouble
- for (size_t i=0; i<num; i++) {
- if (IntersectorK::occluded(pre,ray,k,context,prim[i]))
- return true;
- }
- return false;
- }
-
- static __forceinline size_t occluded(const Accel::Intersectors* This, size_t cur_mask, RayK<K>** __restrict__ inputPackets, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
- {
- size_t m_occluded = 0;
- for (size_t i=0; i<num; i++) {
- size_t bits = cur_mask & (~m_occluded);
- for (; bits!=0; )
- {
- const size_t rayID = bscf(bits);
- RayHitK<K> &ray = *inputPackets[rayID / K];
- const size_t k = rayID % K;
- PrecalculationsK pre(ray.tnear() <= ray.tfar,ray); // FIXME: might cause trouble
- if (IntersectorK::occluded(pre,ray,k,context,prim[i]))
- {
- m_occluded |= (size_t)1 << rayID;
- ray.tfar[k] = neg_inf;
- }
- }
- }
- return m_occluded;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/line_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/line_intersector.h
deleted file mode 100644
index eef5b0b1fd..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/line_intersector.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "curve_intersector_precalculations.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct LineIntersectorHitM
- {
- __forceinline LineIntersectorHitM() {}
-
- __forceinline LineIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
- : vu(u), vv(v), vt(t), vNg(Ng) {}
-
- __forceinline void finalize() {}
-
- __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
- __forceinline float t (const size_t i) const { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- public:
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- template<int M>
- struct FlatLinearCurveIntersector1
- {
- typedef CurvePrecalculations1 Precalculations;
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- Ray& ray,
- IntersectContext* context,
- const LineSegments* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
- const Epilog& epilog)
- {
- /* transform end points into ray space */
- vbool<M> valid = valid_i;
- vfloat<M> depth_scale = pre.depth_scale;
- LinearSpace3<Vec3vf<M>> ray_space = pre.ray_space;
-
- const Vec3vf<M> ray_org ((Vec3fa)ray.org);
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec4vf<M> v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i);
-
- Vec4vf<M> p0(xfmVector(ray_space,v0.xyz()-ray_org), v0.w);
- Vec4vf<M> p1(xfmVector(ray_space,v1.xyz()-ray_org), v1.w);
-
- /* approximative intersection with cone */
- const Vec4vf<M> v = p1-p0;
- const Vec4vf<M> w = -p0;
- const vfloat<M> d0 = madd(w.x,v.x,w.y*v.y);
- const vfloat<M> d1 = madd(v.x,v.x,v.y*v.y);
- const vfloat<M> u = clamp(d0*rcp(d1),vfloat<M>(zero),vfloat<M>(one));
- const Vec4vf<M> p = madd(u,v,p0);
- const vfloat<M> t = p.z;
- const vfloat<M> d2 = madd(p.x,p.x,p.y*p.y);
- const vfloat<M> r = p.w;
- const vfloat<M> r2 = r*r;
- valid &= (d2 <= r2) & (vfloat<M>(ray.tnear()) <= t) & (t <= vfloat<M>(ray.tfar));
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
- valid &= t > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale; // ignore self intersections
- if (unlikely(none(valid))) return false;
-
- /* ignore denormalized segments */
- const Vec3vf<M> T = v1.xyz()-v0.xyz();
- valid &= (T.x != vfloat<M>(zero)) | (T.y != vfloat<M>(zero)) | (T.z != vfloat<M>(zero));
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- LineIntersectorHitM<M> hit(u,zero,t,T);
- return epilog(valid,hit);
- }
- };
-
- template<int M, int K>
- struct FlatLinearCurveIntersectorK
- {
- typedef CurvePrecalculationsK<K> Precalculations;
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- RayK<K>& ray, size_t k,
- IntersectContext* context,
- const LineSegments* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
- const Epilog& epilog)
- {
- /* transform end points into ray space */
- vbool<M> valid = valid_i;
- vfloat<M> depth_scale = pre.depth_scale[k];
- LinearSpace3<Vec3vf<M>> ray_space = pre.ray_space[k];
- const Vec3vf<M> ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
- const Vec3vf<M> ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
-
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec4vf<M> v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i);
-
- Vec4vf<M> p0(xfmVector(ray_space,v0.xyz()-ray_org), v0.w);
- Vec4vf<M> p1(xfmVector(ray_space,v1.xyz()-ray_org), v1.w);
-
- /* approximative intersection with cone */
- const Vec4vf<M> v = p1-p0;
- const Vec4vf<M> w = -p0;
- const vfloat<M> d0 = madd(w.x,v.x,w.y*v.y);
- const vfloat<M> d1 = madd(v.x,v.x,v.y*v.y);
- const vfloat<M> u = clamp(d0*rcp(d1),vfloat<M>(zero),vfloat<M>(one));
- const Vec4vf<M> p = madd(u,v,p0);
- const vfloat<M> t = p.z;
- const vfloat<M> d2 = madd(p.x,p.x,p.y*p.y);
- const vfloat<M> r = p.w;
- const vfloat<M> r2 = r*r;
- valid &= (d2 <= r2) & (vfloat<M>(ray.tnear()[k]) <= t) & (t <= vfloat<M>(ray.tfar[k]));
- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
- valid &= t > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale; // ignore self intersections
- if (unlikely(none(valid))) return false;
-
- /* ignore denormalized segments */
- const Vec3vf<M> T = v1.xyz()-v0.xyz();
- valid &= (T.x != vfloat<M>(zero)) | (T.y != vfloat<M>(zero)) | (T.z != vfloat<M>(zero));
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- LineIntersectorHitM<M> hit(u,zero,t,T);
- return epilog(valid,hit);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/linei.h b/thirdparty/embree-aarch64/kernels/geometry/linei.h
deleted file mode 100644
index a72029ca53..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/linei.h
+++ /dev/null
@@ -1,709 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-
-namespace embree
-{
- template<int M>
- struct LineMi
- {
- /* Virtual interface to query information about the line segment type */
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* primitive supports multiple time segments */
- static const bool singleTimeSegment = false;
-
- /* Returns maximum number of stored line segments */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N line segments */
- static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
-
- /* Returns required number of bytes for N line segments */
- static __forceinline size_t bytes(size_t N) { return blocks(N)*sizeof(LineMi); }
-
- public:
-
- /* Default constructor */
- __forceinline LineMi() { }
-
- /* Construction from vertices and IDs */
- __forceinline LineMi(const vuint<M>& v0, unsigned short leftExists, unsigned short rightExists, const vuint<M>& geomIDs, const vuint<M>& primIDs, Geometry::GType gtype)
- : gtype((unsigned char)gtype), m((unsigned char)popcnt(vuint<M>(primIDs) != vuint<M>(-1))), sharedGeomID(geomIDs[0]), leftExists (leftExists), rightExists(rightExists), v0(v0), primIDs(primIDs)
- {
- assert(all(vuint<M>(geomID()) == geomIDs));
- }
-
- /* Returns a mask that tells which line segments are valid */
- __forceinline vbool<M> valid() const { return primIDs != vuint<M>(-1); }
-
- /* Returns a mask that tells which line segments are valid */
- template<int Mx>
- __forceinline vbool<Mx> valid() const { return vuint<Mx>(primIDs) != vuint<Mx>(-1); }
-
- /* Returns if the specified line segment is valid */
- __forceinline bool valid(const size_t i) const { assert(i<M); return primIDs[i] != -1; }
-
- /* Returns the number of stored line segments */
- __forceinline size_t size() const { return bsf(~movemask(valid())); }
-
- /* Returns the geometry IDs */
- //template<class T>
- //static __forceinline T unmask(T &index) { return index & 0x3fffffff; }
-
- __forceinline unsigned int geomID(unsigned int i = 0) const { return sharedGeomID; }
- //__forceinline vuint<M> geomID() { return unmask(geomIDs); }
- //__forceinline const vuint<M> geomID() const { return unmask(geomIDs); }
- //__forceinline unsigned int geomID(const size_t i) const { assert(i<M); return unmask(geomIDs[i]); }
-
- /* Returns the primitive IDs */
- __forceinline vuint<M>& primID() { return primIDs; }
- __forceinline const vuint<M>& primID() const { return primIDs; }
- __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
-
- /* gather the line segments */
- __forceinline void gather(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- const LineSegments* geom) const;
-
- __forceinline void gatheri(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- const LineSegments* geom,
- const int itime) const;
-
- __forceinline void gather(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- const LineSegments* geom,
- float time) const;
-
- /* gather the line segments with lateral info */
- __forceinline void gather(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- Vec4vf<M>& pL,
- Vec4vf<M>& pR,
- const LineSegments* geom) const;
-
- __forceinline void gatheri(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- Vec4vf<M>& pL,
- Vec4vf<M>& pR,
- const LineSegments* geom,
- const int itime) const;
-
- __forceinline void gather(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- Vec4vf<M>& pL,
- Vec4vf<M>& pR,
- const LineSegments* geom,
- float time) const;
-
- __forceinline void gather(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- vbool<M>& cL,
- vbool<M>& cR,
- const LineSegments* geom) const;
-
- __forceinline void gatheri(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- vbool<M>& cL,
- vbool<M>& cR,
- const LineSegments* geom,
- const int itime) const;
-
- __forceinline void gather(Vec4vf<M>& p0,
- Vec4vf<M>& p1,
- vbool<M>& cL,
- vbool<M>& cR,
- const LineSegments* geom,
- float time) const;
-
- /* Calculate the bounds of the line segments */
- __forceinline const BBox3fa bounds(const Scene* scene, size_t itime = 0) const
- {
- BBox3fa bounds = empty;
- for (size_t i=0; i<M && valid(i); i++)
- {
- const LineSegments* geom = scene->get<LineSegments>(geomID(i));
- const Vec3ff& p0 = geom->vertex(v0[i]+0,itime);
- const Vec3ff& p1 = geom->vertex(v0[i]+1,itime);
- BBox3fa b = merge(BBox3fa(p0),BBox3fa(p1));
- b = enlarge(b,Vec3fa(max(p0.w,p1.w)));
- bounds.extend(b);
- }
- return bounds;
- }
-
- /* Calculate the linear bounds of the primitive */
- __forceinline LBBox3fa linearBounds(const Scene* scene, size_t itime) {
- return LBBox3fa(bounds(scene,itime+0), bounds(scene,itime+1));
- }
-
- __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps) {
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<M && valid(i); i++)
- {
- const LineSegments* geom = scene->get<LineSegments>(geomID(i));
- allBounds.extend(geom->linearBounds(primID(i), itime, numTimeSteps));
- }
- return allBounds;
- }
-
- __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range)
- {
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<M && valid(i); i++)
- {
- const LineSegments* geom = scene->get<LineSegments>(geomID((unsigned int)i));
- allBounds.extend(geom->linearBounds(primID(i), time_range));
- }
- return allBounds;
- }
-
- /* Fill line segment from line segment list */
- template<typename PrimRefT>
- __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene)
- {
- Geometry::GType gty = scene->get(prims[begin].geomID())->getType();
- vuint<M> geomID, primID;
- vuint<M> v0;
- unsigned short leftExists = 0;
- unsigned short rightExists = 0;
- const PrimRefT* prim = &prims[begin];
-
- for (size_t i=0; i<M; i++)
- {
- const LineSegments* geom = scene->get<LineSegments>(prim->geomID());
- if (begin<end) {
- geomID[i] = prim->geomID();
- primID[i] = prim->primID();
- v0[i] = geom->segment(prim->primID());
- leftExists |= geom->segmentLeftExists(primID[i]) << i;
- rightExists |= geom->segmentRightExists(primID[i]) << i;
- begin++;
- } else {
- assert(i);
- if (i>0) {
- geomID[i] = geomID[i-1];
- primID[i] = -1;
- v0[i] = v0[i-1];
- }
- }
- if (begin<end) prim = &prims[begin]; // FIXME: remove this line
- }
- new (this) LineMi(v0,leftExists,rightExists,geomID,primID,gty); // FIXME: use non temporal store
- }
-
- template<typename BVH, typename Allocator>
- __forceinline static typename BVH::NodeRef createLeaf (BVH* bvh, const PrimRef* prims, const range<size_t>& set, const Allocator& alloc)
- {
- size_t start = set.begin();
- size_t items = LineMi::blocks(set.size());
- size_t numbytes = LineMi::bytes(set.size());
- LineMi* accel = (LineMi*) alloc.malloc1(numbytes,M*sizeof(float));
- for (size_t i=0; i<items; i++) {
- accel[i].fill(prims,start,set.end(),bvh->scene);
- }
- return bvh->encodeLeaf((char*)accel,items);
- };
-
- __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
- {
- fill(prims,begin,end,scene);
- return linearBounds(scene,itime);
- }
-
- __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
- {
- fill(prims,begin,end,scene);
- return linearBounds(scene,time_range);
- }
-
- template<typename BVH, typename SetMB, typename Allocator>
- __forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc)
- {
- size_t start = prims.begin();
- size_t end = prims.end();
- size_t items = LineMi::blocks(prims.size());
- size_t numbytes = LineMi::bytes(prims.size());
- LineMi* accel = (LineMi*) alloc.malloc1(numbytes,M*sizeof(float));
- const typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,items);
-
- LBBox3fa bounds = empty;
- for (size_t i=0; i<items; i++)
- bounds.extend(accel[i].fillMB(prims.prims->data(),start,end,bvh->scene,prims.time_range));
-
- return typename BVH::NodeRecordMB4D(node,bounds,prims.time_range);
- };
-
- /* Updates the primitive */
- __forceinline BBox3fa update(LineSegments* geom)
- {
- BBox3fa bounds = empty;
- for (size_t i=0; i<M && valid(i); i++)
- {
- const Vec3ff& p0 = geom->vertex(v0[i]+0);
- const Vec3ff& p1 = geom->vertex(v0[i]+1);
- BBox3fa b = merge(BBox3fa(p0),BBox3fa(p1));
- b = enlarge(b,Vec3fa(max(p0.w,p1.w)));
- bounds.extend(b);
- }
- return bounds;
- }
-
- /*! output operator */
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const LineMi& line) {
- return cout << "Line" << M << "i {" << line.v0 << ", " << line.geomID() << ", " << line.primID() << "}";
- }
-
- public:
- unsigned char gtype;
- unsigned char m;
- unsigned int sharedGeomID;
- unsigned short leftExists, rightExists;
- vuint<M> v0; // index of start vertex
- private:
- vuint<M> primIDs; // primitive ID
- };
-
- template<>
- __forceinline void LineMi<4>::gather(Vec4vf4& p0,
- Vec4vf4& p1,
- const LineSegments* geom) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0]));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1]));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2]));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3]));
- transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
-
- const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1));
- const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1));
- const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1));
- const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1));
- transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
- }
-
- template<>
- __forceinline void LineMi<4>::gatheri(Vec4vf4& p0,
- Vec4vf4& p1,
- const LineSegments* geom,
- const int itime) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
- transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
-
- const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
- const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
- const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
- const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
- transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
- }
-
- template<>
- __forceinline void LineMi<4>::gather(Vec4vf4& p0,
- Vec4vf4& p1,
- const LineSegments* geom,
- float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf4 a0,a1;
- gatheri(a0,a1,geom,itime);
- Vec4vf4 b0,b1;
- gatheri(b0,b1,geom,itime+1);
- p0 = lerp(a0,b0,vfloat4(ftime));
- p1 = lerp(a1,b1,vfloat4(ftime));
- }
-
- template<>
- __forceinline void LineMi<4>::gather(Vec4vf4& p0,
- Vec4vf4& p1,
- vbool4& cL,
- vbool4& cR,
- const LineSegments* geom) const
- {
- gather(p0,p1,geom);
- cL = !vbool4(leftExists);
- cR = !vbool4(rightExists);
- }
-
- template<>
- __forceinline void LineMi<4>::gatheri(Vec4vf4& p0,
- Vec4vf4& p1,
- vbool4& cL,
- vbool4& cR,
- const LineSegments* geom,
- const int itime) const
- {
- gatheri(p0,p1,geom,itime);
- cL = !vbool4(leftExists);
- cR = !vbool4(rightExists);
- }
-
- template<>
- __forceinline void LineMi<4>::gather(Vec4vf4& p0,
- Vec4vf4& p1,
- vbool4& cL,
- vbool4& cR,
- const LineSegments* geom,
- float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf4 a0,a1;
- gatheri(a0,a1,geom,itime);
- Vec4vf4 b0,b1;
- gatheri(b0,b1,geom,itime+1);
- p0 = lerp(a0,b0,vfloat4(ftime));
- p1 = lerp(a1,b1,vfloat4(ftime));
- cL = !vbool4(leftExists);
- cR = !vbool4(rightExists);
- }
-
- template<>
- __forceinline void LineMi<4>::gather(Vec4vf4& p0,
- Vec4vf4& p1,
- Vec4vf4& pL,
- Vec4vf4& pR,
- const LineSegments* geom) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0]));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1]));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2]));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3]));
- transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
-
- const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1));
- const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1));
- const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1));
- const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1));
- transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
-
- const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1)) : vfloat4(inf);
- const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1)) : vfloat4(inf);
- const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1)) : vfloat4(inf);
- const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1)) : vfloat4(inf);
- transpose(l0,l1,l2,l3,pL.x,pL.y,pL.z,pL.w);
-
- const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2)) : vfloat4(inf);
- const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2)) : vfloat4(inf);
- const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2)) : vfloat4(inf);
- const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2)) : vfloat4(inf);
- transpose(r0,r1,r2,r3,pR.x,pR.y,pR.z,pR.w);
- }
-
- template<>
- __forceinline void LineMi<4>::gatheri(Vec4vf4& p0,
- Vec4vf4& p1,
- Vec4vf4& pL,
- Vec4vf4& pR,
- const LineSegments* geom,
- const int itime) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
- transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
-
- const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
- const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
- const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
- const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
- transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
-
- const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1,itime)) : vfloat4(inf);
- const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1,itime)) : vfloat4(inf);
- const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1,itime)) : vfloat4(inf);
- const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1,itime)) : vfloat4(inf);
- transpose(l0,l1,l2,l3,pL.x,pL.y,pL.z,pL.w);
-
- const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2,itime)) : vfloat4(inf);
- const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2,itime)) : vfloat4(inf);
- const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2,itime)) : vfloat4(inf);
- const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2,itime)) : vfloat4(inf);
- transpose(r0,r1,r2,r3,pR.x,pR.y,pR.z,pR.w);
- }
-
- template<>
- __forceinline void LineMi<4>::gather(Vec4vf4& p0,
- Vec4vf4& p1,
- Vec4vf4& pL,
- Vec4vf4& pR,
- const LineSegments* geom,
- float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf4 a0,a1,aL,aR;
- gatheri(a0,a1,aL,aR,geom,itime);
- Vec4vf4 b0,b1,bL,bR;
- gatheri(b0,b1,bL,bR,geom,itime+1);
- p0 = lerp(a0,b0,vfloat4(ftime));
- p1 = lerp(a1,b1,vfloat4(ftime));
- pL = lerp(aL,bL,vfloat4(ftime));
- pR = lerp(aR,bR,vfloat4(ftime));
- }
-
-#if defined(__AVX__)
-
- template<>
- __forceinline void LineMi<8>::gather(Vec4vf8& p0,
- Vec4vf8& p1,
- const LineSegments* geom) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0]));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1]));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2]));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3]));
- const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4]));
- const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5]));
- const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6]));
- const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7]));
- transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
-
- const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1));
- const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1));
- const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1));
- const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1));
- const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1));
- const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1));
- const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1));
- const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1));
- transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
- }
-
- template<>
- __forceinline void LineMi<8>::gatheri(Vec4vf8& p0,
- Vec4vf8& p1,
- const LineSegments* geom,
- const int itime) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
- const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4],itime));
- const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5],itime));
- const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6],itime));
- const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7],itime));
- transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
-
- const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
- const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
- const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
- const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
- const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1,itime));
- const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1,itime));
- const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1,itime));
- const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1,itime));
- transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
- }
-
- template<>
- __forceinline void LineMi<8>::gather(Vec4vf8& p0,
- Vec4vf8& p1,
- const LineSegments* geom,
- float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf8 a0,a1;
- gatheri(a0,a1,geom,itime);
- Vec4vf8 b0,b1;
- gatheri(b0,b1,geom,itime+1);
- p0 = lerp(a0,b0,vfloat8(ftime));
- p1 = lerp(a1,b1,vfloat8(ftime));
- }
-
- template<>
- __forceinline void LineMi<8>::gather(Vec4vf8& p0,
- Vec4vf8& p1,
- Vec4vf8& pL,
- Vec4vf8& pR,
- const LineSegments* geom) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0]));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1]));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2]));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3]));
- const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4]));
- const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5]));
- const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6]));
- const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7]));
- transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
-
- const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1));
- const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1));
- const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1));
- const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1));
- const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1));
- const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1));
- const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1));
- const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1));
- transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
-
- const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1)) : vfloat4(inf);
- const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1)) : vfloat4(inf);
- const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1)) : vfloat4(inf);
- const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1)) : vfloat4(inf);
- const vfloat4 l4 = (leftExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]-1)) : vfloat4(inf);
- const vfloat4 l5 = (leftExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]-1)) : vfloat4(inf);
- const vfloat4 l6 = (leftExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]-1)) : vfloat4(inf);
- const vfloat4 l7 = (leftExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]-1)) : vfloat4(inf);
- transpose(l0,l1,l2,l3,l4,l5,l6,l7,pL.x,pL.y,pL.z,pL.w);
-
- const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2)) : vfloat4(inf);
- const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2)) : vfloat4(inf);
- const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2)) : vfloat4(inf);
- const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2)) : vfloat4(inf);
- const vfloat4 r4 = (rightExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]+2)) : vfloat4(inf);
- const vfloat4 r5 = (rightExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]+2)) : vfloat4(inf);
- const vfloat4 r6 = (rightExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]+2)) : vfloat4(inf);
- const vfloat4 r7 = (rightExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]+2)) : vfloat4(inf);
- transpose(r0,r1,r2,r3,r4,r5,r6,r7,pR.x,pR.y,pR.z,pR.w);
- }
-
- template<>
- __forceinline void LineMi<8>::gatheri(Vec4vf8& p0,
- Vec4vf8& p1,
- Vec4vf8& pL,
- Vec4vf8& pR,
- const LineSegments* geom,
- const int itime) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
- const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4],itime));
- const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5],itime));
- const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6],itime));
- const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7],itime));
- transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
-
- const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
- const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
- const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
- const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
- const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1,itime));
- const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1,itime));
- const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1,itime));
- const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1,itime));
- transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
-
- const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1,itime)) : vfloat4(inf);
- const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1,itime)) : vfloat4(inf);
- const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1,itime)) : vfloat4(inf);
- const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1,itime)) : vfloat4(inf);
- const vfloat4 l4 = (leftExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]-1,itime)) : vfloat4(inf);
- const vfloat4 l5 = (leftExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]-1,itime)) : vfloat4(inf);
- const vfloat4 l6 = (leftExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]-1,itime)) : vfloat4(inf);
- const vfloat4 l7 = (leftExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]-1,itime)) : vfloat4(inf);
- transpose(l0,l1,l2,l3,l4,l5,l6,l7,pL.x,pL.y,pL.z,pL.w);
-
- const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2,itime)) : vfloat4(inf);
- const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2,itime)) : vfloat4(inf);
- const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2,itime)) : vfloat4(inf);
- const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2,itime)) : vfloat4(inf);
- const vfloat4 r4 = (rightExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]+2,itime)) : vfloat4(inf);
- const vfloat4 r5 = (rightExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]+2,itime)) : vfloat4(inf);
- const vfloat4 r6 = (rightExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]+2,itime)) : vfloat4(inf);
- const vfloat4 r7 = (rightExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]+2,itime)) : vfloat4(inf);
- transpose(r0,r1,r2,r3,r4,r5,r6,r7,pR.x,pR.y,pR.z,pR.w);
- }
-
- template<>
- __forceinline void LineMi<8>::gather(Vec4vf8& p0,
- Vec4vf8& p1,
- Vec4vf8& pL,
- Vec4vf8& pR,
- const LineSegments* geom,
- float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf8 a0,a1,aL,aR;
- gatheri(a0,a1,aL,aR,geom,itime);
- Vec4vf8 b0,b1,bL,bR;
- gatheri(b0,b1,bL,bR,geom,itime+1);
- p0 = lerp(a0,b0,vfloat8(ftime));
- p1 = lerp(a1,b1,vfloat8(ftime));
- pL = lerp(aL,bL,vfloat8(ftime));
- pR = lerp(aR,bR,vfloat8(ftime));
- }
-
- template<>
- __forceinline void LineMi<8>::gather(Vec4vf8& p0,
- Vec4vf8& p1,
- vbool8& cL,
- vbool8& cR,
- const LineSegments* geom) const
- {
- gather(p0,p1,geom);
- cL = !vbool8(leftExists);
- cR = !vbool8(rightExists);
- }
-
- template<>
- __forceinline void LineMi<8>::gatheri(Vec4vf8& p0,
- Vec4vf8& p1,
- vbool8& cL,
- vbool8& cR,
- const LineSegments* geom,
- const int itime) const
- {
- gatheri(p0,p1,geom,itime);
- cL = !vbool8(leftExists);
- cR = !vbool8(rightExists);
- }
-
- template<>
- __forceinline void LineMi<8>::gather(Vec4vf8& p0,
- Vec4vf8& p1,
- vbool8& cL,
- vbool8& cR,
- const LineSegments* geom,
- float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf8 a0,a1;
- gatheri(a0,a1,geom,itime);
- Vec4vf8 b0,b1;
- gatheri(b0,b1,geom,itime+1);
- p0 = lerp(a0,b0,vfloat8(ftime));
- p1 = lerp(a1,b1,vfloat8(ftime));
- cL = !vbool8(leftExists);
- cR = !vbool8(rightExists);
- }
-
-#endif
-
- template<int M>
- typename LineMi<M>::Type LineMi<M>::type;
-
- typedef LineMi<4> Line4i;
- typedef LineMi<8> Line8i;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/linei_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/linei_intersector.h
deleted file mode 100644
index a431796a88..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/linei_intersector.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "linei.h"
-#include "line_intersector.h"
-#include "intersector_epilog.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M, int Mx, bool filter>
- struct FlatLinearCurveMiIntersector1
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1; line.gather(v0,v1,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- FlatLinearCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,Intersect1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1; line.gather(v0,v1,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- return FlatLinearCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,Occluded1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
- }
- };
-
- template<int M, int Mx, bool filter>
- struct FlatLinearCurveMiMBIntersector1
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1; line.gather(v0,v1,geom,ray.time());
- const vbool<Mx> valid = line.template valid<Mx>();
- FlatLinearCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,Intersect1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1; line.gather(v0,v1,geom,ray.time());
- const vbool<Mx> valid = line.template valid<Mx>();
- return FlatLinearCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,Occluded1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct FlatLinearCurveMiIntersectorK
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1; line.gather(v0,v1,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- FlatLinearCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1; line.gather(v0,v1,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- return FlatLinearCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct FlatLinearCurveMiMBIntersectorK
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1; line.gather(v0,v1,geom,ray.time()[k]);
- const vbool<Mx> valid = line.template valid<Mx>();
- FlatLinearCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1; line.gather(v0,v1,geom,ray.time()[k]);
- const vbool<Mx> valid = line.template valid<Mx>();
- return FlatLinearCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/object.h b/thirdparty/embree-aarch64/kernels/geometry/object.h
deleted file mode 100644
index f26391de52..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/object.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-
-namespace embree
-{
- struct Object
- {
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* primitive supports multiple time segments */
- static const bool singleTimeSegment = false;
-
- /* Returns maximum number of stored primitives */
- static __forceinline size_t max_size() { return 1; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return N; }
-
- public:
-
- /*! constructs a virtual object */
- Object (unsigned geomID, unsigned primID)
- : _geomID(geomID), _primID(primID) {}
-
- __forceinline unsigned geomID() const {
- return _geomID;
- }
-
- __forceinline unsigned primID() const {
- return _primID;
- }
-
- /*! fill triangle from triangle list */
- __forceinline void fill(const PrimRef* prims, size_t& i, size_t end, Scene* scene)
- {
- const PrimRef& prim = prims[i]; i++;
- new (this) Object(prim.geomID(), prim.primID());
- }
-
- /*! fill triangle from triangle list */
- __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& i, size_t end, Scene* scene, size_t itime)
- {
- const PrimRef& prim = prims[i]; i++;
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- new (this) Object(geomID, primID);
- AccelSet* accel = (AccelSet*) scene->get(geomID);
- return accel->linearBounds(primID,itime);
- }
-
- /*! fill triangle from triangle list */
- __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& i, size_t end, Scene* scene, const BBox1f time_range)
- {
- const PrimRefMB& prim = prims[i]; i++;
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- new (this) Object(geomID, primID);
- AccelSet* accel = (AccelSet*) scene->get(geomID);
- return accel->linearBounds(primID,time_range);
- }
-
- /* Updates the primitive */
- __forceinline BBox3fa update(AccelSet* mesh) {
- return mesh->bounds(primID());
- }
-
- private:
- unsigned int _geomID; //!< geometry ID
- unsigned int _primID; //!< primitive ID
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/object_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/object_intersector.h
deleted file mode 100644
index 97882e0e59..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/object_intersector.h
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "object.h"
-#include "../common/ray.h"
-
-namespace embree
-{
- namespace isa
- {
- template<bool mblur>
- struct ObjectIntersector1
- {
- typedef Object Primitive;
-
- static const bool validIntersectorK = false;
-
- struct Precalculations {
- __forceinline Precalculations() {}
- __forceinline Precalculations (const Ray& ray, const void *ptr) {}
- };
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
- {
- AccelSet* accel = (AccelSet*) context->scene->get(prim.geomID());
-
- /* perform ray mask test */
-#if defined(EMBREE_RAY_MASK)
- if ((ray.mask & accel->mask) == 0)
- return;
-#endif
-
- accel->intersect(ray,prim.geomID(),prim.primID(),context,reportIntersection1);
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
- {
- AccelSet* accel = (AccelSet*) context->scene->get(prim.geomID());
- /* perform ray mask test */
-#if defined(EMBREE_RAY_MASK)
- if ((ray.mask & accel->mask) == 0)
- return false;
-#endif
-
- accel->occluded(ray,prim.geomID(),prim.primID(),context,&reportOcclusion1);
- return ray.tfar < 0.0f;
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& prim)
- {
- AccelSet* accel = (AccelSet*)context->scene->get(prim.geomID());
- context->geomID = prim.geomID();
- context->primID = prim.primID();
- return accel->pointQuery(query, context);
- }
-
- template<int K>
- static __forceinline void intersectK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
- {
- assert(false);
- }
-
- template<int K>
- static __forceinline vbool<K> occludedK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
- {
- assert(false);
- return valid;
- }
- };
-
- template<int K, bool mblur>
- struct ObjectIntersectorK
- {
- typedef Object Primitive;
-
- struct Precalculations {
- __forceinline Precalculations (const vbool<K>& valid, const RayK<K>& ray) {}
- };
-
- static __forceinline void intersect(const vbool<K>& valid_i, const Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& prim)
- {
- vbool<K> valid = valid_i;
- AccelSet* accel = (AccelSet*) context->scene->get(prim.geomID());
-
- /* perform ray mask test */
-#if defined(EMBREE_RAY_MASK)
- valid &= (ray.mask & accel->mask) != 0;
- if (none(valid)) return;
-#endif
- accel->intersect(valid,ray,prim.geomID(),prim.primID(),context,&reportIntersection1);
- }
-
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& prim)
- {
- vbool<K> valid = valid_i;
- AccelSet* accel = (AccelSet*) context->scene->get(prim.geomID());
-
- /* perform ray mask test */
-#if defined(EMBREE_RAY_MASK)
- valid &= (ray.mask & accel->mask) != 0;
- if (none(valid)) return false;
-#endif
- accel->occluded(valid,ray,prim.geomID(),prim.primID(),context,&reportOcclusion1);
- return ray.tfar < 0.0f;
- }
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
- intersect(vbool<K>(1<<int(k)),pre,ray,context,prim);
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
- occluded(vbool<K>(1<<int(k)),pre,ray,context,prim);
- return ray.tfar[k] < 0.0f;
- }
- };
-
- typedef ObjectIntersectorK<4,false> ObjectIntersector4;
- typedef ObjectIntersectorK<8,false> ObjectIntersector8;
- typedef ObjectIntersectorK<16,false> ObjectIntersector16;
-
- typedef ObjectIntersectorK<4,true> ObjectIntersector4MB;
- typedef ObjectIntersectorK<8,true> ObjectIntersector8MB;
- typedef ObjectIntersectorK<16,true> ObjectIntersector16MB;
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/plane.h b/thirdparty/embree-aarch64/kernels/geometry/plane.h
deleted file mode 100644
index ebe45db558..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/plane.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-
-namespace embree
-{
- namespace isa
- {
- struct HalfPlane
- {
- const Vec3fa P; //!< plane origin
- const Vec3fa N; //!< plane normal
-
- __forceinline HalfPlane(const Vec3fa& P, const Vec3fa& N)
- : P(P), N(N) {}
-
- __forceinline BBox1f intersect(const Vec3fa& ray_org, const Vec3fa& ray_dir) const
- {
- Vec3fa O = Vec3fa(ray_org) - P;
- Vec3fa D = Vec3fa(ray_dir);
- float ON = dot(O,N);
- float DN = dot(D,N);
- bool eps = abs(DN) < min_rcp_input;
- float t = -ON*rcp(DN);
- float lower = select(eps || DN < 0.0f, float(neg_inf), t);
- float upper = select(eps || DN > 0.0f, float(pos_inf), t);
- return BBox1f(lower,upper);
- }
- };
-
- template<int M>
- struct HalfPlaneN
- {
- const Vec3vf<M> P; //!< plane origin
- const Vec3vf<M> N; //!< plane normal
-
- __forceinline HalfPlaneN(const Vec3vf<M>& P, const Vec3vf<M>& N)
- : P(P), N(N) {}
-
- __forceinline BBox<vfloat<M>> intersect(const Vec3fa& ray_org, const Vec3fa& ray_dir) const
- {
- Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray_org) - P;
- Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray_dir);
- vfloat<M> ON = dot(O,N);
- vfloat<M> DN = dot(D,N);
- vbool<M> eps = abs(DN) < min_rcp_input;
- vfloat<M> t = -ON*rcp(DN);
- vfloat<M> lower = select(eps | DN < 0.0f, vfloat<M>(neg_inf), t);
- vfloat<M> upper = select(eps | DN > 0.0f, vfloat<M>(pos_inf), t);
- return BBox<vfloat<M>>(lower,upper);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/pointi.h b/thirdparty/embree-aarch64/kernels/geometry/pointi.h
deleted file mode 100644
index 4ba298e86b..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/pointi.h
+++ /dev/null
@@ -1,417 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-
-namespace embree
-{
- template<int M>
- struct PointMi
- {
- /* Virtual interface to query information about the line segment type */
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
- /* primitive supports multiple time segments */
- static const bool singleTimeSegment = false;
-
- /* Returns maximum number of stored line segments */
- static __forceinline size_t max_size()
- {
- return M;
- }
-
- /* Returns required number of primitive blocks for N line segments */
- static __forceinline size_t blocks(size_t N)
- {
- return (N + max_size() - 1) / max_size();
- }
-
- /* Returns required number of bytes for N line segments */
- static __forceinline size_t bytes(size_t N)
- {
- return blocks(N) * sizeof(PointMi);
- }
-
- public:
- /* Default constructor */
- __forceinline PointMi() {}
-
- /* Construction from vertices and IDs */
- __forceinline PointMi(const vuint<M>& geomIDs, const vuint<M>& primIDs, Geometry::GType gtype, uint32_t numPrimitives)
- : gtype((unsigned char)gtype),
- numPrimitives(numPrimitives),
- sharedGeomID(geomIDs[0]),
- primIDs(primIDs)
- {
- assert(all(vuint<M>(geomID()) == geomIDs));
- }
-
- /* Returns a mask that tells which line segments are valid */
- __forceinline vbool<M> valid() const {
- return vint<M>(step) < vint<M>(numPrimitives);
- }
-
- /* Returns a mask that tells which line segments are valid */
- template<int Mx> __forceinline vbool<Mx> valid() const {
- return vint<Mx>(step) < vint<Mx>(numPrimitives);
- }
-
- /* Returns if the specified line segment is valid */
- __forceinline bool valid(const size_t i) const
- {
- assert(i < M);
- return i < numPrimitives;
- }
-
- /* Returns the number of stored line segments */
- __forceinline size_t size() const {
- return numPrimitives;
- }
-
- __forceinline unsigned int geomID(unsigned int i = 0) const {
- return sharedGeomID;
- }
-
- __forceinline vuint<M>& primID() {
- return primIDs;
- }
- __forceinline const vuint<M>& primID() const {
- return primIDs;
- }
- __forceinline unsigned int primID(const size_t i) const {
- assert(i < M);
- return primIDs[i];
- }
-
- /* gather the line segments */
- __forceinline void gather(Vec4vf<M>& p0, const Points* geom) const;
- __forceinline void gather(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom) const;
-
- __forceinline void gatheri(Vec4vf<M>& p0, const Points* geom, const int itime) const;
- __forceinline void gatheri(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom, const int itime) const;
-
- __forceinline void gather(Vec4vf<M>& p0, const Points* geom, float time) const;
- __forceinline void gather(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom, float time) const;
-
- /* Calculate the bounds of the line segments */
- __forceinline const BBox3fa bounds(const Scene* scene, size_t itime = 0) const
- {
- BBox3fa bounds = empty;
- for (size_t i = 0; i < M && valid(i); i++) {
- const Points* geom = scene->get<Points>(geomID(i));
- bounds.extend(geom->bounds(primID(i),itime));
- }
- return bounds;
- }
-
- /* Calculate the linear bounds of the primitive */
- __forceinline LBBox3fa linearBounds(const Scene* scene, size_t itime) {
- return LBBox3fa(bounds(scene, itime + 0), bounds(scene, itime + 1));
- }
-
- __forceinline LBBox3fa linearBounds(const Scene* const scene, size_t itime, size_t numTimeSteps)
- {
- LBBox3fa allBounds = empty;
- for (size_t i = 0; i < M && valid(i); i++) {
- const Points* geom = scene->get<Points>(geomID(i));
- allBounds.extend(geom->linearBounds(primID(i), itime, numTimeSteps));
- }
- return allBounds;
- }
-
- __forceinline LBBox3fa linearBounds(const Scene* const scene, const BBox1f time_range)
- {
- LBBox3fa allBounds = empty;
- for (size_t i = 0; i < M && valid(i); i++) {
- const Points* geom = scene->get<Points>(geomID((unsigned int)i));
- allBounds.extend(geom->linearBounds(primID(i), time_range));
- }
- return allBounds;
- }
-
- /* Fill line segment from line segment list */
- template<typename PrimRefT>
- __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene)
- {
- Geometry::GType gty = scene->get(prims[begin].geomID())->getType();
- vuint<M> geomID, primID;
- vuint<M> v0;
- const PrimRefT* prim = &prims[begin];
-
- int numPrimitives = 0;
- for (size_t i = 0; i < M; i++) {
- if (begin < end) {
- geomID[i] = prim->geomID();
- primID[i] = prim->primID();
- begin++;
- numPrimitives++;
- } else {
- assert(i);
- if (i > 0) {
- geomID[i] = geomID[i - 1];
- primID[i] = primID[i - 1];
- }
- }
- if (begin < end)
- prim = &prims[begin]; // FIXME: remove this line
- }
- new (this) PointMi(geomID, primID, gty, numPrimitives); // FIXME: use non temporal store
- }
-
- template<typename BVH, typename Allocator>
- __forceinline static typename BVH::NodeRef createLeaf(BVH* bvh,
- const PrimRef* prims,
- const range<size_t>& set,
- const Allocator& alloc)
- {
- size_t start = set.begin();
- size_t items = PointMi::blocks(set.size());
- size_t numbytes = PointMi::bytes(set.size());
- PointMi* accel = (PointMi*)alloc.malloc1(numbytes, M * sizeof(float));
- for (size_t i = 0; i < items; i++) {
- accel[i].fill(prims, start, set.end(), bvh->scene);
- }
- return bvh->encodeLeaf((char*)accel, items);
- };
-
- __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
- {
- fill(prims, begin, end, scene);
- return linearBounds(scene, itime);
- }
-
- __forceinline LBBox3fa fillMB(
- const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
- {
- fill(prims, begin, end, scene);
- return linearBounds(scene, time_range);
- }
-
- template<typename BVH, typename SetMB, typename Allocator>
- __forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc)
- {
- size_t start = prims.object_range.begin();
- size_t end = prims.object_range.end();
- size_t items = PointMi::blocks(prims.object_range.size());
- size_t numbytes = PointMi::bytes(prims.object_range.size());
- PointMi* accel = (PointMi*)alloc.malloc1(numbytes, M * sizeof(float));
- const typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel, items);
-
- LBBox3fa bounds = empty;
- for (size_t i = 0; i < items; i++)
- bounds.extend(accel[i].fillMB(prims.prims->data(), start, end, bvh->scene, prims.time_range));
-
- return typename BVH::NodeRecordMB4D(node, bounds, prims.time_range);
- };
-
- /*! output operator */
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const PointMi& line)
- {
- return cout << "Line" << M << "i {" << line.v0 << ", " << line.geomID() << ", " << line.primID() << "}";
- }
-
- public:
- unsigned char gtype;
- unsigned char numPrimitives;
- unsigned int sharedGeomID;
-
- private:
- vuint<M> primIDs; // primitive ID
- };
-
- template<>
- __forceinline void PointMi<4>::gather(Vec4vf4& p0, const Points* geom) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0)));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1)));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2)));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3)));
- transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w);
- }
-
- template<>
- __forceinline void PointMi<4>::gather(Vec4vf4& p0, Vec3vf4& n0, const Points* geom) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0)));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1)));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2)));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3)));
- transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w);
- const vfloat4 b0 = vfloat4(geom->normal(primID(0)));
- const vfloat4 b1 = vfloat4(geom->normal(primID(1)));
- const vfloat4 b2 = vfloat4(geom->normal(primID(2)));
- const vfloat4 b3 = vfloat4(geom->normal(primID(3)));
- transpose(b0, b1, b2, b3, n0.x, n0.y, n0.z);
- }
-
- template<>
- __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, const Points* geom, const int itime) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime));
- transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w);
- }
-
- template<>
- __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, const int itime) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime));
- transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w);
- const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime));
- const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime));
- const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime));
- const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime));
- transpose(b0, b1, b2, b3, n0.x, n0.y, n0.z);
- }
-
- template<>
- __forceinline void PointMi<4>::gather(Vec4vf4& p0, const Points* geom, float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf4 a0; gatheri(a0, geom, itime);
- Vec4vf4 b0; gatheri(b0, geom, itime + 1);
- p0 = lerp(a0, b0, vfloat4(ftime));
- }
-
- template<>
- __forceinline void PointMi<4>::gather(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf4 a0, b0;
- Vec3vf4 norm0, norm1;
- gatheri(a0, norm0, geom, itime);
- gatheri(b0, norm1, geom, itime + 1);
- p0 = lerp(a0, b0, vfloat4(ftime));
- n0 = lerp(norm0, norm1, vfloat4(ftime));
- }
-
-#if defined(__AVX__)
-
- template<>
- __forceinline void PointMi<8>::gather(Vec4vf8& p0, const Points* geom) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0)));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1)));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2)));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3)));
- const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4)));
- const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5)));
- const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6)));
- const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7)));
- transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w);
- }
-
- template<>
- __forceinline void PointMi<8>::gather(Vec4vf8& p0, Vec3vf8& n0, const Points* geom) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0)));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1)));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2)));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3)));
- const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4)));
- const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5)));
- const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6)));
- const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7)));
- transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w);
- const vfloat4 b0 = vfloat4(geom->normal(primID(0)));
- const vfloat4 b1 = vfloat4(geom->normal(primID(1)));
- const vfloat4 b2 = vfloat4(geom->normal(primID(2)));
- const vfloat4 b3 = vfloat4(geom->normal(primID(3)));
- const vfloat4 b4 = vfloat4(geom->normal(primID(4)));
- const vfloat4 b5 = vfloat4(geom->normal(primID(5)));
- const vfloat4 b6 = vfloat4(geom->normal(primID(6)));
- const vfloat4 b7 = vfloat4(geom->normal(primID(7)));
- transpose(b0, b1, b2, b3, b4, b5, b6, b7, n0.x, n0.y, n0.z);
- }
-
- template<>
- __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, const Points* geom, const int itime) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime));
- const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime));
- const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime));
- const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime));
- const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime));
- transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w);
- }
-
- template<>
- __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, const int itime) const
- {
- const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime));
- const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime));
- const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime));
- const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime));
- const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime));
- const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime));
- const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime));
- const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime));
- transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w);
- const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime));
- const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime));
- const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime));
- const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime));
- const vfloat4 b4 = vfloat4(geom->normal(primID(4), itime));
- const vfloat4 b5 = vfloat4(geom->normal(primID(5), itime));
- const vfloat4 b6 = vfloat4(geom->normal(primID(6), itime));
- const vfloat4 b7 = vfloat4(geom->normal(primID(7), itime));
- transpose(b0, b1, b2, b3, b4, b5, b6, b7, n0.x, n0.y, n0.z);
- }
-
- template<>
- __forceinline void PointMi<8>::gather(Vec4vf8& p0, const Points* geom, float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf8 a0;
- gatheri(a0, geom, itime);
- Vec4vf8 b0;
- gatheri(b0, geom, itime + 1);
- p0 = lerp(a0, b0, vfloat8(ftime));
- }
-
- template<>
- __forceinline void PointMi<8>::gather(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, float time) const
- {
- float ftime;
- const int itime = geom->timeSegment(time, ftime);
-
- Vec4vf8 a0, b0;
- Vec3vf8 norm0, norm1;
- gatheri(a0, norm0, geom, itime);
- gatheri(b0, norm1, geom, itime + 1);
- p0 = lerp(a0, b0, vfloat8(ftime));
- n0 = lerp(norm0, norm1, vfloat8(ftime));
- }
-#endif
-
- template<int M>
- typename PointMi<M>::Type PointMi<M>::type;
-
- typedef PointMi<4> Point4i;
- typedef PointMi<8> Point8i;
-
-} // namespace embree
diff --git a/thirdparty/embree-aarch64/kernels/geometry/primitive.h b/thirdparty/embree-aarch64/kernels/geometry/primitive.h
deleted file mode 100644
index 41e5b2b304..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/primitive.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-#include "../common/scene.h"
-#include "../../common/simd/simd.h"
-#include "../common/primref.h"
-#include "../common/primref_mb.h"
-
-namespace embree
-{
- struct PrimitiveType
- {
- /*! returns name of this primitive type */
- virtual const char* name() const = 0;
-
- /*! Returns the number of stored active primitives in a block. */
- virtual size_t sizeActive(const char* This) const = 0;
-
- /*! Returns the number of stored active and inactive primitives in a block. */
- virtual size_t sizeTotal(const char* This) const = 0;
-
- /*! Returns the number of bytes of block. */
- virtual size_t getBytes(const char* This) const = 0;
- };
-
- template<typename Primitive>
- struct PrimitivePointQuery1
- {
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& prim)
- {
- bool changed = false;
- for (size_t i = 0; i < Primitive::max_size(); i++)
- {
- if (!prim.valid(i)) break;
- STAT3(point_query.trav_prims,1,1,1);
- AccelSet* accel = (AccelSet*)context->scene->get(prim.geomID(i));
- context->geomID = prim.geomID(i);
- context->primID = prim.primID(i);
- changed |= accel->pointQuery(query, context);
- }
- return changed;
- }
-
- static __forceinline void pointQueryNoop(PointQuery* query, PointQueryContext* context, const Primitive& prim) { }
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/primitive4.cpp b/thirdparty/embree-aarch64/kernels/geometry/primitive4.cpp
deleted file mode 100644
index f93574c9c8..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/primitive4.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "primitive.h"
-#include "curveNv.h"
-#include "curveNi.h"
-#include "curveNi_mb.h"
-#include "linei.h"
-#include "triangle.h"
-#include "trianglev.h"
-#include "trianglev_mb.h"
-#include "trianglei.h"
-#include "quadv.h"
-#include "quadi.h"
-#include "subdivpatch1.h"
-#include "object.h"
-#include "instance.h"
-#include "subgrid.h"
-
-namespace embree
-{
- /********************** Curve4v **************************/
-
- template<>
- const char* Curve4v::Type::name () const {
- return "curve4v";
- }
-
- template<>
- size_t Curve4v::Type::sizeActive(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return ((Line4i*)This)->size();
- else
- return ((Curve4v*)This)->N;
- }
-
- template<>
- size_t Curve4v::Type::sizeTotal(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return 4;
- else
- return ((Curve4v*)This)->N;
- }
-
- template<>
- size_t Curve4v::Type::getBytes(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return Line4i::bytes(sizeActive(This));
- else
- return Curve4v::bytes(sizeActive(This));
- }
-
- /********************** Curve4i **************************/
-
- template<>
- const char* Curve4i::Type::name () const {
- return "curve4i";
- }
-
- template<>
- size_t Curve4i::Type::sizeActive(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return ((Line4i*)This)->size();
- else
- return ((Curve4i*)This)->N;
- }
-
- template<>
- size_t Curve4i::Type::sizeTotal(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return 4;
- else
- return ((Curve4i*)This)->N;
- }
-
- template<>
- size_t Curve4i::Type::getBytes(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return Line4i::bytes(sizeActive(This));
- else
- return Curve4i::bytes(sizeActive(This));
- }
-
- /********************** Curve4iMB **************************/
-
- template<>
- const char* Curve4iMB::Type::name () const {
- return "curve4imb";
- }
-
- template<>
- size_t Curve4iMB::Type::sizeActive(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return ((Line4i*)This)->size();
- else
- return ((Curve4iMB*)This)->N;
- }
-
- template<>
- size_t Curve4iMB::Type::sizeTotal(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return 4;
- else
- return ((Curve4iMB*)This)->N;
- }
-
- template<>
- size_t Curve4iMB::Type::getBytes(const char* This) const
- {
- if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
- return Line4i::bytes(sizeActive(This));
- else
- return Curve4iMB::bytes(sizeActive(This));
- }
-
- /********************** Line4i **************************/
-
- template<>
- const char* Line4i::Type::name () const {
- return "line4i";
- }
-
- template<>
- size_t Line4i::Type::sizeActive(const char* This) const {
- return ((Line4i*)This)->size();
- }
-
- template<>
- size_t Line4i::Type::sizeTotal(const char* This) const {
- return 4;
- }
-
- template<>
- size_t Line4i::Type::getBytes(const char* This) const {
- return sizeof(Line4i);
- }
-
- /********************** Triangle4 **************************/
-
- template<>
- const char* Triangle4::Type::name () const {
- return "triangle4";
- }
-
- template<>
- size_t Triangle4::Type::sizeActive(const char* This) const {
- return ((Triangle4*)This)->size();
- }
-
- template<>
- size_t Triangle4::Type::sizeTotal(const char* This) const {
- return 4;
- }
-
- template<>
- size_t Triangle4::Type::getBytes(const char* This) const {
- return sizeof(Triangle4);
- }
-
- /********************** Triangle4v **************************/
-
- template<>
- const char* Triangle4v::Type::name () const {
- return "triangle4v";
- }
-
- template<>
- size_t Triangle4v::Type::sizeActive(const char* This) const {
- return ((Triangle4v*)This)->size();
- }
-
- template<>
- size_t Triangle4v::Type::sizeTotal(const char* This) const {
- return 4;
- }
-
- template<>
- size_t Triangle4v::Type::getBytes(const char* This) const {
- return sizeof(Triangle4v);
- }
-
- /********************** Triangle4i **************************/
-
- template<>
- const char* Triangle4i::Type::name () const {
- return "triangle4i";
- }
-
- template<>
- size_t Triangle4i::Type::sizeActive(const char* This) const {
- return ((Triangle4i*)This)->size();
- }
-
- template<>
- size_t Triangle4i::Type::sizeTotal(const char* This) const {
- return 4;
- }
-
- template<>
- size_t Triangle4i::Type::getBytes(const char* This) const {
- return sizeof(Triangle4i);
- }
-
- /********************** Triangle4vMB **************************/
-
- template<>
- const char* Triangle4vMB::Type::name () const {
- return "triangle4vmb";
- }
-
- template<>
- size_t Triangle4vMB::Type::sizeActive(const char* This) const {
- return ((Triangle4vMB*)This)->size();
- }
-
- template<>
- size_t Triangle4vMB::Type::sizeTotal(const char* This) const {
- return 4;
- }
-
- template<>
- size_t Triangle4vMB::Type::getBytes(const char* This) const {
- return sizeof(Triangle4vMB);
- }
-
- /********************** Quad4v **************************/
-
- template<>
- const char* Quad4v::Type::name () const {
- return "quad4v";
- }
-
- template<>
- size_t Quad4v::Type::sizeActive(const char* This) const {
- return ((Quad4v*)This)->size();
- }
-
- template<>
- size_t Quad4v::Type::sizeTotal(const char* This) const {
- return 4;
- }
-
- template<>
- size_t Quad4v::Type::getBytes(const char* This) const {
- return sizeof(Quad4v);
- }
-
- /********************** Quad4i **************************/
-
- template<>
- const char* Quad4i::Type::name () const {
- return "quad4i";
- }
-
- template<>
- size_t Quad4i::Type::sizeActive(const char* This) const {
- return ((Quad4i*)This)->size();
- }
-
- template<>
- size_t Quad4i::Type::sizeTotal(const char* This) const {
- return 4;
- }
-
- template<>
- size_t Quad4i::Type::getBytes(const char* This) const {
- return sizeof(Quad4i);
- }
-
- /********************** SubdivPatch1 **************************/
-
- const char* SubdivPatch1::Type::name () const {
- return "subdivpatch1";
- }
-
- size_t SubdivPatch1::Type::sizeActive(const char* This) const {
- return 1;
- }
-
- size_t SubdivPatch1::Type::sizeTotal(const char* This) const {
- return 1;
- }
-
- size_t SubdivPatch1::Type::getBytes(const char* This) const {
- return sizeof(SubdivPatch1);
- }
-
- SubdivPatch1::Type SubdivPatch1::type;
-
- /********************** Virtual Object **************************/
-
- const char* Object::Type::name () const {
- return "object";
- }
-
- size_t Object::Type::sizeActive(const char* This) const {
- return 1;
- }
-
- size_t Object::Type::sizeTotal(const char* This) const {
- return 1;
- }
-
- size_t Object::Type::getBytes(const char* This) const {
- return sizeof(Object);
- }
-
- Object::Type Object::type;
-
- /********************** Instance **************************/
-
- const char* InstancePrimitive::Type::name () const {
- return "instance";
- }
-
- size_t InstancePrimitive::Type::sizeActive(const char* This) const {
- return 1;
- }
-
- size_t InstancePrimitive::Type::sizeTotal(const char* This) const {
- return 1;
- }
-
- size_t InstancePrimitive::Type::getBytes(const char* This) const {
- return sizeof(InstancePrimitive);
- }
-
- InstancePrimitive::Type InstancePrimitive::type;
-
- /********************** SubGrid **************************/
-
- const char* SubGrid::Type::name () const {
- return "subgrid";
- }
-
- size_t SubGrid::Type::sizeActive(const char* This) const {
- return 1;
- }
-
- size_t SubGrid::Type::sizeTotal(const char* This) const {
- return 1;
- }
-
- size_t SubGrid::Type::getBytes(const char* This) const {
- return sizeof(SubGrid);
- }
-
- SubGrid::Type SubGrid::type;
-
- /********************** SubGridQBVH4 **************************/
-
- template<>
- const char* SubGridQBVH4::Type::name () const {
- return "SubGridQBVH4";
- }
-
- template<>
- size_t SubGridQBVH4::Type::sizeActive(const char* This) const {
- return 1;
- }
-
- template<>
- size_t SubGridQBVH4::Type::sizeTotal(const char* This) const {
- return 1;
- }
-
- template<>
- size_t SubGridQBVH4::Type::getBytes(const char* This) const {
- return sizeof(SubGridQBVH4);
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/quad_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/quad_intersector.h
deleted file mode 100644
index 57ff4e60e5..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/quad_intersector.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- namespace isa
- {
- /*! Intersects a ray with a quad with backface culling
- * enabled. The quad v0,v1,v2,v3 is split into two triangles
- * v0,v1,v3 and v2,v3,v1. The edge v1,v2 decides which of the two
- * triangles gets intersected. */
- template<int N>
- __forceinline vbool<N> intersect_quad_backface_culling(const vbool<N>& valid0,
- const Vec3fa& ray_org,
- const Vec3fa& ray_dir,
- const float ray_tnear,
- const float ray_tfar,
- const Vec3vf<N>& quad_v0,
- const Vec3vf<N>& quad_v1,
- const Vec3vf<N>& quad_v2,
- const Vec3vf<N>& quad_v3,
- vfloat<N>& u_o,
- vfloat<N>& v_o,
- vfloat<N>& t_o)
- {
- /* calculate vertices relative to ray origin */
- vbool<N> valid = valid0;
- const Vec3vf<N> O = Vec3vf<N>(ray_org);
- const Vec3vf<N> D = Vec3vf<N>(ray_dir);
- const Vec3vf<N> va = quad_v0-O;
- const Vec3vf<N> vb = quad_v1-O;
- const Vec3vf<N> vc = quad_v2-O;
- const Vec3vf<N> vd = quad_v3-O;
-
- const Vec3vf<N> edb = vb-vd;
- const vfloat<N> WW = dot(cross(vd,edb),D);
- const Vec3vf<N> v0 = select(WW <= 0.0f,va,vc);
- const Vec3vf<N> v1 = select(WW <= 0.0f,vb,vd);
- const Vec3vf<N> v2 = select(WW <= 0.0f,vd,vb);
-
- /* calculate edges */
- const Vec3vf<N> e0 = v2-v0;
- const Vec3vf<N> e1 = v0-v1;
-
- /* perform edge tests */
- const vfloat<N> U = dot(cross(v0,e0),D);
- const vfloat<N> V = dot(cross(v1,e1),D);
- valid &= max(U,V) <= 0.0f;
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<N> Ng = cross(e1,e0);
- const vfloat<N> den = dot(Ng,D);
- const vfloat<N> rcpDen = rcp(den);
-
- /* perform depth test */
- const vfloat<N> t = rcpDen*dot(v0,Ng);
- valid &= vfloat<N>(ray_tnear) <= t & t <= vfloat<N>(ray_tfar);
- if (unlikely(none(valid))) return false;
-
- /* avoid division by 0 */
- valid &= den != vfloat<N>(zero);
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- t_o = t;
- u_o = U * rcpDen;
- v_o = V * rcpDen;
- u_o = select(WW <= 0.0f,u_o,1.0f-u_o);
- v_o = select(WW <= 0.0f,v_o,1.0f-v_o);
- return valid;
- }
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/quad_intersector_moeller.h b/thirdparty/embree-aarch64/kernels/geometry/quad_intersector_moeller.h
deleted file mode 100644
index 74e8c7720c..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/quad_intersector_moeller.h
+++ /dev/null
@@ -1,566 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "quadv.h"
-#include "triangle_intersector_moeller.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct QuadHitM
- {
- __forceinline QuadHitM() {}
-
- __forceinline QuadHitM(const vbool<M>& valid,
- const vfloat<M>& U,
- const vfloat<M>& V,
- const vfloat<M>& T,
- const vfloat<M>& absDen,
- const Vec3vf<M>& Ng,
- const vbool<M>& flags)
- : U(U), V(V), T(T), absDen(absDen), tri_Ng(Ng), valid(valid), flags(flags) {}
-
- __forceinline void finalize()
- {
- const vfloat<M> rcpAbsDen = rcp(absDen);
- vt = T * rcpAbsDen;
- const vfloat<M> u = min(U * rcpAbsDen,1.0f);
- const vfloat<M> v = min(V * rcpAbsDen,1.0f);
- const vfloat<M> u1 = vfloat<M>(1.0f) - u;
- const vfloat<M> v1 = vfloat<M>(1.0f) - v;
-#if !defined(__AVX__) || defined(EMBREE_BACKFACE_CULLING)
- vu = select(flags,u1,u);
- vv = select(flags,v1,v);
- vNg = Vec3vf<M>(tri_Ng.x,tri_Ng.y,tri_Ng.z);
-#else
- const vfloat<M> flip = select(flags,vfloat<M>(-1.0f),vfloat<M>(1.0f));
- vv = select(flags,u1,v);
- vu = select(flags,v1,u);
- vNg = Vec3vf<M>(flip*tri_Ng.x,flip*tri_Ng.y,flip*tri_Ng.z);
-#endif
- }
-
- __forceinline Vec2f uv(const size_t i)
- {
- const float u = vu[i];
- const float v = vv[i];
- return Vec2f(u,v);
- }
-
- __forceinline float t(const size_t i) { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- private:
- vfloat<M> U;
- vfloat<M> V;
- vfloat<M> T;
- vfloat<M> absDen;
- Vec3vf<M> tri_Ng;
-
- public:
- vbool<M> valid;
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
-
- public:
- const vbool<M> flags;
- };
-
- template<int K>
- struct QuadHitK
- {
- __forceinline QuadHitK(const vfloat<K>& U,
- const vfloat<K>& V,
- const vfloat<K>& T,
- const vfloat<K>& absDen,
- const Vec3vf<K>& Ng,
- const vbool<K>& flags)
- : U(U), V(V), T(T), absDen(absDen), flags(flags), tri_Ng(Ng) {}
-
- __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
- {
- const vfloat<K> rcpAbsDen = rcp(absDen);
- const vfloat<K> t = T * rcpAbsDen;
- const vfloat<K> u0 = min(U * rcpAbsDen,1.0f);
- const vfloat<K> v0 = min(V * rcpAbsDen,1.0f);
- const vfloat<K> u1 = vfloat<K>(1.0f) - u0;
- const vfloat<K> v1 = vfloat<K>(1.0f) - v0;
- const vfloat<K> u = select(flags,u1,u0);
- const vfloat<K> v = select(flags,v1,v0);
- const Vec3vf<K> Ng(tri_Ng.x,tri_Ng.y,tri_Ng.z);
- return std::make_tuple(u,v,t,Ng);
- }
-
- private:
- const vfloat<K> U;
- const vfloat<K> V;
- const vfloat<K> T;
- const vfloat<K> absDen;
- const vbool<K> flags;
- const Vec3vf<K> tri_Ng;
- };
-
- /* ----------------------------- */
- /* -- single ray intersectors -- */
- /* ----------------------------- */
-
-
- template<int M, bool filter>
- struct QuadMIntersector1MoellerTrumbore;
-
- /*! Intersects M quads with 1 ray */
- template<int M, bool filter>
- struct QuadMIntersector1MoellerTrumbore
- {
- __forceinline QuadMIntersector1MoellerTrumbore() {}
-
- __forceinline QuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
-
- __forceinline void intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const vuint<M>& geomID, const vuint<M>& primID) const
- {
- MoellerTrumboreHitM<M> hit;
- MoellerTrumboreIntersector1<M> intersector(ray,nullptr);
- Intersect1EpilogM<M,M,filter> epilog(ray,context,geomID,primID);
-
- /* intersect first triangle */
- if (intersector.intersect(ray,v0,v1,v3,hit))
- epilog(hit.valid,hit);
-
- /* intersect second triangle */
- if (intersector.intersect(ray,v2,v3,v1,hit))
- {
- hit.U = hit.absDen - hit.U;
- hit.V = hit.absDen - hit.V;
- epilog(hit.valid,hit);
- }
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const vuint<M>& geomID, const vuint<M>& primID) const
- {
- MoellerTrumboreHitM<M> hit;
- MoellerTrumboreIntersector1<M> intersector(ray,nullptr);
- Occluded1EpilogM<M,M,filter> epilog(ray,context,geomID,primID);
-
- /* intersect first triangle */
- if (intersector.intersect(ray,v0,v1,v3,hit))
- {
- if (epilog(hit.valid,hit))
- return true;
- }
-
- /* intersect second triangle */
- if (intersector.intersect(ray,v2,v3,v1,hit))
- {
- hit.U = hit.absDen - hit.U;
- hit.V = hit.absDen - hit.V;
- if (epilog(hit.valid,hit))
- return true;
- }
- return false;
- }
- };
-
-#if defined(__AVX512ER__) // KNL
-
- /*! Intersects 4 quads with 1 ray using AVX512 */
- template<bool filter>
- struct QuadMIntersector1MoellerTrumbore<4,filter>
- {
- __forceinline QuadMIntersector1MoellerTrumbore() {}
-
- __forceinline QuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
-
- template<typename Epilog>
- __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
- {
- const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)),
- select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)),
- select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z)));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z));
- const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z));
-#else
- const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)),
- select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)),
- select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z)));
- const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)),
- select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)),
- select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z)));
-#endif
- const vbool16 flags(0xf0f0);
-
- MoellerTrumboreHitM<16> hit;
- MoellerTrumboreIntersector1<16> intersector(ray,nullptr);
- if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,hit)))
- {
- vfloat16 U = hit.U, V = hit.V, absDen = hit.absDen;
-#if !defined(EMBREE_BACKFACE_CULLING)
- hit.U = select(flags,absDen-V,U);
- hit.V = select(flags,absDen-U,V);
- hit.vNg *= select(flags,vfloat16(-1.0f),vfloat16(1.0f)); // FIXME: use XOR
-#else
- hit.U = select(flags,absDen-U,U);
- hit.V = select(flags,absDen-V,V);
-#endif
- if (likely(epilog(hit.valid,hit)))
- return true;
- }
- return false;
- }
-
- __forceinline bool intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,16,filter>(ray,context,vuint8(geomID),vuint8(primID)));
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,16,filter>(ray,context,vuint8(geomID),vuint8(primID)));
- }
- };
-
-#elif defined(__AVX__)
-
- /*! Intersects 4 quads with 1 ray using AVX */
- template<bool filter>
- struct QuadMIntersector1MoellerTrumbore<4,filter>
- {
- __forceinline QuadMIntersector1MoellerTrumbore() {}
-
- __forceinline QuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
-
- template<typename Epilog>
- __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
- {
- const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
- const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
-#else
- const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
- const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
-#endif
- MoellerTrumboreHitM<8> hit;
- MoellerTrumboreIntersector1<8> intersector(ray,nullptr);
- const vbool8 flags(0,0,0,0,1,1,1,1);
- if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,hit)))
- {
- vfloat8 U = hit.U, V = hit.V, absDen = hit.absDen;
-
-#if !defined(EMBREE_BACKFACE_CULLING)
- hit.U = select(flags,absDen-V,U);
- hit.V = select(flags,absDen-U,V);
- hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f)); // FIXME: use XOR
-#else
- hit.U = select(flags,absDen-U,U);
- hit.V = select(flags,absDen-V,V);
-#endif
- if (unlikely(epilog(hit.valid,hit)))
- return true;
- }
- return false;
- }
-
- __forceinline bool intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,8,filter>(ray,context,vuint8(geomID),vuint8(primID)));
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,8,filter>(ray,context,vuint8(geomID),vuint8(primID)));
- }
- };
-
-#endif
-
- /* ----------------------------- */
- /* -- ray packet intersectors -- */
- /* ----------------------------- */
-
-
- struct MoellerTrumboreIntersector1KTriangleM
- {
- /*! Intersect k'th ray from ray packet of size K with M triangles. */
- template<int M, int K, typename Epilog>
- static __forceinline bool intersect(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- const Vec3vf<M>& tri_Ng,
- const vbool<M>& flags,
- const Epilog& epilog)
- {
- /* calculate denominator */
- const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
- const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
- const Vec3vf<M> C = Vec3vf<M>(tri_v0) - O;
- const Vec3vf<M> R = cross(C,D);
- const vfloat<M> den = dot(Vec3vf<M>(tri_Ng),D);
- const vfloat<M> absDen = abs(den);
- const vfloat<M> sgnDen = signmsk(den);
-
- /* perform edge tests */
- const vfloat<M> U = dot(R,Vec3vf<M>(tri_e2)) ^ sgnDen;
- const vfloat<M> V = dot(R,Vec3vf<M>(tri_e1)) ^ sgnDen;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#else
- vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#endif
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
- valid &= (absDen*vfloat<M>(ray.tnear()[k]) < T) & (T <= absDen*vfloat<M>(ray.tfar[k]));
- if (likely(none(valid))) return false;
-
- /* calculate hit information */
- QuadHitM<M> hit(valid,U,V,T,absDen,tri_Ng,flags);
- return epilog(valid,hit);
- }
-
- template<int M, int K, typename Epilog>
- static __forceinline bool intersect1(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const vbool<M>& flags,
- const Epilog& epilog)
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- const Vec3vf<M> Ng = cross(e2,e1);
- return intersect(ray,k,v0,e1,e2,Ng,flags,epilog);
- }
- };
-
- template<int M, int K, bool filter>
- struct QuadMIntersectorKMoellerTrumboreBase
- {
- __forceinline QuadMIntersectorKMoellerTrumboreBase(const vbool<K>& valid, const RayK<K>& ray) {}
-
- /*! Intersects K rays with one of M triangles. */
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_e1,
- const Vec3vf<K>& tri_e2,
- const Vec3vf<K>& tri_Ng,
- const vbool<K>& flags,
- const Epilog& epilog) const
- {
- /* calculate denominator */
- vbool<K> valid = valid0;
- const Vec3vf<K> C = tri_v0 - ray.org;
- const Vec3vf<K> R = cross(C,ray.dir);
- const vfloat<K> den = dot(tri_Ng,ray.dir);
- const vfloat<K> absDen = abs(den);
- const vfloat<K> sgnDen = signmsk(den);
-
- /* test against edge p2 p0 */
- const vfloat<K> U = dot(R,tri_e2) ^ sgnDen;
- valid &= U >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* test against edge p0 p1 */
- const vfloat<K> V = dot(R,tri_e1) ^ sgnDen;
- valid &= V >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* test against edge p1 p2 */
- const vfloat<K> W = absDen-U-V;
- valid &= W >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen;
- valid &= (absDen*ray.tnear() < T) & (T <= absDen*ray.tfar);
- if (unlikely(none(valid))) return false;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- valid &= den < vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-#else
- valid &= den != vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-#endif
-
- /* calculate hit information */
- QuadHitK<K> hit(U,V,T,absDen,tri_Ng,flags);
- return epilog(valid,hit);
- }
-
- /*! Intersects K rays with one of M quads. */
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_v1,
- const Vec3vf<K>& tri_v2,
- const vbool<K>& flags,
- const Epilog& epilog) const
- {
- const Vec3vf<K> e1 = tri_v0-tri_v1;
- const Vec3vf<K> e2 = tri_v2-tri_v0;
- const Vec3vf<K> Ng = cross(e2,e1);
- return intersectK(valid0,ray,tri_v0,e1,e2,Ng,flags,epilog);
- }
-
- /*! Intersects K rays with one of M quads. */
- template<typename Epilog>
- __forceinline bool intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& v0,
- const Vec3vf<K>& v1,
- const Vec3vf<K>& v2,
- const Vec3vf<K>& v3,
- const Epilog& epilog) const
- {
- intersectK(valid0,ray,v0,v1,v3,vbool<K>(false),epilog);
- if (none(valid0)) return true;
- intersectK(valid0,ray,v2,v3,v1,vbool<K>(true ),epilog);
- return none(valid0);
- }
- };
-
- template<int M, int K, bool filter>
- struct QuadMIntersectorKMoellerTrumbore : public QuadMIntersectorKMoellerTrumboreBase<M,K,filter>
- {
- __forceinline QuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
- : QuadMIntersectorKMoellerTrumboreBase<M,K,filter>(valid,ray) {}
-
- __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const vuint<M>& geomID, const vuint<M>& primID) const
- {
- Intersect1KEpilogM<M,M,K,filter> epilog(ray,k,context,geomID,primID);
- MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool<M>(false),epilog);
- MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool<M>(true ),epilog);
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const vuint<M>& geomID, const vuint<M>& primID) const
- {
- Occluded1KEpilogM<M,M,K,filter> epilog(ray,k,context,geomID,primID);
- if (MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool<M>(false),epilog)) return true;
- if (MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool<M>(true ),epilog)) return true;
- return false;
- }
- };
-
-
-#if defined(__AVX512ER__) // KNL
-
- /*! Intersects 4 quads with 1 ray using AVX512 */
- template<int K, bool filter>
- struct QuadMIntersectorKMoellerTrumbore<4,K,filter> : public QuadMIntersectorKMoellerTrumboreBase<4,K,filter>
- {
- __forceinline QuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
- : QuadMIntersectorKMoellerTrumboreBase<4,K,filter>(valid,ray) {}
-
- template<typename Epilog>
- __forceinline bool intersect1(RayK<K>& ray, size_t k,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
- {
- const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)),
- select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)),
- select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z)));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z));
- const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z));
-#else
- const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)),
- select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)),
- select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z)));
- const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)),
- select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)),
- select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z)));
-#endif
- const vbool16 flags(0xf0f0);
- return MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog);
- }
-
- __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,16,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,16,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
- }
- };
-
-#elif defined(__AVX__)
-
- /*! Intersects 4 quads with 1 ray using AVX */
- template<int K, bool filter>
- struct QuadMIntersectorKMoellerTrumbore<4,K,filter> : public QuadMIntersectorKMoellerTrumboreBase<4,K,filter>
- {
- __forceinline QuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
- : QuadMIntersectorKMoellerTrumboreBase<4,K,filter>(valid,ray) {}
-
- template<typename Epilog>
- __forceinline bool intersect1(RayK<K>& ray, size_t k,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
- {
- const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
- const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
-#else
- const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
- const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
-#endif
- const vbool8 flags(0,0,0,0,1,1,1,1);
- return MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog);
- }
-
- __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
- }
- };
-
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/quad_intersector_pluecker.h b/thirdparty/embree-aarch64/kernels/geometry/quad_intersector_pluecker.h
deleted file mode 100644
index 7ca3aed0a0..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/quad_intersector_pluecker.h
+++ /dev/null
@@ -1,529 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "quad_intersector_moeller.h"
-
-/*! Modified Pluecker ray/triangle intersector. The test first shifts
- * the ray origin into the origin of the coordinate system and then
- * uses Pluecker coordinates for the intersection. Due to the shift,
- * the Pluecker coordinate calculation simplifies and the tests get
- * numerically stable. The edge equations are watertight along the
- * edge for neighboring triangles. */
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct QuadHitPlueckerM
- {
- __forceinline QuadHitPlueckerM() {}
-
- __forceinline QuadHitPlueckerM(const vbool<M>& valid,
- const vfloat<M>& U,
- const vfloat<M>& V,
- const vfloat<M>& UVW,
- const vfloat<M>& t,
- const Vec3vf<M>& Ng,
- const vbool<M>& flags)
- : U(U), V(V), UVW(UVW), tri_Ng(Ng), valid(valid), vt(t), flags(flags) {}
-
- __forceinline void finalize()
- {
- const vbool<M> invalid = abs(UVW) < min_rcp_input;
- const vfloat<M> rcpUVW = select(invalid,vfloat<M>(0.0f),rcp(UVW));
- const vfloat<M> u = min(U * rcpUVW,1.0f);
- const vfloat<M> v = min(V * rcpUVW,1.0f);
- const vfloat<M> u1 = vfloat<M>(1.0f) - u;
- const vfloat<M> v1 = vfloat<M>(1.0f) - v;
-#if !defined(__AVX__) || defined(EMBREE_BACKFACE_CULLING)
- vu = select(flags,u1,u);
- vv = select(flags,v1,v);
- vNg = Vec3vf<M>(tri_Ng.x,tri_Ng.y,tri_Ng.z);
-#else
- const vfloat<M> flip = select(flags,vfloat<M>(-1.0f),vfloat<M>(1.0f));
- vv = select(flags,u1,v);
- vu = select(flags,v1,u);
- vNg = Vec3vf<M>(flip*tri_Ng.x,flip*tri_Ng.y,flip*tri_Ng.z);
-#endif
- }
-
- __forceinline Vec2f uv(const size_t i)
- {
- const float u = vu[i];
- const float v = vv[i];
- return Vec2f(u,v);
- }
-
- __forceinline float t(const size_t i) { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- private:
- vfloat<M> U;
- vfloat<M> V;
- vfloat<M> UVW;
- Vec3vf<M> tri_Ng;
-
- public:
- vbool<M> valid;
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
-
- public:
- const vbool<M> flags;
- };
-
- template<int K>
- struct QuadHitPlueckerK
- {
- __forceinline QuadHitPlueckerK(const vfloat<K>& U,
- const vfloat<K>& V,
- const vfloat<K>& UVW,
- const vfloat<K>& t,
- const Vec3vf<K>& Ng,
- const vbool<K>& flags)
- : U(U), V(V), UVW(UVW), t(t), flags(flags), tri_Ng(Ng) {}
-
- __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
- {
- const vbool<K> invalid = abs(UVW) < min_rcp_input;
- const vfloat<K> rcpUVW = select(invalid,vfloat<K>(0.0f),rcp(UVW));
- const vfloat<K> u0 = min(U * rcpUVW,1.0f);
- const vfloat<K> v0 = min(V * rcpUVW,1.0f);
- const vfloat<K> u1 = vfloat<K>(1.0f) - u0;
- const vfloat<K> v1 = vfloat<K>(1.0f) - v0;
- const vfloat<K> u = select(flags,u1,u0);
- const vfloat<K> v = select(flags,v1,v0);
- const Vec3vf<K> Ng(tri_Ng.x,tri_Ng.y,tri_Ng.z);
- return std::make_tuple(u,v,t,Ng);
- }
-
- private:
- const vfloat<K> U;
- const vfloat<K> V;
- const vfloat<K> UVW;
- const vfloat<K> t;
- const vbool<K> flags;
- const Vec3vf<K> tri_Ng;
- };
-
- struct PlueckerIntersectorTriangle1
- {
- template<int M, typename Epilog>
- static __forceinline bool intersect(Ray& ray,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_v1,
- const Vec3vf<M>& tri_v2,
- const vbool<M>& flags,
- const Epilog& epilog)
- {
- /* calculate vertices relative to ray origin */
- const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org);
- const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir);
- const Vec3vf<M> v0 = tri_v0-O;
- const Vec3vf<M> v1 = tri_v1-O;
- const Vec3vf<M> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<M> e0 = v2-v0;
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<M> U = dot(cross(e0,v2+v0),D);
- const vfloat<M> V = dot(cross(e1,v0+v1),D);
- const vfloat<M> W = dot(cross(e2,v1+v2),D);
- const vfloat<M> UVW = U+V+W;
- const vfloat<M> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = max(U,V,W) <= eps;
-#else
- vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<M> den = twice(dot(Ng,D));
-
- /* perform depth test */
- const vfloat<M> T = twice(dot(v0,Ng));
- const vfloat<M> t = rcp(den)*T;
- valid &= vfloat<M>(ray.tnear()) <= t & t <= vfloat<M>(ray.tfar);
- valid &= den != vfloat<M>(zero);
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- QuadHitPlueckerM<M> hit(valid,U,V,UVW,t,Ng,flags);
- return epilog(valid,hit);
- }
- };
-
- /*! Intersects M quads with 1 ray */
- template<int M, bool filter>
- struct QuadMIntersector1Pluecker
- {
- __forceinline QuadMIntersector1Pluecker() {}
-
- __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
-
- __forceinline void intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const vuint<M>& geomID, const vuint<M>& primID) const
- {
- Intersect1EpilogM<M,M,filter> epilog(ray,context,geomID,primID);
- PlueckerIntersectorTriangle1::intersect(ray,v0,v1,v3,vbool<M>(false),epilog);
- PlueckerIntersectorTriangle1::intersect(ray,v2,v3,v1,vbool<M>(true),epilog);
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const vuint<M>& geomID, const vuint<M>& primID) const
- {
- Occluded1EpilogM<M,M,filter> epilog(ray,context,geomID,primID);
- if (PlueckerIntersectorTriangle1::intersect(ray,v0,v1,v3,vbool<M>(false),epilog)) return true;
- if (PlueckerIntersectorTriangle1::intersect(ray,v2,v3,v1,vbool<M>(true ),epilog)) return true;
- return false;
- }
- };
-
-#if defined(__AVX512ER__) // KNL
-
- /*! Intersects 4 quads with 1 ray using AVX512 */
- template<bool filter>
- struct QuadMIntersector1Pluecker<4,filter>
- {
- __forceinline QuadMIntersector1Pluecker() {}
-
- __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
-
- template<typename Epilog>
- __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
- {
- const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)),
- select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)),
- select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z)));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z));
- const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z));
-#else
- const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)),
- select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)),
- select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z)));
- const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)),
- select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)),
- select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z)));
-#endif
- const vbool16 flags(0xf0f0);
- return PlueckerIntersectorTriangle1::intersect(ray,vtx0,vtx1,vtx2,flags,epilog);
- }
-
- __forceinline bool intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,16,filter>(ray,context,vuint8(geomID),vuint8(primID)));
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,16,filter>(ray,context,vuint8(geomID),vuint8(primID)));
- }
- };
-
-#elif defined(__AVX__)
-
- /*! Intersects 4 quads with 1 ray using AVX */
- template<bool filter>
- struct QuadMIntersector1Pluecker<4,filter>
- {
- __forceinline QuadMIntersector1Pluecker() {}
-
- __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
-
- template<typename Epilog>
- __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
- {
- const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
- const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
-#else
- const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
- const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
-#endif
- const vbool8 flags(0,0,0,0,1,1,1,1);
- return PlueckerIntersectorTriangle1::intersect(ray,vtx0,vtx1,vtx2,flags,epilog);
- }
-
- __forceinline bool intersect(RayHit& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,8,filter>(ray,context,vuint8(geomID),vuint8(primID)));
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,8,filter>(ray,context,vuint8(geomID),vuint8(primID)));
- }
- };
-
-#endif
-
-
- /* ----------------------------- */
- /* -- ray packet intersectors -- */
- /* ----------------------------- */
-
- struct PlueckerIntersector1KTriangleM
- {
- /*! Intersect k'th ray from ray packet of size K with M triangles. */
- template<int M, int K, typename Epilog>
- static __forceinline bool intersect1(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_v1,
- const Vec3vf<M>& tri_v2,
- const vbool<M>& flags,
- const Epilog& epilog)
- {
- /* calculate vertices relative to ray origin */
- const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
- const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
- const Vec3vf<M> v0 = tri_v0-O;
- const Vec3vf<M> v1 = tri_v1-O;
- const Vec3vf<M> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<M> e0 = v2-v0;
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<M> U = dot(cross(e0,v2+v0),D);
- const vfloat<M> V = dot(cross(e1,v0+v1),D);
- const vfloat<M> W = dot(cross(e2,v1+v2),D);
- const vfloat<M> UVW = U+V+W;
- const vfloat<M> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = max(U,V,W) <= eps;
-#else
- vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<M> den = twice(dot(Ng,D));
-
- /* perform depth test */
- const vfloat<M> T = twice(dot(v0,Ng));
- const vfloat<M> t = rcp(den)*T;
- valid &= vfloat<M>(ray.tnear()[k]) <= t & t <= vfloat<M>(ray.tfar[k]);
- if (unlikely(none(valid))) return false;
-
- /* avoid division by 0 */
- valid &= den != vfloat<M>(zero);
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- QuadHitPlueckerM<M> hit(valid,U,V,UVW,t,Ng,flags);
- return epilog(valid,hit);
- }
- };
-
- template<int M, int K, bool filter>
- struct QuadMIntersectorKPlueckerBase
- {
- __forceinline QuadMIntersectorKPlueckerBase(const vbool<K>& valid, const RayK<K>& ray) {}
-
- /*! Intersects K rays with one of M triangles. */
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_v1,
- const Vec3vf<K>& tri_v2,
- const vbool<K>& flags,
- const Epilog& epilog) const
- {
- /* calculate vertices relative to ray origin */
- vbool<K> valid = valid0;
- const Vec3vf<K> O = ray.org;
- const Vec3vf<K> D = ray.dir;
- const Vec3vf<K> v0 = tri_v0-O;
- const Vec3vf<K> v1 = tri_v1-O;
- const Vec3vf<K> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<K> e0 = v2-v0;
- const Vec3vf<K> e1 = v0-v1;
- const Vec3vf<K> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<K> U = dot(Vec3vf<K>(cross(e0,v2+v0)),D);
- const vfloat<K> V = dot(Vec3vf<K>(cross(e1,v0+v1)),D);
- const vfloat<K> W = dot(Vec3vf<K>(cross(e2,v1+v2)),D);
- const vfloat<K> UVW = U+V+W;
- const vfloat<K> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- valid &= max(U,V,W) <= eps;
-#else
- valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<K> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<K> den = twice(dot(Vec3vf<K>(Ng),D));
-
- /* perform depth test */
- const vfloat<K> T = twice(dot(v0,Vec3vf<K>(Ng)));
- const vfloat<K> t = rcp(den)*T;
- valid &= ray.tnear() <= t & t <= ray.tfar;
- valid &= den != vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-
- /* calculate hit information */
- QuadHitPlueckerK<K> hit(U,V,UVW,t,Ng,flags);
- return epilog(valid,hit);
- }
-
- /*! Intersects K rays with one of M quads. */
- template<typename Epilog>
- __forceinline bool intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& v0,
- const Vec3vf<K>& v1,
- const Vec3vf<K>& v2,
- const Vec3vf<K>& v3,
- const Epilog& epilog) const
- {
- intersectK(valid0,ray,v0,v1,v3,vbool<K>(false),epilog);
- if (none(valid0)) return true;
- intersectK(valid0,ray,v2,v3,v1,vbool<K>(true ),epilog);
- return none(valid0);
- }
- };
-
- template<int M, int K, bool filter>
- struct QuadMIntersectorKPluecker : public QuadMIntersectorKPlueckerBase<M,K,filter>
- {
- __forceinline QuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
- : QuadMIntersectorKPlueckerBase<M,K,filter>(valid,ray) {}
-
- __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const vuint<M>& geomID, const vuint<M>& primID) const
- {
- Intersect1KEpilogM<M,M,K,filter> epilog(ray,k,context,geomID,primID);
- PlueckerIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool<M>(false),epilog);
- PlueckerIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool<M>(true ),epilog);
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const vuint<M>& geomID, const vuint<M>& primID) const
- {
- Occluded1KEpilogM<M,M,K,filter> epilog(ray,k,context,geomID,primID);
- if (PlueckerIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool<M>(false),epilog)) return true;
- if (PlueckerIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool<M>(true ),epilog)) return true;
- return false;
- }
- };
-
-#if defined(__AVX512ER__) // KNL
-
- /*! Intersects 4 quads with 1 ray using AVX512 */
- template<int K, bool filter>
- struct QuadMIntersectorKPluecker<4,K,filter> : public QuadMIntersectorKPlueckerBase<4,K,filter>
- {
- __forceinline QuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
- : QuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {}
-
- template<typename Epilog>
- __forceinline bool intersect1(RayK<K>& ray, size_t k, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
- {
- const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)),
- select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)),
- select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z)));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z));
- const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z));
-#else
- const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)),
- select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)),
- select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z)));
- const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)),
- select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)),
- select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z)));
-#endif
-
- const vbool16 flags(0xf0f0);
- return PlueckerIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog);
- }
-
- __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,16,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,16,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
- }
- };
-
-#elif defined(__AVX__)
-
- /*! Intersects 4 quads with 1 ray using AVX */
- template<int K, bool filter>
- struct QuadMIntersectorKPluecker<4,K,filter> : public QuadMIntersectorKPlueckerBase<4,K,filter>
- {
- __forceinline QuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
- : QuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {}
-
- template<typename Epilog>
- __forceinline bool intersect1(RayK<K>& ray, size_t k, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
- {
- const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
- const vbool8 flags(0,0,0,0,1,1,1,1);
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
- const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
-#else
- const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
- const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
-#endif
- return PlueckerIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog);
- }
-
- __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const vuint4& geomID, const vuint4& primID) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
- }
- };
-
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/quadi.h b/thirdparty/embree-aarch64/kernels/geometry/quadi.h
deleted file mode 100644
index 741ec519ab..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/quadi.h
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-#include "../common/scene.h"
-
-namespace embree
-{
- /* Stores M quads from an indexed face set */
- template <int M>
- struct QuadMi
- {
- /* Virtual interface to query information about the quad type */
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* primitive supports multiple time segments */
- static const bool singleTimeSegment = false;
-
- /* Returns maximum number of stored quads */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
-
- public:
-
- /* Default constructor */
- __forceinline QuadMi() { }
-
- /* Construction from vertices and IDs */
- __forceinline QuadMi(const vuint<M>& v0,
- const vuint<M>& v1,
- const vuint<M>& v2,
- const vuint<M>& v3,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs)
-#if defined(EMBREE_COMPACT_POLYS)
- : geomIDs(geomIDs), primIDs(primIDs) {}
-#else
- : v0_(v0),v1_(v1), v2_(v2), v3_(v3), geomIDs(geomIDs), primIDs(primIDs) {}
-#endif
-
- /* Returns a mask that tells which quads are valid */
- __forceinline vbool<M> valid() const { return primIDs != vuint<M>(-1); }
-
- /* Returns if the specified quad is valid */
- __forceinline bool valid(const size_t i) const { assert(i<M); return primIDs[i] != -1; }
-
- /* Returns the number of stored quads */
- __forceinline size_t size() const { return bsf(~movemask(valid())); }
-
- /* Returns the geometry IDs */
- __forceinline vuint<M>& geomID() { return geomIDs; }
- __forceinline const vuint<M>& geomID() const { return geomIDs; }
- __forceinline unsigned int geomID(const size_t i) const { assert(i<M); assert(geomIDs[i] != -1); return geomIDs[i]; }
-
- /* Returns the primitive IDs */
- __forceinline vuint<M>& primID() { return primIDs; }
- __forceinline const vuint<M>& primID() const { return primIDs; }
- __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
-
- /* Calculate the bounds of the quads */
- __forceinline const BBox3fa bounds(const Scene *const scene, const size_t itime=0) const
- {
- BBox3fa bounds = empty;
- for (size_t i=0; i<M && valid(i); i++) {
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(i));
- bounds.extend(mesh->bounds(primID(i),itime));
- }
- return bounds;
- }
-
- /* Calculate the linear bounds of the primitive */
- __forceinline LBBox3fa linearBounds(const Scene* const scene, const size_t itime) {
- return LBBox3fa(bounds(scene,itime+0),bounds(scene,itime+1));
- }
-
- __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps)
- {
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<M && valid(i); i++)
- {
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(i));
- allBounds.extend(mesh->linearBounds(primID(i), itime, numTimeSteps));
- }
- return allBounds;
- }
-
- __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range)
- {
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<M && valid(i); i++)
- {
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(i));
- allBounds.extend(mesh->linearBounds(primID(i), time_range));
- }
- return allBounds;
- }
-
- /* Fill quad from quad list */
- template<typename PrimRefT>
- __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene)
- {
- vuint<M> geomID = -1, primID = -1;
- const PrimRefT* prim = &prims[begin];
- vuint<M> v0 = zero, v1 = zero, v2 = zero, v3 = zero;
-
- for (size_t i=0; i<M; i++)
- {
- if (begin<end) {
- geomID[i] = prim->geomID();
- primID[i] = prim->primID();
-#if !defined(EMBREE_COMPACT_POLYS)
- const QuadMesh* mesh = scene->get<QuadMesh>(prim->geomID());
- const QuadMesh::Quad& q = mesh->quad(prim->primID());
- unsigned int_stride = mesh->vertices0.getStride()/4;
- v0[i] = q.v[0] * int_stride;
- v1[i] = q.v[1] * int_stride;
- v2[i] = q.v[2] * int_stride;
- v3[i] = q.v[3] * int_stride;
-#endif
- begin++;
- } else {
- assert(i);
- if (likely(i > 0)) {
- geomID[i] = geomID[0]; // always valid geomIDs
- primID[i] = -1; // indicates invalid data
- v0[i] = v0[0];
- v1[i] = v0[0];
- v2[i] = v0[0];
- v3[i] = v0[0];
- }
- }
- if (begin<end) prim = &prims[begin];
- }
- new (this) QuadMi(v0,v1,v2,v3,geomID,primID); // FIXME: use non temporal store
- }
-
- __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
- {
- fill(prims, begin, end, scene);
- return linearBounds(scene, itime);
- }
-
- __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
- {
- fill(prims, begin, end, scene);
- return linearBounds(scene, time_range);
- }
-
- friend embree_ostream operator<<(embree_ostream cout, const QuadMi& quad) {
- return cout << "QuadMi<" << M << ">( "
-#if !defined(EMBREE_COMPACT_POLYS)
- << "v0 = " << quad.v0_ << ", v1 = " << quad.v1_ << ", v2 = " << quad.v2_ << ", v3 = " << quad.v3_ << ", "
-#endif
- << "geomID = " << quad.geomIDs << ", primID = " << quad.primIDs << " )";
- }
-
- protected:
-#if !defined(EMBREE_COMPACT_POLYS)
- vuint<M> v0_; // 4 byte offset of 1st vertex
- vuint<M> v1_; // 4 byte offset of 2nd vertex
- vuint<M> v2_; // 4 byte offset of 3rd vertex
- vuint<M> v3_; // 4 byte offset of 4th vertex
-#endif
- vuint<M> geomIDs; // geometry ID of mesh
- vuint<M> primIDs; // primitive ID of primitive inside mesh
- };
-
- namespace isa
- {
-
- template<int M>
- struct QuadMi : public embree::QuadMi<M>
- {
-#if !defined(EMBREE_COMPACT_POLYS)
- using embree::QuadMi<M>::v0_;
- using embree::QuadMi<M>::v1_;
- using embree::QuadMi<M>::v2_;
- using embree::QuadMi<M>::v3_;
-#endif
- using embree::QuadMi<M>::geomIDs;
- using embree::QuadMi<M>::primIDs;
- using embree::QuadMi<M>::geomID;
- using embree::QuadMi<M>::primID;
- using embree::QuadMi<M>::valid;
-
- template<int vid>
- __forceinline Vec3f getVertex(const size_t index, const Scene *const scene) const
- {
-#if defined(EMBREE_COMPACT_POLYS)
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
- const QuadMesh::Quad& quad = mesh->quad(primID(index));
- return (Vec3f) mesh->vertices[0][quad.v[vid]];
-#else
- const vuint<M>& v = getVertexOffset<vid>();
- const float* vertices = scene->vertices[geomID(index)];
- return (Vec3f&) vertices[v[index]];
-#endif
- }
-
- template<int vid, typename T>
- __forceinline Vec3<T> getVertex(const size_t index, const Scene *const scene, const size_t itime, const T& ftime) const
- {
-#if defined(EMBREE_COMPACT_POLYS)
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
- const QuadMesh::Quad& quad = mesh->quad(primID(index));
- const Vec3fa v0 = mesh->vertices[itime+0][quad.v[vid]];
- const Vec3fa v1 = mesh->vertices[itime+1][quad.v[vid]];
-#else
- const vuint<M>& v = getVertexOffset<vid>();
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
- const float* vertices0 = (const float*) mesh->vertexPtr(0,itime+0);
- const float* vertices1 = (const float*) mesh->vertexPtr(0,itime+1);
- const Vec3fa v0 = Vec3fa::loadu(vertices0+v[index]);
- const Vec3fa v1 = Vec3fa::loadu(vertices1+v[index]);
-#endif
- const Vec3<T> p0(v0.x,v0.y,v0.z);
- const Vec3<T> p1(v1.x,v1.y,v1.z);
- return lerp(p0,p1,ftime);
- }
-
- template<int vid, int K, typename T>
- __forceinline Vec3<T> getVertex(const vbool<K>& valid, const size_t index, const Scene *const scene, const vint<K>& itime, const T& ftime) const
- {
- Vec3<T> p0, p1;
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
-
- for (size_t mask=movemask(valid), i=bsf(mask); mask; mask=btc(mask,i), i=bsf(mask))
- {
-#if defined(EMBREE_COMPACT_POLYS)
- const QuadMesh::Quad& quad = mesh->quad(primID(index));
- const Vec3fa v0 = mesh->vertices[itime[i]+0][quad.v[vid]];
- const Vec3fa v1 = mesh->vertices[itime[i]+1][quad.v[vid]];
-#else
- const vuint<M>& v = getVertexOffset<vid>();
- const float* vertices0 = (const float*) mesh->vertexPtr(0,itime[i]+0);
- const float* vertices1 = (const float*) mesh->vertexPtr(0,itime[i]+1);
- const Vec3fa v0 = Vec3fa::loadu(vertices0+v[index]);
- const Vec3fa v1 = Vec3fa::loadu(vertices1+v[index]);
-#endif
- p0.x[i] = v0.x; p0.y[i] = v0.y; p0.z[i] = v0.z;
- p1.x[i] = v1.x; p1.y[i] = v1.y; p1.z[i] = v1.z;
- }
- return (T(one)-ftime)*p0 + ftime*p1;
- }
-
- struct Quad {
- vfloat4 v0,v1,v2,v3;
- };
-
-#if defined(EMBREE_COMPACT_POLYS)
-
- __forceinline Quad loadQuad(const int i, const Scene* const scene) const
- {
- const unsigned int geomID = geomIDs[i];
- const unsigned int primID = primIDs[i];
- if (unlikely(primID == -1)) return { zero, zero, zero, zero };
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID);
- const QuadMesh::Quad& quad = mesh->quad(primID);
- const vfloat4 v0 = (vfloat4) mesh->vertices0[quad.v[0]];
- const vfloat4 v1 = (vfloat4) mesh->vertices0[quad.v[1]];
- const vfloat4 v2 = (vfloat4) mesh->vertices0[quad.v[2]];
- const vfloat4 v3 = (vfloat4) mesh->vertices0[quad.v[3]];
- return { v0, v1, v2, v3 };
- }
-
- __forceinline Quad loadQuad(const int i, const int itime, const Scene* const scene) const
- {
- const unsigned int geomID = geomIDs[i];
- const unsigned int primID = primIDs[i];
- if (unlikely(primID == -1)) return { zero, zero, zero, zero };
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID);
- const QuadMesh::Quad& quad = mesh->quad(primID);
- const vfloat4 v0 = (vfloat4) mesh->vertices[itime][quad.v[0]];
- const vfloat4 v1 = (vfloat4) mesh->vertices[itime][quad.v[1]];
- const vfloat4 v2 = (vfloat4) mesh->vertices[itime][quad.v[2]];
- const vfloat4 v3 = (vfloat4) mesh->vertices[itime][quad.v[3]];
- return { v0, v1, v2, v3 };
- }
-
-#else
-
- __forceinline Quad loadQuad(const int i, const Scene* const scene) const
- {
- const float* vertices = scene->vertices[geomID(i)];
- const vfloat4 v0 = vfloat4::loadu(vertices + v0_[i]);
- const vfloat4 v1 = vfloat4::loadu(vertices + v1_[i]);
- const vfloat4 v2 = vfloat4::loadu(vertices + v2_[i]);
- const vfloat4 v3 = vfloat4::loadu(vertices + v3_[i]);
- return { v0, v1, v2, v3 };
- }
-
- __forceinline Quad loadQuad(const int i, const int itime, const Scene* const scene) const
- {
- const unsigned int geomID = geomIDs[i];
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID);
- const float* vertices = (const float*) mesh->vertexPtr(0,itime);
- const vfloat4 v0 = vfloat4::loadu(vertices + v0_[i]);
- const vfloat4 v1 = vfloat4::loadu(vertices + v1_[i]);
- const vfloat4 v2 = vfloat4::loadu(vertices + v2_[i]);
- const vfloat4 v3 = vfloat4::loadu(vertices + v3_[i]);
- return { v0, v1, v2, v3 };
- }
-
-#endif
-
- /* Gather the quads */
- __forceinline void gather(Vec3vf<M>& p0,
- Vec3vf<M>& p1,
- Vec3vf<M>& p2,
- Vec3vf<M>& p3,
- const Scene *const scene) const;
-
-#if defined(__AVX512F__)
- __forceinline void gather(Vec3vf16& p0,
- Vec3vf16& p1,
- Vec3vf16& p2,
- Vec3vf16& p3,
- const Scene *const scene) const;
-#endif
-
- template<int K>
-#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 2000) // workaround for compiler bug in ICC 2019
- __noinline
-#else
- __forceinline
-#endif
- void gather(const vbool<K>& valid,
- Vec3vf<K>& p0,
- Vec3vf<K>& p1,
- Vec3vf<K>& p2,
- Vec3vf<K>& p3,
- const size_t index,
- const Scene* const scene,
- const vfloat<K>& time) const
- {
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
-
- vfloat<K> ftime;
- const vint<K> itime = mesh->timeSegment(time, ftime);
-
- const size_t first = bsf(movemask(valid));
- if (likely(all(valid,itime[first] == itime)))
- {
- p0 = getVertex<0>(index, scene, itime[first], ftime);
- p1 = getVertex<1>(index, scene, itime[first], ftime);
- p2 = getVertex<2>(index, scene, itime[first], ftime);
- p3 = getVertex<3>(index, scene, itime[first], ftime);
- }
- else
- {
- p0 = getVertex<0>(valid, index, scene, itime, ftime);
- p1 = getVertex<1>(valid, index, scene, itime, ftime);
- p2 = getVertex<2>(valid, index, scene, itime, ftime);
- p3 = getVertex<3>(valid, index, scene, itime, ftime);
- }
- }
-
- __forceinline void gather(Vec3vf<M>& p0,
- Vec3vf<M>& p1,
- Vec3vf<M>& p2,
- Vec3vf<M>& p3,
- const QuadMesh* mesh,
- const Scene *const scene,
- const int itime) const;
-
- __forceinline void gather(Vec3vf<M>& p0,
- Vec3vf<M>& p1,
- Vec3vf<M>& p2,
- Vec3vf<M>& p3,
- const Scene *const scene,
- const float time) const;
-
- /* Updates the primitive */
- __forceinline BBox3fa update(QuadMesh* mesh)
- {
- BBox3fa bounds = empty;
- for (size_t i=0; i<M; i++)
- {
- if (!valid(i)) break;
- const unsigned primId = primID(i);
- const QuadMesh::Quad& q = mesh->quad(primId);
- const Vec3fa p0 = mesh->vertex(q.v[0]);
- const Vec3fa p1 = mesh->vertex(q.v[1]);
- const Vec3fa p2 = mesh->vertex(q.v[2]);
- const Vec3fa p3 = mesh->vertex(q.v[3]);
- bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2),BBox3fa(p3)));
- }
- return bounds;
- }
-
- private:
-#if !defined(EMBREE_COMPACT_POLYS)
- template<int N> const vuint<M>& getVertexOffset() const;
-#endif
- };
-
-#if !defined(EMBREE_COMPACT_POLYS)
- template<> template<> __forceinline const vuint<4>& QuadMi<4>::getVertexOffset<0>() const { return v0_; }
- template<> template<> __forceinline const vuint<4>& QuadMi<4>::getVertexOffset<1>() const { return v1_; }
- template<> template<> __forceinline const vuint<4>& QuadMi<4>::getVertexOffset<2>() const { return v2_; }
- template<> template<> __forceinline const vuint<4>& QuadMi<4>::getVertexOffset<3>() const { return v3_; }
-#endif
-
- template<>
- __forceinline void QuadMi<4>::gather(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- Vec3vf4& p3,
- const Scene *const scene) const
- {
- prefetchL1(((char*)this)+0*64);
- prefetchL1(((char*)this)+1*64);
- const Quad tri0 = loadQuad(0,scene);
- const Quad tri1 = loadQuad(1,scene);
- const Quad tri2 = loadQuad(2,scene);
- const Quad tri3 = loadQuad(3,scene);
- transpose(tri0.v0,tri1.v0,tri2.v0,tri3.v0,p0.x,p0.y,p0.z);
- transpose(tri0.v1,tri1.v1,tri2.v1,tri3.v1,p1.x,p1.y,p1.z);
- transpose(tri0.v2,tri1.v2,tri2.v2,tri3.v2,p2.x,p2.y,p2.z);
- transpose(tri0.v3,tri1.v3,tri2.v3,tri3.v3,p3.x,p3.y,p3.z);
- }
-
- template<>
- __forceinline void QuadMi<4>::gather(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- Vec3vf4& p3,
- const QuadMesh* mesh,
- const Scene *const scene,
- const int itime) const
- {
- // FIXME: for trianglei there all geometries are identical, is this the case here too?
-
- const Quad tri0 = loadQuad(0,itime,scene);
- const Quad tri1 = loadQuad(1,itime,scene);
- const Quad tri2 = loadQuad(2,itime,scene);
- const Quad tri3 = loadQuad(3,itime,scene);
- transpose(tri0.v0,tri1.v0,tri2.v0,tri3.v0,p0.x,p0.y,p0.z);
- transpose(tri0.v1,tri1.v1,tri2.v1,tri3.v1,p1.x,p1.y,p1.z);
- transpose(tri0.v2,tri1.v2,tri2.v2,tri3.v2,p2.x,p2.y,p2.z);
- transpose(tri0.v3,tri1.v3,tri2.v3,tri3.v3,p3.x,p3.y,p3.z);
- }
-
- template<>
- __forceinline void QuadMi<4>::gather(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- Vec3vf4& p3,
- const Scene *const scene,
- const float time) const
- {
- const QuadMesh* mesh = scene->get<QuadMesh>(geomID(0)); // in mblur mode all geometries are identical
-
- float ftime;
- const int itime = mesh->timeSegment(time, ftime);
-
- Vec3vf4 a0,a1,a2,a3; gather(a0,a1,a2,a3,mesh,scene,itime);
- Vec3vf4 b0,b1,b2,b3; gather(b0,b1,b2,b3,mesh,scene,itime+1);
- p0 = lerp(a0,b0,vfloat4(ftime));
- p1 = lerp(a1,b1,vfloat4(ftime));
- p2 = lerp(a2,b2,vfloat4(ftime));
- p3 = lerp(a3,b3,vfloat4(ftime));
- }
- }
-
- template<int M>
- typename QuadMi<M>::Type QuadMi<M>::type;
-
- typedef QuadMi<4> Quad4i;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/quadi_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/quadi_intersector.h
deleted file mode 100644
index 96cf7f1ca2..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/quadi_intersector.h
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "quadi.h"
-#include "quad_intersector_moeller.h"
-#include "quad_intersector_pluecker.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Intersects M quads with 1 ray */
- template<int M, bool filter>
- struct QuadMiIntersector1Moeller
- {
- typedef QuadMi<M> Primitive;
- typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations;
-
- /*! Intersect a ray with the M quads and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
- pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of M quads. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
- return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
- }
- };
-
- /*! Intersects M triangles with K rays. */
- template<int M, int K, bool filter>
- struct QuadMiIntersectorKMoeller
- {
- typedef QuadMi<M> Primitive;
- typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
- {
- Scene* scene = context->scene;
- for (size_t i=0; i<QuadMi<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene);
- const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene);
- const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene);
- const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene);
- pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
- {
- Scene* scene = context->scene;
- vbool<K> valid0 = valid_i;
- for (size_t i=0; i<QuadMi<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene);
- const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene);
- const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene);
- const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene);
- if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
- break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
- pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
- return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
- };
-
- /*! Intersects M quads with 1 ray */
- template<int M, bool filter>
- struct QuadMiIntersector1Pluecker
- {
- typedef QuadMi<M> Primitive;
- typedef QuadMIntersector1Pluecker<M,filter> Precalculations;
-
- /*! Intersect a ray with the M quads and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
- pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of M quads. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
- return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
- }
- };
-
- /*! Intersects M triangles with K rays. */
- template<int M, int K, bool filter>
- struct QuadMiIntersectorKPluecker
- {
- typedef QuadMi<M> Primitive;
- typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
- {
- Scene* scene = context->scene;
- for (size_t i=0; i<QuadMi<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene);
- const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene);
- const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene);
- const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene);
- pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
- {
- Scene* scene = context->scene;
- vbool<K> valid0 = valid_i;
- for (size_t i=0; i<QuadMi<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene);
- const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene);
- const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene);
- const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene);
- if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
- break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
- pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
- return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
- };
-
- /*! Intersects M motion blur quads with 1 ray */
- template<int M, bool filter>
- struct QuadMiMBIntersector1Moeller
- {
- typedef QuadMi<M> Primitive;
- typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations;
-
- /*! Intersect a ray with the M quads and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time());
- pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of M quads. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time());
- return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
- }
- };
-
- /*! Intersects M motion blur quads with K rays. */
- template<int M, int K, bool filter>
- struct QuadMiMBIntersectorKMoeller
- {
- typedef QuadMi<M> Primitive;
- typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations;
-
- /*! Intersects K rays with M quads. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
- {
- for (size_t i=0; i<QuadMi<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- Vec3vf<K> v0,v1,v2,v3; quad.gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time());
- pre.intersectK(valid_i,ray,v0,v1,v2,v3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M quads. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
- {
- vbool<K> valid0 = valid_i;
- for (size_t i=0; i<QuadMi<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- Vec3vf<K> v0,v1,v2,v3; quad.gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time());
- if (pre.intersectK(valid0,ray,v0,v1,v2,v3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
- break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M quads and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]);
- pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of the M quads. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]);
- return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
- };
-
- /*! Intersects M motion blur quads with 1 ray */
- template<int M, bool filter>
- struct QuadMiMBIntersector1Pluecker
- {
- typedef QuadMi<M> Primitive;
- typedef QuadMIntersector1Pluecker<M,filter> Precalculations;
-
- /*! Intersect a ray with the M quads and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time());
- pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of M quads. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time());
- return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
- }
- };
-
- /*! Intersects M motion blur quads with K rays. */
- template<int M, int K, bool filter>
- struct QuadMiMBIntersectorKPluecker
- {
- typedef QuadMi<M> Primitive;
- typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations;
-
- /*! Intersects K rays with M quads. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
- {
- for (size_t i=0; i<QuadMi<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- Vec3vf<K> v0,v1,v2,v3; quad.gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time());
- pre.intersectK(valid_i,ray,v0,v1,v2,v3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M quads. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
- {
- vbool<K> valid0 = valid_i;
- for (size_t i=0; i<QuadMi<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- Vec3vf<K> v0,v1,v2,v3; quad.gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time());
- if (pre.intersectK(valid0,ray,v0,v1,v2,v3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
- break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M quads and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]);
- pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of the M quads. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]);
- return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/quadv.h b/thirdparty/embree-aarch64/kernels/geometry/quadv.h
deleted file mode 100644
index 0a1fe4d128..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/quadv.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-
-namespace embree
-{
- /* Stores the vertices of M quads in struct of array layout */
- template <int M>
- struct QuadMv
- {
- public:
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* Returns maximum number of stored quads */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
-
- public:
-
- /* Default constructor */
- __forceinline QuadMv() {}
-
- /* Construction from vertices and IDs */
- __forceinline QuadMv(const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const vuint<M>& geomIDs, const vuint<M>& primIDs)
- : v0(v0), v1(v1), v2(v2), v3(v3), geomIDs(geomIDs), primIDs(primIDs) {}
-
- /* Returns a mask that tells which quads are valid */
- __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); }
-
- /* Returns true if the specified quad is valid */
- __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; }
-
- /* Returns the number of stored quads */
- __forceinline size_t size() const { return bsf(~movemask(valid())); }
-
- /* Returns the geometry IDs */
- __forceinline vuint<M>& geomID() { return geomIDs; }
- __forceinline const vuint<M>& geomID() const { return geomIDs; }
- __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
-
- /* Returns the primitive IDs */
- __forceinline vuint<M> primID() { return primIDs; }
- __forceinline const vuint<M> primID() const { return primIDs; }
- __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
-
- /* Calculate the bounds of the quads */
- __forceinline BBox3fa bounds() const
- {
- Vec3vf<M> lower = min(v0,v1,v2,v3);
- Vec3vf<M> upper = max(v0,v1,v2,v3);
- vbool<M> mask = valid();
- lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
- lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
- lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
- upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
- upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
- upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
- return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
- Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
- }
-
- /* Non temporal store */
- __forceinline static void store_nt(QuadMv* dst, const QuadMv& src)
- {
- vfloat<M>::store_nt(&dst->v0.x,src.v0.x);
- vfloat<M>::store_nt(&dst->v0.y,src.v0.y);
- vfloat<M>::store_nt(&dst->v0.z,src.v0.z);
- vfloat<M>::store_nt(&dst->v1.x,src.v1.x);
- vfloat<M>::store_nt(&dst->v1.y,src.v1.y);
- vfloat<M>::store_nt(&dst->v1.z,src.v1.z);
- vfloat<M>::store_nt(&dst->v2.x,src.v2.x);
- vfloat<M>::store_nt(&dst->v2.y,src.v2.y);
- vfloat<M>::store_nt(&dst->v2.z,src.v2.z);
- vfloat<M>::store_nt(&dst->v3.x,src.v3.x);
- vfloat<M>::store_nt(&dst->v3.y,src.v3.y);
- vfloat<M>::store_nt(&dst->v3.z,src.v3.z);
- vuint<M>::store_nt(&dst->geomIDs,src.geomIDs);
- vuint<M>::store_nt(&dst->primIDs,src.primIDs);
- }
-
- /* Fill quad from quad list */
- __forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
- {
- vuint<M> vgeomID = -1, vprimID = -1;
- Vec3vf<M> v0 = zero, v1 = zero, v2 = zero, v3 = zero;
-
- for (size_t i=0; i<M && begin<end; i++, begin++)
- {
- const PrimRef& prim = prims[begin];
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const QuadMesh* __restrict__ const mesh = scene->get<QuadMesh>(geomID);
- const QuadMesh::Quad& quad = mesh->quad(primID);
- const Vec3fa& p0 = mesh->vertex(quad.v[0]);
- const Vec3fa& p1 = mesh->vertex(quad.v[1]);
- const Vec3fa& p2 = mesh->vertex(quad.v[2]);
- const Vec3fa& p3 = mesh->vertex(quad.v[3]);
- vgeomID [i] = geomID;
- vprimID [i] = primID;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- v3.x[i] = p3.x; v3.y[i] = p3.y; v3.z[i] = p3.z;
- }
- QuadMv::store_nt(this,QuadMv(v0,v1,v2,v3,vgeomID,vprimID));
- }
-
- /* Updates the primitive */
- __forceinline BBox3fa update(QuadMesh* mesh)
- {
- BBox3fa bounds = empty;
- vuint<M> vgeomID = -1, vprimID = -1;
- Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
-
- for (size_t i=0; i<M; i++)
- {
- if (primID(i) == -1) break;
- const unsigned geomId = geomID(i);
- const unsigned primId = primID(i);
- const QuadMesh::Quad& quad = mesh->quad(primId);
- const Vec3fa p0 = mesh->vertex(quad.v[0]);
- const Vec3fa p1 = mesh->vertex(quad.v[1]);
- const Vec3fa p2 = mesh->vertex(quad.v[2]);
- const Vec3fa p3 = mesh->vertex(quad.v[3]);
- bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2),BBox3fa(p3)));
- vgeomID [i] = geomId;
- vprimID [i] = primId;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- v3.x[i] = p3.x; v3.y[i] = p3.y; v3.z[i] = p3.z;
- }
- new (this) QuadMv(v0,v1,v2,v3,vgeomID,vprimID);
- return bounds;
- }
-
- public:
- Vec3vf<M> v0; // 1st vertex of the quads
- Vec3vf<M> v1; // 2nd vertex of the quads
- Vec3vf<M> v2; // 3rd vertex of the quads
- Vec3vf<M> v3; // 4rd vertex of the quads
- private:
- vuint<M> geomIDs; // geometry ID
- vuint<M> primIDs; // primitive ID
- };
-
- template<int M>
- typename QuadMv<M>::Type QuadMv<M>::type;
-
- typedef QuadMv<4> Quad4v;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/quadv_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/quadv_intersector.h
deleted file mode 100644
index 30a24b291a..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/quadv_intersector.h
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "quadv.h"
-#include "quad_intersector_moeller.h"
-#include "quad_intersector_pluecker.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Intersects M quads with 1 ray */
- template<int M, bool filter>
- struct QuadMvIntersector1Moeller
- {
- typedef QuadMv<M> Primitive;
- typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations;
-
- /*! Intersect a ray with the M quads and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersect(ray,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of M quads. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.occluded(ray,context, quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
- }
- };
-
- /*! Intersects M triangles with K rays. */
- template<int M, int K, bool filter>
- struct QuadMvIntersectorKMoeller
- {
- typedef QuadMv<M> Primitive;
- typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMv<M>& quad)
- {
- for (size_t i=0; i<QuadMv<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i);
- const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i);
- const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i);
- const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i);
- pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMv<M>& quad)
- {
- vbool<K> valid0 = valid_i;
-
- for (size_t i=0; i<QuadMv<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i);
- const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i);
- const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i);
- const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i);
- if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
- break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersect1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.occluded1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
- }
- };
-
- /*! Intersects M quads with 1 ray */
- template<int M, bool filter>
- struct QuadMvIntersector1Pluecker
- {
- typedef QuadMv<M> Primitive;
- typedef QuadMIntersector1Pluecker<M,filter> Precalculations;
-
- /*! Intersect a ray with the M quads and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersect(ray,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of M quads. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.occluded(ray,context, quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
- }
- };
-
- /*! Intersects M triangles with K rays. */
- template<int M, int K, bool filter>
- struct QuadMvIntersectorKPluecker
- {
- typedef QuadMv<M> Primitive;
- typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMv<M>& quad)
- {
- for (size_t i=0; i<QuadMv<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i);
- const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i);
- const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i);
- const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i);
- pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMv<M>& quad)
- {
- vbool<K> valid0 = valid_i;
-
- for (size_t i=0; i<QuadMv<M>::max_size(); i++)
- {
- if (!quad.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i);
- const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i);
- const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i);
- const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i);
- if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
- break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersect1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.occluded1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
- }
- };
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/geometry/roundline_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/roundline_intersector.h
deleted file mode 100644
index cdf68f486b..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/roundline_intersector.h
+++ /dev/null
@@ -1,710 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "curve_intersector_precalculations.h"
-
-
-/*
-
- This file implements the intersection of a ray with a round linear
- curve segment. We define the geometry of such a round linear curve
- segment from point p0 with radius r0 to point p1 with radius r1
- using the cone that touches spheres p0/r0 and p1/r1 tangentially
- plus the sphere p1/r1. We denote the tangentially touching cone from
- p0/r0 to p1/r1 with cone(p0,r0,p1,r1) and the cone plus the ending
- sphere with cone_sphere(p0,r0,p1,r1).
-
- For multiple connected round linear curve segments this construction
- yield a proper shape when viewed from the outside. Using the
- following CSG we can also handle the interiour in most common cases:
-
- round_linear_curve(pl,rl,p0,r0,p1,r1,pr,rr) =
- cone_sphere(p0,r0,p1,r1) - cone(pl,rl,p0,r0) - cone(p1,r1,pr,rr)
-
- Thus by subtracting the neighboring cone geometries, we cut away
- parts of the center cone_sphere surface which lie inside the
- combined curve. This approach works as long as geometry of the
- current cone_sphere penetrates into direct neighbor segments only,
- and not into segments further away.
-
- To construct a cone that touches two spheres at p0 and p1 with r0
- and r1, one has to increase the cone radius at r0 and r1 to obtain
- larger radii w0 and w1, such that the infinite cone properly touches
- the spheres. From the paper "Ray Tracing Generalized Tube
- Primitives: Method and Applications"
- (https://www.researchgate.net/publication/334378683_Ray_Tracing_Generalized_Tube_Primitives_Method_and_Applications)
- one can derive the following equations for these increased
- radii:
-
- sr = 1.0f / sqrt(1-sqr(dr)/sqr(p1-p0))
- w0 = sr*r0
- w1 = sr*r1
-
- Further, we want the cone to start where it touches the sphere at p0
- and to end where it touches sphere at p1. Therefore, we need to
- construct clipping locations y0 and y1 for the start and end of the
- cone. These start and end clipping location of the cone can get
- calculated as:
-
- Y0 = - r0 * (r1-r0) / length(p1-p0)
- Y1 = length(p1-p0) - r1 * (r1-r0) / length(p1-p0)
-
- Where the cone starts a distance Y0 and ends a distance Y1 away of
- point p0 along the cone center. The distance between Y1-Y0 can get
- calculated as:
-
- dY = length(p1-p0) - (r1-r0)^2 / length(p1-p0)
-
- In the code below, Y will always be scaled by length(p1-p0) to
- obtain y and you will find the terms r0*(r1-r0) and
- (p1-p0)^2-(r1-r0)^2.
-
- */
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct RoundLineIntersectorHitM
- {
- __forceinline RoundLineIntersectorHitM() {}
-
- __forceinline RoundLineIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
- : vu(u), vv(v), vt(t), vNg(Ng) {}
-
- __forceinline void finalize() {}
-
- __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
- __forceinline float t (const size_t i) const { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- public:
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- namespace __roundline_internal
- {
- template<int M>
- struct ConeGeometry
- {
- ConeGeometry (const Vec4vf<M>& a, const Vec4vf<M>& b)
- : p0(a.xyz()), p1(b.xyz()), dP(p1-p0), dPdP(dot(dP,dP)), r0(a.w), sqr_r0(sqr(r0)), r1(b.w), dr(r1-r0), drdr(dr*dr), r0dr (r0*dr), g(dPdP - drdr) {}
-
- /*
-
- This function tests if a point is accepted by first cone
- clipping plane.
-
- First, we need to project the point onto the line p0->p1:
-
- Y = (p-p0)*(p1-p0)/length(p1-p0)
-
- This value y is the distance to the projection point from
- p0. The clip distances are calculated as:
-
- Y0 = - r0 * (r1-r0) / length(p1-p0)
- Y1 = length(p1-p0) - r1 * (r1-r0) / length(p1-p0)
-
- Thus to test if the point p is accepted by the first
- clipping plane we need to test Y > Y0 and to test if it
- is accepted by the second clipping plane we need to test
- Y < Y1.
-
- By multiplying the calculations with length(p1-p0) these
- calculation can get simplied to:
-
- y = (p-p0)*(p1-p0)
- y0 = - r0 * (r1-r0)
- y1 = (p1-p0)^2 - r1 * (r1-r0)
-
- and the test y > y0 and y < y1.
-
- */
-
- __forceinline vbool<M> isClippedByPlane (const vbool<M>& valid_i, const Vec3vf<M>& p) const
- {
- const Vec3vf<M> p0p = p - p0;
- const vfloat<M> y = dot(p0p,dP);
- const vfloat<M> cap0 = -r0dr;
- const vbool<M> inside_cone = y > cap0;
- return valid_i & (p0.x != vfloat<M>(inf)) & (p1.x != vfloat<M>(inf)) & inside_cone;
- }
-
- /*
-
- This function tests whether a point lies inside the capped cone
- tangential to its ending spheres.
-
- Therefore one has to check if the point is inside the
- region defined by the cone clipping planes, which is
- performed similar as in the previous function.
-
- To perform the inside cone test we need to project the
- point onto the line p0->p1:
-
- dP = p1-p0
- Y = (p-p0)*dP/length(dP)
-
- This value Y is the distance to the projection point from
- p0. To obtain a parameter value u going from 0 to 1 along
- the line p0->p1 we calculate:
-
- U = Y/length(dP)
-
- The radii to use at points p0 and p1 are:
-
- w0 = sr * r0
- w1 = sr * r1
- dw = w1-w0
-
- Using these radii and u one can directly test if the point
- lies inside the cone using the formula dP*dP < wy*wy with:
-
- wy = w0 + u*dw
- py = p0 + u*dP - p
-
- By multiplying the calculations with length(p1-p0) and
- inserting the definition of w can obtain simpler equations:
-
- y = (p-p0)*dP
- ry = r0 + y/dP^2 * dr
- wy = sr*ry
- py = p0 + y/dP^2*dP - p
- y0 = - r0 * dr
- y1 = dP^2 - r1 * dr
-
- Thus for the in-cone test we get:
-
- py^2 < wy^2
- <=> py^2 < sr^2 * ry^2
- <=> py^2 * ( dP^2 - dr^2 ) < dP^2 * ry^2
-
- This can further get simplified to:
-
- (p0-p)^2 * (dP^2 - dr^2) - y^2 < dP^2 * r0^2 + 2.0f*r0*dr*y;
-
- */
-
- __forceinline vbool<M> isInsideCappedCone (const vbool<M>& valid_i, const Vec3vf<M>& p) const
- {
- const Vec3vf<M> p0p = p - p0;
- const vfloat<M> y = dot(p0p,dP);
- const vfloat<M> cap0 = -r0dr+vfloat<M>(ulp);
- const vfloat<M> cap1 = -r1*dr + dPdP;
-
- vbool<M> inside_cone = valid_i & (p0.x != vfloat<M>(inf)) & (p1.x != vfloat<M>(inf));
- inside_cone &= y > cap0; // start clipping plane
- inside_cone &= y < cap1; // end clipping plane
- inside_cone &= sqr(p0p)*g - sqr(y) < dPdP * sqr_r0 + 2.0f*r0dr*y; // in cone test
- return inside_cone;
- }
-
- protected:
- Vec3vf<M> p0;
- Vec3vf<M> p1;
- Vec3vf<M> dP;
- vfloat<M> dPdP;
- vfloat<M> r0;
- vfloat<M> sqr_r0;
- vfloat<M> r1;
- vfloat<M> dr;
- vfloat<M> drdr;
- vfloat<M> r0dr;
- vfloat<M> g;
- };
-
- template<int M>
- struct ConeGeometryIntersector : public ConeGeometry<M>
- {
- using ConeGeometry<M>::p0;
- using ConeGeometry<M>::p1;
- using ConeGeometry<M>::dP;
- using ConeGeometry<M>::dPdP;
- using ConeGeometry<M>::r0;
- using ConeGeometry<M>::sqr_r0;
- using ConeGeometry<M>::r1;
- using ConeGeometry<M>::dr;
- using ConeGeometry<M>::r0dr;
- using ConeGeometry<M>::g;
-
- ConeGeometryIntersector (const Vec3vf<M>& ray_org, const Vec3vf<M>& ray_dir, const vfloat<M>& dOdO, const vfloat<M>& rcp_dOdO, const Vec4vf<M>& a, const Vec4vf<M>& b)
- : ConeGeometry<M>(a,b), org(ray_org), O(ray_org-p0), dO(ray_dir), dOdO(dOdO), rcp_dOdO(rcp_dOdO), OdP(dot(dP,O)), dOdP(dot(dP,dO)), yp(OdP + r0dr) {}
-
- /*
-
- This function intersects a ray with a cone that touches a
- start sphere p0/r0 and end sphere p1/r1.
-
- To find this ray/cone intersections one could just
- calculate radii w0 and w1 as described above and use a
- standard ray/cone intersection routine with these
- radii. However, it turns out that calculations can get
- simplified when deriving a specialized ray/cone
- intersection for this special case. We perform
- calculations relative to the cone origin p0 and define:
-
- O = ray_org - p0
- dO = ray_dir
- dP = p1-p0
- dr = r1-r0
- dw = w1-w0
-
- For some t we can compute the potential hit point h = O + t*dO and
- project it onto the cone vector dP to obtain u = (h*dP)/(dP*dP). In
- case of an intersection, the squared distance from the hit point
- projected onto the cone center line to the hit point should be equal
- to the squared cone radius at u:
-
- (u*dP - h)^2 = (w0 + u*dw)^2
-
- Inserting the definition of h, u, w0, and dw into this formula, then
- factoring out all terms, and sorting by t^2, t^1, and t^0 terms
- yields a quadratic equation to solve.
-
- Inserting u:
- ( (h*dP)*dP/dP^2 - h )^2 = ( w0 + (h*dP)*dw/dP^2 )^2
-
- Multiplying by dP^4:
- ( (h*dP)*dP - h*dP^2 )^2 = ( w0*dP^2 + (h*dP)*dw )^2
-
- Inserting w0 and dw:
- ( (h*dP)*dP - h*dP^2 )^2 = ( r0*dP^2 + (h*dP)*dr )^2 / (1-dr^2/dP^2)
- ( (h*dP)*dP - h*dP^2 )^2 *(dP^2 - dr^2) = dP^2 * ( r0*dP^2 + (h*dP)*dr )^2
-
- Now one can insert the definition of h, factor out, and presort by t:
- ( ((O + t*dO)*dP)*dP - (O + t*dO)*dP^2 )^2 *(dP^2 - dr^2) = dP^2 * ( r0*dP^2 + ((O + t*dO)*dP)*dr )^2
- ( (O*dP)*dP-O*dP^2 + t*( (dO*dP)*dP - dO*dP^2 ) )^2 *(dP^2 - dr^2) = dP^2 * ( r0*dP^2 + (O*dP)*dr + t*(dO*dP)*dr )^2
-
- Factoring out further and sorting by t^2, t^1 and t^0 yields:
-
- 0 = t^2 * [ ((dO*dP)*dP - dO-dP^2)^2 * (dP^2 - dr^2) - dP^2*(dO*dP)^2*dr^2 ]
- + 2*t^1 * [ ((O*dP)*dP - O*dP^2) * ((dO*dP)*dP - dO*dP^2) * (dP^2 - dr^2) - dP^2*(r0*dP^2 + (O*dP)*dr)*(dO*dP)*dr ]
- + t^0 * [ ( (O*dP)*dP - O*dP^2)^2 * (dP^2-dr^2) - dP^2*(r0*dP^2 + (O*dP)*dr)^2 ]
-
- This can be simplified to:
-
- 0 = t^2 * [ (dP^2 - dr^2)*dO^2 - (dO*dP)^2 ]
- + 2*t^1 * [ (dP^2 - dr^2)*(O*dO) - (dO*dP)*(O*dP + r0*dr) ]
- + t^0 * [ (dP^2 - dr^2)*O^2 - (O*dP)^2 - r0^2*dP^2 - 2.0f*r0*dr*(O*dP) ]
-
- Solving this quadratic equation yields the values for t at which the
- ray intersects the cone.
-
- */
-
- __forceinline bool intersectCone(vbool<M>& valid, vfloat<M>& lower, vfloat<M>& upper)
- {
- /* return no hit by default */
- lower = pos_inf;
- upper = neg_inf;
-
- /* compute quadratic equation A*t^2 + B*t + C = 0 */
- const vfloat<M> OO = dot(O,O);
- const vfloat<M> OdO = dot(dO,O);
- const vfloat<M> A = g * dOdO - sqr(dOdP);
- const vfloat<M> B = 2.0f * (g*OdO - dOdP*yp);
- const vfloat<M> C = g*OO - sqr(OdP) - sqr_r0*dPdP - 2.0f*r0dr*OdP;
-
- /* we miss the cone if determinant is smaller than zero */
- const vfloat<M> D = B*B - 4.0f*A*C;
- valid &= (D >= 0.0f & g > 0.0f); // if g <= 0 then the cone is inside a sphere end
-
- /* When rays are parallel to the cone surface, then the
- * ray may be inside or outside the cone. We just assume a
- * miss in that case, which is fine as rays inside the
- * cone would anyway hit the ending spheres in that
- * case. */
- valid &= abs(A) > min_rcp_input;
- if (unlikely(none(valid))) {
- return false;
- }
-
- /* compute distance to front and back hit */
- const vfloat<M> Q = sqrt(D);
- const vfloat<M> rcp_2A = rcp(2.0f*A);
- t_cone_front = (-B-Q)*rcp_2A;
- y_cone_front = yp + t_cone_front*dOdP;
- lower = select( (y_cone_front > -(float)ulp) & (y_cone_front <= g) & (g > 0.0f), t_cone_front, vfloat<M>(pos_inf));
-#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
- t_cone_back = (-B+Q)*rcp_2A;
- y_cone_back = yp + t_cone_back *dOdP;
- upper = select( (y_cone_back > -(float)ulp) & (y_cone_back <= g) & (g > 0.0f), t_cone_back , vfloat<M>(neg_inf));
-#endif
- return true;
- }
-
- /*
- This function intersects the ray with the end sphere at
- p1. We already clip away hits that are inside the
- neighboring cone segment.
-
- */
-
- __forceinline void intersectEndSphere(vbool<M>& valid,
- const ConeGeometry<M>& coneR,
- vfloat<M>& lower, vfloat<M>& upper)
- {
- /* calculate front and back hit with end sphere */
- const Vec3vf<M> O1 = org - p1;
- const vfloat<M> O1dO = dot(O1,dO);
- const vfloat<M> h2 = sqr(O1dO) - dOdO*(sqr(O1) - sqr(r1));
- const vfloat<M> rhs1 = select( h2 >= 0.0f, sqrt(h2), vfloat<M>(neg_inf) );
-
- /* clip away front hit if it is inside next cone segment */
- t_sph1_front = (-O1dO - rhs1)*rcp_dOdO;
- const Vec3vf<M> hit_front = org + t_sph1_front*dO;
- vbool<M> valid_sph1_front = h2 >= 0.0f & yp + t_sph1_front*dOdP > g & !coneR.isClippedByPlane (valid, hit_front);
- lower = select(valid_sph1_front, t_sph1_front, vfloat<M>(pos_inf));
-
-#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
- /* clip away back hit if it is inside next cone segment */
- t_sph1_back = (-O1dO + rhs1)*rcp_dOdO;
- const Vec3vf<M> hit_back = org + t_sph1_back*dO;
- vbool<M> valid_sph1_back = h2 >= 0.0f & yp + t_sph1_back*dOdP > g & !coneR.isClippedByPlane (valid, hit_back);
- upper = select(valid_sph1_back, t_sph1_back, vfloat<M>(neg_inf));
-#else
- upper = vfloat<M>(neg_inf);
-#endif
- }
-
- __forceinline void intersectBeginSphere(const vbool<M>& valid,
- vfloat<M>& lower, vfloat<M>& upper)
- {
- /* calculate front and back hit with end sphere */
- const Vec3vf<M> O1 = org - p0;
- const vfloat<M> O1dO = dot(O1,dO);
- const vfloat<M> h2 = sqr(O1dO) - dOdO*(sqr(O1) - sqr(r0));
- const vfloat<M> rhs1 = select( h2 >= 0.0f, sqrt(h2), vfloat<M>(neg_inf) );
-
- /* clip away front hit if it is inside next cone segment */
- t_sph0_front = (-O1dO - rhs1)*rcp_dOdO;
- vbool<M> valid_sph1_front = valid & h2 >= 0.0f & yp + t_sph0_front*dOdP < 0;
- lower = select(valid_sph1_front, t_sph0_front, vfloat<M>(pos_inf));
-
-#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
- /* clip away back hit if it is inside next cone segment */
- t_sph0_back = (-O1dO + rhs1)*rcp_dOdO;
- vbool<M> valid_sph1_back = valid & h2 >= 0.0f & yp + t_sph0_back*dOdP < 0;
- upper = select(valid_sph1_back, t_sph0_back, vfloat<M>(neg_inf));
-#else
- upper = vfloat<M>(neg_inf);
-#endif
- }
-
- /*
-
- This function calculates the geometry normal of some cone hit.
-
- For a given hit point h (relative to p0) with a cone
- starting at p0 with radius w0 and ending at p1 with
- radius w1 one normally calculates the geometry normal by
- first calculating the parmetric u hit location along the
- cone:
-
- u = dot(h,dP)/dP^2
-
- Using this value one can now directly calculate the
- geometry normal by bending the connection vector (h-u*dP)
- from hit to projected hit with some cone dependent value
- dw/sqrt(dP^2) * normalize(dP):
-
- Ng = normalize(h-u*dP) - dw/length(dP) * normalize(dP)
-
- The length of the vector (h-u*dP) can also get calculated
- by interpolating the radii as w0+u*dw which yields:
-
- Ng = (h-u*dP)/(w0+u*dw) - dw/dP^2 * dP
-
- Multiplying with (w0+u*dw) yield a scaled Ng':
-
- Ng' = (h-u*dP) - (w0+u*dw)*dw/dP^2*dP
-
- Inserting the definition of w0 and dw and refactoring
- yield a furhter scaled Ng'':
-
- Ng'' = (dP^2 - dr^2) (h-q) - (r0+u*dr)*dr*dP
-
- Now inserting the definition of u gives and multiplying
- with the denominator yields:
-
- Ng''' = (dP^2-dr^2)*(dP^2*h-dot(h,dP)*dP) - (dP^2*r0+dot(h,dP)*dr)*dr*dP
-
- Factoring out, cancelling terms, dividing by dP^2, and
- factoring again yields finally:
-
- Ng'''' = (dP^2-dr^2)*h - dP*(dot(h,dP) + r0*dr)
-
- */
-
- __forceinline Vec3vf<M> Ng_cone(const vbool<M>& front_hit) const
- {
-#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
- const vfloat<M> y = select(front_hit, y_cone_front, y_cone_back);
- const vfloat<M> t = select(front_hit, t_cone_front, t_cone_back);
- const Vec3vf<M> h = O + t*dO;
- return g*h-dP*y;
-#else
- const Vec3vf<M> h = O + t_cone_front*dO;
- return g*h-dP*y_cone_front;
-#endif
- }
-
- /* compute geometry normal of sphere hit as the difference
- * vector from hit point to sphere center */
-
- __forceinline Vec3vf<M> Ng_sphere1(const vbool<M>& front_hit) const
- {
-#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
- const vfloat<M> t_sph1 = select(front_hit, t_sph1_front, t_sph1_back);
- return org+t_sph1*dO-p1;
-#else
- return org+t_sph1_front*dO-p1;
-#endif
- }
-
- __forceinline Vec3vf<M> Ng_sphere0(const vbool<M>& front_hit) const
- {
-#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
- const vfloat<M> t_sph0 = select(front_hit, t_sph0_front, t_sph0_back);
- return org+t_sph0*dO-p0;
-#else
- return org+t_sph0_front*dO-p0;
-#endif
- }
-
- /*
- This function calculates the u coordinate of a
- hit. Therefore we use the hit distance y (which is zero
- at the first cone clipping plane) and divide by distance
- g between the clipping planes.
-
- */
-
- __forceinline vfloat<M> u_cone(const vbool<M>& front_hit) const
- {
-#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
- const vfloat<M> y = select(front_hit, y_cone_front, y_cone_back);
- return clamp(y*rcp(g));
-#else
- return clamp(y_cone_front*rcp(g));
-#endif
- }
-
- private:
- Vec3vf<M> org;
- Vec3vf<M> O;
- Vec3vf<M> dO;
- vfloat<M> dOdO;
- vfloat<M> rcp_dOdO;
- vfloat<M> OdP;
- vfloat<M> dOdP;
-
- /* for ray/cone intersection */
- private:
- vfloat<M> yp;
- vfloat<M> y_cone_front;
- vfloat<M> t_cone_front;
-#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
- vfloat<M> y_cone_back;
- vfloat<M> t_cone_back;
-#endif
-
- /* for ray/sphere intersection */
- private:
- vfloat<M> t_sph1_front;
- vfloat<M> t_sph0_front;
-#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
- vfloat<M> t_sph1_back;
- vfloat<M> t_sph0_back;
-#endif
- };
-
-
- template<int M, typename Epilog, typename ray_tfar_func>
- static __forceinline bool intersectConeSphere(const vbool<M>& valid_i,
- const Vec3vf<M>& ray_org_in, const Vec3vf<M>& ray_dir,
- const vfloat<M>& ray_tnear, const ray_tfar_func& ray_tfar,
- const Vec4vf<M>& v0, const Vec4vf<M>& v1,
- const Vec4vf<M>& vL, const Vec4vf<M>& vR,
- const Epilog& epilog)
- {
- vbool<M> valid = valid_i;
-
- /* move ray origin closer to make calculations numerically stable */
- const vfloat<M> dOdO = sqr(ray_dir);
- const vfloat<M> rcp_dOdO = rcp(dOdO);
- const Vec3vf<M> center = vfloat<M>(0.5f)*(v0.xyz()+v1.xyz());
- const vfloat<M> dt = dot(center-ray_org_in,ray_dir)*rcp_dOdO;
- const Vec3vf<M> ray_org = ray_org_in + dt*ray_dir;
-
- /* intersect with cone from v0 to v1 */
- vfloat<M> t_cone_lower, t_cone_upper;
- ConeGeometryIntersector<M> cone (ray_org, ray_dir, dOdO, rcp_dOdO, v0, v1);
- vbool<M> validCone = valid;
- cone.intersectCone(validCone, t_cone_lower, t_cone_upper);
-
- valid &= (validCone | (cone.g <= 0.0f)); // if cone is entirely in sphere end - check sphere
- if (unlikely(none(valid)))
- return false;
-
- /* cone hits inside the neighboring capped cones are inside the geometry and thus ignored */
- const ConeGeometry<M> coneL (v0, vL);
- const ConeGeometry<M> coneR (v1, vR);
-#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
- const Vec3vf<M> hit_lower = ray_org + t_cone_lower*ray_dir;
- const Vec3vf<M> hit_upper = ray_org + t_cone_upper*ray_dir;
- t_cone_lower = select (!coneL.isInsideCappedCone (validCone, hit_lower) & !coneR.isInsideCappedCone (validCone, hit_lower), t_cone_lower, vfloat<M>(pos_inf));
- t_cone_upper = select (!coneL.isInsideCappedCone (validCone, hit_upper) & !coneR.isInsideCappedCone (validCone, hit_upper), t_cone_upper, vfloat<M>(neg_inf));
-#endif
-
- /* intersect ending sphere */
- vfloat<M> t_sph1_lower, t_sph1_upper;
- vfloat<M> t_sph0_lower = vfloat<M>(pos_inf);
- vfloat<M> t_sph0_upper = vfloat<M>(neg_inf);
- cone.intersectEndSphere(valid, coneR, t_sph1_lower, t_sph1_upper);
-
- const vbool<M> isBeginPoint = valid & (vL[0] == vfloat<M>(pos_inf));
- if (unlikely(any(isBeginPoint))) {
- cone.intersectBeginSphere (isBeginPoint, t_sph0_lower, t_sph0_upper);
- }
-
- /* CSG union of cone and end sphere */
- vfloat<M> t_sph_lower = min(t_sph0_lower, t_sph1_lower);
- vfloat<M> t_cone_sphere_lower = min(t_cone_lower, t_sph_lower);
-#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
- vfloat<M> t_sph_upper = max(t_sph0_upper, t_sph1_upper);
- vfloat<M> t_cone_sphere_upper = max(t_cone_upper, t_sph_upper);
-
- /* filter out hits that are not in tnear/tfar range */
- const vbool<M> valid_lower = valid & ray_tnear <= dt+t_cone_sphere_lower & dt+t_cone_sphere_lower <= ray_tfar() & t_cone_sphere_lower != vfloat<M>(pos_inf);
- const vbool<M> valid_upper = valid & ray_tnear <= dt+t_cone_sphere_upper & dt+t_cone_sphere_upper <= ray_tfar() & t_cone_sphere_upper != vfloat<M>(neg_inf);
-
- /* check if there is a first hit */
- const vbool<M> valid_first = valid_lower | valid_upper;
- if (unlikely(none(valid_first)))
- return false;
-
- /* construct first hit */
- const vfloat<M> t_first = select(valid_lower, t_cone_sphere_lower, t_cone_sphere_upper);
- const vbool<M> cone_hit_first = t_first == t_cone_lower | t_first == t_cone_upper;
- const vbool<M> sph0_hit_first = t_first == t_sph0_lower | t_first == t_sph0_upper;
- const Vec3vf<M> Ng_first = select(cone_hit_first, cone.Ng_cone(valid_lower), select (sph0_hit_first, cone.Ng_sphere0(valid_lower), cone.Ng_sphere1(valid_lower)));
- const vfloat<M> u_first = select(cone_hit_first, cone.u_cone(valid_lower), select (sph0_hit_first, vfloat<M>(zero), vfloat<M>(one)));
-
- /* invoke intersection filter for first hit */
- RoundLineIntersectorHitM<M> hit(u_first,zero,dt+t_first,Ng_first);
- const bool is_hit_first = epilog(valid_first, hit);
-
- /* check for possible second hits before potentially accepted hit */
- const vfloat<M> t_second = t_cone_sphere_upper;
- const vbool<M> valid_second = valid_lower & valid_upper & (dt+t_cone_sphere_upper <= ray_tfar());
- if (unlikely(none(valid_second)))
- return is_hit_first;
-
- /* invoke intersection filter for second hit */
- const vbool<M> cone_hit_second = t_second == t_cone_lower | t_second == t_cone_upper;
- const vbool<M> sph0_hit_second = t_second == t_sph0_lower | t_second == t_sph0_upper;
- const Vec3vf<M> Ng_second = select(cone_hit_second, cone.Ng_cone(false), select (sph0_hit_second, cone.Ng_sphere0(false), cone.Ng_sphere1(false)));
- const vfloat<M> u_second = select(cone_hit_second, cone.u_cone(false), select (sph0_hit_second, vfloat<M>(zero), vfloat<M>(one)));
-
- hit = RoundLineIntersectorHitM<M>(u_second,zero,dt+t_second,Ng_second);
- const bool is_hit_second = epilog(valid_second, hit);
-
- return is_hit_first | is_hit_second;
-#else
- /* filter out hits that are not in tnear/tfar range */
- const vbool<M> valid_lower = valid & ray_tnear <= dt+t_cone_sphere_lower & dt+t_cone_sphere_lower <= ray_tfar() & t_cone_sphere_lower != vfloat<M>(pos_inf);
-
- /* check if there is a valid hit */
- if (unlikely(none(valid_lower)))
- return false;
-
- /* construct first hit */
- const vbool<M> cone_hit_first = t_cone_sphere_lower == t_cone_lower | t_cone_sphere_lower == t_cone_upper;
- const vbool<M> sph0_hit_first = t_cone_sphere_lower == t_sph0_lower | t_cone_sphere_lower == t_sph0_upper;
- const Vec3vf<M> Ng_first = select(cone_hit_first, cone.Ng_cone(valid_lower), select (sph0_hit_first, cone.Ng_sphere0(valid_lower), cone.Ng_sphere1(valid_lower)));
- const vfloat<M> u_first = select(cone_hit_first, cone.u_cone(valid_lower), select (sph0_hit_first, vfloat<M>(zero), vfloat<M>(one)));
-
- /* invoke intersection filter for first hit */
- RoundLineIntersectorHitM<M> hit(u_first,zero,dt+t_cone_sphere_lower,Ng_first);
- const bool is_hit_first = epilog(valid_lower, hit);
-
- return is_hit_first;
-#endif
- }
-
- } // end namespace __roundline_internal
-
- template<int M>
- struct RoundLinearCurveIntersector1
- {
- typedef CurvePrecalculations1 Precalculations;
-
- struct ray_tfar {
- Ray& ray;
- __forceinline ray_tfar(Ray& ray) : ray(ray) {}
- __forceinline vfloat<M> operator() () const { return ray.tfar; };
- };
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- Ray& ray,
- IntersectContext* context,
- const LineSegments* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
- const Vec4vf<M>& vLi, const Vec4vf<M>& vRi,
- const Epilog& epilog)
- {
- const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
- const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
- const vfloat<M> ray_tnear(ray.tnear());
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec4vf<M> v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i);
- const Vec4vf<M> vL = enlargeRadiusToMinWidth(context,geom,ray_org,vLi);
- const Vec4vf<M> vR = enlargeRadiusToMinWidth(context,geom,ray_org,vRi);
- return __roundline_internal::intersectConeSphere(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray),v0,v1,vL,vR,epilog);
- }
- };
-
- template<int M, int K>
- struct RoundLinearCurveIntersectorK
- {
- typedef CurvePrecalculationsK<K> Precalculations;
-
- struct ray_tfar {
- RayK<K>& ray;
- size_t k;
- __forceinline ray_tfar(RayK<K>& ray, size_t k) : ray(ray), k(k) {}
- __forceinline vfloat<M> operator() () const { return ray.tfar[k]; };
- };
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- RayK<K>& ray, size_t k,
- IntersectContext* context,
- const LineSegments* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
- const Vec4vf<M>& vLi, const Vec4vf<M>& vRi,
- const Epilog& epilog)
- {
- const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
- const vfloat<M> ray_tnear = ray.tnear()[k];
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec4vf<M> v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i);
- const Vec4vf<M> vL = enlargeRadiusToMinWidth(context,geom,ray_org,vLi);
- const Vec4vf<M> vR = enlargeRadiusToMinWidth(context,geom,ray_org,vRi);
- return __roundline_internal::intersectConeSphere(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray,k),v0,v1,vL,vR,epilog);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/roundlinei_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/roundlinei_intersector.h
deleted file mode 100644
index 079817335e..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/roundlinei_intersector.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// ======================================================================== //
-// Copyright 2009-2020 Intel Corporation //
-// //
-// Licensed under the Apache License, Version 2.0 (the "License"); //
-// you may not use this file except in compliance with the License. //
-// You may obtain a copy of the License at //
-// //
-// http://www.apache.org/licenses/LICENSE-2.0 //
-// //
-// Unless required by applicable law or agreed to in writing, software //
-// distributed under the License is distributed on an "AS IS" BASIS, //
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
-// See the License for the specific language governing permissions and //
-// limitations under the License. //
-// ======================================================================== //
-
-#pragma once
-
-#include "roundline_intersector.h"
-#include "intersector_epilog.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M, int Mx, bool filter>
- struct RoundLinearCurveMiIntersector1
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- RoundLinearCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Intersect1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- return RoundLinearCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Occluded1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
- }
- };
-
- template<int M, int Mx, bool filter>
- struct RoundLinearCurveMiMBIntersector1
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time());
- const vbool<Mx> valid = line.template valid<Mx>();
- RoundLinearCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Intersect1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time());
- const vbool<Mx> valid = line.template valid<Mx>();
- return RoundLinearCurveIntersector1<Mx>::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Occluded1EpilogM<M,Mx,filter>(ray,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct RoundLinearCurveMiIntersectorK
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- RoundLinearCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom);
- const vbool<Mx> valid = line.template valid<Mx>();
- return RoundLinearCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct RoundLinearCurveMiMBIntersectorK
- {
- typedef LineMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(normal.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time()[k]);
- const vbool<Mx> valid = line.template valid<Mx>();
- RoundLinearCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
- Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time()[k]);
- const vbool<Mx> valid = line.template valid<Mx>();
- return RoundLinearCurveIntersectorK<Mx,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,line.geomID(),line.primID()));
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/sphere_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/sphere_intersector.h
deleted file mode 100644
index 3ab90c29ef..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/sphere_intersector.h
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "../common/scene_points.h"
-#include "curve_intersector_precalculations.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct SphereIntersectorHitM
- {
- __forceinline SphereIntersectorHitM() {}
-
- __forceinline SphereIntersectorHitM(const vfloat<M>& t, const Vec3vf<M>& Ng)
- : vt(t), vNg(Ng) {}
-
- __forceinline void finalize() {}
-
- __forceinline Vec2f uv(const size_t i) const {
- return Vec2f(0.0f, 0.0f);
- }
- __forceinline float t(const size_t i) const {
- return vt[i];
- }
- __forceinline Vec3fa Ng(const size_t i) const {
- return Vec3fa(vNg.x[i], vNg.y[i], vNg.z[i]);
- }
-
- public:
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- template<int M>
- struct SphereIntersector1
- {
- typedef CurvePrecalculations1 Precalculations;
-
- template<typename Epilog>
- static __forceinline bool intersect(
- const vbool<M>& valid_i, Ray& ray,
- const Precalculations& pre, const Vec4vf<M>& v0, const Epilog& epilog)
- {
- vbool<M> valid = valid_i;
-
- const vfloat<M> rd2 = rcp(dot(ray.dir, ray.dir));
- const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
- const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
- const Vec3vf<M> center = v0.xyz();
- const vfloat<M> radius = v0.w;
-
- const Vec3vf<M> c0 = center - ray_org;
- const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
- const Vec3vf<M> perp = c0 - projC0 * ray_dir;
- const vfloat<M> l2 = dot(perp, perp);
- const vfloat<M> r2 = radius * radius;
- valid &= (l2 <= r2);
- if (unlikely(none(valid)))
- return false;
-
- const vfloat<M> td = sqrt((r2 - l2) * rd2);
- const vfloat<M> t_front = projC0 - td;
- const vfloat<M> t_back = projC0 + td;
-
- const vbool<M> valid_front = valid & (ray.tnear() <= t_front) & (t_front <= ray.tfar);
- const vbool<M> valid_back = valid & (ray.tnear() <= t_back ) & (t_back <= ray.tfar);
-
- /* check if there is a first hit */
- const vbool<M> valid_first = valid_front | valid_back;
- if (unlikely(none(valid_first)))
- return false;
-
- /* construct first hit */
- const vfloat<M> td_front = -td;
- const vfloat<M> td_back = +td;
- const vfloat<M> t_first = select(valid_front, t_front, t_back);
- const Vec3vf<M> Ng_first = select(valid_front, td_front, td_back) * ray_dir - perp;
- SphereIntersectorHitM<M> hit(t_first, Ng_first);
-
- /* invoke intersection filter for first hit */
- const bool is_hit_first = epilog(valid_first, hit);
-
- /* check for possible second hits before potentially accepted hit */
- const vfloat<M> t_second = t_back;
- const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar);
- if (unlikely(none(valid_second)))
- return is_hit_first;
-
- /* invoke intersection filter for second hit */
- const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
- hit = SphereIntersectorHitM<M> (t_second, Ng_second);
- const bool is_hit_second = epilog(valid_second, hit);
-
- return is_hit_first | is_hit_second;
- }
-
- template<typename Epilog>
- static __forceinline bool intersect(
- const vbool<M>& valid_i, Ray& ray, IntersectContext* context, const Points* geom,
- const Precalculations& pre, const Vec4vf<M>& v0i, const Epilog& epilog)
- {
- const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- return intersect(valid_i,ray,pre,v0,epilog);
- }
- };
-
- template<int M, int K>
- struct SphereIntersectorK
- {
- typedef CurvePrecalculationsK<K> Precalculations;
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid_i,
- RayK<K>& ray, size_t k,
- IntersectContext* context,
- const Points* geom,
- const Precalculations& pre,
- const Vec4vf<M>& v0i,
- const Epilog& epilog)
- {
- vbool<M> valid = valid_i;
-
- const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
- const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
- const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
-
- const Vec4vf<M> v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i);
- const Vec3vf<M> center = v0.xyz();
- const vfloat<M> radius = v0.w;
-
- const Vec3vf<M> c0 = center - ray_org;
- const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
- const Vec3vf<M> perp = c0 - projC0 * ray_dir;
- const vfloat<M> l2 = dot(perp, perp);
- const vfloat<M> r2 = radius * radius;
- valid &= (l2 <= r2);
- if (unlikely(none(valid)))
- return false;
-
- const vfloat<M> td = sqrt((r2 - l2) * rd2);
- const vfloat<M> t_front = projC0 - td;
- const vfloat<M> t_back = projC0 + td;
-
- const vbool<M> valid_front = valid & (ray.tnear()[k] <= t_front) & (t_front <= ray.tfar[k]);
- const vbool<M> valid_back = valid & (ray.tnear()[k] <= t_back ) & (t_back <= ray.tfar[k]);
-
- /* check if there is a first hit */
- const vbool<M> valid_first = valid_front | valid_back;
- if (unlikely(none(valid_first)))
- return false;
-
- /* construct first hit */
- const vfloat<M> td_front = -td;
- const vfloat<M> td_back = +td;
- const vfloat<M> t_first = select(valid_front, t_front, t_back);
- const Vec3vf<M> Ng_first = select(valid_front, td_front, td_back) * ray_dir - perp;
- SphereIntersectorHitM<M> hit(t_first, Ng_first);
-
- /* invoke intersection filter for first hit */
- const bool is_hit_first = epilog(valid_first, hit);
-
- /* check for possible second hits before potentially accepted hit */
- const vfloat<M> t_second = t_back;
- const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar[k]);
- if (unlikely(none(valid_second)))
- return is_hit_first;
-
- /* invoke intersection filter for second hit */
- const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
- hit = SphereIntersectorHitM<M> (t_second, Ng_second);
- const bool is_hit_second = epilog(valid_second, hit);
-
- return is_hit_first | is_hit_second;
- }
- };
- } // namespace isa
-} // namespace embree
diff --git a/thirdparty/embree-aarch64/kernels/geometry/spherei_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/spherei_intersector.h
deleted file mode 100644
index 1146847602..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/spherei_intersector.h
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "intersector_epilog.h"
-#include "pointi.h"
-#include "sphere_intersector.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int M, int Mx, bool filter>
- struct SphereMiIntersector1
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre,
- RayHit& ray,
- IntersectContext* context,
- const Primitive& sphere)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(sphere.geomID());
- Vec4vf<M> v0; sphere.gather(v0, geom);
- const vbool<Mx> valid = sphere.template valid<Mx>();
- SphereIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, Intersect1EpilogM<M, Mx, filter>(ray, context, sphere.geomID(), sphere.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre,
- Ray& ray,
- IntersectContext* context,
- const Primitive& sphere)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(sphere.geomID());
- Vec4vf<M> v0; sphere.gather(v0, geom);
- const vbool<Mx> valid = sphere.template valid<Mx>();
- return SphereIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, Occluded1EpilogM<M, Mx, filter>(ray, context, sphere.geomID(), sphere.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query,
- PointQueryContext* context,
- const Primitive& sphere)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, sphere);
- }
- };
-
- template<int M, int Mx, bool filter>
- struct SphereMiMBIntersector1
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculations1 Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre,
- RayHit& ray,
- IntersectContext* context,
- const Primitive& sphere)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(sphere.geomID());
- Vec4vf<M> v0; sphere.gather(v0, geom, ray.time());
- const vbool<Mx> valid = sphere.template valid<Mx>();
- SphereIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, Intersect1EpilogM<M, Mx, filter>(ray, context, sphere.geomID(), sphere.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre,
- Ray& ray,
- IntersectContext* context,
- const Primitive& sphere)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(sphere.geomID());
- Vec4vf<M> v0; sphere.gather(v0, geom, ray.time());
- const vbool<Mx> valid = sphere.template valid<Mx>();
- return SphereIntersector1<Mx>::intersect(
- valid, ray, context, geom, pre, v0, Occluded1EpilogM<M, Mx, filter>(ray, context, sphere.geomID(), sphere.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query,
- PointQueryContext* context,
- const Primitive& sphere)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, sphere);
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct SphereMiIntersectorK
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(
- const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& sphere)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(sphere.geomID());
- Vec4vf<M> v0; sphere.gather(v0, geom);
- const vbool<Mx> valid = sphere.template valid<Mx>();
- SphereIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0,
- Intersect1KEpilogM<M, Mx, K, filter>(ray, k, context, sphere.geomID(), sphere.primID()));
- }
-
- static __forceinline bool occluded(
- const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& sphere)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(sphere.geomID());
- Vec4vf<M> v0; sphere.gather(v0, geom);
- const vbool<Mx> valid = sphere.template valid<Mx>();
- return SphereIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0,
- Occluded1KEpilogM<M, Mx, K, filter>(ray, k, context, sphere.geomID(), sphere.primID()));
- }
- };
-
- template<int M, int Mx, int K, bool filter>
- struct SphereMiMBIntersectorK
- {
- typedef PointMi<M> Primitive;
- typedef CurvePrecalculationsK<K> Precalculations;
-
- static __forceinline void intersect(
- const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& sphere)
- {
- STAT3(normal.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(sphere.geomID());
- Vec4vf<M> v0; sphere.gather(v0, geom, ray.time()[k]);
- const vbool<Mx> valid = sphere.template valid<Mx>();
- SphereIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0,
- Intersect1KEpilogM<M, Mx, K, filter>(ray, k, context, sphere.geomID(), sphere.primID()));
- }
-
- static __forceinline bool occluded(
- const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& sphere)
- {
- STAT3(shadow.trav_prims, 1, 1, 1);
- const Points* geom = context->scene->get<Points>(sphere.geomID());
- Vec4vf<M> v0; sphere.gather(v0, geom, ray.time()[k]);
- const vbool<Mx> valid = sphere.template valid<Mx>();
- return SphereIntersectorK<Mx, K>::intersect(
- valid, ray, k, context, geom, pre, v0,
- Occluded1KEpilogM<M, Mx, K, filter>(ray, k, context, sphere.geomID(), sphere.primID()));
- }
- };
- } // namespace isa
-} // namespace embree
diff --git a/thirdparty/embree-aarch64/kernels/geometry/subdivpatch1.h b/thirdparty/embree-aarch64/kernels/geometry/subdivpatch1.h
deleted file mode 100644
index 94ad46ad87..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/subdivpatch1.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../geometry/primitive.h"
-#include "../subdiv/subdivpatch1base.h"
-
-namespace embree
-{
-
- struct __aligned(64) SubdivPatch1 : public SubdivPatch1Base
- {
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
-
- static Type type;
-
- public:
-
- /*! constructor for cached subdiv patch */
- SubdivPatch1 (const unsigned int gID,
- const unsigned int pID,
- const unsigned int subPatch,
- const SubdivMesh *const mesh,
- const size_t time,
- const Vec2f uv[4],
- const float edge_level[4],
- const int subdiv[4],
- const int simd_width)
- : SubdivPatch1Base(gID,pID,subPatch,mesh,time,uv,edge_level,subdiv,simd_width) {}
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/subdivpatch1_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/subdivpatch1_intersector.h
deleted file mode 100644
index 74ec1de258..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/subdivpatch1_intersector.h
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "subdivpatch1.h"
-#include "grid_soa.h"
-#include "grid_soa_intersector1.h"
-#include "grid_soa_intersector_packet.h"
-#include "../common/ray.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename T>
- class SubdivPatch1Precalculations : public T
- {
- public:
- __forceinline SubdivPatch1Precalculations (const Ray& ray, const void* ptr)
- : T(ray,ptr) {}
- };
-
- template<int K, typename T>
- class SubdivPatch1PrecalculationsK : public T
- {
- public:
- __forceinline SubdivPatch1PrecalculationsK (const vbool<K>& valid, RayK<K>& ray)
- : T(valid,ray) {}
- };
-
- class SubdivPatch1Intersector1
- {
- public:
- typedef GridSOA Primitive;
- typedef SubdivPatch1Precalculations<GridSOAIntersector1::Precalculations> Precalculations;
-
- static __forceinline bool processLazyNode(Precalculations& pre, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- lazy_node = prim->root(0);
- pre.grid = (Primitive*)prim;
- return false;
- }
-
- /*! Intersect a ray with the primitive. */
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) GridSOAIntersector1::intersect(pre,ray,context,prim,lazy_node);
- else processLazyNode(pre,context,prim,lazy_node);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node) {
- intersect(This,pre,ray,context,prim,ty,tray,lazy_node);
- }
-
- /*! Test if the ray is occluded by the primitive */
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) return GridSOAIntersector1::occluded(pre,ray,context,prim,lazy_node);
- else return processLazyNode(pre,context,prim,lazy_node);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node) {
- return occluded(This,pre,ray,context,prim,ty,tray,lazy_node);
- }
-
- template<int N>
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t ty, const TravPointQuery<N> &tquery, size_t& lazy_node)
- {
- // TODO: PointQuery implement
- assert(false && "not implemented");
- return false;
- }
-
- template<int N>
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravPointQuery<N> &tquery, size_t& lazy_node) {
- return pointQuery(This,query,context,prim,ty,tquery,lazy_node);
- }
- };
-
- class SubdivPatch1MBIntersector1
- {
- public:
- typedef SubdivPatch1 Primitive;
- typedef GridSOAMBIntersector1::Precalculations Precalculations;
-
- static __forceinline bool processLazyNode(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim_i, size_t& lazy_node)
- {
- Primitive* prim = (Primitive*) prim_i;
- GridSOA* grid = nullptr;
- grid = (GridSOA*) prim->root_ref.get();
- pre.itime = getTimeSegment(ray.time(), float(grid->time_steps-1), pre.ftime);
- lazy_node = grid->root(pre.itime);
- pre.grid = grid;
- return false;
- }
-
- /*! Intersect a ray with the primitive. */
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) GridSOAMBIntersector1::intersect(pre,ray,context,prim,lazy_node);
- else processLazyNode(pre,ray,context,prim,lazy_node);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node) {
- intersect(This,pre,ray,context,prim,ty,tray,lazy_node);
- }
-
- /*! Test if the ray is occluded by the primitive */
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) return GridSOAMBIntersector1::occluded(pre,ray,context,prim,lazy_node);
- else return processLazyNode(pre,ray,context,prim,lazy_node);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node) {
- return occluded(This,pre,ray,context,prim,ty,tray,lazy_node);
- }
-
- template<int N>
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t ty, const TravPointQuery<N> &tquery, size_t& lazy_node)
- {
- // TODO: PointQuery implement
- assert(false && "not implemented");
- return false;
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravPointQuery<N> &tquery, size_t& lazy_node) {
- return pointQuery(This,query,context,prim,ty,tquery,lazy_node);
- }
- };
-
- template <int K>
- struct SubdivPatch1IntersectorK
- {
- typedef GridSOA Primitive;
- typedef SubdivPatch1PrecalculationsK<K,typename GridSOAIntersectorK<K>::Precalculations> Precalculations;
-
- static __forceinline bool processLazyNode(Precalculations& pre, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
- {
- lazy_node = prim->root(0);
- pre.grid = (Primitive*)prim;
- return false;
- }
-
- template<bool robust>
- static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) GridSOAIntersectorK<K>::intersect(valid,pre,ray,context,prim,lazy_node);
- else processLazyNode(pre,context,prim,lazy_node);
- }
-
- template<bool robust>
- static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) return GridSOAIntersectorK<K>::occluded(valid,pre,ray,context,prim,lazy_node);
- else return processLazyNode(pre,context,prim,lazy_node);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) GridSOAIntersectorK<K>::intersect(pre,ray,k,context,prim,lazy_node);
- else processLazyNode(pre,context,prim,lazy_node);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) return GridSOAIntersectorK<K>::occluded(pre,ray,k,context,prim,lazy_node);
- else return processLazyNode(pre,context,prim,lazy_node);
- }
- };
-
- typedef SubdivPatch1IntersectorK<4> SubdivPatch1Intersector4;
- typedef SubdivPatch1IntersectorK<8> SubdivPatch1Intersector8;
- typedef SubdivPatch1IntersectorK<16> SubdivPatch1Intersector16;
-
- template <int K>
- struct SubdivPatch1MBIntersectorK
- {
- typedef SubdivPatch1 Primitive;
- //typedef GridSOAMBIntersectorK<K>::Precalculations Precalculations;
- typedef SubdivPatch1PrecalculationsK<K,typename GridSOAMBIntersectorK<K>::Precalculations> Precalculations;
-
- static __forceinline bool processLazyNode(Precalculations& pre, IntersectContext* context, const Primitive* prim_i, size_t& lazy_node)
- {
- Primitive* prim = (Primitive*) prim_i;
- GridSOA* grid = (GridSOA*) prim->root_ref.get();
- lazy_node = grid->troot;
- pre.grid = grid;
- return false;
- }
-
- template<bool robust>
- static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) GridSOAMBIntersectorK<K>::intersect(valid,pre,ray,context,prim,lazy_node);
- else processLazyNode(pre,context,prim,lazy_node);
- }
-
- template<bool robust>
- static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) return GridSOAMBIntersectorK<K>::occluded(valid,pre,ray,context,prim,lazy_node);
- else return processLazyNode(pre,context,prim,lazy_node);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) GridSOAMBIntersectorK<K>::intersect(pre,ray,k,context,prim,lazy_node);
- else processLazyNode(pre,context,prim,lazy_node);
- }
-
- template<int N, int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- if (likely(ty == 0)) return GridSOAMBIntersectorK<K>::occluded(pre,ray,k,context,prim,lazy_node);
- else return processLazyNode(pre,context,prim,lazy_node);
- }
- };
-
- typedef SubdivPatch1MBIntersectorK<4> SubdivPatch1MBIntersector4;
- typedef SubdivPatch1MBIntersectorK<8> SubdivPatch1MBIntersector8;
- typedef SubdivPatch1MBIntersectorK<16> SubdivPatch1MBIntersector16;
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/subgrid.h b/thirdparty/embree-aarch64/kernels/geometry/subgrid.h
deleted file mode 100644
index 39fa6fb0f0..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/subgrid.h
+++ /dev/null
@@ -1,517 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/ray.h"
-#include "../common/scene_grid_mesh.h"
-#include "../bvh/bvh.h"
-
-namespace embree
-{
- /* Stores M quads from an indexed face set */
- struct SubGrid
- {
- /* Virtual interface to query information about the quad type */
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* primitive supports multiple time segments */
- static const bool singleTimeSegment = false;
-
- /* Returns maximum number of stored quads */
- static __forceinline size_t max_size() { return 1; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
-
- public:
-
- /* Default constructor */
- __forceinline SubGrid() { }
-
- /* Construction from vertices and IDs */
- __forceinline SubGrid(const unsigned int x,
- const unsigned int y,
- const unsigned int geomID,
- const unsigned int primID)
- : _x(x), _y(y), _geomID(geomID), _primID(primID)
- {
- }
-
- __forceinline bool invalid3x3X() const { return (unsigned int)_x & (1<<15); }
- __forceinline bool invalid3x3Y() const { return (unsigned int)_y & (1<<15); }
-
- /* Gather the quads */
- __forceinline void gather(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- Vec3vf4& p3,
- const GridMesh* const mesh,
- const GridMesh::Grid &g) const
- {
- /* first quad always valid */
- const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset;
- const size_t vtxID01 = vtxID00 + 1;
- const vfloat4 vtx00 = vfloat4::loadu(mesh->vertexPtr(vtxID00));
- const vfloat4 vtx01 = vfloat4::loadu(mesh->vertexPtr(vtxID01));
- const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
- const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
- const vfloat4 vtx10 = vfloat4::loadu(mesh->vertexPtr(vtxID10));
- const vfloat4 vtx11 = vfloat4::loadu(mesh->vertexPtr(vtxID11));
-
- /* deltaX => vtx02, vtx12 */
- const size_t deltaX = invalid3x3X() ? 0 : 1;
- const size_t vtxID02 = vtxID01 + deltaX;
- const vfloat4 vtx02 = vfloat4::loadu(mesh->vertexPtr(vtxID02));
- const size_t vtxID12 = vtxID11 + deltaX;
- const vfloat4 vtx12 = vfloat4::loadu(mesh->vertexPtr(vtxID12));
-
- /* deltaY => vtx20, vtx21 */
- const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset;
- const size_t vtxID20 = vtxID10 + deltaY;
- const size_t vtxID21 = vtxID11 + deltaY;
- const vfloat4 vtx20 = vfloat4::loadu(mesh->vertexPtr(vtxID20));
- const vfloat4 vtx21 = vfloat4::loadu(mesh->vertexPtr(vtxID21));
-
- /* deltaX/deltaY => vtx22 */
- const size_t vtxID22 = vtxID11 + deltaX + deltaY;
- const vfloat4 vtx22 = vfloat4::loadu(mesh->vertexPtr(vtxID22));
-
- transpose(vtx00,vtx01,vtx11,vtx10,p0.x,p0.y,p0.z);
- transpose(vtx01,vtx02,vtx12,vtx11,p1.x,p1.y,p1.z);
- transpose(vtx11,vtx12,vtx22,vtx21,p2.x,p2.y,p2.z);
- transpose(vtx10,vtx11,vtx21,vtx20,p3.x,p3.y,p3.z);
- }
-
- template<typename T>
- __forceinline vfloat4 getVertexMB(const GridMesh* const mesh, const size_t offset, const size_t itime, const float ftime) const
- {
- const T v0 = T::loadu(mesh->vertexPtr(offset,itime+0));
- const T v1 = T::loadu(mesh->vertexPtr(offset,itime+1));
- return lerp(v0,v1,ftime);
- }
-
- /* Gather the quads */
- __forceinline void gatherMB(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- Vec3vf4& p3,
- const GridMesh* const mesh,
- const GridMesh::Grid &g,
- const size_t itime,
- const float ftime) const
- {
- /* first quad always valid */
- const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset;
- const size_t vtxID01 = vtxID00 + 1;
- const vfloat4 vtx00 = getVertexMB<vfloat4>(mesh,vtxID00,itime,ftime);
- const vfloat4 vtx01 = getVertexMB<vfloat4>(mesh,vtxID01,itime,ftime);
- const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
- const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
- const vfloat4 vtx10 = getVertexMB<vfloat4>(mesh,vtxID10,itime,ftime);
- const vfloat4 vtx11 = getVertexMB<vfloat4>(mesh,vtxID11,itime,ftime);
-
- /* deltaX => vtx02, vtx12 */
- const size_t deltaX = invalid3x3X() ? 0 : 1;
- const size_t vtxID02 = vtxID01 + deltaX;
- const vfloat4 vtx02 = getVertexMB<vfloat4>(mesh,vtxID02,itime,ftime);
- const size_t vtxID12 = vtxID11 + deltaX;
- const vfloat4 vtx12 = getVertexMB<vfloat4>(mesh,vtxID12,itime,ftime);
-
- /* deltaY => vtx20, vtx21 */
- const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset;
- const size_t vtxID20 = vtxID10 + deltaY;
- const size_t vtxID21 = vtxID11 + deltaY;
- const vfloat4 vtx20 = getVertexMB<vfloat4>(mesh,vtxID20,itime,ftime);
- const vfloat4 vtx21 = getVertexMB<vfloat4>(mesh,vtxID21,itime,ftime);
-
- /* deltaX/deltaY => vtx22 */
- const size_t vtxID22 = vtxID11 + deltaX + deltaY;
- const vfloat4 vtx22 = getVertexMB<vfloat4>(mesh,vtxID22,itime,ftime);
-
- transpose(vtx00,vtx01,vtx11,vtx10,p0.x,p0.y,p0.z);
- transpose(vtx01,vtx02,vtx12,vtx11,p1.x,p1.y,p1.z);
- transpose(vtx11,vtx12,vtx22,vtx21,p2.x,p2.y,p2.z);
- transpose(vtx10,vtx11,vtx21,vtx20,p3.x,p3.y,p3.z);
- }
-
-
-
- /* Gather the quads */
- __forceinline void gather(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- Vec3vf4& p3,
- const Scene *const scene) const
- {
- const GridMesh* const mesh = scene->get<GridMesh>(geomID());
- const GridMesh::Grid &g = mesh->grid(primID());
- gather(p0,p1,p2,p3,mesh,g);
- }
-
- /* Gather the quads in the motion blur case */
- __forceinline void gatherMB(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- Vec3vf4& p3,
- const Scene *const scene,
- const size_t itime,
- const float ftime) const
- {
- const GridMesh* const mesh = scene->get<GridMesh>(geomID());
- const GridMesh::Grid &g = mesh->grid(primID());
- gatherMB(p0,p1,p2,p3,mesh,g,itime,ftime);
- }
-
- /* Gather the quads */
- __forceinline void gather(Vec3fa vtx[16], const Scene *const scene) const
- {
- const GridMesh* mesh = scene->get<GridMesh>(geomID());
- const GridMesh::Grid &g = mesh->grid(primID());
-
- /* first quad always valid */
- const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset;
- const size_t vtxID01 = vtxID00 + 1;
- const Vec3fa vtx00 = Vec3fa::loadu(mesh->vertexPtr(vtxID00));
- const Vec3fa vtx01 = Vec3fa::loadu(mesh->vertexPtr(vtxID01));
- const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
- const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
- const Vec3fa vtx10 = Vec3fa::loadu(mesh->vertexPtr(vtxID10));
- const Vec3fa vtx11 = Vec3fa::loadu(mesh->vertexPtr(vtxID11));
-
- /* deltaX => vtx02, vtx12 */
- const size_t deltaX = invalid3x3X() ? 0 : 1;
- const size_t vtxID02 = vtxID01 + deltaX;
- const Vec3fa vtx02 = Vec3fa::loadu(mesh->vertexPtr(vtxID02));
- const size_t vtxID12 = vtxID11 + deltaX;
- const Vec3fa vtx12 = Vec3fa::loadu(mesh->vertexPtr(vtxID12));
-
- /* deltaY => vtx20, vtx21 */
- const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset;
- const size_t vtxID20 = vtxID10 + deltaY;
- const size_t vtxID21 = vtxID11 + deltaY;
- const Vec3fa vtx20 = Vec3fa::loadu(mesh->vertexPtr(vtxID20));
- const Vec3fa vtx21 = Vec3fa::loadu(mesh->vertexPtr(vtxID21));
-
- /* deltaX/deltaY => vtx22 */
- const size_t vtxID22 = vtxID11 + deltaX + deltaY;
- const Vec3fa vtx22 = Vec3fa::loadu(mesh->vertexPtr(vtxID22));
-
- vtx[ 0] = vtx00; vtx[ 1] = vtx01; vtx[ 2] = vtx11; vtx[ 3] = vtx10;
- vtx[ 4] = vtx01; vtx[ 5] = vtx02; vtx[ 6] = vtx12; vtx[ 7] = vtx11;
- vtx[ 8] = vtx10; vtx[ 9] = vtx11; vtx[10] = vtx21; vtx[11] = vtx20;
- vtx[12] = vtx11; vtx[13] = vtx12; vtx[14] = vtx22; vtx[15] = vtx21;
- }
-
- /* Gather the quads */
- __forceinline void gatherMB(vfloat4 vtx[16], const Scene *const scene, const size_t itime, const float ftime) const
- {
- const GridMesh* mesh = scene->get<GridMesh>(geomID());
- const GridMesh::Grid &g = mesh->grid(primID());
-
- /* first quad always valid */
- const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset;
- const size_t vtxID01 = vtxID00 + 1;
- const vfloat4 vtx00 = getVertexMB<vfloat4>(mesh,vtxID00,itime,ftime);
- const vfloat4 vtx01 = getVertexMB<vfloat4>(mesh,vtxID01,itime,ftime);
- const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
- const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
- const vfloat4 vtx10 = getVertexMB<vfloat4>(mesh,vtxID10,itime,ftime);
- const vfloat4 vtx11 = getVertexMB<vfloat4>(mesh,vtxID11,itime,ftime);
-
- /* deltaX => vtx02, vtx12 */
- const size_t deltaX = invalid3x3X() ? 0 : 1;
- const size_t vtxID02 = vtxID01 + deltaX;
- const vfloat4 vtx02 = getVertexMB<vfloat4>(mesh,vtxID02,itime,ftime);
- const size_t vtxID12 = vtxID11 + deltaX;
- const vfloat4 vtx12 = getVertexMB<vfloat4>(mesh,vtxID12,itime,ftime);
-
- /* deltaY => vtx20, vtx21 */
- const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset;
- const size_t vtxID20 = vtxID10 + deltaY;
- const size_t vtxID21 = vtxID11 + deltaY;
- const vfloat4 vtx20 = getVertexMB<vfloat4>(mesh,vtxID20,itime,ftime);
- const vfloat4 vtx21 = getVertexMB<vfloat4>(mesh,vtxID21,itime,ftime);
-
- /* deltaX/deltaY => vtx22 */
- const size_t vtxID22 = vtxID11 + deltaX + deltaY;
- const vfloat4 vtx22 = getVertexMB<vfloat4>(mesh,vtxID22,itime,ftime);
-
- vtx[ 0] = vtx00; vtx[ 1] = vtx01; vtx[ 2] = vtx11; vtx[ 3] = vtx10;
- vtx[ 4] = vtx01; vtx[ 5] = vtx02; vtx[ 6] = vtx12; vtx[ 7] = vtx11;
- vtx[ 8] = vtx10; vtx[ 9] = vtx11; vtx[10] = vtx21; vtx[11] = vtx20;
- vtx[12] = vtx11; vtx[13] = vtx12; vtx[14] = vtx22; vtx[15] = vtx21;
- }
-
-
- /* Calculate the bounds of the subgrid */
- __forceinline const BBox3fa bounds(const Scene *const scene, const size_t itime=0) const
- {
- BBox3fa bounds = empty;
- FATAL("not implemented yet");
- return bounds;
- }
-
- /* Calculate the linear bounds of the primitive */
- __forceinline LBBox3fa linearBounds(const Scene* const scene, const size_t itime)
- {
- return LBBox3fa(bounds(scene,itime+0),bounds(scene,itime+1));
- }
-
- __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps)
- {
- LBBox3fa allBounds = empty;
- FATAL("not implemented yet");
- return allBounds;
- }
-
- __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range)
- {
- LBBox3fa allBounds = empty;
- FATAL("not implemented yet");
- return allBounds;
- }
-
-
- friend embree_ostream operator<<(embree_ostream cout, const SubGrid& sg) {
- return cout << "SubGrid " << " ( x " << sg.x() << ", y = " << sg.y() << ", geomID = " << sg.geomID() << ", primID = " << sg.primID() << " )";
- }
-
- __forceinline unsigned int geomID() const { return _geomID; }
- __forceinline unsigned int primID() const { return _primID; }
- __forceinline unsigned int x() const { return (unsigned int)_x & 0x7fff; }
- __forceinline unsigned int y() const { return (unsigned int)_y & 0x7fff; }
-
- private:
- unsigned short _x;
- unsigned short _y;
- unsigned int _geomID; // geometry ID of mesh
- unsigned int _primID; // primitive ID of primitive inside mesh
- };
-
- struct SubGridID {
- unsigned short x;
- unsigned short y;
- unsigned int primID;
-
- __forceinline SubGridID() {}
- __forceinline SubGridID(const unsigned int x, const unsigned int y, const unsigned int primID) :
- x(x), y(y), primID(primID) {}
- };
-
- /* QuantizedBaseNode as large subgrid leaf */
- template<int N>
- struct SubGridQBVHN
- {
- /* Virtual interface to query information about the quad type */
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- __forceinline size_t size() const
- {
- for (size_t i=0;i<N;i++)
- if (primID(i) == -1) return i;
- return N;
- }
-
- __forceinline void clear() {
- for (size_t i=0;i<N;i++)
- subgridIDs[i] = SubGridID(0,0,(unsigned int)-1);
- qnode.clear();
- }
-
- /* Default constructor */
- __forceinline SubGridQBVHN() { }
-
- /* Construction from vertices and IDs */
- __forceinline SubGridQBVHN(const unsigned int x[N],
- const unsigned int y[N],
- const unsigned int primID[N],
- const BBox3fa * const subGridBounds,
- const unsigned int geomID,
- const unsigned int items)
- {
- clear();
- _geomID = geomID;
-
- __aligned(64) typename BVHN<N>::AABBNode node;
- node.clear();
- for (size_t i=0;i<items;i++)
- {
- subgridIDs[i] = SubGridID(x[i],y[i],primID[i]);
- node.setBounds(i,subGridBounds[i]);
- }
- qnode.init_dim(node);
- }
-
- __forceinline unsigned int geomID() const { return _geomID; }
- __forceinline unsigned int primID(const size_t i) const { assert(i < N); return subgridIDs[i].primID; }
- __forceinline unsigned int x(const size_t i) const { assert(i < N); return subgridIDs[i].x; }
- __forceinline unsigned int y(const size_t i) const { assert(i < N); return subgridIDs[i].y; }
-
- __forceinline SubGrid subgrid(const size_t i) const {
- assert(i < N);
- assert(primID(i) != -1);
- return SubGrid(x(i),y(i),geomID(),primID(i));
- }
-
- public:
- SubGridID subgridIDs[N];
-
- typename BVHN<N>::QuantizedBaseNode qnode;
-
- unsigned int _geomID; // geometry ID of mesh
-
-
- friend embree_ostream operator<<(embree_ostream cout, const SubGridQBVHN& sg) {
- cout << "SubGridQBVHN " << embree_endl;
- for (size_t i=0;i<N;i++)
- cout << i << " ( x = " << sg.subgridIDs[i].x << ", y = " << sg.subgridIDs[i].y << ", primID = " << sg.subgridIDs[i].primID << " )" << embree_endl;
- cout << "geomID " << sg._geomID << embree_endl;
- cout << "lowerX " << sg.qnode.dequantizeLowerX() << embree_endl;
- cout << "upperX " << sg.qnode.dequantizeUpperX() << embree_endl;
- cout << "lowerY " << sg.qnode.dequantizeLowerY() << embree_endl;
- cout << "upperY " << sg.qnode.dequantizeUpperY() << embree_endl;
- cout << "lowerZ " << sg.qnode.dequantizeLowerZ() << embree_endl;
- cout << "upperZ " << sg.qnode.dequantizeUpperZ() << embree_endl;
- return cout;
- }
-
- };
-
- template<int N>
- typename SubGridQBVHN<N>::Type SubGridQBVHN<N>::type;
-
- typedef SubGridQBVHN<4> SubGridQBVH4;
- typedef SubGridQBVHN<8> SubGridQBVH8;
-
-
- /* QuantizedBaseNode as large subgrid leaf */
- template<int N>
- struct SubGridMBQBVHN
- {
- /* Virtual interface to query information about the quad type */
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- __forceinline size_t size() const
- {
- for (size_t i=0;i<N;i++)
- if (primID(i) == -1) return i;
- return N;
- }
-
- __forceinline void clear() {
- for (size_t i=0;i<N;i++)
- subgridIDs[i] = SubGridID(0,0,(unsigned int)-1);
- qnode.clear();
- }
-
- /* Default constructor */
- __forceinline SubGridMBQBVHN() { }
-
- /* Construction from vertices and IDs */
- __forceinline SubGridMBQBVHN(const unsigned int x[N],
- const unsigned int y[N],
- const unsigned int primID[N],
- const BBox3fa * const subGridBounds0,
- const BBox3fa * const subGridBounds1,
- const unsigned int geomID,
- const float toffset,
- const float tscale,
- const unsigned int items)
- {
- clear();
- _geomID = geomID;
- time_offset = toffset;
- time_scale = tscale;
-
- __aligned(64) typename BVHN<N>::AABBNode node0,node1;
- node0.clear();
- node1.clear();
- for (size_t i=0;i<items;i++)
- {
- subgridIDs[i] = SubGridID(x[i],y[i],primID[i]);
- node0.setBounds(i,subGridBounds0[i]);
- node1.setBounds(i,subGridBounds1[i]);
- }
- qnode.node0.init_dim(node0);
- qnode.node1.init_dim(node1);
- }
-
- __forceinline unsigned int geomID() const { return _geomID; }
- __forceinline unsigned int primID(const size_t i) const { assert(i < N); return subgridIDs[i].primID; }
- __forceinline unsigned int x(const size_t i) const { assert(i < N); return subgridIDs[i].x; }
- __forceinline unsigned int y(const size_t i) const { assert(i < N); return subgridIDs[i].y; }
-
- __forceinline SubGrid subgrid(const size_t i) const {
- assert(i < N);
- assert(primID(i) != -1);
- return SubGrid(x(i),y(i),geomID(),primID(i));
- }
-
- __forceinline float adjustTime(const float t) const { return time_scale * (t-time_offset); }
-
- template<int K>
- __forceinline vfloat<K> adjustTime(const vfloat<K> &t) const { return time_scale * (t-time_offset); }
-
- public:
- SubGridID subgridIDs[N];
-
- typename BVHN<N>::QuantizedBaseNodeMB qnode;
-
- float time_offset;
- float time_scale;
- unsigned int _geomID; // geometry ID of mesh
-
-
- friend embree_ostream operator<<(embree_ostream cout, const SubGridMBQBVHN& sg) {
- cout << "SubGridMBQBVHN " << embree_endl;
- for (size_t i=0;i<N;i++)
- cout << i << " ( x = " << sg.subgridIDs[i].x << ", y = " << sg.subgridIDs[i].y << ", primID = " << sg.subgridIDs[i].primID << " )" << embree_endl;
- cout << "geomID " << sg._geomID << embree_endl;
- cout << "time_offset " << sg.time_offset << embree_endl;
- cout << "time_scale " << sg.time_scale << embree_endl;
- cout << "lowerX " << sg.qnode.node0.dequantizeLowerX() << embree_endl;
- cout << "upperX " << sg.qnode.node0.dequantizeUpperX() << embree_endl;
- cout << "lowerY " << sg.qnode.node0.dequantizeLowerY() << embree_endl;
- cout << "upperY " << sg.qnode.node0.dequantizeUpperY() << embree_endl;
- cout << "lowerZ " << sg.qnode.node0.dequantizeLowerZ() << embree_endl;
- cout << "upperZ " << sg.qnode.node0.dequantizeUpperZ() << embree_endl;
- cout << "lowerX " << sg.qnode.node1.dequantizeLowerX() << embree_endl;
- cout << "upperX " << sg.qnode.node1.dequantizeUpperX() << embree_endl;
- cout << "lowerY " << sg.qnode.node1.dequantizeLowerY() << embree_endl;
- cout << "upperY " << sg.qnode.node1.dequantizeUpperY() << embree_endl;
- cout << "lowerZ " << sg.qnode.node1.dequantizeLowerZ() << embree_endl;
- cout << "upperZ " << sg.qnode.node1.dequantizeUpperZ() << embree_endl;
- return cout;
- }
-
- };
-
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector.h
deleted file mode 100644
index 045eee4329..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector.h
+++ /dev/null
@@ -1,518 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "subgrid.h"
-#include "subgrid_intersector_moeller.h"
-#include "subgrid_intersector_pluecker.h"
-
-namespace embree
-{
- namespace isa
- {
-
- // =======================================================================================
- // =================================== SubGridIntersectors ===============================
- // =======================================================================================
-
-
- template<int N, bool filter>
- struct SubGridIntersector1Moeller
- {
- typedef SubGridQBVHN<N> Primitive;
- typedef SubGridQuadMIntersector1MoellerTrumbore<4,filter> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(normal.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
- pre.intersect(ray,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
- return pre.occluded(ray,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const SubGrid& subgrid)
- {
- STAT3(point_query.trav_prims,1,1,1);
- AccelSet* accel = (AccelSet*)context->scene->get(subgrid.geomID());
- assert(accel);
- context->geomID = subgrid.geomID();
- context->primID = subgrid.primID();
- return accel->pointQuery(query, context);
- }
-
- template<int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
-#if defined(__AVX__)
- STAT3(normal.trav_hit_boxes[popcnt(mask)],1,1,1);
-#endif
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
-
- if (unlikely(dist[ID] > ray.tfar)) continue;
- intersect(pre,ray,context,prim[i].subgrid(ID));
- }
- }
- }
- template<int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
-
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
-
- if (occluded(pre,ray,context,prim[i].subgrid(ID)))
- return true;
- }
- }
- return false;
- }
-
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t num, const TravPointQuery<N> &tquery, size_t& lazy_node)
- {
- bool changed = false;
- for (size_t i=0;i<num;i++)
- {
- vfloat<N> dist;
- size_t mask;
- if (likely(context->query_type == POINT_QUERY_TYPE_SPHERE)) {
- mask = BVHNQuantizedBaseNodePointQuerySphere1<N>::pointQuery(&prim[i].qnode,tquery,dist);
- } else {
- mask = BVHNQuantizedBaseNodePointQueryAABB1<N>::pointQuery(&prim[i].qnode,tquery,dist);
- }
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
- changed |= pointQuery(query, context, prim[i].subgrid(ID));
- }
- }
- return changed;
- }
- };
-
- template<int N, bool filter>
- struct SubGridIntersector1Pluecker
- {
- typedef SubGridQBVHN<N> Primitive;
- typedef SubGridQuadMIntersector1Pluecker<4,filter> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(normal.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
- pre.intersect(ray,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
- return pre.occluded(ray,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const SubGrid& subgrid)
- {
- STAT3(point_query.trav_prims,1,1,1);
- AccelSet* accel = (AccelSet*)context->scene->get(subgrid.geomID());
- context->geomID = subgrid.geomID();
- context->primID = subgrid.primID();
- return accel->pointQuery(query, context);
- }
-
- template<int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
-#if defined(__AVX__)
- STAT3(normal.trav_hit_boxes[popcnt(mask)],1,1,1);
-#endif
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
-
- if (unlikely(dist[ID] > ray.tfar)) continue;
- intersect(pre,ray,context,prim[i].subgrid(ID));
- }
- }
- }
-
- template<int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
-
- if (occluded(pre,ray,context,prim[i].subgrid(ID)))
- return true;
- }
- }
- return false;
- }
-
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t num, const TravPointQuery<N> &tquery, size_t& lazy_node)
- {
- bool changed = false;
- for (size_t i=0;i<num;i++)
- {
- vfloat<N> dist;
- size_t mask;
- if (likely(context->query_type == POINT_QUERY_TYPE_SPHERE)) {
- mask = BVHNQuantizedBaseNodePointQuerySphere1<N>::pointQuery(&prim[i].qnode,tquery,dist);
- } else {
- mask = BVHNQuantizedBaseNodePointQueryAABB1<N>::pointQuery(&prim[i].qnode,tquery,dist);
- }
-#if defined(__AVX__)
- STAT3(point_query.trav_hit_boxes[popcnt(mask)],1,1,1);
-#endif
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
- changed |= pointQuery(query, context, prim[i].subgrid(ID));
- }
- }
- return changed;
- }
- };
-
- template<int N, int K, bool filter>
- struct SubGridIntersectorKMoeller
- {
- typedef SubGridQBVHN<N> Primitive;
- typedef SubGridQuadMIntersectorKMoellerTrumbore<4,K,filter> Precalculations;
-
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- Vec3fa vtx[16];
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- subgrid.gather(vtx,context->scene);
- for (unsigned int i=0; i<4; i++)
- {
- const Vec3vf<K> p0 = vtx[i*4+0];
- const Vec3vf<K> p1 = vtx[i*4+1];
- const Vec3vf<K> p2 = vtx[i*4+2];
- const Vec3vf<K> p3 = vtx[i*4+3];
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- pre.intersectK(valid_i,ray,p0,p1,p2,p3,g,subgrid,i,IntersectKEpilogM<4,K,filter>(ray,context,subgrid.geomID(),subgrid.primID(),i));
- }
- }
-
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- vbool<K> valid0 = valid_i;
- Vec3fa vtx[16];
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- subgrid.gather(vtx,context->scene);
- for (unsigned int i=0; i<4; i++)
- {
- const Vec3vf<K> p0 = vtx[i*4+0];
- const Vec3vf<K> p1 = vtx[i*4+1];
- const Vec3vf<K> p2 = vtx[i*4+2];
- const Vec3vf<K> p3 = vtx[i*4+3];
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- if (pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)))
- break;
- }
- return !valid0;
- }
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(normal.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
- pre.intersect1(ray,k,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
- Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
- return pre.occluded1(ray,k,context,v0,v1,v2,v3,g,subgrid);
- }
-
- template<bool robust>
- static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
- for (size_t j=0;j<num;j++)
- {
- size_t m_valid = movemask(prim[j].qnode.validMask());
- vfloat<K> dist;
- while(m_valid)
- {
- const size_t i = bscf(m_valid);
- if (none(valid & isecK.intersectK(&prim[j].qnode,i,tray,dist))) continue;
- intersect(valid,pre,ray,context,prim[j].subgrid(i));
- }
- }
- }
-
- template<bool robust>
- static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
- vbool<K> valid0 = valid;
- for (size_t j=0;j<num;j++)
- {
- size_t m_valid = movemask(prim[j].qnode.validMask());
- vfloat<K> dist;
- while(m_valid)
- {
- const size_t i = bscf(m_valid);
- if (none(valid0 & isecK.intersectK(&prim[j].qnode,i,tray,dist))) continue;
- valid0 &= !occluded(valid0,pre,ray,context,prim[j].subgrid(i));
- if (none(valid0)) break;
- }
- }
- return !valid0;
- }
-
- template<int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
-
- if (unlikely(dist[ID] > ray.tfar[k])) continue;
- intersect(pre,ray,k,context,prim[i].subgrid(ID));
- }
- }
- }
-
- template<int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
-
- if (occluded(pre,ray,k,context,prim[i].subgrid(ID)))
- return true;
- }
- }
- return false;
- }
- };
-
-
- template<int N, int K, bool filter>
- struct SubGridIntersectorKPluecker
- {
- typedef SubGridQBVHN<N> Primitive;
- typedef SubGridQuadMIntersectorKPluecker<4,K,filter> Precalculations;
-
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- Vec3fa vtx[16];
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- subgrid.gather(vtx,context->scene);
- for (unsigned int i=0; i<4; i++)
- {
- const Vec3vf<K> p0 = vtx[i*4+0];
- const Vec3vf<K> p1 = vtx[i*4+1];
- const Vec3vf<K> p2 = vtx[i*4+2];
- const Vec3vf<K> p3 = vtx[i*4+3];
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- pre.intersectK(valid_i,ray,p0,p1,p2,p3,g,subgrid,i,IntersectKEpilogM<4,K,filter>(ray,context,subgrid.geomID(),subgrid.primID(),i));
- }
- }
-
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- vbool<K> valid0 = valid_i;
- Vec3fa vtx[16];
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- subgrid.gather(vtx,context->scene);
- for (unsigned int i=0; i<4; i++)
- {
- const Vec3vf<K> p0 = vtx[i*4+0];
- const Vec3vf<K> p1 = vtx[i*4+1];
- const Vec3vf<K> p2 = vtx[i*4+2];
- const Vec3vf<K> p3 = vtx[i*4+3];
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- if (pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)))
- break;
- }
- return !valid0;
- }
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(normal.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
- pre.intersect1(ray,k,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
- Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
- return pre.occluded1(ray,k,context,v0,v1,v2,v3,g,subgrid);
- }
-
- template<bool robust>
- static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
- for (size_t j=0;j<num;j++)
- {
- size_t m_valid = movemask(prim[j].qnode.validMask());
- vfloat<K> dist;
- while(m_valid)
- {
- const size_t i = bscf(m_valid);
- if (none(valid & isecK.intersectK(&prim[j].qnode,i,tray,dist))) continue;
- intersect(valid,pre,ray,context,prim[j].subgrid(i));
- }
- }
- }
-
- template<bool robust>
- static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
- vbool<K> valid0 = valid;
- for (size_t j=0;j<num;j++)
- {
- size_t m_valid = movemask(prim[j].qnode.validMask());
- vfloat<K> dist;
- while(m_valid)
- {
- const size_t i = bscf(m_valid);
- if (none(valid0 & isecK.intersectK(&prim[j].qnode,i,tray,dist))) continue;
- valid0 &= !occluded(valid0,pre,ray,context,prim[j].subgrid(i));
- if (none(valid0)) break;
- }
- }
- return !valid0;
- }
-
- template<int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
-
- if (unlikely(dist[ID] > ray.tfar[k])) continue;
- intersect(pre,ray,k,context,prim[i].subgrid(ID));
- }
- }
- }
-
- template<int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
-
- if (occluded(pre,ray,k,context,prim[i].subgrid(ID)))
- return true;
- }
- }
- return false;
- }
- };
-
-
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector_moeller.h b/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector_moeller.h
deleted file mode 100644
index f65b4abf61..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector_moeller.h
+++ /dev/null
@@ -1,493 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "subgrid.h"
-#include "quad_intersector_moeller.h"
-
-namespace embree
-{
- namespace isa
- {
-
- /* ----------------------------- */
- /* -- single ray intersectors -- */
- /* ----------------------------- */
-
- template<int M>
- __forceinline void interpolateUV(MoellerTrumboreHitM<M> &hit,const GridMesh::Grid &g, const SubGrid& subgrid)
- {
- /* correct U,V interpolation across the entire grid */
- const vint<M> sx((int)subgrid.x());
- const vint<M> sy((int)subgrid.y());
- const vint<M> sxM(sx + vint<M>(0,1,1,0));
- const vint<M> syM(sy + vint<M>(0,0,1,1));
- const float inv_resX = rcp((float)((int)g.resX-1));
- const float inv_resY = rcp((float)((int)g.resY-1));
- hit.U = (hit.U + (vfloat<M>)sxM * hit.absDen) * inv_resX;
- hit.V = (hit.V + (vfloat<M>)syM * hit.absDen) * inv_resY;
- }
-
- template<int M, bool filter>
- struct SubGridQuadMIntersector1MoellerTrumbore;
-
- template<int M, bool filter>
- struct SubGridQuadMIntersector1MoellerTrumbore
- {
- __forceinline SubGridQuadMIntersector1MoellerTrumbore() {}
-
- __forceinline SubGridQuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
-
- __forceinline void intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const GridMesh::Grid &g, const SubGrid& subgrid) const
- {
- MoellerTrumboreHitM<M> hit;
- MoellerTrumboreIntersector1<M> intersector(ray,nullptr);
- Intersect1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
-
- /* intersect first triangle */
- if (intersector.intersect(ray,v0,v1,v3,hit))
- {
- interpolateUV<M>(hit,g,subgrid);
- epilog(hit.valid,hit);
- }
-
- /* intersect second triangle */
- if (intersector.intersect(ray,v2,v3,v1,hit))
- {
- hit.U = hit.absDen - hit.U;
- hit.V = hit.absDen - hit.V;
- interpolateUV<M>(hit,g,subgrid);
- epilog(hit.valid,hit);
- }
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const GridMesh::Grid &g, const SubGrid& subgrid) const
- {
- MoellerTrumboreHitM<M> hit;
- MoellerTrumboreIntersector1<M> intersector(ray,nullptr);
- Occluded1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
-
- /* intersect first triangle */
- if (intersector.intersect(ray,v0,v1,v3,hit))
- {
- interpolateUV<M>(hit,g,subgrid);
- if (epilog(hit.valid,hit))
- return true;
- }
-
- /* intersect second triangle */
- if (intersector.intersect(ray,v2,v3,v1,hit))
- {
- hit.U = hit.absDen - hit.U;
- hit.V = hit.absDen - hit.V;
- interpolateUV<M>(hit,g,subgrid);
- if (epilog(hit.valid,hit))
- return true;
- }
- return false;
- }
- };
-
-#if defined (__AVX__)
-
- /*! Intersects 4 quads with 1 ray using AVX */
- template<bool filter>
- struct SubGridQuadMIntersector1MoellerTrumbore<4,filter>
- {
- __forceinline SubGridQuadMIntersector1MoellerTrumbore() {}
-
- __forceinline SubGridQuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
-
- template<typename Epilog>
- __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid& subgrid, const Epilog& epilog) const
- {
- const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
- const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
-#else
- const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
- const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
-#endif
- MoellerTrumboreHitM<8> hit;
- MoellerTrumboreIntersector1<8> intersector(ray,nullptr);
- const vbool8 flags(0,0,0,0,1,1,1,1);
- if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,hit)))
- {
- vfloat8 U = hit.U, V = hit.V, absDen = hit.absDen;
-
-#if !defined(EMBREE_BACKFACE_CULLING)
- hit.U = select(flags,absDen-V,U);
- hit.V = select(flags,absDen-U,V);
- hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));
-#else
- hit.U = select(flags,absDen-U,U);
- hit.V = select(flags,absDen-V,V);
-#endif
- /* correct U,V interpolation across the entire grid */
- const vint8 sx((int)subgrid.x());
- const vint8 sy((int)subgrid.y());
- const vint8 sx8(sx + vint8(0,1,1,0,0,1,1,0));
- const vint8 sy8(sy + vint8(0,0,1,1,0,0,1,1));
- const float inv_resX = rcp((float)((int)g.resX-1));
- const float inv_resY = rcp((float)((int)g.resY-1));
- hit.U = (hit.U + (vfloat8)sx8 * absDen) * inv_resX;
- hit.V = (hit.V + (vfloat8)sy8 * absDen) * inv_resY;
-
- if (unlikely(epilog(hit.valid,hit)))
- return true;
- }
- return false;
- }
-
- __forceinline bool intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const GridMesh::Grid &g, const SubGrid& subgrid) const
- {
- return intersect(ray,v0,v1,v2,v3,g,subgrid,Intersect1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const GridMesh::Grid &g, const SubGrid& subgrid) const
- {
- return intersect(ray,v0,v1,v2,v3,g,subgrid,Occluded1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
- }
- };
-
-#endif
-
- // ============================================================================================================================
- // ============================================================================================================================
- // ============================================================================================================================
-
-
- /* ----------------------------- */
- /* -- ray packet intersectors -- */
- /* ----------------------------- */
-
- template<int K>
- struct SubGridQuadHitK
- {
- __forceinline SubGridQuadHitK(const vfloat<K>& U,
- const vfloat<K>& V,
- const vfloat<K>& T,
- const vfloat<K>& absDen,
- const Vec3vf<K>& Ng,
- const vbool<K>& flags,
- const GridMesh::Grid &g,
- const SubGrid& subgrid,
- const unsigned int i)
- : U(U), V(V), T(T), absDen(absDen), flags(flags), tri_Ng(Ng), g(g), subgrid(subgrid), i(i) {}
-
- __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
- {
- const vfloat<K> rcpAbsDen = rcp(absDen);
- const vfloat<K> t = T * rcpAbsDen;
- const vfloat<K> u0 = min(U * rcpAbsDen,1.0f);
- const vfloat<K> v0 = min(V * rcpAbsDen,1.0f);
- const vfloat<K> u1 = vfloat<K>(1.0f) - u0;
- const vfloat<K> v1 = vfloat<K>(1.0f) - v0;
- const vfloat<K> uu = select(flags,u1,u0);
- const vfloat<K> vv = select(flags,v1,v0);
- const unsigned int sx = subgrid.x() + (unsigned int)(i % 2);
- const unsigned int sy = subgrid.y() + (unsigned int)(i >>1);
- const float inv_resX = rcp((float)(int)(g.resX-1));
- const float inv_resY = rcp((float)(int)(g.resY-1));
- const vfloat<K> u = (uu + (float)(int)sx) * inv_resX;
- const vfloat<K> v = (vv + (float)(int)sy) * inv_resY;
- const Vec3vf<K> Ng(tri_Ng.x,tri_Ng.y,tri_Ng.z);
- return std::make_tuple(u,v,t,Ng);
- }
-
- private:
- const vfloat<K> U;
- const vfloat<K> V;
- const vfloat<K> T;
- const vfloat<K> absDen;
- const vbool<K> flags;
- const Vec3vf<K> tri_Ng;
-
- const GridMesh::Grid &g;
- const SubGrid& subgrid;
- const size_t i;
- };
-
- template<int M, int K, bool filter>
- struct SubGridQuadMIntersectorKMoellerTrumboreBase
- {
- __forceinline SubGridQuadMIntersectorKMoellerTrumboreBase(const vbool<K>& valid, const RayK<K>& ray) {}
-
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_e1,
- const Vec3vf<K>& tri_e2,
- const Vec3vf<K>& tri_Ng,
- const vbool<K>& flags,
- const GridMesh::Grid &g,
- const SubGrid &subgrid,
- const unsigned int i,
- const Epilog& epilog) const
- {
- /* calculate denominator */
- vbool<K> valid = valid0;
- const Vec3vf<K> C = tri_v0 - ray.org;
- const Vec3vf<K> R = cross(C,ray.dir);
- const vfloat<K> den = dot(tri_Ng,ray.dir);
- const vfloat<K> absDen = abs(den);
- const vfloat<K> sgnDen = signmsk(den);
-
- /* test against edge p2 p0 */
- const vfloat<K> U = dot(R,tri_e2) ^ sgnDen;
- valid &= U >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* test against edge p0 p1 */
- const vfloat<K> V = dot(R,tri_e1) ^ sgnDen;
- valid &= V >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* test against edge p1 p2 */
- const vfloat<K> W = absDen-U-V;
- valid &= W >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen;
- valid &= (absDen*ray.tnear() < T) & (T <= absDen*ray.tfar);
- if (unlikely(none(valid))) return false;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- valid &= den < vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-#else
- valid &= den != vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-#endif
-
- /* calculate hit information */
- SubGridQuadHitK<K> hit(U,V,T,absDen,tri_Ng,flags,g,subgrid,i);
- return epilog(valid,hit);
- }
-
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_v1,
- const Vec3vf<K>& tri_v2,
- const vbool<K>& flags,
- const GridMesh::Grid &g,
- const SubGrid &subgrid,
- const unsigned int i,
- const Epilog& epilog) const
- {
- const Vec3vf<K> e1 = tri_v0-tri_v1;
- const Vec3vf<K> e2 = tri_v2-tri_v0;
- const Vec3vf<K> Ng = cross(e2,e1);
- return intersectK(valid0,ray,tri_v0,e1,e2,Ng,flags,g,subgrid,i,epilog);
- }
-
- template<typename Epilog>
- __forceinline bool intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& v0,
- const Vec3vf<K>& v1,
- const Vec3vf<K>& v2,
- const Vec3vf<K>& v3,
- const GridMesh::Grid &g,
- const SubGrid &subgrid,
- const unsigned int i,
- const Epilog& epilog) const
- {
- intersectK(valid0,ray,v0,v1,v3,vbool<K>(false),g,subgrid,i,epilog);
- if (none(valid0)) return true;
- intersectK(valid0,ray,v2,v3,v1,vbool<K>(true ),g,subgrid,i,epilog);
- return none(valid0);
- }
-
- static __forceinline bool intersect1(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- const Vec3vf<M>& tri_Ng,
- MoellerTrumboreHitM<M> &hit)
- {
- /* calculate denominator */
- const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
- const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
- const Vec3vf<M> C = Vec3vf<M>(tri_v0) - O;
- const Vec3vf<M> R = cross(C,D);
- const vfloat<M> den = dot(Vec3vf<M>(tri_Ng),D);
- const vfloat<M> absDen = abs(den);
- const vfloat<M> sgnDen = signmsk(den);
-
- /* perform edge tests */
- const vfloat<M> U = dot(R,Vec3vf<M>(tri_e2)) ^ sgnDen;
- const vfloat<M> V = dot(R,Vec3vf<M>(tri_e1)) ^ sgnDen;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#else
- vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#endif
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
- valid &= (absDen*vfloat<M>(ray.tnear()[k]) < T) & (T <= absDen*vfloat<M>(ray.tfar[k]));
- if (likely(none(valid))) return false;
-
- /* calculate hit information */
- new (&hit) MoellerTrumboreHitM<M>(valid,U,V,T,absDen,tri_Ng);
- return true;
- }
-
- static __forceinline bool intersect1(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- MoellerTrumboreHitM<M> &hit)
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- const Vec3vf<M> Ng = cross(e2,e1);
- return intersect1(ray,k,v0,e1,e2,Ng,hit);
- }
-
- };
-
- template<int M, int K, bool filter>
- struct SubGridQuadMIntersectorKMoellerTrumbore : public SubGridQuadMIntersectorKMoellerTrumboreBase<M,K,filter>
- {
- __forceinline SubGridQuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
- : SubGridQuadMIntersectorKMoellerTrumboreBase<M,K,filter>(valid,ray) {}
-
- __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
- {
- Intersect1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
-
- MoellerTrumboreHitM<4> hit;
- if (SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>::intersect1(ray,k,v0,v1,v3,hit))
- {
- interpolateUV<M>(hit,g,subgrid);
- epilog(hit.valid,hit);
- }
-
- if (SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>::intersect1(ray,k,v2,v3,v1,hit))
- {
- hit.U = hit.absDen - hit.U;
- hit.V = hit.absDen - hit.V;
- interpolateUV<M>(hit,g,subgrid);
- epilog(hit.valid,hit);
- }
-
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
- {
- Occluded1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
-
- MoellerTrumboreHitM<4> hit;
- if (SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>::intersect1(ray,k,v0,v1,v3,hit))
- {
- interpolateUV<M>(hit,g,subgrid);
- if (epilog(hit.valid,hit)) return true;
- }
-
- if (SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>::intersect1(ray,k,v2,v3,v1,hit))
- {
- hit.U = hit.absDen - hit.U;
- hit.V = hit.absDen - hit.V;
- interpolateUV<M>(hit,g,subgrid);
- if (epilog(hit.valid,hit)) return true;
- }
- return false;
- }
- };
-
-
-#if defined (__AVX__)
-
- /*! Intersects 4 quads with 1 ray using AVX */
- template<int K, bool filter>
- struct SubGridQuadMIntersectorKMoellerTrumbore<4,K,filter> : public SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>
- {
- __forceinline SubGridQuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
- : SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>(valid,ray) {}
-
- template<typename Epilog>
- __forceinline bool intersect1(RayK<K>& ray, size_t k,const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const GridMesh::Grid &g, const SubGrid &subgrid, const Epilog& epilog) const
- {
- const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
- const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
-#else
- const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
- const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
-#endif
- const vbool8 flags(0,0,0,0,1,1,1,1);
-
- MoellerTrumboreHitM<8> hit;
- if (SubGridQuadMIntersectorKMoellerTrumboreBase<8,K,filter>::intersect1(ray,k,vtx0,vtx1,vtx2,hit))
- {
- vfloat8 U = hit.U, V = hit.V, absDen = hit.absDen;
-#if !defined(EMBREE_BACKFACE_CULLING)
- hit.U = select(flags,absDen-V,U);
- hit.V = select(flags,absDen-U,V);
- hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));
-#else
- hit.U = select(flags,absDen-U,U);
- hit.V = select(flags,absDen-V,V);
-#endif
-
- /* correct U,V interpolation across the entire grid */
- const vint8 sx((int)subgrid.x());
- const vint8 sy((int)subgrid.y());
- const vint8 sx8(sx + vint8(0,1,1,0,0,1,1,0));
- const vint8 sy8(sy + vint8(0,0,1,1,0,0,1,1));
- const float inv_resX = rcp((float)((int)g.resX-1));
- const float inv_resY = rcp((float)((int)g.resY-1));
- hit.U = (hit.U + (vfloat8)sx8 * absDen) * inv_resX;
- hit.V = (hit.V + (vfloat8)sy8 * absDen) * inv_resY;
- if (unlikely(epilog(hit.valid,hit)))
- return true;
-
- }
- return false;
- }
-
- __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Intersect1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID()));
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
- {
- return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Occluded1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID()));
- }
- };
-
-#endif
-
-
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector_pluecker.h b/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector_pluecker.h
deleted file mode 100644
index 1cd88aa799..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/subgrid_intersector_pluecker.h
+++ /dev/null
@@ -1,508 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "subgrid.h"
-#include "quad_intersector_moeller.h"
-#include "quad_intersector_pluecker.h"
-
-namespace embree
-{
- namespace isa
- {
-
- template<int M>
- struct SubGridQuadHitPlueckerM
- {
- __forceinline SubGridQuadHitPlueckerM() {}
-
- __forceinline SubGridQuadHitPlueckerM(const vbool<M>& valid,
- const vfloat<M>& U,
- const vfloat<M>& V,
- const vfloat<M>& UVW,
- const vfloat<M>& t,
- const Vec3vf<M>& Ng,
- const vbool<M>& flags) : valid(valid), vt(t)
- {
- const vbool<M> invalid = abs(UVW) < min_rcp_input;
- const vfloat<M> rcpUVW = select(invalid,vfloat<M>(0.0f),rcp(UVW));
- const vfloat<M> u = min(U * rcpUVW,1.0f);
- const vfloat<M> v = min(V * rcpUVW,1.0f);
- const vfloat<M> u1 = vfloat<M>(1.0f) - u;
- const vfloat<M> v1 = vfloat<M>(1.0f) - v;
-#if !defined(__AVX__) || defined(EMBREE_BACKFACE_CULLING)
- vu = select(flags,u1,u);
- vv = select(flags,v1,v);
- vNg = Vec3vf<M>(Ng.x,Ng.y,Ng.z);
-#else
- const vfloat<M> flip = select(flags,vfloat<M>(-1.0f),vfloat<M>(1.0f));
- vv = select(flags,u1,v);
- vu = select(flags,v1,u);
- vNg = Vec3vf<M>(flip*Ng.x,flip*Ng.y,flip*Ng.z);
-#endif
- }
-
- __forceinline void finalize()
- {
- }
-
- __forceinline Vec2f uv(const size_t i)
- {
- const float u = vu[i];
- const float v = vv[i];
- return Vec2f(u,v);
- }
-
- __forceinline float t(const size_t i) { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- public:
- vbool<M> valid;
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- template<int M>
- __forceinline void interpolateUV(SubGridQuadHitPlueckerM<M> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const vint<M> &stepX, const vint<M> &stepY)
- {
- /* correct U,V interpolation across the entire grid */
- const vint<M> sx((int)subgrid.x());
- const vint<M> sy((int)subgrid.y());
- const vint<M> sxM(sx + stepX);
- const vint<M> syM(sy + stepY);
- const float inv_resX = rcp((float)((int)g.resX-1));
- const float inv_resY = rcp((float)((int)g.resY-1));
- hit.vu = (hit.vu + vfloat<M>(sxM)) * inv_resX;
- hit.vv = (hit.vv + vfloat<M>(syM)) * inv_resY;
- }
-
- template<int M>
- __forceinline static bool intersectPluecker(Ray& ray,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_v1,
- const Vec3vf<M>& tri_v2,
- const vbool<M>& flags,
- SubGridQuadHitPlueckerM<M> &hit)
- {
- /* calculate vertices relative to ray origin */
- const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org);
- const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir);
- const Vec3vf<M> v0 = tri_v0-O;
- const Vec3vf<M> v1 = tri_v1-O;
- const Vec3vf<M> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<M> e0 = v2-v0;
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<M> U = dot(cross(e0,v2+v0),D);
- const vfloat<M> V = dot(cross(e1,v0+v1),D);
- const vfloat<M> W = dot(cross(e2,v1+v2),D);
- const vfloat<M> UVW = U+V+W;
- const vfloat<M> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = max(U,V,W) <= eps;
-#else
- vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<M> den = twice(dot(Ng,D));
-
- /* perform depth test */
- const vfloat<M> T = twice(dot(v0,Ng));
- const vfloat<M> t = rcp(den)*T;
- valid &= vfloat<M>(ray.tnear()) <= t & t <= vfloat<M>(ray.tfar);
- valid &= den != vfloat<M>(zero);
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- new (&hit) SubGridQuadHitPlueckerM<M>(valid,U,V,UVW,t,Ng,flags);
- return true;
- }
-
- template<int M, bool filter>
- struct SubGridQuadMIntersector1Pluecker;
-
- template<int M, bool filter>
- struct SubGridQuadMIntersector1Pluecker
- {
- __forceinline SubGridQuadMIntersector1Pluecker() {}
-
- __forceinline SubGridQuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
-
- __forceinline void intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const GridMesh::Grid &g, const SubGrid& subgrid) const
- {
- SubGridQuadHitPlueckerM<M> hit;
- Intersect1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
-
- /* intersect first triangle */
- if (intersectPluecker(ray,v0,v1,v3,vbool<M>(false),hit))
- {
- interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
- epilog(hit.valid,hit);
- }
-
- /* intersect second triangle */
- if (intersectPluecker(ray,v2,v3,v1,vbool<M>(true),hit))
- {
- interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
- epilog(hit.valid,hit);
- }
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
- const GridMesh::Grid &g, const SubGrid& subgrid) const
- {
- SubGridQuadHitPlueckerM<M> hit;
- Occluded1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
-
- /* intersect first triangle */
- if (intersectPluecker(ray,v0,v1,v3,vbool<M>(false),hit))
- {
- interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
- if (epilog(hit.valid,hit))
- return true;
- }
-
- /* intersect second triangle */
- if (intersectPluecker(ray,v2,v3,v1,vbool<M>(true),hit))
- {
- interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
- if (epilog(hit.valid,hit))
- return true;
- }
-
- return false;
- }
- };
-
-#if defined (__AVX__)
-
- /*! Intersects 4 quads with 1 ray using AVX */
- template<bool filter>
- struct SubGridQuadMIntersector1Pluecker<4,filter>
- {
- __forceinline SubGridQuadMIntersector1Pluecker() {}
-
- __forceinline SubGridQuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
-
- template<typename Epilog>
- __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid& subgrid, const Epilog& epilog) const
- {
- const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
-#if !defined(EMBREE_BACKFACE_CULLING)
- const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
- const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
-#else
- const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
- const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
-#endif
- SubGridQuadHitPlueckerM<8> hit;
- const vbool8 flags(0,0,0,0,1,1,1,1);
- if (unlikely(intersectPluecker(ray,vtx0,vtx1,vtx2,flags,hit)))
- {
- /* correct U,V interpolation across the entire grid */
- interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1));
- if (unlikely(epilog(hit.valid,hit)))
- return true;
- }
- return false;
- }
-
- __forceinline bool intersect(RayHit& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const GridMesh::Grid &g, const SubGrid& subgrid) const
- {
- return intersect(ray,v0,v1,v2,v3,g,subgrid,Intersect1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
- }
-
- __forceinline bool occluded(Ray& ray, IntersectContext* context,
- const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
- const GridMesh::Grid &g, const SubGrid& subgrid) const
- {
- return intersect(ray,v0,v1,v2,v3,g,subgrid,Occluded1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
- }
- };
-
-#endif
-
-
- /* ----------------------------- */
- /* -- ray packet intersectors -- */
- /* ----------------------------- */
-
- template<int K>
- struct SubGridQuadHitPlueckerK
- {
- __forceinline SubGridQuadHitPlueckerK(const vfloat<K>& U,
- const vfloat<K>& V,
- const vfloat<K>& UVW,
- const vfloat<K>& t,
- const Vec3vf<K>& Ng,
- const vbool<K>& flags,
- const GridMesh::Grid &g,
- const SubGrid& subgrid,
- const unsigned int i)
- : U(U), V(V), UVW(UVW), t(t), flags(flags), tri_Ng(Ng), g(g), subgrid(subgrid), i(i) {}
-
- __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
- {
- const vbool<K> invalid = abs(UVW) < min_rcp_input;
- const vfloat<K> rcpUVW = select(invalid,vfloat<K>(0.0f),rcp(UVW));
- const vfloat<K> u0 = min(U * rcpUVW,1.0f);
- const vfloat<K> v0 = min(V * rcpUVW,1.0f);
- const vfloat<K> u1 = vfloat<K>(1.0f) - u0;
- const vfloat<K> v1 = vfloat<K>(1.0f) - v0;
- const vfloat<K> uu = select(flags,u1,u0);
- const vfloat<K> vv = select(flags,v1,v0);
- const unsigned int sx = subgrid.x() + (unsigned int)(i % 2);
- const unsigned int sy = subgrid.y() + (unsigned int)(i >>1);
- const float inv_resX = rcp((float)(int)(g.resX-1));
- const float inv_resY = rcp((float)(int)(g.resY-1));
- const vfloat<K> u = (uu + (float)(int)sx) * inv_resX;
- const vfloat<K> v = (vv + (float)(int)sy) * inv_resY;
- const Vec3vf<K> Ng(tri_Ng.x,tri_Ng.y,tri_Ng.z);
- return std::make_tuple(u,v,t,Ng);
- }
-
- private:
- const vfloat<K> U;
- const vfloat<K> V;
- const vfloat<K> UVW;
- const vfloat<K> t;
- const vfloat<K> absDen;
- const vbool<K> flags;
- const Vec3vf<K> tri_Ng;
-
- const GridMesh::Grid &g;
- const SubGrid& subgrid;
- const size_t i;
- };
-
-
- template<int M, int K, bool filter>
- struct SubGridQuadMIntersectorKPlueckerBase
- {
- __forceinline SubGridQuadMIntersectorKPlueckerBase(const vbool<K>& valid, const RayK<K>& ray) {}
-
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_v1,
- const Vec3vf<K>& tri_v2,
- const Vec3vf<K>& tri_Ng,
- const vbool<K>& flags,
- const GridMesh::Grid &g,
- const SubGrid &subgrid,
- const unsigned int i,
- const Epilog& epilog) const
- {
- /* calculate denominator */
- /* calculate vertices relative to ray origin */
- vbool<K> valid = valid0;
- const Vec3vf<K> O = ray.org;
- const Vec3vf<K> D = ray.dir;
- const Vec3vf<K> v0 = tri_v0-O;
- const Vec3vf<K> v1 = tri_v1-O;
- const Vec3vf<K> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<K> e0 = v2-v0;
- const Vec3vf<K> e1 = v0-v1;
- const Vec3vf<K> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<K> U = dot(Vec3vf<K>(cross(e0,v2+v0)),D);
- const vfloat<K> V = dot(Vec3vf<K>(cross(e1,v0+v1)),D);
- const vfloat<K> W = dot(Vec3vf<K>(cross(e2,v1+v2)),D);
- const vfloat<K> UVW = U+V+W;
- const vfloat<K> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- valid &= max(U,V,W) <= eps;
-#else
- valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<K> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<K> den = twice(dot(Vec3vf<K>(Ng),D));
-
- /* perform depth test */
- const vfloat<K> T = twice(dot(v0,Vec3vf<K>(Ng)));
- const vfloat<K> t = rcp(den)*T;
- valid &= ray.tnear() <= t & t <= ray.tfar;
- valid &= den != vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-
- /* calculate hit information */
- SubGridQuadHitPlueckerK<K> hit(U,V,UVW,t,tri_Ng,flags,g,subgrid,i);
- return epilog(valid,hit);
- }
-
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& v0,
- const Vec3vf<K>& v1,
- const Vec3vf<K>& v2,
- const vbool<K>& flags,
- const GridMesh::Grid &g,
- const SubGrid &subgrid,
- const unsigned int i,
- const Epilog& epilog) const
- {
- const Vec3vf<K> e1 = v0-v1;
- const Vec3vf<K> e2 = v2-v0;
- const Vec3vf<K> Ng = cross(e2,e1);
- return intersectK(valid0,ray,v0,v1,v2,Ng,flags,g,subgrid,i,epilog);
- }
-
- template<typename Epilog>
- __forceinline bool intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& v0,
- const Vec3vf<K>& v1,
- const Vec3vf<K>& v2,
- const Vec3vf<K>& v3,
- const GridMesh::Grid &g,
- const SubGrid &subgrid,
- const unsigned int i,
- const Epilog& epilog) const
- {
- intersectK(valid0,ray,v0,v1,v3,vbool<K>(false),g,subgrid,i,epilog);
- if (none(valid0)) return true;
- intersectK(valid0,ray,v2,v3,v1,vbool<K>(true ),g,subgrid,i,epilog);
- return none(valid0);
- }
-
- static __forceinline bool intersect1(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_v1,
- const Vec3vf<M>& tri_v2,
- const Vec3vf<M>& tri_Ng,
- const vbool<M>& flags,
- SubGridQuadHitPlueckerM<M> &hit)
- {
- /* calculate vertices relative to ray origin */
- const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
- const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
- const Vec3vf<M> v0 = tri_v0-O;
- const Vec3vf<M> v1 = tri_v1-O;
- const Vec3vf<M> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<M> e0 = v2-v0;
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<M> U = dot(cross(e0,v2+v0),D);
- const vfloat<M> V = dot(cross(e1,v0+v1),D);
- const vfloat<M> W = dot(cross(e2,v1+v2),D);
- const vfloat<M> UVW = U+V+W;
- const vfloat<M> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = max(U,V,W) <= eps ;
-#else
- vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<M> den = twice(dot(Ng,D));
-
- /* perform depth test */
- const vfloat<M> T = twice(dot(v0,Ng));
- const vfloat<M> t = rcp(den)*T;
- valid &= vfloat<M>(ray.tnear()[k]) <= t & t <= vfloat<M>(ray.tfar[k]);
- if (unlikely(none(valid))) return false;
-
- /* avoid division by 0 */
- valid &= den != vfloat<M>(zero);
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- new (&hit) SubGridQuadHitPlueckerM<M>(valid,U,V,UVW,t,tri_Ng,flags);
- return true;
- }
-
- static __forceinline bool intersect1(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const vbool<M>& flags,
- SubGridQuadHitPlueckerM<M> &hit)
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- const Vec3vf<M> Ng = cross(e2,e1); // FIXME: optimize!!!
- return intersect1(ray,k,v0,v1,v2,Ng,flags,hit);
- }
-
- };
-
- template<int M, int K, bool filter>
- struct SubGridQuadMIntersectorKPluecker : public SubGridQuadMIntersectorKPlueckerBase<M,K,filter>
- {
- __forceinline SubGridQuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
- : SubGridQuadMIntersectorKPlueckerBase<M,K,filter>(valid,ray) {}
-
- __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
- {
- Intersect1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
-
- SubGridQuadHitPlueckerM<4> hit;
- if (SubGridQuadMIntersectorKPlueckerBase<4,K,filter>::intersect1(ray,k,v0,v1,v3,vboolf4(false),hit))
- {
- interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
- epilog(hit.valid,hit);
- }
-
- if (SubGridQuadMIntersectorKPlueckerBase<4,K,filter>::intersect1(ray,k,v2,v3,v1,vboolf4(true),hit))
- {
- interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
- epilog(hit.valid,hit);
- }
-
- }
-
- __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
- const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
- {
- Occluded1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
-
- SubGridQuadHitPlueckerM<4> hit;
- if (SubGridQuadMIntersectorKPlueckerBase<4,K,filter>::intersect1(ray,k,v0,v1,v3,vboolf4(false),hit))
- {
- interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
- if (epilog(hit.valid,hit)) return true;
- }
-
- if (SubGridQuadMIntersectorKPlueckerBase<4,K,filter>::intersect1(ray,k,v2,v3,v1,vboolf4(true),hit))
- {
- interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
- if (epilog(hit.valid,hit)) return true;
- }
- return false;
- }
- };
-
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/subgrid_mb_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/subgrid_mb_intersector.h
deleted file mode 100644
index 400a88b985..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/subgrid_mb_intersector.h
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "subgrid_intersector.h"
-
-namespace embree
-{
- namespace isa
- {
- template<int N, bool filter>
- struct SubGridMBIntersector1Pluecker
- {
- typedef SubGridMBQBVHN<N> Primitive;
- typedef SubGridQuadMIntersector1Pluecker<4,filter> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(normal.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- float ftime;
- const int itime = mesh->timeSegment(ray.time(), ftime);
- Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime,ftime);
- pre.intersect(ray,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- float ftime;
- const int itime = mesh->timeSegment(ray.time(), ftime);
-
- Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime,ftime);
- return pre.occluded(ray,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const SubGrid& subgrid)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, subgrid);
- }
-
- template<int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
- for (size_t i=0;i<num;i++)
- {
- vfloat<Nx> dist;
- const float time = prim[i].adjustTime(ray.time());
-
- assert(time <= 1.0f);
- size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist);
-#if defined(__AVX__)
- STAT3(normal.trav_hit_boxes[popcnt(mask)],1,1,1);
-#endif
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- if (unlikely(dist[ID] > ray.tfar)) continue;
- intersect(pre,ray,context,prim[i].subgrid(ID));
- }
- }
- }
-
- template<int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
- for (size_t i=0;i<num;i++)
- {
- const float time = prim[i].adjustTime(ray.time());
- assert(time <= 1.0f);
- vfloat<Nx> dist;
- size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- if (occluded(pre,ray,context,prim[i].subgrid(ID)))
- return true;
- }
- }
- return false;
- }
-
- static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t num, const TravPointQuery<N> &tquery, size_t& lazy_node)
- {
- assert(false && "not implemented");
- return false;
- }
- };
-
-
- template<int N, int K, bool filter>
- struct SubGridMBIntersectorKPluecker
- {
- typedef SubGridMBQBVHN<N> Primitive;
- typedef SubGridQuadMIntersectorKPluecker<4,K,filter> Precalculations;
-
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- size_t m_valid = movemask(valid_i);
- while(m_valid)
- {
- size_t ID = bscf(m_valid);
- intersect(pre,ray,ID,context,subgrid);
- }
- }
-
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
- {
- vbool<K> valid0 = valid_i;
- size_t m_valid = movemask(valid_i);
- while(m_valid)
- {
- size_t ID = bscf(m_valid);
- if (occluded(pre,ray,ID,context,subgrid))
- clear(valid0,ID);
- }
- return !valid0;
- }
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(normal.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- vfloat<K> ftime;
- const vint<K> itime = mesh->timeSegment(ray.time(), ftime);
- Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime[k],ftime[k]);
- pre.intersect1(ray,k,context,v0,v1,v2,v3,g,subgrid);
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
- const GridMesh::Grid &g = mesh->grid(subgrid.primID());
-
- vfloat<K> ftime;
- const vint<K> itime = mesh->timeSegment(ray.time(), ftime);
- Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime[k],ftime[k]);
- return pre.occluded1(ray,k,context,v0,v1,v2,v3,g,subgrid);
- }
-
- template<bool robust>
- static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
- for (size_t j=0;j<num;j++)
- {
- size_t m_valid = movemask(prim[j].qnode.validMask());
- const vfloat<K> time = prim[j].adjustTime(ray.time());
-
- vfloat<K> dist;
- while(m_valid)
- {
- const size_t i = bscf(m_valid);
- if (none(valid & isecK.intersectK(&prim[j].qnode,i,tray,time,dist))) continue;
- intersect(valid,pre,ray,context,prim[j].subgrid(i));
- }
- }
- }
-
- template<bool robust>
- static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
-
- vbool<K> valid0 = valid;
- for (size_t j=0;j<num;j++)
- {
- size_t m_valid = movemask(prim[j].qnode.validMask());
- const vfloat<K> time = prim[j].adjustTime(ray.time());
- vfloat<K> dist;
- while(m_valid)
- {
- const size_t i = bscf(m_valid);
- if (none(valid0 & isecK.intersectK(&prim[j].qnode,i,tray,time,dist))) continue;
- valid0 &= !occluded(valid0,pre,ray,context,prim[j].subgrid(i));
- if (none(valid0)) break;
- }
- }
- return !valid0;
- }
-
- template<int Nx, bool robust>
- static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
- for (size_t i=0;i<num;i++)
- {
- vfloat<N> dist;
- const float time = prim[i].adjustTime(ray.time()[k]);
- assert(time <= 1.0f);
-
- size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- if (unlikely(dist[ID] > ray.tfar[k])) continue;
- intersect(pre,ray,k,context,prim[i].subgrid(ID));
- }
- }
- }
-
- template<int Nx, bool robust>
- static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,Nx,robust> &tray, size_t& lazy_node)
- {
- BVHNQuantizedBaseNodeIntersector1<N,Nx,robust> isec1;
-
- for (size_t i=0;i<num;i++)
- {
- vfloat<N> dist;
- const float time = prim[i].adjustTime(ray.time()[k]);
- assert(time <= 1.0f);
-
- size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist);
- while(mask != 0)
- {
- const size_t ID = bscf(mask);
- if (occluded(pre,ray,k,context,prim[i].subgrid(ID)))
- return true;
- }
- }
- return false;
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/triangle.h b/thirdparty/embree-aarch64/kernels/geometry/triangle.h
deleted file mode 100644
index 0dedf6dc4c..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/triangle.h
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-
-namespace embree
-{
- /* Precalculated representation for M triangles. Stores for each
- triangle a base vertex, two edges, and the geometry normal to
- speed up intersection calculations */
- template<int M>
- struct TriangleM
- {
- public:
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* Returns maximum number of stored triangles */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
-
- public:
-
- /* Default constructor */
- __forceinline TriangleM() {}
-
- /* Construction from vertices and IDs */
- __forceinline TriangleM(const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const vuint<M>& geomIDs, const vuint<M>& primIDs)
- : v0(v0), e1(v0-v1), e2(v2-v0), geomIDs(geomIDs), primIDs(primIDs) {}
-
- /* Returns a mask that tells which triangles are valid */
- __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); }
-
- /* Returns true if the specified triangle is valid */
- __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; }
-
- /* Returns the number of stored triangles */
- __forceinline size_t size() const { return bsf(~movemask(valid())); }
-
- /* Returns the geometry IDs */
- __forceinline vuint<M>& geomID() { return geomIDs; }
- __forceinline const vuint<M>& geomID() const { return geomIDs; }
- __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
-
- /* Returns the primitive IDs */
- __forceinline vuint<M>& primID() { return primIDs; }
- __forceinline const vuint<M>& primID() const { return primIDs; }
- __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
-
- /* Calculate the bounds of the triangle */
- __forceinline BBox3fa bounds() const
- {
- Vec3vf<M> p0 = v0;
- Vec3vf<M> p1 = v0-e1;
- Vec3vf<M> p2 = v0+e2;
- Vec3vf<M> lower = min(p0,p1,p2);
- Vec3vf<M> upper = max(p0,p1,p2);
- vbool<M> mask = valid();
- lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
- lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
- lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
- upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
- upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
- upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
- return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
- Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
- }
-
- /* Non temporal store */
- __forceinline static void store_nt(TriangleM* dst, const TriangleM& src)
- {
- vfloat<M>::store_nt(&dst->v0.x,src.v0.x);
- vfloat<M>::store_nt(&dst->v0.y,src.v0.y);
- vfloat<M>::store_nt(&dst->v0.z,src.v0.z);
- vfloat<M>::store_nt(&dst->e1.x,src.e1.x);
- vfloat<M>::store_nt(&dst->e1.y,src.e1.y);
- vfloat<M>::store_nt(&dst->e1.z,src.e1.z);
- vfloat<M>::store_nt(&dst->e2.x,src.e2.x);
- vfloat<M>::store_nt(&dst->e2.y,src.e2.y);
- vfloat<M>::store_nt(&dst->e2.z,src.e2.z);
- vuint<M>::store_nt(&dst->geomIDs,src.geomIDs);
- vuint<M>::store_nt(&dst->primIDs,src.primIDs);
- }
-
- /* Fill triangle from triangle list */
- __forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
- {
- vuint<M> vgeomID = -1, vprimID = -1;
- Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
-
- for (size_t i=0; i<M && begin<end; i++, begin++)
- {
- const PrimRef& prim = prims[begin];
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(geomID);
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- const Vec3fa& p0 = mesh->vertex(tri.v[0]);
- const Vec3fa& p1 = mesh->vertex(tri.v[1]);
- const Vec3fa& p2 = mesh->vertex(tri.v[2]);
- vgeomID [i] = geomID;
- vprimID [i] = primID;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- }
- TriangleM::store_nt(this,TriangleM(v0,v1,v2,vgeomID,vprimID));
- }
-
- /* Updates the primitive */
- __forceinline BBox3fa update(TriangleMesh* mesh)
- {
- BBox3fa bounds = empty;
- vuint<M> vgeomID = -1, vprimID = -1;
- Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
-
- for (size_t i=0; i<M; i++)
- {
- if (unlikely(geomID(i) == -1)) break;
- const unsigned geomId = geomID(i);
- const unsigned primId = primID(i);
- const TriangleMesh::Triangle& tri = mesh->triangle(primId);
- const Vec3fa p0 = mesh->vertex(tri.v[0]);
- const Vec3fa p1 = mesh->vertex(tri.v[1]);
- const Vec3fa p2 = mesh->vertex(tri.v[2]);
- bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2)));
- vgeomID [i] = geomId;
- vprimID [i] = primId;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- }
- TriangleM::store_nt(this,TriangleM(v0,v1,v2,vgeomID,vprimID));
- return bounds;
- }
-
- public:
- Vec3vf<M> v0; // base vertex of the triangles
- Vec3vf<M> e1; // 1st edge of the triangles (v0-v1)
- Vec3vf<M> e2; // 2nd edge of the triangles (v2-v0)
- private:
- vuint<M> geomIDs; // geometry IDs
- vuint<M> primIDs; // primitive IDs
- };
-
- template<int M>
- typename TriangleM<M>::Type TriangleM<M>::type;
-
- typedef TriangleM<4> Triangle4;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector.h
deleted file mode 100644
index 125a42c5fe..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "triangle.h"
-#include "triangle_intersector_moeller.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Intersects M triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMIntersector1Moeller
- {
- typedef TriangleM<M> Primitive;
- typedef MoellerTrumboreIntersector1<Mx> Precalculations;
-
- /*! Intersect a ray with the M triangles and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleM<M>& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of M triangles. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleM<M>& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
-
- };
-
- /*! Intersects M triangles with K rays. */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMIntersectorKMoeller
- {
- typedef TriangleM<M> Primitive;
- typedef MoellerTrumboreIntersectorK<Mx,K> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleM<M>& tri)
- {
- STAT_USER(0,TriangleM<M>::max_size());
- for (size_t i=0; i<TriangleM<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> p0 = broadcast<vfloat<K>>(tri.v0,i);
- const Vec3vf<K> e1 = broadcast<vfloat<K>>(tri.e1,i);
- const Vec3vf<K> e2 = broadcast<vfloat<K>>(tri.e2,i);
- pre.intersectEdgeK(valid_i,ray,p0,e1,e2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleM<M>& tri)
- {
- vbool<K> valid0 = valid_i;
-
- for (size_t i=0; i<TriangleM<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- const Vec3vf<K> p0 = broadcast<vfloat<K>>(tri.v0,i);
- const Vec3vf<K> e1 = broadcast<vfloat<K>>(tri.e1,i);
- const Vec3vf<K> e2 = broadcast<vfloat<K>>(tri.e2,i);
- pre.intersectEdgeK(valid0,ray,p0,e1,e2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleM<M>& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleM<M>& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_moeller.h b/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_moeller.h
deleted file mode 100644
index b5a8519236..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_moeller.h
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "triangle.h"
-#include "intersector_epilog.h"
-
-/*! This intersector implements a modified version of the Moeller
- * Trumbore intersector from the paper "Fast, Minimum Storage
- * Ray-Triangle Intersection". In contrast to the paper we
- * precalculate some factors and factor the calculations differently
- * to allow precalculating the cross product e1 x e2. The resulting
- * algorithm is similar to the fastest one of the paper "Optimizing
- * Ray-Triangle Intersection via Automated Search". */
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct MoellerTrumboreHitM
- {
- __forceinline MoellerTrumboreHitM() {}
-
- __forceinline MoellerTrumboreHitM(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const vfloat<M>& absDen, const Vec3vf<M>& Ng)
- : U(U), V(V), T(T), absDen(absDen), valid(valid), vNg(Ng) {}
-
- __forceinline void finalize()
- {
- const vfloat<M> rcpAbsDen = rcp(absDen);
- vt = T * rcpAbsDen;
- vu = U * rcpAbsDen;
- vv = V * rcpAbsDen;
- }
-
- __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
- __forceinline float t (const size_t i) const { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- public:
- vfloat<M> U;
- vfloat<M> V;
- vfloat<M> T;
- vfloat<M> absDen;
-
- public:
- vbool<M> valid;
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- template<int M>
- struct MoellerTrumboreIntersector1
- {
- __forceinline MoellerTrumboreIntersector1() {}
-
- __forceinline MoellerTrumboreIntersector1(const Ray& ray, const void* ptr) {}
-
- __forceinline bool intersect(const vbool<M>& valid0,
- Ray& ray,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- const Vec3vf<M>& tri_Ng,
- MoellerTrumboreHitM<M>& hit) const
- {
- /* calculate denominator */
- vbool<M> valid = valid0;
- const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org);
- const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir);
- const Vec3vf<M> C = Vec3vf<M>(tri_v0) - O;
- const Vec3vf<M> R = cross(C,D);
- const vfloat<M> den = dot(Vec3vf<M>(tri_Ng),D);
-
- const vfloat<M> absDen = abs(den);
- const vfloat<M> sgnDen = signmsk(den);
-
- /* perform edge tests */
- const vfloat<M> U = dot(R,Vec3vf<M>(tri_e2)) ^ sgnDen;
- const vfloat<M> V = dot(R,Vec3vf<M>(tri_e1)) ^ sgnDen;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- valid &= (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#else
- valid &= (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#endif
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
- valid &= (absDen*vfloat<M>(ray.tnear()) < T) & (T <= absDen*vfloat<M>(ray.tfar));
- if (likely(none(valid))) return false;
-
-
- /* update hit information */
- new (&hit) MoellerTrumboreHitM<M>(valid,U,V,T,absDen,tri_Ng);
-
- return true;
- }
-
- __forceinline bool intersectEdge(Ray& ray,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- MoellerTrumboreHitM<M>& hit) const
- {
- vbool<M> valid = true;
- const Vec3<vfloat<M>> tri_Ng = cross(tri_e2,tri_e1);
- return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,hit);
- }
-
- __forceinline bool intersect(Ray& ray,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- MoellerTrumboreHitM<M>& hit) const
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- return intersectEdge(ray,v0,e1,e2,hit);
- }
-
- __forceinline bool intersect(const vbool<M>& valid,
- Ray& ray,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- MoellerTrumboreHitM<M>& hit) const
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- return intersectEdge(valid,ray,v0,e1,e2,hit);
- }
-
- template<typename Epilog>
- __forceinline bool intersectEdge(Ray& ray,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& e1,
- const Vec3vf<M>& e2,
- const Epilog& epilog) const
- {
- MoellerTrumboreHitM<M> hit;
- if (likely(intersectEdge(ray,v0,e1,e2,hit))) return epilog(hit.valid,hit);
- return false;
- }
-
- template<typename Epilog>
- __forceinline bool intersect(Ray& ray,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const Epilog& epilog) const
- {
- MoellerTrumboreHitM<M> hit;
- if (likely(intersect(ray,v0,v1,v2,hit))) return epilog(hit.valid,hit);
- return false;
- }
-
- template<typename Epilog>
- __forceinline bool intersect(const vbool<M>& valid,
- Ray& ray,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const Epilog& epilog) const
- {
- MoellerTrumboreHitM<M> hit;
- if (likely(intersect(valid,ray,v0,v1,v2,hit))) return epilog(hit.valid,hit);
- return false;
- }
- };
-
- template<int K>
- struct MoellerTrumboreHitK
- {
- __forceinline MoellerTrumboreHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& T, const vfloat<K>& absDen, const Vec3vf<K>& Ng)
- : U(U), V(V), T(T), absDen(absDen), Ng(Ng) {}
-
- __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
- {
- const vfloat<K> rcpAbsDen = rcp(absDen);
- const vfloat<K> t = T * rcpAbsDen;
- const vfloat<K> u = U * rcpAbsDen;
- const vfloat<K> v = V * rcpAbsDen;
- return std::make_tuple(u,v,t,Ng);
- }
-
- private:
- const vfloat<K> U;
- const vfloat<K> V;
- const vfloat<K> T;
- const vfloat<K> absDen;
- const Vec3vf<K> Ng;
- };
-
- template<int M, int K>
- struct MoellerTrumboreIntersectorK
- {
- __forceinline MoellerTrumboreIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {}
-
- /*! Intersects K rays with one of M triangles. */
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- //RayK<K>& ray,
- const Vec3vf<K>& ray_org,
- const Vec3vf<K>& ray_dir,
- const vfloat<K>& ray_tnear,
- const vfloat<K>& ray_tfar,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_e1,
- const Vec3vf<K>& tri_e2,
- const Vec3vf<K>& tri_Ng,
- const Epilog& epilog) const
- {
- /* calculate denominator */
- vbool<K> valid = valid0;
- const Vec3vf<K> C = tri_v0 - ray_org;
- const Vec3vf<K> R = cross(C,ray_dir);
- const vfloat<K> den = dot(tri_Ng,ray_dir);
- const vfloat<K> absDen = abs(den);
- const vfloat<K> sgnDen = signmsk(den);
-
- /* test against edge p2 p0 */
- const vfloat<K> U = dot(tri_e2,R) ^ sgnDen;
- valid &= U >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* test against edge p0 p1 */
- const vfloat<K> V = dot(tri_e1,R) ^ sgnDen;
- valid &= V >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* test against edge p1 p2 */
- const vfloat<K> W = absDen-U-V;
- valid &= W >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen;
- valid &= (absDen*ray_tnear < T) & (T <= absDen*ray_tfar);
- if (unlikely(none(valid))) return false;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- valid &= den < vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-#else
- valid &= den != vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-#endif
-
- /* calculate hit information */
- MoellerTrumboreHitK<K> hit(U,V,T,absDen,tri_Ng);
- return epilog(valid,hit);
- }
-
- /*! Intersects K rays with one of M triangles. */
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_v1,
- const Vec3vf<K>& tri_v2,
- const Epilog& epilog) const
- {
- const Vec3vf<K> e1 = tri_v0-tri_v1;
- const Vec3vf<K> e2 = tri_v2-tri_v0;
- const Vec3vf<K> Ng = cross(e2,e1);
- return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,epilog);
- }
-
- /*! Intersects K rays with one of M triangles. */
- template<typename Epilog>
- __forceinline vbool<K> intersectEdgeK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_e1,
- const Vec3vf<K>& tri_e2,
- const Epilog& epilog) const
- {
- const Vec3vf<K> tri_Ng = cross(tri_e2,tri_e1);
- return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,tri_e1,tri_e2,tri_Ng,epilog);
- }
-
- /*! Intersect k'th ray from ray packet of size K with M triangles. */
- __forceinline bool intersectEdge(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- MoellerTrumboreHitM<M>& hit) const
- {
- /* calculate denominator */
- typedef Vec3vf<M> Vec3vfM;
- const Vec3vf<M> tri_Ng = cross(tri_e2,tri_e1);
-
- const Vec3vfM O = broadcast<vfloat<M>>(ray.org,k);
- const Vec3vfM D = broadcast<vfloat<M>>(ray.dir,k);
- const Vec3vfM C = Vec3vfM(tri_v0) - O;
- const Vec3vfM R = cross(C,D);
- const vfloat<M> den = dot(Vec3vfM(tri_Ng),D);
- const vfloat<M> absDen = abs(den);
- const vfloat<M> sgnDen = signmsk(den);
-
- /* perform edge tests */
- const vfloat<M> U = dot(Vec3vf<M>(tri_e2),R) ^ sgnDen;
- const vfloat<M> V = dot(Vec3vf<M>(tri_e1),R) ^ sgnDen;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#else
- vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#endif
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
- valid &= (absDen*vfloat<M>(ray.tnear()[k]) < T) & (T <= absDen*vfloat<M>(ray.tfar[k]));
- if (likely(none(valid))) return false;
-
- /* calculate hit information */
- new (&hit) MoellerTrumboreHitM<M>(valid,U,V,T,absDen,tri_Ng);
- return true;
- }
-
- __forceinline bool intersectEdge(RayK<K>& ray,
- size_t k,
- const BBox<vfloat<M>>& time_range,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- MoellerTrumboreHitM<M>& hit) const
- {
- if (likely(intersect(ray,k,tri_v0,tri_e1,tri_e2,hit)))
- {
- hit.valid &= time_range.lower <= vfloat<M>(ray.time[k]);
- hit.valid &= vfloat<M>(ray.time[k]) < time_range.upper;
- return any(hit.valid);
- }
- return false;
- }
-
- template<typename Epilog>
- __forceinline bool intersectEdge(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- const Epilog& epilog) const
- {
- MoellerTrumboreHitM<M> hit;
- if (likely(intersectEdge(ray,k,tri_v0,tri_e1,tri_e2,hit))) return epilog(hit.valid,hit);
- return false;
- }
-
- template<typename Epilog>
- __forceinline bool intersectEdge(RayK<K>& ray,
- size_t k,
- const BBox<vfloat<M>>& time_range,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- const Epilog& epilog) const
- {
- MoellerTrumboreHitM<M> hit;
- if (likely(intersectEdge(ray,k,time_range,tri_v0,tri_e1,tri_e2,hit))) return epilog(hit.valid,hit);
- return false;
- }
-
- template<typename Epilog>
- __forceinline bool intersect(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const Epilog& epilog) const
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- return intersectEdge(ray,k,v0,e1,e2,epilog);
- }
-
- template<typename Epilog>
- __forceinline bool intersect(RayK<K>& ray,
- size_t k,
- const BBox<vfloat<M>>& time_range,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const Epilog& epilog) const
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- return intersectEdge(ray,k,time_range,v0,e1,e2,epilog);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_pluecker.h b/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_pluecker.h
deleted file mode 100644
index f1de99d208..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_pluecker.h
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "triangle.h"
-#include "trianglev.h"
-#include "trianglev_mb.h"
-#include "intersector_epilog.h"
-
-/*! Modified Pluecker ray/triangle intersector. The test first shifts
- * the ray origin into the origin of the coordinate system and then
- * uses Pluecker coordinates for the intersection. Due to the shift,
- * the Pluecker coordinate calculation simplifies and the tests get
- * numerically stable. The edge equations are watertight along the
- * edge for neighboring triangles. */
-
-namespace embree
-{
- namespace isa
- {
- template<int M, typename UVMapper>
- struct PlueckerHitM
- {
- __forceinline PlueckerHitM(const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& UVW, const vfloat<M>& t, const Vec3vf<M>& Ng, const UVMapper& mapUV)
- : U(U), V(V), UVW(UVW), mapUV(mapUV), vt(t), vNg(Ng) {}
-
- __forceinline void finalize()
- {
- const vbool<M> invalid = abs(UVW) < min_rcp_input;
- const vfloat<M> rcpUVW = select(invalid,vfloat<M>(0.0f),rcp(UVW));
- vu = U * rcpUVW;
- vv = V * rcpUVW;
- mapUV(vu,vv);
- }
-
- __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
- __forceinline float t (const size_t i) const { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- private:
- const vfloat<M> U;
- const vfloat<M> V;
- const vfloat<M> UVW;
- const UVMapper& mapUV;
-
- public:
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- template<int M>
- struct PlueckerIntersector1
- {
- __forceinline PlueckerIntersector1() {}
-
- __forceinline PlueckerIntersector1(const Ray& ray, const void* ptr) {}
-
- template<typename UVMapper, typename Epilog>
- __forceinline bool intersect(Ray& ray,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_v1,
- const Vec3vf<M>& tri_v2,
- const UVMapper& mapUV,
- const Epilog& epilog) const
- {
- /* calculate vertices relative to ray origin */
- const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org);
- const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir);
- const Vec3vf<M> v0 = tri_v0-O;
- const Vec3vf<M> v1 = tri_v1-O;
- const Vec3vf<M> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<M> e0 = v2-v0;
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<M> U = dot(cross(e0,v2+v0),D);
- const vfloat<M> V = dot(cross(e1,v0+v1),D);
- const vfloat<M> W = dot(cross(e2,v1+v2),D);
- const vfloat<M> UVW = U+V+W;
- const vfloat<M> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = max(U,V,W) <= eps;
-#else
- vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<M> den = twice(dot(Ng,D));
-
- /* perform depth test */
- const vfloat<M> T = twice(dot(v0,Ng));
- const vfloat<M> t = rcp(den)*T;
- valid &= vfloat<M>(ray.tnear()) <= t & t <= vfloat<M>(ray.tfar);
- valid &= den != vfloat<M>(zero);
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- PlueckerHitM<M,UVMapper> hit(U,V,UVW,t,Ng,mapUV);
- return epilog(valid,hit);
- }
- };
-
- template<int K, typename UVMapper>
- struct PlueckerHitK
- {
- __forceinline PlueckerHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& UVW, const vfloat<K>& t, const Vec3vf<K>& Ng, const UVMapper& mapUV)
- : U(U), V(V), UVW(UVW), t(t), Ng(Ng), mapUV(mapUV) {}
-
- __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
- {
- const vbool<K> invalid = abs(UVW) < min_rcp_input;
- const vfloat<K> rcpUVW = select(invalid,vfloat<K>(0.0f),rcp(UVW));
- vfloat<K> u = U * rcpUVW;
- vfloat<K> v = V * rcpUVW;
- mapUV(u,v);
- return std::make_tuple(u,v,t,Ng);
- }
-
- private:
- const vfloat<K> U;
- const vfloat<K> V;
- const vfloat<K> UVW;
- const vfloat<K> t;
- const Vec3vf<K> Ng;
- const UVMapper& mapUV;
- };
-
- template<int M, int K>
- struct PlueckerIntersectorK
- {
- __forceinline PlueckerIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {}
-
- /*! Intersects K rays with one of M triangles. */
- template<typename UVMapper, typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_v1,
- const Vec3vf<K>& tri_v2,
- const UVMapper& mapUV,
- const Epilog& epilog) const
- {
- /* calculate vertices relative to ray origin */
- vbool<K> valid = valid0;
- const Vec3vf<K> O = ray.org;
- const Vec3vf<K> D = ray.dir;
- const Vec3vf<K> v0 = tri_v0-O;
- const Vec3vf<K> v1 = tri_v1-O;
- const Vec3vf<K> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<K> e0 = v2-v0;
- const Vec3vf<K> e1 = v0-v1;
- const Vec3vf<K> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<K> U = dot(Vec3vf<K>(cross(e0,v2+v0)),D);
- const vfloat<K> V = dot(Vec3vf<K>(cross(e1,v0+v1)),D);
- const vfloat<K> W = dot(Vec3vf<K>(cross(e2,v1+v2)),D);
- const vfloat<K> UVW = U+V+W;
- const vfloat<K> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- valid &= max(U,V,W) <= eps;
-#else
- valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<K> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<K> den = twice(dot(Vec3vf<K>(Ng),D));
-
- /* perform depth test */
- const vfloat<K> T = twice(dot(v0,Vec3vf<K>(Ng)));
- const vfloat<K> t = rcp(den)*T;
- valid &= ray.tnear() <= t & t <= ray.tfar;
- valid &= den != vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-
- /* calculate hit information */
- PlueckerHitK<K,UVMapper> hit(U,V,UVW,t,Ng,mapUV);
- return epilog(valid,hit);
- }
-
- /*! Intersect k'th ray from ray packet of size K with M triangles. */
- template<typename UVMapper, typename Epilog>
- __forceinline bool intersect(RayK<K>& ray, size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_v1,
- const Vec3vf<M>& tri_v2,
- const UVMapper& mapUV,
- const Epilog& epilog) const
- {
- /* calculate vertices relative to ray origin */
- const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
- const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
- const Vec3vf<M> v0 = tri_v0-O;
- const Vec3vf<M> v1 = tri_v1-O;
- const Vec3vf<M> v2 = tri_v2-O;
-
- /* calculate triangle edges */
- const Vec3vf<M> e0 = v2-v0;
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v1-v2;
-
- /* perform edge tests */
- const vfloat<M> U = dot(cross(e0,v2+v0),D);
- const vfloat<M> V = dot(cross(e1,v0+v1),D);
- const vfloat<M> W = dot(cross(e2,v1+v2),D);
- const vfloat<M> UVW = U+V+W;
- const vfloat<M> eps = float(ulp)*abs(UVW);
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = max(U,V,W) <= eps;
-#else
- vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
-#endif
- if (unlikely(none(valid))) return false;
-
- /* calculate geometry normal and denominator */
- const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
- const vfloat<M> den = twice(dot(Ng,D));
-
- /* perform depth test */
- const vfloat<M> T = twice(dot(v0,Ng));
- const vfloat<M> t = rcp(den)*T;
- valid &= vfloat<M>(ray.tnear()[k]) <= t & t <= vfloat<M>(ray.tfar[k]);
- if (unlikely(none(valid))) return false;
-
- /* avoid division by 0 */
- valid &= den != vfloat<M>(zero);
- if (unlikely(none(valid))) return false;
-
- /* update hit information */
- PlueckerHitM<M,UVMapper> hit(U,V,UVW,t,Ng,mapUV);
- return epilog(valid,hit);
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_woop.h b/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_woop.h
deleted file mode 100644
index 63e649d8fb..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/triangle_intersector_woop.h
+++ /dev/null
@@ -1,418 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "triangle.h"
-#include "intersector_epilog.h"
-
-/*! This intersector implements a modified version of the Woop's ray-triangle intersection test */
-
-namespace embree
-{
- namespace isa
- {
- template<int M>
- struct WoopHitM
- {
- __forceinline WoopHitM() {}
-
- __forceinline WoopHitM(const vbool<M>& valid,
- const vfloat<M>& U,
- const vfloat<M>& V,
- const vfloat<M>& T,
- const vfloat<M>& inv_det,
- const Vec3vf<M>& Ng)
- : U(U), V(V), T(T), inv_det(inv_det), valid(valid), vNg(Ng) {}
-
- __forceinline void finalize()
- {
- vt = T;
- vu = U*inv_det;
- vv = V*inv_det;
- }
-
- __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
- __forceinline float t (const size_t i) const { return vt[i]; }
- __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
-
- private:
- const vfloat<M> U;
- const vfloat<M> V;
- const vfloat<M> T;
- const vfloat<M> inv_det;
-
- public:
- const vbool<M> valid;
- vfloat<M> vu;
- vfloat<M> vv;
- vfloat<M> vt;
- Vec3vf<M> vNg;
- };
-
- template<int M>
- struct WoopPrecalculations1
- {
- unsigned int kx,ky,kz;
- Vec3vf<M> org;
- Vec3fa S;
- __forceinline WoopPrecalculations1() {}
-
- __forceinline WoopPrecalculations1(const Ray& ray, const void* ptr)
- {
- kz = maxDim(abs(ray.dir));
- kx = (kz+1) % 3;
- ky = (kx+1) % 3;
- const float inv_dir_kz = rcp(ray.dir[kz]);
- if (ray.dir[kz]) std::swap(kx,ky);
- S.x = ray.dir[kx] * inv_dir_kz;
- S.y = ray.dir[ky] * inv_dir_kz;
- S.z = inv_dir_kz;
- org = Vec3vf<M>(ray.org[kx],ray.org[ky],ray.org[kz]);
- }
- };
-
-
- template<int M>
- struct WoopIntersector1
- {
-
- typedef WoopPrecalculations1<M> Precalculations;
-
- __forceinline WoopIntersector1() {}
-
- __forceinline WoopIntersector1(const Ray& ray, const void* ptr) {}
-
- static __forceinline bool intersect(const vbool<M>& valid0,
- Ray& ray,
- const Precalculations& pre,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_v1,
- const Vec3vf<M>& tri_v2,
- WoopHitM<M>& hit)
- {
- vbool<M> valid = valid0;
-
- /* vertices relative to ray origin */
- const Vec3vf<M> org = Vec3vf<M>(pre.org.x,pre.org.y,pre.org.z);
- const Vec3vf<M> A = Vec3vf<M>(tri_v0[pre.kx],tri_v0[pre.ky],tri_v0[pre.kz]) - org;
- const Vec3vf<M> B = Vec3vf<M>(tri_v1[pre.kx],tri_v1[pre.ky],tri_v1[pre.kz]) - org;
- const Vec3vf<M> C = Vec3vf<M>(tri_v2[pre.kx],tri_v2[pre.ky],tri_v2[pre.kz]) - org;
-
- /* shear and scale vertices */
- const vfloat<M> Ax = nmadd(A.z,pre.S.x,A.x);
- const vfloat<M> Ay = nmadd(A.z,pre.S.y,A.y);
- const vfloat<M> Bx = nmadd(B.z,pre.S.x,B.x);
- const vfloat<M> By = nmadd(B.z,pre.S.y,B.y);
- const vfloat<M> Cx = nmadd(C.z,pre.S.x,C.x);
- const vfloat<M> Cy = nmadd(C.z,pre.S.y,C.y);
-
- /* scaled barycentric */
- const vfloat<M> U0 = Cx*By;
- const vfloat<M> U1 = Cy*Bx;
- const vfloat<M> V0 = Ax*Cy;
- const vfloat<M> V1 = Ay*Cx;
- const vfloat<M> W0 = Bx*Ay;
- const vfloat<M> W1 = By*Ax;
-#if !defined(__AVX512F__)
- valid &= (U0 >= U1) & (V0 >= V1) & (W0 >= W1) |
- (U0 <= U1) & (V0 <= V1) & (W0 <= W1);
-#else
- valid &= ge(ge(U0 >= U1,V0,V1),W0,W1) | le(le(U0 <= U1,V0,V1),W0,W1);
-#endif
-
- if (likely(none(valid))) return false;
- const vfloat<M> U = U0-U1;
- const vfloat<M> V = V0-V1;
- const vfloat<M> W = W0-W1;
-
- const vfloat<M> det = U+V+W;
-
- valid &= det != 0.0f;
- const vfloat<M> inv_det = rcp(det);
-
- const vfloat<M> Az = pre.S.z * A.z;
- const vfloat<M> Bz = pre.S.z * B.z;
- const vfloat<M> Cz = pre.S.z * C.z;
- const vfloat<M> T = madd(U,Az,madd(V,Bz,W*Cz));
- const vfloat<M> t = T * inv_det;
- /* perform depth test */
- valid &= (vfloat<M>(ray.tnear()) < t) & (t <= vfloat<M>(ray.tfar));
- if (likely(none(valid))) return false;
-
- const Vec3vf<M> tri_Ng = cross(tri_v2-tri_v0,tri_v0-tri_v1);
-
- /* update hit information */
- new (&hit) WoopHitM<M>(valid,U,V,t,inv_det,tri_Ng);
- return true;
- }
-
- static __forceinline bool intersect(Ray& ray,
- const Precalculations& pre,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- WoopHitM<M>& hit)
- {
- vbool<M> valid = true;
- return intersect(valid,ray,pre,v0,v1,v2,hit);
- }
-
-
- template<typename Epilog>
- static __forceinline bool intersect(Ray& ray,
- const Precalculations& pre,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const Epilog& epilog)
- {
- WoopHitM<M> hit;
- if (likely(intersect(ray,pre,v0,v1,v2,hit))) return epilog(hit.valid,hit);
- return false;
- }
-
- template<typename Epilog>
- static __forceinline bool intersect(const vbool<M>& valid,
- Ray& ray,
- const Precalculations& pre,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const Epilog& epilog)
- {
- WoopHitM<M> hit;
- if (likely(intersect(valid,ray,pre,v0,v1,v2,hit))) return epilog(hit.valid,hit);
- return false;
- }
- };
-
-#if 0
- template<int K>
- struct WoopHitK
- {
- __forceinline WoopHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& T, const vfloat<K>& absDen, const Vec3vf<K>& Ng)
- : U(U), V(V), T(T), absDen(absDen), Ng(Ng) {}
-
- __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
- {
- const vfloat<K> rcpAbsDen = rcp(absDen);
- const vfloat<K> t = T * rcpAbsDen;
- const vfloat<K> u = U * rcpAbsDen;
- const vfloat<K> v = V * rcpAbsDen;
- return std::make_tuple(u,v,t,Ng);
- }
-
- private:
- const vfloat<K> U;
- const vfloat<K> V;
- const vfloat<K> T;
- const vfloat<K> absDen;
- const Vec3vf<K> Ng;
- };
-
- template<int M, int K>
- struct WoopIntersectorK
- {
- __forceinline WoopIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {}
-
- /*! Intersects K rays with one of M triangles. */
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- //RayK<K>& ray,
- const Vec3vf<K>& ray_org,
- const Vec3vf<K>& ray_dir,
- const vfloat<K>& ray_tnear,
- const vfloat<K>& ray_tfar,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_e1,
- const Vec3vf<K>& tri_e2,
- const Vec3vf<K>& tri_Ng,
- const Epilog& epilog) const
- {
- /* calculate denominator */
- vbool<K> valid = valid0;
- const Vec3vf<K> C = tri_v0 - ray_org;
- const Vec3vf<K> R = cross(C,ray_dir);
- const vfloat<K> den = dot(tri_Ng,ray_dir);
- const vfloat<K> absDen = abs(den);
- const vfloat<K> sgnDen = signmsk(den);
-
- /* test against edge p2 p0 */
- const vfloat<K> U = dot(tri_e2,R) ^ sgnDen;
- valid &= U >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* test against edge p0 p1 */
- const vfloat<K> V = dot(tri_e1,R) ^ sgnDen;
- valid &= V >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* test against edge p1 p2 */
- const vfloat<K> W = absDen-U-V;
- valid &= W >= 0.0f;
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen;
- valid &= (absDen*ray_tnear < T) & (T <= absDen*ray_tfar);
- if (unlikely(none(valid))) return false;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- valid &= den < vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-#else
- valid &= den != vfloat<K>(zero);
- if (unlikely(none(valid))) return false;
-#endif
-
- /* calculate hit information */
- WoopHitK<K> hit(U,V,T,absDen,tri_Ng);
- return epilog(valid,hit);
- }
-
- /*! Intersects K rays with one of M triangles. */
- template<typename Epilog>
- __forceinline vbool<K> intersectK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_v1,
- const Vec3vf<K>& tri_v2,
- const Epilog& epilog) const
- {
- const Vec3vf<K> e1 = tri_v0-tri_v1;
- const Vec3vf<K> e2 = tri_v2-tri_v0;
- const Vec3vf<K> Ng = cross(e2,e1);
- return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,epilog);
- }
-
- /*! Intersects K rays with one of M triangles. */
- template<typename Epilog>
- __forceinline vbool<K> intersectEdgeK(const vbool<K>& valid0,
- RayK<K>& ray,
- const Vec3vf<K>& tri_v0,
- const Vec3vf<K>& tri_e1,
- const Vec3vf<K>& tri_e2,
- const Epilog& epilog) const
- {
- const Vec3vf<K> tri_Ng = cross(tri_e2,tri_e1);
- return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,tri_e1,tri_e2,tri_Ng,epilog);
- }
-
- /*! Intersect k'th ray from ray packet of size K with M triangles. */
- __forceinline bool intersectEdge(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- WoopHitM<M>& hit) const
- {
- /* calculate denominator */
- typedef Vec3vf<M> Vec3vfM;
- const Vec3vf<M> tri_Ng = cross(tri_e2,tri_e1);
-
- const Vec3vfM O = broadcast<vfloat<M>>(ray.org,k);
- const Vec3vfM D = broadcast<vfloat<M>>(ray.dir,k);
- const Vec3vfM C = Vec3vfM(tri_v0) - O;
- const Vec3vfM R = cross(C,D);
- const vfloat<M> den = dot(Vec3vfM(tri_Ng),D);
- const vfloat<M> absDen = abs(den);
- const vfloat<M> sgnDen = signmsk(den);
-
- /* perform edge tests */
- const vfloat<M> U = dot(Vec3vf<M>(tri_e2),R) ^ sgnDen;
- const vfloat<M> V = dot(Vec3vf<M>(tri_e1),R) ^ sgnDen;
-
- /* perform backface culling */
-#if defined(EMBREE_BACKFACE_CULLING)
- vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#else
- vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
-#endif
- if (likely(none(valid))) return false;
-
- /* perform depth test */
- const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
- valid &= (absDen*vfloat<M>(ray.tnear()[k]) < T) & (T <= absDen*vfloat<M>(ray.tfar[k]));
- if (likely(none(valid))) return false;
-
- /* calculate hit information */
- new (&hit) WoopHitM<M>(valid,U,V,T,absDen,tri_Ng);
- return true;
- }
-
- __forceinline bool intersectEdge(RayK<K>& ray,
- size_t k,
- const BBox<vfloat<M>>& time_range,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- WoopHitM<M>& hit) const
- {
- if (likely(intersect(ray,k,tri_v0,tri_e1,tri_e2,hit)))
- {
- hit.valid &= time_range.lower <= vfloat<M>(ray.time[k]);
- hit.valid &= vfloat<M>(ray.time[k]) < time_range.upper;
- return any(hit.valid);
- }
- return false;
- }
-
- template<typename Epilog>
- __forceinline bool intersectEdge(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- const Epilog& epilog) const
- {
- WoopHitM<M> hit;
- if (likely(intersectEdge(ray,k,tri_v0,tri_e1,tri_e2,hit))) return epilog(hit.valid,hit);
- return false;
- }
-
- template<typename Epilog>
- __forceinline bool intersectEdge(RayK<K>& ray,
- size_t k,
- const BBox<vfloat<M>>& time_range,
- const Vec3vf<M>& tri_v0,
- const Vec3vf<M>& tri_e1,
- const Vec3vf<M>& tri_e2,
- const Epilog& epilog) const
- {
- WoopHitM<M> hit;
- if (likely(intersectEdge(ray,k,time_range,tri_v0,tri_e1,tri_e2,hit))) return epilog(hit.valid,hit);
- return false;
- }
-
- template<typename Epilog>
- __forceinline bool intersect(RayK<K>& ray,
- size_t k,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const Epilog& epilog) const
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- return intersectEdge(ray,k,v0,e1,e2,epilog);
- }
-
- template<typename Epilog>
- __forceinline bool intersect(RayK<K>& ray,
- size_t k,
- const BBox<vfloat<M>>& time_range,
- const Vec3vf<M>& v0,
- const Vec3vf<M>& v1,
- const Vec3vf<M>& v2,
- const Epilog& epilog) const
- {
- const Vec3vf<M> e1 = v0-v1;
- const Vec3vf<M> e2 = v2-v0;
- return intersectEdge(ray,k,time_range,v0,e1,e2,epilog);
- }
- };
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/triangle_triangle_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/triangle_triangle_intersector.h
deleted file mode 100644
index 91b35c36f3..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/triangle_triangle_intersector.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#include "primitive.h"
-
-namespace embree
-{
- namespace isa
- {
- struct TriangleTriangleIntersector
- {
- __forceinline static float T(float pa0, float pa1, float da0, float da1) {
- return pa0 + (pa1-pa0)*da0/(da0-da1);
- }
-
- __forceinline static bool point_line_side(const Vec2f& p, const Vec2f& a0, const Vec2f& a1) {
- return det(p-a0,a0-a1) >= 0.0f;
- }
-
- __forceinline static bool point_inside_triangle(const Vec2f& p, const Vec2f& a, const Vec2f& b, const Vec2f& c)
- {
- const bool pab = point_line_side(p,a,b);
- const bool pbc = point_line_side(p,b,c);
- const bool pca = point_line_side(p,c,a);
- return pab == pbc && pab == pca;
- }
-
- __forceinline static bool intersect_line_line(const Vec2f& a0, const Vec2f& a1, const Vec2f& b0, const Vec2f& b1)
- {
- const bool different_sides0 = point_line_side(b0,a0,a1) != point_line_side(b1,a0,a1);
- const bool different_sides1 = point_line_side(a0,b0,b1) != point_line_side(a1,b0,b1);
- return different_sides0 && different_sides1;
- }
-
- __forceinline static bool intersect_triangle_triangle (const Vec2f& a0, const Vec2f& a1, const Vec2f& a2,
- const Vec2f& b0, const Vec2f& b1, const Vec2f& b2)
- {
- const bool a01_b01 = intersect_line_line(a0,a1,b0,b1);
- if (a01_b01) return true;
- const bool a01_b12 = intersect_line_line(a0,a1,b1,b2);
- if (a01_b12) return true;
- const bool a01_b20 = intersect_line_line(a0,a1,b2,b0);
- if (a01_b20) return true;
- const bool a12_b01 = intersect_line_line(a1,a2,b0,b1);
- if (a12_b01) return true;
- const bool a12_b12 = intersect_line_line(a1,a2,b1,b2);
- if (a12_b12) return true;
- const bool a12_b20 = intersect_line_line(a1,a2,b2,b0);
- if (a12_b20) return true;
- const bool a20_b01 = intersect_line_line(a2,a0,b0,b1);
- if (a20_b01) return true;
- const bool a20_b12 = intersect_line_line(a2,a0,b1,b2);
- if (a20_b12) return true;
- const bool a20_b20 = intersect_line_line(a2,a0,b2,b0);
- if (a20_b20) return true;
-
- bool a_in_b = point_inside_triangle(a0,b0,b1,b2) && point_inside_triangle(a1,b0,b1,b2) && point_inside_triangle(a2,b0,b1,b2);
- if (a_in_b) return true;
-
- bool b_in_a = point_inside_triangle(b0,a0,a1,a2) && point_inside_triangle(b1,a0,a1,a2) && point_inside_triangle(b2,a0,a1,a2);
- if (b_in_a) return true;
-
- return false;
- }
-
- static bool intersect_triangle_triangle (const Vec3fa& a0, const Vec3fa& a1, const Vec3fa& a2,
- const Vec3fa& b0, const Vec3fa& b1, const Vec3fa& b2)
- {
- const float eps = 1E-5f;
-
- /* calculate triangle planes */
- const Vec3fa Na = cross(a1-a0,a2-a0);
- const float Ca = dot(Na,a0);
- const Vec3fa Nb = cross(b1-b0,b2-b0);
- const float Cb = dot(Nb,b0);
-
- /* project triangle A onto plane B */
- const float da0 = dot(Nb,a0)-Cb;
- const float da1 = dot(Nb,a1)-Cb;
- const float da2 = dot(Nb,a2)-Cb;
- if (max(da0,da1,da2) < -eps) return false;
- if (min(da0,da1,da2) > +eps) return false;
- //CSTAT(bvh_collide_prim_intersections4++);
-
- /* project triangle B onto plane A */
- const float db0 = dot(Na,b0)-Ca;
- const float db1 = dot(Na,b1)-Ca;
- const float db2 = dot(Na,b2)-Ca;
- if (max(db0,db1,db2) < -eps) return false;
- if (min(db0,db1,db2) > +eps) return false;
- //CSTAT(bvh_collide_prim_intersections5++);
-
- if (unlikely((std::fabs(da0) < eps && std::fabs(da1) < eps && std::fabs(da2) < eps) ||
- (std::fabs(db0) < eps && std::fabs(db1) < eps && std::fabs(db2) < eps)))
- {
- const size_t dz = maxDim(Na);
- const size_t dx = (dz+1)%3;
- const size_t dy = (dx+1)%3;
- const Vec2f A0(a0[dx],a0[dy]);
- const Vec2f A1(a1[dx],a1[dy]);
- const Vec2f A2(a2[dx],a2[dy]);
- const Vec2f B0(b0[dx],b0[dy]);
- const Vec2f B1(b1[dx],b1[dy]);
- const Vec2f B2(b2[dx],b2[dy]);
- return intersect_triangle_triangle(A0,A1,A2,B0,B1,B2);
- }
-
- const Vec3fa D = cross(Na,Nb);
- const float pa0 = dot(D,a0);
- const float pa1 = dot(D,a1);
- const float pa2 = dot(D,a2);
- const float pb0 = dot(D,b0);
- const float pb1 = dot(D,b1);
- const float pb2 = dot(D,b2);
-
- BBox1f ba = empty;
- if (min(da0,da1) <= 0.0f && max(da0,da1) >= 0.0f && abs(da0-da1) > 0.0f) ba.extend(T(pa0,pa1,da0,da1));
- if (min(da1,da2) <= 0.0f && max(da1,da2) >= 0.0f && abs(da1-da2) > 0.0f) ba.extend(T(pa1,pa2,da1,da2));
- if (min(da2,da0) <= 0.0f && max(da2,da0) >= 0.0f && abs(da2-da0) > 0.0f) ba.extend(T(pa2,pa0,da2,da0));
-
- BBox1f bb = empty;
- if (min(db0,db1) <= 0.0f && max(db0,db1) >= 0.0f && abs(db0-db1) > 0.0f) bb.extend(T(pb0,pb1,db0,db1));
- if (min(db1,db2) <= 0.0f && max(db1,db2) >= 0.0f && abs(db1-db2) > 0.0f) bb.extend(T(pb1,pb2,db1,db2));
- if (min(db2,db0) <= 0.0f && max(db2,db0) >= 0.0f && abs(db2-db0) > 0.0f) bb.extend(T(pb2,pb0,db2,db0));
-
- return conjoint(ba,bb);
- }
- };
- }
-}
-
-
diff --git a/thirdparty/embree-aarch64/kernels/geometry/trianglei.h b/thirdparty/embree-aarch64/kernels/geometry/trianglei.h
deleted file mode 100644
index 4f3118cc0c..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/trianglei.h
+++ /dev/null
@@ -1,442 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-#include "../common/scene.h"
-
-namespace embree
-{
- /* Stores M triangles from an indexed face set */
- template <int M>
- struct TriangleMi
- {
- /* Virtual interface to query information about the triangle type */
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* primitive supports multiple time segments */
- static const bool singleTimeSegment = false;
-
- /* Returns maximum number of stored triangles */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
-
- public:
-
- /* Default constructor */
- __forceinline TriangleMi() { }
-
- /* Construction from vertices and IDs */
- __forceinline TriangleMi(const vuint<M>& v0,
- const vuint<M>& v1,
- const vuint<M>& v2,
- const vuint<M>& geomIDs,
- const vuint<M>& primIDs)
-#if defined(EMBREE_COMPACT_POLYS)
- : geomIDs(geomIDs), primIDs(primIDs) {}
-#else
- : v0_(v0), v1_(v1), v2_(v2), geomIDs(geomIDs), primIDs(primIDs) {}
-#endif
-
- /* Returns a mask that tells which triangles are valid */
- __forceinline vbool<M> valid() const { return primIDs != vuint<M>(-1); }
-
- /* Returns if the specified triangle is valid */
- __forceinline bool valid(const size_t i) const { assert(i<M); return primIDs[i] != -1; }
-
- /* Returns the number of stored triangles */
- __forceinline size_t size() const { return bsf(~movemask(valid())); }
-
- /* Returns the geometry IDs */
- __forceinline vuint<M> geomID() const { return geomIDs; }
- __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
-
- /* Returns the primitive IDs */
- __forceinline vuint<M> primID() const { return primIDs; }
- __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
-
- /* Calculate the bounds of the triangles */
- __forceinline const BBox3fa bounds(const Scene *const scene, const size_t itime=0) const
- {
- BBox3fa bounds = empty;
- for (size_t i=0; i<M && valid(i); i++) {
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(i));
- bounds.extend(mesh->bounds(primID(i),itime));
- }
- return bounds;
- }
-
- /* Calculate the linear bounds of the primitive */
- __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime) {
- return LBBox3fa(bounds(scene,itime+0),bounds(scene,itime+1));
- }
-
- __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps)
- {
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<M && valid(i); i++)
- {
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(i));
- allBounds.extend(mesh->linearBounds(primID(i), itime, numTimeSteps));
- }
- return allBounds;
- }
-
- __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range)
- {
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<M && valid(i); i++)
- {
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(i));
- allBounds.extend(mesh->linearBounds(primID(i), time_range));
- }
- return allBounds;
- }
-
- /* Non-temporal store */
- __forceinline static void store_nt(TriangleMi* dst, const TriangleMi& src)
- {
-#if !defined(EMBREE_COMPACT_POLYS)
- vuint<M>::store_nt(&dst->v0_,src.v0_);
- vuint<M>::store_nt(&dst->v1_,src.v1_);
- vuint<M>::store_nt(&dst->v2_,src.v2_);
-#endif
- vuint<M>::store_nt(&dst->geomIDs,src.geomIDs);
- vuint<M>::store_nt(&dst->primIDs,src.primIDs);
- }
-
- /* Fill triangle from triangle list */
- template<typename PrimRefT>
- __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene)
- {
- vuint<M> v0 = zero, v1 = zero, v2 = zero;
- vuint<M> geomID = -1, primID = -1;
- const PrimRefT* prim = &prims[begin];
-
- for (size_t i=0; i<M; i++)
- {
- if (begin<end) {
- geomID[i] = prim->geomID();
- primID[i] = prim->primID();
-#if !defined(EMBREE_COMPACT_POLYS)
- const TriangleMesh* mesh = scene->get<TriangleMesh>(prim->geomID());
- const TriangleMesh::Triangle& tri = mesh->triangle(prim->primID());
- unsigned int int_stride = mesh->vertices0.getStride()/4;
- v0[i] = tri.v[0] * int_stride;
- v1[i] = tri.v[1] * int_stride;
- v2[i] = tri.v[2] * int_stride;
-#endif
- begin++;
- } else {
- assert(i);
- if (likely(i > 0)) {
- geomID[i] = geomID[0];
- primID[i] = -1;
- v0[i] = v0[0];
- v1[i] = v0[0];
- v2[i] = v0[0];
- }
- }
- if (begin<end) prim = &prims[begin];
- }
- new (this) TriangleMi(v0,v1,v2,geomID,primID); // FIXME: use non temporal store
- }
-
- __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
- {
- fill(prims, begin, end, scene);
- return linearBounds(scene, itime);
- }
-
- __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
- {
- fill(prims, begin, end, scene);
- return linearBounds(scene, time_range);
- }
-
- /* Updates the primitive */
- __forceinline BBox3fa update(TriangleMesh* mesh)
- {
- BBox3fa bounds = empty;
- for (size_t i=0; i<M; i++)
- {
- if (primID(i) == -1) break;
- const unsigned int primId = primID(i);
- const TriangleMesh::Triangle& tri = mesh->triangle(primId);
- const Vec3fa p0 = mesh->vertex(tri.v[0]);
- const Vec3fa p1 = mesh->vertex(tri.v[1]);
- const Vec3fa p2 = mesh->vertex(tri.v[2]);
- bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2)));
- }
- return bounds;
- }
-
- protected:
-#if !defined(EMBREE_COMPACT_POLYS)
- vuint<M> v0_; // 4 byte offset of 1st vertex
- vuint<M> v1_; // 4 byte offset of 2nd vertex
- vuint<M> v2_; // 4 byte offset of 3rd vertex
-#endif
- vuint<M> geomIDs; // geometry ID of mesh
- vuint<M> primIDs; // primitive ID of primitive inside mesh
- };
-
- namespace isa
- {
-
- template<int M>
- struct TriangleMi : public embree::TriangleMi<M>
- {
-#if !defined(EMBREE_COMPACT_POLYS)
- using embree::TriangleMi<M>::v0_;
- using embree::TriangleMi<M>::v1_;
- using embree::TriangleMi<M>::v2_;
-#endif
- using embree::TriangleMi<M>::geomIDs;
- using embree::TriangleMi<M>::primIDs;
- using embree::TriangleMi<M>::geomID;
- using embree::TriangleMi<M>::primID;
- using embree::TriangleMi<M>::valid;
-
- /* loads a single vertex */
- template<int vid>
- __forceinline Vec3f getVertex(const size_t index, const Scene *const scene) const
- {
-#if defined(EMBREE_COMPACT_POLYS)
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
- const TriangleMesh::Triangle& tri = mesh->triangle(primID(index));
- return (Vec3f) mesh->vertices[0][tri.v[vid]];
-#else
- const vuint<M>& v = getVertexOffset<vid>();
- const float* vertices = scene->vertices[geomID(index)];
- return (Vec3f&) vertices[v[index]];
-#endif
- }
-
- template<int vid, typename T>
- __forceinline Vec3<T> getVertex(const size_t index, const Scene *const scene, const size_t itime, const T& ftime) const
- {
-#if defined(EMBREE_COMPACT_POLYS)
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
- const TriangleMesh::Triangle& tri = mesh->triangle(primID(index));
- const Vec3fa v0 = mesh->vertices[itime+0][tri.v[vid]];
- const Vec3fa v1 = mesh->vertices[itime+1][tri.v[vid]];
-#else
- const vuint<M>& v = getVertexOffset<vid>();
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
- const float* vertices0 = (const float*) mesh->vertexPtr(0,itime+0);
- const float* vertices1 = (const float*) mesh->vertexPtr(0,itime+1);
- const Vec3fa v0 = Vec3fa::loadu(vertices0+v[index]);
- const Vec3fa v1 = Vec3fa::loadu(vertices1+v[index]);
-#endif
- const Vec3<T> p0(v0.x,v0.y,v0.z);
- const Vec3<T> p1(v1.x,v1.y,v1.z);
- return lerp(p0,p1,ftime);
- }
-
- template<int vid, int K, typename T>
- __forceinline Vec3<T> getVertex(const vbool<K>& valid, const size_t index, const Scene *const scene, const vint<K>& itime, const T& ftime) const
- {
- Vec3<T> p0, p1;
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
-
- for (size_t mask=movemask(valid), i=bsf(mask); mask; mask=btc(mask,i), i=bsf(mask))
- {
-#if defined(EMBREE_COMPACT_POLYS)
- const TriangleMesh::Triangle& tri = mesh->triangle(primID(index));
- const Vec3fa v0 = mesh->vertices[itime[i]+0][tri.v[vid]];
- const Vec3fa v1 = mesh->vertices[itime[i]+1][tri.v[vid]];
-#else
- const vuint<M>& v = getVertexOffset<vid>();
- const float* vertices0 = (const float*) mesh->vertexPtr(0,itime[i]+0);
- const float* vertices1 = (const float*) mesh->vertexPtr(0,itime[i]+1);
- const Vec3fa v0 = Vec3fa::loadu(vertices0+v[index]);
- const Vec3fa v1 = Vec3fa::loadu(vertices1+v[index]);
-#endif
- p0.x[i] = v0.x; p0.y[i] = v0.y; p0.z[i] = v0.z;
- p1.x[i] = v1.x; p1.y[i] = v1.y; p1.z[i] = v1.z;
- }
- return (T(one)-ftime)*p0 + ftime*p1;
- }
-
- struct Triangle {
- vfloat4 v0,v1,v2;
- };
-
-#if defined(EMBREE_COMPACT_POLYS)
-
- __forceinline Triangle loadTriangle(const int i, const Scene* const scene) const
- {
- const unsigned int geomID = geomIDs[i];
- const unsigned int primID = primIDs[i];
- if (unlikely(primID == -1)) return { zero, zero, zero };
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID);
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- const vfloat4 v0 = (vfloat4) mesh->vertices0[tri.v[0]];
- const vfloat4 v1 = (vfloat4) mesh->vertices0[tri.v[1]];
- const vfloat4 v2 = (vfloat4) mesh->vertices0[tri.v[2]];
- return { v0, v1, v2 };
- }
-
- __forceinline Triangle loadTriangle(const int i, const int itime, const TriangleMesh* const mesh) const
- {
- const unsigned int primID = primIDs[i];
- if (unlikely(primID == -1)) return { zero, zero, zero };
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- const vfloat4 v0 = (vfloat4) mesh->vertices[itime][tri.v[0]];
- const vfloat4 v1 = (vfloat4) mesh->vertices[itime][tri.v[1]];
- const vfloat4 v2 = (vfloat4) mesh->vertices[itime][tri.v[2]];
- return { v0, v1, v2 };
- }
-
-#else
-
- __forceinline Triangle loadTriangle(const int i, const Scene* const scene) const
- {
- const float* vertices = scene->vertices[geomID(i)];
- const vfloat4 v0 = vfloat4::loadu(vertices + v0_[i]);
- const vfloat4 v1 = vfloat4::loadu(vertices + v1_[i]);
- const vfloat4 v2 = vfloat4::loadu(vertices + v2_[i]);
- return { v0, v1, v2 };
- }
-
- __forceinline Triangle loadTriangle(const int i, const int itime, const TriangleMesh* const mesh) const
- {
- const float* vertices = (const float*) mesh->vertexPtr(0,itime);
- const vfloat4 v0 = vfloat4::loadu(vertices + v0_[i]);
- const vfloat4 v1 = vfloat4::loadu(vertices + v1_[i]);
- const vfloat4 v2 = vfloat4::loadu(vertices + v2_[i]);
- return { v0, v1, v2 };
- }
-
-#endif
-
- /* Gather the triangles */
- __forceinline void gather(Vec3vf<M>& p0, Vec3vf<M>& p1, Vec3vf<M>& p2, const Scene* const scene) const;
-
- template<int K>
-#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 2000) // workaround for compiler bug in ICC 2019
- __noinline
-#else
- __forceinline
-#endif
- void gather(const vbool<K>& valid,
- Vec3vf<K>& p0,
- Vec3vf<K>& p1,
- Vec3vf<K>& p2,
- const size_t index,
- const Scene* const scene,
- const vfloat<K>& time) const
- {
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
-
- vfloat<K> ftime;
- const vint<K> itime = mesh->timeSegment(time, ftime);
-
- const size_t first = bsf(movemask(valid));
- if (likely(all(valid,itime[first] == itime)))
- {
- p0 = getVertex<0>(index, scene, itime[first], ftime);
- p1 = getVertex<1>(index, scene, itime[first], ftime);
- p2 = getVertex<2>(index, scene, itime[first], ftime);
- } else {
- p0 = getVertex<0>(valid, index, scene, itime, ftime);
- p1 = getVertex<1>(valid, index, scene, itime, ftime);
- p2 = getVertex<2>(valid, index, scene, itime, ftime);
- }
- }
-
- __forceinline void gather(Vec3vf<M>& p0,
- Vec3vf<M>& p1,
- Vec3vf<M>& p2,
- const TriangleMesh* mesh,
- const Scene *const scene,
- const int itime) const;
-
- __forceinline void gather(Vec3vf<M>& p0,
- Vec3vf<M>& p1,
- Vec3vf<M>& p2,
- const Scene *const scene,
- const float time) const;
-
-
-#if !defined(EMBREE_COMPACT_POLYS)
- template<int N> const vuint<M>& getVertexOffset() const;
-#endif
- };
-
-#if !defined(EMBREE_COMPACT_POLYS)
- template<> template<> __forceinline const vuint<4>& TriangleMi<4>::getVertexOffset<0>() const { return v0_; }
- template<> template<> __forceinline const vuint<4>& TriangleMi<4>::getVertexOffset<1>() const { return v1_; }
- template<> template<> __forceinline const vuint<4>& TriangleMi<4>::getVertexOffset<2>() const { return v2_; }
-#endif
-
- template<>
- __forceinline void TriangleMi<4>::gather(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- const Scene* const scene) const
- {
- const Triangle tri0 = loadTriangle(0,scene);
- const Triangle tri1 = loadTriangle(1,scene);
- const Triangle tri2 = loadTriangle(2,scene);
- const Triangle tri3 = loadTriangle(3,scene);
- transpose(tri0.v0,tri1.v0,tri2.v0,tri3.v0,p0.x,p0.y,p0.z);
- transpose(tri0.v1,tri1.v1,tri2.v1,tri3.v1,p1.x,p1.y,p1.z);
- transpose(tri0.v2,tri1.v2,tri2.v2,tri3.v2,p2.x,p2.y,p2.z);
- }
-
- template<>
- __forceinline void TriangleMi<4>::gather(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- const TriangleMesh* mesh,
- const Scene *const scene,
- const int itime) const
- {
- const Triangle tri0 = loadTriangle(0,itime,mesh);
- const Triangle tri1 = loadTriangle(1,itime,mesh);
- const Triangle tri2 = loadTriangle(2,itime,mesh);
- const Triangle tri3 = loadTriangle(3,itime,mesh);
- transpose(tri0.v0,tri1.v0,tri2.v0,tri3.v0,p0.x,p0.y,p0.z);
- transpose(tri0.v1,tri1.v1,tri2.v1,tri3.v1,p1.x,p1.y,p1.z);
- transpose(tri0.v2,tri1.v2,tri2.v2,tri3.v2,p2.x,p2.y,p2.z);
- }
-
- template<>
- __forceinline void TriangleMi<4>::gather(Vec3vf4& p0,
- Vec3vf4& p1,
- Vec3vf4& p2,
- const Scene *const scene,
- const float time) const
- {
- const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(0)); // in mblur mode all geometries are identical
-
- float ftime;
- const int itime = mesh->timeSegment(time, ftime);
-
- Vec3vf4 a0,a1,a2; gather(a0,a1,a2,mesh,scene,itime);
- Vec3vf4 b0,b1,b2; gather(b0,b1,b2,mesh,scene,itime+1);
- p0 = lerp(a0,b0,vfloat4(ftime));
- p1 = lerp(a1,b1,vfloat4(ftime));
- p2 = lerp(a2,b2,vfloat4(ftime));
- }
- }
-
- template<int M>
- typename TriangleMi<M>::Type TriangleMi<M>::type;
-
- typedef TriangleMi<4> Triangle4i;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/trianglei_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/trianglei_intersector.h
deleted file mode 100644
index e2f106a62c..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/trianglei_intersector.h
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "trianglei.h"
-#include "triangle_intersector_moeller.h"
-#include "triangle_intersector_pluecker.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Intersects M triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMiIntersector1Moeller
- {
- typedef TriangleMi<M> Primitive;
- typedef MoellerTrumboreIntersector1<Mx> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
- pre.intersect(ray,v0,v1,v2,/*UVIdentity<Mx>(),*/Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
- return pre.intersect(ray,v0,v1,v2,/*UVIdentity<Mx>(),*/Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
- /*! Intersects M triangles with K rays */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMiIntersectorKMoeller
- {
- typedef TriangleMi<M> Primitive;
- typedef MoellerTrumboreIntersectorK<Mx,K> Precalculations;
-
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri)
- {
- const Scene* scene = context->scene;
- for (size_t i=0; i<Primitive::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),RayHitK<K>::size());
- const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene);
- const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene);
- const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene);
- pre.intersectK(valid_i,ray,v0,v1,v2,/*UVIdentity<K>(),*/IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri)
- {
- vbool<K> valid0 = valid_i;
- const Scene* scene = context->scene;
-
- for (size_t i=0; i<Primitive::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid_i),RayHitK<K>::size());
- const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene);
- const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene);
- const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene);
- pre.intersectK(valid0,ray,v0,v1,v2,/*UVIdentity<K>(),*/OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
- pre.intersect(ray,k,v0,v1,v2,/*UVIdentity<Mx>(),*/Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
- return pre.intersect(ray,k,v0,v1,v2,/*UVIdentity<Mx>(),*/Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
- };
-
- /*! Intersects M triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMiIntersector1Pluecker
- {
- typedef TriangleMi<M> Primitive;
- typedef PlueckerIntersector1<Mx> Precalculations;
-
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
- pre.intersect(ray,v0,v1,v2,UVIdentity<Mx>(),Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
- return pre.intersect(ray,v0,v1,v2,UVIdentity<Mx>(),Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
- /*! Intersects M triangles with K rays */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMiIntersectorKPluecker
- {
- typedef TriangleMi<M> Primitive;
- typedef PlueckerIntersectorK<Mx,K> Precalculations;
-
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri)
- {
- const Scene* scene = context->scene;
- for (size_t i=0; i<Primitive::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),RayHitK<K>::size());
- const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene);
- const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene);
- const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene);
- pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri)
- {
- vbool<K> valid0 = valid_i;
- const Scene* scene = context->scene;
-
- for (size_t i=0; i<Primitive::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid_i),RayHitK<K>::size());
- const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene);
- const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene);
- const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene);
- pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
- pre.intersect(ray,k,v0,v1,v2,UVIdentity<Mx>(),Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
- return pre.intersect(ray,k,v0,v1,v2,UVIdentity<Mx>(),Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
- };
-
- /*! Intersects M motion blur triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMiMBIntersector1Moeller
- {
- typedef TriangleMi<M> Primitive;
- typedef MoellerTrumboreIntersector1<Mx> Precalculations;
-
- /*! Intersect a ray with the M triangles and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time());
- pre.intersect(ray,v0,v1,v2,/*UVIdentity<Mx>(),*/Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of M triangles. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time());
- return pre.intersect(ray,v0,v1,v2,/*UVIdentity<Mx>(),*/Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
- /*! Intersects M motion blur triangles with K rays. */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMiMBIntersectorKMoeller
- {
- typedef TriangleMi<M> Primitive;
- typedef MoellerTrumboreIntersectorK<Mx,K> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri)
- {
- for (size_t i=0; i<TriangleMi<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- Vec3vf<K> v0,v1,v2; tri.gather(valid_i,v0,v1,v2,i,context->scene,ray.time());
- pre.intersectK(valid_i,ray,v0,v1,v2,/*UVIdentity<K>(),*/IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri)
- {
- vbool<K> valid0 = valid_i;
- for (size_t i=0; i<TriangleMi<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- Vec3vf<K> v0,v1,v2; tri.gather(valid_i,v0,v1,v2,i,context->scene,ray.time());
- pre.intersectK(valid0,ray,v0,v1,v2,/*UVIdentity<K>(),*/OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]);
- pre.intersect(ray,k,v0,v1,v2,/*UVIdentity<Mx>(),*/Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]);
- return pre.intersect(ray,k,v0,v1,v2,/*UVIdentity<Mx>(),*/Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
- };
-
- /*! Intersects M motion blur triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMiMBIntersector1Pluecker
- {
- typedef TriangleMi<M> Primitive;
- typedef PlueckerIntersector1<Mx> Precalculations;
-
- /*! Intersect a ray with the M triangles and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time());
- pre.intersect(ray,v0,v1,v2,UVIdentity<Mx>(),Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of M triangles. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time());
- return pre.intersect(ray,v0,v1,v2,UVIdentity<Mx>(),Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
- /*! Intersects M motion blur triangles with K rays. */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMiMBIntersectorKPluecker
- {
- typedef TriangleMi<M> Primitive;
- typedef PlueckerIntersectorK<Mx,K> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri)
- {
- for (size_t i=0; i<TriangleMi<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- Vec3vf<K> v0,v1,v2; tri.gather(valid_i,v0,v1,v2,i,context->scene,ray.time());
- pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri)
- {
- vbool<K> valid0 = valid_i;
- for (size_t i=0; i<TriangleMi<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- Vec3vf<K> v0,v1,v2; tri.gather(valid_i,v0,v1,v2,i,context->scene,ray.time());
- pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]);
- pre.intersect(ray,k,v0,v1,v2,UVIdentity<Mx>(),Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]);
- return pre.intersect(ray,k,v0,v1,v2,UVIdentity<Mx>(),Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/trianglev.h b/thirdparty/embree-aarch64/kernels/geometry/trianglev.h
deleted file mode 100644
index 19af389e73..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/trianglev.h
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-
-namespace embree
-{
- /* Stores the vertices of M triangles in struct of array layout */
- template <int M>
- struct TriangleMv
- {
- public:
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
- static Type type;
-
- public:
-
- /* Returns maximum number of stored triangles */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
-
- public:
-
- /* Default constructor */
- __forceinline TriangleMv() {}
-
- /* Construction from vertices and IDs */
- __forceinline TriangleMv(const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const vuint<M>& geomIDs, const vuint<M>& primIDs)
- : v0(v0), v1(v1), v2(v2), geomIDs(geomIDs), primIDs(primIDs) {}
-
- /* Returns a mask that tells which triangles are valid */
- __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); }
-
- /* Returns true if the specified triangle is valid */
- __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; }
-
- /* Returns the number of stored triangles */
- __forceinline size_t size() const { return bsf(~movemask(valid())); }
-
- /* Returns the geometry IDs */
- __forceinline vuint<M>& geomID() { return geomIDs; }
- __forceinline const vuint<M>& geomID() const { return geomIDs; }
- __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
-
- /* Returns the primitive IDs */
- __forceinline vuint<M>& primID() { return primIDs; }
- __forceinline const vuint<M>& primID() const { return primIDs; }
- __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
-
- /* Calculate the bounds of the triangles */
- __forceinline BBox3fa bounds() const
- {
- Vec3vf<M> lower = min(v0,v1,v2);
- Vec3vf<M> upper = max(v0,v1,v2);
- vbool<M> mask = valid();
- lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
- lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
- lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
- upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
- upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
- upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
- return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
- Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
- }
-
- /* Non temporal store */
- __forceinline static void store_nt(TriangleMv* dst, const TriangleMv& src)
- {
- vfloat<M>::store_nt(&dst->v0.x,src.v0.x);
- vfloat<M>::store_nt(&dst->v0.y,src.v0.y);
- vfloat<M>::store_nt(&dst->v0.z,src.v0.z);
- vfloat<M>::store_nt(&dst->v1.x,src.v1.x);
- vfloat<M>::store_nt(&dst->v1.y,src.v1.y);
- vfloat<M>::store_nt(&dst->v1.z,src.v1.z);
- vfloat<M>::store_nt(&dst->v2.x,src.v2.x);
- vfloat<M>::store_nt(&dst->v2.y,src.v2.y);
- vfloat<M>::store_nt(&dst->v2.z,src.v2.z);
- vuint<M>::store_nt(&dst->geomIDs,src.geomIDs);
- vuint<M>::store_nt(&dst->primIDs,src.primIDs);
- }
-
- /* Fill triangle from triangle list */
- __forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
- {
- vuint<M> vgeomID = -1, vprimID = -1;
- Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
-
- for (size_t i=0; i<M && begin<end; i++, begin++)
- {
- const PrimRef& prim = prims[begin];
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(geomID);
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- const Vec3fa& p0 = mesh->vertex(tri.v[0]);
- const Vec3fa& p1 = mesh->vertex(tri.v[1]);
- const Vec3fa& p2 = mesh->vertex(tri.v[2]);
- vgeomID [i] = geomID;
- vprimID [i] = primID;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- }
- TriangleMv::store_nt(this,TriangleMv(v0,v1,v2,vgeomID,vprimID));
- }
-
- /* Updates the primitive */
- __forceinline BBox3fa update(TriangleMesh* mesh)
- {
- BBox3fa bounds = empty;
- vuint<M> vgeomID = -1, vprimID = -1;
- Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
-
- for (size_t i=0; i<M; i++)
- {
- if (primID(i) == -1) break;
- const unsigned geomId = geomID(i);
- const unsigned primId = primID(i);
- const TriangleMesh::Triangle& tri = mesh->triangle(primId);
- const Vec3fa p0 = mesh->vertex(tri.v[0]);
- const Vec3fa p1 = mesh->vertex(tri.v[1]);
- const Vec3fa p2 = mesh->vertex(tri.v[2]);
- bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2)));
- vgeomID [i] = geomId;
- vprimID [i] = primId;
- v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
- v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
- v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
- }
- new (this) TriangleMv(v0,v1,v2,vgeomID,vprimID);
- return bounds;
- }
-
- public:
- Vec3vf<M> v0; // 1st vertex of the triangles
- Vec3vf<M> v1; // 2nd vertex of the triangles
- Vec3vf<M> v2; // 3rd vertex of the triangles
- private:
- vuint<M> geomIDs; // geometry ID
- vuint<M> primIDs; // primitive ID
- };
-
- template<int M>
- typename TriangleMv<M>::Type TriangleMv<M>::type;
-
- typedef TriangleMv<4> Triangle4v;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/trianglev_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/trianglev_intersector.h
deleted file mode 100644
index 6af0d5a11c..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/trianglev_intersector.h
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "triangle.h"
-#include "triangle_intersector_pluecker.h"
-#include "triangle_intersector_moeller.h"
-#include "triangle_intersector_woop.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Intersects M triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMvIntersector1Moeller
- {
- typedef TriangleMv<M> Primitive;
- typedef MoellerTrumboreIntersector1<Mx> Precalculations;
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity<Mx>(),*/Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity<Mx>(),*/Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
-
- template<int M, int Mx, bool filter>
- struct TriangleMvIntersector1Woop
- {
- typedef TriangleMv<M> Primitive;
- typedef WoopIntersector1<Mx> intersec;
- typedef WoopPrecalculations1<M> Precalculations;
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
-
- /*! Intersects M triangles with K rays */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMvIntersectorKMoeller
- {
- typedef TriangleMv<M> Primitive;
- typedef MoellerTrumboreIntersectorK<Mx,K> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri)
- {
- for (size_t i=0; i<M; i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i);
- const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i);
- const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i);
- pre.intersectK(valid_i,ray,v0,v1,v2,/*UVIdentity<K>(),*/IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri)
- {
- vbool<K> valid0 = valid_i;
-
- for (size_t i=0; i<M; i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i);
- const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i);
- const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i);
- pre.intersectK(valid0,ray,v0,v1,v2,/*UVIdentity<K>(),*/OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity<Mx>(),*/Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M,Mx
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity<Mx>(),*/Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M,Mx
- }
- };
-
- /*! Intersects M triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMvIntersector1Pluecker
- {
- typedef TriangleMv<M> Primitive;
- typedef PlueckerIntersector1<Mx> Precalculations;
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity<Mx>(),Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity<Mx>(),Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
- /*! Intersects M triangles with K rays */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMvIntersectorKPluecker
- {
- typedef TriangleMv<M> Primitive;
- typedef PlueckerIntersectorK<Mx,K> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri)
- {
- for (size_t i=0; i<M; i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i);
- const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i);
- const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i);
- pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri)
- {
- vbool<K> valid0 = valid_i;
-
- for (size_t i=0; i<M; i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i);
- const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i);
- const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i);
- pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity<Mx>(),Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M,Mx
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity<Mx>(),Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M,Mx
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/trianglev_mb.h b/thirdparty/embree-aarch64/kernels/geometry/trianglev_mb.h
deleted file mode 100644
index 63137aee16..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/trianglev_mb.h
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "primitive.h"
-
-namespace embree
-{
- /* Stores the vertices of M triangles in struct of array layout */
- template<int M>
- struct TriangleMvMB
- {
- public:
- struct Type : public PrimitiveType
- {
- const char* name() const;
- size_t sizeActive(const char* This) const;
- size_t sizeTotal(const char* This) const;
- size_t getBytes(const char* This) const;
- };
-
- static Type type;
-
- public:
-
- /* primitive supports single time segments */
- static const bool singleTimeSegment = true;
-
- /* Returns maximum number of stored triangles */
- static __forceinline size_t max_size() { return M; }
-
- /* Returns required number of primitive blocks for N primitives */
- static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
-
- public:
-
- /* Default constructor */
- __forceinline TriangleMvMB() {}
-
- /* Construction from vertices and IDs */
- __forceinline TriangleMvMB(const Vec3vf<M>& a0, const Vec3vf<M>& a1,
- const Vec3vf<M>& b0, const Vec3vf<M>& b1,
- const Vec3vf<M>& c0, const Vec3vf<M>& c1,
- const vuint<M>& geomIDs, const vuint<M>& primIDs)
- : v0(a0), v1(b0), v2(c0), dv0(a1-a0), dv1(b1-b0), dv2(c1-c0), geomIDs(geomIDs), primIDs(primIDs) {}
-
- /* Returns a mask that tells which triangles are valid */
- __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); }
-
- /* Returns if the specified triangle is valid */
- __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; }
-
- /* Returns the number of stored triangles */
- __forceinline size_t size() const { return bsf(~movemask(valid())); }
-
- /* Returns the geometry IDs */
- __forceinline vuint<M>& geomID() { return geomIDs; }
- __forceinline const vuint<M>& geomID() const { return geomIDs; }
- __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
-
- /* Returns the primitive IDs */
- __forceinline vuint<M>& primID() { return primIDs; }
- __forceinline const vuint<M>& primID() const { return primIDs; }
- __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
-
- /* Calculate the bounds of the triangles at t0 */
- __forceinline BBox3fa bounds0() const
- {
- Vec3vf<M> lower = min(v0,v1,v2);
- Vec3vf<M> upper = max(v0,v1,v2);
- const vbool<M> mask = valid();
- lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
- lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
- lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
- upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
- upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
- upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
- return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
- Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
- }
-
- /* Calculate the bounds of the triangles at t1 */
- __forceinline BBox3fa bounds1() const
- {
- const Vec3vf<M> p0 = v0+dv0;
- const Vec3vf<M> p1 = v1+dv1;
- const Vec3vf<M> p2 = v2+dv2;
- Vec3vf<M> lower = min(p0,p1,p2);
- Vec3vf<M> upper = max(p0,p1,p2);
- const vbool<M> mask = valid();
- lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
- lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
- lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
- upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
- upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
- upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
- return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
- Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
- }
-
- /* Calculate the linear bounds of the primitive */
- __forceinline LBBox3fa linearBounds() const {
- return LBBox3fa(bounds0(),bounds1());
- }
-
- /* Fill triangle from triangle list */
- __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
- {
- vuint<M> vgeomID = -1, vprimID = -1;
- Vec3vf<M> va0 = zero, vb0 = zero, vc0 = zero;
- Vec3vf<M> va1 = zero, vb1 = zero, vc1 = zero;
-
- BBox3fa bounds0 = empty;
- BBox3fa bounds1 = empty;
-
- for (size_t i=0; i<M && begin<end; i++, begin++)
- {
- const PrimRef& prim = prims[begin];
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(geomID);
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- const Vec3fa& a0 = mesh->vertex(tri.v[0],itime+0); bounds0.extend(a0);
- const Vec3fa& a1 = mesh->vertex(tri.v[0],itime+1); bounds1.extend(a1);
- const Vec3fa& b0 = mesh->vertex(tri.v[1],itime+0); bounds0.extend(b0);
- const Vec3fa& b1 = mesh->vertex(tri.v[1],itime+1); bounds1.extend(b1);
- const Vec3fa& c0 = mesh->vertex(tri.v[2],itime+0); bounds0.extend(c0);
- const Vec3fa& c1 = mesh->vertex(tri.v[2],itime+1); bounds1.extend(c1);
- vgeomID [i] = geomID;
- vprimID [i] = primID;
- va0.x[i] = a0.x; va0.y[i] = a0.y; va0.z[i] = a0.z;
- va1.x[i] = a1.x; va1.y[i] = a1.y; va1.z[i] = a1.z;
- vb0.x[i] = b0.x; vb0.y[i] = b0.y; vb0.z[i] = b0.z;
- vb1.x[i] = b1.x; vb1.y[i] = b1.y; vb1.z[i] = b1.z;
- vc0.x[i] = c0.x; vc0.y[i] = c0.y; vc0.z[i] = c0.z;
- vc1.x[i] = c1.x; vc1.y[i] = c1.y; vc1.z[i] = c1.z;
- }
- new (this) TriangleMvMB(va0,va1,vb0,vb1,vc0,vc1,vgeomID,vprimID);
- return LBBox3fa(bounds0,bounds1);
- }
-
- /* Fill triangle from triangle list */
- __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
- {
- vuint<M> vgeomID = -1, vprimID = -1;
- Vec3vf<M> va0 = zero, vb0 = zero, vc0 = zero;
- Vec3vf<M> va1 = zero, vb1 = zero, vc1 = zero;
-
- LBBox3fa allBounds = empty;
- for (size_t i=0; i<M && begin<end; i++, begin++)
- {
- const PrimRefMB& prim = prims[begin];
- const unsigned geomID = prim.geomID();
- const unsigned primID = prim.primID();
- const TriangleMesh* const mesh = scene->get<TriangleMesh>(geomID);
- const range<int> itime_range = mesh->timeSegmentRange(time_range);
- assert(itime_range.size() == 1);
- const int ilower = itime_range.begin();
- const TriangleMesh::Triangle& tri = mesh->triangle(primID);
- allBounds.extend(mesh->linearBounds(primID, time_range));
- const Vec3fa& a0 = mesh->vertex(tri.v[0],ilower+0);
- const Vec3fa& a1 = mesh->vertex(tri.v[0],ilower+1);
- const Vec3fa& b0 = mesh->vertex(tri.v[1],ilower+0);
- const Vec3fa& b1 = mesh->vertex(tri.v[1],ilower+1);
- const Vec3fa& c0 = mesh->vertex(tri.v[2],ilower+0);
- const Vec3fa& c1 = mesh->vertex(tri.v[2],ilower+1);
- const BBox1f time_range_v(mesh->timeStep(ilower+0),mesh->timeStep(ilower+1));
- auto a01 = globalLinear(std::make_pair(a0,a1),time_range_v);
- auto b01 = globalLinear(std::make_pair(b0,b1),time_range_v);
- auto c01 = globalLinear(std::make_pair(c0,c1),time_range_v);
- vgeomID [i] = geomID;
- vprimID [i] = primID;
- va0.x[i] = a01.first .x; va0.y[i] = a01.first .y; va0.z[i] = a01.first .z;
- va1.x[i] = a01.second.x; va1.y[i] = a01.second.y; va1.z[i] = a01.second.z;
- vb0.x[i] = b01.first .x; vb0.y[i] = b01.first .y; vb0.z[i] = b01.first .z;
- vb1.x[i] = b01.second.x; vb1.y[i] = b01.second.y; vb1.z[i] = b01.second.z;
- vc0.x[i] = c01.first .x; vc0.y[i] = c01.first .y; vc0.z[i] = c01.first .z;
- vc1.x[i] = c01.second.x; vc1.y[i] = c01.second.y; vc1.z[i] = c01.second.z;
- }
- new (this) TriangleMvMB(va0,va1,vb0,vb1,vc0,vc1,vgeomID,vprimID);
- return allBounds;
- }
-
- public:
- Vec3vf<M> v0; // 1st vertex of the triangles
- Vec3vf<M> v1; // 2nd vertex of the triangles
- Vec3vf<M> v2; // 3rd vertex of the triangles
- Vec3vf<M> dv0; // difference vector between time steps t0 and t1 for first vertex
- Vec3vf<M> dv1; // difference vector between time steps t0 and t1 for second vertex
- Vec3vf<M> dv2; // difference vector between time steps t0 and t1 for third vertex
- private:
- vuint<M> geomIDs; // geometry ID
- vuint<M> primIDs; // primitive ID
- };
-
- template<int M>
- typename TriangleMvMB<M>::Type TriangleMvMB<M>::type;
-
- typedef TriangleMvMB<4> Triangle4vMB;
-}
diff --git a/thirdparty/embree-aarch64/kernels/geometry/trianglev_mb_intersector.h b/thirdparty/embree-aarch64/kernels/geometry/trianglev_mb_intersector.h
deleted file mode 100644
index 35a260d826..0000000000
--- a/thirdparty/embree-aarch64/kernels/geometry/trianglev_mb_intersector.h
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "triangle.h"
-#include "intersector_epilog.h"
-
-namespace embree
-{
- namespace isa
- {
- /*! Intersects M motion blur triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMvMBIntersector1Moeller
- {
- typedef TriangleMvMB<M> Primitive;
- typedef MoellerTrumboreIntersector1<Mx> Precalculations;
-
- /*! Intersect a ray with the M triangles and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- const Vec3vf<Mx> time(ray.time());
- const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
- const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
- const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
- pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of M triangles. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const Vec3vf<Mx> time(ray.time());
- const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
- const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
- const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
- return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
- /*! Intersects M motion blur triangles with K rays. */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMvMBIntersectorKMoeller
- {
- typedef TriangleMvMB<M> Primitive;
- typedef MoellerTrumboreIntersectorK<Mx,K> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> time(ray.time());
- const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
- const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
- const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
- pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- vbool<K> valid0 = valid_i;
-
- for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- const Vec3vf<K> time(ray.time());
- const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
- const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
- const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
- pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- const Vec3vf<Mx> time(ray.time()[k]);
- const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
- const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
- const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
- pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const Vec3vf<Mx> time(ray.time()[k]);
- const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
- const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
- const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
- return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
- };
-
- /*! Intersects M motion blur triangles with 1 ray */
- template<int M, int Mx, bool filter>
- struct TriangleMvMBIntersector1Pluecker
- {
- typedef TriangleMvMB<M> Primitive;
- typedef PlueckerIntersector1<Mx> Precalculations;
-
- /*! Intersect a ray with the M triangles and updates the hit. */
- static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- const Vec3vf<Mx> time(ray.time());
- const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
- const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
- const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
- pre.intersect(ray,v0,v1,v2,UVIdentity<Mx>(),Intersect1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of M triangles. */
- static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const Vec3vf<Mx> time(ray.time());
- const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
- const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
- const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
- return pre.intersect(ray,v0,v1,v2,UVIdentity<Mx>(),Occluded1EpilogM<M,Mx,filter>(ray,context,tri.geomID(),tri.primID()));
- }
-
- static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
- {
- return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
- }
- };
-
- /*! Intersects M motion blur triangles with K rays. */
- template<int M, int Mx, int K, bool filter>
- struct TriangleMvMBIntersectorKPluecker
- {
- typedef TriangleMvMB<M> Primitive;
- typedef PlueckerIntersectorK<Mx,K> Precalculations;
-
- /*! Intersects K rays with M triangles. */
- static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(normal.trav_prims,1,popcnt(valid_i),K);
- const Vec3vf<K> time(ray.time());
- const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
- const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
- const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
- pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
- }
- }
-
- /*! Test for K rays if they are occluded by any of the M triangles. */
- static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- vbool<K> valid0 = valid_i;
-
- for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
- {
- if (!tri.valid(i)) break;
- STAT3(shadow.trav_prims,1,popcnt(valid0),K);
- const Vec3vf<K> time(ray.time());
- const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
- const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
- const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
- pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
- if (none(valid0)) break;
- }
- return !valid0;
- }
-
- /*! Intersect a ray with M triangles and updates the hit. */
- static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- STAT3(normal.trav_prims,1,1,1);
- const Vec3vf<Mx> time(ray.time()[k]);
- const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
- const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
- const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
- pre.intersect(ray,k,v0,v1,v2,UVIdentity<Mx>(),Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
-
- /*! Test if the ray is occluded by one of the M triangles. */
- static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
- {
- STAT3(shadow.trav_prims,1,1,1);
- const Vec3vf<Mx> time(ray.time()[k]);
- const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
- const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
- const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
- return pre.intersect(ray,k,v0,v1,v2,UVIdentity<Mx>(),Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
- }
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/hash.h b/thirdparty/embree-aarch64/kernels/hash.h
deleted file mode 100644
index 4abbe203d6..0000000000
--- a/thirdparty/embree-aarch64/kernels/hash.h
+++ /dev/null
@@ -1,5 +0,0 @@
-
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#define RTC_HASH "6ef362f99af80c9dfe8dd2bfc582d9067897edc6"
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/bezier_curve.h b/thirdparty/embree-aarch64/kernels/subdiv/bezier_curve.h
deleted file mode 100644
index c0e78820f8..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/bezier_curve.h
+++ /dev/null
@@ -1,669 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-#include "../common/scene_curves.h"
-
-namespace embree
-{
- class BezierBasis
- {
- public:
-
- template<typename T>
- static __forceinline Vec4<T> eval(const T& u)
- {
- const T t1 = u;
- const T t0 = 1.0f-t1;
- const T B0 = t0 * t0 * t0;
- const T B1 = 3.0f * t1 * (t0 * t0);
- const T B2 = 3.0f * (t1 * t1) * t0;
- const T B3 = t1 * t1 * t1;
- return Vec4<T>(B0,B1,B2,B3);
- }
-
- template<typename T>
- static __forceinline Vec4<T> derivative(const T& u)
- {
- const T t1 = u;
- const T t0 = 1.0f-t1;
- const T B0 = -(t0*t0);
- const T B1 = madd(-2.0f,t0*t1,t0*t0);
- const T B2 = msub(+2.0f,t0*t1,t1*t1);
- const T B3 = +(t1*t1);
- return T(3.0f)*Vec4<T>(B0,B1,B2,B3);
- }
-
- template<typename T>
- static __forceinline Vec4<T> derivative2(const T& u)
- {
- const T t1 = u;
- const T t0 = 1.0f-t1;
- const T B0 = t0;
- const T B1 = madd(-2.0f,t0,t1);
- const T B2 = madd(-2.0f,t1,t0);
- const T B3 = t1;
- return T(6.0f)*Vec4<T>(B0,B1,B2,B3);
- }
- };
-
- struct PrecomputedBezierBasis
- {
- enum { N = 16 };
- public:
- PrecomputedBezierBasis() {}
- PrecomputedBezierBasis(int shift);
-
- /* basis for bezier evaluation */
- public:
- float c0[N+1][N+1];
- float c1[N+1][N+1];
- float c2[N+1][N+1];
- float c3[N+1][N+1];
-
- /* basis for bezier derivative evaluation */
- public:
- float d0[N+1][N+1];
- float d1[N+1][N+1];
- float d2[N+1][N+1];
- float d3[N+1][N+1];
- };
- extern PrecomputedBezierBasis bezier_basis0;
- extern PrecomputedBezierBasis bezier_basis1;
-
-
- template<typename V>
- struct LinearBezierCurve
- {
- V v0,v1;
-
- __forceinline LinearBezierCurve () {}
-
- __forceinline LinearBezierCurve (const LinearBezierCurve& other)
- : v0(other.v0), v1(other.v1) {}
-
- __forceinline LinearBezierCurve& operator= (const LinearBezierCurve& other) {
- v0 = other.v0; v1 = other.v1; return *this;
- }
-
- __forceinline LinearBezierCurve (const V& v0, const V& v1)
- : v0(v0), v1(v1) {}
-
- __forceinline V begin() const { return v0; }
- __forceinline V end () const { return v1; }
-
- bool hasRoot() const;
-
- friend embree_ostream operator<<(embree_ostream cout, const LinearBezierCurve& a) {
- return cout << "LinearBezierCurve (" << a.v0 << ", " << a.v1 << ")";
- }
- };
-
- template<> __forceinline bool LinearBezierCurve<Interval1f>::hasRoot() const {
- return numRoots(v0,v1);
- }
-
- template<typename V>
- struct QuadraticBezierCurve
- {
- V v0,v1,v2;
-
- __forceinline QuadraticBezierCurve () {}
-
- __forceinline QuadraticBezierCurve (const QuadraticBezierCurve& other)
- : v0(other.v0), v1(other.v1), v2(other.v2) {}
-
- __forceinline QuadraticBezierCurve& operator= (const QuadraticBezierCurve& other) {
- v0 = other.v0; v1 = other.v1; v2 = other.v2; return *this;
- }
-
- __forceinline QuadraticBezierCurve (const V& v0, const V& v1, const V& v2)
- : v0(v0), v1(v1), v2(v2) {}
-
- __forceinline V begin() const { return v0; }
- __forceinline V end () const { return v2; }
-
- __forceinline V interval() const {
- return merge(v0,v1,v2);
- }
-
- __forceinline BBox<V> bounds() const {
- return merge(BBox<V>(v0),BBox<V>(v1),BBox<V>(v2));
- }
-
- friend embree_ostream operator<<(embree_ostream cout, const QuadraticBezierCurve& a) {
- return cout << "QuadraticBezierCurve ( (" << a.u.lower << ", " << a.u.upper << "), " << a.v0 << ", " << a.v1 << ", " << a.v2 << ")";
- }
- };
-
-
- typedef QuadraticBezierCurve<float> QuadraticBezierCurve1f;
- typedef QuadraticBezierCurve<Vec2fa> QuadraticBezierCurve2fa;
- typedef QuadraticBezierCurve<Vec3fa> QuadraticBezierCurve3fa;
-
- template<typename Vertex>
- struct CubicBezierCurve
- {
- Vertex v0,v1,v2,v3;
-
- __forceinline CubicBezierCurve() {}
-
- template<typename T1>
- __forceinline CubicBezierCurve (const CubicBezierCurve<T1>& other)
- : v0(other.v0), v1(other.v1), v2(other.v2), v3(other.v3) {}
-
- __forceinline CubicBezierCurve& operator= (const CubicBezierCurve& other) {
- v0 = other.v0; v1 = other.v1; v2 = other.v2; v3 = other.v3; return *this;
- }
-
- __forceinline CubicBezierCurve(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3)
- : v0(v0), v1(v1), v2(v2), v3(v3) {}
-
- __forceinline Vertex begin() const {
- return v0;
- }
-
- __forceinline Vertex end() const {
- return v3;
- }
-
- __forceinline Vertex center() const {
- return 0.25f*(v0+v1+v2+v3);
- }
-
- __forceinline Vertex begin_direction() const {
- return v1-v0;
- }
-
- __forceinline Vertex end_direction() const {
- return v3-v2;
- }
-
- __forceinline CubicBezierCurve<float> xfm(const Vertex& dx) const {
- return CubicBezierCurve<float>(dot(v0,dx),dot(v1,dx),dot(v2,dx),dot(v3,dx));
- }
-
- __forceinline CubicBezierCurve<vfloatx> vxfm(const Vertex& dx) const {
- return CubicBezierCurve<vfloatx>(dot(v0,dx),dot(v1,dx),dot(v2,dx),dot(v3,dx));
- }
-
- __forceinline CubicBezierCurve<float> xfm(const Vertex& dx, const Vertex& p) const {
- return CubicBezierCurve<float>(dot(v0-p,dx),dot(v1-p,dx),dot(v2-p,dx),dot(v3-p,dx));
- }
-
- __forceinline CubicBezierCurve<Vec3fa> xfm(const LinearSpace3fa& space) const
- {
- const Vec3fa q0 = xfmVector(space,v0);
- const Vec3fa q1 = xfmVector(space,v1);
- const Vec3fa q2 = xfmVector(space,v2);
- const Vec3fa q3 = xfmVector(space,v3);
- return CubicBezierCurve<Vec3fa>(q0,q1,q2,q3);
- }
-
- __forceinline CubicBezierCurve<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p) const
- {
- const Vec3fa q0 = xfmVector(space,v0-p);
- const Vec3fa q1 = xfmVector(space,v1-p);
- const Vec3fa q2 = xfmVector(space,v2-p);
- const Vec3fa q3 = xfmVector(space,v3-p);
- return CubicBezierCurve<Vec3fa>(q0,q1,q2,q3);
- }
-
- __forceinline CubicBezierCurve<Vec3ff> xfm_pr(const LinearSpace3fa& space, const Vec3fa& p) const
- {
- const Vec3ff q0(xfmVector(space,(Vec3fa)v0-p), v0.w);
- const Vec3ff q1(xfmVector(space,(Vec3fa)v1-p), v1.w);
- const Vec3ff q2(xfmVector(space,(Vec3fa)v2-p), v2.w);
- const Vec3ff q3(xfmVector(space,(Vec3fa)v3-p), v3.w);
- return CubicBezierCurve<Vec3ff>(q0,q1,q2,q3);
- }
-
- __forceinline CubicBezierCurve<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p, const float s) const
- {
- const Vec3fa q0 = xfmVector(space,s*(v0-p));
- const Vec3fa q1 = xfmVector(space,s*(v1-p));
- const Vec3fa q2 = xfmVector(space,s*(v2-p));
- const Vec3fa q3 = xfmVector(space,s*(v3-p));
- return CubicBezierCurve<Vec3fa>(q0,q1,q2,q3);
- }
-
- __forceinline int maxRoots() const;
-
- __forceinline BBox<Vertex> bounds() const {
- return merge(BBox<Vertex>(v0),BBox<Vertex>(v1),BBox<Vertex>(v2),BBox<Vertex>(v3));
- }
-
- __forceinline friend CubicBezierCurve operator +( const CubicBezierCurve& a, const CubicBezierCurve& b ) {
- return CubicBezierCurve(a.v0+b.v0,a.v1+b.v1,a.v2+b.v2,a.v3+b.v3);
- }
-
- __forceinline friend CubicBezierCurve operator -( const CubicBezierCurve& a, const CubicBezierCurve& b ) {
- return CubicBezierCurve(a.v0-b.v0,a.v1-b.v1,a.v2-b.v2,a.v3-b.v3);
- }
-
- __forceinline friend CubicBezierCurve operator -( const CubicBezierCurve& a, const Vertex& b ) {
- return CubicBezierCurve(a.v0-b,a.v1-b,a.v2-b,a.v3-b);
- }
-
- __forceinline friend CubicBezierCurve operator *( const Vertex& a, const CubicBezierCurve& b ) {
- return CubicBezierCurve(a*b.v0,a*b.v1,a*b.v2,a*b.v3);
- }
-
- __forceinline friend CubicBezierCurve cmadd( const Vertex& a, const CubicBezierCurve& b, const CubicBezierCurve& c) {
- return CubicBezierCurve(madd(a,b.v0,c.v0),madd(a,b.v1,c.v1),madd(a,b.v2,c.v2),madd(a,b.v3,c.v3));
- }
-
- __forceinline friend CubicBezierCurve clerp ( const CubicBezierCurve& a, const CubicBezierCurve& b, const Vertex& t ) {
- return cmadd((Vertex(1.0f)-t),a,t*b);
- }
-
- __forceinline friend CubicBezierCurve merge ( const CubicBezierCurve& a, const CubicBezierCurve& b ) {
- return CubicBezierCurve(merge(a.v0,b.v0),merge(a.v1,b.v1),merge(a.v2,b.v2),merge(a.v3,b.v3));
- }
-
- __forceinline void split(CubicBezierCurve& left, CubicBezierCurve& right, const float t = 0.5f) const
- {
- const Vertex p00 = v0;
- const Vertex p01 = v1;
- const Vertex p02 = v2;
- const Vertex p03 = v3;
-
- const Vertex p10 = lerp(p00,p01,t);
- const Vertex p11 = lerp(p01,p02,t);
- const Vertex p12 = lerp(p02,p03,t);
- const Vertex p20 = lerp(p10,p11,t);
- const Vertex p21 = lerp(p11,p12,t);
- const Vertex p30 = lerp(p20,p21,t);
-
- new (&left ) CubicBezierCurve(p00,p10,p20,p30);
- new (&right) CubicBezierCurve(p30,p21,p12,p03);
- }
-
- __forceinline CubicBezierCurve<Vec2vfx> split() const
- {
- const float u0 = 0.0f, u1 = 1.0f;
- const float dscale = (u1-u0)*(1.0f/(3.0f*(VSIZEX-1)));
- const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(VSIZEX-1)));
- Vec2vfx P0, dP0du; evalN(vu0,P0,dP0du); dP0du = dP0du * Vec2vfx(dscale);
- const Vec2vfx P3 = shift_right_1(P0);
- const Vec2vfx dP3du = shift_right_1(dP0du);
- const Vec2vfx P1 = P0 + dP0du;
- const Vec2vfx P2 = P3 - dP3du;
- return CubicBezierCurve<Vec2vfx>(P0,P1,P2,P3);
- }
-
- __forceinline CubicBezierCurve<Vec2vfx> split(const BBox1f& u) const
- {
- const float u0 = u.lower, u1 = u.upper;
- const float dscale = (u1-u0)*(1.0f/(3.0f*(VSIZEX-1)));
- const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(VSIZEX-1)));
- Vec2vfx P0, dP0du; evalN(vu0,P0,dP0du); dP0du = dP0du * Vec2vfx(dscale);
- const Vec2vfx P3 = shift_right_1(P0);
- const Vec2vfx dP3du = shift_right_1(dP0du);
- const Vec2vfx P1 = P0 + dP0du;
- const Vec2vfx P2 = P3 - dP3du;
- return CubicBezierCurve<Vec2vfx>(P0,P1,P2,P3);
- }
-
- __forceinline void eval(float t, Vertex& p, Vertex& dp) const
- {
- const Vertex p00 = v0;
- const Vertex p01 = v1;
- const Vertex p02 = v2;
- const Vertex p03 = v3;
-
- const Vertex p10 = lerp(p00,p01,t);
- const Vertex p11 = lerp(p01,p02,t);
- const Vertex p12 = lerp(p02,p03,t);
- const Vertex p20 = lerp(p10,p11,t);
- const Vertex p21 = lerp(p11,p12,t);
- const Vertex p30 = lerp(p20,p21,t);
-
- p = p30;
- dp = Vertex(3.0f)*(p21-p20);
- }
-
-#if 0
- __forceinline Vertex eval(float t) const
- {
- const Vertex p00 = v0;
- const Vertex p01 = v1;
- const Vertex p02 = v2;
- const Vertex p03 = v3;
-
- const Vertex p10 = lerp(p00,p01,t);
- const Vertex p11 = lerp(p01,p02,t);
- const Vertex p12 = lerp(p02,p03,t);
- const Vertex p20 = lerp(p10,p11,t);
- const Vertex p21 = lerp(p11,p12,t);
- const Vertex p30 = lerp(p20,p21,t);
-
- return p30;
- }
-#else
- __forceinline Vertex eval(const float t) const
- {
- const Vec4<float> b = BezierBasis::eval(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-#endif
-
- __forceinline Vertex eval_dt(float t) const
- {
- const Vertex p00 = v1-v0;
- const Vertex p01 = v2-v1;
- const Vertex p02 = v3-v2;
- const Vertex p10 = lerp(p00,p01,t);
- const Vertex p11 = lerp(p01,p02,t);
- const Vertex p20 = lerp(p10,p11,t);
- return Vertex(3.0f)*p20;
- }
-
- __forceinline Vertex eval_du(const float t) const
- {
- const Vec4<float> b = BezierBasis::derivative(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-
- __forceinline Vertex eval_dudu(const float t) const
- {
- const Vec4<float> b = BezierBasis::derivative2(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-
- __forceinline void evalN(const vfloatx& t, Vec2vfx& p, Vec2vfx& dp) const
- {
- const Vec2vfx p00 = v0;
- const Vec2vfx p01 = v1;
- const Vec2vfx p02 = v2;
- const Vec2vfx p03 = v3;
-
- const Vec2vfx p10 = lerp(p00,p01,t);
- const Vec2vfx p11 = lerp(p01,p02,t);
- const Vec2vfx p12 = lerp(p02,p03,t);
-
- const Vec2vfx p20 = lerp(p10,p11,t);
- const Vec2vfx p21 = lerp(p11,p12,t);
-
- const Vec2vfx p30 = lerp(p20,p21,t);
-
- p = p30;
- dp = vfloatx(3.0f)*(p21-p20);
- }
-
- __forceinline void eval(const float t, Vertex& p, Vertex& dp, Vertex& ddp) const
- {
- const Vertex p00 = v0;
- const Vertex p01 = v1;
- const Vertex p02 = v2;
- const Vertex p03 = v3;
- const Vertex p10 = lerp(p00,p01,t);
- const Vertex p11 = lerp(p01,p02,t);
- const Vertex p12 = lerp(p02,p03,t);
- const Vertex p20 = lerp(p10,p11,t);
- const Vertex p21 = lerp(p11,p12,t);
- const Vertex p30 = lerp(p20,p21,t);
- p = p30;
- dp = 3.0f*(p21-p20);
- ddp = eval_dudu(t);
- }
-
- __forceinline CubicBezierCurve clip(const Interval1f& u1) const
- {
- Vertex f0,df0; eval(u1.lower,f0,df0);
- Vertex f1,df1; eval(u1.upper,f1,df1);
- float s = u1.upper-u1.lower;
- return CubicBezierCurve(f0,f0+s*(1.0f/3.0f)*df0,f1-s*(1.0f/3.0f)*df1,f1);
- }
-
- __forceinline QuadraticBezierCurve<Vertex> derivative() const
- {
- const Vertex q0 = 3.0f*(v1-v0);
- const Vertex q1 = 3.0f*(v2-v1);
- const Vertex q2 = 3.0f*(v3-v2);
- return QuadraticBezierCurve<Vertex>(q0,q1,q2);
- }
-
- __forceinline BBox<Vertex> derivative_bounds(const Interval1f& u1) const
- {
- Vertex f0,df0; eval(u1.lower,f0,df0);
- Vertex f3,df3; eval(u1.upper,f3,df3);
- const float s = u1.upper-u1.lower;
- const Vertex f1 = f0+s*(1.0f/3.0f)*df0;
- const Vertex f2 = f3-s*(1.0f/3.0f)*df3;
- const Vertex q0 = s*df0;
- const Vertex q1 = 3.0f*(f2-f1);
- const Vertex q2 = s*df3;
- return merge(BBox<Vertex>(q0),BBox<Vertex>(q1),BBox<Vertex>(q2));
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = BezierBasis::eval(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval_du(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = BezierBasis::derivative(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval_dudu(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = BezierBasis::derivative2(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline void veval(const vfloat<M>& t, Vec4vf<M>& p, Vec4vf<M>& dp) const
- {
- const Vec4vf<M> p00 = v0;
- const Vec4vf<M> p01 = v1;
- const Vec4vf<M> p02 = v2;
- const Vec4vf<M> p03 = v3;
-
- const Vec4vf<M> p10 = lerp(p00,p01,t);
- const Vec4vf<M> p11 = lerp(p01,p02,t);
- const Vec4vf<M> p12 = lerp(p02,p03,t);
- const Vec4vf<M> p20 = lerp(p10,p11,t);
- const Vec4vf<M> p21 = lerp(p11,p12,t);
- const Vec4vf<M> p30 = lerp(p20,p21,t);
-
- p = p30;
- dp = vfloat<M>(3.0f)*(p21-p20);
- }
-
- template<int M, typename Vec = Vec4vf<M>>
- __forceinline Vec eval0(const int ofs, const int size) const
- {
- assert(size <= PrecomputedBezierBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&bezier_basis0.c0[size][ofs]), Vec(v0),
- madd(vfloat<M>::loadu(&bezier_basis0.c1[size][ofs]), Vec(v1),
- madd(vfloat<M>::loadu(&bezier_basis0.c2[size][ofs]), Vec(v2),
- vfloat<M>::loadu(&bezier_basis0.c3[size][ofs]) * Vec(v3))));
- }
-
- template<int M, typename Vec = Vec4vf<M>>
- __forceinline Vec eval1(const int ofs, const int size) const
- {
- assert(size <= PrecomputedBezierBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&bezier_basis1.c0[size][ofs]), Vec(v0),
- madd(vfloat<M>::loadu(&bezier_basis1.c1[size][ofs]), Vec(v1),
- madd(vfloat<M>::loadu(&bezier_basis1.c2[size][ofs]), Vec(v2),
- vfloat<M>::loadu(&bezier_basis1.c3[size][ofs]) * Vec(v3))));
- }
-
- template<int M, typename Vec = Vec4vf<M>>
- __forceinline Vec derivative0(const int ofs, const int size) const
- {
- assert(size <= PrecomputedBezierBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&bezier_basis0.d0[size][ofs]), Vec(v0),
- madd(vfloat<M>::loadu(&bezier_basis0.d1[size][ofs]), Vec(v1),
- madd(vfloat<M>::loadu(&bezier_basis0.d2[size][ofs]), Vec(v2),
- vfloat<M>::loadu(&bezier_basis0.d3[size][ofs]) * Vec(v3))));
- }
-
- template<int M, typename Vec = Vec4vf<M>>
- __forceinline Vec derivative1(const int ofs, const int size) const
- {
- assert(size <= PrecomputedBezierBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&bezier_basis1.d0[size][ofs]), Vec(v0),
- madd(vfloat<M>::loadu(&bezier_basis1.d1[size][ofs]), Vec(v1),
- madd(vfloat<M>::loadu(&bezier_basis1.d2[size][ofs]), Vec(v2),
- vfloat<M>::loadu(&bezier_basis1.d3[size][ofs]) * Vec(v3))));
- }
-
- /* calculates bounds of bezier curve geometry */
- __forceinline BBox3fa accurateBounds() const
- {
- const int N = 7;
- const float scale = 1.0f/(3.0f*(N-1));
- Vec3vfx pl(pos_inf), pu(neg_inf);
- for (int i=0; i<=N; i+=VSIZEX)
- {
- vintx vi = vintx(i)+vintx(step);
- vboolx valid = vi <= vintx(N);
- const Vec3vfx p = eval0<VSIZEX,Vec3vf<VSIZEX>>(i,N);
- const Vec3vfx dp = derivative0<VSIZEX,Vec3vf<VSIZEX>>(i,N);
- const Vec3vfx pm = p-Vec3vfx(scale)*select(vi!=vintx(0),dp,Vec3vfx(zero));
- const Vec3vfx pp = p+Vec3vfx(scale)*select(vi!=vintx(N),dp,Vec3vfx(zero));
- pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
- pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
- }
- const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
- const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
- return BBox3fa(lower,upper);
- }
-
- /* calculates bounds of bezier curve geometry */
- __forceinline BBox3fa accurateRoundBounds() const
- {
- const int N = 7;
- const float scale = 1.0f/(3.0f*(N-1));
- Vec4vfx pl(pos_inf), pu(neg_inf);
- for (int i=0; i<=N; i+=VSIZEX)
- {
- vintx vi = vintx(i)+vintx(step);
- vboolx valid = vi <= vintx(N);
- const Vec4vfx p = eval0<VSIZEX>(i,N);
- const Vec4vfx dp = derivative0<VSIZEX>(i,N);
- const Vec4vfx pm = p-Vec4vfx(scale)*select(vi!=vintx(0),dp,Vec4vfx(zero));
- const Vec4vfx pp = p+Vec4vfx(scale)*select(vi!=vintx(N),dp,Vec4vfx(zero));
- pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
- pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
- }
- const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
- const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
- const float r_min = reduce_min(pl.w);
- const float r_max = reduce_max(pu.w);
- const Vec3fa upper_r = Vec3fa(max(abs(r_min),abs(r_max)));
- return enlarge(BBox3fa(lower,upper),upper_r);
- }
-
- /* calculates bounds when tessellated into N line segments */
- __forceinline BBox3fa accurateFlatBounds(int N) const
- {
- if (likely(N == 4))
- {
- const Vec4vf4 pi = eval0<4>(0,4);
- const Vec3fa lower(reduce_min(pi.x),reduce_min(pi.y),reduce_min(pi.z));
- const Vec3fa upper(reduce_max(pi.x),reduce_max(pi.y),reduce_max(pi.z));
- const Vec3fa upper_r = Vec3fa(reduce_max(abs(pi.w)));
- return enlarge(BBox3fa(min(lower,v3),max(upper,v3)),max(upper_r,Vec3fa(abs(v3.w))));
- }
- else
- {
- Vec3vfx pl(pos_inf), pu(neg_inf); vfloatx ru(0.0f);
- for (int i=0; i<N; i+=VSIZEX)
- {
- vboolx valid = vintx(i)+vintx(step) < vintx(N);
- const Vec4vfx pi = eval0<VSIZEX>(i,N);
-
- pl.x = select(valid,min(pl.x,pi.x),pl.x); // FIXME: use masked min
- pl.y = select(valid,min(pl.y,pi.y),pl.y);
- pl.z = select(valid,min(pl.z,pi.z),pl.z);
-
- pu.x = select(valid,max(pu.x,pi.x),pu.x); // FIXME: use masked min
- pu.y = select(valid,max(pu.y,pi.y),pu.y);
- pu.z = select(valid,max(pu.z,pi.z),pu.z);
-
- ru = select(valid,max(ru,abs(pi.w)),ru);
- }
- const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
- const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
- const Vec3fa upper_r(reduce_max(ru));
- return enlarge(BBox3fa(min(lower,v3),max(upper,v3)),max(upper_r,Vec3fa(abs(v3.w))));
- }
- }
-
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const CubicBezierCurve& curve) {
- return cout << "CubicBezierCurve { v0 = " << curve.v0 << ", v1 = " << curve.v1 << ", v2 = " << curve.v2 << ", v3 = " << curve.v3 << " }";
- }
- };
-
-#if defined(__AVX__)
- template<>
- __forceinline CubicBezierCurve<vfloat4> CubicBezierCurve<vfloat4>::clip(const Interval1f& u1) const
- {
- const vfloat8 p00 = vfloat8(v0);
- const vfloat8 p01 = vfloat8(v1);
- const vfloat8 p02 = vfloat8(v2);
- const vfloat8 p03 = vfloat8(v3);
-
- const vfloat8 t(vfloat4(u1.lower),vfloat4(u1.upper));
- const vfloat8 p10 = lerp(p00,p01,t);
- const vfloat8 p11 = lerp(p01,p02,t);
- const vfloat8 p12 = lerp(p02,p03,t);
- const vfloat8 p20 = lerp(p10,p11,t);
- const vfloat8 p21 = lerp(p11,p12,t);
- const vfloat8 p30 = lerp(p20,p21,t);
-
- const vfloat8 f01 = p30;
- const vfloat8 df01 = vfloat8(3.0f)*(p21-p20);
-
- const vfloat4 f0 = extract4<0>(f01), f1 = extract4<1>(f01);
- const vfloat4 df0 = extract4<0>(df01), df1 = extract4<1>(df01);
- const float s = u1.upper-u1.lower;
- return CubicBezierCurve(f0,f0+s*(1.0f/3.0f)*df0,f1-s*(1.0f/3.0f)*df1,f1);
- }
-#endif
-
- template<typename Vertex> using BezierCurveT = CubicBezierCurve<Vertex>;
-
- typedef CubicBezierCurve<float> CubicBezierCurve1f;
- typedef CubicBezierCurve<Vec2fa> CubicBezierCurve2fa;
- typedef CubicBezierCurve<Vec3fa> CubicBezierCurve3fa;
- typedef CubicBezierCurve<Vec3fa> BezierCurve3fa;
-
- template<> __forceinline int CubicBezierCurve<float>::maxRoots() const
- {
- float eps = 1E-4f;
- bool neg0 = v0 <= 0.0f; bool zero0 = fabs(v0) < eps;
- bool neg1 = v1 <= 0.0f; bool zero1 = fabs(v1) < eps;
- bool neg2 = v2 <= 0.0f; bool zero2 = fabs(v2) < eps;
- bool neg3 = v3 <= 0.0f; bool zero3 = fabs(v3) < eps;
- return (neg0 != neg1 || zero0) + (neg1 != neg2 || zero1) + (neg2 != neg3 || zero2 || zero3);
- }
-
- template<> __forceinline int CubicBezierCurve<Interval1f>::maxRoots() const {
- return numRoots(v0,v1) + numRoots(v1,v2) + numRoots(v2,v3);
- }
-
- __forceinline CubicBezierCurve<Vec3ff> enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const CubicBezierCurve<Vec3ff>& curve)
- {
- return CubicBezierCurve<Vec3ff>(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v1),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v2),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v3));
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/bezier_patch.h b/thirdparty/embree-aarch64/kernels/subdiv/bezier_patch.h
deleted file mode 100644
index d87ed41ccb..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/bezier_patch.h
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "catmullclark_patch.h"
-#include "bezier_curve.h"
-
-namespace embree
-{
- template<class T, class S>
- static __forceinline T deCasteljau(const S& uu, const T& v0, const T& v1, const T& v2, const T& v3)
- {
- const T v0_1 = lerp(v0,v1,uu);
- const T v1_1 = lerp(v1,v2,uu);
- const T v2_1 = lerp(v2,v3,uu);
- const T v0_2 = lerp(v0_1,v1_1,uu);
- const T v1_2 = lerp(v1_1,v2_1,uu);
- const T v0_3 = lerp(v0_2,v1_2,uu);
- return v0_3;
- }
-
- template<class T, class S>
- static __forceinline T deCasteljau_tangent(const S& uu, const T& v0, const T& v1, const T& v2, const T& v3)
- {
- const T v0_1 = lerp(v0,v1,uu);
- const T v1_1 = lerp(v1,v2,uu);
- const T v2_1 = lerp(v2,v3,uu);
- const T v0_2 = lerp(v0_1,v1_1,uu);
- const T v1_2 = lerp(v1_1,v2_1,uu);
- return S(3.0f)*(v1_2-v0_2);
- }
-
- template<typename Vertex>
- __forceinline Vertex computeInnerBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
- return 1.0f / 36.0f * (16.0f * v[y][x] + 4.0f * (v[y-1][x] + v[y+1][x] + v[y][x-1] + v[y][x+1]) + (v[y-1][x-1] + v[y+1][x+1] + v[y-1][x+1] + v[y+1][x-1]));
- }
-
- template<typename Vertex>
- __forceinline Vertex computeTopEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
- return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y-1][x] + 2.0f * (v[y][x-1] + v[y][x+1]) + (v[y-1][x-1] + v[y-1][x+1]));
- }
-
- template<typename Vertex>
- __forceinline Vertex computeBottomEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
- return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y+1][x] + 2.0f * (v[y][x-1] + v[y][x+1]) + v[y+1][x-1] + v[y+1][x+1]);
- }
-
- template<typename Vertex>
- __forceinline Vertex computeLeftEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
- return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y][x-1] + 2.0f * (v[y-1][x] + v[y+1][x]) + v[y-1][x-1] + v[y+1][x-1]);
- }
-
- template<typename Vertex>
- __forceinline Vertex computeRightEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
- return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y][x+1] + 2.0f * (v[y-1][x] + v[y+1][x]) + v[y-1][x+1] + v[y+1][x+1]);
- }
-
- template<typename Vertex>
- __forceinline Vertex computeCornerBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x, const ssize_t delta_y, const ssize_t delta_x)
- {
- return 1.0f / 9.0f * (4.0f * v[y][x] + 2.0f * (v[y+delta_y][x] + v[y][x+delta_x]) + v[y+delta_y][x+delta_x]);
- }
-
- template<typename Vertex, typename Vertex_t>
- class __aligned(64) BezierPatchT
- {
- public:
- Vertex matrix[4][4];
-
- public:
-
- __forceinline BezierPatchT() {}
-
- __forceinline BezierPatchT (const HalfEdge* edge, const char* vertices, size_t stride);
-
- __forceinline BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch);
-
- __forceinline BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch,
- const BezierCurveT<Vertex>* border0,
- const BezierCurveT<Vertex>* border1,
- const BezierCurveT<Vertex>* border2,
- const BezierCurveT<Vertex>* border3);
-
- __forceinline BezierPatchT(const BSplinePatchT<Vertex,Vertex_t>& source)
- {
- /* compute inner bezier control points */
- matrix[0][0] = computeInnerBezierControlPoint(source.v,1,1);
- matrix[0][3] = computeInnerBezierControlPoint(source.v,1,2);
- matrix[3][3] = computeInnerBezierControlPoint(source.v,2,2);
- matrix[3][0] = computeInnerBezierControlPoint(source.v,2,1);
-
- /* compute top edge control points */
- matrix[0][1] = computeRightEdgeBezierControlPoint(source.v,1,1);
- matrix[0][2] = computeLeftEdgeBezierControlPoint(source.v,1,2);
-
- /* compute buttom edge control points */
- matrix[3][1] = computeRightEdgeBezierControlPoint(source.v,2,1);
- matrix[3][2] = computeLeftEdgeBezierControlPoint(source.v,2,2);
-
- /* compute left edge control points */
- matrix[1][0] = computeBottomEdgeBezierControlPoint(source.v,1,1);
- matrix[2][0] = computeTopEdgeBezierControlPoint(source.v,2,1);
-
- /* compute right edge control points */
- matrix[1][3] = computeBottomEdgeBezierControlPoint(source.v,1,2);
- matrix[2][3] = computeTopEdgeBezierControlPoint(source.v,2,2);
-
- /* compute corner control points */
- matrix[1][1] = computeCornerBezierControlPoint(source.v,1,1, 1, 1);
- matrix[1][2] = computeCornerBezierControlPoint(source.v,1,2, 1,-1);
- matrix[2][2] = computeCornerBezierControlPoint(source.v,2,2,-1,-1);
- matrix[2][1] = computeCornerBezierControlPoint(source.v,2,1,-1, 1);
- }
-
- static __forceinline Vertex_t bilinear(const Vec4f Bu, const Vertex matrix[4][4], const Vec4f Bv)
- {
- const Vertex_t M0 = madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3])));
- const Vertex_t M1 = madd(Bu.x,matrix[1][0],madd(Bu.y,matrix[1][1],madd(Bu.z,matrix[1][2],Bu.w * matrix[1][3])));
- const Vertex_t M2 = madd(Bu.x,matrix[2][0],madd(Bu.y,matrix[2][1],madd(Bu.z,matrix[2][2],Bu.w * matrix[2][3])));
- const Vertex_t M3 = madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3])));
- return madd(Bv.x,M0,madd(Bv.y,M1,madd(Bv.z,M2,Bv.w*M3)));
- }
-
- static __forceinline Vertex_t eval(const Vertex matrix[4][4], const float uu, const float vv)
- {
- const Vec4f Bu = BezierBasis::eval(uu);
- const Vec4f Bv = BezierBasis::eval(vv);
- return bilinear(Bu,matrix,Bv);
- }
-
- static __forceinline Vertex_t eval_du(const Vertex matrix[4][4], const float uu, const float vv)
- {
- const Vec4f Bu = BezierBasis::derivative(uu);
- const Vec4f Bv = BezierBasis::eval(vv);
- return bilinear(Bu,matrix,Bv);
- }
-
- static __forceinline Vertex_t eval_dv(const Vertex matrix[4][4], const float uu, const float vv)
- {
- const Vec4f Bu = BezierBasis::eval(uu);
- const Vec4f Bv = BezierBasis::derivative(vv);
- return bilinear(Bu,matrix,Bv);
- }
-
- static __forceinline Vertex_t eval_dudu(const Vertex matrix[4][4], const float uu, const float vv)
- {
- const Vec4f Bu = BezierBasis::derivative2(uu);
- const Vec4f Bv = BezierBasis::eval(vv);
- return bilinear(Bu,matrix,Bv);
- }
-
- static __forceinline Vertex_t eval_dvdv(const Vertex matrix[4][4], const float uu, const float vv)
- {
- const Vec4f Bu = BezierBasis::eval(uu);
- const Vec4f Bv = BezierBasis::derivative2(vv);
- return bilinear(Bu,matrix,Bv);
- }
-
- static __forceinline Vertex_t eval_dudv(const Vertex matrix[4][4], const float uu, const float vv)
- {
- const Vec4f Bu = BezierBasis::derivative(uu);
- const Vec4f Bv = BezierBasis::derivative(vv);
- return bilinear(Bu,matrix,Bv);
- }
-
- static __forceinline Vertex_t normal(const Vertex matrix[4][4], const float uu, const float vv)
- {
- const Vertex_t dPdu = eval_du(matrix,uu,vv);
- const Vertex_t dPdv = eval_dv(matrix,uu,vv);
- return cross(dPdu,dPdv);
- }
-
- __forceinline Vertex_t normal(const float uu, const float vv)
- {
- const Vertex_t dPdu = eval_du(matrix,uu,vv);
- const Vertex_t dPdv = eval_dv(matrix,uu,vv);
- return cross(dPdu,dPdv);
- }
-
- __forceinline Vertex_t eval(const float uu, const float vv) const {
- return eval(matrix,uu,vv);
- }
-
- __forceinline Vertex_t eval_du(const float uu, const float vv) const {
- return eval_du(matrix,uu,vv);
- }
-
- __forceinline Vertex_t eval_dv(const float uu, const float vv) const {
- return eval_dv(matrix,uu,vv);
- }
-
- __forceinline Vertex_t eval_dudu(const float uu, const float vv) const {
- return eval_dudu(matrix,uu,vv);
- }
-
- __forceinline Vertex_t eval_dvdv(const float uu, const float vv) const {
- return eval_dvdv(matrix,uu,vv);
- }
-
- __forceinline Vertex_t eval_dudv(const float uu, const float vv) const {
- return eval_dudv(matrix,uu,vv);
- }
-
- __forceinline void eval(const float u, const float v, Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv, const float dscale = 1.0f) const
- {
- if (P) {
- *P = eval(u,v);
- }
- if (dPdu) {
- assert(dPdu); *dPdu = eval_du(u,v)*dscale;
- assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
- }
- if (ddPdudu) {
- assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
- assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
- assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
- }
- }
-
- template<class vfloat>
- __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n) const
- {
- const vfloat curve0_x = v_n[0] * vfloat(matrix[0][0][i]) + v_n[1] * vfloat(matrix[1][0][i]) + v_n[2] * vfloat(matrix[2][0][i]) + v_n[3] * vfloat(matrix[3][0][i]);
- const vfloat curve1_x = v_n[0] * vfloat(matrix[0][1][i]) + v_n[1] * vfloat(matrix[1][1][i]) + v_n[2] * vfloat(matrix[2][1][i]) + v_n[3] * vfloat(matrix[3][1][i]);
- const vfloat curve2_x = v_n[0] * vfloat(matrix[0][2][i]) + v_n[1] * vfloat(matrix[1][2][i]) + v_n[2] * vfloat(matrix[2][2][i]) + v_n[3] * vfloat(matrix[3][2][i]);
- const vfloat curve3_x = v_n[0] * vfloat(matrix[0][3][i]) + v_n[1] * vfloat(matrix[1][3][i]) + v_n[2] * vfloat(matrix[2][3][i]) + v_n[3] * vfloat(matrix[3][3][i]);
- return u_n[0] * curve0_x + u_n[1] * curve1_x + u_n[2] * curve2_x + u_n[3] * curve3_x;
- }
-
- template<typename vbool, typename vfloat>
- __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
- const float dscale, const size_t dstride, const size_t N) const
- {
- if (P) {
- const Vec4<vfloat> u_n = BezierBasis::eval(uu);
- const Vec4<vfloat> v_n = BezierBasis::eval(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv,u_n,v_n));
- }
- if (dPdu)
- {
- {
- assert(dPdu);
- const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
- const Vec4<vfloat> v_n = BezierBasis::eval(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,dPdu+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
- }
- {
- assert(dPdv);
- const Vec4<vfloat> u_n = BezierBasis::eval(uu);
- const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,dPdv+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
- }
- }
- if (ddPdudu)
- {
- {
- assert(ddPdudu);
- const Vec4<vfloat> u_n = BezierBasis::derivative2(uu);
- const Vec4<vfloat> v_n = BezierBasis::eval(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudu+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
- }
- {
- assert(ddPdvdv);
- const Vec4<vfloat> u_n = BezierBasis::eval(uu);
- const Vec4<vfloat> v_n = BezierBasis::derivative2(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdvdv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
- }
- {
- assert(ddPdudv);
- const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
- const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
- }
- }
- }
-
- template<typename T>
- static __forceinline Vec3<T> eval(const Vertex matrix[4][4], const T& uu, const T& vv)
- {
- const T one_minus_uu = 1.0f - uu;
- const T one_minus_vv = 1.0f - vv;
-
- const T B0_u = one_minus_uu * one_minus_uu * one_minus_uu;
- const T B0_v = one_minus_vv * one_minus_vv * one_minus_vv;
- const T B1_u = 3.0f * (one_minus_uu * uu * one_minus_uu);
- const T B1_v = 3.0f * (one_minus_vv * vv * one_minus_vv);
- const T B2_u = 3.0f * (uu * one_minus_uu * uu);
- const T B2_v = 3.0f * (vv * one_minus_vv * vv);
- const T B3_u = uu * uu * uu;
- const T B3_v = vv * vv * vv;
-
- const T x =
- madd(B0_v,madd(B0_u,matrix[0][0].x,madd(B1_u,matrix[0][1].x,madd(B2_u,matrix[0][2].x,B3_u*matrix[0][3].x))),
- madd(B1_v,madd(B0_u,matrix[1][0].x,madd(B1_u,matrix[1][1].x,madd(B2_u,matrix[1][2].x,B3_u*matrix[1][3].x))),
- madd(B2_v,madd(B0_u,matrix[2][0].x,madd(B1_u,matrix[2][1].x,madd(B2_u,matrix[2][2].x,B3_u*matrix[2][3].x))),
- B3_v*madd(B0_u,matrix[3][0].x,madd(B1_u,matrix[3][1].x,madd(B2_u,matrix[3][2].x,B3_u*matrix[3][3].x))))));
-
- const T y =
- madd(B0_v,madd(B0_u,matrix[0][0].y,madd(B1_u,matrix[0][1].y,madd(B2_u,matrix[0][2].y,B3_u*matrix[0][3].y))),
- madd(B1_v,madd(B0_u,matrix[1][0].y,madd(B1_u,matrix[1][1].y,madd(B2_u,matrix[1][2].y,B3_u*matrix[1][3].y))),
- madd(B2_v,madd(B0_u,matrix[2][0].y,madd(B1_u,matrix[2][1].y,madd(B2_u,matrix[2][2].y,B3_u*matrix[2][3].y))),
- B3_v*madd(B0_u,matrix[3][0].y,madd(B1_u,matrix[3][1].y,madd(B2_u,matrix[3][2].y,B3_u*matrix[3][3].y))))));
-
- const T z =
- madd(B0_v,madd(B0_u,matrix[0][0].z,madd(B1_u,matrix[0][1].z,madd(B2_u,matrix[0][2].z,B3_u*matrix[0][3].z))),
- madd(B1_v,madd(B0_u,matrix[1][0].z,madd(B1_u,matrix[1][1].z,madd(B2_u,matrix[1][2].z,B3_u*matrix[1][3].z))),
- madd(B2_v,madd(B0_u,matrix[2][0].z,madd(B1_u,matrix[2][1].z,madd(B2_u,matrix[2][2].z,B3_u*matrix[2][3].z))),
- B3_v*madd(B0_u,matrix[3][0].z,madd(B1_u,matrix[3][1].z,madd(B2_u,matrix[3][2].z,B3_u*matrix[3][3].z))))));
-
- return Vec3<T>(x,y,z);
- }
-
- template<typename vfloat>
- __forceinline Vec3<vfloat> eval(const vfloat& uu, const vfloat& vv) const {
- return eval(matrix,uu,vv);
- }
-
- template<class T>
- static __forceinline Vec3<T> normal(const Vertex matrix[4][4], const T& uu, const T& vv)
- {
-
- const Vec3<T> matrix_00 = Vec3<T>(matrix[0][0].x,matrix[0][0].y,matrix[0][0].z);
- const Vec3<T> matrix_01 = Vec3<T>(matrix[0][1].x,matrix[0][1].y,matrix[0][1].z);
- const Vec3<T> matrix_02 = Vec3<T>(matrix[0][2].x,matrix[0][2].y,matrix[0][2].z);
- const Vec3<T> matrix_03 = Vec3<T>(matrix[0][3].x,matrix[0][3].y,matrix[0][3].z);
-
- const Vec3<T> matrix_10 = Vec3<T>(matrix[1][0].x,matrix[1][0].y,matrix[1][0].z);
- const Vec3<T> matrix_11 = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);
- const Vec3<T> matrix_12 = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);
- const Vec3<T> matrix_13 = Vec3<T>(matrix[1][3].x,matrix[1][3].y,matrix[1][3].z);
-
- const Vec3<T> matrix_20 = Vec3<T>(matrix[2][0].x,matrix[2][0].y,matrix[2][0].z);
- const Vec3<T> matrix_21 = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);
- const Vec3<T> matrix_22 = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);
- const Vec3<T> matrix_23 = Vec3<T>(matrix[2][3].x,matrix[2][3].y,matrix[2][3].z);
-
- const Vec3<T> matrix_30 = Vec3<T>(matrix[3][0].x,matrix[3][0].y,matrix[3][0].z);
- const Vec3<T> matrix_31 = Vec3<T>(matrix[3][1].x,matrix[3][1].y,matrix[3][1].z);
- const Vec3<T> matrix_32 = Vec3<T>(matrix[3][2].x,matrix[3][2].y,matrix[3][2].z);
- const Vec3<T> matrix_33 = Vec3<T>(matrix[3][3].x,matrix[3][3].y,matrix[3][3].z);
-
- /* tangentU */
- const Vec3<T> col0 = deCasteljau(vv, matrix_00, matrix_10, matrix_20, matrix_30);
- const Vec3<T> col1 = deCasteljau(vv, matrix_01, matrix_11, matrix_21, matrix_31);
- const Vec3<T> col2 = deCasteljau(vv, matrix_02, matrix_12, matrix_22, matrix_32);
- const Vec3<T> col3 = deCasteljau(vv, matrix_03, matrix_13, matrix_23, matrix_33);
-
- const Vec3<T> tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);
-
- /* tangentV */
- const Vec3<T> row0 = deCasteljau(uu, matrix_00, matrix_01, matrix_02, matrix_03);
- const Vec3<T> row1 = deCasteljau(uu, matrix_10, matrix_11, matrix_12, matrix_13);
- const Vec3<T> row2 = deCasteljau(uu, matrix_20, matrix_21, matrix_22, matrix_23);
- const Vec3<T> row3 = deCasteljau(uu, matrix_30, matrix_31, matrix_32, matrix_33);
-
- const Vec3<T> tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);
-
- /* normal = tangentU x tangentV */
- const Vec3<T> n = cross(tangentU,tangentV);
- return n;
- }
-
- template<typename vfloat>
- __forceinline Vec3<vfloat> normal(const vfloat& uu, const vfloat& vv) const {
- return normal(matrix,uu,vv);
- }
- };
-
- typedef BezierPatchT<Vec3fa,Vec3fa_t> BezierPatch3fa;
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/bilinear_patch.h b/thirdparty/embree-aarch64/kernels/subdiv/bilinear_patch.h
deleted file mode 100644
index 35748754bd..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/bilinear_patch.h
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "catmullclark_patch.h"
-#include "bezier_curve.h"
-
-namespace embree
-{
- template<typename Vertex, typename Vertex_t = Vertex>
- class __aligned(64) BilinearPatchT
- {
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
-
- public:
- Vertex v[4];
-
- public:
-
- __forceinline BilinearPatchT () {}
-
- __forceinline BilinearPatchT (const HalfEdge* edge, const BufferView<Vertex>& vertices) {
- init(edge,vertices.getPtr(),vertices.getStride());
- }
-
- __forceinline BilinearPatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
- init(edge,vertices,stride);
- }
-
- __forceinline void init (const HalfEdge* edge, const char* vertices, size_t stride)
- {
- v[0] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
- v[1] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
- v[2] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
- v[3] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
- }
-
- __forceinline BilinearPatchT (const CatmullClarkPatch& patch)
- {
- v[0] = patch.ring[0].getLimitVertex();
- v[1] = patch.ring[1].getLimitVertex();
- v[2] = patch.ring[2].getLimitVertex();
- v[3] = patch.ring[3].getLimitVertex();
- }
-
- __forceinline BBox<Vertex> bounds() const
- {
-
- BBox<Vertex> bounds (v[0]);
- bounds.extend(v[1]);
- bounds.extend(v[2]);
- bounds.extend(v[3]);
- return bounds;
- }
-
- __forceinline Vertex eval(const float uu, const float vv) const {
- return lerp(lerp(v[0],v[1],uu),lerp(v[3],v[2],uu),vv);
- }
-
- __forceinline Vertex eval_du(const float uu, const float vv) const {
- return lerp(v[1]-v[0],v[2]-v[3],vv);
- }
-
- __forceinline Vertex eval_dv(const float uu, const float vv) const {
- return lerp(v[3]-v[0],v[2]-v[1],uu);
- }
-
- __forceinline Vertex eval_dudu(const float uu, const float vv) const {
- return Vertex(zero);
- }
-
- __forceinline Vertex eval_dvdv(const float uu, const float vv) const {
- return Vertex(zero);
- }
-
- __forceinline Vertex eval_dudv(const float uu, const float vv) const {
- return (v[2]-v[3]) - (v[1]-v[0]);
- }
-
- __forceinline Vertex normal(const float uu, const float vv) const {
- return cross(eval_du(uu,vv),eval_dv(uu,vv));
- }
-
- __forceinline void eval(const float u, const float v,
- Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
- const float dscale = 1.0f) const
- {
- if (P) {
- *P = eval(u,v);
- }
- if (dPdu) {
- assert(dPdu); *dPdu = eval_du(u,v)*dscale;
- assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
- }
- if (ddPdudu) {
- assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
- assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
- assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
- }
- }
-
- template<class vfloat>
- __forceinline Vec3<vfloat> eval(const vfloat& uu, const vfloat& vv) const
- {
- const vfloat x = lerp(lerp(v[0].x,v[1].x,uu),lerp(v[3].x,v[2].x,uu),vv);
- const vfloat y = lerp(lerp(v[0].y,v[1].y,uu),lerp(v[3].y,v[2].y,uu),vv);
- const vfloat z = lerp(lerp(v[0].z,v[1].z,uu),lerp(v[3].z,v[2].z,uu),vv);
- return Vec3<vfloat>(x,y,z);
- }
-
- template<class vfloat>
- __forceinline Vec3<vfloat> eval_du(const vfloat& uu, const vfloat& vv) const
- {
- const vfloat x = lerp(v[1].x-v[0].x,v[2].x-v[3].x,vv);
- const vfloat y = lerp(v[1].y-v[0].y,v[2].y-v[3].y,vv);
- const vfloat z = lerp(v[1].z-v[0].z,v[2].z-v[3].z,vv);
- return Vec3<vfloat>(x,y,z);
- }
-
- template<class vfloat>
- __forceinline Vec3<vfloat> eval_dv(const vfloat& uu, const vfloat& vv) const
- {
- const vfloat x = lerp(v[3].x-v[0].x,v[2].x-v[1].x,uu);
- const vfloat y = lerp(v[3].y-v[0].y,v[2].y-v[1].y,uu);
- const vfloat z = lerp(v[3].z-v[0].z,v[2].z-v[1].z,uu);
- return Vec3<vfloat>(x,y,z);
- }
-
- template<typename vfloat>
- __forceinline Vec3<vfloat> normal(const vfloat& uu, const vfloat& vv) const {
- return cross(eval_du(uu,vv),eval_dv(uu,vv));
- }
-
- template<class vfloat>
- __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv) const {
- return lerp(lerp(v[0][i],v[1][i],uu),lerp(v[3][i],v[2][i],uu),vv);
- }
-
- template<class vfloat>
- __forceinline vfloat eval_du(const size_t i, const vfloat& uu, const vfloat& vv) const {
- return lerp(v[1][i]-v[0][i],v[2][i]-v[3][i],vv);
- }
-
- template<class vfloat>
- __forceinline vfloat eval_dv(const size_t i, const vfloat& uu, const vfloat& vv) const {
- return lerp(v[3][i]-v[0][i],v[2][i]-v[1][i],uu);
- }
-
- template<class vfloat>
- __forceinline vfloat eval_dudu(const size_t i, const vfloat& uu, const vfloat& vv) const {
- return vfloat(zero);
- }
-
- template<class vfloat>
- __forceinline vfloat eval_dvdv(const size_t i, const vfloat& uu, const vfloat& vv) const {
- return vfloat(zero);
- }
-
- template<class vfloat>
- __forceinline vfloat eval_dudv(const size_t i, const vfloat& uu, const vfloat& vv) const {
- return (v[2][i]-v[3][i]) - (v[1][i]-v[0][i]);
- }
-
- template<typename vbool, typename vfloat>
- __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
- const float dscale, const size_t dstride, const size_t N) const
- {
- if (P) {
- for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv));
- }
- if (dPdu) {
- for (size_t i=0; i<N; i++) {
- assert(dPdu); vfloat::store(valid,dPdu+i*dstride,eval_du(i,uu,vv)*dscale);
- assert(dPdv); vfloat::store(valid,dPdv+i*dstride,eval_dv(i,uu,vv)*dscale);
- }
- }
- if (ddPdudu) {
- for (size_t i=0; i<N; i++) {
- assert(ddPdudu); vfloat::store(valid,ddPdudu+i*dstride,eval_dudu(i,uu,vv)*sqr(dscale));
- assert(ddPdvdv); vfloat::store(valid,ddPdvdv+i*dstride,eval_dvdv(i,uu,vv)*sqr(dscale));
- assert(ddPdudv); vfloat::store(valid,ddPdudv+i*dstride,eval_dudv(i,uu,vv)*sqr(dscale));
- }
- }
- }
- };
-
- typedef BilinearPatchT<Vec3fa,Vec3fa_t> BilinearPatch3fa;
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/bspline_curve.h b/thirdparty/embree-aarch64/kernels/subdiv/bspline_curve.h
deleted file mode 100644
index a325667328..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/bspline_curve.h
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-#include "bezier_curve.h"
-
-namespace embree
-{
- class BSplineBasis
- {
- public:
-
- template<typename T>
- static __forceinline Vec4<T> eval(const T& u)
- {
- const T t = u;
- const T s = T(1.0f) - u;
- const T n0 = s*s*s;
- const T n1 = (4.0f*(s*s*s)+(t*t*t)) + (12.0f*((s*t)*s) + 6.0f*((t*s)*t));
- const T n2 = (4.0f*(t*t*t)+(s*s*s)) + (12.0f*((t*s)*t) + 6.0f*((s*t)*s));
- const T n3 = t*t*t;
- return T(1.0f/6.0f)*Vec4<T>(n0,n1,n2,n3);
- }
-
- template<typename T>
- static __forceinline Vec4<T> derivative(const T& u)
- {
- const T t = u;
- const T s = 1.0f - u;
- const T n0 = -s*s;
- const T n1 = -t*t - 4.0f*(t*s);
- const T n2 = s*s + 4.0f*(s*t);
- const T n3 = t*t;
- return T(0.5f)*Vec4<T>(n0,n1,n2,n3);
- }
-
- template<typename T>
- static __forceinline Vec4<T> derivative2(const T& u)
- {
- const T t = u;
- const T s = 1.0f - u;
- const T n0 = s;
- const T n1 = t - 2.0f*s;
- const T n2 = s - 2.0f*t;
- const T n3 = t;
- return Vec4<T>(n0,n1,n2,n3);
- }
- };
-
- struct PrecomputedBSplineBasis
- {
- enum { N = 16 };
- public:
- PrecomputedBSplineBasis() {}
- PrecomputedBSplineBasis(int shift);
-
- /* basis for bspline evaluation */
- public:
- float c0[N+1][N+1];
- float c1[N+1][N+1];
- float c2[N+1][N+1];
- float c3[N+1][N+1];
-
- /* basis for bspline derivative evaluation */
- public:
- float d0[N+1][N+1];
- float d1[N+1][N+1];
- float d2[N+1][N+1];
- float d3[N+1][N+1];
- };
- extern PrecomputedBSplineBasis bspline_basis0;
- extern PrecomputedBSplineBasis bspline_basis1;
-
- template<typename Vertex>
- struct BSplineCurveT
- {
- Vertex v0,v1,v2,v3;
-
- __forceinline BSplineCurveT() {}
-
- __forceinline BSplineCurveT(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3)
- : v0(v0), v1(v1), v2(v2), v3(v3) {}
-
- __forceinline Vertex begin() const {
- return madd(1.0f/6.0f,v0,madd(2.0f/3.0f,v1,1.0f/6.0f*v2));
- }
-
- __forceinline Vertex end() const {
- return madd(1.0f/6.0f,v1,madd(2.0f/3.0f,v2,1.0f/6.0f*v3));
- }
-
- __forceinline Vertex center() const {
- return 0.25f*(v0+v1+v2+v3);
- }
-
- __forceinline BBox<Vertex> bounds() const {
- return merge(BBox<Vertex>(v0),BBox<Vertex>(v1),BBox<Vertex>(v2),BBox<Vertex>(v3));
- }
-
- __forceinline friend BSplineCurveT operator -( const BSplineCurveT& a, const Vertex& b ) {
- return BSplineCurveT(a.v0-b,a.v1-b,a.v2-b,a.v3-b);
- }
-
- __forceinline BSplineCurveT<Vec3ff> xfm_pr(const LinearSpace3fa& space, const Vec3fa& p) const
- {
- const Vec3ff q0(xfmVector(space,(Vec3fa)v0-p), v0.w);
- const Vec3ff q1(xfmVector(space,(Vec3fa)v1-p), v1.w);
- const Vec3ff q2(xfmVector(space,(Vec3fa)v2-p), v2.w);
- const Vec3ff q3(xfmVector(space,(Vec3fa)v3-p), v3.w);
- return BSplineCurveT<Vec3ff>(q0,q1,q2,q3);
- }
-
- __forceinline Vertex eval(const float t) const
- {
- const Vec4<float> b = BSplineBasis::eval(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-
- __forceinline Vertex eval_du(const float t) const
- {
- const Vec4<float> b = BSplineBasis::derivative(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-
- __forceinline Vertex eval_dudu(const float t) const
- {
- const Vec4<float> b = BSplineBasis::derivative2(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-
- __forceinline void eval(const float t, Vertex& p, Vertex& dp, Vertex& ddp) const
- {
- p = eval(t);
- dp = eval_du(t);
- ddp = eval_dudu(t);
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = BSplineBasis::eval(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval_du(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = BSplineBasis::derivative(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval_dudu(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = BSplineBasis::derivative2(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline void veval(const vfloat<M>& t, Vec4vf<M>& p, Vec4vf<M>& dp) const
- {
- p = veval(t);
- dp = veval_du(t);
- }
-
- template<int M>
- __forceinline Vec4vf<M> eval0(const int ofs, const int size) const
- {
- assert(size <= PrecomputedBSplineBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&bspline_basis0.c0[size][ofs]), Vec4vf<M>(v0),
- madd(vfloat<M>::loadu(&bspline_basis0.c1[size][ofs]), Vec4vf<M>(v1),
- madd(vfloat<M>::loadu(&bspline_basis0.c2[size][ofs]), Vec4vf<M>(v2),
- vfloat<M>::loadu(&bspline_basis0.c3[size][ofs]) * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> eval1(const int ofs, const int size) const
- {
- assert(size <= PrecomputedBSplineBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&bspline_basis1.c0[size][ofs]), Vec4vf<M>(v0),
- madd(vfloat<M>::loadu(&bspline_basis1.c1[size][ofs]), Vec4vf<M>(v1),
- madd(vfloat<M>::loadu(&bspline_basis1.c2[size][ofs]), Vec4vf<M>(v2),
- vfloat<M>::loadu(&bspline_basis1.c3[size][ofs]) * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> derivative0(const int ofs, const int size) const
- {
- assert(size <= PrecomputedBSplineBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&bspline_basis0.d0[size][ofs]), Vec4vf<M>(v0),
- madd(vfloat<M>::loadu(&bspline_basis0.d1[size][ofs]), Vec4vf<M>(v1),
- madd(vfloat<M>::loadu(&bspline_basis0.d2[size][ofs]), Vec4vf<M>(v2),
- vfloat<M>::loadu(&bspline_basis0.d3[size][ofs]) * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> derivative1(const int ofs, const int size) const
- {
- assert(size <= PrecomputedBSplineBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&bspline_basis1.d0[size][ofs]), Vec4vf<M>(v0),
- madd(vfloat<M>::loadu(&bspline_basis1.d1[size][ofs]), Vec4vf<M>(v1),
- madd(vfloat<M>::loadu(&bspline_basis1.d2[size][ofs]), Vec4vf<M>(v2),
- vfloat<M>::loadu(&bspline_basis1.d3[size][ofs]) * Vec4vf<M>(v3))));
- }
-
- /* calculates bounds of bspline curve geometry */
- __forceinline BBox3fa accurateRoundBounds() const
- {
- const int N = 7;
- const float scale = 1.0f/(3.0f*(N-1));
- Vec4vfx pl(pos_inf), pu(neg_inf);
- for (int i=0; i<=N; i+=VSIZEX)
- {
- vintx vi = vintx(i)+vintx(step);
- vboolx valid = vi <= vintx(N);
- const Vec4vfx p = eval0<VSIZEX>(i,N);
- const Vec4vfx dp = derivative0<VSIZEX>(i,N);
- const Vec4vfx pm = p-Vec4vfx(scale)*select(vi!=vintx(0),dp,Vec4vfx(zero));
- const Vec4vfx pp = p+Vec4vfx(scale)*select(vi!=vintx(N),dp,Vec4vfx(zero));
- pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
- pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
- }
- const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
- const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
- const float r_min = reduce_min(pl.w);
- const float r_max = reduce_max(pu.w);
- const Vec3fa upper_r = Vec3fa(max(abs(r_min),abs(r_max)));
- return enlarge(BBox3fa(lower,upper),upper_r);
- }
-
- /* calculates bounds when tessellated into N line segments */
- __forceinline BBox3fa accurateFlatBounds(int N) const
- {
- if (likely(N == 4))
- {
- const Vec4vf4 pi = eval0<4>(0,4);
- const Vec3fa lower(reduce_min(pi.x),reduce_min(pi.y),reduce_min(pi.z));
- const Vec3fa upper(reduce_max(pi.x),reduce_max(pi.y),reduce_max(pi.z));
- const Vec3fa upper_r = Vec3fa(reduce_max(abs(pi.w)));
- const Vec3ff pe = end();
- return enlarge(BBox3fa(min(lower,pe),max(upper,pe)),max(upper_r,Vec3fa(abs(pe.w))));
- }
- else
- {
- Vec3vfx pl(pos_inf), pu(neg_inf); vfloatx ru(0.0f);
- for (int i=0; i<=N; i+=VSIZEX)
- {
- vboolx valid = vintx(i)+vintx(step) <= vintx(N);
- const Vec4vfx pi = eval0<VSIZEX>(i,N);
-
- pl.x = select(valid,min(pl.x,pi.x),pl.x); // FIXME: use masked min
- pl.y = select(valid,min(pl.y,pi.y),pl.y);
- pl.z = select(valid,min(pl.z,pi.z),pl.z);
-
- pu.x = select(valid,max(pu.x,pi.x),pu.x); // FIXME: use masked min
- pu.y = select(valid,max(pu.y,pi.y),pu.y);
- pu.z = select(valid,max(pu.z,pi.z),pu.z);
-
- ru = select(valid,max(ru,abs(pi.w)),ru);
- }
- const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
- const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
- const Vec3fa upper_r(reduce_max(ru));
- return enlarge(BBox3fa(lower,upper),upper_r);
- }
- }
-
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const BSplineCurveT& curve) {
- return cout << "BSplineCurve { v0 = " << curve.v0 << ", v1 = " << curve.v1 << ", v2 = " << curve.v2 << ", v3 = " << curve.v3 << " }";
- }
- };
-
- template<typename Vertex>
- __forceinline void convert(const BezierCurveT<Vertex>& icurve, BezierCurveT<Vertex>& ocurve) {
- ocurve = icurve;
- }
-
- template<typename Vertex>
- __forceinline void convert(const BSplineCurveT<Vertex>& icurve, BSplineCurveT<Vertex>& ocurve) {
- ocurve = icurve;
- }
-
- template<typename Vertex>
- __forceinline void convert(const BezierCurveT<Vertex>& icurve, BSplineCurveT<Vertex>& ocurve)
- {
- const Vertex v0 = madd(6.0f,icurve.v0,madd(-7.0f,icurve.v1,2.0f*icurve.v2));
- const Vertex v1 = msub(2.0f,icurve.v1,icurve.v2);
- const Vertex v2 = msub(2.0f,icurve.v2,icurve.v1);
- const Vertex v3 = madd(2.0f,icurve.v1,madd(-7.0f,icurve.v2,6.0f*icurve.v3));
- ocurve = BSplineCurveT<Vertex>(v0,v1,v2,v3);
- }
-
- template<typename Vertex>
- __forceinline void convert(const BSplineCurveT<Vertex>& icurve, BezierCurveT<Vertex>& ocurve)
- {
- const Vertex v0 = madd(1.0f/6.0f,icurve.v0,madd(2.0f/3.0f,icurve.v1,1.0f/6.0f*icurve.v2));
- const Vertex v1 = madd(2.0f/3.0f,icurve.v1,1.0f/3.0f*icurve.v2);
- const Vertex v2 = madd(1.0f/3.0f,icurve.v1,2.0f/3.0f*icurve.v2);
- const Vertex v3 = madd(1.0f/6.0f,icurve.v1,madd(2.0f/3.0f,icurve.v2,1.0f/6.0f*icurve.v3));
- ocurve = BezierCurveT<Vertex>(v0,v1,v2,v3);
- }
-
- __forceinline BSplineCurveT<Vec3ff> enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const BSplineCurveT<Vec3ff>& curve)
- {
- return BSplineCurveT<Vec3ff>(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v1),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v2),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v3));
- }
-
- typedef BSplineCurveT<Vec3fa> BSplineCurve3fa;
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/bspline_patch.h b/thirdparty/embree-aarch64/kernels/subdiv/bspline_patch.h
deleted file mode 100644
index 9769bc17bd..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/bspline_patch.h
+++ /dev/null
@@ -1,449 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "catmullclark_patch.h"
-#include "bspline_curve.h"
-
-namespace embree
-{
- template<typename Vertex, typename Vertex_t = Vertex>
- class __aligned(64) BSplinePatchT
- {
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
-
- public:
-
- __forceinline BSplinePatchT () {}
-
- __forceinline BSplinePatchT (const CatmullClarkPatch& patch) {
- init(patch);
- }
-
- __forceinline BSplinePatchT(const CatmullClarkPatch& patch,
- const BezierCurveT<Vertex>* border0,
- const BezierCurveT<Vertex>* border1,
- const BezierCurveT<Vertex>* border2,
- const BezierCurveT<Vertex>* border3)
- {
- init(patch);
- }
-
- __forceinline BSplinePatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
- init(edge,vertices,stride);
- }
-
- __forceinline Vertex hard_corner(const Vertex& v01, const Vertex& v02,
- const Vertex& v10, const Vertex& v11, const Vertex& v12,
- const Vertex& v20, const Vertex& v21, const Vertex& v22)
- {
- return 4.0f*v11 - 2.0f*(v12+v21) + v22;
- }
-
- __forceinline Vertex soft_convex_corner( const Vertex& v01, const Vertex& v02,
- const Vertex& v10, const Vertex& v11, const Vertex& v12,
- const Vertex& v20, const Vertex& v21, const Vertex& v22)
- {
- return -8.0f*v11 + 4.0f*(v12+v21) + v22;
- }
-
- __forceinline Vertex convex_corner(const float vertex_crease_weight,
- const Vertex& v01, const Vertex& v02,
- const Vertex& v10, const Vertex& v11, const Vertex& v12,
- const Vertex& v20, const Vertex& v21, const Vertex& v22)
- {
- if (std::isinf(vertex_crease_weight)) return hard_corner(v01,v02,v10,v11,v12,v20,v21,v22);
- else return soft_convex_corner(v01,v02,v10,v11,v12,v20,v21,v22);
- }
-
- __forceinline Vertex load(const HalfEdge* edge, const char* vertices, size_t stride) {
- return Vertex_t::loadu(vertices+edge->getStartVertexIndex()*stride);
- }
-
- __forceinline void init_border(const CatmullClarkRing& edge0,
- Vertex& v01, Vertex& v02,
- const Vertex& v11, const Vertex& v12,
- const Vertex& v21, const Vertex& v22)
- {
- if (likely(edge0.has_opposite_back(0)))
- {
- v01 = edge0.back(2);
- v02 = edge0.back(1);
- } else {
- v01 = 2.0f*v11-v21;
- v02 = 2.0f*v12-v22;
- }
- }
-
- __forceinline void init_corner(const CatmullClarkRing& edge0,
- Vertex& v00, const Vertex& v01, const Vertex& v02,
- const Vertex& v10, const Vertex& v11, const Vertex& v12,
- const Vertex& v20, const Vertex& v21, const Vertex& v22)
- {
- const bool MAYBE_UNUSED has_back1 = edge0.has_opposite_back(1);
- const bool has_back0 = edge0.has_opposite_back(0);
- const bool has_front1 = edge0.has_opposite_front(1);
- const bool MAYBE_UNUSED has_front2 = edge0.has_opposite_front(2);
-
- if (likely(has_back0)) {
- if (likely(has_front1)) { assert(has_back1 && has_front2); v00 = edge0.back(3); }
- else { assert(!has_back1); v00 = 2.0f*v01-v02; }
- }
- else {
- if (likely(has_front1)) { assert(!has_front2); v00 = 2.0f*v10-v20; }
- else v00 = convex_corner(edge0.vertex_crease_weight,v01,v02,v10,v11,v12,v20,v21,v22);
- }
- }
-
- void init(const CatmullClarkPatch& patch)
- {
- /* fill inner vertices */
- const Vertex v11 = v[1][1] = patch.ring[0].vtx;
- const Vertex v12 = v[1][2] = patch.ring[1].vtx;
- const Vertex v22 = v[2][2] = patch.ring[2].vtx;
- const Vertex v21 = v[2][1] = patch.ring[3].vtx;
-
- /* fill border vertices */
- init_border(patch.ring[0],v[0][1],v[0][2],v11,v12,v21,v22);
- init_border(patch.ring[1],v[1][3],v[2][3],v12,v22,v11,v21);
- init_border(patch.ring[2],v[3][2],v[3][1],v22,v21,v12,v11);
- init_border(patch.ring[3],v[2][0],v[1][0],v21,v11,v22,v12);
-
- /* fill corner vertices */
- init_corner(patch.ring[0],v[0][0],v[0][1],v[0][2],v[1][0],v11,v12,v[2][0],v21,v22);
- init_corner(patch.ring[1],v[0][3],v[1][3],v[2][3],v[0][2],v12,v22,v[0][1],v11,v21);
- init_corner(patch.ring[2],v[3][3],v[3][2],v[3][1],v[2][3],v22,v21,v[1][3],v12,v11);
- init_corner(patch.ring[3],v[3][0],v[2][0],v[1][0],v[3][1],v21,v11,v[3][2],v22,v12);
- }
-
- void init_border(const HalfEdge* edge0, const char* vertices, size_t stride,
- Vertex& v01, Vertex& v02,
- const Vertex& v11, const Vertex& v12,
- const Vertex& v21, const Vertex& v22)
- {
- if (likely(edge0->hasOpposite()))
- {
- const HalfEdge* e = edge0->opposite()->next()->next();
- v01 = load(e,vertices,stride);
- v02 = load(e->next(),vertices,stride);
- } else {
- v01 = 2.0f*v11-v21;
- v02 = 2.0f*v12-v22;
- }
- }
-
- void init_corner(const HalfEdge* edge0, const char* vertices, size_t stride,
- Vertex& v00, const Vertex& v01, const Vertex& v02,
- const Vertex& v10, const Vertex& v11, const Vertex& v12,
- const Vertex& v20, const Vertex& v21, const Vertex& v22)
- {
- const bool has_back0 = edge0->hasOpposite();
- const bool has_front1 = edge0->prev()->hasOpposite();
-
- if (likely(has_back0))
- {
- const HalfEdge* e = edge0->opposite()->next();
- if (likely(has_front1))
- {
- assert(e->hasOpposite());
- assert(edge0->prev()->opposite()->prev()->hasOpposite());
- v00 = load(e->opposite()->prev(),vertices,stride);
- }
- else {
- assert(!e->hasOpposite());
- v00 = 2.0f*v01-v02;
- }
- }
- else
- {
- if (likely(has_front1)) {
- assert(!edge0->prev()->opposite()->prev()->hasOpposite());
- v00 = 2.0f*v10-v20;
- }
- else {
- assert(edge0->vertex_crease_weight == 0.0f || std::isinf(edge0->vertex_crease_weight));
- v00 = convex_corner(edge0->vertex_crease_weight,v01,v02,v10,v11,v12,v20,v21,v22);
- }
- }
- }
-
- void init(const HalfEdge* edge0, const char* vertices, size_t stride)
- {
- assert( edge0->isRegularFace() );
-
- /* fill inner vertices */
- const Vertex v11 = v[1][1] = load(edge0,vertices,stride); const HalfEdge* edge1 = edge0->next();
- const Vertex v12 = v[1][2] = load(edge1,vertices,stride); const HalfEdge* edge2 = edge1->next();
- const Vertex v22 = v[2][2] = load(edge2,vertices,stride); const HalfEdge* edge3 = edge2->next();
- const Vertex v21 = v[2][1] = load(edge3,vertices,stride); assert(edge0 == edge3->next());
-
- /* fill border vertices */
- init_border(edge0,vertices,stride,v[0][1],v[0][2],v11,v12,v21,v22);
- init_border(edge1,vertices,stride,v[1][3],v[2][3],v12,v22,v11,v21);
- init_border(edge2,vertices,stride,v[3][2],v[3][1],v22,v21,v12,v11);
- init_border(edge3,vertices,stride,v[2][0],v[1][0],v21,v11,v22,v12);
-
- /* fill corner vertices */
- init_corner(edge0,vertices,stride,v[0][0],v[0][1],v[0][2],v[1][0],v11,v12,v[2][0],v21,v22);
- init_corner(edge1,vertices,stride,v[0][3],v[1][3],v[2][3],v[0][2],v12,v22,v[0][1],v11,v21);
- init_corner(edge2,vertices,stride,v[3][3],v[3][2],v[3][1],v[2][3],v22,v21,v[1][3],v12,v11);
- init_corner(edge3,vertices,stride,v[3][0],v[2][0],v[1][0],v[3][1],v21,v11,v[3][2],v22,v12);
- }
-
- __forceinline BBox<Vertex> bounds() const
- {
- const Vertex* const cv = &v[0][0];
- BBox<Vertex> bounds (cv[0]);
- for (size_t i=1; i<16 ; i++)
- bounds.extend( cv[i] );
- return bounds;
- }
-
- __forceinline Vertex eval(const float uu, const float vv) const
- {
- const Vec4f v_n = BSplineBasis::eval(vv);
- const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
- const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
- const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
- const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
-
- const Vec4f u_n = BSplineBasis::eval(uu);
- return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
- }
-
- __forceinline Vertex eval_du(const float uu, const float vv) const
- {
- const Vec4f v_n = BSplineBasis::eval(vv);
- const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
- const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
- const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
- const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
-
- const Vec4f u_n = BSplineBasis::derivative(uu);
- return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
- }
-
- __forceinline Vertex eval_dv(const float uu, const float vv) const
- {
- const Vec4f v_n = BSplineBasis::derivative(vv);
- const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
- const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
- const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
- const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
-
- const Vec4f u_n = BSplineBasis::eval(uu);
- return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
- }
-
- __forceinline Vertex eval_dudu(const float uu, const float vv) const
- {
- const Vec4f v_n = BSplineBasis::eval(vv);
- const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
- const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
- const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
- const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
-
- const Vec4f u_n = BSplineBasis::derivative2(uu);
- return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
- }
-
- __forceinline Vertex eval_dvdv(const float uu, const float vv) const
- {
- const Vec4f v_n = BSplineBasis::derivative2(vv);
- const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
- const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
- const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
- const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
-
- const Vec4f u_n = BSplineBasis::eval(uu);
- return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
- }
-
- __forceinline Vertex eval_dudv(const float uu, const float vv) const
- {
- const Vec4f v_n = BSplineBasis::derivative(vv);
- const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
- const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
- const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
- const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
-
- const Vec4f u_n = BSplineBasis::derivative(uu);
- return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
- }
-
- __forceinline Vertex normal(const float uu, const float vv) const
- {
- const Vertex tu = eval_du(uu,vv);
- const Vertex tv = eval_dv(uu,vv);
- return cross(tu,tv);
- }
-
- template<typename T>
- __forceinline Vec3<T> eval(const T& uu, const T& vv, const Vec4<T>& u_n, const Vec4<T>& v_n) const
- {
- const T curve0_x = madd(v_n[0],T(v[0][0].x),madd(v_n[1],T(v[1][0].x),madd(v_n[2],T(v[2][0].x),v_n[3] * T(v[3][0].x))));
- const T curve1_x = madd(v_n[0],T(v[0][1].x),madd(v_n[1],T(v[1][1].x),madd(v_n[2],T(v[2][1].x),v_n[3] * T(v[3][1].x))));
- const T curve2_x = madd(v_n[0],T(v[0][2].x),madd(v_n[1],T(v[1][2].x),madd(v_n[2],T(v[2][2].x),v_n[3] * T(v[3][2].x))));
- const T curve3_x = madd(v_n[0],T(v[0][3].x),madd(v_n[1],T(v[1][3].x),madd(v_n[2],T(v[2][3].x),v_n[3] * T(v[3][3].x))));
- const T x = madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));
-
- const T curve0_y = madd(v_n[0],T(v[0][0].y),madd(v_n[1],T(v[1][0].y),madd(v_n[2],T(v[2][0].y),v_n[3] * T(v[3][0].y))));
- const T curve1_y = madd(v_n[0],T(v[0][1].y),madd(v_n[1],T(v[1][1].y),madd(v_n[2],T(v[2][1].y),v_n[3] * T(v[3][1].y))));
- const T curve2_y = madd(v_n[0],T(v[0][2].y),madd(v_n[1],T(v[1][2].y),madd(v_n[2],T(v[2][2].y),v_n[3] * T(v[3][2].y))));
- const T curve3_y = madd(v_n[0],T(v[0][3].y),madd(v_n[1],T(v[1][3].y),madd(v_n[2],T(v[2][3].y),v_n[3] * T(v[3][3].y))));
- const T y = madd(u_n[0],curve0_y,madd(u_n[1],curve1_y,madd(u_n[2],curve2_y,u_n[3] * curve3_y)));
-
- const T curve0_z = madd(v_n[0],T(v[0][0].z),madd(v_n[1],T(v[1][0].z),madd(v_n[2],T(v[2][0].z),v_n[3] * T(v[3][0].z))));
- const T curve1_z = madd(v_n[0],T(v[0][1].z),madd(v_n[1],T(v[1][1].z),madd(v_n[2],T(v[2][1].z),v_n[3] * T(v[3][1].z))));
- const T curve2_z = madd(v_n[0],T(v[0][2].z),madd(v_n[1],T(v[1][2].z),madd(v_n[2],T(v[2][2].z),v_n[3] * T(v[3][2].z))));
- const T curve3_z = madd(v_n[0],T(v[0][3].z),madd(v_n[1],T(v[1][3].z),madd(v_n[2],T(v[2][3].z),v_n[3] * T(v[3][3].z))));
- const T z = madd(u_n[0],curve0_z,madd(u_n[1],curve1_z,madd(u_n[2],curve2_z,u_n[3] * curve3_z)));
-
- return Vec3<T>(x,y,z);
- }
-
- template<typename T>
- __forceinline Vec3<T> eval(const T& uu, const T& vv) const
- {
- const Vec4<T> u_n = BSplineBasis::eval(uu);
- const Vec4<T> v_n = BSplineBasis::eval(vv);
- return eval(uu,vv,u_n,v_n);
- }
-
- template<typename T>
- __forceinline Vec3<T> eval_du(const T& uu, const T& vv) const
- {
- const Vec4<T> u_n = BSplineBasis::derivative(uu);
- const Vec4<T> v_n = BSplineBasis::eval(vv);
- return eval(uu,vv,u_n,v_n);
- }
-
- template<typename T>
- __forceinline Vec3<T> eval_dv(const T& uu, const T& vv) const
- {
- const Vec4<T> u_n = BSplineBasis::eval(uu);
- const Vec4<T> v_n = BSplineBasis::derivative(vv);
- return eval(uu,vv,u_n,v_n);
- }
-
- template<typename T>
- __forceinline Vec3<T> eval_dudu(const T& uu, const T& vv) const
- {
- const Vec4<T> u_n = BSplineBasis::derivative2(uu);
- const Vec4<T> v_n = BSplineBasis::eval(vv);
- return eval(uu,vv,u_n,v_n);
- }
-
- template<typename T>
- __forceinline Vec3<T> eval_dvdv(const T& uu, const T& vv) const
- {
- const Vec4<T> u_n = BSplineBasis::eval(uu);
- const Vec4<T> v_n = BSplineBasis::derivative2(vv);
- return eval(uu,vv,u_n,v_n);
- }
-
- template<typename T>
- __forceinline Vec3<T> eval_dudv(const T& uu, const T& vv) const
- {
- const Vec4<T> u_n = BSplineBasis::derivative(uu);
- const Vec4<T> v_n = BSplineBasis::derivative(vv);
- return eval(uu,vv,u_n,v_n);
- }
-
- template<typename T>
- __forceinline Vec3<T> normal(const T& uu, const T& vv) const {
- return cross(eval_du(uu,vv),eval_dv(uu,vv));
- }
-
- void eval(const float u, const float v,
- Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
- const float dscale = 1.0f) const
- {
- if (P) {
- *P = eval(u,v);
- }
- if (dPdu) {
- assert(dPdu); *dPdu = eval_du(u,v)*dscale;
- assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
- }
- if (ddPdudu) {
- assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
- assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
- assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
- }
- }
-
- template<class vfloat>
- __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n) const
- {
- const vfloat curve0_x = madd(v_n[0],vfloat(v[0][0][i]),madd(v_n[1],vfloat(v[1][0][i]),madd(v_n[2],vfloat(v[2][0][i]),v_n[3] * vfloat(v[3][0][i]))));
- const vfloat curve1_x = madd(v_n[0],vfloat(v[0][1][i]),madd(v_n[1],vfloat(v[1][1][i]),madd(v_n[2],vfloat(v[2][1][i]),v_n[3] * vfloat(v[3][1][i]))));
- const vfloat curve2_x = madd(v_n[0],vfloat(v[0][2][i]),madd(v_n[1],vfloat(v[1][2][i]),madd(v_n[2],vfloat(v[2][2][i]),v_n[3] * vfloat(v[3][2][i]))));
- const vfloat curve3_x = madd(v_n[0],vfloat(v[0][3][i]),madd(v_n[1],vfloat(v[1][3][i]),madd(v_n[2],vfloat(v[2][3][i]),v_n[3] * vfloat(v[3][3][i]))));
- return madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));
- }
-
- template<typename vbool, typename vfloat>
- void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
- const float dscale, const size_t dstride, const size_t N) const
- {
- if (P) {
- const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
- const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv,u_n,v_n));
- }
- if (dPdu)
- {
- {
- assert(dPdu);
- const Vec4<vfloat> u_n = BSplineBasis::derivative(uu);
- const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,dPdu+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
- }
- {
- assert(dPdv);
- const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
- const Vec4<vfloat> v_n = BSplineBasis::derivative(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,dPdv+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
- }
- }
- if (ddPdudu)
- {
- {
- assert(ddPdudu);
- const Vec4<vfloat> u_n = BSplineBasis::derivative2(uu);
- const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudu+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
- }
- {
- assert(ddPdvdv);
- const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
- const Vec4<vfloat> v_n = BSplineBasis::derivative2(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdvdv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
- }
- {
- assert(ddPdudv);
- const Vec4<vfloat> u_n = BSplineBasis::derivative(uu);
- const Vec4<vfloat> v_n = BSplineBasis::derivative(vv);
- for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
- }
- }
- }
-
- friend __forceinline embree_ostream operator<<(embree_ostream o, const BSplinePatchT& p)
- {
- for (size_t y=0; y<4; y++)
- for (size_t x=0; x<4; x++)
- o << "[" << y << "][" << x << "] " << p.v[y][x] << embree_endl;
- return o;
- }
-
- public:
- Vertex v[4][4];
- };
-
- typedef BSplinePatchT<Vec3fa,Vec3fa_t> BSplinePatch3fa;
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_coefficients.h b/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_coefficients.h
deleted file mode 100644
index 05031cf6b9..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_coefficients.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/geometry.h"
-
-namespace embree
-{
- static const size_t MAX_PATCH_VALENCE = 16; //!< maximum number of vertices of a patch
- static const size_t MAX_RING_FACE_VALENCE = 64; //!< maximum number of faces per ring
- static const size_t MAX_RING_EDGE_VALENCE = 2*64; //!< maximum number of edges per ring
-
- class CatmullClarkPrecomputedCoefficients
- {
- private:
-
- float table_cos_2PI_div_n[MAX_RING_FACE_VALENCE+1];
-
- float* table_limittangent_a[MAX_RING_FACE_VALENCE+1];
- float* table_limittangent_b[MAX_RING_FACE_VALENCE+1];
- float table_limittangent_c[MAX_RING_FACE_VALENCE+1];
-
- __forceinline float set_cos_2PI_div_n(const size_t n) {
- if (unlikely(n == 0)) return 1.0f;
- return cosf(2.0f*float(pi)/(float)n);
- }
-
- __forceinline float set_limittangent_a(const size_t i, const size_t n)
- {
- if (unlikely(n == 0)) return 1.0f;
- const float c0 = 1.0f/(float)n * 1.0f / sqrtf(4.0f + cosf(float(pi)/(float)n)*cosf(float(pi)/(float)n));
- const float c1 = (1.0f/(float)n + cosf(float(pi)/(float)n) * c0);
- return cosf(2.0f*float(pi)*(float)i/(float)n) * c1;
- }
-
- __forceinline float set_limittangent_b(const size_t i, const size_t n)
- {
- if (unlikely(n == 0)) return 1.0f;
- const float c0 = 1.0f/(float)n * 1.0f / sqrtf(4.0f + cosf(float(pi)/(float)n)*cosf(float(pi)/(float)n));
- return cosf((2.0f*float(pi)*i+float(pi))/(float)n) * c0;
- }
-
- __forceinline float set_limittangent_c(const size_t n)
- {
- if (unlikely(n == 0)) return 1.0f;
- return 2.0f/16.0f * (5.0f + cosf(2.0f*float(pi)/(float)n) + cosf(float(pi)/(float)n) * sqrtf(18.0f+2.0f*cosf(2.0f*float(pi)/(float)n)));
- }
-
- public:
-
- __forceinline float cos_2PI_div_n(const size_t n)
- {
- if (likely(n <= MAX_RING_FACE_VALENCE))
- return table_cos_2PI_div_n[n];
- else
- return set_cos_2PI_div_n(n);
- }
-
- __forceinline float limittangent_a(const size_t i, const size_t n)
- {
- assert(n <= MAX_RING_FACE_VALENCE);
- assert(i < n);
- return table_limittangent_a[n][i];
- }
-
- __forceinline float limittangent_b(const size_t i, const size_t n)
- {
- assert(n <= MAX_RING_FACE_VALENCE);
- assert(i < n);
- return table_limittangent_b[n][i];
- }
-
- __forceinline float limittangent_c(const size_t n)
- {
- assert(n <= MAX_RING_FACE_VALENCE);
- return table_limittangent_c[n];
- }
-
- static CatmullClarkPrecomputedCoefficients table;
-
- CatmullClarkPrecomputedCoefficients();
- ~CatmullClarkPrecomputedCoefficients();
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_patch.h b/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_patch.h
deleted file mode 100644
index ab1d63594a..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_patch.h
+++ /dev/null
@@ -1,562 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "catmullclark_ring.h"
-#include "bezier_curve.h"
-
-namespace embree
-{
- template<typename Vertex, typename Vertex_t = Vertex>
- class __aligned(64) CatmullClarkPatchT
- {
- public:
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
- typedef typename CatmullClark1Ring::Type Type;
-
- array_t<CatmullClark1RingT<Vertex,Vertex_t>,4> ring;
-
- public:
- __forceinline CatmullClarkPatchT () {}
-
- __forceinline CatmullClarkPatchT (const HalfEdge* first_half_edge, const char* vertices, size_t stride) {
- init(first_half_edge,vertices,stride);
- }
-
- __forceinline CatmullClarkPatchT (const HalfEdge* first_half_edge, const BufferView<Vec3fa>& vertices) {
- init(first_half_edge,vertices.getPtr(),vertices.getStride());
- }
-
- __forceinline void init (const HalfEdge* first_half_edge, const char* vertices, size_t stride)
- {
- for (unsigned i=0; i<4; i++)
- ring[i].init(first_half_edge+i,vertices,stride);
-
- assert(verify());
- }
-
- __forceinline size_t bytes() const {
- return ring[0].bytes()+ring[1].bytes()+ring[2].bytes()+ring[3].bytes();
- }
-
- __forceinline void serialize(void* ptr, size_t& ofs) const
- {
- for (size_t i=0; i<4; i++)
- ring[i].serialize((char*)ptr,ofs);
- }
-
- __forceinline void deserialize(void* ptr)
- {
- size_t ofs = 0;
- for (size_t i=0; i<4; i++)
- ring[i].deserialize((char*)ptr,ofs);
- }
-
- __forceinline BBox3fa bounds() const
- {
- BBox3fa bounds (ring[0].bounds());
- for (size_t i=1; i<4; i++)
- bounds.extend(ring[i].bounds());
- return bounds;
- }
-
- __forceinline Type type() const
- {
- const int ty0 = ring[0].type() ^ CatmullClark1Ring::TYPE_CREASES;
- const int ty1 = ring[1].type() ^ CatmullClark1Ring::TYPE_CREASES;
- const int ty2 = ring[2].type() ^ CatmullClark1Ring::TYPE_CREASES;
- const int ty3 = ring[3].type() ^ CatmullClark1Ring::TYPE_CREASES;
- return (Type) ((ty0 & ty1 & ty2 & ty3) ^ CatmullClark1Ring::TYPE_CREASES);
- }
-
- __forceinline bool isFinalResolution(float res) const {
- return ring[0].isFinalResolution(res) && ring[1].isFinalResolution(res) && ring[2].isFinalResolution(res) && ring[3].isFinalResolution(res);
- }
-
- static __forceinline void init_regular(const CatmullClark1RingT<Vertex,Vertex_t>& p0,
- const CatmullClark1RingT<Vertex,Vertex_t>& p1,
- CatmullClark1RingT<Vertex,Vertex_t>& dest0,
- CatmullClark1RingT<Vertex,Vertex_t>& dest1)
- {
- assert(p1.face_valence > 2);
- dest1.vertex_level = dest0.vertex_level = p0.edge_level;
- dest1.face_valence = dest0.face_valence = 4;
- dest1.edge_valence = dest0.edge_valence = 8;
- dest1.border_index = dest0.border_index = -1;
- dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
- dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
-
- dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
- dest1.ring[1] = dest0.ring[7] = (Vertex_t)p1.ring[0];
- dest1.ring[0] = dest0.ring[6] = (Vertex_t)p1.vtx;
- dest1.ring[7] = dest0.ring[5] = (Vertex_t)p1.ring[4];
- dest1.ring[6] = dest0.ring[4] = (Vertex_t)p0.ring[p0.edge_valence-1];
- dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.edge_valence-2];
- dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
- dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
-
- dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
- dest1.crease_weight[0] = dest0.crease_weight[3] = p1.crease_weight[1];
- dest1.crease_weight[3] = dest0.crease_weight[2] = 0.0f;
- dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
-
- if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
- {
- dest0.eval_start_index = 3;
- dest1.eval_start_index = 0;
- dest0.eval_unique_identifier = p0.eval_unique_identifier;
- dest1.eval_unique_identifier = p0.eval_unique_identifier;
- }
- else
- {
- dest0.eval_start_index = 1;
- dest1.eval_start_index = 2;
- dest0.eval_unique_identifier = p1.eval_unique_identifier;
- dest1.eval_unique_identifier = p1.eval_unique_identifier;
- }
- }
-
- static __forceinline void init_border(const CatmullClark1RingT<Vertex,Vertex_t> &p0,
- const CatmullClark1RingT<Vertex,Vertex_t> &p1,
- CatmullClark1RingT<Vertex,Vertex_t> &dest0,
- CatmullClark1RingT<Vertex,Vertex_t> &dest1)
- {
- dest1.vertex_level = dest0.vertex_level = p0.edge_level;
- dest1.face_valence = dest0.face_valence = 3;
- dest1.edge_valence = dest0.edge_valence = 6;
- dest0.border_index = 2;
- dest1.border_index = 4;
- dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
- dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
-
- dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
- dest1.ring[1] = dest0.ring[5] = (Vertex_t)p1.ring[0];
- dest1.ring[0] = dest0.ring[4] = (Vertex_t)p1.vtx;
- dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.border_index+1]; // dummy
- dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
- dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
-
- dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
- dest1.crease_weight[0] = dest0.crease_weight[2] = p1.crease_weight[1];
- dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
-
- if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
- {
- dest0.eval_start_index = 1;
- dest1.eval_start_index = 2;
- dest0.eval_unique_identifier = p0.eval_unique_identifier;
- dest1.eval_unique_identifier = p0.eval_unique_identifier;
- }
- else
- {
- dest0.eval_start_index = 2;
- dest1.eval_start_index = 0;
- dest0.eval_unique_identifier = p1.eval_unique_identifier;
- dest1.eval_unique_identifier = p1.eval_unique_identifier;
- }
- }
-
- static __forceinline void init_regular(const Vertex_t &center, const Vertex_t center_ring[8], const unsigned int offset, CatmullClark1RingT<Vertex,Vertex_t> &dest)
- {
- dest.vertex_level = 0.0f;
- dest.face_valence = 4;
- dest.edge_valence = 8;
- dest.border_index = -1;
- dest.vtx = (Vertex_t)center;
- dest.vertex_crease_weight = 0.0f;
- for (size_t i=0; i<8; i++)
- dest.ring[i] = (Vertex_t)center_ring[(offset+i)%8];
- for (size_t i=0; i<4; i++)
- dest.crease_weight[i] = 0.0f;
-
- dest.eval_start_index = (8-offset)>>1;
- if (dest.eval_start_index >= dest.face_valence) dest.eval_start_index -= dest.face_valence;
- assert( dest.eval_start_index < dest.face_valence );
- dest.eval_unique_identifier = 0;
- }
-
- __noinline void subdivide(array_t<CatmullClarkPatchT,4>& patch) const
- {
- ring[0].subdivide(patch[0].ring[0]);
- ring[1].subdivide(patch[1].ring[1]);
- ring[2].subdivide(patch[2].ring[2]);
- ring[3].subdivide(patch[3].ring[3]);
-
- patch[0].ring[0].edge_level = 0.5f*ring[0].edge_level;
- patch[0].ring[1].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
- patch[0].ring[2].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
- patch[0].ring[3].edge_level = 0.5f*ring[3].edge_level;
-
- patch[1].ring[0].edge_level = 0.5f*ring[0].edge_level;
- patch[1].ring[1].edge_level = 0.5f*ring[1].edge_level;
- patch[1].ring[2].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
- patch[1].ring[3].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
-
- patch[2].ring[0].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
- patch[2].ring[1].edge_level = 0.5f*ring[1].edge_level;
- patch[2].ring[2].edge_level = 0.5f*ring[2].edge_level;
- patch[2].ring[3].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
-
- patch[3].ring[0].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
- patch[3].ring[1].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
- patch[3].ring[2].edge_level = 0.5f*ring[2].edge_level;
- patch[3].ring[3].edge_level = 0.5f*ring[3].edge_level;
-
- const bool regular0 = ring[0].has_last_face() && ring[1].face_valence > 2;
- if (likely(regular0))
- init_regular(patch[0].ring[0],patch[1].ring[1],patch[0].ring[1],patch[1].ring[0]);
- else
- init_border(patch[0].ring[0],patch[1].ring[1],patch[0].ring[1],patch[1].ring[0]);
-
- const bool regular1 = ring[1].has_last_face() && ring[2].face_valence > 2;
- if (likely(regular1))
- init_regular(patch[1].ring[1],patch[2].ring[2],patch[1].ring[2],patch[2].ring[1]);
- else
- init_border(patch[1].ring[1],patch[2].ring[2],patch[1].ring[2],patch[2].ring[1]);
-
- const bool regular2 = ring[2].has_last_face() && ring[3].face_valence > 2;
- if (likely(regular2))
- init_regular(patch[2].ring[2],patch[3].ring[3],patch[2].ring[3],patch[3].ring[2]);
- else
- init_border(patch[2].ring[2],patch[3].ring[3],patch[2].ring[3],patch[3].ring[2]);
-
- const bool regular3 = ring[3].has_last_face() && ring[0].face_valence > 2;
- if (likely(regular3))
- init_regular(patch[3].ring[3],patch[0].ring[0],patch[3].ring[0],patch[0].ring[3]);
- else
- init_border(patch[3].ring[3],patch[0].ring[0],patch[3].ring[0],patch[0].ring[3]);
-
- Vertex_t center = (ring[0].vtx + ring[1].vtx + ring[2].vtx + ring[3].vtx) * 0.25f;
-
- Vertex_t center_ring[8];
- center_ring[0] = (Vertex_t)patch[3].ring[3].ring[0];
- center_ring[7] = (Vertex_t)patch[3].ring[3].vtx;
- center_ring[6] = (Vertex_t)patch[2].ring[2].ring[0];
- center_ring[5] = (Vertex_t)patch[2].ring[2].vtx;
- center_ring[4] = (Vertex_t)patch[1].ring[1].ring[0];
- center_ring[3] = (Vertex_t)patch[1].ring[1].vtx;
- center_ring[2] = (Vertex_t)patch[0].ring[0].ring[0];
- center_ring[1] = (Vertex_t)patch[0].ring[0].vtx;
-
- init_regular(center,center_ring,0,patch[0].ring[2]);
- init_regular(center,center_ring,2,patch[1].ring[3]);
- init_regular(center,center_ring,4,patch[2].ring[0]);
- init_regular(center,center_ring,6,patch[3].ring[1]);
-
- assert(patch[0].verify());
- assert(patch[1].verify());
- assert(patch[2].verify());
- assert(patch[3].verify());
- }
-
- bool verify() const {
- return ring[0].hasValidPositions() && ring[1].hasValidPositions() && ring[2].hasValidPositions() && ring[3].hasValidPositions();
- }
-
- __forceinline void init( FinalQuad& quad ) const
- {
- quad.vtx[0] = (Vertex_t)ring[0].vtx;
- quad.vtx[1] = (Vertex_t)ring[1].vtx;
- quad.vtx[2] = (Vertex_t)ring[2].vtx;
- quad.vtx[3] = (Vertex_t)ring[3].vtx;
- };
-
- friend __forceinline embree_ostream operator<<(embree_ostream o, const CatmullClarkPatchT &p)
- {
- o << "CatmullClarkPatch { " << embree_endl;
- for (size_t i=0; i<4; i++)
- o << "ring" << i << ": " << p.ring[i] << embree_endl;
- o << "}" << embree_endl;
- return o;
- }
- };
-
- typedef CatmullClarkPatchT<Vec3fa,Vec3fa_t> CatmullClarkPatch3fa;
-
- template<typename Vertex, typename Vertex_t = Vertex>
- class __aligned(64) GeneralCatmullClarkPatchT
- {
- public:
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
- typedef BezierCurveT<Vertex> BezierCurve;
-
- static const unsigned SIZE = MAX_PATCH_VALENCE;
- DynamicStackArray<GeneralCatmullClark1RingT<Vertex,Vertex_t>,8,SIZE> ring;
- unsigned N;
-
- __forceinline GeneralCatmullClarkPatchT ()
- : N(0) {}
-
- GeneralCatmullClarkPatchT (const HalfEdge* h, const char* vertices, size_t stride) {
- init(h,vertices,stride);
- }
-
- __forceinline GeneralCatmullClarkPatchT (const HalfEdge* first_half_edge, const BufferView<Vec3fa>& vertices) {
- init(first_half_edge,vertices.getPtr(),vertices.getStride());
- }
-
- __forceinline void init (const HalfEdge* h, const char* vertices, size_t stride)
- {
- unsigned int i = 0;
- const HalfEdge* edge = h;
- do {
- ring[i].init(edge,vertices,stride);
- edge = edge->next();
- i++;
- } while ((edge != h) && (i < SIZE));
- N = i;
- }
-
- __forceinline unsigned size() const {
- return N;
- }
-
- __forceinline bool isQuadPatch() const {
- return (N == 4) && ring[0].only_quads && ring[1].only_quads && ring[2].only_quads && ring[3].only_quads;
- }
-
- static __forceinline void init_regular(const CatmullClark1RingT<Vertex,Vertex_t>& p0,
- const CatmullClark1RingT<Vertex,Vertex_t>& p1,
- CatmullClark1RingT<Vertex,Vertex_t>& dest0,
- CatmullClark1RingT<Vertex,Vertex_t>& dest1)
- {
- assert(p1.face_valence > 2);
- dest1.vertex_level = dest0.vertex_level = p0.edge_level;
- dest1.face_valence = dest0.face_valence = 4;
- dest1.edge_valence = dest0.edge_valence = 8;
- dest1.border_index = dest0.border_index = -1;
- dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
- dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
-
- dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
- dest1.ring[1] = dest0.ring[7] = (Vertex_t)p1.ring[0];
- dest1.ring[0] = dest0.ring[6] = (Vertex_t)p1.vtx;
- dest1.ring[7] = dest0.ring[5] = (Vertex_t)p1.ring[4];
- dest1.ring[6] = dest0.ring[4] = (Vertex_t)p0.ring[p0.edge_valence-1];
- dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.edge_valence-2];
- dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
- dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
-
- dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
- dest1.crease_weight[0] = dest0.crease_weight[3] = p1.crease_weight[1];
- dest1.crease_weight[3] = dest0.crease_weight[2] = 0.0f;
- dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
-
- if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
- {
- dest0.eval_start_index = 3;
- dest1.eval_start_index = 0;
- dest0.eval_unique_identifier = p0.eval_unique_identifier;
- dest1.eval_unique_identifier = p0.eval_unique_identifier;
- }
- else
- {
- dest0.eval_start_index = 1;
- dest1.eval_start_index = 2;
- dest0.eval_unique_identifier = p1.eval_unique_identifier;
- dest1.eval_unique_identifier = p1.eval_unique_identifier;
- }
- }
-
-
- static __forceinline void init_border(const CatmullClark1RingT<Vertex,Vertex_t> &p0,
- const CatmullClark1RingT<Vertex,Vertex_t> &p1,
- CatmullClark1RingT<Vertex,Vertex_t> &dest0,
- CatmullClark1RingT<Vertex,Vertex_t> &dest1)
- {
- dest1.vertex_level = dest0.vertex_level = p0.edge_level;
- dest1.face_valence = dest0.face_valence = 3;
- dest1.edge_valence = dest0.edge_valence = 6;
- dest0.border_index = 2;
- dest1.border_index = 4;
- dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
- dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
-
- dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
- dest1.ring[1] = dest0.ring[5] = (Vertex_t)p1.ring[0];
- dest1.ring[0] = dest0.ring[4] = (Vertex_t)p1.vtx;
- dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.border_index+1]; // dummy
- dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
- dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
-
- dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
- dest1.crease_weight[0] = dest0.crease_weight[2] = p1.crease_weight[1];
- dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
-
- if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
- {
- dest0.eval_start_index = 1;
- dest1.eval_start_index = 2;
- dest0.eval_unique_identifier = p0.eval_unique_identifier;
- dest1.eval_unique_identifier = p0.eval_unique_identifier;
- }
- else
- {
- dest0.eval_start_index = 2;
- dest1.eval_start_index = 0;
- dest0.eval_unique_identifier = p1.eval_unique_identifier;
- dest1.eval_unique_identifier = p1.eval_unique_identifier;
- }
- }
-
- static __forceinline void init_regular(const Vertex_t &center, const array_t<Vertex_t,2*SIZE>& center_ring, const float vertex_level, const unsigned int N, const unsigned int offset, CatmullClark1RingT<Vertex,Vertex_t> &dest)
- {
- assert(N<(MAX_RING_FACE_VALENCE));
- assert(2*N<(MAX_RING_EDGE_VALENCE));
- dest.vertex_level = vertex_level;
- dest.face_valence = N;
- dest.edge_valence = 2*N;
- dest.border_index = -1;
- dest.vtx = (Vertex_t)center;
- dest.vertex_crease_weight = 0.0f;
- for (unsigned i=0; i<2*N; i++) {
- dest.ring[i] = (Vertex_t)center_ring[(2*N+offset+i-1)%(2*N)];
- assert(isvalid(dest.ring[i]));
- }
- for (unsigned i=0; i<N; i++)
- dest.crease_weight[i] = 0.0f;
-
- assert(offset <= 2*N);
- dest.eval_start_index = (2*N-offset)>>1;
- if (dest.eval_start_index >= dest.face_valence) dest.eval_start_index -= dest.face_valence;
-
- assert( dest.eval_start_index < dest.face_valence );
- dest.eval_unique_identifier = 0;
- }
-
- __noinline void subdivide(array_t<CatmullClarkPatch,SIZE>& patch, unsigned& N_o) const
- {
- N_o = N;
- assert( N );
- for (unsigned i=0; i<N; i++) {
- unsigned ip1 = (i+1)%N; // FIXME: %
- ring[i].subdivide(patch[i].ring[0]);
- patch[i] .ring[0].edge_level = 0.5f*ring[i].edge_level;
- patch[ip1].ring[3].edge_level = 0.5f*ring[i].edge_level;
-
- assert( patch[i].ring[0].hasValidPositions() );
-
- }
- assert(N < 2*SIZE);
- Vertex_t center = Vertex_t(0.0f);
- array_t<Vertex_t,2*SIZE> center_ring;
- float center_vertex_level = 2.0f; // guarantees that irregular vertices get always isolated also for non-quads
-
- for (unsigned i=0; i<N; i++)
- {
- unsigned ip1 = (i+1)%N; // FIXME: %
- unsigned im1 = (i+N-1)%N; // FIXME: %
- bool regular = ring[i].has_last_face() && ring[ip1].face_valence > 2;
- if (likely(regular)) init_regular(patch[i].ring[0],patch[ip1].ring[0],patch[i].ring[1],patch[ip1].ring[3]);
- else init_border (patch[i].ring[0],patch[ip1].ring[0],patch[i].ring[1],patch[ip1].ring[3]);
-
- assert( patch[i].ring[1].hasValidPositions() );
- assert( patch[ip1].ring[3].hasValidPositions() );
-
- float level = 0.25f*(ring[im1].edge_level+ring[ip1].edge_level);
- patch[i].ring[1].edge_level = patch[ip1].ring[2].edge_level = level;
- center_vertex_level = max(center_vertex_level,level);
-
- center += ring[i].vtx;
- center_ring[2*i+0] = (Vertex_t)patch[i].ring[0].vtx;
- center_ring[2*i+1] = (Vertex_t)patch[i].ring[0].ring[0];
- }
- center /= float(N);
-
- for (unsigned int i=0; i<N; i++) {
- init_regular(center,center_ring,center_vertex_level,N,2*i,patch[i].ring[2]);
-
- assert( patch[i].ring[2].hasValidPositions() );
- }
- }
-
- void init(CatmullClarkPatch& patch) const
- {
- assert(size() == 4);
- ring[0].convert(patch.ring[0]);
- ring[1].convert(patch.ring[1]);
- ring[2].convert(patch.ring[2]);
- ring[3].convert(patch.ring[3]);
- }
-
- static void fix_quad_ring_order (array_t<CatmullClarkPatch,GeneralCatmullClarkPatchT::SIZE>& patches)
- {
- CatmullClark1Ring patches1ring1 = patches[1].ring[1];
- patches[1].ring[1] = patches[1].ring[0]; // FIXME: optimize these assignments
- patches[1].ring[0] = patches[1].ring[3];
- patches[1].ring[3] = patches[1].ring[2];
- patches[1].ring[2] = patches1ring1;
-
- CatmullClark1Ring patches2ring2 = patches[2].ring[2];
- patches[2].ring[2] = patches[2].ring[0];
- patches[2].ring[0] = patches2ring2;
- CatmullClark1Ring patches2ring3 = patches[2].ring[3];
- patches[2].ring[3] = patches[2].ring[1];
- patches[2].ring[1] = patches2ring3;
-
- CatmullClark1Ring patches3ring3 = patches[3].ring[3];
- patches[3].ring[3] = patches[3].ring[0];
- patches[3].ring[0] = patches[3].ring[1];
- patches[3].ring[1] = patches[3].ring[2];
- patches[3].ring[2] = patches3ring3;
- }
-
- __forceinline void getLimitBorder(BezierCurve curves[GeneralCatmullClarkPatchT::SIZE]) const
- {
- Vertex P0 = ring[0].getLimitVertex();
- for (unsigned i=0; i<N; i++)
- {
- const unsigned i0 = i, i1 = i+1==N ? 0 : i+1;
- const Vertex P1 = madd(1.0f/3.0f,ring[i0].getLimitTangent(),P0);
- const Vertex P3 = ring[i1].getLimitVertex();
- const Vertex P2 = madd(1.0f/3.0f,ring[i1].getSecondLimitTangent(),P3);
- new (&curves[i]) BezierCurve(P0,P1,P2,P3);
- P0 = P3;
- }
- }
-
- __forceinline void getLimitBorder(BezierCurve curves[2], const unsigned subPatch) const
- {
- const unsigned i0 = subPatch;
- const Vertex t0_p = ring[i0].getLimitTangent();
- const Vertex t0_m = ring[i0].getSecondLimitTangent();
-
- const unsigned i1 = subPatch+1 == N ? 0 : subPatch+1;
- const Vertex t1_p = ring[i1].getLimitTangent();
- const Vertex t1_m = ring[i1].getSecondLimitTangent();
-
- const unsigned i2 = subPatch == 0 ? N-1 : subPatch-1;
- const Vertex t2_p = ring[i2].getLimitTangent();
- const Vertex t2_m = ring[i2].getSecondLimitTangent();
-
- const Vertex b00 = ring[i0].getLimitVertex();
- const Vertex b03 = ring[i1].getLimitVertex();
- const Vertex b33 = ring[i2].getLimitVertex();
-
- const Vertex b01 = madd(1.0/3.0f,t0_p,b00);
- const Vertex b11 = madd(1.0/3.0f,t0_m,b00);
-
- //const Vertex b13 = madd(1.0/3.0f,t1_p,b03);
- const Vertex b02 = madd(1.0/3.0f,t1_m,b03);
-
- const Vertex b22 = madd(1.0/3.0f,t2_p,b33);
- const Vertex b23 = madd(1.0/3.0f,t2_m,b33);
-
- new (&curves[0]) BezierCurve(b00,b01,b02,b03);
- new (&curves[1]) BezierCurve(b33,b22,b11,b00);
- }
-
- friend __forceinline embree_ostream operator<<(embree_ostream o, const GeneralCatmullClarkPatchT &p)
- {
- o << "GeneralCatmullClarkPatch { " << embree_endl;
- for (unsigned i=0; i<p.N; i++)
- o << "ring" << i << ": " << p.ring[i] << embree_endl;
- o << "}" << embree_endl;
- return o;
- }
- };
-
- typedef GeneralCatmullClarkPatchT<Vec3fa,Vec3fa_t> GeneralCatmullClarkPatch3fa;
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_ring.h b/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_ring.h
deleted file mode 100644
index 73b41fd4ff..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/catmullclark_ring.h
+++ /dev/null
@@ -1,826 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/geometry.h"
-#include "../common/buffer.h"
-#include "half_edge.h"
-#include "catmullclark_coefficients.h"
-
-namespace embree
-{
- struct __aligned(64) FinalQuad {
- Vec3fa vtx[4];
- };
-
- template<typename Vertex, typename Vertex_t = Vertex>
- struct __aligned(64) CatmullClark1RingT
- {
- ALIGNED_STRUCT_(64);
-
- int border_index; //!< edge index where border starts
- unsigned int face_valence; //!< number of adjacent quad faces
- unsigned int edge_valence; //!< number of adjacent edges (2*face_valence)
- float vertex_crease_weight; //!< weight of vertex crease (0 if no vertex crease)
- DynamicStackArray<float,16,MAX_RING_FACE_VALENCE> crease_weight; //!< edge crease weights for each adjacent edge
- float vertex_level; //!< maximum level of all adjacent edges
- float edge_level; //!< level of first edge
- unsigned int eval_start_index; //!< topology dependent index to start evaluation
- unsigned int eval_unique_identifier; //!< topology dependent unique identifier for this ring
- Vertex vtx; //!< center vertex
- DynamicStackArray<Vertex,32,MAX_RING_EDGE_VALENCE> ring; //!< ring of neighboring vertices
-
- public:
- CatmullClark1RingT ()
- : eval_start_index(0), eval_unique_identifier(0) {} // FIXME: default constructor should be empty
-
- /*! calculates number of bytes required to serialize this structure */
- __forceinline size_t bytes() const
- {
- size_t ofs = 0;
- ofs += sizeof(border_index);
- ofs += sizeof(face_valence);
- assert(2*face_valence == edge_valence);
- ofs += sizeof(vertex_crease_weight);
- ofs += face_valence*sizeof(float);
- ofs += sizeof(vertex_level);
- ofs += sizeof(edge_level);
- ofs += sizeof(eval_start_index);
- ofs += sizeof(eval_unique_identifier);
- ofs += sizeof(vtx);
- ofs += edge_valence*sizeof(Vertex);
- return ofs;
- }
-
- template<typename Ty>
- static __forceinline void store(char* ptr, size_t& ofs, const Ty& v) {
- *(Ty*)&ptr[ofs] = v; ofs += sizeof(Ty);
- }
-
- template<typename Ty>
- static __forceinline void load(char* ptr, size_t& ofs, Ty& v) {
- v = *(Ty*)&ptr[ofs]; ofs += sizeof(Ty);
- }
-
- /*! serializes the ring to some memory location */
- __forceinline void serialize(char* ptr, size_t& ofs) const
- {
- store(ptr,ofs,border_index);
- store(ptr,ofs,face_valence);
- store(ptr,ofs,vertex_crease_weight);
- for (size_t i=0; i<face_valence; i++)
- store(ptr,ofs,crease_weight[i]);
- store(ptr,ofs,vertex_level);
- store(ptr,ofs,edge_level);
- store(ptr,ofs,eval_start_index);
- store(ptr,ofs,eval_unique_identifier);
- Vertex_t::storeu(&ptr[ofs],vtx); ofs += sizeof(Vertex);
- for (size_t i=0; i<edge_valence; i++) {
- Vertex_t::storeu(&ptr[ofs],ring[i]); ofs += sizeof(Vertex);
- }
- }
-
- /*! deserializes the ring from some memory location */
- __forceinline void deserialize(char* ptr, size_t& ofs)
- {
- load(ptr,ofs,border_index);
- load(ptr,ofs,face_valence);
- edge_valence = 2*face_valence;
- load(ptr,ofs,vertex_crease_weight);
- for (size_t i=0; i<face_valence; i++)
- load(ptr,ofs,crease_weight[i]);
- load(ptr,ofs,vertex_level);
- load(ptr,ofs,edge_level);
- load(ptr,ofs,eval_start_index);
- load(ptr,ofs,eval_unique_identifier);
- vtx = Vertex_t::loadu(&ptr[ofs]); ofs += sizeof(Vertex);
- for (size_t i=0; i<edge_valence; i++) {
- ring[i] = Vertex_t::loadu(&ptr[ofs]); ofs += sizeof(Vertex);
- }
- }
-
- __forceinline bool hasBorder() const {
- return border_index != -1;
- }
-
- __forceinline const Vertex& front(size_t i) const {
- assert(edge_valence>i);
- return ring[i];
- }
-
- __forceinline const Vertex& back(size_t i) const {
- assert(edge_valence>=i);
- return ring[edge_valence-i];
- }
-
- __forceinline bool has_last_face() const {
- return (size_t)border_index != (size_t)edge_valence-2;
- }
-
- __forceinline bool has_opposite_front(size_t i) const {
- return (size_t)border_index != 2*i;
- }
-
- __forceinline bool has_opposite_back(size_t i) const {
- return (size_t)border_index != ((size_t)edge_valence-2-2*i);
- }
-
- __forceinline BBox3fa bounds() const
- {
- BBox3fa bounds ( vtx );
- for (size_t i = 0; i<edge_valence ; i++)
- bounds.extend( ring[i] );
- return bounds;
- }
-
- /*! initializes the ring from the half edge structure */
- __forceinline void init(const HalfEdge* const h, const char* vertices, size_t stride)
- {
- border_index = -1;
- vtx = Vertex_t::loadu(vertices+h->getStartVertexIndex()*stride);
- vertex_crease_weight = h->vertex_crease_weight;
-
- HalfEdge* p = (HalfEdge*) h;
-
- unsigned i=0;
- unsigned min_vertex_index = (unsigned)-1;
- unsigned min_vertex_index_face = (unsigned)-1;
- edge_level = p->edge_level;
- vertex_level = 0.0f;
-
- do
- {
- vertex_level = max(vertex_level,p->edge_level);
- crease_weight[i/2] = p->edge_crease_weight;
- assert(p->hasOpposite() || p->edge_crease_weight == float(inf));
-
- /* store first two vertices of face */
- p = p->next();
- const unsigned index0 = p->getStartVertexIndex();
- ring[i++] = Vertex_t::loadu(vertices+index0*stride);
- if (index0 < min_vertex_index) { min_vertex_index = index0; min_vertex_index_face = i>>1; }
- p = p->next();
-
- const unsigned index1 = p->getStartVertexIndex();
- ring[i++] = Vertex_t::loadu(vertices+index1*stride);
- p = p->next();
-
- /* continue with next face */
- if (likely(p->hasOpposite()))
- p = p->opposite();
-
- /* if there is no opposite go the long way to the other side of the border */
- else
- {
- /* find minimum start vertex */
- const unsigned index0 = p->getStartVertexIndex();
- if (index0 < min_vertex_index) { min_vertex_index = index0; min_vertex_index_face = i>>1; }
-
- /*! mark first border edge and store dummy vertex for face between the two border edges */
- border_index = i;
- crease_weight[i/2] = inf;
- ring[i++] = Vertex_t::loadu(vertices+index0*stride);
- ring[i++] = vtx; // dummy vertex
-
- /*! goto other side of border */
- p = (HalfEdge*) h;
- while (p->hasOpposite())
- p = p->opposite()->next();
- }
-
- } while (p != h);
-
- edge_valence = i;
- face_valence = i >> 1;
- eval_unique_identifier = min_vertex_index;
- eval_start_index = min_vertex_index_face;
-
- assert( hasValidPositions() );
- }
-
- __forceinline void subdivide(CatmullClark1RingT& dest) const
- {
- dest.edge_level = 0.5f*edge_level;
- dest.vertex_level = 0.5f*vertex_level;
- dest.face_valence = face_valence;
- dest.edge_valence = edge_valence;
- dest.border_index = border_index;
- dest.vertex_crease_weight = max(0.0f,vertex_crease_weight-1.0f);
- dest.eval_start_index = eval_start_index;
- dest.eval_unique_identifier = eval_unique_identifier;
-
- /* calculate face points */
- Vertex_t S = Vertex_t(0.0f);
- for (size_t i=0; i<face_valence; i++)
- {
- size_t face_index = i + eval_start_index; if (face_index >= face_valence) face_index -= face_valence; assert(face_index < face_valence);
- size_t index0 = 2*face_index+0; if (index0 >= edge_valence) index0 -= edge_valence; assert(index0 < edge_valence);
- size_t index1 = 2*face_index+1; if (index1 >= edge_valence) index1 -= edge_valence; assert(index1 < edge_valence);
- size_t index2 = 2*face_index+2; if (index2 >= edge_valence) index2 -= edge_valence; assert(index2 < edge_valence);
- S += dest.ring[index1] = ((vtx + ring[index1]) + (ring[index0] + ring[index2])) * 0.25f;
- }
-
- /* calculate new edge points */
- size_t num_creases = 0;
- array_t<size_t,MAX_RING_FACE_VALENCE> crease_id;
-
- for (size_t i=0; i<face_valence; i++)
- {
- size_t face_index = i + eval_start_index;
- if (face_index >= face_valence) face_index -= face_valence;
- const float edge_crease = crease_weight[face_index];
- dest.crease_weight[face_index] = max(edge_crease-1.0f,0.0f);
-
- size_t index = 2*face_index;
- size_t prev_index = face_index == 0 ? edge_valence-1 : 2*face_index-1;
- size_t next_index = 2*face_index+1;
-
- const Vertex_t v = vtx + ring[index];
- const Vertex_t f = dest.ring[prev_index] + dest.ring[next_index];
- S += ring[index];
-
- /* fast path for regular edge points */
- if (likely(edge_crease <= 0.0f)) {
- dest.ring[index] = (v+f) * 0.25f;
- }
-
- /* slower path for hard edge rule */
- else {
- crease_id[num_creases++] = face_index;
- dest.ring[index] = v*0.5f;
-
- /* even slower path for blended edge rule */
- if (unlikely(edge_crease < 1.0f)) {
- dest.ring[index] = lerp((v+f)*0.25f,v*0.5f,edge_crease);
- }
- }
- }
-
- /* compute new vertex using smooth rule */
- const float inv_face_valence = 1.0f / (float)face_valence;
- const Vertex_t v_smooth = (Vertex_t) madd(inv_face_valence,S,(float(face_valence)-2.0f)*vtx)*inv_face_valence;
- dest.vtx = v_smooth;
-
- /* compute new vertex using vertex_crease_weight rule */
- if (unlikely(vertex_crease_weight > 0.0f))
- {
- if (vertex_crease_weight >= 1.0f) {
- dest.vtx = vtx;
- } else {
- dest.vtx = lerp(v_smooth,vtx,vertex_crease_weight);
- }
- return;
- }
-
- /* no edge crease rule and dart rule */
- if (likely(num_creases <= 1))
- return;
-
- /* compute new vertex using crease rule */
- if (likely(num_creases == 2))
- {
- /* update vertex using crease rule */
- const size_t crease0 = crease_id[0], crease1 = crease_id[1];
- const Vertex_t v_sharp = (Vertex_t)(ring[2*crease0] + 6.0f*vtx + ring[2*crease1]) * (1.0f / 8.0f);
- dest.vtx = v_sharp;
-
- /* update crease_weights using chaikin rule */
- const float crease_weight0 = crease_weight[crease0], crease_weight1 = crease_weight[crease1];
- dest.crease_weight[crease0] = max(0.25f*(3.0f*crease_weight0 + crease_weight1)-1.0f,0.0f);
- dest.crease_weight[crease1] = max(0.25f*(3.0f*crease_weight1 + crease_weight0)-1.0f,0.0f);
-
- /* interpolate between sharp and smooth rule */
- const float v_blend = 0.5f*(crease_weight0+crease_weight1);
- if (unlikely(v_blend < 1.0f)) {
- dest.vtx = lerp(v_smooth,v_sharp,v_blend);
- }
- }
-
- /* compute new vertex using corner rule */
- else {
- dest.vtx = vtx;
- }
- }
-
- __forceinline bool isRegular1() const
- {
- if (border_index == -1) {
- if (face_valence == 4) return true;
- } else {
- if (face_valence < 4) return true;
- }
- return false;
- }
-
- __forceinline size_t numEdgeCreases() const
- {
- ssize_t numCreases = 0;
- for (size_t i=0; i<face_valence; i++) {
- numCreases += crease_weight[i] > 0.0f;
- }
- return numCreases;
- }
-
- enum Type {
- TYPE_NONE = 0, //!< invalid type
- TYPE_REGULAR = 1, //!< regular patch when ignoring creases
- TYPE_REGULAR_CREASES = 2, //!< regular patch when considering creases
- TYPE_GREGORY = 4, //!< gregory patch when ignoring creases
- TYPE_GREGORY_CREASES = 8, //!< gregory patch when considering creases
- TYPE_CREASES = 16 //!< patch has crease features
- };
-
- __forceinline Type type() const
- {
- /* check if there is an edge crease anywhere */
- const size_t numCreases = numEdgeCreases();
- const bool noInnerCreases = hasBorder() ? numCreases == 2 : numCreases == 0;
-
- Type crease_mask = (Type) (TYPE_REGULAR | TYPE_GREGORY);
- if (noInnerCreases ) crease_mask = (Type) (crease_mask | TYPE_REGULAR_CREASES | TYPE_GREGORY_CREASES);
- if (numCreases != 0) crease_mask = (Type) (crease_mask | TYPE_CREASES);
-
- /* calculate if this vertex is regular */
- bool hasBorder = border_index != -1;
- if (face_valence == 2 && hasBorder) {
- if (vertex_crease_weight == 0.0f ) return (Type) (crease_mask & (TYPE_REGULAR | TYPE_REGULAR_CREASES | TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
- else if (vertex_crease_weight == float(inf)) return (Type) (crease_mask & (TYPE_REGULAR | TYPE_REGULAR_CREASES | TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
- else return TYPE_CREASES;
- }
- else if (vertex_crease_weight != 0.0f) return TYPE_CREASES;
- else if (face_valence == 3 && hasBorder) return (Type) (crease_mask & (TYPE_REGULAR | TYPE_REGULAR_CREASES | TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
- else if (face_valence == 4 && !hasBorder) return (Type) (crease_mask & (TYPE_REGULAR | TYPE_REGULAR_CREASES | TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
- else return (Type) (crease_mask & (TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
- }
-
- __forceinline bool isFinalResolution(float res) const {
- return vertex_level <= res;
- }
-
- /* computes the limit vertex */
- __forceinline Vertex getLimitVertex() const
- {
- /* return hard corner */
- if (unlikely(std::isinf(vertex_crease_weight)))
- return vtx;
-
- /* border vertex rule */
- if (unlikely(border_index != -1))
- {
- const unsigned int second_border_index = border_index+2 >= int(edge_valence) ? 0 : border_index+2;
- return (4.0f * vtx + (ring[border_index] + ring[second_border_index])) * 1.0f/6.0f;
- }
-
- Vertex_t F( 0.0f );
- Vertex_t E( 0.0f );
-
- assert(eval_start_index < face_valence);
-
- for (size_t i=0; i<face_valence; i++) {
- size_t index = i+eval_start_index;
- if (index >= face_valence) index -= face_valence;
- F += ring[2*index+1];
- E += ring[2*index];
- }
-
- const float n = (float)face_valence;
- return (Vertex_t)(n*n*vtx+4.0f*E+F) / ((n+5.0f)*n);
- }
-
- /* gets limit tangent in the direction of egde vtx -> ring[0] */
- __forceinline Vertex getLimitTangent() const
- {
- if (unlikely(std::isinf(vertex_crease_weight)))
- return ring[0] - vtx;
-
- /* border vertex rule */
- if (unlikely(border_index != -1))
- {
- if (border_index != (int)edge_valence-2 ) {
- return ring[0] - vtx;
- }
- else
- {
- const unsigned int second_border_index = border_index+2 >= int(edge_valence) ? 0 : border_index+2;
- return (ring[second_border_index] - ring[border_index]) * 0.5f;
- }
- }
-
- Vertex_t alpha( 0.0f );
- Vertex_t beta ( 0.0f );
-
- const size_t n = face_valence;
-
- assert(eval_start_index < face_valence);
-
- Vertex_t q( 0.0f );
- for (size_t i=0; i<face_valence; i++)
- {
- size_t index = i+eval_start_index;
- if (index >= face_valence) index -= face_valence;
- const float a = CatmullClarkPrecomputedCoefficients::table.limittangent_a(index,n);
- const float b = CatmullClarkPrecomputedCoefficients::table.limittangent_b(index,n);
- alpha += a * ring[2*index];
- beta += b * ring[2*index+1];
- }
-
- const float sigma = CatmullClarkPrecomputedCoefficients::table.limittangent_c(n);
- return sigma * (alpha + beta);
- }
-
- /* gets limit tangent in the direction of egde vtx -> ring[edge_valence-2] */
- __forceinline Vertex getSecondLimitTangent() const
- {
- if (unlikely(std::isinf(vertex_crease_weight)))
- return ring[2] - vtx;
-
- /* border vertex rule */
- if (unlikely(border_index != -1))
- {
- if (border_index != 2) {
- return ring[2] - vtx;
- }
- else {
- const unsigned int second_border_index = border_index+2 >= int(edge_valence) ? 0 : border_index+2;
- return (ring[border_index] - ring[second_border_index]) * 0.5f;
- }
- }
-
- Vertex_t alpha( 0.0f );
- Vertex_t beta ( 0.0f );
-
- const size_t n = face_valence;
-
- assert(eval_start_index < face_valence);
-
- for (size_t i=0; i<face_valence; i++)
- {
- size_t index = i+eval_start_index;
- if (index >= face_valence) index -= face_valence;
-
- size_t prev_index = index == 0 ? face_valence-1 : index-1; // need to be bit-wise exact in cosf eval
- const float a = CatmullClarkPrecomputedCoefficients::table.limittangent_a(prev_index,n);
- const float b = CatmullClarkPrecomputedCoefficients::table.limittangent_b(prev_index,n);
- alpha += a * ring[2*index];
- beta += b * ring[2*index+1];
- }
-
- const float sigma = CatmullClarkPrecomputedCoefficients::table.limittangent_c(n);
- return sigma* (alpha + beta);
- }
-
- /* gets surface normal */
- const Vertex getNormal() const {
- return cross(getLimitTangent(),getSecondLimitTangent());
- }
-
- /* returns center of the n-th quad in the 1-ring */
- __forceinline Vertex getQuadCenter(const size_t index) const
- {
- const Vertex_t &p0 = vtx;
- const Vertex_t &p1 = ring[2*index+0];
- const Vertex_t &p2 = ring[2*index+1];
- const Vertex_t &p3 = index == face_valence-1 ? ring[0] : ring[2*index+2];
- const Vertex p = (p0+p1+p2+p3) * 0.25f;
- return p;
- }
-
- /* returns center of the n-th edge in the 1-ring */
- __forceinline Vertex getEdgeCenter(const size_t index) const {
- return (vtx + ring[index*2]) * 0.5f;
- }
-
- bool hasValidPositions() const
- {
- for (size_t i=0; i<edge_valence; i++) {
- if (!isvalid(ring[i]))
- return false;
- }
- return true;
- }
-
- friend __forceinline embree_ostream operator<<(embree_ostream o, const CatmullClark1RingT &c)
- {
- o << "vtx " << c.vtx << " size = " << c.edge_valence << ", " <<
- "hard_edge = " << c.border_index << ", face_valence " << c.face_valence <<
- ", edge_level = " << c.edge_level << ", vertex_level = " << c.vertex_level << ", eval_start_index: " << c.eval_start_index << ", ring: " << embree_endl;
-
- for (unsigned int i=0; i<min(c.edge_valence,(unsigned int)MAX_RING_FACE_VALENCE); i++) {
- o << i << " -> " << c.ring[i];
- if (i % 2 == 0) o << " crease = " << c.crease_weight[i/2];
- o << embree_endl;
- }
- return o;
- }
- };
-
- typedef CatmullClark1RingT<Vec3fa,Vec3fa_t> CatmullClark1Ring3fa;
-
- template<typename Vertex, typename Vertex_t = Vertex>
- struct __aligned(64) GeneralCatmullClark1RingT
- {
- ALIGNED_STRUCT_(64);
-
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
-
- struct Face
- {
- __forceinline Face() {}
- __forceinline Face (int size, float crease_weight)
- : size(size), crease_weight(crease_weight) {}
-
- // FIXME: add member that returns total number of vertices
-
- int size; // number of vertices-2 of nth face in ring
- float crease_weight;
- };
-
- Vertex vtx;
- DynamicStackArray<Vertex,32,MAX_RING_EDGE_VALENCE> ring;
- DynamicStackArray<Face,16,MAX_RING_FACE_VALENCE> faces;
- unsigned int face_valence;
- unsigned int edge_valence;
- int border_face;
- float vertex_crease_weight;
- float vertex_level; //!< maximum level of adjacent edges
- float edge_level; // level of first edge
- bool only_quads; // true if all faces are quads
- unsigned int eval_start_face_index;
- unsigned int eval_start_vertex_index;
- unsigned int eval_unique_identifier;
-
- public:
- GeneralCatmullClark1RingT()
- : eval_start_face_index(0), eval_start_vertex_index(0), eval_unique_identifier(0) {}
-
- __forceinline bool isRegular() const
- {
- if (border_face == -1 && face_valence == 4) return true;
- return false;
- }
-
- __forceinline bool has_last_face() const {
- return border_face != (int)face_valence-1;
- }
-
- __forceinline bool has_second_face() const {
- return (border_face == -1) || (border_face >= 2);
- }
-
- bool hasValidPositions() const
- {
- for (size_t i=0; i<edge_valence; i++) {
- if (!isvalid(ring[i]))
- return false;
- }
- return true;
- }
-
- __forceinline void init(const HalfEdge* const h, const char* vertices, size_t stride)
- {
- only_quads = true;
- border_face = -1;
- vtx = Vertex_t::loadu(vertices+h->getStartVertexIndex()*stride);
- vertex_crease_weight = h->vertex_crease_weight;
- HalfEdge* p = (HalfEdge*) h;
-
- unsigned int e=0, f=0;
- unsigned min_vertex_index = (unsigned)-1;
- unsigned min_vertex_index_face = (unsigned)-1;
- unsigned min_vertex_index_vertex = (unsigned)-1;
- edge_level = p->edge_level;
- vertex_level = 0.0f;
- do
- {
- HalfEdge* p_prev = p->prev();
- HalfEdge* p_next = p->next();
- const float crease_weight = p->edge_crease_weight;
- assert(p->hasOpposite() || p->edge_crease_weight == float(inf));
- vertex_level = max(vertex_level,p->edge_level);
-
- /* find minimum start vertex */
- unsigned vertex_index = p_next->getStartVertexIndex();
- if (vertex_index < min_vertex_index) { min_vertex_index = vertex_index; min_vertex_index_face = f; min_vertex_index_vertex = e; }
-
- /* store first N-2 vertices of face */
- unsigned int vn = 0;
- for (p = p_next; p!=p_prev; p=p->next()) {
- ring[e++] = Vertex_t::loadu(vertices+p->getStartVertexIndex()*stride);
- vn++;
- }
- faces[f++] = Face(vn,crease_weight);
- only_quads &= (vn == 2);
-
- /* continue with next face */
- if (likely(p->hasOpposite()))
- p = p->opposite();
-
- /* if there is no opposite go the long way to the other side of the border */
- else
- {
- /* find minimum start vertex */
- unsigned vertex_index = p->getStartVertexIndex();
- if (vertex_index < min_vertex_index) { min_vertex_index = vertex_index; min_vertex_index_face = f; min_vertex_index_vertex = e; }
-
- /*! mark first border edge and store dummy vertex for face between the two border edges */
- border_face = f;
- faces[f++] = Face(2,inf);
- ring[e++] = Vertex_t::loadu(vertices+p->getStartVertexIndex()*stride);
- ring[e++] = vtx; // dummy vertex
-
- /*! goto other side of border */
- p = (HalfEdge*) h;
- while (p->hasOpposite())
- p = p->opposite()->next();
- }
-
- } while (p != h);
-
- edge_valence = e;
- face_valence = f;
- eval_unique_identifier = min_vertex_index;
- eval_start_face_index = min_vertex_index_face;
- eval_start_vertex_index = min_vertex_index_vertex;
-
- assert( hasValidPositions() );
- }
-
- __forceinline void subdivide(CatmullClark1Ring& dest) const
- {
- dest.edge_level = 0.5f*edge_level;
- dest.vertex_level = 0.5f*vertex_level;
- dest.face_valence = face_valence;
- dest.edge_valence = 2*face_valence;
- dest.border_index = border_face == -1 ? -1 : 2*border_face; // FIXME:
- dest.vertex_crease_weight = max(0.0f,vertex_crease_weight-1.0f);
- dest.eval_start_index = eval_start_face_index;
- dest.eval_unique_identifier = eval_unique_identifier;
- assert(dest.face_valence <= MAX_RING_FACE_VALENCE);
-
- /* calculate face points */
- Vertex_t S = Vertex_t(0.0f);
- for (size_t face=0, v=eval_start_vertex_index; face<face_valence; face++) {
- size_t f = (face + eval_start_face_index)%face_valence;
-
- Vertex_t F = vtx;
- for (size_t k=v; k<=v+faces[f].size; k++) F += ring[k%edge_valence]; // FIXME: optimize
- S += dest.ring[2*f+1] = F/float(faces[f].size+2);
- v+=faces[f].size;
- v%=edge_valence;
- }
-
- /* calculate new edge points */
- size_t num_creases = 0;
- array_t<size_t,MAX_RING_FACE_VALENCE> crease_id;
- Vertex_t C = Vertex_t(0.0f);
- for (size_t face=0, j=eval_start_vertex_index; face<face_valence; face++)
- {
- size_t i = (face + eval_start_face_index)%face_valence;
-
- const Vertex_t v = vtx + ring[j];
- Vertex_t f = dest.ring[2*i+1];
- if (i == 0) f += dest.ring[dest.edge_valence-1];
- else f += dest.ring[2*i-1];
- S += ring[j];
- dest.crease_weight[i] = max(faces[i].crease_weight-1.0f,0.0f);
-
- /* fast path for regular edge points */
- if (likely(faces[i].crease_weight <= 0.0f)) {
- dest.ring[2*i] = (v+f) * 0.25f;
- }
-
- /* slower path for hard edge rule */
- else {
- C += ring[j]; crease_id[num_creases++] = i;
- dest.ring[2*i] = v*0.5f;
-
- /* even slower path for blended edge rule */
- if (unlikely(faces[i].crease_weight < 1.0f)) {
- dest.ring[2*i] = lerp((v+f)*0.25f,v*0.5f,faces[i].crease_weight);
- }
- }
- j+=faces[i].size;
- j%=edge_valence;
- }
-
- /* compute new vertex using smooth rule */
- const float inv_face_valence = 1.0f / (float)face_valence;
- const Vertex_t v_smooth = (Vertex_t) madd(inv_face_valence,S,(float(face_valence)-2.0f)*vtx)*inv_face_valence;
- dest.vtx = v_smooth;
-
- /* compute new vertex using vertex_crease_weight rule */
- if (unlikely(vertex_crease_weight > 0.0f))
- {
- if (vertex_crease_weight >= 1.0f) {
- dest.vtx = vtx;
- } else {
- dest.vtx = lerp(vtx,v_smooth,vertex_crease_weight);
- }
- return;
- }
-
- if (likely(num_creases <= 1))
- return;
-
- /* compute new vertex using crease rule */
- if (likely(num_creases == 2)) {
- const Vertex_t v_sharp = (Vertex_t)(C + 6.0f * vtx) * (1.0f / 8.0f);
- const float crease_weight0 = faces[crease_id[0]].crease_weight;
- const float crease_weight1 = faces[crease_id[1]].crease_weight;
- dest.vtx = v_sharp;
- dest.crease_weight[crease_id[0]] = max(0.25f*(3.0f*crease_weight0 + crease_weight1)-1.0f,0.0f);
- dest.crease_weight[crease_id[1]] = max(0.25f*(3.0f*crease_weight1 + crease_weight0)-1.0f,0.0f);
- const float v_blend = 0.5f*(crease_weight0+crease_weight1);
- if (unlikely(v_blend < 1.0f)) {
- dest.vtx = lerp(v_sharp,v_smooth,v_blend);
- }
- }
-
- /* compute new vertex using corner rule */
- else {
- dest.vtx = vtx;
- }
- }
-
- void convert(CatmullClark1Ring& dst) const
- {
- dst.edge_level = edge_level;
- dst.vertex_level = vertex_level;
- dst.vtx = vtx;
- dst.face_valence = face_valence;
- dst.edge_valence = 2*face_valence;
- dst.border_index = border_face == -1 ? -1 : 2*border_face;
- for (size_t i=0; i<face_valence; i++)
- dst.crease_weight[i] = faces[i].crease_weight;
- dst.vertex_crease_weight = vertex_crease_weight;
- for (size_t i=0; i<edge_valence; i++) dst.ring[i] = ring[i];
-
- dst.eval_start_index = eval_start_face_index;
- dst.eval_unique_identifier = eval_unique_identifier;
-
- assert( dst.hasValidPositions() );
- }
-
-
- /* gets limit tangent in the direction of egde vtx -> ring[0] */
- __forceinline Vertex getLimitTangent() const
- {
- CatmullClark1Ring cc_vtx;
-
- /* fast path for quad only rings */
- if (only_quads)
- {
- convert(cc_vtx);
- return cc_vtx.getLimitTangent();
- }
-
- subdivide(cc_vtx);
- return 2.0f * cc_vtx.getLimitTangent();
- }
-
- /* gets limit tangent in the direction of egde vtx -> ring[edge_valence-2] */
- __forceinline Vertex getSecondLimitTangent() const
- {
- CatmullClark1Ring cc_vtx;
-
- /* fast path for quad only rings */
- if (only_quads)
- {
- convert(cc_vtx);
- return cc_vtx.getSecondLimitTangent();
- }
-
- subdivide(cc_vtx);
- return 2.0f * cc_vtx.getSecondLimitTangent();
- }
-
-
- /* gets limit vertex */
- __forceinline Vertex getLimitVertex() const
- {
- CatmullClark1Ring cc_vtx;
-
- /* fast path for quad only rings */
- if (only_quads)
- convert(cc_vtx);
- else
- subdivide(cc_vtx);
- return cc_vtx.getLimitVertex();
- }
-
- friend __forceinline embree_ostream operator<<(embree_ostream o, const GeneralCatmullClark1RingT &c)
- {
- o << "vtx " << c.vtx << " size = " << c.edge_valence << ", border_face = " << c.border_face << ", " << " face_valence = " << c.face_valence <<
- ", edge_level = " << c.edge_level << ", vertex_level = " << c.vertex_level << ", ring: " << embree_endl;
- for (size_t v=0, f=0; f<c.face_valence; v+=c.faces[f++].size) {
- for (size_t i=v; i<v+c.faces[f].size; i++) {
- o << i << " -> " << c.ring[i];
- if (i == v) o << " crease = " << c.faces[f].crease_weight;
- o << embree_endl;
- }
- }
- return o;
- }
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/catmullrom_curve.h b/thirdparty/embree-aarch64/kernels/subdiv/catmullrom_curve.h
deleted file mode 100644
index b244af481c..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/catmullrom_curve.h
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-#include "../common/scene_curves.h"
-
-/*
-
- Implements Catmul Rom curves with control points p0, p1, p2, p3. At
- t=0 the curve goes through p1, with tangent (p2-p0)/3, and for t=1
- the curve goes through p2 with tangent (p3-p2)/2.
-
- */
-
-namespace embree
-{
- class CatmullRomBasis
- {
- public:
-
- template<typename T>
- static __forceinline Vec4<T> eval(const T& u)
- {
- const T t = u;
- const T s = T(1.0f) - u;
- const T n0 = - t * s * s;
- const T n1 = 2.0f + t * t * (3.0f * t - 5.0f);
- const T n2 = 2.0f + s * s * (3.0f * s - 5.0f);
- const T n3 = - s * t * t;
- return T(0.5f) * Vec4<T>(n0, n1, n2, n3);
- }
-
- template<typename T>
- static __forceinline Vec4<T> derivative(const T& u)
- {
- const T t = u;
- const T s = 1.0f - u;
- const T n0 = - s * s + 2.0f * s * t;
- const T n1 = 2.0f * t * (3.0f * t - 5.0f) + 3.0f * t * t;
- const T n2 = 2.0f * s * (3.0f * t + 2.0f) - 3.0f * s * s;
- const T n3 = -2.0f * s * t + t * t;
- return T(0.5f) * Vec4<T>(n0, n1, n2, n3);
- }
-
- template<typename T>
- static __forceinline Vec4<T> derivative2(const T& u)
- {
- const T t = u;
- const T n0 = -3.0f * t + 2.0f;
- const T n1 = 9.0f * t - 5.0f;
- const T n2 = -9.0f * t + 4.0f;
- const T n3 = 3.0f * t - 1.0f;
- return Vec4<T>(n0, n1, n2, n3);
- }
- };
-
- struct PrecomputedCatmullRomBasis
- {
- enum { N = 16 };
- public:
- PrecomputedCatmullRomBasis() {}
- PrecomputedCatmullRomBasis(int shift);
-
- /* basis for bspline evaluation */
- public:
- float c0[N+1][N+1];
- float c1[N+1][N+1];
- float c2[N+1][N+1];
- float c3[N+1][N+1];
-
- /* basis for bspline derivative evaluation */
- public:
- float d0[N+1][N+1];
- float d1[N+1][N+1];
- float d2[N+1][N+1];
- float d3[N+1][N+1];
- };
- extern PrecomputedCatmullRomBasis catmullrom_basis0;
- extern PrecomputedCatmullRomBasis catmullrom_basis1;
-
- template<typename Vertex>
- struct CatmullRomCurveT
- {
- Vertex v0,v1,v2,v3;
-
- __forceinline CatmullRomCurveT() {}
-
- __forceinline CatmullRomCurveT(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3)
- : v0(v0), v1(v1), v2(v2), v3(v3) {}
-
- __forceinline Vertex begin() const {
- return madd(1.0f/6.0f,v0,madd(2.0f/3.0f,v1,1.0f/6.0f*v2));
- }
-
- __forceinline Vertex end() const {
- return madd(1.0f/6.0f,v1,madd(2.0f/3.0f,v2,1.0f/6.0f*v3));
- }
-
- __forceinline Vertex center() const {
- return 0.25f*(v0+v1+v2+v3);
- }
-
- __forceinline BBox<Vertex> bounds() const {
- return merge(BBox<Vertex>(v0),BBox<Vertex>(v1),BBox<Vertex>(v2),BBox<Vertex>(v3));
- }
-
- __forceinline friend CatmullRomCurveT operator -( const CatmullRomCurveT& a, const Vertex& b ) {
- return CatmullRomCurveT(a.v0-b,a.v1-b,a.v2-b,a.v3-b);
- }
-
- __forceinline CatmullRomCurveT<Vec3ff> xfm_pr(const LinearSpace3fa& space, const Vec3fa& p) const
- {
- const Vec3ff q0(xfmVector(space,v0-p), v0.w);
- const Vec3ff q1(xfmVector(space,v1-p), v1.w);
- const Vec3ff q2(xfmVector(space,v2-p), v2.w);
- const Vec3ff q3(xfmVector(space,v3-p), v3.w);
- return CatmullRomCurveT<Vec3ff>(q0,q1,q2,q3);
- }
-
- __forceinline Vertex eval(const float t) const
- {
- const Vec4<float> b = CatmullRomBasis::eval(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-
- __forceinline Vertex eval_du(const float t) const
- {
- const Vec4<float> b = CatmullRomBasis::derivative(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-
- __forceinline Vertex eval_dudu(const float t) const
- {
- const Vec4<float> b = CatmullRomBasis::derivative2(t);
- return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
- }
-
- __forceinline void eval(const float t, Vertex& p, Vertex& dp, Vertex& ddp) const
- {
- p = eval(t);
- dp = eval_du(t);
- ddp = eval_dudu(t);
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = CatmullRomBasis::eval(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval_du(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = CatmullRomBasis::derivative(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> veval_dudu(const vfloat<M>& t) const
- {
- const Vec4vf<M> b = CatmullRomBasis::derivative2(t);
- return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline void veval(const vfloat<M>& t, Vec4vf<M>& p, Vec4vf<M>& dp) const
- {
- p = veval(t);
- dp = veval_du(t);
- }
-
- template<int M>
- __forceinline Vec4vf<M> eval0(const int ofs, const int size) const
- {
- assert(size <= PrecomputedCatmullRomBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&catmullrom_basis0.c0[size][ofs]), Vec4vf<M>(v0),
- madd(vfloat<M>::loadu(&catmullrom_basis0.c1[size][ofs]), Vec4vf<M>(v1),
- madd(vfloat<M>::loadu(&catmullrom_basis0.c2[size][ofs]), Vec4vf<M>(v2),
- vfloat<M>::loadu(&catmullrom_basis0.c3[size][ofs]) * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> eval1(const int ofs, const int size) const
- {
- assert(size <= PrecomputedCatmullRomBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&catmullrom_basis1.c0[size][ofs]), Vec4vf<M>(v0),
- madd(vfloat<M>::loadu(&catmullrom_basis1.c1[size][ofs]), Vec4vf<M>(v1),
- madd(vfloat<M>::loadu(&catmullrom_basis1.c2[size][ofs]), Vec4vf<M>(v2),
- vfloat<M>::loadu(&catmullrom_basis1.c3[size][ofs]) * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> derivative0(const int ofs, const int size) const
- {
- assert(size <= PrecomputedCatmullRomBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&catmullrom_basis0.d0[size][ofs]), Vec4vf<M>(v0),
- madd(vfloat<M>::loadu(&catmullrom_basis0.d1[size][ofs]), Vec4vf<M>(v1),
- madd(vfloat<M>::loadu(&catmullrom_basis0.d2[size][ofs]), Vec4vf<M>(v2),
- vfloat<M>::loadu(&catmullrom_basis0.d3[size][ofs]) * Vec4vf<M>(v3))));
- }
-
- template<int M>
- __forceinline Vec4vf<M> derivative1(const int ofs, const int size) const
- {
- assert(size <= PrecomputedCatmullRomBasis::N);
- assert(ofs <= size);
- return madd(vfloat<M>::loadu(&catmullrom_basis1.d0[size][ofs]), Vec4vf<M>(v0),
- madd(vfloat<M>::loadu(&catmullrom_basis1.d1[size][ofs]), Vec4vf<M>(v1),
- madd(vfloat<M>::loadu(&catmullrom_basis1.d2[size][ofs]), Vec4vf<M>(v2),
- vfloat<M>::loadu(&catmullrom_basis1.d3[size][ofs]) * Vec4vf<M>(v3))));
- }
-
- /* calculates bounds of catmull-rom curve geometry */
- __forceinline BBox3fa accurateRoundBounds() const
- {
- const int N = 7;
- const float scale = 1.0f/(3.0f*(N-1));
- Vec4vfx pl(pos_inf), pu(neg_inf);
- for (int i=0; i<=N; i+=VSIZEX)
- {
- vintx vi = vintx(i)+vintx(step);
- vboolx valid = vi <= vintx(N);
- const Vec4vfx p = eval0<VSIZEX>(i,N);
- const Vec4vfx dp = derivative0<VSIZEX>(i,N);
- const Vec4vfx pm = p-Vec4vfx(scale)*select(vi!=vintx(0),dp,Vec4vfx(zero));
- const Vec4vfx pp = p+Vec4vfx(scale)*select(vi!=vintx(N),dp,Vec4vfx(zero));
- pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
- pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
- }
- const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
- const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
- const float r_min = reduce_min(pl.w);
- const float r_max = reduce_max(pu.w);
- const Vec3fa upper_r = Vec3fa(max(abs(r_min),abs(r_max)));
- return enlarge(BBox3fa(lower,upper),upper_r);
- }
-
- /* calculates bounds when tessellated into N line segments */
- __forceinline BBox3fa accurateFlatBounds(int N) const
- {
- if (likely(N == 4))
- {
- const Vec4vf4 pi = eval0<4>(0,4);
- const Vec3fa lower(reduce_min(pi.x),reduce_min(pi.y),reduce_min(pi.z));
- const Vec3fa upper(reduce_max(pi.x),reduce_max(pi.y),reduce_max(pi.z));
- const Vec3fa upper_r = Vec3fa(reduce_max(abs(pi.w)));
- const Vec3ff pe = end();
- return enlarge(BBox3fa(min(lower,pe),max(upper,pe)),max(upper_r,Vec3fa(abs(pe.w))));
- }
- else
- {
- Vec3vfx pl(pos_inf), pu(neg_inf); vfloatx ru(0.0f);
- for (int i=0; i<=N; i+=VSIZEX)
- {
- vboolx valid = vintx(i)+vintx(step) <= vintx(N);
- const Vec4vfx pi = eval0<VSIZEX>(i,N);
-
- pl.x = select(valid,min(pl.x,pi.x),pl.x); // FIXME: use masked min
- pl.y = select(valid,min(pl.y,pi.y),pl.y);
- pl.z = select(valid,min(pl.z,pi.z),pl.z);
-
- pu.x = select(valid,max(pu.x,pi.x),pu.x); // FIXME: use masked min
- pu.y = select(valid,max(pu.y,pi.y),pu.y);
- pu.z = select(valid,max(pu.z,pi.z),pu.z);
-
- ru = select(valid,max(ru,abs(pi.w)),ru);
- }
- const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
- const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
- const Vec3fa upper_r(reduce_max(ru));
- return enlarge(BBox3fa(lower,upper),upper_r);
- }
- }
-
- friend __forceinline embree_ostream operator<<(embree_ostream cout, const CatmullRomCurveT& curve) {
- return cout << "CatmullRomCurve { v0 = " << curve.v0 << ", v1 = " << curve.v1 << ", v2 = " << curve.v2 << ", v3 = " << curve.v3 << " }";
- }
- };
-
- __forceinline CatmullRomCurveT<Vec3ff> enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const CatmullRomCurveT<Vec3ff>& curve)
- {
- return CatmullRomCurveT<Vec3ff>(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v1),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v2),
- enlargeRadiusToMinWidth(context,geom,ray_org,curve.v3));
- }
-
- typedef CatmullRomCurveT<Vec3fa> CatmullRomCurve3fa;
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval.h b/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval.h
deleted file mode 100644
index 23f24c360c..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval.h
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "patch.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename Vertex, typename Vertex_t = Vertex>
- struct FeatureAdaptiveEval
- {
- public:
-
- typedef PatchT<Vertex,Vertex_t> Patch;
- typedef typename Patch::Ref Ref;
- typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
- typedef BSplinePatchT<Vertex,Vertex_t> BSplinePatch;
- typedef BezierPatchT<Vertex,Vertex_t> BezierPatch;
- typedef GregoryPatchT<Vertex,Vertex_t> GregoryPatch;
- typedef BilinearPatchT<Vertex,Vertex_t> BilinearPatch;
- typedef BezierCurveT<Vertex> BezierCurve;
-
- public:
-
- FeatureAdaptiveEval (const HalfEdge* edge, const char* vertices, size_t stride, const float u, const float v,
- Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv)
- : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv)
- {
- switch (edge->patch_type) {
- case HalfEdge::BILINEAR_PATCH: BilinearPatch(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;
- case HalfEdge::REGULAR_QUAD_PATCH: RegularPatchT(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;
-#if PATCH_USE_GREGORY == 2
- case HalfEdge::IRREGULAR_QUAD_PATCH: GregoryPatch(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;
-#endif
- default: {
- GeneralCatmullClarkPatch patch(edge,vertices,stride);
- eval(patch,Vec2f(u,v),0);
- break;
- }
- }
- }
-
- FeatureAdaptiveEval (CatmullClarkPatch& patch, const float u, const float v, float dscale, size_t depth,
- Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv)
- : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv)
- {
- eval(patch,Vec2f(u,v),dscale,depth);
- }
-
- void eval_general_quad(const GeneralCatmullClarkPatch& patch, array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE>& patches, const Vec2f& uv, size_t depth)
- {
- float u = uv.x, v = uv.y;
- if (v < 0.5f) {
- if (u < 0.5f) {
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[2]; patch.getLimitBorder(borders,0);
- BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
- eval(patches[0],Vec2f(2.0f*u,2.0f*v),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
-#else
- eval(patches[0],Vec2f(2.0f*u,2.0f*v),2.0f,depth+1);
-#endif
- if (dPdu && dPdv) {
- const Vertex dpdx = *dPdu, dpdy = *dPdv;
- *dPdu = dpdx; *dPdv = dpdy;
- }
- }
- else {
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[2]; patch.getLimitBorder(borders,1);
- BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
- eval(patches[1],Vec2f(2.0f*v,2.0f-2.0f*u),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
-#else
- eval(patches[1],Vec2f(2.0f*v,2.0f-2.0f*u),2.0f,depth+1);
-#endif
- if (dPdu && dPdv) {
- const Vertex dpdx = *dPdu, dpdy = *dPdv;
- *dPdu = -dpdy; *dPdv = dpdx;
- }
- }
- } else {
- if (u > 0.5f) {
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[2]; patch.getLimitBorder(borders,2);
- BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
- eval(patches[2],Vec2f(2.0f-2.0f*u,2.0f-2.0f*v),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
-#else
- eval(patches[2],Vec2f(2.0f-2.0f*u,2.0f-2.0f*v),2.0f,depth+1);
-#endif
- if (dPdu && dPdv) {
- const Vertex dpdx = *dPdu, dpdy = *dPdv;
- *dPdu = -dpdx; *dPdv = -dpdy;
- }
- }
- else {
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[2]; patch.getLimitBorder(borders,3);
- BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
- eval(patches[3],Vec2f(2.0f-2.0f*v,2.0f*u),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
-#else
- eval(patches[3],Vec2f(2.0f-2.0f*v,2.0f*u),2.0f,depth+1);
-#endif
- if (dPdu && dPdv) {
- const Vertex dpdx = *dPdu, dpdy = *dPdv;
- *dPdu = dpdy; *dPdv = -dpdx;
- }
- }
- }
- }
-
- __forceinline bool final(const CatmullClarkPatch& patch, const typename CatmullClarkRing::Type type, size_t depth)
- {
- const int max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
-//#if PATCH_MIN_RESOLUTION
-// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=(size_t)max_eval_depth;
-//#else
- return depth>=(size_t)max_eval_depth;
-//#endif
- }
-
- void eval(CatmullClarkPatch& patch, Vec2f uv, float dscale, size_t depth,
- BezierCurve* border0 = nullptr, BezierCurve* border1 = nullptr, BezierCurve* border2 = nullptr, BezierCurve* border3 = nullptr)
- {
- while (true)
- {
- typename CatmullClarkPatch::Type ty = patch.type();
-
- if (unlikely(final(patch,ty,depth)))
- {
- if (ty & CatmullClarkRing::TYPE_REGULAR) {
- RegularPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
- PATCH_DEBUG_SUBDIVISION(234423,c,c,-1);
- return;
- } else {
- IrregularFillPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
- PATCH_DEBUG_SUBDIVISION(34534,c,-1,c);
- return;
- }
- }
- else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
- assert(depth > 0);
- RegularPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
- PATCH_DEBUG_SUBDIVISION(43524,c,c,-1);
- return;
- }
-#if PATCH_USE_GREGORY == 2
- else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
- assert(depth > 0);
- GregoryPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
- PATCH_DEBUG_SUBDIVISION(23498,c,-1,c);
- return;
- }
-#endif
- else
- {
- array_t<CatmullClarkPatch,4> patches;
- patch.subdivide(patches); // FIXME: only have to generate one of the patches
-
- const float u = uv.x, v = uv.y;
- if (v < 0.5f) {
- if (u < 0.5f) { patch = patches[0]; uv = Vec2f(2.0f*u,2.0f*v); dscale *= 2.0f; }
- else { patch = patches[1]; uv = Vec2f(2.0f*u-1.0f,2.0f*v); dscale *= 2.0f; }
- } else {
- if (u > 0.5f) { patch = patches[2]; uv = Vec2f(2.0f*u-1.0f,2.0f*v-1.0f); dscale *= 2.0f; }
- else { patch = patches[3]; uv = Vec2f(2.0f*u,2.0f*v-1.0f); dscale *= 2.0f; }
- }
- depth++;
- }
- }
- }
-
- void eval(const GeneralCatmullClarkPatch& patch, const Vec2f& uv, const size_t depth)
- {
- /* convert into standard quad patch if possible */
- if (likely(patch.isQuadPatch()))
- {
- CatmullClarkPatch qpatch; patch.init(qpatch);
- return eval(qpatch,uv,1.0f,depth);
- }
-
- /* subdivide patch */
- unsigned N;
- array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches;
- patch.subdivide(patches,N); // FIXME: only have to generate one of the patches
-
- /* parametrization for quads */
- if (N == 4)
- eval_general_quad(patch,patches,uv,depth);
-
- /* parametrization for arbitrary polygons */
- else
- {
- const unsigned l = (unsigned) floor(0.5f*uv.x); const float u = 2.0f*frac(0.5f*uv.x)-0.5f;
- const unsigned h = (unsigned) floor(0.5f*uv.y); const float v = 2.0f*frac(0.5f*uv.y)-0.5f;
- const unsigned i = 4*h+l; assert(i<N);
- if (i >= N) return;
-
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[2]; patch.getLimitBorder(borders,i);
- BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
- eval(patches[i],Vec2f(u,v),1.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
-#else
- eval(patches[i],Vec2f(u,v),1.0f,depth+1);
-#endif
- }
- }
-
- private:
- Vertex* const P;
- Vertex* const dPdu;
- Vertex* const dPdv;
- Vertex* const ddPdudu;
- Vertex* const ddPdvdv;
- Vertex* const ddPdudv;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval_grid.h b/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval_grid.h
deleted file mode 100644
index 76583b2e5d..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval_grid.h
+++ /dev/null
@@ -1,359 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "patch.h"
-#include "catmullclark_patch.h"
-#include "bspline_patch.h"
-#include "gregory_patch.h"
-#include "tessellation.h"
-
-namespace embree
-{
- namespace isa
- {
- struct FeatureAdaptiveEvalGrid
- {
- typedef CatmullClark1Ring3fa CatmullClarkRing;
- typedef CatmullClarkPatch3fa CatmullClarkPatch;
- typedef BilinearPatch3fa BilinearPatch;
- typedef BSplinePatch3fa BSplinePatch;
- typedef BezierPatch3fa BezierPatch;
- typedef GregoryPatch3fa GregoryPatch;
-
- private:
- const unsigned x0,x1;
- const unsigned y0,y1;
- const unsigned swidth,sheight;
- const float rcp_swidth, rcp_sheight;
- float* const Px;
- float* const Py;
- float* const Pz;
- float* const U;
- float* const V;
- float* const Nx;
- float* const Ny;
- float* const Nz;
- const unsigned dwidth;
- //const unsigned dheight;
- unsigned count;
-
-
- public:
- FeatureAdaptiveEvalGrid (const GeneralCatmullClarkPatch3fa& patch, unsigned subPatch,
- const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
- float* Px, float* Py, float* Pz, float* U, float* V,
- float* Nx, float* Ny, float* Nz,
- const unsigned dwidth, const unsigned dheight)
- : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
- Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), /*dheight(dheight),*/ count(0)
- {
- assert(swidth < (2<<20) && sheight < (2<<20));
- const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(float(swidth-1),float(sheight-1)));
- const BBox2f erange(Vec2f((float)x0,(float)y0),Vec2f((float)x1,(float)y1));
-
- /* convert into standard quad patch if possible */
- if (likely(patch.isQuadPatch()))
- {
- CatmullClarkPatch3fa qpatch; patch.init(qpatch);
- eval(qpatch, srange, erange, 0);
- assert(count == (x1-x0+1)*(y1-y0+1));
- return;
- }
-
- /* subdivide patch */
- unsigned N;
- array_t<CatmullClarkPatch3fa,GeneralCatmullClarkPatch3fa::SIZE> patches;
- patch.subdivide(patches,N);
-
- if (N == 4)
- {
- const Vec2f c = srange.center();
- const BBox2f srange0(srange.lower,c);
- const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
- const BBox2f srange2(c,srange.upper);
- const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
-
-#if PATCH_USE_GREGORY == 2
- BezierCurve3fa borders[GeneralCatmullClarkPatch3fa::SIZE]; patch.getLimitBorder(borders);
- BezierCurve3fa border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve3fa border1l,border1r; borders[1].subdivide(border1l,border1r);
- BezierCurve3fa border2l,border2r; borders[2].subdivide(border2l,border2r);
- BezierCurve3fa border3l,border3r; borders[3].subdivide(border3l,border3r);
- GeneralCatmullClarkPatch3fa::fix_quad_ring_order(patches);
- eval(patches[0],srange0,intersect(srange0,erange),1,&border0l,nullptr,nullptr,&border3r);
- eval(patches[1],srange1,intersect(srange1,erange),1,&border0r,&border1l,nullptr,nullptr);
- eval(patches[2],srange2,intersect(srange2,erange),1,nullptr,&border1r,&border2l,nullptr);
- eval(patches[3],srange3,intersect(srange3,erange),1,nullptr,nullptr,&border2r,&border3l);
-#else
- GeneralCatmullClarkPatch3fa::fix_quad_ring_order(patches);
- eval(patches[0],srange0,intersect(srange0,erange),1);
- eval(patches[1],srange1,intersect(srange1,erange),1);
- eval(patches[2],srange2,intersect(srange2,erange),1);
- eval(patches[3],srange3,intersect(srange3,erange),1);
-#endif
- }
- else
- {
- assert(subPatch < N);
-
-#if PATCH_USE_GREGORY == 2
- BezierCurve3fa borders[2]; patch.getLimitBorder(borders,subPatch);
- BezierCurve3fa border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve3fa border2l,border2r; borders[1].subdivide(border2l,border2r);
- eval(patches[subPatch], srange, erange, 1, &border0l, nullptr, nullptr, &border2r);
-#else
- eval(patches[subPatch], srange, erange, 1);
-#endif
-
- }
- assert(count == (x1-x0+1)*(y1-y0+1));
- }
-
- FeatureAdaptiveEvalGrid (const CatmullClarkPatch3fa& patch,
- const BBox2f& srange, const BBox2f& erange, const unsigned depth,
- const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
- float* Px, float* Py, float* Pz, float* U, float* V,
- float* Nx, float* Ny, float* Nz,
- const unsigned dwidth, const unsigned dheight)
- : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
- Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), /*dheight(dheight),*/ count(0)
- {
- eval(patch,srange,erange,depth);
- }
-
- template<typename Patch>
- void evalLocalGrid(const Patch& patch, const BBox2f& srange, const int lx0, const int lx1, const int ly0, const int ly1)
- {
- const float scale_x = rcp(srange.upper.x-srange.lower.x);
- const float scale_y = rcp(srange.upper.y-srange.lower.y);
- count += (lx1-lx0)*(ly1-ly0);
-
-#if 0
- for (unsigned iy=ly0; iy<ly1; iy++) {
- for (unsigned ix=lx0; ix<lx1; ix++) {
- const float lu = select(ix == swidth -1, float(1.0f), (float(ix)-srange.lower.x)*scale_x);
- const float lv = select(iy == sheight-1, float(1.0f), (float(iy)-srange.lower.y)*scale_y);
- const Vec3fa p = patch.eval(lu,lv);
- const float u = float(ix)*rcp_swidth;
- const float v = float(iy)*rcp_sheight;
- const int ofs = (iy-y0)*dwidth+(ix-x0);
- Px[ofs] = p.x;
- Py[ofs] = p.y;
- Pz[ofs] = p.z;
- U[ofs] = u;
- V[ofs] = v;
- }
- }
-#else
- foreach2(lx0,lx1,ly0,ly1,[&](const vboolx& valid, const vintx& ix, const vintx& iy) {
- const vfloatx lu = select(ix == swidth -1, vfloatx(1.0f), (vfloatx(ix)-srange.lower.x)*scale_x);
- const vfloatx lv = select(iy == sheight-1, vfloatx(1.0f), (vfloatx(iy)-srange.lower.y)*scale_y);
- const Vec3vfx p = patch.eval(lu,lv);
- Vec3vfx n = zero;
- if (unlikely(Nx != nullptr)) n = normalize_safe(patch.normal(lu,lv));
- const vfloatx u = vfloatx(ix)*rcp_swidth;
- const vfloatx v = vfloatx(iy)*rcp_sheight;
- const vintx ofs = (iy-y0)*dwidth+(ix-x0);
- if (likely(all(valid)) && all(iy==iy[0])) {
- const unsigned ofs2 = ofs[0];
- vfloatx::storeu(Px+ofs2,p.x);
- vfloatx::storeu(Py+ofs2,p.y);
- vfloatx::storeu(Pz+ofs2,p.z);
- vfloatx::storeu(U+ofs2,u);
- vfloatx::storeu(V+ofs2,v);
- if (unlikely(Nx != nullptr)) {
- vfloatx::storeu(Nx+ofs2,n.x);
- vfloatx::storeu(Ny+ofs2,n.y);
- vfloatx::storeu(Nz+ofs2,n.z);
- }
- } else {
- foreach_unique_index(valid,iy,[&](const vboolx& valid, const int iy0, const int j) {
- const unsigned ofs2 = ofs[j]-j;
- vfloatx::storeu(valid,Px+ofs2,p.x);
- vfloatx::storeu(valid,Py+ofs2,p.y);
- vfloatx::storeu(valid,Pz+ofs2,p.z);
- vfloatx::storeu(valid,U+ofs2,u);
- vfloatx::storeu(valid,V+ofs2,v);
- if (unlikely(Nx != nullptr)) {
- vfloatx::storeu(valid,Nx+ofs2,n.x);
- vfloatx::storeu(valid,Ny+ofs2,n.y);
- vfloatx::storeu(valid,Nz+ofs2,n.z);
- }
- });
- }
- });
-#endif
- }
-
- __forceinline bool final(const CatmullClarkPatch3fa& patch, const CatmullClarkRing::Type type, unsigned depth)
- {
- const unsigned max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
-//#if PATCH_MIN_RESOLUTION
-// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=max_eval_depth;
-//#else
- return depth>=max_eval_depth;
-//#endif
- }
-
- void eval(const CatmullClarkPatch3fa& patch, const BBox2f& srange, const BBox2f& erange, const unsigned depth,
- const BezierCurve3fa* border0 = nullptr, const BezierCurve3fa* border1 = nullptr, const BezierCurve3fa* border2 = nullptr, const BezierCurve3fa* border3 = nullptr)
- {
- if (erange.empty())
- return;
-
- int lx0 = (int) ceilf(erange.lower.x);
- int lx1 = (int) ceilf(erange.upper.x) + (erange.upper.x == x1 && (srange.lower.x < erange.upper.x || erange.upper.x == 0));
- int ly0 = (int) ceilf(erange.lower.y);
- int ly1 = (int) ceilf(erange.upper.y) + (erange.upper.y == y1 && (srange.lower.y < erange.upper.y || erange.upper.y == 0));
- if (lx0 >= lx1 || ly0 >= ly1) return;
-
- CatmullClarkPatch::Type ty = patch.type();
-
- if (unlikely(final(patch,ty,depth)))
- {
- if (ty & CatmullClarkRing::TYPE_REGULAR) {
- RegularPatch rpatch(patch,border0,border1,border2,border3);
- evalLocalGrid(rpatch,srange,lx0,lx1,ly0,ly1);
- return;
- } else {
- IrregularFillPatch ipatch(patch,border0,border1,border2,border3);
- evalLocalGrid(ipatch,srange,lx0,lx1,ly0,ly1);
- return;
- }
- }
- else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
- assert(depth > 0);
- RegularPatch rpatch(patch,border0,border1,border2,border3);
- evalLocalGrid(rpatch,srange,lx0,lx1,ly0,ly1);
- return;
- }
-#if PATCH_USE_GREGORY == 2
- else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
- assert(depth > 0);
- GregoryPatch gpatch(patch,border0,border1,border2,border3);
- evalLocalGrid(gpatch,srange,lx0,lx1,ly0,ly1);
- }
-#endif
- else
- {
- array_t<CatmullClarkPatch3fa,4> patches;
- patch.subdivide(patches);
-
- const Vec2f c = srange.center();
- const BBox2f srange0(srange.lower,c);
- const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
- const BBox2f srange2(c,srange.upper);
- const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
-
- eval(patches[0],srange0,intersect(srange0,erange),depth+1);
- eval(patches[1],srange1,intersect(srange1,erange),depth+1);
- eval(patches[2],srange2,intersect(srange2,erange),depth+1);
- eval(patches[3],srange3,intersect(srange3,erange),depth+1);
- }
- }
- };
-
- template<typename Eval, typename Patch>
- bool stitch_col(const Patch& patch, int subPatch,
- const bool right, const unsigned y0, const unsigned y1, const int fine_y, const int coarse_y,
- float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dx0, const unsigned dwidth, const unsigned dheight)
- {
- assert(coarse_y <= fine_y);
- if (likely(fine_y == coarse_y))
- return false;
-
- const unsigned y0s = stitch(y0,fine_y,coarse_y);
- const unsigned y1s = stitch(y1,fine_y,coarse_y);
- const unsigned M = y1s-y0s+1 + VSIZEX;
-
- dynamic_large_stack_array(float,px,M,64*sizeof(float));
- dynamic_large_stack_array(float,py,M,64*sizeof(float));
- dynamic_large_stack_array(float,pz,M,64*sizeof(float));
- dynamic_large_stack_array(float,u,M,64*sizeof(float));
- dynamic_large_stack_array(float,v,M,64*sizeof(float));
- dynamic_large_stack_array(float,nx,M,64*sizeof(float));
- dynamic_large_stack_array(float,ny,M,64*sizeof(float));
- dynamic_large_stack_array(float,nz,M,64*sizeof(float));
- const bool has_Nxyz = Nx; assert(!Nx || (Ny && Nz));
- Eval(patch,subPatch, right,right, y0s,y1s, 2,coarse_y+1, px,py,pz,u,v,
- has_Nxyz ? (float*)nx : nullptr,has_Nxyz ? (float*)ny : nullptr ,has_Nxyz ? (float*)nz : nullptr, 1,4097);
-
- for (unsigned y=y0; y<=y1; y++)
- {
- const unsigned ys = stitch(y,fine_y,coarse_y)-y0s;
- Px[(y-y0)*dwidth+dx0] = px[ys];
- Py[(y-y0)*dwidth+dx0] = py[ys];
- Pz[(y-y0)*dwidth+dx0] = pz[ys];
- U [(y-y0)*dwidth+dx0] = u[ys];
- V [(y-y0)*dwidth+dx0] = v[ys];
- if (unlikely(has_Nxyz)) {
- Nx[(y-y0)*dwidth+dx0] = nx[ys];
- Ny[(y-y0)*dwidth+dx0] = ny[ys];
- Nz[(y-y0)*dwidth+dx0] = nz[ys];
- }
- }
- return true;
- }
-
- template<typename Eval, typename Patch>
- bool stitch_row(const Patch& patch, int subPatch,
- const bool bottom, const unsigned x0, const unsigned x1, const int fine_x, const int coarse_x,
- float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dy0, const unsigned dwidth, const unsigned dheight)
- {
- assert(coarse_x <= fine_x);
- if (likely(fine_x == coarse_x))
- return false;
-
- const unsigned x0s = stitch(x0,fine_x,coarse_x);
- const unsigned x1s = stitch(x1,fine_x,coarse_x);
- const unsigned M = x1s-x0s+1 + VSIZEX;
-
- dynamic_large_stack_array(float,px,M,32*sizeof(float));
- dynamic_large_stack_array(float,py,M,32*sizeof(float));
- dynamic_large_stack_array(float,pz,M,32*sizeof(float));
- dynamic_large_stack_array(float,u,M,32*sizeof(float));
- dynamic_large_stack_array(float,v,M,32*sizeof(float));
- dynamic_large_stack_array(float,nx,M,32*sizeof(float));
- dynamic_large_stack_array(float,ny,M,32*sizeof(float));
- dynamic_large_stack_array(float,nz,M,32*sizeof(float));
- const bool has_Nxyz = Nx; assert(!Nx || (Ny && Nz));
- Eval(patch,subPatch, x0s,x1s, bottom,bottom, coarse_x+1,2, px,py,pz,u,v,
- has_Nxyz ? (float*)nx :nullptr, has_Nxyz ? (float*)ny : nullptr , has_Nxyz ? (float*)nz : nullptr, 4097,1);
-
- for (unsigned x=x0; x<=x1; x++)
- {
- const unsigned xs = stitch(x,fine_x,coarse_x)-x0s;
- Px[dy0*dwidth+x-x0] = px[xs];
- Py[dy0*dwidth+x-x0] = py[xs];
- Pz[dy0*dwidth+x-x0] = pz[xs];
- U [dy0*dwidth+x-x0] = u[xs];
- V [dy0*dwidth+x-x0] = v[xs];
- if (unlikely(has_Nxyz)) {
- Nx[dy0*dwidth+x-x0] = nx[xs];
- Ny[dy0*dwidth+x-x0] = ny[xs];
- Nz[dy0*dwidth+x-x0] = nz[xs];
- }
- }
- return true;
- }
-
- template<typename Eval, typename Patch>
- void feature_adaptive_eval_grid (const Patch& patch, unsigned subPatch, const float levels[4],
- const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
- float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dwidth, const unsigned dheight)
- {
- bool sl = false, sr = false, st = false, sb = false;
- if (levels) {
- sl = x0 == 0 && stitch_col<Eval,Patch>(patch,subPatch,0,y0,y1,sheight-1,int(levels[3]), Px,Py,Pz,U,V,Nx,Ny,Nz, 0 ,dwidth,dheight);
- sr = x1 == swidth-1 && stitch_col<Eval,Patch>(patch,subPatch,1,y0,y1,sheight-1,int(levels[1]), Px,Py,Pz,U,V,Nx,Ny,Nz, x1-x0,dwidth,dheight);
- st = y0 == 0 && stitch_row<Eval,Patch>(patch,subPatch,0,x0,x1,swidth-1,int(levels[0]), Px,Py,Pz,U,V,Nx,Ny,Nz, 0 ,dwidth,dheight);
- sb = y1 == sheight-1 && stitch_row<Eval,Patch>(patch,subPatch,1,x0,x1,swidth-1,int(levels[2]), Px,Py,Pz,U,V,Nx,Ny,Nz, y1-y0,dwidth,dheight);
- }
- const unsigned ofs = st*dwidth+sl;
- Eval(patch,subPatch,x0+sl,x1-sr,y0+st,y1-sb, swidth,sheight, Px+ofs,Py+ofs,Pz+ofs,U+ofs,V+ofs,Nx?Nx+ofs:nullptr,Ny?Ny+ofs:nullptr,Nz?Nz+ofs:nullptr, dwidth,dheight);
- }
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval_simd.h b/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval_simd.h
deleted file mode 100644
index fa3216730f..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/feature_adaptive_eval_simd.h
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "patch.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename vbool, typename vint, typename vfloat, typename Vertex, typename Vertex_t = Vertex>
- struct FeatureAdaptiveEvalSimd
- {
- public:
-
- typedef PatchT<Vertex,Vertex_t> Patch;
- typedef typename Patch::Ref Ref;
- typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
- typedef BSplinePatchT<Vertex,Vertex_t> BSplinePatch;
- typedef BezierPatchT<Vertex,Vertex_t> BezierPatch;
- typedef GregoryPatchT<Vertex,Vertex_t> GregoryPatch;
- typedef BilinearPatchT<Vertex,Vertex_t> BilinearPatch;
- typedef BezierCurveT<Vertex> BezierCurve;
-
- FeatureAdaptiveEvalSimd (const HalfEdge* edge, const char* vertices, size_t stride, const vbool& valid, const vfloat& u, const vfloat& v,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, const size_t dstride, const size_t N)
- : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv), dstride(dstride), N(N)
- {
- switch (edge->patch_type) {
- case HalfEdge::BILINEAR_PATCH: BilinearPatch(edge,vertices,stride).eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f,dstride,N); break;
- case HalfEdge::REGULAR_QUAD_PATCH: RegularPatchT(edge,vertices,stride).eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f,dstride,N); break;
-#if PATCH_USE_GREGORY == 2
- case HalfEdge::IRREGULAR_QUAD_PATCH: GregoryPatchT<Vertex,Vertex_t>(edge,vertices,stride).eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f,dstride,N); break;
-#endif
- default: {
- GeneralCatmullClarkPatch patch(edge,vertices,stride);
- eval_direct(valid,patch,Vec2<vfloat>(u,v),0);
- break;
- }
- }
- }
-
- FeatureAdaptiveEvalSimd (const CatmullClarkPatch& patch, const vbool& valid, const vfloat& u, const vfloat& v, float dscale, size_t depth,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, const size_t dstride, const size_t N)
- : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv), dstride(dstride), N(N)
- {
- eval_direct(valid,patch,Vec2<vfloat>(u,v),dscale,depth);
- }
-
- template<size_t N>
- __forceinline void eval_quad_direct(const vbool& valid, array_t<CatmullClarkPatch,N>& patches, const Vec2<vfloat>& uv, float dscale, size_t depth)
- {
- const vfloat u = uv.x, v = uv.y;
- const vbool u0_mask = u < 0.5f, u1_mask = u >= 0.5f;
- const vbool v0_mask = v < 0.5f, v1_mask = v >= 0.5f;
- const vbool u0v0_mask = valid & u0_mask & v0_mask;
- const vbool u0v1_mask = valid & u0_mask & v1_mask;
- const vbool u1v0_mask = valid & u1_mask & v0_mask;
- const vbool u1v1_mask = valid & u1_mask & v1_mask;
- if (any(u0v0_mask)) eval_direct(u0v0_mask,patches[0],Vec2<vfloat>(2.0f*u,2.0f*v),2.0f*dscale,depth+1);
- if (any(u1v0_mask)) eval_direct(u1v0_mask,patches[1],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v),2.0f*dscale,depth+1);
- if (any(u1v1_mask)) eval_direct(u1v1_mask,patches[2],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v-1.0f),2.0f*dscale,depth+1);
- if (any(u0v1_mask)) eval_direct(u0v1_mask,patches[3],Vec2<vfloat>(2.0f*u,2.0f*v-1.0f),2.0f*dscale,depth+1);
- }
-
- template<size_t N>
- __forceinline void eval_general_quad_direct(const vbool& valid, const GeneralCatmullClarkPatch& patch, array_t<CatmullClarkPatch,N>& patches, const Vec2<vfloat>& uv, float dscale, size_t depth)
- {
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[GeneralCatmullClarkPatch::SIZE]; patch.getLimitBorder(borders);
- BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve border1l,border1r; borders[1].subdivide(border1l,border1r);
- BezierCurve border2l,border2r; borders[2].subdivide(border2l,border2r);
- BezierCurve border3l,border3r; borders[3].subdivide(border3l,border3r);
-#endif
- GeneralCatmullClarkPatch::fix_quad_ring_order(patches);
- const vfloat u = uv.x, v = uv.y;
- const vbool u0_mask = u < 0.5f, u1_mask = u >= 0.5f;
- const vbool v0_mask = v < 0.5f, v1_mask = v >= 0.5f;
- const vbool u0v0_mask = valid & u0_mask & v0_mask;
- const vbool u0v1_mask = valid & u0_mask & v1_mask;
- const vbool u1v0_mask = valid & u1_mask & v0_mask;
- const vbool u1v1_mask = valid & u1_mask & v1_mask;
-#if PATCH_USE_GREGORY == 2
- if (any(u0v0_mask)) eval_direct(u0v0_mask,patches[0],Vec2<vfloat>(2.0f*u,2.0f*v),2.0f*dscale,depth+1,&border0l,nullptr,nullptr,&border3r);
- if (any(u1v0_mask)) eval_direct(u1v0_mask,patches[1],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v),2.0f*dscale,depth+1,&border0r,&border1l,nullptr,nullptr);
- if (any(u1v1_mask)) eval_direct(u1v1_mask,patches[2],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v-1.0f),2.0f*dscale,depth+1,nullptr,&border1r,&border2l,nullptr);
- if (any(u0v1_mask)) eval_direct(u0v1_mask,patches[3],Vec2<vfloat>(2.0f*u,2.0f*v-1.0f),2.0f*dscale,depth+1,nullptr,nullptr,&border2r,&border3l);
-#else
- if (any(u0v0_mask)) eval_direct(u0v0_mask,patches[0],Vec2<vfloat>(2.0f*u,2.0f*v),2.0f*dscale,depth+1);
- if (any(u1v0_mask)) eval_direct(u1v0_mask,patches[1],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v),2.0f*dscale,depth+1);
- if (any(u1v1_mask)) eval_direct(u1v1_mask,patches[2],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v-1.0f),2.0f*dscale,depth+1);
- if (any(u0v1_mask)) eval_direct(u0v1_mask,patches[3],Vec2<vfloat>(2.0f*u,2.0f*v-1.0f),2.0f*dscale,depth+1);
-#endif
- }
-
- __forceinline bool final(const CatmullClarkPatch& patch, const typename CatmullClarkRing::Type type, size_t depth)
- {
- const size_t max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
-//#if PATCH_MIN_RESOLUTION
-// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=max_eval_depth;
-//#else
- return depth>=max_eval_depth;
-//#endif
- }
-
- void eval_direct(const vbool& valid, const CatmullClarkPatch& patch, const Vec2<vfloat>& uv, float dscale, size_t depth,
- BezierCurve* border0 = nullptr, BezierCurve* border1 = nullptr, BezierCurve* border2 = nullptr, BezierCurve* border3 = nullptr)
- {
- typename CatmullClarkPatch::Type ty = patch.type();
-
- if (unlikely(final(patch,ty,depth)))
- {
- if (ty & CatmullClarkRing::TYPE_REGULAR) {
- RegularPatch(patch,border0,border1,border2,border3).eval(valid,uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- } else {
- IrregularFillPatch(patch,border0,border1,border2,border3).eval(valid,uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- }
- }
- else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
- assert(depth > 0); RegularPatch(patch,border0,border1,border2,border3).eval(valid,uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- }
-#if PATCH_USE_GREGORY == 2
- else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
- assert(depth > 0); GregoryPatch(patch,border0,border1,border2,border3).eval(valid,uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- }
-#endif
- else
- {
- array_t<CatmullClarkPatch,4> patches;
- patch.subdivide(patches); // FIXME: only have to generate one of the patches
- eval_quad_direct(valid,patches,uv,dscale,depth);
- }
- }
-
- void eval_direct(const vbool& valid, const GeneralCatmullClarkPatch& patch, const Vec2<vfloat>& uv, const size_t depth)
- {
- /* convert into standard quad patch if possible */
- if (likely(patch.isQuadPatch())) {
- CatmullClarkPatch qpatch; patch.init(qpatch);
- return eval_direct(valid,qpatch,uv,1.0f,depth);
- }
-
- /* subdivide patch */
- unsigned Nc;
- array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches;
- patch.subdivide(patches,Nc); // FIXME: only have to generate one of the patches
-
- /* parametrization for quads */
- if (Nc == 4)
- eval_general_quad_direct(valid,patch,patches,uv,1.0f,depth);
-
- /* parametrization for arbitrary polygons */
- else
- {
- const vint l = (vint)floor(0.5f*uv.x); const vfloat u = 2.0f*frac(0.5f*uv.x)-0.5f;
- const vint h = (vint)floor(0.5f*uv.y); const vfloat v = 2.0f*frac(0.5f*uv.y)-0.5f;
- const vint i = (h<<2)+l; assert(all(valid,i<Nc));
- foreach_unique(valid,i,[&](const vbool& valid, const int i) {
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[2]; patch.getLimitBorder(borders,i);
- BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
- eval_direct(valid,patches[i],Vec2<vfloat>(u,v),1.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
-#else
- eval_direct(valid,patches[i],Vec2<vfloat>(u,v),1.0f,depth+1);
-#endif
- });
- }
- }
-
- private:
- float* const P;
- float* const dPdu;
- float* const dPdv;
- float* const ddPdudu;
- float* const ddPdvdv;
- float* const ddPdudv;
- const size_t dstride;
- const size_t N;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/gregory_patch.h b/thirdparty/embree-aarch64/kernels/subdiv/gregory_patch.h
deleted file mode 100644
index 2a7c4b1f2c..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/gregory_patch.h
+++ /dev/null
@@ -1,893 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "catmullclark_patch.h"
-#include "bezier_patch.h"
-#include "bezier_curve.h"
-#include "catmullclark_coefficients.h"
-
-namespace embree
-{
- template<typename Vertex, typename Vertex_t = Vertex>
- class __aligned(64) GregoryPatchT
- {
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
- typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
- typedef BezierCurveT<Vertex> BezierCurve;
-
- public:
- Vertex v[4][4];
- Vertex f[2][2];
-
- __forceinline GregoryPatchT() {}
-
- __forceinline GregoryPatchT(const CatmullClarkPatch& patch) {
- init(patch);
- }
-
- __forceinline GregoryPatchT(const CatmullClarkPatch& patch,
- const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)
- {
- init_crackfix(patch,border0,border1,border2,border3);
- }
-
- __forceinline GregoryPatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
- init(CatmullClarkPatch(edge,vertices,stride));
- }
-
- __forceinline Vertex& p0() { return v[0][0]; }
- __forceinline Vertex& p1() { return v[0][3]; }
- __forceinline Vertex& p2() { return v[3][3]; }
- __forceinline Vertex& p3() { return v[3][0]; }
-
- __forceinline Vertex& e0_p() { return v[0][1]; }
- __forceinline Vertex& e0_m() { return v[1][0]; }
- __forceinline Vertex& e1_p() { return v[1][3]; }
- __forceinline Vertex& e1_m() { return v[0][2]; }
- __forceinline Vertex& e2_p() { return v[3][2]; }
- __forceinline Vertex& e2_m() { return v[2][3]; }
- __forceinline Vertex& e3_p() { return v[2][0]; }
- __forceinline Vertex& e3_m() { return v[3][1]; }
-
- __forceinline Vertex& f0_p() { return v[1][1]; }
- __forceinline Vertex& f1_p() { return v[1][2]; }
- __forceinline Vertex& f2_p() { return v[2][2]; }
- __forceinline Vertex& f3_p() { return v[2][1]; }
- __forceinline Vertex& f0_m() { return f[0][0]; }
- __forceinline Vertex& f1_m() { return f[0][1]; }
- __forceinline Vertex& f2_m() { return f[1][1]; }
- __forceinline Vertex& f3_m() { return f[1][0]; }
-
- __forceinline const Vertex& p0() const { return v[0][0]; }
- __forceinline const Vertex& p1() const { return v[0][3]; }
- __forceinline const Vertex& p2() const { return v[3][3]; }
- __forceinline const Vertex& p3() const { return v[3][0]; }
-
- __forceinline const Vertex& e0_p() const { return v[0][1]; }
- __forceinline const Vertex& e0_m() const { return v[1][0]; }
- __forceinline const Vertex& e1_p() const { return v[1][3]; }
- __forceinline const Vertex& e1_m() const { return v[0][2]; }
- __forceinline const Vertex& e2_p() const { return v[3][2]; }
- __forceinline const Vertex& e2_m() const { return v[2][3]; }
- __forceinline const Vertex& e3_p() const { return v[2][0]; }
- __forceinline const Vertex& e3_m() const { return v[3][1]; }
-
- __forceinline const Vertex& f0_p() const { return v[1][1]; }
- __forceinline const Vertex& f1_p() const { return v[1][2]; }
- __forceinline const Vertex& f2_p() const { return v[2][2]; }
- __forceinline const Vertex& f3_p() const { return v[2][1]; }
- __forceinline const Vertex& f0_m() const { return f[0][0]; }
- __forceinline const Vertex& f1_m() const { return f[0][1]; }
- __forceinline const Vertex& f2_m() const { return f[1][1]; }
- __forceinline const Vertex& f3_m() const { return f[1][0]; }
-
- __forceinline Vertex initCornerVertex(const CatmullClarkPatch& irreg_patch, const size_t index) {
- return irreg_patch.ring[index].getLimitVertex();
- }
-
- __forceinline Vertex initPositiveEdgeVertex(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx) {
- return madd(1.0f/3.0f,irreg_patch.ring[index].getLimitTangent(),p_vtx);
- }
-
- __forceinline Vertex initNegativeEdgeVertex(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx) {
- return madd(1.0f/3.0f,irreg_patch.ring[index].getSecondLimitTangent(),p_vtx);
- }
-
- __forceinline Vertex initPositiveEdgeVertex2(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx)
- {
- CatmullClark1Ring3fa r0,r1,r2;
- irreg_patch.ring[index].subdivide(r0);
- r0.subdivide(r1);
- r1.subdivide(r2);
- return madd(8.0f/3.0f,r2.getLimitTangent(),p_vtx);
- }
-
- __forceinline Vertex initNegativeEdgeVertex2(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx)
- {
- CatmullClark1Ring3fa r0,r1,r2;
- irreg_patch.ring[index].subdivide(r0);
- r0.subdivide(r1);
- r1.subdivide(r2);
- return madd(8.0f/3.0f,r2.getSecondLimitTangent(),p_vtx);
- }
-
- void initFaceVertex(const CatmullClarkPatch& irreg_patch,
- const size_t index,
- const Vertex& p_vtx,
- const Vertex& e0_p_vtx,
- const Vertex& e1_m_vtx,
- const unsigned int face_valence_p1,
- const Vertex& e0_m_vtx,
- const Vertex& e3_p_vtx,
- const unsigned int face_valence_p3,
- Vertex& f_p_vtx,
- Vertex& f_m_vtx)
- {
- const unsigned int face_valence = irreg_patch.ring[index].face_valence;
- const unsigned int edge_valence = irreg_patch.ring[index].edge_valence;
- const unsigned int border_index = irreg_patch.ring[index].border_index;
-
- const Vertex& vtx = irreg_patch.ring[index].vtx;
- const Vertex e_i = irreg_patch.ring[index].getEdgeCenter(0);
- const Vertex c_i_m_1 = irreg_patch.ring[index].getQuadCenter(0);
- const Vertex e_i_m_1 = irreg_patch.ring[index].getEdgeCenter(1);
-
- Vertex c_i, e_i_p_1;
- const bool hasHardEdge0 =
- std::isinf(irreg_patch.ring[index].vertex_crease_weight) &&
- std::isinf(irreg_patch.ring[index].crease_weight[0]);
-
- if (unlikely((border_index == edge_valence-2) || hasHardEdge0))
- {
- /* mirror quad center and edge mid-point */
- c_i = madd(2.0f, e_i - c_i_m_1, c_i_m_1);
- e_i_p_1 = madd(2.0f, vtx - e_i_m_1, e_i_m_1);
- }
- else
- {
- c_i = irreg_patch.ring[index].getQuadCenter( face_valence-1 );
- e_i_p_1 = irreg_patch.ring[index].getEdgeCenter( face_valence-1 );
- }
-
- Vertex c_i_m_2, e_i_m_2;
- const bool hasHardEdge1 =
- std::isinf(irreg_patch.ring[index].vertex_crease_weight) &&
- std::isinf(irreg_patch.ring[index].crease_weight[1]);
-
- if (unlikely(border_index == 2 || hasHardEdge1))
- {
- /* mirror quad center and edge mid-point */
- c_i_m_2 = madd(2.0f, e_i_m_1 - c_i_m_1, c_i_m_1);
- e_i_m_2 = madd(2.0f, vtx - e_i, + e_i);
- }
- else
- {
- c_i_m_2 = irreg_patch.ring[index].getQuadCenter( 1 );
- e_i_m_2 = irreg_patch.ring[index].getEdgeCenter( 2 );
- }
-
- const float d = 3.0f;
- //const float c = cosf(2.0f*M_PI/(float)face_valence);
- //const float c_e_p = cosf(2.0f*M_PI/(float)face_valence_p1);
- //const float c_e_m = cosf(2.0f*M_PI/(float)face_valence_p3);
-
- const float c = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence);
- const float c_e_p = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p1);
- const float c_e_m = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p3);
-
- const Vertex r_e_p = 1.0f/3.0f * (e_i_m_1 - e_i_p_1) + 2.0f/3.0f * (c_i_m_1 - c_i);
- const Vertex r_e_m = 1.0f/3.0f * (e_i - e_i_m_2) + 2.0f/3.0f * (c_i_m_1 - c_i_m_2);
-
- f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);
- f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);
- }
-
- __noinline void init(const CatmullClarkPatch& patch)
- {
- assert( patch.ring[0].hasValidPositions() );
- assert( patch.ring[1].hasValidPositions() );
- assert( patch.ring[2].hasValidPositions() );
- assert( patch.ring[3].hasValidPositions() );
-
- p0() = initCornerVertex(patch,0);
- p1() = initCornerVertex(patch,1);
- p2() = initCornerVertex(patch,2);
- p3() = initCornerVertex(patch,3);
-
- e0_p() = initPositiveEdgeVertex(patch,0, p0());
- e1_p() = initPositiveEdgeVertex(patch,1, p1());
- e2_p() = initPositiveEdgeVertex(patch,2, p2());
- e3_p() = initPositiveEdgeVertex(patch,3, p3());
-
- e0_m() = initNegativeEdgeVertex(patch,0, p0());
- e1_m() = initNegativeEdgeVertex(patch,1, p1());
- e2_m() = initNegativeEdgeVertex(patch,2, p2());
- e3_m() = initNegativeEdgeVertex(patch,3, p3());
-
- const unsigned int face_valence_p0 = patch.ring[0].face_valence;
- const unsigned int face_valence_p1 = patch.ring[1].face_valence;
- const unsigned int face_valence_p2 = patch.ring[2].face_valence;
- const unsigned int face_valence_p3 = patch.ring[3].face_valence;
-
- initFaceVertex(patch,0,p0(),e0_p(),e1_m(),face_valence_p1,e0_m(),e3_p(),face_valence_p3,f0_p(),f0_m() );
- initFaceVertex(patch,1,p1(),e1_p(),e2_m(),face_valence_p2,e1_m(),e0_p(),face_valence_p0,f1_p(),f1_m() );
- initFaceVertex(patch,2,p2(),e2_p(),e3_m(),face_valence_p3,e2_m(),e1_p(),face_valence_p1,f2_p(),f2_m() );
- initFaceVertex(patch,3,p3(),e3_p(),e0_m(),face_valence_p0,e3_m(),e2_p(),face_valence_p3,f3_p(),f3_m() );
-
- }
-
- __noinline void init_crackfix(const CatmullClarkPatch& patch,
- const BezierCurve* border0,
- const BezierCurve* border1,
- const BezierCurve* border2,
- const BezierCurve* border3)
- {
- assert( patch.ring[0].hasValidPositions() );
- assert( patch.ring[1].hasValidPositions() );
- assert( patch.ring[2].hasValidPositions() );
- assert( patch.ring[3].hasValidPositions() );
-
- p0() = initCornerVertex(patch,0);
- p1() = initCornerVertex(patch,1);
- p2() = initCornerVertex(patch,2);
- p3() = initCornerVertex(patch,3);
-
- e0_p() = initPositiveEdgeVertex(patch,0, p0());
- e1_p() = initPositiveEdgeVertex(patch,1, p1());
- e2_p() = initPositiveEdgeVertex(patch,2, p2());
- e3_p() = initPositiveEdgeVertex(patch,3, p3());
-
- e0_m() = initNegativeEdgeVertex(patch,0, p0());
- e1_m() = initNegativeEdgeVertex(patch,1, p1());
- e2_m() = initNegativeEdgeVertex(patch,2, p2());
- e3_m() = initNegativeEdgeVertex(patch,3, p3());
-
- if (unlikely(border0 != nullptr))
- {
- p0() = border0->v0;
- e0_p() = border0->v1;
- e1_m() = border0->v2;
- p1() = border0->v3;
- }
-
- if (unlikely(border1 != nullptr))
- {
- p1() = border1->v0;
- e1_p() = border1->v1;
- e2_m() = border1->v2;
- p2() = border1->v3;
- }
-
- if (unlikely(border2 != nullptr))
- {
- p2() = border2->v0;
- e2_p() = border2->v1;
- e3_m() = border2->v2;
- p3() = border2->v3;
- }
-
- if (unlikely(border3 != nullptr))
- {
- p3() = border3->v0;
- e3_p() = border3->v1;
- e0_m() = border3->v2;
- p0() = border3->v3;
- }
-
- const unsigned int face_valence_p0 = patch.ring[0].face_valence;
- const unsigned int face_valence_p1 = patch.ring[1].face_valence;
- const unsigned int face_valence_p2 = patch.ring[2].face_valence;
- const unsigned int face_valence_p3 = patch.ring[3].face_valence;
-
- initFaceVertex(patch,0,p0(),e0_p(),e1_m(),face_valence_p1,e0_m(),e3_p(),face_valence_p3,f0_p(),f0_m() );
- initFaceVertex(patch,1,p1(),e1_p(),e2_m(),face_valence_p2,e1_m(),e0_p(),face_valence_p0,f1_p(),f1_m() );
- initFaceVertex(patch,2,p2(),e2_p(),e3_m(),face_valence_p3,e2_m(),e1_p(),face_valence_p1,f2_p(),f2_m() );
- initFaceVertex(patch,3,p3(),e3_p(),e0_m(),face_valence_p0,e3_m(),e2_p(),face_valence_p3,f3_p(),f3_m() );
- }
-
-
- void computeGregoryPatchFacePoints(const unsigned int face_valence,
- const Vertex& r_e_p,
- const Vertex& r_e_m,
- const Vertex& p_vtx,
- const Vertex& e0_p_vtx,
- const Vertex& e1_m_vtx,
- const unsigned int face_valence_p1,
- const Vertex& e0_m_vtx,
- const Vertex& e3_p_vtx,
- const unsigned int face_valence_p3,
- Vertex& f_p_vtx,
- Vertex& f_m_vtx,
- const float d = 3.0f)
- {
- //const float c = cosf(2.0*M_PI/(float)face_valence);
- //const float c_e_p = cosf(2.0*M_PI/(float)face_valence_p1);
- //const float c_e_m = cosf(2.0*M_PI/(float)face_valence_p3);
-
- const float c = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence);
- const float c_e_p = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p1);
- const float c_e_m = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p3);
-
-
- f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);
- f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);
- f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);
- f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);
- }
-
- __noinline void init(const GeneralCatmullClarkPatch& patch)
- {
- assert(patch.size() == 4);
-#if 0
- CatmullClarkPatch qpatch; patch.init(qpatch);
- init(qpatch);
-#else
- const float face_valence_p0 = patch.ring[0].face_valence;
- const float face_valence_p1 = patch.ring[1].face_valence;
- const float face_valence_p2 = patch.ring[2].face_valence;
- const float face_valence_p3 = patch.ring[3].face_valence;
-
- Vertex p0_r_p, p0_r_m;
- patch.ring[0].computeGregoryPatchEdgePoints( p0(), e0_p(), e0_m(), p0_r_p, p0_r_m );
-
- Vertex p1_r_p, p1_r_m;
- patch.ring[1].computeGregoryPatchEdgePoints( p1(), e1_p(), e1_m(), p1_r_p, p1_r_m );
-
- Vertex p2_r_p, p2_r_m;
- patch.ring[2].computeGregoryPatchEdgePoints( p2(), e2_p(), e2_m(), p2_r_p, p2_r_m );
-
- Vertex p3_r_p, p3_r_m;
- patch.ring[3].computeGregoryPatchEdgePoints( p3(), e3_p(), e3_m(), p3_r_p, p3_r_m );
-
- computeGregoryPatchFacePoints(face_valence_p0, p0_r_p, p0_r_m, p0(), e0_p(), e1_m(), face_valence_p1, e0_m(), e3_p(), face_valence_p3, f0_p(), f0_m() );
- computeGregoryPatchFacePoints(face_valence_p1, p1_r_p, p1_r_m, p1(), e1_p(), e2_m(), face_valence_p2, e1_m(), e0_p(), face_valence_p0, f1_p(), f1_m() );
- computeGregoryPatchFacePoints(face_valence_p2, p2_r_p, p2_r_m, p2(), e2_p(), e3_m(), face_valence_p3, e2_m(), e1_p(), face_valence_p1, f2_p(), f2_m() );
- computeGregoryPatchFacePoints(face_valence_p3, p3_r_p, p3_r_m, p3(), e3_p(), e0_m(), face_valence_p0, e3_m(), e2_p(), face_valence_p3, f3_p(), f3_m() );
-
-#endif
- }
-
-
- __forceinline void convert_to_bezier()
- {
- f0_p() = (f0_p() + f0_m()) * 0.5f;
- f1_p() = (f1_p() + f1_m()) * 0.5f;
- f2_p() = (f2_p() + f2_m()) * 0.5f;
- f3_p() = (f3_p() + f3_m()) * 0.5f;
- f0_m() = Vertex( zero );
- f1_m() = Vertex( zero );
- f2_m() = Vertex( zero );
- f3_m() = Vertex( zero );
- }
-
- static __forceinline void computeInnerVertices(const Vertex matrix[4][4], const Vertex f_m[2][2], const float uu, const float vv,
- Vertex_t& matrix_11, Vertex_t& matrix_12, Vertex_t& matrix_22, Vertex_t& matrix_21)
- {
- if (unlikely(uu == 0.0f || uu == 1.0f || vv == 0.0f || vv == 1.0f))
- {
- matrix_11 = matrix[1][1];
- matrix_12 = matrix[1][2];
- matrix_22 = matrix[2][2];
- matrix_21 = matrix[2][1];
- }
- else
- {
- const Vertex_t f0_p = matrix[1][1];
- const Vertex_t f1_p = matrix[1][2];
- const Vertex_t f2_p = matrix[2][2];
- const Vertex_t f3_p = matrix[2][1];
-
- const Vertex_t f0_m = f_m[0][0];
- const Vertex_t f1_m = f_m[0][1];
- const Vertex_t f2_m = f_m[1][1];
- const Vertex_t f3_m = f_m[1][0];
-
- matrix_11 = ( uu * f0_p + vv * f0_m)*rcp(uu+vv);
- matrix_12 = ((1.0f-uu) * f1_m + vv * f1_p)*rcp(1.0f-uu+vv);
- matrix_22 = ((1.0f-uu) * f2_p + (1.0f-vv) * f2_m)*rcp(2.0f-uu-vv);
- matrix_21 = ( uu * f3_m + (1.0f-vv) * f3_p)*rcp(1.0f+uu-vv);
- }
- }
-
- template<typename vfloat>
- static __forceinline void computeInnerVertices(const Vertex v[4][4], const Vertex f[2][2],
- size_t i, const vfloat& uu, const vfloat& vv, vfloat& matrix_11, vfloat& matrix_12, vfloat& matrix_22, vfloat& matrix_21)
- {
- const auto m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);
-
- const vfloat f0_p = v[1][1][i];
- const vfloat f1_p = v[1][2][i];
- const vfloat f2_p = v[2][2][i];
- const vfloat f3_p = v[2][1][i];
-
- const vfloat f0_m = f[0][0][i];
- const vfloat f1_m = f[0][1][i];
- const vfloat f2_m = f[1][1][i];
- const vfloat f3_m = f[1][0][i];
-
- const vfloat one_minus_uu = vfloat(1.0f) - uu;
- const vfloat one_minus_vv = vfloat(1.0f) - vv;
-
- const vfloat f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);
- const vfloat f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);
- const vfloat f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);
- const vfloat f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);
-
- matrix_11 = select(m_border,f0_p,f0_i);
- matrix_12 = select(m_border,f1_p,f1_i);
- matrix_22 = select(m_border,f2_p,f2_i);
- matrix_21 = select(m_border,f3_p,f3_i);
- }
-
- static __forceinline Vertex eval(const Vertex matrix[4][4], const Vertex f[2][2], const float& uu, const float& vv)
- {
- Vertex_t v_11, v_12, v_22, v_21;
- computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
-
- const Vec4<float> Bu = BezierBasis::eval(uu);
- const Vec4<float> Bv = BezierBasis::eval(vv);
-
- return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
- madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
- madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
- Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
- }
-
- static __forceinline Vertex eval_du(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
- {
- Vertex_t v_11, v_12, v_22, v_21;
- computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
-
- const Vec4<float> Bu = BezierBasis::derivative(uu);
- const Vec4<float> Bv = BezierBasis::eval(vv);
-
- return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
- madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
- madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
- Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
- }
-
- static __forceinline Vertex eval_dv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
- {
- Vertex_t v_11, v_12, v_22, v_21;
- computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
-
- const Vec4<float> Bu = BezierBasis::eval(uu);
- const Vec4<float> Bv = BezierBasis::derivative(vv);
-
- return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
- madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
- madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
- Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
- }
-
- static __forceinline Vertex eval_dudu(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
- {
- Vertex_t v_11, v_12, v_22, v_21;
- computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
-
- const Vec4<float> Bu = BezierBasis::derivative2(uu);
- const Vec4<float> Bv = BezierBasis::eval(vv);
-
- return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
- madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
- madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
- Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
- }
-
- static __forceinline Vertex eval_dvdv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
- {
- Vertex_t v_11, v_12, v_22, v_21;
- computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
-
- const Vec4<float> Bu = BezierBasis::eval(uu);
- const Vec4<float> Bv = BezierBasis::derivative2(vv);
-
- return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
- madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
- madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
- Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
- }
-
- static __forceinline Vertex eval_dudv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
- {
- Vertex_t v_11, v_12, v_22, v_21;
- computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
-
- const Vec4<float> Bu = BezierBasis::derivative(uu);
- const Vec4<float> Bv = BezierBasis::derivative(vv);
-
- return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
- madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
- madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
- Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
- }
-
- __forceinline Vertex eval(const float uu, const float vv) const {
- return eval(v,f,uu,vv);
- }
-
- __forceinline Vertex eval_du( const float uu, const float vv) const {
- return eval_du(v,f,uu,vv);
- }
-
- __forceinline Vertex eval_dv( const float uu, const float vv) const {
- return eval_dv(v,f,uu,vv);
- }
-
- __forceinline Vertex eval_dudu( const float uu, const float vv) const {
- return eval_dudu(v,f,uu,vv);
- }
-
- __forceinline Vertex eval_dvdv( const float uu, const float vv) const {
- return eval_dvdv(v,f,uu,vv);
- }
-
- __forceinline Vertex eval_dudv( const float uu, const float vv) const {
- return eval_dudv(v,f,uu,vv);
- }
-
- static __forceinline Vertex normal(const Vertex matrix[4][4], const Vertex f_m[2][2], const float uu, const float vv) // FIXME: why not using basis functions
- {
- /* interpolate inner vertices */
- Vertex_t matrix_11, matrix_12, matrix_22, matrix_21;
- computeInnerVertices(matrix,f_m,uu,vv,matrix_11, matrix_12, matrix_22, matrix_21);
-
- /* tangentU */
- const Vertex_t col0 = deCasteljau(vv, (Vertex_t)matrix[0][0], (Vertex_t)matrix[1][0], (Vertex_t)matrix[2][0], (Vertex_t)matrix[3][0]);
- const Vertex_t col1 = deCasteljau(vv, (Vertex_t)matrix[0][1], (Vertex_t)matrix_11 , (Vertex_t)matrix_21 , (Vertex_t)matrix[3][1]);
- const Vertex_t col2 = deCasteljau(vv, (Vertex_t)matrix[0][2], (Vertex_t)matrix_12 , (Vertex_t)matrix_22 , (Vertex_t)matrix[3][2]);
- const Vertex_t col3 = deCasteljau(vv, (Vertex_t)matrix[0][3], (Vertex_t)matrix[1][3], (Vertex_t)matrix[2][3], (Vertex_t)matrix[3][3]);
-
- const Vertex_t tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);
-
- /* tangentV */
- const Vertex_t row0 = deCasteljau(uu, (Vertex_t)matrix[0][0], (Vertex_t)matrix[0][1], (Vertex_t)matrix[0][2], (Vertex_t)matrix[0][3]);
- const Vertex_t row1 = deCasteljau(uu, (Vertex_t)matrix[1][0], (Vertex_t)matrix_11 , (Vertex_t)matrix_12 , (Vertex_t)matrix[1][3]);
- const Vertex_t row2 = deCasteljau(uu, (Vertex_t)matrix[2][0], (Vertex_t)matrix_21 , (Vertex_t)matrix_22 , (Vertex_t)matrix[2][3]);
- const Vertex_t row3 = deCasteljau(uu, (Vertex_t)matrix[3][0], (Vertex_t)matrix[3][1], (Vertex_t)matrix[3][2], (Vertex_t)matrix[3][3]);
-
- const Vertex_t tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);
-
- /* normal = tangentU x tangentV */
- const Vertex_t n = cross(tangentU,tangentV);
-
- return n;
- }
-
- __forceinline Vertex normal( const float uu, const float vv) const {
- return normal(v,f,uu,vv);
- }
-
- __forceinline void eval(const float u, const float v,
- Vertex* P, Vertex* dPdu, Vertex* dPdv,
- Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
- const float dscale = 1.0f) const
- {
- if (P) {
- *P = eval(u,v);
- }
- if (dPdu) {
- assert(dPdu); *dPdu = eval_du(u,v)*dscale;
- assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
- }
- if (ddPdudu) {
- assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
- assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
- assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
- }
- }
-
- template<class vfloat>
- static __forceinline vfloat eval(const Vertex v[4][4], const Vertex f[2][2],
- const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n,
- vfloat& matrix_11, vfloat& matrix_12, vfloat& matrix_22, vfloat& matrix_21)
- {
- const vfloat curve0_x = madd(v_n[0],vfloat(v[0][0][i]),madd(v_n[1],vfloat(v[1][0][i]),madd(v_n[2],vfloat(v[2][0][i]),v_n[3] * vfloat(v[3][0][i]))));
- const vfloat curve1_x = madd(v_n[0],vfloat(v[0][1][i]),madd(v_n[1],vfloat(matrix_11 ),madd(v_n[2],vfloat(matrix_21 ),v_n[3] * vfloat(v[3][1][i]))));
- const vfloat curve2_x = madd(v_n[0],vfloat(v[0][2][i]),madd(v_n[1],vfloat(matrix_12 ),madd(v_n[2],vfloat(matrix_22 ),v_n[3] * vfloat(v[3][2][i]))));
- const vfloat curve3_x = madd(v_n[0],vfloat(v[0][3][i]),madd(v_n[1],vfloat(v[1][3][i]),madd(v_n[2],vfloat(v[2][3][i]),v_n[3] * vfloat(v[3][3][i]))));
- return madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));
- }
-
- template<typename vbool, typename vfloat>
- static __forceinline void eval(const Vertex v[4][4], const Vertex f[2][2],
- const vbool& valid, const vfloat& uu, const vfloat& vv,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
- const float dscale, const size_t dstride, const size_t N)
- {
- if (P) {
- const Vec4<vfloat> u_n = BezierBasis::eval(uu);
- const Vec4<vfloat> v_n = BezierBasis::eval(vv);
- for (size_t i=0; i<N; i++) {
- vfloat matrix_11, matrix_12, matrix_22, matrix_21;
- computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
- vfloat::store(valid,P+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21));
- }
- }
- if (dPdu)
- {
- {
- assert(dPdu);
- const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
- const Vec4<vfloat> v_n = BezierBasis::eval(vv);
- for (size_t i=0; i<N; i++) {
- vfloat matrix_11, matrix_12, matrix_22, matrix_21;
- computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
- vfloat::store(valid,dPdu+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*dscale);
- }
- }
- {
- assert(dPdv);
- const Vec4<vfloat> u_n = BezierBasis::eval(uu);
- const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
- for (size_t i=0; i<N; i++) {
- vfloat matrix_11, matrix_12, matrix_22, matrix_21;
- computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
- vfloat::store(valid,dPdv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*dscale);
- }
- }
- }
- if (ddPdudu)
- {
- {
- assert(ddPdudu);
- const Vec4<vfloat> u_n = BezierBasis::derivative2(uu);
- const Vec4<vfloat> v_n = BezierBasis::eval(vv);
- for (size_t i=0; i<N; i++) {
- vfloat matrix_11, matrix_12, matrix_22, matrix_21;
- computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
- vfloat::store(valid,ddPdudu+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));
- }
- }
- {
- assert(ddPdvdv);
- const Vec4<vfloat> u_n = BezierBasis::eval(uu);
- const Vec4<vfloat> v_n = BezierBasis::derivative2(vv);
- for (size_t i=0; i<N; i++) {
- vfloat matrix_11, matrix_12, matrix_22, matrix_21;
- computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
- vfloat::store(valid,ddPdvdv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));
- }
- }
- {
- assert(ddPdudv);
- const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
- const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
- for (size_t i=0; i<N; i++) {
- vfloat matrix_11, matrix_12, matrix_22, matrix_21;
- computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
- vfloat::store(valid,ddPdudv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));
- }
- }
- }
- }
-
- template<typename vbool, typename vfloat>
- __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
- const float dscale, const size_t dstride, const size_t N) const {
- eval(v,f,valid,uu,vv,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- }
-
- template<class T>
- static __forceinline Vec3<T> eval_t(const Vertex matrix[4][4], const Vec3<T> f[2][2], const T& uu, const T& vv)
- {
- typedef typename T::Bool M;
- const M m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);
-
- const Vec3<T> f0_p = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);
- const Vec3<T> f1_p = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);
- const Vec3<T> f2_p = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);
- const Vec3<T> f3_p = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);
-
- const Vec3<T> f0_m = f[0][0];
- const Vec3<T> f1_m = f[0][1];
- const Vec3<T> f2_m = f[1][1];
- const Vec3<T> f3_m = f[1][0];
-
- const T one_minus_uu = T(1.0f) - uu;
- const T one_minus_vv = T(1.0f) - vv;
-
- const Vec3<T> f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);
- const Vec3<T> f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);
- const Vec3<T> f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);
- const Vec3<T> f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);
-
- const Vec3<T> F0( select(m_border,f0_p.x,f0_i.x), select(m_border,f0_p.y,f0_i.y), select(m_border,f0_p.z,f0_i.z) );
- const Vec3<T> F1( select(m_border,f1_p.x,f1_i.x), select(m_border,f1_p.y,f1_i.y), select(m_border,f1_p.z,f1_i.z) );
- const Vec3<T> F2( select(m_border,f2_p.x,f2_i.x), select(m_border,f2_p.y,f2_i.y), select(m_border,f2_p.z,f2_i.z) );
- const Vec3<T> F3( select(m_border,f3_p.x,f3_i.x), select(m_border,f3_p.y,f3_i.y), select(m_border,f3_p.z,f3_i.z) );
-
- const T B0_u = one_minus_uu * one_minus_uu * one_minus_uu;
- const T B0_v = one_minus_vv * one_minus_vv * one_minus_vv;
- const T B1_u = 3.0f * (one_minus_uu * uu * one_minus_uu);
- const T B1_v = 3.0f * (one_minus_vv * vv * one_minus_vv);
- const T B2_u = 3.0f * (uu * one_minus_uu * uu);
- const T B2_v = 3.0f * (vv * one_minus_vv * vv);
- const T B3_u = uu * uu * uu;
- const T B3_v = vv * vv * vv;
-
- const T x = madd(B0_v,madd(B0_u,matrix[0][0].x,madd(B1_u,matrix[0][1].x,madd(B2_u,matrix[0][2].x,B3_u * matrix[0][3].x))),
- madd(B1_v,madd(B0_u,matrix[1][0].x,madd(B1_u,F0.x ,madd(B2_u,F1.x ,B3_u * matrix[1][3].x))),
- madd(B2_v,madd(B0_u,matrix[2][0].x,madd(B1_u,F3.x ,madd(B2_u,F2.x ,B3_u * matrix[2][3].x))),
- B3_v*madd(B0_u,matrix[3][0].x,madd(B1_u,matrix[3][1].x,madd(B2_u,matrix[3][2].x,B3_u * matrix[3][3].x))))));
-
- const T y = madd(B0_v,madd(B0_u,matrix[0][0].y,madd(B1_u,matrix[0][1].y,madd(B2_u,matrix[0][2].y,B3_u * matrix[0][3].y))),
- madd(B1_v,madd(B0_u,matrix[1][0].y,madd(B1_u,F0.y ,madd(B2_u,F1.y ,B3_u * matrix[1][3].y))),
- madd(B2_v,madd(B0_u,matrix[2][0].y,madd(B1_u,F3.y ,madd(B2_u,F2.y ,B3_u * matrix[2][3].y))),
- B3_v*madd(B0_u,matrix[3][0].y,madd(B1_u,matrix[3][1].y,madd(B2_u,matrix[3][2].y,B3_u * matrix[3][3].y))))));
-
- const T z = madd(B0_v,madd(B0_u,matrix[0][0].z,madd(B1_u,matrix[0][1].z,madd(B2_u,matrix[0][2].z,B3_u * matrix[0][3].z))),
- madd(B1_v,madd(B0_u,matrix[1][0].z,madd(B1_u,F0.z ,madd(B2_u,F1.z ,B3_u * matrix[1][3].z))),
- madd(B2_v,madd(B0_u,matrix[2][0].z,madd(B1_u,F3.z ,madd(B2_u,F2.z ,B3_u * matrix[2][3].z))),
- B3_v*madd(B0_u,matrix[3][0].z,madd(B1_u,matrix[3][1].z,madd(B2_u,matrix[3][2].z,B3_u * matrix[3][3].z))))));
-
- return Vec3<T>(x,y,z);
- }
-
- template<class T>
- __forceinline Vec3<T> eval(const T& uu, const T& vv) const
- {
- Vec3<T> ff[2][2];
- ff[0][0] = Vec3<T>(f[0][0]);
- ff[0][1] = Vec3<T>(f[0][1]);
- ff[1][1] = Vec3<T>(f[1][1]);
- ff[1][0] = Vec3<T>(f[1][0]);
- return eval_t(v,ff,uu,vv);
- }
-
- template<class T>
- static __forceinline Vec3<T> normal_t(const Vertex matrix[4][4], const Vec3<T> f[2][2], const T& uu, const T& vv)
- {
- typedef typename T::Bool M;
-
- const Vec3<T> f0_p = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);
- const Vec3<T> f1_p = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);
- const Vec3<T> f2_p = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);
- const Vec3<T> f3_p = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);
-
- const Vec3<T> f0_m = f[0][0];
- const Vec3<T> f1_m = f[0][1];
- const Vec3<T> f2_m = f[1][1];
- const Vec3<T> f3_m = f[1][0];
-
- const T one_minus_uu = T(1.0f) - uu;
- const T one_minus_vv = T(1.0f) - vv;
-
- const Vec3<T> f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);
- const Vec3<T> f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);
- const Vec3<T> f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);
- const Vec3<T> f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);
-
-#if 1
- const M m_corner0 = (uu == 0.0f) & (vv == 0.0f);
- const M m_corner1 = (uu == 1.0f) & (vv == 0.0f);
- const M m_corner2 = (uu == 1.0f) & (vv == 1.0f);
- const M m_corner3 = (uu == 0.0f) & (vv == 1.0f);
- const Vec3<T> matrix_11( select(m_corner0,f0_p.x,f0_i.x), select(m_corner0,f0_p.y,f0_i.y), select(m_corner0,f0_p.z,f0_i.z) );
- const Vec3<T> matrix_12( select(m_corner1,f1_p.x,f1_i.x), select(m_corner1,f1_p.y,f1_i.y), select(m_corner1,f1_p.z,f1_i.z) );
- const Vec3<T> matrix_22( select(m_corner2,f2_p.x,f2_i.x), select(m_corner2,f2_p.y,f2_i.y), select(m_corner2,f2_p.z,f2_i.z) );
- const Vec3<T> matrix_21( select(m_corner3,f3_p.x,f3_i.x), select(m_corner3,f3_p.y,f3_i.y), select(m_corner3,f3_p.z,f3_i.z) );
-#else
- const M m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);
- const Vec3<T> matrix_11( select(m_border,f0_p.x,f0_i.x), select(m_border,f0_p.y,f0_i.y), select(m_border,f0_p.z,f0_i.z) );
- const Vec3<T> matrix_12( select(m_border,f1_p.x,f1_i.x), select(m_border,f1_p.y,f1_i.y), select(m_border,f1_p.z,f1_i.z) );
- const Vec3<T> matrix_22( select(m_border,f2_p.x,f2_i.x), select(m_border,f2_p.y,f2_i.y), select(m_border,f2_p.z,f2_i.z) );
- const Vec3<T> matrix_21( select(m_border,f3_p.x,f3_i.x), select(m_border,f3_p.y,f3_i.y), select(m_border,f3_p.z,f3_i.z) );
-#endif
-
- const Vec3<T> matrix_00 = Vec3<T>(matrix[0][0].x,matrix[0][0].y,matrix[0][0].z);
- const Vec3<T> matrix_10 = Vec3<T>(matrix[1][0].x,matrix[1][0].y,matrix[1][0].z);
- const Vec3<T> matrix_20 = Vec3<T>(matrix[2][0].x,matrix[2][0].y,matrix[2][0].z);
- const Vec3<T> matrix_30 = Vec3<T>(matrix[3][0].x,matrix[3][0].y,matrix[3][0].z);
-
- const Vec3<T> matrix_01 = Vec3<T>(matrix[0][1].x,matrix[0][1].y,matrix[0][1].z);
- const Vec3<T> matrix_02 = Vec3<T>(matrix[0][2].x,matrix[0][2].y,matrix[0][2].z);
- const Vec3<T> matrix_03 = Vec3<T>(matrix[0][3].x,matrix[0][3].y,matrix[0][3].z);
-
- const Vec3<T> matrix_31 = Vec3<T>(matrix[3][1].x,matrix[3][1].y,matrix[3][1].z);
- const Vec3<T> matrix_32 = Vec3<T>(matrix[3][2].x,matrix[3][2].y,matrix[3][2].z);
- const Vec3<T> matrix_33 = Vec3<T>(matrix[3][3].x,matrix[3][3].y,matrix[3][3].z);
-
- const Vec3<T> matrix_13 = Vec3<T>(matrix[1][3].x,matrix[1][3].y,matrix[1][3].z);
- const Vec3<T> matrix_23 = Vec3<T>(matrix[2][3].x,matrix[2][3].y,matrix[2][3].z);
-
- /* tangentU */
- const Vec3<T> col0 = deCasteljau(vv, matrix_00, matrix_10, matrix_20, matrix_30);
- const Vec3<T> col1 = deCasteljau(vv, matrix_01, matrix_11, matrix_21, matrix_31);
- const Vec3<T> col2 = deCasteljau(vv, matrix_02, matrix_12, matrix_22, matrix_32);
- const Vec3<T> col3 = deCasteljau(vv, matrix_03, matrix_13, matrix_23, matrix_33);
-
- const Vec3<T> tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);
-
- /* tangentV */
- const Vec3<T> row0 = deCasteljau(uu, matrix_00, matrix_01, matrix_02, matrix_03);
- const Vec3<T> row1 = deCasteljau(uu, matrix_10, matrix_11, matrix_12, matrix_13);
- const Vec3<T> row2 = deCasteljau(uu, matrix_20, matrix_21, matrix_22, matrix_23);
- const Vec3<T> row3 = deCasteljau(uu, matrix_30, matrix_31, matrix_32, matrix_33);
-
- const Vec3<T> tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);
-
- /* normal = tangentU x tangentV */
- const Vec3<T> n = cross(tangentU,tangentV);
- return n;
- }
-
- template<class T>
- __forceinline Vec3<T> normal(const T& uu, const T& vv) const
- {
- Vec3<T> ff[2][2];
- ff[0][0] = Vec3<T>(f[0][0]);
- ff[0][1] = Vec3<T>(f[0][1]);
- ff[1][1] = Vec3<T>(f[1][1]);
- ff[1][0] = Vec3<T>(f[1][0]);
- return normal_t(v,ff,uu,vv);
- }
-
- __forceinline BBox<Vertex> bounds() const
- {
- const Vertex *const cv = &v[0][0];
- BBox<Vertex> bounds (cv[0]);
- for (size_t i=1; i<16; i++)
- bounds.extend( cv[i] );
- bounds.extend(f[0][0]);
- bounds.extend(f[1][0]);
- bounds.extend(f[1][1]);
- bounds.extend(f[1][1]);
- return bounds;
- }
-
- friend embree_ostream operator<<(embree_ostream o, const GregoryPatchT& p)
- {
- for (size_t y=0; y<4; y++)
- for (size_t x=0; x<4; x++)
- o << "v[" << y << "][" << x << "] " << p.v[y][x] << embree_endl;
-
- for (size_t y=0; y<2; y++)
- for (size_t x=0; x<2; x++)
- o << "f[" << y << "][" << x << "] " << p.f[y][x] << embree_endl;
- return o;
- }
- };
-
- typedef GregoryPatchT<Vec3fa,Vec3fa_t> GregoryPatch3fa;
-
- template<typename Vertex, typename Vertex_t>
- __forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT (const HalfEdge* edge, const char* vertices, size_t stride)
- {
- CatmullClarkPatchT<Vertex,Vertex_t> patch(edge,vertices,stride);
- GregoryPatchT<Vertex,Vertex_t> gpatch(patch);
- gpatch.convert_to_bezier();
- for (size_t y=0; y<4; y++)
- for (size_t x=0; x<4; x++)
- matrix[y][x] = (Vertex_t)gpatch.v[y][x];
- }
-
- template<typename Vertex, typename Vertex_t>
- __forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch)
- {
- GregoryPatchT<Vertex,Vertex_t> gpatch(patch);
- gpatch.convert_to_bezier();
- for (size_t y=0; y<4; y++)
- for (size_t x=0; x<4; x++)
- matrix[y][x] = (Vertex_t)gpatch.v[y][x];
- }
-
- template<typename Vertex, typename Vertex_t>
- __forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch,
- const BezierCurveT<Vertex>* border0,
- const BezierCurveT<Vertex>* border1,
- const BezierCurveT<Vertex>* border2,
- const BezierCurveT<Vertex>* border3)
- {
- GregoryPatchT<Vertex,Vertex_t> gpatch(patch,border0,border1,border2,border3);
- gpatch.convert_to_bezier();
- for (size_t y=0; y<4; y++)
- for (size_t x=0; x<4; x++)
- matrix[y][x] = (Vertex_t)gpatch.v[y][x];
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/gregory_patch_dense.h b/thirdparty/embree-aarch64/kernels/subdiv/gregory_patch_dense.h
deleted file mode 100644
index 85effd02cf..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/gregory_patch_dense.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "gregory_patch.h"
-
-namespace embree
-{
- class __aligned(64) DenseGregoryPatch3fa
- {
- typedef Vec3fa Vec3fa_4x4[4][4];
- public:
-
- __forceinline DenseGregoryPatch3fa (const GregoryPatch3fa& patch)
- {
- for (size_t y=0; y<4; y++)
- for (size_t x=0; x<4; x++)
- matrix[y][x] = Vec3ff(patch.v[y][x], 0.0f);
-
- matrix[0][0].w = patch.f[0][0].x;
- matrix[0][1].w = patch.f[0][0].y;
- matrix[0][2].w = patch.f[0][0].z;
- matrix[0][3].w = 0.0f;
-
- matrix[1][0].w = patch.f[0][1].x;
- matrix[1][1].w = patch.f[0][1].y;
- matrix[1][2].w = patch.f[0][1].z;
- matrix[1][3].w = 0.0f;
-
- matrix[2][0].w = patch.f[1][1].x;
- matrix[2][1].w = patch.f[1][1].y;
- matrix[2][2].w = patch.f[1][1].z;
- matrix[2][3].w = 0.0f;
-
- matrix[3][0].w = patch.f[1][0].x;
- matrix[3][1].w = patch.f[1][0].y;
- matrix[3][2].w = patch.f[1][0].z;
- matrix[3][3].w = 0.0f;
- }
-
- __forceinline void extract_f_m(Vec3fa f_m[2][2]) const
- {
- f_m[0][0] = Vec3fa( matrix[0][0].w, matrix[0][1].w, matrix[0][2].w );
- f_m[0][1] = Vec3fa( matrix[1][0].w, matrix[1][1].w, matrix[1][2].w );
- f_m[1][1] = Vec3fa( matrix[2][0].w, matrix[2][1].w, matrix[2][2].w );
- f_m[1][0] = Vec3fa( matrix[3][0].w, matrix[3][1].w, matrix[3][2].w );
- }
-
- __forceinline Vec3fa eval(const float uu, const float vv) const
- {
- __aligned(64) Vec3fa f_m[2][2]; extract_f_m(f_m);
- return GregoryPatch3fa::eval(*(Vec3fa_4x4*)&matrix,f_m,uu,vv);
- }
-
- __forceinline Vec3fa normal(const float uu, const float vv) const
- {
- __aligned(64) Vec3fa f_m[2][2]; extract_f_m(f_m);
- return GregoryPatch3fa::normal(*(Vec3fa_4x4*)&matrix,f_m,uu,vv);
- }
-
- template<class T>
- __forceinline Vec3<T> eval(const T &uu, const T &vv) const
- {
- Vec3<T> f_m[2][2];
- f_m[0][0] = Vec3<T>( matrix[0][0].w, matrix[0][1].w, matrix[0][2].w );
- f_m[0][1] = Vec3<T>( matrix[1][0].w, matrix[1][1].w, matrix[1][2].w );
- f_m[1][1] = Vec3<T>( matrix[2][0].w, matrix[2][1].w, matrix[2][2].w );
- f_m[1][0] = Vec3<T>( matrix[3][0].w, matrix[3][1].w, matrix[3][2].w );
- return GregoryPatch3fa::eval_t(*(Vec3fa_4x4*)&matrix,f_m,uu,vv);
- }
-
- template<class T>
- __forceinline Vec3<T> normal(const T &uu, const T &vv) const
- {
- Vec3<T> f_m[2][2];
- f_m[0][0] = Vec3<T>( matrix[0][0].w, matrix[0][1].w, matrix[0][2].w );
- f_m[0][1] = Vec3<T>( matrix[1][0].w, matrix[1][1].w, matrix[1][2].w );
- f_m[1][1] = Vec3<T>( matrix[2][0].w, matrix[2][1].w, matrix[2][2].w );
- f_m[1][0] = Vec3<T>( matrix[3][0].w, matrix[3][1].w, matrix[3][2].w );
- return GregoryPatch3fa::normal_t(*(Vec3fa_4x4*)&matrix,f_m,uu,vv);
- }
-
- __forceinline void eval(const float u, const float v,
- Vec3fa* P, Vec3fa* dPdu, Vec3fa* dPdv, Vec3fa* ddPdudu, Vec3fa* ddPdvdv, Vec3fa* ddPdudv,
- const float dscale = 1.0f) const
- {
- __aligned(64) Vec3fa f_m[2][2]; extract_f_m(f_m);
- if (P) {
- *P = GregoryPatch3fa::eval(*(Vec3fa_4x4*)&matrix,f_m,u,v);
- }
- if (dPdu) {
- assert(dPdu); *dPdu = GregoryPatch3fa::eval_du(*(Vec3fa_4x4*)&matrix,f_m,u,v)*dscale;
- assert(dPdv); *dPdv = GregoryPatch3fa::eval_dv(*(Vec3fa_4x4*)&matrix,f_m,u,v)*dscale;
- }
- if (ddPdudu) {
- assert(ddPdudu); *ddPdudu = GregoryPatch3fa::eval_dudu(*(Vec3fa_4x4*)&matrix,f_m,u,v)*sqr(dscale);
- assert(ddPdvdv); *ddPdvdv = GregoryPatch3fa::eval_dvdv(*(Vec3fa_4x4*)&matrix,f_m,u,v)*sqr(dscale);
- assert(ddPdudv); *ddPdudv = GregoryPatch3fa::eval_dudv(*(Vec3fa_4x4*)&matrix,f_m,u,v)*sqr(dscale);
- }
- }
-
- template<typename vbool, typename vfloat>
- __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv, float* P, float* dPdu, float* dPdv, const float dscale, const size_t dstride, const size_t N) const
- {
- __aligned(64) Vec3fa f_m[2][2]; extract_f_m(f_m);
- GregoryPatch3fa::eval(matrix,f_m,valid,uu,vv,P,dPdu,dPdv,dscale,dstride,N);
- }
-
- private:
- Vec3ff matrix[4][4]; // f_p/m points are stored in 4th component
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/gridrange.h b/thirdparty/embree-aarch64/kernels/subdiv/gridrange.h
deleted file mode 100644
index 4fd741c879..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/gridrange.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-
-namespace embree
-{
- struct __aligned(16) GridRange
- {
- unsigned int u_start;
- unsigned int u_end;
- unsigned int v_start;
- unsigned int v_end;
-
- __forceinline GridRange() {}
-
- __forceinline GridRange(unsigned int u_start, unsigned int u_end, unsigned int v_start, unsigned int v_end)
- : u_start(u_start), u_end(u_end), v_start(v_start), v_end(v_end) {}
-
- __forceinline unsigned int width() const {
- return u_end-u_start+1;
- }
-
- __forceinline unsigned int height() const {
- return v_end-v_start+1;
- }
-
- __forceinline bool hasLeafSize() const
- {
- const unsigned int u_size = u_end-u_start+1;
- const unsigned int v_size = v_end-v_start+1;
- assert(u_size >= 1);
- assert(v_size >= 1);
- return u_size <= 3 && v_size <= 3;
- }
-
- static __forceinline unsigned int split(unsigned int start,unsigned int end)
- {
- const unsigned int center = (start+end)/2;
- assert (center > start);
- assert (center < end);
- return center;
- }
-
- __forceinline void split(GridRange& r0, GridRange& r1) const
- {
- assert( hasLeafSize() == false );
- const unsigned int u_size = u_end-u_start+1;
- const unsigned int v_size = v_end-v_start+1;
- r0 = *this;
- r1 = *this;
-
- if (u_size >= v_size)
- {
- const unsigned int u_mid = split(u_start,u_end);
- r0.u_end = u_mid;
- r1.u_start = u_mid;
- }
- else
- {
- const unsigned int v_mid = split(v_start,v_end);
- r0.v_end = v_mid;
- r1.v_start = v_mid;
- }
- }
-
- __forceinline unsigned int splitIntoSubRanges(GridRange r[4]) const
- {
- assert( !hasLeafSize() );
- unsigned int children = 0;
- GridRange first,second;
- split(first,second);
-
- if (first.hasLeafSize()) {
- r[0] = first;
- children++;
- }
- else {
- first.split(r[0],r[1]);
- children += 2;
- }
-
- if (second.hasLeafSize()) {
- r[children] = second;
- children++;
- }
- else {
- second.split(r[children+0],r[children+1]);
- children += 2;
- }
- return children;
- }
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/half_edge.h b/thirdparty/embree-aarch64/kernels/subdiv/half_edge.h
deleted file mode 100644
index fb350ca71f..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/half_edge.h
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "catmullclark_coefficients.h"
-
-namespace embree
-{
- class __aligned(32) HalfEdge
- {
- friend class SubdivMesh;
- public:
-
- enum PatchType : char {
- BILINEAR_PATCH = 0, //!< a bilinear patch
- REGULAR_QUAD_PATCH = 1, //!< a regular quad patch can be represented as a B-Spline
- IRREGULAR_QUAD_PATCH = 2, //!< an irregular quad patch can be represented as a Gregory patch
- COMPLEX_PATCH = 3 //!< these patches need subdivision and cannot be processed by the above fast code paths
- };
-
- enum VertexType : char {
- REGULAR_VERTEX = 0, //!< regular vertex
- NON_MANIFOLD_EDGE_VERTEX = 1, //!< vertex of a non-manifold edge
- };
-
- __forceinline friend PatchType max( const PatchType& ty0, const PatchType& ty1) {
- return (PatchType) max((int)ty0,(int)ty1);
- }
-
- struct Edge
- {
- /*! edge constructor */
- __forceinline Edge(const uint32_t v0, const uint32_t v1)
- : v0(v0), v1(v1) {}
-
- /*! create an 64 bit identifier that is unique for the not oriented edge */
- __forceinline operator uint64_t() const
- {
- uint32_t p0 = v0, p1 = v1;
- if (p0<p1) std::swap(p0,p1);
- return (((uint64_t)p0) << 32) | (uint64_t)p1;
- }
-
- public:
- uint32_t v0,v1; //!< start and end vertex of the edge
- };
-
- HalfEdge ()
- : vtx_index(-1), next_half_edge_ofs(0), prev_half_edge_ofs(0), opposite_half_edge_ofs(0), edge_crease_weight(0),
- vertex_crease_weight(0), edge_level(0), patch_type(COMPLEX_PATCH), vertex_type(REGULAR_VERTEX)
- {
- static_assert(sizeof(HalfEdge) == 32, "invalid half edge size");
- }
-
- __forceinline bool hasOpposite() const { return opposite_half_edge_ofs != 0; }
- __forceinline void setOpposite(HalfEdge* opposite) { opposite_half_edge_ofs = int(opposite-this); }
-
- __forceinline HalfEdge* next() { assert( next_half_edge_ofs != 0 ); return &this[next_half_edge_ofs]; }
- __forceinline const HalfEdge* next() const { assert( next_half_edge_ofs != 0 ); return &this[next_half_edge_ofs]; }
-
- __forceinline HalfEdge* prev() { assert( prev_half_edge_ofs != 0 ); return &this[prev_half_edge_ofs]; }
- __forceinline const HalfEdge* prev() const { assert( prev_half_edge_ofs != 0 ); return &this[prev_half_edge_ofs]; }
-
- __forceinline HalfEdge* opposite() { assert( opposite_half_edge_ofs != 0 ); return &this[opposite_half_edge_ofs]; }
- __forceinline const HalfEdge* opposite() const { assert( opposite_half_edge_ofs != 0 ); return &this[opposite_half_edge_ofs]; }
-
- __forceinline HalfEdge* rotate() { return opposite()->next(); }
- __forceinline const HalfEdge* rotate() const { return opposite()->next(); }
-
- __forceinline unsigned int getStartVertexIndex() const { return vtx_index; }
- __forceinline unsigned int getEndVertexIndex () const { return next()->vtx_index; }
- __forceinline Edge getEdge () const { return Edge(getStartVertexIndex(),getEndVertexIndex()); }
-
-
- /*! tests if the start vertex of the edge is regular */
- __forceinline PatchType vertexType() const
- {
- const HalfEdge* p = this;
- size_t face_valence = 0;
- bool hasBorder = false;
-
- do
- {
- /* we need subdivision to handle edge creases */
- if (p->hasOpposite() && p->edge_crease_weight > 0.0f)
- return COMPLEX_PATCH;
-
- face_valence++;
-
- /* test for quad */
- const HalfEdge* pp = p;
- pp = pp->next(); if (pp == p) return COMPLEX_PATCH;
- pp = pp->next(); if (pp == p) return COMPLEX_PATCH;
- pp = pp->next(); if (pp == p) return COMPLEX_PATCH;
- pp = pp->next(); if (pp != p) return COMPLEX_PATCH;
-
- /* continue with next face */
- p = p->prev();
- if (likely(p->hasOpposite()))
- p = p->opposite();
-
- /* if there is no opposite go the long way to the other side of the border */
- else
- {
- face_valence++;
- hasBorder = true;
- p = this;
- while (p->hasOpposite())
- p = p->rotate();
- }
- } while (p != this);
-
- /* calculate vertex type */
- if (face_valence == 2 && hasBorder) {
- if (vertex_crease_weight == 0.0f ) return REGULAR_QUAD_PATCH;
- else if (vertex_crease_weight == float(inf)) return REGULAR_QUAD_PATCH;
- else return COMPLEX_PATCH;
- }
- else if (vertex_crease_weight != 0.0f) return COMPLEX_PATCH;
- else if (face_valence == 3 && hasBorder) return REGULAR_QUAD_PATCH;
- else if (face_valence == 4 && !hasBorder) return REGULAR_QUAD_PATCH;
- else return IRREGULAR_QUAD_PATCH;
- }
-
- /*! tests if this edge is part of a bilinear patch */
- __forceinline bool bilinearVertex() const {
- return vertex_crease_weight == float(inf) && edge_crease_weight == float(inf);
- }
-
- /*! calculates the type of the patch */
- __forceinline PatchType patchType() const
- {
- const HalfEdge* p = this;
- PatchType ret = REGULAR_QUAD_PATCH;
- bool bilinear = true;
-
- ret = max(ret,p->vertexType());
- bilinear &= p->bilinearVertex();
- if ((p = p->next()) == this) return COMPLEX_PATCH;
-
- ret = max(ret,p->vertexType());
- bilinear &= p->bilinearVertex();
- if ((p = p->next()) == this) return COMPLEX_PATCH;
-
- ret = max(ret,p->vertexType());
- bilinear &= p->bilinearVertex();
- if ((p = p->next()) == this) return COMPLEX_PATCH;
-
- ret = max(ret,p->vertexType());
- bilinear &= p->bilinearVertex();
- if ((p = p->next()) != this) return COMPLEX_PATCH;
-
- if (bilinear) return BILINEAR_PATCH;
- return ret;
- }
-
- /*! tests if the face is a regular b-spline face */
- __forceinline bool isRegularFace() const {
- return patch_type == REGULAR_QUAD_PATCH;
- }
-
- /*! tests if the face can be diced (using bspline or gregory patch) */
- __forceinline bool isGregoryFace() const {
- return patch_type == IRREGULAR_QUAD_PATCH || patch_type == REGULAR_QUAD_PATCH;
- }
-
- /*! tests if the base vertex of this half edge is a corner vertex */
- __forceinline bool isCorner() const {
- return !hasOpposite() && !prev()->hasOpposite();
- }
-
- /*! tests if the vertex is attached to any border */
- __forceinline bool vertexHasBorder() const
- {
- const HalfEdge* p = this;
- do {
- if (!p->hasOpposite()) return true;
- p = p->rotate();
- } while (p != this);
- return false;
- }
-
- /*! tests if the face this half edge belongs to has some border */
- __forceinline bool faceHasBorder() const
- {
- const HalfEdge* p = this;
- do {
- if (p->vertexHasBorder()) return true;
- p = p->next();
- } while (p != this);
- return false;
- }
-
- /*! calculates conservative bounds of a catmull clark subdivision face */
- __forceinline BBox3fa bounds(const BufferView<Vec3fa>& vertices) const
- {
- BBox3fa bounds = this->get1RingBounds(vertices);
- for (const HalfEdge* p=this->next(); p!=this; p=p->next())
- bounds.extend(p->get1RingBounds(vertices));
- return bounds;
- }
-
- /*! tests if this is a valid patch */
- __forceinline bool valid(const BufferView<Vec3fa>& vertices) const
- {
- size_t N = 1;
- if (!this->validRing(vertices)) return false;
- for (const HalfEdge* p=this->next(); p!=this; p=p->next(), N++) {
- if (!p->validRing(vertices)) return false;
- }
- return N >= 3 && N <= MAX_PATCH_VALENCE;
- }
-
- /*! counts number of polygon edges */
- __forceinline unsigned int numEdges() const
- {
- unsigned int N = 1;
- for (const HalfEdge* p=this->next(); p!=this; p=p->next(), N++);
- return N;
- }
-
- /*! calculates face and edge valence */
- __forceinline void calculateFaceValenceAndEdgeValence(size_t& faceValence, size_t& edgeValence) const
- {
- faceValence = 0;
- edgeValence = 0;
-
- const HalfEdge* p = this;
- do
- {
- /* calculate bounds of current face */
- unsigned int numEdges = p->numEdges();
- assert(numEdges >= 3);
- edgeValence += numEdges-2;
-
- faceValence++;
- p = p->prev();
-
- /* continue with next face */
- if (likely(p->hasOpposite()))
- p = p->opposite();
-
- /* if there is no opposite go the long way to the other side of the border */
- else {
- faceValence++;
- edgeValence++;
- p = this;
- while (p->hasOpposite())
- p = p->opposite()->next();
- }
-
- } while (p != this);
- }
-
- /*! stream output */
- friend __forceinline std::ostream &operator<<(std::ostream &o, const HalfEdge &h)
- {
- return o << "{ " <<
- "vertex = " << h.vtx_index << ", " << //" -> " << h.next()->vtx_index << ", " <<
- "prev = " << h.prev_half_edge_ofs << ", " <<
- "next = " << h.next_half_edge_ofs << ", " <<
- "opposite = " << h.opposite_half_edge_ofs << ", " <<
- "edge_crease = " << h.edge_crease_weight << ", " <<
- "vertex_crease = " << h.vertex_crease_weight << ", " <<
- //"edge_level = " << h.edge_level <<
- " }";
- }
-
- private:
-
- /*! calculates the bounds of the face associated with the half-edge */
- __forceinline BBox3fa getFaceBounds(const BufferView<Vec3fa>& vertices) const
- {
- BBox3fa b = vertices[getStartVertexIndex()];
- for (const HalfEdge* p = next(); p!=this; p=p->next()) {
- b.extend(vertices[p->getStartVertexIndex()]);
- }
- return b;
- }
-
- /*! calculates the bounds of the 1-ring associated with the vertex of the half-edge */
- __forceinline BBox3fa get1RingBounds(const BufferView<Vec3fa>& vertices) const
- {
- BBox3fa bounds = empty;
- const HalfEdge* p = this;
- do
- {
- /* calculate bounds of current face */
- bounds.extend(p->getFaceBounds(vertices));
- p = p->prev();
-
- /* continue with next face */
- if (likely(p->hasOpposite()))
- p = p->opposite();
-
- /* if there is no opposite go the long way to the other side of the border */
- else {
- p = this;
- while (p->hasOpposite())
- p = p->opposite()->next();
- }
-
- } while (p != this);
-
- return bounds;
- }
-
- /*! tests if this is a valid face */
- __forceinline bool validFace(const BufferView<Vec3fa>& vertices, size_t& N) const
- {
- const Vec3fa v = vertices[getStartVertexIndex()];
- if (!isvalid(v)) return false;
- size_t n = 1;
- for (const HalfEdge* p = next(); p!=this; p=p->next(), n++) {
- const Vec3fa v = vertices[p->getStartVertexIndex()];
- if (!isvalid(v)) return false;
- }
- N += n-2;
- return n >= 3 && n <= MAX_PATCH_VALENCE;
- }
-
- /*! tests if this is a valid ring */
- __forceinline bool validRing(const BufferView<Vec3fa>& vertices) const
- {
- size_t faceValence = 0;
- size_t edgeValence = 0;
-
- const HalfEdge* p = this;
- do
- {
- /* calculate bounds of current face */
- if (!p->validFace(vertices,edgeValence))
- return false;
-
- faceValence++;
- p = p->prev();
-
- /* continue with next face */
- if (likely(p->hasOpposite()))
- p = p->opposite();
-
- /* if there is no opposite go the long way to the other side of the border */
- else {
- faceValence++;
- edgeValence++;
- p = this;
- while (p->hasOpposite())
- p = p->opposite()->next();
- }
-
- } while (p != this);
-
- return faceValence <= MAX_RING_FACE_VALENCE && edgeValence <= MAX_RING_EDGE_VALENCE;
- }
-
- private:
- unsigned int vtx_index; //!< index of edge start vertex
- int next_half_edge_ofs; //!< relative offset to next half edge of face
- int prev_half_edge_ofs; //!< relative offset to previous half edge of face
- int opposite_half_edge_ofs; //!< relative offset to opposite half edge
-
- public:
- float edge_crease_weight; //!< crease weight attached to edge
- float vertex_crease_weight; //!< crease weight attached to start vertex
- float edge_level; //!< subdivision factor for edge
- PatchType patch_type; //!< stores type of subdiv patch
- VertexType vertex_type; //!< stores type of the start vertex
- char align[2];
- };
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/hermite_curve.h b/thirdparty/embree-aarch64/kernels/subdiv/hermite_curve.h
deleted file mode 100644
index 9fab79cf0c..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/hermite_curve.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-#include "bezier_curve.h"
-
-namespace embree
-{
- template<typename Vertex>
- struct HermiteCurveT : BezierCurveT<Vertex>
- {
- __forceinline HermiteCurveT() {}
-
- __forceinline HermiteCurveT(const BezierCurveT<Vertex>& curve)
- : BezierCurveT<Vertex>(curve) {}
-
- __forceinline HermiteCurveT(const Vertex& v0, const Vertex& t0, const Vertex& v1, const Vertex& t1)
- : BezierCurveT<Vertex>(v0,madd(1.0f/3.0f,t0,v0),nmadd(1.0f/3.0f,t1,v1),v1) {}
-
- __forceinline HermiteCurveT<Vec3ff> xfm_pr(const LinearSpace3fa& space, const Vec3fa& p) const
- {
- const Vec3ff q0(xfmVector(space,this->v0-p), this->v0.w);
- const Vec3ff q1(xfmVector(space,this->v1-p), this->v1.w);
- const Vec3ff q2(xfmVector(space,this->v2-p), this->v2.w);
- const Vec3ff q3(xfmVector(space,this->v3-p), this->v3.w);
- return BezierCurveT<Vec3ff>(q0,q1,q2,q3);
- }
- };
-
- __forceinline HermiteCurveT<Vec3ff> enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const HermiteCurveT<Vec3ff>& curve) {
- return HermiteCurveT<Vec3ff>(enlargeRadiusToMinWidth(context,geom,ray_org,BezierCurveT<Vec3ff>(curve)));
- }
-
- typedef HermiteCurveT<Vec3fa> HermiteCurve3fa;
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/linear_bezier_patch.h b/thirdparty/embree-aarch64/kernels/subdiv/linear_bezier_patch.h
deleted file mode 100644
index f4a854af7f..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/linear_bezier_patch.h
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "bezier_curve.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename V>
- struct TensorLinearQuadraticBezierSurface
- {
- QuadraticBezierCurve<V> L;
- QuadraticBezierCurve<V> R;
-
- __forceinline TensorLinearQuadraticBezierSurface() {}
-
- __forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<V>& curve)
- : L(curve.L), R(curve.R) {}
-
- __forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {
- L = other.L; R = other.R; return *this;
- }
-
- __forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<V>& L, const QuadraticBezierCurve<V>& R)
- : L(L), R(R) {}
-
- __forceinline BBox<V> bounds() const {
- return merge(L.bounds(),R.bounds());
- }
- };
-
- template<>
- struct TensorLinearQuadraticBezierSurface<Vec2fa>
- {
- QuadraticBezierCurve<vfloat4> LR;
-
- __forceinline TensorLinearQuadraticBezierSurface() {}
-
- __forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<Vec2fa>& curve)
- : LR(curve.LR) {}
-
- __forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {
- LR = other.LR; return *this;
- }
-
- __forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<vfloat4>& LR)
- : LR(LR) {}
-
- __forceinline BBox<Vec2fa> bounds() const
- {
- const BBox<vfloat4> b = LR.bounds();
- const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));
- const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));
- return merge(bl,br);
- }
- };
-
- template<typename V>
- struct TensorLinearCubicBezierSurface
- {
- CubicBezierCurve<V> L;
- CubicBezierCurve<V> R;
-
- __forceinline TensorLinearCubicBezierSurface() {}
-
- __forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)
- : L(curve.L), R(curve.R) {}
-
- __forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {
- L = other.L; R = other.R; return *this;
- }
-
- __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<V>& L, const CubicBezierCurve<V>& R)
- : L(L), R(R) {}
-
- template<template<typename T> class SourceCurve>
- __forceinline static TensorLinearCubicBezierSurface fromCenterAndNormalCurve(const SourceCurve<Vec3ff>& center, const SourceCurve<Vec3fa>& normal)
- {
- SourceCurve<Vec3ff> vcurve = center;
- SourceCurve<Vec3fa> ncurve = normal;
-
- /* here we construct a patch which follows the curve l(t) =
- * p(t) +/- r(t)*normalize(cross(n(t),dp(t))) */
-
- const Vec3ff p0 = vcurve.eval(0.0f);
- const Vec3ff dp0 = vcurve.eval_du(0.0f);
- const Vec3ff ddp0 = vcurve.eval_dudu(0.0f);
-
- const Vec3fa n0 = ncurve.eval(0.0f);
- const Vec3fa dn0 = ncurve.eval_du(0.0f);
-
- const Vec3ff p1 = vcurve.eval(1.0f);
- const Vec3ff dp1 = vcurve.eval_du(1.0f);
- const Vec3ff ddp1 = vcurve.eval_dudu(1.0f);
-
- const Vec3fa n1 = ncurve.eval(1.0f);
- const Vec3fa dn1 = ncurve.eval_du(1.0f);
-
- const Vec3fa bt0 = cross(n0,dp0);
- const Vec3fa dbt0 = cross(dn0,dp0) + cross(n0,ddp0);
-
- const Vec3fa bt1 = cross(n1,dp1);
- const Vec3fa dbt1 = cross(dn1,dp1) + cross(n1,ddp1);
-
- const Vec3fa k0 = normalize(bt0);
- const Vec3fa dk0 = dnormalize(bt0,dbt0);
-
- const Vec3fa k1 = normalize(bt1);
- const Vec3fa dk1 = dnormalize(bt1,dbt1);
-
- const Vec3fa l0 = p0 - p0.w*k0;
- const Vec3fa dl0 = dp0 - (dp0.w*k0 + p0.w*dk0);
-
- const Vec3fa r0 = p0 + p0.w*k0;
- const Vec3fa dr0 = dp0 + (dp0.w*k0 + p0.w*dk0);
-
- const Vec3fa l1 = p1 - p1.w*k1;
- const Vec3fa dl1 = dp1 - (dp1.w*k1 + p1.w*dk1);
-
- const Vec3fa r1 = p1 + p1.w*k1;
- const Vec3fa dr1 = dp1 + (dp1.w*k1 + p1.w*dk1);
-
- const float scale = 1.0f/3.0f;
- CubicBezierCurve<V> L(l0,l0+scale*dl0,l1-scale*dl1,l1);
- CubicBezierCurve<V> R(r0,r0+scale*dr0,r1-scale*dr1,r1);
- return TensorLinearCubicBezierSurface(L,R);
- }
-
- __forceinline BBox<V> bounds() const {
- return merge(L.bounds(),R.bounds());
- }
-
- __forceinline BBox3fa accurateBounds() const {
- return merge(L.accurateBounds(),R.accurateBounds());
- }
-
- __forceinline CubicBezierCurve<Interval1f> reduce_v() const {
- return merge(CubicBezierCurve<Interval<V>>(L),CubicBezierCurve<Interval<V>>(R));
- }
-
- __forceinline LinearBezierCurve<Interval1f> reduce_u() const {
- return LinearBezierCurve<Interval1f>(L.bounds(),R.bounds());
- }
-
- __forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx) const {
- return TensorLinearCubicBezierSurface<float>(L.xfm(dx),R.xfm(dx));
- }
-
- __forceinline TensorLinearCubicBezierSurface<vfloatx> vxfm(const V& dx) const {
- return TensorLinearCubicBezierSurface<vfloatx>(L.vxfm(dx),R.vxfm(dx));
- }
-
- __forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx, const V& p) const {
- return TensorLinearCubicBezierSurface<float>(L.xfm(dx,p),R.xfm(dx,p));
- }
-
- __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space) const {
- return TensorLinearCubicBezierSurface(L.xfm(space),R.xfm(space));
- }
-
- __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p) const {
- return TensorLinearCubicBezierSurface(L.xfm(space,p),R.xfm(space,p));
- }
-
- __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p, const float s) const {
- return TensorLinearCubicBezierSurface(L.xfm(space,p,s),R.xfm(space,p,s));
- }
-
- __forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {
- return TensorLinearCubicBezierSurface(L.clip(u),R.clip(u));
- }
-
- __forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const {
- return TensorLinearCubicBezierSurface(clerp(L,R,V(v.lower)),clerp(L,R,V(v.upper)));
- }
-
- __forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {
- return clip_v(v).clip_u(u);
- }
-
- __forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const
- {
- CubicBezierCurve<V> L0,L1; L.split(L0,L1,u);
- CubicBezierCurve<V> R0,R1; R.split(R0,R1,u);
- new (&left ) TensorLinearCubicBezierSurface(L0,R0);
- new (&right) TensorLinearCubicBezierSurface(L1,R1);
- }
-
- __forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {
- valid = true; clear(valid,VSIZEX-1);
- return TensorLinearCubicBezierSurface<Vec2vfx>(L.split(u),R.split(u));
- }
-
- __forceinline V eval(const float u, const float v) const {
- return clerp(L,R,V(v)).eval(u);
- }
-
- __forceinline V eval_du(const float u, const float v) const {
- return clerp(L,R,V(v)).eval_dt(u);
- }
-
- __forceinline V eval_dv(const float u, const float v) const {
- return (R-L).eval(u);
- }
-
- __forceinline void eval(const float u, const float v, V& p, V& dpdu, V& dpdv) const
- {
- V p0, dp0du; L.eval(u,p0,dp0du);
- V p1, dp1du; R.eval(u,p1,dp1du);
- p = lerp(p0,p1,v);
- dpdu = lerp(dp0du,dp1du,v);
- dpdv = p1-p0;
- }
-
- __forceinline TensorLinearQuadraticBezierSurface<V> derivative_u() const {
- return TensorLinearQuadraticBezierSurface<V>(L.derivative(),R.derivative());
- }
-
- __forceinline CubicBezierCurve<V> derivative_v() const {
- return R-L;
- }
-
- __forceinline V axis_u() const {
- return (L.end()-L.begin())+(R.end()-R.begin());
- }
-
- __forceinline V axis_v() const {
- return (R.begin()-L.begin())+(R.end()-L.end());
- }
-
- friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)
- {
- return cout << "TensorLinearCubicBezierSurface" << embree_endl
- << "{" << embree_endl
- << " L = " << a.L << ", " << embree_endl
- << " R = " << a.R << embree_endl
- << "}";
- }
-
- friend __forceinline TensorLinearCubicBezierSurface clerp(const TensorLinearCubicBezierSurface& a, const TensorLinearCubicBezierSurface& b, const float t) {
- return TensorLinearCubicBezierSurface(clerp(a.L,b.L,V(t)), clerp(a.R,b.R,V(t)));
- }
- };
-
- template<>
- struct TensorLinearCubicBezierSurface<Vec2fa>
- {
- CubicBezierCurve<vfloat4> LR;
-
- __forceinline TensorLinearCubicBezierSurface() {}
-
- __forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)
- : LR(curve.LR) {}
-
- __forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {
- LR = other.LR; return *this;
- }
-
- __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<vfloat4>& LR)
- : LR(LR) {}
-
- __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<Vec2fa>& L, const CubicBezierCurve<Vec2fa>& R)
- : LR(shuffle<0,1,0,1>(vfloat4(L.v0),vfloat4(R.v0)),shuffle<0,1,0,1>(vfloat4(L.v1),vfloat4(R.v1)),shuffle<0,1,0,1>(vfloat4(L.v2),vfloat4(R.v2)),shuffle<0,1,0,1>(vfloat4(L.v3),vfloat4(R.v3))) {}
-
- __forceinline CubicBezierCurve<Vec2fa> getL() const {
- return CubicBezierCurve<Vec2fa>(Vec2fa(LR.v0),Vec2fa(LR.v1),Vec2fa(LR.v2),Vec2fa(LR.v3));
- }
-
- __forceinline CubicBezierCurve<Vec2fa> getR() const {
- return CubicBezierCurve<Vec2fa>(Vec2fa(shuffle<2,3,2,3>(LR.v0)),Vec2fa(shuffle<2,3,2,3>(LR.v1)),Vec2fa(shuffle<2,3,2,3>(LR.v2)),Vec2fa(shuffle<2,3,2,3>(LR.v3)));
- }
-
- __forceinline BBox<Vec2fa> bounds() const
- {
- const BBox<vfloat4> b = LR.bounds();
- const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));
- const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));
- return merge(bl,br);
- }
-
- __forceinline BBox1f bounds(const Vec2fa& axis) const
- {
- const CubicBezierCurve<vfloat4> LRx = LR;
- const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
- const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(axis)),LRx,shuffle<1>(vfloat4(axis))*LRy);
- const BBox<vfloat4> Lb = LRa.bounds();
- const BBox<vfloat4> Rb(shuffle<3>(Lb.lower),shuffle<3>(Lb.upper));
- const BBox<vfloat4> b = merge(Lb,Rb);
- return BBox1f(b.lower[0],b.upper[0]);
- }
-
- __forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx) const
- {
- const CubicBezierCurve<vfloat4> LRx = LR;
- const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
- const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);
- return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),
- CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));
- }
-
- __forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx, const Vec2fa& p) const
- {
- const vfloat4 pxyxy = shuffle<0,1,0,1>(vfloat4(p));
- const CubicBezierCurve<vfloat4> LRx = LR-pxyxy;
- const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
- const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);
- return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),
- CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));
- }
-
- __forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {
- return TensorLinearCubicBezierSurface(LR.clip(u));
- }
-
- __forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const
- {
- const CubicBezierCurve<vfloat4> LL(shuffle<0,1,0,1>(LR.v0),shuffle<0,1,0,1>(LR.v1),shuffle<0,1,0,1>(LR.v2),shuffle<0,1,0,1>(LR.v3));
- const CubicBezierCurve<vfloat4> RR(shuffle<2,3,2,3>(LR.v0),shuffle<2,3,2,3>(LR.v1),shuffle<2,3,2,3>(LR.v2),shuffle<2,3,2,3>(LR.v3));
- return TensorLinearCubicBezierSurface(clerp(LL,RR,vfloat4(v.lower,v.lower,v.upper,v.upper)));
- }
-
- __forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {
- return clip_v(v).clip_u(u);
- }
-
- __forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const
- {
- CubicBezierCurve<vfloat4> LR0,LR1; LR.split(LR0,LR1,u);
- new (&left ) TensorLinearCubicBezierSurface(LR0);
- new (&right) TensorLinearCubicBezierSurface(LR1);
- }
-
- __forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {
- valid = true; clear(valid,VSIZEX-1);
- return TensorLinearCubicBezierSurface<Vec2vfx>(getL().split(u),getR().split(u));
- }
-
- __forceinline Vec2fa eval(const float u, const float v) const
- {
- const vfloat4 p = LR.eval(u);
- return Vec2fa(lerp(shuffle<0,1,0,1>(p),shuffle<2,3,2,3>(p),v));
- }
-
- __forceinline Vec2fa eval_du(const float u, const float v) const
- {
- const vfloat4 dpdu = LR.eval_dt(u);
- return Vec2fa(lerp(shuffle<0,1,0,1>(dpdu),shuffle<2,3,2,3>(dpdu),v));
- }
-
- __forceinline Vec2fa eval_dv(const float u, const float v) const
- {
- const vfloat4 p = LR.eval(u);
- return Vec2fa(shuffle<2,3,2,3>(p)-shuffle<0,1,0,1>(p));
- }
-
- __forceinline void eval(const float u, const float v, Vec2fa& p, Vec2fa& dpdu, Vec2fa& dpdv) const
- {
- vfloat4 p0, dp0du; LR.eval(u,p0,dp0du);
- p = Vec2fa(lerp(shuffle<0,1,0,1>(p0),shuffle<2,3,2,3>(p0),v));
- dpdu = Vec2fa(lerp(shuffle<0,1,0,1>(dp0du),shuffle<2,3,2,3>(dp0du),v));
- dpdv = Vec2fa(shuffle<2,3,2,3>(p0)-shuffle<0,1,0,1>(p0));
- }
-
- __forceinline TensorLinearQuadraticBezierSurface<Vec2fa> derivative_u() const {
- return TensorLinearQuadraticBezierSurface<Vec2fa>(LR.derivative());
- }
-
- __forceinline CubicBezierCurve<Vec2fa> derivative_v() const {
- return getR()-getL();
- }
-
- __forceinline Vec2fa axis_u() const
- {
- const CubicBezierCurve<Vec2fa> L = getL();
- const CubicBezierCurve<Vec2fa> R = getR();
- return (L.end()-L.begin())+(R.end()-R.begin());
- }
-
- __forceinline Vec2fa axis_v() const
- {
- const CubicBezierCurve<Vec2fa> L = getL();
- const CubicBezierCurve<Vec2fa> R = getR();
- return (R.begin()-L.begin())+(R.end()-L.end());
- }
-
- friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)
- {
- return cout << "TensorLinearCubicBezierSurface" << embree_endl
- << "{" << embree_endl
- << " L = " << a.getL() << ", " << embree_endl
- << " R = " << a.getR() << embree_endl
- << "}";
- }
- };
-
- typedef TensorLinearCubicBezierSurface<float> TensorLinearCubicBezierSurface1f;
- typedef TensorLinearCubicBezierSurface<Vec2fa> TensorLinearCubicBezierSurface2fa;
- typedef TensorLinearCubicBezierSurface<Vec3fa> TensorLinearCubicBezierSurface3fa;
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/patch.h b/thirdparty/embree-aarch64/kernels/subdiv/patch.h
deleted file mode 100644
index d58241b96d..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/patch.h
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "catmullclark_patch.h"
-#include "bilinear_patch.h"
-#include "bspline_patch.h"
-#include "bezier_patch.h"
-#include "gregory_patch.h"
-#include "tessellation_cache.h"
-
-#if 1
-#define PATCH_DEBUG_SUBDIVISION(ptr,x,y,z)
-#else
-#define PATCH_DEBUG_SUBDIVISION(ptr,x,y,z) \
- { \
- size_t hex = (size_t)ptr; \
- for (size_t i=0; i<4; i++) hex = hex ^ (hex >> 8); \
- const float c = (float)(((hex >> 0) ^ (hex >> 4) ^ (hex >> 8) ^ (hex >> 12) ^ (hex >> 16))&0xf)/15.0f; \
- if (P) *P = Vertex(0.5f+0.5f*x,0.5f+0.5f*y,0.5f+0.5f*z,0.0f); \
- }
-#endif
-
-#define PATCH_MAX_CACHE_DEPTH 2
-//#define PATCH_MIN_RESOLUTION 1 // FIXME: not yet completely implemented
-#define PATCH_MAX_EVAL_DEPTH_IRREGULAR 10 // maximum evaluation depth at irregular vertices (has to be larger or equal than PATCH_MAX_CACHE_DEPTH)
-#define PATCH_MAX_EVAL_DEPTH_CREASE 10 // maximum evaluation depth at crease features (has to be larger or equal than PATCH_MAX_CACHE_DEPTH)
-#define PATCH_USE_GREGORY 1 // 0 = no gregory, 1 = fill, 2 = as early as possible
-
-#if PATCH_USE_GREGORY==2
-#define PATCH_USE_BEZIER_PATCH 1 // enable use of bezier instead of b-spline patches
-#else
-#define PATCH_USE_BEZIER_PATCH 0 // enable use of bezier instead of b-spline patches
-#endif
-
-#if PATCH_USE_BEZIER_PATCH
-# define RegularPatch BezierPatch
-# define RegularPatchT BezierPatchT<Vertex,Vertex_t>
-#else
-# define RegularPatch BSplinePatch
-# define RegularPatchT BSplinePatchT<Vertex,Vertex_t>
-#endif
-
-#if PATCH_USE_GREGORY
-#define IrregularFillPatch GregoryPatch
-#define IrregularFillPatchT GregoryPatchT<Vertex,Vertex_t>
-#else
-#define IrregularFillPatch BilinearPatch
-#define IrregularFillPatchT BilinearPatchT<Vertex,Vertex_t>
-#endif
-
-namespace embree
-{
- template<typename Vertex, typename Vertex_t = Vertex>
- struct __aligned(64) PatchT
- {
- public:
-
- typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
- typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
- typedef BezierCurveT<Vertex> BezierCurve;
-
- enum Type {
- INVALID_PATCH = 0,
- BILINEAR_PATCH = 1,
- BSPLINE_PATCH = 2,
- BEZIER_PATCH = 3,
- GREGORY_PATCH = 4,
- SUBDIVIDED_GENERAL_PATCH = 7,
- SUBDIVIDED_QUAD_PATCH = 8,
- EVAL_PATCH = 9,
- };
-
- struct Ref
- {
- __forceinline Ref(void* p = nullptr)
- : ptr((size_t)p) {}
-
- __forceinline operator bool() const { return ptr != 0; }
- __forceinline operator size_t() const { return ptr; }
-
- __forceinline Ref (Type ty, void* in)
- : ptr(((size_t)in)+ty) { assert((((size_t)in) & 0xF) == 0); }
-
- __forceinline Type type () const { return (Type)(ptr & 0xF); }
- __forceinline void* object() const { return (void*) (ptr & ~0xF); }
-
- size_t ptr;
- };
-
- struct EvalPatch
- {
- /* creates EvalPatch from a CatmullClarkPatch */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch)
- {
- size_t ofs = 0, bytes = patch.bytes();
- void* ptr = alloc(bytes);
- patch.serialize(ptr,ofs);
- assert(ofs == bytes);
- return Ref(EVAL_PATCH, ptr);
- }
- };
-
- struct BilinearPatch
- {
- /* creates BilinearPatch from a CatmullClarkPatch */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch,
- const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3) {
- return Ref(BILINEAR_PATCH, new (alloc(sizeof(BilinearPatch))) BilinearPatch(patch));
- }
-
- __forceinline BilinearPatch (const CatmullClarkPatch& patch)
- : patch(patch) {}
-
- /* creates BilinearPatch from 4 vertices */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride) {
- return Ref(BILINEAR_PATCH, new (alloc(sizeof(BilinearPatch))) BilinearPatch(edge,vertices,stride));
- }
-
- __forceinline BilinearPatch (const HalfEdge* edge, const char* vertices, size_t stride)
- : patch(edge,vertices,stride) {}
-
- public:
- BilinearPatchT<Vertex,Vertex_t> patch;
- };
-
- struct BSplinePatch
- {
- /* creates BSplinePatch from a half edge */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride) {
- return Ref(BSPLINE_PATCH, new (alloc(sizeof(BSplinePatch))) BSplinePatch(edge,vertices,stride));
- }
-
- __forceinline BSplinePatch (const HalfEdge* edge, const char* vertices, size_t stride)
- : patch(edge,vertices,stride) {}
-
- /* creates BSplinePatch from a CatmullClarkPatch */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch,
- const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3) {
- return Ref(BSPLINE_PATCH, new (alloc(sizeof(BSplinePatch))) BSplinePatch(patch,border0,border1,border2,border3));
- }
-
- __forceinline BSplinePatch (const CatmullClarkPatch& patch, const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)
- : patch(patch,border0,border1,border2,border3) {}
-
- public:
- BSplinePatchT<Vertex,Vertex_t> patch;
- };
-
- struct BezierPatch
- {
- /* creates BezierPatch from a half edge */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride) {
- return Ref(BEZIER_PATCH, new (alloc(sizeof(BezierPatch))) BezierPatch(edge,vertices,stride));
- }
-
- __forceinline BezierPatch (const HalfEdge* edge, const char* vertices, size_t stride)
- : patch(edge,vertices,stride) {}
-
- /* creates Bezier from a CatmullClarkPatch */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch,
- const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3) {
- return Ref(BEZIER_PATCH, new (alloc(sizeof(BezierPatch))) BezierPatch(patch,border0,border1,border2,border3));
- }
-
- __forceinline BezierPatch (const CatmullClarkPatch& patch, const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)
- : patch(patch,border0,border1,border2,border3) {}
-
- public:
- BezierPatchT<Vertex,Vertex_t> patch;
- };
-
- struct GregoryPatch
- {
- /* creates GregoryPatch from half edge */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride) {
- return Ref(GREGORY_PATCH, new (alloc(sizeof(GregoryPatch))) GregoryPatch(edge,vertices,stride));
- }
-
- __forceinline GregoryPatch (const HalfEdge* edge, const char* vertices, size_t stride)
- : patch(CatmullClarkPatch(edge,vertices,stride)) {}
-
- /* creates GregoryPatch from CatmullClarkPatch */
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch,
- const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3) {
- return Ref(GREGORY_PATCH, new (alloc(sizeof(GregoryPatch))) GregoryPatch(patch,border0,border1,border2,border3));
- }
-
- __forceinline GregoryPatch (const CatmullClarkPatch& patch, const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)
- : patch(patch,border0,border1,border2,border3) {}
-
- public:
- GregoryPatchT<Vertex,Vertex_t> patch;
- };
-
- struct SubdividedQuadPatch
- {
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, Ref children[4]) {
- return Ref(SUBDIVIDED_QUAD_PATCH, new (alloc(sizeof(SubdividedQuadPatch))) SubdividedQuadPatch(children));
- }
-
- __forceinline SubdividedQuadPatch(Ref children[4]) {
- for (size_t i=0; i<4; i++) child[i] = children[i];
- }
-
- public:
- Ref child[4];
- };
-
- struct SubdividedGeneralPatch
- {
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, Ref* children, const unsigned N) {
- return Ref(SUBDIVIDED_GENERAL_PATCH, new (alloc(sizeof(SubdividedGeneralPatch))) SubdividedGeneralPatch(children,N));
- }
-
- __forceinline SubdividedGeneralPatch(Ref* children, const unsigned N) : N(N) {
- for (unsigned i=0; i<N; i++) child[i] = children[i];
- }
-
- unsigned N;
- Ref child[MAX_PATCH_VALENCE];
- };
-
- /*! Default constructor. */
- __forceinline PatchT () {}
-
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride)
- {
- if (PATCH_MAX_CACHE_DEPTH == 0)
- return nullptr;
-
- Ref child(0);
- switch (edge->patch_type) {
- case HalfEdge::BILINEAR_PATCH: child = BilinearPatch::create(alloc,edge,vertices,stride); break;
- case HalfEdge::REGULAR_QUAD_PATCH: child = RegularPatch::create(alloc,edge,vertices,stride); break;
-#if PATCH_USE_GREGORY == 2
- case HalfEdge::IRREGULAR_QUAD_PATCH: child = GregoryPatch::create(alloc,edge,vertices,stride); break;
-#endif
- default: {
- GeneralCatmullClarkPatch patch(edge,vertices,stride);
- child = PatchT::create(alloc,patch,edge,vertices,stride,0);
- }
- }
- return child;
- }
-
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, GeneralCatmullClarkPatch& patch, const HalfEdge* edge, const char* vertices, size_t stride, size_t depth)
- {
- /* convert into standard quad patch if possible */
- if (likely(patch.isQuadPatch()))
- {
- CatmullClarkPatch qpatch; patch.init(qpatch);
- return PatchT::create(alloc,qpatch,edge,vertices,stride,depth);
- }
-
- /* do only cache up to some depth */
- if (depth >= PATCH_MAX_CACHE_DEPTH)
- return nullptr;
-
- /* subdivide patch */
- unsigned N;
- array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches;
- patch.subdivide(patches,N);
-
- if (N == 4)
- {
- Ref child[4];
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[GeneralCatmullClarkPatch::SIZE]; patch.getLimitBorder(borders);
- BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
- BezierCurve border1l,border1r; borders[1].subdivide(border1l,border1r);
- BezierCurve border2l,border2r; borders[2].subdivide(border2l,border2r);
- BezierCurve border3l,border3r; borders[3].subdivide(border3l,border3r);
- GeneralCatmullClarkPatch::fix_quad_ring_order(patches);
- child[0] = PatchT::create(alloc,patches[0],edge,vertices,stride,depth+1,&border0l,nullptr,nullptr,&border3r);
- child[1] = PatchT::create(alloc,patches[1],edge,vertices,stride,depth+1,&border0r,&border1l,nullptr,nullptr);
- child[2] = PatchT::create(alloc,patches[2],edge,vertices,stride,depth+1,nullptr,&border1r,&border2l,nullptr);
- child[3] = PatchT::create(alloc,patches[3],edge,vertices,stride,depth+1,nullptr,nullptr,&border2r,&border3l);
-#else
- GeneralCatmullClarkPatch::fix_quad_ring_order(patches);
- for (size_t i=0; i<4; i++)
- child[i] = PatchT::create(alloc,patches[i],edge,vertices,stride,depth+1);
-#endif
- return SubdividedQuadPatch::create(alloc,child);
- }
- else
- {
- assert(N<MAX_PATCH_VALENCE);
- Ref child[MAX_PATCH_VALENCE];
-
-#if PATCH_USE_GREGORY == 2
- BezierCurve borders[GeneralCatmullClarkPatch::SIZE];
- patch.getLimitBorder(borders);
-
- for (size_t i0=0; i0<N; i0++) {
- const size_t i2 = i0==0 ? N-1 : i0-1;
- BezierCurve border0l,border0r; borders[i0].subdivide(border0l,border0r);
- BezierCurve border2l,border2r; borders[i2].subdivide(border2l,border2r);
- child[i0] = PatchT::create(alloc,patches[i0],edge,vertices,stride,depth+1, &border0l, nullptr, nullptr, &border2r);
- }
-#else
- for (size_t i=0; i<N; i++)
- child[i] = PatchT::create(alloc,patches[i],edge,vertices,stride,depth+1);
-#endif
- return SubdividedGeneralPatch::create(alloc,child,N);
- }
-
- return nullptr;
- }
-
- static __forceinline bool final(const CatmullClarkPatch& patch, const typename CatmullClarkRing::Type type, size_t depth)
- {
- const size_t max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
-//#if PATCH_MIN_RESOLUTION
-// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=max_eval_depth;
-//#else
- return depth>=max_eval_depth;
-//#endif
- }
-
- template<typename Allocator>
- __noinline static Ref create(const Allocator& alloc, CatmullClarkPatch& patch, const HalfEdge* edge, const char* vertices, size_t stride, size_t depth,
- const BezierCurve* border0 = nullptr, const BezierCurve* border1 = nullptr, const BezierCurve* border2 = nullptr, const BezierCurve* border3 = nullptr)
- {
- const typename CatmullClarkPatch::Type ty = patch.type();
- if (unlikely(final(patch,ty,depth))) {
- if (ty & CatmullClarkRing::TYPE_REGULAR) return RegularPatch::create(alloc,patch,border0,border1,border2,border3);
- else return IrregularFillPatch::create(alloc,patch,border0,border1,border2,border3);
- }
- else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
- assert(depth > 0); return RegularPatch::create(alloc,patch,border0,border1,border2,border3);
- }
-#if PATCH_USE_GREGORY == 2
- else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
- assert(depth > 0); return GregoryPatch::create(alloc,patch,border0,border1,border2,border3);
- }
-#endif
- else if (depth >= PATCH_MAX_CACHE_DEPTH) {
- return EvalPatch::create(alloc,patch);
- }
-
- else
- {
- Ref child[4];
- array_t<CatmullClarkPatch,4> patches;
- patch.subdivide(patches);
-
- for (size_t i=0; i<4; i++)
- child[i] = PatchT::create(alloc,patches[i],edge,vertices,stride,depth+1);
- return SubdividedQuadPatch::create(alloc,child);
- }
- }
- };
-
- typedef PatchT<Vec3fa,Vec3fa_t> Patch3fa;
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/patch_eval.h b/thirdparty/embree-aarch64/kernels/subdiv/patch_eval.h
deleted file mode 100644
index 482d015fa3..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/patch_eval.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "patch.h"
-#include "feature_adaptive_eval.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename Vertex, typename Vertex_t = Vertex>
- struct PatchEval
- {
- public:
-
- typedef PatchT<Vertex,Vertex_t> Patch;
- typedef typename Patch::Ref Ref;
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
-
- PatchEval (SharedLazyTessellationCache::CacheEntry& entry, size_t commitCounter,
- const HalfEdge* edge, const char* vertices, size_t stride, const float u, const float v,
- Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv)
- : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv)
- {
- /* conservative time for the very first allocation */
- auto time = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
-
- Ref patch = SharedLazyTessellationCache::lookup(entry,commitCounter,[&] () {
- auto alloc = [&](size_t bytes) { return SharedLazyTessellationCache::malloc(bytes); };
- return Patch::create(alloc,edge,vertices,stride);
- },true);
-
- auto curTime = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
- const bool allAllocationsValid = SharedLazyTessellationCache::validTime(time,curTime);
-
- if (patch && allAllocationsValid && eval(patch,u,v,1.0f,0)) {
- SharedLazyTessellationCache::unlock();
- return;
- }
- SharedLazyTessellationCache::unlock();
- FeatureAdaptiveEval<Vertex,Vertex_t>(edge,vertices,stride,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv);
- PATCH_DEBUG_SUBDIVISION(edge,c,-1,-1);
- }
-
- __forceinline bool eval_quad(const typename Patch::SubdividedQuadPatch* This, const float u, const float v, const float dscale, const size_t depth)
- {
- if (v < 0.5f) {
- if (u < 0.5f) return eval(This->child[0],2.0f*u,2.0f*v,2.0f*dscale,depth+1);
- else return eval(This->child[1],2.0f*u-1.0f,2.0f*v,2.0f*dscale,depth+1);
- } else {
- if (u > 0.5f) return eval(This->child[2],2.0f*u-1.0f,2.0f*v-1.0f,2.0f*dscale,depth+1);
- else return eval(This->child[3],2.0f*u,2.0f*v-1.0f,2.0f*dscale,depth+1);
- }
- }
-
- bool eval_general(const typename Patch::SubdividedGeneralPatch* This, const float U, const float V, const size_t depth)
- {
- const unsigned l = (unsigned) floor(0.5f*U); const float u = 2.0f*frac(0.5f*U)-0.5f;
- const unsigned h = (unsigned) floor(0.5f*V); const float v = 2.0f*frac(0.5f*V)-0.5f;
- const unsigned i = 4*h+l; assert(i<This->N);
- return eval(This->child[i],u,v,1.0f,depth+1);
- }
-
- bool eval(Ref This, const float& u, const float& v, const float dscale, const size_t depth)
- {
- if (!This) return false;
- //PRINT(depth);
- //PRINT2(u,v);
-
- switch (This.type())
- {
- case Patch::BILINEAR_PATCH: {
- //PRINT("bilinear");
- ((typename Patch::BilinearPatch*)This.object())->patch.eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
- PATCH_DEBUG_SUBDIVISION(This,-1,c,c);
- return true;
- }
- case Patch::BSPLINE_PATCH: {
- //PRINT("bspline");
- ((typename Patch::BSplinePatch*)This.object())->patch.eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
- PATCH_DEBUG_SUBDIVISION(This,-1,c,-1);
- return true;
- }
- case Patch::BEZIER_PATCH: {
- //PRINT("bezier");
- ((typename Patch::BezierPatch*)This.object())->patch.eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
- PATCH_DEBUG_SUBDIVISION(This,-1,c,-1);
- return true;
- }
- case Patch::GREGORY_PATCH: {
- //PRINT("gregory");
- ((typename Patch::GregoryPatch*)This.object())->patch.eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
- PATCH_DEBUG_SUBDIVISION(This,-1,-1,c);
- return true;
- }
- case Patch::SUBDIVIDED_QUAD_PATCH: {
- //PRINT("subdivided quad");
- return eval_quad(((typename Patch::SubdividedQuadPatch*)This.object()),u,v,dscale,depth);
- }
- case Patch::SUBDIVIDED_GENERAL_PATCH: {
- //PRINT("general_patch");
- assert(dscale == 1.0f);
- return eval_general(((typename Patch::SubdividedGeneralPatch*)This.object()),u,v,depth);
- }
- case Patch::EVAL_PATCH: {
- //PRINT("eval_patch");
- CatmullClarkPatch patch; patch.deserialize(This.object());
- FeatureAdaptiveEval<Vertex,Vertex_t>(patch,u,v,dscale,depth,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv);
- return true;
- }
- default:
- assert(false);
- return false;
- }
- }
-
- private:
- Vertex* const P;
- Vertex* const dPdu;
- Vertex* const dPdv;
- Vertex* const ddPdudu;
- Vertex* const ddPdvdv;
- Vertex* const ddPdudv;
- };
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/patch_eval_grid.h b/thirdparty/embree-aarch64/kernels/subdiv/patch_eval_grid.h
deleted file mode 100644
index c05db55f4c..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/patch_eval_grid.h
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "patch.h"
-#include "feature_adaptive_eval_grid.h"
-
-namespace embree
-{
- namespace isa
- {
- struct PatchEvalGrid
- {
- typedef Patch3fa Patch;
- typedef Patch::Ref Ref;
- typedef GeneralCatmullClarkPatch3fa GeneralCatmullClarkPatch;
- typedef CatmullClarkPatch3fa CatmullClarkPatch;
- typedef BSplinePatch3fa BSplinePatch;
- typedef BezierPatch3fa BezierPatch;
- typedef GregoryPatch3fa GregoryPatch;
- typedef BilinearPatch3fa BilinearPatch;
-
- private:
- const unsigned x0,x1;
- const unsigned y0,y1;
- const unsigned swidth,sheight;
- const float rcp_swidth, rcp_sheight;
- float* const Px;
- float* const Py;
- float* const Pz;
- float* const U;
- float* const V;
- float* const Nx;
- float* const Ny;
- float* const Nz;
- const unsigned dwidth,dheight;
- unsigned count;
-
- public:
-
- PatchEvalGrid (Ref patch, unsigned subPatch,
- const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
- float* Px, float* Py, float* Pz, float* U, float* V,
- float* Nx, float* Ny, float* Nz,
- const unsigned dwidth, const unsigned dheight)
- : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
- Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), dheight(dheight), count(0)
- {
- assert(swidth < (2<<20) && sheight < (2<<20));
- const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(float(swidth-1),float(sheight-1)));
- const BBox2f erange(Vec2f(float(x0),float(y0)),Vec2f((float)x1,(float)y1));
- bool done MAYBE_UNUSED = eval(patch,subPatch,srange,erange);
- assert(done);
- assert(count == (x1-x0+1)*(y1-y0+1));
- }
-
- template<typename Patch>
- __forceinline void evalLocalGrid(const Patch* patch, const BBox2f& srange, const int lx0, const int lx1, const int ly0, const int ly1)
- {
- const float scale_x = rcp(srange.upper.x-srange.lower.x);
- const float scale_y = rcp(srange.upper.y-srange.lower.y);
- count += (lx1-lx0)*(ly1-ly0);
-
-#if 0
- for (unsigned iy=ly0; iy<ly1; iy++) {
- for (unsigned ix=lx0; ix<lx1; ix++) {
- const float lu = select(ix == swidth -1, float(1.0f), (float(ix)-srange.lower.x)*scale_x);
- const float lv = select(iy == sheight-1, float(1.0f), (float(iy)-srange.lower.y)*scale_y);
- const Vec3fa p = patch->patch.eval(lu,lv);
- const float u = float(ix)*rcp_swidth;
- const float v = float(iy)*rcp_sheight;
- const int ofs = (iy-y0)*dwidth+(ix-x0);
- Px[ofs] = p.x;
- Py[ofs] = p.y;
- Pz[ofs] = p.z;
- U[ofs] = u;
- V[ofs] = v;
- }
- }
-#else
- foreach2(lx0,lx1,ly0,ly1,[&](const vboolx& valid, const vintx& ix, const vintx& iy) {
- const vfloatx lu = select(ix == swidth -1, vfloatx(1.0f), (vfloatx(ix)-srange.lower.x)*scale_x);
- const vfloatx lv = select(iy == sheight-1, vfloatx(1.0f), (vfloatx(iy)-srange.lower.y)*scale_y);
- const Vec3vfx p = patch->patch.eval(lu,lv);
- Vec3vfx n = zero;
- if (unlikely(Nx != nullptr)) n = normalize_safe(patch->patch.normal(lu,lv));
- const vfloatx u = vfloatx(ix)*rcp_swidth;
- const vfloatx v = vfloatx(iy)*rcp_sheight;
- const vintx ofs = (iy-y0)*dwidth+(ix-x0);
- if (likely(all(valid)) && all(iy==iy[0])) {
- const unsigned ofs2 = ofs[0];
- vfloatx::storeu(Px+ofs2,p.x);
- vfloatx::storeu(Py+ofs2,p.y);
- vfloatx::storeu(Pz+ofs2,p.z);
- vfloatx::storeu(U+ofs2,u);
- vfloatx::storeu(V+ofs2,v);
- if (unlikely(Nx != nullptr)) {
- vfloatx::storeu(Nx+ofs2,n.x);
- vfloatx::storeu(Ny+ofs2,n.y);
- vfloatx::storeu(Nz+ofs2,n.z);
- }
- } else {
- foreach_unique_index(valid,iy,[&](const vboolx& valid, const int iy0, const int j) {
- const unsigned ofs2 = ofs[j]-j;
- vfloatx::storeu(valid,Px+ofs2,p.x);
- vfloatx::storeu(valid,Py+ofs2,p.y);
- vfloatx::storeu(valid,Pz+ofs2,p.z);
- vfloatx::storeu(valid,U+ofs2,u);
- vfloatx::storeu(valid,V+ofs2,v);
- if (unlikely(Nx != nullptr)) {
- vfloatx::storeu(valid,Nx+ofs2,n.x);
- vfloatx::storeu(valid,Ny+ofs2,n.y);
- vfloatx::storeu(valid,Nz+ofs2,n.z);
- }
- });
- }
- });
-#endif
- }
-
- bool eval(Ref This, const BBox2f& srange, const BBox2f& erange, const unsigned depth)
- {
- if (erange.empty())
- return true;
-
- const int lx0 = (int) ceilf(erange.lower.x);
- const int lx1 = (int) ceilf(erange.upper.x) + (erange.upper.x == x1 && (srange.lower.x < erange.upper.x || erange.upper.x == 0));
- const int ly0 = (int) ceilf(erange.lower.y);
- const int ly1 = (int) ceilf(erange.upper.y) + (erange.upper.y == y1 && (srange.lower.y < erange.upper.y || erange.upper.y == 0));
- if (lx0 >= lx1 || ly0 >= ly1)
- return true;
-
- if (!This)
- return false;
-
- switch (This.type())
- {
- case Patch::BILINEAR_PATCH: {
- evalLocalGrid((Patch::BilinearPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
- return true;
- }
- case Patch::BSPLINE_PATCH: {
- evalLocalGrid((Patch::BSplinePatch*)This.object(),srange,lx0,lx1,ly0,ly1);
- return true;
- }
- case Patch::BEZIER_PATCH: {
- evalLocalGrid((Patch::BezierPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
- return true;
- }
- case Patch::GREGORY_PATCH: {
- evalLocalGrid((Patch::GregoryPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
- return true;
- }
- case Patch::SUBDIVIDED_QUAD_PATCH:
- {
- const Vec2f c = srange.center();
- const BBox2f srange0(srange.lower,c);
- const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
- const BBox2f srange2(c,srange.upper);
- const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
-
- Patch::SubdividedQuadPatch* patch = (Patch::SubdividedQuadPatch*)This.object();
- eval(patch->child[0],srange0,intersect(srange0,erange),depth+1);
- eval(patch->child[1],srange1,intersect(srange1,erange),depth+1);
- eval(patch->child[2],srange2,intersect(srange2,erange),depth+1);
- eval(patch->child[3],srange3,intersect(srange3,erange),depth+1);
- return true;
- }
- case Patch::EVAL_PATCH: {
- CatmullClarkPatch patch; patch.deserialize(This.object());
- FeatureAdaptiveEvalGrid(patch,srange,erange,depth,x0,x1,y0,y1,swidth,sheight,Px,Py,Pz,U,V,Nx,Ny,Nz,dwidth,dheight);
- count += (lx1-lx0)*(ly1-ly0);
- return true;
- }
- default:
- assert(false);
- return false;
- }
- }
-
- bool eval(Ref This, unsigned subPatch, const BBox2f& srange, const BBox2f& erange)
- {
- if (!This)
- return false;
-
- switch (This.type())
- {
- case Patch::SUBDIVIDED_GENERAL_PATCH: {
- Patch::SubdividedGeneralPatch* patch = (Patch::SubdividedGeneralPatch*)This.object();
- assert(subPatch < patch->N);
- return eval(patch->child[subPatch],srange,erange,1);
- }
- default:
- assert(subPatch == 0);
- return eval(This,srange,erange,0);
- }
- }
- };
-
- __forceinline unsigned patch_eval_subdivision_count (const HalfEdge* h)
- {
- const unsigned N = h->numEdges();
- if (N == 4) return 1;
- else return N;
- }
-
- template<typename Tessellator>
- inline void patch_eval_subdivision (const HalfEdge* h, Tessellator tessellator)
- {
- const unsigned N = h->numEdges();
- int neighborSubdiv[GeneralCatmullClarkPatch3fa::SIZE]; // FIXME: use array_t
- float levels[GeneralCatmullClarkPatch3fa::SIZE];
- for (unsigned i=0; i<N; i++) {
- assert(i<GeneralCatmullClarkPatch3fa::SIZE);
- neighborSubdiv[i] = h->hasOpposite() ? h->opposite()->numEdges() != 4 : 0;
- levels[i] = h->edge_level;
- h = h->next();
- }
- if (N == 4)
- {
- const Vec2f uv[4] = { Vec2f(0.0f,0.0f), Vec2f(1.0f,0.0f), Vec2f(1.0f,1.0f), Vec2f(0.0f,1.0f) };
- tessellator(uv,neighborSubdiv,levels,0);
- }
- else
- {
- for (unsigned i=0; i<N; i++)
- {
- assert(i<MAX_PATCH_VALENCE);
- static_assert(MAX_PATCH_VALENCE <= 16, "MAX_PATCH_VALENCE > 16");
- const int h = (i >> 2) & 3, l = i & 3;
- const Vec2f subPatchID((float)l,(float)h);
- const Vec2f uv[4] = { 2.0f*subPatchID + (0.5f+Vec2f(0.0f,0.0f)),
- 2.0f*subPatchID + (0.5f+Vec2f(1.0f,0.0f)),
- 2.0f*subPatchID + (0.5f+Vec2f(1.0f,1.0f)),
- 2.0f*subPatchID + (0.5f+Vec2f(0.0f,1.0f)) };
- const int neighborSubdiv1[4] = { 0,0,0,0 };
- const float levels1[4] = { 0.5f*levels[(i+0)%N], 0.5f*levels[(i+0)%N], 0.5f*levels[(i+N-1)%N], 0.5f*levels[(i+N-1)%N] };
- tessellator(uv,neighborSubdiv1,levels1,i);
- }
- }
- }
- }
-}
-
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/patch_eval_simd.h b/thirdparty/embree-aarch64/kernels/subdiv/patch_eval_simd.h
deleted file mode 100644
index 28016d9e20..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/patch_eval_simd.h
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "patch.h"
-#include "feature_adaptive_eval_simd.h"
-
-namespace embree
-{
- namespace isa
- {
- template<typename vbool, typename vint, typename vfloat, typename Vertex, typename Vertex_t = Vertex>
- struct PatchEvalSimd
- {
- public:
-
- typedef PatchT<Vertex,Vertex_t> Patch;
- typedef typename Patch::Ref Ref;
- typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
-
- PatchEvalSimd (SharedLazyTessellationCache::CacheEntry& entry, size_t commitCounter,
- const HalfEdge* edge, const char* vertices, size_t stride, const vbool& valid0, const vfloat& u, const vfloat& v,
- float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, const size_t dstride, const size_t N)
- : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv), dstride(dstride), N(N)
- {
- /* conservative time for the very first allocation */
- auto time = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
-
- Ref patch = SharedLazyTessellationCache::lookup(entry,commitCounter,[&] () {
- auto alloc = [](size_t bytes) { return SharedLazyTessellationCache::malloc(bytes); };
- return Patch::create(alloc,edge,vertices,stride);
- }, true);
-
- auto curTime = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
- const bool allAllocationsValid = SharedLazyTessellationCache::validTime(time,curTime);
-
- patch = allAllocationsValid ? patch : nullptr;
-
- /* use cached data structure for calculations */
- const vbool valid1 = patch ? eval(valid0,patch,u,v,1.0f,0) : vbool(false);
- SharedLazyTessellationCache::unlock();
- const vbool valid2 = valid0 & !valid1;
- if (any(valid2)) {
- FeatureAdaptiveEvalSimd<vbool,vint,vfloat,Vertex,Vertex_t>(edge,vertices,stride,valid2,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dstride,N);
- }
- }
-
- vbool eval_quad(const vbool& valid, const typename Patch::SubdividedQuadPatch* This, const vfloat& u, const vfloat& v, const float dscale, const size_t depth)
- {
- vbool ret = false;
- const vbool u0_mask = u < 0.5f, u1_mask = u >= 0.5f;
- const vbool v0_mask = v < 0.5f, v1_mask = v >= 0.5f;
- const vbool u0v0_mask = valid & u0_mask & v0_mask;
- const vbool u0v1_mask = valid & u0_mask & v1_mask;
- const vbool u1v0_mask = valid & u1_mask & v0_mask;
- const vbool u1v1_mask = valid & u1_mask & v1_mask;
- if (any(u0v0_mask)) ret |= eval(u0v0_mask,This->child[0],2.0f*u,2.0f*v,2.0f*dscale,depth+1);
- if (any(u1v0_mask)) ret |= eval(u1v0_mask,This->child[1],2.0f*u-1.0f,2.0f*v,2.0f*dscale,depth+1);
- if (any(u1v1_mask)) ret |= eval(u1v1_mask,This->child[2],2.0f*u-1.0f,2.0f*v-1.0f,2.0f*dscale,depth+1);
- if (any(u0v1_mask)) ret |= eval(u0v1_mask,This->child[3],2.0f*u,2.0f*v-1.0f,2.0f*dscale,depth+1);
- return ret;
- }
-
- vbool eval_general(const vbool& valid, const typename Patch::SubdividedGeneralPatch* patch, const vfloat& U, const vfloat& V, const size_t depth)
- {
- vbool ret = false;
- const vint l = (vint)floor(0.5f*U); const vfloat u = 2.0f*frac(0.5f*U)-0.5f;
- const vint h = (vint)floor(0.5f*V); const vfloat v = 2.0f*frac(0.5f*V)-0.5f;
- const vint i = (h<<2)+l; assert(all(valid,i<patch->N));
- foreach_unique(valid,i,[&](const vbool& valid, const int i) {
- ret |= eval(valid,patch->child[i],u,v,1.0f,depth+1);
- });
- return ret;
- }
-
- vbool eval(const vbool& valid, Ref This, const vfloat& u, const vfloat& v, const float dscale, const size_t depth)
- {
- if (!This) return false;
- switch (This.type())
- {
- case Patch::BILINEAR_PATCH: {
- ((typename Patch::BilinearPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- return valid;
- }
- case Patch::BSPLINE_PATCH: {
- ((typename Patch::BSplinePatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- return valid;
- }
- case Patch::BEZIER_PATCH: {
- ((typename Patch::BezierPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- return valid;
- }
- case Patch::GREGORY_PATCH: {
- ((typename Patch::GregoryPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
- return valid;
- }
- case Patch::SUBDIVIDED_QUAD_PATCH: {
- return eval_quad(valid,((typename Patch::SubdividedQuadPatch*)This.object()),u,v,dscale,depth);
- }
- case Patch::SUBDIVIDED_GENERAL_PATCH: {
- assert(dscale == 1.0f);
- return eval_general(valid,((typename Patch::SubdividedGeneralPatch*)This.object()),u,v,depth);
- }
- case Patch::EVAL_PATCH: {
- CatmullClarkPatch patch; patch.deserialize(This.object());
- FeatureAdaptiveEvalSimd<vbool,vint,vfloat,Vertex,Vertex_t>(patch,valid,u,v,dscale,depth,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dstride,N);
- return valid;
- }
- default:
- assert(false);
- return false;
- }
- }
-
- private:
- float* const P;
- float* const dPdu;
- float* const dPdv;
- float* const ddPdudu;
- float* const ddPdvdv;
- float* const ddPdudv;
- const size_t dstride;
- const size_t N;
- };
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/subdivpatch1base.h b/thirdparty/embree-aarch64/kernels/subdiv/subdivpatch1base.h
deleted file mode 100644
index d5bc403cca..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/subdivpatch1base.h
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../geometry/primitive.h"
-#include "bspline_patch.h"
-#include "bezier_patch.h"
-#include "gregory_patch.h"
-#include "gregory_patch_dense.h"
-#include "tessellation.h"
-#include "tessellation_cache.h"
-#include "gridrange.h"
-#include "patch_eval_grid.h"
-#include "feature_adaptive_eval_grid.h"
-#include "../common/scene_subdiv_mesh.h"
-
-namespace embree
-{
- struct __aligned(64) SubdivPatch1Base
- {
- public:
-
- enum Type {
- INVALID_PATCH = 0,
- BSPLINE_PATCH = 1,
- BEZIER_PATCH = 2,
- GREGORY_PATCH = 3,
- EVAL_PATCH = 5,
- BILINEAR_PATCH = 6,
- };
-
- enum Flags {
- TRANSITION_PATCH = 16,
- };
-
- /*! Default constructor. */
- __forceinline SubdivPatch1Base () {}
-
- SubdivPatch1Base (const unsigned int gID,
- const unsigned int pID,
- const unsigned int subPatch,
- const SubdivMesh *const mesh,
- const size_t time,
- const Vec2f uv[4],
- const float edge_level[4],
- const int subdiv[4],
- const int simd_width);
-
- __forceinline bool needsStitching() const {
- return flags & TRANSITION_PATCH;
- }
-
- __forceinline Vec2f getUV(const size_t i) const {
- return Vec2f((float)u[i],(float)v[i]) * (8.0f/0x10000);
- }
-
- static void computeEdgeLevels(const float edge_level[4], const int subdiv[4], float level[4]);
- static Vec2i computeGridSize(const float level[4]);
- bool updateEdgeLevels(const float edge_level[4], const int subdiv[4], const SubdivMesh *const mesh, const int simd_width);
-
- public:
-
- __forceinline size_t getGridBytes() const {
- const size_t grid_size_xyzuv = (grid_size_simd_blocks * VSIZEX) * 4;
- return 64*((grid_size_xyzuv+15) / 16);
- }
-
- __forceinline void write_lock() { mtx.lock(); }
- __forceinline void write_unlock() { mtx.unlock(); }
- __forceinline bool try_write_lock() { return mtx.try_lock(); }
- //__forceinline bool try_read_lock() { return mtx.try_read_lock(); }
-
- __forceinline void resetRootRef() {
- //assert( mtx.hasInitialState() );
- root_ref = SharedLazyTessellationCache::Tag();
- }
-
- __forceinline SharedLazyTessellationCache::CacheEntry& entry() {
- return (SharedLazyTessellationCache::CacheEntry&) root_ref;
- }
-
- public:
- __forceinline unsigned int geomID() const {
- return geom;
- }
-
- __forceinline unsigned int primID() const {
- return prim;
- }
-
- public:
- SharedLazyTessellationCache::Tag root_ref;
- SpinLock mtx;
-
- unsigned short u[4]; //!< 16bit discretized u,v coordinates
- unsigned short v[4];
- float level[4];
-
- unsigned char flags;
- unsigned char type;
- unsigned short grid_u_res;
- unsigned int geom; //!< geometry ID of the subdivision mesh this patch belongs to
- unsigned int prim; //!< primitive ID of this subdivision patch
- unsigned short grid_v_res;
-
- unsigned short grid_size_simd_blocks;
- unsigned int time_;
-
- struct PatchHalfEdge {
- const HalfEdge* edge;
- unsigned subPatch;
- };
-
- Vec3fa patch_v[4][4];
-
- const HalfEdge *edge() const { return ((PatchHalfEdge*)patch_v)->edge; }
- unsigned time() const { return time_; }
- unsigned subPatch() const { return ((PatchHalfEdge*)patch_v)->subPatch; }
-
- void set_edge(const HalfEdge *h) const { ((PatchHalfEdge*)patch_v)->edge = h; }
- void set_subPatch(const unsigned s) const { ((PatchHalfEdge*)patch_v)->subPatch = s; }
- };
-
- namespace isa
- {
- Vec3fa patchEval(const SubdivPatch1Base& patch, const float uu, const float vv);
- Vec3fa patchNormal(const SubdivPatch1Base& patch, const float uu, const float vv);
-
- template<typename simdf>
- Vec3<simdf> patchEval(const SubdivPatch1Base& patch, const simdf& uu, const simdf& vv);
-
- template<typename simdf>
- Vec3<simdf> patchNormal(const SubdivPatch1Base& patch, const simdf& uu, const simdf& vv);
-
-
- /* eval grid over patch and stich edges when required */
- void evalGrid(const SubdivPatch1Base& patch,
- const unsigned x0, const unsigned x1,
- const unsigned y0, const unsigned y1,
- const unsigned swidth, const unsigned sheight,
- float *__restrict__ const grid_x,
- float *__restrict__ const grid_y,
- float *__restrict__ const grid_z,
- float *__restrict__ const grid_u,
- float *__restrict__ const grid_v,
- const SubdivMesh* const geom);
-
- /* eval grid over patch and stich edges when required */
- BBox3fa evalGridBounds(const SubdivPatch1Base& patch,
- const unsigned x0, const unsigned x1,
- const unsigned y0, const unsigned y1,
- const unsigned swidth, const unsigned sheight,
- const SubdivMesh* const geom);
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/tessellation.h b/thirdparty/embree-aarch64/kernels/subdiv/tessellation.h
deleted file mode 100644
index bda1e2d559..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/tessellation.h
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-namespace embree
-{
- /* adjust discret tessellation level for feature-adaptive pre-subdivision */
- __forceinline float adjustTessellationLevel(float l, const size_t sublevel)
- {
- for (size_t i=0; i<sublevel; i++) l *= 0.5f;
- float r = ceilf(l);
- for (size_t i=0; i<sublevel; i++) r *= 2.0f;
- return r;
- }
-
- __forceinline int stitch(const int x, const int fine, const int coarse) {
- return (2*x+1)*coarse/(2*fine);
- }
-
- __forceinline void stitchGridEdges(const unsigned int low_rate,
- const unsigned int high_rate,
- const unsigned int x0,
- const unsigned int x1,
- float * __restrict__ const uv_array,
- const unsigned int uv_array_step)
- {
-#if 1
- const float inv_low_rate = rcp((float)(low_rate-1));
- for (unsigned x=x0; x<=x1; x++) {
- uv_array[(x-x0)*uv_array_step] = float(stitch(x,high_rate-1,low_rate-1))*inv_low_rate;
- }
- if (unlikely(x1 == high_rate-1))
- uv_array[(x1-x0)*uv_array_step] = 1.0f;
-#else
- assert(low_rate < high_rate);
- assert(high_rate >= 2);
-
- const float inv_low_rate = rcp((float)(low_rate-1));
- const unsigned int dy = low_rate - 1;
- const unsigned int dx = high_rate - 1;
-
- int p = 2*dy-dx;
-
- unsigned int offset = 0;
- unsigned int y = 0;
- float value = 0.0f;
- for(unsigned int x=0;x<high_rate-1; x++) // '<=' would be correct but we will leave the 1.0f at the end
- {
- uv_array[offset] = value;
-
- offset += uv_array_step;
- if (unlikely(p > 0))
- {
- y++;
- value = (float)y * inv_low_rate;
- p -= 2*dx;
- }
- p += 2*dy;
- }
-#endif
- }
-
- __forceinline void stitchUVGrid(const float edge_levels[4],
- const unsigned int swidth,
- const unsigned int sheight,
- const unsigned int x0,
- const unsigned int y0,
- const unsigned int grid_u_res,
- const unsigned int grid_v_res,
- float * __restrict__ const u_array,
- float * __restrict__ const v_array)
- {
- const unsigned int x1 = x0+grid_u_res-1;
- const unsigned int y1 = y0+grid_v_res-1;
- const unsigned int int_edge_points0 = (unsigned int)edge_levels[0] + 1;
- const unsigned int int_edge_points1 = (unsigned int)edge_levels[1] + 1;
- const unsigned int int_edge_points2 = (unsigned int)edge_levels[2] + 1;
- const unsigned int int_edge_points3 = (unsigned int)edge_levels[3] + 1;
-
- if (unlikely(y0 == 0 && int_edge_points0 < swidth))
- stitchGridEdges(int_edge_points0,swidth,x0,x1,u_array,1);
-
- if (unlikely(y1 == sheight-1 && int_edge_points2 < swidth))
- stitchGridEdges(int_edge_points2,swidth,x0,x1,&u_array[(grid_v_res-1)*grid_u_res],1);
-
- if (unlikely(x0 == 0 && int_edge_points1 < sheight))
- stitchGridEdges(int_edge_points1,sheight,y0,y1,&v_array[grid_u_res-1],grid_u_res);
-
- if (unlikely(x1 == swidth-1 && int_edge_points3 < sheight))
- stitchGridEdges(int_edge_points3,sheight,y0,y1,v_array,grid_u_res);
- }
-
- __forceinline void gridUVTessellator(const float edge_levels[4],
- const unsigned int swidth,
- const unsigned int sheight,
- const unsigned int x0,
- const unsigned int y0,
- const unsigned int grid_u_res,
- const unsigned int grid_v_res,
- float * __restrict__ const u_array,
- float * __restrict__ const v_array)
- {
- assert( grid_u_res >= 1);
- assert( grid_v_res >= 1);
- assert( edge_levels[0] >= 1.0f );
- assert( edge_levels[1] >= 1.0f );
- assert( edge_levels[2] >= 1.0f );
- assert( edge_levels[3] >= 1.0f );
-
-#if defined(__AVX__)
- const vint8 grid_u_segments = vint8(swidth)-1;
- const vint8 grid_v_segments = vint8(sheight)-1;
-
- const vfloat8 inv_grid_u_segments = rcp(vfloat8(grid_u_segments));
- const vfloat8 inv_grid_v_segments = rcp(vfloat8(grid_v_segments));
-
- unsigned int index = 0;
- vint8 v_i( zero );
- for (unsigned int y=0;y<grid_v_res;y++,index+=grid_u_res,v_i += 1)
- {
- vint8 u_i ( step );
-
- const vbool8 m_v = v_i < grid_v_segments;
-
- for (unsigned int x=0;x<grid_u_res;x+=8, u_i += 8)
- {
- const vbool8 m_u = u_i < grid_u_segments;
- const vfloat8 u = select(m_u, vfloat8(x0+u_i) * inv_grid_u_segments, 1.0f);
- const vfloat8 v = select(m_v, vfloat8(y0+v_i) * inv_grid_v_segments, 1.0f);
- vfloat8::storeu(&u_array[index + x],u);
- vfloat8::storeu(&v_array[index + x],v);
- }
- }
- #else
- const vint4 grid_u_segments = vint4(swidth)-1;
- const vint4 grid_v_segments = vint4(sheight)-1;
-
- const vfloat4 inv_grid_u_segments = rcp(vfloat4(grid_u_segments));
- const vfloat4 inv_grid_v_segments = rcp(vfloat4(grid_v_segments));
-
- unsigned int index = 0;
- vint4 v_i( zero );
- for (unsigned int y=0;y<grid_v_res;y++,index+=grid_u_res,v_i += 1)
- {
- vint4 u_i ( step );
-
- const vbool4 m_v = v_i < grid_v_segments;
-
- for (unsigned int x=0;x<grid_u_res;x+=4, u_i += 4)
- {
- const vbool4 m_u = u_i < grid_u_segments;
- const vfloat4 u = select(m_u, vfloat4(x0+u_i) * inv_grid_u_segments, 1.0f);
- const vfloat4 v = select(m_v, vfloat4(y0+v_i) * inv_grid_v_segments, 1.0f);
- vfloat4::storeu(&u_array[index + x],u);
- vfloat4::storeu(&v_array[index + x],v);
- }
- }
-#endif
- }
-}
diff --git a/thirdparty/embree-aarch64/kernels/subdiv/tessellation_cache.h b/thirdparty/embree-aarch64/kernels/subdiv/tessellation_cache.h
deleted file mode 100644
index 5c215288b6..0000000000
--- a/thirdparty/embree-aarch64/kernels/subdiv/tessellation_cache.h
+++ /dev/null
@@ -1,325 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../common/default.h"
-
-/* force a complete cache invalidation when running out of allocation space */
-#define FORCE_SIMPLE_FLUSH 0
-
-#define THREAD_BLOCK_ATOMIC_ADD 4
-
-#if defined(DEBUG)
-#define CACHE_STATS(x)
-#else
-#define CACHE_STATS(x)
-#endif
-
-namespace embree
-{
- class SharedTessellationCacheStats
- {
- public:
- /* stats */
- static std::atomic<size_t> cache_accesses;
- static std::atomic<size_t> cache_hits;
- static std::atomic<size_t> cache_misses;
- static std::atomic<size_t> cache_flushes;
- static size_t cache_num_patches;
- __aligned(64) static SpinLock mtx;
-
- /* print stats for debugging */
- static void printStats();
- static void clearStats();
- };
-
- void resizeTessellationCache(size_t new_size);
- void resetTessellationCache();
-
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
-
- struct __aligned(64) ThreadWorkState
- {
- ALIGNED_STRUCT_(64);
-
- std::atomic<size_t> counter;
- ThreadWorkState* next;
- bool allocated;
-
- __forceinline ThreadWorkState(bool allocated = false)
- : counter(0), next(nullptr), allocated(allocated)
- {
- assert( ((size_t)this % 64) == 0 );
- }
- };
-
- class __aligned(64) SharedLazyTessellationCache
- {
- public:
-
- static const size_t NUM_CACHE_SEGMENTS = 8;
- static const size_t NUM_PREALLOC_THREAD_WORK_STATES = 512;
- static const size_t COMMIT_INDEX_SHIFT = 32+8;
-#if defined(__X86_64__) || defined(__aarch64__)
- static const size_t REF_TAG_MASK = 0xffffffffff;
-#else
- static const size_t REF_TAG_MASK = 0x7FFFFFFF;
-#endif
- static const size_t MAX_TESSELLATION_CACHE_SIZE = REF_TAG_MASK+1;
- static const size_t BLOCK_SIZE = 64;
-
-
- /*! Per thread tessellation ref cache */
- static __thread ThreadWorkState* init_t_state;
- static ThreadWorkState* current_t_state;
-
- static __forceinline ThreadWorkState *threadState()
- {
- if (unlikely(!init_t_state))
- /* sets init_t_state, can't return pointer due to macosx icc bug*/
- SharedLazyTessellationCache::sharedLazyTessellationCache.getNextRenderThreadWorkState();
- return init_t_state;
- }
-
- struct Tag
- {
- __forceinline Tag() : data(0) {}
-
- __forceinline Tag(void* ptr, size_t combinedTime) {
- init(ptr,combinedTime);
- }
-
- __forceinline Tag(size_t ptr, size_t combinedTime) {
- init((void*)ptr,combinedTime);
- }
-
- __forceinline void init(void* ptr, size_t combinedTime)
- {
- if (ptr == nullptr) {
- data = 0;
- return;
- }
- int64_t new_root_ref = (int64_t) ptr;
- new_root_ref -= (int64_t)SharedLazyTessellationCache::sharedLazyTessellationCache.getDataPtr();
- assert( new_root_ref <= (int64_t)REF_TAG_MASK );
- new_root_ref |= (int64_t)combinedTime << COMMIT_INDEX_SHIFT;
- data = new_root_ref;
- }
-
- __forceinline int64_t get() const { return data.load(); }
- __forceinline void set( int64_t v ) { data.store(v); }
- __forceinline void reset() { data.store(0); }
-
- private:
- atomic<int64_t> data;
- };
-
- static __forceinline size_t extractCommitIndex(const int64_t v) { return v >> SharedLazyTessellationCache::COMMIT_INDEX_SHIFT; }
-
- struct CacheEntry
- {
- Tag tag;
- SpinLock mutex;
- };
-
- private:
-
- float *data;
- bool hugepages;
- size_t size;
- size_t maxBlocks;
- ThreadWorkState *threadWorkState;
-
- __aligned(64) std::atomic<size_t> localTime;
- __aligned(64) std::atomic<size_t> next_block;
- __aligned(64) SpinLock reset_state;
- __aligned(64) SpinLock linkedlist_mtx;
- __aligned(64) std::atomic<size_t> switch_block_threshold;
- __aligned(64) std::atomic<size_t> numRenderThreads;
-
-
- public:
-
-
- SharedLazyTessellationCache();
- ~SharedLazyTessellationCache();
-
- void getNextRenderThreadWorkState();
-
- __forceinline size_t maxAllocSize() const {
- return switch_block_threshold;
- }
-
- __forceinline size_t getCurrentIndex() { return localTime.load(); }
- __forceinline void addCurrentIndex(const size_t i=1) { localTime.fetch_add(i); }
-
- __forceinline size_t getTime(const size_t globalTime) {
- return localTime.load()+NUM_CACHE_SEGMENTS*globalTime;
- }
-
-
- __forceinline size_t lockThread (ThreadWorkState *const t_state, const ssize_t plus=1) { return t_state->counter.fetch_add(plus); }
- __forceinline size_t unlockThread(ThreadWorkState *const t_state, const ssize_t plus=-1) { assert(isLocked(t_state)); return t_state->counter.fetch_add(plus); }
-
- __forceinline bool isLocked(ThreadWorkState *const t_state) { return t_state->counter.load() != 0; }
-
- static __forceinline void lock () { sharedLazyTessellationCache.lockThread(threadState()); }
- static __forceinline void unlock() { sharedLazyTessellationCache.unlockThread(threadState()); }
- static __forceinline bool isLocked() { return sharedLazyTessellationCache.isLocked(threadState()); }
- static __forceinline size_t getState() { return threadState()->counter.load(); }
- static __forceinline void lockThreadLoop() { sharedLazyTessellationCache.lockThreadLoop(threadState()); }
-
- static __forceinline size_t getTCacheTime(const size_t globalTime) {
- return sharedLazyTessellationCache.getTime(globalTime);
- }
-
- /* per thread lock */
- __forceinline void lockThreadLoop (ThreadWorkState *const t_state)
- {
- while(1)
- {
- size_t lock = SharedLazyTessellationCache::sharedLazyTessellationCache.lockThread(t_state,1);
- if (unlikely(lock >= THREAD_BLOCK_ATOMIC_ADD))
- {
- /* lock failed wait until sync phase is over */
- sharedLazyTessellationCache.unlockThread(t_state,-1);
- sharedLazyTessellationCache.waitForUsersLessEqual(t_state,0);
- }
- else
- break;
- }
- }
-
- static __forceinline void* lookup(CacheEntry& entry, size_t globalTime)
- {
- const int64_t subdiv_patch_root_ref = entry.tag.get();
- CACHE_STATS(SharedTessellationCacheStats::cache_accesses++);
-
- if (likely(subdiv_patch_root_ref != 0))
- {
- const size_t subdiv_patch_root = (subdiv_patch_root_ref & REF_TAG_MASK) + (size_t)sharedLazyTessellationCache.getDataPtr();
- const size_t subdiv_patch_cache_index = extractCommitIndex(subdiv_patch_root_ref);
-
- if (likely( sharedLazyTessellationCache.validCacheIndex(subdiv_patch_cache_index,globalTime) ))
- {
- CACHE_STATS(SharedTessellationCacheStats::cache_hits++);
- return (void*) subdiv_patch_root;
- }
- }
- CACHE_STATS(SharedTessellationCacheStats::cache_misses++);
- return nullptr;
- }
-
- template<typename Constructor>
- static __forceinline auto lookup (CacheEntry& entry, size_t globalTime, const Constructor constructor, const bool before=false) -> decltype(constructor())
- {
- ThreadWorkState *t_state = SharedLazyTessellationCache::threadState();
-
- while (true)
- {
- sharedLazyTessellationCache.lockThreadLoop(t_state);
- void* patch = SharedLazyTessellationCache::lookup(entry,globalTime);
- if (patch) return (decltype(constructor())) patch;
-
- if (entry.mutex.try_lock())
- {
- if (!validTag(entry.tag,globalTime))
- {
- auto timeBefore = sharedLazyTessellationCache.getTime(globalTime);
- auto ret = constructor(); // thread is locked here!
- assert(ret);
- /* this should never return nullptr */
- auto timeAfter = sharedLazyTessellationCache.getTime(globalTime);
- auto time = before ? timeBefore : timeAfter;
- __memory_barrier();
- entry.tag = SharedLazyTessellationCache::Tag(ret,time);
- __memory_barrier();
- entry.mutex.unlock();
- return ret;
- }
- entry.mutex.unlock();
- }
- SharedLazyTessellationCache::sharedLazyTessellationCache.unlockThread(t_state);
- }
- }
-
- __forceinline bool validCacheIndex(const size_t i, const size_t globalTime)
- {
-#if FORCE_SIMPLE_FLUSH == 1
- return i == getTime(globalTime);
-#else
- return i+(NUM_CACHE_SEGMENTS-1) >= getTime(globalTime);
-#endif
- }
-
- static __forceinline bool validTime(const size_t oldtime, const size_t newTime)
- {
- return oldtime+(NUM_CACHE_SEGMENTS-1) >= newTime;
- }
-
-
- static __forceinline bool validTag(const Tag& tag, size_t globalTime)
- {
- const int64_t subdiv_patch_root_ref = tag.get();
- if (subdiv_patch_root_ref == 0) return false;
- const size_t subdiv_patch_cache_index = extractCommitIndex(subdiv_patch_root_ref);
- return sharedLazyTessellationCache.validCacheIndex(subdiv_patch_cache_index,globalTime);
- }
-
- void waitForUsersLessEqual(ThreadWorkState *const t_state,
- const unsigned int users);
-
- __forceinline size_t alloc(const size_t blocks)
- {
- if (unlikely(blocks >= switch_block_threshold))
- throw_RTCError(RTC_ERROR_INVALID_OPERATION,"allocation exceeds size of tessellation cache segment");
-
- assert(blocks < switch_block_threshold);
- size_t index = next_block.fetch_add(blocks);
- if (unlikely(index + blocks >= switch_block_threshold)) return (size_t)-1;
- return index;
- }
-
- static __forceinline void* malloc(const size_t bytes)
- {
- size_t block_index = -1;
- ThreadWorkState *const t_state = threadState();
- while (true)
- {
- block_index = sharedLazyTessellationCache.alloc((bytes+BLOCK_SIZE-1)/BLOCK_SIZE);
- if (block_index == (size_t)-1)
- {
- sharedLazyTessellationCache.unlockThread(t_state);
- sharedLazyTessellationCache.allocNextSegment();
- sharedLazyTessellationCache.lockThread(t_state);
- continue;
- }
- break;
- }
- return sharedLazyTessellationCache.getBlockPtr(block_index);
- }
-
- __forceinline void *getBlockPtr(const size_t block_index)
- {
- assert(block_index < maxBlocks);
- assert(data);
- assert(block_index*16 <= size);
- return (void*)&data[block_index*16];
- }
-
- __forceinline void* getDataPtr() { return data; }
- __forceinline size_t getNumUsedBytes() { return next_block * BLOCK_SIZE; }
- __forceinline size_t getMaxBlocks() { return maxBlocks; }
- __forceinline size_t getSize() { return size; }
-
- void allocNextSegment();
- void realloc(const size_t newSize);
-
- void reset();
-
- static SharedLazyTessellationCache sharedLazyTessellationCache;
- };
-}
diff --git a/thirdparty/embree-aarch64/patches/godot-changes.patch b/thirdparty/embree-aarch64/patches/godot-changes.patch
deleted file mode 100644
index 86fbf226d2..0000000000
--- a/thirdparty/embree-aarch64/patches/godot-changes.patch
+++ /dev/null
@@ -1,630 +0,0 @@
-diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_for.h b/thirdparty/embree-aarch64/common/algorithms/parallel_for.h
-index 76c6b740aa..51d296fb16 100644
---- a/thirdparty/embree-aarch64/common/algorithms/parallel_for.h
-+++ b/thirdparty/embree-aarch64/common/algorithms/parallel_for.h
-@@ -27,7 +27,10 @@ namespace embree
- func(r.begin());
- });
- if (!TaskScheduler::wait())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- }
- #elif defined(TASKING_GCD) && defined(BUILD_IOS)
-
-@@ -55,13 +58,19 @@ namespace embree
- func(i);
- },context);
- if (context.is_group_execution_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- #else
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- });
- if (tbb::task::self().is_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- #endif
-
- #elif defined(TASKING_PPL)
-@@ -81,7 +90,10 @@ namespace embree
- #if defined(TASKING_INTERNAL)
- TaskScheduler::spawn(first,last,minStepSize,func);
- if (!TaskScheduler::wait())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
-
- #elif defined(TASKING_GCD) && defined(BUILD_IOS)
-
-@@ -109,13 +121,19 @@ namespace embree
- func(range<Index>(r.begin(),r.end()));
- },context);
- if (context.is_group_execution_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- #else
- tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
- func(range<Index>(r.begin(),r.end()));
- });
- if (tbb::task::self().is_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- #endif
-
- #elif defined(TASKING_PPL)
-@@ -147,13 +165,19 @@ namespace embree
- func(i);
- },tbb::simple_partitioner(),context);
- if (context.is_group_execution_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- #else
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- },tbb::simple_partitioner());
- if (tbb::task::self().is_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- #endif
- }
-
-@@ -168,13 +192,19 @@ namespace embree
- func(i);
- },ap,context);
- if (context.is_group_execution_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- #else
- tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
- func(i);
- },ap);
- if (tbb::task::self().is_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task cancelled");
-+ abort();
-+ // -- GODOT end --
- #endif
- }
-
-diff --git a/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.h b/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.h
-index d444b6a2e4..0daf94e50e 100644
---- a/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.h
-+++ b/thirdparty/embree-aarch64/common/algorithms/parallel_reduce.h
-@@ -58,15 +58,19 @@ namespace embree
- const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
- [&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
- reduction,context);
-- if (context.is_group_execution_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // if (context.is_group_execution_cancelled())
-+ // throw std::runtime_error("task cancelled");
-+ // -- GODOT end --
- return v;
- #else
- const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
- [&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
- reduction);
-- if (tbb::task::self().is_cancelled())
-- throw std::runtime_error("task cancelled");
-+ // -- GODOT start --
-+ // if (tbb::task::self().is_cancelled())
-+ // throw std::runtime_error("task cancelled");
-+ // -- GODOT end --
- return v;
- #endif
- #else // TASKING_PPL
-diff --git a/thirdparty/embree-aarch64/common/lexers/stringstream.cpp b/thirdparty/embree-aarch64/common/lexers/stringstream.cpp
-index 7e7b9faef8..98dc80ad59 100644
---- a/thirdparty/embree-aarch64/common/lexers/stringstream.cpp
-+++ b/thirdparty/embree-aarch64/common/lexers/stringstream.cpp
-@@ -39,7 +39,10 @@ namespace embree
- std::vector<char> str; str.reserve(64);
- while (cin->peek() != EOF && !isSeparator(cin->peek())) {
- int c = cin->get();
-- if (!isValidChar(c)) throw std::runtime_error("invalid character "+std::string(1,c)+" in input");
-+ // -- GODOT start --
-+ // if (!isValidChar(c)) throw std::runtime_error("invalid character "+std::string(1,c)+" in input");
-+ if (!isValidChar(c)) abort();
-+ // -- GODOT end --
- str.push_back((char)c);
- }
- str.push_back(0);
-diff --git a/thirdparty/embree-aarch64/common/sys/alloc.cpp b/thirdparty/embree-aarch64/common/sys/alloc.cpp
-index 4e8928242e..12f143f131 100644
---- a/thirdparty/embree-aarch64/common/sys/alloc.cpp
-+++ b/thirdparty/embree-aarch64/common/sys/alloc.cpp
-@@ -21,7 +21,10 @@ namespace embree
- void* ptr = _mm_malloc(size,align);
-
- if (size != 0 && ptr == nullptr)
-- throw std::bad_alloc();
-+ // -- GODOT start --
-+ // throw std::bad_alloc();
-+ abort();
-+ // -- GODOT end --
-
- return ptr;
- }
-@@ -128,7 +131,10 @@ namespace embree
- /* fall back to 4k pages */
- int flags = MEM_COMMIT | MEM_RESERVE;
- char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
-- if (ptr == nullptr) throw std::bad_alloc();
-+ // -- GODOT start --
-+ // if (ptr == nullptr) throw std::bad_alloc();
-+ if (ptr == nullptr) abort();
-+ // -- GODOT end --
- hugepages = false;
- return ptr;
- }
-@@ -145,7 +151,10 @@ namespace embree
- return bytesOld;
-
- if (!VirtualFree((char*)ptr+bytesNew,bytesOld-bytesNew,MEM_DECOMMIT))
-- throw std::bad_alloc();
-+ // -- GODOT start --
-+ // throw std::bad_alloc();
-+ abort();
-+ // -- GODOT end --
-
- return bytesNew;
- }
-@@ -156,7 +165,10 @@ namespace embree
- return;
-
- if (!VirtualFree(ptr,0,MEM_RELEASE))
-- throw std::bad_alloc();
-+ // -- GODOT start --
-+ // throw std::bad_alloc();
-+ abort();
-+ // -- GODOT end --
- }
-
- void os_advise(void *ptr, size_t bytes)
-@@ -260,7 +272,10 @@ namespace embree
-
- /* fallback to 4k pages */
- void* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
-- if (ptr == MAP_FAILED) throw std::bad_alloc();
-+ // -- GODOT start --
-+ // if (ptr == MAP_FAILED) throw std::bad_alloc();
-+ if (ptr == MAP_FAILED) abort();
-+ // -- GODOT end --
- hugepages = false;
-
- /* advise huge page hint for THP */
-@@ -277,7 +292,10 @@ namespace embree
- return bytesOld;
-
- if (munmap((char*)ptr+bytesNew,bytesOld-bytesNew) == -1)
-- throw std::bad_alloc();
-+ // -- GODOT start --
-+ // throw std::bad_alloc();
-+ abort();
-+ // -- GODOT end --
-
- return bytesNew;
- }
-@@ -291,7 +309,10 @@ namespace embree
- const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
- bytes = (bytes+pageSize-1) & ~(pageSize-1);
- if (munmap(ptr,bytes) == -1)
-- throw std::bad_alloc();
-+ // -- GODOT start --
-+ // throw std::bad_alloc();
-+ abort();
-+ // -- GODOT end --
- }
-
- /* hint for transparent huge pages (THP) */
-diff --git a/thirdparty/embree-aarch64/common/sys/platform.h b/thirdparty/embree-aarch64/common/sys/platform.h
-index 7914eb7a52..737f14aa6e 100644
---- a/thirdparty/embree-aarch64/common/sys/platform.h
-+++ b/thirdparty/embree-aarch64/common/sys/platform.h
-@@ -174,11 +174,19 @@
- #define PRINT4(x,y,z,w) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << embree_endl
-
- #if defined(DEBUG) // only report file and line in debug mode
-+ // -- GODOT start --
-+ // #define THROW_RUNTIME_ERROR(str)
-+ // throw std::runtime_error(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
- #define THROW_RUNTIME_ERROR(str) \
-- throw std::runtime_error(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
-+ printf(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)), abort();
-+ // -- GODOT end --
- #else
-+ // -- GODOT start --
-+ // #define THROW_RUNTIME_ERROR(str)
-+ // throw std::runtime_error(str);
- #define THROW_RUNTIME_ERROR(str) \
-- throw std::runtime_error(str);
-+ abort();
-+ // -- GODOT end --
- #endif
-
- #define FATAL(x) THROW_RUNTIME_ERROR(x)
-diff --git a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.cpp b/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.cpp
-index 98d7fb9249..ebf656d1a0 100644
---- a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.cpp
-+++ b/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.cpp
-@@ -48,13 +48,15 @@ namespace embree
- {
- Task* prevTask = thread.task;
- thread.task = this;
-- try {
-- if (thread.scheduler->cancellingException == nullptr)
-+ // -- GODOT start --
-+ // try {
-+ // if (thread.scheduler->cancellingException == nullptr)
- closure->execute();
-- } catch (...) {
-- if (thread.scheduler->cancellingException == nullptr)
-- thread.scheduler->cancellingException = std::current_exception();
-- }
-+ // } catch (...) {
-+ // if (thread.scheduler->cancellingException == nullptr)
-+ // thread.scheduler->cancellingException = std::current_exception();
-+ // }
-+ // -- GODOT end --
- thread.task = prevTask;
- add_dependencies(-1);
- }
-@@ -297,8 +299,11 @@ namespace embree
- size_t threadIndex = allocThreadIndex();
- condition.wait(mutex, [&] () { return hasRootTask.load(); });
- mutex.unlock();
-- std::exception_ptr except = thread_loop(threadIndex);
-- if (except != nullptr) std::rethrow_exception(except);
-+ // -- GODOT start --
-+ // std::exception_ptr except = thread_loop(threadIndex);
-+ // if (except != nullptr) std::rethrow_exception(except);
-+ thread_loop(threadIndex);
-+ // -- GODOT end --
- }
-
- void TaskScheduler::reset() {
-@@ -330,7 +335,10 @@ namespace embree
- return thread->scheduler->cancellingException == nullptr;
- }
-
-- std::exception_ptr TaskScheduler::thread_loop(size_t threadIndex)
-+// -- GODOT start --
-+// std::exception_ptr TaskScheduler::thread_loop(size_t threadIndex)
-+ void TaskScheduler::thread_loop(size_t threadIndex)
-+// -- GODOT end --
- {
- /* allocate thread structure */
- std::unique_ptr<Thread> mthread(new Thread(threadIndex,this)); // too large for stack allocation
-@@ -353,9 +361,10 @@ namespace embree
- swapThread(oldThread);
-
- /* remember exception to throw */
-- std::exception_ptr except = nullptr;
-- if (cancellingException != nullptr) except = cancellingException;
--
-+ // -- GODOT start --
-+ // std::exception_ptr except = nullptr;
-+ // if (cancellingException != nullptr) except = cancellingException;
-+ // -- GODOT end --
- /* wait for all threads to terminate */
- threadCounter--;
- #if defined(__WIN32__)
-@@ -373,7 +382,10 @@ namespace embree
- yield();
- #endif
- }
-- return except;
-+ // -- GODOT start --
-+ // return except;
-+ return;
-+ // -- GODOT end --
- }
-
- bool TaskScheduler::steal_from_other_threads(Thread& thread)
-diff --git a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h b/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h
-index c2a9391aea..8bd70b2b8c 100644
---- a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h
-+++ b/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h
-@@ -123,7 +123,10 @@ namespace embree
- {
- size_t ofs = bytes + ((align - stackPtr) & (align-1));
- if (stackPtr + ofs > CLOSURE_STACK_SIZE)
-- throw std::runtime_error("closure stack overflow");
-+ // -- GODOT start --
-+ // throw std::runtime_error("closure stack overflow");
-+ abort();
-+ // -- GODOT end --
- stackPtr += ofs;
- return &stack[stackPtr-bytes];
- }
-@@ -132,7 +135,10 @@ namespace embree
- __forceinline void push_right(Thread& thread, const size_t size, const Closure& closure)
- {
- if (right >= TASK_STACK_SIZE)
-- throw std::runtime_error("task stack overflow");
-+ // -- GODOT start --
-+ // throw std::runtime_error("task stack overflow");
-+ abort();
-+ // -- GODOT end --
-
- /* allocate new task on right side of stack */
- size_t oldStackPtr = stackPtr;
-@@ -239,7 +245,10 @@ namespace embree
- void wait_for_threads(size_t threadCount);
-
- /*! thread loop for all worker threads */
-- std::exception_ptr thread_loop(size_t threadIndex);
-+ // -- GODOT start --
-+ // std::exception_ptr thread_loop(size_t threadIndex);
-+ void thread_loop(size_t threadIndex);
-+ // -- GODOT end --
-
- /*! steals a task from a different thread */
- bool steal_from_other_threads(Thread& thread);
-diff --git a/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.cpp b/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.cpp
-index 20cdd2d320..aa56035026 100644
---- a/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.cpp
-+++ b/thirdparty/embree-aarch64/kernels/bvh/bvh_statistics.cpp
-@@ -150,7 +150,10 @@ namespace embree
- }
- }
- else {
-- throw std::runtime_error("not supported node type in bvh_statistics");
-+ // -- GODOT start --
-+ // throw std::runtime_error("not supported node type in bvh_statistics");
-+ abort();
-+ // -- GODOT end --
- }
- return s;
- }
-diff --git a/thirdparty/embree-aarch64/kernels/common/rtcore.cpp b/thirdparty/embree-aarch64/kernels/common/rtcore.cpp
-index ee5c37b238..625fbf6d4f 100644
---- a/thirdparty/embree-aarch64/kernels/common/rtcore.cpp
-+++ b/thirdparty/embree-aarch64/kernels/common/rtcore.cpp
-@@ -230,7 +230,10 @@ RTC_NAMESPACE_BEGIN;
- if (quality != RTC_BUILD_QUALITY_LOW &&
- quality != RTC_BUILD_QUALITY_MEDIUM &&
- quality != RTC_BUILD_QUALITY_HIGH)
-- throw std::runtime_error("invalid build quality");
-+ // -- GODOT start --
-+ // throw std::runtime_error("invalid build quality");
-+ abort();
-+ // -- GODOT end --
- scene->setBuildQuality(quality);
- RTC_CATCH_END2(scene);
- }
-@@ -1383,7 +1386,10 @@ RTC_NAMESPACE_BEGIN;
- quality != RTC_BUILD_QUALITY_MEDIUM &&
- quality != RTC_BUILD_QUALITY_HIGH &&
- quality != RTC_BUILD_QUALITY_REFIT)
-- throw std::runtime_error("invalid build quality");
-+ // -- GODOT start --
-+ // throw std::runtime_error("invalid build quality");
-+ abort();
-+ // -- GODOT end --
- geometry->setBuildQuality(quality);
- RTC_CATCH_END2(geometry);
- }
-diff --git a/thirdparty/embree-aarch64/kernels/common/rtcore.h b/thirdparty/embree-aarch64/kernels/common/rtcore.h
-index 6583d12d57..4b070e122b 100644
---- a/thirdparty/embree-aarch64/kernels/common/rtcore.h
-+++ b/thirdparty/embree-aarch64/kernels/common/rtcore.h
-@@ -25,52 +25,58 @@ namespace embree
- #endif
-
- /*! Macros used in the rtcore API implementation */
--#define RTC_CATCH_BEGIN try {
-+// -- GODOT start --
-+// #define RTC_CATCH_BEGIN try {
-+#define RTC_CATCH_BEGIN
-
--#define RTC_CATCH_END(device) \
-- } catch (std::bad_alloc&) { \
-- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-- } catch (rtcore_error& e) { \
-- Device::process_error(device,e.error,e.what()); \
-- } catch (std::exception& e) { \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-- } catch (...) { \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-- }
-+// #define RTC_CATCH_END(device) \
-+// } catch (std::bad_alloc&) { \
-+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-+// } catch (rtcore_error& e) { \
-+// Device::process_error(device,e.error,e.what()); \
-+// } catch (std::exception& e) { \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-+// } catch (...) { \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-+// }
-+#define RTC_CATCH_END(device)
-
--#define RTC_CATCH_END2(scene) \
-- } catch (std::bad_alloc&) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-- } catch (rtcore_error& e) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,e.error,e.what()); \
-- } catch (std::exception& e) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-- } catch (...) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-- }
-+// #define RTC_CATCH_END2(scene) \
-+// } catch (std::bad_alloc&) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-+// } catch (rtcore_error& e) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,e.error,e.what()); \
-+// } catch (std::exception& e) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-+// } catch (...) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-+// }
-+#define RTC_CATCH_END2(scene)
-
--#define RTC_CATCH_END2_FALSE(scene) \
-- } catch (std::bad_alloc&) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-- return false; \
-- } catch (rtcore_error& e) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,e.error,e.what()); \
-- return false; \
-- } catch (std::exception& e) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-- return false; \
-- } catch (...) { \
-- Device* device = scene ? scene->device : nullptr; \
-- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-- return false; \
-- }
-+// #define RTC_CATCH_END2_FALSE(scene) \
-+// } catch (std::bad_alloc&) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
-+// return false; \
-+// } catch (rtcore_error& e) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,e.error,e.what()); \
-+// return false; \
-+// } catch (std::exception& e) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
-+// return false; \
-+// } catch (...) { \
-+// Device* device = scene ? scene->device : nullptr; \
-+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
-+// return false; \
-+// }
-+#define RTC_CATCH_END2_FALSE(scene) return false;
-+// -- GODOT end --
-
- #define RTC_VERIFY_HANDLE(handle) \
- if (handle == nullptr) { \
-@@ -97,28 +103,38 @@ namespace embree
- #define RTC_TRACE(x)
- #endif
-
-- /*! used to throw embree API errors */
-- struct rtcore_error : public std::exception
-- {
-- __forceinline rtcore_error(RTCError error, const std::string& str)
-- : error(error), str(str) {}
--
-- ~rtcore_error() throw() {}
--
-- const char* what () const throw () {
-- return str.c_str();
-- }
--
-- RTCError error;
-- std::string str;
-- };
-+// -- GODOT begin --
-+// /*! used to throw embree API errors */
-+// struct rtcore_error : public std::exception
-+// {
-+// __forceinline rtcore_error(RTCError error, const std::string& str)
-+// : error(error), str(str) {}
-+//
-+// ~rtcore_error() throw() {}
-+//
-+// const char* what () const throw () {
-+// return str.c_str();
-+// }
-+//
-+// RTCError error;
-+// std::string str;
-+// };
-+// -- GODOT end --
-
- #if defined(DEBUG) // only report file and line in debug mode
-+ // -- GODOT begin --
-+ // #define throw_RTCError(error,str) \
-+ // throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
- #define throw_RTCError(error,str) \
-- throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
-+ printf(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)), abort();
-+ // -- GODOT end --
- #else
-+ // -- GODOT begin --
-+ // #define throw_RTCError(error,str) \
-+ // throw rtcore_error(error,str);
- #define throw_RTCError(error,str) \
-- throw rtcore_error(error,str);
-+ abort();
-+ // -- GODOT end --
- #endif
-
- #define RTC_BUILD_ARGUMENTS_HAS(settings,member) \
-diff --git a/thirdparty/embree-aarch64/kernels/common/scene.cpp b/thirdparty/embree-aarch64/kernels/common/scene.cpp
-index e75aa968f9..1e23aeb415 100644
---- a/thirdparty/embree-aarch64/kernels/common/scene.cpp
-+++ b/thirdparty/embree-aarch64/kernels/common/scene.cpp
-@@ -800,16 +800,18 @@ namespace embree
- }
-
- /* initiate build */
-- try {
-+ // -- GODOT start --
-+ // try {
- scheduler->spawn_root([&]() { commit_task(); Lock<MutexSys> lock(schedulerMutex); this->scheduler = nullptr; }, 1, !join);
-- }
-- catch (...) {
-- accels_clear();
-- updateInterface();
-- Lock<MutexSys> lock(schedulerMutex);
-- this->scheduler = nullptr;
-- throw;
-- }
-+ // }
-+ // catch (...) {
-+ // accels_clear();
-+ // updateInterface();
-+ // Lock<MutexSys> lock(schedulerMutex);
-+ // this->scheduler = nullptr;
-+ // throw;
-+ // }
-+ // -- GODOT end --
- }
-
- #endif
diff --git a/thirdparty/embree/common/algorithms/parallel_any_of.h b/thirdparty/embree/common/algorithms/parallel_any_of.h
new file mode 100644
index 0000000000..a64e4a1889
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_any_of.h
@@ -0,0 +1,55 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <functional>
+#include "parallel_reduce.h"
+
+namespace embree
+{
+
+ template<typename Index, class UnaryPredicate>
+ __forceinline bool parallel_any_of (Index first, Index last, UnaryPredicate pred)
+ {
+ bool ret = false;
+
+#if defined(TASKING_TBB)
+#if TBB_INTERFACE_VERSION >= 12002
+ tbb::task_group_context context;
+ tbb::parallel_for(tbb::blocked_range<size_t>{first, last}, [&ret,pred,&context](const tbb::blocked_range<size_t>& r) {
+ if (context.is_group_execution_cancelled()) return;
+ for (size_t i = r.begin(); i != r.end(); ++i) {
+ if (pred(i)) {
+ ret = true;
+ context.cancel_group_execution();
+ }
+ }
+ });
+#else
+ tbb::parallel_for(tbb::blocked_range<size_t>{first, last}, [&ret,pred](const tbb::blocked_range<size_t>& r) {
+ if (tbb::task::self().is_cancelled()) return;
+ for (size_t i = r.begin(); i != r.end(); ++i) {
+ if (pred(i)) {
+ ret = true;
+ tbb::task::self().cancel_group_execution();
+ }
+ }
+ });
+#endif
+#else
+ ret = parallel_reduce (first, last, false, [pred](const range<size_t>& r)->bool {
+ bool localret = false;
+ for (auto i=r.begin(); i<r.end(); ++i) {
+ localret |= pred(i);
+ }
+ return localret;
+ },
+ std::bit_or<bool>()
+ );
+#endif
+
+ return ret;
+ }
+
+} // end namespace
diff --git a/thirdparty/embree/common/algorithms/parallel_filter.h b/thirdparty/embree/common/algorithms/parallel_filter.h
new file mode 100644
index 0000000000..090ef164c2
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_filter.h
@@ -0,0 +1,93 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "parallel_for.h"
+
+namespace embree
+{
+ template<typename Ty, typename Index, typename Predicate>
+ inline Index sequential_filter( Ty* data, const Index first, const Index last, const Predicate& predicate)
+ {
+ Index j = first;
+ for (Index i=first; i<last; i++)
+ if (predicate(data[i]))
+ data[j++] = data[i];
+
+ return j;
+ }
+
+ template<typename Ty, typename Index, typename Predicate>
+ inline Index parallel_filter( Ty* data, const Index begin, const Index end, const Index minStepSize, const Predicate& predicate)
+ {
+ /* sequential fallback */
+ if (end-begin <= minStepSize)
+ return sequential_filter(data,begin,end,predicate);
+
+ /* calculate number of tasks to use */
+ enum { MAX_TASKS = 64 };
+ const Index numThreads = TaskScheduler::threadCount();
+ const Index numBlocks = (end-begin+minStepSize-1)/minStepSize;
+ const Index taskCount = min(numThreads,numBlocks,(Index)MAX_TASKS);
+
+ /* filter blocks */
+ Index nused[MAX_TASKS];
+ Index nfree[MAX_TASKS];
+ parallel_for(taskCount, [&](const Index taskIndex)
+ {
+ const Index i0 = begin+(taskIndex+0)*(end-begin)/taskCount;
+ const Index i1 = begin+(taskIndex+1)*(end-begin)/taskCount;
+ const Index i2 = sequential_filter(data,i0,i1,predicate);
+ nused[taskIndex] = i2-i0;
+ nfree[taskIndex] = i1-i2;
+ });
+
+ /* calculate offsets */
+ Index sused=0;
+ Index sfree=0;
+ Index pfree[MAX_TASKS];
+ for (Index i=0; i<taskCount; i++)
+ {
+ sused+=nused[i];
+ Index cfree = nfree[i]; pfree[i] = sfree; sfree+=cfree;
+ }
+
+ /* return if we did not filter out any element */
+ assert(sfree <= end-begin);
+ assert(sused <= end-begin);
+ if (sused == end-begin)
+ return end;
+
+ /* otherwise we have to copy misplaced elements around */
+ parallel_for(taskCount, [&](const Index taskIndex)
+ {
+ /* destination to write elements to */
+ Index dst = begin+(taskIndex+0)*(end-begin)/taskCount+nused[taskIndex];
+ Index dst_end = min(dst+nfree[taskIndex],begin+sused);
+ if (dst_end <= dst) return;
+
+ /* range of misplaced elements to copy to destination */
+ Index r0 = pfree[taskIndex];
+ Index r1 = r0+dst_end-dst;
+
+ /* find range in misplaced elements in back to front order */
+ Index k0=0;
+ for (Index i=taskCount-1; i>0; i--)
+ {
+ if (k0 > r1) break;
+ Index k1 = k0+nused[i];
+ Index src = begin+(i+0)*(end-begin)/taskCount+nused[i];
+ for (Index i=max(r0,k0); i<min(r1,k1); i++) {
+ Index isrc = src-i+k0-1;
+ assert(dst >= begin && dst < end);
+ assert(isrc >= begin && isrc < end);
+ data[dst++] = data[isrc];
+ }
+ k0 = k1;
+ }
+ });
+
+ return begin+sused;
+ }
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_for.h b/thirdparty/embree/common/algorithms/parallel_for.h
new file mode 100644
index 0000000000..645681ac63
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_for.h
@@ -0,0 +1,186 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../tasking/taskscheduler.h"
+#include "../sys/array.h"
+#include "../math/math.h"
+#include "../math/range.h"
+
+namespace embree
+{
+ /* parallel_for without range */
+ template<typename Index, typename Func>
+ __forceinline void parallel_for( const Index N, const Func& func)
+ {
+#if defined(TASKING_INTERNAL)
+ if (N) {
+ TaskScheduler::spawn(Index(0),N,Index(1),[&] (const range<Index>& r) {
+ assert(r.size() == 1);
+ func(r.begin());
+ });
+ if (!TaskScheduler::wait())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ }
+
+#elif defined(TASKING_TBB)
+ #if TBB_INTERFACE_VERSION >= 12002
+ tbb::task_group_context context;
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ },context);
+ if (context.is_group_execution_cancelled())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ #else
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ });
+ if (tbb::task::self().is_cancelled())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ #endif
+
+#elif defined(TASKING_PPL)
+ concurrency::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ });
+#else
+# error "no tasking system enabled"
+#endif
+ }
+
+ /* parallel for with range and granulatity */
+ template<typename Index, typename Func>
+ __forceinline void parallel_for( const Index first, const Index last, const Index minStepSize, const Func& func)
+ {
+ assert(first <= last);
+#if defined(TASKING_INTERNAL)
+ TaskScheduler::spawn(first,last,minStepSize,func);
+ if (!TaskScheduler::wait())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+
+#elif defined(TASKING_TBB)
+ #if TBB_INTERFACE_VERSION >= 12002
+ tbb::task_group_context context;
+ tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
+ func(range<Index>(r.begin(),r.end()));
+ },context);
+ if (context.is_group_execution_cancelled())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ #else
+ tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
+ func(range<Index>(r.begin(),r.end()));
+ });
+ if (tbb::task::self().is_cancelled())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ #endif
+
+#elif defined(TASKING_PPL)
+ concurrency::parallel_for(first, last, Index(1) /*minStepSize*/, [&](Index i) {
+ func(range<Index>(i,i+1));
+ });
+
+#else
+# error "no tasking system enabled"
+#endif
+ }
+
+ /* parallel for with range */
+ template<typename Index, typename Func>
+ __forceinline void parallel_for( const Index first, const Index last, const Func& func)
+ {
+ assert(first <= last);
+ parallel_for(first,last,(Index)1,func);
+ }
+
+#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION > 4001)
+
+ template<typename Index, typename Func>
+ __forceinline void parallel_for_static( const Index N, const Func& func)
+ {
+ #if TBB_INTERFACE_VERSION >= 12002
+ tbb::task_group_context context;
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ },tbb::simple_partitioner(),context);
+ if (context.is_group_execution_cancelled())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ #else
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ },tbb::simple_partitioner());
+ if (tbb::task::self().is_cancelled())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ #endif
+ }
+
+ typedef tbb::affinity_partitioner affinity_partitioner;
+
+ template<typename Index, typename Func>
+ __forceinline void parallel_for_affinity( const Index N, const Func& func, tbb::affinity_partitioner& ap)
+ {
+ #if TBB_INTERFACE_VERSION >= 12002
+ tbb::task_group_context context;
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ },ap,context);
+ if (context.is_group_execution_cancelled())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ #else
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ },ap);
+ if (tbb::task::self().is_cancelled())
+ // -- GODOT start --
+ // throw std::runtime_error("task cancelled");
+ abort();
+ // -- GODOT end --
+ #endif
+ }
+
+#else
+
+ template<typename Index, typename Func>
+ __forceinline void parallel_for_static( const Index N, const Func& func)
+ {
+ parallel_for(N,func);
+ }
+
+ struct affinity_partitioner {
+ };
+
+ template<typename Index, typename Func>
+ __forceinline void parallel_for_affinity( const Index N, const Func& func, affinity_partitioner& ap)
+ {
+ parallel_for(N,func);
+ }
+
+#endif
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_for_for.h b/thirdparty/embree/common/algorithms/parallel_for_for.h
new file mode 100644
index 0000000000..92c37a4a38
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_for_for.h
@@ -0,0 +1,149 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "parallel_for.h"
+
+namespace embree
+{
+ template<typename ArrayArray, typename Func>
+ __forceinline void sequential_for_for( ArrayArray& array2, const size_t minStepSize, const Func& func )
+ {
+ size_t k=0;
+ for (size_t i=0; i!=array2.size(); ++i) {
+ const size_t N = array2[i]->size();
+ if (N) func(array2[i],range<size_t>(0,N),k);
+ k+=N;
+ }
+ }
+
+ class ParallelForForState
+ {
+ public:
+
+ enum { MAX_TASKS = 64 };
+
+ __forceinline ParallelForForState ()
+ : taskCount(0) {}
+
+ template<typename ArrayArray>
+ __forceinline ParallelForForState (ArrayArray& array2, const size_t minStepSize) {
+ init(array2,minStepSize);
+ }
+
+ template<typename ArrayArray>
+ __forceinline void init ( ArrayArray& array2, const size_t minStepSize )
+ {
+ /* first calculate total number of elements */
+ size_t N = 0;
+ for (size_t i=0; i<array2.size(); i++) {
+ N += array2[i] ? array2[i]->size() : 0;
+ }
+ this->N = N;
+
+ /* calculate number of tasks to use */
+ const size_t numThreads = TaskScheduler::threadCount();
+ const size_t numBlocks = (N+minStepSize-1)/minStepSize;
+ taskCount = max(size_t(1),min(numThreads,numBlocks,size_t(ParallelForForState::MAX_TASKS)));
+
+ /* calculate start (i,j) for each task */
+ size_t taskIndex = 0;
+ i0[taskIndex] = 0;
+ j0[taskIndex] = 0;
+ size_t k0 = (++taskIndex)*N/taskCount;
+ for (size_t i=0, k=0; taskIndex < taskCount; i++)
+ {
+ assert(i<array2.size());
+ size_t j=0, M = array2[i] ? array2[i]->size() : 0;
+ while (j<M && k+M-j >= k0 && taskIndex < taskCount) {
+ assert(taskIndex<taskCount);
+ i0[taskIndex] = i;
+ j0[taskIndex] = j += k0-k;
+ k=k0;
+ k0 = (++taskIndex)*N/taskCount;
+ }
+ k+=M-j;
+ }
+ }
+
+ __forceinline size_t size() const {
+ return N;
+ }
+
+ public:
+ size_t i0[MAX_TASKS];
+ size_t j0[MAX_TASKS];
+ size_t taskCount;
+ size_t N;
+ };
+
+ template<typename ArrayArray, typename Func>
+ __forceinline void parallel_for_for( ArrayArray& array2, const size_t minStepSize, const Func& func )
+ {
+ ParallelForForState state(array2,minStepSize);
+
+ parallel_for(state.taskCount, [&](const size_t taskIndex)
+ {
+ /* calculate range */
+ const size_t k0 = (taskIndex+0)*state.size()/state.taskCount;
+ const size_t k1 = (taskIndex+1)*state.size()/state.taskCount;
+ size_t i0 = state.i0[taskIndex];
+ size_t j0 = state.j0[taskIndex];
+
+ /* iterate over arrays */
+ size_t k=k0;
+ for (size_t i=i0; k<k1; i++) {
+ const size_t N = array2[i] ? array2[i]->size() : 0;
+ const size_t r0 = j0, r1 = min(N,r0+k1-k);
+ if (r1 > r0) func(array2[i],range<size_t>(r0,r1),k);
+ k+=r1-r0; j0 = 0;
+ }
+ });
+ }
+
+ template<typename ArrayArray, typename Func>
+ __forceinline void parallel_for_for( ArrayArray& array2, const Func& func )
+ {
+ parallel_for_for(array2,1,func);
+ }
+
+ template<typename ArrayArray, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_reduce( ArrayArray& array2, const size_t minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+ ParallelForForState state(array2,minStepSize);
+ Value temp[ParallelForForState::MAX_TASKS];
+
+ for (size_t i=0; i<state.taskCount; i++)
+ temp[i] = identity;
+
+ parallel_for(state.taskCount, [&](const size_t taskIndex)
+ {
+ /* calculate range */
+ const size_t k0 = (taskIndex+0)*state.size()/state.taskCount;
+ const size_t k1 = (taskIndex+1)*state.size()/state.taskCount;
+ size_t i0 = state.i0[taskIndex];
+ size_t j0 = state.j0[taskIndex];
+
+ /* iterate over arrays */
+ size_t k=k0;
+ for (size_t i=i0; k<k1; i++) {
+ const size_t N = array2[i] ? array2[i]->size() : 0;
+ const size_t r0 = j0, r1 = min(N,r0+k1-k);
+ if (r1 > r0) temp[taskIndex] = reduction(temp[taskIndex],func(array2[i],range<size_t>(r0,r1),k));
+ k+=r1-r0; j0 = 0;
+ }
+ });
+
+ Value ret = identity;
+ for (size_t i=0; i<state.taskCount; i++)
+ ret = reduction(ret,temp[i]);
+ return ret;
+ }
+
+ template<typename ArrayArray, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_reduce( ArrayArray& array2, const Value& identity, const Func& func, const Reduction& reduction)
+ {
+ return parallel_for_for_reduce(array2,1,identity,func,reduction);
+ }
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h b/thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h
new file mode 100644
index 0000000000..b15b44a991
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_for_for_prefix_sum.h
@@ -0,0 +1,112 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "parallel_for_for.h"
+#include "parallel_prefix_sum.h"
+
+namespace embree
+{
+ template<typename Value>
+ struct ParallelForForPrefixSumState : public ParallelForForState
+ {
+ __forceinline ParallelForForPrefixSumState () {}
+
+ template<typename ArrayArray>
+ __forceinline ParallelForForPrefixSumState (ArrayArray& array2, const size_t minStepSize)
+ : ParallelForForState(array2,minStepSize) {}
+
+ ParallelPrefixSumState<Value> prefix_state;
+ };
+
+ template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2, Index minStepSize,
+ const Value& identity, const Func& func, const Reduction& reduction)
+ {
+ /* calculate number of tasks to use */
+ const size_t taskCount = state.taskCount;
+ /* perform parallel prefix sum */
+ parallel_for(taskCount, [&](const size_t taskIndex)
+ {
+ const size_t k0 = (taskIndex+0)*state.size()/taskCount;
+ const size_t k1 = (taskIndex+1)*state.size()/taskCount;
+ size_t i0 = state.i0[taskIndex];
+ size_t j0 = state.j0[taskIndex];
+
+ /* iterate over arrays */
+ size_t k=k0;
+ Value N=identity;
+ for (size_t i=i0; k<k1; i++) {
+ const size_t size = array2[i] ? array2[i]->size() : 0;
+ const size_t r0 = j0, r1 = min(size,r0+k1-k);
+ if (r1 > r0) N = reduction(N, func(array2[i],range<Index>((Index)r0,(Index)r1),(Index)k,(Index)i));
+ k+=r1-r0; j0 = 0;
+ }
+ state.prefix_state.counts[taskIndex] = N;
+ });
+
+ /* calculate prefix sum */
+ Value sum=identity;
+ for (size_t i=0; i<taskCount; i++)
+ {
+ const Value c = state.prefix_state.counts[i];
+ state.prefix_state.sums[i] = sum;
+ sum=reduction(sum,c);
+ }
+
+ return sum;
+ }
+
+ template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2, Index minStepSize,
+ const Value& identity, const Func& func, const Reduction& reduction)
+ {
+ /* calculate number of tasks to use */
+ const size_t taskCount = state.taskCount;
+ /* perform parallel prefix sum */
+ parallel_for(taskCount, [&](const size_t taskIndex)
+ {
+ const size_t k0 = (taskIndex+0)*state.size()/taskCount;
+ const size_t k1 = (taskIndex+1)*state.size()/taskCount;
+ size_t i0 = state.i0[taskIndex];
+ size_t j0 = state.j0[taskIndex];
+
+ /* iterate over arrays */
+ size_t k=k0;
+ Value N=identity;
+ for (size_t i=i0; k<k1; i++) {
+ const size_t size = array2[i] ? array2[i]->size() : 0;
+ const size_t r0 = j0, r1 = min(size,r0+k1-k);
+ if (r1 > r0) N = reduction(N, func(array2[i],range<Index>((Index)r0,(Index)r1),(Index)k,(Index)i,reduction(state.prefix_state.sums[taskIndex],N)));
+ k+=r1-r0; j0 = 0;
+ }
+ state.prefix_state.counts[taskIndex] = N;
+ });
+
+ /* calculate prefix sum */
+ Value sum=identity;
+ for (size_t i=0; i<taskCount; i++)
+ {
+ const Value c = state.prefix_state.counts[i];
+ state.prefix_state.sums[i] = sum;
+ sum=reduction(sum,c);
+ }
+
+ return sum;
+ }
+
+ template<typename ArrayArray, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2,
+ const Value& identity, const Func& func, const Reduction& reduction)
+ {
+ return parallel_for_for_prefix_sum0(state,array2,size_t(1),identity,func,reduction);
+ }
+
+ template<typename ArrayArray, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2,
+ const Value& identity, const Func& func, const Reduction& reduction)
+ {
+ return parallel_for_for_prefix_sum1(state,array2,size_t(1),identity,func,reduction);
+ }
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_map.h b/thirdparty/embree/common/algorithms/parallel_map.h
new file mode 100644
index 0000000000..15c098fe20
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_map.h
@@ -0,0 +1,85 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "parallel_sort.h"
+
+namespace embree
+{
+ /*! implementation of a key/value map with parallel construction */
+ template<typename Key, typename Val>
+ class parallel_map
+ {
+ /* key/value pair to build the map */
+ struct KeyValue
+ {
+ __forceinline KeyValue () {}
+
+ __forceinline KeyValue (const Key key, const Val val)
+ : key(key), val(val) {}
+
+ __forceinline operator Key() const {
+ return key;
+ }
+
+ public:
+ Key key;
+ Val val;
+ };
+
+ public:
+
+ /*! parallel map constructors */
+ parallel_map () {}
+
+ /*! construction from pair of vectors */
+ template<typename KeyVector, typename ValVector>
+ parallel_map (const KeyVector& keys, const ValVector& values) { init(keys,values); }
+
+ /*! initialized the parallel map from a vector with keys and values */
+ template<typename KeyVector, typename ValVector>
+ void init(const KeyVector& keys, const ValVector& values)
+ {
+ /* reserve sufficient space for all data */
+ assert(keys.size() == values.size());
+ vec.resize(keys.size());
+
+ /* generate key/value pairs */
+ parallel_for( size_t(0), keys.size(), size_t(4*4096), [&](const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++)
+ vec[i] = KeyValue((Key)keys[i],values[i]);
+ });
+
+ /* perform parallel radix sort of the key/value pairs */
+ std::vector<KeyValue> temp(keys.size());
+ radix_sort<KeyValue,Key>(vec.data(),temp.data(),keys.size());
+ }
+
+ /*! Returns a pointer to the value associated with the specified key. The pointer will be nullptr of the key is not contained in the map. */
+ __forceinline const Val* lookup(const Key& key) const
+ {
+ typename std::vector<KeyValue>::const_iterator i = std::lower_bound(vec.begin(), vec.end(), key);
+ if (i == vec.end()) return nullptr;
+ if (i->key != key) return nullptr;
+ return &i->val;
+ }
+
+ /*! If the key is in the map, the function returns the value associated with the key, otherwise it returns the default value. */
+ __forceinline Val lookup(const Key& key, const Val& def) const
+ {
+ typename std::vector<KeyValue>::const_iterator i = std::lower_bound(vec.begin(), vec.end(), key);
+ if (i == vec.end()) return def;
+ if (i->key != key) return def;
+ return i->val;
+ }
+
+ /*! clears all state */
+ void clear() {
+ vec.clear();
+ }
+
+ private:
+ std::vector<KeyValue> vec; //!< vector containing sorted elements
+ };
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_partition.h b/thirdparty/embree/common/algorithms/parallel_partition.h
new file mode 100644
index 0000000000..a1cbdc8e04
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_partition.h
@@ -0,0 +1,283 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "parallel_for.h"
+#include "../math/range.h"
+
+namespace embree
+{
+ /* serial partitioning */
+ template<typename T, typename V, typename IsLeft, typename Reduction_T>
+ __forceinline size_t serial_partitioning(T* array,
+ const size_t begin,
+ const size_t end,
+ V& leftReduction,
+ V& rightReduction,
+ const IsLeft& is_left,
+ const Reduction_T& reduction_t)
+ {
+ T* l = array + begin;
+ T* r = array + end - 1;
+
+ while(1)
+ {
+ /* *l < pivot */
+ while (likely(l <= r && is_left(*l) ))
+ {
+ //prefetchw(l+4); // FIXME: enable?
+ reduction_t(leftReduction,*l);
+ ++l;
+ }
+ /* *r >= pivot) */
+ while (likely(l <= r && !is_left(*r)))
+ {
+ //prefetchw(r-4); FIXME: enable?
+ reduction_t(rightReduction,*r);
+ --r;
+ }
+ if (r<l) break;
+
+ reduction_t(leftReduction ,*r);
+ reduction_t(rightReduction,*l);
+ xchg(*l,*r);
+ l++; r--;
+ }
+
+ return l - array;
+ }
+
+ template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
+ class __aligned(64) parallel_partition_task
+ {
+ ALIGNED_CLASS_(64);
+ private:
+
+ static const size_t MAX_TASKS = 64;
+
+ T* array;
+ size_t N;
+ const IsLeft& is_left;
+ const Reduction_T& reduction_t;
+ const Reduction_V& reduction_v;
+ const Vi& identity;
+
+ size_t numTasks;
+ __aligned(64) size_t counter_start[MAX_TASKS+1];
+ __aligned(64) size_t counter_left[MAX_TASKS+1];
+ __aligned(64) range<ssize_t> leftMisplacedRanges[MAX_TASKS];
+ __aligned(64) range<ssize_t> rightMisplacedRanges[MAX_TASKS];
+ __aligned(64) V leftReductions[MAX_TASKS];
+ __aligned(64) V rightReductions[MAX_TASKS];
+
+ public:
+
+ __forceinline parallel_partition_task(T* array,
+ const size_t N,
+ const Vi& identity,
+ const IsLeft& is_left,
+ const Reduction_T& reduction_t,
+ const Reduction_V& reduction_v,
+ const size_t BLOCK_SIZE)
+
+ : array(array), N(N), is_left(is_left), reduction_t(reduction_t), reduction_v(reduction_v), identity(identity),
+ numTasks(min((N+BLOCK_SIZE-1)/BLOCK_SIZE,min(TaskScheduler::threadCount(),MAX_TASKS))) {}
+
+ __forceinline const range<ssize_t>* findStartRange(size_t& index, const range<ssize_t>* const r, const size_t numRanges)
+ {
+ size_t i = 0;
+ while(index >= (size_t)r[i].size())
+ {
+ assert(i < numRanges);
+ index -= (size_t)r[i].size();
+ i++;
+ }
+ return &r[i];
+ }
+
+ __forceinline void swapItemsInMisplacedRanges(const size_t numLeftMisplacedRanges,
+ const size_t numRightMisplacedRanges,
+ const size_t startID,
+ const size_t endID)
+ {
+ size_t leftLocalIndex = startID;
+ size_t rightLocalIndex = startID;
+ const range<ssize_t>* l_range = findStartRange(leftLocalIndex,leftMisplacedRanges,numLeftMisplacedRanges);
+ const range<ssize_t>* r_range = findStartRange(rightLocalIndex,rightMisplacedRanges,numRightMisplacedRanges);
+
+ size_t l_left = l_range->size() - leftLocalIndex;
+ size_t r_left = r_range->size() - rightLocalIndex;
+ T *__restrict__ l = &array[l_range->begin() + leftLocalIndex];
+ T *__restrict__ r = &array[r_range->begin() + rightLocalIndex];
+ size_t size = endID - startID;
+ size_t items = min(size,min(l_left,r_left));
+
+ while (size)
+ {
+ if (unlikely(l_left == 0))
+ {
+ l_range++;
+ l_left = l_range->size();
+ l = &array[l_range->begin()];
+ items = min(size,min(l_left,r_left));
+ }
+
+ if (unlikely(r_left == 0))
+ {
+ r_range++;
+ r_left = r_range->size();
+ r = &array[r_range->begin()];
+ items = min(size,min(l_left,r_left));
+ }
+
+ size -= items;
+ l_left -= items;
+ r_left -= items;
+
+ while(items) {
+ items--;
+ xchg(*l++,*r++);
+ }
+ }
+ }
+
+ __forceinline size_t partition(V& leftReduction, V& rightReduction)
+ {
+ /* partition the individual ranges for each task */
+ parallel_for(numTasks,[&] (const size_t taskID) {
+ const size_t startID = (taskID+0)*N/numTasks;
+ const size_t endID = (taskID+1)*N/numTasks;
+ V local_left(identity);
+ V local_right(identity);
+ const size_t mid = serial_partitioning(array,startID,endID,local_left,local_right,is_left,reduction_t);
+ counter_start[taskID] = startID;
+ counter_left [taskID] = mid-startID;
+ leftReductions[taskID] = local_left;
+ rightReductions[taskID] = local_right;
+ });
+ counter_start[numTasks] = N;
+ counter_left[numTasks] = 0;
+
+ /* finalize the reductions */
+ for (size_t i=0; i<numTasks; i++) {
+ reduction_v(leftReduction,leftReductions[i]);
+ reduction_v(rightReduction,rightReductions[i]);
+ }
+
+ /* calculate mid point for partitioning */
+ size_t mid = counter_left[0];
+ for (size_t i=1; i<numTasks; i++)
+ mid += counter_left[i];
+ const range<ssize_t> globalLeft (0,mid);
+ const range<ssize_t> globalRight(mid,N);
+
+ /* calculate all left and right ranges that are on the wrong global side */
+ size_t numMisplacedRangesLeft = 0;
+ size_t numMisplacedRangesRight = 0;
+ size_t numMisplacedItemsLeft = 0;
+ size_t numMisplacedItemsRight = 0;
+
+ for (size_t i=0; i<numTasks; i++)
+ {
+ const range<ssize_t> left_range (counter_start[i], counter_start[i] + counter_left[i]);
+ const range<ssize_t> right_range(counter_start[i] + counter_left[i], counter_start[i+1]);
+ const range<ssize_t> left_misplaced = globalLeft. intersect(right_range);
+ const range<ssize_t> right_misplaced = globalRight.intersect(left_range);
+
+ if (!left_misplaced.empty())
+ {
+ numMisplacedItemsLeft += left_misplaced.size();
+ leftMisplacedRanges[numMisplacedRangesLeft++] = left_misplaced;
+ }
+
+ if (!right_misplaced.empty())
+ {
+ numMisplacedItemsRight += right_misplaced.size();
+ rightMisplacedRanges[numMisplacedRangesRight++] = right_misplaced;
+ }
+ }
+ assert( numMisplacedItemsLeft == numMisplacedItemsRight );
+
+ /* if no items are misplaced we are done */
+ if (numMisplacedItemsLeft == 0)
+ return mid;
+
+ /* otherwise we copy the items to the right place in parallel */
+ parallel_for(numTasks,[&] (const size_t taskID) {
+ const size_t startID = (taskID+0)*numMisplacedItemsLeft/numTasks;
+ const size_t endID = (taskID+1)*numMisplacedItemsLeft/numTasks;
+ swapItemsInMisplacedRanges(numMisplacedRangesLeft,numMisplacedRangesRight,startID,endID);
+ });
+
+ return mid;
+ }
+ };
+
+ template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
+ __noinline size_t parallel_partitioning(T* array,
+ const size_t begin,
+ const size_t end,
+ const Vi &identity,
+ V &leftReduction,
+ V &rightReduction,
+ const IsLeft& is_left,
+ const Reduction_T& reduction_t,
+ const Reduction_V& reduction_v,
+ size_t BLOCK_SIZE = 128)
+ {
+ /* fall back to single threaded partitioning for small N */
+ if (unlikely(end-begin < BLOCK_SIZE))
+ return serial_partitioning(array,begin,end,leftReduction,rightReduction,is_left,reduction_t);
+
+ /* otherwise use parallel code */
+ else {
+ typedef parallel_partition_task<T,V,Vi,IsLeft,Reduction_T,Reduction_V> partition_task;
+ std::unique_ptr<partition_task> p(new partition_task(&array[begin],end-begin,identity,is_left,reduction_t,reduction_v,BLOCK_SIZE));
+ return begin+p->partition(leftReduction,rightReduction);
+ }
+ }
+
+ template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
+ __noinline size_t parallel_partitioning(T* array,
+ const size_t begin,
+ const size_t end,
+ const Vi &identity,
+ V &leftReduction,
+ V &rightReduction,
+ const IsLeft& is_left,
+ const Reduction_T& reduction_t,
+ const Reduction_V& reduction_v,
+ size_t BLOCK_SIZE,
+ size_t PARALLEL_THRESHOLD)
+ {
+ /* fall back to single threaded partitioning for small N */
+ if (unlikely(end-begin < PARALLEL_THRESHOLD))
+ return serial_partitioning(array,begin,end,leftReduction,rightReduction,is_left,reduction_t);
+
+ /* otherwise use parallel code */
+ else {
+ typedef parallel_partition_task<T,V,Vi,IsLeft,Reduction_T,Reduction_V> partition_task;
+ std::unique_ptr<partition_task> p(new partition_task(&array[begin],end-begin,identity,is_left,reduction_t,reduction_v,BLOCK_SIZE));
+ return begin+p->partition(leftReduction,rightReduction);
+ }
+ }
+
+
+ template<typename T, typename IsLeft>
+ inline size_t parallel_partitioning(T* array,
+ const size_t begin,
+ const size_t end,
+ const IsLeft& is_left,
+ size_t BLOCK_SIZE = 128)
+ {
+ size_t leftReduction = 0;
+ size_t rightReduction = 0;
+ return parallel_partitioning(
+ array,begin,end,0,leftReduction,rightReduction,is_left,
+ [] (size_t& t,const T& ref) { },
+ [] (size_t& t0,size_t& t1) { },
+ BLOCK_SIZE);
+ }
+
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_prefix_sum.h b/thirdparty/embree/common/algorithms/parallel_prefix_sum.h
new file mode 100644
index 0000000000..208bb4e480
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_prefix_sum.h
@@ -0,0 +1,85 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "parallel_for.h"
+
+namespace embree
+{
+ template<typename Value>
+ struct ParallelPrefixSumState
+ {
+ enum { MAX_TASKS = 64 };
+ Value counts[MAX_TASKS];
+ Value sums [MAX_TASKS];
+ };
+
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_prefix_sum( ParallelPrefixSumState<Value>& state, Index first, Index last, Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction)
+ {
+ /* calculate number of tasks to use */
+ const size_t numThreads = TaskScheduler::threadCount();
+ const size_t numBlocks = (last-first+minStepSize-1)/minStepSize;
+ const size_t taskCount = min(numThreads,numBlocks,size_t(ParallelPrefixSumState<Value>::MAX_TASKS));
+
+ /* perform parallel prefix sum */
+ parallel_for(taskCount, [&](const size_t taskIndex)
+ {
+ const size_t i0 = first+(taskIndex+0)*(last-first)/taskCount;
+ const size_t i1 = first+(taskIndex+1)*(last-first)/taskCount;
+ state.counts[taskIndex] = func(range<size_t>(i0,i1),state.sums[taskIndex]);
+ });
+
+ /* calculate prefix sum */
+ Value sum=identity;
+ for (size_t i=0; i<taskCount; i++)
+ {
+ const Value c = state.counts[i];
+ state.sums[i] = sum;
+ sum=reduction(sum,c);
+ }
+
+ return sum;
+ }
+
+ /*! parallel calculation of prefix sums */
+ template<typename SrcArray, typename DstArray, typename Value, typename Add>
+ __forceinline Value parallel_prefix_sum(const SrcArray& src, DstArray& dst, size_t N, const Value& identity, const Add& add, const size_t SINGLE_THREAD_THRESHOLD = 4096)
+ {
+ /* perform single threaded prefix operation for small N */
+ if (N < SINGLE_THREAD_THRESHOLD)
+ {
+ Value sum=identity;
+ for (size_t i=0; i<N; sum=add(sum,src[i++])) dst[i] = sum;
+ return sum;
+ }
+
+ /* perform parallel prefix operation for large N */
+ else
+ {
+ ParallelPrefixSumState<Value> state;
+
+ /* initial run just sets up start values for subtasks */
+ parallel_prefix_sum( state, size_t(0), size_t(N), size_t(1024), identity, [&](const range<size_t>& r, const Value& sum) -> Value {
+
+ Value s = identity;
+ for (size_t i=r.begin(); i<r.end(); i++) s = add(s,src[i]);
+ return s;
+
+ }, add);
+
+ /* final run calculates prefix sum */
+ return parallel_prefix_sum( state, size_t(0), size_t(N), size_t(1024), identity, [&](const range<size_t>& r, const Value& sum) -> Value {
+
+ Value s = identity;
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ dst[i] = add(sum,s);
+ s = add(s,src[i]);
+ }
+ return s;
+
+ }, add);
+ }
+ }
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_reduce.h b/thirdparty/embree/common/algorithms/parallel_reduce.h
new file mode 100644
index 0000000000..8271372ea4
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_reduce.h
@@ -0,0 +1,150 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "parallel_for.h"
+
+namespace embree
+{
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value sequential_reduce( const Index first, const Index last, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+ return func(range<Index>(first,last));
+ }
+
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value sequential_reduce( const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+ return func(range<Index>(first,last));
+ }
+
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __noinline Value parallel_reduce_internal( Index taskCount, const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+ const Index maxTasks = 512;
+ const Index threadCount = (Index) TaskScheduler::threadCount();
+ taskCount = min(taskCount,threadCount,maxTasks);
+
+ /* parallel invokation of all tasks */
+ dynamic_large_stack_array(Value,values,taskCount,8192); // consumes at most 8192 bytes on the stack
+ parallel_for(taskCount, [&](const Index taskIndex) {
+ const Index k0 = first+(taskIndex+0)*(last-first)/taskCount;
+ const Index k1 = first+(taskIndex+1)*(last-first)/taskCount;
+ values[taskIndex] = func(range<Index>(k0,k1));
+ });
+
+ /* perform reduction over all tasks */
+ Value v = identity;
+ for (Index i=0; i<taskCount; i++) v = reduction(v,values[i]);
+ return v;
+ }
+
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_reduce( const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+#if defined(TASKING_INTERNAL)
+
+ /* fast path for small number of iterations */
+ Index taskCount = (last-first+minStepSize-1)/minStepSize;
+ if (likely(taskCount == 1)) {
+ return func(range<Index>(first,last));
+ }
+ return parallel_reduce_internal(taskCount,first,last,minStepSize,identity,func,reduction);
+
+#elif defined(TASKING_TBB)
+ #if TBB_INTERFACE_VERSION >= 12002
+ tbb::task_group_context context;
+ const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
+ [&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
+ reduction,context);
+ // -- GODOT start --
+ // if (context.is_group_execution_cancelled())
+ // throw std::runtime_error("task cancelled");
+ // -- GODOT end --
+ return v;
+ #else
+ const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
+ [&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
+ reduction);
+ // -- GODOT start --
+ // if (tbb::task::self().is_cancelled())
+ // throw std::runtime_error("task cancelled");
+ // -- GODOT end --
+ return v;
+ #endif
+#else // TASKING_PPL
+ struct AlignedValue
+ {
+ char storage[__alignof(Value)+sizeof(Value)];
+ static uintptr_t alignUp(uintptr_t p, size_t a) { return p + (~(p - 1) % a); };
+ Value* getValuePtr() { return reinterpret_cast<Value*>(alignUp(uintptr_t(storage), __alignof(Value))); }
+ const Value* getValuePtr() const { return reinterpret_cast<Value*>(alignUp(uintptr_t(storage), __alignof(Value))); }
+ AlignedValue(const Value& v) { new(getValuePtr()) Value(v); }
+ AlignedValue(const AlignedValue& v) { new(getValuePtr()) Value(*v.getValuePtr()); }
+ AlignedValue(const AlignedValue&& v) { new(getValuePtr()) Value(*v.getValuePtr()); };
+ AlignedValue& operator = (const AlignedValue& v) { *getValuePtr() = *v.getValuePtr(); return *this; };
+ AlignedValue& operator = (const AlignedValue&& v) { *getValuePtr() = *v.getValuePtr(); return *this; };
+ operator Value() const { return *getValuePtr(); }
+ };
+
+ struct Iterator_Index
+ {
+ Index v;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef AlignedValue value_type;
+ typedef Index difference_type;
+ typedef Index distance_type;
+ typedef AlignedValue* pointer;
+ typedef AlignedValue& reference;
+ __forceinline Iterator_Index() {}
+ __forceinline Iterator_Index(Index v) : v(v) {}
+ __forceinline bool operator== (Iterator_Index other) { return v == other.v; }
+ __forceinline bool operator!= (Iterator_Index other) { return v != other.v; }
+ __forceinline Iterator_Index operator++() { return Iterator_Index(++v); }
+ __forceinline Iterator_Index operator++(int) { return Iterator_Index(v++); }
+ };
+
+ auto range_reduction = [&](Iterator_Index begin, Iterator_Index end, const AlignedValue& start) {
+ assert(begin.v < end.v);
+ return reduction(start, func(range<Index>(begin.v, end.v)));
+ };
+ const Value v = concurrency::parallel_reduce(Iterator_Index(first), Iterator_Index(last), AlignedValue(identity), range_reduction, reduction);
+ return v;
+#endif
+ }
+
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_reduce( const Index first, const Index last, const Index minStepSize, const Index parallel_threshold, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+ if (likely(last-first < parallel_threshold)) {
+ return func(range<Index>(first,last));
+ } else {
+ return parallel_reduce(first,last,minStepSize,identity,func,reduction);
+ }
+ }
+
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_reduce( const range<Index> range, const Index minStepSize, const Index parallel_threshold, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+ return parallel_reduce(range.begin(),range.end(),minStepSize,parallel_threshold,identity,func,reduction);
+ }
+
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_reduce( const Index first, const Index last, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+ auto funcr = [&] ( const range<Index> r ) {
+ Value v = identity;
+ for (Index i=r.begin(); i<r.end(); i++)
+ v = reduction(v,func(i));
+ return v;
+ };
+ return parallel_reduce(first,last,Index(1),identity,funcr,reduction);
+ }
+
+ template<typename Index, typename Value, typename Func, typename Reduction>
+ __forceinline Value parallel_reduce( const range<Index> range, const Value& identity, const Func& func, const Reduction& reduction )
+ {
+ return parallel_reduce(range.begin(),range.end(),Index(1),identity,func,reduction);
+ }
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_set.h b/thirdparty/embree/common/algorithms/parallel_set.h
new file mode 100644
index 0000000000..7eae577457
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_set.h
@@ -0,0 +1,52 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "parallel_sort.h"
+
+namespace embree
+{
+ /* implementation of a set of values with parallel construction */
+ template<typename T>
+ class parallel_set
+ {
+ public:
+
+ /*! default constructor for the parallel set */
+ parallel_set () {}
+
+ /*! construction from vector */
+ template<typename Vector>
+ parallel_set (const Vector& in) { init(in); }
+
+ /*! initialized the parallel set from a vector */
+ template<typename Vector>
+ void init(const Vector& in)
+ {
+ /* copy data to internal vector */
+ vec.resize(in.size());
+ parallel_for( size_t(0), in.size(), size_t(4*4096), [&](const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++)
+ vec[i] = in[i];
+ });
+
+ /* sort the data */
+ std::vector<T> temp(in.size());
+ radix_sort<T>(vec.data(),temp.data(),vec.size());
+ }
+
+ /*! tests if some element is in the set */
+ __forceinline bool lookup(const T& elt) const {
+ return std::binary_search(vec.begin(), vec.end(), elt);
+ }
+
+ /*! clears all state */
+ void clear() {
+ vec.clear();
+ }
+
+ private:
+ std::vector<T> vec; //!< vector containing sorted elements
+ };
+}
diff --git a/thirdparty/embree/common/algorithms/parallel_sort.h b/thirdparty/embree/common/algorithms/parallel_sort.h
new file mode 100644
index 0000000000..30e56c2bfc
--- /dev/null
+++ b/thirdparty/embree/common/algorithms/parallel_sort.h
@@ -0,0 +1,454 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../simd/simd.h"
+#include "parallel_for.h"
+#include <algorithm>
+
+namespace embree
+{
+ template<class T>
+ __forceinline void insertionsort_ascending(T *__restrict__ array, const size_t length)
+ {
+ for(size_t i = 1;i<length;++i)
+ {
+ T v = array[i];
+ size_t j = i;
+ while(j > 0 && v < array[j-1])
+ {
+ array[j] = array[j-1];
+ --j;
+ }
+ array[j] = v;
+ }
+ }
+
+ template<class T>
+ __forceinline void insertionsort_decending(T *__restrict__ array, const size_t length)
+ {
+ for(size_t i = 1;i<length;++i)
+ {
+ T v = array[i];
+ size_t j = i;
+ while(j > 0 && v > array[j-1])
+ {
+ array[j] = array[j-1];
+ --j;
+ }
+ array[j] = v;
+ }
+ }
+
+ template<class T>
+ void quicksort_ascending(T *__restrict__ t,
+ const ssize_t begin,
+ const ssize_t end)
+ {
+ if (likely(begin < end))
+ {
+ const T pivotvalue = t[begin];
+ ssize_t left = begin - 1;
+ ssize_t right = end + 1;
+
+ while(1)
+ {
+ while (t[--right] > pivotvalue);
+ while (t[++left] < pivotvalue);
+
+ if (left >= right) break;
+
+ const T temp = t[right];
+ t[right] = t[left];
+ t[left] = temp;
+ }
+
+ const int pivot = right;
+ quicksort_ascending(t, begin, pivot);
+ quicksort_ascending(t, pivot + 1, end);
+ }
+ }
+
+ template<class T>
+ void quicksort_decending(T *__restrict__ t,
+ const ssize_t begin,
+ const ssize_t end)
+ {
+ if (likely(begin < end))
+ {
+ const T pivotvalue = t[begin];
+ ssize_t left = begin - 1;
+ ssize_t right = end + 1;
+
+ while(1)
+ {
+ while (t[--right] < pivotvalue);
+ while (t[++left] > pivotvalue);
+
+ if (left >= right) break;
+
+ const T temp = t[right];
+ t[right] = t[left];
+ t[left] = temp;
+ }
+
+ const int pivot = right;
+ quicksort_decending(t, begin, pivot);
+ quicksort_decending(t, pivot + 1, end);
+ }
+ }
+
+
+ template<class T, ssize_t THRESHOLD>
+ void quicksort_insertionsort_ascending(T *__restrict__ t,
+ const ssize_t begin,
+ const ssize_t end)
+ {
+ if (likely(begin < end))
+ {
+ const ssize_t size = end-begin+1;
+ if (likely(size <= THRESHOLD))
+ {
+ insertionsort_ascending<T>(&t[begin],size);
+ }
+ else
+ {
+ const T pivotvalue = t[begin];
+ ssize_t left = begin - 1;
+ ssize_t right = end + 1;
+
+ while(1)
+ {
+ while (t[--right] > pivotvalue);
+ while (t[++left] < pivotvalue);
+
+ if (left >= right) break;
+
+ const T temp = t[right];
+ t[right] = t[left];
+ t[left] = temp;
+ }
+
+ const ssize_t pivot = right;
+ quicksort_insertionsort_ascending<T,THRESHOLD>(t, begin, pivot);
+ quicksort_insertionsort_ascending<T,THRESHOLD>(t, pivot + 1, end);
+ }
+ }
+ }
+
+
+ template<class T, ssize_t THRESHOLD>
+ void quicksort_insertionsort_decending(T *__restrict__ t,
+ const ssize_t begin,
+ const ssize_t end)
+ {
+ if (likely(begin < end))
+ {
+ const ssize_t size = end-begin+1;
+ if (likely(size <= THRESHOLD))
+ {
+ insertionsort_decending<T>(&t[begin],size);
+ }
+ else
+ {
+
+ const T pivotvalue = t[begin];
+ ssize_t left = begin - 1;
+ ssize_t right = end + 1;
+
+ while(1)
+ {
+ while (t[--right] < pivotvalue);
+ while (t[++left] > pivotvalue);
+
+ if (left >= right) break;
+
+ const T temp = t[right];
+ t[right] = t[left];
+ t[left] = temp;
+ }
+
+ const ssize_t pivot = right;
+ quicksort_insertionsort_decending<T,THRESHOLD>(t, begin, pivot);
+ quicksort_insertionsort_decending<T,THRESHOLD>(t, pivot + 1, end);
+ }
+ }
+ }
+
+ template<typename T>
+ static void radixsort32(T* const morton, const size_t num, const unsigned int shift = 3*8)
+ {
+ static const unsigned int BITS = 8;
+ static const unsigned int BUCKETS = (1 << BITS);
+ static const unsigned int CMP_SORT_THRESHOLD = 16;
+
+ __aligned(64) unsigned int count[BUCKETS];
+
+ /* clear buckets */
+ for (size_t i=0;i<BUCKETS;i++) count[i] = 0;
+
+ /* count buckets */
+#if defined(__INTEL_COMPILER)
+#pragma nounroll
+#endif
+ for (size_t i=0;i<num;i++)
+ count[(unsigned(morton[i]) >> shift) & (BUCKETS-1)]++;
+
+ /* prefix sums */
+ __aligned(64) unsigned int head[BUCKETS];
+ __aligned(64) unsigned int tail[BUCKETS];
+
+ head[0] = 0;
+ for (size_t i=1; i<BUCKETS; i++)
+ head[i] = head[i-1] + count[i-1];
+
+ for (size_t i=0; i<BUCKETS-1; i++)
+ tail[i] = head[i+1];
+
+ tail[BUCKETS-1] = head[BUCKETS-1] + count[BUCKETS-1];
+
+ assert(tail[BUCKETS-1] == head[BUCKETS-1] + count[BUCKETS-1]);
+ assert(tail[BUCKETS-1] == num);
+
+ /* in-place swap */
+ for (size_t i=0;i<BUCKETS;i++)
+ {
+ /* process bucket */
+ while(head[i] < tail[i])
+ {
+ T v = morton[head[i]];
+ while(1)
+ {
+ const size_t b = (unsigned(v) >> shift) & (BUCKETS-1);
+ if (b == i) break;
+ std::swap(v,morton[head[b]++]);
+ }
+ assert((unsigned(v) >> shift & (BUCKETS-1)) == i);
+ morton[head[i]++] = v;
+ }
+ }
+ if (shift == 0) return;
+
+ size_t offset = 0;
+ for (size_t i=0;i<BUCKETS;i++)
+ if (count[i])
+ {
+
+ for (size_t j=offset;j<offset+count[i]-1;j++)
+ assert(((unsigned(morton[j]) >> shift) & (BUCKETS-1)) == i);
+
+ if (unlikely(count[i] < CMP_SORT_THRESHOLD))
+ insertionsort_ascending(morton + offset, count[i]);
+ else
+ radixsort32(morton + offset, count[i], shift-BITS);
+
+ for (size_t j=offset;j<offset+count[i]-1;j++)
+ assert(morton[j] <= morton[j+1]);
+
+ offset += count[i];
+ }
+ }
+
+ template<typename Ty, typename Key>
+ class ParallelRadixSort
+ {
+ static const size_t MAX_TASKS = 64;
+ static const size_t BITS = 8;
+ static const size_t BUCKETS = (1 << BITS);
+ typedef unsigned int TyRadixCount[BUCKETS];
+
+ template<typename T>
+ static bool compare(const T& v0, const T& v1) {
+ return (Key)v0 < (Key)v1;
+ }
+
+ private:
+ ParallelRadixSort (const ParallelRadixSort& other) DELETED; // do not implement
+ ParallelRadixSort& operator= (const ParallelRadixSort& other) DELETED; // do not implement
+
+
+ public:
+ ParallelRadixSort (Ty* const src, Ty* const tmp, const size_t N)
+ : radixCount(nullptr), src(src), tmp(tmp), N(N) {}
+
+ void sort(const size_t blockSize)
+ {
+ assert(blockSize > 0);
+
+ /* perform single threaded sort for small N */
+ if (N<=blockSize) // handles also special case of 0!
+ {
+ /* do inplace sort inside destination array */
+ std::sort(src,src+N,compare<Ty>);
+ }
+
+ /* perform parallel sort for large N */
+ else
+ {
+ const size_t numThreads = min((N+blockSize-1)/blockSize,TaskScheduler::threadCount(),size_t(MAX_TASKS));
+ tbbRadixSort(numThreads);
+ }
+ }
+
+ ~ParallelRadixSort()
+ {
+ alignedFree(radixCount);
+ radixCount = nullptr;
+ }
+
+ private:
+
+ void tbbRadixIteration0(const Key shift,
+ const Ty* __restrict const src,
+ Ty* __restrict const dst,
+ const size_t threadIndex, const size_t threadCount)
+ {
+ const size_t startID = (threadIndex+0)*N/threadCount;
+ const size_t endID = (threadIndex+1)*N/threadCount;
+
+ /* mask to extract some number of bits */
+ const Key mask = BUCKETS-1;
+
+ /* count how many items go into the buckets */
+ for (size_t i=0; i<BUCKETS; i++)
+ radixCount[threadIndex][i] = 0;
+
+ /* iterate over src array and count buckets */
+ unsigned int * __restrict const count = radixCount[threadIndex];
+#if defined(__INTEL_COMPILER)
+#pragma nounroll
+#endif
+ for (size_t i=startID; i<endID; i++) {
+#if defined(__64BIT__)
+ const size_t index = ((size_t)(Key)src[i] >> (size_t)shift) & (size_t)mask;
+#else
+ const Key index = ((Key)src[i] >> shift) & mask;
+#endif
+ count[index]++;
+ }
+ }
+
+ void tbbRadixIteration1(const Key shift,
+ const Ty* __restrict const src,
+ Ty* __restrict const dst,
+ const size_t threadIndex, const size_t threadCount)
+ {
+ const size_t startID = (threadIndex+0)*N/threadCount;
+ const size_t endID = (threadIndex+1)*N/threadCount;
+
+ /* mask to extract some number of bits */
+ const Key mask = BUCKETS-1;
+
+ /* calculate total number of items for each bucket */
+ __aligned(64) unsigned int total[BUCKETS];
+ /*
+ for (size_t i=0; i<BUCKETS; i++)
+ total[i] = 0;
+ */
+ for (size_t i=0; i<BUCKETS; i+=VSIZEX)
+ vintx::store(&total[i], zero);
+
+ for (size_t i=0; i<threadCount; i++)
+ {
+ /*
+ for (size_t j=0; j<BUCKETS; j++)
+ total[j] += radixCount[i][j];
+ */
+ for (size_t j=0; j<BUCKETS; j+=VSIZEX)
+ vintx::store(&total[j], vintx::load(&total[j]) + vintx::load(&radixCount[i][j]));
+ }
+
+ /* calculate start offset of each bucket */
+ __aligned(64) unsigned int offset[BUCKETS];
+ offset[0] = 0;
+ for (size_t i=1; i<BUCKETS; i++)
+ offset[i] = offset[i-1] + total[i-1];
+
+ /* calculate start offset of each bucket for this thread */
+ for (size_t i=0; i<threadIndex; i++)
+ {
+ /*
+ for (size_t j=0; j<BUCKETS; j++)
+ offset[j] += radixCount[i][j];
+ */
+ for (size_t j=0; j<BUCKETS; j+=VSIZEX)
+ vintx::store(&offset[j], vintx::load(&offset[j]) + vintx::load(&radixCount[i][j]));
+ }
+
+ /* copy items into their buckets */
+#if defined(__INTEL_COMPILER)
+#pragma nounroll
+#endif
+ for (size_t i=startID; i<endID; i++) {
+ const Ty elt = src[i];
+#if defined(__64BIT__)
+ const size_t index = ((size_t)(Key)src[i] >> (size_t)shift) & (size_t)mask;
+#else
+ const size_t index = ((Key)src[i] >> shift) & mask;
+#endif
+ dst[offset[index]++] = elt;
+ }
+ }
+
+ void tbbRadixIteration(const Key shift, const bool last,
+ const Ty* __restrict src, Ty* __restrict dst,
+ const size_t numTasks)
+ {
+ affinity_partitioner ap;
+ parallel_for_affinity(numTasks,[&] (size_t taskIndex) { tbbRadixIteration0(shift,src,dst,taskIndex,numTasks); },ap);
+ parallel_for_affinity(numTasks,[&] (size_t taskIndex) { tbbRadixIteration1(shift,src,dst,taskIndex,numTasks); },ap);
+ }
+
+ void tbbRadixSort(const size_t numTasks)
+ {
+ radixCount = (TyRadixCount*) alignedMalloc(MAX_TASKS*sizeof(TyRadixCount),64);
+
+ if (sizeof(Key) == sizeof(uint32_t)) {
+ tbbRadixIteration(0*BITS,0,src,tmp,numTasks);
+ tbbRadixIteration(1*BITS,0,tmp,src,numTasks);
+ tbbRadixIteration(2*BITS,0,src,tmp,numTasks);
+ tbbRadixIteration(3*BITS,1,tmp,src,numTasks);
+ }
+ else if (sizeof(Key) == sizeof(uint64_t))
+ {
+ tbbRadixIteration(0*BITS,0,src,tmp,numTasks);
+ tbbRadixIteration(1*BITS,0,tmp,src,numTasks);
+ tbbRadixIteration(2*BITS,0,src,tmp,numTasks);
+ tbbRadixIteration(3*BITS,0,tmp,src,numTasks);
+ tbbRadixIteration(4*BITS,0,src,tmp,numTasks);
+ tbbRadixIteration(5*BITS,0,tmp,src,numTasks);
+ tbbRadixIteration(6*BITS,0,src,tmp,numTasks);
+ tbbRadixIteration(7*BITS,1,tmp,src,numTasks);
+ }
+ }
+
+ private:
+ TyRadixCount* radixCount;
+ Ty* const src;
+ Ty* const tmp;
+ const size_t N;
+ };
+
+ template<typename Ty>
+ void radix_sort(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192)
+ {
+ ParallelRadixSort<Ty,Ty>(src,tmp,N).sort(blockSize);
+ }
+
+ template<typename Ty, typename Key>
+ void radix_sort(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192)
+ {
+ ParallelRadixSort<Ty,Key>(src,tmp,N).sort(blockSize);
+ }
+
+ template<typename Ty>
+ void radix_sort_u32(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192) {
+ radix_sort<Ty,uint32_t>(src,tmp,N,blockSize);
+ }
+
+ template<typename Ty>
+ void radix_sort_u64(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192) {
+ radix_sort<Ty,uint64_t>(src,tmp,N,blockSize);
+ }
+}
diff --git a/thirdparty/embree/common/lexers/parsestream.h b/thirdparty/embree/common/lexers/parsestream.h
new file mode 100644
index 0000000000..f65a52cb47
--- /dev/null
+++ b/thirdparty/embree/common/lexers/parsestream.h
@@ -0,0 +1,101 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "stringstream.h"
+#include "../sys/filename.h"
+#include "../math/vec2.h"
+#include "../math/vec3.h"
+#include "../math/col3.h"
+#include "../math/color.h"
+
+namespace embree
+{
+ /*! helper class for simple command line parsing */
+ class ParseStream : public Stream<std::string>
+ {
+ public:
+ ParseStream (const Ref<Stream<std::string> >& cin) : cin(cin) {}
+
+ ParseStream (const Ref<Stream<int> >& cin, const std::string& seps = "\n\t\r ",
+ const std::string& endl = "", bool multiLine = false)
+ : cin(new StringStream(cin,seps,endl,multiLine)) {}
+
+ public:
+ ParseLocation location() { return cin->loc(); }
+ std::string next() { return cin->get(); }
+
+ void force(const std::string& next) {
+ std::string token = getString();
+ if (token != next)
+ THROW_RUNTIME_ERROR("token \""+next+"\" expected but token \""+token+"\" found");
+ }
+
+ std::string getString() {
+ return get();
+ }
+
+ FileName getFileName() {
+ return FileName(get());
+ }
+
+ int getInt () {
+ return atoi(get().c_str());
+ }
+
+ Vec2i getVec2i() {
+ int x = atoi(get().c_str());
+ int y = atoi(get().c_str());
+ return Vec2i(x,y);
+ }
+
+ Vec3ia getVec3ia() {
+ int x = atoi(get().c_str());
+ int y = atoi(get().c_str());
+ int z = atoi(get().c_str());
+ return Vec3ia(x,y,z);
+ }
+
+ float getFloat() {
+ return (float)atof(get().c_str());
+ }
+
+ Vec2f getVec2f() {
+ float x = (float)atof(get().c_str());
+ float y = (float)atof(get().c_str());
+ return Vec2f(x,y);
+ }
+
+ Vec3f getVec3f() {
+ float x = (float)atof(get().c_str());
+ float y = (float)atof(get().c_str());
+ float z = (float)atof(get().c_str());
+ return Vec3f(x,y,z);
+ }
+
+ Vec3fa getVec3fa() {
+ float x = (float)atof(get().c_str());
+ float y = (float)atof(get().c_str());
+ float z = (float)atof(get().c_str());
+ return Vec3fa(x,y,z);
+ }
+
+ Col3f getCol3f() {
+ float x = (float)atof(get().c_str());
+ float y = (float)atof(get().c_str());
+ float z = (float)atof(get().c_str());
+ return Col3f(x,y,z);
+ }
+
+ Color getColor() {
+ float r = (float)atof(get().c_str());
+ float g = (float)atof(get().c_str());
+ float b = (float)atof(get().c_str());
+ return Color(r,g,b);
+ }
+
+ private:
+ Ref<Stream<std::string> > cin;
+ };
+}
diff --git a/thirdparty/embree/common/lexers/stream.h b/thirdparty/embree/common/lexers/stream.h
new file mode 100644
index 0000000000..a40c15f8eb
--- /dev/null
+++ b/thirdparty/embree/common/lexers/stream.h
@@ -0,0 +1,215 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+#include "../sys/ref.h"
+#include "../sys/filename.h"
+#include "../sys/string.h"
+
+#include <vector>
+#include <iostream>
+#include <cstdio>
+#include <string.h>
+
+namespace embree
+{
+ /*! stores the location of a stream element in the source */
+ class ParseLocation
+ {
+ public:
+ ParseLocation () : lineNumber(-1), colNumber(-1) {}
+ ParseLocation (std::shared_ptr<std::string> fileName, ssize_t lineNumber, ssize_t colNumber, ssize_t /*charNumber*/)
+ : fileName(fileName), lineNumber(lineNumber), colNumber(colNumber) {}
+
+ std::string str() const
+ {
+ std::string str = "unknown";
+ if (fileName) str = *fileName;
+ if (lineNumber >= 0) str += " line " + toString(lineNumber);
+ if (lineNumber >= 0 && colNumber >= 0) str += " character " + toString(colNumber);
+ return str;
+ }
+
+ private:
+ std::shared_ptr<std::string> fileName; /// name of the file (or stream) the token is from
+ ssize_t lineNumber; /// the line number the token is from
+ ssize_t colNumber; /// the character number in the current line
+ };
+
+ /*! a stream class templated over the stream elements */
+ template<typename T> class Stream : public RefCount
+ {
+ enum { BUF_SIZE = 1024 };
+
+ private:
+ virtual T next() = 0;
+ virtual ParseLocation location() = 0;
+ __forceinline std::pair<T,ParseLocation> nextHelper() {
+ ParseLocation l = location();
+ T v = next();
+ return std::pair<T,ParseLocation>(v,l);
+ }
+ __forceinline void push_back(const std::pair<T,ParseLocation>& v) {
+ if (past+future == BUF_SIZE) pop_front();
+ size_t end = (start+past+future++)%BUF_SIZE;
+ buffer[end] = v;
+ }
+ __forceinline void pop_front() {
+ if (past == 0) THROW_RUNTIME_ERROR("stream buffer empty");
+ start = (start+1)%BUF_SIZE; past--;
+ }
+ public:
+ Stream () : start(0), past(0), future(0), buffer(BUF_SIZE) {}
+ virtual ~Stream() {}
+
+ public:
+
+ const ParseLocation& loc() {
+ if (future == 0) push_back(nextHelper());
+ return buffer[(start+past)%BUF_SIZE].second;
+ }
+ T get() {
+ if (future == 0) push_back(nextHelper());
+ T t = buffer[(start+past)%BUF_SIZE].first;
+ past++; future--;
+ return t;
+ }
+ const T& peek() {
+ if (future == 0) push_back(nextHelper());
+ return buffer[(start+past)%BUF_SIZE].first;
+ }
+ const T& unget(size_t n = 1) {
+ if (past < n) THROW_RUNTIME_ERROR ("cannot unget that many items");
+ past -= n; future += n;
+ return peek();
+ }
+ void drop() {
+ if (future == 0) push_back(nextHelper());
+ past++; future--;
+ }
+ private:
+ size_t start,past,future;
+ std::vector<std::pair<T,ParseLocation> > buffer;
+ };
+
+ /*! warps an iostream stream */
+ class StdStream : public Stream<int>
+ {
+ public:
+ StdStream (std::istream& cin, const std::string& name = "std::stream")
+ : cin(cin), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}
+ ~StdStream() {}
+ ParseLocation location() {
+ return ParseLocation(name,lineNumber,colNumber,charNumber);
+ }
+ int next() {
+ int c = cin.get();
+ if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;
+ charNumber++;
+ return c;
+ }
+ private:
+ std::istream& cin;
+ ssize_t lineNumber; /// the line number the token is from
+ ssize_t colNumber; /// the character number in the current line
+ ssize_t charNumber; /// the character in the file
+ std::shared_ptr<std::string> name; /// name of buffer
+ };
+
+ /*! creates a stream from a file */
+ class FileStream : public Stream<int>
+ {
+ public:
+
+ FileStream (FILE* file, const std::string& name = "file")
+ : file(file), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}
+
+ FileStream (const FileName& fileName)
+ : lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(fileName.str())))
+ {
+ file = fopen(fileName.c_str(),"r");
+ if (file == nullptr) THROW_RUNTIME_ERROR("cannot open file " + fileName.str());
+ }
+ ~FileStream() { if (file) fclose(file); }
+
+ public:
+ ParseLocation location() {
+ return ParseLocation(name,lineNumber,colNumber,charNumber);
+ }
+
+ int next() {
+ int c = fgetc(file);
+ if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;
+ charNumber++;
+ return c;
+ }
+
+ private:
+ FILE* file;
+ ssize_t lineNumber; /// the line number the token is from
+ ssize_t colNumber; /// the character number in the current line
+ ssize_t charNumber; /// the character in the file
+ std::shared_ptr<std::string> name; /// name of buffer
+ };
+
+ /*! creates a stream from a string */
+ class StrStream : public Stream<int>
+ {
+ public:
+
+ StrStream (const char* str)
+ : str(str), lineNumber(1), colNumber(0), charNumber(0) {}
+
+ public:
+ ParseLocation location() {
+ return ParseLocation(std::shared_ptr<std::string>(),lineNumber,colNumber,charNumber);
+ }
+
+ int next() {
+ int c = str[charNumber];
+ if (c == 0) return EOF;
+ if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;
+ charNumber++;
+ return c;
+ }
+
+ private:
+ const char* str;
+ ssize_t lineNumber; /// the line number the token is from
+ ssize_t colNumber; /// the character number in the current line
+ ssize_t charNumber; /// the character in the file
+ };
+
+ /*! creates a character stream from a command line */
+ class CommandLineStream : public Stream<int>
+ {
+ public:
+ CommandLineStream (int argc, char** argv, const std::string& name = "command line")
+ : i(0), j(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name)))
+ {
+ if (argc > 0) {
+ for (size_t i=0; argv[0][i] && i<1024; i++) charNumber++;
+ charNumber++;
+ }
+ for (ssize_t k=1; k<argc; k++) args.push_back(argv[k]);
+ }
+ ~CommandLineStream() {}
+ public:
+ ParseLocation location() {
+ return ParseLocation(name,0,charNumber,charNumber);
+ }
+ int next() {
+ if (i == args.size()) return EOF;
+ if (j == args[i].size()) { i++; j=0; charNumber++; return ' '; }
+ charNumber++;
+ return args[i][j++];
+ }
+ private:
+ size_t i,j;
+ std::vector<std::string> args;
+ ssize_t charNumber; /// the character in the file
+ std::shared_ptr<std::string> name; /// name of buffer
+ };
+}
diff --git a/thirdparty/embree/common/lexers/streamfilters.h b/thirdparty/embree/common/lexers/streamfilters.h
new file mode 100644
index 0000000000..3592b77b03
--- /dev/null
+++ b/thirdparty/embree/common/lexers/streamfilters.h
@@ -0,0 +1,39 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "stream.h"
+
+namespace embree
+{
+ /* removes all line comments from a stream */
+ class LineCommentFilter : public Stream<int>
+ {
+ public:
+ LineCommentFilter (const FileName& fileName, const std::string& lineComment)
+ : cin(new FileStream(fileName)), lineComment(lineComment) {}
+ LineCommentFilter (Ref<Stream<int> > cin, const std::string& lineComment)
+ : cin(cin), lineComment(lineComment) {}
+
+ ParseLocation location() { return cin->loc(); }
+
+ int next()
+ {
+ /* look if the line comment starts here */
+ for (size_t j=0; j<lineComment.size(); j++) {
+ if (cin->peek() != lineComment[j]) { cin->unget(j); goto not_found; }
+ cin->get();
+ }
+ /* eat all characters until the end of the line (or file) */
+ while (cin->peek() != '\n' && cin->peek() != EOF) cin->get();
+
+ not_found:
+ return cin->get();
+ }
+
+ private:
+ Ref<Stream<int> > cin;
+ std::string lineComment;
+ };
+}
diff --git a/thirdparty/embree/common/lexers/stringstream.cpp b/thirdparty/embree/common/lexers/stringstream.cpp
new file mode 100644
index 0000000000..a037869506
--- /dev/null
+++ b/thirdparty/embree/common/lexers/stringstream.cpp
@@ -0,0 +1,51 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "stringstream.h"
+
+namespace embree
+{
+ static const std::string stringChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _.,+-=:/*\\";
+
+ /* creates map for fast categorization of characters */
+ static void createCharMap(bool map[256], const std::string& chrs) {
+ for (size_t i=0; i<256; i++) map[i] = false;
+ for (size_t i=0; i<chrs.size(); i++) map[uint8_t(chrs[i])] = true;
+ }
+
+ /* simple tokenizer */
+ StringStream::StringStream(const Ref<Stream<int> >& cin, const std::string& seps, const std::string& endl, bool multiLine)
+ : cin(cin), endl(endl), multiLine(multiLine)
+ {
+ createCharMap(isSepMap,seps);
+ createCharMap(isValidCharMap,stringChars);
+ }
+
+ std::string StringStream::next()
+ {
+ /* skip separators */
+ while (cin->peek() != EOF) {
+ if (endl != "" && cin->peek() == '\n') { cin->drop(); return endl; }
+ if (multiLine && cin->peek() == '\\') {
+ cin->drop();
+ if (cin->peek() == '\n') { cin->drop(); continue; }
+ cin->unget();
+ }
+ if (!isSeparator(cin->peek())) break;
+ cin->drop();
+ }
+
+ /* parse everything until the next separator */
+ std::vector<char> str; str.reserve(64);
+ while (cin->peek() != EOF && !isSeparator(cin->peek())) {
+ int c = cin->get();
+ // -- GODOT start --
+ // if (!isValidChar(c)) throw std::runtime_error("invalid character "+std::string(1,c)+" in input");
+ if (!isValidChar(c)) abort();
+ // -- GODOT end --
+ str.push_back((char)c);
+ }
+ str.push_back(0);
+ return std::string(str.data());
+ }
+}
diff --git a/thirdparty/embree/common/lexers/stringstream.h b/thirdparty/embree/common/lexers/stringstream.h
new file mode 100644
index 0000000000..6d9c27e3cd
--- /dev/null
+++ b/thirdparty/embree/common/lexers/stringstream.h
@@ -0,0 +1,29 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "stream.h"
+
+namespace embree
+{
+ /*! simple tokenizer that produces a string stream */
+ class StringStream : public Stream<std::string>
+ {
+ public:
+ StringStream(const Ref<Stream<int> >& cin, const std::string& seps = "\n\t\r ",
+ const std::string& endl = "", bool multiLine = false);
+ public:
+ ParseLocation location() { return cin->loc(); }
+ std::string next();
+ private:
+ __forceinline bool isSeparator(unsigned int c) const { return c<256 && isSepMap[c]; }
+ __forceinline bool isValidChar(unsigned int c) const { return c<256 && isValidCharMap[c]; }
+ private:
+ Ref<Stream<int> > cin; /*! source character stream */
+ bool isSepMap[256]; /*! map for fast classification of separators */
+ bool isValidCharMap[256]; /*! map for valid characters */
+ std::string endl; /*! the token of the end of line */
+ bool multiLine; /*! whether to parse lines wrapped with \ */
+ };
+}
diff --git a/thirdparty/embree/common/lexers/tokenstream.cpp b/thirdparty/embree/common/lexers/tokenstream.cpp
new file mode 100644
index 0000000000..6ed6f2045a
--- /dev/null
+++ b/thirdparty/embree/common/lexers/tokenstream.cpp
@@ -0,0 +1,181 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "tokenstream.h"
+#include "../math/math.h"
+
+namespace embree
+{
+ /* shorthands for common sets of characters */
+ const std::string TokenStream::alpha = "abcdefghijklmnopqrstuvwxyz";
+ const std::string TokenStream::ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const std::string TokenStream::numbers = "0123456789";
+ const std::string TokenStream::separators = "\n\t\r ";
+ const std::string TokenStream::stringChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _.,+-=:/*\\";
+
+ /* creates map for fast categorization of characters */
+ static void createCharMap(bool map[256], const std::string& chrs) {
+ for (size_t i=0; i<256; i++) map[i] = false;
+ for (size_t i=0; i<chrs.size(); i++) map[uint8_t(chrs[i])] = true;
+ }
+
+ /* build full tokenizer that takes list of valid characters and keywords */
+ TokenStream::TokenStream(const Ref<Stream<int> >& cin, //< stream to read from
+ const std::string& alpha, //< valid characters for identifiers
+ const std::string& seps, //< characters that act as separators
+ const std::vector<std::string>& symbols) //< symbols
+ : cin(cin), symbols(symbols)
+ {
+ createCharMap(isAlphaMap,alpha);
+ createCharMap(isSepMap,seps);
+ createCharMap(isStringCharMap,stringChars);
+ }
+
+ bool TokenStream::decDigits(std::string& str_o)
+ {
+ bool ok = false;
+ std::string str;
+ if (cin->peek() == '+' || cin->peek() == '-') str += (char)cin->get();
+ while (isDigit(cin->peek())) { ok = true; str += (char)cin->get(); }
+ if (ok) str_o += str;
+ else cin->unget(str.size());
+ return ok;
+ }
+
+ bool TokenStream::decDigits1(std::string& str_o)
+ {
+ bool ok = false;
+ std::string str;
+ while (isDigit(cin->peek())) { ok = true; str += (char)cin->get(); }
+ if (ok) str_o += str; else cin->unget(str.size());
+ return ok;
+ }
+
+ bool TokenStream::trySymbol(const std::string& symbol)
+ {
+ size_t pos = 0;
+ while (pos < symbol.size()) {
+ if (symbol[pos] != cin->peek()) { cin->unget(pos); return false; }
+ cin->drop(); pos++;
+ }
+ return true;
+ }
+
+ bool TokenStream::trySymbols(Token& token, const ParseLocation& loc)
+ {
+ for (size_t i=0; i<symbols.size(); i++) {
+ if (!trySymbol(symbols[i])) continue;
+ token = Token(symbols[i],Token::TY_SYMBOL,loc);
+ return true;
+ }
+ return false;
+ }
+
+ bool TokenStream::tryFloat(Token& token, const ParseLocation& loc)
+ {
+ bool ok = false;
+ std::string str;
+ if (trySymbol("nan")) {
+ token = Token(float(nan));
+ return true;
+ }
+ if (trySymbol("+inf")) {
+ token = Token(float(pos_inf));
+ return true;
+ }
+ if (trySymbol("-inf")) {
+ token = Token(float(neg_inf));
+ return true;
+ }
+
+ if (decDigits(str))
+ {
+ if (cin->peek() == '.') {
+ str += (char)cin->get();
+ decDigits(str);
+ if (cin->peek() == 'e' || cin->peek() == 'E') {
+ str += (char)cin->get();
+ if (decDigits(str)) ok = true; // 1.[2]E2
+ }
+ else ok = true; // 1.[2]
+ }
+ else if (cin->peek() == 'e' || cin->peek() == 'E') {
+ str += (char)cin->get();
+ if (decDigits(str)) ok = true; // 1E2
+ }
+ }
+ else
+ {
+ if (cin->peek() == '.') {
+ str += (char)cin->get();
+ if (decDigits(str)) {
+ if (cin->peek() == 'e' || cin->peek() == 'E') {
+ str += (char)cin->get();
+ if (decDigits(str)) ok = true; // .3E2
+ }
+ else ok = true; // .3
+ }
+ }
+ }
+ if (ok) {
+ token = Token((float)atof(str.c_str()),loc);
+ }
+ else cin->unget(str.size());
+ return ok;
+ }
+
+ bool TokenStream::tryInt(Token& token, const ParseLocation& loc) {
+ std::string str;
+ if (decDigits(str)) {
+ token = Token(atoi(str.c_str()),loc);
+ return true;
+ }
+ return false;
+ }
+
+ bool TokenStream::tryString(Token& token, const ParseLocation& loc)
+ {
+ std::string str;
+ if (cin->peek() != '\"') return false;
+ cin->drop();
+ while (cin->peek() != '\"') {
+ const int c = cin->get();
+ if (!isStringChar(c)) THROW_RUNTIME_ERROR("invalid string character "+std::string(1,c)+" at "+loc.str());
+ str += (char)c;
+ }
+ cin->drop();
+ token = Token(str,Token::TY_STRING,loc);
+ return true;
+ }
+
+ bool TokenStream::tryIdentifier(Token& token, const ParseLocation& loc)
+ {
+ std::string str;
+ if (!isAlpha(cin->peek())) return false;
+ str += (char)cin->get();
+ while (isAlphaNum(cin->peek())) str += (char)cin->get();
+ token = Token(str,Token::TY_IDENTIFIER,loc);
+ return true;
+ }
+
+ void TokenStream::skipSeparators()
+ {
+ /* skip separators */
+ while (cin->peek() != EOF && isSeparator(cin->peek()))
+ cin->drop();
+ }
+
+ Token TokenStream::next()
+ {
+ Token token;
+ skipSeparators();
+ ParseLocation loc = cin->loc();
+ if (trySymbols (token,loc)) return token; /**< try to parse a symbol */
+ if (tryFloat (token,loc)) return token; /**< try to parse float */
+ if (tryInt (token,loc)) return token; /**< try to parse integer */
+ if (tryString (token,loc)) return token; /**< try to parse string */
+ if (tryIdentifier(token,loc)) return token; /**< try to parse identifier */
+ if (cin->peek() == EOF ) return Token(loc); /**< return EOF token */
+ return Token((char)cin->get(),loc); /**< return invalid character token */
+ }
+}
diff --git a/thirdparty/embree/common/lexers/tokenstream.h b/thirdparty/embree/common/lexers/tokenstream.h
new file mode 100644
index 0000000000..6e49dd0b39
--- /dev/null
+++ b/thirdparty/embree/common/lexers/tokenstream.h
@@ -0,0 +1,164 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "stream.h"
+#include <string>
+#include <vector>
+
+namespace embree
+{
+ /*! token class */
+ class Token
+ {
+ public:
+
+ enum Type { TY_EOF, TY_CHAR, TY_INT, TY_FLOAT, TY_IDENTIFIER, TY_STRING, TY_SYMBOL };
+
+ Token ( const ParseLocation& loc = ParseLocation()) : ty(TY_EOF ), loc(loc) {}
+ Token (char c, const ParseLocation& loc = ParseLocation()) : ty(TY_CHAR ), c(c), loc(loc) {}
+ Token (int i, const ParseLocation& loc = ParseLocation()) : ty(TY_INT ), i(i), loc(loc) {}
+ Token (float f,const ParseLocation& loc = ParseLocation()) : ty(TY_FLOAT), f(f), loc(loc) {}
+ Token (std::string str, Type ty, const ParseLocation& loc = ParseLocation()) : ty(ty), str(str), loc(loc) {}
+
+ static Token Eof() { return Token(); }
+ static Token Sym(std::string str) { return Token(str,TY_SYMBOL); }
+ static Token Str(std::string str) { return Token(str,TY_STRING); }
+ static Token Id (std::string str) { return Token(str,TY_IDENTIFIER); }
+
+ char Char() const {
+ if (ty == TY_CHAR) return c;
+ THROW_RUNTIME_ERROR(loc.str()+": character expected");
+ }
+
+ int Int() const {
+ if (ty == TY_INT) return i;
+ THROW_RUNTIME_ERROR(loc.str()+": integer expected");
+ }
+
+ float Float(bool cast = true) const {
+ if (ty == TY_FLOAT) return f;
+ if (ty == TY_INT && cast) return (float)i;
+ THROW_RUNTIME_ERROR(loc.str()+": float expected");
+ }
+
+ std::string Identifier() const {
+ if (ty == TY_IDENTIFIER) return str;
+ THROW_RUNTIME_ERROR(loc.str()+": identifier expected");
+ }
+
+ std::string String() const {
+ if (ty == TY_STRING) return str;
+ THROW_RUNTIME_ERROR(loc.str()+": string expected");
+ }
+
+ std::string Symbol() const {
+ if (ty == TY_SYMBOL) return str;
+ THROW_RUNTIME_ERROR(loc.str()+": symbol expected");
+ }
+
+ const ParseLocation& Location() const { return loc; }
+
+ friend bool operator==(const Token& a, const Token& b)
+ {
+ if (a.ty != b.ty) return false;
+ if (a.ty == TY_CHAR) return a.c == b.c;
+ if (a.ty == TY_INT) return a.i == b.i;
+ if (a.ty == TY_FLOAT) return a.f == b.f;
+ if (a.ty == TY_IDENTIFIER) return a.str == b.str;
+ if (a.ty == TY_STRING) return a.str == b.str;
+ if (a.ty == TY_SYMBOL) return a.str == b.str;
+ return true;
+ }
+
+ friend bool operator!=(const Token& a, const Token& b) {
+ return !(a == b);
+ }
+
+ friend bool operator <( const Token& a, const Token& b ) {
+ if (a.ty != b.ty) return (int)a.ty < (int)b.ty;
+ if (a.ty == TY_CHAR) return a.c < b.c;
+ if (a.ty == TY_INT) return a.i < b.i;
+ if (a.ty == TY_FLOAT) return a.f < b.f;
+ if (a.ty == TY_IDENTIFIER) return a.str < b.str;
+ if (a.ty == TY_STRING) return a.str < b.str;
+ if (a.ty == TY_SYMBOL) return a.str < b.str;
+ return false;
+ }
+
+ friend std::ostream& operator<<(std::ostream& cout, const Token& t)
+ {
+ if (t.ty == TY_EOF) return cout << "eof";
+ if (t.ty == TY_CHAR) return cout << "Char(" << t.c << ")";
+ if (t.ty == TY_INT) return cout << "Int(" << t.i << ")";
+ if (t.ty == TY_FLOAT) return cout << "Float(" << t.f << ")";
+ if (t.ty == TY_IDENTIFIER) return cout << "Id(" << t.str << ")";
+ if (t.ty == TY_STRING) return cout << "String(" << t.str << ")";
+ if (t.ty == TY_SYMBOL) return cout << "Symbol(" << t.str << ")";
+ return cout << "unknown";
+ }
+
+ private:
+ Type ty; //< the type of the token
+ union {
+ char c; //< data for char tokens
+ int i; //< data for int tokens
+ float f; //< data for float tokens
+ };
+ std::string str; //< data for string and identifier tokens
+ ParseLocation loc; //< the location the token is from
+ };
+
+ /*! build full tokenizer that takes list of valid characters and keywords */
+ class TokenStream : public Stream<Token>
+ {
+ public:
+
+ /*! shorthands for common sets of characters */
+ static const std::string alpha;
+ static const std::string ALPHA;
+ static const std::string numbers;
+ static const std::string separators;
+ static const std::string stringChars;
+
+ public:
+ TokenStream(const Ref<Stream<int> >& cin,
+ const std::string& alpha, //< valid characters for identifiers
+ const std::string& seps, //< characters that act as separators
+ const std::vector<std::string>& symbols = std::vector<std::string>()); //< symbols
+ public:
+ ParseLocation location() { return cin->loc(); }
+ Token next();
+ bool trySymbol(const std::string& symbol);
+
+ private:
+ void skipSeparators();
+ bool decDigits(std::string& str);
+ bool decDigits1(std::string& str);
+ bool trySymbols(Token& token, const ParseLocation& loc);
+ bool tryFloat(Token& token, const ParseLocation& loc);
+ bool tryInt(Token& token, const ParseLocation& loc);
+ bool tryString(Token& token, const ParseLocation& loc);
+ bool tryIdentifier(Token& token, const ParseLocation& loc);
+
+ Ref<Stream<int> > cin;
+ bool isSepMap[256];
+ bool isAlphaMap[256];
+ bool isStringCharMap[256];
+ std::vector<std::string> symbols;
+
+ /*! checks if a character is a separator */
+ __forceinline bool isSeparator(unsigned int c) const { return c<256 && isSepMap[c]; }
+
+ /*! checks if a character is a number */
+ __forceinline bool isDigit(unsigned int c) const { return c >= '0' && c <= '9'; }
+
+ /*! checks if a character is valid inside a string */
+ __forceinline bool isStringChar(unsigned int c) const { return c<256 && isStringCharMap[c]; }
+
+ /*! checks if a character is legal for an identifier */
+ __forceinline bool isAlpha(unsigned int c) const { return c<256 && isAlphaMap[c]; }
+ __forceinline bool isAlphaNum(unsigned int c) const { return isAlpha(c) || isDigit(c); }
+ };
+}
diff --git a/thirdparty/embree/common/math/affinespace.h b/thirdparty/embree/common/math/affinespace.h
new file mode 100644
index 0000000000..9d4a0f0846
--- /dev/null
+++ b/thirdparty/embree/common/math/affinespace.h
@@ -0,0 +1,361 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "linearspace2.h"
+#include "linearspace3.h"
+#include "quaternion.h"
+#include "bbox.h"
+#include "vec4.h"
+
+namespace embree
+{
+ #define VectorT typename L::Vector
+ #define ScalarT typename L::Vector::Scalar
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Affine Space
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename L>
+ struct AffineSpaceT
+ {
+ L l; /*< linear part of affine space */
+ VectorT p; /*< affine part of affine space */
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Constructors, Assignment, Cast, Copy Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline AffineSpaceT ( ) { }
+ __forceinline AffineSpaceT ( const AffineSpaceT& other ) { l = other.l; p = other.p; }
+ __forceinline AffineSpaceT ( const L & other ) { l = other ; p = VectorT(zero); }
+ __forceinline AffineSpaceT& operator=( const AffineSpaceT& other ) { l = other.l; p = other.p; return *this; }
+
+ __forceinline AffineSpaceT( const VectorT& vx, const VectorT& vy, const VectorT& vz, const VectorT& p ) : l(vx,vy,vz), p(p) {}
+ __forceinline AffineSpaceT( const L& l, const VectorT& p ) : l(l), p(p) {}
+
+ template<typename L1> __forceinline AffineSpaceT( const AffineSpaceT<L1>& s ) : l(s.l), p(s.p) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline AffineSpaceT( ZeroTy ) : l(zero), p(zero) {}
+ __forceinline AffineSpaceT( OneTy ) : l(one), p(zero) {}
+
+ /*! return matrix for scaling */
+ static __forceinline AffineSpaceT scale(const VectorT& s) { return L::scale(s); }
+
+ /*! return matrix for translation */
+ static __forceinline AffineSpaceT translate(const VectorT& p) { return AffineSpaceT(one,p); }
+
+ /*! return matrix for rotation, only in 2D */
+ static __forceinline AffineSpaceT rotate(const ScalarT& r) { return L::rotate(r); }
+
+ /*! return matrix for rotation around arbitrary point (2D) or axis (3D) */
+ static __forceinline AffineSpaceT rotate(const VectorT& u, const ScalarT& r) { return L::rotate(u,r); }
+
+ /*! return matrix for rotation around arbitrary axis and point, only in 3D */
+ static __forceinline AffineSpaceT rotate(const VectorT& p, const VectorT& u, const ScalarT& r) { return translate(+p) * rotate(u,r) * translate(-p); }
+
+ /*! return matrix for looking at given point, only in 3D */
+ static __forceinline AffineSpaceT lookat(const VectorT& eye, const VectorT& point, const VectorT& up) {
+ VectorT Z = normalize(point-eye);
+ VectorT U = normalize(cross(up,Z));
+ VectorT V = normalize(cross(Z,U));
+ return AffineSpaceT(L(U,V,Z),eye);
+ }
+
+ };
+
+ // template specialization to get correct identity matrix for type AffineSpace3fa
+ template<>
+ __forceinline AffineSpaceT<LinearSpace3ff>::AffineSpaceT( OneTy ) : l(one), p(0.f, 0.f, 0.f, 1.f) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename L> __forceinline AffineSpaceT<L> operator -( const AffineSpaceT<L>& a ) { return AffineSpaceT<L>(-a.l,-a.p); }
+ template<typename L> __forceinline AffineSpaceT<L> operator +( const AffineSpaceT<L>& a ) { return AffineSpaceT<L>(+a.l,+a.p); }
+ template<typename L> __forceinline AffineSpaceT<L> rcp( const AffineSpaceT<L>& a ) { L il = rcp(a.l); return AffineSpaceT<L>(il,-(il*a.p)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename L> __forceinline const AffineSpaceT<L> operator +( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return AffineSpaceT<L>(a.l+b.l,a.p+b.p); }
+ template<typename L> __forceinline const AffineSpaceT<L> operator -( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return AffineSpaceT<L>(a.l-b.l,a.p-b.p); }
+
+ template<typename L> __forceinline const AffineSpaceT<L> operator *( const ScalarT & a, const AffineSpaceT<L>& b ) { return AffineSpaceT<L>(a*b.l,a*b.p); }
+ template<typename L> __forceinline const AffineSpaceT<L> operator *( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return AffineSpaceT<L>(a.l*b.l,a.l*b.p+a.p); }
+ template<typename L> __forceinline const AffineSpaceT<L> operator /( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a * rcp(b); }
+ template<typename L> __forceinline const AffineSpaceT<L> operator /( const AffineSpaceT<L>& a, const ScalarT & b ) { return a * rcp(b); }
+
+ template<typename L> __forceinline AffineSpaceT<L>& operator *=( AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a = a * b; }
+ template<typename L> __forceinline AffineSpaceT<L>& operator *=( AffineSpaceT<L>& a, const ScalarT & b ) { return a = a * b; }
+ template<typename L> __forceinline AffineSpaceT<L>& operator /=( AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a = a / b; }
+ template<typename L> __forceinline AffineSpaceT<L>& operator /=( AffineSpaceT<L>& a, const ScalarT & b ) { return a = a / b; }
+
+ template<typename L> __forceinline VectorT xfmPoint (const AffineSpaceT<L>& m, const VectorT& p) { return madd(VectorT(p.x),m.l.vx,madd(VectorT(p.y),m.l.vy,madd(VectorT(p.z),m.l.vz,m.p))); }
+ template<typename L> __forceinline VectorT xfmVector(const AffineSpaceT<L>& m, const VectorT& v) { return xfmVector(m.l,v); }
+ template<typename L> __forceinline VectorT xfmNormal(const AffineSpaceT<L>& m, const VectorT& n) { return xfmNormal(m.l,n); }
+
+ __forceinline const BBox<Vec3fa> xfmBounds(const AffineSpaceT<LinearSpace3<Vec3fa> >& m, const BBox<Vec3fa>& b)
+ {
+ BBox3fa dst = empty;
+ const Vec3fa p0(b.lower.x,b.lower.y,b.lower.z); dst.extend(xfmPoint(m,p0));
+ const Vec3fa p1(b.lower.x,b.lower.y,b.upper.z); dst.extend(xfmPoint(m,p1));
+ const Vec3fa p2(b.lower.x,b.upper.y,b.lower.z); dst.extend(xfmPoint(m,p2));
+ const Vec3fa p3(b.lower.x,b.upper.y,b.upper.z); dst.extend(xfmPoint(m,p3));
+ const Vec3fa p4(b.upper.x,b.lower.y,b.lower.z); dst.extend(xfmPoint(m,p4));
+ const Vec3fa p5(b.upper.x,b.lower.y,b.upper.z); dst.extend(xfmPoint(m,p5));
+ const Vec3fa p6(b.upper.x,b.upper.y,b.lower.z); dst.extend(xfmPoint(m,p6));
+ const Vec3fa p7(b.upper.x,b.upper.y,b.upper.z); dst.extend(xfmPoint(m,p7));
+ return dst;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename L> __forceinline bool operator ==( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a.l == b.l && a.p == b.p; }
+ template<typename L> __forceinline bool operator !=( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a.l != b.l || a.p != b.p; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename L> __forceinline AffineSpaceT<L> select ( const typename L::Vector::Scalar::Bool& s, const AffineSpaceT<L>& t, const AffineSpaceT<L>& f ) {
+ return AffineSpaceT<L>(select(s,t.l,f.l),select(s,t.p,f.p));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename L> static embree_ostream operator<<(embree_ostream cout, const AffineSpaceT<L>& m) {
+ return cout << "{ l = " << m.l << ", p = " << m.p << " }";
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Template Instantiations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ typedef AffineSpaceT<LinearSpace2f> AffineSpace2f;
+ typedef AffineSpaceT<LinearSpace3f> AffineSpace3f;
+ typedef AffineSpaceT<LinearSpace3fa> AffineSpace3fa;
+ typedef AffineSpaceT<LinearSpace3fx> AffineSpace3fx;
+ typedef AffineSpaceT<LinearSpace3ff> AffineSpace3ff;
+ typedef AffineSpaceT<Quaternion3f > OrthonormalSpace3f;
+
+ template<int N> using AffineSpace3vf = AffineSpaceT<LinearSpace3<Vec3<vfloat<N>>>>;
+ typedef AffineSpaceT<LinearSpace3<Vec3<vfloat<4>>>> AffineSpace3vf4;
+ typedef AffineSpaceT<LinearSpace3<Vec3<vfloat<8>>>> AffineSpace3vf8;
+ typedef AffineSpaceT<LinearSpace3<Vec3<vfloat<16>>>> AffineSpace3vf16;
+
+ template<int N> using AffineSpace3vff = AffineSpaceT<LinearSpace3<Vec4<vfloat<N>>>>;
+ typedef AffineSpaceT<LinearSpace3<Vec4<vfloat<4>>>> AffineSpace3vfa4;
+ typedef AffineSpaceT<LinearSpace3<Vec4<vfloat<8>>>> AffineSpace3vfa8;
+ typedef AffineSpaceT<LinearSpace3<Vec4<vfloat<16>>>> AffineSpace3vfa16;
+
+ //////////////////////////////////////////////////////////////////////////////
+ /// Interpolation
+ //////////////////////////////////////////////////////////////////////////////
+ template<typename T, typename R>
+ __forceinline AffineSpaceT<T> lerp(const AffineSpaceT<T>& M0,
+ const AffineSpaceT<T>& M1,
+ const R& t)
+ {
+ return AffineSpaceT<T>(lerp(M0.l,M1.l,t),lerp(M0.p,M1.p,t));
+ }
+
+ // slerp interprets the 16 floats of the matrix M = D * R * S as components of
+ // three matrizes (D, R, S) that are interpolated individually.
+ template<typename T> __forceinline AffineSpaceT<LinearSpace3<Vec3<T>>>
+ slerp(const AffineSpaceT<LinearSpace3<Vec4<T>>>& M0,
+ const AffineSpaceT<LinearSpace3<Vec4<T>>>& M1,
+ const T& t)
+ {
+ QuaternionT<T> q0(M0.p.w, M0.l.vx.w, M0.l.vy.w, M0.l.vz.w);
+ QuaternionT<T> q1(M1.p.w, M1.l.vx.w, M1.l.vy.w, M1.l.vz.w);
+ QuaternionT<T> q = slerp(q0, q1, t);
+
+ AffineSpaceT<LinearSpace3<Vec3<T>>> S = lerp(M0, M1, t);
+ AffineSpaceT<LinearSpace3<Vec3<T>>> D(one);
+ D.p.x = S.l.vx.y;
+ D.p.y = S.l.vx.z;
+ D.p.z = S.l.vy.z;
+ S.l.vx.y = 0;
+ S.l.vx.z = 0;
+ S.l.vy.z = 0;
+
+ AffineSpaceT<LinearSpace3<Vec3<T>>> R = LinearSpace3<Vec3<T>>(q);
+ return D * R * S;
+ }
+
+ // this is a specialized version for Vec3fa because that does
+ // not play along nicely with the other templated Vec3/Vec4 types
+ __forceinline AffineSpace3fa slerp(const AffineSpace3ff& M0,
+ const AffineSpace3ff& M1,
+ const float& t)
+ {
+ Quaternion3f q0(M0.p.w, M0.l.vx.w, M0.l.vy.w, M0.l.vz.w);
+ Quaternion3f q1(M1.p.w, M1.l.vx.w, M1.l.vy.w, M1.l.vz.w);
+ Quaternion3f q = slerp(q0, q1, t);
+
+ AffineSpace3fa S = lerp(M0, M1, t);
+ AffineSpace3fa D(one);
+ D.p.x = S.l.vx.y;
+ D.p.y = S.l.vx.z;
+ D.p.z = S.l.vy.z;
+ S.l.vx.y = 0;
+ S.l.vx.z = 0;
+ S.l.vy.z = 0;
+
+ AffineSpace3fa R = LinearSpace3fa(q);
+ return D * R * S;
+ }
+
+ __forceinline AffineSpace3fa quaternionDecompositionToAffineSpace(const AffineSpace3ff& qd)
+ {
+ // compute affine transform from quaternion decomposition
+ Quaternion3f q(qd.p.w, qd.l.vx.w, qd.l.vy.w, qd.l.vz.w);
+ AffineSpace3fa M = qd;
+ AffineSpace3fa D(one);
+ D.p.x = M.l.vx.y;
+ D.p.y = M.l.vx.z;
+ D.p.z = M.l.vy.z;
+ M.l.vx.y = 0;
+ M.l.vx.z = 0;
+ M.l.vy.z = 0;
+ AffineSpace3fa R = LinearSpace3fa(q);
+ return D * R * M;
+ }
+
+ __forceinline void quaternionDecomposition(const AffineSpace3ff& qd, Vec3fa& T, Quaternion3f& q, AffineSpace3fa& S)
+ {
+ q = Quaternion3f(qd.p.w, qd.l.vx.w, qd.l.vy.w, qd.l.vz.w);
+ S = qd;
+ T.x = qd.l.vx.y;
+ T.y = qd.l.vx.z;
+ T.z = qd.l.vy.z;
+ S.l.vx.y = 0;
+ S.l.vx.z = 0;
+ S.l.vy.z = 0;
+ }
+
+ __forceinline AffineSpace3fx quaternionDecomposition(Vec3fa const& T, Quaternion3f const& q, AffineSpace3fa const& S)
+ {
+ AffineSpace3ff M = S;
+ M.l.vx.w = q.i;
+ M.l.vy.w = q.j;
+ M.l.vz.w = q.k;
+ M.p.w = q.r;
+ M.l.vx.y = T.x;
+ M.l.vx.z = T.y;
+ M.l.vy.z = T.z;
+ return M;
+ }
+
+ struct __aligned(16) QuaternionDecomposition
+ {
+ float scale_x = 1.f;
+ float scale_y = 1.f;
+ float scale_z = 1.f;
+ float skew_xy = 0.f;
+ float skew_xz = 0.f;
+ float skew_yz = 0.f;
+ float shift_x = 0.f;
+ float shift_y = 0.f;
+ float shift_z = 0.f;
+ float quaternion_r = 1.f;
+ float quaternion_i = 0.f;
+ float quaternion_j = 0.f;
+ float quaternion_k = 0.f;
+ float translation_x = 0.f;
+ float translation_y = 0.f;
+ float translation_z = 0.f;
+ };
+
+ __forceinline QuaternionDecomposition quaternionDecomposition(AffineSpace3ff const& M)
+ {
+ QuaternionDecomposition qd;
+ qd.scale_x = M.l.vx.x;
+ qd.scale_y = M.l.vy.y;
+ qd.scale_z = M.l.vz.z;
+ qd.shift_x = M.p.x;
+ qd.shift_y = M.p.y;
+ qd.shift_z = M.p.z;
+ qd.translation_x = M.l.vx.y;
+ qd.translation_y = M.l.vx.z;
+ qd.translation_z = M.l.vy.z;
+ qd.skew_xy = M.l.vy.x;
+ qd.skew_xz = M.l.vz.x;
+ qd.skew_yz = M.l.vz.y;
+ qd.quaternion_r = M.p.w;
+ qd.quaternion_i = M.l.vx.w;
+ qd.quaternion_j = M.l.vy.w;
+ qd.quaternion_k = M.l.vz.w;
+ return qd;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /*
+ * ! Template Specialization for 2D: return matrix for rotation around point
+ * (rotation around arbitrarty vector is not meaningful in 2D)
+ */
+ template<> __forceinline
+ AffineSpace2f AffineSpace2f::rotate(const Vec2f& p, const float& r) {
+ return translate(+p)*AffineSpace2f(LinearSpace2f::rotate(r))*translate(-p);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Similarity Transform
+ //
+ // checks, if M is a similarity transformation, i.e if there exists a factor D
+ // such that for all x,y: distance(Mx, My) = D * distance(x, y)
+ ////////////////////////////////////////////////////////////////////////////////
+ __forceinline bool similarityTransform(const AffineSpace3fa& M, float* D)
+ {
+ if (D) *D = 0.f;
+ if (abs(dot(M.l.vx, M.l.vy)) > 1e-5f) return false;
+ if (abs(dot(M.l.vx, M.l.vz)) > 1e-5f) return false;
+ if (abs(dot(M.l.vy, M.l.vz)) > 1e-5f) return false;
+
+ const float D_x = dot(M.l.vx, M.l.vx);
+ const float D_y = dot(M.l.vy, M.l.vy);
+ const float D_z = dot(M.l.vz, M.l.vz);
+
+ if (abs(D_x - D_y) > 1e-5f ||
+ abs(D_x - D_z) > 1e-5f ||
+ abs(D_y - D_z) > 1e-5f)
+ return false;
+
+ if (D) *D = sqrtf(D_x);
+ return true;
+ }
+
+ __forceinline void AffineSpace3fa_store_unaligned(const AffineSpace3fa &source, AffineSpace3fa* ptr)
+ {
+ Vec3fa::storeu(&ptr->l.vx, source.l.vx);
+ Vec3fa::storeu(&ptr->l.vy, source.l.vy);
+ Vec3fa::storeu(&ptr->l.vz, source.l.vz);
+ Vec3fa::storeu(&ptr->p, source.p);
+ }
+
+ __forceinline AffineSpace3fa AffineSpace3fa_load_unaligned(AffineSpace3fa* ptr)
+ {
+ AffineSpace3fa space;
+ space.l.vx = Vec3fa::loadu(&ptr->l.vx);
+ space.l.vy = Vec3fa::loadu(&ptr->l.vy);
+ space.l.vz = Vec3fa::loadu(&ptr->l.vz);
+ space.p = Vec3fa::loadu(&ptr->p);
+ return space;
+ }
+
+ #undef VectorT
+ #undef ScalarT
+}
diff --git a/thirdparty/embree/common/math/bbox.h b/thirdparty/embree/common/math/bbox.h
new file mode 100644
index 0000000000..bc43155358
--- /dev/null
+++ b/thirdparty/embree/common/math/bbox.h
@@ -0,0 +1,331 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "vec2.h"
+#include "vec3.h"
+
+namespace embree
+{
+ namespace internal {
+
+ template <typename T> __forceinline T divideByTwo(const T& v) { return v / T(2); }
+ template <> __forceinline float divideByTwo<float>(const float& v) { return v * 0.5f; }
+ template <> __forceinline double divideByTwo<double>(const double& v) { return v * 0.5; }
+
+ } // namespace internal
+ template<typename T>
+ struct BBox
+ {
+ T lower, upper;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline BBox ( ) { }
+ template<typename T1>
+ __forceinline BBox ( const BBox<T1>& other ) : lower(other.lower), upper(other.upper) {}
+ __forceinline BBox& operator=( const BBox& other ) { lower = other.lower; upper = other.upper; return *this; }
+
+ __forceinline BBox ( const T& v ) : lower(v), upper(v) {}
+ __forceinline BBox ( const T& lower, const T& upper ) : lower(lower), upper(upper) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Extending Bounds
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const BBox& extend(const BBox& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }
+ __forceinline const BBox& extend(const T & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }
+
+ /*! tests if box is empty */
+ __forceinline bool empty() const { for (int i=0; i<T::N; i++) if (lower[i] > upper[i]) return true; return false; }
+
+ /*! computes the size of the box */
+ __forceinline T size() const { return upper - lower; }
+
+ /*! computes the center of the box */
+ __forceinline T center() const { return internal::divideByTwo<T>(lower+upper); }
+
+ /*! computes twice the center of the box */
+ __forceinline T center2() const { return lower+upper; }
+
+ /*! merges two boxes */
+ __forceinline static const BBox merge (const BBox& a, const BBox& b) {
+ return BBox(min(a.lower, b.lower), max(a.upper, b.upper));
+ }
+
+ /*! enlarge box by some scaling factor */
+ __forceinline BBox enlarge_by(const float a) const {
+ return BBox(lower - T(a)*abs(lower), upper + T(a)*abs(upper));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline BBox( EmptyTy ) : lower(pos_inf), upper(neg_inf) {}
+ __forceinline BBox( FullTy ) : lower(neg_inf), upper(pos_inf) {}
+ __forceinline BBox( FalseTy ) : lower(pos_inf), upper(neg_inf) {}
+ __forceinline BBox( TrueTy ) : lower(neg_inf), upper(pos_inf) {}
+ __forceinline BBox( NegInfTy ): lower(pos_inf), upper(neg_inf) {}
+ __forceinline BBox( PosInfTy ): lower(neg_inf), upper(pos_inf) {}
+ };
+
+ template<> __forceinline bool BBox<float>::empty() const {
+ return lower > upper;
+ }
+
+#if defined(__SSE__)
+ template<> __forceinline bool BBox<Vec3fa>::empty() const {
+ return !all(le_mask(lower,upper));
+ }
+ template<> __forceinline bool BBox<Vec3fx>::empty() const {
+ return !all(le_mask(lower,upper));
+ }
+#endif
+
+ /*! tests if box is finite */
+ __forceinline bool isvalid( const BBox<Vec3fa>& v ) {
+ return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)));
+ }
+
+ /*! tests if box is finite and non-empty*/
+ __forceinline bool isvalid_non_empty( const BBox<Vec3fa>& v ) {
+ return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)) & le_mask(v.lower,v.upper));
+ }
+
+ /*! tests if box has finite entries */
+ __forceinline bool is_finite( const BBox<Vec3fa>& b) {
+ return is_finite(b.lower) && is_finite(b.upper);
+ }
+
+ /*! test if point contained in box */
+ __forceinline bool inside ( const BBox<Vec3fa>& b, const Vec3fa& p ) { return all(ge_mask(p,b.lower) & le_mask(p,b.upper)); }
+
+ /*! computes the center of the box */
+ template<typename T> __forceinline const T center2(const BBox<T>& box) { return box.lower + box.upper; }
+ template<typename T> __forceinline const T center (const BBox<T>& box) { return internal::divideByTwo<T>(center2(box)); }
+
+ /*! computes the volume of a bounding box */
+ __forceinline float volume ( const BBox<Vec3fa>& b ) { return reduce_mul(b.size()); }
+ __forceinline float safeVolume( const BBox<Vec3fa>& b ) { if (b.empty()) return 0.0f; else return volume(b); }
+
+ /*! computes the volume of a bounding box */
+ __forceinline float volume( const BBox<Vec3f>& b ) { return reduce_mul(b.size()); }
+
+ /*! computes the surface area of a bounding box */
+ template<typename T> __forceinline const T area( const BBox<Vec2<T> >& b ) { const Vec2<T> d = b.size(); return d.x*d.y; }
+
+ template<typename T> __forceinline const T halfArea( const BBox<Vec3<T> >& b ) { return halfArea(b.size()); }
+ template<typename T> __forceinline const T area( const BBox<Vec3<T> >& b ) { return T(2)*halfArea(b); }
+
+ __forceinline float halfArea( const BBox<Vec3fa>& b ) { return halfArea(b.size()); }
+ __forceinline float area( const BBox<Vec3fa>& b ) { return 2.0f*halfArea(b); }
+
+ __forceinline float halfArea( const BBox<Vec3fx>& b ) { return halfArea(b.size()); }
+ __forceinline float area( const BBox<Vec3fx>& b ) { return 2.0f*halfArea(b); }
+
+ template<typename Vec> __forceinline float safeArea( const BBox<Vec>& b ) { if (b.empty()) return 0.0f; else return area(b); }
+
+ template<typename T> __forceinline float expectedApproxHalfArea(const BBox<T>& box) {
+ return halfArea(box);
+ }
+
+ /*! merges bounding boxes and points */
+ template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const T& b ) { return BBox<T>(min(a.lower, b ), max(a.upper, b )); }
+ template<typename T> __forceinline const BBox<T> merge( const T& a, const BBox<T>& b ) { return BBox<T>(min(a , b.lower), max(a , b.upper)); }
+ template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(min(a.lower, b.lower), max(a.upper, b.upper)); }
+
+ /*! Merges three boxes. */
+ template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return merge(a,merge(b,c)); }
+
+ /*! Merges four boxes. */
+ template<typename T> __forceinline BBox<T> merge(const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d) {
+ return merge(merge(a,b),merge(c,d));
+ }
+
+ /*! Comparison Operators */
+ template<typename T> __forceinline bool operator==( const BBox<T>& a, const BBox<T>& b ) { return a.lower == b.lower && a.upper == b.upper; }
+ template<typename T> __forceinline bool operator!=( const BBox<T>& a, const BBox<T>& b ) { return a.lower != b.lower || a.upper != b.upper; }
+
+ /*! scaling */
+ template<typename T> __forceinline BBox<T> operator *( const float& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
+ template<typename T> __forceinline BBox<T> operator *( const T& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
+
+ /*! translations */
+ template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower+b.lower,a.upper+b.upper); }
+ template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower-b.lower,a.upper-b.upper); }
+ template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower+b ,a.upper+b ); }
+ template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower-b ,a.upper-b ); }
+
+ /*! extension */
+ template<typename T> __forceinline BBox<T> enlarge(const BBox<T>& a, const T& b) { return BBox<T>(a.lower-b, a.upper+b); }
+
+ /*! intersect bounding boxes */
+ template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(max(a.lower, b.lower), min(a.upper, b.upper)); }
+ template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return intersect(a,intersect(b,c)); }
+ template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d ) { return intersect(intersect(a,b),intersect(c,d)); }
+
+ /*! subtract bounds from each other */
+ template<typename T> __forceinline void subtract(const BBox<T>& a, const BBox<T>& b, BBox<T>& c, BBox<T>& d)
+ {
+ c.lower = a.lower;
+ c.upper = min(a.upper,b.lower);
+ d.lower = max(a.lower,b.upper);
+ d.upper = a.upper;
+ }
+
+ /*! tests if bounding boxes (and points) are disjoint (empty intersection) */
+ template<typename T> __inline bool disjoint( const BBox<T>& a, const BBox<T>& b ) { return intersect(a,b).empty(); }
+ template<typename T> __inline bool disjoint( const BBox<T>& a, const T& b ) { return disjoint(a,BBox<T>(b)); }
+ template<typename T> __inline bool disjoint( const T& a, const BBox<T>& b ) { return disjoint(BBox<T>(a),b); }
+
+ /*! tests if bounding boxes (and points) are conjoint (non-empty intersection) */
+ template<typename T> __inline bool conjoint( const BBox<T>& a, const BBox<T>& b ) { return !intersect(a,b).empty(); }
+ template<typename T> __inline bool conjoint( const BBox<T>& a, const T& b ) { return conjoint(a,BBox<T>(b)); }
+ template<typename T> __inline bool conjoint( const T& a, const BBox<T>& b ) { return conjoint(BBox<T>(a),b); }
+
+ /*! subset relation */
+ template<typename T> __inline bool subset( const BBox<T>& a, const BBox<T>& b )
+ {
+ for ( size_t i = 0; i < T::N; i++ ) if ( a.lower[i] < b.lower[i] ) return false;
+ for ( size_t i = 0; i < T::N; i++ ) if ( a.upper[i] > b.upper[i] ) return false;
+ return true;
+ }
+
+ template<> __inline bool subset( const BBox<Vec3fa>& a, const BBox<Vec3fa>& b ) {
+ return all(ge_mask(a.lower,b.lower)) & all(le_mask(a.upper,b.upper));
+ }
+
+ template<> __inline bool subset( const BBox<Vec3fx>& a, const BBox<Vec3fx>& b ) {
+ return all(ge_mask(a.lower,b.lower)) & all(le_mask(a.upper,b.upper));
+ }
+
+ /*! blending */
+ template<typename T>
+ __forceinline BBox<T> lerp(const BBox<T>& b0, const BBox<T>& b1, const float t) {
+ return BBox<T>(lerp(b0.lower,b1.lower,t),lerp(b0.upper,b1.upper,t));
+ }
+
+ /*! output operator */
+ template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const BBox<T>& box) {
+ return cout << "[" << box.lower << "; " << box.upper << "]";
+ }
+
+ /*! default template instantiations */
+ typedef BBox<float> BBox1f;
+ typedef BBox<Vec2f> BBox2f;
+ typedef BBox<Vec2fa> BBox2fa;
+ typedef BBox<Vec3f> BBox3f;
+ typedef BBox<Vec3fa> BBox3fa;
+ typedef BBox<Vec3fx> BBox3fx;
+ typedef BBox<Vec3ff> BBox3ff;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// SSE / AVX / MIC specializations
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined __SSE__
+#include "../simd/sse.h"
+#endif
+
+#if defined __AVX__
+#include "../simd/avx.h"
+#endif
+
+#if defined(__AVX512F__)
+#include "../simd/avx512.h"
+#endif
+
+namespace embree
+{
+ template<int N>
+ __forceinline BBox<Vec3<vfloat<N>>> transpose(const BBox3fa* bounds);
+
+ template<>
+ __forceinline BBox<Vec3<vfloat4>> transpose<4>(const BBox3fa* bounds)
+ {
+ BBox<Vec3<vfloat4>> dest;
+
+ transpose((vfloat4&)bounds[0].lower,
+ (vfloat4&)bounds[1].lower,
+ (vfloat4&)bounds[2].lower,
+ (vfloat4&)bounds[3].lower,
+ dest.lower.x,
+ dest.lower.y,
+ dest.lower.z);
+
+ transpose((vfloat4&)bounds[0].upper,
+ (vfloat4&)bounds[1].upper,
+ (vfloat4&)bounds[2].upper,
+ (vfloat4&)bounds[3].upper,
+ dest.upper.x,
+ dest.upper.y,
+ dest.upper.z);
+
+ return dest;
+ }
+
+#if defined(__AVX__)
+ template<>
+ __forceinline BBox<Vec3<vfloat8>> transpose<8>(const BBox3fa* bounds)
+ {
+ BBox<Vec3<vfloat8>> dest;
+
+ transpose((vfloat4&)bounds[0].lower,
+ (vfloat4&)bounds[1].lower,
+ (vfloat4&)bounds[2].lower,
+ (vfloat4&)bounds[3].lower,
+ (vfloat4&)bounds[4].lower,
+ (vfloat4&)bounds[5].lower,
+ (vfloat4&)bounds[6].lower,
+ (vfloat4&)bounds[7].lower,
+ dest.lower.x,
+ dest.lower.y,
+ dest.lower.z);
+
+ transpose((vfloat4&)bounds[0].upper,
+ (vfloat4&)bounds[1].upper,
+ (vfloat4&)bounds[2].upper,
+ (vfloat4&)bounds[3].upper,
+ (vfloat4&)bounds[4].upper,
+ (vfloat4&)bounds[5].upper,
+ (vfloat4&)bounds[6].upper,
+ (vfloat4&)bounds[7].upper,
+ dest.upper.x,
+ dest.upper.y,
+ dest.upper.z);
+
+ return dest;
+ }
+#endif
+
+ template<int N>
+ __forceinline BBox3fa merge(const BBox3fa* bounds);
+
+ template<>
+ __forceinline BBox3fa merge<4>(const BBox3fa* bounds)
+ {
+ const Vec3fa lower = min(min(bounds[0].lower,bounds[1].lower),
+ min(bounds[2].lower,bounds[3].lower));
+ const Vec3fa upper = max(max(bounds[0].upper,bounds[1].upper),
+ max(bounds[2].upper,bounds[3].upper));
+ return BBox3fa(lower,upper);
+ }
+
+#if defined(__AVX__)
+ template<>
+ __forceinline BBox3fa merge<8>(const BBox3fa* bounds)
+ {
+ const Vec3fa lower = min(min(min(bounds[0].lower,bounds[1].lower),min(bounds[2].lower,bounds[3].lower)),
+ min(min(bounds[4].lower,bounds[5].lower),min(bounds[6].lower,bounds[7].lower)));
+ const Vec3fa upper = max(max(max(bounds[0].upper,bounds[1].upper),max(bounds[2].upper,bounds[3].upper)),
+ max(max(bounds[4].upper,bounds[5].upper),max(bounds[6].upper,bounds[7].upper)));
+ return BBox3fa(lower,upper);
+ }
+#endif
+}
+
diff --git a/thirdparty/embree/common/math/col3.h b/thirdparty/embree/common/math/col3.h
new file mode 100644
index 0000000000..3f50c04393
--- /dev/null
+++ b/thirdparty/embree/common/math/col3.h
@@ -0,0 +1,47 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "math.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// RGB Color Class
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> struct Col3
+ {
+ T r, g, b;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Col3 ( ) { }
+ __forceinline Col3 ( const Col3& other ) { r = other.r; g = other.g; b = other.b; }
+ __forceinline Col3& operator=( const Col3& other ) { r = other.r; g = other.g; b = other.b; return *this; }
+
+ __forceinline explicit Col3 (const T& v) : r(v), g(v), b(v) {}
+ __forceinline Col3 (const T& r, const T& g, const T& b) : r(r), g(g), b(b) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Col3 (ZeroTy) : r(zero) , g(zero) , b(zero) {}
+ __forceinline Col3 (OneTy) : r(one) , g(one) , b(one) {}
+ __forceinline Col3 (PosInfTy) : r(pos_inf), g(pos_inf), b(pos_inf) {}
+ __forceinline Col3 (NegInfTy) : r(neg_inf), g(neg_inf), b(neg_inf) {}
+ };
+
+ /*! output operator */
+ template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Col3<T>& a) {
+ return cout << "(" << a.r << ", " << a.g << ", " << a.b << ")";
+ }
+
+ /*! default template instantiations */
+ typedef Col3<unsigned char> Col3uc;
+ typedef Col3<float > Col3f;
+}
diff --git a/thirdparty/embree/common/math/col4.h b/thirdparty/embree/common/math/col4.h
new file mode 100644
index 0000000000..788508516b
--- /dev/null
+++ b/thirdparty/embree/common/math/col4.h
@@ -0,0 +1,47 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "math.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// RGBA Color Class
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> struct Col4
+ {
+ T r, g, b, a;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Col4 ( ) { }
+ __forceinline Col4 ( const Col4& other ) { r = other.r; g = other.g; b = other.b; a = other.a; }
+ __forceinline Col4& operator=( const Col4& other ) { r = other.r; g = other.g; b = other.b; a = other.a; return *this; }
+
+ __forceinline explicit Col4 (const T& v) : r(v), g(v), b(v), a(v) {}
+ __forceinline Col4 (const T& r, const T& g, const T& b, const T& a) : r(r), g(g), b(b), a(a) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Col4 (ZeroTy) : r(zero) , g(zero) , b(zero) , a(zero) {}
+ __forceinline Col4 (OneTy) : r(one) , g(one) , b(one) , a(one) {}
+ __forceinline Col4 (PosInfTy) : r(pos_inf), g(pos_inf), b(pos_inf), a(pos_inf) {}
+ __forceinline Col4 (NegInfTy) : r(neg_inf), g(neg_inf), b(neg_inf), a(neg_inf) {}
+ };
+
+ /*! output operator */
+ template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Col4<T>& a) {
+ return cout << "(" << a.r << ", " << a.g << ", " << a.b << ", " << a.a << ")";
+ }
+
+ /*! default template instantiations */
+ typedef Col4<unsigned char> Col4uc;
+ typedef Col4<float > Col4f;
+}
diff --git a/thirdparty/embree/common/math/color.h b/thirdparty/embree/common/math/color.h
new file mode 100644
index 0000000000..529584ea16
--- /dev/null
+++ b/thirdparty/embree/common/math/color.h
@@ -0,0 +1,241 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "constants.h"
+#include "col3.h"
+#include "col4.h"
+
+#include "../simd/sse.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// SSE RGBA Color Class
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct Color4
+ {
+ union {
+ __m128 m128;
+ struct { float r,g,b,a; };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Color4 () {}
+ __forceinline Color4 ( const __m128 a ) : m128(a) {}
+
+ __forceinline explicit Color4 (const float v) : m128(_mm_set1_ps(v)) {}
+ __forceinline Color4 (const float r, const float g, const float b, const float a) : m128(_mm_set_ps(a,b,g,r)) {}
+
+ __forceinline explicit Color4 ( const Col3uc& other ) { m128 = _mm_mul_ps(_mm_set_ps(255.0f,other.b,other.g,other.r),_mm_set1_ps(one_over_255)); }
+ __forceinline explicit Color4 ( const Col3f& other ) { m128 = _mm_set_ps(1.0f,other.b,other.g,other.r); }
+ __forceinline explicit Color4 ( const Col4uc& other ) { m128 = _mm_mul_ps(_mm_set_ps(other.a,other.b,other.g,other.r),_mm_set1_ps(one_over_255)); }
+ __forceinline explicit Color4 ( const Col4f& other ) { m128 = _mm_set_ps(other.a,other.b,other.g,other.r); }
+
+ __forceinline Color4 ( const Color4& other ) : m128(other.m128) {}
+ __forceinline Color4& operator=( const Color4& other ) { m128 = other.m128; return *this; }
+
+ __forceinline operator const __m128&() const { return m128; }
+ __forceinline operator __m128&() { return m128; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Set
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline void set(Col3f& d) const { d.r = r; d.g = g; d.b = b; }
+ __forceinline void set(Col4f& d) const { d.r = r; d.g = g; d.b = b; d.a = a; }
+ __forceinline void set(Col3uc& d) const
+ {
+ vfloat4 s = clamp(vfloat4(m128))*255.0f;
+ d.r = (unsigned char)(s[0]);
+ d.g = (unsigned char)(s[1]);
+ d.b = (unsigned char)(s[2]);
+ }
+ __forceinline void set(Col4uc& d) const
+ {
+ vfloat4 s = clamp(vfloat4(m128))*255.0f;
+ d.r = (unsigned char)(s[0]);
+ d.g = (unsigned char)(s[1]);
+ d.b = (unsigned char)(s[2]);
+ d.a = (unsigned char)(s[3]);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Color4( ZeroTy ) : m128(_mm_set1_ps(0.0f)) {}
+ __forceinline Color4( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
+ __forceinline Color4( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
+ __forceinline Color4( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// SSE RGB Color Class
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct Color
+ {
+ union {
+ __m128 m128;
+ struct { float r,g,b; };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Color () {}
+ __forceinline Color ( const __m128 a ) : m128(a) {}
+
+ __forceinline explicit Color (const float v) : m128(_mm_set1_ps(v)) {}
+ __forceinline Color (const float r, const float g, const float b) : m128(_mm_set_ps(0.0f,b,g,r)) {}
+
+ __forceinline Color ( const Color& other ) : m128(other.m128) {}
+ __forceinline Color& operator=( const Color& other ) { m128 = other.m128; return *this; }
+
+ __forceinline Color ( const Color4& other ) : m128(other.m128) {}
+ __forceinline Color& operator=( const Color4& other ) { m128 = other.m128; return *this; }
+
+ __forceinline operator const __m128&() const { return m128; }
+ __forceinline operator __m128&() { return m128; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Set
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline void set(Col3f& d) const { d.r = r; d.g = g; d.b = b; }
+ __forceinline void set(Col4f& d) const { d.r = r; d.g = g; d.b = b; d.a = 1.0f; }
+ __forceinline void set(Col3uc& d) const
+ {
+ vfloat4 s = clamp(vfloat4(m128))*255.0f;
+ d.r = (unsigned char)(s[0]);
+ d.g = (unsigned char)(s[1]);
+ d.b = (unsigned char)(s[2]);
+ }
+ __forceinline void set(Col4uc& d) const
+ {
+ vfloat4 s = clamp(vfloat4(m128))*255.0f;
+ d.r = (unsigned char)(s[0]);
+ d.g = (unsigned char)(s[1]);
+ d.b = (unsigned char)(s[2]);
+ d.a = 255;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Color( ZeroTy ) : m128(_mm_set1_ps(0.0f)) {}
+ __forceinline Color( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
+ __forceinline Color( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
+ __forceinline Color( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const Color operator +( const Color& a ) { return a; }
+ __forceinline const Color operator -( const Color& a ) {
+ const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
+ return _mm_xor_ps(a.m128, mask);
+ }
+ __forceinline const Color abs ( const Color& a ) {
+ const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
+ return _mm_and_ps(a.m128, mask);
+ }
+ __forceinline const Color rcp ( const Color& a )
+ {
+#if defined(__AVX512VL__)
+ const Color r = _mm_rcp14_ps(a.m128);
+#else
+ const Color r = _mm_rcp_ps(a.m128);
+#endif
+ return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+ }
+ __forceinline const Color rsqrt( const Color& a )
+ {
+#if defined(__AVX512VL__)
+ __m128 r = _mm_rsqrt14_ps(a.m128);
+#else
+ __m128 r = _mm_rsqrt_ps(a.m128);
+#endif
+ return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+ }
+ __forceinline const Color sqrt ( const Color& a ) { return _mm_sqrt_ps(a.m128); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const Color operator +( const Color& a, const Color& b ) { return _mm_add_ps(a.m128, b.m128); }
+ __forceinline const Color operator -( const Color& a, const Color& b ) { return _mm_sub_ps(a.m128, b.m128); }
+ __forceinline const Color operator *( const Color& a, const Color& b ) { return _mm_mul_ps(a.m128, b.m128); }
+ __forceinline const Color operator *( const Color& a, const float b ) { return a * Color(b); }
+ __forceinline const Color operator *( const float a, const Color& b ) { return Color(a) * b; }
+ __forceinline const Color operator /( const Color& a, const Color& b ) { return a * rcp(b); }
+ __forceinline const Color operator /( const Color& a, const float b ) { return a * rcp(b); }
+
+ __forceinline const Color min( const Color& a, const Color& b ) { return _mm_min_ps(a.m128,b.m128); }
+ __forceinline const Color max( const Color& a, const Color& b ) { return _mm_max_ps(a.m128,b.m128); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const Color operator+=(Color& a, const Color& b) { return a = a + b; }
+ __forceinline const Color operator-=(Color& a, const Color& b) { return a = a - b; }
+ __forceinline const Color operator*=(Color& a, const Color& b) { return a = a * b; }
+ __forceinline const Color operator/=(Color& a, const Color& b) { return a = a / b; }
+ __forceinline const Color operator*=(Color& a, const float b ) { return a = a * b; }
+ __forceinline const Color operator/=(Color& a, const float b ) { return a = a / b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline float reduce_add(const Color& v) { return v.r+v.g+v.b; }
+ __forceinline float reduce_mul(const Color& v) { return v.r*v.g*v.b; }
+ __forceinline float reduce_min(const Color& v) { return min(v.r,v.g,v.b); }
+ __forceinline float reduce_max(const Color& v) { return max(v.r,v.g,v.b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator ==( const Color& a, const Color& b ) { return (_mm_movemask_ps(_mm_cmpeq_ps (a.m128, b.m128)) & 7) == 7; }
+ __forceinline bool operator !=( const Color& a, const Color& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 7) != 0; }
+ __forceinline bool operator < ( const Color& a, const Color& b ) {
+ if (a.r != b.r) return a.r < b.r;
+ if (a.g != b.g) return a.g < b.g;
+ if (a.b != b.b) return a.b < b.b;
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const Color select( bool s, const Color& t, const Color& f ) {
+ __m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
+ return blendv_ps(f, t, mask);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Special Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ /*! computes luminance of a color */
+ __forceinline float luminance (const Color& a) { return madd(0.212671f,a.r,madd(0.715160f,a.g,0.072169f*a.b)); }
+
+ /*! output operator */
+ __forceinline embree_ostream operator<<(embree_ostream cout, const Color& a) {
+ return cout << "(" << a.r << ", " << a.g << ", " << a.b << ")";
+ }
+}
diff --git a/thirdparty/embree/common/math/constants.cpp b/thirdparty/embree/common/math/constants.cpp
new file mode 100644
index 0000000000..03919ae20c
--- /dev/null
+++ b/thirdparty/embree/common/math/constants.cpp
@@ -0,0 +1,27 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "constants.h"
+
+namespace embree
+{
+ TrueTy True;
+ FalseTy False;
+ ZeroTy zero;
+ OneTy one;
+ NegInfTy neg_inf;
+ PosInfTy inf;
+ PosInfTy pos_inf;
+ NaNTy nan;
+ UlpTy ulp;
+ PiTy pi;
+ OneOverPiTy one_over_pi;
+ TwoPiTy two_pi;
+ OneOverTwoPiTy one_over_two_pi;
+ FourPiTy four_pi;
+ OneOverFourPiTy one_over_four_pi;
+ StepTy step;
+ ReverseStepTy reverse_step;
+ EmptyTy empty;
+ UndefinedTy undefined;
+}
diff --git a/thirdparty/embree/common/math/constants.h b/thirdparty/embree/common/math/constants.h
new file mode 100644
index 0000000000..578473a8ab
--- /dev/null
+++ b/thirdparty/embree/common/math/constants.h
@@ -0,0 +1,197 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+
+#include <limits>
+
+#define _USE_MATH_DEFINES
+#include <math.h> // using cmath causes issues under Windows
+#include <cfloat>
+#include <climits>
+
+namespace embree
+{
+ static MAYBE_UNUSED const float one_over_255 = 1.0f/255.0f;
+ static MAYBE_UNUSED const float min_rcp_input = 1E-18f; // for abs(x) >= min_rcp_input the newton raphson rcp calculation does not fail
+
+ /* we consider floating point numbers in that range as valid input numbers */
+ static MAYBE_UNUSED float FLT_LARGE = 1.844E18f;
+
+ struct TrueTy {
+ __forceinline operator bool( ) const { return true; }
+ };
+
+ extern MAYBE_UNUSED TrueTy True;
+
+ struct FalseTy {
+ __forceinline operator bool( ) const { return false; }
+ };
+
+ extern MAYBE_UNUSED FalseTy False;
+
+ struct ZeroTy
+ {
+ __forceinline operator double ( ) const { return 0; }
+ __forceinline operator float ( ) const { return 0; }
+ __forceinline operator long long( ) const { return 0; }
+ __forceinline operator unsigned long long( ) const { return 0; }
+ __forceinline operator long ( ) const { return 0; }
+ __forceinline operator unsigned long ( ) const { return 0; }
+ __forceinline operator int ( ) const { return 0; }
+ __forceinline operator unsigned int ( ) const { return 0; }
+ __forceinline operator short ( ) const { return 0; }
+ __forceinline operator unsigned short ( ) const { return 0; }
+ __forceinline operator char ( ) const { return 0; }
+ __forceinline operator unsigned char ( ) const { return 0; }
+ };
+
+ extern MAYBE_UNUSED ZeroTy zero;
+
+ struct OneTy
+ {
+ __forceinline operator double ( ) const { return 1; }
+ __forceinline operator float ( ) const { return 1; }
+ __forceinline operator long long( ) const { return 1; }
+ __forceinline operator unsigned long long( ) const { return 1; }
+ __forceinline operator long ( ) const { return 1; }
+ __forceinline operator unsigned long ( ) const { return 1; }
+ __forceinline operator int ( ) const { return 1; }
+ __forceinline operator unsigned int ( ) const { return 1; }
+ __forceinline operator short ( ) const { return 1; }
+ __forceinline operator unsigned short ( ) const { return 1; }
+ __forceinline operator char ( ) const { return 1; }
+ __forceinline operator unsigned char ( ) const { return 1; }
+ };
+
+ extern MAYBE_UNUSED OneTy one;
+
+ struct NegInfTy
+ {
+ __forceinline operator double ( ) const { return -std::numeric_limits<double>::infinity(); }
+ __forceinline operator float ( ) const { return -std::numeric_limits<float>::infinity(); }
+ __forceinline operator long long( ) const { return std::numeric_limits<long long>::min(); }
+ __forceinline operator unsigned long long( ) const { return std::numeric_limits<unsigned long long>::min(); }
+ __forceinline operator long ( ) const { return std::numeric_limits<long>::min(); }
+ __forceinline operator unsigned long ( ) const { return std::numeric_limits<unsigned long>::min(); }
+ __forceinline operator int ( ) const { return std::numeric_limits<int>::min(); }
+ __forceinline operator unsigned int ( ) const { return std::numeric_limits<unsigned int>::min(); }
+ __forceinline operator short ( ) const { return std::numeric_limits<short>::min(); }
+ __forceinline operator unsigned short ( ) const { return std::numeric_limits<unsigned short>::min(); }
+ __forceinline operator char ( ) const { return std::numeric_limits<char>::min(); }
+ __forceinline operator unsigned char ( ) const { return std::numeric_limits<unsigned char>::min(); }
+
+ };
+
+ extern MAYBE_UNUSED NegInfTy neg_inf;
+
+ struct PosInfTy
+ {
+ __forceinline operator double ( ) const { return std::numeric_limits<double>::infinity(); }
+ __forceinline operator float ( ) const { return std::numeric_limits<float>::infinity(); }
+ __forceinline operator long long( ) const { return std::numeric_limits<long long>::max(); }
+ __forceinline operator unsigned long long( ) const { return std::numeric_limits<unsigned long long>::max(); }
+ __forceinline operator long ( ) const { return std::numeric_limits<long>::max(); }
+ __forceinline operator unsigned long ( ) const { return std::numeric_limits<unsigned long>::max(); }
+ __forceinline operator int ( ) const { return std::numeric_limits<int>::max(); }
+ __forceinline operator unsigned int ( ) const { return std::numeric_limits<unsigned int>::max(); }
+ __forceinline operator short ( ) const { return std::numeric_limits<short>::max(); }
+ __forceinline operator unsigned short ( ) const { return std::numeric_limits<unsigned short>::max(); }
+ __forceinline operator char ( ) const { return std::numeric_limits<char>::max(); }
+ __forceinline operator unsigned char ( ) const { return std::numeric_limits<unsigned char>::max(); }
+ };
+
+ extern MAYBE_UNUSED PosInfTy inf;
+ extern MAYBE_UNUSED PosInfTy pos_inf;
+
+ struct NaNTy
+ {
+ __forceinline operator double( ) const { return std::numeric_limits<double>::quiet_NaN(); }
+ __forceinline operator float ( ) const { return std::numeric_limits<float>::quiet_NaN(); }
+ };
+
+ extern MAYBE_UNUSED NaNTy nan;
+
+ struct UlpTy
+ {
+ __forceinline operator double( ) const { return std::numeric_limits<double>::epsilon(); }
+ __forceinline operator float ( ) const { return std::numeric_limits<float>::epsilon(); }
+ };
+
+ extern MAYBE_UNUSED UlpTy ulp;
+
+ struct PiTy
+ {
+ __forceinline operator double( ) const { return double(M_PI); }
+ __forceinline operator float ( ) const { return float(M_PI); }
+ };
+
+ extern MAYBE_UNUSED PiTy pi;
+
+ struct OneOverPiTy
+ {
+ __forceinline operator double( ) const { return double(M_1_PI); }
+ __forceinline operator float ( ) const { return float(M_1_PI); }
+ };
+
+ extern MAYBE_UNUSED OneOverPiTy one_over_pi;
+
+ struct TwoPiTy
+ {
+ __forceinline operator double( ) const { return double(2.0*M_PI); }
+ __forceinline operator float ( ) const { return float(2.0*M_PI); }
+ };
+
+ extern MAYBE_UNUSED TwoPiTy two_pi;
+
+ struct OneOverTwoPiTy
+ {
+ __forceinline operator double( ) const { return double(0.5*M_1_PI); }
+ __forceinline operator float ( ) const { return float(0.5*M_1_PI); }
+ };
+
+ extern MAYBE_UNUSED OneOverTwoPiTy one_over_two_pi;
+
+ struct FourPiTy
+ {
+ __forceinline operator double( ) const { return double(4.0*M_PI); }
+ __forceinline operator float ( ) const { return float(4.0*M_PI); }
+ };
+
+ extern MAYBE_UNUSED FourPiTy four_pi;
+
+ struct OneOverFourPiTy
+ {
+ __forceinline operator double( ) const { return double(0.25*M_1_PI); }
+ __forceinline operator float ( ) const { return float(0.25*M_1_PI); }
+ };
+
+ extern MAYBE_UNUSED OneOverFourPiTy one_over_four_pi;
+
+ struct StepTy {
+ };
+
+ extern MAYBE_UNUSED StepTy step;
+
+ struct ReverseStepTy {
+ };
+
+ extern MAYBE_UNUSED ReverseStepTy reverse_step;
+
+ struct EmptyTy {
+ };
+
+ extern MAYBE_UNUSED EmptyTy empty;
+
+ struct FullTy {
+ };
+
+ extern MAYBE_UNUSED FullTy full;
+
+ struct UndefinedTy {
+ };
+
+ extern MAYBE_UNUSED UndefinedTy undefined;
+}
diff --git a/thirdparty/embree/common/math/interval.h b/thirdparty/embree/common/math/interval.h
new file mode 100644
index 0000000000..310add2129
--- /dev/null
+++ b/thirdparty/embree/common/math/interval.h
@@ -0,0 +1,161 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "vec2.h"
+#include "vec3.h"
+#include "bbox.h"
+
+namespace embree
+{
+ template<typename V>
+ struct Interval
+ {
+ V lower, upper;
+
+ __forceinline Interval() {}
+ __forceinline Interval ( const Interval& other ) { lower = other.lower; upper = other.upper; }
+ __forceinline Interval& operator=( const Interval& other ) { lower = other.lower; upper = other.upper; return *this; }
+
+ __forceinline Interval(const V& a) : lower(a), upper(a) {}
+ __forceinline Interval(const V& lower, const V& upper) : lower(lower), upper(upper) {}
+ __forceinline Interval(const BBox<V>& a) : lower(a.lower), upper(a.upper) {}
+
+ /*! tests if box is empty */
+ //__forceinline bool empty() const { return lower > upper; }
+
+ /*! computes the size of the interval */
+ __forceinline V size() const { return upper - lower; }
+
+ __forceinline V center() const { return 0.5f*(lower+upper); }
+
+ __forceinline const Interval& extend(const Interval& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }
+ __forceinline const Interval& extend(const V & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }
+
+ __forceinline friend Interval operator +( const Interval& a, const Interval& b ) {
+ return Interval(a.lower+b.lower,a.upper+b.upper);
+ }
+
+ __forceinline friend Interval operator -( const Interval& a, const Interval& b ) {
+ return Interval(a.lower-b.upper,a.upper-b.lower);
+ }
+
+ __forceinline friend Interval operator -( const Interval& a, const V& b ) {
+ return Interval(a.lower-b,a.upper-b);
+ }
+
+ __forceinline friend Interval operator *( const Interval& a, const Interval& b )
+ {
+ const V ll = a.lower*b.lower;
+ const V lu = a.lower*b.upper;
+ const V ul = a.upper*b.lower;
+ const V uu = a.upper*b.upper;
+ return Interval(min(ll,lu,ul,uu),max(ll,lu,ul,uu));
+ }
+
+ __forceinline friend Interval merge( const Interval& a, const Interval& b) {
+ return Interval(min(a.lower,b.lower),max(a.upper,b.upper));
+ }
+
+ __forceinline friend Interval merge( const Interval& a, const Interval& b, const Interval& c) {
+ return merge(merge(a,b),c);
+ }
+
+ __forceinline friend Interval merge( const Interval& a, const Interval& b, const Interval& c, const Interval& d) {
+ return merge(merge(a,b),merge(c,d));
+ }
+
+ /*! intersect bounding boxes */
+ __forceinline friend const Interval intersect( const Interval& a, const Interval& b ) { return Interval(max(a.lower, b.lower), min(a.upper, b.upper)); }
+ __forceinline friend const Interval intersect( const Interval& a, const Interval& b, const Interval& c ) { return intersect(a,intersect(b,c)); }
+ __forceinline friend const Interval intersect( const Interval& a, const Interval& b, const Interval& c, const Interval& d ) { return intersect(intersect(a,b),intersect(c,d)); }
+
+ friend embree_ostream operator<<(embree_ostream cout, const Interval& a) {
+ return cout << "[" << a.lower << ", " << a.upper << "]";
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Interval( EmptyTy ) : lower(pos_inf), upper(neg_inf) {}
+ __forceinline Interval( FullTy ) : lower(neg_inf), upper(pos_inf) {}
+ };
+
+ __forceinline bool isEmpty(const Interval<float>& v) {
+ return v.lower > v.upper;
+ }
+
+ __forceinline vboolx isEmpty(const Interval<vfloatx>& v) {
+ return v.lower > v.upper;
+ }
+
+ /*! subset relation */
+ template<typename T> __forceinline bool subset( const Interval<T>& a, const Interval<T>& b ) {
+ return (a.lower > b.lower) && (a.upper < b.upper);
+ }
+
+ template<typename T> __forceinline bool subset( const Vec2<Interval<T>>& a, const Vec2<Interval<T>>& b ) {
+ return subset(a.x,b.x) && subset(a.y,b.y);
+ }
+
+ template<typename T> __forceinline const Vec2<Interval<T>> intersect( const Vec2<Interval<T>>& a, const Vec2<Interval<T>>& b ) {
+ return Vec2<Interval<T>>(intersect(a.x,b.x),intersect(a.y,b.y));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Interval<T> select ( bool s, const Interval<T>& t, const Interval<T>& f ) {
+ return Interval<T>(select(s,t.lower,f.lower),select(s,t.upper,f.upper));
+ }
+
+ template<typename T> __forceinline Interval<T> select ( const typename T::Bool& s, const Interval<T>& t, const Interval<T>& f ) {
+ return Interval<T>(select(s,t.lower,f.lower),select(s,t.upper,f.upper));
+ }
+
+ __forceinline int numRoots(const Interval<float>& p0, const Interval<float>& p1)
+ {
+ float eps = 1E-4f;
+ bool neg0 = p0.lower < eps; bool pos0 = p0.upper > -eps;
+ bool neg1 = p1.lower < eps; bool pos1 = p1.upper > -eps;
+ return (neg0 && pos1) || (pos0 && neg1) || (neg0 && pos0) || (neg1 && pos1);
+ }
+
+ typedef Interval<float> Interval1f;
+ typedef Vec2<Interval<float>> Interval2f;
+ typedef Vec3<Interval<float>> Interval3f;
+
+inline void swap(float& a, float& b) { float tmp = a; a = b; b = tmp; }
+
+inline Interval1f shift(const Interval1f& v, float shift) { return Interval1f(v.lower + shift, v.upper + shift); }
+
+#define TWO_PI (2.0*M_PI)
+inline Interval1f sin(Interval1f interval)
+{
+ if (interval.upper-interval.lower >= M_PI) { return Interval1f(-1.0, 1.0); }
+ if (interval.upper > TWO_PI) { interval = shift(interval, -TWO_PI*floor(interval.upper/TWO_PI)); }
+ if (interval.lower < 0) { interval = shift(interval, -TWO_PI*floor(interval.lower/TWO_PI)); }
+ float sinLower = sin(interval.lower);
+ float sinUpper = sin(interval.upper);
+ if (sinLower > sinUpper) swap(sinLower, sinUpper);
+ if (interval.lower < M_PI / 2.0 && interval.upper > M_PI / 2.0) sinUpper = 1.0;
+ if (interval.lower < 3.0 * M_PI / 2.0 && interval.upper > 3.0 * M_PI / 2.0) sinLower = -1.0;
+ return Interval1f(sinLower, sinUpper);
+}
+
+inline Interval1f cos(Interval1f interval)
+{
+ if (interval.upper-interval.lower >= M_PI) { return Interval1f(-1.0, 1.0); }
+ if (interval.upper > TWO_PI) { interval = shift(interval, -TWO_PI*floor(interval.upper/TWO_PI)); }
+ if (interval.lower < 0) { interval = shift(interval, -TWO_PI*floor(interval.lower/TWO_PI)); }
+ float cosLower = cos(interval.lower);
+ float cosUpper = cos(interval.upper);
+ if (cosLower > cosUpper) swap(cosLower, cosUpper);
+ if (interval.lower < M_PI && interval.upper > M_PI) cosLower = -1.0;
+ return Interval1f(cosLower, cosUpper);
+}
+#undef TWO_PI
+}
diff --git a/thirdparty/embree/common/math/lbbox.h b/thirdparty/embree/common/math/lbbox.h
new file mode 100644
index 0000000000..2b397a05c8
--- /dev/null
+++ b/thirdparty/embree/common/math/lbbox.h
@@ -0,0 +1,289 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bbox.h"
+#include "range.h"
+
+namespace embree
+{
+ template<typename T>
+ __forceinline std::pair<T,T> globalLinear(const std::pair<T,T>& v, const BBox1f& dt)
+ {
+ const float rcp_dt_size = float(1.0f)/dt.size();
+ const T g0 = lerp(v.first,v.second,-dt.lower*rcp_dt_size);
+ const T g1 = lerp(v.first,v.second,(1.0f-dt.lower)*rcp_dt_size);
+ return std::make_pair(g0,g1);
+ }
+
+ template<typename T>
+ struct LBBox
+ {
+ public:
+ __forceinline LBBox () {}
+
+ template<typename T1>
+ __forceinline LBBox ( const LBBox<T1>& other )
+ : bounds0(other.bounds0), bounds1(other.bounds1) {}
+
+ __forceinline LBBox& operator= ( const LBBox& other ) {
+ bounds0 = other.bounds0; bounds1 = other.bounds1; return *this;
+ }
+
+ __forceinline LBBox (EmptyTy)
+ : bounds0(EmptyTy()), bounds1(EmptyTy()) {}
+
+ __forceinline explicit LBBox ( const BBox<T>& bounds)
+ : bounds0(bounds), bounds1(bounds) { }
+
+ __forceinline LBBox ( const BBox<T>& bounds0, const BBox<T>& bounds1)
+ : bounds0(bounds0), bounds1(bounds1) { }
+
+ LBBox ( const avector<BBox<T>>& bounds )
+ {
+ assert(bounds.size());
+ BBox<T> b0 = bounds.front();
+ BBox<T> b1 = bounds.back();
+ for (size_t i=1; i<bounds.size()-1; i++) {
+ const float f = float(i)/float(bounds.size()-1);
+ const BBox<T> bt = lerp(b0,b1,f);
+ const T dlower = min(bounds[i].lower-bt.lower,T(zero));
+ const T dupper = max(bounds[i].upper-bt.upper,T(zero));
+ b0.lower += dlower; b1.lower += dlower;
+ b0.upper += dupper; b1.upper += dupper;
+ }
+ bounds0 = b0;
+ bounds1 = b1;
+ }
+
+ /*! calculates the linear bounds of a primitive for the specified time range */
+ template<typename BoundsFunc>
+ __forceinline LBBox(const BoundsFunc& bounds, const BBox1f& time_range, float numTimeSegments)
+ {
+ const float lower = time_range.lower*numTimeSegments;
+ const float upper = time_range.upper*numTimeSegments;
+ const float ilowerf = floor(lower);
+ const float iupperf = ceil(upper);
+ const int ilower = (int)ilowerf;
+ const int iupper = (int)iupperf;
+
+ const BBox<T> blower0 = bounds(ilower);
+ const BBox<T> bupper1 = bounds(iupper);
+
+ if (iupper-ilower == 1) {
+ bounds0 = lerp(blower0, bupper1, lower-ilowerf);
+ bounds1 = lerp(bupper1, blower0, iupperf-upper);
+ return;
+ }
+
+ const BBox<T> blower1 = bounds(ilower+1);
+ const BBox<T> bupper0 = bounds(iupper-1);
+ BBox<T> b0 = lerp(blower0, blower1, lower-ilowerf);
+ BBox<T> b1 = lerp(bupper1, bupper0, iupperf-upper);
+
+ for (int i = ilower+1; i < iupper; i++)
+ {
+ const float f = (float(i)/numTimeSegments - time_range.lower) / time_range.size();
+ const BBox<T> bt = lerp(b0, b1, f);
+ const BBox<T> bi = bounds(i);
+ const T dlower = min(bi.lower-bt.lower, T(zero));
+ const T dupper = max(bi.upper-bt.upper, T(zero));
+ b0.lower += dlower; b1.lower += dlower;
+ b0.upper += dupper; b1.upper += dupper;
+ }
+
+ bounds0 = b0;
+ bounds1 = b1;
+ }
+
+ /*! calculates the linear bounds of a primitive for the specified time range */
+ template<typename BoundsFunc>
+ __forceinline LBBox(const BoundsFunc& bounds, const BBox1f& time_range_in, const BBox1f& geom_time_range, float geom_time_segments)
+ {
+ /* normalize global time_range_in to local geom_time_range */
+ const BBox1f time_range((time_range_in.lower-geom_time_range.lower)/geom_time_range.size(),
+ (time_range_in.upper-geom_time_range.lower)/geom_time_range.size());
+
+ const float lower = time_range.lower*geom_time_segments;
+ const float upper = time_range.upper*geom_time_segments;
+ const float ilowerf = floor(lower);
+ const float iupperf = ceil(upper);
+ const float ilowerfc = max(0.0f,ilowerf);
+ const float iupperfc = min(iupperf,geom_time_segments);
+ const int ilowerc = (int)ilowerfc;
+ const int iupperc = (int)iupperfc;
+ assert(iupperc-ilowerc > 0);
+
+ /* this larger iteration range guarantees that we process borders of geom_time_range is (partially) inside time_range_in */
+ const int ilower_iter = max(-1,(int)ilowerf);
+ const int iupper_iter = min((int)iupperf,(int)geom_time_segments+1);
+
+ const BBox<T> blower0 = bounds(ilowerc);
+ const BBox<T> bupper1 = bounds(iupperc);
+ if (iupper_iter-ilower_iter == 1) {
+ bounds0 = lerp(blower0, bupper1, max(0.0f,lower-ilowerfc));
+ bounds1 = lerp(bupper1, blower0, max(0.0f,iupperfc-upper));
+ return;
+ }
+
+ const BBox<T> blower1 = bounds(ilowerc+1);
+ const BBox<T> bupper0 = bounds(iupperc-1);
+ BBox<T> b0 = lerp(blower0, blower1, max(0.0f,lower-ilowerfc));
+ BBox<T> b1 = lerp(bupper1, bupper0, max(0.0f,iupperfc-upper));
+
+ for (int i = ilower_iter+1; i < iupper_iter; i++)
+ {
+ const float f = (float(i)/geom_time_segments - time_range.lower) / time_range.size();
+ const BBox<T> bt = lerp(b0, b1, f);
+ const BBox<T> bi = bounds(i);
+ const T dlower = min(bi.lower-bt.lower, T(zero));
+ const T dupper = max(bi.upper-bt.upper, T(zero));
+ b0.lower += dlower; b1.lower += dlower;
+ b0.upper += dupper; b1.upper += dupper;
+ }
+
+ bounds0 = b0;
+ bounds1 = b1;
+ }
+
+ /*! calculates the linear bounds of a primitive for the specified time range */
+ template<typename BoundsFunc>
+ __forceinline LBBox(const BoundsFunc& bounds, const range<int>& time_range, int numTimeSegments)
+ {
+ const int ilower = time_range.begin();
+ const int iupper = time_range.end();
+
+ BBox<T> b0 = bounds(ilower);
+ BBox<T> b1 = bounds(iupper);
+
+ if (iupper-ilower == 1)
+ {
+ bounds0 = b0;
+ bounds1 = b1;
+ return;
+ }
+
+ for (int i = ilower+1; i<iupper; i++)
+ {
+ const float f = float(i - time_range.begin()) / float(time_range.size());
+ const BBox<T> bt = lerp(b0, b1, f);
+ const BBox<T> bi = bounds(i);
+ const T dlower = min(bi.lower-bt.lower, T(zero));
+ const T dupper = max(bi.upper-bt.upper, T(zero));
+ b0.lower += dlower; b1.lower += dlower;
+ b0.upper += dupper; b1.upper += dupper;
+ }
+
+ bounds0 = b0;
+ bounds1 = b1;
+ }
+
+ public:
+
+ __forceinline bool empty() const {
+ return bounds().empty();
+ }
+
+ __forceinline BBox<T> bounds () const {
+ return merge(bounds0,bounds1);
+ }
+
+ __forceinline BBox<T> interpolate( const float t ) const {
+ return lerp(bounds0,bounds1,t);
+ }
+
+ __forceinline LBBox<T> interpolate( const BBox1f& dt ) const {
+ return LBBox<T>(interpolate(dt.lower),interpolate(dt.upper));
+ }
+
+ __forceinline void extend( const LBBox& other ) {
+ bounds0.extend(other.bounds0);
+ bounds1.extend(other.bounds1);
+ }
+
+ __forceinline float expectedHalfArea() const;
+
+ __forceinline float expectedHalfArea(const BBox1f& dt) const {
+ return interpolate(dt).expectedHalfArea();
+ }
+
+ __forceinline float expectedApproxHalfArea() const {
+ return 0.5f*(halfArea(bounds0) + halfArea(bounds1));
+ }
+
+ /* calculates bounds for [0,1] time range from bounds in dt time range */
+ __forceinline LBBox global(const BBox1f& dt) const
+ {
+ const float rcp_dt_size = 1.0f/dt.size();
+ const BBox<T> b0 = interpolate(-dt.lower*rcp_dt_size);
+ const BBox<T> b1 = interpolate((1.0f-dt.lower)*rcp_dt_size);
+ return LBBox(b0,b1);
+ }
+
+ /*! Comparison Operators */
+ //template<typename TT> friend __forceinline bool operator==( const LBBox<TT>& a, const LBBox<TT>& b ) { return a.bounds0 == b.bounds0 && a.bounds1 == b.bounds1; }
+ //template<typename TT> friend __forceinline bool operator!=( const LBBox<TT>& a, const LBBox<TT>& b ) { return a.bounds0 != b.bounds0 || a.bounds1 != b.bounds1; }
+ friend __forceinline bool operator==( const LBBox& a, const LBBox& b ) { return a.bounds0 == b.bounds0 && a.bounds1 == b.bounds1; }
+ friend __forceinline bool operator!=( const LBBox& a, const LBBox& b ) { return a.bounds0 != b.bounds0 || a.bounds1 != b.bounds1; }
+
+ /*! output operator */
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const LBBox& box) {
+ return cout << "LBBox { " << box.bounds0 << "; " << box.bounds1 << " }";
+ }
+
+ public:
+ BBox<T> bounds0, bounds1;
+ };
+
+ /*! tests if box is finite */
+ template<typename T>
+ __forceinline bool isvalid( const LBBox<T>& v ) {
+ return isvalid(v.bounds0) && isvalid(v.bounds1);
+ }
+
+ template<typename T>
+ __forceinline bool isvalid_non_empty( const LBBox<T>& v ) {
+ return isvalid_non_empty(v.bounds0) && isvalid_non_empty(v.bounds1);
+ }
+
+ template<typename T>
+ __forceinline T expectedArea(const T& a0, const T& a1, const T& b0, const T& b1)
+ {
+ const T da = a1-a0;
+ const T db = b1-b0;
+ return a0*b0+(a0*db+da*b0)*T(0.5f) + da*db*T(1.0f/3.0f);
+ }
+
+ template<> __forceinline float LBBox<Vec3fa>::expectedHalfArea() const
+ {
+ const Vec3fa d0 = bounds0.size();
+ const Vec3fa d1 = bounds1.size();
+ return reduce_add(expectedArea(Vec3fa(d0.x,d0.y,d0.z),
+ Vec3fa(d1.x,d1.y,d1.z),
+ Vec3fa(d0.y,d0.z,d0.x),
+ Vec3fa(d1.y,d1.z,d1.x)));
+ }
+
+ template<typename T>
+ __forceinline float expectedApproxHalfArea(const LBBox<T>& box) {
+ return box.expectedApproxHalfArea();
+ }
+
+ template<typename T>
+ __forceinline LBBox<T> merge(const LBBox<T>& a, const LBBox<T>& b) {
+ return LBBox<T>(merge(a.bounds0, b.bounds0), merge(a.bounds1, b.bounds1));
+ }
+
+ /*! subset relation */
+ template<typename T> __inline bool subset( const LBBox<T>& a, const LBBox<T>& b ) {
+ return subset(a.bounds0,b.bounds0) && subset(a.bounds1,b.bounds1);
+ }
+
+ /*! default template instantiations */
+ typedef LBBox<float> LBBox1f;
+ typedef LBBox<Vec2f> LBBox2f;
+ typedef LBBox<Vec3f> LBBox3f;
+ typedef LBBox<Vec3fa> LBBox3fa;
+ typedef LBBox<Vec3fx> LBBox3fx;
+}
diff --git a/thirdparty/embree/common/math/linearspace2.h b/thirdparty/embree/common/math/linearspace2.h
new file mode 100644
index 0000000000..184ee695fb
--- /dev/null
+++ b/thirdparty/embree/common/math/linearspace2.h
@@ -0,0 +1,148 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "vec2.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// 2D Linear Transform (2x2 Matrix)
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> struct LinearSpace2
+ {
+ typedef T Vector;
+ typedef typename T::Scalar Scalar;
+
+ /*! default matrix constructor */
+ __forceinline LinearSpace2 ( ) {}
+ __forceinline LinearSpace2 ( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; }
+ __forceinline LinearSpace2& operator=( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; return *this; }
+
+ template<typename L1> __forceinline LinearSpace2( const LinearSpace2<L1>& s ) : vx(s.vx), vy(s.vy) {}
+
+ /*! matrix construction from column vectors */
+ __forceinline LinearSpace2(const Vector& vx, const Vector& vy)
+ : vx(vx), vy(vy) {}
+
+ /*! matrix construction from row mayor data */
+ __forceinline LinearSpace2(const Scalar& m00, const Scalar& m01,
+ const Scalar& m10, const Scalar& m11)
+ : vx(m00,m10), vy(m01,m11) {}
+
+ /*! compute the determinant of the matrix */
+ __forceinline const Scalar det() const { return vx.x*vy.y - vx.y*vy.x; }
+
+ /*! compute adjoint matrix */
+ __forceinline const LinearSpace2 adjoint() const { return LinearSpace2(vy.y,-vy.x,-vx.y,vx.x); }
+
+ /*! compute inverse matrix */
+ __forceinline const LinearSpace2 inverse() const { return adjoint()/det(); }
+
+ /*! compute transposed matrix */
+ __forceinline const LinearSpace2 transposed() const { return LinearSpace2(vx.x,vx.y,vy.x,vy.y); }
+
+ /*! returns first row of matrix */
+ __forceinline Vector row0() const { return Vector(vx.x,vy.x); }
+
+ /*! returns second row of matrix */
+ __forceinline Vector row1() const { return Vector(vx.y,vy.y); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline LinearSpace2( ZeroTy ) : vx(zero), vy(zero) {}
+ __forceinline LinearSpace2( OneTy ) : vx(one, zero), vy(zero, one) {}
+
+ /*! return matrix for scaling */
+ static __forceinline LinearSpace2 scale(const Vector& s) {
+ return LinearSpace2(s.x, 0,
+ 0 , s.y);
+ }
+
+ /*! return matrix for rotation */
+ static __forceinline LinearSpace2 rotate(const Scalar& r) {
+ Scalar s = sin(r), c = cos(r);
+ return LinearSpace2(c, -s,
+ s, c);
+ }
+
+ /*! return closest orthogonal matrix (i.e. a general rotation including reflection) */
+ LinearSpace2 orthogonal() const
+ {
+ LinearSpace2 m = *this;
+
+ // mirrored?
+ Scalar mirror(one);
+ if (m.det() < Scalar(zero)) {
+ m.vx = -m.vx;
+ mirror = -mirror;
+ }
+
+ // rotation
+ for (int i = 0; i < 99; i++) {
+ const LinearSpace2 m_next = 0.5 * (m + m.transposed().inverse());
+ const LinearSpace2 d = m_next - m;
+ m = m_next;
+ // norm^2 of difference small enough?
+ if (max(dot(d.vx, d.vx), dot(d.vy, d.vy)) < 1e-8)
+ break;
+ }
+
+ // rotation * mirror_x
+ return LinearSpace2(mirror*m.vx, m.vy);
+ }
+
+ public:
+
+ /*! the column vectors of the matrix */
+ Vector vx,vy;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline LinearSpace2<T> operator -( const LinearSpace2<T>& a ) { return LinearSpace2<T>(-a.vx,-a.vy); }
+ template<typename T> __forceinline LinearSpace2<T> operator +( const LinearSpace2<T>& a ) { return LinearSpace2<T>(+a.vx,+a.vy); }
+ template<typename T> __forceinline LinearSpace2<T> rcp ( const LinearSpace2<T>& a ) { return a.inverse(); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline LinearSpace2<T> operator +( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx+b.vx,a.vy+b.vy); }
+ template<typename T> __forceinline LinearSpace2<T> operator -( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx-b.vx,a.vy-b.vy); }
+
+ template<typename T> __forceinline LinearSpace2<T> operator*(const typename T::Scalar & a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
+ template<typename T> __forceinline T operator*(const LinearSpace2<T>& a, const T & b) { return b.x*a.vx + b.y*a.vy; }
+ template<typename T> __forceinline LinearSpace2<T> operator*(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
+
+ template<typename T> __forceinline LinearSpace2<T> operator/(const LinearSpace2<T>& a, const typename T::Scalar & b) { return LinearSpace2<T>(a.vx/b, a.vy/b); }
+ template<typename T> __forceinline LinearSpace2<T> operator/(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return a * rcp(b); }
+
+ template<typename T> __forceinline LinearSpace2<T>& operator *=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a * b; }
+ template<typename T> __forceinline LinearSpace2<T>& operator /=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a / b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline bool operator ==( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx == b.vx && a.vy == b.vy; }
+ template<typename T> __forceinline bool operator !=( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx != b.vx || a.vy != b.vy; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> static embree_ostream operator<<(embree_ostream cout, const LinearSpace2<T>& m) {
+ return cout << "{ vx = " << m.vx << ", vy = " << m.vy << "}";
+ }
+
+ /*! Shortcuts for common linear spaces. */
+ typedef LinearSpace2<Vec2f> LinearSpace2f;
+ typedef LinearSpace2<Vec2fa> LinearSpace2fa;
+}
diff --git a/thirdparty/embree/common/math/linearspace3.h b/thirdparty/embree/common/math/linearspace3.h
new file mode 100644
index 0000000000..9eaa2cc2bb
--- /dev/null
+++ b/thirdparty/embree/common/math/linearspace3.h
@@ -0,0 +1,213 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "vec3.h"
+#include "quaternion.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// 3D Linear Transform (3x3 Matrix)
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> struct LinearSpace3
+ {
+ typedef T Vector;
+ typedef typename T::Scalar Scalar;
+
+ /*! default matrix constructor */
+ __forceinline LinearSpace3 ( ) {}
+ __forceinline LinearSpace3 ( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; }
+ __forceinline LinearSpace3& operator=( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; return *this; }
+
+ template<typename L1> __forceinline LinearSpace3( const LinearSpace3<L1>& s ) : vx(s.vx), vy(s.vy), vz(s.vz) {}
+
+ /*! matrix construction from column vectors */
+ __forceinline LinearSpace3(const Vector& vx, const Vector& vy, const Vector& vz)
+ : vx(vx), vy(vy), vz(vz) {}
+
+ /*! construction from quaternion */
+ __forceinline LinearSpace3( const QuaternionT<Scalar>& q )
+ : vx((q.r*q.r + q.i*q.i - q.j*q.j - q.k*q.k), 2.0f*(q.i*q.j + q.r*q.k), 2.0f*(q.i*q.k - q.r*q.j))
+ , vy(2.0f*(q.i*q.j - q.r*q.k), (q.r*q.r - q.i*q.i + q.j*q.j - q.k*q.k), 2.0f*(q.j*q.k + q.r*q.i))
+ , vz(2.0f*(q.i*q.k + q.r*q.j), 2.0f*(q.j*q.k - q.r*q.i), (q.r*q.r - q.i*q.i - q.j*q.j + q.k*q.k)) {}
+
+ /*! matrix construction from row mayor data */
+ __forceinline LinearSpace3(const Scalar& m00, const Scalar& m01, const Scalar& m02,
+ const Scalar& m10, const Scalar& m11, const Scalar& m12,
+ const Scalar& m20, const Scalar& m21, const Scalar& m22)
+ : vx(m00,m10,m20), vy(m01,m11,m21), vz(m02,m12,m22) {}
+
+ /*! compute the determinant of the matrix */
+ __forceinline const Scalar det() const { return dot(vx,cross(vy,vz)); }
+
+ /*! compute adjoint matrix */
+ __forceinline const LinearSpace3 adjoint() const { return LinearSpace3(cross(vy,vz),cross(vz,vx),cross(vx,vy)).transposed(); }
+
+ /*! compute inverse matrix */
+ __forceinline const LinearSpace3 inverse() const { return adjoint()/det(); }
+
+ /*! compute transposed matrix */
+ __forceinline const LinearSpace3 transposed() const { return LinearSpace3(vx.x,vx.y,vx.z,vy.x,vy.y,vy.z,vz.x,vz.y,vz.z); }
+
+ /*! returns first row of matrix */
+ __forceinline Vector row0() const { return Vector(vx.x,vy.x,vz.x); }
+
+ /*! returns second row of matrix */
+ __forceinline Vector row1() const { return Vector(vx.y,vy.y,vz.y); }
+
+ /*! returns third row of matrix */
+ __forceinline Vector row2() const { return Vector(vx.z,vy.z,vz.z); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline LinearSpace3( ZeroTy ) : vx(zero), vy(zero), vz(zero) {}
+ __forceinline LinearSpace3( OneTy ) : vx(one, zero, zero), vy(zero, one, zero), vz(zero, zero, one) {}
+
+ /*! return matrix for scaling */
+ static __forceinline LinearSpace3 scale(const Vector& s) {
+ return LinearSpace3(s.x, 0, 0,
+ 0 , s.y, 0,
+ 0 , 0, s.z);
+ }
+
+ /*! return matrix for rotation around arbitrary axis */
+ static __forceinline LinearSpace3 rotate(const Vector& _u, const Scalar& r) {
+ Vector u = normalize(_u);
+ Scalar s = sin(r), c = cos(r);
+ return LinearSpace3(u.x*u.x+(1-u.x*u.x)*c, u.x*u.y*(1-c)-u.z*s, u.x*u.z*(1-c)+u.y*s,
+ u.x*u.y*(1-c)+u.z*s, u.y*u.y+(1-u.y*u.y)*c, u.y*u.z*(1-c)-u.x*s,
+ u.x*u.z*(1-c)-u.y*s, u.y*u.z*(1-c)+u.x*s, u.z*u.z+(1-u.z*u.z)*c);
+ }
+
+ public:
+
+ /*! the column vectors of the matrix */
+ Vector vx,vy,vz;
+ };
+
+ /*! compute transposed matrix */
+ template<> __forceinline const LinearSpace3<Vec3fa> LinearSpace3<Vec3fa>::transposed() const {
+ vfloat4 rx,ry,rz; transpose((vfloat4&)vx,(vfloat4&)vy,(vfloat4&)vz,vfloat4(zero),rx,ry,rz);
+ return LinearSpace3<Vec3fa>(Vec3fa(rx),Vec3fa(ry),Vec3fa(rz));
+ }
+
+ template<typename T>
+ __forceinline const LinearSpace3<T> transposed(const LinearSpace3<T>& xfm) {
+ return xfm.transposed();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline LinearSpace3<T> operator -( const LinearSpace3<T>& a ) { return LinearSpace3<T>(-a.vx,-a.vy,-a.vz); }
+ template<typename T> __forceinline LinearSpace3<T> operator +( const LinearSpace3<T>& a ) { return LinearSpace3<T>(+a.vx,+a.vy,+a.vz); }
+ template<typename T> __forceinline LinearSpace3<T> rcp ( const LinearSpace3<T>& a ) { return a.inverse(); }
+
+ /* constructs a coordinate frame form a normalized normal */
+ template<typename T> __forceinline LinearSpace3<T> frame(const T& N)
+ {
+ const T dx0(0,N.z,-N.y);
+ const T dx1(-N.z,0,N.x);
+ const T dx = normalize(select(dot(dx0,dx0) > dot(dx1,dx1),dx0,dx1));
+ const T dy = normalize(cross(N,dx));
+ return LinearSpace3<T>(dx,dy,N);
+ }
+
+ /* constructs a coordinate frame from a normal and approximate x-direction */
+ template<typename T> __forceinline LinearSpace3<T> frame(const T& N, const T& dxi)
+ {
+ if (abs(dot(dxi,N)) > 0.99f) return frame(N); // fallback in case N and dxi are very parallel
+ const T dx = normalize(cross(dxi,N));
+ const T dy = normalize(cross(N,dx));
+ return LinearSpace3<T>(dx,dy,N);
+ }
+
+ /* clamps linear space to range -1 to +1 */
+ template<typename T> __forceinline LinearSpace3<T> clamp(const LinearSpace3<T>& space) {
+ return LinearSpace3<T>(clamp(space.vx,T(-1.0f),T(1.0f)),
+ clamp(space.vy,T(-1.0f),T(1.0f)),
+ clamp(space.vz,T(-1.0f),T(1.0f)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline LinearSpace3<T> operator +( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return LinearSpace3<T>(a.vx+b.vx,a.vy+b.vy,a.vz+b.vz); }
+ template<typename T> __forceinline LinearSpace3<T> operator -( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return LinearSpace3<T>(a.vx-b.vx,a.vy-b.vy,a.vz-b.vz); }
+
+ template<typename T> __forceinline LinearSpace3<T> operator*(const typename T::Scalar & a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
+ template<typename T> __forceinline T operator*(const LinearSpace3<T>& a, const T & b) { return madd(T(b.x),a.vx,madd(T(b.y),a.vy,T(b.z)*a.vz)); }
+ template<typename T> __forceinline LinearSpace3<T> operator*(const LinearSpace3<T>& a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
+
+ template<typename T> __forceinline LinearSpace3<T> operator/(const LinearSpace3<T>& a, const typename T::Scalar & b) { return LinearSpace3<T>(a.vx/b, a.vy/b, a.vz/b); }
+ template<typename T> __forceinline LinearSpace3<T> operator/(const LinearSpace3<T>& a, const LinearSpace3<T>& b) { return a * rcp(b); }
+
+ template<typename T> __forceinline LinearSpace3<T>& operator *=( LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a = a * b; }
+ template<typename T> __forceinline LinearSpace3<T>& operator /=( LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a = a / b; }
+
+ template<typename T> __forceinline T xfmPoint (const LinearSpace3<T>& s, const T & a) { return madd(T(a.x),s.vx,madd(T(a.y),s.vy,T(a.z)*s.vz)); }
+ template<typename T> __forceinline T xfmVector(const LinearSpace3<T>& s, const T & a) { return madd(T(a.x),s.vx,madd(T(a.y),s.vy,T(a.z)*s.vz)); }
+ template<typename T> __forceinline T xfmNormal(const LinearSpace3<T>& s, const T & a) { return xfmVector(s.inverse().transposed(),a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline bool operator ==( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx == b.vx && a.vy == b.vy && a.vz == b.vz; }
+ template<typename T> __forceinline bool operator !=( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx != b.vx || a.vy != b.vy || a.vz != b.vz; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline LinearSpace3<T> select ( const typename T::Scalar::Bool& s, const LinearSpace3<T>& t, const LinearSpace3<T>& f ) {
+ return LinearSpace3<T>(select(s,t.vx,f.vx),select(s,t.vy,f.vy),select(s,t.vz,f.vz));
+ }
+
+ /*! blending */
+ template<typename T>
+ __forceinline LinearSpace3<T> lerp(const LinearSpace3<T>& l0, const LinearSpace3<T>& l1, const float t)
+ {
+ return LinearSpace3<T>(lerp(l0.vx,l1.vx,t),
+ lerp(l0.vy,l1.vy,t),
+ lerp(l0.vz,l1.vz,t));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> static embree_ostream operator<<(embree_ostream cout, const LinearSpace3<T>& m) {
+ return cout << "{ vx = " << m.vx << ", vy = " << m.vy << ", vz = " << m.vz << "}";
+ }
+
+ /*! Shortcuts for common linear spaces. */
+ typedef LinearSpace3<Vec3f> LinearSpace3f;
+ typedef LinearSpace3<Vec3fa> LinearSpace3fa;
+ typedef LinearSpace3<Vec3fx> LinearSpace3fx;
+ typedef LinearSpace3<Vec3ff> LinearSpace3ff;
+
+ template<int N> using LinearSpace3vf = LinearSpace3<Vec3<vfloat<N>>>;
+ typedef LinearSpace3<Vec3<vfloat<4>>> LinearSpace3vf4;
+ typedef LinearSpace3<Vec3<vfloat<8>>> LinearSpace3vf8;
+ typedef LinearSpace3<Vec3<vfloat<16>>> LinearSpace3vf16;
+
+ /*! blending */
+ template<typename T, typename S>
+ __forceinline LinearSpace3<T> lerp(const LinearSpace3<T>& l0,
+ const LinearSpace3<T>& l1,
+ const S& t)
+ {
+ return LinearSpace3<T>(lerp(l0.vx,l1.vx,t),
+ lerp(l0.vy,l1.vy,t),
+ lerp(l0.vz,l1.vz,t));
+ }
+
+}
diff --git a/thirdparty/embree/common/math/math.h b/thirdparty/embree/common/math/math.h
new file mode 100644
index 0000000000..4bc54c1a6a
--- /dev/null
+++ b/thirdparty/embree/common/math/math.h
@@ -0,0 +1,369 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+#include "../sys/intrinsics.h"
+#include "constants.h"
+#include <cmath>
+
+#if defined(__ARM_NEON)
+#include "../simd/arm/emulation.h"
+#else
+#include <emmintrin.h>
+#include <xmmintrin.h>
+#include <immintrin.h>
+#endif
+
+#if defined(__WIN32__)
+#if defined(_MSC_VER) && (_MSC_VER <= 1700)
+namespace std
+{
+ __forceinline bool isinf ( const float x ) { return _finite(x) == 0; }
+ __forceinline bool isnan ( const float x ) { return _isnan(x) != 0; }
+ __forceinline bool isfinite (const float x) { return _finite(x) != 0; }
+}
+#endif
+#endif
+
+namespace embree
+{
+ __forceinline bool isvalid ( const float& v ) {
+ return (v > -FLT_LARGE) & (v < +FLT_LARGE);
+ }
+
+ __forceinline int cast_f2i(float f) {
+ union { float f; int i; } v; v.f = f; return v.i;
+ }
+
+ __forceinline float cast_i2f(int i) {
+ union { float f; int i; } v; v.i = i; return v.f;
+ }
+
+ __forceinline int toInt (const float& a) { return int(a); }
+ __forceinline float toFloat(const int& a) { return float(a); }
+
+#if defined(__WIN32__)
+ __forceinline bool finite ( const float x ) { return _finite(x) != 0; }
+#endif
+
+ __forceinline float sign ( const float x ) { return x<0?-1.0f:1.0f; }
+ __forceinline float sqr ( const float x ) { return x*x; }
+
+ __forceinline float rcp ( const float x )
+ {
+ const __m128 a = _mm_set_ss(x);
+
+#if defined(__AVX512VL__)
+ const __m128 r = _mm_rcp14_ss(_mm_set_ss(0.0f),a);
+#else
+ const __m128 r = _mm_rcp_ss(a);
+#endif
+
+#if defined(__AVX2__)
+ return _mm_cvtss_f32(_mm_mul_ss(r,_mm_fnmadd_ss(r, a, _mm_set_ss(2.0f))));
+#else
+ return _mm_cvtss_f32(_mm_mul_ss(r,_mm_sub_ss(_mm_set_ss(2.0f), _mm_mul_ss(r, a))));
+#endif
+ }
+
+ __forceinline float signmsk ( const float x ) {
+ return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
+ }
+ __forceinline float xorf( const float x, const float y ) {
+ return _mm_cvtss_f32(_mm_xor_ps(_mm_set_ss(x),_mm_set_ss(y)));
+ }
+ __forceinline float andf( const float x, const unsigned y ) {
+ return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(y))));
+ }
+ __forceinline float rsqrt( const float x )
+ {
+ const __m128 a = _mm_set_ss(x);
+#if defined(__AVX512VL__)
+ __m128 r = _mm_rsqrt14_ss(_mm_set_ss(0.0f),a);
+#else
+ __m128 r = _mm_rsqrt_ss(a);
+#endif
+ r = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r), _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)));
+#if defined(__ARM_NEON)
+ r = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r), _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)));
+#endif
+ return _mm_cvtss_f32(r);
+ }
+
+#if defined(__WIN32__) && defined(_MSC_VER) && (_MSC_VER <= 1700)
+ __forceinline float nextafter(float x, float y) { if ((x<y) == (x>0)) return x*(1.1f+float(ulp)); else return x*(0.9f-float(ulp)); }
+ __forceinline double nextafter(double x, double y) { return _nextafter(x, y); }
+ __forceinline int roundf(float f) { return (int)(f + 0.5f); }
+#else
+ __forceinline float nextafter(float x, float y) { return ::nextafterf(x, y); }
+ __forceinline double nextafter(double x, double y) { return ::nextafter(x, y); }
+#endif
+
+ __forceinline float abs ( const float x ) { return ::fabsf(x); }
+ __forceinline float acos ( const float x ) { return ::acosf (x); }
+ __forceinline float asin ( const float x ) { return ::asinf (x); }
+ __forceinline float atan ( const float x ) { return ::atanf (x); }
+ __forceinline float atan2( const float y, const float x ) { return ::atan2f(y, x); }
+ __forceinline float cos ( const float x ) { return ::cosf (x); }
+ __forceinline float cosh ( const float x ) { return ::coshf (x); }
+ __forceinline float exp ( const float x ) { return ::expf (x); }
+ __forceinline float fmod ( const float x, const float y ) { return ::fmodf (x, y); }
+ __forceinline float log ( const float x ) { return ::logf (x); }
+ __forceinline float log10( const float x ) { return ::log10f(x); }
+ __forceinline float pow ( const float x, const float y ) { return ::powf (x, y); }
+ __forceinline float sin ( const float x ) { return ::sinf (x); }
+ __forceinline float sinh ( const float x ) { return ::sinhf (x); }
+ __forceinline float sqrt ( const float x ) { return ::sqrtf (x); }
+ __forceinline float tan ( const float x ) { return ::tanf (x); }
+ __forceinline float tanh ( const float x ) { return ::tanhf (x); }
+ __forceinline float floor( const float x ) { return ::floorf (x); }
+ __forceinline float ceil ( const float x ) { return ::ceilf (x); }
+ __forceinline float frac ( const float x ) { return x-floor(x); }
+
+ __forceinline double abs ( const double x ) { return ::fabs(x); }
+ __forceinline double sign ( const double x ) { return x<0?-1.0:1.0; }
+ __forceinline double acos ( const double x ) { return ::acos (x); }
+ __forceinline double asin ( const double x ) { return ::asin (x); }
+ __forceinline double atan ( const double x ) { return ::atan (x); }
+ __forceinline double atan2( const double y, const double x ) { return ::atan2(y, x); }
+ __forceinline double cos ( const double x ) { return ::cos (x); }
+ __forceinline double cosh ( const double x ) { return ::cosh (x); }
+ __forceinline double exp ( const double x ) { return ::exp (x); }
+ __forceinline double fmod ( const double x, const double y ) { return ::fmod (x, y); }
+ __forceinline double log ( const double x ) { return ::log (x); }
+ __forceinline double log10( const double x ) { return ::log10(x); }
+ __forceinline double pow ( const double x, const double y ) { return ::pow (x, y); }
+ __forceinline double rcp ( const double x ) { return 1.0/x; }
+ __forceinline double rsqrt( const double x ) { return 1.0/::sqrt(x); }
+ __forceinline double sin ( const double x ) { return ::sin (x); }
+ __forceinline double sinh ( const double x ) { return ::sinh (x); }
+ __forceinline double sqr ( const double x ) { return x*x; }
+ __forceinline double sqrt ( const double x ) { return ::sqrt (x); }
+ __forceinline double tan ( const double x ) { return ::tan (x); }
+ __forceinline double tanh ( const double x ) { return ::tanh (x); }
+ __forceinline double floor( const double x ) { return ::floor (x); }
+ __forceinline double ceil ( const double x ) { return ::ceil (x); }
+
+#if defined(__SSE4_1__)
+ __forceinline float mini(float a, float b) {
+ const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
+ const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
+ const __m128i ci = _mm_min_epi32(ai,bi);
+ return _mm_cvtss_f32(_mm_castsi128_ps(ci));
+ }
+#endif
+
+#if defined(__SSE4_1__)
+ __forceinline float maxi(float a, float b) {
+ const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
+ const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
+ const __m128i ci = _mm_max_epi32(ai,bi);
+ return _mm_cvtss_f32(_mm_castsi128_ps(ci));
+ }
+#endif
+
+ template<typename T>
+ __forceinline T twice(const T& a) { return a+a; }
+
+ __forceinline int min(int a, int b) { return a<b ? a:b; }
+ __forceinline unsigned min(unsigned a, unsigned b) { return a<b ? a:b; }
+ __forceinline int64_t min(int64_t a, int64_t b) { return a<b ? a:b; }
+ __forceinline float min(float a, float b) { return a<b ? a:b; }
+ __forceinline double min(double a, double b) { return a<b ? a:b; }
+#if defined(__64BIT__)
+ __forceinline size_t min(size_t a, size_t b) { return a<b ? a:b; }
+#endif
+
+ template<typename T> __forceinline T min(const T& a, const T& b, const T& c) { return min(min(a,b),c); }
+ template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d) { return min(min(a,b),min(c,d)); }
+ template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d, const T& e) { return min(min(min(a,b),min(c,d)),e); }
+
+ template<typename T> __forceinline T mini(const T& a, const T& b, const T& c) { return mini(mini(a,b),c); }
+ template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d) { return mini(mini(a,b),mini(c,d)); }
+ template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d, const T& e) { return mini(mini(mini(a,b),mini(c,d)),e); }
+
+ __forceinline int max(int a, int b) { return a<b ? b:a; }
+ __forceinline unsigned max(unsigned a, unsigned b) { return a<b ? b:a; }
+ __forceinline int64_t max(int64_t a, int64_t b) { return a<b ? b:a; }
+ __forceinline float max(float a, float b) { return a<b ? b:a; }
+ __forceinline double max(double a, double b) { return a<b ? b:a; }
+#if defined(__64BIT__)
+ __forceinline size_t max(size_t a, size_t b) { return a<b ? b:a; }
+#endif
+
+ template<typename T> __forceinline T max(const T& a, const T& b, const T& c) { return max(max(a,b),c); }
+ template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d) { return max(max(a,b),max(c,d)); }
+ template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d, const T& e) { return max(max(max(a,b),max(c,d)),e); }
+
+ template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c) { return maxi(maxi(a,b),c); }
+ template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d) { return maxi(maxi(a,b),maxi(c,d)); }
+ template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d, const T& e) { return maxi(maxi(maxi(a,b),maxi(c,d)),e); }
+
+#if defined(__MACOSX__)
+ __forceinline ssize_t min(ssize_t a, ssize_t b) { return a<b ? a:b; }
+ __forceinline ssize_t max(ssize_t a, ssize_t b) { return a<b ? b:a; }
+#endif
+
+#if defined(__MACOSX__) && !defined(__INTEL_COMPILER)
+ __forceinline void sincosf(float x, float *sin, float *cos) {
+ __sincosf(x,sin,cos);
+ }
+#endif
+
+#if defined(__WIN32__) || defined(__FreeBSD__)
+ __forceinline void sincosf(float x, float *s, float *c) {
+ *s = sinf(x); *c = cosf(x);
+ }
+#endif
+
+ template<typename T> __forceinline T clamp(const T& x, const T& lower = T(zero), const T& upper = T(one)) { return max(min(x,upper),lower); }
+ template<typename T> __forceinline T clampz(const T& x, const T& upper) { return max(T(zero), min(x,upper)); }
+
+ template<typename T> __forceinline T deg2rad ( const T& x ) { return x * T(1.74532925199432957692e-2f); }
+ template<typename T> __forceinline T rad2deg ( const T& x ) { return x * T(5.72957795130823208768e1f); }
+ template<typename T> __forceinline T sin2cos ( const T& x ) { return sqrt(max(T(zero),T(one)-x*x)); }
+ template<typename T> __forceinline T cos2sin ( const T& x ) { return sin2cos(x); }
+
+#if defined(__AVX2__)
+ __forceinline float madd ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fmadd_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
+ __forceinline float msub ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fmsub_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
+ __forceinline float nmadd ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fnmadd_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
+ __forceinline float nmsub ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fnmsub_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); }
+#else
+ __forceinline float madd ( const float a, const float b, const float c) { return a*b+c; }
+ __forceinline float msub ( const float a, const float b, const float c) { return a*b-c; }
+ __forceinline float nmadd ( const float a, const float b, const float c) { return -a*b+c;}
+ __forceinline float nmsub ( const float a, const float b, const float c) { return -a*b-c; }
+#endif
+
+ /*! random functions */
+ template<typename T> T random() { return T(0); }
+#if defined(_WIN32)
+ template<> __forceinline int random() { return int(rand()) ^ (int(rand()) << 8) ^ (int(rand()) << 16); }
+ template<> __forceinline uint32_t random() { return uint32_t(rand()) ^ (uint32_t(rand()) << 8) ^ (uint32_t(rand()) << 16); }
+#else
+ template<> __forceinline int random() { return int(rand()); }
+ template<> __forceinline uint32_t random() { return uint32_t(rand()) ^ (uint32_t(rand()) << 16); }
+#endif
+ template<> __forceinline float random() { return rand()/float(RAND_MAX); }
+ template<> __forceinline double random() { return rand()/double(RAND_MAX); }
+
+#if _WIN32
+ __forceinline double drand48() {
+ return double(rand())/double(RAND_MAX);
+ }
+
+ __forceinline void srand48(long seed) {
+ return srand(seed);
+ }
+#endif
+
+ /*! selects */
+ __forceinline bool select(bool s, bool t , bool f) { return s ? t : f; }
+ __forceinline int select(bool s, int t, int f) { return s ? t : f; }
+ __forceinline float select(bool s, float t, float f) { return s ? t : f; }
+
+ __forceinline bool all(bool s) { return s; }
+
+ __forceinline float lerp(const float v0, const float v1, const float t) {
+ return madd(1.0f-t,v0,t*v1);
+ }
+
+ template<typename T>
+ __forceinline T lerp2(const float x0, const float x1, const float x2, const float x3, const T& u, const T& v) {
+ return madd((1.0f-u),madd((1.0f-v),T(x0),v*T(x2)),u*madd((1.0f-v),T(x1),v*T(x3)));
+ }
+
+ /*! exchange */
+ template<typename T> __forceinline void xchg ( T& a, T& b ) { const T tmp = a; a = b; b = tmp; }
+
+ /* load/store */
+ template<typename Ty> struct mem;
+
+ template<> struct mem<float> {
+ static __forceinline float load (bool mask, const void* ptr) { return mask ? *(float*)ptr : 0.0f; }
+ static __forceinline float loadu(bool mask, const void* ptr) { return mask ? *(float*)ptr : 0.0f; }
+
+ static __forceinline void store (bool mask, void* ptr, const float v) { if (mask) *(float*)ptr = v; }
+ static __forceinline void storeu(bool mask, void* ptr, const float v) { if (mask) *(float*)ptr = v; }
+ };
+
+ /*! bit reverse operation */
+ template<class T>
+ __forceinline T bitReverse(const T& vin)
+ {
+ T v = vin;
+ v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
+ v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
+ v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
+ v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
+ v = ( v >> 16 ) | ( v << 16);
+ return v;
+ }
+
+ /*! bit interleave operation */
+ template<class T>
+ __forceinline T bitInterleave(const T& xin, const T& yin, const T& zin)
+ {
+ T x = xin, y = yin, z = zin;
+ x = (x | (x << 16)) & 0x030000FF;
+ x = (x | (x << 8)) & 0x0300F00F;
+ x = (x | (x << 4)) & 0x030C30C3;
+ x = (x | (x << 2)) & 0x09249249;
+
+ y = (y | (y << 16)) & 0x030000FF;
+ y = (y | (y << 8)) & 0x0300F00F;
+ y = (y | (y << 4)) & 0x030C30C3;
+ y = (y | (y << 2)) & 0x09249249;
+
+ z = (z | (z << 16)) & 0x030000FF;
+ z = (z | (z << 8)) & 0x0300F00F;
+ z = (z | (z << 4)) & 0x030C30C3;
+ z = (z | (z << 2)) & 0x09249249;
+
+ return x | (y << 1) | (z << 2);
+ }
+
+#if defined(__AVX2__)
+
+ template<>
+ __forceinline unsigned int bitInterleave(const unsigned int &xi, const unsigned int& yi, const unsigned int& zi)
+ {
+ const unsigned int xx = pdep(xi,0x49249249 /* 0b01001001001001001001001001001001 */ );
+ const unsigned int yy = pdep(yi,0x92492492 /* 0b10010010010010010010010010010010 */);
+ const unsigned int zz = pdep(zi,0x24924924 /* 0b00100100100100100100100100100100 */);
+ return xx | yy | zz;
+ }
+
+#endif
+
+ /*! bit interleave operation for 64bit data types*/
+ template<class T>
+ __forceinline T bitInterleave64(const T& xin, const T& yin, const T& zin){
+ T x = xin & 0x1fffff;
+ T y = yin & 0x1fffff;
+ T z = zin & 0x1fffff;
+
+ x = (x | x << 32) & 0x1f00000000ffff;
+ x = (x | x << 16) & 0x1f0000ff0000ff;
+ x = (x | x << 8) & 0x100f00f00f00f00f;
+ x = (x | x << 4) & 0x10c30c30c30c30c3;
+ x = (x | x << 2) & 0x1249249249249249;
+
+ y = (y | y << 32) & 0x1f00000000ffff;
+ y = (y | y << 16) & 0x1f0000ff0000ff;
+ y = (y | y << 8) & 0x100f00f00f00f00f;
+ y = (y | y << 4) & 0x10c30c30c30c30c3;
+ y = (y | y << 2) & 0x1249249249249249;
+
+ z = (z | z << 32) & 0x1f00000000ffff;
+ z = (z | z << 16) & 0x1f0000ff0000ff;
+ z = (z | z << 8) & 0x100f00f00f00f00f;
+ z = (z | z << 4) & 0x10c30c30c30c30c3;
+ z = (z | z << 2) & 0x1249249249249249;
+
+ return x | (y << 1) | (z << 2);
+ }
+}
diff --git a/thirdparty/embree/common/math/obbox.h b/thirdparty/embree/common/math/obbox.h
new file mode 100644
index 0000000000..2fe8bbf071
--- /dev/null
+++ b/thirdparty/embree/common/math/obbox.h
@@ -0,0 +1,39 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bbox.h"
+#include "linearspace3.h"
+
+namespace embree
+{
+ /*! Oriented bounding box */
+ template<typename T>
+ struct OBBox
+ {
+ public:
+
+ __forceinline OBBox () {}
+
+ __forceinline OBBox (EmptyTy)
+ : space(one), bounds(empty) {}
+
+ __forceinline OBBox (const BBox<T>& bounds)
+ : space(one), bounds(bounds) {}
+
+ __forceinline OBBox (const LinearSpace3<T>& space, const BBox<T>& bounds)
+ : space(space), bounds(bounds) {}
+
+ friend embree_ostream operator<<(embree_ostream cout, const OBBox& p) {
+ return cout << "{ space = " << p.space << ", bounds = " << p.bounds << "}";
+ }
+
+ public:
+ LinearSpace3<T> space; //!< orthonormal transformation
+ BBox<T> bounds; //!< bounds in transformed space
+ };
+
+ typedef OBBox<Vec3f> OBBox3f;
+ typedef OBBox<Vec3fa> OBBox3fa;
+}
diff --git a/thirdparty/embree/common/math/quaternion.h b/thirdparty/embree/common/math/quaternion.h
new file mode 100644
index 0000000000..080800efcd
--- /dev/null
+++ b/thirdparty/embree/common/math/quaternion.h
@@ -0,0 +1,254 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "vec3.h"
+#include "vec4.h"
+
+#include "transcendental.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////
+ // Quaternion Struct
+ ////////////////////////////////////////////////////////////////
+
+ template<typename T>
+ struct QuaternionT
+ {
+ typedef Vec3<T> Vector;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline QuaternionT () { }
+ __forceinline QuaternionT ( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; }
+ __forceinline QuaternionT& operator=( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; return *this; }
+
+ __forceinline QuaternionT( const T& r ) : r(r), i(zero), j(zero), k(zero) {}
+ __forceinline explicit QuaternionT( const Vec3<T>& v ) : r(zero), i(v.x), j(v.y), k(v.z) {}
+ __forceinline explicit QuaternionT( const Vec4<T>& v ) : r(v.x), i(v.y), j(v.z), k(v.w) {}
+ __forceinline QuaternionT( const T& r, const T& i, const T& j, const T& k ) : r(r), i(i), j(j), k(k) {}
+ __forceinline QuaternionT( const T& r, const Vec3<T>& v ) : r(r), i(v.x), j(v.y), k(v.z) {}
+
+ __inline QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz );
+ __inline QuaternionT( const T& yaw, const T& pitch, const T& roll );
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline QuaternionT( ZeroTy ) : r(zero), i(zero), j(zero), k(zero) {}
+ __forceinline QuaternionT( OneTy ) : r( one), i(zero), j(zero), k(zero) {}
+
+ /*! return quaternion for rotation around arbitrary axis */
+ static __forceinline QuaternionT rotate(const Vec3<T>& u, const T& r) {
+ return QuaternionT<T>(cos(T(0.5)*r),sin(T(0.5)*r)*normalize(u));
+ }
+
+ /*! returns the rotation axis of the quaternion as a vector */
+ __forceinline Vec3<T> v( ) const { return Vec3<T>(i, j, k); }
+
+ public:
+ T r, i, j, k;
+ };
+
+ template<typename T> __forceinline QuaternionT<T> operator *( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a * b.r, a * b.i, a * b.j, a * b.k); }
+ template<typename T> __forceinline QuaternionT<T> operator *( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r * b, a.i * b, a.j * b, a.k * b); }
+
+ ////////////////////////////////////////////////////////////////
+ // Unary Operators
+ ////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a ) { return QuaternionT<T>(+a.r, +a.i, +a.j, +a.k); }
+ template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a ) { return QuaternionT<T>(-a.r, -a.i, -a.j, -a.k); }
+ template<typename T> __forceinline QuaternionT<T> conj ( const QuaternionT<T>& a ) { return QuaternionT<T>(a.r, -a.i, -a.j, -a.k); }
+ template<typename T> __forceinline T abs ( const QuaternionT<T>& a ) { return sqrt(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
+ template<typename T> __forceinline QuaternionT<T> rcp ( const QuaternionT<T>& a ) { return conj(a)*rcp(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
+ template<typename T> __forceinline QuaternionT<T> normalize ( const QuaternionT<T>& a ) { return a*rsqrt(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
+
+ // evaluates a*q-r
+ template<typename T> __forceinline QuaternionT<T>
+ msub(const T& a, const QuaternionT<T>& q, const QuaternionT<T>& p)
+ {
+ return QuaternionT<T>(msub(a, q.r, p.r),
+ msub(a, q.i, p.i),
+ msub(a, q.j, p.j),
+ msub(a, q.k, p.k));
+ }
+ // evaluates a*q-r
+ template<typename T> __forceinline QuaternionT<T>
+ madd (const T& a, const QuaternionT<T>& q, const QuaternionT<T>& p)
+ {
+ return QuaternionT<T>(madd(a, q.r, p.r),
+ madd(a, q.i, p.i),
+ madd(a, q.j, p.j),
+ madd(a, q.k, p.k));
+ }
+
+ ////////////////////////////////////////////////////////////////
+ // Binary Operators
+ ////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline QuaternionT<T> operator +( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a + b.r, b.i, b.j, b.k); }
+ template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r + b, a.i, a.j, a.k); }
+ template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return QuaternionT<T>(a.r + b.r, a.i + b.i, a.j + b.j, a.k + b.k); }
+ template<typename T> __forceinline QuaternionT<T> operator -( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a - b.r, -b.i, -b.j, -b.k); }
+ template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r - b, a.i, a.j, a.k); }
+ template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return QuaternionT<T>(a.r - b.r, a.i - b.i, a.j - b.j, a.k - b.k); }
+
+ template<typename T> __forceinline Vec3<T> operator *( const QuaternionT<T>& a, const Vec3<T> & b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
+ template<typename T> __forceinline QuaternionT<T> operator *( const QuaternionT<T>& a, const QuaternionT<T>& b ) {
+ return QuaternionT<T>(a.r*b.r - a.i*b.i - a.j*b.j - a.k*b.k,
+ a.r*b.i + a.i*b.r + a.j*b.k - a.k*b.j,
+ a.r*b.j - a.i*b.k + a.j*b.r + a.k*b.i,
+ a.r*b.k + a.i*b.j - a.j*b.i + a.k*b.r);
+ }
+ template<typename T> __forceinline QuaternionT<T> operator /( const T & a, const QuaternionT<T>& b ) { return a*rcp(b); }
+ template<typename T> __forceinline QuaternionT<T> operator /( const QuaternionT<T>& a, const T & b ) { return a*rcp(b); }
+ template<typename T> __forceinline QuaternionT<T> operator /( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a*rcp(b); }
+
+ template<typename T> __forceinline QuaternionT<T>& operator +=( QuaternionT<T>& a, const T & b ) { return a = a+b; }
+ template<typename T> __forceinline QuaternionT<T>& operator +=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a+b; }
+ template<typename T> __forceinline QuaternionT<T>& operator -=( QuaternionT<T>& a, const T & b ) { return a = a-b; }
+ template<typename T> __forceinline QuaternionT<T>& operator -=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a-b; }
+ template<typename T> __forceinline QuaternionT<T>& operator *=( QuaternionT<T>& a, const T & b ) { return a = a*b; }
+ template<typename T> __forceinline QuaternionT<T>& operator *=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a*b; }
+ template<typename T> __forceinline QuaternionT<T>& operator /=( QuaternionT<T>& a, const T & b ) { return a = a*rcp(b); }
+ template<typename T> __forceinline QuaternionT<T>& operator /=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a*rcp(b); }
+
+ template<typename T, typename M> __forceinline QuaternionT<T>
+ select(const M& m, const QuaternionT<T>& q, const QuaternionT<T>& p)
+ {
+ return QuaternionT<T>(select(m, q.r, p.r),
+ select(m, q.i, p.i),
+ select(m, q.j, p.j),
+ select(m, q.k, p.k));
+ }
+
+
+ template<typename T> __forceinline Vec3<T> xfmPoint ( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
+ template<typename T> __forceinline Vec3<T> xfmVector( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
+ template<typename T> __forceinline Vec3<T> xfmNormal( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
+
+ template<typename T> __forceinline T dot(const QuaternionT<T>& a, const QuaternionT<T>& b) { return a.r*b.r + a.i*b.i + a.j*b.j + a.k*b.k; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline bool operator ==( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a.r == b.r && a.i == b.i && a.j == b.j && a.k == b.k; }
+ template<typename T> __forceinline bool operator !=( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a.r != b.r || a.i != b.i || a.j != b.j || a.k != b.k; }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Orientation Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> QuaternionT<T>::QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz )
+ {
+ if ( vx.x + vy.y + vz.z >= T(zero) )
+ {
+ const T t = T(one) + (vx.x + vy.y + vz.z);
+ const T s = rsqrt(t)*T(0.5f);
+ r = t*s;
+ i = (vy.z - vz.y)*s;
+ j = (vz.x - vx.z)*s;
+ k = (vx.y - vy.x)*s;
+ }
+ else if ( vx.x >= max(vy.y, vz.z) )
+ {
+ const T t = (T(one) + vx.x) - (vy.y + vz.z);
+ const T s = rsqrt(t)*T(0.5f);
+ r = (vy.z - vz.y)*s;
+ i = t*s;
+ j = (vx.y + vy.x)*s;
+ k = (vz.x + vx.z)*s;
+ }
+ else if ( vy.y >= vz.z ) // if ( vy.y >= max(vz.z, vx.x) )
+ {
+ const T t = (T(one) + vy.y) - (vz.z + vx.x);
+ const T s = rsqrt(t)*T(0.5f);
+ r = (vz.x - vx.z)*s;
+ i = (vx.y + vy.x)*s;
+ j = t*s;
+ k = (vy.z + vz.y)*s;
+ }
+ else //if ( vz.z >= max(vy.y, vx.x) )
+ {
+ const T t = (T(one) + vz.z) - (vx.x + vy.y);
+ const T s = rsqrt(t)*T(0.5f);
+ r = (vx.y - vy.x)*s;
+ i = (vz.x + vx.z)*s;
+ j = (vy.z + vz.y)*s;
+ k = t*s;
+ }
+ }
+
+ template<typename T> QuaternionT<T>::QuaternionT( const T& yaw, const T& pitch, const T& roll )
+ {
+ const T cya = cos(yaw *T(0.5f));
+ const T cpi = cos(pitch*T(0.5f));
+ const T cro = cos(roll *T(0.5f));
+ const T sya = sin(yaw *T(0.5f));
+ const T spi = sin(pitch*T(0.5f));
+ const T sro = sin(roll *T(0.5f));
+ r = cro*cya*cpi + sro*sya*spi;
+ i = cro*cya*spi + sro*sya*cpi;
+ j = cro*sya*cpi - sro*cya*spi;
+ k = sro*cya*cpi - cro*sya*spi;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ //////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> static embree_ostream operator<<(embree_ostream cout, const QuaternionT<T>& q) {
+ return cout << "{ r = " << q.r << ", i = " << q.i << ", j = " << q.j << ", k = " << q.k << " }";
+ }
+
+ /*! default template instantiations */
+ typedef QuaternionT<float> Quaternion3f;
+ typedef QuaternionT<double> Quaternion3d;
+
+ template<int N> using Quaternion3vf = QuaternionT<vfloat<N>>;
+ typedef QuaternionT<vfloat<4>> Quaternion3vf4;
+ typedef QuaternionT<vfloat<8>> Quaternion3vf8;
+ typedef QuaternionT<vfloat<16>> Quaternion3vf16;
+
+ //////////////////////////////////////////////////////////////////////////////
+ /// Interpolation
+ //////////////////////////////////////////////////////////////////////////////
+ template<typename T>
+ __forceinline QuaternionT<T>lerp(const QuaternionT<T>& q0,
+ const QuaternionT<T>& q1,
+ const T& factor)
+ {
+ QuaternionT<T> q;
+ q.r = lerp(q0.r, q1.r, factor);
+ q.i = lerp(q0.i, q1.i, factor);
+ q.j = lerp(q0.j, q1.j, factor);
+ q.k = lerp(q0.k, q1.k, factor);
+ return q;
+ }
+
+ template<typename T>
+ __forceinline QuaternionT<T> slerp(const QuaternionT<T>& q0,
+ const QuaternionT<T>& q1_,
+ const T& t)
+ {
+ T cosTheta = dot(q0, q1_);
+ QuaternionT<T> q1 = select(cosTheta < 0.f, -q1_, q1_);
+ cosTheta = select(cosTheta < 0.f, -cosTheta, cosTheta);
+ if (unlikely(all(cosTheta > 0.9995f))) {
+ return normalize(lerp(q0, q1, t));
+ }
+ const T phi = t * fastapprox::acos(cosTheta);
+ T sinPhi, cosPhi;
+ fastapprox::sincos(phi, sinPhi, cosPhi);
+ QuaternionT<T> qperp = sinPhi * normalize(msub(cosTheta, q0, q1));
+ return msub(cosPhi, q0, qperp);
+ }
+}
diff --git a/thirdparty/embree/common/math/range.h b/thirdparty/embree/common/math/range.h
new file mode 100644
index 0000000000..909fadb995
--- /dev/null
+++ b/thirdparty/embree/common/math/range.h
@@ -0,0 +1,137 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+#include "../math/math.h"
+
+namespace embree
+{
+ template<typename Ty>
+ struct range
+ {
+ __forceinline range() {}
+
+ __forceinline range(const Ty& begin)
+ : _begin(begin), _end(begin+1) {}
+
+ __forceinline range(const Ty& begin, const Ty& end)
+ : _begin(begin), _end(end) {}
+
+ __forceinline range(const range& other)
+ : _begin(other._begin), _end(other._end) {}
+
+ template<typename T1>
+ __forceinline range(const range<T1>& other)
+ : _begin(Ty(other._begin)), _end(Ty(other._end)) {}
+
+ template<typename T1>
+ __forceinline range& operator =(const range<T1>& other) {
+ _begin = other._begin;
+ _end = other._end;
+ return *this;
+ }
+
+ __forceinline Ty begin() const {
+ return _begin;
+ }
+
+ __forceinline Ty end() const {
+ return _end;
+ }
+
+ __forceinline range intersect(const range& r) const {
+ return range (max(_begin,r._begin),min(_end,r._end));
+ }
+
+ __forceinline Ty size() const {
+ return _end - _begin;
+ }
+
+ __forceinline bool empty() const {
+ return _end <= _begin;
+ }
+
+ __forceinline Ty center() const {
+ return (_begin + _end)/2;
+ }
+
+ __forceinline std::pair<range,range> split() const
+ {
+ const Ty _center = center();
+ return std::make_pair(range(_begin,_center),range(_center,_end));
+ }
+
+ __forceinline void split(range& left_o, range& right_o) const
+ {
+ const Ty _center = center();
+ left_o = range(_begin,_center);
+ right_o = range(_center,_end);
+ }
+
+ __forceinline friend bool operator< (const range& r0, const range& r1) {
+ return r0.size() < r1.size();
+ }
+
+ friend embree_ostream operator<<(embree_ostream cout, const range& r) {
+ return cout << "range [" << r.begin() << ", " << r.end() << "]";
+ }
+
+ Ty _begin, _end;
+ };
+
+ template<typename Ty>
+ range<Ty> make_range(const Ty& begin, const Ty& end) {
+ return range<Ty>(begin,end);
+ }
+
+ template<typename Ty>
+ struct extended_range : public range<Ty>
+ {
+ __forceinline extended_range () {}
+
+ __forceinline extended_range (const Ty& begin)
+ : range<Ty>(begin), _ext_end(begin+1) {}
+
+ __forceinline extended_range (const Ty& begin, const Ty& end)
+ : range<Ty>(begin,end), _ext_end(end) {}
+
+ __forceinline extended_range (const Ty& begin, const Ty& end, const Ty& ext_end)
+ : range<Ty>(begin,end), _ext_end(ext_end) {}
+
+ __forceinline Ty ext_end() const {
+ return _ext_end;
+ }
+
+ __forceinline Ty ext_size() const {
+ return _ext_end - range<Ty>::_begin;
+ }
+
+ __forceinline Ty ext_range_size() const {
+ return _ext_end - range<Ty>::_end;
+ }
+
+ __forceinline bool has_ext_range() const {
+ assert(_ext_end >= range<Ty>::_end);
+ return (_ext_end - range<Ty>::_end) > 0;
+ }
+
+ __forceinline void set_ext_range(const size_t ext_end){
+ assert(ext_end >= range<Ty>::_end);
+ _ext_end = ext_end;
+ }
+
+ __forceinline void move_right(const size_t plus){
+ range<Ty>::_begin += plus;
+ range<Ty>::_end += plus;
+ _ext_end += plus;
+ }
+
+ friend embree_ostream operator<<(embree_ostream cout, const extended_range& r) {
+ return cout << "extended_range [" << r.begin() << ", " << r.end() << " (" << r.ext_end() << ")]";
+ }
+
+ Ty _ext_end;
+ };
+}
diff --git a/thirdparty/embree/common/math/transcendental.h b/thirdparty/embree/common/math/transcendental.h
new file mode 100644
index 0000000000..fd16c26e81
--- /dev/null
+++ b/thirdparty/embree/common/math/transcendental.h
@@ -0,0 +1,525 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+// Transcendental functions from "ispc": https://github.com/ispc/ispc/
+// Most of the transcendental implementations in ispc code come from
+// Solomon Boulos's "syrah": https://github.com/boulos/syrah/
+
+#include "../simd/simd.h"
+
+namespace embree
+{
+
+namespace fastapprox
+{
+
+template <typename T>
+__forceinline T sin(const T &v)
+{
+ static const float piOverTwoVec = 1.57079637050628662109375;
+ static const float twoOverPiVec = 0.636619746685028076171875;
+ auto scaled = v * twoOverPiVec;
+ auto kReal = floor(scaled);
+ auto k = toInt(kReal);
+
+ // Reduced range version of x
+ auto x = v - kReal * piOverTwoVec;
+ auto kMod4 = k & 3;
+ auto sinUseCos = (kMod4 == 1 | kMod4 == 3);
+ auto flipSign = (kMod4 > 1);
+
+ // These coefficients are from sollya with fpminimax(sin(x)/x, [|0, 2,
+ // 4, 6, 8, 10|], [|single...|], [0;Pi/2]);
+ static const float sinC2 = -0.16666667163372039794921875;
+ static const float sinC4 = +8.333347737789154052734375e-3;
+ static const float sinC6 = -1.9842604524455964565277099609375e-4;
+ static const float sinC8 = +2.760012648650445044040679931640625e-6;
+ static const float sinC10 = -2.50293279435709337121807038784027099609375e-8;
+
+ static const float cosC2 = -0.5;
+ static const float cosC4 = +4.166664183139801025390625e-2;
+ static const float cosC6 = -1.388833043165504932403564453125e-3;
+ static const float cosC8 = +2.47562347794882953166961669921875e-5;
+ static const float cosC10 = -2.59630184018533327616751194000244140625e-7;
+
+ auto outside = select(sinUseCos, 1., x);
+ auto c2 = select(sinUseCos, T(cosC2), T(sinC2));
+ auto c4 = select(sinUseCos, T(cosC4), T(sinC4));
+ auto c6 = select(sinUseCos, T(cosC6), T(sinC6));
+ auto c8 = select(sinUseCos, T(cosC8), T(sinC8));
+ auto c10 = select(sinUseCos, T(cosC10), T(sinC10));
+
+ auto x2 = x * x;
+ auto formula = x2 * c10 + c8;
+ formula = x2 * formula + c6;
+ formula = x2 * formula + c4;
+ formula = x2 * formula + c2;
+ formula = x2 * formula + 1.;
+ formula *= outside;
+
+ formula = select(flipSign, -formula, formula);
+ return formula;
+}
+
+template <typename T>
+__forceinline T cos(const T &v)
+{
+ static const float piOverTwoVec = 1.57079637050628662109375;
+ static const float twoOverPiVec = 0.636619746685028076171875;
+ auto scaled = v * twoOverPiVec;
+ auto kReal = floor(scaled);
+ auto k = toInt(kReal);
+
+ // Reduced range version of x
+ auto x = v - kReal * piOverTwoVec;
+
+ auto kMod4 = k & 3;
+ auto cosUseCos = (kMod4 == 0 | kMod4 == 2);
+ auto flipSign = (kMod4 == 1 | kMod4 == 2);
+
+ const float sinC2 = -0.16666667163372039794921875;
+ const float sinC4 = +8.333347737789154052734375e-3;
+ const float sinC6 = -1.9842604524455964565277099609375e-4;
+ const float sinC8 = +2.760012648650445044040679931640625e-6;
+ const float sinC10 = -2.50293279435709337121807038784027099609375e-8;
+
+ const float cosC2 = -0.5;
+ const float cosC4 = +4.166664183139801025390625e-2;
+ const float cosC6 = -1.388833043165504932403564453125e-3;
+ const float cosC8 = +2.47562347794882953166961669921875e-5;
+ const float cosC10 = -2.59630184018533327616751194000244140625e-7;
+
+ auto outside = select(cosUseCos, 1., x);
+ auto c2 = select(cosUseCos, T(cosC2), T(sinC2));
+ auto c4 = select(cosUseCos, T(cosC4), T(sinC4));
+ auto c6 = select(cosUseCos, T(cosC6), T(sinC6));
+ auto c8 = select(cosUseCos, T(cosC8), T(sinC8));
+ auto c10 = select(cosUseCos, T(cosC10), T(sinC10));
+
+ auto x2 = x * x;
+ auto formula = x2 * c10 + c8;
+ formula = x2 * formula + c6;
+ formula = x2 * formula + c4;
+ formula = x2 * formula + c2;
+ formula = x2 * formula + 1.;
+ formula *= outside;
+
+ formula = select(flipSign, -formula, formula);
+ return formula;
+}
+
+template <typename T>
+__forceinline void sincos(const T &v, T &sinResult, T &cosResult)
+{
+ const float piOverTwoVec = 1.57079637050628662109375;
+ const float twoOverPiVec = 0.636619746685028076171875;
+ auto scaled = v * twoOverPiVec;
+ auto kReal = floor(scaled);
+ auto k = toInt(kReal);
+
+ // Reduced range version of x
+ auto x = v - kReal * piOverTwoVec;
+ auto kMod4 = k & 3;
+ auto cosUseCos = ((kMod4 == 0) | (kMod4 == 2));
+ auto sinUseCos = ((kMod4 == 1) | (kMod4 == 3));
+ auto sinFlipSign = (kMod4 > 1);
+ auto cosFlipSign = ((kMod4 == 1) | (kMod4 == 2));
+
+ const float oneVec = +1.;
+ const float sinC2 = -0.16666667163372039794921875;
+ const float sinC4 = +8.333347737789154052734375e-3;
+ const float sinC6 = -1.9842604524455964565277099609375e-4;
+ const float sinC8 = +2.760012648650445044040679931640625e-6;
+ const float sinC10 = -2.50293279435709337121807038784027099609375e-8;
+
+ const float cosC2 = -0.5;
+ const float cosC4 = +4.166664183139801025390625e-2;
+ const float cosC6 = -1.388833043165504932403564453125e-3;
+ const float cosC8 = +2.47562347794882953166961669921875e-5;
+ const float cosC10 = -2.59630184018533327616751194000244140625e-7;
+
+ auto x2 = x * x;
+
+ auto sinFormula = x2 * sinC10 + sinC8;
+ auto cosFormula = x2 * cosC10 + cosC8;
+ sinFormula = x2 * sinFormula + sinC6;
+ cosFormula = x2 * cosFormula + cosC6;
+
+ sinFormula = x2 * sinFormula + sinC4;
+ cosFormula = x2 * cosFormula + cosC4;
+
+ sinFormula = x2 * sinFormula + sinC2;
+ cosFormula = x2 * cosFormula + cosC2;
+
+ sinFormula = x2 * sinFormula + oneVec;
+ cosFormula = x2 * cosFormula + oneVec;
+
+ sinFormula *= x;
+
+ sinResult = select(sinUseCos, cosFormula, sinFormula);
+ cosResult = select(cosUseCos, cosFormula, sinFormula);
+
+ sinResult = select(sinFlipSign, -sinResult, sinResult);
+ cosResult = select(cosFlipSign, -cosResult, cosResult);
+}
+
+template <typename T>
+__forceinline T tan(const T &v)
+{
+ const float piOverFourVec = 0.785398185253143310546875;
+ const float fourOverPiVec = 1.27323949337005615234375;
+
+ auto xLt0 = v < 0.;
+ auto y = select(xLt0, -v, v);
+ auto scaled = y * fourOverPiVec;
+
+ auto kReal = floor(scaled);
+ auto k = toInt(kReal);
+
+ auto x = y - kReal * piOverFourVec;
+
+ // If k & 1, x -= Pi/4
+ auto needOffset = (k & 1) != 0;
+ x = select(needOffset, x - piOverFourVec, x);
+
+ // If k & 3 == (0 or 3) let z = tan_In...(y) otherwise z = -cot_In0To...
+ auto kMod4 = k & 3;
+ auto useCotan = (kMod4 == 1) | (kMod4 == 2);
+
+ const float oneVec = 1.0;
+
+ const float tanC2 = +0.33333075046539306640625;
+ const float tanC4 = +0.13339905440807342529296875;
+ const float tanC6 = +5.3348250687122344970703125e-2;
+ const float tanC8 = +2.46033705770969390869140625e-2;
+ const float tanC10 = +2.892402000725269317626953125e-3;
+ const float tanC12 = +9.500005282461643218994140625e-3;
+
+ const float cotC2 = -0.3333333432674407958984375;
+ const float cotC4 = -2.222204394638538360595703125e-2;
+ const float cotC6 = -2.11752182804048061370849609375e-3;
+ const float cotC8 = -2.0846328698098659515380859375e-4;
+ const float cotC10 = -2.548247357481159269809722900390625e-5;
+ const float cotC12 = -3.5257363606433500535786151885986328125e-7;
+
+ auto x2 = x * x;
+ T z;
+ if (any(useCotan))
+ {
+ auto cotVal = x2 * cotC12 + cotC10;
+ cotVal = x2 * cotVal + cotC8;
+ cotVal = x2 * cotVal + cotC6;
+ cotVal = x2 * cotVal + cotC4;
+ cotVal = x2 * cotVal + cotC2;
+ cotVal = x2 * cotVal + oneVec;
+ // The equation is for x * cot(x) but we need -x * cot(x) for the tan part.
+ cotVal /= -x;
+ z = cotVal;
+ }
+ auto useTan = !useCotan;
+ if (any(useTan))
+ {
+ auto tanVal = x2 * tanC12 + tanC10;
+ tanVal = x2 * tanVal + tanC8;
+ tanVal = x2 * tanVal + tanC6;
+ tanVal = x2 * tanVal + tanC4;
+ tanVal = x2 * tanVal + tanC2;
+ tanVal = x2 * tanVal + oneVec;
+ // Equation was for tan(x)/x
+ tanVal *= x;
+ z = select(useTan, tanVal, z);
+ }
+ return select(xLt0, -z, z);
+}
+
+template <typename T>
+__forceinline T asin(const T &x0)
+{
+ auto isneg = (x0 < 0.f);
+ auto x = abs(x0);
+ auto isnan = (x > 1.f);
+
+ // sollya
+ // fpminimax(((asin(x)-pi/2)/-sqrt(1-x)), [|0,1,2,3,4,5|],[|single...|],
+ // [1e-20;.9999999999999999]);
+ // avg error: 1.1105439e-06, max error 1.3187528e-06
+ auto v = 1.57079517841339111328125f +
+ x * (-0.21450997889041900634765625f +
+ x * (8.78556668758392333984375e-2f +
+ x * (-4.489909112453460693359375e-2f +
+ x * (1.928029954433441162109375e-2f +
+ x * (-4.3095736764371395111083984375e-3f)))));
+
+ v *= -sqrt(1.f - x);
+ v = v + 1.57079637050628662109375f;
+
+ v = select(v < 0.f, T(0.f), v);
+ v = select(isneg, -v, v);
+ v = select(isnan, T(cast_i2f(0x7fc00000)), v);
+
+ return v;
+}
+
+template <typename T>
+__forceinline T acos(const T &v)
+{
+ return 1.57079637050628662109375f - asin(v);
+}
+
+template <typename T>
+__forceinline T atan(const T &v)
+{
+ const float piOverTwoVec = 1.57079637050628662109375;
+ // atan(-x) = -atan(x) (so flip from negative to positive first)
+ // If x > 1 -> atan(x) = Pi/2 - atan(1/x)
+ auto xNeg = v < 0.f;
+ auto xFlipped = select(xNeg, -v, v);
+
+ auto xGt1 = xFlipped > 1.;
+ auto x = select(xGt1, rcpSafe(xFlipped), xFlipped);
+
+ // These coefficients approximate atan(x)/x
+ const float atanC0 = +0.99999988079071044921875;
+ const float atanC2 = -0.3333191573619842529296875;
+ const float atanC4 = +0.199689209461212158203125;
+ const float atanC6 = -0.14015688002109527587890625;
+ const float atanC8 = +9.905083477497100830078125e-2;
+ const float atanC10 = -5.93664981424808502197265625e-2;
+ const float atanC12 = +2.417283318936824798583984375e-2;
+ const float atanC14 = -4.6721356920897960662841796875e-3;
+
+ auto x2 = x * x;
+ auto result = x2 * atanC14 + atanC12;
+ result = x2 * result + atanC10;
+ result = x2 * result + atanC8;
+ result = x2 * result + atanC6;
+ result = x2 * result + atanC4;
+ result = x2 * result + atanC2;
+ result = x2 * result + atanC0;
+ result *= x;
+
+ result = select(xGt1, piOverTwoVec - result, result);
+ result = select(xNeg, -result, result);
+ return result;
+}
+
+template <typename T>
+__forceinline T atan2(const T &y, const T &x)
+{
+ const float piVec = 3.1415926536;
+ // atan2(y, x) =
+ //
+ // atan2(y > 0, x = +-0) -> Pi/2
+ // atan2(y < 0, x = +-0) -> -Pi/2
+ // atan2(y = +-0, x < +0) -> +-Pi
+ // atan2(y = +-0, x >= +0) -> +-0
+ //
+ // atan2(y >= 0, x < 0) -> Pi + atan(y/x)
+ // atan2(y < 0, x < 0) -> -Pi + atan(y/x)
+ // atan2(y, x > 0) -> atan(y/x)
+ //
+ // and then a bunch of code for dealing with infinities.
+ auto yOverX = y * rcpSafe(x);
+ auto atanArg = atan(yOverX);
+ auto xLt0 = x < 0.f;
+ auto yLt0 = y < 0.f;
+ auto offset = select(xLt0,
+ select(yLt0, T(-piVec), T(piVec)), 0.f);
+ return offset + atanArg;
+}
+
+template <typename T>
+__forceinline T exp(const T &v)
+{
+ const float ln2Part1 = 0.6931457519;
+ const float ln2Part2 = 1.4286067653e-6;
+ const float oneOverLn2 = 1.44269502162933349609375;
+
+ auto scaled = v * oneOverLn2;
+ auto kReal = floor(scaled);
+ auto k = toInt(kReal);
+
+ // Reduced range version of x
+ auto x = v - kReal * ln2Part1;
+ x -= kReal * ln2Part2;
+
+ // These coefficients are for e^x in [0, ln(2)]
+ const float one = 1.;
+ const float c2 = 0.4999999105930328369140625;
+ const float c3 = 0.166668415069580078125;
+ const float c4 = 4.16539050638675689697265625e-2;
+ const float c5 = 8.378830738365650177001953125e-3;
+ const float c6 = 1.304379315115511417388916015625e-3;
+ const float c7 = 2.7555381529964506626129150390625e-4;
+
+ auto result = x * c7 + c6;
+ result = x * result + c5;
+ result = x * result + c4;
+ result = x * result + c3;
+ result = x * result + c2;
+ result = x * result + one;
+ result = x * result + one;
+
+ // Compute 2^k (should differ for float and double, but I'll avoid
+ // it for now and just do floats)
+ const int fpbias = 127;
+ auto biasedN = k + fpbias;
+ auto overflow = kReal > fpbias;
+ // Minimum exponent is -126, so if k is <= -127 (k + 127 <= 0)
+ // we've got underflow. -127 * ln(2) -> -88.02. So the most
+ // negative float input that doesn't result in zero is like -88.
+ auto underflow = kReal <= -fpbias;
+ const int infBits = 0x7f800000;
+ biasedN <<= 23;
+ // Reinterpret this thing as float
+ auto twoToTheN = asFloat(biasedN);
+ // Handle both doubles and floats (hopefully eliding the copy for float)
+ auto elemtype2n = twoToTheN;
+ result *= elemtype2n;
+ result = select(overflow, cast_i2f(infBits), result);
+ result = select(underflow, 0., result);
+ return result;
+}
+
+// Range reduction for logarithms takes log(x) -> log(2^n * y) -> n
+// * log(2) + log(y) where y is the reduced range (usually in [1/2, 1)).
+template <typename T, typename R>
+__forceinline void __rangeReduceLog(const T &input,
+ T &reduced,
+ R &exponent)
+{
+ auto intVersion = asInt(input);
+ // single precision = SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
+ // exponent mask = 0111 1111 1000 0000 0000 0000 0000 0000
+ // 0x7 0xF 0x8 0x0 0x0 0x0 0x0 0x0
+ // non-exponent = 1000 0000 0111 1111 1111 1111 1111 1111
+ // = 0x8 0x0 0x7 0xF 0xF 0xF 0xF 0xF
+
+ //const int exponentMask(0x7F800000)
+ static const int nonexponentMask = 0x807FFFFF;
+
+ // We want the reduced version to have an exponent of -1 which is
+ // -1 + 127 after biasing or 126
+ static const int exponentNeg1 = (126l << 23);
+ // NOTE(boulos): We don't need to mask anything out since we know
+ // the sign bit has to be 0. If it's 1, we need to return infinity/nan
+ // anyway (log(x), x = +-0 -> infinity, x < 0 -> NaN).
+ auto biasedExponent = intVersion >> 23; // This number is [0, 255] but it means [-127, 128]
+
+ auto offsetExponent = biasedExponent + 1; // Treat the number as if it were 2^{e+1} * (1.m)/2
+ exponent = offsetExponent - 127; // get the real value
+
+ // Blend the offset_exponent with the original input (do this in
+ // int for now, until I decide if float can have & and &not)
+ auto blended = (intVersion & nonexponentMask) | (exponentNeg1);
+ reduced = asFloat(blended);
+}
+
+template <typename T> struct ExponentType { };
+template <int N> struct ExponentType<vfloat_impl<N>> { typedef vint<N> Ty; };
+template <> struct ExponentType<float> { typedef int Ty; };
+
+template <typename T>
+__forceinline T log(const T &v)
+{
+ T reduced;
+ typename ExponentType<T>::Ty exponent;
+
+ const int nanBits = 0x7fc00000;
+ const int negInfBits = 0xFF800000;
+ const float nan = cast_i2f(nanBits);
+ const float negInf = cast_i2f(negInfBits);
+ auto useNan = v < 0.;
+ auto useInf = v == 0.;
+ auto exceptional = useNan | useInf;
+ const float one = 1.0;
+
+ auto patched = select(exceptional, one, v);
+ __rangeReduceLog(patched, reduced, exponent);
+
+ const float ln2 = 0.693147182464599609375;
+
+ auto x1 = one - reduced;
+ const float c1 = +0.50000095367431640625;
+ const float c2 = +0.33326041698455810546875;
+ const float c3 = +0.2519190013408660888671875;
+ const float c4 = +0.17541764676570892333984375;
+ const float c5 = +0.3424419462680816650390625;
+ const float c6 = -0.599632322788238525390625;
+ const float c7 = +1.98442304134368896484375;
+ const float c8 = -2.4899270534515380859375;
+ const float c9 = +1.7491014003753662109375;
+
+ auto result = x1 * c9 + c8;
+ result = x1 * result + c7;
+ result = x1 * result + c6;
+ result = x1 * result + c5;
+ result = x1 * result + c4;
+ result = x1 * result + c3;
+ result = x1 * result + c2;
+ result = x1 * result + c1;
+ result = x1 * result + one;
+
+ // Equation was for -(ln(red)/(1-red))
+ result *= -x1;
+ result += toFloat(exponent) * ln2;
+
+ return select(exceptional,
+ select(useNan, T(nan), T(negInf)),
+ result);
+}
+
+template <typename T>
+__forceinline T pow(const T &x, const T &y)
+{
+ auto x1 = abs(x);
+ auto z = exp(y * log(x1));
+
+ // Handle special cases
+ const float twoOver23 = 8388608.0f;
+ auto yInt = y == round(y);
+ auto yOddInt = select(yInt, asInt(abs(y) + twoOver23) << 31, 0); // set sign bit
+
+ // x == 0
+ z = select(x == 0.0f,
+ select(y < 0.0f, T(inf) | signmsk(x),
+ select(y == 0.0f, T(1.0f), asFloat(yOddInt) & x)), z);
+
+ // x < 0
+ auto xNegative = x < 0.0f;
+ if (any(xNegative))
+ {
+ auto z1 = z | asFloat(yOddInt);
+ z1 = select(yInt, z1, std::numeric_limits<float>::quiet_NaN());
+ z = select(xNegative, z1, z);
+ }
+
+ auto xFinite = isfinite(x);
+ auto yFinite = isfinite(y);
+ if (all(xFinite & yFinite))
+ return z;
+
+ // x finite and y infinite
+ z = select(andn(xFinite, yFinite),
+ select(x1 == 1.0f, 1.0f,
+ select((x1 > 1.0f) ^ (y < 0.0f), inf, T(0.0f))), z);
+
+ // x infinite
+ z = select(xFinite, z,
+ select(y == 0.0f, 1.0f,
+ select(y < 0.0f, T(0.0f), inf) | (asFloat(yOddInt) & x)));
+
+ return z;
+}
+
+template <typename T>
+__forceinline T pow(const T &x, float y)
+{
+ return pow(x, T(y));
+}
+
+} // namespace fastapprox
+
+} // namespace embree
diff --git a/thirdparty/embree/common/math/vec2.h b/thirdparty/embree/common/math/vec2.h
new file mode 100644
index 0000000000..d62aef51f3
--- /dev/null
+++ b/thirdparty/embree/common/math/vec2.h
@@ -0,0 +1,235 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "math.h"
+
+namespace embree
+{
+ struct Vec2fa;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Generic 2D vector Class
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> struct Vec2
+ {
+ enum { N = 2 };
+ union {
+ struct { T x, y; };
+#if !(defined(__WIN32__) && _MSC_VER == 1800) // workaround for older VS 2013 compiler
+ T components[N];
+#endif
+ };
+
+ typedef T Scalar;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec2( ) {}
+ __forceinline explicit Vec2( const T& a ) : x(a), y(a) {}
+ __forceinline Vec2( const T& x, const T& y ) : x(x), y(y) {}
+
+ __forceinline Vec2( const Vec2& other ) { x = other.x; y = other.y; }
+ __forceinline Vec2( const Vec2fa& other );
+
+ template<typename T1> __forceinline Vec2( const Vec2<T1>& a ) : x(T(a.x)), y(T(a.y)) {}
+ template<typename T1> __forceinline Vec2& operator =( const Vec2<T1>& other ) { x = other.x; y = other.y; return *this; }
+
+ __forceinline Vec2& operator =( const Vec2& other ) { x = other.x; y = other.y; return *this; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec2( ZeroTy ) : x(zero), y(zero) {}
+ __forceinline Vec2( OneTy ) : x(one), y(one) {}
+ __forceinline Vec2( PosInfTy ) : x(pos_inf), y(pos_inf) {}
+ __forceinline Vec2( NegInfTy ) : x(neg_inf), y(neg_inf) {}
+
+#if defined(__WIN32__) && _MSC_VER == 1800 // workaround for older VS 2013 compiler
+ __forceinline const T& operator [](const size_t axis) const { assert(axis < 2); return (&x)[axis]; }
+ __forceinline T& operator [](const size_t axis) { assert(axis < 2); return (&x)[axis]; }
+#else
+ __forceinline const T& operator [](const size_t axis) const { assert(axis < 2); return components[axis]; }
+ __forceinline T& operator [](const size_t axis ) { assert(axis < 2); return components[axis]; }
+#endif
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a ) { return Vec2<T>(+a.x, +a.y); }
+ template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a ) { return Vec2<T>(-a.x, -a.y); }
+ template<typename T> __forceinline Vec2<T> abs ( const Vec2<T>& a ) { return Vec2<T>(abs (a.x), abs (a.y)); }
+ template<typename T> __forceinline Vec2<T> rcp ( const Vec2<T>& a ) { return Vec2<T>(rcp (a.x), rcp (a.y)); }
+ template<typename T> __forceinline Vec2<T> rsqrt ( const Vec2<T>& a ) { return Vec2<T>(rsqrt(a.x), rsqrt(a.y)); }
+ template<typename T> __forceinline Vec2<T> sqrt ( const Vec2<T>& a ) { return Vec2<T>(sqrt (a.x), sqrt (a.y)); }
+ template<typename T> __forceinline Vec2<T> frac ( const Vec2<T>& a ) { return Vec2<T>(frac (a.x), frac (a.y)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x + b.x, a.y + b.y); }
+ template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x + b , a.y + b ); }
+ template<typename T> __forceinline Vec2<T> operator +( const T& a, const Vec2<T>& b ) { return Vec2<T>(a + b.x, a + b.y); }
+ template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x - b.x, a.y - b.y); }
+ template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x - b , a.y - b ); }
+ template<typename T> __forceinline Vec2<T> operator -( const T& a, const Vec2<T>& b ) { return Vec2<T>(a - b.x, a - b.y); }
+ template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x * b.x, a.y * b.y); }
+ template<typename T> __forceinline Vec2<T> operator *( const T& a, const Vec2<T>& b ) { return Vec2<T>(a * b.x, a * b.y); }
+ template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x * b , a.y * b ); }
+ template<typename T> __forceinline Vec2<T> operator /( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x / b.x, a.y / b.y); }
+ template<typename T> __forceinline Vec2<T> operator /( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x / b , a.y / b ); }
+ template<typename T> __forceinline Vec2<T> operator /( const T& a, const Vec2<T>& b ) { return Vec2<T>(a / b.x, a / b.y); }
+
+ template<typename T> __forceinline Vec2<T> min(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(min(a.x, b.x), min(a.y, b.y)); }
+ template<typename T> __forceinline Vec2<T> max(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(max(a.x, b.x), max(a.y, b.y)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec2<T> madd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y) ); }
+ template<typename T> __forceinline Vec2<T> msub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y) ); }
+ template<typename T> __forceinline Vec2<T> nmadd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y) ); }
+ template<typename T> __forceinline Vec2<T> nmsub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y) ); }
+
+ template<typename T> __forceinline Vec2<T> madd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a,b.x,c.x), madd(a,b.y,c.y) ); }
+ template<typename T> __forceinline Vec2<T> msub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a,b.x,c.x), msub(a,b.y,c.y) ); }
+ template<typename T> __forceinline Vec2<T> nmadd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y) ); }
+ template<typename T> __forceinline Vec2<T> nmsub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y) ); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec2<T>& operator +=( Vec2<T>& a, const Vec2<T>& b ) { a.x += b.x; a.y += b.y; return a; }
+ template<typename T> __forceinline Vec2<T>& operator -=( Vec2<T>& a, const Vec2<T>& b ) { a.x -= b.x; a.y -= b.y; return a; }
+ template<typename T> __forceinline Vec2<T>& operator *=( Vec2<T>& a, const T& b ) { a.x *= b ; a.y *= b ; return a; }
+ template<typename T> __forceinline Vec2<T>& operator /=( Vec2<T>& a, const T& b ) { a.x /= b ; a.y /= b ; return a; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline T reduce_add( const Vec2<T>& a ) { return a.x + a.y; }
+ template<typename T> __forceinline T reduce_mul( const Vec2<T>& a ) { return a.x * a.y; }
+ template<typename T> __forceinline T reduce_min( const Vec2<T>& a ) { return min(a.x, a.y); }
+ template<typename T> __forceinline T reduce_max( const Vec2<T>& a ) { return max(a.x, a.y); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline bool operator ==( const Vec2<T>& a, const Vec2<T>& b ) { return a.x == b.x && a.y == b.y; }
+ template<typename T> __forceinline bool operator !=( const Vec2<T>& a, const Vec2<T>& b ) { return a.x != b.x || a.y != b.y; }
+ template<typename T> __forceinline bool operator < ( const Vec2<T>& a, const Vec2<T>& b ) {
+ if (a.x != b.x) return a.x < b.x;
+ if (a.y != b.y) return a.y < b.y;
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Shift Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec2<T> shift_right_1( const Vec2<T>& a ) {
+ return Vec2<T>(shift_right_1(a.x),shift_right_1(a.y));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Euclidian Space Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline T dot ( const Vec2<T>& a, const Vec2<T>& b ) { return madd(a.x,b.x,a.y*b.y); }
+ template<typename T> __forceinline Vec2<T> cross ( const Vec2<T>& a ) { return Vec2<T>(-a.y,a.x); }
+ template<typename T> __forceinline T length ( const Vec2<T>& a ) { return sqrt(dot(a,a)); }
+ template<typename T> __forceinline Vec2<T> normalize( const Vec2<T>& a ) { return a*rsqrt(dot(a,a)); }
+ template<typename T> __forceinline T distance ( const Vec2<T>& a, const Vec2<T>& b ) { return length(a-b); }
+ template<typename T> __forceinline T det ( const Vec2<T>& a, const Vec2<T>& b ) { return a.x*b.y - a.y*b.x; }
+
+ template<typename T> __forceinline Vec2<T> normalize_safe( const Vec2<T>& a ) {
+ const T d = dot(a,a); return select(d == T( zero ),a, a*rsqrt(d) );
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec2<T> select ( bool s, const Vec2<T>& t, const Vec2<T>& f ) {
+ return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y));
+ }
+
+ template<typename T> __forceinline Vec2<T> select ( const Vec2<bool>& s, const Vec2<T>& t, const Vec2<T>& f ) {
+ return Vec2<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y));
+ }
+
+ template<typename T> __forceinline Vec2<T> select ( const typename T::Bool& s, const Vec2<T>& t, const Vec2<T>& f ) {
+ return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y));
+ }
+
+ template<typename T>
+ __forceinline Vec2<T> lerp(const Vec2<T>& v0, const Vec2<T>& v1, const T& t) {
+ return madd(Vec2<T>(T(1.0f)-t),v0,t*v1);
+ }
+
+ template<typename T> __forceinline int maxDim ( const Vec2<T>& a )
+ {
+ const Vec2<T> b = abs(a);
+ if (b.x > b.y) return 0;
+ else return 1;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Vec2<T>& a) {
+ return cout << "(" << a.x << ", " << a.y << ")";
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Default template instantiations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ typedef Vec2<bool > Vec2b;
+ typedef Vec2<int > Vec2i;
+ typedef Vec2<float> Vec2f;
+}
+
+#include "vec2fa.h"
+
+#if defined __SSE__
+#include "../simd/sse.h"
+#endif
+
+#if defined __AVX__
+#include "../simd/avx.h"
+#endif
+
+#if defined(__AVX512F__)
+#include "../simd/avx512.h"
+#endif
+
+namespace embree
+{
+ template<> __forceinline Vec2<float>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
+
+#if defined(__SSE__)
+ template<> __forceinline Vec2<vfloat4>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
+#endif
+
+#if defined(__AVX__)
+ template<> __forceinline Vec2<vfloat8>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
+#endif
+
+#if defined(__AVX512F__)
+ template<> __forceinline Vec2<vfloat16>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {}
+#endif
+}
diff --git a/thirdparty/embree/common/math/vec2fa.h b/thirdparty/embree/common/math/vec2fa.h
new file mode 100644
index 0000000000..a51fb68fd0
--- /dev/null
+++ b/thirdparty/embree/common/math/vec2fa.h
@@ -0,0 +1,301 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/alloc.h"
+#include "math.h"
+#include "../simd/sse.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// SSE Vec2fa Type
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct __aligned(16) Vec2fa
+ {
+ ALIGNED_STRUCT_(16);
+
+ typedef float Scalar;
+ enum { N = 2 };
+ union {
+ __m128 m128;
+ struct { float x,y,az,aw; };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec2fa( ) {}
+ __forceinline Vec2fa( const __m128 a ) : m128(a) {}
+
+ __forceinline Vec2fa ( const Vec2<float>& other ) { x = other.x; y = other.y; }
+ __forceinline Vec2fa& operator =( const Vec2<float>& other ) { x = other.x; y = other.y; return *this; }
+
+ __forceinline Vec2fa ( const Vec2fa& other ) { m128 = other.m128; }
+ __forceinline Vec2fa& operator =( const Vec2fa& other ) { m128 = other.m128; return *this; }
+
+ __forceinline explicit Vec2fa( const float a ) : m128(_mm_set1_ps(a)) {}
+ __forceinline Vec2fa( const float x, const float y) : m128(_mm_set_ps(y, y, y, x)) {}
+
+ __forceinline explicit Vec2fa( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
+
+ __forceinline operator const __m128&() const { return m128; }
+ __forceinline operator __m128&() { return m128; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline Vec2fa load( const void* const a ) {
+ return Vec2fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, 0, -1, -1))));
+ }
+
+ static __forceinline Vec2fa loadu( const void* const a ) {
+ return Vec2fa(_mm_and_ps(_mm_loadu_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, 0, -1, -1))));
+ }
+
+ static __forceinline void storeu ( void* ptr, const Vec2fa& v ) {
+ _mm_storeu_ps((float*)ptr,v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec2fa( ZeroTy ) : m128(_mm_setzero_ps()) {}
+ __forceinline Vec2fa( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
+ __forceinline Vec2fa( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
+ __forceinline Vec2fa( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const float& operator []( const size_t index ) const { assert(index < 2); return (&x)[index]; }
+ __forceinline float& operator []( const size_t index ) { assert(index < 2); return (&x)[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec2fa operator +( const Vec2fa& a ) { return a; }
+ __forceinline Vec2fa operator -( const Vec2fa& a ) {
+ const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
+ return _mm_xor_ps(a.m128, mask);
+ }
+ __forceinline Vec2fa abs ( const Vec2fa& a ) {
+ const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
+ return _mm_and_ps(a.m128, mask);
+ }
+ __forceinline Vec2fa sign ( const Vec2fa& a ) {
+ return blendv_ps(Vec2fa(one), -Vec2fa(one), _mm_cmplt_ps (a,Vec2fa(zero)));
+ }
+
+ __forceinline Vec2fa rcp ( const Vec2fa& a )
+ {
+#if defined(__AVX512VL__)
+ const Vec2fa r = _mm_rcp14_ps(a.m128);
+#else
+ const Vec2fa r = _mm_rcp_ps(a.m128);
+#endif
+
+#if defined(__AVX2__)
+ const Vec2fa res = _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f)));
+#else
+ const Vec2fa res = _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a)));
+ //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+#endif
+
+ return res;
+ }
+
+ __forceinline Vec2fa sqrt ( const Vec2fa& a ) { return _mm_sqrt_ps(a.m128); }
+ __forceinline Vec2fa sqr ( const Vec2fa& a ) { return _mm_mul_ps(a,a); }
+
+ __forceinline Vec2fa rsqrt( const Vec2fa& a )
+ {
+#if defined(__AVX512VL__)
+ __m128 r = _mm_rsqrt14_ps(a.m128);
+#else
+ __m128 r = _mm_rsqrt_ps(a.m128);
+#endif
+ return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+ }
+
+ __forceinline Vec2fa zero_fix(const Vec2fa& a) {
+ return blendv_ps(a, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
+ }
+ __forceinline Vec2fa rcp_safe(const Vec2fa& a) {
+ return rcp(zero_fix(a));
+ }
+ __forceinline Vec2fa log ( const Vec2fa& a ) {
+ return Vec2fa(logf(a.x),logf(a.y));
+ }
+
+ __forceinline Vec2fa exp ( const Vec2fa& a ) {
+ return Vec2fa(expf(a.x),expf(a.y));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec2fa operator +( const Vec2fa& a, const Vec2fa& b ) { return _mm_add_ps(a.m128, b.m128); }
+ __forceinline Vec2fa operator -( const Vec2fa& a, const Vec2fa& b ) { return _mm_sub_ps(a.m128, b.m128); }
+ __forceinline Vec2fa operator *( const Vec2fa& a, const Vec2fa& b ) { return _mm_mul_ps(a.m128, b.m128); }
+ __forceinline Vec2fa operator *( const Vec2fa& a, const float b ) { return a * Vec2fa(b); }
+ __forceinline Vec2fa operator *( const float a, const Vec2fa& b ) { return Vec2fa(a) * b; }
+ __forceinline Vec2fa operator /( const Vec2fa& a, const Vec2fa& b ) { return _mm_div_ps(a.m128,b.m128); }
+ __forceinline Vec2fa operator /( const Vec2fa& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
+ __forceinline Vec2fa operator /( const float a, const Vec2fa& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
+
+ __forceinline Vec2fa min( const Vec2fa& a, const Vec2fa& b ) { return _mm_min_ps(a.m128,b.m128); }
+ __forceinline Vec2fa max( const Vec2fa& a, const Vec2fa& b ) { return _mm_max_ps(a.m128,b.m128); }
+
+#if defined(__SSE4_1__)
+ __forceinline Vec2fa mini(const Vec2fa& a, const Vec2fa& b) {
+ const vint4 ai = _mm_castps_si128(a);
+ const vint4 bi = _mm_castps_si128(b);
+ const vint4 ci = _mm_min_epi32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+#endif
+
+#if defined(__SSE4_1__)
+ __forceinline Vec2fa maxi(const Vec2fa& a, const Vec2fa& b) {
+ const vint4 ai = _mm_castps_si128(a);
+ const vint4 bi = _mm_castps_si128(b);
+ const vint4 ci = _mm_max_epi32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+#endif
+
+ __forceinline Vec2fa pow ( const Vec2fa& a, const float& b ) {
+ return Vec2fa(powf(a.x,b),powf(a.y,b));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX2__)
+ __forceinline Vec2fa madd ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return _mm_fmadd_ps(a,b,c); }
+ __forceinline Vec2fa msub ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return _mm_fmsub_ps(a,b,c); }
+ __forceinline Vec2fa nmadd ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return _mm_fnmadd_ps(a,b,c); }
+ __forceinline Vec2fa nmsub ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return _mm_fnmsub_ps(a,b,c); }
+#else
+ __forceinline Vec2fa madd ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return a*b+c; }
+ __forceinline Vec2fa msub ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return a*b-c; }
+ __forceinline Vec2fa nmadd ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return -a*b+c;}
+ __forceinline Vec2fa nmsub ( const Vec2fa& a, const Vec2fa& b, const Vec2fa& c) { return -a*b-c; }
+#endif
+
+ __forceinline Vec2fa madd ( const float a, const Vec2fa& b, const Vec2fa& c) { return madd(Vec2fa(a),b,c); }
+ __forceinline Vec2fa msub ( const float a, const Vec2fa& b, const Vec2fa& c) { return msub(Vec2fa(a),b,c); }
+ __forceinline Vec2fa nmadd ( const float a, const Vec2fa& b, const Vec2fa& c) { return nmadd(Vec2fa(a),b,c); }
+ __forceinline Vec2fa nmsub ( const float a, const Vec2fa& b, const Vec2fa& c) { return nmsub(Vec2fa(a),b,c); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec2fa& operator +=( Vec2fa& a, const Vec2fa& b ) { return a = a + b; }
+ __forceinline Vec2fa& operator -=( Vec2fa& a, const Vec2fa& b ) { return a = a - b; }
+ __forceinline Vec2fa& operator *=( Vec2fa& a, const Vec2fa& b ) { return a = a * b; }
+ __forceinline Vec2fa& operator *=( Vec2fa& a, const float b ) { return a = a * b; }
+ __forceinline Vec2fa& operator /=( Vec2fa& a, const Vec2fa& b ) { return a = a / b; }
+ __forceinline Vec2fa& operator /=( Vec2fa& a, const float b ) { return a = a / b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline float reduce_add(const Vec2fa& v) { return v.x+v.y; }
+ __forceinline float reduce_mul(const Vec2fa& v) { return v.x*v.y; }
+ __forceinline float reduce_min(const Vec2fa& v) { return min(v.x,v.y); }
+ __forceinline float reduce_max(const Vec2fa& v) { return max(v.x,v.y); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator ==( const Vec2fa& a, const Vec2fa& b ) { return (_mm_movemask_ps(_mm_cmpeq_ps (a.m128, b.m128)) & 3) == 3; }
+ __forceinline bool operator !=( const Vec2fa& a, const Vec2fa& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 3) != 0; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Euclidian Space Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__SSE4_1__)
+ __forceinline float dot ( const Vec2fa& a, const Vec2fa& b ) {
+ return _mm_cvtss_f32(_mm_dp_ps(a,b,0x3F));
+ }
+#else
+ __forceinline float dot ( const Vec2fa& a, const Vec2fa& b ) {
+ return reduce_add(a*b);
+ }
+#endif
+
+ __forceinline Vec2fa cross ( const Vec2fa& a ) {
+ return Vec2fa(-a.y,a.x);
+ }
+
+ __forceinline float sqr_length ( const Vec2fa& a ) { return dot(a,a); }
+ __forceinline float rcp_length ( const Vec2fa& a ) { return rsqrt(dot(a,a)); }
+ __forceinline float rcp_length2( const Vec2fa& a ) { return rcp(dot(a,a)); }
+ __forceinline float length ( const Vec2fa& a ) { return sqrt(dot(a,a)); }
+ __forceinline Vec2fa normalize( const Vec2fa& a ) { return a*rsqrt(dot(a,a)); }
+ __forceinline float distance ( const Vec2fa& a, const Vec2fa& b ) { return length(a-b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec2fa select( bool s, const Vec2fa& t, const Vec2fa& f ) {
+ __m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
+ return blendv_ps(f, t, mask);
+ }
+
+ __forceinline Vec2fa lerp(const Vec2fa& v0, const Vec2fa& v1, const float t) {
+ return madd(1.0f-t,v0,t*v1);
+ }
+
+ __forceinline int maxDim ( const Vec2fa& a )
+ {
+ const Vec2fa b = abs(a);
+ if (b.x > b.y) return 0;
+ else return 1;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Rounding Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__aarch64__)
+ //__forceinline Vec2fa trunc(const Vec2fa& a) { return vrndq_f32(a); }
+ __forceinline Vec2fa floor(const Vec2fa& a) { return vrndmq_f32(a); }
+ __forceinline Vec2fa ceil (const Vec2fa& a) { return vrndpq_f32(a); }
+#elif defined (__SSE4_1__)
+ //__forceinline Vec2fa trunc( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
+ __forceinline Vec2fa floor( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
+ __forceinline Vec2fa ceil ( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
+#else
+ //__forceinline Vec2fa trunc( const Vec2fa& a ) { return Vec2fa(truncf(a.x),truncf(a.y),truncf(a.z)); }
+ __forceinline Vec2fa floor( const Vec2fa& a ) { return Vec2fa(floorf(a.x),floorf(a.y)); }
+ __forceinline Vec2fa ceil ( const Vec2fa& a ) { return Vec2fa(ceilf (a.x),ceilf (a.y)); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator<<(embree_ostream cout, const Vec2fa& a) {
+ return cout << "(" << a.x << ", " << a.y << ")";
+ }
+
+ typedef Vec2fa Vec2fa_t;
+}
diff --git a/thirdparty/embree/common/math/vec3.h b/thirdparty/embree/common/math/vec3.h
new file mode 100644
index 0000000000..ce94eff327
--- /dev/null
+++ b/thirdparty/embree/common/math/vec3.h
@@ -0,0 +1,337 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "math.h"
+
+namespace embree
+{
+ struct Vec3fa;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Generic 3D vector Class
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> struct Vec3
+ {
+ enum { N = 3 };
+
+ union {
+ struct {
+ T x, y, z;
+ };
+#if !(defined(__WIN32__) && _MSC_VER == 1800) // workaround for older VS 2013 compiler
+ T components[N];
+#endif
+ };
+
+ typedef T Scalar;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3( ) {}
+ __forceinline explicit Vec3( const T& a ) : x(a), y(a), z(a) {}
+ __forceinline Vec3( const T& x, const T& y, const T& z ) : x(x), y(y), z(z) {}
+
+ __forceinline Vec3( const Vec3& other ) { x = other.x; y = other.y; z = other.z; }
+ __forceinline Vec3( const Vec3fa& other );
+
+ template<typename T1> __forceinline Vec3( const Vec3<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)) {}
+ template<typename T1> __forceinline Vec3& operator =(const Vec3<T1>& other) { x = other.x; y = other.y; z = other.z; return *this; }
+
+ __forceinline Vec3& operator =(const Vec3& other) { x = other.x; y = other.y; z = other.z; return *this; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3( ZeroTy ) : x(zero), y(zero), z(zero) {}
+ __forceinline Vec3( OneTy ) : x(one), y(one), z(one) {}
+ __forceinline Vec3( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf) {}
+ __forceinline Vec3( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf) {}
+
+#if defined(__WIN32__) && (_MSC_VER == 1800) // workaround for older VS 2013 compiler
+ __forceinline const T& operator []( const size_t axis ) const { assert(axis < 3); return (&x)[axis]; }
+ __forceinline T& operator []( const size_t axis ) { assert(axis < 3); return (&x)[axis]; }
+#else
+ __forceinline const T& operator [](const size_t axis) const { assert(axis < 3); return components[axis]; }
+ __forceinline T& operator [](const size_t axis) { assert(axis < 3); return components[axis]; }
+#endif
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec3<T> operator +( const Vec3<T>& a ) { return Vec3<T>(+a.x, +a.y, +a.z); }
+ template<typename T> __forceinline Vec3<T> operator -( const Vec3<T>& a ) { return Vec3<T>(-a.x, -a.y, -a.z); }
+ template<typename T> __forceinline Vec3<T> abs ( const Vec3<T>& a ) { return Vec3<T>(abs (a.x), abs (a.y), abs (a.z)); }
+ template<typename T> __forceinline Vec3<T> rcp ( const Vec3<T>& a ) { return Vec3<T>(rcp (a.x), rcp (a.y), rcp (a.z)); }
+ template<typename T> __forceinline Vec3<T> rsqrt ( const Vec3<T>& a ) { return Vec3<T>(rsqrt(a.x), rsqrt(a.y), rsqrt(a.z)); }
+ template<typename T> __forceinline Vec3<T> sqrt ( const Vec3<T>& a ) { return Vec3<T>(sqrt (a.x), sqrt (a.y), sqrt (a.z)); }
+
+ template<typename T> __forceinline Vec3<T> zero_fix( const Vec3<T>& a )
+ {
+ return Vec3<T>(select(abs(a.x)<min_rcp_input,T(min_rcp_input),a.x),
+ select(abs(a.y)<min_rcp_input,T(min_rcp_input),a.y),
+ select(abs(a.z)<min_rcp_input,T(min_rcp_input),a.z));
+ }
+ template<typename T> __forceinline Vec3<T> rcp_safe(const Vec3<T>& a) { return rcp(zero_fix(a)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec3<T> operator +( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x + b.x, a.y + b.y, a.z + b.z); }
+ template<typename T> __forceinline Vec3<T> operator -( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x - b.x, a.y - b.y, a.z - b.z); }
+ template<typename T> __forceinline Vec3<T> operator *( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x * b.x, a.y * b.y, a.z * b.z); }
+ template<typename T> __forceinline Vec3<T> operator *( const T& a, const Vec3<T>& b ) { return Vec3<T>(a * b.x, a * b.y, a * b.z); }
+ template<typename T> __forceinline Vec3<T> operator *( const Vec3<T>& a, const T& b ) { return Vec3<T>(a.x * b , a.y * b , a.z * b ); }
+ template<typename T> __forceinline Vec3<T> operator /( const Vec3<T>& a, const T& b ) { return Vec3<T>(a.x / b , a.y / b , a.z / b ); }
+ template<typename T> __forceinline Vec3<T> operator /( const T& a, const Vec3<T>& b ) { return Vec3<T>(a / b.x, a / b.y, a / b.z); }
+ template<typename T> __forceinline Vec3<T> operator /( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x / b.x, a.y / b.y, a.z / b.z); }
+
+ template<typename T> __forceinline Vec3<T> min(const Vec3<T>& a, const Vec3<T>& b) { return Vec3<T>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); }
+ template<typename T> __forceinline Vec3<T> max(const Vec3<T>& a, const Vec3<T>& b) { return Vec3<T>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); }
+
+ template<typename T> __forceinline Vec3<T> operator >>( const Vec3<T>& a, const int b ) { return Vec3<T>(a.x >> b, a.y >> b, a.z >> b); }
+ template<typename T> __forceinline Vec3<T> operator <<( const Vec3<T>& a, const int b ) { return Vec3<T>(a.x << b, a.y << b, a.z << b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec3<T> madd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z)); }
+ template<typename T> __forceinline Vec3<T> msub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z)); }
+ template<typename T> __forceinline Vec3<T> nmadd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z));}
+ template<typename T> __forceinline Vec3<T> nmsub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z)); }
+
+ template<typename T> __forceinline Vec3<T> madd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z)); }
+ template<typename T> __forceinline Vec3<T> msub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z)); }
+ template<typename T> __forceinline Vec3<T> nmadd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z));}
+ template<typename T> __forceinline Vec3<T> nmsub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const T b ) { a.x += b; a.y += b; a.z += b; return a; }
+ template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const Vec3<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
+ template<typename T> __forceinline Vec3<T>& operator -=( Vec3<T>& a, const Vec3<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
+ template<typename T> __forceinline Vec3<T>& operator *=( Vec3<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; return a; }
+ template<typename T> __forceinline Vec3<T>& operator /=( Vec3<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; return a; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline T reduce_add( const Vec3<T>& a ) { return a.x + a.y + a.z; }
+ template<typename T> __forceinline T reduce_mul( const Vec3<T>& a ) { return a.x * a.y * a.z; }
+ template<typename T> __forceinline T reduce_min( const Vec3<T>& a ) { return min(a.x, a.y, a.z); }
+ template<typename T> __forceinline T reduce_max( const Vec3<T>& a ) { return max(a.x, a.y, a.z); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline bool operator ==( const Vec3<T>& a, const Vec3<T>& b ) { return a.x == b.x && a.y == b.y && a.z == b.z; }
+ template<typename T> __forceinline bool operator !=( const Vec3<T>& a, const Vec3<T>& b ) { return a.x != b.x || a.y != b.y || a.z != b.z; }
+ template<typename T> __forceinline bool operator < ( const Vec3<T>& a, const Vec3<T>& b ) {
+ if (a.x != b.x) return a.x < b.x;
+ if (a.y != b.y) return a.y < b.y;
+ if (a.z != b.z) return a.z < b.z;
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Shift Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec3<T> shift_right_1( const Vec3<T>& a ) {
+ return Vec3<T>(shift_right_1(a.x),shift_right_1(a.y),shift_right_1(a.z));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec3<T> select ( bool s, const Vec3<T>& t, const Vec3<T>& f ) {
+ return Vec3<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z));
+ }
+
+ template<typename T> __forceinline Vec3<T> select ( const Vec3<bool>& s, const Vec3<T>& t, const Vec3<T>& f ) {
+ return Vec3<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z));
+ }
+
+ template<typename T> __forceinline Vec3<T> select ( const typename T::Bool& s, const Vec3<T>& t, const Vec3<T>& f ) {
+ return Vec3<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z));
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> lerp(const Vec3<T>& v0, const Vec3<T>& v1, const T& t) {
+ return madd(Vec3<T>(T(1.0f)-t),v0,t*v1);
+ }
+
+ template<typename T> __forceinline int maxDim ( const Vec3<T>& a )
+ {
+ const Vec3<T> b = abs(a);
+ if (b.x > b.y) {
+ if (b.x > b.z) return 0; else return 2;
+ } else {
+ if (b.y > b.z) return 1; else return 2;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec3<bool> eq_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x==b.x,a.y==b.y,a.z==b.z); }
+ template<typename T> __forceinline Vec3<bool> neq_mask(const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x!=b.x,a.y!=b.y,a.z!=b.z); }
+ template<typename T> __forceinline Vec3<bool> lt_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x< b.x,a.y< b.y,a.z< b.z); }
+ template<typename T> __forceinline Vec3<bool> le_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x<=b.x,a.y<=b.y,a.z<=b.z); }
+ template<typename T> __forceinline Vec3<bool> gt_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x> b.x,a.y> b.y,a.z> b.z); }
+ template<typename T> __forceinline Vec3<bool> ge_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x>=b.x,a.y>=b.y,a.z>=b.z); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Euclidian Space Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline T sqr ( const Vec3<T>& a ) { return dot(a,a); }
+ template<typename T> __forceinline T dot ( const Vec3<T>& a, const Vec3<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,a.z*b.z)); }
+ template<typename T> __forceinline T length ( const Vec3<T>& a ) { return sqrt(sqr(a)); }
+ template<typename T> __forceinline T rcp_length( const Vec3<T>& a ) { return rsqrt(sqr(a)); }
+ template<typename T> __forceinline Vec3<T> normalize( const Vec3<T>& a ) { return a*rsqrt(sqr(a)); }
+ template<typename T> __forceinline T distance ( const Vec3<T>& a, const Vec3<T>& b ) { return length(a-b); }
+ template<typename T> __forceinline Vec3<T> cross ( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(msub(a.y,b.z,a.z*b.y), msub(a.z,b.x,a.x*b.z), msub(a.x,b.y,a.y*b.x)); }
+
+ template<typename T> __forceinline Vec3<T> stable_triangle_normal( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c )
+ {
+ const T ab_x = a.z*b.y, ab_y = a.x*b.z, ab_z = a.y*b.x;
+ const T bc_x = b.z*c.y, bc_y = b.x*c.z, bc_z = b.y*c.x;
+ const Vec3<T> cross_ab(msub(a.y,b.z,ab_x), msub(a.z,b.x,ab_y), msub(a.x,b.y,ab_z));
+ const Vec3<T> cross_bc(msub(b.y,c.z,bc_x), msub(b.z,c.x,bc_y), msub(b.x,c.y,bc_z));
+ const auto sx = abs(ab_x) < abs(bc_x);
+ const auto sy = abs(ab_y) < abs(bc_y);
+ const auto sz = abs(ab_z) < abs(bc_z);
+ return Vec3<T>(select(sx,cross_ab.x,cross_bc.x),
+ select(sy,cross_ab.y,cross_bc.y),
+ select(sz,cross_ab.z,cross_bc.z));
+ }
+
+ template<typename T> __forceinline T sum ( const Vec3<T>& a ) { return a.x+a.y+a.z; }
+
+ template<typename T> __forceinline T halfArea ( const Vec3<T>& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
+ template<typename T> __forceinline T area ( const Vec3<T>& d ) { return 2.0f*halfArea(d); }
+
+ template<typename T> __forceinline Vec3<T> normalize_safe( const Vec3<T>& a ) {
+ const T d = dot(a,a); return select(d == T( zero ), a , a*rsqrt(d) );
+ }
+
+ template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& P, const Vec3<T>& Q0, const Vec3<T>& Q1)
+ {
+ const Vec3<T> N = cross(P-Q0,Q1-Q0);
+ const Vec3<T> D = Q1-Q0;
+ return dot(N,N)*rcp(dot(D,D));
+ }
+
+ template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& PmQ0, const Vec3<T>& Q1mQ0)
+ {
+ const Vec3<T> N = cross(PmQ0,Q1mQ0);
+ const Vec3<T> D = Q1mQ0;
+ return dot(N,N)*rcp(dot(D,D));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3<T>& a) {
+ return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
+ }
+
+ typedef Vec3<bool > Vec3b;
+ typedef Vec3<int > Vec3i;
+ typedef Vec3<float> Vec3f;
+}
+
+#include "vec3ba.h"
+#include "vec3ia.h"
+#include "vec3fa.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/// SSE / AVX / MIC specializations
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined __SSE__
+#include "../simd/sse.h"
+#endif
+
+#if defined __AVX__
+#include "../simd/avx.h"
+#endif
+
+#if defined(__AVX512F__)
+#include "../simd/avx512.h"
+#endif
+
+namespace embree
+{
+ template<typename Out, typename In>
+ __forceinline Vec3<Out> broadcast(const Vec3<In>& a, const size_t k) {
+ return Vec3<Out>(Out(a.x[k]), Out(a.y[k]), Out(a.z[k]));
+ }
+
+ template<> __forceinline Vec3<float>::Vec3(const Vec3fa& a) { x = a.x; y = a.y; z = a.z; }
+
+#if defined(__AVX__)
+ template<> __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
+ x = a.x; y = a.y; z = a.z;
+ }
+#elif defined(__SSE__)
+ template<>
+ __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
+ const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
+ }
+#endif
+
+#if defined(__SSE__)
+ template<>
+ __forceinline Vec3<vfloat4> broadcast<vfloat4,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
+ return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline Vec3<vfloat4> shuffle(const Vec3<vfloat4>& b) {
+ return Vec3<vfloat4>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
+ }
+#endif
+
+#if defined(__AVX__)
+ template<>
+ __forceinline Vec3<vfloat8>::Vec3(const Vec3fa& a) {
+ x = a.x; y = a.y; z = a.z;
+ }
+
+ template<>
+ __forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
+ return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
+ }
+ template<>
+ __forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat8>(const Vec3<vfloat8>& a, const size_t k) {
+ return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline Vec3<vfloat8> shuffle(const Vec3<vfloat8>& b) {
+ return Vec3<vfloat8>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
+ }
+#endif
+
+#if defined(__AVX512F__)
+ template<> __forceinline Vec3<vfloat16>::Vec3(const Vec3fa& a) : x(a.x), y(a.y), z(a.z) {}
+#endif
+}
diff --git a/thirdparty/embree/common/math/vec3ba.h b/thirdparty/embree/common/math/vec3ba.h
new file mode 100644
index 0000000000..a021b522dc
--- /dev/null
+++ b/thirdparty/embree/common/math/vec3ba.h
@@ -0,0 +1,120 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/alloc.h"
+#include "math.h"
+#include "../simd/sse.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// SSE Vec3ba Type
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct __aligned(16) Vec3ba
+ {
+ ALIGNED_STRUCT_(16);
+
+ union {
+ __m128 m128;
+ struct { int x,y,z; };
+ };
+
+ typedef int Scalar;
+ enum { N = 3 };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ba( ) {}
+ __forceinline Vec3ba( const __m128 input ) : m128(input) {}
+ __forceinline Vec3ba( const Vec3ba& other ) : m128(other.m128) {}
+ __forceinline Vec3ba& operator =(const Vec3ba& other) { m128 = other.m128; return *this; }
+
+ __forceinline explicit Vec3ba( bool a )
+ : m128(mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
+ __forceinline Vec3ba( bool a, bool b, bool c)
+ : m128(mm_lookupmask_ps[(size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
+
+ __forceinline operator const __m128&() const { return m128; }
+ __forceinline operator __m128&() { return m128; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ba( FalseTy ) : m128(_mm_setzero_ps()) {}
+ __forceinline Vec3ba( TrueTy ) : m128(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const int& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
+ __forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ba operator !( const Vec3ba& a ) { return _mm_xor_ps(a.m128, Vec3ba(embree::True)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return _mm_and_ps(a.m128, b.m128); }
+ __forceinline Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return _mm_or_ps (a.m128, b.m128); }
+ __forceinline Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return _mm_xor_ps(a.m128, b.m128); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ba& operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
+ __forceinline Vec3ba& operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
+ __forceinline Vec3ba& operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator ==( const Vec3ba& a, const Vec3ba& b ) {
+ return (_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_castps_si128(a.m128), _mm_castps_si128(b.m128)))) & 7) == 7;
+ }
+ __forceinline bool operator !=( const Vec3ba& a, const Vec3ba& b ) {
+ return (_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_castps_si128(a.m128), _mm_castps_si128(b.m128)))) & 7) != 7;
+ }
+ __forceinline bool operator < ( const Vec3ba& a, const Vec3ba& b ) {
+ if (a.x != b.x) return a.x < b.x;
+ if (a.y != b.y) return a.y < b.y;
+ if (a.z != b.z) return a.z < b.z;
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool reduce_and( const Vec3ba& a ) { return (_mm_movemask_ps(a) & 0x7) == 0x7; }
+ __forceinline bool reduce_or ( const Vec3ba& a ) { return (_mm_movemask_ps(a) & 0x7) != 0x0; }
+
+ __forceinline bool all ( const Vec3ba& b ) { return (_mm_movemask_ps(b) & 0x7) == 0x7; }
+ __forceinline bool any ( const Vec3ba& b ) { return (_mm_movemask_ps(b) & 0x7) != 0x0; }
+ __forceinline bool none ( const Vec3ba& b ) { return (_mm_movemask_ps(b) & 0x7) == 0x0; }
+
+ __forceinline size_t movemask(const Vec3ba& a) { return _mm_movemask_ps(a) & 0x7; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3ba& a) {
+ return cout << "(" << (a.x ? "1" : "0") << ", " << (a.y ? "1" : "0") << ", " << (a.z ? "1" : "0") << ")";
+ }
+}
diff --git a/thirdparty/embree/common/math/vec3fa.h b/thirdparty/embree/common/math/vec3fa.h
new file mode 100644
index 0000000000..586039741d
--- /dev/null
+++ b/thirdparty/embree/common/math/vec3fa.h
@@ -0,0 +1,727 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/alloc.h"
+#include "math.h"
+#include "../simd/sse.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// SSE Vec3fa Type
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct __aligned(16) Vec3fa
+ {
+ ALIGNED_STRUCT_(16);
+
+ typedef float Scalar;
+ enum { N = 3 };
+ union {
+ __m128 m128;
+ struct { float x,y,z; };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fa( ) {}
+ __forceinline Vec3fa( const __m128 a ) : m128(a) {}
+
+ __forceinline Vec3fa ( const Vec3<float>& other ) { m128 = _mm_set_ps(0, other.z, other.y, other.x); }
+ //__forceinline Vec3fa& operator =( const Vec3<float>& other ) { m128 = _mm_set_ps(0, other.z, other.y, other.x); return *this; }
+
+ __forceinline Vec3fa ( const Vec3fa& other ) { m128 = other.m128; }
+ __forceinline Vec3fa& operator =( const Vec3fa& other ) { m128 = other.m128; return *this; }
+
+ __forceinline explicit Vec3fa( const float a ) : m128(_mm_set1_ps(a)) {}
+ __forceinline Vec3fa( const float x, const float y, const float z) : m128(_mm_set_ps(0, z, y, x)) {}
+
+ __forceinline explicit Vec3fa( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
+
+ __forceinline explicit operator const vfloat4() const { return vfloat4(m128); }
+ __forceinline explicit operator const vint4() const { return vint4(_mm_cvtps_epi32(m128)); }
+ __forceinline explicit operator const Vec2fa() const { return Vec2fa(m128); }
+ __forceinline explicit operator const Vec3ia() const { return Vec3ia(_mm_cvtps_epi32(m128)); }
+
+ //__forceinline operator const __m128&() const { return m128; }
+ //__forceinline operator __m128&() { return m128; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline Vec3fa load( const void* const a ) {
+ return Vec3fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
+ }
+
+ static __forceinline Vec3fa loadu( const void* const a ) {
+ return Vec3fa(_mm_loadu_ps((float*)a));
+ }
+
+ static __forceinline void storeu ( void* ptr, const Vec3fa& v ) {
+ _mm_storeu_ps((float*)ptr,v.m128);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fa( ZeroTy ) : m128(_mm_setzero_ps()) {}
+ __forceinline Vec3fa( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
+ __forceinline Vec3fa( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
+ __forceinline Vec3fa( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const float& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
+ __forceinline float& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fa operator +( const Vec3fa& a ) { return a; }
+ __forceinline Vec3fa operator -( const Vec3fa& a ) {
+ const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
+ return _mm_xor_ps(a.m128, mask);
+ }
+ __forceinline Vec3fa abs ( const Vec3fa& a ) {
+ const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
+ return _mm_and_ps(a.m128, mask);
+ }
+ __forceinline Vec3fa sign ( const Vec3fa& a ) {
+ return blendv_ps(Vec3fa(one).m128, (-Vec3fa(one)).m128, _mm_cmplt_ps (a.m128,Vec3fa(zero).m128));
+ }
+
+ __forceinline Vec3fa rcp ( const Vec3fa& a )
+ {
+#if defined(__AVX512VL__)
+ const Vec3fa r = _mm_rcp14_ps(a.m128);
+#else
+ const Vec3fa r = _mm_rcp_ps(a.m128);
+#endif
+
+#if defined(__AVX2__)
+ const Vec3fa res = _mm_mul_ps(r.m128,_mm_fnmadd_ps(r.m128, a.m128, vfloat4(2.0f)));
+#else
+ const Vec3fa res = _mm_mul_ps(r.m128,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r.m128, a.m128)));
+ //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+#endif
+
+ return res;
+ }
+
+ __forceinline Vec3fa sqrt ( const Vec3fa& a ) { return _mm_sqrt_ps(a.m128); }
+ __forceinline Vec3fa sqr ( const Vec3fa& a ) { return _mm_mul_ps(a.m128,a.m128); }
+
+ __forceinline Vec3fa rsqrt( const Vec3fa& a )
+ {
+#if defined(__AVX512VL__)
+ __m128 r = _mm_rsqrt14_ps(a.m128);
+#else
+ __m128 r = _mm_rsqrt_ps(a.m128);
+#endif
+ return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a.m128, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+ }
+
+ __forceinline Vec3fa zero_fix(const Vec3fa& a) {
+ return blendv_ps(a.m128, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
+ }
+ __forceinline Vec3fa rcp_safe(const Vec3fa& a) {
+ return rcp(zero_fix(a));
+ }
+ __forceinline Vec3fa log ( const Vec3fa& a ) {
+ return Vec3fa(logf(a.x),logf(a.y),logf(a.z));
+ }
+
+ __forceinline Vec3fa exp ( const Vec3fa& a ) {
+ return Vec3fa(expf(a.x),expf(a.y),expf(a.z));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fa operator +( const Vec3fa& a, const Vec3fa& b ) { return _mm_add_ps(a.m128, b.m128); }
+ __forceinline Vec3fa operator -( const Vec3fa& a, const Vec3fa& b ) { return _mm_sub_ps(a.m128, b.m128); }
+ __forceinline Vec3fa operator *( const Vec3fa& a, const Vec3fa& b ) { return _mm_mul_ps(a.m128, b.m128); }
+ __forceinline Vec3fa operator *( const Vec3fa& a, const float b ) { return a * Vec3fa(b); }
+ __forceinline Vec3fa operator *( const float a, const Vec3fa& b ) { return Vec3fa(a) * b; }
+ __forceinline Vec3fa operator /( const Vec3fa& a, const Vec3fa& b ) { return _mm_div_ps(a.m128,b.m128); }
+ __forceinline Vec3fa operator /( const Vec3fa& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
+ __forceinline Vec3fa operator /( const float a, const Vec3fa& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
+
+ __forceinline Vec3fa min( const Vec3fa& a, const Vec3fa& b ) { return _mm_min_ps(a.m128,b.m128); }
+ __forceinline Vec3fa max( const Vec3fa& a, const Vec3fa& b ) { return _mm_max_ps(a.m128,b.m128); }
+
+#if defined(__SSE4_1__)
+ __forceinline Vec3fa mini(const Vec3fa& a, const Vec3fa& b) {
+ const vint4 ai = _mm_castps_si128(a.m128);
+ const vint4 bi = _mm_castps_si128(b.m128);
+ const vint4 ci = _mm_min_epi32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+#endif
+
+#if defined(__SSE4_1__)
+ __forceinline Vec3fa maxi(const Vec3fa& a, const Vec3fa& b) {
+ const vint4 ai = _mm_castps_si128(a.m128);
+ const vint4 bi = _mm_castps_si128(b.m128);
+ const vint4 ci = _mm_max_epi32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+#endif
+
+ __forceinline Vec3fa pow ( const Vec3fa& a, const float& b ) {
+ return Vec3fa(powf(a.x,b),powf(a.y,b),powf(a.z,b));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX2__)
+ __forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fmadd_ps(a.m128,b.m128,c.m128); }
+ __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fmsub_ps(a.m128,b.m128,c.m128); }
+ __forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fnmadd_ps(a.m128,b.m128,c.m128); }
+ __forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fnmsub_ps(a.m128,b.m128,c.m128); }
+#else
+ __forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b+c; }
+ __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b-c; }
+ __forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b+c;}
+ __forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b-c; }
+#endif
+
+ __forceinline Vec3fa madd ( const float a, const Vec3fa& b, const Vec3fa& c) { return madd(Vec3fa(a),b,c); }
+ __forceinline Vec3fa msub ( const float a, const Vec3fa& b, const Vec3fa& c) { return msub(Vec3fa(a),b,c); }
+ __forceinline Vec3fa nmadd ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmadd(Vec3fa(a),b,c); }
+ __forceinline Vec3fa nmsub ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmsub(Vec3fa(a),b,c); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fa& operator +=( Vec3fa& a, const Vec3fa& b ) { return a = a + b; }
+ __forceinline Vec3fa& operator -=( Vec3fa& a, const Vec3fa& b ) { return a = a - b; }
+ __forceinline Vec3fa& operator *=( Vec3fa& a, const Vec3fa& b ) { return a = a * b; }
+ __forceinline Vec3fa& operator *=( Vec3fa& a, const float b ) { return a = a * b; }
+ __forceinline Vec3fa& operator /=( Vec3fa& a, const Vec3fa& b ) { return a = a / b; }
+ __forceinline Vec3fa& operator /=( Vec3fa& a, const float b ) { return a = a / b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline float reduce_add(const Vec3fa& v) {
+ const vfloat4 a(v.m128);
+ const vfloat4 b = shuffle<1>(a);
+ const vfloat4 c = shuffle<2>(a);
+ return _mm_cvtss_f32(a+b+c);
+ }
+
+ __forceinline float reduce_mul(const Vec3fa& v) { return v.x*v.y*v.z; }
+ __forceinline float reduce_min(const Vec3fa& v) { return min(v.x,v.y,v.z); }
+ __forceinline float reduce_max(const Vec3fa& v) { return max(v.x,v.y,v.z); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator ==( const Vec3fa& a, const Vec3fa& b ) { return (_mm_movemask_ps(_mm_cmpeq_ps (a.m128, b.m128)) & 7) == 7; }
+ __forceinline bool operator !=( const Vec3fa& a, const Vec3fa& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 7) != 0; }
+
+ __forceinline Vec3ba eq_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpeq_ps (a.m128, b.m128); }
+ __forceinline Vec3ba neq_mask(const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpneq_ps(a.m128, b.m128); }
+ __forceinline Vec3ba lt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmplt_ps (a.m128, b.m128); }
+ __forceinline Vec3ba le_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmple_ps (a.m128, b.m128); }
+ __forceinline Vec3ba gt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpnle_ps(a.m128, b.m128); }
+ __forceinline Vec3ba ge_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); }
+
+ __forceinline bool isvalid ( const Vec3fa& v ) {
+ return all(gt_mask(v,Vec3fa(-FLT_LARGE)) & lt_mask(v,Vec3fa(+FLT_LARGE)));
+ }
+
+ __forceinline bool is_finite ( const Vec3fa& a ) {
+ return all(ge_mask(a,Vec3fa(-FLT_MAX)) & le_mask(a,Vec3fa(+FLT_MAX)));
+ }
+
+ __forceinline bool isvalid4 ( const Vec3fa& v ) {
+ return all((vfloat4(v.m128) > vfloat4(-FLT_LARGE)) & (vfloat4(v.m128) < vfloat4(+FLT_LARGE)));
+ }
+
+ __forceinline bool is_finite4 ( const Vec3fa& a ) {
+ return all((vfloat4(a.m128) >= vfloat4(-FLT_MAX)) & (vfloat4(a.m128) <= vfloat4(+FLT_MAX)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Euclidian Space Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__SSE4_1__)
+ __forceinline float dot ( const Vec3fa& a, const Vec3fa& b ) {
+ return _mm_cvtss_f32(_mm_dp_ps(a.m128,b.m128,0x7F));
+ }
+#else
+ __forceinline float dot ( const Vec3fa& a, const Vec3fa& b ) {
+ return reduce_add(a*b);
+ }
+#endif
+
+ __forceinline Vec3fa cross ( const Vec3fa& a, const Vec3fa& b )
+ {
+ vfloat4 a0 = vfloat4(a.m128);
+ vfloat4 b0 = shuffle<1,2,0,3>(vfloat4(b.m128));
+ vfloat4 a1 = shuffle<1,2,0,3>(vfloat4(a.m128));
+ vfloat4 b1 = vfloat4(b.m128);
+ return Vec3fa(shuffle<1,2,0,3>(msub(a0,b0,a1*b1)));
+ }
+
+ __forceinline float sqr_length ( const Vec3fa& a ) { return dot(a,a); }
+ __forceinline float rcp_length ( const Vec3fa& a ) { return rsqrt(dot(a,a)); }
+ __forceinline float rcp_length2( const Vec3fa& a ) { return rcp(dot(a,a)); }
+ __forceinline float length ( const Vec3fa& a ) { return sqrt(dot(a,a)); }
+ __forceinline Vec3fa normalize( const Vec3fa& a ) { return a*rsqrt(dot(a,a)); }
+ __forceinline float distance ( const Vec3fa& a, const Vec3fa& b ) { return length(a-b); }
+ __forceinline float halfArea ( const Vec3fa& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
+ __forceinline float area ( const Vec3fa& d ) { return 2.0f*halfArea(d); }
+
+ __forceinline Vec3fa normalize_safe( const Vec3fa& a ) {
+ const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
+ }
+
+ /*! differentiated normalization */
+ __forceinline Vec3fa dnormalize(const Vec3fa& p, const Vec3fa& dp)
+ {
+ const float pp = dot(p,p);
+ const float pdp = dot(p,dp);
+ return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fa select( bool s, const Vec3fa& t, const Vec3fa& f ) {
+ __m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
+ return blendv_ps(f.m128, t.m128, mask);
+ }
+
+ __forceinline Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
+ return blendv_ps(f.m128, t.m128, s);
+ }
+
+ __forceinline Vec3fa lerp(const Vec3fa& v0, const Vec3fa& v1, const float t) {
+ return madd(1.0f-t,v0,t*v1);
+ }
+
+ __forceinline int maxDim ( const Vec3fa& a )
+ {
+ const Vec3fa b = abs(a);
+ if (b.x > b.y) {
+ if (b.x > b.z) return 0; else return 2;
+ } else {
+ if (b.y > b.z) return 1; else return 2;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Rounding Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined (__SSE4_1__)
+ __forceinline Vec3fa trunc( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEAREST_INT); }
+ __forceinline Vec3fa floor( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEG_INF ); }
+ __forceinline Vec3fa ceil ( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_POS_INF ); }
+#else
+ __forceinline Vec3fa trunc( const Vec3fa& a ) { return Vec3fa(truncf(a.x),truncf(a.y),truncf(a.z)); }
+ __forceinline Vec3fa floor( const Vec3fa& a ) { return Vec3fa(floorf(a.x),floorf(a.y),floorf(a.z)); }
+ __forceinline Vec3fa ceil ( const Vec3fa& a ) { return Vec3fa(ceilf (a.x),ceilf (a.y),ceilf (a.z)); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3fa& a) {
+ return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
+ }
+
+ typedef Vec3fa Vec3fa_t;
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// SSE Vec3fx Type
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct __aligned(16) Vec3fx
+ {
+ ALIGNED_STRUCT_(16);
+
+ typedef float Scalar;
+ enum { N = 3 };
+ union {
+ __m128 m128;
+ struct { float x,y,z; union { int a; unsigned u; float w; }; };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fx( ) {}
+ __forceinline Vec3fx( const __m128 a ) : m128(a) {}
+
+ __forceinline explicit Vec3fx(const Vec3fa& v) : m128(v.m128) {}
+ __forceinline operator Vec3fa () const { return Vec3fa(m128); }
+
+ __forceinline explicit Vec3fx ( const Vec3<float>& other ) { m128 = _mm_set_ps(0, other.z, other.y, other.x); }
+ //__forceinline Vec3fx& operator =( const Vec3<float>& other ) { m128 = _mm_set_ps(0, other.z, other.y, other.x); return *this; }
+
+ __forceinline Vec3fx ( const Vec3fx& other ) { m128 = other.m128; }
+
+ __forceinline Vec3fx& operator =( const Vec3fx& other ) { m128 = other.m128; return *this; }
+
+ __forceinline explicit Vec3fx( const float a ) : m128(_mm_set1_ps(a)) {}
+ __forceinline Vec3fx( const float x, const float y, const float z) : m128(_mm_set_ps(0, z, y, x)) {}
+
+ __forceinline Vec3fx( const Vec3fa& other, const int a1) { m128 = other.m128; a = a1; }
+ __forceinline Vec3fx( const Vec3fa& other, const unsigned a1) { m128 = other.m128; u = a1; }
+ __forceinline Vec3fx( const Vec3fa& other, const float w1) {
+#if defined (__SSE4_1__)
+ m128 = _mm_insert_ps(other.m128, _mm_set_ss(w1),3 << 4);
+#else
+ const vint4 mask(-1,-1,-1,0);
+ m128 = select(vboolf4(_mm_castsi128_ps(mask)),vfloat4(other.m128),vfloat4(w1));
+#endif
+ }
+ //__forceinline Vec3fx( const float x, const float y, const float z, const int a) : x(x), y(y), z(z), a(a) {} // not working properly!
+ //__forceinline Vec3fx( const float x, const float y, const float z, const unsigned a) : x(x), y(y), z(z), u(a) {} // not working properly!
+ __forceinline Vec3fx( const float x, const float y, const float z, const float w) : m128(_mm_set_ps(w, z, y, x)) {}
+
+ //__forceinline explicit Vec3fx( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
+
+ __forceinline explicit operator const vfloat4() const { return vfloat4(m128); }
+ __forceinline explicit operator const vint4() const { return vint4(_mm_cvtps_epi32(m128)); }
+ __forceinline explicit operator const Vec2fa() const { return Vec2fa(m128); }
+ __forceinline explicit operator const Vec3ia() const { return Vec3ia(_mm_cvtps_epi32(m128)); }
+
+ //__forceinline operator const __m128&() const { return m128; }
+ //__forceinline operator __m128&() { return m128; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline Vec3fx load( const void* const a ) {
+ return Vec3fx(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
+ }
+
+ static __forceinline Vec3fx loadu( const void* const a ) {
+ return Vec3fx(_mm_loadu_ps((float*)a));
+ }
+
+ static __forceinline void storeu ( void* ptr, const Vec3fx& v ) {
+ _mm_storeu_ps((float*)ptr,v.m128);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fx( ZeroTy ) : m128(_mm_setzero_ps()) {}
+ __forceinline Vec3fx( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
+ __forceinline Vec3fx( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
+ __forceinline Vec3fx( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const float& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
+ __forceinline float& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fx operator +( const Vec3fx& a ) { return a; }
+ __forceinline Vec3fx operator -( const Vec3fx& a ) {
+ const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
+ return _mm_xor_ps(a.m128, mask);
+ }
+ __forceinline Vec3fx abs ( const Vec3fx& a ) {
+ const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
+ return _mm_and_ps(a.m128, mask);
+ }
+ __forceinline Vec3fx sign ( const Vec3fx& a ) {
+ return blendv_ps(Vec3fx(one).m128, (-Vec3fx(one)).m128, _mm_cmplt_ps (a.m128,Vec3fx(zero).m128));
+ }
+
+ __forceinline Vec3fx rcp ( const Vec3fx& a )
+ {
+#if defined(__AVX512VL__)
+ const Vec3fx r = _mm_rcp14_ps(a.m128);
+#else
+ const Vec3fx r = _mm_rcp_ps(a.m128);
+#endif
+
+#if defined(__AVX2__)
+ const Vec3fx res = _mm_mul_ps(r.m128,_mm_fnmadd_ps(r.m128, a.m128, vfloat4(2.0f)));
+#else
+ const Vec3fx res = _mm_mul_ps(r.m128,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r.m128, a.m128)));
+ //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+#endif
+
+ return res;
+ }
+
+ __forceinline Vec3fx sqrt ( const Vec3fx& a ) { return _mm_sqrt_ps(a.m128); }
+ __forceinline Vec3fx sqr ( const Vec3fx& a ) { return _mm_mul_ps(a.m128,a.m128); }
+
+ __forceinline Vec3fx rsqrt( const Vec3fx& a )
+ {
+#if defined(__AVX512VL__)
+ __m128 r = _mm_rsqrt14_ps(a.m128);
+#else
+ __m128 r = _mm_rsqrt_ps(a.m128);
+#endif
+ return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a.m128, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+ }
+
+ __forceinline Vec3fx zero_fix(const Vec3fx& a) {
+ return blendv_ps(a.m128, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
+ }
+ __forceinline Vec3fx rcp_safe(const Vec3fx& a) {
+ return rcp(zero_fix(a));
+ }
+ __forceinline Vec3fx log ( const Vec3fx& a ) {
+ return Vec3fx(logf(a.x),logf(a.y),logf(a.z));
+ }
+
+ __forceinline Vec3fx exp ( const Vec3fx& a ) {
+ return Vec3fx(expf(a.x),expf(a.y),expf(a.z));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fx operator +( const Vec3fx& a, const Vec3fx& b ) { return _mm_add_ps(a.m128, b.m128); }
+ __forceinline Vec3fx operator -( const Vec3fx& a, const Vec3fx& b ) { return _mm_sub_ps(a.m128, b.m128); }
+ __forceinline Vec3fx operator *( const Vec3fx& a, const Vec3fx& b ) { return _mm_mul_ps(a.m128, b.m128); }
+ __forceinline Vec3fx operator *( const Vec3fx& a, const float b ) { return a * Vec3fx(b); }
+ __forceinline Vec3fx operator *( const float a, const Vec3fx& b ) { return Vec3fx(a) * b; }
+ __forceinline Vec3fx operator /( const Vec3fx& a, const Vec3fx& b ) { return _mm_div_ps(a.m128,b.m128); }
+ __forceinline Vec3fx operator /( const Vec3fx& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
+ __forceinline Vec3fx operator /( const float a, const Vec3fx& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
+
+ __forceinline Vec3fx min( const Vec3fx& a, const Vec3fx& b ) { return _mm_min_ps(a.m128,b.m128); }
+ __forceinline Vec3fx max( const Vec3fx& a, const Vec3fx& b ) { return _mm_max_ps(a.m128,b.m128); }
+
+#if defined(__SSE4_1__)
+ __forceinline Vec3fx mini(const Vec3fx& a, const Vec3fx& b) {
+ const vint4 ai = _mm_castps_si128(a.m128);
+ const vint4 bi = _mm_castps_si128(b.m128);
+ const vint4 ci = _mm_min_epi32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+#endif
+
+#if defined(__SSE4_1__)
+ __forceinline Vec3fx maxi(const Vec3fx& a, const Vec3fx& b) {
+ const vint4 ai = _mm_castps_si128(a.m128);
+ const vint4 bi = _mm_castps_si128(b.m128);
+ const vint4 ci = _mm_max_epi32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+#endif
+
+ __forceinline Vec3fx pow ( const Vec3fx& a, const float& b ) {
+ return Vec3fx(powf(a.x,b),powf(a.y,b),powf(a.z,b));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX2__)
+ __forceinline Vec3fx madd ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return _mm_fmadd_ps(a.m128,b.m128,c.m128); }
+ __forceinline Vec3fx msub ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return _mm_fmsub_ps(a.m128,b.m128,c.m128); }
+ __forceinline Vec3fx nmadd ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return _mm_fnmadd_ps(a.m128,b.m128,c.m128); }
+ __forceinline Vec3fx nmsub ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return _mm_fnmsub_ps(a.m128,b.m128,c.m128); }
+#else
+ __forceinline Vec3fx madd ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return a*b+c; }
+ __forceinline Vec3fx msub ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return a*b-c; }
+ __forceinline Vec3fx nmadd ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return -a*b+c;}
+ __forceinline Vec3fx nmsub ( const Vec3fx& a, const Vec3fx& b, const Vec3fx& c) { return -a*b-c; }
+#endif
+
+ __forceinline Vec3fx madd ( const float a, const Vec3fx& b, const Vec3fx& c) { return madd(Vec3fx(a),b,c); }
+ __forceinline Vec3fx msub ( const float a, const Vec3fx& b, const Vec3fx& c) { return msub(Vec3fx(a),b,c); }
+ __forceinline Vec3fx nmadd ( const float a, const Vec3fx& b, const Vec3fx& c) { return nmadd(Vec3fx(a),b,c); }
+ __forceinline Vec3fx nmsub ( const float a, const Vec3fx& b, const Vec3fx& c) { return nmsub(Vec3fx(a),b,c); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fx& operator +=( Vec3fx& a, const Vec3fx& b ) { return a = a + b; }
+ __forceinline Vec3fx& operator -=( Vec3fx& a, const Vec3fx& b ) { return a = a - b; }
+ __forceinline Vec3fx& operator *=( Vec3fx& a, const Vec3fx& b ) { return a = a * b; }
+ __forceinline Vec3fx& operator *=( Vec3fx& a, const float b ) { return a = a * b; }
+ __forceinline Vec3fx& operator /=( Vec3fx& a, const Vec3fx& b ) { return a = a / b; }
+ __forceinline Vec3fx& operator /=( Vec3fx& a, const float b ) { return a = a / b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline float reduce_add(const Vec3fx& v) {
+ const vfloat4 a(v.m128);
+ const vfloat4 b = shuffle<1>(a);
+ const vfloat4 c = shuffle<2>(a);
+ return _mm_cvtss_f32(a+b+c);
+ }
+
+ __forceinline float reduce_mul(const Vec3fx& v) { return v.x*v.y*v.z; }
+ __forceinline float reduce_min(const Vec3fx& v) { return min(v.x,v.y,v.z); }
+ __forceinline float reduce_max(const Vec3fx& v) { return max(v.x,v.y,v.z); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator ==( const Vec3fx& a, const Vec3fx& b ) { return (_mm_movemask_ps(_mm_cmpeq_ps (a.m128, b.m128)) & 7) == 7; }
+ __forceinline bool operator !=( const Vec3fx& a, const Vec3fx& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 7) != 0; }
+
+ __forceinline Vec3ba eq_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmpeq_ps (a.m128, b.m128); }
+ __forceinline Vec3ba neq_mask(const Vec3fx& a, const Vec3fx& b ) { return _mm_cmpneq_ps(a.m128, b.m128); }
+ __forceinline Vec3ba lt_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmplt_ps (a.m128, b.m128); }
+ __forceinline Vec3ba le_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmple_ps (a.m128, b.m128); }
+ __forceinline Vec3ba gt_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmpnle_ps(a.m128, b.m128); }
+ __forceinline Vec3ba ge_mask( const Vec3fx& a, const Vec3fx& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); }
+
+ __forceinline bool isvalid ( const Vec3fx& v ) {
+ return all(gt_mask(v,Vec3fx(-FLT_LARGE)) & lt_mask(v,Vec3fx(+FLT_LARGE)));
+ }
+
+ __forceinline bool is_finite ( const Vec3fx& a ) {
+ return all(ge_mask(a,Vec3fx(-FLT_MAX)) & le_mask(a,Vec3fx(+FLT_MAX)));
+ }
+
+ __forceinline bool isvalid4 ( const Vec3fx& v ) {
+ return all((vfloat4(v.m128) > vfloat4(-FLT_LARGE)) & (vfloat4(v.m128) < vfloat4(+FLT_LARGE)));
+ }
+
+ __forceinline bool is_finite4 ( const Vec3fx& a ) {
+ return all((vfloat4(a.m128) >= vfloat4(-FLT_MAX)) & (vfloat4(a.m128) <= vfloat4(+FLT_MAX)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Euclidian Space Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__SSE4_1__)
+ __forceinline float dot ( const Vec3fx& a, const Vec3fx& b ) {
+ return _mm_cvtss_f32(_mm_dp_ps(a.m128,b.m128,0x7F));
+ }
+#else
+ __forceinline float dot ( const Vec3fx& a, const Vec3fx& b ) {
+ return reduce_add(a*b);
+ }
+#endif
+
+ __forceinline Vec3fx cross ( const Vec3fx& a, const Vec3fx& b )
+ {
+ vfloat4 a0 = vfloat4(a.m128);
+ vfloat4 b0 = shuffle<1,2,0,3>(vfloat4(b.m128));
+ vfloat4 a1 = shuffle<1,2,0,3>(vfloat4(a.m128));
+ vfloat4 b1 = vfloat4(b.m128);
+ return Vec3fx(shuffle<1,2,0,3>(msub(a0,b0,a1*b1)));
+ }
+
+ __forceinline float sqr_length ( const Vec3fx& a ) { return dot(a,a); }
+ __forceinline float rcp_length ( const Vec3fx& a ) { return rsqrt(dot(a,a)); }
+ __forceinline float rcp_length2( const Vec3fx& a ) { return rcp(dot(a,a)); }
+ __forceinline float length ( const Vec3fx& a ) { return sqrt(dot(a,a)); }
+ __forceinline Vec3fx normalize( const Vec3fx& a ) { return a*rsqrt(dot(a,a)); }
+ __forceinline float distance ( const Vec3fx& a, const Vec3fx& b ) { return length(a-b); }
+ __forceinline float halfArea ( const Vec3fx& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
+ __forceinline float area ( const Vec3fx& d ) { return 2.0f*halfArea(d); }
+
+ __forceinline Vec3fx normalize_safe( const Vec3fx& a ) {
+ const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
+ }
+
+ /*! differentiated normalization */
+ __forceinline Vec3fx dnormalize(const Vec3fx& p, const Vec3fx& dp)
+ {
+ const float pp = dot(p,p);
+ const float pdp = dot(p,dp);
+ return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3fx select( bool s, const Vec3fx& t, const Vec3fx& f ) {
+ __m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
+ return blendv_ps(f.m128, t.m128, mask);
+ }
+
+ __forceinline Vec3fx select( const Vec3ba& s, const Vec3fx& t, const Vec3fx& f ) {
+ return blendv_ps(f.m128, t.m128, s);
+ }
+
+ __forceinline Vec3fx lerp(const Vec3fx& v0, const Vec3fx& v1, const float t) {
+ return madd(1.0f-t,v0,t*v1);
+ }
+
+ __forceinline int maxDim ( const Vec3fx& a )
+ {
+ const Vec3fx b = abs(a);
+ if (b.x > b.y) {
+ if (b.x > b.z) return 0; else return 2;
+ } else {
+ if (b.y > b.z) return 1; else return 2;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Rounding Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__aarch64__)
+ __forceinline Vec3fx trunc(const Vec3fx& a) { return vrndq_f32(a.m128); }
+ __forceinline Vec3fx floor(const Vec3fx& a) { return vrndmq_f32(a.m128); }
+ __forceinline Vec3fx ceil (const Vec3fx& a) { return vrndpq_f32(a.m128); }
+#elif defined (__SSE4_1__)
+ __forceinline Vec3fx trunc( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEAREST_INT); }
+ __forceinline Vec3fx floor( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEG_INF ); }
+ __forceinline Vec3fx ceil ( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_POS_INF ); }
+#else
+ __forceinline Vec3fx trunc( const Vec3fx& a ) { return Vec3fx(truncf(a.x),truncf(a.y),truncf(a.z)); }
+ __forceinline Vec3fx floor( const Vec3fx& a ) { return Vec3fx(floorf(a.x),floorf(a.y),floorf(a.z)); }
+ __forceinline Vec3fx ceil ( const Vec3fx& a ) { return Vec3fx(ceilf (a.x),ceilf (a.y),ceilf (a.z)); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3fx& a) {
+ return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
+ }
+
+
+ typedef Vec3fx Vec3ff;
+}
diff --git a/thirdparty/embree/common/math/vec3ia.h b/thirdparty/embree/common/math/vec3ia.h
new file mode 100644
index 0000000000..694804c40d
--- /dev/null
+++ b/thirdparty/embree/common/math/vec3ia.h
@@ -0,0 +1,186 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/alloc.h"
+#include "math.h"
+#include "../simd/sse.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// SSE Vec3ia Type
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct __aligned(16) Vec3ia
+ {
+ ALIGNED_STRUCT_(16);
+
+ union {
+ __m128i m128;
+ struct { int x,y,z; };
+ };
+
+ typedef int Scalar;
+ enum { N = 3 };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ia( ) {}
+ __forceinline Vec3ia( const __m128i a ) : m128(a) {}
+ __forceinline Vec3ia( const Vec3ia& other ) : m128(other.m128) {}
+ __forceinline Vec3ia& operator =(const Vec3ia& other) { m128 = other.m128; return *this; }
+
+ __forceinline explicit Vec3ia( const int a ) : m128(_mm_set1_epi32(a)) {}
+ __forceinline Vec3ia( const int x, const int y, const int z) : m128(_mm_set_epi32(z, z, y, x)) {}
+ __forceinline explicit Vec3ia( const __m128 a ) : m128(_mm_cvtps_epi32(a)) {}
+
+ __forceinline operator const __m128i&() const { return m128; }
+ __forceinline operator __m128i&() { return m128; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ia( ZeroTy ) : m128(_mm_setzero_si128()) {}
+ __forceinline Vec3ia( OneTy ) : m128(_mm_set1_epi32(1)) {}
+ __forceinline Vec3ia( PosInfTy ) : m128(_mm_set1_epi32(pos_inf)) {}
+ __forceinline Vec3ia( NegInfTy ) : m128(_mm_set1_epi32(neg_inf)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const int& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
+ __forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ia operator +( const Vec3ia& a ) { return a; }
+ __forceinline Vec3ia operator -( const Vec3ia& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
+#if defined(__SSSE3__)
+ __forceinline Vec3ia abs ( const Vec3ia& a ) { return _mm_abs_epi32(a.m128); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ia operator +( const Vec3ia& a, const Vec3ia& b ) { return _mm_add_epi32(a.m128, b.m128); }
+ __forceinline Vec3ia operator +( const Vec3ia& a, const int b ) { return a+Vec3ia(b); }
+ __forceinline Vec3ia operator +( const int a, const Vec3ia& b ) { return Vec3ia(a)+b; }
+
+ __forceinline Vec3ia operator -( const Vec3ia& a, const Vec3ia& b ) { return _mm_sub_epi32(a.m128, b.m128); }
+ __forceinline Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); }
+ __forceinline Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; }
+
+#if defined(__SSE4_1__)
+ __forceinline Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
+ __forceinline Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); }
+ __forceinline Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; }
+#endif
+
+ __forceinline Vec3ia operator &( const Vec3ia& a, const Vec3ia& b ) { return _mm_and_si128(a.m128, b.m128); }
+ __forceinline Vec3ia operator &( const Vec3ia& a, const int b ) { return a & Vec3ia(b); }
+ __forceinline Vec3ia operator &( const int a, const Vec3ia& b ) { return Vec3ia(a) & b; }
+
+ __forceinline Vec3ia operator |( const Vec3ia& a, const Vec3ia& b ) { return _mm_or_si128(a.m128, b.m128); }
+ __forceinline Vec3ia operator |( const Vec3ia& a, const int b ) { return a | Vec3ia(b); }
+ __forceinline Vec3ia operator |( const int a, const Vec3ia& b ) { return Vec3ia(a) | b; }
+
+ __forceinline Vec3ia operator ^( const Vec3ia& a, const Vec3ia& b ) { return _mm_xor_si128(a.m128, b.m128); }
+ __forceinline Vec3ia operator ^( const Vec3ia& a, const int b ) { return a ^ Vec3ia(b); }
+ __forceinline Vec3ia operator ^( const int a, const Vec3ia& b ) { return Vec3ia(a) ^ b; }
+
+ __forceinline Vec3ia operator <<( const Vec3ia& a, const int n ) { return _mm_slli_epi32(a.m128, n); }
+ __forceinline Vec3ia operator >>( const Vec3ia& a, const int n ) { return _mm_srai_epi32(a.m128, n); }
+
+ __forceinline Vec3ia sll ( const Vec3ia& a, const int b ) { return _mm_slli_epi32(a.m128, b); }
+ __forceinline Vec3ia sra ( const Vec3ia& a, const int b ) { return _mm_srai_epi32(a.m128, b); }
+ __forceinline Vec3ia srl ( const Vec3ia& a, const int b ) { return _mm_srli_epi32(a.m128, b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ia& operator +=( Vec3ia& a, const Vec3ia& b ) { return a = a + b; }
+ __forceinline Vec3ia& operator +=( Vec3ia& a, const int& b ) { return a = a + b; }
+
+ __forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia& b ) { return a = a - b; }
+ __forceinline Vec3ia& operator -=( Vec3ia& a, const int& b ) { return a = a - b; }
+
+#if defined(__SSE4_1__)
+ __forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia& b ) { return a = a * b; }
+ __forceinline Vec3ia& operator *=( Vec3ia& a, const int& b ) { return a = a * b; }
+#endif
+
+ __forceinline Vec3ia& operator &=( Vec3ia& a, const Vec3ia& b ) { return a = a & b; }
+ __forceinline Vec3ia& operator &=( Vec3ia& a, const int& b ) { return a = a & b; }
+
+ __forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia& b ) { return a = a | b; }
+ __forceinline Vec3ia& operator |=( Vec3ia& a, const int& b ) { return a = a | b; }
+
+ __forceinline Vec3ia& operator <<=( Vec3ia& a, const int& b ) { return a = a << b; }
+ __forceinline Vec3ia& operator >>=( Vec3ia& a, const int& b ) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline int reduce_add(const Vec3ia& v) { return v.x+v.y+v.z; }
+ __forceinline int reduce_mul(const Vec3ia& v) { return v.x*v.y*v.z; }
+ __forceinline int reduce_min(const Vec3ia& v) { return min(v.x,v.y,v.z); }
+ __forceinline int reduce_max(const Vec3ia& v) { return max(v.x,v.y,v.z); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator ==( const Vec3ia& a, const Vec3ia& b ) { return (_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(a.m128, b.m128))) & 7) == 7; }
+ __forceinline bool operator !=( const Vec3ia& a, const Vec3ia& b ) { return (_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(a.m128, b.m128))) & 7) != 7; }
+ __forceinline bool operator < ( const Vec3ia& a, const Vec3ia& b ) {
+ if (a.x != b.x) return a.x < b.x;
+ if (a.y != b.y) return a.y < b.y;
+ if (a.z != b.z) return a.z < b.z;
+ return false;
+ }
+
+ __forceinline Vec3ba eq_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32 (a.m128, b.m128)); }
+ __forceinline Vec3ba lt_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmplt_epi32 (a.m128, b.m128)); }
+ __forceinline Vec3ba gt_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmpgt_epi32 (a.m128, b.m128)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
+#if defined(__SSE4_1__)
+ return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
+#else
+ return _mm_or_si128(_mm_and_si128(_mm_castps_si128(m), t), _mm_andnot_si128(_mm_castps_si128(m), f));
+#endif
+ }
+
+#if defined(__SSE4_1__)
+ __forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return _mm_min_epi32(a.m128,b.m128); }
+ __forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return _mm_max_epi32(a.m128,b.m128); }
+#else
+ __forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return select(lt_mask(a,b),a,b); }
+ __forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return select(gt_mask(a,b),a,b); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3ia& a) {
+ return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
+ }
+}
diff --git a/thirdparty/embree/common/math/vec4.h b/thirdparty/embree/common/math/vec4.h
new file mode 100644
index 0000000000..0ed107928a
--- /dev/null
+++ b/thirdparty/embree/common/math/vec4.h
@@ -0,0 +1,243 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "math.h"
+#include "vec3.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Generic 4D vector Class
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> struct Vec4
+ {
+ enum { N = 4 };
+ union {
+ struct { T x, y, z, w; };
+#if !(defined(__WIN32__) && _MSC_VER == 1800) // workaround for older VS 2013 compiler
+ T components[N];
+#endif
+ };
+
+ typedef T Scalar;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Construction
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec4( ) {}
+ __forceinline explicit Vec4( const T& a ) : x(a), y(a), z(a), w(a) {}
+ __forceinline Vec4( const T& x, const T& y, const T& z, const T& w ) : x(x), y(y), z(z), w(w) {}
+ __forceinline Vec4( const Vec3<T>& xyz, const T& w ) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
+
+ __forceinline Vec4( const Vec4& other ) { x = other.x; y = other.y; z = other.z; w = other.w; }
+ __forceinline Vec4( const Vec3fx& other );
+
+ template<typename T1> __forceinline Vec4( const Vec4<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)), w(T(a.w)) {}
+ template<typename T1> __forceinline Vec4& operator =(const Vec4<T1>& other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; }
+
+ __forceinline Vec4& operator =(const Vec4& other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; }
+
+ __forceinline operator Vec3<T> () const { return Vec3<T>(x,y,z); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec4( ZeroTy ) : x(zero), y(zero), z(zero), w(zero) {}
+ __forceinline Vec4( OneTy ) : x(one), y(one), z(one), w(one) {}
+ __forceinline Vec4( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf), w(pos_inf) {}
+ __forceinline Vec4( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf), w(neg_inf) {}
+
+#if defined(__WIN32__) && (_MSC_VER == 1800) // workaround for older VS 2013 compiler
+ __forceinline const T& operator [](const size_t axis) const { assert(axis < 4); return (&x)[axis]; }
+ __forceinline T& operator [](const size_t axis) { assert(axis < 4); return (&x)[axis]; }
+#else
+ __forceinline const T& operator [](const size_t axis ) const { assert(axis < 4); return components[axis]; }
+ __forceinline T& operator [](const size_t axis) { assert(axis < 4); return components[axis]; }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Swizzles
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Vec3<T> xyz() const { return Vec3<T>(x, y, z); }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec4<T> operator +( const Vec4<T>& a ) { return Vec4<T>(+a.x, +a.y, +a.z, +a.w); }
+ template<typename T> __forceinline Vec4<T> operator -( const Vec4<T>& a ) { return Vec4<T>(-a.x, -a.y, -a.z, -a.w); }
+ template<typename T> __forceinline Vec4<T> abs ( const Vec4<T>& a ) { return Vec4<T>(abs (a.x), abs (a.y), abs (a.z), abs (a.w)); }
+ template<typename T> __forceinline Vec4<T> rcp ( const Vec4<T>& a ) { return Vec4<T>(rcp (a.x), rcp (a.y), rcp (a.z), rcp (a.w)); }
+ template<typename T> __forceinline Vec4<T> rsqrt ( const Vec4<T>& a ) { return Vec4<T>(rsqrt(a.x), rsqrt(a.y), rsqrt(a.z), rsqrt(a.w)); }
+ template<typename T> __forceinline Vec4<T> sqrt ( const Vec4<T>& a ) { return Vec4<T>(sqrt (a.x), sqrt (a.y), sqrt (a.z), sqrt (a.w)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec4<T> operator +( const Vec4<T>& a, const Vec4<T>& b ) { return Vec4<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); }
+ template<typename T> __forceinline Vec4<T> operator -( const Vec4<T>& a, const Vec4<T>& b ) { return Vec4<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); }
+ template<typename T> __forceinline Vec4<T> operator *( const Vec4<T>& a, const Vec4<T>& b ) { return Vec4<T>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); }
+ template<typename T> __forceinline Vec4<T> operator *( const T& a, const Vec4<T>& b ) { return Vec4<T>(a * b.x, a * b.y, a * b.z, a * b.w); }
+ template<typename T> __forceinline Vec4<T> operator *( const Vec4<T>& a, const T& b ) { return Vec4<T>(a.x * b , a.y * b , a.z * b , a.w * b ); }
+ template<typename T> __forceinline Vec4<T> operator /( const Vec4<T>& a, const Vec4<T>& b ) { return Vec4<T>(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); }
+ template<typename T> __forceinline Vec4<T> operator /( const Vec4<T>& a, const T& b ) { return Vec4<T>(a.x / b , a.y / b , a.z / b , a.w / b ); }
+ template<typename T> __forceinline Vec4<T> operator /( const T& a, const Vec4<T>& b ) { return Vec4<T>(a / b.x, a / b.y, a / b.z, a / b.w); }
+
+ template<typename T> __forceinline Vec4<T> min(const Vec4<T>& a, const Vec4<T>& b) { return Vec4<T>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w)); }
+ template<typename T> __forceinline Vec4<T> max(const Vec4<T>& a, const Vec4<T>& b) { return Vec4<T>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec4<T> madd ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z), madd(a.w,b.w,c.w)); }
+ template<typename T> __forceinline Vec4<T> msub ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z), msub(a.w,b.w,c.w)); }
+ template<typename T> __forceinline Vec4<T> nmadd ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z),nmadd(a.w,b.w,c.w)); }
+ template<typename T> __forceinline Vec4<T> nmsub ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z),nmsub(a.w,b.w,c.w)); }
+
+ template<typename T> __forceinline Vec4<T> madd ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z), madd(a,b.w,c.w)); }
+ template<typename T> __forceinline Vec4<T> msub ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z), msub(a,b.w,c.w)); }
+ template<typename T> __forceinline Vec4<T> nmadd ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z),nmadd(a,b.w,c.w)); }
+ template<typename T> __forceinline Vec4<T> nmsub ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z),nmsub(a,b.w,c.w)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec4<T>& operator +=( Vec4<T>& a, const Vec4<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w; return a; }
+ template<typename T> __forceinline Vec4<T>& operator -=( Vec4<T>& a, const Vec4<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; a.w -= b.w; return a; }
+ template<typename T> __forceinline Vec4<T>& operator *=( Vec4<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; a.w *= b ; return a; }
+ template<typename T> __forceinline Vec4<T>& operator /=( Vec4<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; a.w /= b ; return a; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline T reduce_add( const Vec4<T>& a ) { return a.x + a.y + a.z + a.w; }
+ template<typename T> __forceinline T reduce_mul( const Vec4<T>& a ) { return a.x * a.y * a.z * a.w; }
+ template<typename T> __forceinline T reduce_min( const Vec4<T>& a ) { return min(a.x, a.y, a.z, a.w); }
+ template<typename T> __forceinline T reduce_max( const Vec4<T>& a ) { return max(a.x, a.y, a.z, a.w); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline bool operator ==( const Vec4<T>& a, const Vec4<T>& b ) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
+ template<typename T> __forceinline bool operator !=( const Vec4<T>& a, const Vec4<T>& b ) { return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w; }
+ template<typename T> __forceinline bool operator < ( const Vec4<T>& a, const Vec4<T>& b ) {
+ if (a.x != b.x) return a.x < b.x;
+ if (a.y != b.y) return a.y < b.y;
+ if (a.z != b.z) return a.z < b.z;
+ if (a.w != b.w) return a.w < b.w;
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Shift Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec4<T> shift_right_1( const Vec4<T>& a ) {
+ return Vec4<T>(shift_right_1(a.x),shift_right_1(a.y),shift_right_1(a.z),shift_right_1(a.w));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Euclidian Space Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline T dot ( const Vec4<T>& a, const Vec4<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,madd(a.z,b.z,a.w*b.w))); }
+
+ template<typename T> __forceinline T length ( const Vec4<T>& a ) { return sqrt(dot(a,a)); }
+ template<typename T> __forceinline Vec4<T> normalize( const Vec4<T>& a ) { return a*rsqrt(dot(a,a)); }
+ template<typename T> __forceinline T distance ( const Vec4<T>& a, const Vec4<T>& b ) { return length(a-b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline Vec4<T> select ( bool s, const Vec4<T>& t, const Vec4<T>& f ) {
+ return Vec4<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z),select(s,t.w,f.w));
+ }
+
+ template<typename T> __forceinline Vec4<T> select ( const Vec4<bool>& s, const Vec4<T>& t, const Vec4<T>& f ) {
+ return Vec4<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z),select(s.w,t.w,f.w));
+ }
+
+ template<typename T> __forceinline Vec4<T> select ( const typename T::Bool& s, const Vec4<T>& t, const Vec4<T>& f ) {
+ return Vec4<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z),select(s,t.w,f.w));
+ }
+
+ template<typename T>
+ __forceinline Vec4<T> lerp(const Vec4<T>& v0, const Vec4<T>& v1, const T& t) {
+ return madd(Vec4<T>(T(1.0f)-t),v0,t*v1);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Vec4<T>& a) {
+ return cout << "(" << a.x << ", " << a.y << ", " << a.z << ", " << a.w << ")";
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Default template instantiations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ typedef Vec4<bool > Vec4b;
+ typedef Vec4<unsigned char> Vec4uc;
+ typedef Vec4<int > Vec4i;
+ typedef Vec4<float > Vec4f;
+}
+
+#include "vec3ba.h"
+#include "vec3ia.h"
+#include "vec3fa.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/// SSE / AVX / MIC specializations
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined __SSE__
+#include "../simd/sse.h"
+#endif
+
+#if defined __AVX__
+#include "../simd/avx.h"
+#endif
+
+#if defined __AVX512F__
+#include "../simd/avx512.h"
+#endif
+
+namespace embree
+{
+ template<> __forceinline Vec4<float>::Vec4( const Vec3fx& a ) { x = a.x; y = a.y; z = a.z; w = a.w; }
+
+#if defined(__AVX__)
+ template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fx& a ) {
+ x = a.x; y = a.y; z = a.z; w = a.w;
+ }
+#elif defined(__SSE__)
+ template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fx& a ) {
+ const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); w = shuffle<3,3,3,3>(v);
+ }
+#endif
+
+#if defined(__AVX__)
+ template<> __forceinline Vec4<vfloat8>::Vec4( const Vec3fx& a ) {
+ x = a.x; y = a.y; z = a.z; w = a.w;
+ }
+#endif
+
+#if defined(__AVX512F__)
+ template<> __forceinline Vec4<vfloat16>::Vec4( const Vec3fx& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
+#endif
+}
diff --git a/thirdparty/embree/common/simd/arm/emulation.h b/thirdparty/embree/common/simd/arm/emulation.h
new file mode 100644
index 0000000000..1c3875fb27
--- /dev/null
+++ b/thirdparty/embree/common/simd/arm/emulation.h
@@ -0,0 +1,50 @@
+// Copyright 2009-2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+/* Make precision match SSE, at the cost of some performance */
+#if !defined(__aarch64__)
+# define SSE2NEON_PRECISE_DIV 1
+# define SSE2NEON_PRECISE_SQRT 1
+#endif
+
+#include "sse2neon.h"
+
+__forceinline __m128 _mm_fmsub_ps(__m128 a, __m128 b, __m128 c) {
+ __m128 neg_c = vreinterpretq_m128_f32(vnegq_f32(vreinterpretq_f32_m128(c)));
+ return _mm_fmadd_ps(a, b, neg_c);
+}
+
+__forceinline __m128 _mm_fnmadd_ps(__m128 a, __m128 b, __m128 c) {
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(vfmsq_f32(vreinterpretq_f32_m128(c),
+ vreinterpretq_f32_m128(b),
+ vreinterpretq_f32_m128(a)));
+#else
+ return _mm_sub_ps(c, _mm_mul_ps(a, b));
+#endif
+}
+
+__forceinline __m128 _mm_fnmsub_ps(__m128 a, __m128 b, __m128 c) {
+ return vreinterpretq_m128_f32(vnegq_f32(vreinterpretq_f32_m128(_mm_fmadd_ps(a,b,c))));
+}
+
+
+/* Dummy defines for floating point control */
+#define _MM_MASK_MASK 0x1f80
+#define _MM_MASK_DIV_ZERO 0x200
+#define _MM_FLUSH_ZERO_ON 0x8000
+#define _MM_MASK_DENORM 0x100
+#define _MM_SET_EXCEPTION_MASK(x)
+#define _MM_SET_FLUSH_ZERO_MODE(x)
+
+__forceinline int _mm_getcsr()
+{
+ return 0;
+}
+
+__forceinline void _mm_mfence()
+{
+ __sync_synchronize();
+}
diff --git a/thirdparty/embree/common/simd/arm/sse2neon.h b/thirdparty/embree/common/simd/arm/sse2neon.h
new file mode 100644
index 0000000000..7eb25cf2c5
--- /dev/null
+++ b/thirdparty/embree/common/simd/arm/sse2neon.h
@@ -0,0 +1,6996 @@
+#ifndef SSE2NEON_H
+#define SSE2NEON_H
+
+// This header file provides a simple API translation layer
+// between SSE intrinsics to their corresponding Arm/Aarch64 NEON versions
+//
+// This header file does not yet translate all of the SSE intrinsics.
+//
+// Contributors to this work are:
+// John W. Ratcliff <jratcliffscarab@gmail.com>
+// Brandon Rowlett <browlett@nvidia.com>
+// Ken Fast <kfast@gdeb.com>
+// Eric van Beurden <evanbeurden@nvidia.com>
+// Alexander Potylitsin <apotylitsin@nvidia.com>
+// Hasindu Gamaarachchi <hasindu2008@gmail.com>
+// Jim Huang <jserv@biilabs.io>
+// Mark Cheng <marktwtn@biilabs.io>
+// Malcolm James MacLeod <malcolm@gulden.com>
+// Devin Hussey (easyaspi314) <husseydevin@gmail.com>
+// Sebastian Pop <spop@amazon.com>
+// Developer Ecosystem Engineering <DeveloperEcosystemEngineering@apple.com>
+// Danila Kutenin <danilak@google.com>
+// François Turban (JishinMaster) <francois.turban@gmail.com>
+// Pei-Hsuan Hung <afcidk@gmail.com>
+// Yang-Hao Yuan <yanghau@biilabs.io>
+// Syoyo Fujita <syoyo@lighttransport.com>
+// Brecht Van Lommel <brecht@blender.org>
+
+/*
+ * sse2neon is freely redistributable under the MIT License.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Tunable configurations */
+
+/* Enable precise implementation of math operations
+ * This would slow down the computation a bit, but gives consistent result with
+ * x86 SSE2. (e.g. would solve a hole or NaN pixel in the rendering result)
+ */
+/* _mm_min_ps and _mm_max_ps */
+#ifndef SSE2NEON_PRECISE_MINMAX
+#define SSE2NEON_PRECISE_MINMAX (0)
+#endif
+/* _mm_rcp_ps and _mm_div_ps */
+#ifndef SSE2NEON_PRECISE_DIV
+#define SSE2NEON_PRECISE_DIV (0)
+#endif
+/* _mm_sqrt_ps and _mm_rsqrt_ps */
+#ifndef SSE2NEON_PRECISE_SQRT
+#define SSE2NEON_PRECISE_SQRT (0)
+#endif
+#ifndef SSE2NEON_PRECISE_RSQRT
+#define SSE2NEON_PRECISE_RSQRT (0)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma push_macro("FORCE_INLINE")
+#pragma push_macro("ALIGN_STRUCT")
+#define FORCE_INLINE static inline __attribute__((always_inline))
+#define ALIGN_STRUCT(x) __attribute__((aligned(x)))
+#ifndef likely
+#define likely(x) __builtin_expect(!!(x), 1)
+#endif
+#ifndef unlikely
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+#else
+#error "Macro name collisions may happen with unsupported compiler."
+#ifdef FORCE_INLINE
+#undef FORCE_INLINE
+#endif
+#define FORCE_INLINE static inline
+#ifndef ALIGN_STRUCT
+#define ALIGN_STRUCT(x) __declspec(align(x))
+#endif
+#endif
+#ifndef likely
+#define likely(x) (x)
+#endif
+#ifndef unlikely
+#define unlikely(x) (x)
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/* Architecture-specific build options */
+/* FIXME: #pragma GCC push_options is only available on GCC */
+#if defined(__GNUC__)
+#if defined(__arm__) && __ARM_ARCH == 7
+/* According to ARM C Language Extensions Architecture specification,
+ * __ARM_NEON is defined to a value indicating the Advanced SIMD (NEON)
+ * architecture supported.
+ */
+#if !defined(__ARM_NEON) || !defined(__ARM_NEON__)
+#error "You must enable NEON instructions (e.g. -mfpu=neon) to use SSE2NEON."
+#endif
+#if !defined(__clang__)
+#pragma GCC push_options
+#pragma GCC target("fpu=neon")
+#endif
+#elif defined(__aarch64__)
+#if !defined(__clang__)
+#pragma GCC push_options
+#pragma GCC target("+simd")
+#endif
+#else
+#error "Unsupported target. Must be either ARMv7-A+NEON or ARMv8-A."
+#endif
+#endif
+
+#include <arm_neon.h>
+
+/* Rounding functions require either Aarch64 instructions or libm failback */
+#if !defined(__aarch64__)
+#include <math.h>
+#endif
+
+/* "__has_builtin" can be used to query support for built-in functions
+ * provided by gcc/clang and other compilers that support it.
+ */
+#ifndef __has_builtin /* GCC prior to 10 or non-clang compilers */
+/* Compatibility with gcc <= 9 */
+#if __GNUC__ <= 9
+#define __has_builtin(x) HAS##x
+#define HAS__builtin_popcount 1
+#define HAS__builtin_popcountll 1
+#else
+#define __has_builtin(x) 0
+#endif
+#endif
+
+/**
+ * MACRO for shuffle parameter for _mm_shuffle_ps().
+ * Argument fp3 is a digit[0123] that represents the fp from argument "b"
+ * of mm_shuffle_ps that will be placed in fp3 of result. fp2 is the same
+ * for fp2 in result. fp1 is a digit[0123] that represents the fp from
+ * argument "a" of mm_shuffle_ps that will be places in fp1 of result.
+ * fp0 is the same for fp0 of result.
+ */
+#define _MM_SHUFFLE(fp3, fp2, fp1, fp0) \
+ (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | ((fp0)))
+
+/* Rounding mode macros. */
+#define _MM_FROUND_TO_NEAREST_INT 0x00
+#define _MM_FROUND_TO_NEG_INF 0x01
+#define _MM_FROUND_TO_POS_INF 0x02
+#define _MM_FROUND_TO_ZERO 0x03
+#define _MM_FROUND_CUR_DIRECTION 0x04
+#define _MM_FROUND_NO_EXC 0x08
+#define _MM_ROUND_NEAREST 0x0000
+#define _MM_ROUND_DOWN 0x2000
+#define _MM_ROUND_UP 0x4000
+#define _MM_ROUND_TOWARD_ZERO 0x6000
+
+/* indicate immediate constant argument in a given range */
+#define __constrange(a, b) const
+
+/* A few intrinsics accept traditional data types like ints or floats, but
+ * most operate on data types that are specific to SSE.
+ * If a vector type ends in d, it contains doubles, and if it does not have
+ * a suffix, it contains floats. An integer vector type can contain any type
+ * of integer, from chars to shorts to unsigned long longs.
+ */
+typedef int64x1_t __m64;
+typedef float32x4_t __m128; /* 128-bit vector containing 4 floats */
+// On ARM 32-bit architecture, the float64x2_t is not supported.
+// The data type __m128d should be represented in a different way for related
+// intrinsic conversion.
+#if defined(__aarch64__)
+typedef float64x2_t __m128d; /* 128-bit vector containing 2 doubles */
+#else
+typedef float32x4_t __m128d;
+#endif
+typedef int64x2_t __m128i; /* 128-bit vector containing integers */
+
+/* type-safe casting between types */
+
+#define vreinterpretq_m128_f16(x) vreinterpretq_f32_f16(x)
+#define vreinterpretq_m128_f32(x) (x)
+#define vreinterpretq_m128_f64(x) vreinterpretq_f32_f64(x)
+
+#define vreinterpretq_m128_u8(x) vreinterpretq_f32_u8(x)
+#define vreinterpretq_m128_u16(x) vreinterpretq_f32_u16(x)
+#define vreinterpretq_m128_u32(x) vreinterpretq_f32_u32(x)
+#define vreinterpretq_m128_u64(x) vreinterpretq_f32_u64(x)
+
+#define vreinterpretq_m128_s8(x) vreinterpretq_f32_s8(x)
+#define vreinterpretq_m128_s16(x) vreinterpretq_f32_s16(x)
+#define vreinterpretq_m128_s32(x) vreinterpretq_f32_s32(x)
+#define vreinterpretq_m128_s64(x) vreinterpretq_f32_s64(x)
+
+#define vreinterpretq_f16_m128(x) vreinterpretq_f16_f32(x)
+#define vreinterpretq_f32_m128(x) (x)
+#define vreinterpretq_f64_m128(x) vreinterpretq_f64_f32(x)
+
+#define vreinterpretq_u8_m128(x) vreinterpretq_u8_f32(x)
+#define vreinterpretq_u16_m128(x) vreinterpretq_u16_f32(x)
+#define vreinterpretq_u32_m128(x) vreinterpretq_u32_f32(x)
+#define vreinterpretq_u64_m128(x) vreinterpretq_u64_f32(x)
+
+#define vreinterpretq_s8_m128(x) vreinterpretq_s8_f32(x)
+#define vreinterpretq_s16_m128(x) vreinterpretq_s16_f32(x)
+#define vreinterpretq_s32_m128(x) vreinterpretq_s32_f32(x)
+#define vreinterpretq_s64_m128(x) vreinterpretq_s64_f32(x)
+
+#define vreinterpretq_m128i_s8(x) vreinterpretq_s64_s8(x)
+#define vreinterpretq_m128i_s16(x) vreinterpretq_s64_s16(x)
+#define vreinterpretq_m128i_s32(x) vreinterpretq_s64_s32(x)
+#define vreinterpretq_m128i_s64(x) (x)
+
+#define vreinterpretq_m128i_u8(x) vreinterpretq_s64_u8(x)
+#define vreinterpretq_m128i_u16(x) vreinterpretq_s64_u16(x)
+#define vreinterpretq_m128i_u32(x) vreinterpretq_s64_u32(x)
+#define vreinterpretq_m128i_u64(x) vreinterpretq_s64_u64(x)
+
+#define vreinterpretq_f32_m128i(x) vreinterpretq_f32_s64(x)
+#define vreinterpretq_f64_m128i(x) vreinterpretq_f64_s64(x)
+
+#define vreinterpretq_s8_m128i(x) vreinterpretq_s8_s64(x)
+#define vreinterpretq_s16_m128i(x) vreinterpretq_s16_s64(x)
+#define vreinterpretq_s32_m128i(x) vreinterpretq_s32_s64(x)
+#define vreinterpretq_s64_m128i(x) (x)
+
+#define vreinterpretq_u8_m128i(x) vreinterpretq_u8_s64(x)
+#define vreinterpretq_u16_m128i(x) vreinterpretq_u16_s64(x)
+#define vreinterpretq_u32_m128i(x) vreinterpretq_u32_s64(x)
+#define vreinterpretq_u64_m128i(x) vreinterpretq_u64_s64(x)
+
+#define vreinterpret_m64_s8(x) vreinterpret_s64_s8(x)
+#define vreinterpret_m64_s16(x) vreinterpret_s64_s16(x)
+#define vreinterpret_m64_s32(x) vreinterpret_s64_s32(x)
+#define vreinterpret_m64_s64(x) (x)
+
+#define vreinterpret_m64_u8(x) vreinterpret_s64_u8(x)
+#define vreinterpret_m64_u16(x) vreinterpret_s64_u16(x)
+#define vreinterpret_m64_u32(x) vreinterpret_s64_u32(x)
+#define vreinterpret_m64_u64(x) vreinterpret_s64_u64(x)
+
+#define vreinterpret_m64_f16(x) vreinterpret_s64_f16(x)
+#define vreinterpret_m64_f32(x) vreinterpret_s64_f32(x)
+#define vreinterpret_m64_f64(x) vreinterpret_s64_f64(x)
+
+#define vreinterpret_u8_m64(x) vreinterpret_u8_s64(x)
+#define vreinterpret_u16_m64(x) vreinterpret_u16_s64(x)
+#define vreinterpret_u32_m64(x) vreinterpret_u32_s64(x)
+#define vreinterpret_u64_m64(x) vreinterpret_u64_s64(x)
+
+#define vreinterpret_s8_m64(x) vreinterpret_s8_s64(x)
+#define vreinterpret_s16_m64(x) vreinterpret_s16_s64(x)
+#define vreinterpret_s32_m64(x) vreinterpret_s32_s64(x)
+#define vreinterpret_s64_m64(x) (x)
+
+#define vreinterpret_f32_m64(x) vreinterpret_f32_s64(x)
+
+#if defined(__aarch64__)
+#define vreinterpretq_m128d_s32(x) vreinterpretq_f64_s32(x)
+#define vreinterpretq_m128d_s64(x) vreinterpretq_f64_s64(x)
+
+#define vreinterpretq_m128d_u64(x) vreinterpretq_f64_u64(x)
+
+#define vreinterpretq_m128d_f32(x) vreinterpretq_f64_f32(x)
+#define vreinterpretq_m128d_f64(x) (x)
+
+#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f64(x)
+
+#define vreinterpretq_u64_m128d(x) vreinterpretq_u64_f64(x)
+
+#define vreinterpretq_f64_m128d(x) (x)
+#define vreinterpretq_f32_m128d(x) vreinterpretq_f32_f64(x)
+#else
+#define vreinterpretq_m128d_s32(x) vreinterpretq_f32_s32(x)
+#define vreinterpretq_m128d_s64(x) vreinterpretq_f32_s64(x)
+
+#define vreinterpretq_m128d_u32(x) vreinterpretq_f32_u32(x)
+#define vreinterpretq_m128d_u64(x) vreinterpretq_f32_u64(x)
+
+#define vreinterpretq_m128d_f32(x) (x)
+
+#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f32(x)
+
+#define vreinterpretq_u32_m128d(x) vreinterpretq_u32_f32(x)
+#define vreinterpretq_u64_m128d(x) vreinterpretq_u64_f32(x)
+
+#define vreinterpretq_f32_m128d(x) (x)
+#endif
+
+// A struct is defined in this header file called 'SIMDVec' which can be used
+// by applications which attempt to access the contents of an _m128 struct
+// directly. It is important to note that accessing the __m128 struct directly
+// is bad coding practice by Microsoft: @see:
+// https://msdn.microsoft.com/en-us/library/ayeb3ayc.aspx
+//
+// However, some legacy source code may try to access the contents of an __m128
+// struct directly so the developer can use the SIMDVec as an alias for it. Any
+// casting must be done manually by the developer, as you cannot cast or
+// otherwise alias the base NEON data type for intrinsic operations.
+//
+// union intended to allow direct access to an __m128 variable using the names
+// that the MSVC compiler provides. This union should really only be used when
+// trying to access the members of the vector as integer values. GCC/clang
+// allow native access to the float members through a simple array access
+// operator (in C since 4.6, in C++ since 4.8).
+//
+// Ideally direct accesses to SIMD vectors should not be used since it can cause
+// a performance hit. If it really is needed however, the original __m128
+// variable can be aliased with a pointer to this union and used to access
+// individual components. The use of this union should be hidden behind a macro
+// that is used throughout the codebase to access the members instead of always
+// declaring this type of variable.
+typedef union ALIGN_STRUCT(16) SIMDVec {
+ float m128_f32[4]; // as floats - DON'T USE. Added for convenience.
+ int8_t m128_i8[16]; // as signed 8-bit integers.
+ int16_t m128_i16[8]; // as signed 16-bit integers.
+ int32_t m128_i32[4]; // as signed 32-bit integers.
+ int64_t m128_i64[2]; // as signed 64-bit integers.
+ uint8_t m128_u8[16]; // as unsigned 8-bit integers.
+ uint16_t m128_u16[8]; // as unsigned 16-bit integers.
+ uint32_t m128_u32[4]; // as unsigned 32-bit integers.
+ uint64_t m128_u64[2]; // as unsigned 64-bit integers.
+} SIMDVec;
+
+// casting using SIMDVec
+#define vreinterpretq_nth_u64_m128i(x, n) (((SIMDVec *) &x)->m128_u64[n])
+#define vreinterpretq_nth_u32_m128i(x, n) (((SIMDVec *) &x)->m128_u32[n])
+#define vreinterpretq_nth_u8_m128i(x, n) (((SIMDVec *) &x)->m128_u8[n])
+
+/* Backwards compatibility for compilers with lack of specific type support */
+
+// Older gcc does not define vld1q_u8_x4 type
+#if defined(__GNUC__) && !defined(__clang__) && \
+ ((__GNUC__ == 10 && (__GNUC_MINOR__ <= 1)) || \
+ (__GNUC__ == 9 && (__GNUC_MINOR__ <= 3)) || \
+ (__GNUC__ == 8 && (__GNUC_MINOR__ <= 4)) || __GNUC__ <= 7)
+FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
+{
+ uint8x16x4_t ret;
+ ret.val[0] = vld1q_u8(p + 0);
+ ret.val[1] = vld1q_u8(p + 16);
+ ret.val[2] = vld1q_u8(p + 32);
+ ret.val[3] = vld1q_u8(p + 48);
+ return ret;
+}
+#else
+// Wraps vld1q_u8_x4
+FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
+{
+ return vld1q_u8_x4(p);
+}
+#endif
+
+/* Function Naming Conventions
+ * The naming convention of SSE intrinsics is straightforward. A generic SSE
+ * intrinsic function is given as follows:
+ * _mm_<name>_<data_type>
+ *
+ * The parts of this format are given as follows:
+ * 1. <name> describes the operation performed by the intrinsic
+ * 2. <data_type> identifies the data type of the function's primary arguments
+ *
+ * This last part, <data_type>, is a little complicated. It identifies the
+ * content of the input values, and can be set to any of the following values:
+ * + ps - vectors contain floats (ps stands for packed single-precision)
+ * + pd - vectors cantain doubles (pd stands for packed double-precision)
+ * + epi8/epi16/epi32/epi64 - vectors contain 8-bit/16-bit/32-bit/64-bit
+ * signed integers
+ * + epu8/epu16/epu32/epu64 - vectors contain 8-bit/16-bit/32-bit/64-bit
+ * unsigned integers
+ * + si128 - unspecified 128-bit vector or 256-bit vector
+ * + m128/m128i/m128d - identifies input vector types when they are different
+ * than the type of the returned vector
+ *
+ * For example, _mm_setzero_ps. The _mm implies that the function returns
+ * a 128-bit vector. The _ps at the end implies that the argument vectors
+ * contain floats.
+ *
+ * A complete example: Byte Shuffle - pshufb (_mm_shuffle_epi8)
+ * // Set packed 16-bit integers. 128 bits, 8 short, per 16 bits
+ * __m128i v_in = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
+ * // Set packed 8-bit integers
+ * // 128 bits, 16 chars, per 8 bits
+ * __m128i v_perm = _mm_setr_epi8(1, 0, 2, 3, 8, 9, 10, 11,
+ * 4, 5, 12, 13, 6, 7, 14, 15);
+ * // Shuffle packed 8-bit integers
+ * __m128i v_out = _mm_shuffle_epi8(v_in, v_perm); // pshufb
+ *
+ * Data (Number, Binary, Byte Index):
+ +------+------+-------------+------+------+-------------+
+ | 1 | 2 | 3 | 4 | Number
+ +------+------+------+------+------+------+------+------+
+ | 0000 | 0001 | 0000 | 0010 | 0000 | 0011 | 0000 | 0100 | Binary
+ +------+------+------+------+------+------+------+------+
+ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Index
+ +------+------+------+------+------+------+------+------+
+
+ +------+------+------+------+------+------+------+------+
+ | 5 | 6 | 7 | 8 | Number
+ +------+------+------+------+------+------+------+------+
+ | 0000 | 0101 | 0000 | 0110 | 0000 | 0111 | 0000 | 1000 | Binary
+ +------+------+------+------+------+------+------+------+
+ | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Index
+ +------+------+------+------+------+------+------+------+
+ * Index (Byte Index):
+ +------+------+------+------+------+------+------+------+
+ | 1 | 0 | 2 | 3 | 8 | 9 | 10 | 11 |
+ +------+------+------+------+------+------+------+------+
+
+ +------+------+------+------+------+------+------+------+
+ | 4 | 5 | 12 | 13 | 6 | 7 | 14 | 15 |
+ +------+------+------+------+------+------+------+------+
+ * Result:
+ +------+------+------+------+------+------+------+------+
+ | 1 | 0 | 2 | 3 | 8 | 9 | 10 | 11 | Index
+ +------+------+------+------+------+------+------+------+
+ | 0001 | 0000 | 0000 | 0010 | 0000 | 0101 | 0000 | 0110 | Binary
+ +------+------+------+------+------+------+------+------+
+ | 256 | 2 | 5 | 6 | Number
+ +------+------+------+------+------+------+------+------+
+
+ +------+------+------+------+------+------+------+------+
+ | 4 | 5 | 12 | 13 | 6 | 7 | 14 | 15 | Index
+ +------+------+------+------+------+------+------+------+
+ | 0000 | 0011 | 0000 | 0111 | 0000 | 0100 | 0000 | 1000 | Binary
+ +------+------+------+------+------+------+------+------+
+ | 3 | 7 | 4 | 8 | Number
+ +------+------+------+------+------+------+-------------+
+ */
+
+/* Set/get methods */
+
+/* Constants for use with _mm_prefetch. */
+enum _mm_hint {
+ _MM_HINT_NTA = 0, /* load data to L1 and L2 cache, mark it as NTA */
+ _MM_HINT_T0 = 1, /* load data to L1 and L2 cache */
+ _MM_HINT_T1 = 2, /* load data to L2 cache only */
+ _MM_HINT_T2 = 3, /* load data to L2 cache only, mark it as NTA */
+ _MM_HINT_ENTA = 4, /* exclusive version of _MM_HINT_NTA */
+ _MM_HINT_ET0 = 5, /* exclusive version of _MM_HINT_T0 */
+ _MM_HINT_ET1 = 6, /* exclusive version of _MM_HINT_T1 */
+ _MM_HINT_ET2 = 7 /* exclusive version of _MM_HINT_T2 */
+};
+
+// Loads one cache line of data from address p to a location closer to the
+// processor. https://msdn.microsoft.com/en-us/library/84szxsww(v=vs.100).aspx
+FORCE_INLINE void _mm_prefetch(const void *p, int i)
+{
+ (void) i;
+ __builtin_prefetch(p);
+}
+
+// Pause the processor. This is typically used in spin-wait loops and depending
+// on the x86 processor typical values are in the 40-100 cycle range. The
+// 'yield' instruction isn't a good fit beacuse it's effectively a nop on most
+// Arm cores. Experience with several databases has shown has shown an 'isb' is
+// a reasonable approximation.
+FORCE_INLINE void _mm_pause()
+{
+ __asm__ __volatile__("isb\n");
+}
+
+// Copy the lower single-precision (32-bit) floating-point element of a to dst.
+//
+// dst[31:0] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_f32
+FORCE_INLINE float _mm_cvtss_f32(__m128 a)
+{
+ return vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+}
+
+// Convert the lower single-precision (32-bit) floating-point element in b to a
+// double-precision (64-bit) floating-point element, store the result in the
+// lower element of dst, and copy the upper element from a to the upper element
+// of dst.
+//
+// dst[63:0] := Convert_FP32_To_FP64(b[31:0])
+// dst[127:64] := a[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_sd
+FORCE_INLINE __m128d _mm_cvtss_sd(__m128d a, __m128 b)
+{
+ double d = (double) vgetq_lane_f32(vreinterpretq_f32_m128(b), 0);
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vsetq_lane_f64(d, vreinterpretq_f64_m128d(a), 0));
+#else
+ return vreinterpretq_m128d_s64(
+ vsetq_lane_s64(*(int64_t *) &d, vreinterpretq_s64_m128d(a), 0));
+#endif
+}
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 32-bit integer, and store the result in dst.
+//
+// dst[31:0] := Convert_FP32_To_Int32(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si32
+#define _mm_cvtss_si32(a) _mm_cvt_ss2si(a)
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 64-bit integer, and store the result in dst.
+//
+// dst[63:0] := Convert_FP32_To_Int64(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si64
+FORCE_INLINE int _mm_cvtss_si64(__m128 a)
+{
+#if defined(__aarch64__)
+ return vgetq_lane_s64(
+ vreinterpretq_s64_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a))), 0);
+#else
+ float32_t data = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ float32_t diff = data - floor(data);
+ if (diff > 0.5)
+ return (int64_t) ceil(data);
+ if (unlikely(diff == 0.5)) {
+ int64_t f = (int64_t) floor(data);
+ int64_t c = (int64_t) ceil(data);
+ return c & 1 ? f : c;
+ }
+ return (int64_t) floor(data);
+#endif
+}
+
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 32-bit integers with truncation, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := 32*j
+// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ps2pi
+FORCE_INLINE __m64 _mm_cvtt_ps2pi(__m128 a)
+{
+ return vreinterpret_m64_s32(
+ vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a))));
+}
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 32-bit integer with truncation, and store the result in dst.
+//
+// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ss2si
+FORCE_INLINE int _mm_cvtt_ss2si(__m128 a)
+{
+ return vgetq_lane_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)), 0);
+}
+
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 32-bit integers with truncation, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := 32*j
+// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttps_pi32
+#define _mm_cvttps_pi32(a) _mm_cvtt_ps2pi(a)
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 32-bit integer with truncation, and store the result in dst.
+//
+// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si32
+#define _mm_cvttss_si32(a) _mm_cvtt_ss2si(a)
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 64-bit integer with truncation, and store the result in dst.
+//
+// dst[63:0] := Convert_FP32_To_Int64_Truncate(a[31:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si64
+FORCE_INLINE int64_t _mm_cvttss_si64(__m128 a)
+{
+ return vgetq_lane_s64(
+ vmovl_s32(vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)))), 0);
+}
+
+// Sets the 128-bit value to zero
+// https://msdn.microsoft.com/en-us/library/vstudio/ys7dw0kh(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_setzero_si128(void)
+{
+ return vreinterpretq_m128i_s32(vdupq_n_s32(0));
+}
+
+// Clears the four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/vstudio/tk1t2tbz(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_setzero_ps(void)
+{
+ return vreinterpretq_m128_f32(vdupq_n_f32(0));
+}
+
+// Return vector of type __m128d with all elements set to zero.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setzero_pd
+FORCE_INLINE __m128d _mm_setzero_pd(void)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vdupq_n_f64(0));
+#else
+ return vreinterpretq_m128d_f32(vdupq_n_f32(0));
+#endif
+}
+
+// Sets the four single-precision, floating-point values to w.
+//
+// r0 := r1 := r2 := r3 := w
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_set1_ps(float _w)
+{
+ return vreinterpretq_m128_f32(vdupq_n_f32(_w));
+}
+
+// Sets the four single-precision, floating-point values to w.
+// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_set_ps1(float _w)
+{
+ return vreinterpretq_m128_f32(vdupq_n_f32(_w));
+}
+
+// Sets the four single-precision, floating-point values to the four inputs.
+// https://msdn.microsoft.com/en-us/library/vstudio/afh0zf75(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x)
+{
+ float ALIGN_STRUCT(16) data[4] = {x, y, z, w};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
+}
+
+// Copy single-precision (32-bit) floating-point element a to the lower element
+// of dst, and zero the upper 3 elements.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_ss
+FORCE_INLINE __m128 _mm_set_ss(float a)
+{
+ float ALIGN_STRUCT(16) data[4] = {a, 0, 0, 0};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
+}
+
+// Sets the four single-precision, floating-point values to the four inputs in
+// reverse order.
+// https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x)
+{
+ float ALIGN_STRUCT(16) data[4] = {w, z, y, x};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
+}
+
+// Sets the 8 signed 16-bit integer values in reverse order.
+//
+// Return Value
+// r0 := w0
+// r1 := w1
+// ...
+// r7 := w7
+FORCE_INLINE __m128i _mm_setr_epi16(short w0,
+ short w1,
+ short w2,
+ short w3,
+ short w4,
+ short w5,
+ short w6,
+ short w7)
+{
+ int16_t ALIGN_STRUCT(16) data[8] = {w0, w1, w2, w3, w4, w5, w6, w7};
+ return vreinterpretq_m128i_s16(vld1q_s16((int16_t *) data));
+}
+
+// Sets the 4 signed 32-bit integer values in reverse order
+// https://technet.microsoft.com/en-us/library/security/27yb3ee5(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0)
+{
+ int32_t ALIGN_STRUCT(16) data[4] = {i3, i2, i1, i0};
+ return vreinterpretq_m128i_s32(vld1q_s32(data));
+}
+
+// Set packed 64-bit integers in dst with the supplied values in reverse order.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_epi64
+FORCE_INLINE __m128i _mm_setr_epi64(__m64 e1, __m64 e0)
+{
+ return vreinterpretq_m128i_s64(vcombine_s64(e1, e0));
+}
+
+// Sets the 16 signed 8-bit integer values to b.
+//
+// r0 := b
+// r1 := b
+// ...
+// r15 := b
+//
+// https://msdn.microsoft.com/en-us/library/6e14xhyf(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_set1_epi8(signed char w)
+{
+ return vreinterpretq_m128i_s8(vdupq_n_s8(w));
+}
+
+// Broadcast double-precision (64-bit) floating-point value a to all elements of
+// dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_pd
+FORCE_INLINE __m128d _mm_set1_pd(double d)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vdupq_n_f64(d));
+#else
+ return vreinterpretq_m128d_s64(vdupq_n_s64(*(int64_t *) &d));
+#endif
+}
+
+// Sets the 8 signed 16-bit integer values to w.
+//
+// r0 := w
+// r1 := w
+// ...
+// r7 := w
+//
+// https://msdn.microsoft.com/en-us/library/k0ya3x0e(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_set1_epi16(short w)
+{
+ return vreinterpretq_m128i_s16(vdupq_n_s16(w));
+}
+
+// Sets the 16 signed 8-bit integer values.
+// https://msdn.microsoft.com/en-us/library/x0cx8zd3(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_set_epi8(signed char b15,
+ signed char b14,
+ signed char b13,
+ signed char b12,
+ signed char b11,
+ signed char b10,
+ signed char b9,
+ signed char b8,
+ signed char b7,
+ signed char b6,
+ signed char b5,
+ signed char b4,
+ signed char b3,
+ signed char b2,
+ signed char b1,
+ signed char b0)
+{
+ int8_t ALIGN_STRUCT(16)
+ data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3,
+ (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7,
+ (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11,
+ (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15};
+ return (__m128i) vld1q_s8(data);
+}
+
+// Sets the 8 signed 16-bit integer values.
+// https://msdn.microsoft.com/en-au/library/3e0fek84(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_set_epi16(short i7,
+ short i6,
+ short i5,
+ short i4,
+ short i3,
+ short i2,
+ short i1,
+ short i0)
+{
+ int16_t ALIGN_STRUCT(16) data[8] = {i0, i1, i2, i3, i4, i5, i6, i7};
+ return vreinterpretq_m128i_s16(vld1q_s16(data));
+}
+
+// Sets the 16 signed 8-bit integer values in reverse order.
+// https://msdn.microsoft.com/en-us/library/2khb9c7k(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_setr_epi8(signed char b0,
+ signed char b1,
+ signed char b2,
+ signed char b3,
+ signed char b4,
+ signed char b5,
+ signed char b6,
+ signed char b7,
+ signed char b8,
+ signed char b9,
+ signed char b10,
+ signed char b11,
+ signed char b12,
+ signed char b13,
+ signed char b14,
+ signed char b15)
+{
+ int8_t ALIGN_STRUCT(16)
+ data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3,
+ (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7,
+ (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11,
+ (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15};
+ return (__m128i) vld1q_s8(data);
+}
+
+// Sets the 4 signed 32-bit integer values to i.
+//
+// r0 := i
+// r1 := i
+// r2 := i
+// r3 := I
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/h4xscxat(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_set1_epi32(int _i)
+{
+ return vreinterpretq_m128i_s32(vdupq_n_s32(_i));
+}
+
+// Sets the 2 signed 64-bit integer values to i.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/whtfzhzk(v=vs.100)
+FORCE_INLINE __m128i _mm_set1_epi64(__m64 _i)
+{
+ return vreinterpretq_m128i_s64(vdupq_n_s64((int64_t) _i));
+}
+
+// Sets the 2 signed 64-bit integer values to i.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_epi64x
+FORCE_INLINE __m128i _mm_set1_epi64x(int64_t _i)
+{
+ return vreinterpretq_m128i_s64(vdupq_n_s64(_i));
+}
+
+// Sets the 4 signed 32-bit integer values.
+// https://msdn.microsoft.com/en-us/library/vstudio/019beekt(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0)
+{
+ int32_t ALIGN_STRUCT(16) data[4] = {i0, i1, i2, i3};
+ return vreinterpretq_m128i_s32(vld1q_s32(data));
+}
+
+// Returns the __m128i structure with its two 64-bit integer values
+// initialized to the values of the two 64-bit integers passed in.
+// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx
+FORCE_INLINE __m128i _mm_set_epi64x(int64_t i1, int64_t i2)
+{
+ return vreinterpretq_m128i_s64(
+ vcombine_s64(vcreate_s64(i2), vcreate_s64(i1)));
+}
+
+// Returns the __m128i structure with its two 64-bit integer values
+// initialized to the values of the two 64-bit integers passed in.
+// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx
+FORCE_INLINE __m128i _mm_set_epi64(__m64 i1, __m64 i2)
+{
+ return _mm_set_epi64x((int64_t) i1, (int64_t) i2);
+}
+
+// Set packed double-precision (64-bit) floating-point elements in dst with the
+// supplied values.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd
+FORCE_INLINE __m128d _mm_set_pd(double e1, double e0)
+{
+ double ALIGN_STRUCT(16) data[2] = {e0, e1};
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vld1q_f64((float64_t *) data));
+#else
+ return vreinterpretq_m128d_f32(vld1q_f32((float32_t *) data));
+#endif
+}
+
+// Set packed double-precision (64-bit) floating-point elements in dst with the
+// supplied values in reverse order.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_pd
+FORCE_INLINE __m128d _mm_setr_pd(double e1, double e0)
+{
+ return _mm_set_pd(e0, e1);
+}
+
+// Copy double-precision (64-bit) floating-point element a to the lower element
+// of dst, and zero the upper element.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_sd
+FORCE_INLINE __m128d _mm_set_sd(double a)
+{
+ return _mm_set_pd(0, a);
+}
+
+// Broadcast double-precision (64-bit) floating-point value a to all elements of
+// dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd1
+#define _mm_set_pd1 _mm_set1_pd
+
+// Stores four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx
+FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
+{
+ vst1q_f32(p, vreinterpretq_f32_m128(a));
+}
+
+// Store the lower single-precision (32-bit) floating-point element from a into
+// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte
+// boundary or a general-protection exception may be generated.
+//
+// MEM[mem_addr+31:mem_addr] := a[31:0]
+// MEM[mem_addr+63:mem_addr+32] := a[31:0]
+// MEM[mem_addr+95:mem_addr+64] := a[31:0]
+// MEM[mem_addr+127:mem_addr+96] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_ps1
+FORCE_INLINE void _mm_store_ps1(float *p, __m128 a)
+{
+ float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ vst1q_f32(p, vdupq_n_f32(a0));
+}
+
+// Store the lower single-precision (32-bit) floating-point element from a into
+// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte
+// boundary or a general-protection exception may be generated.
+//
+// MEM[mem_addr+31:mem_addr] := a[31:0]
+// MEM[mem_addr+63:mem_addr+32] := a[31:0]
+// MEM[mem_addr+95:mem_addr+64] := a[31:0]
+// MEM[mem_addr+127:mem_addr+96] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store1_ps
+#define _mm_store1_ps _mm_store_ps1
+
+// Store 4 single-precision (32-bit) floating-point elements from a into memory
+// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
+//
+// MEM[mem_addr+31:mem_addr] := a[127:96]
+// MEM[mem_addr+63:mem_addr+32] := a[95:64]
+// MEM[mem_addr+95:mem_addr+64] := a[63:32]
+// MEM[mem_addr+127:mem_addr+96] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storer_ps
+FORCE_INLINE void _mm_storer_ps(float *p, __m128 a)
+{
+ float32x4_t tmp = vrev64q_f32(vreinterpretq_f32_m128(a));
+ float32x4_t rev = vextq_f32(tmp, tmp, 2);
+ vst1q_f32(p, rev);
+}
+
+// Stores four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx
+FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a)
+{
+ vst1q_f32(p, vreinterpretq_f32_m128(a));
+}
+
+// Stores four 32-bit integer values as (as a __m128i value) at the address p.
+// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
+FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a)
+{
+ vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
+}
+
+// Stores four 32-bit integer values as (as a __m128i value) at the address p.
+// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
+FORCE_INLINE void _mm_storeu_si128(__m128i *p, __m128i a)
+{
+ vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
+}
+
+// Stores the lower single - precision, floating - point value.
+// https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx
+FORCE_INLINE void _mm_store_ss(float *p, __m128 a)
+{
+ vst1q_lane_f32(p, vreinterpretq_f32_m128(a), 0);
+}
+
+// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
+// elements) from a into memory. mem_addr must be aligned on a 16-byte boundary
+// or a general-protection exception may be generated.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd
+FORCE_INLINE void _mm_store_pd(double *mem_addr, __m128d a)
+{
+#if defined(__aarch64__)
+ vst1q_f64((float64_t *) mem_addr, vreinterpretq_f64_m128d(a));
+#else
+ vst1q_f32((float32_t *) mem_addr, vreinterpretq_f32_m128d(a));
+#endif
+}
+
+// Store the upper double-precision (64-bit) floating-point element from a into
+// memory.
+//
+// MEM[mem_addr+63:mem_addr] := a[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeh_pd
+FORCE_INLINE void _mm_storeh_pd(double *mem_addr, __m128d a)
+{
+#if defined(__aarch64__)
+ vst1_f64((float64_t *) mem_addr, vget_high_f64(vreinterpretq_f64_m128d(a)));
+#else
+ vst1_f32((float32_t *) mem_addr, vget_high_f32(vreinterpretq_f32_m128d(a)));
+#endif
+}
+
+// Store the lower double-precision (64-bit) floating-point element from a into
+// memory.
+//
+// MEM[mem_addr+63:mem_addr] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storel_pd
+FORCE_INLINE void _mm_storel_pd(double *mem_addr, __m128d a)
+{
+#if defined(__aarch64__)
+ vst1_f64((float64_t *) mem_addr, vget_low_f64(vreinterpretq_f64_m128d(a)));
+#else
+ vst1_f32((float32_t *) mem_addr, vget_low_f32(vreinterpretq_f32_m128d(a)));
+#endif
+}
+
+// Store 2 double-precision (64-bit) floating-point elements from a into memory
+// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
+//
+// MEM[mem_addr+63:mem_addr] := a[127:64]
+// MEM[mem_addr+127:mem_addr+64] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storer_pd
+FORCE_INLINE void _mm_storer_pd(double *mem_addr, __m128d a)
+{
+ float32x4_t f = vreinterpretq_f32_m128d(a);
+ _mm_store_pd(mem_addr, vreinterpretq_m128d_f32(vextq_f32(f, f, 2)));
+}
+
+// Store the lower double-precision (64-bit) floating-point element from a into
+// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte
+// boundary or a general-protection exception may be generated.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd1
+FORCE_INLINE void _mm_store_pd1(double *mem_addr, __m128d a)
+{
+#if defined(__aarch64__)
+ float64x1_t a_low = vget_low_f64(vreinterpretq_f64_m128d(a));
+ vst1q_f64((float64_t *) mem_addr,
+ vreinterpretq_f64_m128d(vcombine_f64(a_low, a_low)));
+#else
+ float32x2_t a_low = vget_low_f32(vreinterpretq_f32_m128d(a));
+ vst1q_f32((float32_t *) mem_addr,
+ vreinterpretq_f32_m128d(vcombine_f32(a_low, a_low)));
+#endif
+}
+
+// Store the lower double-precision (64-bit) floating-point element from a into
+// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte
+// boundary or a general-protection exception may be generated.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=9,526,5601&text=_mm_store1_pd
+#define _mm_store1_pd _mm_store_pd1
+
+// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
+// elements) from a into memory. mem_addr does not need to be aligned on any
+// particular boundary.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_pd
+FORCE_INLINE void _mm_storeu_pd(double *mem_addr, __m128d a)
+{
+ _mm_store_pd(mem_addr, a);
+}
+
+// Reads the lower 64 bits of b and stores them into the lower 64 bits of a.
+// https://msdn.microsoft.com/en-us/library/hhwf428f%28v=vs.90%29.aspx
+FORCE_INLINE void _mm_storel_epi64(__m128i *a, __m128i b)
+{
+ uint64x1_t hi = vget_high_u64(vreinterpretq_u64_m128i(*a));
+ uint64x1_t lo = vget_low_u64(vreinterpretq_u64_m128i(b));
+ *a = vreinterpretq_m128i_u64(vcombine_u64(lo, hi));
+}
+
+// Stores the lower two single-precision floating point values of a to the
+// address p.
+//
+// *p0 := a0
+// *p1 := a1
+//
+// https://msdn.microsoft.com/en-us/library/h54t98ks(v=vs.90).aspx
+FORCE_INLINE void _mm_storel_pi(__m64 *p, __m128 a)
+{
+ *p = vreinterpret_m64_f32(vget_low_f32(a));
+}
+
+// Stores the upper two single-precision, floating-point values of a to the
+// address p.
+//
+// *p0 := a2
+// *p1 := a3
+//
+// https://msdn.microsoft.com/en-us/library/a7525fs8(v%3dvs.90).aspx
+FORCE_INLINE void _mm_storeh_pi(__m64 *p, __m128 a)
+{
+ *p = vreinterpret_m64_f32(vget_high_f32(a));
+}
+
+// Loads a single single-precision, floating-point value, copying it into all
+// four words
+// https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_load1_ps(const float *p)
+{
+ return vreinterpretq_m128_f32(vld1q_dup_f32(p));
+}
+
+// Load a single-precision (32-bit) floating-point element from memory into all
+// elements of dst.
+//
+// dst[31:0] := MEM[mem_addr+31:mem_addr]
+// dst[63:32] := MEM[mem_addr+31:mem_addr]
+// dst[95:64] := MEM[mem_addr+31:mem_addr]
+// dst[127:96] := MEM[mem_addr+31:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_ps1
+#define _mm_load_ps1 _mm_load1_ps
+
+// Sets the lower two single-precision, floating-point values with 64
+// bits of data loaded from the address p; the upper two values are passed
+// through from a.
+//
+// Return Value
+// r0 := *p0
+// r1 := *p1
+// r2 := a2
+// r3 := a3
+//
+// https://msdn.microsoft.com/en-us/library/s57cyak2(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_loadl_pi(__m128 a, __m64 const *p)
+{
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vld1_f32((const float32_t *) p), vget_high_f32(a)));
+}
+
+// Load 4 single-precision (32-bit) floating-point elements from memory into dst
+// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
+//
+// dst[31:0] := MEM[mem_addr+127:mem_addr+96]
+// dst[63:32] := MEM[mem_addr+95:mem_addr+64]
+// dst[95:64] := MEM[mem_addr+63:mem_addr+32]
+// dst[127:96] := MEM[mem_addr+31:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_ps
+FORCE_INLINE __m128 _mm_loadr_ps(const float *p)
+{
+ float32x4_t v = vrev64q_f32(vld1q_f32(p));
+ return vreinterpretq_m128_f32(vextq_f32(v, v, 2));
+}
+
+// Sets the upper two single-precision, floating-point values with 64
+// bits of data loaded from the address p; the lower two values are passed
+// through from a.
+//
+// r0 := a0
+// r1 := a1
+// r2 := *p0
+// r3 := *p1
+//
+// https://msdn.microsoft.com/en-us/library/w92wta0x(v%3dvs.100).aspx
+FORCE_INLINE __m128 _mm_loadh_pi(__m128 a, __m64 const *p)
+{
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vget_low_f32(a), vld1_f32((const float32_t *) p)));
+}
+
+// Loads four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_load_ps(const float *p)
+{
+ return vreinterpretq_m128_f32(vld1q_f32(p));
+}
+
+// Loads four single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx
+FORCE_INLINE __m128 _mm_loadu_ps(const float *p)
+{
+ // for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are
+ // equivalent for neon
+ return vreinterpretq_m128_f32(vld1q_f32(p));
+}
+
+// Load unaligned 16-bit integer from memory into the first element of dst.
+//
+// dst[15:0] := MEM[mem_addr+15:mem_addr]
+// dst[MAX:16] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si16
+FORCE_INLINE __m128i _mm_loadu_si16(const void *p)
+{
+ return vreinterpretq_m128i_s16(
+ vsetq_lane_s16(*(const int16_t *) p, vdupq_n_s16(0), 0));
+}
+
+// Load unaligned 64-bit integer from memory into the first element of dst.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[MAX:64] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si64
+FORCE_INLINE __m128i _mm_loadu_si64(const void *p)
+{
+ return vreinterpretq_m128i_s64(
+ vcombine_s64(vld1_s64((const int64_t *) p), vdup_n_s64(0)));
+}
+
+// Load a double-precision (64-bit) floating-point element from memory into the
+// lower of dst, and zero the upper element. mem_addr does not need to be
+// aligned on any particular boundary.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_sd
+FORCE_INLINE __m128d _mm_load_sd(const double *p)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vsetq_lane_f64(*p, vdupq_n_f64(0), 0));
+#else
+ const float *fp = (const float *) p;
+ float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], 0, 0};
+ return vreinterpretq_m128d_f32(vld1q_f32(data));
+#endif
+}
+
+// Loads two double-precision from 16-byte aligned memory, floating-point
+// values.
+//
+// dst[127:0] := MEM[mem_addr+127:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd
+FORCE_INLINE __m128d _mm_load_pd(const double *p)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vld1q_f64(p));
+#else
+ const float *fp = (const float *) p;
+ float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], fp[2], fp[3]};
+ return vreinterpretq_m128d_f32(vld1q_f32(data));
+#endif
+}
+
+// Loads two double-precision from unaligned memory, floating-point values.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_pd
+FORCE_INLINE __m128d _mm_loadu_pd(const double *p)
+{
+ return _mm_load_pd(p);
+}
+
+// Loads an single - precision, floating - point value into the low word and
+// clears the upper three words.
+// https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx
+FORCE_INLINE __m128 _mm_load_ss(const float *p)
+{
+ return vreinterpretq_m128_f32(vsetq_lane_f32(*p, vdupq_n_f32(0), 0));
+}
+
+// Load 64-bit integer from memory into the first element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_epi64
+FORCE_INLINE __m128i _mm_loadl_epi64(__m128i const *p)
+{
+ /* Load the lower 64 bits of the value pointed to by p into the
+ * lower 64 bits of the result, zeroing the upper 64 bits of the result.
+ */
+ return vreinterpretq_m128i_s32(
+ vcombine_s32(vld1_s32((int32_t const *) p), vcreate_s32(0)));
+}
+
+// Load a double-precision (64-bit) floating-point element from memory into the
+// lower element of dst, and copy the upper element from a to dst. mem_addr does
+// not need to be aligned on any particular boundary.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := a[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_pd
+FORCE_INLINE __m128d _mm_loadl_pd(__m128d a, const double *p)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vcombine_f64(vld1_f64(p), vget_high_f64(vreinterpretq_f64_m128d(a))));
+#else
+ return vreinterpretq_m128d_f32(
+ vcombine_f32(vld1_f32((const float *) p),
+ vget_high_f32(vreinterpretq_f32_m128d(a))));
+#endif
+}
+
+// Load 2 double-precision (64-bit) floating-point elements from memory into dst
+// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
+//
+// dst[63:0] := MEM[mem_addr+127:mem_addr+64]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_pd
+FORCE_INLINE __m128d _mm_loadr_pd(const double *p)
+{
+#if defined(__aarch64__)
+ float64x2_t v = vld1q_f64(p);
+ return vreinterpretq_m128d_f64(vextq_f64(v, v, 1));
+#else
+ int64x2_t v = vld1q_s64((const int64_t *) p);
+ return vreinterpretq_m128d_s64(vextq_s64(v, v, 1));
+#endif
+}
+
+// Sets the low word to the single-precision, floating-point value of b
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/35hdzazd(v=vs.100)
+FORCE_INLINE __m128 _mm_move_ss(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), 0),
+ vreinterpretq_f32_m128(a), 0));
+}
+
+// Move the lower double-precision (64-bit) floating-point element from b to the
+// lower element of dst, and copy the upper element from a to the upper element
+// of dst.
+//
+// dst[63:0] := b[63:0]
+// dst[127:64] := a[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_sd
+FORCE_INLINE __m128d _mm_move_sd(__m128d a, __m128d b)
+{
+ return vreinterpretq_m128d_f32(
+ vcombine_f32(vget_low_f32(vreinterpretq_f32_m128d(b)),
+ vget_high_f32(vreinterpretq_f32_m128d(a))));
+}
+
+// Copy the lower 64-bit integer in a to the lower element of dst, and zero the
+// upper element.
+//
+// dst[63:0] := a[63:0]
+// dst[127:64] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_epi64
+FORCE_INLINE __m128i _mm_move_epi64(__m128i a)
+{
+ return vreinterpretq_m128i_s64(
+ vsetq_lane_s64(0, vreinterpretq_s64_m128i(a), 1));
+}
+
+// Return vector of type __m128 with undefined elements.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_ps
+FORCE_INLINE __m128 _mm_undefined_ps(void)
+{
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+ __m128 a;
+ return a;
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+}
+
+/* Logic/Binary operations */
+
+// Computes the bitwise AND-NOT of the four single-precision, floating-point
+// values of a and b.
+//
+// r0 := ~a0 & b0
+// r1 := ~a1 & b1
+// r2 := ~a2 & b2
+// r3 := ~a3 & b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_s32(
+ vbicq_s32(vreinterpretq_s32_m128(b),
+ vreinterpretq_s32_m128(a))); // *NOTE* argument swap
+}
+
+// Compute the bitwise NOT of packed double-precision (64-bit) floating-point
+// elements in a and then AND with b, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// dst[i+63:i] := ((NOT a[i+63:i]) AND b[i+63:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_andnot_pd
+FORCE_INLINE __m128d _mm_andnot_pd(__m128d a, __m128d b)
+{
+ // *NOTE* argument swap
+ return vreinterpretq_m128d_s64(
+ vbicq_s64(vreinterpretq_s64_m128d(b), vreinterpretq_s64_m128d(a)));
+}
+
+// Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the
+// 128-bit value in a.
+//
+// r := (~a) & b
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vbicq_s32(vreinterpretq_s32_m128i(b),
+ vreinterpretq_s32_m128i(a))); // *NOTE* argument swap
+}
+
+// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in
+// b.
+//
+// r := a & b
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Computes the bitwise AND of the four single-precision, floating-point values
+// of a and b.
+//
+// r0 := a0 & b0
+// r1 := a1 & b1
+// r2 := a2 & b2
+// r3 := a3 & b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_s32(
+ vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
+}
+
+// Compute the bitwise AND of packed double-precision (64-bit) floating-point
+// elements in a and b, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// dst[i+63:i] := a[i+63:i] AND b[i+63:i]
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_and_pd
+FORCE_INLINE __m128d _mm_and_pd(__m128d a, __m128d b)
+{
+ return vreinterpretq_m128d_s64(
+ vandq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
+}
+
+// Computes the bitwise OR of the four single-precision, floating-point values
+// of a and b.
+// https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_s32(
+ vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
+}
+
+// Computes bitwise EXOR (exclusive-or) of the four single-precision,
+// floating-point values of a and b.
+// https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_s32(
+ veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
+}
+
+// Compute the bitwise XOR of packed double-precision (64-bit) floating-point
+// elements in a and b, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// dst[i+63:i] := a[i+63:i] XOR b[i+63:i]
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_xor_pd
+FORCE_INLINE __m128d _mm_xor_pd(__m128d a, __m128d b)
+{
+ return vreinterpretq_m128d_s64(
+ veorq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
+}
+
+// Compute the bitwise OR of packed double-precision (64-bit) floating-point
+// elements in a and b, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_or_pd
+FORCE_INLINE __m128d _mm_or_pd(__m128d a, __m128d b)
+{
+ return vreinterpretq_m128d_s64(
+ vorrq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b)));
+}
+
+// Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b.
+//
+// r := a | b
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_or_si128(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in
+// b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Duplicate the low double-precision (64-bit) floating-point element from a,
+// and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movedup_pd
+FORCE_INLINE __m128d _mm_movedup_pd(__m128d a)
+{
+#if (__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vdupq_laneq_f64(vreinterpretq_f64_m128d(a), 0));
+#else
+ return vreinterpretq_m128d_u64(
+ vdupq_n_u64(vgetq_lane_u64(vreinterpretq_u64_m128d(a), 0)));
+#endif
+}
+
+// Duplicate odd-indexed single-precision (32-bit) floating-point elements
+// from a, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movehdup_ps
+FORCE_INLINE __m128 _mm_movehdup_ps(__m128 a)
+{
+#if __has_builtin(__builtin_shufflevector)
+ return vreinterpretq_m128_f32(__builtin_shufflevector(
+ vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 1, 1, 3, 3));
+#else
+ float32_t a1 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 1);
+ float32_t a3 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 3);
+ float ALIGN_STRUCT(16) data[4] = {a1, a1, a3, a3};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
+#endif
+}
+
+// Duplicate even-indexed single-precision (32-bit) floating-point elements
+// from a, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_moveldup_ps
+FORCE_INLINE __m128 _mm_moveldup_ps(__m128 a)
+{
+#if __has_builtin(__builtin_shufflevector)
+ return vreinterpretq_m128_f32(__builtin_shufflevector(
+ vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 0, 0, 2, 2));
+#else
+ float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ float32_t a2 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 2);
+ float ALIGN_STRUCT(16) data[4] = {a0, a0, a2, a2};
+ return vreinterpretq_m128_f32(vld1q_f32(data));
+#endif
+}
+
+// Moves the upper two values of B into the lower two values of A.
+//
+// r3 := a3
+// r2 := a2
+// r1 := b3
+// r0 := b2
+FORCE_INLINE __m128 _mm_movehl_ps(__m128 __A, __m128 __B)
+{
+ float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(__A));
+ float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(__B));
+ return vreinterpretq_m128_f32(vcombine_f32(b32, a32));
+}
+
+// Moves the lower two values of B into the upper two values of A.
+//
+// r3 := b1
+// r2 := b0
+// r1 := a1
+// r0 := a0
+FORCE_INLINE __m128 _mm_movelh_ps(__m128 __A, __m128 __B)
+{
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(__A));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(__B));
+ return vreinterpretq_m128_f32(vcombine_f32(a10, b10));
+}
+
+// Compute the absolute value of packed signed 32-bit integers in a, and store
+// the unsigned results in dst.
+//
+// FOR j := 0 to 3
+// i := j*32
+// dst[i+31:i] := ABS(a[i+31:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi32
+FORCE_INLINE __m128i _mm_abs_epi32(__m128i a)
+{
+ return vreinterpretq_m128i_s32(vabsq_s32(vreinterpretq_s32_m128i(a)));
+}
+
+// Compute the absolute value of packed signed 16-bit integers in a, and store
+// the unsigned results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// dst[i+15:i] := ABS(a[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi16
+FORCE_INLINE __m128i _mm_abs_epi16(__m128i a)
+{
+ return vreinterpretq_m128i_s16(vabsq_s16(vreinterpretq_s16_m128i(a)));
+}
+
+// Compute the absolute value of packed signed 8-bit integers in a, and store
+// the unsigned results in dst.
+//
+// FOR j := 0 to 15
+// i := j*8
+// dst[i+7:i] := ABS(a[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi8
+FORCE_INLINE __m128i _mm_abs_epi8(__m128i a)
+{
+ return vreinterpretq_m128i_s8(vabsq_s8(vreinterpretq_s8_m128i(a)));
+}
+
+// Compute the absolute value of packed signed 32-bit integers in a, and store
+// the unsigned results in dst.
+//
+// FOR j := 0 to 1
+// i := j*32
+// dst[i+31:i] := ABS(a[i+31:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi32
+FORCE_INLINE __m64 _mm_abs_pi32(__m64 a)
+{
+ return vreinterpret_m64_s32(vabs_s32(vreinterpret_s32_m64(a)));
+}
+
+// Compute the absolute value of packed signed 16-bit integers in a, and store
+// the unsigned results in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := ABS(a[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi16
+FORCE_INLINE __m64 _mm_abs_pi16(__m64 a)
+{
+ return vreinterpret_m64_s16(vabs_s16(vreinterpret_s16_m64(a)));
+}
+
+// Compute the absolute value of packed signed 8-bit integers in a, and store
+// the unsigned results in dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := ABS(a[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi8
+FORCE_INLINE __m64 _mm_abs_pi8(__m64 a)
+{
+ return vreinterpret_m64_s8(vabs_s8(vreinterpret_s8_m64(a)));
+}
+
+// Concatenate 16-byte blocks in a and b into a 32-byte temporary result, shift
+// the result right by imm8 bytes, and store the low 16 bytes in dst.
+//
+// tmp[255:0] := ((a[127:0] << 128)[255:0] OR b[127:0]) >> (imm8*8)
+// dst[127:0] := tmp[127:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_epi8
+#define _mm_alignr_epi8(a, b, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (unlikely((imm) >= 32)) { \
+ ret = _mm_setzero_si128(); \
+ } else { \
+ uint8x16_t tmp_low, tmp_high; \
+ if (imm >= 16) { \
+ const int idx = imm - 16; \
+ tmp_low = vreinterpretq_u8_m128i(a); \
+ tmp_high = vdupq_n_u8(0); \
+ ret = \
+ vreinterpretq_m128i_u8(vextq_u8(tmp_low, tmp_high, idx)); \
+ } else { \
+ const int idx = imm; \
+ tmp_low = vreinterpretq_u8_m128i(b); \
+ tmp_high = vreinterpretq_u8_m128i(a); \
+ ret = \
+ vreinterpretq_m128i_u8(vextq_u8(tmp_low, tmp_high, idx)); \
+ } \
+ } \
+ ret; \
+ })
+
+// Concatenate 8-byte blocks in a and b into a 16-byte temporary result, shift
+// the result right by imm8 bytes, and store the low 8 bytes in dst.
+//
+// tmp[127:0] := ((a[63:0] << 64)[127:0] OR b[63:0]) >> (imm8*8)
+// dst[63:0] := tmp[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_pi8
+#define _mm_alignr_pi8(a, b, imm) \
+ __extension__({ \
+ __m64 ret; \
+ if (unlikely((imm) >= 16)) { \
+ ret = vreinterpret_m64_s8(vdup_n_s8(0)); \
+ } else { \
+ uint8x8_t tmp_low, tmp_high; \
+ if (imm >= 8) { \
+ const int idx = imm - 8; \
+ tmp_low = vreinterpret_u8_m64(a); \
+ tmp_high = vdup_n_u8(0); \
+ ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \
+ } else { \
+ const int idx = imm; \
+ tmp_low = vreinterpret_u8_m64(b); \
+ tmp_high = vreinterpret_u8_m64(a); \
+ ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \
+ } \
+ } \
+ ret; \
+ })
+
+// Takes the upper 64 bits of a and places it in the low end of the result
+// Takes the lower 64 bits of b and places it into the high end of the result.
+FORCE_INLINE __m128 _mm_shuffle_ps_1032(__m128 a, __m128 b)
+{
+ float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a32, b10));
+}
+
+// takes the lower two 32-bit values from a and swaps them and places in high
+// end of result takes the higher two 32 bit values from b and swaps them and
+// places in low end of result.
+FORCE_INLINE __m128 _mm_shuffle_ps_2301(__m128 a, __m128 b)
+{
+ float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
+ float32x2_t b23 = vrev64_f32(vget_high_f32(vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128_f32(vcombine_f32(a01, b23));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_0321(__m128 a, __m128 b)
+{
+ float32x2_t a21 = vget_high_f32(
+ vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3));
+ float32x2_t b03 = vget_low_f32(
+ vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3));
+ return vreinterpretq_m128_f32(vcombine_f32(a21, b03));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2103(__m128 a, __m128 b)
+{
+ float32x2_t a03 = vget_low_f32(
+ vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3));
+ float32x2_t b21 = vget_high_f32(
+ vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3));
+ return vreinterpretq_m128_f32(vcombine_f32(a03, b21));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_1010(__m128 a, __m128 b)
+{
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a10, b10));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_1001(__m128 a, __m128 b)
+{
+ float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a01, b10));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_0101(__m128 a, __m128 b)
+{
+ float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
+ float32x2_t b01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(b)));
+ return vreinterpretq_m128_f32(vcombine_f32(a01, b01));
+}
+
+// keeps the low 64 bits of b in the low and puts the high 64 bits of a in the
+// high
+FORCE_INLINE __m128 _mm_shuffle_ps_3210(__m128 a, __m128 b)
+{
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a10, b32));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_0011(__m128 a, __m128 b)
+{
+ float32x2_t a11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 1);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ return vreinterpretq_m128_f32(vcombine_f32(a11, b00));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_0022(__m128 a, __m128 b)
+{
+ float32x2_t a22 =
+ vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ return vreinterpretq_m128_f32(vcombine_f32(a22, b00));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2200(__m128 a, __m128 b)
+{
+ float32x2_t a00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 0);
+ float32x2_t b22 =
+ vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(b)), 0);
+ return vreinterpretq_m128_f32(vcombine_f32(a00, b22));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_3202(__m128 a, __m128 b)
+{
+ float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ float32x2_t a22 =
+ vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0);
+ float32x2_t a02 = vset_lane_f32(a0, a22, 1); /* TODO: use vzip ?*/
+ float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(vcombine_f32(a02, b32));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_1133(__m128 a, __m128 b)
+{
+ float32x2_t a33 =
+ vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 1);
+ float32x2_t b11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 1);
+ return vreinterpretq_m128_f32(vcombine_f32(a33, b11));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2010(__m128 a, __m128 b)
+{
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32_t b2 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 2);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ float32x2_t b20 = vset_lane_f32(b2, b00, 1);
+ return vreinterpretq_m128_f32(vcombine_f32(a10, b20));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2001(__m128 a, __m128 b)
+{
+ float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
+ float32_t b2 = vgetq_lane_f32(b, 2);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ float32x2_t b20 = vset_lane_f32(b2, b00, 1);
+ return vreinterpretq_m128_f32(vcombine_f32(a01, b20));
+}
+
+FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b)
+{
+ float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
+ float32_t b2 = vgetq_lane_f32(b, 2);
+ float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
+ float32x2_t b20 = vset_lane_f32(b2, b00, 1);
+ return vreinterpretq_m128_f32(vcombine_f32(a32, b20));
+}
+
+// NEON does not support a general purpose permute intrinsic
+// Selects four specific single-precision, floating-point values from a and b,
+// based on the mask i.
+//
+// C equivalent:
+// __m128 _mm_shuffle_ps_default(__m128 a, __m128 b,
+// __constrange(0, 255) int imm) {
+// __m128 ret;
+// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3];
+// ret[2] = b[(imm >> 4) & 0x03]; ret[3] = b[(imm >> 6) & 0x03];
+// return ret;
+// }
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx
+#define _mm_shuffle_ps_default(a, b, imm) \
+ __extension__({ \
+ float32x4_t ret; \
+ ret = vmovq_n_f32( \
+ vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & (0x3))); \
+ ret = vsetq_lane_f32( \
+ vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), \
+ ret, 1); \
+ ret = vsetq_lane_f32( \
+ vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), \
+ ret, 2); \
+ ret = vsetq_lane_f32( \
+ vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), \
+ ret, 3); \
+ vreinterpretq_m128_f32(ret); \
+ })
+
+// FORCE_INLINE __m128 _mm_shuffle_ps(__m128 a, __m128 b, __constrange(0,255)
+// int imm)
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shuffle_ps(a, b, imm) \
+ __extension__({ \
+ float32x4_t _input1 = vreinterpretq_f32_m128(a); \
+ float32x4_t _input2 = vreinterpretq_f32_m128(b); \
+ float32x4_t _shuf = __builtin_shufflevector( \
+ _input1, _input2, (imm) & (0x3), ((imm) >> 2) & 0x3, \
+ (((imm) >> 4) & 0x3) + 4, (((imm) >> 6) & 0x3) + 4); \
+ vreinterpretq_m128_f32(_shuf); \
+ })
+#else // generic
+#define _mm_shuffle_ps(a, b, imm) \
+ __extension__({ \
+ __m128 ret; \
+ switch (imm) { \
+ case _MM_SHUFFLE(1, 0, 3, 2): \
+ ret = _mm_shuffle_ps_1032((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(2, 3, 0, 1): \
+ ret = _mm_shuffle_ps_2301((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(0, 3, 2, 1): \
+ ret = _mm_shuffle_ps_0321((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(2, 1, 0, 3): \
+ ret = _mm_shuffle_ps_2103((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(1, 0, 1, 0): \
+ ret = _mm_movelh_ps((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(1, 0, 0, 1): \
+ ret = _mm_shuffle_ps_1001((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(0, 1, 0, 1): \
+ ret = _mm_shuffle_ps_0101((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(3, 2, 1, 0): \
+ ret = _mm_shuffle_ps_3210((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(0, 0, 1, 1): \
+ ret = _mm_shuffle_ps_0011((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(0, 0, 2, 2): \
+ ret = _mm_shuffle_ps_0022((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(2, 2, 0, 0): \
+ ret = _mm_shuffle_ps_2200((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(3, 2, 0, 2): \
+ ret = _mm_shuffle_ps_3202((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(3, 2, 3, 2): \
+ ret = _mm_movehl_ps((b), (a)); \
+ break; \
+ case _MM_SHUFFLE(1, 1, 3, 3): \
+ ret = _mm_shuffle_ps_1133((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(2, 0, 1, 0): \
+ ret = _mm_shuffle_ps_2010((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(2, 0, 0, 1): \
+ ret = _mm_shuffle_ps_2001((a), (b)); \
+ break; \
+ case _MM_SHUFFLE(2, 0, 3, 2): \
+ ret = _mm_shuffle_ps_2032((a), (b)); \
+ break; \
+ default: \
+ ret = _mm_shuffle_ps_default((a), (b), (imm)); \
+ break; \
+ } \
+ ret; \
+ })
+#endif
+
+// Takes the upper 64 bits of a and places it in the low end of the result
+// Takes the lower 64 bits of a and places it into the high end of the result.
+FORCE_INLINE __m128i _mm_shuffle_epi_1032(__m128i a)
+{
+ int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a));
+ int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
+ return vreinterpretq_m128i_s32(vcombine_s32(a32, a10));
+}
+
+// takes the lower two 32-bit values from a and swaps them and places in low end
+// of result takes the higher two 32 bit values from a and swaps them and places
+// in high end of result.
+FORCE_INLINE __m128i _mm_shuffle_epi_2301(__m128i a)
+{
+ int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
+ int32x2_t a23 = vrev64_s32(vget_high_s32(vreinterpretq_s32_m128i(a)));
+ return vreinterpretq_m128i_s32(vcombine_s32(a01, a23));
+}
+
+// rotates the least significant 32 bits into the most signficant 32 bits, and
+// shifts the rest down
+FORCE_INLINE __m128i _mm_shuffle_epi_0321(__m128i a)
+{
+ return vreinterpretq_m128i_s32(
+ vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 1));
+}
+
+// rotates the most significant 32 bits into the least signficant 32 bits, and
+// shifts the rest up
+FORCE_INLINE __m128i _mm_shuffle_epi_2103(__m128i a)
+{
+ return vreinterpretq_m128i_s32(
+ vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 3));
+}
+
+// gets the lower 64 bits of a, and places it in the upper 64 bits
+// gets the lower 64 bits of a and places it in the lower 64 bits
+FORCE_INLINE __m128i _mm_shuffle_epi_1010(__m128i a)
+{
+ int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
+ return vreinterpretq_m128i_s32(vcombine_s32(a10, a10));
+}
+
+// gets the lower 64 bits of a, swaps the 0 and 1 elements, and places it in the
+// lower 64 bits gets the lower 64 bits of a, and places it in the upper 64 bits
+FORCE_INLINE __m128i _mm_shuffle_epi_1001(__m128i a)
+{
+ int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
+ int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
+ return vreinterpretq_m128i_s32(vcombine_s32(a01, a10));
+}
+
+// gets the lower 64 bits of a, swaps the 0 and 1 elements and places it in the
+// upper 64 bits gets the lower 64 bits of a, swaps the 0 and 1 elements, and
+// places it in the lower 64 bits
+FORCE_INLINE __m128i _mm_shuffle_epi_0101(__m128i a)
+{
+ int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
+ return vreinterpretq_m128i_s32(vcombine_s32(a01, a01));
+}
+
+FORCE_INLINE __m128i _mm_shuffle_epi_2211(__m128i a)
+{
+ int32x2_t a11 = vdup_lane_s32(vget_low_s32(vreinterpretq_s32_m128i(a)), 1);
+ int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0);
+ return vreinterpretq_m128i_s32(vcombine_s32(a11, a22));
+}
+
+FORCE_INLINE __m128i _mm_shuffle_epi_0122(__m128i a)
+{
+ int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0);
+ int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
+ return vreinterpretq_m128i_s32(vcombine_s32(a22, a01));
+}
+
+FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a)
+{
+ int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a));
+ int32x2_t a33 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 1);
+ return vreinterpretq_m128i_s32(vcombine_s32(a32, a33));
+}
+
+// Shuffle packed 8-bit integers in a according to shuffle control mask in the
+// corresponding 8-bit element of b, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_epi8
+FORCE_INLINE __m128i _mm_shuffle_epi8(__m128i a, __m128i b)
+{
+ int8x16_t tbl = vreinterpretq_s8_m128i(a); // input a
+ uint8x16_t idx = vreinterpretq_u8_m128i(b); // input b
+ uint8x16_t idx_masked =
+ vandq_u8(idx, vdupq_n_u8(0x8F)); // avoid using meaningless bits
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s8(vqtbl1q_s8(tbl, idx_masked));
+#elif defined(__GNUC__)
+ int8x16_t ret;
+ // %e and %f represent the even and odd D registers
+ // respectively.
+ __asm__ __volatile__(
+ "vtbl.8 %e[ret], {%e[tbl], %f[tbl]}, %e[idx]\n"
+ "vtbl.8 %f[ret], {%e[tbl], %f[tbl]}, %f[idx]\n"
+ : [ret] "=&w"(ret)
+ : [tbl] "w"(tbl), [idx] "w"(idx_masked));
+ return vreinterpretq_m128i_s8(ret);
+#else
+ // use this line if testing on aarch64
+ int8x8x2_t a_split = {vget_low_s8(tbl), vget_high_s8(tbl)};
+ return vreinterpretq_m128i_s8(
+ vcombine_s8(vtbl2_s8(a_split, vget_low_u8(idx_masked)),
+ vtbl2_s8(a_split, vget_high_u8(idx_masked))));
+#endif
+}
+
+// C equivalent:
+// __m128i _mm_shuffle_epi32_default(__m128i a,
+// __constrange(0, 255) int imm) {
+// __m128i ret;
+// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3];
+// ret[2] = a[(imm >> 4) & 0x03]; ret[3] = a[(imm >> 6) & 0x03];
+// return ret;
+// }
+#define _mm_shuffle_epi32_default(a, imm) \
+ __extension__({ \
+ int32x4_t ret; \
+ ret = vmovq_n_s32( \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & (0x3))); \
+ ret = vsetq_lane_s32( \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), \
+ ret, 1); \
+ ret = vsetq_lane_s32( \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), \
+ ret, 2); \
+ ret = vsetq_lane_s32( \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), \
+ ret, 3); \
+ vreinterpretq_m128i_s32(ret); \
+ })
+
+// FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a, __constrange(0,255)
+// int imm)
+#if defined(__aarch64__)
+#define _mm_shuffle_epi32_splat(a, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s32( \
+ vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \
+ })
+#else
+#define _mm_shuffle_epi32_splat(a, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s32( \
+ vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \
+ })
+#endif
+
+// Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm.
+// https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx
+// FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i a,
+// __constrange(0,255) int imm)
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shuffle_epi32(a, imm) \
+ __extension__({ \
+ int32x4_t _input = vreinterpretq_s32_m128i(a); \
+ int32x4_t _shuf = __builtin_shufflevector( \
+ _input, _input, (imm) & (0x3), ((imm) >> 2) & 0x3, \
+ ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3); \
+ vreinterpretq_m128i_s32(_shuf); \
+ })
+#else // generic
+#define _mm_shuffle_epi32(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ switch (imm) { \
+ case _MM_SHUFFLE(1, 0, 3, 2): \
+ ret = _mm_shuffle_epi_1032((a)); \
+ break; \
+ case _MM_SHUFFLE(2, 3, 0, 1): \
+ ret = _mm_shuffle_epi_2301((a)); \
+ break; \
+ case _MM_SHUFFLE(0, 3, 2, 1): \
+ ret = _mm_shuffle_epi_0321((a)); \
+ break; \
+ case _MM_SHUFFLE(2, 1, 0, 3): \
+ ret = _mm_shuffle_epi_2103((a)); \
+ break; \
+ case _MM_SHUFFLE(1, 0, 1, 0): \
+ ret = _mm_shuffle_epi_1010((a)); \
+ break; \
+ case _MM_SHUFFLE(1, 0, 0, 1): \
+ ret = _mm_shuffle_epi_1001((a)); \
+ break; \
+ case _MM_SHUFFLE(0, 1, 0, 1): \
+ ret = _mm_shuffle_epi_0101((a)); \
+ break; \
+ case _MM_SHUFFLE(2, 2, 1, 1): \
+ ret = _mm_shuffle_epi_2211((a)); \
+ break; \
+ case _MM_SHUFFLE(0, 1, 2, 2): \
+ ret = _mm_shuffle_epi_0122((a)); \
+ break; \
+ case _MM_SHUFFLE(3, 3, 3, 2): \
+ ret = _mm_shuffle_epi_3332((a)); \
+ break; \
+ case _MM_SHUFFLE(0, 0, 0, 0): \
+ ret = _mm_shuffle_epi32_splat((a), 0); \
+ break; \
+ case _MM_SHUFFLE(1, 1, 1, 1): \
+ ret = _mm_shuffle_epi32_splat((a), 1); \
+ break; \
+ case _MM_SHUFFLE(2, 2, 2, 2): \
+ ret = _mm_shuffle_epi32_splat((a), 2); \
+ break; \
+ case _MM_SHUFFLE(3, 3, 3, 3): \
+ ret = _mm_shuffle_epi32_splat((a), 3); \
+ break; \
+ default: \
+ ret = _mm_shuffle_epi32_default((a), (imm)); \
+ break; \
+ } \
+ ret; \
+ })
+#endif
+
+// Shuffles the lower 4 signed or unsigned 16-bit integers in a as specified
+// by imm.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/y41dkk37(v=vs.100)
+// FORCE_INLINE __m128i _mm_shufflelo_epi16_function(__m128i a,
+// __constrange(0,255) int
+// imm)
+#define _mm_shufflelo_epi16_function(a, imm) \
+ __extension__({ \
+ int16x8_t ret = vreinterpretq_s16_m128i(a); \
+ int16x4_t lowBits = vget_low_s16(ret); \
+ ret = vsetq_lane_s16(vget_lane_s16(lowBits, (imm) & (0x3)), ret, 0); \
+ ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 2) & 0x3), ret, \
+ 1); \
+ ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 4) & 0x3), ret, \
+ 2); \
+ ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 6) & 0x3), ret, \
+ 3); \
+ vreinterpretq_m128i_s16(ret); \
+ })
+
+// FORCE_INLINE __m128i _mm_shufflelo_epi16(__m128i a,
+// __constrange(0,255) int imm)
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shufflelo_epi16(a, imm) \
+ __extension__({ \
+ int16x8_t _input = vreinterpretq_s16_m128i(a); \
+ int16x8_t _shuf = __builtin_shufflevector( \
+ _input, _input, ((imm) & (0x3)), (((imm) >> 2) & 0x3), \
+ (((imm) >> 4) & 0x3), (((imm) >> 6) & 0x3), 4, 5, 6, 7); \
+ vreinterpretq_m128i_s16(_shuf); \
+ })
+#else // generic
+#define _mm_shufflelo_epi16(a, imm) _mm_shufflelo_epi16_function((a), (imm))
+#endif
+
+// Shuffles the upper 4 signed or unsigned 16-bit integers in a as specified
+// by imm.
+// https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx
+// FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a,
+// __constrange(0,255) int
+// imm)
+#define _mm_shufflehi_epi16_function(a, imm) \
+ __extension__({ \
+ int16x8_t ret = vreinterpretq_s16_m128i(a); \
+ int16x4_t highBits = vget_high_s16(ret); \
+ ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & (0x3)), ret, 4); \
+ ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 2) & 0x3), ret, \
+ 5); \
+ ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, \
+ 6); \
+ ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, \
+ 7); \
+ vreinterpretq_m128i_s16(ret); \
+ })
+
+// FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i a,
+// __constrange(0,255) int imm)
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shufflehi_epi16(a, imm) \
+ __extension__({ \
+ int16x8_t _input = vreinterpretq_s16_m128i(a); \
+ int16x8_t _shuf = __builtin_shufflevector( \
+ _input, _input, 0, 1, 2, 3, ((imm) & (0x3)) + 4, \
+ (((imm) >> 2) & 0x3) + 4, (((imm) >> 4) & 0x3) + 4, \
+ (((imm) >> 6) & 0x3) + 4); \
+ vreinterpretq_m128i_s16(_shuf); \
+ })
+#else // generic
+#define _mm_shufflehi_epi16(a, imm) _mm_shufflehi_epi16_function((a), (imm))
+#endif
+
+// Shuffle double-precision (64-bit) floating-point elements using the control
+// in imm8, and store the results in dst.
+//
+// dst[63:0] := (imm8[0] == 0) ? a[63:0] : a[127:64]
+// dst[127:64] := (imm8[1] == 0) ? b[63:0] : b[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pd
+#if __has_builtin(__builtin_shufflevector)
+#define _mm_shuffle_pd(a, b, imm8) \
+ vreinterpretq_m128d_s64(__builtin_shufflevector( \
+ vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b), imm8 & 0x1, \
+ ((imm8 & 0x2) >> 1) + 2))
+#else
+#define _mm_shuffle_pd(a, b, imm8) \
+ _mm_castsi128_pd(_mm_set_epi64x( \
+ vgetq_lane_s64(vreinterpretq_s64_m128d(b), (imm8 & 0x2) >> 1), \
+ vgetq_lane_s64(vreinterpretq_s64_m128d(a), imm8 & 0x1)))
+#endif
+
+// Blend packed 16-bit integers from a and b using control mask imm8, and store
+// the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF imm8[j]
+// dst[i+15:i] := b[i+15:i]
+// ELSE
+// dst[i+15:i] := a[i+15:i]
+// FI
+// ENDFOR
+// FORCE_INLINE __m128i _mm_blend_epi16(__m128i a, __m128i b,
+// __constrange(0,255) int imm)
+#define _mm_blend_epi16(a, b, imm) \
+ __extension__({ \
+ const uint16_t _mask[8] = {((imm) & (1 << 0)) ? 0xFFFF : 0x0000, \
+ ((imm) & (1 << 1)) ? 0xFFFF : 0x0000, \
+ ((imm) & (1 << 2)) ? 0xFFFF : 0x0000, \
+ ((imm) & (1 << 3)) ? 0xFFFF : 0x0000, \
+ ((imm) & (1 << 4)) ? 0xFFFF : 0x0000, \
+ ((imm) & (1 << 5)) ? 0xFFFF : 0x0000, \
+ ((imm) & (1 << 6)) ? 0xFFFF : 0x0000, \
+ ((imm) & (1 << 7)) ? 0xFFFF : 0x0000}; \
+ uint16x8_t _mask_vec = vld1q_u16(_mask); \
+ uint16x8_t _a = vreinterpretq_u16_m128i(a); \
+ uint16x8_t _b = vreinterpretq_u16_m128i(b); \
+ vreinterpretq_m128i_u16(vbslq_u16(_mask_vec, _b, _a)); \
+ })
+
+// Blend packed 8-bit integers from a and b using mask, and store the results in
+// dst.
+//
+// FOR j := 0 to 15
+// i := j*8
+// IF mask[i+7]
+// dst[i+7:i] := b[i+7:i]
+// ELSE
+// dst[i+7:i] := a[i+7:i]
+// FI
+// ENDFOR
+FORCE_INLINE __m128i _mm_blendv_epi8(__m128i _a, __m128i _b, __m128i _mask)
+{
+ // Use a signed shift right to create a mask with the sign bit
+ uint8x16_t mask =
+ vreinterpretq_u8_s8(vshrq_n_s8(vreinterpretq_s8_m128i(_mask), 7));
+ uint8x16_t a = vreinterpretq_u8_m128i(_a);
+ uint8x16_t b = vreinterpretq_u8_m128i(_b);
+ return vreinterpretq_m128i_u8(vbslq_u8(mask, b, a));
+}
+
+/* Shifts */
+
+
+// Shift packed 16-bit integers in a right by imm while shifting in sign
+// bits, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi16
+FORCE_INLINE __m128i _mm_srai_epi16(__m128i a, int imm)
+{
+ const int count = (imm & ~15) ? 15 : imm;
+ return (__m128i) vshlq_s16((int16x8_t) a, vdupq_n_s16(-count));
+}
+
+// Shifts the 8 signed or unsigned 16-bit integers in a left by count bits while
+// shifting in zeros.
+//
+// r0 := a0 << count
+// r1 := a1 << count
+// ...
+// r7 := a7 << count
+//
+// https://msdn.microsoft.com/en-us/library/es73bcsy(v=vs.90).aspx
+#define _mm_slli_epi16(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (unlikely((imm)) <= 0) { \
+ ret = a; \
+ } \
+ if (unlikely((imm) > 15)) { \
+ ret = _mm_setzero_si128(); \
+ } else { \
+ ret = vreinterpretq_m128i_s16( \
+ vshlq_n_s16(vreinterpretq_s16_m128i(a), (imm))); \
+ } \
+ ret; \
+ })
+
+// Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while
+// shifting in zeros. :
+// https://msdn.microsoft.com/en-us/library/z2k3bbtb%28v=vs.90%29.aspx
+// FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, __constrange(0,255) int imm)
+FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, int imm)
+{
+ if (unlikely(imm <= 0)) /* TODO: add constant range macro: [0, 255] */
+ return a;
+ if (unlikely(imm > 31))
+ return _mm_setzero_si128();
+ return vreinterpretq_m128i_s32(
+ vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(imm)));
+}
+
+// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and
+// store the results in dst.
+FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
+{
+ if (unlikely(imm <= 0)) /* TODO: add constant range macro: [0, 255] */
+ return a;
+ if (unlikely(imm > 63))
+ return _mm_setzero_si128();
+ return vreinterpretq_m128i_s64(
+ vshlq_s64(vreinterpretq_s64_m128i(a), vdupq_n_s64(imm)));
+}
+
+// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// IF imm8[7:0] > 15
+// dst[i+15:i] := 0
+// ELSE
+// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi16
+#define _mm_srli_epi16(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (unlikely(imm) == 0) { \
+ ret = a; \
+ } \
+ if (likely(0 < (imm) && (imm) < 16)) { \
+ ret = vreinterpretq_m128i_u16( \
+ vshlq_u16(vreinterpretq_u16_m128i(a), vdupq_n_s16(-imm))); \
+ } else { \
+ ret = _mm_setzero_si128(); \
+ } \
+ ret; \
+ })
+
+// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*32
+// IF imm8[7:0] > 31
+// dst[i+31:i] := 0
+// ELSE
+// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi32
+// FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, __constrange(0,255) int imm)
+#define _mm_srli_epi32(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (unlikely((imm) == 0)) { \
+ ret = a; \
+ } \
+ if (likely(0 < (imm) && (imm) < 32)) { \
+ ret = vreinterpretq_m128i_u32( \
+ vshlq_u32(vreinterpretq_u32_m128i(a), vdupq_n_s32(-imm))); \
+ } else { \
+ ret = _mm_setzero_si128(); \
+ } \
+ ret; \
+ })
+
+// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and
+// store the results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// IF imm8[7:0] > 63
+// dst[i+63:i] := 0
+// ELSE
+// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi64
+#define _mm_srli_epi64(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (unlikely((imm) == 0)) { \
+ ret = a; \
+ } \
+ if (likely(0 < (imm) && (imm) < 64)) { \
+ ret = vreinterpretq_m128i_u64( \
+ vshlq_u64(vreinterpretq_u64_m128i(a), vdupq_n_s64(-imm))); \
+ } else { \
+ ret = _mm_setzero_si128(); \
+ } \
+ ret; \
+ })
+
+// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits,
+// and store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*32
+// IF imm8[7:0] > 31
+// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0)
+// ELSE
+// dst[i+31:i] := SignExtend32(a[i+31:i] >> imm8[7:0])
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi32
+// FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, __constrange(0,255) int imm)
+#define _mm_srai_epi32(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (unlikely((imm) == 0)) { \
+ ret = a; \
+ } \
+ if (likely(0 < (imm) && (imm) < 32)) { \
+ ret = vreinterpretq_m128i_s32( \
+ vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(-imm))); \
+ } else { \
+ ret = vreinterpretq_m128i_s32( \
+ vshrq_n_s32(vreinterpretq_s32_m128i(a), 31)); \
+ } \
+ ret; \
+ })
+
+// Shifts the 128 - bit value in a right by imm bytes while shifting in
+// zeros.imm must be an immediate.
+//
+// r := srl(a, imm*8)
+//
+// https://msdn.microsoft.com/en-us/library/305w28yz(v=vs.100).aspx
+// FORCE_INLINE _mm_srli_si128(__m128i a, __constrange(0,255) int imm)
+#define _mm_srli_si128(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (unlikely((imm) <= 0)) { \
+ ret = a; \
+ } \
+ if (unlikely((imm) > 15)) { \
+ ret = _mm_setzero_si128(); \
+ } else { \
+ ret = vreinterpretq_m128i_s8( \
+ vextq_s8(vreinterpretq_s8_m128i(a), vdupq_n_s8(0), (imm))); \
+ } \
+ ret; \
+ })
+
+// Shifts the 128-bit value in a left by imm bytes while shifting in zeros. imm
+// must be an immediate.
+//
+// r := a << (imm * 8)
+//
+// https://msdn.microsoft.com/en-us/library/34d3k2kt(v=vs.100).aspx
+// FORCE_INLINE __m128i _mm_slli_si128(__m128i a, __constrange(0,255) int imm)
+#define _mm_slli_si128(a, imm) \
+ __extension__({ \
+ __m128i ret; \
+ if (unlikely((imm) <= 0)) { \
+ ret = a; \
+ } \
+ if (unlikely((imm) > 15)) { \
+ ret = _mm_setzero_si128(); \
+ } else { \
+ ret = vreinterpretq_m128i_s8(vextq_s8( \
+ vdupq_n_s8(0), vreinterpretq_s8_m128i(a), 16 - (imm))); \
+ } \
+ ret; \
+ })
+
+// Shifts the 8 signed or unsigned 16-bit integers in a left by count bits while
+// shifting in zeros.
+//
+// r0 := a0 << count
+// r1 := a1 << count
+// ...
+// r7 := a7 << count
+//
+// https://msdn.microsoft.com/en-us/library/c79w388h(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_sll_epi16(__m128i a, __m128i count)
+{
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (unlikely(c > 15))
+ return _mm_setzero_si128();
+
+ int16x8_t vc = vdupq_n_s16((int16_t) c);
+ return vreinterpretq_m128i_s16(vshlq_s16(vreinterpretq_s16_m128i(a), vc));
+}
+
+// Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while
+// shifting in zeros.
+//
+// r0 := a0 << count
+// r1 := a1 << count
+// r2 := a2 << count
+// r3 := a3 << count
+//
+// https://msdn.microsoft.com/en-us/library/6fe5a6s9(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_sll_epi32(__m128i a, __m128i count)
+{
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (unlikely(c > 31))
+ return _mm_setzero_si128();
+
+ int32x4_t vc = vdupq_n_s32((int32_t) c);
+ return vreinterpretq_m128i_s32(vshlq_s32(vreinterpretq_s32_m128i(a), vc));
+}
+
+// Shifts the 2 signed or unsigned 64-bit integers in a left by count bits while
+// shifting in zeros.
+//
+// r0 := a0 << count
+// r1 := a1 << count
+//
+// https://msdn.microsoft.com/en-us/library/6ta9dffd(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_sll_epi64(__m128i a, __m128i count)
+{
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (unlikely(c > 63))
+ return _mm_setzero_si128();
+
+ int64x2_t vc = vdupq_n_s64((int64_t) c);
+ return vreinterpretq_m128i_s64(vshlq_s64(vreinterpretq_s64_m128i(a), vc));
+}
+
+// Shifts the 8 signed or unsigned 16-bit integers in a right by count bits
+// while shifting in zeros.
+//
+// r0 := srl(a0, count)
+// r1 := srl(a1, count)
+// ...
+// r7 := srl(a7, count)
+//
+// https://msdn.microsoft.com/en-us/library/wd5ax830(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_srl_epi16(__m128i a, __m128i count)
+{
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (unlikely(c > 15))
+ return _mm_setzero_si128();
+
+ int16x8_t vc = vdupq_n_s16(-(int16_t) c);
+ return vreinterpretq_m128i_u16(vshlq_u16(vreinterpretq_u16_m128i(a), vc));
+}
+
+// Shifts the 4 signed or unsigned 32-bit integers in a right by count bits
+// while shifting in zeros.
+//
+// r0 := srl(a0, count)
+// r1 := srl(a1, count)
+// r2 := srl(a2, count)
+// r3 := srl(a3, count)
+//
+// https://msdn.microsoft.com/en-us/library/a9cbttf4(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_srl_epi32(__m128i a, __m128i count)
+{
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (unlikely(c > 31))
+ return _mm_setzero_si128();
+
+ int32x4_t vc = vdupq_n_s32(-(int32_t) c);
+ return vreinterpretq_m128i_u32(vshlq_u32(vreinterpretq_u32_m128i(a), vc));
+}
+
+// Shifts the 2 signed or unsigned 64-bit integers in a right by count bits
+// while shifting in zeros.
+//
+// r0 := srl(a0, count)
+// r1 := srl(a1, count)
+//
+// https://msdn.microsoft.com/en-us/library/yf6cf9k8(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_srl_epi64(__m128i a, __m128i count)
+{
+ uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
+ if (unlikely(c > 63))
+ return _mm_setzero_si128();
+
+ int64x2_t vc = vdupq_n_s64(-(int64_t) c);
+ return vreinterpretq_m128i_u64(vshlq_u64(vreinterpretq_u64_m128i(a), vc));
+}
+
+// NEON does not provide a version of this function.
+// Creates a 16-bit mask from the most significant bits of the 16 signed or
+// unsigned 8-bit integers in a and zero extends the upper bits.
+// https://msdn.microsoft.com/en-us/library/vstudio/s090c8fk(v=vs.100).aspx
+FORCE_INLINE int _mm_movemask_epi8(__m128i a)
+{
+ // Use increasingly wide shifts+adds to collect the sign bits
+ // together.
+ // Since the widening shifts would be rather confusing to follow in little
+ // endian, everything will be illustrated in big endian order instead. This
+ // has a different result - the bits would actually be reversed on a big
+ // endian machine.
+
+ // Starting input (only half the elements are shown):
+ // 89 ff 1d c0 00 10 99 33
+ uint8x16_t input = vreinterpretq_u8_m128i(a);
+
+ // Shift out everything but the sign bits with an unsigned shift right.
+ //
+ // Bytes of the vector::
+ // 89 ff 1d c0 00 10 99 33
+ // \ \ \ \ \ \ \ \ high_bits = (uint16x4_t)(input >> 7)
+ // | | | | | | | |
+ // 01 01 00 01 00 00 01 00
+ //
+ // Bits of first important lane(s):
+ // 10001001 (89)
+ // \______
+ // |
+ // 00000001 (01)
+ uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(input, 7));
+
+ // Merge the even lanes together with a 16-bit unsigned shift right + add.
+ // 'xx' represents garbage data which will be ignored in the final result.
+ // In the important bytes, the add functions like a binary OR.
+ //
+ // 01 01 00 01 00 00 01 00
+ // \_ | \_ | \_ | \_ | paired16 = (uint32x4_t)(input + (input >> 7))
+ // \| \| \| \|
+ // xx 03 xx 01 xx 00 xx 02
+ //
+ // 00000001 00000001 (01 01)
+ // \_______ |
+ // \|
+ // xxxxxxxx xxxxxx11 (xx 03)
+ uint32x4_t paired16 =
+ vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7));
+
+ // Repeat with a wider 32-bit shift + add.
+ // xx 03 xx 01 xx 00 xx 02
+ // \____ | \____ | paired32 = (uint64x1_t)(paired16 + (paired16 >>
+ // 14))
+ // \| \|
+ // xx xx xx 0d xx xx xx 02
+ //
+ // 00000011 00000001 (03 01)
+ // \\_____ ||
+ // '----.\||
+ // xxxxxxxx xxxx1101 (xx 0d)
+ uint64x2_t paired32 =
+ vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14));
+
+ // Last, an even wider 64-bit shift + add to get our result in the low 8 bit
+ // lanes. xx xx xx 0d xx xx xx 02
+ // \_________ | paired64 = (uint8x8_t)(paired32 + (paired32 >>
+ // 28))
+ // \|
+ // xx xx xx xx xx xx xx d2
+ //
+ // 00001101 00000010 (0d 02)
+ // \ \___ | |
+ // '---. \| |
+ // xxxxxxxx 11010010 (xx d2)
+ uint8x16_t paired64 =
+ vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28));
+
+ // Extract the low 8 bits from each 64-bit lane with 2 8-bit extracts.
+ // xx xx xx xx xx xx xx d2
+ // || return paired64[0]
+ // d2
+ // Note: Little endian would return the correct value 4b (01001011) instead.
+ return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8);
+}
+
+// Copy the lower 64-bit integer in a to dst.
+//
+// dst[63:0] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi64_pi64
+FORCE_INLINE __m64 _mm_movepi64_pi64(__m128i a)
+{
+ return vreinterpret_m64_s64(vget_low_s64(vreinterpretq_s64_m128i(a)));
+}
+
+// Copy the 64-bit integer a to the lower element of dst, and zero the upper
+// element.
+//
+// dst[63:0] := a[63:0]
+// dst[127:64] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movpi64_epi64
+FORCE_INLINE __m128i _mm_movpi64_epi64(__m64 a)
+{
+ return vreinterpretq_m128i_s64(
+ vcombine_s64(vreinterpret_s64_m64(a), vdup_n_s64(0)));
+}
+
+// NEON does not provide this method
+// Creates a 4-bit mask from the most significant bits of the four
+// single-precision, floating-point values.
+// https://msdn.microsoft.com/en-us/library/vstudio/4490ys29(v=vs.100).aspx
+FORCE_INLINE int _mm_movemask_ps(__m128 a)
+{
+ uint32x4_t input = vreinterpretq_u32_m128(a);
+#if defined(__aarch64__)
+ static const int32x4_t shift = {0, 1, 2, 3};
+ uint32x4_t tmp = vshrq_n_u32(input, 31);
+ return vaddvq_u32(vshlq_u32(tmp, shift));
+#else
+ // Uses the exact same method as _mm_movemask_epi8, see that for details.
+ // Shift out everything but the sign bits with a 32-bit unsigned shift
+ // right.
+ uint64x2_t high_bits = vreinterpretq_u64_u32(vshrq_n_u32(input, 31));
+ // Merge the two pairs together with a 64-bit unsigned shift right + add.
+ uint8x16_t paired =
+ vreinterpretq_u8_u64(vsraq_n_u64(high_bits, high_bits, 31));
+ // Extract the result.
+ return vgetq_lane_u8(paired, 0) | (vgetq_lane_u8(paired, 8) << 2);
+#endif
+}
+
+// Compute the bitwise NOT of a and then AND with a 128-bit vector containing
+// all 1's, and return 1 if the result is zero, otherwise return 0.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_ones
+FORCE_INLINE int _mm_test_all_ones(__m128i a)
+{
+ return (uint64_t)(vgetq_lane_s64(a, 0) & vgetq_lane_s64(a, 1)) ==
+ ~(uint64_t) 0;
+}
+
+// Compute the bitwise AND of 128 bits (representing integer data) in a and
+// mask, and return 1 if the result is zero, otherwise return 0.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_zeros
+FORCE_INLINE int _mm_test_all_zeros(__m128i a, __m128i mask)
+{
+ int64x2_t a_and_mask =
+ vandq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(mask));
+ return (vgetq_lane_s64(a_and_mask, 0) | vgetq_lane_s64(a_and_mask, 1)) ? 0
+ : 1;
+}
+
+/* Math operations */
+
+// Subtracts the four single-precision, floating-point values of a and b.
+//
+// r0 := a0 - b0
+// r1 := a1 - b1
+// r2 := a2 - b2
+// r3 := a3 - b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/1zad2k61(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_f32(
+ vsubq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Subtract the lower single-precision (32-bit) floating-point element in b from
+// the lower single-precision (32-bit) floating-point element in a, store the
+// result in the lower element of dst, and copy the upper 3 packed elements from
+// a to the upper elements of dst.
+//
+// dst[31:0] := a[31:0] - b[31:0]
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_ss
+FORCE_INLINE __m128 _mm_sub_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_sub_ps(a, b));
+}
+
+// Subtract 2 packed 64-bit integers in b from 2 packed 64-bit integers in a,
+// and store the results in dst.
+// r0 := a0 - b0
+// r1 := a1 - b1
+FORCE_INLINE __m128i _mm_sub_epi64(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s64(
+ vsubq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
+}
+
+// Subtracts the 4 signed or unsigned 32-bit integers of b from the 4 signed or
+// unsigned 32-bit integers of a.
+//
+// r0 := a0 - b0
+// r1 := a1 - b1
+// r2 := a2 - b2
+// r3 := a3 - b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/fhh866h0(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_sub_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vsubq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Subtract packed 16-bit integers in b from packed 16-bit integers in a, and
+// store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_epi16
+FORCE_INLINE __m128i _mm_sub_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Subtract packed 8-bit integers in b from packed 8-bit integers in a, and
+// store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_epi8
+FORCE_INLINE __m128i _mm_sub_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Subtract 64-bit integer b from 64-bit integer a, and store the result in dst.
+//
+// dst[63:0] := a[63:0] - b[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_si64
+FORCE_INLINE __m64 _mm_sub_si64(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s64(
+ vsub_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b)));
+}
+
+// Subtracts the 8 unsigned 16-bit integers of bfrom the 8 unsigned 16-bit
+// integers of a and saturates..
+// https://technet.microsoft.com/en-us/subscriptions/index/f44y0s19(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_subs_epu16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vqsubq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+}
+
+// Subtracts the 16 unsigned 8-bit integers of b from the 16 unsigned 8-bit
+// integers of a and saturates.
+//
+// r0 := UnsignedSaturate(a0 - b0)
+// r1 := UnsignedSaturate(a1 - b1)
+// ...
+// r15 := UnsignedSaturate(a15 - b15)
+//
+// https://technet.microsoft.com/en-us/subscriptions/yadkxc18(v=vs.90)
+FORCE_INLINE __m128i _mm_subs_epu8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vqsubq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+}
+
+// Subtracts the 16 signed 8-bit integers of b from the 16 signed 8-bit integers
+// of a and saturates.
+//
+// r0 := SignedSaturate(a0 - b0)
+// r1 := SignedSaturate(a1 - b1)
+// ...
+// r15 := SignedSaturate(a15 - b15)
+//
+// https://technet.microsoft.com/en-us/subscriptions/by7kzks1(v=vs.90)
+FORCE_INLINE __m128i _mm_subs_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vqsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Subtracts the 8 signed 16-bit integers of b from the 8 signed 16-bit integers
+// of a and saturates.
+//
+// r0 := SignedSaturate(a0 - b0)
+// r1 := SignedSaturate(a1 - b1)
+// ...
+// r7 := SignedSaturate(a7 - b7)
+//
+// https://technet.microsoft.com/en-us/subscriptions/3247z5b8(v=vs.90)
+FORCE_INLINE __m128i _mm_subs_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vqsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Subtract packed double-precision (64-bit) floating-point elements in b from
+// packed double-precision (64-bit) floating-point elements in a, and store the
+// results in dst.
+//
+// FOR j := 0 to 1
+// i := j*64
+// dst[i+63:i] := a[i+63:i] - b[i+63:i]
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_sub_pd
+FORCE_INLINE __m128d _mm_sub_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vsubq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] - db[0];
+ c[1] = da[1] - db[1];
+ return vld1q_f32((float32_t *) c);
+#endif
+}
+
+// Subtract the lower double-precision (64-bit) floating-point element in b from
+// the lower double-precision (64-bit) floating-point element in a, store the
+// result in the lower element of dst, and copy the upper element from a to the
+// upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_sd
+FORCE_INLINE __m128d _mm_sub_sd(__m128d a, __m128d b)
+{
+ return _mm_move_sd(a, _mm_sub_pd(a, b));
+}
+
+// Add packed unsigned 16-bit integers in a and b using saturation, and store
+// the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epu16
+FORCE_INLINE __m128i _mm_adds_epu16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vqaddq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+}
+
+// Negate packed 8-bit integers in a when the corresponding signed
+// 8-bit integer in b is negative, and store the results in dst.
+// Element in dst are zeroed out when the corresponding element
+// in b is zero.
+//
+// for i in 0..15
+// if b[i] < 0
+// r[i] := -a[i]
+// else if b[i] == 0
+// r[i] := 0
+// else
+// r[i] := a[i]
+// fi
+// done
+FORCE_INLINE __m128i _mm_sign_epi8(__m128i _a, __m128i _b)
+{
+ int8x16_t a = vreinterpretq_s8_m128i(_a);
+ int8x16_t b = vreinterpretq_s8_m128i(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFF : 0
+ uint8x16_t ltMask = vreinterpretq_u8_s8(vshrq_n_s8(b, 7));
+
+ // (b == 0) ? 0xFF : 0
+#if defined(__aarch64__)
+ int8x16_t zeroMask = vreinterpretq_s8_u8(vceqzq_s8(b));
+#else
+ int8x16_t zeroMask = vreinterpretq_s8_u8(vceqq_s8(b, vdupq_n_s8(0)));
+#endif
+
+ // bitwise select either a or nagative 'a' (vnegq_s8(a) return nagative 'a')
+ // based on ltMask
+ int8x16_t masked = vbslq_s8(ltMask, vnegq_s8(a), a);
+ // res = masked & (~zeroMask)
+ int8x16_t res = vbicq_s8(masked, zeroMask);
+
+ return vreinterpretq_m128i_s8(res);
+}
+
+// Negate packed 16-bit integers in a when the corresponding signed
+// 16-bit integer in b is negative, and store the results in dst.
+// Element in dst are zeroed out when the corresponding element
+// in b is zero.
+//
+// for i in 0..7
+// if b[i] < 0
+// r[i] := -a[i]
+// else if b[i] == 0
+// r[i] := 0
+// else
+// r[i] := a[i]
+// fi
+// done
+FORCE_INLINE __m128i _mm_sign_epi16(__m128i _a, __m128i _b)
+{
+ int16x8_t a = vreinterpretq_s16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFFFF : 0
+ uint16x8_t ltMask = vreinterpretq_u16_s16(vshrq_n_s16(b, 15));
+ // (b == 0) ? 0xFFFF : 0
+#if defined(__aarch64__)
+ int16x8_t zeroMask = vreinterpretq_s16_u16(vceqzq_s16(b));
+#else
+ int16x8_t zeroMask = vreinterpretq_s16_u16(vceqq_s16(b, vdupq_n_s16(0)));
+#endif
+
+ // bitwise select either a or negative 'a' (vnegq_s16(a) equals to negative
+ // 'a') based on ltMask
+ int16x8_t masked = vbslq_s16(ltMask, vnegq_s16(a), a);
+ // res = masked & (~zeroMask)
+ int16x8_t res = vbicq_s16(masked, zeroMask);
+ return vreinterpretq_m128i_s16(res);
+}
+
+// Negate packed 32-bit integers in a when the corresponding signed
+// 32-bit integer in b is negative, and store the results in dst.
+// Element in dst are zeroed out when the corresponding element
+// in b is zero.
+//
+// for i in 0..3
+// if b[i] < 0
+// r[i] := -a[i]
+// else if b[i] == 0
+// r[i] := 0
+// else
+// r[i] := a[i]
+// fi
+// done
+FORCE_INLINE __m128i _mm_sign_epi32(__m128i _a, __m128i _b)
+{
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFFFFFFFF : 0
+ uint32x4_t ltMask = vreinterpretq_u32_s32(vshrq_n_s32(b, 31));
+
+ // (b == 0) ? 0xFFFFFFFF : 0
+#if defined(__aarch64__)
+ int32x4_t zeroMask = vreinterpretq_s32_u32(vceqzq_s32(b));
+#else
+ int32x4_t zeroMask = vreinterpretq_s32_u32(vceqq_s32(b, vdupq_n_s32(0)));
+#endif
+
+ // bitwise select either a or negative 'a' (vnegq_s32(a) equals to negative
+ // 'a') based on ltMask
+ int32x4_t masked = vbslq_s32(ltMask, vnegq_s32(a), a);
+ // res = masked & (~zeroMask)
+ int32x4_t res = vbicq_s32(masked, zeroMask);
+ return vreinterpretq_m128i_s32(res);
+}
+
+// Negate packed 16-bit integers in a when the corresponding signed 16-bit
+// integer in b is negative, and store the results in dst. Element in dst are
+// zeroed out when the corresponding element in b is zero.
+//
+// FOR j := 0 to 3
+// i := j*16
+// IF b[i+15:i] < 0
+// dst[i+15:i] := -(a[i+15:i])
+// ELSE IF b[i+15:i] == 0
+// dst[i+15:i] := 0
+// ELSE
+// dst[i+15:i] := a[i+15:i]
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi16
+FORCE_INLINE __m64 _mm_sign_pi16(__m64 _a, __m64 _b)
+{
+ int16x4_t a = vreinterpret_s16_m64(_a);
+ int16x4_t b = vreinterpret_s16_m64(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFFFF : 0
+ uint16x4_t ltMask = vreinterpret_u16_s16(vshr_n_s16(b, 15));
+
+ // (b == 0) ? 0xFFFF : 0
+#if defined(__aarch64__)
+ int16x4_t zeroMask = vreinterpret_s16_u16(vceqz_s16(b));
+#else
+ int16x4_t zeroMask = vreinterpret_s16_u16(vceq_s16(b, vdup_n_s16(0)));
+#endif
+
+ // bitwise select either a or nagative 'a' (vneg_s16(a) return nagative 'a')
+ // based on ltMask
+ int16x4_t masked = vbsl_s16(ltMask, vneg_s16(a), a);
+ // res = masked & (~zeroMask)
+ int16x4_t res = vbic_s16(masked, zeroMask);
+
+ return vreinterpret_m64_s16(res);
+}
+
+// Negate packed 32-bit integers in a when the corresponding signed 32-bit
+// integer in b is negative, and store the results in dst. Element in dst are
+// zeroed out when the corresponding element in b is zero.
+//
+// FOR j := 0 to 1
+// i := j*32
+// IF b[i+31:i] < 0
+// dst[i+31:i] := -(a[i+31:i])
+// ELSE IF b[i+31:i] == 0
+// dst[i+31:i] := 0
+// ELSE
+// dst[i+31:i] := a[i+31:i]
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi32
+FORCE_INLINE __m64 _mm_sign_pi32(__m64 _a, __m64 _b)
+{
+ int32x2_t a = vreinterpret_s32_m64(_a);
+ int32x2_t b = vreinterpret_s32_m64(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFFFFFFFF : 0
+ uint32x2_t ltMask = vreinterpret_u32_s32(vshr_n_s32(b, 31));
+
+ // (b == 0) ? 0xFFFFFFFF : 0
+#if defined(__aarch64__)
+ int32x2_t zeroMask = vreinterpret_s32_u32(vceqz_s32(b));
+#else
+ int32x2_t zeroMask = vreinterpret_s32_u32(vceq_s32(b, vdup_n_s32(0)));
+#endif
+
+ // bitwise select either a or nagative 'a' (vneg_s32(a) return nagative 'a')
+ // based on ltMask
+ int32x2_t masked = vbsl_s32(ltMask, vneg_s32(a), a);
+ // res = masked & (~zeroMask)
+ int32x2_t res = vbic_s32(masked, zeroMask);
+
+ return vreinterpret_m64_s32(res);
+}
+
+// Negate packed 8-bit integers in a when the corresponding signed 8-bit integer
+// in b is negative, and store the results in dst. Element in dst are zeroed out
+// when the corresponding element in b is zero.
+//
+// FOR j := 0 to 7
+// i := j*8
+// IF b[i+7:i] < 0
+// dst[i+7:i] := -(a[i+7:i])
+// ELSE IF b[i+7:i] == 0
+// dst[i+7:i] := 0
+// ELSE
+// dst[i+7:i] := a[i+7:i]
+// FI
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi8
+FORCE_INLINE __m64 _mm_sign_pi8(__m64 _a, __m64 _b)
+{
+ int8x8_t a = vreinterpret_s8_m64(_a);
+ int8x8_t b = vreinterpret_s8_m64(_b);
+
+ // signed shift right: faster than vclt
+ // (b < 0) ? 0xFF : 0
+ uint8x8_t ltMask = vreinterpret_u8_s8(vshr_n_s8(b, 7));
+
+ // (b == 0) ? 0xFF : 0
+#if defined(__aarch64__)
+ int8x8_t zeroMask = vreinterpret_s8_u8(vceqz_s8(b));
+#else
+ int8x8_t zeroMask = vreinterpret_s8_u8(vceq_s8(b, vdup_n_s8(0)));
+#endif
+
+ // bitwise select either a or nagative 'a' (vneg_s8(a) return nagative 'a')
+ // based on ltMask
+ int8x8_t masked = vbsl_s8(ltMask, vneg_s8(a), a);
+ // res = masked & (~zeroMask)
+ int8x8_t res = vbic_s8(masked, zeroMask);
+
+ return vreinterpret_m64_s8(res);
+}
+
+// Average packed unsigned 16-bit integers in a and b, and store the results in
+// dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu16
+FORCE_INLINE __m64 _mm_avg_pu16(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_u16(
+ vrhadd_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)));
+}
+
+// Average packed unsigned 8-bit integers in a and b, and store the results in
+// dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu8
+FORCE_INLINE __m64 _mm_avg_pu8(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_u8(
+ vrhadd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
+}
+
+// Average packed unsigned 8-bit integers in a and b, and store the results in
+// dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgb
+#define _m_pavgb(a, b) _mm_avg_pu8(a, b)
+
+// Average packed unsigned 16-bit integers in a and b, and store the results in
+// dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgw
+#define _m_pavgw(a, b) _mm_avg_pu16(a, b)
+
+// Extract a 16-bit integer from a, selected with imm8, and store the result in
+// the lower element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pextrw
+#define _m_pextrw(a, imm) _mm_extract_pi16(a, imm)
+
+// Copy a to dst, and insert the 16-bit integer i into dst at the location
+// specified by imm8.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=m_pinsrw
+#define _m_pinsrw(a, i, imm) _mm_insert_pi16(a, i, imm)
+
+// Compare packed signed 16-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmaxsw
+#define _m_pmaxsw(a, b) _mm_max_pi16(a, b)
+
+// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmaxub
+#define _m_pmaxub(a, b) _mm_max_pu8(a, b)
+
+// Compare packed signed 16-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pminsw
+#define _m_pminsw(a, b) _mm_min_pi16(a, b)
+
+// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pminub
+#define _m_pminub(a, b) _mm_min_pu8(a, b)
+
+// Computes the average of the 16 unsigned 8-bit integers in a and the 16
+// unsigned 8-bit integers in b and rounds.
+//
+// r0 := (a0 + b0) / 2
+// r1 := (a1 + b1) / 2
+// ...
+// r15 := (a15 + b15) / 2
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/8zwh554a(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_avg_epu8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vrhaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+}
+
+// Computes the average of the 8 unsigned 16-bit integers in a and the 8
+// unsigned 16-bit integers in b and rounds.
+//
+// r0 := (a0 + b0) / 2
+// r1 := (a1 + b1) / 2
+// ...
+// r7 := (a7 + b7) / 2
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/y13ca3c8(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_avg_epu16(__m128i a, __m128i b)
+{
+ return (__m128i) vrhaddq_u16(vreinterpretq_u16_m128i(a),
+ vreinterpretq_u16_m128i(b));
+}
+
+// Adds the four single-precision, floating-point values of a and b.
+//
+// r0 := a0 + b0
+// r1 := a1 + b1
+// r2 := a2 + b2
+// r3 := a3 + b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/c9848chc(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_f32(
+ vaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Add packed double-precision (64-bit) floating-point elements in a and b, and
+// store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_pd
+FORCE_INLINE __m128d _mm_add_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] + db[0];
+ c[1] = da[1] + db[1];
+ return vld1q_f32((float32_t *) c);
+#endif
+}
+
+// Add the lower double-precision (64-bit) floating-point element in a and b,
+// store the result in the lower element of dst, and copy the upper element from
+// a to the upper element of dst.
+//
+// dst[63:0] := a[63:0] + b[63:0]
+// dst[127:64] := a[127:64]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_sd
+FORCE_INLINE __m128d _mm_add_sd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return _mm_move_sd(a, _mm_add_pd(a, b));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] + db[0];
+ c[1] = da[1];
+ return vld1q_f32((float32_t *) c);
+#endif
+}
+
+// Add 64-bit integers a and b, and store the result in dst.
+//
+// dst[63:0] := a[63:0] + b[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_si64
+FORCE_INLINE __m64 _mm_add_si64(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s64(
+ vadd_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b)));
+}
+
+// adds the scalar single-precision floating point values of a and b.
+// https://msdn.microsoft.com/en-us/library/be94x2y6(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_add_ss(__m128 a, __m128 b)
+{
+ float32_t b0 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 0);
+ float32x4_t value = vsetq_lane_f32(b0, vdupq_n_f32(0), 0);
+ // the upper values in the result must be the remnants of <a>.
+ return vreinterpretq_m128_f32(vaddq_f32(a, value));
+}
+
+// Adds the 4 signed or unsigned 64-bit integers in a to the 4 signed or
+// unsigned 32-bit integers in b.
+// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_add_epi64(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s64(
+ vaddq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
+}
+
+// Adds the 4 signed or unsigned 32-bit integers in a to the 4 signed or
+// unsigned 32-bit integers in b.
+//
+// r0 := a0 + b0
+// r1 := a1 + b1
+// r2 := a2 + b2
+// r3 := a3 + b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vaddq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Adds the 8 signed or unsigned 16-bit integers in a to the 8 signed or
+// unsigned 16-bit integers in b.
+// https://msdn.microsoft.com/en-us/library/fceha5k4(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_add_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Adds the 16 signed or unsigned 8-bit integers in a to the 16 signed or
+// unsigned 8-bit integers in b.
+// https://technet.microsoft.com/en-us/subscriptions/yc7tcyzs(v=vs.90)
+FORCE_INLINE __m128i _mm_add_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Adds the 8 signed 16-bit integers in a to the 8 signed 16-bit integers in b
+// and saturates.
+//
+// r0 := SignedSaturate(a0 + b0)
+// r1 := SignedSaturate(a1 + b1)
+// ...
+// r7 := SignedSaturate(a7 + b7)
+//
+// https://msdn.microsoft.com/en-us/library/1a306ef8(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_adds_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vqaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Add packed signed 8-bit integers in a and b using saturation, and store the
+// results in dst.
+//
+// FOR j := 0 to 15
+// i := j*8
+// dst[i+7:i] := Saturate8( a[i+7:i] + b[i+7:i] )
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epi8
+FORCE_INLINE __m128i _mm_adds_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vqaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Adds the 16 unsigned 8-bit integers in a to the 16 unsigned 8-bit integers in
+// b and saturates..
+// https://msdn.microsoft.com/en-us/library/9hahyddy(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_adds_epu8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vqaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+}
+
+// Multiplies the 8 signed or unsigned 16-bit integers from a by the 8 signed or
+// unsigned 16-bit integers from b.
+//
+// r0 := (a0 * b0)[15:0]
+// r1 := (a1 * b1)[15:0]
+// ...
+// r7 := (a7 * b7)[15:0]
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/9ks1472s(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vmulq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or
+// unsigned 32-bit integers from b.
+// https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vmulq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Multiply the packed unsigned 16-bit integers in a and b, producing
+// intermediate 32-bit integers, and store the high 16 bits of the intermediate
+// integers in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// tmp[31:0] := a[i+15:i] * b[i+15:i]
+// dst[i+15:i] := tmp[31:16]
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmulhuw
+#define _m_pmulhuw(a, b) _mm_mulhi_pu16(a, b)
+
+// Multiplies the four single-precision, floating-point values of a and b.
+//
+// r0 := a0 * b0
+// r1 := a1 * b1
+// r2 := a2 * b2
+// r3 := a3 * b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_f32(
+ vmulq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Multiply packed double-precision (64-bit) floating-point elements in a and b,
+// and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_pd
+FORCE_INLINE __m128d _mm_mul_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vmulq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] * db[0];
+ c[1] = da[1] * db[1];
+ return vld1q_f32((float32_t *) c);
+#endif
+}
+
+// Multiply the lower double-precision (64-bit) floating-point element in a and
+// b, store the result in the lower element of dst, and copy the upper element
+// from a to the upper element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_mul_sd
+FORCE_INLINE __m128d _mm_mul_sd(__m128d a, __m128d b)
+{
+ return _mm_move_sd(a, _mm_mul_pd(a, b));
+}
+
+// Multiply the lower single-precision (32-bit) floating-point element in a and
+// b, store the result in the lower element of dst, and copy the upper 3 packed
+// elements from a to the upper elements of dst.
+//
+// dst[31:0] := a[31:0] * b[31:0]
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_ss
+FORCE_INLINE __m128 _mm_mul_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_mul_ps(a, b));
+}
+
+// Multiply the low unsigned 32-bit integers from each packed 64-bit element in
+// a and b, and store the unsigned 64-bit results in dst.
+//
+// r0 := (a0 & 0xFFFFFFFF) * (b0 & 0xFFFFFFFF)
+// r1 := (a2 & 0xFFFFFFFF) * (b2 & 0xFFFFFFFF)
+FORCE_INLINE __m128i _mm_mul_epu32(__m128i a, __m128i b)
+{
+ // vmull_u32 upcasts instead of masking, so we downcast.
+ uint32x2_t a_lo = vmovn_u64(vreinterpretq_u64_m128i(a));
+ uint32x2_t b_lo = vmovn_u64(vreinterpretq_u64_m128i(b));
+ return vreinterpretq_m128i_u64(vmull_u32(a_lo, b_lo));
+}
+
+// Multiply the low unsigned 32-bit integers from a and b, and store the
+// unsigned 64-bit result in dst.
+//
+// dst[63:0] := a[31:0] * b[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_su32
+FORCE_INLINE __m64 _mm_mul_su32(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_u64(vget_low_u64(
+ vmull_u32(vreinterpret_u32_m64(a), vreinterpret_u32_m64(b))));
+}
+
+// Multiply the low signed 32-bit integers from each packed 64-bit element in
+// a and b, and store the signed 64-bit results in dst.
+//
+// r0 := (int64_t)(int32_t)a0 * (int64_t)(int32_t)b0
+// r1 := (int64_t)(int32_t)a2 * (int64_t)(int32_t)b2
+FORCE_INLINE __m128i _mm_mul_epi32(__m128i a, __m128i b)
+{
+ // vmull_s32 upcasts instead of masking, so we downcast.
+ int32x2_t a_lo = vmovn_s64(vreinterpretq_s64_m128i(a));
+ int32x2_t b_lo = vmovn_s64(vreinterpretq_s64_m128i(b));
+ return vreinterpretq_m128i_s64(vmull_s32(a_lo, b_lo));
+}
+
+// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit
+// integers from b.
+//
+// r0 := (a0 * b0) + (a1 * b1)
+// r1 := (a2 * b2) + (a3 * b3)
+// r2 := (a4 * b4) + (a5 * b5)
+// r3 := (a6 * b6) + (a7 * b7)
+// https://msdn.microsoft.com/en-us/library/yht36sa6(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_madd_epi16(__m128i a, __m128i b)
+{
+ int32x4_t low = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)),
+ vget_low_s16(vreinterpretq_s16_m128i(b)));
+ int32x4_t high = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)),
+ vget_high_s16(vreinterpretq_s16_m128i(b)));
+
+ int32x2_t low_sum = vpadd_s32(vget_low_s32(low), vget_high_s32(low));
+ int32x2_t high_sum = vpadd_s32(vget_low_s32(high), vget_high_s32(high));
+
+ return vreinterpretq_m128i_s32(vcombine_s32(low_sum, high_sum));
+}
+
+// Multiply packed signed 16-bit integers in a and b, producing intermediate
+// signed 32-bit integers. Shift right by 15 bits while rounding up, and store
+// the packed 16-bit integers in dst.
+//
+// r0 := Round(((int32_t)a0 * (int32_t)b0) >> 15)
+// r1 := Round(((int32_t)a1 * (int32_t)b1) >> 15)
+// r2 := Round(((int32_t)a2 * (int32_t)b2) >> 15)
+// ...
+// r7 := Round(((int32_t)a7 * (int32_t)b7) >> 15)
+FORCE_INLINE __m128i _mm_mulhrs_epi16(__m128i a, __m128i b)
+{
+ // Has issues due to saturation
+ // return vreinterpretq_m128i_s16(vqrdmulhq_s16(a, b));
+
+ // Multiply
+ int32x4_t mul_lo = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)),
+ vget_low_s16(vreinterpretq_s16_m128i(b)));
+ int32x4_t mul_hi = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)),
+ vget_high_s16(vreinterpretq_s16_m128i(b)));
+
+ // Rounding narrowing shift right
+ // narrow = (int16_t)((mul + 16384) >> 15);
+ int16x4_t narrow_lo = vrshrn_n_s32(mul_lo, 15);
+ int16x4_t narrow_hi = vrshrn_n_s32(mul_hi, 15);
+
+ // Join together
+ return vreinterpretq_m128i_s16(vcombine_s16(narrow_lo, narrow_hi));
+}
+
+// Vertically multiply each unsigned 8-bit integer from a with the corresponding
+// signed 8-bit integer from b, producing intermediate signed 16-bit integers.
+// Horizontally add adjacent pairs of intermediate signed 16-bit integers,
+// and pack the saturated results in dst.
+//
+// FOR j := 0 to 7
+// i := j*16
+// dst[i+15:i] := Saturate_To_Int16( a[i+15:i+8]*b[i+15:i+8] +
+// a[i+7:i]*b[i+7:i] )
+// ENDFOR
+FORCE_INLINE __m128i _mm_maddubs_epi16(__m128i _a, __m128i _b)
+{
+#if defined(__aarch64__)
+ uint8x16_t a = vreinterpretq_u8_m128i(_a);
+ int8x16_t b = vreinterpretq_s8_m128i(_b);
+ int16x8_t tl = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(a))),
+ vmovl_s8(vget_low_s8(b)));
+ int16x8_t th = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(a))),
+ vmovl_s8(vget_high_s8(b)));
+ return vreinterpretq_m128i_s16(
+ vqaddq_s16(vuzp1q_s16(tl, th), vuzp2q_s16(tl, th)));
+#else
+ // This would be much simpler if x86 would choose to zero extend OR sign
+ // extend, not both. This could probably be optimized better.
+ uint16x8_t a = vreinterpretq_u16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+
+ // Zero extend a
+ int16x8_t a_odd = vreinterpretq_s16_u16(vshrq_n_u16(a, 8));
+ int16x8_t a_even = vreinterpretq_s16_u16(vbicq_u16(a, vdupq_n_u16(0xff00)));
+
+ // Sign extend by shifting left then shifting right.
+ int16x8_t b_even = vshrq_n_s16(vshlq_n_s16(b, 8), 8);
+ int16x8_t b_odd = vshrq_n_s16(b, 8);
+
+ // multiply
+ int16x8_t prod1 = vmulq_s16(a_even, b_even);
+ int16x8_t prod2 = vmulq_s16(a_odd, b_odd);
+
+ // saturated add
+ return vreinterpretq_m128i_s16(vqaddq_s16(prod1, prod2));
+#endif
+}
+
+// Computes the fused multiple add product of 32-bit floating point numbers.
+//
+// Return Value
+// Multiplies A and B, and adds C to the temporary result before returning it.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fmadd
+FORCE_INLINE __m128 _mm_fmadd_ps(__m128 a, __m128 b, __m128 c)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(vfmaq_f32(vreinterpretq_f32_m128(c),
+ vreinterpretq_f32_m128(b),
+ vreinterpretq_f32_m128(a)));
+#else
+ return _mm_add_ps(_mm_mul_ps(a, b), c);
+#endif
+}
+
+// Alternatively add and subtract packed single-precision (32-bit)
+// floating-point elements in a to/from packed elements in b, and store the
+// results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=addsub_ps
+FORCE_INLINE __m128 _mm_addsub_ps(__m128 a, __m128 b)
+{
+ __m128 mask = {-1.0f, 1.0f, -1.0f, 1.0f};
+ return _mm_fmadd_ps(b, mask, a);
+}
+
+// Horizontally add adjacent pairs of double-precision (64-bit) floating-point
+// elements in a and b, and pack the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pd
+FORCE_INLINE __m128d _mm_hadd_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vpaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[] = {da[0] + da[1], db[0] + db[1]};
+ return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c));
+#endif
+}
+
+// Compute the absolute differences of packed unsigned 8-bit integers in a and
+// b, then horizontally sum each consecutive 8 differences to produce two
+// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
+// 16 bits of 64-bit elements in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_epu8
+FORCE_INLINE __m128i _mm_sad_epu8(__m128i a, __m128i b)
+{
+ uint16x8_t t = vpaddlq_u8(vabdq_u8((uint8x16_t) a, (uint8x16_t) b));
+ uint16_t r0 = t[0] + t[1] + t[2] + t[3];
+ uint16_t r4 = t[4] + t[5] + t[6] + t[7];
+ uint16x8_t r = vsetq_lane_u16(r0, vdupq_n_u16(0), 0);
+ return (__m128i) vsetq_lane_u16(r4, r, 4);
+}
+
+// Compute the absolute differences of packed unsigned 8-bit integers in a and
+// b, then horizontally sum each consecutive 8 differences to produce four
+// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
+// 16 bits of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_pu8
+FORCE_INLINE __m64 _mm_sad_pu8(__m64 a, __m64 b)
+{
+ uint16x4_t t =
+ vpaddl_u8(vabd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
+ uint16_t r0 = t[0] + t[1] + t[2] + t[3];
+ return vreinterpret_m64_u16(vset_lane_u16(r0, vdup_n_u16(0), 0));
+}
+
+// Compute the absolute differences of packed unsigned 8-bit integers in a and
+// b, then horizontally sum each consecutive 8 differences to produce four
+// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
+// 16 bits of dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// tmp[i+7:i] := ABS(a[i+7:i] - b[i+7:i])
+// ENDFOR
+// dst[15:0] := tmp[7:0] + tmp[15:8] + tmp[23:16] + tmp[31:24] + tmp[39:32] +
+// tmp[47:40] + tmp[55:48] + tmp[63:56] dst[63:16] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_psadbw
+#define _m_psadbw(a, b) _mm_sad_pu8(a, b)
+
+// Divides the four single-precision, floating-point values of a and b.
+//
+// r0 := a0 / b0
+// r1 := a1 / b1
+// r2 := a2 / b2
+// r3 := a3 / b3
+//
+// https://msdn.microsoft.com/en-us/library/edaw8147(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_div_ps(__m128 a, __m128 b)
+{
+#if defined(__aarch64__) && !SSE2NEON_PRECISE_DIV
+ return vreinterpretq_m128_f32(
+ vdivq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#else
+ float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(b));
+ recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b)));
+#if SSE2NEON_PRECISE_DIV
+ // Additional Netwon-Raphson iteration for accuracy
+ recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b)));
+#endif
+ return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(a), recip));
+#endif
+}
+
+// Divides the scalar single-precision floating point value of a by b.
+// https://msdn.microsoft.com/en-us/library/4y73xa49(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_div_ss(__m128 a, __m128 b)
+{
+ float32_t value =
+ vgetq_lane_f32(vreinterpretq_f32_m128(_mm_div_ps(a, b)), 0);
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
+}
+
+// Divide packed double-precision (64-bit) floating-point elements in a by
+// packed elements in b, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := 64*j
+// dst[i+63:i] := a[i+63:i] / b[i+63:i]
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_div_pd
+FORCE_INLINE __m128d _mm_div_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vdivq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ double *da = (double *) &a;
+ double *db = (double *) &b;
+ double c[2];
+ c[0] = da[0] / db[0];
+ c[1] = da[1] / db[1];
+ return vld1q_f32((float32_t *) c);
+#endif
+}
+
+// Divide the lower double-precision (64-bit) floating-point element in a by the
+// lower double-precision (64-bit) floating-point element in b, store the result
+// in the lower element of dst, and copy the upper element from a to the upper
+// element of dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_div_sd
+FORCE_INLINE __m128d _mm_div_sd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ float64x2_t tmp =
+ vdivq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b));
+ return vreinterpretq_m128d_f64(
+ vsetq_lane_f64(vgetq_lane_f64(vreinterpretq_f64_m128d(a), 1), tmp, 1));
+#else
+ return _mm_move_sd(a, _mm_div_pd(a, b));
+#endif
+}
+
+// Compute the approximate reciprocal of packed single-precision (32-bit)
+// floating-point elements in a, and store the results in dst. The maximum
+// relative error for this approximation is less than 1.5*2^-12.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ps
+FORCE_INLINE __m128 _mm_rcp_ps(__m128 in)
+{
+ float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(in));
+ recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
+#if SSE2NEON_PRECISE_DIV
+ // Additional Netwon-Raphson iteration for accuracy
+ recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
+#endif
+ return vreinterpretq_m128_f32(recip);
+}
+
+// Compute the approximate reciprocal of the lower single-precision (32-bit)
+// floating-point element in a, store the result in the lower element of dst,
+// and copy the upper 3 packed elements from a to the upper elements of dst. The
+// maximum relative error for this approximation is less than 1.5*2^-12.
+//
+// dst[31:0] := (1.0 / a[31:0])
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ss
+FORCE_INLINE __m128 _mm_rcp_ss(__m128 a)
+{
+ return _mm_move_ss(a, _mm_rcp_ps(a));
+}
+
+// Computes the approximations of square roots of the four single-precision,
+// floating-point values of a. First computes reciprocal square roots and then
+// reciprocals of the four values.
+//
+// r0 := sqrt(a0)
+// r1 := sqrt(a1)
+// r2 := sqrt(a2)
+// r3 := sqrt(a3)
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/8z67bwwk(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in)
+{
+#if SSE2NEON_PRECISE_SQRT
+ float32x4_t recip = vrsqrteq_f32(vreinterpretq_f32_m128(in));
+
+ // Test for vrsqrteq_f32(0) -> positive infinity case.
+ // Change to zero, so that s * 1/sqrt(s) result is zero too.
+ const uint32x4_t pos_inf = vdupq_n_u32(0x7F800000);
+ const uint32x4_t div_by_zero =
+ vceqq_u32(pos_inf, vreinterpretq_u32_f32(recip));
+ recip = vreinterpretq_f32_u32(
+ vandq_u32(vmvnq_u32(div_by_zero), vreinterpretq_u32_f32(recip)));
+
+ // Additional Netwon-Raphson iteration for accuracy
+ recip = vmulq_f32(
+ vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)),
+ recip);
+ recip = vmulq_f32(
+ vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)),
+ recip);
+
+ // sqrt(s) = s * 1/sqrt(s)
+ return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(in), recip));
+#elif defined(__aarch64__)
+ return vreinterpretq_m128_f32(vsqrtq_f32(vreinterpretq_f32_m128(in)));
+#else
+ float32x4_t recipsq = vrsqrteq_f32(vreinterpretq_f32_m128(in));
+ float32x4_t sq = vrecpeq_f32(recipsq);
+ return vreinterpretq_m128_f32(sq);
+#endif
+}
+
+// Computes the approximation of the square root of the scalar single-precision
+// floating point value of in.
+// https://msdn.microsoft.com/en-us/library/ahfsc22d(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_sqrt_ss(__m128 in)
+{
+ float32_t value =
+ vgetq_lane_f32(vreinterpretq_f32_m128(_mm_sqrt_ps(in)), 0);
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(value, vreinterpretq_f32_m128(in), 0));
+}
+
+// Computes the approximations of the reciprocal square roots of the four
+// single-precision floating point values of in.
+// https://msdn.microsoft.com/en-us/library/22hfsh53(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_rsqrt_ps(__m128 in)
+{
+ float32x4_t out = vrsqrteq_f32(vreinterpretq_f32_m128(in));
+#if SSE2NEON_PRECISE_RSQRT
+ // Additional Netwon-Raphson iteration for accuracy
+ out = vmulq_f32(
+ out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out));
+ out = vmulq_f32(
+ out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out));
+#endif
+ return vreinterpretq_m128_f32(out);
+}
+
+// Compute the approximate reciprocal square root of the lower single-precision
+// (32-bit) floating-point element in a, store the result in the lower element
+// of dst, and copy the upper 3 packed elements from a to the upper elements of
+// dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rsqrt_ss
+FORCE_INLINE __m128 _mm_rsqrt_ss(__m128 in)
+{
+ return vsetq_lane_f32(vgetq_lane_f32(_mm_rsqrt_ps(in), 0), in, 0);
+}
+
+// Compare packed signed 16-bit integers in a and b, and store packed maximum
+// values in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pi16
+FORCE_INLINE __m64 _mm_max_pi16(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s16(
+ vmax_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
+}
+
+// Compare packed signed 16-bit integers in a and b, and store packed maximum
+// values in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pi16
+#define _m_pmaxsw(a, b) _mm_max_pi16(a, b)
+
+// Computes the maximums of the four single-precision, floating-point values of
+// a and b.
+// https://msdn.microsoft.com/en-us/library/vstudio/ff5d607a(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_max_ps(__m128 a, __m128 b)
+{
+#if SSE2NEON_PRECISE_MINMAX
+ float32x4_t _a = vreinterpretq_f32_m128(a);
+ float32x4_t _b = vreinterpretq_f32_m128(b);
+ return vbslq_f32(vcltq_f32(_b, _a), _a, _b);
+#else
+ return vreinterpretq_m128_f32(
+ vmaxq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#endif
+}
+
+// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
+// values in dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pu8
+FORCE_INLINE __m64 _mm_max_pu8(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_u8(
+ vmax_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
+}
+
+// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
+// values in dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pu8
+#define _m_pmaxub(a, b) _mm_max_pu8(a, b)
+
+// Compare packed signed 16-bit integers in a and b, and store packed minimum
+// values in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pi16
+FORCE_INLINE __m64 _mm_min_pi16(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s16(
+ vmin_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
+}
+
+// Compare packed signed 16-bit integers in a and b, and store packed minimum
+// values in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pi16
+#define _m_pminsw(a, b) _mm_min_pi16(a, b)
+
+// Computes the minima of the four single-precision, floating-point values of a
+// and b.
+// https://msdn.microsoft.com/en-us/library/vstudio/wh13kadz(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_min_ps(__m128 a, __m128 b)
+{
+#if SSE2NEON_PRECISE_MINMAX
+ float32x4_t _a = vreinterpretq_f32_m128(a);
+ float32x4_t _b = vreinterpretq_f32_m128(b);
+ return vbslq_f32(vcltq_f32(_a, _b), _a, _b);
+#else
+ return vreinterpretq_m128_f32(
+ vminq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#endif
+}
+
+// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
+// values in dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pu8
+FORCE_INLINE __m64 _mm_min_pu8(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_u8(
+ vmin_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)));
+}
+
+// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
+// values in dst.
+//
+// FOR j := 0 to 7
+// i := j*8
+// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pu8
+#define _m_pminub(a, b) _mm_min_pu8(a, b)
+
+// Computes the maximum of the two lower scalar single-precision floating point
+// values of a and b.
+// https://msdn.microsoft.com/en-us/library/s6db5esz(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_max_ss(__m128 a, __m128 b)
+{
+ float32_t value = vgetq_lane_f32(_mm_max_ps(a, b), 0);
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
+}
+
+// Computes the minimum of the two lower scalar single-precision floating point
+// values of a and b.
+// https://msdn.microsoft.com/en-us/library/0a9y7xaa(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_min_ss(__m128 a, __m128 b)
+{
+ float32_t value = vgetq_lane_f32(_mm_min_ps(a, b), 0);
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
+}
+
+// Computes the pairwise maxima of the 16 unsigned 8-bit integers from a and the
+// 16 unsigned 8-bit integers from b.
+// https://msdn.microsoft.com/en-us/library/st6634za(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_max_epu8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vmaxq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+}
+
+// Computes the pairwise minima of the 16 unsigned 8-bit integers from a and the
+// 16 unsigned 8-bit integers from b.
+// https://msdn.microsoft.com/ko-kr/library/17k8cf58(v=vs.100).aspxx
+FORCE_INLINE __m128i _mm_min_epu8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vminq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
+}
+
+// Computes the pairwise minima of the 8 signed 16-bit integers from a and the 8
+// signed 16-bit integers from b.
+// https://msdn.microsoft.com/en-us/library/vstudio/6te997ew(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_min_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vminq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Compare packed signed 8-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epi8
+FORCE_INLINE __m128i _mm_max_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vmaxq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Compare packed unsigned 16-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu16
+FORCE_INLINE __m128i _mm_max_epu16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vmaxq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+}
+
+// Compare packed signed 8-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epi8
+FORCE_INLINE __m128i _mm_min_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vminq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Compare packed unsigned 16-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epu16
+FORCE_INLINE __m128i _mm_min_epu16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vminq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)));
+}
+
+// Computes the pairwise maxima of the 8 signed 16-bit integers from a and the 8
+// signed 16-bit integers from b.
+// https://msdn.microsoft.com/en-us/LIBRary/3x060h7c(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_max_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vmaxq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// epi versions of min/max
+// Computes the pariwise maximums of the four signed 32-bit integer values of a
+// and b.
+//
+// A 128-bit parameter that can be defined with the following equations:
+// r0 := (a0 > b0) ? a0 : b0
+// r1 := (a1 > b1) ? a1 : b1
+// r2 := (a2 > b2) ? a2 : b2
+// r3 := (a3 > b3) ? a3 : b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/bb514055(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_max_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vmaxq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Computes the pariwise minima of the four signed 32-bit integer values of a
+// and b.
+//
+// A 128-bit parameter that can be defined with the following equations:
+// r0 := (a0 < b0) ? a0 : b0
+// r1 := (a1 < b1) ? a1 : b1
+// r2 := (a2 < b2) ? a2 : b2
+// r3 := (a3 < b3) ? a3 : b3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/bb531476(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s32(
+ vminq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Compare packed unsigned 32-bit integers in a and b, and store packed maximum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32
+FORCE_INLINE __m128i _mm_max_epu32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u32(
+ vmaxq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b)));
+}
+
+// Compare packed unsigned 32-bit integers in a and b, and store packed minimum
+// values in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32
+FORCE_INLINE __m128i _mm_min_epu32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u32(
+ vminq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b)));
+}
+
+// Multiply the packed unsigned 16-bit integers in a and b, producing
+// intermediate 32-bit integers, and store the high 16 bits of the intermediate
+// integers in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhi_pu16
+FORCE_INLINE __m64 _mm_mulhi_pu16(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_u16(vshrn_n_u32(
+ vmull_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)), 16));
+}
+
+// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit
+// integers from b.
+//
+// r0 := (a0 * b0)[31:16]
+// r1 := (a1 * b1)[31:16]
+// ...
+// r7 := (a7 * b7)[31:16]
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/59hddw1d(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b)
+{
+ /* FIXME: issue with large values because of result saturation */
+ // int16x8_t ret = vqdmulhq_s16(vreinterpretq_s16_m128i(a),
+ // vreinterpretq_s16_m128i(b)); /* =2*a*b */ return
+ // vreinterpretq_m128i_s16(vshrq_n_s16(ret, 1));
+ int16x4_t a3210 = vget_low_s16(vreinterpretq_s16_m128i(a));
+ int16x4_t b3210 = vget_low_s16(vreinterpretq_s16_m128i(b));
+ int32x4_t ab3210 = vmull_s16(a3210, b3210); /* 3333222211110000 */
+ int16x4_t a7654 = vget_high_s16(vreinterpretq_s16_m128i(a));
+ int16x4_t b7654 = vget_high_s16(vreinterpretq_s16_m128i(b));
+ int32x4_t ab7654 = vmull_s16(a7654, b7654); /* 7777666655554444 */
+ uint16x8x2_t r =
+ vuzpq_u16(vreinterpretq_u16_s32(ab3210), vreinterpretq_u16_s32(ab7654));
+ return vreinterpretq_m128i_u16(r.val[1]);
+}
+
+// Multiply the packed unsigned 16-bit integers in a and b, producing
+// intermediate 32-bit integers, and store the high 16 bits of the intermediate
+// integers in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhi_epu16
+FORCE_INLINE __m128i _mm_mulhi_epu16(__m128i a, __m128i b)
+{
+ uint16x4_t a3210 = vget_low_u16(vreinterpretq_u16_m128i(a));
+ uint16x4_t b3210 = vget_low_u16(vreinterpretq_u16_m128i(b));
+ uint32x4_t ab3210 = vmull_u16(a3210, b3210);
+#if defined(__aarch64__)
+ uint32x4_t ab7654 =
+ vmull_high_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b));
+ uint16x8_t r = vuzp2q_u16(vreinterpretq_u16_u32(ab3210),
+ vreinterpretq_u16_u32(ab7654));
+ return vreinterpretq_m128i_u16(r);
+#else
+ uint16x4_t a7654 = vget_high_u16(vreinterpretq_u16_m128i(a));
+ uint16x4_t b7654 = vget_high_u16(vreinterpretq_u16_m128i(b));
+ uint32x4_t ab7654 = vmull_u16(a7654, b7654);
+ uint16x8x2_t r =
+ vuzpq_u16(vreinterpretq_u16_u32(ab3210), vreinterpretq_u16_u32(ab7654));
+ return vreinterpretq_m128i_u16(r.val[1]);
+#endif
+}
+
+// Computes pairwise add of each argument as single-precision, floating-point
+// values a and b.
+// https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx
+FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(
+ vpaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#else
+ float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
+ float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vpadd_f32(a10, a32), vpadd_f32(b10, b32)));
+#endif
+}
+
+// Computes pairwise add of each argument as a 16-bit signed or unsigned integer
+// values a and b.
+FORCE_INLINE __m128i _mm_hadd_epi16(__m128i _a, __m128i _b)
+{
+ int16x8_t a = vreinterpretq_s16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s16(vpaddq_s16(a, b));
+#else
+ return vreinterpretq_m128i_s16(
+ vcombine_s16(vpadd_s16(vget_low_s16(a), vget_high_s16(a)),
+ vpadd_s16(vget_low_s16(b), vget_high_s16(b))));
+#endif
+}
+
+// Horizontally substract adjacent pairs of single-precision (32-bit)
+// floating-point elements in a and b, and pack the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_ps
+FORCE_INLINE __m128 _mm_hsub_ps(__m128 _a, __m128 _b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(vsubq_f32(
+ vuzp1q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)),
+ vuzp2q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b))));
+#else
+ float32x4x2_t c =
+ vuzpq_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b));
+ return vreinterpretq_m128_f32(vsubq_f32(c.val[0], c.val[1]));
+#endif
+}
+
+// Horizontally add adjacent pairs of 16-bit integers in a and b, and pack the
+// signed 16-bit results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi16
+FORCE_INLINE __m64 _mm_hadd_pi16(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s16(
+ vpadd_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b)));
+}
+
+// Horizontally add adjacent pairs of 32-bit integers in a and b, and pack the
+// signed 32-bit results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi32
+FORCE_INLINE __m64 _mm_hadd_pi32(__m64 a, __m64 b)
+{
+ return vreinterpret_m64_s32(
+ vpadd_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b)));
+}
+
+// Computes pairwise difference of each argument as a 16-bit signed or unsigned
+// integer values a and b.
+FORCE_INLINE __m128i _mm_hsub_epi16(__m128i _a, __m128i _b)
+{
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+ // Interleave using vshrn/vmovn
+ // [a0|a2|a4|a6|b0|b2|b4|b6]
+ // [a1|a3|a5|a7|b1|b3|b5|b7]
+ int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
+ int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
+ // Subtract
+ return vreinterpretq_m128i_s16(vsubq_s16(ab0246, ab1357));
+}
+
+// Computes saturated pairwise sub of each argument as a 16-bit signed
+// integer values a and b.
+FORCE_INLINE __m128i _mm_hadds_epi16(__m128i _a, __m128i _b)
+{
+#if defined(__aarch64__)
+ int16x8_t a = vreinterpretq_s16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+ return vreinterpretq_s64_s16(
+ vqaddq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
+#else
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+ // Interleave using vshrn/vmovn
+ // [a0|a2|a4|a6|b0|b2|b4|b6]
+ // [a1|a3|a5|a7|b1|b3|b5|b7]
+ int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
+ int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
+ // Saturated add
+ return vreinterpretq_m128i_s16(vqaddq_s16(ab0246, ab1357));
+#endif
+}
+
+// Computes saturated pairwise difference of each argument as a 16-bit signed
+// integer values a and b.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsubs_epi16
+FORCE_INLINE __m128i _mm_hsubs_epi16(__m128i _a, __m128i _b)
+{
+#if defined(__aarch64__)
+ int16x8_t a = vreinterpretq_s16_m128i(_a);
+ int16x8_t b = vreinterpretq_s16_m128i(_b);
+ return vreinterpretq_s64_s16(
+ vqsubq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
+#else
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+ // Interleave using vshrn/vmovn
+ // [a0|a2|a4|a6|b0|b2|b4|b6]
+ // [a1|a3|a5|a7|b1|b3|b5|b7]
+ int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
+ int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
+ // Saturated subtract
+ return vreinterpretq_m128i_s16(vqsubq_s16(ab0246, ab1357));
+#endif
+}
+
+// Computes pairwise add of each argument as a 32-bit signed or unsigned integer
+// values a and b.
+FORCE_INLINE __m128i _mm_hadd_epi32(__m128i _a, __m128i _b)
+{
+ int32x4_t a = vreinterpretq_s32_m128i(_a);
+ int32x4_t b = vreinterpretq_s32_m128i(_b);
+ return vreinterpretq_m128i_s32(
+ vcombine_s32(vpadd_s32(vget_low_s32(a), vget_high_s32(a)),
+ vpadd_s32(vget_low_s32(b), vget_high_s32(b))));
+}
+
+// Computes pairwise difference of each argument as a 32-bit signed or unsigned
+// integer values a and b.
+FORCE_INLINE __m128i _mm_hsub_epi32(__m128i _a, __m128i _b)
+{
+ int64x2_t a = vreinterpretq_s64_m128i(_a);
+ int64x2_t b = vreinterpretq_s64_m128i(_b);
+ // Interleave using vshrn/vmovn
+ // [a0|a2|b0|b2]
+ // [a1|a2|b1|b3]
+ int32x4_t ab02 = vcombine_s32(vmovn_s64(a), vmovn_s64(b));
+ int32x4_t ab13 = vcombine_s32(vshrn_n_s64(a, 32), vshrn_n_s64(b, 32));
+ // Subtract
+ return vreinterpretq_m128i_s32(vsubq_s32(ab02, ab13));
+}
+
+// Kahan summation for accurate summation of floating-point numbers.
+// http://blog.zachbjornson.com/2019/08/11/fast-float-summation.html
+FORCE_INLINE void _sse2neon_kadd_f32(float *sum, float *c, float y)
+{
+ y -= *c;
+ float t = *sum + y;
+ *c = (t - *sum) - y;
+ *sum = t;
+}
+
+// Conditionally multiply the packed single-precision (32-bit) floating-point
+// elements in a and b using the high 4 bits in imm8, sum the four products,
+// and conditionally store the sum in dst using the low 4 bits of imm.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dp_ps
+FORCE_INLINE __m128 _mm_dp_ps(__m128 a, __m128 b, const int imm)
+{
+#if defined(__aarch64__)
+ /* shortcuts */
+ if (imm == 0xFF) {
+ return _mm_set1_ps(vaddvq_f32(_mm_mul_ps(a, b)));
+ }
+ if (imm == 0x7F) {
+ float32x4_t m = _mm_mul_ps(a, b);
+ m[3] = 0;
+ return _mm_set1_ps(vaddvq_f32(m));
+ }
+#endif
+
+ float s = 0, c = 0;
+ float32x4_t f32a = vreinterpretq_f32_m128(a);
+ float32x4_t f32b = vreinterpretq_f32_m128(b);
+
+ /* To improve the accuracy of floating-point summation, Kahan algorithm
+ * is used for each operation.
+ */
+ if (imm & (1 << 4))
+ _sse2neon_kadd_f32(&s, &c, f32a[0] * f32b[0]);
+ if (imm & (1 << 5))
+ _sse2neon_kadd_f32(&s, &c, f32a[1] * f32b[1]);
+ if (imm & (1 << 6))
+ _sse2neon_kadd_f32(&s, &c, f32a[2] * f32b[2]);
+ if (imm & (1 << 7))
+ _sse2neon_kadd_f32(&s, &c, f32a[3] * f32b[3]);
+ s += c;
+
+ float32x4_t res = {
+ (imm & 0x1) ? s : 0,
+ (imm & 0x2) ? s : 0,
+ (imm & 0x4) ? s : 0,
+ (imm & 0x8) ? s : 0,
+ };
+ return vreinterpretq_m128_f32(res);
+}
+
+/* Compare operations */
+
+// Compares for less than
+// https://msdn.microsoft.com/en-us/library/vstudio/f330yhc8(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmplt_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_u32(
+ vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Compares for less than
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fy94wye7(v=vs.100)
+FORCE_INLINE __m128 _mm_cmplt_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmplt_ps(a, b));
+}
+
+// Compares for greater than.
+//
+// r0 := (a0 > b0) ? 0xffffffff : 0x0
+// r1 := (a1 > b1) ? 0xffffffff : 0x0
+// r2 := (a2 > b2) ? 0xffffffff : 0x0
+// r3 := (a3 > b3) ? 0xffffffff : 0x0
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/11dy102s(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmpgt_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_u32(
+ vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Compares for greater than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/1xyyyy9e(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpgt_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmpgt_ps(a, b));
+}
+
+// Compares for greater than or equal.
+// https://msdn.microsoft.com/en-us/library/vstudio/fs813y2t(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_u32(
+ vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Compares for greater than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/kesh3ddc(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpge_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmpge_ps(a, b));
+}
+
+// Compares for less than or equal.
+//
+// r0 := (a0 <= b0) ? 0xffffffff : 0x0
+// r1 := (a1 <= b1) ? 0xffffffff : 0x0
+// r2 := (a2 <= b2) ? 0xffffffff : 0x0
+// r3 := (a3 <= b3) ? 0xffffffff : 0x0
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/1s75w83z(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_u32(
+ vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Compares for less than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/a7x0hbhw(v=vs.100)
+FORCE_INLINE __m128 _mm_cmple_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmple_ps(a, b));
+}
+
+// Compares for equality.
+// https://msdn.microsoft.com/en-us/library/vstudio/36aectz5(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmpeq_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_u32(
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+}
+
+// Compares for equality.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/k423z28e(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpeq_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmpeq_ps(a, b));
+}
+
+// Compares for inequality.
+// https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b)
+{
+ return vreinterpretq_m128_u32(vmvnq_u32(
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))));
+}
+
+// Compares for inequality.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/ekya8fh4(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpneq_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmpneq_ps(a, b));
+}
+
+// Compares for not greater than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/wsexys62(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnge_ps(__m128 a, __m128 b)
+{
+ return _mm_cmplt_ps(a, b);
+}
+
+// Compares for not greater than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fk2y80s8(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnge_ss(__m128 a, __m128 b)
+{
+ return _mm_cmplt_ss(a, b);
+}
+
+// Compares for not greater than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/d0xh7w0s(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpngt_ps(__m128 a, __m128 b)
+{
+ return _mm_cmple_ps(a, b);
+}
+
+// Compares for not greater than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpngt_ss(__m128 a, __m128 b)
+{
+ return _mm_cmple_ss(a, b);
+}
+
+// Compares for not less than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/6a330kxw(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnle_ps(__m128 a, __m128 b)
+{
+ return _mm_cmpgt_ps(a, b);
+}
+
+// Compares for not less than or equal.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnle_ss(__m128 a, __m128 b)
+{
+ return _mm_cmpgt_ss(a, b);
+}
+
+// Compares for not less than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/4686bbdw(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnlt_ps(__m128 a, __m128 b)
+{
+ return _mm_cmpge_ps(a, b);
+}
+
+// Compares for not less than.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/56b9z2wf(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpnlt_ss(__m128 a, __m128 b)
+{
+ return _mm_cmpge_ss(a, b);
+}
+
+// Compares the 16 signed or unsigned 8-bit integers in a and the 16 signed or
+// unsigned 8-bit integers in b for equality.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/bz5xk21a(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_cmpeq_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vceqq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Compare packed double-precision (64-bit) floating-point elements in a and b
+// for equality, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_pd
+FORCE_INLINE __m128d _mm_cmpeq_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_u64(
+ vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
+ uint32x4_t cmp =
+ vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b));
+ uint32x4_t swapped = vrev64q_u32(cmp);
+ return vreinterpretq_m128d_u32(vandq_u32(cmp, swapped));
+#endif
+}
+
+// Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or
+// unsigned 16-bit integers in b for equality.
+// https://msdn.microsoft.com/en-us/library/2ay060te(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmpeq_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vceqq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Compare packed 32-bit integers in a and b for equality, and store the results
+// in dst
+FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u32(
+ vceqq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Compare packed 64-bit integers in a and b for equality, and store the results
+// in dst
+FORCE_INLINE __m128i _mm_cmpeq_epi64(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_u64(
+ vceqq_u64(vreinterpretq_u64_m128i(a), vreinterpretq_u64_m128i(b)));
+#else
+ // ARMv7 lacks vceqq_u64
+ // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
+ uint32x4_t cmp =
+ vceqq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b));
+ uint32x4_t swapped = vrev64q_u32(cmp);
+ return vreinterpretq_m128i_u32(vandq_u32(cmp, swapped));
+#endif
+}
+
+// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
+// in b for lesser than.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/9s46csht(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_cmplt_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vcltq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
+// in b for greater than.
+//
+// r0 := (a0 > b0) ? 0xff : 0x0
+// r1 := (a1 > b1) ? 0xff : 0x0
+// ...
+// r15 := (a15 > b15) ? 0xff : 0x0
+//
+// https://msdn.microsoft.com/zh-tw/library/wf45zt2b(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmpgt_epi8(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vcgtq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+}
+
+// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
+// in b for less than.
+//
+// r0 := (a0 < b0) ? 0xffff : 0x0
+// r1 := (a1 < b1) ? 0xffff : 0x0
+// ...
+// r7 := (a7 < b7) ? 0xffff : 0x0
+//
+// https://technet.microsoft.com/en-us/library/t863edb2(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmplt_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vcltq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
+// in b for greater than.
+//
+// r0 := (a0 > b0) ? 0xffff : 0x0
+// r1 := (a1 > b1) ? 0xffff : 0x0
+// ...
+// r7 := (a7 > b7) ? 0xffff : 0x0
+//
+// https://technet.microsoft.com/en-us/library/xd43yfsa(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmpgt_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vcgtq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+}
+
+
+// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers
+// in b for less than.
+// https://msdn.microsoft.com/en-us/library/vstudio/4ak0bf5d(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmplt_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u32(
+ vcltq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers
+// in b for greater than.
+// https://msdn.microsoft.com/en-us/library/vstudio/1s9f2z0y(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u32(
+ vcgtq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+}
+
+// Compares the 2 signed 64-bit integers in a and the 2 signed 64-bit integers
+// in b for greater than.
+FORCE_INLINE __m128i _mm_cmpgt_epi64(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_u64(
+ vcgtq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
+#else
+ // ARMv7 lacks vcgtq_s64.
+ // This is based off of Clang's SSE2 polyfill:
+ // (a > b) -> ((a_hi > b_hi) || (a_lo > b_lo && a_hi == b_hi))
+
+ // Mask the sign bit out since we need a signed AND an unsigned comparison
+ // and it is ugly to try and split them.
+ int32x4_t mask = vreinterpretq_s32_s64(vdupq_n_s64(0x80000000ull));
+ int32x4_t a_mask = veorq_s32(vreinterpretq_s32_m128i(a), mask);
+ int32x4_t b_mask = veorq_s32(vreinterpretq_s32_m128i(b), mask);
+ // Check if a > b
+ int64x2_t greater = vreinterpretq_s64_u32(vcgtq_s32(a_mask, b_mask));
+ // Copy upper mask to lower mask
+ // a_hi > b_hi
+ int64x2_t gt_hi = vshrq_n_s64(greater, 63);
+ // Copy lower mask to upper mask
+ // a_lo > b_lo
+ int64x2_t gt_lo = vsliq_n_s64(greater, greater, 32);
+ // Compare for equality
+ int64x2_t equal = vreinterpretq_s64_u32(vceqq_s32(a_mask, b_mask));
+ // Copy upper mask to lower mask
+ // a_hi == b_hi
+ int64x2_t eq_hi = vshrq_n_s64(equal, 63);
+ // a_hi > b_hi || (a_lo > b_lo && a_hi == b_hi)
+ int64x2_t ret = vorrq_s64(gt_hi, vandq_s64(gt_lo, eq_hi));
+ return vreinterpretq_m128i_s64(ret);
+#endif
+}
+
+// Compares the four 32-bit floats in a and b to check if any values are NaN.
+// Ordered compare between each value returns true for "orderable" and false for
+// "not orderable" (NaN).
+// https://msdn.microsoft.com/en-us/library/vstudio/0h9w00fx(v=vs.100).aspx see
+// also:
+// http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean
+// http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics
+FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b)
+{
+ // Note: NEON does not have ordered compare builtin
+ // Need to compare a eq a and b eq b to check for NaN
+ // Do AND of results to get final
+ uint32x4_t ceqaa =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t ceqbb =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_u32(vandq_u32(ceqaa, ceqbb));
+}
+
+// Compares for ordered.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/343t62da(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpord_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmpord_ps(a, b));
+}
+
+// Compares for unordered.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/khy6fk1t(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpunord_ps(__m128 a, __m128 b)
+{
+ uint32x4_t f32a =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t f32b =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ return vreinterpretq_m128_u32(vmvnq_u32(vandq_u32(f32a, f32b)));
+}
+
+// Compares for unordered.
+// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/2as2387b(v=vs.100)
+FORCE_INLINE __m128 _mm_cmpunord_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(a, _mm_cmpunord_ps(a, b));
+}
+
+// Compares the lower single-precision floating point scalar values of a and b
+// using a less than operation. :
+// https://msdn.microsoft.com/en-us/library/2kwe606b(v=vs.90).aspx Important
+// note!! The documentation on MSDN is incorrect! If either of the values is a
+// NAN the docs say you will get a one, but in fact, it will return a zero!!
+FORCE_INLINE int _mm_comilt_ss(__m128 a, __m128 b)
+{
+ uint32x4_t a_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t b_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
+ uint32x4_t a_lt_b =
+ vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_lt_b), 0) != 0) ? 1 : 0;
+}
+
+// Compares the lower single-precision floating point scalar values of a and b
+// using a greater than operation. :
+// https://msdn.microsoft.com/en-us/library/b0738e0t(v=vs.100).aspx
+FORCE_INLINE int _mm_comigt_ss(__m128 a, __m128 b)
+{
+ // return vgetq_lane_u32(vcgtq_f32(vreinterpretq_f32_m128(a),
+ // vreinterpretq_f32_m128(b)), 0);
+ uint32x4_t a_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t b_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
+ uint32x4_t a_gt_b =
+ vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_gt_b), 0) != 0) ? 1 : 0;
+}
+
+// Compares the lower single-precision floating point scalar values of a and b
+// using a less than or equal operation. :
+// https://msdn.microsoft.com/en-us/library/1w4t7c57(v=vs.90).aspx
+FORCE_INLINE int _mm_comile_ss(__m128 a, __m128 b)
+{
+ // return vgetq_lane_u32(vcleq_f32(vreinterpretq_f32_m128(a),
+ // vreinterpretq_f32_m128(b)), 0);
+ uint32x4_t a_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t b_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
+ uint32x4_t a_le_b =
+ vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_le_b), 0) != 0) ? 1 : 0;
+}
+
+// Compares the lower single-precision floating point scalar values of a and b
+// using a greater than or equal operation. :
+// https://msdn.microsoft.com/en-us/library/8t80des6(v=vs.100).aspx
+FORCE_INLINE int _mm_comige_ss(__m128 a, __m128 b)
+{
+ // return vgetq_lane_u32(vcgeq_f32(vreinterpretq_f32_m128(a),
+ // vreinterpretq_f32_m128(b)), 0);
+ uint32x4_t a_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t b_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
+ uint32x4_t a_ge_b =
+ vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_ge_b), 0) != 0) ? 1 : 0;
+}
+
+// Compares the lower single-precision floating point scalar values of a and b
+// using an equality operation. :
+// https://msdn.microsoft.com/en-us/library/93yx2h2b(v=vs.100).aspx
+FORCE_INLINE int _mm_comieq_ss(__m128 a, __m128 b)
+{
+ // return vgetq_lane_u32(vceqq_f32(vreinterpretq_f32_m128(a),
+ // vreinterpretq_f32_m128(b)), 0);
+ uint32x4_t a_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t b_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
+ uint32x4_t a_eq_b =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b));
+ return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_eq_b), 0) != 0) ? 1 : 0;
+}
+
+// Compares the lower single-precision floating point scalar values of a and b
+// using an inequality operation. :
+// https://msdn.microsoft.com/en-us/library/bafh5e0a(v=vs.90).aspx
+FORCE_INLINE int _mm_comineq_ss(__m128 a, __m128 b)
+{
+ // return !vgetq_lane_u32(vceqq_f32(vreinterpretq_f32_m128(a),
+ // vreinterpretq_f32_m128(b)), 0);
+ uint32x4_t a_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a));
+ uint32x4_t b_not_nan =
+ vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b));
+ uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan));
+ uint32x4_t a_neq_b = vmvnq_u32(
+ vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+ return (vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_neq_b), 0) != 0) ? 1 : 0;
+}
+
+// according to the documentation, these intrinsics behave the same as the
+// non-'u' versions. We'll just alias them here.
+#define _mm_ucomieq_ss _mm_comieq_ss
+#define _mm_ucomige_ss _mm_comige_ss
+#define _mm_ucomigt_ss _mm_comigt_ss
+#define _mm_ucomile_ss _mm_comile_ss
+#define _mm_ucomilt_ss _mm_comilt_ss
+#define _mm_ucomineq_ss _mm_comineq_ss
+
+/* Conversions */
+
+// Convert packed signed 32-bit integers in b to packed single-precision
+// (32-bit) floating-point elements, store the results in the lower 2 elements
+// of dst, and copy the upper 2 packed elements from a to the upper elements of
+// dst.
+//
+// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
+// dst[63:32] := Convert_Int32_To_FP32(b[63:32])
+// dst[95:64] := a[95:64]
+// dst[127:96] := a[127:96]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_pi2ps
+FORCE_INLINE __m128 _mm_cvt_pi2ps(__m128 a, __m64 b)
+{
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)),
+ vget_high_f32(vreinterpretq_f32_m128(a))));
+}
+
+// Convert the signed 32-bit integer b to a single-precision (32-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper 3 packed elements from a to the upper elements of dst.
+//
+// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_si2ss
+FORCE_INLINE __m128 _mm_cvt_si2ss(__m128 a, int b)
+{
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0));
+}
+
+// Convert the signed 32-bit integer b to a single-precision (32-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper 3 packed elements from a to the upper elements of dst.
+//
+// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi32_ss
+#define _mm_cvtsi32_ss(a, b) _mm_cvt_si2ss(a, b)
+
+// Convert the signed 64-bit integer b to a single-precision (32-bit)
+// floating-point element, store the result in the lower element of dst, and
+// copy the upper 3 packed elements from a to the upper elements of dst.
+//
+// dst[31:0] := Convert_Int64_To_FP32(b[63:0])
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_ss
+FORCE_INLINE __m128 _mm_cvtsi64_ss(__m128 a, int64_t b)
+{
+ return vreinterpretq_m128_f32(
+ vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0));
+}
+
+// Convert the lower single-precision (32-bit) floating-point element in a to a
+// 32-bit integer, and store the result in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ss2si
+FORCE_INLINE int _mm_cvt_ss2si(__m128 a)
+{
+#if defined(__aarch64__)
+ return vgetq_lane_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a)), 0);
+#else
+ float32_t data = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ float32_t diff = data - floor(data);
+ if (diff > 0.5)
+ return (int32_t) ceil(data);
+ if (unlikely(diff == 0.5)) {
+ int32_t f = (int32_t) floor(data);
+ int32_t c = (int32_t) ceil(data);
+ return c & 1 ? f : c;
+ }
+ return (int32_t) floor(data);
+#endif
+}
+
+// Convert packed 16-bit integers in a to packed single-precision (32-bit)
+// floating-point elements, and store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// m := j*32
+// dst[m+31:m] := Convert_Int16_To_FP32(a[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi16_ps
+FORCE_INLINE __m128 _mm_cvtpi16_ps(__m64 a)
+{
+ return vreinterpretq_m128_f32(
+ vcvtq_f32_s32(vmovl_s16(vreinterpret_s16_m64(a))));
+}
+
+// Convert packed 32-bit integers in b to packed single-precision (32-bit)
+// floating-point elements, store the results in the lower 2 elements of dst,
+// and copy the upper 2 packed elements from a to the upper elements of dst.
+//
+// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
+// dst[63:32] := Convert_Int32_To_FP32(b[63:32])
+// dst[95:64] := a[95:64]
+// dst[127:96] := a[127:96]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32_ps
+FORCE_INLINE __m128 _mm_cvtpi32_ps(__m128 a, __m64 b)
+{
+ return vreinterpretq_m128_f32(
+ vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)),
+ vget_high_f32(vreinterpretq_f32_m128(a))));
+}
+
+// Convert packed signed 32-bit integers in a to packed single-precision
+// (32-bit) floating-point elements, store the results in the lower 2 elements
+// of dst, then covert the packed signed 32-bit integers in b to
+// single-precision (32-bit) floating-point element, and store the results in
+// the upper 2 elements of dst.
+//
+// dst[31:0] := Convert_Int32_To_FP32(a[31:0])
+// dst[63:32] := Convert_Int32_To_FP32(a[63:32])
+// dst[95:64] := Convert_Int32_To_FP32(b[31:0])
+// dst[127:96] := Convert_Int32_To_FP32(b[63:32])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32x2_ps
+FORCE_INLINE __m128 _mm_cvtpi32x2_ps(__m64 a, __m64 b)
+{
+ return vreinterpretq_m128_f32(vcvtq_f32_s32(
+ vcombine_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b))));
+}
+
+// Convert the lower packed 8-bit integers in a to packed single-precision
+// (32-bit) floating-point elements, and store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*8
+// m := j*32
+// dst[m+31:m] := Convert_Int8_To_FP32(a[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi8_ps
+FORCE_INLINE __m128 _mm_cvtpi8_ps(__m64 a)
+{
+ return vreinterpretq_m128_f32(vcvtq_f32_s32(
+ vmovl_s16(vget_low_s16(vmovl_s8(vreinterpret_s8_m64(a))))));
+}
+
+// Convert packed unsigned 16-bit integers in a to packed single-precision
+// (32-bit) floating-point elements, and store the results in dst.
+//
+// FOR j := 0 to 3
+// i := j*16
+// m := j*32
+// dst[m+31:m] := Convert_UInt16_To_FP32(a[i+15:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu16_ps
+FORCE_INLINE __m128 _mm_cvtpu16_ps(__m64 a)
+{
+ return vreinterpretq_m128_f32(
+ vcvtq_f32_u32(vmovl_u16(vreinterpret_u16_m64(a))));
+}
+
+// Convert the lower packed unsigned 8-bit integers in a to packed
+// single-precision (32-bit) floating-point elements, and store the results in
+// dst.
+//
+// FOR j := 0 to 3
+// i := j*8
+// m := j*32
+// dst[m+31:m] := Convert_UInt8_To_FP32(a[i+7:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu8_ps
+FORCE_INLINE __m128 _mm_cvtpu8_ps(__m64 a)
+{
+ return vreinterpretq_m128_f32(vcvtq_f32_u32(
+ vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_m64(a))))));
+}
+
+// Converts the four single-precision, floating-point values of a to signed
+// 32-bit integer values using truncate.
+// https://msdn.microsoft.com/en-us/library/vstudio/1h005y6x(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a)
+{
+ return vreinterpretq_m128i_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)));
+}
+
+// Convert the lower double-precision (64-bit) floating-point element in a to a
+// 64-bit integer with truncation, and store the result in dst.
+//
+// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64
+FORCE_INLINE int64_t _mm_cvttsd_si64(__m128d a)
+{
+#if defined(__aarch64__)
+ return vgetq_lane_s64(vcvtq_s64_f64(vreinterpretq_f64_m128d(a)), 0);
+#else
+ double ret = *((double *) &a);
+ return (int64_t) ret;
+#endif
+}
+
+// Convert the lower double-precision (64-bit) floating-point element in a to a
+// 64-bit integer with truncation, and store the result in dst.
+//
+// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64x
+#define _mm_cvttsd_si64x(a) _mm_cvttsd_si64(a)
+
+// Converts the four signed 32-bit integer values of a to single-precision,
+// floating-point values
+// https://msdn.microsoft.com/en-us/library/vstudio/36bwxcx5(v=vs.100).aspx
+FORCE_INLINE __m128 _mm_cvtepi32_ps(__m128i a)
+{
+ return vreinterpretq_m128_f32(vcvtq_f32_s32(vreinterpretq_s32_m128i(a)));
+}
+
+// Converts the four unsigned 8-bit integers in the lower 16 bits to four
+// unsigned 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu8_epi16(__m128i a)
+{
+ uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */
+ uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */
+ return vreinterpretq_m128i_u16(u16x8);
+}
+
+// Converts the four unsigned 8-bit integers in the lower 32 bits to four
+// unsigned 32-bit integers.
+// https://msdn.microsoft.com/en-us/library/bb531467%28v=vs.100%29.aspx
+FORCE_INLINE __m128i _mm_cvtepu8_epi32(__m128i a)
+{
+ uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */
+ uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */
+ uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000D 000C 000B 000A */
+ return vreinterpretq_m128i_u32(u32x4);
+}
+
+// Converts the two unsigned 8-bit integers in the lower 16 bits to two
+// unsigned 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu8_epi64(__m128i a)
+{
+ uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx xxBA */
+ uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0x0x 0B0A */
+ uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */
+ uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */
+ return vreinterpretq_m128i_u64(u64x2);
+}
+
+// Converts the four unsigned 8-bit integers in the lower 16 bits to four
+// unsigned 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi8_epi16(__m128i a)
+{
+ int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */
+ int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */
+ return vreinterpretq_m128i_s16(s16x8);
+}
+
+// Converts the four unsigned 8-bit integers in the lower 32 bits to four
+// unsigned 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi8_epi32(__m128i a)
+{
+ int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */
+ int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */
+ int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000D 000C 000B 000A */
+ return vreinterpretq_m128i_s32(s32x4);
+}
+
+// Converts the two signed 8-bit integers in the lower 32 bits to four
+// signed 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi8_epi64(__m128i a)
+{
+ int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx xxBA */
+ int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0x0x 0B0A */
+ int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */
+ int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */
+ return vreinterpretq_m128i_s64(s64x2);
+}
+
+// Converts the four signed 16-bit integers in the lower 64 bits to four signed
+// 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi16_epi32(__m128i a)
+{
+ return vreinterpretq_m128i_s32(
+ vmovl_s16(vget_low_s16(vreinterpretq_s16_m128i(a))));
+}
+
+// Converts the two signed 16-bit integers in the lower 32 bits two signed
+// 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi16_epi64(__m128i a)
+{
+ int16x8_t s16x8 = vreinterpretq_s16_m128i(a); /* xxxx xxxx xxxx 0B0A */
+ int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */
+ int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */
+ return vreinterpretq_m128i_s64(s64x2);
+}
+
+// Converts the four unsigned 16-bit integers in the lower 64 bits to four
+// unsigned 32-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu16_epi32(__m128i a)
+{
+ return vreinterpretq_m128i_u32(
+ vmovl_u16(vget_low_u16(vreinterpretq_u16_m128i(a))));
+}
+
+// Converts the two unsigned 16-bit integers in the lower 32 bits to two
+// unsigned 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu16_epi64(__m128i a)
+{
+ uint16x8_t u16x8 = vreinterpretq_u16_m128i(a); /* xxxx xxxx xxxx 0B0A */
+ uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */
+ uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */
+ return vreinterpretq_m128i_u64(u64x2);
+}
+
+// Converts the two unsigned 32-bit integers in the lower 64 bits to two
+// unsigned 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepu32_epi64(__m128i a)
+{
+ return vreinterpretq_m128i_u64(
+ vmovl_u32(vget_low_u32(vreinterpretq_u32_m128i(a))));
+}
+
+// Converts the two signed 32-bit integers in the lower 64 bits to two signed
+// 64-bit integers.
+FORCE_INLINE __m128i _mm_cvtepi32_epi64(__m128i a)
+{
+ return vreinterpretq_m128i_s64(
+ vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a))));
+}
+
+// Converts the four single-precision, floating-point values of a to signed
+// 32-bit integer values.
+//
+// r0 := (int) a0
+// r1 := (int) a1
+// r2 := (int) a2
+// r3 := (int) a3
+//
+// https://msdn.microsoft.com/en-us/library/vstudio/xdc42k5e(v=vs.100).aspx
+// *NOTE*. The default rounding mode on SSE is 'round to even', which ARMv7-A
+// does not support! It is supported on ARMv8-A however.
+FORCE_INLINE __m128i _mm_cvtps_epi32(__m128 a)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s32(vcvtnq_s32_f32(a));
+#else
+ uint32x4_t signmask = vdupq_n_u32(0x80000000);
+ float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a),
+ vdupq_n_f32(0.5f)); /* +/- 0.5 */
+ int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(
+ vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/
+ int32x4_t r_trunc =
+ vcvtq_s32_f32(vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */
+ int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(
+ vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */
+ int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone),
+ vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */
+ float32x4_t delta = vsubq_f32(
+ vreinterpretq_f32_m128(a),
+ vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */
+ uint32x4_t is_delta_half = vceqq_f32(delta, half); /* delta == +/- 0.5 */
+ return vreinterpretq_m128i_s32(vbslq_s32(is_delta_half, r_even, r_normal));
+#endif
+}
+
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 16-bit integers, and store the results in dst. Note: this intrinsic
+// will generate 0x7FFF, rather than 0x8000, for input values between 0x7FFF and
+// 0x7FFFFFFF.
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi16
+FORCE_INLINE __m64 _mm_cvtps_pi16(__m128 a)
+{
+ return vreinterpret_m64_s16(
+ vmovn_s32(vreinterpretq_s32_m128i(_mm_cvtps_epi32(a))));
+}
+
+// Copy the lower 32-bit integer in a to dst.
+//
+// dst[31:0] := a[31:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si32
+FORCE_INLINE int _mm_cvtsi128_si32(__m128i a)
+{
+ return vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0);
+}
+
+// Copy the lower 64-bit integer in a to dst.
+//
+// dst[63:0] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64
+FORCE_INLINE int64_t _mm_cvtsi128_si64(__m128i a)
+{
+ return vgetq_lane_s64(vreinterpretq_s64_m128i(a), 0);
+}
+
+// Copy the lower 64-bit integer in a to dst.
+//
+// dst[63:0] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64x
+#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a)
+
+// Moves 32-bit integer a to the least significant 32 bits of an __m128 object,
+// zero extending the upper bits.
+//
+// r0 := a
+// r1 := 0x0
+// r2 := 0x0
+// r3 := 0x0
+//
+// https://msdn.microsoft.com/en-us/library/ct3539ha%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_cvtsi32_si128(int a)
+{
+ return vreinterpretq_m128i_s32(vsetq_lane_s32(a, vdupq_n_s32(0), 0));
+}
+
+// Moves 64-bit integer a to the least significant 64 bits of an __m128 object,
+// zero extending the upper bits.
+//
+// r0 := a
+// r1 := 0x0
+FORCE_INLINE __m128i _mm_cvtsi64_si128(int64_t a)
+{
+ return vreinterpretq_m128i_s64(vsetq_lane_s64(a, vdupq_n_s64(0), 0));
+}
+
+// Cast vector of type __m128 to type __m128d. This intrinsic is only used for
+// compilation and does not generate any instructions, thus it has zero latency.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castps_pd
+FORCE_INLINE __m128d _mm_castps_pd(__m128 a)
+{
+ return vreinterpretq_m128d_s32(vreinterpretq_s32_m128(a));
+}
+
+// Applies a type cast to reinterpret four 32-bit floating point values passed
+// in as a 128-bit parameter as packed 32-bit integers.
+// https://msdn.microsoft.com/en-us/library/bb514099.aspx
+FORCE_INLINE __m128i _mm_castps_si128(__m128 a)
+{
+ return vreinterpretq_m128i_s32(vreinterpretq_s32_m128(a));
+}
+
+// Cast vector of type __m128i to type __m128d. This intrinsic is only used for
+// compilation and does not generate any instructions, thus it has zero latency.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castsi128_pd
+FORCE_INLINE __m128d _mm_castsi128_pd(__m128i a)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vreinterpretq_f64_m128i(a));
+#else
+ return vreinterpretq_m128d_f32(vreinterpretq_f32_m128i(a));
+#endif
+}
+
+// Applies a type cast to reinterpret four 32-bit integers passed in as a
+// 128-bit parameter as packed 32-bit floating point values.
+// https://msdn.microsoft.com/en-us/library/bb514029.aspx
+FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a)
+{
+ return vreinterpretq_m128_s32(vreinterpretq_s32_m128i(a));
+}
+
+// Loads 128-bit value. :
+// https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx
+FORCE_INLINE __m128i _mm_load_si128(const __m128i *p)
+{
+ return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p));
+}
+
+// Load a double-precision (64-bit) floating-point element from memory into both
+// elements of dst.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load1_pd
+FORCE_INLINE __m128d _mm_load1_pd(const double *p)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(vld1q_dup_f64(p));
+#else
+ return vreinterpretq_m128d_s64(vdupq_n_s64(*(const int64_t *) p));
+#endif
+}
+
+// Load a double-precision (64-bit) floating-point element from memory into both
+// elements of dst.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd1
+#define _mm_load_pd1 _mm_load1_pd
+
+// Load a double-precision (64-bit) floating-point element from memory into the
+// upper element of dst, and copy the lower element from a to dst. mem_addr does
+// not need to be aligned on any particular boundary.
+//
+// dst[63:0] := a[63:0]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadh_pd
+FORCE_INLINE __m128d _mm_loadh_pd(__m128d a, const double *p)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vcombine_f64(vget_low_f64(vreinterpretq_f64_m128d(a)), vld1_f64(p)));
+#else
+ return vreinterpretq_m128d_f32(vcombine_f32(
+ vget_low_f32(vreinterpretq_f32_m128d(a)), vld1_f32((const float *) p)));
+#endif
+}
+
+// Load a double-precision (64-bit) floating-point element from memory into both
+// elements of dst.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd1
+#define _mm_load_pd1 _mm_load1_pd
+
+// Load a double-precision (64-bit) floating-point element from memory into both
+// elements of dst.
+//
+// dst[63:0] := MEM[mem_addr+63:mem_addr]
+// dst[127:64] := MEM[mem_addr+63:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loaddup_pd
+#define _mm_loaddup_pd _mm_load1_pd
+
+// Loads 128-bit value. :
+// https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx
+FORCE_INLINE __m128i _mm_loadu_si128(const __m128i *p)
+{
+ return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p));
+}
+
+// Load unaligned 32-bit integer from memory into the first element of dst.
+//
+// dst[31:0] := MEM[mem_addr+31:mem_addr]
+// dst[MAX:32] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si32
+FORCE_INLINE __m128i _mm_loadu_si32(const void *p)
+{
+ return vreinterpretq_m128i_s32(
+ vsetq_lane_s32(*(const int32_t *) p, vdupq_n_s32(0), 0));
+}
+
+// Convert packed double-precision (64-bit) floating-point elements in a to
+// packed single-precision (32-bit) floating-point elements, and store the
+// results in dst.
+//
+// FOR j := 0 to 1
+// i := 32*j
+// k := 64*j
+// dst[i+31:i] := Convert_FP64_To_FP32(a[k+64:k])
+// ENDFOR
+// dst[127:64] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_ps
+FORCE_INLINE __m128 _mm_cvtpd_ps(__m128d a)
+{
+#if defined(__aarch64__)
+ float32x2_t tmp = vcvt_f32_f64(vreinterpretq_f64_m128d(a));
+ return vreinterpretq_m128_f32(vcombine_f32(tmp, vdup_n_f32(0)));
+#else
+ float a0 = (float) ((double *) &a)[0];
+ float a1 = (float) ((double *) &a)[1];
+ return _mm_set_ps(0, 0, a1, a0);
+#endif
+}
+
+// Copy the lower double-precision (64-bit) floating-point element of a to dst.
+//
+// dst[63:0] := a[63:0]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_f64
+FORCE_INLINE double _mm_cvtsd_f64(__m128d a)
+{
+#if defined(__aarch64__)
+ return (double) vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0);
+#else
+ return ((double *) &a)[0];
+#endif
+}
+
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed double-precision (64-bit) floating-point elements, and store the
+// results in dst.
+//
+// FOR j := 0 to 1
+// i := 64*j
+// k := 32*j
+// dst[i+63:i] := Convert_FP32_To_FP64(a[k+31:k])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pd
+FORCE_INLINE __m128d _mm_cvtps_pd(__m128 a)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vcvt_f64_f32(vget_low_f32(vreinterpretq_f32_m128(a))));
+#else
+ double a0 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
+ double a1 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 1);
+ return _mm_set_pd(a1, a0);
+#endif
+}
+
+// Cast vector of type __m128d to type __m128i. This intrinsic is only used for
+// compilation and does not generate any instructions, thus it has zero latency.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_si128
+FORCE_INLINE __m128i _mm_castpd_si128(__m128d a)
+{
+ return vreinterpretq_m128i_s64(vreinterpretq_s64_m128d(a));
+}
+
+// Cast vector of type __m128d to type __m128. This intrinsic is only used for
+// compilation and does not generate any instructions, thus it has zero latency.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_ps
+FORCE_INLINE __m128 _mm_castpd_ps(__m128d a)
+{
+ return vreinterpretq_m128_s64(vreinterpretq_s64_m128d(a));
+}
+
+// Blend packed single-precision (32-bit) floating-point elements from a and b
+// using mask, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blendv_ps
+FORCE_INLINE __m128 _mm_blendv_ps(__m128 _a, __m128 _b, __m128 _mask)
+{
+ // Use a signed shift right to create a mask with the sign bit
+ uint32x4_t mask =
+ vreinterpretq_u32_s32(vshrq_n_s32(vreinterpretq_s32_m128(_mask), 31));
+ float32x4_t a = vreinterpretq_f32_m128(_a);
+ float32x4_t b = vreinterpretq_f32_m128(_b);
+ return vreinterpretq_m128_f32(vbslq_f32(mask, b, a));
+}
+
+// Blend packed single-precision (32-bit) floating-point elements from a and b
+// using mask, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blend_ps
+FORCE_INLINE __m128 _mm_blend_ps(__m128 _a, __m128 _b, const char imm8)
+{
+ const uint32_t ALIGN_STRUCT(16)
+ data[4] = {((imm8) & (1 << 0)) ? UINT32_MAX : 0,
+ ((imm8) & (1 << 1)) ? UINT32_MAX : 0,
+ ((imm8) & (1 << 2)) ? UINT32_MAX : 0,
+ ((imm8) & (1 << 3)) ? UINT32_MAX : 0};
+ uint32x4_t mask = vld1q_u32(data);
+ float32x4_t a = vreinterpretq_f32_m128(_a);
+ float32x4_t b = vreinterpretq_f32_m128(_b);
+ return vreinterpretq_m128_f32(vbslq_f32(mask, b, a));
+}
+
+// Blend packed double-precision (64-bit) floating-point elements from a and b
+// using mask, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blendv_pd
+FORCE_INLINE __m128d _mm_blendv_pd(__m128d _a, __m128d _b, __m128d _mask)
+{
+ uint64x2_t mask =
+ vreinterpretq_u64_s64(vshrq_n_s64(vreinterpretq_s64_m128d(_mask), 63));
+#if defined(__aarch64__)
+ float64x2_t a = vreinterpretq_f64_m128d(_a);
+ float64x2_t b = vreinterpretq_f64_m128d(_b);
+ return vreinterpretq_m128d_f64(vbslq_f64(mask, b, a));
+#else
+ uint64x2_t a = vreinterpretq_u64_m128d(_a);
+ uint64x2_t b = vreinterpretq_u64_m128d(_b);
+ return vreinterpretq_m128d_u64(vbslq_u64(mask, b, a));
+#endif
+}
+
+typedef struct {
+ uint16_t res0;
+ uint8_t res1 : 6;
+ uint8_t bit22 : 1;
+ uint8_t bit23 : 1;
+ uint8_t res2;
+#if defined(__aarch64__)
+ uint32_t res3;
+#endif
+} fpcr_bitfield;
+
+// Macro: Set the rounding mode bits of the MXCSR control and status register to
+// the value in unsigned 32-bit integer a. The rounding mode may contain any of
+// the following flags: _MM_ROUND_NEAREST, _MM_ROUND_DOWN, _MM_ROUND_UP,
+// _MM_ROUND_TOWARD_ZERO
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_ROUNDING_MODE
+FORCE_INLINE void _MM_SET_ROUNDING_MODE(int rounding)
+{
+ union {
+ fpcr_bitfield field;
+#if defined(__aarch64__)
+ uint64_t value;
+#else
+ uint32_t value;
+#endif
+ } r;
+
+#if defined(__aarch64__)
+ asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */
+#else
+ asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
+#endif
+
+ switch (rounding) {
+ case _MM_ROUND_TOWARD_ZERO:
+ r.field.bit22 = 1;
+ r.field.bit23 = 1;
+ break;
+ case _MM_ROUND_DOWN:
+ r.field.bit22 = 0;
+ r.field.bit23 = 1;
+ break;
+ case _MM_ROUND_UP:
+ r.field.bit22 = 1;
+ r.field.bit23 = 0;
+ break;
+ default: //_MM_ROUND_NEAREST
+ r.field.bit22 = 0;
+ r.field.bit23 = 0;
+ }
+
+#if defined(__aarch64__)
+ asm volatile("msr FPCR, %0" ::"r"(r)); /* write */
+#else
+ asm volatile("vmsr FPSCR, %0" ::"r"(r)); /* write */
+#endif
+}
+
+FORCE_INLINE void _mm_setcsr(unsigned int a)
+{
+ _MM_SET_ROUNDING_MODE(a);
+}
+
+// Round the packed single-precision (32-bit) floating-point elements in a using
+// the rounding parameter, and store the results as packed single-precision
+// floating-point elements in dst.
+// software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_ps
+FORCE_INLINE __m128 _mm_round_ps(__m128 a, int rounding)
+{
+#if defined(__aarch64__)
+ switch (rounding) {
+ case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC):
+ return vreinterpretq_m128_f32(vrndnq_f32(vreinterpretq_f32_m128(a)));
+ case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC):
+ return vreinterpretq_m128_f32(vrndmq_f32(vreinterpretq_f32_m128(a)));
+ case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC):
+ return vreinterpretq_m128_f32(vrndpq_f32(vreinterpretq_f32_m128(a)));
+ case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC):
+ return vreinterpretq_m128_f32(vrndq_f32(vreinterpretq_f32_m128(a)));
+ default: //_MM_FROUND_CUR_DIRECTION
+ return vreinterpretq_m128_f32(vrndiq_f32(vreinterpretq_f32_m128(a)));
+ }
+#else
+ float *v_float = (float *) &a;
+ __m128 zero, neg_inf, pos_inf;
+
+ switch (rounding) {
+ case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC):
+ return _mm_cvtepi32_ps(_mm_cvtps_epi32(a));
+ case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC):
+ return (__m128){floorf(v_float[0]), floorf(v_float[1]),
+ floorf(v_float[2]), floorf(v_float[3])};
+ case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC):
+ return (__m128){ceilf(v_float[0]), ceilf(v_float[1]), ceilf(v_float[2]),
+ ceilf(v_float[3])};
+ case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC):
+ zero = _mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f);
+ neg_inf = _mm_set_ps(floorf(v_float[0]), floorf(v_float[1]),
+ floorf(v_float[2]), floorf(v_float[3]));
+ pos_inf = _mm_set_ps(ceilf(v_float[0]), ceilf(v_float[1]),
+ ceilf(v_float[2]), ceilf(v_float[3]));
+ return _mm_blendv_ps(pos_inf, neg_inf, _mm_cmple_ps(a, zero));
+ default: //_MM_FROUND_CUR_DIRECTION
+ return (__m128){roundf(v_float[0]), roundf(v_float[1]),
+ roundf(v_float[2]), roundf(v_float[3])};
+ }
+#endif
+}
+
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 32-bit integers, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := 32*j
+// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ps2pi
+FORCE_INLINE __m64 _mm_cvt_ps2pi(__m128 a)
+{
+#if defined(__aarch64__)
+ return vreinterpret_m64_s32(
+ vget_low_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a))));
+#else
+ return vreinterpret_m64_s32(
+ vcvt_s32_f32(vget_low_f32(vreinterpretq_f32_m128(
+ _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)))));
+#endif
+}
+
+// Convert packed single-precision (32-bit) floating-point elements in a to
+// packed 32-bit integers, and store the results in dst.
+//
+// FOR j := 0 to 1
+// i := 32*j
+// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i])
+// ENDFOR
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi32
+#define _mm_cvtps_pi32(a) _mm_cvt_ps2pi(a)
+
+// Round the packed single-precision (32-bit) floating-point elements in a up to
+// an integer value, and store the results as packed single-precision
+// floating-point elements in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_ps
+FORCE_INLINE __m128 _mm_ceil_ps(__m128 a)
+{
+ return _mm_round_ps(a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+}
+
+// Round the lower single-precision (32-bit) floating-point element in b up to
+// an integer value, store the result as a single-precision floating-point
+// element in the lower element of dst, and copy the upper 3 packed elements
+// from a to the upper elements of dst.
+//
+// dst[31:0] := CEIL(b[31:0])
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_ss
+FORCE_INLINE __m128 _mm_ceil_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(
+ a, _mm_round_ps(b, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC));
+}
+
+// Round the packed single-precision (32-bit) floating-point elements in a down
+// to an integer value, and store the results as packed single-precision
+// floating-point elements in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ps
+FORCE_INLINE __m128 _mm_floor_ps(__m128 a)
+{
+ return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+}
+
+// Round the lower single-precision (32-bit) floating-point element in b down to
+// an integer value, store the result as a single-precision floating-point
+// element in the lower element of dst, and copy the upper 3 packed elements
+// from a to the upper elements of dst.
+//
+// dst[31:0] := FLOOR(b[31:0])
+// dst[127:32] := a[127:32]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ss
+FORCE_INLINE __m128 _mm_floor_ss(__m128 a, __m128 b)
+{
+ return _mm_move_ss(
+ a, _mm_round_ps(b, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC));
+}
+
+// Load 128-bits of integer data from unaligned memory into dst. This intrinsic
+// may perform better than _mm_loadu_si128 when the data crosses a cache line
+// boundary.
+//
+// dst[127:0] := MEM[mem_addr+127:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_lddqu_si128
+#define _mm_lddqu_si128 _mm_loadu_si128
+
+/* Miscellaneous Operations */
+
+// Shifts the 8 signed 16-bit integers in a right by count bits while shifting
+// in the sign bit.
+//
+// r0 := a0 >> count
+// r1 := a1 >> count
+// ...
+// r7 := a7 >> count
+//
+// https://msdn.microsoft.com/en-us/library/3c9997dk(v%3dvs.90).aspx
+FORCE_INLINE __m128i _mm_sra_epi16(__m128i a, __m128i count)
+{
+ int64_t c = (int64_t) vget_low_s64((int64x2_t) count);
+ if (unlikely(c > 15))
+ return _mm_cmplt_epi16(a, _mm_setzero_si128());
+ return vreinterpretq_m128i_s16(vshlq_s16((int16x8_t) a, vdupq_n_s16(-c)));
+}
+
+// Shifts the 4 signed 32-bit integers in a right by count bits while shifting
+// in the sign bit.
+//
+// r0 := a0 >> count
+// r1 := a1 >> count
+// r2 := a2 >> count
+// r3 := a3 >> count
+//
+// https://msdn.microsoft.com/en-us/library/ce40009e(v%3dvs.100).aspx
+FORCE_INLINE __m128i _mm_sra_epi32(__m128i a, __m128i count)
+{
+ int64_t c = (int64_t) vget_low_s64((int64x2_t) count);
+ if (unlikely(c > 31))
+ return _mm_cmplt_epi32(a, _mm_setzero_si128());
+ return vreinterpretq_m128i_s32(vshlq_s32((int32x4_t) a, vdupq_n_s32(-c)));
+}
+
+// Packs the 16 signed 16-bit integers from a and b into 8-bit integers and
+// saturates.
+// https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s8(
+ vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)),
+ vqmovn_s16(vreinterpretq_s16_m128i(b))));
+}
+
+// Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned
+// integers and saturates.
+//
+// r0 := UnsignedSaturate(a0)
+// r1 := UnsignedSaturate(a1)
+// ...
+// r7 := UnsignedSaturate(a7)
+// r8 := UnsignedSaturate(b0)
+// r9 := UnsignedSaturate(b1)
+// ...
+// r15 := UnsignedSaturate(b7)
+//
+// https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)),
+ vqmovun_s16(vreinterpretq_s16_m128i(b))));
+}
+
+// Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers
+// and saturates.
+//
+// r0 := SignedSaturate(a0)
+// r1 := SignedSaturate(a1)
+// r2 := SignedSaturate(a2)
+// r3 := SignedSaturate(a3)
+// r4 := SignedSaturate(b0)
+// r5 := SignedSaturate(b1)
+// r6 := SignedSaturate(b2)
+// r7 := SignedSaturate(b3)
+//
+// https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_s16(
+ vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)),
+ vqmovn_s32(vreinterpretq_s32_m128i(b))));
+}
+
+// Packs the 8 unsigned 32-bit integers from a and b into unsigned 16-bit
+// integers and saturates.
+//
+// r0 := UnsignedSaturate(a0)
+// r1 := UnsignedSaturate(a1)
+// r2 := UnsignedSaturate(a2)
+// r3 := UnsignedSaturate(a3)
+// r4 := UnsignedSaturate(b0)
+// r5 := UnsignedSaturate(b1)
+// r6 := UnsignedSaturate(b2)
+// r7 := UnsignedSaturate(b3)
+FORCE_INLINE __m128i _mm_packus_epi32(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u16(
+ vcombine_u16(vqmovun_s32(vreinterpretq_s32_m128i(a)),
+ vqmovun_s32(vreinterpretq_s32_m128i(b))));
+}
+
+// Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower
+// 8 signed or unsigned 8-bit integers in b.
+//
+// r0 := a0
+// r1 := b0
+// r2 := a1
+// r3 := b1
+// ...
+// r14 := a7
+// r15 := b7
+//
+// https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_unpacklo_epi8(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s8(
+ vzip1q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+#else
+ int8x8_t a1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(a)));
+ int8x8_t b1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(b)));
+ int8x8x2_t result = vzip_s8(a1, b1);
+ return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1]));
+#endif
+}
+
+// Interleaves the lower 4 signed or unsigned 16-bit integers in a with the
+// lower 4 signed or unsigned 16-bit integers in b.
+//
+// r0 := a0
+// r1 := b0
+// r2 := a1
+// r3 := b1
+// r4 := a2
+// r5 := b2
+// r6 := a3
+// r7 := b3
+//
+// https://msdn.microsoft.com/en-us/library/btxb17bw%28v=vs.90%29.aspx
+FORCE_INLINE __m128i _mm_unpacklo_epi16(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s16(
+ vzip1q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+#else
+ int16x4_t a1 = vget_low_s16(vreinterpretq_s16_m128i(a));
+ int16x4_t b1 = vget_low_s16(vreinterpretq_s16_m128i(b));
+ int16x4x2_t result = vzip_s16(a1, b1);
+ return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1]));
+#endif
+}
+
+// Interleaves the lower 2 signed or unsigned 32 - bit integers in a with the
+// lower 2 signed or unsigned 32 - bit integers in b.
+//
+// r0 := a0
+// r1 := b0
+// r2 := a1
+// r3 := b1
+//
+// https://msdn.microsoft.com/en-us/library/x8atst9d(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_unpacklo_epi32(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s32(
+ vzip1q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+#else
+ int32x2_t a1 = vget_low_s32(vreinterpretq_s32_m128i(a));
+ int32x2_t b1 = vget_low_s32(vreinterpretq_s32_m128i(b));
+ int32x2x2_t result = vzip_s32(a1, b1);
+ return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1]));
+#endif
+}
+
+FORCE_INLINE __m128i _mm_unpacklo_epi64(__m128i a, __m128i b)
+{
+ int64x1_t a_l = vget_low_s64(vreinterpretq_s64_m128i(a));
+ int64x1_t b_l = vget_low_s64(vreinterpretq_s64_m128i(b));
+ return vreinterpretq_m128i_s64(vcombine_s64(a_l, b_l));
+}
+
+// Selects and interleaves the lower two single-precision, floating-point values
+// from a and b.
+//
+// r0 := a0
+// r1 := b0
+// r2 := a1
+// r3 := b1
+//
+// https://msdn.microsoft.com/en-us/library/25st103b%28v=vs.90%29.aspx
+FORCE_INLINE __m128 _mm_unpacklo_ps(__m128 a, __m128 b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(
+ vzip1q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#else
+ float32x2_t a1 = vget_low_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b1 = vget_low_f32(vreinterpretq_f32_m128(b));
+ float32x2x2_t result = vzip_f32(a1, b1);
+ return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1]));
+#endif
+}
+
+// Unpack and interleave double-precision (64-bit) floating-point elements from
+// the low half of a and b, and store the results in dst.
+//
+// DEFINE INTERLEAVE_QWORDS(src1[127:0], src2[127:0]) {
+// dst[63:0] := src1[63:0]
+// dst[127:64] := src2[63:0]
+// RETURN dst[127:0]
+// }
+// dst[127:0] := INTERLEAVE_QWORDS(a[127:0], b[127:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_unpacklo_pd
+FORCE_INLINE __m128d _mm_unpacklo_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vzip1q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ return vreinterpretq_m128d_s64(
+ vcombine_s64(vget_low_s64(vreinterpretq_s64_m128d(a)),
+ vget_low_s64(vreinterpretq_s64_m128d(b))));
+#endif
+}
+
+// Unpack and interleave double-precision (64-bit) floating-point elements from
+// the high half of a and b, and store the results in dst.
+//
+// DEFINE INTERLEAVE_HIGH_QWORDS(src1[127:0], src2[127:0]) {
+// dst[63:0] := src1[127:64]
+// dst[127:64] := src2[127:64]
+// RETURN dst[127:0]
+// }
+// dst[127:0] := INTERLEAVE_HIGH_QWORDS(a[127:0], b[127:0])
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_unpackhi_pd
+FORCE_INLINE __m128d _mm_unpackhi_pd(__m128d a, __m128d b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128d_f64(
+ vzip2q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
+#else
+ return vreinterpretq_m128d_s64(
+ vcombine_s64(vget_high_s64(vreinterpretq_s64_m128d(a)),
+ vget_high_s64(vreinterpretq_s64_m128d(b))));
+#endif
+}
+
+// Selects and interleaves the upper two single-precision, floating-point values
+// from a and b.
+//
+// r0 := a2
+// r1 := b2
+// r2 := a3
+// r3 := b3
+//
+// https://msdn.microsoft.com/en-us/library/skccxx7d%28v=vs.90%29.aspx
+FORCE_INLINE __m128 _mm_unpackhi_ps(__m128 a, __m128 b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128_f32(
+ vzip2q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)));
+#else
+ float32x2_t a1 = vget_high_f32(vreinterpretq_f32_m128(a));
+ float32x2_t b1 = vget_high_f32(vreinterpretq_f32_m128(b));
+ float32x2x2_t result = vzip_f32(a1, b1);
+ return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1]));
+#endif
+}
+
+// Interleaves the upper 8 signed or unsigned 8-bit integers in a with the upper
+// 8 signed or unsigned 8-bit integers in b.
+//
+// r0 := a8
+// r1 := b8
+// r2 := a9
+// r3 := b9
+// ...
+// r14 := a15
+// r15 := b15
+//
+// https://msdn.microsoft.com/en-us/library/t5h7783k(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_unpackhi_epi8(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s8(
+ vzip2q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
+#else
+ int8x8_t a1 =
+ vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(a)));
+ int8x8_t b1 =
+ vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(b)));
+ int8x8x2_t result = vzip_s8(a1, b1);
+ return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1]));
+#endif
+}
+
+// Interleaves the upper 4 signed or unsigned 16-bit integers in a with the
+// upper 4 signed or unsigned 16-bit integers in b.
+//
+// r0 := a4
+// r1 := b4
+// r2 := a5
+// r3 := b5
+// r4 := a6
+// r5 := b6
+// r6 := a7
+// r7 := b7
+//
+// https://msdn.microsoft.com/en-us/library/03196cz7(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_unpackhi_epi16(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s16(
+ vzip2q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b)));
+#else
+ int16x4_t a1 = vget_high_s16(vreinterpretq_s16_m128i(a));
+ int16x4_t b1 = vget_high_s16(vreinterpretq_s16_m128i(b));
+ int16x4x2_t result = vzip_s16(a1, b1);
+ return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1]));
+#endif
+}
+
+// Interleaves the upper 2 signed or unsigned 32-bit integers in a with the
+// upper 2 signed or unsigned 32-bit integers in b.
+// https://msdn.microsoft.com/en-us/library/65sa7cbs(v=vs.100).aspx
+FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b)
+{
+#if defined(__aarch64__)
+ return vreinterpretq_m128i_s32(
+ vzip2q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
+#else
+ int32x2_t a1 = vget_high_s32(vreinterpretq_s32_m128i(a));
+ int32x2_t b1 = vget_high_s32(vreinterpretq_s32_m128i(b));
+ int32x2x2_t result = vzip_s32(a1, b1);
+ return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1]));
+#endif
+}
+
+// Interleaves the upper signed or unsigned 64-bit integer in a with the
+// upper signed or unsigned 64-bit integer in b.
+//
+// r0 := a1
+// r1 := b1
+FORCE_INLINE __m128i _mm_unpackhi_epi64(__m128i a, __m128i b)
+{
+ int64x1_t a_h = vget_high_s64(vreinterpretq_s64_m128i(a));
+ int64x1_t b_h = vget_high_s64(vreinterpretq_s64_m128i(b));
+ return vreinterpretq_m128i_s64(vcombine_s64(a_h, b_h));
+}
+
+// Horizontally compute the minimum amongst the packed unsigned 16-bit integers
+// in a, store the minimum and index in dst, and zero the remaining bits in dst.
+//
+// index[2:0] := 0
+// min[15:0] := a[15:0]
+// FOR j := 0 to 7
+// i := j*16
+// IF a[i+15:i] < min[15:0]
+// index[2:0] := j
+// min[15:0] := a[i+15:i]
+// FI
+// ENDFOR
+// dst[15:0] := min[15:0]
+// dst[18:16] := index[2:0]
+// dst[127:19] := 0
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_minpos_epu16
+FORCE_INLINE __m128i _mm_minpos_epu16(__m128i a)
+{
+ __m128i dst;
+ uint16_t min, idx = 0;
+ // Find the minimum value
+#if defined(__aarch64__)
+ min = vminvq_u16(vreinterpretq_u16_m128i(a));
+#else
+ __m64 tmp;
+ tmp = vreinterpret_m64_u16(
+ vmin_u16(vget_low_u16(vreinterpretq_u16_m128i(a)),
+ vget_high_u16(vreinterpretq_u16_m128i(a))));
+ tmp = vreinterpret_m64_u16(
+ vpmin_u16(vreinterpret_u16_m64(tmp), vreinterpret_u16_m64(tmp)));
+ tmp = vreinterpret_m64_u16(
+ vpmin_u16(vreinterpret_u16_m64(tmp), vreinterpret_u16_m64(tmp)));
+ min = vget_lane_u16(vreinterpret_u16_m64(tmp), 0);
+#endif
+ // Get the index of the minimum value
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (min == vgetq_lane_u16(vreinterpretq_u16_m128i(a), 0)) {
+ idx = (uint16_t) i;
+ break;
+ }
+ a = _mm_srli_si128(a, 2);
+ }
+ // Generate result
+ dst = _mm_setzero_si128();
+ dst = vreinterpretq_m128i_u16(
+ vsetq_lane_u16(min, vreinterpretq_u16_m128i(dst), 0));
+ dst = vreinterpretq_m128i_u16(
+ vsetq_lane_u16(idx, vreinterpretq_u16_m128i(dst), 1));
+ return dst;
+}
+
+// Compute the bitwise AND of 128 bits (representing integer data) in a and b,
+// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the
+// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero,
+// otherwise set CF to 0. Return the CF value.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testc_si128
+FORCE_INLINE int _mm_testc_si128(__m128i a, __m128i b)
+{
+ int64x2_t s64 =
+ vandq_s64(vreinterpretq_s64_s32(vmvnq_s32(vreinterpretq_s32_m128i(a))),
+ vreinterpretq_s64_m128i(b));
+ return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1));
+}
+
+// Compute the bitwise AND of 128 bits (representing integer data) in a and b,
+// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the
+// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero,
+// otherwise set CF to 0. Return the ZF value.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testz_si128
+FORCE_INLINE int _mm_testz_si128(__m128i a, __m128i b)
+{
+ int64x2_t s64 =
+ vandq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b));
+ return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1));
+}
+
+// Extracts the selected signed or unsigned 8-bit integer from a and zero
+// extends.
+// FORCE_INLINE int _mm_extract_epi8(__m128i a, __constrange(0,16) int imm)
+#define _mm_extract_epi8(a, imm) vgetq_lane_u8(vreinterpretq_u8_m128i(a), (imm))
+
+// Inserts the least significant 8 bits of b into the selected 8-bit integer
+// of a.
+// FORCE_INLINE __m128i _mm_insert_epi8(__m128i a, int b,
+// __constrange(0,16) int imm)
+#define _mm_insert_epi8(a, b, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s8( \
+ vsetq_lane_s8((b), vreinterpretq_s8_m128i(a), (imm))); \
+ })
+
+// Extracts the selected signed or unsigned 16-bit integer from a and zero
+// extends.
+// https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx
+// FORCE_INLINE int _mm_extract_epi16(__m128i a, __constrange(0,8) int imm)
+#define _mm_extract_epi16(a, imm) \
+ vgetq_lane_u16(vreinterpretq_u16_m128i(a), (imm))
+
+// Inserts the least significant 16 bits of b into the selected 16-bit integer
+// of a.
+// https://msdn.microsoft.com/en-us/library/kaze8hz1%28v=vs.100%29.aspx
+// FORCE_INLINE __m128i _mm_insert_epi16(__m128i a, int b,
+// __constrange(0,8) int imm)
+#define _mm_insert_epi16(a, b, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s16( \
+ vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \
+ })
+
+// Copy a to dst, and insert the 16-bit integer i into dst at the location
+// specified by imm8.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_insert_pi16
+#define _mm_insert_pi16(a, b, imm) \
+ __extension__({ \
+ vreinterpret_m64_s16( \
+ vset_lane_s16((b), vreinterpret_s16_m64(a), (imm))); \
+ })
+
+// Extracts the selected signed or unsigned 32-bit integer from a and zero
+// extends.
+// FORCE_INLINE int _mm_extract_epi32(__m128i a, __constrange(0,4) int imm)
+#define _mm_extract_epi32(a, imm) \
+ vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm))
+
+// Extracts the selected single-precision (32-bit) floating-point from a.
+// FORCE_INLINE int _mm_extract_ps(__m128 a, __constrange(0,4) int imm)
+#define _mm_extract_ps(a, imm) vgetq_lane_s32(vreinterpretq_s32_m128(a), (imm))
+
+// Inserts the least significant 32 bits of b into the selected 32-bit integer
+// of a.
+// FORCE_INLINE __m128i _mm_insert_epi32(__m128i a, int b,
+// __constrange(0,4) int imm)
+#define _mm_insert_epi32(a, b, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s32( \
+ vsetq_lane_s32((b), vreinterpretq_s32_m128i(a), (imm))); \
+ })
+
+// Extracts the selected signed or unsigned 64-bit integer from a and zero
+// extends.
+// FORCE_INLINE __int64 _mm_extract_epi64(__m128i a, __constrange(0,2) int imm)
+#define _mm_extract_epi64(a, imm) \
+ vgetq_lane_s64(vreinterpretq_s64_m128i(a), (imm))
+
+// Inserts the least significant 64 bits of b into the selected 64-bit integer
+// of a.
+// FORCE_INLINE __m128i _mm_insert_epi64(__m128i a, __int64 b,
+// __constrange(0,2) int imm)
+#define _mm_insert_epi64(a, b, imm) \
+ __extension__({ \
+ vreinterpretq_m128i_s64( \
+ vsetq_lane_s64((b), vreinterpretq_s64_m128i(a), (imm))); \
+ })
+
+// Count the number of bits set to 1 in unsigned 32-bit integer a, and
+// return that count in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u32
+FORCE_INLINE int _mm_popcnt_u32(unsigned int a)
+{
+#if defined(__aarch64__)
+#if __has_builtin(__builtin_popcount)
+ return __builtin_popcount(a);
+#else
+ return (int) vaddlv_u8(vcnt_u8(vcreate_u8((uint64_t) a)));
+#endif
+#else
+ uint32_t count = 0;
+ uint8x8_t input_val, count8x8_val;
+ uint16x4_t count16x4_val;
+ uint32x2_t count32x2_val;
+
+ input_val = vld1_u8((uint8_t *) &a);
+ count8x8_val = vcnt_u8(input_val);
+ count16x4_val = vpaddl_u8(count8x8_val);
+ count32x2_val = vpaddl_u16(count16x4_val);
+
+ vst1_u32(&count, count32x2_val);
+ return count;
+#endif
+}
+
+// Count the number of bits set to 1 in unsigned 64-bit integer a, and
+// return that count in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u64
+FORCE_INLINE int64_t _mm_popcnt_u64(uint64_t a)
+{
+#if defined(__aarch64__)
+#if __has_builtin(__builtin_popcountll)
+ return __builtin_popcountll(a);
+#else
+ return (int64_t) vaddlv_u8(vcnt_u8(vcreate_u8(a)));
+#endif
+#else
+ uint64_t count = 0;
+ uint8x8_t input_val, count8x8_val;
+ uint16x4_t count16x4_val;
+ uint32x2_t count32x2_val;
+ uint64x1_t count64x1_val;
+
+ input_val = vld1_u8((uint8_t *) &a);
+ count8x8_val = vcnt_u8(input_val);
+ count16x4_val = vpaddl_u8(count8x8_val);
+ count32x2_val = vpaddl_u16(count16x4_val);
+ count64x1_val = vpaddl_u32(count32x2_val);
+ vst1_u64(&count, count64x1_val);
+ return count;
+#endif
+}
+
+// Macro: Transpose the 4x4 matrix formed by the 4 rows of single-precision
+// (32-bit) floating-point elements in row0, row1, row2, and row3, and store the
+// transposed matrix in these vectors (row0 now contains column 0, etc.).
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=MM_TRANSPOSE4_PS
+#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \
+ do { \
+ float32x4x2_t ROW01 = vtrnq_f32(row0, row1); \
+ float32x4x2_t ROW23 = vtrnq_f32(row2, row3); \
+ row0 = vcombine_f32(vget_low_f32(ROW01.val[0]), \
+ vget_low_f32(ROW23.val[0])); \
+ row1 = vcombine_f32(vget_low_f32(ROW01.val[1]), \
+ vget_low_f32(ROW23.val[1])); \
+ row2 = vcombine_f32(vget_high_f32(ROW01.val[0]), \
+ vget_high_f32(ROW23.val[0])); \
+ row3 = vcombine_f32(vget_high_f32(ROW01.val[1]), \
+ vget_high_f32(ROW23.val[1])); \
+ } while (0)
+
+/* Crypto Extensions */
+
+#if defined(__ARM_FEATURE_CRYPTO)
+// Wraps vmull_p64
+FORCE_INLINE uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
+{
+ poly64_t a = vget_lane_p64(vreinterpret_p64_u64(_a), 0);
+ poly64_t b = vget_lane_p64(vreinterpret_p64_u64(_b), 0);
+ return vreinterpretq_u64_p128(vmull_p64(a, b));
+}
+#else // ARMv7 polyfill
+// ARMv7/some A64 lacks vmull_p64, but it has vmull_p8.
+//
+// vmull_p8 calculates 8 8-bit->16-bit polynomial multiplies, but we need a
+// 64-bit->128-bit polynomial multiply.
+//
+// It needs some work and is somewhat slow, but it is still faster than all
+// known scalar methods.
+//
+// Algorithm adapted to C from
+// https://www.workofard.com/2017/07/ghash-for-low-end-cores/, which is adapted
+// from "Fast Software Polynomial Multiplication on ARM Processors Using the
+// NEON Engine" by Danilo Camara, Conrado Gouvea, Julio Lopez and Ricardo Dahab
+// (https://hal.inria.fr/hal-01506572)
+static uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
+{
+ poly8x8_t a = vreinterpret_p8_u64(_a);
+ poly8x8_t b = vreinterpret_p8_u64(_b);
+
+ // Masks
+ uint8x16_t k48_32 = vcombine_u8(vcreate_u8(0x0000ffffffffffff),
+ vcreate_u8(0x00000000ffffffff));
+ uint8x16_t k16_00 = vcombine_u8(vcreate_u8(0x000000000000ffff),
+ vcreate_u8(0x0000000000000000));
+
+ // Do the multiplies, rotating with vext to get all combinations
+ uint8x16_t d = vreinterpretq_u8_p16(vmull_p8(a, b)); // D = A0 * B0
+ uint8x16_t e =
+ vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 1))); // E = A0 * B1
+ uint8x16_t f =
+ vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 1), b)); // F = A1 * B0
+ uint8x16_t g =
+ vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 2))); // G = A0 * B2
+ uint8x16_t h =
+ vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 2), b)); // H = A2 * B0
+ uint8x16_t i =
+ vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 3))); // I = A0 * B3
+ uint8x16_t j =
+ vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 3), b)); // J = A3 * B0
+ uint8x16_t k =
+ vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 4))); // L = A0 * B4
+
+ // Add cross products
+ uint8x16_t l = veorq_u8(e, f); // L = E + F
+ uint8x16_t m = veorq_u8(g, h); // M = G + H
+ uint8x16_t n = veorq_u8(i, j); // N = I + J
+
+ // Interleave. Using vzip1 and vzip2 prevents Clang from emitting TBL
+ // instructions.
+#if defined(__aarch64__)
+ uint8x16_t lm_p0 = vreinterpretq_u8_u64(
+ vzip1q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m)));
+ uint8x16_t lm_p1 = vreinterpretq_u8_u64(
+ vzip2q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m)));
+ uint8x16_t nk_p0 = vreinterpretq_u8_u64(
+ vzip1q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k)));
+ uint8x16_t nk_p1 = vreinterpretq_u8_u64(
+ vzip2q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k)));
+#else
+ uint8x16_t lm_p0 = vcombine_u8(vget_low_u8(l), vget_low_u8(m));
+ uint8x16_t lm_p1 = vcombine_u8(vget_high_u8(l), vget_high_u8(m));
+ uint8x16_t nk_p0 = vcombine_u8(vget_low_u8(n), vget_low_u8(k));
+ uint8x16_t nk_p1 = vcombine_u8(vget_high_u8(n), vget_high_u8(k));
+#endif
+ // t0 = (L) (P0 + P1) << 8
+ // t1 = (M) (P2 + P3) << 16
+ uint8x16_t t0t1_tmp = veorq_u8(lm_p0, lm_p1);
+ uint8x16_t t0t1_h = vandq_u8(lm_p1, k48_32);
+ uint8x16_t t0t1_l = veorq_u8(t0t1_tmp, t0t1_h);
+
+ // t2 = (N) (P4 + P5) << 24
+ // t3 = (K) (P6 + P7) << 32
+ uint8x16_t t2t3_tmp = veorq_u8(nk_p0, nk_p1);
+ uint8x16_t t2t3_h = vandq_u8(nk_p1, k16_00);
+ uint8x16_t t2t3_l = veorq_u8(t2t3_tmp, t2t3_h);
+
+ // De-interleave
+#if defined(__aarch64__)
+ uint8x16_t t0 = vreinterpretq_u8_u64(
+ vuzp1q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h)));
+ uint8x16_t t1 = vreinterpretq_u8_u64(
+ vuzp2q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h)));
+ uint8x16_t t2 = vreinterpretq_u8_u64(
+ vuzp1q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h)));
+ uint8x16_t t3 = vreinterpretq_u8_u64(
+ vuzp2q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h)));
+#else
+ uint8x16_t t1 = vcombine_u8(vget_high_u8(t0t1_l), vget_high_u8(t0t1_h));
+ uint8x16_t t0 = vcombine_u8(vget_low_u8(t0t1_l), vget_low_u8(t0t1_h));
+ uint8x16_t t3 = vcombine_u8(vget_high_u8(t2t3_l), vget_high_u8(t2t3_h));
+ uint8x16_t t2 = vcombine_u8(vget_low_u8(t2t3_l), vget_low_u8(t2t3_h));
+#endif
+ // Shift the cross products
+ uint8x16_t t0_shift = vextq_u8(t0, t0, 15); // t0 << 8
+ uint8x16_t t1_shift = vextq_u8(t1, t1, 14); // t1 << 16
+ uint8x16_t t2_shift = vextq_u8(t2, t2, 13); // t2 << 24
+ uint8x16_t t3_shift = vextq_u8(t3, t3, 12); // t3 << 32
+
+ // Accumulate the products
+ uint8x16_t cross1 = veorq_u8(t0_shift, t1_shift);
+ uint8x16_t cross2 = veorq_u8(t2_shift, t3_shift);
+ uint8x16_t mix = veorq_u8(d, cross1);
+ uint8x16_t r = veorq_u8(mix, cross2);
+ return vreinterpretq_u64_u8(r);
+}
+#endif // ARMv7 polyfill
+
+// Perform a carry-less multiplication of two 64-bit integers, selected from a
+// and b according to imm8, and store the results in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_clmulepi64_si128
+FORCE_INLINE __m128i _mm_clmulepi64_si128(__m128i _a, __m128i _b, const int imm)
+{
+ uint64x2_t a = vreinterpretq_u64_m128i(_a);
+ uint64x2_t b = vreinterpretq_u64_m128i(_b);
+ switch (imm & 0x11) {
+ case 0x00:
+ return vreinterpretq_m128i_u64(
+ _sse2neon_vmull_p64(vget_low_u64(a), vget_low_u64(b)));
+ case 0x01:
+ return vreinterpretq_m128i_u64(
+ _sse2neon_vmull_p64(vget_high_u64(a), vget_low_u64(b)));
+ case 0x10:
+ return vreinterpretq_m128i_u64(
+ _sse2neon_vmull_p64(vget_low_u64(a), vget_high_u64(b)));
+ case 0x11:
+ return vreinterpretq_m128i_u64(
+ _sse2neon_vmull_p64(vget_high_u64(a), vget_high_u64(b)));
+ default:
+ abort();
+ }
+}
+
+#if !defined(__ARM_FEATURE_CRYPTO)
+/* clang-format off */
+#define SSE2NEON_AES_DATA(w) \
+ { \
+ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), \
+ w(0xc5), w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), \
+ w(0xab), w(0x76), w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), \
+ w(0x59), w(0x47), w(0xf0), w(0xad), w(0xd4), w(0xa2), w(0xaf), \
+ w(0x9c), w(0xa4), w(0x72), w(0xc0), w(0xb7), w(0xfd), w(0x93), \
+ w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc), w(0x34), w(0xa5), \
+ w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15), w(0x04), \
+ w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a), \
+ w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), \
+ w(0x75), w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), \
+ w(0x5a), w(0xa0), w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), \
+ w(0xe3), w(0x2f), w(0x84), w(0x53), w(0xd1), w(0x00), w(0xed), \
+ w(0x20), w(0xfc), w(0xb1), w(0x5b), w(0x6a), w(0xcb), w(0xbe), \
+ w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf), w(0xd0), w(0xef), \
+ w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85), w(0x45), \
+ w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8), \
+ w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), \
+ w(0xf5), w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), \
+ w(0xf3), w(0xd2), w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), \
+ w(0x97), w(0x44), w(0x17), w(0xc4), w(0xa7), w(0x7e), w(0x3d), \
+ w(0x64), w(0x5d), w(0x19), w(0x73), w(0x60), w(0x81), w(0x4f), \
+ w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88), w(0x46), w(0xee), \
+ w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb), w(0xe0), \
+ w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c), \
+ w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), \
+ w(0x79), w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), \
+ w(0x4e), w(0xa9), w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), \
+ w(0x7a), w(0xae), w(0x08), w(0xba), w(0x78), w(0x25), w(0x2e), \
+ w(0x1c), w(0xa6), w(0xb4), w(0xc6), w(0xe8), w(0xdd), w(0x74), \
+ w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a), w(0x70), w(0x3e), \
+ w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e), w(0x61), \
+ w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e), \
+ w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), \
+ w(0x94), w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), \
+ w(0x28), w(0xdf), w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), \
+ w(0xe6), w(0x42), w(0x68), w(0x41), w(0x99), w(0x2d), w(0x0f), \
+ w(0xb0), w(0x54), w(0xbb), w(0x16) \
+ }
+/* clang-format on */
+
+/* X Macro trick. See https://en.wikipedia.org/wiki/X_Macro */
+#define SSE2NEON_AES_H0(x) (x)
+static const uint8_t SSE2NEON_sbox[256] = SSE2NEON_AES_DATA(SSE2NEON_AES_H0);
+#undef SSE2NEON_AES_H0
+
+// In the absence of crypto extensions, implement aesenc using regular neon
+// intrinsics instead. See:
+// https://www.workofard.com/2017/01/accelerated-aes-for-the-arm64-linux-kernel/
+// https://www.workofard.com/2017/07/ghash-for-low-end-cores/ and
+// https://github.com/ColinIanKing/linux-next-mirror/blob/b5f466091e130caaf0735976648f72bd5e09aa84/crypto/aegis128-neon-inner.c#L52
+// for more information Reproduced with permission of the author.
+FORCE_INLINE __m128i _mm_aesenc_si128(__m128i EncBlock, __m128i RoundKey)
+{
+#if defined(__aarch64__)
+ static const uint8_t shift_rows[] = {0x0, 0x5, 0xa, 0xf, 0x4, 0x9,
+ 0xe, 0x3, 0x8, 0xd, 0x2, 0x7,
+ 0xc, 0x1, 0x6, 0xb};
+ static const uint8_t ror32by8[] = {0x1, 0x2, 0x3, 0x0, 0x5, 0x6, 0x7, 0x4,
+ 0x9, 0xa, 0xb, 0x8, 0xd, 0xe, 0xf, 0xc};
+
+ uint8x16_t v;
+ uint8x16_t w = vreinterpretq_u8_m128i(EncBlock);
+
+ // shift rows
+ w = vqtbl1q_u8(w, vld1q_u8(shift_rows));
+
+ // sub bytes
+ v = vqtbl4q_u8(_sse2neon_vld1q_u8_x4(SSE2NEON_sbox), w);
+ v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(SSE2NEON_sbox + 0x40), w - 0x40);
+ v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(SSE2NEON_sbox + 0x80), w - 0x80);
+ v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(SSE2NEON_sbox + 0xc0), w - 0xc0);
+
+ // mix columns
+ w = (v << 1) ^ (uint8x16_t)(((int8x16_t) v >> 7) & 0x1b);
+ w ^= (uint8x16_t) vrev32q_u16((uint16x8_t) v);
+ w ^= vqtbl1q_u8(v ^ w, vld1q_u8(ror32by8));
+
+ // add round key
+ return vreinterpretq_m128i_u8(w) ^ RoundKey;
+
+#else /* ARMv7-A NEON implementation */
+#define SSE2NEON_AES_B2W(b0, b1, b2, b3) \
+ (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | \
+ (b0))
+#define SSE2NEON_AES_F2(x) ((x << 1) ^ (((x >> 7) & 1) * 0x011b /* WPOLY */))
+#define SSE2NEON_AES_F3(x) (SSE2NEON_AES_F2(x) ^ x)
+#define SSE2NEON_AES_U0(p) \
+ SSE2NEON_AES_B2W(SSE2NEON_AES_F2(p), p, p, SSE2NEON_AES_F3(p))
+#define SSE2NEON_AES_U1(p) \
+ SSE2NEON_AES_B2W(SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p), p, p)
+#define SSE2NEON_AES_U2(p) \
+ SSE2NEON_AES_B2W(p, SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p), p)
+#define SSE2NEON_AES_U3(p) \
+ SSE2NEON_AES_B2W(p, p, SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p))
+ static const uint32_t ALIGN_STRUCT(16) aes_table[4][256] = {
+ SSE2NEON_AES_DATA(SSE2NEON_AES_U0),
+ SSE2NEON_AES_DATA(SSE2NEON_AES_U1),
+ SSE2NEON_AES_DATA(SSE2NEON_AES_U2),
+ SSE2NEON_AES_DATA(SSE2NEON_AES_U3),
+ };
+#undef SSE2NEON_AES_B2W
+#undef SSE2NEON_AES_F2
+#undef SSE2NEON_AES_F3
+#undef SSE2NEON_AES_U0
+#undef SSE2NEON_AES_U1
+#undef SSE2NEON_AES_U2
+#undef SSE2NEON_AES_U3
+
+ uint32_t x0 = _mm_cvtsi128_si32(EncBlock);
+ uint32_t x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0x55));
+ uint32_t x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0xAA));
+ uint32_t x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0xFF));
+
+ __m128i out = _mm_set_epi32(
+ (aes_table[0][x3 & 0xff] ^ aes_table[1][(x0 >> 8) & 0xff] ^
+ aes_table[2][(x1 >> 16) & 0xff] ^ aes_table[3][x2 >> 24]),
+ (aes_table[0][x2 & 0xff] ^ aes_table[1][(x3 >> 8) & 0xff] ^
+ aes_table[2][(x0 >> 16) & 0xff] ^ aes_table[3][x1 >> 24]),
+ (aes_table[0][x1 & 0xff] ^ aes_table[1][(x2 >> 8) & 0xff] ^
+ aes_table[2][(x3 >> 16) & 0xff] ^ aes_table[3][x0 >> 24]),
+ (aes_table[0][x0 & 0xff] ^ aes_table[1][(x1 >> 8) & 0xff] ^
+ aes_table[2][(x2 >> 16) & 0xff] ^ aes_table[3][x3 >> 24]));
+
+ return _mm_xor_si128(out, RoundKey);
+#endif
+}
+
+// Perform the last round of an AES encryption flow on data (state) in a using
+// the round key in RoundKey, and store the result in dst.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenclast_si128
+FORCE_INLINE __m128i _mm_aesenclast_si128(__m128i a, __m128i RoundKey)
+{
+ /* FIXME: optimized for NEON */
+ uint8_t v[4][4] = {
+ [0] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 0)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 5)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 10)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 15)]},
+ [1] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 4)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 9)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 14)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 3)]},
+ [2] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 8)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 13)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 2)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 7)]},
+ [3] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 12)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 1)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 6)],
+ SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 11)]},
+ };
+ for (int i = 0; i < 16; i++)
+ vreinterpretq_nth_u8_m128i(a, i) =
+ v[i / 4][i % 4] ^ vreinterpretq_nth_u8_m128i(RoundKey, i);
+ return a;
+}
+
+// Emits the Advanced Encryption Standard (AES) instruction aeskeygenassist.
+// This instruction generates a round key for AES encryption. See
+// https://kazakov.life/2017/11/01/cryptocurrency-mining-on-ios-devices/
+// for details.
+//
+// https://msdn.microsoft.com/en-us/library/cc714138(v=vs.120).aspx
+FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i key, const int rcon)
+{
+ uint32_t X1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0x55));
+ uint32_t X3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0xFF));
+ for (int i = 0; i < 4; ++i) {
+ ((uint8_t *) &X1)[i] = SSE2NEON_sbox[((uint8_t *) &X1)[i]];
+ ((uint8_t *) &X3)[i] = SSE2NEON_sbox[((uint8_t *) &X3)[i]];
+ }
+ return _mm_set_epi32(((X3 >> 8) | (X3 << 24)) ^ rcon, X3,
+ ((X1 >> 8) | (X1 << 24)) ^ rcon, X1);
+}
+#undef SSE2NEON_AES_DATA
+
+#else /* __ARM_FEATURE_CRYPTO */
+// Implements equivalent of 'aesenc' by combining AESE (with an empty key) and
+// AESMC and then manually applying the real key as an xor operation. This
+// unfortunately means an additional xor op; the compiler should be able to
+// optimize this away for repeated calls however. See
+// https://blog.michaelbrase.com/2018/05/08/emulating-x86-aes-intrinsics-on-armv8-a
+// for more details.
+FORCE_INLINE __m128i _mm_aesenc_si128(__m128i a, __m128i b)
+{
+ return vreinterpretq_m128i_u8(
+ vaesmcq_u8(vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0))) ^
+ vreinterpretq_u8_m128i(b));
+}
+
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenclast_si128
+FORCE_INLINE __m128i _mm_aesenclast_si128(__m128i a, __m128i RoundKey)
+{
+ return _mm_xor_si128(vreinterpretq_m128i_u8(vaeseq_u8(
+ vreinterpretq_u8_m128i(a), vdupq_n_u8(0))),
+ RoundKey);
+}
+
+FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i a, const int rcon)
+{
+ // AESE does ShiftRows and SubBytes on A
+ uint8x16_t u8 = vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0));
+
+ uint8x16_t dest = {
+ // Undo ShiftRows step from AESE and extract X1 and X3
+ u8[0x4], u8[0x1], u8[0xE], u8[0xB], // SubBytes(X1)
+ u8[0x1], u8[0xE], u8[0xB], u8[0x4], // ROT(SubBytes(X1))
+ u8[0xC], u8[0x9], u8[0x6], u8[0x3], // SubBytes(X3)
+ u8[0x9], u8[0x6], u8[0x3], u8[0xC], // ROT(SubBytes(X3))
+ };
+ uint32x4_t r = {0, (unsigned) rcon, 0, (unsigned) rcon};
+ return vreinterpretq_m128i_u8(dest) ^ vreinterpretq_m128i_u32(r);
+}
+#endif
+
+/* Streaming Extensions */
+
+// Guarantees that every preceding store is globally visible before any
+// subsequent store.
+// https://msdn.microsoft.com/en-us/library/5h2w73d1%28v=vs.90%29.aspx
+FORCE_INLINE void _mm_sfence(void)
+{
+ __sync_synchronize();
+}
+
+// Store 128-bits (composed of 4 packed single-precision (32-bit) floating-
+// point elements) from a into memory using a non-temporal memory hint.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_ps
+FORCE_INLINE void _mm_stream_ps(float *p, __m128 a)
+{
+#if __has_builtin(__builtin_nontemporal_store)
+ __builtin_nontemporal_store(a, (float32x4_t *) p);
+#else
+ vst1q_f32(p, vreinterpretq_f32_m128(a));
+#endif
+}
+
+// Stores the data in a to the address p without polluting the caches. If the
+// cache line containing address p is already in the cache, the cache will be
+// updated.
+// https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx
+FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a)
+{
+#if __has_builtin(__builtin_nontemporal_store)
+ __builtin_nontemporal_store(a, p);
+#else
+ vst1q_s64((int64_t *) p, vreinterpretq_s64_m128i(a));
+#endif
+}
+
+// Load 128-bits of integer data from memory into dst using a non-temporal
+// memory hint. mem_addr must be aligned on a 16-byte boundary or a
+// general-protection exception may be generated.
+//
+// dst[127:0] := MEM[mem_addr+127:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_load_si128
+FORCE_INLINE __m128i _mm_stream_load_si128(__m128i *p)
+{
+#if __has_builtin(__builtin_nontemporal_store)
+ return __builtin_nontemporal_load(p);
+#else
+ return vreinterpretq_m128i_s64(vld1q_s64((int64_t *) p));
+#endif
+}
+
+// Cache line containing p is flushed and invalidated from all caches in the
+// coherency domain. :
+// https://msdn.microsoft.com/en-us/library/ba08y07y(v=vs.100).aspx
+FORCE_INLINE void _mm_clflush(void const *p)
+{
+ (void) p;
+ // no corollary for Neon?
+}
+
+// Allocate aligned blocks of memory.
+// https://software.intel.com/en-us/
+// cpp-compiler-developer-guide-and-reference-allocating-and-freeing-aligned-memory-blocks
+FORCE_INLINE void *_mm_malloc(size_t size, size_t align)
+{
+ void *ptr;
+ if (align == 1)
+ return malloc(size);
+ if (align == 2 || (sizeof(void *) == 8 && align == 4))
+ align = sizeof(void *);
+ if (!posix_memalign(&ptr, align, size))
+ return ptr;
+ return NULL;
+}
+
+// Free aligned memory that was allocated with _mm_malloc.
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_free
+FORCE_INLINE void _mm_free(void *addr)
+{
+ free(addr);
+}
+
+// Starting with the initial value in crc, accumulates a CRC32 value for
+// unsigned 8-bit integer v.
+// https://msdn.microsoft.com/en-us/library/bb514036(v=vs.100)
+FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t crc, uint8_t v)
+{
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
+ __asm__ __volatile__("crc32cb %w[c], %w[c], %w[v]\n\t"
+ : [c] "+r"(crc)
+ : [v] "r"(v));
+#else
+ crc ^= v;
+ for (int bit = 0; bit < 8; bit++) {
+ if (crc & 1)
+ crc = (crc >> 1) ^ UINT32_C(0x82f63b78);
+ else
+ crc = (crc >> 1);
+ }
+#endif
+ return crc;
+}
+
+// Starting with the initial value in crc, accumulates a CRC32 value for
+// unsigned 16-bit integer v.
+// https://msdn.microsoft.com/en-us/library/bb531411(v=vs.100)
+FORCE_INLINE uint32_t _mm_crc32_u16(uint32_t crc, uint16_t v)
+{
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
+ __asm__ __volatile__("crc32ch %w[c], %w[c], %w[v]\n\t"
+ : [c] "+r"(crc)
+ : [v] "r"(v));
+#else
+ crc = _mm_crc32_u8(crc, v & 0xff);
+ crc = _mm_crc32_u8(crc, (v >> 8) & 0xff);
+#endif
+ return crc;
+}
+
+// Starting with the initial value in crc, accumulates a CRC32 value for
+// unsigned 32-bit integer v.
+// https://msdn.microsoft.com/en-us/library/bb531394(v=vs.100)
+FORCE_INLINE uint32_t _mm_crc32_u32(uint32_t crc, uint32_t v)
+{
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
+ __asm__ __volatile__("crc32cw %w[c], %w[c], %w[v]\n\t"
+ : [c] "+r"(crc)
+ : [v] "r"(v));
+#else
+ crc = _mm_crc32_u16(crc, v & 0xffff);
+ crc = _mm_crc32_u16(crc, (v >> 16) & 0xffff);
+#endif
+ return crc;
+}
+
+// Starting with the initial value in crc, accumulates a CRC32 value for
+// unsigned 64-bit integer v.
+// https://msdn.microsoft.com/en-us/library/bb514033(v=vs.100)
+FORCE_INLINE uint64_t _mm_crc32_u64(uint64_t crc, uint64_t v)
+{
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
+ __asm__ __volatile__("crc32cx %w[c], %w[c], %x[v]\n\t"
+ : [c] "+r"(crc)
+ : [v] "r"(v));
+#else
+ crc = _mm_crc32_u32((uint32_t)(crc), v & 0xffffffff);
+ crc = _mm_crc32_u32((uint32_t)(crc), (v >> 32) & 0xffffffff);
+#endif
+ return crc;
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma pop_macro("ALIGN_STRUCT")
+#pragma pop_macro("FORCE_INLINE")
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC pop_options
+#endif
+
+#endif
diff --git a/thirdparty/embree/common/simd/avx.h b/thirdparty/embree/common/simd/avx.h
new file mode 100644
index 0000000000..d3100306ee
--- /dev/null
+++ b/thirdparty/embree/common/simd/avx.h
@@ -0,0 +1,34 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "sse.h"
+
+#if defined(__AVX512VL__)
+#include "vboolf8_avx512.h"
+#include "vboold4_avx512.h"
+#else
+#include "vboolf8_avx.h"
+#include "vboold4_avx.h"
+#endif
+
+#if defined(__AVX2__)
+#include "vint8_avx2.h"
+#include "vuint8_avx2.h"
+#if defined(__X86_64__)
+#include "vllong4_avx2.h"
+#endif
+#else
+#include "vint8_avx.h"
+#include "vuint8_avx.h"
+#endif
+#include "vfloat8_avx.h"
+#if defined(__X86_64__)
+#include "vdouble4_avx.h"
+#endif
+
+#if defined(__AVX512F__)
+#include "avx512.h"
+#endif
+
diff --git a/thirdparty/embree/common/simd/avx512.h b/thirdparty/embree/common/simd/avx512.h
new file mode 100644
index 0000000000..d43bbacea1
--- /dev/null
+++ b/thirdparty/embree/common/simd/avx512.h
@@ -0,0 +1,41 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+#include "../sys/intrinsics.h"
+#include "../math/constants.h"
+#include "../sys/alloc.h"
+#include "varying.h"
+
+#include "vboolf16_avx512.h"
+#include "vint16_avx512.h"
+#include "vuint16_avx512.h"
+#include "vfloat16_avx512.h"
+
+#include "vboold8_avx512.h"
+#include "vllong8_avx512.h"
+#include "vdouble8_avx512.h"
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Prefetching
+ ////////////////////////////////////////////////////////////////////////////////
+
+#define PFHINT_L1 0
+#define PFHINT_L2 1
+#define PFHINT_NT 2
+
+ template<const unsigned int mode>
+ __forceinline void prefetch(const void * __restrict__ const m)
+ {
+ if (mode == PFHINT_L1)
+ _mm_prefetch((const char*)m,_MM_HINT_T0);
+ else if (mode == PFHINT_L2)
+ _mm_prefetch((const char*)m,_MM_HINT_T1);
+ else if (mode == PFHINT_NT)
+ _mm_prefetch((const char*)m,_MM_HINT_NTA);
+ }
+}
diff --git a/thirdparty/embree/common/simd/simd.h b/thirdparty/embree/common/simd/simd.h
new file mode 100644
index 0000000000..195506b530
--- /dev/null
+++ b/thirdparty/embree/common/simd/simd.h
@@ -0,0 +1,110 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../math/math.h"
+
+/* include SSE wrapper classes */
+#if defined(__SSE__)
+# include "sse.h"
+#endif
+
+/* include AVX wrapper classes */
+#if defined(__AVX__)
+# include "avx.h"
+#endif
+
+/* include AVX512 wrapper classes */
+#if defined (__AVX512F__)
+# include "avx512.h"
+#endif
+
+namespace embree
+{
+ template <int N>
+ __forceinline vbool<N> isfinite(const vfloat<N>& v)
+ {
+ return (v >= vfloat<N>(-std::numeric_limits<float>::max()))
+ & (v <= vfloat<N>( std::numeric_limits<float>::max()));
+ }
+
+ /* foreach unique */
+ template<typename vbool, typename vint, typename Closure>
+ __forceinline void foreach_unique(const vbool& valid0, const vint& vi, const Closure& closure)
+ {
+ vbool valid1 = valid0;
+ while (any(valid1)) {
+ const int j = int(bsf(movemask(valid1)));
+ const int i = vi[j];
+ const vbool valid2 = valid1 & (i == vi);
+ valid1 = andn(valid1, valid2);
+ closure(valid2, i);
+ }
+ }
+
+ /* returns the next unique value i in vi and the corresponding valid_i mask */
+ template<typename vbool, typename vint>
+ __forceinline int next_unique(vbool& valid, const vint& vi, /*out*/ vbool& valid_i)
+ {
+ assert(any(valid));
+ const int j = int(bsf(movemask(valid)));
+ const int i = vi[j];
+ valid_i = valid & (i == vi);
+ valid = andn(valid, valid_i);
+ return i;
+ }
+
+ /* foreach unique index */
+ template<typename vbool, typename vint, typename Closure>
+ __forceinline void foreach_unique_index(const vbool& valid0, const vint& vi, const Closure& closure)
+ {
+ vbool valid1 = valid0;
+ while (any(valid1)) {
+ const int j = int(bsf(movemask(valid1)));
+ const int i = vi[j];
+ const vbool valid2 = valid1 & (i == vi);
+ valid1 = andn(valid1, valid2);
+ closure(valid2, i, j);
+ }
+ }
+
+ /* returns the index of the next unique value i in vi and the corresponding valid_i mask */
+ template<typename vbool, typename vint>
+ __forceinline int next_unique_index(vbool& valid, const vint& vi, /*out*/ vbool& valid_i)
+ {
+ assert(any(valid));
+ const int j = int(bsf(movemask(valid)));
+ const int i = vi[j];
+ valid_i = valid & (i == vi);
+ valid = andn(valid, valid_i);
+ return j;
+ }
+
+ template<typename Closure>
+ __forceinline void foreach2(int x0, int x1, int y0, int y1, const Closure& closure)
+ {
+ __aligned(64) int U[2*VSIZEX];
+ __aligned(64) int V[2*VSIZEX];
+ int index = 0;
+ for (int y=y0; y<y1; y++) {
+ const bool lasty = y+1>=y1;
+ const vintx vy = y;
+ for (int x=x0; x<x1; ) { //x+=VSIZEX) {
+ const bool lastx = x+VSIZEX >= x1;
+ vintx vx = x+vintx(step);
+ vintx::storeu(&U[index], vx);
+ vintx::storeu(&V[index], vy);
+ const int dx = min(x1-x,VSIZEX);
+ index += dx;
+ x += dx;
+ if (index >= VSIZEX || (lastx && lasty)) {
+ const vboolx valid = vintx(step) < vintx(index);
+ closure(valid, vintx::load(U), vintx::load(V));
+ x-= max(0, index-VSIZEX);
+ index = 0;
+ }
+ }
+ }
+ }
+}
diff --git a/thirdparty/embree/common/simd/sse.cpp b/thirdparty/embree/common/simd/sse.cpp
new file mode 100644
index 0000000000..535d6943d8
--- /dev/null
+++ b/thirdparty/embree/common/simd/sse.cpp
@@ -0,0 +1,34 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sse.h"
+
+namespace embree
+{
+ const __m128 mm_lookupmask_ps[16] = {
+ _mm_castsi128_ps(_mm_set_epi32( 0, 0, 0, 0)),
+ _mm_castsi128_ps(_mm_set_epi32( 0, 0, 0,-1)),
+ _mm_castsi128_ps(_mm_set_epi32( 0, 0,-1, 0)),
+ _mm_castsi128_ps(_mm_set_epi32( 0, 0,-1,-1)),
+ _mm_castsi128_ps(_mm_set_epi32( 0,-1, 0, 0)),
+ _mm_castsi128_ps(_mm_set_epi32( 0,-1, 0,-1)),
+ _mm_castsi128_ps(_mm_set_epi32( 0,-1,-1, 0)),
+ _mm_castsi128_ps(_mm_set_epi32( 0,-1,-1,-1)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, 0, 0, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, 0, 0,-1)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, 0,-1, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, 0,-1,-1)),
+ _mm_castsi128_ps(_mm_set_epi32(-1,-1, 0, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(-1,-1, 0,-1)),
+ _mm_castsi128_ps(_mm_set_epi32(-1,-1,-1, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(-1,-1,-1,-1))
+ };
+
+ const __m128d mm_lookupmask_pd[4] = {
+ _mm_castsi128_pd(_mm_set_epi32( 0, 0, 0, 0)),
+ _mm_castsi128_pd(_mm_set_epi32( 0, 0,-1,-1)),
+ _mm_castsi128_pd(_mm_set_epi32(-1,-1, 0, 0)),
+ _mm_castsi128_pd(_mm_set_epi32(-1,-1,-1,-1))
+ };
+
+}
diff --git a/thirdparty/embree/common/simd/sse.h b/thirdparty/embree/common/simd/sse.h
new file mode 100644
index 0000000000..1465fb4fb0
--- /dev/null
+++ b/thirdparty/embree/common/simd/sse.h
@@ -0,0 +1,35 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+#include "../sys/intrinsics.h"
+#include "../sys/alloc.h"
+#include "../math/constants.h"
+#include "varying.h"
+
+namespace embree
+{
+#if defined(__SSE4_1__)
+ __forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
+ return _mm_blendv_ps(f,t,mask);
+ }
+#else
+ __forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
+ return _mm_or_ps(_mm_and_ps(mask, t), _mm_andnot_ps(mask, f));
+ }
+#endif
+
+ extern const __m128 mm_lookupmask_ps[16];
+ extern const __m128d mm_lookupmask_pd[4];
+}
+
+#if defined(__AVX512VL__)
+#include "vboolf4_avx512.h"
+#else
+#include "vboolf4_sse2.h"
+#endif
+#include "vint4_sse2.h"
+#include "vuint4_sse2.h"
+#include "vfloat4_sse2.h"
diff --git a/thirdparty/embree/common/simd/varying.h b/thirdparty/embree/common/simd/varying.h
new file mode 100644
index 0000000000..9b98d326be
--- /dev/null
+++ b/thirdparty/embree/common/simd/varying.h
@@ -0,0 +1,145 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+
+namespace embree
+{
+ /* Varying numeric types */
+ template<int N>
+ struct vfloat_impl
+ {
+ union { float f[N]; int i[N]; };
+ __forceinline const float& operator [](size_t index) const { assert(index < N); return f[index]; }
+ __forceinline float& operator [](size_t index) { assert(index < N); return f[index]; }
+ };
+
+ template<int N>
+ struct vdouble_impl
+ {
+ union { double f[N]; long long i[N]; };
+ __forceinline const double& operator [](size_t index) const { assert(index < N); return f[index]; }
+ __forceinline double& operator [](size_t index) { assert(index < N); return f[index]; }
+ };
+
+ template<int N>
+ struct vint_impl
+ {
+ int i[N];
+ __forceinline const int& operator [](size_t index) const { assert(index < N); return i[index]; }
+ __forceinline int& operator [](size_t index) { assert(index < N); return i[index]; }
+ };
+
+ template<int N>
+ struct vuint_impl
+ {
+ unsigned int i[N];
+ __forceinline const unsigned int& operator [](size_t index) const { assert(index < N); return i[index]; }
+ __forceinline unsigned int& operator [](size_t index) { assert(index < N); return i[index]; }
+ };
+
+ template<int N>
+ struct vllong_impl
+ {
+ long long i[N];
+ __forceinline const long long& operator [](size_t index) const { assert(index < N); return i[index]; }
+ __forceinline long long& operator [](size_t index) { assert(index < N); return i[index]; }
+ };
+
+ /* Varying bool types */
+ template<int N> struct vboolf_impl { int i[N]; }; // for float/int
+ template<int N> struct vboold_impl { long long i[N]; }; // for double/long long
+
+ /* Varying size constants */
+#if defined(__AVX512VL__) // SKX
+ const int VSIZEX = 8; // default size
+ const int VSIZEL = 16; // large size
+#elif defined(__AVX__)
+ const int VSIZEX = 8;
+ const int VSIZEL = 8;
+#else
+ const int VSIZEX = 4;
+ const int VSIZEL = 4;
+#endif
+
+ template<int N>
+ struct vtypes {
+ using vbool = vboolf_impl<N>;
+ using vboolf = vboolf_impl<N>;
+ using vboold = vboold_impl<N>;
+ using vint = vint_impl<N>;
+ using vuint = vuint_impl<N>;
+ using vllong = vllong_impl<N>;
+ using vfloat = vfloat_impl<N>;
+ using vdouble = vdouble_impl<N>;
+ };
+
+ template<>
+ struct vtypes<1> {
+ using vbool = bool;
+ using vboolf = bool;
+ using vboold = bool;
+ using vint = int;
+ using vuint = unsigned int;
+ using vllong = long long;
+ using vfloat = float;
+ using vdouble = double;
+ };
+
+ /* Aliases to default types */
+ template<int N> using vbool = typename vtypes<N>::vbool;
+ template<int N> using vboolf = typename vtypes<N>::vboolf;
+ template<int N> using vboold = typename vtypes<N>::vboold;
+ template<int N> using vint = typename vtypes<N>::vint;
+ template<int N> using vuint = typename vtypes<N>::vuint;
+ template<int N> using vllong = typename vtypes<N>::vllong;
+ template<int N> using vreal = typename vtypes<N>::vfloat;
+ template<int N> using vfloat = typename vtypes<N>::vfloat;
+ template<int N> using vdouble = typename vtypes<N>::vdouble;
+
+ /* 4-wide shortcuts */
+ typedef vfloat<4> vfloat4;
+ typedef vdouble<4> vdouble4;
+ typedef vreal<4> vreal4;
+ typedef vint<4> vint4;
+ typedef vuint<4> vuint4;
+ typedef vllong<4> vllong4;
+ typedef vbool<4> vbool4;
+ typedef vboolf<4> vboolf4;
+ typedef vboold<4> vboold4;
+
+ /* 8-wide shortcuts */
+ typedef vfloat<8> vfloat8;
+ typedef vdouble<8> vdouble8;
+ typedef vreal<8> vreal8;
+ typedef vint<8> vint8;
+ typedef vuint<8> vuint8;
+ typedef vllong<8> vllong8;
+ typedef vbool<8> vbool8;
+ typedef vboolf<8> vboolf8;
+ typedef vboold<8> vboold8;
+
+ /* 16-wide shortcuts */
+ typedef vfloat<16> vfloat16;
+ typedef vdouble<16> vdouble16;
+ typedef vreal<16> vreal16;
+ typedef vint<16> vint16;
+ typedef vuint<16> vuint16;
+ typedef vllong<16> vllong16;
+ typedef vbool<16> vbool16;
+ typedef vboolf<16> vboolf16;
+ typedef vboold<16> vboold16;
+
+ /* Default shortcuts */
+ typedef vfloat<VSIZEX> vfloatx;
+ typedef vdouble<VSIZEX> vdoublex;
+ typedef vreal<VSIZEX> vrealx;
+ typedef vint<VSIZEX> vintx;
+ typedef vuint<VSIZEX> vuintx;
+ typedef vllong<VSIZEX> vllongx;
+ typedef vbool<VSIZEX> vboolx;
+ typedef vboolf<VSIZEX> vboolfx;
+ typedef vboold<VSIZEX> vbooldx;
+}
diff --git a/thirdparty/embree/common/simd/vboold4_avx.h b/thirdparty/embree/common/simd/vboold4_avx.h
new file mode 100644
index 0000000000..7db0d1c5c1
--- /dev/null
+++ b/thirdparty/embree/common/simd/vboold4_avx.h
@@ -0,0 +1,169 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide AVX bool type for 64bit data types*/
+ template<>
+ struct vboold<4>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboold4 Bool;
+
+ enum { size = 4 }; // number of SIMD elements
+ union { // data
+ __m256d v;
+ struct { __m128d vl,vh; };
+ long long i[4];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold() {}
+ __forceinline vboold(const vboold4& a) { v = a.v; }
+ __forceinline vboold4& operator =(const vboold4& a) { v = a.v; return *this; }
+
+ __forceinline vboold(__m256d a) : v(a) {}
+ __forceinline vboold(__m256i a) : v(_mm256_castsi256_pd(a)) {}
+
+ __forceinline operator const __m256() const { return _mm256_castpd_ps(v); }
+ __forceinline operator const __m256i() const { return _mm256_castpd_si256(v); }
+ __forceinline operator const __m256d() const { return v; }
+
+ __forceinline vboold(int a)
+ {
+ assert(a >= 0 && a <= 255);
+#if defined (__AVX2__)
+ const __m256i mask = _mm256_set_epi64x(0x8, 0x4, 0x2, 0x1);
+ const __m256i b = _mm256_set1_epi64x(a);
+ const __m256i c = _mm256_and_si256(b,mask);
+ v = _mm256_castsi256_pd(_mm256_cmpeq_epi64(c,mask));
+#else
+ vl = mm_lookupmask_pd[a & 0x3];
+ vh = mm_lookupmask_pd[a >> 2];
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold(FalseTy) : v(_mm256_setzero_pd()) {}
+ __forceinline vboold(TrueTy) : v(_mm256_cmp_pd(_mm256_setzero_pd(), _mm256_setzero_pd(), _CMP_EQ_OQ)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator [](size_t index) const { assert(index < 4); return (_mm256_movemask_pd(v) >> index) & 1; }
+ __forceinline long long& operator [](size_t index) { assert(index < 4); return i[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold4 operator !(const vboold4& a) { return _mm256_xor_pd(a, vboold4(embree::True)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold4 operator &(const vboold4& a, const vboold4& b) { return _mm256_and_pd(a, b); }
+ __forceinline vboold4 operator |(const vboold4& a, const vboold4& b) { return _mm256_or_pd (a, b); }
+ __forceinline vboold4 operator ^(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(a, b); }
+
+ __forceinline vboold4 andn(const vboold4& a, const vboold4& b) { return _mm256_andnot_pd(b, a); }
+
+ __forceinline vboold4& operator &=(vboold4& a, const vboold4& b) { return a = a & b; }
+ __forceinline vboold4& operator |=(vboold4& a, const vboold4& b) { return a = a | b; }
+ __forceinline vboold4& operator ^=(vboold4& a, const vboold4& b) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold4 operator !=(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(a, b); }
+ __forceinline vboold4 operator ==(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(_mm256_xor_pd(a,b),vboold4(embree::True)); }
+
+ __forceinline vboold4 select(const vboold4& mask, const vboold4& t, const vboold4& f) {
+ return _mm256_blendv_pd(f, t, mask);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold4 unpacklo(const vboold4& a, const vboold4& b) { return _mm256_unpacklo_pd(a, b); }
+ __forceinline vboold4 unpackhi(const vboold4& a, const vboold4& b) { return _mm256_unpackhi_pd(a, b); }
+
+
+#if defined(__AVX2__)
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vboold4 shuffle(const vboold4& v) {
+ return _mm256_permute4x64_pd(v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i>
+ __forceinline vboold4 shuffle(const vboold4& v) {
+ return _mm256_permute4x64_pd(v, _MM_SHUFFLE(i, i, i, i));
+ }
+#endif
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool reduce_and(const vboold4& a) { return _mm256_movemask_pd(a) == (unsigned int)0xf; }
+ __forceinline bool reduce_or (const vboold4& a) { return !_mm256_testz_pd(a,a); }
+
+ __forceinline bool all (const vboold4& a) { return _mm256_movemask_pd(a) == (unsigned int)0xf; }
+ __forceinline bool any (const vboold4& a) { return !_mm256_testz_pd(a,a); }
+ __forceinline bool none(const vboold4& a) { return _mm256_testz_pd(a,a) != 0; }
+
+ __forceinline bool all (const vboold4& valid, const vboold4& b) { return all((!valid) | b); }
+ __forceinline bool any (const vboold4& valid, const vboold4& b) { return any(valid & b); }
+ __forceinline bool none(const vboold4& valid, const vboold4& b) { return none(valid & b); }
+
+ __forceinline unsigned int movemask(const vboold4& a) { return _mm256_movemask_pd(a); }
+ __forceinline size_t popcnt (const vboold4& a) { return popcnt((size_t)_mm256_movemask_pd(a)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Get/Set Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool get(const vboold4& a, size_t index) { return a[index]; }
+ __forceinline void set (vboold4& a, size_t index) { a[index] = -1; }
+ __forceinline void clear(vboold4& a, size_t index) { a[index] = 0; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vboold4& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
+ << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vboold4_avx512.h b/thirdparty/embree/common/simd/vboold4_avx512.h
new file mode 100644
index 0000000000..ceaad7bba5
--- /dev/null
+++ b/thirdparty/embree/common/simd/vboold4_avx512.h
@@ -0,0 +1,156 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide AVX-512 bool type */
+ template<>
+ struct vboold<4>
+ {
+ typedef vboold4 Bool;
+ typedef vint4 Int;
+
+ enum { size = 4 }; // number of SIMD elements
+ __mmask8 v; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold() {}
+ __forceinline vboold(const vboold4& t) { v = t.v; }
+ __forceinline vboold4& operator =(const vboold4& f) { v = f.v; return *this; }
+
+ __forceinline vboold(const __mmask8 &t) { v = t; }
+ __forceinline operator __mmask8() const { return v; }
+
+ __forceinline vboold(bool b) { v = b ? 0xf : 0x0; }
+ __forceinline vboold(int t) { v = (__mmask8)t; }
+ __forceinline vboold(unsigned int t) { v = (__mmask8)t; }
+
+ /* return int8 mask */
+ __forceinline __m128i mask8() const {
+ return _mm_movm_epi8(v);
+ }
+
+ /* return int32 mask */
+ __forceinline __m128i mask32() const {
+ return _mm_movm_epi32(v);
+ }
+
+ /* return int64 mask */
+ __forceinline __m256i mask64() const {
+ return _mm256_movm_epi64(v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold(FalseTy) : v(0x0) {}
+ __forceinline vboold(TrueTy) : v(0xf) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator [](size_t index) const {
+ assert(index < 4); return (mm512_mask2int(v) >> index) & 1;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold4 operator !(const vboold4& a) { return _mm512_kandn(a, 0xf); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold4 operator &(const vboold4& a, const vboold4& b) { return _mm512_kand(a, b); }
+ __forceinline vboold4 operator |(const vboold4& a, const vboold4& b) { return _mm512_kor(a, b); }
+ __forceinline vboold4 operator ^(const vboold4& a, const vboold4& b) { return _mm512_kxor(a, b); }
+
+ __forceinline vboold4 andn(const vboold4& a, const vboold4& b) { return _mm512_kandn(b, a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold4& operator &=(vboold4& a, const vboold4& b) { return a = a & b; }
+ __forceinline vboold4& operator |=(vboold4& a, const vboold4& b) { return a = a | b; }
+ __forceinline vboold4& operator ^=(vboold4& a, const vboold4& b) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold4 operator !=(const vboold4& a, const vboold4& b) { return _mm512_kxor(a, b); }
+ __forceinline vboold4 operator ==(const vboold4& a, const vboold4& b) { return _mm512_kand(_mm512_kxnor(a, b), 0xf); }
+
+ __forceinline vboold4 select(const vboold4& s, const vboold4& a, const vboold4& b) {
+ return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline int all (const vboold4& a) { return a.v == 0xf; }
+ __forceinline int any (const vboold4& a) { return _mm512_kortestz(a, a) == 0; }
+ __forceinline int none(const vboold4& a) { return _mm512_kortestz(a, a) != 0; }
+
+ __forceinline int all (const vboold4& valid, const vboold4& b) { return all((!valid) | b); }
+ __forceinline int any (const vboold4& valid, const vboold4& b) { return any(valid & b); }
+ __forceinline int none(const vboold4& valid, const vboold4& b) { return none(valid & b); }
+
+ __forceinline size_t movemask(const vboold4& a) { return _mm512_kmov(a); }
+ __forceinline size_t popcnt (const vboold4& a) { return popcnt(a.v); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Conversion Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline unsigned int toInt(const vboold4& a) { return mm512_mask2int(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Get/Set Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool get(const vboold4& a, size_t index) { assert(index < 4); return (toInt(a) >> index) & 1; }
+ __forceinline void set(vboold4& a, size_t index) { assert(index < 4); a |= 1 << index; }
+ __forceinline void clear(vboold4& a, size_t index) { assert(index < 4); a = andn(a, 1 << index); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vboold4& a)
+ {
+ cout << "<";
+ for (size_t i=0; i<4; i++) {
+ if ((a.v >> i) & 1) cout << "1"; else cout << "0";
+ }
+ return cout << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vboold8_avx512.h b/thirdparty/embree/common/simd/vboold8_avx512.h
new file mode 100644
index 0000000000..66d2054872
--- /dev/null
+++ b/thirdparty/embree/common/simd/vboold8_avx512.h
@@ -0,0 +1,151 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX-512 bool type */
+ template<>
+ struct vboold<8>
+ {
+ typedef vboold8 Bool;
+ typedef vint8 Int;
+
+ enum { size = 8 }; // number of SIMD elements
+ __mmask8 v; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold() {}
+ __forceinline vboold(const vboold8& t) { v = t.v; }
+ __forceinline vboold8& operator =(const vboold8& f) { v = f.v; return *this; }
+
+ __forceinline vboold(const __mmask8& t) { v = t; }
+ __forceinline operator __mmask8() const { return v; }
+
+ __forceinline vboold(bool b) { v = b ? 0xff : 0x00; }
+ __forceinline vboold(int t) { v = (__mmask8)t; }
+ __forceinline vboold(unsigned int t) { v = (__mmask8)t; }
+
+ /* return int8 mask */
+ __forceinline __m128i mask8() const {
+ return _mm_movm_epi8(v);
+ }
+
+ /* return int64 mask */
+ __forceinline __m512i mask64() const {
+ return _mm512_movm_epi64(v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold(FalseTy) : v(0x00) {}
+ __forceinline vboold(TrueTy) : v(0xff) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator [](size_t index) const {
+ assert(index < 8); return (mm512_mask2int(v) >> index) & 1;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold8 operator !(const vboold8& a) { return _mm512_knot(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold8 operator &(const vboold8& a, const vboold8& b) { return _mm512_kand(a, b); }
+ __forceinline vboold8 operator |(const vboold8& a, const vboold8& b) { return _mm512_kor(a, b); }
+ __forceinline vboold8 operator ^(const vboold8& a, const vboold8& b) { return _mm512_kxor(a, b); }
+
+ __forceinline vboold8 andn(const vboold8& a, const vboold8& b) { return _mm512_kandn(b, a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold8& operator &=(vboold8& a, const vboold8& b) { return a = a & b; }
+ __forceinline vboold8& operator |=(vboold8& a, const vboold8& b) { return a = a | b; }
+ __forceinline vboold8& operator ^=(vboold8& a, const vboold8& b) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold8 operator !=(const vboold8& a, const vboold8& b) { return _mm512_kxor(a, b); }
+ __forceinline vboold8 operator ==(const vboold8& a, const vboold8& b) { return _mm512_kxnor(a, b); }
+
+ __forceinline vboold8 select(const vboold8& s, const vboold8& a, const vboold8& b) {
+ return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline int all (const vboold8& a) { return a.v == 0xff; }
+ __forceinline int any (const vboold8& a) { return _mm512_kortestz(a, a) == 0; }
+ __forceinline int none(const vboold8& a) { return _mm512_kortestz(a, a) != 0; }
+
+ __forceinline int all (const vboold8& valid, const vboold8& b) { return all((!valid) | b); }
+ __forceinline int any (const vboold8& valid, const vboold8& b) { return any(valid & b); }
+ __forceinline int none(const vboold8& valid, const vboold8& b) { return none(valid & b); }
+
+ __forceinline size_t movemask(const vboold8& a) { return _mm512_kmov(a); }
+ __forceinline size_t popcnt (const vboold8& a) { return popcnt(a.v); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Conversion Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline unsigned int toInt(const vboold8& a) { return mm512_mask2int(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Get/Set Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool get(const vboold8& a, size_t index) { assert(index < 8); return (toInt(a) >> index) & 1; }
+ __forceinline void set(vboold8& a, size_t index) { assert(index < 8); a |= 1 << index; }
+ __forceinline void clear(vboold8& a, size_t index) { assert(index < 8); a = andn(a, 1 << index); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vboold8& a)
+ {
+ cout << "<";
+ for (size_t i=0; i<8; i++) {
+ if ((a.v >> i) & 1) cout << "1"; else cout << "0";
+ }
+ return cout << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vboolf16_avx512.h b/thirdparty/embree/common/simd/vboolf16_avx512.h
new file mode 100644
index 0000000000..19841dcea8
--- /dev/null
+++ b/thirdparty/embree/common/simd/vboolf16_avx512.h
@@ -0,0 +1,153 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 16-wide AVX-512 bool type */
+ template<>
+ struct vboolf<16>
+ {
+ typedef vboolf16 Bool;
+ typedef vint16 Int;
+ typedef vfloat16 Float;
+
+ enum { size = 16 }; // number of SIMD elements
+ __mmask16 v; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf() {}
+ __forceinline vboolf(const vboolf16& t) { v = t.v; }
+ __forceinline vboolf16& operator =(const vboolf16& f) { v = f.v; return *this; }
+
+ __forceinline vboolf(const __mmask16& t) { v = t; }
+ __forceinline operator __mmask16() const { return v; }
+
+ __forceinline vboolf(bool b) { v = b ? 0xFFFF : 0x0000; }
+ __forceinline vboolf(int t) { v = (__mmask16)t; }
+ __forceinline vboolf(unsigned int t) { v = (__mmask16)t; }
+
+ /* return int8 mask */
+ __forceinline __m128i mask8() const {
+ return _mm_movm_epi8(v);
+ }
+
+ /* return int32 mask */
+ __forceinline __m512i mask32() const {
+ return _mm512_movm_epi32(v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf(FalseTy) : v(0x0000) {}
+ __forceinline vboolf(TrueTy) : v(0xffff) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator [](size_t index) const {
+ assert(index < 16); return (mm512_mask2int(v) >> index) & 1;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16 operator !(const vboolf16& a) { return _mm512_knot(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16 operator &(const vboolf16& a, const vboolf16& b) { return _mm512_kand(a,b); }
+ __forceinline vboolf16 operator |(const vboolf16& a, const vboolf16& b) { return _mm512_kor(a,b); }
+ __forceinline vboolf16 operator ^(const vboolf16& a, const vboolf16& b) { return _mm512_kxor(a,b); }
+
+ __forceinline vboolf16 andn(const vboolf16& a, const vboolf16& b) { return _mm512_kandn(b,a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16& operator &=(vboolf16& a, const vboolf16& b) { return a = a & b; }
+ __forceinline vboolf16& operator |=(vboolf16& a, const vboolf16& b) { return a = a | b; }
+ __forceinline vboolf16& operator ^=(vboolf16& a, const vboolf16& b) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16 operator !=(const vboolf16& a, const vboolf16& b) { return _mm512_kxor(a, b); }
+ __forceinline vboolf16 operator ==(const vboolf16& a, const vboolf16& b) { return _mm512_kxnor(a, b); }
+
+ __forceinline vboolf16 select(const vboolf16& s, const vboolf16& a, const vboolf16& b) {
+ return _mm512_kor(_mm512_kand(s,a),_mm512_kandn(s,b));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline int all (const vboolf16& a) { return _mm512_kortestc(a,a) != 0; }
+ __forceinline int any (const vboolf16& a) { return _mm512_kortestz(a,a) == 0; }
+ __forceinline int none(const vboolf16& a) { return _mm512_kortestz(a,a) != 0; }
+
+ __forceinline int all (const vboolf16& valid, const vboolf16& b) { return all((!valid) | b); }
+ __forceinline int any (const vboolf16& valid, const vboolf16& b) { return any(valid & b); }
+ __forceinline int none(const vboolf16& valid, const vboolf16& b) { return none(valid & b); }
+
+ __forceinline size_t movemask(const vboolf16& a) { return _mm512_kmov(a); }
+ __forceinline size_t popcnt (const vboolf16& a) { return popcnt(a.v); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Convertion Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline unsigned int toInt (const vboolf16& a) { return mm512_mask2int(a); }
+ __forceinline vboolf16 toMask(const int& a) { return mm512_int2mask(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Get/Set Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool get(const vboolf16& a, size_t index) { assert(index < 16); return (toInt(a) >> index) & 1; }
+ __forceinline void set(vboolf16& a, size_t index) { assert(index < 16); a |= 1 << index; }
+ __forceinline void clear(vboolf16& a, size_t index) { assert(index < 16); a = andn(a, 1 << index); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf16& a)
+ {
+ cout << "<";
+ for (size_t i=0; i<16; i++) {
+ if ((a.v >> i) & 1) cout << "1"; else cout << "0";
+ }
+ return cout << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vboolf4_avx512.h b/thirdparty/embree/common/simd/vboolf4_avx512.h
new file mode 100644
index 0000000000..e65f66b025
--- /dev/null
+++ b/thirdparty/embree/common/simd/vboolf4_avx512.h
@@ -0,0 +1,159 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide AVX-512 bool type */
+ template<>
+ struct vboolf<4>
+ {
+ typedef vboolf4 Bool;
+ typedef vint4 Int;
+
+ enum { size = 4 }; // number of SIMD elements
+ __mmask8 v; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf() {}
+ __forceinline vboolf(const vboolf4& t) { v = t.v; }
+ __forceinline vboolf4& operator =(const vboolf4& f) { v = f.v; return *this; }
+
+ __forceinline vboolf(const __mmask8 &t) { v = t; }
+ __forceinline operator __mmask8() const { return v; }
+
+ __forceinline vboolf(bool b) { v = b ? 0xf : 0x0; }
+ __forceinline vboolf(int t) { v = (__mmask8)t; }
+ __forceinline vboolf(unsigned int t) { v = (__mmask8)t; }
+
+ __forceinline vboolf(bool a, bool b, bool c, bool d)
+ : v((__mmask8)((int(d) << 3) | (int(c) << 2) | (int(b) << 1) | int(a))) {}
+
+ /* return int8 mask */
+ __forceinline __m128i mask8() const {
+ return _mm_movm_epi8(v);
+ }
+
+ /* return int32 mask */
+ __forceinline __m128i mask32() const {
+ return _mm_movm_epi32(v);
+ }
+
+ /* return int64 mask */
+ __forceinline __m256i mask64() const {
+ return _mm256_movm_epi64(v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf(FalseTy) : v(0x0) {}
+ __forceinline vboolf(TrueTy) : v(0xf) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator [](size_t index) const {
+ assert(index < 4); return (mm512_mask2int(v) >> index) & 1;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4 operator !(const vboolf4& a) { return _mm512_kandn(a, 0xf); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4 operator &(const vboolf4& a, const vboolf4& b) { return _mm512_kand(a, b); }
+ __forceinline vboolf4 operator |(const vboolf4& a, const vboolf4& b) { return _mm512_kor(a, b); }
+ __forceinline vboolf4 operator ^(const vboolf4& a, const vboolf4& b) { return _mm512_kxor(a, b); }
+
+ __forceinline vboolf4 andn(const vboolf4& a, const vboolf4& b) { return _mm512_kandn(b, a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4& operator &=(vboolf4& a, const vboolf4& b) { return a = a & b; }
+ __forceinline vboolf4& operator |=(vboolf4& a, const vboolf4& b) { return a = a | b; }
+ __forceinline vboolf4& operator ^=(vboolf4& a, const vboolf4& b) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4 operator !=(const vboolf4& a, const vboolf4& b) { return _mm512_kxor(a, b); }
+ __forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm512_kand(_mm512_kxnor(a, b), 0xf); }
+
+ __forceinline vboolf4 select(const vboolf4& s, const vboolf4& a, const vboolf4& b) {
+ return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline int all (const vboolf4& a) { return a.v == 0xf; }
+ __forceinline int any (const vboolf4& a) { return _mm512_kortestz(a, a) == 0; }
+ __forceinline int none(const vboolf4& a) { return _mm512_kortestz(a, a) != 0; }
+
+ __forceinline int all (const vboolf4& valid, const vboolf4& b) { return all((!valid) | b); }
+ __forceinline int any (const vboolf4& valid, const vboolf4& b) { return any(valid & b); }
+ __forceinline int none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
+
+ __forceinline size_t movemask(const vboolf4& a) { return _mm512_kmov(a); }
+ __forceinline size_t popcnt (const vboolf4& a) { return popcnt(a.v); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Conversion Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline unsigned int toInt(const vboolf4& a) { return mm512_mask2int(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Get/Set Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool get(const vboolf4& a, size_t index) { assert(index < 4); return (toInt(a) >> index) & 1; }
+ __forceinline void set(vboolf4& a, size_t index) { assert(index < 4); a |= 1 << index; }
+ __forceinline void clear(vboolf4& a, size_t index) { assert(index < 4); a = andn(a, 1 << index); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf4& a)
+ {
+ cout << "<";
+ for (size_t i=0; i<4; i++) {
+ if ((a.v >> i) & 1) cout << "1"; else cout << "0";
+ }
+ return cout << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vboolf4_sse2.h b/thirdparty/embree/common/simd/vboolf4_sse2.h
new file mode 100644
index 0000000000..fa84b1b6ee
--- /dev/null
+++ b/thirdparty/embree/common/simd/vboolf4_sse2.h
@@ -0,0 +1,189 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide SSE bool type */
+ template<>
+ struct vboolf<4>
+ {
+ ALIGNED_STRUCT_(16);
+
+ typedef vboolf4 Bool;
+ typedef vint4 Int;
+ typedef vfloat4 Float;
+
+ enum { size = 4 }; // number of SIMD elements
+ union { __m128 v; int i[4]; }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf() {}
+ __forceinline vboolf(const vboolf4& other) { v = other.v; }
+ __forceinline vboolf4& operator =(const vboolf4& other) { v = other.v; return *this; }
+
+ __forceinline vboolf(__m128 input) : v(input) {}
+ __forceinline operator const __m128&() const { return v; }
+ __forceinline operator const __m128i() const { return _mm_castps_si128(v); }
+ __forceinline operator const __m128d() const { return _mm_castps_pd(v); }
+
+ __forceinline vboolf(bool a)
+ : v(mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
+ __forceinline vboolf(bool a, bool b)
+ : v(mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
+ __forceinline vboolf(bool a, bool b, bool c, bool d)
+ : v(mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
+ __forceinline vboolf(int mask) { assert(mask >= 0 && mask < 16); v = mm_lookupmask_ps[mask]; }
+ __forceinline vboolf(unsigned int mask) { assert(mask < 16); v = mm_lookupmask_ps[mask]; }
+
+ /* return int32 mask */
+ __forceinline __m128i mask32() const {
+ return _mm_castps_si128(v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf(FalseTy) : v(_mm_setzero_ps()) {}
+ __forceinline vboolf(TrueTy) : v(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator [](size_t index) const { assert(index < 4); return (_mm_movemask_ps(v) >> index) & 1; }
+ __forceinline int& operator [](size_t index) { assert(index < 4); return i[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4 operator !(const vboolf4& a) { return _mm_xor_ps(a, vboolf4(embree::True)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4 operator &(const vboolf4& a, const vboolf4& b) { return _mm_and_ps(a, b); }
+ __forceinline vboolf4 operator |(const vboolf4& a, const vboolf4& b) { return _mm_or_ps (a, b); }
+ __forceinline vboolf4 operator ^(const vboolf4& a, const vboolf4& b) { return _mm_xor_ps(a, b); }
+
+ __forceinline vboolf4 andn(const vboolf4& a, const vboolf4& b) { return _mm_andnot_ps(b, a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4& operator &=(vboolf4& a, const vboolf4& b) { return a = a & b; }
+ __forceinline vboolf4& operator |=(vboolf4& a, const vboolf4& b) { return a = a | b; }
+ __forceinline vboolf4& operator ^=(vboolf4& a, const vboolf4& b) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4 operator !=(const vboolf4& a, const vboolf4& b) { return _mm_xor_ps(a, b); }
+ __forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
+
+ __forceinline vboolf4 select(const vboolf4& m, const vboolf4& t, const vboolf4& f) {
+#if defined(__SSE4_1__)
+ return _mm_blendv_ps(f, t, m);
+#else
+ return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf4 unpacklo(const vboolf4& a, const vboolf4& b) { return _mm_unpacklo_ps(a, b); }
+ __forceinline vboolf4 unpackhi(const vboolf4& a, const vboolf4& b) { return _mm_unpackhi_ps(a, b); }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vboolf4 shuffle(const vboolf4& v) {
+ return _mm_castsi128_ps(_mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) {
+ return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i0>
+ __forceinline vboolf4 shuffle(const vboolf4& v) {
+ return shuffle<i0,i0,i0,i0>(v);
+ }
+
+#if defined(__SSE3__)
+ template<> __forceinline vboolf4 shuffle<0, 0, 2, 2>(const vboolf4& v) { return _mm_moveldup_ps(v); }
+ template<> __forceinline vboolf4 shuffle<1, 1, 3, 3>(const vboolf4& v) { return _mm_movehdup_ps(v); }
+ template<> __forceinline vboolf4 shuffle<0, 1, 0, 1>(const vboolf4& v) { return _mm_castpd_ps(_mm_movedup_pd(v)); }
+#endif
+
+#if defined(__SSE4_1__)
+ template<int dst, int src, int clr> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
+ template<int dst, int src> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return insert<dst, src, 0>(a, b); }
+ template<int dst> __forceinline vboolf4 insert(const vboolf4& a, const bool b) { return insert<dst, 0>(a, vboolf4(b)); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool reduce_and(const vboolf4& a) { return _mm_movemask_ps(a) == 0xf; }
+ __forceinline bool reduce_or (const vboolf4& a) { return _mm_movemask_ps(a) != 0x0; }
+
+ __forceinline bool all (const vboolf4& b) { return _mm_movemask_ps(b) == 0xf; }
+ __forceinline bool any (const vboolf4& b) { return _mm_movemask_ps(b) != 0x0; }
+ __forceinline bool none(const vboolf4& b) { return _mm_movemask_ps(b) == 0x0; }
+
+ __forceinline bool all (const vboolf4& valid, const vboolf4& b) { return all((!valid) | b); }
+ __forceinline bool any (const vboolf4& valid, const vboolf4& b) { return any(valid & b); }
+ __forceinline bool none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
+
+ __forceinline size_t movemask(const vboolf4& a) { return _mm_movemask_ps(a); }
+#if defined(__SSE4_2__)
+ __forceinline size_t popcnt(const vboolf4& a) { return popcnt((size_t)_mm_movemask_ps(a)); }
+#else
+ __forceinline size_t popcnt(const vboolf4& a) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Get/Set Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool get(const vboolf4& a, size_t index) { return a[index]; }
+ __forceinline void set(vboolf4& a, size_t index) { a[index] = -1; }
+ __forceinline void clear(vboolf4& a, size_t index) { a[index] = 0; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf4& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vboolf8_avx.h b/thirdparty/embree/common/simd/vboolf8_avx.h
new file mode 100644
index 0000000000..ba77cc3c5e
--- /dev/null
+++ b/thirdparty/embree/common/simd/vboolf8_avx.h
@@ -0,0 +1,202 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX bool type */
+ template<>
+ struct vboolf<8>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboolf8 Bool;
+ typedef vint8 Int;
+ typedef vfloat8 Float;
+
+ enum { size = 8 }; // number of SIMD elements
+ union { // data
+ __m256 v;
+ struct { __m128 vl,vh; };
+ int i[8];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf() {}
+ __forceinline vboolf(const vboolf8& a) { v = a.v; }
+ __forceinline vboolf8& operator =(const vboolf8& a) { v = a.v; return *this; }
+
+ __forceinline vboolf(__m256 a) : v(a) {}
+ __forceinline operator const __m256&() const { return v; }
+ __forceinline operator const __m256i() const { return _mm256_castps_si256(v); }
+ __forceinline operator const __m256d() const { return _mm256_castps_pd(v); }
+
+ __forceinline vboolf(int a)
+ {
+ assert(a >= 0 && a <= 255);
+#if defined (__AVX2__)
+ const __m256i mask = _mm256_set_epi32(0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1);
+ const __m256i b = _mm256_set1_epi32(a);
+ const __m256i c = _mm256_and_si256(b,mask);
+ v = _mm256_castsi256_ps(_mm256_cmpeq_epi32(c,mask));
+#else
+ vl = mm_lookupmask_ps[a & 0xF];
+ vh = mm_lookupmask_ps[a >> 4];
+#endif
+ }
+
+ __forceinline vboolf(const vboolf4& a) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
+ __forceinline vboolf(const vboolf4& a, const vboolf4& b) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
+ __forceinline vboolf(__m128 a, __m128 b) : vl(a), vh(b) {}
+
+ __forceinline vboolf(bool a) : v(vboolf8(vboolf4(a), vboolf4(a))) {}
+ __forceinline vboolf(bool a, bool b) : v(vboolf8(vboolf4(a), vboolf4(b))) {}
+ __forceinline vboolf(bool a, bool b, bool c, bool d) : v(vboolf8(vboolf4(a,b), vboolf4(c,d))) {}
+ __forceinline vboolf(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h) : v(vboolf8(vboolf4(a,b,c,d), vboolf4(e,f,g,h))) {}
+
+ /* return int32 mask */
+ __forceinline __m256i mask32() const {
+ return _mm256_castps_si256(v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf(FalseTy) : v(_mm256_setzero_ps()) {}
+ __forceinline vboolf(TrueTy) : v(_mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OQ)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator [](size_t index) const { assert(index < 8); return (_mm256_movemask_ps(v) >> index) & 1; }
+ __forceinline int& operator [](size_t index) { assert(index < 8); return i[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 operator !(const vboolf8& a) { return _mm256_xor_ps(a, vboolf8(embree::True)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 operator &(const vboolf8& a, const vboolf8& b) { return _mm256_and_ps(a, b); }
+ __forceinline vboolf8 operator |(const vboolf8& a, const vboolf8& b) { return _mm256_or_ps (a, b); }
+ __forceinline vboolf8 operator ^(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(a, b); }
+
+ __forceinline vboolf8 andn(const vboolf8& a, const vboolf8& b) { return _mm256_andnot_ps(b, a); }
+
+ __forceinline vboolf8& operator &=(vboolf8& a, const vboolf8& b) { return a = a & b; }
+ __forceinline vboolf8& operator |=(vboolf8& a, const vboolf8& b) { return a = a | b; }
+ __forceinline vboolf8& operator ^=(vboolf8& a, const vboolf8& b) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 operator !=(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(a, b); }
+ __forceinline vboolf8 operator ==(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(_mm256_xor_ps(a,b),vboolf8(embree::True)); }
+
+ __forceinline vboolf8 select(const vboolf8& mask, const vboolf8& t, const vboolf8& f) {
+ return _mm256_blendv_ps(f, t, mask);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 unpacklo(const vboolf8& a, const vboolf8& b) { return _mm256_unpacklo_ps(a, b); }
+ __forceinline vboolf8 unpackhi(const vboolf8& a, const vboolf8& b) { return _mm256_unpackhi_ps(a, b); }
+
+ template<int i>
+ __forceinline vboolf8 shuffle(const vboolf8& v) {
+ return _mm256_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
+ }
+
+ template<int i0, int i1>
+ __forceinline vboolf8 shuffle4(const vboolf8& v) {
+ return _mm256_permute2f128_ps(v, v, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1>
+ __forceinline vboolf8 shuffle4(const vboolf8& a, const vboolf8& b) {
+ return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vboolf8 shuffle(const vboolf8& v) {
+ return _mm256_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vboolf8 shuffle(const vboolf8& a, const vboolf8& b) {
+ return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<> __forceinline vboolf8 shuffle<0, 0, 2, 2>(const vboolf8& v) { return _mm256_moveldup_ps(v); }
+ template<> __forceinline vboolf8 shuffle<1, 1, 3, 3>(const vboolf8& v) { return _mm256_movehdup_ps(v); }
+ template<> __forceinline vboolf8 shuffle<0, 1, 0, 1>(const vboolf8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); }
+
+ template<int i> __forceinline vboolf8 insert4(const vboolf8& a, const vboolf4& b) { return _mm256_insertf128_ps(a, b, i); }
+ template<int i> __forceinline vboolf4 extract4 (const vboolf8& a) { return _mm256_extractf128_ps(a, i); }
+ template<> __forceinline vboolf4 extract4<0>(const vboolf8& a) { return _mm256_castps256_ps128(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool reduce_and(const vboolf8& a) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
+ __forceinline bool reduce_or (const vboolf8& a) { return !_mm256_testz_ps(a,a); }
+
+ __forceinline bool all (const vboolf8& a) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
+ __forceinline bool any (const vboolf8& a) { return !_mm256_testz_ps(a,a); }
+ __forceinline bool none(const vboolf8& a) { return _mm256_testz_ps(a,a) != 0; }
+
+ __forceinline bool all (const vboolf8& valid, const vboolf8& b) { return all((!valid) | b); }
+ __forceinline bool any (const vboolf8& valid, const vboolf8& b) { return any(valid & b); }
+ __forceinline bool none(const vboolf8& valid, const vboolf8& b) { return none(valid & b); }
+
+ __forceinline unsigned int movemask(const vboolf8& a) { return _mm256_movemask_ps(a); }
+ __forceinline size_t popcnt (const vboolf8& a) { return popcnt((size_t)_mm256_movemask_ps(a)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Get/Set Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool get(const vboolf8& a, size_t index) { return a[index]; }
+ __forceinline void set(vboolf8& a, size_t index) { a[index] = -1; }
+ __forceinline void clear(vboolf8& a, size_t index) { a[index] = 0; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf8& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
+ << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vboolf8_avx512.h b/thirdparty/embree/common/simd/vboolf8_avx512.h
new file mode 100644
index 0000000000..73ff5666e1
--- /dev/null
+++ b/thirdparty/embree/common/simd/vboolf8_avx512.h
@@ -0,0 +1,159 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX-512 bool type */
+ template<>
+ struct vboolf<8>
+ {
+ typedef vboolf8 Bool;
+ typedef vint8 Int;
+
+ enum { size = 8 }; // number of SIMD elements
+ __mmask8 v; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf() {}
+ __forceinline vboolf(const vboolf8& t) { v = t.v; }
+ __forceinline vboolf8& operator =(const vboolf8& f) { v = f.v; return *this; }
+
+ __forceinline vboolf(const __mmask8 &t) { v = t; }
+ __forceinline operator __mmask8() const { return v; }
+
+ __forceinline vboolf(bool b) { v = b ? 0xff : 0x00; }
+ __forceinline vboolf(int t) { v = (__mmask8)t; }
+ __forceinline vboolf(unsigned int t) { v = (__mmask8)t; }
+
+ __forceinline vboolf(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h)
+ : v((__mmask8)((int(h) << 7) | (int(g) << 6) | (int(f) << 5) | (int(e) << 4) | (int(d) << 3) | (int(c) << 2) | (int(b) << 1) | int(a))) {}
+
+ /* return int8 mask */
+ __forceinline __m128i mask8() const {
+ return _mm_movm_epi8(v);
+ }
+
+ /* return int32 mask */
+ __forceinline __m256i mask32() const {
+ return _mm256_movm_epi32(v);
+ }
+
+ /* return int64 mask */
+ __forceinline __m512i mask64() const {
+ return _mm512_movm_epi64(v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf(FalseTy) : v(0x00) {}
+ __forceinline vboolf(TrueTy) : v(0xff) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator [](size_t index) const {
+ assert(index < 8); return (mm512_mask2int(v) >> index) & 1;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 operator !(const vboolf8& a) { return _mm512_knot(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 operator &(const vboolf8& a, const vboolf8& b) { return _mm512_kand(a, b); }
+ __forceinline vboolf8 operator |(const vboolf8& a, const vboolf8& b) { return _mm512_kor(a, b); }
+ __forceinline vboolf8 operator ^(const vboolf8& a, const vboolf8& b) { return _mm512_kxor(a, b); }
+
+ __forceinline vboolf8 andn(const vboolf8& a, const vboolf8& b) { return _mm512_kandn(b, a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8& operator &=(vboolf8& a, const vboolf8& b) { return a = a & b; }
+ __forceinline vboolf8& operator |=(vboolf8& a, const vboolf8& b) { return a = a | b; }
+ __forceinline vboolf8& operator ^=(vboolf8& a, const vboolf8& b) { return a = a ^ b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 operator !=(const vboolf8& a, const vboolf8& b) { return _mm512_kxor(a, b); }
+ __forceinline vboolf8 operator ==(const vboolf8& a, const vboolf8& b) { return _mm512_kxnor(a, b); }
+
+ __forceinline vboolf8 select(const vboolf8& s, const vboolf8& a, const vboolf8& b) {
+ return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reduction Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline int all (const vboolf8& a) { return a.v == 0xff; }
+ __forceinline int any (const vboolf8& a) { return _mm512_kortestz(a, a) == 0; }
+ __forceinline int none(const vboolf8& a) { return _mm512_kortestz(a, a) != 0; }
+
+ __forceinline int all (const vboolf8& valid, const vboolf8& b) { return all((!valid) | b); }
+ __forceinline int any (const vboolf8& valid, const vboolf8& b) { return any(valid & b); }
+ __forceinline int none(const vboolf8& valid, const vboolf8& b) { return none(valid & b); }
+
+ __forceinline size_t movemask(const vboolf8& a) { return _mm512_kmov(a); }
+ __forceinline size_t popcnt (const vboolf8& a) { return popcnt(a.v); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Conversion Operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline unsigned int toInt(const vboolf8& a) { return mm512_mask2int(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Get/Set Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool get(const vboolf8& a, size_t index) { assert(index < 8); return (toInt(a) >> index) & 1; }
+ __forceinline void set(vboolf8& a, size_t index) { assert(index < 8); a |= 1 << index; }
+ __forceinline void clear(vboolf8& a, size_t index) { assert(index < 8); a = andn(a, 1 << index); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vboolf8& a)
+ {
+ cout << "<";
+ for (size_t i=0; i<8; i++) {
+ if ((a.v >> i) & 1) cout << "1"; else cout << "0";
+ }
+ return cout << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vdouble4_avx.h b/thirdparty/embree/common/simd/vdouble4_avx.h
new file mode 100644
index 0000000000..55326de7dd
--- /dev/null
+++ b/thirdparty/embree/common/simd/vdouble4_avx.h
@@ -0,0 +1,321 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide AVX 64-bit double type */
+ template<>
+ struct vdouble<4>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboold4 Bool;
+
+ enum { size = 4 }; // number of SIMD elements
+ union { // data
+ __m256d v;
+ double i[4];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble() {}
+ __forceinline vdouble(const vdouble4& t) { v = t.v; }
+ __forceinline vdouble4& operator =(const vdouble4& f) { v = f.v; return *this; }
+
+ __forceinline vdouble(const __m256d& t) { v = t; }
+ __forceinline operator __m256d() const { return v; }
+
+ __forceinline vdouble(double i) {
+ v = _mm256_set1_pd(i);
+ }
+
+ __forceinline vdouble(double a, double b, double c, double d) {
+ v = _mm256_set_pd(d,c,b,a);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble(ZeroTy) : v(_mm256_setzero_pd()) {}
+ __forceinline vdouble(OneTy) : v(_mm256_set1_pd(1)) {}
+ __forceinline vdouble(StepTy) : v(_mm256_set_pd(3.0,2.0,1.0,0.0)) {}
+ __forceinline vdouble(ReverseStepTy) : v(_mm256_setr_pd(3.0,2.0,1.0,0.0)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline void store_nt(double *__restrict__ ptr, const vdouble4& a) {
+ _mm256_stream_pd(ptr, a);
+ }
+
+ static __forceinline vdouble4 loadu(const double* addr) {
+ return _mm256_loadu_pd(addr);
+ }
+
+ static __forceinline vdouble4 load(const vdouble4* addr) {
+ return _mm256_load_pd((double*)addr);
+ }
+
+ static __forceinline vdouble4 load(const double* addr) {
+ return _mm256_load_pd(addr);
+ }
+
+ static __forceinline void store(double* ptr, const vdouble4& v) {
+ _mm256_store_pd(ptr, v);
+ }
+
+ static __forceinline void storeu(double* ptr, const vdouble4& v) {
+ _mm256_storeu_pd(ptr, v);
+ }
+
+ static __forceinline vdouble4 broadcast(const void* a) { return _mm256_set1_pd(*(double*)a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline double& operator [](size_t index) { assert(index < 4); return i[index]; }
+ __forceinline const double& operator [](size_t index) const { assert(index < 4); return i[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX2__)
+ __forceinline vdouble4 asDouble(const vllong4& a) { return _mm256_castsi256_pd(a); }
+ __forceinline vllong4 asLLong (const vdouble4& a) { return _mm256_castpd_si256(a); }
+#endif
+
+ __forceinline vdouble4 operator +(const vdouble4& a) { return a; }
+ __forceinline vdouble4 operator -(const vdouble4& a) { return _mm256_sub_pd(_mm256_setzero_pd(), a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble4 operator +(const vdouble4& a, const vdouble4& b) { return _mm256_add_pd(a, b); }
+ __forceinline vdouble4 operator +(const vdouble4& a, double b) { return a + vdouble4(b); }
+ __forceinline vdouble4 operator +(double a, const vdouble4& b) { return vdouble4(a) + b; }
+
+ __forceinline vdouble4 operator -(const vdouble4& a, const vdouble4& b) { return _mm256_sub_pd(a, b); }
+ __forceinline vdouble4 operator -(const vdouble4& a, double b) { return a - vdouble4(b); }
+ __forceinline vdouble4 operator -(double a, const vdouble4& b) { return vdouble4(a) - b; }
+
+ __forceinline vdouble4 operator *(const vdouble4& a, const vdouble4& b) { return _mm256_mul_pd(a, b); }
+ __forceinline vdouble4 operator *(const vdouble4& a, double b) { return a * vdouble4(b); }
+ __forceinline vdouble4 operator *(double a, const vdouble4& b) { return vdouble4(a) * b; }
+
+ __forceinline vdouble4 operator &(const vdouble4& a, const vdouble4& b) { return _mm256_and_pd(a, b); }
+ __forceinline vdouble4 operator &(const vdouble4& a, double b) { return a & vdouble4(b); }
+ __forceinline vdouble4 operator &(double a, const vdouble4& b) { return vdouble4(a) & b; }
+
+ __forceinline vdouble4 operator |(const vdouble4& a, const vdouble4& b) { return _mm256_or_pd(a, b); }
+ __forceinline vdouble4 operator |(const vdouble4& a, double b) { return a | vdouble4(b); }
+ __forceinline vdouble4 operator |(double a, const vdouble4& b) { return vdouble4(a) | b; }
+
+ __forceinline vdouble4 operator ^(const vdouble4& a, const vdouble4& b) { return _mm256_xor_pd(a, b); }
+ __forceinline vdouble4 operator ^(const vdouble4& a, double b) { return a ^ vdouble4(b); }
+ __forceinline vdouble4 operator ^(double a, const vdouble4& b) { return vdouble4(a) ^ b; }
+
+ __forceinline vdouble4 min(const vdouble4& a, const vdouble4& b) { return _mm256_min_pd(a, b); }
+ __forceinline vdouble4 min(const vdouble4& a, double b) { return min(a,vdouble4(b)); }
+ __forceinline vdouble4 min(double a, const vdouble4& b) { return min(vdouble4(a),b); }
+
+ __forceinline vdouble4 max(const vdouble4& a, const vdouble4& b) { return _mm256_max_pd(a, b); }
+ __forceinline vdouble4 max(const vdouble4& a, double b) { return max(a,vdouble4(b)); }
+ __forceinline vdouble4 max(double a, const vdouble4& b) { return max(vdouble4(a),b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__FMA__)
+ __forceinline vdouble4 madd (const vdouble4& a, const vdouble4& b, const vdouble4& c) { return _mm256_fmadd_pd(a,b,c); }
+ __forceinline vdouble4 msub (const vdouble4& a, const vdouble4& b, const vdouble4& c) { return _mm256_fmsub_pd(a,b,c); }
+ __forceinline vdouble4 nmadd(const vdouble4& a, const vdouble4& b, const vdouble4& c) { return _mm256_fnmadd_pd(a,b,c); }
+ __forceinline vdouble4 nmsub(const vdouble4& a, const vdouble4& b, const vdouble4& c) { return _mm256_fnmsub_pd(a,b,c); }
+#else
+ __forceinline vdouble4 madd (const vdouble4& a, const vdouble4& b, const vdouble4& c) { return a*b+c; }
+ __forceinline vdouble4 msub (const vdouble4& a, const vdouble4& b, const vdouble4& c) { return a*b-c; }
+ __forceinline vdouble4 nmadd(const vdouble4& a, const vdouble4& b, const vdouble4& c) { return -a*b+c;}
+ __forceinline vdouble4 nmsub(const vdouble4& a, const vdouble4& b, const vdouble4& c) { return -a*b-c; }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble4& operator +=(vdouble4& a, const vdouble4& b) { return a = a + b; }
+ __forceinline vdouble4& operator +=(vdouble4& a, double b) { return a = a + b; }
+
+ __forceinline vdouble4& operator -=(vdouble4& a, const vdouble4& b) { return a = a - b; }
+ __forceinline vdouble4& operator -=(vdouble4& a, double b) { return a = a - b; }
+
+ __forceinline vdouble4& operator *=(vdouble4& a, const vdouble4& b) { return a = a * b; }
+ __forceinline vdouble4& operator *=(vdouble4& a, double b) { return a = a * b; }
+
+ __forceinline vdouble4& operator &=(vdouble4& a, const vdouble4& b) { return a = a & b; }
+ __forceinline vdouble4& operator &=(vdouble4& a, double b) { return a = a & b; }
+
+ __forceinline vdouble4& operator |=(vdouble4& a, const vdouble4& b) { return a = a | b; }
+ __forceinline vdouble4& operator |=(vdouble4& a, double b) { return a = a | b; }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_EQ); }
+ __forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_NE); }
+ __forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_LT); }
+ __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_GE); }
+ __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_GT); }
+ __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_LE); }
+#else
+ __forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_EQ_OQ); }
+ __forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NEQ_UQ); }
+ __forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_LT_OS); }
+ __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NLT_US); }
+ __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NLE_US); }
+ __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_LE_OS); }
+#endif
+
+ __forceinline vboold4 operator ==(const vdouble4& a, double b) { return a == vdouble4(b); }
+ __forceinline vboold4 operator ==(double a, const vdouble4& b) { return vdouble4(a) == b; }
+
+ __forceinline vboold4 operator !=(const vdouble4& a, double b) { return a != vdouble4(b); }
+ __forceinline vboold4 operator !=(double a, const vdouble4& b) { return vdouble4(a) != b; }
+
+ __forceinline vboold4 operator < (const vdouble4& a, double b) { return a < vdouble4(b); }
+ __forceinline vboold4 operator < (double a, const vdouble4& b) { return vdouble4(a) < b; }
+
+ __forceinline vboold4 operator >=(const vdouble4& a, double b) { return a >= vdouble4(b); }
+ __forceinline vboold4 operator >=(double a, const vdouble4& b) { return vdouble4(a) >= b; }
+
+ __forceinline vboold4 operator > (const vdouble4& a, double b) { return a > vdouble4(b); }
+ __forceinline vboold4 operator > (double a, const vdouble4& b) { return vdouble4(a) > b; }
+
+ __forceinline vboold4 operator <=(const vdouble4& a, double b) { return a <= vdouble4(b); }
+ __forceinline vboold4 operator <=(double a, const vdouble4& b) { return vdouble4(a) <= b; }
+
+ __forceinline vboold4 eq(const vdouble4& a, const vdouble4& b) { return a == b; }
+ __forceinline vboold4 ne(const vdouble4& a, const vdouble4& b) { return a != b; }
+ __forceinline vboold4 lt(const vdouble4& a, const vdouble4& b) { return a < b; }
+ __forceinline vboold4 ge(const vdouble4& a, const vdouble4& b) { return a >= b; }
+ __forceinline vboold4 gt(const vdouble4& a, const vdouble4& b) { return a > b; }
+ __forceinline vboold4 le(const vdouble4& a, const vdouble4& b) { return a <= b; }
+
+#if defined(__AVX512VL__)
+ __forceinline vboold4 eq(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_EQ); }
+ __forceinline vboold4 ne(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_NE); }
+ __forceinline vboold4 lt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_LT); }
+ __forceinline vboold4 ge(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_GE); }
+ __forceinline vboold4 gt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_GT); }
+ __forceinline vboold4 le(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_LE); }
+#else
+ __forceinline vboold4 eq(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a == b); }
+ __forceinline vboold4 ne(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a != b); }
+ __forceinline vboold4 lt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a < b); }
+ __forceinline vboold4 ge(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a >= b); }
+ __forceinline vboold4 gt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a > b); }
+ __forceinline vboold4 le(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a <= b); }
+#endif
+
+ __forceinline vdouble4 select(const vboold4& m, const vdouble4& t, const vdouble4& f) {
+#if defined(__AVX512VL__)
+ return _mm256_mask_blend_pd(m, f, t);
+#else
+ return _mm256_blendv_pd(f, t, m);
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int i0, int i1>
+ __forceinline vdouble4 shuffle(const vdouble4& v) {
+ return _mm256_permute_pd(v, (i1 << 3) | (i0 << 2) | (i1 << 1) | i0);
+ }
+
+ template<int i>
+ __forceinline vdouble4 shuffle(const vdouble4& v) {
+ return shuffle<i, i>(v);
+ }
+
+ template<int i0, int i1>
+ __forceinline vdouble4 shuffle2(const vdouble4& v) {
+ return _mm256_permute2f128_pd(v, v, (i1 << 4) | i0);
+ }
+
+ __forceinline double toScalar(const vdouble4& v) {
+ return _mm_cvtsd_f64(_mm256_castpd256_pd128(v));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble4 vreduce_min2(const vdouble4& x) { return min(x, shuffle<1,0>(x)); }
+ __forceinline vdouble4 vreduce_min (const vdouble4& y) { const vdouble4 x = vreduce_min2(y); return min(x, shuffle2<1,0>(x)); }
+
+ __forceinline vdouble4 vreduce_max2(const vdouble4& x) { return max(x,shuffle<1,0>(x)); }
+ __forceinline vdouble4 vreduce_max (const vdouble4& y) { const vdouble4 x = vreduce_max2(y); return max(x, shuffle2<1,0>(x)); }
+
+ __forceinline vdouble4 vreduce_and2(const vdouble4& x) { return x & shuffle<1,0>(x); }
+ __forceinline vdouble4 vreduce_and (const vdouble4& y) { const vdouble4 x = vreduce_and2(y); return x & shuffle2<1,0>(x); }
+
+ __forceinline vdouble4 vreduce_or2(const vdouble4& x) { return x | shuffle<1,0>(x); }
+ __forceinline vdouble4 vreduce_or (const vdouble4& y) { const vdouble4 x = vreduce_or2(y); return x | shuffle2<1,0>(x); }
+
+ __forceinline vdouble4 vreduce_add2(const vdouble4& x) { return x + shuffle<1,0>(x); }
+ __forceinline vdouble4 vreduce_add (const vdouble4& y) { const vdouble4 x = vreduce_add2(y); return x + shuffle2<1,0>(x); }
+
+ __forceinline double reduce_add(const vdouble4& a) { return toScalar(vreduce_add(a)); }
+ __forceinline double reduce_min(const vdouble4& a) { return toScalar(vreduce_min(a)); }
+ __forceinline double reduce_max(const vdouble4& a) { return toScalar(vreduce_max(a)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Memory load and store operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vdouble4& v)
+ {
+ cout << "<" << v[0];
+ for (size_t i=1; i<4; i++) cout << ", " << v[i];
+ cout << ">";
+ return cout;
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vdouble8_avx512.h b/thirdparty/embree/common/simd/vdouble8_avx512.h
new file mode 100644
index 0000000000..98d21bfe4a
--- /dev/null
+++ b/thirdparty/embree/common/simd/vdouble8_avx512.h
@@ -0,0 +1,351 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX-512 64-bit double type */
+ template<>
+ struct vdouble<8>
+ {
+ ALIGNED_STRUCT_(64);
+
+ typedef vboold8 Bool;
+
+ enum { size = 8 }; // number of SIMD elements
+ union { // data
+ __m512d v;
+ double i[8];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble() {}
+ __forceinline vdouble(const vdouble8& t) { v = t.v; }
+ __forceinline vdouble8& operator =(const vdouble8& f) { v = f.v; return *this; }
+
+ __forceinline vdouble(const __m512d& t) { v = t; }
+ __forceinline operator __m512d() const { return v; }
+ __forceinline operator __m256d() const { return _mm512_castpd512_pd256(v); }
+
+ __forceinline vdouble(double i) {
+ v = _mm512_set1_pd(i);
+ }
+
+ __forceinline vdouble(double a, double b, double c, double d) {
+ v = _mm512_set4_pd(d,c,b,a);
+ }
+
+ __forceinline vdouble(double a0, double a1, double a2, double a3,
+ double a4, double a5, double a6, double a7)
+ {
+ v = _mm512_set_pd(a7,a6,a5,a4,a3,a2,a1,a0);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble(ZeroTy) : v(_mm512_setzero_pd()) {}
+ __forceinline vdouble(OneTy) : v(_mm512_set1_pd(1)) {}
+ __forceinline vdouble(StepTy) : v(_mm512_set_pd(7.0,6.0,5.0,4.0,3.0,2.0,1.0,0.0)) {}
+ __forceinline vdouble(ReverseStepTy) : v(_mm512_setr_pd(7.0,6.0,5.0,4.0,3.0,2.0,1.0,0.0)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline void store_nt(void *__restrict__ ptr, const vdouble8& a) {
+ _mm512_stream_pd((double*)ptr, a);
+ }
+
+ static __forceinline vdouble8 loadu(const void* addr) {
+ return _mm512_loadu_pd((double*)addr);
+ }
+
+ static __forceinline vdouble8 load(const vdouble8* addr) {
+ return _mm512_load_pd((double*)addr);
+ }
+
+ static __forceinline vdouble8 load(const double* addr) {
+ return _mm512_load_pd(addr);
+ }
+
+ static __forceinline void store(void* ptr, const vdouble8& v) {
+ _mm512_store_pd(ptr, v);
+ }
+
+ static __forceinline void storeu(void* ptr, const vdouble8& v) {
+ _mm512_storeu_pd(ptr, v);
+ }
+
+ static __forceinline void storeu(const vboold8& mask, double* ptr, const vdouble8& f) {
+ _mm512_mask_storeu_pd(ptr, mask, f);
+ }
+
+ static __forceinline void store(const vboold8& mask, void* addr, const vdouble8& v2) {
+ _mm512_mask_store_pd(addr, mask, v2);
+ }
+
+ static __forceinline vdouble8 compact(const vboold8& mask, vdouble8& v) {
+ return _mm512_mask_compress_pd(v, mask, v);
+ }
+
+ static __forceinline vdouble8 compact(const vboold8& mask, const vdouble8& a, vdouble8& b) {
+ return _mm512_mask_compress_pd(a, mask, b);
+ }
+
+ static __forceinline vdouble8 broadcast(const void* a) { return _mm512_set1_pd(*(double*)a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline double& operator [](size_t index) { assert(index < 8); return i[index]; }
+ __forceinline const double& operator [](size_t index) const { assert(index < 8); return i[index]; }
+
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble8 asDouble(const vllong8& a) { return _mm512_castsi512_pd(a); }
+ __forceinline vllong8 asLLong (const vdouble8& a) { return _mm512_castpd_si512(a); }
+
+ __forceinline vdouble8 operator +(const vdouble8& a) { return a; }
+ __forceinline vdouble8 operator -(const vdouble8& a) { return _mm512_sub_pd(_mm512_setzero_pd(), a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble8 operator +(const vdouble8& a, const vdouble8& b) { return _mm512_add_pd(a, b); }
+ __forceinline vdouble8 operator +(const vdouble8& a, double b) { return a + vdouble8(b); }
+ __forceinline vdouble8 operator +(double a, const vdouble8& b) { return vdouble8(a) + b; }
+
+ __forceinline vdouble8 operator -(const vdouble8& a, const vdouble8& b) { return _mm512_sub_pd(a, b); }
+ __forceinline vdouble8 operator -(const vdouble8& a, double b) { return a - vdouble8(b); }
+ __forceinline vdouble8 operator -(double a, const vdouble8& b) { return vdouble8(a) - b; }
+
+ __forceinline vdouble8 operator *(const vdouble8& a, const vdouble8& b) { return _mm512_mul_pd(a, b); }
+ __forceinline vdouble8 operator *(const vdouble8& a, double b) { return a * vdouble8(b); }
+ __forceinline vdouble8 operator *(double a, const vdouble8& b) { return vdouble8(a) * b; }
+
+ __forceinline vdouble8 operator &(const vdouble8& a, const vdouble8& b) { return _mm512_and_pd(a, b); }
+ __forceinline vdouble8 operator &(const vdouble8& a, double b) { return a & vdouble8(b); }
+ __forceinline vdouble8 operator &(double a, const vdouble8& b) { return vdouble8(a) & b; }
+
+ __forceinline vdouble8 operator |(const vdouble8& a, const vdouble8& b) { return _mm512_or_pd(a, b); }
+ __forceinline vdouble8 operator |(const vdouble8& a, double b) { return a | vdouble8(b); }
+ __forceinline vdouble8 operator |(double a, const vdouble8& b) { return vdouble8(a) | b; }
+
+ __forceinline vdouble8 operator ^(const vdouble8& a, const vdouble8& b) { return _mm512_xor_pd(a, b); }
+ __forceinline vdouble8 operator ^(const vdouble8& a, double b) { return a ^ vdouble8(b); }
+ __forceinline vdouble8 operator ^(double a, const vdouble8& b) { return vdouble8(a) ^ b; }
+
+ __forceinline vdouble8 operator <<(const vdouble8& a, const unsigned int n) { return _mm512_castsi512_pd(_mm512_slli_epi64(_mm512_castpd_si512(a), n)); }
+ __forceinline vdouble8 operator >>(const vdouble8& a, const unsigned int n) { return _mm512_castsi512_pd(_mm512_srai_epi64(_mm512_castpd_si512(a), n)); }
+
+ __forceinline vdouble8 operator <<(const vdouble8& a, const vllong8& n) { return _mm512_castsi512_pd(_mm512_sllv_epi64(_mm512_castpd_si512(a), n)); }
+ __forceinline vdouble8 operator >>(const vdouble8& a, const vllong8& n) { return _mm512_castsi512_pd(_mm512_srav_epi64(_mm512_castpd_si512(a), n)); }
+
+ __forceinline vdouble8 sll (const vdouble8& a, const unsigned int b) { return _mm512_castsi512_pd(_mm512_slli_epi64(_mm512_castpd_si512(a), b)); }
+ __forceinline vdouble8 sra (const vdouble8& a, const unsigned int b) { return _mm512_castsi512_pd(_mm512_srai_epi64(_mm512_castpd_si512(a), b)); }
+ __forceinline vdouble8 srl (const vdouble8& a, const unsigned int b) { return _mm512_castsi512_pd(_mm512_srli_epi64(_mm512_castpd_si512(a), b)); }
+
+ __forceinline vdouble8 min(const vdouble8& a, const vdouble8& b) { return _mm512_min_pd(a, b); }
+ __forceinline vdouble8 min(const vdouble8& a, double b) { return min(a,vdouble8(b)); }
+ __forceinline vdouble8 min(double a, const vdouble8& b) { return min(vdouble8(a),b); }
+
+ __forceinline vdouble8 max(const vdouble8& a, const vdouble8& b) { return _mm512_max_pd(a, b); }
+ __forceinline vdouble8 max(const vdouble8& a, double b) { return max(a,vdouble8(b)); }
+ __forceinline vdouble8 max(double a, const vdouble8& b) { return max(vdouble8(a),b); }
+
+ __forceinline vdouble8 mask_add(const vboold8& mask, vdouble8& c, const vdouble8& a, const vdouble8& b) { return _mm512_mask_add_pd(c,mask,a,b); }
+ __forceinline vdouble8 mask_sub(const vboold8& mask, vdouble8& c, const vdouble8& a, const vdouble8& b) { return _mm512_mask_sub_pd(c,mask,a,b); }
+
+ __forceinline vdouble8 mask_and(const vboold8& m,vdouble8& c, const vdouble8& a, const vdouble8& b) { return _mm512_mask_and_pd(c,m,a,b); }
+ __forceinline vdouble8 mask_or (const vboold8& m,vdouble8& c, const vdouble8& a, const vdouble8& b) { return _mm512_mask_or_pd(c,m,a,b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble8 madd (const vdouble8& a, const vdouble8& b, const vdouble8& c) { return _mm512_fmadd_pd(a,b,c); }
+ __forceinline vdouble8 msub (const vdouble8& a, const vdouble8& b, const vdouble8& c) { return _mm512_fmsub_pd(a,b,c); }
+ __forceinline vdouble8 nmadd(const vdouble8& a, const vdouble8& b, const vdouble8& c) { return _mm512_fnmadd_pd(a,b,c); }
+ __forceinline vdouble8 nmsub(const vdouble8& a, const vdouble8& b, const vdouble8& c) { return _mm512_fnmsub_pd(a,b,c); }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble8& operator +=(vdouble8& a, const vdouble8& b) { return a = a + b; }
+ __forceinline vdouble8& operator +=(vdouble8& a, double b) { return a = a + b; }
+
+ __forceinline vdouble8& operator -=(vdouble8& a, const vdouble8& b) { return a = a - b; }
+ __forceinline vdouble8& operator -=(vdouble8& a, double b) { return a = a - b; }
+
+ __forceinline vdouble8& operator *=(vdouble8& a, const vdouble8& b) { return a = a * b; }
+ __forceinline vdouble8& operator *=(vdouble8& a, double b) { return a = a * b; }
+
+ __forceinline vdouble8& operator &=(vdouble8& a, const vdouble8& b) { return a = a & b; }
+ __forceinline vdouble8& operator &=(vdouble8& a, double b) { return a = a & b; }
+
+ __forceinline vdouble8& operator |=(vdouble8& a, const vdouble8& b) { return a = a | b; }
+ __forceinline vdouble8& operator |=(vdouble8& a, double b) { return a = a | b; }
+
+ __forceinline vdouble8& operator <<=(vdouble8& a, const double b) { return a = a << b; }
+ __forceinline vdouble8& operator >>=(vdouble8& a, const double b) { return a = a >> b; }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold8 operator ==(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboold8 operator ==(const vdouble8& a, double b) { return a == vdouble8(b); }
+ __forceinline vboold8 operator ==(double a, const vdouble8& b) { return vdouble8(a) == b; }
+
+ __forceinline vboold8 operator !=(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboold8 operator !=(const vdouble8& a, double b) { return a != vdouble8(b); }
+ __forceinline vboold8 operator !=(double a, const vdouble8& b) { return vdouble8(a) != b; }
+
+ __forceinline vboold8 operator < (const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboold8 operator < (const vdouble8& a, double b) { return a < vdouble8(b); }
+ __forceinline vboold8 operator < (double a, const vdouble8& b) { return vdouble8(a) < b; }
+
+ __forceinline vboold8 operator >=(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboold8 operator >=(const vdouble8& a, double b) { return a >= vdouble8(b); }
+ __forceinline vboold8 operator >=(double a, const vdouble8& b) { return vdouble8(a) >= b; }
+
+ __forceinline vboold8 operator > (const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboold8 operator > (const vdouble8& a, double b) { return a > vdouble8(b); }
+ __forceinline vboold8 operator > (double a, const vdouble8& b) { return vdouble8(a) > b; }
+
+ __forceinline vboold8 operator <=(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_LE); }
+ __forceinline vboold8 operator <=(const vdouble8& a, double b) { return a <= vdouble8(b); }
+ __forceinline vboold8 operator <=(double a, const vdouble8& b) { return vdouble8(a) <= b; }
+
+ __forceinline vboold8 eq(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboold8 ne(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboold8 lt(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboold8 ge(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboold8 gt(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboold8 le(const vdouble8& a, const vdouble8& b) { return _mm512_cmp_pd_mask(a,b,_MM_CMPINT_LE); }
+
+ __forceinline vboold8 eq(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_EQ); }
+ __forceinline vboold8 ne(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_NE); }
+ __forceinline vboold8 lt(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_LT); }
+ __forceinline vboold8 ge(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_GE); }
+ __forceinline vboold8 gt(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_GT); }
+ __forceinline vboold8 le(const vboold8 mask, const vdouble8& a, const vdouble8& b) { return _mm512_mask_cmp_pd_mask(mask,a,b,_MM_CMPINT_LE); }
+
+ __forceinline vdouble8 select(const vboold8& m, const vdouble8& t, const vdouble8& f) {
+ return _mm512_mask_or_pd(f,m,t,t);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int i0, int i1>
+ __forceinline vdouble8 shuffle(const vdouble8& v) {
+ return _mm512_permute_pd(v, (i1 << 7) | (i0 << 6) | (i1 << 5) | (i0 << 4) | (i1 << 3) | (i0 << 2) | (i1 << 1) | i0);
+ }
+
+ template<int i>
+ __forceinline vdouble8 shuffle(const vdouble8& v) {
+ return shuffle<i, i>(v);
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vdouble8 shuffle(const vdouble8& v) {
+ return _mm512_permutex_pd(v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i0, int i1>
+ __forceinline vdouble8 shuffle4(const vdouble8& v) {
+ return _mm512_shuffle_f64x2(v, v, _MM_SHUFFLE(i1*2+1, i1*2, i0*2+1, i0*2));
+ }
+
+ template<int i>
+ __forceinline vdouble8 shuffle4(const vdouble8& v) {
+ return shuffle4<i, i>(v);
+ }
+
+ template<int i>
+ __forceinline vdouble8 align_shift_right(const vdouble8& a, const vdouble8& b) {
+ return _mm512_castsi512_pd(_mm512_alignr_epi64(_mm512_castpd_si512(a), _mm512_castpd_si512(b), i));
+ }
+
+ __forceinline double toScalar(const vdouble8& v) {
+ return _mm_cvtsd_f64(_mm512_castpd512_pd128(v));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble8 vreduce_add2(vdouble8 x) { return x + shuffle<1,0,3,2>(x); }
+ __forceinline vdouble8 vreduce_add4(vdouble8 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
+ __forceinline vdouble8 vreduce_add (vdouble8 x) { x = vreduce_add4(x); return x + shuffle4<1,0>(x); }
+
+ __forceinline vdouble8 vreduce_min2(vdouble8 x) { return min(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vdouble8 vreduce_min4(vdouble8 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vdouble8 vreduce_min (vdouble8 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0>(x)); }
+
+ __forceinline vdouble8 vreduce_max2(vdouble8 x) { return max(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vdouble8 vreduce_max4(vdouble8 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vdouble8 vreduce_max (vdouble8 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0>(x)); }
+
+ __forceinline double reduce_add(const vdouble8& v) { return toScalar(vreduce_add(v)); }
+ __forceinline double reduce_min(const vdouble8& v) { return toScalar(vreduce_min(v)); }
+ __forceinline double reduce_max(const vdouble8& v) { return toScalar(vreduce_max(v)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Memory load and store operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vdouble8 permute(const vdouble8& v, const vllong8& index) {
+ return _mm512_permutexvar_pd(index, v);
+ }
+
+ __forceinline vdouble8 reverse(const vdouble8& a) {
+ return permute(a, vllong8(reverse_step));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vdouble8& v)
+ {
+ cout << "<" << v[0];
+ for (size_t i=1; i<8; i++) cout << ", " << v[i];
+ cout << ">";
+ return cout;
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vfloat16_avx512.h b/thirdparty/embree/common/simd/vfloat16_avx512.h
new file mode 100644
index 0000000000..9f1e2459c4
--- /dev/null
+++ b/thirdparty/embree/common/simd/vfloat16_avx512.h
@@ -0,0 +1,615 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 16-wide AVX-512 float type */
+ template<>
+ struct vfloat<16>
+ {
+ ALIGNED_STRUCT_(64);
+
+ typedef vboolf16 Bool;
+ typedef vint16 Int;
+ typedef vfloat16 Float;
+
+ enum { size = 16 }; // number of SIMD elements
+ union { // data
+ __m512 v;
+ float f[16];
+ int i[16];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat() {}
+ __forceinline vfloat(const vfloat16& t) { v = t; }
+ __forceinline vfloat16& operator =(const vfloat16& f) { v = f.v; return *this; }
+
+ __forceinline vfloat(const __m512& t) { v = t; }
+ __forceinline operator __m512() const { return v; }
+ __forceinline operator __m256() const { return _mm512_castps512_ps256(v); }
+ __forceinline operator __m128() const { return _mm512_castps512_ps128(v); }
+
+ __forceinline vfloat(float f) {
+ v = _mm512_set1_ps(f);
+ }
+
+ __forceinline vfloat(float a, float b, float c, float d) {
+ v = _mm512_set4_ps(a, b, c, d);
+ }
+
+ __forceinline vfloat(const vfloat4& i) {
+ v = _mm512_broadcast_f32x4(i);
+ }
+
+ __forceinline vfloat(const vfloat4& a, const vfloat4& b, const vfloat4& c, const vfloat4& d) {
+ v = _mm512_castps128_ps512(a);
+ v = _mm512_insertf32x4(v, b, 1);
+ v = _mm512_insertf32x4(v, c, 2);
+ v = _mm512_insertf32x4(v, d, 3);
+ }
+
+ __forceinline vfloat(const vboolf16& mask, const vfloat4& a, const vfloat4& b) {
+ v = _mm512_broadcast_f32x4(a);
+ v = _mm512_mask_broadcast_f32x4(v,mask,b);
+ }
+
+ __forceinline vfloat(const vfloat8& i) {
+ v = _mm512_castpd_ps(_mm512_broadcast_f64x4(_mm256_castps_pd(i)));
+ }
+
+ __forceinline vfloat(const vfloat8& a, const vfloat8& b) {
+ v = _mm512_castps256_ps512(a);
+#if defined(__AVX512DQ__)
+ v = _mm512_insertf32x8(v, b, 1);
+#else
+ v = _mm512_castpd_ps(_mm512_insertf64x4(_mm512_castps_pd(v), _mm256_castps_pd(b), 1));
+#endif
+ }
+
+ /* WARNING: due to f64x4 the mask is considered as an 8bit mask */
+ /*__forceinline vfloat(const vboolf16& mask, const vfloat8& a, const vfloat8& b) {
+ __m512d aa = _mm512_broadcast_f64x4(_mm256_castps_pd(a));
+ aa = _mm512_mask_broadcast_f64x4(aa,mask,_mm256_castps_pd(b));
+ v = _mm512_castpd_ps(aa);
+ }*/
+
+ __forceinline explicit vfloat(const vint16& a) {
+ v = _mm512_cvtepi32_ps(a);
+ }
+
+ __forceinline explicit vfloat(const vuint16& a) {
+ v = _mm512_cvtepu32_ps(a);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat(ZeroTy) : v(_mm512_setzero_ps()) {}
+ __forceinline vfloat(OneTy) : v(_mm512_set1_ps(1.0f)) {}
+ __forceinline vfloat(PosInfTy) : v(_mm512_set1_ps(pos_inf)) {}
+ __forceinline vfloat(NegInfTy) : v(_mm512_set1_ps(neg_inf)) {}
+ __forceinline vfloat(StepTy) : v(_mm512_set_ps(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
+ __forceinline vfloat(NaNTy) : v(_mm512_set1_ps(nan)) {}
+ __forceinline vfloat(UndefinedTy) : v(_mm512_undefined_ps()) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vfloat16 load (const void* ptr) { return _mm512_load_ps((float*)ptr); }
+ static __forceinline vfloat16 loadu(const void* ptr) { return _mm512_loadu_ps((float*)ptr); }
+
+ static __forceinline vfloat16 load (const vboolf16& mask, const void* ptr) { return _mm512_mask_load_ps (_mm512_setzero_ps(),mask,(float*)ptr); }
+ static __forceinline vfloat16 loadu(const vboolf16& mask, const void* ptr) { return _mm512_mask_loadu_ps(_mm512_setzero_ps(),mask,(float*)ptr); }
+
+ static __forceinline void store (void* ptr, const vfloat16& v) { _mm512_store_ps ((float*)ptr,v); }
+ static __forceinline void storeu(void* ptr, const vfloat16& v) { _mm512_storeu_ps((float*)ptr,v); }
+
+ static __forceinline void store (const vboolf16& mask, void* ptr, const vfloat16& v) { _mm512_mask_store_ps ((float*)ptr,mask,v); }
+ static __forceinline void storeu(const vboolf16& mask, void* ptr, const vfloat16& v) { _mm512_mask_storeu_ps((float*)ptr,mask,v); }
+
+ static __forceinline void store_nt(void* __restrict__ ptr, const vfloat16& a) {
+ _mm512_stream_ps((float*)ptr,a);
+ }
+
+ static __forceinline vfloat16 broadcast(const float* f) {
+ return _mm512_set1_ps(*f);
+ }
+
+ template<int scale = 4>
+ static __forceinline vfloat16 gather(const float* ptr, const vint16& index) {
+ return _mm512_i32gather_ps(index, ptr, scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline vfloat16 gather(const vboolf16& mask, const float* ptr, const vint16& index) {
+ vfloat16 r = zero;
+ return _mm512_mask_i32gather_ps(r, mask, index, ptr, scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(float* ptr, const vint16& index, const vfloat16& v) {
+ _mm512_i32scatter_ps(ptr, index, v, scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf16& mask, float* ptr, const vint16& index, const vfloat16& v) {
+ _mm512_mask_i32scatter_ps(ptr, mask, index, v, scale);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline float& operator [](size_t index) { assert(index < 16); return f[index]; }
+ __forceinline const float& operator [](size_t index) const { assert(index < 16); return f[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat16 asFloat(const vint16& a) { return _mm512_castsi512_ps(a); }
+ __forceinline vint16 asInt (const vfloat16& a) { return _mm512_castps_si512(a); }
+ __forceinline vuint16 asUInt (const vfloat16& a) { return _mm512_castps_si512(a); }
+
+ __forceinline vint16 toInt (const vfloat16& a) { return vint16(a); }
+ __forceinline vfloat16 toFloat(const vint16& a) { return vfloat16(a); }
+
+ __forceinline vfloat16 operator +(const vfloat16& a) { return a; }
+ __forceinline vfloat16 operator -(const vfloat16& a) { return _mm512_mul_ps(a,vfloat16(-1)); }
+
+ __forceinline vfloat16 abs (const vfloat16& a) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x7FFFFFFF))); }
+ __forceinline vfloat16 signmsk(const vfloat16& a) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x80000000))); }
+
+ __forceinline vfloat16 rcp(const vfloat16& a) {
+ const vfloat16 r = _mm512_rcp14_ps(a);
+ return _mm512_mul_ps(r, _mm512_fnmadd_ps(r, a, vfloat16(2.0f)));
+ }
+
+ __forceinline vfloat16 sqr (const vfloat16& a) { return _mm512_mul_ps(a,a); }
+ __forceinline vfloat16 sqrt(const vfloat16& a) { return _mm512_sqrt_ps(a); }
+
+ __forceinline vfloat16 rsqrt(const vfloat16& a)
+ {
+ const vfloat16 r = _mm512_rsqrt14_ps(a);
+ return _mm512_fmadd_ps(_mm512_set1_ps(1.5f), r,
+ _mm512_mul_ps(_mm512_mul_ps(_mm512_mul_ps(a, _mm512_set1_ps(-0.5f)), r), _mm512_mul_ps(r, r)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat16 operator +(const vfloat16& a, const vfloat16& b) { return _mm512_add_ps(a, b); }
+ __forceinline vfloat16 operator +(const vfloat16& a, float b) { return a + vfloat16(b); }
+ __forceinline vfloat16 operator +(float a, const vfloat16& b) { return vfloat16(a) + b; }
+
+ __forceinline vfloat16 operator -(const vfloat16& a, const vfloat16& b) { return _mm512_sub_ps(a, b); }
+ __forceinline vfloat16 operator -(const vfloat16& a, float b) { return a - vfloat16(b); }
+ __forceinline vfloat16 operator -(float a, const vfloat16& b) { return vfloat16(a) - b; }
+
+ __forceinline vfloat16 operator *(const vfloat16& a, const vfloat16& b) { return _mm512_mul_ps(a, b); }
+ __forceinline vfloat16 operator *(const vfloat16& a, float b) { return a * vfloat16(b); }
+ __forceinline vfloat16 operator *(float a, const vfloat16& b) { return vfloat16(a) * b; }
+
+ __forceinline vfloat16 operator /(const vfloat16& a, const vfloat16& b) { return _mm512_div_ps(a,b); }
+ __forceinline vfloat16 operator /(const vfloat16& a, float b) { return a/vfloat16(b); }
+ __forceinline vfloat16 operator /(float a, const vfloat16& b) { return vfloat16(a)/b; }
+
+ __forceinline vfloat16 operator &(const vfloat16& a, const vfloat16& b) { return _mm512_and_ps(a,b); }
+ __forceinline vfloat16 operator |(const vfloat16& a, const vfloat16& b) { return _mm512_or_ps(a,b); }
+ __forceinline vfloat16 operator ^(const vfloat16& a, const vfloat16& b) {
+ return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b)));
+ }
+
+ __forceinline vfloat16 min(const vfloat16& a, const vfloat16& b) { return _mm512_min_ps(a,b); }
+ __forceinline vfloat16 min(const vfloat16& a, float b) { return _mm512_min_ps(a,vfloat16(b)); }
+ __forceinline vfloat16 min(const float& a, const vfloat16& b) { return _mm512_min_ps(vfloat16(a),b); }
+
+ __forceinline vfloat16 max(const vfloat16& a, const vfloat16& b) { return _mm512_max_ps(a,b); }
+ __forceinline vfloat16 max(const vfloat16& a, float b) { return _mm512_max_ps(a,vfloat16(b)); }
+ __forceinline vfloat16 max(const float& a, const vfloat16& b) { return _mm512_max_ps(vfloat16(a),b); }
+
+ __forceinline vfloat16 mini(const vfloat16& a, const vfloat16& b) {
+ const vint16 ai = _mm512_castps_si512(a);
+ const vint16 bi = _mm512_castps_si512(b);
+ const vint16 ci = _mm512_min_epi32(ai,bi);
+ return _mm512_castsi512_ps(ci);
+ }
+
+ __forceinline vfloat16 maxi(const vfloat16& a, const vfloat16& b) {
+ const vint16 ai = _mm512_castps_si512(a);
+ const vint16 bi = _mm512_castps_si512(b);
+ const vint16 ci = _mm512_max_epi32(ai,bi);
+ return _mm512_castsi512_ps(ci);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat16 madd (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmadd_ps(a,b,c); }
+ __forceinline vfloat16 msub (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmsub_ps(a,b,c); }
+ __forceinline vfloat16 nmadd(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fnmadd_ps(a,b,c); }
+ __forceinline vfloat16 nmsub(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fnmsub_ps(a,b,c); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat16& operator +=(vfloat16& a, const vfloat16& b) { return a = a + b; }
+ __forceinline vfloat16& operator +=(vfloat16& a, float b) { return a = a + b; }
+
+ __forceinline vfloat16& operator -=(vfloat16& a, const vfloat16& b) { return a = a - b; }
+ __forceinline vfloat16& operator -=(vfloat16& a, float b) { return a = a - b; }
+
+ __forceinline vfloat16& operator *=(vfloat16& a, const vfloat16& b) { return a = a * b; }
+ __forceinline vfloat16& operator *=(vfloat16& a, float b) { return a = a * b; }
+
+ __forceinline vfloat16& operator /=(vfloat16& a, const vfloat16& b) { return a = a / b; }
+ __forceinline vfloat16& operator /=(vfloat16& a, float b) { return a = a / b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16 operator ==(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 operator ==(const vfloat16& a, float b) { return a == vfloat16(b); }
+ __forceinline vboolf16 operator ==(float a, const vfloat16& b) { return vfloat16(a) == b; }
+
+ __forceinline vboolf16 operator !=(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 operator !=(const vfloat16& a, float b) { return a != vfloat16(b); }
+ __forceinline vboolf16 operator !=(float a, const vfloat16& b) { return vfloat16(a) != b; }
+
+ __forceinline vboolf16 operator < (const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 operator < (const vfloat16& a, float b) { return a < vfloat16(b); }
+ __forceinline vboolf16 operator < (float a, const vfloat16& b) { return vfloat16(a) < b; }
+
+ __forceinline vboolf16 operator >=(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 operator >=(const vfloat16& a, float b) { return a >= vfloat16(b); }
+ __forceinline vboolf16 operator >=(float a, const vfloat16& b) { return vfloat16(a) >= b; }
+
+ __forceinline vboolf16 operator > (const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 operator > (const vfloat16& a, float b) { return a > vfloat16(b); }
+ __forceinline vboolf16 operator > (float a, const vfloat16& b) { return vfloat16(a) > b; }
+
+ __forceinline vboolf16 operator <=(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
+ __forceinline vboolf16 operator <=(const vfloat16& a, float b) { return a <= vfloat16(b); }
+ __forceinline vboolf16 operator <=(float a, const vfloat16& b) { return vfloat16(a) <= b; }
+
+ __forceinline vboolf16 eq(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 ne(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 lt(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 ge(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 gt(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 le(const vfloat16& a, const vfloat16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
+
+ __forceinline vboolf16 eq(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 ne(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 lt(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 ge(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 gt(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 le(const vboolf16& mask, const vfloat16& a, const vfloat16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LE); }
+
+ __forceinline vfloat16 select(const vboolf16& s, const vfloat16& t, const vfloat16& f) {
+ return _mm512_mask_blend_ps(s, f, t);
+ }
+
+ __forceinline vfloat16 lerp(const vfloat16& a, const vfloat16& b, const vfloat16& t) {
+ return madd(t,b-a,a);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Rounding Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat16 floor(const vfloat16& a) {
+ return _mm512_floor_ps(a);
+ }
+ __forceinline vfloat16 ceil (const vfloat16& a) {
+ return _mm512_ceil_ps(a);
+ }
+ __forceinline vfloat16 round (const vfloat16& a) {
+ return _mm512_roundscale_ps(a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+ }
+ __forceinline vint16 floori (const vfloat16& a) {
+ return _mm512_cvt_roundps_epi32(a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat16 unpacklo(const vfloat16& a, const vfloat16& b) { return _mm512_unpacklo_ps(a, b); }
+ __forceinline vfloat16 unpackhi(const vfloat16& a, const vfloat16& b) { return _mm512_unpackhi_ps(a, b); }
+
+ template<int i>
+ __forceinline vfloat16 shuffle(const vfloat16& v) {
+ return _mm512_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vfloat16 shuffle(const vfloat16& v) {
+ return _mm512_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i>
+ __forceinline vfloat16 shuffle4(const vfloat16& v) {
+ return _mm512_shuffle_f32x4(v, v ,_MM_SHUFFLE(i, i, i, i));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vfloat16 shuffle4(const vfloat16& v) {
+ return _mm512_shuffle_f32x4(v, v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ __forceinline vfloat16 interleave4_even(const vfloat16& a, const vfloat16& b) {
+ return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(a), mm512_int2mask(0xcc), _mm512_castps_si512(b), (_MM_PERM_ENUM)0x4e));
+ }
+
+ __forceinline vfloat16 interleave4_odd(const vfloat16& a, const vfloat16& b) {
+ return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(b), mm512_int2mask(0x33), _mm512_castps_si512(a), (_MM_PERM_ENUM)0x4e));
+ }
+
+ __forceinline vfloat16 permute(vfloat16 v, __m512i index) {
+ return _mm512_castsi512_ps(_mm512_permutexvar_epi32(index, _mm512_castps_si512(v)));
+ }
+
+ __forceinline vfloat16 reverse(const vfloat16& v) {
+ return permute(v,_mm512_setr_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0));
+ }
+
+ template<int i>
+ __forceinline vfloat16 align_shift_right(const vfloat16& a, const vfloat16& b) {
+ return _mm512_castsi512_ps(_mm512_alignr_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b),i));
+ };
+
+ template<int i>
+ __forceinline vfloat16 mask_align_shift_right(const vboolf16& mask, vfloat16& c, const vfloat16& a, const vfloat16& b) {
+ return _mm512_castsi512_ps(_mm512_mask_alignr_epi32(_mm512_castps_si512(c),mask,_mm512_castps_si512(a),_mm512_castps_si512(b),i));
+ };
+
+ __forceinline vfloat16 shift_left_1(const vfloat16& a) {
+ vfloat16 z = zero;
+ return mask_align_shift_right<15>(0xfffe,z,a,a);
+ }
+
+ __forceinline vfloat16 shift_right_1(const vfloat16& x) {
+ return align_shift_right<1>(zero,x);
+ }
+
+ __forceinline float toScalar(const vfloat16& v) { return mm512_cvtss_f32(v); }
+
+
+ template<int i> __forceinline vfloat16 insert4(const vfloat16& a, const vfloat4& b) { return _mm512_insertf32x4(a, b, i); }
+
+ template<int N, int i>
+ vfloat<N> extractN(const vfloat16& v);
+
+ template<> __forceinline vfloat4 extractN<4,0>(const vfloat16& v) { return _mm512_castps512_ps128(v); }
+ template<> __forceinline vfloat4 extractN<4,1>(const vfloat16& v) { return _mm512_extractf32x4_ps(v, 1); }
+ template<> __forceinline vfloat4 extractN<4,2>(const vfloat16& v) { return _mm512_extractf32x4_ps(v, 2); }
+ template<> __forceinline vfloat4 extractN<4,3>(const vfloat16& v) { return _mm512_extractf32x4_ps(v, 3); }
+
+ template<> __forceinline vfloat8 extractN<8,0>(const vfloat16& v) { return _mm512_castps512_ps256(v); }
+ template<> __forceinline vfloat8 extractN<8,1>(const vfloat16& v) { return _mm512_extractf32x8_ps(v, 1); }
+
+ template<int i> __forceinline vfloat4 extract4 (const vfloat16& v) { return _mm512_extractf32x4_ps(v, i); }
+ template<> __forceinline vfloat4 extract4<0>(const vfloat16& v) { return _mm512_castps512_ps128(v); }
+
+ template<int i> __forceinline vfloat8 extract8 (const vfloat16& v) { return _mm512_extractf32x8_ps(v, i); }
+ template<> __forceinline vfloat8 extract8<0>(const vfloat16& v) { return _mm512_castps512_ps256(v); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Transpose
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline void transpose(const vfloat16& r0, const vfloat16& r1, const vfloat16& r2, const vfloat16& r3,
+ vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3)
+ {
+ vfloat16 a0a2_b0b2 = unpacklo(r0, r2);
+ vfloat16 c0c2_d0d2 = unpackhi(r0, r2);
+ vfloat16 a1a3_b1b3 = unpacklo(r1, r3);
+ vfloat16 c1c3_d1d3 = unpackhi(r1, r3);
+
+ c0 = unpacklo(a0a2_b0b2, a1a3_b1b3);
+ c1 = unpackhi(a0a2_b0b2, a1a3_b1b3);
+ c2 = unpacklo(c0c2_d0d2, c1c3_d1d3);
+ c3 = unpackhi(c0c2_d0d2, c1c3_d1d3);
+ }
+
+ __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3,
+ const vfloat4& r4, const vfloat4& r5, const vfloat4& r6, const vfloat4& r7,
+ const vfloat4& r8, const vfloat4& r9, const vfloat4& r10, const vfloat4& r11,
+ const vfloat4& r12, const vfloat4& r13, const vfloat4& r14, const vfloat4& r15,
+ vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3)
+ {
+ return transpose(vfloat16(r0, r4, r8, r12), vfloat16(r1, r5, r9, r13), vfloat16(r2, r6, r10, r14), vfloat16(r3, r7, r11, r15),
+ c0, c1, c2, c3);
+ }
+
+ __forceinline void transpose(const vfloat16& r0, const vfloat16& r1, const vfloat16& r2, const vfloat16& r3,
+ const vfloat16& r4, const vfloat16& r5, const vfloat16& r6, const vfloat16& r7,
+ vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3,
+ vfloat16& c4, vfloat16& c5, vfloat16& c6, vfloat16& c7)
+ {
+ vfloat16 a0a1a2a3_e0e1e2e3, b0b1b2b3_f0f1f2f3, c0c1c2c3_g0g1g2g3, d0d1d2d3_h0h1h2h3;
+ transpose(r0, r1, r2, r3, a0a1a2a3_e0e1e2e3, b0b1b2b3_f0f1f2f3, c0c1c2c3_g0g1g2g3, d0d1d2d3_h0h1h2h3);
+
+ vfloat16 a4a5a6a7_e4e5e6e7, b4b5b6b7_f4f5f6f7, c4c5c6c7_g4g5g6g7, d4d5d6d7_h4h5h6h7;
+ transpose(r4, r5, r6, r7, a4a5a6a7_e4e5e6e7, b4b5b6b7_f4f5f6f7, c4c5c6c7_g4g5g6g7, d4d5d6d7_h4h5h6h7);
+
+ c0 = interleave4_even(a0a1a2a3_e0e1e2e3, a4a5a6a7_e4e5e6e7);
+ c1 = interleave4_even(b0b1b2b3_f0f1f2f3, b4b5b6b7_f4f5f6f7);
+ c2 = interleave4_even(c0c1c2c3_g0g1g2g3, c4c5c6c7_g4g5g6g7);
+ c3 = interleave4_even(d0d1d2d3_h0h1h2h3, d4d5d6d7_h4h5h6h7);
+ c4 = interleave4_odd (a0a1a2a3_e0e1e2e3, a4a5a6a7_e4e5e6e7);
+ c5 = interleave4_odd (b0b1b2b3_f0f1f2f3, b4b5b6b7_f4f5f6f7);
+ c6 = interleave4_odd (c0c1c2c3_g0g1g2g3, c4c5c6c7_g4g5g6g7);
+ c7 = interleave4_odd (d0d1d2d3_h0h1h2h3, d4d5d6d7_h4h5h6h7);
+ }
+
+ __forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3,
+ const vfloat8& r4, const vfloat8& r5, const vfloat8& r6, const vfloat8& r7,
+ const vfloat8& r8, const vfloat8& r9, const vfloat8& r10, const vfloat8& r11,
+ const vfloat8& r12, const vfloat8& r13, const vfloat8& r14, const vfloat8& r15,
+ vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3,
+ vfloat16& c4, vfloat16& c5, vfloat16& c6, vfloat16& c7)
+ {
+ return transpose(vfloat16(r0, r8), vfloat16(r1, r9), vfloat16(r2, r10), vfloat16(r3, r11),
+ vfloat16(r4, r12), vfloat16(r5, r13), vfloat16(r6, r14), vfloat16(r7, r15),
+ c0, c1, c2, c3, c4, c5, c6, c7);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat16 vreduce_add2(vfloat16 x) { return x + shuffle<1,0,3,2>(x); }
+ __forceinline vfloat16 vreduce_add4(vfloat16 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
+ __forceinline vfloat16 vreduce_add8(vfloat16 x) { x = vreduce_add4(x); return x + shuffle4<1,0,3,2>(x); }
+ __forceinline vfloat16 vreduce_add (vfloat16 x) { x = vreduce_add8(x); return x + shuffle4<2,3,0,1>(x); }
+
+ __forceinline vfloat16 vreduce_min2(vfloat16 x) { return min(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vfloat16 vreduce_min4(vfloat16 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vfloat16 vreduce_min8(vfloat16 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0,3,2>(x)); }
+ __forceinline vfloat16 vreduce_min (vfloat16 x) { x = vreduce_min8(x); return min(x, shuffle4<2,3,0,1>(x)); }
+
+ __forceinline vfloat16 vreduce_max2(vfloat16 x) { return max(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vfloat16 vreduce_max4(vfloat16 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vfloat16 vreduce_max8(vfloat16 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0,3,2>(x)); }
+ __forceinline vfloat16 vreduce_max (vfloat16 x) { x = vreduce_max8(x); return max(x, shuffle4<2,3,0,1>(x)); }
+
+ __forceinline float reduce_add(const vfloat16& v) { return toScalar(vreduce_add(v)); }
+ __forceinline float reduce_min(const vfloat16& v) { return toScalar(vreduce_min(v)); }
+ __forceinline float reduce_max(const vfloat16& v) { return toScalar(vreduce_max(v)); }
+
+ __forceinline size_t select_min(const vfloat16& v) {
+ return bsf(_mm512_kmov(_mm512_cmp_epi32_mask(_mm512_castps_si512(v),_mm512_castps_si512(vreduce_min(v)),_MM_CMPINT_EQ)));
+ }
+
+ __forceinline size_t select_max(const vfloat16& v) {
+ return bsf(_mm512_kmov(_mm512_cmp_epi32_mask(_mm512_castps_si512(v),_mm512_castps_si512(vreduce_max(v)),_MM_CMPINT_EQ)));
+ }
+
+ __forceinline size_t select_min(const vboolf16& valid, const vfloat16& v)
+ {
+ const vfloat16 a = select(valid,v,vfloat16(pos_inf));
+ const vbool16 valid_min = valid & (a == vreduce_min(a));
+ return bsf(movemask(any(valid_min) ? valid_min : valid));
+ }
+
+ __forceinline size_t select_max(const vboolf16& valid, const vfloat16& v)
+ {
+ const vfloat16 a = select(valid,v,vfloat16(neg_inf));
+ const vbool16 valid_max = valid & (a == vreduce_max(a));
+ return bsf(movemask(any(valid_max) ? valid_max : valid));
+ }
+
+ __forceinline vfloat16 prefix_sum(const vfloat16& a)
+ {
+ const vfloat16 z(zero);
+ vfloat16 v = a;
+ v = v + align_shift_right<16-1>(v,z);
+ v = v + align_shift_right<16-2>(v,z);
+ v = v + align_shift_right<16-4>(v,z);
+ v = v + align_shift_right<16-8>(v,z);
+ return v;
+ }
+
+ __forceinline vfloat16 reverse_prefix_sum(const vfloat16& a)
+ {
+ const vfloat16 z(zero);
+ vfloat16 v = a;
+ v = v + align_shift_right<1>(z,v);
+ v = v + align_shift_right<2>(z,v);
+ v = v + align_shift_right<4>(z,v);
+ v = v + align_shift_right<8>(z,v);
+ return v;
+ }
+
+ __forceinline vfloat16 prefix_min(const vfloat16& a)
+ {
+ const vfloat16 z(pos_inf);
+ vfloat16 v = a;
+ v = min(v,align_shift_right<16-1>(v,z));
+ v = min(v,align_shift_right<16-2>(v,z));
+ v = min(v,align_shift_right<16-4>(v,z));
+ v = min(v,align_shift_right<16-8>(v,z));
+ return v;
+ }
+
+ __forceinline vfloat16 prefix_max(const vfloat16& a)
+ {
+ const vfloat16 z(neg_inf);
+ vfloat16 v = a;
+ v = max(v,align_shift_right<16-1>(v,z));
+ v = max(v,align_shift_right<16-2>(v,z));
+ v = max(v,align_shift_right<16-4>(v,z));
+ v = max(v,align_shift_right<16-8>(v,z));
+ return v;
+ }
+
+
+ __forceinline vfloat16 reverse_prefix_min(const vfloat16& a)
+ {
+ const vfloat16 z(pos_inf);
+ vfloat16 v = a;
+ v = min(v,align_shift_right<1>(z,v));
+ v = min(v,align_shift_right<2>(z,v));
+ v = min(v,align_shift_right<4>(z,v));
+ v = min(v,align_shift_right<8>(z,v));
+ return v;
+ }
+
+ __forceinline vfloat16 reverse_prefix_max(const vfloat16& a)
+ {
+ const vfloat16 z(neg_inf);
+ vfloat16 v = a;
+ v = max(v,align_shift_right<1>(z,v));
+ v = max(v,align_shift_right<2>(z,v));
+ v = max(v,align_shift_right<4>(z,v));
+ v = max(v,align_shift_right<8>(z,v));
+ return v;
+ }
+
+ __forceinline vfloat16 rcp_safe(const vfloat16& a) {
+ return rcp(select(a != vfloat16(zero), a, vfloat16(min_rcp_input)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vfloat16& v)
+ {
+ cout << "<" << v[0];
+ for (int i=1; i<16; i++) cout << ", " << v[i];
+ cout << ">";
+ return cout;
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vfloat4_sse2.h b/thirdparty/embree/common/simd/vfloat4_sse2.h
new file mode 100644
index 0000000000..5215bf9730
--- /dev/null
+++ b/thirdparty/embree/common/simd/vfloat4_sse2.h
@@ -0,0 +1,722 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide SSE float type */
+ template<>
+ struct vfloat<4>
+ {
+ ALIGNED_STRUCT_(16);
+
+ typedef vboolf4 Bool;
+ typedef vint4 Int;
+ typedef vfloat4 Float;
+
+ enum { size = 4 }; // number of SIMD elements
+ union { __m128 v; float f[4]; int i[4]; }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat() {}
+ __forceinline vfloat(const vfloat4& other) { v = other.v; }
+ __forceinline vfloat4& operator =(const vfloat4& other) { v = other.v; return *this; }
+
+ __forceinline vfloat(__m128 a) : v(a) {}
+ __forceinline operator const __m128&() const { return v; }
+ __forceinline operator __m128&() { return v; }
+
+ __forceinline vfloat(float a) : v(_mm_set1_ps(a)) {}
+ __forceinline vfloat(float a, float b, float c, float d) : v(_mm_set_ps(d, c, b, a)) {}
+
+ __forceinline explicit vfloat(const vint4& a) : v(_mm_cvtepi32_ps(a)) {}
+ __forceinline explicit vfloat(const vuint4& x) {
+ const __m128i a = _mm_and_si128(x,_mm_set1_epi32(0x7FFFFFFF));
+ const __m128i b = _mm_and_si128(_mm_srai_epi32(x,31),_mm_set1_epi32(0x4F000000)); //0x4F000000 = 2^31
+ const __m128 af = _mm_cvtepi32_ps(a);
+ const __m128 bf = _mm_castsi128_ps(b);
+ v = _mm_add_ps(af,bf);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat(ZeroTy) : v(_mm_setzero_ps()) {}
+ __forceinline vfloat(OneTy) : v(_mm_set1_ps(1.0f)) {}
+ __forceinline vfloat(PosInfTy) : v(_mm_set1_ps(pos_inf)) {}
+ __forceinline vfloat(NegInfTy) : v(_mm_set1_ps(neg_inf)) {}
+ __forceinline vfloat(StepTy) : v(_mm_set_ps(3.0f, 2.0f, 1.0f, 0.0f)) {}
+ __forceinline vfloat(NaNTy) : v(_mm_set1_ps(nan)) {}
+ __forceinline vfloat(UndefinedTy) : v(_mm_undefined_ps()) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vfloat4 load (const void* a) { return _mm_load_ps((float*)a); }
+ static __forceinline vfloat4 loadu(const void* a) { return _mm_loadu_ps((float*)a); }
+
+ static __forceinline void store (void* ptr, const vfloat4& v) { _mm_store_ps((float*)ptr,v); }
+ static __forceinline void storeu(void* ptr, const vfloat4& v) { _mm_storeu_ps((float*)ptr,v); }
+
+#if defined(__AVX512VL__)
+
+ static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return _mm_mask_load_ps (_mm_setzero_ps(),mask,(float*)ptr); }
+ static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return _mm_mask_loadu_ps(_mm_setzero_ps(),mask,(float*)ptr); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vfloat4& v) { _mm_mask_store_ps ((float*)ptr,mask,v); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vfloat4& v) { _mm_mask_storeu_ps((float*)ptr,mask,v); }
+#elif defined(__AVX__)
+ static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return _mm_maskload_ps((float*)ptr,mask); }
+ static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return _mm_maskload_ps((float*)ptr,mask); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vfloat4& v) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,v); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vfloat4& v) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,v); }
+#else
+ static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return _mm_and_ps(_mm_load_ps ((float*)ptr),mask); }
+ static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return _mm_and_ps(_mm_loadu_ps((float*)ptr),mask); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vfloat4& v) { store (ptr,select(mask,v,load (ptr))); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vfloat4& v) { storeu(ptr,select(mask,v,loadu(ptr))); }
+#endif
+
+#if defined(__AVX__)
+ static __forceinline vfloat4 broadcast(const void* a) { return _mm_broadcast_ss((float*)a); }
+#else
+ static __forceinline vfloat4 broadcast(const void* a) { return _mm_set1_ps(*(float*)a); }
+#endif
+
+ static __forceinline vfloat4 load_nt (const float* ptr) {
+#if defined (__SSE4_1__)
+ return _mm_castsi128_ps(_mm_stream_load_si128((__m128i*)ptr));
+#else
+ return _mm_load_ps(ptr);
+#endif
+ }
+
+#if defined(__SSE4_1__)
+ static __forceinline vfloat4 load(const char* ptr) {
+ return _mm_cvtepi32_ps(_mm_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr)));
+ }
+#else
+ static __forceinline vfloat4 load(const char* ptr) {
+ return vfloat4(ptr[0],ptr[1],ptr[2],ptr[3]);
+ }
+#endif
+
+#if defined(__SSE4_1__)
+ static __forceinline vfloat4 load(const unsigned char* ptr) {
+ return _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
+ }
+#else
+ static __forceinline vfloat4 load(const unsigned char* ptr) {
+ //return _mm_cvtpu8_ps(*(__m64*)ptr); // don't enable, will use MMX instructions
+ return vfloat4(ptr[0],ptr[1],ptr[2],ptr[3]);
+ }
+#endif
+
+#if defined(__SSE4_1__)
+ static __forceinline vfloat4 load(const short* ptr) {
+ return _mm_cvtepi32_ps(_mm_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr)));
+ }
+#else
+ static __forceinline vfloat4 load(const short* ptr) {
+ return vfloat4(ptr[0],ptr[1],ptr[2],ptr[3]);
+ }
+#endif
+
+ static __forceinline vfloat4 load(const unsigned short* ptr) {
+ return _mm_mul_ps(vfloat4(vint4::load(ptr)),vfloat4(1.0f/65535.0f));
+ }
+
+ static __forceinline void store_nt(void* ptr, const vfloat4& v)
+ {
+#if defined (__SSE4_1__)
+ _mm_stream_ps((float*)ptr,v);
+#else
+ _mm_store_ps((float*)ptr,v);
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline vfloat4 gather(const float* ptr, const vint4& index) {
+#if defined(__AVX2__)
+ return _mm_i32gather_ps(ptr, index, scale);
+#else
+ return vfloat4(
+ *(float*)(((char*)ptr)+scale*index[0]),
+ *(float*)(((char*)ptr)+scale*index[1]),
+ *(float*)(((char*)ptr)+scale*index[2]),
+ *(float*)(((char*)ptr)+scale*index[3]));
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline vfloat4 gather(const vboolf4& mask, const float* ptr, const vint4& index) {
+ vfloat4 r = zero;
+#if defined(__AVX512VL__)
+ return _mm_mmask_i32gather_ps(r, mask, index, ptr, scale);
+#elif defined(__AVX2__)
+ return _mm_mask_i32gather_ps(r, ptr, index, mask, scale);
+#else
+ if (likely(mask[0])) r[0] = *(float*)(((char*)ptr)+scale*index[0]);
+ if (likely(mask[1])) r[1] = *(float*)(((char*)ptr)+scale*index[1]);
+ if (likely(mask[2])) r[2] = *(float*)(((char*)ptr)+scale*index[2]);
+ if (likely(mask[3])) r[3] = *(float*)(((char*)ptr)+scale*index[3]);
+ return r;
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(void* ptr, const vint4& index, const vfloat4& v)
+ {
+#if defined(__AVX512VL__)
+ _mm_i32scatter_ps((float*)ptr, index, v, scale);
+#else
+ *(float*)(((char*)ptr)+scale*index[0]) = v[0];
+ *(float*)(((char*)ptr)+scale*index[1]) = v[1];
+ *(float*)(((char*)ptr)+scale*index[2]) = v[2];
+ *(float*)(((char*)ptr)+scale*index[3]) = v[3];
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf4& mask, void* ptr, const vint4& index, const vfloat4& v)
+ {
+#if defined(__AVX512VL__)
+ _mm_mask_i32scatter_ps((float*)ptr ,mask, index, v, scale);
+#else
+ if (likely(mask[0])) *(float*)(((char*)ptr)+scale*index[0]) = v[0];
+ if (likely(mask[1])) *(float*)(((char*)ptr)+scale*index[1]) = v[1];
+ if (likely(mask[2])) *(float*)(((char*)ptr)+scale*index[2]) = v[2];
+ if (likely(mask[3])) *(float*)(((char*)ptr)+scale*index[3]) = v[3];
+#endif
+ }
+
+ static __forceinline void store(const vboolf4& mask, char* ptr, const vint4& ofs, const vfloat4& v) {
+ scatter<1>(mask,ptr,ofs,v);
+ }
+ static __forceinline void store(const vboolf4& mask, float* ptr, const vint4& ofs, const vfloat4& v) {
+ scatter<4>(mask,ptr,ofs,v);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const float& operator [](size_t index) const { assert(index < 4); return f[index]; }
+ __forceinline float& operator [](size_t index) { assert(index < 4); return f[index]; }
+
+ friend __forceinline vfloat4 select(const vboolf4& m, const vfloat4& t, const vfloat4& f) {
+#if defined(__AVX512VL__)
+ return _mm_mask_blend_ps(m, f, t);
+#elif defined(__SSE4_1__)
+ return _mm_blendv_ps(f, t, m);
+#else
+ return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
+#endif
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Load/Store
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<> struct mem<vfloat4>
+ {
+ static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return vfloat4::load (mask,ptr); }
+ static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return vfloat4::loadu(mask,ptr); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vfloat4& v) { vfloat4::store (mask,ptr,v); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vfloat4& v) { vfloat4::storeu(mask,ptr,v); }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat4 asFloat(const vint4& a) { return _mm_castsi128_ps(a); }
+ __forceinline vint4 asInt (const vfloat4& a) { return _mm_castps_si128(a); }
+ __forceinline vuint4 asUInt (const vfloat4& a) { return _mm_castps_si128(a); }
+
+ __forceinline vint4 toInt (const vfloat4& a) { return vint4(a); }
+ __forceinline vfloat4 toFloat(const vint4& a) { return vfloat4(a); }
+
+ __forceinline vfloat4 operator +(const vfloat4& a) { return a; }
+ __forceinline vfloat4 operator -(const vfloat4& a) { return _mm_xor_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
+
+ __forceinline vfloat4 abs(const vfloat4& a) { return _mm_and_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); }
+#if defined(__AVX512VL__)
+ __forceinline vfloat4 sign(const vfloat4& a) { return _mm_mask_blend_ps(_mm_cmp_ps_mask(a, vfloat4(zero), _CMP_LT_OQ), vfloat4(one), -vfloat4(one)); }
+#else
+ __forceinline vfloat4 sign(const vfloat4& a) { return blendv_ps(vfloat4(one), -vfloat4(one), _mm_cmplt_ps(a, vfloat4(zero))); }
+#endif
+ __forceinline vfloat4 signmsk(const vfloat4& a) { return _mm_and_ps(a,_mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
+
+ __forceinline vfloat4 rcp(const vfloat4& a)
+ {
+#if defined(__AVX512VL__)
+ const vfloat4 r = _mm_rcp14_ps(a);
+#else
+ const vfloat4 r = _mm_rcp_ps(a);
+#endif
+
+#if defined(__AVX2__)
+ return _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f)));
+#else
+ return _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a)));
+#endif
+ }
+ __forceinline vfloat4 sqr (const vfloat4& a) { return _mm_mul_ps(a,a); }
+ __forceinline vfloat4 sqrt(const vfloat4& a) { return _mm_sqrt_ps(a); }
+
+ __forceinline vfloat4 rsqrt(const vfloat4& a)
+ {
+#if defined(__AVX512VL__)
+ vfloat4 r = _mm_rsqrt14_ps(a);
+#else
+ vfloat4 r = _mm_rsqrt_ps(a);
+#endif
+
+#if defined(__ARM_NEON)
+ r = _mm_fmadd_ps(_mm_set1_ps(1.5f), r, _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+ r = _mm_fmadd_ps(_mm_set1_ps(1.5f), r, _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+#elif defined(__AVX2__)
+ r = _mm_fmadd_ps(_mm_set1_ps(1.5f), r, _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+#else
+ r = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f), r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
+#endif
+ return r;
+ }
+
+ __forceinline vboolf4 isnan(const vfloat4& a) {
+ const vfloat4 b = _mm_and_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)));
+#if defined(__AVX512VL__)
+ return _mm_cmp_epi32_mask(_mm_castps_si128(b), _mm_set1_epi32(0x7f800000), _MM_CMPINT_GT);
+#else
+ return _mm_castsi128_ps(_mm_cmpgt_epi32(_mm_castps_si128(b), _mm_set1_epi32(0x7f800000)));
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat4 operator +(const vfloat4& a, const vfloat4& b) { return _mm_add_ps(a, b); }
+ __forceinline vfloat4 operator +(const vfloat4& a, float b) { return a + vfloat4(b); }
+ __forceinline vfloat4 operator +(float a, const vfloat4& b) { return vfloat4(a) + b; }
+
+ __forceinline vfloat4 operator -(const vfloat4& a, const vfloat4& b) { return _mm_sub_ps(a, b); }
+ __forceinline vfloat4 operator -(const vfloat4& a, float b) { return a - vfloat4(b); }
+ __forceinline vfloat4 operator -(float a, const vfloat4& b) { return vfloat4(a) - b; }
+
+ __forceinline vfloat4 operator *(const vfloat4& a, const vfloat4& b) { return _mm_mul_ps(a, b); }
+ __forceinline vfloat4 operator *(const vfloat4& a, float b) { return a * vfloat4(b); }
+ __forceinline vfloat4 operator *(float a, const vfloat4& b) { return vfloat4(a) * b; }
+
+ __forceinline vfloat4 operator /(const vfloat4& a, const vfloat4& b) { return _mm_div_ps(a,b); }
+ __forceinline vfloat4 operator /(const vfloat4& a, float b) { return a/vfloat4(b); }
+ __forceinline vfloat4 operator /(float a, const vfloat4& b) { return vfloat4(a)/b; }
+
+ __forceinline vfloat4 operator &(const vfloat4& a, const vfloat4& b) { return _mm_and_ps(a,b); }
+ __forceinline vfloat4 operator |(const vfloat4& a, const vfloat4& b) { return _mm_or_ps(a,b); }
+ __forceinline vfloat4 operator ^(const vfloat4& a, const vfloat4& b) { return _mm_xor_ps(a,b); }
+ __forceinline vfloat4 operator ^(const vfloat4& a, const vint4& b) { return _mm_xor_ps(a,_mm_castsi128_ps(b)); }
+
+ __forceinline vfloat4 min(const vfloat4& a, const vfloat4& b) { return _mm_min_ps(a,b); }
+ __forceinline vfloat4 min(const vfloat4& a, float b) { return _mm_min_ps(a,vfloat4(b)); }
+ __forceinline vfloat4 min(float a, const vfloat4& b) { return _mm_min_ps(vfloat4(a),b); }
+
+ __forceinline vfloat4 max(const vfloat4& a, const vfloat4& b) { return _mm_max_ps(a,b); }
+ __forceinline vfloat4 max(const vfloat4& a, float b) { return _mm_max_ps(a,vfloat4(b)); }
+ __forceinline vfloat4 max(float a, const vfloat4& b) { return _mm_max_ps(vfloat4(a),b); }
+
+#if defined(__SSE4_1__)
+ __forceinline vfloat4 mini(const vfloat4& a, const vfloat4& b) {
+ const vint4 ai = _mm_castps_si128(a);
+ const vint4 bi = _mm_castps_si128(b);
+ const vint4 ci = _mm_min_epi32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+
+ __forceinline vfloat4 maxi(const vfloat4& a, const vfloat4& b) {
+ const vint4 ai = _mm_castps_si128(a);
+ const vint4 bi = _mm_castps_si128(b);
+ const vint4 ci = _mm_max_epi32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+
+ __forceinline vfloat4 minui(const vfloat4& a, const vfloat4& b) {
+ const vint4 ai = _mm_castps_si128(a);
+ const vint4 bi = _mm_castps_si128(b);
+ const vint4 ci = _mm_min_epu32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+
+ __forceinline vfloat4 maxui(const vfloat4& a, const vfloat4& b) {
+ const vint4 ai = _mm_castps_si128(a);
+ const vint4 bi = _mm_castps_si128(b);
+ const vint4 ci = _mm_max_epu32(ai,bi);
+ return _mm_castsi128_ps(ci);
+ }
+#else
+ __forceinline vfloat4 mini(const vfloat4& a, const vfloat4& b) {
+ return min(a,b);
+ }
+
+ __forceinline vfloat4 maxi(const vfloat4& a, const vfloat4& b) {
+ return max(a,b);
+ }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ __forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fmadd_ps(a,b,c); }
+ __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fmsub_ps(a,b,c); }
+ __forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmadd_ps(a,b,c); }
+ __forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmsub_ps(a,b,c); }
+#else
+ __forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b+c; }
+ __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b-c; }
+ __forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return -a*b+c;}
+ __forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return -a*b-c; }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat4& operator +=(vfloat4& a, const vfloat4& b) { return a = a + b; }
+ __forceinline vfloat4& operator +=(vfloat4& a, float b) { return a = a + b; }
+
+ __forceinline vfloat4& operator -=(vfloat4& a, const vfloat4& b) { return a = a - b; }
+ __forceinline vfloat4& operator -=(vfloat4& a, float b) { return a = a - b; }
+
+ __forceinline vfloat4& operator *=(vfloat4& a, const vfloat4& b) { return a = a * b; }
+ __forceinline vfloat4& operator *=(vfloat4& a, float b) { return a = a * b; }
+
+ __forceinline vfloat4& operator /=(vfloat4& a, const vfloat4& b) { return a = a / b; }
+ __forceinline vfloat4& operator /=(vfloat4& a, float b) { return a = a / b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf4 operator ==(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_EQ); }
+ __forceinline vboolf4 operator !=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_NE); }
+ __forceinline vboolf4 operator < (const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_LT); }
+ __forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_GE); }
+ __forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_GT); }
+ __forceinline vboolf4 operator <=(const vfloat4& a, const vfloat4& b) { return _mm_cmp_ps_mask(a, b, _MM_CMPINT_LE); }
+#else
+ __forceinline vboolf4 operator ==(const vfloat4& a, const vfloat4& b) { return _mm_cmpeq_ps (a, b); }
+ __forceinline vboolf4 operator !=(const vfloat4& a, const vfloat4& b) { return _mm_cmpneq_ps(a, b); }
+ __forceinline vboolf4 operator < (const vfloat4& a, const vfloat4& b) { return _mm_cmplt_ps (a, b); }
+ __forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmpnlt_ps(a, b); }
+ __forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmpnle_ps(a, b); }
+ __forceinline vboolf4 operator <=(const vfloat4& a, const vfloat4& b) { return _mm_cmple_ps (a, b); }
+#endif
+
+ __forceinline vboolf4 operator ==(const vfloat4& a, float b) { return a == vfloat4(b); }
+ __forceinline vboolf4 operator ==(float a, const vfloat4& b) { return vfloat4(a) == b; }
+
+ __forceinline vboolf4 operator !=(const vfloat4& a, float b) { return a != vfloat4(b); }
+ __forceinline vboolf4 operator !=(float a, const vfloat4& b) { return vfloat4(a) != b; }
+
+ __forceinline vboolf4 operator < (const vfloat4& a, float b) { return a < vfloat4(b); }
+ __forceinline vboolf4 operator < (float a, const vfloat4& b) { return vfloat4(a) < b; }
+
+ __forceinline vboolf4 operator >=(const vfloat4& a, float b) { return a >= vfloat4(b); }
+ __forceinline vboolf4 operator >=(float a, const vfloat4& b) { return vfloat4(a) >= b; }
+
+ __forceinline vboolf4 operator > (const vfloat4& a, float b) { return a > vfloat4(b); }
+ __forceinline vboolf4 operator > (float a, const vfloat4& b) { return vfloat4(a) > b; }
+
+ __forceinline vboolf4 operator <=(const vfloat4& a, float b) { return a <= vfloat4(b); }
+ __forceinline vboolf4 operator <=(float a, const vfloat4& b) { return vfloat4(a) <= b; }
+
+ __forceinline vboolf4 eq(const vfloat4& a, const vfloat4& b) { return a == b; }
+ __forceinline vboolf4 ne(const vfloat4& a, const vfloat4& b) { return a != b; }
+ __forceinline vboolf4 lt(const vfloat4& a, const vfloat4& b) { return a < b; }
+ __forceinline vboolf4 ge(const vfloat4& a, const vfloat4& b) { return a >= b; }
+ __forceinline vboolf4 gt(const vfloat4& a, const vfloat4& b) { return a > b; }
+ __forceinline vboolf4 le(const vfloat4& a, const vfloat4& b) { return a <= b; }
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf4 eq(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); }
+ __forceinline vboolf4 ne(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); }
+ __forceinline vboolf4 lt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); }
+ __forceinline vboolf4 ge(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); }
+ __forceinline vboolf4 gt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); }
+ __forceinline vboolf4 le(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); }
+#else
+ __forceinline vboolf4 eq(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a == b); }
+ __forceinline vboolf4 ne(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a != b); }
+ __forceinline vboolf4 lt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a < b); }
+ __forceinline vboolf4 ge(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a >= b); }
+ __forceinline vboolf4 gt(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a > b); }
+ __forceinline vboolf4 le(const vboolf4& mask, const vfloat4& a, const vfloat4& b) { return mask & (a <= b); }
+#endif
+
+ template<int mask>
+ __forceinline vfloat4 select(const vfloat4& t, const vfloat4& f)
+ {
+#if defined(__SSE4_1__)
+ return _mm_blend_ps(f, t, mask);
+#else
+ return select(vboolf4(mask), t, f);
+#endif
+ }
+
+ __forceinline vfloat4 lerp(const vfloat4& a, const vfloat4& b, const vfloat4& t) {
+ return madd(t,b-a,a);
+ }
+
+ __forceinline bool isvalid(const vfloat4& v) {
+ return all((v > vfloat4(-FLT_LARGE)) & (v < vfloat4(+FLT_LARGE)));
+ }
+
+ __forceinline bool is_finite(const vfloat4& a) {
+ return all((a >= vfloat4(-FLT_MAX)) & (a <= vfloat4(+FLT_MAX)));
+ }
+
+ __forceinline bool is_finite(const vboolf4& valid, const vfloat4& a) {
+ return all(valid, (a >= vfloat4(-FLT_MAX)) & (a <= vfloat4(+FLT_MAX)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Rounding Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__aarch64__)
+ __forceinline vfloat4 floor(const vfloat4& a) { return vrndmq_f32(a.v); }
+ __forceinline vfloat4 ceil (const vfloat4& a) { return vrndpq_f32(a.v); }
+ __forceinline vfloat4 trunc(const vfloat4& a) { return vrndq_f32(a.v); }
+ __forceinline vfloat4 round(const vfloat4& a) { return vrndnq_f32(a.v); }
+#elif defined (__SSE4_1__)
+ __forceinline vfloat4 floor(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
+ __forceinline vfloat4 ceil (const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
+ __forceinline vfloat4 trunc(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_ZERO ); }
+ __forceinline vfloat4 round(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
+#else
+ __forceinline vfloat4 floor(const vfloat4& a) { return vfloat4(floorf(a[0]),floorf(a[1]),floorf(a[2]),floorf(a[3])); }
+ __forceinline vfloat4 ceil (const vfloat4& a) { return vfloat4(ceilf (a[0]),ceilf (a[1]),ceilf (a[2]),ceilf (a[3])); }
+ __forceinline vfloat4 trunc(const vfloat4& a) { return vfloat4(truncf(a[0]),truncf(a[1]),truncf(a[2]),truncf(a[3])); }
+ __forceinline vfloat4 round(const vfloat4& a) { return vfloat4(roundf(a[0]),roundf(a[1]),roundf(a[2]),roundf(a[3])); }
+#endif
+ __forceinline vfloat4 frac(const vfloat4& a) { return a-floor(a); }
+
+ __forceinline vint4 floori(const vfloat4& a) {
+#if defined(__SSE4_1__)
+ return vint4(floor(a));
+#else
+ return vint4(a-vfloat4(0.5f));
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat4 unpacklo(const vfloat4& a, const vfloat4& b) { return _mm_unpacklo_ps(a, b); }
+ __forceinline vfloat4 unpackhi(const vfloat4& a, const vfloat4& b) { return _mm_unpackhi_ps(a, b); }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vfloat4 shuffle(const vfloat4& v) {
+ return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) {
+ return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+#if defined(__SSE3__)
+ template<> __forceinline vfloat4 shuffle<0, 0, 2, 2>(const vfloat4& v) { return _mm_moveldup_ps(v); }
+ template<> __forceinline vfloat4 shuffle<1, 1, 3, 3>(const vfloat4& v) { return _mm_movehdup_ps(v); }
+ template<> __forceinline vfloat4 shuffle<0, 1, 0, 1>(const vfloat4& v) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(v))); }
+#endif
+
+ template<int i>
+ __forceinline vfloat4 shuffle(const vfloat4& v) {
+ return shuffle<i,i,i,i>(v);
+ }
+
+ template<int i> __forceinline float extract (const vfloat4& a) { return _mm_cvtss_f32(shuffle<i>(a)); }
+ template<> __forceinline float extract<0>(const vfloat4& a) { return _mm_cvtss_f32(a); }
+
+#if defined (__SSE4_1__)
+ template<int dst, int src, int clr> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
+ template<int dst, int src> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return insert<dst, src, 0>(a, b); }
+ template<int dst> __forceinline vfloat4 insert(const vfloat4& a, const float b) { return insert<dst, 0>(a, _mm_set_ss(b)); }
+#else
+ template<int dst, int src> __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { vfloat4 c = a; c[dst&3] = b[src&3]; return c; }
+ template<int dst> __forceinline vfloat4 insert(const vfloat4& a, float b) { vfloat4 c = a; c[dst&3] = b; return c; }
+#endif
+
+ __forceinline float toScalar(const vfloat4& v) { return _mm_cvtss_f32(v); }
+
+ __forceinline vfloat4 shift_right_1(const vfloat4& x) {
+ return _mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(x), 4));
+ }
+
+#if defined (__AVX2__)
+ __forceinline vfloat4 permute(const vfloat4 &a, const __m128i &index) {
+ return _mm_permutevar_ps(a,index);
+ }
+
+ __forceinline vfloat4 broadcast1f(const void* a) { return _mm_broadcast_ss((float*)a); }
+
+#endif
+
+#if defined(__AVX512VL__)
+ template<int i>
+ __forceinline vfloat4 align_shift_right(const vfloat4& a, const vfloat4& b) {
+ return _mm_castsi128_ps(_mm_alignr_epi32(_mm_castps_si128(a), _mm_castps_si128(b), i));
+ }
+#endif
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Sorting Network
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat4 sort_ascending(const vfloat4& v)
+ {
+ const vfloat4 a0 = v;
+ const vfloat4 b0 = shuffle<1,0,3,2>(a0);
+ const vfloat4 c0 = min(a0,b0);
+ const vfloat4 d0 = max(a0,b0);
+ const vfloat4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
+ const vfloat4 b1 = shuffle<2,3,0,1>(a1);
+ const vfloat4 c1 = min(a1,b1);
+ const vfloat4 d1 = max(a1,b1);
+ const vfloat4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
+ const vfloat4 b2 = shuffle<0,2,1,3>(a2);
+ const vfloat4 c2 = min(a2,b2);
+ const vfloat4 d2 = max(a2,b2);
+ const vfloat4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
+ return a3;
+ }
+
+ __forceinline vfloat4 sort_descending(const vfloat4& v)
+ {
+ const vfloat4 a0 = v;
+ const vfloat4 b0 = shuffle<1,0,3,2>(a0);
+ const vfloat4 c0 = max(a0,b0);
+ const vfloat4 d0 = min(a0,b0);
+ const vfloat4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
+ const vfloat4 b1 = shuffle<2,3,0,1>(a1);
+ const vfloat4 c1 = max(a1,b1);
+ const vfloat4 d1 = min(a1,b1);
+ const vfloat4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
+ const vfloat4 b2 = shuffle<0,2,1,3>(a2);
+ const vfloat4 c2 = max(a2,b2);
+ const vfloat4 d2 = min(a2,b2);
+ const vfloat4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
+ return a3;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Transpose
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, vfloat4& c0, vfloat4& c1, vfloat4& c2, vfloat4& c3)
+ {
+ vfloat4 l02 = unpacklo(r0,r2);
+ vfloat4 h02 = unpackhi(r0,r2);
+ vfloat4 l13 = unpacklo(r1,r3);
+ vfloat4 h13 = unpackhi(r1,r3);
+ c0 = unpacklo(l02,l13);
+ c1 = unpackhi(l02,l13);
+ c2 = unpacklo(h02,h13);
+ c3 = unpackhi(h02,h13);
+ }
+
+ __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, vfloat4& c0, vfloat4& c1, vfloat4& c2)
+ {
+ vfloat4 l02 = unpacklo(r0,r2);
+ vfloat4 h02 = unpackhi(r0,r2);
+ vfloat4 l13 = unpacklo(r1,r3);
+ vfloat4 h13 = unpackhi(r1,r3);
+ c0 = unpacklo(l02,l13);
+ c1 = unpackhi(l02,l13);
+ c2 = unpacklo(h02,h13);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat4 vreduce_min(const vfloat4& v) { vfloat4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
+ __forceinline vfloat4 vreduce_max(const vfloat4& v) { vfloat4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
+ __forceinline vfloat4 vreduce_add(const vfloat4& v) { vfloat4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
+
+ __forceinline float reduce_min(const vfloat4& v) { return _mm_cvtss_f32(vreduce_min(v)); }
+ __forceinline float reduce_max(const vfloat4& v) { return _mm_cvtss_f32(vreduce_max(v)); }
+ __forceinline float reduce_add(const vfloat4& v) { return _mm_cvtss_f32(vreduce_add(v)); }
+
+ __forceinline size_t select_min(const vboolf4& valid, const vfloat4& v)
+ {
+ const vfloat4 a = select(valid,v,vfloat4(pos_inf));
+ const vbool4 valid_min = valid & (a == vreduce_min(a));
+ return bsf(movemask(any(valid_min) ? valid_min : valid));
+ }
+ __forceinline size_t select_max(const vboolf4& valid, const vfloat4& v)
+ {
+ const vfloat4 a = select(valid,v,vfloat4(neg_inf));
+ const vbool4 valid_max = valid & (a == vreduce_max(a));
+ return bsf(movemask(any(valid_max) ? valid_max : valid));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Euclidian Space Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline float dot(const vfloat4& a, const vfloat4& b) {
+ return reduce_add(a*b);
+ }
+
+ __forceinline vfloat4 cross(const vfloat4& a, const vfloat4& b)
+ {
+ const vfloat4 a0 = a;
+ const vfloat4 b0 = shuffle<1,2,0,3>(b);
+ const vfloat4 a1 = shuffle<1,2,0,3>(a);
+ const vfloat4 b1 = b;
+ return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vfloat4& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
+ }
+
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vfloat8_avx.h b/thirdparty/embree/common/simd/vfloat8_avx.h
new file mode 100644
index 0000000000..13446454e8
--- /dev/null
+++ b/thirdparty/embree/common/simd/vfloat8_avx.h
@@ -0,0 +1,758 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX float type */
+ template<>
+ struct vfloat<8>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboolf8 Bool;
+ typedef vint8 Int;
+ typedef vfloat8 Float;
+
+ enum { size = 8 }; // number of SIMD elements
+ union { __m256 v; float f[8]; int i[8]; }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat() {}
+ __forceinline vfloat(const vfloat8& other) { v = other.v; }
+ __forceinline vfloat8& operator =(const vfloat8& other) { v = other.v; return *this; }
+
+ __forceinline vfloat(__m256 a) : v(a) {}
+ __forceinline operator const __m256&() const { return v; }
+ __forceinline operator __m256&() { return v; }
+
+ __forceinline explicit vfloat(const vfloat4& a) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
+ __forceinline vfloat(const vfloat4& a, const vfloat4& b) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
+
+ __forceinline explicit vfloat(const char* a) : v(_mm256_loadu_ps((const float*)a)) {}
+ __forceinline vfloat(float a) : v(_mm256_set1_ps(a)) {}
+ __forceinline vfloat(float a, float b) : v(_mm256_set_ps(b, a, b, a, b, a, b, a)) {}
+ __forceinline vfloat(float a, float b, float c, float d) : v(_mm256_set_ps(d, c, b, a, d, c, b, a)) {}
+ __forceinline vfloat(float a, float b, float c, float d, float e, float f, float g, float h) : v(_mm256_set_ps(h, g, f, e, d, c, b, a)) {}
+
+ __forceinline explicit vfloat(__m256i a) : v(_mm256_cvtepi32_ps(a)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat(ZeroTy) : v(_mm256_setzero_ps()) {}
+ __forceinline vfloat(OneTy) : v(_mm256_set1_ps(1.0f)) {}
+ __forceinline vfloat(PosInfTy) : v(_mm256_set1_ps(pos_inf)) {}
+ __forceinline vfloat(NegInfTy) : v(_mm256_set1_ps(neg_inf)) {}
+ __forceinline vfloat(StepTy) : v(_mm256_set_ps(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f)) {}
+ __forceinline vfloat(NaNTy) : v(_mm256_set1_ps(nan)) {}
+ __forceinline vfloat(UndefinedTy) : v(_mm256_undefined_ps()) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vfloat8 broadcast(const void* a) {
+ return _mm256_broadcast_ss((float*)a);
+ }
+
+ static __forceinline vfloat8 load(const char* ptr) {
+#if defined(__AVX2__)
+ return _mm256_cvtepi32_ps(_mm256_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr)));
+#else
+ return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
+#endif
+ }
+
+ static __forceinline vfloat8 load(const unsigned char* ptr) {
+#if defined(__AVX2__)
+ return _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
+#else
+ return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
+#endif
+ }
+
+ static __forceinline vfloat8 load(const short* ptr) {
+#if defined(__AVX2__)
+ return _mm256_cvtepi32_ps(_mm256_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr)));
+#else
+ return vfloat8(vfloat4::load(ptr),vfloat4::load(ptr+4));
+#endif
+ }
+
+ static __forceinline vfloat8 load (const void* ptr) { return _mm256_load_ps((float*)ptr); }
+ static __forceinline vfloat8 loadu(const void* ptr) { return _mm256_loadu_ps((float*)ptr); }
+
+ static __forceinline void store (void* ptr, const vfloat8& v) { return _mm256_store_ps((float*)ptr,v); }
+ static __forceinline void storeu(void* ptr, const vfloat8& v) { return _mm256_storeu_ps((float*)ptr,v); }
+
+#if defined(__AVX512VL__)
+
+ static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_ps (_mm256_setzero_ps(),mask,(float*)ptr); }
+ static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_ps(_mm256_setzero_ps(),mask,(float*)ptr); }
+
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_store_ps ((float*)ptr,mask,v); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_storeu_ps((float*)ptr,mask,v); }
+#else
+ static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask); }
+ static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask); }
+
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,v); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,v); }
+#endif
+
+#if defined(__AVX2__)
+ static __forceinline vfloat8 load_nt(void* ptr) {
+ return _mm256_castsi256_ps(_mm256_stream_load_si256((__m256i*)ptr));
+ }
+#endif
+
+ static __forceinline void store_nt(void* ptr, const vfloat8& v) {
+ _mm256_stream_ps((float*)ptr,v);
+ }
+
+ template<int scale = 4>
+ static __forceinline vfloat8 gather(const float* ptr, const vint8& index) {
+#if defined(__AVX2__)
+ return _mm256_i32gather_ps(ptr, index ,scale);
+#else
+ return vfloat8(
+ *(float*)(((char*)ptr)+scale*index[0]),
+ *(float*)(((char*)ptr)+scale*index[1]),
+ *(float*)(((char*)ptr)+scale*index[2]),
+ *(float*)(((char*)ptr)+scale*index[3]),
+ *(float*)(((char*)ptr)+scale*index[4]),
+ *(float*)(((char*)ptr)+scale*index[5]),
+ *(float*)(((char*)ptr)+scale*index[6]),
+ *(float*)(((char*)ptr)+scale*index[7]));
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline vfloat8 gather(const vboolf8& mask, const float* ptr, const vint8& index) {
+ vfloat8 r = zero;
+#if defined(__AVX512VL__)
+ return _mm256_mmask_i32gather_ps(r, mask, index, ptr, scale);
+#elif defined(__AVX2__)
+ return _mm256_mask_i32gather_ps(r, ptr, index, mask, scale);
+#else
+ if (likely(mask[0])) r[0] = *(float*)(((char*)ptr)+scale*index[0]);
+ if (likely(mask[1])) r[1] = *(float*)(((char*)ptr)+scale*index[1]);
+ if (likely(mask[2])) r[2] = *(float*)(((char*)ptr)+scale*index[2]);
+ if (likely(mask[3])) r[3] = *(float*)(((char*)ptr)+scale*index[3]);
+ if (likely(mask[4])) r[4] = *(float*)(((char*)ptr)+scale*index[4]);
+ if (likely(mask[5])) r[5] = *(float*)(((char*)ptr)+scale*index[5]);
+ if (likely(mask[6])) r[6] = *(float*)(((char*)ptr)+scale*index[6]);
+ if (likely(mask[7])) r[7] = *(float*)(((char*)ptr)+scale*index[7]);
+ return r;
+ #endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(void* ptr, const vint8& ofs, const vfloat8& v)
+ {
+#if defined(__AVX512VL__)
+ _mm256_i32scatter_ps((float*)ptr, ofs, v, scale);
+#else
+ *(float*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ *(float*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ *(float*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ *(float*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ *(float*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ *(float*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ *(float*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ *(float*)(((char*)ptr)+scale*ofs[7]) = v[7];
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vfloat8& v)
+ {
+#if defined(__AVX512VL__)
+ _mm256_mask_i32scatter_ps((float*)ptr, mask, ofs, v, scale);
+#else
+ if (likely(mask[0])) *(float*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ if (likely(mask[1])) *(float*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ if (likely(mask[2])) *(float*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ if (likely(mask[3])) *(float*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ if (likely(mask[4])) *(float*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ if (likely(mask[5])) *(float*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ if (likely(mask[6])) *(float*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ if (likely(mask[7])) *(float*)(((char*)ptr)+scale*ofs[7]) = v[7];
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const float& operator [](size_t index) const { assert(index < 8); return f[index]; }
+ __forceinline float& operator [](size_t index) { assert(index < 8); return f[index]; }
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat8 asFloat(const vint8& a) { return _mm256_castsi256_ps(a); }
+ __forceinline vint8 asInt (const vfloat8& a) { return _mm256_castps_si256(a); }
+
+ __forceinline vint8 toInt (const vfloat8& a) { return vint8(a); }
+ __forceinline vfloat8 toFloat(const vint8& a) { return vfloat8(a); }
+
+ __forceinline vfloat8 operator +(const vfloat8& a) { return a; }
+ __forceinline vfloat8 operator -(const vfloat8& a) {
+ const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
+ return _mm256_xor_ps(a, mask);
+ }
+ __forceinline vfloat8 abs(const vfloat8& a) {
+ const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff));
+ return _mm256_and_ps(a, mask);
+ }
+ __forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmp_ps(a, vfloat8(zero), _CMP_NGE_UQ)); }
+ __forceinline vfloat8 signmsk(const vfloat8& a) { return _mm256_and_ps(a,_mm256_castsi256_ps(_mm256_set1_epi32(0x80000000))); }
+
+
+ static __forceinline vfloat8 rcp(const vfloat8& a)
+ {
+#if defined(__AVX512VL__)
+ const vfloat8 r = _mm256_rcp14_ps(a);
+#else
+ const vfloat8 r = _mm256_rcp_ps(a);
+#endif
+
+#if defined(__AVX2__)
+ return _mm256_mul_ps(r, _mm256_fnmadd_ps(r, a, vfloat8(2.0f)));
+#else
+ return _mm256_mul_ps(r, _mm256_sub_ps(vfloat8(2.0f), _mm256_mul_ps(r, a)));
+#endif
+ }
+ __forceinline vfloat8 sqr (const vfloat8& a) { return _mm256_mul_ps(a,a); }
+ __forceinline vfloat8 sqrt(const vfloat8& a) { return _mm256_sqrt_ps(a); }
+
+ static __forceinline vfloat8 rsqrt(const vfloat8& a)
+ {
+#if defined(__AVX512VL__)
+ const vfloat8 r = _mm256_rsqrt14_ps(a);
+#else
+ const vfloat8 r = _mm256_rsqrt_ps(a);
+#endif
+
+#if defined(__AVX2__)
+ return _mm256_fmadd_ps(_mm256_set1_ps(1.5f), r,
+ _mm256_mul_ps(_mm256_mul_ps(_mm256_mul_ps(a, _mm256_set1_ps(-0.5f)), r), _mm256_mul_ps(r, r)));
+#else
+ return _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(1.5f), r),
+ _mm256_mul_ps(_mm256_mul_ps(_mm256_mul_ps(a, _mm256_set1_ps(-0.5f)), r), _mm256_mul_ps(r, r)));
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat8 operator +(const vfloat8& a, const vfloat8& b) { return _mm256_add_ps(a, b); }
+ __forceinline vfloat8 operator +(const vfloat8& a, float b) { return a + vfloat8(b); }
+ __forceinline vfloat8 operator +(float a, const vfloat8& b) { return vfloat8(a) + b; }
+
+ __forceinline vfloat8 operator -(const vfloat8& a, const vfloat8& b) { return _mm256_sub_ps(a, b); }
+ __forceinline vfloat8 operator -(const vfloat8& a, float b) { return a - vfloat8(b); }
+ __forceinline vfloat8 operator -(float a, const vfloat8& b) { return vfloat8(a) - b; }
+
+ __forceinline vfloat8 operator *(const vfloat8& a, const vfloat8& b) { return _mm256_mul_ps(a, b); }
+ __forceinline vfloat8 operator *(const vfloat8& a, float b) { return a * vfloat8(b); }
+ __forceinline vfloat8 operator *(float a, const vfloat8& b) { return vfloat8(a) * b; }
+
+ __forceinline vfloat8 operator /(const vfloat8& a, const vfloat8& b) { return _mm256_div_ps(a, b); }
+ __forceinline vfloat8 operator /(const vfloat8& a, float b) { return a / vfloat8(b); }
+ __forceinline vfloat8 operator /(float a, const vfloat8& b) { return vfloat8(a) / b; }
+
+ __forceinline vfloat8 operator &(const vfloat8& a, const vfloat8& b) { return _mm256_and_ps(a,b); }
+ __forceinline vfloat8 operator |(const vfloat8& a, const vfloat8& b) { return _mm256_or_ps(a,b); }
+ __forceinline vfloat8 operator ^(const vfloat8& a, const vfloat8& b) { return _mm256_xor_ps(a,b); }
+ __forceinline vfloat8 operator ^(const vfloat8& a, const vint8& b) { return _mm256_xor_ps(a,_mm256_castsi256_ps(b)); }
+
+ __forceinline vfloat8 min(const vfloat8& a, const vfloat8& b) { return _mm256_min_ps(a, b); }
+ __forceinline vfloat8 min(const vfloat8& a, float b) { return _mm256_min_ps(a, vfloat8(b)); }
+ __forceinline vfloat8 min(float a, const vfloat8& b) { return _mm256_min_ps(vfloat8(a), b); }
+
+ __forceinline vfloat8 max(const vfloat8& a, const vfloat8& b) { return _mm256_max_ps(a, b); }
+ __forceinline vfloat8 max(const vfloat8& a, float b) { return _mm256_max_ps(a, vfloat8(b)); }
+ __forceinline vfloat8 max(float a, const vfloat8& b) { return _mm256_max_ps(vfloat8(a), b); }
+
+ /* need "static __forceinline for MSVC, otherwise we'll link the wrong version in debug mode */
+#if defined(__AVX2__)
+
+ static __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) {
+ const vint8 ai = _mm256_castps_si256(a);
+ const vint8 bi = _mm256_castps_si256(b);
+ const vint8 ci = _mm256_min_epi32(ai,bi);
+ return _mm256_castsi256_ps(ci);
+ }
+
+ static __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) {
+ const vint8 ai = _mm256_castps_si256(a);
+ const vint8 bi = _mm256_castps_si256(b);
+ const vint8 ci = _mm256_max_epi32(ai,bi);
+ return _mm256_castsi256_ps(ci);
+ }
+
+ static __forceinline vfloat8 minui(const vfloat8& a, const vfloat8& b) {
+ const vint8 ai = _mm256_castps_si256(a);
+ const vint8 bi = _mm256_castps_si256(b);
+ const vint8 ci = _mm256_min_epu32(ai,bi);
+ return _mm256_castsi256_ps(ci);
+ }
+
+ static __forceinline vfloat8 maxui(const vfloat8& a, const vfloat8& b) {
+ const vint8 ai = _mm256_castps_si256(a);
+ const vint8 bi = _mm256_castps_si256(b);
+ const vint8 ci = _mm256_max_epu32(ai,bi);
+ return _mm256_castsi256_ps(ci);
+ }
+
+#else
+
+ static __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) {
+ return asFloat(min(asInt(a),asInt(b)));
+ }
+
+ static __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) {
+ return asFloat(max(asInt(a),asInt(b)));
+ }
+
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Ternary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX2__)
+ static __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmadd_ps(a,b,c); }
+ static __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmsub_ps(a,b,c); }
+ static __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmadd_ps(a,b,c); }
+ static __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmsub_ps(a,b,c); }
+#else
+ static __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b+c; }
+ static __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b-c; }
+ static __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b+c;}
+ static __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b-c; }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat8& operator +=(vfloat8& a, const vfloat8& b) { return a = a + b; }
+ __forceinline vfloat8& operator +=(vfloat8& a, float b) { return a = a + b; }
+
+ __forceinline vfloat8& operator -=(vfloat8& a, const vfloat8& b) { return a = a - b; }
+ __forceinline vfloat8& operator -=(vfloat8& a, float b) { return a = a - b; }
+
+ __forceinline vfloat8& operator *=(vfloat8& a, const vfloat8& b) { return a = a * b; }
+ __forceinline vfloat8& operator *=(vfloat8& a, float b) { return a = a * b; }
+
+ __forceinline vfloat8& operator /=(vfloat8& a, const vfloat8& b) { return a = a / b; }
+ __forceinline vfloat8& operator /=(vfloat8& a, float b) { return a = a / b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_EQ); }
+ static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_NE); }
+ static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LT); }
+ static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GE); }
+ static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GT); }
+ static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LE); }
+
+ static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
+ return _mm256_mask_blend_ps(m, f, t);
+ }
+#else
+ static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); }
+ static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); }
+ static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LT_OS); }
+ static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); }
+ static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); }
+ static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LE_OS); }
+
+ static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) {
+ return _mm256_blendv_ps(f, t, m);
+ }
+#endif
+
+ template<int mask>
+ __forceinline vfloat8 select(const vfloat8& t, const vfloat8& f) {
+ return _mm256_blend_ps(f, t, mask);
+ }
+
+ __forceinline vboolf8 operator ==(const vfloat8& a, const float& b) { return a == vfloat8(b); }
+ __forceinline vboolf8 operator ==(const float& a, const vfloat8& b) { return vfloat8(a) == b; }
+
+ __forceinline vboolf8 operator !=(const vfloat8& a, const float& b) { return a != vfloat8(b); }
+ __forceinline vboolf8 operator !=(const float& a, const vfloat8& b) { return vfloat8(a) != b; }
+
+ __forceinline vboolf8 operator < (const vfloat8& a, const float& b) { return a < vfloat8(b); }
+ __forceinline vboolf8 operator < (const float& a, const vfloat8& b) { return vfloat8(a) < b; }
+
+ __forceinline vboolf8 operator >=(const vfloat8& a, const float& b) { return a >= vfloat8(b); }
+ __forceinline vboolf8 operator >=(const float& a, const vfloat8& b) { return vfloat8(a) >= b; }
+
+ __forceinline vboolf8 operator > (const vfloat8& a, const float& b) { return a > vfloat8(b); }
+ __forceinline vboolf8 operator > (const float& a, const vfloat8& b) { return vfloat8(a) > b; }
+
+ __forceinline vboolf8 operator <=(const vfloat8& a, const float& b) { return a <= vfloat8(b); }
+ __forceinline vboolf8 operator <=(const float& a, const vfloat8& b) { return vfloat8(a) <= b; }
+
+ __forceinline vboolf8 eq(const vfloat8& a, const vfloat8& b) { return a == b; }
+ __forceinline vboolf8 ne(const vfloat8& a, const vfloat8& b) { return a != b; }
+ __forceinline vboolf8 lt(const vfloat8& a, const vfloat8& b) { return a < b; }
+ __forceinline vboolf8 ge(const vfloat8& a, const vfloat8& b) { return a >= b; }
+ __forceinline vboolf8 gt(const vfloat8& a, const vfloat8& b) { return a > b; }
+ __forceinline vboolf8 le(const vfloat8& a, const vfloat8& b) { return a <= b; }
+
+#if defined(__AVX512VL__)
+ static __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); }
+ static __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); }
+ static __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); }
+ static __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); }
+ static __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); }
+ static __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); }
+#else
+ static __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a == b); }
+ static __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a != b); }
+ static __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a < b); }
+ static __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a >= b); }
+ static __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a > b); }
+ static __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a <= b); }
+#endif
+
+ __forceinline vfloat8 lerp(const vfloat8& a, const vfloat8& b, const vfloat8& t) {
+ return madd(t,b-a,a);
+ }
+
+ __forceinline bool isvalid (const vfloat8& v) {
+ return all((v > vfloat8(-FLT_LARGE)) & (v < vfloat8(+FLT_LARGE)));
+ }
+
+ __forceinline bool is_finite (const vfloat8& a) {
+ return all((a >= vfloat8(-FLT_MAX)) & (a <= vfloat8(+FLT_MAX)));
+ }
+
+ __forceinline bool is_finite (const vboolf8& valid, const vfloat8& a) {
+ return all(valid, (a >= vfloat8(-FLT_MAX)) & (a <= vfloat8(+FLT_MAX)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Rounding Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat8 floor(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
+ __forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); }
+ __forceinline vfloat8 trunc(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_ZERO ); }
+ __forceinline vfloat8 round(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
+ __forceinline vfloat8 frac (const vfloat8& a) { return a-floor(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat8 unpacklo(const vfloat8& a, const vfloat8& b) { return _mm256_unpacklo_ps(a, b); }
+ __forceinline vfloat8 unpackhi(const vfloat8& a, const vfloat8& b) { return _mm256_unpackhi_ps(a, b); }
+
+ template<int i>
+ __forceinline vfloat8 shuffle(const vfloat8& v) {
+ return _mm256_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
+ }
+
+ template<int i0, int i1>
+ __forceinline vfloat8 shuffle4(const vfloat8& v) {
+ return _mm256_permute2f128_ps(v, v, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1>
+ __forceinline vfloat8 shuffle4(const vfloat8& a, const vfloat8& b) {
+ return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vfloat8 shuffle(const vfloat8& v) {
+ return _mm256_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vfloat8 shuffle(const vfloat8& a, const vfloat8& b) {
+ return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<> __forceinline vfloat8 shuffle<0, 0, 2, 2>(const vfloat8& v) { return _mm256_moveldup_ps(v); }
+ template<> __forceinline vfloat8 shuffle<1, 1, 3, 3>(const vfloat8& v) { return _mm256_movehdup_ps(v); }
+ template<> __forceinline vfloat8 shuffle<0, 1, 0, 1>(const vfloat8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); }
+
+ __forceinline vfloat8 broadcast(const float* ptr) { return _mm256_broadcast_ss(ptr); }
+ template<size_t i> __forceinline vfloat8 insert4(const vfloat8& a, const vfloat4& b) { return _mm256_insertf128_ps(a, b, i); }
+ template<size_t i> __forceinline vfloat4 extract4 (const vfloat8& a) { return _mm256_extractf128_ps(a, i); }
+ template<> __forceinline vfloat4 extract4<0>(const vfloat8& a) { return _mm256_castps256_ps128(a); }
+
+ __forceinline float toScalar(const vfloat8& v) { return _mm_cvtss_f32(_mm256_castps256_ps128(v)); }
+
+#if defined (__AVX2__)
+ static __forceinline vfloat8 permute(const vfloat8& a, const __m256i& index) {
+ return _mm256_permutevar8x32_ps(a, index);
+ }
+#endif
+
+#if defined(__AVX512VL__)
+ template<int i>
+ static __forceinline vfloat8 align_shift_right(const vfloat8& a, const vfloat8& b) {
+ return _mm256_castsi256_ps(_mm256_alignr_epi32(_mm256_castps_si256(a), _mm256_castps_si256(b), i));
+ }
+#endif
+
+#if defined (__AVX_I__)
+ template<const int mode>
+ static __forceinline vint4 convert_to_hf16(const vfloat8& a) {
+ return _mm256_cvtps_ph(a, mode);
+ }
+
+ static __forceinline vfloat8 convert_from_hf16(const vint4& a) {
+ return _mm256_cvtph_ps(a);
+ }
+#endif
+
+#if defined(__AVX512VL__)
+ static __forceinline vfloat8 shift_right_1(const vfloat8& x) {
+ return align_shift_right<1>(zero,x);
+ }
+#else
+ static __forceinline vfloat8 shift_right_1(const vfloat8& x) {
+ const vfloat8 t0 = shuffle<1,2,3,0>(x);
+ const vfloat8 t1 = shuffle4<1,0>(t0);
+ return _mm256_blend_ps(t0,t1,0x88);
+ }
+#endif
+
+ __forceinline vint8 floori(const vfloat8& a) {
+ return vint8(floor(a));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Transpose
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3)
+ {
+ vfloat8 l02 = unpacklo(r0,r2);
+ vfloat8 h02 = unpackhi(r0,r2);
+ vfloat8 l13 = unpacklo(r1,r3);
+ vfloat8 h13 = unpackhi(r1,r3);
+ c0 = unpacklo(l02,l13);
+ c1 = unpackhi(l02,l13);
+ c2 = unpacklo(h02,h13);
+ c3 = unpackhi(h02,h13);
+ }
+
+ __forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, vfloat8& c0, vfloat8& c1, vfloat8& c2)
+ {
+ vfloat8 l02 = unpacklo(r0,r2);
+ vfloat8 h02 = unpackhi(r0,r2);
+ vfloat8 l13 = unpacklo(r1,r3);
+ vfloat8 h13 = unpackhi(r1,r3);
+ c0 = unpacklo(l02,l13);
+ c1 = unpackhi(l02,l13);
+ c2 = unpacklo(h02,h13);
+ }
+
+ __forceinline void transpose(const vfloat8& r0, const vfloat8& r1, const vfloat8& r2, const vfloat8& r3, const vfloat8& r4, const vfloat8& r5, const vfloat8& r6, const vfloat8& r7,
+ vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3, vfloat8& c4, vfloat8& c5, vfloat8& c6, vfloat8& c7)
+ {
+ vfloat8 h0,h1,h2,h3; transpose(r0,r1,r2,r3,h0,h1,h2,h3);
+ vfloat8 h4,h5,h6,h7; transpose(r4,r5,r6,r7,h4,h5,h6,h7);
+ c0 = shuffle4<0,2>(h0,h4);
+ c1 = shuffle4<0,2>(h1,h5);
+ c2 = shuffle4<0,2>(h2,h6);
+ c3 = shuffle4<0,2>(h3,h7);
+ c4 = shuffle4<1,3>(h0,h4);
+ c5 = shuffle4<1,3>(h1,h5);
+ c6 = shuffle4<1,3>(h2,h6);
+ c7 = shuffle4<1,3>(h3,h7);
+ }
+
+ __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, const vfloat4& r4, const vfloat4& r5, const vfloat4& r6, const vfloat4& r7,
+ vfloat8& c0, vfloat8& c1, vfloat8& c2, vfloat8& c3)
+ {
+ transpose(vfloat8(r0,r4), vfloat8(r1,r5), vfloat8(r2,r6), vfloat8(r3,r7), c0, c1, c2, c3);
+ }
+
+ __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, const vfloat4& r4, const vfloat4& r5, const vfloat4& r6, const vfloat4& r7,
+ vfloat8& c0, vfloat8& c1, vfloat8& c2)
+ {
+ transpose(vfloat8(r0,r4), vfloat8(r1,r5), vfloat8(r2,r6), vfloat8(r3,r7), c0, c1, c2);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat8 vreduce_min2(const vfloat8& v) { return min(v,shuffle<1,0,3,2>(v)); }
+ __forceinline vfloat8 vreduce_min4(const vfloat8& v) { vfloat8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
+ __forceinline vfloat8 vreduce_min (const vfloat8& v) { vfloat8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
+
+ __forceinline vfloat8 vreduce_max2(const vfloat8& v) { return max(v,shuffle<1,0,3,2>(v)); }
+ __forceinline vfloat8 vreduce_max4(const vfloat8& v) { vfloat8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
+ __forceinline vfloat8 vreduce_max (const vfloat8& v) { vfloat8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
+
+ __forceinline vfloat8 vreduce_add2(const vfloat8& v) { return v + shuffle<1,0,3,2>(v); }
+ __forceinline vfloat8 vreduce_add4(const vfloat8& v) { vfloat8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
+ __forceinline vfloat8 vreduce_add (const vfloat8& v) { vfloat8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
+
+ __forceinline float reduce_min(const vfloat8& v) { return toScalar(vreduce_min(v)); }
+ __forceinline float reduce_max(const vfloat8& v) { return toScalar(vreduce_max(v)); }
+ __forceinline float reduce_add(const vfloat8& v) { return toScalar(vreduce_add(v)); }
+
+ __forceinline size_t select_min(const vboolf8& valid, const vfloat8& v)
+ {
+ const vfloat8 a = select(valid,v,vfloat8(pos_inf));
+ const vbool8 valid_min = valid & (a == vreduce_min(a));
+ return bsf(movemask(any(valid_min) ? valid_min : valid));
+ }
+
+ __forceinline size_t select_max(const vboolf8& valid, const vfloat8& v)
+ {
+ const vfloat8 a = select(valid,v,vfloat8(neg_inf));
+ const vbool8 valid_max = valid & (a == vreduce_max(a));
+ return bsf(movemask(any(valid_max) ? valid_max : valid));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Euclidian Space Operators (pairs of Vec3fa's)
+ ////////////////////////////////////////////////////////////////////////////////
+
+ //__forceinline vfloat8 dot(const vfloat8& a, const vfloat8& b) {
+ // return vreduce_add4(a*b);
+ //}
+
+ __forceinline vfloat8 dot(const vfloat8& a, const vfloat8& b) {
+ return _mm256_dp_ps(a,b,0x7F);
+ }
+
+ __forceinline vfloat8 cross(const vfloat8& a, const vfloat8& b)
+ {
+ const vfloat8 a0 = a;
+ const vfloat8 b0 = shuffle<1,2,0,3>(b);
+ const vfloat8 a1 = shuffle<1,2,0,3>(a);
+ const vfloat8 b1 = b;
+ return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
+ }
+
+ //__forceinline float sqr_length (const vfloat<8>& a) { return dot(a,a); }
+ //__forceinline float rcp_length (const vfloat<8>& a) { return rsqrt(dot(a,a)); }
+ //__forceinline float rcp_length2(const vfloat<8>& a) { return rcp(dot(a,a)); }
+ //__forceinline float length (const vfloat<8>& a) { return sqrt(dot(a,a)); }
+ __forceinline vfloat<8> normalize(const vfloat<8>& a) { return a*rsqrt(dot(a,a)); }
+ //__forceinline float distance(const vfloat<8>& a, const vfloat<8>& b) { return length(a-b); }
+ //__forceinline float halfArea(const vfloat<8>& d) { return madd(d.x,(d.y+d.z),d.y*d.z); }
+ //__forceinline float area (const vfloat<8>& d) { return 2.0f*halfArea(d); }
+ //__forceinline vfloat<8> reflect(const vfloat<8>& V, const vfloat<8>& N) { return 2.0f*dot(V,N)*N-V; }
+
+ //__forceinline vfloat<8> normalize_safe(const vfloat<8>& a) {
+ // const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
+ //}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// In Register Sorting
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vfloat8 sort_ascending(const vfloat8& v)
+ {
+ const vfloat8 a0 = v;
+ const vfloat8 b0 = shuffle<1,0,3,2>(a0);
+ const vfloat8 c0 = min(a0,b0);
+ const vfloat8 d0 = max(a0,b0);
+ const vfloat8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
+ const vfloat8 b1 = shuffle<2,3,0,1>(a1);
+ const vfloat8 c1 = min(a1,b1);
+ const vfloat8 d1 = max(a1,b1);
+ const vfloat8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
+ const vfloat8 b2 = shuffle<1,0,3,2>(a2);
+ const vfloat8 c2 = min(a2,b2);
+ const vfloat8 d2 = max(a2,b2);
+ const vfloat8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
+ const vfloat8 b3 = shuffle4<1,0>(a3);
+ const vfloat8 c3 = min(a3,b3);
+ const vfloat8 d3 = max(a3,b3);
+ const vfloat8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
+ const vfloat8 b4 = shuffle<2,3,0,1>(a4);
+ const vfloat8 c4 = min(a4,b4);
+ const vfloat8 d4 = max(a4,b4);
+ const vfloat8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
+ const vfloat8 b5 = shuffle<1,0,3,2>(a5);
+ const vfloat8 c5 = min(a5,b5);
+ const vfloat8 d5 = max(a5,b5);
+ const vfloat8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
+ return a6;
+ }
+
+ __forceinline vfloat8 sort_descending(const vfloat8& v)
+ {
+ const vfloat8 a0 = v;
+ const vfloat8 b0 = shuffle<1,0,3,2>(a0);
+ const vfloat8 c0 = max(a0,b0);
+ const vfloat8 d0 = min(a0,b0);
+ const vfloat8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
+ const vfloat8 b1 = shuffle<2,3,0,1>(a1);
+ const vfloat8 c1 = max(a1,b1);
+ const vfloat8 d1 = min(a1,b1);
+ const vfloat8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
+ const vfloat8 b2 = shuffle<1,0,3,2>(a2);
+ const vfloat8 c2 = max(a2,b2);
+ const vfloat8 d2 = min(a2,b2);
+ const vfloat8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
+ const vfloat8 b3 = shuffle4<1,0>(a3);
+ const vfloat8 c3 = max(a3,b3);
+ const vfloat8 d3 = min(a3,b3);
+ const vfloat8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
+ const vfloat8 b4 = shuffle<2,3,0,1>(a4);
+ const vfloat8 c4 = max(a4,b4);
+ const vfloat8 d4 = min(a4,b4);
+ const vfloat8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
+ const vfloat8 b5 = shuffle<1,0,3,2>(a5);
+ const vfloat8 c5 = max(a5,b5);
+ const vfloat8 d5 = min(a5,b5);
+ const vfloat8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
+ return a6;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vfloat8& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vint16_avx512.h b/thirdparty/embree/common/simd/vint16_avx512.h
new file mode 100644
index 0000000000..3720c3c9d6
--- /dev/null
+++ b/thirdparty/embree/common/simd/vint16_avx512.h
@@ -0,0 +1,472 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 16-wide AVX-512 integer type */
+ template<>
+ struct vint<16>
+ {
+ ALIGNED_STRUCT_(64);
+
+ typedef vboolf16 Bool;
+ typedef vint16 Int;
+ typedef vfloat16 Float;
+
+ enum { size = 16 }; // number of SIMD elements
+ union { // data
+ __m512i v;
+ int i[16];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint() {}
+ __forceinline vint(const vint16& t) { v = t.v; }
+ __forceinline vint16& operator =(const vint16& f) { v = f.v; return *this; }
+
+ __forceinline vint(const __m512i& t) { v = t; }
+ __forceinline operator __m512i() const { return v; }
+ __forceinline operator __m256i() const { return _mm512_castsi512_si256(v); }
+
+ __forceinline vint(int i) {
+ v = _mm512_set1_epi32(i);
+ }
+
+ __forceinline vint(int a, int b, int c, int d) {
+ v = _mm512_set4_epi32(d,c,b,a);
+ }
+
+ __forceinline vint(int a0 , int a1 , int a2 , int a3,
+ int a4 , int a5 , int a6 , int a7,
+ int a8 , int a9 , int a10, int a11,
+ int a12, int a13, int a14, int a15)
+ {
+ v = _mm512_set_epi32(a15,a14,a13,a12,a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0);
+ }
+
+ __forceinline vint(const vint4& i) {
+ v = _mm512_broadcast_i32x4(i);
+ }
+
+ __forceinline vint(const vint4& a, const vint4& b, const vint4& c, const vint4& d) {
+ v = _mm512_castsi128_si512(a);
+ v = _mm512_inserti32x4(v, b, 1);
+ v = _mm512_inserti32x4(v, c, 2);
+ v = _mm512_inserti32x4(v, d, 3);
+ }
+
+ __forceinline vint(const vint8& i) {
+ v = _mm512_castps_si512(_mm512_castpd_ps(_mm512_broadcast_f64x4(_mm256_castsi256_pd(i))));
+ }
+
+ __forceinline vint(const vint8& a, const vint8& b) {
+ v = _mm512_castsi256_si512(a);
+ v = _mm512_inserti64x4(v, b, 1);
+ }
+
+ __forceinline explicit vint(const __m512& f) {
+ v = _mm512_cvtps_epi32(f);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint(ZeroTy) : v(_mm512_setzero_epi32()) {}
+ __forceinline vint(OneTy) : v(_mm512_set1_epi32(1)) {}
+ __forceinline vint(PosInfTy) : v(_mm512_set1_epi32(pos_inf)) {}
+ __forceinline vint(NegInfTy) : v(_mm512_set1_epi32(neg_inf)) {}
+ __forceinline vint(StepTy) : v(_mm512_set_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
+ __forceinline vint(ReverseStepTy) : v(_mm512_setr_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vint16 load (const void* addr) { return _mm512_load_si512((int*)addr); }
+
+ static __forceinline vint16 load(const unsigned char* ptr) { return _mm512_cvtepu8_epi32(_mm_load_si128((__m128i*)ptr)); }
+ static __forceinline vint16 load(const unsigned short* ptr) { return _mm512_cvtepu16_epi32(_mm256_load_si256((__m256i*)ptr)); }
+
+ static __forceinline vint16 loadu(const unsigned char* ptr) { return _mm512_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)); }
+ static __forceinline vint16 loadu(const unsigned short* ptr) { return _mm512_cvtepu16_epi32(_mm256_loadu_si256((__m256i*)ptr)); }
+
+ static __forceinline vint16 loadu(const void* addr) { return _mm512_loadu_si512(addr); }
+
+ static __forceinline vint16 load (const vboolf16& mask, const void* addr) { return _mm512_mask_load_epi32 (_mm512_setzero_epi32(),mask,addr); }
+ static __forceinline vint16 loadu(const vboolf16& mask, const void* addr) { return _mm512_mask_loadu_epi32(_mm512_setzero_epi32(),mask,addr); }
+
+ static __forceinline void store (void* ptr, const vint16& v) { _mm512_store_si512 (ptr,v); }
+ static __forceinline void storeu(void* ptr, const vint16& v) { _mm512_storeu_si512(ptr,v); }
+
+ static __forceinline void store (const vboolf16& mask, void* addr, const vint16& v2) { _mm512_mask_store_epi32(addr,mask,v2); }
+ static __forceinline void storeu(const vboolf16& mask, void* ptr, const vint16& f) { _mm512_mask_storeu_epi32((int*)ptr,mask,f); }
+
+ static __forceinline void store_nt(void* __restrict__ ptr, const vint16& a) { _mm512_stream_si512((__m512i*)ptr,a); }
+
+ static __forceinline vint16 compact(const vboolf16& mask, vint16 &v) {
+ return _mm512_mask_compress_epi32(v,mask,v);
+ }
+
+ static __forceinline vint16 compact(const vboolf16& mask, const vint16 &a, vint16 &b) {
+ return _mm512_mask_compress_epi32(a,mask,b);
+ }
+
+ static __forceinline vint16 expand(const vboolf16& mask, const vint16& a, vint16& b) {
+ return _mm512_mask_expand_epi32(b,mask,a);
+ }
+
+ template<int scale = 4>
+ static __forceinline vint16 gather(const int* ptr, const vint16& index) {
+ return _mm512_i32gather_epi32(index,ptr,scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline vint16 gather(const vboolf16& mask, const int* ptr, const vint16& index) {
+ return _mm512_mask_i32gather_epi32(_mm512_undefined_epi32(),mask,index,ptr,scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline vint16 gather(const vboolf16& mask, vint16& dest, const int* ptr, const vint16& index) {
+ return _mm512_mask_i32gather_epi32(dest,mask,index,ptr,scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(int* ptr, const vint16& index, const vint16& v) {
+ _mm512_i32scatter_epi32((int*)ptr,index,v,scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf16& mask, int* ptr, const vint16& index, const vint16& v) {
+ _mm512_mask_i32scatter_epi32((int*)ptr,mask,index,v,scale);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline int& operator [](size_t index) { assert(index < 16); return i[index]; }
+ __forceinline const int& operator [](size_t index) const { assert(index < 16); return i[index]; }
+
+ __forceinline unsigned int uint (size_t index) const { assert(index < 16); return ((unsigned int*)i)[index]; }
+ __forceinline size_t& uint64_t(size_t index) const { assert(index < 8); return ((size_t*)i)[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16 asBool(const vint16& a) { return _mm512_movepi32_mask(a); }
+
+ __forceinline vint16 operator +(const vint16& a) { return a; }
+ __forceinline vint16 operator -(const vint16& a) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint16 operator +(const vint16& a, const vint16& b) { return _mm512_add_epi32(a, b); }
+ __forceinline vint16 operator +(const vint16& a, int b) { return a + vint16(b); }
+ __forceinline vint16 operator +(int a, const vint16& b) { return vint16(a) + b; }
+
+ __forceinline vint16 operator -(const vint16& a, const vint16& b) { return _mm512_sub_epi32(a, b); }
+ __forceinline vint16 operator -(const vint16& a, int b) { return a - vint16(b); }
+ __forceinline vint16 operator -(int a, const vint16& b) { return vint16(a) - b; }
+
+ __forceinline vint16 operator *(const vint16& a, const vint16& b) { return _mm512_mullo_epi32(a, b); }
+ __forceinline vint16 operator *(const vint16& a, int b) { return a * vint16(b); }
+ __forceinline vint16 operator *(int a, const vint16& b) { return vint16(a) * b; }
+
+ __forceinline vint16 operator &(const vint16& a, const vint16& b) { return _mm512_and_epi32(a, b); }
+ __forceinline vint16 operator &(const vint16& a, int b) { return a & vint16(b); }
+ __forceinline vint16 operator &(int a, const vint16& b) { return vint16(a) & b; }
+
+ __forceinline vint16 operator |(const vint16& a, const vint16& b) { return _mm512_or_epi32(a, b); }
+ __forceinline vint16 operator |(const vint16& a, int b) { return a | vint16(b); }
+ __forceinline vint16 operator |(int a, const vint16& b) { return vint16(a) | b; }
+
+ __forceinline vint16 operator ^(const vint16& a, const vint16& b) { return _mm512_xor_epi32(a, b); }
+ __forceinline vint16 operator ^(const vint16& a, int b) { return a ^ vint16(b); }
+ __forceinline vint16 operator ^(int a, const vint16& b) { return vint16(a) ^ b; }
+
+ __forceinline vint16 operator <<(const vint16& a, int n) { return _mm512_slli_epi32(a, n); }
+ __forceinline vint16 operator >>(const vint16& a, int n) { return _mm512_srai_epi32(a, n); }
+
+ __forceinline vint16 operator <<(const vint16& a, const vint16& n) { return _mm512_sllv_epi32(a, n); }
+ __forceinline vint16 operator >>(const vint16& a, const vint16& n) { return _mm512_srav_epi32(a, n); }
+
+ __forceinline vint16 sll (const vint16& a, int b) { return _mm512_slli_epi32(a, b); }
+ __forceinline vint16 sra (const vint16& a, int b) { return _mm512_srai_epi32(a, b); }
+ __forceinline vint16 srl (const vint16& a, int b) { return _mm512_srli_epi32(a, b); }
+
+ __forceinline vint16 min(const vint16& a, const vint16& b) { return _mm512_min_epi32(a, b); }
+ __forceinline vint16 min(const vint16& a, int b) { return min(a,vint16(b)); }
+ __forceinline vint16 min(int a, const vint16& b) { return min(vint16(a),b); }
+
+ __forceinline vint16 max(const vint16& a, const vint16& b) { return _mm512_max_epi32(a, b); }
+ __forceinline vint16 max(const vint16& a, int b) { return max(a,vint16(b)); }
+ __forceinline vint16 max(int a, const vint16& b) { return max(vint16(a),b); }
+
+ __forceinline vint16 umin(const vint16& a, const vint16& b) { return _mm512_min_epu32(a, b); }
+ __forceinline vint16 umax(const vint16& a, const vint16& b) { return _mm512_max_epu32(a, b); }
+
+ __forceinline vint16 mask_add(const vboolf16& mask, vint16& c, const vint16& a, const vint16& b) { return _mm512_mask_add_epi32(c,mask,a,b); }
+ __forceinline vint16 mask_sub(const vboolf16& mask, vint16& c, const vint16& a, const vint16& b) { return _mm512_mask_sub_epi32(c,mask,a,b); }
+
+ __forceinline vint16 mask_and(const vboolf16& m, vint16& c, const vint16& a, const vint16& b) { return _mm512_mask_and_epi32(c,m,a,b); }
+ __forceinline vint16 mask_or (const vboolf16& m, vint16& c, const vint16& a, const vint16& b) { return _mm512_mask_or_epi32(c,m,a,b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint16& operator +=(vint16& a, const vint16& b) { return a = a + b; }
+ __forceinline vint16& operator +=(vint16& a, int b) { return a = a + b; }
+
+ __forceinline vint16& operator -=(vint16& a, const vint16& b) { return a = a - b; }
+ __forceinline vint16& operator -=(vint16& a, int b) { return a = a - b; }
+
+ __forceinline vint16& operator *=(vint16& a, const vint16& b) { return a = a * b; }
+ __forceinline vint16& operator *=(vint16& a, int b) { return a = a * b; }
+
+ __forceinline vint16& operator &=(vint16& a, const vint16& b) { return a = a & b; }
+ __forceinline vint16& operator &=(vint16& a, int b) { return a = a & b; }
+
+ __forceinline vint16& operator |=(vint16& a, const vint16& b) { return a = a | b; }
+ __forceinline vint16& operator |=(vint16& a, int b) { return a = a | b; }
+
+ __forceinline vint16& operator <<=(vint16& a, int b) { return a = a << b; }
+ __forceinline vint16& operator >>=(vint16& a, int b) { return a = a >> b; }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16 operator ==(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 operator ==(const vint16& a, int b) { return a == vint16(b); }
+ __forceinline vboolf16 operator ==(int a, const vint16& b) { return vint16(a) == b; }
+
+ __forceinline vboolf16 operator !=(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 operator !=(const vint16& a, int b) { return a != vint16(b); }
+ __forceinline vboolf16 operator !=(int a, const vint16& b) { return vint16(a) != b; }
+
+ __forceinline vboolf16 operator < (const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 operator < (const vint16& a, int b) { return a < vint16(b); }
+ __forceinline vboolf16 operator < (int a, const vint16& b) { return vint16(a) < b; }
+
+ __forceinline vboolf16 operator >=(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 operator >=(const vint16& a, int b) { return a >= vint16(b); }
+ __forceinline vboolf16 operator >=(int a, const vint16& b) { return vint16(a) >= b; }
+
+ __forceinline vboolf16 operator > (const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 operator > (const vint16& a, int b) { return a > vint16(b); }
+ __forceinline vboolf16 operator > (int a, const vint16& b) { return vint16(a) > b; }
+
+ __forceinline vboolf16 operator <=(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
+ __forceinline vboolf16 operator <=(const vint16& a, int b) { return a <= vint16(b); }
+ __forceinline vboolf16 operator <=(int a, const vint16& b) { return vint16(a) <= b; }
+
+ __forceinline vboolf16 eq(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 ne(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 lt(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 ge(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 gt(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 le(const vint16& a, const vint16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
+ __forceinline vboolf16 uint_le(const vint16& a, const vint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
+ __forceinline vboolf16 uint_gt(const vint16& a, const vint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
+
+ __forceinline vboolf16 eq(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 ne(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 lt(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 ge(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 gt(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 le(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LE); }
+ __forceinline vboolf16 uint_le(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_LE); }
+ __forceinline vboolf16 uint_gt(const vboolf16 mask, const vint16& a, const vint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_GT); }
+
+
+ __forceinline vint16 select(const vboolf16& m, const vint16& t, const vint16& f) {
+ return _mm512_mask_or_epi32(f,m,t,t);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint16 unpacklo(const vint16& a, const vint16& b) { return _mm512_unpacklo_epi32(a, b); }
+ __forceinline vint16 unpackhi(const vint16& a, const vint16& b) { return _mm512_unpackhi_epi32(a, b); }
+
+ template<int i>
+ __forceinline vint16 shuffle(const vint16& v) {
+ return _mm512_castps_si512(_mm512_permute_ps(_mm512_castsi512_ps(v), _MM_SHUFFLE(i, i, i, i)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint16 shuffle(const vint16& v) {
+ return _mm512_castps_si512(_mm512_permute_ps(_mm512_castsi512_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i>
+ __forceinline vint16 shuffle4(const vint16& v) {
+ return _mm512_castps_si512(_mm512_shuffle_f32x4(_mm512_castsi512_ps(v), _mm512_castsi512_ps(v), _MM_SHUFFLE(i, i, i, i)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint16 shuffle4(const vint16& v) {
+ return _mm512_castps_si512(_mm512_shuffle_f32x4(_mm512_castsi512_ps(v), _mm512_castsi512_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i>
+ __forceinline vint16 align_shift_right(const vint16& a, const vint16& b) {
+ return _mm512_alignr_epi32(a, b, i);
+ };
+
+ __forceinline int toScalar(const vint16& v) {
+ return _mm_cvtsi128_si32(_mm512_castsi512_si128(v));
+ }
+
+ template<int i> __forceinline vint16 insert4(const vint16& a, const vint4& b) { return _mm512_inserti32x4(a, b, i); }
+
+ template<int N, int i>
+ vint<N> extractN(const vint16& v);
+
+ template<> __forceinline vint4 extractN<4,0>(const vint16& v) { return _mm512_castsi512_si128(v); }
+ template<> __forceinline vint4 extractN<4,1>(const vint16& v) { return _mm512_extracti32x4_epi32(v, 1); }
+ template<> __forceinline vint4 extractN<4,2>(const vint16& v) { return _mm512_extracti32x4_epi32(v, 2); }
+ template<> __forceinline vint4 extractN<4,3>(const vint16& v) { return _mm512_extracti32x4_epi32(v, 3); }
+
+ template<> __forceinline vint8 extractN<8,0>(const vint16& v) { return _mm512_castsi512_si256(v); }
+ template<> __forceinline vint8 extractN<8,1>(const vint16& v) { return _mm512_extracti32x8_epi32(v, 1); }
+
+ template<int i> __forceinline vint4 extract4 (const vint16& v) { return _mm512_extracti32x4_epi32(v, i); }
+ template<> __forceinline vint4 extract4<0>(const vint16& v) { return _mm512_castsi512_si128(v); }
+
+ template<int i> __forceinline vint8 extract8 (const vint16& v) { return _mm512_extracti32x8_epi32(v, i); }
+ template<> __forceinline vint8 extract8<0>(const vint16& v) { return _mm512_castsi512_si256(v); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint16 vreduce_min2(vint16 x) { return min(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vint16 vreduce_min4(vint16 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vint16 vreduce_min8(vint16 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0,3,2>(x)); }
+ __forceinline vint16 vreduce_min (vint16 x) { x = vreduce_min8(x); return min(x, shuffle4<2,3,0,1>(x)); }
+
+ __forceinline vint16 vreduce_max2(vint16 x) { return max(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vint16 vreduce_max4(vint16 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vint16 vreduce_max8(vint16 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0,3,2>(x)); }
+ __forceinline vint16 vreduce_max (vint16 x) { x = vreduce_max8(x); return max(x, shuffle4<2,3,0,1>(x)); }
+
+ __forceinline vint16 vreduce_and2(vint16 x) { return x & shuffle<1,0,3,2>(x); }
+ __forceinline vint16 vreduce_and4(vint16 x) { x = vreduce_and2(x); return x & shuffle<2,3,0,1>(x); }
+ __forceinline vint16 vreduce_and8(vint16 x) { x = vreduce_and4(x); return x & shuffle4<1,0,3,2>(x); }
+ __forceinline vint16 vreduce_and (vint16 x) { x = vreduce_and8(x); return x & shuffle4<2,3,0,1>(x); }
+
+ __forceinline vint16 vreduce_or2(vint16 x) { return x | shuffle<1,0,3,2>(x); }
+ __forceinline vint16 vreduce_or4(vint16 x) { x = vreduce_or2(x); return x | shuffle<2,3,0,1>(x); }
+ __forceinline vint16 vreduce_or8(vint16 x) { x = vreduce_or4(x); return x | shuffle4<1,0,3,2>(x); }
+ __forceinline vint16 vreduce_or (vint16 x) { x = vreduce_or8(x); return x | shuffle4<2,3,0,1>(x); }
+
+ __forceinline vint16 vreduce_add2(vint16 x) { return x + shuffle<1,0,3,2>(x); }
+ __forceinline vint16 vreduce_add4(vint16 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
+ __forceinline vint16 vreduce_add8(vint16 x) { x = vreduce_add4(x); return x + shuffle4<1,0,3,2>(x); }
+ __forceinline vint16 vreduce_add (vint16 x) { x = vreduce_add8(x); return x + shuffle4<2,3,0,1>(x); }
+
+ __forceinline int reduce_min(const vint16& v) { return toScalar(vreduce_min(v)); }
+ __forceinline int reduce_max(const vint16& v) { return toScalar(vreduce_max(v)); }
+ __forceinline int reduce_and(const vint16& v) { return toScalar(vreduce_and(v)); }
+ __forceinline int reduce_or (const vint16& v) { return toScalar(vreduce_or (v)); }
+ __forceinline int reduce_add(const vint16& v) { return toScalar(vreduce_add(v)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Memory load and store operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint16 conflict(const vint16& index)
+ {
+ return _mm512_conflict_epi32(index);
+ }
+
+ __forceinline vint16 conflict(const vboolf16& mask, vint16& dest, const vint16& index)
+ {
+ return _mm512_mask_conflict_epi32(dest,mask,index);
+ }
+
+ __forceinline vint16 convert_uint32_t(const __m512& f) {
+ return _mm512_cvtps_epu32(f);
+ }
+
+ __forceinline vint16 permute(vint16 v, vint16 index) {
+ return _mm512_permutexvar_epi32(index,v);
+ }
+
+ __forceinline vint16 reverse(const vint16 &a) {
+ return permute(a,vint16(reverse_step));
+ }
+
+ __forceinline vint16 prefix_sum(const vint16& a)
+ {
+ const vint16 z(zero);
+ vint16 v = a;
+ v = v + align_shift_right<16-1>(v,z);
+ v = v + align_shift_right<16-2>(v,z);
+ v = v + align_shift_right<16-4>(v,z);
+ v = v + align_shift_right<16-8>(v,z);
+ return v;
+ }
+
+ __forceinline vint16 reverse_prefix_sum(const vint16& a)
+ {
+ const vint16 z(zero);
+ vint16 v = a;
+ v = v + align_shift_right<1>(z,v);
+ v = v + align_shift_right<2>(z,v);
+ v = v + align_shift_right<4>(z,v);
+ v = v + align_shift_right<8>(z,v);
+ return v;
+ }
+
+ /* this should use a vbool8 and a vint8_64...*/
+ template<int scale = 1, int hint = _MM_HINT_T0>
+ __forceinline void gather_prefetch64(const void* base_addr, const vbool16& mask, const vint16& offset)
+ {
+#if defined(__AVX512PF__)
+ _mm512_mask_prefetch_i64gather_pd(offset, mask, base_addr, scale, hint);
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vint16& v)
+ {
+ cout << "<" << v[0];
+ for (int i=1; i<16; i++) cout << ", " << v[i];
+ cout << ">";
+ return cout;
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vint4_sse2.h b/thirdparty/embree/common/simd/vint4_sse2.h
new file mode 100644
index 0000000000..9814d5c71c
--- /dev/null
+++ b/thirdparty/embree/common/simd/vint4_sse2.h
@@ -0,0 +1,598 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../math/math.h"
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide SSE integer type */
+ template<>
+ struct vint<4>
+ {
+ ALIGNED_STRUCT_(16);
+
+ typedef vboolf4 Bool;
+ typedef vint4 Int;
+ typedef vfloat4 Float;
+
+ enum { size = 4 }; // number of SIMD elements
+ union { __m128i v; int i[4]; }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint() {}
+ __forceinline vint(const vint4& a) { v = a.v; }
+ __forceinline vint4& operator =(const vint4& a) { v = a.v; return *this; }
+
+ __forceinline vint(__m128i a) : v(a) {}
+ __forceinline operator const __m128i&() const { return v; }
+ __forceinline operator __m128i&() { return v; }
+
+ __forceinline vint(int a) : v(_mm_set1_epi32(a)) {}
+ __forceinline vint(int a, int b, int c, int d) : v(_mm_set_epi32(d, c, b, a)) {}
+
+ __forceinline explicit vint(__m128 a) : v(_mm_cvtps_epi32(a)) {}
+#if defined(__AVX512VL__)
+ __forceinline explicit vint(const vboolf4& a) : v(_mm_movm_epi32(a)) {}
+#else
+ __forceinline explicit vint(const vboolf4& a) : v(_mm_castps_si128((__m128)a)) {}
+#endif
+
+ __forceinline vint(long long a, long long b) : v(_mm_set_epi64x(b,a)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint(ZeroTy) : v(_mm_setzero_si128()) {}
+ __forceinline vint(OneTy) : v(_mm_set_epi32(1, 1, 1, 1)) {}
+ __forceinline vint(PosInfTy) : v(_mm_set_epi32(pos_inf, pos_inf, pos_inf, pos_inf)) {}
+ __forceinline vint(NegInfTy) : v(_mm_set_epi32(neg_inf, neg_inf, neg_inf, neg_inf)) {}
+ __forceinline vint(StepTy) : v(_mm_set_epi32(3, 2, 1, 0)) {}
+ __forceinline vint(ReverseStepTy) : v(_mm_set_epi32(0, 1, 2, 3)) {}
+
+ __forceinline vint(TrueTy) { v = _mm_cmpeq_epi32(v,v); }
+ __forceinline vint(UndefinedTy) : v(_mm_castps_si128(_mm_undefined_ps())) {}
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vint4 load (const void* a) { return _mm_load_si128((__m128i*)a); }
+ static __forceinline vint4 loadu(const void* a) { return _mm_loadu_si128((__m128i*)a); }
+
+ static __forceinline void store (void* ptr, const vint4& v) { _mm_store_si128((__m128i*)ptr,v); }
+ static __forceinline void storeu(void* ptr, const vint4& v) { _mm_storeu_si128((__m128i*)ptr,v); }
+
+#if defined(__AVX512VL__)
+
+ static __forceinline vint4 compact(const vboolf4& mask, vint4 &v) {
+ return _mm_mask_compress_epi32(v, mask, v);
+ }
+ static __forceinline vint4 compact(const vboolf4& mask, vint4 &a, const vint4& b) {
+ return _mm_mask_compress_epi32(a, mask, b);
+ }
+
+ static __forceinline vint4 load (const vboolf4& mask, const void* ptr) { return _mm_mask_load_epi32 (_mm_setzero_si128(),mask,ptr); }
+ static __forceinline vint4 loadu(const vboolf4& mask, const void* ptr) { return _mm_mask_loadu_epi32(_mm_setzero_si128(),mask,ptr); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vint4& v) { _mm_mask_store_epi32 (ptr,mask,v); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vint4& v) { _mm_mask_storeu_epi32(ptr,mask,v); }
+#elif defined(__AVX__)
+ static __forceinline vint4 load (const vbool4& mask, const void* a) { return _mm_castps_si128(_mm_maskload_ps((float*)a,mask)); }
+ static __forceinline vint4 loadu(const vbool4& mask, const void* a) { return _mm_castps_si128(_mm_maskload_ps((float*)a,mask)); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vint4& i) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i)); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vint4& i) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i)); }
+#else
+ static __forceinline vint4 load (const vbool4& mask, const void* a) { return _mm_and_si128(_mm_load_si128 ((__m128i*)a),mask); }
+ static __forceinline vint4 loadu(const vbool4& mask, const void* a) { return _mm_and_si128(_mm_loadu_si128((__m128i*)a),mask); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vint4& i) { store (ptr,select(mask,i,load (ptr))); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vint4& i) { storeu(ptr,select(mask,i,loadu(ptr))); }
+#endif
+
+
+#if defined(__SSE4_1__)
+ static __forceinline vint4 load(const unsigned char* ptr) {
+ return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
+ }
+
+ static __forceinline vint4 loadu(const unsigned char* ptr) {
+ return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
+ }
+#else
+
+ static __forceinline vint4 load(const unsigned char* ptr) {
+ return vint4(ptr[0],ptr[1],ptr[2],ptr[3]);
+ }
+
+ static __forceinline vint4 loadu(const unsigned char* ptr) {
+ return vint4(ptr[0],ptr[1],ptr[2],ptr[3]);
+ }
+
+#endif
+
+ static __forceinline vint4 load(const unsigned short* ptr) {
+#if defined (__SSE4_1__)
+ return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr));
+#else
+ return vint4(ptr[0],ptr[1],ptr[2],ptr[3]);
+#endif
+ }
+
+ static __forceinline void store(unsigned char* ptr, const vint4& v) {
+#if defined(__SSE4_1__)
+ __m128i x = v;
+ x = _mm_packus_epi32(x, x);
+ x = _mm_packus_epi16(x, x);
+ *(int*)ptr = _mm_cvtsi128_si32(x);
+#else
+ for (size_t i=0;i<4;i++)
+ ptr[i] = (unsigned char)v[i];
+#endif
+ }
+
+ static __forceinline void store(unsigned short* ptr, const vint4& v) {
+ for (size_t i=0;i<4;i++)
+ ptr[i] = (unsigned short)v[i];
+ }
+
+ static __forceinline vint4 load_nt(void* ptr) {
+#if defined(__SSE4_1__)
+ return _mm_stream_load_si128((__m128i*)ptr);
+#else
+ return _mm_load_si128((__m128i*)ptr);
+#endif
+ }
+
+ static __forceinline void store_nt(void* ptr, const vint4& v) {
+#if defined(__SSE4_1__)
+ _mm_stream_ps((float*)ptr, _mm_castsi128_ps(v));
+#else
+ _mm_store_si128((__m128i*)ptr,v);
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline vint4 gather(const int* ptr, const vint4& index) {
+#if defined(__AVX2__)
+ return _mm_i32gather_epi32(ptr, index, scale);
+#else
+ return vint4(
+ *(int*)(((char*)ptr)+scale*index[0]),
+ *(int*)(((char*)ptr)+scale*index[1]),
+ *(int*)(((char*)ptr)+scale*index[2]),
+ *(int*)(((char*)ptr)+scale*index[3]));
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline vint4 gather(const vboolf4& mask, const int* ptr, const vint4& index) {
+ vint4 r = zero;
+#if defined(__AVX512VL__)
+ return _mm_mmask_i32gather_epi32(r, mask, index, ptr, scale);
+#elif defined(__AVX2__)
+ return _mm_mask_i32gather_epi32(r, ptr, index, mask, scale);
+#else
+ if (likely(mask[0])) r[0] = *(int*)(((char*)ptr)+scale*index[0]);
+ if (likely(mask[1])) r[1] = *(int*)(((char*)ptr)+scale*index[1]);
+ if (likely(mask[2])) r[2] = *(int*)(((char*)ptr)+scale*index[2]);
+ if (likely(mask[3])) r[3] = *(int*)(((char*)ptr)+scale*index[3]);
+ return r;
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(void* ptr, const vint4& index, const vint4& v)
+ {
+#if defined(__AVX512VL__)
+ _mm_i32scatter_epi32((int*)ptr, index, v, scale);
+#else
+ *(int*)(((char*)ptr)+scale*index[0]) = v[0];
+ *(int*)(((char*)ptr)+scale*index[1]) = v[1];
+ *(int*)(((char*)ptr)+scale*index[2]) = v[2];
+ *(int*)(((char*)ptr)+scale*index[3]) = v[3];
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf4& mask, void* ptr, const vint4& index, const vint4& v)
+ {
+#if defined(__AVX512VL__)
+ _mm_mask_i32scatter_epi32((int*)ptr, mask, index, v, scale);
+#else
+ if (likely(mask[0])) *(int*)(((char*)ptr)+scale*index[0]) = v[0];
+ if (likely(mask[1])) *(int*)(((char*)ptr)+scale*index[1]) = v[1];
+ if (likely(mask[2])) *(int*)(((char*)ptr)+scale*index[2]) = v[2];
+ if (likely(mask[3])) *(int*)(((char*)ptr)+scale*index[3]) = v[3];
+#endif
+ }
+
+#if defined(__x86_64__)
+ static __forceinline vint4 broadcast64(long long a) { return _mm_set1_epi64x(a); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const int& operator [](size_t index) const { assert(index < 4); return i[index]; }
+ __forceinline int& operator [](size_t index) { assert(index < 4); return i[index]; }
+
+ friend __forceinline vint4 select(const vboolf4& m, const vint4& t, const vint4& f) {
+#if defined(__AVX512VL__)
+ return _mm_mask_blend_epi32(m, (__m128i)f, (__m128i)t);
+#elif defined(__SSE4_1__)
+ return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
+#else
+ return _mm_or_si128(_mm_and_si128(m, t), _mm_andnot_si128(m, f));
+#endif
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf4 asBool(const vint4& a) { return _mm_movepi32_mask(a); }
+#else
+ __forceinline vboolf4 asBool(const vint4& a) { return _mm_castsi128_ps(a); }
+#endif
+
+ __forceinline vint4 operator +(const vint4& a) { return a; }
+ __forceinline vint4 operator -(const vint4& a) { return _mm_sub_epi32(_mm_setzero_si128(), a); }
+#if defined(__SSSE3__)
+ __forceinline vint4 abs(const vint4& a) { return _mm_abs_epi32(a); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint4 operator +(const vint4& a, const vint4& b) { return _mm_add_epi32(a, b); }
+ __forceinline vint4 operator +(const vint4& a, int b) { return a + vint4(b); }
+ __forceinline vint4 operator +(int a, const vint4& b) { return vint4(a) + b; }
+
+ __forceinline vint4 operator -(const vint4& a, const vint4& b) { return _mm_sub_epi32(a, b); }
+ __forceinline vint4 operator -(const vint4& a, int b) { return a - vint4(b); }
+ __forceinline vint4 operator -(int a, const vint4& b) { return vint4(a) - b; }
+
+#if defined(__SSE4_1__)
+ __forceinline vint4 operator *(const vint4& a, const vint4& b) { return _mm_mullo_epi32(a, b); }
+#else
+ __forceinline vint4 operator *(const vint4& a, const vint4& b) { return vint4(a[0]*b[0],a[1]*b[1],a[2]*b[2],a[3]*b[3]); }
+#endif
+ __forceinline vint4 operator *(const vint4& a, int b) { return a * vint4(b); }
+ __forceinline vint4 operator *(int a, const vint4& b) { return vint4(a) * b; }
+
+ __forceinline vint4 operator &(const vint4& a, const vint4& b) { return _mm_and_si128(a, b); }
+ __forceinline vint4 operator &(const vint4& a, int b) { return a & vint4(b); }
+ __forceinline vint4 operator &(int a, const vint4& b) { return vint4(a) & b; }
+
+ __forceinline vint4 operator |(const vint4& a, const vint4& b) { return _mm_or_si128(a, b); }
+ __forceinline vint4 operator |(const vint4& a, int b) { return a | vint4(b); }
+ __forceinline vint4 operator |(int a, const vint4& b) { return vint4(a) | b; }
+
+ __forceinline vint4 operator ^(const vint4& a, const vint4& b) { return _mm_xor_si128(a, b); }
+ __forceinline vint4 operator ^(const vint4& a, int b) { return a ^ vint4(b); }
+ __forceinline vint4 operator ^(int a, const vint4& b) { return vint4(a) ^ b; }
+
+ __forceinline vint4 operator <<(const vint4& a, int n) { return _mm_slli_epi32(a, n); }
+ __forceinline vint4 operator >>(const vint4& a, int n) { return _mm_srai_epi32(a, n); }
+
+ __forceinline vint4 sll (const vint4& a, int b) { return _mm_slli_epi32(a, b); }
+ __forceinline vint4 sra (const vint4& a, int b) { return _mm_srai_epi32(a, b); }
+ __forceinline vint4 srl (const vint4& a, int b) { return _mm_srli_epi32(a, b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint4& operator +=(vint4& a, const vint4& b) { return a = a + b; }
+ __forceinline vint4& operator +=(vint4& a, int b) { return a = a + b; }
+
+ __forceinline vint4& operator -=(vint4& a, const vint4& b) { return a = a - b; }
+ __forceinline vint4& operator -=(vint4& a, int b) { return a = a - b; }
+
+#if defined(__SSE4_1__)
+ __forceinline vint4& operator *=(vint4& a, const vint4& b) { return a = a * b; }
+ __forceinline vint4& operator *=(vint4& a, int b) { return a = a * b; }
+#endif
+
+ __forceinline vint4& operator &=(vint4& a, const vint4& b) { return a = a & b; }
+ __forceinline vint4& operator &=(vint4& a, int b) { return a = a & b; }
+
+ __forceinline vint4& operator |=(vint4& a, const vint4& b) { return a = a | b; }
+ __forceinline vint4& operator |=(vint4& a, int b) { return a = a | b; }
+
+ __forceinline vint4& operator <<=(vint4& a, int b) { return a = a << b; }
+ __forceinline vint4& operator >>=(vint4& a, int b) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf4 operator ==(const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf4 operator !=(const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf4 operator < (const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf4 operator >=(const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf4 operator > (const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf4 operator <=(const vint4& a, const vint4& b) { return _mm_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
+#else
+ __forceinline vboolf4 operator ==(const vint4& a, const vint4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
+ __forceinline vboolf4 operator !=(const vint4& a, const vint4& b) { return !(a == b); }
+ __forceinline vboolf4 operator < (const vint4& a, const vint4& b) { return _mm_castsi128_ps(_mm_cmplt_epi32(a, b)); }
+ __forceinline vboolf4 operator >=(const vint4& a, const vint4& b) { return !(a < b); }
+ __forceinline vboolf4 operator > (const vint4& a, const vint4& b) { return _mm_castsi128_ps(_mm_cmpgt_epi32(a, b)); }
+ __forceinline vboolf4 operator <=(const vint4& a, const vint4& b) { return !(a > b); }
+#endif
+
+ __forceinline vboolf4 operator ==(const vint4& a, int b) { return a == vint4(b); }
+ __forceinline vboolf4 operator ==(int a, const vint4& b) { return vint4(a) == b; }
+
+ __forceinline vboolf4 operator !=(const vint4& a, int b) { return a != vint4(b); }
+ __forceinline vboolf4 operator !=(int a, const vint4& b) { return vint4(a) != b; }
+
+ __forceinline vboolf4 operator < (const vint4& a, int b) { return a < vint4(b); }
+ __forceinline vboolf4 operator < (int a, const vint4& b) { return vint4(a) < b; }
+
+ __forceinline vboolf4 operator >=(const vint4& a, int b) { return a >= vint4(b); }
+ __forceinline vboolf4 operator >=(int a, const vint4& b) { return vint4(a) >= b; }
+
+ __forceinline vboolf4 operator > (const vint4& a, int b) { return a > vint4(b); }
+ __forceinline vboolf4 operator > (int a, const vint4& b) { return vint4(a) > b; }
+
+ __forceinline vboolf4 operator <=(const vint4& a, int b) { return a <= vint4(b); }
+ __forceinline vboolf4 operator <=(int a, const vint4& b) { return vint4(a) <= b; }
+
+ __forceinline vboolf4 eq(const vint4& a, const vint4& b) { return a == b; }
+ __forceinline vboolf4 ne(const vint4& a, const vint4& b) { return a != b; }
+ __forceinline vboolf4 lt(const vint4& a, const vint4& b) { return a < b; }
+ __forceinline vboolf4 ge(const vint4& a, const vint4& b) { return a >= b; }
+ __forceinline vboolf4 gt(const vint4& a, const vint4& b) { return a > b; }
+ __forceinline vboolf4 le(const vint4& a, const vint4& b) { return a <= b; }
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf4 eq(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_EQ); }
+ __forceinline vboolf4 ne(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_NE); }
+ __forceinline vboolf4 lt(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); }
+ __forceinline vboolf4 ge(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GE); }
+ __forceinline vboolf4 gt(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GT); }
+ __forceinline vboolf4 le(const vboolf4& mask, const vint4& a, const vint4& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LE); }
+#else
+ __forceinline vboolf4 eq(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a == b); }
+ __forceinline vboolf4 ne(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a != b); }
+ __forceinline vboolf4 lt(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a < b); }
+ __forceinline vboolf4 ge(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a >= b); }
+ __forceinline vboolf4 gt(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a > b); }
+ __forceinline vboolf4 le(const vboolf4& mask, const vint4& a, const vint4& b) { return mask & (a <= b); }
+#endif
+
+ template<int mask>
+ __forceinline vint4 select(const vint4& t, const vint4& f) {
+#if defined(__SSE4_1__)
+ return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), mask));
+#else
+ return select(vboolf4(mask), t, f);
+#endif
+ }
+
+#if defined(__SSE4_1__)
+ __forceinline vint4 min(const vint4& a, const vint4& b) { return _mm_min_epi32(a, b); }
+ __forceinline vint4 max(const vint4& a, const vint4& b) { return _mm_max_epi32(a, b); }
+
+ __forceinline vint4 umin(const vint4& a, const vint4& b) { return _mm_min_epu32(a, b); }
+ __forceinline vint4 umax(const vint4& a, const vint4& b) { return _mm_max_epu32(a, b); }
+
+#else
+ __forceinline vint4 min(const vint4& a, const vint4& b) { return select(a < b,a,b); }
+ __forceinline vint4 max(const vint4& a, const vint4& b) { return select(a < b,b,a); }
+#endif
+
+ __forceinline vint4 min(const vint4& a, int b) { return min(a,vint4(b)); }
+ __forceinline vint4 min(int a, const vint4& b) { return min(vint4(a),b); }
+ __forceinline vint4 max(const vint4& a, int b) { return max(a,vint4(b)); }
+ __forceinline vint4 max(int a, const vint4& b) { return max(vint4(a),b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint4 unpacklo(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
+ __forceinline vint4 unpackhi(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint4 shuffle(const vint4& v) {
+ return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint4 shuffle(const vint4& a, const vint4& b) {
+ return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+#if defined(__SSE3__)
+ template<> __forceinline vint4 shuffle<0, 0, 2, 2>(const vint4& v) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(v))); }
+ template<> __forceinline vint4 shuffle<1, 1, 3, 3>(const vint4& v) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(v))); }
+ template<> __forceinline vint4 shuffle<0, 1, 0, 1>(const vint4& v) { return _mm_castpd_si128(_mm_movedup_pd (_mm_castsi128_pd(v))); }
+#endif
+
+ template<int i>
+ __forceinline vint4 shuffle(const vint4& v) {
+ return shuffle<i,i,i,i>(v);
+ }
+
+#if defined(__SSE4_1__)
+ template<int src> __forceinline int extract(const vint4& b) { return _mm_extract_epi32(b, src); }
+ template<int dst> __forceinline vint4 insert(const vint4& a, const int b) { return _mm_insert_epi32(a, b, dst); }
+#else
+ template<int src> __forceinline int extract(const vint4& b) { return b[src&3]; }
+ template<int dst> __forceinline vint4 insert(const vint4& a, int b) { vint4 c = a; c[dst&3] = b; return c; }
+#endif
+
+
+ template<> __forceinline int extract<0>(const vint4& b) { return _mm_cvtsi128_si32(b); }
+
+ __forceinline int toScalar(const vint4& v) { return _mm_cvtsi128_si32(v); }
+
+ __forceinline size_t toSizeT(const vint4& v) {
+#if defined(__WIN32__) && !defined(__X86_64__) // win32 workaround
+ return toScalar(v);
+#else
+ return _mm_cvtsi128_si64(v);
+#endif
+ }
+
+#if defined(__AVX512VL__)
+
+ __forceinline vint4 permute(const vint4 &a, const vint4 &index) {
+ return _mm_castps_si128(_mm_permutevar_ps(_mm_castsi128_ps(a),index));
+ }
+
+ template<int i>
+ __forceinline vint4 align_shift_right(const vint4& a, const vint4& b) {
+ return _mm_alignr_epi32(a, b, i);
+ }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__SSE4_1__)
+ __forceinline vint4 vreduce_min(const vint4& v) { vint4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
+ __forceinline vint4 vreduce_max(const vint4& v) { vint4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
+ __forceinline vint4 vreduce_add(const vint4& v) { vint4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
+
+ __forceinline int reduce_min(const vint4& v) { return toScalar(vreduce_min(v)); }
+ __forceinline int reduce_max(const vint4& v) { return toScalar(vreduce_max(v)); }
+ __forceinline int reduce_add(const vint4& v) { return toScalar(vreduce_add(v)); }
+
+ __forceinline size_t select_min(const vint4& v) { return bsf(movemask(v == vreduce_min(v))); }
+ __forceinline size_t select_max(const vint4& v) { return bsf(movemask(v == vreduce_max(v))); }
+
+ __forceinline size_t select_min(const vboolf4& valid, const vint4& v) { const vint4 a = select(valid,v,vint4(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
+ __forceinline size_t select_max(const vboolf4& valid, const vint4& v) { const vint4 a = select(valid,v,vint4(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
+
+#else
+
+ __forceinline int reduce_min(const vint4& v) { return min(v[0],v[1],v[2],v[3]); }
+ __forceinline int reduce_max(const vint4& v) { return max(v[0],v[1],v[2],v[3]); }
+ __forceinline int reduce_add(const vint4& v) { return v[0]+v[1]+v[2]+v[3]; }
+
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Sorting networks
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__SSE4_1__)
+
+ __forceinline vint4 usort_ascending(const vint4& v)
+ {
+ const vint4 a0 = v;
+ const vint4 b0 = shuffle<1,0,3,2>(a0);
+ const vint4 c0 = umin(a0,b0);
+ const vint4 d0 = umax(a0,b0);
+ const vint4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
+ const vint4 b1 = shuffle<2,3,0,1>(a1);
+ const vint4 c1 = umin(a1,b1);
+ const vint4 d1 = umax(a1,b1);
+ const vint4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
+ const vint4 b2 = shuffle<0,2,1,3>(a2);
+ const vint4 c2 = umin(a2,b2);
+ const vint4 d2 = umax(a2,b2);
+ const vint4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
+ return a3;
+ }
+
+ __forceinline vint4 usort_descending(const vint4& v)
+ {
+ const vint4 a0 = v;
+ const vint4 b0 = shuffle<1,0,3,2>(a0);
+ const vint4 c0 = umax(a0,b0);
+ const vint4 d0 = umin(a0,b0);
+ const vint4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
+ const vint4 b1 = shuffle<2,3,0,1>(a1);
+ const vint4 c1 = umax(a1,b1);
+ const vint4 d1 = umin(a1,b1);
+ const vint4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
+ const vint4 b2 = shuffle<0,2,1,3>(a2);
+ const vint4 c2 = umax(a2,b2);
+ const vint4 d2 = umin(a2,b2);
+ const vint4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
+ return a3;
+ }
+
+#else
+
+ __forceinline vint4 usort_ascending(const vint4& v)
+ {
+ const vint4 a0 = v-vint4(0x80000000);
+ const vint4 b0 = shuffle<1,0,3,2>(a0);
+ const vint4 c0 = min(a0,b0);
+ const vint4 d0 = max(a0,b0);
+ const vint4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
+ const vint4 b1 = shuffle<2,3,0,1>(a1);
+ const vint4 c1 = min(a1,b1);
+ const vint4 d1 = max(a1,b1);
+ const vint4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
+ const vint4 b2 = shuffle<0,2,1,3>(a2);
+ const vint4 c2 = min(a2,b2);
+ const vint4 d2 = max(a2,b2);
+ const vint4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
+ return a3+vint4(0x80000000);
+ }
+
+ __forceinline vint4 usort_descending(const vint4& v)
+ {
+ const vint4 a0 = v-vint4(0x80000000);
+ const vint4 b0 = shuffle<1,0,3,2>(a0);
+ const vint4 c0 = max(a0,b0);
+ const vint4 d0 = min(a0,b0);
+ const vint4 a1 = select<0x5 /* 0b0101 */>(c0,d0);
+ const vint4 b1 = shuffle<2,3,0,1>(a1);
+ const vint4 c1 = max(a1,b1);
+ const vint4 d1 = min(a1,b1);
+ const vint4 a2 = select<0x3 /* 0b0011 */>(c1,d1);
+ const vint4 b2 = shuffle<0,2,1,3>(a2);
+ const vint4 c2 = max(a2,b2);
+ const vint4 d2 = min(a2,b2);
+ const vint4 a3 = select<0x2 /* 0b0010 */>(c2,d2);
+ return a3+vint4(0x80000000);
+ }
+
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vint4& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vint8_avx.h b/thirdparty/embree/common/simd/vint8_avx.h
new file mode 100644
index 0000000000..f43e9a8c22
--- /dev/null
+++ b/thirdparty/embree/common/simd/vint8_avx.h
@@ -0,0 +1,470 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX integer type */
+ template<>
+ struct vint<8>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboolf8 Bool;
+ typedef vint8 Int;
+ typedef vfloat8 Float;
+
+ enum { size = 8 }; // number of SIMD elements
+ union { // data
+ __m256i v;
+ struct { __m128i vl,vh; };
+ int i[8];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint() {}
+ __forceinline vint(const vint8& a) { v = a.v; }
+ __forceinline vint8& operator =(const vint8& a) { v = a.v; return *this; }
+
+ __forceinline vint(__m256i a) : v(a) {}
+ __forceinline operator const __m256i&() const { return v; }
+ __forceinline operator __m256i&() { return v; }
+
+ __forceinline explicit vint(const vint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
+ __forceinline vint(const vint4& a, const vint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
+ __forceinline vint(const __m128i& a, const __m128i& b) : vl(a), vh(b) {}
+
+ __forceinline explicit vint(const int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
+ __forceinline vint(int a) : v(_mm256_set1_epi32(a)) {}
+ __forceinline vint(int a, int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
+ __forceinline vint(int a, int b, int c, int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
+ __forceinline vint(int a, int b, int c, int d, int e, int f, int g, int vh) : v(_mm256_set_epi32(vh, g, f, e, d, c, b, a)) {}
+
+ __forceinline explicit vint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint(ZeroTy) : v(_mm256_setzero_si256()) {}
+ __forceinline vint(OneTy) : v(_mm256_set_epi32(1,1,1,1,1,1,1,1)) {}
+ __forceinline vint(PosInfTy) : v(_mm256_set_epi32(pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf)) {}
+ __forceinline vint(NegInfTy) : v(_mm256_set_epi32(neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf)) {}
+ __forceinline vint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
+ __forceinline vint(ReverseStepTy) : v(_mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7)) {}
+ __forceinline vint(UndefinedTy) : v(_mm256_undefined_si256()) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vint8 load (const void* a) { return _mm256_castps_si256(_mm256_load_ps((float*)a)); }
+ static __forceinline vint8 loadu(const void* a) { return _mm256_castps_si256(_mm256_loadu_ps((float*)a)); }
+
+ static __forceinline vint8 load (const vboolf8& mask, const void* a) { return _mm256_castps_si256(_mm256_maskload_ps((float*)a,mask)); }
+ static __forceinline vint8 loadu(const vboolf8& mask, const void* a) { return _mm256_castps_si256(_mm256_maskload_ps((float*)a,mask)); }
+
+ static __forceinline void store (void* ptr, const vint8& f) { _mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f)); }
+ static __forceinline void storeu(void* ptr, const vint8& f) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f)); }
+
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
+
+ static __forceinline void store_nt(void* ptr, const vint8& v) {
+ _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
+ }
+
+ static __forceinline vint8 load(const unsigned char* ptr) {
+ vint4 il = vint4::load(ptr+0);
+ vint4 ih = vint4::load(ptr+4);
+ return vint8(il,ih);
+ }
+
+ static __forceinline vint8 loadu(const unsigned char* ptr) {
+ vint4 il = vint4::loadu(ptr+0);
+ vint4 ih = vint4::loadu(ptr+4);
+ return vint8(il,ih);
+ }
+
+ static __forceinline vint8 load(const unsigned short* ptr) {
+ vint4 il = vint4::load(ptr+0);
+ vint4 ih = vint4::load(ptr+4);
+ return vint8(il,ih);
+ }
+
+ static __forceinline vint8 loadu(const unsigned short* ptr) {
+ vint4 il = vint4::loadu(ptr+0);
+ vint4 ih = vint4::loadu(ptr+4);
+ return vint8(il,ih);
+ }
+
+ static __forceinline void store(unsigned char* ptr, const vint8& i) {
+ vint4 il(i.vl);
+ vint4 ih(i.vh);
+ vint4::store(ptr + 0,il);
+ vint4::store(ptr + 4,ih);
+ }
+
+ static __forceinline void store(unsigned short* ptr, const vint8& v) {
+ for (size_t i=0;i<8;i++)
+ ptr[i] = (unsigned short)v[i];
+ }
+
+ template<int scale = 4>
+ static __forceinline vint8 gather(const int* ptr, const vint8& index) {
+ return vint8(
+ *(int*)(((char*)ptr)+scale*index[0]),
+ *(int*)(((char*)ptr)+scale*index[1]),
+ *(int*)(((char*)ptr)+scale*index[2]),
+ *(int*)(((char*)ptr)+scale*index[3]),
+ *(int*)(((char*)ptr)+scale*index[4]),
+ *(int*)(((char*)ptr)+scale*index[5]),
+ *(int*)(((char*)ptr)+scale*index[6]),
+ *(int*)(((char*)ptr)+scale*index[7]));
+ }
+
+ template<int scale = 4>
+ static __forceinline vint8 gather(const vboolf8& mask, const int* ptr, const vint8& index) {
+ vint8 r = zero;
+ if (likely(mask[0])) r[0] = *(int*)(((char*)ptr)+scale*index[0]);
+ if (likely(mask[1])) r[1] = *(int*)(((char*)ptr)+scale*index[1]);
+ if (likely(mask[2])) r[2] = *(int*)(((char*)ptr)+scale*index[2]);
+ if (likely(mask[3])) r[3] = *(int*)(((char*)ptr)+scale*index[3]);
+ if (likely(mask[4])) r[4] = *(int*)(((char*)ptr)+scale*index[4]);
+ if (likely(mask[5])) r[5] = *(int*)(((char*)ptr)+scale*index[5]);
+ if (likely(mask[6])) r[6] = *(int*)(((char*)ptr)+scale*index[6]);
+ if (likely(mask[7])) r[7] = *(int*)(((char*)ptr)+scale*index[7]);
+ return r;
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(void* ptr, const vint8& ofs, const vint8& v)
+ {
+ *(int*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ *(int*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ *(int*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ *(int*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ *(int*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ *(int*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ *(int*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ *(int*)(((char*)ptr)+scale*ofs[7]) = v[7];
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vint8& v)
+ {
+ if (likely(mask[0])) *(int*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ if (likely(mask[1])) *(int*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ if (likely(mask[2])) *(int*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ if (likely(mask[3])) *(int*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ if (likely(mask[4])) *(int*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ if (likely(mask[5])) *(int*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ if (likely(mask[6])) *(int*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ if (likely(mask[7])) *(int*)(((char*)ptr)+scale*ofs[7]) = v[7];
+ }
+
+
+ static __forceinline vint8 broadcast64(const long long& a) { return _mm256_set1_epi64x(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const int& operator [](size_t index) const { assert(index < 8); return i[index]; }
+ __forceinline int& operator [](size_t index) { assert(index < 8); return i[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 asBool(const vint8& a) { return _mm256_castsi256_ps(a); }
+
+ __forceinline vint8 operator +(const vint8& a) { return a; }
+ __forceinline vint8 operator -(const vint8& a) { return vint8(_mm_sub_epi32(_mm_setzero_si128(), a.vl), _mm_sub_epi32(_mm_setzero_si128(), a.vh)); }
+ __forceinline vint8 abs (const vint8& a) { return vint8(_mm_abs_epi32(a.vl), _mm_abs_epi32(a.vh)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8 operator +(const vint8& a, const vint8& b) { return vint8(_mm_add_epi32(a.vl, b.vl), _mm_add_epi32(a.vh, b.vh)); }
+ __forceinline vint8 operator +(const vint8& a, int b) { return a + vint8(b); }
+ __forceinline vint8 operator +(int a, const vint8& b) { return vint8(a) + b; }
+
+ __forceinline vint8 operator -(const vint8& a, const vint8& b) { return vint8(_mm_sub_epi32(a.vl, b.vl), _mm_sub_epi32(a.vh, b.vh)); }
+ __forceinline vint8 operator -(const vint8& a, int b) { return a - vint8(b); }
+ __forceinline vint8 operator -(int a, const vint8& b) { return vint8(a) - b; }
+
+ __forceinline vint8 operator *(const vint8& a, const vint8& b) { return vint8(_mm_mullo_epi32(a.vl, b.vl), _mm_mullo_epi32(a.vh, b.vh)); }
+ __forceinline vint8 operator *(const vint8& a, int b) { return a * vint8(b); }
+ __forceinline vint8 operator *(int a, const vint8& b) { return vint8(a) * b; }
+
+ __forceinline vint8 operator &(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_and_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+ __forceinline vint8 operator &(const vint8& a, int b) { return a & vint8(b); }
+ __forceinline vint8 operator &(int a, const vint8& b) { return vint8(a) & b; }
+
+ __forceinline vint8 operator |(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_or_ps (_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+ __forceinline vint8 operator |(const vint8& a, int b) { return a | vint8(b); }
+ __forceinline vint8 operator |(int a, const vint8& b) { return vint8(a) | b; }
+
+ __forceinline vint8 operator ^(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+ __forceinline vint8 operator ^(const vint8& a, int b) { return a ^ vint8(b); }
+ __forceinline vint8 operator ^(int a, const vint8& b) { return vint8(a) ^ b; }
+
+ __forceinline vint8 operator <<(const vint8& a, int n) { return vint8(_mm_slli_epi32(a.vl, n), _mm_slli_epi32(a.vh, n)); }
+ __forceinline vint8 operator >>(const vint8& a, int n) { return vint8(_mm_srai_epi32(a.vl, n), _mm_srai_epi32(a.vh, n)); }
+
+ __forceinline vint8 sll (const vint8& a, int b) { return vint8(_mm_slli_epi32(a.vl, b), _mm_slli_epi32(a.vh, b)); }
+ __forceinline vint8 sra (const vint8& a, int b) { return vint8(_mm_srai_epi32(a.vl, b), _mm_srai_epi32(a.vh, b)); }
+ __forceinline vint8 srl (const vint8& a, int b) { return vint8(_mm_srli_epi32(a.vl, b), _mm_srli_epi32(a.vh, b)); }
+
+ __forceinline vint8 min(const vint8& a, const vint8& b) { return vint8(_mm_min_epi32(a.vl, b.vl), _mm_min_epi32(a.vh, b.vh)); }
+ __forceinline vint8 min(const vint8& a, int b) { return min(a,vint8(b)); }
+ __forceinline vint8 min(int a, const vint8& b) { return min(vint8(a),b); }
+
+ __forceinline vint8 max(const vint8& a, const vint8& b) { return vint8(_mm_max_epi32(a.vl, b.vl), _mm_max_epi32(a.vh, b.vh)); }
+ __forceinline vint8 max(const vint8& a, int b) { return max(a,vint8(b)); }
+ __forceinline vint8 max(int a, const vint8& b) { return max(vint8(a),b); }
+
+ __forceinline vint8 umin(const vint8& a, const vint8& b) { return vint8(_mm_min_epu32(a.vl, b.vl), _mm_min_epu32(a.vh, b.vh)); }
+ __forceinline vint8 umin(const vint8& a, int b) { return umin(a,vint8(b)); }
+ __forceinline vint8 umin(int a, const vint8& b) { return umin(vint8(a),b); }
+
+ __forceinline vint8 umax(const vint8& a, const vint8& b) { return vint8(_mm_max_epu32(a.vl, b.vl), _mm_max_epu32(a.vh, b.vh)); }
+ __forceinline vint8 umax(const vint8& a, int b) { return umax(a,vint8(b)); }
+ __forceinline vint8 umax(int a, const vint8& b) { return umax(vint8(a),b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8& operator +=(vint8& a, const vint8& b) { return a = a + b; }
+ __forceinline vint8& operator +=(vint8& a, int b) { return a = a + b; }
+
+ __forceinline vint8& operator -=(vint8& a, const vint8& b) { return a = a - b; }
+ __forceinline vint8& operator -=(vint8& a, int b) { return a = a - b; }
+
+ __forceinline vint8& operator *=(vint8& a, const vint8& b) { return a = a * b; }
+ __forceinline vint8& operator *=(vint8& a, int b) { return a = a * b; }
+
+ __forceinline vint8& operator &=(vint8& a, const vint8& b) { return a = a & b; }
+ __forceinline vint8& operator &=(vint8& a, int b) { return a = a & b; }
+
+ __forceinline vint8& operator |=(vint8& a, const vint8& b) { return a = a | b; }
+ __forceinline vint8& operator |=(vint8& a, int b) { return a = a | b; }
+
+ __forceinline vint8& operator <<=(vint8& a, int b) { return a = a << b; }
+ __forceinline vint8& operator >>=(vint8& a, int b) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmpeq_epi32 (a.vl, b.vl)),
+ _mm_castsi128_ps(_mm_cmpeq_epi32 (a.vh, b.vh))); }
+ __forceinline vboolf8 operator ==(const vint8& a, int b) { return a == vint8(b); }
+ __forceinline vboolf8 operator ==(int a, const vint8& b) { return vint8(a) == b; }
+
+ __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return !(a == b); }
+ __forceinline vboolf8 operator !=(const vint8& a, int b) { return a != vint8(b); }
+ __forceinline vboolf8 operator !=(int a, const vint8& b) { return vint8(a) != b; }
+
+ __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmplt_epi32 (a.vl, b.vl)),
+ _mm_castsi128_ps(_mm_cmplt_epi32 (a.vh, b.vh))); }
+ __forceinline vboolf8 operator < (const vint8& a, int b) { return a < vint8(b); }
+ __forceinline vboolf8 operator < (int a, const vint8& b) { return vint8(a) < b; }
+
+ __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return !(a < b); }
+ __forceinline vboolf8 operator >=(const vint8& a, int b) { return a >= vint8(b); }
+ __forceinline vboolf8 operator >=(int a, const vint8& b) { return vint8(a) >= b; }
+
+ __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmpgt_epi32 (a.vl, b.vl)),
+ _mm_castsi128_ps(_mm_cmpgt_epi32 (a.vh, b.vh))); }
+ __forceinline vboolf8 operator > (const vint8& a, int b) { return a > vint8(b); }
+ __forceinline vboolf8 operator > (int a, const vint8& b) { return vint8(a) > b; }
+
+ __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return !(a > b); }
+ __forceinline vboolf8 operator <=(const vint8& a, int b) { return a <= vint8(b); }
+ __forceinline vboolf8 operator <=(int a, const vint8& b) { return vint8(a) <= b; }
+
+ __forceinline vboolf8 eq(const vint8& a, const vint8& b) { return a == b; }
+ __forceinline vboolf8 ne(const vint8& a, const vint8& b) { return a != b; }
+ __forceinline vboolf8 lt(const vint8& a, const vint8& b) { return a < b; }
+ __forceinline vboolf8 ge(const vint8& a, const vint8& b) { return a >= b; }
+ __forceinline vboolf8 gt(const vint8& a, const vint8& b) { return a > b; }
+ __forceinline vboolf8 le(const vint8& a, const vint8& b) { return a <= b; }
+
+ __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a == b); }
+ __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a != b); }
+ __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a < b); }
+ __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a >= b); }
+ __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a > b); }
+ __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a <= b); }
+
+ __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) {
+ return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8 unpacklo(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_unpacklo_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+ __forceinline vint8 unpackhi(const vint8& a, const vint8& b) { return _mm256_castps_si256(_mm256_unpackhi_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+
+ template<int i>
+ __forceinline vint8 shuffle(const vint8& v) {
+ return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
+ }
+
+ template<int i0, int i1>
+ __forceinline vint8 shuffle4(const vint8& v) {
+ return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1>
+ __forceinline vint8 shuffle4(const vint8& a, const vint8& b) {
+ return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint8 shuffle(const vint8& v) {
+ return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint8 shuffle(const vint8& a, const vint8& b) {
+ return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<> __forceinline vint8 shuffle<0, 0, 2, 2>(const vint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
+ template<> __forceinline vint8 shuffle<1, 1, 3, 3>(const vint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
+ template<> __forceinline vint8 shuffle<0, 1, 0, 1>(const vint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
+
+ __forceinline vint8 broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
+ template<int i> __forceinline vint8 insert4(const vint8& a, const vint4& b) { return _mm256_insertf128_si256(a, b, i); }
+ template<int i> __forceinline vint4 extract4(const vint8& a) { return _mm256_extractf128_si256(a, i); }
+ template<> __forceinline vint4 extract4<0>(const vint8& a) { return _mm256_castsi256_si128(a); }
+
+ __forceinline int toScalar(const vint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8 vreduce_min2(const vint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
+ __forceinline vint8 vreduce_min4(const vint8& v) { vint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
+ __forceinline vint8 vreduce_min (const vint8& v) { vint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
+
+ __forceinline vint8 vreduce_max2(const vint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
+ __forceinline vint8 vreduce_max4(const vint8& v) { vint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
+ __forceinline vint8 vreduce_max (const vint8& v) { vint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
+
+ __forceinline vint8 vreduce_add2(const vint8& v) { return v + shuffle<1,0,3,2>(v); }
+ __forceinline vint8 vreduce_add4(const vint8& v) { vint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
+ __forceinline vint8 vreduce_add (const vint8& v) { vint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
+
+ __forceinline int reduce_min(const vint8& v) { return toScalar(vreduce_min(v)); }
+ __forceinline int reduce_max(const vint8& v) { return toScalar(vreduce_max(v)); }
+ __forceinline int reduce_add(const vint8& v) { return toScalar(vreduce_add(v)); }
+
+ __forceinline size_t select_min(const vint8& v) { return bsf(movemask(v == vreduce_min(v))); }
+ __forceinline size_t select_max(const vint8& v) { return bsf(movemask(v == vreduce_max(v))); }
+
+ __forceinline size_t select_min(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
+ __forceinline size_t select_max(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Sorting networks
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8 usort_ascending(const vint8& v)
+ {
+ const vint8 a0 = v;
+ const vint8 b0 = shuffle<1,0,3,2>(a0);
+ const vint8 c0 = umin(a0,b0);
+ const vint8 d0 = umax(a0,b0);
+ const vint8 a1 = select(0x99 /* 0b10011001 */,c0,d0);
+ const vint8 b1 = shuffle<2,3,0,1>(a1);
+ const vint8 c1 = umin(a1,b1);
+ const vint8 d1 = umax(a1,b1);
+ const vint8 a2 = select(0xc3 /* 0b11000011 */,c1,d1);
+ const vint8 b2 = shuffle<1,0,3,2>(a2);
+ const vint8 c2 = umin(a2,b2);
+ const vint8 d2 = umax(a2,b2);
+ const vint8 a3 = select(0xa5 /* 0b10100101 */,c2,d2);
+ const vint8 b3 = shuffle4<1,0>(a3);
+ const vint8 c3 = umin(a3,b3);
+ const vint8 d3 = umax(a3,b3);
+ const vint8 a4 = select(0xf /* 0b00001111 */,c3,d3);
+ const vint8 b4 = shuffle<2,3,0,1>(a4);
+ const vint8 c4 = umin(a4,b4);
+ const vint8 d4 = umax(a4,b4);
+ const vint8 a5 = select(0x33 /* 0b00110011 */,c4,d4);
+ const vint8 b5 = shuffle<1,0,3,2>(a5);
+ const vint8 c5 = umin(a5,b5);
+ const vint8 d5 = umax(a5,b5);
+ const vint8 a6 = select(0x55 /* 0b01010101 */,c5,d5);
+ return a6;
+ }
+
+ __forceinline vint8 usort_descending(const vint8& v)
+ {
+ const vint8 a0 = v;
+ const vint8 b0 = shuffle<1,0,3,2>(a0);
+ const vint8 c0 = umax(a0,b0);
+ const vint8 d0 = umin(a0,b0);
+ const vint8 a1 = select(0x99 /* 0b10011001 */,c0,d0);
+ const vint8 b1 = shuffle<2,3,0,1>(a1);
+ const vint8 c1 = umax(a1,b1);
+ const vint8 d1 = umin(a1,b1);
+ const vint8 a2 = select(0xc3 /* 0b11000011 */,c1,d1);
+ const vint8 b2 = shuffle<1,0,3,2>(a2);
+ const vint8 c2 = umax(a2,b2);
+ const vint8 d2 = umin(a2,b2);
+ const vint8 a3 = select(0xa5 /* 0b10100101 */,c2,d2);
+ const vint8 b3 = shuffle4<1,0>(a3);
+ const vint8 c3 = umax(a3,b3);
+ const vint8 d3 = umin(a3,b3);
+ const vint8 a4 = select(0xf /* 0b00001111 */,c3,d3);
+ const vint8 b4 = shuffle<2,3,0,1>(a4);
+ const vint8 c4 = umax(a4,b4);
+ const vint8 d4 = umin(a4,b4);
+ const vint8 a5 = select(0x33 /* 0b00110011 */,c4,d4);
+ const vint8 b5 = shuffle<1,0,3,2>(a5);
+ const vint8 c5 = umax(a5,b5);
+ const vint8 d5 = umin(a5,b5);
+ const vint8 a6 = select(0x55 /* 0b01010101 */,c5,d5);
+ return a6;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vint8& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vint8_avx2.h b/thirdparty/embree/common/simd/vint8_avx2.h
new file mode 100644
index 0000000000..e04737ffbe
--- /dev/null
+++ b/thirdparty/embree/common/simd/vint8_avx2.h
@@ -0,0 +1,518 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX integer type */
+ template<>
+ struct vint<8>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboolf8 Bool;
+ typedef vint8 Int;
+ typedef vfloat8 Float;
+
+ enum { size = 8 }; // number of SIMD elements
+ union { // data
+ __m256i v;
+ int i[8];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint() {}
+ __forceinline vint(const vint8& a) { v = a.v; }
+ __forceinline vint8& operator =(const vint8& a) { v = a.v; return *this; }
+
+ __forceinline vint(__m256i a) : v(a) {}
+ __forceinline operator const __m256i&() const { return v; }
+ __forceinline operator __m256i&() { return v; }
+
+ __forceinline explicit vint(const vint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
+ __forceinline vint(const vint4& a, const vint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
+ __forceinline vint(const __m128i& a, const __m128i& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
+
+ __forceinline explicit vint(const int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
+ __forceinline vint(int a) : v(_mm256_set1_epi32(a)) {}
+ __forceinline vint(int a, int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
+ __forceinline vint(int a, int b, int c, int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
+ __forceinline vint(int a, int b, int c, int d, int e, int f, int g, int h) : v(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
+
+ __forceinline explicit vint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
+
+#if defined(__AVX512VL__)
+ __forceinline explicit vint(const vboolf8& a) : v(_mm256_movm_epi32(a)) {}
+#else
+ __forceinline explicit vint(const vboolf8& a) : v(_mm256_castps_si256((__m256)a)) {}
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint(ZeroTy) : v(_mm256_setzero_si256()) {}
+ __forceinline vint(OneTy) : v(_mm256_set1_epi32(1)) {}
+ __forceinline vint(PosInfTy) : v(_mm256_set1_epi32(pos_inf)) {}
+ __forceinline vint(NegInfTy) : v(_mm256_set1_epi32(neg_inf)) {}
+ __forceinline vint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
+ __forceinline vint(ReverseStepTy) : v(_mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7)) {}
+ __forceinline vint(UndefinedTy) : v(_mm256_undefined_si256()) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vint8 load(const unsigned char* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
+ static __forceinline vint8 loadu(const unsigned char* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
+ static __forceinline vint8 load(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_load_si128((__m128i*)ptr)); }
+ static __forceinline vint8 loadu(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr)); }
+
+ static __forceinline vint8 load(const void* ptr) { return _mm256_load_si256((__m256i*)ptr); }
+ static __forceinline vint8 loadu(const void* ptr) { return _mm256_loadu_si256((__m256i*)ptr); }
+
+ static __forceinline void store (void* ptr, const vint8& v) { _mm256_store_si256((__m256i*)ptr,v); }
+ static __forceinline void storeu(void* ptr, const vint8& v) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(v)); }
+
+#if defined(__AVX512VL__)
+
+ static __forceinline vint8 compact(const vboolf8& mask, vint8 &v) {
+ return _mm256_mask_compress_epi32(v, mask, v);
+ }
+ static __forceinline vint8 compact(const vboolf8& mask, vint8 &a, const vint8& b) {
+ return _mm256_mask_compress_epi32(a, mask, b);
+ }
+
+ static __forceinline vint8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_epi32 (_mm256_setzero_si256(),mask,ptr); }
+ static __forceinline vint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_epi32(_mm256_setzero_si256(),mask,ptr); }
+
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& v) { _mm256_mask_store_epi32 (ptr,mask,v); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& v) { _mm256_mask_storeu_epi32(ptr,mask,v); }
+#else
+ static __forceinline vint8 load (const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
+ static __forceinline vint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
+
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
+#endif
+
+ static __forceinline vint8 load_nt(void* ptr) {
+ return _mm256_stream_load_si256((__m256i*)ptr);
+ }
+
+ static __forceinline void store_nt(void* ptr, const vint8& v) {
+ _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
+ }
+
+ static __forceinline void store(unsigned char* ptr, const vint8& i)
+ {
+ for (size_t j=0; j<8; j++)
+ ptr[j] = i[j];
+ }
+
+ static __forceinline void store(unsigned short* ptr, const vint8& v) {
+ for (size_t i=0;i<8;i++)
+ ptr[i] = (unsigned short)v[i];
+ }
+
+ template<int scale = 4>
+ static __forceinline vint8 gather(const int *const ptr, const vint8& index) {
+ return _mm256_i32gather_epi32(ptr, index, scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline vint8 gather(const vboolf8& mask, const int *const ptr, const vint8& index) {
+ vint8 r = zero;
+#if defined(__AVX512VL__)
+ return _mm256_mmask_i32gather_epi32(r, mask, index, ptr, scale);
+#else
+ return _mm256_mask_i32gather_epi32(r, ptr, index, mask, scale);
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(void* ptr, const vint8& ofs, const vint8& v)
+ {
+#if defined(__AVX512VL__)
+ _mm256_i32scatter_epi32((int*)ptr, ofs, v, scale);
+#else
+ *(int*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ *(int*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ *(int*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ *(int*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ *(int*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ *(int*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ *(int*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ *(int*)(((char*)ptr)+scale*ofs[7]) = v[7];
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vint8& v)
+ {
+#if defined(__AVX512VL__)
+ _mm256_mask_i32scatter_epi32((int*)ptr, mask, ofs, v, scale);
+#else
+ if (likely(mask[0])) *(int*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ if (likely(mask[1])) *(int*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ if (likely(mask[2])) *(int*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ if (likely(mask[3])) *(int*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ if (likely(mask[4])) *(int*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ if (likely(mask[5])) *(int*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ if (likely(mask[6])) *(int*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ if (likely(mask[7])) *(int*)(((char*)ptr)+scale*ofs[7]) = v[7];
+#endif
+ }
+
+ static __forceinline vint8 broadcast64(const long long &a) { return _mm256_set1_epi64x(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const int& operator [](size_t index) const { assert(index < 8); return i[index]; }
+ __forceinline int& operator [](size_t index) { assert(index < 8); return i[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ static __forceinline vboolf8 asBool(const vint8& a) { return _mm256_movepi32_mask(a); }
+#else
+ static __forceinline vboolf8 asBool(const vint8& a) { return _mm256_castsi256_ps(a); }
+#endif
+
+ __forceinline vint8 operator +(const vint8& a) { return a; }
+ __forceinline vint8 operator -(const vint8& a) { return _mm256_sub_epi32(_mm256_setzero_si256(), a); }
+ __forceinline vint8 abs (const vint8& a) { return _mm256_abs_epi32(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8 operator +(const vint8& a, const vint8& b) { return _mm256_add_epi32(a, b); }
+ __forceinline vint8 operator +(const vint8& a, int b) { return a + vint8(b); }
+ __forceinline vint8 operator +(int a, const vint8& b) { return vint8(a) + b; }
+
+ __forceinline vint8 operator -(const vint8& a, const vint8& b) { return _mm256_sub_epi32(a, b); }
+ __forceinline vint8 operator -(const vint8& a, int b) { return a - vint8(b); }
+ __forceinline vint8 operator -(int a, const vint8& b) { return vint8(a) - b; }
+
+ __forceinline vint8 operator *(const vint8& a, const vint8& b) { return _mm256_mullo_epi32(a, b); }
+ __forceinline vint8 operator *(const vint8& a, int b) { return a * vint8(b); }
+ __forceinline vint8 operator *(int a, const vint8& b) { return vint8(a) * b; }
+
+ __forceinline vint8 operator &(const vint8& a, const vint8& b) { return _mm256_and_si256(a, b); }
+ __forceinline vint8 operator &(const vint8& a, int b) { return a & vint8(b); }
+ __forceinline vint8 operator &(int a, const vint8& b) { return vint8(a) & b; }
+
+ __forceinline vint8 operator |(const vint8& a, const vint8& b) { return _mm256_or_si256(a, b); }
+ __forceinline vint8 operator |(const vint8& a, int b) { return a | vint8(b); }
+ __forceinline vint8 operator |(int a, const vint8& b) { return vint8(a) | b; }
+
+ __forceinline vint8 operator ^(const vint8& a, const vint8& b) { return _mm256_xor_si256(a, b); }
+ __forceinline vint8 operator ^(const vint8& a, int b) { return a ^ vint8(b); }
+ __forceinline vint8 operator ^(int a, const vint8& b) { return vint8(a) ^ b; }
+
+ __forceinline vint8 operator <<(const vint8& a, int n) { return _mm256_slli_epi32(a, n); }
+ __forceinline vint8 operator >>(const vint8& a, int n) { return _mm256_srai_epi32(a, n); }
+
+ __forceinline vint8 operator <<(const vint8& a, const vint8& n) { return _mm256_sllv_epi32(a, n); }
+ __forceinline vint8 operator >>(const vint8& a, const vint8& n) { return _mm256_srav_epi32(a, n); }
+
+ __forceinline vint8 sll(const vint8& a, int b) { return _mm256_slli_epi32(a, b); }
+ __forceinline vint8 sra(const vint8& a, int b) { return _mm256_srai_epi32(a, b); }
+ __forceinline vint8 srl(const vint8& a, int b) { return _mm256_srli_epi32(a, b); }
+
+ __forceinline vint8 sll(const vint8& a, const vint8& b) { return _mm256_sllv_epi32(a, b); }
+ __forceinline vint8 sra(const vint8& a, const vint8& b) { return _mm256_srav_epi32(a, b); }
+ __forceinline vint8 srl(const vint8& a, const vint8& b) { return _mm256_srlv_epi32(a, b); }
+
+ __forceinline vint8 min(const vint8& a, const vint8& b) { return _mm256_min_epi32(a, b); }
+ __forceinline vint8 min(const vint8& a, int b) { return min(a,vint8(b)); }
+ __forceinline vint8 min(int a, const vint8& b) { return min(vint8(a),b); }
+
+ __forceinline vint8 max(const vint8& a, const vint8& b) { return _mm256_max_epi32(a, b); }
+ __forceinline vint8 max(const vint8& a, int b) { return max(a,vint8(b)); }
+ __forceinline vint8 max(int a, const vint8& b) { return max(vint8(a),b); }
+
+ __forceinline vint8 umin(const vint8& a, const vint8& b) { return _mm256_min_epu32(a, b); }
+ __forceinline vint8 umax(const vint8& a, const vint8& b) { return _mm256_max_epu32(a, b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8& operator +=(vint8& a, const vint8& b) { return a = a + b; }
+ __forceinline vint8& operator +=(vint8& a, int b) { return a = a + b; }
+
+ __forceinline vint8& operator -=(vint8& a, const vint8& b) { return a = a - b; }
+ __forceinline vint8& operator -=(vint8& a, int b) { return a = a - b; }
+
+ __forceinline vint8& operator *=(vint8& a, const vint8& b) { return a = a * b; }
+ __forceinline vint8& operator *=(vint8& a, int b) { return a = a * b; }
+
+ __forceinline vint8& operator &=(vint8& a, const vint8& b) { return a = a & b; }
+ __forceinline vint8& operator &=(vint8& a, int b) { return a = a & b; }
+
+ __forceinline vint8& operator |=(vint8& a, const vint8& b) { return a = a | b; }
+ __forceinline vint8& operator |=(vint8& a, int b) { return a = a | b; }
+
+ __forceinline vint8& operator <<=(vint8& a, const int b) { return a = a << b; }
+ __forceinline vint8& operator >>=(vint8& a, const int b) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ static __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
+ static __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
+ static __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
+ static __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
+ static __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
+ static __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
+
+ static __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) {
+ return _mm256_mask_blend_epi32(m, (__m256i)f, (__m256i)t);
+ }
+#else
+ static __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b)); }
+ static __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return !(a == b); }
+ static __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32(b, a)); }
+ static __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return !(a < b); }
+ static __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32(a, b)); }
+ static __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return !(a > b); }
+
+ static __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) {
+ return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
+ }
+#endif
+
+ template<int mask>
+ __forceinline vint8 select(const vint8& t, const vint8& f) {
+ return _mm256_blend_epi32(f, t, mask);
+ }
+
+ __forceinline vboolf8 operator ==(const vint8& a, int b) { return a == vint8(b); }
+ __forceinline vboolf8 operator ==(int a, const vint8& b) { return vint8(a) == b; }
+
+ __forceinline vboolf8 operator !=(const vint8& a, int b) { return a != vint8(b); }
+ __forceinline vboolf8 operator !=(int a, const vint8& b) { return vint8(a) != b; }
+
+ __forceinline vboolf8 operator < (const vint8& a, int b) { return a < vint8(b); }
+ __forceinline vboolf8 operator < (int a, const vint8& b) { return vint8(a) < b; }
+
+ __forceinline vboolf8 operator >=(const vint8& a, int b) { return a >= vint8(b); }
+ __forceinline vboolf8 operator >=(int a, const vint8& b) { return vint8(a) >= b; }
+
+ __forceinline vboolf8 operator > (const vint8& a, int b) { return a > vint8(b); }
+ __forceinline vboolf8 operator > (int a, const vint8& b) { return vint8(a) > b; }
+
+ __forceinline vboolf8 operator <=(const vint8& a, int b) { return a <= vint8(b); }
+ __forceinline vboolf8 operator <=(int a, const vint8& b) { return vint8(a) <= b; }
+
+ __forceinline vboolf8 eq(const vint8& a, const vint8& b) { return a == b; }
+ __forceinline vboolf8 ne(const vint8& a, const vint8& b) { return a != b; }
+ __forceinline vboolf8 lt(const vint8& a, const vint8& b) { return a < b; }
+ __forceinline vboolf8 ge(const vint8& a, const vint8& b) { return a >= b; }
+ __forceinline vboolf8 gt(const vint8& a, const vint8& b) { return a > b; }
+ __forceinline vboolf8 le(const vint8& a, const vint8& b) { return a <= b; }
+
+#if defined(__AVX512VL__)
+ static __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_EQ); }
+ static __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_NE); }
+ static __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); }
+ static __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GE); }
+ static __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GT); }
+ static __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LE); }
+#else
+ static __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a == b); }
+ static __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a != b); }
+ static __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a < b); }
+ static __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a >= b); }
+ static __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a > b); }
+ static __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a <= b); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8 unpacklo(const vint8& a, const vint8& b) { return _mm256_unpacklo_epi32(a, b); }
+ __forceinline vint8 unpackhi(const vint8& a, const vint8& b) { return _mm256_unpackhi_epi32(a, b); }
+
+ template<int i>
+ __forceinline vint8 shuffle(const vint8& v) {
+ return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
+ }
+
+ template<int i0, int i1>
+ __forceinline vint8 shuffle4(const vint8& v) {
+ return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1>
+ __forceinline vint8 shuffle4(const vint8& a, const vint8& b) {
+ return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint8 shuffle(const vint8& v) {
+ return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vint8 shuffle(const vint8& a, const vint8& b) {
+ return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<> __forceinline vint8 shuffle<0, 0, 2, 2>(const vint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
+ template<> __forceinline vint8 shuffle<1, 1, 3, 3>(const vint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
+ template<> __forceinline vint8 shuffle<0, 1, 0, 1>(const vint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
+
+ __forceinline vint8 broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
+
+ template<int i> __forceinline vint8 insert4(const vint8& a, const vint4& b) { return _mm256_insertf128_si256(a, b, i); }
+ template<int i> __forceinline vint4 extract4(const vint8& a) { return _mm256_extractf128_si256(a, i); }
+ template<> __forceinline vint4 extract4<0>(const vint8& a) { return _mm256_castsi256_si128(a); }
+
+ __forceinline int toScalar(const vint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
+
+ __forceinline vint8 permute(const vint8& v, const __m256i& index) {
+ return _mm256_permutevar8x32_epi32(v, index);
+ }
+
+ __forceinline vint8 shuffle(const vint8& v, const __m256i& index) {
+ return _mm256_castps_si256(_mm256_permutevar_ps(_mm256_castsi256_ps(v), index));
+ }
+
+ template<int i>
+ static __forceinline vint8 align_shift_right(const vint8& a, const vint8& b) {
+#if defined(__AVX512VL__)
+ return _mm256_alignr_epi32(a, b, i);
+#else
+ return _mm256_alignr_epi8(a, b, 4*i);
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8 vreduce_min2(const vint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
+ __forceinline vint8 vreduce_min4(const vint8& v) { vint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
+ __forceinline vint8 vreduce_min (const vint8& v) { vint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
+
+ __forceinline vint8 vreduce_max2(const vint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
+ __forceinline vint8 vreduce_max4(const vint8& v) { vint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
+ __forceinline vint8 vreduce_max (const vint8& v) { vint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
+
+ __forceinline vint8 vreduce_add2(const vint8& v) { return v + shuffle<1,0,3,2>(v); }
+ __forceinline vint8 vreduce_add4(const vint8& v) { vint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
+ __forceinline vint8 vreduce_add (const vint8& v) { vint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
+
+ __forceinline int reduce_min(const vint8& v) { return toScalar(vreduce_min(v)); }
+ __forceinline int reduce_max(const vint8& v) { return toScalar(vreduce_max(v)); }
+ __forceinline int reduce_add(const vint8& v) { return toScalar(vreduce_add(v)); }
+
+ __forceinline size_t select_min(const vint8& v) { return bsf(movemask(v == vreduce_min(v))); }
+ __forceinline size_t select_max(const vint8& v) { return bsf(movemask(v == vreduce_max(v))); }
+
+ __forceinline size_t select_min(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
+ __forceinline size_t select_max(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Sorting networks
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vint8 usort_ascending(const vint8& v)
+ {
+ const vint8 a0 = v;
+ const vint8 b0 = shuffle<1,0,3,2>(a0);
+ const vint8 c0 = umin(a0,b0);
+ const vint8 d0 = umax(a0,b0);
+ const vint8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
+ const vint8 b1 = shuffle<2,3,0,1>(a1);
+ const vint8 c1 = umin(a1,b1);
+ const vint8 d1 = umax(a1,b1);
+ const vint8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
+ const vint8 b2 = shuffle<1,0,3,2>(a2);
+ const vint8 c2 = umin(a2,b2);
+ const vint8 d2 = umax(a2,b2);
+ const vint8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
+ const vint8 b3 = shuffle4<1,0>(a3);
+ const vint8 c3 = umin(a3,b3);
+ const vint8 d3 = umax(a3,b3);
+ const vint8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
+ const vint8 b4 = shuffle<2,3,0,1>(a4);
+ const vint8 c4 = umin(a4,b4);
+ const vint8 d4 = umax(a4,b4);
+ const vint8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
+ const vint8 b5 = shuffle<1,0,3,2>(a5);
+ const vint8 c5 = umin(a5,b5);
+ const vint8 d5 = umax(a5,b5);
+ const vint8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
+ return a6;
+ }
+
+ __forceinline vint8 usort_descending(const vint8& v)
+ {
+ const vint8 a0 = v;
+ const vint8 b0 = shuffle<1,0,3,2>(a0);
+ const vint8 c0 = umax(a0,b0);
+ const vint8 d0 = umin(a0,b0);
+ const vint8 a1 = select<0x99 /* 0b10011001 */>(c0,d0);
+ const vint8 b1 = shuffle<2,3,0,1>(a1);
+ const vint8 c1 = umax(a1,b1);
+ const vint8 d1 = umin(a1,b1);
+ const vint8 a2 = select<0xc3 /* 0b11000011 */>(c1,d1);
+ const vint8 b2 = shuffle<1,0,3,2>(a2);
+ const vint8 c2 = umax(a2,b2);
+ const vint8 d2 = umin(a2,b2);
+ const vint8 a3 = select<0xa5 /* 0b10100101 */>(c2,d2);
+ const vint8 b3 = shuffle4<1,0>(a3);
+ const vint8 c3 = umax(a3,b3);
+ const vint8 d3 = umin(a3,b3);
+ const vint8 a4 = select<0xf /* 0b00001111 */>(c3,d3);
+ const vint8 b4 = shuffle<2,3,0,1>(a4);
+ const vint8 c4 = umax(a4,b4);
+ const vint8 d4 = umin(a4,b4);
+ const vint8 a5 = select<0x33 /* 0b00110011 */>(c4,d4);
+ const vint8 b5 = shuffle<1,0,3,2>(a5);
+ const vint8 c5 = umax(a5,b5);
+ const vint8 d5 = umin(a5,b5);
+ const vint8 a6 = select<0x55 /* 0b01010101 */>(c5,d5);
+ return a6;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vint8& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vllong4_avx2.h b/thirdparty/embree/common/simd/vllong4_avx2.h
new file mode 100644
index 0000000000..6c86845877
--- /dev/null
+++ b/thirdparty/embree/common/simd/vllong4_avx2.h
@@ -0,0 +1,352 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide AVX2 64-bit long long type */
+ template<>
+ struct vllong<4>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboold4 Bool;
+
+ enum { size = 4 }; // number of SIMD elements
+ union { // data
+ __m256i v;
+ long long i[4];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong() {}
+ __forceinline vllong(const vllong4& t) { v = t.v; }
+ __forceinline vllong4& operator =(const vllong4& f) { v = f.v; return *this; }
+
+ __forceinline vllong(const __m256i& t) { v = t; }
+ __forceinline operator __m256i() const { return v; }
+ __forceinline operator __m256d() const { return _mm256_castsi256_pd(v); }
+
+
+ __forceinline vllong(long long i) {
+ v = _mm256_set1_epi64x(i);
+ }
+
+ __forceinline vllong(long long a, long long b, long long c, long long d) {
+ v = _mm256_set_epi64x(d,c,b,a);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong(ZeroTy) : v(_mm256_setzero_si256()) {}
+ __forceinline vllong(OneTy) : v(_mm256_set1_epi64x(1)) {}
+ __forceinline vllong(StepTy) : v(_mm256_set_epi64x(3,2,1,0)) {}
+ __forceinline vllong(ReverseStepTy) : v(_mm256_set_epi64x(0,1,2,3)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline void store_nt(void* __restrict__ ptr, const vllong4& a) {
+ _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(a));
+ }
+
+ static __forceinline vllong4 loadu(const void* addr)
+ {
+ return _mm256_loadu_si256((__m256i*)addr);
+ }
+
+ static __forceinline vllong4 load(const vllong4* addr) {
+ return _mm256_load_si256((__m256i*)addr);
+ }
+
+ static __forceinline vllong4 load(const long long* addr) {
+ return _mm256_load_si256((__m256i*)addr);
+ }
+
+ static __forceinline void store(void* ptr, const vllong4& v) {
+ _mm256_store_si256((__m256i*)ptr,v);
+ }
+
+ static __forceinline void storeu(void* ptr, const vllong4& v) {
+ _mm256_storeu_si256((__m256i*)ptr,v);
+ }
+
+ static __forceinline void storeu(const vboold4& mask, long long* ptr, const vllong4& f) {
+#if defined(__AVX512VL__)
+ _mm256_mask_storeu_epi64(ptr,mask,f);
+#else
+ _mm256_maskstore_pd((double*)ptr,mask,_mm256_castsi256_pd(f));
+#endif
+ }
+
+ static __forceinline void store(const vboold4& mask, void* ptr, const vllong4& f) {
+#if defined(__AVX512VL__)
+ _mm256_mask_store_epi64(ptr,mask,f);
+#else
+ _mm256_maskstore_pd((double*)ptr,mask,_mm256_castsi256_pd(f));
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline long long& operator [](size_t index) { assert(index < 4); return i[index]; }
+ __forceinline const long long& operator [](size_t index) const { assert(index < 4); return i[index]; }
+
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong4 select(const vboold4& m, const vllong4& t, const vllong4& f) {
+ #if defined(__AVX512VL__)
+ return _mm256_mask_blend_epi64(m, f, t);
+ #else
+ return _mm256_castpd_si256(_mm256_blendv_pd(_mm256_castsi256_pd(f), _mm256_castsi256_pd(t), m));
+ #endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboold4 asBool(const vllong4& a) { return _mm256_movepi64_mask(a); }
+#else
+ __forceinline vboold4 asBool(const vllong4& a) { return _mm256_castsi256_pd(a); }
+#endif
+
+ __forceinline vllong4 operator +(const vllong4& a) { return a; }
+ __forceinline vllong4 operator -(const vllong4& a) { return _mm256_sub_epi64(_mm256_setzero_si256(), a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong4 operator +(const vllong4& a, const vllong4& b) { return _mm256_add_epi64(a, b); }
+ __forceinline vllong4 operator +(const vllong4& a, long long b) { return a + vllong4(b); }
+ __forceinline vllong4 operator +(long long a, const vllong4& b) { return vllong4(a) + b; }
+
+ __forceinline vllong4 operator -(const vllong4& a, const vllong4& b) { return _mm256_sub_epi64(a, b); }
+ __forceinline vllong4 operator -(const vllong4& a, long long b) { return a - vllong4(b); }
+ __forceinline vllong4 operator -(long long a, const vllong4& b) { return vllong4(a) - b; }
+
+ /* only low 32bit part */
+ __forceinline vllong4 operator *(const vllong4& a, const vllong4& b) { return _mm256_mul_epi32(a, b); }
+ __forceinline vllong4 operator *(const vllong4& a, long long b) { return a * vllong4(b); }
+ __forceinline vllong4 operator *(long long a, const vllong4& b) { return vllong4(a) * b; }
+
+ __forceinline vllong4 operator &(const vllong4& a, const vllong4& b) { return _mm256_and_si256(a, b); }
+ __forceinline vllong4 operator &(const vllong4& a, long long b) { return a & vllong4(b); }
+ __forceinline vllong4 operator &(long long a, const vllong4& b) { return vllong4(a) & b; }
+
+ __forceinline vllong4 operator |(const vllong4& a, const vllong4& b) { return _mm256_or_si256(a, b); }
+ __forceinline vllong4 operator |(const vllong4& a, long long b) { return a | vllong4(b); }
+ __forceinline vllong4 operator |(long long a, const vllong4& b) { return vllong4(a) | b; }
+
+ __forceinline vllong4 operator ^(const vllong4& a, const vllong4& b) { return _mm256_xor_si256(a, b); }
+ __forceinline vllong4 operator ^(const vllong4& a, long long b) { return a ^ vllong4(b); }
+ __forceinline vllong4 operator ^(long long a, const vllong4& b) { return vllong4(a) ^ b; }
+
+ __forceinline vllong4 operator <<(const vllong4& a, long long n) { return _mm256_slli_epi64(a, (int)n); }
+ //__forceinline vllong4 operator >>(const vllong4& a, long long n) { return _mm256_srai_epi64(a, n); }
+
+ __forceinline vllong4 operator <<(const vllong4& a, const vllong4& n) { return _mm256_sllv_epi64(a, n); }
+ //__forceinline vllong4 operator >>(const vllong4& a, const vllong4& n) { return _mm256_srav_epi64(a, n); }
+ //__forceinline vllong4 sra(const vllong4& a, long long b) { return _mm256_srai_epi64(a, b); }
+
+ __forceinline vllong4 srl(const vllong4& a, long long b) { return _mm256_srli_epi64(a, (int)b); }
+
+ //__forceinline vllong4 min(const vllong4& a, const vllong4& b) { return _mm256_min_epi64(a, b); }
+ //__forceinline vllong4 min(const vllong4& a, long long b) { return min(a,vllong4(b)); }
+ //__forceinline vllong4 min(long long a, const vllong4& b) { return min(vllong4(a),b); }
+
+ //__forceinline vllong4 max(const vllong4& a, const vllong4& b) { return _mm256_max_epi64(a, b); }
+ //__forceinline vllong4 max(const vllong4& a, long long b) { return max(a,vllong4(b)); }
+ //__forceinline vllong4 max(long long a, const vllong4& b) { return max(vllong4(a),b); }
+
+#if defined(__AVX512VL__)
+ __forceinline vllong4 mask_and(const vboold4& m, const vllong4& c, const vllong4& a, const vllong4& b) { return _mm256_mask_and_epi64(c,m,a,b); }
+ __forceinline vllong4 mask_or (const vboold4& m, const vllong4& c, const vllong4& a, const vllong4& b) { return _mm256_mask_or_epi64(c,m,a,b); }
+#else
+ __forceinline vllong4 mask_and(const vboold4& m, const vllong4& c, const vllong4& a, const vllong4& b) { return select(m, a & b, c); }
+ __forceinline vllong4 mask_or (const vboold4& m, const vllong4& c, const vllong4& a, const vllong4& b) { return select(m, a | b, c); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong4& operator +=(vllong4& a, const vllong4& b) { return a = a + b; }
+ __forceinline vllong4& operator +=(vllong4& a, long long b) { return a = a + b; }
+
+ __forceinline vllong4& operator -=(vllong4& a, const vllong4& b) { return a = a - b; }
+ __forceinline vllong4& operator -=(vllong4& a, long long b) { return a = a - b; }
+
+ __forceinline vllong4& operator *=(vllong4& a, const vllong4& b) { return a = a * b; }
+ __forceinline vllong4& operator *=(vllong4& a, long long b) { return a = a * b; }
+
+ __forceinline vllong4& operator &=(vllong4& a, const vllong4& b) { return a = a & b; }
+ __forceinline vllong4& operator &=(vllong4& a, long long b) { return a = a & b; }
+
+ __forceinline vllong4& operator |=(vllong4& a, const vllong4& b) { return a = a | b; }
+ __forceinline vllong4& operator |=(vllong4& a, long long b) { return a = a | b; }
+
+ __forceinline vllong4& operator <<=(vllong4& a, long long b) { return a = a << b; }
+ //__forceinline vllong4& operator >>=(vllong4& a, long long b) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboold4 operator ==(const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboold4 operator !=(const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboold4 operator < (const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboold4 operator >=(const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboold4 operator > (const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboold4 operator <=(const vllong4& a, const vllong4& b) { return _mm256_cmp_epi64_mask(a,b,_MM_CMPINT_LE); }
+#else
+ __forceinline vboold4 operator ==(const vllong4& a, const vllong4& b) { return _mm256_cmpeq_epi64(a,b); }
+ __forceinline vboold4 operator !=(const vllong4& a, const vllong4& b) { return !(a == b); }
+ __forceinline vboold4 operator > (const vllong4& a, const vllong4& b) { return _mm256_cmpgt_epi64(a,b); }
+ __forceinline vboold4 operator < (const vllong4& a, const vllong4& b) { return _mm256_cmpgt_epi64(b,a); }
+ __forceinline vboold4 operator >=(const vllong4& a, const vllong4& b) { return !(a < b); }
+ __forceinline vboold4 operator <=(const vllong4& a, const vllong4& b) { return !(a > b); }
+#endif
+
+ __forceinline vboold4 operator ==(const vllong4& a, long long b) { return a == vllong4(b); }
+ __forceinline vboold4 operator ==(long long a, const vllong4& b) { return vllong4(a) == b; }
+
+ __forceinline vboold4 operator !=(const vllong4& a, long long b) { return a != vllong4(b); }
+ __forceinline vboold4 operator !=(long long a, const vllong4& b) { return vllong4(a) != b; }
+
+ __forceinline vboold4 operator > (const vllong4& a, long long b) { return a > vllong4(b); }
+ __forceinline vboold4 operator > (long long a, const vllong4& b) { return vllong4(a) > b; }
+
+ __forceinline vboold4 operator < (const vllong4& a, long long b) { return a < vllong4(b); }
+ __forceinline vboold4 operator < (long long a, const vllong4& b) { return vllong4(a) < b; }
+
+ __forceinline vboold4 operator >=(const vllong4& a, long long b) { return a >= vllong4(b); }
+ __forceinline vboold4 operator >=(long long a, const vllong4& b) { return vllong4(a) >= b; }
+
+ __forceinline vboold4 operator <=(const vllong4& a, long long b) { return a <= vllong4(b); }
+ __forceinline vboold4 operator <=(long long a, const vllong4& b) { return vllong4(a) <= b; }
+
+ __forceinline vboold4 eq(const vllong4& a, const vllong4& b) { return a == b; }
+ __forceinline vboold4 ne(const vllong4& a, const vllong4& b) { return a != b; }
+ __forceinline vboold4 lt(const vllong4& a, const vllong4& b) { return a < b; }
+ __forceinline vboold4 ge(const vllong4& a, const vllong4& b) { return a >= b; }
+ __forceinline vboold4 gt(const vllong4& a, const vllong4& b) { return a > b; }
+ __forceinline vboold4 le(const vllong4& a, const vllong4& b) { return a <= b; }
+
+#if defined(__AVX512VL__)
+ __forceinline vboold4 eq(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_EQ); }
+ __forceinline vboold4 ne(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_NE); }
+ __forceinline vboold4 lt(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_LT); }
+ __forceinline vboold4 ge(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_GE); }
+ __forceinline vboold4 gt(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_GT); }
+ __forceinline vboold4 le(const vboold4& mask, const vllong4& a, const vllong4& b) { return _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_LE); }
+#else
+ __forceinline vboold4 eq(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a == b); }
+ __forceinline vboold4 ne(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a != b); }
+ __forceinline vboold4 lt(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a < b); }
+ __forceinline vboold4 ge(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a >= b); }
+ __forceinline vboold4 gt(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a > b); }
+ __forceinline vboold4 le(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a <= b); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int i0, int i1>
+ __forceinline vllong4 shuffle(const vllong4& v) {
+ return _mm256_castpd_si256(_mm256_permute_pd(_mm256_castsi256_pd(v), (i1 << 3) | (i0 << 2) | (i1 << 1) | i0));
+ }
+
+ template<int i>
+ __forceinline vllong4 shuffle(const vllong4& v) {
+ return shuffle<i, i>(v);
+ }
+
+ template<int i0, int i1>
+ __forceinline vllong4 shuffle2(const vllong4& v) {
+ return _mm256_castpd_si256(_mm256_permute2f128_pd(_mm256_castsi256_pd(v), _mm256_castsi256_pd(v), (i1 << 4) | i0));
+ }
+
+ __forceinline long long toScalar(const vllong4& v) {
+ return _mm_cvtsi128_si64(_mm256_castsi256_si128(v));
+ }
+
+#if defined(__AVX512VL__)
+ __forceinline vllong4 permute(const vllong4& a, const __m256i& index) {
+ // workaround for GCC 7.x
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
+ return _mm256_permutex2var_epi64(a,index,a);
+#else
+ return _mm256_permutexvar_epi64(index,a);
+#endif
+ }
+
+ __forceinline vllong4 permutex2var(const vllong4& index, const vllong4& a, const vllong4& b) {
+ return _mm256_permutex2var_epi64(a,index,b);
+ }
+
+#endif
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ __forceinline vllong4 vreduce_and2(const vllong4& x) { return x & shuffle<1,0>(x); }
+ __forceinline vllong4 vreduce_and (const vllong4& y) { const vllong4 x = vreduce_and2(y); return x & shuffle2<1,0>(x); }
+
+ __forceinline vllong4 vreduce_or2(const vllong4& x) { return x | shuffle<1,0>(x); }
+ __forceinline vllong4 vreduce_or (const vllong4& y) { const vllong4 x = vreduce_or2(y); return x | shuffle2<1,0>(x); }
+
+ __forceinline vllong4 vreduce_add2(const vllong4& x) { return x + shuffle<1,0>(x); }
+ __forceinline vllong4 vreduce_add (const vllong4& y) { const vllong4 x = vreduce_add2(y); return x + shuffle2<1,0>(x); }
+
+ __forceinline long long reduce_add(const vllong4& a) { return toScalar(vreduce_add(a)); }
+ __forceinline long long reduce_or (const vllong4& a) { return toScalar(vreduce_or(a)); }
+ __forceinline long long reduce_and(const vllong4& a) { return toScalar(vreduce_and(a)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vllong4& v)
+ {
+ cout << "<" << v[0];
+ for (size_t i=1; i<4; i++) cout << ", " << v[i];
+ cout << ">";
+ return cout;
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vllong8_avx512.h b/thirdparty/embree/common/simd/vllong8_avx512.h
new file mode 100644
index 0000000000..ee69411637
--- /dev/null
+++ b/thirdparty/embree/common/simd/vllong8_avx512.h
@@ -0,0 +1,358 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX-512 64-bit long long type */
+ template<>
+ struct vllong<8>
+ {
+ ALIGNED_STRUCT_(64);
+
+ typedef vboold8 Bool;
+
+ enum { size = 8 }; // number of SIMD elements
+ union { // data
+ __m512i v;
+ long long i[8];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong() {}
+ __forceinline vllong(const vllong8& t) { v = t.v; }
+ __forceinline vllong8& operator =(const vllong8& f) { v = f.v; return *this; }
+
+ __forceinline vllong(const __m512i& t) { v = t; }
+ __forceinline operator __m512i() const { return v; }
+ __forceinline operator __m256i() const { return _mm512_castsi512_si256(v); }
+
+ __forceinline vllong(long long i) {
+ v = _mm512_set1_epi64(i);
+ }
+
+ __forceinline vllong(long long a, long long b, long long c, long long d) {
+ v = _mm512_set4_epi64(d,c,b,a);
+ }
+
+ __forceinline vllong(long long a0, long long a1, long long a2, long long a3,
+ long long a4, long long a5, long long a6, long long a7)
+ {
+ v = _mm512_set_epi64(a7,a6,a5,a4,a3,a2,a1,a0);
+ }
+
+ __forceinline vllong(const vllong<4>& i) {
+ v = _mm512_broadcast_i64x4(i);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong(ZeroTy) : v(_mm512_setzero_epi32()) {}
+ __forceinline vllong(OneTy) : v(_mm512_set1_epi64(1)) {}
+ __forceinline vllong(StepTy) : v(_mm512_set_epi64(7,6,5,4,3,2,1,0)) {}
+ __forceinline vllong(ReverseStepTy) : v(_mm512_setr_epi64(7,6,5,4,3,2,1,0)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline void store_nt(void* __restrict__ ptr, const vllong8& a) {
+ _mm512_stream_si512((__m512i*)ptr,a);
+ }
+
+ static __forceinline vllong8 loadu(const void* addr) {
+ return _mm512_loadu_si512(addr);
+ }
+
+ static __forceinline vllong8 load(const vllong8* addr) {
+ return _mm512_load_si512(addr);
+ }
+
+ static __forceinline vllong8 load(const long long* addr) {
+ return _mm512_load_si512(addr);
+ }
+
+ static __forceinline vllong8 load(const unsigned char* ptr) {
+ return _mm512_cvtepu8_epi64(*(__m128i*)ptr);
+ }
+
+ static __forceinline void store(void* ptr, const vllong8& v) {
+ _mm512_store_si512(ptr,v);
+ }
+
+ static __forceinline void storeu(void* ptr, const vllong8& v) {
+ _mm512_storeu_si512(ptr,v);
+ }
+
+ static __forceinline void storeu(const vboold8& mask, long long* ptr, const vllong8& f) {
+ _mm512_mask_storeu_epi64(ptr,mask,f);
+ }
+
+ static __forceinline void store(const vboold8& mask, void* addr, const vllong8& v2) {
+ _mm512_mask_store_epi64(addr,mask,v2);
+ }
+
+ static __forceinline vllong8 compact(const vboold8& mask, vllong8& v) {
+ return _mm512_mask_compress_epi64(v,mask,v);
+ }
+
+ static __forceinline vllong8 compact(const vboold8& mask, const vllong8& a, vllong8& b) {
+ return _mm512_mask_compress_epi64(a,mask,b);
+ }
+
+ static __forceinline vllong8 expand(const vboold8& mask, const vllong8& a, vllong8& b) {
+ return _mm512_mask_expand_epi64(b,mask,a);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline long long& operator [](size_t index) { assert(index < 8); return i[index]; }
+ __forceinline const long long& operator [](size_t index) const { assert(index < 8); return i[index]; }
+
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold8 asBool(const vllong8& a) { return _mm512_movepi64_mask(a); }
+
+ __forceinline vllong8 operator +(const vllong8& a) { return a; }
+ __forceinline vllong8 operator -(const vllong8& a) { return _mm512_sub_epi64(_mm512_setzero_epi32(), a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong8 operator +(const vllong8& a, const vllong8& b) { return _mm512_add_epi64(a, b); }
+ __forceinline vllong8 operator +(const vllong8& a, long long b) { return a + vllong8(b); }
+ __forceinline vllong8 operator +(long long a, const vllong8& b) { return vllong8(a) + b; }
+
+ __forceinline vllong8 operator -(const vllong8& a, const vllong8& b) { return _mm512_sub_epi64(a, b); }
+ __forceinline vllong8 operator -(const vllong8& a, long long b) { return a - vllong8(b); }
+ __forceinline vllong8 operator -(long long a, const vllong8& b) { return vllong8(a) - b; }
+
+ __forceinline vllong8 operator *(const vllong8& a, const vllong8& b) { return _mm512_mullo_epi64(a, b); }
+ __forceinline vllong8 operator *(const vllong8& a, long long b) { return a * vllong8(b); }
+ __forceinline vllong8 operator *(long long a, const vllong8& b) { return vllong8(a) * b; }
+
+ __forceinline vllong8 operator &(const vllong8& a, const vllong8& b) { return _mm512_and_epi64(a, b); }
+ __forceinline vllong8 operator &(const vllong8& a, long long b) { return a & vllong8(b); }
+ __forceinline vllong8 operator &(long long a, const vllong8& b) { return vllong8(a) & b; }
+
+ __forceinline vllong8 operator |(const vllong8& a, const vllong8& b) { return _mm512_or_epi64(a, b); }
+ __forceinline vllong8 operator |(const vllong8& a, long long b) { return a | vllong8(b); }
+ __forceinline vllong8 operator |(long long a, const vllong8& b) { return vllong8(a) | b; }
+
+ __forceinline vllong8 operator ^(const vllong8& a, const vllong8& b) { return _mm512_xor_epi64(a, b); }
+ __forceinline vllong8 operator ^(const vllong8& a, long long b) { return a ^ vllong8(b); }
+ __forceinline vllong8 operator ^(long long a, const vllong8& b) { return vllong8(a) ^ b; }
+
+ __forceinline vllong8 operator <<(const vllong8& a, long long n) { return _mm512_slli_epi64(a, n); }
+ __forceinline vllong8 operator >>(const vllong8& a, long long n) { return _mm512_srai_epi64(a, n); }
+
+ __forceinline vllong8 operator <<(const vllong8& a, const vllong8& n) { return _mm512_sllv_epi64(a, n); }
+ __forceinline vllong8 operator >>(const vllong8& a, const vllong8& n) { return _mm512_srav_epi64(a, n); }
+
+ __forceinline vllong8 sll (const vllong8& a, long long b) { return _mm512_slli_epi64(a, b); }
+ __forceinline vllong8 sra (const vllong8& a, long long b) { return _mm512_srai_epi64(a, b); }
+ __forceinline vllong8 srl (const vllong8& a, long long b) { return _mm512_srli_epi64(a, b); }
+
+ __forceinline vllong8 min(const vllong8& a, const vllong8& b) { return _mm512_min_epi64(a, b); }
+ __forceinline vllong8 min(const vllong8& a, long long b) { return min(a,vllong8(b)); }
+ __forceinline vllong8 min(long long a, const vllong8& b) { return min(vllong8(a),b); }
+
+ __forceinline vllong8 max(const vllong8& a, const vllong8& b) { return _mm512_max_epi64(a, b); }
+ __forceinline vllong8 max(const vllong8& a, long long b) { return max(a,vllong8(b)); }
+ __forceinline vllong8 max(long long a, const vllong8& b) { return max(vllong8(a),b); }
+
+ __forceinline vllong8 mask_add(const vboold8& m, const vllong8& c, const vllong8& a, const vllong8& b) { return _mm512_mask_add_epi64(c,m,a,b); }
+ __forceinline vllong8 mask_sub(const vboold8& m, const vllong8& c, const vllong8& a, const vllong8& b) { return _mm512_mask_sub_epi64(c,m,a,b); }
+
+ __forceinline vllong8 mask_and(const vboold8& m, const vllong8& c, const vllong8& a, const vllong8& b) { return _mm512_mask_and_epi64(c,m,a,b); }
+ __forceinline vllong8 mask_or (const vboold8& m, const vllong8& c, const vllong8& a, const vllong8& b) { return _mm512_mask_or_epi64(c,m,a,b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong8& operator +=(vllong8& a, const vllong8& b) { return a = a + b; }
+ __forceinline vllong8& operator +=(vllong8& a, long long b) { return a = a + b; }
+
+ __forceinline vllong8& operator -=(vllong8& a, const vllong8& b) { return a = a - b; }
+ __forceinline vllong8& operator -=(vllong8& a, long long b) { return a = a - b; }
+
+ __forceinline vllong8& operator *=(vllong8& a, const vllong8& b) { return a = a * b; }
+ __forceinline vllong8& operator *=(vllong8& a, long long b) { return a = a * b; }
+
+ __forceinline vllong8& operator &=(vllong8& a, const vllong8& b) { return a = a & b; }
+ __forceinline vllong8& operator &=(vllong8& a, long long b) { return a = a & b; }
+
+ __forceinline vllong8& operator |=(vllong8& a, const vllong8& b) { return a = a | b; }
+ __forceinline vllong8& operator |=(vllong8& a, long long b) { return a = a | b; }
+
+ __forceinline vllong8& operator <<=(vllong8& a, long long b) { return a = a << b; }
+ __forceinline vllong8& operator >>=(vllong8& a, long long b) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboold8 operator ==(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboold8 operator ==(const vllong8& a, long long b) { return a == vllong8(b); }
+ __forceinline vboold8 operator ==(long long a, const vllong8& b) { return vllong8(a) == b; }
+
+ __forceinline vboold8 operator !=(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboold8 operator !=(const vllong8& a, long long b) { return a != vllong8(b); }
+ __forceinline vboold8 operator !=(long long a, const vllong8& b) { return vllong8(a) != b; }
+
+ __forceinline vboold8 operator < (const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboold8 operator < (const vllong8& a, long long b) { return a < vllong8(b); }
+ __forceinline vboold8 operator < (long long a, const vllong8& b) { return vllong8(a) < b; }
+
+ __forceinline vboold8 operator >=(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboold8 operator >=(const vllong8& a, long long b) { return a >= vllong8(b); }
+ __forceinline vboold8 operator >=(long long a, const vllong8& b) { return vllong8(a) >= b; }
+
+ __forceinline vboold8 operator > (const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboold8 operator > (const vllong8& a, long long b) { return a > vllong8(b); }
+ __forceinline vboold8 operator > (long long a, const vllong8& b) { return vllong8(a) > b; }
+
+ __forceinline vboold8 operator <=(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_LE); }
+ __forceinline vboold8 operator <=(const vllong8& a, long long b) { return a <= vllong8(b); }
+ __forceinline vboold8 operator <=(long long a, const vllong8& b) { return vllong8(a) <= b; }
+
+ __forceinline vboold8 eq(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboold8 ne(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboold8 lt(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboold8 ge(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboold8 gt(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboold8 le(const vllong8& a, const vllong8& b) { return _mm512_cmp_epi64_mask(a,b,_MM_CMPINT_LE); }
+
+ __forceinline vboold8 eq(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_EQ); }
+ __forceinline vboold8 ne(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_NE); }
+ __forceinline vboold8 lt(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_LT); }
+ __forceinline vboold8 ge(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_GE); }
+ __forceinline vboold8 gt(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_GT); }
+ __forceinline vboold8 le(const vboold8 mask, const vllong8& a, const vllong8& b) { return _mm512_mask_cmp_epi64_mask(mask,a,b,_MM_CMPINT_LE); }
+
+ __forceinline vllong8 select(const vboold8& m, const vllong8& t, const vllong8& f) {
+ return _mm512_mask_or_epi64(f,m,t,t);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int i0, int i1>
+ __forceinline vllong8 shuffle(const vllong8& v) {
+ return _mm512_castpd_si512(_mm512_permute_pd(_mm512_castsi512_pd(v), (i1 << 7) | (i0 << 6) | (i1 << 5) | (i0 << 4) | (i1 << 3) | (i0 << 2) | (i1 << 1) | i0));
+ }
+
+ template<int i>
+ __forceinline vllong8 shuffle(const vllong8& v) {
+ return shuffle<i, i>(v);
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vllong8 shuffle(const vllong8& v) {
+ return _mm512_permutex_epi64(v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i0, int i1>
+ __forceinline vllong8 shuffle4(const vllong8& v) {
+ return _mm512_shuffle_i64x2(v, v, _MM_SHUFFLE(i1*2+1, i1*2, i0*2+1, i0*2));
+ }
+
+ template<int i>
+ __forceinline vllong8 shuffle4(const vllong8& v) {
+ return shuffle4<i, i>(v);
+ }
+
+ template<int i>
+ __forceinline vllong8 align_shift_right(const vllong8& a, const vllong8& b) {
+ return _mm512_alignr_epi64(a, b, i);
+ };
+
+ __forceinline long long toScalar(const vllong8& v) {
+ return _mm_cvtsi128_si64(_mm512_castsi512_si128(v));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong8 vreduce_min2(vllong8 x) { return min(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vllong8 vreduce_min4(vllong8 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vllong8 vreduce_min (vllong8 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0>(x)); }
+
+ __forceinline vllong8 vreduce_max2(vllong8 x) { return max(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vllong8 vreduce_max4(vllong8 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vllong8 vreduce_max (vllong8 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0>(x)); }
+
+ __forceinline vllong8 vreduce_and2(vllong8 x) { return x & shuffle<1,0,3,2>(x); }
+ __forceinline vllong8 vreduce_and4(vllong8 x) { x = vreduce_and2(x); return x & shuffle<2,3,0,1>(x); }
+ __forceinline vllong8 vreduce_and (vllong8 x) { x = vreduce_and4(x); return x & shuffle4<1,0>(x); }
+
+ __forceinline vllong8 vreduce_or2(vllong8 x) { return x | shuffle<1,0,3,2>(x); }
+ __forceinline vllong8 vreduce_or4(vllong8 x) { x = vreduce_or2(x); return x | shuffle<2,3,0,1>(x); }
+ __forceinline vllong8 vreduce_or (vllong8 x) { x = vreduce_or4(x); return x | shuffle4<1,0>(x); }
+
+ __forceinline vllong8 vreduce_add2(vllong8 x) { return x + shuffle<1,0,3,2>(x); }
+ __forceinline vllong8 vreduce_add4(vllong8 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
+ __forceinline vllong8 vreduce_add (vllong8 x) { x = vreduce_add4(x); return x + shuffle4<1,0>(x); }
+
+ __forceinline long long reduce_min(const vllong8& v) { return toScalar(vreduce_min(v)); }
+ __forceinline long long reduce_max(const vllong8& v) { return toScalar(vreduce_max(v)); }
+ __forceinline long long reduce_and(const vllong8& v) { return toScalar(vreduce_and(v)); }
+ __forceinline long long reduce_or (const vllong8& v) { return toScalar(vreduce_or (v)); }
+ __forceinline long long reduce_add(const vllong8& v) { return toScalar(vreduce_add(v)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Memory load and store operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vllong8 permute(const vllong8& v, const vllong8& index) {
+ return _mm512_permutexvar_epi64(index,v);
+ }
+
+ __forceinline vllong8 reverse(const vllong8& a) {
+ return permute(a,vllong8(reverse_step));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vllong8& v)
+ {
+ cout << "<" << v[0];
+ for (size_t i=1; i<8; i++) cout << ", " << v[i];
+ cout << ">";
+ return cout;
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vuint16_avx512.h b/thirdparty/embree/common/simd/vuint16_avx512.h
new file mode 100644
index 0000000000..c9eb6682ff
--- /dev/null
+++ b/thirdparty/embree/common/simd/vuint16_avx512.h
@@ -0,0 +1,424 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 16-wide AVX-512 unsigned integer type */
+ template<>
+ struct vuint<16>
+ {
+ ALIGNED_STRUCT_(64);
+
+ typedef vboolf16 Bool;
+ typedef vuint16 UInt;
+ typedef vfloat16 Float;
+
+ enum { size = 16 }; // number of SIMD elements
+ union { // data
+ __m512i v;
+ unsigned int i[16];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint() {}
+ __forceinline vuint(const vuint16& t) { v = t.v; }
+ __forceinline vuint16& operator =(const vuint16& f) { v = f.v; return *this; }
+
+ __forceinline vuint(const __m512i& t) { v = t; }
+ __forceinline operator __m512i() const { return v; }
+ __forceinline operator __m256i() const { return _mm512_castsi512_si256(v); }
+
+ __forceinline vuint(unsigned int i) {
+ v = _mm512_set1_epi32(i);
+ }
+
+ __forceinline vuint(const vuint4& i) {
+ v = _mm512_broadcast_i32x4(i);
+ }
+
+ __forceinline vuint(const vuint8& i) {
+ v = _mm512_castps_si512(_mm512_castpd_ps(_mm512_broadcast_f64x4(_mm256_castsi256_pd(i))));
+ }
+
+ __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) {
+ v = _mm512_set4_epi32(d,c,b,a);
+ }
+
+ __forceinline vuint(unsigned int a0 , unsigned int a1 , unsigned int a2 , unsigned int a3,
+ unsigned int a4 , unsigned int a5 , unsigned int a6 , unsigned int a7,
+ unsigned int a8 , unsigned int a9 , unsigned int a10, unsigned int a11,
+ unsigned int a12, unsigned int a13, unsigned int a14, unsigned int a15)
+ {
+ v = _mm512_set_epi32(a15,a14,a13,a12,a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0);
+ }
+
+ __forceinline explicit vuint(const __m512& f) {
+ v = _mm512_cvtps_epu32(f);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint(ZeroTy) : v(_mm512_setzero_epi32()) {}
+ __forceinline vuint(OneTy) : v(_mm512_set1_epi32(1)) {}
+ __forceinline vuint(StepTy) : v(_mm512_set_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
+ __forceinline vuint(ReverseStepTy) : v(_mm512_setr_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline void store_nt(void* __restrict__ ptr, const vuint16& a) {
+ _mm512_stream_si512((__m512i*)ptr,a);
+ }
+
+ static __forceinline vuint16 loadu(const void* addr)
+ {
+ return _mm512_loadu_si512(addr);
+ }
+
+ static __forceinline vuint16 loadu(const unsigned char* ptr) { return _mm512_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)); }
+ static __forceinline vuint16 loadu(const unsigned short* ptr) { return _mm512_cvtepu16_epi32(_mm256_loadu_si256((__m256i*)ptr)); }
+
+ static __forceinline vuint16 load(const vuint16* addr) {
+ return _mm512_load_si512(addr);
+ }
+
+ static __forceinline vuint16 load(const unsigned int* addr) {
+ return _mm512_load_si512(addr);
+ }
+
+ static __forceinline vuint16 load(unsigned short* ptr) { return _mm512_cvtepu16_epi32(*(__m256i*)ptr); }
+
+
+ static __forceinline void store(void* ptr, const vuint16& v) {
+ _mm512_store_si512(ptr,v);
+ }
+
+ static __forceinline void storeu(void* ptr, const vuint16& v) {
+ _mm512_storeu_si512(ptr,v);
+ }
+
+ static __forceinline void storeu(const vboolf16& mask, void* ptr, const vuint16& f) {
+ _mm512_mask_storeu_epi32(ptr,mask,f);
+ }
+
+ static __forceinline void store(const vboolf16& mask, void* addr, const vuint16& v2) {
+ _mm512_mask_store_epi32(addr,mask,v2);
+ }
+
+ static __forceinline vuint16 compact(const vboolf16& mask, vuint16& v) {
+ return _mm512_mask_compress_epi32(v,mask,v);
+ }
+
+ static __forceinline vuint16 compact(const vboolf16& mask, const vuint16& a, vuint16& b) {
+ return _mm512_mask_compress_epi32(a,mask,b);
+ }
+
+ static __forceinline vuint16 expand(const vboolf16& mask, const vuint16& a, vuint16& b) {
+ return _mm512_mask_expand_epi32(b,mask,a);
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint16 gather(const unsigned int* ptr, const vint16& index) {
+ return _mm512_i32gather_epi32(index,ptr,scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint16 gather(const vboolf16& mask, const unsigned int* ptr, const vint16& index) {
+ return _mm512_mask_i32gather_epi32(_mm512_undefined_epi32(),mask,index,ptr,scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint16 gather(const vboolf16& mask, vuint16& dest, const unsigned int* ptr, const vint16& index) {
+ return _mm512_mask_i32gather_epi32(dest,mask,index,ptr,scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(unsigned int* ptr, const vint16& index, const vuint16& v) {
+ _mm512_i32scatter_epi32((int*)ptr,index,v,scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf16& mask, unsigned int* ptr, const vint16& index, const vuint16& v) {
+ _mm512_mask_i32scatter_epi32((int*)ptr,mask,index,v,scale);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline unsigned int& operator [](size_t index) { assert(index < 16); return i[index]; }
+ __forceinline const unsigned int& operator [](size_t index) const { assert(index < 16); return i[index]; }
+
+ __forceinline unsigned int uint (size_t index) const { assert(index < 16); return ((unsigned int*)i)[index]; }
+ __forceinline size_t& uint64_t(size_t index) const { assert(index < 8); return ((size_t*)i)[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16 asBool(const vuint16& a) { return _mm512_movepi32_mask(a); }
+
+ __forceinline vuint16 operator +(const vuint16& a) { return a; }
+ __forceinline vuint16 operator -(const vuint16& a) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint16 operator +(const vuint16& a, const vuint16& b) { return _mm512_add_epi32(a, b); }
+ __forceinline vuint16 operator +(const vuint16& a, unsigned int b) { return a + vuint16(b); }
+ __forceinline vuint16 operator +(unsigned int a, const vuint16& b) { return vuint16(a) + b; }
+
+ __forceinline vuint16 operator -(const vuint16& a, const vuint16& b) { return _mm512_sub_epi32(a, b); }
+ __forceinline vuint16 operator -(const vuint16& a, unsigned int b) { return a - vuint16(b); }
+ __forceinline vuint16 operator -(unsigned int a, const vuint16& b) { return vuint16(a) - b; }
+
+ __forceinline vuint16 operator *(const vuint16& a, const vuint16& b) { return _mm512_mul_epu32(a, b); }
+ __forceinline vuint16 operator *(const vuint16& a, unsigned int b) { return a * vuint16(b); }
+ __forceinline vuint16 operator *(unsigned int a, const vuint16& b) { return vuint16(a) * b; }
+
+ __forceinline vuint16 operator &(const vuint16& a, const vuint16& b) { return _mm512_and_epi32(a, b); }
+ __forceinline vuint16 operator &(const vuint16& a, unsigned int b) { return a & vuint16(b); }
+ __forceinline vuint16 operator &(unsigned int a, const vuint16& b) { return vuint16(a) & b; }
+
+ __forceinline vuint16 operator |(const vuint16& a, const vuint16& b) { return _mm512_or_epi32(a, b); }
+ __forceinline vuint16 operator |(const vuint16& a, unsigned int b) { return a | vuint16(b); }
+ __forceinline vuint16 operator |(unsigned int a, const vuint16& b) { return vuint16(a) | b; }
+
+ __forceinline vuint16 operator ^(const vuint16& a, const vuint16& b) { return _mm512_xor_epi32(a, b); }
+ __forceinline vuint16 operator ^(const vuint16& a, unsigned int b) { return a ^ vuint16(b); }
+ __forceinline vuint16 operator ^(unsigned int a, const vuint16& b) { return vuint16(a) ^ b; }
+
+ __forceinline vuint16 operator <<(const vuint16& a, unsigned int n) { return _mm512_slli_epi32(a, n); }
+ __forceinline vuint16 operator >>(const vuint16& a, unsigned int n) { return _mm512_srli_epi32(a, n); }
+
+ __forceinline vuint16 operator <<(const vuint16& a, const vuint16& n) { return _mm512_sllv_epi32(a, n); }
+ __forceinline vuint16 operator >>(const vuint16& a, const vuint16& n) { return _mm512_srlv_epi32(a, n); }
+
+ __forceinline vuint16 sll (const vuint16& a, unsigned int b) { return _mm512_slli_epi32(a, b); }
+ __forceinline vuint16 sra (const vuint16& a, unsigned int b) { return _mm512_srai_epi32(a, b); }
+ __forceinline vuint16 srl (const vuint16& a, unsigned int b) { return _mm512_srli_epi32(a, b); }
+
+ __forceinline vuint16 min(const vuint16& a, const vuint16& b) { return _mm512_min_epu32(a, b); }
+ __forceinline vuint16 min(const vuint16& a, unsigned int b) { return min(a,vuint16(b)); }
+ __forceinline vuint16 min(unsigned int a, const vuint16& b) { return min(vuint16(a),b); }
+
+ __forceinline vuint16 max(const vuint16& a, const vuint16& b) { return _mm512_max_epu32(a, b); }
+ __forceinline vuint16 max(const vuint16& a, unsigned int b) { return max(a,vuint16(b)); }
+ __forceinline vuint16 max(unsigned int a, const vuint16& b) { return max(vuint16(a),b); }
+
+ __forceinline vuint16 mask_add(const vboolf16& mask, vuint16& c, const vuint16& a, const vuint16& b) { return _mm512_mask_add_epi32(c,mask,a,b); }
+ __forceinline vuint16 mask_sub(const vboolf16& mask, vuint16& c, const vuint16& a, const vuint16& b) { return _mm512_mask_sub_epi32(c,mask,a,b); }
+
+ __forceinline vuint16 mask_and(const vboolf16& m, vuint16& c, const vuint16& a, const vuint16& b) { return _mm512_mask_and_epi32(c,m,a,b); }
+ __forceinline vuint16 mask_or (const vboolf16& m, vuint16& c, const vuint16& a, const vuint16& b) { return _mm512_mask_or_epi32(c,m,a,b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint16& operator +=(vuint16& a, const vuint16& b) { return a = a + b; }
+ __forceinline vuint16& operator +=(vuint16& a, unsigned int b) { return a = a + b; }
+
+ __forceinline vuint16& operator -=(vuint16& a, const vuint16& b) { return a = a - b; }
+ __forceinline vuint16& operator -=(vuint16& a, unsigned int b) { return a = a - b; }
+
+ __forceinline vuint16& operator *=(vuint16& a, const vuint16& b) { return a = a * b; }
+ __forceinline vuint16& operator *=(vuint16& a, unsigned int b) { return a = a * b; }
+
+ __forceinline vuint16& operator &=(vuint16& a, const vuint16& b) { return a = a & b; }
+ __forceinline vuint16& operator &=(vuint16& a, unsigned int b) { return a = a & b; }
+
+ __forceinline vuint16& operator |=(vuint16& a, const vuint16& b) { return a = a | b; }
+ __forceinline vuint16& operator |=(vuint16& a, unsigned int b) { return a = a | b; }
+
+ __forceinline vuint16& operator <<=(vuint16& a, unsigned int b) { return a = a << b; }
+ __forceinline vuint16& operator >>=(vuint16& a, unsigned int b) { return a = a >> b; }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf16 operator ==(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 operator ==(const vuint16& a, unsigned int b) { return a == vuint16(b); }
+ __forceinline vboolf16 operator ==(unsigned int a, const vuint16& b) { return vuint16(a) == b; }
+
+ __forceinline vboolf16 operator !=(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 operator !=(const vuint16& a, unsigned int b) { return a != vuint16(b); }
+ __forceinline vboolf16 operator !=(unsigned int a, const vuint16& b) { return vuint16(a) != b; }
+
+ __forceinline vboolf16 operator < (const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 operator < (const vuint16& a, unsigned int b) { return a < vuint16(b); }
+ __forceinline vboolf16 operator < (unsigned int a, const vuint16& b) { return vuint16(a) < b; }
+
+ __forceinline vboolf16 operator >=(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 operator >=(const vuint16& a, unsigned int b) { return a >= vuint16(b); }
+ __forceinline vboolf16 operator >=(unsigned int a, const vuint16& b) { return vuint16(a) >= b; }
+
+ __forceinline vboolf16 operator > (const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 operator > (const vuint16& a, unsigned int b) { return a > vuint16(b); }
+ __forceinline vboolf16 operator > (unsigned int a, const vuint16& b) { return vuint16(a) > b; }
+
+ __forceinline vboolf16 operator <=(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
+ __forceinline vboolf16 operator <=(const vuint16& a, unsigned int b) { return a <= vuint16(b); }
+ __forceinline vboolf16 operator <=(unsigned int a, const vuint16& b) { return vuint16(a) <= b; }
+
+ __forceinline vboolf16 eq(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 ne(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 lt(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 ge(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 gt(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 le(const vuint16& a, const vuint16& b) { return _mm512_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
+
+ __forceinline vboolf16 eq(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf16 ne(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf16 lt(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf16 ge(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf16 gt(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf16 le(const vboolf16 mask, const vuint16& a, const vuint16& b) { return _mm512_mask_cmp_epu32_mask(mask,a,b,_MM_CMPINT_LE); }
+
+
+ __forceinline vuint16 select(const vboolf16& m, const vuint16& t, const vuint16& f) {
+ return _mm512_mask_or_epi32(f,m,t,t);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int i>
+ __forceinline vuint16 shuffle(const vuint16& v) {
+ return _mm512_castps_si512(_mm512_permute_ps(_mm512_castsi512_ps(v), _MM_SHUFFLE(i, i, i, i)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint16 shuffle(const vuint16& v) {
+ return _mm512_castps_si512(_mm512_permute_ps(_mm512_castsi512_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i>
+ __forceinline vuint16 shuffle4(const vuint16& v) {
+ return _mm512_castps_si512(_mm512_shuffle_f32x4(_mm512_castsi512_ps(v), _mm512_castsi512_ps(v) ,_MM_SHUFFLE(i, i, i, i)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint16 shuffle4(const vuint16& v) {
+ return _mm512_castps_si512(_mm512_shuffle_f32x4(_mm512_castsi512_ps(v), _mm512_castsi512_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i>
+ __forceinline vuint16 align_shift_right(const vuint16& a, const vuint16& b) {
+ return _mm512_alignr_epi32(a, b, i);
+ };
+
+ __forceinline unsigned int toScalar(const vuint16& v) {
+ return _mm_cvtsi128_si32(_mm512_castsi512_si128(v));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint16 vreduce_min2(vuint16 x) { return min(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vuint16 vreduce_min4(vuint16 x) { x = vreduce_min2(x); return min(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vuint16 vreduce_min8(vuint16 x) { x = vreduce_min4(x); return min(x, shuffle4<1,0,3,2>(x)); }
+ __forceinline vuint16 vreduce_min (vuint16 x) { x = vreduce_min8(x); return min(x, shuffle4<2,3,0,1>(x)); }
+
+ __forceinline vuint16 vreduce_max2(vuint16 x) { return max(x, shuffle<1,0,3,2>(x)); }
+ __forceinline vuint16 vreduce_max4(vuint16 x) { x = vreduce_max2(x); return max(x, shuffle<2,3,0,1>(x)); }
+ __forceinline vuint16 vreduce_max8(vuint16 x) { x = vreduce_max4(x); return max(x, shuffle4<1,0,3,2>(x)); }
+ __forceinline vuint16 vreduce_max (vuint16 x) { x = vreduce_max8(x); return max(x, shuffle4<2,3,0,1>(x)); }
+
+ __forceinline vuint16 vreduce_and2(vuint16 x) { return x & shuffle<1,0,3,2>(x); }
+ __forceinline vuint16 vreduce_and4(vuint16 x) { x = vreduce_and2(x); return x & shuffle<2,3,0,1>(x); }
+ __forceinline vuint16 vreduce_and8(vuint16 x) { x = vreduce_and4(x); return x & shuffle4<1,0,3,2>(x); }
+ __forceinline vuint16 vreduce_and (vuint16 x) { x = vreduce_and8(x); return x & shuffle4<2,3,0,1>(x); }
+
+ __forceinline vuint16 vreduce_or2(vuint16 x) { return x | shuffle<1,0,3,2>(x); }
+ __forceinline vuint16 vreduce_or4(vuint16 x) { x = vreduce_or2(x); return x | shuffle<2,3,0,1>(x); }
+ __forceinline vuint16 vreduce_or8(vuint16 x) { x = vreduce_or4(x); return x | shuffle4<1,0,3,2>(x); }
+ __forceinline vuint16 vreduce_or (vuint16 x) { x = vreduce_or8(x); return x | shuffle4<2,3,0,1>(x); }
+
+ __forceinline vuint16 vreduce_add2(vuint16 x) { return x + shuffle<1,0,3,2>(x); }
+ __forceinline vuint16 vreduce_add4(vuint16 x) { x = vreduce_add2(x); return x + shuffle<2,3,0,1>(x); }
+ __forceinline vuint16 vreduce_add8(vuint16 x) { x = vreduce_add4(x); return x + shuffle4<1,0,3,2>(x); }
+ __forceinline vuint16 vreduce_add (vuint16 x) { x = vreduce_add8(x); return x + shuffle4<2,3,0,1>(x); }
+
+ __forceinline unsigned int reduce_min(const vuint16& v) { return toScalar(vreduce_min(v)); }
+ __forceinline unsigned int reduce_max(const vuint16& v) { return toScalar(vreduce_max(v)); }
+ __forceinline unsigned int reduce_and(const vuint16& v) { return toScalar(vreduce_and(v)); }
+ __forceinline unsigned int reduce_or (const vuint16& v) { return toScalar(vreduce_or (v)); }
+ __forceinline unsigned int reduce_add(const vuint16& v) { return toScalar(vreduce_add(v)); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Memory load and store operations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint16 permute(vuint16 v, vuint16 index) {
+ return _mm512_permutexvar_epi32(index,v);
+ }
+
+ __forceinline vuint16 reverse(const vuint16& a) {
+ return permute(a,vuint16(reverse_step));
+ }
+
+ __forceinline vuint16 prefix_sum(const vuint16& a)
+ {
+ const vuint16 z(zero);
+ vuint16 v = a;
+ v = v + align_shift_right<16-1>(v,z);
+ v = v + align_shift_right<16-2>(v,z);
+ v = v + align_shift_right<16-4>(v,z);
+ v = v + align_shift_right<16-8>(v,z);
+ return v;
+ }
+
+ __forceinline vuint16 reverse_prefix_sum(const vuint16& a)
+ {
+ const vuint16 z(zero);
+ vuint16 v = a;
+ v = v + align_shift_right<1>(z,v);
+ v = v + align_shift_right<2>(z,v);
+ v = v + align_shift_right<4>(z,v);
+ v = v + align_shift_right<8>(z,v);
+ return v;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vuint16& v)
+ {
+ cout << "<" << v[0];
+ for (int i=1; i<16; i++) cout << ", " << v[i];
+ cout << ">";
+ return cout;
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vuint4_sse2.h b/thirdparty/embree/common/simd/vuint4_sse2.h
new file mode 100644
index 0000000000..0601b9ab80
--- /dev/null
+++ b/thirdparty/embree/common/simd/vuint4_sse2.h
@@ -0,0 +1,426 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../math/math.h"
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 4-wide SSE integer type */
+ template<>
+ struct vuint<4>
+ {
+ ALIGNED_STRUCT_(16);
+
+ typedef vboolf4 Bool;
+ typedef vuint4 Int;
+ typedef vfloat4 Float;
+
+ enum { size = 4 }; // number of SIMD elements
+ union { __m128i v; unsigned int i[4]; }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint() {}
+ __forceinline vuint(const vuint4& a) { v = a.v; }
+ __forceinline vuint4& operator =(const vuint4& a) { v = a.v; return *this; }
+
+ __forceinline vuint(const __m128i a) : v(a) {}
+ __forceinline operator const __m128i&() const { return v; }
+ __forceinline operator __m128i&() { return v; }
+
+
+ __forceinline vuint(unsigned int a) : v(_mm_set1_epi32(a)) {}
+ __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) : v(_mm_set_epi32(d, c, b, a)) {}
+
+#if defined(__AVX512VL__)
+ __forceinline explicit vuint(__m128 a) : v(_mm_cvtps_epu32(a)) {}
+#endif
+
+#if defined(__AVX512VL__)
+ __forceinline explicit vuint(const vboolf4& a) : v(_mm_movm_epi32(a)) {}
+#else
+ __forceinline explicit vuint(const vboolf4& a) : v(_mm_castps_si128((__m128)a)) {}
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint(ZeroTy) : v(_mm_setzero_si128()) {}
+ __forceinline vuint(OneTy) : v(_mm_set1_epi32(1)) {}
+ __forceinline vuint(PosInfTy) : v(_mm_set1_epi32(unsigned(pos_inf))) {}
+ __forceinline vuint(StepTy) : v(_mm_set_epi32(3, 2, 1, 0)) {}
+ __forceinline vuint(TrueTy) { v = _mm_cmpeq_epi32(v,v); }
+ __forceinline vuint(UndefinedTy) : v(_mm_castps_si128(_mm_undefined_ps())) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vuint4 load (const void* a) { return _mm_load_si128((__m128i*)a); }
+ static __forceinline vuint4 loadu(const void* a) { return _mm_loadu_si128((__m128i*)a); }
+
+ static __forceinline void store (void* ptr, const vuint4& v) { _mm_store_si128((__m128i*)ptr,v); }
+ static __forceinline void storeu(void* ptr, const vuint4& v) { _mm_storeu_si128((__m128i*)ptr,v); }
+
+#if defined(__AVX512VL__)
+ static __forceinline vuint4 load (const vboolf4& mask, const void* ptr) { return _mm_mask_load_epi32 (_mm_setzero_si128(),mask,ptr); }
+ static __forceinline vuint4 loadu(const vboolf4& mask, const void* ptr) { return _mm_mask_loadu_epi32(_mm_setzero_si128(),mask,ptr); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vuint4& v) { _mm_mask_store_epi32 (ptr,mask,v); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vuint4& v) { _mm_mask_storeu_epi32(ptr,mask,v); }
+#elif defined(__AVX__)
+ static __forceinline vuint4 load (const vbool4& mask, const void* a) { return _mm_castps_si128(_mm_maskload_ps((float*)a,mask)); }
+ static __forceinline vuint4 loadu(const vbool4& mask, const void* a) { return _mm_castps_si128(_mm_maskload_ps((float*)a,mask)); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vuint4& i) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i)); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vuint4& i) { _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i)); }
+#else
+ static __forceinline vuint4 load (const vbool4& mask, const void* a) { return _mm_and_si128(_mm_load_si128 ((__m128i*)a),mask); }
+ static __forceinline vuint4 loadu(const vbool4& mask, const void* a) { return _mm_and_si128(_mm_loadu_si128((__m128i*)a),mask); }
+
+ static __forceinline void store (const vboolf4& mask, void* ptr, const vuint4& i) { store (ptr,select(mask,i,load (ptr))); }
+ static __forceinline void storeu(const vboolf4& mask, void* ptr, const vuint4& i) { storeu(ptr,select(mask,i,loadu(ptr))); }
+#endif
+
+#if defined(__SSE4_1__)
+ static __forceinline vuint4 load(const unsigned char* ptr) {
+ return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
+ }
+
+ static __forceinline vuint4 loadu(const unsigned char* ptr) {
+ return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr));
+ }
+
+#endif
+
+ static __forceinline vuint4 load(const unsigned short* ptr) {
+#if defined (__SSE4_1__)
+ return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr));
+#else
+ return vuint4(ptr[0],ptr[1],ptr[2],ptr[3]);
+#endif
+ }
+
+ static __forceinline vuint4 load_nt(void* ptr) {
+#if defined(__SSE4_1__)
+ return _mm_stream_load_si128((__m128i*)ptr);
+#else
+ return _mm_load_si128((__m128i*)ptr);
+#endif
+ }
+
+ static __forceinline void store_nt(void* ptr, const vuint4& v) {
+#if defined(__SSE4_1__)
+ _mm_stream_ps((float*)ptr,_mm_castsi128_ps(v));
+#else
+ _mm_store_si128((__m128i*)ptr,v);
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint4 gather(const unsigned int* ptr, const vint4& index) {
+#if defined(__AVX2__)
+ return _mm_i32gather_epi32((const int*)ptr, index, scale);
+#else
+ return vuint4(
+ *(unsigned int*)(((char*)ptr)+scale*index[0]),
+ *(unsigned int*)(((char*)ptr)+scale*index[1]),
+ *(unsigned int*)(((char*)ptr)+scale*index[2]),
+ *(unsigned int*)(((char*)ptr)+scale*index[3]));
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint4 gather(const vboolf4& mask, const unsigned int* ptr, const vint4& index) {
+ vuint4 r = zero;
+#if defined(__AVX512VL__)
+ return _mm_mmask_i32gather_epi32(r, mask, index, ptr, scale);
+#elif defined(__AVX2__)
+ return _mm_mask_i32gather_epi32(r, (const int*)ptr, index, mask, scale);
+#else
+ if (likely(mask[0])) r[0] = *(unsigned int*)(((char*)ptr)+scale*index[0]);
+ if (likely(mask[1])) r[1] = *(unsigned int*)(((char*)ptr)+scale*index[1]);
+ if (likely(mask[2])) r[2] = *(unsigned int*)(((char*)ptr)+scale*index[2]);
+ if (likely(mask[3])) r[3] = *(unsigned int*)(((char*)ptr)+scale*index[3]);
+ return r;
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const unsigned int& operator [](size_t index) const { assert(index < 4); return i[index]; }
+ __forceinline unsigned int& operator [](size_t index) { assert(index < 4); return i[index]; }
+
+ friend __forceinline vuint4 select(const vboolf4& m, const vuint4& t, const vuint4& f) {
+#if defined(__AVX512VL__)
+ return _mm_mask_blend_epi32(m, (__m128i)f, (__m128i)t);
+#elif defined(__SSE4_1__)
+ return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
+#else
+ return _mm_or_si128(_mm_and_si128(m, t), _mm_andnot_si128(m, f));
+#endif
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf4 asBool(const vuint4& a) { return _mm_movepi32_mask(a); }
+#else
+ __forceinline vboolf4 asBool(const vuint4& a) { return _mm_castsi128_ps(a); }
+#endif
+
+ __forceinline vuint4 operator +(const vuint4& a) { return a; }
+ __forceinline vuint4 operator -(const vuint4& a) { return _mm_sub_epi32(_mm_setzero_si128(), a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint4 operator +(const vuint4& a, const vuint4& b) { return _mm_add_epi32(a, b); }
+ __forceinline vuint4 operator +(const vuint4& a, unsigned int b) { return a + vuint4(b); }
+ __forceinline vuint4 operator +(unsigned int a, const vuint4& b) { return vuint4(a) + b; }
+
+ __forceinline vuint4 operator -(const vuint4& a, const vuint4& b) { return _mm_sub_epi32(a, b); }
+ __forceinline vuint4 operator -(const vuint4& a, unsigned int b) { return a - vuint4(b); }
+ __forceinline vuint4 operator -(unsigned int a, const vuint4& b) { return vuint4(a) - b; }
+
+//#if defined(__SSE4_1__)
+// __forceinline vuint4 operator *(const vuint4& a, const vuint4& b) { return _mm_mullo_epu32(a, b); }
+//#else
+// __forceinline vuint4 operator *(const vuint4& a, const vuint4& b) { return vuint4(a[0]*b[0],a[1]*b[1],a[2]*b[2],a[3]*b[3]); }
+//#endif
+// __forceinline vuint4 operator *(const vuint4& a, unsigned int b) { return a * vuint4(b); }
+// __forceinline vuint4 operator *(unsigned int a, const vuint4& b) { return vuint4(a) * b; }
+
+ __forceinline vuint4 operator &(const vuint4& a, const vuint4& b) { return _mm_and_si128(a, b); }
+ __forceinline vuint4 operator &(const vuint4& a, unsigned int b) { return a & vuint4(b); }
+ __forceinline vuint4 operator &(unsigned int a, const vuint4& b) { return vuint4(a) & b; }
+
+ __forceinline vuint4 operator |(const vuint4& a, const vuint4& b) { return _mm_or_si128(a, b); }
+ __forceinline vuint4 operator |(const vuint4& a, unsigned int b) { return a | vuint4(b); }
+ __forceinline vuint4 operator |(unsigned int a, const vuint4& b) { return vuint4(a) | b; }
+
+ __forceinline vuint4 operator ^(const vuint4& a, const vuint4& b) { return _mm_xor_si128(a, b); }
+ __forceinline vuint4 operator ^(const vuint4& a, unsigned int b) { return a ^ vuint4(b); }
+ __forceinline vuint4 operator ^(unsigned int a, const vuint4& b) { return vuint4(a) ^ b; }
+
+ __forceinline vuint4 operator <<(const vuint4& a, unsigned int n) { return _mm_slli_epi32(a, n); }
+ __forceinline vuint4 operator >>(const vuint4& a, unsigned int n) { return _mm_srli_epi32(a, n); }
+
+ __forceinline vuint4 sll (const vuint4& a, unsigned int b) { return _mm_slli_epi32(a, b); }
+ __forceinline vuint4 sra (const vuint4& a, unsigned int b) { return _mm_srai_epi32(a, b); }
+ __forceinline vuint4 srl (const vuint4& a, unsigned int b) { return _mm_srli_epi32(a, b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint4& operator +=(vuint4& a, const vuint4& b) { return a = a + b; }
+ __forceinline vuint4& operator +=(vuint4& a, unsigned int b) { return a = a + b; }
+
+ __forceinline vuint4& operator -=(vuint4& a, const vuint4& b) { return a = a - b; }
+ __forceinline vuint4& operator -=(vuint4& a, unsigned int b) { return a = a - b; }
+
+//#if defined(__SSE4_1__)
+// __forceinline vuint4& operator *=(vuint4& a, const vuint4& b) { return a = a * b; }
+// __forceinline vuint4& operator *=(vuint4& a, unsigned int b) { return a = a * b; }
+//#endif
+
+ __forceinline vuint4& operator &=(vuint4& a, const vuint4& b) { return a = a & b; }
+ __forceinline vuint4& operator &=(vuint4& a, unsigned int b) { return a = a & b; }
+
+ __forceinline vuint4& operator |=(vuint4& a, const vuint4& b) { return a = a | b; }
+ __forceinline vuint4& operator |=(vuint4& a, unsigned int b) { return a = a | b; }
+
+ __forceinline vuint4& operator <<=(vuint4& a, unsigned int b) { return a = a << b; }
+ __forceinline vuint4& operator >>=(vuint4& a, unsigned int b) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf4 operator ==(const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf4 operator !=(const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
+ //__forceinline vboolf4 operator < (const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
+ //__forceinline vboolf4 operator >=(const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
+ //__forceinline vboolf4 operator > (const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
+ //__forceinline vboolf4 operator <=(const vuint4& a, const vuint4& b) { return _mm_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
+#else
+ __forceinline vboolf4 operator ==(const vuint4& a, const vuint4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
+ __forceinline vboolf4 operator !=(const vuint4& a, const vuint4& b) { return !(a == b); }
+ //__forceinline vboolf4 operator < (const vuint4& a, const vuint4& b) { return _mm_castsi128_ps(_mm_cmplt_epu32(a, b)); }
+ //__forceinline vboolf4 operator >=(const vuint4& a, const vuint4& b) { return !(a < b); }
+ //__forceinline vboolf4 operator > (const vuint4& a, const vuint4& b) { return _mm_castsi128_ps(_mm_cmpgt_epu32(a, b)); }
+ //__forceinline vboolf4 operator <=(const vuint4& a, const vuint4& b) { return !(a > b); }
+#endif
+
+ __forceinline vboolf4 operator ==(const vuint4& a, unsigned int b) { return a == vuint4(b); }
+ __forceinline vboolf4 operator ==(unsigned int a, const vuint4& b) { return vuint4(a) == b; }
+
+ __forceinline vboolf4 operator !=(const vuint4& a, unsigned int b) { return a != vuint4(b); }
+ __forceinline vboolf4 operator !=(unsigned int a, const vuint4& b) { return vuint4(a) != b; }
+
+ //__forceinline vboolf4 operator < (const vuint4& a, unsigned int b) { return a < vuint4(b); }
+ //__forceinline vboolf4 operator < (unsigned int a, const vuint4& b) { return vuint4(a) < b; }
+
+ //__forceinline vboolf4 operator >=(const vuint4& a, unsigned int b) { return a >= vuint4(b); }
+ //__forceinline vboolf4 operator >=(unsigned int a, const vuint4& b) { return vuint4(a) >= b; }
+
+ //__forceinline vboolf4 operator > (const vuint4& a, unsigned int b) { return a > vuint4(b); }
+ //__forceinline vboolf4 operator > (unsigned int a, const vuint4& b) { return vuint4(a) > b; }
+
+ //__forceinline vboolf4 operator <=(const vuint4& a, unsigned int b) { return a <= vuint4(b); }
+ //__forceinline vboolf4 operator <=(unsigned int a, const vuint4& b) { return vuint4(a) <= b; }
+
+ __forceinline vboolf4 eq(const vuint4& a, const vuint4& b) { return a == b; }
+ __forceinline vboolf4 ne(const vuint4& a, const vuint4& b) { return a != b; }
+ //__forceinline vboolf4 lt(const vuint4& a, const vuint4& b) { return a < b; }
+ //__forceinline vboolf4 ge(const vuint4& a, const vuint4& b) { return a >= b; }
+ //__forceinline vboolf4 gt(const vuint4& a, const vuint4& b) { return a > b; }
+ //__forceinline vboolf4 le(const vuint4& a, const vuint4& b) { return a <= b; }
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf4 eq(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_EQ); }
+ __forceinline vboolf4 ne(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_NE); }
+ //__forceinline vboolf4 lt(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LT); }
+ //__forceinline vboolf4 ge(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GE); }
+ //__forceinline vboolf4 gt(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GT); }
+ //__forceinline vboolf4 le(const vboolf4& mask, const vuint4& a, const vuint4& b) { return _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LE); }
+#else
+ __forceinline vboolf4 eq(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a == b); }
+ __forceinline vboolf4 ne(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a != b); }
+ //__forceinline vboolf4 lt(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a < b); }
+ //__forceinline vboolf4 ge(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a >= b); }
+ //__forceinline vboolf4 gt(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a > b); }
+ //__forceinline vboolf4 le(const vboolf4& mask, const vuint4& a, const vuint4& b) { return mask & (a <= b); }
+#endif
+
+ template<int mask>
+ __forceinline vuint4 select(const vuint4& t, const vuint4& f) {
+#if defined(__SSE4_1__)
+ return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), mask));
+#else
+ return select(vboolf4(mask), t, f);
+#endif
+ }
+
+/*#if defined(__SSE4_1__)
+ __forceinline vuint4 min(const vuint4& a, const vuint4& b) { return _mm_min_epu32(a, b); }
+ __forceinline vuint4 max(const vuint4& a, const vuint4& b) { return _mm_max_epu32(a, b); }
+
+#else
+ __forceinline vuint4 min(const vuint4& a, const vuint4& b) { return select(a < b,a,b); }
+ __forceinline vuint4 max(const vuint4& a, const vuint4& b) { return select(a < b,b,a); }
+#endif
+
+ __forceinline vuint4 min(const vuint4& a, unsigned int b) { return min(a,vuint4(b)); }
+ __forceinline vuint4 min(unsigned int a, const vuint4& b) { return min(vuint4(a),b); }
+ __forceinline vuint4 max(const vuint4& a, unsigned int b) { return max(a,vuint4(b)); }
+ __forceinline vuint4 max(unsigned int a, const vuint4& b) { return max(vuint4(a),b); }*/
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint4 unpacklo(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
+ __forceinline vuint4 unpackhi(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint4 shuffle(const vuint4& v) {
+ return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint4 shuffle(const vuint4& a, const vuint4& b) {
+ return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+#if defined(__SSE3__)
+ template<> __forceinline vuint4 shuffle<0, 0, 2, 2>(const vuint4& v) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(v))); }
+ template<> __forceinline vuint4 shuffle<1, 1, 3, 3>(const vuint4& v) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(v))); }
+ template<> __forceinline vuint4 shuffle<0, 1, 0, 1>(const vuint4& v) { return _mm_castpd_si128(_mm_movedup_pd (_mm_castsi128_pd(v))); }
+#endif
+
+ template<int i>
+ __forceinline vuint4 shuffle(const vuint4& v) {
+ return shuffle<i,i,i,i>(v);
+ }
+
+#if defined(__SSE4_1__)
+ template<int src> __forceinline unsigned int extract(const vuint4& b) { return _mm_extract_epi32(b, src); }
+ template<int dst> __forceinline vuint4 insert(const vuint4& a, const unsigned b) { return _mm_insert_epi32(a, b, dst); }
+#else
+ template<int src> __forceinline unsigned int extract(const vuint4& b) { return b[src&3]; }
+ template<int dst> __forceinline vuint4 insert(const vuint4& a, const unsigned b) { vuint4 c = a; c[dst&3] = b; return c; }
+#endif
+
+
+ template<> __forceinline unsigned int extract<0>(const vuint4& b) { return _mm_cvtsi128_si32(b); }
+
+ __forceinline unsigned int toScalar(const vuint4& v) { return _mm_cvtsi128_si32(v); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+#if defined(__SSE4_1__)
+
+ __forceinline vuint4 vreduce_min(const vuint4& v) { vuint4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
+ __forceinline vuint4 vreduce_max(const vuint4& v) { vuint4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
+ __forceinline vuint4 vreduce_add(const vuint4& v) { vuint4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
+
+ __forceinline unsigned int reduce_min(const vuint4& v) { return toScalar(vreduce_min(v)); }
+ __forceinline unsigned int reduce_max(const vuint4& v) { return toScalar(vreduce_max(v)); }
+ __forceinline unsigned int reduce_add(const vuint4& v) { return toScalar(vreduce_add(v)); }
+
+ __forceinline size_t select_min(const vuint4& v) { return bsf(movemask(v == vreduce_min(v))); }
+ __forceinline size_t select_max(const vuint4& v) { return bsf(movemask(v == vreduce_max(v))); }
+
+ //__forceinline size_t select_min(const vboolf4& valid, const vuint4& v) { const vuint4 a = select(valid,v,vuint4(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
+ //__forceinline size_t select_max(const vboolf4& valid, const vuint4& v) { const vuint4 a = select(valid,v,vuint4(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
+
+#else
+
+ __forceinline unsigned int reduce_min(const vuint4& v) { return min(v[0],v[1],v[2],v[3]); }
+ __forceinline unsigned int reduce_max(const vuint4& v) { return max(v[0],v[1],v[2],v[3]); }
+ __forceinline unsigned int reduce_add(const vuint4& v) { return v[0]+v[1]+v[2]+v[3]; }
+
+#endif
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vuint4& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vuint8_avx.h b/thirdparty/embree/common/simd/vuint8_avx.h
new file mode 100644
index 0000000000..589cd9d731
--- /dev/null
+++ b/thirdparty/embree/common/simd/vuint8_avx.h
@@ -0,0 +1,386 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX integer type */
+ template<>
+ struct vuint<8>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboolf8 Bool;
+ typedef vuint8 Int;
+ typedef vfloat8 Float;
+
+ enum { size = 8 }; // number of SIMD elements
+ union { // data
+ __m256i v;
+ struct { __m128i vl,vh; };
+ unsigned int i[8];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint() {}
+ __forceinline vuint(const vuint8& a) { v = a.v; }
+ __forceinline vuint8& operator =(const vuint8& a) { v = a.v; return *this; }
+
+ __forceinline vuint(__m256i a) : v(a) {}
+ __forceinline operator const __m256i&() const { return v; }
+ __forceinline operator __m256i&() { return v; }
+
+ __forceinline explicit vuint(const vuint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
+ __forceinline vuint(const vuint4& a, const vuint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
+ __forceinline vuint(const __m128i& a, const __m128i& b) : vl(a), vh(b) {}
+
+ __forceinline explicit vuint(const unsigned int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
+ __forceinline vuint(unsigned int a) : v(_mm256_set1_epi32(a)) {}
+ __forceinline vuint(unsigned int a, unsigned int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
+ __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
+ __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f, unsigned int g, unsigned int vh) : v(_mm256_set_epi32(vh, g, f, e, d, c, b, a)) {}
+
+ __forceinline explicit vuint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint(ZeroTy) : v(_mm256_setzero_si256()) {}
+ __forceinline vuint(OneTy) : v(_mm256_set1_epi32(1)) {}
+ __forceinline vuint(PosInfTy) : v(_mm256_set1_epi32(0xFFFFFFFF)) {}
+ __forceinline vuint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
+ __forceinline vuint(UndefinedTy) : v(_mm256_undefined_si256()) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vuint8 load (const void* a) { return _mm256_castps_si256(_mm256_load_ps((float*)a)); }
+ static __forceinline vuint8 loadu(const void* a) { return _mm256_castps_si256(_mm256_loadu_ps((float*)a)); }
+
+ static __forceinline vuint8 load (const vboolf8& mask, const void* a) { return _mm256_castps_si256(_mm256_maskload_ps((float*)a,mask)); }
+ static __forceinline vuint8 loadu(const vboolf8& mask, const void* a) { return _mm256_castps_si256(_mm256_maskload_ps((float*)a,mask)); }
+
+ static __forceinline void store (void* ptr, const vuint8& f) { _mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f)); }
+ static __forceinline void storeu(void* ptr, const vuint8& f) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f)); }
+
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); }
+
+ static __forceinline void store_nt(void* ptr, const vuint8& v) {
+ _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
+ }
+
+ static __forceinline vuint8 load(const unsigned char* ptr) {
+ vuint4 il = vuint4::load(ptr+0);
+ vuint4 ih = vuint4::load(ptr+4);
+ return vuint8(il,ih);
+ }
+
+ static __forceinline vuint8 loadu(const unsigned char* ptr) {
+ vuint4 il = vuint4::loadu(ptr+0);
+ vuint4 ih = vuint4::loadu(ptr+4);
+ return vuint8(il,ih);
+ }
+
+ static __forceinline vuint8 load(const unsigned short* ptr) {
+ vuint4 il = vuint4::load(ptr+0);
+ vuint4 ih = vuint4::load(ptr+4);
+ return vuint8(il,ih);
+ }
+
+ static __forceinline vuint8 loadu(const unsigned short* ptr) {
+ vuint4 il = vuint4::loadu(ptr+0);
+ vuint4 ih = vuint4::loadu(ptr+4);
+ return vuint8(il,ih);
+ }
+
+ static __forceinline void store(unsigned char* ptr, const vuint8& i) {
+ vuint4 il(i.vl);
+ vuint4 ih(i.vh);
+ vuint4::store(ptr + 0,il);
+ vuint4::store(ptr + 4,ih);
+ }
+
+ static __forceinline void store(unsigned short* ptr, const vuint8& v) {
+ for (size_t i=0;i<8;i++)
+ ptr[i] = (unsigned short)v[i];
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint8 gather(const unsigned int* ptr, const vint8& index) {
+ return vuint8(
+ *(unsigned int*)(((char*)ptr)+scale*index[0]),
+ *(unsigned int*)(((char*)ptr)+scale*index[1]),
+ *(unsigned int*)(((char*)ptr)+scale*index[2]),
+ *(unsigned int*)(((char*)ptr)+scale*index[3]),
+ *(unsigned int*)(((char*)ptr)+scale*index[4]),
+ *(unsigned int*)(((char*)ptr)+scale*index[5]),
+ *(unsigned int*)(((char*)ptr)+scale*index[6]),
+ *(unsigned int*)(((char*)ptr)+scale*index[7]));
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint8 gather(const vboolf8& mask, const unsigned int* ptr, const vint8& index) {
+ vuint8 r = zero;
+ if (likely(mask[0])) r[0] = *(unsigned int*)(((char*)ptr)+scale*index[0]);
+ if (likely(mask[1])) r[1] = *(unsigned int*)(((char*)ptr)+scale*index[1]);
+ if (likely(mask[2])) r[2] = *(unsigned int*)(((char*)ptr)+scale*index[2]);
+ if (likely(mask[3])) r[3] = *(unsigned int*)(((char*)ptr)+scale*index[3]);
+ if (likely(mask[4])) r[4] = *(unsigned int*)(((char*)ptr)+scale*index[4]);
+ if (likely(mask[5])) r[5] = *(unsigned int*)(((char*)ptr)+scale*index[5]);
+ if (likely(mask[6])) r[6] = *(unsigned int*)(((char*)ptr)+scale*index[6]);
+ if (likely(mask[7])) r[7] = *(unsigned int*)(((char*)ptr)+scale*index[7]);
+ return r;
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(void* ptr, const vint8& ofs, const vuint8& v)
+ {
+ *(unsigned int*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[7]) = v[7];
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vuint8& v)
+ {
+ if (likely(mask[0])) *(unsigned int*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ if (likely(mask[1])) *(unsigned int*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ if (likely(mask[2])) *(unsigned int*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ if (likely(mask[3])) *(unsigned int*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ if (likely(mask[4])) *(unsigned int*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ if (likely(mask[5])) *(unsigned int*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ if (likely(mask[6])) *(unsigned int*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ if (likely(mask[7])) *(unsigned int*)(((char*)ptr)+scale*ofs[7]) = v[7];
+ }
+
+
+ static __forceinline vuint8 broadcast64(const long long& a) { return _mm256_set1_epi64x(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const unsigned int& operator [](size_t index) const { assert(index < 8); return i[index]; }
+ __forceinline unsigned int& operator [](size_t index) { assert(index < 8); return i[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 asBool(const vuint8& a) { return _mm256_castsi256_ps(a); }
+
+ __forceinline vuint8 operator +(const vuint8& a) { return a; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint8 operator +(const vuint8& a, const vuint8& b) { return vuint8(_mm_add_epi32(a.vl, b.vl), _mm_add_epi32(a.vh, b.vh)); }
+ __forceinline vuint8 operator +(const vuint8& a, unsigned int b) { return a + vuint8(b); }
+ __forceinline vuint8 operator +(unsigned int a, const vuint8& b) { return vuint8(a) + b; }
+
+ __forceinline vuint8 operator -(const vuint8& a, const vuint8& b) { return vuint8(_mm_sub_epi32(a.vl, b.vl), _mm_sub_epi32(a.vh, b.vh)); }
+ __forceinline vuint8 operator -(const vuint8& a, unsigned int b) { return a - vuint8(b); }
+ __forceinline vuint8 operator -(unsigned int a, const vuint8& b) { return vuint8(a) - b; }
+
+ //__forceinline vuint8 operator *(const vuint8& a, const vuint8& b) { return vuint8(_mm_mullo_epu32(a.vl, b.vl), _mm_mullo_epu32(a.vh, b.vh)); }
+ //__forceinline vuint8 operator *(const vuint8& a, unsigned int b) { return a * vuint8(b); }
+ //__forceinline vuint8 operator *(unsigned int a, const vuint8& b) { return vuint8(a) * b; }
+
+ __forceinline vuint8 operator &(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_and_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+ __forceinline vuint8 operator &(const vuint8& a, unsigned int b) { return a & vuint8(b); }
+ __forceinline vuint8 operator &(unsigned int a, const vuint8& b) { return vuint8(a) & b; }
+
+ __forceinline vuint8 operator |(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_or_ps (_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+ __forceinline vuint8 operator |(const vuint8& a, unsigned int b) { return a | vuint8(b); }
+ __forceinline vuint8 operator |(unsigned int a, const vuint8& b) { return vuint8(a) | b; }
+
+ __forceinline vuint8 operator ^(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+ __forceinline vuint8 operator ^(const vuint8& a, unsigned int b) { return a ^ vuint8(b); }
+ __forceinline vuint8 operator ^(unsigned int a, const vuint8& b) { return vuint8(a) ^ b; }
+
+ __forceinline vuint8 operator <<(const vuint8& a, unsigned int n) { return vuint8(_mm_slli_epi32(a.vl, n), _mm_slli_epi32(a.vh, n)); }
+ __forceinline vuint8 operator >>(const vuint8& a, unsigned int n) { return vuint8(_mm_srai_epi32(a.vl, n), _mm_srli_epi32(a.vh, n)); }
+
+ __forceinline vuint8 sll (const vuint8& a, unsigned int b) { return vuint8(_mm_slli_epi32(a.vl, b), _mm_slli_epi32(a.vh, b)); }
+ __forceinline vuint8 sra (const vuint8& a, unsigned int b) { return vuint8(_mm_srai_epi32(a.vl, b), _mm_srai_epi32(a.vh, b)); }
+ __forceinline vuint8 srl (const vuint8& a, unsigned int b) { return vuint8(_mm_srli_epi32(a.vl, b), _mm_srli_epi32(a.vh, b)); }
+
+ __forceinline vuint8 min(const vuint8& a, const vuint8& b) { return vuint8(_mm_min_epu32(a.vl, b.vl), _mm_min_epu32(a.vh, b.vh)); }
+ __forceinline vuint8 min(const vuint8& a, unsigned int b) { return min(a,vuint8(b)); }
+ __forceinline vuint8 min(unsigned int a, const vuint8& b) { return min(vuint8(a),b); }
+
+ __forceinline vuint8 max(const vuint8& a, const vuint8& b) { return vuint8(_mm_max_epu32(a.vl, b.vl), _mm_max_epu32(a.vh, b.vh)); }
+ __forceinline vuint8 max(const vuint8& a, unsigned int b) { return max(a,vuint8(b)); }
+ __forceinline vuint8 max(unsigned int a, const vuint8& b) { return max(vuint8(a),b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint8& operator +=(vuint8& a, const vuint8& b) { return a = a + b; }
+ __forceinline vuint8& operator +=(vuint8& a, unsigned int b) { return a = a + b; }
+
+ __forceinline vuint8& operator -=(vuint8& a, const vuint8& b) { return a = a - b; }
+ __forceinline vuint8& operator -=(vuint8& a, unsigned int b) { return a = a - b; }
+
+ //__forceinline vuint8& operator *=(vuint8& a, const vuint8& b) { return a = a * b; }
+ //__forceinline vuint8& operator *=(vuint8& a, unsigned int b) { return a = a * b; }
+
+ __forceinline vuint8& operator &=(vuint8& a, const vuint8& b) { return a = a & b; }
+ __forceinline vuint8& operator &=(vuint8& a, unsigned int b) { return a = a & b; }
+
+ __forceinline vuint8& operator |=(vuint8& a, const vuint8& b) { return a = a | b; }
+ __forceinline vuint8& operator |=(vuint8& a, unsigned int b) { return a = a | b; }
+
+ __forceinline vuint8& operator <<=(vuint8& a, unsigned int b) { return a = a << b; }
+ __forceinline vuint8& operator >>=(vuint8& a, unsigned int b) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vboolf8 operator ==(const vuint8& a, const vuint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmpeq_epi32 (a.vl, b.vl)),
+ _mm_castsi128_ps(_mm_cmpeq_epi32 (a.vh, b.vh))); }
+ __forceinline vboolf8 operator ==(const vuint8& a, unsigned int b) { return a == vuint8(b); }
+ __forceinline vboolf8 operator ==(unsigned int a, const vuint8& b) { return vuint8(a) == b; }
+
+ __forceinline vboolf8 operator !=(const vuint8& a, const vuint8& b) { return !(a == b); }
+ __forceinline vboolf8 operator !=(const vuint8& a, unsigned int b) { return a != vuint8(b); }
+ __forceinline vboolf8 operator !=(unsigned int a, const vuint8& b) { return vuint8(a) != b; }
+
+ //__forceinline vboolf8 operator < (const vuint8& a, const vuint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmplt_epu32 (a.vl, b.vl)),
+ // _mm_castsi128_ps(_mm_cmplt_epu32 (a.vh, b.vh))); }
+ //__forceinline vboolf8 operator < (const vuint8& a, unsigned int b) { return a < vuint8(b); }
+ //__forceinline vboolf8 operator < (unsigned int a, const vuint8& b) { return vuint8(a) < b; }
+
+ //__forceinline vboolf8 operator >=(const vuint8& a, const vuint8& b) { return !(a < b); }
+ //__forceinline vboolf8 operator >=(const vuint8& a, unsigned int b) { return a >= vuint8(b); }
+ //__forceinline vboolf8 operator >=(unsigned int a, const vuint8& b) { return vuint8(a) >= b; }
+
+ //__forceinline vboolf8 operator > (const vuint8& a, const vuint8& b) { return vboolf8(_mm_castsi128_ps(_mm_cmpgt_epu32 (a.vl, b.vl)),
+ // _mm_castsi128_ps(_mm_cmpgt_epu32 (a.vh, b.vh))); }
+ //__forceinline vboolf8 operator > (const vuint8& a, unsigned int b) { return a > vuint8(b); }
+ //__forceinline vboolf8 operator > (unsigned int a, const vuint8& b) { return vuint8(a) > b; }
+
+ //__forceinline vboolf8 operator <=(const vuint8& a, const vuint8& b) { return !(a > b); }
+ //__forceinline vboolf8 operator <=(const vuint8& a, unsigned int b) { return a <= vuint8(b); }
+ //__forceinline vboolf8 operator <=(unsigned int a, const vuint8& b) { return vuint8(a) <= b; }
+
+ __forceinline vboolf8 eq(const vuint8& a, const vuint8& b) { return a == b; }
+ __forceinline vboolf8 ne(const vuint8& a, const vuint8& b) { return a != b; }
+
+ __forceinline vboolf8 eq(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a == b); }
+ __forceinline vboolf8 ne(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a != b); }
+
+ __forceinline vuint8 select(const vboolf8& m, const vuint8& t, const vuint8& f) {
+ return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint8 unpacklo(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_unpacklo_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+ __forceinline vuint8 unpackhi(const vuint8& a, const vuint8& b) { return _mm256_castps_si256(_mm256_unpackhi_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
+
+ template<int i>
+ __forceinline vuint8 shuffle(const vuint8& v) {
+ return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
+ }
+
+ template<int i0, int i1>
+ __forceinline vuint8 shuffle4(const vuint8& v) {
+ return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1>
+ __forceinline vuint8 shuffle4(const vuint8& a, const vuint8& b) {
+ return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint8 shuffle(const vuint8& v) {
+ return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint8 shuffle(const vuint8& a, const vuint8& b) {
+ return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<> __forceinline vuint8 shuffle<0, 0, 2, 2>(const vuint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
+ template<> __forceinline vuint8 shuffle<1, 1, 3, 3>(const vuint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
+ template<> __forceinline vuint8 shuffle<0, 1, 0, 1>(const vuint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
+
+ template<int i> __forceinline vuint8 insert4(const vuint8& a, const vuint4& b) { return _mm256_insertf128_si256(a, b, i); }
+ template<int i> __forceinline vuint4 extract4(const vuint8& a) { return _mm256_extractf128_si256(a, i); }
+ template<> __forceinline vuint4 extract4<0>(const vuint8& a) { return _mm256_castsi256_si128(a); }
+
+ __forceinline int toScalar(const vuint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ //__forceinline vuint8 vreduce_min2(const vuint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
+ //__forceinline vuint8 vreduce_min4(const vuint8& v) { vuint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
+ //__forceinline vuint8 vreduce_min (const vuint8& v) { vuint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
+
+ //__forceinline vuint8 vreduce_max2(const vuint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
+ //__forceinline vuint8 vreduce_max4(const vuint8& v) { vuint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
+ //__forceinline vuint8 vreduce_max (const vuint8& v) { vuint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
+
+ __forceinline vuint8 vreduce_add2(const vuint8& v) { return v + shuffle<1,0,3,2>(v); }
+ __forceinline vuint8 vreduce_add4(const vuint8& v) { vuint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
+ __forceinline vuint8 vreduce_add (const vuint8& v) { vuint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
+
+ //__forceinline int reduce_min(const vuint8& v) { return toScalar(vreduce_min(v)); }
+ //__forceinline int reduce_max(const vuint8& v) { return toScalar(vreduce_max(v)); }
+ __forceinline int reduce_add(const vuint8& v) { return toScalar(vreduce_add(v)); }
+
+ //__forceinline size_t select_min(const vuint8& v) { return bsf(movemask(v == vreduce_min(v))); }
+ //__forceinline size_t select_max(const vuint8& v) { return bsf(movemask(v == vreduce_max(v))); }
+
+ //__forceinline size_t select_min(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
+ //__forceinline size_t select_max(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vuint8& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/simd/vuint8_avx2.h b/thirdparty/embree/common/simd/vuint8_avx2.h
new file mode 100644
index 0000000000..17b994522f
--- /dev/null
+++ b/thirdparty/embree/common/simd/vuint8_avx2.h
@@ -0,0 +1,446 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define vboolf vboolf_impl
+#define vboold vboold_impl
+#define vint vint_impl
+#define vuint vuint_impl
+#define vllong vllong_impl
+#define vfloat vfloat_impl
+#define vdouble vdouble_impl
+
+namespace embree
+{
+ /* 8-wide AVX integer type */
+ template<>
+ struct vuint<8>
+ {
+ ALIGNED_STRUCT_(32);
+
+ typedef vboolf8 Bool;
+ typedef vuint8 Int;
+ typedef vfloat8 Float;
+
+ enum { size = 8 }; // number of SIMD elements
+ union { // data
+ __m256i v;
+ unsigned int i[8];
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint() {}
+ __forceinline vuint(const vuint8& a) { v = a.v; }
+ __forceinline vuint8& operator =(const vuint8& a) { v = a.v; return *this; }
+
+ __forceinline vuint(__m256i a) : v(a) {}
+ __forceinline operator const __m256i&() const { return v; }
+ __forceinline operator __m256i&() { return v; }
+
+ __forceinline explicit vuint(const vuint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
+ __forceinline vuint(const vuint4& a, const vuint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
+ __forceinline vuint(const __m128i& a, const __m128i& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
+
+ __forceinline explicit vuint(const unsigned int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
+ __forceinline vuint(unsigned int a) : v(_mm256_set1_epi32(a)) {}
+ __forceinline vuint(unsigned int a, unsigned int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
+ __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
+ __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f, unsigned int g, unsigned int h) : v(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
+
+ __forceinline explicit vuint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
+
+#if defined(__AVX512VL__)
+ __forceinline explicit vuint(const vboolf8& a) : v(_mm256_movm_epi32(a)) {}
+#else
+ __forceinline explicit vuint(const vboolf8& a) : v(_mm256_castps_si256((__m256)a)) {}
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint(ZeroTy) : v(_mm256_setzero_si256()) {}
+ __forceinline vuint(OneTy) : v(_mm256_set1_epi32(1)) {}
+ __forceinline vuint(PosInfTy) : v(_mm256_set1_epi32(pos_inf)) {}
+ __forceinline vuint(NegInfTy) : v(_mm256_set1_epi32(neg_inf)) {}
+ __forceinline vuint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
+ __forceinline vuint(UndefinedTy) : v(_mm256_undefined_si256()) {}
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static __forceinline vuint8 load(const unsigned char* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
+ static __forceinline vuint8 loadu(const unsigned char* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
+ static __forceinline vuint8 load(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_load_si128((__m128i*)ptr)); }
+ static __forceinline vuint8 loadu(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr)); }
+
+ static __forceinline vuint8 load(const void* ptr) { return _mm256_load_si256((__m256i*)ptr); }
+ static __forceinline vuint8 loadu(const void* ptr) { return _mm256_loadu_si256((__m256i*)ptr); }
+
+ static __forceinline void store (void* ptr, const vuint8& v) { _mm256_store_si256((__m256i*)ptr,v); }
+ static __forceinline void storeu(void* ptr, const vuint8& v) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(v)); }
+
+#if defined(__AVX512VL__)
+
+ static __forceinline vuint8 compact(const vboolf8& mask, vuint8 &v) {
+ return _mm256_mask_compress_epi32(v, mask, v);
+ }
+ static __forceinline vuint8 compact(const vboolf8& mask, vuint8 &a, const vuint8& b) {
+ return _mm256_mask_compress_epi32(a, mask, b);
+ }
+
+ static __forceinline vuint8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_epi32 (_mm256_setzero_si256(),mask,ptr); }
+ static __forceinline vuint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_epi32(_mm256_setzero_si256(),mask,ptr); }
+
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_mask_store_epi32 (ptr,mask,v); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_mask_storeu_epi32(ptr,mask,v); }
+#else
+ static __forceinline vuint8 load (const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
+ static __forceinline vuint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
+
+ static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
+ static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
+#endif
+
+ static __forceinline vuint8 load_nt(void* ptr) {
+ return _mm256_stream_load_si256((__m256i*)ptr);
+ }
+
+ static __forceinline void store_nt(void* ptr, const vuint8& v) {
+ _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
+ }
+
+ static __forceinline void store(unsigned char* ptr, const vuint8& i)
+ {
+ for (size_t j=0; j<8; j++)
+ ptr[j] = i[j];
+ }
+
+ static __forceinline void store(unsigned short* ptr, const vuint8& v) {
+ for (size_t i=0;i<8;i++)
+ ptr[i] = (unsigned short)v[i];
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint8 gather(const unsigned int *const ptr, const vint8& index) {
+ return _mm256_i32gather_epi32((const int*) ptr, index, scale);
+ }
+
+ template<int scale = 4>
+ static __forceinline vuint8 gather(const vboolf8& mask, const unsigned int *const ptr, const vint8& index) {
+ vuint8 r = zero;
+#if defined(__AVX512VL__)
+ return _mm256_mmask_i32gather_epi32(r, mask, index, (const int*) ptr, scale);
+#else
+ return _mm256_mask_i32gather_epi32(r, (const int*) ptr, index, mask, scale);
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(void* ptr, const vint8& ofs, const vuint8& v)
+ {
+#if defined(__AVX512VL__)
+ _mm256_i32scatter_epi32((int*)ptr, ofs, v, scale);
+#else
+ *(unsigned int*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ *(unsigned int*)(((char*)ptr)+scale*ofs[7]) = v[7];
+#endif
+ }
+
+ template<int scale = 4>
+ static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vuint8& v)
+ {
+#if defined(__AVX512VL__)
+ _mm256_mask_i32scatter_epi32((int*)ptr, mask, ofs, v, scale);
+#else
+ if (likely(mask[0])) *(unsigned int*)(((char*)ptr)+scale*ofs[0]) = v[0];
+ if (likely(mask[1])) *(unsigned int*)(((char*)ptr)+scale*ofs[1]) = v[1];
+ if (likely(mask[2])) *(unsigned int*)(((char*)ptr)+scale*ofs[2]) = v[2];
+ if (likely(mask[3])) *(unsigned int*)(((char*)ptr)+scale*ofs[3]) = v[3];
+ if (likely(mask[4])) *(unsigned int*)(((char*)ptr)+scale*ofs[4]) = v[4];
+ if (likely(mask[5])) *(unsigned int*)(((char*)ptr)+scale*ofs[5]) = v[5];
+ if (likely(mask[6])) *(unsigned int*)(((char*)ptr)+scale*ofs[6]) = v[6];
+ if (likely(mask[7])) *(unsigned int*)(((char*)ptr)+scale*ofs[7]) = v[7];
+#endif
+ }
+
+ static __forceinline vuint8 broadcast64(const long long &a) { return _mm256_set1_epi64x(a); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const unsigned int& operator [](size_t index) const { assert(index < 8); return i[index]; }
+ __forceinline unsigned int& operator [](size_t index) { assert(index < 8); return i[index]; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Unary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf8 asBool(const vuint8& a) { return _mm256_movepi32_mask(a); }
+#else
+ __forceinline vboolf8 asBool(const vuint8& a) { return _mm256_castsi256_ps(a); }
+#endif
+
+ __forceinline vuint8 operator +(const vuint8& a) { return a; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Binary Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint8 operator +(const vuint8& a, const vuint8& b) { return _mm256_add_epi32(a, b); }
+ __forceinline vuint8 operator +(const vuint8& a, unsigned int b) { return a + vuint8(b); }
+ __forceinline vuint8 operator +(unsigned int a, const vuint8& b) { return vuint8(a) + b; }
+
+ __forceinline vuint8 operator -(const vuint8& a, const vuint8& b) { return _mm256_sub_epi32(a, b); }
+ __forceinline vuint8 operator -(const vuint8& a, unsigned int b) { return a - vuint8(b); }
+ __forceinline vuint8 operator -(unsigned int a, const vuint8& b) { return vuint8(a) - b; }
+
+ //__forceinline vuint8 operator *(const vuint8& a, const vuint8& b) { return _mm256_mullo_epu32(a, b); }
+ //__forceinline vuint8 operator *(const vuint8& a, unsigned int b) { return a * vuint8(b); }
+ //__forceinline vuint8 operator *(unsigned int a, const vuint8& b) { return vuint8(a) * b; }
+
+ __forceinline vuint8 operator &(const vuint8& a, const vuint8& b) { return _mm256_and_si256(a, b); }
+ __forceinline vuint8 operator &(const vuint8& a, unsigned int b) { return a & vuint8(b); }
+ __forceinline vuint8 operator &(unsigned int a, const vuint8& b) { return vuint8(a) & b; }
+
+ __forceinline vuint8 operator |(const vuint8& a, const vuint8& b) { return _mm256_or_si256(a, b); }
+ __forceinline vuint8 operator |(const vuint8& a, unsigned int b) { return a | vuint8(b); }
+ __forceinline vuint8 operator |(unsigned int a, const vuint8& b) { return vuint8(a) | b; }
+
+ __forceinline vuint8 operator ^(const vuint8& a, const vuint8& b) { return _mm256_xor_si256(a, b); }
+ __forceinline vuint8 operator ^(const vuint8& a, unsigned int b) { return a ^ vuint8(b); }
+ __forceinline vuint8 operator ^(unsigned int a, const vuint8& b) { return vuint8(a) ^ b; }
+
+ __forceinline vuint8 operator <<(const vuint8& a, unsigned int n) { return _mm256_slli_epi32(a, n); }
+ __forceinline vuint8 operator >>(const vuint8& a, unsigned int n) { return _mm256_srli_epi32(a, n); }
+
+ __forceinline vuint8 operator <<(const vuint8& a, const vuint8& n) { return _mm256_sllv_epi32(a, n); }
+ __forceinline vuint8 operator >>(const vuint8& a, const vuint8& n) { return _mm256_srlv_epi32(a, n); }
+
+ __forceinline vuint8 sll(const vuint8& a, unsigned int b) { return _mm256_slli_epi32(a, b); }
+ __forceinline vuint8 sra(const vuint8& a, unsigned int b) { return _mm256_srai_epi32(a, b); }
+ __forceinline vuint8 srl(const vuint8& a, unsigned int b) { return _mm256_srli_epi32(a, b); }
+
+ __forceinline vuint8 sll(const vuint8& a, const vuint8& b) { return _mm256_sllv_epi32(a, b); }
+ __forceinline vuint8 sra(const vuint8& a, const vuint8& b) { return _mm256_srav_epi32(a, b); }
+ __forceinline vuint8 srl(const vuint8& a, const vuint8& b) { return _mm256_srlv_epi32(a, b); }
+
+ __forceinline vuint8 min(const vuint8& a, const vuint8& b) { return _mm256_min_epu32(a, b); }
+ __forceinline vuint8 min(const vuint8& a, unsigned int b) { return min(a,vuint8(b)); }
+ __forceinline vuint8 min(unsigned int a, const vuint8& b) { return min(vuint8(a),b); }
+
+ __forceinline vuint8 max(const vuint8& a, const vuint8& b) { return _mm256_max_epu32(a, b); }
+ __forceinline vuint8 max(const vuint8& a, unsigned int b) { return max(a,vuint8(b)); }
+ __forceinline vuint8 max(unsigned int a, const vuint8& b) { return max(vuint8(a),b); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Assignment Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint8& operator +=(vuint8& a, const vuint8& b) { return a = a + b; }
+ __forceinline vuint8& operator +=(vuint8& a, unsigned int b) { return a = a + b; }
+
+ __forceinline vuint8& operator -=(vuint8& a, const vuint8& b) { return a = a - b; }
+ __forceinline vuint8& operator -=(vuint8& a, unsigned int b) { return a = a - b; }
+
+ //__forceinline vuint8& operator *=(vuint8& a, const vuint8& b) { return a = a * b; }
+ //__forceinline vuint8& operator *=(vuint8& a, unsigned int b) { return a = a * b; }
+
+ __forceinline vuint8& operator &=(vuint8& a, const vuint8& b) { return a = a & b; }
+ __forceinline vuint8& operator &=(vuint8& a, unsigned int b) { return a = a & b; }
+
+ __forceinline vuint8& operator |=(vuint8& a, const vuint8& b) { return a = a | b; }
+ __forceinline vuint8& operator |=(vuint8& a, unsigned int b) { return a = a | b; }
+
+ __forceinline vuint8& operator <<=(vuint8& a, const unsigned int b) { return a = a << b; }
+ __forceinline vuint8& operator >>=(vuint8& a, const unsigned int b) { return a = a >> b; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Comparison Operators + Select
+ ////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf8 operator ==(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
+ __forceinline vboolf8 operator !=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
+ __forceinline vboolf8 operator < (const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
+ __forceinline vboolf8 operator >=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
+ __forceinline vboolf8 operator > (const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
+ __forceinline vboolf8 operator <=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
+
+ __forceinline vuint8 select(const vboolf8& m, const vuint8& t, const vuint8& f) {
+ return _mm256_mask_blend_epi32(m, (__m256i)f, (__m256i)t);
+ }
+#else
+ __forceinline vboolf8 operator ==(const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b)); }
+ __forceinline vboolf8 operator !=(const vuint8& a, const vuint8& b) { return !(a == b); }
+ //__forceinline vboolf8 operator < (const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epu32(b, a)); }
+ //__forceinline vboolf8 operator >=(const vuint8& a, const vuint8& b) { return !(a < b); }
+ //__forceinline vboolf8 operator > (const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epu32(a, b)); }
+ //__forceinline vboolf8 operator <=(const vuint8& a, const vuint8& b) { return !(a > b); }
+
+ __forceinline vuint8 select(const vboolf8& m, const vuint8& t, const vuint8& f) {
+ return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
+ }
+#endif
+
+ template<int mask>
+ __forceinline vuint8 select(const vuint8& t, const vuint8& f) {
+ return _mm256_blend_epi32(f, t, mask);
+ }
+
+ __forceinline vboolf8 operator ==(const vuint8& a, unsigned int b) { return a == vuint8(b); }
+ __forceinline vboolf8 operator ==(unsigned int a, const vuint8& b) { return vuint8(a) == b; }
+
+ __forceinline vboolf8 operator !=(const vuint8& a, unsigned int b) { return a != vuint8(b); }
+ __forceinline vboolf8 operator !=(unsigned int a, const vuint8& b) { return vuint8(a) != b; }
+
+ //__forceinline vboolf8 operator < (const vuint8& a, unsigned int b) { return a < vuint8(b); }
+ //__forceinline vboolf8 operator < (unsigned int a, const vuint8& b) { return vuint8(a) < b; }
+
+ //__forceinline vboolf8 operator >=(const vuint8& a, unsigned int b) { return a >= vuint8(b); }
+ //__forceinline vboolf8 operator >=(unsigned int a, const vuint8& b) { return vuint8(a) >= b; }
+
+ //__forceinline vboolf8 operator > (const vuint8& a, unsigned int b) { return a > vuint8(b); }
+ //__forceinline vboolf8 operator > (unsigned int a, const vuint8& b) { return vuint8(a) > b; }
+
+ //__forceinline vboolf8 operator <=(const vuint8& a, unsigned int b) { return a <= vuint8(b); }
+ //__forceinline vboolf8 operator <=(unsigned int a, const vuint8& b) { return vuint8(a) <= b; }
+
+ __forceinline vboolf8 eq(const vuint8& a, const vuint8& b) { return a == b; }
+ __forceinline vboolf8 ne(const vuint8& a, const vuint8& b) { return a != b; }
+ //__forceinline vboolf8 lt(const vuint8& a, const vuint8& b) { return a < b; }
+ //__forceinline vboolf8 ge(const vuint8& a, const vuint8& b) { return a >= b; }
+ //__forceinline vboolf8 gt(const vuint8& a, const vuint8& b) { return a > b; }
+ //__forceinline vboolf8 le(const vuint8& a, const vuint8& b) { return a <= b; }
+
+#if defined(__AVX512VL__)
+ __forceinline vboolf8 eq(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_EQ); }
+ __forceinline vboolf8 ne(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_NE); }
+ __forceinline vboolf8 lt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LT); }
+ __forceinline vboolf8 ge(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GE); }
+ __forceinline vboolf8 gt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GT); }
+ __forceinline vboolf8 le(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LE); }
+#else
+ __forceinline vboolf8 eq(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a == b); }
+ __forceinline vboolf8 ne(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a != b); }
+ //__forceinline vboolf8 lt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a < b); }
+ //__forceinline vboolf8 ge(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a >= b); }
+ //__forceinline vboolf8 gt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a > b); }
+ //__forceinline vboolf8 le(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a <= b); }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Movement/Shifting/Shuffling Functions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline vuint8 unpacklo(const vuint8& a, const vuint8& b) { return _mm256_unpacklo_epi32(a, b); }
+ __forceinline vuint8 unpackhi(const vuint8& a, const vuint8& b) { return _mm256_unpackhi_epi32(a, b); }
+
+ template<int i>
+ __forceinline vuint8 shuffle(const vuint8& v) {
+ return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
+ }
+
+ template<int i0, int i1>
+ __forceinline vuint8 shuffle4(const vuint8& v) {
+ return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1>
+ __forceinline vuint8 shuffle4(const vuint8& a, const vuint8& b) {
+ return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint8 shuffle(const vuint8& v) {
+ return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<int i0, int i1, int i2, int i3>
+ __forceinline vuint8 shuffle(const vuint8& a, const vuint8& b) {
+ return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
+ }
+
+ template<> __forceinline vuint8 shuffle<0, 0, 2, 2>(const vuint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
+ template<> __forceinline vuint8 shuffle<1, 1, 3, 3>(const vuint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
+ template<> __forceinline vuint8 shuffle<0, 1, 0, 1>(const vuint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
+
+ template<int i> __forceinline vuint8 insert4(const vuint8& a, const vuint4& b) { return _mm256_insertf128_si256(a, b, i); }
+ template<int i> __forceinline vuint4 extract4(const vuint8& a) { return _mm256_extractf128_si256(a, i); }
+ template<> __forceinline vuint4 extract4<0>(const vuint8& a) { return _mm256_castsi256_si128(a); }
+
+ __forceinline int toScalar(const vuint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
+
+ __forceinline vuint8 permute(const vuint8& v, const __m256i& index) {
+ return _mm256_permutevar8x32_epi32(v, index);
+ }
+
+ __forceinline vuint8 shuffle(const vuint8& v, const __m256i& index) {
+ return _mm256_castps_si256(_mm256_permutevar_ps(_mm256_castsi256_ps(v), index));
+ }
+
+ template<int i>
+ __forceinline vuint8 align_shift_right(const vuint8& a, const vuint8& b) {
+#if defined(__AVX512VL__)
+ return _mm256_alignr_epi32(a, b, i);
+#else
+ return _mm256_alignr_epi8(a, b, 4*i);
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reductions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ //__forceinline vuint8 vreduce_min2(const vuint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
+ //__forceinline vuint8 vreduce_min4(const vuint8& v) { vuint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
+ //__forceinline vuint8 vreduce_min (const vuint8& v) { vuint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
+
+ //__forceinline vuint8 vreduce_max2(const vuint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
+ //__forceinline vuint8 vreduce_max4(const vuint8& v) { vuint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
+ //__forceinline vuint8 vreduce_max (const vuint8& v) { vuint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
+
+ __forceinline vuint8 vreduce_add2(const vuint8& v) { return v + shuffle<1,0,3,2>(v); }
+ __forceinline vuint8 vreduce_add4(const vuint8& v) { vuint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
+ __forceinline vuint8 vreduce_add (const vuint8& v) { vuint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
+
+ //__forceinline int reduce_min(const vuint8& v) { return toScalar(vreduce_min(v)); }
+ //__forceinline int reduce_max(const vuint8& v) { return toScalar(vreduce_max(v)); }
+ __forceinline int reduce_add(const vuint8& v) { return toScalar(vreduce_add(v)); }
+
+ //__forceinline size_t select_min(const vuint8& v) { return bsf(movemask(v == vreduce_min(v))); }
+ //__forceinline size_t select_max(const vuint8& v) { return bsf(movemask(v == vreduce_max(v))); }
+
+ //__forceinline size_t select_min(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
+ //__forceinline size_t select_max(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Output Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline embree_ostream operator <<(embree_ostream cout, const vuint8& a) {
+ return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
+ }
+}
+
+#undef vboolf
+#undef vboold
+#undef vint
+#undef vuint
+#undef vllong
+#undef vfloat
+#undef vdouble
diff --git a/thirdparty/embree/common/sys/alloc.cpp b/thirdparty/embree/common/sys/alloc.cpp
new file mode 100644
index 0000000000..abdd269069
--- /dev/null
+++ b/thirdparty/embree/common/sys/alloc.cpp
@@ -0,0 +1,327 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "alloc.h"
+#include "intrinsics.h"
+#include "sysinfo.h"
+#include "mutex.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/// All Platforms
+////////////////////////////////////////////////////////////////////////////////
+
+namespace embree
+{
+ void* alignedMalloc(size_t size, size_t align)
+ {
+ if (size == 0)
+ return nullptr;
+
+ assert((align & (align-1)) == 0);
+ void* ptr = _mm_malloc(size,align);
+
+ if (size != 0 && ptr == nullptr)
+ // -- GODOT start --
+ // throw std::bad_alloc();
+ abort();
+ // -- GODOT end --
+
+ return ptr;
+ }
+
+ void alignedFree(void* ptr)
+ {
+ if (ptr)
+ _mm_free(ptr);
+ }
+
+ static bool huge_pages_enabled = false;
+ static MutexSys os_init_mutex;
+
+ __forceinline bool isHugePageCandidate(const size_t bytes)
+ {
+ if (!huge_pages_enabled)
+ return false;
+
+ /* use huge pages only when memory overhead is low */
+ const size_t hbytes = (bytes+PAGE_SIZE_2M-1) & ~size_t(PAGE_SIZE_2M-1);
+ return 66*(hbytes-bytes) < bytes; // at most 1.5% overhead
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef _WIN32
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <malloc.h>
+
+namespace embree
+{
+ bool win_enable_selockmemoryprivilege (bool verbose)
+ {
+ HANDLE hToken;
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
+ if (verbose) std::cout << "WARNING: OpenProcessToken failed while trying to enable SeLockMemoryPrivilege: " << GetLastError() << std::endl;
+ return false;
+ }
+
+ TOKEN_PRIVILEGES tp;
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (!LookupPrivilegeValueW(nullptr, L"SeLockMemoryPrivilege", &tp.Privileges[0].Luid)) {
+ if (verbose) std::cout << "WARNING: LookupPrivilegeValue failed while trying to enable SeLockMemoryPrivilege: " << GetLastError() << std::endl;
+ return false;
+ }
+
+ SetLastError(ERROR_SUCCESS);
+ if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), nullptr, 0)) {
+ if (verbose) std::cout << "WARNING: AdjustTokenPrivileges failed while trying to enable SeLockMemoryPrivilege" << std::endl;
+ return false;
+ }
+
+ if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
+ if (verbose) std::cout << "WARNING: AdjustTokenPrivileges failed to enable SeLockMemoryPrivilege: Add SeLockMemoryPrivilege for current user and run process in elevated mode (Run as administrator)." << std::endl;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool os_init(bool hugepages, bool verbose)
+ {
+ Lock<MutexSys> lock(os_init_mutex);
+
+ if (!hugepages) {
+ huge_pages_enabled = false;
+ return true;
+ }
+
+ if (GetLargePageMinimum() != PAGE_SIZE_2M) {
+ huge_pages_enabled = false;
+ return false;
+ }
+
+ huge_pages_enabled = true;
+ return true;
+ }
+
+ void* os_malloc(size_t bytes, bool& hugepages)
+ {
+ if (bytes == 0) {
+ hugepages = false;
+ return nullptr;
+ }
+
+ /* try direct huge page allocation first */
+ if (isHugePageCandidate(bytes))
+ {
+ int flags = MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES;
+ char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
+ if (ptr != nullptr) {
+ hugepages = true;
+ return ptr;
+ }
+ }
+
+ /* fall back to 4k pages */
+ int flags = MEM_COMMIT | MEM_RESERVE;
+ char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
+ // -- GODOT start --
+ // if (ptr == nullptr) throw std::bad_alloc();
+ if (ptr == nullptr) abort();
+ // -- GODOT end --
+ hugepages = false;
+ return ptr;
+ }
+
+ size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages)
+ {
+ if (hugepages) // decommitting huge pages seems not to work under Windows
+ return bytesOld;
+
+ const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
+ bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
+ bytesOld = (bytesOld+pageSize-1) & ~(pageSize-1);
+ if (bytesNew >= bytesOld)
+ return bytesOld;
+
+ if (!VirtualFree((char*)ptr+bytesNew,bytesOld-bytesNew,MEM_DECOMMIT))
+ // -- GODOT start --
+ // throw std::bad_alloc();
+ abort();
+ // -- GODOT end --
+
+ return bytesNew;
+ }
+
+ void os_free(void* ptr, size_t bytes, bool hugepages)
+ {
+ if (bytes == 0)
+ return;
+
+ if (!VirtualFree(ptr,0,MEM_RELEASE))
+ // -- GODOT start --
+ // throw std::bad_alloc();
+ abort();
+ // -- GODOT end --
+ }
+
+ void os_advise(void *ptr, size_t bytes)
+ {
+ }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <sys/mman.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sstream>
+
+#if defined(__MACOSX__)
+#include <mach/vm_statistics.h>
+#endif
+
+namespace embree
+{
+ bool os_init(bool hugepages, bool verbose)
+ {
+ Lock<MutexSys> lock(os_init_mutex);
+
+ if (!hugepages) {
+ huge_pages_enabled = false;
+ return true;
+ }
+
+#if defined(__LINUX__)
+
+ int hugepagesize = 0;
+
+ std::ifstream file;
+ file.open("/proc/meminfo",std::ios::in);
+ if (!file.is_open()) {
+ if (verbose) std::cout << "WARNING: Could not open /proc/meminfo. Huge page support cannot get enabled!" << std::endl;
+ huge_pages_enabled = false;
+ return false;
+ }
+
+ std::string line;
+ while (getline(file,line))
+ {
+ std::stringstream sline(line);
+ while (!sline.eof() && sline.peek() == ' ') sline.ignore();
+ std::string tag; getline(sline,tag,' ');
+ while (!sline.eof() && sline.peek() == ' ') sline.ignore();
+ std::string val; getline(sline,val,' ');
+ while (!sline.eof() && sline.peek() == ' ') sline.ignore();
+ std::string unit; getline(sline,unit,' ');
+ if (tag == "Hugepagesize:" && unit == "kB") {
+ hugepagesize = std::stoi(val)*1024;
+ break;
+ }
+ }
+
+ if (hugepagesize != PAGE_SIZE_2M)
+ {
+ if (verbose) std::cout << "WARNING: Only 2MB huge pages supported. Huge page support cannot get enabled!" << std::endl;
+ huge_pages_enabled = false;
+ return false;
+ }
+#endif
+
+ huge_pages_enabled = true;
+ return true;
+ }
+
+ void* os_malloc(size_t bytes, bool& hugepages)
+ {
+ if (bytes == 0) {
+ hugepages = false;
+ return nullptr;
+ }
+
+ /* try direct huge page allocation first */
+ if (isHugePageCandidate(bytes))
+ {
+#if defined(__MACOSX__)
+ void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
+ if (ptr != MAP_FAILED) {
+ hugepages = true;
+ return ptr;
+ }
+#elif defined(MAP_HUGETLB)
+ void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_HUGETLB, -1, 0);
+ if (ptr != MAP_FAILED) {
+ hugepages = true;
+ return ptr;
+ }
+#endif
+ }
+
+ /* fallback to 4k pages */
+ void* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ // -- GODOT start --
+ // if (ptr == MAP_FAILED) throw std::bad_alloc();
+ if (ptr == MAP_FAILED) abort();
+ // -- GODOT end --
+ hugepages = false;
+
+ /* advise huge page hint for THP */
+ os_advise(ptr,bytes);
+ return ptr;
+ }
+
+ size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages)
+ {
+ const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
+ bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
+ bytesOld = (bytesOld+pageSize-1) & ~(pageSize-1);
+ if (bytesNew >= bytesOld)
+ return bytesOld;
+
+ if (munmap((char*)ptr+bytesNew,bytesOld-bytesNew) == -1)
+ // -- GODOT start --
+ // throw std::bad_alloc();
+ abort();
+ // -- GODOT end --
+
+ return bytesNew;
+ }
+
+ void os_free(void* ptr, size_t bytes, bool hugepages)
+ {
+ if (bytes == 0)
+ return;
+
+ /* for hugepages we need to also align the size */
+ const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
+ bytes = (bytes+pageSize-1) & ~(pageSize-1);
+ if (munmap(ptr,bytes) == -1)
+ // -- GODOT start --
+ // throw std::bad_alloc();
+ abort();
+ // -- GODOT end --
+ }
+
+ /* hint for transparent huge pages (THP) */
+ void os_advise(void* pptr, size_t bytes)
+ {
+#if defined(MADV_HUGEPAGE)
+ madvise(pptr,bytes,MADV_HUGEPAGE);
+#endif
+ }
+}
+
+#endif
diff --git a/thirdparty/embree/common/sys/alloc.h b/thirdparty/embree/common/sys/alloc.h
new file mode 100644
index 0000000000..4fa474ec1d
--- /dev/null
+++ b/thirdparty/embree/common/sys/alloc.h
@@ -0,0 +1,164 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+#include <vector>
+#include <set>
+
+namespace embree
+{
+#define ALIGNED_STRUCT_(align) \
+ void* operator new(size_t size) { return alignedMalloc(size,align); } \
+ void operator delete(void* ptr) { alignedFree(ptr); } \
+ void* operator new[](size_t size) { return alignedMalloc(size,align); } \
+ void operator delete[](void* ptr) { alignedFree(ptr); }
+
+#define ALIGNED_CLASS_(align) \
+ public: \
+ ALIGNED_STRUCT_(align) \
+ private:
+
+ /*! aligned allocation */
+ void* alignedMalloc(size_t size, size_t align);
+ void alignedFree(void* ptr);
+
+ /*! allocator that performs aligned allocations */
+ template<typename T, size_t alignment>
+ struct aligned_allocator
+ {
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ __forceinline pointer allocate( size_type n ) {
+ return (pointer) alignedMalloc(n*sizeof(value_type),alignment);
+ }
+
+ __forceinline void deallocate( pointer p, size_type n ) {
+ return alignedFree(p);
+ }
+
+ __forceinline void construct( pointer p, const_reference val ) {
+ new (p) T(val);
+ }
+
+ __forceinline void destroy( pointer p ) {
+ p->~T();
+ }
+ };
+
+ /*! allocates pages directly from OS */
+ bool win_enable_selockmemoryprivilege(bool verbose);
+ bool os_init(bool hugepages, bool verbose);
+ void* os_malloc (size_t bytes, bool& hugepages);
+ size_t os_shrink (void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages);
+ void os_free (void* ptr, size_t bytes, bool hugepages);
+ void os_advise (void* ptr, size_t bytes);
+
+ /*! allocator that performs OS allocations */
+ template<typename T>
+ struct os_allocator
+ {
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ __forceinline os_allocator ()
+ : hugepages(false) {}
+
+ __forceinline pointer allocate( size_type n ) {
+ return (pointer) os_malloc(n*sizeof(value_type),hugepages);
+ }
+
+ __forceinline void deallocate( pointer p, size_type n ) {
+ return os_free(p,n*sizeof(value_type),hugepages);
+ }
+
+ __forceinline void construct( pointer p, const_reference val ) {
+ new (p) T(val);
+ }
+
+ __forceinline void destroy( pointer p ) {
+ p->~T();
+ }
+
+ bool hugepages;
+ };
+
+ /*! allocator for IDs */
+ template<typename T, size_t max_id>
+ struct IDPool
+ {
+ typedef T value_type;
+
+ IDPool ()
+ : nextID(0) {}
+
+ T allocate()
+ {
+ /* return ID from list */
+ if (!IDs.empty())
+ {
+ T id = *IDs.begin();
+ IDs.erase(IDs.begin());
+ return id;
+ }
+
+ /* allocate new ID */
+ else
+ {
+ if (size_t(nextID)+1 > max_id)
+ return -1;
+
+ return nextID++;
+ }
+ }
+
+ /* adds an ID provided by the user */
+ bool add(T id)
+ {
+ if (id > max_id)
+ return false;
+
+ /* check if ID should be in IDs set */
+ if (id < nextID) {
+ auto p = IDs.find(id);
+ if (p == IDs.end()) return false;
+ IDs.erase(p);
+ return true;
+ }
+
+ /* otherwise increase ID set */
+ else
+ {
+ for (T i=nextID; i<id; i++) {
+ IDs.insert(i);
+ }
+ nextID = id+1;
+ return true;
+ }
+ }
+
+ void deallocate( T id )
+ {
+ assert(id < nextID);
+ MAYBE_UNUSED auto done = IDs.insert(id).second;
+ assert(done);
+ }
+
+ private:
+ std::set<T> IDs; //!< stores deallocated IDs to be reused
+ T nextID; //!< next ID to use when IDs vector is empty
+ };
+}
+
diff --git a/thirdparty/embree/common/sys/array.h b/thirdparty/embree/common/sys/array.h
new file mode 100644
index 0000000000..dd9190c52a
--- /dev/null
+++ b/thirdparty/embree/common/sys/array.h
@@ -0,0 +1,222 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+#include "alloc.h"
+
+namespace embree
+{
+ /*! static array with static size */
+ template<typename T, size_t N>
+ class array_t
+ {
+ public:
+
+ /********************** Iterators ****************************/
+
+ __forceinline T* begin() const { return items; };
+ __forceinline T* end () const { return items+N; };
+
+
+ /********************** Capacity ****************************/
+
+ __forceinline bool empty () const { return N == 0; }
+ __forceinline size_t size () const { return N; }
+ __forceinline size_t max_size () const { return N; }
+
+
+ /******************** Element access **************************/
+
+ __forceinline T& operator[](size_t i) { assert(i < N); return items[i]; }
+ __forceinline const T& operator[](size_t i) const { assert(i < N); return items[i]; }
+
+ __forceinline T& at(size_t i) { assert(i < N); return items[i]; }
+ __forceinline const T& at(size_t i) const { assert(i < N); return items[i]; }
+
+ __forceinline T& front() const { assert(N > 0); return items[0]; };
+ __forceinline T& back () const { assert(N > 0); return items[N-1]; };
+
+ __forceinline T* data() { return items; };
+ __forceinline const T* data() const { return items; };
+
+ private:
+ T items[N];
+ };
+
+ /*! static array with dynamic size */
+ template<typename T, size_t N>
+ class darray_t
+ {
+ public:
+
+ __forceinline darray_t () : M(0) {}
+
+ __forceinline darray_t (const T& v) : M(0) {
+ for (size_t i=0; i<N; i++) items[i] = v;
+ }
+
+ /********************** Iterators ****************************/
+
+ __forceinline T* begin() const { return items; };
+ __forceinline T* end () const { return items+M; };
+
+
+ /********************** Capacity ****************************/
+
+ __forceinline bool empty () const { return M == 0; }
+ __forceinline size_t size () const { return M; }
+ __forceinline size_t capacity () const { return N; }
+ __forceinline size_t max_size () const { return N; }
+
+ void resize(size_t new_size) {
+ assert(new_size < max_size());
+ M = new_size;
+ }
+
+ /******************** Modifiers **************************/
+
+ __forceinline void push_back(const T& v)
+ {
+ assert(M+1 < max_size());
+ items[M++] = v;
+ }
+
+ __forceinline void pop_back()
+ {
+ assert(!empty());
+ M--;
+ }
+
+ __forceinline void clear() {
+ M = 0;
+ }
+
+ /******************** Element access **************************/
+
+ __forceinline T& operator[](size_t i) { assert(i < M); return items[i]; }
+ __forceinline const T& operator[](size_t i) const { assert(i < M); return items[i]; }
+
+ __forceinline T& at(size_t i) { assert(i < M); return items[i]; }
+ __forceinline const T& at(size_t i) const { assert(i < M); return items[i]; }
+
+ __forceinline T& front() const { assert(M > 0); return items[0]; };
+ __forceinline T& back () const { assert(M > 0); return items[M-1]; };
+
+ __forceinline T* data() { return items; };
+ __forceinline const T* data() const { return items; };
+
+ private:
+ size_t M;
+ T items[N];
+ };
+
+ /*! dynamic sized array that is allocated on the stack */
+#define dynamic_large_stack_array(Ty,Name,N,max_stack_bytes) StackArray<Ty,max_stack_bytes> Name(N)
+ template<typename Ty, size_t max_stack_bytes>
+ struct __aligned(64) StackArray
+ {
+ __forceinline StackArray (const size_t N)
+ : N(N)
+ {
+ if (N*sizeof(Ty) <= max_stack_bytes)
+ data = &arr[0];
+ else
+ data = (Ty*) alignedMalloc(N*sizeof(Ty),64);
+ }
+
+ __forceinline ~StackArray () {
+ if (data != &arr[0]) alignedFree(data);
+ }
+
+ __forceinline operator Ty* () { return data; }
+ __forceinline operator const Ty* () const { return data; }
+
+ __forceinline Ty& operator[](const int i) { assert(i>=0 && i<N); return data[i]; }
+ __forceinline const Ty& operator[](const int i) const { assert(i>=0 && i<N); return data[i]; }
+
+ __forceinline Ty& operator[](const unsigned i) { assert(i<N); return data[i]; }
+ __forceinline const Ty& operator[](const unsigned i) const { assert(i<N); return data[i]; }
+
+#if defined(__64BIT__)
+ __forceinline Ty& operator[](const size_t i) { assert(i<N); return data[i]; }
+ __forceinline const Ty& operator[](const size_t i) const { assert(i<N); return data[i]; }
+#endif
+
+ private:
+ Ty arr[max_stack_bytes/sizeof(Ty)];
+ Ty* data;
+ size_t N;
+
+ private:
+ StackArray (const StackArray& other) DELETED; // do not implement
+ StackArray& operator= (const StackArray& other) DELETED; // do not implement
+
+ };
+
+ /*! dynamic sized array that is allocated on the stack */
+ template<typename Ty, size_t max_stack_elements, size_t max_total_elements>
+ struct __aligned(64) DynamicStackArray
+ {
+ __forceinline DynamicStackArray ()
+ : data(&arr[0]) {}
+
+ __forceinline ~DynamicStackArray ()
+ {
+ if (!isStackAllocated())
+ delete[] data;
+ }
+
+ __forceinline bool isStackAllocated() const {
+ return data == &arr[0];
+ }
+
+ __forceinline size_t size() const
+ {
+ if (isStackAllocated()) return max_stack_elements;
+ else return max_total_elements;
+ }
+
+ __forceinline void resize(size_t M)
+ {
+ assert(M <= max_total_elements);
+ if (likely(M <= max_stack_elements)) return;
+ if (likely(!isStackAllocated())) return;
+
+ data = new Ty[max_total_elements];
+
+ for (size_t i=0; i<max_stack_elements; i++)
+ data[i] = arr[i];
+ }
+
+ __forceinline operator Ty* () { return data; }
+ __forceinline operator const Ty* () const { return data; }
+
+ __forceinline Ty& operator[](const int i) { assert(i>=0 && i<max_total_elements); resize(i+1); return data[i]; }
+ __forceinline Ty& operator[](const unsigned i) { assert(i<max_total_elements); resize(i+1); return data[i]; }
+
+#if defined(__64BIT__)
+ __forceinline Ty& operator[](const size_t i) { assert(i<max_total_elements); resize(i+1); return data[i]; }
+#endif
+
+ __forceinline DynamicStackArray (const DynamicStackArray& other)
+ : data(&arr[0])
+ {
+ for (size_t i=0; i<other.size(); i++)
+ this->operator[] (i) = other[i];
+ }
+
+ DynamicStackArray& operator= (const DynamicStackArray& other)
+ {
+ for (size_t i=0; i<other.size(); i++)
+ this->operator[] (i) = other[i];
+
+ return *this;
+ }
+
+ private:
+ Ty arr[max_stack_elements];
+ Ty* data;
+ };
+}
diff --git a/thirdparty/embree/common/sys/atomic.h b/thirdparty/embree/common/sys/atomic.h
new file mode 100644
index 0000000000..67af254f36
--- /dev/null
+++ b/thirdparty/embree/common/sys/atomic.h
@@ -0,0 +1,59 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <atomic>
+#include "intrinsics.h"
+
+namespace embree
+{
+/* compiler memory barriers */
+#if defined(__INTEL_COMPILER)
+//#define __memory_barrier() __memory_barrier()
+#elif defined(__GNUC__) || defined(__clang__)
+# define __memory_barrier() asm volatile("" ::: "memory")
+#elif defined(_MSC_VER)
+# define __memory_barrier() _ReadWriteBarrier()
+#endif
+
+ template <typename T>
+ struct atomic : public std::atomic<T>
+ {
+ atomic () {}
+
+ atomic (const T& a)
+ : std::atomic<T>(a) {}
+
+ atomic (const atomic<T>& a) {
+ this->store(a.load());
+ }
+
+ atomic& operator=(const atomic<T>& other) {
+ this->store(other.load());
+ return *this;
+ }
+ };
+
+ template<typename T>
+ __forceinline void atomic_min(std::atomic<T>& aref, const T& bref)
+ {
+ const T b = bref.load();
+ while (true) {
+ T a = aref.load();
+ if (a <= b) break;
+ if (aref.compare_exchange_strong(a,b)) break;
+ }
+ }
+
+ template<typename T>
+ __forceinline void atomic_max(std::atomic<T>& aref, const T& bref)
+ {
+ const T b = bref.load();
+ while (true) {
+ T a = aref.load();
+ if (a >= b) break;
+ if (aref.compare_exchange_strong(a,b)) break;
+ }
+ }
+}
diff --git a/thirdparty/embree/common/sys/barrier.cpp b/thirdparty/embree/common/sys/barrier.cpp
new file mode 100644
index 0000000000..0c0e39d92d
--- /dev/null
+++ b/thirdparty/embree/common/sys/barrier.cpp
@@ -0,0 +1,289 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "barrier.h"
+#include "condition.h"
+#include "regression.h"
+#include "thread.h"
+
+#if defined (__WIN32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace embree
+{
+ struct BarrierSysImplementation
+ {
+ __forceinline BarrierSysImplementation (size_t N)
+ : i(0), enterCount(0), exitCount(0), barrierSize(0)
+ {
+ events[0] = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ events[1] = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ init(N);
+ }
+
+ __forceinline ~BarrierSysImplementation ()
+ {
+ CloseHandle(events[0]);
+ CloseHandle(events[1]);
+ }
+
+ __forceinline void init(size_t N)
+ {
+ barrierSize = N;
+ enterCount.store(N);
+ exitCount.store(N);
+ }
+
+ __forceinline void wait()
+ {
+ /* every thread entering the barrier decrements this count */
+ size_t i0 = i;
+ size_t cnt0 = enterCount--;
+
+ /* all threads except the last one are wait in the barrier */
+ if (cnt0 > 1)
+ {
+ if (WaitForSingleObject(events[i0], INFINITE) != WAIT_OBJECT_0)
+ THROW_RUNTIME_ERROR("WaitForSingleObjects failed");
+ }
+
+ /* the last thread starts all threads waiting at the barrier */
+ else
+ {
+ i = 1-i;
+ enterCount.store(barrierSize);
+ if (SetEvent(events[i0]) == 0)
+ THROW_RUNTIME_ERROR("SetEvent failed");
+ }
+
+ /* every thread leaving the barrier decrements this count */
+ size_t cnt1 = exitCount--;
+
+ /* the last thread that left the barrier resets the event again */
+ if (cnt1 == 1)
+ {
+ exitCount.store(barrierSize);
+ if (ResetEvent(events[i0]) == 0)
+ THROW_RUNTIME_ERROR("ResetEvent failed");
+ }
+ }
+
+ public:
+ HANDLE events[2];
+ atomic<size_t> i;
+ atomic<size_t> enterCount;
+ atomic<size_t> exitCount;
+ size_t barrierSize;
+ };
+}
+
+#else
+
+namespace embree
+{
+ struct BarrierSysImplementation
+ {
+ __forceinline BarrierSysImplementation (size_t N)
+ : count(0), barrierSize(0)
+ {
+ init(N);
+ }
+
+ __forceinline void init(size_t N)
+ {
+ assert(count == 0);
+ count = 0;
+ barrierSize = N;
+ }
+
+ __forceinline void wait()
+ {
+ mutex.lock();
+ count++;
+
+ if (count == barrierSize) {
+ count = 0;
+ cond.notify_all();
+ mutex.unlock();
+ return;
+ }
+
+ cond.wait(mutex);
+ mutex.unlock();
+ return;
+ }
+
+ public:
+ MutexSys mutex;
+ ConditionSys cond;
+ volatile size_t count;
+ volatile size_t barrierSize;
+ };
+}
+
+#endif
+
+namespace embree
+{
+ BarrierSys::BarrierSys (size_t N) {
+ opaque = new BarrierSysImplementation(N);
+ }
+
+ BarrierSys::~BarrierSys () {
+ delete (BarrierSysImplementation*) opaque;
+ }
+
+ void BarrierSys::init(size_t count) {
+ ((BarrierSysImplementation*) opaque)->init(count);
+ }
+
+ void BarrierSys::wait() {
+ ((BarrierSysImplementation*) opaque)->wait();
+ }
+
+ LinearBarrierActive::LinearBarrierActive (size_t N)
+ : count0(nullptr), count1(nullptr), mode(0), flag0(0), flag1(0), threadCount(0)
+ {
+ if (N == 0) N = getNumberOfLogicalThreads();
+ init(N);
+ }
+
+ LinearBarrierActive::~LinearBarrierActive()
+ {
+ delete[] count0;
+ delete[] count1;
+ }
+
+ void LinearBarrierActive::init(size_t N)
+ {
+ if (threadCount != N) {
+ threadCount = N;
+ if (count0) delete[] count0; count0 = new unsigned char[N];
+ if (count1) delete[] count1; count1 = new unsigned char[N];
+ }
+ mode = 0;
+ flag0 = 0;
+ flag1 = 0;
+ for (size_t i=0; i<N; i++) count0[i] = 0;
+ for (size_t i=0; i<N; i++) count1[i] = 0;
+ }
+
+ void LinearBarrierActive::wait (const size_t threadIndex)
+ {
+ if (mode == 0)
+ {
+ if (threadIndex == 0)
+ {
+ for (size_t i=0; i<threadCount; i++)
+ count1[i] = 0;
+
+ for (size_t i=1; i<threadCount; i++)
+ {
+ while (likely(count0[i] == 0))
+ pause_cpu();
+ }
+ mode = 1;
+ flag1 = 0;
+ __memory_barrier();
+ flag0 = 1;
+ }
+ else
+ {
+ count0[threadIndex] = 1;
+ {
+ while (likely(flag0 == 0))
+ pause_cpu();
+ }
+
+ }
+ }
+ else
+ {
+ if (threadIndex == 0)
+ {
+ for (size_t i=0; i<threadCount; i++)
+ count0[i] = 0;
+
+ for (size_t i=1; i<threadCount; i++)
+ {
+ while (likely(count1[i] == 0))
+ pause_cpu();
+ }
+
+ mode = 0;
+ flag0 = 0;
+ __memory_barrier();
+ flag1 = 1;
+ }
+ else
+ {
+ count1[threadIndex] = 1;
+ {
+ while (likely(flag1 == 0))
+ pause_cpu();
+ }
+ }
+ }
+ }
+
+ struct barrier_sys_regression_test : public RegressionTest
+ {
+ BarrierSys barrier;
+ std::atomic<size_t> threadID;
+ std::atomic<size_t> numFailed;
+ std::vector<size_t> threadResults;
+
+ barrier_sys_regression_test()
+ : RegressionTest("barrier_sys_regression_test"), threadID(0), numFailed(0)
+ {
+ registerRegressionTest(this);
+ }
+
+ static void thread_alloc(barrier_sys_regression_test* This)
+ {
+ size_t tid = This->threadID++;
+ for (size_t j=0; j<1000; j++)
+ {
+ This->barrier.wait();
+ This->threadResults[tid] = tid;
+ This->barrier.wait();
+ }
+ }
+
+ bool run ()
+ {
+ threadID.store(0);
+ numFailed.store(0);
+
+ size_t numThreads = getNumberOfLogicalThreads();
+ threadResults.resize(numThreads);
+ barrier.init(numThreads+1);
+
+ /* create threads */
+ std::vector<thread_t> threads;
+ for (size_t i=0; i<numThreads; i++)
+ threads.push_back(createThread((thread_func)thread_alloc,this));
+
+ /* run test */
+ for (size_t i=0; i<1000; i++)
+ {
+ for (size_t i=0; i<numThreads; i++) threadResults[i] = 0;
+ barrier.wait();
+ barrier.wait();
+ for (size_t i=0; i<numThreads; i++) numFailed += threadResults[i] != i;
+ }
+
+ /* destroy threads */
+ for (size_t i=0; i<numThreads; i++)
+ join(threads[i]);
+
+ return numFailed == 0;
+ }
+ };
+
+ barrier_sys_regression_test barrier_sys_regression_test;
+}
+
+
diff --git a/thirdparty/embree/common/sys/barrier.h b/thirdparty/embree/common/sys/barrier.h
new file mode 100644
index 0000000000..37fc036291
--- /dev/null
+++ b/thirdparty/embree/common/sys/barrier.h
@@ -0,0 +1,112 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "intrinsics.h"
+#include "sysinfo.h"
+#include "atomic.h"
+
+namespace embree
+{
+ /*! system barrier using operating system */
+ class BarrierSys
+ {
+ public:
+
+ /*! construction / destruction */
+ BarrierSys (size_t N = 0);
+ ~BarrierSys ();
+
+ private:
+ /*! class in non-copyable */
+ BarrierSys (const BarrierSys& other) DELETED; // do not implement
+ BarrierSys& operator= (const BarrierSys& other) DELETED; // do not implement
+
+ public:
+ /*! intializes the barrier with some number of threads */
+ void init(size_t count);
+
+ /*! lets calling thread wait in barrier */
+ void wait();
+
+ private:
+ void* opaque;
+ };
+
+ /*! fast active barrier using atomitc counter */
+ struct BarrierActive
+ {
+ public:
+ BarrierActive ()
+ : cntr(0) {}
+
+ void reset() {
+ cntr.store(0);
+ }
+
+ void wait (size_t numThreads)
+ {
+ cntr++;
+ while (cntr.load() != numThreads)
+ pause_cpu();
+ }
+
+ private:
+ std::atomic<size_t> cntr;
+ };
+
+ /*! fast active barrier that does not require initialization to some number of threads */
+ struct BarrierActiveAutoReset
+ {
+ public:
+ BarrierActiveAutoReset ()
+ : cntr0(0), cntr1(0) {}
+
+ void wait (size_t threadCount)
+ {
+ cntr0.fetch_add(1);
+ while (cntr0 != threadCount) pause_cpu();
+ cntr1.fetch_add(1);
+ while (cntr1 != threadCount) pause_cpu();
+ cntr0.fetch_add(-1);
+ while (cntr0 != 0) pause_cpu();
+ cntr1.fetch_add(-1);
+ while (cntr1 != 0) pause_cpu();
+ }
+
+ private:
+ std::atomic<size_t> cntr0;
+ std::atomic<size_t> cntr1;
+ };
+
+ class LinearBarrierActive
+ {
+ public:
+
+ /*! construction and destruction */
+ LinearBarrierActive (size_t threadCount = 0);
+ ~LinearBarrierActive();
+
+ private:
+ /*! class in non-copyable */
+ LinearBarrierActive (const LinearBarrierActive& other) DELETED; // do not implement
+ LinearBarrierActive& operator= (const LinearBarrierActive& other) DELETED; // do not implement
+
+ public:
+ /*! intializes the barrier with some number of threads */
+ void init(size_t threadCount);
+
+ /*! thread with threadIndex waits in the barrier */
+ void wait (const size_t threadIndex);
+
+ private:
+ volatile unsigned char* count0;
+ volatile unsigned char* count1;
+ volatile unsigned int mode;
+ volatile unsigned int flag0;
+ volatile unsigned int flag1;
+ volatile size_t threadCount;
+ };
+}
+
diff --git a/thirdparty/embree/common/sys/condition.cpp b/thirdparty/embree/common/sys/condition.cpp
new file mode 100644
index 0000000000..606a1d0b04
--- /dev/null
+++ b/thirdparty/embree/common/sys/condition.cpp
@@ -0,0 +1,85 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "condition.h"
+
+#if defined(__WIN32__) && !defined(PTHREADS_WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace embree
+{
+ struct ConditionImplementation
+ {
+ __forceinline ConditionImplementation () {
+ InitializeConditionVariable(&cond);
+ }
+
+ __forceinline ~ConditionImplementation () {
+ }
+
+ __forceinline void wait(MutexSys& mutex_in) {
+ SleepConditionVariableCS(&cond, (LPCRITICAL_SECTION)mutex_in.mutex, INFINITE);
+ }
+
+ __forceinline void notify_all() {
+ WakeAllConditionVariable(&cond);
+ }
+
+ public:
+ CONDITION_VARIABLE cond;
+ };
+}
+#endif
+
+#if defined(__UNIX__) || defined(PTHREADS_WIN32)
+#include <pthread.h>
+namespace embree
+{
+ struct ConditionImplementation
+ {
+ __forceinline ConditionImplementation () {
+ if (pthread_cond_init(&cond,nullptr) != 0)
+ THROW_RUNTIME_ERROR("pthread_cond_init failed");
+ }
+
+ __forceinline ~ConditionImplementation() {
+ MAYBE_UNUSED bool ok = pthread_cond_destroy(&cond) == 0;
+ assert(ok);
+ }
+
+ __forceinline void wait(MutexSys& mutex) {
+ if (pthread_cond_wait(&cond, (pthread_mutex_t*)mutex.mutex) != 0)
+ THROW_RUNTIME_ERROR("pthread_cond_wait failed");
+ }
+
+ __forceinline void notify_all() {
+ if (pthread_cond_broadcast(&cond) != 0)
+ THROW_RUNTIME_ERROR("pthread_cond_broadcast failed");
+ }
+
+ public:
+ pthread_cond_t cond;
+ };
+}
+#endif
+
+namespace embree
+{
+ ConditionSys::ConditionSys () {
+ cond = new ConditionImplementation;
+ }
+
+ ConditionSys::~ConditionSys() {
+ delete (ConditionImplementation*) cond;
+ }
+
+ void ConditionSys::wait(MutexSys& mutex) {
+ ((ConditionImplementation*) cond)->wait(mutex);
+ }
+
+ void ConditionSys::notify_all() {
+ ((ConditionImplementation*) cond)->notify_all();
+ }
+}
diff --git a/thirdparty/embree/common/sys/condition.h b/thirdparty/embree/common/sys/condition.h
new file mode 100644
index 0000000000..557c6e3482
--- /dev/null
+++ b/thirdparty/embree/common/sys/condition.h
@@ -0,0 +1,31 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "mutex.h"
+
+namespace embree
+{
+ class ConditionSys
+ {
+ public:
+ ConditionSys();
+ ~ConditionSys();
+ void wait( class MutexSys& mutex );
+ void notify_all();
+
+ template<typename Predicate>
+ __forceinline void wait( class MutexSys& mutex, const Predicate& pred )
+ {
+ while (!pred()) wait(mutex);
+ }
+
+ private:
+ ConditionSys (const ConditionSys& other) DELETED; // do not implement
+ ConditionSys& operator= (const ConditionSys& other) DELETED; // do not implement
+
+ protected:
+ void* cond;
+ };
+}
diff --git a/thirdparty/embree/common/sys/filename.cpp b/thirdparty/embree/common/sys/filename.cpp
new file mode 100644
index 0000000000..f55b224302
--- /dev/null
+++ b/thirdparty/embree/common/sys/filename.cpp
@@ -0,0 +1,138 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "filename.h"
+#include "sysinfo.h"
+
+namespace embree
+{
+#ifdef __WIN32__
+ const char path_sep = '\\';
+#else
+ const char path_sep = '/';
+#endif
+
+ /*! create an empty filename */
+ FileName::FileName () {}
+
+ /*! create a valid filename from a string */
+ FileName::FileName (const char* in) {
+ filename = in;
+ for (size_t i=0; i<filename.size(); i++)
+ if (filename[i] == '\\' || filename[i] == '/')
+ filename[i] = path_sep;
+ while (!filename.empty() && filename[filename.size()-1] == path_sep)
+ filename.resize(filename.size()-1);
+ }
+
+ /*! create a valid filename from a string */
+ FileName::FileName (const std::string& in) {
+ filename = in;
+ for (size_t i=0; i<filename.size(); i++)
+ if (filename[i] == '\\' || filename[i] == '/')
+ filename[i] = path_sep;
+ while (!filename.empty() && filename[filename.size()-1] == path_sep)
+ filename.resize(filename.size()-1);
+ }
+
+ /*! returns path to home folder */
+ FileName FileName::homeFolder()
+ {
+#ifdef __WIN32__
+ const char* home = getenv("UserProfile");
+#else
+ const char* home = getenv("HOME");
+#endif
+ if (home) return home;
+ return "";
+ }
+
+ /*! returns path to executable */
+ FileName FileName::executableFolder() {
+ return FileName(getExecutableFileName()).path();
+ }
+
+ /*! returns the path */
+ FileName FileName::path() const {
+ size_t pos = filename.find_last_of(path_sep);
+ if (pos == std::string::npos) return FileName();
+ return filename.substr(0,pos);
+ }
+
+ /*! returns the basename */
+ std::string FileName::base() const {
+ size_t pos = filename.find_last_of(path_sep);
+ if (pos == std::string::npos) return filename;
+ return filename.substr(pos+1);
+ }
+
+ /*! returns the extension */
+ std::string FileName::ext() const {
+ size_t pos = filename.find_last_of('.');
+ if (pos == std::string::npos) return "";
+ return filename.substr(pos+1);
+ }
+
+ /*! returns the extension */
+ FileName FileName::dropExt() const {
+ size_t pos = filename.find_last_of('.');
+ if (pos == std::string::npos) return filename;
+ return filename.substr(0,pos);
+ }
+
+ /*! returns the basename without extension */
+ std::string FileName::name() const {
+ size_t start = filename.find_last_of(path_sep);
+ if (start == std::string::npos) start = 0; else start++;
+ size_t end = filename.find_last_of('.');
+ if (end == std::string::npos || end < start) end = filename.size();
+ return filename.substr(start, end - start);
+ }
+
+ /*! replaces the extension */
+ FileName FileName::setExt(const std::string& ext) const {
+ size_t start = filename.find_last_of(path_sep);
+ if (start == std::string::npos) start = 0; else start++;
+ size_t end = filename.find_last_of('.');
+ if (end == std::string::npos || end < start) return FileName(filename+ext);
+ return FileName(filename.substr(0,end)+ext);
+ }
+
+ /*! adds the extension */
+ FileName FileName::addExt(const std::string& ext) const {
+ return FileName(filename+ext);
+ }
+
+ /*! concatenates two filenames to this/other */
+ FileName FileName::operator +( const FileName& other ) const {
+ if (filename == "") return FileName(other);
+ else return FileName(filename + path_sep + other.filename);
+ }
+
+ /*! concatenates two filenames to this/other */
+ FileName FileName::operator +( const std::string& other ) const {
+ return operator+(FileName(other));
+ }
+
+ /*! removes the base from a filename (if possible) */
+ FileName FileName::operator -( const FileName& base ) const {
+ size_t pos = filename.find_first_of(base);
+ if (pos == std::string::npos) return *this;
+ return FileName(filename.substr(pos+1));
+ }
+
+ /*! == operator */
+ bool operator== (const FileName& a, const FileName& b) {
+ return a.filename == b.filename;
+ }
+
+ /*! != operator */
+ bool operator!= (const FileName& a, const FileName& b) {
+ return a.filename != b.filename;
+ }
+
+ /*! output operator */
+ std::ostream& operator<<(std::ostream& cout, const FileName& filename) {
+ return cout << filename.filename;
+ }
+}
diff --git a/thirdparty/embree/common/sys/filename.h b/thirdparty/embree/common/sys/filename.h
new file mode 100644
index 0000000000..d5929cd836
--- /dev/null
+++ b/thirdparty/embree/common/sys/filename.h
@@ -0,0 +1,81 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+
+namespace embree
+{
+ /*! Convenience class for handling file names and paths. */
+ class FileName
+ {
+ public:
+
+ /*! create an empty filename */
+ FileName ();
+
+ /*! create a valid filename from a string */
+ FileName (const char* filename);
+
+ /*! create a valid filename from a string */
+ FileName (const std::string& filename);
+
+ /*! returns path to home folder */
+ static FileName homeFolder();
+
+ /*! returns path to executable */
+ static FileName executableFolder();
+
+ /*! auto convert into a string */
+ operator std::string() const { return filename; }
+
+ /*! returns a string of the filename */
+ const std::string str() const { return filename; }
+
+ /*! returns a c-string of the filename */
+ const char* c_str() const { return filename.c_str(); }
+
+ /*! returns the path of a filename */
+ FileName path() const;
+
+ /*! returns the file of a filename */
+ std::string base() const;
+
+ /*! returns the base of a filename without extension */
+ std::string name() const;
+
+ /*! returns the file extension */
+ std::string ext() const;
+
+ /*! drops the file extension */
+ FileName dropExt() const;
+
+ /*! replaces the file extension */
+ FileName setExt(const std::string& ext = "") const;
+
+ /*! adds file extension */
+ FileName addExt(const std::string& ext = "") const;
+
+ /*! concatenates two filenames to this/other */
+ FileName operator +( const FileName& other ) const;
+
+ /*! concatenates two filenames to this/other */
+ FileName operator +( const std::string& other ) const;
+
+ /*! removes the base from a filename (if possible) */
+ FileName operator -( const FileName& base ) const;
+
+ /*! == operator */
+ friend bool operator==(const FileName& a, const FileName& b);
+
+ /*! != operator */
+ friend bool operator!=(const FileName& a, const FileName& b);
+
+ /*! output operator */
+ friend std::ostream& operator<<(std::ostream& cout, const FileName& filename);
+
+ private:
+ std::string filename;
+ };
+}
diff --git a/thirdparty/embree/common/sys/intrinsics.h b/thirdparty/embree/common/sys/intrinsics.h
new file mode 100644
index 0000000000..ed8dd7d40a
--- /dev/null
+++ b/thirdparty/embree/common/sys/intrinsics.h
@@ -0,0 +1,525 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+
+#if defined(__WIN32__)
+#include <intrin.h>
+#endif
+
+#if defined(__ARM_NEON)
+#include "../simd/arm/emulation.h"
+#else
+#include <immintrin.h>
+#endif
+
+#if defined(__BMI__) && defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ #if !defined(_tzcnt_u32)
+ #define _tzcnt_u32 __tzcnt_u32
+ #endif
+ #if !defined(_tzcnt_u64)
+ #define _tzcnt_u64 __tzcnt_u64
+ #endif
+#endif
+
+#if defined(__LZCNT__)
+ #if !defined(_lzcnt_u32)
+ #define _lzcnt_u32 __lzcnt32
+ #endif
+ #if !defined(_lzcnt_u64)
+ #define _lzcnt_u64 __lzcnt64
+ #endif
+#endif
+
+#if defined(__WIN32__)
+// -- GODOT start --
+#if !defined(NOMINMAX)
+// -- GODOT end --
+#define NOMINMAX
+// -- GODOT start --
+#endif
+#include "windows.h"
+// -- GODOT end --
+#endif
+
+/* normally defined in pmmintrin.h, but we always need this */
+#if !defined(_MM_SET_DENORMALS_ZERO_MODE)
+#define _MM_DENORMALS_ZERO_ON (0x0040)
+#define _MM_DENORMALS_ZERO_OFF (0x0000)
+#define _MM_DENORMALS_ZERO_MASK (0x0040)
+#define _MM_SET_DENORMALS_ZERO_MODE(x) (_mm_setcsr((_mm_getcsr() & ~_MM_DENORMALS_ZERO_MASK) | (x)))
+#endif
+
+namespace embree
+{
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__WIN32__)
+
+ __forceinline size_t read_tsc()
+ {
+ LARGE_INTEGER li;
+ QueryPerformanceCounter(&li);
+ return (size_t)li.QuadPart;
+ }
+
+ __forceinline int bsf(int v) {
+#if defined(__AVX2__)
+ return _tzcnt_u32(v);
+#else
+ unsigned long r = 0; _BitScanForward(&r,v); return r;
+#endif
+ }
+
+ __forceinline unsigned bsf(unsigned v) {
+#if defined(__AVX2__)
+ return _tzcnt_u32(v);
+#else
+ unsigned long r = 0; _BitScanForward(&r,v); return r;
+#endif
+ }
+
+#if defined(__X86_64__)
+ __forceinline size_t bsf(size_t v) {
+#if defined(__AVX2__)
+ return _tzcnt_u64(v);
+#else
+ unsigned long r = 0; _BitScanForward64(&r,v); return r;
+#endif
+ }
+#endif
+
+ __forceinline int bscf(int& v)
+ {
+ int i = bsf(v);
+ v &= v-1;
+ return i;
+ }
+
+ __forceinline unsigned bscf(unsigned& v)
+ {
+ unsigned i = bsf(v);
+ v &= v-1;
+ return i;
+ }
+
+#if defined(__X86_64__)
+ __forceinline size_t bscf(size_t& v)
+ {
+ size_t i = bsf(v);
+ v &= v-1;
+ return i;
+ }
+#endif
+
+ __forceinline int bsr(int v) {
+#if defined(__AVX2__)
+ return 31 - _lzcnt_u32(v);
+#else
+ unsigned long r = 0; _BitScanReverse(&r,v); return r;
+#endif
+ }
+
+ __forceinline unsigned bsr(unsigned v) {
+#if defined(__AVX2__)
+ return 31 - _lzcnt_u32(v);
+#else
+ unsigned long r = 0; _BitScanReverse(&r,v); return r;
+#endif
+ }
+
+#if defined(__X86_64__)
+ __forceinline size_t bsr(size_t v) {
+#if defined(__AVX2__)
+ return 63 -_lzcnt_u64(v);
+#else
+ unsigned long r = 0; _BitScanReverse64(&r, v); return r;
+#endif
+ }
+#endif
+
+ __forceinline int lzcnt(const int x)
+ {
+#if defined(__AVX2__)
+ return _lzcnt_u32(x);
+#else
+ if (unlikely(x == 0)) return 32;
+ return 31 - bsr(x);
+#endif
+ }
+
+ __forceinline int btc(int v, int i) {
+ long r = v; _bittestandcomplement(&r,i); return r;
+ }
+
+ __forceinline int bts(int v, int i) {
+ long r = v; _bittestandset(&r,i); return r;
+ }
+
+ __forceinline int btr(int v, int i) {
+ long r = v; _bittestandreset(&r,i); return r;
+ }
+
+#if defined(__X86_64__)
+
+ __forceinline size_t btc(size_t v, size_t i) {
+ size_t r = v; _bittestandcomplement64((__int64*)&r,i); return r;
+ }
+
+ __forceinline size_t bts(size_t v, size_t i) {
+ __int64 r = v; _bittestandset64(&r,i); return r;
+ }
+
+ __forceinline size_t btr(size_t v, size_t i) {
+ __int64 r = v; _bittestandreset64(&r,i); return r;
+ }
+
+#endif
+
+ __forceinline int32_t atomic_cmpxchg(volatile int32_t* p, const int32_t c, const int32_t v) {
+ return _InterlockedCompareExchange((volatile long*)p,v,c);
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#else
+
+#if defined(__i386__) && defined(__PIC__)
+
+ __forceinline void __cpuid(int out[4], int op)
+ {
+ asm volatile ("xchg{l}\t{%%}ebx, %1\n\t"
+ "cpuid\n\t"
+ "xchg{l}\t{%%}ebx, %1\n\t"
+ : "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3])
+ : "0"(op));
+ }
+
+ __forceinline void __cpuid_count(int out[4], int op1, int op2)
+ {
+ asm volatile ("xchg{l}\t{%%}ebx, %1\n\t"
+ "cpuid\n\t"
+ "xchg{l}\t{%%}ebx, %1\n\t"
+ : "=a" (out[0]), "=r" (out[1]), "=c" (out[2]), "=d" (out[3])
+ : "0" (op1), "2" (op2));
+ }
+
+#elif defined(__X86_ASM__)
+
+ __forceinline void __cpuid(int out[4], int op) {
+ asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op));
+ }
+
+ __forceinline void __cpuid_count(int out[4], int op1, int op2) {
+ asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op1), "c"(op2));
+ }
+
+#endif
+
+ __forceinline uint64_t read_tsc() {
+#if defined(__X86_ASM__)
+ uint32_t high,low;
+ asm volatile ("rdtsc" : "=d"(high), "=a"(low));
+ return (((uint64_t)high) << 32) + (uint64_t)low;
+#else
+ /* Not supported yet, meaning measuring traversal cost per pixel does not work. */
+ return 0;
+#endif
+ }
+
+ __forceinline int bsf(int v) {
+#if defined(__AVX2__)
+ return _tzcnt_u32(v);
+#elif defined(__X86_ASM__)
+ int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+#else
+ return __builtin_ctz(v);
+#endif
+ }
+
+#if defined(__64BIT__)
+ __forceinline unsigned bsf(unsigned v)
+ {
+#if defined(__AVX2__)
+ return _tzcnt_u32(v);
+#elif defined(__X86_ASM__)
+ unsigned r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+#else
+ return __builtin_ctz(v);
+#endif
+ }
+#endif
+
+ __forceinline size_t bsf(size_t v) {
+#if defined(__AVX2__)
+#if defined(__X86_64__)
+ return _tzcnt_u64(v);
+#else
+ return _tzcnt_u32(v);
+#endif
+#elif defined(__X86_ASM__)
+ size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+#else
+ return __builtin_ctzl(v);
+#endif
+ }
+
+ __forceinline int bscf(int& v)
+ {
+ int i = bsf(v);
+ v &= v-1;
+ return i;
+ }
+
+#if defined(__64BIT__)
+ __forceinline unsigned int bscf(unsigned int& v)
+ {
+ unsigned int i = bsf(v);
+ v &= v-1;
+ return i;
+ }
+#endif
+
+ __forceinline size_t bscf(size_t& v)
+ {
+ size_t i = bsf(v);
+ v &= v-1;
+ return i;
+ }
+
+ __forceinline int bsr(int v) {
+#if defined(__AVX2__)
+ return 31 - _lzcnt_u32(v);
+#elif defined(__X86_ASM__)
+ int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+#else
+ return __builtin_clz(v) ^ 31;
+#endif
+ }
+
+#if defined(__64BIT__)
+ __forceinline unsigned bsr(unsigned v) {
+#if defined(__AVX2__)
+ return 31 - _lzcnt_u32(v);
+#elif defined(__X86_ASM__)
+ unsigned r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+#else
+ return __builtin_clz(v) ^ 31;
+#endif
+ }
+#endif
+
+ __forceinline size_t bsr(size_t v) {
+#if defined(__AVX2__)
+#if defined(__X86_64__)
+ return 63 - _lzcnt_u64(v);
+#else
+ return 31 - _lzcnt_u32(v);
+#endif
+#elif defined(__X86_ASM__)
+ size_t r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+#else
+ return (sizeof(v) * 8 - 1) - __builtin_clzl(v);
+#endif
+ }
+
+ __forceinline int lzcnt(const int x)
+ {
+#if defined(__AVX2__)
+ return _lzcnt_u32(x);
+#else
+ if (unlikely(x == 0)) return 32;
+ return 31 - bsr(x);
+#endif
+ }
+
+ __forceinline size_t blsr(size_t v) {
+#if defined(__AVX2__)
+#if defined(__INTEL_COMPILER)
+ return _blsr_u64(v);
+#else
+#if defined(__X86_64__)
+ return __blsr_u64(v);
+#else
+ return __blsr_u32(v);
+#endif
+#endif
+#else
+ return v & (v-1);
+#endif
+ }
+
+ __forceinline int btc(int v, int i) {
+#if defined(__X86_ASM__)
+ int r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r;
+#else
+ return (v ^ (1 << i));
+#endif
+ }
+
+ __forceinline int bts(int v, int i) {
+#if defined(__X86_ASM__)
+ int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+#else
+ return (v | (v << i));
+#endif
+ }
+
+ __forceinline int btr(int v, int i) {
+#if defined(__X86_ASM__)
+ int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+#else
+ return (v & ~(v << i));
+#endif
+ }
+
+ __forceinline size_t btc(size_t v, size_t i) {
+#if defined(__X86_ASM__)
+ size_t r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r;
+#else
+ return (v ^ (1 << i));
+#endif
+ }
+
+ __forceinline size_t bts(size_t v, size_t i) {
+#if defined(__X86_ASM__)
+ size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+#else
+ return (v | (v << i));
+#endif
+ }
+
+ __forceinline size_t btr(size_t v, size_t i) {
+#if defined(__X86_ASM__)
+ size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+#else
+ return (v & ~(v << i));
+#endif
+ }
+
+ __forceinline int32_t atomic_cmpxchg(int32_t volatile* value, int32_t comparand, const int32_t input) {
+ return __sync_val_compare_and_swap(value, comparand, input);
+ }
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// All Platforms
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__clang__) || defined(__GNUC__)
+#if !defined(_mm_undefined_ps)
+ __forceinline __m128 _mm_undefined_ps() { return _mm_setzero_ps(); }
+#endif
+#if !defined(_mm_undefined_si128)
+ __forceinline __m128i _mm_undefined_si128() { return _mm_setzero_si128(); }
+#endif
+#if !defined(_mm256_undefined_ps) && defined(__AVX__)
+ __forceinline __m256 _mm256_undefined_ps() { return _mm256_setzero_ps(); }
+#endif
+#if !defined(_mm256_undefined_si256) && defined(__AVX__)
+ __forceinline __m256i _mm256_undefined_si256() { return _mm256_setzero_si256(); }
+#endif
+#if !defined(_mm512_undefined_ps) && defined(__AVX512F__)
+ __forceinline __m512 _mm512_undefined_ps() { return _mm512_setzero_ps(); }
+#endif
+#if !defined(_mm512_undefined_epi32) && defined(__AVX512F__)
+ __forceinline __m512i _mm512_undefined_epi32() { return _mm512_setzero_si512(); }
+#endif
+#endif
+
+#if defined(__SSE4_2__)
+
+ __forceinline int popcnt(int in) {
+ return _mm_popcnt_u32(in);
+ }
+
+ __forceinline unsigned popcnt(unsigned in) {
+ return _mm_popcnt_u32(in);
+ }
+
+#if defined(__64BIT__)
+ __forceinline size_t popcnt(size_t in) {
+ return _mm_popcnt_u64(in);
+ }
+#endif
+
+#endif
+
+#if defined(__X86_ASM__)
+ __forceinline uint64_t rdtsc()
+ {
+ int dummy[4];
+ __cpuid(dummy,0);
+ uint64_t clock = read_tsc();
+ __cpuid(dummy,0);
+ return clock;
+ }
+#endif
+
+ __forceinline void pause_cpu(const size_t N = 8)
+ {
+ for (size_t i=0; i<N; i++)
+ _mm_pause();
+ }
+
+ /* prefetches */
+ __forceinline void prefetchL1 (const void* ptr) { _mm_prefetch((const char*)ptr,_MM_HINT_T0); }
+ __forceinline void prefetchL2 (const void* ptr) { _mm_prefetch((const char*)ptr,_MM_HINT_T1); }
+ __forceinline void prefetchL3 (const void* ptr) { _mm_prefetch((const char*)ptr,_MM_HINT_T2); }
+ __forceinline void prefetchNTA(const void* ptr) { _mm_prefetch((const char*)ptr,_MM_HINT_NTA); }
+ __forceinline void prefetchEX (const void* ptr) {
+#if defined(__INTEL_COMPILER)
+ _mm_prefetch((const char*)ptr,_MM_HINT_ET0);
+#else
+ _mm_prefetch((const char*)ptr,_MM_HINT_T0);
+#endif
+ }
+
+ __forceinline void prefetchL1EX(const void* ptr) {
+ prefetchEX(ptr);
+ }
+
+ __forceinline void prefetchL2EX(const void* ptr) {
+ prefetchEX(ptr);
+ }
+#if defined(__AVX2__)
+ __forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); }
+ __forceinline unsigned int pdep(unsigned int a, unsigned int b) { return _pdep_u32(a, b); }
+#if defined(__X86_64__)
+ __forceinline size_t pext(size_t a, size_t b) { return _pext_u64(a, b); }
+ __forceinline size_t pdep(size_t a, size_t b) { return _pdep_u64(a, b); }
+#endif
+#endif
+
+#if defined(__AVX512F__)
+#if defined(__INTEL_COMPILER)
+ __forceinline float mm512_cvtss_f32(__m512 v) {
+ return _mm512_cvtss_f32(v);
+ }
+ __forceinline int mm512_mask2int(__mmask16 k1) {
+ return _mm512_mask2int(k1);
+ }
+ __forceinline __mmask16 mm512_int2mask(int mask) {
+ return _mm512_int2mask(mask);
+ }
+#else
+ __forceinline float mm512_cvtss_f32(__m512 v) { // FIXME: _mm512_cvtss_f32 neither supported by clang v4.0.0 nor GCC 6.3
+ return _mm_cvtss_f32(_mm512_castps512_ps128(v));
+ }
+ __forceinline int mm512_mask2int(__mmask16 k1) { // FIXME: _mm512_mask2int not yet supported by GCC 6.3
+ return (int)k1;
+ }
+ __forceinline __mmask16 mm512_int2mask(int mask) { // FIXME: _mm512_int2mask not yet supported by GCC 6.3
+ return (__mmask16)mask;
+ }
+#endif
+#endif
+}
diff --git a/thirdparty/embree/common/sys/library.cpp b/thirdparty/embree/common/sys/library.cpp
new file mode 100644
index 0000000000..fc983dffd5
--- /dev/null
+++ b/thirdparty/embree/common/sys/library.cpp
@@ -0,0 +1,83 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "library.h"
+#include "sysinfo.h"
+#include "filename.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__WIN32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace embree
+{
+ /* opens a shared library */
+ lib_t openLibrary(const std::string& file)
+ {
+ std::string fullName = file+".dll";
+ FileName executable = getExecutableFileName();
+ HANDLE handle = LoadLibrary((executable.path() + fullName).c_str());
+ return lib_t(handle);
+ }
+
+ /* returns address of a symbol from the library */
+ void* getSymbol(lib_t lib, const std::string& sym) {
+ return (void*)GetProcAddress(HMODULE(lib),sym.c_str());
+ }
+
+ /* closes the shared library */
+ void closeLibrary(lib_t lib) {
+ FreeLibrary(HMODULE(lib));
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <dlfcn.h>
+
+namespace embree
+{
+ /* opens a shared library */
+ lib_t openLibrary(const std::string& file)
+ {
+#if defined(__MACOSX__)
+ std::string fullName = "lib"+file+".dylib";
+#else
+ std::string fullName = "lib"+file+".so";
+#endif
+ void* lib = dlopen(fullName.c_str(), RTLD_NOW);
+ if (lib) return lib_t(lib);
+ FileName executable = getExecutableFileName();
+ lib = dlopen((executable.path() + fullName).c_str(),RTLD_NOW);
+ if (lib == nullptr) {
+ const char* error = dlerror();
+ if (error) {
+ THROW_RUNTIME_ERROR(error);
+ } else {
+ THROW_RUNTIME_ERROR("could not load library "+executable.str());
+ }
+ }
+ return lib_t(lib);
+ }
+
+ /* returns address of a symbol from the library */
+ void* getSymbol(lib_t lib, const std::string& sym) {
+ return dlsym(lib,sym.c_str());
+ }
+
+ /* closes the shared library */
+ void closeLibrary(lib_t lib) {
+ dlclose(lib);
+ }
+}
+#endif
diff --git a/thirdparty/embree/common/sys/library.h b/thirdparty/embree/common/sys/library.h
new file mode 100644
index 0000000000..67e14d2420
--- /dev/null
+++ b/thirdparty/embree/common/sys/library.h
@@ -0,0 +1,21 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+
+namespace embree
+{
+ /*! type for shared library */
+ typedef struct opaque_lib_t* lib_t;
+
+ /*! loads a shared library */
+ lib_t openLibrary(const std::string& file);
+
+ /*! returns address of a symbol from the library */
+ void* getSymbol(lib_t lib, const std::string& sym);
+
+ /*! unloads a shared library */
+ void closeLibrary(lib_t lib);
+}
diff --git a/thirdparty/embree/common/sys/mutex.cpp b/thirdparty/embree/common/sys/mutex.cpp
new file mode 100644
index 0000000000..789feaf2d8
--- /dev/null
+++ b/thirdparty/embree/common/sys/mutex.cpp
@@ -0,0 +1,57 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "mutex.h"
+#include "regression.h"
+
+#if defined(__WIN32__) && !defined(PTHREADS_WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace embree
+{
+ MutexSys::MutexSys() { mutex = new CRITICAL_SECTION; InitializeCriticalSection((CRITICAL_SECTION*)mutex); }
+ MutexSys::~MutexSys() { DeleteCriticalSection((CRITICAL_SECTION*)mutex); delete (CRITICAL_SECTION*)mutex; }
+ void MutexSys::lock() { EnterCriticalSection((CRITICAL_SECTION*)mutex); }
+ bool MutexSys::try_lock() { return TryEnterCriticalSection((CRITICAL_SECTION*)mutex) != 0; }
+ void MutexSys::unlock() { LeaveCriticalSection((CRITICAL_SECTION*)mutex); }
+}
+#endif
+
+#if defined(__UNIX__) || defined(PTHREADS_WIN32)
+#include <pthread.h>
+namespace embree
+{
+ /*! system mutex using pthreads */
+ MutexSys::MutexSys()
+ {
+ mutex = new pthread_mutex_t;
+ if (pthread_mutex_init((pthread_mutex_t*)mutex, nullptr) != 0)
+ THROW_RUNTIME_ERROR("pthread_mutex_init failed");
+ }
+
+ MutexSys::~MutexSys()
+ {
+ MAYBE_UNUSED bool ok = pthread_mutex_destroy((pthread_mutex_t*)mutex) == 0;
+ assert(ok);
+ delete (pthread_mutex_t*)mutex;
+ }
+
+ void MutexSys::lock()
+ {
+ if (pthread_mutex_lock((pthread_mutex_t*)mutex) != 0)
+ THROW_RUNTIME_ERROR("pthread_mutex_lock failed");
+ }
+
+ bool MutexSys::try_lock() {
+ return pthread_mutex_trylock((pthread_mutex_t*)mutex) == 0;
+ }
+
+ void MutexSys::unlock()
+ {
+ if (pthread_mutex_unlock((pthread_mutex_t*)mutex) != 0)
+ THROW_RUNTIME_ERROR("pthread_mutex_unlock failed");
+ }
+};
+#endif
diff --git a/thirdparty/embree/common/sys/mutex.h b/thirdparty/embree/common/sys/mutex.h
new file mode 100644
index 0000000000..4cb3626d92
--- /dev/null
+++ b/thirdparty/embree/common/sys/mutex.h
@@ -0,0 +1,98 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+#include "intrinsics.h"
+#include "atomic.h"
+
+namespace embree
+{
+ /*! system mutex */
+ class MutexSys {
+ friend struct ConditionImplementation;
+ public:
+ MutexSys();
+ ~MutexSys();
+
+ private:
+ MutexSys (const MutexSys& other) DELETED; // do not implement
+ MutexSys& operator= (const MutexSys& other) DELETED; // do not implement
+
+ public:
+ void lock();
+ bool try_lock();
+ void unlock();
+
+ protected:
+ void* mutex;
+ };
+
+ /*! spinning mutex */
+ class SpinLock
+ {
+ public:
+
+ SpinLock ()
+ : flag(false) {}
+
+ __forceinline bool isLocked() {
+ return flag.load();
+ }
+
+ __forceinline void lock()
+ {
+ while (true)
+ {
+ while (flag.load())
+ {
+ _mm_pause();
+ _mm_pause();
+ }
+
+ bool expected = false;
+ if (flag.compare_exchange_strong(expected,true,std::memory_order_acquire))
+ break;
+ }
+ }
+
+ __forceinline bool try_lock()
+ {
+ bool expected = false;
+ if (flag.load() != expected) {
+ return false;
+ }
+ return flag.compare_exchange_strong(expected,true,std::memory_order_acquire);
+ }
+
+ __forceinline void unlock() {
+ flag.store(false,std::memory_order_release);
+ }
+
+ __forceinline void wait_until_unlocked()
+ {
+ while(flag.load())
+ {
+ _mm_pause();
+ _mm_pause();
+ }
+ }
+
+ public:
+ atomic<bool> flag;
+ };
+
+ /*! safe mutex lock and unlock helper */
+ template<typename Mutex> class Lock {
+ public:
+ Lock (Mutex& mutex) : mutex(mutex), locked(true) { mutex.lock(); }
+ Lock (Mutex& mutex, bool locked) : mutex(mutex), locked(locked) {}
+ ~Lock() { if (locked) mutex.unlock(); }
+ __forceinline void lock() { assert(!locked); locked = true; mutex.lock(); }
+ __forceinline bool isLocked() const { return locked; }
+ protected:
+ Mutex& mutex;
+ bool locked;
+ };
+}
diff --git a/thirdparty/embree/common/sys/platform.h b/thirdparty/embree/common/sys/platform.h
new file mode 100644
index 0000000000..697e07bb86
--- /dev/null
+++ b/thirdparty/embree/common/sys/platform.h
@@ -0,0 +1,392 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <cstddef>
+#include <cassert>
+#include <cstdlib>
+#include <cstdio>
+#include <memory>
+#include <stdexcept>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <cstring>
+#include <stdint.h>
+#include <functional>
+
+////////////////////////////////////////////////////////////////////////////////
+/// detect platform
+////////////////////////////////////////////////////////////////////////////////
+
+/* detect 32 or 64 Intel platform */
+#if defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
+#define __X86_64__
+#define __X86_ASM__
+#elif defined(__i386__) || defined(_M_IX86)
+#define __X86_ASM__
+#endif
+
+/* detect 64 bit platform */
+#if defined(__X86_64__) || defined(__aarch64__)
+#define __64BIT__
+#endif
+
+/* detect Linux platform */
+#if defined(linux) || defined(__linux__) || defined(__LINUX__)
+# if !defined(__LINUX__)
+# define __LINUX__
+# endif
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+/* detect FreeBSD platform */
+#if defined(__FreeBSD__) || defined(__FREEBSD__)
+# if !defined(__FREEBSD__)
+# define __FREEBSD__
+# endif
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+/* detect Windows 95/98/NT/2000/XP/Vista/7/8/10 platform */
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) && !defined(__CYGWIN__)
+# if !defined(__WIN32__)
+# define __WIN32__
+# endif
+#endif
+
+/* detect Cygwin platform */
+#if defined(__CYGWIN__)
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+/* detect MAC OS X platform */
+#if defined(__APPLE__) || defined(MACOSX) || defined(__MACOSX__)
+# if !defined(__MACOSX__)
+# define __MACOSX__
+# endif
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+/* try to detect other Unix systems */
+#if defined(__unix__) || defined (unix) || defined(__unix) || defined(_unix)
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Macros
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+#define dll_export __declspec(dllexport)
+#define dll_import __declspec(dllimport)
+#else
+#define dll_export __attribute__ ((visibility ("default")))
+#define dll_import
+#endif
+
+// -- GODOT start --
+#if defined(__WIN32__) && !defined(__MINGW32__)
+// -- GODOT end --
+#if !defined(__noinline)
+#define __noinline __declspec(noinline)
+#endif
+//#define __forceinline __forceinline
+//#define __restrict __restrict
+#if defined(__INTEL_COMPILER)
+#define __restrict__ __restrict
+#else
+#define __restrict__ //__restrict // causes issues with MSVC
+#endif
+#if !defined(__thread)
+#define __thread __declspec(thread)
+#endif
+#if !defined(__aligned)
+#define __aligned(...) __declspec(align(__VA_ARGS__))
+#endif
+//#define __FUNCTION__ __FUNCTION__
+#define debugbreak() __debugbreak()
+
+#else
+#if !defined(__noinline)
+#define __noinline __attribute__((noinline))
+#endif
+#if !defined(__forceinline)
+#define __forceinline inline __attribute__((always_inline))
+#endif
+//#define __restrict __restrict
+//#define __thread __thread
+#if !defined(__aligned)
+#define __aligned(...) __attribute__((aligned(__VA_ARGS__)))
+#endif
+#if !defined(__FUNCTION__)
+#define __FUNCTION__ __PRETTY_FUNCTION__
+#endif
+#define debugbreak() asm ("int $3")
+#endif
+
+#if defined(__clang__) || defined(__GNUC__)
+ #define MAYBE_UNUSED __attribute__((unused))
+#else
+ #define MAYBE_UNUSED
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900) // before VS2015 deleted functions are not supported properly
+ #define DELETED
+#else
+ #define DELETED = delete
+#endif
+
+// -- GODOT start --
+#if !defined(likely)
+// -- GODOT end --
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+#define likely(expr) (expr)
+#define unlikely(expr) (expr)
+#else
+#define likely(expr) __builtin_expect((bool)(expr),true )
+#define unlikely(expr) __builtin_expect((bool)(expr),false)
+#endif
+// -- GODOT start --
+#endif
+// -- GODOT end --
+
+////////////////////////////////////////////////////////////////////////////////
+/// Error handling and debugging
+////////////////////////////////////////////////////////////////////////////////
+
+/* debug printing macros */
+#define STRING(x) #x
+#define TOSTRING(x) STRING(x)
+#define PING embree_cout << __FILE__ << " (" << __LINE__ << "): " << __FUNCTION__ << embree_endl
+#define PRINT(x) embree_cout << STRING(x) << " = " << (x) << embree_endl
+#define PRINT2(x,y) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << embree_endl
+#define PRINT3(x,y,z) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << embree_endl
+#define PRINT4(x,y,z,w) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << embree_endl
+
+#if defined(DEBUG) // only report file and line in debug mode
+ // -- GODOT start --
+ // #define THROW_RUNTIME_ERROR(str)
+ // throw std::runtime_error(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
+ #define THROW_RUNTIME_ERROR(str) \
+ printf(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)), abort();
+ // -- GODOT end --
+#else
+ // -- GODOT start --
+ // #define THROW_RUNTIME_ERROR(str)
+ // throw std::runtime_error(str);
+ #define THROW_RUNTIME_ERROR(str) \
+ abort();
+ // -- GODOT end --
+#endif
+
+#define FATAL(x) THROW_RUNTIME_ERROR(x)
+#define WARNING(x) { std::cerr << "Warning: " << x << embree_endl << std::flush; }
+
+#define NOT_IMPLEMENTED FATAL(std::string(__FUNCTION__) + " not implemented")
+
+////////////////////////////////////////////////////////////////////////////////
+/// Basic types
+////////////////////////////////////////////////////////////////////////////////
+
+/* default floating-point type */
+namespace embree {
+ typedef float real;
+}
+
+/* windows does not have ssize_t */
+#if defined(__WIN32__)
+#if defined(__64BIT__)
+typedef int64_t ssize_t;
+#else
+typedef int32_t ssize_t;
+#endif
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Basic utility functions
+////////////////////////////////////////////////////////////////////////////////
+
+__forceinline std::string toString(long long value) {
+ return std::to_string(value);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Disable some compiler warnings
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__INTEL_COMPILER)
+//#pragma warning(disable:265 ) // floating-point operation result is out of range
+//#pragma warning(disable:383 ) // value copied to temporary, reference to temporary used
+//#pragma warning(disable:869 ) // parameter was never referenced
+//#pragma warning(disable:981 ) // operands are evaluated in unspecified order
+//#pragma warning(disable:1418) // external function definition with no prior declaration
+//#pragma warning(disable:1419) // external declaration in primary source file
+//#pragma warning(disable:1572) // floating-point equality and inequality comparisons are unreliable
+//#pragma warning(disable:94 ) // the size of an array must be greater than zero
+//#pragma warning(disable:1599) // declaration hides parameter
+//#pragma warning(disable:424 ) // extra ";" ignored
+#pragma warning(disable:2196) // routine is both "inline" and "noinline"
+//#pragma warning(disable:177 ) // label was declared but never referenced
+//#pragma warning(disable:114 ) // function was referenced but not defined
+//#pragma warning(disable:819 ) // template nesting depth does not match the previous declaration of function
+#pragma warning(disable:15335) // was not vectorized: vectorization possible but seems inefficient
+#endif
+
+#if defined(_MSC_VER)
+//#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union
+#pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning)
+//#pragma warning(disable:4267) // '=' : conversion from 'size_t' to 'unsigned long', possible loss of data
+#pragma warning(disable:4244) // 'argument' : conversion from 'ssize_t' to 'unsigned int', possible loss of data
+//#pragma warning(disable:4355) // 'this' : used in base member initializer list
+//#pragma warning(disable:391 ) // '<=' : signed / unsigned mismatch
+//#pragma warning(disable:4018) // '<' : signed / unsigned mismatch
+//#pragma warning(disable:4305) // 'initializing' : truncation from 'double' to 'float'
+//#pragma warning(disable:4068) // unknown pragma
+//#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
+//#pragma warning(disable:4838) // conversion from 'unsigned int' to 'const int' requires a narrowing conversion)
+//#pragma warning(disable:4227) // anachronism used : qualifiers on reference are ignored
+#pragma warning(disable:4503) // decorated name length exceeded, name was truncated
+#pragma warning(disable:4180) // qualifier applied to function type has no meaning; ignored
+#pragma warning(disable:4258) // definition from the for loop is ignored; the definition from the enclosing scope is used
+
+# if _MSC_VER < 1910 // prior to Visual studio 2017 (V141)
+# pragma warning(disable:4101) // warning C4101: 'x': unreferenced local variable // a compiler bug issues wrong warnings
+# pragma warning(disable:4789) // buffer '' of size 8 bytes will be overrun; 32 bytes will be written starting at offset 0
+# endif
+
+#endif
+
+#if defined(__clang__) && !defined(__INTEL_COMPILER)
+//#pragma clang diagnostic ignored "-Wunknown-pragmas"
+//#pragma clang diagnostic ignored "-Wunused-variable"
+//#pragma clang diagnostic ignored "-Wreorder"
+//#pragma clang diagnostic ignored "-Wmicrosoft"
+//#pragma clang diagnostic ignored "-Wunused-private-field"
+//#pragma clang diagnostic ignored "-Wunused-local-typedef"
+//#pragma clang diagnostic ignored "-Wunused-function"
+//#pragma clang diagnostic ignored "-Wnarrowing"
+//#pragma clang diagnostic ignored "-Wc++11-narrowing"
+//#pragma clang diagnostic ignored "-Wdeprecated-register"
+//#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Wpragmas"
+//#pragma GCC diagnostic ignored "-Wnarrowing"
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+//#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+//#pragma GCC diagnostic ignored "-Warray-bounds"
+#pragma GCC diagnostic ignored "-Wattributes"
+#pragma GCC diagnostic ignored "-Wmisleading-indentation"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wparentheses"
+#endif
+
+#if defined(__clang__) && defined(__WIN32__)
+#pragma clang diagnostic ignored "-Wunused-parameter"
+#pragma clang diagnostic ignored "-Wmicrosoft-cast"
+#pragma clang diagnostic ignored "-Wmicrosoft-enum-value"
+#pragma clang diagnostic ignored "-Wmicrosoft-include"
+#pragma clang diagnostic ignored "-Wunused-function"
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#endif
+
+/* disabling deprecated warning, please use only where use of deprecated Embree API functions is desired */
+#if defined(__WIN32__) && defined(__INTEL_COMPILER)
+#define DISABLE_DEPRECATED_WARNING __pragma(warning (disable: 1478)) // warning: function was declared deprecated
+#define ENABLE_DEPRECATED_WARNING __pragma(warning (enable: 1478)) // warning: function was declared deprecated
+#elif defined(__INTEL_COMPILER)
+#define DISABLE_DEPRECATED_WARNING _Pragma("warning (disable: 1478)") // warning: function was declared deprecated
+#define ENABLE_DEPRECATED_WARNING _Pragma("warning (enable : 1478)") // warning: function was declared deprecated
+#elif defined(__clang__)
+#define DISABLE_DEPRECATED_WARNING _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") // warning: xxx is deprecated
+#define ENABLE_DEPRECATED_WARNING _Pragma("clang diagnostic warning \"-Wdeprecated-declarations\"") // warning: xxx is deprecated
+#elif defined(__GNUC__)
+#define DISABLE_DEPRECATED_WARNING _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") // warning: xxx is deprecated
+#define ENABLE_DEPRECATED_WARNING _Pragma("GCC diagnostic warning \"-Wdeprecated-declarations\"") // warning: xxx is deprecated
+#elif defined(_MSC_VER)
+#define DISABLE_DEPRECATED_WARNING __pragma(warning (disable: 4996)) // warning: function was declared deprecated
+#define ENABLE_DEPRECATED_WARNING __pragma(warning (enable : 4996)) // warning: function was declared deprecated
+#endif
+
+/* embree output stream */
+#define embree_ostream std::ostream&
+#define embree_cout std::cout
+#define embree_cout_uniform std::cout
+#define embree_endl std::endl
+
+////////////////////////////////////////////////////////////////////////////////
+/// Some macros for static profiling
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined (__GNUC__)
+#define IACA_SSC_MARK( MARK_ID ) \
+__asm__ __volatile__ ( \
+ "\n\t movl $"#MARK_ID", %%ebx" \
+ "\n\t .byte 0x64, 0x67, 0x90" \
+ : : : "memory" );
+
+#define IACA_UD_BYTES __asm__ __volatile__ ("\n\t .byte 0x0F, 0x0B");
+
+#else
+#define IACA_UD_BYTES {__asm _emit 0x0F \
+ __asm _emit 0x0B}
+
+#define IACA_SSC_MARK(x) {__asm mov ebx, x\
+ __asm _emit 0x64 \
+ __asm _emit 0x67 \
+ __asm _emit 0x90 }
+
+#define IACA_VC64_START __writegsbyte(111, 111);
+#define IACA_VC64_END __writegsbyte(222, 222);
+
+#endif
+
+#define IACA_START {IACA_UD_BYTES \
+ IACA_SSC_MARK(111)}
+#define IACA_END {IACA_SSC_MARK(222) \
+ IACA_UD_BYTES}
+
+namespace embree
+{
+ template<typename Closure>
+ struct OnScopeExitHelper
+ {
+ OnScopeExitHelper (const Closure f) : active(true), f(f) {}
+ ~OnScopeExitHelper() { if (active) f(); }
+ void deactivate() { active = false; }
+ bool active;
+ const Closure f;
+ };
+
+ template <typename Closure>
+ OnScopeExitHelper<Closure> OnScopeExit(const Closure f) {
+ return OnScopeExitHelper<Closure>(f);
+ }
+
+#define STRING_JOIN2(arg1, arg2) DO_STRING_JOIN2(arg1, arg2)
+#define DO_STRING_JOIN2(arg1, arg2) arg1 ## arg2
+#define ON_SCOPE_EXIT(code) \
+ auto STRING_JOIN2(on_scope_exit_, __LINE__) = OnScopeExit([&](){code;})
+
+ template<typename Ty>
+ std::unique_ptr<Ty> make_unique(Ty* ptr) {
+ return std::unique_ptr<Ty>(ptr);
+ }
+
+}
diff --git a/thirdparty/embree/common/sys/ref.h b/thirdparty/embree/common/sys/ref.h
new file mode 100644
index 0000000000..c2b56c1908
--- /dev/null
+++ b/thirdparty/embree/common/sys/ref.h
@@ -0,0 +1,122 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "atomic.h"
+
+namespace embree
+{
+ struct NullTy {
+ };
+
+ extern MAYBE_UNUSED NullTy null;
+
+ class RefCount
+ {
+ public:
+ RefCount(int val = 0) : refCounter(val) {}
+ virtual ~RefCount() {};
+
+ virtual RefCount* refInc() { refCounter.fetch_add(1); return this; }
+ virtual void refDec() { if (refCounter.fetch_add(-1) == 1) delete this; }
+ private:
+ std::atomic<size_t> refCounter;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reference to single object
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename Type>
+ class Ref
+ {
+ public:
+ Type* ptr;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline Ref() : ptr(nullptr) {}
+ __forceinline Ref(NullTy) : ptr(nullptr) {}
+ __forceinline Ref(const Ref& input) : ptr(input.ptr) { if (ptr) ptr->refInc(); }
+ __forceinline Ref(Ref&& input) : ptr(input.ptr) { input.ptr = nullptr; }
+
+ __forceinline Ref(Type* const input) : ptr(input)
+ {
+ if (ptr)
+ ptr->refInc();
+ }
+
+ __forceinline ~Ref()
+ {
+ if (ptr)
+ ptr->refDec();
+ }
+
+ __forceinline Ref& operator =(const Ref& input)
+ {
+ if (input.ptr)
+ input.ptr->refInc();
+ if (ptr)
+ ptr->refDec();
+ ptr = input.ptr;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(Ref&& input)
+ {
+ if (ptr)
+ ptr->refDec();
+ ptr = input.ptr;
+ input.ptr = nullptr;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(Type* const input)
+ {
+ if (input)
+ input->refInc();
+ if (ptr)
+ ptr->refDec();
+ ptr = input;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(NullTy)
+ {
+ if (ptr)
+ ptr->refDec();
+ ptr = nullptr;
+ return *this;
+ }
+
+ __forceinline operator bool() const { return ptr != nullptr; }
+
+ __forceinline const Type& operator *() const { return *ptr; }
+ __forceinline Type& operator *() { return *ptr; }
+ __forceinline const Type* operator ->() const { return ptr; }
+ __forceinline Type* operator ->() { return ptr; }
+
+ template<typename TypeOut>
+ __forceinline Ref<TypeOut> cast() { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
+ template<typename TypeOut>
+ __forceinline const Ref<TypeOut> cast() const { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
+
+ template<typename TypeOut>
+ __forceinline Ref<TypeOut> dynamicCast() { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); }
+ template<typename TypeOut>
+ __forceinline const Ref<TypeOut> dynamicCast() const { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); }
+ };
+
+ template<typename Type> __forceinline bool operator < (const Ref<Type>& a, const Ref<Type>& b) { return a.ptr < b.ptr; }
+
+ template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, NullTy ) { return a.ptr == nullptr; }
+ template<typename Type> __forceinline bool operator ==(NullTy , const Ref<Type>& b) { return nullptr == b.ptr; }
+ template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr == b.ptr; }
+
+ template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, NullTy ) { return a.ptr != nullptr; }
+ template<typename Type> __forceinline bool operator !=(NullTy , const Ref<Type>& b) { return nullptr != b.ptr; }
+ template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr != b.ptr; }
+}
diff --git a/thirdparty/embree/common/sys/regression.cpp b/thirdparty/embree/common/sys/regression.cpp
new file mode 100644
index 0000000000..45315b1105
--- /dev/null
+++ b/thirdparty/embree/common/sys/regression.cpp
@@ -0,0 +1,30 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "regression.h"
+
+namespace embree
+{
+ /* registerRegressionTest is invoked from static initializers, thus
+ * we cannot have the regression_tests variable as global static
+ * variable due to issues with static variable initialization
+ * order. */
+ std::vector<RegressionTest*>& get_regression_tests()
+ {
+ static std::vector<RegressionTest*> regression_tests;
+ return regression_tests;
+ }
+
+ void registerRegressionTest(RegressionTest* test)
+ {
+ get_regression_tests().push_back(test);
+ }
+
+ RegressionTest* getRegressionTest(size_t index)
+ {
+ if (index >= get_regression_tests().size())
+ return nullptr;
+
+ return get_regression_tests()[index];
+ }
+}
diff --git a/thirdparty/embree/common/sys/regression.h b/thirdparty/embree/common/sys/regression.h
new file mode 100644
index 0000000000..bb0bb94006
--- /dev/null
+++ b/thirdparty/embree/common/sys/regression.h
@@ -0,0 +1,25 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+
+#include <vector>
+
+namespace embree
+{
+ /*! virtual interface for all regression tests */
+ struct RegressionTest
+ {
+ RegressionTest (std::string name) : name(name) {}
+ virtual bool run() = 0;
+ std::string name;
+ };
+
+ /*! registers a regression test */
+ void registerRegressionTest(RegressionTest* test);
+
+ /*! run all regression tests */
+ RegressionTest* getRegressionTest(size_t index);
+}
diff --git a/thirdparty/embree/common/sys/string.cpp b/thirdparty/embree/common/sys/string.cpp
new file mode 100644
index 0000000000..f42fdc8536
--- /dev/null
+++ b/thirdparty/embree/common/sys/string.cpp
@@ -0,0 +1,42 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "string.h"
+
+#include <algorithm>
+#include <ctype.h>
+
+namespace embree
+{
+ char to_lower(char c) { return char(tolower(int(c))); }
+ char to_upper(char c) { return char(toupper(int(c))); }
+ std::string toLowerCase(const std::string& s) { std::string dst(s); std::transform(dst.begin(), dst.end(), dst.begin(), to_lower); return dst; }
+ std::string toUpperCase(const std::string& s) { std::string dst(s); std::transform(dst.begin(), dst.end(), dst.begin(), to_upper); return dst; }
+
+ Vec2f string_to_Vec2f ( std::string str )
+ {
+ size_t next = 0;
+ const float x = std::stof(str,&next); str = str.substr(next+1);
+ const float y = std::stof(str,&next);
+ return Vec2f(x,y);
+ }
+
+ Vec3f string_to_Vec3f ( std::string str )
+ {
+ size_t next = 0;
+ const float x = std::stof(str,&next); str = str.substr(next+1);
+ const float y = std::stof(str,&next); str = str.substr(next+1);
+ const float z = std::stof(str,&next);
+ return Vec3f(x,y,z);
+ }
+
+ Vec4f string_to_Vec4f ( std::string str )
+ {
+ size_t next = 0;
+ const float x = std::stof(str,&next); str = str.substr(next+1);
+ const float y = std::stof(str,&next); str = str.substr(next+1);
+ const float z = std::stof(str,&next); str = str.substr(next+1);
+ const float w = std::stof(str,&next);
+ return Vec4f(x,y,z,w);
+ }
+}
diff --git a/thirdparty/embree/common/sys/string.h b/thirdparty/embree/common/sys/string.h
new file mode 100644
index 0000000000..820076b21c
--- /dev/null
+++ b/thirdparty/embree/common/sys/string.h
@@ -0,0 +1,37 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+#include "../math/vec2.h"
+#include "../math/vec3.h"
+#include "../math/vec4.h"
+
+namespace embree
+{
+ class IOStreamStateRestorer
+ {
+ public:
+ IOStreamStateRestorer(std::ostream& iostream)
+ : iostream(iostream), flags(iostream.flags()), precision(iostream.precision()) {
+ }
+
+ ~IOStreamStateRestorer() {
+ iostream.flags(flags);
+ iostream.precision(precision);
+ }
+
+ private:
+ std::ostream& iostream;
+ std::ios::fmtflags flags;
+ std::streamsize precision;
+ };
+
+ std::string toLowerCase(const std::string& s);
+ std::string toUpperCase(const std::string& s);
+
+ Vec2f string_to_Vec2f ( std::string str );
+ Vec3f string_to_Vec3f ( std::string str );
+ Vec4f string_to_Vec4f ( std::string str );
+}
diff --git a/thirdparty/embree/common/sys/sysinfo.cpp b/thirdparty/embree/common/sys/sysinfo.cpp
new file mode 100644
index 0000000000..f1a59e511e
--- /dev/null
+++ b/thirdparty/embree/common/sys/sysinfo.cpp
@@ -0,0 +1,656 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sysinfo.h"
+#include "intrinsics.h"
+#include "string.h"
+#include "ref.h"
+#if defined(__FREEBSD__)
+#include <sys/cpuset.h>
+#include <pthread_np.h>
+typedef cpuset_t cpu_set_t;
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// All Platforms
+////////////////////////////////////////////////////////////////////////////////
+
+namespace embree
+{
+ NullTy null;
+
+ std::string getPlatformName()
+ {
+#if defined(__LINUX__) && !defined(__64BIT__)
+ return "Linux (32bit)";
+#elif defined(__LINUX__) && defined(__64BIT__)
+ return "Linux (64bit)";
+#elif defined(__FREEBSD__) && !defined(__64BIT__)
+ return "FreeBSD (32bit)";
+#elif defined(__FREEBSD__) && defined(__64BIT__)
+ return "FreeBSD (64bit)";
+#elif defined(__CYGWIN__) && !defined(__64BIT__)
+ return "Cygwin (32bit)";
+#elif defined(__CYGWIN__) && defined(__64BIT__)
+ return "Cygwin (64bit)";
+#elif defined(__WIN32__) && !defined(__64BIT__)
+ return "Windows (32bit)";
+#elif defined(__WIN32__) && defined(__64BIT__)
+ return "Windows (64bit)";
+#elif defined(__MACOSX__) && !defined(__64BIT__)
+ return "Mac OS X (32bit)";
+#elif defined(__MACOSX__) && defined(__64BIT__)
+ return "Mac OS X (64bit)";
+#elif defined(__UNIX__) && !defined(__64BIT__)
+ return "Unix (32bit)";
+#elif defined(__UNIX__) && defined(__64BIT__)
+ return "Unix (64bit)";
+#else
+ return "Unknown";
+#endif
+ }
+
+ std::string getCompilerName()
+ {
+#if defined(__INTEL_COMPILER)
+ int icc_mayor = __INTEL_COMPILER / 100 % 100;
+ int icc_minor = __INTEL_COMPILER % 100;
+ std::string version = "Intel Compiler ";
+ version += toString(icc_mayor);
+ version += "." + toString(icc_minor);
+#if defined(__INTEL_COMPILER_UPDATE)
+ version += "." + toString(__INTEL_COMPILER_UPDATE);
+#endif
+ return version;
+#elif defined(__clang__)
+ return "CLANG " __clang_version__;
+#elif defined (__GNUC__)
+ return "GCC " __VERSION__;
+#elif defined(_MSC_VER)
+ std::string version = toString(_MSC_FULL_VER);
+ version.insert(4,".");
+ version.insert(9,".");
+ version.insert(2,".");
+ return "Visual C++ Compiler " + version;
+#else
+ return "Unknown Compiler";
+#endif
+ }
+
+ std::string getCPUVendor()
+ {
+#if defined(__X86_ASM__)
+ int cpuinfo[4];
+ __cpuid (cpuinfo, 0);
+ int name[4];
+ name[0] = cpuinfo[1];
+ name[1] = cpuinfo[3];
+ name[2] = cpuinfo[2];
+ name[3] = 0;
+ return (char*)name;
+#elif defined(__ARM_NEON)
+ return "ARM";
+#else
+ return "Unknown";
+#endif
+ }
+
+ CPU getCPUModel()
+ {
+#if defined(__X86_ASM__)
+ if (getCPUVendor() != "GenuineIntel")
+ return CPU::UNKNOWN;
+
+ int out[4];
+ __cpuid(out, 0);
+ if (out[0] < 1) return CPU::UNKNOWN;
+ __cpuid(out, 1);
+
+ /* please see CPUID documentation for these formulas */
+ uint32_t family_ID = (out[0] >> 8) & 0x0F;
+ uint32_t extended_family_ID = (out[0] >> 20) & 0xFF;
+
+ uint32_t model_ID = (out[0] >> 4) & 0x0F;
+ uint32_t extended_model_ID = (out[0] >> 16) & 0x0F;
+
+ uint32_t DisplayFamily = family_ID;
+ if (family_ID == 0x0F)
+ DisplayFamily += extended_family_ID;
+
+ uint32_t DisplayModel = model_ID;
+ if (family_ID == 0x06 || family_ID == 0x0F)
+ DisplayModel += extended_model_ID << 4;
+
+ uint32_t DisplayFamily_DisplayModel = (DisplayFamily << 8) + (DisplayModel << 0);
+
+ // Data from Intel® 64 and IA-32 Architectures, Volume 4, Chapter 2, Table 2-1 (CPUID Signature Values of DisplayFamily_DisplayModel)
+ if (DisplayFamily_DisplayModel == 0x067D) return CPU::CORE_ICE_LAKE;
+ if (DisplayFamily_DisplayModel == 0x067E) return CPU::CORE_ICE_LAKE;
+ if (DisplayFamily_DisplayModel == 0x068C) return CPU::CORE_TIGER_LAKE;
+ if (DisplayFamily_DisplayModel == 0x06A5) return CPU::CORE_COMET_LAKE;
+ if (DisplayFamily_DisplayModel == 0x06A6) return CPU::CORE_COMET_LAKE;
+ if (DisplayFamily_DisplayModel == 0x0666) return CPU::CORE_CANNON_LAKE;
+ if (DisplayFamily_DisplayModel == 0x068E) return CPU::CORE_KABY_LAKE;
+ if (DisplayFamily_DisplayModel == 0x069E) return CPU::CORE_KABY_LAKE;
+ if (DisplayFamily_DisplayModel == 0x066A) return CPU::XEON_ICE_LAKE;
+ if (DisplayFamily_DisplayModel == 0x066C) return CPU::XEON_ICE_LAKE;
+ if (DisplayFamily_DisplayModel == 0x0655) return CPU::XEON_SKY_LAKE;
+ if (DisplayFamily_DisplayModel == 0x064E) return CPU::CORE_SKY_LAKE;
+ if (DisplayFamily_DisplayModel == 0x065E) return CPU::CORE_SKY_LAKE;
+ if (DisplayFamily_DisplayModel == 0x0656) return CPU::XEON_BROADWELL;
+ if (DisplayFamily_DisplayModel == 0x064F) return CPU::XEON_BROADWELL;
+ if (DisplayFamily_DisplayModel == 0x0647) return CPU::CORE_BROADWELL;
+ if (DisplayFamily_DisplayModel == 0x063D) return CPU::CORE_BROADWELL;
+ if (DisplayFamily_DisplayModel == 0x063F) return CPU::XEON_HASWELL;
+ if (DisplayFamily_DisplayModel == 0x063C) return CPU::CORE_HASWELL;
+ if (DisplayFamily_DisplayModel == 0x0645) return CPU::CORE_HASWELL;
+ if (DisplayFamily_DisplayModel == 0x0646) return CPU::CORE_HASWELL;
+ if (DisplayFamily_DisplayModel == 0x063E) return CPU::XEON_IVY_BRIDGE;
+ if (DisplayFamily_DisplayModel == 0x063A) return CPU::CORE_IVY_BRIDGE;
+ if (DisplayFamily_DisplayModel == 0x062D) return CPU::SANDY_BRIDGE;
+ if (DisplayFamily_DisplayModel == 0x062F) return CPU::SANDY_BRIDGE;
+ if (DisplayFamily_DisplayModel == 0x062A) return CPU::SANDY_BRIDGE;
+ if (DisplayFamily_DisplayModel == 0x062E) return CPU::NEHALEM;
+ if (DisplayFamily_DisplayModel == 0x0625) return CPU::NEHALEM;
+ if (DisplayFamily_DisplayModel == 0x062C) return CPU::NEHALEM;
+ if (DisplayFamily_DisplayModel == 0x061E) return CPU::NEHALEM;
+ if (DisplayFamily_DisplayModel == 0x061F) return CPU::NEHALEM;
+ if (DisplayFamily_DisplayModel == 0x061A) return CPU::NEHALEM;
+ if (DisplayFamily_DisplayModel == 0x061D) return CPU::NEHALEM;
+ if (DisplayFamily_DisplayModel == 0x0617) return CPU::CORE2;
+ if (DisplayFamily_DisplayModel == 0x060F) return CPU::CORE2;
+ if (DisplayFamily_DisplayModel == 0x060E) return CPU::CORE1;
+
+ if (DisplayFamily_DisplayModel == 0x0685) return CPU::XEON_PHI_KNIGHTS_MILL;
+ if (DisplayFamily_DisplayModel == 0x0657) return CPU::XEON_PHI_KNIGHTS_LANDING;
+
+#elif defined(__ARM_NEON)
+ return CPU::ARM;
+#endif
+
+ return CPU::UNKNOWN;
+ }
+
+ std::string stringOfCPUModel(CPU model)
+ {
+ switch (model) {
+ case CPU::XEON_ICE_LAKE : return "Xeon Ice Lake";
+ case CPU::CORE_ICE_LAKE : return "Core Ice Lake";
+ case CPU::CORE_TIGER_LAKE : return "Core Tiger Lake";
+ case CPU::CORE_COMET_LAKE : return "Core Comet Lake";
+ case CPU::CORE_CANNON_LAKE : return "Core Cannon Lake";
+ case CPU::CORE_KABY_LAKE : return "Core Kaby Lake";
+ case CPU::XEON_SKY_LAKE : return "Xeon Sky Lake";
+ case CPU::CORE_SKY_LAKE : return "Core Sky Lake";
+ case CPU::XEON_PHI_KNIGHTS_MILL : return "Xeon Phi Knights Mill";
+ case CPU::XEON_PHI_KNIGHTS_LANDING: return "Xeon Phi Knights Landing";
+ case CPU::XEON_BROADWELL : return "Xeon Broadwell";
+ case CPU::CORE_BROADWELL : return "Core Broadwell";
+ case CPU::XEON_HASWELL : return "Xeon Haswell";
+ case CPU::CORE_HASWELL : return "Core Haswell";
+ case CPU::XEON_IVY_BRIDGE : return "Xeon Ivy Bridge";
+ case CPU::CORE_IVY_BRIDGE : return "Core Ivy Bridge";
+ case CPU::SANDY_BRIDGE : return "Sandy Bridge";
+ case CPU::NEHALEM : return "Nehalem";
+ case CPU::CORE2 : return "Core2";
+ case CPU::CORE1 : return "Core";
+ case CPU::ARM : return "ARM";
+ case CPU::UNKNOWN : return "Unknown CPU";
+ }
+ return "Unknown CPU (error)";
+ }
+
+#if defined(__X86_ASM__)
+ /* constants to access destination registers of CPUID instruction */
+ static const int EAX = 0;
+ static const int EBX = 1;
+ static const int ECX = 2;
+ static const int EDX = 3;
+
+ /* cpuid[eax=1].ecx */
+ static const int CPU_FEATURE_BIT_SSE3 = 1 << 0;
+ static const int CPU_FEATURE_BIT_SSSE3 = 1 << 9;
+ static const int CPU_FEATURE_BIT_FMA3 = 1 << 12;
+ static const int CPU_FEATURE_BIT_SSE4_1 = 1 << 19;
+ static const int CPU_FEATURE_BIT_SSE4_2 = 1 << 20;
+ //static const int CPU_FEATURE_BIT_MOVBE = 1 << 22;
+ static const int CPU_FEATURE_BIT_POPCNT = 1 << 23;
+ //static const int CPU_FEATURE_BIT_XSAVE = 1 << 26;
+ static const int CPU_FEATURE_BIT_OXSAVE = 1 << 27;
+ static const int CPU_FEATURE_BIT_AVX = 1 << 28;
+ static const int CPU_FEATURE_BIT_F16C = 1 << 29;
+ static const int CPU_FEATURE_BIT_RDRAND = 1 << 30;
+
+ /* cpuid[eax=1].edx */
+ static const int CPU_FEATURE_BIT_SSE = 1 << 25;
+ static const int CPU_FEATURE_BIT_SSE2 = 1 << 26;
+
+ /* cpuid[eax=0x80000001].ecx */
+ static const int CPU_FEATURE_BIT_LZCNT = 1 << 5;
+
+ /* cpuid[eax=7,ecx=0].ebx */
+ static const int CPU_FEATURE_BIT_BMI1 = 1 << 3;
+ static const int CPU_FEATURE_BIT_AVX2 = 1 << 5;
+ static const int CPU_FEATURE_BIT_BMI2 = 1 << 8;
+ static const int CPU_FEATURE_BIT_AVX512F = 1 << 16; // AVX512F (foundation)
+ static const int CPU_FEATURE_BIT_AVX512DQ = 1 << 17; // AVX512DQ (doubleword and quadword instructions)
+ static const int CPU_FEATURE_BIT_AVX512PF = 1 << 26; // AVX512PF (prefetch gather/scatter instructions)
+ static const int CPU_FEATURE_BIT_AVX512ER = 1 << 27; // AVX512ER (exponential and reciprocal instructions)
+ static const int CPU_FEATURE_BIT_AVX512CD = 1 << 28; // AVX512CD (conflict detection instructions)
+ static const int CPU_FEATURE_BIT_AVX512BW = 1 << 30; // AVX512BW (byte and word instructions)
+ static const int CPU_FEATURE_BIT_AVX512VL = 1 << 31; // AVX512VL (vector length extensions)
+ static const int CPU_FEATURE_BIT_AVX512IFMA = 1 << 21; // AVX512IFMA (integer fused multiple-add instructions)
+
+ /* cpuid[eax=7,ecx=0].ecx */
+ static const int CPU_FEATURE_BIT_AVX512VBMI = 1 << 1; // AVX512VBMI (vector bit manipulation instructions)
+#endif
+
+#if defined(__X86_ASM__)
+ __noinline int64_t get_xcr0()
+ {
+// -- GODOT start --
+#if defined (__WIN32__) && !defined (__MINGW32__)
+// -- GODOT end --
+ int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32
+ xcr0 = _xgetbv(0);
+ return xcr0;
+#else
+ int xcr0 = 0;
+ __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
+ return xcr0;
+#endif
+ }
+#endif
+
+ int getCPUFeatures()
+ {
+#if defined(__X86_ASM__)
+ /* cache CPU features access */
+ static int cpu_features = 0;
+ if (cpu_features)
+ return cpu_features;
+
+ /* get number of CPUID leaves */
+ int cpuid_leaf0[4];
+ __cpuid(cpuid_leaf0, 0x00000000);
+ unsigned nIds = cpuid_leaf0[EAX];
+
+ /* get number of extended CPUID leaves */
+ int cpuid_leafe[4];
+ __cpuid(cpuid_leafe, 0x80000000);
+ unsigned nExIds = cpuid_leafe[EAX];
+
+ /* get CPUID leaves for EAX = 1,7, and 0x80000001 */
+ int cpuid_leaf_1[4] = { 0,0,0,0 };
+ int cpuid_leaf_7[4] = { 0,0,0,0 };
+ int cpuid_leaf_e1[4] = { 0,0,0,0 };
+ if (nIds >= 1) __cpuid (cpuid_leaf_1,0x00000001);
+#if _WIN32
+#if _MSC_VER && (_MSC_FULL_VER < 160040219)
+#else
+ if (nIds >= 7) __cpuidex(cpuid_leaf_7,0x00000007,0);
+#endif
+#else
+ if (nIds >= 7) __cpuid_count(cpuid_leaf_7,0x00000007,0);
+#endif
+ if (nExIds >= 0x80000001) __cpuid(cpuid_leaf_e1,0x80000001);
+
+ /* detect if OS saves XMM, YMM, and ZMM states */
+ bool xmm_enabled = true;
+ bool ymm_enabled = false;
+ bool zmm_enabled = false;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_OXSAVE) {
+ int64_t xcr0 = get_xcr0();
+ xmm_enabled = ((xcr0 & 0x02) == 0x02); /* checks if xmm are enabled in XCR0 */
+ ymm_enabled = xmm_enabled && ((xcr0 & 0x04) == 0x04); /* checks if ymm state are enabled in XCR0 */
+ zmm_enabled = ymm_enabled && ((xcr0 & 0xE0) == 0xE0); /* checks if OPMASK state, upper 256-bit of ZMM0-ZMM15 and ZMM16-ZMM31 state are enabled in XCR0 */
+ }
+ if (xmm_enabled) cpu_features |= CPU_FEATURE_XMM_ENABLED;
+ if (ymm_enabled) cpu_features |= CPU_FEATURE_YMM_ENABLED;
+ if (zmm_enabled) cpu_features |= CPU_FEATURE_ZMM_ENABLED;
+
+ if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE ) cpu_features |= CPU_FEATURE_SSE;
+ if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE2 ) cpu_features |= CPU_FEATURE_SSE2;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE3 ) cpu_features |= CPU_FEATURE_SSE3;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSSE3 ) cpu_features |= CPU_FEATURE_SSSE3;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_1) cpu_features |= CPU_FEATURE_SSE41;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_2) cpu_features |= CPU_FEATURE_SSE42;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_POPCNT) cpu_features |= CPU_FEATURE_POPCNT;
+
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_AVX ) cpu_features |= CPU_FEATURE_AVX;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_F16C ) cpu_features |= CPU_FEATURE_F16C;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_RDRAND) cpu_features |= CPU_FEATURE_RDRAND;
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX2 ) cpu_features |= CPU_FEATURE_AVX2;
+ if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_FMA3 ) cpu_features |= CPU_FEATURE_FMA3;
+ if (cpuid_leaf_e1[ECX] & CPU_FEATURE_BIT_LZCNT) cpu_features |= CPU_FEATURE_LZCNT;
+ if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI1 ) cpu_features |= CPU_FEATURE_BMI1;
+ if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI2 ) cpu_features |= CPU_FEATURE_BMI2;
+
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512F ) cpu_features |= CPU_FEATURE_AVX512F;
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512DQ ) cpu_features |= CPU_FEATURE_AVX512DQ;
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512PF ) cpu_features |= CPU_FEATURE_AVX512PF;
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512ER ) cpu_features |= CPU_FEATURE_AVX512ER;
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512CD ) cpu_features |= CPU_FEATURE_AVX512CD;
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512BW ) cpu_features |= CPU_FEATURE_AVX512BW;
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512IFMA) cpu_features |= CPU_FEATURE_AVX512IFMA;
+ if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512VL ) cpu_features |= CPU_FEATURE_AVX512VL;
+ if (cpuid_leaf_7[ECX] & CPU_FEATURE_BIT_AVX512VBMI) cpu_features |= CPU_FEATURE_AVX512VBMI;
+
+ return cpu_features;
+#elif defined(__ARM_NEON)
+ /* emulated features with sse2neon */
+ return CPU_FEATURE_SSE|CPU_FEATURE_SSE2|CPU_FEATURE_XMM_ENABLED;
+#else
+ /* Unknown CPU. */
+ return 0;
+#endif
+ }
+
+ std::string stringOfCPUFeatures(int features)
+ {
+ std::string str;
+ if (features & CPU_FEATURE_XMM_ENABLED) str += "XMM ";
+ if (features & CPU_FEATURE_YMM_ENABLED) str += "YMM ";
+ if (features & CPU_FEATURE_ZMM_ENABLED) str += "ZMM ";
+ if (features & CPU_FEATURE_SSE ) str += "SSE ";
+ if (features & CPU_FEATURE_SSE2 ) str += "SSE2 ";
+ if (features & CPU_FEATURE_SSE3 ) str += "SSE3 ";
+ if (features & CPU_FEATURE_SSSE3 ) str += "SSSE3 ";
+ if (features & CPU_FEATURE_SSE41 ) str += "SSE4.1 ";
+ if (features & CPU_FEATURE_SSE42 ) str += "SSE4.2 ";
+ if (features & CPU_FEATURE_POPCNT) str += "POPCNT ";
+ if (features & CPU_FEATURE_AVX ) str += "AVX ";
+ if (features & CPU_FEATURE_F16C ) str += "F16C ";
+ if (features & CPU_FEATURE_RDRAND) str += "RDRAND ";
+ if (features & CPU_FEATURE_AVX2 ) str += "AVX2 ";
+ if (features & CPU_FEATURE_FMA3 ) str += "FMA3 ";
+ if (features & CPU_FEATURE_LZCNT ) str += "LZCNT ";
+ if (features & CPU_FEATURE_BMI1 ) str += "BMI1 ";
+ if (features & CPU_FEATURE_BMI2 ) str += "BMI2 ";
+ if (features & CPU_FEATURE_AVX512F) str += "AVX512F ";
+ if (features & CPU_FEATURE_AVX512DQ) str += "AVX512DQ ";
+ if (features & CPU_FEATURE_AVX512PF) str += "AVX512PF ";
+ if (features & CPU_FEATURE_AVX512ER) str += "AVX512ER ";
+ if (features & CPU_FEATURE_AVX512CD) str += "AVX512CD ";
+ if (features & CPU_FEATURE_AVX512BW) str += "AVX512BW ";
+ if (features & CPU_FEATURE_AVX512VL) str += "AVX512VL ";
+ if (features & CPU_FEATURE_AVX512IFMA) str += "AVX512IFMA ";
+ if (features & CPU_FEATURE_AVX512VBMI) str += "AVX512VBMI ";
+ return str;
+ }
+
+ std::string stringOfISA (int isa)
+ {
+ if (isa == SSE) return "SSE";
+ if (isa == SSE2) return "SSE2";
+ if (isa == SSE3) return "SSE3";
+ if (isa == SSSE3) return "SSSE3";
+ if (isa == SSE41) return "SSE4.1";
+ if (isa == SSE42) return "SSE4.2";
+ if (isa == AVX) return "AVX";
+ if (isa == AVX2) return "AVX2";
+ if (isa == AVX512) return "AVX512";
+ return "UNKNOWN";
+ }
+
+ bool hasISA(int features, int isa) {
+ return (features & isa) == isa;
+ }
+
+ std::string supportedTargetList (int features)
+ {
+ std::string v;
+ if (hasISA(features,SSE)) v += "SSE ";
+ if (hasISA(features,SSE2)) v += "SSE2 ";
+ if (hasISA(features,SSE3)) v += "SSE3 ";
+ if (hasISA(features,SSSE3)) v += "SSSE3 ";
+ if (hasISA(features,SSE41)) v += "SSE4.1 ";
+ if (hasISA(features,SSE42)) v += "SSE4.2 ";
+ if (hasISA(features,AVX)) v += "AVX ";
+ if (hasISA(features,AVXI)) v += "AVXI ";
+ if (hasISA(features,AVX2)) v += "AVX2 ";
+ if (hasISA(features,AVX512)) v += "AVX512 ";
+ return v;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__WIN32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <psapi.h>
+
+namespace embree
+{
+ std::string getExecutableFileName() {
+ char filename[1024];
+ if (!GetModuleFileName(nullptr, filename, sizeof(filename)))
+ return std::string();
+ return std::string(filename);
+ }
+
+ unsigned int getNumberOfLogicalThreads()
+ {
+ static int nThreads = -1;
+ if (nThreads != -1) return nThreads;
+
+ typedef WORD (WINAPI *GetActiveProcessorGroupCountFunc)();
+ typedef DWORD (WINAPI *GetActiveProcessorCountFunc)(WORD);
+ HMODULE hlib = LoadLibrary("Kernel32");
+ GetActiveProcessorGroupCountFunc pGetActiveProcessorGroupCount = (GetActiveProcessorGroupCountFunc)GetProcAddress(hlib, "GetActiveProcessorGroupCount");
+ GetActiveProcessorCountFunc pGetActiveProcessorCount = (GetActiveProcessorCountFunc) GetProcAddress(hlib, "GetActiveProcessorCount");
+
+ if (pGetActiveProcessorGroupCount && pGetActiveProcessorCount)
+ {
+ int groups = pGetActiveProcessorGroupCount();
+ int totalProcessors = 0;
+ for (int i = 0; i < groups; i++)
+ totalProcessors += pGetActiveProcessorCount(i);
+ nThreads = totalProcessors;
+ }
+ else
+ {
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ nThreads = sysinfo.dwNumberOfProcessors;
+ }
+ assert(nThreads);
+ return nThreads;
+ }
+
+ int getTerminalWidth()
+ {
+ HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (handle == INVALID_HANDLE_VALUE) return 80;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ memset(&info,0,sizeof(info));
+ GetConsoleScreenBufferInfo(handle, &info);
+ return info.dwSize.X;
+ }
+
+ double getSeconds()
+ {
+ LARGE_INTEGER freq, val;
+ QueryPerformanceFrequency(&freq);
+ QueryPerformanceCounter(&val);
+ return (double)val.QuadPart / (double)freq.QuadPart;
+ }
+
+ void sleepSeconds(double t) {
+ Sleep(DWORD(1000.0*t));
+ }
+
+ size_t getVirtualMemoryBytes()
+ {
+ PROCESS_MEMORY_COUNTERS info;
+ GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
+ return (size_t)info.QuotaPeakPagedPoolUsage;
+ }
+
+ size_t getResidentMemoryBytes()
+ {
+ PROCESS_MEMORY_COUNTERS info;
+ GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
+ return (size_t)info.WorkingSetSize;
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Linux Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__LINUX__)
+
+#include <stdio.h>
+#include <unistd.h>
+
+namespace embree
+{
+ std::string getExecutableFileName()
+ {
+ std::string pid = "/proc/" + toString(getpid()) + "/exe";
+ char buf[4096];
+ memset(buf,0,sizeof(buf));
+ if (readlink(pid.c_str(), buf, sizeof(buf)-1) == -1)
+ return std::string();
+ return std::string(buf);
+ }
+
+ size_t getVirtualMemoryBytes()
+ {
+ size_t virt, resident, shared;
+ std::ifstream buffer("/proc/self/statm");
+ buffer >> virt >> resident >> shared;
+ return virt*sysconf(_SC_PAGE_SIZE);
+ }
+
+ size_t getResidentMemoryBytes()
+ {
+ size_t virt, resident, shared;
+ std::ifstream buffer("/proc/self/statm");
+ buffer >> virt >> resident >> shared;
+ return resident*sysconf(_SC_PAGE_SIZE);
+ }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// FreeBSD Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined (__FreeBSD__)
+
+#include <sys/sysctl.h>
+
+namespace embree
+{
+ std::string getExecutableFileName()
+ {
+ const int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
+ char buf[4096];
+ memset(buf,0,sizeof(buf));
+ size_t len = sizeof(buf)-1;
+ if (sysctl(mib, 4, buf, &len, 0x0, 0) == -1)
+ return std::string();
+ return std::string(buf);
+ }
+
+ size_t getVirtualMemoryBytes() {
+ return 0;
+ }
+
+ size_t getResidentMemoryBytes() {
+ return 0;
+ }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mac OS X Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__MACOSX__)
+
+#include <mach-o/dyld.h>
+
+namespace embree
+{
+ std::string getExecutableFileName()
+ {
+ char buf[4096];
+ uint32_t size = sizeof(buf);
+ if (_NSGetExecutablePath(buf, &size) != 0)
+ return std::string();
+ return std::string(buf);
+ }
+
+ size_t getVirtualMemoryBytes() {
+ return 0;
+ }
+
+ size_t getResidentMemoryBytes() {
+ return 0;
+ }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+namespace embree
+{
+ unsigned int getNumberOfLogicalThreads()
+ {
+ static int nThreads = -1;
+ if (nThreads != -1) return nThreads;
+
+// -- GODOT start --
+// #if defined(__MACOSX__)
+#if defined(__MACOSX__) || defined(__ANDROID__)
+// -- GODOT end --
+ nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container
+ assert(nThreads);
+#else
+ cpu_set_t set;
+ if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)
+ nThreads = CPU_COUNT(&set);
+#endif
+
+ assert(nThreads);
+ return nThreads;
+ }
+
+ int getTerminalWidth()
+ {
+ struct winsize info;
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &info) < 0) return 80;
+ return info.ws_col;
+ }
+
+ double getSeconds() {
+ struct timeval tp; gettimeofday(&tp,nullptr);
+ return double(tp.tv_sec) + double(tp.tv_usec)/1E6;
+ }
+
+ void sleepSeconds(double t) {
+ usleep(1000000.0*t);
+ }
+}
+#endif
+
diff --git a/thirdparty/embree/common/sys/sysinfo.h b/thirdparty/embree/common/sys/sysinfo.h
new file mode 100644
index 0000000000..72351d12e4
--- /dev/null
+++ b/thirdparty/embree/common/sys/sysinfo.h
@@ -0,0 +1,178 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define CACHELINE_SIZE 64
+
+#if !defined(PAGE_SIZE)
+ #define PAGE_SIZE 4096
+#endif
+
+#define PAGE_SIZE_2M (2*1024*1024)
+#define PAGE_SIZE_4K (4*1024)
+
+#include "platform.h"
+
+/* define isa namespace and ISA bitvector */
+#if defined (__AVX512VL__)
+# define isa avx512
+# define ISA AVX512
+# define ISA_STR "AVX512"
+#elif defined (__AVX2__)
+# define isa avx2
+# define ISA AVX2
+# define ISA_STR "AVX2"
+#elif defined(__AVXI__)
+# define isa avxi
+# define ISA AVXI
+# define ISA_STR "AVXI"
+#elif defined(__AVX__)
+# define isa avx
+# define ISA AVX
+# define ISA_STR "AVX"
+#elif defined (__SSE4_2__)
+# define isa sse42
+# define ISA SSE42
+# define ISA_STR "SSE4.2"
+//#elif defined (__SSE4_1__) // we demote this to SSE2, MacOSX code compiles with SSE41 by default with XCode 11
+//# define isa sse41
+//# define ISA SSE41
+//# define ISA_STR "SSE4.1"
+//#elif defined(__SSSE3__) // we demote this to SSE2, MacOSX code compiles with SSSE3 by default with ICC
+//# define isa ssse3
+//# define ISA SSSE3
+//# define ISA_STR "SSSE3"
+//#elif defined(__SSE3__) // we demote this to SSE2, MacOSX code compiles with SSE3 by default with clang
+//# define isa sse3
+//# define ISA SSE3
+//# define ISA_STR "SSE3"
+#elif defined(__SSE2__) || defined(__SSE3__) || defined(__SSSE3__)
+# define isa sse2
+# define ISA SSE2
+# define ISA_STR "SSE2"
+#elif defined(__SSE__)
+# define isa sse
+# define ISA SSE
+# define ISA_STR "SSE"
+#else
+#error Unknown ISA
+#endif
+
+namespace embree
+{
+ enum class CPU
+ {
+ XEON_ICE_LAKE,
+ CORE_ICE_LAKE,
+ CORE_TIGER_LAKE,
+ CORE_COMET_LAKE,
+ CORE_CANNON_LAKE,
+ CORE_KABY_LAKE,
+ XEON_SKY_LAKE,
+ CORE_SKY_LAKE,
+ XEON_PHI_KNIGHTS_MILL,
+ XEON_PHI_KNIGHTS_LANDING,
+ XEON_BROADWELL,
+ CORE_BROADWELL,
+ XEON_HASWELL,
+ CORE_HASWELL,
+ XEON_IVY_BRIDGE,
+ CORE_IVY_BRIDGE,
+ SANDY_BRIDGE,
+ NEHALEM,
+ CORE2,
+ CORE1,
+ ARM,
+ UNKNOWN,
+ };
+
+ /*! get the full path to the running executable */
+ std::string getExecutableFileName();
+
+ /*! return platform name */
+ std::string getPlatformName();
+
+ /*! get the full name of the compiler */
+ std::string getCompilerName();
+
+ /*! return the name of the CPU */
+ std::string getCPUVendor();
+
+ /*! get microprocessor model */
+ CPU getCPUModel();
+
+ /*! converts CPU model into string */
+ std::string stringOfCPUModel(CPU model);
+
+ /*! CPU features */
+ static const int CPU_FEATURE_SSE = 1 << 0;
+ static const int CPU_FEATURE_SSE2 = 1 << 1;
+ static const int CPU_FEATURE_SSE3 = 1 << 2;
+ static const int CPU_FEATURE_SSSE3 = 1 << 3;
+ static const int CPU_FEATURE_SSE41 = 1 << 4;
+ static const int CPU_FEATURE_SSE42 = 1 << 5;
+ static const int CPU_FEATURE_POPCNT = 1 << 6;
+ static const int CPU_FEATURE_AVX = 1 << 7;
+ static const int CPU_FEATURE_F16C = 1 << 8;
+ static const int CPU_FEATURE_RDRAND = 1 << 9;
+ static const int CPU_FEATURE_AVX2 = 1 << 10;
+ static const int CPU_FEATURE_FMA3 = 1 << 11;
+ static const int CPU_FEATURE_LZCNT = 1 << 12;
+ static const int CPU_FEATURE_BMI1 = 1 << 13;
+ static const int CPU_FEATURE_BMI2 = 1 << 14;
+ static const int CPU_FEATURE_AVX512F = 1 << 16;
+ static const int CPU_FEATURE_AVX512DQ = 1 << 17;
+ static const int CPU_FEATURE_AVX512PF = 1 << 18;
+ static const int CPU_FEATURE_AVX512ER = 1 << 19;
+ static const int CPU_FEATURE_AVX512CD = 1 << 20;
+ static const int CPU_FEATURE_AVX512BW = 1 << 21;
+ static const int CPU_FEATURE_AVX512VL = 1 << 22;
+ static const int CPU_FEATURE_AVX512IFMA = 1 << 23;
+ static const int CPU_FEATURE_AVX512VBMI = 1 << 24;
+ static const int CPU_FEATURE_XMM_ENABLED = 1 << 25;
+ static const int CPU_FEATURE_YMM_ENABLED = 1 << 26;
+ static const int CPU_FEATURE_ZMM_ENABLED = 1 << 27;
+
+ /*! get CPU features */
+ int getCPUFeatures();
+
+ /*! convert CPU features into a string */
+ std::string stringOfCPUFeatures(int features);
+
+ /*! creates a string of all supported targets that are supported */
+ std::string supportedTargetList (int isa);
+
+ /*! ISAs */
+ static const int SSE = CPU_FEATURE_SSE | CPU_FEATURE_XMM_ENABLED;
+ static const int SSE2 = SSE | CPU_FEATURE_SSE2;
+ static const int SSE3 = SSE2 | CPU_FEATURE_SSE3;
+ static const int SSSE3 = SSE3 | CPU_FEATURE_SSSE3;
+ static const int SSE41 = SSSE3 | CPU_FEATURE_SSE41;
+ static const int SSE42 = SSE41 | CPU_FEATURE_SSE42 | CPU_FEATURE_POPCNT;
+ static const int AVX = SSE42 | CPU_FEATURE_AVX | CPU_FEATURE_YMM_ENABLED;
+ static const int AVXI = AVX | CPU_FEATURE_F16C | CPU_FEATURE_RDRAND;
+ static const int AVX2 = AVXI | CPU_FEATURE_AVX2 | CPU_FEATURE_FMA3 | CPU_FEATURE_BMI1 | CPU_FEATURE_BMI2 | CPU_FEATURE_LZCNT;
+ static const int AVX512 = AVX2 | CPU_FEATURE_AVX512F | CPU_FEATURE_AVX512DQ | CPU_FEATURE_AVX512CD | CPU_FEATURE_AVX512BW | CPU_FEATURE_AVX512VL | CPU_FEATURE_ZMM_ENABLED;
+
+ /*! converts ISA bitvector into a string */
+ std::string stringOfISA(int features);
+
+ /*! return the number of logical threads of the system */
+ unsigned int getNumberOfLogicalThreads();
+
+ /*! returns the size of the terminal window in characters */
+ int getTerminalWidth();
+
+ /*! returns performance counter in seconds */
+ double getSeconds();
+
+ /*! sleeps the specified number of seconds */
+ void sleepSeconds(double t);
+
+ /*! returns virtual address space occupied by process */
+ size_t getVirtualMemoryBytes();
+
+ /*! returns resident memory required by process */
+ size_t getResidentMemoryBytes();
+}
diff --git a/thirdparty/embree/common/sys/thread.cpp b/thirdparty/embree/common/sys/thread.cpp
new file mode 100644
index 0000000000..f4014be89b
--- /dev/null
+++ b/thirdparty/embree/common/sys/thread.cpp
@@ -0,0 +1,474 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "thread.h"
+#include "sysinfo.h"
+#include "string.h"
+
+#include <iostream>
+#if defined(__ARM_NEON)
+#include "../simd/arm/emulation.h"
+#else
+#include <xmmintrin.h>
+#endif
+
+#if defined(PTHREADS_WIN32)
+#pragma comment (lib, "pthreadVC.lib")
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__WIN32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace embree
+{
+ /*! set the affinity of a given thread */
+ void setAffinity(HANDLE thread, ssize_t affinity)
+ {
+ typedef WORD (WINAPI *GetActiveProcessorGroupCountFunc)();
+ typedef DWORD (WINAPI *GetActiveProcessorCountFunc)(WORD);
+ typedef BOOL (WINAPI *SetThreadGroupAffinityFunc)(HANDLE, const GROUP_AFFINITY *, PGROUP_AFFINITY);
+ typedef BOOL (WINAPI *SetThreadIdealProcessorExFunc)(HANDLE, PPROCESSOR_NUMBER, PPROCESSOR_NUMBER);
+ HMODULE hlib = LoadLibrary("Kernel32");
+ GetActiveProcessorGroupCountFunc pGetActiveProcessorGroupCount = (GetActiveProcessorGroupCountFunc)GetProcAddress(hlib, "GetActiveProcessorGroupCount");
+ GetActiveProcessorCountFunc pGetActiveProcessorCount = (GetActiveProcessorCountFunc)GetProcAddress(hlib, "GetActiveProcessorCount");
+ SetThreadGroupAffinityFunc pSetThreadGroupAffinity = (SetThreadGroupAffinityFunc)GetProcAddress(hlib, "SetThreadGroupAffinity");
+ SetThreadIdealProcessorExFunc pSetThreadIdealProcessorEx = (SetThreadIdealProcessorExFunc)GetProcAddress(hlib, "SetThreadIdealProcessorEx");
+ if (pGetActiveProcessorGroupCount && pGetActiveProcessorCount && pSetThreadGroupAffinity && pSetThreadIdealProcessorEx)
+ {
+ int groups = pGetActiveProcessorGroupCount();
+ int totalProcessors = 0, group = 0, number = 0;
+ for (int i = 0; i<groups; i++) {
+ int processors = pGetActiveProcessorCount(i);
+ if (totalProcessors + processors > affinity) {
+ group = i;
+ number = (int)affinity - totalProcessors;
+ break;
+ }
+ totalProcessors += processors;
+ }
+
+ GROUP_AFFINITY groupAffinity;
+ groupAffinity.Group = (WORD)group;
+ groupAffinity.Mask = (KAFFINITY)(uint64_t(1) << number);
+ groupAffinity.Reserved[0] = 0;
+ groupAffinity.Reserved[1] = 0;
+ groupAffinity.Reserved[2] = 0;
+ if (!pSetThreadGroupAffinity(thread, &groupAffinity, nullptr))
+ WARNING("SetThreadGroupAffinity failed"); // on purpose only a warning
+
+ PROCESSOR_NUMBER processorNumber;
+ processorNumber.Group = group;
+ processorNumber.Number = number;
+ processorNumber.Reserved = 0;
+ if (!pSetThreadIdealProcessorEx(thread, &processorNumber, nullptr))
+ WARNING("SetThreadIdealProcessorEx failed"); // on purpose only a warning
+ }
+ else
+ {
+ if (!SetThreadAffinityMask(thread, DWORD_PTR(uint64_t(1) << affinity)))
+ WARNING("SetThreadAffinityMask failed"); // on purpose only a warning
+ if (SetThreadIdealProcessor(thread, (DWORD)affinity) == (DWORD)-1)
+ WARNING("SetThreadIdealProcessor failed"); // on purpose only a warning
+ }
+ }
+
+ /*! set affinity of the calling thread */
+ void setAffinity(ssize_t affinity) {
+ setAffinity(GetCurrentThread(), affinity);
+ }
+
+ struct ThreadStartupData
+ {
+ public:
+ ThreadStartupData (thread_func f, void* arg)
+ : f(f), arg(arg) {}
+ public:
+ thread_func f;
+ void* arg;
+ };
+
+ DWORD WINAPI threadStartup(LPVOID ptr)
+ {
+ ThreadStartupData* parg = (ThreadStartupData*) ptr;
+ _mm_setcsr(_mm_getcsr() | /*FTZ:*/ (1<<15) | /*DAZ:*/ (1<<6));
+ parg->f(parg->arg);
+ delete parg;
+ return 0;
+ }
+
+#if !defined(PTHREADS_WIN32)
+
+ /*! creates a hardware thread running on specific core */
+ thread_t createThread(thread_func f, void* arg, size_t stack_size, ssize_t threadID)
+ {
+ HANDLE thread = CreateThread(nullptr, stack_size, threadStartup, new ThreadStartupData(f,arg), 0, nullptr);
+ if (thread == nullptr) FATAL("CreateThread failed");
+ if (threadID >= 0) setAffinity(thread, threadID);
+ return thread_t(thread);
+ }
+
+ /*! the thread calling this function gets yielded */
+ void yield() {
+ SwitchToThread();
+ }
+
+ /*! waits until the given thread has terminated */
+ void join(thread_t tid) {
+ WaitForSingleObject(HANDLE(tid), INFINITE);
+ CloseHandle(HANDLE(tid));
+ }
+
+ /*! destroy a hardware thread by its handle */
+ void destroyThread(thread_t tid) {
+ TerminateThread(HANDLE(tid),0);
+ CloseHandle(HANDLE(tid));
+ }
+
+ /*! creates thread local storage */
+ tls_t createTls() {
+ return tls_t(size_t(TlsAlloc()));
+ }
+
+ /*! set the thread local storage pointer */
+ void setTls(tls_t tls, void* const ptr) {
+ TlsSetValue(DWORD(size_t(tls)), ptr);
+ }
+
+ /*! return the thread local storage pointer */
+ void* getTls(tls_t tls) {
+ return TlsGetValue(DWORD(size_t(tls)));
+ }
+
+ /*! destroys thread local storage identifier */
+ void destroyTls(tls_t tls) {
+ TlsFree(DWORD(size_t(tls)));
+ }
+#endif
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Linux Platform
+////////////////////////////////////////////////////////////////////////////////
+
+// -- GODOT start --
+#if defined(__LINUX__) && !defined(__ANDROID__)
+// -- GODOT end --
+
+#include <fstream>
+#include <sstream>
+#include <algorithm>
+
+namespace embree
+{
+ static MutexSys mutex;
+ static std::vector<size_t> threadIDs;
+
+ /* changes thread ID mapping such that we first fill up all thread on one core */
+ size_t mapThreadID(size_t threadID)
+ {
+ Lock<MutexSys> lock(mutex);
+
+ if (threadIDs.size() == 0)
+ {
+ /* parse thread/CPU topology */
+ for (size_t cpuID=0;;cpuID++)
+ {
+ std::fstream fs;
+ std::string cpu = std::string("/sys/devices/system/cpu/cpu") + std::to_string((long long)cpuID) + std::string("/topology/thread_siblings_list");
+ fs.open (cpu.c_str(), std::fstream::in);
+ if (fs.fail()) break;
+
+ int i;
+ while (fs >> i)
+ {
+ if (std::none_of(threadIDs.begin(),threadIDs.end(),[&] (int id) { return id == i; }))
+ threadIDs.push_back(i);
+ if (fs.peek() == ',')
+ fs.ignore();
+ }
+ fs.close();
+ }
+
+#if 0
+ for (size_t i=0;i<threadIDs.size();i++)
+ std::cout << i << " -> " << threadIDs[i] << std::endl;
+#endif
+
+ /* verify the mapping and do not use it if the mapping has errors */
+ for (size_t i=0;i<threadIDs.size();i++) {
+ for (size_t j=0;j<threadIDs.size();j++) {
+ if (i != j && threadIDs[i] == threadIDs[j]) {
+ threadIDs.clear();
+ }
+ }
+ }
+ }
+
+ /* re-map threadIDs if mapping is available */
+ size_t ID = threadID;
+ if (threadID < threadIDs.size())
+ ID = threadIDs[threadID];
+
+ /* find correct thread to affinitize to */
+ cpu_set_t set;
+ if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)
+ {
+ for (int i=0, j=0; i<CPU_SETSIZE; i++)
+ {
+ if (!CPU_ISSET(i,&set)) continue;
+
+ if (j == ID) {
+ ID = i;
+ break;
+ }
+ j++;
+ }
+ }
+
+ return ID;
+ }
+
+ /*! set affinity of the calling thread */
+ void setAffinity(ssize_t affinity)
+ {
+ cpu_set_t cset;
+ CPU_ZERO(&cset);
+ size_t threadID = mapThreadID(affinity);
+ CPU_SET(threadID, &cset);
+
+ pthread_setaffinity_np(pthread_self(), sizeof(cset), &cset);
+ }
+}
+#endif
+
+// -- GODOT start --
+////////////////////////////////////////////////////////////////////////////////
+/// Android Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__ANDROID__)
+
+namespace embree
+{
+ /*! set affinity of the calling thread */
+ void setAffinity(ssize_t affinity)
+ {
+ cpu_set_t cset;
+ CPU_ZERO(&cset);
+ CPU_SET(affinity, &cset);
+
+ sched_setaffinity(0, sizeof(cset), &cset);
+ }
+}
+#endif
+// -- GODOT end --
+
+////////////////////////////////////////////////////////////////////////////////
+/// FreeBSD Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__FreeBSD__)
+
+#include <pthread_np.h>
+
+namespace embree
+{
+ /*! set affinity of the calling thread */
+ void setAffinity(ssize_t affinity)
+ {
+ cpuset_t cset;
+ CPU_ZERO(&cset);
+ CPU_SET(affinity, &cset);
+
+ pthread_setaffinity_np(pthread_self(), sizeof(cset), &cset);
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// MacOSX Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__MACOSX__)
+
+#include <mach/thread_act.h>
+#include <mach/thread_policy.h>
+#include <mach/mach_init.h>
+
+namespace embree
+{
+ /*! set affinity of the calling thread */
+ void setAffinity(ssize_t affinity)
+ {
+#if !defined(__ARM_NEON) // affinity seems not supported on M1 chip
+
+ thread_affinity_policy ap;
+ ap.affinity_tag = affinity;
+ if (thread_policy_set(mach_thread_self(),THREAD_AFFINITY_POLICY,(thread_policy_t)&ap,THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS)
+ WARNING("setting thread affinity failed"); // on purpose only a warning
+
+#endif
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__) || defined(PTHREADS_WIN32)
+
+#include <pthread.h>
+#include <sched.h>
+
+#if defined(__USE_NUMA__)
+#include <numa.h>
+#endif
+
+namespace embree
+{
+ struct ThreadStartupData
+ {
+ public:
+ ThreadStartupData (thread_func f, void* arg, int affinity)
+ : f(f), arg(arg), affinity(affinity) {}
+ public:
+ thread_func f;
+ void* arg;
+ ssize_t affinity;
+ };
+
+ static void* threadStartup(ThreadStartupData* parg)
+ {
+ _mm_setcsr(_mm_getcsr() | /*FTZ:*/ (1<<15) | /*DAZ:*/ (1<<6));
+
+ /*! Mac OS X does not support setting affinity at thread creation time */
+#if defined(__MACOSX__)
+ if (parg->affinity >= 0)
+ setAffinity(parg->affinity);
+#endif
+
+ parg->f(parg->arg);
+ delete parg;
+ return nullptr;
+ }
+
+ /*! creates a hardware thread running on specific core */
+ thread_t createThread(thread_func f, void* arg, size_t stack_size, ssize_t threadID)
+ {
+ /* set stack size */
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ if (stack_size > 0) pthread_attr_setstacksize (&attr, stack_size);
+
+ /* create thread */
+ pthread_t* tid = new pthread_t;
+ if (pthread_create(tid,&attr,(void*(*)(void*))threadStartup,new ThreadStartupData(f,arg,threadID)) != 0) {
+ pthread_attr_destroy(&attr);
+ delete tid;
+ FATAL("pthread_create failed");
+ }
+ pthread_attr_destroy(&attr);
+
+ /* set affinity */
+// -- GODOT start --
+#if defined(__LINUX__) && !defined(__ANDROID__)
+// -- GODOT end --
+ if (threadID >= 0) {
+ cpu_set_t cset;
+ CPU_ZERO(&cset);
+ threadID = mapThreadID(threadID);
+ CPU_SET(threadID, &cset);
+ pthread_setaffinity_np(*tid, sizeof(cset), &cset);
+ }
+#elif defined(__FreeBSD__)
+ if (threadID >= 0) {
+ cpuset_t cset;
+ CPU_ZERO(&cset);
+ CPU_SET(threadID, &cset);
+ pthread_setaffinity_np(*tid, sizeof(cset), &cset);
+ }
+// -- GODOT start --
+#elif defined(__ANDROID__)
+ if (threadID >= 0) {
+ cpu_set_t cset;
+ CPU_ZERO(&cset);
+ CPU_SET(threadID, &cset);
+ sched_setaffinity(pthread_gettid_np(*tid), sizeof(cset), &cset);
+ }
+#endif
+// -- GODOT end --
+
+ return thread_t(tid);
+ }
+
+ /*! the thread calling this function gets yielded */
+ void yield() {
+ sched_yield();
+ }
+
+ /*! waits until the given thread has terminated */
+ void join(thread_t tid) {
+ if (pthread_join(*(pthread_t*)tid, nullptr) != 0)
+ FATAL("pthread_join failed");
+ delete (pthread_t*)tid;
+ }
+
+ /*! destroy a hardware thread by its handle */
+ void destroyThread(thread_t tid) {
+// -- GODOT start --
+#if defined(__ANDROID__)
+ FATAL("Can't destroy threads on Android.");
+#else
+ pthread_cancel(*(pthread_t*)tid);
+ delete (pthread_t*)tid;
+#endif
+// -- GODOT end --
+ }
+
+ /*! creates thread local storage */
+ tls_t createTls()
+ {
+ pthread_key_t* key = new pthread_key_t;
+ if (pthread_key_create(key,nullptr) != 0) {
+ delete key;
+ FATAL("pthread_key_create failed");
+ }
+
+ return tls_t(key);
+ }
+
+ /*! return the thread local storage pointer */
+ void* getTls(tls_t tls)
+ {
+ assert(tls);
+ return pthread_getspecific(*(pthread_key_t*)tls);
+ }
+
+ /*! set the thread local storage pointer */
+ void setTls(tls_t tls, void* const ptr)
+ {
+ assert(tls);
+ if (pthread_setspecific(*(pthread_key_t*)tls, ptr) != 0)
+ FATAL("pthread_setspecific failed");
+ }
+
+ /*! destroys thread local storage identifier */
+ void destroyTls(tls_t tls)
+ {
+ assert(tls);
+ if (pthread_key_delete(*(pthread_key_t*)tls) != 0)
+ FATAL("pthread_key_delete failed");
+ delete (pthread_key_t*)tls;
+ }
+}
+
+#endif
diff --git a/thirdparty/embree/common/sys/thread.h b/thirdparty/embree/common/sys/thread.h
new file mode 100644
index 0000000000..92a10d5c5d
--- /dev/null
+++ b/thirdparty/embree/common/sys/thread.h
@@ -0,0 +1,49 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "platform.h"
+#include "mutex.h"
+#include "alloc.h"
+#include "vector.h"
+#include <vector>
+
+namespace embree
+{
+ /*! type for thread */
+ typedef struct opaque_thread_t* thread_t;
+
+ /*! signature of thread start function */
+ typedef void (*thread_func)(void*);
+
+ /*! creates a hardware thread running on specific logical thread */
+ thread_t createThread(thread_func f, void* arg, size_t stack_size = 0, ssize_t threadID = -1);
+
+ /*! set affinity of the calling thread */
+ void setAffinity(ssize_t affinity);
+
+ /*! the thread calling this function gets yielded */
+ void yield();
+
+ /*! waits until the given thread has terminated */
+ void join(thread_t tid);
+
+ /*! destroy handle of a thread */
+ void destroyThread(thread_t tid);
+
+ /*! type for handle to thread local storage */
+ typedef struct opaque_tls_t* tls_t;
+
+ /*! creates thread local storage */
+ tls_t createTls();
+
+ /*! set the thread local storage pointer */
+ void setTls(tls_t tls, void* const ptr);
+
+ /*! return the thread local storage pointer */
+ void* getTls(tls_t tls);
+
+ /*! destroys thread local storage identifier */
+ void destroyTls(tls_t tls);
+}
diff --git a/thirdparty/embree/common/sys/vector.h b/thirdparty/embree/common/sys/vector.h
new file mode 100644
index 0000000000..f832626789
--- /dev/null
+++ b/thirdparty/embree/common/sys/vector.h
@@ -0,0 +1,242 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "alloc.h"
+#include <algorithm>
+
+namespace embree
+{
+ template<typename T, typename allocator>
+ class vector_t
+ {
+ public:
+ typedef T value_type;
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ __forceinline vector_t ()
+ : size_active(0), size_alloced(0), items(nullptr) {}
+
+ __forceinline explicit vector_t (size_t sz)
+ : size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }
+
+ template<typename M>
+ __forceinline explicit vector_t (M alloc, size_t sz)
+ : alloc(alloc), size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }
+
+ __forceinline ~vector_t() {
+ clear();
+ }
+
+ __forceinline vector_t (const vector_t& other)
+ {
+ size_active = other.size_active;
+ size_alloced = other.size_alloced;
+ items = alloc.allocate(size_alloced);
+ for (size_t i=0; i<size_active; i++)
+ ::new (&items[i]) value_type(other.items[i]);
+ }
+
+ __forceinline vector_t (vector_t&& other)
+ : alloc(std::move(other.alloc))
+ {
+ size_active = other.size_active; other.size_active = 0;
+ size_alloced = other.size_alloced; other.size_alloced = 0;
+ items = other.items; other.items = nullptr;
+ }
+
+ __forceinline vector_t& operator=(const vector_t& other)
+ {
+ resize(other.size_active);
+ for (size_t i=0; i<size_active; i++)
+ items[i] = value_type(other.items[i]);
+ return *this;
+ }
+
+ __forceinline vector_t& operator=(vector_t&& other)
+ {
+ clear();
+ alloc = std::move(other.alloc);
+ size_active = other.size_active; other.size_active = 0;
+ size_alloced = other.size_alloced; other.size_alloced = 0;
+ items = other.items; other.items = nullptr;
+ return *this;
+ }
+
+ /********************** Iterators ****************************/
+
+ __forceinline iterator begin() { return items; };
+ __forceinline const_iterator begin() const { return items; };
+
+ __forceinline iterator end () { return items+size_active; };
+ __forceinline const_iterator end () const { return items+size_active; };
+
+
+ /********************** Capacity ****************************/
+
+ __forceinline bool empty () const { return size_active == 0; }
+ __forceinline size_t size () const { return size_active; }
+ __forceinline size_t capacity () const { return size_alloced; }
+
+
+ __forceinline void resize(size_t new_size) {
+ internal_resize(new_size,internal_grow_size(new_size));
+ }
+
+ __forceinline void reserve(size_t new_alloced)
+ {
+ /* do nothing if container already large enough */
+ if (new_alloced <= size_alloced)
+ return;
+
+ /* resize exact otherwise */
+ internal_resize(size_active,new_alloced);
+ }
+
+ __forceinline void shrink_to_fit() {
+ internal_resize(size_active,size_active);
+ }
+
+ /******************** Element access **************************/
+
+ __forceinline T& operator[](size_t i) { assert(i < size_active); return items[i]; }
+ __forceinline const T& operator[](size_t i) const { assert(i < size_active); return items[i]; }
+
+ __forceinline T& at(size_t i) { assert(i < size_active); return items[i]; }
+ __forceinline const T& at(size_t i) const { assert(i < size_active); return items[i]; }
+
+ __forceinline T& front() const { assert(size_active > 0); return items[0]; };
+ __forceinline T& back () const { assert(size_active > 0); return items[size_active-1]; };
+
+ __forceinline T* data() { return items; };
+ __forceinline const T* data() const { return items; };
+
+
+ /******************** Modifiers **************************/
+
+ __forceinline void push_back(const T& nt)
+ {
+ const T v = nt; // need local copy as input reference could point to this vector
+ internal_resize(size_active,internal_grow_size(size_active+1));
+ ::new (&items[size_active++]) T(v);
+ }
+
+ __forceinline void pop_back()
+ {
+ assert(!empty());
+ size_active--;
+ alloc.destroy(&items[size_active]);
+ }
+
+ __forceinline void clear()
+ {
+ /* destroy elements */
+ for (size_t i=0; i<size_active; i++)
+ alloc.destroy(&items[i]);
+
+ /* free memory */
+ alloc.deallocate(items,size_alloced);
+ items = nullptr;
+ size_active = size_alloced = 0;
+ }
+
+ /******************** Comparisons **************************/
+
+ friend bool operator== (const vector_t& a, const vector_t& b)
+ {
+ if (a.size() != b.size()) return false;
+ for (size_t i=0; i<a.size(); i++)
+ if (a[i] != b[i])
+ return false;
+ return true;
+ }
+
+ friend bool operator!= (const vector_t& a, const vector_t& b) {
+ return !(a==b);
+ }
+
+ private:
+
+ __forceinline void internal_resize_init(size_t new_active)
+ {
+ assert(size_active == 0);
+ assert(size_alloced == 0);
+ assert(items == nullptr);
+ if (new_active == 0) return;
+ items = alloc.allocate(new_active);
+ for (size_t i=0; i<new_active; i++) ::new (&items[i]) T();
+ size_active = new_active;
+ size_alloced = new_active;
+ }
+
+ __forceinline void internal_resize(size_t new_active, size_t new_alloced)
+ {
+ assert(new_active <= new_alloced);
+
+ /* destroy elements */
+ if (new_active < size_active)
+ {
+ for (size_t i=new_active; i<size_active; i++)
+ alloc.destroy(&items[i]);
+ size_active = new_active;
+ }
+
+ /* only reallocate if necessary */
+ if (new_alloced == size_alloced) {
+ for (size_t i=size_active; i<new_active; i++) ::new (&items[i]) T;
+ size_active = new_active;
+ return;
+ }
+
+ /* reallocate and copy items */
+ T* old_items = items;
+ items = alloc.allocate(new_alloced);
+ for (size_t i=0; i<size_active; i++) {
+ ::new (&items[i]) T(std::move(old_items[i]));
+ alloc.destroy(&old_items[i]);
+ }
+
+ for (size_t i=size_active; i<new_active; i++) {
+ ::new (&items[i]) T;
+ }
+
+ alloc.deallocate(old_items,size_alloced);
+ size_active = new_active;
+ size_alloced = new_alloced;
+ }
+
+ __forceinline size_t internal_grow_size(size_t new_alloced)
+ {
+ /* do nothing if container already large enough */
+ if (new_alloced <= size_alloced)
+ return size_alloced;
+
+ /* resize to next power of 2 otherwise */
+ size_t new_size_alloced = size_alloced;
+ while (new_size_alloced < new_alloced) {
+ new_size_alloced = std::max(size_t(1),2*new_size_alloced);
+ }
+ return new_size_alloced;
+ }
+
+ private:
+ allocator alloc;
+ size_t size_active; // number of valid items
+ size_t size_alloced; // number of items allocated
+ T* items; // data array
+ };
+
+ /*! vector class that performs standard allocations */
+ template<typename T>
+ using vector = vector_t<T,std::allocator<T>>;
+
+ /*! vector class that performs aligned allocations */
+ template<typename T>
+ using avector = vector_t<T,aligned_allocator<T,std::alignment_of<T>::value> >;
+
+ /*! vector class that performs OS allocations */
+ template<typename T>
+ using ovector = vector_t<T,os_allocator<T> >;
+}
diff --git a/thirdparty/embree/common/tasking/taskscheduler.h b/thirdparty/embree/common/tasking/taskscheduler.h
new file mode 100644
index 0000000000..8f3dd87689
--- /dev/null
+++ b/thirdparty/embree/common/tasking/taskscheduler.h
@@ -0,0 +1,15 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#if defined(TASKING_INTERNAL)
+# include "taskschedulerinternal.h"
+#elif defined(TASKING_TBB)
+# include "taskschedulertbb.h"
+#elif defined(TASKING_PPL)
+# include "taskschedulerppl.h"
+#else
+# error "no tasking system enabled"
+#endif
+
diff --git a/thirdparty/embree/common/tasking/taskschedulerinternal.cpp b/thirdparty/embree/common/tasking/taskschedulerinternal.cpp
new file mode 100644
index 0000000000..ad438588a3
--- /dev/null
+++ b/thirdparty/embree/common/tasking/taskschedulerinternal.cpp
@@ -0,0 +1,420 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "taskschedulerinternal.h"
+#include "../math/math.h"
+#include "../sys/sysinfo.h"
+#include <algorithm>
+
+namespace embree
+{
+ RTC_NAMESPACE_BEGIN
+
+ static MutexSys g_mutex;
+ size_t TaskScheduler::g_numThreads = 0;
+ __thread TaskScheduler* TaskScheduler::g_instance = nullptr;
+ std::vector<Ref<TaskScheduler>> g_instance_vector;
+ __thread TaskScheduler::Thread* TaskScheduler::thread_local_thread = nullptr;
+ TaskScheduler::ThreadPool* TaskScheduler::threadPool = nullptr;
+
+ template<typename Predicate, typename Body>
+ __forceinline void TaskScheduler::steal_loop(Thread& thread, const Predicate& pred, const Body& body)
+ {
+ while (true)
+ {
+ /*! some rounds that yield */
+ for (size_t i=0; i<32; i++)
+ {
+ /*! some spinning rounds */
+ const size_t threadCount = thread.threadCount();
+ for (size_t j=0; j<1024; j+=threadCount)
+ {
+ if (!pred()) return;
+ if (thread.scheduler->steal_from_other_threads(thread)) {
+ i=j=0;
+ body();
+ }
+ }
+ yield();
+ }
+ }
+ }
+
+ /*! run this task */
+ void TaskScheduler::Task::run_internal (Thread& thread) // FIXME: avoid as many dll_exports as possible
+ {
+ /* try to run if not already stolen */
+ if (try_switch_state(INITIALIZED,DONE))
+ {
+ Task* prevTask = thread.task;
+ thread.task = this;
+ // -- GODOT start --
+ // try {
+ // if (thread.scheduler->cancellingException == nullptr)
+ closure->execute();
+ // } catch (...) {
+ // if (thread.scheduler->cancellingException == nullptr)
+ // thread.scheduler->cancellingException = std::current_exception();
+ // }
+ // -- GODOT end --
+ thread.task = prevTask;
+ add_dependencies(-1);
+ }
+
+ /* steal until all dependencies have completed */
+ steal_loop(thread,
+ [&] () { return dependencies>0; },
+ [&] () { while (thread.tasks.execute_local_internal(thread,this)); });
+
+ /* now signal our parent task that we are finished */
+ if (parent)
+ parent->add_dependencies(-1);
+ }
+
+ /*! run this task */
+ dll_export void TaskScheduler::Task::run (Thread& thread) {
+ run_internal(thread);
+ }
+
+ bool TaskScheduler::TaskQueue::execute_local_internal(Thread& thread, Task* parent)
+ {
+ /* stop if we run out of local tasks or reach the waiting task */
+ if (right == 0 || &tasks[right-1] == parent)
+ return false;
+
+ /* execute task */
+ size_t oldRight = right;
+ tasks[right-1].run_internal(thread);
+ if (right != oldRight) {
+ THROW_RUNTIME_ERROR("you have to wait for spawned subtasks");
+ }
+
+ /* pop task and closure from stack */
+ right--;
+ if (tasks[right].stackPtr != size_t(-1))
+ stackPtr = tasks[right].stackPtr;
+
+ /* also move left pointer */
+ if (left >= right) left.store(right.load());
+
+ return right != 0;
+ }
+
+ dll_export bool TaskScheduler::TaskQueue::execute_local(Thread& thread, Task* parent) {
+ return execute_local_internal(thread,parent);
+ }
+
+ bool TaskScheduler::TaskQueue::steal(Thread& thread)
+ {
+ size_t l = left;
+ size_t r = right;
+ if (l < r)
+ {
+ l = left++;
+ if (l >= r)
+ return false;
+ }
+ else
+ return false;
+
+ if (!tasks[l].try_steal(thread.tasks.tasks[thread.tasks.right]))
+ return false;
+
+ thread.tasks.right++;
+ return true;
+ }
+
+ /* we steal from the left */
+ size_t TaskScheduler::TaskQueue::getTaskSizeAtLeft()
+ {
+ if (left >= right) return 0;
+ return tasks[left].N;
+ }
+
+ void threadPoolFunction(std::pair<TaskScheduler::ThreadPool*,size_t>* pair)
+ {
+ TaskScheduler::ThreadPool* pool = pair->first;
+ size_t threadIndex = pair->second;
+ delete pair;
+ pool->thread_loop(threadIndex);
+ }
+
+ TaskScheduler::ThreadPool::ThreadPool(bool set_affinity)
+ : numThreads(0), numThreadsRunning(0), set_affinity(set_affinity), running(false) {}
+
+ dll_export void TaskScheduler::ThreadPool::startThreads()
+ {
+ if (running) return;
+ setNumThreads(numThreads,true);
+ }
+
+ void TaskScheduler::ThreadPool::setNumThreads(size_t newNumThreads, bool startThreads)
+ {
+ Lock<MutexSys> lock(g_mutex);
+ assert(newNumThreads);
+ newNumThreads = min(newNumThreads, (size_t) getNumberOfLogicalThreads());
+
+ numThreads = newNumThreads;
+ if (!startThreads && !running) return;
+ running = true;
+ size_t numThreadsActive = numThreadsRunning;
+
+ mutex.lock();
+ numThreadsRunning = newNumThreads;
+ mutex.unlock();
+ condition.notify_all();
+
+ /* start new threads */
+ for (size_t t=numThreadsActive; t<numThreads; t++)
+ {
+ if (t == 0) continue;
+ auto pair = new std::pair<TaskScheduler::ThreadPool*,size_t>(this,t);
+ threads.push_back(createThread((thread_func)threadPoolFunction,pair,4*1024*1024,set_affinity ? t : -1));
+ }
+
+ /* stop some threads if we reduce the number of threads */
+ for (ssize_t t=numThreadsActive-1; t>=ssize_t(numThreadsRunning); t--) {
+ if (t == 0) continue;
+ embree::join(threads.back());
+ threads.pop_back();
+ }
+ }
+
+ TaskScheduler::ThreadPool::~ThreadPool()
+ {
+ /* leave all taskschedulers */
+ mutex.lock();
+ numThreadsRunning = 0;
+ mutex.unlock();
+ condition.notify_all();
+
+ /* wait for threads to terminate */
+ for (size_t i=0; i<threads.size(); i++)
+ embree::join(threads[i]);
+ }
+
+ dll_export void TaskScheduler::ThreadPool::add(const Ref<TaskScheduler>& scheduler)
+ {
+ mutex.lock();
+ schedulers.push_back(scheduler);
+ mutex.unlock();
+ condition.notify_all();
+ }
+
+ dll_export void TaskScheduler::ThreadPool::remove(const Ref<TaskScheduler>& scheduler)
+ {
+ Lock<MutexSys> lock(mutex);
+ for (std::list<Ref<TaskScheduler> >::iterator it = schedulers.begin(); it != schedulers.end(); it++) {
+ if (scheduler == *it) {
+ schedulers.erase(it);
+ return;
+ }
+ }
+ }
+
+ void TaskScheduler::ThreadPool::thread_loop(size_t globalThreadIndex)
+ {
+ while (globalThreadIndex < numThreadsRunning)
+ {
+ Ref<TaskScheduler> scheduler = NULL;
+ ssize_t threadIndex = -1;
+ {
+ Lock<MutexSys> lock(mutex);
+ condition.wait(mutex, [&] () { return globalThreadIndex >= numThreadsRunning || !schedulers.empty(); });
+ if (globalThreadIndex >= numThreadsRunning) break;
+ scheduler = schedulers.front();
+ threadIndex = scheduler->allocThreadIndex();
+ }
+ scheduler->thread_loop(threadIndex);
+ }
+ }
+
+ TaskScheduler::TaskScheduler()
+ : threadCounter(0), anyTasksRunning(0), hasRootTask(false)
+ {
+ threadLocal.resize(2*getNumberOfLogicalThreads()); // FIXME: this has to be 2x as in the compatibility join mode with rtcCommitScene the worker threads also join. When disallowing rtcCommitScene to join a build we can remove the 2x.
+ for (size_t i=0; i<threadLocal.size(); i++)
+ threadLocal[i].store(nullptr);
+ }
+
+ TaskScheduler::~TaskScheduler()
+ {
+ assert(threadCounter == 0);
+ }
+
+ dll_export size_t TaskScheduler::threadID()
+ {
+ Thread* thread = TaskScheduler::thread();
+ if (thread) return thread->threadIndex;
+ else return 0;
+ }
+
+ dll_export size_t TaskScheduler::threadIndex()
+ {
+ Thread* thread = TaskScheduler::thread();
+ if (thread) return thread->threadIndex;
+ else return 0;
+ }
+
+ dll_export size_t TaskScheduler::threadCount() {
+ return threadPool->size();
+ }
+
+ dll_export TaskScheduler* TaskScheduler::instance()
+ {
+ if (g_instance == NULL) {
+ Lock<MutexSys> lock(g_mutex);
+ g_instance = new TaskScheduler;
+ g_instance_vector.push_back(g_instance);
+ }
+ return g_instance;
+ }
+
+ void TaskScheduler::create(size_t numThreads, bool set_affinity, bool start_threads)
+ {
+ if (!threadPool) threadPool = new TaskScheduler::ThreadPool(set_affinity);
+ threadPool->setNumThreads(numThreads,start_threads);
+ }
+
+ void TaskScheduler::destroy() {
+ delete threadPool; threadPool = nullptr;
+ }
+
+ dll_export ssize_t TaskScheduler::allocThreadIndex()
+ {
+ size_t threadIndex = threadCounter++;
+ assert(threadIndex < threadLocal.size());
+ return threadIndex;
+ }
+
+ void TaskScheduler::join()
+ {
+ mutex.lock();
+ size_t threadIndex = allocThreadIndex();
+ condition.wait(mutex, [&] () { return hasRootTask.load(); });
+ mutex.unlock();
+ // -- GODOT start --
+ // std::exception_ptr except = thread_loop(threadIndex);
+ // if (except != nullptr) std::rethrow_exception(except);
+ thread_loop(threadIndex);
+ // -- GODOT end --
+ }
+
+ void TaskScheduler::reset() {
+ hasRootTask = false;
+ }
+
+ void TaskScheduler::wait_for_threads(size_t threadCount)
+ {
+ while (threadCounter < threadCount-1)
+ pause_cpu();
+ }
+
+ dll_export TaskScheduler::Thread* TaskScheduler::thread() {
+ return thread_local_thread;
+ }
+
+ dll_export TaskScheduler::Thread* TaskScheduler::swapThread(Thread* thread)
+ {
+ Thread* old = thread_local_thread;
+ thread_local_thread = thread;
+ return old;
+ }
+
+ dll_export bool TaskScheduler::wait()
+ {
+ Thread* thread = TaskScheduler::thread();
+ if (thread == nullptr) return true;
+ while (thread->tasks.execute_local_internal(*thread,thread->task)) {};
+ return thread->scheduler->cancellingException == nullptr;
+ }
+
+// -- GODOT start --
+// std::exception_ptr TaskScheduler::thread_loop(size_t threadIndex)
+ void TaskScheduler::thread_loop(size_t threadIndex)
+// -- GODOT end --
+ {
+ /* allocate thread structure */
+ std::unique_ptr<Thread> mthread(new Thread(threadIndex,this)); // too large for stack allocation
+ Thread& thread = *mthread;
+ threadLocal[threadIndex].store(&thread);
+ Thread* oldThread = swapThread(&thread);
+
+ /* main thread loop */
+ while (anyTasksRunning)
+ {
+ steal_loop(thread,
+ [&] () { return anyTasksRunning > 0; },
+ [&] () {
+ anyTasksRunning++;
+ while (thread.tasks.execute_local_internal(thread,nullptr));
+ anyTasksRunning--;
+ });
+ }
+ threadLocal[threadIndex].store(nullptr);
+ swapThread(oldThread);
+
+ /* remember exception to throw */
+ // -- GODOT start --
+ // std::exception_ptr except = nullptr;
+ // if (cancellingException != nullptr) except = cancellingException;
+ // -- GODOT end --
+ /* wait for all threads to terminate */
+ threadCounter--;
+#if defined(__WIN32__)
+ size_t loopIndex = 1;
+#endif
+#define LOOP_YIELD_THRESHOLD (4096)
+ while (threadCounter > 0) {
+#if defined(__WIN32__)
+ if ((loopIndex % LOOP_YIELD_THRESHOLD) == 0)
+ yield();
+ else
+ _mm_pause();
+ loopIndex++;
+#else
+ yield();
+#endif
+ }
+ // -- GODOT start --
+ // return except;
+ return;
+ // -- GODOT end --
+ }
+
+ bool TaskScheduler::steal_from_other_threads(Thread& thread)
+ {
+ const size_t threadIndex = thread.threadIndex;
+ const size_t threadCount = this->threadCounter;
+
+ for (size_t i=1; i<threadCount; i++)
+ {
+ pause_cpu(32);
+ size_t otherThreadIndex = threadIndex+i;
+ if (otherThreadIndex >= threadCount) otherThreadIndex -= threadCount;
+
+ Thread* othread = threadLocal[otherThreadIndex].load();
+ if (!othread)
+ continue;
+
+ if (othread->tasks.steal(thread))
+ return true;
+ }
+
+ return false;
+ }
+
+ dll_export void TaskScheduler::startThreads() {
+ threadPool->startThreads();
+ }
+
+ dll_export void TaskScheduler::addScheduler(const Ref<TaskScheduler>& scheduler) {
+ threadPool->add(scheduler);
+ }
+
+ dll_export void TaskScheduler::removeScheduler(const Ref<TaskScheduler>& scheduler) {
+ threadPool->remove(scheduler);
+ }
+
+ RTC_NAMESPACE_END
+}
diff --git a/thirdparty/embree/common/tasking/taskschedulerinternal.h b/thirdparty/embree/common/tasking/taskschedulerinternal.h
new file mode 100644
index 0000000000..8fa6bb12fa
--- /dev/null
+++ b/thirdparty/embree/common/tasking/taskschedulerinternal.h
@@ -0,0 +1,385 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+#include "../sys/alloc.h"
+#include "../sys/barrier.h"
+#include "../sys/thread.h"
+#include "../sys/mutex.h"
+#include "../sys/condition.h"
+#include "../sys/ref.h"
+#include "../sys/atomic.h"
+#include "../math/range.h"
+#include "../../include/embree3/rtcore.h"
+
+#include <list>
+
+namespace embree
+{
+
+ /* The tasking system exports some symbols to be used by the tutorials. Thus we
+ hide is also in the API namespace when requested. */
+ RTC_NAMESPACE_BEGIN
+
+ struct TaskScheduler : public RefCount
+ {
+ ALIGNED_STRUCT_(64);
+ friend class Device;
+
+ static const size_t TASK_STACK_SIZE = 4*1024; //!< task structure stack
+ static const size_t CLOSURE_STACK_SIZE = 512*1024; //!< stack for task closures
+
+ struct Thread;
+
+ /*! virtual interface for all tasks */
+ struct TaskFunction {
+ virtual void execute() = 0;
+ };
+
+ /*! builds a task interface from a closure */
+ template<typename Closure>
+ struct ClosureTaskFunction : public TaskFunction
+ {
+ Closure closure;
+ __forceinline ClosureTaskFunction (const Closure& closure) : closure(closure) {}
+ void execute() { closure(); };
+ };
+
+ struct __aligned(64) Task
+ {
+ /*! states a task can be in */
+ enum { DONE, INITIALIZED };
+
+ /*! switch from one state to another */
+ __forceinline void switch_state(int from, int to)
+ {
+ __memory_barrier();
+ MAYBE_UNUSED bool success = state.compare_exchange_strong(from,to);
+ assert(success);
+ }
+
+ /*! try to switch from one state to another */
+ __forceinline bool try_switch_state(int from, int to) {
+ __memory_barrier();
+ return state.compare_exchange_strong(from,to);
+ }
+
+ /*! increment/decrement dependency counter */
+ void add_dependencies(int n) {
+ dependencies+=n;
+ }
+
+ /*! initialize all tasks to DONE state by default */
+ __forceinline Task()
+ : state(DONE) {}
+
+ /*! construction of new task */
+ __forceinline Task (TaskFunction* closure, Task* parent, size_t stackPtr, size_t N)
+ : dependencies(1), stealable(true), closure(closure), parent(parent), stackPtr(stackPtr), N(N)
+ {
+ if (parent) parent->add_dependencies(+1);
+ switch_state(DONE,INITIALIZED);
+ }
+
+ /*! construction of stolen task, stealing thread will decrement initial dependency */
+ __forceinline Task (TaskFunction* closure, Task* parent)
+ : dependencies(1), stealable(false), closure(closure), parent(parent), stackPtr(-1), N(1)
+ {
+ switch_state(DONE,INITIALIZED);
+ }
+
+ /*! try to steal this task */
+ bool try_steal(Task& child)
+ {
+ if (!stealable) return false;
+ if (!try_switch_state(INITIALIZED,DONE)) return false;
+ new (&child) Task(closure, this);
+ return true;
+ }
+
+ /*! run this task */
+ dll_export void run(Thread& thread);
+
+ void run_internal(Thread& thread);
+
+ public:
+ std::atomic<int> state; //!< state this task is in
+ std::atomic<int> dependencies; //!< dependencies to wait for
+ std::atomic<bool> stealable; //!< true if task can be stolen
+ TaskFunction* closure; //!< the closure to execute
+ Task* parent; //!< parent task to signal when we are finished
+ size_t stackPtr; //!< stack location where closure is stored
+ size_t N; //!< approximative size of task
+ };
+
+ struct TaskQueue
+ {
+ TaskQueue ()
+ : left(0), right(0), stackPtr(0) {}
+
+ __forceinline void* alloc(size_t bytes, size_t align = 64)
+ {
+ size_t ofs = bytes + ((align - stackPtr) & (align-1));
+ if (stackPtr + ofs > CLOSURE_STACK_SIZE)
+ // -- GODOT start --
+ // throw std::runtime_error("closure stack overflow");
+ abort();
+ // -- GODOT end --
+ stackPtr += ofs;
+ return &stack[stackPtr-bytes];
+ }
+
+ template<typename Closure>
+ __forceinline void push_right(Thread& thread, const size_t size, const Closure& closure)
+ {
+ if (right >= TASK_STACK_SIZE)
+ // -- GODOT start --
+ // throw std::runtime_error("task stack overflow");
+ abort();
+ // -- GODOT end --
+
+ /* allocate new task on right side of stack */
+ size_t oldStackPtr = stackPtr;
+ TaskFunction* func = new (alloc(sizeof(ClosureTaskFunction<Closure>))) ClosureTaskFunction<Closure>(closure);
+ new (&tasks[right]) Task(func,thread.task,oldStackPtr,size);
+ right++;
+
+ /* also move left pointer */
+ if (left >= right-1) left = right-1;
+ }
+
+ dll_export bool execute_local(Thread& thread, Task* parent);
+ bool execute_local_internal(Thread& thread, Task* parent);
+ bool steal(Thread& thread);
+ size_t getTaskSizeAtLeft();
+
+ bool empty() { return right == 0; }
+
+ public:
+
+ /* task stack */
+ Task tasks[TASK_STACK_SIZE];
+ __aligned(64) std::atomic<size_t> left; //!< threads steal from left
+ __aligned(64) std::atomic<size_t> right; //!< new tasks are added to the right
+
+ /* closure stack */
+ __aligned(64) char stack[CLOSURE_STACK_SIZE];
+ size_t stackPtr;
+ };
+
+ /*! thread local structure for each thread */
+ struct Thread
+ {
+ ALIGNED_STRUCT_(64);
+
+ Thread (size_t threadIndex, const Ref<TaskScheduler>& scheduler)
+ : threadIndex(threadIndex), task(nullptr), scheduler(scheduler) {}
+
+ __forceinline size_t threadCount() {
+ return scheduler->threadCounter;
+ }
+
+ size_t threadIndex; //!< ID of this thread
+ TaskQueue tasks; //!< local task queue
+ Task* task; //!< current active task
+ Ref<TaskScheduler> scheduler; //!< pointer to task scheduler
+ };
+
+ /*! pool of worker threads */
+ struct ThreadPool
+ {
+ ThreadPool (bool set_affinity);
+ ~ThreadPool ();
+
+ /*! starts the threads */
+ dll_export void startThreads();
+
+ /*! sets number of threads to use */
+ void setNumThreads(size_t numThreads, bool startThreads = false);
+
+ /*! adds a task scheduler object for scheduling */
+ dll_export void add(const Ref<TaskScheduler>& scheduler);
+
+ /*! remove the task scheduler object again */
+ dll_export void remove(const Ref<TaskScheduler>& scheduler);
+
+ /*! returns number of threads of the thread pool */
+ size_t size() const { return numThreads; }
+
+ /*! main loop for all threads */
+ void thread_loop(size_t threadIndex);
+
+ private:
+ std::atomic<size_t> numThreads;
+ std::atomic<size_t> numThreadsRunning;
+ bool set_affinity;
+ std::atomic<bool> running;
+ std::vector<thread_t> threads;
+
+ private:
+ MutexSys mutex;
+ ConditionSys condition;
+ std::list<Ref<TaskScheduler> > schedulers;
+ };
+
+ TaskScheduler ();
+ ~TaskScheduler ();
+
+ /*! initializes the task scheduler */
+ static void create(size_t numThreads, bool set_affinity, bool start_threads);
+
+ /*! destroys the task scheduler again */
+ static void destroy();
+
+ /*! lets new worker threads join the tasking system */
+ void join();
+ void reset();
+
+ /*! let a worker thread allocate a thread index */
+ dll_export ssize_t allocThreadIndex();
+
+ /*! wait for some number of threads available (threadCount includes main thread) */
+ void wait_for_threads(size_t threadCount);
+
+ /*! thread loop for all worker threads */
+ // -- GODOT start --
+ // std::exception_ptr thread_loop(size_t threadIndex);
+ void thread_loop(size_t threadIndex);
+ // -- GODOT end --
+
+ /*! steals a task from a different thread */
+ bool steal_from_other_threads(Thread& thread);
+
+ template<typename Predicate, typename Body>
+ static void steal_loop(Thread& thread, const Predicate& pred, const Body& body);
+
+ /* spawn a new task at the top of the threads task stack */
+ template<typename Closure>
+ void spawn_root(const Closure& closure, size_t size = 1, bool useThreadPool = true)
+ {
+ if (useThreadPool) startThreads();
+
+ size_t threadIndex = allocThreadIndex();
+ std::unique_ptr<Thread> mthread(new Thread(threadIndex,this)); // too large for stack allocation
+ Thread& thread = *mthread;
+ assert(threadLocal[threadIndex].load() == nullptr);
+ threadLocal[threadIndex] = &thread;
+ Thread* oldThread = swapThread(&thread);
+ thread.tasks.push_right(thread,size,closure);
+ {
+ Lock<MutexSys> lock(mutex);
+ anyTasksRunning++;
+ hasRootTask = true;
+ condition.notify_all();
+ }
+
+ if (useThreadPool) addScheduler(this);
+
+ while (thread.tasks.execute_local(thread,nullptr));
+ anyTasksRunning--;
+ if (useThreadPool) removeScheduler(this);
+
+ threadLocal[threadIndex] = nullptr;
+ swapThread(oldThread);
+
+ /* remember exception to throw */
+ std::exception_ptr except = nullptr;
+ if (cancellingException != nullptr) except = cancellingException;
+
+ /* wait for all threads to terminate */
+ threadCounter--;
+ while (threadCounter > 0) yield();
+ cancellingException = nullptr;
+
+ /* re-throw proper exception */
+ if (except != nullptr)
+ std::rethrow_exception(except);
+ }
+
+ /* spawn a new task at the top of the threads task stack */
+ template<typename Closure>
+ static __forceinline void spawn(size_t size, const Closure& closure)
+ {
+ Thread* thread = TaskScheduler::thread();
+ if (likely(thread != nullptr)) thread->tasks.push_right(*thread,size,closure);
+ else instance()->spawn_root(closure,size);
+ }
+
+ /* spawn a new task at the top of the threads task stack */
+ template<typename Closure>
+ static __forceinline void spawn(const Closure& closure) {
+ spawn(1,closure);
+ }
+
+ /* spawn a new task set */
+ template<typename Index, typename Closure>
+ static void spawn(const Index begin, const Index end, const Index blockSize, const Closure& closure)
+ {
+ spawn(end-begin, [=]()
+ {
+ if (end-begin <= blockSize) {
+ return closure(range<Index>(begin,end));
+ }
+ const Index center = (begin+end)/2;
+ spawn(begin,center,blockSize,closure);
+ spawn(center,end ,blockSize,closure);
+ wait();
+ });
+ }
+
+ /* work on spawned subtasks and wait until all have finished */
+ dll_export static bool wait();
+
+ /* returns the ID of the current thread */
+ dll_export static size_t threadID();
+
+ /* returns the index (0..threadCount-1) of the current thread */
+ dll_export static size_t threadIndex();
+
+ /* returns the total number of threads */
+ dll_export static size_t threadCount();
+
+ private:
+
+ /* returns the thread local task list of this worker thread */
+ dll_export static Thread* thread();
+
+ /* sets the thread local task list of this worker thread */
+ dll_export static Thread* swapThread(Thread* thread);
+
+ /*! returns the taskscheduler object to be used by the master thread */
+ dll_export static TaskScheduler* instance();
+
+ /*! starts the threads */
+ dll_export static void startThreads();
+
+ /*! adds a task scheduler object for scheduling */
+ dll_export static void addScheduler(const Ref<TaskScheduler>& scheduler);
+
+ /*! remove the task scheduler object again */
+ dll_export static void removeScheduler(const Ref<TaskScheduler>& scheduler);
+
+ private:
+ std::vector<atomic<Thread*>> threadLocal;
+ std::atomic<size_t> threadCounter;
+ std::atomic<size_t> anyTasksRunning;
+ std::atomic<bool> hasRootTask;
+ std::exception_ptr cancellingException;
+ MutexSys mutex;
+ ConditionSys condition;
+
+ private:
+ static size_t g_numThreads;
+ static __thread TaskScheduler* g_instance;
+ static __thread Thread* thread_local_thread;
+ static ThreadPool* threadPool;
+ };
+
+ RTC_NAMESPACE_END
+
+#if defined(RTC_NAMESPACE)
+ using RTC_NAMESPACE::TaskScheduler;
+#endif
+}
diff --git a/thirdparty/embree/common/tasking/taskschedulerppl.h b/thirdparty/embree/common/tasking/taskschedulerppl.h
new file mode 100644
index 0000000000..cbc2ecdbb8
--- /dev/null
+++ b/thirdparty/embree/common/tasking/taskschedulerppl.h
@@ -0,0 +1,46 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+#include "../sys/alloc.h"
+#include "../sys/barrier.h"
+#include "../sys/thread.h"
+#include "../sys/mutex.h"
+#include "../sys/condition.h"
+#include "../sys/ref.h"
+
+#if !defined(__WIN32__)
+#error PPL tasking system only available under windows
+#endif
+
+#include <ppl.h>
+
+namespace embree
+{
+ struct TaskScheduler
+ {
+ /*! initializes the task scheduler */
+ static void create(size_t numThreads, bool set_affinity, bool start_threads);
+
+ /*! destroys the task scheduler again */
+ static void destroy();
+
+ /* returns the ID of the current thread */
+ static __forceinline size_t threadID() {
+ return GetCurrentThreadId();
+ }
+
+ /* returns the index (0..threadCount-1) of the current thread */
+ /* FIXME: threadIndex is NOT supported by PPL! */
+ static __forceinline size_t threadIndex() {
+ return 0;
+ }
+
+ /* returns the total number of threads */
+ static __forceinline size_t threadCount() {
+ return GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS) + 1;
+ }
+ };
+};
diff --git a/thirdparty/embree/common/tasking/taskschedulertbb.h b/thirdparty/embree/common/tasking/taskschedulertbb.h
new file mode 100644
index 0000000000..35bd49849f
--- /dev/null
+++ b/thirdparty/embree/common/tasking/taskschedulertbb.h
@@ -0,0 +1,73 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../sys/platform.h"
+#include "../sys/alloc.h"
+#include "../sys/barrier.h"
+#include "../sys/thread.h"
+#include "../sys/mutex.h"
+#include "../sys/condition.h"
+#include "../sys/ref.h"
+
+#if defined(__WIN32__)
+// -- GODOT start --
+#if !defined(NOMINMAX)
+// -- GODOT end --
+# define NOMINMAX
+// -- GODOT start --
+#endif
+// -- GODOT end --
+#endif
+
+// We need to define these to avoid implicit linkage against
+// tbb_debug.lib under Windows. When removing these lines debug build
+// under Windows fails.
+#define __TBB_NO_IMPLICIT_LINKAGE 1
+#define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1
+#define TBB_SUPPRESS_DEPRECATED_MESSAGES 1
+#define TBB_PREVIEW_ISOLATED_TASK_GROUP 1
+#include "tbb/tbb.h"
+#include "tbb/parallel_sort.h"
+
+namespace embree
+{
+ struct TaskScheduler
+ {
+ /*! initializes the task scheduler */
+ static void create(size_t numThreads, bool set_affinity, bool start_threads);
+
+ /*! destroys the task scheduler again */
+ static void destroy();
+
+ /* returns the ID of the current thread */
+ static __forceinline size_t threadID()
+ {
+ return threadIndex();
+ }
+
+ /* returns the index (0..threadCount-1) of the current thread */
+ static __forceinline size_t threadIndex()
+ {
+#if TBB_INTERFACE_VERSION >= 9100
+ return tbb::this_task_arena::current_thread_index();
+#elif TBB_INTERFACE_VERSION >= 9000
+ return tbb::task_arena::current_thread_index();
+#else
+ return 0;
+#endif
+ }
+
+ /* returns the total number of threads */
+ static __forceinline size_t threadCount() {
+#if TBB_INTERFACE_VERSION >= 9100
+ return tbb::this_task_arena::max_concurrency();
+#else
+ return tbb::task_scheduler_init::default_num_threads();
+#endif
+ }
+
+ };
+
+};
diff --git a/thirdparty/embree/include/embree3/rtcore.h b/thirdparty/embree/include/embree3/rtcore.h
new file mode 100644
index 0000000000..450ab4c535
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore.h
@@ -0,0 +1,14 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore_config.h"
+#include "rtcore_common.h"
+#include "rtcore_device.h"
+#include "rtcore_buffer.h"
+#include "rtcore_ray.h"
+#include "rtcore_geometry.h"
+#include "rtcore_scene.h"
+#include "rtcore_builder.h"
+#include "rtcore_quaternion.h"
diff --git a/thirdparty/embree/include/embree3/rtcore_buffer.h b/thirdparty/embree/include/embree3/rtcore_buffer.h
new file mode 100644
index 0000000000..6b8eba9769
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_buffer.h
@@ -0,0 +1,51 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore_device.h"
+
+RTC_NAMESPACE_BEGIN
+
+/* Types of buffers */
+enum RTCBufferType
+{
+ RTC_BUFFER_TYPE_INDEX = 0,
+ RTC_BUFFER_TYPE_VERTEX = 1,
+ RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE = 2,
+ RTC_BUFFER_TYPE_NORMAL = 3,
+ RTC_BUFFER_TYPE_TANGENT = 4,
+ RTC_BUFFER_TYPE_NORMAL_DERIVATIVE = 5,
+
+ RTC_BUFFER_TYPE_GRID = 8,
+
+ RTC_BUFFER_TYPE_FACE = 16,
+ RTC_BUFFER_TYPE_LEVEL = 17,
+ RTC_BUFFER_TYPE_EDGE_CREASE_INDEX = 18,
+ RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT = 19,
+ RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX = 20,
+ RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT = 21,
+ RTC_BUFFER_TYPE_HOLE = 22,
+
+ RTC_BUFFER_TYPE_FLAGS = 32
+};
+
+/* Opaque buffer type */
+typedef struct RTCBufferTy* RTCBuffer;
+
+/* Creates a new buffer. */
+RTC_API RTCBuffer rtcNewBuffer(RTCDevice device, size_t byteSize);
+
+/* Creates a new shared buffer. */
+RTC_API RTCBuffer rtcNewSharedBuffer(RTCDevice device, void* ptr, size_t byteSize);
+
+/* Returns a pointer to the buffer data. */
+RTC_API void* rtcGetBufferData(RTCBuffer buffer);
+
+/* Retains the buffer (increments the reference count). */
+RTC_API void rtcRetainBuffer(RTCBuffer buffer);
+
+/* Releases the buffer (decrements the reference count). */
+RTC_API void rtcReleaseBuffer(RTCBuffer buffer);
+
+RTC_NAMESPACE_END
diff --git a/thirdparty/embree/include/embree3/rtcore_builder.h b/thirdparty/embree/include/embree3/rtcore_builder.h
new file mode 100644
index 0000000000..4bff999fed
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_builder.h
@@ -0,0 +1,125 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore_scene.h"
+
+RTC_NAMESPACE_BEGIN
+
+/* Opaque BVH type */
+typedef struct RTCBVHTy* RTCBVH;
+
+/* Input build primitives for the builder */
+struct RTC_ALIGN(32) RTCBuildPrimitive
+{
+ float lower_x, lower_y, lower_z;
+ unsigned int geomID;
+ float upper_x, upper_y, upper_z;
+ unsigned int primID;
+};
+
+/* Opaque thread local allocator type */
+typedef struct RTCThreadLocalAllocatorTy* RTCThreadLocalAllocator;
+
+/* Callback to create a node */
+typedef void* (*RTCCreateNodeFunction) (RTCThreadLocalAllocator allocator, unsigned int childCount, void* userPtr);
+
+/* Callback to set the pointer to all children */
+typedef void (*RTCSetNodeChildrenFunction) (void* nodePtr, void** children, unsigned int childCount, void* userPtr);
+
+/* Callback to set the bounds of all children */
+typedef void (*RTCSetNodeBoundsFunction) (void* nodePtr, const struct RTCBounds** bounds, unsigned int childCount, void* userPtr);
+
+/* Callback to create a leaf node */
+typedef void* (*RTCCreateLeafFunction) (RTCThreadLocalAllocator allocator, const struct RTCBuildPrimitive* primitives, size_t primitiveCount, void* userPtr);
+
+/* Callback to split a build primitive */
+typedef void (*RTCSplitPrimitiveFunction) (const struct RTCBuildPrimitive* primitive, unsigned int dimension, float position, struct RTCBounds* leftBounds, struct RTCBounds* rightBounds, void* userPtr);
+
+/* Build flags */
+enum RTCBuildFlags
+{
+ RTC_BUILD_FLAG_NONE = 0,
+ RTC_BUILD_FLAG_DYNAMIC = (1 << 0),
+};
+
+enum RTCBuildConstants
+{
+ RTC_BUILD_MAX_PRIMITIVES_PER_LEAF = 32
+};
+
+/* Input for builders */
+struct RTCBuildArguments
+{
+ size_t byteSize;
+
+ enum RTCBuildQuality buildQuality;
+ enum RTCBuildFlags buildFlags;
+ unsigned int maxBranchingFactor;
+ unsigned int maxDepth;
+ unsigned int sahBlockSize;
+ unsigned int minLeafSize;
+ unsigned int maxLeafSize;
+ float traversalCost;
+ float intersectionCost;
+
+ RTCBVH bvh;
+ struct RTCBuildPrimitive* primitives;
+ size_t primitiveCount;
+ size_t primitiveArrayCapacity;
+
+ RTCCreateNodeFunction createNode;
+ RTCSetNodeChildrenFunction setNodeChildren;
+ RTCSetNodeBoundsFunction setNodeBounds;
+ RTCCreateLeafFunction createLeaf;
+ RTCSplitPrimitiveFunction splitPrimitive;
+ RTCProgressMonitorFunction buildProgress;
+ void* userPtr;
+};
+
+/* Returns the default build settings. */
+RTC_FORCEINLINE struct RTCBuildArguments rtcDefaultBuildArguments()
+{
+ struct RTCBuildArguments args;
+ args.byteSize = sizeof(args);
+ args.buildQuality = RTC_BUILD_QUALITY_MEDIUM;
+ args.buildFlags = RTC_BUILD_FLAG_NONE;
+ args.maxBranchingFactor = 2;
+ args.maxDepth = 32;
+ args.sahBlockSize = 1;
+ args.minLeafSize = 1;
+ args.maxLeafSize = RTC_BUILD_MAX_PRIMITIVES_PER_LEAF;
+ args.traversalCost = 1.0f;
+ args.intersectionCost = 1.0f;
+ args.bvh = NULL;
+ args.primitives = NULL;
+ args.primitiveCount = 0;
+ args.primitiveArrayCapacity = 0;
+ args.createNode = NULL;
+ args.setNodeChildren = NULL;
+ args.setNodeBounds = NULL;
+ args.createLeaf = NULL;
+ args.splitPrimitive = NULL;
+ args.buildProgress = NULL;
+ args.userPtr = NULL;
+ return args;
+}
+
+/* Creates a new BVH. */
+RTC_API RTCBVH rtcNewBVH(RTCDevice device);
+
+/* Builds a BVH. */
+RTC_API void* rtcBuildBVH(const struct RTCBuildArguments* args);
+
+/* Allocates memory using the thread local allocator. */
+RTC_API void* rtcThreadLocalAlloc(RTCThreadLocalAllocator allocator, size_t bytes, size_t align);
+
+/* Retains the BVH (increments reference count). */
+RTC_API void rtcRetainBVH(RTCBVH bvh);
+
+/* Releases the BVH (decrements reference count). */
+RTC_API void rtcReleaseBVH(RTCBVH bvh);
+
+RTC_NAMESPACE_END
+
diff --git a/thirdparty/embree/include/embree3/rtcore_common.h b/thirdparty/embree/include/embree3/rtcore_common.h
new file mode 100644
index 0000000000..4857e1e05e
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_common.h
@@ -0,0 +1,328 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+#include "rtcore_config.h"
+
+RTC_NAMESPACE_BEGIN
+
+#if defined(_WIN32)
+#if defined(_M_X64)
+typedef long long ssize_t;
+#else
+typedef int ssize_t;
+#endif
+#endif
+
+// -- GODOT start --
+#if defined(_WIN32) && defined(_MSC_VER)
+// -- GODOT end --
+# define RTC_ALIGN(...) __declspec(align(__VA_ARGS__))
+#else
+# define RTC_ALIGN(...) __attribute__((aligned(__VA_ARGS__)))
+#endif
+
+#if !defined (RTC_DEPRECATED)
+#ifdef __GNUC__
+ #define RTC_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+ #define RTC_DEPRECATED __declspec(deprecated)
+#else
+ #define RTC_DEPRECATED
+#endif
+#endif
+
+#if defined(_WIN32)
+# define RTC_FORCEINLINE __forceinline
+#else
+# define RTC_FORCEINLINE inline __attribute__((always_inline))
+#endif
+
+/* Invalid geometry ID */
+#define RTC_INVALID_GEOMETRY_ID ((unsigned int)-1)
+
+/* Maximum number of time steps */
+#define RTC_MAX_TIME_STEP_COUNT 129
+
+/* Formats of buffers and other data structures */
+enum RTCFormat
+{
+ RTC_FORMAT_UNDEFINED = 0,
+
+ /* 8-bit unsigned integer */
+ RTC_FORMAT_UCHAR = 0x1001,
+ RTC_FORMAT_UCHAR2,
+ RTC_FORMAT_UCHAR3,
+ RTC_FORMAT_UCHAR4,
+
+ /* 8-bit signed integer */
+ RTC_FORMAT_CHAR = 0x2001,
+ RTC_FORMAT_CHAR2,
+ RTC_FORMAT_CHAR3,
+ RTC_FORMAT_CHAR4,
+
+ /* 16-bit unsigned integer */
+ RTC_FORMAT_USHORT = 0x3001,
+ RTC_FORMAT_USHORT2,
+ RTC_FORMAT_USHORT3,
+ RTC_FORMAT_USHORT4,
+
+ /* 16-bit signed integer */
+ RTC_FORMAT_SHORT = 0x4001,
+ RTC_FORMAT_SHORT2,
+ RTC_FORMAT_SHORT3,
+ RTC_FORMAT_SHORT4,
+
+ /* 32-bit unsigned integer */
+ RTC_FORMAT_UINT = 0x5001,
+ RTC_FORMAT_UINT2,
+ RTC_FORMAT_UINT3,
+ RTC_FORMAT_UINT4,
+
+ /* 32-bit signed integer */
+ RTC_FORMAT_INT = 0x6001,
+ RTC_FORMAT_INT2,
+ RTC_FORMAT_INT3,
+ RTC_FORMAT_INT4,
+
+ /* 64-bit unsigned integer */
+ RTC_FORMAT_ULLONG = 0x7001,
+ RTC_FORMAT_ULLONG2,
+ RTC_FORMAT_ULLONG3,
+ RTC_FORMAT_ULLONG4,
+
+ /* 64-bit signed integer */
+ RTC_FORMAT_LLONG = 0x8001,
+ RTC_FORMAT_LLONG2,
+ RTC_FORMAT_LLONG3,
+ RTC_FORMAT_LLONG4,
+
+ /* 32-bit float */
+ RTC_FORMAT_FLOAT = 0x9001,
+ RTC_FORMAT_FLOAT2,
+ RTC_FORMAT_FLOAT3,
+ RTC_FORMAT_FLOAT4,
+ RTC_FORMAT_FLOAT5,
+ RTC_FORMAT_FLOAT6,
+ RTC_FORMAT_FLOAT7,
+ RTC_FORMAT_FLOAT8,
+ RTC_FORMAT_FLOAT9,
+ RTC_FORMAT_FLOAT10,
+ RTC_FORMAT_FLOAT11,
+ RTC_FORMAT_FLOAT12,
+ RTC_FORMAT_FLOAT13,
+ RTC_FORMAT_FLOAT14,
+ RTC_FORMAT_FLOAT15,
+ RTC_FORMAT_FLOAT16,
+
+ /* 32-bit float matrix (row-major order) */
+ RTC_FORMAT_FLOAT2X2_ROW_MAJOR = 0x9122,
+ RTC_FORMAT_FLOAT2X3_ROW_MAJOR = 0x9123,
+ RTC_FORMAT_FLOAT2X4_ROW_MAJOR = 0x9124,
+ RTC_FORMAT_FLOAT3X2_ROW_MAJOR = 0x9132,
+ RTC_FORMAT_FLOAT3X3_ROW_MAJOR = 0x9133,
+ RTC_FORMAT_FLOAT3X4_ROW_MAJOR = 0x9134,
+ RTC_FORMAT_FLOAT4X2_ROW_MAJOR = 0x9142,
+ RTC_FORMAT_FLOAT4X3_ROW_MAJOR = 0x9143,
+ RTC_FORMAT_FLOAT4X4_ROW_MAJOR = 0x9144,
+
+ /* 32-bit float matrix (column-major order) */
+ RTC_FORMAT_FLOAT2X2_COLUMN_MAJOR = 0x9222,
+ RTC_FORMAT_FLOAT2X3_COLUMN_MAJOR = 0x9223,
+ RTC_FORMAT_FLOAT2X4_COLUMN_MAJOR = 0x9224,
+ RTC_FORMAT_FLOAT3X2_COLUMN_MAJOR = 0x9232,
+ RTC_FORMAT_FLOAT3X3_COLUMN_MAJOR = 0x9233,
+ RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR = 0x9234,
+ RTC_FORMAT_FLOAT4X2_COLUMN_MAJOR = 0x9242,
+ RTC_FORMAT_FLOAT4X3_COLUMN_MAJOR = 0x9243,
+ RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR = 0x9244,
+
+ /* special 12-byte format for grids */
+ RTC_FORMAT_GRID = 0xA001
+};
+
+/* Build quality levels */
+enum RTCBuildQuality
+{
+ RTC_BUILD_QUALITY_LOW = 0,
+ RTC_BUILD_QUALITY_MEDIUM = 1,
+ RTC_BUILD_QUALITY_HIGH = 2,
+ RTC_BUILD_QUALITY_REFIT = 3,
+};
+
+/* Axis-aligned bounding box representation */
+struct RTC_ALIGN(16) RTCBounds
+{
+ float lower_x, lower_y, lower_z, align0;
+ float upper_x, upper_y, upper_z, align1;
+};
+
+/* Linear axis-aligned bounding box representation */
+struct RTC_ALIGN(16) RTCLinearBounds
+{
+ struct RTCBounds bounds0;
+ struct RTCBounds bounds1;
+};
+
+/* Intersection context flags */
+enum RTCIntersectContextFlags
+{
+ RTC_INTERSECT_CONTEXT_FLAG_NONE = 0,
+ RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT = (0 << 0), // optimize for incoherent rays
+ RTC_INTERSECT_CONTEXT_FLAG_COHERENT = (1 << 0) // optimize for coherent rays
+};
+
+/* Arguments for RTCFilterFunctionN */
+struct RTCFilterFunctionNArguments
+{
+ int* valid;
+ void* geometryUserPtr;
+ struct RTCIntersectContext* context;
+ struct RTCRayN* ray;
+ struct RTCHitN* hit;
+ unsigned int N;
+};
+
+/* Filter callback function */
+typedef void (*RTCFilterFunctionN)(const struct RTCFilterFunctionNArguments* args);
+
+/* Intersection context passed to intersect/occluded calls */
+struct RTCIntersectContext
+{
+ enum RTCIntersectContextFlags flags; // intersection flags
+ RTCFilterFunctionN filter; // filter function to execute
+
+#if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
+ unsigned int instStackSize; // Number of instances currently on the stack.
+#endif
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // The current stack of instance ids.
+
+#if RTC_MIN_WIDTH
+ float minWidthDistanceFactor; // curve radius is set to this factor times distance to ray origin
+#endif
+};
+
+/* Initializes an intersection context. */
+RTC_FORCEINLINE void rtcInitIntersectContext(struct RTCIntersectContext* context)
+{
+ unsigned l = 0;
+ context->flags = RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT;
+ context->filter = NULL;
+
+#if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
+ context->instStackSize = 0;
+#endif
+ for (; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
+ context->instID[l] = RTC_INVALID_GEOMETRY_ID;
+
+#if RTC_MIN_WIDTH
+ context->minWidthDistanceFactor = 0.0f;
+#endif
+}
+
+/* Point query structure for closest point query */
+struct RTC_ALIGN(16) RTCPointQuery
+{
+ float x; // x coordinate of the query point
+ float y; // y coordinate of the query point
+ float z; // z coordinate of the query point
+ float time; // time of the point query
+ float radius; // radius of the point query
+};
+
+/* Structure of a packet of 4 query points */
+struct RTC_ALIGN(16) RTCPointQuery4
+{
+ float x[4]; // x coordinate of the query point
+ float y[4]; // y coordinate of the query point
+ float z[4]; // z coordinate of the query point
+ float time[4]; // time of the point query
+ float radius[4]; // radius of the point query
+};
+
+/* Structure of a packet of 8 query points */
+struct RTC_ALIGN(32) RTCPointQuery8
+{
+ float x[8]; // x coordinate of the query point
+ float y[8]; // y coordinate of the query point
+ float z[8]; // z coordinate of the query point
+ float time[8]; // time of the point query
+ float radius[8]; // radius ofr the point query
+};
+
+/* Structure of a packet of 16 query points */
+struct RTC_ALIGN(64) RTCPointQuery16
+{
+ float x[16]; // x coordinate of the query point
+ float y[16]; // y coordinate of the query point
+ float z[16]; // z coordinate of the query point
+ float time[16]; // time of the point quey
+ float radius[16]; // radius of the point query
+};
+
+struct RTCPointQueryN;
+
+struct RTC_ALIGN(16) RTCPointQueryContext
+{
+ // accumulated 4x4 column major matrices from world space to instance space.
+ // undefined if size == 0.
+ float world2inst[RTC_MAX_INSTANCE_LEVEL_COUNT][16];
+
+ // accumulated 4x4 column major matrices from instance space to world space.
+ // undefined if size == 0.
+ float inst2world[RTC_MAX_INSTANCE_LEVEL_COUNT][16];
+
+ // instance ids.
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT];
+
+ // number of instances currently on the stack.
+ unsigned int instStackSize;
+};
+
+/* Initializes an intersection context. */
+RTC_FORCEINLINE void rtcInitPointQueryContext(struct RTCPointQueryContext* context)
+{
+ context->instStackSize = 0;
+ context->instID[0] = RTC_INVALID_GEOMETRY_ID;
+}
+
+struct RTC_ALIGN(16) RTCPointQueryFunctionArguments
+{
+ // The (world space) query object that was passed as an argument of rtcPointQuery. The
+ // radius of the query can be decreased inside the callback to shrink the
+ // search domain. Increasing the radius or modifying the time or position of
+ // the query results in undefined behaviour.
+ struct RTCPointQuery* query;
+
+ // Used for user input/output data. Will not be read or modified internally.
+ void* userPtr;
+
+ // primitive and geometry ID of primitive
+ unsigned int primID;
+ unsigned int geomID;
+
+ // the context with transformation and instance ID stack
+ struct RTCPointQueryContext* context;
+
+ // If the current instance transform M (= context->world2inst[context->instStackSize])
+ // is a similarity matrix, i.e there is a constant factor similarityScale such that,
+ // for all x,y: dist(Mx, My) = similarityScale * dist(x, y),
+ // The similarity scale is 0, if the current instance transform is not a
+ // similarity transform and vice versa. The similarity scale allows to compute
+ // distance information in instance space and scale the distances into world
+ // space by dividing with the similarity scale, for example, to update the
+ // query radius. If the current instance transform is not a similarity
+ // transform (similarityScale = 0), the distance computation has to be
+ // performed in world space to ensure correctness. if there is no instance
+ // transform (context->instStackSize == 0), the similarity scale is 1.
+ float similarityScale;
+};
+
+typedef bool (*RTCPointQueryFunction)(struct RTCPointQueryFunctionArguments* args);
+
+RTC_NAMESPACE_END
diff --git a/thirdparty/embree/include/embree3/rtcore_config.h b/thirdparty/embree/include/embree3/rtcore_config.h
new file mode 100644
index 0000000000..3a9819c9f1
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_config.h
@@ -0,0 +1,57 @@
+
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define RTC_VERSION_MAJOR 3
+#define RTC_VERSION_MINOR 13
+#define RTC_VERSION_PATCH 0
+#define RTC_VERSION 31300
+#define RTC_VERSION_STRING "3.13.0"
+
+#define RTC_MAX_INSTANCE_LEVEL_COUNT 1
+
+#define EMBREE_MIN_WIDTH 0
+#define RTC_MIN_WIDTH EMBREE_MIN_WIDTH
+
+#define EMBREE_STATIC_LIB
+/* #undef EMBREE_API_NAMESPACE */
+
+#if defined(EMBREE_API_NAMESPACE)
+# define RTC_NAMESPACE
+# define RTC_NAMESPACE_BEGIN namespace {
+# define RTC_NAMESPACE_END }
+# define RTC_NAMESPACE_USE using namespace ;
+# define RTC_API_EXTERN_C
+# undef EMBREE_API_NAMESPACE
+#else
+# define RTC_NAMESPACE_BEGIN
+# define RTC_NAMESPACE_END
+# define RTC_NAMESPACE_USE
+# if defined(__cplusplus)
+# define RTC_API_EXTERN_C extern "C"
+# else
+# define RTC_API_EXTERN_C
+# endif
+#endif
+
+#if defined(ISPC)
+# define RTC_API_IMPORT extern "C" unmasked
+# define RTC_API_EXPORT extern "C" unmasked
+#elif defined(EMBREE_STATIC_LIB)
+# define RTC_API_IMPORT RTC_API_EXTERN_C
+# define RTC_API_EXPORT RTC_API_EXTERN_C
+#elif defined(_WIN32)
+# define RTC_API_IMPORT RTC_API_EXTERN_C __declspec(dllimport)
+# define RTC_API_EXPORT RTC_API_EXTERN_C __declspec(dllexport)
+#else
+# define RTC_API_IMPORT RTC_API_EXTERN_C
+# define RTC_API_EXPORT RTC_API_EXTERN_C __attribute__ ((visibility ("default")))
+#endif
+
+#if defined(RTC_EXPORT_API)
+# define RTC_API RTC_API_EXPORT
+#else
+# define RTC_API RTC_API_IMPORT
+#endif
diff --git a/thirdparty/embree/include/embree3/rtcore_device.h b/thirdparty/embree/include/embree3/rtcore_device.h
new file mode 100644
index 0000000000..2dd3047603
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_device.h
@@ -0,0 +1,87 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore_common.h"
+
+RTC_NAMESPACE_BEGIN
+
+/* Opaque device type */
+typedef struct RTCDeviceTy* RTCDevice;
+
+/* Creates a new Embree device. */
+RTC_API RTCDevice rtcNewDevice(const char* config);
+
+/* Retains the Embree device (increments the reference count). */
+RTC_API void rtcRetainDevice(RTCDevice device);
+
+/* Releases an Embree device (decrements the reference count). */
+RTC_API void rtcReleaseDevice(RTCDevice device);
+
+/* Device properties */
+enum RTCDeviceProperty
+{
+ RTC_DEVICE_PROPERTY_VERSION = 0,
+ RTC_DEVICE_PROPERTY_VERSION_MAJOR = 1,
+ RTC_DEVICE_PROPERTY_VERSION_MINOR = 2,
+ RTC_DEVICE_PROPERTY_VERSION_PATCH = 3,
+
+ RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED = 32,
+ RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED = 33,
+ RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED = 34,
+ RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED = 35,
+
+ RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED = 63,
+ RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED = 64,
+ RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED = 65,
+ RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED = 66,
+ RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED = 67,
+ RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED = 68,
+
+ RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED = 96,
+ RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED = 97,
+ RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED = 98,
+ RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED = 99,
+ RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED = 100,
+ RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED = 101,
+
+ RTC_DEVICE_PROPERTY_TASKING_SYSTEM = 128,
+ RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED = 129,
+ RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED = 130
+};
+
+/* Gets a device property. */
+RTC_API ssize_t rtcGetDeviceProperty(RTCDevice device, enum RTCDeviceProperty prop);
+
+/* Sets a device property. */
+RTC_API void rtcSetDeviceProperty(RTCDevice device, const enum RTCDeviceProperty prop, ssize_t value);
+
+/* Error codes */
+enum RTCError
+{
+ RTC_ERROR_NONE = 0,
+ RTC_ERROR_UNKNOWN = 1,
+ RTC_ERROR_INVALID_ARGUMENT = 2,
+ RTC_ERROR_INVALID_OPERATION = 3,
+ RTC_ERROR_OUT_OF_MEMORY = 4,
+ RTC_ERROR_UNSUPPORTED_CPU = 5,
+ RTC_ERROR_CANCELLED = 6
+};
+
+/* Returns the error code. */
+RTC_API enum RTCError rtcGetDeviceError(RTCDevice device);
+
+/* Error callback function */
+typedef void (*RTCErrorFunction)(void* userPtr, enum RTCError code, const char* str);
+
+/* Sets the error callback function. */
+RTC_API void rtcSetDeviceErrorFunction(RTCDevice device, RTCErrorFunction error, void* userPtr);
+
+/* Memory monitor callback function */
+typedef bool (*RTCMemoryMonitorFunction)(void* ptr, ssize_t bytes, bool post);
+
+/* Sets the memory monitor callback function. */
+RTC_API void rtcSetDeviceMemoryMonitorFunction(RTCDevice device, RTCMemoryMonitorFunction memoryMonitor, void* userPtr);
+
+RTC_NAMESPACE_END
diff --git a/thirdparty/embree/include/embree3/rtcore_geometry.h b/thirdparty/embree/include/embree3/rtcore_geometry.h
new file mode 100644
index 0000000000..d1de17491c
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_geometry.h
@@ -0,0 +1,383 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore_buffer.h"
+#include "rtcore_quaternion.h"
+
+RTC_NAMESPACE_BEGIN
+
+/* Opaque scene type */
+typedef struct RTCSceneTy* RTCScene;
+
+/* Opaque geometry type */
+typedef struct RTCGeometryTy* RTCGeometry;
+
+/* Types of geometries */
+enum RTCGeometryType
+{
+ RTC_GEOMETRY_TYPE_TRIANGLE = 0, // triangle mesh
+ RTC_GEOMETRY_TYPE_QUAD = 1, // quad (triangle pair) mesh
+ RTC_GEOMETRY_TYPE_GRID = 2, // grid mesh
+
+ RTC_GEOMETRY_TYPE_SUBDIVISION = 8, // Catmull-Clark subdivision surface
+
+ RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE = 15, // Cone linear curves - discontinuous at edge boundaries
+ RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE = 16, // Round (rounded cone like) linear curves
+ RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE = 17, // flat (ribbon-like) linear curves
+
+ RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE = 24, // round (tube-like) Bezier curves
+ RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE = 25, // flat (ribbon-like) Bezier curves
+ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE = 26, // flat normal-oriented Bezier curves
+
+ RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE = 32, // round (tube-like) B-spline curves
+ RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE = 33, // flat (ribbon-like) B-spline curves
+ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE = 34, // flat normal-oriented B-spline curves
+
+ RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE = 40, // round (tube-like) Hermite curves
+ RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE = 41, // flat (ribbon-like) Hermite curves
+ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE = 42, // flat normal-oriented Hermite curves
+
+ RTC_GEOMETRY_TYPE_SPHERE_POINT = 50,
+ RTC_GEOMETRY_TYPE_DISC_POINT = 51,
+ RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT = 52,
+
+ RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE = 58, // round (tube-like) Catmull-Rom curves
+ RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE = 59, // flat (ribbon-like) Catmull-Rom curves
+ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE = 60, // flat normal-oriented Catmull-Rom curves
+
+ RTC_GEOMETRY_TYPE_USER = 120, // user-defined geometry
+ RTC_GEOMETRY_TYPE_INSTANCE = 121 // scene instance
+};
+
+/* Interpolation modes for subdivision surfaces */
+enum RTCSubdivisionMode
+{
+ RTC_SUBDIVISION_MODE_NO_BOUNDARY = 0,
+ RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY = 1,
+ RTC_SUBDIVISION_MODE_PIN_CORNERS = 2,
+ RTC_SUBDIVISION_MODE_PIN_BOUNDARY = 3,
+ RTC_SUBDIVISION_MODE_PIN_ALL = 4,
+};
+
+/* Curve segment flags */
+enum RTCCurveFlags
+{
+ RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0), // left segments exists
+ RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1) // right segment exists
+};
+
+/* Arguments for RTCBoundsFunction */
+struct RTCBoundsFunctionArguments
+{
+ void* geometryUserPtr;
+ unsigned int primID;
+ unsigned int timeStep;
+ struct RTCBounds* bounds_o;
+};
+
+/* Bounding callback function */
+typedef void (*RTCBoundsFunction)(const struct RTCBoundsFunctionArguments* args);
+
+/* Arguments for RTCIntersectFunctionN */
+struct RTCIntersectFunctionNArguments
+{
+ int* valid;
+ void* geometryUserPtr;
+ unsigned int primID;
+ struct RTCIntersectContext* context;
+ struct RTCRayHitN* rayhit;
+ unsigned int N;
+ unsigned int geomID;
+};
+
+/* Intersection callback function */
+typedef void (*RTCIntersectFunctionN)(const struct RTCIntersectFunctionNArguments* args);
+
+/* Arguments for RTCOccludedFunctionN */
+struct RTCOccludedFunctionNArguments
+{
+ int* valid;
+ void* geometryUserPtr;
+ unsigned int primID;
+ struct RTCIntersectContext* context;
+ struct RTCRayN* ray;
+ unsigned int N;
+ unsigned int geomID;
+};
+
+/* Occlusion callback function */
+typedef void (*RTCOccludedFunctionN)(const struct RTCOccludedFunctionNArguments* args);
+
+/* Arguments for RTCDisplacementFunctionN */
+struct RTCDisplacementFunctionNArguments
+{
+ void* geometryUserPtr;
+ RTCGeometry geometry;
+ unsigned int primID;
+ unsigned int timeStep;
+ const float* u;
+ const float* v;
+ const float* Ng_x;
+ const float* Ng_y;
+ const float* Ng_z;
+ float* P_x;
+ float* P_y;
+ float* P_z;
+ unsigned int N;
+};
+
+/* Displacement mapping callback function */
+typedef void (*RTCDisplacementFunctionN)(const struct RTCDisplacementFunctionNArguments* args);
+
+/* Creates a new geometry of specified type. */
+RTC_API RTCGeometry rtcNewGeometry(RTCDevice device, enum RTCGeometryType type);
+
+/* Retains the geometry (increments the reference count). */
+RTC_API void rtcRetainGeometry(RTCGeometry geometry);
+
+/* Releases the geometry (decrements the reference count) */
+RTC_API void rtcReleaseGeometry(RTCGeometry geometry);
+
+/* Commits the geometry. */
+RTC_API void rtcCommitGeometry(RTCGeometry geometry);
+
+
+/* Enables the geometry. */
+RTC_API void rtcEnableGeometry(RTCGeometry geometry);
+
+/* Disables the geometry. */
+RTC_API void rtcDisableGeometry(RTCGeometry geometry);
+
+
+/* Sets the number of motion blur time steps of the geometry. */
+RTC_API void rtcSetGeometryTimeStepCount(RTCGeometry geometry, unsigned int timeStepCount);
+
+/* Sets the motion blur time range of the geometry. */
+RTC_API void rtcSetGeometryTimeRange(RTCGeometry geometry, float startTime, float endTime);
+
+/* Sets the number of vertex attributes of the geometry. */
+RTC_API void rtcSetGeometryVertexAttributeCount(RTCGeometry geometry, unsigned int vertexAttributeCount);
+
+/* Sets the ray mask of the geometry. */
+RTC_API void rtcSetGeometryMask(RTCGeometry geometry, unsigned int mask);
+
+/* Sets the build quality of the geometry. */
+RTC_API void rtcSetGeometryBuildQuality(RTCGeometry geometry, enum RTCBuildQuality quality);
+
+/* Sets the maximal curve or point radius scale allowed by min-width feature. */
+RTC_API void rtcSetGeometryMaxRadiusScale(RTCGeometry geometry, float maxRadiusScale);
+
+
+/* Sets a geometry buffer. */
+RTC_API void rtcSetGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot, enum RTCFormat format, RTCBuffer buffer, size_t byteOffset, size_t byteStride, size_t itemCount);
+
+/* Sets a shared geometry buffer. */
+RTC_API void rtcSetSharedGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot, enum RTCFormat format, const void* ptr, size_t byteOffset, size_t byteStride, size_t itemCount);
+
+/* Creates and sets a new geometry buffer. */
+RTC_API void* rtcSetNewGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot, enum RTCFormat format, size_t byteStride, size_t itemCount);
+
+/* Returns the pointer to the data of a buffer. */
+RTC_API void* rtcGetGeometryBufferData(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot);
+
+/* Updates a geometry buffer. */
+RTC_API void rtcUpdateGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot);
+
+
+/* Sets the intersection filter callback function of the geometry. */
+RTC_API void rtcSetGeometryIntersectFilterFunction(RTCGeometry geometry, RTCFilterFunctionN filter);
+
+/* Sets the occlusion filter callback function of the geometry. */
+RTC_API void rtcSetGeometryOccludedFilterFunction(RTCGeometry geometry, RTCFilterFunctionN filter);
+
+/* Sets the user-defined data pointer of the geometry. */
+RTC_API void rtcSetGeometryUserData(RTCGeometry geometry, void* ptr);
+
+/* Gets the user-defined data pointer of the geometry. */
+RTC_API void* rtcGetGeometryUserData(RTCGeometry geometry);
+
+/* Set the point query callback function of a geometry. */
+RTC_API void rtcSetGeometryPointQueryFunction(RTCGeometry geometry, RTCPointQueryFunction pointQuery);
+
+/* Sets the number of primitives of a user geometry. */
+RTC_API void rtcSetGeometryUserPrimitiveCount(RTCGeometry geometry, unsigned int userPrimitiveCount);
+
+/* Sets the bounding callback function to calculate bounding boxes for user primitives. */
+RTC_API void rtcSetGeometryBoundsFunction(RTCGeometry geometry, RTCBoundsFunction bounds, void* userPtr);
+
+/* Set the intersect callback function of a user geometry. */
+RTC_API void rtcSetGeometryIntersectFunction(RTCGeometry geometry, RTCIntersectFunctionN intersect);
+
+/* Set the occlusion callback function of a user geometry. */
+RTC_API void rtcSetGeometryOccludedFunction(RTCGeometry geometry, RTCOccludedFunctionN occluded);
+
+/* Invokes the intersection filter from the intersection callback function. */
+RTC_API void rtcFilterIntersection(const struct RTCIntersectFunctionNArguments* args, const struct RTCFilterFunctionNArguments* filterArgs);
+
+/* Invokes the occlusion filter from the occlusion callback function. */
+RTC_API void rtcFilterOcclusion(const struct RTCOccludedFunctionNArguments* args, const struct RTCFilterFunctionNArguments* filterArgs);
+
+
+/* Sets the instanced scene of an instance geometry. */
+RTC_API void rtcSetGeometryInstancedScene(RTCGeometry geometry, RTCScene scene);
+
+/* Sets the transformation of an instance for the specified time step. */
+RTC_API void rtcSetGeometryTransform(RTCGeometry geometry, unsigned int timeStep, enum RTCFormat format, const void* xfm);
+
+/* Sets the transformation quaternion of an instance for the specified time step. */
+RTC_API void rtcSetGeometryTransformQuaternion(RTCGeometry geometry, unsigned int timeStep, const struct RTCQuaternionDecomposition* qd);
+
+/* Returns the interpolated transformation of an instance for the specified time. */
+RTC_API void rtcGetGeometryTransform(RTCGeometry geometry, float time, enum RTCFormat format, void* xfm);
+
+
+/* Sets the uniform tessellation rate of the geometry. */
+RTC_API void rtcSetGeometryTessellationRate(RTCGeometry geometry, float tessellationRate);
+
+/* Sets the number of topologies of a subdivision surface. */
+RTC_API void rtcSetGeometryTopologyCount(RTCGeometry geometry, unsigned int topologyCount);
+
+/* Sets the subdivision interpolation mode. */
+RTC_API void rtcSetGeometrySubdivisionMode(RTCGeometry geometry, unsigned int topologyID, enum RTCSubdivisionMode mode);
+
+/* Binds a vertex attribute to a topology of the geometry. */
+RTC_API void rtcSetGeometryVertexAttributeTopology(RTCGeometry geometry, unsigned int vertexAttributeID, unsigned int topologyID);
+
+/* Sets the displacement callback function of a subdivision surface. */
+RTC_API void rtcSetGeometryDisplacementFunction(RTCGeometry geometry, RTCDisplacementFunctionN displacement);
+
+/* Returns the first half edge of a face. */
+RTC_API unsigned int rtcGetGeometryFirstHalfEdge(RTCGeometry geometry, unsigned int faceID);
+
+/* Returns the face the half edge belongs to. */
+RTC_API unsigned int rtcGetGeometryFace(RTCGeometry geometry, unsigned int edgeID);
+
+/* Returns next half edge. */
+RTC_API unsigned int rtcGetGeometryNextHalfEdge(RTCGeometry geometry, unsigned int edgeID);
+
+/* Returns previous half edge. */
+RTC_API unsigned int rtcGetGeometryPreviousHalfEdge(RTCGeometry geometry, unsigned int edgeID);
+
+/* Returns opposite half edge. */
+RTC_API unsigned int rtcGetGeometryOppositeHalfEdge(RTCGeometry geometry, unsigned int topologyID, unsigned int edgeID);
+
+
+/* Arguments for rtcInterpolate */
+struct RTCInterpolateArguments
+{
+ RTCGeometry geometry;
+ unsigned int primID;
+ float u;
+ float v;
+ enum RTCBufferType bufferType;
+ unsigned int bufferSlot;
+ float* P;
+ float* dPdu;
+ float* dPdv;
+ float* ddPdudu;
+ float* ddPdvdv;
+ float* ddPdudv;
+ unsigned int valueCount;
+};
+
+/* Interpolates vertex data to some u/v location and optionally calculates all derivatives. */
+RTC_API void rtcInterpolate(const struct RTCInterpolateArguments* args);
+
+/* Interpolates vertex data to some u/v location. */
+RTC_FORCEINLINE void rtcInterpolate0(RTCGeometry geometry, unsigned int primID, float u, float v, enum RTCBufferType bufferType, unsigned int bufferSlot, float* P, unsigned int valueCount)
+{
+ struct RTCInterpolateArguments args;
+ args.geometry = geometry;
+ args.primID = primID;
+ args.u = u;
+ args.v = v;
+ args.bufferType = bufferType;
+ args.bufferSlot = bufferSlot;
+ args.P = P;
+ args.dPdu = NULL;
+ args.dPdv = NULL;
+ args.ddPdudu = NULL;
+ args.ddPdvdv = NULL;
+ args.ddPdudv = NULL;
+ args.valueCount = valueCount;
+ rtcInterpolate(&args);
+}
+
+/* Interpolates vertex data to some u/v location and calculates first order derivatives. */
+RTC_FORCEINLINE void rtcInterpolate1(RTCGeometry geometry, unsigned int primID, float u, float v, enum RTCBufferType bufferType, unsigned int bufferSlot,
+ float* P, float* dPdu, float* dPdv, unsigned int valueCount)
+{
+ struct RTCInterpolateArguments args;
+ args.geometry = geometry;
+ args.primID = primID;
+ args.u = u;
+ args.v = v;
+ args.bufferType = bufferType;
+ args.bufferSlot = bufferSlot;
+ args.P = P;
+ args.dPdu = dPdu;
+ args.dPdv = dPdv;
+ args.ddPdudu = NULL;
+ args.ddPdvdv = NULL;
+ args.ddPdudv = NULL;
+ args.valueCount = valueCount;
+ rtcInterpolate(&args);
+}
+
+/* Interpolates vertex data to some u/v location and calculates first and second order derivatives. */
+RTC_FORCEINLINE void rtcInterpolate2(RTCGeometry geometry, unsigned int primID, float u, float v, enum RTCBufferType bufferType, unsigned int bufferSlot,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, unsigned int valueCount)
+{
+ struct RTCInterpolateArguments args;
+ args.geometry = geometry;
+ args.primID = primID;
+ args.u = u;
+ args.v = v;
+ args.bufferType = bufferType;
+ args.bufferSlot = bufferSlot;
+ args.P = P;
+ args.dPdu = dPdu;
+ args.dPdv = dPdv;
+ args.ddPdudu = ddPdudu;
+ args.ddPdvdv = ddPdvdv;
+ args.ddPdudv = ddPdudv;
+ args.valueCount = valueCount;
+ rtcInterpolate(&args);
+}
+
+/* Arguments for rtcInterpolateN */
+struct RTCInterpolateNArguments
+{
+ RTCGeometry geometry;
+ const void* valid;
+ const unsigned int* primIDs;
+ const float* u;
+ const float* v;
+ unsigned int N;
+ enum RTCBufferType bufferType;
+ unsigned int bufferSlot;
+ float* P;
+ float* dPdu;
+ float* dPdv;
+ float* ddPdudu;
+ float* ddPdvdv;
+ float* ddPdudv;
+ unsigned int valueCount;
+};
+
+/* Interpolates vertex data to an array of u/v locations. */
+RTC_API void rtcInterpolateN(const struct RTCInterpolateNArguments* args);
+
+/* RTCGrid primitive for grid mesh */
+struct RTCGrid
+{
+ unsigned int startVertexID;
+ unsigned int stride;
+ unsigned short width,height; // max is a 32k x 32k grid
+};
+
+RTC_NAMESPACE_END
+
+
diff --git a/thirdparty/embree/include/embree3/rtcore_quaternion.h b/thirdparty/embree/include/embree3/rtcore_quaternion.h
new file mode 100644
index 0000000000..6489fa3467
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_quaternion.h
@@ -0,0 +1,101 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore_common.h"
+
+RTC_NAMESPACE_BEGIN
+
+/*
+ * Structure for transformation respresentation as a matrix decomposition using
+ * a quaternion
+ */
+struct RTC_ALIGN(16) RTCQuaternionDecomposition
+{
+ float scale_x;
+ float scale_y;
+ float scale_z;
+ float skew_xy;
+ float skew_xz;
+ float skew_yz;
+ float shift_x;
+ float shift_y;
+ float shift_z;
+ float quaternion_r;
+ float quaternion_i;
+ float quaternion_j;
+ float quaternion_k;
+ float translation_x;
+ float translation_y;
+ float translation_z;
+};
+
+RTC_FORCEINLINE void rtcInitQuaternionDecomposition(struct RTCQuaternionDecomposition* qdecomp)
+{
+ qdecomp->scale_x = 1.f;
+ qdecomp->scale_y = 1.f;
+ qdecomp->scale_z = 1.f;
+ qdecomp->skew_xy = 0.f;
+ qdecomp->skew_xz = 0.f;
+ qdecomp->skew_yz = 0.f;
+ qdecomp->shift_x = 0.f;
+ qdecomp->shift_y = 0.f;
+ qdecomp->shift_z = 0.f;
+ qdecomp->quaternion_r = 1.f;
+ qdecomp->quaternion_i = 0.f;
+ qdecomp->quaternion_j = 0.f;
+ qdecomp->quaternion_k = 0.f;
+ qdecomp->translation_x = 0.f;
+ qdecomp->translation_y = 0.f;
+ qdecomp->translation_z = 0.f;
+}
+
+RTC_FORCEINLINE void rtcQuaternionDecompositionSetQuaternion(
+ struct RTCQuaternionDecomposition* qdecomp,
+ float r, float i, float j, float k)
+{
+ qdecomp->quaternion_r = r;
+ qdecomp->quaternion_i = i;
+ qdecomp->quaternion_j = j;
+ qdecomp->quaternion_k = k;
+}
+
+RTC_FORCEINLINE void rtcQuaternionDecompositionSetScale(
+ struct RTCQuaternionDecomposition* qdecomp,
+ float scale_x, float scale_y, float scale_z)
+{
+ qdecomp->scale_x = scale_x;
+ qdecomp->scale_y = scale_y;
+ qdecomp->scale_z = scale_z;
+}
+
+RTC_FORCEINLINE void rtcQuaternionDecompositionSetSkew(
+ struct RTCQuaternionDecomposition* qdecomp,
+ float skew_xy, float skew_xz, float skew_yz)
+{
+ qdecomp->skew_xy = skew_xy;
+ qdecomp->skew_xz = skew_xz;
+ qdecomp->skew_yz = skew_yz;
+}
+
+RTC_FORCEINLINE void rtcQuaternionDecompositionSetShift(
+ struct RTCQuaternionDecomposition* qdecomp,
+ float shift_x, float shift_y, float shift_z)
+{
+ qdecomp->shift_x = shift_x;
+ qdecomp->shift_y = shift_y;
+ qdecomp->shift_z = shift_z;
+}
+
+RTC_FORCEINLINE void rtcQuaternionDecompositionSetTranslation(
+ struct RTCQuaternionDecomposition* qdecomp,
+ float translation_x, float translation_y, float translation_z)
+{
+ qdecomp->translation_x = translation_x;
+ qdecomp->translation_y = translation_y;
+ qdecomp->translation_z = translation_z;
+}
+
+RTC_NAMESPACE_END
+
diff --git a/thirdparty/embree/include/embree3/rtcore_ray.h b/thirdparty/embree/include/embree3/rtcore_ray.h
new file mode 100644
index 0000000000..a2ee6dabbb
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_ray.h
@@ -0,0 +1,378 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore_common.h"
+
+RTC_NAMESPACE_BEGIN
+
+/* Ray structure for a single ray */
+struct RTC_ALIGN(16) RTCRay
+{
+ float org_x; // x coordinate of ray origin
+ float org_y; // y coordinate of ray origin
+ float org_z; // z coordinate of ray origin
+ float tnear; // start of ray segment
+
+ float dir_x; // x coordinate of ray direction
+ float dir_y; // y coordinate of ray direction
+ float dir_z; // z coordinate of ray direction
+ float time; // time of this ray for motion blur
+
+ float tfar; // end of ray segment (set to hit distance)
+ unsigned int mask; // ray mask
+ unsigned int id; // ray ID
+ unsigned int flags; // ray flags
+};
+
+/* Hit structure for a single ray */
+struct RTC_ALIGN(16) RTCHit
+{
+ float Ng_x; // x coordinate of geometry normal
+ float Ng_y; // y coordinate of geometry normal
+ float Ng_z; // z coordinate of geometry normal
+
+ float u; // barycentric u coordinate of hit
+ float v; // barycentric v coordinate of hit
+
+ unsigned int primID; // primitive ID
+ unsigned int geomID; // geometry ID
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
+};
+
+/* Combined ray/hit structure for a single ray */
+struct RTCRayHit
+{
+ struct RTCRay ray;
+ struct RTCHit hit;
+};
+
+/* Ray structure for a packet of 4 rays */
+struct RTC_ALIGN(16) RTCRay4
+{
+ float org_x[4];
+ float org_y[4];
+ float org_z[4];
+ float tnear[4];
+
+ float dir_x[4];
+ float dir_y[4];
+ float dir_z[4];
+ float time[4];
+
+ float tfar[4];
+ unsigned int mask[4];
+ unsigned int id[4];
+ unsigned int flags[4];
+};
+
+/* Hit structure for a packet of 4 rays */
+struct RTC_ALIGN(16) RTCHit4
+{
+ float Ng_x[4];
+ float Ng_y[4];
+ float Ng_z[4];
+
+ float u[4];
+ float v[4];
+
+ unsigned int primID[4];
+ unsigned int geomID[4];
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT][4];
+};
+
+/* Combined ray/hit structure for a packet of 4 rays */
+struct RTCRayHit4
+{
+ struct RTCRay4 ray;
+ struct RTCHit4 hit;
+};
+
+/* Ray structure for a packet of 8 rays */
+struct RTC_ALIGN(32) RTCRay8
+{
+ float org_x[8];
+ float org_y[8];
+ float org_z[8];
+ float tnear[8];
+
+ float dir_x[8];
+ float dir_y[8];
+ float dir_z[8];
+ float time[8];
+
+ float tfar[8];
+ unsigned int mask[8];
+ unsigned int id[8];
+ unsigned int flags[8];
+};
+
+/* Hit structure for a packet of 8 rays */
+struct RTC_ALIGN(32) RTCHit8
+{
+ float Ng_x[8];
+ float Ng_y[8];
+ float Ng_z[8];
+
+ float u[8];
+ float v[8];
+
+ unsigned int primID[8];
+ unsigned int geomID[8];
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT][8];
+};
+
+/* Combined ray/hit structure for a packet of 8 rays */
+struct RTCRayHit8
+{
+ struct RTCRay8 ray;
+ struct RTCHit8 hit;
+};
+
+/* Ray structure for a packet of 16 rays */
+struct RTC_ALIGN(64) RTCRay16
+{
+ float org_x[16];
+ float org_y[16];
+ float org_z[16];
+ float tnear[16];
+
+ float dir_x[16];
+ float dir_y[16];
+ float dir_z[16];
+ float time[16];
+
+ float tfar[16];
+ unsigned int mask[16];
+ unsigned int id[16];
+ unsigned int flags[16];
+};
+
+/* Hit structure for a packet of 16 rays */
+struct RTC_ALIGN(64) RTCHit16
+{
+ float Ng_x[16];
+ float Ng_y[16];
+ float Ng_z[16];
+
+ float u[16];
+ float v[16];
+
+ unsigned int primID[16];
+ unsigned int geomID[16];
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT][16];
+};
+
+/* Combined ray/hit structure for a packet of 16 rays */
+struct RTCRayHit16
+{
+ struct RTCRay16 ray;
+ struct RTCHit16 hit;
+};
+
+/* Ray structure for a packet/stream of N rays in pointer SOA layout */
+struct RTCRayNp
+{
+ float* org_x;
+ float* org_y;
+ float* org_z;
+ float* tnear;
+
+ float* dir_x;
+ float* dir_y;
+ float* dir_z;
+ float* time;
+
+ float* tfar;
+ unsigned int* mask;
+ unsigned int* id;
+ unsigned int* flags;
+};
+
+/* Hit structure for a packet/stream of N rays in pointer SOA layout */
+struct RTCHitNp
+{
+ float* Ng_x;
+ float* Ng_y;
+ float* Ng_z;
+
+ float* u;
+ float* v;
+
+ unsigned int* primID;
+ unsigned int* geomID;
+ unsigned int* instID[RTC_MAX_INSTANCE_LEVEL_COUNT];
+};
+
+/* Combined ray/hit structure for a packet/stream of N rays in pointer SOA layout */
+struct RTCRayHitNp
+{
+ struct RTCRayNp ray;
+ struct RTCHitNp hit;
+};
+
+struct RTCRayN;
+struct RTCHitN;
+struct RTCRayHitN;
+
+#if defined(__cplusplus)
+
+/* Helper functions to access ray packets of runtime size N */
+RTC_FORCEINLINE float& RTCRayN_org_x(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[0*N+i]; }
+RTC_FORCEINLINE float& RTCRayN_org_y(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[1*N+i]; }
+RTC_FORCEINLINE float& RTCRayN_org_z(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[2*N+i]; }
+RTC_FORCEINLINE float& RTCRayN_tnear(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[3*N+i]; }
+
+RTC_FORCEINLINE float& RTCRayN_dir_x(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[4*N+i]; }
+RTC_FORCEINLINE float& RTCRayN_dir_y(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[5*N+i]; }
+RTC_FORCEINLINE float& RTCRayN_dir_z(RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[6*N+i]; }
+RTC_FORCEINLINE float& RTCRayN_time (RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[7*N+i]; }
+
+RTC_FORCEINLINE float& RTCRayN_tfar (RTCRayN* ray, unsigned int N, unsigned int i) { return ((float*)ray)[8*N+i]; }
+RTC_FORCEINLINE unsigned int& RTCRayN_mask (RTCRayN* ray, unsigned int N, unsigned int i) { return ((unsigned*)ray)[9*N+i]; }
+RTC_FORCEINLINE unsigned int& RTCRayN_id (RTCRayN* ray, unsigned int N, unsigned int i) { return ((unsigned*)ray)[10*N+i]; }
+RTC_FORCEINLINE unsigned int& RTCRayN_flags(RTCRayN* ray, unsigned int N, unsigned int i) { return ((unsigned*)ray)[11*N+i]; }
+
+/* Helper functions to access hit packets of runtime size N */
+RTC_FORCEINLINE float& RTCHitN_Ng_x(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[0*N+i]; }
+RTC_FORCEINLINE float& RTCHitN_Ng_y(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[1*N+i]; }
+RTC_FORCEINLINE float& RTCHitN_Ng_z(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[2*N+i]; }
+
+RTC_FORCEINLINE float& RTCHitN_u(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[3*N+i]; }
+RTC_FORCEINLINE float& RTCHitN_v(RTCHitN* hit, unsigned int N, unsigned int i) { return ((float*)hit)[4*N+i]; }
+
+RTC_FORCEINLINE unsigned int& RTCHitN_primID(RTCHitN* hit, unsigned int N, unsigned int i) { return ((unsigned*)hit)[5*N+i]; }
+RTC_FORCEINLINE unsigned int& RTCHitN_geomID(RTCHitN* hit, unsigned int N, unsigned int i) { return ((unsigned*)hit)[6*N+i]; }
+RTC_FORCEINLINE unsigned int& RTCHitN_instID(RTCHitN* hit, unsigned int N, unsigned int i, unsigned int l) { return ((unsigned*)hit)[7*N+i+N*l]; }
+
+/* Helper functions to extract RTCRayN and RTCHitN from RTCRayHitN */
+RTC_FORCEINLINE RTCRayN* RTCRayHitN_RayN(RTCRayHitN* rayhit, unsigned int N) { return (RTCRayN*)&((float*)rayhit)[0*N]; }
+RTC_FORCEINLINE RTCHitN* RTCRayHitN_HitN(RTCRayHitN* rayhit, unsigned int N) { return (RTCHitN*)&((float*)rayhit)[12*N]; }
+
+/* Helper structure for a ray packet of compile-time size N */
+template<int N>
+struct RTCRayNt
+{
+ float org_x[N];
+ float org_y[N];
+ float org_z[N];
+ float tnear[N];
+
+ float dir_x[N];
+ float dir_y[N];
+ float dir_z[N];
+ float time[N];
+
+ float tfar[N];
+ unsigned int mask[N];
+ unsigned int id[N];
+ unsigned int flags[N];
+};
+
+/* Helper structure for a hit packet of compile-time size N */
+template<int N>
+struct RTCHitNt
+{
+ float Ng_x[N];
+ float Ng_y[N];
+ float Ng_z[N];
+
+ float u[N];
+ float v[N];
+
+ unsigned int primID[N];
+ unsigned int geomID[N];
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT][N];
+};
+
+/* Helper structure for a combined ray/hit packet of compile-time size N */
+template<int N>
+struct RTCRayHitNt
+{
+ RTCRayNt<N> ray;
+ RTCHitNt<N> hit;
+};
+
+RTC_FORCEINLINE RTCRay rtcGetRayFromRayN(RTCRayN* rayN, unsigned int N, unsigned int i)
+{
+ RTCRay ray;
+ ray.org_x = RTCRayN_org_x(rayN,N,i);
+ ray.org_y = RTCRayN_org_y(rayN,N,i);
+ ray.org_z = RTCRayN_org_z(rayN,N,i);
+ ray.tnear = RTCRayN_tnear(rayN,N,i);
+ ray.dir_x = RTCRayN_dir_x(rayN,N,i);
+ ray.dir_y = RTCRayN_dir_y(rayN,N,i);
+ ray.dir_z = RTCRayN_dir_z(rayN,N,i);
+ ray.time = RTCRayN_time(rayN,N,i);
+ ray.tfar = RTCRayN_tfar(rayN,N,i);
+ ray.mask = RTCRayN_mask(rayN,N,i);
+ ray.id = RTCRayN_id(rayN,N,i);
+ ray.flags = RTCRayN_flags(rayN,N,i);
+ return ray;
+}
+
+RTC_FORCEINLINE RTCHit rtcGetHitFromHitN(RTCHitN* hitN, unsigned int N, unsigned int i)
+{
+ RTCHit hit;
+ hit.Ng_x = RTCHitN_Ng_x(hitN,N,i);
+ hit.Ng_y = RTCHitN_Ng_y(hitN,N,i);
+ hit.Ng_z = RTCHitN_Ng_z(hitN,N,i);
+ hit.u = RTCHitN_u(hitN,N,i);
+ hit.v = RTCHitN_v(hitN,N,i);
+ hit.primID = RTCHitN_primID(hitN,N,i);
+ hit.geomID = RTCHitN_geomID(hitN,N,i);
+ for (unsigned int l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; l++)
+ hit.instID[l] = RTCHitN_instID(hitN,N,i,l);
+ return hit;
+}
+
+RTC_FORCEINLINE void rtcCopyHitToHitN(RTCHitN* hitN, const RTCHit* hit, unsigned int N, unsigned int i)
+{
+ RTCHitN_Ng_x(hitN,N,i) = hit->Ng_x;
+ RTCHitN_Ng_y(hitN,N,i) = hit->Ng_y;
+ RTCHitN_Ng_z(hitN,N,i) = hit->Ng_z;
+ RTCHitN_u(hitN,N,i) = hit->u;
+ RTCHitN_v(hitN,N,i) = hit->v;
+ RTCHitN_primID(hitN,N,i) = hit->primID;
+ RTCHitN_geomID(hitN,N,i) = hit->geomID;
+ for (unsigned int l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; l++)
+ RTCHitN_instID(hitN,N,i,l) = hit->instID[l];
+}
+
+RTC_FORCEINLINE RTCRayHit rtcGetRayHitFromRayHitN(RTCRayHitN* rayhitN, unsigned int N, unsigned int i)
+{
+ RTCRayHit rh;
+
+ RTCRayN* ray = RTCRayHitN_RayN(rayhitN,N);
+ rh.ray.org_x = RTCRayN_org_x(ray,N,i);
+ rh.ray.org_y = RTCRayN_org_y(ray,N,i);
+ rh.ray.org_z = RTCRayN_org_z(ray,N,i);
+ rh.ray.tnear = RTCRayN_tnear(ray,N,i);
+ rh.ray.dir_x = RTCRayN_dir_x(ray,N,i);
+ rh.ray.dir_y = RTCRayN_dir_y(ray,N,i);
+ rh.ray.dir_z = RTCRayN_dir_z(ray,N,i);
+ rh.ray.time = RTCRayN_time(ray,N,i);
+ rh.ray.tfar = RTCRayN_tfar(ray,N,i);
+ rh.ray.mask = RTCRayN_mask(ray,N,i);
+ rh.ray.id = RTCRayN_id(ray,N,i);
+ rh.ray.flags = RTCRayN_flags(ray,N,i);
+
+ RTCHitN* hit = RTCRayHitN_HitN(rayhitN,N);
+ rh.hit.Ng_x = RTCHitN_Ng_x(hit,N,i);
+ rh.hit.Ng_y = RTCHitN_Ng_y(hit,N,i);
+ rh.hit.Ng_z = RTCHitN_Ng_z(hit,N,i);
+ rh.hit.u = RTCHitN_u(hit,N,i);
+ rh.hit.v = RTCHitN_v(hit,N,i);
+ rh.hit.primID = RTCHitN_primID(hit,N,i);
+ rh.hit.geomID = RTCHitN_geomID(hit,N,i);
+ for (unsigned int l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; l++)
+ rh.hit.instID[l] = RTCHitN_instID(hit,N,i,l);
+
+ return rh;
+}
+
+#endif
+
+RTC_NAMESPACE_END
+
diff --git a/thirdparty/embree/include/embree3/rtcore_scene.h b/thirdparty/embree/include/embree3/rtcore_scene.h
new file mode 100644
index 0000000000..5878a3d402
--- /dev/null
+++ b/thirdparty/embree/include/embree3/rtcore_scene.h
@@ -0,0 +1,160 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore_device.h"
+
+RTC_NAMESPACE_BEGIN
+
+/* Forward declarations for ray structures */
+struct RTCRayHit;
+struct RTCRayHit4;
+struct RTCRayHit8;
+struct RTCRayHit16;
+struct RTCRayHitNp;
+
+/* Scene flags */
+enum RTCSceneFlags
+{
+ RTC_SCENE_FLAG_NONE = 0,
+ RTC_SCENE_FLAG_DYNAMIC = (1 << 0),
+ RTC_SCENE_FLAG_COMPACT = (1 << 1),
+ RTC_SCENE_FLAG_ROBUST = (1 << 2),
+ RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION = (1 << 3)
+};
+
+/* Creates a new scene. */
+RTC_API RTCScene rtcNewScene(RTCDevice device);
+
+/* Returns the device the scene got created in. The reference count of
+ * the device is incremented by this function. */
+RTC_API RTCDevice rtcGetSceneDevice(RTCScene hscene);
+
+/* Retains the scene (increments the reference count). */
+RTC_API void rtcRetainScene(RTCScene scene);
+
+/* Releases the scene (decrements the reference count). */
+RTC_API void rtcReleaseScene(RTCScene scene);
+
+
+/* Attaches the geometry to a scene. */
+RTC_API unsigned int rtcAttachGeometry(RTCScene scene, RTCGeometry geometry);
+
+/* Attaches the geometry to a scene using the specified geometry ID. */
+RTC_API void rtcAttachGeometryByID(RTCScene scene, RTCGeometry geometry, unsigned int geomID);
+
+/* Detaches the geometry from the scene. */
+RTC_API void rtcDetachGeometry(RTCScene scene, unsigned int geomID);
+
+/* Gets a geometry handle from the scene. */
+RTC_API RTCGeometry rtcGetGeometry(RTCScene scene, unsigned int geomID);
+
+
+/* Commits the scene. */
+RTC_API void rtcCommitScene(RTCScene scene);
+
+/* Commits the scene from multiple threads. */
+RTC_API void rtcJoinCommitScene(RTCScene scene);
+
+
+/* Progress monitor callback function */
+typedef bool (*RTCProgressMonitorFunction)(void* ptr, double n);
+
+/* Sets the progress monitor callback function of the scene. */
+RTC_API void rtcSetSceneProgressMonitorFunction(RTCScene scene, RTCProgressMonitorFunction progress, void* ptr);
+
+/* Sets the build quality of the scene. */
+RTC_API void rtcSetSceneBuildQuality(RTCScene scene, enum RTCBuildQuality quality);
+
+/* Sets the scene flags. */
+RTC_API void rtcSetSceneFlags(RTCScene scene, enum RTCSceneFlags flags);
+
+/* Returns the scene flags. */
+RTC_API enum RTCSceneFlags rtcGetSceneFlags(RTCScene scene);
+
+/* Returns the axis-aligned bounds of the scene. */
+RTC_API void rtcGetSceneBounds(RTCScene scene, struct RTCBounds* bounds_o);
+
+/* Returns the linear axis-aligned bounds of the scene. */
+RTC_API void rtcGetSceneLinearBounds(RTCScene scene, struct RTCLinearBounds* bounds_o);
+
+
+/* Perform a closest point query of the scene. */
+RTC_API bool rtcPointQuery(RTCScene scene, struct RTCPointQuery* query, struct RTCPointQueryContext* context, RTCPointQueryFunction queryFunc, void* userPtr);
+
+/* Perform a closest point query with a packet of 4 points with the scene. */
+RTC_API bool rtcPointQuery4(const int* valid, RTCScene scene, struct RTCPointQuery4* query, struct RTCPointQueryContext* context, RTCPointQueryFunction queryFunc, void** userPtr);
+
+/* Perform a closest point query with a packet of 4 points with the scene. */
+RTC_API bool rtcPointQuery8(const int* valid, RTCScene scene, struct RTCPointQuery8* query, struct RTCPointQueryContext* context, RTCPointQueryFunction queryFunc, void** userPtr);
+
+/* Perform a closest point query with a packet of 4 points with the scene. */
+RTC_API bool rtcPointQuery16(const int* valid, RTCScene scene, struct RTCPointQuery16* query, struct RTCPointQueryContext* context, RTCPointQueryFunction queryFunc, void** userPtr);
+
+/* Intersects a single ray with the scene. */
+RTC_API void rtcIntersect1(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit* rayhit);
+
+/* Intersects a packet of 4 rays with the scene. */
+RTC_API void rtcIntersect4(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit4* rayhit);
+
+/* Intersects a packet of 8 rays with the scene. */
+RTC_API void rtcIntersect8(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit8* rayhit);
+
+/* Intersects a packet of 16 rays with the scene. */
+RTC_API void rtcIntersect16(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit16* rayhit);
+
+/* Intersects a stream of M rays with the scene. */
+RTC_API void rtcIntersect1M(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit* rayhit, unsigned int M, size_t byteStride);
+
+/* Intersects a stream of pointers to M rays with the scene. */
+RTC_API void rtcIntersect1Mp(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHit** rayhit, unsigned int M);
+
+/* Intersects a stream of M ray packets of size N in SOA format with the scene. */
+RTC_API void rtcIntersectNM(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayHitN* rayhit, unsigned int N, unsigned int M, size_t byteStride);
+
+/* Intersects a stream of M ray packets of size N in SOA format with the scene. */
+RTC_API void rtcIntersectNp(RTCScene scene, struct RTCIntersectContext* context, const struct RTCRayHitNp* rayhit, unsigned int N);
+
+/* Tests a single ray for occlusion with the scene. */
+RTC_API void rtcOccluded1(RTCScene scene, struct RTCIntersectContext* context, struct RTCRay* ray);
+
+/* Tests a packet of 4 rays for occlusion occluded with the scene. */
+RTC_API void rtcOccluded4(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRay4* ray);
+
+/* Tests a packet of 8 rays for occlusion with the scene. */
+RTC_API void rtcOccluded8(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRay8* ray);
+
+/* Tests a packet of 16 rays for occlusion with the scene. */
+RTC_API void rtcOccluded16(const int* valid, RTCScene scene, struct RTCIntersectContext* context, struct RTCRay16* ray);
+
+/* Tests a stream of M rays for occlusion with the scene. */
+RTC_API void rtcOccluded1M(RTCScene scene, struct RTCIntersectContext* context, struct RTCRay* ray, unsigned int M, size_t byteStride);
+
+/* Tests a stream of pointers to M rays for occlusion with the scene. */
+RTC_API void rtcOccluded1Mp(RTCScene scene, struct RTCIntersectContext* context, struct RTCRay** ray, unsigned int M);
+
+/* Tests a stream of M ray packets of size N in SOA format for occlusion with the scene. */
+RTC_API void rtcOccludedNM(RTCScene scene, struct RTCIntersectContext* context, struct RTCRayN* ray, unsigned int N, unsigned int M, size_t byteStride);
+
+/* Tests a stream of M ray packets of size N in SOA format for occlusion with the scene. */
+RTC_API void rtcOccludedNp(RTCScene scene, struct RTCIntersectContext* context, const struct RTCRayNp* ray, unsigned int N);
+
+/*! collision callback */
+struct RTCCollision { unsigned int geomID0; unsigned int primID0; unsigned int geomID1; unsigned int primID1; };
+typedef void (*RTCCollideFunc) (void* userPtr, struct RTCCollision* collisions, unsigned int num_collisions);
+
+/*! Performs collision detection of two scenes */
+RTC_API void rtcCollide (RTCScene scene0, RTCScene scene1, RTCCollideFunc callback, void* userPtr);
+
+#if defined(__cplusplus)
+
+/* Helper for easily combining scene flags */
+inline RTCSceneFlags operator|(RTCSceneFlags a, RTCSceneFlags b) {
+ return (RTCSceneFlags)((size_t)a | (size_t)b);
+}
+
+#endif
+
+RTC_NAMESPACE_END
+
diff --git a/thirdparty/embree/kernels/builders/bvh_builder_hair.h b/thirdparty/embree/kernels/builders/bvh_builder_hair.h
new file mode 100644
index 0000000000..d83e8918a1
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/bvh_builder_hair.h
@@ -0,0 +1,411 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../bvh/bvh.h"
+#include "../geometry/primitive.h"
+#include "../builders/bvh_builder_sah.h"
+#include "../builders/heuristic_binning_array_aligned.h"
+#include "../builders/heuristic_binning_array_unaligned.h"
+#include "../builders/heuristic_strand_array.h"
+
+#define NUM_HAIR_OBJECT_BINS 32
+
+namespace embree
+{
+ namespace isa
+ {
+ struct BVHBuilderHair
+ {
+ /*! settings for builder */
+ struct Settings
+ {
+ /*! default settings */
+ Settings ()
+ : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(7), finished_range_threshold(inf) {}
+
+ public:
+ size_t branchingFactor; //!< branching factor of BVH to build
+ size_t maxDepth; //!< maximum depth of BVH to build
+ size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
+ size_t minLeafSize; //!< minimum size of a leaf
+ size_t maxLeafSize; //!< maximum size of a leaf
+ size_t finished_range_threshold; //!< finished range threshold
+ };
+
+ template<typename NodeRef,
+ typename CreateAllocFunc,
+ typename CreateAABBNodeFunc,
+ typename SetAABBNodeFunc,
+ typename CreateOBBNodeFunc,
+ typename SetOBBNodeFunc,
+ typename CreateLeafFunc,
+ typename ProgressMonitor,
+ typename ReportFinishedRangeFunc>
+
+ class BuilderT
+ {
+ ALIGNED_CLASS_(16);
+ friend struct BVHBuilderHair;
+
+ typedef FastAllocator::CachedAllocator Allocator;
+ typedef HeuristicArrayBinningSAH<PrimRef,NUM_HAIR_OBJECT_BINS> HeuristicBinningSAH;
+ typedef UnalignedHeuristicArrayBinningSAH<PrimRef,NUM_HAIR_OBJECT_BINS> UnalignedHeuristicBinningSAH;
+ typedef HeuristicStrandSplit HeuristicStrandSplitSAH;
+
+ static const size_t MAX_BRANCHING_FACTOR = 8; //!< maximum supported BVH branching factor
+ static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree if we are that many levels before the maximum tree depth
+ static const size_t SINGLE_THREADED_THRESHOLD = 4096; //!< threshold to switch to single threaded build
+
+ static const size_t travCostAligned = 1;
+ static const size_t travCostUnaligned = 5;
+ static const size_t intCost = 6;
+
+ BuilderT (Scene* scene,
+ PrimRef* prims,
+ const CreateAllocFunc& createAlloc,
+ const CreateAABBNodeFunc& createAABBNode,
+ const SetAABBNodeFunc& setAABBNode,
+ const CreateOBBNodeFunc& createOBBNode,
+ const SetOBBNodeFunc& setOBBNode,
+ const CreateLeafFunc& createLeaf,
+ const ProgressMonitor& progressMonitor,
+ const ReportFinishedRangeFunc& reportFinishedRange,
+ const Settings settings)
+
+ : cfg(settings),
+ prims(prims),
+ createAlloc(createAlloc),
+ createAABBNode(createAABBNode),
+ setAABBNode(setAABBNode),
+ createOBBNode(createOBBNode),
+ setOBBNode(setOBBNode),
+ createLeaf(createLeaf),
+ progressMonitor(progressMonitor),
+ reportFinishedRange(reportFinishedRange),
+ alignedHeuristic(prims), unalignedHeuristic(scene,prims), strandHeuristic(scene,prims) {}
+
+ /*! checks if all primitives are from the same geometry */
+ __forceinline bool sameGeometry(const PrimInfoRange& range)
+ {
+ if (range.size() == 0) return true;
+ unsigned int firstGeomID = prims[range.begin()].geomID();
+ for (size_t i=range.begin()+1; i<range.end(); i++) {
+ if (prims[i].geomID() != firstGeomID){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*! creates a large leaf that could be larger than supported by the BVH */
+ NodeRef createLargeLeaf(size_t depth, const PrimInfoRange& pinfo, Allocator alloc)
+ {
+ /* this should never occur but is a fatal error */
+ if (depth > cfg.maxDepth)
+ throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
+
+ /* create leaf for few primitives */
+ if (pinfo.size() <= cfg.maxLeafSize && sameGeometry(pinfo))
+ return createLeaf(prims,pinfo,alloc);
+
+ /* fill all children by always splitting the largest one */
+ PrimInfoRange children[MAX_BRANCHING_FACTOR];
+ unsigned numChildren = 1;
+ children[0] = pinfo;
+
+ do {
+
+ /* find best child with largest bounding box area */
+ int bestChild = -1;
+ size_t bestSize = 0;
+ for (unsigned i=0; i<numChildren; i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].size() <= cfg.maxLeafSize && sameGeometry(children[i]))
+ continue;
+
+ /* remember child with largest size */
+ if (children[i].size() > bestSize) {
+ bestSize = children[i].size();
+ bestChild = i;
+ }
+ }
+ if (bestChild == -1) break;
+
+ /*! split best child into left and right child */
+ __aligned(64) PrimInfoRange left, right;
+ if (!sameGeometry(children[bestChild])) {
+ alignedHeuristic.splitByGeometry(children[bestChild],left,right);
+ } else {
+ alignedHeuristic.splitFallback(children[bestChild],left,right);
+ }
+
+ /* add new children left and right */
+ children[bestChild] = children[numChildren-1];
+ children[numChildren-1] = left;
+ children[numChildren+0] = right;
+ numChildren++;
+
+ } while (numChildren < cfg.branchingFactor);
+
+ /* create node */
+ auto node = createAABBNode(alloc);
+
+ for (size_t i=0; i<numChildren; i++) {
+ const NodeRef child = createLargeLeaf(depth+1,children[i],alloc);
+ setAABBNode(node,i,child,children[i].geomBounds);
+ }
+
+ return node;
+ }
+
+ /*! performs split */
+ __noinline void split(const PrimInfoRange& pinfo, PrimInfoRange& linfo, PrimInfoRange& rinfo, bool& aligned) // FIXME: not inlined as ICC otherwise uses much stack
+ {
+ /* variable to track the SAH of the best splitting approach */
+ float bestSAH = inf;
+ const size_t blocks = (pinfo.size()+(1ull<<cfg.logBlockSize)-1ull) >> cfg.logBlockSize;
+ const float leafSAH = intCost*float(blocks)*halfArea(pinfo.geomBounds);
+
+ /* try standard binning in aligned space */
+ float alignedObjectSAH = inf;
+ HeuristicBinningSAH::Split alignedObjectSplit;
+ if (aligned) {
+ alignedObjectSplit = alignedHeuristic.find(pinfo,cfg.logBlockSize);
+ alignedObjectSAH = travCostAligned*halfArea(pinfo.geomBounds) + intCost*alignedObjectSplit.splitSAH();
+ bestSAH = min(alignedObjectSAH,bestSAH);
+ }
+
+ /* try standard binning in unaligned space */
+ UnalignedHeuristicBinningSAH::Split unalignedObjectSplit;
+ LinearSpace3fa uspace;
+ float unalignedObjectSAH = inf;
+ if (bestSAH > 0.7f*leafSAH) {
+ uspace = unalignedHeuristic.computeAlignedSpace(pinfo);
+ const PrimInfoRange sinfo = unalignedHeuristic.computePrimInfo(pinfo,uspace);
+ unalignedObjectSplit = unalignedHeuristic.find(sinfo,cfg.logBlockSize,uspace);
+ unalignedObjectSAH = travCostUnaligned*halfArea(pinfo.geomBounds) + intCost*unalignedObjectSplit.splitSAH();
+ bestSAH = min(unalignedObjectSAH,bestSAH);
+ }
+
+ /* try splitting into two strands */
+ HeuristicStrandSplitSAH::Split strandSplit;
+ float strandSAH = inf;
+ if (bestSAH > 0.7f*leafSAH && pinfo.size() <= 256) {
+ strandSplit = strandHeuristic.find(pinfo,cfg.logBlockSize);
+ strandSAH = travCostUnaligned*halfArea(pinfo.geomBounds) + intCost*strandSplit.splitSAH();
+ bestSAH = min(strandSAH,bestSAH);
+ }
+
+ /* fallback if SAH heuristics failed */
+ if (unlikely(!std::isfinite(bestSAH)))
+ {
+ alignedHeuristic.deterministic_order(pinfo);
+ alignedHeuristic.splitFallback(pinfo,linfo,rinfo);
+ }
+
+ /* perform aligned split if this is best */
+ else if (bestSAH == alignedObjectSAH) {
+ alignedHeuristic.split(alignedObjectSplit,pinfo,linfo,rinfo);
+ }
+
+ /* perform unaligned split if this is best */
+ else if (bestSAH == unalignedObjectSAH) {
+ unalignedHeuristic.split(unalignedObjectSplit,uspace,pinfo,linfo,rinfo);
+ aligned = false;
+ }
+
+ /* perform strand split if this is best */
+ else if (bestSAH == strandSAH) {
+ strandHeuristic.split(strandSplit,pinfo,linfo,rinfo);
+ aligned = false;
+ }
+
+ /* can never happen */
+ else
+ assert(false);
+ }
+
+ /*! recursive build */
+ NodeRef recurse(size_t depth, const PrimInfoRange& pinfo, Allocator alloc, bool toplevel, bool alloc_barrier)
+ {
+ /* get thread local allocator */
+ if (!alloc)
+ alloc = createAlloc();
+
+ /* call memory monitor function to signal progress */
+ if (toplevel && pinfo.size() <= SINGLE_THREADED_THRESHOLD)
+ progressMonitor(pinfo.size());
+
+ PrimInfoRange children[MAX_BRANCHING_FACTOR];
+
+ /* create leaf node */
+ if (depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || pinfo.size() <= cfg.minLeafSize) {
+ alignedHeuristic.deterministic_order(pinfo);
+ return createLargeLeaf(depth,pinfo,alloc);
+ }
+
+ /* fill all children by always splitting the one with the largest surface area */
+ size_t numChildren = 1;
+ children[0] = pinfo;
+ bool aligned = true;
+
+ do {
+
+ /* find best child with largest bounding box area */
+ ssize_t bestChild = -1;
+ float bestArea = neg_inf;
+ for (size_t i=0; i<numChildren; i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].size() <= cfg.minLeafSize)
+ continue;
+
+ /* remember child with largest area */
+ if (area(children[i].geomBounds) > bestArea) {
+ bestArea = area(children[i].geomBounds);
+ bestChild = i;
+ }
+ }
+ if (bestChild == -1) break;
+
+ /*! split best child into left and right child */
+ PrimInfoRange left, right;
+ split(children[bestChild],left,right,aligned);
+
+ /* add new children left and right */
+ children[bestChild] = children[numChildren-1];
+ children[numChildren-1] = left;
+ children[numChildren+0] = right;
+ numChildren++;
+
+ } while (numChildren < cfg.branchingFactor);
+
+ NodeRef node;
+
+ /* create aligned node */
+ if (aligned)
+ {
+ node = createAABBNode(alloc);
+
+ /* spawn tasks or ... */
+ if (pinfo.size() > SINGLE_THREADED_THRESHOLD)
+ {
+ parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ const bool child_alloc_barrier = pinfo.size() > cfg.finished_range_threshold && children[i].size() <= cfg.finished_range_threshold;
+ setAABBNode(node,i,recurse(depth+1,children[i],nullptr,true,child_alloc_barrier),children[i].geomBounds);
+ _mm_mfence(); // to allow non-temporal stores during build
+ }
+ });
+ }
+ /* ... continue sequentially */
+ else {
+ for (size_t i=0; i<numChildren; i++) {
+ const bool child_alloc_barrier = pinfo.size() > cfg.finished_range_threshold && children[i].size() <= cfg.finished_range_threshold;
+ setAABBNode(node,i,recurse(depth+1,children[i],alloc,false,child_alloc_barrier),children[i].geomBounds);
+ }
+ }
+ }
+
+ /* create unaligned node */
+ else
+ {
+ node = createOBBNode(alloc);
+
+ /* spawn tasks or ... */
+ if (pinfo.size() > SINGLE_THREADED_THRESHOLD)
+ {
+ parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpace(children[i]);
+ const PrimInfoRange sinfo = unalignedHeuristic.computePrimInfo(children[i],space);
+ const OBBox3fa obounds(space,sinfo.geomBounds);
+ const bool child_alloc_barrier = pinfo.size() > cfg.finished_range_threshold && children[i].size() <= cfg.finished_range_threshold;
+ setOBBNode(node,i,recurse(depth+1,children[i],nullptr,true,child_alloc_barrier),obounds);
+ _mm_mfence(); // to allow non-temporal stores during build
+ }
+ });
+ }
+ /* ... continue sequentially */
+ else
+ {
+ for (size_t i=0; i<numChildren; i++) {
+ const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpace(children[i]);
+ const PrimInfoRange sinfo = unalignedHeuristic.computePrimInfo(children[i],space);
+ const OBBox3fa obounds(space,sinfo.geomBounds);
+ const bool child_alloc_barrier = pinfo.size() > cfg.finished_range_threshold && children[i].size() <= cfg.finished_range_threshold;
+ setOBBNode(node,i,recurse(depth+1,children[i],alloc,false,child_alloc_barrier),obounds);
+ }
+ }
+ }
+
+ /* reports a finished range of primrefs */
+ if (unlikely(alloc_barrier))
+ reportFinishedRange(pinfo);
+
+ return node;
+ }
+
+ private:
+ Settings cfg;
+ PrimRef* prims;
+ const CreateAllocFunc& createAlloc;
+ const CreateAABBNodeFunc& createAABBNode;
+ const SetAABBNodeFunc& setAABBNode;
+ const CreateOBBNodeFunc& createOBBNode;
+ const SetOBBNodeFunc& setOBBNode;
+ const CreateLeafFunc& createLeaf;
+ const ProgressMonitor& progressMonitor;
+ const ReportFinishedRangeFunc& reportFinishedRange;
+
+ private:
+ HeuristicBinningSAH alignedHeuristic;
+ UnalignedHeuristicBinningSAH unalignedHeuristic;
+ HeuristicStrandSplitSAH strandHeuristic;
+ };
+
+ template<typename NodeRef,
+ typename CreateAllocFunc,
+ typename CreateAABBNodeFunc,
+ typename SetAABBNodeFunc,
+ typename CreateOBBNodeFunc,
+ typename SetOBBNodeFunc,
+ typename CreateLeafFunc,
+ typename ProgressMonitor,
+ typename ReportFinishedRangeFunc>
+
+ static NodeRef build (const CreateAllocFunc& createAlloc,
+ const CreateAABBNodeFunc& createAABBNode,
+ const SetAABBNodeFunc& setAABBNode,
+ const CreateOBBNodeFunc& createOBBNode,
+ const SetOBBNodeFunc& setOBBNode,
+ const CreateLeafFunc& createLeaf,
+ const ProgressMonitor& progressMonitor,
+ const ReportFinishedRangeFunc& reportFinishedRange,
+ Scene* scene,
+ PrimRef* prims,
+ const PrimInfo& pinfo,
+ const Settings settings)
+ {
+ typedef BuilderT<NodeRef,
+ CreateAllocFunc,
+ CreateAABBNodeFunc,SetAABBNodeFunc,
+ CreateOBBNodeFunc,SetOBBNodeFunc,
+ CreateLeafFunc,ProgressMonitor,
+ ReportFinishedRangeFunc> Builder;
+
+ Builder builder(scene,prims,createAlloc,
+ createAABBNode,setAABBNode,
+ createOBBNode,setOBBNode,
+ createLeaf,progressMonitor,reportFinishedRange,settings);
+
+ NodeRef root = builder.recurse(1,pinfo,nullptr,true,false);
+ _mm_mfence(); // to allow non-temporal stores during build
+ return root;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/bvh_builder_morton.h b/thirdparty/embree/kernels/builders/bvh_builder_morton.h
new file mode 100644
index 0000000000..8f21e3254f
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/bvh_builder_morton.h
@@ -0,0 +1,501 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/builder.h"
+#include "../../common/algorithms/parallel_reduce.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct BVHBuilderMorton
+ {
+ static const size_t MAX_BRANCHING_FACTOR = 8; //!< maximum supported BVH branching factor
+ static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree of we are that many levels before the maximum tree depth
+
+ /*! settings for morton builder */
+ struct Settings
+ {
+ /*! default settings */
+ Settings ()
+ : branchingFactor(2), maxDepth(32), minLeafSize(1), maxLeafSize(7), singleThreadThreshold(1024) {}
+
+ /*! initialize settings from API settings */
+ Settings (const RTCBuildArguments& settings)
+ : branchingFactor(2), maxDepth(32), minLeafSize(1), maxLeafSize(7), singleThreadThreshold(1024)
+ {
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,maxBranchingFactor)) branchingFactor = settings.maxBranchingFactor;
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,maxDepth )) maxDepth = settings.maxDepth;
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,minLeafSize )) minLeafSize = settings.minLeafSize;
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,maxLeafSize )) maxLeafSize = settings.maxLeafSize;
+
+ minLeafSize = min(minLeafSize,maxLeafSize);
+ }
+
+ Settings (size_t branchingFactor, size_t maxDepth, size_t minLeafSize, size_t maxLeafSize, size_t singleThreadThreshold)
+ : branchingFactor(branchingFactor), maxDepth(maxDepth), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize), singleThreadThreshold(singleThreadThreshold)
+ {
+ minLeafSize = min(minLeafSize,maxLeafSize);
+ }
+
+ public:
+ size_t branchingFactor; //!< branching factor of BVH to build
+ size_t maxDepth; //!< maximum depth of BVH to build
+ size_t minLeafSize; //!< minimum size of a leaf
+ size_t maxLeafSize; //!< maximum size of a leaf
+ size_t singleThreadThreshold; //!< threshold when we switch to single threaded build
+ };
+
+ /*! Build primitive consisting of morton code and primitive ID. */
+ struct __aligned(8) BuildPrim
+ {
+ union {
+ struct {
+ unsigned int code; //!< morton code
+ unsigned int index; //!< i'th primitive
+ };
+ uint64_t t;
+ };
+
+ /*! interface for radix sort */
+ __forceinline operator unsigned() const { return code; }
+
+ /*! interface for standard sort */
+ __forceinline bool operator<(const BuildPrim &m) const { return code < m.code; }
+ };
+
+ /*! maps bounding box to morton code */
+ struct MortonCodeMapping
+ {
+ static const size_t LATTICE_BITS_PER_DIM = 10;
+ static const size_t LATTICE_SIZE_PER_DIM = size_t(1) << LATTICE_BITS_PER_DIM;
+
+ vfloat4 base;
+ vfloat4 scale;
+
+ __forceinline MortonCodeMapping(const BBox3fa& bounds)
+ {
+ base = (vfloat4)bounds.lower;
+ const vfloat4 diag = (vfloat4)bounds.upper - (vfloat4)bounds.lower;
+ scale = select(diag > vfloat4(1E-19f), rcp(diag) * vfloat4(LATTICE_SIZE_PER_DIM * 0.99f),vfloat4(0.0f));
+ }
+
+ __forceinline const vint4 bin (const BBox3fa& box) const
+ {
+ const vfloat4 lower = (vfloat4)box.lower;
+ const vfloat4 upper = (vfloat4)box.upper;
+ const vfloat4 centroid = lower+upper;
+ return vint4((centroid-base)*scale);
+ }
+
+ __forceinline unsigned int code (const BBox3fa& box) const
+ {
+ const vint4 binID = bin(box);
+ const unsigned int x = extract<0>(binID);
+ const unsigned int y = extract<1>(binID);
+ const unsigned int z = extract<2>(binID);
+ const unsigned int xyz = bitInterleave(x,y,z);
+ return xyz;
+ }
+ };
+
+#if defined (__AVX2__)
+
+ /*! for AVX2 there is a fast scalar bitInterleave */
+ struct MortonCodeGenerator
+ {
+ __forceinline MortonCodeGenerator(const MortonCodeMapping& mapping, BuildPrim* dest)
+ : mapping(mapping), dest(dest) {}
+
+ __forceinline void operator() (const BBox3fa& b, const unsigned index)
+ {
+ dest->index = index;
+ dest->code = mapping.code(b);
+ dest++;
+ }
+
+ public:
+ const MortonCodeMapping mapping;
+ BuildPrim* dest;
+ size_t currentID;
+ };
+
+#else
+
+ /*! before AVX2 is it better to use the SSE version of bitInterleave */
+ struct MortonCodeGenerator
+ {
+ __forceinline MortonCodeGenerator(const MortonCodeMapping& mapping, BuildPrim* dest)
+ : mapping(mapping), dest(dest), currentID(0), slots(0), ax(0), ay(0), az(0), ai(0) {}
+
+ __forceinline ~MortonCodeGenerator()
+ {
+ if (slots != 0)
+ {
+ const vint4 code = bitInterleave(ax,ay,az);
+ for (size_t i=0; i<slots; i++) {
+ dest[currentID-slots+i].index = ai[i];
+ dest[currentID-slots+i].code = code[i];
+ }
+ }
+ }
+
+ __forceinline void operator() (const BBox3fa& b, const unsigned index)
+ {
+ const vint4 binID = mapping.bin(b);
+ ax[slots] = extract<0>(binID);
+ ay[slots] = extract<1>(binID);
+ az[slots] = extract<2>(binID);
+ ai[slots] = index;
+ slots++;
+ currentID++;
+
+ if (slots == 4)
+ {
+ const vint4 code = bitInterleave(ax,ay,az);
+ vint4::storeu(&dest[currentID-4],unpacklo(code,ai));
+ vint4::storeu(&dest[currentID-2],unpackhi(code,ai));
+ slots = 0;
+ }
+ }
+
+ public:
+ const MortonCodeMapping mapping;
+ BuildPrim* dest;
+ size_t currentID;
+ size_t slots;
+ vint4 ax, ay, az, ai;
+ };
+
+#endif
+
+ template<
+ typename ReductionTy,
+ typename Allocator,
+ typename CreateAllocator,
+ typename CreateNodeFunc,
+ typename SetNodeBoundsFunc,
+ typename CreateLeafFunc,
+ typename CalculateBounds,
+ typename ProgressMonitor>
+
+ class BuilderT : private Settings
+ {
+ ALIGNED_CLASS_(16);
+
+ public:
+
+ BuilderT (CreateAllocator& createAllocator,
+ CreateNodeFunc& createNode,
+ SetNodeBoundsFunc& setBounds,
+ CreateLeafFunc& createLeaf,
+ CalculateBounds& calculateBounds,
+ ProgressMonitor& progressMonitor,
+ const Settings& settings)
+
+ : Settings(settings),
+ createAllocator(createAllocator),
+ createNode(createNode),
+ setBounds(setBounds),
+ createLeaf(createLeaf),
+ calculateBounds(calculateBounds),
+ progressMonitor(progressMonitor),
+ morton(nullptr) {}
+
+ ReductionTy createLargeLeaf(size_t depth, const range<unsigned>& current, Allocator alloc)
+ {
+ /* this should never occur but is a fatal error */
+ if (depth > maxDepth)
+ throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
+
+ /* create leaf for few primitives */
+ if (current.size() <= maxLeafSize)
+ return createLeaf(current,alloc);
+
+ /* fill all children by always splitting the largest one */
+ range<unsigned> children[MAX_BRANCHING_FACTOR];
+ size_t numChildren = 1;
+ children[0] = current;
+
+ do {
+
+ /* find best child with largest number of primitives */
+ size_t bestChild = -1;
+ size_t bestSize = 0;
+ for (size_t i=0; i<numChildren; i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].size() <= maxLeafSize)
+ continue;
+
+ /* remember child with largest size */
+ if (children[i].size() > bestSize) {
+ bestSize = children[i].size();
+ bestChild = i;
+ }
+ }
+ if (bestChild == size_t(-1)) break;
+
+ /*! split best child into left and right child */
+ auto split = children[bestChild].split();
+
+ /* add new children left and right */
+ children[bestChild] = children[numChildren-1];
+ children[numChildren-1] = split.first;
+ children[numChildren+0] = split.second;
+ numChildren++;
+
+ } while (numChildren < branchingFactor);
+
+ /* create node */
+ auto node = createNode(alloc,numChildren);
+
+ /* recurse into each child */
+ ReductionTy bounds[MAX_BRANCHING_FACTOR];
+ for (size_t i=0; i<numChildren; i++)
+ bounds[i] = createLargeLeaf(depth+1,children[i],alloc);
+
+ return setBounds(node,bounds,numChildren);
+ }
+
+ /*! recreates morton codes when reaching a region where all codes are identical */
+ __noinline void recreateMortonCodes(const range<unsigned>& current) const
+ {
+ /* fast path for small ranges */
+ if (likely(current.size() < 1024))
+ {
+ /*! recalculate centroid bounds */
+ BBox3fa centBounds(empty);
+ for (size_t i=current.begin(); i<current.end(); i++)
+ centBounds.extend(center2(calculateBounds(morton[i])));
+
+ /* recalculate morton codes */
+ MortonCodeMapping mapping(centBounds);
+ for (size_t i=current.begin(); i<current.end(); i++)
+ morton[i].code = mapping.code(calculateBounds(morton[i]));
+
+ /* sort morton codes */
+ std::sort(morton+current.begin(),morton+current.end());
+ }
+ else
+ {
+ /*! recalculate centroid bounds */
+ auto calculateCentBounds = [&] ( const range<unsigned>& r ) {
+ BBox3fa centBounds = empty;
+ for (size_t i=r.begin(); i<r.end(); i++)
+ centBounds.extend(center2(calculateBounds(morton[i])));
+ return centBounds;
+ };
+ const BBox3fa centBounds = parallel_reduce(current.begin(), current.end(), unsigned(1024),
+ BBox3fa(empty), calculateCentBounds, BBox3fa::merge);
+
+ /* recalculate morton codes */
+ MortonCodeMapping mapping(centBounds);
+ parallel_for(current.begin(), current.end(), unsigned(1024), [&] ( const range<unsigned>& r ) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ morton[i].code = mapping.code(calculateBounds(morton[i]));
+ }
+ });
+
+ /*! sort morton codes */
+#if defined(TASKING_TBB)
+ tbb::parallel_sort(morton+current.begin(),morton+current.end());
+#else
+ radixsort32(morton+current.begin(),current.size());
+#endif
+ }
+ }
+
+ __forceinline void split(const range<unsigned>& current, range<unsigned>& left, range<unsigned>& right) const
+ {
+ const unsigned int code_start = morton[current.begin()].code;
+ const unsigned int code_end = morton[current.end()-1].code;
+ unsigned int bitpos = lzcnt(code_start^code_end);
+
+ /* if all items mapped to same morton code, then re-create new morton codes for the items */
+ if (unlikely(bitpos == 32))
+ {
+ recreateMortonCodes(current);
+ const unsigned int code_start = morton[current.begin()].code;
+ const unsigned int code_end = morton[current.end()-1].code;
+ bitpos = lzcnt(code_start^code_end);
+
+ /* if the morton code is still the same, goto fall back split */
+ if (unlikely(bitpos == 32)) {
+ current.split(left,right);
+ return;
+ }
+ }
+
+ /* split the items at the topmost different morton code bit */
+ const unsigned int bitpos_diff = 31-bitpos;
+ const unsigned int bitmask = 1 << bitpos_diff;
+
+ /* find location where bit differs using binary search */
+ unsigned begin = current.begin();
+ unsigned end = current.end();
+ while (begin + 1 != end) {
+ const unsigned mid = (begin+end)/2;
+ const unsigned bit = morton[mid].code & bitmask;
+ if (bit == 0) begin = mid; else end = mid;
+ }
+ unsigned center = end;
+#if defined(DEBUG)
+ for (unsigned int i=begin; i<center; i++) assert((morton[i].code & bitmask) == 0);
+ for (unsigned int i=center; i<end; i++) assert((morton[i].code & bitmask) == bitmask);
+#endif
+
+ left = make_range(current.begin(),center);
+ right = make_range(center,current.end());
+ }
+
+ ReductionTy recurse(size_t depth, const range<unsigned>& current, Allocator alloc, bool toplevel)
+ {
+ /* get thread local allocator */
+ if (!alloc)
+ alloc = createAllocator();
+
+ /* call memory monitor function to signal progress */
+ if (toplevel && current.size() <= singleThreadThreshold)
+ progressMonitor(current.size());
+
+ /* create leaf node */
+ if (unlikely(depth+MIN_LARGE_LEAF_LEVELS >= maxDepth || current.size() <= minLeafSize))
+ return createLargeLeaf(depth,current,alloc);
+
+ /* fill all children by always splitting the one with the largest surface area */
+ range<unsigned> children[MAX_BRANCHING_FACTOR];
+ split(current,children[0],children[1]);
+ size_t numChildren = 2;
+
+ while (numChildren < branchingFactor)
+ {
+ /* find best child with largest number of primitives */
+ int bestChild = -1;
+ unsigned bestItems = 0;
+ for (unsigned int i=0; i<numChildren; i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].size() <= minLeafSize)
+ continue;
+
+ /* remember child with largest area */
+ if (children[i].size() > bestItems) {
+ bestItems = children[i].size();
+ bestChild = i;
+ }
+ }
+ if (bestChild == -1) break;
+
+ /*! split best child into left and right child */
+ range<unsigned> left, right;
+ split(children[bestChild],left,right);
+
+ /* add new children left and right */
+ children[bestChild] = children[numChildren-1];
+ children[numChildren-1] = left;
+ children[numChildren+0] = right;
+ numChildren++;
+ }
+
+ /* create leaf node if no split is possible */
+ if (unlikely(numChildren == 1))
+ return createLeaf(current,alloc);
+
+ /* allocate node */
+ auto node = createNode(alloc,numChildren);
+
+ /* process top parts of tree parallel */
+ ReductionTy bounds[MAX_BRANCHING_FACTOR];
+ if (current.size() > singleThreadThreshold)
+ {
+ /*! parallel_for is faster than spawing sub-tasks */
+ parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ bounds[i] = recurse(depth+1,children[i],nullptr,true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ }
+ });
+ }
+
+ /* finish tree sequentially */
+ else
+ {
+ for (size_t i=0; i<numChildren; i++)
+ bounds[i] = recurse(depth+1,children[i],alloc,false);
+ }
+
+ return setBounds(node,bounds,numChildren);
+ }
+
+ /* build function */
+ ReductionTy build(BuildPrim* src, BuildPrim* tmp, size_t numPrimitives)
+ {
+ /* sort morton codes */
+ morton = src;
+ radix_sort_u32(src,tmp,numPrimitives,singleThreadThreshold);
+
+ /* build BVH */
+ const ReductionTy root = recurse(1, range<unsigned>(0,(unsigned)numPrimitives), nullptr, true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ return root;
+ }
+
+ public:
+ CreateAllocator& createAllocator;
+ CreateNodeFunc& createNode;
+ SetNodeBoundsFunc& setBounds;
+ CreateLeafFunc& createLeaf;
+ CalculateBounds& calculateBounds;
+ ProgressMonitor& progressMonitor;
+
+ public:
+ BuildPrim* morton;
+ };
+
+
+ template<
+ typename ReductionTy,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename SetBoundsFunc,
+ typename CreateLeafFunc,
+ typename CalculateBoundsFunc,
+ typename ProgressMonitor>
+
+ static ReductionTy build(CreateAllocFunc createAllocator,
+ CreateNodeFunc createNode,
+ SetBoundsFunc setBounds,
+ CreateLeafFunc createLeaf,
+ CalculateBoundsFunc calculateBounds,
+ ProgressMonitor progressMonitor,
+ BuildPrim* src,
+ BuildPrim* tmp,
+ size_t numPrimitives,
+ const Settings& settings)
+ {
+ typedef BuilderT<
+ ReductionTy,
+ decltype(createAllocator()),
+ CreateAllocFunc,
+ CreateNodeFunc,
+ SetBoundsFunc,
+ CreateLeafFunc,
+ CalculateBoundsFunc,
+ ProgressMonitor> Builder;
+
+ Builder builder(createAllocator,
+ createNode,
+ setBounds,
+ createLeaf,
+ calculateBounds,
+ progressMonitor,
+ settings);
+
+ return builder.build(src,tmp,numPrimitives);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/bvh_builder_msmblur.h b/thirdparty/embree/kernels/builders/bvh_builder_msmblur.h
new file mode 100644
index 0000000000..f9a08d65cd
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/bvh_builder_msmblur.h
@@ -0,0 +1,692 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#define MBLUR_NUM_TEMPORAL_BINS 2
+#define MBLUR_NUM_OBJECT_BINS 32
+
+#include "../bvh/bvh.h"
+#include "../common/primref_mb.h"
+#include "heuristic_binning_array_aligned.h"
+#include "heuristic_timesplit_array.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename T>
+ struct SharedVector
+ {
+ __forceinline SharedVector() {}
+
+ __forceinline SharedVector(T* ptr, size_t refCount = 1)
+ : prims(ptr), refCount(refCount) {}
+
+ __forceinline void incRef() {
+ refCount++;
+ }
+
+ __forceinline void decRef()
+ {
+ if (--refCount == 0)
+ delete prims;
+ }
+
+ T* prims;
+ size_t refCount;
+ };
+
+ template<typename BuildRecord, int MAX_BRANCHING_FACTOR>
+ struct LocalChildListT
+ {
+ typedef SharedVector<mvector<PrimRefMB>> SharedPrimRefVector;
+
+ __forceinline LocalChildListT (const BuildRecord& record)
+ : numChildren(1), numSharedPrimVecs(1)
+ {
+ /* the local root will be freed in the ancestor where it was created (thus refCount is 2) */
+ children[0] = record;
+ primvecs[0] = new (&sharedPrimVecs[0]) SharedPrimRefVector(record.prims.prims, 2);
+ }
+
+ __forceinline ~LocalChildListT()
+ {
+ for (size_t i = 0; i < numChildren; i++)
+ primvecs[i]->decRef();
+ }
+
+ __forceinline BuildRecord& operator[] ( const size_t i ) {
+ return children[i];
+ }
+
+ __forceinline size_t size() const {
+ return numChildren;
+ }
+
+ __forceinline void split(ssize_t bestChild, const BuildRecord& lrecord, const BuildRecord& rrecord, std::unique_ptr<mvector<PrimRefMB>> new_vector)
+ {
+ SharedPrimRefVector* bsharedPrimVec = primvecs[bestChild];
+ if (lrecord.prims.prims == bsharedPrimVec->prims) {
+ primvecs[bestChild] = bsharedPrimVec;
+ bsharedPrimVec->incRef();
+ }
+ else {
+ primvecs[bestChild] = new (&sharedPrimVecs[numSharedPrimVecs++]) SharedPrimRefVector(lrecord.prims.prims);
+ }
+
+ if (rrecord.prims.prims == bsharedPrimVec->prims) {
+ primvecs[numChildren] = bsharedPrimVec;
+ bsharedPrimVec->incRef();
+ }
+ else {
+ primvecs[numChildren] = new (&sharedPrimVecs[numSharedPrimVecs++]) SharedPrimRefVector(rrecord.prims.prims);
+ }
+ bsharedPrimVec->decRef();
+ new_vector.release();
+
+ children[bestChild] = lrecord;
+ children[numChildren] = rrecord;
+ numChildren++;
+ }
+
+ public:
+ array_t<BuildRecord,MAX_BRANCHING_FACTOR> children;
+ array_t<SharedPrimRefVector*,MAX_BRANCHING_FACTOR> primvecs;
+ size_t numChildren;
+
+ array_t<SharedPrimRefVector,2*MAX_BRANCHING_FACTOR> sharedPrimVecs;
+ size_t numSharedPrimVecs;
+ };
+
+ template<typename Mesh>
+ struct RecalculatePrimRef
+ {
+ Scene* scene;
+
+ __forceinline RecalculatePrimRef (Scene* scene)
+ : scene(scene) {}
+
+ __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const
+ {
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const Mesh* mesh = scene->get<Mesh>(geomID);
+ const LBBox3fa lbounds = mesh->linearBounds(primID, time_range);
+ const range<int> tbounds = mesh->timeSegmentRange(time_range);
+ return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
+ }
+
+ // __noinline is workaround for ICC16 bug under MacOSX
+ __noinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const
+ {
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const Mesh* mesh = scene->get<Mesh>(geomID);
+ const LBBox3fa lbounds = mesh->linearBounds(space, primID, time_range);
+ const range<int> tbounds = mesh->timeSegmentRange(time_range);
+ return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
+ }
+
+ __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
+ return scene->get<Mesh>(prim.geomID())->linearBounds(prim.primID(), time_range);
+ }
+
+ // __noinline is workaround for ICC16 bug under MacOSX
+ __noinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const {
+ return scene->get<Mesh>(prim.geomID())->linearBounds(space, prim.primID(), time_range);
+ }
+ };
+
+ struct VirtualRecalculatePrimRef
+ {
+ Scene* scene;
+
+ __forceinline VirtualRecalculatePrimRef (Scene* scene)
+ : scene(scene) {}
+
+ __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const
+ {
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const Geometry* mesh = scene->get(geomID);
+ const LBBox3fa lbounds = mesh->vlinearBounds(primID, time_range);
+ const range<int> tbounds = mesh->timeSegmentRange(time_range);
+ return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
+ }
+
+ __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const
+ {
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const Geometry* mesh = scene->get(geomID);
+ const LBBox3fa lbounds = mesh->vlinearBounds(space, primID, time_range);
+ const range<int> tbounds = mesh->timeSegmentRange(time_range);
+ return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, mesh->numTimeSegments(), geomID, primID);
+ }
+
+ __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
+ return scene->get(prim.geomID())->vlinearBounds(prim.primID(), time_range);
+ }
+
+ __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range, const LinearSpace3fa& space) const {
+ return scene->get(prim.geomID())->vlinearBounds(space, prim.primID(), time_range);
+ }
+ };
+
+ struct BVHBuilderMSMBlur
+ {
+ /*! settings for msmblur builder */
+ struct Settings
+ {
+ /*! default settings */
+ Settings ()
+ : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8),
+ travCost(1.0f), intCost(1.0f), singleLeafTimeSegment(false),
+ singleThreadThreshold(1024) {}
+
+
+ Settings (size_t sahBlockSize, size_t minLeafSize, size_t maxLeafSize, float travCost, float intCost, size_t singleThreadThreshold)
+ : branchingFactor(2), maxDepth(32), logBlockSize(bsr(sahBlockSize)), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize),
+ travCost(travCost), intCost(intCost), singleThreadThreshold(singleThreadThreshold)
+ {
+ minLeafSize = min(minLeafSize,maxLeafSize);
+ }
+
+ public:
+ size_t branchingFactor; //!< branching factor of BVH to build
+ size_t maxDepth; //!< maximum depth of BVH to build
+ size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
+ size_t minLeafSize; //!< minimum size of a leaf
+ size_t maxLeafSize; //!< maximum size of a leaf
+ float travCost; //!< estimated cost of one traversal step
+ float intCost; //!< estimated cost of one primitive intersection
+ bool singleLeafTimeSegment; //!< split time to single time range
+ size_t singleThreadThreshold; //!< threshold when we switch to single threaded build
+ };
+
+ struct BuildRecord
+ {
+ public:
+ __forceinline BuildRecord () {}
+
+ __forceinline BuildRecord (size_t depth)
+ : depth(depth) {}
+
+ __forceinline BuildRecord (const SetMB& prims, size_t depth)
+ : depth(depth), prims(prims) {}
+
+ __forceinline friend bool operator< (const BuildRecord& a, const BuildRecord& b) {
+ return a.prims.size() < b.prims.size();
+ }
+
+ __forceinline size_t size() const {
+ return prims.size();
+ }
+
+ public:
+ size_t depth; //!< Depth of the root of this subtree.
+ SetMB prims; //!< The list of primitives.
+ };
+
+ struct BuildRecordSplit : public BuildRecord
+ {
+ __forceinline BuildRecordSplit () {}
+
+ __forceinline BuildRecordSplit (size_t depth)
+ : BuildRecord(depth) {}
+
+ __forceinline BuildRecordSplit (const BuildRecord& record, const BinSplit<MBLUR_NUM_OBJECT_BINS>& split)
+ : BuildRecord(record), split(split) {}
+
+ BinSplit<MBLUR_NUM_OBJECT_BINS> split;
+ };
+
+ template<
+ typename NodeRef,
+ typename RecalculatePrimRef,
+ typename Allocator,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename SetNodeFunc,
+ typename CreateLeafFunc,
+ typename ProgressMonitor>
+
+ class BuilderT
+ {
+ ALIGNED_CLASS_(16);
+ static const size_t MAX_BRANCHING_FACTOR = 16; //!< maximum supported BVH branching factor
+ static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree if we are that many levels before the maximum tree depth
+
+ typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
+ typedef BinSplit<MBLUR_NUM_OBJECT_BINS> Split;
+ typedef mvector<PrimRefMB>* PrimRefVector;
+ typedef SharedVector<mvector<PrimRefMB>> SharedPrimRefVector;
+ typedef LocalChildListT<BuildRecord,MAX_BRANCHING_FACTOR> LocalChildList;
+ typedef LocalChildListT<BuildRecordSplit,MAX_BRANCHING_FACTOR> LocalChildListSplit;
+
+ public:
+
+ BuilderT (MemoryMonitorInterface* device,
+ const RecalculatePrimRef recalculatePrimRef,
+ const CreateAllocFunc createAlloc,
+ const CreateNodeFunc createNode,
+ const SetNodeFunc setNode,
+ const CreateLeafFunc createLeaf,
+ const ProgressMonitor progressMonitor,
+ const Settings& settings)
+ : cfg(settings),
+ heuristicObjectSplit(),
+ heuristicTemporalSplit(device, recalculatePrimRef),
+ recalculatePrimRef(recalculatePrimRef), createAlloc(createAlloc), createNode(createNode), setNode(setNode), createLeaf(createLeaf),
+ progressMonitor(progressMonitor)
+ {
+ if (cfg.branchingFactor > MAX_BRANCHING_FACTOR)
+ throw_RTCError(RTC_ERROR_UNKNOWN,"bvh_builder: branching factor too large");
+ }
+
+ /*! finds the best split */
+ const Split find(const SetMB& set)
+ {
+ /* first try standard object split */
+ const Split object_split = heuristicObjectSplit.find(set,cfg.logBlockSize);
+ const float object_split_sah = object_split.splitSAH();
+
+ /* test temporal splits only when object split was bad */
+ const float leaf_sah = set.leafSAH(cfg.logBlockSize);
+ if (object_split_sah < 0.50f*leaf_sah)
+ return object_split;
+
+ /* do temporal splits only if the time range is big enough */
+ if (set.time_range.size() > 1.01f/float(set.max_num_time_segments))
+ {
+ const Split temporal_split = heuristicTemporalSplit.find(set,cfg.logBlockSize);
+ const float temporal_split_sah = temporal_split.splitSAH();
+
+ /* take temporal split if it improved SAH */
+ if (temporal_split_sah < object_split_sah)
+ return temporal_split;
+ }
+
+ return object_split;
+ }
+
+ /*! array partitioning */
+ __forceinline std::unique_ptr<mvector<PrimRefMB>> split(const Split& split, const SetMB& set, SetMB& lset, SetMB& rset)
+ {
+ /* perform object split */
+ if (likely(split.data == Split::SPLIT_OBJECT)) {
+ heuristicObjectSplit.split(split,set,lset,rset);
+ }
+ /* perform temporal split */
+ else if (likely(split.data == Split::SPLIT_TEMPORAL)) {
+ return heuristicTemporalSplit.split(split,set,lset,rset);
+ }
+ /* perform fallback split */
+ else if (unlikely(split.data == Split::SPLIT_FALLBACK)) {
+ set.deterministic_order();
+ splitFallback(set,lset,rset);
+ }
+ /* split by geometry */
+ else if (unlikely(split.data == Split::SPLIT_GEOMID)) {
+ set.deterministic_order();
+ splitByGeometry(set,lset,rset);
+ }
+ else
+ assert(false);
+
+ return std::unique_ptr<mvector<PrimRefMB>>();
+ }
+
+ /*! finds the best fallback split */
+ __noinline Split findFallback(const SetMB& set)
+ {
+ /* split if primitives are not from same geometry */
+ if (!sameGeometry(set))
+ return Split(0.0f,Split::SPLIT_GEOMID);
+
+ /* if a leaf can only hold a single time-segment, we might have to do additional temporal splits */
+ if (cfg.singleLeafTimeSegment)
+ {
+ /* test if one primitive has more than one time segment in time range, if so split time */
+ for (size_t i=set.begin(); i<set.end(); i++)
+ {
+ const PrimRefMB& prim = (*set.prims)[i];
+ const range<int> itime_range = prim.timeSegmentRange(set.time_range);
+ const int localTimeSegments = itime_range.size();
+ assert(localTimeSegments > 0);
+ if (localTimeSegments > 1) {
+ const int icenter = (itime_range.begin() + itime_range.end())/2;
+ const float splitTime = prim.timeStep(icenter);
+ return Split(0.0f,(unsigned)Split::SPLIT_TEMPORAL,0,splitTime);
+ }
+ }
+ }
+
+ /* otherwise return fallback split */
+ return Split(0.0f,Split::SPLIT_FALLBACK);
+ }
+
+ /*! performs fallback split */
+ void splitFallback(const SetMB& set, SetMB& lset, SetMB& rset)
+ {
+ mvector<PrimRefMB>& prims = *set.prims;
+
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ const size_t center = (begin + end)/2;
+
+ PrimInfoMB linfo = empty;
+ for (size_t i=begin; i<center; i++)
+ linfo.add_primref(prims[i]);
+
+ PrimInfoMB rinfo = empty;
+ for (size_t i=center; i<end; i++)
+ rinfo.add_primref(prims[i]);
+
+ new (&lset) SetMB(linfo,set.prims,range<size_t>(begin,center),set.time_range);
+ new (&rset) SetMB(rinfo,set.prims,range<size_t>(center,end ),set.time_range);
+ }
+
+ /*! checks if all primitives are from the same geometry */
+ __forceinline bool sameGeometry(const SetMB& set)
+ {
+ if (set.size() == 0) return true;
+ mvector<PrimRefMB>& prims = *set.prims;
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ unsigned int firstGeomID = prims[begin].geomID();
+ for (size_t i=begin+1; i<end; i++) {
+ if (prims[i].geomID() != firstGeomID){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* split by geometry ID */
+ void splitByGeometry(const SetMB& set, SetMB& lset, SetMB& rset)
+ {
+ assert(set.size() > 1);
+
+ mvector<PrimRefMB>& prims = *set.prims;
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+
+ PrimInfoMB left(empty);
+ PrimInfoMB right(empty);
+ unsigned int geomID = prims[begin].geomID();
+ size_t center = serial_partitioning(prims.data(),begin,end,left,right,
+ [&] ( const PrimRefMB& prim ) { return prim.geomID() == geomID; },
+ [ ] ( PrimInfoMB& dst, const PrimRefMB& prim ) { dst.add_primref(prim); });
+
+ new (&lset) SetMB(left, set.prims,range<size_t>(begin,center),set.time_range);
+ new (&rset) SetMB(right,set.prims,range<size_t>(center,end ),set.time_range);
+ }
+
+ const NodeRecordMB4D createLargeLeaf(const BuildRecord& in, Allocator alloc)
+ {
+ /* this should never occur but is a fatal error */
+ if (in.depth > cfg.maxDepth)
+ throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
+
+ /* replace already found split by fallback split */
+ const BuildRecordSplit current(BuildRecord(in.prims,in.depth),findFallback(in.prims));
+
+ /* special case when directly creating leaf without any splits that could shrink time_range */
+ bool force_split = false;
+ if (current.depth == 1 && current.size() > 0)
+ {
+ BBox1f c = empty;
+ BBox1f p = current.prims.time_range;
+ for (size_t i=current.prims.begin(); i<current.prims.end(); i++) {
+ mvector<PrimRefMB>& prims = *current.prims.prims;
+ c.extend(prims[i].time_range);
+ }
+
+ force_split = c.lower > p.lower || c.upper < p.upper;
+ }
+
+ /* create leaf for few primitives */
+ if (current.size() <= cfg.maxLeafSize && current.split.data < Split::SPLIT_ENFORCE && !force_split)
+ return createLeaf(current,alloc);
+
+ /* fill all children by always splitting the largest one */
+ bool hasTimeSplits = false;
+ NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
+ LocalChildListSplit children(current);
+
+ do {
+ /* find best child with largest bounding box area */
+ size_t bestChild = -1;
+ size_t bestSize = 0;
+ for (size_t i=0; i<children.size(); i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].size() <= cfg.maxLeafSize && children[i].split.data < Split::SPLIT_ENFORCE && !force_split)
+ continue;
+
+ force_split = false;
+
+ /* remember child with largest size */
+ if (children[i].size() > bestSize) {
+ bestSize = children[i].size();
+ bestChild = i;
+ }
+ }
+ if (bestChild == -1) break;
+
+ /* perform best found split */
+ BuildRecordSplit& brecord = children[bestChild];
+ BuildRecordSplit lrecord(current.depth+1);
+ BuildRecordSplit rrecord(current.depth+1);
+ std::unique_ptr<mvector<PrimRefMB>> new_vector = split(brecord.split,brecord.prims,lrecord.prims,rrecord.prims);
+ hasTimeSplits |= new_vector != nullptr;
+
+ /* find new splits */
+ lrecord.split = findFallback(lrecord.prims);
+ rrecord.split = findFallback(rrecord.prims);
+ children.split(bestChild,lrecord,rrecord,std::move(new_vector));
+
+ } while (children.size() < cfg.branchingFactor);
+
+ /* detect time_ranges that have shrunken */
+ for (size_t i=0; i<children.size(); i++) {
+ const BBox1f c = children[i].prims.time_range;
+ const BBox1f p = in.prims.time_range;
+ hasTimeSplits |= c.lower > p.lower || c.upper < p.upper;
+ }
+
+ /* create node */
+ auto node = createNode(children.children.data(),children.numChildren,alloc,hasTimeSplits);
+
+ /* recurse into each child and perform reduction */
+ LBBox3fa gbounds = empty;
+ for (size_t i=0; i<children.size(); i++) {
+ values[i] = createLargeLeaf(children[i],alloc);
+ gbounds.extend(values[i].lbounds);
+ }
+
+ setNode(current,children.children.data(),node,values,children.numChildren);
+
+ /* calculate geometry bounds of this node */
+ if (hasTimeSplits)
+ return NodeRecordMB4D(node,current.prims.linearBounds(recalculatePrimRef),current.prims.time_range);
+ else
+ return NodeRecordMB4D(node,gbounds,current.prims.time_range);
+ }
+
+ const NodeRecordMB4D recurse(const BuildRecord& current, Allocator alloc, bool toplevel)
+ {
+ /* get thread local allocator */
+ if (!alloc)
+ alloc = createAlloc();
+
+ /* call memory monitor function to signal progress */
+ if (toplevel && current.size() <= cfg.singleThreadThreshold)
+ progressMonitor(current.size());
+
+ /*! find best split */
+ const Split csplit = find(current.prims);
+
+ /*! compute leaf and split cost */
+ const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.logBlockSize);
+ const float splitSAH = cfg.travCost*current.prims.halfArea()+cfg.intCost*csplit.splitSAH();
+ assert((current.size() == 0) || ((leafSAH >= 0) && (splitSAH >= 0)));
+
+ /*! create a leaf node when threshold reached or SAH tells us to stop */
+ if (current.size() <= cfg.minLeafSize || current.depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || (current.size() <= cfg.maxLeafSize && leafSAH <= splitSAH)) {
+ current.prims.deterministic_order();
+ return createLargeLeaf(current,alloc);
+ }
+
+ /*! perform initial split */
+ SetMB lprims,rprims;
+ std::unique_ptr<mvector<PrimRefMB>> new_vector = split(csplit,current.prims,lprims,rprims);
+ bool hasTimeSplits = new_vector != nullptr;
+ NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
+ LocalChildList children(current);
+ {
+ BuildRecord lrecord(lprims,current.depth+1);
+ BuildRecord rrecord(rprims,current.depth+1);
+ children.split(0,lrecord,rrecord,std::move(new_vector));
+ }
+
+ /*! split until node is full or SAH tells us to stop */
+ while (children.size() < cfg.branchingFactor)
+ {
+ /*! find best child to split */
+ float bestArea = neg_inf;
+ ssize_t bestChild = -1;
+ for (size_t i=0; i<children.size(); i++)
+ {
+ if (children[i].size() <= cfg.minLeafSize) continue;
+ if (expectedApproxHalfArea(children[i].prims.geomBounds) > bestArea) {
+ bestChild = i; bestArea = expectedApproxHalfArea(children[i].prims.geomBounds);
+ }
+ }
+ if (bestChild == -1) break;
+
+ /* perform split */
+ BuildRecord& brecord = children[bestChild];
+ BuildRecord lrecord(current.depth+1);
+ BuildRecord rrecord(current.depth+1);
+ Split csplit = find(brecord.prims);
+ std::unique_ptr<mvector<PrimRefMB>> new_vector = split(csplit,brecord.prims,lrecord.prims,rrecord.prims);
+ hasTimeSplits |= new_vector != nullptr;
+ children.split(bestChild,lrecord,rrecord,std::move(new_vector));
+ }
+
+ /* detect time_ranges that have shrunken */
+ for (size_t i=0; i<children.size(); i++) {
+ const BBox1f c = children[i].prims.time_range;
+ const BBox1f p = current.prims.time_range;
+ hasTimeSplits |= c.lower > p.lower || c.upper < p.upper;
+ }
+
+ /* sort buildrecords for simpler shadow ray traversal */
+ //std::sort(&children[0],&children[children.size()],std::greater<BuildRecord>()); // FIXME: reduces traversal performance of bvh8.triangle4 (need to verified) !!
+
+ /*! create an inner node */
+ auto node = createNode(children.children.data(), children.numChildren, alloc, hasTimeSplits);
+ LBBox3fa gbounds = empty;
+
+ /* spawn tasks */
+ if (unlikely(current.size() > cfg.singleThreadThreshold))
+ {
+ /*! parallel_for is faster than spawing sub-tasks */
+ parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ values[i] = recurse(children[i],nullptr,true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ }
+ });
+
+ /*! merge bounding boxes */
+ for (size_t i=0; i<children.size(); i++)
+ gbounds.extend(values[i].lbounds);
+ }
+ /* recurse into each child */
+ else
+ {
+ //for (size_t i=0; i<children.size(); i++)
+ for (ssize_t i=children.size()-1; i>=0; i--) {
+ values[i] = recurse(children[i],alloc,false);
+ gbounds.extend(values[i].lbounds);
+ }
+ }
+
+ setNode(current,children.children.data(),node,values,children.numChildren);
+
+ /* calculate geometry bounds of this node */
+ if (unlikely(hasTimeSplits))
+ return NodeRecordMB4D(node,current.prims.linearBounds(recalculatePrimRef),current.prims.time_range);
+ else
+ return NodeRecordMB4D(node,gbounds,current.prims.time_range);
+ }
+
+ /*! builder entry function */
+ __forceinline const NodeRecordMB4D operator() (mvector<PrimRefMB>& prims, const PrimInfoMB& pinfo)
+ {
+ const SetMB set(pinfo,&prims);
+ auto ret = recurse(BuildRecord(set,1),nullptr,true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ return ret;
+ }
+
+ private:
+ Settings cfg;
+ HeuristicArrayBinningMB<PrimRefMB,MBLUR_NUM_OBJECT_BINS> heuristicObjectSplit;
+ HeuristicMBlurTemporalSplit<PrimRefMB,RecalculatePrimRef,MBLUR_NUM_TEMPORAL_BINS> heuristicTemporalSplit;
+ const RecalculatePrimRef recalculatePrimRef;
+ const CreateAllocFunc createAlloc;
+ const CreateNodeFunc createNode;
+ const SetNodeFunc setNode;
+ const CreateLeafFunc createLeaf;
+ const ProgressMonitor progressMonitor;
+ };
+
+ template<typename NodeRef,
+ typename RecalculatePrimRef,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename SetNodeFunc,
+ typename CreateLeafFunc,
+ typename ProgressMonitorFunc>
+
+ static const BVHNodeRecordMB4D<NodeRef> build(mvector<PrimRefMB>& prims,
+ const PrimInfoMB& pinfo,
+ MemoryMonitorInterface* device,
+ const RecalculatePrimRef recalculatePrimRef,
+ const CreateAllocFunc createAlloc,
+ const CreateNodeFunc createNode,
+ const SetNodeFunc setNode,
+ const CreateLeafFunc createLeaf,
+ const ProgressMonitorFunc progressMonitor,
+ const Settings& settings)
+ {
+ typedef BuilderT<
+ NodeRef,
+ RecalculatePrimRef,
+ decltype(createAlloc()),
+ CreateAllocFunc,
+ CreateNodeFunc,
+ SetNodeFunc,
+ CreateLeafFunc,
+ ProgressMonitorFunc> Builder;
+
+ Builder builder(device,
+ recalculatePrimRef,
+ createAlloc,
+ createNode,
+ setNode,
+ createLeaf,
+ progressMonitor,
+ settings);
+
+
+ return builder(prims,pinfo);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/bvh_builder_msmblur_hair.h b/thirdparty/embree/kernels/builders/bvh_builder_msmblur_hair.h
new file mode 100644
index 0000000000..397e8636b1
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/bvh_builder_msmblur_hair.h
@@ -0,0 +1,526 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../bvh/bvh.h"
+#include "../geometry/primitive.h"
+#include "../builders/bvh_builder_msmblur.h"
+#include "../builders/heuristic_binning_array_aligned.h"
+#include "../builders/heuristic_binning_array_unaligned.h"
+#include "../builders/heuristic_timesplit_array.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct BVHBuilderHairMSMBlur
+ {
+ /*! settings for msmblur builder */
+ struct Settings
+ {
+ /*! default settings */
+ Settings ()
+ : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(8) {}
+
+ public:
+ size_t branchingFactor; //!< branching factor of BVH to build
+ size_t maxDepth; //!< maximum depth of BVH to build
+ size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
+ size_t minLeafSize; //!< minimum size of a leaf
+ size_t maxLeafSize; //!< maximum size of a leaf
+ };
+
+ struct BuildRecord
+ {
+ public:
+ __forceinline BuildRecord () {}
+
+ __forceinline BuildRecord (size_t depth)
+ : depth(depth) {}
+
+ __forceinline BuildRecord (const SetMB& prims, size_t depth)
+ : depth(depth), prims(prims) {}
+
+ __forceinline size_t size() const {
+ return prims.size();
+ }
+
+ public:
+ size_t depth; //!< depth of the root of this subtree
+ SetMB prims; //!< the list of primitives
+ };
+
+ template<typename NodeRef,
+ typename RecalculatePrimRef,
+ typename CreateAllocFunc,
+ typename CreateAABBNodeMBFunc,
+ typename SetAABBNodeMBFunc,
+ typename CreateOBBNodeMBFunc,
+ typename SetOBBNodeMBFunc,
+ typename CreateLeafFunc,
+ typename ProgressMonitor>
+
+ class BuilderT
+ {
+ ALIGNED_CLASS_(16);
+
+ static const size_t MAX_BRANCHING_FACTOR = 8; //!< maximum supported BVH branching factor
+ static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree if we are that many levels before the maximum tree depth
+ static const size_t SINGLE_THREADED_THRESHOLD = 4096; //!< threshold to switch to single threaded build
+
+ typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
+ typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
+
+ typedef FastAllocator::CachedAllocator Allocator;
+ typedef LocalChildListT<BuildRecord,MAX_BRANCHING_FACTOR> LocalChildList;
+
+ typedef HeuristicMBlurTemporalSplit<PrimRefMB,RecalculatePrimRef,MBLUR_NUM_TEMPORAL_BINS> HeuristicTemporal;
+ typedef HeuristicArrayBinningMB<PrimRefMB,MBLUR_NUM_OBJECT_BINS> HeuristicBinning;
+ typedef UnalignedHeuristicArrayBinningMB<PrimRefMB,MBLUR_NUM_OBJECT_BINS> UnalignedHeuristicBinning;
+
+ public:
+
+ BuilderT (Scene* scene,
+ const RecalculatePrimRef& recalculatePrimRef,
+ const CreateAllocFunc& createAlloc,
+ const CreateAABBNodeMBFunc& createAABBNodeMB,
+ const SetAABBNodeMBFunc& setAABBNodeMB,
+ const CreateOBBNodeMBFunc& createOBBNodeMB,
+ const SetOBBNodeMBFunc& setOBBNodeMB,
+ const CreateLeafFunc& createLeaf,
+ const ProgressMonitor& progressMonitor,
+ const Settings settings)
+
+ : cfg(settings),
+ scene(scene),
+ recalculatePrimRef(recalculatePrimRef),
+ createAlloc(createAlloc),
+ createAABBNodeMB(createAABBNodeMB), setAABBNodeMB(setAABBNodeMB),
+ createOBBNodeMB(createOBBNodeMB), setOBBNodeMB(setOBBNodeMB),
+ createLeaf(createLeaf),
+ progressMonitor(progressMonitor),
+ unalignedHeuristic(scene),
+ temporalSplitHeuristic(scene->device,recalculatePrimRef) {}
+
+ private:
+
+ /*! checks if all primitives are from the same geometry */
+ __forceinline bool sameGeometry(const SetMB& set)
+ {
+ mvector<PrimRefMB>& prims = *set.prims;
+ unsigned int firstGeomID = prims[set.begin()].geomID();
+ for (size_t i=set.begin()+1; i<set.end(); i++) {
+ if (prims[i].geomID() != firstGeomID){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*! performs some split if SAH approaches fail */
+ void splitFallback(const SetMB& set, SetMB& lset, SetMB& rset)
+ {
+ mvector<PrimRefMB>& prims = *set.prims;
+
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ const size_t center = (begin + end)/2;
+
+ PrimInfoMB linfo = empty;
+ for (size_t i=begin; i<center; i++)
+ linfo.add_primref(prims[i]);
+
+ PrimInfoMB rinfo = empty;
+ for (size_t i=center; i<end; i++)
+ rinfo.add_primref(prims[i]);
+
+ new (&lset) SetMB(linfo,set.prims,range<size_t>(begin,center),set.time_range);
+ new (&rset) SetMB(rinfo,set.prims,range<size_t>(center,end ),set.time_range);
+ }
+
+ void splitByGeometry(const SetMB& set, SetMB& lset, SetMB& rset)
+ {
+ assert(set.size() > 1);
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfoMB linfo(empty);
+ PrimInfoMB rinfo(empty);
+ unsigned int geomID = (*set.prims)[begin].geomID();
+ size_t center = serial_partitioning(set.prims->data(),begin,end,linfo,rinfo,
+ [&] ( const PrimRefMB& prim ) { return prim.geomID() == geomID; },
+ [ ] ( PrimInfoMB& a, const PrimRefMB& ref ) { a.add_primref(ref); });
+
+ new (&lset) SetMB(linfo,set.prims,range<size_t>(begin,center),set.time_range);
+ new (&rset) SetMB(rinfo,set.prims,range<size_t>(center,end ),set.time_range);
+ }
+
+ /*! creates a large leaf that could be larger than supported by the BVH */
+ NodeRecordMB4D createLargeLeaf(BuildRecord& current, Allocator alloc)
+ {
+ /* this should never occur but is a fatal error */
+ if (current.depth > cfg.maxDepth)
+ throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
+
+ /* special case when directly creating leaf without any splits that could shrink time_range */
+ bool force_split = false;
+ if (current.depth == 1 && current.size() > 0)
+ {
+ BBox1f c = empty;
+ BBox1f p = current.prims.time_range;
+ for (size_t i=current.prims.begin(); i<current.prims.end(); i++) {
+ mvector<PrimRefMB>& prims = *current.prims.prims;
+ c.extend(prims[i].time_range);
+ }
+
+ force_split = c.lower > p.lower || c.upper < p.upper;
+ }
+
+ /* create leaf for few primitives */
+ if (current.size() <= cfg.maxLeafSize && sameGeometry(current.prims) && !force_split)
+ return createLeaf(current.prims,alloc);
+
+ /* fill all children by always splitting the largest one */
+ LocalChildList children(current);
+ NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
+
+ do {
+
+ /* find best child with largest bounding box area */
+ int bestChild = -1;
+ size_t bestSize = 0;
+ for (unsigned i=0; i<children.size(); i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].size() <= cfg.maxLeafSize && sameGeometry(children[i].prims) && !force_split)
+ continue;
+
+ force_split = false;
+
+ /* remember child with largest size */
+ if (children[i].size() > bestSize) {
+ bestSize = children[i].size();
+ bestChild = i;
+ }
+ }
+ if (bestChild == -1) break;
+
+ /*! split best child into left and right child */
+ BuildRecord left(current.depth+1);
+ BuildRecord right(current.depth+1);
+ if (!sameGeometry(children[bestChild].prims)) {
+ splitByGeometry(children[bestChild].prims,left.prims,right.prims);
+ } else {
+ splitFallback(children[bestChild].prims,left.prims,right.prims);
+ }
+ children.split(bestChild,left,right,std::unique_ptr<mvector<PrimRefMB>>());
+
+ } while (children.size() < cfg.branchingFactor);
+
+
+ /* detect time_ranges that have shrunken */
+ bool timesplit = false;
+ for (size_t i=0; i<children.size(); i++) {
+ const BBox1f c = children[i].prims.time_range;
+ const BBox1f p = current.prims.time_range;
+ timesplit |= c.lower > p.lower || c.upper < p.upper;
+ }
+
+ /* create node */
+ NodeRef node = createAABBNodeMB(children.children.data(),children.numChildren,alloc,timesplit);
+
+ LBBox3fa bounds = empty;
+ for (size_t i=0; i<children.size(); i++) {
+ values[i] = createLargeLeaf(children[i],alloc);
+ bounds.extend(values[i].lbounds);
+ }
+
+ setAABBNodeMB(current,children.children.data(),node,values,children.numChildren);
+
+ if (timesplit)
+ bounds = current.prims.linearBounds(recalculatePrimRef);
+
+ return NodeRecordMB4D(node,bounds,current.prims.time_range);
+ }
+
+ /*! performs split */
+ std::unique_ptr<mvector<PrimRefMB>> split(const BuildRecord& current, BuildRecord& lrecord, BuildRecord& rrecord, bool& aligned, bool& timesplit)
+ {
+ /* variable to track the SAH of the best splitting approach */
+ float bestSAH = inf;
+ const float leafSAH = current.prims.leafSAH(cfg.logBlockSize);
+
+ /* perform standard binning in aligned space */
+ HeuristicBinning::Split alignedObjectSplit = alignedHeuristic.find(current.prims,cfg.logBlockSize);
+ float alignedObjectSAH = alignedObjectSplit.splitSAH();
+ bestSAH = min(alignedObjectSAH,bestSAH);
+
+ /* perform standard binning in unaligned space */
+ UnalignedHeuristicBinning::Split unalignedObjectSplit;
+ LinearSpace3fa uspace;
+ float unalignedObjectSAH = inf;
+ if (alignedObjectSAH > 0.7f*leafSAH) {
+ uspace = unalignedHeuristic.computeAlignedSpaceMB(scene,current.prims);
+ const SetMB sset = current.prims.primInfo(recalculatePrimRef,uspace);
+ unalignedObjectSplit = unalignedHeuristic.find(sset,cfg.logBlockSize,uspace);
+ unalignedObjectSAH = 1.3f*unalignedObjectSplit.splitSAH(); // makes unaligned splits more expensive
+ bestSAH = min(unalignedObjectSAH,bestSAH);
+ }
+
+ /* do temporal splits only if previous approaches failed to produce good SAH and the the time range is large enough */
+ float temporal_split_sah = inf;
+ typename HeuristicTemporal::Split temporal_split;
+ if (bestSAH > 0.5f*leafSAH) {
+ if (current.prims.time_range.size() > 1.01f/float(current.prims.max_num_time_segments)) {
+ temporal_split = temporalSplitHeuristic.find(current.prims,cfg.logBlockSize);
+ temporal_split_sah = temporal_split.splitSAH();
+ bestSAH = min(temporal_split_sah,bestSAH);
+ }
+ }
+
+ /* perform fallback split if SAH heuristics failed */
+ if (unlikely(!std::isfinite(bestSAH))) {
+ current.prims.deterministic_order();
+ splitFallback(current.prims,lrecord.prims,rrecord.prims);
+ }
+ /* perform aligned split if this is best */
+ else if (likely(bestSAH == alignedObjectSAH)) {
+ alignedHeuristic.split(alignedObjectSplit,current.prims,lrecord.prims,rrecord.prims);
+ }
+ /* perform unaligned split if this is best */
+ else if (likely(bestSAH == unalignedObjectSAH)) {
+ unalignedHeuristic.split(unalignedObjectSplit,uspace,current.prims,lrecord.prims,rrecord.prims);
+ aligned = false;
+ }
+ /* perform temporal split if this is best */
+ else if (likely(bestSAH == temporal_split_sah)) {
+ timesplit = true;
+ return temporalSplitHeuristic.split(temporal_split,current.prims,lrecord.prims,rrecord.prims);
+ }
+ else
+ assert(false);
+
+ return std::unique_ptr<mvector<PrimRefMB>>();
+ }
+
+ /*! recursive build */
+ NodeRecordMB4D recurse(BuildRecord& current, Allocator alloc, bool toplevel)
+ {
+ /* get thread local allocator */
+ if (!alloc)
+ alloc = createAlloc();
+
+ /* call memory monitor function to signal progress */
+ if (toplevel && current.size() <= SINGLE_THREADED_THRESHOLD)
+ progressMonitor(current.size());
+
+ /* create leaf node */
+ if (current.depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || current.size() <= cfg.minLeafSize) {
+ current.prims.deterministic_order();
+ return createLargeLeaf(current,alloc);
+ }
+
+ /* fill all children by always splitting the one with the largest surface area */
+ NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
+ LocalChildList children(current);
+ bool aligned = true;
+ bool timesplit = false;
+
+ do {
+
+ /* find best child with largest bounding box area */
+ ssize_t bestChild = -1;
+ float bestArea = neg_inf;
+ for (size_t i=0; i<children.size(); i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].size() <= cfg.minLeafSize)
+ continue;
+
+ /* remember child with largest area */
+ const float A = children[i].prims.halfArea();
+ if (A > bestArea) {
+ bestArea = children[i].prims.halfArea();
+ bestChild = i;
+ }
+ }
+ if (bestChild == -1) break;
+
+ /*! split best child into left and right child */
+ BuildRecord left(current.depth+1);
+ BuildRecord right(current.depth+1);
+ std::unique_ptr<mvector<PrimRefMB>> new_vector = split(children[bestChild],left,right,aligned,timesplit);
+ children.split(bestChild,left,right,std::move(new_vector));
+
+ } while (children.size() < cfg.branchingFactor);
+
+ /* detect time_ranges that have shrunken */
+ for (size_t i=0; i<children.size(); i++) {
+ const BBox1f c = children[i].prims.time_range;
+ const BBox1f p = current.prims.time_range;
+ timesplit |= c.lower > p.lower || c.upper < p.upper;
+ }
+
+ /* create time split node */
+ if (timesplit)
+ {
+ const NodeRef node = createAABBNodeMB(children.children.data(),children.numChildren,alloc,true);
+
+ /* spawn tasks or ... */
+ if (current.size() > SINGLE_THREADED_THRESHOLD)
+ {
+ parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ values[i] = recurse(children[i],nullptr,true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ }
+ });
+ }
+ /* ... continue sequential */
+ else {
+ for (size_t i=0; i<children.size(); i++) {
+ values[i] = recurse(children[i],alloc,false);
+ }
+ }
+
+ setAABBNodeMB(current,children.children.data(),node,values,children.numChildren);
+
+ const LBBox3fa bounds = current.prims.linearBounds(recalculatePrimRef);
+ return NodeRecordMB4D(node,bounds,current.prims.time_range);
+ }
+
+ /* create aligned node */
+ else if (aligned)
+ {
+ const NodeRef node = createAABBNodeMB(children.children.data(),children.numChildren,alloc,true);
+
+ /* spawn tasks or ... */
+ if (current.size() > SINGLE_THREADED_THRESHOLD)
+ {
+ LBBox3fa cbounds[MAX_BRANCHING_FACTOR];
+ parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ values[i] = recurse(children[i],nullptr,true);
+ cbounds[i] = values[i].lbounds;
+ _mm_mfence(); // to allow non-temporal stores during build
+ }
+ });
+
+ LBBox3fa bounds = empty;
+ for (size_t i=0; i<children.size(); i++)
+ bounds.extend(cbounds[i]);
+ setAABBNodeMB(current,children.children.data(),node,values,children.numChildren);
+ return NodeRecordMB4D(node,bounds,current.prims.time_range);
+ }
+ /* ... continue sequentially */
+ else
+ {
+ LBBox3fa bounds = empty;
+ for (size_t i=0; i<children.size(); i++) {
+ values[i] = recurse(children[i],alloc,false);
+ bounds.extend(values[i].lbounds);
+ }
+ setAABBNodeMB(current,children.children.data(),node,values,children.numChildren);
+ return NodeRecordMB4D(node,bounds,current.prims.time_range);
+ }
+ }
+
+ /* create unaligned node */
+ else
+ {
+ const NodeRef node = createOBBNodeMB(alloc);
+
+ /* spawn tasks or ... */
+ if (current.size() > SINGLE_THREADED_THRESHOLD)
+ {
+ parallel_for(size_t(0), children.size(), [&] (const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpaceMB(scene,children[i].prims);
+ const LBBox3fa lbounds = children[i].prims.linearBounds(recalculatePrimRef,space);
+ const auto child = recurse(children[i],nullptr,true);
+ setOBBNodeMB(node,i,child.ref,space,lbounds,children[i].prims.time_range);
+ _mm_mfence(); // to allow non-temporal stores during build
+ }
+ });
+ }
+ /* ... continue sequentially */
+ else
+ {
+ for (size_t i=0; i<children.size(); i++) {
+ const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpaceMB(scene,children[i].prims);
+ const LBBox3fa lbounds = children[i].prims.linearBounds(recalculatePrimRef,space);
+ const auto child = recurse(children[i],alloc,false);
+ setOBBNodeMB(node,i,child.ref,space,lbounds,children[i].prims.time_range);
+ }
+ }
+
+ const LBBox3fa bounds = current.prims.linearBounds(recalculatePrimRef);
+ return NodeRecordMB4D(node,bounds,current.prims.time_range);
+ }
+ }
+
+ public:
+
+ /*! entry point into builder */
+ NodeRecordMB4D operator() (mvector<PrimRefMB>& prims, const PrimInfoMB& pinfo)
+ {
+ BuildRecord record(SetMB(pinfo,&prims),1);
+ auto root = recurse(record,nullptr,true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ return root;
+ }
+
+ private:
+ Settings cfg;
+ Scene* scene;
+ const RecalculatePrimRef& recalculatePrimRef;
+ const CreateAllocFunc& createAlloc;
+ const CreateAABBNodeMBFunc& createAABBNodeMB;
+ const SetAABBNodeMBFunc& setAABBNodeMB;
+ const CreateOBBNodeMBFunc& createOBBNodeMB;
+ const SetOBBNodeMBFunc& setOBBNodeMB;
+ const CreateLeafFunc& createLeaf;
+ const ProgressMonitor& progressMonitor;
+
+ private:
+ HeuristicBinning alignedHeuristic;
+ UnalignedHeuristicBinning unalignedHeuristic;
+ HeuristicTemporal temporalSplitHeuristic;
+ };
+
+ template<typename NodeRef,
+ typename RecalculatePrimRef,
+ typename CreateAllocFunc,
+ typename CreateAABBNodeMBFunc,
+ typename SetAABBNodeMBFunc,
+ typename CreateOBBNodeMBFunc,
+ typename SetOBBNodeMBFunc,
+ typename CreateLeafFunc,
+ typename ProgressMonitor>
+
+ static BVHNodeRecordMB4D<NodeRef> build (Scene* scene, mvector<PrimRefMB>& prims, const PrimInfoMB& pinfo,
+ const RecalculatePrimRef& recalculatePrimRef,
+ const CreateAllocFunc& createAlloc,
+ const CreateAABBNodeMBFunc& createAABBNodeMB,
+ const SetAABBNodeMBFunc& setAABBNodeMB,
+ const CreateOBBNodeMBFunc& createOBBNodeMB,
+ const SetOBBNodeMBFunc& setOBBNodeMB,
+ const CreateLeafFunc& createLeaf,
+ const ProgressMonitor& progressMonitor,
+ const Settings settings)
+ {
+ typedef BuilderT<NodeRef,RecalculatePrimRef,CreateAllocFunc,
+ CreateAABBNodeMBFunc,SetAABBNodeMBFunc,
+ CreateOBBNodeMBFunc,SetOBBNodeMBFunc,
+ CreateLeafFunc,ProgressMonitor> Builder;
+
+ Builder builder(scene,recalculatePrimRef,createAlloc,
+ createAABBNodeMB,setAABBNodeMB,
+ createOBBNodeMB,setOBBNodeMB,
+ createLeaf,progressMonitor,settings);
+
+ return builder(prims,pinfo);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/bvh_builder_sah.h b/thirdparty/embree/kernels/builders/bvh_builder_sah.h
new file mode 100644
index 0000000000..fff4bf2a35
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/bvh_builder_sah.h
@@ -0,0 +1,669 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "heuristic_binning_array_aligned.h"
+#include "heuristic_spatial_array.h"
+#include "heuristic_openmerge_array.h"
+
+#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
+# define NUM_OBJECT_BINS 16
+# define NUM_SPATIAL_BINS 16
+#else
+# define NUM_OBJECT_BINS 32
+# define NUM_SPATIAL_BINS 16
+#endif
+
+namespace embree
+{
+ namespace isa
+ {
+ MAYBE_UNUSED static const float travCost = 1.0f;
+ MAYBE_UNUSED static const size_t DEFAULT_SINGLE_THREAD_THRESHOLD = 1024;
+
+ struct GeneralBVHBuilder
+ {
+ static const size_t MAX_BRANCHING_FACTOR = 16; //!< maximum supported BVH branching factor
+ static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree of we are that many levels before the maximum tree depth
+
+
+ /*! settings for SAH builder */
+ struct Settings
+ {
+ /*! default settings */
+ Settings ()
+ : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(7),
+ travCost(1.0f), intCost(1.0f), singleThreadThreshold(1024), primrefarrayalloc(inf) {}
+
+ /*! initialize settings from API settings */
+ Settings (const RTCBuildArguments& settings)
+ : branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(7),
+ travCost(1.0f), intCost(1.0f), singleThreadThreshold(1024), primrefarrayalloc(inf)
+ {
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,maxBranchingFactor)) branchingFactor = settings.maxBranchingFactor;
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,maxDepth )) maxDepth = settings.maxDepth;
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,sahBlockSize )) logBlockSize = bsr(settings.sahBlockSize);
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,minLeafSize )) minLeafSize = settings.minLeafSize;
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,maxLeafSize )) maxLeafSize = settings.maxLeafSize;
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,traversalCost )) travCost = settings.traversalCost;
+ if (RTC_BUILD_ARGUMENTS_HAS(settings,intersectionCost )) intCost = settings.intersectionCost;
+
+ minLeafSize = min(minLeafSize,maxLeafSize);
+ }
+
+ Settings (size_t sahBlockSize, size_t minLeafSize, size_t maxLeafSize, float travCost, float intCost, size_t singleThreadThreshold, size_t primrefarrayalloc = inf)
+ : branchingFactor(2), maxDepth(32), logBlockSize(bsr(sahBlockSize)), minLeafSize(minLeafSize), maxLeafSize(maxLeafSize),
+ travCost(travCost), intCost(intCost), singleThreadThreshold(singleThreadThreshold), primrefarrayalloc(primrefarrayalloc)
+ {
+ minLeafSize = min(minLeafSize,maxLeafSize);
+ }
+
+ public:
+ size_t branchingFactor; //!< branching factor of BVH to build
+ size_t maxDepth; //!< maximum depth of BVH to build
+ size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
+ size_t minLeafSize; //!< minimum size of a leaf
+ size_t maxLeafSize; //!< maximum size of a leaf
+ float travCost; //!< estimated cost of one traversal step
+ float intCost; //!< estimated cost of one primitive intersection
+ size_t singleThreadThreshold; //!< threshold when we switch to single threaded build
+ size_t primrefarrayalloc; //!< builder uses prim ref array to allocate nodes and leaves when a subtree of that size is finished
+ };
+
+ /*! recursive state of builder */
+ template<typename Set, typename Split>
+ struct BuildRecordT
+ {
+ public:
+ __forceinline BuildRecordT () {}
+
+ __forceinline BuildRecordT (size_t depth)
+ : depth(depth), alloc_barrier(false), prims(empty) {}
+
+ __forceinline BuildRecordT (size_t depth, const Set& prims)
+ : depth(depth), alloc_barrier(false), prims(prims) {}
+
+ __forceinline BBox3fa bounds() const { return prims.geomBounds; }
+
+ __forceinline friend bool operator< (const BuildRecordT& a, const BuildRecordT& b) { return a.prims.size() < b.prims.size(); }
+ __forceinline friend bool operator> (const BuildRecordT& a, const BuildRecordT& b) { return a.prims.size() > b.prims.size(); }
+
+ __forceinline size_t size() const { return prims.size(); }
+
+ public:
+ size_t depth; //!< Depth of the root of this subtree.
+ bool alloc_barrier; //!< barrier used to reuse primref-array blocks to allocate nodes
+ Set prims; //!< The list of primitives.
+ };
+
+ template<typename PrimRef, typename Set>
+ struct DefaultCanCreateLeafFunc
+ {
+ __forceinline bool operator()(const PrimRef*, const Set&) const { return true; }
+ };
+
+ template<typename PrimRef, typename Set>
+ struct DefaultCanCreateLeafSplitFunc
+ {
+ __forceinline void operator()(PrimRef*, const Set&, Set&, Set&) const { }
+ };
+
+ template<typename BuildRecord,
+ typename Heuristic,
+ typename Set,
+ typename PrimRef,
+ typename ReductionTy,
+ typename Allocator,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename UpdateNodeFunc,
+ typename CreateLeafFunc,
+ typename CanCreateLeafFunc,
+ typename CanCreateLeafSplitFunc,
+ typename ProgressMonitor>
+
+ class BuilderT
+ {
+ friend struct GeneralBVHBuilder;
+
+ BuilderT (PrimRef* prims,
+ Heuristic& heuristic,
+ const CreateAllocFunc& createAlloc,
+ const CreateNodeFunc& createNode,
+ const UpdateNodeFunc& updateNode,
+ const CreateLeafFunc& createLeaf,
+ const CanCreateLeafFunc& canCreateLeaf,
+ const CanCreateLeafSplitFunc& canCreateLeafSplit,
+ const ProgressMonitor& progressMonitor,
+ const Settings& settings) :
+ cfg(settings),
+ prims(prims),
+ heuristic(heuristic),
+ createAlloc(createAlloc),
+ createNode(createNode),
+ updateNode(updateNode),
+ createLeaf(createLeaf),
+ canCreateLeaf(canCreateLeaf),
+ canCreateLeafSplit(canCreateLeafSplit),
+ progressMonitor(progressMonitor)
+ {
+ if (cfg.branchingFactor > MAX_BRANCHING_FACTOR)
+ throw_RTCError(RTC_ERROR_UNKNOWN,"bvh_builder: branching factor too large");
+ }
+
+ const ReductionTy createLargeLeaf(const BuildRecord& current, Allocator alloc)
+ {
+ /* this should never occur but is a fatal error */
+ if (current.depth > cfg.maxDepth)
+ throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
+
+ /* create leaf for few primitives */
+ if (current.prims.size() <= cfg.maxLeafSize && canCreateLeaf(prims,current.prims))
+ return createLeaf(prims,current.prims,alloc);
+
+ /* fill all children by always splitting the largest one */
+ ReductionTy values[MAX_BRANCHING_FACTOR];
+ BuildRecord children[MAX_BRANCHING_FACTOR];
+ size_t numChildren = 1;
+ children[0] = current;
+ do {
+
+ /* find best child with largest bounding box area */
+ size_t bestChild = -1;
+ size_t bestSize = 0;
+ for (size_t i=0; i<numChildren; i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].prims.size() <= cfg.maxLeafSize && canCreateLeaf(prims,children[i].prims))
+ continue;
+
+ /* remember child with largest size */
+ if (children[i].prims.size() > bestSize) {
+ bestSize = children[i].prims.size();
+ bestChild = i;
+ }
+ }
+ if (bestChild == (size_t)-1) break;
+
+ /*! split best child into left and right child */
+ BuildRecord left(current.depth+1);
+ BuildRecord right(current.depth+1);
+ if (!canCreateLeaf(prims,children[bestChild].prims)) {
+ canCreateLeafSplit(prims,children[bestChild].prims,left.prims,right.prims);
+ } else {
+ heuristic.splitFallback(children[bestChild].prims,left.prims,right.prims);
+ }
+
+ /* add new children left and right */
+ children[bestChild] = children[numChildren-1];
+ children[numChildren-1] = left;
+ children[numChildren+0] = right;
+ numChildren++;
+
+ } while (numChildren < cfg.branchingFactor);
+
+ /* set barrier for primrefarrayalloc */
+ if (unlikely(current.size() > cfg.primrefarrayalloc))
+ for (size_t i=0; i<numChildren; i++)
+ children[i].alloc_barrier = children[i].size() <= cfg.primrefarrayalloc;
+
+ /* create node */
+ auto node = createNode(children,numChildren,alloc);
+
+ /* recurse into each child and perform reduction */
+ for (size_t i=0; i<numChildren; i++)
+ values[i] = createLargeLeaf(children[i],alloc);
+
+ /* perform reduction */
+ return updateNode(current,children,node,values,numChildren);
+ }
+
+ const ReductionTy recurse(BuildRecord& current, Allocator alloc, bool toplevel)
+ {
+ /* get thread local allocator */
+ if (!alloc)
+ alloc = createAlloc();
+
+ /* call memory monitor function to signal progress */
+ if (toplevel && current.size() <= cfg.singleThreadThreshold)
+ progressMonitor(current.size());
+
+ /*! find best split */
+ auto split = heuristic.find(current.prims,cfg.logBlockSize);
+
+ /*! compute leaf and split cost */
+ const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.logBlockSize);
+ const float splitSAH = cfg.travCost*halfArea(current.prims.geomBounds)+cfg.intCost*split.splitSAH();
+ assert((current.prims.size() == 0) || ((leafSAH >= 0) && (splitSAH >= 0)));
+
+ /*! create a leaf node when threshold reached or SAH tells us to stop */
+ if (current.prims.size() <= cfg.minLeafSize || current.depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || (current.prims.size() <= cfg.maxLeafSize && leafSAH <= splitSAH)) {
+ heuristic.deterministic_order(current.prims);
+ return createLargeLeaf(current,alloc);
+ }
+
+ /*! perform initial split */
+ Set lprims,rprims;
+ heuristic.split(split,current.prims,lprims,rprims);
+
+ /*! initialize child list with initial split */
+ ReductionTy values[MAX_BRANCHING_FACTOR];
+ BuildRecord children[MAX_BRANCHING_FACTOR];
+ children[0] = BuildRecord(current.depth+1,lprims);
+ children[1] = BuildRecord(current.depth+1,rprims);
+ size_t numChildren = 2;
+
+ /*! split until node is full or SAH tells us to stop */
+ while (numChildren < cfg.branchingFactor)
+ {
+ /*! find best child to split */
+ float bestArea = neg_inf;
+ ssize_t bestChild = -1;
+ for (size_t i=0; i<numChildren; i++)
+ {
+ /* ignore leaves as they cannot get split */
+ if (children[i].prims.size() <= cfg.minLeafSize) continue;
+
+ /* find child with largest surface area */
+ if (halfArea(children[i].prims.geomBounds) > bestArea) {
+ bestChild = i;
+ bestArea = halfArea(children[i].prims.geomBounds);
+ }
+ }
+ if (bestChild == -1) break;
+
+ /* perform best found split */
+ BuildRecord& brecord = children[bestChild];
+ BuildRecord lrecord(current.depth+1);
+ BuildRecord rrecord(current.depth+1);
+ auto split = heuristic.find(brecord.prims,cfg.logBlockSize);
+ heuristic.split(split,brecord.prims,lrecord.prims,rrecord.prims);
+ children[bestChild ] = lrecord;
+ children[numChildren] = rrecord;
+ numChildren++;
+ }
+
+ /* set barrier for primrefarrayalloc */
+ if (unlikely(current.size() > cfg.primrefarrayalloc))
+ for (size_t i=0; i<numChildren; i++)
+ children[i].alloc_barrier = children[i].size() <= cfg.primrefarrayalloc;
+
+ /* sort buildrecords for faster shadow ray traversal */
+ std::sort(&children[0],&children[numChildren],std::greater<BuildRecord>());
+
+ /*! create an inner node */
+ auto node = createNode(children,numChildren,alloc);
+
+ /* spawn tasks */
+ if (current.size() > cfg.singleThreadThreshold)
+ {
+ /*! parallel_for is faster than spawing sub-tasks */
+ parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) { // FIXME: no range here
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ values[i] = recurse(children[i],nullptr,true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ }
+ });
+
+ return updateNode(current,children,node,values,numChildren);
+ }
+ /* recurse into each child */
+ else
+ {
+ for (size_t i=0; i<numChildren; i++)
+ values[i] = recurse(children[i],alloc,false);
+
+ return updateNode(current,children,node,values,numChildren);
+ }
+ }
+
+ private:
+ Settings cfg;
+ PrimRef* prims;
+ Heuristic& heuristic;
+ const CreateAllocFunc& createAlloc;
+ const CreateNodeFunc& createNode;
+ const UpdateNodeFunc& updateNode;
+ const CreateLeafFunc& createLeaf;
+ const CanCreateLeafFunc& canCreateLeaf;
+ const CanCreateLeafSplitFunc& canCreateLeafSplit;
+ const ProgressMonitor& progressMonitor;
+ };
+
+ template<
+ typename ReductionTy,
+ typename Heuristic,
+ typename Set,
+ typename PrimRef,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename UpdateNodeFunc,
+ typename CreateLeafFunc,
+ typename ProgressMonitor>
+
+ __noinline static ReductionTy build(Heuristic& heuristic,
+ PrimRef* prims,
+ const Set& set,
+ CreateAllocFunc createAlloc,
+ CreateNodeFunc createNode, UpdateNodeFunc updateNode,
+ const CreateLeafFunc& createLeaf,
+ const ProgressMonitor& progressMonitor,
+ const Settings& settings)
+ {
+ typedef BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
+
+ typedef BuilderT<
+ BuildRecord,
+ Heuristic,
+ Set,
+ PrimRef,
+ ReductionTy,
+ decltype(createAlloc()),
+ CreateAllocFunc,
+ CreateNodeFunc,
+ UpdateNodeFunc,
+ CreateLeafFunc,
+ DefaultCanCreateLeafFunc<PrimRef, Set>,
+ DefaultCanCreateLeafSplitFunc<PrimRef, Set>,
+ ProgressMonitor> Builder;
+
+ /* instantiate builder */
+ Builder builder(prims,
+ heuristic,
+ createAlloc,
+ createNode,
+ updateNode,
+ createLeaf,
+ DefaultCanCreateLeafFunc<PrimRef, Set>(),
+ DefaultCanCreateLeafSplitFunc<PrimRef, Set>(),
+ progressMonitor,
+ settings);
+
+ /* build hierarchy */
+ BuildRecord record(1,set);
+ const ReductionTy root = builder.recurse(record,nullptr,true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ return root;
+ }
+
+ template<
+ typename ReductionTy,
+ typename Heuristic,
+ typename Set,
+ typename PrimRef,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename UpdateNodeFunc,
+ typename CreateLeafFunc,
+ typename CanCreateLeafFunc,
+ typename CanCreateLeafSplitFunc,
+ typename ProgressMonitor>
+
+ __noinline static ReductionTy build(Heuristic& heuristic,
+ PrimRef* prims,
+ const Set& set,
+ CreateAllocFunc createAlloc,
+ CreateNodeFunc createNode, UpdateNodeFunc updateNode,
+ const CreateLeafFunc& createLeaf,
+ const CanCreateLeafFunc& canCreateLeaf,
+ const CanCreateLeafSplitFunc& canCreateLeafSplit,
+ const ProgressMonitor& progressMonitor,
+ const Settings& settings)
+ {
+ typedef BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
+
+ typedef BuilderT<
+ BuildRecord,
+ Heuristic,
+ Set,
+ PrimRef,
+ ReductionTy,
+ decltype(createAlloc()),
+ CreateAllocFunc,
+ CreateNodeFunc,
+ UpdateNodeFunc,
+ CreateLeafFunc,
+ CanCreateLeafFunc,
+ CanCreateLeafSplitFunc,
+ ProgressMonitor> Builder;
+
+ /* instantiate builder */
+ Builder builder(prims,
+ heuristic,
+ createAlloc,
+ createNode,
+ updateNode,
+ createLeaf,
+ canCreateLeaf,
+ canCreateLeafSplit,
+ progressMonitor,
+ settings);
+
+ /* build hierarchy */
+ BuildRecord record(1,set);
+ const ReductionTy root = builder.recurse(record,nullptr,true);
+ _mm_mfence(); // to allow non-temporal stores during build
+ return root;
+ }
+ };
+
+ /* SAH builder that operates on an array of BuildRecords */
+ struct BVHBuilderBinnedSAH
+ {
+ typedef PrimInfoRange Set;
+ typedef HeuristicArrayBinningSAH<PrimRef,NUM_OBJECT_BINS> Heuristic;
+ typedef GeneralBVHBuilder::BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
+ typedef GeneralBVHBuilder::Settings Settings;
+
+ /*! special builder that propagates reduction over the tree */
+ template<
+ typename ReductionTy,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename UpdateNodeFunc,
+ typename CreateLeafFunc,
+ typename ProgressMonitor>
+
+ static ReductionTy build(CreateAllocFunc createAlloc,
+ CreateNodeFunc createNode, UpdateNodeFunc updateNode,
+ const CreateLeafFunc& createLeaf,
+ const ProgressMonitor& progressMonitor,
+ PrimRef* prims, const PrimInfo& pinfo,
+ const Settings& settings)
+ {
+ Heuristic heuristic(prims);
+ return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
+ heuristic,
+ prims,
+ PrimInfoRange(0,pinfo.size(),pinfo),
+ createAlloc,
+ createNode,
+ updateNode,
+ createLeaf,
+ progressMonitor,
+ settings);
+ }
+
+ /*! special builder that propagates reduction over the tree */
+ template<
+ typename ReductionTy,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename UpdateNodeFunc,
+ typename CreateLeafFunc,
+ typename CanCreateLeafFunc,
+ typename CanCreateLeafSplitFunc,
+ typename ProgressMonitor>
+
+ static ReductionTy build(CreateAllocFunc createAlloc,
+ CreateNodeFunc createNode, UpdateNodeFunc updateNode,
+ const CreateLeafFunc& createLeaf,
+ const CanCreateLeafFunc& canCreateLeaf,
+ const CanCreateLeafSplitFunc& canCreateLeafSplit,
+ const ProgressMonitor& progressMonitor,
+ PrimRef* prims, const PrimInfo& pinfo,
+ const Settings& settings)
+ {
+ Heuristic heuristic(prims);
+ return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
+ heuristic,
+ prims,
+ PrimInfoRange(0,pinfo.size(),pinfo),
+ createAlloc,
+ createNode,
+ updateNode,
+ createLeaf,
+ canCreateLeaf,
+ canCreateLeafSplit,
+ progressMonitor,
+ settings);
+ }
+ };
+
+ /* Spatial SAH builder that operates on an double-buffered array of BuildRecords */
+ struct BVHBuilderBinnedFastSpatialSAH
+ {
+ typedef PrimInfoExtRange Set;
+ typedef Split2<BinSplit<NUM_OBJECT_BINS>,SpatialBinSplit<NUM_SPATIAL_BINS> > Split;
+ typedef GeneralBVHBuilder::BuildRecordT<Set,Split> BuildRecord;
+ typedef GeneralBVHBuilder::Settings Settings;
+
+ static const unsigned int GEOMID_MASK = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
+ static const unsigned int SPLITS_MASK = 0xFFFFFFFF << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
+
+ template<typename ReductionTy, typename UserCreateLeaf>
+ struct CreateLeafExt
+ {
+ __forceinline CreateLeafExt (const UserCreateLeaf userCreateLeaf)
+ : userCreateLeaf(userCreateLeaf) {}
+
+ // __noinline is workaround for ICC2016 compiler bug
+ template<typename Allocator>
+ __noinline ReductionTy operator() (PrimRef* prims, const range<size_t>& range, Allocator alloc) const
+ {
+ for (size_t i=range.begin(); i<range.end(); i++)
+ prims[i].lower.u &= GEOMID_MASK;
+
+ return userCreateLeaf(prims,range,alloc);
+ }
+
+ const UserCreateLeaf userCreateLeaf;
+ };
+
+ /*! special builder that propagates reduction over the tree */
+ template<
+ typename ReductionTy,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename UpdateNodeFunc,
+ typename CreateLeafFunc,
+ typename SplitPrimitiveFunc,
+ typename ProgressMonitor>
+
+ static ReductionTy build(CreateAllocFunc createAlloc,
+ CreateNodeFunc createNode,
+ UpdateNodeFunc updateNode,
+ const CreateLeafFunc& createLeaf,
+ SplitPrimitiveFunc splitPrimitive,
+ ProgressMonitor progressMonitor,
+ PrimRef* prims,
+ const size_t extSize,
+ const PrimInfo& pinfo,
+ const Settings& settings)
+ {
+ typedef HeuristicArraySpatialSAH<SplitPrimitiveFunc,PrimRef,NUM_OBJECT_BINS,NUM_SPATIAL_BINS> Heuristic;
+ Heuristic heuristic(splitPrimitive,prims,pinfo);
+
+ /* calculate total surface area */ // FIXME: this sum is not deterministic
+ const float A = (float) parallel_reduce(size_t(0),pinfo.size(),0.0, [&] (const range<size_t>& r) -> double {
+
+ double A = 0.0f;
+ for (size_t i=r.begin(); i<r.end(); i++)
+ {
+ PrimRef& prim = prims[i];
+ A += area(prim.bounds());
+ }
+ return A;
+ },std::plus<double>());
+
+
+ /* calculate maximum number of spatial splits per primitive */
+ const unsigned int maxSplits = ((size_t)1 << RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)-1;
+ const float f = 10.0f;
+
+ const float invA = 1.0f / A;
+ parallel_for( size_t(0), pinfo.size(), [&](const range<size_t>& r) {
+
+ for (size_t i=r.begin(); i<r.end(); i++)
+ {
+ PrimRef& prim = prims[i];
+ assert((prim.geomID() & SPLITS_MASK) == 0);
+ // FIXME: is there a better general heuristic ?
+ const float nf = ceilf(f*pinfo.size()*area(prim.bounds()) * invA);
+ unsigned int n = 4+min((int)maxSplits-4, max(1, (int)(nf)));
+ prim.lower.u |= n << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
+ }
+ });
+
+ return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
+ heuristic,
+ prims,
+ PrimInfoExtRange(0,pinfo.size(),extSize,pinfo),
+ createAlloc,
+ createNode,
+ updateNode,
+ CreateLeafExt<ReductionTy,CreateLeafFunc>(createLeaf),
+ progressMonitor,
+ settings);
+ }
+ };
+
+ /* Open/Merge SAH builder that operates on an array of BuildRecords */
+ struct BVHBuilderBinnedOpenMergeSAH
+ {
+ static const size_t NUM_OBJECT_BINS_HQ = 32;
+ typedef PrimInfoExtRange Set;
+ typedef BinSplit<NUM_OBJECT_BINS_HQ> Split;
+ typedef GeneralBVHBuilder::BuildRecordT<Set,Split> BuildRecord;
+ typedef GeneralBVHBuilder::Settings Settings;
+
+ /*! special builder that propagates reduction over the tree */
+ template<
+ typename ReductionTy,
+ typename BuildRef,
+ typename CreateAllocFunc,
+ typename CreateNodeFunc,
+ typename UpdateNodeFunc,
+ typename CreateLeafFunc,
+ typename NodeOpenerFunc,
+ typename ProgressMonitor>
+
+ static ReductionTy build(CreateAllocFunc createAlloc,
+ CreateNodeFunc createNode,
+ UpdateNodeFunc updateNode,
+ const CreateLeafFunc& createLeaf,
+ NodeOpenerFunc nodeOpenerFunc,
+ ProgressMonitor progressMonitor,
+ BuildRef* prims,
+ const size_t extSize,
+ const PrimInfo& pinfo,
+ const Settings& settings)
+ {
+ typedef HeuristicArrayOpenMergeSAH<NodeOpenerFunc,BuildRef,NUM_OBJECT_BINS_HQ> Heuristic;
+ Heuristic heuristic(nodeOpenerFunc,prims,settings.branchingFactor);
+
+ return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,BuildRef>(
+ heuristic,
+ prims,
+ PrimInfoExtRange(0,pinfo.size(),extSize,pinfo),
+ createAlloc,
+ createNode,
+ updateNode,
+ createLeaf,
+ progressMonitor,
+ settings);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/heuristic_binning.h b/thirdparty/embree/kernels/builders/heuristic_binning.h
new file mode 100644
index 0000000000..ee29d09ac9
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/heuristic_binning.h
@@ -0,0 +1,496 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "priminfo.h"
+#include "../../common/algorithms/parallel_reduce.h"
+#include "../../common/algorithms/parallel_partition.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! mapping into bins */
+ template<size_t BINS>
+ struct BinMapping
+ {
+ public:
+ __forceinline BinMapping() {}
+
+ /*! calculates the mapping */
+ __forceinline BinMapping(size_t N, const BBox3fa& centBounds)
+ {
+ num = min(BINS,size_t(4.0f + 0.05f*N));
+ assert(num >= 1);
+ const vfloat4 eps = 1E-34f;
+ const vfloat4 diag = max(eps, (vfloat4) centBounds.size());
+ scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
+ ofs = (vfloat4) centBounds.lower;
+ }
+
+ /*! calculates the mapping */
+ __forceinline BinMapping(const BBox3fa& centBounds)
+ {
+ num = BINS;
+ const vfloat4 eps = 1E-34f;
+ const vfloat4 diag = max(eps, (vfloat4) centBounds.size());
+ scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
+ ofs = (vfloat4) centBounds.lower;
+ }
+
+ /*! calculates the mapping */
+ template<typename PrimInfo>
+ __forceinline BinMapping(const PrimInfo& pinfo)
+ {
+ const vfloat4 eps = 1E-34f;
+ num = min(BINS,size_t(4.0f + 0.05f*pinfo.size()));
+ const vfloat4 diag = max(eps,(vfloat4) pinfo.centBounds.size());
+ scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
+ ofs = (vfloat4) pinfo.centBounds.lower;
+ }
+
+ /*! returns number of bins */
+ __forceinline size_t size() const { return num; }
+
+ /*! slower but safe binning */
+ __forceinline Vec3ia bin(const Vec3fa& p) const
+ {
+ const vint4 i = floori((vfloat4(p)-ofs)*scale);
+#if 1
+ assert(i[0] >= 0 && (size_t)i[0] < num);
+ assert(i[1] >= 0 && (size_t)i[1] < num);
+ assert(i[2] >= 0 && (size_t)i[2] < num);
+ return Vec3ia(i);
+#else
+ return Vec3ia(clamp(i,vint4(0),vint4(num-1)));
+#endif
+ }
+
+ /*! faster but unsafe binning */
+ __forceinline Vec3ia bin_unsafe(const Vec3fa& p) const {
+ return Vec3ia(floori((vfloat4(p)-ofs)*scale));
+ }
+
+ /*! faster but unsafe binning */
+ template<typename PrimRef>
+ __forceinline Vec3ia bin_unsafe(const PrimRef& p) const {
+ return bin_unsafe(p.binCenter());
+ }
+
+ /*! faster but unsafe binning */
+ template<typename PrimRef, typename BinBoundsAndCenter>
+ __forceinline Vec3ia bin_unsafe(const PrimRef& p, const BinBoundsAndCenter& binBoundsAndCenter) const {
+ return bin_unsafe(binBoundsAndCenter.binCenter(p));
+ }
+
+ template<typename PrimRef>
+ __forceinline bool bin_unsafe(const PrimRef& ref,
+ const vint4& vSplitPos,
+ const vbool4& splitDimMask) const // FIXME: rename to isLeft
+ {
+ return any(((vint4)bin_unsafe(center2(ref.bounds())) < vSplitPos) & splitDimMask);
+ }
+ /*! calculates left spatial position of bin */
+ __forceinline float pos(const size_t bin, const size_t dim) const {
+ return madd(float(bin),1.0f / scale[dim],ofs[dim]);
+ }
+
+ /*! returns true if the mapping is invalid in some dimension */
+ __forceinline bool invalid(const size_t dim) const {
+ return scale[dim] == 0.0f;
+ }
+
+ /*! stream output */
+ friend embree_ostream operator<<(embree_ostream cout, const BinMapping& mapping) {
+ return cout << "BinMapping { num = " << mapping.num << ", ofs = " << mapping.ofs << ", scale = " << mapping.scale << "}";
+ }
+
+ public:
+ size_t num;
+ vfloat4 ofs,scale; //!< linear function that maps to bin ID
+ };
+
+ /*! stores all information to perform some split */
+ template<size_t BINS>
+ struct BinSplit
+ {
+ enum
+ {
+ SPLIT_OBJECT = 0,
+ SPLIT_FALLBACK = 1,
+ SPLIT_ENFORCE = 2, // splits with larger ID are enforced in createLargeLeaf even if we could create a leaf already
+ SPLIT_TEMPORAL = 2,
+ SPLIT_GEOMID = 3,
+ };
+
+ /*! construct an invalid split by default */
+ __forceinline BinSplit()
+ : sah(inf), dim(-1), pos(0), data(0) {}
+
+ __forceinline BinSplit(float sah, unsigned data, int dim = 0, float fpos = 0)
+ : sah(sah), dim(dim), fpos(fpos), data(data) {}
+
+ /*! constructs specified split */
+ __forceinline BinSplit(float sah, int dim, int pos, const BinMapping<BINS>& mapping)
+ : sah(sah), dim(dim), pos(pos), data(0), mapping(mapping) {}
+
+ /*! tests if this split is valid */
+ __forceinline bool valid() const { return dim != -1; }
+
+ /*! calculates surface area heuristic for performing the split */
+ __forceinline float splitSAH() const { return sah; }
+
+ /*! stream output */
+ friend embree_ostream operator<<(embree_ostream cout, const BinSplit& split) {
+ return cout << "BinSplit { sah = " << split.sah << ", dim = " << split.dim << ", pos = " << split.pos << "}";
+ }
+
+ public:
+ float sah; //!< SAH cost of the split
+ int dim; //!< split dimension
+ union { int pos; float fpos; }; //!< bin index for splitting
+ unsigned int data; //!< extra optional split data
+ BinMapping<BINS> mapping; //!< mapping into bins
+ };
+
+ /*! stores extended information about the split */
+ template<typename BBox>
+ struct SplitInfoT
+ {
+
+ __forceinline SplitInfoT () {}
+
+ __forceinline SplitInfoT (size_t leftCount, const BBox& leftBounds, size_t rightCount, const BBox& rightBounds)
+ : leftCount(leftCount), rightCount(rightCount), leftBounds(leftBounds), rightBounds(rightBounds) {}
+
+ public:
+ size_t leftCount,rightCount;
+ BBox leftBounds,rightBounds;
+ };
+
+ typedef SplitInfoT<BBox3fa> SplitInfo;
+ typedef SplitInfoT<LBBox3fa> SplitInfo2;
+
+ /*! stores all binning information */
+ template<size_t BINS, typename PrimRef, typename BBox>
+ struct __aligned(64) BinInfoT
+ {
+ typedef BinSplit<BINS> Split;
+ typedef vbool4 vbool;
+ typedef vint4 vint;
+ typedef vfloat4 vfloat;
+
+ __forceinline BinInfoT() {
+ }
+
+ __forceinline BinInfoT(EmptyTy) {
+ clear();
+ }
+
+ /*! bin access function */
+ __forceinline BBox &bounds(const size_t binID, const size_t dimID) { return _bounds[binID][dimID]; }
+ __forceinline const BBox &bounds(const size_t binID, const size_t dimID) const { return _bounds[binID][dimID]; }
+
+ __forceinline unsigned int &counts(const size_t binID, const size_t dimID) { return _counts[binID][dimID]; }
+ __forceinline const unsigned int &counts(const size_t binID, const size_t dimID) const { return _counts[binID][dimID]; }
+
+ __forceinline vuint4 &counts(const size_t binID) { return _counts[binID]; }
+ __forceinline const vuint4 &counts(const size_t binID) const { return _counts[binID]; }
+
+ /*! clears the bin info */
+ __forceinline void clear()
+ {
+ for (size_t i=0; i<BINS; i++) {
+ bounds(i,0) = bounds(i,1) = bounds(i,2) = empty;
+ counts(i) = vuint4(zero);
+ }
+ }
+
+ /*! bins an array of primitives */
+ __forceinline void bin (const PrimRef* prims, size_t N, const BinMapping<BINS>& mapping)
+ {
+ if (unlikely(N == 0)) return;
+ size_t i;
+ for (i=0; i<N-1; i+=2)
+ {
+ /*! map even and odd primitive to bin */
+ BBox prim0; Vec3fa center0;
+ prims[i+0].binBoundsAndCenter(prim0,center0);
+ const vint4 bin0 = (vint4)mapping.bin(center0);
+
+ BBox prim1; Vec3fa center1;
+ prims[i+1].binBoundsAndCenter(prim1,center1);
+ const vint4 bin1 = (vint4)mapping.bin(center1);
+
+ /*! increase bounds for bins for even primitive */
+ const unsigned int b00 = extract<0>(bin0); bounds(b00,0).extend(prim0);
+ const unsigned int b01 = extract<1>(bin0); bounds(b01,1).extend(prim0);
+ const unsigned int b02 = extract<2>(bin0); bounds(b02,2).extend(prim0);
+ const unsigned int s0 = (unsigned int)prims[i+0].size();
+ counts(b00,0)+=s0;
+ counts(b01,1)+=s0;
+ counts(b02,2)+=s0;
+
+ /*! increase bounds of bins for odd primitive */
+ const unsigned int b10 = extract<0>(bin1); bounds(b10,0).extend(prim1);
+ const unsigned int b11 = extract<1>(bin1); bounds(b11,1).extend(prim1);
+ const unsigned int b12 = extract<2>(bin1); bounds(b12,2).extend(prim1);
+ const unsigned int s1 = (unsigned int)prims[i+1].size();
+ counts(b10,0)+=s1;
+ counts(b11,1)+=s1;
+ counts(b12,2)+=s1;
+ }
+ /*! for uneven number of primitives */
+ if (i < N)
+ {
+ /*! map primitive to bin */
+ BBox prim0; Vec3fa center0;
+ prims[i].binBoundsAndCenter(prim0,center0);
+ const vint4 bin0 = (vint4)mapping.bin(center0);
+
+ /*! increase bounds of bins */
+ const unsigned int s0 = (unsigned int)prims[i].size();
+ const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
+ const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
+ const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
+ }
+ }
+
+ /*! bins an array of primitives */
+ template<typename BinBoundsAndCenter>
+ __forceinline void bin (const PrimRef* prims, size_t N, const BinMapping<BINS>& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
+ {
+ if (N == 0) return;
+
+ size_t i;
+ for (i=0; i<N-1; i+=2)
+ {
+ /*! map even and odd primitive to bin */
+ BBox prim0; Vec3fa center0; binBoundsAndCenter.binBoundsAndCenter(prims[i+0],prim0,center0);
+ const vint4 bin0 = (vint4)mapping.bin(center0);
+ BBox prim1; Vec3fa center1; binBoundsAndCenter.binBoundsAndCenter(prims[i+1],prim1,center1);
+ const vint4 bin1 = (vint4)mapping.bin(center1);
+
+ /*! increase bounds for bins for even primitive */
+ const unsigned int s0 = prims[i+0].size();
+ const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
+ const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
+ const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
+
+ /*! increase bounds of bins for odd primitive */
+ const unsigned int s1 = prims[i+1].size();
+ const int b10 = extract<0>(bin1); counts(b10,0)+=s1; bounds(b10,0).extend(prim1);
+ const int b11 = extract<1>(bin1); counts(b11,1)+=s1; bounds(b11,1).extend(prim1);
+ const int b12 = extract<2>(bin1); counts(b12,2)+=s1; bounds(b12,2).extend(prim1);
+ }
+
+ /*! for uneven number of primitives */
+ if (i < N)
+ {
+ /*! map primitive to bin */
+ BBox prim0; Vec3fa center0; binBoundsAndCenter.binBoundsAndCenter(prims[i+0],prim0,center0);
+ const vint4 bin0 = (vint4)mapping.bin(center0);
+
+ /*! increase bounds of bins */
+ const unsigned int s0 = prims[i+0].size();
+ const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
+ const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
+ const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
+ }
+ }
+
+ __forceinline void bin(const PrimRef* prims, size_t begin, size_t end, const BinMapping<BINS>& mapping) {
+ bin(prims+begin,end-begin,mapping);
+ }
+
+ template<typename BinBoundsAndCenter>
+ __forceinline void bin(const PrimRef* prims, size_t begin, size_t end, const BinMapping<BINS>& mapping, const BinBoundsAndCenter& binBoundsAndCenter) {
+ bin<BinBoundsAndCenter>(prims+begin,end-begin,mapping,binBoundsAndCenter);
+ }
+
+ /*! merges in other binning information */
+ __forceinline void merge (const BinInfoT& other, size_t numBins)
+ {
+
+ for (size_t i=0; i<numBins; i++)
+ {
+ counts(i) += other.counts(i);
+ bounds(i,0).extend(other.bounds(i,0));
+ bounds(i,1).extend(other.bounds(i,1));
+ bounds(i,2).extend(other.bounds(i,2));
+ }
+ }
+
+ /*! reduces binning information */
+ static __forceinline const BinInfoT reduce (const BinInfoT& a, const BinInfoT& b, const size_t numBins = BINS)
+ {
+ BinInfoT c;
+ for (size_t i=0; i<numBins; i++)
+ {
+ c.counts(i) = a.counts(i)+b.counts(i);
+ c.bounds(i,0) = embree::merge(a.bounds(i,0),b.bounds(i,0));
+ c.bounds(i,1) = embree::merge(a.bounds(i,1),b.bounds(i,1));
+ c.bounds(i,2) = embree::merge(a.bounds(i,2),b.bounds(i,2));
+ }
+ return c;
+ }
+
+ /*! finds the best split by scanning binning information */
+ __forceinline Split best(const BinMapping<BINS>& mapping, const size_t blocks_shift) const
+ {
+ /* sweep from right to left and compute parallel prefix of merged bounds */
+ vfloat4 rAreas[BINS];
+ vuint4 rCounts[BINS];
+ vuint4 count = 0; BBox bx = empty; BBox by = empty; BBox bz = empty;
+ for (size_t i=mapping.size()-1; i>0; i--)
+ {
+ count += counts(i);
+ rCounts[i] = count;
+ bx.extend(bounds(i,0)); rAreas[i][0] = expectedApproxHalfArea(bx);
+ by.extend(bounds(i,1)); rAreas[i][1] = expectedApproxHalfArea(by);
+ bz.extend(bounds(i,2)); rAreas[i][2] = expectedApproxHalfArea(bz);
+ rAreas[i][3] = 0.0f;
+ }
+ /* sweep from left to right and compute SAH */
+ vuint4 blocks_add = (1 << blocks_shift)-1;
+ vuint4 ii = 1; vfloat4 vbestSAH = pos_inf; vuint4 vbestPos = 0;
+ count = 0; bx = empty; by = empty; bz = empty;
+ for (size_t i=1; i<mapping.size(); i++, ii+=1)
+ {
+ count += counts(i-1);
+ bx.extend(bounds(i-1,0)); float Ax = expectedApproxHalfArea(bx);
+ by.extend(bounds(i-1,1)); float Ay = expectedApproxHalfArea(by);
+ bz.extend(bounds(i-1,2)); float Az = expectedApproxHalfArea(bz);
+ const vfloat4 lArea = vfloat4(Ax,Ay,Az,Az);
+ const vfloat4 rArea = rAreas[i];
+ const vuint4 lCount = (count +blocks_add) >> (unsigned int)(blocks_shift); // if blocks_shift >=1 then lCount < 4B and could be represented with an vint4, which would allow for faster vfloat4 conversions.
+ const vuint4 rCount = (rCounts[i]+blocks_add) >> (unsigned int)(blocks_shift);
+ const vfloat4 sah = madd(lArea,vfloat4(lCount),rArea*vfloat4(rCount));
+ //const vfloat4 sah = madd(lArea,vfloat4(vint4(lCount)),rArea*vfloat4(vint4(rCount)));
+
+ vbestPos = select(sah < vbestSAH,ii ,vbestPos);
+ vbestSAH = select(sah < vbestSAH,sah,vbestSAH);
+ }
+
+ /* find best dimension */
+ float bestSAH = inf;
+ int bestDim = -1;
+ int bestPos = 0;
+ for (int dim=0; dim<3; dim++)
+ {
+ /* ignore zero sized dimensions */
+ if (unlikely(mapping.invalid(dim)))
+ continue;
+
+ /* test if this is a better dimension */
+ if (vbestSAH[dim] < bestSAH && vbestPos[dim] != 0) {
+ bestDim = dim;
+ bestPos = vbestPos[dim];
+ bestSAH = vbestSAH[dim];
+ }
+ }
+ return Split(bestSAH,bestDim,bestPos,mapping);
+ }
+
+ /*! calculates extended split information */
+ __forceinline void getSplitInfo(const BinMapping<BINS>& mapping, const Split& split, SplitInfoT<BBox>& info) const
+ {
+ if (split.dim == -1) {
+ new (&info) SplitInfoT<BBox>(0,empty,0,empty);
+ return;
+ }
+
+ size_t leftCount = 0;
+ BBox leftBounds = empty;
+ for (size_t i=0; i<(size_t)split.pos; i++) {
+ leftCount += counts(i,split.dim);
+ leftBounds.extend(bounds(i,split.dim));
+ }
+ size_t rightCount = 0;
+ BBox rightBounds = empty;
+ for (size_t i=split.pos; i<mapping.size(); i++) {
+ rightCount += counts(i,split.dim);
+ rightBounds.extend(bounds(i,split.dim));
+ }
+ new (&info) SplitInfoT<BBox>(leftCount,leftBounds,rightCount,rightBounds);
+ }
+
+ /*! gets the number of primitives left of the split */
+ __forceinline size_t getLeftCount(const BinMapping<BINS>& mapping, const Split& split) const
+ {
+ if (unlikely(split.dim == -1)) return -1;
+
+ size_t leftCount = 0;
+ for (size_t i = 0; i < (size_t)split.pos; i++) {
+ leftCount += counts(i, split.dim);
+ }
+ return leftCount;
+ }
+
+ /*! gets the number of primitives right of the split */
+ __forceinline size_t getRightCount(const BinMapping<BINS>& mapping, const Split& split) const
+ {
+ if (unlikely(split.dim == -1)) return -1;
+
+ size_t rightCount = 0;
+ for (size_t i = (size_t)split.pos; i<mapping.size(); i++) {
+ rightCount += counts(i, split.dim);
+ }
+ return rightCount;
+ }
+
+ private:
+ BBox _bounds[BINS][3]; //!< geometry bounds for each bin in each dimension
+ vuint4 _counts[BINS]; //!< counts number of primitives that map into the bins
+ };
+ }
+
+ template<typename BinInfoT, typename BinMapping, typename PrimRef>
+ __forceinline void bin_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, const BinMapping& mapping)
+ {
+ if (likely(end-begin < parallelThreshold)) {
+ binner.bin(prims,begin,end,mapping);
+ } else {
+ binner = parallel_reduce(begin,end,blockSize,binner,
+ [&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping); return binner; },
+ [&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
+ }
+ }
+
+ template<typename BinBoundsAndCenter, typename BinInfoT, typename BinMapping, typename PrimRef>
+ __forceinline void bin_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, const BinMapping& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
+ {
+ if (likely(end-begin < parallelThreshold)) {
+ binner.bin(prims,begin,end,mapping,binBoundsAndCenter);
+ } else {
+ binner = parallel_reduce(begin,end,blockSize,binner,
+ [&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping, binBoundsAndCenter); return binner; },
+ [&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
+ }
+ }
+
+ template<bool parallel, typename BinInfoT, typename BinMapping, typename PrimRef>
+ __forceinline void bin_serial_or_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, const BinMapping& mapping)
+ {
+ if (!parallel) {
+ binner.bin(prims,begin,end,mapping);
+ } else {
+ binner = parallel_reduce(begin,end,blockSize,binner,
+ [&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping); return binner; },
+ [&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
+ }
+ }
+
+ template<bool parallel, typename BinBoundsAndCenter, typename BinInfoT, typename BinMapping, typename PrimRef>
+ __forceinline void bin_serial_or_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, const BinMapping& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
+ {
+ if (!parallel) {
+ binner.bin(prims,begin,end,mapping,binBoundsAndCenter);
+ } else {
+ binner = parallel_reduce(begin,end,blockSize,binner,
+ [&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping, binBoundsAndCenter); return binner; },
+ [&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/heuristic_binning_array_aligned.h b/thirdparty/embree/kernels/builders/heuristic_binning_array_aligned.h
new file mode 100644
index 0000000000..ab3b97efb9
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/heuristic_binning_array_aligned.h
@@ -0,0 +1,200 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "heuristic_binning.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct PrimInfoRange : public CentGeomBBox3fa, public range<size_t>
+ {
+ __forceinline PrimInfoRange () {
+ }
+
+ __forceinline PrimInfoRange(const PrimInfo& pinfo)
+ : CentGeomBBox3fa(pinfo), range<size_t>(pinfo.begin,pinfo.end) {}
+
+ __forceinline PrimInfoRange(EmptyTy)
+ : CentGeomBBox3fa(EmptyTy()), range<size_t>(0,0) {}
+
+ __forceinline PrimInfoRange (size_t begin, size_t end, const CentGeomBBox3fa& centGeomBounds)
+ : CentGeomBBox3fa(centGeomBounds), range<size_t>(begin,end) {}
+
+ __forceinline float leafSAH() const {
+ return expectedApproxHalfArea(geomBounds)*float(size());
+ }
+
+ __forceinline float leafSAH(size_t block_shift) const {
+ return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
+ }
+ };
+
+ /*! Performs standard object binning */
+ template<typename PrimRef, size_t BINS>
+ struct HeuristicArrayBinningSAH
+ {
+ typedef BinSplit<BINS> Split;
+ typedef BinInfoT<BINS,PrimRef,BBox3fa> Binner;
+ typedef range<size_t> Set;
+
+ static const size_t PARALLEL_THRESHOLD = 3 * 1024;
+ static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
+ static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
+
+ __forceinline HeuristicArrayBinningSAH ()
+ : prims(nullptr) {}
+
+ /*! remember prim array */
+ __forceinline HeuristicArrayBinningSAH (PrimRef* prims)
+ : prims(prims) {}
+
+ /*! finds the best split */
+ __noinline const Split find(const PrimInfoRange& pinfo, const size_t logBlockSize)
+ {
+ if (likely(pinfo.size() < PARALLEL_THRESHOLD))
+ return find_template<false>(pinfo,logBlockSize);
+ else
+ return find_template<true>(pinfo,logBlockSize);
+ }
+
+ template<bool parallel>
+ __forceinline const Split find_template(const PrimInfoRange& pinfo, const size_t logBlockSize)
+ {
+ Binner binner(empty);
+ const BinMapping<BINS> mapping(pinfo);
+ bin_serial_or_parallel<parallel>(binner,prims,pinfo.begin(),pinfo.end(),PARALLEL_FIND_BLOCK_SIZE,mapping);
+ return binner.best(mapping,logBlockSize);
+ }
+
+ /*! array partitioning */
+ __forceinline void split(const Split& split, const PrimInfoRange& pinfo, PrimInfoRange& linfo, PrimInfoRange& rinfo)
+ {
+ if (likely(pinfo.size() < PARALLEL_THRESHOLD))
+ split_template<false>(split,pinfo,linfo,rinfo);
+ else
+ split_template<true>(split,pinfo,linfo,rinfo);
+ }
+
+ template<bool parallel>
+ __forceinline void split_template(const Split& split, const PrimInfoRange& set, PrimInfoRange& lset, PrimInfoRange& rset)
+ {
+ if (!split.valid()) {
+ deterministic_order(set);
+ return splitFallback(set,lset,rset);
+ }
+
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ CentGeomBBox3fa local_left(empty);
+ CentGeomBBox3fa local_right(empty);
+ const unsigned int splitPos = split.pos;
+ const unsigned int splitDim = split.dim;
+ const unsigned int splitDimMask = (unsigned int)1 << splitDim;
+
+ const typename Binner::vint vSplitPos(splitPos);
+ const typename Binner::vbool vSplitMask(splitDimMask);
+ auto isLeft = [&] (const PrimRef &ref) { return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask); };
+
+ size_t center = 0;
+ if (!parallel)
+ center = serial_partitioning(prims,begin,end,local_left,local_right,isLeft,
+ [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend_center2(ref); });
+ else
+ center = parallel_partitioning(
+ prims,begin,end,EmptyTy(),local_left,local_right,isLeft,
+ [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend_center2(ref); },
+ [] (CentGeomBBox3fa& pinfo0,const CentGeomBBox3fa& pinfo1) { pinfo0.merge(pinfo1); },
+ PARALLEL_PARTITION_BLOCK_SIZE);
+
+ new (&lset) PrimInfoRange(begin,center,local_left);
+ new (&rset) PrimInfoRange(center,end,local_right);
+ assert(area(lset.geomBounds) >= 0.0f);
+ assert(area(rset.geomBounds) >= 0.0f);
+ }
+
+ void deterministic_order(const PrimInfoRange& pinfo)
+ {
+ /* required as parallel partition destroys original primitive order */
+ std::sort(&prims[pinfo.begin()],&prims[pinfo.end()]);
+ }
+
+ void splitFallback(const PrimInfoRange& pinfo, PrimInfoRange& linfo, PrimInfoRange& rinfo)
+ {
+ const size_t begin = pinfo.begin();
+ const size_t end = pinfo.end();
+ const size_t center = (begin + end)/2;
+
+ CentGeomBBox3fa left(empty);
+ for (size_t i=begin; i<center; i++)
+ left.extend_center2(prims[i]);
+ new (&linfo) PrimInfoRange(begin,center,left);
+
+ CentGeomBBox3fa right(empty);
+ for (size_t i=center; i<end; i++)
+ right.extend_center2(prims[i]);
+ new (&rinfo) PrimInfoRange(center,end,right);
+ }
+
+ void splitByGeometry(const range<size_t>& range, PrimInfoRange& linfo, PrimInfoRange& rinfo)
+ {
+ assert(range.size() > 1);
+ CentGeomBBox3fa left(empty);
+ CentGeomBBox3fa right(empty);
+ unsigned int geomID = prims[range.begin()].geomID();
+ size_t center = serial_partitioning(prims,range.begin(),range.end(),left,right,
+ [&] ( const PrimRef& prim ) { return prim.geomID() == geomID; },
+ [ ] ( CentGeomBBox3fa& a, const PrimRef& ref ) { a.extend_center2(ref); });
+
+ new (&linfo) PrimInfoRange(range.begin(),center,left);
+ new (&rinfo) PrimInfoRange(center,range.end(),right);
+ }
+
+ private:
+ PrimRef* const prims;
+ };
+
+ /*! Performs standard object binning */
+ template<typename PrimRefMB, size_t BINS>
+ struct HeuristicArrayBinningMB
+ {
+ typedef BinSplit<BINS> Split;
+ typedef typename PrimRefMB::BBox BBox;
+ typedef BinInfoT<BINS,PrimRefMB,BBox> ObjectBinner;
+ static const size_t PARALLEL_THRESHOLD = 3 * 1024;
+ static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
+ static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
+
+ /*! finds the best split */
+ const Split find(const SetMB& set, const size_t logBlockSize)
+ {
+ ObjectBinner binner(empty);
+ const BinMapping<BINS> mapping(set.size(),set.centBounds);
+ bin_parallel(binner,set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,mapping);
+ Split osplit = binner.best(mapping,logBlockSize);
+ osplit.sah *= set.time_range.size();
+ if (!osplit.valid()) osplit.data = Split::SPLIT_FALLBACK; // use fallback split
+ return osplit;
+ }
+
+ /*! array partitioning */
+ __forceinline void split(const Split& split, const SetMB& set, SetMB& lset, SetMB& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfoMB left = empty;
+ PrimInfoMB right = empty;
+ const vint4 vSplitPos(split.pos);
+ const vbool4 vSplitMask(1 << split.dim);
+ auto isLeft = [&] (const PrimRefMB &ref) { return any(((vint4)split.mapping.bin_unsafe(ref) < vSplitPos) & vSplitMask); };
+ auto reduction = [] (PrimInfoMB& pinfo, const PrimRefMB& ref) { pinfo.add_primref(ref); };
+ auto reduction2 = [] (PrimInfoMB& pinfo0,const PrimInfoMB& pinfo1) { pinfo0.merge(pinfo1); };
+ size_t center = parallel_partitioning(set.prims->data(),begin,end,EmptyTy(),left,right,isLeft,reduction,reduction2,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD);
+ new (&lset) SetMB(left, set.prims,range<size_t>(begin,center),set.time_range);
+ new (&rset) SetMB(right,set.prims,range<size_t>(center,end ),set.time_range);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/heuristic_binning_array_unaligned.h b/thirdparty/embree/kernels/builders/heuristic_binning_array_unaligned.h
new file mode 100644
index 0000000000..34a7f121bb
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/heuristic_binning_array_unaligned.h
@@ -0,0 +1,302 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "heuristic_binning.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Performs standard object binning */
+ template<typename PrimRef, size_t BINS>
+ struct UnalignedHeuristicArrayBinningSAH
+ {
+ typedef BinSplit<BINS> Split;
+ typedef BinInfoT<BINS,PrimRef,BBox3fa> Binner;
+ typedef range<size_t> Set;
+
+ __forceinline UnalignedHeuristicArrayBinningSAH () // FIXME: required?
+ : scene(nullptr), prims(nullptr) {}
+
+ /*! remember prim array */
+ __forceinline UnalignedHeuristicArrayBinningSAH (Scene* scene, PrimRef* prims)
+ : scene(scene), prims(prims) {}
+
+ const LinearSpace3fa computeAlignedSpace(const range<size_t>& set)
+ {
+ Vec3fa axis(0,0,1);
+ uint64_t bestGeomPrimID = -1;
+
+ /*! find curve with minimum ID that defines valid direction */
+ for (size_t i=set.begin(); i<set.end(); i++)
+ {
+ const unsigned int geomID = prims[i].geomID();
+ const unsigned int primID = prims[i].primID();
+ const uint64_t geomprimID = prims[i].ID64();
+ if (geomprimID >= bestGeomPrimID) continue;
+ const Vec3fa axis1 = scene->get(geomID)->computeDirection(primID);
+ if (sqr_length(axis1) > 1E-18f) {
+ axis = normalize(axis1);
+ bestGeomPrimID = geomprimID;
+ }
+ }
+ return frame(axis).transposed();
+ }
+
+ const PrimInfo computePrimInfo(const range<size_t>& set, const LinearSpace3fa& space)
+ {
+ auto computeBounds = [&](const range<size_t>& r) -> CentGeomBBox3fa
+ {
+ CentGeomBBox3fa bounds(empty);
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ Geometry* mesh = scene->get(prims[i].geomID());
+ bounds.extend(mesh->vbounds(space,prims[i].primID()));
+ }
+ return bounds;
+ };
+
+ const CentGeomBBox3fa bounds = parallel_reduce(set.begin(), set.end(), size_t(1024), size_t(4096),
+ CentGeomBBox3fa(empty), computeBounds, CentGeomBBox3fa::merge2);
+
+ return PrimInfo(set.begin(),set.end(),bounds);
+ }
+
+ struct BinBoundsAndCenter
+ {
+ __forceinline BinBoundsAndCenter(Scene* scene, const LinearSpace3fa& space)
+ : scene(scene), space(space) {}
+
+ /*! returns center for binning */
+ __forceinline Vec3fa binCenter(const PrimRef& ref) const
+ {
+ Geometry* mesh = (Geometry*) scene->get(ref.geomID());
+ BBox3fa bounds = mesh->vbounds(space,ref.primID());
+ return embree::center2(bounds);
+ }
+
+ /*! returns bounds and centroid used for binning */
+ __forceinline void binBoundsAndCenter(const PrimRef& ref, BBox3fa& bounds_o, Vec3fa& center_o) const
+ {
+ Geometry* mesh = (Geometry*) scene->get(ref.geomID());
+ BBox3fa bounds = mesh->vbounds(space,ref.primID());
+ bounds_o = bounds;
+ center_o = embree::center2(bounds);
+ }
+
+ private:
+ Scene* scene;
+ const LinearSpace3fa space;
+ };
+
+ /*! finds the best split */
+ __forceinline const Split find(const PrimInfoRange& pinfo, const size_t logBlockSize, const LinearSpace3fa& space)
+ {
+ if (likely(pinfo.size() < 10000))
+ return find_template<false>(pinfo,logBlockSize,space);
+ else
+ return find_template<true>(pinfo,logBlockSize,space);
+ }
+
+ /*! finds the best split */
+ template<bool parallel>
+ const Split find_template(const PrimInfoRange& set, const size_t logBlockSize, const LinearSpace3fa& space)
+ {
+ Binner binner(empty);
+ const BinMapping<BINS> mapping(set);
+ BinBoundsAndCenter binBoundsAndCenter(scene,space);
+ bin_serial_or_parallel<parallel>(binner,prims,set.begin(),set.end(),size_t(4096),mapping,binBoundsAndCenter);
+ return binner.best(mapping,logBlockSize);
+ }
+
+ /*! array partitioning */
+ __forceinline void split(const Split& split, const LinearSpace3fa& space, const Set& set, PrimInfoRange& lset, PrimInfoRange& rset)
+ {
+ if (likely(set.size() < 10000))
+ split_template<false>(split,space,set,lset,rset);
+ else
+ split_template<true>(split,space,set,lset,rset);
+ }
+
+ /*! array partitioning */
+ template<bool parallel>
+ __forceinline void split_template(const Split& split, const LinearSpace3fa& space, const Set& set, PrimInfoRange& lset, PrimInfoRange& rset)
+ {
+ if (!split.valid()) {
+ deterministic_order(set);
+ return splitFallback(set,lset,rset);
+ }
+
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ CentGeomBBox3fa local_left(empty);
+ CentGeomBBox3fa local_right(empty);
+ const int splitPos = split.pos;
+ const int splitDim = split.dim;
+ BinBoundsAndCenter binBoundsAndCenter(scene,space);
+
+ size_t center = 0;
+ if (likely(set.size() < 10000))
+ center = serial_partitioning(prims,begin,end,local_left,local_right,
+ [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,binBoundsAndCenter)[splitDim] < splitPos; },
+ [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend_center2(ref); });
+ else
+ center = parallel_partitioning(prims,begin,end,EmptyTy(),local_left,local_right,
+ [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,binBoundsAndCenter)[splitDim] < splitPos; },
+ [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend_center2(ref); },
+ [] (CentGeomBBox3fa& pinfo0,const CentGeomBBox3fa& pinfo1) { pinfo0.merge(pinfo1); },
+ 128);
+
+ new (&lset) PrimInfoRange(begin,center,local_left);
+ new (&rset) PrimInfoRange(center,end,local_right);
+ assert(area(lset.geomBounds) >= 0.0f);
+ assert(area(rset.geomBounds) >= 0.0f);
+ }
+
+ void deterministic_order(const range<size_t>& set)
+ {
+ /* required as parallel partition destroys original primitive order */
+ std::sort(&prims[set.begin()],&prims[set.end()]);
+ }
+
+ void splitFallback(const range<size_t>& set, PrimInfoRange& lset, PrimInfoRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ const size_t center = (begin + end)/2;
+
+ CentGeomBBox3fa left(empty);
+ for (size_t i=begin; i<center; i++)
+ left.extend_center2(prims[i]);
+ new (&lset) PrimInfoRange(begin,center,left);
+
+ CentGeomBBox3fa right(empty);
+ for (size_t i=center; i<end; i++)
+ right.extend_center2(prims[i]);
+ new (&rset) PrimInfoRange(center,end,right);
+ }
+
+ private:
+ Scene* const scene;
+ PrimRef* const prims;
+ };
+
+ /*! Performs standard object binning */
+ template<typename PrimRefMB, size_t BINS>
+ struct UnalignedHeuristicArrayBinningMB
+ {
+ typedef BinSplit<BINS> Split;
+ typedef typename PrimRefMB::BBox BBox;
+ typedef BinInfoT<BINS,PrimRefMB,BBox> ObjectBinner;
+
+ static const size_t PARALLEL_THRESHOLD = 3 * 1024;
+ static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
+ static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
+
+ UnalignedHeuristicArrayBinningMB(Scene* scene)
+ : scene(scene) {}
+
+ const LinearSpace3fa computeAlignedSpaceMB(Scene* scene, const SetMB& set)
+ {
+ Vec3fa axis0(0,0,1);
+ uint64_t bestGeomPrimID = -1;
+
+ /*! find curve with minimum ID that defines valid direction */
+ for (size_t i=set.begin(); i<set.end(); i++)
+ {
+ const PrimRefMB& prim = (*set.prims)[i];
+ const unsigned int geomID = prim.geomID();
+ const unsigned int primID = prim.primID();
+ const uint64_t geomprimID = prim.ID64();
+ if (geomprimID >= bestGeomPrimID) continue;
+
+ const Geometry* mesh = scene->get(geomID);
+ const range<int> tbounds = mesh->timeSegmentRange(set.time_range);
+ if (tbounds.size() == 0) continue;
+
+ const size_t t = (tbounds.begin()+tbounds.end())/2;
+ const Vec3fa axis1 = mesh->computeDirection(primID,t);
+ if (sqr_length(axis1) > 1E-18f) {
+ axis0 = normalize(axis1);
+ bestGeomPrimID = geomprimID;
+ }
+ }
+
+ return frame(axis0).transposed();
+ }
+
+ struct BinBoundsAndCenter
+ {
+ __forceinline BinBoundsAndCenter(Scene* scene, BBox1f time_range, const LinearSpace3fa& space)
+ : scene(scene), time_range(time_range), space(space) {}
+
+ /*! returns center for binning */
+ template<typename PrimRef>
+ __forceinline Vec3fa binCenter(const PrimRef& ref) const
+ {
+ Geometry* mesh = scene->get(ref.geomID());
+ LBBox3fa lbounds = mesh->vlinearBounds(space,ref.primID(),time_range);
+ return center2(lbounds.interpolate(0.5f));
+ }
+
+ /*! returns bounds and centroid used for binning */
+ __noinline void binBoundsAndCenter (const PrimRefMB& ref, BBox3fa& bounds_o, Vec3fa& center_o) const // __noinline is workaround for ICC16 bug under MacOSX
+ {
+ Geometry* mesh = scene->get(ref.geomID());
+ LBBox3fa lbounds = mesh->vlinearBounds(space,ref.primID(),time_range);
+ bounds_o = lbounds.interpolate(0.5f);
+ center_o = center2(bounds_o);
+ }
+
+ /*! returns bounds and centroid used for binning */
+ __noinline void binBoundsAndCenter (const PrimRefMB& ref, LBBox3fa& bounds_o, Vec3fa& center_o) const // __noinline is workaround for ICC16 bug under MacOSX
+ {
+ Geometry* mesh = scene->get(ref.geomID());
+ LBBox3fa lbounds = mesh->vlinearBounds(space,ref.primID(),time_range);
+ bounds_o = lbounds;
+ center_o = center2(lbounds.interpolate(0.5f));
+ }
+
+ private:
+ Scene* scene;
+ BBox1f time_range;
+ const LinearSpace3fa space;
+ };
+
+ /*! finds the best split */
+ const Split find(const SetMB& set, const size_t logBlockSize, const LinearSpace3fa& space)
+ {
+ BinBoundsAndCenter binBoundsAndCenter(scene,set.time_range,space);
+ ObjectBinner binner(empty);
+ const BinMapping<BINS> mapping(set.size(),set.centBounds);
+ bin_parallel(binner,set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,mapping,binBoundsAndCenter);
+ Split osplit = binner.best(mapping,logBlockSize);
+ osplit.sah *= set.time_range.size();
+ if (!osplit.valid()) osplit.data = Split::SPLIT_FALLBACK; // use fallback split
+ return osplit;
+ }
+
+ /*! array partitioning */
+ __forceinline void split(const Split& split, const LinearSpace3fa& space, const SetMB& set, SetMB& lset, SetMB& rset)
+ {
+ BinBoundsAndCenter binBoundsAndCenter(scene,set.time_range,space);
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfoMB left = empty;
+ PrimInfoMB right = empty;
+ const vint4 vSplitPos(split.pos);
+ const vbool4 vSplitMask(1 << split.dim);
+ auto isLeft = [&] (const PrimRefMB &ref) { return any(((vint4)split.mapping.bin_unsafe(ref,binBoundsAndCenter) < vSplitPos) & vSplitMask); };
+ auto reduction = [] (PrimInfoMB& pinfo, const PrimRefMB& ref) { pinfo.add_primref(ref); };
+ auto reduction2 = [] (PrimInfoMB& pinfo0,const PrimInfoMB& pinfo1) { pinfo0.merge(pinfo1); };
+ size_t center = parallel_partitioning(set.prims->data(),begin,end,EmptyTy(),left,right,isLeft,reduction,reduction2,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD);
+ new (&lset) SetMB(left,set.prims,range<size_t>(begin,center),set.time_range);
+ new (&rset) SetMB(right,set.prims,range<size_t>(center,end ),set.time_range);
+ }
+
+ private:
+ Scene* scene;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/heuristic_openmerge_array.h b/thirdparty/embree/kernels/builders/heuristic_openmerge_array.h
new file mode 100644
index 0000000000..4249d16ea1
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/heuristic_openmerge_array.h
@@ -0,0 +1,443 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+// TODO:
+// - adjust parallel build thresholds
+// - openNodesBasedOnExtend should consider max extended size
+
+#pragma once
+
+#include "heuristic_binning.h"
+#include "heuristic_spatial.h"
+
+/* stop opening of all bref.geomIDs are the same */
+#define EQUAL_GEOMID_STOP_CRITERIA 1
+
+/* 10% spatial extend threshold */
+#define MAX_EXTEND_THRESHOLD 0.1f
+
+/* maximum is 8 children */
+#define MAX_OPENED_CHILD_NODES 8
+
+/* open until all build refs are below threshold size in one step */
+#define USE_LOOP_OPENING 0
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Performs standard object binning */
+ template<typename NodeOpenerFunc, typename PrimRef, size_t OBJECT_BINS>
+ struct HeuristicArrayOpenMergeSAH
+ {
+ typedef BinSplit<OBJECT_BINS> Split;
+ typedef BinInfoT<OBJECT_BINS,PrimRef,BBox3fa> Binner;
+
+ static const size_t PARALLEL_THRESHOLD = 1024;
+ static const size_t PARALLEL_FIND_BLOCK_SIZE = 512;
+ static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
+
+ static const size_t MOVE_STEP_SIZE = 64;
+ static const size_t CREATE_SPLITS_STEP_SIZE = 128;
+
+ __forceinline HeuristicArrayOpenMergeSAH ()
+ : prims0(nullptr) {}
+
+ /*! remember prim array */
+ __forceinline HeuristicArrayOpenMergeSAH (const NodeOpenerFunc& nodeOpenerFunc, PrimRef* prims0, size_t max_open_size)
+ : prims0(prims0), nodeOpenerFunc(nodeOpenerFunc), max_open_size(max_open_size)
+ {
+ assert(max_open_size <= MAX_OPENED_CHILD_NODES);
+ }
+
+ struct OpenHeuristic
+ {
+ __forceinline OpenHeuristic( const PrimInfoExtRange& pinfo )
+ {
+ const Vec3fa diag = pinfo.geomBounds.size();
+ dim = maxDim(diag);
+ assert(diag[dim] > 0.0f);
+ inv_max_extend = 1.0f / diag[dim];
+ }
+
+ __forceinline bool operator () ( PrimRef& prim ) const {
+ return !prim.node.isLeaf() && prim.bounds().size()[dim] * inv_max_extend > MAX_EXTEND_THRESHOLD;
+ }
+
+ private:
+ size_t dim;
+ float inv_max_extend;
+ };
+
+ /*! compute extended ranges */
+ __forceinline void setExtentedRanges(const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset, const size_t lweight, const size_t rweight)
+ {
+ assert(set.ext_range_size() > 0);
+ const float left_factor = (float)lweight / (lweight + rweight);
+ const size_t ext_range_size = set.ext_range_size();
+ const size_t left_ext_range_size = min((size_t)(floorf(left_factor * ext_range_size)),ext_range_size);
+ const size_t right_ext_range_size = ext_range_size - left_ext_range_size;
+ lset.set_ext_range(lset.end() + left_ext_range_size);
+ rset.set_ext_range(rset.end() + right_ext_range_size);
+ }
+
+ /*! move ranges */
+ __forceinline void moveExtentedRange(const PrimInfoExtRange& set, const PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t left_ext_range_size = lset.ext_range_size();
+ const size_t right_size = rset.size();
+
+ /* has the left child an extended range? */
+ if (left_ext_range_size > 0)
+ {
+ /* left extended range smaller than right range ? */
+ if (left_ext_range_size < right_size)
+ {
+ /* only move a small part of the beginning of the right range to the end */
+ parallel_for( rset.begin(), rset.begin()+left_ext_range_size, MOVE_STEP_SIZE, [&](const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++)
+ prims0[i+right_size] = prims0[i];
+ });
+ }
+ else
+ {
+ /* no overlap, move entire right range to new location, can be made fully parallel */
+ parallel_for( rset.begin(), rset.end(), MOVE_STEP_SIZE, [&](const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++)
+ prims0[i+left_ext_range_size] = prims0[i];
+ });
+ }
+ /* update right range */
+ assert(rset.ext_end() + left_ext_range_size == set.ext_end());
+ rset.move_right(left_ext_range_size);
+ }
+ }
+
+ /* estimates the extra space required when opening, and checks if all primitives are from same geometry */
+ __noinline std::pair<size_t,bool> getProperties(const PrimInfoExtRange& set)
+ {
+ const OpenHeuristic heuristic(set);
+ const unsigned int geomID = prims0[set.begin()].geomID();
+
+ auto body = [&] (const range<size_t>& r) -> std::pair<size_t,bool> {
+ bool commonGeomID = true;
+ size_t opens = 0;
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ commonGeomID &= prims0[i].geomID() == geomID;
+ if (heuristic(prims0[i]))
+ opens += prims0[i].node.getN()-1; // coarse approximation
+ }
+ return std::pair<size_t,bool>(opens,commonGeomID);
+ };
+ auto reduction = [&] (const std::pair<size_t,bool>& b0, const std::pair<size_t,bool>& b1) -> std::pair<size_t,bool> {
+ return std::pair<size_t,bool>(b0.first+b1.first,b0.second && b1.second);
+ };
+ return parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,std::pair<size_t,bool>(0,true),body,reduction);
+ }
+
+ // FIXME: should consider maximum available extended size
+ __noinline void openNodesBasedOnExtend(PrimInfoExtRange& set)
+ {
+ const OpenHeuristic heuristic(set);
+ const size_t ext_range_start = set.end();
+
+ if (false && set.size() < PARALLEL_THRESHOLD)
+ {
+ size_t extra_elements = 0;
+ for (size_t i=set.begin(); i<set.end(); i++)
+ {
+ if (heuristic(prims0[i]))
+ {
+ PrimRef tmp[MAX_OPENED_CHILD_NODES];
+ const size_t n = nodeOpenerFunc(prims0[i],tmp);
+ assert(extra_elements + n-1 <= set.ext_range_size());
+ for (size_t j=0; j<n; j++)
+ set.extend_center2(tmp[j]);
+
+ prims0[i] = tmp[0];
+ for (size_t j=1; j<n; j++)
+ prims0[ext_range_start+extra_elements+j-1] = tmp[j];
+ extra_elements += n-1;
+ }
+ }
+ set._end += extra_elements;
+ }
+ else
+ {
+ std::atomic<size_t> ext_elements;
+ ext_elements.store(0);
+ PrimInfo info = parallel_reduce( set.begin(), set.end(), CREATE_SPLITS_STEP_SIZE, PrimInfo(empty), [&](const range<size_t>& r) -> PrimInfo {
+ PrimInfo info(empty);
+ for (size_t i=r.begin(); i<r.end(); i++)
+ if (heuristic(prims0[i]))
+ {
+ PrimRef tmp[MAX_OPENED_CHILD_NODES];
+ const size_t n = nodeOpenerFunc(prims0[i],tmp);
+ const size_t ID = ext_elements.fetch_add(n-1);
+ assert(ID + n-1 <= set.ext_range_size());
+
+ for (size_t j=0; j<n; j++)
+ info.extend_center2(tmp[j]);
+
+ prims0[i] = tmp[0];
+ for (size_t j=1; j<n; j++)
+ prims0[ext_range_start+ID+j-1] = tmp[j];
+ }
+ return info;
+ }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
+ set.centBounds.extend(info.centBounds);
+ assert(ext_elements.load() <= set.ext_range_size());
+ set._end += ext_elements.load();
+ }
+ }
+
+ __noinline void openNodesBasedOnExtendLoop(PrimInfoExtRange& set, const size_t est_new_elements)
+ {
+ const OpenHeuristic heuristic(set);
+ size_t next_iteration_extra_elements = est_new_elements;
+
+ while (next_iteration_extra_elements <= set.ext_range_size())
+ {
+ next_iteration_extra_elements = 0;
+ size_t extra_elements = 0;
+ const size_t ext_range_start = set.end();
+
+ for (size_t i=set.begin(); i<set.end(); i++)
+ {
+ if (heuristic(prims0[i]))
+ {
+ PrimRef tmp[MAX_OPENED_CHILD_NODES];
+ const size_t n = nodeOpenerFunc(prims0[i],tmp);
+ assert(extra_elements + n-1 <= set.ext_range_size());
+ for (size_t j=0;j<n;j++)
+ set.extend_center2(tmp[j]);
+
+ prims0[i] = tmp[0];
+ for (size_t j=1;j<n;j++)
+ prims0[ext_range_start+extra_elements+j-1] = tmp[j];
+ extra_elements += n-1;
+
+ for (size_t j=0; j<n; j++)
+ if (heuristic(tmp[j]))
+ next_iteration_extra_elements += tmp[j].node.getN()-1; // coarse approximation
+
+ }
+ }
+ assert( extra_elements <= set.ext_range_size());
+ set._end += extra_elements;
+
+ for (size_t i=set.begin();i<set.end();i++)
+ assert(prims0[i].numPrimitives() > 0);
+
+ if (unlikely(next_iteration_extra_elements == 0)) break;
+ }
+ }
+
+ __noinline const Split find(PrimInfoExtRange& set, const size_t logBlockSize)
+ {
+ /* single element */
+ if (set.size() <= 1)
+ return Split();
+
+ /* disable opening if there is no overlap */
+ const size_t D = 4;
+ if (unlikely(set.has_ext_range() && set.size() <= D))
+ {
+ bool disjoint = true;
+ for (size_t j=set.begin(); j<set.end()-1; j++) {
+ for (size_t i=set.begin()+1; i<set.end(); i++) {
+ if (conjoint(prims0[j].bounds(),prims0[i].bounds())) {
+ disjoint = false; break;
+ }
+ }
+ }
+ if (disjoint) set.set_ext_range(set.end()); /* disables opening */
+ }
+
+ std::pair<size_t,bool> p(0,false);
+
+ /* disable opening when all primitives are from same geometry */
+ if (unlikely(set.has_ext_range()))
+ {
+ p = getProperties(set);
+#if EQUAL_GEOMID_STOP_CRITERIA == 1
+ if (p.second) set.set_ext_range(set.end()); /* disable opening */
+#endif
+ }
+
+ /* open nodes when we have sufficient space available */
+ if (unlikely(set.has_ext_range()))
+ {
+#if USE_LOOP_OPENING == 1
+ openNodesBasedOnExtendLoop(set,p.first);
+#else
+ if (p.first <= set.ext_range_size())
+ openNodesBasedOnExtend(set);
+#endif
+
+ /* disable opening when unsufficient space for opening a node available */
+ if (set.ext_range_size() < max_open_size-1)
+ set.set_ext_range(set.end()); /* disable opening */
+ }
+
+ /* find best split */
+ return object_find(set,logBlockSize);
+ }
+
+
+ /*! finds the best object split */
+ __forceinline const Split object_find(const PrimInfoExtRange& set,const size_t logBlockSize)
+ {
+ if (set.size() < PARALLEL_THRESHOLD) return sequential_object_find(set,logBlockSize);
+ else return parallel_object_find (set,logBlockSize);
+ }
+
+ /*! finds the best object split */
+ __noinline const Split sequential_object_find(const PrimInfoExtRange& set, const size_t logBlockSize)
+ {
+ Binner binner(empty);
+ const BinMapping<OBJECT_BINS> mapping(set.centBounds);
+ binner.bin(prims0,set.begin(),set.end(),mapping);
+ return binner.best(mapping,logBlockSize);
+ }
+
+ /*! finds the best split */
+ __noinline const Split parallel_object_find(const PrimInfoExtRange& set, const size_t logBlockSize)
+ {
+ Binner binner(empty);
+ const BinMapping<OBJECT_BINS> mapping(set.centBounds);
+ const BinMapping<OBJECT_BINS>& _mapping = mapping; // CLANG 3.4 parser bug workaround
+ auto body = [&] (const range<size_t>& r) -> Binner {
+ Binner binner(empty); binner.bin(prims0+r.begin(),r.size(),_mapping); return binner;
+ };
+ auto reduction = [&] (const Binner& b0, const Binner& b1) -> Binner {
+ Binner r = b0; r.merge(b1,_mapping.size()); return r;
+ };
+ binner = parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,binner,body,reduction);
+ return binner.best(mapping,logBlockSize);
+ }
+
+ /*! array partitioning */
+ __noinline void split(const Split& split, const PrimInfoExtRange& set_i, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ PrimInfoExtRange set = set_i;
+
+ /* valid split */
+ if (unlikely(!split.valid())) {
+ deterministic_order(set);
+ splitFallback(set,lset,rset);
+ return;
+ }
+
+ std::pair<size_t,size_t> ext_weights(0,0);
+
+ /* object split */
+ if (likely(set.size() < PARALLEL_THRESHOLD))
+ ext_weights = sequential_object_split(split,set,lset,rset);
+ else
+ ext_weights = parallel_object_split(split,set,lset,rset);
+
+ /* if we have an extended range, set extended child ranges and move right split range */
+ if (unlikely(set.has_ext_range()))
+ {
+ setExtentedRanges(set,lset,rset,ext_weights.first,ext_weights.second);
+ moveExtentedRange(set,lset,rset);
+ }
+ }
+
+ /*! array partitioning */
+ std::pair<size_t,size_t> sequential_object_split(const Split& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfo local_left(empty);
+ PrimInfo local_right(empty);
+ const unsigned int splitPos = split.pos;
+ const unsigned int splitDim = split.dim;
+ const unsigned int splitDimMask = (unsigned int)1 << splitDim;
+
+ const vint4 vSplitPos(splitPos);
+ const vbool4 vSplitMask( (int)splitDimMask );
+
+ size_t center = serial_partitioning(prims0,
+ begin,end,local_left,local_right,
+ [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask); },
+ [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref); });
+
+ new (&lset) PrimInfoExtRange(begin,center,center,local_left);
+ new (&rset) PrimInfoExtRange(center,end,end,local_right);
+ assert(area(lset.geomBounds) >= 0.0f);
+ assert(area(rset.geomBounds) >= 0.0f);
+ return std::pair<size_t,size_t>(local_left.size(),local_right.size());
+ }
+
+ /*! array partitioning */
+ __noinline std::pair<size_t,size_t> parallel_object_split(const Split& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfo left(empty);
+ PrimInfo right(empty);
+ const unsigned int splitPos = split.pos;
+ const unsigned int splitDim = split.dim;
+ const unsigned int splitDimMask = (unsigned int)1 << splitDim;
+
+ const vint4 vSplitPos(splitPos);
+ const vbool4 vSplitMask( (int)splitDimMask );
+ auto isLeft = [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask); };
+
+ const size_t center = parallel_partitioning(
+ prims0,begin,end,EmptyTy(),left,right,isLeft,
+ [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref); },
+ [] (PrimInfo& pinfo0,const PrimInfo& pinfo1) { pinfo0.merge(pinfo1); },
+ PARALLEL_PARTITION_BLOCK_SIZE);
+
+ new (&lset) PrimInfoExtRange(begin,center,center,left);
+ new (&rset) PrimInfoExtRange(center,end,end,right);
+ assert(area(lset.geomBounds) >= 0.0f);
+ assert(area(rset.geomBounds) >= 0.0f);
+
+ return std::pair<size_t,size_t>(left.size(),right.size());
+ }
+
+ void deterministic_order(const extended_range<size_t>& set)
+ {
+ /* required as parallel partition destroys original primitive order */
+ std::sort(&prims0[set.begin()],&prims0[set.end()]);
+ }
+
+ __forceinline void splitFallback(const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ const size_t center = (begin + end)/2;
+
+ PrimInfo left(empty);
+ for (size_t i=begin; i<center; i++)
+ left.add_center2(prims0[i]);
+
+ const size_t lweight = left.end;
+
+ PrimInfo right(empty);
+ for (size_t i=center; i<end; i++)
+ right.add_center2(prims0[i]);
+
+ const size_t rweight = right.end;
+ new (&lset) PrimInfoExtRange(begin,center,center,left);
+ new (&rset) PrimInfoExtRange(center,end,end,right);
+
+ /* if we have an extended range */
+ if (set.has_ext_range())
+ {
+ setExtentedRanges(set,lset,rset,lweight,rweight);
+ moveExtentedRange(set,lset,rset);
+ }
+ }
+
+ private:
+ PrimRef* const prims0;
+ const NodeOpenerFunc& nodeOpenerFunc;
+ size_t max_open_size;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/heuristic_spatial.h b/thirdparty/embree/kernels/builders/heuristic_spatial.h
new file mode 100644
index 0000000000..a6939ba258
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/heuristic_spatial.h
@@ -0,0 +1,414 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/scene.h"
+#include "priminfo.h"
+
+namespace embree
+{
+ static const unsigned int RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS = 5;
+
+ namespace isa
+ {
+
+ /*! mapping into bins */
+ template<size_t BINS>
+ struct SpatialBinMapping
+ {
+ public:
+ __forceinline SpatialBinMapping() {}
+
+ /*! calculates the mapping */
+ __forceinline SpatialBinMapping(const CentGeomBBox3fa& pinfo)
+ {
+ const vfloat4 lower = (vfloat4) pinfo.geomBounds.lower;
+ const vfloat4 upper = (vfloat4) pinfo.geomBounds.upper;
+ const vfloat4 eps = 128.0f*vfloat4(ulp)*max(abs(lower),abs(upper));
+ const vfloat4 diag = max(eps,(vfloat4) pinfo.geomBounds.size());
+ scale = select(upper-lower <= eps,vfloat4(0.0f),vfloat4(BINS)/diag);
+ ofs = (vfloat4) pinfo.geomBounds.lower;
+ inv_scale = 1.0f / scale;
+ }
+
+ /*! slower but safe binning */
+ __forceinline vint4 bin(const Vec3fa& p) const
+ {
+ const vint4 i = floori((vfloat4(p)-ofs)*scale);
+ return clamp(i,vint4(0),vint4(BINS-1));
+ }
+
+ __forceinline std::pair<vint4,vint4> bin(const BBox3fa& b) const
+ {
+#if defined(__AVX__)
+ const vfloat8 ofs8(ofs);
+ const vfloat8 scale8(scale);
+ const vint8 lu = floori((vfloat8::loadu(&b)-ofs8)*scale8);
+ const vint8 c_lu = clamp(lu,vint8(zero),vint8(BINS-1));
+ return std::pair<vint4,vint4>(extract4<0>(c_lu),extract4<1>(c_lu));
+#else
+ const vint4 lower = floori((vfloat4(b.lower)-ofs)*scale);
+ const vint4 upper = floori((vfloat4(b.upper)-ofs)*scale);
+ const vint4 c_lower = clamp(lower,vint4(0),vint4(BINS-1));
+ const vint4 c_upper = clamp(upper,vint4(0),vint4(BINS-1));
+ return std::pair<vint4,vint4>(c_lower,c_upper);
+#endif
+ }
+
+
+ /*! calculates left spatial position of bin */
+ __forceinline float pos(const size_t bin, const size_t dim) const {
+ return madd(float(bin),inv_scale[dim],ofs[dim]);
+ }
+
+ /*! calculates left spatial position of bin */
+ template<size_t N>
+ __forceinline vfloat<N> posN(const vfloat<N> bin, const size_t dim) const {
+ return madd(bin,vfloat<N>(inv_scale[dim]),vfloat<N>(ofs[dim]));
+ }
+
+ /*! returns true if the mapping is invalid in some dimension */
+ __forceinline bool invalid(const size_t dim) const {
+ return scale[dim] == 0.0f;
+ }
+
+ public:
+ vfloat4 ofs,scale,inv_scale; //!< linear function that maps to bin ID
+ };
+
+ /*! stores all information required to perform some split */
+ template<size_t BINS>
+ struct SpatialBinSplit
+ {
+ /*! construct an invalid split by default */
+ __forceinline SpatialBinSplit()
+ : sah(inf), dim(-1), pos(0), left(-1), right(-1), factor(1.0f) {}
+
+ /*! constructs specified split */
+ __forceinline SpatialBinSplit(float sah, int dim, int pos, const SpatialBinMapping<BINS>& mapping)
+ : sah(sah), dim(dim), pos(pos), left(-1), right(-1), factor(1.0f), mapping(mapping) {}
+
+ /*! constructs specified split */
+ __forceinline SpatialBinSplit(float sah, int dim, int pos, int left, int right, float factor, const SpatialBinMapping<BINS>& mapping)
+ : sah(sah), dim(dim), pos(pos), left(left), right(right), factor(factor), mapping(mapping) {}
+
+ /*! tests if this split is valid */
+ __forceinline bool valid() const { return dim != -1; }
+
+ /*! calculates surface area heuristic for performing the split */
+ __forceinline float splitSAH() const { return sah; }
+
+ /*! stream output */
+ friend embree_ostream operator<<(embree_ostream cout, const SpatialBinSplit& split) {
+ return cout << "SpatialBinSplit { sah = " << split.sah << ", dim = " << split.dim << ", pos = " << split.pos << ", left = " << split.left << ", right = " << split.right << ", factor = " << split.factor << "}";
+ }
+
+ public:
+ float sah; //!< SAH cost of the split
+ int dim; //!< split dimension
+ int pos; //!< split position
+ int left; //!< number of elements on the left side
+ int right; //!< number of elements on the right side
+ float factor; //!< factor splitting the extended range
+ SpatialBinMapping<BINS> mapping; //!< mapping into bins
+ };
+
+ /*! stores all binning information */
+ template<size_t BINS, typename PrimRef>
+ struct __aligned(64) SpatialBinInfo
+ {
+ SpatialBinInfo() {
+ }
+
+ __forceinline SpatialBinInfo(EmptyTy) {
+ clear();
+ }
+
+ /*! clears the bin info */
+ __forceinline void clear()
+ {
+ for (size_t i=0; i<BINS; i++) {
+ bounds[i][0] = bounds[i][1] = bounds[i][2] = empty;
+ numBegin[i] = numEnd[i] = 0;
+ }
+ }
+
+ /*! adds binning data */
+ __forceinline void add(const size_t dim,
+ const size_t beginID,
+ const size_t endID,
+ const size_t binID,
+ const BBox3fa &b,
+ const size_t n = 1)
+ {
+ assert(beginID < BINS);
+ assert(endID < BINS);
+ assert(binID < BINS);
+
+ numBegin[beginID][dim]+=(unsigned int)n;
+ numEnd [endID][dim]+=(unsigned int)n;
+ bounds [binID][dim].extend(b);
+ }
+
+ /*! extends binning bounds */
+ __forceinline void extend(const size_t dim,
+ const size_t binID,
+ const BBox3fa &b)
+ {
+ assert(binID < BINS);
+ bounds [binID][dim].extend(b);
+ }
+
+ /*! bins an array of triangles */
+ template<typename SplitPrimitive>
+ __forceinline void bin(const SplitPrimitive& splitPrimitive, const PrimRef* prims, size_t N, const SpatialBinMapping<BINS>& mapping)
+ {
+ for (size_t i=0; i<N; i++)
+ {
+ const PrimRef prim = prims[i];
+ unsigned splits = prim.geomID() >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
+
+ if (unlikely(splits == 1))
+ {
+ const vint4 bin = mapping.bin(center(prim.bounds()));
+ for (size_t dim=0; dim<3; dim++)
+ {
+ assert(bin[dim] >= (int)0 && bin[dim] < (int)BINS);
+ numBegin[bin[dim]][dim]++;
+ numEnd [bin[dim]][dim]++;
+ bounds [bin[dim]][dim].extend(prim.bounds());
+ }
+ }
+ else
+ {
+ const vint4 bin0 = mapping.bin(prim.bounds().lower);
+ const vint4 bin1 = mapping.bin(prim.bounds().upper);
+
+ for (size_t dim=0; dim<3; dim++)
+ {
+ size_t bin;
+ PrimRef rest = prim;
+ size_t l = bin0[dim];
+ size_t r = bin1[dim];
+
+ // same bin optimization
+ if (likely(l == r))
+ {
+ numBegin[l][dim]++;
+ numEnd [l][dim]++;
+ bounds [l][dim].extend(prim.bounds());
+ continue;
+ }
+
+ for (bin=(size_t)bin0[dim]; bin<(size_t)bin1[dim]; bin++)
+ {
+ const float pos = mapping.pos(bin+1,dim);
+
+ PrimRef left,right;
+ splitPrimitive(rest,(int)dim,pos,left,right);
+ if (unlikely(left.bounds().empty())) l++;
+ bounds[bin][dim].extend(left.bounds());
+ rest = right;
+ }
+ if (unlikely(rest.bounds().empty())) r--;
+ numBegin[l][dim]++;
+ numEnd [r][dim]++;
+ bounds [bin][dim].extend(rest.bounds());
+ }
+ }
+ }
+ }
+
+ /*! bins a range of primitives inside an array */
+ template<typename SplitPrimitive>
+ void bin(const SplitPrimitive& splitPrimitive, const PrimRef* prims, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping) {
+ bin(splitPrimitive,prims+begin,end-begin,mapping);
+ }
+
+ /*! bins an array of primitives */
+ template<typename PrimitiveSplitterFactory>
+ __forceinline void bin2(const PrimitiveSplitterFactory& splitterFactory, const PrimRef* source, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping)
+ {
+ for (size_t i=begin; i<end; i++)
+ {
+ const PrimRef &prim = source[i];
+ const vint4 bin0 = mapping.bin(prim.bounds().lower);
+ const vint4 bin1 = mapping.bin(prim.bounds().upper);
+
+ for (size_t dim=0; dim<3; dim++)
+ {
+ if (unlikely(mapping.invalid(dim)))
+ continue;
+
+ size_t bin;
+ size_t l = bin0[dim];
+ size_t r = bin1[dim];
+
+ // same bin optimization
+ if (likely(l == r))
+ {
+ add(dim,l,l,l,prim.bounds());
+ continue;
+ }
+ const size_t bin_start = bin0[dim];
+ const size_t bin_end = bin1[dim];
+ BBox3fa rest = prim.bounds();
+ const auto splitter = splitterFactory(prim);
+ for (bin=bin_start; bin<bin_end; bin++)
+ {
+ const float pos = mapping.pos(bin+1,dim);
+ BBox3fa left,right;
+ splitter(rest,dim,pos,left,right);
+ if (unlikely(left.empty())) l++;
+ extend(dim,bin,left);
+ rest = right;
+ }
+ if (unlikely(rest.empty())) r--;
+ add(dim,l,r,bin,rest);
+ }
+ }
+ }
+
+
+
+ /*! bins an array of primitives */
+ __forceinline void binSubTreeRefs(const PrimRef* source, size_t begin, size_t end, const SpatialBinMapping<BINS>& mapping)
+ {
+ for (size_t i=begin; i<end; i++)
+ {
+ const PrimRef &prim = source[i];
+ const vint4 bin0 = mapping.bin(prim.bounds().lower);
+ const vint4 bin1 = mapping.bin(prim.bounds().upper);
+
+ for (size_t dim=0; dim<3; dim++)
+ {
+ if (unlikely(mapping.invalid(dim)))
+ continue;
+
+ const size_t l = bin0[dim];
+ const size_t r = bin1[dim];
+
+ const unsigned int n = prim.primID();
+
+ // same bin optimization
+ if (likely(l == r))
+ {
+ add(dim,l,l,l,prim.bounds(),n);
+ continue;
+ }
+ const size_t bin_start = bin0[dim];
+ const size_t bin_end = bin1[dim];
+ for (size_t bin=bin_start; bin<bin_end; bin++)
+ add(dim,l,r,bin,prim.bounds(),n);
+ }
+ }
+ }
+
+ /*! merges in other binning information */
+ void merge (const SpatialBinInfo& other)
+ {
+ for (size_t i=0; i<BINS; i++)
+ {
+ numBegin[i] += other.numBegin[i];
+ numEnd [i] += other.numEnd [i];
+ bounds[i][0].extend(other.bounds[i][0]);
+ bounds[i][1].extend(other.bounds[i][1]);
+ bounds[i][2].extend(other.bounds[i][2]);
+ }
+ }
+
+ /*! merges in other binning information */
+ static __forceinline const SpatialBinInfo reduce (const SpatialBinInfo& a, const SpatialBinInfo& b)
+ {
+ SpatialBinInfo c(empty);
+ for (size_t i=0; i<BINS; i++)
+ {
+ c.numBegin[i] += a.numBegin[i]+b.numBegin[i];
+ c.numEnd [i] += a.numEnd [i]+b.numEnd [i];
+ c.bounds[i][0] = embree::merge(a.bounds[i][0],b.bounds[i][0]);
+ c.bounds[i][1] = embree::merge(a.bounds[i][1],b.bounds[i][1]);
+ c.bounds[i][2] = embree::merge(a.bounds[i][2],b.bounds[i][2]);
+ }
+ return c;
+ }
+
+ /*! finds the best split by scanning binning information */
+ SpatialBinSplit<BINS> best(const SpatialBinMapping<BINS>& mapping, const size_t blocks_shift) const
+ {
+ /* sweep from right to left and compute parallel prefix of merged bounds */
+ vfloat4 rAreas[BINS];
+ vuint4 rCounts[BINS];
+ vuint4 count = 0; BBox3fa bx = empty; BBox3fa by = empty; BBox3fa bz = empty;
+ for (size_t i=BINS-1; i>0; i--)
+ {
+ count += numEnd[i];
+ rCounts[i] = count;
+ bx.extend(bounds[i][0]); rAreas[i][0] = halfArea(bx);
+ by.extend(bounds[i][1]); rAreas[i][1] = halfArea(by);
+ bz.extend(bounds[i][2]); rAreas[i][2] = halfArea(bz);
+ rAreas[i][3] = 0.0f;
+ }
+
+ /* sweep from left to right and compute SAH */
+ vuint4 blocks_add = (1 << blocks_shift)-1;
+ vuint4 ii = 1; vfloat4 vbestSAH = pos_inf; vuint4 vbestPos = 0; vuint4 vbestlCount = 0; vuint4 vbestrCount = 0;
+ count = 0; bx = empty; by = empty; bz = empty;
+ for (size_t i=1; i<BINS; i++, ii+=1)
+ {
+ count += numBegin[i-1];
+ bx.extend(bounds[i-1][0]); float Ax = halfArea(bx);
+ by.extend(bounds[i-1][1]); float Ay = halfArea(by);
+ bz.extend(bounds[i-1][2]); float Az = halfArea(bz);
+ const vfloat4 lArea = vfloat4(Ax,Ay,Az,Az);
+ const vfloat4 rArea = rAreas[i];
+ const vuint4 lCount = (count +blocks_add) >> (unsigned int)(blocks_shift);
+ const vuint4 rCount = (rCounts[i]+blocks_add) >> (unsigned int)(blocks_shift);
+ const vfloat4 sah = madd(lArea,vfloat4(lCount),rArea*vfloat4(rCount));
+ // const vfloat4 sah = madd(lArea,vfloat4(vint4(lCount)),rArea*vfloat4(vint4(rCount)));
+ const vbool4 mask = sah < vbestSAH;
+ vbestPos = select(mask,ii ,vbestPos);
+ vbestSAH = select(mask,sah,vbestSAH);
+ vbestlCount = select(mask,count,vbestlCount);
+ vbestrCount = select(mask,rCounts[i],vbestrCount);
+ }
+
+ /* find best dimension */
+ float bestSAH = inf;
+ int bestDim = -1;
+ int bestPos = 0;
+ unsigned int bestlCount = 0;
+ unsigned int bestrCount = 0;
+ for (int dim=0; dim<3; dim++)
+ {
+ /* ignore zero sized dimensions */
+ if (unlikely(mapping.invalid(dim)))
+ continue;
+
+ /* test if this is a better dimension */
+ if (vbestSAH[dim] < bestSAH && vbestPos[dim] != 0) {
+ bestDim = dim;
+ bestPos = vbestPos[dim];
+ bestSAH = vbestSAH[dim];
+ bestlCount = vbestlCount[dim];
+ bestrCount = vbestrCount[dim];
+ }
+ }
+ assert(bestSAH >= 0.0f);
+
+ /* return invalid split if no split found */
+ if (bestDim == -1)
+ return SpatialBinSplit<BINS>(inf,-1,0,mapping);
+
+ /* return best found split */
+ return SpatialBinSplit<BINS>(bestSAH,bestDim,bestPos,bestlCount,bestrCount,1.0f,mapping);
+ }
+
+ private:
+ BBox3fa bounds[BINS][3]; //!< geometry bounds for each bin in each dimension
+ vuint4 numBegin[BINS]; //!< number of primitives starting in bin
+ vuint4 numEnd[BINS]; //!< number of primitives ending in bin
+ };
+ }
+}
+
diff --git a/thirdparty/embree/kernels/builders/heuristic_spatial_array.h b/thirdparty/embree/kernels/builders/heuristic_spatial_array.h
new file mode 100644
index 0000000000..60d235f48d
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/heuristic_spatial_array.h
@@ -0,0 +1,546 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "heuristic_binning.h"
+#include "heuristic_spatial.h"
+
+namespace embree
+{
+ namespace isa
+ {
+#if 0
+#define SPATIAL_ASPLIT_OVERLAP_THRESHOLD 0.2f
+#define SPATIAL_ASPLIT_SAH_THRESHOLD 0.95f
+#define SPATIAL_ASPLIT_AREA_THRESHOLD 0.0f
+#else
+#define SPATIAL_ASPLIT_OVERLAP_THRESHOLD 0.1f
+#define SPATIAL_ASPLIT_SAH_THRESHOLD 0.99f
+#define SPATIAL_ASPLIT_AREA_THRESHOLD 0.000005f
+#endif
+
+ struct PrimInfoExtRange : public CentGeomBBox3fa, public extended_range<size_t>
+ {
+ __forceinline PrimInfoExtRange() {
+ }
+
+ __forceinline PrimInfoExtRange(EmptyTy)
+ : CentGeomBBox3fa(EmptyTy()), extended_range<size_t>(0,0,0) {}
+
+ __forceinline PrimInfoExtRange(size_t begin, size_t end, size_t ext_end, const CentGeomBBox3fa& centGeomBounds)
+ : CentGeomBBox3fa(centGeomBounds), extended_range<size_t>(begin,end,ext_end) {}
+
+ __forceinline float leafSAH() const {
+ return expectedApproxHalfArea(geomBounds)*float(size());
+ }
+
+ __forceinline float leafSAH(size_t block_shift) const {
+ return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
+ }
+ };
+
+ template<typename ObjectSplit, typename SpatialSplit>
+ struct Split2
+ {
+ __forceinline Split2 () {}
+
+ __forceinline Split2 (const Split2& other)
+ {
+ spatial = other.spatial;
+ sah = other.sah;
+ if (spatial) spatialSplit() = other.spatialSplit();
+ else objectSplit() = other.objectSplit();
+ }
+
+ __forceinline Split2& operator= (const Split2& other)
+ {
+ spatial = other.spatial;
+ sah = other.sah;
+ if (spatial) spatialSplit() = other.spatialSplit();
+ else objectSplit() = other.objectSplit();
+ return *this;
+ }
+
+ __forceinline ObjectSplit& objectSplit() { return *( ObjectSplit*)data; }
+ __forceinline const ObjectSplit& objectSplit() const { return *(const ObjectSplit*)data; }
+
+ __forceinline SpatialSplit& spatialSplit() { return *( SpatialSplit*)data; }
+ __forceinline const SpatialSplit& spatialSplit() const { return *(const SpatialSplit*)data; }
+
+ __forceinline Split2 (const ObjectSplit& objectSplit, float sah)
+ : spatial(false), sah(sah)
+ {
+ new (data) ObjectSplit(objectSplit);
+ }
+
+ __forceinline Split2 (const SpatialSplit& spatialSplit, float sah)
+ : spatial(true), sah(sah)
+ {
+ new (data) SpatialSplit(spatialSplit);
+ }
+
+ __forceinline float splitSAH() const {
+ return sah;
+ }
+
+ __forceinline bool valid() const {
+ return sah < float(inf);
+ }
+
+ public:
+ __aligned(64) char data[sizeof(ObjectSplit) > sizeof(SpatialSplit) ? sizeof(ObjectSplit) : sizeof(SpatialSplit)];
+ bool spatial;
+ float sah;
+ };
+
+ /*! Performs standard object binning */
+ template<typename PrimitiveSplitterFactory, typename PrimRef, size_t OBJECT_BINS, size_t SPATIAL_BINS>
+ struct HeuristicArraySpatialSAH
+ {
+ typedef BinSplit<OBJECT_BINS> ObjectSplit;
+ typedef BinInfoT<OBJECT_BINS,PrimRef,BBox3fa> ObjectBinner;
+
+ typedef SpatialBinSplit<SPATIAL_BINS> SpatialSplit;
+ typedef SpatialBinInfo<SPATIAL_BINS,PrimRef> SpatialBinner;
+
+ //typedef extended_range<size_t> Set;
+ typedef Split2<ObjectSplit,SpatialSplit> Split;
+
+ static const size_t PARALLEL_THRESHOLD = 3*1024;
+ static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
+ static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
+
+ static const size_t MOVE_STEP_SIZE = 64;
+ static const size_t CREATE_SPLITS_STEP_SIZE = 64;
+
+ __forceinline HeuristicArraySpatialSAH ()
+ : prims0(nullptr) {}
+
+ /*! remember prim array */
+ __forceinline HeuristicArraySpatialSAH (const PrimitiveSplitterFactory& splitterFactory, PrimRef* prims0, const CentGeomBBox3fa& root_info)
+ : prims0(prims0), splitterFactory(splitterFactory), root_info(root_info) {}
+
+
+ /*! compute extended ranges */
+ __noinline void setExtentedRanges(const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset, const size_t lweight, const size_t rweight)
+ {
+ assert(set.ext_range_size() > 0);
+ const float left_factor = (float)lweight / (lweight + rweight);
+ const size_t ext_range_size = set.ext_range_size();
+ const size_t left_ext_range_size = min((size_t)(floorf(left_factor * ext_range_size)),ext_range_size);
+ const size_t right_ext_range_size = ext_range_size - left_ext_range_size;
+ lset.set_ext_range(lset.end() + left_ext_range_size);
+ rset.set_ext_range(rset.end() + right_ext_range_size);
+ }
+
+ /*! move ranges */
+ __noinline void moveExtentedRange(const PrimInfoExtRange& set, const PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t left_ext_range_size = lset.ext_range_size();
+ const size_t right_size = rset.size();
+
+ /* has the left child an extended range? */
+ if (left_ext_range_size > 0)
+ {
+ /* left extended range smaller than right range ? */
+ if (left_ext_range_size < right_size)
+ {
+ /* only move a small part of the beginning of the right range to the end */
+ parallel_for( rset.begin(), rset.begin()+left_ext_range_size, MOVE_STEP_SIZE, [&](const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++)
+ prims0[i+right_size] = prims0[i];
+ });
+ }
+ else
+ {
+ /* no overlap, move entire right range to new location, can be made fully parallel */
+ parallel_for( rset.begin(), rset.end(), MOVE_STEP_SIZE, [&](const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++)
+ prims0[i+left_ext_range_size] = prims0[i];
+ });
+ }
+ /* update right range */
+ assert(rset.ext_end() + left_ext_range_size == set.ext_end());
+ rset.move_right(left_ext_range_size);
+ }
+ }
+
+ /*! finds the best split */
+ const Split find(const PrimInfoExtRange& set, const size_t logBlockSize)
+ {
+ SplitInfo oinfo;
+ const ObjectSplit object_split = object_find(set,logBlockSize,oinfo);
+ const float object_split_sah = object_split.splitSAH();
+
+ if (unlikely(set.has_ext_range()))
+ {
+ const BBox3fa overlap = intersect(oinfo.leftBounds, oinfo.rightBounds);
+
+ /* do only spatial splits if the child bounds overlap */
+ if (safeArea(overlap) >= SPATIAL_ASPLIT_AREA_THRESHOLD*safeArea(root_info.geomBounds) &&
+ safeArea(overlap) >= SPATIAL_ASPLIT_OVERLAP_THRESHOLD*safeArea(set.geomBounds))
+ {
+ const SpatialSplit spatial_split = spatial_find(set, logBlockSize);
+ const float spatial_split_sah = spatial_split.splitSAH();
+
+ /* valid spatial split, better SAH and number of splits do not exceed extended range */
+ if (spatial_split_sah < SPATIAL_ASPLIT_SAH_THRESHOLD*object_split_sah &&
+ spatial_split.left + spatial_split.right - set.size() <= set.ext_range_size())
+ {
+ return Split(spatial_split,spatial_split_sah);
+ }
+ }
+ }
+
+ return Split(object_split,object_split_sah);
+ }
+
+ /*! finds the best object split */
+ __forceinline const ObjectSplit object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
+ {
+ if (set.size() < PARALLEL_THRESHOLD) return sequential_object_find(set,logBlockSize,info);
+ else return parallel_object_find (set,logBlockSize,info);
+ }
+
+ /*! finds the best object split */
+ __noinline const ObjectSplit sequential_object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
+ {
+ ObjectBinner binner(empty);
+ const BinMapping<OBJECT_BINS> mapping(set);
+ binner.bin(prims0,set.begin(),set.end(),mapping);
+ ObjectSplit s = binner.best(mapping,logBlockSize);
+ binner.getSplitInfo(mapping, s, info);
+ return s;
+ }
+
+ /*! finds the best split */
+ __noinline const ObjectSplit parallel_object_find(const PrimInfoExtRange& set, const size_t logBlockSize, SplitInfo &info)
+ {
+ ObjectBinner binner(empty);
+ const BinMapping<OBJECT_BINS> mapping(set);
+ const BinMapping<OBJECT_BINS>& _mapping = mapping; // CLANG 3.4 parser bug workaround
+ binner = parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,binner,
+ [&] (const range<size_t>& r) -> ObjectBinner { ObjectBinner binner(empty); binner.bin(prims0+r.begin(),r.size(),_mapping); return binner; },
+ [&] (const ObjectBinner& b0, const ObjectBinner& b1) -> ObjectBinner { ObjectBinner r = b0; r.merge(b1,_mapping.size()); return r; });
+ ObjectSplit s = binner.best(mapping,logBlockSize);
+ binner.getSplitInfo(mapping, s, info);
+ return s;
+ }
+
+ /*! finds the best spatial split */
+ __forceinline const SpatialSplit spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
+ {
+ if (set.size() < PARALLEL_THRESHOLD) return sequential_spatial_find(set, logBlockSize);
+ else return parallel_spatial_find (set, logBlockSize);
+ }
+
+ /*! finds the best spatial split */
+ __noinline const SpatialSplit sequential_spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
+ {
+ SpatialBinner binner(empty);
+ const SpatialBinMapping<SPATIAL_BINS> mapping(set);
+ binner.bin2(splitterFactory,prims0,set.begin(),set.end(),mapping);
+ /* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/
+ return binner.best(mapping,logBlockSize); //,set.ext_size());
+ }
+
+ __noinline const SpatialSplit parallel_spatial_find(const PrimInfoExtRange& set, const size_t logBlockSize)
+ {
+ SpatialBinner binner(empty);
+ const SpatialBinMapping<SPATIAL_BINS> mapping(set);
+ const SpatialBinMapping<SPATIAL_BINS>& _mapping = mapping; // CLANG 3.4 parser bug workaround
+ binner = parallel_reduce(set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,binner,
+ [&] (const range<size_t>& r) -> SpatialBinner {
+ SpatialBinner binner(empty);
+ binner.bin2(splitterFactory,prims0,r.begin(),r.end(),_mapping);
+ return binner; },
+ [&] (const SpatialBinner& b0, const SpatialBinner& b1) -> SpatialBinner { return SpatialBinner::reduce(b0,b1); });
+ /* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/
+ return binner.best(mapping,logBlockSize); //,set.ext_size());
+ }
+
+
+ /*! subdivides primitives based on a spatial split */
+ __noinline void create_spatial_splits(PrimInfoExtRange& set, const SpatialSplit& split, const SpatialBinMapping<SPATIAL_BINS> &mapping)
+ {
+ assert(set.has_ext_range());
+ const size_t max_ext_range_size = set.ext_range_size();
+ const size_t ext_range_start = set.end();
+
+ /* atomic counter for number of primref splits */
+ std::atomic<size_t> ext_elements;
+ ext_elements.store(0);
+
+ const float fpos = split.mapping.pos(split.pos,split.dim);
+
+ const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
+
+ parallel_for( set.begin(), set.end(), CREATE_SPLITS_STEP_SIZE, [&](const range<size_t>& r) {
+ for (size_t i=r.begin();i<r.end();i++)
+ {
+ const unsigned int splits = prims0[i].geomID() >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
+
+ if (likely(splits <= 1)) continue; /* todo: does this ever happen ? */
+
+ //int bin0 = split.mapping.bin(prims0[i].lower)[split.dim];
+ //int bin1 = split.mapping.bin(prims0[i].upper)[split.dim];
+ //if (unlikely(bin0 < split.pos && bin1 >= split.pos))
+ if (unlikely(prims0[i].lower[split.dim] < fpos && prims0[i].upper[split.dim] > fpos))
+ {
+ assert(splits > 1);
+
+ PrimRef left,right;
+ const auto splitter = splitterFactory(prims0[i]);
+ splitter(prims0[i],split.dim,fpos,left,right);
+
+ // no empty splits
+ if (unlikely(left.bounds().empty() || right.bounds().empty())) continue;
+
+ left.lower.u = (left.lower.u & mask) | ((splits-1) << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS));
+ right.lower.u = (right.lower.u & mask) | ((splits-1) << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS));
+
+ const size_t ID = ext_elements.fetch_add(1);
+
+ /* break if the number of subdivided elements are greater than the maximum allowed size */
+ if (unlikely(ID >= max_ext_range_size))
+ break;
+
+ /* only write within the correct bounds */
+ assert(ID < max_ext_range_size);
+ prims0[i] = left;
+ prims0[ext_range_start+ID] = right;
+ }
+ }
+ });
+
+ const size_t numExtElements = min(max_ext_range_size,ext_elements.load());
+ assert(set.end()+numExtElements<=set.ext_end());
+ set._end += numExtElements;
+ }
+
+ /*! array partitioning */
+ void split(const Split& split, const PrimInfoExtRange& set_i, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ PrimInfoExtRange set = set_i;
+
+ /* valid split */
+ if (unlikely(!split.valid())) {
+ deterministic_order(set);
+ return splitFallback(set,lset,rset);
+ }
+
+ std::pair<size_t,size_t> ext_weights(0,0);
+
+ if (unlikely(split.spatial))
+ {
+ create_spatial_splits(set,split.spatialSplit(), split.spatialSplit().mapping);
+
+ /* spatial split */
+ if (likely(set.size() < PARALLEL_THRESHOLD))
+ ext_weights = sequential_spatial_split(split.spatialSplit(),set,lset,rset);
+ else
+ ext_weights = parallel_spatial_split(split.spatialSplit(),set,lset,rset);
+ }
+ else
+ {
+ /* object split */
+ if (likely(set.size() < PARALLEL_THRESHOLD))
+ ext_weights = sequential_object_split(split.objectSplit(),set,lset,rset);
+ else
+ ext_weights = parallel_object_split(split.objectSplit(),set,lset,rset);
+ }
+
+ /* if we have an extended range, set extended child ranges and move right split range */
+ if (unlikely(set.has_ext_range()))
+ {
+ setExtentedRanges(set,lset,rset,ext_weights.first,ext_weights.second);
+ moveExtentedRange(set,lset,rset);
+ }
+ }
+
+ /*! array partitioning */
+ std::pair<size_t,size_t> sequential_object_split(const ObjectSplit& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfo local_left(empty);
+ PrimInfo local_right(empty);
+ const unsigned int splitPos = split.pos;
+ const unsigned int splitDim = split.dim;
+ const unsigned int splitDimMask = (unsigned int)1 << splitDim;
+
+ const typename ObjectBinner::vint vSplitPos(splitPos);
+ const typename ObjectBinner::vbool vSplitMask(splitDimMask);
+ size_t center = serial_partitioning(prims0,
+ begin,end,local_left,local_right,
+ [&] (const PrimRef& ref) {
+ return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask);
+ },
+ [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); });
+ const size_t left_weight = local_left.end;
+ const size_t right_weight = local_right.end;
+
+ new (&lset) PrimInfoExtRange(begin,center,center,local_left);
+ new (&rset) PrimInfoExtRange(center,end,end,local_right);
+
+ assert(area(lset.geomBounds) >= 0.0f);
+ assert(area(rset.geomBounds) >= 0.0f);
+ return std::pair<size_t,size_t>(left_weight,right_weight);
+ }
+
+
+ /*! array partitioning */
+ __noinline std::pair<size_t,size_t> sequential_spatial_split(const SpatialSplit& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfo local_left(empty);
+ PrimInfo local_right(empty);
+ const unsigned int splitPos = split.pos;
+ const unsigned int splitDim = split.dim;
+ const unsigned int splitDimMask = (unsigned int)1 << splitDim;
+
+ /* init spatial mapping */
+ const SpatialBinMapping<SPATIAL_BINS> &mapping = split.mapping;
+ const vint4 vSplitPos(splitPos);
+ const vbool4 vSplitMask( (int)splitDimMask );
+
+ size_t center = serial_partitioning(prims0,
+ begin,end,local_left,local_right,
+ [&] (const PrimRef& ref) {
+ const Vec3fa c = ref.bounds().center();
+ return any(((vint4)mapping.bin(c) < vSplitPos) & vSplitMask);
+ },
+ [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); });
+
+ const size_t left_weight = local_left.end;
+ const size_t right_weight = local_right.end;
+
+ new (&lset) PrimInfoExtRange(begin,center,center,local_left);
+ new (&rset) PrimInfoExtRange(center,end,end,local_right);
+ assert(area(lset.geomBounds) >= 0.0f);
+ assert(area(rset.geomBounds) >= 0.0f);
+ return std::pair<size_t,size_t>(left_weight,right_weight);
+ }
+
+
+
+ /*! array partitioning */
+ __noinline std::pair<size_t,size_t> parallel_object_split(const ObjectSplit& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfo left(empty);
+ PrimInfo right(empty);
+ const unsigned int splitPos = split.pos;
+ const unsigned int splitDim = split.dim;
+ const unsigned int splitDimMask = (unsigned int)1 << splitDim;
+
+ const typename ObjectBinner::vint vSplitPos(splitPos);
+ const typename ObjectBinner::vbool vSplitMask(splitDimMask);
+ auto isLeft = [&] (const PrimRef &ref) { return split.mapping.bin_unsafe(ref,vSplitPos,vSplitMask); };
+
+ const size_t center = parallel_partitioning(
+ prims0,begin,end,EmptyTy(),left,right,isLeft,
+ [] (PrimInfo &pinfo,const PrimRef &ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); },
+ [] (PrimInfo &pinfo0,const PrimInfo &pinfo1) { pinfo0.merge(pinfo1); },
+ PARALLEL_PARTITION_BLOCK_SIZE);
+
+ const size_t left_weight = left.end;
+ const size_t right_weight = right.end;
+
+ left.begin = begin; left.end = center;
+ right.begin = center; right.end = end;
+
+ new (&lset) PrimInfoExtRange(begin,center,center,left);
+ new (&rset) PrimInfoExtRange(center,end,end,right);
+
+ assert(area(left.geomBounds) >= 0.0f);
+ assert(area(right.geomBounds) >= 0.0f);
+ return std::pair<size_t,size_t>(left_weight,right_weight);
+ }
+
+ /*! array partitioning */
+ __noinline std::pair<size_t,size_t> parallel_spatial_split(const SpatialSplit& split, const PrimInfoExtRange& set, PrimInfoExtRange& lset, PrimInfoExtRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ PrimInfo left(empty);
+ PrimInfo right(empty);
+ const unsigned int splitPos = split.pos;
+ const unsigned int splitDim = split.dim;
+ const unsigned int splitDimMask = (unsigned int)1 << splitDim;
+
+ /* init spatial mapping */
+ const SpatialBinMapping<SPATIAL_BINS>& mapping = split.mapping;
+ const vint4 vSplitPos(splitPos);
+ const vbool4 vSplitMask( (int)splitDimMask );
+
+ auto isLeft = [&] (const PrimRef &ref) {
+ const Vec3fa c = ref.bounds().center();
+ return any(((vint4)mapping.bin(c) < vSplitPos) & vSplitMask); };
+
+ const size_t center = parallel_partitioning(
+ prims0,begin,end,EmptyTy(),left,right,isLeft,
+ [] (PrimInfo &pinfo,const PrimRef &ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); },
+ [] (PrimInfo &pinfo0,const PrimInfo &pinfo1) { pinfo0.merge(pinfo1); },
+ PARALLEL_PARTITION_BLOCK_SIZE);
+
+ const size_t left_weight = left.end;
+ const size_t right_weight = right.end;
+
+ left.begin = begin; left.end = center;
+ right.begin = center; right.end = end;
+
+ new (&lset) PrimInfoExtRange(begin,center,center,left);
+ new (&rset) PrimInfoExtRange(center,end,end,right);
+
+ assert(area(left.geomBounds) >= 0.0f);
+ assert(area(right.geomBounds) >= 0.0f);
+ return std::pair<size_t,size_t>(left_weight,right_weight);
+ }
+
+ void deterministic_order(const PrimInfoExtRange& set)
+ {
+ /* required as parallel partition destroys original primitive order */
+ std::sort(&prims0[set.begin()],&prims0[set.end()]);
+ }
+
+ void splitFallback(const PrimInfoExtRange& set,
+ PrimInfoExtRange& lset,
+ PrimInfoExtRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ const size_t center = (begin + end)/2;
+
+ PrimInfo left(empty);
+ for (size_t i=begin; i<center; i++) {
+ left.add_center2(prims0[i],prims0[i].lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS));
+ }
+ const size_t lweight = left.end;
+
+ PrimInfo right(empty);
+ for (size_t i=center; i<end; i++) {
+ right.add_center2(prims0[i],prims0[i].lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS));
+ }
+ const size_t rweight = right.end;
+
+ new (&lset) PrimInfoExtRange(begin,center,center,left);
+ new (&rset) PrimInfoExtRange(center,end,end,right);
+
+ /* if we have an extended range */
+ if (set.has_ext_range()) {
+ setExtentedRanges(set,lset,rset,lweight,rweight);
+ moveExtentedRange(set,lset,rset);
+ }
+ }
+
+ private:
+ PrimRef* const prims0;
+ const PrimitiveSplitterFactory& splitterFactory;
+ const CentGeomBBox3fa& root_info;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/heuristic_strand_array.h b/thirdparty/embree/kernels/builders/heuristic_strand_array.h
new file mode 100644
index 0000000000..19c7fcdaa8
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/heuristic_strand_array.h
@@ -0,0 +1,188 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "priminfo.h"
+#include "../../common/algorithms/parallel_reduce.h"
+#include "../../common/algorithms/parallel_partition.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Performs standard object binning */
+ struct HeuristicStrandSplit
+ {
+ typedef range<size_t> Set;
+
+ static const size_t PARALLEL_THRESHOLD = 10000;
+ static const size_t PARALLEL_FIND_BLOCK_SIZE = 4096;
+ static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 64;
+
+ /*! stores all information to perform some split */
+ struct Split
+ {
+ /*! construct an invalid split by default */
+ __forceinline Split()
+ : sah(inf), axis0(zero), axis1(zero) {}
+
+ /*! constructs specified split */
+ __forceinline Split(const float sah, const Vec3fa& axis0, const Vec3fa& axis1)
+ : sah(sah), axis0(axis0), axis1(axis1) {}
+
+ /*! calculates standard surface area heuristic for the split */
+ __forceinline float splitSAH() const { return sah; }
+
+ /*! test if this split is valid */
+ __forceinline bool valid() const { return sah != float(inf); }
+
+ public:
+ float sah; //!< SAH cost of the split
+ Vec3fa axis0, axis1; //!< axis the two strands are aligned into
+ };
+
+ __forceinline HeuristicStrandSplit () // FIXME: required?
+ : scene(nullptr), prims(nullptr) {}
+
+ /*! remember prim array */
+ __forceinline HeuristicStrandSplit (Scene* scene, PrimRef* prims)
+ : scene(scene), prims(prims) {}
+
+ __forceinline const Vec3fa direction(const PrimRef& prim) {
+ return scene->get(prim.geomID())->computeDirection(prim.primID());
+ }
+
+ __forceinline const BBox3fa bounds(const PrimRef& prim) {
+ return scene->get(prim.geomID())->vbounds(prim.primID());
+ }
+
+ __forceinline const BBox3fa bounds(const LinearSpace3fa& space, const PrimRef& prim) {
+ return scene->get(prim.geomID())->vbounds(space,prim.primID());
+ }
+
+ /*! finds the best split */
+ const Split find(const range<size_t>& set, size_t logBlockSize)
+ {
+ Vec3fa axis0(0,0,1);
+ uint64_t bestGeomPrimID = -1;
+
+ /* curve with minimum ID determines first axis */
+ for (size_t i=set.begin(); i<set.end(); i++)
+ {
+ const uint64_t geomprimID = prims[i].ID64();
+ if (geomprimID >= bestGeomPrimID) continue;
+ const Vec3fa axis = direction(prims[i]);
+ if (sqr_length(axis) > 1E-18f) {
+ axis0 = normalize(axis);
+ bestGeomPrimID = geomprimID;
+ }
+ }
+
+ /* find 2nd axis that is most misaligned with first axis and has minimum ID */
+ float bestCos = 1.0f;
+ Vec3fa axis1 = axis0;
+ bestGeomPrimID = -1;
+ for (size_t i=set.begin(); i<set.end(); i++)
+ {
+ const uint64_t geomprimID = prims[i].ID64();
+ Vec3fa axisi = direction(prims[i]);
+ float leni = length(axisi);
+ if (leni == 0.0f) continue;
+ axisi /= leni;
+ float cos = abs(dot(axisi,axis0));
+ if ((cos == bestCos && (geomprimID < bestGeomPrimID)) || cos < bestCos) {
+ bestCos = cos; axis1 = axisi;
+ bestGeomPrimID = geomprimID;
+ }
+ }
+
+ /* partition the two strands */
+ size_t lnum = 0, rnum = 0;
+ BBox3fa lbounds = empty, rbounds = empty;
+ const LinearSpace3fa space0 = frame(axis0).transposed();
+ const LinearSpace3fa space1 = frame(axis1).transposed();
+
+ for (size_t i=set.begin(); i<set.end(); i++)
+ {
+ PrimRef& prim = prims[i];
+ const Vec3fa axisi = normalize(direction(prim));
+ const float cos0 = abs(dot(axisi,axis0));
+ const float cos1 = abs(dot(axisi,axis1));
+
+ if (cos0 > cos1) { lnum++; lbounds.extend(bounds(space0,prim)); }
+ else { rnum++; rbounds.extend(bounds(space1,prim)); }
+ }
+
+ /*! return an invalid split if we do not partition */
+ if (lnum == 0 || rnum == 0)
+ return Split(inf,axis0,axis1);
+
+ /*! calculate sah for the split */
+ const size_t lblocks = (lnum+(1ull<<logBlockSize)-1ull) >> logBlockSize;
+ const size_t rblocks = (rnum+(1ull<<logBlockSize)-1ull) >> logBlockSize;
+ const float sah = madd(float(lblocks),halfArea(lbounds),float(rblocks)*halfArea(rbounds));
+ return Split(sah,axis0,axis1);
+ }
+
+ /*! array partitioning */
+ void split(const Split& split, const PrimInfoRange& set, PrimInfoRange& lset, PrimInfoRange& rset)
+ {
+ if (!split.valid()) {
+ deterministic_order(set);
+ return splitFallback(set,lset,rset);
+ }
+
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ CentGeomBBox3fa local_left(empty);
+ CentGeomBBox3fa local_right(empty);
+
+ auto primOnLeftSide = [&] (const PrimRef& prim) -> bool {
+ const Vec3fa axisi = normalize(direction(prim));
+ const float cos0 = abs(dot(axisi,split.axis0));
+ const float cos1 = abs(dot(axisi,split.axis1));
+ return cos0 > cos1;
+ };
+
+ auto mergePrimBounds = [this] (CentGeomBBox3fa& pinfo,const PrimRef& ref) {
+ pinfo.extend(bounds(ref));
+ };
+
+ size_t center = serial_partitioning(prims,begin,end,local_left,local_right,primOnLeftSide,mergePrimBounds);
+
+ new (&lset) PrimInfoRange(begin,center,local_left);
+ new (&rset) PrimInfoRange(center,end,local_right);
+ assert(area(lset.geomBounds) >= 0.0f);
+ assert(area(rset.geomBounds) >= 0.0f);
+ }
+
+ void deterministic_order(const Set& set)
+ {
+ /* required as parallel partition destroys original primitive order */
+ std::sort(&prims[set.begin()],&prims[set.end()]);
+ }
+
+ void splitFallback(const Set& set, PrimInfoRange& lset, PrimInfoRange& rset)
+ {
+ const size_t begin = set.begin();
+ const size_t end = set.end();
+ const size_t center = (begin + end)/2;
+
+ CentGeomBBox3fa left(empty);
+ for (size_t i=begin; i<center; i++)
+ left.extend(bounds(prims[i]));
+ new (&lset) PrimInfoRange(begin,center,left);
+
+ CentGeomBBox3fa right(empty);
+ for (size_t i=center; i<end; i++)
+ right.extend(bounds(prims[i]));
+ new (&rset) PrimInfoRange(center,end,right);
+ }
+
+ private:
+ Scene* const scene;
+ PrimRef* const prims;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/heuristic_timesplit_array.h b/thirdparty/embree/kernels/builders/heuristic_timesplit_array.h
new file mode 100644
index 0000000000..b968e01c90
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/heuristic_timesplit_array.h
@@ -0,0 +1,237 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/primref_mb.h"
+#include "../../common/algorithms/parallel_filter.h"
+
+#define MBLUR_TIME_SPLIT_THRESHOLD 1.25f
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Performs standard object binning */
+ template<typename PrimRefMB, typename RecalculatePrimRef, size_t BINS>
+ struct HeuristicMBlurTemporalSplit
+ {
+ typedef BinSplit<MBLUR_NUM_OBJECT_BINS> Split;
+ typedef mvector<PrimRefMB>* PrimRefVector;
+ typedef typename PrimRefMB::BBox BBox;
+
+ static const size_t PARALLEL_THRESHOLD = 3 * 1024;
+ static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
+ static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
+
+ HeuristicMBlurTemporalSplit (MemoryMonitorInterface* device, const RecalculatePrimRef& recalculatePrimRef)
+ : device(device), recalculatePrimRef(recalculatePrimRef) {}
+
+ struct TemporalBinInfo
+ {
+ __forceinline TemporalBinInfo () {
+ }
+
+ __forceinline TemporalBinInfo (EmptyTy)
+ {
+ for (size_t i=0; i<BINS-1; i++)
+ {
+ count0[i] = count1[i] = 0;
+ bounds0[i] = bounds1[i] = empty;
+ }
+ }
+
+ void bin(const PrimRefMB* prims, size_t begin, size_t end, BBox1f time_range, const SetMB& set, const RecalculatePrimRef& recalculatePrimRef)
+ {
+ for (int b=0; b<BINS-1; b++)
+ {
+ const float t = float(b+1)/float(BINS);
+ const float ct = lerp(time_range.lower,time_range.upper,t);
+ const float center_time = set.align_time(ct);
+ if (center_time <= time_range.lower) continue;
+ if (center_time >= time_range.upper) continue;
+ const BBox1f dt0(time_range.lower,center_time);
+ const BBox1f dt1(center_time,time_range.upper);
+
+ /* find linear bounds for both time segments */
+ for (size_t i=begin; i<end; i++)
+ {
+ if (prims[i].time_range_overlap(dt0))
+ {
+ const LBBox3fa bn0 = recalculatePrimRef.linearBounds(prims[i],dt0);
+#if MBLUR_BIN_LBBOX
+ bounds0[b].extend(bn0);
+#else
+ bounds0[b].extend(bn0.interpolate(0.5f));
+#endif
+ count0[b] += prims[i].timeSegmentRange(dt0).size();
+ }
+
+ if (prims[i].time_range_overlap(dt1))
+ {
+ const LBBox3fa bn1 = recalculatePrimRef.linearBounds(prims[i],dt1);
+#if MBLUR_BIN_LBBOX
+ bounds1[b].extend(bn1);
+#else
+ bounds1[b].extend(bn1.interpolate(0.5f));
+#endif
+ count1[b] += prims[i].timeSegmentRange(dt1).size();
+ }
+ }
+ }
+ }
+
+ __forceinline void bin_parallel(const PrimRefMB* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, BBox1f time_range, const SetMB& set, const RecalculatePrimRef& recalculatePrimRef)
+ {
+ if (likely(end-begin < parallelThreshold)) {
+ bin(prims,begin,end,time_range,set,recalculatePrimRef);
+ }
+ else
+ {
+ auto bin = [&](const range<size_t>& r) -> TemporalBinInfo {
+ TemporalBinInfo binner(empty); binner.bin(prims, r.begin(), r.end(), time_range, set, recalculatePrimRef); return binner;
+ };
+ *this = parallel_reduce(begin,end,blockSize,TemporalBinInfo(empty),bin,merge2);
+ }
+ }
+
+ /*! merges in other binning information */
+ __forceinline void merge (const TemporalBinInfo& other)
+ {
+ for (size_t i=0; i<BINS-1; i++)
+ {
+ count0[i] += other.count0[i];
+ count1[i] += other.count1[i];
+ bounds0[i].extend(other.bounds0[i]);
+ bounds1[i].extend(other.bounds1[i]);
+ }
+ }
+
+ static __forceinline const TemporalBinInfo merge2(const TemporalBinInfo& a, const TemporalBinInfo& b) {
+ TemporalBinInfo r = a; r.merge(b); return r;
+ }
+
+ Split best(int logBlockSize, BBox1f time_range, const SetMB& set)
+ {
+ float bestSAH = inf;
+ float bestPos = 0.0f;
+ for (int b=0; b<BINS-1; b++)
+ {
+ float t = float(b+1)/float(BINS);
+ float ct = lerp(time_range.lower,time_range.upper,t);
+ const float center_time = set.align_time(ct);
+ if (center_time <= time_range.lower) continue;
+ if (center_time >= time_range.upper) continue;
+ const BBox1f dt0(time_range.lower,center_time);
+ const BBox1f dt1(center_time,time_range.upper);
+
+ /* calculate sah */
+ const size_t lCount = (count0[b]+(size_t(1) << logBlockSize)-1) >> int(logBlockSize);
+ const size_t rCount = (count1[b]+(size_t(1) << logBlockSize)-1) >> int(logBlockSize);
+ float sah0 = expectedApproxHalfArea(bounds0[b])*float(lCount)*dt0.size();
+ float sah1 = expectedApproxHalfArea(bounds1[b])*float(rCount)*dt1.size();
+ if (unlikely(lCount == 0)) sah0 = 0.0f; // happens for initial splits when objects not alive over entire shutter time
+ if (unlikely(rCount == 0)) sah1 = 0.0f;
+ const float sah = sah0+sah1;
+ if (sah < bestSAH) {
+ bestSAH = sah;
+ bestPos = center_time;
+ }
+ }
+ return Split(bestSAH*MBLUR_TIME_SPLIT_THRESHOLD,(unsigned)Split::SPLIT_TEMPORAL,0,bestPos);
+ }
+
+ public:
+ size_t count0[BINS-1];
+ size_t count1[BINS-1];
+ BBox bounds0[BINS-1];
+ BBox bounds1[BINS-1];
+ };
+
+ /*! finds the best split */
+ const Split find(const SetMB& set, const size_t logBlockSize)
+ {
+ assert(set.size() > 0);
+ TemporalBinInfo binner(empty);
+ binner.bin_parallel(set.prims->data(),set.begin(),set.end(),PARALLEL_FIND_BLOCK_SIZE,PARALLEL_THRESHOLD,set.time_range,set,recalculatePrimRef);
+ Split tsplit = binner.best((int)logBlockSize,set.time_range,set);
+ if (!tsplit.valid()) tsplit.data = Split::SPLIT_FALLBACK; // use fallback split
+ return tsplit;
+ }
+
+ __forceinline std::unique_ptr<mvector<PrimRefMB>> split(const Split& tsplit, const SetMB& set, SetMB& lset, SetMB& rset)
+ {
+ assert(tsplit.sah != float(inf));
+ assert(tsplit.fpos > set.time_range.lower);
+ assert(tsplit.fpos < set.time_range.upper);
+
+ float center_time = tsplit.fpos;
+ const BBox1f time_range0(set.time_range.lower,center_time);
+ const BBox1f time_range1(center_time,set.time_range.upper);
+ mvector<PrimRefMB>& prims = *set.prims;
+
+ /* calculate primrefs for first time range */
+ std::unique_ptr<mvector<PrimRefMB>> new_vector(new mvector<PrimRefMB>(device, set.size()));
+ PrimRefVector lprims = new_vector.get();
+
+ auto reduction_func0 = [&] (const range<size_t>& r) {
+ PrimInfoMB pinfo = empty;
+ for (size_t i=r.begin(); i<r.end(); i++)
+ {
+ if (likely(prims[i].time_range_overlap(time_range0)))
+ {
+ const PrimRefMB& prim = recalculatePrimRef(prims[i],time_range0);
+ (*lprims)[i-set.begin()] = prim;
+ pinfo.add_primref(prim);
+ }
+ else
+ {
+ (*lprims)[i-set.begin()] = prims[i];
+ }
+ }
+ return pinfo;
+ };
+ PrimInfoMB linfo = parallel_reduce(set.object_range,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD,PrimInfoMB(empty),reduction_func0,PrimInfoMB::merge2);
+
+ /* primrefs for first time range are in lprims[0 .. set.size()) */
+ /* some primitives may need to be filtered out */
+ if (linfo.size() != set.size())
+ linfo.object_range._end = parallel_filter(lprims->data(), size_t(0), set.size(), size_t(1024),
+ [&](const PrimRefMB& prim) { return prim.time_range_overlap(time_range0); });
+
+ lset = SetMB(linfo,lprims,time_range0);
+
+ /* calculate primrefs for second time range */
+ auto reduction_func1 = [&] (const range<size_t>& r) {
+ PrimInfoMB pinfo = empty;
+ for (size_t i=r.begin(); i<r.end(); i++)
+ {
+ if (likely(prims[i].time_range_overlap(time_range1)))
+ {
+ const PrimRefMB& prim = recalculatePrimRef(prims[i],time_range1);
+ prims[i] = prim;
+ pinfo.add_primref(prim);
+ }
+ }
+ return pinfo;
+ };
+ PrimInfoMB rinfo = parallel_reduce(set.object_range,PARALLEL_PARTITION_BLOCK_SIZE,PARALLEL_THRESHOLD,PrimInfoMB(empty),reduction_func1,PrimInfoMB::merge2);
+ rinfo.object_range = range<size_t>(set.begin(), set.begin() + rinfo.size());
+
+ /* primrefs for second time range are in prims[set.begin() .. set.end()) */
+ /* some primitives may need to be filtered out */
+ if (rinfo.size() != set.size())
+ rinfo.object_range._end = parallel_filter(prims.data(), set.begin(), set.end(), size_t(1024),
+ [&](const PrimRefMB& prim) { return prim.time_range_overlap(time_range1); });
+
+ rset = SetMB(rinfo,&prims,time_range1);
+
+ return new_vector;
+ }
+
+ private:
+ MemoryMonitorInterface* device; // device to report memory usage to
+ const RecalculatePrimRef recalculatePrimRef;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/priminfo.h b/thirdparty/embree/kernels/builders/priminfo.h
new file mode 100644
index 0000000000..fee515247a
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/priminfo.h
@@ -0,0 +1,362 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+#include "../common/primref.h"
+#include "../common/primref_mb.h"
+
+namespace embree
+{
+ // FIXME: maybe there's a better place for this util fct
+ __forceinline float areaProjectedTriangle(const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2)
+ {
+ const Vec3fa e0 = v1-v0;
+ const Vec3fa e1 = v2-v0;
+ const Vec3fa d = cross(e0,e1);
+ return fabs(d.x) + fabs(d.y) + fabs(d.z);
+ }
+
+ //namespace isa
+ //{
+ template<typename BBox>
+ class CentGeom
+ {
+ public:
+ __forceinline CentGeom () {}
+
+ __forceinline CentGeom (EmptyTy)
+ : geomBounds(empty), centBounds(empty) {}
+
+ __forceinline CentGeom (const BBox& geomBounds, const BBox3fa& centBounds)
+ : geomBounds(geomBounds), centBounds(centBounds) {}
+
+ template<typename PrimRef>
+ __forceinline void extend_primref(const PrimRef& prim)
+ {
+ BBox bounds; Vec3fa center;
+ prim.binBoundsAndCenter(bounds,center);
+ geomBounds.extend(bounds);
+ centBounds.extend(center);
+ }
+
+ template<typename PrimRef>
+ __forceinline void extend_center2(const PrimRef& prim)
+ {
+ BBox3fa bounds = prim.bounds();
+ geomBounds.extend(bounds);
+ centBounds.extend(bounds.center2());
+ }
+
+ __forceinline void extend(const BBox& geomBounds_) {
+ geomBounds.extend(geomBounds_);
+ centBounds.extend(center2(geomBounds_));
+ }
+
+ __forceinline void merge(const CentGeom& other)
+ {
+ geomBounds.extend(other.geomBounds);
+ centBounds.extend(other.centBounds);
+ }
+
+ static __forceinline const CentGeom merge2(const CentGeom& a, const CentGeom& b) {
+ CentGeom r = a; r.merge(b); return r;
+ }
+
+ public:
+ BBox geomBounds; //!< geometry bounds of primitives
+ BBox3fa centBounds; //!< centroid bounds of primitives
+ };
+
+ typedef CentGeom<BBox3fa> CentGeomBBox3fa;
+
+ /*! stores bounding information for a set of primitives */
+ template<typename BBox>
+ class PrimInfoT : public CentGeom<BBox>
+ {
+ public:
+ using CentGeom<BBox>::geomBounds;
+ using CentGeom<BBox>::centBounds;
+
+ __forceinline PrimInfoT () {}
+
+ __forceinline PrimInfoT (EmptyTy)
+ : CentGeom<BBox>(empty), begin(0), end(0) {}
+
+ __forceinline PrimInfoT (size_t begin, size_t end, const CentGeomBBox3fa& centGeomBounds)
+ : CentGeom<BBox>(centGeomBounds), begin(begin), end(end) {}
+
+ template<typename PrimRef>
+ __forceinline void add_primref(const PrimRef& prim)
+ {
+ CentGeom<BBox>::extend_primref(prim);
+ end++;
+ }
+
+ template<typename PrimRef>
+ __forceinline void add_center2(const PrimRef& prim) {
+ CentGeom<BBox>::extend_center2(prim);
+ end++;
+ }
+
+ template<typename PrimRef>
+ __forceinline void add_center2(const PrimRef& prim, const size_t i) {
+ CentGeom<BBox>::extend_center2(prim);
+ end+=i;
+ }
+
+ /*__forceinline void add(const BBox& geomBounds_) {
+ CentGeom<BBox>::extend(geomBounds_);
+ end++;
+ }
+
+ __forceinline void add(const BBox& geomBounds_, const size_t i) {
+ CentGeom<BBox>::extend(geomBounds_);
+ end+=i;
+ }*/
+
+ __forceinline void merge(const PrimInfoT& other)
+ {
+ CentGeom<BBox>::merge(other);
+ begin += other.begin;
+ end += other.end;
+ }
+
+ static __forceinline const PrimInfoT merge(const PrimInfoT& a, const PrimInfoT& b) {
+ PrimInfoT r = a; r.merge(b); return r;
+ }
+
+ /*! returns the number of primitives */
+ __forceinline size_t size() const {
+ return end-begin;
+ }
+
+ __forceinline float halfArea() {
+ return expectedApproxHalfArea(geomBounds);
+ }
+
+ __forceinline float leafSAH() const {
+ return expectedApproxHalfArea(geomBounds)*float(size());
+ //return halfArea(geomBounds)*blocks(num);
+ }
+
+ __forceinline float leafSAH(size_t block_shift) const {
+ return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
+ //return halfArea(geomBounds)*float((num+3) >> 2);
+ //return halfArea(geomBounds)*blocks(num);
+ }
+
+ /*! stream output */
+ friend embree_ostream operator<<(embree_ostream cout, const PrimInfoT& pinfo) {
+ return cout << "PrimInfo { begin = " << pinfo.begin << ", end = " << pinfo.end << ", geomBounds = " << pinfo.geomBounds << ", centBounds = " << pinfo.centBounds << "}";
+ }
+
+ public:
+ size_t begin,end; //!< number of primitives
+ };
+
+ typedef PrimInfoT<BBox3fa> PrimInfo;
+ //typedef PrimInfoT<LBBox3fa> PrimInfoMB;
+
+ /*! stores bounding information for a set of primitives */
+ template<typename BBox>
+ class PrimInfoMBT : public CentGeom<BBox>
+ {
+ public:
+ using CentGeom<BBox>::geomBounds;
+ using CentGeom<BBox>::centBounds;
+
+ __forceinline PrimInfoMBT () {
+ }
+
+ __forceinline PrimInfoMBT (EmptyTy)
+ : CentGeom<BBox>(empty), object_range(0,0), num_time_segments(0), max_num_time_segments(0), max_time_range(0.0f,1.0f), time_range(1.0f,0.0f) {}
+
+ __forceinline PrimInfoMBT (size_t begin, size_t end)
+ : CentGeom<BBox>(empty), object_range(begin,end), num_time_segments(0), max_num_time_segments(0), max_time_range(0.0f,1.0f), time_range(1.0f,0.0f) {}
+
+ template<typename PrimRef>
+ __forceinline void add_primref(const PrimRef& prim)
+ {
+ CentGeom<BBox>::extend_primref(prim);
+ time_range.extend(prim.time_range);
+ object_range._end++;
+ num_time_segments += prim.size();
+ if (max_num_time_segments < prim.totalTimeSegments()) {
+ max_num_time_segments = prim.totalTimeSegments();
+ max_time_range = prim.time_range;
+ }
+ }
+
+ __forceinline void merge(const PrimInfoMBT& other)
+ {
+ CentGeom<BBox>::merge(other);
+ time_range.extend(other.time_range);
+ object_range._begin += other.object_range.begin();
+ object_range._end += other.object_range.end();
+ num_time_segments += other.num_time_segments;
+ if (max_num_time_segments < other.max_num_time_segments) {
+ max_num_time_segments = other.max_num_time_segments;
+ max_time_range = other.max_time_range;
+ }
+ }
+
+ static __forceinline const PrimInfoMBT merge2(const PrimInfoMBT& a, const PrimInfoMBT& b) {
+ PrimInfoMBT r = a; r.merge(b); return r;
+ }
+
+ __forceinline size_t begin() const {
+ return object_range.begin();
+ }
+
+ __forceinline size_t end() const {
+ return object_range.end();
+ }
+
+ /*! returns the number of primitives */
+ __forceinline size_t size() const {
+ return object_range.size();
+ }
+
+ __forceinline float halfArea() const {
+ return time_range.size()*expectedApproxHalfArea(geomBounds);
+ }
+
+ __forceinline float leafSAH() const {
+ return time_range.size()*expectedApproxHalfArea(geomBounds)*float(num_time_segments);
+ }
+
+ __forceinline float leafSAH(size_t block_shift) const {
+ return time_range.size()*expectedApproxHalfArea(geomBounds)*float((num_time_segments+(size_t(1)<<block_shift)-1) >> block_shift);
+ }
+
+ __forceinline float align_time(float ct) const
+ {
+ //return roundf(ct * float(numTimeSegments)) / float(numTimeSegments);
+ float t0 = (ct-max_time_range.lower)/max_time_range.size();
+ float t1 = roundf(t0 * float(max_num_time_segments)) / float(max_num_time_segments);
+ return t1*max_time_range.size()+max_time_range.lower;
+ }
+
+ /*! stream output */
+ friend embree_ostream operator<<(embree_ostream cout, const PrimInfoMBT& pinfo)
+ {
+ return cout << "PrimInfo { " <<
+ "object_range = " << pinfo.object_range <<
+ ", time_range = " << pinfo.time_range <<
+ ", time_segments = " << pinfo.num_time_segments <<
+ ", geomBounds = " << pinfo.geomBounds <<
+ ", centBounds = " << pinfo.centBounds <<
+ "}";
+ }
+
+ public:
+ range<size_t> object_range; //!< primitive range
+ size_t num_time_segments; //!< total number of time segments of all added primrefs
+ size_t max_num_time_segments; //!< maximum number of time segments of a primitive
+ BBox1f max_time_range; //!< time range of primitive with max_num_time_segments
+ BBox1f time_range; //!< merged time range of primitives when merging prims, or additionally clipped with build time range when used in SetMB
+ };
+
+ typedef PrimInfoMBT<typename PrimRefMB::BBox> PrimInfoMB;
+
+ struct SetMB : public PrimInfoMB
+ {
+ static const size_t PARALLEL_THRESHOLD = 3 * 1024;
+ static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
+ static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
+
+ typedef mvector<PrimRefMB>* PrimRefVector;
+
+ __forceinline SetMB() {}
+
+ __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims)
+ : PrimInfoMB(pinfo_i), prims(prims) {}
+
+ __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, range<size_t> object_range_in, BBox1f time_range_in)
+ : PrimInfoMB(pinfo_i), prims(prims)
+ {
+ object_range = object_range_in;
+ time_range = intersect(time_range,time_range_in);
+ }
+
+ __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, BBox1f time_range_in)
+ : PrimInfoMB(pinfo_i), prims(prims)
+ {
+ time_range = intersect(time_range,time_range_in);
+ }
+
+ void deterministic_order() const
+ {
+ /* required as parallel partition destroys original primitive order */
+ PrimRefMB* prim = prims->data();
+ std::sort(&prim[object_range.begin()],&prim[object_range.end()]);
+ }
+
+ template<typename RecalculatePrimRef>
+ __forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef) const
+ {
+ auto reduce = [&](const range<size_t>& r) -> LBBox3fa
+ {
+ LBBox3fa cbounds(empty);
+ for (size_t j = r.begin(); j < r.end(); j++)
+ {
+ PrimRefMB& ref = (*prims)[j];
+ const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range);
+ cbounds.extend(bn);
+ };
+ return cbounds;
+ };
+
+ return parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD, LBBox3fa(empty),
+ reduce,
+ [&](const LBBox3fa& b0, const LBBox3fa& b1) -> LBBox3fa { return embree::merge(b0, b1); });
+ }
+
+ template<typename RecalculatePrimRef>
+ __forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
+ {
+ auto reduce = [&](const range<size_t>& r) -> LBBox3fa
+ {
+ LBBox3fa cbounds(empty);
+ for (size_t j = r.begin(); j < r.end(); j++)
+ {
+ PrimRefMB& ref = (*prims)[j];
+ const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range, space);
+ cbounds.extend(bn);
+ };
+ return cbounds;
+ };
+
+ return parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD, LBBox3fa(empty),
+ reduce,
+ [&](const LBBox3fa& b0, const LBBox3fa& b1) -> LBBox3fa { return embree::merge(b0, b1); });
+ }
+
+ template<typename RecalculatePrimRef>
+ const SetMB primInfo(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
+ {
+ auto computePrimInfo = [&](const range<size_t>& r) -> PrimInfoMB
+ {
+ PrimInfoMB pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ PrimRefMB& ref = (*prims)[j];
+ PrimRefMB ref1 = recalculatePrimRef(ref,time_range,space);
+ pinfo.add_primref(ref1);
+ };
+ return pinfo;
+ };
+
+ const PrimInfoMB pinfo = parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD,
+ PrimInfoMB(empty), computePrimInfo, PrimInfoMB::merge2);
+
+ return SetMB(pinfo,prims,object_range,time_range);
+ }
+
+ public:
+ PrimRefVector prims;
+ };
+//}
+}
diff --git a/thirdparty/embree/kernels/builders/primrefgen.cpp b/thirdparty/embree/kernels/builders/primrefgen.cpp
new file mode 100644
index 0000000000..d279dc4993
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/primrefgen.cpp
@@ -0,0 +1,312 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "primrefgen.h"
+#include "primrefgen_presplit.h"
+
+#include "../../common/algorithms/parallel_for_for.h"
+#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
+ {
+ ParallelPrefixSumState<PrimInfo> pstate;
+
+ /* first try */
+ progressMonitor(0);
+ PrimInfo pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
+ return geometry->createPrimRefArray(prims,r,r.begin(),geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ /* if we need to filter out geometry, run again */
+ if (pinfo.size() != numPrimRefs)
+ {
+ progressMonitor(0);
+ pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
+ return geometry->createPrimRefArray(prims,r,base.size(),geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+ }
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
+ {
+ ParallelForForPrefixSumState<PrimInfo> pstate;
+ Scene::Iterator2 iter(scene,types,mblur);
+
+ /* first try */
+ progressMonitor(0);
+ pstate.init(iter,size_t(1024));
+ PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
+ return mesh->createPrimRefArray(prims,r,k,(unsigned)geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ /* if we need to filter out geometry, run again */
+ if (pinfo.size() != numPrimRefs)
+ {
+ progressMonitor(0);
+ pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
+ return mesh->createPrimRefArray(prims,r,base.size(),(unsigned)geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+ }
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
+ {
+ ParallelForForPrefixSumState<PrimInfo> pstate;
+ Scene::Iterator2 iter(scene,types,true);
+
+ /* first try */
+ progressMonitor(0);
+ pstate.init(iter,size_t(1024));
+ PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
+ return mesh->createPrimRefArrayMB(prims,itime,r,k,(unsigned)geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ /* if we need to filter out geometry, run again */
+ if (pinfo.size() != numPrimRefs)
+ {
+ progressMonitor(0);
+ pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
+ return mesh->createPrimRefArrayMB(prims,itime,r,base.size(),(unsigned)geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+ }
+ return pinfo;
+ }
+
+ PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
+ {
+ ParallelForForPrefixSumState<PrimInfoMB> pstate;
+ Scene::Iterator2 iter(scene,types,true);
+
+ /* first try */
+ progressMonitor(0);
+ pstate.init(iter,size_t(1024));
+ PrimInfoMB pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfoMB {
+ return mesh->createPrimRefMBArray(prims,t0t1,r,k,(unsigned)geomID);
+ }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
+
+ /* if we need to filter out geometry, run again */
+ if (pinfo.size() != numPrimRefs)
+ {
+ progressMonitor(0);
+ pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
+ return mesh->createPrimRefMBArray(prims,t0t1,r,base.size(),(unsigned)geomID);
+ }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
+ }
+
+ /* the BVH starts with that time range, even though primitives might have smaller/larger time range */
+ pinfo.time_range = t0t1;
+ return pinfo;
+ }
+
+ template<typename Mesh>
+ size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor)
+ {
+ size_t numPrimitives = morton.size();
+
+ /* compute scene bounds */
+ std::pair<size_t,BBox3fa> cb_empty(0,empty);
+ auto cb = parallel_reduce
+ ( size_t(0), numPrimitives, size_t(1024), cb_empty, [&](const range<size_t>& r) -> std::pair<size_t,BBox3fa>
+ {
+ size_t num = 0;
+ BBox3fa bounds = empty;
+
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa prim_bounds = empty;
+ if (unlikely(!mesh->buildBounds(j,&prim_bounds))) continue;
+ bounds.extend(center2(prim_bounds));
+ num++;
+ }
+ return std::make_pair(num,bounds);
+ }, [] (const std::pair<size_t,BBox3fa>& a, const std::pair<size_t,BBox3fa>& b) {
+ return std::make_pair(a.first + b.first,merge(a.second,b.second));
+ });
+
+
+ size_t numPrimitivesGen = cb.first;
+ const BBox3fa centBounds = cb.second;
+
+ /* compute morton codes */
+ if (likely(numPrimitivesGen == numPrimitives))
+ {
+ /* fast path if all primitives were valid */
+ BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
+ parallel_for( size_t(0), numPrimitives, size_t(1024), [&](const range<size_t>& r) -> void {
+ BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ generator(mesh->bounds(j),unsigned(j));
+ });
+ }
+ else
+ {
+ /* slow path, fallback in case some primitives were invalid */
+ ParallelPrefixSumState<size_t> pstate;
+ BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
+ parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {
+ size_t num = 0;
+ BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (unlikely(!mesh->buildBounds(j,&bounds))) continue;
+ generator(bounds,unsigned(j));
+ num++;
+ }
+ return num;
+ }, std::plus<size_t>());
+
+ parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {
+ size_t num = 0;
+ BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[base]);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!mesh->buildBounds(j,&bounds)) continue;
+ generator(bounds,unsigned(j));
+ num++;
+ }
+ return num;
+ }, std::plus<size_t>());
+ }
+ return numPrimitivesGen;
+ }
+
+ // ====================================================================================================
+ // ====================================================================================================
+ // ====================================================================================================
+
+ // special variants for grid meshes
+
+// -- GODOT start --
+#if defined(EMBREE_GEOMETRY_GRID)
+// -- GODOT end --
+ PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
+ {
+ PrimInfo pinfo(empty);
+ size_t numPrimitives = 0;
+
+ /* first run to get #primitives */
+
+ ParallelForForPrefixSumState<PrimInfo> pstate;
+ Scene::Iterator<GridMesh,false> iter(scene);
+
+ pstate.init(iter,size_t(1024));
+
+ /* iterate over all meshes in the scene */
+ pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!mesh->valid(j)) continue;
+ BBox3fa bounds = empty;
+ const PrimRef prim(bounds,(unsigned)geomID,(unsigned)j);
+ if (!mesh->valid(j)) continue;
+ pinfo.add_center2(prim,mesh->getNumSubGrids(j));
+ }
+ return pinfo;
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+ numPrimitives = pinfo.size();
+
+ /* resize arrays */
+ sgrids.resize(numPrimitives);
+ prims.resize(numPrimitives);
+
+ /* second run to fill primrefs and SubGridBuildData arrays */
+ pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
+ k = base.size();
+ size_t p_index = k;
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!mesh->valid(j)) continue;
+ const GridMesh::Grid &g = mesh->grid(j);
+ for (unsigned int y=0; y<g.resY-1u; y+=2)
+ for (unsigned int x=0; x<g.resX-1u; x+=2)
+ {
+ BBox3fa bounds = empty;
+ if (!mesh->buildBounds(g,x,y,bounds)) continue; // get bounds of subgrid
+ const PrimRef prim(bounds,(unsigned)geomID,(unsigned)p_index);
+ pinfo.add_center2(prim);
+ sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
+ prims[p_index++] = prim;
+ }
+ }
+ return pinfo;
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+ assert(pinfo.size() == numPrimitives);
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArrayGrids(GridMesh* mesh, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
+ {
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max ();
+
+ PrimInfo pinfo(empty);
+ size_t numPrimitives = 0;
+
+ ParallelPrefixSumState<PrimInfo> pstate;
+ /* iterate over all grids in a single mesh */
+ pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!mesh->valid(j)) continue;
+ BBox3fa bounds = empty;
+ const PrimRef prim(bounds,geomID_,unsigned(j));
+ pinfo.add_center2(prim,mesh->getNumSubGrids(j));
+ }
+ return pinfo;
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+ numPrimitives = pinfo.size();
+ /* resize arrays */
+ sgrids.resize(numPrimitives);
+ prims.resize(numPrimitives);
+
+ /* second run to fill primrefs and SubGridBuildData arrays */
+ pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
+ {
+
+ size_t p_index = base.size();
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!mesh->valid(j)) continue;
+ const GridMesh::Grid &g = mesh->grid(j);
+ for (unsigned int y=0; y<g.resY-1u; y+=2)
+ for (unsigned int x=0; x<g.resX-1u; x+=2)
+ {
+ BBox3fa bounds = empty;
+ if (!mesh->buildBounds(g,x,y,bounds)) continue; // get bounds of subgrid
+ const PrimRef prim(bounds,geomID_,unsigned(p_index));
+ pinfo.add_center2(prim);
+ sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
+ prims[p_index++] = prim;
+ }
+ }
+ return pinfo;
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ return pinfo;
+ }
+// -- GODOT start --
+#endif
+// -- GODOT end --
+
+ // ====================================================================================================
+ // ====================================================================================================
+ // ====================================================================================================
+
+ IF_ENABLED_TRIS (template size_t createMortonCodeArray<TriangleMesh>(TriangleMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
+ IF_ENABLED_QUADS(template size_t createMortonCodeArray<QuadMesh>(QuadMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
+ IF_ENABLED_USER (template size_t createMortonCodeArray<UserGeometry>(UserGeometry* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
+ IF_ENABLED_INSTANCE (template size_t createMortonCodeArray<Instance>(Instance* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/primrefgen.h b/thirdparty/embree/kernels/builders/primrefgen.h
new file mode 100644
index 0000000000..c09a848ba3
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/primrefgen.h
@@ -0,0 +1,34 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/scene.h"
+#include "../common/primref.h"
+#include "../common/primref_mb.h"
+#include "priminfo.h"
+#include "bvh_builder_morton.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, size_t numPrimitives, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor);
+
+ PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, size_t numPrimitives, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor);
+
+ PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, size_t numPrimitives, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime = 0);
+
+ PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, size_t numPrimitives, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f));
+
+ template<typename Mesh>
+ size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor);
+
+ /* special variants for grids */
+ PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids);
+
+ PrimInfo createPrimRefArrayGrids(GridMesh* mesh, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids);
+
+ }
+}
+
diff --git a/thirdparty/embree/kernels/builders/primrefgen_presplit.h b/thirdparty/embree/kernels/builders/primrefgen_presplit.h
new file mode 100644
index 0000000000..8cd251ddd2
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/primrefgen_presplit.h
@@ -0,0 +1,371 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../builders/primrefgen.h"
+#include "../builders/heuristic_spatial.h"
+#include "../builders/splitter.h"
+
+#include "../../common/algorithms/parallel_for_for.h"
+#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
+
+#define DBG_PRESPLIT(x)
+#define CHECK_PRESPLIT(x)
+
+#define GRID_SIZE 1024
+#define MAX_PRESPLITS_PER_PRIMITIVE_LOG 5
+#define MAX_PRESPLITS_PER_PRIMITIVE (1<<MAX_PRESPLITS_PER_PRIMITIVE_LOG)
+#define PRIORITY_CUTOFF_THRESHOLD 1.0f
+#define PRIORITY_SPLIT_POS_WEIGHT 1.5f
+
+namespace embree
+{
+ namespace isa
+ {
+
+ struct PresplitItem
+ {
+ union {
+ float priority;
+ unsigned int data;
+ };
+ unsigned int index;
+
+ __forceinline operator unsigned() const
+ {
+ return reinterpret_cast<const unsigned&>(priority);
+ }
+ __forceinline bool operator < (const PresplitItem& item) const
+ {
+ return (priority < item.priority);
+ }
+
+ template<typename Mesh>
+ __forceinline static float compute_priority(const PrimRef &ref, Scene *scene, const Vec2i &mc)
+ {
+ const unsigned int geomID = ref.geomID();
+ const unsigned int primID = ref.primID();
+ const float area_aabb = area(ref.bounds());
+ const float area_prim = ((Mesh*)scene->get(geomID))->projectedPrimitiveArea(primID);
+ const unsigned int diff = 31 - lzcnt(mc.x^mc.y);
+ assert(area_prim <= area_aabb);
+ //const float priority = powf((area_aabb - area_prim) * powf(PRIORITY_SPLIT_POS_WEIGHT,(float)diff),1.0f/4.0f);
+ const float priority = sqrtf(sqrtf( (area_aabb - area_prim) * powf(PRIORITY_SPLIT_POS_WEIGHT,(float)diff) ));
+ assert(priority >= 0.0f && priority < FLT_LARGE);
+ return priority;
+ }
+
+
+ };
+
+ inline std::ostream &operator<<(std::ostream &cout, const PresplitItem& item) {
+ return cout << "index " << item.index << " priority " << item.priority;
+ };
+
+ template<typename SplitterFactory>
+ void splitPrimitive(SplitterFactory &Splitter,
+ const PrimRef &prim,
+ const unsigned int geomID,
+ const unsigned int primID,
+ const unsigned int split_level,
+ const Vec3fa &grid_base,
+ const float grid_scale,
+ const float grid_extend,
+ PrimRef subPrims[MAX_PRESPLITS_PER_PRIMITIVE],
+ unsigned int& numSubPrims)
+ {
+ assert(split_level <= MAX_PRESPLITS_PER_PRIMITIVE_LOG);
+ if (split_level == 0)
+ {
+ assert(numSubPrims < MAX_PRESPLITS_PER_PRIMITIVE);
+ subPrims[numSubPrims++] = prim;
+ }
+ else
+ {
+ const Vec3fa lower = prim.lower;
+ const Vec3fa upper = prim.upper;
+ const Vec3fa glower = (lower-grid_base)*Vec3fa(grid_scale)+Vec3fa(0.2f);
+ const Vec3fa gupper = (upper-grid_base)*Vec3fa(grid_scale)-Vec3fa(0.2f);
+ Vec3ia ilower(floor(glower));
+ Vec3ia iupper(floor(gupper));
+
+ /* this ignores dimensions that are empty */
+ iupper = (Vec3ia)(select(vint4(glower) >= vint4(gupper),vint4(ilower),vint4(iupper)));
+
+ /* compute a morton code for the lower and upper grid coordinates. */
+ const unsigned int lower_code = bitInterleave(ilower.x,ilower.y,ilower.z);
+ const unsigned int upper_code = bitInterleave(iupper.x,iupper.y,iupper.z);
+
+ /* if all bits are equal then we cannot split */
+ if(unlikely(lower_code == upper_code))
+ {
+ assert(numSubPrims < MAX_PRESPLITS_PER_PRIMITIVE);
+ subPrims[numSubPrims++] = prim;
+ return;
+ }
+
+ /* compute octree level and dimension to perform the split in */
+ const unsigned int diff = 31 - lzcnt(lower_code^upper_code);
+ const unsigned int level = diff / 3;
+ const unsigned int dim = diff % 3;
+
+ /* now we compute the grid position of the split */
+ const unsigned int isplit = iupper[dim] & ~((1<<level)-1);
+
+ /* compute world space position of split */
+ const float inv_grid_size = 1.0f / GRID_SIZE;
+ const float fsplit = grid_base[dim] + isplit * inv_grid_size * grid_extend;
+
+ assert(prim.lower[dim] <= fsplit &&
+ prim.upper[dim] >= fsplit);
+
+ /* split primitive */
+ const auto splitter = Splitter(prim);
+ BBox3fa left,right;
+ splitter(prim.bounds(),dim,fsplit,left,right);
+ assert(!left.empty());
+ assert(!right.empty());
+
+
+ splitPrimitive(Splitter,PrimRef(left ,geomID,primID),geomID,primID,split_level-1,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
+ splitPrimitive(Splitter,PrimRef(right,geomID,primID),geomID,primID,split_level-1,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
+ }
+ }
+
+
+ template<typename Mesh, typename SplitterFactory>
+ PrimInfo createPrimRefArray_presplit(Geometry* geometry, unsigned int geomID, size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
+ {
+ ParallelPrefixSumState<PrimInfo> pstate;
+
+ /* first try */
+ progressMonitor(0);
+ PrimInfo pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
+ return geometry->createPrimRefArray(prims,r,r.begin(),geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ /* if we need to filter out geometry, run again */
+ if (pinfo.size() != numPrimRefs)
+ {
+ progressMonitor(0);
+ pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
+ return geometry->createPrimRefArray(prims,r,base.size(),geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+ }
+ return pinfo;
+ }
+
+ __forceinline Vec2i computeMC(const Vec3fa &grid_base, const float grid_scale, const PrimRef &ref)
+ {
+ const Vec3fa lower = ref.lower;
+ const Vec3fa upper = ref.upper;
+ const Vec3fa glower = (lower-grid_base)*Vec3fa(grid_scale)+Vec3fa(0.2f);
+ const Vec3fa gupper = (upper-grid_base)*Vec3fa(grid_scale)-Vec3fa(0.2f);
+ Vec3ia ilower(floor(glower));
+ Vec3ia iupper(floor(gupper));
+
+ /* this ignores dimensions that are empty */
+ iupper = (Vec3ia)select(vint4(glower) >= vint4(gupper),vint4(ilower),vint4(iupper));
+
+ /* compute a morton code for the lower and upper grid coordinates. */
+ const unsigned int lower_code = bitInterleave(ilower.x,ilower.y,ilower.z);
+ const unsigned int upper_code = bitInterleave(iupper.x,iupper.y,iupper.z);
+ return Vec2i(lower_code,upper_code);
+ }
+
+ template<typename Mesh, typename SplitterFactory>
+ PrimInfo createPrimRefArray_presplit(Scene* scene, Geometry::GTypeMask types, bool mblur, size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
+ {
+ static const size_t MIN_STEP_SIZE = 128;
+
+ ParallelForForPrefixSumState<PrimInfo> pstate;
+ Scene::Iterator2 iter(scene,types,mblur);
+
+ /* first try */
+ progressMonitor(0);
+ pstate.init(iter,size_t(1024));
+ PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
+ return mesh->createPrimRefArray(prims,r,k,(unsigned)geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ /* if we need to filter out geometry, run again */
+ if (pinfo.size() != numPrimRefs)
+ {
+ progressMonitor(0);
+ pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
+ return mesh->createPrimRefArray(prims,r,base.size(),(unsigned)geomID);
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+ }
+
+ /* use correct number of primitives */
+ size_t numPrimitives = pinfo.size();
+ const size_t alloc_numPrimitives = prims.size();
+ const size_t numSplitPrimitivesBudget = alloc_numPrimitives - numPrimitives;
+
+ /* set up primitive splitter */
+ SplitterFactory Splitter(scene);
+
+
+ DBG_PRESPLIT(
+ const size_t org_numPrimitives = pinfo.size();
+ PRINT(numPrimitives);
+ PRINT(alloc_numPrimitives);
+ PRINT(numSplitPrimitivesBudget);
+ );
+
+ /* allocate double buffer presplit items */
+ const size_t presplit_allocation_size = sizeof(PresplitItem)*alloc_numPrimitives;
+ PresplitItem *presplitItem = (PresplitItem*)alignedMalloc(presplit_allocation_size,64);
+ PresplitItem *tmp_presplitItem = (PresplitItem*)alignedMalloc(presplit_allocation_size,64);
+
+ /* compute grid */
+ const Vec3fa grid_base = pinfo.geomBounds.lower;
+ const Vec3fa grid_diag = pinfo.geomBounds.size();
+ const float grid_extend = max(grid_diag.x,max(grid_diag.y,grid_diag.z));
+ const float grid_scale = grid_extend == 0.0f ? 0.0f : GRID_SIZE / grid_extend;
+
+ /* init presplit items and get total sum */
+ const float psum = parallel_reduce( size_t(0), numPrimitives, size_t(MIN_STEP_SIZE), 0.0f, [&](const range<size_t>& r) -> float {
+ float sum = 0.0f;
+ for (size_t i=r.begin(); i<r.end(); i++)
+ {
+ presplitItem[i].index = (unsigned int)i;
+ const Vec2i mc = computeMC(grid_base,grid_scale,prims[i]);
+ /* if all bits are equal then we cannot split */
+ presplitItem[i].priority = (mc.x != mc.y) ? PresplitItem::compute_priority<Mesh>(prims[i],scene,mc) : 0.0f;
+ /* FIXME: sum undeterministic */
+ sum += presplitItem[i].priority;
+ }
+ return sum;
+ },[](const float& a, const float& b) -> float { return a+b; });
+
+ /* compute number of splits per primitive */
+ const float inv_psum = 1.0f / psum;
+ parallel_for( size_t(0), numPrimitives, size_t(MIN_STEP_SIZE), [&](const range<size_t>& r) -> void {
+ for (size_t i=r.begin(); i<r.end(); i++)
+ {
+ if (presplitItem[i].priority > 0.0f)
+ {
+ const float rel_p = (float)numSplitPrimitivesBudget * presplitItem[i].priority * inv_psum;
+ if (rel_p >= PRIORITY_CUTOFF_THRESHOLD) // need at least a split budget that generates two sub-prims
+ {
+ presplitItem[i].priority = max(min(ceilf(logf(rel_p)/logf(2.0f)),(float)MAX_PRESPLITS_PER_PRIMITIVE_LOG),1.0f);
+ //presplitItem[i].priority = min(floorf(logf(rel_p)/logf(2.0f)),(float)MAX_PRESPLITS_PER_PRIMITIVE_LOG);
+ assert(presplitItem[i].priority >= 0.0f && presplitItem[i].priority <= (float)MAX_PRESPLITS_PER_PRIMITIVE_LOG);
+ }
+ else
+ presplitItem[i].priority = 0.0f;
+ }
+ }
+ });
+
+ auto isLeft = [&] (const PresplitItem &ref) { return ref.priority < PRIORITY_CUTOFF_THRESHOLD; };
+ size_t center = parallel_partitioning(presplitItem,0,numPrimitives,isLeft,1024);
+
+ /* anything to split ? */
+ if (center < numPrimitives)
+ {
+ const size_t numPrimitivesToSplit = numPrimitives - center;
+ assert(presplitItem[center].priority >= 1.0f);
+
+ /* sort presplit items in ascending order */
+ radix_sort_u32(presplitItem + center,tmp_presplitItem + center,numPrimitivesToSplit,1024);
+
+ CHECK_PRESPLIT(
+ parallel_for( size_t(center+1), numPrimitives, size_t(MIN_STEP_SIZE), [&](const range<size_t>& r) -> void {
+ for (size_t i=r.begin(); i<r.end(); i++)
+ assert(presplitItem[i-1].priority <= presplitItem[i].priority);
+ });
+ );
+
+ unsigned int *const primOffset0 = (unsigned int*)tmp_presplitItem;
+ unsigned int *const primOffset1 = (unsigned int*)tmp_presplitItem + numPrimitivesToSplit;
+
+ /* compute actual number of sub-primitives generated within the [center;numPrimitives-1] range */
+ const size_t totalNumSubPrims = parallel_reduce( size_t(center), numPrimitives, size_t(MIN_STEP_SIZE), size_t(0), [&](const range<size_t>& t) -> size_t {
+ size_t sum = 0;
+ for (size_t i=t.begin(); i<t.end(); i++)
+ {
+ PrimRef subPrims[MAX_PRESPLITS_PER_PRIMITIVE];
+ assert(presplitItem[i].priority >= 1.0f);
+ const unsigned int primrefID = presplitItem[i].index;
+ const float prio = presplitItem[i].priority;
+ const unsigned int geomID = prims[primrefID].geomID();
+ const unsigned int primID = prims[primrefID].primID();
+ const unsigned int split_levels = (unsigned int)prio;
+ unsigned int numSubPrims = 0;
+ splitPrimitive(Splitter,prims[primrefID],geomID,primID,split_levels,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
+ assert(numSubPrims);
+ numSubPrims--; // can reuse slot
+ sum+=numSubPrims;
+ presplitItem[i].data = (numSubPrims << MAX_PRESPLITS_PER_PRIMITIVE_LOG) | split_levels;
+ primOffset0[i-center] = numSubPrims;
+ }
+ return sum;
+ },[](const size_t& a, const size_t& b) -> size_t { return a+b; });
+
+ /* if we are over budget, need to shrink the range */
+ if (totalNumSubPrims > numSplitPrimitivesBudget)
+ {
+ size_t new_center = numPrimitives-1;
+ size_t sum = 0;
+ for (;new_center>=center;new_center--)
+ {
+ const unsigned int numSubPrims = presplitItem[new_center].data >> MAX_PRESPLITS_PER_PRIMITIVE_LOG;
+ if (unlikely(sum + numSubPrims >= numSplitPrimitivesBudget)) break;
+ sum += numSubPrims;
+ }
+ new_center++;
+ center = new_center;
+ }
+
+ /* parallel prefix sum to compute offsets for storing sub-primitives */
+ const unsigned int offset = parallel_prefix_sum(primOffset0,primOffset1,numPrimitivesToSplit,(unsigned int)0,std::plus<unsigned int>());
+
+ /* iterate over range, and split primitives into sub primitives and append them to prims array */
+ parallel_for( size_t(center), numPrimitives, size_t(MIN_STEP_SIZE), [&](const range<size_t>& rn) -> void {
+ for (size_t j=rn.begin(); j<rn.end(); j++)
+ {
+ PrimRef subPrims[MAX_PRESPLITS_PER_PRIMITIVE];
+ const unsigned int primrefID = presplitItem[j].index;
+ const unsigned int geomID = prims[primrefID].geomID();
+ const unsigned int primID = prims[primrefID].primID();
+ const unsigned int split_levels = presplitItem[j].data & ((unsigned int)(1 << MAX_PRESPLITS_PER_PRIMITIVE_LOG)-1);
+
+ assert(split_levels);
+ assert(split_levels <= MAX_PRESPLITS_PER_PRIMITIVE_LOG);
+ unsigned int numSubPrims = 0;
+ splitPrimitive(Splitter,prims[primrefID],geomID,primID,split_levels,grid_base,grid_scale,grid_extend,subPrims,numSubPrims);
+ const size_t newID = numPrimitives + primOffset1[j-center];
+ assert(newID+numSubPrims <= alloc_numPrimitives);
+ prims[primrefID] = subPrims[0];
+ for (size_t i=1;i<numSubPrims;i++)
+ prims[newID+i-1] = subPrims[i];
+ }
+ });
+
+ numPrimitives += offset;
+ DBG_PRESPLIT(
+ PRINT(pinfo.size());
+ PRINT(numPrimitives);
+ PRINT((float)numPrimitives/org_numPrimitives));
+ }
+
+ /* recompute centroid bounding boxes */
+ pinfo = parallel_reduce(size_t(0),numPrimitives,size_t(MIN_STEP_SIZE),PrimInfo(empty),[&] (const range<size_t>& r) -> PrimInfo {
+ PrimInfo p(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ p.add_center2(prims[j]);
+ return p;
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ assert(pinfo.size() == numPrimitives);
+
+ /* free double buffer presplit items */
+ alignedFree(tmp_presplitItem);
+ alignedFree(presplitItem);
+ return pinfo;
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/builders/splitter.h b/thirdparty/embree/kernels/builders/splitter.h
new file mode 100644
index 0000000000..f7720bd284
--- /dev/null
+++ b/thirdparty/embree/kernels/builders/splitter.h
@@ -0,0 +1,191 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/scene.h"
+#include "../common/primref.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<size_t N>
+ __forceinline void splitPolygon(const BBox3fa& bounds,
+ const size_t dim,
+ const float pos,
+ const Vec3fa (&v)[N+1],
+ const Vec3fa (&inv_length)[N],
+ BBox3fa& left_o,
+ BBox3fa& right_o)
+ {
+ BBox3fa left = empty, right = empty;
+ /* clip triangle to left and right box by processing all edges */
+ for (size_t i=0; i<N; i++)
+ {
+ const Vec3fa &v0 = v[i];
+ const Vec3fa &v1 = v[i+1];
+ const float v0d = v0[dim];
+ const float v1d = v1[dim];
+
+ if (v0d <= pos) left. extend(v0); // this point is on left side
+ if (v0d >= pos) right.extend(v0); // this point is on right side
+
+ if ((v0d < pos && pos < v1d) || (v1d < pos && pos < v0d)) // the edge crosses the splitting location
+ {
+ assert((v1d-v0d) != 0.0f);
+ const Vec3fa c = madd(Vec3fa((pos-v0d)*inv_length[i][dim]),v1-v0,v0);
+ left.extend(c);
+ right.extend(c);
+ }
+ }
+
+ /* clip against current bounds */
+ left_o = intersect(left,bounds);
+ right_o = intersect(right,bounds);
+ }
+
+ template<size_t N>
+ __forceinline void splitPolygon(const PrimRef& prim,
+ const size_t dim,
+ const float pos,
+ const Vec3fa (&v)[N+1],
+ PrimRef& left_o,
+ PrimRef& right_o)
+ {
+ BBox3fa left = empty, right = empty;
+ for (size_t i=0; i<N; i++)
+ {
+ const Vec3fa &v0 = v[i];
+ const Vec3fa &v1 = v[i+1];
+ const float v0d = v0[dim];
+ const float v1d = v1[dim];
+
+ if (v0d <= pos) left. extend(v0); // this point is on left side
+ if (v0d >= pos) right.extend(v0); // this point is on right side
+
+ if ((v0d < pos && pos < v1d) || (v1d < pos && pos < v0d)) // the edge crosses the splitting location
+ {
+ assert((v1d-v0d) != 0.0f);
+ const float inv_length = 1.0f/(v1d-v0d);
+ const Vec3fa c = madd(Vec3fa((pos-v0d)*inv_length),v1-v0,v0);
+ left.extend(c);
+ right.extend(c);
+ }
+ }
+
+ /* clip against current bounds */
+ new (&left_o ) PrimRef(intersect(left ,prim.bounds()),prim.geomID(), prim.primID());
+ new (&right_o) PrimRef(intersect(right,prim.bounds()),prim.geomID(), prim.primID());
+ }
+
+ struct TriangleSplitter
+ {
+ __forceinline TriangleSplitter(const Scene* scene, const PrimRef& prim)
+ {
+ const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
+ const TriangleMesh* mesh = (const TriangleMesh*) scene->get(prim.geomID() & mask );
+ TriangleMesh::Triangle tri = mesh->triangle(prim.primID());
+ v[0] = mesh->vertex(tri.v[0]);
+ v[1] = mesh->vertex(tri.v[1]);
+ v[2] = mesh->vertex(tri.v[2]);
+ v[3] = mesh->vertex(tri.v[0]);
+ inv_length[0] = Vec3fa(1.0f) / (v[1]-v[0]);
+ inv_length[1] = Vec3fa(1.0f) / (v[2]-v[1]);
+ inv_length[2] = Vec3fa(1.0f) / (v[0]-v[2]);
+ }
+
+ __forceinline void operator() (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const {
+ splitPolygon<3>(prim,dim,pos,v,left_o,right_o);
+ }
+
+ __forceinline void operator() (const BBox3fa& prim, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const {
+ splitPolygon<3>(prim,dim,pos,v,inv_length,left_o,right_o);
+ }
+
+ private:
+ Vec3fa v[4];
+ Vec3fa inv_length[3];
+ };
+
+ struct TriangleSplitterFactory
+ {
+ __forceinline TriangleSplitterFactory(const Scene* scene)
+ : scene(scene) {}
+
+ __forceinline TriangleSplitter operator() (const PrimRef& prim) const {
+ return TriangleSplitter(scene,prim);
+ }
+
+ private:
+ const Scene* scene;
+ };
+
+ struct QuadSplitter
+ {
+ __forceinline QuadSplitter(const Scene* scene, const PrimRef& prim)
+ {
+ const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
+ const QuadMesh* mesh = (const QuadMesh*) scene->get(prim.geomID() & mask );
+ QuadMesh::Quad quad = mesh->quad(prim.primID());
+ v[0] = mesh->vertex(quad.v[0]);
+ v[1] = mesh->vertex(quad.v[1]);
+ v[2] = mesh->vertex(quad.v[2]);
+ v[3] = mesh->vertex(quad.v[3]);
+ v[4] = mesh->vertex(quad.v[0]);
+ inv_length[0] = Vec3fa(1.0f) / (v[1]-v[0]);
+ inv_length[1] = Vec3fa(1.0f) / (v[2]-v[1]);
+ inv_length[2] = Vec3fa(1.0f) / (v[3]-v[2]);
+ inv_length[3] = Vec3fa(1.0f) / (v[0]-v[3]);
+ }
+
+ __forceinline void operator() (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const {
+ splitPolygon<4>(prim,dim,pos,v,left_o,right_o);
+ }
+
+ __forceinline void operator() (const BBox3fa& prim, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const {
+ splitPolygon<4>(prim,dim,pos,v,inv_length,left_o,right_o);
+ }
+
+ private:
+ Vec3fa v[5];
+ Vec3fa inv_length[4];
+ };
+
+ struct QuadSplitterFactory
+ {
+ __forceinline QuadSplitterFactory(const Scene* scene)
+ : scene(scene) {}
+
+ __forceinline QuadSplitter operator() (const PrimRef& prim) const {
+ return QuadSplitter(scene,prim);
+ }
+
+ private:
+ const Scene* scene;
+ };
+
+
+ struct DummySplitter
+ {
+ __forceinline DummySplitter(const Scene* scene, const PrimRef& prim)
+ {
+ }
+ };
+
+ struct DummySplitterFactory
+ {
+ __forceinline DummySplitterFactory(const Scene* scene)
+ : scene(scene) {}
+
+ __forceinline DummySplitter operator() (const PrimRef& prim) const {
+ return DummySplitter(scene,prim);
+ }
+
+ private:
+ const Scene* scene;
+ };
+
+ }
+}
+
diff --git a/thirdparty/embree/kernels/bvh/bvh.cpp b/thirdparty/embree/kernels/bvh/bvh.cpp
new file mode 100644
index 0000000000..a84295f0da
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh.cpp
@@ -0,0 +1,190 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh.h"
+#include "bvh_statistics.h"
+
+namespace embree
+{
+ template<int N>
+ BVHN<N>::BVHN (const PrimitiveType& primTy, Scene* scene)
+ : AccelData((N==4) ? AccelData::TY_BVH4 : (N==8) ? AccelData::TY_BVH8 : AccelData::TY_UNKNOWN),
+ primTy(&primTy), device(scene->device), scene(scene),
+ root(emptyNode), alloc(scene->device,scene->isStaticAccel()), numPrimitives(0), numVertices(0)
+ {
+ }
+
+ template<int N>
+ BVHN<N>::~BVHN ()
+ {
+ for (size_t i=0; i<objects.size(); i++)
+ delete objects[i];
+ }
+
+ template<int N>
+ void BVHN<N>::clear()
+ {
+ set(BVHN::emptyNode,empty,0);
+ alloc.clear();
+ }
+
+ template<int N>
+ void BVHN<N>::set (NodeRef root, const LBBox3fa& bounds, size_t numPrimitives)
+ {
+ this->root = root;
+ this->bounds = bounds;
+ this->numPrimitives = numPrimitives;
+ }
+
+ template<int N>
+ void BVHN<N>::clearBarrier(NodeRef& node)
+ {
+ if (node.isBarrier())
+ node.clearBarrier();
+ else if (!node.isLeaf()) {
+ BaseNode* n = node.baseNode(); // FIXME: flags should be stored in BVH
+ for (size_t c=0; c<N; c++)
+ clearBarrier(n->child(c));
+ }
+ }
+
+ template<int N>
+ void BVHN<N>::layoutLargeNodes(size_t num)
+ {
+#if defined(__64BIT__) // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues
+ struct NodeArea
+ {
+ __forceinline NodeArea() {}
+
+ __forceinline NodeArea(NodeRef& node, const BBox3fa& bounds)
+ : node(&node), A(node.isLeaf() ? float(neg_inf) : area(bounds)) {}
+
+ __forceinline bool operator< (const NodeArea& other) const {
+ return this->A < other.A;
+ }
+
+ NodeRef* node;
+ float A;
+ };
+ std::vector<NodeArea> lst;
+ lst.reserve(num);
+ lst.push_back(NodeArea(root,empty));
+
+ while (lst.size() < num)
+ {
+ std::pop_heap(lst.begin(), lst.end());
+ NodeArea n = lst.back(); lst.pop_back();
+ if (!n.node->isAABBNode()) break;
+ AABBNode* node = n.node->getAABBNode();
+ for (size_t i=0; i<N; i++) {
+ if (node->child(i) == BVHN::emptyNode) continue;
+ lst.push_back(NodeArea(node->child(i),node->bounds(i)));
+ std::push_heap(lst.begin(), lst.end());
+ }
+ }
+
+ for (size_t i=0; i<lst.size(); i++)
+ lst[i].node->setBarrier();
+
+ root = layoutLargeNodesRecursion(root,alloc.getCachedAllocator());
+#endif
+ }
+
+ template<int N>
+ typename BVHN<N>::NodeRef BVHN<N>::layoutLargeNodesRecursion(NodeRef& node, const FastAllocator::CachedAllocator& allocator)
+ {
+ if (node.isBarrier()) {
+ node.clearBarrier();
+ return node;
+ }
+ else if (node.isAABBNode())
+ {
+ AABBNode* oldnode = node.getAABBNode();
+ AABBNode* newnode = (BVHN::AABBNode*) allocator.malloc0(sizeof(BVHN::AABBNode),byteNodeAlignment);
+ *newnode = *oldnode;
+ for (size_t c=0; c<N; c++)
+ newnode->child(c) = layoutLargeNodesRecursion(oldnode->child(c),allocator);
+ return encodeNode(newnode);
+ }
+ else return node;
+ }
+
+ template<int N>
+ double BVHN<N>::preBuild(const std::string& builderName)
+ {
+ if (builderName == "")
+ return inf;
+
+ if (device->verbosity(2))
+ {
+ Lock<MutexSys> lock(g_printMutex);
+ std::cout << "building BVH" << N << (builderName.find("MBlur") != std::string::npos ? "MB" : "") << "<" << primTy->name() << "> using " << builderName << " ..." << std::endl << std::flush;
+ }
+
+ double t0 = 0.0;
+ if (device->benchmark || device->verbosity(2)) t0 = getSeconds();
+ return t0;
+ }
+
+ template<int N>
+ void BVHN<N>::postBuild(double t0)
+ {
+ if (t0 == double(inf))
+ return;
+
+ double dt = 0.0;
+ if (device->benchmark || device->verbosity(2))
+ dt = getSeconds()-t0;
+
+ std::unique_ptr<BVHNStatistics<N>> stat;
+
+ /* print statistics */
+ if (device->verbosity(2))
+ {
+ if (!stat) stat.reset(new BVHNStatistics<N>(this));
+ const size_t usedBytes = alloc.getUsedBytes();
+ Lock<MutexSys> lock(g_printMutex);
+ std::cout << "finished BVH" << N << "<" << primTy->name() << "> : " << 1000.0f*dt << "ms, " << 1E-6*double(numPrimitives)/dt << " Mprim/s, " << 1E-9*double(usedBytes)/dt << " GB/s" << std::endl;
+
+ if (device->verbosity(2))
+ std::cout << stat->str();
+
+ if (device->verbosity(2))
+ {
+ FastAllocator::AllStatistics stat(&alloc);
+ for (size_t i=0; i<objects.size(); i++)
+ if (objects[i])
+ stat = stat + FastAllocator::AllStatistics(&objects[i]->alloc);
+
+ stat.print(numPrimitives);
+ }
+
+ if (device->verbosity(3))
+ {
+ alloc.print_blocks();
+ for (size_t i=0; i<objects.size(); i++)
+ if (objects[i])
+ objects[i]->alloc.print_blocks();
+ }
+
+ std::cout << std::flush;
+ }
+
+ /* benchmark mode */
+ if (device->benchmark)
+ {
+ if (!stat) stat.reset(new BVHNStatistics<N>(this));
+ Lock<MutexSys> lock(g_printMutex);
+ std::cout << "BENCHMARK_BUILD " << dt << " " << double(numPrimitives)/dt << " " << stat->sah() << " " << stat->bytesUsed() << " BVH" << N << "<" << primTy->name() << ">" << std::endl << std::flush;
+ }
+ }
+
+#if defined(__AVX__)
+ template class BVHN<8>;
+#endif
+
+#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)
+ template class BVHN<4>;
+#endif
+}
+
diff --git a/thirdparty/embree/kernels/bvh/bvh.h b/thirdparty/embree/kernels/bvh/bvh.h
new file mode 100644
index 0000000000..565eec5a58
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh.h
@@ -0,0 +1,235 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+/* include all node types */
+#include "bvh_node_aabb.h"
+#include "bvh_node_aabb_mb.h"
+#include "bvh_node_aabb_mb4d.h"
+#include "bvh_node_obb.h"
+#include "bvh_node_obb_mb.h"
+#include "bvh_node_qaabb.h"
+
+namespace embree
+{
+ /*! flags used to enable specific node types in intersectors */
+ enum BVHNodeFlags
+ {
+ BVH_FLAG_ALIGNED_NODE = 0x00001,
+ BVH_FLAG_ALIGNED_NODE_MB = 0x00010,
+ BVH_FLAG_UNALIGNED_NODE = 0x00100,
+ BVH_FLAG_UNALIGNED_NODE_MB = 0x01000,
+ BVH_FLAG_QUANTIZED_NODE = 0x100000,
+ BVH_FLAG_ALIGNED_NODE_MB4D = 0x1000000,
+
+ /* short versions */
+ BVH_AN1 = BVH_FLAG_ALIGNED_NODE,
+ BVH_AN2 = BVH_FLAG_ALIGNED_NODE_MB,
+ BVH_AN2_AN4D = BVH_FLAG_ALIGNED_NODE_MB | BVH_FLAG_ALIGNED_NODE_MB4D,
+ BVH_UN1 = BVH_FLAG_UNALIGNED_NODE,
+ BVH_UN2 = BVH_FLAG_UNALIGNED_NODE_MB,
+ BVH_MB = BVH_FLAG_ALIGNED_NODE_MB | BVH_FLAG_UNALIGNED_NODE_MB | BVH_FLAG_ALIGNED_NODE_MB4D,
+ BVH_AN1_UN1 = BVH_FLAG_ALIGNED_NODE | BVH_FLAG_UNALIGNED_NODE,
+ BVH_AN2_UN2 = BVH_FLAG_ALIGNED_NODE_MB | BVH_FLAG_UNALIGNED_NODE_MB,
+ BVH_AN2_AN4D_UN2 = BVH_FLAG_ALIGNED_NODE_MB | BVH_FLAG_ALIGNED_NODE_MB4D | BVH_FLAG_UNALIGNED_NODE_MB,
+ BVH_QN1 = BVH_FLAG_QUANTIZED_NODE
+ };
+
+ /*! Multi BVH with N children. Each node stores the bounding box of
+ * it's N children as well as N child references. */
+ template<int N>
+ class BVHN : public AccelData
+ {
+ ALIGNED_CLASS_(16);
+ public:
+
+ /*! forward declaration of node ref type */
+ typedef NodeRefPtr<N> NodeRef;
+ typedef BaseNode_t<NodeRef,N> BaseNode;
+ typedef AABBNode_t<NodeRef,N> AABBNode;
+ typedef AABBNodeMB_t<NodeRef,N> AABBNodeMB;
+ typedef AABBNodeMB4D_t<NodeRef,N> AABBNodeMB4D;
+ typedef OBBNode_t<NodeRef,N> OBBNode;
+ typedef OBBNodeMB_t<NodeRef,N> OBBNodeMB;
+ typedef QuantizedBaseNode_t<N> QuantizedBaseNode;
+ typedef QuantizedBaseNodeMB_t<N> QuantizedBaseNodeMB;
+ typedef QuantizedNode_t<NodeRef,N> QuantizedNode;
+
+ /*! Number of bytes the nodes and primitives are minimally aligned to.*/
+ static const size_t byteAlignment = 16;
+ static const size_t byteNodeAlignment = 4*N;
+
+ /*! Empty node */
+ static const size_t emptyNode = NodeRef::emptyNode;
+
+ /*! Invalid node, used as marker in traversal */
+ static const size_t invalidNode = NodeRef::invalidNode;
+ static const size_t popRay = NodeRef::popRay;
+
+ /*! Maximum depth of the BVH. */
+ static const size_t maxBuildDepth = 32;
+ static const size_t maxBuildDepthLeaf = maxBuildDepth+8;
+ static const size_t maxDepth = 2*maxBuildDepthLeaf; // 2x because of two level builder
+
+ /*! Maximum number of primitive blocks in a leaf. */
+ static const size_t maxLeafBlocks = NodeRef::maxLeafBlocks;
+
+ public:
+
+ /*! Builder interface to create allocator */
+ struct CreateAlloc : public FastAllocator::Create {
+ __forceinline CreateAlloc (BVHN* bvh) : FastAllocator::Create(&bvh->alloc) {}
+ };
+
+ typedef BVHNodeRecord<NodeRef> NodeRecord;
+ typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
+ typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
+
+ public:
+
+ /*! BVHN default constructor. */
+ BVHN (const PrimitiveType& primTy, Scene* scene);
+
+ /*! BVHN destruction */
+ ~BVHN ();
+
+ /*! clears the acceleration structure */
+ void clear();
+
+ /*! sets BVH members after build */
+ void set (NodeRef root, const LBBox3fa& bounds, size_t numPrimitives);
+
+ /*! Clears the barrier bits of a subtree. */
+ void clearBarrier(NodeRef& node);
+
+ /*! lays out num large nodes of the BVH */
+ void layoutLargeNodes(size_t num);
+ NodeRef layoutLargeNodesRecursion(NodeRef& node, const FastAllocator::CachedAllocator& allocator);
+
+ /*! called by all builders before build starts */
+ double preBuild(const std::string& builderName);
+
+ /*! called by all builders after build ended */
+ void postBuild(double t0);
+
+ /*! allocator class */
+ struct Allocator {
+ BVHN* bvh;
+ Allocator (BVHN* bvh) : bvh(bvh) {}
+ __forceinline void* operator() (size_t bytes) const {
+ return bvh->alloc._threadLocal()->malloc(&bvh->alloc,bytes);
+ }
+ };
+
+ /*! post build cleanup */
+ void cleanup() {
+ alloc.cleanup();
+ }
+
+ public:
+
+ /*! Encodes a node */
+ static __forceinline NodeRef encodeNode(AABBNode* node) { return NodeRef::encodeNode(node); }
+ static __forceinline NodeRef encodeNode(AABBNodeMB* node) { return NodeRef::encodeNode(node); }
+ static __forceinline NodeRef encodeNode(AABBNodeMB4D* node) { return NodeRef::encodeNode(node); }
+ static __forceinline NodeRef encodeNode(OBBNode* node) { return NodeRef::encodeNode(node); }
+ static __forceinline NodeRef encodeNode(OBBNodeMB* node) { return NodeRef::encodeNode(node); }
+ static __forceinline NodeRef encodeLeaf(void* tri, size_t num) { return NodeRef::encodeLeaf(tri,num); }
+ static __forceinline NodeRef encodeTypedLeaf(void* ptr, size_t ty) { return NodeRef::encodeTypedLeaf(ptr,ty); }
+
+ public:
+
+ /*! Prefetches the node this reference points to */
+ __forceinline static void prefetch(const NodeRef ref, int types=0)
+ {
+#if defined(__AVX512PF__) // MIC
+ if (types != BVH_FLAG_QUANTIZED_NODE) {
+ prefetchL2(((char*)ref.ptr)+0*64);
+ prefetchL2(((char*)ref.ptr)+1*64);
+ if ((N >= 8) || (types > BVH_FLAG_ALIGNED_NODE)) {
+ prefetchL2(((char*)ref.ptr)+2*64);
+ prefetchL2(((char*)ref.ptr)+3*64);
+ }
+ if ((N >= 8) && (types > BVH_FLAG_ALIGNED_NODE)) {
+ /* KNL still needs L2 prefetches for large nodes */
+ prefetchL2(((char*)ref.ptr)+4*64);
+ prefetchL2(((char*)ref.ptr)+5*64);
+ prefetchL2(((char*)ref.ptr)+6*64);
+ prefetchL2(((char*)ref.ptr)+7*64);
+ }
+ }
+ else
+ {
+ /* todo: reduce if 32bit offsets are enabled */
+ prefetchL2(((char*)ref.ptr)+0*64);
+ prefetchL2(((char*)ref.ptr)+1*64);
+ prefetchL2(((char*)ref.ptr)+2*64);
+ }
+#else
+ if (types != BVH_FLAG_QUANTIZED_NODE) {
+ prefetchL1(((char*)ref.ptr)+0*64);
+ prefetchL1(((char*)ref.ptr)+1*64);
+ if ((N >= 8) || (types > BVH_FLAG_ALIGNED_NODE)) {
+ prefetchL1(((char*)ref.ptr)+2*64);
+ prefetchL1(((char*)ref.ptr)+3*64);
+ }
+ if ((N >= 8) && (types > BVH_FLAG_ALIGNED_NODE)) {
+ /* deactivate for large nodes on Xeon, as it introduces regressions */
+ //prefetchL1(((char*)ref.ptr)+4*64);
+ //prefetchL1(((char*)ref.ptr)+5*64);
+ //prefetchL1(((char*)ref.ptr)+6*64);
+ //prefetchL1(((char*)ref.ptr)+7*64);
+ }
+ }
+ else
+ {
+ /* todo: reduce if 32bit offsets are enabled */
+ prefetchL1(((char*)ref.ptr)+0*64);
+ prefetchL1(((char*)ref.ptr)+1*64);
+ prefetchL1(((char*)ref.ptr)+2*64);
+ }
+#endif
+ }
+
+ __forceinline static void prefetchW(const NodeRef ref, int types=0)
+ {
+ embree::prefetchEX(((char*)ref.ptr)+0*64);
+ embree::prefetchEX(((char*)ref.ptr)+1*64);
+ if ((N >= 8) || (types > BVH_FLAG_ALIGNED_NODE)) {
+ embree::prefetchEX(((char*)ref.ptr)+2*64);
+ embree::prefetchEX(((char*)ref.ptr)+3*64);
+ }
+ if ((N >= 8) && (types > BVH_FLAG_ALIGNED_NODE)) {
+ embree::prefetchEX(((char*)ref.ptr)+4*64);
+ embree::prefetchEX(((char*)ref.ptr)+5*64);
+ embree::prefetchEX(((char*)ref.ptr)+6*64);
+ embree::prefetchEX(((char*)ref.ptr)+7*64);
+ }
+ }
+
+ /*! bvh type information */
+ public:
+ const PrimitiveType* primTy; //!< primitive type stored in the BVH
+
+ /*! bvh data */
+ public:
+ Device* device; //!< device pointer
+ Scene* scene; //!< scene pointer
+ NodeRef root; //!< root node
+ FastAllocator alloc; //!< allocator used to allocate nodes
+
+ /*! statistics data */
+ public:
+ size_t numPrimitives; //!< number of primitives the BVH is build over
+ size_t numVertices; //!< number of vertices the BVH references
+
+ /*! data arrays for special builders */
+ public:
+ std::vector<BVHN*> objects;
+ vector_t<char,aligned_allocator<char,32>> subdiv_patches;
+ };
+
+ typedef BVHN<4> BVH4;
+ typedef BVHN<8> BVH8;
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh4_factory.cpp b/thirdparty/embree/kernels/bvh/bvh4_factory.cpp
new file mode 100644
index 0000000000..890d5e7b7c
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh4_factory.cpp
@@ -0,0 +1,1325 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh4_factory.h"
+#include "../bvh/bvh.h"
+
+#include "../geometry/curveNv.h"
+#include "../geometry/curveNi.h"
+#include "../geometry/curveNi_mb.h"
+#include "../geometry/linei.h"
+#include "../geometry/triangle.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/trianglev_mb.h"
+#include "../geometry/trianglei.h"
+#include "../geometry/quadv.h"
+#include "../geometry/quadi.h"
+#include "../geometry/subdivpatch1.h"
+#include "../geometry/object.h"
+#include "../geometry/instance.h"
+#include "../geometry/subgrid.h"
+#include "../common/accelinstance.h"
+
+namespace embree
+{
+ DECLARE_SYMBOL2(Accel::Collider,BVH4ColliderUserGeom);
+
+ DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector4i,void);
+ DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8i,void);
+ DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector4v,void);
+ DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8v,void);
+ DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector4iMB,void);
+ DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8iMB,void);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersector1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersector1MB);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersectorRobust1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersectorRobust1MB);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4Intersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vIntersector1Pluecker);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vMBIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iMBIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vMBIntersector1Pluecker);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iMBIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4vIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4iIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4vIntersector1Pluecker);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4iIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4iMBIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4Quad4iMBIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,QBVH4Triangle4iIntersector1Pluecker);
+ DECLARE_SYMBOL2(Accel::Intersector1,QBVH4Quad4iIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4SubdivPatch1Intersector1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4SubdivPatch1MBIntersector1);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4VirtualIntersector1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4VirtualMBIntersector1);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4InstanceIntersector1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4InstanceMBIntersector1);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4GridIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4GridMBIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH4GridIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersector4Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersector4HybridMB);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersectorRobust4Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersectorRobust4HybridMB);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4Intersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4Intersector4HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vIntersector4HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vMBIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iMBIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vMBIntersector4HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iMBIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4iIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4iIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4iMBIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4Quad4iMBIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4SubdivPatch1Intersector4);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4SubdivPatch1MBIntersector4);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4VirtualIntersector4Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4VirtualMBIntersector4Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4InstanceIntersector4Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4InstanceMBIntersector4Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4GridIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4GridMBIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH4GridIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersector8Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersector8HybridMB);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersectorRobust8Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersectorRobust8HybridMB);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4Intersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4Intersector8HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vIntersector8HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vMBIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iMBIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vMBIntersector8HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iMBIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4iIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4iIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4iMBIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4Quad4iMBIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4SubdivPatch1Intersector8);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4SubdivPatch1MBIntersector8);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4VirtualIntersector8Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4VirtualMBIntersector8Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4InstanceIntersector8Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4InstanceMBIntersector8Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4GridIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4GridMBIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH4GridIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersector16Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersector16HybridMB);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersectorRobust16Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersectorRobust16HybridMB);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4Intersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4Intersector16HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vIntersector16HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vMBIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iMBIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vMBIntersector16HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iMBIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4iIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4iIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4iMBIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4Quad4iMBIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4SubdivPatch1Intersector16);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4SubdivPatch1MBIntersector16);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4VirtualIntersector16Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4VirtualMBIntersector16Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4InstanceIntersector16Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4InstanceMBIntersector16Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4GridIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4GridMBIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH4GridIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4IntersectorStreamPacketFallback);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4IntersectorStreamMoeller);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4IntersectorStreamMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4iIntersectorStreamMoeller);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4vIntersectorStreamPluecker);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Triangle4iIntersectorStreamPluecker);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4vIntersectorStreamMoeller);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4vIntersectorStreamMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4iIntersectorStreamMoeller);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4vIntersectorStreamPluecker);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Quad4iIntersectorStreamPluecker);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4VirtualIntersectorStream);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH4InstanceIntersectorStream);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4MeshSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4vMeshSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Curve4vBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Curve4iBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4OBBCurve4iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Curve8iBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4OBBCurve8iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4QuantizedTriangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4QuantizedQuad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4SceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMBSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4GridSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4GridMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4SubdivPatch1BuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4SubdivPatch1MBBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4MeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshRefitSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
+
+ BVH4Factory::BVH4Factory(int bfeatures, int ifeatures)
+ {
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2(ifeatures,BVH4ColliderUserGeom);
+
+ selectBuilders(bfeatures);
+ selectIntersectors(ifeatures);
+ }
+
+ void BVH4Factory::selectBuilders(int features)
+ {
+ IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelTriangle4MeshSAH));
+ IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelTriangle4iMeshSAH));
+ IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelTriangle4vMeshSAH));
+ IF_ENABLED_QUADS (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelQuadMeshSAH));
+ IF_ENABLED_USER (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelVirtualSAH));
+ IF_ENABLED_INSTANCE (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelInstanceSAH));
+
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Curve4vBuilder_OBB_New));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Curve4iBuilder_OBB_New));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4OBBCurve4iMBBuilder_OBB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH4Curve8iBuilder_OBB_New));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH4OBBCurve8iMBBuilder_OBB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4SceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4vSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4iSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4iMBSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4vMBSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4QuantizedTriangle4iSceneBuilderSAH));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4vSceneBuilderSAH));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4iSceneBuilderSAH));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4iMBSceneBuilderSAH));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4QuantizedQuad4iSceneBuilderSAH));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4SceneBuilderFastSpatialSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4vSceneBuilderFastSpatialSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4iSceneBuilderFastSpatialSAH));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4vSceneBuilderFastSpatialSAH));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4VirtualSceneBuilderSAH));
+ IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4VirtualMBSceneBuilderSAH));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4InstanceSceneBuilderSAH));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4InstanceMBSceneBuilderSAH));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4GridSceneBuilderSAH));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4GridMBSceneBuilderSAH));
+
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4SubdivPatch1BuilderSAH));
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4SubdivPatch1MBBuilderSAH));
+ }
+
+ void BVH4Factory::selectIntersectors(int features)
+ {
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,VirtualCurveIntersector4i));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8i));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,VirtualCurveIntersector4v));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8v));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,VirtualCurveIntersector4iMB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8iMB));
+
+ /* select intersectors1 */
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector1));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector1MB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust1));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust1MB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector1Moeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,BVH4Triangle4iIntersector1Moeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,BVH4Triangle4vIntersector1Pluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,BVH4Triangle4iIntersector1Pluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector1Moeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector1Moeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector1Pluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector1Pluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector1Moeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector1Moeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector1Pluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector1Pluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector1Pluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector1Moeller));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,QBVH4Triangle4iIntersector1Pluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,QBVH4Quad4iIntersector1Pluecker));
+
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4SubdivPatch1Intersector1));
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4SubdivPatch1MBIntersector1));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualIntersector1));
+ IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualMBIntersector1));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceIntersector1));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceMBIntersector1));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridIntersector1Moeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridMBIntersector1Moeller))
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridIntersector1Pluecker));
+
+#if defined (EMBREE_RAY_PACKETS)
+
+ /* select intersectors4 */
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector4Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector4HybridMB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust4Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust4HybridMB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector4HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector4HybridMoellerNoFilter));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersector4HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vIntersector4HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersector4HybridPluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector4HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector4HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector4HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector4HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector4HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector4HybridMoellerNoFilter));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector4HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector4HybridPluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector4HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector4HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector4HybridPluecker));
+
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4SubdivPatch1Intersector4));
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4SubdivPatch1MBIntersector4));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualIntersector4Chunk));
+ IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualMBIntersector4Chunk));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceIntersector4Chunk));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceMBIntersector4Chunk));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector4HybridMoeller));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridIntersector4HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridMBIntersector4HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridIntersector4HybridPluecker));
+
+ /* select intersectors8 */
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector8Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector8HybridMB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust8Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust8HybridMB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector8HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector8HybridMoellerNoFilter));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersector8HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4vIntersector8HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersector8HybridPluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector8HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector8HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector8HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector8HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector8HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector8HybridMoellerNoFilter));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector8HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector8HybridPluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector8HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector8HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector8HybridPluecker));
+
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4SubdivPatch1Intersector8));
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4SubdivPatch1MBIntersector8));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4VirtualIntersector8Chunk));
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4VirtualMBIntersector8Chunk));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4InstanceIntersector8Chunk));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4InstanceMBIntersector8Chunk));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4GridIntersector8HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4GridMBIntersector8HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4GridIntersector8HybridPluecker));
+
+ /* select intersectors16 */
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH4OBBVirtualCurveIntersector16Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH4OBBVirtualCurveIntersector16HybridMB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust16Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust16HybridMB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4Intersector16HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4Intersector16HybridMoellerNoFilter));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4iIntersector16HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4vIntersector16HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4iIntersector16HybridPluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4vMBIntersector16HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4iMBIntersector16HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4vMBIntersector16HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4iMBIntersector16HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4vIntersector16HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4vIntersector16HybridMoellerNoFilter));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4iIntersector16HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4vIntersector16HybridPluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4iIntersector16HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4iMBIntersector16HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4iMBIntersector16HybridPluecker));
+
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX512(features,BVH4SubdivPatch1Intersector16));
+ IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX512(features,BVH4SubdivPatch1MBIntersector16));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512(features,BVH4VirtualIntersector16Chunk));
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512(features,BVH4VirtualMBIntersector16Chunk));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512(features,BVH4InstanceIntersector16Chunk));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512(features,BVH4InstanceMBIntersector16Chunk));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH4GridIntersector16HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH4GridMBIntersector16HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH4GridIntersector16HybridPluecker));
+
+ /* select stream intersectors */
+ SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4IntersectorStreamPacketFallback);
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4IntersectorStreamMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4IntersectorStreamMoellerNoFilter));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersectorStreamMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vIntersectorStreamPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersectorStreamPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersectorStreamMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersectorStreamMoellerNoFilter));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersectorStreamMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersectorStreamPluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersectorStreamPluecker));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualIntersectorStream));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceIntersectorStream));
+
+#endif
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4OBBVirtualCurveIntersectors(BVH4* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.leafIntersector = leafIntersector;
+ intersectors.intersector1 = BVH4OBBVirtualCurveIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4OBBVirtualCurveIntersector4Hybrid();
+ intersectors.intersector8 = BVH4OBBVirtualCurveIntersector8Hybrid();
+ intersectors.intersector16 = BVH4OBBVirtualCurveIntersector16Hybrid();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.leafIntersector = leafIntersector;
+ intersectors.intersector1 = BVH4OBBVirtualCurveIntersectorRobust1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4OBBVirtualCurveIntersectorRobust4Hybrid();
+ intersectors.intersector8 = BVH4OBBVirtualCurveIntersectorRobust8Hybrid();
+ intersectors.intersector16 = BVH4OBBVirtualCurveIntersectorRobust16Hybrid();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ default: assert(false);
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4OBBVirtualCurveIntersectorsMB(BVH4* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.leafIntersector = leafIntersector;
+ intersectors.intersector1 = BVH4OBBVirtualCurveIntersector1MB();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4OBBVirtualCurveIntersector4HybridMB();
+ intersectors.intersector8 = BVH4OBBVirtualCurveIntersector8HybridMB();
+ intersectors.intersector16 = BVH4OBBVirtualCurveIntersector16HybridMB();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.leafIntersector = leafIntersector;
+ intersectors.intersector1 = BVH4OBBVirtualCurveIntersectorRobust1MB();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4OBBVirtualCurveIntersectorRobust4HybridMB();
+ intersectors.intersector8 = BVH4OBBVirtualCurveIntersectorRobust8HybridMB();
+ intersectors.intersector16 = BVH4OBBVirtualCurveIntersectorRobust16HybridMB();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ default: assert(false);
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4Triangle4Intersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ assert(ivariant == IntersectVariant::FAST);
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Triangle4Intersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4_filter = BVH4Triangle4Intersector4HybridMoeller();
+ intersectors.intersector4_nofilter = BVH4Triangle4Intersector4HybridMoellerNoFilter();
+ intersectors.intersector8_filter = BVH4Triangle4Intersector8HybridMoeller();
+ intersectors.intersector8_nofilter = BVH4Triangle4Intersector8HybridMoellerNoFilter();
+ intersectors.intersector16_filter = BVH4Triangle4Intersector16HybridMoeller();
+ intersectors.intersector16_nofilter = BVH4Triangle4Intersector16HybridMoellerNoFilter();
+ intersectors.intersectorN_filter = BVH4Triangle4IntersectorStreamMoeller();
+ intersectors.intersectorN_nofilter = BVH4Triangle4IntersectorStreamMoellerNoFilter();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4Triangle4vIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ assert(ivariant == IntersectVariant::ROBUST);
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Triangle4vIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Triangle4vIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH4Triangle4vIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH4Triangle4vIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH4Triangle4vIntersectorStreamPluecker();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4Triangle4iIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Triangle4iIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Triangle4iIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH4Triangle4iIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH4Triangle4iIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH4Triangle4iIntersectorStreamMoeller();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Triangle4iIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Triangle4iIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH4Triangle4iIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH4Triangle4iIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH4Triangle4iIntersectorStreamPluecker();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4Triangle4vMBIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Triangle4vMBIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Triangle4vMBIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH4Triangle4vMBIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH4Triangle4vMBIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Triangle4vMBIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Triangle4vMBIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH4Triangle4vMBIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH4Triangle4vMBIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4Triangle4iMBIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Triangle4iMBIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Triangle4iMBIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH4Triangle4iMBIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH4Triangle4iMBIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Triangle4iMBIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Triangle4iMBIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH4Triangle4iMBIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH4Triangle4iMBIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4Quad4vIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Quad4vIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4_filter = BVH4Quad4vIntersector4HybridMoeller();
+ intersectors.intersector4_nofilter = BVH4Quad4vIntersector4HybridMoellerNoFilter();
+ intersectors.intersector8_filter = BVH4Quad4vIntersector8HybridMoeller();
+ intersectors.intersector8_nofilter = BVH4Quad4vIntersector8HybridMoellerNoFilter();
+ intersectors.intersector16_filter = BVH4Quad4vIntersector16HybridMoeller();
+ intersectors.intersector16_nofilter = BVH4Quad4vIntersector16HybridMoellerNoFilter();
+ intersectors.intersectorN_filter = BVH4Quad4vIntersectorStreamMoeller();
+ intersectors.intersectorN_nofilter = BVH4Quad4vIntersectorStreamMoellerNoFilter();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Quad4vIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Quad4vIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH4Quad4vIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH4Quad4vIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH4Quad4vIntersectorStreamPluecker();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4Quad4iIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Quad4iIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Quad4iIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH4Quad4iIntersector8HybridMoeller();
+ intersectors.intersector16= BVH4Quad4iIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH4Quad4iIntersectorStreamMoeller();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Quad4iIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Quad4iIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH4Quad4iIntersector8HybridPluecker();
+ intersectors.intersector16= BVH4Quad4iIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH4Quad4iIntersectorStreamPluecker();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4Quad4iMBIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Quad4iMBIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Quad4iMBIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH4Quad4iMBIntersector8HybridMoeller();
+ intersectors.intersector16= BVH4Quad4iMBIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4Quad4iMBIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4Quad4iMBIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH4Quad4iMBIntersector8HybridPluecker();
+ intersectors.intersector16= BVH4Quad4iMBIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH4Factory::QBVH4Triangle4iIntersectors(BVH4* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = QBVH4Triangle4iIntersector1Pluecker();
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::QBVH4Quad4iIntersectors(BVH4* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = QBVH4Quad4iIntersector1Pluecker();
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4UserGeometryIntersectors(BVH4* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4VirtualIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4VirtualIntersector4Chunk();
+ intersectors.intersector8 = BVH4VirtualIntersector8Chunk();
+ intersectors.intersector16 = BVH4VirtualIntersector16Chunk();
+ intersectors.intersectorN = BVH4VirtualIntersectorStream();
+#endif
+ intersectors.collider = BVH4ColliderUserGeom();
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4UserGeometryMBIntersectors(BVH4* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4VirtualMBIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4VirtualMBIntersector4Chunk();
+ intersectors.intersector8 = BVH4VirtualMBIntersector8Chunk();
+ intersectors.intersector16 = BVH4VirtualMBIntersector16Chunk();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4InstanceIntersectors(BVH4* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4InstanceIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4InstanceIntersector4Chunk();
+ intersectors.intersector8 = BVH4InstanceIntersector8Chunk();
+ intersectors.intersector16 = BVH4InstanceIntersector16Chunk();
+ intersectors.intersectorN = BVH4InstanceIntersectorStream();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4InstanceMBIntersectors(BVH4* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4InstanceMBIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4InstanceMBIntersector4Chunk();
+ intersectors.intersector8 = BVH4InstanceMBIntersector8Chunk();
+ intersectors.intersector16 = BVH4InstanceMBIntersector16Chunk();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4SubdivPatch1Intersectors(BVH4* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4SubdivPatch1Intersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4SubdivPatch1Intersector4();
+ intersectors.intersector8 = BVH4SubdivPatch1Intersector8();
+ intersectors.intersector16 = BVH4SubdivPatch1Intersector16();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4SubdivPatch1MBIntersectors(BVH4* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4SubdivPatch1MBIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4SubdivPatch1MBIntersector4();
+ intersectors.intersector8 = BVH4SubdivPatch1MBIntersector8();
+ intersectors.intersector16 = BVH4SubdivPatch1MBIntersector16();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+
+ Accel* BVH4Factory::BVH4OBBVirtualCurve4i(Scene* scene, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Curve4i::type,scene);
+ Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectors(accel,VirtualCurveIntersector4i(),ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->hair_builder == "default" ) builder = BVH4Curve4iBuilder_OBB_New(accel,scene,0);
+ else if (scene->device->hair_builder == "sah" ) builder = BVH4Curve4iBuilder_OBB_New(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve4i>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+#if defined(EMBREE_TARGET_SIMD8)
+ Accel* BVH4Factory::BVH4OBBVirtualCurve8i(Scene* scene, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Curve8i::type,scene);
+ Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectors(accel,VirtualCurveIntersector8i(),ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->hair_builder == "default" ) builder = BVH4Curve8iBuilder_OBB_New(accel,scene,0);
+ else if (scene->device->hair_builder == "sah" ) builder = BVH4Curve8iBuilder_OBB_New(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve8i>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+#endif
+
+ Accel* BVH4Factory::BVH4OBBVirtualCurve4v(Scene* scene, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Curve4v::type,scene);
+ Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectors(accel,VirtualCurveIntersector4v(),ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->hair_builder == "default" ) builder = BVH4Curve4vBuilder_OBB_New(accel,scene,0);
+ else if (scene->device->hair_builder == "sah" ) builder = BVH4Curve4vBuilder_OBB_New(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve4v>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4OBBVirtualCurve4iMB(Scene* scene, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Curve4iMB::type,scene);
+ Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectorsMB(accel,VirtualCurveIntersector4iMB(),ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->hair_builder == "default" ) builder = BVH4OBBCurve4iMBBuilder_OBB(accel,scene,0);
+ else if (scene->device->hair_builder == "sah" ) builder = BVH4OBBCurve4iMBBuilder_OBB(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve4iMB>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+#if defined(EMBREE_TARGET_SIMD8)
+ Accel* BVH4Factory::BVH4OBBVirtualCurve8iMB(Scene* scene, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Curve8iMB::type,scene);
+ Accel::Intersectors intersectors = BVH4OBBVirtualCurveIntersectorsMB(accel,VirtualCurveIntersector8iMB(), ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->hair_builder == "default" ) builder = BVH4OBBCurve8iMBBuilder_OBB(accel,scene,0);
+ else if (scene->device->hair_builder == "sah" ) builder = BVH4OBBCurve8iMBBuilder_OBB(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->hair_builder+" for BVH4OBB<VirtualCurve8iMB>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+#endif
+
+ Accel* BVH4Factory::BVH4Triangle4(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Triangle4::type,scene);
+
+ Accel::Intersectors intersectors;
+ if (scene->device->tri_traverser == "default") intersectors = BVH4Triangle4Intersectors(accel,ivariant);
+ else if (scene->device->tri_traverser == "fast" ) intersectors = BVH4Triangle4Intersectors(accel,IntersectVariant::FAST);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser+" for BVH4<Triangle4>");
+
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4Triangle4SceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelTriangle4MeshSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: builder = BVH4Triangle4SceneBuilderFastSpatialSAH(accel,scene,0); break;
+ }
+ }
+ else if (scene->device->tri_builder == "sah" ) builder = BVH4Triangle4SceneBuilderSAH(accel,scene,0);
+ else if (scene->device->tri_builder == "sah_fast_spatial" ) builder = BVH4Triangle4SceneBuilderFastSpatialSAH(accel,scene,0);
+ else if (scene->device->tri_builder == "sah_presplit") builder = BVH4Triangle4SceneBuilderSAH(accel,scene,MODE_HIGH_QUALITY);
+ else if (scene->device->tri_builder == "dynamic" ) builder = BVH4BuilderTwoLevelTriangle4MeshSAH(accel,scene,false);
+ else if (scene->device->tri_builder == "morton" ) builder = BVH4BuilderTwoLevelTriangle4MeshSAH(accel,scene,true);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH4<Triangle4>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4Triangle4v(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Triangle4v::type,scene);
+
+ Accel::Intersectors intersectors;
+ if (scene->device->tri_traverser == "default") intersectors = BVH4Triangle4vIntersectors(accel,ivariant);
+ else if (scene->device->tri_traverser == "fast" ) intersectors = BVH4Triangle4vIntersectors(accel,IntersectVariant::FAST);
+ else if (scene->device->tri_traverser == "robust" ) intersectors = BVH4Triangle4vIntersectors(accel,IntersectVariant::ROBUST);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser+" for BVH4<Triangle4>");
+
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4Triangle4vSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelTriangle4vMeshSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: builder = BVH4Triangle4vSceneBuilderFastSpatialSAH(accel,scene,0); break;
+ }
+ }
+ else if (scene->device->tri_builder == "sah" ) builder = BVH4Triangle4vSceneBuilderSAH(accel,scene,0);
+ else if (scene->device->tri_builder == "sah_fast_spatial" ) builder = BVH4Triangle4vSceneBuilderFastSpatialSAH(accel,scene,0);
+ else if (scene->device->tri_builder == "sah_presplit") builder = BVH4Triangle4vSceneBuilderSAH(accel,scene,MODE_HIGH_QUALITY);
+ else if (scene->device->tri_builder == "dynamic" ) builder = BVH4BuilderTwoLevelTriangle4vMeshSAH(accel,scene,false);
+ else if (scene->device->tri_builder == "morton" ) builder = BVH4BuilderTwoLevelTriangle4vMeshSAH(accel,scene,true);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH4<Triangle4v>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4Triangle4i(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Triangle4i::type,scene);
+
+ Accel::Intersectors intersectors;
+ if (scene->device->tri_traverser == "default") intersectors = BVH4Triangle4iIntersectors(accel,ivariant);
+ else if (scene->device->tri_traverser == "fast" ) intersectors = BVH4Triangle4iIntersectors(accel,IntersectVariant::FAST);
+ else if (scene->device->tri_traverser == "robust" ) intersectors = BVH4Triangle4iIntersectors(accel,IntersectVariant::ROBUST);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser+" for BVH4<Triangle4i>");
+
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder == "default" ) {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4Triangle4iSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelTriangle4iMeshSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: builder = BVH4Triangle4iSceneBuilderFastSpatialSAH(accel,scene,0); break;
+ }
+ }
+ else if (scene->device->tri_builder == "sah" ) builder = BVH4Triangle4iSceneBuilderSAH(accel,scene,0);
+ else if (scene->device->tri_builder == "sah_fast_spatial" ) builder = BVH4Triangle4iSceneBuilderFastSpatialSAH(accel,scene,0);
+ else if (scene->device->tri_builder == "sah_presplit") builder = BVH4Triangle4iSceneBuilderSAH(accel,scene,MODE_HIGH_QUALITY);
+ else if (scene->device->tri_builder == "dynamic" ) builder = BVH4BuilderTwoLevelTriangle4iMeshSAH(accel,scene,false);
+ else if (scene->device->tri_builder == "morton" ) builder = BVH4BuilderTwoLevelTriangle4iMeshSAH(accel,scene,true);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH4<Triangle4i>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4Triangle4iMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Triangle4i::type,scene);
+
+ Accel::Intersectors intersectors;
+ if (scene->device->tri_traverser_mb == "default") intersectors = BVH4Triangle4iMBIntersectors(accel,ivariant);
+ else if (scene->device->tri_traverser_mb == "fast" ) intersectors = BVH4Triangle4iMBIntersectors(accel,IntersectVariant::FAST);
+ else if (scene->device->tri_traverser_mb == "robust" ) intersectors = BVH4Triangle4iMBIntersectors(accel,IntersectVariant::ROBUST);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser_mb+" for BVH4<Triangle4iMB>");
+
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder_mb == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4Triangle4iMBSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->tri_builder_mb == "internal_time_splits") builder = BVH4Triangle4iMBSceneBuilderSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder_mb+" for BVH4<Triangle4iMB>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4Triangle4vMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Triangle4vMB::type,scene);
+
+ Accel::Intersectors intersectors;
+ if (scene->device->tri_traverser_mb == "default") intersectors = BVH4Triangle4vMBIntersectors(accel,ivariant);
+ else if (scene->device->tri_traverser_mb == "fast" ) intersectors = BVH4Triangle4vMBIntersectors(accel,IntersectVariant::FAST);
+ else if (scene->device->tri_traverser_mb == "robust" ) intersectors = BVH4Triangle4vMBIntersectors(accel,IntersectVariant::ROBUST);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown traverser "+scene->device->tri_traverser_mb+" for BVH4<Triangle4vMB>");
+
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder_mb == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4Triangle4vMBSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->tri_builder_mb == "internal_time_splits") builder = BVH4Triangle4vMBSceneBuilderSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder_mb+" for BVH4<Triangle4vMB>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4Quad4v(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Quad4v::type,scene);
+ Accel::Intersectors intersectors = BVH4Quad4vIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->quad_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4Quad4vSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelQuadMeshSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: builder = BVH4Quad4vSceneBuilderFastSpatialSAH(accel,scene,0); break;
+ }
+ }
+ else if (scene->device->quad_builder == "sah" ) builder = BVH4Quad4vSceneBuilderSAH(accel,scene,0);
+ else if (scene->device->quad_builder == "sah_fast_spatial" ) builder = BVH4Quad4vSceneBuilderFastSpatialSAH(accel,scene,0);
+ else if (scene->device->quad_builder == "dynamic" ) builder = BVH4BuilderTwoLevelQuadMeshSAH(accel,scene,false);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for BVH4<Quad4v>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4Quad4i(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Quad4i::type,scene);
+ Accel::Intersectors intersectors = BVH4Quad4iIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->quad_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4Quad4iSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
+ case BuildVariant::HIGH_QUALITY: assert(false); break; // FIXME: implement
+ }
+ }
+ else if (scene->device->quad_builder == "sah") builder = BVH4Quad4iSceneBuilderSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for BVH4<Quad4i>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4Quad4iMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(Quad4i::type,scene);
+ Accel::Intersectors intersectors = BVH4Quad4iMBIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->quad_builder_mb == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4Quad4iMBSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->quad_builder_mb == "sah") builder = BVH4Quad4iMBSceneBuilderSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder_mb+" for BVH4<Quad4iMB>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4QuantizedQuad4i(Scene* scene)
+ {
+ BVH4* accel = new BVH4(Quad4i::type,scene);
+ Builder* builder = BVH4QuantizedQuad4iSceneBuilderSAH(accel,scene,0);
+ Accel::Intersectors intersectors = QBVH4Quad4iIntersectors(accel);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4QuantizedTriangle4i(Scene* scene)
+ {
+ BVH4* accel = new BVH4(Triangle4i::type,scene);
+ Builder* builder = BVH4QuantizedTriangle4iSceneBuilderSAH(accel,scene,0);
+ Accel::Intersectors intersectors = QBVH4Triangle4iIntersectors(accel);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4SubdivPatch1(Scene* scene)
+ {
+ BVH4* accel = new BVH4(SubdivPatch1::type,scene);
+ Accel::Intersectors intersectors = BVH4SubdivPatch1Intersectors(accel);
+ Builder* builder = BVH4SubdivPatch1BuilderSAH(accel,scene,0);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4SubdivPatch1MB(Scene* scene)
+ {
+ BVH4* accel = new BVH4(SubdivPatch1::type,scene);
+ Accel::Intersectors intersectors = BVH4SubdivPatch1MBIntersectors(accel);
+ Builder* builder = BVH4SubdivPatch1MBBuilderSAH(accel,scene,0);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4UserGeometry(Scene* scene, BuildVariant bvariant)
+ {
+ BVH4* accel = new BVH4(Object::type,scene);
+ Accel::Intersectors intersectors = BVH4UserGeometryIntersectors(accel);
+
+ Builder* builder = nullptr;
+ if (scene->device->object_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4VirtualSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelVirtualSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->object_builder == "sah") builder = BVH4VirtualSceneBuilderSAH(accel,scene,0);
+ else if (scene->device->object_builder == "dynamic") builder = BVH4BuilderTwoLevelVirtualSAH(accel,scene,false);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH4<Object>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4UserGeometryMB(Scene* scene)
+ {
+ BVH4* accel = new BVH4(Object::type,scene);
+ Accel::Intersectors intersectors = BVH4UserGeometryMBIntersectors(accel);
+ Builder* builder = BVH4VirtualMBSceneBuilderSAH(accel,scene,0);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4Instance(Scene* scene, bool isExpensive, BuildVariant bvariant)
+ {
+ BVH4* accel = new BVH4(InstancePrimitive::type,scene);
+ Accel::Intersectors intersectors = BVH4InstanceIntersectors(accel);
+ auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE_CHEAP;
+ // Builder* builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype);
+
+ Builder* builder = nullptr;
+ if (scene->device->object_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype); break;
+ case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelInstanceSAH(accel,scene,gtype,false); break;
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->object_builder == "sah") builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype);
+ else if (scene->device->object_builder == "dynamic") builder = BVH4BuilderTwoLevelInstanceSAH(accel,scene,gtype,false);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH4<Object>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4InstanceMB(Scene* scene, bool isExpensive)
+ {
+ BVH4* accel = new BVH4(InstancePrimitive::type,scene);
+ Accel::Intersectors intersectors = BVH4InstanceMBIntersectors(accel);
+ auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE_CHEAP;
+ Builder* builder = BVH4InstanceMBSceneBuilderSAH(accel,scene,gtype);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4GridIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ if (ivariant == IntersectVariant::FAST)
+ {
+ intersectors.intersector1 = BVH4GridIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4GridIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH4GridIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH4GridIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ }
+ else /* if (ivariant == IntersectVariant::ROBUST) */
+ {
+ intersectors.intersector1 = BVH4GridIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4GridIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH4GridIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH4GridIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ }
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH4Factory::BVH4GridMBIntersectors(BVH4* bvh, IntersectVariant ivariant)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH4GridMBIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH4GridMBIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH4GridMBIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH4GridMBIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+
+ Accel* BVH4Factory::BVH4Grid(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(SubGridQBVH4::type,scene);
+ Accel::Intersectors intersectors = BVH4GridIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->object_builder == "default") {
+ builder = BVH4GridSceneBuilderSAH(accel,scene,0);
+ }
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->grid_builder+" for BVH4<GridMesh>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH4Factory::BVH4GridMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH4* accel = new BVH4(SubGridQBVH4::type,scene);
+ Accel::Intersectors intersectors = BVH4GridMBIntersectors(accel,ivariant);
+ Builder* builder = nullptr;
+ if (scene->device->object_builder == "default") {
+ builder = BVH4GridMBSceneBuilderSAH(accel,scene,0);
+ }
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->grid_builder+" for BVH4MB<GridMesh>");
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh4_factory.h b/thirdparty/embree/kernels/bvh/bvh4_factory.h
new file mode 100644
index 0000000000..30973971a4
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh4_factory.h
@@ -0,0 +1,316 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_factory.h"
+
+namespace embree
+{
+ /*! BVH4 instantiations */
+ class BVH4Factory : public BVHFactory
+ {
+ public:
+ BVH4Factory(int bfeatures, int ifeatures);
+
+ public:
+ Accel* BVH4OBBVirtualCurve4i(Scene* scene, IntersectVariant ivariant);
+ Accel* BVH4OBBVirtualCurve4v(Scene* scene, IntersectVariant ivariant);
+ Accel* BVH4OBBVirtualCurve8i(Scene* scene, IntersectVariant ivariant);
+ Accel* BVH4OBBVirtualCurve4iMB(Scene* scene, IntersectVariant ivariant);
+ Accel* BVH4OBBVirtualCurve8iMB(Scene* scene, IntersectVariant ivariant);
+ DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector4i);
+ DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8i);
+ DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector4v);
+ DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8v);
+ DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector4iMB);
+ DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8iMB);
+
+ Accel* BVH4Triangle4 (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH4Triangle4v (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::ROBUST);
+ Accel* BVH4Triangle4i (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH4Triangle4vMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH4Triangle4iMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+
+ Accel* BVH4Quad4v (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH4Quad4i (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH4Quad4iMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+
+ Accel* BVH4QuantizedTriangle4i(Scene* scene);
+ Accel* BVH4QuantizedQuad4i(Scene* scene);
+
+ Accel* BVH4SubdivPatch1(Scene* scene);
+ Accel* BVH4SubdivPatch1MB(Scene* scene);
+
+ Accel* BVH4UserGeometry(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC);
+ Accel* BVH4UserGeometryMB(Scene* scene);
+
+ Accel* BVH4Instance(Scene* scene, bool isExpensive, BuildVariant bvariant = BuildVariant::STATIC);
+ Accel* BVH4InstanceMB(Scene* scene, bool isExpensive);
+
+ Accel* BVH4Grid(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH4GridMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+
+ private:
+ void selectBuilders(int features);
+ void selectIntersectors(int features);
+
+ private:
+ Accel::Intersectors BVH4OBBVirtualCurveIntersectors(BVH4* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant);
+ Accel::Intersectors BVH4OBBVirtualCurveIntersectorsMB(BVH4* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant);
+
+ Accel::Intersectors BVH4Triangle4Intersectors(BVH4* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH4Triangle4vIntersectors(BVH4* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH4Triangle4iIntersectors(BVH4* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH4Triangle4iMBIntersectors(BVH4* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH4Triangle4vMBIntersectors(BVH4* bvh, IntersectVariant ivariant);
+
+ Accel::Intersectors BVH4Quad4vIntersectors(BVH4* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH4Quad4iIntersectors(BVH4* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH4Quad4iMBIntersectors(BVH4* bvh, IntersectVariant ivariant);
+
+ Accel::Intersectors QBVH4Quad4iIntersectors(BVH4* bvh);
+ Accel::Intersectors QBVH4Triangle4iIntersectors(BVH4* bvh);
+
+ Accel::Intersectors BVH4UserGeometryIntersectors(BVH4* bvh);
+ Accel::Intersectors BVH4UserGeometryMBIntersectors(BVH4* bvh);
+
+ Accel::Intersectors BVH4InstanceIntersectors(BVH4* bvh);
+ Accel::Intersectors BVH4InstanceMBIntersectors(BVH4* bvh);
+
+ Accel::Intersectors BVH4SubdivPatch1Intersectors(BVH4* bvh);
+ Accel::Intersectors BVH4SubdivPatch1MBIntersectors(BVH4* bvh);
+
+ Accel::Intersectors BVH4GridIntersectors(BVH4* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH4GridMBIntersectors(BVH4* bvh, IntersectVariant ivariant);
+
+ private:
+
+ DEFINE_SYMBOL2(Accel::Collider,BVH4ColliderUserGeom);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersector1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersector1MB);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersectorRobust1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4OBBVirtualCurveIntersectorRobust1MB);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4Intersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vIntersector1Pluecker);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vMBIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iMBIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4vMBIntersector1Pluecker);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Triangle4iMBIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4vIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4iIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4vIntersector1Pluecker);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4iIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4iMBIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4Quad4iMBIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,QBVH4Triangle4iIntersector1Pluecker);
+ DEFINE_SYMBOL2(Accel::Intersector1,QBVH4Quad4iIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4SubdivPatch1Intersector1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4SubdivPatch1MBIntersector1);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4VirtualIntersector1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4VirtualMBIntersector1);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4InstanceIntersector1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4InstanceMBIntersector1);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4GridIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4GridMBIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH4GridIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersector4Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersector4HybridMB);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersectorRobust4Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4OBBVirtualCurveIntersectorRobust4HybridMB);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4Intersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4Intersector4HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vIntersector4HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vMBIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iMBIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4vMBIntersector4HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Triangle4iMBIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4iIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4vIntersector4HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4iIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4iMBIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4Quad4iMBIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4SubdivPatch1Intersector4);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4SubdivPatch1MBIntersector4);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4VirtualIntersector4Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4VirtualMBIntersector4Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4InstanceIntersector4Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4InstanceMBIntersector4Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4GridIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4GridMBIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH4GridIntersector4HybridPluecker);
+
+ // ==============
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersector8Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersector8HybridMB);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersectorRobust8Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4OBBVirtualCurveIntersectorRobust8HybridMB);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4Intersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4Intersector8HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vIntersector8HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vMBIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iMBIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4vMBIntersector8HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Triangle4iMBIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4iIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4vIntersector8HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4iIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4iMBIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4Quad4iMBIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4SubdivPatch1Intersector8);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4SubdivPatch1MBIntersector8);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4VirtualIntersector8Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4VirtualMBIntersector8Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4InstanceIntersector8Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4InstanceMBIntersector8Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4GridIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4GridMBIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH4GridIntersector8HybridPluecker);
+
+ // ==============
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersector16Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersector16HybridMB);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersectorRobust16Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4OBBVirtualCurveIntersectorRobust16HybridMB);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4Intersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4Intersector16HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vIntersector16HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vMBIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iMBIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4vMBIntersector16HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Triangle4iMBIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4iIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4vIntersector16HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4iIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4iMBIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4Quad4iMBIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4SubdivPatch1Intersector16);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4SubdivPatch1MBIntersector16);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4VirtualIntersector16Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4VirtualMBIntersector16Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4InstanceIntersector16Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4InstanceMBIntersector16Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4GridIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4GridMBIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH4GridIntersector16HybridPluecker);
+
+ // ==============
+
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4IntersectorStreamPacketFallback);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4IntersectorStreamMoeller);
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4IntersectorStreamMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4iIntersectorStreamMoeller);
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4vIntersectorStreamPluecker);
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4iIntersectorStreamPluecker);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4vIntersectorStreamMoeller);
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4vIntersectorStreamMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4iIntersectorStreamMoeller);
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4vIntersectorStreamPluecker);
+ DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Quad4iIntersectorStreamPluecker);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH4VirtualIntersectorStream);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH4InstanceIntersectorStream);
+
+ // SAH scene builders
+ private:
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Curve4vBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Curve4iBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4OBBCurve4iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Curve8iBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4OBBCurve8iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4vMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4QuantizedTriangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Quad4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Quad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Quad4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4QuantizedQuad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH4SubdivPatch1BuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4SubdivPatch1MBBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH4VirtualSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4VirtualMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH4InstanceSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4InstanceMBSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH4GridSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4GridMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ // spatial scene builder
+ private:
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4SceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Triangle4iSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4Quad4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+
+ // twolevel scene builders
+ private:
+ DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4MeshSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4vMeshSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool);
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh8_factory.cpp b/thirdparty/embree/kernels/bvh/bvh8_factory.cpp
new file mode 100644
index 0000000000..d4521af241
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh8_factory.cpp
@@ -0,0 +1,1165 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "../common/isa.h" // to define EMBREE_TARGET_SIMD8
+
+#if defined (EMBREE_TARGET_SIMD8)
+
+#include "bvh8_factory.h"
+#include "../bvh/bvh.h"
+
+#include "../geometry/curveNv.h"
+#include "../geometry/curveNi.h"
+#include "../geometry/curveNi_mb.h"
+#include "../geometry/linei.h"
+#include "../geometry/triangle.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/trianglev_mb.h"
+#include "../geometry/trianglei.h"
+#include "../geometry/quadv.h"
+#include "../geometry/quadi.h"
+#include "../geometry/subdivpatch1.h"
+#include "../geometry/object.h"
+#include "../geometry/instance.h"
+#include "../geometry/subgrid.h"
+#include "../common/accelinstance.h"
+
+namespace embree
+{
+ DECLARE_SYMBOL2(Accel::Collider,BVH8ColliderUserGeom);
+
+ DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8v,void);
+ DECLARE_ISA_FUNCTION(VirtualCurveIntersector*,VirtualCurveIntersector8iMB,void);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersector1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersector1MB);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersectorRobust1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersectorRobust1MB);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4Intersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vIntersector1Pluecker);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vIntersector1Woop);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vMBIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iMBIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vMBIntersector1Pluecker);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iMBIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4vIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4iIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4vIntersector1Pluecker);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4iIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4iMBIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8Quad4iMBIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,QBVH8Triangle4iIntersector1Pluecker);
+ DECLARE_SYMBOL2(Accel::Intersector1,QBVH8Triangle4Intersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,QBVH8Quad4iIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8VirtualIntersector1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8VirtualMBIntersector1);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8InstanceIntersector1);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8InstanceMBIntersector1);
+
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8GridIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8GridMBIntersector1Moeller);
+ DECLARE_SYMBOL2(Accel::Intersector1,BVH8GridIntersector1Pluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersector4Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersector4HybridMB);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersectorRobust4Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersectorRobust4HybridMB);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4Intersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4Intersector4HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vIntersector4HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vMBIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iMBIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vMBIntersector4HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iMBIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4iIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4iIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4iMBIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8Quad4iMBIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8VirtualIntersector4Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8VirtualMBIntersector4Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8InstanceIntersector4Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8InstanceMBIntersector4Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8GridIntersector4HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector4,BVH8GridIntersector4HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersector8Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersector8HybridMB);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersectorRobust8Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersectorRobust8HybridMB);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4Intersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4Intersector8HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vIntersector8HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vMBIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iMBIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vMBIntersector8HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iMBIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4iIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4iIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4iMBIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8Quad4iMBIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8VirtualIntersector8Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8VirtualMBIntersector8Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8InstanceIntersector8Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8InstanceMBIntersector8Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8GridIntersector8HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector8,BVH8GridIntersector8HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersector16Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersector16HybridMB);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersectorRobust16Hybrid);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersectorRobust16HybridMB);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4Intersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4Intersector16HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vIntersector16HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vMBIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iMBIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vMBIntersector16HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iMBIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4iIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridPluecker);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4iIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4iMBIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8Quad4iMBIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8VirtualIntersector16Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8VirtualMBIntersector16Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8InstanceIntersector16Chunk);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8InstanceMBIntersector16Chunk);
+
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8GridIntersector16HybridMoeller);
+ DECLARE_SYMBOL2(Accel::Intersector16,BVH8GridIntersector16HybridPluecker);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8IntersectorStreamPacketFallback);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoeller);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamMoeller);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4vIntersectorStreamPluecker);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamPluecker);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamMoeller);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamMoellerNoFilter);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4iIntersectorStreamMoeller);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamPluecker);
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Quad4iIntersectorStreamPluecker);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8VirtualIntersectorStream);
+
+ DECLARE_SYMBOL2(Accel::IntersectorN,BVH8InstanceIntersectorStream);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Curve8vBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8OBBCurve8iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8QuantizedTriangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8QuantizedTriangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8QuantizedQuad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMBSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4SceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8GridSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8GridMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4MeshSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4vMeshSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool);
+
+ BVH8Factory::BVH8Factory(int bfeatures, int ifeatures)
+ {
+ SELECT_SYMBOL_INIT_AVX(ifeatures,BVH8ColliderUserGeom);
+
+ selectBuilders(bfeatures);
+ selectIntersectors(ifeatures);
+ }
+
+ void BVH8Factory::selectBuilders(int features)
+ {
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH8Curve8vBuilder_OBB_New));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH8OBBCurve8iMBBuilder_OBB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4SceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4vSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4iSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4iMBSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4vMBSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedTriangle4iSceneBuilderSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedTriangle4SceneBuilderSAH));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8Quad4vSceneBuilderSAH));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8Quad4iSceneBuilderSAH));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8Quad4iMBSceneBuilderSAH));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedQuad4iSceneBuilderSAH));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX(features,BVH8VirtualSceneBuilderSAH));
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX(features,BVH8VirtualMBSceneBuilderSAH));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX(features,BVH8InstanceSceneBuilderSAH));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX(features,BVH8InstanceMBSceneBuilderSAH));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX(features,BVH8GridSceneBuilderSAH));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX(features,BVH8GridMBSceneBuilderSAH));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4SceneBuilderFastSpatialSAH));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4vSceneBuilderFastSpatialSAH));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8Quad4vSceneBuilderFastSpatialSAH));
+
+ IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelTriangle4MeshSAH));
+ IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelTriangle4vMeshSAH));
+ IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelTriangle4iMeshSAH));
+ IF_ENABLED_QUADS (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelQuadMeshSAH));
+ IF_ENABLED_USER (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelVirtualSAH));
+ IF_ENABLED_INSTANCE (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelInstanceSAH));
+ }
+
+ void BVH8Factory::selectIntersectors(int features)
+ {
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8v));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8iMB));
+
+ /* select intersectors1 */
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector1));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector1MB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust1));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust1MB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector1Moeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector1Moeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersector1Pluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector1Pluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersector1Woop));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector1Moeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector1Moeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector1Pluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector1Pluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector1Moeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector1Moeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector1Pluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector1Pluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iMBIntersector1Moeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iMBIntersector1Pluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,QBVH8Triangle4iIntersector1Pluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,QBVH8Triangle4Intersector1Moeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,QBVH8Quad4iIntersector1Pluecker));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualIntersector1));
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualMBIntersector1));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceIntersector1));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceMBIntersector1));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector1Moeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridMBIntersector1Moeller))
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector1Pluecker));
+
+#if defined (EMBREE_RAY_PACKETS)
+
+ /* select intersectors4 */
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector4Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector4HybridMB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust4Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust4HybridMB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector4HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector4HybridMoellerNoFilter));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector4HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersector4HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector4HybridPluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector4HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector4HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector4HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector4HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector4HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector4HybridMoellerNoFilter));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector4HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector4HybridPluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector4HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector4HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector4HybridPluecker));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualIntersector4Chunk));
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualMBIntersector4Chunk));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceIntersector4Chunk));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceMBIntersector4Chunk));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector4HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector4HybridPluecker));
+
+ /* select intersectors8 */
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector8Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector8HybridMB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust8Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust8HybridMB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector8HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector8HybridMoellerNoFilter));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector8HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersector8HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector8HybridPluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector8HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector8HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector8HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector8HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector8HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector8HybridMoellerNoFilter));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector8HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector8HybridPluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector8HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector8HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector8HybridPluecker));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualIntersector8Chunk));
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualMBIntersector8Chunk));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceIntersector8Chunk));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceMBIntersector8Chunk));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector8HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector8HybridPluecker));
+
+ /* select intersectors16 */
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH8OBBVirtualCurveIntersector16Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH8OBBVirtualCurveIntersector16HybridMB));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust16Hybrid));
+ IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust16HybridMB));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4Intersector16HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4Intersector16HybridMoellerNoFilter));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4iIntersector16HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4vIntersector16HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4iIntersector16HybridPluecker));
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4vMBIntersector16HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4iMBIntersector16HybridMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4vMBIntersector16HybridPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4iMBIntersector16HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4vIntersector16HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4vIntersector16HybridMoellerNoFilter));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4iIntersector16HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4vIntersector16HybridPluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4iIntersector16HybridPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4iMBIntersector16HybridMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4iMBIntersector16HybridPluecker));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512(features,BVH8VirtualIntersector16Chunk));
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512(features,BVH8VirtualMBIntersector16Chunk));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512(features,BVH8InstanceIntersector16Chunk));
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512(features,BVH8InstanceMBIntersector16Chunk));
+
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH8GridIntersector16HybridMoeller));
+ IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH8GridIntersector16HybridPluecker));
+
+ /* select stream intersectors */
+
+ SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8IntersectorStreamPacketFallback);
+
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4IntersectorStreamMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4IntersectorStreamMoellerNoFilter));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersectorStreamMoeller));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersectorStreamPluecker));
+ IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersectorStreamPluecker));
+
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersectorStreamMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersectorStreamMoellerNoFilter));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersectorStreamMoeller));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersectorStreamPluecker));
+ IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersectorStreamPluecker));
+
+ IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualIntersectorStream));
+
+ IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceIntersectorStream));
+
+#endif
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8OBBVirtualCurveIntersectors(BVH8* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.leafIntersector = leafIntersector;
+ intersectors.intersector1 = BVH8OBBVirtualCurveIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8OBBVirtualCurveIntersector4Hybrid();
+ intersectors.intersector8 = BVH8OBBVirtualCurveIntersector8Hybrid();
+ intersectors.intersector16 = BVH8OBBVirtualCurveIntersector16Hybrid();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.leafIntersector = leafIntersector;
+ intersectors.intersector1 = BVH8OBBVirtualCurveIntersectorRobust1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8OBBVirtualCurveIntersectorRobust4Hybrid();
+ intersectors.intersector8 = BVH8OBBVirtualCurveIntersectorRobust8Hybrid();
+ intersectors.intersector16 = BVH8OBBVirtualCurveIntersectorRobust16Hybrid();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ default: assert(false);
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8OBBVirtualCurveIntersectorsMB(BVH8* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.leafIntersector = leafIntersector;
+ intersectors.intersector1 = BVH8OBBVirtualCurveIntersector1MB();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8OBBVirtualCurveIntersector4HybridMB();
+ intersectors.intersector8 = BVH8OBBVirtualCurveIntersector8HybridMB();
+ intersectors.intersector16 = BVH8OBBVirtualCurveIntersector16HybridMB();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.leafIntersector = leafIntersector;
+ intersectors.intersector1 = BVH8OBBVirtualCurveIntersectorRobust1MB();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8OBBVirtualCurveIntersectorRobust4HybridMB();
+ intersectors.intersector8 = BVH8OBBVirtualCurveIntersectorRobust8HybridMB();
+ intersectors.intersector16 = BVH8OBBVirtualCurveIntersectorRobust16HybridMB();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ default: assert(false);
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8Triangle4Intersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ assert(ivariant == IntersectVariant::FAST);
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Triangle4Intersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4_filter = BVH8Triangle4Intersector4HybridMoeller();
+ intersectors.intersector4_nofilter = BVH8Triangle4Intersector4HybridMoellerNoFilter();
+ intersectors.intersector8_filter = BVH8Triangle4Intersector8HybridMoeller();
+ intersectors.intersector8_nofilter = BVH8Triangle4Intersector8HybridMoellerNoFilter();
+ intersectors.intersector16_filter = BVH8Triangle4Intersector16HybridMoeller();
+ intersectors.intersector16_nofilter = BVH8Triangle4Intersector16HybridMoellerNoFilter();
+ intersectors.intersectorN_filter = BVH8Triangle4IntersectorStreamMoeller();
+ intersectors.intersectorN_nofilter = BVH8Triangle4IntersectorStreamMoellerNoFilter();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8Triangle4vIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+#define ENABLE_WOOP_TEST 0
+#if ENABLE_WOOP_TEST == 0
+ //assert(ivariant == IntersectVariant::ROBUST);
+ intersectors.intersector1 = BVH8Triangle4vIntersector1Pluecker();
+#else
+ intersectors.intersector1 = BVH8Triangle4vIntersector1Woop();
+#endif
+
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Triangle4vIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH8Triangle4vIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH8Triangle4vIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH8Triangle4vIntersectorStreamPluecker();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8Triangle4iIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Triangle4iIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Triangle4iIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH8Triangle4iIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH8Triangle4iIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH8Triangle4iIntersectorStreamMoeller();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Triangle4iIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Triangle4iIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH8Triangle4iIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH8Triangle4iIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH8Triangle4iIntersectorStreamPluecker();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8Triangle4vMBIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Triangle4vMBIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Triangle4vMBIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH8Triangle4vMBIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH8Triangle4vMBIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Triangle4vMBIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Triangle4vMBIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH8Triangle4vMBIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH8Triangle4vMBIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8Triangle4iMBIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Triangle4iMBIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Triangle4iMBIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH8Triangle4iMBIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH8Triangle4iMBIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Triangle4iMBIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Triangle4iMBIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH8Triangle4iMBIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH8Triangle4iMBIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8Quad4vIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Quad4vIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4_filter = BVH8Quad4vIntersector4HybridMoeller();
+ intersectors.intersector4_nofilter = BVH8Quad4vIntersector4HybridMoellerNoFilter();
+ intersectors.intersector8_filter = BVH8Quad4vIntersector8HybridMoeller();
+ intersectors.intersector8_nofilter = BVH8Quad4vIntersector8HybridMoellerNoFilter();
+ intersectors.intersector16_filter = BVH8Quad4vIntersector16HybridMoeller();
+ intersectors.intersector16_nofilter = BVH8Quad4vIntersector16HybridMoellerNoFilter();
+ intersectors.intersectorN_filter = BVH8Quad4vIntersectorStreamMoeller();
+ intersectors.intersectorN_nofilter = BVH8Quad4vIntersectorStreamMoellerNoFilter();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Quad4vIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Quad4vIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH8Quad4vIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH8Quad4vIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH8Quad4vIntersectorStreamPluecker();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8Quad4iIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Quad4iIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Quad4iIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH8Quad4iIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH8Quad4iIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH8Quad4iIntersectorStreamMoeller();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Quad4iIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Quad4iIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH8Quad4iIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH8Quad4iIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH8Quad4iIntersectorStreamPluecker();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8Quad4iMBIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ switch (ivariant) {
+ case IntersectVariant::FAST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Quad4iMBIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Quad4iMBIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH8Quad4iMBIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH8Quad4iMBIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ case IntersectVariant::ROBUST:
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8Quad4iMBIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8Quad4iMBIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH8Quad4iMBIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH8Quad4iMBIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+ }
+ return Accel::Intersectors();
+ }
+
+ Accel::Intersectors BVH8Factory::QBVH8Triangle4iIntersectors(BVH8* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = QBVH8Triangle4iIntersector1Pluecker();
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::QBVH8Triangle4Intersectors(BVH8* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = QBVH8Triangle4Intersector1Moeller();
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::QBVH8Quad4iIntersectors(BVH8* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = QBVH8Quad4iIntersector1Pluecker();
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8UserGeometryIntersectors(BVH8* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8VirtualIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8VirtualIntersector4Chunk();
+ intersectors.intersector8 = BVH8VirtualIntersector8Chunk();
+ intersectors.intersector16 = BVH8VirtualIntersector16Chunk();
+ intersectors.intersectorN = BVH8VirtualIntersectorStream();
+#endif
+ intersectors.collider = BVH8ColliderUserGeom();
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8UserGeometryMBIntersectors(BVH8* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8VirtualMBIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8VirtualMBIntersector4Chunk();
+ intersectors.intersector8 = BVH8VirtualMBIntersector8Chunk();
+ intersectors.intersector16 = BVH8VirtualMBIntersector16Chunk();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8InstanceIntersectors(BVH8* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8InstanceIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8InstanceIntersector4Chunk();
+ intersectors.intersector8 = BVH8InstanceIntersector8Chunk();
+ intersectors.intersector16 = BVH8InstanceIntersector16Chunk();
+ intersectors.intersectorN = BVH8InstanceIntersectorStream();
+#endif
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8InstanceMBIntersectors(BVH8* bvh)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8InstanceMBIntersector1();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8InstanceMBIntersector4Chunk();
+ intersectors.intersector8 = BVH8InstanceMBIntersector8Chunk();
+ intersectors.intersector16 = BVH8InstanceMBIntersector16Chunk();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ return intersectors;
+ }
+
+ Accel* BVH8Factory::BVH8OBBVirtualCurve8v(Scene* scene, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Curve8v::type,scene);
+ Accel::Intersectors intersectors = BVH8OBBVirtualCurveIntersectors(accel,VirtualCurveIntersector8v(),ivariant);
+ Builder* builder = BVH8Curve8vBuilder_OBB_New(accel,scene,0);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8OBBVirtualCurve8iMB(Scene* scene, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Curve8iMB::type,scene);
+ Accel::Intersectors intersectors = BVH8OBBVirtualCurveIntersectorsMB(accel,VirtualCurveIntersector8iMB(),ivariant);
+ Builder* builder = BVH8OBBCurve8iMBBuilder_OBB(accel,scene,0);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Triangle4(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Triangle4::type,scene);
+ Accel::Intersectors intersectors= BVH8Triangle4Intersectors(accel,ivariant);
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8Triangle4SceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelTriangle4MeshSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: builder = BVH8Triangle4SceneBuilderFastSpatialSAH(accel,scene,0); break;
+ }
+ }
+ else if (scene->device->tri_builder == "sah" ) builder = BVH8Triangle4SceneBuilderSAH(accel,scene,0);
+ else if (scene->device->tri_builder == "sah_fast_spatial") builder = BVH8Triangle4SceneBuilderFastSpatialSAH(accel,scene,0);
+ else if (scene->device->tri_builder == "sah_presplit") builder = BVH8Triangle4SceneBuilderSAH(accel,scene,MODE_HIGH_QUALITY);
+ else if (scene->device->tri_builder == "dynamic" ) builder = BVH8BuilderTwoLevelTriangle4MeshSAH(accel,scene,false);
+ else if (scene->device->tri_builder == "morton" ) builder = BVH8BuilderTwoLevelTriangle4MeshSAH(accel,scene,true);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH8<Triangle4>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Triangle4v(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Triangle4v::type,scene);
+ Accel::Intersectors intersectors= BVH8Triangle4vIntersectors(accel,ivariant);
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8Triangle4vSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelTriangle4vMeshSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: builder = BVH8Triangle4vSceneBuilderFastSpatialSAH(accel,scene,0); break;
+ }
+ }
+ else if (scene->device->tri_builder == "sah_fast_spatial") builder = BVH8Triangle4SceneBuilderFastSpatialSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH8<Triangle4v>");
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Triangle4i(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Triangle4i::type,scene);
+ Accel::Intersectors intersectors = BVH8Triangle4iIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8Triangle4iSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelTriangle4iMeshSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: assert(false); break; // FIXME: implement
+ }
+ }
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder+" for BVH8<Triangle4i>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Triangle4iMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Triangle4i::type,scene);
+ Accel::Intersectors intersectors = BVH8Triangle4iMBIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder_mb == "default") { // FIXME: implement
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8Triangle4iMBSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->tri_builder_mb == "internal_time_splits") builder = BVH8Triangle4iMBSceneBuilderSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder_mb+" for BVH8<Triangle4iMB>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Triangle4vMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Triangle4vMB::type,scene);
+ Accel::Intersectors intersectors= BVH8Triangle4vMBIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->tri_builder_mb == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8Triangle4vMBSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->tri_builder_mb == "internal_time_splits") builder = BVH8Triangle4vMBSceneBuilderSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->tri_builder_mb+" for BVH8<Triangle4vMB>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8QuantizedTriangle4i(Scene* scene)
+ {
+ BVH8* accel = new BVH8(Triangle4i::type,scene);
+ Accel::Intersectors intersectors = QBVH8Triangle4iIntersectors(accel);
+ Builder* builder = BVH8QuantizedTriangle4iSceneBuilderSAH(accel,scene,0);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8QuantizedTriangle4(Scene* scene)
+ {
+ BVH8* accel = new BVH8(Triangle4::type,scene);
+ Accel::Intersectors intersectors = QBVH8Triangle4Intersectors(accel);
+ Builder* builder = BVH8QuantizedTriangle4SceneBuilderSAH(accel,scene,0);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Quad4v(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Quad4v::type,scene);
+ Accel::Intersectors intersectors = BVH8Quad4vIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->quad_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8Quad4vSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelQuadMeshSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: builder = BVH8Quad4vSceneBuilderFastSpatialSAH(accel,scene,0); break;
+ }
+ }
+ else if (scene->device->quad_builder == "dynamic" ) builder = BVH8BuilderTwoLevelQuadMeshSAH(accel,scene,false);
+ else if (scene->device->quad_builder == "morton" ) builder = BVH8BuilderTwoLevelQuadMeshSAH(accel,scene,true);
+ else if (scene->device->quad_builder == "sah_fast_spatial" ) builder = BVH8Quad4vSceneBuilderFastSpatialSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for BVH8<Quad4v>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Quad4i(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Quad4i::type,scene);
+ Accel::Intersectors intersectors = BVH8Quad4iIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->quad_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8Quad4iSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
+ case BuildVariant::HIGH_QUALITY: assert(false); break; // FIXME: implement
+ }
+ }
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for BVH8<Quad4i>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Quad4iMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(Quad4i::type,scene);
+ Accel::Intersectors intersectors = BVH8Quad4iMBIntersectors(accel,ivariant);
+
+ Builder* builder = nullptr;
+ if (scene->device->quad_builder_mb == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8Quad4iMBSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : assert(false); break; // FIXME: implement
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder_mb+" for BVH8<Quad4i>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8QuantizedQuad4i(Scene* scene)
+ {
+ BVH8* accel = new BVH8(Quad4i::type,scene);
+ Accel::Intersectors intersectors = QBVH8Quad4iIntersectors(accel);
+ Builder* builder = nullptr;
+ if (scene->device->quad_builder == "default" ) builder = BVH8QuantizedQuad4iSceneBuilderSAH(accel,scene,0);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->quad_builder+" for QBVH8<Quad4i>");
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8UserGeometry(Scene* scene, BuildVariant bvariant)
+ {
+ BVH8* accel = new BVH8(Object::type,scene);
+ Accel::Intersectors intersectors = BVH8UserGeometryIntersectors(accel);
+
+ Builder* builder = nullptr;
+ if (scene->device->object_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8VirtualSceneBuilderSAH(accel,scene,0); break;
+ case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelVirtualSAH(accel,scene,false); break;
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->object_builder == "sah") builder = BVH8VirtualSceneBuilderSAH(accel,scene,0);
+ else if (scene->device->object_builder == "dynamic") builder = BVH8BuilderTwoLevelVirtualSAH(accel,scene,false);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH8<Object>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8UserGeometryMB(Scene* scene)
+ {
+ BVH8* accel = new BVH8(Object::type,scene);
+ Accel::Intersectors intersectors = BVH8UserGeometryMBIntersectors(accel);
+ Builder* builder = BVH8VirtualMBSceneBuilderSAH(accel,scene,0);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8Instance(Scene* scene, bool isExpensive, BuildVariant bvariant)
+ {
+ BVH8* accel = new BVH8(InstancePrimitive::type,scene);
+ Accel::Intersectors intersectors = BVH8InstanceIntersectors(accel);
+ auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE;
+ // Builder* builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype);
+
+ Builder* builder = nullptr;
+ if (scene->device->object_builder == "default") {
+ switch (bvariant) {
+ case BuildVariant::STATIC : builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype);; break;
+ case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelInstanceSAH(accel,scene,gtype,false); break;
+ case BuildVariant::HIGH_QUALITY: assert(false); break;
+ }
+ }
+ else if (scene->device->object_builder == "sah") builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype);
+ else if (scene->device->object_builder == "dynamic") builder = BVH8BuilderTwoLevelInstanceSAH(accel,scene,gtype,false);
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH8<Object>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8InstanceMB(Scene* scene, bool isExpensive)
+ {
+ BVH8* accel = new BVH8(InstancePrimitive::type,scene);
+ Accel::Intersectors intersectors = BVH8InstanceMBIntersectors(accel);
+ auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE;
+ Builder* builder = BVH8InstanceMBSceneBuilderSAH(accel,scene,gtype);
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8GridIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ if (ivariant == IntersectVariant::FAST)
+ {
+ intersectors.intersector1 = BVH8GridIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8GridIntersector4HybridMoeller();
+ intersectors.intersector8 = BVH8GridIntersector8HybridMoeller();
+ intersectors.intersector16 = BVH8GridIntersector16HybridMoeller();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ }
+ else /* if (ivariant == IntersectVariant::ROBUST) */
+ {
+ intersectors.intersector1 = BVH8GridIntersector1Pluecker();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = BVH8GridIntersector4HybridPluecker();
+ intersectors.intersector8 = BVH8GridIntersector8HybridPluecker();
+ intersectors.intersector16 = BVH8GridIntersector16HybridPluecker();
+ intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
+#endif
+ }
+ return intersectors;
+ }
+
+ Accel::Intersectors BVH8Factory::BVH8GridMBIntersectors(BVH8* bvh, IntersectVariant ivariant)
+ {
+ Accel::Intersectors intersectors;
+ intersectors.ptr = bvh;
+ intersectors.intersector1 = BVH8GridMBIntersector1Moeller();
+#if defined (EMBREE_RAY_PACKETS)
+ intersectors.intersector4 = nullptr;
+ intersectors.intersector8 = nullptr;
+ intersectors.intersector16 = nullptr;
+ intersectors.intersectorN = nullptr;
+#endif
+ return intersectors;
+ }
+
+ Accel* BVH8Factory::BVH8Grid(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(SubGridQBVH8::type,scene);
+ Accel::Intersectors intersectors = BVH8GridIntersectors(accel,ivariant);
+ Builder* builder = nullptr;
+ if (scene->device->grid_builder == "default") {
+ builder = BVH8GridSceneBuilderSAH(accel,scene,0);
+ }
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH4<GridMesh>");
+
+ return new AccelInstance(accel,builder,intersectors);
+ }
+
+ Accel* BVH8Factory::BVH8GridMB(Scene* scene, BuildVariant bvariant, IntersectVariant ivariant)
+ {
+ BVH8* accel = new BVH8(SubGridQBVH8::type,scene);
+ Accel::Intersectors intersectors = BVH8GridMBIntersectors(accel,ivariant);
+ Builder* builder = nullptr;
+ if (scene->device->grid_builder_mb == "default") {
+ builder = BVH8GridMBSceneBuilderSAH(accel,scene,0);
+ }
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH8MB<GridMesh>");
+ return new AccelInstance(accel,builder,intersectors);
+ }
+}
+
+#endif
diff --git a/thirdparty/embree/kernels/bvh/bvh8_factory.h b/thirdparty/embree/kernels/bvh/bvh8_factory.h
new file mode 100644
index 0000000000..198d6f1df0
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh8_factory.h
@@ -0,0 +1,280 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_factory.h"
+
+namespace embree
+{
+ /*! BVH8 instantiations */
+ class BVH8Factory : public BVHFactory
+ {
+ public:
+ BVH8Factory(int bfeatures, int ifeatures);
+
+ public:
+ Accel* BVH8OBBVirtualCurve8v(Scene* scene, IntersectVariant ivariant);
+ Accel* BVH8OBBVirtualCurve8iMB(Scene* scene, IntersectVariant ivariant);
+ DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8v);
+ DEFINE_SYMBOL2(VirtualCurveIntersector*,VirtualCurveIntersector8iMB);
+
+ Accel* BVH8Triangle4 (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH8Triangle4v (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH8Triangle4i (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH8Triangle4vMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH8Triangle4iMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+
+ Accel* BVH8Quad4v (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH8Quad4i (Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH8Quad4iMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+
+ Accel* BVH8QuantizedTriangle4i(Scene* scene);
+ Accel* BVH8QuantizedTriangle4(Scene* scene);
+ Accel* BVH8QuantizedQuad4i(Scene* scene);
+
+ Accel* BVH8UserGeometry(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC);
+ Accel* BVH8UserGeometryMB(Scene* scene);
+
+ Accel* BVH8Instance(Scene* scene, bool isExpensive, BuildVariant bvariant = BuildVariant::STATIC);
+ Accel* BVH8InstanceMB(Scene* scene, bool isExpensive);
+
+ Accel* BVH8Grid(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+ Accel* BVH8GridMB(Scene* scene, BuildVariant bvariant = BuildVariant::STATIC, IntersectVariant ivariant = IntersectVariant::FAST);
+
+ private:
+ void selectBuilders(int features);
+ void selectIntersectors(int features);
+
+ private:
+ Accel::Intersectors BVH8OBBVirtualCurveIntersectors(BVH8* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant);
+ Accel::Intersectors BVH8OBBVirtualCurveIntersectorsMB(BVH8* bvh, VirtualCurveIntersector* leafIntersector, IntersectVariant ivariant);
+
+ Accel::Intersectors BVH8Triangle4Intersectors(BVH8* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH8Triangle4vIntersectors(BVH8* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH8Triangle4iIntersectors(BVH8* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH8Triangle4iMBIntersectors(BVH8* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH8Triangle4vMBIntersectors(BVH8* bvh, IntersectVariant ivariant);
+
+ Accel::Intersectors BVH8Quad4vIntersectors(BVH8* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH8Quad4iIntersectors(BVH8* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH8Quad4iMBIntersectors(BVH8* bvh, IntersectVariant ivariant);
+
+ Accel::Intersectors QBVH8Triangle4iIntersectors(BVH8* bvh);
+ Accel::Intersectors QBVH8Triangle4Intersectors(BVH8* bvh);
+ Accel::Intersectors QBVH8Quad4iIntersectors(BVH8* bvh);
+
+ Accel::Intersectors BVH8UserGeometryIntersectors(BVH8* bvh);
+ Accel::Intersectors BVH8UserGeometryMBIntersectors(BVH8* bvh);
+
+ Accel::Intersectors BVH8InstanceIntersectors(BVH8* bvh);
+ Accel::Intersectors BVH8InstanceMBIntersectors(BVH8* bvh);
+
+ Accel::Intersectors BVH8GridIntersectors(BVH8* bvh, IntersectVariant ivariant);
+ Accel::Intersectors BVH8GridMBIntersectors(BVH8* bvh, IntersectVariant ivariant);
+
+ private:
+ DEFINE_SYMBOL2(Accel::Collider,BVH8ColliderUserGeom);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersector1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersector1MB);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersectorRobust1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8OBBVirtualCurveIntersectorRobust1MB);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4Intersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vIntersector1Pluecker);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vMBIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iMBIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vMBIntersector1Pluecker);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4iMBIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Triangle4vIntersector1Woop);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4vIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4iIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4vIntersector1Pluecker);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4iIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4iMBIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8Quad4iMBIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,QBVH8Triangle4iIntersector1Pluecker);
+ DEFINE_SYMBOL2(Accel::Intersector1,QBVH8Triangle4Intersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,QBVH8Quad4iIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8VirtualIntersector1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8VirtualMBIntersector1);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8InstanceIntersector1);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8InstanceMBIntersector1);
+
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8GridIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8GridMBIntersector1Moeller);
+ DEFINE_SYMBOL2(Accel::Intersector1,BVH8GridIntersector1Pluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersector4Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersector4HybridMB);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersectorRobust4Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8OBBVirtualCurveIntersectorRobust4HybridMB);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4Intersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4Intersector4HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vIntersector4HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vMBIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iMBIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4vMBIntersector4HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Triangle4iMBIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4iIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4vIntersector4HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4iIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4iMBIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8Quad4iMBIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8VirtualIntersector4Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8VirtualMBIntersector4Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8InstanceIntersector4Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8InstanceMBIntersector4Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8GridIntersector4HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector4,BVH8GridIntersector4HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersector8Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersector8HybridMB);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersectorRobust8Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8OBBVirtualCurveIntersectorRobust8HybridMB);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4Intersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4Intersector8HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vIntersector8HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vMBIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iMBIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4vMBIntersector8HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Triangle4iMBIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4iIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4vIntersector8HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4iIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4iMBIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8Quad4iMBIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8VirtualIntersector8Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8VirtualMBIntersector8Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8InstanceIntersector8Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8InstanceMBIntersector8Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8GridIntersector8HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector8,BVH8GridIntersector8HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersector16Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersector16HybridMB);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersectorRobust16Hybrid);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8OBBVirtualCurveIntersectorRobust16HybridMB);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4Intersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4Intersector16HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vIntersector16HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vMBIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iMBIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4vMBIntersector16HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Triangle4iMBIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4iIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4vIntersector16HybridPluecker);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4iIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4iMBIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8Quad4iMBIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8VirtualIntersector16Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8VirtualMBIntersector16Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8InstanceIntersector16Chunk);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8InstanceMBIntersector16Chunk);
+
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8GridIntersector16HybridMoeller);
+ DEFINE_SYMBOL2(Accel::Intersector16,BVH8GridIntersector16HybridPluecker);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8IntersectorStreamPacketFallback);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoeller);
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamMoeller);
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4vIntersectorStreamPluecker);
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamPluecker);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamMoeller);
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamMoellerNoFilter);
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4iIntersectorStreamMoeller);
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4vIntersectorStreamPluecker);
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Quad4iIntersectorStreamPluecker);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8VirtualIntersectorStream);
+
+ DEFINE_SYMBOL2(Accel::IntersectorN,BVH8InstanceIntersectorStream);
+
+ // SAH scene builders
+ private:
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Curve8vBuilder_OBB_New,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8OBBCurve8iMBBuilder_OBB,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4vMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8QuantizedTriangle4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8QuantizedTriangle4SceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Quad4vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Quad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Quad4iMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8QuantizedQuad4iSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH8VirtualSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8VirtualMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH8InstanceSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8InstanceMBSceneBuilderSAH,void* COMMA Scene* COMMA Geometry::GTypeMask);
+
+ DEFINE_ISA_FUNCTION(Builder*,BVH8GridSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8GridMBSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
+
+ // SAH spatial scene builders
+ private:
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4SceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Triangle4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8Quad4vSceneBuilderFastSpatialSAH,void* COMMA Scene* COMMA size_t);
+
+ // twolevel scene builders
+ private:
+ DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4MeshSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4vMeshSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool);
+ DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool);
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder.cpp b/thirdparty/embree/kernels/bvh/bvh_builder.cpp
new file mode 100644
index 0000000000..161d01bb5c
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder.cpp
@@ -0,0 +1,60 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh_builder.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N>
+ typename BVHN<N>::NodeRef BVHNBuilderVirtual<N>::BVHNBuilderV::build(FastAllocator* allocator, BuildProgressMonitor& progressFunc, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings)
+ {
+ auto createLeafFunc = [&] (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) -> NodeRef {
+ return createLeaf(prims,set,alloc);
+ };
+
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxBuildDepthLeaf;
+ return BVHBuilderBinnedSAH::build<NodeRef>
+ (FastAllocator::Create(allocator),typename BVH::AABBNode::Create2(),typename BVH::AABBNode::Set3(allocator,prims),createLeafFunc,progressFunc,prims,pinfo,settings);
+ }
+
+
+ template<int N>
+ typename BVHN<N>::NodeRef BVHNBuilderQuantizedVirtual<N>::BVHNBuilderV::build(FastAllocator* allocator, BuildProgressMonitor& progressFunc, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings)
+ {
+ auto createLeafFunc = [&] (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) -> NodeRef {
+ return createLeaf(prims,set,alloc);
+ };
+
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxBuildDepthLeaf;
+ return BVHBuilderBinnedSAH::build<NodeRef>
+ (FastAllocator::Create(allocator),typename BVH::QuantizedNode::Create2(),typename BVH::QuantizedNode::Set2(),createLeafFunc,progressFunc,prims,pinfo,settings);
+ }
+
+ template<int N>
+ typename BVHN<N>::NodeRecordMB BVHNBuilderMblurVirtual<N>::BVHNBuilderV::build(FastAllocator* allocator, BuildProgressMonitor& progressFunc, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings, const BBox1f& timeRange)
+ {
+ auto createLeafFunc = [&] (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) -> NodeRecordMB {
+ return createLeaf(prims,set,alloc);
+ };
+
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxBuildDepthLeaf;
+ return BVHBuilderBinnedSAH::build<NodeRecordMB>
+ (FastAllocator::Create(allocator),typename BVH::AABBNodeMB::Create(),typename BVH::AABBNodeMB::SetTimeRange(timeRange),createLeafFunc,progressFunc,prims,pinfo,settings);
+ }
+
+ template struct BVHNBuilderVirtual<4>;
+ template struct BVHNBuilderQuantizedVirtual<4>;
+ template struct BVHNBuilderMblurVirtual<4>;
+
+#if defined(__AVX__)
+ template struct BVHNBuilderVirtual<8>;
+ template struct BVHNBuilderQuantizedVirtual<8>;
+ template struct BVHNBuilderMblurVirtual<8>;
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder.h b/thirdparty/embree/kernels/bvh/bvh_builder.h
new file mode 100644
index 0000000000..e35d052a62
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder.h
@@ -0,0 +1,115 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh.h"
+#include "../builders/bvh_builder_sah.h"
+#include "../builders/bvh_builder_msmblur.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+ template<int N>
+ struct BVHNBuilderVirtual
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef FastAllocator::CachedAllocator Allocator;
+
+ struct BVHNBuilderV {
+ NodeRef build(FastAllocator* allocator, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings);
+ virtual NodeRef createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) = 0;
+ };
+
+ template<typename CreateLeafFunc>
+ struct BVHNBuilderT : public BVHNBuilderV
+ {
+ BVHNBuilderT (CreateLeafFunc createLeafFunc)
+ : createLeafFunc(createLeafFunc) {}
+
+ NodeRef createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) {
+ return createLeafFunc(prims,set,alloc);
+ }
+
+ private:
+ CreateLeafFunc createLeafFunc;
+ };
+
+ template<typename CreateLeafFunc>
+ static NodeRef build(FastAllocator* allocator, CreateLeafFunc createLeaf, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings) {
+ return BVHNBuilderT<CreateLeafFunc>(createLeaf).build(allocator,progress,prims,pinfo,settings);
+ }
+ };
+
+ template<int N>
+ struct BVHNBuilderQuantizedVirtual
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef FastAllocator::CachedAllocator Allocator;
+
+ struct BVHNBuilderV {
+ NodeRef build(FastAllocator* allocator, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings);
+ virtual NodeRef createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) = 0;
+ };
+
+ template<typename CreateLeafFunc>
+ struct BVHNBuilderT : public BVHNBuilderV
+ {
+ BVHNBuilderT (CreateLeafFunc createLeafFunc)
+ : createLeafFunc(createLeafFunc) {}
+
+ NodeRef createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) {
+ return createLeafFunc(prims,set,alloc);
+ }
+
+ private:
+ CreateLeafFunc createLeafFunc;
+ };
+
+ template<typename CreateLeafFunc>
+ static NodeRef build(FastAllocator* allocator, CreateLeafFunc createLeaf, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings) {
+ return BVHNBuilderT<CreateLeafFunc>(createLeaf).build(allocator,progress,prims,pinfo,settings);
+ }
+ };
+
+ template<int N>
+ struct BVHNBuilderMblurVirtual
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::AABBNodeMB AABBNodeMB;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecordMB NodeRecordMB;
+ typedef FastAllocator::CachedAllocator Allocator;
+
+ struct BVHNBuilderV {
+ NodeRecordMB build(FastAllocator* allocator, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings, const BBox1f& timeRange);
+ virtual NodeRecordMB createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) = 0;
+ };
+
+ template<typename CreateLeafFunc>
+ struct BVHNBuilderT : public BVHNBuilderV
+ {
+ BVHNBuilderT (CreateLeafFunc createLeafFunc)
+ : createLeafFunc(createLeafFunc) {}
+
+ NodeRecordMB createLeaf (const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) {
+ return createLeafFunc(prims,set,alloc);
+ }
+
+ private:
+ CreateLeafFunc createLeafFunc;
+ };
+
+ template<typename CreateLeafFunc>
+ static NodeRecordMB build(FastAllocator* allocator, CreateLeafFunc createLeaf, BuildProgressMonitor& progress, PrimRef* prims, const PrimInfo& pinfo, GeneralBVHBuilder::Settings settings, const BBox1f& timeRange) {
+ return BVHNBuilderT<CreateLeafFunc>(createLeaf).build(allocator,progress,prims,pinfo,settings,timeRange);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder_morton.cpp b/thirdparty/embree/kernels/bvh/bvh_builder_morton.cpp
new file mode 100644
index 0000000000..4a4d8d71df
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder_morton.cpp
@@ -0,0 +1,531 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh.h"
+#include "bvh_statistics.h"
+#include "bvh_rotate.h"
+#include "../common/profile.h"
+#include "../../common/algorithms/parallel_prefix_sum.h"
+
+#include "../builders/primrefgen.h"
+#include "../builders/bvh_builder_morton.h"
+
+#include "../geometry/triangle.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/trianglei.h"
+#include "../geometry/quadv.h"
+#include "../geometry/quadi.h"
+#include "../geometry/object.h"
+#include "../geometry/instance.h"
+
+#if defined(__64BIT__)
+# define ROTATE_TREE 1 // specifies number of tree rotation rounds to perform
+#else
+# define ROTATE_TREE 0 // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues
+#endif
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N>
+ struct SetBVHNBounds
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecord NodeRecord;
+ typedef typename BVH::AABBNode AABBNode;
+
+ BVH* bvh;
+ __forceinline SetBVHNBounds (BVH* bvh) : bvh(bvh) {}
+
+ __forceinline NodeRecord operator() (NodeRef ref, const NodeRecord* children, size_t num)
+ {
+ AABBNode* node = ref.getAABBNode();
+
+ BBox3fa res = empty;
+ for (size_t i=0; i<num; i++) {
+ const BBox3fa b = children[i].bounds;
+ res.extend(b);
+ node->setRef(i,children[i].ref);
+ node->setBounds(i,b);
+ }
+
+ BBox3fx result = (BBox3fx&)res;
+#if ROTATE_TREE
+ if (N == 4)
+ {
+ size_t n = 0;
+ for (size_t i=0; i<num; i++)
+ n += children[i].bounds.lower.a;
+
+ if (n >= 4096) {
+ for (size_t i=0; i<num; i++) {
+ if (children[i].bounds.lower.a < 4096) {
+ for (int j=0; j<ROTATE_TREE; j++)
+ BVHNRotate<N>::rotate(node->child(i));
+ node->child(i).setBarrier();
+ }
+ }
+ }
+ result.lower.a = unsigned(n);
+ }
+#endif
+
+ return NodeRecord(ref,result);
+ }
+ };
+
+ template<int N, typename Primitive>
+ struct CreateMortonLeaf;
+
+ template<int N>
+ struct CreateMortonLeaf<N,Triangle4>
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecord NodeRecord;
+
+ __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
+ : mesh(mesh), morton(morton), geomID_(geomID) {}
+
+ __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
+ {
+ vfloat4 lower(pos_inf);
+ vfloat4 upper(neg_inf);
+ size_t items = current.size();
+ size_t start = current.begin();
+ assert(items<=4);
+
+ /* allocate leaf node */
+ Triangle4* accel = (Triangle4*) alloc.malloc1(sizeof(Triangle4),BVH::byteAlignment);
+ NodeRef ref = BVH::encodeLeaf((char*)accel,1);
+ vuint4 vgeomID = -1, vprimID = -1;
+ Vec3vf4 v0 = zero, v1 = zero, v2 = zero;
+ const TriangleMesh* __restrict__ const mesh = this->mesh;
+
+ for (size_t i=0; i<items; i++)
+ {
+ const unsigned int primID = morton[start+i].index;
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ const Vec3fa& p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa& p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa& p2 = mesh->vertex(tri.v[2]);
+ lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
+ upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
+ vgeomID [i] = geomID_;
+ vprimID [i] = primID;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ }
+
+ Triangle4::store_nt(accel,Triangle4(v0,v1,v2,vgeomID,vprimID));
+ BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
+#if ROTATE_TREE
+ if (N == 4)
+ box_o.lower.a = unsigned(current.size());
+#endif
+ return NodeRecord(ref,box_o);
+ }
+
+ private:
+ TriangleMesh* mesh;
+ BVHBuilderMorton::BuildPrim* morton;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ };
+
+ template<int N>
+ struct CreateMortonLeaf<N,Triangle4v>
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecord NodeRecord;
+
+ __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
+ : mesh(mesh), morton(morton), geomID_(geomID) {}
+
+ __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
+ {
+ vfloat4 lower(pos_inf);
+ vfloat4 upper(neg_inf);
+ size_t items = current.size();
+ size_t start = current.begin();
+ assert(items<=4);
+
+ /* allocate leaf node */
+ Triangle4v* accel = (Triangle4v*) alloc.malloc1(sizeof(Triangle4v),BVH::byteAlignment);
+ NodeRef ref = BVH::encodeLeaf((char*)accel,1);
+ vuint4 vgeomID = -1, vprimID = -1;
+ Vec3vf4 v0 = zero, v1 = zero, v2 = zero;
+ const TriangleMesh* __restrict__ mesh = this->mesh;
+
+ for (size_t i=0; i<items; i++)
+ {
+ const unsigned int primID = morton[start+i].index;
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ const Vec3fa& p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa& p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa& p2 = mesh->vertex(tri.v[2]);
+ lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
+ upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
+ vgeomID [i] = geomID_;
+ vprimID [i] = primID;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ }
+ Triangle4v::store_nt(accel,Triangle4v(v0,v1,v2,vgeomID,vprimID));
+ BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
+#if ROTATE_TREE
+ if (N == 4)
+ box_o.lower.a = current.size();
+#endif
+ return NodeRecord(ref,box_o);
+ }
+ private:
+ TriangleMesh* mesh;
+ BVHBuilderMorton::BuildPrim* morton;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ };
+
+ template<int N>
+ struct CreateMortonLeaf<N,Triangle4i>
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecord NodeRecord;
+
+ __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
+ : mesh(mesh), morton(morton), geomID_(geomID) {}
+
+ __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
+ {
+ vfloat4 lower(pos_inf);
+ vfloat4 upper(neg_inf);
+ size_t items = current.size();
+ size_t start = current.begin();
+ assert(items<=4);
+
+ /* allocate leaf node */
+ Triangle4i* accel = (Triangle4i*) alloc.malloc1(sizeof(Triangle4i),BVH::byteAlignment);
+ NodeRef ref = BVH::encodeLeaf((char*)accel,1);
+
+ vuint4 v0 = zero, v1 = zero, v2 = zero;
+ vuint4 vgeomID = -1, vprimID = -1;
+ const TriangleMesh* __restrict__ const mesh = this->mesh;
+
+ for (size_t i=0; i<items; i++)
+ {
+ const unsigned int primID = morton[start+i].index;
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ const Vec3fa& p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa& p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa& p2 = mesh->vertex(tri.v[2]);
+ lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
+ upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
+ vgeomID[i] = geomID_;
+ vprimID[i] = primID;
+ unsigned int int_stride = mesh->vertices0.getStride()/4;
+ v0[i] = tri.v[0] * int_stride;
+ v1[i] = tri.v[1] * int_stride;
+ v2[i] = tri.v[2] * int_stride;
+ }
+
+ for (size_t i=items; i<4; i++)
+ {
+ vgeomID[i] = vgeomID[0];
+ vprimID[i] = -1;
+ v0[i] = 0;
+ v1[i] = 0;
+ v2[i] = 0;
+ }
+ Triangle4i::store_nt(accel,Triangle4i(v0,v1,v2,vgeomID,vprimID));
+ BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
+#if ROTATE_TREE
+ if (N == 4)
+ box_o.lower.a = current.size();
+#endif
+ return NodeRecord(ref,box_o);
+ }
+ private:
+ TriangleMesh* mesh;
+ BVHBuilderMorton::BuildPrim* morton;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ };
+
+ template<int N>
+ struct CreateMortonLeaf<N,Quad4v>
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecord NodeRecord;
+
+ __forceinline CreateMortonLeaf (QuadMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
+ : mesh(mesh), morton(morton), geomID_(geomID) {}
+
+ __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
+ {
+ vfloat4 lower(pos_inf);
+ vfloat4 upper(neg_inf);
+ size_t items = current.size();
+ size_t start = current.begin();
+ assert(items<=4);
+
+ /* allocate leaf node */
+ Quad4v* accel = (Quad4v*) alloc.malloc1(sizeof(Quad4v),BVH::byteAlignment);
+ NodeRef ref = BVH::encodeLeaf((char*)accel,1);
+
+ vuint4 vgeomID = -1, vprimID = -1;
+ Vec3vf4 v0 = zero, v1 = zero, v2 = zero, v3 = zero;
+ const QuadMesh* __restrict__ mesh = this->mesh;
+
+ for (size_t i=0; i<items; i++)
+ {
+ const unsigned int primID = morton[start+i].index;
+ const QuadMesh::Quad& tri = mesh->quad(primID);
+ const Vec3fa& p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa& p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa& p2 = mesh->vertex(tri.v[2]);
+ const Vec3fa& p3 = mesh->vertex(tri.v[3]);
+ lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2,(vfloat4)p3);
+ upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2,(vfloat4)p3);
+ vgeomID [i] = geomID_;
+ vprimID [i] = primID;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ v3.x[i] = p3.x; v3.y[i] = p3.y; v3.z[i] = p3.z;
+ }
+ Quad4v::store_nt(accel,Quad4v(v0,v1,v2,v3,vgeomID,vprimID));
+ BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
+#if ROTATE_TREE
+ if (N == 4)
+ box_o.lower.a = current.size();
+#endif
+ return NodeRecord(ref,box_o);
+ }
+ private:
+ QuadMesh* mesh;
+ BVHBuilderMorton::BuildPrim* morton;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ };
+
+ template<int N>
+ struct CreateMortonLeaf<N,Object>
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecord NodeRecord;
+
+ __forceinline CreateMortonLeaf (UserGeometry* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
+ : mesh(mesh), morton(morton), geomID_(geomID) {}
+
+ __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
+ {
+ vfloat4 lower(pos_inf);
+ vfloat4 upper(neg_inf);
+ size_t items = current.size();
+ size_t start = current.begin();
+
+ /* allocate leaf node */
+ Object* accel = (Object*) alloc.malloc1(items*sizeof(Object),BVH::byteAlignment);
+ NodeRef ref = BVH::encodeLeaf((char*)accel,items);
+ const UserGeometry* mesh = this->mesh;
+
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<items; i++)
+ {
+ const unsigned int index = morton[start+i].index;
+ const unsigned int primID = index;
+ bounds.extend(mesh->bounds(primID));
+ new (&accel[i]) Object(geomID_,primID);
+ }
+
+ BBox3fx box_o = (BBox3fx&)bounds;
+#if ROTATE_TREE
+ if (N == 4)
+ box_o.lower.a = current.size();
+#endif
+ return NodeRecord(ref,box_o);
+ }
+ private:
+ UserGeometry* mesh;
+ BVHBuilderMorton::BuildPrim* morton;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ };
+
+ template<int N>
+ struct CreateMortonLeaf<N,InstancePrimitive>
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecord NodeRecord;
+
+ __forceinline CreateMortonLeaf (Instance* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
+ : mesh(mesh), morton(morton), geomID_(geomID) {}
+
+ __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
+ {
+ vfloat4 lower(pos_inf);
+ vfloat4 upper(neg_inf);
+ size_t items = current.size();
+ size_t start = current.begin();
+ assert(items <= 1);
+
+ /* allocate leaf node */
+ InstancePrimitive* accel = (InstancePrimitive*) alloc.malloc1(items*sizeof(InstancePrimitive),BVH::byteAlignment);
+ NodeRef ref = BVH::encodeLeaf((char*)accel,items);
+ const Instance* instance = this->mesh;
+
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<items; i++)
+ {
+ const unsigned int primID = morton[start+i].index;
+ bounds.extend(instance->bounds(primID));
+ new (&accel[i]) InstancePrimitive(instance, geomID_);
+ }
+
+ BBox3fx box_o = (BBox3fx&)bounds;
+#if ROTATE_TREE
+ if (N == 4)
+ box_o.lower.a = current.size();
+#endif
+ return NodeRecord(ref,box_o);
+ }
+ private:
+ Instance* mesh;
+ BVHBuilderMorton::BuildPrim* morton;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ };
+
+ template<typename Mesh>
+ struct CalculateMeshBounds
+ {
+ __forceinline CalculateMeshBounds (Mesh* mesh)
+ : mesh(mesh) {}
+
+ __forceinline const BBox3fa operator() (const BVHBuilderMorton::BuildPrim& morton) {
+ return mesh->bounds(morton.index);
+ }
+
+ private:
+ Mesh* mesh;
+ };
+
+ template<int N, typename Mesh, typename Primitive>
+ class BVHNMeshBuilderMorton : public Builder
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::AABBNode AABBNode;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecord NodeRecord;
+
+ public:
+
+ BVHNMeshBuilderMorton (BVH* bvh, Mesh* mesh, unsigned int geomID, const size_t minLeafSize, const size_t maxLeafSize, const size_t singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD)
+ : bvh(bvh), mesh(mesh), morton(bvh->device,0), settings(N,BVH::maxBuildDepth,minLeafSize,min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks),singleThreadThreshold), geomID_(geomID) {}
+
+ /* build function */
+ void build()
+ {
+ /* we reset the allocator when the mesh size changed */
+ if (mesh->numPrimitives != numPreviousPrimitives) {
+ bvh->alloc.clear();
+ morton.clear();
+ }
+ size_t numPrimitives = mesh->size();
+ numPreviousPrimitives = numPrimitives;
+
+ /* skip build for empty scene */
+ if (numPrimitives == 0) {
+ bvh->set(BVH::emptyNode,empty,0);
+ return;
+ }
+
+ /* preallocate arrays */
+ morton.resize(numPrimitives);
+ size_t bytesEstimated = numPrimitives*sizeof(AABBNode)/(4*N) + size_t(1.2f*Primitive::blocks(numPrimitives)*sizeof(Primitive));
+ size_t bytesMortonCodes = numPrimitives*sizeof(BVHBuilderMorton::BuildPrim);
+ bytesEstimated = max(bytesEstimated,bytesMortonCodes); // the first allocation block is reused to sort the morton codes
+ bvh->alloc.init(bytesMortonCodes,bytesMortonCodes,bytesEstimated);
+
+ /* create morton code array */
+ BVHBuilderMorton::BuildPrim* dest = (BVHBuilderMorton::BuildPrim*) bvh->alloc.specialAlloc(bytesMortonCodes);
+ size_t numPrimitivesGen = createMortonCodeArray<Mesh>(mesh,morton,bvh->scene->progressInterface);
+
+ /* create BVH */
+ SetBVHNBounds<N> setBounds(bvh);
+ CreateMortonLeaf<N,Primitive> createLeaf(mesh,geomID_,morton.data());
+ CalculateMeshBounds<Mesh> calculateBounds(mesh);
+ auto root = BVHBuilderMorton::build<NodeRecord>(
+ typename BVH::CreateAlloc(bvh),
+ typename BVH::AABBNode::Create(),
+ setBounds,createLeaf,calculateBounds,bvh->scene->progressInterface,
+ morton.data(),dest,numPrimitivesGen,settings);
+
+ bvh->set(root.ref,LBBox3fa(root.bounds),numPrimitives);
+
+#if ROTATE_TREE
+ if (N == 4)
+ {
+ for (int i=0; i<ROTATE_TREE; i++)
+ BVHNRotate<N>::rotate(bvh->root);
+ bvh->clearBarrier(bvh->root);
+ }
+#endif
+
+ /* clear temporary data for static geometry */
+ if (bvh->scene->isStaticAccel()) {
+ morton.clear();
+ }
+ bvh->cleanup();
+ }
+
+ void clear() {
+ morton.clear();
+ }
+
+ private:
+ BVH* bvh;
+ Mesh* mesh;
+ mvector<BVHBuilderMorton::BuildPrim> morton;
+ BVHBuilderMorton::Settings settings;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ unsigned int numPreviousPrimitives = 0;
+ };
+
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ Builder* BVH4Triangle4MeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4> ((BVH4*)bvh,mesh,geomID,4,4); }
+ Builder* BVH4Triangle4vMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4v>((BVH4*)bvh,mesh,geomID,4,4); }
+ Builder* BVH4Triangle4iMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4i>((BVH4*)bvh,mesh,geomID,4,4); }
+#if defined(__AVX__)
+ Builder* BVH8Triangle4MeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4> ((BVH8*)bvh,mesh,geomID,4,4); }
+ Builder* BVH8Triangle4vMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4v>((BVH8*)bvh,mesh,geomID,4,4); }
+ Builder* BVH8Triangle4iMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4i>((BVH8*)bvh,mesh,geomID,4,4); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_QUAD)
+ Builder* BVH4Quad4vMeshBuilderMortonGeneral (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,QuadMesh,Quad4v>((BVH4*)bvh,mesh,geomID,4,4); }
+#if defined(__AVX__)
+ Builder* BVH8Quad4vMeshBuilderMortonGeneral (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,QuadMesh,Quad4v>((BVH8*)bvh,mesh,geomID,4,4); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_USER)
+ Builder* BVH4VirtualMeshBuilderMortonGeneral (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,UserGeometry,Object>((BVH4*)bvh,mesh,geomID,1,BVH4::maxLeafBlocks); }
+#if defined(__AVX__)
+ Builder* BVH8VirtualMeshBuilderMortonGeneral (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,UserGeometry,Object>((BVH8*)bvh,mesh,geomID,1,BVH4::maxLeafBlocks); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ Builder* BVH4InstanceMeshBuilderMortonGeneral (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,Instance,InstancePrimitive>((BVH4*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); }
+#if defined(__AVX__)
+ Builder* BVH8InstanceMeshBuilderMortonGeneral (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,Instance,InstancePrimitive>((BVH8*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); }
+#endif
+#endif
+
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder_sah.cpp b/thirdparty/embree/kernels/bvh/bvh_builder_sah.cpp
new file mode 100644
index 0000000000..fad02fcc04
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder_sah.cpp
@@ -0,0 +1,543 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh.h"
+#include "bvh_builder.h"
+#include "../builders/primrefgen.h"
+#include "../builders/splitter.h"
+
+#include "../geometry/linei.h"
+#include "../geometry/triangle.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/trianglev_mb.h"
+#include "../geometry/trianglei.h"
+#include "../geometry/quadv.h"
+#include "../geometry/quadi.h"
+#include "../geometry/object.h"
+#include "../geometry/instance.h"
+#include "../geometry/subgrid.h"
+
+#include "../common/state.h"
+#include "../../common/algorithms/parallel_for_for.h"
+#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
+
+#define PROFILE 0
+#define PROFILE_RUNS 20
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N, typename Primitive>
+ struct CreateLeaf
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+
+ __forceinline CreateLeaf (BVH* bvh) : bvh(bvh) {}
+
+ __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
+ {
+ size_t n = set.size();
+ size_t items = Primitive::blocks(n);
+ size_t start = set.begin();
+ Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
+ typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
+ for (size_t i=0; i<items; i++) {
+ accel[i].fill(prims,start,set.end(),bvh->scene);
+ }
+ return node;
+ }
+
+ BVH* bvh;
+ };
+
+
+ template<int N, typename Primitive>
+ struct CreateLeafQuantized
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+
+ __forceinline CreateLeafQuantized (BVH* bvh) : bvh(bvh) {}
+
+ __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
+ {
+ size_t n = set.size();
+ size_t items = Primitive::blocks(n);
+ size_t start = set.begin();
+ Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
+ typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
+ for (size_t i=0; i<items; i++) {
+ accel[i].fill(prims,start,set.end(),bvh->scene);
+ }
+ return node;
+ }
+
+ BVH* bvh;
+ };
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+ template<int N, typename Primitive>
+ struct BVHNBuilderSAH : public Builder
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVHN<N>::NodeRef NodeRef;
+
+ BVH* bvh;
+ Scene* scene;
+ Geometry* mesh;
+ mvector<PrimRef> prims;
+ GeneralBVHBuilder::Settings settings;
+ Geometry::GTypeMask gtype_;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max ();
+ bool primrefarrayalloc;
+ unsigned int numPreviousPrimitives = 0;
+
+ BVHNBuilderSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize,
+ const Geometry::GTypeMask gtype, bool primrefarrayalloc = false)
+ : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0),
+ settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), primrefarrayalloc(primrefarrayalloc) {}
+
+ BVHNBuilderSAH (BVH* bvh, Geometry* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
+ : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), geomID_(geomID), primrefarrayalloc(false) {}
+
+ // FIXME: shrink bvh->alloc in destructor here and in other builders too
+
+ void build()
+ {
+ /* we reset the allocator when the mesh size changed */
+ if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
+ bvh->alloc.clear();
+ }
+
+ /* if we use the primrefarray for allocations we have to take it back from the BVH */
+ if (settings.primrefarrayalloc != size_t(inf))
+ bvh->alloc.unshare(prims);
+
+ /* skip build for empty scene */
+ const size_t numPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(gtype_,false);
+ numPreviousPrimitives = numPrimitives;
+ if (numPrimitives == 0) {
+ bvh->clear();
+ prims.clear();
+ return;
+ }
+
+ double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + "BuilderSAH");
+
+#if PROFILE
+ profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
+#endif
+
+ /* create primref array */
+ if (primrefarrayalloc) {
+ settings.primrefarrayalloc = numPrimitives/1000;
+ if (settings.primrefarrayalloc < 1000)
+ settings.primrefarrayalloc = inf;
+ }
+
+ /* enable os_malloc for two level build */
+ if (mesh)
+ bvh->alloc.setOSallocation(true);
+
+ /* initialize allocator */
+ const size_t node_bytes = numPrimitives*sizeof(typename BVH::AABBNodeMB)/(4*N);
+ const size_t leaf_bytes = size_t(1.2*Primitive::blocks(numPrimitives)*sizeof(Primitive));
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
+ prims.resize(numPrimitives);
+
+ PrimInfo pinfo = mesh ?
+ createPrimRefArray(mesh,geomID_,numPrimitives,prims,bvh->scene->progressInterface) :
+ createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface);
+
+ /* pinfo might has zero size due to invalid geometry */
+ if (unlikely(pinfo.size() == 0))
+ {
+ bvh->clear();
+ prims.clear();
+ return;
+ }
+
+ /* call BVH builder */
+ NodeRef root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeaf<N,Primitive>(bvh),bvh->scene->progressInterface,prims.data(),pinfo,settings);
+ bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
+ bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
+
+#if PROFILE
+ });
+#endif
+
+ /* if we allocated using the primrefarray we have to keep it alive */
+ if (settings.primrefarrayalloc != size_t(inf))
+ bvh->alloc.share(prims);
+
+ /* for static geometries we can do some cleanups */
+ else if (scene && scene->isStaticAccel()) {
+ prims.clear();
+ }
+ bvh->cleanup();
+ bvh->postBuild(t0);
+ }
+
+ void clear() {
+ prims.clear();
+ }
+ };
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+ template<int N, typename Primitive>
+ struct BVHNBuilderSAHQuantized : public Builder
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVHN<N>::NodeRef NodeRef;
+
+ BVH* bvh;
+ Scene* scene;
+ Geometry* mesh;
+ mvector<PrimRef> prims;
+ GeneralBVHBuilder::Settings settings;
+ Geometry::GTypeMask gtype_;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ unsigned int numPreviousPrimitives = 0;
+
+ BVHNBuilderSAHQuantized (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
+ : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype) {}
+
+ BVHNBuilderSAHQuantized (BVH* bvh, Geometry* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
+ : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), geomID_(geomID) {}
+
+ // FIXME: shrink bvh->alloc in destructor here and in other builders too
+
+ void build()
+ {
+ /* we reset the allocator when the mesh size changed */
+ if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
+ bvh->alloc.clear();
+ }
+
+ /* skip build for empty scene */
+ const size_t numPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(gtype_,false);
+ numPreviousPrimitives = numPrimitives;
+ if (numPrimitives == 0) {
+ prims.clear();
+ bvh->clear();
+ return;
+ }
+
+ double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::QBVH" + toString(N) + "BuilderSAH");
+
+#if PROFILE
+ profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
+#endif
+ /* create primref array */
+ prims.resize(numPrimitives);
+ PrimInfo pinfo = mesh ?
+ createPrimRefArray(mesh,geomID_,numPrimitives,prims,bvh->scene->progressInterface) :
+ createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface);
+
+ /* enable os_malloc for two level build */
+ if (mesh)
+ bvh->alloc.setOSallocation(true);
+
+ /* call BVH builder */
+ const size_t node_bytes = numPrimitives*sizeof(typename BVH::QuantizedNode)/(4*N);
+ const size_t leaf_bytes = size_t(1.2*Primitive::blocks(numPrimitives)*sizeof(Primitive));
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
+ NodeRef root = BVHNBuilderQuantizedVirtual<N>::build(&bvh->alloc,CreateLeafQuantized<N,Primitive>(bvh),bvh->scene->progressInterface,prims.data(),pinfo,settings);
+ bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
+ //bvh->layoutLargeNodes(pinfo.size()*0.005f); // FIXME: COPY LAYOUT FOR LARGE NODES !!!
+#if PROFILE
+ });
+#endif
+
+ /* clear temporary data for static geometry */
+ if (scene && scene->isStaticAccel()) {
+ prims.clear();
+ }
+ bvh->cleanup();
+ bvh->postBuild(t0);
+ }
+
+ void clear() {
+ prims.clear();
+ }
+ };
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+
+ template<int N, typename Primitive>
+ struct CreateLeafGrid
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+
+ __forceinline CreateLeafGrid (BVH* bvh, const SubGridBuildData * const sgrids) : bvh(bvh),sgrids(sgrids) {}
+
+ __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
+ {
+ const size_t items = set.size(); //Primitive::blocks(n);
+ const size_t start = set.begin();
+
+ /* collect all subsets with unique geomIDs */
+ assert(items <= N);
+ unsigned int geomIDs[N];
+ unsigned int num_geomIDs = 1;
+ geomIDs[0] = prims[start].geomID();
+
+ for (size_t i=1;i<items;i++)
+ {
+ bool found = false;
+ const unsigned int new_geomID = prims[start+i].geomID();
+ for (size_t j=0;j<num_geomIDs;j++)
+ if (new_geomID == geomIDs[j])
+ { found = true; break; }
+ if (!found)
+ geomIDs[num_geomIDs++] = new_geomID;
+ }
+
+ /* allocate all leaf memory in one single block */
+ SubGridQBVHN<N>* accel = (SubGridQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridQBVHN<N>),BVH::byteAlignment);
+ typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,num_geomIDs);
+
+ for (size_t g=0;g<num_geomIDs;g++)
+ {
+ unsigned int x[N];
+ unsigned int y[N];
+ unsigned int primID[N];
+ BBox3fa bounds[N];
+ unsigned int pos = 0;
+ for (size_t i=0;i<items;i++)
+ {
+ if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
+
+ const SubGridBuildData& sgrid_bd = sgrids[prims[start+i].primID()];
+ x[pos] = sgrid_bd.sx;
+ y[pos] = sgrid_bd.sy;
+ primID[pos] = sgrid_bd.primID;
+ bounds[pos] = prims[start+i].bounds();
+ pos++;
+ }
+ assert(pos <= N);
+ new (&accel[g]) SubGridQBVHN<N>(x,y,primID,bounds,geomIDs[g],pos);
+ }
+
+ return node;
+ }
+
+ BVH* bvh;
+ const SubGridBuildData * const sgrids;
+ };
+
+
+ template<int N>
+ struct BVHNBuilderSAHGrid : public Builder
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVHN<N>::NodeRef NodeRef;
+
+ BVH* bvh;
+ Scene* scene;
+ GridMesh* mesh;
+ mvector<PrimRef> prims;
+ mvector<SubGridBuildData> sgrids;
+ GeneralBVHBuilder::Settings settings;
+ const unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ unsigned int numPreviousPrimitives = 0;
+
+ BVHNBuilderSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
+ : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0), sgrids(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD) {}
+
+ BVHNBuilderSAHGrid (BVH* bvh, GridMesh* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
+ : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), sgrids(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), geomID_(geomID) {}
+
+ void build()
+ {
+ /* we reset the allocator when the mesh size changed */
+ if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
+ bvh->alloc.clear();
+ }
+
+ /* if we use the primrefarray for allocations we have to take it back from the BVH */
+ if (settings.primrefarrayalloc != size_t(inf))
+ bvh->alloc.unshare(prims);
+
+ const size_t numGridPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(GridMesh::geom_type,false);
+ numPreviousPrimitives = numGridPrimitives;
+
+
+ PrimInfo pinfo = mesh ? createPrimRefArrayGrids(mesh,prims,sgrids) : createPrimRefArrayGrids(scene,prims,sgrids);
+ const size_t numPrimitives = pinfo.size();
+ /* no primitives */
+ if (numPrimitives == 0) {
+ bvh->clear();
+ prims.clear();
+ sgrids.clear();
+ return;
+ }
+
+ double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + "BuilderSAH");
+
+ /* create primref array */
+ settings.primrefarrayalloc = numPrimitives/1000;
+ if (settings.primrefarrayalloc < 1000)
+ settings.primrefarrayalloc = inf;
+
+ /* enable os_malloc for two level build */
+ if (mesh)
+ bvh->alloc.setOSallocation(true);
+
+ /* initialize allocator */
+ const size_t node_bytes = numPrimitives*sizeof(typename BVH::AABBNodeMB)/(4*N);
+ const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
+
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
+
+ /* pinfo might has zero size due to invalid geometry */
+ if (unlikely(pinfo.size() == 0))
+ {
+ bvh->clear();
+ sgrids.clear();
+ prims.clear();
+ return;
+ }
+
+ /* call BVH builder */
+ NodeRef root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeafGrid<N,SubGridQBVHN<N>>(bvh,sgrids.data()),bvh->scene->progressInterface,prims.data(),pinfo,settings);
+ bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
+ bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
+
+ /* clear temporary array */
+ sgrids.clear();
+
+ /* if we allocated using the primrefarray we have to keep it alive */
+ if (settings.primrefarrayalloc != size_t(inf))
+ bvh->alloc.share(prims);
+
+ /* for static geometries we can do some cleanups */
+ else if (scene && scene->isStaticAccel()) {
+ prims.clear();
+ }
+ bvh->cleanup();
+ bvh->postBuild(t0);
+ }
+
+ void clear() {
+ prims.clear();
+ }
+ };
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4v>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH4Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4i>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
+
+ Builder* BVH4Triangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH4Triangle4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4v>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH4Triangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type,true); }
+
+ Builder* BVH4QuantizedTriangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
+#if defined(__AVX__)
+ Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH8Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4v>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH8Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4i>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
+
+ Builder* BVH8Triangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH8Triangle4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4v>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH8Triangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type,true); }
+ Builder* BVH8QuantizedTriangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
+ Builder* BVH8QuantizedTriangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Triangle4>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
+
+
+
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_QUAD)
+ Builder* BVH4Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Quad4v>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
+ Builder* BVH4Quad4iMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Quad4i>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
+ Builder* BVH4Quad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Quad4v>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
+ Builder* BVH4Quad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type,true); }
+ Builder* BVH4QuantizedQuad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Quad4v>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
+ Builder* BVH4QuantizedQuad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
+
+#if defined(__AVX__)
+ Builder* BVH8Quad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Quad4v>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
+ Builder* BVH8Quad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type,true); }
+ Builder* BVH8QuantizedQuad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Quad4v>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
+ Builder* BVH8QuantizedQuad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
+ Builder* BVH8Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Quad4v>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
+
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_USER)
+
+ Builder* BVH4VirtualSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
+ int minLeafSize = scene->device->object_accel_min_leaf_size;
+ int maxLeafSize = scene->device->object_accel_max_leaf_size;
+ return new BVHNBuilderSAH<4,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,UserGeometry::geom_type);
+ }
+
+ Builder* BVH4VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) {
+ return new BVHNBuilderSAH<4,Object>((BVH4*)bvh,mesh,geomID,4,1.0f,1,inf,UserGeometry::geom_type);
+ }
+#if defined(__AVX__)
+
+ Builder* BVH8VirtualSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
+ int minLeafSize = scene->device->object_accel_min_leaf_size;
+ int maxLeafSize = scene->device->object_accel_max_leaf_size;
+ return new BVHNBuilderSAH<8,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,UserGeometry::geom_type);
+ }
+
+ Builder* BVH8VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) {
+ return new BVHNBuilderSAH<8,Object>((BVH8*)bvh,mesh,geomID,8,1.0f,1,inf,UserGeometry::geom_type);
+ }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ Builder* BVH4InstanceSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderSAH<4,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }
+ Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) {
+ return new BVHNBuilderSAH<4,InstancePrimitive>((BVH4*)bvh,mesh,geomID,4,1.0f,1,inf,gtype);
+ }
+#if defined(__AVX__)
+ Builder* BVH8InstanceSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderSAH<8,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }
+ Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) {
+ return new BVHNBuilderSAH<8,InstancePrimitive>((BVH8*)bvh,mesh,geomID,8,1.0f,1,inf,gtype);
+ }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_GRID)
+ Builder* BVH4GridMeshBuilderSAH (void* bvh, GridMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAHGrid<4>((BVH4*)bvh,mesh,geomID,4,1.0f,4,4,mode); }
+ Builder* BVH4GridSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4,mode); } // FIXME: check whether cost factors are correct
+
+#if defined(__AVX__)
+ Builder* BVH8GridMeshBuilderSAH (void* bvh, GridMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAHGrid<8>((BVH8*)bvh,mesh,geomID,8,1.0f,8,8,mode); }
+ Builder* BVH8GridSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8,mode); } // FIXME: check whether cost factors are correct
+#endif
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder_sah_mb.cpp b/thirdparty/embree/kernels/bvh/bvh_builder_sah_mb.cpp
new file mode 100644
index 0000000000..d163a80ab1
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder_sah_mb.cpp
@@ -0,0 +1,705 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh.h"
+#include "bvh_builder.h"
+#include "../builders/bvh_builder_msmblur.h"
+
+#include "../builders/primrefgen.h"
+#include "../builders/splitter.h"
+
+#include "../geometry/linei.h"
+#include "../geometry/triangle.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/trianglev_mb.h"
+#include "../geometry/trianglei.h"
+#include "../geometry/quadv.h"
+#include "../geometry/quadi.h"
+#include "../geometry/object.h"
+#include "../geometry/instance.h"
+#include "../geometry/subgrid.h"
+
+#include "../common/state.h"
+
+// FIXME: remove after removing BVHNBuilderMBlurRootTimeSplitsSAH
+#include "../../common/algorithms/parallel_for_for.h"
+#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
+
+
+namespace embree
+{
+ namespace isa
+ {
+
+#if 0
+ template<int N, typename Primitive>
+ struct CreateMBlurLeaf
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecordMB NodeRecordMB;
+
+ __forceinline CreateMBlurLeaf (BVH* bvh, PrimRef* prims, size_t time) : bvh(bvh), prims(prims), time(time) {}
+
+ __forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
+ {
+ size_t items = Primitive::blocks(set.size());
+ size_t start = set.begin();
+ for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
+ Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
+ NodeRef node = bvh->encodeLeaf((char*)accel,items);
+
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<items; i++)
+ allBounds.extend(accel[i].fillMB(prims, start, set.end(), bvh->scene, time));
+
+ return NodeRecordMB(node,allBounds);
+ }
+
+ BVH* bvh;
+ PrimRef* prims;
+ size_t time;
+ };
+#endif
+
+ template<int N, typename Mesh, typename Primitive>
+ struct CreateMSMBlurLeaf
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
+
+ __forceinline CreateMSMBlurLeaf (BVH* bvh) : bvh(bvh) {}
+
+ __forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
+ {
+ size_t items = Primitive::blocks(current.prims.size());
+ size_t start = current.prims.begin();
+ size_t end = current.prims.end();
+ for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
+ Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteNodeAlignment);
+ NodeRef node = bvh->encodeLeaf((char*)accel,items);
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<items; i++)
+ allBounds.extend(accel[i].fillMB(current.prims.prims->data(), start, current.prims.end(), bvh->scene, current.prims.time_range));
+ return NodeRecordMB4D(node,allBounds,current.prims.time_range);
+ }
+
+ BVH* bvh;
+ };
+
+ /* Motion blur BVH with 4D nodes and internal time splits */
+ template<int N, typename Mesh, typename Primitive>
+ struct BVHNBuilderMBlurSAH : public Builder
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVHN<N>::NodeRef NodeRef;
+ typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
+ typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;
+
+ BVH* bvh;
+ Scene* scene;
+ const size_t sahBlockSize;
+ const float intCost;
+ const size_t minLeafSize;
+ const size_t maxLeafSize;
+ const Geometry::GTypeMask gtype_;
+
+ BVHNBuilderMBlurSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
+ : bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks)), gtype_(gtype) {}
+
+ void build()
+ {
+ /* skip build for empty scene */
+ const size_t numPrimitives = scene->getNumPrimitives(gtype_,true);
+ if (numPrimitives == 0) { bvh->clear(); return; }
+
+ double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAH");
+
+#if PROFILE
+ profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
+#endif
+
+ //const size_t numTimeSteps = scene->getNumTimeSteps<typename Mesh::type_t,true>();
+ //const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
+
+ /*if (numTimeSegments == 1)
+ buildSingleSegment(numPrimitives);
+ else*/
+ buildMultiSegment(numPrimitives);
+
+#if PROFILE
+ });
+#endif
+
+ /* clear temporary data for static geometry */
+ bvh->cleanup();
+ bvh->postBuild(t0);
+ }
+
+#if 0 // No longer compatible when time_ranges are present for geometries. Would have to create temporal nodes sometimes, and put only a single geometry into leaf.
+ void buildSingleSegment(size_t numPrimitives)
+ {
+ /* create primref array */
+ mvector<PrimRef> prims(scene->device,numPrimitives);
+ const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface,0);
+ /* early out if no valid primitives */
+ if (pinfo.size() == 0) { bvh->clear(); return; }
+ /* estimate acceleration structure size */
+ const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);
+ const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+
+ /* settings for BVH build */
+ GeneralBVHBuilder::Settings settings;
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxBuildDepthLeaf;
+ settings.logBlockSize = bsr(sahBlockSize);
+ settings.minLeafSize = min(minLeafSize,maxLeafSize);
+ settings.maxLeafSize = maxLeafSize;
+ settings.travCost = travCost;
+ settings.intCost = intCost;
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
+
+ /* build hierarchy */
+ auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>
+ (typename BVH::CreateAlloc(bvh),typename BVH::AABBNodeMB::Create(),typename BVH::AABBNodeMB::Set(),
+ CreateMBlurLeaf<N,Primitive>(bvh,prims.data(),0),bvh->scene->progressInterface,
+ prims.data(),pinfo,settings);
+
+ bvh->set(root.ref,root.lbounds,pinfo.size());
+ }
+#endif
+
+ void buildMultiSegment(size_t numPrimitives)
+ {
+ /* create primref array */
+ mvector<PrimRefMB> prims(scene->device,numPrimitives);
+ PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface);
+
+ /* early out if no valid primitives */
+ if (pinfo.size() == 0) { bvh->clear(); return; }
+
+ /* estimate acceleration structure size */
+ const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);
+ const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(Primitive));
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+
+ /* settings for BVH build */
+ BVHBuilderMSMBlur::Settings settings;
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxDepth;
+ settings.logBlockSize = bsr(sahBlockSize);
+ settings.minLeafSize = min(minLeafSize,maxLeafSize);
+ settings.maxLeafSize = maxLeafSize;
+ settings.travCost = travCost;
+ settings.intCost = intCost;
+ settings.singleLeafTimeSegment = Primitive::singleTimeSegment;
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
+
+ /* build hierarchy */
+ auto root =
+ BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
+ RecalculatePrimRef<Mesh>(scene),
+ typename BVH::CreateAlloc(bvh),
+ typename BVH::AABBNodeMB4D::Create(),
+ typename BVH::AABBNodeMB4D::Set(),
+ CreateMSMBlurLeaf<N,Mesh,Primitive>(bvh),
+ bvh->scene->progressInterface,
+ settings);
+
+ bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
+ }
+
+ void clear() {
+ }
+ };
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+ struct GridRecalculatePrimRef
+ {
+ Scene* scene;
+ const SubGridBuildData * const sgrids;
+
+ __forceinline GridRecalculatePrimRef (Scene* scene, const SubGridBuildData * const sgrids)
+ : scene(scene), sgrids(sgrids) {}
+
+ __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const
+ {
+ const unsigned int geomID = prim.geomID();
+ const GridMesh* mesh = scene->get<GridMesh>(geomID);
+ const unsigned int buildID = prim.primID();
+ const SubGridBuildData &subgrid = sgrids[buildID];
+ const unsigned int primID = subgrid.primID;
+ const size_t x = subgrid.x();
+ const size_t y = subgrid.y();
+ const LBBox3fa lbounds = mesh->linearBounds(mesh->grid(primID),x,y,time_range);
+ const unsigned num_time_segments = mesh->numTimeSegments();
+ const range<int> tbounds = mesh->timeSegmentRange(time_range);
+ return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, num_time_segments, geomID, buildID);
+ }
+
+ __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
+ const unsigned int geomID = prim.geomID();
+ const GridMesh* mesh = scene->get<GridMesh>(geomID);
+ const unsigned int buildID = prim.primID();
+ const SubGridBuildData &subgrid = sgrids[buildID];
+ const unsigned int primID = subgrid.primID;
+ const size_t x = subgrid.x();
+ const size_t y = subgrid.y();
+ return mesh->linearBounds(mesh->grid(primID),x,y,time_range);
+ }
+
+ };
+
+ template<int N>
+ struct CreateMSMBlurLeafGrid
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
+
+ __forceinline CreateMSMBlurLeafGrid (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids) : scene(scene), bvh(bvh), sgrids(sgrids) {}
+
+ __forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
+ {
+ const size_t items = current.prims.size();
+ const size_t start = current.prims.begin();
+
+ const PrimRefMB* prims = current.prims.prims->data();
+ /* collect all subsets with unique geomIDs */
+ assert(items <= N);
+ unsigned int geomIDs[N];
+ unsigned int num_geomIDs = 1;
+ geomIDs[0] = prims[start].geomID();
+
+ for (size_t i=1;i<items;i++)
+ {
+ bool found = false;
+ const unsigned int new_geomID = prims[start+i].geomID();
+ for (size_t j=0;j<num_geomIDs;j++)
+ if (new_geomID == geomIDs[j])
+ { found = true; break; }
+ if (!found)
+ geomIDs[num_geomIDs++] = new_geomID;
+ }
+
+ /* allocate all leaf memory in one single block */
+ SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);
+ typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);
+
+ LBBox3fa allBounds = empty;
+
+ for (size_t g=0;g<num_geomIDs;g++)
+ {
+ const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);
+ unsigned int x[N];
+ unsigned int y[N];
+ unsigned int primID[N];
+ BBox3fa bounds0[N];
+ BBox3fa bounds1[N];
+ unsigned int pos = 0;
+ for (size_t i=0;i<items;i++)
+ {
+ if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
+
+ const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];
+ x[pos] = sgrid_bd.sx;
+ y[pos] = sgrid_bd.sy;
+ primID[pos] = sgrid_bd.primID;
+ const size_t x = sgrid_bd.x();
+ const size_t y = sgrid_bd.y();
+ LBBox3fa newBounds = mesh->linearBounds(mesh->grid(sgrid_bd.primID),x,y,current.prims.time_range);
+ allBounds.extend(newBounds);
+ bounds0[pos] = newBounds.bounds0;
+ bounds1[pos] = newBounds.bounds1;
+ pos++;
+ }
+ assert(pos <= N);
+ new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],current.prims.time_range.lower,1.0f/current.prims.time_range.size(),pos);
+ }
+ return NodeRecordMB4D(node,allBounds,current.prims.time_range);
+ }
+
+ Scene *scene;
+ BVH* bvh;
+ const SubGridBuildData * const sgrids;
+ };
+
+#if 0
+ template<int N>
+ struct CreateLeafGridMB
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::NodeRecordMB NodeRecordMB;
+
+ __forceinline CreateLeafGridMB (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids)
+ : scene(scene), bvh(bvh), sgrids(sgrids) {}
+
+ __forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
+ {
+ const size_t items = set.size();
+ const size_t start = set.begin();
+
+ /* collect all subsets with unique geomIDs */
+ assert(items <= N);
+ unsigned int geomIDs[N];
+ unsigned int num_geomIDs = 1;
+ geomIDs[0] = prims[start].geomID();
+
+ for (size_t i=1;i<items;i++)
+ {
+ bool found = false;
+ const unsigned int new_geomID = prims[start+i].geomID();
+ for (size_t j=0;j<num_geomIDs;j++)
+ if (new_geomID == geomIDs[j])
+ { found = true; break; }
+ if (!found)
+ geomIDs[num_geomIDs++] = new_geomID;
+ }
+
+ /* allocate all leaf memory in one single block */
+ SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);
+ typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);
+
+ LBBox3fa allBounds = empty;
+
+ for (size_t g=0;g<num_geomIDs;g++)
+ {
+ const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);
+
+ unsigned int x[N];
+ unsigned int y[N];
+ unsigned int primID[N];
+ BBox3fa bounds0[N];
+ BBox3fa bounds1[N];
+ unsigned int pos = 0;
+ for (size_t i=0;i<items;i++)
+ {
+ if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
+
+ const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];
+ x[pos] = sgrid_bd.sx;
+ y[pos] = sgrid_bd.sy;
+ primID[pos] = sgrid_bd.primID;
+ const size_t x = sgrid_bd.x();
+ const size_t y = sgrid_bd.y();
+ bool MAYBE_UNUSED valid0 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,0,bounds0[pos]);
+ bool MAYBE_UNUSED valid1 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,1,bounds1[pos]);
+ assert(valid0);
+ assert(valid1);
+ allBounds.extend(LBBox3fa(bounds0[pos],bounds1[pos]));
+ pos++;
+ }
+ new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],0.0f,1.0f,pos);
+ }
+ return NodeRecordMB(node,allBounds);
+ }
+
+ Scene *scene;
+ BVH* bvh;
+ const SubGridBuildData * const sgrids;
+ };
+#endif
+
+
+ /* Motion blur BVH with 4D nodes and internal time splits */
+ template<int N>
+ struct BVHNBuilderMBlurSAHGrid : public Builder
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVHN<N>::NodeRef NodeRef;
+ typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
+ typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;
+
+ BVH* bvh;
+ Scene* scene;
+ const size_t sahBlockSize;
+ const float intCost;
+ const size_t minLeafSize;
+ const size_t maxLeafSize;
+ mvector<SubGridBuildData> sgrids;
+
+
+ BVHNBuilderMBlurSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize)
+ : bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,BVH::maxLeafBlocks)), sgrids(scene->device,0) {}
+
+
+ PrimInfo createPrimRefArrayMBlurGrid(Scene* scene, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
+ {
+ /* first run to get #primitives */
+ ParallelForForPrefixSumState<PrimInfo> pstate;
+ Scene::Iterator<GridMesh,true> iter(scene);
+
+ pstate.init(iter,size_t(1024));
+
+ /* iterate over all meshes in the scene */
+ PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
+
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!mesh->valid(j,range<size_t>(0,1))) continue;
+ BBox3fa bounds = empty;
+ const PrimRef prim(bounds,unsigned(geomID),unsigned(j));
+ pinfo.add_center2(prim,mesh->getNumSubGrids(j));
+ }
+ return pinfo;
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ size_t numPrimitives = pinfo.size();
+ if (numPrimitives == 0) return pinfo;
+
+ /* resize arrays */
+ sgrids.resize(numPrimitives);
+ prims.resize(numPrimitives);
+
+ /* second run to fill primrefs and SubGridBuildData arrays */
+ pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
+
+ k = base.size();
+ size_t p_index = k;
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ const GridMesh::Grid &g = mesh->grid(j);
+ if (!mesh->valid(j,range<size_t>(0,1))) continue;
+
+ for (unsigned int y=0; y<g.resY-1u; y+=2)
+ for (unsigned int x=0; x<g.resX-1u; x+=2)
+ {
+ BBox3fa bounds = empty;
+ if (!mesh->buildBounds(g,x,y,itime,bounds)) continue; // get bounds of subgrid
+ const PrimRef prim(bounds,unsigned(geomID),unsigned(p_index));
+ pinfo.add_center2(prim);
+ sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
+ prims[p_index++] = prim;
+ }
+ }
+ return pinfo;
+ }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
+
+ assert(pinfo.size() == numPrimitives);
+ return pinfo;
+ }
+
+ PrimInfoMB createPrimRefArrayMSMBlurGrid(Scene* scene, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f))
+ {
+ /* first run to get #primitives */
+ ParallelForForPrefixSumState<PrimInfoMB> pstate;
+ Scene::Iterator<GridMesh,true> iter(scene);
+
+ pstate.init(iter,size_t(1024));
+ /* iterate over all meshes in the scene */
+ PrimInfoMB pinfoMB = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t /*geomID*/) -> PrimInfoMB {
+
+ PrimInfoMB pinfoMB(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
+ LBBox3fa bounds(empty);
+ PrimInfoMB gridMB(0,mesh->getNumSubGrids(j));
+ pinfoMB.merge(gridMB);
+ }
+ return pinfoMB;
+ }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
+
+ size_t numPrimitives = pinfoMB.size();
+ if (numPrimitives == 0) return pinfoMB;
+
+ /* resize arrays */
+ sgrids.resize(numPrimitives);
+ prims.resize(numPrimitives);
+ /* second run to fill primrefs and SubGridBuildData arrays */
+ pinfoMB = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
+
+ k = base.size();
+ size_t p_index = k;
+ PrimInfoMB pinfoMB(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
+ const GridMesh::Grid &g = mesh->grid(j);
+
+ for (unsigned int y=0; y<g.resY-1u; y+=2)
+ for (unsigned int x=0; x<g.resX-1u; x+=2)
+ {
+ const PrimRefMB prim(mesh->linearBounds(g,x,y,t0t1),mesh->numTimeSegments(),mesh->time_range,mesh->numTimeSegments(),unsigned(geomID),unsigned(p_index));
+ pinfoMB.add_primref(prim);
+ sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
+ prims[p_index++] = prim;
+ }
+ }
+ return pinfoMB;
+ }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
+
+ assert(pinfoMB.size() == numPrimitives);
+ pinfoMB.time_range = t0t1;
+ return pinfoMB;
+ }
+
+ void build()
+ {
+ /* skip build for empty scene */
+ const size_t numPrimitives = scene->getNumPrimitives(GridMesh::geom_type,true);
+ if (numPrimitives == 0) { bvh->clear(); return; }
+
+ double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAHGrid");
+
+ //const size_t numTimeSteps = scene->getNumTimeSteps<GridMesh,true>();
+ //const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
+ //if (numTimeSegments == 1)
+ // buildSingleSegment(numPrimitives);
+ //else
+ buildMultiSegment(numPrimitives);
+
+ /* clear temporary data for static geometry */
+ bvh->cleanup();
+ bvh->postBuild(t0);
+ }
+
+#if 0
+ void buildSingleSegment(size_t numPrimitives)
+ {
+ /* create primref array */
+ mvector<PrimRef> prims(scene->device,numPrimitives);
+ const PrimInfo pinfo = createPrimRefArrayMBlurGrid(scene,prims,bvh->scene->progressInterface,0);
+ /* early out if no valid primitives */
+ if (pinfo.size() == 0) { bvh->clear(); return; }
+
+ /* estimate acceleration structure size */
+ const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);
+ //TODO: check leaf_bytes
+ const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+
+ /* settings for BVH build */
+ GeneralBVHBuilder::Settings settings;
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxBuildDepthLeaf;
+ settings.logBlockSize = bsr(sahBlockSize);
+ settings.minLeafSize = min(minLeafSize,maxLeafSize);
+ settings.maxLeafSize = maxLeafSize;
+ settings.travCost = travCost;
+ settings.intCost = intCost;
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
+
+ /* build hierarchy */
+ auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>
+ (typename BVH::CreateAlloc(bvh),
+ typename BVH::AABBNodeMB::Create(),
+ typename BVH::AABBNodeMB::Set(),
+ CreateLeafGridMB<N>(scene,bvh,sgrids.data()),
+ bvh->scene->progressInterface,
+ prims.data(),pinfo,settings);
+
+ bvh->set(root.ref,root.lbounds,pinfo.size());
+ }
+#endif
+
+ void buildMultiSegment(size_t numPrimitives)
+ {
+ /* create primref array */
+ mvector<PrimRefMB> prims(scene->device,numPrimitives);
+ PrimInfoMB pinfo = createPrimRefArrayMSMBlurGrid(scene,prims,bvh->scene->progressInterface);
+
+ /* early out if no valid primitives */
+ if (pinfo.size() == 0) { bvh->clear(); return; }
+
+
+
+ GridRecalculatePrimRef recalculatePrimRef(scene,sgrids.data());
+
+ /* estimate acceleration structure size */
+ const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);
+ //FIXME: check leaf_bytes
+ //const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(SubGridQBVHN<N>));
+ const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
+
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+
+ /* settings for BVH build */
+ BVHBuilderMSMBlur::Settings settings;
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxDepth;
+ settings.logBlockSize = bsr(sahBlockSize);
+ settings.minLeafSize = min(minLeafSize,maxLeafSize);
+ settings.maxLeafSize = maxLeafSize;
+ settings.travCost = travCost;
+ settings.intCost = intCost;
+ settings.singleLeafTimeSegment = false;
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
+
+ /* build hierarchy */
+ auto root =
+ BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
+ recalculatePrimRef,
+ typename BVH::CreateAlloc(bvh),
+ typename BVH::AABBNodeMB4D::Create(),
+ typename BVH::AABBNodeMB4D::Set(),
+ CreateMSMBlurLeafGrid<N>(scene,bvh,sgrids.data()),
+ bvh->scene->progressInterface,
+ settings);
+ bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
+ }
+
+ void clear() {
+ }
+ };
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ Builder* BVH4Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
+ Builder* BVH4Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4vMB>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
+#if defined(__AVX__)
+ Builder* BVH8Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
+ Builder* BVH8Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4vMB>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_QUAD)
+ Builder* BVH4Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,QuadMesh,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); }
+#if defined(__AVX__)
+ Builder* BVH8Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,QuadMesh,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_USER)
+ Builder* BVH4VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
+ int minLeafSize = scene->device->object_accel_mb_min_leaf_size;
+ int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;
+ return new BVHNBuilderMBlurSAH<4,UserGeometry,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);
+ }
+#if defined(__AVX__)
+ Builder* BVH8VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
+ int minLeafSize = scene->device->object_accel_mb_min_leaf_size;
+ int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;
+ return new BVHNBuilderMBlurSAH<8,UserGeometry,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);
+ }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ Builder* BVH4InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }
+#if defined(__AVX__)
+ Builder* BVH8InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_GRID)
+ Builder* BVH4GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4); }
+#if defined(__AVX__)
+ Builder* BVH8GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8); }
+#endif
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder_sah_spatial.cpp b/thirdparty/embree/kernels/bvh/bvh_builder_sah_spatial.cpp
new file mode 100644
index 0000000000..a4e55d7484
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder_sah_spatial.cpp
@@ -0,0 +1,201 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh.h"
+#include "bvh_builder.h"
+
+#include "../builders/primrefgen.h"
+#include "../builders/primrefgen_presplit.h"
+#include "../builders/splitter.h"
+
+#include "../geometry/linei.h"
+#include "../geometry/triangle.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/trianglev_mb.h"
+#include "../geometry/trianglei.h"
+#include "../geometry/quadv.h"
+#include "../geometry/quadi.h"
+#include "../geometry/object.h"
+#include "../geometry/instance.h"
+#include "../geometry/subgrid.h"
+
+#include "../common/state.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N, typename Primitive>
+ struct CreateLeafSpatial
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+
+ __forceinline CreateLeafSpatial (BVH* bvh) : bvh(bvh) {}
+
+ __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
+ {
+ size_t n = set.size();
+ size_t items = Primitive::blocks(n);
+ size_t start = set.begin();
+ Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
+ typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
+ for (size_t i=0; i<items; i++) {
+ accel[i].fill(prims,start,set.end(),bvh->scene);
+ }
+ return node;
+ }
+
+ BVH* bvh;
+ };
+
+ template<int N, typename Mesh, typename Primitive, typename Splitter>
+ struct BVHNBuilderFastSpatialSAH : public Builder
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ BVH* bvh;
+ Scene* scene;
+ Mesh* mesh;
+ mvector<PrimRef> prims0;
+ GeneralBVHBuilder::Settings settings;
+ const float splitFactor;
+ unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
+ unsigned int numPreviousPrimitives = 0;
+
+ BVHNBuilderFastSpatialSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
+ : bvh(bvh), scene(scene), mesh(nullptr), prims0(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD),
+ splitFactor(scene->device->max_spatial_split_replications) {}
+
+ BVHNBuilderFastSpatialSAH (BVH* bvh, Mesh* mesh, const unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
+ : bvh(bvh), scene(nullptr), mesh(mesh), prims0(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD),
+ splitFactor(scene->device->max_spatial_split_replications), geomID_(geomID) {}
+
+ // FIXME: shrink bvh->alloc in destructor here and in other builders too
+
+ void build()
+ {
+ /* we reset the allocator when the mesh size changed */
+ if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
+ bvh->alloc.clear();
+ }
+
+ /* skip build for empty scene */
+ const size_t numOriginalPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(Mesh::geom_type,false);
+ numPreviousPrimitives = numOriginalPrimitives;
+ if (numOriginalPrimitives == 0) {
+ prims0.clear();
+ bvh->clear();
+ return;
+ }
+
+ const unsigned int maxGeomID = mesh ? geomID_ : scene->getMaxGeomID<Mesh,false>();
+ const bool usePreSplits = scene->device->useSpatialPreSplits || (maxGeomID >= ((unsigned int)1 << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)));
+ double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + (usePreSplits ? "BuilderFastSpatialPresplitSAH" : "BuilderFastSpatialSAH"));
+
+ /* create primref array */
+ const size_t numSplitPrimitives = max(numOriginalPrimitives,size_t(splitFactor*numOriginalPrimitives));
+ prims0.resize(numSplitPrimitives);
+
+ /* enable os_malloc for two level build */
+ if (mesh)
+ bvh->alloc.setOSallocation(true);
+
+ NodeRef root(0);
+ PrimInfo pinfo;
+
+
+ if (likely(usePreSplits))
+ {
+ /* spatial presplit SAH BVH builder */
+ pinfo = mesh ?
+ createPrimRefArray_presplit<Mesh,Splitter>(mesh,maxGeomID,numOriginalPrimitives,prims0,bvh->scene->progressInterface) :
+ createPrimRefArray_presplit<Mesh,Splitter>(scene,Mesh::geom_type,false,numOriginalPrimitives,prims0,bvh->scene->progressInterface);
+
+ const size_t node_bytes = pinfo.size()*sizeof(typename BVH::AABBNode)/(4*N);
+ const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
+
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxBuildDepthLeaf;
+
+ /* call BVH builder */
+ root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeafSpatial<N,Primitive>(bvh),bvh->scene->progressInterface,prims0.data(),pinfo,settings);
+ }
+ else
+ {
+ /* standard spatial split SAH BVH builder */
+ pinfo = mesh ?
+ createPrimRefArray(mesh,geomID_,numSplitPrimitives,prims0,bvh->scene->progressInterface) :
+ createPrimRefArray(scene,Mesh::geom_type,false,numSplitPrimitives,prims0,bvh->scene->progressInterface);
+
+ Splitter splitter(scene);
+
+ const size_t node_bytes = pinfo.size()*sizeof(typename BVH::AABBNode)/(4*N);
+ const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+ settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
+
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxBuildDepthLeaf;
+
+ /* call BVH builder */
+ root = BVHBuilderBinnedFastSpatialSAH::build<NodeRef>(
+ typename BVH::CreateAlloc(bvh),
+ typename BVH::AABBNode::Create2(),
+ typename BVH::AABBNode::Set2(),
+ CreateLeafSpatial<N,Primitive>(bvh),
+ splitter,
+ bvh->scene->progressInterface,
+ prims0.data(),
+ numSplitPrimitives,
+ pinfo,settings);
+
+ /* ==================== */
+ }
+
+ bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
+ bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
+
+ /* clear temporary data for static geometry */
+ if (scene && scene->isStaticAccel()) {
+ prims0.clear();
+ }
+ bvh->cleanup();
+ bvh->postBuild(t0);
+ }
+
+ void clear() {
+ prims0.clear();
+ }
+ };
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+
+ Builder* BVH4Triangle4SceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
+ Builder* BVH4Triangle4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4v,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
+ Builder* BVH4Triangle4iSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4i,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
+
+#if defined(__AVX__)
+ Builder* BVH8Triangle4SceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,TriangleMesh,Triangle4,TriangleSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
+ Builder* BVH8Triangle4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,TriangleMesh,Triangle4v,TriangleSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_QUAD)
+ Builder* BVH4Quad4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,QuadMesh,Quad4v,QuadSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
+
+#if defined(__AVX__)
+ Builder* BVH8Quad4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,QuadMesh,Quad4v,QuadSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
+#endif
+
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder_twolevel.cpp b/thirdparty/embree/kernels/bvh/bvh_builder_twolevel.cpp
new file mode 100644
index 0000000000..5d45ed3748
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder_twolevel.cpp
@@ -0,0 +1,369 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh_builder_twolevel.h"
+#include "bvh_statistics.h"
+#include "../builders/bvh_builder_sah.h"
+#include "../common/scene_line_segments.h"
+#include "../common/scene_triangle_mesh.h"
+#include "../common/scene_quad_mesh.h"
+
+#define PROFILE 0
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N, typename Mesh, typename Primitive>
+ BVHNBuilderTwoLevel<N,Mesh,Primitive>::BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder, const size_t singleThreadThreshold)
+ : bvh(bvh), scene(scene), refs(scene->device,0), prims(scene->device,0), singleThreadThreshold(singleThreadThreshold), gtype(gtype), useMortonBuilder_(useMortonBuilder) {}
+
+ template<int N, typename Mesh, typename Primitive>
+ BVHNBuilderTwoLevel<N,Mesh,Primitive>::~BVHNBuilderTwoLevel () {
+ }
+
+ // ===========================================================================
+ // ===========================================================================
+ // ===========================================================================
+
+ template<int N, typename Mesh, typename Primitive>
+ void BVHNBuilderTwoLevel<N,Mesh,Primitive>::build()
+ {
+ /* delete some objects */
+ size_t num = scene->size();
+ if (num < bvh->objects.size()) {
+ parallel_for(num, bvh->objects.size(), [&] (const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ builders[i].reset();
+ delete bvh->objects[i]; bvh->objects[i] = nullptr;
+ }
+ });
+ }
+
+#if PROFILE
+ while(1)
+#endif
+ {
+ /* reset memory allocator */
+ bvh->alloc.reset();
+
+ /* skip build for empty scene */
+ const size_t numPrimitives = scene->getNumPrimitives(gtype,false);
+
+ if (numPrimitives == 0) {
+ prims.resize(0);
+ bvh->set(BVH::emptyNode,empty,0);
+ return;
+ }
+
+ /* calculate the size of the entire BVH */
+ const size_t numLeafBlocks = Primitive::blocks(numPrimitives);
+ const size_t node_bytes = 2*numLeafBlocks*sizeof(typename BVH::AABBNode)/N;
+ const size_t leaf_bytes = size_t(1.2*numLeafBlocks*sizeof(Primitive));
+ bvh->alloc.init_estimate(node_bytes+leaf_bytes);
+
+ double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderTwoLevel");
+
+ /* resize object array if scene got larger */
+ if (bvh->objects.size() < num) bvh->objects.resize(num);
+ if (builders.size() < num) builders.resize(num);
+ resizeRefsList ();
+ nextRef.store(0);
+
+ /* create acceleration structures */
+ parallel_for(size_t(0), num, [&] (const range<size_t>& r)
+ {
+ for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
+ {
+ Mesh* mesh = scene->getSafe<Mesh>(objectID);
+
+ /* ignore meshes we do not support */
+ if (mesh == nullptr || mesh->numTimeSteps != 1)
+ continue;
+
+ if (isSmallGeometry(mesh)) {
+ setupSmallBuildRefBuilder (objectID, mesh);
+ } else {
+ setupLargeBuildRefBuilder (objectID, mesh);
+ }
+ }
+ });
+
+ /* parallel build of acceleration structures */
+ parallel_for(size_t(0), num, [&] (const range<size_t>& r)
+ {
+ for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
+ {
+ /* ignore if no triangle mesh or not enabled */
+ Mesh* mesh = scene->getSafe<Mesh>(objectID);
+ if (mesh == nullptr || !mesh->isEnabled() || mesh->numTimeSteps != 1)
+ continue;
+
+ builders[objectID]->attachBuildRefs (this);
+ }
+ });
+
+
+#if PROFILE
+ double d0 = getSeconds();
+#endif
+ /* fast path for single geometry scenes */
+ if (nextRef == 1) {
+ bvh->set(refs[0].node,LBBox3fa(refs[0].bounds()),numPrimitives);
+ }
+
+ else
+ {
+ /* open all large nodes */
+ refs.resize(nextRef);
+
+ /* this probably needs some more tuning */
+ const size_t extSize = max(max((size_t)SPLIT_MIN_EXT_SPACE,refs.size()*SPLIT_MEMORY_RESERVE_SCALE),size_t((float)numPrimitives / SPLIT_MEMORY_RESERVE_FACTOR));
+
+#if !ENABLE_DIRECT_SAH_MERGE_BUILDER
+
+#if ENABLE_OPEN_SEQUENTIAL
+ open_sequential(extSize);
+#endif
+ /* compute PrimRefs */
+ prims.resize(refs.size());
+#endif
+
+ {
+#if ENABLE_DIRECT_SAH_MERGE_BUILDER
+
+ const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(), PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {
+
+ PrimInfo pinfo(empty);
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ pinfo.add_center2(refs[i]);
+ }
+ return pinfo;
+ }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
+
+#else
+ const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(), PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {
+
+ PrimInfo pinfo(empty);
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ pinfo.add_center2(refs[i]);
+ prims[i] = PrimRef(refs[i].bounds(),(size_t)refs[i].node);
+ }
+ return pinfo;
+ }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
+#endif
+
+ /* skip if all objects where empty */
+ if (pinfo.size() == 0)
+ bvh->set(BVH::emptyNode,empty,0);
+
+ /* otherwise build toplevel hierarchy */
+ else
+ {
+ /* settings for BVH build */
+ GeneralBVHBuilder::Settings settings;
+ settings.branchingFactor = N;
+ settings.maxDepth = BVH::maxBuildDepthLeaf;
+ settings.logBlockSize = bsr(N);
+ settings.minLeafSize = 1;
+ settings.maxLeafSize = 1;
+ settings.travCost = 1.0f;
+ settings.intCost = 1.0f;
+ settings.singleThreadThreshold = singleThreadThreshold;
+
+#if ENABLE_DIRECT_SAH_MERGE_BUILDER
+
+ refs.resize(extSize);
+
+ NodeRef root = BVHBuilderBinnedOpenMergeSAH::build<NodeRef,BuildRef>(
+ typename BVH::CreateAlloc(bvh),
+ typename BVH::AABBNode::Create2(),
+ typename BVH::AABBNode::Set2(),
+
+ [&] (const BuildRef* refs, const range<size_t>& range, const FastAllocator::CachedAllocator& alloc) -> NodeRef {
+ assert(range.size() == 1);
+ return (NodeRef) refs[range.begin()].node;
+ },
+ [&] (BuildRef &bref, BuildRef *refs) -> size_t {
+ return openBuildRef(bref,refs);
+ },
+ [&] (size_t dn) { bvh->scene->progressMonitor(0); },
+ refs.data(),extSize,pinfo,settings);
+#else
+ NodeRef root = BVHBuilderBinnedSAH::build<NodeRef>(
+ typename BVH::CreateAlloc(bvh),
+ typename BVH::AABBNode::Create2(),
+ typename BVH::AABBNode::Set2(),
+
+ [&] (const PrimRef* prims, const range<size_t>& range, const FastAllocator::CachedAllocator& alloc) -> NodeRef {
+ assert(range.size() == 1);
+ return (NodeRef) prims[range.begin()].ID();
+ },
+ [&] (size_t dn) { bvh->scene->progressMonitor(0); },
+ prims.data(),pinfo,settings);
+#endif
+
+
+ bvh->set(root,LBBox3fa(pinfo.geomBounds),numPrimitives);
+ }
+ }
+ }
+
+ bvh->alloc.cleanup();
+ bvh->postBuild(t0);
+#if PROFILE
+ double d1 = getSeconds();
+ std::cout << "TOP_LEVEL OPENING/REBUILD TIME " << 1000.0*(d1-d0) << " ms" << std::endl;
+#endif
+ }
+
+ }
+
+ template<int N, typename Mesh, typename Primitive>
+ void BVHNBuilderTwoLevel<N,Mesh,Primitive>::deleteGeometry(size_t geomID)
+ {
+ if (geomID >= bvh->objects.size()) return;
+ if (builders[geomID]) builders[geomID].reset();
+ delete bvh->objects [geomID]; bvh->objects [geomID] = nullptr;
+ }
+
+ template<int N, typename Mesh, typename Primitive>
+ void BVHNBuilderTwoLevel<N,Mesh,Primitive>::clear()
+ {
+ for (size_t i=0; i<bvh->objects.size(); i++)
+ if (bvh->objects[i]) bvh->objects[i]->clear();
+
+ for (size_t i=0; i<builders.size(); i++)
+ if (builders[i]) builders[i].reset();
+
+ refs.clear();
+ }
+
+ template<int N, typename Mesh, typename Primitive>
+ void BVHNBuilderTwoLevel<N,Mesh,Primitive>::open_sequential(const size_t extSize)
+ {
+ if (refs.size() == 0)
+ return;
+
+ refs.reserve(extSize);
+
+#if 1
+ for (size_t i=0;i<refs.size();i++)
+ {
+ NodeRef ref = refs[i].node;
+ if (ref.isAABBNode())
+ BVH::prefetch(ref);
+ }
+#endif
+
+ std::make_heap(refs.begin(),refs.end());
+ while (refs.size()+N-1 <= extSize)
+ {
+ std::pop_heap (refs.begin(),refs.end());
+ NodeRef ref = refs.back().node;
+ if (ref.isLeaf()) break;
+ refs.pop_back();
+
+ AABBNode* node = ref.getAABBNode();
+ for (size_t i=0; i<N; i++) {
+ if (node->child(i) == BVH::emptyNode) continue;
+ refs.push_back(BuildRef(node->bounds(i),node->child(i)));
+
+#if 1
+ NodeRef ref_pre = node->child(i);
+ if (ref_pre.isAABBNode())
+ ref_pre.prefetch();
+#endif
+ std::push_heap (refs.begin(),refs.end());
+ }
+ }
+ }
+
+ template<int N, typename Mesh, typename Primitive>
+ void BVHNBuilderTwoLevel<N,Mesh,Primitive>::setupSmallBuildRefBuilder (size_t objectID, Mesh const * const /*mesh*/)
+ {
+ if (builders[objectID] == nullptr || // new mesh
+ dynamic_cast<RefBuilderSmall*>(builders[objectID].get()) == nullptr) // size change resulted in large->small change
+ {
+ builders[objectID].reset (new RefBuilderSmall(objectID));
+ }
+ }
+
+ template<int N, typename Mesh, typename Primitive>
+ void BVHNBuilderTwoLevel<N,Mesh,Primitive>::setupLargeBuildRefBuilder (size_t objectID, Mesh const * const mesh)
+ {
+ if (bvh->objects[objectID] == nullptr || // new mesh
+ builders[objectID]->meshQualityChanged (mesh->quality) || // changed build quality
+ dynamic_cast<RefBuilderLarge*>(builders[objectID].get()) == nullptr) // size change resulted in small->large change
+ {
+ Builder* builder = nullptr;
+ delete bvh->objects[objectID];
+ createMeshAccel(objectID, builder);
+ builders[objectID].reset (new RefBuilderLarge(objectID, builder, mesh->quality));
+ }
+ }
+
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ Builder* BVH4BuilderTwoLevelTriangle4MeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
+ }
+ Builder* BVH4BuilderTwoLevelTriangle4vMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4v>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
+ }
+ Builder* BVH4BuilderTwoLevelTriangle4iMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
+ }
+#endif
+
+#if defined(EMBREE_GEOMETRY_QUAD)
+ Builder* BVH4BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<4,QuadMesh,Quad4v>((BVH4*)bvh,scene,QuadMesh::geom_type,useMortonBuilder);
+ }
+#endif
+
+#if defined(EMBREE_GEOMETRY_USER)
+ Builder* BVH4BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<4,UserGeometry,Object>((BVH4*)bvh,scene,UserGeometry::geom_type,useMortonBuilder);
+ }
+#endif
+
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ Builder* BVH4BuilderTwoLevelInstanceSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,gtype,useMortonBuilder);
+ }
+#endif
+
+#if defined(__AVX__)
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ Builder* BVH8BuilderTwoLevelTriangle4MeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
+ }
+ Builder* BVH8BuilderTwoLevelTriangle4vMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4v>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
+ }
+ Builder* BVH8BuilderTwoLevelTriangle4iMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder);
+ }
+#endif
+
+#if defined(EMBREE_GEOMETRY_QUAD)
+ Builder* BVH8BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<8,QuadMesh,Quad4v>((BVH8*)bvh,scene,QuadMesh::geom_type,useMortonBuilder);
+ }
+#endif
+
+#if defined(EMBREE_GEOMETRY_USER)
+ Builder* BVH8BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<8,UserGeometry,Object>((BVH8*)bvh,scene,UserGeometry::geom_type,useMortonBuilder);
+ }
+#endif
+
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ Builder* BVH8BuilderTwoLevelInstanceSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder) {
+ return new BVHNBuilderTwoLevel<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,gtype,useMortonBuilder);
+ }
+#endif
+
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder_twolevel.h b/thirdparty/embree/kernels/bvh/bvh_builder_twolevel.h
new file mode 100644
index 0000000000..dc7ec7d278
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder_twolevel.h
@@ -0,0 +1,263 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>
+
+#include "bvh_builder_twolevel_internal.h"
+#include "bvh.h"
+#include "../common/primref.h"
+#include "../builders/priminfo.h"
+#include "../builders/primrefgen.h"
+
+/* new open/merge builder */
+#define ENABLE_DIRECT_SAH_MERGE_BUILDER 1
+#define ENABLE_OPEN_SEQUENTIAL 0
+#define SPLIT_MEMORY_RESERVE_FACTOR 1000
+#define SPLIT_MEMORY_RESERVE_SCALE 2
+#define SPLIT_MIN_EXT_SPACE 1000
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N, typename Mesh, typename Primitive>
+ class BVHNBuilderTwoLevel : public Builder
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::AABBNode AABBNode;
+ typedef typename BVH::NodeRef NodeRef;
+
+ __forceinline static bool isSmallGeometry(Mesh* mesh) {
+ return mesh->size() <= 4;
+ }
+
+ public:
+
+ typedef void (*createMeshAccelTy)(Scene* scene, unsigned int geomID, AccelData*& accel, Builder*& builder);
+
+ struct BuildRef : public PrimRef
+ {
+ public:
+ __forceinline BuildRef () {}
+
+ __forceinline BuildRef (const BBox3fa& bounds, NodeRef node)
+ : PrimRef(bounds,(size_t)node), node(node)
+ {
+ if (node.isLeaf())
+ bounds_area = 0.0f;
+ else
+ bounds_area = area(this->bounds());
+ }
+
+ /* used by the open/merge bvh builder */
+ __forceinline BuildRef (const BBox3fa& bounds, NodeRef node, const unsigned int geomID, const unsigned int numPrimitives)
+ : PrimRef(bounds,geomID,numPrimitives), node(node)
+ {
+ /* important for relative buildref ordering */
+ if (node.isLeaf())
+ bounds_area = 0.0f;
+ else
+ bounds_area = area(this->bounds());
+ }
+
+ __forceinline size_t size() const {
+ return primID();
+ }
+
+ friend bool operator< (const BuildRef& a, const BuildRef& b) {
+ return a.bounds_area < b.bounds_area;
+ }
+
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const BuildRef& ref) {
+ return cout << "{ lower = " << ref.lower << ", upper = " << ref.upper << ", center2 = " << ref.center2() << ", geomID = " << ref.geomID() << ", numPrimitives = " << ref.numPrimitives() << ", bounds_area = " << ref.bounds_area << " }";
+ }
+
+ __forceinline unsigned int numPrimitives() const { return primID(); }
+
+ public:
+ NodeRef node;
+ float bounds_area;
+ };
+
+
+ __forceinline size_t openBuildRef(BuildRef &bref, BuildRef *const refs) {
+ if (bref.node.isLeaf())
+ {
+ refs[0] = bref;
+ return 1;
+ }
+ NodeRef ref = bref.node;
+ unsigned int geomID = bref.geomID();
+ unsigned int numPrims = max((unsigned int)bref.numPrimitives() / N,(unsigned int)1);
+ AABBNode* node = ref.getAABBNode();
+ size_t n = 0;
+ for (size_t i=0; i<N; i++) {
+ if (node->child(i) == BVH::emptyNode) continue;
+ refs[i] = BuildRef(node->bounds(i),node->child(i),geomID,numPrims);
+ n++;
+ }
+ assert(n > 1);
+ return n;
+ }
+
+ /*! Constructor. */
+ BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, Geometry::GTypeMask gtype = Mesh::geom_type, bool useMortonBuilder = false, const size_t singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD);
+
+ /*! Destructor */
+ ~BVHNBuilderTwoLevel ();
+
+ /*! builder entry point */
+ void build();
+ void deleteGeometry(size_t geomID);
+ void clear();
+
+ void open_sequential(const size_t extSize);
+
+ private:
+
+ class RefBuilderBase {
+ public:
+ virtual ~RefBuilderBase () {}
+ virtual void attachBuildRefs (BVHNBuilderTwoLevel* builder) = 0;
+ virtual bool meshQualityChanged (RTCBuildQuality currQuality) = 0;
+ };
+
+ class RefBuilderSmall : public RefBuilderBase {
+ public:
+
+ RefBuilderSmall (size_t objectID)
+ : objectID_ (objectID) {}
+
+ void attachBuildRefs (BVHNBuilderTwoLevel* topBuilder) {
+
+ Mesh* mesh = topBuilder->scene->template getSafe<Mesh>(objectID_);
+ size_t meshSize = mesh->size();
+ assert(isSmallGeometry(mesh));
+
+ mvector<PrimRef> prefs(topBuilder->scene->device, meshSize);
+ auto pinfo = createPrimRefArray(mesh,objectID_,meshSize,prefs,topBuilder->bvh->scene->progressInterface);
+
+ size_t begin=0;
+ while (begin < pinfo.size())
+ {
+ Primitive* accel = (Primitive*) topBuilder->bvh->alloc.getCachedAllocator().malloc1(sizeof(Primitive),BVH::byteAlignment);
+ typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,1);
+ accel->fill(prefs.data(),begin,pinfo.size(),topBuilder->bvh->scene);
+
+ /* create build primitive */
+#if ENABLE_DIRECT_SAH_MERGE_BUILDER
+ topBuilder->refs[topBuilder->nextRef++] = BVHNBuilderTwoLevel::BuildRef(pinfo.geomBounds,node,(unsigned int)objectID_,1);
+#else
+ topBuilder->refs[topBuilder->nextRef++] = BVHNBuilderTwoLevel::BuildRef(pinfo.geomBounds,node);
+#endif
+ }
+ assert(begin == pinfo.size());
+ }
+
+ bool meshQualityChanged (RTCBuildQuality /*currQuality*/) {
+ return false;
+ }
+
+ size_t objectID_;
+ };
+
+ class RefBuilderLarge : public RefBuilderBase {
+ public:
+
+ RefBuilderLarge (size_t objectID, const Ref<Builder>& builder, RTCBuildQuality quality)
+ : objectID_ (objectID), builder_ (builder), quality_ (quality) {}
+
+ void attachBuildRefs (BVHNBuilderTwoLevel* topBuilder)
+ {
+ BVH* object = topBuilder->getBVH(objectID_); assert(object);
+
+ /* build object if it got modified */
+ if (topBuilder->isGeometryModified(objectID_))
+ builder_->build();
+
+ /* create build primitive */
+ if (!object->getBounds().empty())
+ {
+#if ENABLE_DIRECT_SAH_MERGE_BUILDER
+ Mesh* mesh = topBuilder->getMesh(objectID_);
+ topBuilder->refs[topBuilder->nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root,(unsigned int)objectID_,(unsigned int)mesh->size());
+#else
+ topBuilder->refs[topBuilder->nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root);
+#endif
+ }
+ }
+
+ bool meshQualityChanged (RTCBuildQuality currQuality) {
+ return currQuality != quality_;
+ }
+
+ private:
+ size_t objectID_;
+ Ref<Builder> builder_;
+ RTCBuildQuality quality_;
+ };
+
+ void setupLargeBuildRefBuilder (size_t objectID, Mesh const * const mesh);
+ void setupSmallBuildRefBuilder (size_t objectID, Mesh const * const mesh);
+
+ BVH* getBVH (size_t objectID) {
+ return this->bvh->objects[objectID];
+ }
+ Mesh* getMesh (size_t objectID) {
+ return this->scene->template getSafe<Mesh>(objectID);
+ }
+ bool isGeometryModified (size_t objectID) {
+ return this->scene->isGeometryModified(objectID);
+ }
+
+ void resizeRefsList ()
+ {
+ size_t num = parallel_reduce (size_t(0), scene->size(), size_t(0),
+ [this](const range<size_t>& r)->size_t {
+ size_t c = 0;
+ for (auto i=r.begin(); i<r.end(); ++i) {
+ Mesh* mesh = scene->getSafe<Mesh>(i);
+ if (mesh == nullptr || mesh->numTimeSteps != 1)
+ continue;
+ size_t meshSize = mesh->size();
+ c += isSmallGeometry(mesh) ? Primitive::blocks(meshSize) : 1;
+ }
+ return c;
+ },
+ std::plus<size_t>()
+ );
+
+ if (refs.size() < num) {
+ refs.resize(num);
+ }
+ }
+
+ void createMeshAccel (size_t geomID, Builder*& builder)
+ {
+ bvh->objects[geomID] = new BVH(Primitive::type,scene);
+ BVH* accel = bvh->objects[geomID];
+ auto mesh = scene->getSafe<Mesh>(geomID);
+ if (nullptr == mesh) {
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"geomID does not return correct type");
+ return;
+ }
+
+ __internal_two_level_builder__::MeshBuilder<N,Mesh,Primitive>()(accel, mesh, geomID, this->gtype, this->useMortonBuilder_, builder);
+ }
+
+ using BuilderList = std::vector<std::unique_ptr<RefBuilderBase>>;
+
+ BuilderList builders;
+ BVH* bvh;
+ Scene* scene;
+ mvector<BuildRef> refs;
+ mvector<PrimRef> prims;
+ std::atomic<int> nextRef;
+ const size_t singleThreadThreshold;
+ Geometry::GTypeMask gtype;
+ bool useMortonBuilder_ = false;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_builder_twolevel_internal.h b/thirdparty/embree/kernels/bvh/bvh_builder_twolevel_internal.h
new file mode 100644
index 0000000000..023b52b780
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_builder_twolevel_internal.h
@@ -0,0 +1,267 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+#include "../geometry/triangle.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/trianglei.h"
+#include "../geometry/quadv.h"
+#include "../geometry/quadi.h"
+#include "../geometry/object.h"
+#include "../geometry/instance.h"
+
+namespace embree
+{
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4MeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4MeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4MeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4vMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Triangle4iMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshBuilderMortonGeneral,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshBuilderSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshRefitSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshBuilderMortonGeneral,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshBuilderSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshBuilderMortonGeneral,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshBuilderSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshRefitSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t)
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vMeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vMeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4vMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iMeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iMeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4iMeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vMeshBuilderMortonGeneral,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vMeshBuilderSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vMeshRefitSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshBuilderMortonGeneral,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshBuilderSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshBuilderMortonGeneral,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshBuilderSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t);
+ DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshRefitSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t)
+
+ namespace isa
+ {
+
+ namespace __internal_two_level_builder__ {
+
+ template<int N, typename Mesh, typename Primitive>
+ struct MortonBuilder {};
+ template<>
+ struct MortonBuilder<4,TriangleMesh,Triangle4> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<4,TriangleMesh,Triangle4v> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<4,TriangleMesh,Triangle4i> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<4,QuadMesh,Quad4v> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<4,UserGeometry,Object> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<4,Instance,InstancePrimitive> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshBuilderMortonGeneral(bvh,mesh,gtype,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<8,TriangleMesh,Triangle4> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<8,TriangleMesh,Triangle4v> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<8,TriangleMesh,Triangle4i> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<8,QuadMesh,Quad4v> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<8,UserGeometry,Object> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshBuilderMortonGeneral(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct MortonBuilder<8,Instance,InstancePrimitive> {
+ MortonBuilder () {}
+ Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshBuilderMortonGeneral(bvh,mesh,gtype,geomID,0);}
+ };
+
+ template<int N, typename Mesh, typename Primitive>
+ struct SAHBuilder {};
+ template<>
+ struct SAHBuilder<4,TriangleMesh,Triangle4> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<4,TriangleMesh,Triangle4v> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<4,TriangleMesh,Triangle4i> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<4,QuadMesh,Quad4v> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<4,UserGeometry,Object> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<4,Instance,InstancePrimitive> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshBuilderSAH(bvh,mesh,gtype,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<8,TriangleMesh,Triangle4> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<8,TriangleMesh,Triangle4v> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<8,TriangleMesh,Triangle4i> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<8,QuadMesh,Quad4v> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<8,UserGeometry,Object> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshBuilderSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct SAHBuilder<8,Instance,InstancePrimitive> {
+ SAHBuilder () {}
+ Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshBuilderSAH(bvh,mesh,gtype,geomID,0);}
+ };
+
+ template<int N, typename Mesh, typename Primitive>
+ struct RefitBuilder {};
+ template<>
+ struct RefitBuilder<4,TriangleMesh,Triangle4> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<4,TriangleMesh,Triangle4v> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<4,TriangleMesh,Triangle4i> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<4,QuadMesh,Quad4v> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<4,UserGeometry,Object> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<4,Instance,InstancePrimitive> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshRefitSAH(bvh,mesh,gtype,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<8,TriangleMesh,Triangle4> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<8,TriangleMesh,Triangle4v> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<8,TriangleMesh,Triangle4i> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<8,QuadMesh,Quad4v> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<8,UserGeometry,Object> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshRefitSAH(bvh,mesh,geomID,0);}
+ };
+ template<>
+ struct RefitBuilder<8,Instance,InstancePrimitive> {
+ RefitBuilder () {}
+ Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshRefitSAH(bvh,mesh,gtype,geomID,0);}
+ };
+
+ template<int N, typename Mesh, typename Primitive>
+ struct MeshBuilder {
+ MeshBuilder () {}
+ void operator () (void* bvh, Mesh* mesh, size_t geomID, Geometry::GTypeMask gtype, bool useMortonBuilder, Builder*& builder) {
+ if(useMortonBuilder) {
+ builder = MortonBuilder<N,Mesh,Primitive>()(bvh,mesh,geomID,gtype);
+ return;
+ }
+ switch (mesh->quality) {
+ case RTC_BUILD_QUALITY_LOW: builder = MortonBuilder<N,Mesh,Primitive>()(bvh,mesh,geomID,gtype); break;
+ case RTC_BUILD_QUALITY_MEDIUM:
+ case RTC_BUILD_QUALITY_HIGH: builder = SAHBuilder<N,Mesh,Primitive>()(bvh,mesh,geomID,gtype); break;
+ case RTC_BUILD_QUALITY_REFIT: builder = RefitBuilder<N,Mesh,Primitive>()(bvh,mesh,geomID,gtype); break;
+ default: throw_RTCError(RTC_ERROR_UNKNOWN,"invalid build quality");
+ }
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/thirdparty/embree/kernels/bvh/bvh_collider.cpp b/thirdparty/embree/kernels/bvh/bvh_collider.cpp
new file mode 100644
index 0000000000..9428c0b88e
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_collider.cpp
@@ -0,0 +1,375 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh_collider.h"
+#include "../geometry/triangle_triangle_intersector.h"
+
+namespace embree
+{
+ namespace isa
+ {
+#define CSTAT(x)
+
+ size_t parallel_depth_threshold = 3;
+ CSTAT(std::atomic<size_t> bvh_collide_traversal_steps(0));
+ CSTAT(std::atomic<size_t> bvh_collide_leaf_pairs(0));
+ CSTAT(std::atomic<size_t> bvh_collide_leaf_iterations(0));
+ CSTAT(std::atomic<size_t> bvh_collide_prim_intersections1(0));
+ CSTAT(std::atomic<size_t> bvh_collide_prim_intersections2(0));
+ CSTAT(std::atomic<size_t> bvh_collide_prim_intersections3(0));
+ CSTAT(std::atomic<size_t> bvh_collide_prim_intersections4(0));
+ CSTAT(std::atomic<size_t> bvh_collide_prim_intersections5(0));
+ CSTAT(std::atomic<size_t> bvh_collide_prim_intersections(0));
+
+ struct Collision
+ {
+ __forceinline Collision() {}
+
+ __forceinline Collision (unsigned geomID0, unsigned primID0, unsigned geomID1, unsigned primID1)
+ : geomID0(geomID0), primID0(primID0), geomID1(geomID1), primID1(primID1) {}
+
+ unsigned geomID0;
+ unsigned primID0;
+ unsigned geomID1;
+ unsigned primID1;
+ };
+
+ template<int N>
+ __forceinline size_t overlap(const BBox3fa& box0, const typename BVHN<N>::AABBNode& node1)
+ {
+ const vfloat<N> lower_x = max(vfloat<N>(box0.lower.x),node1.lower_x);
+ const vfloat<N> lower_y = max(vfloat<N>(box0.lower.y),node1.lower_y);
+ const vfloat<N> lower_z = max(vfloat<N>(box0.lower.z),node1.lower_z);
+ const vfloat<N> upper_x = min(vfloat<N>(box0.upper.x),node1.upper_x);
+ const vfloat<N> upper_y = min(vfloat<N>(box0.upper.y),node1.upper_y);
+ const vfloat<N> upper_z = min(vfloat<N>(box0.upper.z),node1.upper_z);
+ return movemask((lower_x <= upper_x) & (lower_y <= upper_y) & (lower_z <= upper_z));
+ }
+
+ template<int N>
+ __forceinline size_t overlap(const BBox3fa& box0, const BBox<Vec3<vfloat<N>>>& box1)
+ {
+ const vfloat<N> lower_x = max(vfloat<N>(box0.lower.x),box1.lower.x);
+ const vfloat<N> lower_y = max(vfloat<N>(box0.lower.y),box1.lower.y);
+ const vfloat<N> lower_z = max(vfloat<N>(box0.lower.z),box1.lower.z);
+ const vfloat<N> upper_x = min(vfloat<N>(box0.upper.x),box1.upper.x);
+ const vfloat<N> upper_y = min(vfloat<N>(box0.upper.y),box1.upper.y);
+ const vfloat<N> upper_z = min(vfloat<N>(box0.upper.z),box1.upper.z);
+ return movemask((lower_x <= upper_x) & (lower_y <= upper_y) & (lower_z <= upper_z));
+ }
+
+ template<int N>
+ __forceinline size_t overlap(const BBox<Vec3<vfloat<N>>>& box0, size_t i, const BBox<Vec3<vfloat<N>>>& box1)
+ {
+ const vfloat<N> lower_x = max(vfloat<N>(box0.lower.x[i]),box1.lower.x);
+ const vfloat<N> lower_y = max(vfloat<N>(box0.lower.y[i]),box1.lower.y);
+ const vfloat<N> lower_z = max(vfloat<N>(box0.lower.z[i]),box1.lower.z);
+ const vfloat<N> upper_x = min(vfloat<N>(box0.upper.x[i]),box1.upper.x);
+ const vfloat<N> upper_y = min(vfloat<N>(box0.upper.y[i]),box1.upper.y);
+ const vfloat<N> upper_z = min(vfloat<N>(box0.upper.z[i]),box1.upper.z);
+ return movemask((lower_x <= upper_x) & (lower_y <= upper_y) & (lower_z <= upper_z));
+ }
+
+ bool intersect_triangle_triangle (Scene* scene0, unsigned geomID0, unsigned primID0, Scene* scene1, unsigned geomID1, unsigned primID1)
+ {
+ CSTAT(bvh_collide_prim_intersections1++);
+ const TriangleMesh* mesh0 = scene0->get<TriangleMesh>(geomID0);
+ const TriangleMesh* mesh1 = scene1->get<TriangleMesh>(geomID1);
+ const TriangleMesh::Triangle& tri0 = mesh0->triangle(primID0);
+ const TriangleMesh::Triangle& tri1 = mesh1->triangle(primID1);
+
+ /* special culling for scene intersection with itself */
+ if (scene0 == scene1 && geomID0 == geomID1)
+ {
+ /* ignore self intersections */
+ if (primID0 == primID1)
+ return false;
+ }
+ CSTAT(bvh_collide_prim_intersections2++);
+
+ if (scene0 == scene1 && geomID0 == geomID1)
+ {
+ /* ignore intersection with topological neighbors */
+ const vint4 t0(tri0.v[0],tri0.v[1],tri0.v[2],tri0.v[2]);
+ if (any(vint4(tri1.v[0]) == t0)) return false;
+ if (any(vint4(tri1.v[1]) == t0)) return false;
+ if (any(vint4(tri1.v[2]) == t0)) return false;
+ }
+ CSTAT(bvh_collide_prim_intersections3++);
+
+ const Vec3fa a0 = mesh0->vertex(tri0.v[0]);
+ const Vec3fa a1 = mesh0->vertex(tri0.v[1]);
+ const Vec3fa a2 = mesh0->vertex(tri0.v[2]);
+ const Vec3fa b0 = mesh1->vertex(tri1.v[0]);
+ const Vec3fa b1 = mesh1->vertex(tri1.v[1]);
+ const Vec3fa b2 = mesh1->vertex(tri1.v[2]);
+
+ return TriangleTriangleIntersector::intersect_triangle_triangle(a0,a1,a2,b0,b1,b2);
+ }
+
+ template<int N>
+ __forceinline void BVHNColliderUserGeom<N>::processLeaf(NodeRef node0, NodeRef node1)
+ {
+ Collision collisions[16];
+ size_t num_collisions = 0;
+
+ size_t N0; Object* leaf0 = (Object*) node0.leaf(N0);
+ size_t N1; Object* leaf1 = (Object*) node1.leaf(N1);
+ for (size_t i=0; i<N0; i++) {
+ for (size_t j=0; j<N1; j++) {
+ const unsigned geomID0 = leaf0[i].geomID();
+ const unsigned primID0 = leaf0[i].primID();
+ const unsigned geomID1 = leaf1[j].geomID();
+ const unsigned primID1 = leaf1[j].primID();
+ if (this->scene0 == this->scene1 && geomID0 == geomID1 && primID0 == primID1) continue;
+ collisions[num_collisions++] = Collision(geomID0,primID0,geomID1,primID1);
+ if (num_collisions == 16) {
+ this->callback(this->userPtr,(RTCCollision*)&collisions,num_collisions);
+ num_collisions = 0;
+ }
+ }
+ }
+ if (num_collisions)
+ this->callback(this->userPtr,(RTCCollision*)&collisions,num_collisions);
+ }
+
+ template<int N>
+ void BVHNCollider<N>::collide_recurse(NodeRef ref0, const BBox3fa& bounds0, NodeRef ref1, const BBox3fa& bounds1, size_t depth0, size_t depth1)
+ {
+ CSTAT(bvh_collide_traversal_steps++);
+ if (unlikely(ref0.isLeaf())) {
+ if (unlikely(ref1.isLeaf())) {
+ CSTAT(bvh_collide_leaf_pairs++);
+ processLeaf(ref0,ref1);
+ return;
+ } else goto recurse_node1;
+
+ } else {
+ if (unlikely(ref1.isLeaf())) {
+ goto recurse_node0;
+ } else {
+ if (area(bounds0) > area(bounds1)) {
+ goto recurse_node0;
+ }
+ else {
+ goto recurse_node1;
+ }
+ }
+ }
+
+ {
+ recurse_node0:
+ AABBNode* node0 = ref0.getAABBNode();
+ size_t mask = overlap<N>(bounds1,*node0);
+ //for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
+ //for (size_t i=0; i<N; i++) {
+#if 0
+ if (depth0 < parallel_depth_threshold)
+ {
+ parallel_for(size_t(N), [&] ( size_t i ) {
+ if (mask & ( 1 << i)) {
+ BVHN<N>::prefetch(node0->child(i),BVH_FLAG_ALIGNED_NODE);
+ collide_recurse(node0->child(i),node0->bounds(i),ref1,bounds1,depth0+1,depth1);
+ }
+ });
+ }
+ else
+#endif
+ {
+ for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
+ BVHN<N>::prefetch(node0->child(i),BVH_FLAG_ALIGNED_NODE);
+ collide_recurse(node0->child(i),node0->bounds(i),ref1,bounds1,depth0+1,depth1);
+ }
+ }
+ return;
+ }
+
+ {
+ recurse_node1:
+ AABBNode* node1 = ref1.getAABBNode();
+ size_t mask = overlap<N>(bounds0,*node1);
+ //for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
+ //for (size_t i=0; i<N; i++) {
+#if 0
+ if (depth1 < parallel_depth_threshold)
+ {
+ parallel_for(size_t(N), [&] ( size_t i ) {
+ if (mask & ( 1 << i)) {
+ BVHN<N>::prefetch(node1->child(i),BVH_FLAG_ALIGNED_NODE);
+ collide_recurse(ref0,bounds0,node1->child(i),node1->bounds(i),depth0,depth1+1);
+ }
+ });
+ }
+ else
+#endif
+ {
+ for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
+ BVHN<N>::prefetch(node1->child(i),BVH_FLAG_ALIGNED_NODE);
+ collide_recurse(ref0,bounds0,node1->child(i),node1->bounds(i),depth0,depth1+1);
+ }
+ }
+ return;
+ }
+ }
+
+ template<int N>
+ void BVHNCollider<N>::split(const CollideJob& job, jobvector& jobs)
+ {
+ if (unlikely(job.ref0.isLeaf())) {
+ if (unlikely(job.ref1.isLeaf())) {
+ jobs.push_back(job);
+ return;
+ } else goto recurse_node1;
+ } else {
+ if (unlikely(job.ref1.isLeaf())) {
+ goto recurse_node0;
+ } else {
+ if (area(job.bounds0) > area(job.bounds1)) {
+ goto recurse_node0;
+ }
+ else {
+ goto recurse_node1;
+ }
+ }
+ }
+
+ {
+ recurse_node0:
+ const AABBNode* node0 = job.ref0.getAABBNode();
+ size_t mask = overlap<N>(job.bounds1,*node0);
+ for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
+ jobs.push_back(CollideJob(node0->child(i),node0->bounds(i),job.depth0+1,job.ref1,job.bounds1,job.depth1));
+ }
+ return;
+ }
+
+ {
+ recurse_node1:
+ const AABBNode* node1 = job.ref1.getAABBNode();
+ size_t mask = overlap<N>(job.bounds0,*node1);
+ for (size_t m=mask, i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) {
+ jobs.push_back(CollideJob(job.ref0,job.bounds0,job.depth0,node1->child(i),node1->bounds(i),job.depth1+1));
+ }
+ return;
+ }
+ }
+
+ template<int N>
+ void BVHNCollider<N>::collide_recurse_entry(NodeRef ref0, const BBox3fa& bounds0, NodeRef ref1, const BBox3fa& bounds1)
+ {
+ CSTAT(bvh_collide_traversal_steps = 0);
+ CSTAT(bvh_collide_leaf_pairs = 0);
+ CSTAT(bvh_collide_leaf_iterations = 0);
+ CSTAT(bvh_collide_prim_intersections1 = 0);
+ CSTAT(bvh_collide_prim_intersections2 = 0);
+ CSTAT(bvh_collide_prim_intersections3 = 0);
+ CSTAT(bvh_collide_prim_intersections4 = 0);
+ CSTAT(bvh_collide_prim_intersections5 = 0);
+ CSTAT(bvh_collide_prim_intersections = 0);
+#if 0
+ collide_recurse(ref0,bounds0,ref1,bounds1,0,0);
+#else
+ const int M = 2048;
+ jobvector jobs[2];
+ jobs[0].reserve(M);
+ jobs[1].reserve(M);
+ jobs[0].push_back(CollideJob(ref0,bounds0,0,ref1,bounds1,0));
+ int source = 0;
+ int target = 1;
+
+ /* try to split job until job list is full */
+ while (jobs[source].size()+8 <= M)
+ {
+ for (size_t i=0; i<jobs[source].size(); i++)
+ {
+ const CollideJob& job = jobs[source][i];
+ size_t remaining = jobs[source].size()-i;
+ if (jobs[target].size()+remaining+8 > M) {
+ jobs[target].push_back(job);
+ } else {
+ split(job,jobs[target]);
+ }
+ }
+
+ /* stop splitting jobs if we reached only leaves and cannot make progress anymore */
+ if (jobs[target].size() == jobs[source].size())
+ break;
+
+ jobs[source].resize(0);
+ std::swap(source,target);
+ }
+
+ /* parallel processing of all jobs */
+ parallel_for(size_t(jobs[source].size()), [&] ( size_t i ) {
+ CollideJob& j = jobs[source][i];
+ collide_recurse(j.ref0,j.bounds0,j.ref1,j.bounds1,j.depth0,j.depth1);
+ });
+
+
+#endif
+ CSTAT(PRINT(bvh_collide_traversal_steps));
+ CSTAT(PRINT(bvh_collide_leaf_pairs));
+ CSTAT(PRINT(bvh_collide_leaf_iterations));
+ CSTAT(PRINT(bvh_collide_prim_intersections1));
+ CSTAT(PRINT(bvh_collide_prim_intersections2));
+ CSTAT(PRINT(bvh_collide_prim_intersections3));
+ CSTAT(PRINT(bvh_collide_prim_intersections4));
+ CSTAT(PRINT(bvh_collide_prim_intersections5));
+ CSTAT(PRINT(bvh_collide_prim_intersections));
+ }
+
+ template<int N>
+ void BVHNColliderUserGeom<N>::collide(BVH* __restrict__ bvh0, BVH* __restrict__ bvh1, RTCCollideFunc callback, void* userPtr)
+ {
+ BVHNColliderUserGeom<N>(bvh0->scene,bvh1->scene,callback,userPtr).
+ collide_recurse_entry(bvh0->root,bvh0->bounds.bounds(),bvh1->root,bvh1->bounds.bounds());
+ }
+
+#if defined (EMBREE_LOWEST_ISA)
+ struct collision_regression_test : public RegressionTest
+ {
+ collision_regression_test(const char* name) : RegressionTest(name) {
+ registerRegressionTest(this);
+ }
+
+ bool run ()
+ {
+ bool passed = true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(-0.008815f, 0.041848f, -2.49875e-06f), Vec3fa(-0.008276f, 0.053318f, -2.49875e-06f), Vec3fa(0.003023f, 0.048969f, -2.49875e-06f),
+ Vec3fa(0.00245f, 0.037612f, -2.49875e-06f), Vec3fa(0.01434f, 0.042634f, -2.49875e-06f), Vec3fa(0.013499f, 0.031309f, -2.49875e-06f)) == false;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,1),Vec3fa(1,0,1),Vec3fa(0,1,1)) == false;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,1),Vec3fa(1,0,0),Vec3fa(0,1,0)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,0),Vec3fa(1,0,1),Vec3fa(0,1,1)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,0.1f,0),Vec3fa(1,0,1),Vec3fa(0,1,1)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,0.1f,-0.1f),Vec3fa(1,0,1),Vec3fa(0,1,1)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0,0,0),Vec3fa(0.5f,0,0),Vec3fa(0,0.5f,0)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,0.1f,0),Vec3fa(0.5f,0,0),Vec3fa(0,0.5f,0)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,0.1f,0),Vec3fa(0.5f,0.1f,0),Vec3fa(0.1f,0.5f,0)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(0.1f,-0.1f,0),Vec3fa(0.5f,0.1f,0),Vec3fa(0.1f,0.5f,0)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0), Vec3fa(-0.1f,0.1f,0),Vec3fa(0.5f,0.1f,0),Vec3fa(0.1f,0.5f,0)) == true;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0),
+ Vec3fa(-1,1,0) + Vec3fa(0,0,0),Vec3fa(-1,1,0) + Vec3fa(0.1f,0,0),Vec3fa(-1,1,0) + Vec3fa(0,0.1f,0)) == false;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0),
+ Vec3fa( 2,0.5f,0) + Vec3fa(0,0,0),Vec3fa( 2,0.5f,0) + Vec3fa(0.1f,0,0),Vec3fa( 2,0.5f,0) + Vec3fa(0,0.1f,0)) == false;
+ passed &= TriangleTriangleIntersector::intersect_triangle_triangle (Vec3fa(0,0,0),Vec3fa(1,0,0),Vec3fa(0,1,0),
+ Vec3fa(0.5f,-2.0f,0) + Vec3fa(0,0,0),Vec3fa(0.5f,-2.0f,0) + Vec3fa(0.1f,0,0),Vec3fa(0.5f,-2.0f,0) + Vec3fa(0,0.1f,0)) == false;
+ return passed;
+ }
+ };
+
+ collision_regression_test collision_regression("collision_regression_test");
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Collider Definitions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ DEFINE_COLLIDER(BVH4ColliderUserGeom,BVHNColliderUserGeom<4>);
+
+#if defined(__AVX__)
+ DEFINE_COLLIDER(BVH8ColliderUserGeom,BVHNColliderUserGeom<8>);
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_collider.h b/thirdparty/embree/kernels/bvh/bvh_collider.h
new file mode 100644
index 0000000000..3c42f211c1
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_collider.h
@@ -0,0 +1,72 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/object.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N>
+ class BVHNCollider
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::AABBNode AABBNode;
+
+ struct CollideJob
+ {
+ CollideJob () {}
+
+ CollideJob (NodeRef ref0, const BBox3fa& bounds0, size_t depth0,
+ NodeRef ref1, const BBox3fa& bounds1, size_t depth1)
+ : ref0(ref0), bounds0(bounds0), depth0(depth0), ref1(ref1), bounds1(bounds1), depth1(depth1) {}
+
+ NodeRef ref0;
+ BBox3fa bounds0;
+ size_t depth0;
+ NodeRef ref1;
+ BBox3fa bounds1;
+ size_t depth1;
+ };
+
+ typedef vector_t<CollideJob, aligned_allocator<CollideJob,16>> jobvector;
+
+ void split(const CollideJob& job, jobvector& jobs);
+
+ public:
+ __forceinline BVHNCollider (Scene* scene0, Scene* scene1, RTCCollideFunc callback, void* userPtr)
+ : scene0(scene0), scene1(scene1), callback(callback), userPtr(userPtr) {}
+
+ public:
+ virtual void processLeaf(NodeRef leaf0, NodeRef leaf1) = 0;
+ void collide_recurse(NodeRef node0, const BBox3fa& bounds0, NodeRef node1, const BBox3fa& bounds1, size_t depth0, size_t depth1);
+ void collide_recurse_entry(NodeRef node0, const BBox3fa& bounds0, NodeRef node1, const BBox3fa& bounds1);
+
+ protected:
+ Scene* scene0;
+ Scene* scene1;
+ RTCCollideFunc callback;
+ void* userPtr;
+ };
+
+ template<int N>
+ class BVHNColliderUserGeom : public BVHNCollider<N>
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::AABBNode AABBNode;
+
+ __forceinline BVHNColliderUserGeom (Scene* scene0, Scene* scene1, RTCCollideFunc callback, void* userPtr)
+ : BVHNCollider<N>(scene0,scene1,callback,userPtr) {}
+
+ virtual void processLeaf(NodeRef leaf0, NodeRef leaf1);
+ public:
+ static void collide(BVH* __restrict__ bvh0, BVH* __restrict__ bvh1, RTCCollideFunc callback, void* userPtr);
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_factory.h b/thirdparty/embree/kernels/bvh/bvh_factory.h
new file mode 100644
index 0000000000..453d455bd9
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_factory.h
@@ -0,0 +1,21 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../bvh/bvh.h"
+#include "../common/isa.h"
+#include "../common/accel.h"
+#include "../common/scene.h"
+#include "../geometry/curve_intersector_virtual.h"
+
+namespace embree
+{
+ /*! BVH instantiations */
+ class BVHFactory
+ {
+ public:
+ enum class BuildVariant { STATIC, DYNAMIC, HIGH_QUALITY };
+ enum class IntersectVariant { FAST, ROBUST };
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_intersector1.cpp b/thirdparty/embree/kernels/bvh/bvh_intersector1.cpp
new file mode 100644
index 0000000000..9594f402c3
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_intersector1.cpp
@@ -0,0 +1,321 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh_intersector1.h"
+#include "node_intersector1.h"
+#include "bvh_traverser1.h"
+
+#include "../geometry/intersector_iterators.h"
+#include "../geometry/triangle_intersector.h"
+#include "../geometry/trianglev_intersector.h"
+#include "../geometry/trianglev_mb_intersector.h"
+#include "../geometry/trianglei_intersector.h"
+#include "../geometry/quadv_intersector.h"
+#include "../geometry/quadi_intersector.h"
+#include "../geometry/curveNv_intersector.h"
+#include "../geometry/curveNi_intersector.h"
+#include "../geometry/curveNi_mb_intersector.h"
+#include "../geometry/linei_intersector.h"
+#include "../geometry/subdivpatch1_intersector.h"
+#include "../geometry/object_intersector.h"
+#include "../geometry/instance_intersector.h"
+#include "../geometry/subgrid_intersector.h"
+#include "../geometry/subgrid_mb_intersector.h"
+#include "../geometry/curve_intersector_virtual.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N, int types, bool robust, typename PrimitiveIntersector1>
+ void BVHNIntersector1<N, types, robust, PrimitiveIntersector1>::intersect(const Accel::Intersectors* __restrict__ This,
+ RayHit& __restrict__ ray,
+ IntersectContext* __restrict__ context)
+ {
+ const BVH* __restrict__ bvh = (const BVH*)This->ptr;
+
+ /* we may traverse an empty BVH in case all geometry was invalid */
+ if (bvh->root == BVH::emptyNode)
+ return;
+
+ /* perform per ray precalculations required by the primitive intersector */
+ Precalculations pre(ray, bvh);
+
+ /* stack state */
+ StackItemT<NodeRef> stack[stackSize]; // stack of nodes
+ StackItemT<NodeRef>* stackPtr = stack+1; // current stack pointer
+ StackItemT<NodeRef>* stackEnd = stack+stackSize;
+ stack[0].ptr = bvh->root;
+ stack[0].dist = neg_inf;
+
+ if (bvh->root == BVH::emptyNode)
+ return;
+
+ /* filter out invalid rays */
+#if defined(EMBREE_IGNORE_INVALID_RAYS)
+ if (!ray.valid()) return;
+#endif
+ /* verify correct input */
+ assert(ray.valid());
+ assert(ray.tnear() >= 0.0f);
+ assert(!(types & BVH_MB) || (ray.time() >= 0.0f && ray.time() <= 1.0f));
+
+ /* load the ray into SIMD registers */
+ TravRay<N,robust> tray(ray.org, ray.dir, max(ray.tnear(), 0.0f), max(ray.tfar, 0.0f));
+
+ /* initialize the node traverser */
+ BVHNNodeTraverser1Hit<N, types> nodeTraverser;
+
+ /* pop loop */
+ while (true) pop:
+ {
+ /* pop next node */
+ if (unlikely(stackPtr == stack)) break;
+ stackPtr--;
+ NodeRef cur = NodeRef(stackPtr->ptr);
+
+ /* if popped node is too far, pop next one */
+ if (unlikely(*(float*)&stackPtr->dist > ray.tfar))
+ continue;
+
+ /* downtraversal loop */
+ while (true)
+ {
+ /* intersect node */
+ size_t mask; vfloat<N> tNear;
+ STAT3(normal.trav_nodes,1,1,1);
+ bool nodeIntersected = BVHNNodeIntersector1<N, types, robust>::intersect(cur, tray, ray.time(), tNear, mask);
+ if (unlikely(!nodeIntersected)) { STAT3(normal.trav_nodes,-1,-1,-1); break; }
+
+ /* if no child is hit, pop next node */
+ if (unlikely(mask == 0))
+ goto pop;
+
+ /* select next child and push other children */
+ nodeTraverser.traverseClosestHit(cur, mask, tNear, stackPtr, stackEnd);
+ }
+
+ /* this is a leaf node */
+ assert(cur != BVH::emptyNode);
+ STAT3(normal.trav_leaves,1,1,1);
+ size_t num; Primitive* prim = (Primitive*)cur.leaf(num);
+ size_t lazy_node = 0;
+ PrimitiveIntersector1::intersect(This, pre, ray, context, prim, num, tray, lazy_node);
+ tray.tfar = ray.tfar;
+
+ /* push lazy node onto stack */
+ if (unlikely(lazy_node)) {
+ stackPtr->ptr = lazy_node;
+ stackPtr->dist = neg_inf;
+ stackPtr++;
+ }
+ }
+ }
+
+ template<int N, int types, bool robust, typename PrimitiveIntersector1>
+ void BVHNIntersector1<N, types, robust, PrimitiveIntersector1>::occluded(const Accel::Intersectors* __restrict__ This,
+ Ray& __restrict__ ray,
+ IntersectContext* __restrict__ context)
+ {
+ const BVH* __restrict__ bvh = (const BVH*)This->ptr;
+
+ /* we may traverse an empty BVH in case all geometry was invalid */
+ if (bvh->root == BVH::emptyNode)
+ return;
+
+ /* early out for already occluded rays */
+ if (unlikely(ray.tfar < 0.0f))
+ return;
+
+ /* perform per ray precalculations required by the primitive intersector */
+ Precalculations pre(ray, bvh);
+
+ /* stack state */
+ NodeRef stack[stackSize]; // stack of nodes that still need to get traversed
+ NodeRef* stackPtr = stack+1; // current stack pointer
+ NodeRef* stackEnd = stack+stackSize;
+ stack[0] = bvh->root;
+
+ /* filter out invalid rays */
+#if defined(EMBREE_IGNORE_INVALID_RAYS)
+ if (!ray.valid()) return;
+#endif
+
+ /* verify correct input */
+ assert(ray.valid());
+ assert(ray.tnear() >= 0.0f);
+ assert(!(types & BVH_MB) || (ray.time() >= 0.0f && ray.time() <= 1.0f));
+
+ /* load the ray into SIMD registers */
+ TravRay<N,robust> tray(ray.org, ray.dir, max(ray.tnear(), 0.0f), max(ray.tfar, 0.0f));
+
+ /* initialize the node traverser */
+ BVHNNodeTraverser1Hit<N, types> nodeTraverser;
+
+ /* pop loop */
+ while (true) pop:
+ {
+ /* pop next node */
+ if (unlikely(stackPtr == stack)) break;
+ stackPtr--;
+ NodeRef cur = (NodeRef)*stackPtr;
+
+ /* downtraversal loop */
+ while (true)
+ {
+ /* intersect node */
+ size_t mask; vfloat<N> tNear;
+ STAT3(shadow.trav_nodes,1,1,1);
+ bool nodeIntersected = BVHNNodeIntersector1<N, types, robust>::intersect(cur, tray, ray.time(), tNear, mask);
+ if (unlikely(!nodeIntersected)) { STAT3(shadow.trav_nodes,-1,-1,-1); break; }
+
+ /* if no child is hit, pop next node */
+ if (unlikely(mask == 0))
+ goto pop;
+
+ /* select next child and push other children */
+ nodeTraverser.traverseAnyHit(cur, mask, tNear, stackPtr, stackEnd);
+ }
+
+ /* this is a leaf node */
+ assert(cur != BVH::emptyNode);
+ STAT3(shadow.trav_leaves,1,1,1);
+ size_t num; Primitive* prim = (Primitive*)cur.leaf(num);
+ size_t lazy_node = 0;
+ if (PrimitiveIntersector1::occluded(This, pre, ray, context, prim, num, tray, lazy_node)) {
+ ray.tfar = neg_inf;
+ break;
+ }
+
+ /* push lazy node onto stack */
+ if (unlikely(lazy_node)) {
+ *stackPtr = (NodeRef)lazy_node;
+ stackPtr++;
+ }
+ }
+ }
+
+ template<int N, int types, bool robust, typename PrimitiveIntersector1>
+ struct PointQueryDispatch
+ {
+ typedef typename PrimitiveIntersector1::Precalculations Precalculations;
+ typedef typename PrimitiveIntersector1::Primitive Primitive;
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::AABBNode AABBNode;
+ typedef typename BVH::AABBNodeMB4D AABBNodeMB4D;
+
+ static const size_t stackSize = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store
+
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context)
+ {
+ const BVH* __restrict__ bvh = (const BVH*)This->ptr;
+
+ /* we may traverse an empty BVH in case all geometry was invalid */
+ if (bvh->root == BVH::emptyNode)
+ return false;
+
+ /* stack state */
+ StackItemT<NodeRef> stack[stackSize]; // stack of nodes
+ StackItemT<NodeRef>* stackPtr = stack+1; // current stack pointer
+ StackItemT<NodeRef>* stackEnd = stack+stackSize;
+ stack[0].ptr = bvh->root;
+ stack[0].dist = neg_inf;
+
+ /* verify correct input */
+ assert(!(types & BVH_MB) || (query->time >= 0.0f && query->time <= 1.0f));
+
+ /* load the point query into SIMD registers */
+ TravPointQuery<N> tquery(query->p, context->query_radius);
+
+ /* initialize the node traverser */
+ BVHNNodeTraverser1Hit<N,types> nodeTraverser;
+
+ bool changed = false;
+ float cull_radius = context->query_type == POINT_QUERY_TYPE_SPHERE
+ ? query->radius * query->radius
+ : dot(context->query_radius, context->query_radius);
+
+ /* pop loop */
+ while (true) pop:
+ {
+ /* pop next node */
+ if (unlikely(stackPtr == stack)) break;
+ stackPtr--;
+ NodeRef cur = NodeRef(stackPtr->ptr);
+
+ /* if popped node is too far, pop next one */
+ if (unlikely(*(float*)&stackPtr->dist > cull_radius))
+ continue;
+
+ /* downtraversal loop */
+ while (true)
+ {
+ /* intersect node */
+ size_t mask; vfloat<N> tNear;
+ STAT3(point_query.trav_nodes,1,1,1);
+ bool nodeIntersected;
+ if (likely(context->query_type == POINT_QUERY_TYPE_SPHERE)) {
+ nodeIntersected = BVHNNodePointQuerySphere1<N, types>::pointQuery(cur, tquery, query->time, tNear, mask);
+ } else {
+ nodeIntersected = BVHNNodePointQueryAABB1 <N, types>::pointQuery(cur, tquery, query->time, tNear, mask);
+ }
+ if (unlikely(!nodeIntersected)) { STAT3(point_query.trav_nodes,-1,-1,-1); break; }
+
+ /* if no child is hit, pop next node */
+ if (unlikely(mask == 0))
+ goto pop;
+
+ /* select next child and push other children */
+ nodeTraverser.traverseClosestHit(cur, mask, tNear, stackPtr, stackEnd);
+ }
+
+ /* this is a leaf node */
+ assert(cur != BVH::emptyNode);
+ STAT3(point_query.trav_leaves,1,1,1);
+ size_t num; Primitive* prim = (Primitive*)cur.leaf(num);
+ size_t lazy_node = 0;
+ if (PrimitiveIntersector1::pointQuery(This, query, context, prim, num, tquery, lazy_node))
+ {
+ changed = true;
+ tquery.rad = context->query_radius;
+ cull_radius = context->query_type == POINT_QUERY_TYPE_SPHERE
+ ? query->radius * query->radius
+ : dot(context->query_radius, context->query_radius);
+ }
+
+ /* push lazy node onto stack */
+ if (unlikely(lazy_node)) {
+ stackPtr->ptr = lazy_node;
+ stackPtr->dist = neg_inf;
+ stackPtr++;
+ }
+ }
+ return changed;
+ }
+ };
+
+ /* disable point queries for not yet supported geometry types */
+ template<int N, int types, bool robust>
+ struct PointQueryDispatch<N, types, robust, VirtualCurveIntersector1> {
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
+ };
+
+ template<int N, int types, bool robust>
+ struct PointQueryDispatch<N, types, robust, SubdivPatch1Intersector1> {
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
+ };
+
+ template<int N, int types, bool robust>
+ struct PointQueryDispatch<N, types, robust, SubdivPatch1MBIntersector1> {
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
+ };
+
+ template<int N, int types, bool robust, typename PrimitiveIntersector1>
+ bool BVHNIntersector1<N, types, robust, PrimitiveIntersector1>::pointQuery(
+ const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context)
+ {
+ return PointQueryDispatch<N, types, robust, PrimitiveIntersector1>::pointQuery(This, query, context);
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_intersector1.h b/thirdparty/embree/kernels/bvh/bvh_intersector1.h
new file mode 100644
index 0000000000..2df3d6eddb
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_intersector1.h
@@ -0,0 +1,34 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+#include "../common/ray.h"
+#include "../common/point_query.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! BVH single ray intersector. */
+ template<int N, int types, bool robust, typename PrimitiveIntersector1>
+ class BVHNIntersector1
+ {
+ /* shortcuts for frequently used types */
+ typedef typename PrimitiveIntersector1::Precalculations Precalculations;
+ typedef typename PrimitiveIntersector1::Primitive Primitive;
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::AABBNode AABBNode;
+ typedef typename BVH::AABBNodeMB4D AABBNodeMB4D;
+
+ static const size_t stackSize = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store
+
+ public:
+ static void intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context);
+ static void occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context);
+ static bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context);
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_intersector1_bvh4.cpp b/thirdparty/embree/kernels/bvh/bvh_intersector1_bvh4.cpp
new file mode 100644
index 0000000000..831d613367
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_intersector1_bvh4.cpp
@@ -0,0 +1,61 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh_intersector1.cpp"
+
+namespace embree
+{
+ namespace isa
+ {
+ int getISA() {
+ return VerifyMultiTargetLinking::getISA();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// BVH4Intersector1 Definitions
+ ////////////////////////////////////////////////////////////////////////////////
+
+ IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersector1,BVHNIntersector1<4 COMMA BVH_AN1_UN1 COMMA false COMMA VirtualCurveIntersector1 >));
+ IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersector1MB,BVHNIntersector1<4 COMMA BVH_AN2_AN4D_UN2 COMMA false COMMA VirtualCurveIntersector1 >));
+
+ IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersectorRobust1,BVHNIntersector1<4 COMMA BVH_AN1_UN1 COMMA true COMMA VirtualCurveIntersector1 >));
+ IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersectorRobust1MB,BVHNIntersector1<4 COMMA BVH_AN2_AN4D_UN2 COMMA true COMMA VirtualCurveIntersector1 >));
+
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4Intersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<TriangleMIntersector1Moeller <4 COMMA true> > >));
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<TriangleMiIntersector1Moeller <4 COMMA true> > >));
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1<TriangleMvIntersector1Pluecker<4 COMMA true> > >));
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1<TriangleMiIntersector1Pluecker<4 COMMA true> > >));
+
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<TriangleMvMBIntersector1Moeller <4 COMMA true> > >));
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<TriangleMiMBIntersector1Moeller <4 COMMA true> > >));
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1<TriangleMvMBIntersector1Pluecker<4 COMMA true> > >));
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1<TriangleMiMBIntersector1Pluecker<4 COMMA true> > >));
+
+ IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4vIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<QuadMvIntersector1Moeller <4 COMMA true> > >));
+ IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<QuadMiIntersector1Moeller <4 COMMA true> > >));
+ IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4vIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1<QuadMvIntersector1Pluecker<4 COMMA true> > >));
+ IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1<QuadMiIntersector1Pluecker<4 COMMA true> > >));
+
+ IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<QuadMiMBIntersector1Moeller <4 COMMA true> > >));
+ IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1<QuadMiMBIntersector1Pluecker<4 COMMA true> > >));
+
+ IF_ENABLED_SUBDIV(DEFINE_INTERSECTOR1(BVH4SubdivPatch1Intersector1,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA SubdivPatch1Intersector1>));
+ IF_ENABLED_SUBDIV(DEFINE_INTERSECTOR1(BVH4SubdivPatch1MBIntersector1,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA SubdivPatch1MBIntersector1>));
+
+ IF_ENABLED_USER(DEFINE_INTERSECTOR1(BVH4VirtualIntersector1,BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<ObjectIntersector1<false>> >));
+ IF_ENABLED_USER(DEFINE_INTERSECTOR1(BVH4VirtualMBIntersector1,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<ObjectIntersector1<true>> >));
+
+ IF_ENABLED_INSTANCE(DEFINE_INTERSECTOR1(BVH4InstanceIntersector1,BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1<InstanceIntersector1> >));
+ IF_ENABLED_INSTANCE(DEFINE_INTERSECTOR1(BVH4InstanceMBIntersector1,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1<InstanceIntersector1MB> >));
+
+ IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(QBVH4Triangle4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1<TriangleMiIntersector1Pluecker<4 COMMA true> > >));
+ IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(QBVH4Quad4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1<QuadMiIntersector1Pluecker<4 COMMA true> > >));
+
+ IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridIntersector1Moeller,BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA SubGridIntersector1Moeller<4 COMMA true> >));
+ IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridMBIntersector1Moeller,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA SubGridMBIntersector1Pluecker<4 COMMA true> >));
+
+ IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA SubGridIntersector1Pluecker<4 COMMA true> >));
+ //IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA SubGridMBIntersector1Pluecker<4 COMMA true> >));
+
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.h b/thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.h
new file mode 100644
index 0000000000..50ebf375c4
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_intersector_hybrid.h
@@ -0,0 +1,58 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+#include "../common/ray.h"
+#include "../common/stack_item.h"
+#include "node_intersector_frustum.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int K, bool robust>
+ struct TravRayK;
+
+ /*! BVH hybrid packet intersector. Switches between packet and single ray traversal (optional). */
+ template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK, bool single = true>
+ class BVHNIntersectorKHybrid
+ {
+ /* shortcuts for frequently used types */
+ typedef typename PrimitiveIntersectorK::Precalculations Precalculations;
+ typedef typename PrimitiveIntersectorK::Primitive Primitive;
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::BaseNode BaseNode;
+ typedef typename BVH::AABBNode AABBNode;
+
+ static const size_t stackSizeSingle = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store
+ static const size_t stackSizeChunk = 1+(N-1)*BVH::maxDepth;
+
+ static const size_t switchThresholdIncoherent = \
+ (K==4) ? 3 :
+ (K==8) ? ((N==4) ? 5 : 7) :
+ (K==16) ? 14 : // 14 seems to work best for KNL due to better ordered chunk traversal
+ 0;
+
+ private:
+ static void intersect1(Accel::Intersectors* This, const BVH* bvh, NodeRef root, size_t k, Precalculations& pre,
+ RayHitK<K>& ray, const TravRayK<K, robust>& tray, IntersectContext* context);
+ static bool occluded1(Accel::Intersectors* This, const BVH* bvh, NodeRef root, size_t k, Precalculations& pre,
+ RayK<K>& ray, const TravRayK<K, robust>& tray, IntersectContext* context);
+
+ public:
+ static void intersect(vint<K>* valid, Accel::Intersectors* This, RayHitK<K>& ray, IntersectContext* context);
+ static void occluded (vint<K>* valid, Accel::Intersectors* This, RayK<K>& ray, IntersectContext* context);
+
+ static void intersectCoherent(vint<K>* valid, Accel::Intersectors* This, RayHitK<K>& ray, IntersectContext* context);
+ static void occludedCoherent (vint<K>* valid, Accel::Intersectors* This, RayK<K>& ray, IntersectContext* context);
+
+ };
+
+ /*! BVH packet intersector. */
+ template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK>
+ class BVHNIntersectorKChunk : public BVHNIntersectorKHybrid<N, K, types, robust, PrimitiveIntersectorK, false> {};
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_intersector_stream.h b/thirdparty/embree/kernels/bvh/bvh_intersector_stream.h
new file mode 100644
index 0000000000..717f559677
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_intersector_stream.h
@@ -0,0 +1,270 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "node_intersector_packet_stream.h"
+#include "node_intersector_frustum.h"
+#include "bvh_traverser_stream.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! BVH ray stream intersector. */
+ template<int N, int types, bool robust, typename PrimitiveIntersector>
+ class BVHNIntersectorStream
+ {
+ /* shortcuts for frequently used types */
+ template<int K> using PrimitiveIntersectorK = typename PrimitiveIntersector::template Type<K>;
+ template<int K> using PrimitiveK = typename PrimitiveIntersectorK<K>::PrimitiveK;
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::BaseNode BaseNode;
+ typedef typename BVH::AABBNode AABBNode;
+ typedef typename BVH::AABBNodeMB AABBNodeMB;
+
+ template<int K>
+ __forceinline static size_t initPacketsAndFrustum(RayK<K>** inputPackets, size_t numOctantRays,
+ TravRayKStream<K, robust>* packets, Frustum<robust>& frustum, bool& commonOctant)
+ {
+ const size_t numPackets = (numOctantRays+K-1)/K;
+
+ Vec3vf<K> tmp_min_rdir(pos_inf);
+ Vec3vf<K> tmp_max_rdir(neg_inf);
+ Vec3vf<K> tmp_min_org(pos_inf);
+ Vec3vf<K> tmp_max_org(neg_inf);
+ vfloat<K> tmp_min_dist(pos_inf);
+ vfloat<K> tmp_max_dist(neg_inf);
+
+ size_t m_active = 0;
+ for (size_t i = 0; i < numPackets; i++)
+ {
+ const vfloat<K> tnear = inputPackets[i]->tnear();
+ const vfloat<K> tfar = inputPackets[i]->tfar;
+ vbool<K> m_valid = (tnear <= tfar) & (tnear >= 0.0f);
+
+#if defined(EMBREE_IGNORE_INVALID_RAYS)
+ m_valid &= inputPackets[i]->valid();
+#endif
+
+ m_active |= (size_t)movemask(m_valid) << (i*K);
+
+ vfloat<K> packet_min_dist = max(tnear, 0.0f);
+ vfloat<K> packet_max_dist = select(m_valid, tfar, neg_inf);
+ tmp_min_dist = min(tmp_min_dist, packet_min_dist);
+ tmp_max_dist = max(tmp_max_dist, packet_max_dist);
+
+ const Vec3vf<K>& org = inputPackets[i]->org;
+ const Vec3vf<K>& dir = inputPackets[i]->dir;
+
+ new (&packets[i]) TravRayKStream<K, robust>(org, dir, packet_min_dist, packet_max_dist);
+
+ tmp_min_rdir = min(tmp_min_rdir, select(m_valid, packets[i].rdir, Vec3vf<K>(pos_inf)));
+ tmp_max_rdir = max(tmp_max_rdir, select(m_valid, packets[i].rdir, Vec3vf<K>(neg_inf)));
+ tmp_min_org = min(tmp_min_org , select(m_valid,org , Vec3vf<K>(pos_inf)));
+ tmp_max_org = max(tmp_max_org , select(m_valid,org , Vec3vf<K>(neg_inf)));
+ }
+
+ m_active &= (numOctantRays == (8 * sizeof(size_t))) ? (size_t)-1 : (((size_t)1 << numOctantRays)-1);
+
+
+ const Vec3fa reduced_min_rdir(reduce_min(tmp_min_rdir.x),
+ reduce_min(tmp_min_rdir.y),
+ reduce_min(tmp_min_rdir.z));
+
+ const Vec3fa reduced_max_rdir(reduce_max(tmp_max_rdir.x),
+ reduce_max(tmp_max_rdir.y),
+ reduce_max(tmp_max_rdir.z));
+
+ const Vec3fa reduced_min_origin(reduce_min(tmp_min_org.x),
+ reduce_min(tmp_min_org.y),
+ reduce_min(tmp_min_org.z));
+
+ const Vec3fa reduced_max_origin(reduce_max(tmp_max_org.x),
+ reduce_max(tmp_max_org.y),
+ reduce_max(tmp_max_org.z));
+
+ commonOctant =
+ (reduced_max_rdir.x < 0.0f || reduced_min_rdir.x >= 0.0f) &&
+ (reduced_max_rdir.y < 0.0f || reduced_min_rdir.y >= 0.0f) &&
+ (reduced_max_rdir.z < 0.0f || reduced_min_rdir.z >= 0.0f);
+
+ const float frustum_min_dist = reduce_min(tmp_min_dist);
+ const float frustum_max_dist = reduce_max(tmp_max_dist);
+
+ frustum.init(reduced_min_origin, reduced_max_origin,
+ reduced_min_rdir, reduced_max_rdir,
+ frustum_min_dist, frustum_max_dist,
+ N);
+
+ return m_active;
+ }
+
+ template<int K>
+ __forceinline static size_t intersectAABBNodePacket(size_t m_active,
+ const TravRayKStream<K,robust>* packets,
+ const AABBNode* __restrict__ node,
+ size_t boxID,
+ const NearFarPrecalculations& nf)
+ {
+ assert(m_active);
+ const size_t startPacketID = bsf(m_active) / K;
+ const size_t endPacketID = bsr(m_active) / K;
+ size_t m_trav_active = 0;
+ for (size_t i = startPacketID; i <= endPacketID; i++)
+ {
+ const size_t m_hit = intersectNodeK<N>(node, boxID, packets[i], nf);
+ m_trav_active |= m_hit << (i*K);
+ }
+ return m_trav_active;
+ }
+
+ template<int K>
+ __forceinline static size_t traverseCoherentStream(size_t m_active,
+ TravRayKStream<K, robust>* packets,
+ const AABBNode* __restrict__ node,
+ const Frustum<robust>& frustum,
+ size_t* maskK,
+ vfloat<N>& dist)
+ {
+ size_t m_node_hit = intersectNodeFrustum<N>(node, frustum, dist);
+ const size_t first_index = bsf(m_active);
+ const size_t first_packetID = first_index / K;
+ const size_t first_rayID = first_index % K;
+ size_t m_first_hit = intersectNode1<N>(node, packets[first_packetID], first_rayID, frustum.nf);
+
+ /* this make traversal independent of the ordering of rays */
+ size_t m_node = m_node_hit ^ m_first_hit;
+ while (unlikely(m_node))
+ {
+ const size_t boxID = bscf(m_node);
+ const size_t m_current = m_active & intersectAABBNodePacket(m_active, packets, node, boxID, frustum.nf);
+ m_node_hit ^= m_current ? (size_t)0 : ((size_t)1 << boxID);
+ maskK[boxID] = m_current;
+ }
+ return m_node_hit;
+ }
+
+ // TODO: explicit 16-wide path for KNL
+ template<int K>
+ __forceinline static vint<N> traverseIncoherentStream(size_t m_active,
+ TravRayKStreamFast<K>* __restrict__ packets,
+ const AABBNode* __restrict__ node,
+ const NearFarPrecalculations& nf,
+ const int shiftTable[32])
+ {
+ const vfloat<N> bminX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
+ const vfloat<N> bminY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
+ const vfloat<N> bminZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
+ const vfloat<N> bmaxX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
+ const vfloat<N> bmaxY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
+ const vfloat<N> bmaxZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
+ assert(m_active);
+ vint<N> vmask(zero);
+ do
+ {
+ STAT3(shadow.trav_nodes,1,1,1);
+ const size_t rayID = bscf(m_active);
+ assert(rayID < MAX_INTERNAL_STREAM_SIZE);
+ TravRayKStream<K,robust> &p = packets[rayID / K];
+ const size_t i = rayID % K;
+ const vint<N> bitmask(shiftTable[rayID]);
+ const vfloat<N> tNearX = msub(bminX, p.rdir.x[i], p.org_rdir.x[i]);
+ const vfloat<N> tNearY = msub(bminY, p.rdir.y[i], p.org_rdir.y[i]);
+ const vfloat<N> tNearZ = msub(bminZ, p.rdir.z[i], p.org_rdir.z[i]);
+ const vfloat<N> tFarX = msub(bmaxX, p.rdir.x[i], p.org_rdir.x[i]);
+ const vfloat<N> tFarY = msub(bmaxY, p.rdir.y[i], p.org_rdir.y[i]);
+ const vfloat<N> tFarZ = msub(bmaxZ, p.rdir.z[i], p.org_rdir.z[i]);
+ const vfloat<N> tNear = maxi(tNearX, tNearY, tNearZ, vfloat<N>(p.tnear[i]));
+ const vfloat<N> tFar = mini(tFarX , tFarY , tFarZ, vfloat<N>(p.tfar[i]));
+
+ const vbool<N> hit_mask = tNear <= tFar;
+#if defined(__AVX2__)
+ vmask = vmask | (bitmask & vint<N>(hit_mask));
+#else
+ vmask = select(hit_mask, vmask | bitmask, vmask);
+#endif
+ } while(m_active);
+ return vmask;
+ }
+
+ template<int K>
+ __forceinline static vint<N> traverseIncoherentStream(size_t m_active,
+ TravRayKStreamRobust<K>* __restrict__ packets,
+ const AABBNode* __restrict__ node,
+ const NearFarPrecalculations& nf,
+ const int shiftTable[32])
+ {
+ const vfloat<N> bminX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
+ const vfloat<N> bminY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
+ const vfloat<N> bminZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
+ const vfloat<N> bmaxX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
+ const vfloat<N> bmaxY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
+ const vfloat<N> bmaxZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
+ assert(m_active);
+ vint<N> vmask(zero);
+ do
+ {
+ STAT3(shadow.trav_nodes,1,1,1);
+ const size_t rayID = bscf(m_active);
+ assert(rayID < MAX_INTERNAL_STREAM_SIZE);
+ TravRayKStream<K,robust> &p = packets[rayID / K];
+ const size_t i = rayID % K;
+ const vint<N> bitmask(shiftTable[rayID]);
+ const vfloat<N> tNearX = (bminX - p.org.x[i]) * p.rdir.x[i];
+ const vfloat<N> tNearY = (bminY - p.org.y[i]) * p.rdir.y[i];
+ const vfloat<N> tNearZ = (bminZ - p.org.z[i]) * p.rdir.z[i];
+ const vfloat<N> tFarX = (bmaxX - p.org.x[i]) * p.rdir.x[i];
+ const vfloat<N> tFarY = (bmaxY - p.org.y[i]) * p.rdir.y[i];
+ const vfloat<N> tFarZ = (bmaxZ - p.org.z[i]) * p.rdir.z[i];
+ const vfloat<N> tNear = maxi(tNearX, tNearY, tNearZ, vfloat<N>(p.tnear[i]));
+ const vfloat<N> tFar = mini(tFarX , tFarY , tFarZ, vfloat<N>(p.tfar[i]));
+ const float round_down = 1.0f-2.0f*float(ulp);
+ const float round_up = 1.0f+2.0f*float(ulp);
+ const vbool<N> hit_mask = round_down*tNear <= round_up*tFar;
+#if defined(__AVX2__)
+ vmask = vmask | (bitmask & vint<N>(hit_mask));
+#else
+ vmask = select(hit_mask, vmask | bitmask, vmask);
+#endif
+ } while(m_active);
+ return vmask;
+ }
+
+
+ static const size_t stackSizeSingle = 1+(N-1)*BVH::maxDepth;
+
+ public:
+ static void intersect(Accel::Intersectors* This, RayHitN** inputRays, size_t numRays, IntersectContext* context);
+ static void occluded (Accel::Intersectors* This, RayN** inputRays, size_t numRays, IntersectContext* context);
+
+ private:
+ template<int K>
+ static void intersectCoherent(Accel::Intersectors* This, RayHitK<K>** inputRays, size_t numRays, IntersectContext* context);
+
+ template<int K>
+ static void occludedCoherent(Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
+
+ template<int K>
+ static void occludedIncoherent(Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
+ };
+
+
+ /*! BVH ray stream intersector with direct fallback to packets. */
+ template<int N>
+ class BVHNIntersectorStreamPacketFallback
+ {
+ public:
+ static void intersect(Accel::Intersectors* This, RayHitN** inputRays, size_t numRays, IntersectContext* context);
+ static void occluded (Accel::Intersectors* This, RayN** inputRays, size_t numRays, IntersectContext* context);
+
+ private:
+ template<int K>
+ static void intersectK(Accel::Intersectors* This, RayHitK<K>** inputRays, size_t numRays, IntersectContext* context);
+
+ template<int K>
+ static void occludedK(Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_intersector_stream_filters.h b/thirdparty/embree/kernels/bvh/bvh_intersector_stream_filters.h
new file mode 100644
index 0000000000..e7df7c2ae2
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_intersector_stream_filters.h
@@ -0,0 +1,41 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+#include "../common/ray.h"
+#include "../common/scene.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ class RayStreamFilter
+ {
+ public:
+ static void intersectAOS(Scene* scene, RTCRayHit* rays, size_t N, size_t stride, IntersectContext* context);
+ static void intersectAOP(Scene* scene, RTCRayHit** rays, size_t N, IntersectContext* context);
+ static void intersectSOA(Scene* scene, char* rays, size_t N, size_t numPackets, size_t stride, IntersectContext* context);
+ static void intersectSOP(Scene* scene, const RTCRayHitNp* rays, size_t N, IntersectContext* context);
+
+ static void occludedAOS(Scene* scene, RTCRay* rays, size_t N, size_t stride, IntersectContext* context);
+ static void occludedAOP(Scene* scene, RTCRay** rays, size_t N, IntersectContext* context);
+ static void occludedSOA(Scene* scene, char* rays, size_t N, size_t numPackets, size_t stride, IntersectContext* context);
+ static void occludedSOP(Scene* scene, const RTCRayNp* rays, size_t N, IntersectContext* context);
+
+ private:
+ template<int K, bool intersect>
+ static void filterAOS(Scene* scene, void* rays, size_t N, size_t stride, IntersectContext* context);
+
+ template<int K, bool intersect>
+ static void filterAOP(Scene* scene, void** rays, size_t N, IntersectContext* context);
+
+ template<int K, bool intersect>
+ static void filterSOA(Scene* scene, char* rays, size_t N, size_t numPackets, size_t stride, IntersectContext* context);
+
+ template<int K, bool intersect>
+ static void filterSOP(Scene* scene, const void* rays, size_t N, IntersectContext* context);
+ };
+ }
+};
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_aabb.h b/thirdparty/embree/kernels/bvh/bvh_node_aabb.h
new file mode 100644
index 0000000000..57530692bc
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_node_aabb.h
@@ -0,0 +1,213 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_node_base.h"
+
+namespace embree
+{
+ /*! BVHN AABBNode */
+ template<typename NodeRef, int N>
+ struct AABBNode_t : public BaseNode_t<NodeRef, N>
+ {
+ using BaseNode_t<NodeRef,N>::children;
+
+ struct Create
+ {
+ __forceinline NodeRef operator() (const FastAllocator::CachedAllocator& alloc, size_t numChildren = 0) const
+ {
+ AABBNode_t* node = (AABBNode_t*) alloc.malloc0(sizeof(AABBNode_t),NodeRef::byteNodeAlignment); node->clear();
+ return NodeRef::encodeNode(node);
+ }
+ };
+
+ struct Set
+ {
+ __forceinline void operator() (NodeRef node, size_t i, NodeRef child, const BBox3fa& bounds) const {
+ node.getAABBNode()->setRef(i,child);
+ node.getAABBNode()->setBounds(i,bounds);
+ }
+ };
+
+ struct Create2
+ {
+ template<typename BuildRecord>
+ __forceinline NodeRef operator() (BuildRecord* children, const size_t num, const FastAllocator::CachedAllocator& alloc) const
+ {
+ AABBNode_t* node = (AABBNode_t*) alloc.malloc0(sizeof(AABBNode_t), NodeRef::byteNodeAlignment); node->clear();
+ for (size_t i=0; i<num; i++) node->setBounds(i,children[i].bounds());
+ return NodeRef::encodeNode(node);
+ }
+ };
+
+ struct Set2
+ {
+ template<typename BuildRecord>
+ __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
+ {
+ AABBNode_t* node = ref.getAABBNode();
+ for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
+ return ref;
+ }
+ };
+
+ struct Set3
+ {
+ Set3 (FastAllocator* allocator, PrimRef* prims)
+ : allocator(allocator), prims(prims) {}
+
+ template<typename BuildRecord>
+ __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
+ {
+ AABBNode_t* node = ref.getAABBNode();
+ for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
+
+ if (unlikely(precord.alloc_barrier))
+ {
+ PrimRef* begin = &prims[precord.prims.begin()];
+ PrimRef* end = &prims[precord.prims.end()]; // FIXME: extended end for spatial split builder!!!!!
+ size_t bytes = (size_t)end - (size_t)begin;
+ allocator->addBlock(begin,bytes);
+ }
+
+ return ref;
+ }
+
+ FastAllocator* const allocator;
+ PrimRef* const prims;
+ };
+
+ /*! Clears the node. */
+ __forceinline void clear() {
+ lower_x = lower_y = lower_z = pos_inf;
+ upper_x = upper_y = upper_z = neg_inf;
+ BaseNode_t<NodeRef,N>::clear();
+ }
+
+ /*! Sets bounding box and ID of child. */
+ __forceinline void setRef(size_t i, const NodeRef& ref) {
+ assert(i < N);
+ children[i] = ref;
+ }
+
+ /*! Sets bounding box of child. */
+ __forceinline void setBounds(size_t i, const BBox3fa& bounds)
+ {
+ assert(i < N);
+ lower_x[i] = bounds.lower.x; lower_y[i] = bounds.lower.y; lower_z[i] = bounds.lower.z;
+ upper_x[i] = bounds.upper.x; upper_y[i] = bounds.upper.y; upper_z[i] = bounds.upper.z;
+ }
+
+ /*! Sets bounding box and ID of child. */
+ __forceinline void set(size_t i, const NodeRef& ref, const BBox3fa& bounds) {
+ setBounds(i,bounds);
+ children[i] = ref;
+ }
+
+ /*! Returns bounds of node. */
+ __forceinline BBox3fa bounds() const {
+ const Vec3fa lower(reduce_min(lower_x),reduce_min(lower_y),reduce_min(lower_z));
+ const Vec3fa upper(reduce_max(upper_x),reduce_max(upper_y),reduce_max(upper_z));
+ return BBox3fa(lower,upper);
+ }
+
+ /*! Returns bounds of specified child. */
+ __forceinline BBox3fa bounds(size_t i) const
+ {
+ assert(i < N);
+ const Vec3fa lower(lower_x[i],lower_y[i],lower_z[i]);
+ const Vec3fa upper(upper_x[i],upper_y[i],upper_z[i]);
+ return BBox3fa(lower,upper);
+ }
+
+ /*! Returns extent of bounds of specified child. */
+ __forceinline Vec3fa extend(size_t i) const {
+ return bounds(i).size();
+ }
+
+ /*! Returns bounds of all children (implemented later as specializations) */
+ __forceinline void bounds(BBox<vfloat4>& bounds0, BBox<vfloat4>& bounds1, BBox<vfloat4>& bounds2, BBox<vfloat4>& bounds3) const;
+
+ /*! swap two children of the node */
+ __forceinline void swap(size_t i, size_t j)
+ {
+ assert(i<N && j<N);
+ std::swap(children[i],children[j]);
+ std::swap(lower_x[i],lower_x[j]);
+ std::swap(lower_y[i],lower_y[j]);
+ std::swap(lower_z[i],lower_z[j]);
+ std::swap(upper_x[i],upper_x[j]);
+ std::swap(upper_y[i],upper_y[j]);
+ std::swap(upper_z[i],upper_z[j]);
+ }
+
+ /*! swap the children of two nodes */
+ __forceinline static void swap(AABBNode_t* a, size_t i, AABBNode_t* b, size_t j)
+ {
+ assert(i<N && j<N);
+ std::swap(a->children[i],b->children[j]);
+ std::swap(a->lower_x[i],b->lower_x[j]);
+ std::swap(a->lower_y[i],b->lower_y[j]);
+ std::swap(a->lower_z[i],b->lower_z[j]);
+ std::swap(a->upper_x[i],b->upper_x[j]);
+ std::swap(a->upper_y[i],b->upper_y[j]);
+ std::swap(a->upper_z[i],b->upper_z[j]);
+ }
+
+ /*! compacts a node (moves empty children to the end) */
+ __forceinline static void compact(AABBNode_t* a)
+ {
+ /* find right most filled node */
+ ssize_t j=N;
+ for (j=j-1; j>=0; j--)
+ if (a->child(j) != NodeRef::emptyNode)
+ break;
+
+ /* replace empty nodes with filled nodes */
+ for (ssize_t i=0; i<j; i++) {
+ if (a->child(i) == NodeRef::emptyNode) {
+ a->swap(i,j);
+ for (j=j-1; j>i; j--)
+ if (a->child(j) != NodeRef::emptyNode)
+ break;
+ }
+ }
+ }
+
+ /*! Returns reference to specified child */
+ __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
+ __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
+
+ /*! output operator */
+ friend embree_ostream operator<<(embree_ostream o, const AABBNode_t& n)
+ {
+ o << "AABBNode { " << embree_endl;
+ o << " lower_x " << n.lower_x << embree_endl;
+ o << " upper_x " << n.upper_x << embree_endl;
+ o << " lower_y " << n.lower_y << embree_endl;
+ o << " upper_y " << n.upper_y << embree_endl;
+ o << " lower_z " << n.lower_z << embree_endl;
+ o << " upper_z " << n.upper_z << embree_endl;
+ o << " children = ";
+ for (size_t i=0; i<N; i++) o << n.children[i] << " ";
+ o << embree_endl;
+ o << "}" << embree_endl;
+ return o;
+ }
+
+ public:
+ vfloat<N> lower_x; //!< X dimension of lower bounds of all N children.
+ vfloat<N> upper_x; //!< X dimension of upper bounds of all N children.
+ vfloat<N> lower_y; //!< Y dimension of lower bounds of all N children.
+ vfloat<N> upper_y; //!< Y dimension of upper bounds of all N children.
+ vfloat<N> lower_z; //!< Z dimension of lower bounds of all N children.
+ vfloat<N> upper_z; //!< Z dimension of upper bounds of all N children.
+ };
+
+ template<>
+ __forceinline void AABBNode_t<NodeRefPtr<4>,4>::bounds(BBox<vfloat4>& bounds0, BBox<vfloat4>& bounds1, BBox<vfloat4>& bounds2, BBox<vfloat4>& bounds3) const {
+ transpose(lower_x,lower_y,lower_z,vfloat4(zero),bounds0.lower,bounds1.lower,bounds2.lower,bounds3.lower);
+ transpose(upper_x,upper_y,upper_z,vfloat4(zero),bounds0.upper,bounds1.upper,bounds2.upper,bounds3.upper);
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h b/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h
new file mode 100644
index 0000000000..c4cea7d8ba
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb.h
@@ -0,0 +1,247 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_node_base.h"
+
+namespace embree
+{
+ /*! Motion Blur AABBNode */
+ template<typename NodeRef, int N>
+ struct AABBNodeMB_t : public BaseNode_t<NodeRef, N>
+ {
+ using BaseNode_t<NodeRef,N>::children;
+ typedef BVHNodeRecord<NodeRef> NodeRecord;
+ typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
+ typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
+
+ struct Create
+ {
+ template<typename BuildRecord>
+ __forceinline NodeRef operator() (BuildRecord* children, const size_t num, const FastAllocator::CachedAllocator& alloc) const
+ {
+ AABBNodeMB_t* node = (AABBNodeMB_t*) alloc.malloc0(sizeof(AABBNodeMB_t),NodeRef::byteNodeAlignment); node->clear();
+ return NodeRef::encodeNode(node);
+ }
+ };
+
+ struct Set
+ {
+ template<typename BuildRecord>
+ __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
+ {
+ AABBNodeMB_t* node = ref.getAABBNodeMB();
+
+ LBBox3fa bounds = empty;
+ for (size_t i=0; i<num; i++) {
+ node->setRef(i,children[i].ref);
+ node->setBounds(i,children[i].lbounds);
+ bounds.extend(children[i].lbounds);
+ }
+ return NodeRecordMB(ref,bounds);
+ }
+ };
+
+ struct SetTimeRange
+ {
+ __forceinline SetTimeRange(BBox1f tbounds) : tbounds(tbounds) {}
+
+ template<typename BuildRecord>
+ __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
+ {
+ AABBNodeMB_t* node = ref.getAABBNodeMB();
+
+ LBBox3fa bounds = empty;
+ for (size_t i=0; i<num; i++) {
+ node->setRef(i, children[i].ref);
+ node->setBounds(i, children[i].lbounds, tbounds);
+ bounds.extend(children[i].lbounds);
+ }
+ return NodeRecordMB(ref,bounds);
+ }
+
+ BBox1f tbounds;
+ };
+
+ /*! Clears the node. */
+ __forceinline void clear() {
+ lower_x = lower_y = lower_z = vfloat<N>(pos_inf);
+ upper_x = upper_y = upper_z = vfloat<N>(neg_inf);
+ lower_dx = lower_dy = lower_dz = vfloat<N>(0.0f);
+ upper_dx = upper_dy = upper_dz = vfloat<N>(0.0f);
+ BaseNode_t<NodeRef,N>::clear();
+ }
+
+ /*! Sets ID of child. */
+ __forceinline void setRef(size_t i, NodeRef ref) {
+ children[i] = ref;
+ }
+
+ /*! Sets bounding box of child. */
+ __forceinline void setBounds(size_t i, const BBox3fa& bounds0_i, const BBox3fa& bounds1_i)
+ {
+ /*! for empty bounds we have to avoid inf-inf=nan */
+ BBox3fa bounds0(min(bounds0_i.lower,Vec3fa(+FLT_MAX)),max(bounds0_i.upper,Vec3fa(-FLT_MAX)));
+ BBox3fa bounds1(min(bounds1_i.lower,Vec3fa(+FLT_MAX)),max(bounds1_i.upper,Vec3fa(-FLT_MAX)));
+ bounds0 = bounds0.enlarge_by(4.0f*float(ulp));
+ bounds1 = bounds1.enlarge_by(4.0f*float(ulp));
+ Vec3fa dlower = bounds1.lower-bounds0.lower;
+ Vec3fa dupper = bounds1.upper-bounds0.upper;
+
+ lower_x[i] = bounds0.lower.x; lower_y[i] = bounds0.lower.y; lower_z[i] = bounds0.lower.z;
+ upper_x[i] = bounds0.upper.x; upper_y[i] = bounds0.upper.y; upper_z[i] = bounds0.upper.z;
+
+ lower_dx[i] = dlower.x; lower_dy[i] = dlower.y; lower_dz[i] = dlower.z;
+ upper_dx[i] = dupper.x; upper_dy[i] = dupper.y; upper_dz[i] = dupper.z;
+ }
+
+ /*! Sets bounding box of child. */
+ __forceinline void setBounds(size_t i, const LBBox3fa& bounds) {
+ setBounds(i, bounds.bounds0, bounds.bounds1);
+ }
+
+ /*! Sets bounding box of child. */
+ __forceinline void setBounds(size_t i, const LBBox3fa& bounds, const BBox1f& tbounds) {
+ setBounds(i, bounds.global(tbounds));
+ }
+
+ /*! Sets bounding box and ID of child. */
+ __forceinline void set(size_t i, NodeRef ref, const BBox3fa& bounds) {
+ lower_x[i] = bounds.lower.x; lower_y[i] = bounds.lower.y; lower_z[i] = bounds.lower.z;
+ upper_x[i] = bounds.upper.x; upper_y[i] = bounds.upper.y; upper_z[i] = bounds.upper.z;
+ children[i] = ref;
+ }
+
+ /*! Sets bounding box and ID of child. */
+ __forceinline void set(size_t i, const NodeRecordMB4D& child)
+ {
+ setRef(i, child.ref);
+ setBounds(i, child.lbounds, child.dt);
+ }
+
+ /*! Return bounding box for time 0 */
+ __forceinline BBox3fa bounds0(size_t i) const {
+ return BBox3fa(Vec3fa(lower_x[i],lower_y[i],lower_z[i]),
+ Vec3fa(upper_x[i],upper_y[i],upper_z[i]));
+ }
+
+ /*! Return bounding box for time 1 */
+ __forceinline BBox3fa bounds1(size_t i) const {
+ return BBox3fa(Vec3fa(lower_x[i]+lower_dx[i],lower_y[i]+lower_dy[i],lower_z[i]+lower_dz[i]),
+ Vec3fa(upper_x[i]+upper_dx[i],upper_y[i]+upper_dy[i],upper_z[i]+upper_dz[i]));
+ }
+
+ /*! Returns bounds of node. */
+ __forceinline BBox3fa bounds() const {
+ return BBox3fa(Vec3fa(reduce_min(min(lower_x,lower_x+lower_dx)),
+ reduce_min(min(lower_y,lower_y+lower_dy)),
+ reduce_min(min(lower_z,lower_z+lower_dz))),
+ Vec3fa(reduce_max(max(upper_x,upper_x+upper_dx)),
+ reduce_max(max(upper_y,upper_y+upper_dy)),
+ reduce_max(max(upper_z,upper_z+upper_dz))));
+ }
+
+ /*! Return bounding box of child i */
+ __forceinline BBox3fa bounds(size_t i) const {
+ return merge(bounds0(i),bounds1(i));
+ }
+
+ /*! Return linear bounding box of child i */
+ __forceinline LBBox3fa lbounds(size_t i) const {
+ return LBBox3fa(bounds0(i),bounds1(i));
+ }
+
+ /*! Return bounding box of child i at specified time */
+ __forceinline BBox3fa bounds(size_t i, float time) const {
+ return lerp(bounds0(i),bounds1(i),time);
+ }
+
+ /*! Returns the expected surface area when randomly sampling the time. */
+ __forceinline float expectedHalfArea(size_t i) const {
+ return lbounds(i).expectedHalfArea();
+ }
+
+ /*! Returns the expected surface area when randomly sampling the time. */
+ __forceinline float expectedHalfArea(size_t i, const BBox1f& t0t1) const {
+ return lbounds(i).expectedHalfArea(t0t1);
+ }
+
+ /*! swap two children of the node */
+ __forceinline void swap(size_t i, size_t j)
+ {
+ assert(i<N && j<N);
+ std::swap(children[i],children[j]);
+
+ std::swap(lower_x[i],lower_x[j]);
+ std::swap(upper_x[i],upper_x[j]);
+ std::swap(lower_y[i],lower_y[j]);
+ std::swap(upper_y[i],upper_y[j]);
+ std::swap(lower_z[i],lower_z[j]);
+ std::swap(upper_z[i],upper_z[j]);
+
+ std::swap(lower_dx[i],lower_dx[j]);
+ std::swap(upper_dx[i],upper_dx[j]);
+ std::swap(lower_dy[i],lower_dy[j]);
+ std::swap(upper_dy[i],upper_dy[j]);
+ std::swap(lower_dz[i],lower_dz[j]);
+ std::swap(upper_dz[i],upper_dz[j]);
+ }
+
+ /*! compacts a node (moves empty children to the end) */
+ __forceinline static void compact(AABBNodeMB_t* a)
+ {
+ /* find right most filled node */
+ ssize_t j=N;
+ for (j=j-1; j>=0; j--)
+ if (a->child(j) != NodeRef::emptyNode)
+ break;
+
+ /* replace empty nodes with filled nodes */
+ for (ssize_t i=0; i<j; i++) {
+ if (a->child(i) == NodeRef::emptyNode) {
+ a->swap(i,j);
+ for (j=j-1; j>i; j--)
+ if (a->child(j) != NodeRef::emptyNode)
+ break;
+ }
+ }
+ }
+
+ /*! Returns reference to specified child */
+ __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
+ __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
+
+ /*! stream output operator */
+ friend embree_ostream operator<<(embree_ostream cout, const AABBNodeMB_t& n)
+ {
+ cout << "AABBNodeMB {" << embree_endl;
+ for (size_t i=0; i<N; i++)
+ {
+ const BBox3fa b0 = n.bounds0(i);
+ const BBox3fa b1 = n.bounds1(i);
+ cout << " child" << i << " { " << embree_endl;
+ cout << " bounds0 = " << b0 << ", " << embree_endl;
+ cout << " bounds1 = " << b1 << ", " << embree_endl;
+ cout << " }";
+ }
+ cout << "}";
+ return cout;
+ }
+
+ public:
+ vfloat<N> lower_x; //!< X dimension of lower bounds of all N children.
+ vfloat<N> upper_x; //!< X dimension of upper bounds of all N children.
+ vfloat<N> lower_y; //!< Y dimension of lower bounds of all N children.
+ vfloat<N> upper_y; //!< Y dimension of upper bounds of all N children.
+ vfloat<N> lower_z; //!< Z dimension of lower bounds of all N children.
+ vfloat<N> upper_z; //!< Z dimension of upper bounds of all N children.
+
+ vfloat<N> lower_dx; //!< X dimension of lower bounds of all N children.
+ vfloat<N> upper_dx; //!< X dimension of upper bounds of all N children.
+ vfloat<N> lower_dy; //!< Y dimension of lower bounds of all N children.
+ vfloat<N> upper_dy; //!< Y dimension of upper bounds of all N children.
+ vfloat<N> lower_dz; //!< Z dimension of lower bounds of all N children.
+ vfloat<N> upper_dz; //!< Z dimension of upper bounds of all N children.
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h b/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h
new file mode 100644
index 0000000000..46a81d7581
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_node_aabb_mb4d.h
@@ -0,0 +1,107 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_node_aabb_mb.h"
+
+namespace embree
+{
+ /*! Aligned 4D Motion Blur Node */
+ template<typename NodeRef, int N>
+ struct AABBNodeMB4D_t : public AABBNodeMB_t<NodeRef, N>
+ {
+ using BaseNode_t<NodeRef,N>::children;
+ using AABBNodeMB_t<NodeRef,N>::set;
+
+ typedef BVHNodeRecord<NodeRef> NodeRecord;
+ typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
+ typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
+
+ struct Create
+ {
+ template<typename BuildRecord>
+ __forceinline NodeRef operator() (BuildRecord*, const size_t, const FastAllocator::CachedAllocator& alloc, bool hasTimeSplits = true) const
+ {
+ if (hasTimeSplits)
+ {
+ AABBNodeMB4D_t* node = (AABBNodeMB4D_t*) alloc.malloc0(sizeof(AABBNodeMB4D_t),NodeRef::byteNodeAlignment); node->clear();
+ return NodeRef::encodeNode(node);
+ }
+ else
+ {
+ AABBNodeMB_t<NodeRef,N>* node = (AABBNodeMB_t<NodeRef,N>*) alloc.malloc0(sizeof(AABBNodeMB_t<NodeRef,N>),NodeRef::byteNodeAlignment); node->clear();
+ return NodeRef::encodeNode(node);
+ }
+ }
+ };
+
+ struct Set
+ {
+ template<typename BuildRecord>
+ __forceinline void operator() (const BuildRecord&, const BuildRecord*, NodeRef ref, NodeRecordMB4D* children, const size_t num) const
+ {
+ if (likely(ref.isAABBNodeMB())) {
+ for (size_t i=0; i<num; i++)
+ ref.getAABBNodeMB()->set(i, children[i]);
+ } else {
+ for (size_t i=0; i<num; i++)
+ ref.getAABBNodeMB4D()->set(i, children[i]);
+ }
+ }
+ };
+
+ /*! Clears the node. */
+ __forceinline void clear() {
+ lower_t = vfloat<N>(pos_inf);
+ upper_t = vfloat<N>(neg_inf);
+ AABBNodeMB_t<NodeRef,N>::clear();
+ }
+
+ /*! Sets bounding box of child. */
+ __forceinline void setBounds(size_t i, const LBBox3fa& bounds, const BBox1f& tbounds)
+ {
+ AABBNodeMB_t<NodeRef,N>::setBounds(i, bounds.global(tbounds));
+ lower_t[i] = tbounds.lower;
+ upper_t[i] = tbounds.upper == 1.0f ? 1.0f+float(ulp) : tbounds.upper;
+ }
+
+ /*! Sets bounding box and ID of child. */
+ __forceinline void set(size_t i, const NodeRecordMB4D& child) {
+ AABBNodeMB_t<NodeRef,N>::setRef(i,child.ref);
+ setBounds(i, child.lbounds, child.dt);
+ }
+
+ /*! Returns the expected surface area when randomly sampling the time. */
+ __forceinline float expectedHalfArea(size_t i) const {
+ return AABBNodeMB_t<NodeRef,N>::lbounds(i).expectedHalfArea(timeRange(i));
+ }
+
+ /*! returns time range for specified child */
+ __forceinline BBox1f timeRange(size_t i) const {
+ return BBox1f(lower_t[i],upper_t[i]);
+ }
+
+ /*! stream output operator */
+ friend embree_ostream operator<<(embree_ostream cout, const AABBNodeMB4D_t& n)
+ {
+ cout << "AABBNodeMB4D {" << embree_endl;
+ for (size_t i=0; i<N; i++)
+ {
+ const BBox3fa b0 = n.bounds0(i);
+ const BBox3fa b1 = n.bounds1(i);
+ cout << " child" << i << " { " << embree_endl;
+ cout << " bounds0 = " << lerp(b0,b1,n.lower_t[i]) << ", " << embree_endl;
+ cout << " bounds1 = " << lerp(b0,b1,n.upper_t[i]) << ", " << embree_endl;
+ cout << " time_bounds = " << n.lower_t[i] << ", " << n.upper_t[i] << embree_endl;
+ cout << " }";
+ }
+ cout << "}";
+ return cout;
+ }
+
+ public:
+ vfloat<N> lower_t; //!< time dimension of lower bounds of all N children
+ vfloat<N> upper_t; //!< time dimension of upper bounds of all N children
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_base.h b/thirdparty/embree/kernels/bvh/bvh_node_base.h
new file mode 100644
index 0000000000..a5570a7b9e
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_node_base.h
@@ -0,0 +1,43 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_node_ref.h"
+
+namespace embree
+{
+
+ /*! BVHN Base Node */
+ template<typename NodeRef, int N>
+ struct BaseNode_t
+ {
+ /*! Clears the node. */
+ __forceinline void clear()
+ {
+ for (size_t i=0; i<N; i++)
+ children[i] = NodeRef::emptyNode;
+ }
+
+ /*! Returns reference to specified child */
+ __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
+ __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
+
+ /*! verifies the node */
+ __forceinline bool verify() const
+ {
+ for (size_t i=0; i<N; i++) {
+ if (child(i) == NodeRef::emptyNode) {
+ for (; i<N; i++) {
+ if (child(i) != NodeRef::emptyNode)
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ NodeRef children[N]; //!< Pointer to the N children (can be a node or leaf)
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_obb.h b/thirdparty/embree/kernels/bvh/bvh_node_obb.h
new file mode 100644
index 0000000000..e6b500691e
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_node_obb.h
@@ -0,0 +1,98 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_node_base.h"
+
+namespace embree
+{
+ /*! Node with unaligned bounds */
+ template<typename NodeRef, int N>
+ struct OBBNode_t : public BaseNode_t<NodeRef, N>
+ {
+ using BaseNode_t<NodeRef,N>::children;
+
+ struct Create
+ {
+ __forceinline NodeRef operator() (const FastAllocator::CachedAllocator& alloc) const
+ {
+ OBBNode_t* node = (OBBNode_t*) alloc.malloc0(sizeof(OBBNode_t),NodeRef::byteNodeAlignment); node->clear();
+ return NodeRef::encodeNode(node);
+ }
+ };
+
+ struct Set
+ {
+ __forceinline void operator() (NodeRef node, size_t i, NodeRef child, const OBBox3fa& bounds) const {
+ node.ungetAABBNode()->setRef(i,child);
+ node.ungetAABBNode()->setBounds(i,bounds);
+ }
+ };
+
+ /*! Clears the node. */
+ __forceinline void clear()
+ {
+ naabb.l.vx = Vec3fa(nan);
+ naabb.l.vy = Vec3fa(nan);
+ naabb.l.vz = Vec3fa(nan);
+ naabb.p = Vec3fa(nan);
+ BaseNode_t<NodeRef,N>::clear();
+ }
+
+ /*! Sets bounding box. */
+ __forceinline void setBounds(size_t i, const OBBox3fa& b)
+ {
+ assert(i < N);
+
+ AffineSpace3fa space = b.space;
+ space.p -= b.bounds.lower;
+ space = AffineSpace3fa::scale(1.0f/max(Vec3fa(1E-19f),b.bounds.upper-b.bounds.lower))*space;
+
+ naabb.l.vx.x[i] = space.l.vx.x;
+ naabb.l.vx.y[i] = space.l.vx.y;
+ naabb.l.vx.z[i] = space.l.vx.z;
+
+ naabb.l.vy.x[i] = space.l.vy.x;
+ naabb.l.vy.y[i] = space.l.vy.y;
+ naabb.l.vy.z[i] = space.l.vy.z;
+
+ naabb.l.vz.x[i] = space.l.vz.x;
+ naabb.l.vz.y[i] = space.l.vz.y;
+ naabb.l.vz.z[i] = space.l.vz.z;
+
+ naabb.p.x[i] = space.p.x;
+ naabb.p.y[i] = space.p.y;
+ naabb.p.z[i] = space.p.z;
+ }
+
+ /*! Sets ID of child. */
+ __forceinline void setRef(size_t i, const NodeRef& ref) {
+ assert(i < N);
+ children[i] = ref;
+ }
+
+ /*! Returns the extent of the bounds of the ith child */
+ __forceinline Vec3fa extent(size_t i) const {
+ assert(i<N);
+ const Vec3fa vx(naabb.l.vx.x[i],naabb.l.vx.y[i],naabb.l.vx.z[i]);
+ const Vec3fa vy(naabb.l.vy.x[i],naabb.l.vy.y[i],naabb.l.vy.z[i]);
+ const Vec3fa vz(naabb.l.vz.x[i],naabb.l.vz.y[i],naabb.l.vz.z[i]);
+ return rsqrt(vx*vx + vy*vy + vz*vz);
+ }
+
+ /*! Returns reference to specified child */
+ __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
+ __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
+
+ /*! output operator */
+ friend embree_ostream operator<<(embree_ostream o, const OBBNode_t& n)
+ {
+ o << "UnAABBNode { " << n.naabb << " } " << embree_endl;
+ return o;
+ }
+
+ public:
+ AffineSpace3vf<N> naabb; //!< non-axis aligned bounding boxes (bounds are [0,1] in specified space)
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_obb_mb.h b/thirdparty/embree/kernels/bvh/bvh_node_obb_mb.h
new file mode 100644
index 0000000000..c06b1aea5e
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_node_obb_mb.h
@@ -0,0 +1,90 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_node_base.h"
+
+namespace embree
+{
+ template<typename NodeRef, int N>
+ struct OBBNodeMB_t : public BaseNode_t<NodeRef, N>
+ {
+ using BaseNode_t<NodeRef,N>::children;
+
+ struct Create
+ {
+ __forceinline NodeRef operator() (const FastAllocator::CachedAllocator& alloc) const
+ {
+ OBBNodeMB_t* node = (OBBNodeMB_t*) alloc.malloc0(sizeof(OBBNodeMB_t),NodeRef::byteNodeAlignment); node->clear();
+ return NodeRef::encodeNode(node);
+ }
+ };
+
+ struct Set
+ {
+ __forceinline void operator() (NodeRef node, size_t i, NodeRef child, const LinearSpace3fa& space, const LBBox3fa& lbounds, const BBox1f dt) const {
+ node.ungetAABBNodeMB()->setRef(i,child);
+ node.ungetAABBNodeMB()->setBounds(i,space,lbounds.global(dt));
+ }
+ };
+
+ /*! Clears the node. */
+ __forceinline void clear()
+ {
+ space0 = one;
+ //b0.lower = b0.upper = Vec3fa(nan);
+ b1.lower = b1.upper = Vec3fa(nan);
+ BaseNode_t<NodeRef,N>::clear();
+ }
+
+ /*! Sets space and bounding boxes. */
+ __forceinline void setBounds(size_t i, const AffineSpace3fa& space, const LBBox3fa& lbounds) {
+ setBounds(i,space,lbounds.bounds0,lbounds.bounds1);
+ }
+
+ /*! Sets space and bounding boxes. */
+ __forceinline void setBounds(size_t i, const AffineSpace3fa& s0, const BBox3fa& a, const BBox3fa& c)
+ {
+ assert(i < N);
+
+ AffineSpace3fa space = s0;
+ space.p -= a.lower;
+ Vec3fa scale = 1.0f/max(Vec3fa(1E-19f),a.upper-a.lower);
+ space = AffineSpace3fa::scale(scale)*space;
+ BBox3fa a1((a.lower-a.lower)*scale,(a.upper-a.lower)*scale);
+ BBox3fa c1((c.lower-a.lower)*scale,(c.upper-a.lower)*scale);
+
+ space0.l.vx.x[i] = space.l.vx.x; space0.l.vx.y[i] = space.l.vx.y; space0.l.vx.z[i] = space.l.vx.z;
+ space0.l.vy.x[i] = space.l.vy.x; space0.l.vy.y[i] = space.l.vy.y; space0.l.vy.z[i] = space.l.vy.z;
+ space0.l.vz.x[i] = space.l.vz.x; space0.l.vz.y[i] = space.l.vz.y; space0.l.vz.z[i] = space.l.vz.z;
+ space0.p .x[i] = space.p .x; space0.p .y[i] = space.p .y; space0.p .z[i] = space.p .z;
+
+ /*b0.lower.x[i] = a1.lower.x; b0.lower.y[i] = a1.lower.y; b0.lower.z[i] = a1.lower.z;
+ b0.upper.x[i] = a1.upper.x; b0.upper.y[i] = a1.upper.y; b0.upper.z[i] = a1.upper.z;*/
+
+ b1.lower.x[i] = c1.lower.x; b1.lower.y[i] = c1.lower.y; b1.lower.z[i] = c1.lower.z;
+ b1.upper.x[i] = c1.upper.x; b1.upper.y[i] = c1.upper.y; b1.upper.z[i] = c1.upper.z;
+ }
+
+ /*! Sets ID of child. */
+ __forceinline void setRef(size_t i, const NodeRef& ref) {
+ assert(i < N);
+ children[i] = ref;
+ }
+
+ /*! Returns the extent of the bounds of the ith child */
+ __forceinline Vec3fa extent0(size_t i) const {
+ assert(i < N);
+ const Vec3fa vx(space0.l.vx.x[i],space0.l.vx.y[i],space0.l.vx.z[i]);
+ const Vec3fa vy(space0.l.vy.x[i],space0.l.vy.y[i],space0.l.vy.z[i]);
+ const Vec3fa vz(space0.l.vz.x[i],space0.l.vz.y[i],space0.l.vz.z[i]);
+ return rsqrt(vx*vx + vy*vy + vz*vz);
+ }
+
+ public:
+ AffineSpace3vf<N> space0;
+ //BBox3vf<N> b0; // these are the unit bounds
+ BBox3vf<N> b1;
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_qaabb.h b/thirdparty/embree/kernels/bvh/bvh_node_qaabb.h
new file mode 100644
index 0000000000..2afc8c98e7
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_node_qaabb.h
@@ -0,0 +1,265 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh_node_base.h"
+
+namespace embree
+{
+ /*! BVHN Quantized Node */
+ template<int N>
+ struct __aligned(8) QuantizedBaseNode_t
+ {
+ typedef unsigned char T;
+ static const T MIN_QUAN = 0;
+ static const T MAX_QUAN = 255;
+
+ /*! Clears the node. */
+ __forceinline void clear() {
+ for (size_t i=0; i<N; i++) lower_x[i] = lower_y[i] = lower_z[i] = MAX_QUAN;
+ for (size_t i=0; i<N; i++) upper_x[i] = upper_y[i] = upper_z[i] = MIN_QUAN;
+ }
+
+ /*! Returns bounds of specified child. */
+ __forceinline BBox3fa bounds(size_t i) const
+ {
+ assert(i < N);
+ const Vec3fa lower(madd(scale.x,(float)lower_x[i],start.x),
+ madd(scale.y,(float)lower_y[i],start.y),
+ madd(scale.z,(float)lower_z[i],start.z));
+ const Vec3fa upper(madd(scale.x,(float)upper_x[i],start.x),
+ madd(scale.y,(float)upper_y[i],start.y),
+ madd(scale.z,(float)upper_z[i],start.z));
+ return BBox3fa(lower,upper);
+ }
+
+ /*! Returns extent of bounds of specified child. */
+ __forceinline Vec3fa extent(size_t i) const {
+ return bounds(i).size();
+ }
+
+ static __forceinline void init_dim(const vfloat<N> &lower,
+ const vfloat<N> &upper,
+ T lower_quant[N],
+ T upper_quant[N],
+ float &start,
+ float &scale)
+ {
+ /* quantize bounds */
+ const vbool<N> m_valid = lower != vfloat<N>(pos_inf);
+ const float minF = reduce_min(lower);
+ const float maxF = reduce_max(upper);
+ float diff = (1.0f+2.0f*float(ulp))*(maxF - minF);
+ float decode_scale = diff / float(MAX_QUAN);
+ if (decode_scale == 0.0f) decode_scale = 2.0f*FLT_MIN; // result may have been flushed to zero
+ assert(madd(decode_scale,float(MAX_QUAN),minF) >= maxF);
+ const float encode_scale = diff > 0 ? (float(MAX_QUAN) / diff) : 0.0f;
+ vint<N> ilower = max(vint<N>(floor((lower - vfloat<N>(minF))*vfloat<N>(encode_scale))),MIN_QUAN);
+ vint<N> iupper = min(vint<N>(ceil ((upper - vfloat<N>(minF))*vfloat<N>(encode_scale))),MAX_QUAN);
+
+ /* lower/upper correction */
+ vbool<N> m_lower_correction = (madd(vfloat<N>(ilower),decode_scale,minF)) > lower;
+ vbool<N> m_upper_correction = (madd(vfloat<N>(iupper),decode_scale,minF)) < upper;
+ ilower = max(select(m_lower_correction,ilower-1,ilower),MIN_QUAN);
+ iupper = min(select(m_upper_correction,iupper+1,iupper),MAX_QUAN);
+
+ /* disable invalid lanes */
+ ilower = select(m_valid,ilower,MAX_QUAN);
+ iupper = select(m_valid,iupper,MIN_QUAN);
+
+ /* store as uchar to memory */
+ vint<N>::store(lower_quant,ilower);
+ vint<N>::store(upper_quant,iupper);
+ start = minF;
+ scale = decode_scale;
+
+#if defined(DEBUG)
+ vfloat<N> extract_lower( vint<N>::loadu(lower_quant) );
+ vfloat<N> extract_upper( vint<N>::loadu(upper_quant) );
+ vfloat<N> final_extract_lower = madd(extract_lower,decode_scale,minF);
+ vfloat<N> final_extract_upper = madd(extract_upper,decode_scale,minF);
+ assert( (movemask(final_extract_lower <= lower ) & movemask(m_valid)) == movemask(m_valid));
+ assert( (movemask(final_extract_upper >= upper ) & movemask(m_valid)) == movemask(m_valid));
+#endif
+ }
+
+ __forceinline void init_dim(AABBNode_t<NodeRefPtr<N>,N>& node)
+ {
+ init_dim(node.lower_x,node.upper_x,lower_x,upper_x,start.x,scale.x);
+ init_dim(node.lower_y,node.upper_y,lower_y,upper_y,start.y,scale.y);
+ init_dim(node.lower_z,node.upper_z,lower_z,upper_z,start.z,scale.z);
+ }
+
+ __forceinline vbool<N> validMask() const { return vint<N>::loadu(lower_x) <= vint<N>::loadu(upper_x); }
+
+#if defined(__AVX512F__) // KNL
+ __forceinline vbool16 validMask16() const { return le(0xff,vint<16>::loadu(lower_x),vint<16>::loadu(upper_x)); }
+#endif
+ __forceinline vfloat<N> dequantizeLowerX() const { return madd(vfloat<N>(vint<N>::loadu(lower_x)),scale.x,vfloat<N>(start.x)); }
+
+ __forceinline vfloat<N> dequantizeUpperX() const { return madd(vfloat<N>(vint<N>::loadu(upper_x)),scale.x,vfloat<N>(start.x)); }
+
+ __forceinline vfloat<N> dequantizeLowerY() const { return madd(vfloat<N>(vint<N>::loadu(lower_y)),scale.y,vfloat<N>(start.y)); }
+
+ __forceinline vfloat<N> dequantizeUpperY() const { return madd(vfloat<N>(vint<N>::loadu(upper_y)),scale.y,vfloat<N>(start.y)); }
+
+ __forceinline vfloat<N> dequantizeLowerZ() const { return madd(vfloat<N>(vint<N>::loadu(lower_z)),scale.z,vfloat<N>(start.z)); }
+
+ __forceinline vfloat<N> dequantizeUpperZ() const { return madd(vfloat<N>(vint<N>::loadu(upper_z)),scale.z,vfloat<N>(start.z)); }
+
+ template <int M>
+ __forceinline vfloat<M> dequantize(const size_t offset) const { return vfloat<M>(vint<M>::loadu(all_planes+offset)); }
+
+#if defined(__AVX512F__)
+ __forceinline vfloat16 dequantizeLowerUpperX(const vint16 &p) const { return madd(vfloat16(permute(vint<16>::loadu(lower_x),p)),scale.x,vfloat16(start.x)); }
+ __forceinline vfloat16 dequantizeLowerUpperY(const vint16 &p) const { return madd(vfloat16(permute(vint<16>::loadu(lower_y),p)),scale.y,vfloat16(start.y)); }
+ __forceinline vfloat16 dequantizeLowerUpperZ(const vint16 &p) const { return madd(vfloat16(permute(vint<16>::loadu(lower_z),p)),scale.z,vfloat16(start.z)); }
+#endif
+
+ union {
+ struct {
+ T lower_x[N]; //!< 8bit discretized X dimension of lower bounds of all N children
+ T upper_x[N]; //!< 8bit discretized X dimension of upper bounds of all N children
+ T lower_y[N]; //!< 8bit discretized Y dimension of lower bounds of all N children
+ T upper_y[N]; //!< 8bit discretized Y dimension of upper bounds of all N children
+ T lower_z[N]; //!< 8bit discretized Z dimension of lower bounds of all N children
+ T upper_z[N]; //!< 8bit discretized Z dimension of upper bounds of all N children
+ };
+ T all_planes[6*N];
+ };
+
+ Vec3f start;
+ Vec3f scale;
+
+ friend embree_ostream operator<<(embree_ostream o, const QuantizedBaseNode_t& n)
+ {
+ o << "QuantizedBaseNode { " << embree_endl;
+ o << " start " << n.start << embree_endl;
+ o << " scale " << n.scale << embree_endl;
+ o << " lower_x " << vuint<N>::loadu(n.lower_x) << embree_endl;
+ o << " upper_x " << vuint<N>::loadu(n.upper_x) << embree_endl;
+ o << " lower_y " << vuint<N>::loadu(n.lower_y) << embree_endl;
+ o << " upper_y " << vuint<N>::loadu(n.upper_y) << embree_endl;
+ o << " lower_z " << vuint<N>::loadu(n.lower_z) << embree_endl;
+ o << " upper_z " << vuint<N>::loadu(n.upper_z) << embree_endl;
+ o << "}" << embree_endl;
+ return o;
+ }
+
+ };
+
+ template<typename NodeRef, int N>
+ struct __aligned(8) QuantizedNode_t : public BaseNode_t<NodeRef, N>, QuantizedBaseNode_t<N>
+ {
+ using BaseNode_t<NodeRef,N>::children;
+ using QuantizedBaseNode_t<N>::lower_x;
+ using QuantizedBaseNode_t<N>::upper_x;
+ using QuantizedBaseNode_t<N>::lower_y;
+ using QuantizedBaseNode_t<N>::upper_y;
+ using QuantizedBaseNode_t<N>::lower_z;
+ using QuantizedBaseNode_t<N>::upper_z;
+ using QuantizedBaseNode_t<N>::start;
+ using QuantizedBaseNode_t<N>::scale;
+ using QuantizedBaseNode_t<N>::init_dim;
+
+ __forceinline void setRef(size_t i, const NodeRef& ref) {
+ assert(i < N);
+ children[i] = ref;
+ }
+
+ struct Create2
+ {
+ template<typename BuildRecord>
+ __forceinline NodeRef operator() (BuildRecord* children, const size_t n, const FastAllocator::CachedAllocator& alloc) const
+ {
+ __aligned(64) AABBNode_t<NodeRef,N> node;
+ node.clear();
+ for (size_t i=0; i<n; i++) {
+ node.setBounds(i,children[i].bounds());
+ }
+ QuantizedNode_t *qnode = (QuantizedNode_t*) alloc.malloc0(sizeof(QuantizedNode_t), NodeRef::byteAlignment);
+ qnode->init(node);
+
+ return (size_t)qnode | NodeRef::tyQuantizedNode;
+ }
+ };
+
+ struct Set2
+ {
+ template<typename BuildRecord>
+ __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
+ {
+ QuantizedNode_t* node = ref.quantizedNode();
+ for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
+ return ref;
+ }
+ };
+
+ __forceinline void init(AABBNode_t<NodeRef,N>& node)
+ {
+ for (size_t i=0;i<N;i++) children[i] = NodeRef::emptyNode;
+ init_dim(node);
+ }
+
+ };
+
+ /*! BVHN Quantized Node */
+ template<int N>
+ struct __aligned(8) QuantizedBaseNodeMB_t
+ {
+ QuantizedBaseNode_t<N> node0;
+ QuantizedBaseNode_t<N> node1;
+
+ /*! Clears the node. */
+ __forceinline void clear() {
+ node0.clear();
+ node1.clear();
+ }
+
+ /*! Returns bounds of specified child. */
+ __forceinline BBox3fa bounds(size_t i) const
+ {
+ assert(i < N);
+ BBox3fa bounds0 = node0.bounds(i);
+ BBox3fa bounds1 = node1.bounds(i);
+ bounds0.extend(bounds1);
+ return bounds0;
+ }
+
+ /*! Returns extent of bounds of specified child. */
+ __forceinline Vec3fa extent(size_t i) const {
+ return bounds(i).size();
+ }
+
+ __forceinline vbool<N> validMask() const { return node0.validMask(); }
+
+ template<typename T>
+ __forceinline vfloat<N> dequantizeLowerX(const T t) const { return lerp(node0.dequantizeLowerX(),node1.dequantizeLowerX(),t); }
+ template<typename T>
+ __forceinline vfloat<N> dequantizeUpperX(const T t) const { return lerp(node0.dequantizeUpperX(),node1.dequantizeUpperX(),t); }
+ template<typename T>
+ __forceinline vfloat<N> dequantizeLowerY(const T t) const { return lerp(node0.dequantizeLowerY(),node1.dequantizeLowerY(),t); }
+ template<typename T>
+ __forceinline vfloat<N> dequantizeUpperY(const T t) const { return lerp(node0.dequantizeUpperY(),node1.dequantizeUpperY(),t); }
+ template<typename T>
+ __forceinline vfloat<N> dequantizeLowerZ(const T t) const { return lerp(node0.dequantizeLowerZ(),node1.dequantizeLowerZ(),t); }
+ template<typename T>
+ __forceinline vfloat<N> dequantizeUpperZ(const T t) const { return lerp(node0.dequantizeUpperZ(),node1.dequantizeUpperZ(),t); }
+
+
+ template<int M>
+ __forceinline vfloat<M> dequantizeLowerX(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeLowerX()[i]),vfloat<M>(node1.dequantizeLowerX()[i]),t); }
+ template<int M>
+ __forceinline vfloat<M> dequantizeUpperX(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeUpperX()[i]),vfloat<M>(node1.dequantizeUpperX()[i]),t); }
+ template<int M>
+ __forceinline vfloat<M> dequantizeLowerY(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeLowerY()[i]),vfloat<M>(node1.dequantizeLowerY()[i]),t); }
+ template<int M>
+ __forceinline vfloat<M> dequantizeUpperY(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeUpperY()[i]),vfloat<M>(node1.dequantizeUpperY()[i]),t); }
+ template<int M>
+ __forceinline vfloat<M> dequantizeLowerZ(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeLowerZ()[i]),vfloat<M>(node1.dequantizeLowerZ()[i]),t); }
+ template<int M>
+ __forceinline vfloat<M> dequantizeUpperZ(const size_t i, const vfloat<M> &t) const { return lerp(vfloat<M>(node0.dequantizeUpperZ()[i]),vfloat<M>(node1.dequantizeUpperZ()[i]),t); }
+
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_node_ref.h b/thirdparty/embree/kernels/bvh/bvh_node_ref.h
new file mode 100644
index 0000000000..6f6da758de
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_node_ref.h
@@ -0,0 +1,242 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+#include "../common/alloc.h"
+#include "../common/accel.h"
+#include "../common/device.h"
+#include "../common/scene.h"
+#include "../geometry/primitive.h"
+#include "../common/ray.h"
+
+namespace embree
+{
+ /* BVH node reference with bounds */
+ template<typename NodeRef>
+ struct BVHNodeRecord
+ {
+ __forceinline BVHNodeRecord() {}
+ __forceinline BVHNodeRecord(NodeRef ref, const BBox3fa& bounds) : ref(ref), bounds((BBox3fx)bounds) {}
+ __forceinline BVHNodeRecord(NodeRef ref, const BBox3fx& bounds) : ref(ref), bounds(bounds) {}
+
+ NodeRef ref;
+ BBox3fx bounds;
+ };
+
+ template<typename NodeRef>
+ struct BVHNodeRecordMB
+ {
+ __forceinline BVHNodeRecordMB() {}
+ __forceinline BVHNodeRecordMB(NodeRef ref, const LBBox3fa& lbounds) : ref(ref), lbounds(lbounds) {}
+
+ NodeRef ref;
+ LBBox3fa lbounds;
+ };
+
+ template<typename NodeRef>
+ struct BVHNodeRecordMB4D
+ {
+ __forceinline BVHNodeRecordMB4D() {}
+ __forceinline BVHNodeRecordMB4D(NodeRef ref, const LBBox3fa& lbounds, const BBox1f& dt) : ref(ref), lbounds(lbounds), dt(dt) {}
+
+ NodeRef ref;
+ LBBox3fa lbounds;
+ BBox1f dt;
+ };
+
+ template<typename NodeRef, int N> struct BaseNode_t;
+ template<typename NodeRef, int N> struct AABBNode_t;
+ template<typename NodeRef, int N> struct AABBNodeMB_t;
+ template<typename NodeRef, int N> struct AABBNodeMB4D_t;
+ template<typename NodeRef, int N> struct OBBNode_t;
+ template<typename NodeRef, int N> struct OBBNodeMB_t;
+ template<typename NodeRef, int N> struct QuantizedNode_t;
+ template<typename NodeRef, int N> struct QuantizedNodeMB_t;
+
+ /*! Pointer that points to a node or a list of primitives */
+ template<int N>
+ struct NodeRefPtr
+ {
+ //template<int NN> friend class BVHN;
+
+ /*! Number of bytes the nodes and primitives are minimally aligned to.*/
+ static const size_t byteAlignment = 16;
+ static const size_t byteNodeAlignment = 4*N;
+
+ /*! highest address bit is used as barrier for some algorithms */
+ static const size_t barrier_mask = (1LL << (8*sizeof(size_t)-1));
+
+ /*! Masks the bits that store the number of items per leaf. */
+ static const size_t align_mask = byteAlignment-1;
+ static const size_t items_mask = byteAlignment-1;
+
+ /*! different supported node types */
+ static const size_t tyAABBNode = 0;
+ static const size_t tyAABBNodeMB = 1;
+ static const size_t tyAABBNodeMB4D = 6;
+ static const size_t tyOBBNode = 2;
+ static const size_t tyOBBNodeMB = 3;
+ static const size_t tyQuantizedNode = 5;
+ static const size_t tyLeaf = 8;
+
+ /*! Empty node */
+ static const size_t emptyNode = tyLeaf;
+
+ /*! Invalid node, used as marker in traversal */
+ static const size_t invalidNode = (((size_t)-1) & (~items_mask)) | (tyLeaf+0);
+ static const size_t popRay = (((size_t)-1) & (~items_mask)) | (tyLeaf+1);
+
+ /*! Maximum number of primitive blocks in a leaf. */
+ static const size_t maxLeafBlocks = items_mask-tyLeaf;
+
+ /*! Default constructor */
+ __forceinline NodeRefPtr () {}
+
+ /*! Construction from integer */
+ __forceinline NodeRefPtr (size_t ptr) : ptr(ptr) {}
+
+ /*! Cast to size_t */
+ __forceinline operator size_t() const { return ptr; }
+
+ /*! Sets the barrier bit. */
+ __forceinline void setBarrier() {
+#if defined(__64BIT__)
+ assert(!isBarrier());
+ ptr |= barrier_mask;
+#else
+ assert(false);
+#endif
+ }
+
+ /*! Clears the barrier bit. */
+ __forceinline void clearBarrier() {
+#if defined(__64BIT__)
+ ptr &= ~barrier_mask;
+#else
+ assert(false);
+#endif
+ }
+
+ /*! Checks if this is an barrier. A barrier tells the top level tree rotations how deep to enter the tree. */
+ __forceinline bool isBarrier() const { return (ptr & barrier_mask) != 0; }
+
+ /*! checks if this is a leaf */
+ __forceinline size_t isLeaf() const { return ptr & tyLeaf; }
+
+ /*! returns node type */
+ __forceinline int type() const { return ptr & (size_t)align_mask; }
+
+ /*! checks if this is a node */
+ __forceinline int isAABBNode() const { return (ptr & (size_t)align_mask) == tyAABBNode; }
+
+ /*! checks if this is a motion blur node */
+ __forceinline int isAABBNodeMB() const { return (ptr & (size_t)align_mask) == tyAABBNodeMB; }
+
+ /*! checks if this is a 4D motion blur node */
+ __forceinline int isAABBNodeMB4D() const { return (ptr & (size_t)align_mask) == tyAABBNodeMB4D; }
+
+ /*! checks if this is a node with unaligned bounding boxes */
+ __forceinline int isOBBNode() const { return (ptr & (size_t)align_mask) == tyOBBNode; }
+
+ /*! checks if this is a motion blur node with unaligned bounding boxes */
+ __forceinline int isOBBNodeMB() const { return (ptr & (size_t)align_mask) == tyOBBNodeMB; }
+
+ /*! checks if this is a quantized node */
+ __forceinline int isQuantizedNode() const { return (ptr & (size_t)align_mask) == tyQuantizedNode; }
+
+ /*! Encodes a node */
+ static __forceinline NodeRefPtr encodeNode(AABBNode_t<NodeRefPtr,N>* node) {
+ assert(!((size_t)node & align_mask));
+ return NodeRefPtr((size_t) node);
+ }
+
+ static __forceinline NodeRefPtr encodeNode(AABBNodeMB_t<NodeRefPtr,N>* node) {
+ assert(!((size_t)node & align_mask));
+ return NodeRefPtr((size_t) node | tyAABBNodeMB);
+ }
+
+ static __forceinline NodeRefPtr encodeNode(AABBNodeMB4D_t<NodeRefPtr,N>* node) {
+ assert(!((size_t)node & align_mask));
+ return NodeRefPtr((size_t) node | tyAABBNodeMB4D);
+ }
+
+ /*! Encodes an unaligned node */
+ static __forceinline NodeRefPtr encodeNode(OBBNode_t<NodeRefPtr,N>* node) {
+ return NodeRefPtr((size_t) node | tyOBBNode);
+ }
+
+ /*! Encodes an unaligned motion blur node */
+ static __forceinline NodeRefPtr encodeNode(OBBNodeMB_t<NodeRefPtr,N>* node) {
+ return NodeRefPtr((size_t) node | tyOBBNodeMB);
+ }
+
+ /*! Encodes a leaf */
+ static __forceinline NodeRefPtr encodeLeaf(void* tri, size_t num) {
+ assert(!((size_t)tri & align_mask));
+ assert(num <= maxLeafBlocks);
+ return NodeRefPtr((size_t)tri | (tyLeaf+min(num,(size_t)maxLeafBlocks)));
+ }
+
+ /*! Encodes a leaf */
+ static __forceinline NodeRefPtr encodeTypedLeaf(void* ptr, size_t ty) {
+ assert(!((size_t)ptr & align_mask));
+ return NodeRefPtr((size_t)ptr | (tyLeaf+ty));
+ }
+
+ /*! returns base node pointer */
+ __forceinline BaseNode_t<NodeRefPtr,N>* baseNode()
+ {
+ assert(!isLeaf());
+ return (BaseNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask);
+ }
+ __forceinline const BaseNode_t<NodeRefPtr,N>* baseNode() const
+ {
+ assert(!isLeaf());
+ return (const BaseNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask);
+ }
+
+ /*! returns node pointer */
+ __forceinline AABBNode_t<NodeRefPtr,N>* getAABBNode() { assert(isAABBNode()); return ( AABBNode_t<NodeRefPtr,N>*)ptr; }
+ __forceinline const AABBNode_t<NodeRefPtr,N>* getAABBNode() const { assert(isAABBNode()); return (const AABBNode_t<NodeRefPtr,N>*)ptr; }
+
+ /*! returns motion blur node pointer */
+ __forceinline AABBNodeMB_t<NodeRefPtr,N>* getAABBNodeMB() { assert(isAABBNodeMB() || isAABBNodeMB4D()); return ( AABBNodeMB_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
+ __forceinline const AABBNodeMB_t<NodeRefPtr,N>* getAABBNodeMB() const { assert(isAABBNodeMB() || isAABBNodeMB4D()); return (const AABBNodeMB_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
+
+ /*! returns 4D motion blur node pointer */
+ __forceinline AABBNodeMB4D_t<NodeRefPtr,N>* getAABBNodeMB4D() { assert(isAABBNodeMB4D()); return ( AABBNodeMB4D_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
+ __forceinline const AABBNodeMB4D_t<NodeRefPtr,N>* getAABBNodeMB4D() const { assert(isAABBNodeMB4D()); return (const AABBNodeMB4D_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
+
+ /*! returns unaligned node pointer */
+ __forceinline OBBNode_t<NodeRefPtr,N>* ungetAABBNode() { assert(isOBBNode()); return ( OBBNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
+ __forceinline const OBBNode_t<NodeRefPtr,N>* ungetAABBNode() const { assert(isOBBNode()); return (const OBBNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
+
+ /*! returns unaligned motion blur node pointer */
+ __forceinline OBBNodeMB_t<NodeRefPtr,N>* ungetAABBNodeMB() { assert(isOBBNodeMB()); return ( OBBNodeMB_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
+ __forceinline const OBBNodeMB_t<NodeRefPtr,N>* ungetAABBNodeMB() const { assert(isOBBNodeMB()); return (const OBBNodeMB_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask); }
+
+ /*! returns quantized node pointer */
+ __forceinline QuantizedNode_t<NodeRefPtr,N>* quantizedNode() { assert(isQuantizedNode()); return ( QuantizedNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask ); }
+ __forceinline const QuantizedNode_t<NodeRefPtr,N>* quantizedNode() const { assert(isQuantizedNode()); return (const QuantizedNode_t<NodeRefPtr,N>*)(ptr & ~(size_t)align_mask ); }
+
+ /*! returns leaf pointer */
+ __forceinline char* leaf(size_t& num) const {
+ assert(isLeaf());
+ num = (ptr & (size_t)items_mask)-tyLeaf;
+ return (char*)(ptr & ~(size_t)align_mask);
+ }
+
+ /*! clear all bit flags */
+ __forceinline void clearFlags() {
+ ptr &= ~(size_t)align_mask;
+ }
+
+ /*! returns the wideness */
+ __forceinline size_t getN() const { return N; }
+
+ public:
+ size_t ptr;
+ };
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_refit.cpp b/thirdparty/embree/kernels/bvh/bvh_refit.cpp
new file mode 100644
index 0000000000..bf5c8538ba
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_refit.cpp
@@ -0,0 +1,247 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh_refit.h"
+#include "bvh_statistics.h"
+
+#include "../geometry/linei.h"
+#include "../geometry/triangle.h"
+#include "../geometry/trianglev.h"
+#include "../geometry/trianglei.h"
+#include "../geometry/quadv.h"
+#include "../geometry/object.h"
+#include "../geometry/instance.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ static const size_t SINGLE_THREAD_THRESHOLD = 4*1024;
+
+ template<int N>
+ __forceinline bool compare(const typename BVHN<N>::NodeRef* a, const typename BVHN<N>::NodeRef* b)
+ {
+ size_t sa = *(size_t*)&a->node()->lower_x;
+ size_t sb = *(size_t*)&b->node()->lower_x;
+ return sa < sb;
+ }
+
+ template<int N>
+ BVHNRefitter<N>::BVHNRefitter (BVH* bvh, const LeafBoundsInterface& leafBounds)
+ : bvh(bvh), leafBounds(leafBounds), numSubTrees(0)
+ {
+ }
+
+ template<int N>
+ void BVHNRefitter<N>::refit()
+ {
+ if (bvh->numPrimitives <= SINGLE_THREAD_THRESHOLD) {
+ bvh->bounds = LBBox3fa(recurse_bottom(bvh->root));
+ }
+ else
+ {
+ BBox3fa subTreeBounds[MAX_NUM_SUB_TREES];
+ numSubTrees = 0;
+ gather_subtree_refs(bvh->root,numSubTrees,0);
+ if (numSubTrees)
+ parallel_for(size_t(0), numSubTrees, size_t(1), [&](const range<size_t>& r) {
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ NodeRef& ref = subTrees[i];
+ subTreeBounds[i] = recurse_bottom(ref);
+ }
+ });
+
+ numSubTrees = 0;
+ bvh->bounds = LBBox3fa(refit_toplevel(bvh->root,numSubTrees,subTreeBounds,0));
+ }
+ }
+
+ template<int N>
+ void BVHNRefitter<N>::gather_subtree_refs(NodeRef& ref,
+ size_t &subtrees,
+ const size_t depth)
+ {
+ if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)
+ {
+ assert(subtrees < MAX_NUM_SUB_TREES);
+ subTrees[subtrees++] = ref;
+ return;
+ }
+
+ if (ref.isAABBNode())
+ {
+ AABBNode* node = ref.getAABBNode();
+ for (size_t i=0; i<N; i++) {
+ NodeRef& child = node->child(i);
+ if (unlikely(child == BVH::emptyNode)) continue;
+ gather_subtree_refs(child,subtrees,depth+1);
+ }
+ }
+ }
+
+ template<int N>
+ BBox3fa BVHNRefitter<N>::refit_toplevel(NodeRef& ref,
+ size_t &subtrees,
+ const BBox3fa *const subTreeBounds,
+ const size_t depth)
+ {
+ if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)
+ {
+ assert(subtrees < MAX_NUM_SUB_TREES);
+ assert(subTrees[subtrees] == ref);
+ return subTreeBounds[subtrees++];
+ }
+
+ if (ref.isAABBNode())
+ {
+ AABBNode* node = ref.getAABBNode();
+ BBox3fa bounds[N];
+
+ for (size_t i=0; i<N; i++)
+ {
+ NodeRef& child = node->child(i);
+
+ if (unlikely(child == BVH::emptyNode))
+ bounds[i] = BBox3fa(empty);
+ else
+ bounds[i] = refit_toplevel(child,subtrees,subTreeBounds,depth+1);
+ }
+
+ BBox3vf<N> boundsT = transpose<N>(bounds);
+
+ /* set new bounds */
+ node->lower_x = boundsT.lower.x;
+ node->lower_y = boundsT.lower.y;
+ node->lower_z = boundsT.lower.z;
+ node->upper_x = boundsT.upper.x;
+ node->upper_y = boundsT.upper.y;
+ node->upper_z = boundsT.upper.z;
+
+ return merge<N>(bounds);
+ }
+ else
+ return leafBounds.leafBounds(ref);
+ }
+
+ // =========================================================
+ // =========================================================
+ // =========================================================
+
+
+ template<int N>
+ BBox3fa BVHNRefitter<N>::recurse_bottom(NodeRef& ref)
+ {
+ /* this is a leaf node */
+ if (unlikely(ref.isLeaf()))
+ return leafBounds.leafBounds(ref);
+
+ /* recurse if this is an internal node */
+ AABBNode* node = ref.getAABBNode();
+
+ /* enable exclusive prefetch for >= AVX platforms */
+#if defined(__AVX__)
+ BVH::prefetchW(ref);
+#endif
+ BBox3fa bounds[N];
+
+ for (size_t i=0; i<N; i++)
+ if (unlikely(node->child(i) == BVH::emptyNode))
+ {
+ bounds[i] = BBox3fa(empty);
+ }
+ else
+ bounds[i] = recurse_bottom(node->child(i));
+
+ /* AOS to SOA transform */
+ BBox3vf<N> boundsT = transpose<N>(bounds);
+
+ /* set new bounds */
+ node->lower_x = boundsT.lower.x;
+ node->lower_y = boundsT.lower.y;
+ node->lower_z = boundsT.lower.z;
+ node->upper_x = boundsT.upper.x;
+ node->upper_y = boundsT.upper.y;
+ node->upper_z = boundsT.upper.z;
+
+ return merge<N>(bounds);
+ }
+
+ template<int N, typename Mesh, typename Primitive>
+ BVHNRefitT<N,Mesh,Primitive>::BVHNRefitT (BVH* bvh, Builder* builder, Mesh* mesh, size_t mode)
+ : bvh(bvh), builder(builder), refitter(new BVHNRefitter<N>(bvh,*(typename BVHNRefitter<N>::LeafBoundsInterface*)this)), mesh(mesh), topologyVersion(0) {}
+
+ template<int N, typename Mesh, typename Primitive>
+ void BVHNRefitT<N,Mesh,Primitive>::clear()
+ {
+ if (builder)
+ builder->clear();
+ }
+
+ template<int N, typename Mesh, typename Primitive>
+ void BVHNRefitT<N,Mesh,Primitive>::build()
+ {
+ if (mesh->topologyChanged(topologyVersion)) {
+ topologyVersion = mesh->getTopologyVersion();
+ builder->build();
+ }
+ else
+ refitter->refit();
+ }
+
+ template class BVHNRefitter<4>;
+#if defined(__AVX__)
+ template class BVHNRefitter<8>;
+#endif
+
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
+ Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
+ Builder* BVH4Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
+
+ Builder* BVH4Triangle4MeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4> ((BVH4*)accel,BVH4Triangle4MeshBuilderSAH (accel,mesh,geomID,mode),mesh,mode); }
+ Builder* BVH4Triangle4vMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4v>((BVH4*)accel,BVH4Triangle4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
+ Builder* BVH4Triangle4iMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4i>((BVH4*)accel,BVH4Triangle4iMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
+#if defined(__AVX__)
+ Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
+ Builder* BVH8Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
+ Builder* BVH8Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
+
+ Builder* BVH8Triangle4MeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4> ((BVH8*)accel,BVH8Triangle4MeshBuilderSAH (accel,mesh,geomID,mode),mesh,mode); }
+ Builder* BVH8Triangle4vMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4v>((BVH8*)accel,BVH8Triangle4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
+ Builder* BVH8Triangle4iMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4i>((BVH8*)accel,BVH8Triangle4iMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_QUAD)
+ Builder* BVH4Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode);
+ Builder* BVH4Quad4vMeshRefitSAH (void* accel, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,QuadMesh,Quad4v>((BVH4*)accel,BVH4Quad4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
+
+#if defined(__AVX__)
+ Builder* BVH8Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode);
+ Builder* BVH8Quad4vMeshRefitSAH (void* accel, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,QuadMesh,Quad4v>((BVH8*)accel,BVH8Quad4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
+#endif
+
+#endif
+
+#if defined(EMBREE_GEOMETRY_USER)
+ Builder* BVH4VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode);
+ Builder* BVH4VirtualMeshRefitSAH (void* accel, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,UserGeometry,Object>((BVH4*)accel,BVH4VirtualMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
+
+#if defined(__AVX__)
+ Builder* BVH8VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode);
+ Builder* BVH8VirtualMeshRefitSAH (void* accel, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,UserGeometry,Object>((BVH8*)accel,BVH8VirtualMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
+#endif
+#endif
+
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);
+ Builder* BVH4InstanceMeshRefitSAH (void* accel, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,Instance,InstancePrimitive>((BVH4*)accel,BVH4InstanceMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); }
+
+#if defined(__AVX__)
+ Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);
+ Builder* BVH8InstanceMeshRefitSAH (void* accel, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,Instance,InstancePrimitive>((BVH8*)accel,BVH8InstanceMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); }
+#endif
+#endif
+
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_refit.h b/thirdparty/embree/kernels/bvh/bvh_refit.h
new file mode 100644
index 0000000000..09bb3d8da5
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_refit.h
@@ -0,0 +1,95 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../bvh/bvh.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N>
+ class BVHNRefitter
+ {
+ public:
+
+ /*! Type shortcuts */
+ typedef BVHN<N> BVH;
+ typedef typename BVH::AABBNode AABBNode;
+ typedef typename BVH::NodeRef NodeRef;
+
+ struct LeafBoundsInterface {
+ virtual const BBox3fa leafBounds(NodeRef& ref) const = 0;
+ };
+
+ public:
+
+ /*! Constructor. */
+ BVHNRefitter (BVH* bvh, const LeafBoundsInterface& leafBounds);
+
+ /*! refits the BVH */
+ void refit();
+
+ private:
+ /* single-threaded subtree extraction based on BVH depth */
+ void gather_subtree_refs(NodeRef& ref,
+ size_t &subtrees,
+ const size_t depth = 0);
+
+ /* single-threaded top-level refit */
+ BBox3fa refit_toplevel(NodeRef& ref,
+ size_t &subtrees,
+ const BBox3fa *const subTreeBounds,
+ const size_t depth = 0);
+
+ /* single-threaded subtree refit */
+ BBox3fa recurse_bottom(NodeRef& ref);
+
+ public:
+ BVH* bvh; //!< BVH to refit
+ const LeafBoundsInterface& leafBounds; //!< calculates bounds of leaves
+
+ static const size_t MAX_SUB_TREE_EXTRACTION_DEPTH = (N==4) ? 4 : (N==8) ? 3 : 3;
+ static const size_t MAX_NUM_SUB_TREES = (N==4) ? 256 : (N==8) ? 512 : N*N*N; // N ^ MAX_SUB_TREE_EXTRACTION_DEPTH
+ size_t numSubTrees;
+ NodeRef subTrees[MAX_NUM_SUB_TREES];
+ };
+
+ template<int N, typename Mesh, typename Primitive>
+ class BVHNRefitT : public Builder, public BVHNRefitter<N>::LeafBoundsInterface
+ {
+ public:
+
+ /*! Type shortcuts */
+ typedef BVHN<N> BVH;
+ typedef typename BVH::AABBNode AABBNode;
+ typedef typename BVH::NodeRef NodeRef;
+
+ public:
+ BVHNRefitT (BVH* bvh, Builder* builder, Mesh* mesh, size_t mode);
+
+ virtual void build();
+
+ virtual void clear();
+
+ virtual const BBox3fa leafBounds (NodeRef& ref) const
+ {
+ size_t num; char* prim = ref.leaf(num);
+ if (unlikely(ref == BVH::emptyNode)) return empty;
+
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<num; i++)
+ bounds.extend(((Primitive*)prim)[i].update(mesh));
+ return bounds;
+ }
+
+ private:
+ BVH* bvh;
+ std::unique_ptr<Builder> builder;
+ std::unique_ptr<BVHNRefitter<N>> refitter;
+ Mesh* mesh;
+ unsigned int topologyVersion;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_rotate.cpp b/thirdparty/embree/kernels/bvh/bvh_rotate.cpp
new file mode 100644
index 0000000000..460bd60c62
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_rotate.cpp
@@ -0,0 +1,127 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh_rotate.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Computes half surface area of box. */
+ __forceinline float halfArea3f(const BBox<vfloat4>& box) {
+ const vfloat4 d = box.size();
+ const vfloat4 a = d*shuffle<1,2,0,3>(d);
+ return a[0]+a[1]+a[2];
+ }
+
+ size_t BVHNRotate<4>::rotate(NodeRef parentRef, size_t depth)
+ {
+ /*! nothing to rotate if we reached a leaf node. */
+ if (parentRef.isBarrier()) return 0;
+ if (parentRef.isLeaf()) return 0;
+ AABBNode* parent = parentRef.getAABBNode();
+
+ /*! rotate all children first */
+ vint4 cdepth;
+ for (size_t c=0; c<4; c++)
+ cdepth[c] = (int)rotate(parent->child(c),depth+1);
+
+ /* compute current areas of all children */
+ vfloat4 sizeX = parent->upper_x-parent->lower_x;
+ vfloat4 sizeY = parent->upper_y-parent->lower_y;
+ vfloat4 sizeZ = parent->upper_z-parent->lower_z;
+ vfloat4 childArea = madd(sizeX,(sizeY + sizeZ),sizeY*sizeZ);
+
+ /*! get node bounds */
+ BBox<vfloat4> child1_0,child1_1,child1_2,child1_3;
+ parent->bounds(child1_0,child1_1,child1_2,child1_3);
+
+ /*! Find best rotation. We pick a first child (child1) and a sub-child
+ (child2child) of a different second child (child2), and swap child1
+ and child2child. We perform the best such swap. */
+ float bestArea = 0;
+ size_t bestChild1 = -1, bestChild2 = -1, bestChild2Child = -1;
+ for (size_t c2=0; c2<4; c2++)
+ {
+ /*! ignore leaf nodes as we cannot descent into them */
+ if (parent->child(c2).isBarrier()) continue;
+ if (parent->child(c2).isLeaf()) continue;
+ AABBNode* child2 = parent->child(c2).getAABBNode();
+
+ /*! transpose child bounds */
+ BBox<vfloat4> child2c0,child2c1,child2c2,child2c3;
+ child2->bounds(child2c0,child2c1,child2c2,child2c3);
+
+ /*! put child1_0 at each child2 position */
+ float cost00 = halfArea3f(merge(child1_0,child2c1,child2c2,child2c3));
+ float cost01 = halfArea3f(merge(child2c0,child1_0,child2c2,child2c3));
+ float cost02 = halfArea3f(merge(child2c0,child2c1,child1_0,child2c3));
+ float cost03 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_0));
+ vfloat4 cost0 = vfloat4(cost00,cost01,cost02,cost03);
+ vfloat4 min0 = vreduce_min(cost0);
+ int pos0 = (int)bsf(movemask(min0 == cost0));
+
+ /*! put child1_1 at each child2 position */
+ float cost10 = halfArea3f(merge(child1_1,child2c1,child2c2,child2c3));
+ float cost11 = halfArea3f(merge(child2c0,child1_1,child2c2,child2c3));
+ float cost12 = halfArea3f(merge(child2c0,child2c1,child1_1,child2c3));
+ float cost13 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_1));
+ vfloat4 cost1 = vfloat4(cost10,cost11,cost12,cost13);
+ vfloat4 min1 = vreduce_min(cost1);
+ int pos1 = (int)bsf(movemask(min1 == cost1));
+
+ /*! put child1_2 at each child2 position */
+ float cost20 = halfArea3f(merge(child1_2,child2c1,child2c2,child2c3));
+ float cost21 = halfArea3f(merge(child2c0,child1_2,child2c2,child2c3));
+ float cost22 = halfArea3f(merge(child2c0,child2c1,child1_2,child2c3));
+ float cost23 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_2));
+ vfloat4 cost2 = vfloat4(cost20,cost21,cost22,cost23);
+ vfloat4 min2 = vreduce_min(cost2);
+ int pos2 = (int)bsf(movemask(min2 == cost2));
+
+ /*! put child1_3 at each child2 position */
+ float cost30 = halfArea3f(merge(child1_3,child2c1,child2c2,child2c3));
+ float cost31 = halfArea3f(merge(child2c0,child1_3,child2c2,child2c3));
+ float cost32 = halfArea3f(merge(child2c0,child2c1,child1_3,child2c3));
+ float cost33 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_3));
+ vfloat4 cost3 = vfloat4(cost30,cost31,cost32,cost33);
+ vfloat4 min3 = vreduce_min(cost3);
+ int pos3 = (int)bsf(movemask(min3 == cost3));
+
+ /*! find best other child */
+ vfloat4 area0123 = vfloat4(extract<0>(min0),extract<0>(min1),extract<0>(min2),extract<0>(min3)) - vfloat4(childArea[c2]);
+ int pos[4] = { pos0,pos1,pos2,pos3 };
+ const size_t mbd = BVH4::maxBuildDepth;
+ vbool4 valid = vint4(int(depth+1))+cdepth <= vint4(mbd); // only select swaps that fulfill depth constraints
+ valid &= vint4(int(c2)) != vint4(step);
+ if (none(valid)) continue;
+ size_t c1 = select_min(valid,area0123);
+ float area = area0123[c1];
+ if (c1 == c2) continue; // can happen if bounds are NANs
+
+ /*! accept a swap when it reduces cost and is not swapping a node with itself */
+ if (area < bestArea) {
+ bestArea = area;
+ bestChild1 = c1;
+ bestChild2 = c2;
+ bestChild2Child = pos[c1];
+ }
+ }
+
+ /*! if we did not find a swap that improves the SAH then do nothing */
+ if (bestChild1 == size_t(-1)) return 1+reduce_max(cdepth);
+
+ /*! perform the best found tree rotation */
+ AABBNode* child2 = parent->child(bestChild2).getAABBNode();
+ AABBNode::swap(parent,bestChild1,child2,bestChild2Child);
+ parent->setBounds(bestChild2,child2->bounds());
+ AABBNode::compact(parent);
+ AABBNode::compact(child2);
+
+ /*! This returned depth is conservative as the child that was
+ * pulled up in the tree could have been on the critical path. */
+ cdepth[bestChild1]++; // bestChild1 was pushed down one level
+ return 1+reduce_max(cdepth);
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_rotate.h b/thirdparty/embree/kernels/bvh/bvh_rotate.h
new file mode 100644
index 0000000000..61ef64a679
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_rotate.h
@@ -0,0 +1,37 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N>
+ class BVHNRotate
+ {
+ typedef typename BVHN<N>::NodeRef NodeRef;
+
+ public:
+ static const bool enabled = false;
+
+ static __forceinline size_t rotate(NodeRef parentRef, size_t depth = 1) { return 0; }
+ static __forceinline void restructure(NodeRef ref, size_t depth = 1) {}
+ };
+
+ /* BVH4 tree rotations */
+ template<>
+ class BVHNRotate<4>
+ {
+ typedef BVH4::AABBNode AABBNode;
+ typedef BVH4::NodeRef NodeRef;
+
+ public:
+ static const bool enabled = true;
+
+ static size_t rotate(NodeRef parentRef, size_t depth = 1);
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_statistics.cpp b/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
new file mode 100644
index 0000000000..d857ff7d95
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
@@ -0,0 +1,168 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bvh_statistics.h"
+#include "../../common/algorithms/parallel_reduce.h"
+
+namespace embree
+{
+ template<int N>
+ BVHNStatistics<N>::BVHNStatistics (BVH* bvh) : bvh(bvh)
+ {
+ double A = max(0.0f,bvh->getLinearBounds().expectedHalfArea());
+ stat = statistics(bvh->root,A,BBox1f(0.0f,1.0f));
+ }
+
+ template<int N>
+ std::string BVHNStatistics<N>::str()
+ {
+ std::ostringstream stream;
+ stream.setf(std::ios::fixed, std::ios::floatfield);
+ stream << " primitives = " << bvh->numPrimitives << ", vertices = " << bvh->numVertices << ", depth = " << stat.depth << std::endl;
+ size_t totalBytes = stat.bytes(bvh);
+ double totalSAH = stat.sah(bvh);
+ stream << " total : sah = " << std::setw(7) << std::setprecision(3) << totalSAH << " (100.00%), ";
+ stream << "#bytes = " << std::setw(7) << std::setprecision(2) << totalBytes/1E6 << " MB (100.00%), ";
+ stream << "#nodes = " << std::setw(7) << stat.size() << " (" << std::setw(6) << std::setprecision(2) << 100.0*stat.fillRate(bvh) << "% filled), ";
+ stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(totalBytes)/double(bvh->numPrimitives) << std::endl;
+ if (stat.statAABBNodes.numNodes ) stream << " getAABBNodes : " << stat.statAABBNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
+ if (stat.statOBBNodes.numNodes ) stream << " ungetAABBNodes : " << stat.statOBBNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
+ if (stat.statAABBNodesMB.numNodes ) stream << " getAABBNodesMB : " << stat.statAABBNodesMB.toString(bvh,totalSAH,totalBytes) << std::endl;
+ if (stat.statAABBNodesMB4D.numNodes) stream << " getAABBNodesMB4D : " << stat.statAABBNodesMB4D.toString(bvh,totalSAH,totalBytes) << std::endl;
+ if (stat.statOBBNodesMB.numNodes) stream << " ungetAABBNodesMB : " << stat.statOBBNodesMB.toString(bvh,totalSAH,totalBytes) << std::endl;
+ if (stat.statQuantizedNodes.numNodes ) stream << " quantizedNodes : " << stat.statQuantizedNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
+ if (true) stream << " leaves : " << stat.statLeaf.toString(bvh,totalSAH,totalBytes) << std::endl;
+ if (true) stream << " histogram : " << stat.statLeaf.histToString() << std::endl;
+ return stream.str();
+ }
+
+ template<int N>
+ typename BVHNStatistics<N>::Statistics BVHNStatistics<N>::statistics(NodeRef node, const double A, const BBox1f t0t1)
+ {
+ Statistics s;
+ assert(t0t1.size() > 0.0f);
+ double dt = max(0.0f,t0t1.size());
+ if (node.isAABBNode())
+ {
+ AABBNode* n = node.getAABBNode();
+ s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
+ if (n->child(i) == BVH::emptyNode) return Statistics();
+ const double Ai = max(0.0f,halfArea(n->extend(i)));
+ Statistics s = statistics(n->child(i),Ai,t0t1);
+ s.statAABBNodes.numChildren++;
+ return s;
+ }, Statistics::add);
+ s.statAABBNodes.numNodes++;
+ s.statAABBNodes.nodeSAH += dt*A;
+ s.depth++;
+ }
+ else if (node.isOBBNode())
+ {
+ OBBNode* n = node.ungetAABBNode();
+ s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
+ if (n->child(i) == BVH::emptyNode) return Statistics();
+ const double Ai = max(0.0f,halfArea(n->extent(i)));
+ Statistics s = statistics(n->child(i),Ai,t0t1);
+ s.statOBBNodes.numChildren++;
+ return s;
+ }, Statistics::add);
+ s.statOBBNodes.numNodes++;
+ s.statOBBNodes.nodeSAH += dt*A;
+ s.depth++;
+ }
+ else if (node.isAABBNodeMB())
+ {
+ AABBNodeMB* n = node.getAABBNodeMB();
+ s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
+ if (n->child(i) == BVH::emptyNode) return Statistics();
+ const double Ai = max(0.0f,n->expectedHalfArea(i,t0t1));
+ Statistics s = statistics(n->child(i),Ai,t0t1);
+ s.statAABBNodesMB.numChildren++;
+ return s;
+ }, Statistics::add);
+ s.statAABBNodesMB.numNodes++;
+ s.statAABBNodesMB.nodeSAH += dt*A;
+ s.depth++;
+ }
+ else if (node.isAABBNodeMB4D())
+ {
+ AABBNodeMB4D* n = node.getAABBNodeMB4D();
+ s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
+ if (n->child(i) == BVH::emptyNode) return Statistics();
+ const BBox1f t0t1i = intersect(t0t1,n->timeRange(i));
+ assert(!t0t1i.empty());
+ const double Ai = n->AABBNodeMB::expectedHalfArea(i,t0t1i);
+ Statistics s = statistics(n->child(i),Ai,t0t1i);
+ s.statAABBNodesMB4D.numChildren++;
+ return s;
+ }, Statistics::add);
+ s.statAABBNodesMB4D.numNodes++;
+ s.statAABBNodesMB4D.nodeSAH += dt*A;
+ s.depth++;
+ }
+ else if (node.isOBBNodeMB())
+ {
+ OBBNodeMB* n = node.ungetAABBNodeMB();
+ s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
+ if (n->child(i) == BVH::emptyNode) return Statistics();
+ const double Ai = max(0.0f,halfArea(n->extent0(i)));
+ Statistics s = statistics(n->child(i),Ai,t0t1);
+ s.statOBBNodesMB.numChildren++;
+ return s;
+ }, Statistics::add);
+ s.statOBBNodesMB.numNodes++;
+ s.statOBBNodesMB.nodeSAH += dt*A;
+ s.depth++;
+ }
+ else if (node.isQuantizedNode())
+ {
+ QuantizedNode* n = node.quantizedNode();
+ s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
+ if (n->child(i) == BVH::emptyNode) return Statistics();
+ const double Ai = max(0.0f,halfArea(n->extent(i)));
+ Statistics s = statistics(n->child(i),Ai,t0t1);
+ s.statQuantizedNodes.numChildren++;
+ return s;
+ }, Statistics::add);
+ s.statQuantizedNodes.numNodes++;
+ s.statQuantizedNodes.nodeSAH += dt*A;
+ s.depth++;
+ }
+ else if (node.isLeaf())
+ {
+ size_t num; const char* tri = node.leaf(num);
+ if (num)
+ {
+ for (size_t i=0; i<num; i++)
+ {
+ const size_t bytes = bvh->primTy->getBytes(tri);
+ s.statLeaf.numPrimsActive += bvh->primTy->sizeActive(tri);
+ s.statLeaf.numPrimsTotal += bvh->primTy->sizeTotal(tri);
+ s.statLeaf.numBytes += bytes;
+ tri+=bytes;
+ }
+ s.statLeaf.numLeaves++;
+ s.statLeaf.numPrimBlocks += num;
+ s.statLeaf.leafSAH += dt*A*num;
+ if (num-1 < Statistics::LeafStat::NHIST) {
+ s.statLeaf.numPrimBlocksHistogram[num-1]++;
+ }
+ }
+ }
+ else {
+ // -- GODOT start --
+ // throw std::runtime_error("not supported node type in bvh_statistics");
+ abort();
+ // -- GODOT end --
+ }
+ return s;
+ }
+
+#if defined(__AVX__)
+ template class BVHNStatistics<8>;
+#endif
+
+#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)
+ template class BVHNStatistics<4>;
+#endif
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_statistics.h b/thirdparty/embree/kernels/bvh/bvh_statistics.h
new file mode 100644
index 0000000000..a28e115f1c
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_statistics.h
@@ -0,0 +1,285 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+#include <sstream>
+
+namespace embree
+{
+ template<int N>
+ class BVHNStatistics
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::AABBNode AABBNode;
+ typedef typename BVH::OBBNode OBBNode;
+ typedef typename BVH::AABBNodeMB AABBNodeMB;
+ typedef typename BVH::AABBNodeMB4D AABBNodeMB4D;
+ typedef typename BVH::OBBNodeMB OBBNodeMB;
+ typedef typename BVH::QuantizedNode QuantizedNode;
+
+ typedef typename BVH::NodeRef NodeRef;
+
+ struct Statistics
+ {
+ template<typename Node>
+ struct NodeStat
+ {
+ NodeStat ( double nodeSAH = 0,
+ size_t numNodes = 0,
+ size_t numChildren = 0)
+ : nodeSAH(nodeSAH),
+ numNodes(numNodes),
+ numChildren(numChildren) {}
+
+ double sah(BVH* bvh) const {
+ return nodeSAH/bvh->getLinearBounds().expectedHalfArea();
+ }
+
+ size_t bytes() const {
+ return numNodes*sizeof(Node);
+ }
+
+ size_t size() const {
+ return numNodes;
+ }
+
+ double fillRateNom () const { return double(numChildren); }
+ double fillRateDen () const { return double(numNodes*N); }
+ double fillRate () const { return fillRateNom()/fillRateDen(); }
+
+ __forceinline friend NodeStat operator+ ( const NodeStat& a, const NodeStat& b)
+ {
+ return NodeStat(a.nodeSAH + b.nodeSAH,
+ a.numNodes+b.numNodes,
+ a.numChildren+b.numChildren);
+ }
+
+ std::string toString(BVH* bvh, double sahTotal, size_t bytesTotal) const
+ {
+ std::ostringstream stream;
+ stream.setf(std::ios::fixed, std::ios::floatfield);
+ stream << "sah = " << std::setw(7) << std::setprecision(3) << sah(bvh);
+ stream << " (" << std::setw(6) << std::setprecision(2) << 100.0*sah(bvh)/sahTotal << "%), ";
+ stream << "#bytes = " << std::setw(7) << std::setprecision(2) << bytes()/1E6 << " MB ";
+ stream << "(" << std::setw(6) << std::setprecision(2) << 100.0*double(bytes())/double(bytesTotal) << "%), ";
+ stream << "#nodes = " << std::setw(7) << numNodes << " (" << std::setw(6) << std::setprecision(2) << 100.0*fillRate() << "% filled), ";
+ stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytes())/double(bvh->numPrimitives);
+ return stream.str();
+ }
+
+ public:
+ double nodeSAH;
+ size_t numNodes;
+ size_t numChildren;
+ };
+
+ struct LeafStat
+ {
+ static const int NHIST = 8;
+
+ LeafStat ( double leafSAH = 0.0f,
+ size_t numLeaves = 0,
+ size_t numPrimsActive = 0,
+ size_t numPrimsTotal = 0,
+ size_t numPrimBlocks = 0,
+ size_t numBytes = 0)
+ : leafSAH(leafSAH),
+ numLeaves(numLeaves),
+ numPrimsActive(numPrimsActive),
+ numPrimsTotal(numPrimsTotal),
+ numPrimBlocks(numPrimBlocks),
+ numBytes(numBytes)
+ {
+ for (size_t i=0; i<NHIST; i++)
+ numPrimBlocksHistogram[i] = 0;
+ }
+
+ double sah(BVH* bvh) const {
+ return leafSAH/bvh->getLinearBounds().expectedHalfArea();
+ }
+
+ size_t bytes(BVH* bvh) const {
+ return numBytes;
+ }
+
+ size_t size() const {
+ return numLeaves;
+ }
+
+ double fillRateNom (BVH* bvh) const { return double(numPrimsActive); }
+ double fillRateDen (BVH* bvh) const { return double(numPrimsTotal); }
+ double fillRate (BVH* bvh) const { return fillRateNom(bvh)/fillRateDen(bvh); }
+
+ __forceinline friend LeafStat operator+ ( const LeafStat& a, const LeafStat& b)
+ {
+ LeafStat stat(a.leafSAH + b.leafSAH,
+ a.numLeaves+b.numLeaves,
+ a.numPrimsActive+b.numPrimsActive,
+ a.numPrimsTotal+b.numPrimsTotal,
+ a.numPrimBlocks+b.numPrimBlocks,
+ a.numBytes+b.numBytes);
+ for (size_t i=0; i<NHIST; i++) {
+ stat.numPrimBlocksHistogram[i] += a.numPrimBlocksHistogram[i];
+ stat.numPrimBlocksHistogram[i] += b.numPrimBlocksHistogram[i];
+ }
+ return stat;
+ }
+
+ std::string toString(BVH* bvh, double sahTotal, size_t bytesTotal) const
+ {
+ std::ostringstream stream;
+ stream.setf(std::ios::fixed, std::ios::floatfield);
+ stream << "sah = " << std::setw(7) << std::setprecision(3) << sah(bvh);
+ stream << " (" << std::setw(6) << std::setprecision(2) << 100.0*sah(bvh)/sahTotal << "%), ";
+ stream << "#bytes = " << std::setw(7) << std::setprecision(2) << double(bytes(bvh))/1E6 << " MB ";
+ stream << "(" << std::setw(6) << std::setprecision(2) << 100.0*double(bytes(bvh))/double(bytesTotal) << "%), ";
+ stream << "#nodes = " << std::setw(7) << numLeaves << " (" << std::setw(6) << std::setprecision(2) << 100.0*fillRate(bvh) << "% filled), ";
+ stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytes(bvh))/double(bvh->numPrimitives);
+ return stream.str();
+ }
+
+ std::string histToString() const
+ {
+ std::ostringstream stream;
+ stream.setf(std::ios::fixed, std::ios::floatfield);
+ for (size_t i=0; i<NHIST; i++)
+ stream << std::setw(6) << std::setprecision(2) << 100.0f*float(numPrimBlocksHistogram[i])/float(numLeaves) << "% ";
+ return stream.str();
+ }
+
+ public:
+ double leafSAH; //!< SAH of the leaves only
+ size_t numLeaves; //!< Number of leaf nodes.
+ size_t numPrimsActive; //!< Number of active primitives (
+ size_t numPrimsTotal; //!< Number of active and inactive primitives
+ size_t numPrimBlocks; //!< Number of primitive blocks.
+ size_t numBytes; //!< Number of bytes of leaves.
+ size_t numPrimBlocksHistogram[8];
+ };
+
+ public:
+ Statistics (size_t depth = 0,
+ LeafStat statLeaf = LeafStat(),
+ NodeStat<AABBNode> statAABBNodes = NodeStat<AABBNode>(),
+ NodeStat<OBBNode> statOBBNodes = NodeStat<OBBNode>(),
+ NodeStat<AABBNodeMB> statAABBNodesMB = NodeStat<AABBNodeMB>(),
+ NodeStat<AABBNodeMB4D> statAABBNodesMB4D = NodeStat<AABBNodeMB4D>(),
+ NodeStat<OBBNodeMB> statOBBNodesMB = NodeStat<OBBNodeMB>(),
+ NodeStat<QuantizedNode> statQuantizedNodes = NodeStat<QuantizedNode>())
+
+ : depth(depth),
+ statLeaf(statLeaf),
+ statAABBNodes(statAABBNodes),
+ statOBBNodes(statOBBNodes),
+ statAABBNodesMB(statAABBNodesMB),
+ statAABBNodesMB4D(statAABBNodesMB4D),
+ statOBBNodesMB(statOBBNodesMB),
+ statQuantizedNodes(statQuantizedNodes) {}
+
+ double sah(BVH* bvh) const
+ {
+ return statLeaf.sah(bvh) +
+ statAABBNodes.sah(bvh) +
+ statOBBNodes.sah(bvh) +
+ statAABBNodesMB.sah(bvh) +
+ statAABBNodesMB4D.sah(bvh) +
+ statOBBNodesMB.sah(bvh) +
+ statQuantizedNodes.sah(bvh);
+ }
+
+ size_t bytes(BVH* bvh) const {
+ return statLeaf.bytes(bvh) +
+ statAABBNodes.bytes() +
+ statOBBNodes.bytes() +
+ statAABBNodesMB.bytes() +
+ statAABBNodesMB4D.bytes() +
+ statOBBNodesMB.bytes() +
+ statQuantizedNodes.bytes();
+ }
+
+ size_t size() const
+ {
+ return statLeaf.size() +
+ statAABBNodes.size() +
+ statOBBNodes.size() +
+ statAABBNodesMB.size() +
+ statAABBNodesMB4D.size() +
+ statOBBNodesMB.size() +
+ statQuantizedNodes.size();
+ }
+
+ double fillRate (BVH* bvh) const
+ {
+ double nom = statLeaf.fillRateNom(bvh) +
+ statAABBNodes.fillRateNom() +
+ statOBBNodes.fillRateNom() +
+ statAABBNodesMB.fillRateNom() +
+ statAABBNodesMB4D.fillRateNom() +
+ statOBBNodesMB.fillRateNom() +
+ statQuantizedNodes.fillRateNom();
+ double den = statLeaf.fillRateDen(bvh) +
+ statAABBNodes.fillRateDen() +
+ statOBBNodes.fillRateDen() +
+ statAABBNodesMB.fillRateDen() +
+ statAABBNodesMB4D.fillRateDen() +
+ statOBBNodesMB.fillRateDen() +
+ statQuantizedNodes.fillRateDen();
+ return nom/den;
+ }
+
+ friend Statistics operator+ ( const Statistics& a, const Statistics& b )
+ {
+ return Statistics(max(a.depth,b.depth),
+ a.statLeaf + b.statLeaf,
+ a.statAABBNodes + b.statAABBNodes,
+ a.statOBBNodes + b.statOBBNodes,
+ a.statAABBNodesMB + b.statAABBNodesMB,
+ a.statAABBNodesMB4D + b.statAABBNodesMB4D,
+ a.statOBBNodesMB + b.statOBBNodesMB,
+ a.statQuantizedNodes + b.statQuantizedNodes);
+ }
+
+ static Statistics add ( const Statistics& a, const Statistics& b ) {
+ return a+b;
+ }
+
+ public:
+ size_t depth;
+ LeafStat statLeaf;
+ NodeStat<AABBNode> statAABBNodes;
+ NodeStat<OBBNode> statOBBNodes;
+ NodeStat<AABBNodeMB> statAABBNodesMB;
+ NodeStat<AABBNodeMB4D> statAABBNodesMB4D;
+ NodeStat<OBBNodeMB> statOBBNodesMB;
+ NodeStat<QuantizedNode> statQuantizedNodes;
+ };
+
+ public:
+
+ /* Constructor gathers statistics. */
+ BVHNStatistics (BVH* bvh);
+
+ /*! Convert statistics into a string */
+ std::string str();
+
+ double sah() const {
+ return stat.sah(bvh);
+ }
+
+ size_t bytesUsed() const {
+ return stat.bytes(bvh);
+ }
+
+ private:
+ Statistics statistics(NodeRef node, const double A, const BBox1f dt);
+
+ private:
+ BVH* bvh;
+ Statistics stat;
+ };
+
+ typedef BVHNStatistics<4> BVH4Statistics;
+ typedef BVHNStatistics<8> BVH8Statistics;
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_traverser1.h b/thirdparty/embree/kernels/bvh/bvh_traverser1.h
new file mode 100644
index 0000000000..8ce01b57f5
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_traverser1.h
@@ -0,0 +1,466 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+#include "node_intersector1.h"
+#include "../common/stack_item.h"
+
+#define NEW_SORTING_CODE 1
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! BVH regular node traversal for single rays. */
+ template<int N, int types>
+ class BVHNNodeTraverser1Hit;
+
+#if defined(__AVX512VL__) // SKX
+
+ template<int N>
+ __forceinline void isort_update(vint<N> &dist, const vint<N> &d)
+ {
+ const vint<N> dist_shift = align_shift_right<N-1>(dist,dist);
+ const vboolf<N> m_geq = d >= dist;
+ const vboolf<N> m_geq_shift = m_geq << 1;
+ dist = select(m_geq,d,dist);
+ dist = select(m_geq_shift,dist_shift,dist);
+ }
+
+ template<int N>
+ __forceinline void isort_quick_update(vint<N> &dist, const vint<N> &d) {
+ dist = align_shift_right<N-1>(dist,permute(d,vint<N>(zero)));
+ }
+
+ __forceinline size_t permuteExtract(const vint8& index, const vllong4& n0, const vllong4& n1) {
+ return toScalar(permutex2var((__m256i)index,n0,n1));
+ }
+
+ __forceinline float permuteExtract(const vint8& index, const vfloat8& n) {
+ return toScalar(permute(n,index));
+ }
+
+#endif
+
+ /* Specialization for BVH4. */
+ template<int types>
+ class BVHNNodeTraverser1Hit<4, types>
+ {
+ typedef BVH4 BVH;
+ typedef BVH4::NodeRef NodeRef;
+ typedef BVH4::BaseNode BaseNode;
+
+
+ public:
+ /* Traverses a node with at least one hit child. Optimized for finding the closest hit (intersection). */
+ static __forceinline void traverseClosestHit(NodeRef& cur,
+ size_t mask,
+ const vfloat4& tNear,
+ StackItemT<NodeRef>*& stackPtr,
+ StackItemT<NodeRef>* stackEnd)
+ {
+ assert(mask != 0);
+ const BaseNode* node = cur.baseNode();
+
+ /*! one child is hit, continue with that child */
+ size_t r = bscf(mask);
+ cur = node->child(r);
+ BVH::prefetch(cur,types);
+ if (likely(mask == 0)) {
+ assert(cur != BVH::emptyNode);
+ return;
+ }
+
+ /*! two children are hit, push far child, and continue with closer child */
+ NodeRef c0 = cur;
+ const unsigned int d0 = ((unsigned int*)&tNear)[r];
+ r = bscf(mask);
+ NodeRef c1 = node->child(r);
+ BVH::prefetch(c1,types);
+ const unsigned int d1 = ((unsigned int*)&tNear)[r];
+ assert(c0 != BVH::emptyNode);
+ assert(c1 != BVH::emptyNode);
+ if (likely(mask == 0)) {
+ assert(stackPtr < stackEnd);
+ if (d0 < d1) { stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++; cur = c0; return; }
+ else { stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++; cur = c1; return; }
+ }
+
+#if NEW_SORTING_CODE == 1
+ vint4 s0((size_t)c0,(size_t)d0);
+ vint4 s1((size_t)c1,(size_t)d1);
+ r = bscf(mask);
+ NodeRef c2 = node->child(r); BVH::prefetch(c2,types); unsigned int d2 = ((unsigned int*)&tNear)[r];
+ vint4 s2((size_t)c2,(size_t)d2);
+ /* 3 hits */
+ if (likely(mask == 0)) {
+ StackItemT<NodeRef>::sort3(s0,s1,s2);
+ *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1;
+ cur = toSizeT(s2);
+ stackPtr+=2;
+ return;
+ }
+ r = bscf(mask);
+ NodeRef c3 = node->child(r); BVH::prefetch(c3,types); unsigned int d3 = ((unsigned int*)&tNear)[r];
+ vint4 s3((size_t)c3,(size_t)d3);
+ /* 4 hits */
+ StackItemT<NodeRef>::sort4(s0,s1,s2,s3);
+ *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1; *(vint4*)&stackPtr[2] = s2;
+ cur = toSizeT(s3);
+ stackPtr+=3;
+#else
+ /*! Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there. */
+ assert(stackPtr < stackEnd);
+ stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++;
+ assert(stackPtr < stackEnd);
+ stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++;
+
+ /*! three children are hit, push all onto stack and sort 3 stack items, continue with closest child */
+ assert(stackPtr < stackEnd);
+ r = bscf(mask);
+ NodeRef c = node->child(r); BVH::prefetch(c,types); unsigned int d = ((unsigned int*)&tNear)[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
+ assert(c != BVH::emptyNode);
+ if (likely(mask == 0)) {
+ sort(stackPtr[-1],stackPtr[-2],stackPtr[-3]);
+ cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
+ return;
+ }
+
+ /*! four children are hit, push all onto stack and sort 4 stack items, continue with closest child */
+ assert(stackPtr < stackEnd);
+ r = bscf(mask);
+ c = node->child(r); BVH::prefetch(c,types); d = *(unsigned int*)&tNear[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
+ assert(c != BVH::emptyNode);
+ sort(stackPtr[-1],stackPtr[-2],stackPtr[-3],stackPtr[-4]);
+ cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
+#endif
+ }
+
+ /* Traverses a node with at least one hit child. Optimized for finding any hit (occlusion). */
+ static __forceinline void traverseAnyHit(NodeRef& cur,
+ size_t mask,
+ const vfloat4& tNear,
+ NodeRef*& stackPtr,
+ NodeRef* stackEnd)
+ {
+ const BaseNode* node = cur.baseNode();
+
+ /*! one child is hit, continue with that child */
+ size_t r = bscf(mask);
+ cur = node->child(r);
+ BVH::prefetch(cur,types);
+
+ /* simpler in sequence traversal order */
+ assert(cur != BVH::emptyNode);
+ if (likely(mask == 0)) return;
+ assert(stackPtr < stackEnd);
+ *stackPtr = cur; stackPtr++;
+
+ for (; ;)
+ {
+ r = bscf(mask);
+ cur = node->child(r); BVH::prefetch(cur,types);
+ assert(cur != BVH::emptyNode);
+ if (likely(mask == 0)) return;
+ assert(stackPtr < stackEnd);
+ *stackPtr = cur; stackPtr++;
+ }
+ }
+ };
+
+ /* Specialization for BVH8. */
+ template<int types>
+ class BVHNNodeTraverser1Hit<8, types>
+ {
+ typedef BVH8 BVH;
+ typedef BVH8::NodeRef NodeRef;
+ typedef BVH8::BaseNode BaseNode;
+
+#if defined(__AVX512VL__)
+ template<class NodeRef, class BaseNode>
+ static __forceinline void traverseClosestHitAVX512VL8(NodeRef& cur,
+ size_t mask,
+ const vfloat8& tNear,
+ StackItemT<NodeRef>*& stackPtr,
+ StackItemT<NodeRef>* stackEnd)
+ {
+ assert(mask != 0);
+ const BaseNode* node = cur.baseNode();
+ const vllong4 n0 = vllong4::loadu((vllong4*)&node->children[0]);
+ const vllong4 n1 = vllong4::loadu((vllong4*)&node->children[4]);
+ vint8 distance_i = (asInt(tNear) & 0xfffffff8) | vint8(step);
+ distance_i = vint8::compact((int)mask,distance_i,distance_i);
+ cur = permuteExtract(distance_i,n0,n1);
+ BVH::prefetch(cur,types);
+
+ mask &= mask-1;
+ if (likely(mask == 0)) return;
+
+ /* 2 hits: order A0 B0 */
+ const vint8 d0(distance_i);
+ const vint8 d1(shuffle<1>(distance_i));
+ cur = permuteExtract(d1,n0,n1);
+ BVH::prefetch(cur,types);
+
+ const vint8 dist_A0 = min(d0, d1);
+ const vint8 dist_B0 = max(d0, d1);
+ assert(dist_A0[0] < dist_B0[0]);
+
+ mask &= mask-1;
+ if (likely(mask == 0)) {
+ cur = permuteExtract(dist_A0,n0,n1);
+ stackPtr[0].ptr = permuteExtract(dist_B0,n0,n1);
+ *(float*)&stackPtr[0].dist = permuteExtract(dist_B0,tNear);
+ stackPtr++;
+ return;
+ }
+
+ /* 3 hits: order A1 B1 C1 */
+
+ const vint8 d2(shuffle<2>(distance_i));
+ cur = permuteExtract(d2,n0,n1);
+ BVH::prefetch(cur,types);
+
+ const vint8 dist_A1 = min(dist_A0,d2);
+ const vint8 dist_tmp_B1 = max(dist_A0,d2);
+ const vint8 dist_B1 = min(dist_B0,dist_tmp_B1);
+ const vint8 dist_C1 = max(dist_B0,dist_tmp_B1);
+ assert(dist_A1[0] < dist_B1[0]);
+ assert(dist_B1[0] < dist_C1[0]);
+
+ mask &= mask-1;
+ if (likely(mask == 0)) {
+ cur = permuteExtract(dist_A1,n0,n1);
+ stackPtr[0].ptr = permuteExtract(dist_C1,n0,n1);
+ *(float*)&stackPtr[0].dist = permuteExtract(dist_C1,tNear);
+ stackPtr[1].ptr = permuteExtract(dist_B1,n0,n1);
+ *(float*)&stackPtr[1].dist = permuteExtract(dist_B1,tNear);
+ stackPtr+=2;
+ return;
+ }
+
+ /* 4 hits: order A2 B2 C2 D2 */
+
+ const vint8 d3(shuffle<3>(distance_i));
+ cur = permuteExtract(d3,n0,n1);
+ BVH::prefetch(cur,types);
+
+ const vint8 dist_A2 = min(dist_A1,d3);
+ const vint8 dist_tmp_B2 = max(dist_A1,d3);
+ const vint8 dist_B2 = min(dist_B1,dist_tmp_B2);
+ const vint8 dist_tmp_C2 = max(dist_B1,dist_tmp_B2);
+ const vint8 dist_C2 = min(dist_C1,dist_tmp_C2);
+ const vint8 dist_D2 = max(dist_C1,dist_tmp_C2);
+ assert(dist_A2[0] < dist_B2[0]);
+ assert(dist_B2[0] < dist_C2[0]);
+ assert(dist_C2[0] < dist_D2[0]);
+
+ mask &= mask-1;
+ if (likely(mask == 0)) {
+ cur = permuteExtract(dist_A2,n0,n1);
+ stackPtr[0].ptr = permuteExtract(dist_D2,n0,n1);
+ *(float*)&stackPtr[0].dist = permuteExtract(dist_D2,tNear);
+ stackPtr[1].ptr = permuteExtract(dist_C2,n0,n1);
+ *(float*)&stackPtr[1].dist = permuteExtract(dist_C2,tNear);
+ stackPtr[2].ptr = permuteExtract(dist_B2,n0,n1);
+ *(float*)&stackPtr[2].dist = permuteExtract(dist_B2,tNear);
+ stackPtr+=3;
+ return;
+ }
+
+ /* >=5 hits: reverse to descending order for writing to stack */
+
+ distance_i = align_shift_right<3>(distance_i,distance_i);
+ const size_t hits = 4 + popcnt(mask);
+ vint8 dist(INT_MIN); // this will work with -0.0f (0x80000000) as distance, isort_update uses >= to insert
+
+ isort_quick_update<8>(dist,dist_A2);
+ isort_quick_update<8>(dist,dist_B2);
+ isort_quick_update<8>(dist,dist_C2);
+ isort_quick_update<8>(dist,dist_D2);
+
+ do {
+
+ distance_i = align_shift_right<1>(distance_i,distance_i);
+ cur = permuteExtract(distance_i,n0,n1);
+ BVH::prefetch(cur,types);
+ const vint8 new_dist(permute(distance_i,vint8(zero)));
+ mask &= mask-1;
+ isort_update<8>(dist,new_dist);
+
+ } while(mask);
+
+ for (size_t i=0; i<7; i++)
+ assert(dist[i+0]>=dist[i+1]);
+
+ for (size_t i=0;i<hits-1;i++)
+ {
+ stackPtr->ptr = permuteExtract(dist,n0,n1);
+ *(float*)&stackPtr->dist = permuteExtract(dist,tNear);
+ dist = align_shift_right<1>(dist,dist);
+ stackPtr++;
+ }
+ cur = permuteExtract(dist,n0,n1);
+ }
+#endif
+
+ public:
+ static __forceinline void traverseClosestHit(NodeRef& cur,
+ size_t mask,
+ const vfloat8& tNear,
+ StackItemT<NodeRef>*& stackPtr,
+ StackItemT<NodeRef>* stackEnd)
+ {
+ assert(mask != 0);
+#if defined(__AVX512VL__)
+ traverseClosestHitAVX512VL8<NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd);
+#else
+
+ const BaseNode* node = cur.baseNode();
+
+ /*! one child is hit, continue with that child */
+ size_t r = bscf(mask);
+ cur = node->child(r);
+ BVH::prefetch(cur,types);
+ if (likely(mask == 0)) {
+ assert(cur != BVH::emptyNode);
+ return;
+ }
+
+ /*! two children are hit, push far child, and continue with closer child */
+ NodeRef c0 = cur;
+ const unsigned int d0 = ((unsigned int*)&tNear)[r];
+ r = bscf(mask);
+ NodeRef c1 = node->child(r);
+ BVH::prefetch(c1,types);
+ const unsigned int d1 = ((unsigned int*)&tNear)[r];
+
+ assert(c0 != BVH::emptyNode);
+ assert(c1 != BVH::emptyNode);
+ if (likely(mask == 0)) {
+ assert(stackPtr < stackEnd);
+ if (d0 < d1) { stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++; cur = c0; return; }
+ else { stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++; cur = c1; return; }
+ }
+#if NEW_SORTING_CODE == 1
+ vint4 s0((size_t)c0,(size_t)d0);
+ vint4 s1((size_t)c1,(size_t)d1);
+
+ r = bscf(mask);
+ NodeRef c2 = node->child(r); BVH::prefetch(c2,types); unsigned int d2 = ((unsigned int*)&tNear)[r];
+ vint4 s2((size_t)c2,(size_t)d2);
+ /* 3 hits */
+ if (likely(mask == 0)) {
+ StackItemT<NodeRef>::sort3(s0,s1,s2);
+ *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1;
+ cur = toSizeT(s2);
+ stackPtr+=2;
+ return;
+ }
+ r = bscf(mask);
+ NodeRef c3 = node->child(r); BVH::prefetch(c3,types); unsigned int d3 = ((unsigned int*)&tNear)[r];
+ vint4 s3((size_t)c3,(size_t)d3);
+ /* 4 hits */
+ if (likely(mask == 0)) {
+ StackItemT<NodeRef>::sort4(s0,s1,s2,s3);
+ *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1; *(vint4*)&stackPtr[2] = s2;
+ cur = toSizeT(s3);
+ stackPtr+=3;
+ return;
+ }
+ *(vint4*)&stackPtr[0] = s0; *(vint4*)&stackPtr[1] = s1; *(vint4*)&stackPtr[2] = s2; *(vint4*)&stackPtr[3] = s3;
+ /*! fallback case if more than 4 children are hit */
+ StackItemT<NodeRef>* stackFirst = stackPtr;
+ stackPtr+=4;
+ while (1)
+ {
+ assert(stackPtr < stackEnd);
+ r = bscf(mask);
+ NodeRef c = node->child(r); BVH::prefetch(c,types); unsigned int d = *(unsigned int*)&tNear[r];
+ const vint4 s((size_t)c,(size_t)d);
+ *(vint4*)stackPtr++ = s;
+ assert(c != BVH::emptyNode);
+ if (unlikely(mask == 0)) break;
+ }
+ sort(stackFirst,stackPtr);
+ cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
+#else
+ /*! Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there. */
+ assert(stackPtr < stackEnd);
+ stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++;
+ assert(stackPtr < stackEnd);
+ stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++;
+
+ /*! three children are hit, push all onto stack and sort 3 stack items, continue with closest child */
+ assert(stackPtr < stackEnd);
+ r = bscf(mask);
+ NodeRef c = node->child(r); BVH::prefetch(c,types); unsigned int d = ((unsigned int*)&tNear)[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
+ assert(c != BVH::emptyNode);
+ if (likely(mask == 0)) {
+ sort(stackPtr[-1],stackPtr[-2],stackPtr[-3]);
+ cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
+ return;
+ }
+
+ /*! four children are hit, push all onto stack and sort 4 stack items, continue with closest child */
+ assert(stackPtr < stackEnd);
+ r = bscf(mask);
+ c = node->child(r); BVH::prefetch(c,types); d = *(unsigned int*)&tNear[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
+ assert(c != BVH::emptyNode);
+ if (likely(mask == 0)) {
+ sort(stackPtr[-1],stackPtr[-2],stackPtr[-3],stackPtr[-4]);
+ cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
+ return;
+ }
+ /*! fallback case if more than 4 children are hit */
+ StackItemT<NodeRef>* stackFirst = stackPtr-4;
+ while (1)
+ {
+ assert(stackPtr < stackEnd);
+ r = bscf(mask);
+ c = node->child(r); BVH::prefetch(c,types); d = *(unsigned int*)&tNear[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
+ assert(c != BVH::emptyNode);
+ if (unlikely(mask == 0)) break;
+ }
+ sort(stackFirst,stackPtr);
+ cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
+#endif
+#endif
+ }
+
+ static __forceinline void traverseAnyHit(NodeRef& cur,
+ size_t mask,
+ const vfloat8& tNear,
+ NodeRef*& stackPtr,
+ NodeRef* stackEnd)
+ {
+ const BaseNode* node = cur.baseNode();
+
+ /*! one child is hit, continue with that child */
+ size_t r = bscf(mask);
+ cur = node->child(r);
+ BVH::prefetch(cur,types);
+
+ /* simpler in sequence traversal order */
+ assert(cur != BVH::emptyNode);
+ if (likely(mask == 0)) return;
+ assert(stackPtr < stackEnd);
+ *stackPtr = cur; stackPtr++;
+
+ for (; ;)
+ {
+ r = bscf(mask);
+ cur = node->child(r); BVH::prefetch(cur,types);
+ assert(cur != BVH::emptyNode);
+ if (likely(mask == 0)) return;
+ assert(stackPtr < stackEnd);
+ *stackPtr = cur; stackPtr++;
+ }
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/bvh_traverser_stream.h b/thirdparty/embree/kernels/bvh/bvh_traverser_stream.h
new file mode 100644
index 0000000000..852981e69d
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/bvh_traverser_stream.h
@@ -0,0 +1,149 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+#include "../common/ray.h"
+#include "../common/stack_item.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N, int types>
+ class BVHNNodeTraverserStreamHitCoherent
+ {
+ typedef BVHN<N> BVH;
+ typedef typename BVH::NodeRef NodeRef;
+ typedef typename BVH::BaseNode BaseNode;
+
+ public:
+ template<class T>
+ static __forceinline void traverseClosestHit(NodeRef& cur,
+ size_t& m_trav_active,
+ const vbool<N>& vmask,
+ const vfloat<N>& tNear,
+ const T* const tMask,
+ StackItemMaskCoherent*& stackPtr)
+ {
+ const NodeRef parent = cur;
+ size_t mask = movemask(vmask);
+ assert(mask != 0);
+ const BaseNode* node = cur.baseNode();
+
+ /*! one child is hit, continue with that child */
+ const size_t r0 = bscf(mask);
+ assert(r0 < 8);
+ cur = node->child(r0);
+ BVHN<N>::prefetch(cur,types);
+ m_trav_active = tMask[r0];
+ assert(cur != BVH::emptyNode);
+ if (unlikely(mask == 0)) return;
+
+ const unsigned int* const tNear_i = (unsigned int*)&tNear;
+
+ /*! two children are hit, push far child, and continue with closer child */
+ NodeRef c0 = cur;
+ unsigned int d0 = tNear_i[r0];
+ const size_t r1 = bscf(mask);
+ assert(r1 < 8);
+ NodeRef c1 = node->child(r1);
+ BVHN<N>::prefetch(c1,types);
+ unsigned int d1 = tNear_i[r1];
+
+ assert(c0 != BVH::emptyNode);
+ assert(c1 != BVH::emptyNode);
+ if (likely(mask == 0)) {
+ if (d0 < d1) {
+ assert(tNear[r1] >= 0.0f);
+ stackPtr->mask = tMask[r1];
+ stackPtr->parent = parent;
+ stackPtr->child = c1;
+ stackPtr++;
+ cur = c0;
+ m_trav_active = tMask[r0];
+ return;
+ }
+ else {
+ assert(tNear[r0] >= 0.0f);
+ stackPtr->mask = tMask[r0];
+ stackPtr->parent = parent;
+ stackPtr->child = c0;
+ stackPtr++;
+ cur = c1;
+ m_trav_active = tMask[r1];
+ return;
+ }
+ }
+
+ /*! slow path for more than two hits */
+ size_t hits = movemask(vmask);
+ const vint<N> dist_i = select(vmask, (asInt(tNear) & 0xfffffff8) | vint<N>(step), 0);
+ const vint<N> dist_i_sorted = usort_descending(dist_i);
+ const vint<N> sorted_index = dist_i_sorted & 7;
+
+ size_t i = 0;
+ for (;;)
+ {
+ const unsigned int index = sorted_index[i];
+ assert(index < 8);
+ cur = node->child(index);
+ m_trav_active = tMask[index];
+ assert(m_trav_active);
+ BVHN<N>::prefetch(cur,types);
+ bscf(hits);
+ if (unlikely(hits==0)) break;
+ i++;
+ assert(cur != BVH::emptyNode);
+ assert(tNear[index] >= 0.0f);
+ stackPtr->mask = m_trav_active;
+ stackPtr->parent = parent;
+ stackPtr->child = cur;
+ stackPtr++;
+ }
+ }
+
+ template<class T>
+ static __forceinline void traverseAnyHit(NodeRef& cur,
+ size_t& m_trav_active,
+ const vbool<N>& vmask,
+ const T* const tMask,
+ StackItemMaskCoherent*& stackPtr)
+ {
+ const NodeRef parent = cur;
+ size_t mask = movemask(vmask);
+ assert(mask != 0);
+ const BaseNode* node = cur.baseNode();
+
+ /*! one child is hit, continue with that child */
+ size_t r = bscf(mask);
+ cur = node->child(r);
+ BVHN<N>::prefetch(cur,types);
+ m_trav_active = tMask[r];
+
+ /* simple in order sequence */
+ assert(cur != BVH::emptyNode);
+ if (likely(mask == 0)) return;
+ stackPtr->mask = m_trav_active;
+ stackPtr->parent = parent;
+ stackPtr->child = cur;
+ stackPtr++;
+
+ for (; ;)
+ {
+ r = bscf(mask);
+ cur = node->child(r);
+ BVHN<N>::prefetch(cur,types);
+ m_trav_active = tMask[r];
+ assert(cur != BVH::emptyNode);
+ if (likely(mask == 0)) return;
+ stackPtr->mask = m_trav_active;
+ stackPtr->parent = parent;
+ stackPtr->child = cur;
+ stackPtr++;
+ }
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/node_intersector.h b/thirdparty/embree/kernels/bvh/node_intersector.h
new file mode 100644
index 0000000000..25edaf295d
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/node_intersector.h
@@ -0,0 +1,31 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bvh.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct NearFarPrecalculations
+ {
+ size_t nearX, nearY, nearZ;
+ size_t farX, farY, farZ;
+
+ __forceinline NearFarPrecalculations() {}
+
+ __forceinline NearFarPrecalculations(const Vec3fa& dir, size_t N)
+ {
+ const size_t size = sizeof(float)*N;
+ nearX = (dir.x < 0.0f) ? 1*size : 0*size;
+ nearY = (dir.y < 0.0f) ? 3*size : 2*size;
+ nearZ = (dir.z < 0.0f) ? 5*size : 4*size;
+ farX = nearX ^ size;
+ farY = nearY ^ size;
+ farZ = nearZ ^ size;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/node_intersector1.h b/thirdparty/embree/kernels/bvh/node_intersector1.h
new file mode 100644
index 0000000000..1ec4fc63fc
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/node_intersector1.h
@@ -0,0 +1,1403 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "node_intersector.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Ray structure used in single-ray traversal
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, bool robust>
+ struct TravRayBase;
+
+ /* Base (without tnear and tfar) */
+ template<int N>
+ struct TravRayBase<N,false>
+ {
+ __forceinline TravRayBase() {}
+
+ __forceinline TravRayBase(const Vec3fa& ray_org, const Vec3fa& ray_dir)
+ : org_xyz(ray_org), dir_xyz(ray_dir)
+ {
+ const Vec3fa ray_rdir = rcp_safe(ray_dir);
+ org = Vec3vf<N>(ray_org.x,ray_org.y,ray_org.z);
+ dir = Vec3vf<N>(ray_dir.x,ray_dir.y,ray_dir.z);
+ rdir = Vec3vf<N>(ray_rdir.x,ray_rdir.y,ray_rdir.z);
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const Vec3fa ray_org_rdir = ray_org*ray_rdir;
+ org_rdir = Vec3vf<N>(ray_org_rdir.x,ray_org_rdir.y,ray_org_rdir.z);
+#endif
+ nearX = ray_rdir.x >= 0.0f ? 0*sizeof(vfloat<N>) : 1*sizeof(vfloat<N>);
+ nearY = ray_rdir.y >= 0.0f ? 2*sizeof(vfloat<N>) : 3*sizeof(vfloat<N>);
+ nearZ = ray_rdir.z >= 0.0f ? 4*sizeof(vfloat<N>) : 5*sizeof(vfloat<N>);
+ farX = nearX ^ sizeof(vfloat<N>);
+ farY = nearY ^ sizeof(vfloat<N>);
+ farZ = nearZ ^ sizeof(vfloat<N>);
+ }
+
+ template<int K>
+ __forceinline void init(size_t k, const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir,
+ const Vec3vf<K>& ray_rdir, const Vec3vi<K>& nearXYZ,
+ size_t flip = sizeof(vfloat<N>))
+ {
+ org = Vec3vf<N>(ray_org.x[k], ray_org.y[k], ray_org.z[k]);
+ dir = Vec3vf<N>(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]);
+ rdir = Vec3vf<N>(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]);
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ org_rdir = org*rdir;
+#endif
+ nearX = nearXYZ.x[k];
+ nearY = nearXYZ.y[k];
+ nearZ = nearXYZ.z[k];
+ farX = nearX ^ flip;
+ farY = nearY ^ flip;
+ farZ = nearZ ^ flip;
+ }
+
+ Vec3fa org_xyz, dir_xyz;
+ Vec3vf<N> org, dir, rdir;
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ Vec3vf<N> org_rdir;
+#endif
+ size_t nearX, nearY, nearZ;
+ size_t farX, farY, farZ;
+ };
+
+ /* Base (without tnear and tfar) */
+ template<int N>
+ struct TravRayBase<N,true>
+ {
+ __forceinline TravRayBase() {}
+
+ __forceinline TravRayBase(const Vec3fa& ray_org, const Vec3fa& ray_dir)
+ : org_xyz(ray_org), dir_xyz(ray_dir)
+ {
+ const float round_down = 1.0f-3.0f*float(ulp);
+ const float round_up = 1.0f+3.0f*float(ulp);
+ const Vec3fa ray_rdir = 1.0f/zero_fix(ray_dir);
+ const Vec3fa ray_rdir_near = round_down*ray_rdir;
+ const Vec3fa ray_rdir_far = round_up *ray_rdir;
+ org = Vec3vf<N>(ray_org.x,ray_org.y,ray_org.z);
+ dir = Vec3vf<N>(ray_dir.x,ray_dir.y,ray_dir.z);
+ rdir_near = Vec3vf<N>(ray_rdir_near.x,ray_rdir_near.y,ray_rdir_near.z);
+ rdir_far = Vec3vf<N>(ray_rdir_far .x,ray_rdir_far .y,ray_rdir_far .z);
+
+ nearX = ray_rdir_near.x >= 0.0f ? 0*sizeof(vfloat<N>) : 1*sizeof(vfloat<N>);
+ nearY = ray_rdir_near.y >= 0.0f ? 2*sizeof(vfloat<N>) : 3*sizeof(vfloat<N>);
+ nearZ = ray_rdir_near.z >= 0.0f ? 4*sizeof(vfloat<N>) : 5*sizeof(vfloat<N>);
+ farX = nearX ^ sizeof(vfloat<N>);
+ farY = nearY ^ sizeof(vfloat<N>);
+ farZ = nearZ ^ sizeof(vfloat<N>);
+ }
+
+ template<int K>
+ __forceinline void init(size_t k, const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir,
+ const Vec3vf<K>& ray_rdir, const Vec3vi<K>& nearXYZ,
+ size_t flip = sizeof(vfloat<N>))
+ {
+ const vfloat<N> round_down = 1.0f-3.0f*float(ulp);
+ const vfloat<N> round_up = 1.0f+3.0f*float(ulp);
+ org = Vec3vf<N>(ray_org.x[k], ray_org.y[k], ray_org.z[k]);
+ dir = Vec3vf<N>(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]);
+ rdir_near = round_down*Vec3vf<N>(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]);
+ rdir_far = round_up *Vec3vf<N>(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]);
+
+ nearX = nearXYZ.x[k];
+ nearY = nearXYZ.y[k];
+ nearZ = nearXYZ.z[k];
+ farX = nearX ^ flip;
+ farY = nearY ^ flip;
+ farZ = nearZ ^ flip;
+ }
+
+ Vec3fa org_xyz, dir_xyz;
+ Vec3vf<N> org, dir, rdir_near, rdir_far;
+ size_t nearX, nearY, nearZ;
+ size_t farX, farY, farZ;
+ };
+
+ /* Full (with tnear and tfar) */
+ template<int N, bool robust>
+ struct TravRay : TravRayBase<N,robust>
+ {
+ __forceinline TravRay() {}
+
+ __forceinline TravRay(const Vec3fa& ray_org, const Vec3fa& ray_dir, float ray_tnear, float ray_tfar)
+ : TravRayBase<N,robust>(ray_org, ray_dir),
+ tnear(ray_tnear), tfar(ray_tfar) {}
+
+ template<int K>
+ __forceinline void init(size_t k, const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir,
+ const Vec3vf<K>& ray_rdir, const Vec3vi<K>& nearXYZ,
+ float ray_tnear, float ray_tfar,
+ size_t flip = sizeof(vfloat<N>))
+ {
+ TravRayBase<N,robust>::template init<K>(k, ray_org, ray_dir, ray_rdir, nearXYZ, flip);
+ tnear = ray_tnear; tfar = ray_tfar;
+ }
+
+ vfloat<N> tnear;
+ vfloat<N> tfar;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Point Query structure used in single-ray traversal
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ struct TravPointQuery
+ {
+ __forceinline TravPointQuery() {}
+
+ __forceinline TravPointQuery(const Vec3fa& query_org, const Vec3fa& query_rad)
+ {
+ org = Vec3vf<N>(query_org.x, query_org.y, query_org.z);
+ rad = Vec3vf<N>(query_rad.x, query_rad.y, query_rad.z);
+ }
+
+ __forceinline vfloat<N> const& tfar() const {
+ return rad.x;
+ }
+
+ Vec3vf<N> org, rad;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // point query
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ __forceinline size_t pointQuerySphereDistAndMask(
+ const TravPointQuery<N>& query, vfloat<N>& dist, vfloat<N> const& minX, vfloat<N> const& maxX,
+ vfloat<N> const& minY, vfloat<N> const& maxY, vfloat<N> const& minZ, vfloat<N> const& maxZ)
+ {
+ const vfloat<N> vX = min(max(query.org.x, minX), maxX) - query.org.x;
+ const vfloat<N> vY = min(max(query.org.y, minY), maxY) - query.org.y;
+ const vfloat<N> vZ = min(max(query.org.z, minZ), maxZ) - query.org.z;
+ dist = vX * vX + vY * vY + vZ * vZ;
+ const vbool<N> vmask = dist <= query.tfar()*query.tfar();
+ const vbool<N> valid = minX <= maxX;
+ return movemask(vmask) & movemask(valid);
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::AABBNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
+ {
+ const vfloat<N> minX = vfloat<N>::load((float*)((const char*)&node->lower_x));
+ const vfloat<N> minY = vfloat<N>::load((float*)((const char*)&node->lower_y));
+ const vfloat<N> minZ = vfloat<N>::load((float*)((const char*)&node->lower_z));
+ const vfloat<N> maxX = vfloat<N>::load((float*)((const char*)&node->upper_x));
+ const vfloat<N> maxY = vfloat<N>::load((float*)((const char*)&node->upper_y));
+ const vfloat<N> maxZ = vfloat<N>::load((float*)((const char*)&node->upper_z));
+ return pointQuerySphereDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ);
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::AABBNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ const vfloat<N>* pMinX = (const vfloat<N>*)((const char*)&node->lower_x);
+ const vfloat<N>* pMinY = (const vfloat<N>*)((const char*)&node->lower_y);
+ const vfloat<N>* pMinZ = (const vfloat<N>*)((const char*)&node->lower_z);
+ const vfloat<N>* pMaxX = (const vfloat<N>*)((const char*)&node->upper_x);
+ const vfloat<N>* pMaxY = (const vfloat<N>*)((const char*)&node->upper_y);
+ const vfloat<N>* pMaxZ = (const vfloat<N>*)((const char*)&node->upper_z);
+ const vfloat<N> minX = madd(time,pMinX[6],vfloat<N>(pMinX[0]));
+ const vfloat<N> minY = madd(time,pMinY[6],vfloat<N>(pMinY[0]));
+ const vfloat<N> minZ = madd(time,pMinZ[6],vfloat<N>(pMinZ[0]));
+ const vfloat<N> maxX = madd(time,pMaxX[6],vfloat<N>(pMaxX[0]));
+ const vfloat<N> maxY = madd(time,pMaxY[6],vfloat<N>(pMaxY[0]));
+ const vfloat<N> maxZ = madd(time,pMaxZ[6],vfloat<N>(pMaxZ[0]));
+ return pointQuerySphereDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ);
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeSphereMB4D(const typename BVHN<N>::NodeRef ref, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
+ size_t mask = pointQueryNodeSphere(node, query, time, dist);
+
+ if (unlikely(ref.isAABBNodeMB4D())) {
+ const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
+ const vbool<N> vmask = (node1->lower_t <= time) & (time < node1->upper_t);
+ mask &= movemask(vmask);
+ }
+
+ return mask;
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::QuantizedBaseNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
+ {
+ const vfloat<N> start_x(node->start.x);
+ const vfloat<N> scale_x(node->scale.x);
+ const vfloat<N> minX = madd(node->template dequantize<N>((0*sizeof(vfloat<N>)) >> 2),scale_x,start_x);
+ const vfloat<N> maxX = madd(node->template dequantize<N>((1*sizeof(vfloat<N>)) >> 2),scale_x,start_x);
+ const vfloat<N> start_y(node->start.y);
+ const vfloat<N> scale_y(node->scale.y);
+ const vfloat<N> minY = madd(node->template dequantize<N>((2*sizeof(vfloat<N>)) >> 2),scale_y,start_y);
+ const vfloat<N> maxY = madd(node->template dequantize<N>((3*sizeof(vfloat<N>)) >> 2),scale_y,start_y);
+ const vfloat<N> start_z(node->start.z);
+ const vfloat<N> scale_z(node->scale.z);
+ const vfloat<N> minZ = madd(node->template dequantize<N>((4*sizeof(vfloat<N>)) >> 2),scale_z,start_z);
+ const vfloat<N> maxZ = madd(node->template dequantize<N>((5*sizeof(vfloat<N>)) >> 2),scale_z,start_z);
+ return pointQuerySphereDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ) & movemask(node->validMask());
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ const vfloat<N> minX = node->dequantizeLowerX(time);
+ const vfloat<N> maxX = node->dequantizeUpperX(time);
+ const vfloat<N> minY = node->dequantizeLowerY(time);
+ const vfloat<N> maxY = node->dequantizeUpperY(time);
+ const vfloat<N> minZ = node->dequantizeLowerZ(time);
+ const vfloat<N> maxZ = node->dequantizeUpperZ(time);
+ return pointQuerySphereDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ) & movemask(node->validMask());
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::OBBNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
+ {
+ // TODO: point query - implement
+ const vbool<N> vmask = vbool<N>(true);
+ const size_t mask = movemask(vmask) & ((1<<N)-1);
+ dist = vfloat<N>(0.0f);
+ return mask;
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeSphere(const typename BVHN<N>::OBBNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ // TODO: point query - implement
+ const vbool<N> vmask = vbool<N>(true);
+ const size_t mask = movemask(vmask) & ((1<<N)-1);
+ dist = vfloat<N>(0.0f);
+ return mask;
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryAABBDistAndMask(
+ const TravPointQuery<N>& query, vfloat<N>& dist, vfloat<N> const& minX, vfloat<N> const& maxX,
+ vfloat<N> const& minY, vfloat<N> const& maxY, vfloat<N> const& minZ, vfloat<N> const& maxZ)
+ {
+ const vfloat<N> vX = min(max(query.org.x, minX), maxX) - query.org.x;
+ const vfloat<N> vY = min(max(query.org.y, minY), maxY) - query.org.y;
+ const vfloat<N> vZ = min(max(query.org.z, minZ), maxZ) - query.org.z;
+ dist = vX * vX + vY * vY + vZ * vZ;
+ const vbool<N> valid = minX <= maxX;
+ const vbool<N> vmask = !((maxX < query.org.x - query.rad.x) | (minX > query.org.x + query.rad.x) |
+ (maxY < query.org.y - query.rad.y) | (minY > query.org.y + query.rad.y) |
+ (maxZ < query.org.z - query.rad.z) | (minZ > query.org.z + query.rad.z));
+ return movemask(vmask) & movemask(valid);
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::AABBNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
+ {
+ const vfloat<N> minX = vfloat<N>::load((float*)((const char*)&node->lower_x));
+ const vfloat<N> minY = vfloat<N>::load((float*)((const char*)&node->lower_y));
+ const vfloat<N> minZ = vfloat<N>::load((float*)((const char*)&node->lower_z));
+ const vfloat<N> maxX = vfloat<N>::load((float*)((const char*)&node->upper_x));
+ const vfloat<N> maxY = vfloat<N>::load((float*)((const char*)&node->upper_y));
+ const vfloat<N> maxZ = vfloat<N>::load((float*)((const char*)&node->upper_z));
+ return pointQueryAABBDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ);
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::AABBNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ const vfloat<N>* pMinX = (const vfloat<N>*)((const char*)&node->lower_x);
+ const vfloat<N>* pMinY = (const vfloat<N>*)((const char*)&node->lower_y);
+ const vfloat<N>* pMinZ = (const vfloat<N>*)((const char*)&node->lower_z);
+ const vfloat<N>* pMaxX = (const vfloat<N>*)((const char*)&node->upper_x);
+ const vfloat<N>* pMaxY = (const vfloat<N>*)((const char*)&node->upper_y);
+ const vfloat<N>* pMaxZ = (const vfloat<N>*)((const char*)&node->upper_z);
+ const vfloat<N> minX = madd(time,pMinX[6],vfloat<N>(pMinX[0]));
+ const vfloat<N> minY = madd(time,pMinY[6],vfloat<N>(pMinY[0]));
+ const vfloat<N> minZ = madd(time,pMinZ[6],vfloat<N>(pMinZ[0]));
+ const vfloat<N> maxX = madd(time,pMaxX[6],vfloat<N>(pMaxX[0]));
+ const vfloat<N> maxY = madd(time,pMaxY[6],vfloat<N>(pMaxY[0]));
+ const vfloat<N> maxZ = madd(time,pMaxZ[6],vfloat<N>(pMaxZ[0]));
+ return pointQueryAABBDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ);
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeAABBMB4D(const typename BVHN<N>::NodeRef ref, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
+ size_t mask = pointQueryNodeAABB(node, query, time, dist);
+
+ if (unlikely(ref.isAABBNodeMB4D())) {
+ const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
+ const vbool<N> vmask = (node1->lower_t <= time) & (time < node1->upper_t);
+ mask &= movemask(vmask);
+ }
+
+ return mask;
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::QuantizedBaseNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
+ {
+ const size_t mvalid = movemask(node->validMask());
+ const vfloat<N> start_x(node->start.x);
+ const vfloat<N> scale_x(node->scale.x);
+ const vfloat<N> minX = madd(node->template dequantize<N>((0*sizeof(vfloat<N>)) >> 2),scale_x,start_x);
+ const vfloat<N> maxX = madd(node->template dequantize<N>((1*sizeof(vfloat<N>)) >> 2),scale_x,start_x);
+ const vfloat<N> start_y(node->start.y);
+ const vfloat<N> scale_y(node->scale.y);
+ const vfloat<N> minY = madd(node->template dequantize<N>((2*sizeof(vfloat<N>)) >> 2),scale_y,start_y);
+ const vfloat<N> maxY = madd(node->template dequantize<N>((3*sizeof(vfloat<N>)) >> 2),scale_y,start_y);
+ const vfloat<N> start_z(node->start.z);
+ const vfloat<N> scale_z(node->scale.z);
+ const vfloat<N> minZ = madd(node->template dequantize<N>((4*sizeof(vfloat<N>)) >> 2),scale_z,start_z);
+ const vfloat<N> maxZ = madd(node->template dequantize<N>((5*sizeof(vfloat<N>)) >> 2),scale_z,start_z);
+ return pointQueryAABBDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ) & mvalid;
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ const size_t mvalid = movemask(node->validMask());
+ const vfloat<N> minX = node->dequantizeLowerX(time);
+ const vfloat<N> maxX = node->dequantizeUpperX(time);
+ const vfloat<N> minY = node->dequantizeLowerY(time);
+ const vfloat<N> maxY = node->dequantizeUpperY(time);
+ const vfloat<N> minZ = node->dequantizeLowerZ(time);
+ const vfloat<N> maxZ = node->dequantizeUpperZ(time);
+ return pointQueryAABBDistAndMask(query, dist, minX, maxX, minY, maxY, minZ, maxZ) & mvalid;
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::OBBNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
+ {
+ // TODO: point query - implement
+ const vbool<N> vmask = vbool<N>(true);
+ const size_t mask = movemask(vmask) & ((1<<N)-1);
+ dist = vfloat<N>(0.0f);
+ return mask;
+ }
+
+ template<int N>
+ __forceinline size_t pointQueryNodeAABB(const typename BVHN<N>::OBBNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ // TODO: point query - implement
+ const vbool<N> vmask = vbool<N>(true);
+ const size_t mask = movemask(vmask) & ((1<<N)-1);
+ dist = vfloat<N>(0.0f);
+ return mask;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast AABBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, bool robust>
+ __forceinline size_t intersectNode(const typename BVHN<N>::AABBNode* node, const TravRay<N,robust>& ray, vfloat<N>& dist);
+
+ template<>
+ __forceinline size_t intersectNode<4>(const typename BVH4::AABBNode* node, const TravRay<4,false>& ray, vfloat4& dist)
+ {
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat4 tNearX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
+ const vfloat4 tNearY = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
+ const vfloat4 tNearZ = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z);
+ const vfloat4 tFarX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x);
+ const vfloat4 tFarY = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y);
+ const vfloat4 tFarZ = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat4 tNearX = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
+ const vfloat4 tNearY = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
+ const vfloat4 tNearZ = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir.z;
+ const vfloat4 tFarX = (vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir.x;
+ const vfloat4 tFarY = (vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir.y;
+ const vfloat4 tFarZ = (vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir.z;
+#endif
+
+#if defined(__aarch64__)
+ const vfloat4 tNear = maxi(tNearX, tNearY, tNearZ, ray.tnear);
+ const vfloat4 tFar = mini(tFarX, tFarY, tFarZ, ray.tfar);
+ const vbool4 vmask = asInt(tNear) <= asInt(tFar);
+ const size_t mask = movemask(vmask);
+#elif defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW
+ const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool4 vmask = asInt(tNear) > asInt(tFar);
+ const size_t mask = movemask(vmask) ^ ((1<<4)-1);
+#elif defined(__AVX512F__) // SKX
+ const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool4 vmask = asInt(tNear) <= asInt(tFar);
+ const size_t mask = movemask(vmask);
+#else
+ const vfloat4 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat4 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool4 vmask = tNear <= tFar;
+ const size_t mask = movemask(vmask);
+#endif
+ dist = tNear;
+ return mask;
+ }
+
+#if defined(__AVX__)
+
+ template<>
+ __forceinline size_t intersectNode<8>(const typename BVH8::AABBNode* node, const TravRay<8,false>& ray, vfloat8& dist)
+ {
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat8 tNearX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
+ const vfloat8 tNearY = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
+ const vfloat8 tNearZ = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z);
+ const vfloat8 tFarX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x);
+ const vfloat8 tFarY = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y);
+ const vfloat8 tFarZ = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat8 tNearX = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
+ const vfloat8 tNearY = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
+ const vfloat8 tNearZ = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir.z;
+ const vfloat8 tFarX = (vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir.x;
+ const vfloat8 tFarY = (vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir.y;
+ const vfloat8 tFarZ = (vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir.z;
+#endif
+
+#if defined(__AVX2__) && !defined(__AVX512F__) // HSW
+ const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool8 vmask = asInt(tNear) > asInt(tFar);
+ const size_t mask = movemask(vmask) ^ ((1<<8)-1);
+#elif defined(__AVX512F__) // SKX
+ const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool8 vmask = asInt(tNear) <= asInt(tFar);
+ const size_t mask = movemask(vmask);
+#else
+ const vfloat8 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat8 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool8 vmask = tNear <= tFar;
+ const size_t mask = movemask(vmask);
+#endif
+ dist = tNear;
+ return mask;
+ }
+
+#endif
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Robust AABBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ __forceinline size_t intersectNodeRobust(const typename BVHN<N>::AABBNode* node, const TravRay<N,true>& ray, vfloat<N>& dist)
+ {
+ const vfloat<N> tNearX = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir_near.x;
+ const vfloat<N> tNearY = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir_near.y;
+ const vfloat<N> tNearZ = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir_near.z;
+ const vfloat<N> tFarX = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir_far.x;
+ const vfloat<N> tFarY = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir_far.y;
+ const vfloat<N> tFarZ = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir_far.z;
+ const vfloat<N> tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat<N> tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool<N> vmask = tNear <= tFar;
+ const size_t mask = movemask(vmask);
+ dist = tNear;
+ return mask;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast AABBNodeMB intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ __forceinline size_t intersectNode(const typename BVHN<N>::AABBNodeMB* node, const TravRay<N,false>& ray, const float time, vfloat<N>& dist)
+ {
+ const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
+ const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
+ const vfloat<N>* pNearZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearZ);
+ const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
+ const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
+ const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat<N> tNearX = msub(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.org_rdir.x);
+ const vfloat<N> tNearY = msub(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.org_rdir.y);
+ const vfloat<N> tNearZ = msub(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.org_rdir.z);
+ const vfloat<N> tFarX = msub(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.org_rdir.x);
+ const vfloat<N> tFarY = msub(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.org_rdir.y);
+ const vfloat<N> tFarZ = msub(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir.x;
+ const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir.y;
+ const vfloat<N> tNearZ = (madd(time,pNearZ[6],vfloat<N>(pNearZ[0])) - ray.org.z) * ray.rdir.z;
+ const vfloat<N> tFarX = (madd(time,pFarX [6],vfloat<N>(pFarX [0])) - ray.org.x) * ray.rdir.x;
+ const vfloat<N> tFarY = (madd(time,pFarY [6],vfloat<N>(pFarY [0])) - ray.org.y) * ray.rdir.y;
+ const vfloat<N> tFarZ = (madd(time,pFarZ [6],vfloat<N>(pFarZ [0])) - ray.org.z) * ray.rdir.z;
+#endif
+#if defined(__AVX2__) && !defined(__AVX512F__) // HSW
+ const vfloat<N> tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat<N> tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool<N> vmask = asInt(tNear) > asInt(tFar);
+ const size_t mask = movemask(vmask) ^ ((1<<N)-1);
+#elif defined(__AVX512F__) // SKX
+ const vfloat<N> tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat<N> tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool<N> vmask = asInt(tNear) <= asInt(tFar);
+ const size_t mask = movemask(vmask);
+#else
+ const vfloat<N> tNear = max(ray.tnear,tNearX,tNearY,tNearZ);
+ const vfloat<N> tFar = min(ray.tfar, tFarX ,tFarY ,tFarZ );
+ const vbool<N> vmask = tNear <= tFar;
+ const size_t mask = movemask(vmask);
+#endif
+ dist = tNear;
+ return mask;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Robust AABBNodeMB intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ __forceinline size_t intersectNodeRobust(const typename BVHN<N>::AABBNodeMB* node, const TravRay<N,true>& ray, const float time, vfloat<N>& dist)
+ {
+ const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
+ const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
+ const vfloat<N>* pNearZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearZ);
+ const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir_near.x;
+ const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir_near.y;
+ const vfloat<N> tNearZ = (madd(time,pNearZ[6],vfloat<N>(pNearZ[0])) - ray.org.z) * ray.rdir_near.z;
+ const vfloat<N> tNear = max(ray.tnear,tNearX,tNearY,tNearZ);
+ const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
+ const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
+ const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
+ const vfloat<N> tFarX = (madd(time,pFarX[6],vfloat<N>(pFarX[0])) - ray.org.x) * ray.rdir_far.x;
+ const vfloat<N> tFarY = (madd(time,pFarY[6],vfloat<N>(pFarY[0])) - ray.org.y) * ray.rdir_far.y;
+ const vfloat<N> tFarZ = (madd(time,pFarZ[6],vfloat<N>(pFarZ[0])) - ray.org.z) * ray.rdir_far.z;
+ const vfloat<N> tFar = min(ray.tfar,tFarX,tFarY,tFarZ);
+ const size_t mask = movemask(tNear <= tFar);
+ dist = tNear;
+ return mask;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast AABBNodeMB4D intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ __forceinline size_t intersectNodeMB4D(const typename BVHN<N>::NodeRef ref, const TravRay<N,false>& ray, const float time, vfloat<N>& dist)
+ {
+ const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
+
+ const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
+ const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
+ const vfloat<N>* pNearZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearZ);
+ const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
+ const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
+ const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
+#if defined (__AVX2__) || defined(__ARM_NEON)
+ const vfloat<N> tNearX = msub(madd(time,pNearX[6],vfloat<N>(pNearX[0])), ray.rdir.x, ray.org_rdir.x);
+ const vfloat<N> tNearY = msub(madd(time,pNearY[6],vfloat<N>(pNearY[0])), ray.rdir.y, ray.org_rdir.y);
+ const vfloat<N> tNearZ = msub(madd(time,pNearZ[6],vfloat<N>(pNearZ[0])), ray.rdir.z, ray.org_rdir.z);
+ const vfloat<N> tFarX = msub(madd(time,pFarX [6],vfloat<N>(pFarX [0])), ray.rdir.x, ray.org_rdir.x);
+ const vfloat<N> tFarY = msub(madd(time,pFarY [6],vfloat<N>(pFarY [0])), ray.rdir.y, ray.org_rdir.y);
+ const vfloat<N> tFarZ = msub(madd(time,pFarZ [6],vfloat<N>(pFarZ [0])), ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir.x;
+ const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir.y;
+ const vfloat<N> tNearZ = (madd(time,pNearZ[6],vfloat<N>(pNearZ[0])) - ray.org.z) * ray.rdir.z;
+ const vfloat<N> tFarX = (madd(time,pFarX [6],vfloat<N>(pFarX [0])) - ray.org.x) * ray.rdir.x;
+ const vfloat<N> tFarY = (madd(time,pFarY [6],vfloat<N>(pFarY [0])) - ray.org.y) * ray.rdir.y;
+ const vfloat<N> tFarZ = (madd(time,pFarZ [6],vfloat<N>(pFarZ [0])) - ray.org.z) * ray.rdir.z;
+#endif
+#if defined(__AVX2__) && !defined(__AVX512F__)
+ const vfloat<N> tNear = maxi(maxi(tNearX,tNearY),maxi(tNearZ,ray.tnear));
+ const vfloat<N> tFar = mini(mini(tFarX ,tFarY ),mini(tFarZ ,ray.tfar ));
+#else
+ const vfloat<N> tNear = max(ray.tnear,tNearX,tNearY,tNearZ);
+ const vfloat<N> tFar = min(ray.tfar, tFarX ,tFarY ,tFarZ );
+#endif
+ vbool<N> vmask = tNear <= tFar;
+ if (unlikely(ref.isAABBNodeMB4D())) {
+ const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
+ vmask &= (node1->lower_t <= time) & (time < node1->upper_t);
+ }
+ const size_t mask = movemask(vmask);
+ dist = tNear;
+ return mask;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Robust AABBNodeMB4D intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ __forceinline size_t intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const TravRay<N,true>& ray, const float time, vfloat<N>& dist)
+ {
+ const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
+
+ const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
+ const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
+ const vfloat<N>* pNearZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearZ);
+ const vfloat<N> tNearX = (madd(time,pNearX[6],vfloat<N>(pNearX[0])) - ray.org.x) * ray.rdir_near.x;
+ const vfloat<N> tNearY = (madd(time,pNearY[6],vfloat<N>(pNearY[0])) - ray.org.y) * ray.rdir_near.y;
+ const vfloat<N> tNearZ = (madd(time,pNearZ[6],vfloat<N>(pNearZ[0])) - ray.org.z) * ray.rdir_near.z;
+ const vfloat<N> tNear = max(ray.tnear,tNearX,tNearY,tNearZ);
+ const vfloat<N>* pFarX = (const vfloat<N>*)((const char*)&node->lower_x+ray.farX);
+ const vfloat<N>* pFarY = (const vfloat<N>*)((const char*)&node->lower_x+ray.farY);
+ const vfloat<N>* pFarZ = (const vfloat<N>*)((const char*)&node->lower_x+ray.farZ);
+ const vfloat<N> tFarX = (madd(time,pFarX[6],vfloat<N>(pFarX[0])) - ray.org.x) * ray.rdir_far.x;
+ const vfloat<N> tFarY = (madd(time,pFarY[6],vfloat<N>(pFarY[0])) - ray.org.y) * ray.rdir_far.y;
+ const vfloat<N> tFarZ = (madd(time,pFarZ[6],vfloat<N>(pFarZ[0])) - ray.org.z) * ray.rdir_far.z;
+ const vfloat<N> tFar = min(ray.tfar,tFarX,tFarY,tFarZ);
+ vbool<N> vmask = tNear <= tFar;
+ if (unlikely(ref.isAABBNodeMB4D())) {
+ const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
+ vmask &= (node1->lower_t <= time) & (time < node1->upper_t);
+ }
+ const size_t mask = movemask(vmask);
+ dist = tNear;
+ return mask;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast QuantizedBaseNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, bool robust>
+ __forceinline size_t intersectNode(const typename BVHN<N>::QuantizedBaseNode* node, const TravRay<N,robust>& ray, vfloat<N>& dist);
+
+ template<>
+ __forceinline size_t intersectNode<4>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,false>& ray, vfloat4& dist)
+ {
+ const size_t mvalid = movemask(node->validMask());
+ const vfloat4 start_x(node->start.x);
+ const vfloat4 scale_x(node->scale.x);
+ const vfloat4 lower_x = madd(node->dequantize<4>(ray.nearX >> 2),scale_x,start_x);
+ const vfloat4 upper_x = madd(node->dequantize<4>(ray.farX >> 2),scale_x,start_x);
+ const vfloat4 start_y(node->start.y);
+ const vfloat4 scale_y(node->scale.y);
+ const vfloat4 lower_y = madd(node->dequantize<4>(ray.nearY >> 2),scale_y,start_y);
+ const vfloat4 upper_y = madd(node->dequantize<4>(ray.farY >> 2),scale_y,start_y);
+ const vfloat4 start_z(node->start.z);
+ const vfloat4 scale_z(node->scale.z);
+ const vfloat4 lower_z = madd(node->dequantize<4>(ray.nearZ >> 2),scale_z,start_z);
+ const vfloat4 upper_z = madd(node->dequantize<4>(ray.farZ >> 2),scale_z,start_z);
+
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat4 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat4 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat4 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
+ const vfloat4 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat4 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat4 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat4 tNearX = (lower_x - ray.org.x) * ray.rdir.x;
+ const vfloat4 tNearY = (lower_y - ray.org.y) * ray.rdir.y;
+ const vfloat4 tNearZ = (lower_z - ray.org.z) * ray.rdir.z;
+ const vfloat4 tFarX = (upper_x - ray.org.x) * ray.rdir.x;
+ const vfloat4 tFarY = (upper_y - ray.org.y) * ray.rdir.y;
+ const vfloat4 tFarZ = (upper_z - ray.org.z) * ray.rdir.z;
+#endif
+
+#if defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW
+ const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool4 vmask = asInt(tNear) > asInt(tFar);
+ const size_t mask = movemask(vmask) ^ ((1<<4)-1);
+#elif defined(__AVX512F__) // SKX
+ const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool4 vmask = asInt(tNear) <= asInt(tFar);
+ const size_t mask = movemask(vmask);
+#else
+ const vfloat4 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat4 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool4 vmask = tNear <= tFar;
+ const size_t mask = movemask(vmask);
+#endif
+ dist = tNear;
+ return mask & mvalid;
+ }
+
+ template<>
+ __forceinline size_t intersectNode<4>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,true>& ray, vfloat4& dist)
+ {
+ const size_t mvalid = movemask(node->validMask());
+ const vfloat4 start_x(node->start.x);
+ const vfloat4 scale_x(node->scale.x);
+ const vfloat4 lower_x = madd(node->dequantize<4>(ray.nearX >> 2),scale_x,start_x);
+ const vfloat4 upper_x = madd(node->dequantize<4>(ray.farX >> 2),scale_x,start_x);
+ const vfloat4 start_y(node->start.y);
+ const vfloat4 scale_y(node->scale.y);
+ const vfloat4 lower_y = madd(node->dequantize<4>(ray.nearY >> 2),scale_y,start_y);
+ const vfloat4 upper_y = madd(node->dequantize<4>(ray.farY >> 2),scale_y,start_y);
+ const vfloat4 start_z(node->start.z);
+ const vfloat4 scale_z(node->scale.z);
+ const vfloat4 lower_z = madd(node->dequantize<4>(ray.nearZ >> 2),scale_z,start_z);
+ const vfloat4 upper_z = madd(node->dequantize<4>(ray.farZ >> 2),scale_z,start_z);
+
+ const vfloat4 tNearX = (lower_x - ray.org.x) * ray.rdir_near.x;
+ const vfloat4 tNearY = (lower_y - ray.org.y) * ray.rdir_near.y;
+ const vfloat4 tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z;
+ const vfloat4 tFarX = (upper_x - ray.org.x) * ray.rdir_far.x;
+ const vfloat4 tFarY = (upper_y - ray.org.y) * ray.rdir_far.y;
+ const vfloat4 tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z;
+
+ const vfloat4 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat4 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool4 vmask = tNear <= tFar;
+ const size_t mask = movemask(vmask);
+ dist = tNear;
+ return mask & mvalid;
+ }
+
+
+#if defined(__AVX__)
+
+ template<>
+ __forceinline size_t intersectNode<8>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,false>& ray, vfloat8& dist)
+ {
+ const size_t mvalid = movemask(node->validMask());
+ const vfloat8 start_x(node->start.x);
+ const vfloat8 scale_x(node->scale.x);
+ const vfloat8 lower_x = madd(node->dequantize<8>(ray.nearX >> 2),scale_x,start_x);
+ const vfloat8 upper_x = madd(node->dequantize<8>(ray.farX >> 2),scale_x,start_x);
+ const vfloat8 start_y(node->start.y);
+ const vfloat8 scale_y(node->scale.y);
+ const vfloat8 lower_y = madd(node->dequantize<8>(ray.nearY >> 2),scale_y,start_y);
+ const vfloat8 upper_y = madd(node->dequantize<8>(ray.farY >> 2),scale_y,start_y);
+ const vfloat8 start_z(node->start.z);
+ const vfloat8 scale_z(node->scale.z);
+ const vfloat8 lower_z = madd(node->dequantize<8>(ray.nearZ >> 2),scale_z,start_z);
+ const vfloat8 upper_z = madd(node->dequantize<8>(ray.farZ >> 2),scale_z,start_z);
+
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat8 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat8 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat8 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
+ const vfloat8 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat8 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat8 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat8 tNearX = (lower_x - ray.org.x) * ray.rdir.x;
+ const vfloat8 tNearY = (lower_y - ray.org.y) * ray.rdir.y;
+ const vfloat8 tNearZ = (lower_z - ray.org.z) * ray.rdir.z;
+ const vfloat8 tFarX = (upper_x - ray.org.x) * ray.rdir.x;
+ const vfloat8 tFarY = (upper_y - ray.org.y) * ray.rdir.y;
+ const vfloat8 tFarZ = (upper_z - ray.org.z) * ray.rdir.z;
+#endif
+
+#if defined(__AVX2__) && !defined(__AVX512F__) // HSW
+ const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool8 vmask = asInt(tNear) > asInt(tFar);
+ const size_t mask = movemask(vmask) ^ ((1<<8)-1);
+#elif defined(__AVX512F__) // SKX
+ const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool8 vmask = asInt(tNear) <= asInt(tFar);
+ const size_t mask = movemask(vmask);
+#else
+ const vfloat8 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat8 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool8 vmask = tNear <= tFar;
+ const size_t mask = movemask(vmask);
+#endif
+ dist = tNear;
+ return mask & mvalid;
+ }
+
+ template<>
+ __forceinline size_t intersectNode<8>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,true>& ray, vfloat8& dist)
+ {
+ const size_t mvalid = movemask(node->validMask());
+ const vfloat8 start_x(node->start.x);
+ const vfloat8 scale_x(node->scale.x);
+ const vfloat8 lower_x = madd(node->dequantize<8>(ray.nearX >> 2),scale_x,start_x);
+ const vfloat8 upper_x = madd(node->dequantize<8>(ray.farX >> 2),scale_x,start_x);
+ const vfloat8 start_y(node->start.y);
+ const vfloat8 scale_y(node->scale.y);
+ const vfloat8 lower_y = madd(node->dequantize<8>(ray.nearY >> 2),scale_y,start_y);
+ const vfloat8 upper_y = madd(node->dequantize<8>(ray.farY >> 2),scale_y,start_y);
+ const vfloat8 start_z(node->start.z);
+ const vfloat8 scale_z(node->scale.z);
+ const vfloat8 lower_z = madd(node->dequantize<8>(ray.nearZ >> 2),scale_z,start_z);
+ const vfloat8 upper_z = madd(node->dequantize<8>(ray.farZ >> 2),scale_z,start_z);
+
+ const vfloat8 tNearX = (lower_x - ray.org.x) * ray.rdir_near.x;
+ const vfloat8 tNearY = (lower_y - ray.org.y) * ray.rdir_near.y;
+ const vfloat8 tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z;
+ const vfloat8 tFarX = (upper_x - ray.org.x) * ray.rdir_far.x;
+ const vfloat8 tFarY = (upper_y - ray.org.y) * ray.rdir_far.y;
+ const vfloat8 tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z;
+
+ const vfloat8 tNear = max(tNearX,tNearY,tNearZ,ray.tnear);
+ const vfloat8 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar);
+ const vbool8 vmask = tNear <= tFar;
+ const size_t mask = movemask(vmask);
+
+ dist = tNear;
+ return mask & mvalid;
+ }
+
+
+#endif
+
+ template<int N>
+ __forceinline size_t intersectNode(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravRay<N,false>& ray, const float time, vfloat<N>& dist)
+ {
+ const vboolf<N> mvalid = node->validMask();
+ const vfloat<N> lower_x = node->dequantizeLowerX(time);
+ const vfloat<N> upper_x = node->dequantizeUpperX(time);
+ const vfloat<N> lower_y = node->dequantizeLowerY(time);
+ const vfloat<N> upper_y = node->dequantizeUpperY(time);
+ const vfloat<N> lower_z = node->dequantizeLowerZ(time);
+ const vfloat<N> upper_z = node->dequantizeUpperZ(time);
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat<N> tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<N> tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<N> tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
+ const vfloat<N> tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<N> tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<N> tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat<N> tNearX = (lower_x - ray.org.x) * ray.rdir.x;
+ const vfloat<N> tNearY = (lower_y - ray.org.y) * ray.rdir.y;
+ const vfloat<N> tNearZ = (lower_z - ray.org.z) * ray.rdir.z;
+ const vfloat<N> tFarX = (upper_x - ray.org.x) * ray.rdir.x;
+ const vfloat<N> tFarY = (upper_y - ray.org.y) * ray.rdir.y;
+ const vfloat<N> tFarZ = (upper_z - ray.org.z) * ray.rdir.z;
+#endif
+
+ const vfloat<N> tminX = mini(tNearX,tFarX);
+ const vfloat<N> tmaxX = maxi(tNearX,tFarX);
+ const vfloat<N> tminY = mini(tNearY,tFarY);
+ const vfloat<N> tmaxY = maxi(tNearY,tFarY);
+ const vfloat<N> tminZ = mini(tNearZ,tFarZ);
+ const vfloat<N> tmaxZ = maxi(tNearZ,tFarZ);
+ const vfloat<N> tNear = maxi(tminX,tminY,tminZ,ray.tnear);
+ const vfloat<N> tFar = mini(tmaxX,tmaxY,tmaxZ,ray.tfar);
+#if defined(__AVX512F__) // SKX
+ const vbool<N> vmask = le(mvalid,asInt(tNear),asInt(tFar));
+#else
+ const vbool<N> vmask = (asInt(tNear) <= asInt(tFar)) & mvalid;
+#endif
+ const size_t mask = movemask(vmask);
+ dist = tNear;
+ return mask;
+ }
+
+ template<int N>
+ __forceinline size_t intersectNode(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravRay<N,true>& ray, const float time, vfloat<N>& dist)
+ {
+ const vboolf<N> mvalid = node->validMask();
+ const vfloat<N> lower_x = node->dequantizeLowerX(time);
+ const vfloat<N> upper_x = node->dequantizeUpperX(time);
+ const vfloat<N> lower_y = node->dequantizeLowerY(time);
+ const vfloat<N> upper_y = node->dequantizeUpperY(time);
+ const vfloat<N> lower_z = node->dequantizeLowerZ(time);
+ const vfloat<N> upper_z = node->dequantizeUpperZ(time);
+ const vfloat<N> tNearX = (lower_x - ray.org.x) * ray.rdir_near.x;
+ const vfloat<N> tNearY = (lower_y - ray.org.y) * ray.rdir_near.y;
+ const vfloat<N> tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z;
+ const vfloat<N> tFarX = (upper_x - ray.org.x) * ray.rdir_far.x;
+ const vfloat<N> tFarY = (upper_y - ray.org.y) * ray.rdir_far.y;
+ const vfloat<N> tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z;
+
+ const vfloat<N> tminX = mini(tNearX,tFarX);
+ const vfloat<N> tmaxX = maxi(tNearX,tFarX);
+ const vfloat<N> tminY = mini(tNearY,tFarY);
+ const vfloat<N> tmaxY = maxi(tNearY,tFarY);
+ const vfloat<N> tminZ = mini(tNearZ,tFarZ);
+ const vfloat<N> tmaxZ = maxi(tNearZ,tFarZ);
+ const vfloat<N> tNear = maxi(tminX,tminY,tminZ,ray.tnear);
+ const vfloat<N> tFar = mini(tmaxX,tmaxY,tmaxZ,ray.tfar);
+#if defined(__AVX512F__) // SKX
+ const vbool<N> vmask = le(mvalid,asInt(tNear),asInt(tFar));
+#else
+ const vbool<N> vmask = (asInt(tNear) <= asInt(tFar)) & mvalid;
+#endif
+ const size_t mask = movemask(vmask);
+ dist = tNear;
+ return mask;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast OBBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, bool robust>
+ __forceinline size_t intersectNode(const typename BVHN<N>::OBBNode* node, const TravRay<N,robust>& ray, vfloat<N>& dist)
+ {
+ const Vec3vf<N> dir = xfmVector(node->naabb,ray.dir);
+ //const Vec3vf<N> nrdir = Vec3vf<N>(vfloat<N>(-1.0f))/dir;
+ const Vec3vf<N> nrdir = Vec3vf<N>(vfloat<N>(-1.0f))*rcp_safe(dir);
+ const Vec3vf<N> org = xfmPoint(node->naabb,ray.org);
+ const Vec3vf<N> tLowerXYZ = org * nrdir; // (Vec3fa(zero) - org) * rdir;
+ const Vec3vf<N> tUpperXYZ = tLowerXYZ - nrdir; // (Vec3fa(one ) - org) * rdir;
+
+ const vfloat<N> tNearX = mini(tLowerXYZ.x,tUpperXYZ.x);
+ const vfloat<N> tNearY = mini(tLowerXYZ.y,tUpperXYZ.y);
+ const vfloat<N> tNearZ = mini(tLowerXYZ.z,tUpperXYZ.z);
+ const vfloat<N> tFarX = maxi(tLowerXYZ.x,tUpperXYZ.x);
+ const vfloat<N> tFarY = maxi(tLowerXYZ.y,tUpperXYZ.y);
+ const vfloat<N> tFarZ = maxi(tLowerXYZ.z,tUpperXYZ.z);
+ vfloat<N> tNear = max(ray.tnear, tNearX,tNearY,tNearZ);
+ vfloat<N> tFar = min(ray.tfar, tFarX ,tFarY ,tFarZ );
+ if (robust) {
+ tNear = tNear*vfloat<N>(1.0f-3.0f*float(ulp));
+ tFar = tFar *vfloat<N>(1.0f+3.0f*float(ulp));
+ }
+ const vbool<N> vmask = tNear <= tFar;
+ dist = tNear;
+ return movemask(vmask);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast OBBNodeMB intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, bool robust>
+ __forceinline size_t intersectNode(const typename BVHN<N>::OBBNodeMB* node, const TravRay<N,robust>& ray, const float time, vfloat<N>& dist)
+ {
+ const AffineSpace3vf<N> xfm = node->space0;
+ const Vec3vf<N> b0_lower = zero;
+ const Vec3vf<N> b0_upper = one;
+ const Vec3vf<N> lower = lerp(b0_lower,node->b1.lower,vfloat<N>(time));
+ const Vec3vf<N> upper = lerp(b0_upper,node->b1.upper,vfloat<N>(time));
+
+ const BBox3vf<N> bounds(lower,upper);
+ const Vec3vf<N> dir = xfmVector(xfm,ray.dir);
+ const Vec3vf<N> rdir = rcp_safe(dir);
+ const Vec3vf<N> org = xfmPoint(xfm,ray.org);
+
+ const Vec3vf<N> tLowerXYZ = (bounds.lower - org) * rdir;
+ const Vec3vf<N> tUpperXYZ = (bounds.upper - org) * rdir;
+
+ const vfloat<N> tNearX = mini(tLowerXYZ.x,tUpperXYZ.x);
+ const vfloat<N> tNearY = mini(tLowerXYZ.y,tUpperXYZ.y);
+ const vfloat<N> tNearZ = mini(tLowerXYZ.z,tUpperXYZ.z);
+ const vfloat<N> tFarX = maxi(tLowerXYZ.x,tUpperXYZ.x);
+ const vfloat<N> tFarY = maxi(tLowerXYZ.y,tUpperXYZ.y);
+ const vfloat<N> tFarZ = maxi(tLowerXYZ.z,tUpperXYZ.z);
+ vfloat<N> tNear = max(ray.tnear, tNearX,tNearY,tNearZ);
+ vfloat<N> tFar = min(ray.tfar, tFarX ,tFarY ,tFarZ );
+ if (robust) {
+ tNear = tNear*vfloat<N>(1.0f-3.0f*float(ulp));
+ tFar = tFar *vfloat<N>(1.0f+3.0f*float(ulp));
+ }
+ const vbool<N> vmask = tNear <= tFar;
+ dist = tNear;
+ return movemask(vmask);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Node intersectors used in point query raversal
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ /*! Computes traversal information for N nodes with 1 point query */
+ template<int N, int types>
+ struct BVHNNodePointQuerySphere1;
+
+ template<int N>
+ struct BVHNNodePointQuerySphere1<N, BVH_AN1>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = pointQueryNodeSphere(node.getAABBNode(), query, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQuerySphere1<N, BVH_AN2>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = pointQueryNodeSphere(node.getAABBNodeMB(), query, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQuerySphere1<N, BVH_AN2_AN4D>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = pointQueryNodeSphereMB4D<N>(node, query, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQuerySphere1<N, BVH_AN1_UN1>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (likely(node.isAABBNode())) mask = pointQueryNodeSphere(node.getAABBNode(), query, dist);
+ else if (unlikely(node.isOBBNode())) mask = pointQueryNodeSphere(node.ungetAABBNode(), query, dist);
+ else return false;
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQuerySphere1<N, BVH_AN2_UN2>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (likely(node.isAABBNodeMB())) mask = pointQueryNodeSphere(node.getAABBNodeMB(), query, time, dist);
+ else if (unlikely(node.isOBBNodeMB())) mask = pointQueryNodeSphere(node.ungetAABBNodeMB(), query, time, dist);
+ else return false;
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQuerySphere1<N, BVH_AN2_AN4D_UN2>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ if (unlikely(node.isOBBNodeMB())) mask = pointQueryNodeSphere(node.ungetAABBNodeMB(), query, time, dist);
+ else mask = pointQueryNodeSphereMB4D(node, query, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQuerySphere1<N, BVH_QN1>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = pointQueryNodeSphere((const typename BVHN<N>::QuantizedNode*)node.quantizedNode(), query, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNQuantizedBaseNodePointQuerySphere1
+ {
+ static __forceinline size_t pointQuery(const typename BVHN<N>::QuantizedBaseNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
+ {
+ return pointQueryNodeSphere(node,query,dist);
+ }
+
+ static __forceinline size_t pointQuery(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ return pointQueryNodeSphere(node,query,time,dist);
+ }
+ };
+
+ /*! Computes traversal information for N nodes with 1 point query */
+ template<int N, int types>
+ struct BVHNNodePointQueryAABB1;
+
+ template<int N>
+ struct BVHNNodePointQueryAABB1<N, BVH_AN1>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = pointQueryNodeAABB(node.getAABBNode(), query, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQueryAABB1<N, BVH_AN2>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = pointQueryNodeAABB(node.getAABBNodeMB(), query, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQueryAABB1<N, BVH_AN2_AN4D>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = pointQueryNodeAABBMB4D<N>(node, query, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQueryAABB1<N, BVH_AN1_UN1>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (likely(node.isAABBNode())) mask = pointQueryNodeAABB(node.getAABBNode(), query, dist);
+ else if (unlikely(node.isOBBNode())) mask = pointQueryNodeAABB(node.ungetAABBNode(), query, dist);
+ else return false;
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQueryAABB1<N, BVH_AN2_UN2>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (likely(node.isAABBNodeMB())) mask = pointQueryNodeAABB(node.getAABBNodeMB(), query, time, dist);
+ else if (unlikely(node.isOBBNodeMB())) mask = pointQueryNodeAABB(node.ungetAABBNodeMB(), query, time, dist);
+ else return false;
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQueryAABB1<N, BVH_AN2_AN4D_UN2>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ if (unlikely(node.isOBBNodeMB())) mask = pointQueryNodeAABB(node.ungetAABBNodeMB(), query, time, dist);
+ else mask = pointQueryNodeAABBMB4D(node, query, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodePointQueryAABB1<N, BVH_QN1>
+ {
+ static __forceinline bool pointQuery(const typename BVHN<N>::NodeRef& node, const TravPointQuery<N>& query, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = pointQueryNodeAABB((const typename BVHN<N>::QuantizedNode*)node.quantizedNode(), query, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNQuantizedBaseNodePointQueryAABB1
+ {
+ static __forceinline size_t pointQuery(const typename BVHN<N>::QuantizedBaseNode* node, const TravPointQuery<N>& query, vfloat<N>& dist)
+ {
+ return pointQueryNodeAABB(node,query,dist);
+ }
+
+ static __forceinline size_t pointQuery(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravPointQuery<N>& query, const float time, vfloat<N>& dist)
+ {
+ return pointQueryNodeAABB(node,query,time,dist);
+ }
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Node intersectors used in ray traversal
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ /*! Intersects N nodes with 1 ray */
+ template<int N, int types, bool robust>
+ struct BVHNNodeIntersector1;
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN1, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,false>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = intersectNode(node.getAABBNode(), ray, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN1, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,true>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = intersectNodeRobust(node.getAABBNode(), ray, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN2, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,false>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = intersectNode(node.getAABBNodeMB(), ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN2, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,true>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = intersectNodeRobust(node.getAABBNodeMB(), ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN2_AN4D, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,false>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = intersectNodeMB4D<N>(node, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN2_AN4D, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,true>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = intersectNodeMB4DRobust<N>(node, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN1_UN1, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,false>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (likely(node.isAABBNode())) mask = intersectNode(node.getAABBNode(), ray, dist);
+ else if (unlikely(node.isOBBNode())) mask = intersectNode(node.ungetAABBNode(), ray, dist);
+ else return false;
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN1_UN1, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,true>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (likely(node.isAABBNode())) mask = intersectNodeRobust(node.getAABBNode(), ray, dist);
+ else if (unlikely(node.isOBBNode())) mask = intersectNode(node.ungetAABBNode(), ray, dist);
+ else return false;
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN2_UN2, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,false>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (likely(node.isAABBNodeMB())) mask = intersectNode(node.getAABBNodeMB(), ray, time, dist);
+ else if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist);
+ else return false;
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN2_UN2, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,true>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (likely(node.isAABBNodeMB())) mask = intersectNodeRobust(node.getAABBNodeMB(), ray, time, dist);
+ else if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist);
+ else return false;
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN2_AN4D_UN2, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,false>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist);
+ else mask = intersectNodeMB4D(node, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_AN2_AN4D_UN2, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,true>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist);
+ else mask = intersectNodeMB4DRobust(node, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_QN1, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,false>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = intersectNode((const typename BVHN<N>::QuantizedNode*)node.quantizedNode(), ray, dist);
+ return true;
+ }
+ };
+
+ template<int N>
+ struct BVHNNodeIntersector1<N, BVH_QN1, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,true>& ray, float time, vfloat<N>& dist, size_t& mask)
+ {
+ if (unlikely(node.isLeaf())) return false;
+ mask = intersectNodeRobust((const typename BVHN<N>::QuantizedNode*)node.quantizedNode(), ray, dist);
+ return true;
+ }
+ };
+
+ /*! Intersects N nodes with K rays */
+ template<int N, bool robust>
+ struct BVHNQuantizedBaseNodeIntersector1;
+
+ template<int N>
+ struct BVHNQuantizedBaseNodeIntersector1<N, false>
+ {
+ static __forceinline size_t intersect(const typename BVHN<N>::QuantizedBaseNode* node, const TravRay<N,false>& ray, vfloat<N>& dist)
+ {
+ return intersectNode(node,ray,dist);
+ }
+
+ static __forceinline size_t intersect(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravRay<N,false>& ray, const float time, vfloat<N>& dist)
+ {
+ return intersectNode(node,ray,time,dist);
+ }
+
+ };
+
+ template<int N>
+ struct BVHNQuantizedBaseNodeIntersector1<N, true>
+ {
+ static __forceinline size_t intersect(const typename BVHN<N>::QuantizedBaseNode* node, const TravRay<N,true>& ray, vfloat<N>& dist)
+ {
+ return intersectNode(node,ray,dist);
+ }
+
+ static __forceinline size_t intersect(const typename BVHN<N>::QuantizedBaseNodeMB* node, const TravRay<N,true>& ray, const float time, vfloat<N>& dist)
+ {
+ return intersectNode(node,ray,time,dist);
+ }
+
+ };
+
+
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/node_intersector_frustum.h b/thirdparty/embree/kernels/bvh/node_intersector_frustum.h
new file mode 100644
index 0000000000..1f7215e5df
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/node_intersector_frustum.h
@@ -0,0 +1,241 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "node_intersector.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Frustum structure used in hybrid and stream traversal
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ Optimized frustum test. We calculate t=(p-org)/dir in ray/box
+ intersection. We assume the rays are split by octant, thus
+ dir intervals are either positive or negative in each
+ dimension.
+
+ Case 1: dir.min >= 0 && dir.max >= 0:
+ t_min = (p_min - org_max) / dir_max = (p_min - org_max)*rdir_min = p_min*rdir_min - org_max*rdir_min
+ t_max = (p_max - org_min) / dir_min = (p_max - org_min)*rdir_max = p_max*rdir_max - org_min*rdir_max
+
+ Case 2: dir.min < 0 && dir.max < 0:
+ t_min = (p_max - org_min) / dir_min = (p_max - org_min)*rdir_max = p_max*rdir_max - org_min*rdir_max
+ t_max = (p_min - org_max) / dir_max = (p_min - org_max)*rdir_min = p_min*rdir_min - org_max*rdir_min
+ */
+
+ template<bool robust>
+ struct Frustum;
+
+ /* Fast variant */
+ template<>
+ struct Frustum<false>
+ {
+ __forceinline Frustum() {}
+
+ template<int K>
+ __forceinline void init(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
+ {
+ const Vec3fa reduced_min_org(reduce_min(select(valid, org.x, pos_inf)),
+ reduce_min(select(valid, org.y, pos_inf)),
+ reduce_min(select(valid, org.z, pos_inf)));
+
+ const Vec3fa reduced_max_org(reduce_max(select(valid, org.x, neg_inf)),
+ reduce_max(select(valid, org.y, neg_inf)),
+ reduce_max(select(valid, org.z, neg_inf)));
+
+ const Vec3fa reduced_min_rdir(reduce_min(select(valid, rdir.x, pos_inf)),
+ reduce_min(select(valid, rdir.y, pos_inf)),
+ reduce_min(select(valid, rdir.z, pos_inf)));
+
+ const Vec3fa reduced_max_rdir(reduce_max(select(valid, rdir.x, neg_inf)),
+ reduce_max(select(valid, rdir.y, neg_inf)),
+ reduce_max(select(valid, rdir.z, neg_inf)));
+
+ const float reduced_min_dist = reduce_min(select(valid, ray_tnear, vfloat<K>(pos_inf)));
+ const float reduced_max_dist = reduce_max(select(valid, ray_tfar , vfloat<K>(neg_inf)));
+
+ init(reduced_min_org, reduced_max_org, reduced_min_rdir, reduced_max_rdir, reduced_min_dist, reduced_max_dist, N);
+ }
+
+ __forceinline void init(const Vec3fa& reduced_min_org,
+ const Vec3fa& reduced_max_org,
+ const Vec3fa& reduced_min_rdir,
+ const Vec3fa& reduced_max_rdir,
+ float reduced_min_dist,
+ float reduced_max_dist,
+ int N)
+ {
+ const Vec3ba pos_rdir = ge_mask(reduced_min_rdir, Vec3fa(zero));
+
+ min_rdir = select(pos_rdir, reduced_min_rdir, reduced_max_rdir);
+ max_rdir = select(pos_rdir, reduced_max_rdir, reduced_min_rdir);
+
+ min_org_rdir = min_rdir * select(pos_rdir, reduced_max_org, reduced_min_org);
+ max_org_rdir = max_rdir * select(pos_rdir, reduced_min_org, reduced_max_org);
+
+ min_dist = reduced_min_dist;
+ max_dist = reduced_max_dist;
+
+ nf = NearFarPrecalculations(min_rdir, N);
+ }
+
+ template<int K>
+ __forceinline void updateMaxDist(const vfloat<K>& ray_tfar)
+ {
+ max_dist = reduce_max(ray_tfar);
+ }
+
+ NearFarPrecalculations nf;
+
+ Vec3fa min_rdir;
+ Vec3fa max_rdir;
+
+ Vec3fa min_org_rdir;
+ Vec3fa max_org_rdir;
+
+ float min_dist;
+ float max_dist;
+ };
+
+ typedef Frustum<false> FrustumFast;
+
+ /* Robust variant */
+ template<>
+ struct Frustum<true>
+ {
+ __forceinline Frustum() {}
+
+ template<int K>
+ __forceinline void init(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
+ {
+ const Vec3fa reduced_min_org(reduce_min(select(valid, org.x, pos_inf)),
+ reduce_min(select(valid, org.y, pos_inf)),
+ reduce_min(select(valid, org.z, pos_inf)));
+
+ const Vec3fa reduced_max_org(reduce_max(select(valid, org.x, neg_inf)),
+ reduce_max(select(valid, org.y, neg_inf)),
+ reduce_max(select(valid, org.z, neg_inf)));
+
+ const Vec3fa reduced_min_rdir(reduce_min(select(valid, rdir.x, pos_inf)),
+ reduce_min(select(valid, rdir.y, pos_inf)),
+ reduce_min(select(valid, rdir.z, pos_inf)));
+
+ const Vec3fa reduced_max_rdir(reduce_max(select(valid, rdir.x, neg_inf)),
+ reduce_max(select(valid, rdir.y, neg_inf)),
+ reduce_max(select(valid, rdir.z, neg_inf)));
+
+ const float reduced_min_dist = reduce_min(select(valid, ray_tnear, vfloat<K>(pos_inf)));
+ const float reduced_max_dist = reduce_max(select(valid, ray_tfar , vfloat<K>(neg_inf)));
+
+ init(reduced_min_org, reduced_max_org, reduced_min_rdir, reduced_max_rdir, reduced_min_dist, reduced_max_dist, N);
+ }
+
+ __forceinline void init(const Vec3fa& reduced_min_org,
+ const Vec3fa& reduced_max_org,
+ const Vec3fa& reduced_min_rdir,
+ const Vec3fa& reduced_max_rdir,
+ float reduced_min_dist,
+ float reduced_max_dist,
+ int N)
+ {
+ const Vec3ba pos_rdir = ge_mask(reduced_min_rdir, Vec3fa(zero));
+ min_rdir = select(pos_rdir, reduced_min_rdir, reduced_max_rdir);
+ max_rdir = select(pos_rdir, reduced_max_rdir, reduced_min_rdir);
+
+ min_org = select(pos_rdir, reduced_max_org, reduced_min_org);
+ max_org = select(pos_rdir, reduced_min_org, reduced_max_org);
+
+ min_dist = reduced_min_dist;
+ max_dist = reduced_max_dist;
+
+ nf = NearFarPrecalculations(min_rdir, N);
+ }
+
+ template<int K>
+ __forceinline void updateMaxDist(const vfloat<K>& ray_tfar)
+ {
+ max_dist = reduce_max(ray_tfar);
+ }
+
+ NearFarPrecalculations nf;
+
+ Vec3fa min_rdir;
+ Vec3fa max_rdir;
+
+ Vec3fa min_org;
+ Vec3fa max_org;
+
+ float min_dist;
+ float max_dist;
+ };
+
+ typedef Frustum<true> FrustumRobust;
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast AABBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ __forceinline size_t intersectNodeFrustum(const typename BVHN<N>::AABBNode* __restrict__ node,
+ const FrustumFast& frustum, vfloat<N>& dist)
+ {
+ const vfloat<N> bminX = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearX);
+ const vfloat<N> bminY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearY);
+ const vfloat<N> bminZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearZ);
+ const vfloat<N> bmaxX = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farX);
+ const vfloat<N> bmaxY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farY);
+ const vfloat<N> bmaxZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farZ);
+
+ const vfloat<N> fminX = msub(bminX, vfloat<N>(frustum.min_rdir.x), vfloat<N>(frustum.min_org_rdir.x));
+ const vfloat<N> fminY = msub(bminY, vfloat<N>(frustum.min_rdir.y), vfloat<N>(frustum.min_org_rdir.y));
+ const vfloat<N> fminZ = msub(bminZ, vfloat<N>(frustum.min_rdir.z), vfloat<N>(frustum.min_org_rdir.z));
+ const vfloat<N> fmaxX = msub(bmaxX, vfloat<N>(frustum.max_rdir.x), vfloat<N>(frustum.max_org_rdir.x));
+ const vfloat<N> fmaxY = msub(bmaxY, vfloat<N>(frustum.max_rdir.y), vfloat<N>(frustum.max_org_rdir.y));
+ const vfloat<N> fmaxZ = msub(bmaxZ, vfloat<N>(frustum.max_rdir.z), vfloat<N>(frustum.max_org_rdir.z));
+
+ const vfloat<N> fmin = maxi(fminX, fminY, fminZ, vfloat<N>(frustum.min_dist));
+ dist = fmin;
+ const vfloat<N> fmax = mini(fmaxX, fmaxY, fmaxZ, vfloat<N>(frustum.max_dist));
+ const vbool<N> vmask_node_hit = fmin <= fmax;
+ size_t m_node = movemask(vmask_node_hit) & (((size_t)1 << N)-1);
+ return m_node;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Robust AABBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N>
+ __forceinline size_t intersectNodeFrustum(const typename BVHN<N>::AABBNode* __restrict__ node,
+ const FrustumRobust& frustum, vfloat<N>& dist)
+ {
+ const vfloat<N> bminX = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearX);
+ const vfloat<N> bminY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearY);
+ const vfloat<N> bminZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.nearZ);
+ const vfloat<N> bmaxX = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farX);
+ const vfloat<N> bmaxY = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farY);
+ const vfloat<N> bmaxZ = *(const vfloat<N>*)((const char*)&node->lower_x + frustum.nf.farZ);
+
+ const vfloat<N> fminX = (bminX - vfloat<N>(frustum.min_org.x)) * vfloat<N>(frustum.min_rdir.x);
+ const vfloat<N> fminY = (bminY - vfloat<N>(frustum.min_org.y)) * vfloat<N>(frustum.min_rdir.y);
+ const vfloat<N> fminZ = (bminZ - vfloat<N>(frustum.min_org.z)) * vfloat<N>(frustum.min_rdir.z);
+ const vfloat<N> fmaxX = (bmaxX - vfloat<N>(frustum.max_org.x)) * vfloat<N>(frustum.max_rdir.x);
+ const vfloat<N> fmaxY = (bmaxY - vfloat<N>(frustum.max_org.y)) * vfloat<N>(frustum.max_rdir.y);
+ const vfloat<N> fmaxZ = (bmaxZ - vfloat<N>(frustum.max_org.z)) * vfloat<N>(frustum.max_rdir.z);
+
+ const float round_down = 1.0f-2.0f*float(ulp); // FIXME: use per instruction rounding for AVX512
+ const float round_up = 1.0f+2.0f*float(ulp);
+ const vfloat<N> fmin = max(fminX, fminY, fminZ, vfloat<N>(frustum.min_dist));
+ dist = fmin;
+ const vfloat<N> fmax = min(fmaxX, fmaxY, fmaxZ, vfloat<N>(frustum.max_dist));
+ const vbool<N> vmask_node_hit = (round_down*fmin <= round_up*fmax);
+ size_t m_node = movemask(vmask_node_hit) & (((size_t)1 << N)-1);
+ return m_node;
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/node_intersector_packet.h b/thirdparty/embree/kernels/bvh/node_intersector_packet.h
new file mode 100644
index 0000000000..d5498fc5db
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/node_intersector_packet.h
@@ -0,0 +1,805 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "node_intersector.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Ray packet structure used in hybrid traversal
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int K, bool robust>
+ struct TravRayK;
+
+ /* Fast variant */
+ template<int K>
+ struct TravRayK<K, false>
+ {
+ __forceinline TravRayK() {}
+
+ __forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)
+ {
+ init(ray_org, ray_dir, N);
+ }
+
+ __forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
+ {
+ init(ray_org, ray_dir, N);
+ tnear = ray_tnear;
+ tfar = ray_tfar;
+ }
+
+ __forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)
+ {
+ org = ray_org;
+ dir = ray_dir;
+ rdir = rcp_safe(ray_dir);
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ org_rdir = org * rdir;
+#endif
+
+ if (N)
+ {
+ const int size = sizeof(float)*N;
+ nearXYZ.x = select(rdir.x >= 0.0f, vint<K>(0*size), vint<K>(1*size));
+ nearXYZ.y = select(rdir.y >= 0.0f, vint<K>(2*size), vint<K>(3*size));
+ nearXYZ.z = select(rdir.z >= 0.0f, vint<K>(4*size), vint<K>(5*size));
+ }
+ }
+
+ Vec3vf<K> org;
+ Vec3vf<K> dir;
+ Vec3vf<K> rdir;
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ Vec3vf<K> org_rdir;
+#endif
+ Vec3vi<K> nearXYZ;
+ vfloat<K> tnear;
+ vfloat<K> tfar;
+ };
+
+ template<int K>
+ using TravRayKFast = TravRayK<K, false>;
+
+ /* Robust variant */
+ template<int K>
+ struct TravRayK<K, true>
+ {
+ __forceinline TravRayK() {}
+
+ __forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)
+ {
+ init(ray_org, ray_dir, N);
+ }
+
+ __forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)
+ {
+ init(ray_org, ray_dir, N);
+ tnear = ray_tnear;
+ tfar = ray_tfar;
+ }
+
+ __forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)
+ {
+ org = ray_org;
+ dir = ray_dir;
+ rdir = vfloat<K>(1.0f)/(zero_fix(ray_dir));
+
+ if (N)
+ {
+ const int size = sizeof(float)*N;
+ nearXYZ.x = select(rdir.x >= 0.0f, vint<K>(0*size), vint<K>(1*size));
+ nearXYZ.y = select(rdir.y >= 0.0f, vint<K>(2*size), vint<K>(3*size));
+ nearXYZ.z = select(rdir.z >= 0.0f, vint<K>(4*size), vint<K>(5*size));
+ }
+ }
+
+ Vec3vf<K> org;
+ Vec3vf<K> dir;
+ Vec3vf<K> rdir;
+ Vec3vi<K> nearXYZ;
+ vfloat<K> tnear;
+ vfloat<K> tfar;
+ };
+
+ template<int K>
+ using TravRayKRobust = TravRayK<K, true>;
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast AABBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectNodeK(const typename BVHN<N>::AABBNode* node, size_t i,
+ const TravRayKFast<K>& ray, vfloat<K>& dist)
+
+ {
+ #if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat<K> lclipMinX = msub(node->lower_x[i], ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMinY = msub(node->lower_y[i], ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMinZ = msub(node->lower_z[i], ray.rdir.z, ray.org_rdir.z);
+ const vfloat<K> lclipMaxX = msub(node->upper_x[i], ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMaxY = msub(node->upper_y[i], ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMaxZ = msub(node->upper_z[i], ray.rdir.z, ray.org_rdir.z);
+ #else
+ const vfloat<K> lclipMinX = (node->lower_x[i] - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (node->lower_y[i] - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (node->lower_z[i] - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (node->upper_x[i] - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (node->upper_y[i] - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (node->upper_z[i] - ray.org.z) * ray.rdir.z;
+ #endif
+
+ #if defined(__AVX512F__) // SKX
+ if (K == 16)
+ {
+ /* use mixed float/int min/max */
+ const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
+ dist = lnearP;
+ return lhit;
+ }
+ else
+ #endif
+ {
+ const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
+ #if defined(__AVX512F__) // SKX
+ const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
+ #else
+ const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+ #endif
+ dist = lnearP;
+ return lhit;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Robust AABBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectNodeKRobust(const typename BVHN<N>::AABBNode* node, size_t i,
+ const TravRayKRobust<K>& ray, vfloat<K>& dist)
+ {
+ // FIXME: use per instruction rounding for AVX512
+ const vfloat<K> lclipMinX = (node->lower_x[i] - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (node->lower_y[i] - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (node->lower_z[i] - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (node->upper_x[i] - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (node->upper_y[i] - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (node->upper_z[i] - ray.org.z) * ray.rdir.z;
+ const float round_up = 1.0f+3.0f*float(ulp);
+ const float round_down = 1.0f-3.0f*float(ulp);
+ const vfloat<K> lnearP = round_down*max(max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY)), min(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = round_up *min(min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY)), max(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);
+ dist = lnearP;
+ return lhit;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast AABBNodeMB intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectNodeK(const typename BVHN<N>::AABBNodeMB* node, const size_t i,
+ const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist)
+ {
+ const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));
+ const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));
+ const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));
+ const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));
+ const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
+ const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
+
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat<K> lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z);
+ const vfloat<K> lclipMaxX = msub(vupper_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMaxY = msub(vupper_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMaxZ = msub(vupper_z, ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;
+#endif
+
+#if defined(__AVX512F__) // SKX
+ if (K == 16)
+ {
+ /* use mixed float/int min/max */
+ const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
+ dist = lnearP;
+ return lhit;
+ }
+ else
+#endif
+ {
+ const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
+#if defined(__AVX512F__) // SKX
+ const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
+#else
+ const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+#endif
+ dist = lnearP;
+ return lhit;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Robust AABBNodeMB intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectNodeKRobust(const typename BVHN<N>::AABBNodeMB* node, const size_t i,
+ const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist)
+ {
+ const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));
+ const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));
+ const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));
+ const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));
+ const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
+ const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
+
+ const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;
+
+ const float round_up = 1.0f+3.0f*float(ulp);
+ const float round_down = 1.0f-3.0f*float(ulp);
+
+#if defined(__AVX512F__) // SKX
+ if (K == 16)
+ {
+ const vfloat<K> lnearP = round_down*maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = round_up *mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+ dist = lnearP;
+ return lhit;
+ }
+ else
+#endif
+ {
+ const vfloat<K> lnearP = round_down*maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = round_up *mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+ dist = lnearP;
+ return lhit;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast AABBNodeMB4D intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectNodeKMB4D(const typename BVHN<N>::NodeRef ref, const size_t i,
+ const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist)
+ {
+ const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
+
+ const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));
+ const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));
+ const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));
+ const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));
+ const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
+ const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
+
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat<K> lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z);
+ const vfloat<K> lclipMaxX = msub(vupper_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMaxY = msub(vupper_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMaxZ = msub(vupper_z, ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;
+#endif
+
+ const vfloat<K> lnearP = maxi(maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY)), mini(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = mini(mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY)), maxi(lclipMinZ, lclipMaxZ));
+ vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+ if (unlikely(ref.isAABBNodeMB4D())) {
+ const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
+ lhit = lhit & (vfloat<K>(node1->lower_t[i]) <= time) & (time < vfloat<K>(node1->upper_t[i]));
+ }
+ dist = lnearP;
+ return lhit;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Robust AABBNodeMB4D intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectNodeKMB4DRobust(const typename BVHN<N>::NodeRef ref, const size_t i,
+ const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist)
+ {
+ const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();
+
+ const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));
+ const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));
+ const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));
+ const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));
+ const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));
+ const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));
+
+ const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;
+
+ const float round_up = 1.0f+3.0f*float(ulp);
+ const float round_down = 1.0f-3.0f*float(ulp);
+ const vfloat<K> lnearP = round_down*maxi(maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY)), mini(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = round_up *mini(mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY)), maxi(lclipMinZ, lclipMaxZ));
+ vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+
+ if (unlikely(ref.isAABBNodeMB4D())) {
+ const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;
+ lhit = lhit & (vfloat<K>(node1->lower_t[i]) <= time) & (time < vfloat<K>(node1->upper_t[i]));
+ }
+ dist = lnearP;
+ return lhit;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast OBBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K, bool robust>
+ __forceinline vbool<K> intersectNodeK(const typename BVHN<N>::OBBNode* node, const size_t i,
+ const TravRayK<K,robust>& ray, vfloat<K>& dist)
+ {
+ const AffineSpace3vf<K> naabb(Vec3f(node->naabb.l.vx.x[i], node->naabb.l.vx.y[i], node->naabb.l.vx.z[i]),
+ Vec3f(node->naabb.l.vy.x[i], node->naabb.l.vy.y[i], node->naabb.l.vy.z[i]),
+ Vec3f(node->naabb.l.vz.x[i], node->naabb.l.vz.y[i], node->naabb.l.vz.z[i]),
+ Vec3f(node->naabb.p .x[i], node->naabb.p .y[i], node->naabb.p .z[i]));
+
+ const Vec3vf<K> dir = xfmVector(naabb, ray.dir);
+ const Vec3vf<K> nrdir = Vec3vf<K>(vfloat<K>(-1.0f)) * rcp_safe(dir); // FIXME: negate instead of mul with -1?
+ const Vec3vf<K> org = xfmPoint(naabb, ray.org);
+
+ const vfloat<K> lclipMinX = org.x * nrdir.x; // (Vec3fa(zero) - org) * rdir;
+ const vfloat<K> lclipMinY = org.y * nrdir.y;
+ const vfloat<K> lclipMinZ = org.z * nrdir.z;
+ const vfloat<K> lclipMaxX = lclipMinX - nrdir.x; // (Vec3fa(one) - org) * rdir;
+ const vfloat<K> lclipMaxY = lclipMinY - nrdir.y;
+ const vfloat<K> lclipMaxZ = lclipMinZ - nrdir.z;
+
+ vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
+ vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
+ if (robust) {
+ lnearP = lnearP*vfloat<K>(1.0f-3.0f*float(ulp));
+ lfarP = lfarP *vfloat<K>(1.0f+3.0f*float(ulp));
+ }
+ const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+ dist = lnearP;
+ return lhit;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast OBBNodeMB intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K, bool robust>
+ __forceinline vbool<K> intersectNodeK(const typename BVHN<N>::OBBNodeMB* node, const size_t i,
+ const TravRayK<K,robust>& ray, const vfloat<K>& time, vfloat<K>& dist)
+ {
+ const AffineSpace3vf<K> xfm(Vec3f(node->space0.l.vx.x[i], node->space0.l.vx.y[i], node->space0.l.vx.z[i]),
+ Vec3f(node->space0.l.vy.x[i], node->space0.l.vy.y[i], node->space0.l.vy.z[i]),
+ Vec3f(node->space0.l.vz.x[i], node->space0.l.vz.y[i], node->space0.l.vz.z[i]),
+ Vec3f(node->space0.p .x[i], node->space0.p .y[i], node->space0.p .z[i]));
+
+ const Vec3vf<K> b0_lower = zero;
+ const Vec3vf<K> b0_upper = one;
+ const Vec3vf<K> b1_lower(node->b1.lower.x[i], node->b1.lower.y[i], node->b1.lower.z[i]);
+ const Vec3vf<K> b1_upper(node->b1.upper.x[i], node->b1.upper.y[i], node->b1.upper.z[i]);
+ const Vec3vf<K> lower = lerp(b0_lower, b1_lower, time);
+ const Vec3vf<K> upper = lerp(b0_upper, b1_upper, time);
+
+ const Vec3vf<K> dir = xfmVector(xfm, ray.dir);
+ const Vec3vf<K> rdir = rcp_safe(dir);
+ const Vec3vf<K> org = xfmPoint(xfm, ray.org);
+
+ const vfloat<K> lclipMinX = (lower.x - org.x) * rdir.x;
+ const vfloat<K> lclipMinY = (lower.y - org.y) * rdir.y;
+ const vfloat<K> lclipMinZ = (lower.z - org.z) * rdir.z;
+ const vfloat<K> lclipMaxX = (upper.x - org.x) * rdir.x;
+ const vfloat<K> lclipMaxY = (upper.y - org.y) * rdir.y;
+ const vfloat<K> lclipMaxZ = (upper.z - org.z) * rdir.z;
+
+ vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
+ vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
+ if (robust) {
+ lnearP = lnearP*vfloat<K>(1.0f-3.0f*float(ulp));
+ lfarP = lfarP *vfloat<K>(1.0f+3.0f*float(ulp));
+ }
+
+ const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+ dist = lnearP;
+ return lhit;
+ }
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // QuantizedBaseNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectQuantizedNodeK(const typename BVHN<N>::QuantizedBaseNode* node, size_t i,
+ const TravRayK<K,false>& ray, vfloat<K>& dist)
+
+ {
+ assert(movemask(node->validMask()) & ((size_t)1 << i));
+ const vfloat<N> lower_x = node->dequantizeLowerX();
+ const vfloat<N> upper_x = node->dequantizeUpperX();
+ const vfloat<N> lower_y = node->dequantizeLowerY();
+ const vfloat<N> upper_y = node->dequantizeUpperY();
+ const vfloat<N> lower_z = node->dequantizeLowerZ();
+ const vfloat<N> upper_z = node->dequantizeUpperZ();
+
+ #if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat<K> lclipMinX = msub(lower_x[i], ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMinY = msub(lower_y[i], ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMinZ = msub(lower_z[i], ray.rdir.z, ray.org_rdir.z);
+ const vfloat<K> lclipMaxX = msub(upper_x[i], ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMaxY = msub(upper_y[i], ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMaxZ = msub(upper_z[i], ray.rdir.z, ray.org_rdir.z);
+ #else
+ const vfloat<K> lclipMinX = (lower_x[i] - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (lower_y[i] - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (lower_z[i] - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (upper_x[i] - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (upper_y[i] - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (upper_z[i] - ray.org.z) * ray.rdir.z;
+ #endif
+
+ #if defined(__AVX512F__) // SKX
+ if (K == 16)
+ {
+ /* use mixed float/int min/max */
+ const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
+ dist = lnearP;
+ return lhit;
+ }
+ else
+ #endif
+ {
+ const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));
+ #if defined(__AVX512F__) // SKX
+ const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));
+ #else
+ const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);
+ #endif
+ dist = lnearP;
+ return lhit;
+ }
+ }
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectQuantizedNodeK(const typename BVHN<N>::QuantizedBaseNode* node, size_t i,
+ const TravRayK<K,true>& ray, vfloat<K>& dist)
+
+ {
+ assert(movemask(node->validMask()) & ((size_t)1 << i));
+ const vfloat<N> lower_x = node->dequantizeLowerX();
+ const vfloat<N> upper_x = node->dequantizeUpperX();
+ const vfloat<N> lower_y = node->dequantizeLowerY();
+ const vfloat<N> upper_y = node->dequantizeUpperY();
+ const vfloat<N> lower_z = node->dequantizeLowerZ();
+ const vfloat<N> upper_z = node->dequantizeUpperZ();
+
+ const vfloat<K> lclipMinX = (lower_x[i] - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (lower_y[i] - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (lower_z[i] - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (upper_x[i] - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (upper_y[i] - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (upper_z[i] - ray.org.z) * ray.rdir.z;
+
+ const float round_up = 1.0f+3.0f*float(ulp);
+ const float round_down = 1.0f-3.0f*float(ulp);
+
+ const vfloat<K> lnearP = round_down*max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = round_up *min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);
+ dist = lnearP;
+ return lhit;
+ }
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectQuantizedNodeMBK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,
+ const TravRayK<K,false>& ray, const vfloat<K>& time, vfloat<K>& dist)
+
+ {
+ assert(movemask(node->validMask()) & ((size_t)1 << i));
+
+ const vfloat<K> lower_x = node->template dequantizeLowerX<K>(i,time);
+ const vfloat<K> upper_x = node->template dequantizeUpperX<K>(i,time);
+ const vfloat<K> lower_y = node->template dequantizeLowerY<K>(i,time);
+ const vfloat<K> upper_y = node->template dequantizeUpperY<K>(i,time);
+ const vfloat<K> lower_z = node->template dequantizeLowerZ<K>(i,time);
+ const vfloat<K> upper_z = node->template dequantizeUpperZ<K>(i,time);
+
+#if defined(__AVX2__) || defined(__ARM_NEON)
+ const vfloat<K> lclipMinX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMinY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMinZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);
+ const vfloat<K> lclipMaxX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> lclipMaxY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> lclipMaxZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);
+#else
+ const vfloat<K> lclipMinX = (lower_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (lower_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (lower_z - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (upper_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (upper_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (upper_z - ray.org.z) * ray.rdir.z;
+ #endif
+ const vfloat<K> lnearP = max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);
+ dist = lnearP;
+ return lhit;
+ }
+
+
+ template<int N, int K>
+ __forceinline vbool<K> intersectQuantizedNodeMBK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,
+ const TravRayK<K,true>& ray, const vfloat<K>& time, vfloat<K>& dist)
+
+ {
+ assert(movemask(node->validMask()) & ((size_t)1 << i));
+
+ const vfloat<K> lower_x = node->template dequantizeLowerX<K>(i,time);
+ const vfloat<K> upper_x = node->template dequantizeUpperX<K>(i,time);
+ const vfloat<K> lower_y = node->template dequantizeLowerY<K>(i,time);
+ const vfloat<K> upper_y = node->template dequantizeUpperY<K>(i,time);
+ const vfloat<K> lower_z = node->template dequantizeLowerZ<K>(i,time);
+ const vfloat<K> upper_z = node->template dequantizeUpperZ<K>(i,time);
+
+ const vfloat<K> lclipMinX = (lower_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMinY = (lower_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMinZ = (lower_z - ray.org.z) * ray.rdir.z;
+ const vfloat<K> lclipMaxX = (upper_x - ray.org.x) * ray.rdir.x;
+ const vfloat<K> lclipMaxY = (upper_y - ray.org.y) * ray.rdir.y;
+ const vfloat<K> lclipMaxZ = (upper_z - ray.org.z) * ray.rdir.z;
+
+ const float round_up = 1.0f+3.0f*float(ulp);
+ const float round_down = 1.0f-3.0f*float(ulp);
+
+ const vfloat<K> lnearP = round_down*max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));
+ const vfloat<K> lfarP = round_up *min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));
+ const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);
+ dist = lnearP;
+ return lhit;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Node intersectors used in hybrid traversal
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ /*! Intersects N nodes with K rays */
+ template<int N, int K, int types, bool robust>
+ struct BVHNNodeIntersectorK;
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN1, false>
+ {
+ /* vmask is both an input and an output parameter! Its initial value should be the parent node
+ hit mask, which is used for correctly computing the current hit mask. The parent hit mask
+ is actually required only for motion blur node intersections (because different rays may
+ have different times), so for regular nodes vmask is simply overwritten. */
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ vmask = intersectNodeK<N,K>(node.getAABBNode(), i, ray, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN1, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ vmask = intersectNodeKRobust<N,K>(node.getAABBNode(), i, ray, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN2, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ vmask = intersectNodeK<N,K>(node.getAABBNodeMB(), i, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN2, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ vmask = intersectNodeKRobust<N,K>(node.getAABBNodeMB(), i, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN1_UN1, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ if (likely(node.isAABBNode())) vmask = intersectNodeK<N,K>(node.getAABBNode(), i, ray, dist);
+ else /*if (unlikely(node.isOBBNode()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNode(), i, ray, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN1_UN1, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ if (likely(node.isAABBNode())) vmask = intersectNodeKRobust<N,K>(node.getAABBNode(), i, ray, dist);
+ else /*if (unlikely(node.isOBBNode()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNode(), i, ray, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN2_UN2, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ if (likely(node.isAABBNodeMB())) vmask = intersectNodeK<N,K>(node.getAABBNodeMB(), i, ray, time, dist);
+ else /*if (unlikely(node.isOBBNodeMB()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN2_UN2, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ if (likely(node.isAABBNodeMB())) vmask = intersectNodeKRobust<N,K>(node.getAABBNodeMB(), i, ray, time, dist);
+ else /*if (unlikely(node.isOBBNodeMB()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ vmask &= intersectNodeKMB4D<N,K>(node, i, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ vmask &= intersectNodeKMB4DRobust<N,K>(node, i, ray, time, dist);
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D_UN2, false>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ if (likely(node.isAABBNodeMB() || node.isAABBNodeMB4D())) {
+ vmask &= intersectNodeKMB4D<N,K>(node, i, ray, time, dist);
+ } else /*if (unlikely(node.isOBBNodeMB()))*/ {
+ assert(node.isOBBNodeMB());
+ vmask &= intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);
+ }
+ return true;
+ }
+ };
+
+ template<int N, int K>
+ struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D_UN2, true>
+ {
+ static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,
+ const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
+ {
+ if (likely(node.isAABBNodeMB() || node.isAABBNodeMB4D())) {
+ vmask &= intersectNodeKMB4DRobust<N,K>(node, i, ray, time, dist);
+ } else /*if (unlikely(node.isOBBNodeMB()))*/ {
+ assert(node.isOBBNodeMB());
+ vmask &= intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);
+ }
+ return true;
+ }
+ };
+
+
+ /*! Intersects N nodes with K rays */
+ template<int N, int K, bool robust>
+ struct BVHNQuantizedBaseNodeIntersectorK;
+
+ template<int N, int K>
+ struct BVHNQuantizedBaseNodeIntersectorK<N, K, false>
+ {
+ static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNode* node, const size_t i,
+ const TravRayK<K,false>& ray, vfloat<K>& dist)
+ {
+ return intersectQuantizedNodeK<N,K>(node,i,ray,dist);
+ }
+
+ static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,
+ const TravRayK<K,false>& ray, const vfloat<K>& time, vfloat<K>& dist)
+ {
+ return intersectQuantizedNodeMBK<N,K>(node,i,ray,time,dist);
+ }
+
+ };
+
+ template<int N, int K>
+ struct BVHNQuantizedBaseNodeIntersectorK<N, K, true>
+ {
+ static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNode* node, const size_t i,
+ const TravRayK<K,true>& ray, vfloat<K>& dist)
+ {
+ return intersectQuantizedNodeK<N,K>(node,i,ray,dist);
+ }
+
+ static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,
+ const TravRayK<K,true>& ray, const vfloat<K>& time, vfloat<K>& dist)
+ {
+ return intersectQuantizedNodeMBK<N,K>(node,i,ray,time,dist);
+ }
+ };
+
+
+ }
+}
diff --git a/thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h b/thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h
new file mode 100644
index 0000000000..55b2c27231
--- /dev/null
+++ b/thirdparty/embree/kernels/bvh/node_intersector_packet_stream.h
@@ -0,0 +1,189 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "node_intersector.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Ray packet structure used in stream traversal
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int K, bool robust>
+ struct TravRayKStream;
+
+ /* Fast variant */
+ template<int K>
+ struct TravRayKStream<K, false>
+ {
+ __forceinline TravRayKStream() {}
+
+ __forceinline TravRayKStream(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar)
+ {
+ init(ray_org, ray_dir);
+ tnear = ray_tnear;
+ tfar = ray_tfar;
+ }
+
+ __forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir)
+ {
+ rdir = rcp_safe(ray_dir);
+ org_rdir = ray_org * rdir;
+ }
+
+ Vec3vf<K> rdir;
+ Vec3vf<K> org_rdir;
+ vfloat<K> tnear;
+ vfloat<K> tfar;
+ };
+
+ template<int K>
+ using TravRayKStreamFast = TravRayKStream<K, false>;
+
+ /* Robust variant */
+ template<int K>
+ struct TravRayKStream<K, true>
+ {
+ __forceinline TravRayKStream() {}
+
+ __forceinline TravRayKStream(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar)
+ {
+ init(ray_org, ray_dir);
+ tnear = ray_tnear;
+ tfar = ray_tfar;
+ }
+
+ __forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir)
+ {
+ rdir = vfloat<K>(1.0f)/(zero_fix(ray_dir));
+ org = ray_org;
+ }
+
+ Vec3vf<K> rdir;
+ Vec3vf<K> org;
+ vfloat<K> tnear;
+ vfloat<K> tfar;
+ };
+
+ template<int K>
+ using TravRayKStreamRobust = TravRayKStream<K, true>;
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Fast AABBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline size_t intersectNode1(const typename BVHN<N>::AABBNode* __restrict__ node,
+ const TravRayKStreamFast<K>& ray, size_t k, const NearFarPrecalculations& nf)
+ {
+ const vfloat<N> bminX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
+ const vfloat<N> bminY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
+ const vfloat<N> bminZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
+ const vfloat<N> bmaxX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
+ const vfloat<N> bmaxY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
+ const vfloat<N> bmaxZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
+
+ const vfloat<N> rminX = msub(bminX, vfloat<N>(ray.rdir.x[k]), vfloat<N>(ray.org_rdir.x[k]));
+ const vfloat<N> rminY = msub(bminY, vfloat<N>(ray.rdir.y[k]), vfloat<N>(ray.org_rdir.y[k]));
+ const vfloat<N> rminZ = msub(bminZ, vfloat<N>(ray.rdir.z[k]), vfloat<N>(ray.org_rdir.z[k]));
+ const vfloat<N> rmaxX = msub(bmaxX, vfloat<N>(ray.rdir.x[k]), vfloat<N>(ray.org_rdir.x[k]));
+ const vfloat<N> rmaxY = msub(bmaxY, vfloat<N>(ray.rdir.y[k]), vfloat<N>(ray.org_rdir.y[k]));
+ const vfloat<N> rmaxZ = msub(bmaxZ, vfloat<N>(ray.rdir.z[k]), vfloat<N>(ray.org_rdir.z[k]));
+ const vfloat<N> rmin = maxi(rminX, rminY, rminZ, vfloat<N>(ray.tnear[k]));
+ const vfloat<N> rmax = mini(rmaxX, rmaxY, rmaxZ, vfloat<N>(ray.tfar[k]));
+
+ const vbool<N> vmask_first_hit = rmin <= rmax;
+
+ return movemask(vmask_first_hit) & (((size_t)1 << N)-1);
+ }
+
+ template<int N, int K>
+ __forceinline size_t intersectNodeK(const typename BVHN<N>::AABBNode* __restrict__ node, size_t i,
+ const TravRayKStreamFast<K>& ray, const NearFarPrecalculations& nf)
+ {
+ char* ptr = (char*)&node->lower_x + i*sizeof(float);
+ const vfloat<K> bminX = *(const float*)(ptr + nf.nearX);
+ const vfloat<K> bminY = *(const float*)(ptr + nf.nearY);
+ const vfloat<K> bminZ = *(const float*)(ptr + nf.nearZ);
+ const vfloat<K> bmaxX = *(const float*)(ptr + nf.farX);
+ const vfloat<K> bmaxY = *(const float*)(ptr + nf.farY);
+ const vfloat<K> bmaxZ = *(const float*)(ptr + nf.farZ);
+
+ const vfloat<K> rminX = msub(bminX, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> rminY = msub(bminY, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> rminZ = msub(bminZ, ray.rdir.z, ray.org_rdir.z);
+ const vfloat<K> rmaxX = msub(bmaxX, ray.rdir.x, ray.org_rdir.x);
+ const vfloat<K> rmaxY = msub(bmaxY, ray.rdir.y, ray.org_rdir.y);
+ const vfloat<K> rmaxZ = msub(bmaxZ, ray.rdir.z, ray.org_rdir.z);
+
+ const vfloat<K> rmin = maxi(rminX, rminY, rminZ, ray.tnear);
+ const vfloat<K> rmax = mini(rmaxX, rmaxY, rmaxZ, ray.tfar);
+
+ const vbool<K> vmask_first_hit = rmin <= rmax;
+
+ return movemask(vmask_first_hit);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Robust AABBNode intersection
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ template<int N, int K>
+ __forceinline size_t intersectNode1(const typename BVHN<N>::AABBNode* __restrict__ node,
+ const TravRayKStreamRobust<K>& ray, size_t k, const NearFarPrecalculations& nf)
+ {
+ const vfloat<N> bminX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
+ const vfloat<N> bminY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
+ const vfloat<N> bminZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
+ const vfloat<N> bmaxX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
+ const vfloat<N> bmaxY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
+ const vfloat<N> bmaxZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
+
+ const vfloat<N> rminX = (bminX - vfloat<N>(ray.org.x[k])) * vfloat<N>(ray.rdir.x[k]);
+ const vfloat<N> rminY = (bminY - vfloat<N>(ray.org.y[k])) * vfloat<N>(ray.rdir.y[k]);
+ const vfloat<N> rminZ = (bminZ - vfloat<N>(ray.org.z[k])) * vfloat<N>(ray.rdir.z[k]);
+ const vfloat<N> rmaxX = (bmaxX - vfloat<N>(ray.org.x[k])) * vfloat<N>(ray.rdir.x[k]);
+ const vfloat<N> rmaxY = (bmaxY - vfloat<N>(ray.org.y[k])) * vfloat<N>(ray.rdir.y[k]);
+ const vfloat<N> rmaxZ = (bmaxZ - vfloat<N>(ray.org.z[k])) * vfloat<N>(ray.rdir.z[k]);
+ const float round_up = 1.0f+3.0f*float(ulp); // FIXME: use per instruction rounding for AVX512
+ const vfloat<N> rmin = max(rminX, rminY, rminZ, vfloat<N>(ray.tnear[k]));
+ const vfloat<N> rmax = round_up *min(rmaxX, rmaxY, rmaxZ, vfloat<N>(ray.tfar[k]));
+
+ const vbool<N> vmask_first_hit = rmin <= rmax;
+
+ return movemask(vmask_first_hit) & (((size_t)1 << N)-1);
+ }
+
+ template<int N, int K>
+ __forceinline size_t intersectNodeK(const typename BVHN<N>::AABBNode* __restrict__ node, size_t i,
+ const TravRayKStreamRobust<K>& ray, const NearFarPrecalculations& nf)
+ {
+ char *ptr = (char*)&node->lower_x + i*sizeof(float);
+ const vfloat<K> bminX = *(const float*)(ptr + nf.nearX);
+ const vfloat<K> bminY = *(const float*)(ptr + nf.nearY);
+ const vfloat<K> bminZ = *(const float*)(ptr + nf.nearZ);
+ const vfloat<K> bmaxX = *(const float*)(ptr + nf.farX);
+ const vfloat<K> bmaxY = *(const float*)(ptr + nf.farY);
+ const vfloat<K> bmaxZ = *(const float*)(ptr + nf.farZ);
+
+ const vfloat<K> rminX = (bminX - ray.org.x) * ray.rdir.x;
+ const vfloat<K> rminY = (bminY - ray.org.y) * ray.rdir.y;
+ const vfloat<K> rminZ = (bminZ - ray.org.z) * ray.rdir.z;
+ const vfloat<K> rmaxX = (bmaxX - ray.org.x) * ray.rdir.x;
+ const vfloat<K> rmaxY = (bmaxY - ray.org.y) * ray.rdir.y;
+ const vfloat<K> rmaxZ = (bmaxZ - ray.org.z) * ray.rdir.z;
+
+ const float round_up = 1.0f+3.0f*float(ulp);
+ const vfloat<K> rmin = max(rminX, rminY, rminZ, vfloat<K>(ray.tnear));
+ const vfloat<K> rmax = round_up * min(rmaxX, rmaxY, rmaxZ, vfloat<K>(ray.tfar));
+
+ const vbool<K> vmask_first_hit = rmin <= rmax;
+
+ return movemask(vmask_first_hit);
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/common/accel.h b/thirdparty/embree/kernels/common/accel.h
new file mode 100644
index 0000000000..cc4ea1805b
--- /dev/null
+++ b/thirdparty/embree/kernels/common/accel.h
@@ -0,0 +1,556 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "ray.h"
+#include "point_query.h"
+#include "context.h"
+
+namespace embree
+{
+ class Scene;
+
+ /*! Base class for the acceleration structure data. */
+ class AccelData : public RefCount
+ {
+ ALIGNED_CLASS_(16);
+ public:
+ enum Type { TY_UNKNOWN = 0, TY_ACCELN = 1, TY_ACCEL_INSTANCE = 2, TY_BVH4 = 3, TY_BVH8 = 4 };
+
+ public:
+ AccelData (const Type type)
+ : bounds(empty), type(type) {}
+
+ /*! notifies the acceleration structure about the deletion of some geometry */
+ virtual void deleteGeometry(size_t geomID) {};
+
+ /*! clears the acceleration structure data */
+ virtual void clear() = 0;
+
+ /*! returns normal bounds */
+ __forceinline BBox3fa getBounds() const {
+ return bounds.bounds();
+ }
+
+ /*! returns bounds for some time */
+ __forceinline BBox3fa getBounds(float t) const {
+ return bounds.interpolate(t);
+ }
+
+ /*! returns linear bounds */
+ __forceinline LBBox3fa getLinearBounds() const {
+ return bounds;
+ }
+
+ /*! checks if acceleration structure is empty */
+ __forceinline bool isEmpty() const {
+ return bounds.bounds0.lower.x == float(pos_inf);
+ }
+
+ public:
+ LBBox3fa bounds; // linear bounds
+ Type type;
+ };
+
+ /*! Base class for all intersectable and buildable acceleration structures. */
+ class Accel : public AccelData
+ {
+ ALIGNED_CLASS_(16);
+ public:
+
+ struct Intersectors;
+
+ /*! Type of collide function */
+ typedef void (*CollideFunc)(void* bvh0, void* bvh1, RTCCollideFunc callback, void* userPtr);
+
+ /*! Type of point query function */
+ typedef bool(*PointQueryFunc)(Intersectors* This, /*!< this pointer to accel */
+ PointQuery* query, /*!< point query for lookup */
+ PointQueryContext* context); /*!< point query context */
+
+ /*! Type of intersect function pointer for single rays. */
+ typedef void (*IntersectFunc)(Intersectors* This, /*!< this pointer to accel */
+ RTCRayHit& ray, /*!< ray to intersect */
+ IntersectContext* context);
+
+ /*! Type of intersect function pointer for ray packets of size 4. */
+ typedef void (*IntersectFunc4)(const void* valid, /*!< pointer to valid mask */
+ Intersectors* This, /*!< this pointer to accel */
+ RTCRayHit4& ray, /*!< ray packet to intersect */
+ IntersectContext* context);
+
+ /*! Type of intersect function pointer for ray packets of size 8. */
+ typedef void (*IntersectFunc8)(const void* valid, /*!< pointer to valid mask */
+ Intersectors* This, /*!< this pointer to accel */
+ RTCRayHit8& ray, /*!< ray packet to intersect */
+ IntersectContext* context);
+
+ /*! Type of intersect function pointer for ray packets of size 16. */
+ typedef void (*IntersectFunc16)(const void* valid, /*!< pointer to valid mask */
+ Intersectors* This, /*!< this pointer to accel */
+ RTCRayHit16& ray, /*!< ray packet to intersect */
+ IntersectContext* context);
+
+ /*! Type of intersect function pointer for ray packets of size N. */
+ typedef void (*IntersectFuncN)(Intersectors* This, /*!< this pointer to accel */
+ RTCRayHitN** ray, /*!< ray stream to intersect */
+ const size_t N, /*!< number of rays in stream */
+ IntersectContext* context /*!< layout flags */);
+
+
+ /*! Type of occlusion function pointer for single rays. */
+ typedef void (*OccludedFunc) (Intersectors* This, /*!< this pointer to accel */
+ RTCRay& ray, /*!< ray to test occlusion */
+ IntersectContext* context);
+
+ /*! Type of occlusion function pointer for ray packets of size 4. */
+ typedef void (*OccludedFunc4) (const void* valid, /*!< pointer to valid mask */
+ Intersectors* This, /*!< this pointer to accel */
+ RTCRay4& ray, /*!< ray packet to test occlusion. */
+ IntersectContext* context);
+
+ /*! Type of occlusion function pointer for ray packets of size 8. */
+ typedef void (*OccludedFunc8) (const void* valid, /*!< pointer to valid mask */
+ Intersectors* This, /*!< this pointer to accel */
+ RTCRay8& ray, /*!< ray packet to test occlusion. */
+ IntersectContext* context);
+
+ /*! Type of occlusion function pointer for ray packets of size 16. */
+ typedef void (*OccludedFunc16) (const void* valid, /*!< pointer to valid mask */
+ Intersectors* This, /*!< this pointer to accel */
+ RTCRay16& ray, /*!< ray packet to test occlusion. */
+ IntersectContext* context);
+
+ /*! Type of intersect function pointer for ray packets of size N. */
+ typedef void (*OccludedFuncN)(Intersectors* This, /*!< this pointer to accel */
+ RTCRayN** ray, /*!< ray stream to test occlusion */
+ const size_t N, /*!< number of rays in stream */
+ IntersectContext* context /*!< layout flags */);
+ typedef void (*ErrorFunc) ();
+
+ struct Collider
+ {
+ Collider (ErrorFunc error = nullptr)
+ : collide((CollideFunc)error), name(nullptr) {}
+
+ Collider (CollideFunc collide, const char* name)
+ : collide(collide), name(name) {}
+
+ operator bool() const { return name; }
+
+ public:
+ CollideFunc collide;
+ const char* name;
+ };
+
+ struct Intersector1
+ {
+ Intersector1 (ErrorFunc error = nullptr)
+ : intersect((IntersectFunc)error), occluded((OccludedFunc)error), name(nullptr) {}
+
+ Intersector1 (IntersectFunc intersect, OccludedFunc occluded, const char* name)
+ : intersect(intersect), occluded(occluded), pointQuery(nullptr), name(name) {}
+
+ Intersector1 (IntersectFunc intersect, OccludedFunc occluded, PointQueryFunc pointQuery, const char* name)
+ : intersect(intersect), occluded(occluded), pointQuery(pointQuery), name(name) {}
+
+ operator bool() const { return name; }
+
+ public:
+ static const char* type;
+ IntersectFunc intersect;
+ OccludedFunc occluded;
+ PointQueryFunc pointQuery;
+ const char* name;
+ };
+
+ struct Intersector4
+ {
+ Intersector4 (ErrorFunc error = nullptr)
+ : intersect((IntersectFunc4)error), occluded((OccludedFunc4)error), name(nullptr) {}
+
+ Intersector4 (IntersectFunc4 intersect, OccludedFunc4 occluded, const char* name)
+ : intersect(intersect), occluded(occluded), name(name) {}
+
+ operator bool() const { return name; }
+
+ public:
+ static const char* type;
+ IntersectFunc4 intersect;
+ OccludedFunc4 occluded;
+ const char* name;
+ };
+
+ struct Intersector8
+ {
+ Intersector8 (ErrorFunc error = nullptr)
+ : intersect((IntersectFunc8)error), occluded((OccludedFunc8)error), name(nullptr) {}
+
+ Intersector8 (IntersectFunc8 intersect, OccludedFunc8 occluded, const char* name)
+ : intersect(intersect), occluded(occluded), name(name) {}
+
+ operator bool() const { return name; }
+
+ public:
+ static const char* type;
+ IntersectFunc8 intersect;
+ OccludedFunc8 occluded;
+ const char* name;
+ };
+
+ struct Intersector16
+ {
+ Intersector16 (ErrorFunc error = nullptr)
+ : intersect((IntersectFunc16)error), occluded((OccludedFunc16)error), name(nullptr) {}
+
+ Intersector16 (IntersectFunc16 intersect, OccludedFunc16 occluded, const char* name)
+ : intersect(intersect), occluded(occluded), name(name) {}
+
+ operator bool() const { return name; }
+
+ public:
+ static const char* type;
+ IntersectFunc16 intersect;
+ OccludedFunc16 occluded;
+ const char* name;
+ };
+
+ struct IntersectorN
+ {
+ IntersectorN (ErrorFunc error = nullptr)
+ : intersect((IntersectFuncN)error), occluded((OccludedFuncN)error), name(nullptr) {}
+
+ IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name)
+ : intersect(intersect), occluded(occluded), name(name) {}
+
+ operator bool() const { return name; }
+
+ public:
+ static const char* type;
+ IntersectFuncN intersect;
+ OccludedFuncN occluded;
+ const char* name;
+ };
+
+ struct Intersectors
+ {
+ Intersectors()
+ : ptr(nullptr), leafIntersector(nullptr), collider(nullptr), intersector1(nullptr), intersector4(nullptr), intersector8(nullptr), intersector16(nullptr), intersectorN(nullptr) {}
+
+ Intersectors (ErrorFunc error)
+ : ptr(nullptr), leafIntersector(nullptr), collider(error), intersector1(error), intersector4(error), intersector8(error), intersector16(error), intersectorN(error) {}
+
+ void print(size_t ident)
+ {
+ if (collider.name) {
+ for (size_t i=0; i<ident; i++) std::cout << " ";
+ std::cout << "collider = " << collider.name << std::endl;
+ }
+ if (intersector1.name) {
+ for (size_t i=0; i<ident; i++) std::cout << " ";
+ std::cout << "intersector1 = " << intersector1.name << std::endl;
+ }
+ if (intersector4.name) {
+ for (size_t i=0; i<ident; i++) std::cout << " ";
+ std::cout << "intersector4 = " << intersector4.name << std::endl;
+ }
+ if (intersector8.name) {
+ for (size_t i=0; i<ident; i++) std::cout << " ";
+ std::cout << "intersector8 = " << intersector8.name << std::endl;
+ }
+ if (intersector16.name) {
+ for (size_t i=0; i<ident; i++) std::cout << " ";
+ std::cout << "intersector16 = " << intersector16.name << std::endl;
+ }
+ if (intersectorN.name) {
+ for (size_t i=0; i<ident; i++) std::cout << " ";
+ std::cout << "intersectorN = " << intersectorN.name << std::endl;
+ }
+ }
+
+ void select(bool filter)
+ {
+ if (intersector4_filter) {
+ if (filter) intersector4 = intersector4_filter;
+ else intersector4 = intersector4_nofilter;
+ }
+ if (intersector8_filter) {
+ if (filter) intersector8 = intersector8_filter;
+ else intersector8 = intersector8_nofilter;
+ }
+ if (intersector16_filter) {
+ if (filter) intersector16 = intersector16_filter;
+ else intersector16 = intersector16_nofilter;
+ }
+ if (intersectorN_filter) {
+ if (filter) intersectorN = intersectorN_filter;
+ else intersectorN = intersectorN_nofilter;
+ }
+ }
+
+ __forceinline bool pointQuery (PointQuery* query, PointQueryContext* context) {
+ assert(intersector1.pointQuery);
+ return intersector1.pointQuery(this,query,context);
+ }
+
+ /*! collides two scenes */
+ __forceinline void collide (Accel* scene0, Accel* scene1, RTCCollideFunc callback, void* userPtr) {
+ assert(collider.collide);
+ collider.collide(scene0->intersectors.ptr,scene1->intersectors.ptr,callback,userPtr);
+ }
+
+ /*! Intersects a single ray with the scene. */
+ __forceinline void intersect (RTCRayHit& ray, IntersectContext* context) {
+ assert(intersector1.intersect);
+ intersector1.intersect(this,ray,context);
+ }
+
+ /*! Intersects a packet of 4 rays with the scene. */
+ __forceinline void intersect4 (const void* valid, RTCRayHit4& ray, IntersectContext* context) {
+ assert(intersector4.intersect);
+ intersector4.intersect(valid,this,ray,context);
+ }
+
+ /*! Intersects a packet of 8 rays with the scene. */
+ __forceinline void intersect8 (const void* valid, RTCRayHit8& ray, IntersectContext* context) {
+ assert(intersector8.intersect);
+ intersector8.intersect(valid,this,ray,context);
+ }
+
+ /*! Intersects a packet of 16 rays with the scene. */
+ __forceinline void intersect16 (const void* valid, RTCRayHit16& ray, IntersectContext* context) {
+ assert(intersector16.intersect);
+ intersector16.intersect(valid,this,ray,context);
+ }
+
+ /*! Intersects a stream of N rays in SOA layout with the scene. */
+ __forceinline void intersectN (RTCRayHitN** rayN, const size_t N, IntersectContext* context)
+ {
+ assert(intersectorN.intersect);
+ intersectorN.intersect(this,rayN,N,context);
+ }
+
+#if defined(__SSE__)
+ __forceinline void intersect(const vbool4& valid, RayHitK<4>& ray, IntersectContext* context) {
+ const vint<4> mask = valid.mask32();
+ intersect4(&mask,(RTCRayHit4&)ray,context);
+ }
+#endif
+#if defined(__AVX__)
+ __forceinline void intersect(const vbool8& valid, RayHitK<8>& ray, IntersectContext* context) {
+ const vint<8> mask = valid.mask32();
+ intersect8(&mask,(RTCRayHit8&)ray,context);
+ }
+#endif
+#if defined(__AVX512F__)
+ __forceinline void intersect(const vbool16& valid, RayHitK<16>& ray, IntersectContext* context) {
+ const vint<16> mask = valid.mask32();
+ intersect16(&mask,(RTCRayHit16&)ray,context);
+ }
+#endif
+
+ template<int K>
+ __forceinline void intersectN (RayHitK<K>** rayN, const size_t N, IntersectContext* context)
+ {
+ intersectN((RTCRayHitN**)rayN,N,context);
+ }
+
+ /*! Tests if single ray is occluded by the scene. */
+ __forceinline void occluded (RTCRay& ray, IntersectContext* context) {
+ assert(intersector1.occluded);
+ intersector1.occluded(this,ray,context);
+ }
+
+ /*! Tests if a packet of 4 rays is occluded by the scene. */
+ __forceinline void occluded4 (const void* valid, RTCRay4& ray, IntersectContext* context) {
+ assert(intersector4.occluded);
+ intersector4.occluded(valid,this,ray,context);
+ }
+
+ /*! Tests if a packet of 8 rays is occluded by the scene. */
+ __forceinline void occluded8 (const void* valid, RTCRay8& ray, IntersectContext* context) {
+ assert(intersector8.occluded);
+ intersector8.occluded(valid,this,ray,context);
+ }
+
+ /*! Tests if a packet of 16 rays is occluded by the scene. */
+ __forceinline void occluded16 (const void* valid, RTCRay16& ray, IntersectContext* context) {
+ assert(intersector16.occluded);
+ intersector16.occluded(valid,this,ray,context);
+ }
+
+ /*! Tests if a stream of N rays in SOA layout is occluded by the scene. */
+ __forceinline void occludedN (RTCRayN** rayN, const size_t N, IntersectContext* context)
+ {
+ assert(intersectorN.occluded);
+ intersectorN.occluded(this,rayN,N,context);
+ }
+
+#if defined(__SSE__)
+ __forceinline void occluded(const vbool4& valid, RayK<4>& ray, IntersectContext* context) {
+ const vint<4> mask = valid.mask32();
+ occluded4(&mask,(RTCRay4&)ray,context);
+ }
+#endif
+#if defined(__AVX__)
+ __forceinline void occluded(const vbool8& valid, RayK<8>& ray, IntersectContext* context) {
+ const vint<8> mask = valid.mask32();
+ occluded8(&mask,(RTCRay8&)ray,context);
+ }
+#endif
+#if defined(__AVX512F__)
+ __forceinline void occluded(const vbool16& valid, RayK<16>& ray, IntersectContext* context) {
+ const vint<16> mask = valid.mask32();
+ occluded16(&mask,(RTCRay16&)ray,context);
+ }
+#endif
+
+ template<int K>
+ __forceinline void occludedN (RayK<K>** rayN, const size_t N, IntersectContext* context)
+ {
+ occludedN((RTCRayN**)rayN,N,context);
+ }
+
+ /*! Tests if single ray is occluded by the scene. */
+ __forceinline void intersect(RTCRay& ray, IntersectContext* context) {
+ occluded(ray, context);
+ }
+
+ /*! Tests if a packet of K rays is occluded by the scene. */
+ template<int K>
+ __forceinline void intersect(const vbool<K>& valid, RayK<K>& ray, IntersectContext* context) {
+ occluded(valid, ray, context);
+ }
+
+ /*! Tests if a packet of N rays in SOA layout is occluded by the scene. */
+ template<int K>
+ __forceinline void intersectN(RayK<K>** rayN, const size_t N, IntersectContext* context) {
+ occludedN(rayN, N, context);
+ }
+
+ public:
+ AccelData* ptr;
+ void* leafIntersector;
+ Collider collider;
+ Intersector1 intersector1;
+ Intersector4 intersector4;
+ Intersector4 intersector4_filter;
+ Intersector4 intersector4_nofilter;
+ Intersector8 intersector8;
+ Intersector8 intersector8_filter;
+ Intersector8 intersector8_nofilter;
+ Intersector16 intersector16;
+ Intersector16 intersector16_filter;
+ Intersector16 intersector16_nofilter;
+ IntersectorN intersectorN;
+ IntersectorN intersectorN_filter;
+ IntersectorN intersectorN_nofilter;
+ };
+
+ public:
+
+ /*! Construction */
+ Accel (const AccelData::Type type)
+ : AccelData(type) {}
+
+ /*! Construction */
+ Accel (const AccelData::Type type, const Intersectors& intersectors)
+ : AccelData(type), intersectors(intersectors) {}
+
+ /*! Virtual destructor */
+ virtual ~Accel() {}
+
+ /*! makes the acceleration structure immutable */
+ virtual void immutable () {}
+
+ /*! build acceleration structure */
+ virtual void build () = 0;
+
+ public:
+ Intersectors intersectors;
+ };
+
+#define DEFINE_COLLIDER(symbol,collider) \
+ Accel::Collider symbol() { \
+ return Accel::Collider((Accel::CollideFunc)collider::collide, \
+ TOSTRING(isa) "::" TOSTRING(symbol)); \
+ }
+
+#define DEFINE_INTERSECTOR1(symbol,intersector) \
+ Accel::Intersector1 symbol() { \
+ return Accel::Intersector1((Accel::IntersectFunc )intersector::intersect, \
+ (Accel::OccludedFunc )intersector::occluded, \
+ (Accel::PointQueryFunc)intersector::pointQuery,\
+ TOSTRING(isa) "::" TOSTRING(symbol)); \
+ }
+
+#define DEFINE_INTERSECTOR4(symbol,intersector) \
+ Accel::Intersector4 symbol() { \
+ return Accel::Intersector4((Accel::IntersectFunc4)intersector::intersect, \
+ (Accel::OccludedFunc4)intersector::occluded, \
+ TOSTRING(isa) "::" TOSTRING(symbol)); \
+ }
+
+#define DEFINE_INTERSECTOR8(symbol,intersector) \
+ Accel::Intersector8 symbol() { \
+ return Accel::Intersector8((Accel::IntersectFunc8)intersector::intersect, \
+ (Accel::OccludedFunc8)intersector::occluded, \
+ TOSTRING(isa) "::" TOSTRING(symbol)); \
+ }
+
+#define DEFINE_INTERSECTOR16(symbol,intersector) \
+ Accel::Intersector16 symbol() { \
+ return Accel::Intersector16((Accel::IntersectFunc16)intersector::intersect, \
+ (Accel::OccludedFunc16)intersector::occluded, \
+ TOSTRING(isa) "::" TOSTRING(symbol)); \
+ }
+
+#define DEFINE_INTERSECTORN(symbol,intersector) \
+ Accel::IntersectorN symbol() { \
+ return Accel::IntersectorN((Accel::IntersectFuncN)intersector::intersect, \
+ (Accel::OccludedFuncN)intersector::occluded, \
+ TOSTRING(isa) "::" TOSTRING(symbol)); \
+ }
+
+ /* ray stream filter interface */
+ typedef void (*intersectStreamAOS_func)(Scene* scene, RTCRayHit* _rayN, const size_t N, const size_t stride, IntersectContext* context);
+ typedef void (*intersectStreamAOP_func)(Scene* scene, RTCRayHit** _rayN, const size_t N, IntersectContext* context);
+ typedef void (*intersectStreamSOA_func)(Scene* scene, char* rayN, const size_t N, const size_t streams, const size_t stream_offset, IntersectContext* context);
+ typedef void (*intersectStreamSOP_func)(Scene* scene, const RTCRayHitNp* rayN, const size_t N, IntersectContext* context);
+
+ typedef void (*occludedStreamAOS_func)(Scene* scene, RTCRay* _rayN, const size_t N, const size_t stride, IntersectContext* context);
+ typedef void (*occludedStreamAOP_func)(Scene* scene, RTCRay** _rayN, const size_t N, IntersectContext* context);
+ typedef void (*occludedStreamSOA_func)(Scene* scene, char* rayN, const size_t N, const size_t streams, const size_t stream_offset, IntersectContext* context);
+ typedef void (*occludedStreamSOP_func)(Scene* scene, const RTCRayNp* rayN, const size_t N, IntersectContext* context);
+
+ struct RayStreamFilterFuncs
+ {
+ RayStreamFilterFuncs()
+ : intersectAOS(nullptr), intersectAOP(nullptr), intersectSOA(nullptr), intersectSOP(nullptr),
+ occludedAOS(nullptr), occludedAOP(nullptr), occludedSOA(nullptr), occludedSOP(nullptr) {}
+
+ RayStreamFilterFuncs(void (*ptr) ())
+ : intersectAOS((intersectStreamAOS_func) ptr), intersectAOP((intersectStreamAOP_func) ptr), intersectSOA((intersectStreamSOA_func) ptr), intersectSOP((intersectStreamSOP_func) ptr),
+ occludedAOS((occludedStreamAOS_func) ptr), occludedAOP((occludedStreamAOP_func) ptr), occludedSOA((occludedStreamSOA_func) ptr), occludedSOP((occludedStreamSOP_func) ptr) {}
+
+ RayStreamFilterFuncs(intersectStreamAOS_func intersectAOS, intersectStreamAOP_func intersectAOP, intersectStreamSOA_func intersectSOA, intersectStreamSOP_func intersectSOP,
+ occludedStreamAOS_func occludedAOS, occludedStreamAOP_func occludedAOP, occludedStreamSOA_func occludedSOA, occludedStreamSOP_func occludedSOP)
+ : intersectAOS(intersectAOS), intersectAOP(intersectAOP), intersectSOA(intersectSOA), intersectSOP(intersectSOP),
+ occludedAOS(occludedAOS), occludedAOP(occludedAOP), occludedSOA(occludedSOA), occludedSOP(occludedSOP) {}
+
+ public:
+ intersectStreamAOS_func intersectAOS;
+ intersectStreamAOP_func intersectAOP;
+ intersectStreamSOA_func intersectSOA;
+ intersectStreamSOP_func intersectSOP;
+
+ occludedStreamAOS_func occludedAOS;
+ occludedStreamAOP_func occludedAOP;
+ occludedStreamSOA_func occludedSOA;
+ occludedStreamSOP_func occludedSOP;
+ };
+
+ typedef RayStreamFilterFuncs (*RayStreamFilterFuncsType)();
+}
diff --git a/thirdparty/embree/kernels/common/accelinstance.h b/thirdparty/embree/kernels/common/accelinstance.h
new file mode 100644
index 0000000000..c63ef998bd
--- /dev/null
+++ b/thirdparty/embree/kernels/common/accelinstance.h
@@ -0,0 +1,41 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "accel.h"
+#include "builder.h"
+
+namespace embree
+{
+ class AccelInstance : public Accel
+ {
+ public:
+ AccelInstance (AccelData* accel, Builder* builder, Intersectors& intersectors)
+ : Accel(AccelData::TY_ACCEL_INSTANCE,intersectors), accel(accel), builder(builder) {}
+
+ void immutable () {
+ builder.reset(nullptr);
+ }
+
+ public:
+ void build () {
+ if (builder) builder->build();
+ bounds = accel->bounds;
+ }
+
+ void deleteGeometry(size_t geomID) {
+ if (accel ) accel->deleteGeometry(geomID);
+ if (builder) builder->deleteGeometry(geomID);
+ }
+
+ void clear() {
+ if (accel) accel->clear();
+ if (builder) builder->clear();
+ }
+
+ private:
+ std::unique_ptr<AccelData> accel;
+ std::unique_ptr<Builder> builder;
+ };
+}
diff --git a/thirdparty/embree/kernels/common/acceln.cpp b/thirdparty/embree/kernels/common/acceln.cpp
new file mode 100644
index 0000000000..32a27c560a
--- /dev/null
+++ b/thirdparty/embree/kernels/common/acceln.cpp
@@ -0,0 +1,232 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "acceln.h"
+#include "ray.h"
+#include "../../include/embree3/rtcore_ray.h"
+#include "../../common/algorithms/parallel_for.h"
+
+namespace embree
+{
+ AccelN::AccelN()
+ : Accel(AccelData::TY_ACCELN), accels() {}
+
+ AccelN::~AccelN()
+ {
+ for (size_t i=0; i<accels.size(); i++)
+ delete accels[i];
+ }
+
+ void AccelN::accels_add(Accel* accel)
+ {
+ assert(accel);
+ accels.push_back(accel);
+ }
+
+ void AccelN::accels_init()
+ {
+ for (size_t i=0; i<accels.size(); i++)
+ delete accels[i];
+
+ accels.clear();
+ }
+
+ bool AccelN::pointQuery (Accel::Intersectors* This_in, PointQuery* query, PointQueryContext* context)
+ {
+ bool changed = false;
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++)
+ if (!This->accels[i]->isEmpty())
+ changed |= This->accels[i]->intersectors.pointQuery(query,context);
+ return changed;
+ }
+
+ void AccelN::intersect (Accel::Intersectors* This_in, RTCRayHit& ray, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++)
+ if (!This->accels[i]->isEmpty())
+ This->accels[i]->intersectors.intersect(ray,context);
+ }
+
+ void AccelN::intersect4 (const void* valid, Accel::Intersectors* This_in, RTCRayHit4& ray, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++)
+ if (!This->accels[i]->isEmpty())
+ This->accels[i]->intersectors.intersect4(valid,ray,context);
+ }
+
+ void AccelN::intersect8 (const void* valid, Accel::Intersectors* This_in, RTCRayHit8& ray, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++)
+ if (!This->accels[i]->isEmpty())
+ This->accels[i]->intersectors.intersect8(valid,ray,context);
+ }
+
+ void AccelN::intersect16 (const void* valid, Accel::Intersectors* This_in, RTCRayHit16& ray, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++)
+ if (!This->accels[i]->isEmpty())
+ This->accels[i]->intersectors.intersect16(valid,ray,context);
+ }
+
+ void AccelN::intersectN (Accel::Intersectors* This_in, RTCRayHitN** ray, const size_t N, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++)
+ if (!This->accels[i]->isEmpty())
+ This->accels[i]->intersectors.intersectN(ray,N,context);
+ }
+
+ void AccelN::occluded (Accel::Intersectors* This_in, RTCRay& ray, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++) {
+ if (This->accels[i]->isEmpty()) continue;
+ This->accels[i]->intersectors.occluded(ray,context);
+ if (ray.tfar < 0.0f) break;
+ }
+ }
+
+ void AccelN::occluded4 (const void* valid, Accel::Intersectors* This_in, RTCRay4& ray, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++) {
+ if (This->accels[i]->isEmpty()) continue;
+ This->accels[i]->intersectors.occluded4(valid,ray,context);
+#if defined(__SSE2__)
+ vbool4 valid0 = asBool(((vint4*)valid)[0]);
+ vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
+ if (unlikely(none(valid0 & hit0))) break;
+#endif
+ }
+ }
+
+ void AccelN::occluded8 (const void* valid, Accel::Intersectors* This_in, RTCRay8& ray, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++) {
+ if (This->accels[i]->isEmpty()) continue;
+ This->accels[i]->intersectors.occluded8(valid,ray,context);
+#if defined(__SSE2__) // FIXME: use higher ISA
+ vbool4 valid0 = asBool(((vint4*)valid)[0]);
+ vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
+ vbool4 valid1 = asBool(((vint4*)valid)[1]);
+ vbool4 hit1 = ((vfloat4*)ray.tfar)[1] >= vfloat4(zero);
+ if (unlikely((none((valid0 & hit0) | (valid1 & hit1))))) break;
+#endif
+ }
+ }
+
+ void AccelN::occluded16 (const void* valid, Accel::Intersectors* This_in, RTCRay16& ray, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ for (size_t i=0; i<This->accels.size(); i++) {
+ if (This->accels[i]->isEmpty()) continue;
+ This->accels[i]->intersectors.occluded16(valid,ray,context);
+#if defined(__SSE2__) // FIXME: use higher ISA
+ vbool4 valid0 = asBool(((vint4*)valid)[0]);
+ vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero);
+ vbool4 valid1 = asBool(((vint4*)valid)[1]);
+ vbool4 hit1 = ((vfloat4*)ray.tfar)[1] >= vfloat4(zero);
+ vbool4 valid2 = asBool(((vint4*)valid)[2]);
+ vbool4 hit2 = ((vfloat4*)ray.tfar)[2] >= vfloat4(zero);
+ vbool4 valid3 = asBool(((vint4*)valid)[3]);
+ vbool4 hit3 = ((vfloat4*)ray.tfar)[3] >= vfloat4(zero);
+ if (unlikely((none((valid0 & hit0) | (valid1 & hit1) | (valid2 & hit2) | (valid3 & hit3))))) break;
+#endif
+ }
+ }
+
+ void AccelN::occludedN (Accel::Intersectors* This_in, RTCRayN** ray, const size_t N, IntersectContext* context)
+ {
+ AccelN* This = (AccelN*)This_in->ptr;
+ size_t M = N;
+ for (size_t i=0; i<This->accels.size(); i++)
+ if (!This->accels[i]->isEmpty())
+ This->accels[i]->intersectors.occludedN(ray,M,context);
+ }
+
+ void AccelN::accels_print(size_t ident)
+ {
+ for (size_t i=0; i<accels.size(); i++)
+ {
+ for (size_t j=0; j<ident; j++) std::cout << " ";
+ std::cout << "accels[" << i << "]" << std::endl;
+ accels[i]->intersectors.print(ident+2);
+ }
+ }
+
+ void AccelN::accels_immutable()
+ {
+ for (size_t i=0; i<accels.size(); i++)
+ accels[i]->immutable();
+ }
+
+ void AccelN::accels_build ()
+ {
+ /* reduce memory consumption */
+ accels.shrink_to_fit();
+
+ /* build all acceleration structures in parallel */
+ parallel_for (accels.size(), [&] (size_t i) {
+ accels[i]->build();
+ });
+
+ /* create list of non-empty acceleration structures */
+ bool valid1 = true;
+ bool valid4 = true;
+ bool valid8 = true;
+ bool valid16 = true;
+ for (size_t i=0; i<accels.size(); i++) {
+ valid1 &= (bool) accels[i]->intersectors.intersector1;
+ valid4 &= (bool) accels[i]->intersectors.intersector4;
+ valid8 &= (bool) accels[i]->intersectors.intersector8;
+ valid16 &= (bool) accels[i]->intersectors.intersector16;
+ }
+
+ if (accels.size() == 1) {
+ type = accels[0]->type; // FIXME: should just assign entire Accel
+ bounds = accels[0]->bounds;
+ intersectors = accels[0]->intersectors;
+ }
+ else
+ {
+ type = AccelData::TY_ACCELN;
+ intersectors.ptr = this;
+ intersectors.intersector1 = Intersector1(&intersect,&occluded,&pointQuery,valid1 ? "AccelN::intersector1": nullptr);
+ intersectors.intersector4 = Intersector4(&intersect4,&occluded4,valid4 ? "AccelN::intersector4" : nullptr);
+ intersectors.intersector8 = Intersector8(&intersect8,&occluded8,valid8 ? "AccelN::intersector8" : nullptr);
+ intersectors.intersector16 = Intersector16(&intersect16,&occluded16,valid16 ? "AccelN::intersector16": nullptr);
+ intersectors.intersectorN = IntersectorN(&intersectN,&occludedN,"AccelN::intersectorN");
+
+ /*! calculate bounds */
+ bounds = empty;
+ for (size_t i=0; i<accels.size(); i++)
+ bounds.extend(accels[i]->bounds);
+ }
+ }
+
+ void AccelN::accels_select(bool filter)
+ {
+ for (size_t i=0; i<accels.size(); i++)
+ accels[i]->intersectors.select(filter);
+ }
+
+ void AccelN::accels_deleteGeometry(size_t geomID)
+ {
+ for (size_t i=0; i<accels.size(); i++)
+ accels[i]->deleteGeometry(geomID);
+ }
+
+ void AccelN::accels_clear()
+ {
+ for (size_t i=0; i<accels.size(); i++) {
+ accels[i]->clear();
+ }
+ }
+}
+
diff --git a/thirdparty/embree/kernels/common/acceln.h b/thirdparty/embree/kernels/common/acceln.h
new file mode 100644
index 0000000000..0445b2e811
--- /dev/null
+++ b/thirdparty/embree/kernels/common/acceln.h
@@ -0,0 +1,49 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "accel.h"
+
+namespace embree
+{
+ /*! merges N acceleration structures together, by processing them in order */
+ class AccelN : public Accel
+ {
+ public:
+ AccelN ();
+ ~AccelN();
+
+ public:
+ void accels_add(Accel* accel);
+ void accels_init();
+
+ public:
+ static bool pointQuery (Accel::Intersectors* This, PointQuery* query, PointQueryContext* context);
+
+ public:
+ static void intersect (Accel::Intersectors* This, RTCRayHit& ray, IntersectContext* context);
+ static void intersect4 (const void* valid, Accel::Intersectors* This, RTCRayHit4& ray, IntersectContext* context);
+ static void intersect8 (const void* valid, Accel::Intersectors* This, RTCRayHit8& ray, IntersectContext* context);
+ static void intersect16 (const void* valid, Accel::Intersectors* This, RTCRayHit16& ray, IntersectContext* context);
+ static void intersectN (Accel::Intersectors* This, RTCRayHitN** ray, const size_t N, IntersectContext* context);
+
+ public:
+ static void occluded (Accel::Intersectors* This, RTCRay& ray, IntersectContext* context);
+ static void occluded4 (const void* valid, Accel::Intersectors* This, RTCRay4& ray, IntersectContext* context);
+ static void occluded8 (const void* valid, Accel::Intersectors* This, RTCRay8& ray, IntersectContext* context);
+ static void occluded16 (const void* valid, Accel::Intersectors* This, RTCRay16& ray, IntersectContext* context);
+ static void occludedN (Accel::Intersectors* This, RTCRayN** ray, const size_t N, IntersectContext* context);
+
+ public:
+ void accels_print(size_t ident);
+ void accels_immutable();
+ void accels_build ();
+ void accels_select(bool filter);
+ void accels_deleteGeometry(size_t geomID);
+ void accels_clear ();
+
+ public:
+ std::vector<Accel*> accels;
+ };
+}
diff --git a/thirdparty/embree/kernels/common/accelset.cpp b/thirdparty/embree/kernels/common/accelset.cpp
new file mode 100644
index 0000000000..8c18f31776
--- /dev/null
+++ b/thirdparty/embree/kernels/common/accelset.cpp
@@ -0,0 +1,17 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "accelset.h"
+#include "scene.h"
+
+namespace embree
+{
+ AccelSet::AccelSet (Device* device, Geometry::GType gtype, size_t numItems, size_t numTimeSteps)
+ : Geometry(device,gtype,(unsigned int)numItems,(unsigned int)numTimeSteps), boundsFunc(nullptr) {}
+
+ AccelSet::IntersectorN::IntersectorN (ErrorFunc error)
+ : intersect((IntersectFuncN)error), occluded((OccludedFuncN)error), name(nullptr) {}
+
+ AccelSet::IntersectorN::IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name)
+ : intersect(intersect), occluded(occluded), name(name) {}
+}
diff --git a/thirdparty/embree/kernels/common/accelset.h b/thirdparty/embree/kernels/common/accelset.h
new file mode 100644
index 0000000000..90b184a07b
--- /dev/null
+++ b/thirdparty/embree/kernels/common/accelset.h
@@ -0,0 +1,248 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "builder.h"
+#include "geometry.h"
+#include "ray.h"
+#include "hit.h"
+
+namespace embree
+{
+ struct IntersectFunctionNArguments;
+ struct OccludedFunctionNArguments;
+
+ typedef void (*ReportIntersectionFunc) (IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
+ typedef void (*ReportOcclusionFunc) (OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
+
+ struct IntersectFunctionNArguments : public RTCIntersectFunctionNArguments
+ {
+ IntersectContext* internal_context;
+ Geometry* geometry;
+ ReportIntersectionFunc report;
+ };
+
+ struct OccludedFunctionNArguments : public RTCOccludedFunctionNArguments
+ {
+ IntersectContext* internal_context;
+ Geometry* geometry;
+ ReportOcclusionFunc report;
+ };
+
+ /*! Base class for set of acceleration structures. */
+ class AccelSet : public Geometry
+ {
+ public:
+ typedef RTCIntersectFunctionN IntersectFuncN;
+ typedef RTCOccludedFunctionN OccludedFuncN;
+ typedef void (*ErrorFunc) ();
+
+ struct IntersectorN
+ {
+ IntersectorN (ErrorFunc error = nullptr) ;
+ IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name);
+
+ operator bool() const { return name; }
+
+ public:
+ static const char* type;
+ IntersectFuncN intersect;
+ OccludedFuncN occluded;
+ const char* name;
+ };
+
+ public:
+
+ /*! construction */
+ AccelSet (Device* device, Geometry::GType gtype, size_t items, size_t numTimeSteps);
+
+ /*! makes the acceleration structure immutable */
+ virtual void immutable () {}
+
+ /*! build accel */
+ virtual void build () = 0;
+
+ /*! check if the i'th primitive is valid between the specified time range */
+ __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
+ {
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
+ if (!isvalid_non_empty(bounds(i,itime))) return false;
+
+ return true;
+ }
+
+ /*! Calculates the bounds of an item */
+ __forceinline BBox3fa bounds(size_t i, size_t itime = 0) const
+ {
+ BBox3fa box;
+ assert(i < size());
+ RTCBoundsFunctionArguments args;
+ args.geometryUserPtr = userPtr;
+ args.primID = (unsigned int)i;
+ args.timeStep = (unsigned int)itime;
+ args.bounds_o = (RTCBounds*)&box;
+ boundsFunc(&args);
+ return box;
+ }
+
+ /*! calculates the linear bounds of the i'th item at the itime'th time segment */
+ __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const
+ {
+ BBox3fa box[2];
+ assert(i < size());
+ RTCBoundsFunctionArguments args;
+ args.geometryUserPtr = userPtr;
+ args.primID = (unsigned int)i;
+ args.timeStep = (unsigned int)(itime+0);
+ args.bounds_o = (RTCBounds*)&box[0];
+ boundsFunc(&args);
+ args.timeStep = (unsigned int)(itime+1);
+ args.bounds_o = (RTCBounds*)&box[1];
+ boundsFunc(&args);
+ return LBBox3fa(box[0],box[1]);
+ }
+
+ /*! calculates the build bounds of the i'th item, if it's valid */
+ __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
+ {
+ const BBox3fa b = bounds(i);
+ if (bbox) *bbox = b;
+ return isvalid_non_empty(b);
+ }
+
+ /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
+ __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
+ {
+ const LBBox3fa bounds = linearBounds(i,itime);
+ bbox = bounds.bounds0; // use bounding box of first timestep to build BVH
+ return isvalid_non_empty(bounds);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
+ return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const {
+ if (!valid(i, timeSegmentRange(time_range))) return false;
+ bbox = linearBounds(i, time_range);
+ return true;
+ }
+
+ /* gets version info of topology */
+ unsigned int getTopologyVersion() const {
+ return numPrimitives;
+ }
+
+ /* returns true if topology changed */
+ bool topologyChanged(unsigned int otherVersion) const {
+ return numPrimitives != otherVersion;
+ }
+
+ public:
+
+ /*! Intersects a single ray with the scene. */
+ __forceinline void intersect (RayHit& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
+ {
+ assert(primID < size());
+ assert(intersectorN.intersect);
+
+ int mask = -1;
+ IntersectFunctionNArguments args;
+ args.valid = &mask;
+ args.geometryUserPtr = userPtr;
+ args.context = context->user;
+ args.rayhit = (RTCRayHitN*)&ray;
+ args.N = 1;
+ args.geomID = geomID;
+ args.primID = primID;
+ args.internal_context = context;
+ args.geometry = this;
+ args.report = report;
+
+ intersectorN.intersect(&args);
+ }
+
+ /*! Tests if single ray is occluded by the scene. */
+ __forceinline void occluded (Ray& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
+ {
+ assert(primID < size());
+ assert(intersectorN.occluded);
+
+ int mask = -1;
+ OccludedFunctionNArguments args;
+ args.valid = &mask;
+ args.geometryUserPtr = userPtr;
+ args.context = context->user;
+ args.ray = (RTCRayN*)&ray;
+ args.N = 1;
+ args.geomID = geomID;
+ args.primID = primID;
+ args.internal_context = context;
+ args.geometry = this;
+ args.report = report;
+
+ intersectorN.occluded(&args);
+ }
+
+ /*! Intersects a packet of K rays with the scene. */
+ template<int K>
+ __forceinline void intersect (const vbool<K>& valid, RayHitK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
+ {
+ assert(primID < size());
+ assert(intersectorN.intersect);
+
+ vint<K> mask = valid.mask32();
+ IntersectFunctionNArguments args;
+ args.valid = (int*)&mask;
+ args.geometryUserPtr = userPtr;
+ args.context = context->user;
+ args.rayhit = (RTCRayHitN*)&ray;
+ args.N = K;
+ args.geomID = geomID;
+ args.primID = primID;
+ args.internal_context = context;
+ args.geometry = this;
+ args.report = report;
+
+ intersectorN.intersect(&args);
+ }
+
+ /*! Tests if a packet of K rays is occluded by the scene. */
+ template<int K>
+ __forceinline void occluded (const vbool<K>& valid, RayK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
+ {
+ assert(primID < size());
+ assert(intersectorN.occluded);
+
+ vint<K> mask = valid.mask32();
+ OccludedFunctionNArguments args;
+ args.valid = (int*)&mask;
+ args.geometryUserPtr = userPtr;
+ args.context = context->user;
+ args.ray = (RTCRayN*)&ray;
+ args.N = K;
+ args.geomID = geomID;
+ args.primID = primID;
+ args.internal_context = context;
+ args.geometry = this;
+ args.report = report;
+
+ intersectorN.occluded(&args);
+ }
+
+ public:
+ RTCBoundsFunction boundsFunc;
+ IntersectorN intersectorN;
+ };
+
+#define DEFINE_SET_INTERSECTORN(symbol,intersector) \
+ AccelSet::IntersectorN symbol() { \
+ return AccelSet::IntersectorN(intersector::intersect, \
+ intersector::occluded, \
+ TOSTRING(isa) "::" TOSTRING(symbol)); \
+ }
+}
diff --git a/thirdparty/embree/kernels/common/alloc.cpp b/thirdparty/embree/kernels/common/alloc.cpp
new file mode 100644
index 0000000000..1a0e1aeed3
--- /dev/null
+++ b/thirdparty/embree/kernels/common/alloc.cpp
@@ -0,0 +1,79 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "alloc.h"
+#include "../../common/sys/thread.h"
+
+namespace embree
+{
+ __thread FastAllocator::ThreadLocal2* FastAllocator::thread_local_allocator2 = nullptr;
+ SpinLock FastAllocator::s_thread_local_allocators_lock;
+ std::vector<std::unique_ptr<FastAllocator::ThreadLocal2>> FastAllocator::s_thread_local_allocators;
+
+ struct fast_allocator_regression_test : public RegressionTest
+ {
+ BarrierSys barrier;
+ std::atomic<size_t> numFailed;
+ std::unique_ptr<FastAllocator> alloc;
+
+ fast_allocator_regression_test()
+ : RegressionTest("fast_allocator_regression_test"), numFailed(0)
+ {
+ registerRegressionTest(this);
+ }
+
+ static void thread_alloc(fast_allocator_regression_test* This)
+ {
+ FastAllocator::CachedAllocator threadalloc = This->alloc->getCachedAllocator();
+
+ size_t* ptrs[1000];
+ for (size_t j=0; j<1000; j++)
+ {
+ This->barrier.wait();
+ for (size_t i=0; i<1000; i++) {
+ ptrs[i] = (size_t*) threadalloc.malloc0(sizeof(size_t)+(i%32));
+ *ptrs[i] = size_t(threadalloc.talloc0) + i;
+ }
+ for (size_t i=0; i<1000; i++) {
+ if (*ptrs[i] != size_t(threadalloc.talloc0) + i)
+ This->numFailed++;
+ }
+ This->barrier.wait();
+ }
+ }
+
+ bool run ()
+ {
+ alloc = make_unique(new FastAllocator(nullptr,false));
+ numFailed.store(0);
+
+ size_t numThreads = getNumberOfLogicalThreads();
+ barrier.init(numThreads+1);
+
+ /* create threads */
+ std::vector<thread_t> threads;
+ for (size_t i=0; i<numThreads; i++)
+ threads.push_back(createThread((thread_func)thread_alloc,this));
+
+ /* run test */
+ for (size_t i=0; i<1000; i++)
+ {
+ alloc->reset();
+ barrier.wait();
+ barrier.wait();
+ }
+
+ /* destroy threads */
+ for (size_t i=0; i<numThreads; i++)
+ join(threads[i]);
+
+ alloc = nullptr;
+
+ return numFailed == 0;
+ }
+ };
+
+ fast_allocator_regression_test fast_allocator_regression;
+}
+
+
diff --git a/thirdparty/embree/kernels/common/alloc.h b/thirdparty/embree/kernels/common/alloc.h
new file mode 100644
index 0000000000..4458e35c24
--- /dev/null
+++ b/thirdparty/embree/kernels/common/alloc.h
@@ -0,0 +1,958 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "device.h"
+#include "scene.h"
+#include "primref.h"
+
+namespace embree
+{
+ class FastAllocator
+ {
+ /*! maximum supported alignment */
+ static const size_t maxAlignment = 64;
+
+ /*! maximum allocation size */
+
+ /* default settings */
+ //static const size_t defaultBlockSize = 4096;
+#define maxAllocationSize size_t(2*1024*1024-maxAlignment)
+
+ static const size_t MAX_THREAD_USED_BLOCK_SLOTS = 8;
+
+ public:
+
+ struct ThreadLocal2;
+ enum AllocationType { ALIGNED_MALLOC, OS_MALLOC, SHARED, ANY_TYPE };
+
+ /*! Per thread structure holding the current memory block. */
+ struct __aligned(64) ThreadLocal
+ {
+ ALIGNED_CLASS_(64);
+ public:
+
+ /*! Constructor for usage with ThreadLocalData */
+ __forceinline ThreadLocal (ThreadLocal2* parent)
+ : parent(parent), ptr(nullptr), cur(0), end(0), allocBlockSize(0), bytesUsed(0), bytesWasted(0) {}
+
+ /*! initialize allocator */
+ void init(FastAllocator* alloc)
+ {
+ ptr = nullptr;
+ cur = end = 0;
+ bytesUsed = 0;
+ bytesWasted = 0;
+ allocBlockSize = 0;
+ if (alloc) allocBlockSize = alloc->defaultBlockSize;
+ }
+
+ /* Allocate aligned memory from the threads memory block. */
+ __forceinline void* malloc(FastAllocator* alloc, size_t bytes, size_t align = 16)
+ {
+ /* bind the thread local allocator to the proper FastAllocator*/
+ parent->bind(alloc);
+
+ assert(align <= maxAlignment);
+ bytesUsed += bytes;
+
+ /* try to allocate in local block */
+ size_t ofs = (align - cur) & (align-1);
+ cur += bytes + ofs;
+ if (likely(cur <= end)) { bytesWasted += ofs; return &ptr[cur - bytes]; }
+ cur -= bytes + ofs;
+
+ /* if allocation is too large allocate with parent allocator */
+ if (4*bytes > allocBlockSize) {
+ return alloc->malloc(bytes,maxAlignment,false);
+ }
+
+ /* get new partial block if allocation failed */
+ size_t blockSize = allocBlockSize;
+ ptr = (char*) alloc->malloc(blockSize,maxAlignment,true);
+ bytesWasted += end-cur;
+ cur = 0; end = blockSize;
+
+ /* retry allocation */
+ ofs = (align - cur) & (align-1);
+ cur += bytes + ofs;
+ if (likely(cur <= end)) { bytesWasted += ofs; return &ptr[cur - bytes]; }
+ cur -= bytes + ofs;
+
+ /* get new full block if allocation failed */
+ blockSize = allocBlockSize;
+ ptr = (char*) alloc->malloc(blockSize,maxAlignment,false);
+ bytesWasted += end-cur;
+ cur = 0; end = blockSize;
+
+ /* retry allocation */
+ ofs = (align - cur) & (align-1);
+ cur += bytes + ofs;
+ if (likely(cur <= end)) { bytesWasted += ofs; return &ptr[cur - bytes]; }
+ cur -= bytes + ofs;
+
+ /* should never happen as large allocations get handled specially above */
+ assert(false);
+ return nullptr;
+ }
+
+
+ /*! returns amount of used bytes */
+ __forceinline size_t getUsedBytes() const { return bytesUsed; }
+
+ /*! returns amount of free bytes */
+ __forceinline size_t getFreeBytes() const { return end-cur; }
+
+ /*! returns amount of wasted bytes */
+ __forceinline size_t getWastedBytes() const { return bytesWasted; }
+
+ private:
+ ThreadLocal2* parent;
+ char* ptr; //!< pointer to memory block
+ size_t cur; //!< current location of the allocator
+ size_t end; //!< end of the memory block
+ size_t allocBlockSize; //!< block size for allocations
+ size_t bytesUsed; //!< number of total bytes allocated
+ size_t bytesWasted; //!< number of bytes wasted
+ };
+
+ /*! Two thread local structures. */
+ struct __aligned(64) ThreadLocal2
+ {
+ ALIGNED_CLASS_(64);
+ public:
+
+ __forceinline ThreadLocal2()
+ : alloc(nullptr), alloc0(this), alloc1(this) {}
+
+ /*! bind to fast allocator */
+ __forceinline void bind(FastAllocator* alloc_i)
+ {
+ assert(alloc_i);
+ if (alloc.load() == alloc_i) return;
+ Lock<SpinLock> lock(mutex);
+ //if (alloc.load() == alloc_i) return; // not required as only one thread calls bind
+ if (alloc.load()) {
+ alloc.load()->bytesUsed += alloc0.getUsedBytes() + alloc1.getUsedBytes();
+ alloc.load()->bytesFree += alloc0.getFreeBytes() + alloc1.getFreeBytes();
+ alloc.load()->bytesWasted += alloc0.getWastedBytes() + alloc1.getWastedBytes();
+ }
+ alloc0.init(alloc_i);
+ alloc1.init(alloc_i);
+ alloc.store(alloc_i);
+ alloc_i->join(this);
+ }
+
+ /*! unbind to fast allocator */
+ void unbind(FastAllocator* alloc_i)
+ {
+ assert(alloc_i);
+ if (alloc.load() != alloc_i) return;
+ Lock<SpinLock> lock(mutex);
+ if (alloc.load() != alloc_i) return; // required as a different thread calls unbind
+ alloc.load()->bytesUsed += alloc0.getUsedBytes() + alloc1.getUsedBytes();
+ alloc.load()->bytesFree += alloc0.getFreeBytes() + alloc1.getFreeBytes();
+ alloc.load()->bytesWasted += alloc0.getWastedBytes() + alloc1.getWastedBytes();
+ alloc0.init(nullptr);
+ alloc1.init(nullptr);
+ alloc.store(nullptr);
+ }
+
+ public:
+ SpinLock mutex; //!< required as unbind is called from other threads
+ std::atomic<FastAllocator*> alloc; //!< parent allocator
+ ThreadLocal alloc0;
+ ThreadLocal alloc1;
+ };
+
+ FastAllocator (Device* device, bool osAllocation)
+ : device(device), slotMask(0), usedBlocks(nullptr), freeBlocks(nullptr), use_single_mode(false), defaultBlockSize(PAGE_SIZE), estimatedSize(0),
+ growSize(PAGE_SIZE), maxGrowSize(maxAllocationSize), log2_grow_size_scale(0), bytesUsed(0), bytesFree(0), bytesWasted(0), atype(osAllocation ? OS_MALLOC : ALIGNED_MALLOC),
+ primrefarray(device,0)
+ {
+ for (size_t i=0; i<MAX_THREAD_USED_BLOCK_SLOTS; i++)
+ {
+ threadUsedBlocks[i] = nullptr;
+ threadBlocks[i] = nullptr;
+ assert(!slotMutex[i].isLocked());
+ }
+ }
+
+ ~FastAllocator () {
+ clear();
+ }
+
+ /*! returns the device attached to this allocator */
+ Device* getDevice() {
+ return device;
+ }
+
+ void share(mvector<PrimRef>& primrefarray_i) {
+ primrefarray = std::move(primrefarray_i);
+ }
+
+ void unshare(mvector<PrimRef>& primrefarray_o)
+ {
+ reset(); // this removes blocks that are allocated inside the shared primref array
+ primrefarray_o = std::move(primrefarray);
+ }
+
+ /*! returns first fast thread local allocator */
+ __forceinline ThreadLocal* _threadLocal() {
+ return &threadLocal2()->alloc0;
+ }
+
+ void setOSallocation(bool flag)
+ {
+ atype = flag ? OS_MALLOC : ALIGNED_MALLOC;
+ }
+
+ private:
+
+ /*! returns both fast thread local allocators */
+ __forceinline ThreadLocal2* threadLocal2()
+ {
+ ThreadLocal2* alloc = thread_local_allocator2;
+ if (alloc == nullptr) {
+ thread_local_allocator2 = alloc = new ThreadLocal2;
+ Lock<SpinLock> lock(s_thread_local_allocators_lock);
+ s_thread_local_allocators.push_back(make_unique(alloc));
+ }
+ return alloc;
+ }
+
+ public:
+
+ __forceinline void join(ThreadLocal2* alloc)
+ {
+ Lock<SpinLock> lock(thread_local_allocators_lock);
+ thread_local_allocators.push_back(alloc);
+ }
+
+ public:
+
+ struct CachedAllocator
+ {
+ __forceinline CachedAllocator(void* ptr)
+ : alloc(nullptr), talloc0(nullptr), talloc1(nullptr)
+ {
+ assert(ptr == nullptr);
+ }
+
+ __forceinline CachedAllocator(FastAllocator* alloc, ThreadLocal2* talloc)
+ : alloc(alloc), talloc0(&talloc->alloc0), talloc1(alloc->use_single_mode ? &talloc->alloc0 : &talloc->alloc1) {}
+
+ __forceinline operator bool () const {
+ return alloc != nullptr;
+ }
+
+ __forceinline void* operator() (size_t bytes, size_t align = 16) const {
+ return talloc0->malloc(alloc,bytes,align);
+ }
+
+ __forceinline void* malloc0 (size_t bytes, size_t align = 16) const {
+ return talloc0->malloc(alloc,bytes,align);
+ }
+
+ __forceinline void* malloc1 (size_t bytes, size_t align = 16) const {
+ return talloc1->malloc(alloc,bytes,align);
+ }
+
+ public:
+ FastAllocator* alloc;
+ ThreadLocal* talloc0;
+ ThreadLocal* talloc1;
+ };
+
+ __forceinline CachedAllocator getCachedAllocator() {
+ return CachedAllocator(this,threadLocal2());
+ }
+
+ /*! Builder interface to create thread local allocator */
+ struct Create
+ {
+ public:
+ __forceinline Create (FastAllocator* allocator) : allocator(allocator) {}
+ __forceinline CachedAllocator operator() () const { return allocator->getCachedAllocator(); }
+
+ private:
+ FastAllocator* allocator;
+ };
+
+ void internal_fix_used_blocks()
+ {
+ /* move thread local blocks to global block list */
+ for (size_t i = 0; i < MAX_THREAD_USED_BLOCK_SLOTS; i++)
+ {
+ while (threadBlocks[i].load() != nullptr) {
+ Block* nextUsedBlock = threadBlocks[i].load()->next;
+ threadBlocks[i].load()->next = usedBlocks.load();
+ usedBlocks = threadBlocks[i].load();
+ threadBlocks[i] = nextUsedBlock;
+ }
+ threadBlocks[i] = nullptr;
+ }
+ }
+
+ static const size_t threadLocalAllocOverhead = 20; //! 20 means 5% parallel allocation overhead through unfilled thread local blocks
+ static const size_t mainAllocOverheadStatic = 20; //! 20 means 5% allocation overhead through unfilled main alloc blocks
+ static const size_t mainAllocOverheadDynamic = 8; //! 20 means 12.5% allocation overhead through unfilled main alloc blocks
+
+ /* calculates a single threaded threshold for the builders such
+ * that for small scenes the overhead of partly allocated blocks
+ * per thread is low */
+ size_t fixSingleThreadThreshold(size_t branchingFactor, size_t defaultThreshold, size_t numPrimitives, size_t bytesEstimated)
+ {
+ if (numPrimitives == 0 || bytesEstimated == 0)
+ return defaultThreshold;
+
+ /* calculate block size in bytes to fulfill threadLocalAllocOverhead constraint */
+ const size_t single_mode_factor = use_single_mode ? 1 : 2;
+ const size_t threadCount = TaskScheduler::threadCount();
+ const size_t singleThreadBytes = single_mode_factor*threadLocalAllocOverhead*defaultBlockSize;
+
+ /* if we do not have to limit number of threads use optimal thresdhold */
+ if ( (bytesEstimated+(singleThreadBytes-1))/singleThreadBytes >= threadCount)
+ return defaultThreshold;
+
+ /* otherwise limit number of threads by calculating proper single thread threshold */
+ else {
+ double bytesPerPrimitive = double(bytesEstimated)/double(numPrimitives);
+ return size_t(ceil(branchingFactor*singleThreadBytes/bytesPerPrimitive));
+ }
+ }
+
+ __forceinline size_t alignSize(size_t i) {
+ return (i+127)/128*128;
+ }
+
+ /*! initializes the grow size */
+ __forceinline void initGrowSizeAndNumSlots(size_t bytesEstimated, bool fast)
+ {
+ /* we do not need single thread local allocator mode */
+ use_single_mode = false;
+
+ /* calculate growSize such that at most mainAllocationOverhead gets wasted when a block stays unused */
+ size_t mainAllocOverhead = fast ? mainAllocOverheadDynamic : mainAllocOverheadStatic;
+ size_t blockSize = alignSize(bytesEstimated/mainAllocOverhead);
+ growSize = maxGrowSize = clamp(blockSize,size_t(1024),maxAllocationSize);
+
+ /* if we reached the maxAllocationSize for growSize, we can
+ * increase the number of allocation slots by still guaranteeing
+ * the mainAllocationOverhead */
+ slotMask = 0x0;
+
+ if (MAX_THREAD_USED_BLOCK_SLOTS >= 2 && bytesEstimated > 2*mainAllocOverhead*growSize) slotMask = 0x1;
+ if (MAX_THREAD_USED_BLOCK_SLOTS >= 4 && bytesEstimated > 4*mainAllocOverhead*growSize) slotMask = 0x3;
+ if (MAX_THREAD_USED_BLOCK_SLOTS >= 8 && bytesEstimated > 8*mainAllocOverhead*growSize) slotMask = 0x7;
+ if (MAX_THREAD_USED_BLOCK_SLOTS >= 8 && bytesEstimated > 16*mainAllocOverhead*growSize) { growSize *= 2; } /* if the overhead is tiny, double the growSize */
+
+ /* set the thread local alloc block size */
+ size_t defaultBlockSizeSwitch = PAGE_SIZE+maxAlignment;
+
+ /* for sufficiently large scene we can increase the defaultBlockSize over the defaultBlockSizeSwitch size */
+#if 0 // we do not do this as a block size of 4160 if for some reason best for KNL
+ const size_t threadCount = TaskScheduler::threadCount();
+ const size_t single_mode_factor = use_single_mode ? 1 : 2;
+ const size_t singleThreadBytes = single_mode_factor*threadLocalAllocOverhead*defaultBlockSizeSwitch;
+ if (bytesEstimated+(singleThreadBytes-1))/singleThreadBytes >= threadCount)
+ defaultBlockSize = min(max(defaultBlockSizeSwitch,bytesEstimated/(single_mode_factor*threadLocalAllocOverhead*threadCount)),growSize);
+
+ /* otherwise we grow the defaultBlockSize up to defaultBlockSizeSwitch */
+ else
+#endif
+ defaultBlockSize = clamp(blockSize,size_t(1024),defaultBlockSizeSwitch);
+
+ if (bytesEstimated == 0) {
+ maxGrowSize = maxAllocationSize; // special mode if builder cannot estimate tree size
+ defaultBlockSize = defaultBlockSizeSwitch;
+ }
+ log2_grow_size_scale = 0;
+
+ if (device->alloc_main_block_size != 0) growSize = device->alloc_main_block_size;
+ if (device->alloc_num_main_slots >= 1 ) slotMask = 0x0;
+ if (device->alloc_num_main_slots >= 2 ) slotMask = 0x1;
+ if (device->alloc_num_main_slots >= 4 ) slotMask = 0x3;
+ if (device->alloc_num_main_slots >= 8 ) slotMask = 0x7;
+ if (device->alloc_thread_block_size != 0) defaultBlockSize = device->alloc_thread_block_size;
+ if (device->alloc_single_thread_alloc != -1) use_single_mode = device->alloc_single_thread_alloc;
+ }
+
+ /*! initializes the allocator */
+ void init(size_t bytesAllocate, size_t bytesReserve, size_t bytesEstimate)
+ {
+ internal_fix_used_blocks();
+ /* distribute the allocation to multiple thread block slots */
+ slotMask = MAX_THREAD_USED_BLOCK_SLOTS-1; // FIXME: remove
+ if (usedBlocks.load() || freeBlocks.load()) { reset(); return; }
+ if (bytesReserve == 0) bytesReserve = bytesAllocate;
+ freeBlocks = Block::create(device,bytesAllocate,bytesReserve,nullptr,atype);
+ estimatedSize = bytesEstimate;
+ initGrowSizeAndNumSlots(bytesEstimate,true);
+ }
+
+ /*! initializes the allocator */
+ void init_estimate(size_t bytesEstimate)
+ {
+ internal_fix_used_blocks();
+ if (usedBlocks.load() || freeBlocks.load()) { reset(); return; }
+ /* single allocator mode ? */
+ estimatedSize = bytesEstimate;
+ //initGrowSizeAndNumSlots(bytesEstimate,false);
+ initGrowSizeAndNumSlots(bytesEstimate,false);
+
+ }
+
+ /*! frees state not required after build */
+ __forceinline void cleanup()
+ {
+ internal_fix_used_blocks();
+
+ /* unbind all thread local allocators */
+ for (auto alloc : thread_local_allocators) alloc->unbind(this);
+ thread_local_allocators.clear();
+ }
+
+ /*! resets the allocator, memory blocks get reused */
+ void reset ()
+ {
+ internal_fix_used_blocks();
+
+ bytesUsed.store(0);
+ bytesFree.store(0);
+ bytesWasted.store(0);
+
+ /* reset all used blocks and move them to begin of free block list */
+ while (usedBlocks.load() != nullptr) {
+ usedBlocks.load()->reset_block();
+ Block* nextUsedBlock = usedBlocks.load()->next;
+ usedBlocks.load()->next = freeBlocks.load();
+ freeBlocks = usedBlocks.load();
+ usedBlocks = nextUsedBlock;
+ }
+
+ /* remove all shared blocks as they are re-added during build */
+ freeBlocks.store(Block::remove_shared_blocks(freeBlocks.load()));
+
+ for (size_t i=0; i<MAX_THREAD_USED_BLOCK_SLOTS; i++)
+ {
+ threadUsedBlocks[i] = nullptr;
+ threadBlocks[i] = nullptr;
+ }
+
+ /* unbind all thread local allocators */
+ for (auto alloc : thread_local_allocators) alloc->unbind(this);
+ thread_local_allocators.clear();
+ }
+
+ /*! frees all allocated memory */
+ __forceinline void clear()
+ {
+ cleanup();
+ bytesUsed.store(0);
+ bytesFree.store(0);
+ bytesWasted.store(0);
+ if (usedBlocks.load() != nullptr) usedBlocks.load()->clear_list(device); usedBlocks = nullptr;
+ if (freeBlocks.load() != nullptr) freeBlocks.load()->clear_list(device); freeBlocks = nullptr;
+ for (size_t i=0; i<MAX_THREAD_USED_BLOCK_SLOTS; i++) {
+ threadUsedBlocks[i] = nullptr;
+ threadBlocks[i] = nullptr;
+ }
+ primrefarray.clear();
+ }
+
+ __forceinline size_t incGrowSizeScale()
+ {
+ size_t scale = log2_grow_size_scale.fetch_add(1)+1;
+ return size_t(1) << min(size_t(16),scale);
+ }
+
+ /*! thread safe allocation of memory */
+ void* malloc(size_t& bytes, size_t align, bool partial)
+ {
+ assert(align <= maxAlignment);
+
+ while (true)
+ {
+ /* allocate using current block */
+ size_t threadID = TaskScheduler::threadID();
+ size_t slot = threadID & slotMask;
+ Block* myUsedBlocks = threadUsedBlocks[slot];
+ if (myUsedBlocks) {
+ void* ptr = myUsedBlocks->malloc(device,bytes,align,partial);
+ if (ptr) return ptr;
+ }
+
+ /* throw error if allocation is too large */
+ if (bytes > maxAllocationSize)
+ throw_RTCError(RTC_ERROR_UNKNOWN,"allocation is too large");
+
+ /* parallel block creation in case of no freeBlocks, avoids single global mutex */
+ if (likely(freeBlocks.load() == nullptr))
+ {
+ Lock<SpinLock> lock(slotMutex[slot]);
+ if (myUsedBlocks == threadUsedBlocks[slot]) {
+ const size_t alignedBytes = (bytes+(align-1)) & ~(align-1);
+ const size_t allocSize = max(min(growSize,maxGrowSize),alignedBytes);
+ assert(allocSize >= bytes);
+ threadBlocks[slot] = threadUsedBlocks[slot] = Block::create(device,allocSize,allocSize,threadBlocks[slot],atype); // FIXME: a large allocation might throw away a block here!
+ // FIXME: a direct allocation should allocate inside the block here, and not in the next loop! a different thread could do some allocation and make the large allocation fail.
+ }
+ continue;
+ }
+
+ /* if this fails allocate new block */
+ {
+ Lock<SpinLock> lock(mutex);
+ if (myUsedBlocks == threadUsedBlocks[slot])
+ {
+ if (freeBlocks.load() != nullptr) {
+ Block* nextFreeBlock = freeBlocks.load()->next;
+ freeBlocks.load()->next = usedBlocks;
+ __memory_barrier();
+ usedBlocks = freeBlocks.load();
+ threadUsedBlocks[slot] = freeBlocks.load();
+ freeBlocks = nextFreeBlock;
+ } else {
+ const size_t allocSize = min(growSize*incGrowSizeScale(),maxGrowSize);
+ usedBlocks = threadUsedBlocks[slot] = Block::create(device,allocSize,allocSize,usedBlocks,atype); // FIXME: a large allocation should get delivered directly, like above!
+ }
+ }
+ }
+ }
+ }
+
+ /*! add new block */
+ void addBlock(void* ptr, ssize_t bytes)
+ {
+ Lock<SpinLock> lock(mutex);
+ const size_t sizeof_Header = offsetof(Block,data[0]);
+ void* aptr = (void*) ((((size_t)ptr)+maxAlignment-1) & ~(maxAlignment-1));
+ size_t ofs = (size_t) aptr - (size_t) ptr;
+ bytes -= ofs;
+ if (bytes < 4096) return; // ignore empty or very small blocks
+ freeBlocks = new (aptr) Block(SHARED,bytes-sizeof_Header,bytes-sizeof_Header,freeBlocks,ofs);
+ }
+
+ /* special allocation only used from morton builder only a single time for each build */
+ void* specialAlloc(size_t bytes)
+ {
+ assert(freeBlocks.load() != nullptr && freeBlocks.load()->getBlockAllocatedBytes() >= bytes);
+ return freeBlocks.load()->ptr();
+ }
+
+ struct Statistics
+ {
+ Statistics ()
+ : bytesUsed(0), bytesFree(0), bytesWasted(0) {}
+
+ Statistics (size_t bytesUsed, size_t bytesFree, size_t bytesWasted)
+ : bytesUsed(bytesUsed), bytesFree(bytesFree), bytesWasted(bytesWasted) {}
+
+ Statistics (FastAllocator* alloc, AllocationType atype, bool huge_pages = false)
+ : bytesUsed(0), bytesFree(0), bytesWasted(0)
+ {
+ Block* usedBlocks = alloc->usedBlocks.load();
+ Block* freeBlocks = alloc->freeBlocks.load();
+ if (usedBlocks) bytesUsed += usedBlocks->getUsedBytes(atype,huge_pages);
+ if (freeBlocks) bytesFree += freeBlocks->getAllocatedBytes(atype,huge_pages);
+ if (usedBlocks) bytesFree += usedBlocks->getFreeBytes(atype,huge_pages);
+ if (freeBlocks) bytesWasted += freeBlocks->getWastedBytes(atype,huge_pages);
+ if (usedBlocks) bytesWasted += usedBlocks->getWastedBytes(atype,huge_pages);
+ }
+
+ std::string str(size_t numPrimitives)
+ {
+ std::stringstream str;
+ str.setf(std::ios::fixed, std::ios::floatfield);
+ str << "used = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesUsed << " MB, "
+ << "free = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesFree << " MB, "
+ << "wasted = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesWasted << " MB, "
+ << "total = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesAllocatedTotal() << " MB, "
+ << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytesAllocatedTotal())/double(numPrimitives);
+ return str.str();
+ }
+
+ friend Statistics operator+ ( const Statistics& a, const Statistics& b)
+ {
+ return Statistics(a.bytesUsed+b.bytesUsed,
+ a.bytesFree+b.bytesFree,
+ a.bytesWasted+b.bytesWasted);
+ }
+
+ size_t bytesAllocatedTotal() const {
+ return bytesUsed + bytesFree + bytesWasted;
+ }
+
+ public:
+ size_t bytesUsed;
+ size_t bytesFree;
+ size_t bytesWasted;
+ };
+
+ Statistics getStatistics(AllocationType atype, bool huge_pages = false) {
+ return Statistics(this,atype,huge_pages);
+ }
+
+ size_t getUsedBytes() {
+ return bytesUsed;
+ }
+
+ size_t getWastedBytes() {
+ return bytesWasted;
+ }
+
+ struct AllStatistics
+ {
+ AllStatistics (FastAllocator* alloc)
+
+ : bytesUsed(alloc->bytesUsed),
+ bytesFree(alloc->bytesFree),
+ bytesWasted(alloc->bytesWasted),
+ stat_all(alloc,ANY_TYPE),
+ stat_malloc(alloc,ALIGNED_MALLOC),
+ stat_4K(alloc,OS_MALLOC,false),
+ stat_2M(alloc,OS_MALLOC,true),
+ stat_shared(alloc,SHARED) {}
+
+ AllStatistics (size_t bytesUsed,
+ size_t bytesFree,
+ size_t bytesWasted,
+ Statistics stat_all,
+ Statistics stat_malloc,
+ Statistics stat_4K,
+ Statistics stat_2M,
+ Statistics stat_shared)
+
+ : bytesUsed(bytesUsed),
+ bytesFree(bytesFree),
+ bytesWasted(bytesWasted),
+ stat_all(stat_all),
+ stat_malloc(stat_malloc),
+ stat_4K(stat_4K),
+ stat_2M(stat_2M),
+ stat_shared(stat_shared) {}
+
+ friend AllStatistics operator+ (const AllStatistics& a, const AllStatistics& b)
+ {
+ return AllStatistics(a.bytesUsed+b.bytesUsed,
+ a.bytesFree+b.bytesFree,
+ a.bytesWasted+b.bytesWasted,
+ a.stat_all + b.stat_all,
+ a.stat_malloc + b.stat_malloc,
+ a.stat_4K + b.stat_4K,
+ a.stat_2M + b.stat_2M,
+ a.stat_shared + b.stat_shared);
+ }
+
+ void print(size_t numPrimitives)
+ {
+ std::stringstream str0;
+ str0.setf(std::ios::fixed, std::ios::floatfield);
+ str0 << " alloc : "
+ << "used = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesUsed << " MB, "
+ << " "
+ << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytesUsed)/double(numPrimitives);
+ std::cout << str0.str() << std::endl;
+
+ std::stringstream str1;
+ str1.setf(std::ios::fixed, std::ios::floatfield);
+ str1 << " alloc : "
+ << "used = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesUsed << " MB, "
+ << "free = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesFree << " MB, "
+ << "wasted = " << std::setw(7) << std::setprecision(3) << 1E-6f*bytesWasted << " MB, "
+ << "total = " << std::setw(7) << std::setprecision(3) << 1E-6f*(bytesUsed+bytesFree+bytesWasted) << " MB, "
+ << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytesUsed+bytesFree+bytesWasted)/double(numPrimitives);
+ std::cout << str1.str() << std::endl;
+
+ std::cout << " total : " << stat_all.str(numPrimitives) << std::endl;
+ std::cout << " 4K : " << stat_4K.str(numPrimitives) << std::endl;
+ std::cout << " 2M : " << stat_2M.str(numPrimitives) << std::endl;
+ std::cout << " malloc: " << stat_malloc.str(numPrimitives) << std::endl;
+ std::cout << " shared: " << stat_shared.str(numPrimitives) << std::endl;
+ }
+
+ private:
+ size_t bytesUsed;
+ size_t bytesFree;
+ size_t bytesWasted;
+ Statistics stat_all;
+ Statistics stat_malloc;
+ Statistics stat_4K;
+ Statistics stat_2M;
+ Statistics stat_shared;
+ };
+
+ void print_blocks()
+ {
+ std::cout << " estimatedSize = " << estimatedSize << ", slotMask = " << slotMask << ", use_single_mode = " << use_single_mode << ", maxGrowSize = " << maxGrowSize << ", defaultBlockSize = " << defaultBlockSize << std::endl;
+
+ std::cout << " used blocks = ";
+ if (usedBlocks.load() != nullptr) usedBlocks.load()->print_list();
+ std::cout << "[END]" << std::endl;
+
+ std::cout << " free blocks = ";
+ if (freeBlocks.load() != nullptr) freeBlocks.load()->print_list();
+ std::cout << "[END]" << std::endl;
+ }
+
+ private:
+
+ struct Block
+ {
+ static Block* create(MemoryMonitorInterface* device, size_t bytesAllocate, size_t bytesReserve, Block* next, AllocationType atype)
+ {
+ /* We avoid using os_malloc for small blocks as this could
+ * cause a risk of fragmenting the virtual address space and
+ * reach the limit of vm.max_map_count = 65k under Linux. */
+ if (atype == OS_MALLOC && bytesAllocate < maxAllocationSize)
+ atype = ALIGNED_MALLOC;
+
+ /* we need to additionally allocate some header */
+ const size_t sizeof_Header = offsetof(Block,data[0]);
+ bytesAllocate = sizeof_Header+bytesAllocate;
+ bytesReserve = sizeof_Header+bytesReserve;
+
+ /* consume full 4k pages with using os_malloc */
+ if (atype == OS_MALLOC) {
+ bytesAllocate = ((bytesAllocate+PAGE_SIZE-1) & ~(PAGE_SIZE-1));
+ bytesReserve = ((bytesReserve +PAGE_SIZE-1) & ~(PAGE_SIZE-1));
+ }
+
+ /* either use alignedMalloc or os_malloc */
+ void *ptr = nullptr;
+ if (atype == ALIGNED_MALLOC)
+ {
+ /* special handling for default block size */
+ if (bytesAllocate == (2*PAGE_SIZE_2M))
+ {
+ const size_t alignment = maxAlignment;
+ if (device) device->memoryMonitor(bytesAllocate+alignment,false);
+ ptr = alignedMalloc(bytesAllocate,alignment);
+
+ /* give hint to transparently convert these pages to 2MB pages */
+ const size_t ptr_aligned_begin = ((size_t)ptr) & ~size_t(PAGE_SIZE_2M-1);
+ os_advise((void*)(ptr_aligned_begin + 0),PAGE_SIZE_2M); // may fail if no memory mapped before block
+ os_advise((void*)(ptr_aligned_begin + 1*PAGE_SIZE_2M),PAGE_SIZE_2M);
+ os_advise((void*)(ptr_aligned_begin + 2*PAGE_SIZE_2M),PAGE_SIZE_2M); // may fail if no memory mapped after block
+
+ return new (ptr) Block(ALIGNED_MALLOC,bytesAllocate-sizeof_Header,bytesAllocate-sizeof_Header,next,alignment);
+ }
+ else
+ {
+ const size_t alignment = maxAlignment;
+ if (device) device->memoryMonitor(bytesAllocate+alignment,false);
+ ptr = alignedMalloc(bytesAllocate,alignment);
+ return new (ptr) Block(ALIGNED_MALLOC,bytesAllocate-sizeof_Header,bytesAllocate-sizeof_Header,next,alignment);
+ }
+ }
+ else if (atype == OS_MALLOC)
+ {
+ if (device) device->memoryMonitor(bytesAllocate,false);
+ bool huge_pages; ptr = os_malloc(bytesReserve,huge_pages);
+ return new (ptr) Block(OS_MALLOC,bytesAllocate-sizeof_Header,bytesReserve-sizeof_Header,next,0,huge_pages);
+ }
+ else
+ assert(false);
+
+ return NULL;
+ }
+
+ Block (AllocationType atype, size_t bytesAllocate, size_t bytesReserve, Block* next, size_t wasted, bool huge_pages = false)
+ : cur(0), allocEnd(bytesAllocate), reserveEnd(bytesReserve), next(next), wasted(wasted), atype(atype), huge_pages(huge_pages)
+ {
+ assert((((size_t)&data[0]) & (maxAlignment-1)) == 0);
+ }
+
+ static Block* remove_shared_blocks(Block* head)
+ {
+ Block** prev_next = &head;
+ for (Block* block = head; block; block = block->next) {
+ if (block->atype == SHARED) *prev_next = block->next;
+ else prev_next = &block->next;
+ }
+ return head;
+ }
+
+ void clear_list(MemoryMonitorInterface* device)
+ {
+ Block* block = this;
+ while (block) {
+ Block* next = block->next;
+ block->clear_block(device);
+ block = next;
+ }
+ }
+
+ void clear_block (MemoryMonitorInterface* device)
+ {
+ const size_t sizeof_Header = offsetof(Block,data[0]);
+ const ssize_t sizeof_Alloced = wasted+sizeof_Header+getBlockAllocatedBytes();
+
+ if (atype == ALIGNED_MALLOC) {
+ alignedFree(this);
+ if (device) device->memoryMonitor(-sizeof_Alloced,true);
+ }
+
+ else if (atype == OS_MALLOC) {
+ size_t sizeof_This = sizeof_Header+reserveEnd;
+ os_free(this,sizeof_This,huge_pages);
+ if (device) device->memoryMonitor(-sizeof_Alloced,true);
+ }
+
+ else /* if (atype == SHARED) */ {
+ }
+ }
+
+ void* malloc(MemoryMonitorInterface* device, size_t& bytes_in, size_t align, bool partial)
+ {
+ size_t bytes = bytes_in;
+ assert(align <= maxAlignment);
+ bytes = (bytes+(align-1)) & ~(align-1);
+ if (unlikely(cur+bytes > reserveEnd && !partial)) return nullptr;
+ const size_t i = cur.fetch_add(bytes);
+ if (unlikely(i+bytes > reserveEnd && !partial)) return nullptr;
+ if (unlikely(i > reserveEnd)) return nullptr;
+ bytes_in = bytes = min(bytes,reserveEnd-i);
+
+ if (i+bytes > allocEnd) {
+ if (device) device->memoryMonitor(i+bytes-max(i,allocEnd),true);
+ }
+ return &data[i];
+ }
+
+ void* ptr() {
+ return &data[cur];
+ }
+
+ void reset_block ()
+ {
+ allocEnd = max(allocEnd,(size_t)cur);
+ cur = 0;
+ }
+
+ size_t getBlockUsedBytes() const {
+ return min(size_t(cur),reserveEnd);
+ }
+
+ size_t getBlockFreeBytes() const {
+ return getBlockAllocatedBytes() - getBlockUsedBytes();
+ }
+
+ size_t getBlockAllocatedBytes() const {
+ return min(max(allocEnd,size_t(cur)),reserveEnd);
+ }
+
+ size_t getBlockWastedBytes() const {
+ const size_t sizeof_Header = offsetof(Block,data[0]);
+ return sizeof_Header + wasted;
+ }
+
+ size_t getBlockReservedBytes() const {
+ return reserveEnd;
+ }
+
+ bool hasType(AllocationType atype_i, bool huge_pages_i) const
+ {
+ if (atype_i == ANY_TYPE ) return true;
+ else if (atype == OS_MALLOC) return atype_i == atype && huge_pages_i == huge_pages;
+ else return atype_i == atype;
+ }
+
+ size_t getUsedBytes(AllocationType atype, bool huge_pages = false) const {
+ size_t bytes = 0;
+ for (const Block* block = this; block; block = block->next) {
+ if (!block->hasType(atype,huge_pages)) continue;
+ bytes += block->getBlockUsedBytes();
+ }
+ return bytes;
+ }
+
+ size_t getFreeBytes(AllocationType atype, bool huge_pages = false) const {
+ size_t bytes = 0;
+ for (const Block* block = this; block; block = block->next) {
+ if (!block->hasType(atype,huge_pages)) continue;
+ bytes += block->getBlockFreeBytes();
+ }
+ return bytes;
+ }
+
+ size_t getWastedBytes(AllocationType atype, bool huge_pages = false) const {
+ size_t bytes = 0;
+ for (const Block* block = this; block; block = block->next) {
+ if (!block->hasType(atype,huge_pages)) continue;
+ bytes += block->getBlockWastedBytes();
+ }
+ return bytes;
+ }
+
+ size_t getAllocatedBytes(AllocationType atype, bool huge_pages = false) const {
+ size_t bytes = 0;
+ for (const Block* block = this; block; block = block->next) {
+ if (!block->hasType(atype,huge_pages)) continue;
+ bytes += block->getBlockAllocatedBytes();
+ }
+ return bytes;
+ }
+
+ void print_list ()
+ {
+ for (const Block* block = this; block; block = block->next)
+ block->print_block();
+ }
+
+ void print_block() const
+ {
+ if (atype == ALIGNED_MALLOC) std::cout << "A";
+ else if (atype == OS_MALLOC) std::cout << "O";
+ else if (atype == SHARED) std::cout << "S";
+ if (huge_pages) std::cout << "H";
+ size_t bytesUsed = getBlockUsedBytes();
+ size_t bytesFree = getBlockFreeBytes();
+ size_t bytesWasted = getBlockWastedBytes();
+ std::cout << "[" << bytesUsed << ", " << bytesFree << ", " << bytesWasted << "] ";
+ }
+
+ public:
+ std::atomic<size_t> cur; //!< current location of the allocator
+ std::atomic<size_t> allocEnd; //!< end of the allocated memory region
+ std::atomic<size_t> reserveEnd; //!< end of the reserved memory region
+ Block* next; //!< pointer to next block in list
+ size_t wasted; //!< amount of memory wasted through block alignment
+ AllocationType atype; //!< allocation mode of the block
+ bool huge_pages; //!< whether the block uses huge pages
+ char align[maxAlignment-5*sizeof(size_t)-sizeof(AllocationType)-sizeof(bool)]; //!< align data to maxAlignment
+ char data[1]; //!< here starts memory to use for allocations
+ };
+
+ private:
+ Device* device;
+ SpinLock mutex;
+ size_t slotMask;
+ std::atomic<Block*> threadUsedBlocks[MAX_THREAD_USED_BLOCK_SLOTS];
+ std::atomic<Block*> usedBlocks;
+ std::atomic<Block*> freeBlocks;
+
+ std::atomic<Block*> threadBlocks[MAX_THREAD_USED_BLOCK_SLOTS];
+ SpinLock slotMutex[MAX_THREAD_USED_BLOCK_SLOTS];
+
+ bool use_single_mode;
+ size_t defaultBlockSize;
+ size_t estimatedSize;
+ size_t growSize;
+ size_t maxGrowSize;
+ std::atomic<size_t> log2_grow_size_scale; //!< log2 of scaling factor for grow size // FIXME: remove
+ std::atomic<size_t> bytesUsed;
+ std::atomic<size_t> bytesFree;
+ std::atomic<size_t> bytesWasted;
+ static __thread ThreadLocal2* thread_local_allocator2;
+ static SpinLock s_thread_local_allocators_lock;
+ static std::vector<std::unique_ptr<ThreadLocal2>> s_thread_local_allocators;
+ SpinLock thread_local_allocators_lock;
+ std::vector<ThreadLocal2*> thread_local_allocators;
+ AllocationType atype;
+ mvector<PrimRef> primrefarray; //!< primrefarray used to allocate nodes
+ };
+}
diff --git a/thirdparty/embree/kernels/common/buffer.h b/thirdparty/embree/kernels/common/buffer.h
new file mode 100644
index 0000000000..793012c04d
--- /dev/null
+++ b/thirdparty/embree/kernels/common/buffer.h
@@ -0,0 +1,263 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "device.h"
+
+namespace embree
+{
+ /*! Implements an API data buffer object. This class may or may not own the data. */
+ class Buffer : public RefCount
+ {
+ public:
+ /*! Buffer construction */
+ Buffer()
+ : device(nullptr), ptr(nullptr), numBytes(0), shared(false) {}
+
+ /*! Buffer construction */
+ Buffer(Device* device, size_t numBytes_in, void* ptr_in = nullptr)
+ : device(device), numBytes(numBytes_in)
+ {
+ device->refInc();
+
+ if (ptr_in)
+ {
+ shared = true;
+ ptr = (char*)ptr_in;
+ }
+ else
+ {
+ shared = false;
+ alloc();
+ }
+ }
+
+ /*! Buffer destruction */
+ ~Buffer() {
+ free();
+ device->refDec();
+ }
+
+ /*! this class is not copyable */
+ private:
+ Buffer(const Buffer& other) DELETED; // do not implement
+ Buffer& operator =(const Buffer& other) DELETED; // do not implement
+
+ public:
+ /* inits and allocates the buffer */
+ void create(Device* device_in, size_t numBytes_in)
+ {
+ init(device_in, numBytes_in);
+ alloc();
+ }
+
+ /* inits the buffer */
+ void init(Device* device_in, size_t numBytes_in)
+ {
+ free();
+ device = device_in;
+ ptr = nullptr;
+ numBytes = numBytes_in;
+ shared = false;
+ }
+
+ /*! sets shared buffer */
+ void set(Device* device_in, void* ptr_in, size_t numBytes_in)
+ {
+ free();
+ device = device_in;
+ ptr = (char*)ptr_in;
+ if (numBytes_in != (size_t)-1)
+ numBytes = numBytes_in;
+ shared = true;
+ }
+
+ /*! allocated buffer */
+ void alloc()
+ {
+ if (device)
+ device->memoryMonitor(this->bytes(), false);
+ size_t b = (this->bytes()+15) & ssize_t(-16);
+ ptr = (char*)alignedMalloc(b,16);
+ }
+
+ /*! frees the buffer */
+ void free()
+ {
+ if (shared) return;
+ alignedFree(ptr);
+ if (device)
+ device->memoryMonitor(-ssize_t(this->bytes()), true);
+ ptr = nullptr;
+ }
+
+ /*! gets buffer pointer */
+ void* data()
+ {
+ /* report error if buffer is not existing */
+ if (!device)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer specified");
+
+ /* return buffer */
+ return ptr;
+ }
+
+ /*! returns pointer to first element */
+ __forceinline char* getPtr() const {
+ return ptr;
+ }
+
+ /*! returns the number of bytes of the buffer */
+ __forceinline size_t bytes() const {
+ return numBytes;
+ }
+
+ /*! returns true of the buffer is not empty */
+ __forceinline operator bool() const {
+ return ptr;
+ }
+
+ public:
+ Device* device; //!< device to report memory usage to
+ char* ptr; //!< pointer to buffer data
+ size_t numBytes; //!< number of bytes in the buffer
+ bool shared; //!< set if memory is shared with application
+ };
+
+ /*! An untyped contiguous range of a buffer. This class does not own the buffer content. */
+ class RawBufferView
+ {
+ public:
+ /*! Buffer construction */
+ RawBufferView()
+ : ptr_ofs(nullptr), stride(0), num(0), format(RTC_FORMAT_UNDEFINED), modCounter(1), modified(true), userData(0) {}
+
+ public:
+ /*! sets the buffer view */
+ void set(const Ref<Buffer>& buffer_in, size_t offset_in, size_t stride_in, size_t num_in, RTCFormat format_in)
+ {
+ if ((offset_in + stride_in * num_in) > (stride_in * buffer_in->numBytes))
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "buffer range out of bounds");
+
+ ptr_ofs = buffer_in->ptr + offset_in;
+ stride = stride_in;
+ num = num_in;
+ format = format_in;
+ modCounter++;
+ modified = true;
+ buffer = buffer_in;
+ }
+
+ /*! returns pointer to the first element */
+ __forceinline char* getPtr() const {
+ return ptr_ofs;
+ }
+
+ /*! returns pointer to the i'th element */
+ __forceinline char* getPtr(size_t i) const
+ {
+ assert(i<num);
+ return ptr_ofs + i*stride;
+ }
+
+ /*! returns the number of elements of the buffer */
+ __forceinline size_t size() const {
+ return num;
+ }
+
+ /*! returns the number of bytes of the buffer */
+ __forceinline size_t bytes() const {
+ return num*stride;
+ }
+
+ /*! returns the buffer stride */
+ __forceinline unsigned getStride() const
+ {
+ assert(stride <= unsigned(inf));
+ return unsigned(stride);
+ }
+
+ /*! return the buffer format */
+ __forceinline RTCFormat getFormat() const {
+ return format;
+ }
+
+ /*! mark buffer as modified or unmodified */
+ __forceinline void setModified() {
+ modCounter++;
+ modified = true;
+ }
+
+ /*! mark buffer as modified or unmodified */
+ __forceinline bool isModified(unsigned int otherModCounter) const {
+ return modCounter > otherModCounter;
+ }
+
+ /*! mark buffer as modified or unmodified */
+ __forceinline bool isLocalModified() const {
+ return modified;
+ }
+
+ /*! clear local modified flag */
+ __forceinline void clearLocalModified() {
+ modified = false;
+ }
+
+ /*! returns true of the buffer is not empty */
+ __forceinline operator bool() const {
+ return ptr_ofs;
+ }
+
+ /*! checks padding to 16 byte check, fails hard */
+ __forceinline void checkPadding16() const
+ {
+ if (ptr_ofs && num)
+ volatile int MAYBE_UNUSED w = *((int*)getPtr(size()-1)+3); // FIXME: is failing hard avoidable?
+ }
+
+ public:
+ char* ptr_ofs; //!< base pointer plus offset
+ size_t stride; //!< stride of the buffer in bytes
+ size_t num; //!< number of elements in the buffer
+ RTCFormat format; //!< format of the buffer
+ unsigned int modCounter; //!< version ID of this buffer
+ bool modified; //!< local modified data
+ int userData; //!< special data
+ Ref<Buffer> buffer; //!< reference to the parent buffer
+ };
+
+ /*! A typed contiguous range of a buffer. This class does not own the buffer content. */
+ template<typename T>
+ class BufferView : public RawBufferView
+ {
+ public:
+ typedef T value_type;
+
+ /*! access to the ith element of the buffer */
+ __forceinline T& operator [](size_t i) { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
+ __forceinline const T& operator [](size_t i) const { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
+ };
+
+ template<>
+ class BufferView<Vec3fa> : public RawBufferView
+ {
+ public:
+ typedef Vec3fa value_type;
+
+ /*! access to the ith element of the buffer */
+ __forceinline const Vec3fa operator [](size_t i) const
+ {
+ assert(i<num);
+ return Vec3fa(vfloat4::loadu((float*)(ptr_ofs + i*stride)));
+ }
+
+ /*! writes the i'th element */
+ __forceinline void store(size_t i, const Vec3fa& v)
+ {
+ assert(i<num);
+ vfloat4::storeu((float*)(ptr_ofs + i*stride), (vfloat4)v);
+ }
+ };
+}
diff --git a/thirdparty/embree/kernels/common/builder.h b/thirdparty/embree/kernels/common/builder.h
new file mode 100644
index 0000000000..07fe7b069b
--- /dev/null
+++ b/thirdparty/embree/kernels/common/builder.h
@@ -0,0 +1,60 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "accel.h"
+
+namespace embree
+{
+#define MODE_HIGH_QUALITY (1<<8)
+
+ /*! virtual interface for all hierarchy builders */
+ class Builder : public RefCount {
+ public:
+
+ static const size_t DEFAULT_SINGLE_THREAD_THRESHOLD = 1024;
+
+ /*! initiates the hierarchy builder */
+ virtual void build() = 0;
+
+ /*! notifies the builder about the deletion of some geometry */
+ virtual void deleteGeometry(size_t geomID) {};
+
+ /*! clears internal builder state */
+ virtual void clear() = 0;
+ };
+
+ /*! virtual interface for progress monitor class */
+ struct BuildProgressMonitor {
+ virtual void operator() (size_t dn) const = 0;
+ };
+
+ /*! build the progress monitor interface from a closure */
+ template<typename Closure>
+ struct ProgressMonitorClosure : BuildProgressMonitor
+ {
+ public:
+ ProgressMonitorClosure (const Closure& closure) : closure(closure) {}
+ void operator() (size_t dn) const { closure(dn); }
+ private:
+ const Closure closure;
+ };
+ template<typename Closure> __forceinline const ProgressMonitorClosure<Closure> BuildProgressMonitorFromClosure(const Closure& closure) {
+ return ProgressMonitorClosure<Closure>(closure);
+ }
+
+ struct LineSegments;
+ struct TriangleMesh;
+ struct QuadMesh;
+ struct UserGeometry;
+
+ class Scene;
+
+ typedef void (*createLineSegmentsAccelTy)(Scene* scene, LineSegments* mesh, AccelData*& accel, Builder*& builder);
+ typedef void (*createTriangleMeshAccelTy)(Scene* scene, unsigned int geomID, AccelData*& accel, Builder*& builder);
+ typedef void (*createQuadMeshAccelTy)(Scene* scene, unsigned int geomID, AccelData*& accel, Builder*& builder);
+ typedef void (*createUserGeometryAccelTy)(Scene* scene, unsigned int geomID, AccelData*& accel, Builder*& builder);
+
+}
diff --git a/thirdparty/embree/kernels/common/context.h b/thirdparty/embree/kernels/common/context.h
new file mode 100644
index 0000000000..ccd88bdeac
--- /dev/null
+++ b/thirdparty/embree/kernels/common/context.h
@@ -0,0 +1,131 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "rtcore.h"
+#include "point_query.h"
+
+namespace embree
+{
+ class Scene;
+
+ struct IntersectContext
+ {
+ public:
+ __forceinline IntersectContext(Scene* scene, RTCIntersectContext* user_context)
+ : scene(scene), user(user_context) {}
+
+ __forceinline bool hasContextFilter() const {
+ return user->filter != nullptr;
+ }
+
+ __forceinline bool isCoherent() const {
+ return embree::isCoherent(user->flags);
+ }
+
+ __forceinline bool isIncoherent() const {
+ return embree::isIncoherent(user->flags);
+ }
+
+ public:
+ Scene* scene;
+ RTCIntersectContext* user;
+ };
+
+ template<int M, typename Geometry>
+ __forceinline Vec4vf<M> enlargeRadiusToMinWidth(const IntersectContext* context, const Geometry* geom, const Vec3vf<M>& ray_org, const Vec4vf<M>& v)
+ {
+#if RTC_MIN_WIDTH
+ const vfloat<M> d = length(Vec3vf<M>(v) - ray_org);
+ const vfloat<M> r = clamp(context->user->minWidthDistanceFactor*d, v.w, geom->maxRadiusScale*v.w);
+ return Vec4vf<M>(v.x,v.y,v.z,r);
+#else
+ return v;
+#endif
+ }
+
+ template<typename Geometry>
+ __forceinline Vec3ff enlargeRadiusToMinWidth(const IntersectContext* context, const Geometry* geom, const Vec3fa& ray_org, const Vec3ff& v)
+ {
+#if RTC_MIN_WIDTH
+ const float d = length(Vec3fa(v) - ray_org);
+ const float r = clamp(context->user->minWidthDistanceFactor*d, v.w, geom->maxRadiusScale*v.w);
+ return Vec3ff(v.x,v.y,v.z,r);
+#else
+ return v;
+#endif
+ }
+
+ enum PointQueryType
+ {
+ POINT_QUERY_TYPE_UNDEFINED = 0,
+ POINT_QUERY_TYPE_SPHERE = 1,
+ POINT_QUERY_TYPE_AABB = 2,
+ };
+
+ typedef bool (*PointQueryFunction)(struct RTCPointQueryFunctionArguments* args);
+
+ struct PointQueryContext
+ {
+ public:
+ __forceinline PointQueryContext(Scene* scene,
+ PointQuery* query_ws,
+ PointQueryType query_type,
+ PointQueryFunction func,
+ RTCPointQueryContext* userContext,
+ float similarityScale,
+ void* userPtr)
+ : scene(scene)
+ , query_ws(query_ws)
+ , query_type(query_type)
+ , func(func)
+ , userContext(userContext)
+ , similarityScale(similarityScale)
+ , userPtr(userPtr)
+ , primID(RTC_INVALID_GEOMETRY_ID)
+ , geomID(RTC_INVALID_GEOMETRY_ID)
+ , query_radius(query_ws->radius)
+ {
+ if (query_type == POINT_QUERY_TYPE_AABB) {
+ assert(similarityScale == 0.f);
+ updateAABB();
+ }
+ if (userContext->instStackSize == 0) {
+ assert(similarityScale == 1.f);
+ }
+ }
+
+ public:
+ __forceinline void updateAABB()
+ {
+ if (likely(query_ws->radius == (float)inf || userContext->instStackSize == 0)) {
+ query_radius = Vec3fa(query_ws->radius);
+ return;
+ }
+
+ const AffineSpace3fa m = AffineSpace3fa_load_unaligned((AffineSpace3fa*)userContext->world2inst[userContext->instStackSize-1]);
+ BBox3fa bbox(Vec3fa(-query_ws->radius), Vec3fa(query_ws->radius));
+ bbox = xfmBounds(m, bbox);
+ query_radius = 0.5f * (bbox.upper - bbox.lower);
+ }
+
+public:
+ Scene* scene;
+
+ PointQuery* query_ws; // the original world space point query
+ PointQueryType query_type;
+ PointQueryFunction func;
+ RTCPointQueryContext* userContext;
+ const float similarityScale;
+
+ void* userPtr;
+
+ unsigned int primID;
+ unsigned int geomID;
+
+ Vec3fa query_radius; // used if the query is converted to an AABB internally
+ };
+}
+
diff --git a/thirdparty/embree/kernels/common/default.h b/thirdparty/embree/kernels/common/default.h
new file mode 100644
index 0000000000..f15d61b768
--- /dev/null
+++ b/thirdparty/embree/kernels/common/default.h
@@ -0,0 +1,268 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../../common/sys/platform.h"
+#include "../../common/sys/sysinfo.h"
+#include "../../common/sys/thread.h"
+#include "../../common/sys/alloc.h"
+#include "../../common/sys/ref.h"
+#include "../../common/sys/intrinsics.h"
+#include "../../common/sys/atomic.h"
+#include "../../common/sys/mutex.h"
+#include "../../common/sys/vector.h"
+#include "../../common/sys/array.h"
+#include "../../common/sys/string.h"
+#include "../../common/sys/regression.h"
+#include "../../common/sys/vector.h"
+
+#include "../../common/math/math.h"
+#include "../../common/math/transcendental.h"
+#include "../../common/simd/simd.h"
+#include "../../common/math/vec2.h"
+#include "../../common/math/vec3.h"
+#include "../../common/math/vec4.h"
+#include "../../common/math/vec2fa.h"
+#include "../../common/math/vec3fa.h"
+#include "../../common/math/interval.h"
+#include "../../common/math/bbox.h"
+#include "../../common/math/obbox.h"
+#include "../../common/math/lbbox.h"
+#include "../../common/math/linearspace2.h"
+#include "../../common/math/linearspace3.h"
+#include "../../common/math/affinespace.h"
+#include "../../common/math/range.h"
+#include "../../common/lexers/tokenstream.h"
+
+#include "../../common/tasking/taskscheduler.h"
+
+#define COMMA ,
+
+#include "../config.h"
+#include "isa.h"
+#include "stat.h"
+#include "profile.h"
+#include "rtcore.h"
+#include "vector.h"
+#include "state.h"
+#include "instance_stack.h"
+
+#include <vector>
+#include <map>
+#include <algorithm>
+#include <functional>
+#include <utility>
+#include <sstream>
+
+namespace embree
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Vec2 shortcuts
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int N> using Vec2vf = Vec2<vfloat<N>>;
+ template<int N> using Vec2vd = Vec2<vdouble<N>>;
+ template<int N> using Vec2vr = Vec2<vreal<N>>;
+ template<int N> using Vec2vi = Vec2<vint<N>>;
+ template<int N> using Vec2vl = Vec2<vllong<N>>;
+ template<int N> using Vec2vb = Vec2<vbool<N>>;
+ template<int N> using Vec2vbf = Vec2<vboolf<N>>;
+ template<int N> using Vec2vbd = Vec2<vboold<N>>;
+
+ typedef Vec2<vfloat4> Vec2vf4;
+ typedef Vec2<vdouble4> Vec2vd4;
+ typedef Vec2<vreal4> Vec2vr4;
+ typedef Vec2<vint4> Vec2vi4;
+ typedef Vec2<vllong4> Vec2vl4;
+ typedef Vec2<vbool4> Vec2vb4;
+ typedef Vec2<vboolf4> Vec2vbf4;
+ typedef Vec2<vboold4> Vec2vbd4;
+
+ typedef Vec2<vfloat8> Vec2vf8;
+ typedef Vec2<vdouble8> Vec2vd8;
+ typedef Vec2<vreal8> Vec2vr8;
+ typedef Vec2<vint8> Vec2vi8;
+ typedef Vec2<vllong8> Vec2vl8;
+ typedef Vec2<vbool8> Vec2vb8;
+ typedef Vec2<vboolf8> Vec2vbf8;
+ typedef Vec2<vboold8> Vec2vbd8;
+
+ typedef Vec2<vfloat16> Vec2vf16;
+ typedef Vec2<vdouble16> Vec2vd16;
+ typedef Vec2<vreal16> Vec2vr16;
+ typedef Vec2<vint16> Vec2vi16;
+ typedef Vec2<vllong16> Vec2vl16;
+ typedef Vec2<vbool16> Vec2vb16;
+ typedef Vec2<vboolf16> Vec2vbf16;
+ typedef Vec2<vboold16> Vec2vbd16;
+
+ typedef Vec2<vfloatx> Vec2vfx;
+ typedef Vec2<vdoublex> Vec2vdx;
+ typedef Vec2<vrealx> Vec2vrx;
+ typedef Vec2<vintx> Vec2vix;
+ typedef Vec2<vllongx> Vec2vlx;
+ typedef Vec2<vboolx> Vec2vbx;
+ typedef Vec2<vboolfx> Vec2vbfx;
+ typedef Vec2<vbooldx> Vec2vbdx;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Vec3 shortcuts
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int N> using Vec3vf = Vec3<vfloat<N>>;
+ template<int N> using Vec3vd = Vec3<vdouble<N>>;
+ template<int N> using Vec3vr = Vec3<vreal<N>>;
+ template<int N> using Vec3vi = Vec3<vint<N>>;
+ template<int N> using Vec3vl = Vec3<vllong<N>>;
+ template<int N> using Vec3vb = Vec3<vbool<N>>;
+ template<int N> using Vec3vbf = Vec3<vboolf<N>>;
+ template<int N> using Vec3vbd = Vec3<vboold<N>>;
+
+ typedef Vec3<vfloat4> Vec3vf4;
+ typedef Vec3<vdouble4> Vec3vd4;
+ typedef Vec3<vreal4> Vec3vr4;
+ typedef Vec3<vint4> Vec3vi4;
+ typedef Vec3<vllong4> Vec3vl4;
+ typedef Vec3<vbool4> Vec3vb4;
+ typedef Vec3<vboolf4> Vec3vbf4;
+ typedef Vec3<vboold4> Vec3vbd4;
+
+ typedef Vec3<vfloat8> Vec3vf8;
+ typedef Vec3<vdouble8> Vec3vd8;
+ typedef Vec3<vreal8> Vec3vr8;
+ typedef Vec3<vint8> Vec3vi8;
+ typedef Vec3<vllong8> Vec3vl8;
+ typedef Vec3<vbool8> Vec3vb8;
+ typedef Vec3<vboolf8> Vec3vbf8;
+ typedef Vec3<vboold8> Vec3vbd8;
+
+ typedef Vec3<vfloat16> Vec3vf16;
+ typedef Vec3<vdouble16> Vec3vd16;
+ typedef Vec3<vreal16> Vec3vr16;
+ typedef Vec3<vint16> Vec3vi16;
+ typedef Vec3<vllong16> Vec3vl16;
+ typedef Vec3<vbool16> Vec3vb16;
+ typedef Vec3<vboolf16> Vec3vbf16;
+ typedef Vec3<vboold16> Vec3vbd16;
+
+ typedef Vec3<vfloatx> Vec3vfx;
+ typedef Vec3<vdoublex> Vec3vdx;
+ typedef Vec3<vrealx> Vec3vrx;
+ typedef Vec3<vintx> Vec3vix;
+ typedef Vec3<vllongx> Vec3vlx;
+ typedef Vec3<vboolx> Vec3vbx;
+ typedef Vec3<vboolfx> Vec3vbfx;
+ typedef Vec3<vbooldx> Vec3vbdx;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Vec4 shortcuts
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int N> using Vec4vf = Vec4<vfloat<N>>;
+ template<int N> using Vec4vd = Vec4<vdouble<N>>;
+ template<int N> using Vec4vr = Vec4<vreal<N>>;
+ template<int N> using Vec4vi = Vec4<vint<N>>;
+ template<int N> using Vec4vl = Vec4<vllong<N>>;
+ template<int N> using Vec4vb = Vec4<vbool<N>>;
+ template<int N> using Vec4vbf = Vec4<vboolf<N>>;
+ template<int N> using Vec4vbd = Vec4<vboold<N>>;
+
+ typedef Vec4<vfloat4> Vec4vf4;
+ typedef Vec4<vdouble4> Vec4vd4;
+ typedef Vec4<vreal4> Vec4vr4;
+ typedef Vec4<vint4> Vec4vi4;
+ typedef Vec4<vllong4> Vec4vl4;
+ typedef Vec4<vbool4> Vec4vb4;
+ typedef Vec4<vboolf4> Vec4vbf4;
+ typedef Vec4<vboold4> Vec4vbd4;
+
+ typedef Vec4<vfloat8> Vec4vf8;
+ typedef Vec4<vdouble8> Vec4vd8;
+ typedef Vec4<vreal8> Vec4vr8;
+ typedef Vec4<vint8> Vec4vi8;
+ typedef Vec4<vllong8> Vec4vl8;
+ typedef Vec4<vbool8> Vec4vb8;
+ typedef Vec4<vboolf8> Vec4vbf8;
+ typedef Vec4<vboold8> Vec4vbd8;
+
+ typedef Vec4<vfloat16> Vec4vf16;
+ typedef Vec4<vdouble16> Vec4vd16;
+ typedef Vec4<vreal16> Vec4vr16;
+ typedef Vec4<vint16> Vec4vi16;
+ typedef Vec4<vllong16> Vec4vl16;
+ typedef Vec4<vbool16> Vec4vb16;
+ typedef Vec4<vboolf16> Vec4vbf16;
+ typedef Vec4<vboold16> Vec4vbd16;
+
+ typedef Vec4<vfloatx> Vec4vfx;
+ typedef Vec4<vdoublex> Vec4vdx;
+ typedef Vec4<vrealx> Vec4vrx;
+ typedef Vec4<vintx> Vec4vix;
+ typedef Vec4<vllongx> Vec4vlx;
+ typedef Vec4<vboolx> Vec4vbx;
+ typedef Vec4<vboolfx> Vec4vbfx;
+ typedef Vec4<vbooldx> Vec4vbdx;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Other shortcuts
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<int N> using BBox3vf = BBox<Vec3vf<N>>;
+ typedef BBox<Vec3vf4> BBox3vf4;
+ typedef BBox<Vec3vf8> BBox3vf8;
+ typedef BBox<Vec3vf16> BBox3vf16;
+
+ /* calculate time segment itime and fractional time ftime */
+ __forceinline int getTimeSegment(float time, float numTimeSegments, float& ftime)
+ {
+ const float timeScaled = time * numTimeSegments;
+ const float itimef = clamp(floorf(timeScaled), 0.0f, numTimeSegments-1.0f);
+ ftime = timeScaled - itimef;
+ return int(itimef);
+ }
+
+ __forceinline int getTimeSegment(float time, float start_time, float end_time, float numTimeSegments, float& ftime)
+ {
+ const float timeScaled = (time-start_time)/(end_time-start_time) * numTimeSegments;
+ const float itimef = clamp(floorf(timeScaled), 0.0f, numTimeSegments-1.0f);
+ ftime = timeScaled - itimef;
+ return int(itimef);
+ }
+
+ template<int N>
+ __forceinline vint<N> getTimeSegment(const vfloat<N>& time, const vfloat<N>& numTimeSegments, vfloat<N>& ftime)
+ {
+ const vfloat<N> timeScaled = time * numTimeSegments;
+ const vfloat<N> itimef = clamp(floor(timeScaled), vfloat<N>(zero), numTimeSegments-1.0f);
+ ftime = timeScaled - itimef;
+ return vint<N>(itimef);
+ }
+
+ template<int N>
+ __forceinline vint<N> getTimeSegment(const vfloat<N>& time, const vfloat<N>& start_time, const vfloat<N>& end_time, const vfloat<N>& numTimeSegments, vfloat<N>& ftime)
+ {
+ const vfloat<N> timeScaled = (time-start_time)/(end_time-start_time) * numTimeSegments;
+ const vfloat<N> itimef = clamp(floor(timeScaled), vfloat<N>(zero), numTimeSegments-1.0f);
+ ftime = timeScaled - itimef;
+ return vint<N>(itimef);
+ }
+
+ /* calculate overlapping time segment range */
+ __forceinline range<int> getTimeSegmentRange(const BBox1f& time_range, float numTimeSegments)
+ {
+ const float round_up = 1.0f+2.0f*float(ulp); // corrects inaccuracies to precisely match time step
+ const float round_down = 1.0f-2.0f*float(ulp);
+ const int itime_lower = (int)max(floor(round_up *time_range.lower*numTimeSegments), 0.0f);
+ const int itime_upper = (int)min(ceil (round_down*time_range.upper*numTimeSegments), numTimeSegments);
+ return make_range(itime_lower, itime_upper);
+ }
+
+ /* calculate overlapping time segment range */
+ __forceinline range<int> getTimeSegmentRange(const BBox1f& range, BBox1f time_range, float numTimeSegments)
+ {
+ const float lower = (range.lower-time_range.lower)/time_range.size();
+ const float upper = (range.upper-time_range.lower)/time_range.size();
+ return getTimeSegmentRange(BBox1f(lower,upper),numTimeSegments);
+ }
+}
diff --git a/thirdparty/embree/kernels/common/device.cpp b/thirdparty/embree/kernels/common/device.cpp
new file mode 100644
index 0000000000..068e0c2983
--- /dev/null
+++ b/thirdparty/embree/kernels/common/device.cpp
@@ -0,0 +1,556 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "device.h"
+#include "../hash.h"
+#include "scene_triangle_mesh.h"
+#include "scene_user_geometry.h"
+#include "scene_instance.h"
+#include "scene_curves.h"
+#include "scene_subdiv_mesh.h"
+
+#include "../subdiv/tessellation_cache.h"
+
+#include "acceln.h"
+#include "geometry.h"
+
+#include "../geometry/cylinder.h"
+
+#include "../bvh/bvh4_factory.h"
+#include "../bvh/bvh8_factory.h"
+
+#include "../../common/tasking/taskscheduler.h"
+#include "../../common/sys/alloc.h"
+
+namespace embree
+{
+ /*! some global variables that can be set via rtcSetParameter1i for debugging purposes */
+ ssize_t Device::debug_int0 = 0;
+ ssize_t Device::debug_int1 = 0;
+ ssize_t Device::debug_int2 = 0;
+ ssize_t Device::debug_int3 = 0;
+
+ DECLARE_SYMBOL2(RayStreamFilterFuncs,rayStreamFilterFuncs);
+
+ static MutexSys g_mutex;
+ static std::map<Device*,size_t> g_cache_size_map;
+ static std::map<Device*,size_t> g_num_threads_map;
+
+ Device::Device (const char* cfg)
+ {
+ /* check that CPU supports lowest ISA */
+ if (!hasISA(ISA)) {
+ throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"CPU does not support " ISA_STR);
+ }
+
+ /* set default frequency level for detected CPU */
+ switch (getCPUModel()) {
+ case CPU::UNKNOWN: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::XEON_ICE_LAKE: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::CORE_ICE_LAKE: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::CORE_TIGER_LAKE: frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::CORE_COMET_LAKE: frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::CORE_CANNON_LAKE:frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::CORE_KABY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::XEON_SKY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::CORE_SKY_LAKE: frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::XEON_BROADWELL: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::CORE_BROADWELL: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::XEON_HASWELL: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::CORE_HASWELL: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::XEON_IVY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::CORE_IVY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::SANDY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break;
+ case CPU::NEHALEM: frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::CORE2: frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::CORE1: frequency_level = FREQUENCY_SIMD128; break;
+ case CPU::XEON_PHI_KNIGHTS_MILL : frequency_level = FREQUENCY_SIMD512; break;
+ case CPU::XEON_PHI_KNIGHTS_LANDING: frequency_level = FREQUENCY_SIMD512; break;
+ case CPU::ARM: frequency_level = FREQUENCY_SIMD128; break;
+ }
+
+ /* initialize global state */
+#if defined(EMBREE_CONFIG)
+ State::parseString(EMBREE_CONFIG);
+#endif
+ State::parseString(cfg);
+ State::verify();
+
+ /* check whether selected ISA is supported by the HW, as the user could have forced an unsupported ISA */
+ if (!checkISASupport()) {
+ throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"CPU does not support selected ISA");
+ }
+
+ /*! do some internal tests */
+ assert(isa::Cylinder::verify());
+
+ /*! enable huge page support if desired */
+#if defined(__WIN32__)
+ if (State::enable_selockmemoryprivilege)
+ State::hugepages_success &= win_enable_selockmemoryprivilege(State::verbosity(3));
+#endif
+ State::hugepages_success &= os_init(State::hugepages,State::verbosity(3));
+
+ /*! set tessellation cache size */
+ setCacheSize( State::tessellation_cache_size );
+
+ /*! enable some floating point exceptions to catch bugs */
+ if (State::float_exceptions)
+ {
+ int exceptions = _MM_MASK_MASK;
+ //exceptions &= ~_MM_MASK_INVALID;
+ exceptions &= ~_MM_MASK_DENORM;
+ exceptions &= ~_MM_MASK_DIV_ZERO;
+ //exceptions &= ~_MM_MASK_OVERFLOW;
+ //exceptions &= ~_MM_MASK_UNDERFLOW;
+ //exceptions &= ~_MM_MASK_INEXACT;
+ _MM_SET_EXCEPTION_MASK(exceptions);
+ }
+
+ /* print info header */
+ if (State::verbosity(1))
+ print();
+ if (State::verbosity(2))
+ State::print();
+
+ /* register all algorithms */
+ bvh4_factory = make_unique(new BVH4Factory(enabled_builder_cpu_features, enabled_cpu_features));
+
+#if defined(EMBREE_TARGET_SIMD8)
+ bvh8_factory = make_unique(new BVH8Factory(enabled_builder_cpu_features, enabled_cpu_features));
+#endif
+
+ /* setup tasking system */
+ initTaskingSystem(numThreads);
+
+ /* ray stream SOA to AOS conversion */
+#if defined(EMBREE_RAY_PACKETS)
+ RayStreamFilterFuncsType rayStreamFilterFuncs;
+ SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(enabled_cpu_features,rayStreamFilterFuncs);
+ rayStreamFilters = rayStreamFilterFuncs();
+#endif
+ }
+
+ Device::~Device ()
+ {
+ setCacheSize(0);
+ exitTaskingSystem();
+ }
+
+ std::string getEnabledTargets()
+ {
+ std::string v;
+#if defined(EMBREE_TARGET_SSE2)
+ v += "SSE2 ";
+#endif
+#if defined(EMBREE_TARGET_SSE42)
+ v += "SSE4.2 ";
+#endif
+#if defined(EMBREE_TARGET_AVX)
+ v += "AVX ";
+#endif
+#if defined(EMBREE_TARGET_AVX2)
+ v += "AVX2 ";
+#endif
+#if defined(EMBREE_TARGET_AVX512)
+ v += "AVX512 ";
+#endif
+ return v;
+ }
+
+ std::string getEmbreeFeatures()
+ {
+ std::string v;
+#if defined(EMBREE_RAY_MASK)
+ v += "raymasks ";
+#endif
+#if defined (EMBREE_BACKFACE_CULLING)
+ v += "backfaceculling ";
+#endif
+#if defined (EMBREE_BACKFACE_CULLING_CURVES)
+ v += "backfacecullingcurves ";
+#endif
+#if defined(EMBREE_FILTER_FUNCTION)
+ v += "intersection_filter ";
+#endif
+#if defined (EMBREE_COMPACT_POLYS)
+ v += "compact_polys ";
+#endif
+ return v;
+ }
+
+ void Device::print()
+ {
+ const int cpu_features = getCPUFeatures();
+ std::cout << std::endl;
+ std::cout << "Embree Ray Tracing Kernels " << RTC_VERSION_STRING << " (" << RTC_HASH << ")" << std::endl;
+ std::cout << " Compiler : " << getCompilerName() << std::endl;
+ std::cout << " Build : ";
+#if defined(DEBUG)
+ std::cout << "Debug " << std::endl;
+#else
+ std::cout << "Release " << std::endl;
+#endif
+ std::cout << " Platform : " << getPlatformName() << std::endl;
+ std::cout << " CPU : " << stringOfCPUModel(getCPUModel()) << " (" << getCPUVendor() << ")" << std::endl;
+ std::cout << " Threads : " << getNumberOfLogicalThreads() << std::endl;
+ std::cout << " ISA : " << stringOfCPUFeatures(cpu_features) << std::endl;
+ std::cout << " Targets : " << supportedTargetList(cpu_features) << std::endl;
+ const bool hasFTZ = _mm_getcsr() & _MM_FLUSH_ZERO_ON;
+ const bool hasDAZ = _mm_getcsr() & _MM_DENORMALS_ZERO_ON;
+ std::cout << " MXCSR : " << "FTZ=" << hasFTZ << ", DAZ=" << hasDAZ << std::endl;
+ std::cout << " Config" << std::endl;
+ std::cout << " Threads : " << (numThreads ? toString(numThreads) : std::string("default")) << std::endl;
+ std::cout << " ISA : " << stringOfCPUFeatures(enabled_cpu_features) << std::endl;
+ std::cout << " Targets : " << supportedTargetList(enabled_cpu_features) << " (supported)" << std::endl;
+ std::cout << " " << getEnabledTargets() << " (compile time enabled)" << std::endl;
+ std::cout << " Features: " << getEmbreeFeatures() << std::endl;
+ std::cout << " Tasking : ";
+#if defined(TASKING_TBB)
+ std::cout << "TBB" << TBB_VERSION_MAJOR << "." << TBB_VERSION_MINOR << " ";
+ #if TBB_INTERFACE_VERSION >= 12002
+ std::cout << "TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << TBB_runtime_interface_version() << " ";
+ #else
+ std::cout << "TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << tbb::TBB_runtime_interface_version() << " ";
+ #endif
+#endif
+#if defined(TASKING_INTERNAL)
+ std::cout << "internal_tasking_system ";
+#endif
+#if defined(TASKING_PPL)
+ std::cout << "PPL ";
+#endif
+ std::cout << std::endl;
+
+ /* check of FTZ and DAZ flags are set in CSR */
+ if (!hasFTZ || !hasDAZ)
+ {
+#if !defined(_DEBUG)
+ if (State::verbosity(1))
+#endif
+ {
+ std::cout << std::endl;
+ std::cout << "================================================================================" << std::endl;
+ std::cout << " WARNING: \"Flush to Zero\" or \"Denormals are Zero\" mode not enabled " << std::endl
+ << " in the MXCSR control and status register. This can have a severe " << std::endl
+ << " performance impact. Please enable these modes for each application " << std::endl
+ << " thread the following way:" << std::endl
+ << std::endl
+ << " #include \"xmmintrin.h\"" << std::endl
+ << " #include \"pmmintrin.h\"" << std::endl
+ << std::endl
+ << " _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);" << std::endl
+ << " _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);" << std::endl;
+ std::cout << "================================================================================" << std::endl;
+ std::cout << std::endl;
+ }
+ }
+ std::cout << std::endl;
+ }
+
+ void Device::setDeviceErrorCode(RTCError error)
+ {
+ RTCError* stored_error = errorHandler.error();
+ if (*stored_error == RTC_ERROR_NONE)
+ *stored_error = error;
+ }
+
+ RTCError Device::getDeviceErrorCode()
+ {
+ RTCError* stored_error = errorHandler.error();
+ RTCError error = *stored_error;
+ *stored_error = RTC_ERROR_NONE;
+ return error;
+ }
+
+ void Device::setThreadErrorCode(RTCError error)
+ {
+ RTCError* stored_error = g_errorHandler.error();
+ if (*stored_error == RTC_ERROR_NONE)
+ *stored_error = error;
+ }
+
+ RTCError Device::getThreadErrorCode()
+ {
+ RTCError* stored_error = g_errorHandler.error();
+ RTCError error = *stored_error;
+ *stored_error = RTC_ERROR_NONE;
+ return error;
+ }
+
+ void Device::process_error(Device* device, RTCError error, const char* str)
+ {
+ /* store global error code when device construction failed */
+ if (!device)
+ return setThreadErrorCode(error);
+
+ /* print error when in verbose mode */
+ if (device->verbosity(1))
+ {
+ switch (error) {
+ case RTC_ERROR_NONE : std::cerr << "Embree: No error"; break;
+ case RTC_ERROR_UNKNOWN : std::cerr << "Embree: Unknown error"; break;
+ case RTC_ERROR_INVALID_ARGUMENT : std::cerr << "Embree: Invalid argument"; break;
+ case RTC_ERROR_INVALID_OPERATION: std::cerr << "Embree: Invalid operation"; break;
+ case RTC_ERROR_OUT_OF_MEMORY : std::cerr << "Embree: Out of memory"; break;
+ case RTC_ERROR_UNSUPPORTED_CPU : std::cerr << "Embree: Unsupported CPU"; break;
+ default : std::cerr << "Embree: Invalid error code"; break;
+ };
+ if (str) std::cerr << ", (" << str << ")";
+ std::cerr << std::endl;
+ }
+
+ /* call user specified error callback */
+ if (device->error_function)
+ device->error_function(device->error_function_userptr,error,str);
+
+ /* record error code */
+ device->setDeviceErrorCode(error);
+ }
+
+ void Device::memoryMonitor(ssize_t bytes, bool post)
+ {
+ if (State::memory_monitor_function && bytes != 0) {
+ if (!State::memory_monitor_function(State::memory_monitor_userptr,bytes,post)) {
+ if (bytes > 0) { // only throw exception when we allocate memory to never throw inside a destructor
+ throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"memory monitor forced termination");
+ }
+ }
+ }
+ }
+
+ size_t getMaxNumThreads()
+ {
+ size_t maxNumThreads = 0;
+ for (std::map<Device*,size_t>::iterator i=g_num_threads_map.begin(); i != g_num_threads_map.end(); i++)
+ maxNumThreads = max(maxNumThreads, (*i).second);
+ if (maxNumThreads == 0)
+ maxNumThreads = std::numeric_limits<size_t>::max();
+ return maxNumThreads;
+ }
+
+ size_t getMaxCacheSize()
+ {
+ size_t maxCacheSize = 0;
+ for (std::map<Device*,size_t>::iterator i=g_cache_size_map.begin(); i!= g_cache_size_map.end(); i++)
+ maxCacheSize = max(maxCacheSize, (*i).second);
+ return maxCacheSize;
+ }
+
+ void Device::setCacheSize(size_t bytes)
+ {
+#if defined(EMBREE_GEOMETRY_SUBDIVISION)
+ Lock<MutexSys> lock(g_mutex);
+ if (bytes == 0) g_cache_size_map.erase(this);
+ else g_cache_size_map[this] = bytes;
+
+ size_t maxCacheSize = getMaxCacheSize();
+ resizeTessellationCache(maxCacheSize);
+#endif
+ }
+
+ void Device::initTaskingSystem(size_t numThreads)
+ {
+ Lock<MutexSys> lock(g_mutex);
+ if (numThreads == 0)
+ g_num_threads_map[this] = std::numeric_limits<size_t>::max();
+ else
+ g_num_threads_map[this] = numThreads;
+
+ /* create task scheduler */
+ size_t maxNumThreads = getMaxNumThreads();
+ TaskScheduler::create(maxNumThreads,State::set_affinity,State::start_threads);
+#if USE_TASK_ARENA
+ const size_t nThreads = min(maxNumThreads,TaskScheduler::threadCount());
+ const size_t uThreads = min(max(numUserThreads,(size_t)1),nThreads);
+ arena = make_unique(new tbb::task_arena((int)nThreads,(unsigned int)uThreads));
+#endif
+ }
+
+ void Device::exitTaskingSystem()
+ {
+ Lock<MutexSys> lock(g_mutex);
+ g_num_threads_map.erase(this);
+
+ /* terminate tasking system */
+ if (g_num_threads_map.size() == 0) {
+ TaskScheduler::destroy();
+ }
+ /* or configure new number of threads */
+ else {
+ size_t maxNumThreads = getMaxNumThreads();
+ TaskScheduler::create(maxNumThreads,State::set_affinity,State::start_threads);
+ }
+#if USE_TASK_ARENA
+ arena.reset();
+#endif
+ }
+
+ void Device::setProperty(const RTCDeviceProperty prop, ssize_t val)
+ {
+ /* hidden internal properties */
+ switch ((size_t)prop)
+ {
+ case 1000000: debug_int0 = val; return;
+ case 1000001: debug_int1 = val; return;
+ case 1000002: debug_int2 = val; return;
+ case 1000003: debug_int3 = val; return;
+ }
+
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown writable property");
+ }
+
+ ssize_t Device::getProperty(const RTCDeviceProperty prop)
+ {
+ size_t iprop = (size_t)prop;
+
+ /* get name of internal regression test */
+ if (iprop >= 2000000 && iprop < 3000000)
+ {
+ RegressionTest* test = getRegressionTest(iprop-2000000);
+ if (test) return (ssize_t) test->name.c_str();
+ else return 0;
+ }
+
+ /* run internal regression test */
+ if (iprop >= 3000000 && iprop < 4000000)
+ {
+ RegressionTest* test = getRegressionTest(iprop-3000000);
+ if (test) return test->run();
+ else return 0;
+ }
+
+ /* documented properties */
+ switch (prop)
+ {
+ case RTC_DEVICE_PROPERTY_VERSION_MAJOR: return RTC_VERSION_MAJOR;
+ case RTC_DEVICE_PROPERTY_VERSION_MINOR: return RTC_VERSION_MINOR;
+ case RTC_DEVICE_PROPERTY_VERSION_PATCH: return RTC_VERSION_PATCH;
+ case RTC_DEVICE_PROPERTY_VERSION : return RTC_VERSION;
+
+#if defined(EMBREE_TARGET_SIMD4) && defined(EMBREE_RAY_PACKETS)
+ case RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED: return hasISA(SSE2);
+#else
+ case RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_TARGET_SIMD8) && defined(EMBREE_RAY_PACKETS)
+ case RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED: return hasISA(AVX);
+#else
+ case RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_TARGET_SIMD16) && defined(EMBREE_RAY_PACKETS)
+ case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return hasISA(AVX512);
+#else
+ case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_RAY_PACKETS)
+ case RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_RAY_MASK)
+ case RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_BACKFACE_CULLING)
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED: return 0;
+#endif
+
+#if defined(EMBREE_BACKFACE_CULLING_CURVES)
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 0;
+#endif
+
+#if defined(EMBREE_COMPACT_POLYS)
+ case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 0;
+#endif
+
+#if defined(EMBREE_FILTER_FUNCTION)
+ case RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_IGNORE_INVALID_RAYS)
+ case RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED: return 0;
+#endif
+
+#if defined(TASKING_INTERNAL)
+ case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 0;
+#endif
+
+#if defined(TASKING_TBB)
+ case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 1;
+#endif
+
+#if defined(TASKING_PPL)
+ case RTC_DEVICE_PROPERTY_TASKING_SYSTEM: return 2;
+#endif
+
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ case RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_GEOMETRY_QUAD)
+ case RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_GEOMETRY_CURVE)
+ case RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_GEOMETRY_SUBDIVISION)
+ case RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_GEOMETRY_USER)
+ case RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED: return 0;
+#endif
+
+#if defined(EMBREE_GEOMETRY_POINT)
+ case RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED: return 0;
+#endif
+
+#if defined(TASKING_PPL)
+ case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 0;
+#elif defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)
+ case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 0;
+#else
+ case RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: return 1;
+#endif
+
+#if defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION
+ case RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED: return 0;
+#endif
+
+ default: throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown readable property"); break;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/common/device.h b/thirdparty/embree/kernels/common/device.h
new file mode 100644
index 0000000000..21c42c654d
--- /dev/null
+++ b/thirdparty/embree/kernels/common/device.h
@@ -0,0 +1,85 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "state.h"
+#include "accel.h"
+
+namespace embree
+{
+ class BVH4Factory;
+ class BVH8Factory;
+
+ class Device : public State, public MemoryMonitorInterface
+ {
+ ALIGNED_CLASS_(16);
+
+ public:
+
+ /*! Device construction */
+ Device (const char* cfg);
+
+ /*! Device destruction */
+ virtual ~Device ();
+
+ /*! prints info about the device */
+ void print();
+
+ /*! sets the error code */
+ void setDeviceErrorCode(RTCError error);
+
+ /*! returns and clears the error code */
+ RTCError getDeviceErrorCode();
+
+ /*! sets the error code */
+ static void setThreadErrorCode(RTCError error);
+
+ /*! returns and clears the error code */
+ static RTCError getThreadErrorCode();
+
+ /*! processes error codes, do not call directly */
+ static void process_error(Device* device, RTCError error, const char* str);
+
+ /*! invokes the memory monitor callback */
+ void memoryMonitor(ssize_t bytes, bool post);
+
+ /*! sets the size of the software cache. */
+ void setCacheSize(size_t bytes);
+
+ /*! sets a property */
+ void setProperty(const RTCDeviceProperty prop, ssize_t val);
+
+ /*! gets a property */
+ ssize_t getProperty(const RTCDeviceProperty prop);
+
+ private:
+
+ /*! initializes the tasking system */
+ void initTaskingSystem(size_t numThreads);
+
+ /*! shuts down the tasking system */
+ void exitTaskingSystem();
+
+ /*! some variables that can be set via rtcSetParameter1i for debugging purposes */
+ public:
+ static ssize_t debug_int0;
+ static ssize_t debug_int1;
+ static ssize_t debug_int2;
+ static ssize_t debug_int3;
+
+ public:
+ std::unique_ptr<BVH4Factory> bvh4_factory;
+#if defined(EMBREE_TARGET_SIMD8)
+ std::unique_ptr<BVH8Factory> bvh8_factory;
+#endif
+
+#if USE_TASK_ARENA
+ std::unique_ptr<tbb::task_arena> arena;
+#endif
+
+ /* ray streams filter */
+ RayStreamFilterFuncs rayStreamFilters;
+ };
+}
diff --git a/thirdparty/embree/kernels/common/geometry.cpp b/thirdparty/embree/kernels/common/geometry.cpp
new file mode 100644
index 0000000000..d8d3f65a5c
--- /dev/null
+++ b/thirdparty/embree/kernels/common/geometry.cpp
@@ -0,0 +1,259 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "geometry.h"
+#include "scene.h"
+
+namespace embree
+{
+ const char* Geometry::gtype_names[Geometry::GTY_END] =
+ {
+ "flat_linear_curve",
+ "round_linear_curve",
+ "oriented_linear_curve",
+ "",
+ "flat_bezier_curve",
+ "round_bezier_curve",
+ "oriented_bezier_curve",
+ "",
+ "flat_bspline_curve",
+ "round_bspline_curve",
+ "oriented_bspline_curve",
+ "",
+ "flat_hermite_curve",
+ "round_hermite_curve",
+ "oriented_hermite_curve",
+ "",
+ "flat_catmull_rom_curve",
+ "round_catmull_rom_curve",
+ "oriented_catmull_rom_curve",
+ "",
+ "triangles",
+ "quads",
+ "grid",
+ "subdivs",
+ "",
+ "sphere",
+ "disc",
+ "oriented_disc",
+ "",
+ "usergeom",
+ "instance_cheap",
+ "instance_expensive",
+ };
+
+ Geometry::Geometry (Device* device, GType gtype, unsigned int numPrimitives, unsigned int numTimeSteps)
+ : device(device), userPtr(nullptr),
+ numPrimitives(numPrimitives), numTimeSteps(unsigned(numTimeSteps)), fnumTimeSegments(float(numTimeSteps-1)), time_range(0.0f,1.0f),
+ mask(-1),
+ gtype(gtype),
+ gsubtype(GTY_SUBTYPE_DEFAULT),
+ quality(RTC_BUILD_QUALITY_MEDIUM),
+ state((unsigned)State::MODIFIED),
+ enabled(true),
+ intersectionFilterN(nullptr), occlusionFilterN(nullptr), pointQueryFunc(nullptr)
+ {
+ device->refInc();
+ }
+
+ Geometry::~Geometry()
+ {
+ device->refDec();
+ }
+
+ void Geometry::setNumPrimitives(unsigned int numPrimitives_in)
+ {
+ if (numPrimitives_in == numPrimitives) return;
+
+ numPrimitives = numPrimitives_in;
+
+ Geometry::update();
+ }
+
+ void Geometry::setNumTimeSteps (unsigned int numTimeSteps_in)
+ {
+ if (numTimeSteps_in == numTimeSteps) {
+ return;
+ }
+
+ numTimeSteps = numTimeSteps_in;
+ fnumTimeSegments = float(numTimeSteps_in-1);
+
+ Geometry::update();
+ }
+
+ void Geometry::setTimeRange (const BBox1f range)
+ {
+ time_range = range;
+ Geometry::update();
+ }
+
+ void Geometry::update()
+ {
+ ++modCounter_; // FIXME: required?
+ state = (unsigned)State::MODIFIED;
+ }
+
+ void Geometry::commit()
+ {
+ ++modCounter_;
+ state = (unsigned)State::COMMITTED;
+ }
+
+ void Geometry::preCommit()
+ {
+ if (State::MODIFIED == (State)state)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"geometry not committed");
+ }
+
+ void Geometry::postCommit()
+ {
+ }
+
+ void Geometry::enable ()
+ {
+ if (isEnabled())
+ return;
+
+ enabled = true;
+ ++modCounter_;
+ }
+
+ void Geometry::disable ()
+ {
+ if (isDisabled())
+ return;
+
+ enabled = false;
+ ++modCounter_;
+ }
+
+ void Geometry::setUserData (void* ptr)
+ {
+ userPtr = ptr;
+ }
+
+ void Geometry::setIntersectionFilterFunctionN (RTCFilterFunctionN filter)
+ {
+ if (!(getTypeMask() & (MTY_TRIANGLE_MESH | MTY_QUAD_MESH | MTY_CURVES | MTY_SUBDIV_MESH | MTY_USER_GEOMETRY | MTY_GRID_MESH)))
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"filter functions not supported for this geometry");
+
+ intersectionFilterN = filter;
+ }
+
+ void Geometry::setOcclusionFilterFunctionN (RTCFilterFunctionN filter)
+ {
+ if (!(getTypeMask() & (MTY_TRIANGLE_MESH | MTY_QUAD_MESH | MTY_CURVES | MTY_SUBDIV_MESH | MTY_USER_GEOMETRY | MTY_GRID_MESH)))
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"filter functions not supported for this geometry");
+
+ occlusionFilterN = filter;
+ }
+
+ void Geometry::setPointQueryFunction (RTCPointQueryFunction func)
+ {
+ pointQueryFunc = func;
+ }
+
+ void Geometry::interpolateN(const RTCInterpolateNArguments* const args)
+ {
+ const void* valid_i = args->valid;
+ const unsigned* primIDs = args->primIDs;
+ const float* u = args->u;
+ const float* v = args->v;
+ unsigned int N = args->N;
+ RTCBufferType bufferType = args->bufferType;
+ unsigned int bufferSlot = args->bufferSlot;
+ float* P = args->P;
+ float* dPdu = args->dPdu;
+ float* dPdv = args->dPdv;
+ float* ddPdudu = args->ddPdudu;
+ float* ddPdvdv = args->ddPdvdv;
+ float* ddPdudv = args->ddPdudv;
+ unsigned int valueCount = args->valueCount;
+
+ if (valueCount > 256) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"maximally 256 floating point values can be interpolated per vertex");
+ const int* valid = (const int*) valid_i;
+
+ __aligned(64) float P_tmp[256];
+ __aligned(64) float dPdu_tmp[256];
+ __aligned(64) float dPdv_tmp[256];
+ __aligned(64) float ddPdudu_tmp[256];
+ __aligned(64) float ddPdvdv_tmp[256];
+ __aligned(64) float ddPdudv_tmp[256];
+
+ float* Pt = P ? P_tmp : nullptr;
+ float* dPdut = nullptr, *dPdvt = nullptr;
+ if (dPdu) { dPdut = dPdu_tmp; dPdvt = dPdv_tmp; }
+ float* ddPdudut = nullptr, *ddPdvdvt = nullptr, *ddPdudvt = nullptr;
+ if (ddPdudu) { ddPdudut = ddPdudu_tmp; ddPdvdvt = ddPdvdv_tmp; ddPdudvt = ddPdudv_tmp; }
+
+ for (unsigned int i=0; i<N; i++)
+ {
+ if (valid && !valid[i]) continue;
+
+ RTCInterpolateArguments iargs;
+ iargs.primID = primIDs[i];
+ iargs.u = u[i];
+ iargs.v = v[i];
+ iargs.bufferType = bufferType;
+ iargs.bufferSlot = bufferSlot;
+ iargs.P = Pt;
+ iargs.dPdu = dPdut;
+ iargs.dPdv = dPdvt;
+ iargs.ddPdudu = ddPdudut;
+ iargs.ddPdvdv = ddPdvdvt;
+ iargs.ddPdudv = ddPdudvt;
+ iargs.valueCount = valueCount;
+ interpolate(&iargs);
+
+ if (likely(P)) {
+ for (unsigned int j=0; j<valueCount; j++)
+ P[j*N+i] = Pt[j];
+ }
+ if (likely(dPdu))
+ {
+ for (unsigned int j=0; j<valueCount; j++) {
+ dPdu[j*N+i] = dPdut[j];
+ dPdv[j*N+i] = dPdvt[j];
+ }
+ }
+ if (likely(ddPdudu))
+ {
+ for (unsigned int j=0; j<valueCount; j++) {
+ ddPdudu[j*N+i] = ddPdudut[j];
+ ddPdvdv[j*N+i] = ddPdvdvt[j];
+ ddPdudv[j*N+i] = ddPdudvt[j];
+ }
+ }
+ }
+ }
+
+ bool Geometry::pointQuery(PointQuery* query, PointQueryContext* context)
+ {
+ assert(context->primID < size());
+
+ RTCPointQueryFunctionArguments args;
+ args.query = (RTCPointQuery*)context->query_ws;
+ args.userPtr = context->userPtr;
+ args.primID = context->primID;
+ args.geomID = context->geomID;
+ args.context = context->userContext;
+ args.similarityScale = context->similarityScale;
+
+ bool update = false;
+ if(context->func) update |= context->func(&args);
+ if(pointQueryFunc) update |= pointQueryFunc(&args);
+
+ if (update && context->userContext->instStackSize > 0)
+ {
+ // update point query
+ if (context->query_type == POINT_QUERY_TYPE_AABB) {
+ context->updateAABB();
+ } else {
+ assert(context->similarityScale > 0.f);
+ query->radius = context->query_ws->radius * context->similarityScale;
+ }
+ }
+ return update;
+ }
+}
diff --git a/thirdparty/embree/kernels/common/geometry.h b/thirdparty/embree/kernels/common/geometry.h
new file mode 100644
index 0000000000..2f9f2e7c94
--- /dev/null
+++ b/thirdparty/embree/kernels/common/geometry.h
@@ -0,0 +1,582 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "device.h"
+#include "buffer.h"
+#include "../common/point_query.h"
+#include "../builders/priminfo.h"
+
+namespace embree
+{
+ class Scene;
+ class Geometry;
+
+ struct GeometryCounts
+ {
+ __forceinline GeometryCounts()
+ : numFilterFunctions(0),
+ numTriangles(0), numMBTriangles(0),
+ numQuads(0), numMBQuads(0),
+ numBezierCurves(0), numMBBezierCurves(0),
+ numLineSegments(0), numMBLineSegments(0),
+ numSubdivPatches(0), numMBSubdivPatches(0),
+ numUserGeometries(0), numMBUserGeometries(0),
+ numInstancesCheap(0), numMBInstancesCheap(0),
+ numInstancesExpensive(0), numMBInstancesExpensive(0),
+ numGrids(0), numMBGrids(0),
+ numPoints(0), numMBPoints(0) {}
+
+ __forceinline size_t size() const {
+ return numTriangles + numQuads + numBezierCurves + numLineSegments + numSubdivPatches + numUserGeometries + numInstancesCheap + numInstancesExpensive + numGrids + numPoints
+ + numMBTriangles + numMBQuads + numMBBezierCurves + numMBLineSegments + numMBSubdivPatches + numMBUserGeometries + numMBInstancesCheap + numMBInstancesExpensive + numMBGrids + numMBPoints;
+ }
+
+ __forceinline unsigned int enabledGeometryTypesMask() const
+ {
+ unsigned int mask = 0;
+ if (numTriangles) mask |= 1 << 0;
+ if (numQuads) mask |= 1 << 1;
+ if (numBezierCurves+numLineSegments) mask |= 1 << 2;
+ if (numSubdivPatches) mask |= 1 << 3;
+ if (numUserGeometries) mask |= 1 << 4;
+ if (numInstancesCheap) mask |= 1 << 5;
+ if (numInstancesExpensive) mask |= 1 << 6;
+ if (numGrids) mask |= 1 << 7;
+ if (numPoints) mask |= 1 << 8;
+
+ unsigned int maskMB = 0;
+ if (numMBTriangles) maskMB |= 1 << 0;
+ if (numMBQuads) maskMB |= 1 << 1;
+ if (numMBBezierCurves+numMBLineSegments) maskMB |= 1 << 2;
+ if (numMBSubdivPatches) maskMB |= 1 << 3;
+ if (numMBUserGeometries) maskMB |= 1 << 4;
+ if (numMBInstancesCheap) maskMB |= 1 << 5;
+ if (numMBInstancesExpensive) maskMB |= 1 << 6;
+ if (numMBGrids) maskMB |= 1 << 7;
+ if (numMBPoints) maskMB |= 1 << 8;
+
+ return (mask<<8) + maskMB;
+ }
+
+ __forceinline GeometryCounts operator+ (GeometryCounts const & rhs) const
+ {
+ GeometryCounts ret;
+ ret.numFilterFunctions = numFilterFunctions + rhs.numFilterFunctions;
+ ret.numTriangles = numTriangles + rhs.numTriangles;
+ ret.numMBTriangles = numMBTriangles + rhs.numMBTriangles;
+ ret.numQuads = numQuads + rhs.numQuads;
+ ret.numMBQuads = numMBQuads + rhs.numMBQuads;
+ ret.numBezierCurves = numBezierCurves + rhs.numBezierCurves;
+ ret.numMBBezierCurves = numMBBezierCurves + rhs.numMBBezierCurves;
+ ret.numLineSegments = numLineSegments + rhs.numLineSegments;
+ ret.numMBLineSegments = numMBLineSegments + rhs.numMBLineSegments;
+ ret.numSubdivPatches = numSubdivPatches + rhs.numSubdivPatches;
+ ret.numMBSubdivPatches = numMBSubdivPatches + rhs.numMBSubdivPatches;
+ ret.numUserGeometries = numUserGeometries + rhs.numUserGeometries;
+ ret.numMBUserGeometries = numMBUserGeometries + rhs.numMBUserGeometries;
+ ret.numInstancesCheap = numInstancesCheap + rhs.numInstancesCheap;
+ ret.numMBInstancesCheap = numMBInstancesCheap + rhs.numMBInstancesCheap;
+ ret.numInstancesExpensive = numInstancesExpensive + rhs.numInstancesExpensive;
+ ret.numMBInstancesExpensive = numMBInstancesExpensive + rhs.numMBInstancesExpensive;
+ ret.numGrids = numGrids + rhs.numGrids;
+ ret.numMBGrids = numMBGrids + rhs.numMBGrids;
+ ret.numPoints = numPoints + rhs.numPoints;
+ ret.numMBPoints = numMBPoints + rhs.numMBPoints;
+
+ return ret;
+ }
+
+ size_t numFilterFunctions; //!< number of geometries with filter functions enabled
+ size_t numTriangles; //!< number of enabled triangles
+ size_t numMBTriangles; //!< number of enabled motion blured triangles
+ size_t numQuads; //!< number of enabled quads
+ size_t numMBQuads; //!< number of enabled motion blurred quads
+ size_t numBezierCurves; //!< number of enabled curves
+ size_t numMBBezierCurves; //!< number of enabled motion blurred curves
+ size_t numLineSegments; //!< number of enabled line segments
+ size_t numMBLineSegments; //!< number of enabled line motion blurred segments
+ size_t numSubdivPatches; //!< number of enabled subdivision patches
+ size_t numMBSubdivPatches; //!< number of enabled motion blured subdivision patches
+ size_t numUserGeometries; //!< number of enabled user geometries
+ size_t numMBUserGeometries; //!< number of enabled motion blurred user geometries
+ size_t numInstancesCheap; //!< number of enabled cheap instances
+ size_t numMBInstancesCheap; //!< number of enabled motion blurred cheap instances
+ size_t numInstancesExpensive; //!< number of enabled expensive instances
+ size_t numMBInstancesExpensive; //!< number of enabled motion blurred expensive instances
+ size_t numGrids; //!< number of enabled grid geometries
+ size_t numMBGrids; //!< number of enabled motion blurred grid geometries
+ size_t numPoints; //!< number of enabled points
+ size_t numMBPoints; //!< number of enabled motion blurred points
+ };
+
+ /*! Base class all geometries are derived from */
+ class Geometry : public RefCount
+ {
+ friend class Scene;
+ public:
+
+ /*! type of geometry */
+ enum GType
+ {
+ GTY_FLAT_LINEAR_CURVE = 0,
+ GTY_ROUND_LINEAR_CURVE = 1,
+ GTY_ORIENTED_LINEAR_CURVE = 2,
+ GTY_CONE_LINEAR_CURVE = 3,
+
+ GTY_FLAT_BEZIER_CURVE = 4,
+ GTY_ROUND_BEZIER_CURVE = 5,
+ GTY_ORIENTED_BEZIER_CURVE = 6,
+
+ GTY_FLAT_BSPLINE_CURVE = 8,
+ GTY_ROUND_BSPLINE_CURVE = 9,
+ GTY_ORIENTED_BSPLINE_CURVE = 10,
+
+ GTY_FLAT_HERMITE_CURVE = 12,
+ GTY_ROUND_HERMITE_CURVE = 13,
+ GTY_ORIENTED_HERMITE_CURVE = 14,
+
+ GTY_FLAT_CATMULL_ROM_CURVE = 16,
+ GTY_ROUND_CATMULL_ROM_CURVE = 17,
+ GTY_ORIENTED_CATMULL_ROM_CURVE = 18,
+
+ GTY_TRIANGLE_MESH = 20,
+ GTY_QUAD_MESH = 21,
+ GTY_GRID_MESH = 22,
+ GTY_SUBDIV_MESH = 23,
+
+ GTY_SPHERE_POINT = 25,
+ GTY_DISC_POINT = 26,
+ GTY_ORIENTED_DISC_POINT = 27,
+
+ GTY_USER_GEOMETRY = 29,
+ GTY_INSTANCE_CHEAP = 30,
+ GTY_INSTANCE_EXPENSIVE = 31,
+ GTY_END = 32,
+
+ GTY_BASIS_LINEAR = 0,
+ GTY_BASIS_BEZIER = 4,
+ GTY_BASIS_BSPLINE = 8,
+ GTY_BASIS_HERMITE = 12,
+ GTY_BASIS_CATMULL_ROM = 16,
+ GTY_BASIS_MASK = 28,
+
+ GTY_SUBTYPE_FLAT_CURVE = 0,
+ GTY_SUBTYPE_ROUND_CURVE = 1,
+ GTY_SUBTYPE_ORIENTED_CURVE = 2,
+ GTY_SUBTYPE_MASK = 3,
+ };
+
+ enum GSubType
+ {
+ GTY_SUBTYPE_DEFAULT= 0,
+ GTY_SUBTYPE_INSTANCE_LINEAR = 0,
+ GTY_SUBTYPE_INSTANCE_QUATERNION = 1
+ };
+
+ enum GTypeMask
+ {
+ MTY_FLAT_LINEAR_CURVE = 1ul << GTY_FLAT_LINEAR_CURVE,
+ MTY_ROUND_LINEAR_CURVE = 1ul << GTY_ROUND_LINEAR_CURVE,
+ MTY_CONE_LINEAR_CURVE = 1ul << GTY_CONE_LINEAR_CURVE,
+ MTY_ORIENTED_LINEAR_CURVE = 1ul << GTY_ORIENTED_LINEAR_CURVE,
+
+ MTY_FLAT_BEZIER_CURVE = 1ul << GTY_FLAT_BEZIER_CURVE,
+ MTY_ROUND_BEZIER_CURVE = 1ul << GTY_ROUND_BEZIER_CURVE,
+ MTY_ORIENTED_BEZIER_CURVE = 1ul << GTY_ORIENTED_BEZIER_CURVE,
+
+ MTY_FLAT_BSPLINE_CURVE = 1ul << GTY_FLAT_BSPLINE_CURVE,
+ MTY_ROUND_BSPLINE_CURVE = 1ul << GTY_ROUND_BSPLINE_CURVE,
+ MTY_ORIENTED_BSPLINE_CURVE = 1ul << GTY_ORIENTED_BSPLINE_CURVE,
+
+ MTY_FLAT_HERMITE_CURVE = 1ul << GTY_FLAT_HERMITE_CURVE,
+ MTY_ROUND_HERMITE_CURVE = 1ul << GTY_ROUND_HERMITE_CURVE,
+ MTY_ORIENTED_HERMITE_CURVE = 1ul << GTY_ORIENTED_HERMITE_CURVE,
+
+ MTY_FLAT_CATMULL_ROM_CURVE = 1ul << GTY_FLAT_CATMULL_ROM_CURVE,
+ MTY_ROUND_CATMULL_ROM_CURVE = 1ul << GTY_ROUND_CATMULL_ROM_CURVE,
+ MTY_ORIENTED_CATMULL_ROM_CURVE = 1ul << GTY_ORIENTED_CATMULL_ROM_CURVE,
+
+ MTY_CURVE2 = MTY_FLAT_LINEAR_CURVE | MTY_ROUND_LINEAR_CURVE | MTY_CONE_LINEAR_CURVE | MTY_ORIENTED_LINEAR_CURVE,
+
+ MTY_CURVE4 = MTY_FLAT_BEZIER_CURVE | MTY_ROUND_BEZIER_CURVE | MTY_ORIENTED_BEZIER_CURVE |
+ MTY_FLAT_BSPLINE_CURVE | MTY_ROUND_BSPLINE_CURVE | MTY_ORIENTED_BSPLINE_CURVE |
+ MTY_FLAT_HERMITE_CURVE | MTY_ROUND_HERMITE_CURVE | MTY_ORIENTED_HERMITE_CURVE |
+ MTY_FLAT_CATMULL_ROM_CURVE | MTY_ROUND_CATMULL_ROM_CURVE | MTY_ORIENTED_CATMULL_ROM_CURVE,
+
+ MTY_SPHERE_POINT = 1ul << GTY_SPHERE_POINT,
+ MTY_DISC_POINT = 1ul << GTY_DISC_POINT,
+ MTY_ORIENTED_DISC_POINT = 1ul << GTY_ORIENTED_DISC_POINT,
+
+ MTY_POINTS = MTY_SPHERE_POINT | MTY_DISC_POINT | MTY_ORIENTED_DISC_POINT,
+
+ MTY_CURVES = MTY_CURVE2 | MTY_CURVE4 | MTY_POINTS,
+
+ MTY_TRIANGLE_MESH = 1ul << GTY_TRIANGLE_MESH,
+ MTY_QUAD_MESH = 1ul << GTY_QUAD_MESH,
+ MTY_GRID_MESH = 1ul << GTY_GRID_MESH,
+ MTY_SUBDIV_MESH = 1ul << GTY_SUBDIV_MESH,
+ MTY_USER_GEOMETRY = 1ul << GTY_USER_GEOMETRY,
+
+ MTY_INSTANCE_CHEAP = 1ul << GTY_INSTANCE_CHEAP,
+ MTY_INSTANCE_EXPENSIVE = 1ul << GTY_INSTANCE_EXPENSIVE,
+ MTY_INSTANCE = MTY_INSTANCE_CHEAP | MTY_INSTANCE_EXPENSIVE
+ };
+
+ static const char* gtype_names[GTY_END];
+
+ enum class State : unsigned {
+ MODIFIED = 0,
+ COMMITTED = 1,
+ };
+
+ public:
+
+ /*! Geometry constructor */
+ Geometry (Device* device, GType gtype, unsigned int numPrimitives, unsigned int numTimeSteps);
+
+ /*! Geometry destructor */
+ virtual ~Geometry();
+
+ public:
+
+ /*! tests if geometry is enabled */
+ __forceinline bool isEnabled() const { return enabled; }
+
+ /*! tests if geometry is disabled */
+ __forceinline bool isDisabled() const { return !isEnabled(); }
+
+ /*! tests if that geometry has some filter function set */
+ __forceinline bool hasFilterFunctions () const {
+ return (intersectionFilterN != nullptr) || (occlusionFilterN != nullptr);
+ }
+
+ /*! returns geometry type */
+ __forceinline GType getType() const { return gtype; }
+
+ /*! returns curve type */
+ __forceinline GType getCurveType() const { return (GType)(gtype & GTY_SUBTYPE_MASK); }
+
+ /*! returns curve basis */
+ __forceinline GType getCurveBasis() const { return (GType)(gtype & GTY_BASIS_MASK); }
+
+ /*! returns geometry type mask */
+ __forceinline GTypeMask getTypeMask() const { return (GTypeMask)(1 << gtype); }
+
+ /*! returns number of primitives */
+ __forceinline size_t size() const { return numPrimitives; }
+
+ /*! sets the number of primitives */
+ virtual void setNumPrimitives(unsigned int numPrimitives_in);
+
+ /*! sets number of time steps */
+ virtual void setNumTimeSteps (unsigned int numTimeSteps_in);
+
+ /*! sets motion blur time range */
+ void setTimeRange (const BBox1f range);
+
+ /*! sets number of vertex attributes */
+ virtual void setVertexAttributeCount (unsigned int N) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! sets number of topologies */
+ virtual void setTopologyCount (unsigned int N) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! sets the build quality */
+ void setBuildQuality(RTCBuildQuality quality_in)
+ {
+ this->quality = quality_in;
+ Geometry::update();
+ }
+
+ /* calculate time segment itime and fractional time ftime */
+ __forceinline int timeSegment(float time, float& ftime) const {
+ return getTimeSegment(time,time_range.lower,time_range.upper,fnumTimeSegments,ftime);
+ }
+
+ template<int N>
+ __forceinline vint<N> timeSegment(const vfloat<N>& time, vfloat<N>& ftime) const {
+ return getTimeSegment<N>(time,vfloat<N>(time_range.lower),vfloat<N>(time_range.upper),vfloat<N>(fnumTimeSegments),ftime);
+ }
+
+ /* calculate overlapping time segment range */
+ __forceinline range<int> timeSegmentRange(const BBox1f& range) const {
+ return getTimeSegmentRange(range,time_range,fnumTimeSegments);
+ }
+
+ /* returns time that corresponds to time step */
+ __forceinline float timeStep(const int i) const {
+ assert(i>=0 && i<(int)numTimeSteps);
+ return time_range.lower + time_range.size()*float(i)/fnumTimeSegments;
+ }
+
+ /*! for all geometries */
+ public:
+
+ /*! Enable geometry. */
+ virtual void enable();
+
+ /*! Update geometry. */
+ void update();
+
+ /*! commit of geometry */
+ virtual void commit();
+
+ /*! Update geometry buffer. */
+ virtual void updateBuffer(RTCBufferType type, unsigned int slot) {
+ update(); // update everything for geometries not supporting this call
+ }
+
+ /*! Disable geometry. */
+ virtual void disable();
+
+ /*! Verify the geometry */
+ virtual bool verify() { return true; }
+
+ /*! called before every build */
+ virtual void preCommit();
+
+ /*! called after every build */
+ virtual void postCommit();
+
+ virtual void addElementsToCount (GeometryCounts & counts) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ };
+
+ /*! sets constant tessellation rate for the geometry */
+ virtual void setTessellationRate(float N) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Sets the maximal curve radius scale allowed by min-width feature. */
+ virtual void setMaxRadiusScale(float s) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Set user data pointer. */
+ virtual void setUserData(void* ptr);
+
+ /*! Get user data pointer. */
+ __forceinline void* getUserData() const {
+ return userPtr;
+ }
+
+ /*! interpolates user data to the specified u/v location */
+ virtual void interpolate(const RTCInterpolateArguments* const args) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! interpolates user data to the specified u/v locations */
+ virtual void interpolateN(const RTCInterpolateNArguments* const args);
+
+ /* point query api */
+ bool pointQuery(PointQuery* query, PointQueryContext* context);
+
+ /*! for subdivision surfaces only */
+ public:
+ virtual void setSubdivisionMode (unsigned topologyID, RTCSubdivisionMode mode) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ virtual void setVertexAttributeTopology(unsigned int vertexBufferSlot, unsigned int indexBufferSlot) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Set displacement function. */
+ virtual void setDisplacementFunction (RTCDisplacementFunctionN filter) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ virtual unsigned int getFirstHalfEdge(unsigned int faceID) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ virtual unsigned int getFace(unsigned int edgeID) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ virtual unsigned int getNextHalfEdge(unsigned int edgeID) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ virtual unsigned int getPreviousHalfEdge(unsigned int edgeID) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ virtual unsigned int getOppositeHalfEdge(unsigned int topologyID, unsigned int edgeID) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! get fast access to first vertex buffer if applicable */
+ virtual float * getCompactVertexArray () const {
+ return nullptr;
+ }
+
+ /*! Returns the modified counter - how many times the geo has been modified */
+ __forceinline unsigned int getModCounter () const {
+ return modCounter_;
+ }
+
+ /*! for triangle meshes and bezier curves only */
+ public:
+
+
+ /*! Sets ray mask. */
+ virtual void setMask(unsigned mask) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Sets specified buffer. */
+ virtual void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Gets specified buffer. */
+ virtual void* getBuffer(RTCBufferType type, unsigned int slot) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Set intersection filter function for ray packets of size N. */
+ virtual void setIntersectionFilterFunctionN (RTCFilterFunctionN filterN);
+
+ /*! Set occlusion filter function for ray packets of size N. */
+ virtual void setOcclusionFilterFunctionN (RTCFilterFunctionN filterN);
+
+ /*! for instances only */
+ public:
+
+ /*! Sets the instanced scene */
+ virtual void setInstancedScene(const Ref<Scene>& scene) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Sets transformation of the instance */
+ virtual void setTransform(const AffineSpace3fa& transform, unsigned int timeStep) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Sets transformation of the instance */
+ virtual void setQuaternionDecomposition(const AffineSpace3ff& qd, unsigned int timeStep) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Returns the transformation of the instance */
+ virtual AffineSpace3fa getTransform(float time) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! for user geometries only */
+ public:
+
+ /*! Set bounds function. */
+ virtual void setBoundsFunction (RTCBoundsFunction bounds, void* userPtr) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Set intersect function for ray packets of size N. */
+ virtual void setIntersectFunctionN (RTCIntersectFunctionN intersect) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Set occlusion function for ray packets of size N. */
+ virtual void setOccludedFunctionN (RTCOccludedFunctionN occluded) {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation not supported for this geometry");
+ }
+
+ /*! Set point query function. */
+ void setPointQueryFunction(RTCPointQueryFunction func);
+
+ /*! returns number of time segments */
+ __forceinline unsigned numTimeSegments () const {
+ return numTimeSteps-1;
+ }
+
+ public:
+
+ virtual PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"createPrimRefArray not implemented for this geometry");
+ }
+
+ virtual PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"createPrimRefMBArray not implemented for this geometry");
+ }
+
+ virtual PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"createPrimRefMBArray not implemented for this geometry");
+ }
+
+ virtual LinearSpace3fa computeAlignedSpace(const size_t primID) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"computeAlignedSpace not implemented for this geometry");
+ }
+
+ virtual LinearSpace3fa computeAlignedSpaceMB(const size_t primID, const BBox1f time_range) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"computeAlignedSpace not implemented for this geometry");
+ }
+
+ virtual Vec3fa computeDirection(unsigned int primID) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"computeDirection not implemented for this geometry");
+ }
+
+ virtual Vec3fa computeDirection(unsigned int primID, size_t time) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"computeDirection not implemented for this geometry");
+ }
+
+ virtual BBox3fa vbounds(size_t primID) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vbounds not implemented for this geometry");
+ }
+
+ virtual BBox3fa vbounds(const LinearSpace3fa& space, size_t primID) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vbounds not implemented for this geometry");
+ }
+
+ virtual BBox3fa vbounds(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vbounds not implemented for this geometry");
+ }
+
+ virtual LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vlinearBounds not implemented for this geometry");
+ }
+
+ virtual LBBox3fa vlinearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vlinearBounds not implemented for this geometry");
+ }
+
+ virtual LBBox3fa vlinearBounds(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"vlinearBounds not implemented for this geometry");
+ }
+
+ public:
+ __forceinline bool hasIntersectionFilter() const { return intersectionFilterN != nullptr; }
+ __forceinline bool hasOcclusionFilter() const { return occlusionFilterN != nullptr; }
+
+ public:
+ Device* device; //!< device this geometry belongs to
+
+ void* userPtr; //!< user pointer
+ unsigned int numPrimitives; //!< number of primitives of this geometry
+
+ unsigned int numTimeSteps; //!< number of time steps
+ float fnumTimeSegments; //!< number of time segments (precalculation)
+ BBox1f time_range; //!< motion blur time range
+
+ unsigned int mask; //!< for masking out geometry
+ unsigned int modCounter_ = 1; //!< counter for every modification - used to rebuild scenes when geo is modified
+
+ struct {
+ GType gtype : 8; //!< geometry type
+ GSubType gsubtype : 8; //!< geometry subtype
+ RTCBuildQuality quality : 3; //!< build quality for geometry
+ unsigned state : 2;
+ bool enabled : 1; //!< true if geometry is enabled
+ };
+
+ RTCFilterFunctionN intersectionFilterN;
+ RTCFilterFunctionN occlusionFilterN;
+ RTCPointQueryFunction pointQueryFunc;
+ };
+}
diff --git a/thirdparty/embree/kernels/common/hit.h b/thirdparty/embree/kernels/common/hit.h
new file mode 100644
index 0000000000..fd1a9d6391
--- /dev/null
+++ b/thirdparty/embree/kernels/common/hit.h
@@ -0,0 +1,114 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "ray.h"
+#include "instance_stack.h"
+
+namespace embree
+{
+ /* Hit structure for K hits */
+ template<int K>
+ struct HitK
+ {
+ /* Default construction does nothing */
+ __forceinline HitK() {}
+
+ /* Constructs a hit */
+ __forceinline HitK(const RTCIntersectContext* context, const vuint<K>& geomID, const vuint<K>& primID, const vfloat<K>& u, const vfloat<K>& v, const Vec3vf<K>& Ng)
+ : Ng(Ng), u(u), v(v), primID(primID), geomID(geomID)
+ {
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
+ instID[l] = RTC_INVALID_GEOMETRY_ID;
+ instance_id_stack::copy_UV<K>(context->instID, instID);
+ }
+
+ /* Returns the size of the hit */
+ static __forceinline size_t size() { return K; }
+
+ public:
+ Vec3vf<K> Ng; // geometry normal
+ vfloat<K> u; // barycentric u coordinate of hit
+ vfloat<K> v; // barycentric v coordinate of hit
+ vuint<K> primID; // primitive ID
+ vuint<K> geomID; // geometry ID
+ vuint<K> instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
+ };
+
+ /* Specialization for a single hit */
+ template<>
+ struct __aligned(16) HitK<1>
+ {
+ /* Default construction does nothing */
+ __forceinline HitK() {}
+
+ /* Constructs a hit */
+ __forceinline HitK(const RTCIntersectContext* context, unsigned int geomID, unsigned int primID, float u, float v, const Vec3fa& Ng)
+ : Ng(Ng.x,Ng.y,Ng.z), u(u), v(v), primID(primID), geomID(geomID)
+ {
+ instance_id_stack::copy_UU(context->instID, instID);
+ }
+
+ /* Returns the size of the hit */
+ static __forceinline size_t size() { return 1; }
+
+ public:
+ Vec3<float> Ng; // geometry normal
+ float u; // barycentric u coordinate of hit
+ float v; // barycentric v coordinate of hit
+ unsigned int primID; // primitive ID
+ unsigned int geomID; // geometry ID
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
+ };
+
+ /* Shortcuts */
+ typedef HitK<1> Hit;
+ typedef HitK<4> Hit4;
+ typedef HitK<8> Hit8;
+ typedef HitK<16> Hit16;
+
+ /* Outputs hit to stream */
+ template<int K>
+ __forceinline embree_ostream operator<<(embree_ostream cout, const HitK<K>& ray)
+ {
+ cout << "{ " << embree_endl
+ << " Ng = " << ray.Ng << embree_endl
+ << " u = " << ray.u << embree_endl
+ << " v = " << ray.v << embree_endl
+ << " primID = " << ray.primID << embree_endl
+ << " geomID = " << ray.geomID << embree_endl
+ << " instID =";
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
+ {
+ cout << " " << ray.instID[l];
+ }
+ cout << embree_endl;
+ return cout << "}";
+ }
+
+ template<typename Hit>
+ __forceinline void copyHitToRay(RayHit& ray, const Hit& hit)
+ {
+ ray.Ng = hit.Ng;
+ ray.u = hit.u;
+ ray.v = hit.v;
+ ray.primID = hit.primID;
+ ray.geomID = hit.geomID;
+ instance_id_stack::copy_UU(hit.instID, ray.instID);
+ }
+
+ template<int K>
+ __forceinline void copyHitToRay(const vbool<K> &mask, RayHitK<K> &ray, const HitK<K> &hit)
+ {
+ vfloat<K>::storeu(mask,&ray.Ng.x, hit.Ng.x);
+ vfloat<K>::storeu(mask,&ray.Ng.y, hit.Ng.y);
+ vfloat<K>::storeu(mask,&ray.Ng.z, hit.Ng.z);
+ vfloat<K>::storeu(mask,&ray.u, hit.u);
+ vfloat<K>::storeu(mask,&ray.v, hit.v);
+ vuint<K>::storeu(mask,&ray.primID, hit.primID);
+ vuint<K>::storeu(mask,&ray.geomID, hit.geomID);
+ instance_id_stack::copy_VV<K>(hit.instID, ray.instID, mask);
+ }
+}
diff --git a/thirdparty/embree/kernels/common/instance_stack.h b/thirdparty/embree/kernels/common/instance_stack.h
new file mode 100644
index 0000000000..d3c0a643f1
--- /dev/null
+++ b/thirdparty/embree/kernels/common/instance_stack.h
@@ -0,0 +1,179 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "rtcore.h"
+
+namespace embree {
+namespace instance_id_stack {
+
+static_assert(RTC_MAX_INSTANCE_LEVEL_COUNT > 0,
+ "RTC_MAX_INSTANCE_LEVEL_COUNT must be greater than 0.");
+
+/*******************************************************************************
+ * Instance ID stack manipulation.
+ * This is used from the instance intersector.
+ ******************************************************************************/
+
+/*
+ * Push an instance to the stack.
+ */
+RTC_FORCEINLINE bool push(RTCIntersectContext* context,
+ unsigned instanceId)
+{
+#if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
+ const bool spaceAvailable = context->instStackSize < RTC_MAX_INSTANCE_LEVEL_COUNT;
+ /* We assert here because instances are silently dropped when the stack is full.
+ This might be quite hard to find in production. */
+ assert(spaceAvailable);
+ if (likely(spaceAvailable))
+ context->instID[context->instStackSize++] = instanceId;
+ return spaceAvailable;
+#else
+ const bool spaceAvailable = (context->instID[0] == RTC_INVALID_GEOMETRY_ID);
+ assert(spaceAvailable);
+ if (likely(spaceAvailable))
+ context->instID[0] = instanceId;
+ return spaceAvailable;
+#endif
+}
+
+
+/*
+ * Pop the last instance pushed to the stack.
+ * Do not call on an empty stack.
+ */
+RTC_FORCEINLINE void pop(RTCIntersectContext* context)
+{
+ assert(context);
+#if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
+ assert(context->instStackSize > 0);
+ context->instID[--context->instStackSize] = RTC_INVALID_GEOMETRY_ID;
+#else
+ assert(context->instID[0] != RTC_INVALID_GEOMETRY_ID);
+ context->instID[0] = RTC_INVALID_GEOMETRY_ID;
+#endif
+}
+
+/*
+ * Optimized instance id stack copy.
+ * The copy() functions will either copy full
+ * stacks or copy only until the last valid element has been copied, depending
+ * on RTC_MAX_INSTANCE_LEVEL_COUNT.
+ */
+RTC_FORCEINLINE void copy_UU(const unsigned* src, unsigned* tgt)
+{
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
+ tgt[0] = src[0];
+
+#else
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
+ tgt[l] = src[l];
+ if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
+ if (src[l] == RTC_INVALID_GEOMETRY_ID)
+ break;
+ }
+#endif
+}
+
+template <int K>
+RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint<K>* tgt)
+{
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
+ tgt[0] = src[0];
+
+#else
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
+ tgt[l] = src[l];
+ if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
+ if (src[l] == RTC_INVALID_GEOMETRY_ID)
+ break;
+ }
+#endif
+}
+
+template <int K>
+RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint<K>* tgt, size_t j)
+{
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
+ tgt[0][j] = src[0];
+
+#else
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
+ tgt[l][j] = src[l];
+ if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
+ if (src[l] == RTC_INVALID_GEOMETRY_ID)
+ break;
+ }
+#endif
+}
+
+template <int K>
+RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint<K>* tgt, const vbool<K>& mask)
+{
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
+ vuint<K>::store(mask, tgt, src[0]);
+
+#else
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
+ vuint<K>::store(mask, tgt + l, src[l]);
+ if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
+ if (src[l] == RTC_INVALID_GEOMETRY_ID)
+ break;
+ }
+#endif
+}
+
+template <int K>
+RTC_FORCEINLINE void copy_VU(const vuint<K>* src, unsigned* tgt, size_t i)
+{
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
+ tgt[0] = src[0][i];
+
+#else
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
+ tgt[l] = src[l][i];
+ if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
+ if (src[l][i] == RTC_INVALID_GEOMETRY_ID)
+ break;
+ }
+#endif
+}
+
+template <int K>
+RTC_FORCEINLINE void copy_VV(const vuint<K>* src, vuint<K>* tgt, size_t i, size_t j)
+{
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
+ tgt[0][j] = src[0][i];
+
+#else
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
+ tgt[l][j] = src[l][i];
+ if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
+ if (src[l][i] == RTC_INVALID_GEOMETRY_ID)
+ break;
+ }
+#endif
+}
+
+template <int K>
+RTC_FORCEINLINE void copy_VV(const vuint<K>* src, vuint<K>* tgt, const vbool<K>& mask)
+{
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
+ vuint<K>::store(mask, tgt, src[0]);
+
+#else
+ vbool<K> done = !mask;
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
+ vuint<K>::store(mask, tgt + l, src[l]);
+ if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) {
+ done |= src[l] == RTC_INVALID_GEOMETRY_ID;
+ if (all(done)) break;
+ }
+ }
+#endif
+}
+
+} // namespace instance_id_stack
+} // namespace embree
diff --git a/thirdparty/embree/kernels/common/isa.h b/thirdparty/embree/kernels/common/isa.h
new file mode 100644
index 0000000000..ae6556336c
--- /dev/null
+++ b/thirdparty/embree/kernels/common/isa.h
@@ -0,0 +1,246 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../../common/sys/platform.h"
+#include "../../common/sys/sysinfo.h"
+
+namespace embree
+{
+#define DEFINE_SYMBOL2(type,name) \
+ typedef type (*name##Func)(); \
+ name##Func name;
+
+#define DECLARE_SYMBOL2(type,name) \
+ namespace sse2 { extern type name(); } \
+ namespace sse42 { extern type name(); } \
+ namespace avx { extern type name(); } \
+ namespace avx2 { extern type name(); } \
+ namespace avx512 { extern type name(); } \
+ void name##_error2() { throw_RTCError(RTC_ERROR_UNKNOWN,"internal error in ISA selection for " TOSTRING(name)); } \
+ type name##_error() { return type(name##_error2); } \
+ type name##_zero() { return type(nullptr); }
+
+#define DECLARE_ISA_FUNCTION(type,symbol,args) \
+ namespace sse2 { extern type symbol(args); } \
+ namespace sse42 { extern type symbol(args); } \
+ namespace avx { extern type symbol(args); } \
+ namespace avx2 { extern type symbol(args); } \
+ namespace avx512 { extern type symbol(args); } \
+ inline type symbol##_error(args) { throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"function " TOSTRING(symbol) " not supported by your CPU"); } \
+ typedef type (*symbol##Ty)(args); \
+
+#define DEFINE_ISA_FUNCTION(type,symbol,args) \
+ typedef type (*symbol##Func)(args); \
+ symbol##Func symbol;
+
+#define ZERO_SYMBOL(features,intersector) \
+ intersector = intersector##_zero;
+
+#define INIT_SYMBOL(features,intersector) \
+ intersector = decltype(intersector)(intersector##_error);
+
+#define SELECT_SYMBOL_DEFAULT(features,intersector) \
+ intersector = isa::intersector;
+
+#if defined(__SSE__)
+#if !defined(EMBREE_TARGET_SIMD4)
+#define EMBREE_TARGET_SIMD4
+#endif
+#endif
+
+#if defined(EMBREE_TARGET_SSE42)
+#define SELECT_SYMBOL_SSE42(features,intersector) \
+ if ((features & SSE42) == SSE42) intersector = sse42::intersector;
+#else
+#define SELECT_SYMBOL_SSE42(features,intersector)
+#endif
+
+#if defined(EMBREE_TARGET_AVX) || defined(__AVX__)
+#if !defined(EMBREE_TARGET_SIMD8)
+#define EMBREE_TARGET_SIMD8
+#endif
+#if defined(__AVX__) // if default ISA is >= AVX we treat AVX target as default target
+#define SELECT_SYMBOL_AVX(features,intersector) \
+ if ((features & ISA) == ISA) intersector = isa::intersector;
+#else
+#define SELECT_SYMBOL_AVX(features,intersector) \
+ if ((features & AVX) == AVX) intersector = avx::intersector;
+#endif
+#else
+#define SELECT_SYMBOL_AVX(features,intersector)
+#endif
+
+#if defined(EMBREE_TARGET_AVX2)
+#if !defined(EMBREE_TARGET_SIMD8)
+#define EMBREE_TARGET_SIMD8
+#endif
+#define SELECT_SYMBOL_AVX2(features,intersector) \
+ if ((features & AVX2) == AVX2) intersector = avx2::intersector;
+#else
+#define SELECT_SYMBOL_AVX2(features,intersector)
+#endif
+
+#if defined(EMBREE_TARGET_AVX512)
+#if !defined(EMBREE_TARGET_SIMD16)
+#define EMBREE_TARGET_SIMD16
+#endif
+#define SELECT_SYMBOL_AVX512(features,intersector) \
+ if ((features & AVX512) == AVX512) intersector = avx512::intersector;
+#else
+#define SELECT_SYMBOL_AVX512(features,intersector)
+#endif
+
+#define SELECT_SYMBOL_DEFAULT_SSE42(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_SSE42_AVX(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_AVX(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_AVX_AVX2(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_AVX(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_AVX_AVX512(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_AVX_AVX512(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_INIT_AVX(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector);
+
+#define SELECT_SYMBOL_INIT_AVX_AVX2(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector);
+
+#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector);
+
+#define SELECT_SYMBOL_INIT_AVX(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector);
+
+#define SELECT_SYMBOL_INIT_AVX_AVX512(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_INIT_AVX_AVX2(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector);
+
+#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2_AVX512(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_ZERO_SSE42_AVX_AVX2_AVX512(features,intersector) \
+ ZERO_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,intersector) \
+ SELECT_SYMBOL_DEFAULT(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_INIT_AVX512(features,intersector) \
+ INIT_SYMBOL(features,intersector); \
+ SELECT_SYMBOL_AVX512(features,intersector);
+
+#define SELECT_SYMBOL_SSE42_AVX_AVX2(features,intersector) \
+ SELECT_SYMBOL_SSE42(features,intersector); \
+ SELECT_SYMBOL_AVX(features,intersector); \
+ SELECT_SYMBOL_AVX2(features,intersector);
+
+ struct VerifyMultiTargetLinking {
+ static __noinline int getISA(int depth = 5) {
+ if (depth == 0) return ISA;
+ else return getISA(depth-1);
+ }
+ };
+ namespace sse2 { int getISA(); };
+ namespace sse42 { int getISA(); };
+ namespace avx { int getISA(); };
+ namespace avx2 { int getISA(); };
+ namespace avx512 { int getISA(); };
+}
diff --git a/thirdparty/embree/kernels/common/motion_derivative.h b/thirdparty/embree/kernels/common/motion_derivative.h
new file mode 100644
index 0000000000..c619d6a675
--- /dev/null
+++ b/thirdparty/embree/kernels/common/motion_derivative.h
@@ -0,0 +1,325 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../../common/math/affinespace.h"
+#include "../../common/math/interval.h"
+
+#include <functional>
+
+namespace embree {
+
+#define MOTION_DERIVATIVE_ROOT_EPSILON 1e-4f
+
+static void motion_derivative_coefficients(const float *p, float *coeff);
+
+struct MotionDerivativeCoefficients
+{
+ float theta;
+ float coeffs[3*8*7];
+
+ MotionDerivativeCoefficients() {}
+
+ // xfm0 and xfm1 are interpret as quaternion decomposition
+ MotionDerivativeCoefficients(AffineSpace3ff const& xfm0, AffineSpace3ff const& xfm1)
+ {
+ // cosTheta of the two quaternions
+ const float cosTheta = min(1.f, max(-1.f,
+ xfm0.l.vx.w * xfm1.l.vx.w
+ + xfm0.l.vy.w * xfm1.l.vy.w
+ + xfm0.l.vz.w * xfm1.l.vz.w
+ + xfm0.p.w * xfm1.p.w));
+
+ theta = std::acos(cosTheta);
+ Vec4f qperp(xfm1.p.w, xfm1.l.vx.w, xfm1.l.vy.w, xfm1.l.vz.w);
+ if (cosTheta < 0.995f) {
+ // compute perpendicular quaternion
+ qperp.x = xfm1.p.w - cosTheta * xfm0.p.w;
+ qperp.y = xfm1.l.vx.w - cosTheta * xfm0.l.vx.w;
+ qperp.z = xfm1.l.vy.w - cosTheta * xfm0.l.vy.w;
+ qperp.w = xfm1.l.vz.w - cosTheta * xfm0.l.vz.w;
+ qperp = normalize(qperp);
+ }
+ const float p[33] = {
+ theta,
+ xfm0.l.vx.y, xfm0.l.vx.z, xfm0.l.vy.z, // translation component of xfm0
+ xfm1.l.vx.y, xfm1.l.vx.z, xfm1.l.vy.z, // translation component of xfm1
+ xfm0.p.w, xfm0.l.vx.w, xfm0.l.vy.w, xfm0.l.vz.w, // quaternion of xfm0
+ qperp.x, qperp.y, qperp.z, qperp.w,
+ xfm0.l.vx.x, xfm0.l.vy.x, xfm0.l.vz.x, xfm0.p.x, // scale/skew component of xfm0
+ xfm0.l.vy.y, xfm0.l.vz.y, xfm0.p.y,
+ xfm0.l.vz.z, xfm0.p.z,
+ xfm1.l.vx.x, xfm1.l.vy.x, xfm1.l.vz.x, xfm1.p.x, // scale/skew component of xfm1
+ xfm1.l.vy.y, xfm1.l.vz.y, xfm1.p.y,
+ xfm1.l.vz.z, xfm1.p.z
+ };
+ motion_derivative_coefficients(p, coeffs);
+ }
+};
+
+struct MotionDerivative
+{
+ float twoTheta;
+ float c[8];
+
+ MotionDerivative(MotionDerivativeCoefficients const& mdc,
+ int dim, Vec3fa const& p0, Vec3fa const& p1)
+ : twoTheta(2.f*mdc.theta)
+ {
+ const float p[7] = { 1, p0.x, p0.y, p0.z, p1.x, p1.y, p1.z };
+ for (int i = 0; i < 8; ++i) {
+ c[i] = 0;
+ for (int j = 0; j < 7; ++j) {
+ c[i] += mdc.coeffs[8*7*dim + i*7 + j] * p[j];
+ }
+ }
+ }
+
+ template<typename T>
+ struct EvalMotionDerivative
+ {
+ MotionDerivative const& md;
+ float offset;
+
+ EvalMotionDerivative(MotionDerivative const& md, float offset) : md(md), offset(offset) {}
+
+ T operator()(T const& time) const {
+ return md.c[0] + md.c[1] * time
+ + (md.c[2] + md.c[3] * time + md.c[4] * time * time) * cos(md.twoTheta * time)
+ + (md.c[5] + md.c[6] * time + md.c[7] * time * time) * sin(md.twoTheta * time)
+ + offset;
+ }
+ };
+
+ unsigned int findRoots(
+ Interval1f const& interval,
+ float offset,
+ float* roots,
+ unsigned int maxNumRoots)
+ {
+ unsigned int numRoots = 0;
+ EvalMotionDerivative<Interval1f> eval(*this, offset);
+ findRoots(eval, interval, numRoots, roots, maxNumRoots);
+ return numRoots;
+ }
+
+ template<typename Eval>
+ static void findRoots(
+
+ Eval const& eval,
+ Interval1f const& interval,
+ unsigned int& numRoots,
+ float* roots,
+ unsigned int maxNumRoots)
+ {
+ Interval1f range = eval(interval);
+ if (range.lower > 0 || range.upper < 0 || range.lower >= range.upper) return;
+
+ const float split = 0.5f * (interval.upper + interval.lower);
+ if (interval.upper-interval.lower < 1e-7f || abs(split-interval.lower) < 1e-7f || abs(split-interval.upper) < 1e-7f)
+ {
+ // check if the root already exists
+ for (unsigned int k = 0; k < numRoots && k < maxNumRoots; ++k) {
+ if (abs(roots[k]-split) < MOTION_DERIVATIVE_ROOT_EPSILON)
+ return;
+ }
+ if (numRoots < maxNumRoots) {
+ roots[numRoots++] = split;
+ }
+ if (numRoots > maxNumRoots) {
+ printf("error: more roots than expected\n"); // FIXME: workaround for ICC2019.4 compiler bug under macOS
+ return;
+ }
+ return;
+ }
+
+ findRoots(eval, Interval1f(interval.lower, split), numRoots, roots, maxNumRoots);
+ findRoots(eval, Interval1f(split, interval.upper), numRoots, roots, maxNumRoots);
+ }
+};
+
+/******************************************************************************
+ * Code generated with sympy 1.4 *
+ * See http://www.sympy.org/ for more information. *
+ * *
+ * see *
+ * *
+ * scripts/generate_motion_derivative_coefficients.py *
+ * *
+ * for how this code is generated *
+ * *
+ ******************************************************************************/
+static void motion_derivative_coefficients(const float *p, float *coeff)
+{
+ coeff[0] = -p[1] + p[4] - p[7]*p[9]*p[23] + p[7]*p[9]*p[32] + p[7]*p[10]*p[21] - p[7]*p[10]*p[30] - p[8]*p[9]*p[21] + p[8]*p[9]*p[30] - p[8]*p[10]*p[23] + p[8]*p[10]*p[32] + p[9]*p[9]*p[18] - p[9]*p[9]*p[27] + p[10]*p[10]*p[18] - p[10]*p[10]*p[27] - p[11]*p[13]*p[23] + p[11]*p[13]*p[32] + p[11]*p[14]*p[21] - p[11]*p[14]*p[30] - p[12]*p[13]*p[21] + p[12]*p[13]*p[30] - p[12]*p[14]*p[23] + p[12]*p[14]*p[32] + p[13]*p[13]*p[18] - p[13]*p[13]*p[27] + p[14]*p[14]*p[18] - p[14]*p[14]*p[27] - p[18] + p[27];
+ coeff[1] = 2*p[9]*p[9]*p[15] - p[9]*p[9]*p[24] + 2*p[10]*p[10]*p[15] - p[10]*p[10]*p[24] + 2*p[13]*p[13]*p[15] - p[13]*p[13]*p[24] + 2*p[14]*p[14]*p[15] - p[14]*p[14]*p[24] - 2*p[15] + p[24];
+ coeff[2] = 2*p[7]*p[10]*p[19] - p[7]*p[10]*p[28] - 2*p[8]*p[9]*p[19] + p[8]*p[9]*p[28] + 2*p[9]*p[9]*p[16] - p[9]*p[9]*p[25] + 2*p[10]*p[10]*p[16] - p[10]*p[10]*p[25] + 2*p[11]*p[14]*p[19] - p[11]*p[14]*p[28] - 2*p[12]*p[13]*p[19] + p[12]*p[13]*p[28] + 2*p[13]*p[13]*p[16] - p[13]*p[13]*p[25] + 2*p[14]*p[14]*p[16] - p[14]*p[14]*p[25] - 2*p[16] + p[25];
+ coeff[3] = -2*p[7]*p[9]*p[22] + p[7]*p[9]*p[31] + 2*p[7]*p[10]*p[20] - p[7]*p[10]*p[29] - 2*p[8]*p[9]*p[20] + p[8]*p[9]*p[29] - 2*p[8]*p[10]*p[22] + p[8]*p[10]*p[31] + 2*p[9]*p[9]*p[17] - p[9]*p[9]*p[26] + 2*p[10]*p[10]*p[17] - p[10]*p[10]*p[26] - 2*p[11]*p[13]*p[22] + p[11]*p[13]*p[31] + 2*p[11]*p[14]*p[20] - p[11]*p[14]*p[29] - 2*p[12]*p[13]*p[20] + p[12]*p[13]*p[29] - 2*p[12]*p[14]*p[22] + p[12]*p[14]*p[31] + 2*p[13]*p[13]*p[17] - p[13]*p[13]*p[26] + 2*p[14]*p[14]*p[17] - p[14]*p[14]*p[26] - 2*p[17] + p[26];
+ coeff[4] = (-p[9]*p[9] - p[10]*p[10] - p[13]*p[13] - p[14]*p[14] + 1)*p[15];
+ coeff[5] = -p[7]*p[10]*p[19] + p[8]*p[9]*p[19] - p[9]*p[9]*p[16] - p[10]*p[10]*p[16] - p[11]*p[14]*p[19] + p[12]*p[13]*p[19] - p[13]*p[13]*p[16] - p[14]*p[14]*p[16] + p[16];
+ coeff[6] = p[7]*p[9]*p[22] - p[7]*p[10]*p[20] + p[8]*p[9]*p[20] + p[8]*p[10]*p[22] - p[9]*p[9]*p[17] - p[10]*p[10]*p[17] + p[11]*p[13]*p[22] - p[11]*p[14]*p[20] + p[12]*p[13]*p[20] + p[12]*p[14]*p[22] - p[13]*p[13]*p[17] - p[14]*p[14]*p[17] + p[17];
+ coeff[7] = 0;
+ coeff[8] = -2*p[9]*p[9]*p[15] + 2*p[9]*p[9]*p[24] - 2*p[10]*p[10]*p[15] + 2*p[10]*p[10]*p[24] - 2*p[13]*p[13]*p[15] + 2*p[13]*p[13]*p[24] - 2*p[14]*p[14]*p[15] + 2*p[14]*p[14]*p[24] + 2*p[15] - 2*p[24];
+ coeff[9] = -2*p[7]*p[10]*p[19] + 2*p[7]*p[10]*p[28] + 2*p[8]*p[9]*p[19] - 2*p[8]*p[9]*p[28] - 2*p[9]*p[9]*p[16] + 2*p[9]*p[9]*p[25] - 2*p[10]*p[10]*p[16] + 2*p[10]*p[10]*p[25] - 2*p[11]*p[14]*p[19] + 2*p[11]*p[14]*p[28] + 2*p[12]*p[13]*p[19] - 2*p[12]*p[13]*p[28] - 2*p[13]*p[13]*p[16] + 2*p[13]*p[13]*p[25] - 2*p[14]*p[14]*p[16] + 2*p[14]*p[14]*p[25] + 2*p[16] - 2*p[25];
+ coeff[10] = 2*p[7]*p[9]*p[22] - 2*p[7]*p[9]*p[31] - 2*p[7]*p[10]*p[20] + 2*p[7]*p[10]*p[29] + 2*p[8]*p[9]*p[20] - 2*p[8]*p[9]*p[29] + 2*p[8]*p[10]*p[22] - 2*p[8]*p[10]*p[31] - 2*p[9]*p[9]*p[17] + 2*p[9]*p[9]*p[26] - 2*p[10]*p[10]*p[17] + 2*p[10]*p[10]*p[26] + 2*p[11]*p[13]*p[22] - 2*p[11]*p[13]*p[31] - 2*p[11]*p[14]*p[20] + 2*p[11]*p[14]*p[29] + 2*p[12]*p[13]*p[20] - 2*p[12]*p[13]*p[29] + 2*p[12]*p[14]*p[22] - 2*p[12]*p[14]*p[31] - 2*p[13]*p[13]*p[17] + 2*p[13]*p[13]*p[26] - 2*p[14]*p[14]*p[17] + 2*p[14]*p[14]*p[26] + 2*p[17] - 2*p[26];
+ coeff[11] = 2*p[9]*p[9]*p[15] - 2*p[9]*p[9]*p[24] + 2*p[10]*p[10]*p[15] - 2*p[10]*p[10]*p[24] + 2*p[13]*p[13]*p[15] - 2*p[13]*p[13]*p[24] + 2*p[14]*p[14]*p[15] - 2*p[14]*p[14]*p[24] - 2*p[15] + 2*p[24];
+ coeff[12] = 2*p[7]*p[10]*p[19] - 2*p[7]*p[10]*p[28] - 2*p[8]*p[9]*p[19] + 2*p[8]*p[9]*p[28] + 2*p[9]*p[9]*p[16] - 2*p[9]*p[9]*p[25] + 2*p[10]*p[10]*p[16] - 2*p[10]*p[10]*p[25] + 2*p[11]*p[14]*p[19] - 2*p[11]*p[14]*p[28] - 2*p[12]*p[13]*p[19] + 2*p[12]*p[13]*p[28] + 2*p[13]*p[13]*p[16] - 2*p[13]*p[13]*p[25] + 2*p[14]*p[14]*p[16] - 2*p[14]*p[14]*p[25] - 2*p[16] + 2*p[25];
+ coeff[13] = -2*p[7]*p[9]*p[22] + 2*p[7]*p[9]*p[31] + 2*p[7]*p[10]*p[20] - 2*p[7]*p[10]*p[29] - 2*p[8]*p[9]*p[20] + 2*p[8]*p[9]*p[29] - 2*p[8]*p[10]*p[22] + 2*p[8]*p[10]*p[31] + 2*p[9]*p[9]*p[17] - 2*p[9]*p[9]*p[26] + 2*p[10]*p[10]*p[17] - 2*p[10]*p[10]*p[26] - 2*p[11]*p[13]*p[22] + 2*p[11]*p[13]*p[31] + 2*p[11]*p[14]*p[20] - 2*p[11]*p[14]*p[29] - 2*p[12]*p[13]*p[20] + 2*p[12]*p[13]*p[29] - 2*p[12]*p[14]*p[22] + 2*p[12]*p[14]*p[31] + 2*p[13]*p[13]*p[17] - 2*p[13]*p[13]*p[26] + 2*p[14]*p[14]*p[17] - 2*p[14]*p[14]*p[26] - 2*p[17] + 2*p[26];
+ coeff[14] = 2*p[0]*p[7]*p[11]*p[18] + 2*p[0]*p[7]*p[13]*p[23] - 2*p[0]*p[7]*p[14]*p[21] + 2*p[0]*p[8]*p[12]*p[18] + 2*p[0]*p[8]*p[13]*p[21] + 2*p[0]*p[8]*p[14]*p[23] + 2*p[0]*p[9]*p[11]*p[23] + 2*p[0]*p[9]*p[12]*p[21] - 2*p[0]*p[9]*p[13]*p[18] - 2*p[0]*p[10]*p[11]*p[21] + 2*p[0]*p[10]*p[12]*p[23] - 2*p[0]*p[10]*p[14]*p[18] - p[7]*p[9]*p[23] + p[7]*p[9]*p[32] + p[7]*p[10]*p[21] - p[7]*p[10]*p[30] - p[8]*p[9]*p[21] + p[8]*p[9]*p[30] - p[8]*p[10]*p[23] + p[8]*p[10]*p[32] + p[9]*p[9]*p[18] - p[9]*p[9]*p[27] + p[10]*p[10]*p[18] - p[10]*p[10]*p[27] + p[11]*p[13]*p[23] - p[11]*p[13]*p[32] - p[11]*p[14]*p[21] + p[11]*p[14]*p[30] + p[12]*p[13]*p[21] - p[12]*p[13]*p[30] + p[12]*p[14]*p[23] - p[12]*p[14]*p[32] - p[13]*p[13]*p[18] + p[13]*p[13]*p[27] - p[14]*p[14]*p[18] + p[14]*p[14]*p[27];
+ coeff[15] = 2*p[0]*p[7]*p[11]*p[15] + 2*p[0]*p[8]*p[12]*p[15] - 2*p[0]*p[9]*p[13]*p[15] - 2*p[0]*p[10]*p[14]*p[15] + 2*p[9]*p[9]*p[15] - p[9]*p[9]*p[24] + 2*p[10]*p[10]*p[15] - p[10]*p[10]*p[24] - 2*p[13]*p[13]*p[15] + p[13]*p[13]*p[24] - 2*p[14]*p[14]*p[15] + p[14]*p[14]*p[24];
+ coeff[16] = 2*p[0]*p[7]*p[11]*p[16] - 2*p[0]*p[7]*p[14]*p[19] + 2*p[0]*p[8]*p[12]*p[16] + 2*p[0]*p[8]*p[13]*p[19] + 2*p[0]*p[9]*p[12]*p[19] - 2*p[0]*p[9]*p[13]*p[16] - 2*p[0]*p[10]*p[11]*p[19] - 2*p[0]*p[10]*p[14]*p[16] + 2*p[7]*p[10]*p[19] - p[7]*p[10]*p[28] - 2*p[8]*p[9]*p[19] + p[8]*p[9]*p[28] + 2*p[9]*p[9]*p[16] - p[9]*p[9]*p[25] + 2*p[10]*p[10]*p[16] - p[10]*p[10]*p[25] - 2*p[11]*p[14]*p[19] + p[11]*p[14]*p[28] + 2*p[12]*p[13]*p[19] - p[12]*p[13]*p[28] - 2*p[13]*p[13]*p[16] + p[13]*p[13]*p[25] - 2*p[14]*p[14]*p[16] + p[14]*p[14]*p[25];
+ coeff[17] = 2*p[0]*p[7]*p[11]*p[17] + 2*p[0]*p[7]*p[13]*p[22] - 2*p[0]*p[7]*p[14]*p[20] + 2*p[0]*p[8]*p[12]*p[17] + 2*p[0]*p[8]*p[13]*p[20] + 2*p[0]*p[8]*p[14]*p[22] + 2*p[0]*p[9]*p[11]*p[22] + 2*p[0]*p[9]*p[12]*p[20] - 2*p[0]*p[9]*p[13]*p[17] - 2*p[0]*p[10]*p[11]*p[20] + 2*p[0]*p[10]*p[12]*p[22] - 2*p[0]*p[10]*p[14]*p[17] - 2*p[7]*p[9]*p[22] + p[7]*p[9]*p[31] + 2*p[7]*p[10]*p[20] - p[7]*p[10]*p[29] - 2*p[8]*p[9]*p[20] + p[8]*p[9]*p[29] - 2*p[8]*p[10]*p[22] + p[8]*p[10]*p[31] + 2*p[9]*p[9]*p[17] - p[9]*p[9]*p[26] + 2*p[10]*p[10]*p[17] - p[10]*p[10]*p[26] + 2*p[11]*p[13]*p[22] - p[11]*p[13]*p[31] - 2*p[11]*p[14]*p[20] + p[11]*p[14]*p[29] + 2*p[12]*p[13]*p[20] - p[12]*p[13]*p[29] + 2*p[12]*p[14]*p[22] - p[12]*p[14]*p[31] - 2*p[13]*p[13]*p[17] + p[13]*p[13]*p[26] - 2*p[14]*p[14]*p[17] + p[14]*p[14]*p[26];
+ coeff[18] = (-p[9]*p[9] - p[10]*p[10] + p[13]*p[13] + p[14]*p[14])*p[15];
+ coeff[19] = -p[7]*p[10]*p[19] + p[8]*p[9]*p[19] - p[9]*p[9]*p[16] - p[10]*p[10]*p[16] + p[11]*p[14]*p[19] - p[12]*p[13]*p[19] + p[13]*p[13]*p[16] + p[14]*p[14]*p[16];
+ coeff[20] = p[7]*p[9]*p[22] - p[7]*p[10]*p[20] + p[8]*p[9]*p[20] + p[8]*p[10]*p[22] - p[9]*p[9]*p[17] - p[10]*p[10]*p[17] - p[11]*p[13]*p[22] + p[11]*p[14]*p[20] - p[12]*p[13]*p[20] - p[12]*p[14]*p[22] + p[13]*p[13]*p[17] + p[14]*p[14]*p[17];
+ coeff[21] = 2*(-p[7]*p[11]*p[18] + p[7]*p[11]*p[27] - p[7]*p[13]*p[23] + p[7]*p[13]*p[32] + p[7]*p[14]*p[21] - p[7]*p[14]*p[30] - p[8]*p[12]*p[18] + p[8]*p[12]*p[27] - p[8]*p[13]*p[21] + p[8]*p[13]*p[30] - p[8]*p[14]*p[23] + p[8]*p[14]*p[32] - p[9]*p[11]*p[23] + p[9]*p[11]*p[32] - p[9]*p[12]*p[21] + p[9]*p[12]*p[30] + p[9]*p[13]*p[18] - p[9]*p[13]*p[27] + p[10]*p[11]*p[21] - p[10]*p[11]*p[30] - p[10]*p[12]*p[23] + p[10]*p[12]*p[32] + p[10]*p[14]*p[18] - p[10]*p[14]*p[27])*p[0];
+ coeff[22] = -4*p[0]*p[7]*p[11]*p[15] + 2*p[0]*p[7]*p[11]*p[24] - 4*p[0]*p[8]*p[12]*p[15] + 2*p[0]*p[8]*p[12]*p[24] + 4*p[0]*p[9]*p[13]*p[15] - 2*p[0]*p[9]*p[13]*p[24] + 4*p[0]*p[10]*p[14]*p[15] - 2*p[0]*p[10]*p[14]*p[24] - 2*p[9]*p[9]*p[15] + 2*p[9]*p[9]*p[24] - 2*p[10]*p[10]*p[15] + 2*p[10]*p[10]*p[24] + 2*p[13]*p[13]*p[15] - 2*p[13]*p[13]*p[24] + 2*p[14]*p[14]*p[15] - 2*p[14]*p[14]*p[24];
+ coeff[23] = -4*p[0]*p[7]*p[11]*p[16] + 2*p[0]*p[7]*p[11]*p[25] + 4*p[0]*p[7]*p[14]*p[19] - 2*p[0]*p[7]*p[14]*p[28] - 4*p[0]*p[8]*p[12]*p[16] + 2*p[0]*p[8]*p[12]*p[25] - 4*p[0]*p[8]*p[13]*p[19] + 2*p[0]*p[8]*p[13]*p[28] - 4*p[0]*p[9]*p[12]*p[19] + 2*p[0]*p[9]*p[12]*p[28] + 4*p[0]*p[9]*p[13]*p[16] - 2*p[0]*p[9]*p[13]*p[25] + 4*p[0]*p[10]*p[11]*p[19] - 2*p[0]*p[10]*p[11]*p[28] + 4*p[0]*p[10]*p[14]*p[16] - 2*p[0]*p[10]*p[14]*p[25] - 2*p[7]*p[10]*p[19] + 2*p[7]*p[10]*p[28] + 2*p[8]*p[9]*p[19] - 2*p[8]*p[9]*p[28] - 2*p[9]*p[9]*p[16] + 2*p[9]*p[9]*p[25] - 2*p[10]*p[10]*p[16] + 2*p[10]*p[10]*p[25] + 2*p[11]*p[14]*p[19] - 2*p[11]*p[14]*p[28] - 2*p[12]*p[13]*p[19] + 2*p[12]*p[13]*p[28] + 2*p[13]*p[13]*p[16] - 2*p[13]*p[13]*p[25] + 2*p[14]*p[14]*p[16] - 2*p[14]*p[14]*p[25];
+ coeff[24] = -4*p[0]*p[7]*p[11]*p[17] + 2*p[0]*p[7]*p[11]*p[26] - 4*p[0]*p[7]*p[13]*p[22] + 2*p[0]*p[7]*p[13]*p[31] + 4*p[0]*p[7]*p[14]*p[20] - 2*p[0]*p[7]*p[14]*p[29] - 4*p[0]*p[8]*p[12]*p[17] + 2*p[0]*p[8]*p[12]*p[26] - 4*p[0]*p[8]*p[13]*p[20] + 2*p[0]*p[8]*p[13]*p[29] - 4*p[0]*p[8]*p[14]*p[22] + 2*p[0]*p[8]*p[14]*p[31] - 4*p[0]*p[9]*p[11]*p[22] + 2*p[0]*p[9]*p[11]*p[31] - 4*p[0]*p[9]*p[12]*p[20] + 2*p[0]*p[9]*p[12]*p[29] + 4*p[0]*p[9]*p[13]*p[17] - 2*p[0]*p[9]*p[13]*p[26] + 4*p[0]*p[10]*p[11]*p[20] - 2*p[0]*p[10]*p[11]*p[29] - 4*p[0]*p[10]*p[12]*p[22] + 2*p[0]*p[10]*p[12]*p[31] + 4*p[0]*p[10]*p[14]*p[17] - 2*p[0]*p[10]*p[14]*p[26] + 2*p[7]*p[9]*p[22] - 2*p[7]*p[9]*p[31] - 2*p[7]*p[10]*p[20] + 2*p[7]*p[10]*p[29] + 2*p[8]*p[9]*p[20] - 2*p[8]*p[9]*p[29] + 2*p[8]*p[10]*p[22] - 2*p[8]*p[10]*p[31] - 2*p[9]*p[9]*p[17] + 2*p[9]*p[9]*p[26] - 2*p[10]*p[10]*p[17] + 2*p[10]*p[10]*p[26] - 2*p[11]*p[13]*p[22] + 2*p[11]*p[13]*p[31] + 2*p[11]*p[14]*p[20] - 2*p[11]*p[14]*p[29] - 2*p[12]*p[13]*p[20] + 2*p[12]*p[13]*p[29] - 2*p[12]*p[14]*p[22] + 2*p[12]*p[14]*p[31] + 2*p[13]*p[13]*p[17] - 2*p[13]*p[13]*p[26] + 2*p[14]*p[14]*p[17] - 2*p[14]*p[14]*p[26];
+ coeff[25] = 2*p[0]*p[7]*p[11]*p[15] + 2*p[0]*p[8]*p[12]*p[15] - 2*p[0]*p[9]*p[13]*p[15] - 2*p[0]*p[10]*p[14]*p[15] + 2*p[9]*p[9]*p[15] - 2*p[9]*p[9]*p[24] + 2*p[10]*p[10]*p[15] - 2*p[10]*p[10]*p[24] - 2*p[13]*p[13]*p[15] + 2*p[13]*p[13]*p[24] - 2*p[14]*p[14]*p[15] + 2*p[14]*p[14]*p[24];
+ coeff[26] = 2*p[0]*p[7]*p[11]*p[16] - 2*p[0]*p[7]*p[14]*p[19] + 2*p[0]*p[8]*p[12]*p[16] + 2*p[0]*p[8]*p[13]*p[19] + 2*p[0]*p[9]*p[12]*p[19] - 2*p[0]*p[9]*p[13]*p[16] - 2*p[0]*p[10]*p[11]*p[19] - 2*p[0]*p[10]*p[14]*p[16] + 2*p[7]*p[10]*p[19] - 2*p[7]*p[10]*p[28] - 2*p[8]*p[9]*p[19] + 2*p[8]*p[9]*p[28] + 2*p[9]*p[9]*p[16] - 2*p[9]*p[9]*p[25] + 2*p[10]*p[10]*p[16] - 2*p[10]*p[10]*p[25] - 2*p[11]*p[14]*p[19] + 2*p[11]*p[14]*p[28] + 2*p[12]*p[13]*p[19] - 2*p[12]*p[13]*p[28] - 2*p[13]*p[13]*p[16] + 2*p[13]*p[13]*p[25] - 2*p[14]*p[14]*p[16] + 2*p[14]*p[14]*p[25];
+ coeff[27] = 2*p[0]*p[7]*p[11]*p[17] + 2*p[0]*p[7]*p[13]*p[22] - 2*p[0]*p[7]*p[14]*p[20] + 2*p[0]*p[8]*p[12]*p[17] + 2*p[0]*p[8]*p[13]*p[20] + 2*p[0]*p[8]*p[14]*p[22] + 2*p[0]*p[9]*p[11]*p[22] + 2*p[0]*p[9]*p[12]*p[20] - 2*p[0]*p[9]*p[13]*p[17] - 2*p[0]*p[10]*p[11]*p[20] + 2*p[0]*p[10]*p[12]*p[22] - 2*p[0]*p[10]*p[14]*p[17] - 2*p[7]*p[9]*p[22] + 2*p[7]*p[9]*p[31] + 2*p[7]*p[10]*p[20] - 2*p[7]*p[10]*p[29] - 2*p[8]*p[9]*p[20] + 2*p[8]*p[9]*p[29] - 2*p[8]*p[10]*p[22] + 2*p[8]*p[10]*p[31] + 2*p[9]*p[9]*p[17] - 2*p[9]*p[9]*p[26] + 2*p[10]*p[10]*p[17] - 2*p[10]*p[10]*p[26] + 2*p[11]*p[13]*p[22] - 2*p[11]*p[13]*p[31] - 2*p[11]*p[14]*p[20] + 2*p[11]*p[14]*p[29] + 2*p[12]*p[13]*p[20] - 2*p[12]*p[13]*p[29] + 2*p[12]*p[14]*p[22] - 2*p[12]*p[14]*p[31] - 2*p[13]*p[13]*p[17] + 2*p[13]*p[13]*p[26] - 2*p[14]*p[14]*p[17] + 2*p[14]*p[14]*p[26];
+ coeff[28] = 0;
+ coeff[29] = 2*(p[7]*p[11]*p[15] - p[7]*p[11]*p[24] + p[8]*p[12]*p[15] - p[8]*p[12]*p[24] - p[9]*p[13]*p[15] + p[9]*p[13]*p[24] - p[10]*p[14]*p[15] + p[10]*p[14]*p[24])*p[0];
+ coeff[30] = 2*(p[7]*p[11]*p[16] - p[7]*p[11]*p[25] - p[7]*p[14]*p[19] + p[7]*p[14]*p[28] + p[8]*p[12]*p[16] - p[8]*p[12]*p[25] + p[8]*p[13]*p[19] - p[8]*p[13]*p[28] + p[9]*p[12]*p[19] - p[9]*p[12]*p[28] - p[9]*p[13]*p[16] + p[9]*p[13]*p[25] - p[10]*p[11]*p[19] + p[10]*p[11]*p[28] - p[10]*p[14]*p[16] + p[10]*p[14]*p[25])*p[0];
+ coeff[31] = 2*(p[7]*p[11]*p[17] - p[7]*p[11]*p[26] + p[7]*p[13]*p[22] - p[7]*p[13]*p[31] - p[7]*p[14]*p[20] + p[7]*p[14]*p[29] + p[8]*p[12]*p[17] - p[8]*p[12]*p[26] + p[8]*p[13]*p[20] - p[8]*p[13]*p[29] + p[8]*p[14]*p[22] - p[8]*p[14]*p[31] + p[9]*p[11]*p[22] - p[9]*p[11]*p[31] + p[9]*p[12]*p[20] - p[9]*p[12]*p[29] - p[9]*p[13]*p[17] + p[9]*p[13]*p[26] - p[10]*p[11]*p[20] + p[10]*p[11]*p[29] + p[10]*p[12]*p[22] - p[10]*p[12]*p[31] - p[10]*p[14]*p[17] + p[10]*p[14]*p[26])*p[0];
+ coeff[32] = 2*(-p[7]*p[11]*p[15] + p[7]*p[11]*p[24] - p[8]*p[12]*p[15] + p[8]*p[12]*p[24] + p[9]*p[13]*p[15] - p[9]*p[13]*p[24] + p[10]*p[14]*p[15] - p[10]*p[14]*p[24])*p[0];
+ coeff[33] = 2*(-p[7]*p[11]*p[16] + p[7]*p[11]*p[25] + p[7]*p[14]*p[19] - p[7]*p[14]*p[28] - p[8]*p[12]*p[16] + p[8]*p[12]*p[25] - p[8]*p[13]*p[19] + p[8]*p[13]*p[28] - p[9]*p[12]*p[19] + p[9]*p[12]*p[28] + p[9]*p[13]*p[16] - p[9]*p[13]*p[25] + p[10]*p[11]*p[19] - p[10]*p[11]*p[28] + p[10]*p[14]*p[16] - p[10]*p[14]*p[25])*p[0];
+ coeff[34] = 2*(-p[7]*p[11]*p[17] + p[7]*p[11]*p[26] - p[7]*p[13]*p[22] + p[7]*p[13]*p[31] + p[7]*p[14]*p[20] - p[7]*p[14]*p[29] - p[8]*p[12]*p[17] + p[8]*p[12]*p[26] - p[8]*p[13]*p[20] + p[8]*p[13]*p[29] - p[8]*p[14]*p[22] + p[8]*p[14]*p[31] - p[9]*p[11]*p[22] + p[9]*p[11]*p[31] - p[9]*p[12]*p[20] + p[9]*p[12]*p[29] + p[9]*p[13]*p[17] - p[9]*p[13]*p[26] + p[10]*p[11]*p[20] - p[10]*p[11]*p[29] - p[10]*p[12]*p[22] + p[10]*p[12]*p[31] + p[10]*p[14]*p[17] - p[10]*p[14]*p[26])*p[0];
+ coeff[35] = -2*p[0]*p[7]*p[9]*p[23] + 2*p[0]*p[7]*p[10]*p[21] - 2*p[0]*p[8]*p[9]*p[21] - 2*p[0]*p[8]*p[10]*p[23] + 2*p[0]*p[9]*p[9]*p[18] + 2*p[0]*p[10]*p[10]*p[18] + 2*p[0]*p[11]*p[13]*p[23] - 2*p[0]*p[11]*p[14]*p[21] + 2*p[0]*p[12]*p[13]*p[21] + 2*p[0]*p[12]*p[14]*p[23] - 2*p[0]*p[13]*p[13]*p[18] - 2*p[0]*p[14]*p[14]*p[18] - p[7]*p[11]*p[18] + p[7]*p[11]*p[27] - p[7]*p[13]*p[23] + p[7]*p[13]*p[32] + p[7]*p[14]*p[21] - p[7]*p[14]*p[30] - p[8]*p[12]*p[18] + p[8]*p[12]*p[27] - p[8]*p[13]*p[21] + p[8]*p[13]*p[30] - p[8]*p[14]*p[23] + p[8]*p[14]*p[32] - p[9]*p[11]*p[23] + p[9]*p[11]*p[32] - p[9]*p[12]*p[21] + p[9]*p[12]*p[30] + p[9]*p[13]*p[18] - p[9]*p[13]*p[27] + p[10]*p[11]*p[21] - p[10]*p[11]*p[30] - p[10]*p[12]*p[23] + p[10]*p[12]*p[32] + p[10]*p[14]*p[18] - p[10]*p[14]*p[27];
+ coeff[36] = 2*p[0]*p[9]*p[9]*p[15] + 2*p[0]*p[10]*p[10]*p[15] - 2*p[0]*p[13]*p[13]*p[15] - 2*p[0]*p[14]*p[14]*p[15] - 2*p[7]*p[11]*p[15] + p[7]*p[11]*p[24] - 2*p[8]*p[12]*p[15] + p[8]*p[12]*p[24] + 2*p[9]*p[13]*p[15] - p[9]*p[13]*p[24] + 2*p[10]*p[14]*p[15] - p[10]*p[14]*p[24];
+ coeff[37] = 2*p[0]*p[7]*p[10]*p[19] - 2*p[0]*p[8]*p[9]*p[19] + 2*p[0]*p[9]*p[9]*p[16] + 2*p[0]*p[10]*p[10]*p[16] - 2*p[0]*p[11]*p[14]*p[19] + 2*p[0]*p[12]*p[13]*p[19] - 2*p[0]*p[13]*p[13]*p[16] - 2*p[0]*p[14]*p[14]*p[16] - 2*p[7]*p[11]*p[16] + p[7]*p[11]*p[25] + 2*p[7]*p[14]*p[19] - p[7]*p[14]*p[28] - 2*p[8]*p[12]*p[16] + p[8]*p[12]*p[25] - 2*p[8]*p[13]*p[19] + p[8]*p[13]*p[28] - 2*p[9]*p[12]*p[19] + p[9]*p[12]*p[28] + 2*p[9]*p[13]*p[16] - p[9]*p[13]*p[25] + 2*p[10]*p[11]*p[19] - p[10]*p[11]*p[28] + 2*p[10]*p[14]*p[16] - p[10]*p[14]*p[25];
+ coeff[38] = -2*p[0]*p[7]*p[9]*p[22] + 2*p[0]*p[7]*p[10]*p[20] - 2*p[0]*p[8]*p[9]*p[20] - 2*p[0]*p[8]*p[10]*p[22] + 2*p[0]*p[9]*p[9]*p[17] + 2*p[0]*p[10]*p[10]*p[17] + 2*p[0]*p[11]*p[13]*p[22] - 2*p[0]*p[11]*p[14]*p[20] + 2*p[0]*p[12]*p[13]*p[20] + 2*p[0]*p[12]*p[14]*p[22] - 2*p[0]*p[13]*p[13]*p[17] - 2*p[0]*p[14]*p[14]*p[17] - 2*p[7]*p[11]*p[17] + p[7]*p[11]*p[26] - 2*p[7]*p[13]*p[22] + p[7]*p[13]*p[31] + 2*p[7]*p[14]*p[20] - p[7]*p[14]*p[29] - 2*p[8]*p[12]*p[17] + p[8]*p[12]*p[26] - 2*p[8]*p[13]*p[20] + p[8]*p[13]*p[29] - 2*p[8]*p[14]*p[22] + p[8]*p[14]*p[31] - 2*p[9]*p[11]*p[22] + p[9]*p[11]*p[31] - 2*p[9]*p[12]*p[20] + p[9]*p[12]*p[29] + 2*p[9]*p[13]*p[17] - p[9]*p[13]*p[26] + 2*p[10]*p[11]*p[20] - p[10]*p[11]*p[29] - 2*p[10]*p[12]*p[22] + p[10]*p[12]*p[31] + 2*p[10]*p[14]*p[17] - p[10]*p[14]*p[26];
+ coeff[39] = (p[7]*p[11] + p[8]*p[12] - p[9]*p[13] - p[10]*p[14])*p[15];
+ coeff[40] = p[7]*p[11]*p[16] - p[7]*p[14]*p[19] + p[8]*p[12]*p[16] + p[8]*p[13]*p[19] + p[9]*p[12]*p[19] - p[9]*p[13]*p[16] - p[10]*p[11]*p[19] - p[10]*p[14]*p[16];
+ coeff[41] = p[7]*p[11]*p[17] + p[7]*p[13]*p[22] - p[7]*p[14]*p[20] + p[8]*p[12]*p[17] + p[8]*p[13]*p[20] + p[8]*p[14]*p[22] + p[9]*p[11]*p[22] + p[9]*p[12]*p[20] - p[9]*p[13]*p[17] - p[10]*p[11]*p[20] + p[10]*p[12]*p[22] - p[10]*p[14]*p[17];
+ coeff[42] = 2*(p[7]*p[9]*p[23] - p[7]*p[9]*p[32] - p[7]*p[10]*p[21] + p[7]*p[10]*p[30] + p[8]*p[9]*p[21] - p[8]*p[9]*p[30] + p[8]*p[10]*p[23] - p[8]*p[10]*p[32] - p[9]*p[9]*p[18] + p[9]*p[9]*p[27] - p[10]*p[10]*p[18] + p[10]*p[10]*p[27] - p[11]*p[13]*p[23] + p[11]*p[13]*p[32] + p[11]*p[14]*p[21] - p[11]*p[14]*p[30] - p[12]*p[13]*p[21] + p[12]*p[13]*p[30] - p[12]*p[14]*p[23] + p[12]*p[14]*p[32] + p[13]*p[13]*p[18] - p[13]*p[13]*p[27] + p[14]*p[14]*p[18] - p[14]*p[14]*p[27])*p[0];
+ coeff[43] = -4*p[0]*p[9]*p[9]*p[15] + 2*p[0]*p[9]*p[9]*p[24] - 4*p[0]*p[10]*p[10]*p[15] + 2*p[0]*p[10]*p[10]*p[24] + 4*p[0]*p[13]*p[13]*p[15] - 2*p[0]*p[13]*p[13]*p[24] + 4*p[0]*p[14]*p[14]*p[15] - 2*p[0]*p[14]*p[14]*p[24] + 2*p[7]*p[11]*p[15] - 2*p[7]*p[11]*p[24] + 2*p[8]*p[12]*p[15] - 2*p[8]*p[12]*p[24] - 2*p[9]*p[13]*p[15] + 2*p[9]*p[13]*p[24] - 2*p[10]*p[14]*p[15] + 2*p[10]*p[14]*p[24];
+ coeff[44] = -4*p[0]*p[7]*p[10]*p[19] + 2*p[0]*p[7]*p[10]*p[28] + 4*p[0]*p[8]*p[9]*p[19] - 2*p[0]*p[8]*p[9]*p[28] - 4*p[0]*p[9]*p[9]*p[16] + 2*p[0]*p[9]*p[9]*p[25] - 4*p[0]*p[10]*p[10]*p[16] + 2*p[0]*p[10]*p[10]*p[25] + 4*p[0]*p[11]*p[14]*p[19] - 2*p[0]*p[11]*p[14]*p[28] - 4*p[0]*p[12]*p[13]*p[19] + 2*p[0]*p[12]*p[13]*p[28] + 4*p[0]*p[13]*p[13]*p[16] - 2*p[0]*p[13]*p[13]*p[25] + 4*p[0]*p[14]*p[14]*p[16] - 2*p[0]*p[14]*p[14]*p[25] + 2*p[7]*p[11]*p[16] - 2*p[7]*p[11]*p[25] - 2*p[7]*p[14]*p[19] + 2*p[7]*p[14]*p[28] + 2*p[8]*p[12]*p[16] - 2*p[8]*p[12]*p[25] + 2*p[8]*p[13]*p[19] - 2*p[8]*p[13]*p[28] + 2*p[9]*p[12]*p[19] - 2*p[9]*p[12]*p[28] - 2*p[9]*p[13]*p[16] + 2*p[9]*p[13]*p[25] - 2*p[10]*p[11]*p[19] + 2*p[10]*p[11]*p[28] - 2*p[10]*p[14]*p[16] + 2*p[10]*p[14]*p[25];
+ coeff[45] = 4*p[0]*p[7]*p[9]*p[22] - 2*p[0]*p[7]*p[9]*p[31] - 4*p[0]*p[7]*p[10]*p[20] + 2*p[0]*p[7]*p[10]*p[29] + 4*p[0]*p[8]*p[9]*p[20] - 2*p[0]*p[8]*p[9]*p[29] + 4*p[0]*p[8]*p[10]*p[22] - 2*p[0]*p[8]*p[10]*p[31] - 4*p[0]*p[9]*p[9]*p[17] + 2*p[0]*p[9]*p[9]*p[26] - 4*p[0]*p[10]*p[10]*p[17] + 2*p[0]*p[10]*p[10]*p[26] - 4*p[0]*p[11]*p[13]*p[22] + 2*p[0]*p[11]*p[13]*p[31] + 4*p[0]*p[11]*p[14]*p[20] - 2*p[0]*p[11]*p[14]*p[29] - 4*p[0]*p[12]*p[13]*p[20] + 2*p[0]*p[12]*p[13]*p[29] - 4*p[0]*p[12]*p[14]*p[22] + 2*p[0]*p[12]*p[14]*p[31] + 4*p[0]*p[13]*p[13]*p[17] - 2*p[0]*p[13]*p[13]*p[26] + 4*p[0]*p[14]*p[14]*p[17] - 2*p[0]*p[14]*p[14]*p[26] + 2*p[7]*p[11]*p[17] - 2*p[7]*p[11]*p[26] + 2*p[7]*p[13]*p[22] - 2*p[7]*p[13]*p[31] - 2*p[7]*p[14]*p[20] + 2*p[7]*p[14]*p[29] + 2*p[8]*p[12]*p[17] - 2*p[8]*p[12]*p[26] + 2*p[8]*p[13]*p[20] - 2*p[8]*p[13]*p[29] + 2*p[8]*p[14]*p[22] - 2*p[8]*p[14]*p[31] + 2*p[9]*p[11]*p[22] - 2*p[9]*p[11]*p[31] + 2*p[9]*p[12]*p[20] - 2*p[9]*p[12]*p[29] - 2*p[9]*p[13]*p[17] + 2*p[9]*p[13]*p[26] - 2*p[10]*p[11]*p[20] + 2*p[10]*p[11]*p[29] + 2*p[10]*p[12]*p[22] - 2*p[10]*p[12]*p[31] - 2*p[10]*p[14]*p[17] + 2*p[10]*p[14]*p[26];
+ coeff[46] = 2*p[0]*p[9]*p[9]*p[15] + 2*p[0]*p[10]*p[10]*p[15] - 2*p[0]*p[13]*p[13]*p[15] - 2*p[0]*p[14]*p[14]*p[15] - 2*p[7]*p[11]*p[15] + 2*p[7]*p[11]*p[24] - 2*p[8]*p[12]*p[15] + 2*p[8]*p[12]*p[24] + 2*p[9]*p[13]*p[15] - 2*p[9]*p[13]*p[24] + 2*p[10]*p[14]*p[15] - 2*p[10]*p[14]*p[24];
+ coeff[47] = 2*p[0]*p[7]*p[10]*p[19] - 2*p[0]*p[8]*p[9]*p[19] + 2*p[0]*p[9]*p[9]*p[16] + 2*p[0]*p[10]*p[10]*p[16] - 2*p[0]*p[11]*p[14]*p[19] + 2*p[0]*p[12]*p[13]*p[19] - 2*p[0]*p[13]*p[13]*p[16] - 2*p[0]*p[14]*p[14]*p[16] - 2*p[7]*p[11]*p[16] + 2*p[7]*p[11]*p[25] + 2*p[7]*p[14]*p[19] - 2*p[7]*p[14]*p[28] - 2*p[8]*p[12]*p[16] + 2*p[8]*p[12]*p[25] - 2*p[8]*p[13]*p[19] + 2*p[8]*p[13]*p[28] - 2*p[9]*p[12]*p[19] + 2*p[9]*p[12]*p[28] + 2*p[9]*p[13]*p[16] - 2*p[9]*p[13]*p[25] + 2*p[10]*p[11]*p[19] - 2*p[10]*p[11]*p[28] + 2*p[10]*p[14]*p[16] - 2*p[10]*p[14]*p[25];
+ coeff[48] = -2*p[0]*p[7]*p[9]*p[22] + 2*p[0]*p[7]*p[10]*p[20] - 2*p[0]*p[8]*p[9]*p[20] - 2*p[0]*p[8]*p[10]*p[22] + 2*p[0]*p[9]*p[9]*p[17] + 2*p[0]*p[10]*p[10]*p[17] + 2*p[0]*p[11]*p[13]*p[22] - 2*p[0]*p[11]*p[14]*p[20] + 2*p[0]*p[12]*p[13]*p[20] + 2*p[0]*p[12]*p[14]*p[22] - 2*p[0]*p[13]*p[13]*p[17] - 2*p[0]*p[14]*p[14]*p[17] - 2*p[7]*p[11]*p[17] + 2*p[7]*p[11]*p[26] - 2*p[7]*p[13]*p[22] + 2*p[7]*p[13]*p[31] + 2*p[7]*p[14]*p[20] - 2*p[7]*p[14]*p[29] - 2*p[8]*p[12]*p[17] + 2*p[8]*p[12]*p[26] - 2*p[8]*p[13]*p[20] + 2*p[8]*p[13]*p[29] - 2*p[8]*p[14]*p[22] + 2*p[8]*p[14]*p[31] - 2*p[9]*p[11]*p[22] + 2*p[9]*p[11]*p[31] - 2*p[9]*p[12]*p[20] + 2*p[9]*p[12]*p[29] + 2*p[9]*p[13]*p[17] - 2*p[9]*p[13]*p[26] + 2*p[10]*p[11]*p[20] - 2*p[10]*p[11]*p[29] - 2*p[10]*p[12]*p[22] + 2*p[10]*p[12]*p[31] + 2*p[10]*p[14]*p[17] - 2*p[10]*p[14]*p[26];
+ coeff[49] = 0;
+ coeff[50] = 2*(p[9]*p[9]*p[15] - p[9]*p[9]*p[24] + p[10]*p[10]*p[15] - p[10]*p[10]*p[24] - p[13]*p[13]*p[15] + p[13]*p[13]*p[24] - p[14]*p[14]*p[15] + p[14]*p[14]*p[24])*p[0];
+ coeff[51] = 2*(p[7]*p[10]*p[19] - p[7]*p[10]*p[28] - p[8]*p[9]*p[19] + p[8]*p[9]*p[28] + p[9]*p[9]*p[16] - p[9]*p[9]*p[25] + p[10]*p[10]*p[16] - p[10]*p[10]*p[25] - p[11]*p[14]*p[19] + p[11]*p[14]*p[28] + p[12]*p[13]*p[19] - p[12]*p[13]*p[28] - p[13]*p[13]*p[16] + p[13]*p[13]*p[25] - p[14]*p[14]*p[16] + p[14]*p[14]*p[25])*p[0];
+ coeff[52] = 2*(-p[7]*p[9]*p[22] + p[7]*p[9]*p[31] + p[7]*p[10]*p[20] - p[7]*p[10]*p[29] - p[8]*p[9]*p[20] + p[8]*p[9]*p[29] - p[8]*p[10]*p[22] + p[8]*p[10]*p[31] + p[9]*p[9]*p[17] - p[9]*p[9]*p[26] + p[10]*p[10]*p[17] - p[10]*p[10]*p[26] + p[11]*p[13]*p[22] - p[11]*p[13]*p[31] - p[11]*p[14]*p[20] + p[11]*p[14]*p[29] + p[12]*p[13]*p[20] - p[12]*p[13]*p[29] + p[12]*p[14]*p[22] - p[12]*p[14]*p[31] - p[13]*p[13]*p[17] + p[13]*p[13]*p[26] - p[14]*p[14]*p[17] + p[14]*p[14]*p[26])*p[0];
+ coeff[53] = 2*(-p[9]*p[9]*p[15] + p[9]*p[9]*p[24] - p[10]*p[10]*p[15] + p[10]*p[10]*p[24] + p[13]*p[13]*p[15] - p[13]*p[13]*p[24] + p[14]*p[14]*p[15] - p[14]*p[14]*p[24])*p[0];
+ coeff[54] = 2*(-p[7]*p[10]*p[19] + p[7]*p[10]*p[28] + p[8]*p[9]*p[19] - p[8]*p[9]*p[28] - p[9]*p[9]*p[16] + p[9]*p[9]*p[25] - p[10]*p[10]*p[16] + p[10]*p[10]*p[25] + p[11]*p[14]*p[19] - p[11]*p[14]*p[28] - p[12]*p[13]*p[19] + p[12]*p[13]*p[28] + p[13]*p[13]*p[16] - p[13]*p[13]*p[25] + p[14]*p[14]*p[16] - p[14]*p[14]*p[25])*p[0];
+ coeff[55] = 2*(p[7]*p[9]*p[22] - p[7]*p[9]*p[31] - p[7]*p[10]*p[20] + p[7]*p[10]*p[29] + p[8]*p[9]*p[20] - p[8]*p[9]*p[29] + p[8]*p[10]*p[22] - p[8]*p[10]*p[31] - p[9]*p[9]*p[17] + p[9]*p[9]*p[26] - p[10]*p[10]*p[17] + p[10]*p[10]*p[26] - p[11]*p[13]*p[22] + p[11]*p[13]*p[31] + p[11]*p[14]*p[20] - p[11]*p[14]*p[29] - p[12]*p[13]*p[20] + p[12]*p[13]*p[29] - p[12]*p[14]*p[22] + p[12]*p[14]*p[31] + p[13]*p[13]*p[17] - p[13]*p[13]*p[26] + p[14]*p[14]*p[17] - p[14]*p[14]*p[26])*p[0];
+ coeff[56] = -p[2] + p[5] + p[7]*p[8]*p[23] - p[7]*p[8]*p[32] - p[7]*p[10]*p[18] + p[7]*p[10]*p[27] + p[8]*p[8]*p[21] - p[8]*p[8]*p[30] - p[8]*p[9]*p[18] + p[8]*p[9]*p[27] - p[9]*p[10]*p[23] + p[9]*p[10]*p[32] + p[10]*p[10]*p[21] - p[10]*p[10]*p[30] + p[11]*p[12]*p[23] - p[11]*p[12]*p[32] - p[11]*p[14]*p[18] + p[11]*p[14]*p[27] + p[12]*p[12]*p[21] - p[12]*p[12]*p[30] - p[12]*p[13]*p[18] + p[12]*p[13]*p[27] - p[13]*p[14]*p[23] + p[13]*p[14]*p[32] + p[14]*p[14]*p[21] - p[14]*p[14]*p[30] - p[21] + p[30];
+ coeff[57] = -2*p[7]*p[10]*p[15] + p[7]*p[10]*p[24] - 2*p[8]*p[9]*p[15] + p[8]*p[9]*p[24] - 2*p[11]*p[14]*p[15] + p[11]*p[14]*p[24] - 2*p[12]*p[13]*p[15] + p[12]*p[13]*p[24];
+ coeff[58] = -2*p[7]*p[10]*p[16] + p[7]*p[10]*p[25] + 2*p[8]*p[8]*p[19] - p[8]*p[8]*p[28] - 2*p[8]*p[9]*p[16] + p[8]*p[9]*p[25] + 2*p[10]*p[10]*p[19] - p[10]*p[10]*p[28] - 2*p[11]*p[14]*p[16] + p[11]*p[14]*p[25] + 2*p[12]*p[12]*p[19] - p[12]*p[12]*p[28] - 2*p[12]*p[13]*p[16] + p[12]*p[13]*p[25] + 2*p[14]*p[14]*p[19] - p[14]*p[14]*p[28] - 2*p[19] + p[28];
+ coeff[59] = 2*p[7]*p[8]*p[22] - p[7]*p[8]*p[31] - 2*p[7]*p[10]*p[17] + p[7]*p[10]*p[26] + 2*p[8]*p[8]*p[20] - p[8]*p[8]*p[29] - 2*p[8]*p[9]*p[17] + p[8]*p[9]*p[26] - 2*p[9]*p[10]*p[22] + p[9]*p[10]*p[31] + 2*p[10]*p[10]*p[20] - p[10]*p[10]*p[29] + 2*p[11]*p[12]*p[22] - p[11]*p[12]*p[31] - 2*p[11]*p[14]*p[17] + p[11]*p[14]*p[26] + 2*p[12]*p[12]*p[20] - p[12]*p[12]*p[29] - 2*p[12]*p[13]*p[17] + p[12]*p[13]*p[26] - 2*p[13]*p[14]*p[22] + p[13]*p[14]*p[31] + 2*p[14]*p[14]*p[20] - p[14]*p[14]*p[29] - 2*p[20] + p[29];
+ coeff[60] = (p[7]*p[10] + p[8]*p[9] + p[11]*p[14] + p[12]*p[13])*p[15];
+ coeff[61] = p[7]*p[10]*p[16] - p[8]*p[8]*p[19] + p[8]*p[9]*p[16] - p[10]*p[10]*p[19] + p[11]*p[14]*p[16] - p[12]*p[12]*p[19] + p[12]*p[13]*p[16] - p[14]*p[14]*p[19] + p[19];
+ coeff[62] = -p[7]*p[8]*p[22] + p[7]*p[10]*p[17] - p[8]*p[8]*p[20] + p[8]*p[9]*p[17] + p[9]*p[10]*p[22] - p[10]*p[10]*p[20] - p[11]*p[12]*p[22] + p[11]*p[14]*p[17] - p[12]*p[12]*p[20] + p[12]*p[13]*p[17] + p[13]*p[14]*p[22] - p[14]*p[14]*p[20] + p[20];
+ coeff[63] = 0;
+ coeff[64] = 2*p[7]*p[10]*p[15] - 2*p[7]*p[10]*p[24] + 2*p[8]*p[9]*p[15] - 2*p[8]*p[9]*p[24] + 2*p[11]*p[14]*p[15] - 2*p[11]*p[14]*p[24] + 2*p[12]*p[13]*p[15] - 2*p[12]*p[13]*p[24];
+ coeff[65] = 2*p[7]*p[10]*p[16] - 2*p[7]*p[10]*p[25] - 2*p[8]*p[8]*p[19] + 2*p[8]*p[8]*p[28] + 2*p[8]*p[9]*p[16] - 2*p[8]*p[9]*p[25] - 2*p[10]*p[10]*p[19] + 2*p[10]*p[10]*p[28] + 2*p[11]*p[14]*p[16] - 2*p[11]*p[14]*p[25] - 2*p[12]*p[12]*p[19] + 2*p[12]*p[12]*p[28] + 2*p[12]*p[13]*p[16] - 2*p[12]*p[13]*p[25] - 2*p[14]*p[14]*p[19] + 2*p[14]*p[14]*p[28] + 2*p[19] - 2*p[28];
+ coeff[66] = -2*p[7]*p[8]*p[22] + 2*p[7]*p[8]*p[31] + 2*p[7]*p[10]*p[17] - 2*p[7]*p[10]*p[26] - 2*p[8]*p[8]*p[20] + 2*p[8]*p[8]*p[29] + 2*p[8]*p[9]*p[17] - 2*p[8]*p[9]*p[26] + 2*p[9]*p[10]*p[22] - 2*p[9]*p[10]*p[31] - 2*p[10]*p[10]*p[20] + 2*p[10]*p[10]*p[29] - 2*p[11]*p[12]*p[22] + 2*p[11]*p[12]*p[31] + 2*p[11]*p[14]*p[17] - 2*p[11]*p[14]*p[26] - 2*p[12]*p[12]*p[20] + 2*p[12]*p[12]*p[29] + 2*p[12]*p[13]*p[17] - 2*p[12]*p[13]*p[26] + 2*p[13]*p[14]*p[22] - 2*p[13]*p[14]*p[31] - 2*p[14]*p[14]*p[20] + 2*p[14]*p[14]*p[29] + 2*p[20] - 2*p[29];
+ coeff[67] = -2*p[7]*p[10]*p[15] + 2*p[7]*p[10]*p[24] - 2*p[8]*p[9]*p[15] + 2*p[8]*p[9]*p[24] - 2*p[11]*p[14]*p[15] + 2*p[11]*p[14]*p[24] - 2*p[12]*p[13]*p[15] + 2*p[12]*p[13]*p[24];
+ coeff[68] = -2*p[7]*p[10]*p[16] + 2*p[7]*p[10]*p[25] + 2*p[8]*p[8]*p[19] - 2*p[8]*p[8]*p[28] - 2*p[8]*p[9]*p[16] + 2*p[8]*p[9]*p[25] + 2*p[10]*p[10]*p[19] - 2*p[10]*p[10]*p[28] - 2*p[11]*p[14]*p[16] + 2*p[11]*p[14]*p[25] + 2*p[12]*p[12]*p[19] - 2*p[12]*p[12]*p[28] - 2*p[12]*p[13]*p[16] + 2*p[12]*p[13]*p[25] + 2*p[14]*p[14]*p[19] - 2*p[14]*p[14]*p[28] - 2*p[19] + 2*p[28];
+ coeff[69] = 2*p[7]*p[8]*p[22] - 2*p[7]*p[8]*p[31] - 2*p[7]*p[10]*p[17] + 2*p[7]*p[10]*p[26] + 2*p[8]*p[8]*p[20] - 2*p[8]*p[8]*p[29] - 2*p[8]*p[9]*p[17] + 2*p[8]*p[9]*p[26] - 2*p[9]*p[10]*p[22] + 2*p[9]*p[10]*p[31] + 2*p[10]*p[10]*p[20] - 2*p[10]*p[10]*p[29] + 2*p[11]*p[12]*p[22] - 2*p[11]*p[12]*p[31] - 2*p[11]*p[14]*p[17] + 2*p[11]*p[14]*p[26] + 2*p[12]*p[12]*p[20] - 2*p[12]*p[12]*p[29] - 2*p[12]*p[13]*p[17] + 2*p[12]*p[13]*p[26] - 2*p[13]*p[14]*p[22] + 2*p[13]*p[14]*p[31] + 2*p[14]*p[14]*p[20] - 2*p[14]*p[14]*p[29] - 2*p[20] + 2*p[29];
+ coeff[70] = 2*p[0]*p[7]*p[11]*p[21] - 2*p[0]*p[7]*p[12]*p[23] + 2*p[0]*p[7]*p[14]*p[18] - 2*p[0]*p[8]*p[11]*p[23] - 2*p[0]*p[8]*p[12]*p[21] + 2*p[0]*p[8]*p[13]*p[18] + 2*p[0]*p[9]*p[12]*p[18] + 2*p[0]*p[9]*p[13]*p[21] + 2*p[0]*p[9]*p[14]*p[23] + 2*p[0]*p[10]*p[11]*p[18] + 2*p[0]*p[10]*p[13]*p[23] - 2*p[0]*p[10]*p[14]*p[21] + p[7]*p[8]*p[23] - p[7]*p[8]*p[32] - p[7]*p[10]*p[18] + p[7]*p[10]*p[27] + p[8]*p[8]*p[21] - p[8]*p[8]*p[30] - p[8]*p[9]*p[18] + p[8]*p[9]*p[27] - p[9]*p[10]*p[23] + p[9]*p[10]*p[32] + p[10]*p[10]*p[21] - p[10]*p[10]*p[30] - p[11]*p[12]*p[23] + p[11]*p[12]*p[32] + p[11]*p[14]*p[18] - p[11]*p[14]*p[27] - p[12]*p[12]*p[21] + p[12]*p[12]*p[30] + p[12]*p[13]*p[18] - p[12]*p[13]*p[27] + p[13]*p[14]*p[23] - p[13]*p[14]*p[32] - p[14]*p[14]*p[21] + p[14]*p[14]*p[30];
+ coeff[71] = 2*p[0]*p[7]*p[14]*p[15] + 2*p[0]*p[8]*p[13]*p[15] + 2*p[0]*p[9]*p[12]*p[15] + 2*p[0]*p[10]*p[11]*p[15] - 2*p[7]*p[10]*p[15] + p[7]*p[10]*p[24] - 2*p[8]*p[9]*p[15] + p[8]*p[9]*p[24] + 2*p[11]*p[14]*p[15] - p[11]*p[14]*p[24] + 2*p[12]*p[13]*p[15] - p[12]*p[13]*p[24];
+ coeff[72] = 2*p[0]*p[7]*p[11]*p[19] + 2*p[0]*p[7]*p[14]*p[16] - 2*p[0]*p[8]*p[12]*p[19] + 2*p[0]*p[8]*p[13]*p[16] + 2*p[0]*p[9]*p[12]*p[16] + 2*p[0]*p[9]*p[13]*p[19] + 2*p[0]*p[10]*p[11]*p[16] - 2*p[0]*p[10]*p[14]*p[19] - 2*p[7]*p[10]*p[16] + p[7]*p[10]*p[25] + 2*p[8]*p[8]*p[19] - p[8]*p[8]*p[28] - 2*p[8]*p[9]*p[16] + p[8]*p[9]*p[25] + 2*p[10]*p[10]*p[19] - p[10]*p[10]*p[28] + 2*p[11]*p[14]*p[16] - p[11]*p[14]*p[25] - 2*p[12]*p[12]*p[19] + p[12]*p[12]*p[28] + 2*p[12]*p[13]*p[16] - p[12]*p[13]*p[25] - 2*p[14]*p[14]*p[19] + p[14]*p[14]*p[28];
+ coeff[73] = 2*p[0]*p[7]*p[11]*p[20] - 2*p[0]*p[7]*p[12]*p[22] + 2*p[0]*p[7]*p[14]*p[17] - 2*p[0]*p[8]*p[11]*p[22] - 2*p[0]*p[8]*p[12]*p[20] + 2*p[0]*p[8]*p[13]*p[17] + 2*p[0]*p[9]*p[12]*p[17] + 2*p[0]*p[9]*p[13]*p[20] + 2*p[0]*p[9]*p[14]*p[22] + 2*p[0]*p[10]*p[11]*p[17] + 2*p[0]*p[10]*p[13]*p[22] - 2*p[0]*p[10]*p[14]*p[20] + 2*p[7]*p[8]*p[22] - p[7]*p[8]*p[31] - 2*p[7]*p[10]*p[17] + p[7]*p[10]*p[26] + 2*p[8]*p[8]*p[20] - p[8]*p[8]*p[29] - 2*p[8]*p[9]*p[17] + p[8]*p[9]*p[26] - 2*p[9]*p[10]*p[22] + p[9]*p[10]*p[31] + 2*p[10]*p[10]*p[20] - p[10]*p[10]*p[29] - 2*p[11]*p[12]*p[22] + p[11]*p[12]*p[31] + 2*p[11]*p[14]*p[17] - p[11]*p[14]*p[26] - 2*p[12]*p[12]*p[20] + p[12]*p[12]*p[29] + 2*p[12]*p[13]*p[17] - p[12]*p[13]*p[26] + 2*p[13]*p[14]*p[22] - p[13]*p[14]*p[31] - 2*p[14]*p[14]*p[20] + p[14]*p[14]*p[29];
+ coeff[74] = (p[7]*p[10] + p[8]*p[9] - p[11]*p[14] - p[12]*p[13])*p[15];
+ coeff[75] = p[7]*p[10]*p[16] - p[8]*p[8]*p[19] + p[8]*p[9]*p[16] - p[10]*p[10]*p[19] - p[11]*p[14]*p[16] + p[12]*p[12]*p[19] - p[12]*p[13]*p[16] + p[14]*p[14]*p[19];
+ coeff[76] = -p[7]*p[8]*p[22] + p[7]*p[10]*p[17] - p[8]*p[8]*p[20] + p[8]*p[9]*p[17] + p[9]*p[10]*p[22] - p[10]*p[10]*p[20] + p[11]*p[12]*p[22] - p[11]*p[14]*p[17] + p[12]*p[12]*p[20] - p[12]*p[13]*p[17] - p[13]*p[14]*p[22] + p[14]*p[14]*p[20];
+ coeff[77] = 2*(-p[7]*p[11]*p[21] + p[7]*p[11]*p[30] + p[7]*p[12]*p[23] - p[7]*p[12]*p[32] - p[7]*p[14]*p[18] + p[7]*p[14]*p[27] + p[8]*p[11]*p[23] - p[8]*p[11]*p[32] + p[8]*p[12]*p[21] - p[8]*p[12]*p[30] - p[8]*p[13]*p[18] + p[8]*p[13]*p[27] - p[9]*p[12]*p[18] + p[9]*p[12]*p[27] - p[9]*p[13]*p[21] + p[9]*p[13]*p[30] - p[9]*p[14]*p[23] + p[9]*p[14]*p[32] - p[10]*p[11]*p[18] + p[10]*p[11]*p[27] - p[10]*p[13]*p[23] + p[10]*p[13]*p[32] + p[10]*p[14]*p[21] - p[10]*p[14]*p[30])*p[0];
+ coeff[78] = -4*p[0]*p[7]*p[14]*p[15] + 2*p[0]*p[7]*p[14]*p[24] - 4*p[0]*p[8]*p[13]*p[15] + 2*p[0]*p[8]*p[13]*p[24] - 4*p[0]*p[9]*p[12]*p[15] + 2*p[0]*p[9]*p[12]*p[24] - 4*p[0]*p[10]*p[11]*p[15] + 2*p[0]*p[10]*p[11]*p[24] + 2*p[7]*p[10]*p[15] - 2*p[7]*p[10]*p[24] + 2*p[8]*p[9]*p[15] - 2*p[8]*p[9]*p[24] - 2*p[11]*p[14]*p[15] + 2*p[11]*p[14]*p[24] - 2*p[12]*p[13]*p[15] + 2*p[12]*p[13]*p[24];
+ coeff[79] = -4*p[0]*p[7]*p[11]*p[19] + 2*p[0]*p[7]*p[11]*p[28] - 4*p[0]*p[7]*p[14]*p[16] + 2*p[0]*p[7]*p[14]*p[25] + 4*p[0]*p[8]*p[12]*p[19] - 2*p[0]*p[8]*p[12]*p[28] - 4*p[0]*p[8]*p[13]*p[16] + 2*p[0]*p[8]*p[13]*p[25] - 4*p[0]*p[9]*p[12]*p[16] + 2*p[0]*p[9]*p[12]*p[25] - 4*p[0]*p[9]*p[13]*p[19] + 2*p[0]*p[9]*p[13]*p[28] - 4*p[0]*p[10]*p[11]*p[16] + 2*p[0]*p[10]*p[11]*p[25] + 4*p[0]*p[10]*p[14]*p[19] - 2*p[0]*p[10]*p[14]*p[28] + 2*p[7]*p[10]*p[16] - 2*p[7]*p[10]*p[25] - 2*p[8]*p[8]*p[19] + 2*p[8]*p[8]*p[28] + 2*p[8]*p[9]*p[16] - 2*p[8]*p[9]*p[25] - 2*p[10]*p[10]*p[19] + 2*p[10]*p[10]*p[28] - 2*p[11]*p[14]*p[16] + 2*p[11]*p[14]*p[25] + 2*p[12]*p[12]*p[19] - 2*p[12]*p[12]*p[28] - 2*p[12]*p[13]*p[16] + 2*p[12]*p[13]*p[25] + 2*p[14]*p[14]*p[19] - 2*p[14]*p[14]*p[28];
+ coeff[80] = -4*p[0]*p[7]*p[11]*p[20] + 2*p[0]*p[7]*p[11]*p[29] + 4*p[0]*p[7]*p[12]*p[22] - 2*p[0]*p[7]*p[12]*p[31] - 4*p[0]*p[7]*p[14]*p[17] + 2*p[0]*p[7]*p[14]*p[26] + 4*p[0]*p[8]*p[11]*p[22] - 2*p[0]*p[8]*p[11]*p[31] + 4*p[0]*p[8]*p[12]*p[20] - 2*p[0]*p[8]*p[12]*p[29] - 4*p[0]*p[8]*p[13]*p[17] + 2*p[0]*p[8]*p[13]*p[26] - 4*p[0]*p[9]*p[12]*p[17] + 2*p[0]*p[9]*p[12]*p[26] - 4*p[0]*p[9]*p[13]*p[20] + 2*p[0]*p[9]*p[13]*p[29] - 4*p[0]*p[9]*p[14]*p[22] + 2*p[0]*p[9]*p[14]*p[31] - 4*p[0]*p[10]*p[11]*p[17] + 2*p[0]*p[10]*p[11]*p[26] - 4*p[0]*p[10]*p[13]*p[22] + 2*p[0]*p[10]*p[13]*p[31] + 4*p[0]*p[10]*p[14]*p[20] - 2*p[0]*p[10]*p[14]*p[29] - 2*p[7]*p[8]*p[22] + 2*p[7]*p[8]*p[31] + 2*p[7]*p[10]*p[17] - 2*p[7]*p[10]*p[26] - 2*p[8]*p[8]*p[20] + 2*p[8]*p[8]*p[29] + 2*p[8]*p[9]*p[17] - 2*p[8]*p[9]*p[26] + 2*p[9]*p[10]*p[22] - 2*p[9]*p[10]*p[31] - 2*p[10]*p[10]*p[20] + 2*p[10]*p[10]*p[29] + 2*p[11]*p[12]*p[22] - 2*p[11]*p[12]*p[31] - 2*p[11]*p[14]*p[17] + 2*p[11]*p[14]*p[26] + 2*p[12]*p[12]*p[20] - 2*p[12]*p[12]*p[29] - 2*p[12]*p[13]*p[17] + 2*p[12]*p[13]*p[26] - 2*p[13]*p[14]*p[22] + 2*p[13]*p[14]*p[31] + 2*p[14]*p[14]*p[20] - 2*p[14]*p[14]*p[29];
+ coeff[81] = 2*p[0]*p[7]*p[14]*p[15] + 2*p[0]*p[8]*p[13]*p[15] + 2*p[0]*p[9]*p[12]*p[15] + 2*p[0]*p[10]*p[11]*p[15] - 2*p[7]*p[10]*p[15] + 2*p[7]*p[10]*p[24] - 2*p[8]*p[9]*p[15] + 2*p[8]*p[9]*p[24] + 2*p[11]*p[14]*p[15] - 2*p[11]*p[14]*p[24] + 2*p[12]*p[13]*p[15] - 2*p[12]*p[13]*p[24];
+ coeff[82] = 2*p[0]*p[7]*p[11]*p[19] + 2*p[0]*p[7]*p[14]*p[16] - 2*p[0]*p[8]*p[12]*p[19] + 2*p[0]*p[8]*p[13]*p[16] + 2*p[0]*p[9]*p[12]*p[16] + 2*p[0]*p[9]*p[13]*p[19] + 2*p[0]*p[10]*p[11]*p[16] - 2*p[0]*p[10]*p[14]*p[19] - 2*p[7]*p[10]*p[16] + 2*p[7]*p[10]*p[25] + 2*p[8]*p[8]*p[19] - 2*p[8]*p[8]*p[28] - 2*p[8]*p[9]*p[16] + 2*p[8]*p[9]*p[25] + 2*p[10]*p[10]*p[19] - 2*p[10]*p[10]*p[28] + 2*p[11]*p[14]*p[16] - 2*p[11]*p[14]*p[25] - 2*p[12]*p[12]*p[19] + 2*p[12]*p[12]*p[28] + 2*p[12]*p[13]*p[16] - 2*p[12]*p[13]*p[25] - 2*p[14]*p[14]*p[19] + 2*p[14]*p[14]*p[28];
+ coeff[83] = 2*p[0]*p[7]*p[11]*p[20] - 2*p[0]*p[7]*p[12]*p[22] + 2*p[0]*p[7]*p[14]*p[17] - 2*p[0]*p[8]*p[11]*p[22] - 2*p[0]*p[8]*p[12]*p[20] + 2*p[0]*p[8]*p[13]*p[17] + 2*p[0]*p[9]*p[12]*p[17] + 2*p[0]*p[9]*p[13]*p[20] + 2*p[0]*p[9]*p[14]*p[22] + 2*p[0]*p[10]*p[11]*p[17] + 2*p[0]*p[10]*p[13]*p[22] - 2*p[0]*p[10]*p[14]*p[20] + 2*p[7]*p[8]*p[22] - 2*p[7]*p[8]*p[31] - 2*p[7]*p[10]*p[17] + 2*p[7]*p[10]*p[26] + 2*p[8]*p[8]*p[20] - 2*p[8]*p[8]*p[29] - 2*p[8]*p[9]*p[17] + 2*p[8]*p[9]*p[26] - 2*p[9]*p[10]*p[22] + 2*p[9]*p[10]*p[31] + 2*p[10]*p[10]*p[20] - 2*p[10]*p[10]*p[29] - 2*p[11]*p[12]*p[22] + 2*p[11]*p[12]*p[31] + 2*p[11]*p[14]*p[17] - 2*p[11]*p[14]*p[26] - 2*p[12]*p[12]*p[20] + 2*p[12]*p[12]*p[29] + 2*p[12]*p[13]*p[17] - 2*p[12]*p[13]*p[26] + 2*p[13]*p[14]*p[22] - 2*p[13]*p[14]*p[31] - 2*p[14]*p[14]*p[20] + 2*p[14]*p[14]*p[29];
+ coeff[84] = 0;
+ coeff[85] = 2*(p[7]*p[14]*p[15] - p[7]*p[14]*p[24] + p[8]*p[13]*p[15] - p[8]*p[13]*p[24] + p[9]*p[12]*p[15] - p[9]*p[12]*p[24] + p[10]*p[11]*p[15] - p[10]*p[11]*p[24])*p[0];
+ coeff[86] = 2*(p[7]*p[11]*p[19] - p[7]*p[11]*p[28] + p[7]*p[14]*p[16] - p[7]*p[14]*p[25] - p[8]*p[12]*p[19] + p[8]*p[12]*p[28] + p[8]*p[13]*p[16] - p[8]*p[13]*p[25] + p[9]*p[12]*p[16] - p[9]*p[12]*p[25] + p[9]*p[13]*p[19] - p[9]*p[13]*p[28] + p[10]*p[11]*p[16] - p[10]*p[11]*p[25] - p[10]*p[14]*p[19] + p[10]*p[14]*p[28])*p[0];
+ coeff[87] = 2*(p[7]*p[11]*p[20] - p[7]*p[11]*p[29] - p[7]*p[12]*p[22] + p[7]*p[12]*p[31] + p[7]*p[14]*p[17] - p[7]*p[14]*p[26] - p[8]*p[11]*p[22] + p[8]*p[11]*p[31] - p[8]*p[12]*p[20] + p[8]*p[12]*p[29] + p[8]*p[13]*p[17] - p[8]*p[13]*p[26] + p[9]*p[12]*p[17] - p[9]*p[12]*p[26] + p[9]*p[13]*p[20] - p[9]*p[13]*p[29] + p[9]*p[14]*p[22] - p[9]*p[14]*p[31] + p[10]*p[11]*p[17] - p[10]*p[11]*p[26] + p[10]*p[13]*p[22] - p[10]*p[13]*p[31] - p[10]*p[14]*p[20] + p[10]*p[14]*p[29])*p[0];
+ coeff[88] = 2*(-p[7]*p[14]*p[15] + p[7]*p[14]*p[24] - p[8]*p[13]*p[15] + p[8]*p[13]*p[24] - p[9]*p[12]*p[15] + p[9]*p[12]*p[24] - p[10]*p[11]*p[15] + p[10]*p[11]*p[24])*p[0];
+ coeff[89] = 2*(-p[7]*p[11]*p[19] + p[7]*p[11]*p[28] - p[7]*p[14]*p[16] + p[7]*p[14]*p[25] + p[8]*p[12]*p[19] - p[8]*p[12]*p[28] - p[8]*p[13]*p[16] + p[8]*p[13]*p[25] - p[9]*p[12]*p[16] + p[9]*p[12]*p[25] - p[9]*p[13]*p[19] + p[9]*p[13]*p[28] - p[10]*p[11]*p[16] + p[10]*p[11]*p[25] + p[10]*p[14]*p[19] - p[10]*p[14]*p[28])*p[0];
+ coeff[90] = 2*(-p[7]*p[11]*p[20] + p[7]*p[11]*p[29] + p[7]*p[12]*p[22] - p[7]*p[12]*p[31] - p[7]*p[14]*p[17] + p[7]*p[14]*p[26] + p[8]*p[11]*p[22] - p[8]*p[11]*p[31] + p[8]*p[12]*p[20] - p[8]*p[12]*p[29] - p[8]*p[13]*p[17] + p[8]*p[13]*p[26] - p[9]*p[12]*p[17] + p[9]*p[12]*p[26] - p[9]*p[13]*p[20] + p[9]*p[13]*p[29] - p[9]*p[14]*p[22] + p[9]*p[14]*p[31] - p[10]*p[11]*p[17] + p[10]*p[11]*p[26] - p[10]*p[13]*p[22] + p[10]*p[13]*p[31] + p[10]*p[14]*p[20] - p[10]*p[14]*p[29])*p[0];
+ coeff[91] = 2*p[0]*p[7]*p[8]*p[23] - 2*p[0]*p[7]*p[10]*p[18] + 2*p[0]*p[8]*p[8]*p[21] - 2*p[0]*p[8]*p[9]*p[18] - 2*p[0]*p[9]*p[10]*p[23] + 2*p[0]*p[10]*p[10]*p[21] - 2*p[0]*p[11]*p[12]*p[23] + 2*p[0]*p[11]*p[14]*p[18] - 2*p[0]*p[12]*p[12]*p[21] + 2*p[0]*p[12]*p[13]*p[18] + 2*p[0]*p[13]*p[14]*p[23] - 2*p[0]*p[14]*p[14]*p[21] - p[7]*p[11]*p[21] + p[7]*p[11]*p[30] + p[7]*p[12]*p[23] - p[7]*p[12]*p[32] - p[7]*p[14]*p[18] + p[7]*p[14]*p[27] + p[8]*p[11]*p[23] - p[8]*p[11]*p[32] + p[8]*p[12]*p[21] - p[8]*p[12]*p[30] - p[8]*p[13]*p[18] + p[8]*p[13]*p[27] - p[9]*p[12]*p[18] + p[9]*p[12]*p[27] - p[9]*p[13]*p[21] + p[9]*p[13]*p[30] - p[9]*p[14]*p[23] + p[9]*p[14]*p[32] - p[10]*p[11]*p[18] + p[10]*p[11]*p[27] - p[10]*p[13]*p[23] + p[10]*p[13]*p[32] + p[10]*p[14]*p[21] - p[10]*p[14]*p[30];
+ coeff[92] = -2*p[0]*p[7]*p[10]*p[15] - 2*p[0]*p[8]*p[9]*p[15] + 2*p[0]*p[11]*p[14]*p[15] + 2*p[0]*p[12]*p[13]*p[15] - 2*p[7]*p[14]*p[15] + p[7]*p[14]*p[24] - 2*p[8]*p[13]*p[15] + p[8]*p[13]*p[24] - 2*p[9]*p[12]*p[15] + p[9]*p[12]*p[24] - 2*p[10]*p[11]*p[15] + p[10]*p[11]*p[24];
+ coeff[93] = -2*p[0]*p[7]*p[10]*p[16] + 2*p[0]*p[8]*p[8]*p[19] - 2*p[0]*p[8]*p[9]*p[16] + 2*p[0]*p[10]*p[10]*p[19] + 2*p[0]*p[11]*p[14]*p[16] - 2*p[0]*p[12]*p[12]*p[19] + 2*p[0]*p[12]*p[13]*p[16] - 2*p[0]*p[14]*p[14]*p[19] - 2*p[7]*p[11]*p[19] + p[7]*p[11]*p[28] - 2*p[7]*p[14]*p[16] + p[7]*p[14]*p[25] + 2*p[8]*p[12]*p[19] - p[8]*p[12]*p[28] - 2*p[8]*p[13]*p[16] + p[8]*p[13]*p[25] - 2*p[9]*p[12]*p[16] + p[9]*p[12]*p[25] - 2*p[9]*p[13]*p[19] + p[9]*p[13]*p[28] - 2*p[10]*p[11]*p[16] + p[10]*p[11]*p[25] + 2*p[10]*p[14]*p[19] - p[10]*p[14]*p[28];
+ coeff[94] = 2*p[0]*p[7]*p[8]*p[22] - 2*p[0]*p[7]*p[10]*p[17] + 2*p[0]*p[8]*p[8]*p[20] - 2*p[0]*p[8]*p[9]*p[17] - 2*p[0]*p[9]*p[10]*p[22] + 2*p[0]*p[10]*p[10]*p[20] - 2*p[0]*p[11]*p[12]*p[22] + 2*p[0]*p[11]*p[14]*p[17] - 2*p[0]*p[12]*p[12]*p[20] + 2*p[0]*p[12]*p[13]*p[17] + 2*p[0]*p[13]*p[14]*p[22] - 2*p[0]*p[14]*p[14]*p[20] - 2*p[7]*p[11]*p[20] + p[7]*p[11]*p[29] + 2*p[7]*p[12]*p[22] - p[7]*p[12]*p[31] - 2*p[7]*p[14]*p[17] + p[7]*p[14]*p[26] + 2*p[8]*p[11]*p[22] - p[8]*p[11]*p[31] + 2*p[8]*p[12]*p[20] - p[8]*p[12]*p[29] - 2*p[8]*p[13]*p[17] + p[8]*p[13]*p[26] - 2*p[9]*p[12]*p[17] + p[9]*p[12]*p[26] - 2*p[9]*p[13]*p[20] + p[9]*p[13]*p[29] - 2*p[9]*p[14]*p[22] + p[9]*p[14]*p[31] - 2*p[10]*p[11]*p[17] + p[10]*p[11]*p[26] - 2*p[10]*p[13]*p[22] + p[10]*p[13]*p[31] + 2*p[10]*p[14]*p[20] - p[10]*p[14]*p[29];
+ coeff[95] = (p[7]*p[14] + p[8]*p[13] + p[9]*p[12] + p[10]*p[11])*p[15];
+ coeff[96] = p[7]*p[11]*p[19] + p[7]*p[14]*p[16] - p[8]*p[12]*p[19] + p[8]*p[13]*p[16] + p[9]*p[12]*p[16] + p[9]*p[13]*p[19] + p[10]*p[11]*p[16] - p[10]*p[14]*p[19];
+ coeff[97] = p[7]*p[11]*p[20] - p[7]*p[12]*p[22] + p[7]*p[14]*p[17] - p[8]*p[11]*p[22] - p[8]*p[12]*p[20] + p[8]*p[13]*p[17] + p[9]*p[12]*p[17] + p[9]*p[13]*p[20] + p[9]*p[14]*p[22] + p[10]*p[11]*p[17] + p[10]*p[13]*p[22] - p[10]*p[14]*p[20];
+ coeff[98] = 2*(-p[7]*p[8]*p[23] + p[7]*p[8]*p[32] + p[7]*p[10]*p[18] - p[7]*p[10]*p[27] - p[8]*p[8]*p[21] + p[8]*p[8]*p[30] + p[8]*p[9]*p[18] - p[8]*p[9]*p[27] + p[9]*p[10]*p[23] - p[9]*p[10]*p[32] - p[10]*p[10]*p[21] + p[10]*p[10]*p[30] + p[11]*p[12]*p[23] - p[11]*p[12]*p[32] - p[11]*p[14]*p[18] + p[11]*p[14]*p[27] + p[12]*p[12]*p[21] - p[12]*p[12]*p[30] - p[12]*p[13]*p[18] + p[12]*p[13]*p[27] - p[13]*p[14]*p[23] + p[13]*p[14]*p[32] + p[14]*p[14]*p[21] - p[14]*p[14]*p[30])*p[0];
+ coeff[99] = 4*p[0]*p[7]*p[10]*p[15] - 2*p[0]*p[7]*p[10]*p[24] + 4*p[0]*p[8]*p[9]*p[15] - 2*p[0]*p[8]*p[9]*p[24] - 4*p[0]*p[11]*p[14]*p[15] + 2*p[0]*p[11]*p[14]*p[24] - 4*p[0]*p[12]*p[13]*p[15] + 2*p[0]*p[12]*p[13]*p[24] + 2*p[7]*p[14]*p[15] - 2*p[7]*p[14]*p[24] + 2*p[8]*p[13]*p[15] - 2*p[8]*p[13]*p[24] + 2*p[9]*p[12]*p[15] - 2*p[9]*p[12]*p[24] + 2*p[10]*p[11]*p[15] - 2*p[10]*p[11]*p[24];
+ coeff[100] = 4*p[0]*p[7]*p[10]*p[16] - 2*p[0]*p[7]*p[10]*p[25] - 4*p[0]*p[8]*p[8]*p[19] + 2*p[0]*p[8]*p[8]*p[28] + 4*p[0]*p[8]*p[9]*p[16] - 2*p[0]*p[8]*p[9]*p[25] - 4*p[0]*p[10]*p[10]*p[19] + 2*p[0]*p[10]*p[10]*p[28] - 4*p[0]*p[11]*p[14]*p[16] + 2*p[0]*p[11]*p[14]*p[25] + 4*p[0]*p[12]*p[12]*p[19] - 2*p[0]*p[12]*p[12]*p[28] - 4*p[0]*p[12]*p[13]*p[16] + 2*p[0]*p[12]*p[13]*p[25] + 4*p[0]*p[14]*p[14]*p[19] - 2*p[0]*p[14]*p[14]*p[28] + 2*p[7]*p[11]*p[19] - 2*p[7]*p[11]*p[28] + 2*p[7]*p[14]*p[16] - 2*p[7]*p[14]*p[25] - 2*p[8]*p[12]*p[19] + 2*p[8]*p[12]*p[28] + 2*p[8]*p[13]*p[16] - 2*p[8]*p[13]*p[25] + 2*p[9]*p[12]*p[16] - 2*p[9]*p[12]*p[25] + 2*p[9]*p[13]*p[19] - 2*p[9]*p[13]*p[28] + 2*p[10]*p[11]*p[16] - 2*p[10]*p[11]*p[25] - 2*p[10]*p[14]*p[19] + 2*p[10]*p[14]*p[28];
+ coeff[101] = -4*p[0]*p[7]*p[8]*p[22] + 2*p[0]*p[7]*p[8]*p[31] + 4*p[0]*p[7]*p[10]*p[17] - 2*p[0]*p[7]*p[10]*p[26] - 4*p[0]*p[8]*p[8]*p[20] + 2*p[0]*p[8]*p[8]*p[29] + 4*p[0]*p[8]*p[9]*p[17] - 2*p[0]*p[8]*p[9]*p[26] + 4*p[0]*p[9]*p[10]*p[22] - 2*p[0]*p[9]*p[10]*p[31] - 4*p[0]*p[10]*p[10]*p[20] + 2*p[0]*p[10]*p[10]*p[29] + 4*p[0]*p[11]*p[12]*p[22] - 2*p[0]*p[11]*p[12]*p[31] - 4*p[0]*p[11]*p[14]*p[17] + 2*p[0]*p[11]*p[14]*p[26] + 4*p[0]*p[12]*p[12]*p[20] - 2*p[0]*p[12]*p[12]*p[29] - 4*p[0]*p[12]*p[13]*p[17] + 2*p[0]*p[12]*p[13]*p[26] - 4*p[0]*p[13]*p[14]*p[22] + 2*p[0]*p[13]*p[14]*p[31] + 4*p[0]*p[14]*p[14]*p[20] - 2*p[0]*p[14]*p[14]*p[29] + 2*p[7]*p[11]*p[20] - 2*p[7]*p[11]*p[29] - 2*p[7]*p[12]*p[22] + 2*p[7]*p[12]*p[31] + 2*p[7]*p[14]*p[17] - 2*p[7]*p[14]*p[26] - 2*p[8]*p[11]*p[22] + 2*p[8]*p[11]*p[31] - 2*p[8]*p[12]*p[20] + 2*p[8]*p[12]*p[29] + 2*p[8]*p[13]*p[17] - 2*p[8]*p[13]*p[26] + 2*p[9]*p[12]*p[17] - 2*p[9]*p[12]*p[26] + 2*p[9]*p[13]*p[20] - 2*p[9]*p[13]*p[29] + 2*p[9]*p[14]*p[22] - 2*p[9]*p[14]*p[31] + 2*p[10]*p[11]*p[17] - 2*p[10]*p[11]*p[26] + 2*p[10]*p[13]*p[22] - 2*p[10]*p[13]*p[31] - 2*p[10]*p[14]*p[20] + 2*p[10]*p[14]*p[29];
+ coeff[102] = -2*p[0]*p[7]*p[10]*p[15] - 2*p[0]*p[8]*p[9]*p[15] + 2*p[0]*p[11]*p[14]*p[15] + 2*p[0]*p[12]*p[13]*p[15] - 2*p[7]*p[14]*p[15] + 2*p[7]*p[14]*p[24] - 2*p[8]*p[13]*p[15] + 2*p[8]*p[13]*p[24] - 2*p[9]*p[12]*p[15] + 2*p[9]*p[12]*p[24] - 2*p[10]*p[11]*p[15] + 2*p[10]*p[11]*p[24];
+ coeff[103] = -2*p[0]*p[7]*p[10]*p[16] + 2*p[0]*p[8]*p[8]*p[19] - 2*p[0]*p[8]*p[9]*p[16] + 2*p[0]*p[10]*p[10]*p[19] + 2*p[0]*p[11]*p[14]*p[16] - 2*p[0]*p[12]*p[12]*p[19] + 2*p[0]*p[12]*p[13]*p[16] - 2*p[0]*p[14]*p[14]*p[19] - 2*p[7]*p[11]*p[19] + 2*p[7]*p[11]*p[28] - 2*p[7]*p[14]*p[16] + 2*p[7]*p[14]*p[25] + 2*p[8]*p[12]*p[19] - 2*p[8]*p[12]*p[28] - 2*p[8]*p[13]*p[16] + 2*p[8]*p[13]*p[25] - 2*p[9]*p[12]*p[16] + 2*p[9]*p[12]*p[25] - 2*p[9]*p[13]*p[19] + 2*p[9]*p[13]*p[28] - 2*p[10]*p[11]*p[16] + 2*p[10]*p[11]*p[25] + 2*p[10]*p[14]*p[19] - 2*p[10]*p[14]*p[28];
+ coeff[104] = 2*p[0]*p[7]*p[8]*p[22] - 2*p[0]*p[7]*p[10]*p[17] + 2*p[0]*p[8]*p[8]*p[20] - 2*p[0]*p[8]*p[9]*p[17] - 2*p[0]*p[9]*p[10]*p[22] + 2*p[0]*p[10]*p[10]*p[20] - 2*p[0]*p[11]*p[12]*p[22] + 2*p[0]*p[11]*p[14]*p[17] - 2*p[0]*p[12]*p[12]*p[20] + 2*p[0]*p[12]*p[13]*p[17] + 2*p[0]*p[13]*p[14]*p[22] - 2*p[0]*p[14]*p[14]*p[20] - 2*p[7]*p[11]*p[20] + 2*p[7]*p[11]*p[29] + 2*p[7]*p[12]*p[22] - 2*p[7]*p[12]*p[31] - 2*p[7]*p[14]*p[17] + 2*p[7]*p[14]*p[26] + 2*p[8]*p[11]*p[22] - 2*p[8]*p[11]*p[31] + 2*p[8]*p[12]*p[20] - 2*p[8]*p[12]*p[29] - 2*p[8]*p[13]*p[17] + 2*p[8]*p[13]*p[26] - 2*p[9]*p[12]*p[17] + 2*p[9]*p[12]*p[26] - 2*p[9]*p[13]*p[20] + 2*p[9]*p[13]*p[29] - 2*p[9]*p[14]*p[22] + 2*p[9]*p[14]*p[31] - 2*p[10]*p[11]*p[17] + 2*p[10]*p[11]*p[26] - 2*p[10]*p[13]*p[22] + 2*p[10]*p[13]*p[31] + 2*p[10]*p[14]*p[20] - 2*p[10]*p[14]*p[29];
+ coeff[105] = 0;
+ coeff[106] = 2*(-p[7]*p[10]*p[15] + p[7]*p[10]*p[24] - p[8]*p[9]*p[15] + p[8]*p[9]*p[24] + p[11]*p[14]*p[15] - p[11]*p[14]*p[24] + p[12]*p[13]*p[15] - p[12]*p[13]*p[24])*p[0];
+ coeff[107] = 2*(-p[7]*p[10]*p[16] + p[7]*p[10]*p[25] + p[8]*p[8]*p[19] - p[8]*p[8]*p[28] - p[8]*p[9]*p[16] + p[8]*p[9]*p[25] + p[10]*p[10]*p[19] - p[10]*p[10]*p[28] + p[11]*p[14]*p[16] - p[11]*p[14]*p[25] - p[12]*p[12]*p[19] + p[12]*p[12]*p[28] + p[12]*p[13]*p[16] - p[12]*p[13]*p[25] - p[14]*p[14]*p[19] + p[14]*p[14]*p[28])*p[0];
+ coeff[108] = 2*(p[7]*p[8]*p[22] - p[7]*p[8]*p[31] - p[7]*p[10]*p[17] + p[7]*p[10]*p[26] + p[8]*p[8]*p[20] - p[8]*p[8]*p[29] - p[8]*p[9]*p[17] + p[8]*p[9]*p[26] - p[9]*p[10]*p[22] + p[9]*p[10]*p[31] + p[10]*p[10]*p[20] - p[10]*p[10]*p[29] - p[11]*p[12]*p[22] + p[11]*p[12]*p[31] + p[11]*p[14]*p[17] - p[11]*p[14]*p[26] - p[12]*p[12]*p[20] + p[12]*p[12]*p[29] + p[12]*p[13]*p[17] - p[12]*p[13]*p[26] + p[13]*p[14]*p[22] - p[13]*p[14]*p[31] - p[14]*p[14]*p[20] + p[14]*p[14]*p[29])*p[0];
+ coeff[109] = 2*(p[7]*p[10]*p[15] - p[7]*p[10]*p[24] + p[8]*p[9]*p[15] - p[8]*p[9]*p[24] - p[11]*p[14]*p[15] + p[11]*p[14]*p[24] - p[12]*p[13]*p[15] + p[12]*p[13]*p[24])*p[0];
+ coeff[110] = 2*(p[7]*p[10]*p[16] - p[7]*p[10]*p[25] - p[8]*p[8]*p[19] + p[8]*p[8]*p[28] + p[8]*p[9]*p[16] - p[8]*p[9]*p[25] - p[10]*p[10]*p[19] + p[10]*p[10]*p[28] - p[11]*p[14]*p[16] + p[11]*p[14]*p[25] + p[12]*p[12]*p[19] - p[12]*p[12]*p[28] - p[12]*p[13]*p[16] + p[12]*p[13]*p[25] + p[14]*p[14]*p[19] - p[14]*p[14]*p[28])*p[0];
+ coeff[111] = 2*(-p[7]*p[8]*p[22] + p[7]*p[8]*p[31] + p[7]*p[10]*p[17] - p[7]*p[10]*p[26] - p[8]*p[8]*p[20] + p[8]*p[8]*p[29] + p[8]*p[9]*p[17] - p[8]*p[9]*p[26] + p[9]*p[10]*p[22] - p[9]*p[10]*p[31] - p[10]*p[10]*p[20] + p[10]*p[10]*p[29] + p[11]*p[12]*p[22] - p[11]*p[12]*p[31] - p[11]*p[14]*p[17] + p[11]*p[14]*p[26] + p[12]*p[12]*p[20] - p[12]*p[12]*p[29] - p[12]*p[13]*p[17] + p[12]*p[13]*p[26] - p[13]*p[14]*p[22] + p[13]*p[14]*p[31] + p[14]*p[14]*p[20] - p[14]*p[14]*p[29])*p[0];
+ coeff[112] = -p[3] + p[6] - p[7]*p[8]*p[21] + p[7]*p[8]*p[30] + p[7]*p[9]*p[18] - p[7]*p[9]*p[27] + p[8]*p[8]*p[23] - p[8]*p[8]*p[32] - p[8]*p[10]*p[18] + p[8]*p[10]*p[27] + p[9]*p[9]*p[23] - p[9]*p[9]*p[32] - p[9]*p[10]*p[21] + p[9]*p[10]*p[30] - p[11]*p[12]*p[21] + p[11]*p[12]*p[30] + p[11]*p[13]*p[18] - p[11]*p[13]*p[27] + p[12]*p[12]*p[23] - p[12]*p[12]*p[32] - p[12]*p[14]*p[18] + p[12]*p[14]*p[27] + p[13]*p[13]*p[23] - p[13]*p[13]*p[32] - p[13]*p[14]*p[21] + p[13]*p[14]*p[30] - p[23] + p[32];
+ coeff[113] = 2*p[7]*p[9]*p[15] - p[7]*p[9]*p[24] - 2*p[8]*p[10]*p[15] + p[8]*p[10]*p[24] + 2*p[11]*p[13]*p[15] - p[11]*p[13]*p[24] - 2*p[12]*p[14]*p[15] + p[12]*p[14]*p[24];
+ coeff[114] = -2*p[7]*p[8]*p[19] + p[7]*p[8]*p[28] + 2*p[7]*p[9]*p[16] - p[7]*p[9]*p[25] - 2*p[8]*p[10]*p[16] + p[8]*p[10]*p[25] - 2*p[9]*p[10]*p[19] + p[9]*p[10]*p[28] - 2*p[11]*p[12]*p[19] + p[11]*p[12]*p[28] + 2*p[11]*p[13]*p[16] - p[11]*p[13]*p[25] - 2*p[12]*p[14]*p[16] + p[12]*p[14]*p[25] - 2*p[13]*p[14]*p[19] + p[13]*p[14]*p[28];
+ coeff[115] = -2*p[7]*p[8]*p[20] + p[7]*p[8]*p[29] + 2*p[7]*p[9]*p[17] - p[7]*p[9]*p[26] + 2*p[8]*p[8]*p[22] - p[8]*p[8]*p[31] - 2*p[8]*p[10]*p[17] + p[8]*p[10]*p[26] + 2*p[9]*p[9]*p[22] - p[9]*p[9]*p[31] - 2*p[9]*p[10]*p[20] + p[9]*p[10]*p[29] - 2*p[11]*p[12]*p[20] + p[11]*p[12]*p[29] + 2*p[11]*p[13]*p[17] - p[11]*p[13]*p[26] + 2*p[12]*p[12]*p[22] - p[12]*p[12]*p[31] - 2*p[12]*p[14]*p[17] + p[12]*p[14]*p[26] + 2*p[13]*p[13]*p[22] - p[13]*p[13]*p[31] - 2*p[13]*p[14]*p[20] + p[13]*p[14]*p[29] - 2*p[22] + p[31];
+ coeff[116] = (-p[7]*p[9] + p[8]*p[10] - p[11]*p[13] + p[12]*p[14])*p[15];
+ coeff[117] = p[7]*p[8]*p[19] - p[7]*p[9]*p[16] + p[8]*p[10]*p[16] + p[9]*p[10]*p[19] + p[11]*p[12]*p[19] - p[11]*p[13]*p[16] + p[12]*p[14]*p[16] + p[13]*p[14]*p[19];
+ coeff[118] = p[7]*p[8]*p[20] - p[7]*p[9]*p[17] - p[8]*p[8]*p[22] + p[8]*p[10]*p[17] - p[9]*p[9]*p[22] + p[9]*p[10]*p[20] + p[11]*p[12]*p[20] - p[11]*p[13]*p[17] - p[12]*p[12]*p[22] + p[12]*p[14]*p[17] - p[13]*p[13]*p[22] + p[13]*p[14]*p[20] + p[22];
+ coeff[119] = 0;
+ coeff[120] = -2*p[7]*p[9]*p[15] + 2*p[7]*p[9]*p[24] + 2*p[8]*p[10]*p[15] - 2*p[8]*p[10]*p[24] - 2*p[11]*p[13]*p[15] + 2*p[11]*p[13]*p[24] + 2*p[12]*p[14]*p[15] - 2*p[12]*p[14]*p[24];
+ coeff[121] = 2*p[7]*p[8]*p[19] - 2*p[7]*p[8]*p[28] - 2*p[7]*p[9]*p[16] + 2*p[7]*p[9]*p[25] + 2*p[8]*p[10]*p[16] - 2*p[8]*p[10]*p[25] + 2*p[9]*p[10]*p[19] - 2*p[9]*p[10]*p[28] + 2*p[11]*p[12]*p[19] - 2*p[11]*p[12]*p[28] - 2*p[11]*p[13]*p[16] + 2*p[11]*p[13]*p[25] + 2*p[12]*p[14]*p[16] - 2*p[12]*p[14]*p[25] + 2*p[13]*p[14]*p[19] - 2*p[13]*p[14]*p[28];
+ coeff[122] = 2*p[7]*p[8]*p[20] - 2*p[7]*p[8]*p[29] - 2*p[7]*p[9]*p[17] + 2*p[7]*p[9]*p[26] - 2*p[8]*p[8]*p[22] + 2*p[8]*p[8]*p[31] + 2*p[8]*p[10]*p[17] - 2*p[8]*p[10]*p[26] - 2*p[9]*p[9]*p[22] + 2*p[9]*p[9]*p[31] + 2*p[9]*p[10]*p[20] - 2*p[9]*p[10]*p[29] + 2*p[11]*p[12]*p[20] - 2*p[11]*p[12]*p[29] - 2*p[11]*p[13]*p[17] + 2*p[11]*p[13]*p[26] - 2*p[12]*p[12]*p[22] + 2*p[12]*p[12]*p[31] + 2*p[12]*p[14]*p[17] - 2*p[12]*p[14]*p[26] - 2*p[13]*p[13]*p[22] + 2*p[13]*p[13]*p[31] + 2*p[13]*p[14]*p[20] - 2*p[13]*p[14]*p[29] + 2*p[22] - 2*p[31];
+ coeff[123] = 2*p[7]*p[9]*p[15] - 2*p[7]*p[9]*p[24] - 2*p[8]*p[10]*p[15] + 2*p[8]*p[10]*p[24] + 2*p[11]*p[13]*p[15] - 2*p[11]*p[13]*p[24] - 2*p[12]*p[14]*p[15] + 2*p[12]*p[14]*p[24];
+ coeff[124] = -2*p[7]*p[8]*p[19] + 2*p[7]*p[8]*p[28] + 2*p[7]*p[9]*p[16] - 2*p[7]*p[9]*p[25] - 2*p[8]*p[10]*p[16] + 2*p[8]*p[10]*p[25] - 2*p[9]*p[10]*p[19] + 2*p[9]*p[10]*p[28] - 2*p[11]*p[12]*p[19] + 2*p[11]*p[12]*p[28] + 2*p[11]*p[13]*p[16] - 2*p[11]*p[13]*p[25] - 2*p[12]*p[14]*p[16] + 2*p[12]*p[14]*p[25] - 2*p[13]*p[14]*p[19] + 2*p[13]*p[14]*p[28];
+ coeff[125] = -2*p[7]*p[8]*p[20] + 2*p[7]*p[8]*p[29] + 2*p[7]*p[9]*p[17] - 2*p[7]*p[9]*p[26] + 2*p[8]*p[8]*p[22] - 2*p[8]*p[8]*p[31] - 2*p[8]*p[10]*p[17] + 2*p[8]*p[10]*p[26] + 2*p[9]*p[9]*p[22] - 2*p[9]*p[9]*p[31] - 2*p[9]*p[10]*p[20] + 2*p[9]*p[10]*p[29] - 2*p[11]*p[12]*p[20] + 2*p[11]*p[12]*p[29] + 2*p[11]*p[13]*p[17] - 2*p[11]*p[13]*p[26] + 2*p[12]*p[12]*p[22] - 2*p[12]*p[12]*p[31] - 2*p[12]*p[14]*p[17] + 2*p[12]*p[14]*p[26] + 2*p[13]*p[13]*p[22] - 2*p[13]*p[13]*p[31] - 2*p[13]*p[14]*p[20] + 2*p[13]*p[14]*p[29] - 2*p[22] + 2*p[31];
+ coeff[126] = 2*p[0]*p[7]*p[11]*p[23] + 2*p[0]*p[7]*p[12]*p[21] - 2*p[0]*p[7]*p[13]*p[18] + 2*p[0]*p[8]*p[11]*p[21] - 2*p[0]*p[8]*p[12]*p[23] + 2*p[0]*p[8]*p[14]*p[18] - 2*p[0]*p[9]*p[11]*p[18] - 2*p[0]*p[9]*p[13]*p[23] + 2*p[0]*p[9]*p[14]*p[21] + 2*p[0]*p[10]*p[12]*p[18] + 2*p[0]*p[10]*p[13]*p[21] + 2*p[0]*p[10]*p[14]*p[23] - p[7]*p[8]*p[21] + p[7]*p[8]*p[30] + p[7]*p[9]*p[18] - p[7]*p[9]*p[27] + p[8]*p[8]*p[23] - p[8]*p[8]*p[32] - p[8]*p[10]*p[18] + p[8]*p[10]*p[27] + p[9]*p[9]*p[23] - p[9]*p[9]*p[32] - p[9]*p[10]*p[21] + p[9]*p[10]*p[30] + p[11]*p[12]*p[21] - p[11]*p[12]*p[30] - p[11]*p[13]*p[18] + p[11]*p[13]*p[27] - p[12]*p[12]*p[23] + p[12]*p[12]*p[32] + p[12]*p[14]*p[18] - p[12]*p[14]*p[27] - p[13]*p[13]*p[23] + p[13]*p[13]*p[32] + p[13]*p[14]*p[21] - p[13]*p[14]*p[30];
+ coeff[127] = -2*p[0]*p[7]*p[13]*p[15] + 2*p[0]*p[8]*p[14]*p[15] - 2*p[0]*p[9]*p[11]*p[15] + 2*p[0]*p[10]*p[12]*p[15] + 2*p[7]*p[9]*p[15] - p[7]*p[9]*p[24] - 2*p[8]*p[10]*p[15] + p[8]*p[10]*p[24] - 2*p[11]*p[13]*p[15] + p[11]*p[13]*p[24] + 2*p[12]*p[14]*p[15] - p[12]*p[14]*p[24];
+ coeff[128] = 2*p[0]*p[7]*p[12]*p[19] - 2*p[0]*p[7]*p[13]*p[16] + 2*p[0]*p[8]*p[11]*p[19] + 2*p[0]*p[8]*p[14]*p[16] - 2*p[0]*p[9]*p[11]*p[16] + 2*p[0]*p[9]*p[14]*p[19] + 2*p[0]*p[10]*p[12]*p[16] + 2*p[0]*p[10]*p[13]*p[19] - 2*p[7]*p[8]*p[19] + p[7]*p[8]*p[28] + 2*p[7]*p[9]*p[16] - p[7]*p[9]*p[25] - 2*p[8]*p[10]*p[16] + p[8]*p[10]*p[25] - 2*p[9]*p[10]*p[19] + p[9]*p[10]*p[28] + 2*p[11]*p[12]*p[19] - p[11]*p[12]*p[28] - 2*p[11]*p[13]*p[16] + p[11]*p[13]*p[25] + 2*p[12]*p[14]*p[16] - p[12]*p[14]*p[25] + 2*p[13]*p[14]*p[19] - p[13]*p[14]*p[28];
+ coeff[129] = 2*p[0]*p[7]*p[11]*p[22] + 2*p[0]*p[7]*p[12]*p[20] - 2*p[0]*p[7]*p[13]*p[17] + 2*p[0]*p[8]*p[11]*p[20] - 2*p[0]*p[8]*p[12]*p[22] + 2*p[0]*p[8]*p[14]*p[17] - 2*p[0]*p[9]*p[11]*p[17] - 2*p[0]*p[9]*p[13]*p[22] + 2*p[0]*p[9]*p[14]*p[20] + 2*p[0]*p[10]*p[12]*p[17] + 2*p[0]*p[10]*p[13]*p[20] + 2*p[0]*p[10]*p[14]*p[22] - 2*p[7]*p[8]*p[20] + p[7]*p[8]*p[29] + 2*p[7]*p[9]*p[17] - p[7]*p[9]*p[26] + 2*p[8]*p[8]*p[22] - p[8]*p[8]*p[31] - 2*p[8]*p[10]*p[17] + p[8]*p[10]*p[26] + 2*p[9]*p[9]*p[22] - p[9]*p[9]*p[31] - 2*p[9]*p[10]*p[20] + p[9]*p[10]*p[29] + 2*p[11]*p[12]*p[20] - p[11]*p[12]*p[29] - 2*p[11]*p[13]*p[17] + p[11]*p[13]*p[26] - 2*p[12]*p[12]*p[22] + p[12]*p[12]*p[31] + 2*p[12]*p[14]*p[17] - p[12]*p[14]*p[26] - 2*p[13]*p[13]*p[22] + p[13]*p[13]*p[31] + 2*p[13]*p[14]*p[20] - p[13]*p[14]*p[29];
+ coeff[130] = (-p[7]*p[9] + p[8]*p[10] + p[11]*p[13] - p[12]*p[14])*p[15];
+ coeff[131] = p[7]*p[8]*p[19] - p[7]*p[9]*p[16] + p[8]*p[10]*p[16] + p[9]*p[10]*p[19] - p[11]*p[12]*p[19] + p[11]*p[13]*p[16] - p[12]*p[14]*p[16] - p[13]*p[14]*p[19];
+ coeff[132] = p[7]*p[8]*p[20] - p[7]*p[9]*p[17] - p[8]*p[8]*p[22] + p[8]*p[10]*p[17] - p[9]*p[9]*p[22] + p[9]*p[10]*p[20] - p[11]*p[12]*p[20] + p[11]*p[13]*p[17] + p[12]*p[12]*p[22] - p[12]*p[14]*p[17] + p[13]*p[13]*p[22] - p[13]*p[14]*p[20];
+ coeff[133] = 2*(-p[7]*p[11]*p[23] + p[7]*p[11]*p[32] - p[7]*p[12]*p[21] + p[7]*p[12]*p[30] + p[7]*p[13]*p[18] - p[7]*p[13]*p[27] - p[8]*p[11]*p[21] + p[8]*p[11]*p[30] + p[8]*p[12]*p[23] - p[8]*p[12]*p[32] - p[8]*p[14]*p[18] + p[8]*p[14]*p[27] + p[9]*p[11]*p[18] - p[9]*p[11]*p[27] + p[9]*p[13]*p[23] - p[9]*p[13]*p[32] - p[9]*p[14]*p[21] + p[9]*p[14]*p[30] - p[10]*p[12]*p[18] + p[10]*p[12]*p[27] - p[10]*p[13]*p[21] + p[10]*p[13]*p[30] - p[10]*p[14]*p[23] + p[10]*p[14]*p[32])*p[0];
+ coeff[134] = 4*p[0]*p[7]*p[13]*p[15] - 2*p[0]*p[7]*p[13]*p[24] - 4*p[0]*p[8]*p[14]*p[15] + 2*p[0]*p[8]*p[14]*p[24] + 4*p[0]*p[9]*p[11]*p[15] - 2*p[0]*p[9]*p[11]*p[24] - 4*p[0]*p[10]*p[12]*p[15] + 2*p[0]*p[10]*p[12]*p[24] - 2*p[7]*p[9]*p[15] + 2*p[7]*p[9]*p[24] + 2*p[8]*p[10]*p[15] - 2*p[8]*p[10]*p[24] + 2*p[11]*p[13]*p[15] - 2*p[11]*p[13]*p[24] - 2*p[12]*p[14]*p[15] + 2*p[12]*p[14]*p[24];
+ coeff[135] = -4*p[0]*p[7]*p[12]*p[19] + 2*p[0]*p[7]*p[12]*p[28] + 4*p[0]*p[7]*p[13]*p[16] - 2*p[0]*p[7]*p[13]*p[25] - 4*p[0]*p[8]*p[11]*p[19] + 2*p[0]*p[8]*p[11]*p[28] - 4*p[0]*p[8]*p[14]*p[16] + 2*p[0]*p[8]*p[14]*p[25] + 4*p[0]*p[9]*p[11]*p[16] - 2*p[0]*p[9]*p[11]*p[25] - 4*p[0]*p[9]*p[14]*p[19] + 2*p[0]*p[9]*p[14]*p[28] - 4*p[0]*p[10]*p[12]*p[16] + 2*p[0]*p[10]*p[12]*p[25] - 4*p[0]*p[10]*p[13]*p[19] + 2*p[0]*p[10]*p[13]*p[28] + 2*p[7]*p[8]*p[19] - 2*p[7]*p[8]*p[28] - 2*p[7]*p[9]*p[16] + 2*p[7]*p[9]*p[25] + 2*p[8]*p[10]*p[16] - 2*p[8]*p[10]*p[25] + 2*p[9]*p[10]*p[19] - 2*p[9]*p[10]*p[28] - 2*p[11]*p[12]*p[19] + 2*p[11]*p[12]*p[28] + 2*p[11]*p[13]*p[16] - 2*p[11]*p[13]*p[25] - 2*p[12]*p[14]*p[16] + 2*p[12]*p[14]*p[25] - 2*p[13]*p[14]*p[19] + 2*p[13]*p[14]*p[28];
+ coeff[136] = -4*p[0]*p[7]*p[11]*p[22] + 2*p[0]*p[7]*p[11]*p[31] - 4*p[0]*p[7]*p[12]*p[20] + 2*p[0]*p[7]*p[12]*p[29] + 4*p[0]*p[7]*p[13]*p[17] - 2*p[0]*p[7]*p[13]*p[26] - 4*p[0]*p[8]*p[11]*p[20] + 2*p[0]*p[8]*p[11]*p[29] + 4*p[0]*p[8]*p[12]*p[22] - 2*p[0]*p[8]*p[12]*p[31] - 4*p[0]*p[8]*p[14]*p[17] + 2*p[0]*p[8]*p[14]*p[26] + 4*p[0]*p[9]*p[11]*p[17] - 2*p[0]*p[9]*p[11]*p[26] + 4*p[0]*p[9]*p[13]*p[22] - 2*p[0]*p[9]*p[13]*p[31] - 4*p[0]*p[9]*p[14]*p[20] + 2*p[0]*p[9]*p[14]*p[29] - 4*p[0]*p[10]*p[12]*p[17] + 2*p[0]*p[10]*p[12]*p[26] - 4*p[0]*p[10]*p[13]*p[20] + 2*p[0]*p[10]*p[13]*p[29] - 4*p[0]*p[10]*p[14]*p[22] + 2*p[0]*p[10]*p[14]*p[31] + 2*p[7]*p[8]*p[20] - 2*p[7]*p[8]*p[29] - 2*p[7]*p[9]*p[17] + 2*p[7]*p[9]*p[26] - 2*p[8]*p[8]*p[22] + 2*p[8]*p[8]*p[31] + 2*p[8]*p[10]*p[17] - 2*p[8]*p[10]*p[26] - 2*p[9]*p[9]*p[22] + 2*p[9]*p[9]*p[31] + 2*p[9]*p[10]*p[20] - 2*p[9]*p[10]*p[29] - 2*p[11]*p[12]*p[20] + 2*p[11]*p[12]*p[29] + 2*p[11]*p[13]*p[17] - 2*p[11]*p[13]*p[26] + 2*p[12]*p[12]*p[22] - 2*p[12]*p[12]*p[31] - 2*p[12]*p[14]*p[17] + 2*p[12]*p[14]*p[26] + 2*p[13]*p[13]*p[22] - 2*p[13]*p[13]*p[31] - 2*p[13]*p[14]*p[20] + 2*p[13]*p[14]*p[29];
+ coeff[137] = -2*p[0]*p[7]*p[13]*p[15] + 2*p[0]*p[8]*p[14]*p[15] - 2*p[0]*p[9]*p[11]*p[15] + 2*p[0]*p[10]*p[12]*p[15] + 2*p[7]*p[9]*p[15] - 2*p[7]*p[9]*p[24] - 2*p[8]*p[10]*p[15] + 2*p[8]*p[10]*p[24] - 2*p[11]*p[13]*p[15] + 2*p[11]*p[13]*p[24] + 2*p[12]*p[14]*p[15] - 2*p[12]*p[14]*p[24];
+ coeff[138] = 2*p[0]*p[7]*p[12]*p[19] - 2*p[0]*p[7]*p[13]*p[16] + 2*p[0]*p[8]*p[11]*p[19] + 2*p[0]*p[8]*p[14]*p[16] - 2*p[0]*p[9]*p[11]*p[16] + 2*p[0]*p[9]*p[14]*p[19] + 2*p[0]*p[10]*p[12]*p[16] + 2*p[0]*p[10]*p[13]*p[19] - 2*p[7]*p[8]*p[19] + 2*p[7]*p[8]*p[28] + 2*p[7]*p[9]*p[16] - 2*p[7]*p[9]*p[25] - 2*p[8]*p[10]*p[16] + 2*p[8]*p[10]*p[25] - 2*p[9]*p[10]*p[19] + 2*p[9]*p[10]*p[28] + 2*p[11]*p[12]*p[19] - 2*p[11]*p[12]*p[28] - 2*p[11]*p[13]*p[16] + 2*p[11]*p[13]*p[25] + 2*p[12]*p[14]*p[16] - 2*p[12]*p[14]*p[25] + 2*p[13]*p[14]*p[19] - 2*p[13]*p[14]*p[28];
+ coeff[139] = 2*p[0]*p[7]*p[11]*p[22] + 2*p[0]*p[7]*p[12]*p[20] - 2*p[0]*p[7]*p[13]*p[17] + 2*p[0]*p[8]*p[11]*p[20] - 2*p[0]*p[8]*p[12]*p[22] + 2*p[0]*p[8]*p[14]*p[17] - 2*p[0]*p[9]*p[11]*p[17] - 2*p[0]*p[9]*p[13]*p[22] + 2*p[0]*p[9]*p[14]*p[20] + 2*p[0]*p[10]*p[12]*p[17] + 2*p[0]*p[10]*p[13]*p[20] + 2*p[0]*p[10]*p[14]*p[22] - 2*p[7]*p[8]*p[20] + 2*p[7]*p[8]*p[29] + 2*p[7]*p[9]*p[17] - 2*p[7]*p[9]*p[26] + 2*p[8]*p[8]*p[22] - 2*p[8]*p[8]*p[31] - 2*p[8]*p[10]*p[17] + 2*p[8]*p[10]*p[26] + 2*p[9]*p[9]*p[22] - 2*p[9]*p[9]*p[31] - 2*p[9]*p[10]*p[20] + 2*p[9]*p[10]*p[29] + 2*p[11]*p[12]*p[20] - 2*p[11]*p[12]*p[29] - 2*p[11]*p[13]*p[17] + 2*p[11]*p[13]*p[26] - 2*p[12]*p[12]*p[22] + 2*p[12]*p[12]*p[31] + 2*p[12]*p[14]*p[17] - 2*p[12]*p[14]*p[26] - 2*p[13]*p[13]*p[22] + 2*p[13]*p[13]*p[31] + 2*p[13]*p[14]*p[20] - 2*p[13]*p[14]*p[29];
+ coeff[140] = 0;
+ coeff[141] = 2*(-p[7]*p[13]*p[15] + p[7]*p[13]*p[24] + p[8]*p[14]*p[15] - p[8]*p[14]*p[24] - p[9]*p[11]*p[15] + p[9]*p[11]*p[24] + p[10]*p[12]*p[15] - p[10]*p[12]*p[24])*p[0];
+ coeff[142] = 2*(p[7]*p[12]*p[19] - p[7]*p[12]*p[28] - p[7]*p[13]*p[16] + p[7]*p[13]*p[25] + p[8]*p[11]*p[19] - p[8]*p[11]*p[28] + p[8]*p[14]*p[16] - p[8]*p[14]*p[25] - p[9]*p[11]*p[16] + p[9]*p[11]*p[25] + p[9]*p[14]*p[19] - p[9]*p[14]*p[28] + p[10]*p[12]*p[16] - p[10]*p[12]*p[25] + p[10]*p[13]*p[19] - p[10]*p[13]*p[28])*p[0];
+ coeff[143] = 2*(p[7]*p[11]*p[22] - p[7]*p[11]*p[31] + p[7]*p[12]*p[20] - p[7]*p[12]*p[29] - p[7]*p[13]*p[17] + p[7]*p[13]*p[26] + p[8]*p[11]*p[20] - p[8]*p[11]*p[29] - p[8]*p[12]*p[22] + p[8]*p[12]*p[31] + p[8]*p[14]*p[17] - p[8]*p[14]*p[26] - p[9]*p[11]*p[17] + p[9]*p[11]*p[26] - p[9]*p[13]*p[22] + p[9]*p[13]*p[31] + p[9]*p[14]*p[20] - p[9]*p[14]*p[29] + p[10]*p[12]*p[17] - p[10]*p[12]*p[26] + p[10]*p[13]*p[20] - p[10]*p[13]*p[29] + p[10]*p[14]*p[22] - p[10]*p[14]*p[31])*p[0];
+ coeff[144] = 2*(p[7]*p[13]*p[15] - p[7]*p[13]*p[24] - p[8]*p[14]*p[15] + p[8]*p[14]*p[24] + p[9]*p[11]*p[15] - p[9]*p[11]*p[24] - p[10]*p[12]*p[15] + p[10]*p[12]*p[24])*p[0];
+ coeff[145] = 2*(-p[7]*p[12]*p[19] + p[7]*p[12]*p[28] + p[7]*p[13]*p[16] - p[7]*p[13]*p[25] - p[8]*p[11]*p[19] + p[8]*p[11]*p[28] - p[8]*p[14]*p[16] + p[8]*p[14]*p[25] + p[9]*p[11]*p[16] - p[9]*p[11]*p[25] - p[9]*p[14]*p[19] + p[9]*p[14]*p[28] - p[10]*p[12]*p[16] + p[10]*p[12]*p[25] - p[10]*p[13]*p[19] + p[10]*p[13]*p[28])*p[0];
+ coeff[146] = 2*(-p[7]*p[11]*p[22] + p[7]*p[11]*p[31] - p[7]*p[12]*p[20] + p[7]*p[12]*p[29] + p[7]*p[13]*p[17] - p[7]*p[13]*p[26] - p[8]*p[11]*p[20] + p[8]*p[11]*p[29] + p[8]*p[12]*p[22] - p[8]*p[12]*p[31] - p[8]*p[14]*p[17] + p[8]*p[14]*p[26] + p[9]*p[11]*p[17] - p[9]*p[11]*p[26] + p[9]*p[13]*p[22] - p[9]*p[13]*p[31] - p[9]*p[14]*p[20] + p[9]*p[14]*p[29] - p[10]*p[12]*p[17] + p[10]*p[12]*p[26] - p[10]*p[13]*p[20] + p[10]*p[13]*p[29] - p[10]*p[14]*p[22] + p[10]*p[14]*p[31])*p[0];
+ coeff[147] = -2*p[0]*p[7]*p[8]*p[21] + 2*p[0]*p[7]*p[9]*p[18] + 2*p[0]*p[8]*p[8]*p[23] - 2*p[0]*p[8]*p[10]*p[18] + 2*p[0]*p[9]*p[9]*p[23] - 2*p[0]*p[9]*p[10]*p[21] + 2*p[0]*p[11]*p[12]*p[21] - 2*p[0]*p[11]*p[13]*p[18] - 2*p[0]*p[12]*p[12]*p[23] + 2*p[0]*p[12]*p[14]*p[18] - 2*p[0]*p[13]*p[13]*p[23] + 2*p[0]*p[13]*p[14]*p[21] - p[7]*p[11]*p[23] + p[7]*p[11]*p[32] - p[7]*p[12]*p[21] + p[7]*p[12]*p[30] + p[7]*p[13]*p[18] - p[7]*p[13]*p[27] - p[8]*p[11]*p[21] + p[8]*p[11]*p[30] + p[8]*p[12]*p[23] - p[8]*p[12]*p[32] - p[8]*p[14]*p[18] + p[8]*p[14]*p[27] + p[9]*p[11]*p[18] - p[9]*p[11]*p[27] + p[9]*p[13]*p[23] - p[9]*p[13]*p[32] - p[9]*p[14]*p[21] + p[9]*p[14]*p[30] - p[10]*p[12]*p[18] + p[10]*p[12]*p[27] - p[10]*p[13]*p[21] + p[10]*p[13]*p[30] - p[10]*p[14]*p[23] + p[10]*p[14]*p[32];
+ coeff[148] = 2*p[0]*p[7]*p[9]*p[15] - 2*p[0]*p[8]*p[10]*p[15] - 2*p[0]*p[11]*p[13]*p[15] + 2*p[0]*p[12]*p[14]*p[15] + 2*p[7]*p[13]*p[15] - p[7]*p[13]*p[24] - 2*p[8]*p[14]*p[15] + p[8]*p[14]*p[24] + 2*p[9]*p[11]*p[15] - p[9]*p[11]*p[24] - 2*p[10]*p[12]*p[15] + p[10]*p[12]*p[24];
+ coeff[149] = -2*p[0]*p[7]*p[8]*p[19] + 2*p[0]*p[7]*p[9]*p[16] - 2*p[0]*p[8]*p[10]*p[16] - 2*p[0]*p[9]*p[10]*p[19] + 2*p[0]*p[11]*p[12]*p[19] - 2*p[0]*p[11]*p[13]*p[16] + 2*p[0]*p[12]*p[14]*p[16] + 2*p[0]*p[13]*p[14]*p[19] - 2*p[7]*p[12]*p[19] + p[7]*p[12]*p[28] + 2*p[7]*p[13]*p[16] - p[7]*p[13]*p[25] - 2*p[8]*p[11]*p[19] + p[8]*p[11]*p[28] - 2*p[8]*p[14]*p[16] + p[8]*p[14]*p[25] + 2*p[9]*p[11]*p[16] - p[9]*p[11]*p[25] - 2*p[9]*p[14]*p[19] + p[9]*p[14]*p[28] - 2*p[10]*p[12]*p[16] + p[10]*p[12]*p[25] - 2*p[10]*p[13]*p[19] + p[10]*p[13]*p[28];
+ coeff[150] = -2*p[0]*p[7]*p[8]*p[20] + 2*p[0]*p[7]*p[9]*p[17] + 2*p[0]*p[8]*p[8]*p[22] - 2*p[0]*p[8]*p[10]*p[17] + 2*p[0]*p[9]*p[9]*p[22] - 2*p[0]*p[9]*p[10]*p[20] + 2*p[0]*p[11]*p[12]*p[20] - 2*p[0]*p[11]*p[13]*p[17] - 2*p[0]*p[12]*p[12]*p[22] + 2*p[0]*p[12]*p[14]*p[17] - 2*p[0]*p[13]*p[13]*p[22] + 2*p[0]*p[13]*p[14]*p[20] - 2*p[7]*p[11]*p[22] + p[7]*p[11]*p[31] - 2*p[7]*p[12]*p[20] + p[7]*p[12]*p[29] + 2*p[7]*p[13]*p[17] - p[7]*p[13]*p[26] - 2*p[8]*p[11]*p[20] + p[8]*p[11]*p[29] + 2*p[8]*p[12]*p[22] - p[8]*p[12]*p[31] - 2*p[8]*p[14]*p[17] + p[8]*p[14]*p[26] + 2*p[9]*p[11]*p[17] - p[9]*p[11]*p[26] + 2*p[9]*p[13]*p[22] - p[9]*p[13]*p[31] - 2*p[9]*p[14]*p[20] + p[9]*p[14]*p[29] - 2*p[10]*p[12]*p[17] + p[10]*p[12]*p[26] - 2*p[10]*p[13]*p[20] + p[10]*p[13]*p[29] - 2*p[10]*p[14]*p[22] + p[10]*p[14]*p[31];
+ coeff[151] = (-p[7]*p[13] + p[8]*p[14] - p[9]*p[11] + p[10]*p[12])*p[15];
+ coeff[152] = p[7]*p[12]*p[19] - p[7]*p[13]*p[16] + p[8]*p[11]*p[19] + p[8]*p[14]*p[16] - p[9]*p[11]*p[16] + p[9]*p[14]*p[19] + p[10]*p[12]*p[16] + p[10]*p[13]*p[19];
+ coeff[153] = p[7]*p[11]*p[22] + p[7]*p[12]*p[20] - p[7]*p[13]*p[17] + p[8]*p[11]*p[20] - p[8]*p[12]*p[22] + p[8]*p[14]*p[17] - p[9]*p[11]*p[17] - p[9]*p[13]*p[22] + p[9]*p[14]*p[20] + p[10]*p[12]*p[17] + p[10]*p[13]*p[20] + p[10]*p[14]*p[22];
+ coeff[154] = 2*(p[7]*p[8]*p[21] - p[7]*p[8]*p[30] - p[7]*p[9]*p[18] + p[7]*p[9]*p[27] - p[8]*p[8]*p[23] + p[8]*p[8]*p[32] + p[8]*p[10]*p[18] - p[8]*p[10]*p[27] - p[9]*p[9]*p[23] + p[9]*p[9]*p[32] + p[9]*p[10]*p[21] - p[9]*p[10]*p[30] - p[11]*p[12]*p[21] + p[11]*p[12]*p[30] + p[11]*p[13]*p[18] - p[11]*p[13]*p[27] + p[12]*p[12]*p[23] - p[12]*p[12]*p[32] - p[12]*p[14]*p[18] + p[12]*p[14]*p[27] + p[13]*p[13]*p[23] - p[13]*p[13]*p[32] - p[13]*p[14]*p[21] + p[13]*p[14]*p[30])*p[0];
+ coeff[155] = -4*p[0]*p[7]*p[9]*p[15] + 2*p[0]*p[7]*p[9]*p[24] + 4*p[0]*p[8]*p[10]*p[15] - 2*p[0]*p[8]*p[10]*p[24] + 4*p[0]*p[11]*p[13]*p[15] - 2*p[0]*p[11]*p[13]*p[24] - 4*p[0]*p[12]*p[14]*p[15] + 2*p[0]*p[12]*p[14]*p[24] - 2*p[7]*p[13]*p[15] + 2*p[7]*p[13]*p[24] + 2*p[8]*p[14]*p[15] - 2*p[8]*p[14]*p[24] - 2*p[9]*p[11]*p[15] + 2*p[9]*p[11]*p[24] + 2*p[10]*p[12]*p[15] - 2*p[10]*p[12]*p[24];
+ coeff[156] = 4*p[0]*p[7]*p[8]*p[19] - 2*p[0]*p[7]*p[8]*p[28] - 4*p[0]*p[7]*p[9]*p[16] + 2*p[0]*p[7]*p[9]*p[25] + 4*p[0]*p[8]*p[10]*p[16] - 2*p[0]*p[8]*p[10]*p[25] + 4*p[0]*p[9]*p[10]*p[19] - 2*p[0]*p[9]*p[10]*p[28] - 4*p[0]*p[11]*p[12]*p[19] + 2*p[0]*p[11]*p[12]*p[28] + 4*p[0]*p[11]*p[13]*p[16] - 2*p[0]*p[11]*p[13]*p[25] - 4*p[0]*p[12]*p[14]*p[16] + 2*p[0]*p[12]*p[14]*p[25] - 4*p[0]*p[13]*p[14]*p[19] + 2*p[0]*p[13]*p[14]*p[28] + 2*p[7]*p[12]*p[19] - 2*p[7]*p[12]*p[28] - 2*p[7]*p[13]*p[16] + 2*p[7]*p[13]*p[25] + 2*p[8]*p[11]*p[19] - 2*p[8]*p[11]*p[28] + 2*p[8]*p[14]*p[16] - 2*p[8]*p[14]*p[25] - 2*p[9]*p[11]*p[16] + 2*p[9]*p[11]*p[25] + 2*p[9]*p[14]*p[19] - 2*p[9]*p[14]*p[28] + 2*p[10]*p[12]*p[16] - 2*p[10]*p[12]*p[25] + 2*p[10]*p[13]*p[19] - 2*p[10]*p[13]*p[28];
+ coeff[157] = 4*p[0]*p[7]*p[8]*p[20] - 2*p[0]*p[7]*p[8]*p[29] - 4*p[0]*p[7]*p[9]*p[17] + 2*p[0]*p[7]*p[9]*p[26] - 4*p[0]*p[8]*p[8]*p[22] + 2*p[0]*p[8]*p[8]*p[31] + 4*p[0]*p[8]*p[10]*p[17] - 2*p[0]*p[8]*p[10]*p[26] - 4*p[0]*p[9]*p[9]*p[22] + 2*p[0]*p[9]*p[9]*p[31] + 4*p[0]*p[9]*p[10]*p[20] - 2*p[0]*p[9]*p[10]*p[29] - 4*p[0]*p[11]*p[12]*p[20] + 2*p[0]*p[11]*p[12]*p[29] + 4*p[0]*p[11]*p[13]*p[17] - 2*p[0]*p[11]*p[13]*p[26] + 4*p[0]*p[12]*p[12]*p[22] - 2*p[0]*p[12]*p[12]*p[31] - 4*p[0]*p[12]*p[14]*p[17] + 2*p[0]*p[12]*p[14]*p[26] + 4*p[0]*p[13]*p[13]*p[22] - 2*p[0]*p[13]*p[13]*p[31] - 4*p[0]*p[13]*p[14]*p[20] + 2*p[0]*p[13]*p[14]*p[29] + 2*p[7]*p[11]*p[22] - 2*p[7]*p[11]*p[31] + 2*p[7]*p[12]*p[20] - 2*p[7]*p[12]*p[29] - 2*p[7]*p[13]*p[17] + 2*p[7]*p[13]*p[26] + 2*p[8]*p[11]*p[20] - 2*p[8]*p[11]*p[29] - 2*p[8]*p[12]*p[22] + 2*p[8]*p[12]*p[31] + 2*p[8]*p[14]*p[17] - 2*p[8]*p[14]*p[26] - 2*p[9]*p[11]*p[17] + 2*p[9]*p[11]*p[26] - 2*p[9]*p[13]*p[22] + 2*p[9]*p[13]*p[31] + 2*p[9]*p[14]*p[20] - 2*p[9]*p[14]*p[29] + 2*p[10]*p[12]*p[17] - 2*p[10]*p[12]*p[26] + 2*p[10]*p[13]*p[20] - 2*p[10]*p[13]*p[29] + 2*p[10]*p[14]*p[22] - 2*p[10]*p[14]*p[31];
+ coeff[158] = 2*p[0]*p[7]*p[9]*p[15] - 2*p[0]*p[8]*p[10]*p[15] - 2*p[0]*p[11]*p[13]*p[15] + 2*p[0]*p[12]*p[14]*p[15] + 2*p[7]*p[13]*p[15] - 2*p[7]*p[13]*p[24] - 2*p[8]*p[14]*p[15] + 2*p[8]*p[14]*p[24] + 2*p[9]*p[11]*p[15] - 2*p[9]*p[11]*p[24] - 2*p[10]*p[12]*p[15] + 2*p[10]*p[12]*p[24];
+ coeff[159] = -2*p[0]*p[7]*p[8]*p[19] + 2*p[0]*p[7]*p[9]*p[16] - 2*p[0]*p[8]*p[10]*p[16] - 2*p[0]*p[9]*p[10]*p[19] + 2*p[0]*p[11]*p[12]*p[19] - 2*p[0]*p[11]*p[13]*p[16] + 2*p[0]*p[12]*p[14]*p[16] + 2*p[0]*p[13]*p[14]*p[19] - 2*p[7]*p[12]*p[19] + 2*p[7]*p[12]*p[28] + 2*p[7]*p[13]*p[16] - 2*p[7]*p[13]*p[25] - 2*p[8]*p[11]*p[19] + 2*p[8]*p[11]*p[28] - 2*p[8]*p[14]*p[16] + 2*p[8]*p[14]*p[25] + 2*p[9]*p[11]*p[16] - 2*p[9]*p[11]*p[25] - 2*p[9]*p[14]*p[19] + 2*p[9]*p[14]*p[28] - 2*p[10]*p[12]*p[16] + 2*p[10]*p[12]*p[25] - 2*p[10]*p[13]*p[19] + 2*p[10]*p[13]*p[28];
+ coeff[160] = -2*p[0]*p[7]*p[8]*p[20] + 2*p[0]*p[7]*p[9]*p[17] + 2*p[0]*p[8]*p[8]*p[22] - 2*p[0]*p[8]*p[10]*p[17] + 2*p[0]*p[9]*p[9]*p[22] - 2*p[0]*p[9]*p[10]*p[20] + 2*p[0]*p[11]*p[12]*p[20] - 2*p[0]*p[11]*p[13]*p[17] - 2*p[0]*p[12]*p[12]*p[22] + 2*p[0]*p[12]*p[14]*p[17] - 2*p[0]*p[13]*p[13]*p[22] + 2*p[0]*p[13]*p[14]*p[20] - 2*p[7]*p[11]*p[22] + 2*p[7]*p[11]*p[31] - 2*p[7]*p[12]*p[20] + 2*p[7]*p[12]*p[29] + 2*p[7]*p[13]*p[17] - 2*p[7]*p[13]*p[26] - 2*p[8]*p[11]*p[20] + 2*p[8]*p[11]*p[29] + 2*p[8]*p[12]*p[22] - 2*p[8]*p[12]*p[31] - 2*p[8]*p[14]*p[17] + 2*p[8]*p[14]*p[26] + 2*p[9]*p[11]*p[17] - 2*p[9]*p[11]*p[26] + 2*p[9]*p[13]*p[22] - 2*p[9]*p[13]*p[31] - 2*p[9]*p[14]*p[20] + 2*p[9]*p[14]*p[29] - 2*p[10]*p[12]*p[17] + 2*p[10]*p[12]*p[26] - 2*p[10]*p[13]*p[20] + 2*p[10]*p[13]*p[29] - 2*p[10]*p[14]*p[22] + 2*p[10]*p[14]*p[31];
+ coeff[161] = 0;
+ coeff[162] = 2*(p[7]*p[9]*p[15] - p[7]*p[9]*p[24] - p[8]*p[10]*p[15] + p[8]*p[10]*p[24] - p[11]*p[13]*p[15] + p[11]*p[13]*p[24] + p[12]*p[14]*p[15] - p[12]*p[14]*p[24])*p[0];
+ coeff[163] = 2*(-p[7]*p[8]*p[19] + p[7]*p[8]*p[28] + p[7]*p[9]*p[16] - p[7]*p[9]*p[25] - p[8]*p[10]*p[16] + p[8]*p[10]*p[25] - p[9]*p[10]*p[19] + p[9]*p[10]*p[28] + p[11]*p[12]*p[19] - p[11]*p[12]*p[28] - p[11]*p[13]*p[16] + p[11]*p[13]*p[25] + p[12]*p[14]*p[16] - p[12]*p[14]*p[25] + p[13]*p[14]*p[19] - p[13]*p[14]*p[28])*p[0];
+ coeff[164] = 2*(-p[7]*p[8]*p[20] + p[7]*p[8]*p[29] + p[7]*p[9]*p[17] - p[7]*p[9]*p[26] + p[8]*p[8]*p[22] - p[8]*p[8]*p[31] - p[8]*p[10]*p[17] + p[8]*p[10]*p[26] + p[9]*p[9]*p[22] - p[9]*p[9]*p[31] - p[9]*p[10]*p[20] + p[9]*p[10]*p[29] + p[11]*p[12]*p[20] - p[11]*p[12]*p[29] - p[11]*p[13]*p[17] + p[11]*p[13]*p[26] - p[12]*p[12]*p[22] + p[12]*p[12]*p[31] + p[12]*p[14]*p[17] - p[12]*p[14]*p[26] - p[13]*p[13]*p[22] + p[13]*p[13]*p[31] + p[13]*p[14]*p[20] - p[13]*p[14]*p[29])*p[0];
+ coeff[165] = 2*(-p[7]*p[9]*p[15] + p[7]*p[9]*p[24] + p[8]*p[10]*p[15] - p[8]*p[10]*p[24] + p[11]*p[13]*p[15] - p[11]*p[13]*p[24] - p[12]*p[14]*p[15] + p[12]*p[14]*p[24])*p[0];
+ coeff[166] = 2*(p[7]*p[8]*p[19] - p[7]*p[8]*p[28] - p[7]*p[9]*p[16] + p[7]*p[9]*p[25] + p[8]*p[10]*p[16] - p[8]*p[10]*p[25] + p[9]*p[10]*p[19] - p[9]*p[10]*p[28] - p[11]*p[12]*p[19] + p[11]*p[12]*p[28] + p[11]*p[13]*p[16] - p[11]*p[13]*p[25] - p[12]*p[14]*p[16] + p[12]*p[14]*p[25] - p[13]*p[14]*p[19] + p[13]*p[14]*p[28])*p[0];
+ coeff[167] = 2*(p[7]*p[8]*p[20] - p[7]*p[8]*p[29] - p[7]*p[9]*p[17] + p[7]*p[9]*p[26] - p[8]*p[8]*p[22] + p[8]*p[8]*p[31] + p[8]*p[10]*p[17] - p[8]*p[10]*p[26] - p[9]*p[9]*p[22] + p[9]*p[9]*p[31] + p[9]*p[10]*p[20] - p[9]*p[10]*p[29] - p[11]*p[12]*p[20] + p[11]*p[12]*p[29] + p[11]*p[13]*p[17] - p[11]*p[13]*p[26] + p[12]*p[12]*p[22] - p[12]*p[12]*p[31] - p[12]*p[14]*p[17] + p[12]*p[14]*p[26] + p[13]*p[13]*p[22] - p[13]*p[13]*p[31] - p[13]*p[14]*p[20] + p[13]*p[14]*p[29])*p[0];
+}
+
+} // namespace embree
diff --git a/thirdparty/embree/kernels/common/point_query.h b/thirdparty/embree/kernels/common/point_query.h
new file mode 100644
index 0000000000..7d55c91fff
--- /dev/null
+++ b/thirdparty/embree/kernels/common/point_query.h
@@ -0,0 +1,136 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+
+namespace embree
+{
+ /* Point query structure for closest point query */
+ template<int K>
+ struct RTC_ALIGN(16) PointQueryK
+ {
+ /* Default construction does nothing */
+ __forceinline PointQueryK() {}
+
+ /* Constructs a ray from origin, direction, and ray segment. Near
+ * has to be smaller than far */
+ __forceinline PointQueryK(const Vec3vf<K>& p, const vfloat<K>& radius = inf, const vfloat<K>& time = zero)
+ : p(p), time(time), radius(radius) {}
+
+ /* Returns the size of the ray */
+ static __forceinline size_t size() { return K; }
+
+ /* Calculates if this is a valid ray that does not cause issues during traversal */
+ __forceinline vbool<K> valid() const
+ {
+ const vbool<K> vx = (abs(p.x) <= vfloat<K>(FLT_LARGE));
+ const vbool<K> vy = (abs(p.y) <= vfloat<K>(FLT_LARGE));
+ const vbool<K> vz = (abs(p.z) <= vfloat<K>(FLT_LARGE));
+ const vbool<K> vn = radius >= vfloat<K>(0);
+ const vbool<K> vf = abs(time) < vfloat<K>(inf);
+ return vx & vy & vz & vn & vf;
+ }
+
+ __forceinline void get(PointQueryK<1>* ray) const;
+ __forceinline void get(size_t i, PointQueryK<1>& ray) const;
+ __forceinline void set(const PointQueryK<1>* ray);
+ __forceinline void set(size_t i, const PointQueryK<1>& ray);
+
+ Vec3vf<K> p; // location of the query point
+ vfloat<K> time; // time for motion blur
+ vfloat<K> radius; // radius for the point query
+ };
+
+ /* Specialization for a single point query */
+ template<>
+ struct RTC_ALIGN(16) PointQueryK<1>
+ {
+ /* Default construction does nothing */
+ __forceinline PointQueryK() {}
+
+ /* Constructs a ray from origin, direction, and ray segment. Near
+ * has to be smaller than far */
+ __forceinline PointQueryK(const Vec3fa& p, float radius = inf, float time = zero)
+ : p(p), time(time), radius(radius) {}
+
+ /* Calculates if this is a valid ray that does not cause issues during traversal */
+ __forceinline bool valid() const {
+ return all(le_mask(abs(Vec3fa(p)), Vec3fa(FLT_LARGE)) & le_mask(Vec3fa(0.f), Vec3fa(radius))) && abs(time) < float(inf);
+ }
+
+ Vec3f p;
+ float time;
+ float radius;
+ };
+
+ /* Converts point query packet to single point query */
+ template<int K>
+ __forceinline void PointQueryK<K>::get(PointQueryK<1>* query) const
+ {
+ for (size_t i = 0; i < K; i++) // FIXME: use SIMD transpose
+ {
+ query[i].p.x = p.x[i];
+ query[i].p.y = p.y[i];
+ query[i].p.z = p.z[i];
+ query[i].time = time[i];
+ query[i].radius = radius[i];
+ }
+ }
+
+ /* Extracts a single point query out of a point query packet*/
+ template<int K>
+ __forceinline void PointQueryK<K>::get(size_t i, PointQueryK<1>& query) const
+ {
+ query.p.x = p.x[i];
+ query.p.y = p.y[i];
+ query.p.z = p.z[i];
+ query.radius = radius[i];
+ query.time = time[i];
+ }
+
+ /* Converts single point query to point query packet */
+ template<int K>
+ __forceinline void PointQueryK<K>::set(const PointQueryK<1>* query)
+ {
+ for (size_t i = 0; i < K; i++)
+ {
+ p.x[i] = query[i].p.x;
+ p.y[i] = query[i].p.y;
+ p.z[i] = query[i].p.z;
+ radius[i] = query[i].radius;
+ time[i] = query[i].time;
+ }
+ }
+
+ /* inserts a single point query into a point query packet element */
+ template<int K>
+ __forceinline void PointQueryK<K>::set(size_t i, const PointQueryK<1>& query)
+ {
+ p.x[i] = query.p.x;
+ p.y[i] = query.p.y;
+ p.z[i] = query.p.z;
+ radius[i] = query.radius;
+ time[i] = query.time;
+ }
+
+ /* Shortcuts */
+ typedef PointQueryK<1> PointQuery;
+ typedef PointQueryK<4> PointQuery4;
+ typedef PointQueryK<8> PointQuery8;
+ typedef PointQueryK<16> PointQuery16;
+ struct PointQueryN;
+
+ /* Outputs point query to stream */
+ template<int K>
+ __forceinline embree_ostream operator <<(embree_ostream cout, const PointQueryK<K>& query)
+ {
+ cout << "{ " << embree_endl
+ << " p = " << query.p << embree_endl
+ << " r = " << query.radius << embree_endl
+ << " time = " << query.time << embree_endl
+ << "}";
+ return cout;
+ }
+}
diff --git a/thirdparty/embree/kernels/common/primref.h b/thirdparty/embree/kernels/common/primref.h
new file mode 100644
index 0000000000..d61763487b
--- /dev/null
+++ b/thirdparty/embree/kernels/common/primref.h
@@ -0,0 +1,138 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+
+namespace embree
+{
+ /*! A primitive reference stores the bounds of the primitive and its ID. */
+ struct __aligned(32) PrimRef
+ {
+ __forceinline PrimRef () {}
+
+#if defined(__AVX__)
+ __forceinline PrimRef(const PrimRef& v) {
+ vfloat8::store((float*)this,vfloat8::load((float*)&v));
+ }
+ __forceinline PrimRef& operator=(const PrimRef& v) {
+ vfloat8::store((float*)this,vfloat8::load((float*)&v)); return *this;
+ }
+#endif
+
+ __forceinline PrimRef (const BBox3fa& bounds, unsigned int geomID, unsigned int primID)
+ {
+ lower = Vec3fx(bounds.lower, geomID);
+ upper = Vec3fx(bounds.upper, primID);
+ }
+
+ __forceinline PrimRef (const BBox3fa& bounds, size_t id)
+ {
+#if defined(__64BIT__)
+ lower = Vec3fx(bounds.lower, (unsigned)(id & 0xFFFFFFFF));
+ upper = Vec3fx(bounds.upper, (unsigned)((id >> 32) & 0xFFFFFFFF));
+#else
+ lower = Vec3fx(bounds.lower, (unsigned)id);
+ upper = Vec3fx(bounds.upper, (unsigned)0);
+#endif
+ }
+
+ /*! calculates twice the center of the primitive */
+ __forceinline const Vec3fa center2() const {
+ return lower+upper;
+ }
+
+ /*! return the bounding box of the primitive */
+ __forceinline const BBox3fa bounds() const {
+ return BBox3fa(lower,upper);
+ }
+
+ /*! size for bin heuristic is 1 */
+ __forceinline unsigned size() const {
+ return 1;
+ }
+
+ /*! returns bounds and centroid used for binning */
+ __forceinline void binBoundsAndCenter(BBox3fa& bounds_o, Vec3fa& center_o) const
+ {
+ bounds_o = bounds();
+ center_o = embree::center2(bounds_o);
+ }
+
+ __forceinline unsigned& geomIDref() { // FIXME: remove !!!!!!!
+ return lower.u;
+ }
+ __forceinline unsigned& primIDref() { // FIXME: remove !!!!!!!
+ return upper.u;
+ }
+
+ /*! returns the geometry ID */
+ __forceinline unsigned geomID() const {
+ return lower.a;
+ }
+
+ /*! returns the primitive ID */
+ __forceinline unsigned primID() const {
+ return upper.a;
+ }
+
+ /*! returns an size_t sized ID */
+ __forceinline size_t ID() const {
+#if defined(__64BIT__)
+ return size_t(lower.u) + (size_t(upper.u) << 32);
+#else
+ return size_t(lower.u);
+#endif
+ }
+
+ /*! special function for operator< */
+ __forceinline uint64_t ID64() const {
+ return (((uint64_t)primID()) << 32) + (uint64_t)geomID();
+ }
+
+ /*! allows sorting the primrefs by ID */
+ friend __forceinline bool operator<(const PrimRef& p0, const PrimRef& p1) {
+ return p0.ID64() < p1.ID64();
+ }
+
+ /*! Outputs primitive reference to a stream. */
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRef& ref) {
+ return cout << "{ lower = " << ref.lower << ", upper = " << ref.upper << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << " }";
+ }
+
+ public:
+ Vec3fx lower; //!< lower bounds and geomID
+ Vec3fx upper; //!< upper bounds and primID
+ };
+
+ /*! fast exchange for PrimRefs */
+ __forceinline void xchg(PrimRef& a, PrimRef& b)
+ {
+#if defined(__AVX__)
+ const vfloat8 aa = vfloat8::load((float*)&a);
+ const vfloat8 bb = vfloat8::load((float*)&b);
+ vfloat8::store((float*)&a,bb);
+ vfloat8::store((float*)&b,aa);
+#else
+ std::swap(a,b);
+#endif
+ }
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+ /************************************************************************************/
+
+ struct SubGridBuildData {
+ unsigned short sx,sy;
+ unsigned int primID;
+
+ __forceinline SubGridBuildData() {};
+ __forceinline SubGridBuildData(const unsigned int sx, const unsigned int sy, const unsigned int primID) : sx(sx), sy(sy), primID(primID) {};
+
+ __forceinline size_t x() const { return (size_t)sx & 0x7fff; }
+ __forceinline size_t y() const { return (size_t)sy & 0x7fff; }
+
+ };
+}
diff --git a/thirdparty/embree/kernels/common/primref_mb.h b/thirdparty/embree/kernels/common/primref_mb.h
new file mode 100644
index 0000000000..fb08a05003
--- /dev/null
+++ b/thirdparty/embree/kernels/common/primref_mb.h
@@ -0,0 +1,262 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+
+#define MBLUR_BIN_LBBOX 1
+
+namespace embree
+{
+#if MBLUR_BIN_LBBOX
+
+ /*! A primitive reference stores the bounds of the primitive and its ID. */
+ struct PrimRefMB
+ {
+ typedef LBBox3fa BBox;
+
+ __forceinline PrimRefMB () {}
+
+ __forceinline PrimRefMB (const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, unsigned int geomID, unsigned int primID)
+ : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
+ {
+ assert(activeTimeSegments > 0);
+ lbounds.bounds0.lower.a = geomID;
+ lbounds.bounds0.upper.a = primID;
+ lbounds.bounds1.lower.a = activeTimeSegments;
+ lbounds.bounds1.upper.a = totalTimeSegments;
+ }
+
+ __forceinline PrimRefMB (EmptyTy empty, const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
+ : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
+ {
+ assert(activeTimeSegments > 0);
+#if defined(__64BIT__)
+ lbounds.bounds0.lower.a = id & 0xFFFFFFFF;
+ lbounds.bounds0.upper.a = (id >> 32) & 0xFFFFFFFF;
+#else
+ lbounds.bounds0.lower.a = id;
+ lbounds.bounds0.upper.a = 0;
+#endif
+ lbounds.bounds1.lower.a = activeTimeSegments;
+ lbounds.bounds1.upper.a = totalTimeSegments;
+ }
+
+ __forceinline PrimRefMB (const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
+ : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
+ {
+ assert(activeTimeSegments > 0);
+#if defined(__64BIT__)
+ lbounds.bounds0.lower.u = id & 0xFFFFFFFF;
+ lbounds.bounds0.upper.u = (id >> 32) & 0xFFFFFFFF;
+#else
+ lbounds.bounds0.lower.u = id;
+ lbounds.bounds0.upper.u = 0;
+#endif
+ lbounds.bounds1.lower.a = activeTimeSegments;
+ lbounds.bounds1.upper.a = totalTimeSegments;
+ }
+
+ /*! returns bounds for binning */
+ __forceinline LBBox3fa bounds() const {
+ return lbounds;
+ }
+
+ /*! returns the number of time segments of this primref */
+ __forceinline unsigned size() const {
+ return lbounds.bounds1.lower.a;
+ }
+
+ __forceinline unsigned totalTimeSegments() const {
+ return lbounds.bounds1.upper.a;
+ }
+
+ /* calculate overlapping time segment range */
+ __forceinline range<int> timeSegmentRange(const BBox1f& range) const {
+ return getTimeSegmentRange(range,time_range,float(totalTimeSegments()));
+ }
+
+ /* returns time that corresponds to time step */
+ __forceinline float timeStep(const int i) const {
+ assert(i>=0 && i<=(int)totalTimeSegments());
+ return time_range.lower + time_range.size()*float(i)/float(totalTimeSegments());
+ }
+
+ /*! checks if time range overlaps */
+ __forceinline bool time_range_overlap(const BBox1f& range) const
+ {
+ if (0.9999f*time_range.upper <= range.lower) return false;
+ if (1.0001f*time_range.lower >= range.upper) return false;
+ return true;
+ }
+
+ /*! returns center for binning */
+ __forceinline Vec3fa binCenter() const {
+ return center2(lbounds.interpolate(0.5f));
+ }
+
+ /*! returns bounds and centroid used for binning */
+ __forceinline void binBoundsAndCenter(LBBox3fa& bounds_o, Vec3fa& center_o) const
+ {
+ bounds_o = bounds();
+ center_o = binCenter();
+ }
+
+ /*! returns the geometry ID */
+ __forceinline unsigned geomID() const {
+ return lbounds.bounds0.lower.a;
+ }
+
+ /*! returns the primitive ID */
+ __forceinline unsigned primID() const {
+ return lbounds.bounds0.upper.a;
+ }
+
+ /*! returns an size_t sized ID */
+ __forceinline size_t ID() const {
+#if defined(__64BIT__)
+ return size_t(lbounds.bounds0.lower.u) + (size_t(lbounds.bounds0.upper.u) << 32);
+#else
+ return size_t(lbounds.bounds0.lower.u);
+#endif
+ }
+
+ /*! special function for operator< */
+ __forceinline uint64_t ID64() const {
+ return (((uint64_t)primID()) << 32) + (uint64_t)geomID();
+ }
+
+ /*! allows sorting the primrefs by ID */
+ friend __forceinline bool operator<(const PrimRefMB& p0, const PrimRefMB& p1) {
+ return p0.ID64() < p1.ID64();
+ }
+
+ /*! Outputs primitive reference to a stream. */
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRefMB& ref) {
+ return cout << "{ time_range = " << ref.time_range << ", bounds = " << ref.bounds() << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << ", active_segments = " << ref.size() << ", total_segments = " << ref.totalTimeSegments() << " }";
+ }
+
+ public:
+ LBBox3fx lbounds;
+ BBox1f time_range; // entire geometry time range
+ };
+
+#else
+
+ /*! A primitive reference stores the bounds of the primitive and its ID. */
+ struct __aligned(16) PrimRefMB
+ {
+ typedef BBox3fa BBox;
+
+ __forceinline PrimRefMB () {}
+
+ __forceinline PrimRefMB (const LBBox3fa& bounds, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, unsigned int geomID, unsigned int primID)
+ : bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range)
+ {
+ assert(activeTimeSegments > 0);
+ bbox.lower.a = geomID;
+ bbox.upper.a = primID;
+ }
+
+ __forceinline PrimRefMB (EmptyTy empty, const LBBox3fa& bounds, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
+ : bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range)
+ {
+ assert(activeTimeSegments > 0);
+#if defined(__64BIT__)
+ bbox.lower.u = id & 0xFFFFFFFF;
+ bbox.upper.u = (id >> 32) & 0xFFFFFFFF;
+#else
+ bbox.lower.u = id;
+ bbox.upper.u = 0;
+#endif
+ }
+
+ /*! returns bounds for binning */
+ __forceinline BBox3fa bounds() const {
+ return bbox;
+ }
+
+ /*! returns the number of time segments of this primref */
+ __forceinline unsigned int size() const {
+ return _activeTimeSegments;
+ }
+
+ __forceinline unsigned int totalTimeSegments() const {
+ return _totalTimeSegments;
+ }
+
+ /* calculate overlapping time segment range */
+ __forceinline range<int> timeSegmentRange(const BBox1f& range) const {
+ return getTimeSegmentRange(range,time_range,float(_totalTimeSegments));
+ }
+
+ /* returns time that corresponds to time step */
+ __forceinline float timeStep(const int i) const {
+ assert(i>=0 && i<=(int)_totalTimeSegments);
+ return time_range.lower + time_range.size()*float(i)/float(_totalTimeSegments);
+ }
+
+ /*! checks if time range overlaps */
+ __forceinline bool time_range_overlap(const BBox1f& range) const
+ {
+ if (0.9999f*time_range.upper <= range.lower) return false;
+ if (1.0001f*time_range.lower >= range.upper) return false;
+ return true;
+ }
+
+ /*! returns center for binning */
+ __forceinline Vec3fa binCenter() const {
+ return center2(bounds());
+ }
+
+ /*! returns bounds and centroid used for binning */
+ __forceinline void binBoundsAndCenter(BBox3fa& bounds_o, Vec3fa& center_o) const
+ {
+ bounds_o = bounds();
+ center_o = center2(bounds());
+ }
+
+ /*! returns the geometry ID */
+ __forceinline unsigned int geomID() const {
+ return bbox.lower.a;
+ }
+
+ /*! returns the primitive ID */
+ __forceinline unsigned int primID() const {
+ return bbox.upper.a;
+ }
+
+ /*! returns an size_t sized ID */
+ __forceinline size_t ID() const {
+#if defined(__64BIT__)
+ return size_t(bbox.lower.u) + (size_t(bbox.upper.u) << 32);
+#else
+ return size_t(bbox.lower.u);
+#endif
+ }
+
+ /*! special function for operator< */
+ __forceinline uint64_t ID64() const {
+ return (((uint64_t)primID()) << 32) + (uint64_t)geomID();
+ }
+
+ /*! allows sorting the primrefs by ID */
+ friend __forceinline bool operator<(const PrimRefMB& p0, const PrimRefMB& p1) {
+ return p0.ID64() < p1.ID64();
+ }
+
+ /*! Outputs primitive reference to a stream. */
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRefMB& ref) {
+ return cout << "{ bounds = " << ref.bounds() << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << ", active_segments = " << ref.size() << ", total_segments = " << ref.totalTimeSegments() << " }";
+ }
+
+ public:
+ BBox3fa bbox; // bounds, geomID, primID
+ unsigned int _activeTimeSegments;
+ unsigned int _totalTimeSegments;
+ BBox1f time_range; // entire geometry time range
+ };
+
+#endif
+}
diff --git a/thirdparty/embree/kernels/common/profile.h b/thirdparty/embree/kernels/common/profile.h
new file mode 100644
index 0000000000..5ef7f6ec0f
--- /dev/null
+++ b/thirdparty/embree/kernels/common/profile.h
@@ -0,0 +1,159 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+
+namespace embree
+{
+ /*! helper structure for the implementation of the profile functions below */
+ struct ProfileTimer
+ {
+ static const size_t N = 20;
+
+ ProfileTimer () {}
+
+ ProfileTimer (const size_t numSkip) : i(0), j(0), maxJ(0), numSkip(numSkip), t0(0)
+ {
+ for (size_t i=0; i<N; i++) names[i] = nullptr;
+ for (size_t i=0; i<N; i++) dt_fst[i] = 0.0;
+ for (size_t i=0; i<N; i++) dt_min[i] = pos_inf;
+ for (size_t i=0; i<N; i++) dt_avg[i] = 0.0;
+ for (size_t i=0; i<N; i++) dt_max[i] = neg_inf;
+ }
+
+ __forceinline void begin()
+ {
+ j=0;
+ t0 = tj = getSeconds();
+ }
+
+ __forceinline void end() {
+ absolute("total");
+ i++;
+ }
+
+ __forceinline void operator() (const char* name) {
+ relative(name);
+ }
+
+ __forceinline void absolute (const char* name)
+ {
+ const double t1 = getSeconds();
+ const double dt = t1-t0;
+ assert(names[j] == nullptr || names[j] == name);
+ names[j] = name;
+ if (i == 0) dt_fst[j] = dt;
+ if (i>=numSkip) {
+ dt_min[j] = min(dt_min[j],dt);
+ dt_avg[j] = dt_avg[j] + dt;
+ dt_max[j] = max(dt_max[j],dt);
+ }
+ j++;
+ maxJ = max(maxJ,j);
+ }
+
+ __forceinline void relative (const char* name)
+ {
+ const double t1 = getSeconds();
+ const double dt = t1-tj;
+ tj = t1;
+ assert(names[j] == nullptr || names[j] == name);
+ names[j] = name;
+ if (i == 0) dt_fst[j] = dt;
+ if (i>=numSkip) {
+ dt_min[j] = min(dt_min[j],dt);
+ dt_avg[j] = dt_avg[j] + dt;
+ dt_max[j] = max(dt_max[j],dt);
+ }
+ j++;
+ maxJ = max(maxJ,j);
+ }
+
+ void print(size_t numElements)
+ {
+ for (size_t k=0; k<N; k++)
+ dt_avg[k] /= double(i-numSkip);
+
+ printf(" profile [M/s]:\n");
+ for (size_t j=0; j<maxJ; j++)
+ printf("%20s: fst = %7.2f M/s, min = %7.2f M/s, avg = %7.2f M/s, max = %7.2f M/s\n",
+ names[j],numElements/dt_fst[j]*1E-6,numElements/dt_max[j]*1E-6,numElements/dt_avg[j]*1E-6,numElements/dt_min[j]*1E-6);
+
+ printf(" profile [ms]:\n");
+ for (size_t j=0; j<maxJ; j++)
+ printf("%20s: fst = %7.2f ms, min = %7.2f ms, avg = %7.2f ms, max = %7.2fms\n",
+ names[j],1000.0*dt_fst[j],1000.0*dt_min[j],1000.0*dt_avg[j],1000.0*dt_max[j]);
+ }
+
+ void print()
+ {
+ printf(" profile:\n");
+
+ for (size_t k=0; k<N; k++)
+ dt_avg[k] /= double(i-numSkip);
+
+ for (size_t j=0; j<maxJ; j++) {
+ printf("%20s: fst = %7.2f ms, min = %7.2f ms, avg = %7.2f ms, max = %7.2fms\n",
+ names[j],1000.0*dt_fst[j],1000.0*dt_min[j],1000.0*dt_avg[j],1000.0*dt_max[j]);
+ }
+ }
+
+ double avg() {
+ return dt_avg[maxJ-1]/double(i-numSkip);
+ }
+
+ private:
+ size_t i;
+ size_t j;
+ size_t maxJ;
+ size_t numSkip;
+ double t0;
+ double tj;
+ const char* names[N];
+ double dt_fst[N];
+ double dt_min[N];
+ double dt_avg[N];
+ double dt_max[N];
+ };
+
+ /*! This function executes some code block multiple times and measured sections of it.
+ Use the following way:
+
+ profile(1,10,1000,[&](ProfileTimer& timer) {
+ // code
+ timer("A");
+ // code
+ timer("B");
+ });
+ */
+ template<typename Closure>
+ void profile(const size_t numSkip, const size_t numIter, const size_t numElements, const Closure& closure)
+ {
+ ProfileTimer timer(numSkip);
+
+ for (size_t i=0; i<numSkip+numIter; i++)
+ {
+ timer.begin();
+ closure(timer);
+ timer.end();
+ }
+ timer.print(numElements);
+ }
+
+ /*! similar as the function above, but the timer object comes externally */
+ template<typename Closure>
+ void profile(ProfileTimer& timer, const size_t numSkip, const size_t numIter, const size_t numElements, const Closure& closure)
+ {
+ timer = ProfileTimer(numSkip);
+
+ for (size_t i=0; i<numSkip+numIter; i++)
+ {
+ timer.begin();
+ closure(timer);
+ timer.end();
+ }
+ timer.print(numElements);
+ }
+}
diff --git a/thirdparty/embree/kernels/common/ray.h b/thirdparty/embree/kernels/common/ray.h
new file mode 100644
index 0000000000..7b951cc1e8
--- /dev/null
+++ b/thirdparty/embree/kernels/common/ray.h
@@ -0,0 +1,1517 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "instance_stack.h"
+
+// FIXME: if ray gets seperated into ray* and hit, uload4 needs to be adjusted
+
+namespace embree
+{
+ static const size_t MAX_INTERNAL_STREAM_SIZE = 32;
+
+ /* Ray structure for K rays */
+ template<int K>
+ struct RayK
+ {
+ /* Default construction does nothing */
+ __forceinline RayK() {}
+
+ /* Constructs a ray from origin, direction, and ray segment. Near
+ * has to be smaller than far */
+ __forceinline RayK(const Vec3vf<K>& org, const Vec3vf<K>& dir,
+ const vfloat<K>& tnear = zero, const vfloat<K>& tfar = inf,
+ const vfloat<K>& time = zero, const vint<K>& mask = -1, const vint<K>& id = 0, const vint<K>& flags = 0)
+ : org(org), dir(dir), _tnear(tnear), tfar(tfar), _time(time), mask(mask), id(id), flags(flags) {}
+
+ /* Returns the size of the ray */
+ static __forceinline size_t size() { return K; }
+
+ /* Calculates if this is a valid ray that does not cause issues during traversal */
+ __forceinline vbool<K> valid() const
+ {
+ const vbool<K> vx = (abs(org.x) <= vfloat<K>(FLT_LARGE)) & (abs(dir.x) <= vfloat<K>(FLT_LARGE));
+ const vbool<K> vy = (abs(org.y) <= vfloat<K>(FLT_LARGE)) & (abs(dir.y) <= vfloat<K>(FLT_LARGE));
+ const vbool<K> vz = (abs(org.z) <= vfloat<K>(FLT_LARGE)) & (abs(dir.z) <= vfloat<K>(FLT_LARGE));
+ const vbool<K> vn = abs(tnear()) <= vfloat<K>(inf);
+ const vbool<K> vf = abs(tfar) <= vfloat<K>(inf);
+ return vx & vy & vz & vn & vf;
+ }
+
+ __forceinline void get(RayK<1>* ray) const;
+ __forceinline void get(size_t i, RayK<1>& ray) const;
+ __forceinline void set(const RayK<1>* ray);
+ __forceinline void set(size_t i, const RayK<1>& ray);
+
+ __forceinline void copy(size_t dest, size_t source);
+
+ __forceinline vint<K> octant() const
+ {
+ return select(dir.x < 0.0f, vint<K>(1), vint<K>(zero)) |
+ select(dir.y < 0.0f, vint<K>(2), vint<K>(zero)) |
+ select(dir.z < 0.0f, vint<K>(4), vint<K>(zero));
+ }
+
+ /* Ray data */
+ Vec3vf<K> org; // ray origin
+ vfloat<K> _tnear; // start of ray segment
+ Vec3vf<K> dir; // ray direction
+ vfloat<K> _time; // time of this ray for motion blur
+ vfloat<K> tfar; // end of ray segment
+ vint<K> mask; // used to mask out objects during traversal
+ vint<K> id;
+ vint<K> flags;
+
+ __forceinline vfloat<K>& tnear() { return _tnear; }
+ __forceinline vfloat<K>& time() { return _time; }
+ __forceinline const vfloat<K>& tnear() const { return _tnear; }
+ __forceinline const vfloat<K>& time() const { return _time; }
+ };
+
+ /* Ray+hit structure for K rays */
+ template<int K>
+ struct RayHitK : RayK<K>
+ {
+ using RayK<K>::org;
+ using RayK<K>::_tnear;
+ using RayK<K>::dir;
+ using RayK<K>::_time;
+ using RayK<K>::tfar;
+ using RayK<K>::mask;
+ using RayK<K>::id;
+ using RayK<K>::flags;
+
+ using RayK<K>::tnear;
+ using RayK<K>::time;
+
+ /* Default construction does nothing */
+ __forceinline RayHitK() {}
+
+ /* Constructs a ray from origin, direction, and ray segment. Near
+ * has to be smaller than far */
+ __forceinline RayHitK(const Vec3vf<K>& org, const Vec3vf<K>& dir,
+ const vfloat<K>& tnear = zero, const vfloat<K>& tfar = inf,
+ const vfloat<K>& time = zero, const vint<K>& mask = -1, const vint<K>& id = 0, const vint<K>& flags = 0)
+ : RayK<K>(org, dir, tnear, tfar, time, mask, id, flags),
+ geomID(RTC_INVALID_GEOMETRY_ID)
+ {
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
+ instID[l] = RTC_INVALID_GEOMETRY_ID;
+ }
+
+ __forceinline RayHitK(const RayK<K>& ray)
+ : RayK<K>(ray),
+ geomID(RTC_INVALID_GEOMETRY_ID)
+ {
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
+ instID[l] = RTC_INVALID_GEOMETRY_ID;
+ }
+
+ __forceinline RayHitK<K>& operator =(const RayK<K>& ray)
+ {
+ org = ray.org;
+ _tnear = ray._tnear;
+ dir = ray.dir;
+ _time = ray._time;
+ tfar = ray.tfar;
+ mask = ray.mask;
+ id = ray.id;
+ flags = ray.flags;
+
+ geomID = RTC_INVALID_GEOMETRY_ID;
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
+ instID[l] = RTC_INVALID_GEOMETRY_ID;
+
+ return *this;
+ }
+
+ /* Calculates if the hit is valid */
+ __forceinline void verifyHit(const vbool<K>& valid0) const
+ {
+ vbool<K> valid = valid0 & geomID != vuint<K>(RTC_INVALID_GEOMETRY_ID);
+ const vbool<K> vt = (abs(tfar) <= vfloat<K>(FLT_LARGE)) | (tfar == vfloat<K>(neg_inf));
+ const vbool<K> vu = (abs(u) <= vfloat<K>(FLT_LARGE));
+ const vbool<K> vv = (abs(u) <= vfloat<K>(FLT_LARGE));
+ const vbool<K> vnx = abs(Ng.x) <= vfloat<K>(FLT_LARGE);
+ const vbool<K> vny = abs(Ng.y) <= vfloat<K>(FLT_LARGE);
+ const vbool<K> vnz = abs(Ng.z) <= vfloat<K>(FLT_LARGE);
+ if (any(valid & !vt)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid t");
+ if (any(valid & !vu)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid u");
+ if (any(valid & !vv)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid v");
+ if (any(valid & !vnx)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid Ng.x");
+ if (any(valid & !vny)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid Ng.y");
+ if (any(valid & !vnz)) throw_RTCError(RTC_ERROR_UNKNOWN,"invalid Ng.z");
+ }
+
+ __forceinline void get(RayHitK<1>* ray) const;
+ __forceinline void get(size_t i, RayHitK<1>& ray) const;
+ __forceinline void set(const RayHitK<1>* ray);
+ __forceinline void set(size_t i, const RayHitK<1>& ray);
+
+ __forceinline void copy(size_t dest, size_t source);
+
+ /* Hit data */
+ Vec3vf<K> Ng; // geometry normal
+ vfloat<K> u; // barycentric u coordinate of hit
+ vfloat<K> v; // barycentric v coordinate of hit
+ vuint<K> primID; // primitive ID
+ vuint<K> geomID; // geometry ID
+ vuint<K> instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
+ };
+
+ /* Specialization for a single ray */
+ template<>
+ struct RayK<1>
+ {
+ /* Default construction does nothing */
+ __forceinline RayK() {}
+
+ /* Constructs a ray from origin, direction, and ray segment. Near
+ * has to be smaller than far */
+ __forceinline RayK(const Vec3fa& org, const Vec3fa& dir, float tnear = zero, float tfar = inf, float time = zero, int mask = -1, int id = 0, int flags = 0)
+ : org(org,tnear), dir(dir,time), tfar(tfar), mask(mask), id(id), flags(flags) {}
+
+ /* Calculates if this is a valid ray that does not cause issues during traversal */
+ __forceinline bool valid() const {
+ return all(le_mask(abs(Vec3fa(org)), Vec3fa(FLT_LARGE)) & le_mask(abs(Vec3fa(dir)), Vec3fa(FLT_LARGE))) && abs(tnear()) <= float(inf) && abs(tfar) <= float(inf);
+ }
+
+ /* Ray data */
+ Vec3ff org; // 3 floats for ray origin, 1 float for tnear
+ //float tnear; // start of ray segment
+ Vec3ff dir; // 3 floats for ray direction, 1 float for time
+ // float time;
+ float tfar; // end of ray segment
+ int mask; // used to mask out objects during traversal
+ int id; // ray ID
+ int flags; // ray flags
+
+ __forceinline float& tnear() { return org.w; };
+ __forceinline const float& tnear() const { return org.w; };
+
+ __forceinline float& time() { return dir.w; };
+ __forceinline const float& time() const { return dir.w; };
+
+ };
+
+ template<>
+ struct RayHitK<1> : RayK<1>
+ {
+ /* Default construction does nothing */
+ __forceinline RayHitK() {}
+
+ /* Constructs a ray from origin, direction, and ray segment. Near
+ * has to be smaller than far */
+ __forceinline RayHitK(const Vec3fa& org, const Vec3fa& dir, float tnear = zero, float tfar = inf, float time = zero, int mask = -1, int id = 0, int flags = 0)
+ : RayK<1>(org, dir, tnear, tfar, time, mask, id, flags),
+ geomID(RTC_INVALID_GEOMETRY_ID) {}
+
+ __forceinline RayHitK(const RayK<1>& ray)
+ : RayK<1>(ray),
+ geomID(RTC_INVALID_GEOMETRY_ID) {}
+
+ __forceinline RayHitK<1>& operator =(const RayK<1>& ray)
+ {
+ org = ray.org;
+ dir = ray.dir;
+ tfar = ray.tfar;
+ mask = ray.mask;
+ id = ray.id;
+ flags = ray.flags;
+
+ geomID = RTC_INVALID_GEOMETRY_ID;
+
+ return *this;
+ }
+
+ /* Calculates if the hit is valid */
+ __forceinline void verifyHit() const
+ {
+ if (geomID == RTC_INVALID_GEOMETRY_ID) return;
+ const bool vt = (abs(tfar) <= FLT_LARGE) || (tfar == float(neg_inf));
+ const bool vu = (abs(u) <= FLT_LARGE);
+ const bool vv = (abs(u) <= FLT_LARGE);
+ const bool vnx = abs(Ng.x) <= FLT_LARGE;
+ const bool vny = abs(Ng.y) <= FLT_LARGE;
+ const bool vnz = abs(Ng.z) <= FLT_LARGE;
+ if (!vt) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid t");
+ if (!vu) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid u");
+ if (!vv) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid v");
+ if (!vnx) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid Ng.x");
+ if (!vny) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid Ng.y");
+ if (!vnz) throw_RTCError(RTC_ERROR_UNKNOWN, "invalid Ng.z");
+ }
+
+ /* Hit data */
+ Vec3f Ng; // not normalized geometry normal
+ float u; // barycentric u coordinate of hit
+ float v; // barycentric v coordinate of hit
+ unsigned int primID; // primitive ID
+ unsigned int geomID; // geometry ID
+ unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID
+ };
+
+ /* Converts ray packet to single rays */
+ template<int K>
+ __forceinline void RayK<K>::get(RayK<1>* ray) const
+ {
+ for (size_t i = 0; i < K; i++) // FIXME: use SIMD transpose
+ {
+ ray[i].org.x = org.x[i]; ray[i].org.y = org.y[i]; ray[i].org.z = org.z[i]; ray[i].tnear() = tnear()[i];
+ ray[i].dir.x = dir.x[i]; ray[i].dir.y = dir.y[i]; ray[i].dir.z = dir.z[i]; ray[i].time() = time()[i];
+ ray[i].tfar = tfar[i]; ray[i].mask = mask[i]; ray[i].id = id[i]; ray[i].flags = flags[i];
+ }
+ }
+
+ template<int K>
+ __forceinline void RayHitK<K>::get(RayHitK<1>* ray) const
+ {
+ // FIXME: use SIMD transpose
+ for (size_t i = 0; i < K; i++)
+ get(i, ray[i]);
+ }
+
+ /* Extracts a single ray out of a ray packet*/
+ template<int K>
+ __forceinline void RayK<K>::get(size_t i, RayK<1>& ray) const
+ {
+ ray.org.x = org.x[i]; ray.org.y = org.y[i]; ray.org.z = org.z[i]; ray.tnear() = tnear()[i];
+ ray.dir.x = dir.x[i]; ray.dir.y = dir.y[i]; ray.dir.z = dir.z[i]; ray.time() = time()[i];
+ ray.tfar = tfar[i]; ray.mask = mask[i]; ray.id = id[i]; ray.flags = flags[i];
+ }
+
+ template<int K>
+ __forceinline void RayHitK<K>::get(size_t i, RayHitK<1>& ray) const
+ {
+ ray.org.x = org.x[i]; ray.org.y = org.y[i]; ray.org.z = org.z[i]; ray.tnear() = tnear()[i];
+ ray.dir.x = dir.x[i]; ray.dir.y = dir.y[i]; ray.dir.z = dir.z[i]; ray.tfar = tfar[i]; ray.time() = time()[i];
+ ray.mask = mask[i]; ray.id = id[i]; ray.flags = flags[i];
+ ray.Ng.x = Ng.x[i]; ray.Ng.y = Ng.y[i]; ray.Ng.z = Ng.z[i];
+ ray.u = u[i]; ray.v = v[i];
+ ray.primID = primID[i]; ray.geomID = geomID[i];
+
+ instance_id_stack::copy_VU<K>(instID, ray.instID, i);
+ }
+
+ /* Converts single rays to ray packet */
+ template<int K>
+ __forceinline void RayK<K>::set(const RayK<1>* ray)
+ {
+ // FIXME: use SIMD transpose
+ for (size_t i = 0; i < K; i++)
+ set(i, ray[i]);
+ }
+
+ template<int K>
+ __forceinline void RayHitK<K>::set(const RayHitK<1>* ray)
+ {
+ // FIXME: use SIMD transpose
+ for (size_t i = 0; i < K; i++)
+ set(i, ray[i]);
+ }
+
+ /* inserts a single ray into a ray packet element */
+ template<int K>
+ __forceinline void RayK<K>::set(size_t i, const RayK<1>& ray)
+ {
+ org.x[i] = ray.org.x; org.y[i] = ray.org.y; org.z[i] = ray.org.z; tnear()[i] = ray.tnear();
+ dir.x[i] = ray.dir.x; dir.y[i] = ray.dir.y; dir.z[i] = ray.dir.z; time()[i] = ray.time();
+ tfar[i] = ray.tfar; mask[i] = ray.mask; id[i] = ray.id; flags[i] = ray.flags;
+ }
+
+ template<int K>
+ __forceinline void RayHitK<K>::set(size_t i, const RayHitK<1>& ray)
+ {
+ org.x[i] = ray.org.x; org.y[i] = ray.org.y; org.z[i] = ray.org.z; tnear()[i] = ray.tnear();
+ dir.x[i] = ray.dir.x; dir.y[i] = ray.dir.y; dir.z[i] = ray.dir.z; time()[i] = ray.time();
+ tfar[i] = ray.tfar; mask[i] = ray.mask; id[i] = ray.id; flags[i] = ray.flags;
+ Ng.x[i] = ray.Ng.x; Ng.y[i] = ray.Ng.y; Ng.z[i] = ray.Ng.z;
+ u[i] = ray.u; v[i] = ray.v;
+ primID[i] = ray.primID; geomID[i] = ray.geomID;
+
+ instance_id_stack::copy_UV<K>(ray.instID, instID, i);
+ }
+
+ /* copies a ray packet element into another element*/
+ template<int K>
+ __forceinline void RayK<K>::copy(size_t dest, size_t source)
+ {
+ org.x[dest] = org.x[source]; org.y[dest] = org.y[source]; org.z[dest] = org.z[source]; tnear()[dest] = tnear()[source];
+ dir.x[dest] = dir.x[source]; dir.y[dest] = dir.y[source]; dir.z[dest] = dir.z[source]; time()[dest] = time()[source];
+ tfar [dest] = tfar[source]; mask[dest] = mask[source]; id[dest] = id[source]; flags[dest] = flags[source];
+ }
+
+ template<int K>
+ __forceinline void RayHitK<K>::copy(size_t dest, size_t source)
+ {
+ org.x[dest] = org.x[source]; org.y[dest] = org.y[source]; org.z[dest] = org.z[source]; tnear()[dest] = tnear()[source];
+ dir.x[dest] = dir.x[source]; dir.y[dest] = dir.y[source]; dir.z[dest] = dir.z[source]; time()[dest] = time()[source];
+ tfar [dest] = tfar[source]; mask[dest] = mask[source]; id[dest] = id[source]; flags[dest] = flags[source];
+ Ng.x[dest] = Ng.x[source]; Ng.y[dest] = Ng.y[source]; Ng.z[dest] = Ng.z[source];
+ u[dest] = u[source]; v[dest] = v[source];
+ primID[dest] = primID[source]; geomID[dest] = geomID[source];
+
+ instance_id_stack::copy_VV<K>(instID, instID, source, dest);
+ }
+
+ /* Shortcuts */
+ typedef RayK<1> Ray;
+ typedef RayK<4> Ray4;
+ typedef RayK<8> Ray8;
+ typedef RayK<16> Ray16;
+ struct RayN;
+
+ typedef RayHitK<1> RayHit;
+ typedef RayHitK<4> RayHit4;
+ typedef RayHitK<8> RayHit8;
+ typedef RayHitK<16> RayHit16;
+ struct RayHitN;
+
+ template<int K, bool intersect>
+ struct RayTypeHelper;
+
+ template<int K>
+ struct RayTypeHelper<K, true>
+ {
+ typedef RayHitK<K> Ty;
+ };
+
+ template<int K>
+ struct RayTypeHelper<K, false>
+ {
+ typedef RayK<K> Ty;
+ };
+
+ template<bool intersect>
+ using RayType = typename RayTypeHelper<1, intersect>::Ty;
+
+ template<int K, bool intersect>
+ using RayTypeK = typename RayTypeHelper<K, intersect>::Ty;
+
+ /* Outputs ray to stream */
+ template<int K>
+ __forceinline embree_ostream operator <<(embree_ostream cout, const RayK<K>& ray)
+ {
+ return cout << "{ " << embree_endl
+ << " org = " << ray.org << embree_endl
+ << " dir = " << ray.dir << embree_endl
+ << " near = " << ray.tnear() << embree_endl
+ << " far = " << ray.tfar << embree_endl
+ << " time = " << ray.time() << embree_endl
+ << " mask = " << ray.mask << embree_endl
+ << " id = " << ray.id << embree_endl
+ << " flags = " << ray.flags << embree_endl
+ << "}";
+ }
+
+ template<int K>
+ __forceinline embree_ostream operator <<(embree_ostream cout, const RayHitK<K>& ray)
+ {
+ cout << "{ " << embree_endl
+ << " org = " << ray.org << embree_endl
+ << " dir = " << ray.dir << embree_endl
+ << " near = " << ray.tnear() << embree_endl
+ << " far = " << ray.tfar << embree_endl
+ << " time = " << ray.time() << embree_endl
+ << " mask = " << ray.mask << embree_endl
+ << " id = " << ray.id << embree_endl
+ << " flags = " << ray.flags << embree_endl
+ << " Ng = " << ray.Ng
+ << " u = " << ray.u << embree_endl
+ << " v = " << ray.v << embree_endl
+ << " primID = " << ray.primID << embree_endl
+ << " geomID = " << ray.geomID << embree_endl
+ << " instID =";
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
+ {
+ cout << " " << ray.instID[l];
+ }
+ cout << embree_endl;
+ return cout << "}";
+ }
+
+ struct RayStreamSOA
+ {
+ __forceinline RayStreamSOA(void* rays, size_t N)
+ : ptr((char*)rays), N(N) {}
+
+ /* ray data access functions */
+ __forceinline float* org_x(size_t offset = 0) { return (float*)&ptr[0*4*N+offset]; } // x coordinate of ray origin
+ __forceinline float* org_y(size_t offset = 0) { return (float*)&ptr[1*4*N+offset]; } // y coordinate of ray origin
+ __forceinline float* org_z(size_t offset = 0) { return (float*)&ptr[2*4*N+offset]; }; // z coordinate of ray origin
+ __forceinline float* tnear(size_t offset = 0) { return (float*)&ptr[3*4*N+offset]; }; // start of ray segment
+
+ __forceinline float* dir_x(size_t offset = 0) { return (float*)&ptr[4*4*N+offset]; }; // x coordinate of ray direction
+ __forceinline float* dir_y(size_t offset = 0) { return (float*)&ptr[5*4*N+offset]; }; // y coordinate of ray direction
+ __forceinline float* dir_z(size_t offset = 0) { return (float*)&ptr[6*4*N+offset]; }; // z coordinate of ray direction
+ __forceinline float* time (size_t offset = 0) { return (float*)&ptr[7*4*N+offset]; }; // time of this ray for motion blur
+
+ __forceinline float* tfar (size_t offset = 0) { return (float*)&ptr[8*4*N+offset]; }; // end of ray segment (set to hit distance)
+ __forceinline int* mask (size_t offset = 0) { return (int*)&ptr[9*4*N+offset]; }; // used to mask out objects during traversal (optional)
+ __forceinline int* id (size_t offset = 0) { return (int*)&ptr[10*4*N+offset]; }; // id
+ __forceinline int* flags(size_t offset = 0) { return (int*)&ptr[11*4*N+offset]; }; // flags
+
+ /* hit data access functions */
+ __forceinline float* Ng_x(size_t offset = 0) { return (float*)&ptr[12*4*N+offset]; }; // x coordinate of geometry normal
+ __forceinline float* Ng_y(size_t offset = 0) { return (float*)&ptr[13*4*N+offset]; }; // y coordinate of geometry normal
+ __forceinline float* Ng_z(size_t offset = 0) { return (float*)&ptr[14*4*N+offset]; }; // z coordinate of geometry normal
+
+ __forceinline float* u(size_t offset = 0) { return (float*)&ptr[15*4*N+offset]; }; // barycentric u coordinate of hit
+ __forceinline float* v(size_t offset = 0) { return (float*)&ptr[16*4*N+offset]; }; // barycentric v coordinate of hit
+
+ __forceinline unsigned int* primID(size_t offset = 0) { return (unsigned int*)&ptr[17*4*N+offset]; }; // primitive ID
+ __forceinline unsigned int* geomID(size_t offset = 0) { return (unsigned int*)&ptr[18*4*N+offset]; }; // geometry ID
+ __forceinline unsigned int* instID(size_t level, size_t offset = 0) { return (unsigned int*)&ptr[19*4*N+level*4*N+offset]; }; // instance ID
+
+ __forceinline Ray getRayByOffset(size_t offset)
+ {
+ Ray ray;
+ ray.org.x = org_x(offset)[0];
+ ray.org.y = org_y(offset)[0];
+ ray.org.z = org_z(offset)[0];
+ ray.tnear() = tnear(offset)[0];
+ ray.dir.x = dir_x(offset)[0];
+ ray.dir.y = dir_y(offset)[0];
+ ray.dir.z = dir_z(offset)[0];
+ ray.time() = time(offset)[0];
+ ray.tfar = tfar(offset)[0];
+ ray.mask = mask(offset)[0];
+ ray.id = id(offset)[0];
+ ray.flags = flags(offset)[0];
+ return ray;
+ }
+
+ template<int K>
+ __forceinline RayK<K> getRayByOffset(size_t offset)
+ {
+ RayK<K> ray;
+ ray.org.x = vfloat<K>::loadu(org_x(offset));
+ ray.org.y = vfloat<K>::loadu(org_y(offset));
+ ray.org.z = vfloat<K>::loadu(org_z(offset));
+ ray.tnear = vfloat<K>::loadu(tnear(offset));
+ ray.dir.x = vfloat<K>::loadu(dir_x(offset));
+ ray.dir.y = vfloat<K>::loadu(dir_y(offset));
+ ray.dir.z = vfloat<K>::loadu(dir_z(offset));
+ ray.time = vfloat<K>::loadu(time(offset));
+ ray.tfar = vfloat<K>::loadu(tfar(offset));
+ ray.mask = vint<K>::loadu(mask(offset));
+ ray.id = vint<K>::loadu(id(offset));
+ ray.flags = vint<K>::loadu(flags(offset));
+ return ray;
+ }
+
+ template<int K>
+ __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, size_t offset)
+ {
+ RayK<K> ray;
+ ray.org.x = vfloat<K>::loadu(valid, org_x(offset));
+ ray.org.y = vfloat<K>::loadu(valid, org_y(offset));
+ ray.org.z = vfloat<K>::loadu(valid, org_z(offset));
+ ray.tnear() = vfloat<K>::loadu(valid, tnear(offset));
+ ray.dir.x = vfloat<K>::loadu(valid, dir_x(offset));
+ ray.dir.y = vfloat<K>::loadu(valid, dir_y(offset));
+ ray.dir.z = vfloat<K>::loadu(valid, dir_z(offset));
+ ray.time() = vfloat<K>::loadu(valid, time(offset));
+ ray.tfar = vfloat<K>::loadu(valid, tfar(offset));
+
+#if !defined(__AVX__)
+ /* SSE: some ray members must be loaded with scalar instructions to ensure that we don't cause memory faults,
+ because the SSE masked loads always access the entire vector */
+ if (unlikely(!all(valid)))
+ {
+ ray.mask = zero;
+ ray.id = zero;
+ ray.flags = zero;
+
+ for (size_t k = 0; k < K; k++)
+ {
+ if (likely(valid[k]))
+ {
+ ray.mask[k] = mask(offset)[k];
+ ray.id[k] = id(offset)[k];
+ ray.flags[k] = flags(offset)[k];
+ }
+ }
+ }
+ else
+#endif
+ {
+ ray.mask = vint<K>::loadu(valid, mask(offset));
+ ray.id = vint<K>::loadu(valid, id(offset));
+ ray.flags = vint<K>::loadu(valid, flags(offset));
+ }
+
+ return ray;
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, size_t offset, const RayHitK<K>& ray)
+ {
+ /*
+ * valid_i: stores which of the input rays exist (do not access nonexistent rays!)
+ * valid: stores which of the rays actually hit something.
+ */
+ vbool<K> valid = valid_i;
+ valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
+
+ if (likely(any(valid)))
+ {
+ vfloat<K>::storeu(valid, tfar(offset), ray.tfar);
+ vfloat<K>::storeu(valid, Ng_x(offset), ray.Ng.x);
+ vfloat<K>::storeu(valid, Ng_y(offset), ray.Ng.y);
+ vfloat<K>::storeu(valid, Ng_z(offset), ray.Ng.z);
+ vfloat<K>::storeu(valid, u(offset), ray.u);
+ vfloat<K>::storeu(valid, v(offset), ray.v);
+
+#if !defined(__AVX__)
+ /* SSE: some ray members must be stored with scalar instructions to ensure that we don't cause memory faults,
+ because the SSE masked stores always access the entire vector */
+ if (unlikely(!all(valid_i)))
+ {
+ for (size_t k = 0; k < K; k++)
+ {
+ if (likely(valid[k]))
+ {
+ primID(offset)[k] = ray.primID[k];
+ geomID(offset)[k] = ray.geomID[k];
+
+ instID(0, offset)[k] = ray.instID[0][k];
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && ray.instID[l-1][k] != RTC_INVALID_GEOMETRY_ID; ++l)
+ instID(l, offset)[k] = ray.instID[l][k];
+#endif
+ }
+ }
+ }
+ else
+#endif
+ {
+ vuint<K>::storeu(valid, primID(offset), ray.primID);
+ vuint<K>::storeu(valid, geomID(offset), ray.geomID);
+
+ vuint<K>::storeu(valid, instID(0, offset), ray.instID[0]);
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
+ vuint<K>::storeu(valid, instID(l, offset), ray.instID[l]);
+#endif
+ }
+ }
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, size_t offset, const RayK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.tfar < 0.0f);
+
+ if (likely(any(valid)))
+ vfloat<K>::storeu(valid, tfar(offset), ray.tfar);
+ }
+
+ __forceinline size_t getOctantByOffset(size_t offset)
+ {
+ const float dx = dir_x(offset)[0];
+ const float dy = dir_y(offset)[0];
+ const float dz = dir_z(offset)[0];
+ const size_t octantID = (dx < 0.0f ? 1 : 0) + (dy < 0.0f ? 2 : 0) + (dz < 0.0f ? 4 : 0);
+ return octantID;
+ }
+
+ __forceinline bool isValidByOffset(size_t offset)
+ {
+ const float nnear = tnear(offset)[0];
+ const float ffar = tfar(offset)[0];
+ return nnear <= ffar;
+ }
+
+ template<int K>
+ __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, const vint<K>& offset)
+ {
+ RayK<K> ray;
+
+#if defined(__AVX2__)
+ ray.org.x = vfloat<K>::template gather<1>(valid, org_x(), offset);
+ ray.org.y = vfloat<K>::template gather<1>(valid, org_y(), offset);
+ ray.org.z = vfloat<K>::template gather<1>(valid, org_z(), offset);
+ ray.tnear() = vfloat<K>::template gather<1>(valid, tnear(), offset);
+ ray.dir.x = vfloat<K>::template gather<1>(valid, dir_x(), offset);
+ ray.dir.y = vfloat<K>::template gather<1>(valid, dir_y(), offset);
+ ray.dir.z = vfloat<K>::template gather<1>(valid, dir_z(), offset);
+ ray.time() = vfloat<K>::template gather<1>(valid, time(), offset);
+ ray.tfar = vfloat<K>::template gather<1>(valid, tfar(), offset);
+ ray.mask = vint<K>::template gather<1>(valid, mask(), offset);
+ ray.id = vint<K>::template gather<1>(valid, id(), offset);
+ ray.flags = vint<K>::template gather<1>(valid, flags(), offset);
+#else
+ ray.org = zero;
+ ray.tnear() = zero;
+ ray.dir = zero;
+ ray.time() = zero;
+ ray.tfar = zero;
+ ray.mask = zero;
+ ray.id = zero;
+ ray.flags = zero;
+
+ for (size_t k = 0; k < K; k++)
+ {
+ if (likely(valid[k]))
+ {
+ const size_t ofs = offset[k];
+
+ ray.org.x[k] = *org_x(ofs);
+ ray.org.y[k] = *org_y(ofs);
+ ray.org.z[k] = *org_z(ofs);
+ ray.tnear()[k] = *tnear(ofs);
+ ray.dir.x[k] = *dir_x(ofs);
+ ray.dir.y[k] = *dir_y(ofs);
+ ray.dir.z[k] = *dir_z(ofs);
+ ray.time()[k] = *time(ofs);
+ ray.tfar[k] = *tfar(ofs);
+ ray.mask[k] = *mask(ofs);
+ ray.id[k] = *id(ofs);
+ ray.flags[k] = *flags(ofs);
+ }
+ }
+#endif
+
+ return ray;
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayHitK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
+
+ if (likely(any(valid)))
+ {
+#if defined(__AVX512F__)
+ vfloat<K>::template scatter<1>(valid, tfar(), offset, ray.tfar);
+ vfloat<K>::template scatter<1>(valid, Ng_x(), offset, ray.Ng.x);
+ vfloat<K>::template scatter<1>(valid, Ng_y(), offset, ray.Ng.y);
+ vfloat<K>::template scatter<1>(valid, Ng_z(), offset, ray.Ng.z);
+ vfloat<K>::template scatter<1>(valid, u(), offset, ray.u);
+ vfloat<K>::template scatter<1>(valid, v(), offset, ray.v);
+ vuint<K>::template scatter<1>(valid, primID(), offset, ray.primID);
+ vuint<K>::template scatter<1>(valid, geomID(), offset, ray.geomID);
+
+ vuint<K>::template scatter<1>(valid, instID(0), offset, ray.instID[0]);
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
+ vuint<K>::template scatter<1>(valid, instID(l), offset, ray.instID[l]);
+#endif
+#else
+ size_t valid_bits = movemask(valid);
+ while (valid_bits != 0)
+ {
+ const size_t k = bscf(valid_bits);
+ const size_t ofs = offset[k];
+
+ *tfar(ofs) = ray.tfar[k];
+
+ *Ng_x(ofs) = ray.Ng.x[k];
+ *Ng_y(ofs) = ray.Ng.y[k];
+ *Ng_z(ofs) = ray.Ng.z[k];
+ *u(ofs) = ray.u[k];
+ *v(ofs) = ray.v[k];
+ *primID(ofs) = ray.primID[k];
+ *geomID(ofs) = ray.geomID[k];
+
+ *instID(0, ofs) = ray.instID[0][k];
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && ray.instID[l-1][k] != RTC_INVALID_GEOMETRY_ID; ++l)
+ *instID(l, ofs) = ray.instID[l][k];
+#endif
+ }
+#endif
+ }
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.tfar < 0.0f);
+
+ if (likely(any(valid)))
+ {
+#if defined(__AVX512F__)
+ vfloat<K>::template scatter<1>(valid, tfar(), offset, ray.tfar);
+#else
+ size_t valid_bits = movemask(valid);
+ while (valid_bits != 0)
+ {
+ const size_t k = bscf(valid_bits);
+ const size_t ofs = offset[k];
+
+ *tfar(ofs) = ray.tfar[k];
+ }
+#endif
+ }
+ }
+
+ char* __restrict__ ptr;
+ size_t N;
+ };
+
+ template<size_t MAX_K>
+ struct StackRayStreamSOA : public RayStreamSOA
+ {
+ __forceinline StackRayStreamSOA(size_t K)
+ : RayStreamSOA(data, K) { assert(K <= MAX_K); }
+
+ char data[MAX_K / 4 * sizeof(RayHit4)];
+ };
+
+
+ struct RayStreamSOP
+ {
+ template<class T>
+ __forceinline void init(T& t)
+ {
+ org_x = (float*)&t.org.x;
+ org_y = (float*)&t.org.y;
+ org_z = (float*)&t.org.z;
+ tnear = (float*)&t.tnear;
+ dir_x = (float*)&t.dir.x;
+ dir_y = (float*)&t.dir.y;
+ dir_z = (float*)&t.dir.z;
+ time = (float*)&t.time;
+ tfar = (float*)&t.tfar;
+ mask = (unsigned int*)&t.mask;
+ id = (unsigned int*)&t.id;
+ flags = (unsigned int*)&t.flags;
+
+ Ng_x = (float*)&t.Ng.x;
+ Ng_y = (float*)&t.Ng.y;
+ Ng_z = (float*)&t.Ng.z;
+ u = (float*)&t.u;
+ v = (float*)&t.v;
+ primID = (unsigned int*)&t.primID;
+ geomID = (unsigned int*)&t.geomID;
+
+ for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l)
+ instID[l] = (unsigned int*)&t.instID[l];
+ }
+
+ __forceinline Ray getRayByOffset(size_t offset)
+ {
+ Ray ray;
+ ray.org.x = *(float* __restrict__)((char*)org_x + offset);
+ ray.org.y = *(float* __restrict__)((char*)org_y + offset);
+ ray.org.z = *(float* __restrict__)((char*)org_z + offset);
+ ray.dir.x = *(float* __restrict__)((char*)dir_x + offset);
+ ray.dir.y = *(float* __restrict__)((char*)dir_y + offset);
+ ray.dir.z = *(float* __restrict__)((char*)dir_z + offset);
+ ray.tfar = *(float* __restrict__)((char*)tfar + offset);
+ ray.tnear() = tnear ? *(float* __restrict__)((char*)tnear + offset) : 0.0f;
+ ray.time() = time ? *(float* __restrict__)((char*)time + offset) : 0.0f;
+ ray.mask = mask ? *(unsigned int* __restrict__)((char*)mask + offset) : -1;
+ ray.id = id ? *(unsigned int* __restrict__)((char*)id + offset) : -1;
+ ray.flags = flags ? *(unsigned int* __restrict__)((char*)flags + offset) : -1;
+ return ray;
+ }
+
+ template<int K>
+ __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, size_t offset)
+ {
+ RayK<K> ray;
+ ray.org.x = vfloat<K>::loadu(valid, (float* __restrict__)((char*)org_x + offset));
+ ray.org.y = vfloat<K>::loadu(valid, (float* __restrict__)((char*)org_y + offset));
+ ray.org.z = vfloat<K>::loadu(valid, (float* __restrict__)((char*)org_z + offset));
+ ray.dir.x = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_x + offset));
+ ray.dir.y = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_y + offset));
+ ray.dir.z = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_z + offset));
+ ray.tfar = vfloat<K>::loadu(valid, (float* __restrict__)((char*)tfar + offset));
+ ray.tnear() = tnear ? vfloat<K>::loadu(valid, (float* __restrict__)((char*)tnear + offset)) : 0.0f;
+ ray.time() = time ? vfloat<K>::loadu(valid, (float* __restrict__)((char*)time + offset)) : 0.0f;
+ ray.mask = mask ? vint<K>::loadu(valid, (const void* __restrict__)((char*)mask + offset)) : -1;
+ ray.id = id ? vint<K>::loadu(valid, (const void* __restrict__)((char*)id + offset)) : -1;
+ ray.flags = flags ? vint<K>::loadu(valid, (const void* __restrict__)((char*)flags + offset)) : -1;
+ return ray;
+ }
+
+ template<int K>
+ __forceinline Vec3vf<K> getDirByOffset(const vbool<K>& valid, size_t offset)
+ {
+ Vec3vf<K> dir;
+ dir.x = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_x + offset));
+ dir.y = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_y + offset));
+ dir.z = vfloat<K>::loadu(valid, (float* __restrict__)((char*)dir_z + offset));
+ return dir;
+ }
+
+ __forceinline void setHitByOffset(size_t offset, const RayHit& ray)
+ {
+ if (ray.geomID != RTC_INVALID_GEOMETRY_ID)
+ {
+ *(float* __restrict__)((char*)tfar + offset) = ray.tfar;
+
+ if (likely(Ng_x)) *(float* __restrict__)((char*)Ng_x + offset) = ray.Ng.x;
+ if (likely(Ng_y)) *(float* __restrict__)((char*)Ng_y + offset) = ray.Ng.y;
+ if (likely(Ng_z)) *(float* __restrict__)((char*)Ng_z + offset) = ray.Ng.z;
+ *(float* __restrict__)((char*)u + offset) = ray.u;
+ *(float* __restrict__)((char*)v + offset) = ray.v;
+ *(unsigned int* __restrict__)((char*)geomID + offset) = ray.geomID;
+ *(unsigned int* __restrict__)((char*)primID + offset) = ray.primID;
+
+ if (likely(instID[0])) {
+ *(unsigned int* __restrict__)((char*)instID[0] + offset) = ray.instID[0];
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID; ++l)
+ *(unsigned int* __restrict__)((char*)instID[l] + offset) = ray.instID[l];
+#endif
+ }
+ }
+ }
+
+ __forceinline void setHitByOffset(size_t offset, const Ray& ray)
+ {
+ *(float* __restrict__)((char*)tfar + offset) = ray.tfar;
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, size_t offset, const RayHitK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
+
+ if (likely(any(valid)))
+ {
+ vfloat<K>::storeu(valid, (float* __restrict__)((char*)tfar + offset), ray.tfar);
+
+ if (likely(Ng_x)) vfloat<K>::storeu(valid, (float* __restrict__)((char*)Ng_x + offset), ray.Ng.x);
+ if (likely(Ng_y)) vfloat<K>::storeu(valid, (float* __restrict__)((char*)Ng_y + offset), ray.Ng.y);
+ if (likely(Ng_z)) vfloat<K>::storeu(valid, (float* __restrict__)((char*)Ng_z + offset), ray.Ng.z);
+ vfloat<K>::storeu(valid, (float* __restrict__)((char*)u + offset), ray.u);
+ vfloat<K>::storeu(valid, (float* __restrict__)((char*)v + offset), ray.v);
+ vuint<K>::storeu(valid, (unsigned int* __restrict__)((char*)primID + offset), ray.primID);
+ vuint<K>::storeu(valid, (unsigned int* __restrict__)((char*)geomID + offset), ray.geomID);
+
+ if (likely(instID[0])) {
+ vuint<K>::storeu(valid, (unsigned int* __restrict__)((char*)instID[0] + offset), ray.instID[0]);
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
+ vuint<K>::storeu(valid, (unsigned int* __restrict__)((char*)instID[l] + offset), ray.instID[l]);
+#endif
+ }
+ }
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, size_t offset, const RayK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.tfar < 0.0f);
+
+ if (likely(any(valid)))
+ vfloat<K>::storeu(valid, (float* __restrict__)((char*)tfar + offset), ray.tfar);
+ }
+
+ __forceinline size_t getOctantByOffset(size_t offset)
+ {
+ const float dx = *(float* __restrict__)((char*)dir_x + offset);
+ const float dy = *(float* __restrict__)((char*)dir_y + offset);
+ const float dz = *(float* __restrict__)((char*)dir_z + offset);
+ const size_t octantID = (dx < 0.0f ? 1 : 0) + (dy < 0.0f ? 2 : 0) + (dz < 0.0f ? 4 : 0);
+ return octantID;
+ }
+
+ __forceinline bool isValidByOffset(size_t offset)
+ {
+ const float nnear = tnear ? *(float* __restrict__)((char*)tnear + offset) : 0.0f;
+ const float ffar = *(float* __restrict__)((char*)tfar + offset);
+ return nnear <= ffar;
+ }
+
+ template<int K>
+ __forceinline vbool<K> isValidByOffset(const vbool<K>& valid, size_t offset)
+ {
+ const vfloat<K> nnear = tnear ? vfloat<K>::loadu(valid, (float* __restrict__)((char*)tnear + offset)) : 0.0f;
+ const vfloat<K> ffar = vfloat<K>::loadu(valid, (float* __restrict__)((char*)tfar + offset));
+ return nnear <= ffar;
+ }
+
+ template<int K>
+ __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, const vint<K>& offset)
+ {
+ RayK<K> ray;
+
+#if defined(__AVX2__)
+ ray.org.x = vfloat<K>::template gather<1>(valid, org_x, offset);
+ ray.org.y = vfloat<K>::template gather<1>(valid, org_y, offset);
+ ray.org.z = vfloat<K>::template gather<1>(valid, org_z, offset);
+ ray.dir.x = vfloat<K>::template gather<1>(valid, dir_x, offset);
+ ray.dir.y = vfloat<K>::template gather<1>(valid, dir_y, offset);
+ ray.dir.z = vfloat<K>::template gather<1>(valid, dir_z, offset);
+ ray.tfar = vfloat<K>::template gather<1>(valid, tfar, offset);
+ ray.tnear() = tnear ? vfloat<K>::template gather<1>(valid, tnear, offset) : vfloat<K>(zero);
+ ray.time() = time ? vfloat<K>::template gather<1>(valid, time, offset) : vfloat<K>(zero);
+ ray.mask = mask ? vint<K>::template gather<1>(valid, (int*)mask, offset) : vint<K>(-1);
+ ray.id = id ? vint<K>::template gather<1>(valid, (int*)id, offset) : vint<K>(-1);
+ ray.flags = flags ? vint<K>::template gather<1>(valid, (int*)flags, offset) : vint<K>(-1);
+#else
+ ray.org = zero;
+ ray.tnear() = zero;
+ ray.dir = zero;
+ ray.tfar = zero;
+ ray.time() = zero;
+ ray.mask = zero;
+ ray.id = zero;
+ ray.flags = zero;
+
+ for (size_t k = 0; k < K; k++)
+ {
+ if (likely(valid[k]))
+ {
+ const size_t ofs = offset[k];
+
+ ray.org.x[k] = *(float* __restrict__)((char*)org_x + ofs);
+ ray.org.y[k] = *(float* __restrict__)((char*)org_y + ofs);
+ ray.org.z[k] = *(float* __restrict__)((char*)org_z + ofs);
+ ray.dir.x[k] = *(float* __restrict__)((char*)dir_x + ofs);
+ ray.dir.y[k] = *(float* __restrict__)((char*)dir_y + ofs);
+ ray.dir.z[k] = *(float* __restrict__)((char*)dir_z + ofs);
+ ray.tfar[k] = *(float* __restrict__)((char*)tfar + ofs);
+ ray.tnear()[k] = tnear ? *(float* __restrict__)((char*)tnear + ofs) : 0.0f;
+ ray.time()[k] = time ? *(float* __restrict__)((char*)time + ofs) : 0.0f;
+ ray.mask[k] = mask ? *(int* __restrict__)((char*)mask + ofs) : -1;
+ ray.id[k] = id ? *(int* __restrict__)((char*)id + ofs) : -1;
+ ray.flags[k] = flags ? *(int* __restrict__)((char*)flags + ofs) : -1;
+ }
+ }
+#endif
+
+ return ray;
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayHitK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
+
+ if (likely(any(valid)))
+ {
+#if defined(__AVX512F__)
+ vfloat<K>::template scatter<1>(valid, tfar, offset, ray.tfar);
+
+ if (likely(Ng_x)) vfloat<K>::template scatter<1>(valid, Ng_x, offset, ray.Ng.x);
+ if (likely(Ng_y)) vfloat<K>::template scatter<1>(valid, Ng_y, offset, ray.Ng.y);
+ if (likely(Ng_z)) vfloat<K>::template scatter<1>(valid, Ng_z, offset, ray.Ng.z);
+ vfloat<K>::template scatter<1>(valid, u, offset, ray.u);
+ vfloat<K>::template scatter<1>(valid, v, offset, ray.v);
+ vuint<K>::template scatter<1>(valid, (unsigned int*)geomID, offset, ray.geomID);
+ vuint<K>::template scatter<1>(valid, (unsigned int*)primID, offset, ray.primID);
+
+ if (likely(instID[0])) {
+ vuint<K>::template scatter<1>(valid, (unsigned int*)instID[0], offset, ray.instID[0]);
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
+ vuint<K>::template scatter<1>(valid, (unsigned int*)instID[l], offset, ray.instID[l]);
+#endif
+ }
+#else
+ size_t valid_bits = movemask(valid);
+ while (valid_bits != 0)
+ {
+ const size_t k = bscf(valid_bits);
+ const size_t ofs = offset[k];
+
+ *(float* __restrict__)((char*)tfar + ofs) = ray.tfar[k];
+
+ if (likely(Ng_x)) *(float* __restrict__)((char*)Ng_x + ofs) = ray.Ng.x[k];
+ if (likely(Ng_y)) *(float* __restrict__)((char*)Ng_y + ofs) = ray.Ng.y[k];
+ if (likely(Ng_z)) *(float* __restrict__)((char*)Ng_z + ofs) = ray.Ng.z[k];
+ *(float* __restrict__)((char*)u + ofs) = ray.u[k];
+ *(float* __restrict__)((char*)v + ofs) = ray.v[k];
+ *(unsigned int* __restrict__)((char*)primID + ofs) = ray.primID[k];
+ *(unsigned int* __restrict__)((char*)geomID + ofs) = ray.geomID[k];
+
+ if (likely(instID[0])) {
+ *(unsigned int* __restrict__)((char*)instID[0] + ofs) = ray.instID[0][k];
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && ray.instID[l-1][k] != RTC_INVALID_GEOMETRY_ID; ++l)
+ *(unsigned int* __restrict__)((char*)instID[l] + ofs) = ray.instID[l][k];
+#endif
+ }
+ }
+#endif
+ }
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.tfar < 0.0f);
+
+ if (likely(any(valid)))
+ {
+#if defined(__AVX512F__)
+ vfloat<K>::template scatter<1>(valid, tfar, offset, ray.tfar);
+#else
+ size_t valid_bits = movemask(valid);
+ while (valid_bits != 0)
+ {
+ const size_t k = bscf(valid_bits);
+ const size_t ofs = offset[k];
+
+ *(float* __restrict__)((char*)tfar + ofs) = ray.tfar[k];
+ }
+#endif
+ }
+ }
+
+ /* ray data */
+ float* __restrict__ org_x; // x coordinate of ray origin
+ float* __restrict__ org_y; // y coordinate of ray origin
+ float* __restrict__ org_z; // z coordinate of ray origin
+ float* __restrict__ tnear; // start of ray segment (optional)
+
+ float* __restrict__ dir_x; // x coordinate of ray direction
+ float* __restrict__ dir_y; // y coordinate of ray direction
+ float* __restrict__ dir_z; // z coordinate of ray direction
+ float* __restrict__ time; // time of this ray for motion blur (optional)
+
+ float* __restrict__ tfar; // end of ray segment (set to hit distance)
+ unsigned int* __restrict__ mask; // used to mask out objects during traversal (optional)
+ unsigned int* __restrict__ id; // ray ID
+ unsigned int* __restrict__ flags; // ray flags
+
+ /* hit data */
+ float* __restrict__ Ng_x; // x coordinate of geometry normal (optional)
+ float* __restrict__ Ng_y; // y coordinate of geometry normal (optional)
+ float* __restrict__ Ng_z; // z coordinate of geometry normal (optional)
+
+ float* __restrict__ u; // barycentric u coordinate of hit
+ float* __restrict__ v; // barycentric v coordinate of hit
+
+ unsigned int* __restrict__ primID; // primitive ID
+ unsigned int* __restrict__ geomID; // geometry ID
+ unsigned int* __restrict__ instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID (optional)
+ };
+
+
+ struct RayStreamAOS
+ {
+ __forceinline RayStreamAOS(void* rays)
+ : ptr((Ray*)rays) {}
+
+ __forceinline Ray& getRayByOffset(size_t offset)
+ {
+ return *(Ray*)((char*)ptr + offset);
+ }
+
+ template<int K>
+ __forceinline RayK<K> getRayByOffset(const vint<K>& offset);
+
+ template<int K>
+ __forceinline RayK<K> getRayByOffset(const vbool<K>& valid, const vint<K>& offset)
+ {
+ const vint<K> valid_offset = select(valid, offset, vintx(zero));
+ return getRayByOffset<K>(valid_offset);
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayHitK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
+
+ if (likely(any(valid)))
+ {
+#if defined(__AVX512F__)
+ vfloat<K>::template scatter<1>(valid, &ptr->tfar, offset, ray.tfar);
+ vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->Ng.x, offset, ray.Ng.x);
+ vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->Ng.y, offset, ray.Ng.y);
+ vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->Ng.z, offset, ray.Ng.z);
+ vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->u, offset, ray.u);
+ vfloat<K>::template scatter<1>(valid, &((RayHit*)ptr)->v, offset, ray.v);
+ vuint<K>::template scatter<1>(valid, (unsigned int*)&((RayHit*)ptr)->primID, offset, ray.primID);
+ vuint<K>::template scatter<1>(valid, (unsigned int*)&((RayHit*)ptr)->geomID, offset, ray.geomID);
+
+ vuint<K>::template scatter<1>(valid, (unsigned int*)&((RayHit*)ptr)->instID[0], offset, ray.instID[0]);
+#if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1)
+ for (unsigned l = 1; l < RTC_MAX_INSTANCE_LEVEL_COUNT && any(valid & (ray.instID[l-1] != RTC_INVALID_GEOMETRY_ID)); ++l)
+ vuint<K>::template scatter<1>(valid, (unsigned int*)&((RayHit*)ptr)->instID[l], offset, ray.instID[l]);
+#endif
+#else
+ size_t valid_bits = movemask(valid);
+ while (valid_bits != 0)
+ {
+ const size_t k = bscf(valid_bits);
+ RayHit* __restrict__ ray_k = (RayHit*)((char*)ptr + offset[k]);
+ ray_k->tfar = ray.tfar[k];
+ ray_k->Ng.x = ray.Ng.x[k];
+ ray_k->Ng.y = ray.Ng.y[k];
+ ray_k->Ng.z = ray.Ng.z[k];
+ ray_k->u = ray.u[k];
+ ray_k->v = ray.v[k];
+ ray_k->primID = ray.primID[k];
+ ray_k->geomID = ray.geomID[k];
+
+ instance_id_stack::copy_VU<K>(ray.instID, ray_k->instID, k);
+ }
+#endif
+ }
+ }
+
+ template<int K>
+ __forceinline void setHitByOffset(const vbool<K>& valid_i, const vint<K>& offset, const RayK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.tfar < 0.0f);
+
+ if (likely(any(valid)))
+ {
+#if defined(__AVX512F__)
+ vfloat<K>::template scatter<1>(valid, &ptr->tfar, offset, ray.tfar);
+#else
+ size_t valid_bits = movemask(valid);
+ while (valid_bits != 0)
+ {
+ const size_t k = bscf(valid_bits);
+ Ray* __restrict__ ray_k = (Ray*)((char*)ptr + offset[k]);
+ ray_k->tfar = ray.tfar[k];
+ }
+#endif
+ }
+ }
+
+ Ray* __restrict__ ptr;
+ };
+
+ template<>
+ __forceinline Ray4 RayStreamAOS::getRayByOffset<4>(const vint4& offset)
+ {
+ Ray4 ray;
+
+ /* load and transpose: org.x, org.y, org.z, tnear */
+ const vfloat4 a0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[0]))->org);
+ const vfloat4 a1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[1]))->org);
+ const vfloat4 a2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[2]))->org);
+ const vfloat4 a3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[3]))->org);
+
+ transpose(a0,a1,a2,a3, ray.org.x, ray.org.y, ray.org.z, ray.tnear());
+
+ /* load and transpose: dir.x, dir.y, dir.z, time */
+ const vfloat4 b0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[0]))->dir);
+ const vfloat4 b1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[1]))->dir);
+ const vfloat4 b2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[2]))->dir);
+ const vfloat4 b3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[3]))->dir);
+
+ transpose(b0,b1,b2,b3, ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
+
+ /* load and transpose: tfar, mask, id, flags */
+ const vfloat4 c0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[0]))->tfar);
+ const vfloat4 c1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[1]))->tfar);
+ const vfloat4 c2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[2]))->tfar);
+ const vfloat4 c3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[3]))->tfar);
+
+ vfloat4 maskf, idf, flagsf;
+ transpose(c0,c1,c2,c3, ray.tfar, maskf, idf, flagsf);
+ ray.mask = asInt(maskf);
+ ray.id = asInt(idf);
+ ray.flags = asInt(flagsf);
+
+ return ray;
+ }
+
+#if defined(__AVX__)
+ template<>
+ __forceinline Ray8 RayStreamAOS::getRayByOffset<8>(const vint8& offset)
+ {
+ Ray8 ray;
+
+ /* load and transpose: org.x, org.y, org.z, tnear, dir.x, dir.y, dir.z, time */
+ const vfloat8 ab0 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[0]))->org);
+ const vfloat8 ab1 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[1]))->org);
+ const vfloat8 ab2 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[2]))->org);
+ const vfloat8 ab3 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[3]))->org);
+ const vfloat8 ab4 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[4]))->org);
+ const vfloat8 ab5 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[5]))->org);
+ const vfloat8 ab6 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[6]))->org);
+ const vfloat8 ab7 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[7]))->org);
+
+ transpose(ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7, ray.org.x, ray.org.y, ray.org.z, ray.tnear(), ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
+
+ /* load and transpose: tfar, mask, id, flags */
+ const vfloat4 c0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[0]))->tfar);
+ const vfloat4 c1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[1]))->tfar);
+ const vfloat4 c2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[2]))->tfar);
+ const vfloat4 c3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[3]))->tfar);
+ const vfloat4 c4 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[4]))->tfar);
+ const vfloat4 c5 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[5]))->tfar);
+ const vfloat4 c6 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[6]))->tfar);
+ const vfloat4 c7 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[7]))->tfar);
+
+ vfloat8 maskf, idf, flagsf;
+ transpose(c0,c1,c2,c3,c4,c5,c6,c7, ray.tfar, maskf, idf, flagsf);
+ ray.mask = asInt(maskf);
+ ray.id = asInt(idf);
+ ray.flags = asInt(flagsf);
+
+ return ray;
+ }
+#endif
+
+#if defined(__AVX512F__)
+ template<>
+ __forceinline Ray16 RayStreamAOS::getRayByOffset<16>(const vint16& offset)
+ {
+ Ray16 ray;
+
+ /* load and transpose: org.x, org.y, org.z, tnear, dir.x, dir.y, dir.z, time */
+ const vfloat8 ab0 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 0]))->org);
+ const vfloat8 ab1 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 1]))->org);
+ const vfloat8 ab2 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 2]))->org);
+ const vfloat8 ab3 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 3]))->org);
+ const vfloat8 ab4 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 4]))->org);
+ const vfloat8 ab5 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 5]))->org);
+ const vfloat8 ab6 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 6]))->org);
+ const vfloat8 ab7 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 7]))->org);
+ const vfloat8 ab8 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 8]))->org);
+ const vfloat8 ab9 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[ 9]))->org);
+ const vfloat8 ab10 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[10]))->org);
+ const vfloat8 ab11 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[11]))->org);
+ const vfloat8 ab12 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[12]))->org);
+ const vfloat8 ab13 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[13]))->org);
+ const vfloat8 ab14 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[14]))->org);
+ const vfloat8 ab15 = vfloat8::loadu(&((Ray*)((char*)ptr + offset[15]))->org);
+
+ transpose(ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7,ab8,ab9,ab10,ab11,ab12,ab13,ab14,ab15,
+ ray.org.x, ray.org.y, ray.org.z, ray.tnear(), ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
+
+ /* load and transpose: tfar, mask, id, flags */
+ const vfloat4 c0 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 0]))->tfar);
+ const vfloat4 c1 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 1]))->tfar);
+ const vfloat4 c2 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 2]))->tfar);
+ const vfloat4 c3 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 3]))->tfar);
+ const vfloat4 c4 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 4]))->tfar);
+ const vfloat4 c5 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 5]))->tfar);
+ const vfloat4 c6 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 6]))->tfar);
+ const vfloat4 c7 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 7]))->tfar);
+ const vfloat4 c8 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 8]))->tfar);
+ const vfloat4 c9 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[ 9]))->tfar);
+ const vfloat4 c10 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[10]))->tfar);
+ const vfloat4 c11 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[11]))->tfar);
+ const vfloat4 c12 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[12]))->tfar);
+ const vfloat4 c13 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[13]))->tfar);
+ const vfloat4 c14 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[14]))->tfar);
+ const vfloat4 c15 = vfloat4::loadu(&((Ray*)((char*)ptr + offset[15]))->tfar);
+
+ vfloat16 maskf, idf, flagsf;
+ transpose(c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,
+ ray.tfar, maskf, idf, flagsf);
+ ray.mask = asInt(maskf);
+ ray.id = asInt(idf);
+ ray.flags = asInt(flagsf);
+
+ return ray;
+ }
+#endif
+
+
+ struct RayStreamAOP
+ {
+ __forceinline RayStreamAOP(void* rays)
+ : ptr((Ray**)rays) {}
+
+ __forceinline Ray& getRayByIndex(size_t index)
+ {
+ return *ptr[index];
+ }
+
+ template<int K>
+ __forceinline RayK<K> getRayByIndex(const vint<K>& index);
+
+ template<int K>
+ __forceinline RayK<K> getRayByIndex(const vbool<K>& valid, const vint<K>& index)
+ {
+ const vint<K> valid_index = select(valid, index, vintx(zero));
+ return getRayByIndex<K>(valid_index);
+ }
+
+ template<int K>
+ __forceinline void setHitByIndex(const vbool<K>& valid_i, const vint<K>& index, const RayHitK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.geomID != RTC_INVALID_GEOMETRY_ID);
+
+ if (likely(any(valid)))
+ {
+ size_t valid_bits = movemask(valid);
+ while (valid_bits != 0)
+ {
+ const size_t k = bscf(valid_bits);
+ RayHit* __restrict__ ray_k = (RayHit*)ptr[index[k]];
+
+ ray_k->tfar = ray.tfar[k];
+ ray_k->Ng.x = ray.Ng.x[k];
+ ray_k->Ng.y = ray.Ng.y[k];
+ ray_k->Ng.z = ray.Ng.z[k];
+ ray_k->u = ray.u[k];
+ ray_k->v = ray.v[k];
+ ray_k->primID = ray.primID[k];
+ ray_k->geomID = ray.geomID[k];
+ instance_id_stack::copy_VU<K>(ray.instID, ray_k->instID, k);
+ }
+ }
+ }
+
+ template<int K>
+ __forceinline void setHitByIndex(const vbool<K>& valid_i, const vint<K>& index, const RayK<K>& ray)
+ {
+ vbool<K> valid = valid_i;
+ valid &= (ray.tfar < 0.0f);
+
+ if (likely(any(valid)))
+ {
+ size_t valid_bits = movemask(valid);
+ while (valid_bits != 0)
+ {
+ const size_t k = bscf(valid_bits);
+ Ray* __restrict__ ray_k = ptr[index[k]];
+
+ ray_k->tfar = ray.tfar[k];
+ }
+ }
+ }
+
+ Ray** __restrict__ ptr;
+ };
+
+ template<>
+ __forceinline Ray4 RayStreamAOP::getRayByIndex<4>(const vint4& index)
+ {
+ Ray4 ray;
+
+ /* load and transpose: org.x, org.y, org.z, tnear */
+ const vfloat4 a0 = vfloat4::loadu(&ptr[index[0]]->org);
+ const vfloat4 a1 = vfloat4::loadu(&ptr[index[1]]->org);
+ const vfloat4 a2 = vfloat4::loadu(&ptr[index[2]]->org);
+ const vfloat4 a3 = vfloat4::loadu(&ptr[index[3]]->org);
+
+ transpose(a0,a1,a2,a3, ray.org.x, ray.org.y, ray.org.z, ray.tnear());
+
+ /* load and transpose: dir.x, dir.y, dir.z, time */
+ const vfloat4 b0 = vfloat4::loadu(&ptr[index[0]]->dir);
+ const vfloat4 b1 = vfloat4::loadu(&ptr[index[1]]->dir);
+ const vfloat4 b2 = vfloat4::loadu(&ptr[index[2]]->dir);
+ const vfloat4 b3 = vfloat4::loadu(&ptr[index[3]]->dir);
+
+ transpose(b0,b1,b2,b3, ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
+
+ /* load and transpose: tfar, mask, id, flags */
+ const vfloat4 c0 = vfloat4::loadu(&ptr[index[0]]->tfar);
+ const vfloat4 c1 = vfloat4::loadu(&ptr[index[1]]->tfar);
+ const vfloat4 c2 = vfloat4::loadu(&ptr[index[2]]->tfar);
+ const vfloat4 c3 = vfloat4::loadu(&ptr[index[3]]->tfar);
+
+ vfloat4 maskf, idf, flagsf;
+ transpose(c0,c1,c2,c3, ray.tfar, maskf, idf, flagsf);
+ ray.mask = asInt(maskf);
+ ray.id = asInt(idf);
+ ray.flags = asInt(flagsf);
+
+ return ray;
+ }
+
+#if defined(__AVX__)
+ template<>
+ __forceinline Ray8 RayStreamAOP::getRayByIndex<8>(const vint8& index)
+ {
+ Ray8 ray;
+
+ /* load and transpose: org.x, org.y, org.z, tnear, dir.x, dir.y, dir.z, time */
+ const vfloat8 ab0 = vfloat8::loadu(&ptr[index[0]]->org);
+ const vfloat8 ab1 = vfloat8::loadu(&ptr[index[1]]->org);
+ const vfloat8 ab2 = vfloat8::loadu(&ptr[index[2]]->org);
+ const vfloat8 ab3 = vfloat8::loadu(&ptr[index[3]]->org);
+ const vfloat8 ab4 = vfloat8::loadu(&ptr[index[4]]->org);
+ const vfloat8 ab5 = vfloat8::loadu(&ptr[index[5]]->org);
+ const vfloat8 ab6 = vfloat8::loadu(&ptr[index[6]]->org);
+ const vfloat8 ab7 = vfloat8::loadu(&ptr[index[7]]->org);
+
+ transpose(ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7, ray.org.x, ray.org.y, ray.org.z, ray.tnear(), ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
+
+ /* load and transpose: tfar, mask, id, flags */
+ const vfloat4 c0 = vfloat4::loadu(&ptr[index[0]]->tfar);
+ const vfloat4 c1 = vfloat4::loadu(&ptr[index[1]]->tfar);
+ const vfloat4 c2 = vfloat4::loadu(&ptr[index[2]]->tfar);
+ const vfloat4 c3 = vfloat4::loadu(&ptr[index[3]]->tfar);
+ const vfloat4 c4 = vfloat4::loadu(&ptr[index[4]]->tfar);
+ const vfloat4 c5 = vfloat4::loadu(&ptr[index[5]]->tfar);
+ const vfloat4 c6 = vfloat4::loadu(&ptr[index[6]]->tfar);
+ const vfloat4 c7 = vfloat4::loadu(&ptr[index[7]]->tfar);
+
+ vfloat8 maskf, idf, flagsf;
+ transpose(c0,c1,c2,c3,c4,c5,c6,c7, ray.tfar, maskf, idf, flagsf);
+ ray.mask = asInt(maskf);
+ ray.id = asInt(idf);
+ ray.flags = asInt(flagsf);
+
+ return ray;
+ }
+#endif
+
+#if defined(__AVX512F__)
+ template<>
+ __forceinline Ray16 RayStreamAOP::getRayByIndex<16>(const vint16& index)
+ {
+ Ray16 ray;
+
+ /* load and transpose: org.x, org.y, org.z, tnear, dir.x, dir.y, dir.z, time */
+ const vfloat8 ab0 = vfloat8::loadu(&ptr[index[0]]->org);
+ const vfloat8 ab1 = vfloat8::loadu(&ptr[index[1]]->org);
+ const vfloat8 ab2 = vfloat8::loadu(&ptr[index[2]]->org);
+ const vfloat8 ab3 = vfloat8::loadu(&ptr[index[3]]->org);
+ const vfloat8 ab4 = vfloat8::loadu(&ptr[index[4]]->org);
+ const vfloat8 ab5 = vfloat8::loadu(&ptr[index[5]]->org);
+ const vfloat8 ab6 = vfloat8::loadu(&ptr[index[6]]->org);
+ const vfloat8 ab7 = vfloat8::loadu(&ptr[index[7]]->org);
+ const vfloat8 ab8 = vfloat8::loadu(&ptr[index[8]]->org);
+ const vfloat8 ab9 = vfloat8::loadu(&ptr[index[9]]->org);
+ const vfloat8 ab10 = vfloat8::loadu(&ptr[index[10]]->org);
+ const vfloat8 ab11 = vfloat8::loadu(&ptr[index[11]]->org);
+ const vfloat8 ab12 = vfloat8::loadu(&ptr[index[12]]->org);
+ const vfloat8 ab13 = vfloat8::loadu(&ptr[index[13]]->org);
+ const vfloat8 ab14 = vfloat8::loadu(&ptr[index[14]]->org);
+ const vfloat8 ab15 = vfloat8::loadu(&ptr[index[15]]->org);
+
+ transpose(ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7,ab8,ab9,ab10,ab11,ab12,ab13,ab14,ab15,
+ ray.org.x, ray.org.y, ray.org.z, ray.tnear(), ray.dir.x, ray.dir.y, ray.dir.z, ray.time());
+
+ /* load and transpose: tfar, mask, id, flags */
+ const vfloat4 c0 = vfloat4::loadu(&ptr[index[0]]->tfar);
+ const vfloat4 c1 = vfloat4::loadu(&ptr[index[1]]->tfar);
+ const vfloat4 c2 = vfloat4::loadu(&ptr[index[2]]->tfar);
+ const vfloat4 c3 = vfloat4::loadu(&ptr[index[3]]->tfar);
+ const vfloat4 c4 = vfloat4::loadu(&ptr[index[4]]->tfar);
+ const vfloat4 c5 = vfloat4::loadu(&ptr[index[5]]->tfar);
+ const vfloat4 c6 = vfloat4::loadu(&ptr[index[6]]->tfar);
+ const vfloat4 c7 = vfloat4::loadu(&ptr[index[7]]->tfar);
+ const vfloat4 c8 = vfloat4::loadu(&ptr[index[8]]->tfar);
+ const vfloat4 c9 = vfloat4::loadu(&ptr[index[9]]->tfar);
+ const vfloat4 c10 = vfloat4::loadu(&ptr[index[10]]->tfar);
+ const vfloat4 c11 = vfloat4::loadu(&ptr[index[11]]->tfar);
+ const vfloat4 c12 = vfloat4::loadu(&ptr[index[12]]->tfar);
+ const vfloat4 c13 = vfloat4::loadu(&ptr[index[13]]->tfar);
+ const vfloat4 c14 = vfloat4::loadu(&ptr[index[14]]->tfar);
+ const vfloat4 c15 = vfloat4::loadu(&ptr[index[15]]->tfar);
+
+ vfloat16 maskf, idf, flagsf;
+ transpose(c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,
+ ray.tfar, maskf, idf, flagsf);
+
+ ray.mask = asInt(maskf);
+ ray.id = asInt(idf);
+ ray.flags = asInt(flagsf);
+
+ return ray;
+ }
+#endif
+}
diff --git a/thirdparty/embree/kernels/common/rtcore.cpp b/thirdparty/embree/kernels/common/rtcore.cpp
new file mode 100644
index 0000000000..94b3819e42
--- /dev/null
+++ b/thirdparty/embree/kernels/common/rtcore.cpp
@@ -0,0 +1,1766 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#define RTC_EXPORT_API
+
+#include "default.h"
+#include "device.h"
+#include "scene.h"
+#include "context.h"
+#include "../../include/embree3/rtcore_ray.h"
+using namespace embree;
+
+RTC_NAMESPACE_BEGIN;
+
+ /* mutex to make API thread safe */
+ static MutexSys g_mutex;
+
+ RTC_API RTCDevice rtcNewDevice(const char* config)
+ {
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcNewDevice);
+ Lock<MutexSys> lock(g_mutex);
+ Device* device = new Device(config);
+ return (RTCDevice) device->refInc();
+ RTC_CATCH_END(nullptr);
+ return (RTCDevice) nullptr;
+ }
+
+ RTC_API void rtcRetainDevice(RTCDevice hdevice)
+ {
+ Device* device = (Device*) hdevice;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcRetainDevice);
+ RTC_VERIFY_HANDLE(hdevice);
+ Lock<MutexSys> lock(g_mutex);
+ device->refInc();
+ RTC_CATCH_END(nullptr);
+ }
+
+ RTC_API void rtcReleaseDevice(RTCDevice hdevice)
+ {
+ Device* device = (Device*) hdevice;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcReleaseDevice);
+ RTC_VERIFY_HANDLE(hdevice);
+ Lock<MutexSys> lock(g_mutex);
+ device->refDec();
+ RTC_CATCH_END(nullptr);
+ }
+
+ RTC_API ssize_t rtcGetDeviceProperty(RTCDevice hdevice, RTCDeviceProperty prop)
+ {
+ Device* device = (Device*) hdevice;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetDeviceProperty);
+ RTC_VERIFY_HANDLE(hdevice);
+ Lock<MutexSys> lock(g_mutex);
+ return device->getProperty(prop);
+ RTC_CATCH_END(device);
+ return 0;
+ }
+
+ RTC_API void rtcSetDeviceProperty(RTCDevice hdevice, const RTCDeviceProperty prop, ssize_t val)
+ {
+ Device* device = (Device*) hdevice;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetDeviceProperty);
+ const bool internal_prop = (size_t)prop >= 1000000 && (size_t)prop < 1000004;
+ if (!internal_prop) RTC_VERIFY_HANDLE(hdevice); // allow NULL device for special internal settings
+ Lock<MutexSys> lock(g_mutex);
+ device->setProperty(prop,val);
+ RTC_CATCH_END(device);
+ }
+
+ RTC_API RTCError rtcGetDeviceError(RTCDevice hdevice)
+ {
+ Device* device = (Device*) hdevice;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetDeviceError);
+ if (device == nullptr) return Device::getThreadErrorCode();
+ else return device->getDeviceErrorCode();
+ RTC_CATCH_END(device);
+ return RTC_ERROR_UNKNOWN;
+ }
+
+ RTC_API void rtcSetDeviceErrorFunction(RTCDevice hdevice, RTCErrorFunction error, void* userPtr)
+ {
+ Device* device = (Device*) hdevice;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetDeviceErrorFunction);
+ RTC_VERIFY_HANDLE(hdevice);
+ device->setErrorFunction(error, userPtr);
+ RTC_CATCH_END(device);
+ }
+
+ RTC_API void rtcSetDeviceMemoryMonitorFunction(RTCDevice hdevice, RTCMemoryMonitorFunction memoryMonitor, void* userPtr)
+ {
+ Device* device = (Device*) hdevice;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetDeviceMemoryMonitorFunction);
+ device->setMemoryMonitorFunction(memoryMonitor, userPtr);
+ RTC_CATCH_END(device);
+ }
+
+ RTC_API RTCBuffer rtcNewBuffer(RTCDevice hdevice, size_t byteSize)
+ {
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcNewBuffer);
+ RTC_VERIFY_HANDLE(hdevice);
+ Buffer* buffer = new Buffer((Device*)hdevice, byteSize);
+ return (RTCBuffer)buffer->refInc();
+ RTC_CATCH_END((Device*)hdevice);
+ return nullptr;
+ }
+
+ RTC_API RTCBuffer rtcNewSharedBuffer(RTCDevice hdevice, void* ptr, size_t byteSize)
+ {
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcNewSharedBuffer);
+ RTC_VERIFY_HANDLE(hdevice);
+ Buffer* buffer = new Buffer((Device*)hdevice, byteSize, ptr);
+ return (RTCBuffer)buffer->refInc();
+ RTC_CATCH_END((Device*)hdevice);
+ return nullptr;
+ }
+
+ RTC_API void* rtcGetBufferData(RTCBuffer hbuffer)
+ {
+ Buffer* buffer = (Buffer*)hbuffer;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetBufferData);
+ RTC_VERIFY_HANDLE(hbuffer);
+ return buffer->data();
+ RTC_CATCH_END2(buffer);
+ return nullptr;
+ }
+
+ RTC_API void rtcRetainBuffer(RTCBuffer hbuffer)
+ {
+ Buffer* buffer = (Buffer*)hbuffer;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcRetainBuffer);
+ RTC_VERIFY_HANDLE(hbuffer);
+ buffer->refInc();
+ RTC_CATCH_END2(buffer);
+ }
+
+ RTC_API void rtcReleaseBuffer(RTCBuffer hbuffer)
+ {
+ Buffer* buffer = (Buffer*)hbuffer;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcReleaseBuffer);
+ RTC_VERIFY_HANDLE(hbuffer);
+ buffer->refDec();
+ RTC_CATCH_END2(buffer);
+ }
+
+ RTC_API RTCScene rtcNewScene (RTCDevice hdevice)
+ {
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcNewScene);
+ RTC_VERIFY_HANDLE(hdevice);
+ Scene* scene = new Scene((Device*)hdevice);
+ return (RTCScene) scene->refInc();
+ RTC_CATCH_END((Device*)hdevice);
+ return nullptr;
+ }
+
+ RTC_API RTCDevice rtcGetSceneDevice(RTCScene hscene)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetSceneDevice);
+ RTC_VERIFY_HANDLE(hscene);
+ return (RTCDevice)scene->device->refInc(); // user will own one additional device reference
+ RTC_CATCH_END2(scene);
+ return (RTCDevice)nullptr;
+ }
+
+ RTC_API void rtcSetSceneProgressMonitorFunction(RTCScene hscene, RTCProgressMonitorFunction progress, void* ptr)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetSceneProgressMonitorFunction);
+ RTC_VERIFY_HANDLE(hscene);
+ Lock<MutexSys> lock(g_mutex);
+ scene->setProgressMonitorFunction(progress,ptr);
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcSetSceneBuildQuality (RTCScene hscene, RTCBuildQuality quality)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetSceneBuildQuality);
+ RTC_VERIFY_HANDLE(hscene);
+ if (quality != RTC_BUILD_QUALITY_LOW &&
+ quality != RTC_BUILD_QUALITY_MEDIUM &&
+ quality != RTC_BUILD_QUALITY_HIGH)
+ // -- GODOT start --
+ // throw std::runtime_error("invalid build quality");
+ abort();
+ // -- GODOT end --
+ scene->setBuildQuality(quality);
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcSetSceneFlags (RTCScene hscene, RTCSceneFlags flags)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetSceneFlags);
+ RTC_VERIFY_HANDLE(hscene);
+ scene->setSceneFlags(flags);
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API RTCSceneFlags rtcGetSceneFlags(RTCScene hscene)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetSceneFlags);
+ RTC_VERIFY_HANDLE(hscene);
+ return scene->getSceneFlags();
+ RTC_CATCH_END2(scene);
+ return RTC_SCENE_FLAG_NONE;
+ }
+
+ RTC_API void rtcCommitScene (RTCScene hscene)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcCommitScene);
+ RTC_VERIFY_HANDLE(hscene);
+ scene->commit(false);
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcJoinCommitScene (RTCScene hscene)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcJoinCommitScene);
+ RTC_VERIFY_HANDLE(hscene);
+ scene->commit(true);
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcGetSceneBounds(RTCScene hscene, RTCBounds* bounds_o)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetSceneBounds);
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ BBox3fa bounds = scene->bounds.bounds();
+ bounds_o->lower_x = bounds.lower.x;
+ bounds_o->lower_y = bounds.lower.y;
+ bounds_o->lower_z = bounds.lower.z;
+ bounds_o->align0 = 0;
+ bounds_o->upper_x = bounds.upper.x;
+ bounds_o->upper_y = bounds.upper.y;
+ bounds_o->upper_z = bounds.upper.z;
+ bounds_o->align1 = 0;
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcGetSceneLinearBounds(RTCScene hscene, RTCLinearBounds* bounds_o)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetSceneBounds);
+ RTC_VERIFY_HANDLE(hscene);
+ if (bounds_o == nullptr)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid destination pointer");
+ if (scene->isModified())
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+
+ bounds_o->bounds0.lower_x = scene->bounds.bounds0.lower.x;
+ bounds_o->bounds0.lower_y = scene->bounds.bounds0.lower.y;
+ bounds_o->bounds0.lower_z = scene->bounds.bounds0.lower.z;
+ bounds_o->bounds0.align0 = 0;
+ bounds_o->bounds0.upper_x = scene->bounds.bounds0.upper.x;
+ bounds_o->bounds0.upper_y = scene->bounds.bounds0.upper.y;
+ bounds_o->bounds0.upper_z = scene->bounds.bounds0.upper.z;
+ bounds_o->bounds0.align1 = 0;
+ bounds_o->bounds1.lower_x = scene->bounds.bounds1.lower.x;
+ bounds_o->bounds1.lower_y = scene->bounds.bounds1.lower.y;
+ bounds_o->bounds1.lower_z = scene->bounds.bounds1.lower.z;
+ bounds_o->bounds1.align0 = 0;
+ bounds_o->bounds1.upper_x = scene->bounds.bounds1.upper.x;
+ bounds_o->bounds1.upper_y = scene->bounds.bounds1.upper.y;
+ bounds_o->bounds1.upper_z = scene->bounds.bounds1.upper.z;
+ bounds_o->bounds1.align1 = 0;
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcCollide (RTCScene hscene0, RTCScene hscene1, RTCCollideFunc callback, void* userPtr)
+ {
+ Scene* scene0 = (Scene*) hscene0;
+ Scene* scene1 = (Scene*) hscene1;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcCollide);
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene0);
+ RTC_VERIFY_HANDLE(hscene1);
+ if (scene0->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
+ if (scene1->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
+ if (scene0->device != scene1->device) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scenes are from different devices");
+ auto nUserPrims0 = scene0->getNumPrimitives (Geometry::MTY_USER_GEOMETRY, false);
+ auto nUserPrims1 = scene1->getNumPrimitives (Geometry::MTY_USER_GEOMETRY, false);
+ if (scene0->numPrimitives() != nUserPrims0 && scene1->numPrimitives() != nUserPrims1) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scenes must only contain user geometries with a single timestep");
+#endif
+ scene0->intersectors.collide(scene0,scene1,callback,userPtr);
+ RTC_CATCH_END(scene0->device);
+ }
+
+ inline bool pointQuery(Scene* scene, RTCPointQuery* query, RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void* userPtr)
+ {
+ bool changed = false;
+ if (userContext->instStackSize > 0)
+ {
+ const AffineSpace3fa transform = AffineSpace3fa_load_unaligned((AffineSpace3fa*)userContext->world2inst[userContext->instStackSize-1]);
+
+ float similarityScale = 0.f;
+ const bool similtude = similarityTransform(transform, &similarityScale);
+ assert((similtude && similarityScale > 0) || (!similtude && similarityScale == 0.f));
+
+ PointQuery query_inst;
+ query_inst.p = xfmPoint(transform, Vec3fa(query->x, query->y, query->z));
+ query_inst.radius = query->radius * similarityScale;
+ query_inst.time = query->time;
+
+ PointQueryContext context_inst(scene, (PointQuery*)query,
+ similtude ? POINT_QUERY_TYPE_SPHERE : POINT_QUERY_TYPE_AABB,
+ queryFunc, userContext, similarityScale, userPtr);
+ changed = scene->intersectors.pointQuery((PointQuery*)&query_inst, &context_inst);
+ }
+ else
+ {
+ PointQueryContext context(scene, (PointQuery*)query,
+ POINT_QUERY_TYPE_SPHERE, queryFunc, userContext, 1.f, userPtr);
+ changed = scene->intersectors.pointQuery((PointQuery*)query, &context);
+ }
+ return changed;
+ }
+
+ RTC_API bool rtcPointQuery(RTCScene hscene, RTCPointQuery* query, RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void* userPtr)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcPointQuery);
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ RTC_VERIFY_HANDLE(userContext);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
+ if (((size_t)query) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "query not aligned to 16 bytes");
+ if (((size_t)userContext) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "context not aligned to 16 bytes");
+#endif
+
+ return pointQuery(scene, query, userContext, queryFunc, userPtr);
+ RTC_CATCH_END2_FALSE(scene);
+ }
+
+ RTC_API bool rtcPointQuery4 (const int* valid, RTCScene hscene, RTCPointQuery4* query, struct RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void** userPtrN)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcPointQuery4);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
+ if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
+ if (((size_t)query) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "query not aligned to 16 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(point_query.travs,cnt,cnt,cnt);
+
+ bool changed = false;
+ PointQuery4* query4 = (PointQuery4*)query;
+ PointQuery query1;
+ for (size_t i=0; i<4; i++) {
+ if (!valid[i]) continue;
+ query4->get(i,query1);
+ changed |= pointQuery(scene, (RTCPointQuery*)&query1, userContext, queryFunc, userPtrN?userPtrN[i]:NULL);
+ query4->set(i,query1);
+ }
+ return changed;
+ RTC_CATCH_END2_FALSE(scene);
+ }
+
+ RTC_API bool rtcPointQuery8 (const int* valid, RTCScene hscene, RTCPointQuery8* query, struct RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void** userPtrN)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcPointQuery8);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
+ if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
+ if (((size_t)query) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "query not aligned to 16 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(point_query.travs,cnt,cnt,cnt);
+
+ bool changed = false;
+ PointQuery8* query8 = (PointQuery8*)query;
+ PointQuery query1;
+ for (size_t i=0; i<8; i++) {
+ if (!valid[i]) continue;
+ query8->get(i,query1);
+ changed |= pointQuery(scene, (RTCPointQuery*)&query1, userContext, queryFunc, userPtrN?userPtrN[i]:NULL);
+ query8->set(i,query1);
+ }
+ return changed;
+ RTC_CATCH_END2_FALSE(scene);
+ }
+
+ RTC_API bool rtcPointQuery16 (const int* valid, RTCScene hscene, RTCPointQuery16* query, struct RTCPointQueryContext* userContext, RTCPointQueryFunction queryFunc, void** userPtrN)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcPointQuery16);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene got not committed");
+ if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
+ if (((size_t)query) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "query not aligned to 16 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(point_query.travs,cnt,cnt,cnt);
+
+ bool changed = false;
+ PointQuery16* query16 = (PointQuery16*)query;
+ PointQuery query1;
+ for (size_t i=0; i<16; i++) {
+ if (!valid[i]) continue;
+ PointQuery query1; query16->get(i,query1);
+ changed |= pointQuery(scene, (RTCPointQuery*)&query1, userContext, queryFunc, userPtrN?userPtrN[i]:NULL);
+ query16->set(i,query1);
+ }
+ return changed;
+ RTC_CATCH_END2_FALSE(scene);
+ }
+
+ RTC_API void rtcIntersect1 (RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit* rayhit)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcIntersect1);
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)rayhit) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 16 bytes");
+#endif
+ STAT3(normal.travs,1,1,1);
+ IntersectContext context(scene,user_context);
+ scene->intersectors.intersect(*rayhit,&context);
+#if defined(DEBUG)
+ ((RayHit*)rayhit)->verifyHit();
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcIntersect4 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit4* rayhit)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcIntersect4);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
+ if (((size_t)rayhit) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit not aligned to 16 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(normal.travs,cnt,cnt,cnt);
+
+ IntersectContext context(scene,user_context);
+#if !defined(EMBREE_RAY_PACKETS)
+ Ray4* ray4 = (Ray4*) rayhit;
+ for (size_t i=0; i<4; i++) {
+ if (!valid[i]) continue;
+ RayHit ray1; ray4->get(i,ray1);
+ scene->intersectors.intersect((RTCRayHit&)ray1,&context);
+ ray4->set(i,ray1);
+ }
+#else
+ scene->intersectors.intersect4(valid,*rayhit,&context);
+#endif
+
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcIntersect8 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit8* rayhit)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcIntersect8);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)valid) & 0x1F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 32 bytes");
+ if (((size_t)rayhit) & 0x1F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit not aligned to 32 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<8; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(normal.travs,cnt,cnt,cnt);
+
+ IntersectContext context(scene,user_context);
+#if !defined(EMBREE_RAY_PACKETS)
+ Ray8* ray8 = (Ray8*) rayhit;
+ for (size_t i=0; i<8; i++) {
+ if (!valid[i]) continue;
+ RayHit ray1; ray8->get(i,ray1);
+ scene->intersectors.intersect((RTCRayHit&)ray1,&context);
+ ray8->set(i,ray1);
+ }
+#else
+ if (likely(scene->intersectors.intersector8))
+ scene->intersectors.intersect8(valid,*rayhit,&context);
+ else
+ scene->device->rayStreamFilters.intersectSOA(scene,(char*)rayhit,8,1,sizeof(RTCRayHit8),&context);
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcIntersect16 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit16* rayhit)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcIntersect16);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)valid) & 0x3F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 64 bytes");
+ if (((size_t)rayhit) & 0x3F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit not aligned to 64 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<16; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(normal.travs,cnt,cnt,cnt);
+
+ IntersectContext context(scene,user_context);
+#if !defined(EMBREE_RAY_PACKETS)
+ Ray16* ray16 = (Ray16*) rayhit;
+ for (size_t i=0; i<16; i++) {
+ if (!valid[i]) continue;
+ RayHit ray1; ray16->get(i,ray1);
+ scene->intersectors.intersect((RTCRayHit&)ray1,&context);
+ ray16->set(i,ray1);
+ }
+#else
+ if (likely(scene->intersectors.intersector16))
+ scene->intersectors.intersect16(valid,*rayhit,&context);
+ else
+ scene->device->rayStreamFilters.intersectSOA(scene,(char*)rayhit,16,1,sizeof(RTCRayHit16),&context);
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcIntersect1M (RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit* rayhit, unsigned int M, size_t byteStride)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcIntersect1M);
+
+#if defined (EMBREE_RAY_PACKETS)
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)rayhit ) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
+#endif
+ STAT3(normal.travs,M,M,M);
+ IntersectContext context(scene,user_context);
+
+ /* fast codepath for single rays */
+ if (likely(M == 1)) {
+ if (likely(rayhit->ray.tnear <= rayhit->ray.tfar))
+ scene->intersectors.intersect(*rayhit,&context);
+ }
+
+ /* codepath for streams */
+ else {
+ scene->device->rayStreamFilters.intersectAOS(scene,rayhit,M,byteStride,&context);
+ }
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect1M not supported");
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcIntersect1Mp (RTCScene hscene, RTCIntersectContext* user_context, RTCRayHit** rn, unsigned int M)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcIntersect1Mp);
+
+#if defined (EMBREE_RAY_PACKETS)
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)rn) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
+#endif
+ STAT3(normal.travs,M,M,M);
+ IntersectContext context(scene,user_context);
+
+ /* fast codepath for single rays */
+ if (likely(M == 1)) {
+ if (likely(rn[0]->ray.tnear <= rn[0]->ray.tfar))
+ scene->intersectors.intersect(*rn[0],&context);
+ }
+
+ /* codepath for streams */
+ else {
+ scene->device->rayStreamFilters.intersectAOP(scene,rn,M,&context);
+ }
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect1Mp not supported");
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcIntersectNM (RTCScene hscene, RTCIntersectContext* user_context, struct RTCRayHitN* rayhit, unsigned int N, unsigned int M, size_t byteStride)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcIntersectNM);
+
+#if defined (EMBREE_RAY_PACKETS)
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)rayhit) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
+#endif
+ STAT3(normal.travs,N*M,N*M,N*M);
+ IntersectContext context(scene,user_context);
+
+ /* code path for single ray streams */
+ if (likely(N == 1))
+ {
+ /* fast code path for streams of size 1 */
+ if (likely(M == 1)) {
+ if (likely(((RTCRayHit*)rayhit)->ray.tnear <= ((RTCRayHit*)rayhit)->ray.tfar))
+ scene->intersectors.intersect(*(RTCRayHit*)rayhit,&context);
+ }
+ /* normal codepath for single ray streams */
+ else {
+ scene->device->rayStreamFilters.intersectAOS(scene,(RTCRayHit*)rayhit,M,byteStride,&context);
+ }
+ }
+ /* code path for ray packet streams */
+ else {
+ scene->device->rayStreamFilters.intersectSOA(scene,(char*)rayhit,N,M,byteStride,&context);
+ }
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectNM not supported");
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcIntersectNp (RTCScene hscene, RTCIntersectContext* user_context, const RTCRayHitNp* rayhit, unsigned int N)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcIntersectNp);
+
+#if defined (EMBREE_RAY_PACKETS)
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)rayhit->ray.org_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.org_x not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.org_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.org_y not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.org_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.org_z not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.dir_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.dir_x not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.dir_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.dir_y not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.dir_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.dir_z not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.tnear ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.dir_x not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.tfar ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.tnear not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.time ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.time not aligned to 4 bytes");
+ if (((size_t)rayhit->ray.mask ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->ray.mask not aligned to 4 bytes");
+ if (((size_t)rayhit->hit.Ng_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.Ng_x not aligned to 4 bytes");
+ if (((size_t)rayhit->hit.Ng_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.Ng_y not aligned to 4 bytes");
+ if (((size_t)rayhit->hit.Ng_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.Ng_z not aligned to 4 bytes");
+ if (((size_t)rayhit->hit.u ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.u not aligned to 4 bytes");
+ if (((size_t)rayhit->hit.v ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.v not aligned to 4 bytes");
+ if (((size_t)rayhit->hit.geomID) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.geomID not aligned to 4 bytes");
+ if (((size_t)rayhit->hit.primID) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.primID not aligned to 4 bytes");
+ if (((size_t)rayhit->hit.instID) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "rayhit->hit.instID not aligned to 4 bytes");
+#endif
+ STAT3(normal.travs,N,N,N);
+ IntersectContext context(scene,user_context);
+ scene->device->rayStreamFilters.intersectSOP(scene,rayhit,N,&context);
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectNp not supported");
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcOccluded1 (RTCScene hscene, RTCIntersectContext* user_context, RTCRay* ray)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcOccluded1);
+ STAT3(shadow.travs,1,1,1);
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)ray) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 16 bytes");
+#endif
+ IntersectContext context(scene,user_context);
+ scene->intersectors.occluded(*ray,&context);
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcOccluded4 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRay4* ray)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcOccluded4);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)valid) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 16 bytes");
+ if (((size_t)ray) & 0x0F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 16 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(shadow.travs,cnt,cnt,cnt);
+
+ IntersectContext context(scene,user_context);
+#if !defined(EMBREE_RAY_PACKETS)
+ RayHit4* ray4 = (RayHit4*) ray;
+ for (size_t i=0; i<4; i++) {
+ if (!valid[i]) continue;
+ RayHit ray1; ray4->get(i,ray1);
+ scene->intersectors.occluded((RTCRay&)ray1,&context);
+ ray4->geomID[i] = ray1.geomID;
+ }
+#else
+ scene->intersectors.occluded4(valid,*ray,&context);
+#endif
+
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcOccluded8 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRay8* ray)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcOccluded8);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)valid) & 0x1F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 32 bytes");
+ if (((size_t)ray) & 0x1F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 32 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<8; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(shadow.travs,cnt,cnt,cnt);
+
+ IntersectContext context(scene,user_context);
+#if !defined(EMBREE_RAY_PACKETS)
+ RayHit8* ray8 = (RayHit8*) ray;
+ for (size_t i=0; i<8; i++) {
+ if (!valid[i]) continue;
+ RayHit ray1; ray8->get(i,ray1);
+ scene->intersectors.occluded((RTCRay&)ray1,&context);
+ ray8->set(i,ray1);
+ }
+#else
+ if (likely(scene->intersectors.intersector8))
+ scene->intersectors.occluded8(valid,*ray,&context);
+ else
+ scene->device->rayStreamFilters.occludedSOA(scene,(char*)ray,8,1,sizeof(RTCRay8),&context);
+#endif
+
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcOccluded16 (const int* valid, RTCScene hscene, RTCIntersectContext* user_context, RTCRay16* ray)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcOccluded16);
+
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)valid) & 0x3F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 64 bytes");
+ if (((size_t)ray) & 0x3F) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 64 bytes");
+#endif
+ STAT(size_t cnt=0; for (size_t i=0; i<16; i++) cnt += ((int*)valid)[i] == -1;);
+ STAT3(shadow.travs,cnt,cnt,cnt);
+
+ IntersectContext context(scene,user_context);
+#if !defined(EMBREE_RAY_PACKETS)
+ RayHit16* ray16 = (RayHit16*) ray;
+ for (size_t i=0; i<16; i++) {
+ if (!valid[i]) continue;
+ RayHit ray1; ray16->get(i,ray1);
+ scene->intersectors.occluded((RTCRay&)ray1,&context);
+ ray16->set(i,ray1);
+ }
+#else
+ if (likely(scene->intersectors.intersector16))
+ scene->intersectors.occluded16(valid,*ray,&context);
+ else
+ scene->device->rayStreamFilters.occludedSOA(scene,(char*)ray,16,1,sizeof(RTCRay16),&context);
+#endif
+
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcOccluded1M(RTCScene hscene, RTCIntersectContext* user_context, RTCRay* ray, unsigned int M, size_t byteStride)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcOccluded1M);
+
+#if defined (EMBREE_RAY_PACKETS)
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)ray) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
+#endif
+ STAT3(shadow.travs,M,M,M);
+ IntersectContext context(scene,user_context);
+ /* fast codepath for streams of size 1 */
+ if (likely(M == 1)) {
+ if (likely(ray->tnear <= ray->tfar))
+ scene->intersectors.occluded (*ray,&context);
+ }
+ /* codepath for normal streams */
+ else {
+ scene->device->rayStreamFilters.occludedAOS(scene,ray,M,byteStride,&context);
+ }
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcOccluded1M not supported");
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcOccluded1Mp(RTCScene hscene, RTCIntersectContext* user_context, RTCRay** ray, unsigned int M)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcOccluded1Mp);
+
+#if defined (EMBREE_RAY_PACKETS)
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)ray) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
+#endif
+ STAT3(shadow.travs,M,M,M);
+ IntersectContext context(scene,user_context);
+
+ /* fast codepath for streams of size 1 */
+ if (likely(M == 1)) {
+ if (likely(ray[0]->tnear <= ray[0]->tfar))
+ scene->intersectors.occluded (*ray[0],&context);
+ }
+ /* codepath for normal streams */
+ else {
+ scene->device->rayStreamFilters.occludedAOP(scene,ray,M,&context);
+ }
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcOccluded1Mp not supported");
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcOccludedNM(RTCScene hscene, RTCIntersectContext* user_context, RTCRayN* ray, unsigned int N, unsigned int M, size_t byteStride)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcOccludedNM);
+
+#if defined (EMBREE_RAY_PACKETS)
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (byteStride < sizeof(RTCRayHit)) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"byteStride too small");
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)ray) & 0x03) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "ray not aligned to 4 bytes");
+#endif
+ STAT3(shadow.travs,N*M,N*N,N*N);
+ IntersectContext context(scene,user_context);
+
+ /* codepath for single rays */
+ if (likely(N == 1))
+ {
+ /* fast path for streams of size 1 */
+ if (likely(M == 1)) {
+ if (likely(((RTCRay*)ray)->tnear <= ((RTCRay*)ray)->tfar))
+ scene->intersectors.occluded (*(RTCRay*)ray,&context);
+ }
+ /* codepath for normal ray streams */
+ else {
+ scene->device->rayStreamFilters.occludedAOS(scene,(RTCRay*)ray,M,byteStride,&context);
+ }
+ }
+ /* code path for ray packet streams */
+ else {
+ scene->device->rayStreamFilters.occludedSOA(scene,(char*)ray,N,M,byteStride,&context);
+ }
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcOccludedNM not supported");
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcOccludedNp(RTCScene hscene, RTCIntersectContext* user_context, const RTCRayNp* ray, unsigned int N)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcOccludedNp);
+
+#if defined (EMBREE_RAY_PACKETS)
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ if (scene->isModified()) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed");
+ if (((size_t)ray->org_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "org_x not aligned to 4 bytes");
+ if (((size_t)ray->org_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "org_y not aligned to 4 bytes");
+ if (((size_t)ray->org_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "org_z not aligned to 4 bytes");
+ if (((size_t)ray->dir_x ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "dir_x not aligned to 4 bytes");
+ if (((size_t)ray->dir_y ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "dir_y not aligned to 4 bytes");
+ if (((size_t)ray->dir_z ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "dir_z not aligned to 4 bytes");
+ if (((size_t)ray->tnear ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "dir_x not aligned to 4 bytes");
+ if (((size_t)ray->tfar ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "tnear not aligned to 4 bytes");
+ if (((size_t)ray->time ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "time not aligned to 4 bytes");
+ if (((size_t)ray->mask ) & 0x03 ) throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "mask not aligned to 4 bytes");
+#endif
+ STAT3(shadow.travs,N,N,N);
+ IntersectContext context(scene,user_context);
+ scene->device->rayStreamFilters.occludedSOP(scene,ray,N,&context);
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcOccludedNp not supported");
+#endif
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcRetainScene (RTCScene hscene)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcRetainScene);
+ RTC_VERIFY_HANDLE(hscene);
+ scene->refInc();
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcReleaseScene (RTCScene hscene)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcReleaseScene);
+ RTC_VERIFY_HANDLE(hscene);
+ scene->refDec();
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcSetGeometryInstancedScene(RTCGeometry hgeometry, RTCScene hscene)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ Ref<Scene> scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryInstancedScene);
+ RTC_VERIFY_HANDLE(hgeometry);
+ RTC_VERIFY_HANDLE(hscene);
+ geometry->setInstancedScene(scene);
+ RTC_CATCH_END2(geometry);
+ }
+
+ AffineSpace3fa loadTransform(RTCFormat format, const float* xfm)
+ {
+ AffineSpace3fa space = one;
+ switch (format)
+ {
+ case RTC_FORMAT_FLOAT3X4_ROW_MAJOR:
+ space = AffineSpace3fa(Vec3fa(xfm[ 0], xfm[ 4], xfm[ 8]),
+ Vec3fa(xfm[ 1], xfm[ 5], xfm[ 9]),
+ Vec3fa(xfm[ 2], xfm[ 6], xfm[10]),
+ Vec3fa(xfm[ 3], xfm[ 7], xfm[11]));
+ break;
+
+ case RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR:
+ space = AffineSpace3fa(Vec3fa(xfm[ 0], xfm[ 1], xfm[ 2]),
+ Vec3fa(xfm[ 3], xfm[ 4], xfm[ 5]),
+ Vec3fa(xfm[ 6], xfm[ 7], xfm[ 8]),
+ Vec3fa(xfm[ 9], xfm[10], xfm[11]));
+ break;
+
+ case RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR:
+ space = AffineSpace3fa(Vec3fa(xfm[ 0], xfm[ 1], xfm[ 2]),
+ Vec3fa(xfm[ 4], xfm[ 5], xfm[ 6]),
+ Vec3fa(xfm[ 8], xfm[ 9], xfm[10]),
+ Vec3fa(xfm[12], xfm[13], xfm[14]));
+ break;
+
+ default:
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid matrix format");
+ break;
+ }
+ return space;
+ }
+
+ void storeTransform(const AffineSpace3fa& space, RTCFormat format, float* xfm)
+ {
+ switch (format)
+ {
+ case RTC_FORMAT_FLOAT3X4_ROW_MAJOR:
+ xfm[ 0] = space.l.vx.x; xfm[ 1] = space.l.vy.x; xfm[ 2] = space.l.vz.x; xfm[ 3] = space.p.x;
+ xfm[ 4] = space.l.vx.y; xfm[ 5] = space.l.vy.y; xfm[ 6] = space.l.vz.y; xfm[ 7] = space.p.y;
+ xfm[ 8] = space.l.vx.z; xfm[ 9] = space.l.vy.z; xfm[10] = space.l.vz.z; xfm[11] = space.p.z;
+ break;
+
+ case RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR:
+ xfm[ 0] = space.l.vx.x; xfm[ 1] = space.l.vx.y; xfm[ 2] = space.l.vx.z;
+ xfm[ 3] = space.l.vy.x; xfm[ 4] = space.l.vy.y; xfm[ 5] = space.l.vy.z;
+ xfm[ 6] = space.l.vz.x; xfm[ 7] = space.l.vz.y; xfm[ 8] = space.l.vz.z;
+ xfm[ 9] = space.p.x; xfm[10] = space.p.y; xfm[11] = space.p.z;
+ break;
+
+ case RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR:
+ xfm[ 0] = space.l.vx.x; xfm[ 1] = space.l.vx.y; xfm[ 2] = space.l.vx.z; xfm[ 3] = 0.f;
+ xfm[ 4] = space.l.vy.x; xfm[ 5] = space.l.vy.y; xfm[ 6] = space.l.vy.z; xfm[ 7] = 0.f;
+ xfm[ 8] = space.l.vz.x; xfm[ 9] = space.l.vz.y; xfm[10] = space.l.vz.z; xfm[11] = 0.f;
+ xfm[12] = space.p.x; xfm[13] = space.p.y; xfm[14] = space.p.z; xfm[15] = 1.f;
+ break;
+
+ default:
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid matrix format");
+ break;
+ }
+ }
+
+ RTC_API void rtcSetGeometryTransform(RTCGeometry hgeometry, unsigned int timeStep, RTCFormat format, const void* xfm)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryTransform);
+ RTC_VERIFY_HANDLE(hgeometry);
+ RTC_VERIFY_HANDLE(xfm);
+ const AffineSpace3fa transform = loadTransform(format, (const float*)xfm);
+ geometry->setTransform(transform, timeStep);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryTransformQuaternion(RTCGeometry hgeometry, unsigned int timeStep, const RTCQuaternionDecomposition* qd)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryTransformQuaternion);
+ RTC_VERIFY_HANDLE(hgeometry);
+ RTC_VERIFY_HANDLE(qd);
+
+ AffineSpace3fx transform;
+ transform.l.vx.x = qd->scale_x;
+ transform.l.vy.y = qd->scale_y;
+ transform.l.vz.z = qd->scale_z;
+ transform.l.vy.x = qd->skew_xy;
+ transform.l.vz.x = qd->skew_xz;
+ transform.l.vz.y = qd->skew_yz;
+ transform.l.vx.y = qd->translation_x;
+ transform.l.vx.z = qd->translation_y;
+ transform.l.vy.z = qd->translation_z;
+ transform.p.x = qd->shift_x;
+ transform.p.y = qd->shift_y;
+ transform.p.z = qd->shift_z;
+
+ // normalize quaternion
+ Quaternion3f q(qd->quaternion_r, qd->quaternion_i, qd->quaternion_j, qd->quaternion_k);
+ q = normalize(q);
+ transform.l.vx.w = q.i;
+ transform.l.vy.w = q.j;
+ transform.l.vz.w = q.k;
+ transform.p.w = q.r;
+
+ geometry->setQuaternionDecomposition(transform, timeStep);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcGetGeometryTransform(RTCGeometry hgeometry, float time, RTCFormat format, void* xfm)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryTransform);
+ const AffineSpace3fa transform = geometry->getTransform(time);
+ storeTransform(transform, format, (float*)xfm);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcFilterIntersection(const struct RTCIntersectFunctionNArguments* const args_i, const struct RTCFilterFunctionNArguments* filter_args)
+ {
+ IntersectFunctionNArguments* args = (IntersectFunctionNArguments*) args_i;
+ args->report(args,filter_args);
+ }
+
+ RTC_API void rtcFilterOcclusion(const struct RTCOccludedFunctionNArguments* const args_i, const struct RTCFilterFunctionNArguments* filter_args)
+ {
+ OccludedFunctionNArguments* args = (OccludedFunctionNArguments*) args_i;
+ args->report(args,filter_args);
+ }
+
+ RTC_API RTCGeometry rtcNewGeometry (RTCDevice hdevice, RTCGeometryType type)
+ {
+ Device* device = (Device*) hdevice;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcNewGeometry);
+ RTC_VERIFY_HANDLE(hdevice);
+
+ switch (type)
+ {
+ case RTC_GEOMETRY_TYPE_TRIANGLE:
+ {
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ createTriangleMeshTy createTriangleMesh = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createTriangleMesh);
+ Geometry* geom = createTriangleMesh(device);
+ return (RTCGeometry) geom->refInc();
+#else
+ throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_TRIANGLE is not supported");
+#endif
+ }
+
+ case RTC_GEOMETRY_TYPE_QUAD:
+ {
+#if defined(EMBREE_GEOMETRY_QUAD)
+ createQuadMeshTy createQuadMesh = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createQuadMesh);
+ Geometry* geom = createQuadMesh(device);
+ return (RTCGeometry) geom->refInc();
+#else
+ throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_QUAD is not supported");
+#endif
+ }
+
+ case RTC_GEOMETRY_TYPE_SPHERE_POINT:
+ case RTC_GEOMETRY_TYPE_DISC_POINT:
+ case RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT:
+ {
+#if defined(EMBREE_GEOMETRY_POINT)
+ createPointsTy createPoints = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_builder_cpu_features, createPoints);
+
+ Geometry *geom;
+ switch(type) {
+ case RTC_GEOMETRY_TYPE_SPHERE_POINT:
+ geom = createPoints(device, Geometry::GTY_SPHERE_POINT);
+ break;
+ case RTC_GEOMETRY_TYPE_DISC_POINT:
+ geom = createPoints(device, Geometry::GTY_DISC_POINT);
+ break;
+ case RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT:
+ geom = createPoints(device, Geometry::GTY_ORIENTED_DISC_POINT);
+ break;
+ default:
+ geom = nullptr;
+ break;
+ }
+ return (RTCGeometry) geom->refInc();
+#else
+ throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_POINT is not supported");
+#endif
+ }
+
+ case RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE:
+ case RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE:
+ case RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE:
+
+ case RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE:
+ case RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE:
+ case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE:
+
+ case RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE:
+ case RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE:
+ case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE:
+
+ case RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE:
+ case RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE:
+ case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE:
+
+ case RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE:
+ case RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE:
+ case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE:
+ {
+#if defined(EMBREE_GEOMETRY_CURVE)
+ createLineSegmentsTy createLineSegments = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createLineSegments);
+ createCurvesTy createCurves = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createCurves);
+
+ Geometry* geom;
+ switch (type) {
+ case RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_CONE_LINEAR_CURVE); break;
+ case RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_ROUND_LINEAR_CURVE); break;
+ case RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_FLAT_LINEAR_CURVE); break;
+ //case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_ORIENTED_LINEAR_CURVE); break;
+
+ case RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE : geom = createCurves(device,Geometry::GTY_ROUND_BEZIER_CURVE); break;
+ case RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE : geom = createCurves(device,Geometry::GTY_FLAT_BEZIER_CURVE); break;
+ case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE : geom = createCurves(device,Geometry::GTY_ORIENTED_BEZIER_CURVE); break;
+
+ case RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE : geom = createCurves(device,Geometry::GTY_ROUND_BSPLINE_CURVE); break;
+ case RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE : geom = createCurves(device,Geometry::GTY_FLAT_BSPLINE_CURVE); break;
+ case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE : geom = createCurves(device,Geometry::GTY_ORIENTED_BSPLINE_CURVE); break;
+
+ case RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE : geom = createCurves(device,Geometry::GTY_ROUND_HERMITE_CURVE); break;
+ case RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE : geom = createCurves(device,Geometry::GTY_FLAT_HERMITE_CURVE); break;
+ case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE : geom = createCurves(device,Geometry::GTY_ORIENTED_HERMITE_CURVE); break;
+
+ case RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE : geom = createCurves(device,Geometry::GTY_ROUND_CATMULL_ROM_CURVE); break;
+ case RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE : geom = createCurves(device,Geometry::GTY_FLAT_CATMULL_ROM_CURVE); break;
+ case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE : geom = createCurves(device,Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE); break;
+ default: geom = nullptr; break;
+ }
+ return (RTCGeometry) geom->refInc();
+#else
+ throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_CURVE is not supported");
+#endif
+ }
+
+ case RTC_GEOMETRY_TYPE_SUBDIVISION:
+ {
+#if defined(EMBREE_GEOMETRY_SUBDIVISION)
+ createSubdivMeshTy createSubdivMesh = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX(device->enabled_cpu_features,createSubdivMesh);
+ //SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createSubdivMesh); // FIXME: this does not work for some reason?
+ Geometry* geom = createSubdivMesh(device);
+ return (RTCGeometry) geom->refInc();
+#else
+ throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_SUBDIVISION is not supported");
+#endif
+ }
+
+ case RTC_GEOMETRY_TYPE_USER:
+ {
+#if defined(EMBREE_GEOMETRY_USER)
+ createUserGeometryTy createUserGeometry = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createUserGeometry);
+ Geometry* geom = createUserGeometry(device);
+ return (RTCGeometry) geom->refInc();
+#else
+ throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_USER is not supported");
+#endif
+ }
+
+ case RTC_GEOMETRY_TYPE_INSTANCE:
+ {
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ createInstanceTy createInstance = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createInstance);
+ Geometry* geom = createInstance(device);
+ return (RTCGeometry) geom->refInc();
+#else
+ throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_INSTANCE is not supported");
+#endif
+ }
+
+ case RTC_GEOMETRY_TYPE_GRID:
+ {
+#if defined(EMBREE_GEOMETRY_GRID)
+ createGridMeshTy createGridMesh = nullptr;
+ SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createGridMesh);
+ Geometry* geom = createGridMesh(device);
+ return (RTCGeometry) geom->refInc();
+#else
+ throw_RTCError(RTC_ERROR_UNKNOWN,"RTC_GEOMETRY_TYPE_GRID is not supported");
+#endif
+ }
+
+ default:
+ throw_RTCError(RTC_ERROR_UNKNOWN,"invalid geometry type");
+ }
+
+ RTC_CATCH_END(device);
+ return nullptr;
+ }
+
+ RTC_API void rtcSetGeometryUserPrimitiveCount(RTCGeometry hgeometry, unsigned int userPrimitiveCount)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryUserPrimitiveCount);
+ RTC_VERIFY_HANDLE(hgeometry);
+
+ if (unlikely(geometry->getType() != Geometry::GTY_USER_GEOMETRY))
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"operation only allowed for user geometries");
+
+ geometry->setNumPrimitives(userPrimitiveCount);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryTimeStepCount(RTCGeometry hgeometry, unsigned int timeStepCount)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryTimeStepCount);
+ RTC_VERIFY_HANDLE(hgeometry);
+
+ if (timeStepCount > RTC_MAX_TIME_STEP_COUNT)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"number of time steps is out of range");
+
+ geometry->setNumTimeSteps(timeStepCount);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryTimeRange(RTCGeometry hgeometry, float startTime, float endTime)
+ {
+ Ref<Geometry> geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryTimeRange);
+ RTC_VERIFY_HANDLE(hgeometry);
+
+ if (startTime > endTime)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"startTime has to be smaller or equal to the endTime");
+
+ geometry->setTimeRange(BBox1f(startTime,endTime));
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryVertexAttributeCount(RTCGeometry hgeometry, unsigned int N)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryVertexAttributeCount);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setVertexAttributeCount(N);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryTopologyCount(RTCGeometry hgeometry, unsigned int N)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryTopologyCount);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setTopologyCount(N);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryBuildQuality (RTCGeometry hgeometry, RTCBuildQuality quality)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryBuildQuality);
+ RTC_VERIFY_HANDLE(hgeometry);
+ if (quality != RTC_BUILD_QUALITY_LOW &&
+ quality != RTC_BUILD_QUALITY_MEDIUM &&
+ quality != RTC_BUILD_QUALITY_HIGH &&
+ quality != RTC_BUILD_QUALITY_REFIT)
+ // -- GODOT start --
+ // throw std::runtime_error("invalid build quality");
+ abort();
+ // -- GODOT end --
+ geometry->setBuildQuality(quality);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryMaxRadiusScale(RTCGeometry hgeometry, float maxRadiusScale)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryMaxRadiusScale);
+ RTC_VERIFY_HANDLE(hgeometry);
+#if RTC_MIN_WIDTH
+ if (maxRadiusScale < 1.0f) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"maximal radius scale has to be larger or equal to 1");
+ geometry->setMaxRadiusScale(maxRadiusScale);
+#else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"min-width feature is not enabled");
+#endif
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryMask (RTCGeometry hgeometry, unsigned int mask)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryMask);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setMask(mask);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometrySubdivisionMode (RTCGeometry hgeometry, unsigned topologyID, RTCSubdivisionMode mode)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometrySubdivisionMode);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setSubdivisionMode(topologyID,mode);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryVertexAttributeTopology(RTCGeometry hgeometry, unsigned int vertexAttributeID, unsigned int topologyID)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryVertexAttributeTopology);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setVertexAttributeTopology(vertexAttributeID, topologyID);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryBuffer(RTCGeometry hgeometry, RTCBufferType type, unsigned int slot, RTCFormat format, RTCBuffer hbuffer, size_t byteOffset, size_t byteStride, size_t itemCount)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ Ref<Buffer> buffer = (Buffer*)hbuffer;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryBuffer);
+ RTC_VERIFY_HANDLE(hgeometry);
+ RTC_VERIFY_HANDLE(hbuffer);
+
+ if (geometry->device != buffer->device)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"inputs are from different devices");
+
+ if (itemCount > 0xFFFFFFFFu)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"buffer too large");
+
+ geometry->setBuffer(type, slot, format, buffer, byteOffset, byteStride, (unsigned int)itemCount);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetSharedGeometryBuffer(RTCGeometry hgeometry, RTCBufferType type, unsigned int slot, RTCFormat format, const void* ptr, size_t byteOffset, size_t byteStride, size_t itemCount)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetSharedGeometryBuffer);
+ RTC_VERIFY_HANDLE(hgeometry);
+
+ if (itemCount > 0xFFFFFFFFu)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"buffer too large");
+
+ Ref<Buffer> buffer = new Buffer(geometry->device, itemCount*byteStride, (char*)ptr + byteOffset);
+ geometry->setBuffer(type, slot, format, buffer, 0, byteStride, (unsigned int)itemCount);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void* rtcSetNewGeometryBuffer(RTCGeometry hgeometry, RTCBufferType type, unsigned int slot, RTCFormat format, size_t byteStride, size_t itemCount)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetNewGeometryBuffer);
+ RTC_VERIFY_HANDLE(hgeometry);
+
+ if (itemCount > 0xFFFFFFFFu)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"buffer too large");
+
+ /* vertex buffers need to get overallocated slightly as elements are accessed using SSE loads */
+ size_t bytes = itemCount*byteStride;
+ if (type == RTC_BUFFER_TYPE_VERTEX || type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
+ bytes += (16 - (byteStride%16))%16;
+
+ Ref<Buffer> buffer = new Buffer(geometry->device, bytes);
+ geometry->setBuffer(type, slot, format, buffer, 0, byteStride, (unsigned int)itemCount);
+ return buffer->data();
+ RTC_CATCH_END2(geometry);
+ return nullptr;
+ }
+
+ RTC_API void* rtcGetGeometryBufferData(RTCGeometry hgeometry, RTCBufferType type, unsigned int slot)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryBufferData);
+ RTC_VERIFY_HANDLE(hgeometry);
+ return geometry->getBuffer(type, slot);
+ RTC_CATCH_END2(geometry);
+ return nullptr;
+ }
+
+ RTC_API void rtcEnableGeometry (RTCGeometry hgeometry)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcEnableGeometry);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->enable();
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcUpdateGeometryBuffer (RTCGeometry hgeometry, RTCBufferType type, unsigned int slot)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcUpdateGeometryBuffer);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->updateBuffer(type, slot);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcDisableGeometry (RTCGeometry hgeometry)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcDisableGeometry);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->disable();
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryTessellationRate (RTCGeometry hgeometry, float tessellationRate)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryTessellationRate);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setTessellationRate(tessellationRate);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryUserData (RTCGeometry hgeometry, void* ptr)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryUserData);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setUserData(ptr);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void* rtcGetGeometryUserData (RTCGeometry hgeometry)
+ {
+ Geometry* geometry = (Geometry*) hgeometry; // no ref counting here!
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryUserData);
+ RTC_VERIFY_HANDLE(hgeometry);
+ return geometry->getUserData();
+ RTC_CATCH_END2(geometry);
+ return nullptr;
+ }
+
+ RTC_API void rtcSetGeometryBoundsFunction (RTCGeometry hgeometry, RTCBoundsFunction bounds, void* userPtr)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryBoundsFunction);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setBoundsFunction(bounds,userPtr);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryDisplacementFunction (RTCGeometry hgeometry, RTCDisplacementFunctionN displacement)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryDisplacementFunction);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setDisplacementFunction(displacement);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryIntersectFunction (RTCGeometry hgeometry, RTCIntersectFunctionN intersect)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryIntersectFunction);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setIntersectFunctionN(intersect);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryPointQueryFunction(RTCGeometry hgeometry, RTCPointQueryFunction pointQuery)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryPointQueryFunction);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setPointQueryFunction(pointQuery);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API unsigned int rtcGetGeometryFirstHalfEdge(RTCGeometry hgeometry, unsigned int faceID)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryFirstHalfEdge);
+ return geometry->getFirstHalfEdge(faceID);
+ RTC_CATCH_END2(geometry);
+ return -1;
+ }
+
+ RTC_API unsigned int rtcGetGeometryFace(RTCGeometry hgeometry, unsigned int edgeID)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryFace);
+ return geometry->getFace(edgeID);
+ RTC_CATCH_END2(geometry);
+ return -1;
+ }
+
+ RTC_API unsigned int rtcGetGeometryNextHalfEdge(RTCGeometry hgeometry, unsigned int edgeID)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryNextHalfEdge);
+ return geometry->getNextHalfEdge(edgeID);
+ RTC_CATCH_END2(geometry);
+ return -1;
+ }
+
+ RTC_API unsigned int rtcGetGeometryPreviousHalfEdge(RTCGeometry hgeometry, unsigned int edgeID)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryPreviousHalfEdge);
+ return geometry->getPreviousHalfEdge(edgeID);
+ RTC_CATCH_END2(geometry);
+ return -1;
+ }
+
+ RTC_API unsigned int rtcGetGeometryOppositeHalfEdge(RTCGeometry hgeometry, unsigned int topologyID, unsigned int edgeID)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometryOppositeHalfEdge);
+ return geometry->getOppositeHalfEdge(topologyID,edgeID);
+ RTC_CATCH_END2(geometry);
+ return -1;
+ }
+
+ RTC_API void rtcSetGeometryOccludedFunction (RTCGeometry hgeometry, RTCOccludedFunctionN occluded)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetOccludedFunctionN);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setOccludedFunctionN(occluded);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryIntersectFilterFunction (RTCGeometry hgeometry, RTCFilterFunctionN filter)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryIntersectFilterFunction);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setIntersectionFilterFunctionN(filter);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcSetGeometryOccludedFilterFunction (RTCGeometry hgeometry, RTCFilterFunctionN filter)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcSetGeometryOccludedFilterFunction);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->setOcclusionFilterFunctionN(filter);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcInterpolate(const RTCInterpolateArguments* const args)
+ {
+ Geometry* geometry = (Geometry*) args->geometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcInterpolate);
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(args->geometry);
+#endif
+ geometry->interpolate(args);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcInterpolateN(const RTCInterpolateNArguments* const args)
+ {
+ Geometry* geometry = (Geometry*) args->geometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcInterpolateN);
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(args->geometry);
+#endif
+ geometry->interpolateN(args);
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcCommitGeometry (RTCGeometry hgeometry)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcCommitGeometry);
+ RTC_VERIFY_HANDLE(hgeometry);
+ return geometry->commit();
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API unsigned int rtcAttachGeometry (RTCScene hscene, RTCGeometry hgeometry)
+ {
+ Scene* scene = (Scene*) hscene;
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcAttachGeometry);
+ RTC_VERIFY_HANDLE(hscene);
+ RTC_VERIFY_HANDLE(hgeometry);
+ if (scene->device != geometry->device)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"inputs are from different devices");
+ return scene->bind(RTC_INVALID_GEOMETRY_ID,geometry);
+ RTC_CATCH_END2(scene);
+ return -1;
+ }
+
+ RTC_API void rtcAttachGeometryByID (RTCScene hscene, RTCGeometry hgeometry, unsigned int geomID)
+ {
+ Scene* scene = (Scene*) hscene;
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcAttachGeometryByID);
+ RTC_VERIFY_HANDLE(hscene);
+ RTC_VERIFY_HANDLE(hgeometry);
+ RTC_VERIFY_GEOMID(geomID);
+ if (scene->device != geometry->device)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"inputs are from different devices");
+ scene->bind(geomID,geometry);
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcDetachGeometry (RTCScene hscene, unsigned int geomID)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcDetachGeometry);
+ RTC_VERIFY_HANDLE(hscene);
+ RTC_VERIFY_GEOMID(geomID);
+ scene->detachGeometry(geomID);
+ RTC_CATCH_END2(scene);
+ }
+
+ RTC_API void rtcRetainGeometry (RTCGeometry hgeometry)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcRetainGeometry);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->refInc();
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API void rtcReleaseGeometry (RTCGeometry hgeometry)
+ {
+ Geometry* geometry = (Geometry*) hgeometry;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcReleaseGeometry);
+ RTC_VERIFY_HANDLE(hgeometry);
+ geometry->refDec();
+ RTC_CATCH_END2(geometry);
+ }
+
+ RTC_API RTCGeometry rtcGetGeometry (RTCScene hscene, unsigned int geomID)
+ {
+ Scene* scene = (Scene*) hscene;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcGetGeometry);
+#if defined(DEBUG)
+ RTC_VERIFY_HANDLE(hscene);
+ RTC_VERIFY_GEOMID(geomID);
+#endif
+ return (RTCGeometry) scene->get(geomID);
+ RTC_CATCH_END2(scene);
+ return nullptr;
+ }
+
+RTC_NAMESPACE_END
diff --git a/thirdparty/embree/kernels/common/rtcore.h b/thirdparty/embree/kernels/common/rtcore.h
new file mode 100644
index 0000000000..373e49a689
--- /dev/null
+++ b/thirdparty/embree/kernels/common/rtcore.h
@@ -0,0 +1,142 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../../include/embree3/rtcore.h"
+RTC_NAMESPACE_USE
+
+namespace embree
+{
+ /*! decoding of intersection flags */
+ __forceinline bool isCoherent (RTCIntersectContextFlags flags) { return (flags & RTC_INTERSECT_CONTEXT_FLAG_COHERENT) == RTC_INTERSECT_CONTEXT_FLAG_COHERENT; }
+ __forceinline bool isIncoherent(RTCIntersectContextFlags flags) { return (flags & RTC_INTERSECT_CONTEXT_FLAG_COHERENT) == RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT; }
+
+#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR >= 8)
+# define USE_TASK_ARENA 1
+#else
+# define USE_TASK_ARENA 0
+#endif
+
+#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION >= 11009) // TBB 2019 Update 9
+# define TASKING_TBB_USE_TASK_ISOLATION 1
+#else
+# define TASKING_TBB_USE_TASK_ISOLATION 0
+#endif
+
+/*! Macros used in the rtcore API implementation */
+// -- GODOT start --
+// #define RTC_CATCH_BEGIN try {
+#define RTC_CATCH_BEGIN
+
+// #define RTC_CATCH_END(device) \
+// } catch (std::bad_alloc&) { \
+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+// } catch (rtcore_error& e) { \
+// Device::process_error(device,e.error,e.what()); \
+// } catch (std::exception& e) { \
+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+// } catch (...) { \
+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+// }
+#define RTC_CATCH_END(device)
+
+// #define RTC_CATCH_END2(scene) \
+// } catch (std::bad_alloc&) { \
+// Device* device = scene ? scene->device : nullptr; \
+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+// } catch (rtcore_error& e) { \
+// Device* device = scene ? scene->device : nullptr; \
+// Device::process_error(device,e.error,e.what()); \
+// } catch (std::exception& e) { \
+// Device* device = scene ? scene->device : nullptr; \
+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+// } catch (...) { \
+// Device* device = scene ? scene->device : nullptr; \
+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+// }
+#define RTC_CATCH_END2(scene)
+
+// #define RTC_CATCH_END2_FALSE(scene) \
+// } catch (std::bad_alloc&) { \
+// Device* device = scene ? scene->device : nullptr; \
+// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+// return false; \
+// } catch (rtcore_error& e) { \
+// Device* device = scene ? scene->device : nullptr; \
+// Device::process_error(device,e.error,e.what()); \
+// return false; \
+// } catch (std::exception& e) { \
+// Device* device = scene ? scene->device : nullptr; \
+// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+// return false; \
+// } catch (...) { \
+// Device* device = scene ? scene->device : nullptr; \
+// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+// return false; \
+// }
+#define RTC_CATCH_END2_FALSE(scene) return false;
+// -- GODOT end --
+
+#define RTC_VERIFY_HANDLE(handle) \
+ if (handle == nullptr) { \
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"invalid argument"); \
+ }
+
+#define RTC_VERIFY_GEOMID(id) \
+ if (id == RTC_INVALID_GEOMETRY_ID) { \
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"invalid argument"); \
+ }
+
+#define RTC_VERIFY_UPPER(id,upper) \
+ if (id > upper) { \
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"invalid argument"); \
+ }
+
+#define RTC_VERIFY_RANGE(id,lower,upper) \
+ if (id < lower || id > upper) \
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"argument out of bounds");
+
+#if 0 // enable to debug print all API calls
+#define RTC_TRACE(x) std::cout << #x << std::endl;
+#else
+#define RTC_TRACE(x)
+#endif
+
+// -- GODOT begin --
+// /*! used to throw embree API errors */
+// struct rtcore_error : public std::exception
+// {
+// __forceinline rtcore_error(RTCError error, const std::string& str)
+// : error(error), str(str) {}
+//
+// ~rtcore_error() throw() {}
+//
+// const char* what () const throw () {
+// return str.c_str();
+// }
+//
+// RTCError error;
+// std::string str;
+// };
+// -- GODOT end --
+
+#if defined(DEBUG) // only report file and line in debug mode
+ // -- GODOT begin --
+ // #define throw_RTCError(error,str) \
+ // throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
+ #define throw_RTCError(error,str) \
+ printf(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)), abort();
+ // -- GODOT end --
+#else
+ // -- GODOT begin --
+ // #define throw_RTCError(error,str) \
+ // throw rtcore_error(error,str);
+ #define throw_RTCError(error,str) \
+ abort();
+ // -- GODOT end --
+#endif
+
+#define RTC_BUILD_ARGUMENTS_HAS(settings,member) \
+ (settings.byteSize > (offsetof(RTCBuildArguments,member)+sizeof(settings.member)))
+}
diff --git a/thirdparty/embree/kernels/common/rtcore_builder.cpp b/thirdparty/embree/kernels/common/rtcore_builder.cpp
new file mode 100644
index 0000000000..1f1b6f6ddf
--- /dev/null
+++ b/thirdparty/embree/kernels/common/rtcore_builder.cpp
@@ -0,0 +1,442 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#define RTC_EXPORT_API
+
+#include "default.h"
+#include "device.h"
+#include "scene.h"
+#include "context.h"
+#include "alloc.h"
+
+#include "../builders/bvh_builder_sah.h"
+#include "../builders/bvh_builder_morton.h"
+
+namespace embree
+{
+ namespace isa // FIXME: support more ISAs for builders
+ {
+ struct BVH : public RefCount
+ {
+ BVH (Device* device)
+ : device(device), allocator(device,true), morton_src(device,0), morton_tmp(device,0)
+ {
+ device->refInc();
+ }
+
+ ~BVH() {
+ device->refDec();
+ }
+
+ public:
+ Device* device;
+ FastAllocator allocator;
+ mvector<BVHBuilderMorton::BuildPrim> morton_src;
+ mvector<BVHBuilderMorton::BuildPrim> morton_tmp;
+ };
+
+ void* rtcBuildBVHMorton(const RTCBuildArguments* arguments)
+ {
+ BVH* bvh = (BVH*) arguments->bvh;
+ RTCBuildPrimitive* prims_i = arguments->primitives;
+ size_t primitiveCount = arguments->primitiveCount;
+ RTCCreateNodeFunction createNode = arguments->createNode;
+ RTCSetNodeChildrenFunction setNodeChildren = arguments->setNodeChildren;
+ RTCSetNodeBoundsFunction setNodeBounds = arguments->setNodeBounds;
+ RTCCreateLeafFunction createLeaf = arguments->createLeaf;
+ RTCProgressMonitorFunction buildProgress = arguments->buildProgress;
+ void* userPtr = arguments->userPtr;
+
+ std::atomic<size_t> progress(0);
+
+ /* initialize temporary arrays for morton builder */
+ PrimRef* prims = (PrimRef*) prims_i;
+ mvector<BVHBuilderMorton::BuildPrim>& morton_src = bvh->morton_src;
+ mvector<BVHBuilderMorton::BuildPrim>& morton_tmp = bvh->morton_tmp;
+ morton_src.resize(primitiveCount);
+ morton_tmp.resize(primitiveCount);
+
+ /* compute centroid bounds */
+ const BBox3fa centBounds = parallel_reduce ( size_t(0), primitiveCount, BBox3fa(empty), [&](const range<size_t>& r) -> BBox3fa {
+
+ BBox3fa bounds(empty);
+ for (size_t i=r.begin(); i<r.end(); i++)
+ bounds.extend(prims[i].bounds().center2());
+ return bounds;
+ }, BBox3fa::merge);
+
+ /* compute morton codes */
+ BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
+ parallel_for ( size_t(0), primitiveCount, [&](const range<size_t>& r) {
+ BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton_src[r.begin()]);
+ for (size_t i=r.begin(); i<r.end(); i++) {
+ generator(prims[i].bounds(),(unsigned) i);
+ }
+ });
+
+ /* start morton build */
+ std::pair<void*,BBox3fa> root = BVHBuilderMorton::build<std::pair<void*,BBox3fa>>(
+
+ /* thread local allocator for fast allocations */
+ [&] () -> FastAllocator::CachedAllocator {
+ return bvh->allocator.getCachedAllocator();
+ },
+
+ /* lambda function that allocates BVH nodes */
+ [&] ( const FastAllocator::CachedAllocator& alloc, size_t N ) -> void* {
+ return createNode((RTCThreadLocalAllocator)&alloc, (unsigned int)N,userPtr);
+ },
+
+ /* lambda function that sets bounds */
+ [&] (void* node, const std::pair<void*,BBox3fa>* children, size_t N) -> std::pair<void*,BBox3fa>
+ {
+ BBox3fa bounds = empty;
+ void* childptrs[BVHBuilderMorton::MAX_BRANCHING_FACTOR];
+ const RTCBounds* cbounds[BVHBuilderMorton::MAX_BRANCHING_FACTOR];
+ for (size_t i=0; i<N; i++) {
+ bounds.extend(children[i].second);
+ childptrs[i] = children[i].first;
+ cbounds[i] = (const RTCBounds*)&children[i].second;
+ }
+ setNodeBounds(node,cbounds,(unsigned int)N,userPtr);
+ setNodeChildren(node,childptrs, (unsigned int)N,userPtr);
+ return std::make_pair(node,bounds);
+ },
+
+ /* lambda function that creates BVH leaves */
+ [&]( const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc) -> std::pair<void*,BBox3fa>
+ {
+ RTCBuildPrimitive localBuildPrims[RTC_BUILD_MAX_PRIMITIVES_PER_LEAF];
+ BBox3fa bounds = empty;
+ for (size_t i=0;i<current.size();i++)
+ {
+ const size_t id = morton_src[current.begin()+i].index;
+ bounds.extend(prims[id].bounds());
+ localBuildPrims[i] = prims_i[id];
+ }
+ void* node = createLeaf((RTCThreadLocalAllocator)&alloc,localBuildPrims,current.size(),userPtr);
+ return std::make_pair(node,bounds);
+ },
+
+ /* lambda that calculates the bounds for some primitive */
+ [&] (const BVHBuilderMorton::BuildPrim& morton) -> BBox3fa {
+ return prims[morton.index].bounds();
+ },
+
+ /* progress monitor function */
+ [&] (size_t dn) {
+ if (!buildProgress) return true;
+ const size_t n = progress.fetch_add(dn)+dn;
+ const double f = std::min(1.0,double(n)/double(primitiveCount));
+ return buildProgress(userPtr,f);
+ },
+
+ morton_src.data(),morton_tmp.data(),primitiveCount,
+ *arguments);
+
+ bvh->allocator.cleanup();
+ return root.first;
+ }
+
+ void* rtcBuildBVHBinnedSAH(const RTCBuildArguments* arguments)
+ {
+ BVH* bvh = (BVH*) arguments->bvh;
+ RTCBuildPrimitive* prims = arguments->primitives;
+ size_t primitiveCount = arguments->primitiveCount;
+ RTCCreateNodeFunction createNode = arguments->createNode;
+ RTCSetNodeChildrenFunction setNodeChildren = arguments->setNodeChildren;
+ RTCSetNodeBoundsFunction setNodeBounds = arguments->setNodeBounds;
+ RTCCreateLeafFunction createLeaf = arguments->createLeaf;
+ RTCProgressMonitorFunction buildProgress = arguments->buildProgress;
+ void* userPtr = arguments->userPtr;
+
+ std::atomic<size_t> progress(0);
+
+ /* calculate priminfo */
+ auto computeBounds = [&](const range<size_t>& r) -> CentGeomBBox3fa
+ {
+ CentGeomBBox3fa bounds(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ bounds.extend((BBox3fa&)prims[j]);
+ return bounds;
+ };
+ const CentGeomBBox3fa bounds =
+ parallel_reduce(size_t(0),primitiveCount,size_t(1024),size_t(1024),CentGeomBBox3fa(empty), computeBounds, CentGeomBBox3fa::merge2);
+
+ const PrimInfo pinfo(0,primitiveCount,bounds);
+
+ /* build BVH */
+ void* root = BVHBuilderBinnedSAH::build<void*>(
+
+ /* thread local allocator for fast allocations */
+ [&] () -> FastAllocator::CachedAllocator {
+ return bvh->allocator.getCachedAllocator();
+ },
+
+ /* lambda function that creates BVH nodes */
+ [&](BVHBuilderBinnedSAH::BuildRecord* children, const size_t N, const FastAllocator::CachedAllocator& alloc) -> void*
+ {
+ void* node = createNode((RTCThreadLocalAllocator)&alloc, (unsigned int)N,userPtr);
+ const RTCBounds* cbounds[GeneralBVHBuilder::MAX_BRANCHING_FACTOR];
+ for (size_t i=0; i<N; i++) cbounds[i] = (const RTCBounds*) &children[i].prims.geomBounds;
+ setNodeBounds(node,cbounds, (unsigned int)N,userPtr);
+ return node;
+ },
+
+ /* lambda function that updates BVH nodes */
+ [&](const BVHBuilderBinnedSAH::BuildRecord& precord, const BVHBuilderBinnedSAH::BuildRecord* crecords, void* node, void** children, const size_t N) -> void* {
+ setNodeChildren(node,children, (unsigned int)N,userPtr);
+ return node;
+ },
+
+ /* lambda function that creates BVH leaves */
+ [&](const PrimRef* prims, const range<size_t>& range, const FastAllocator::CachedAllocator& alloc) -> void* {
+ return createLeaf((RTCThreadLocalAllocator)&alloc,(RTCBuildPrimitive*)(prims+range.begin()),range.size(),userPtr);
+ },
+
+ /* progress monitor function */
+ [&] (size_t dn) {
+ if (!buildProgress) return true;
+ const size_t n = progress.fetch_add(dn)+dn;
+ const double f = std::min(1.0,double(n)/double(primitiveCount));
+ return buildProgress(userPtr,f);
+ },
+
+ (PrimRef*)prims,pinfo,*arguments);
+
+ bvh->allocator.cleanup();
+ return root;
+ }
+
+ static __forceinline const std::pair<CentGeomBBox3fa,unsigned int> mergePair(const std::pair<CentGeomBBox3fa,unsigned int>& a, const std::pair<CentGeomBBox3fa,unsigned int>& b) {
+ CentGeomBBox3fa centBounds = CentGeomBBox3fa::merge2(a.first,b.first);
+ unsigned int maxGeomID = max(a.second,b.second);
+ return std::pair<CentGeomBBox3fa,unsigned int>(centBounds,maxGeomID);
+ }
+
+ void* rtcBuildBVHSpatialSAH(const RTCBuildArguments* arguments)
+ {
+ BVH* bvh = (BVH*) arguments->bvh;
+ RTCBuildPrimitive* prims = arguments->primitives;
+ size_t primitiveCount = arguments->primitiveCount;
+ RTCCreateNodeFunction createNode = arguments->createNode;
+ RTCSetNodeChildrenFunction setNodeChildren = arguments->setNodeChildren;
+ RTCSetNodeBoundsFunction setNodeBounds = arguments->setNodeBounds;
+ RTCCreateLeafFunction createLeaf = arguments->createLeaf;
+ RTCSplitPrimitiveFunction splitPrimitive = arguments->splitPrimitive;
+ RTCProgressMonitorFunction buildProgress = arguments->buildProgress;
+ void* userPtr = arguments->userPtr;
+
+ std::atomic<size_t> progress(0);
+
+ /* calculate priminfo */
+
+ auto computeBounds = [&](const range<size_t>& r) -> std::pair<CentGeomBBox3fa,unsigned int>
+ {
+ CentGeomBBox3fa bounds(empty);
+ unsigned maxGeomID = 0;
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ bounds.extend((BBox3fa&)prims[j]);
+ maxGeomID = max(maxGeomID,prims[j].geomID);
+ }
+ return std::pair<CentGeomBBox3fa,unsigned int>(bounds,maxGeomID);
+ };
+
+
+ const std::pair<CentGeomBBox3fa,unsigned int> pair =
+ parallel_reduce(size_t(0),primitiveCount,size_t(1024),size_t(1024),std::pair<CentGeomBBox3fa,unsigned int>(CentGeomBBox3fa(empty),0), computeBounds, mergePair);
+
+ CentGeomBBox3fa bounds = pair.first;
+ const unsigned int maxGeomID = pair.second;
+
+ if (unlikely(maxGeomID >= ((unsigned int)1 << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS))))
+ {
+ /* fallback code for max geomID larger than threshold */
+ return rtcBuildBVHBinnedSAH(arguments);
+ }
+
+ const PrimInfo pinfo(0,primitiveCount,bounds);
+
+ /* function that splits a build primitive */
+ struct Splitter
+ {
+ Splitter (RTCSplitPrimitiveFunction splitPrimitive, unsigned geomID, unsigned primID, void* userPtr)
+ : splitPrimitive(splitPrimitive), geomID(geomID), primID(primID), userPtr(userPtr) {}
+
+ __forceinline void operator() (PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const
+ {
+ prim.geomIDref() &= BVHBuilderBinnedFastSpatialSAH::GEOMID_MASK;
+ splitPrimitive((RTCBuildPrimitive*)&prim,(unsigned)dim,pos,(RTCBounds*)&left_o,(RTCBounds*)&right_o,userPtr);
+ left_o.geomIDref() = geomID; left_o.primIDref() = primID;
+ right_o.geomIDref() = geomID; right_o.primIDref() = primID;
+ }
+
+ __forceinline void operator() (const BBox3fa& box, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const
+ {
+ PrimRef prim(box,geomID & BVHBuilderBinnedFastSpatialSAH::GEOMID_MASK,primID);
+ splitPrimitive((RTCBuildPrimitive*)&prim,(unsigned)dim,pos,(RTCBounds*)&left_o,(RTCBounds*)&right_o,userPtr);
+ }
+
+ RTCSplitPrimitiveFunction splitPrimitive;
+ unsigned geomID;
+ unsigned primID;
+ void* userPtr;
+ };
+
+ /* build BVH */
+ void* root = BVHBuilderBinnedFastSpatialSAH::build<void*>(
+
+ /* thread local allocator for fast allocations */
+ [&] () -> FastAllocator::CachedAllocator {
+ return bvh->allocator.getCachedAllocator();
+ },
+
+ /* lambda function that creates BVH nodes */
+ [&] (BVHBuilderBinnedFastSpatialSAH::BuildRecord* children, const size_t N, const FastAllocator::CachedAllocator& alloc) -> void*
+ {
+ void* node = createNode((RTCThreadLocalAllocator)&alloc, (unsigned int)N,userPtr);
+ const RTCBounds* cbounds[GeneralBVHBuilder::MAX_BRANCHING_FACTOR];
+ for (size_t i=0; i<N; i++) cbounds[i] = (const RTCBounds*) &children[i].prims.geomBounds;
+ setNodeBounds(node,cbounds, (unsigned int)N,userPtr);
+ return node;
+ },
+
+ /* lambda function that updates BVH nodes */
+ [&] (const BVHBuilderBinnedFastSpatialSAH::BuildRecord& precord, const BVHBuilderBinnedFastSpatialSAH::BuildRecord* crecords, void* node, void** children, const size_t N) -> void* {
+ setNodeChildren(node,children, (unsigned int)N,userPtr);
+ return node;
+ },
+
+ /* lambda function that creates BVH leaves */
+ [&] (const PrimRef* prims, const range<size_t>& range, const FastAllocator::CachedAllocator& alloc) -> void* {
+ return createLeaf((RTCThreadLocalAllocator)&alloc,(RTCBuildPrimitive*)(prims+range.begin()),range.size(),userPtr);
+ },
+
+ /* returns the splitter */
+ [&] ( const PrimRef& prim ) -> Splitter {
+ return Splitter(splitPrimitive,prim.geomID(),prim.primID(),userPtr);
+ },
+
+ /* progress monitor function */
+ [&] (size_t dn) {
+ if (!buildProgress) return true;
+ const size_t n = progress.fetch_add(dn)+dn;
+ const double f = std::min(1.0,double(n)/double(primitiveCount));
+ return buildProgress(userPtr,f);
+ },
+
+ (PrimRef*)prims,
+ arguments->primitiveArrayCapacity,
+ pinfo,*arguments);
+
+ bvh->allocator.cleanup();
+ return root;
+ }
+ }
+}
+
+using namespace embree;
+using namespace embree::isa;
+
+RTC_NAMESPACE_BEGIN
+
+ RTC_API RTCBVH rtcNewBVH(RTCDevice device)
+ {
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcNewAllocator);
+ RTC_VERIFY_HANDLE(device);
+ BVH* bvh = new BVH((Device*)device);
+ return (RTCBVH) bvh->refInc();
+ RTC_CATCH_END((Device*)device);
+ return nullptr;
+ }
+
+ RTC_API void* rtcBuildBVH(const RTCBuildArguments* arguments)
+ {
+ BVH* bvh = (BVH*) arguments->bvh;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcBuildBVH);
+ RTC_VERIFY_HANDLE(bvh);
+ RTC_VERIFY_HANDLE(arguments);
+ RTC_VERIFY_HANDLE(arguments->createNode);
+ RTC_VERIFY_HANDLE(arguments->setNodeChildren);
+ RTC_VERIFY_HANDLE(arguments->setNodeBounds);
+ RTC_VERIFY_HANDLE(arguments->createLeaf);
+
+ if (arguments->primitiveArrayCapacity < arguments->primitiveCount)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"primitiveArrayCapacity must be greater or equal to primitiveCount")
+
+ /* initialize the allocator */
+ bvh->allocator.init_estimate(arguments->primitiveCount*sizeof(BBox3fa));
+ bvh->allocator.reset();
+
+ /* switch between differnet builders based on quality level */
+ if (arguments->buildQuality == RTC_BUILD_QUALITY_LOW)
+ return rtcBuildBVHMorton(arguments);
+ else if (arguments->buildQuality == RTC_BUILD_QUALITY_MEDIUM)
+ return rtcBuildBVHBinnedSAH(arguments);
+ else if (arguments->buildQuality == RTC_BUILD_QUALITY_HIGH) {
+ if (arguments->splitPrimitive == nullptr || arguments->primitiveArrayCapacity <= arguments->primitiveCount)
+ return rtcBuildBVHBinnedSAH(arguments);
+ else
+ return rtcBuildBVHSpatialSAH(arguments);
+ }
+ else
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid build quality");
+
+ /* if we are in dynamic mode, then do not clear temporary data */
+ if (!(arguments->buildFlags & RTC_BUILD_FLAG_DYNAMIC))
+ {
+ bvh->morton_src.clear();
+ bvh->morton_tmp.clear();
+ }
+
+ RTC_CATCH_END(bvh->device);
+ return nullptr;
+ }
+
+ RTC_API void* rtcThreadLocalAlloc(RTCThreadLocalAllocator localAllocator, size_t bytes, size_t align)
+ {
+ FastAllocator::CachedAllocator* alloc = (FastAllocator::CachedAllocator*) localAllocator;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcThreadLocalAlloc);
+ return alloc->malloc0(bytes,align);
+ RTC_CATCH_END(alloc->alloc->getDevice());
+ return nullptr;
+ }
+
+ RTC_API void rtcMakeStaticBVH(RTCBVH hbvh)
+ {
+ BVH* bvh = (BVH*) hbvh;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcStaticBVH);
+ RTC_VERIFY_HANDLE(hbvh);
+ bvh->morton_src.clear();
+ bvh->morton_tmp.clear();
+ RTC_CATCH_END(bvh->device);
+ }
+
+ RTC_API void rtcRetainBVH(RTCBVH hbvh)
+ {
+ BVH* bvh = (BVH*) hbvh;
+ Device* device = bvh ? bvh->device : nullptr;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcRetainBVH);
+ RTC_VERIFY_HANDLE(hbvh);
+ bvh->refInc();
+ RTC_CATCH_END(device);
+ }
+
+ RTC_API void rtcReleaseBVH(RTCBVH hbvh)
+ {
+ BVH* bvh = (BVH*) hbvh;
+ Device* device = bvh ? bvh->device : nullptr;
+ RTC_CATCH_BEGIN;
+ RTC_TRACE(rtcReleaseBVH);
+ RTC_VERIFY_HANDLE(hbvh);
+ bvh->refDec();
+ RTC_CATCH_END(device);
+ }
+
+RTC_NAMESPACE_END
diff --git a/thirdparty/embree/kernels/common/scene.cpp b/thirdparty/embree/kernels/common/scene.cpp
new file mode 100644
index 0000000000..408d7eae6f
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene.cpp
@@ -0,0 +1,955 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "scene.h"
+
+#include "../bvh/bvh4_factory.h"
+#include "../bvh/bvh8_factory.h"
+#include "../../common/algorithms/parallel_reduce.h"
+
+namespace embree
+{
+ /* error raising rtcIntersect and rtcOccluded functions */
+ void missing_rtcCommit() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed"); }
+ void invalid_rtcIntersect1() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect and rtcOccluded not enabled"); }
+ void invalid_rtcIntersect4() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect4 and rtcOccluded4 not enabled"); }
+ void invalid_rtcIntersect8() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect8 and rtcOccluded8 not enabled"); }
+ void invalid_rtcIntersect16() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect16 and rtcOccluded16 not enabled"); }
+ void invalid_rtcIntersectN() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectN and rtcOccludedN not enabled"); }
+
+ Scene::Scene (Device* device)
+ : device(device),
+ flags_modified(true), enabled_geometry_types(0),
+ scene_flags(RTC_SCENE_FLAG_NONE),
+ quality_flags(RTC_BUILD_QUALITY_MEDIUM),
+ is_build(false), modified(true),
+ progressInterface(this), progress_monitor_function(nullptr), progress_monitor_ptr(nullptr), progress_monitor_counter(0)
+ {
+ device->refInc();
+
+ intersectors = Accel::Intersectors(missing_rtcCommit);
+
+ /* one can overwrite flags through device for debugging */
+ if (device->quality_flags != -1)
+ quality_flags = (RTCBuildQuality) device->quality_flags;
+ if (device->scene_flags != -1)
+ scene_flags = (RTCSceneFlags) device->scene_flags;
+ }
+
+ Scene::~Scene() noexcept
+ {
+ device->refDec();
+ }
+
+ void Scene::printStatistics()
+ {
+ /* calculate maximum number of time segments */
+ unsigned max_time_steps = 0;
+ for (size_t i=0; i<size(); i++) {
+ if (!get(i)) continue;
+ max_time_steps = max(max_time_steps,get(i)->numTimeSteps);
+ }
+
+ /* initialize vectors*/
+ std::vector<size_t> statistics[Geometry::GTY_END];
+ for (size_t i=0; i<Geometry::GTY_END; i++)
+ statistics[i].resize(max_time_steps);
+
+ /* gather statistics */
+ for (size_t i=0; i<size(); i++)
+ {
+ if (!get(i)) continue;
+ int ty = get(i)->getType();
+ assert(ty<Geometry::GTY_END);
+ int timesegments = get(i)->numTimeSegments();
+ assert((unsigned int)timesegments < max_time_steps);
+ statistics[ty][timesegments] += get(i)->size();
+ }
+
+ /* print statistics */
+ std::cout << std::setw(23) << "segments" << ": ";
+ for (size_t t=0; t<max_time_steps; t++)
+ std::cout << std::setw(10) << t;
+ std::cout << std::endl;
+
+ std::cout << "-------------------------";
+ for (size_t t=0; t<max_time_steps; t++)
+ std::cout << "----------";
+ std::cout << std::endl;
+
+ for (size_t p=0; p<Geometry::GTY_END; p++)
+ {
+ if (std::string(Geometry::gtype_names[p]) == "") continue;
+ std::cout << std::setw(23) << Geometry::gtype_names[p] << ": ";
+ for (size_t t=0; t<max_time_steps; t++)
+ std::cout << std::setw(10) << statistics[p][t];
+ std::cout << std::endl;
+ }
+ }
+
+ void Scene::createTriangleAccel()
+ {
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ if (device->tri_accel == "default")
+ {
+ if (quality_flags != RTC_BUILD_QUALITY_LOW)
+ {
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+ switch (mode) {
+ case /*0b00*/ 0:
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX())
+ {
+ if (quality_flags == RTC_BUILD_QUALITY_HIGH)
+ accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
+ else
+ accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
+ }
+ else
+#endif
+ {
+ if (quality_flags == RTC_BUILD_QUALITY_HIGH)
+ accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
+ else
+ accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
+ }
+ break;
+
+ case /*0b01*/ 1:
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX())
+ accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
+ else
+#endif
+ accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
+
+ break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ else /* dynamic */
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX())
+ {
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+ switch (mode) {
+ case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ else
+#endif
+ {
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+ switch (mode) {
+ case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ }
+ }
+ else if (device->tri_accel == "bvh4.triangle4") accels_add(device->bvh4_factory->BVH4Triangle4 (this));
+ else if (device->tri_accel == "bvh4.triangle4v") accels_add(device->bvh4_factory->BVH4Triangle4v(this));
+ else if (device->tri_accel == "bvh4.triangle4i") accels_add(device->bvh4_factory->BVH4Triangle4i(this));
+ else if (device->tri_accel == "qbvh4.triangle4i") accels_add(device->bvh4_factory->BVH4QuantizedTriangle4i(this));
+
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->tri_accel == "bvh8.triangle4") accels_add(device->bvh8_factory->BVH8Triangle4 (this));
+ else if (device->tri_accel == "bvh8.triangle4v") accels_add(device->bvh8_factory->BVH8Triangle4v(this));
+ else if (device->tri_accel == "bvh8.triangle4i") accels_add(device->bvh8_factory->BVH8Triangle4i(this));
+ else if (device->tri_accel == "qbvh8.triangle4i") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4i(this));
+ else if (device->tri_accel == "qbvh8.triangle4") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4(this));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown triangle acceleration structure "+device->tri_accel);
+#endif
+ }
+
+ void Scene::createTriangleMBAccel()
+ {
+#if defined(EMBREE_GEOMETRY_TRIANGLE)
+ if (device->tri_accel_mb == "default")
+ {
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX2()) // BVH8 reduces performance on AVX only-machines
+ {
+ switch (mode) {
+ case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ else
+#endif
+ {
+ switch (mode) {
+ case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ }
+ else if (device->tri_accel_mb == "bvh4.triangle4imb") accels_add(device->bvh4_factory->BVH4Triangle4iMB(this));
+ else if (device->tri_accel_mb == "bvh4.triangle4vmb") accels_add(device->bvh4_factory->BVH4Triangle4vMB(this));
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->tri_accel_mb == "bvh8.triangle4imb") accels_add(device->bvh8_factory->BVH8Triangle4iMB(this));
+ else if (device->tri_accel_mb == "bvh8.triangle4vmb") accels_add(device->bvh8_factory->BVH8Triangle4vMB(this));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur triangle acceleration structure "+device->tri_accel_mb);
+#endif
+ }
+
+ void Scene::createQuadAccel()
+ {
+#if defined(EMBREE_GEOMETRY_QUAD)
+ if (device->quad_accel == "default")
+ {
+ if (quality_flags != RTC_BUILD_QUALITY_LOW)
+ {
+ /* static */
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+ switch (mode) {
+ case /*0b00*/ 0:
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX())
+ {
+ if (quality_flags == RTC_BUILD_QUALITY_HIGH)
+ accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
+ else
+ accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
+ }
+ else
+#endif
+ {
+ if (quality_flags == RTC_BUILD_QUALITY_HIGH)
+ accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
+ else
+ accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
+ }
+ break;
+
+ case /*0b01*/ 1:
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX())
+ accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
+ else
+#endif
+ accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
+ break;
+
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ else /* dynamic */
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX())
+ {
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+ switch (mode) {
+ case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ else
+#endif
+ {
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+ switch (mode) {
+ case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ }
+ }
+ else if (device->quad_accel == "bvh4.quad4v") accels_add(device->bvh4_factory->BVH4Quad4v(this));
+ else if (device->quad_accel == "bvh4.quad4i") accels_add(device->bvh4_factory->BVH4Quad4i(this));
+ else if (device->quad_accel == "qbvh4.quad4i") accels_add(device->bvh4_factory->BVH4QuantizedQuad4i(this));
+
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->quad_accel == "bvh8.quad4v") accels_add(device->bvh8_factory->BVH8Quad4v(this));
+ else if (device->quad_accel == "bvh8.quad4i") accels_add(device->bvh8_factory->BVH8Quad4i(this));
+ else if (device->quad_accel == "qbvh8.quad4i") accels_add(device->bvh8_factory->BVH8QuantizedQuad4i(this));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad acceleration structure "+device->quad_accel);
+#endif
+ }
+
+ void Scene::createQuadMBAccel()
+ {
+#if defined(EMBREE_GEOMETRY_QUAD)
+ if (device->quad_accel_mb == "default")
+ {
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+ switch (mode) {
+ case /*0b00*/ 0:
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX())
+ accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
+ else
+#endif
+ accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
+ break;
+
+ case /*0b01*/ 1:
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX())
+ accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
+ else
+#endif
+ accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
+ break;
+
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ else if (device->quad_accel_mb == "bvh4.quad4imb") accels_add(device->bvh4_factory->BVH4Quad4iMB(this));
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->quad_accel_mb == "bvh8.quad4imb") accels_add(device->bvh8_factory->BVH8Quad4iMB(this));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad motion blur acceleration structure "+device->quad_accel_mb);
+#endif
+ }
+
+ void Scene::createHairAccel()
+ {
+#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
+ if (device->hair_accel == "default")
+ {
+ int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX2()) // only enable on HSW machines, for SNB this codepath is slower
+ {
+ switch (mode) {
+ case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::ROBUST)); break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ else
+#endif
+ {
+ switch (mode) {
+ case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::ROBUST)); break;
+ case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST)); break;
+ case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::ROBUST)); break;
+ }
+ }
+ }
+ else if (device->hair_accel == "bvh4obb.virtualcurve4v" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST));
+ else if (device->hair_accel == "bvh4obb.virtualcurve4i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST));
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->hair_accel == "bvh8obb.virtualcurve8v" ) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST));
+ else if (device->hair_accel == "bvh4obb.virtualcurve8i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown hair acceleration structure "+device->hair_accel);
+#endif
+ }
+
+ void Scene::createHairMBAccel()
+ {
+#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
+ if (device->hair_accel_mb == "default")
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX2()) // only enable on HSW machines, on SNB this codepath is slower
+ {
+ if (isRobustAccel()) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::ROBUST));
+ else accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
+ }
+ else
+#endif
+ {
+ if (isRobustAccel()) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::ROBUST));
+ else accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));
+ }
+ }
+ else if (device->hair_accel_mb == "bvh4.virtualcurve4imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));
+
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->hair_accel_mb == "bvh4.virtualcurve8imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
+ else if (device->hair_accel_mb == "bvh8.virtualcurve8imb") accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur hair acceleration structure "+device->hair_accel_mb);
+#endif
+ }
+
+ void Scene::createSubdivAccel()
+ {
+#if defined(EMBREE_GEOMETRY_SUBDIVISION)
+ if (device->subdiv_accel == "default") {
+ accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
+ }
+ else if (device->subdiv_accel == "bvh4.grid.eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
+ else if (device->subdiv_accel == "bvh4.subdivpatch1eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv accel "+device->subdiv_accel);
+#endif
+ }
+
+ void Scene::createSubdivMBAccel()
+ {
+#if defined(EMBREE_GEOMETRY_SUBDIVISION)
+ if (device->subdiv_accel_mb == "default") {
+ accels_add(device->bvh4_factory->BVH4SubdivPatch1MB(this));
+ }
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv mblur accel "+device->subdiv_accel_mb);
+#endif
+ }
+
+ void Scene::createUserGeometryAccel()
+ {
+#if defined(EMBREE_GEOMETRY_USER)
+ if (device->object_accel == "default")
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX() && !isCompactAccel())
+ {
+ if (quality_flags != RTC_BUILD_QUALITY_LOW) {
+ accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::STATIC));
+ } else {
+ accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));
+ }
+ }
+ else
+#endif
+ {
+ if (quality_flags != RTC_BUILD_QUALITY_LOW) {
+ accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::STATIC));
+ } else {
+ accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));
+ }
+ }
+ }
+ else if (device->object_accel == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometry(this));
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->object_accel == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometry(this));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry accel "+device->object_accel);
+#endif
+ }
+
+ void Scene::createUserGeometryMBAccel()
+ {
+#if defined(EMBREE_GEOMETRY_USER)
+ if (device->object_accel_mb == "default" ) {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX() && !isCompactAccel())
+ accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));
+ else
+#endif
+ accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));
+ }
+ else if (device->object_accel_mb == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->object_accel_mb == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry mblur accel "+device->object_accel_mb);
+#endif
+ }
+
+ void Scene::createInstanceAccel()
+ {
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ // if (device->object_accel == "default")
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX() && !isCompactAccel()) {
+ if (quality_flags != RTC_BUILD_QUALITY_LOW) {
+ accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::STATIC));
+ } else {
+ accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));
+ }
+ }
+ else
+#endif
+ {
+ if (quality_flags != RTC_BUILD_QUALITY_LOW) {
+ accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::STATIC));
+ } else {
+ accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));
+ }
+ }
+ }
+ // else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
+#endif
+ }
+
+ void Scene::createInstanceMBAccel()
+ {
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ //if (device->instance_accel_mb == "default")
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX() && !isCompactAccel())
+ accels_add(device->bvh8_factory->BVH8InstanceMB(this, false));
+ else
+#endif
+ accels_add(device->bvh4_factory->BVH4InstanceMB(this, false));
+ }
+ //else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
+#endif
+ }
+
+ void Scene::createInstanceExpensiveAccel()
+ {
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ // if (device->object_accel == "default")
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX() && !isCompactAccel()) {
+ if (quality_flags != RTC_BUILD_QUALITY_LOW) {
+ accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::STATIC));
+ } else {
+ accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));
+ }
+ }
+ else
+#endif
+ {
+ if (quality_flags != RTC_BUILD_QUALITY_LOW) {
+ accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::STATIC));
+ } else {
+ accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));
+ }
+ }
+ }
+ // else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
+#endif
+ }
+
+ void Scene::createInstanceExpensiveMBAccel()
+ {
+#if defined(EMBREE_GEOMETRY_INSTANCE)
+ //if (device->instance_accel_mb == "default")
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX() && !isCompactAccel())
+ accels_add(device->bvh8_factory->BVH8InstanceMB(this, true));
+ else
+#endif
+ accels_add(device->bvh4_factory->BVH4InstanceMB(this, true));
+ }
+ //else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
+#endif
+ }
+
+ void Scene::createGridAccel()
+ {
+ BVHFactory::IntersectVariant ivariant = isRobustAccel() ? BVHFactory::IntersectVariant::ROBUST : BVHFactory::IntersectVariant::FAST;
+#if defined(EMBREE_GEOMETRY_GRID)
+ if (device->grid_accel == "default")
+ {
+#if defined (EMBREE_TARGET_SIMD8)
+ if (device->canUseAVX() && !isCompactAccel())
+ {
+ accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
+ }
+ else
+#endif
+ {
+ accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
+ }
+ }
+ else if (device->grid_accel == "bvh4.grid") accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
+#if defined (EMBREE_TARGET_SIMD8)
+ else if (device->grid_accel == "bvh8.grid") accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
+#endif
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid accel "+device->grid_accel);
+#endif
+
+ }
+
+ void Scene::createGridMBAccel()
+ {
+#if defined(EMBREE_GEOMETRY_GRID)
+ if (device->grid_accel_mb == "default")
+ {
+ accels_add(device->bvh4_factory->BVH4GridMB(this,BVHFactory::BuildVariant::STATIC));
+ }
+ else if (device->grid_accel_mb == "bvh4mb.grid") accels_add(device->bvh4_factory->BVH4GridMB(this));
+ else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid mb accel "+device->grid_accel);
+#endif
+
+ }
+
+ void Scene::clear() {
+ }
+
+ unsigned Scene::bind(unsigned geomID, Ref<Geometry> geometry)
+ {
+ Lock<SpinLock> lock(geometriesMutex);
+ if (geomID == RTC_INVALID_GEOMETRY_ID) {
+ geomID = id_pool.allocate();
+ if (geomID == RTC_INVALID_GEOMETRY_ID)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"too many geometries inside scene");
+ }
+ else
+ {
+ if (!id_pool.add(geomID))
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID provided");
+ }
+ if (geomID >= geometries.size()) {
+ geometries.resize(geomID+1);
+ vertices.resize(geomID+1);
+ geometryModCounters_.resize(geomID+1);
+ }
+ geometries[geomID] = geometry;
+ geometryModCounters_[geomID] = 0;
+ if (geometry->isEnabled()) {
+ setModified ();
+ }
+ return geomID;
+ }
+
+ void Scene::detachGeometry(size_t geomID)
+ {
+ Lock<SpinLock> lock(geometriesMutex);
+
+ if (geomID >= geometries.size())
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID");
+
+ Ref<Geometry>& geometry = geometries[geomID];
+ if (geometry == null)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry");
+
+ if (geometry->isEnabled()) {
+ setModified ();
+ }
+ accels_deleteGeometry(unsigned(geomID));
+ id_pool.deallocate((unsigned)geomID);
+ geometries[geomID] = null;
+ vertices[geomID] = nullptr;
+ geometryModCounters_[geomID] = 0;
+ }
+
+ void Scene::updateInterface()
+ {
+ is_build = true;
+ }
+
+ void Scene::commit_task ()
+ {
+ checkIfModifiedAndSet ();
+ if (!isModified()) {
+ return;
+ }
+
+ /* print scene statistics */
+ if (device->verbosity(2))
+ printStatistics();
+
+ progress_monitor_counter = 0;
+
+ /* gather scene stats and call preCommit function of each geometry */
+ this->world = parallel_reduce (size_t(0), geometries.size(), GeometryCounts (),
+ [this](const range<size_t>& r)->GeometryCounts
+ {
+ GeometryCounts c;
+ for (auto i=r.begin(); i<r.end(); ++i)
+ {
+ if (geometries[i] && geometries[i]->isEnabled())
+ {
+ geometries[i]->preCommit();
+ geometries[i]->addElementsToCount (c);
+ c.numFilterFunctions += (int) geometries[i]->hasFilterFunctions();
+ }
+ }
+ return c;
+ },
+ std::plus<GeometryCounts>()
+ );
+
+ /* select acceleration structures to build */
+ unsigned int new_enabled_geometry_types = world.enabledGeometryTypesMask();
+ if (flags_modified || new_enabled_geometry_types != enabled_geometry_types)
+ {
+ accels_init();
+
+ /* we need to make all geometries modified, otherwise two level builder will
+ not rebuild currently not modified geometries */
+ parallel_for(geometryModCounters_.size(), [&] ( const size_t i ) {
+ geometryModCounters_[i] = 0;
+ });
+
+ if (getNumPrimitives(TriangleMesh::geom_type,false)) createTriangleAccel();
+ if (getNumPrimitives(TriangleMesh::geom_type,true)) createTriangleMBAccel();
+ if (getNumPrimitives(QuadMesh::geom_type,false)) createQuadAccel();
+ if (getNumPrimitives(QuadMesh::geom_type,true)) createQuadMBAccel();
+ if (getNumPrimitives(GridMesh::geom_type,false)) createGridAccel();
+ if (getNumPrimitives(GridMesh::geom_type,true)) createGridMBAccel();
+ if (getNumPrimitives(SubdivMesh::geom_type,false)) createSubdivAccel();
+ if (getNumPrimitives(SubdivMesh::geom_type,true)) createSubdivMBAccel();
+ if (getNumPrimitives(Geometry::MTY_CURVES,false)) createHairAccel();
+ if (getNumPrimitives(Geometry::MTY_CURVES,true)) createHairMBAccel();
+ if (getNumPrimitives(UserGeometry::geom_type,false)) createUserGeometryAccel();
+ if (getNumPrimitives(UserGeometry::geom_type,true)) createUserGeometryMBAccel();
+ if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,false)) createInstanceAccel();
+ if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,true)) createInstanceMBAccel();
+ if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,false)) createInstanceExpensiveAccel();
+ if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,true)) createInstanceExpensiveMBAccel();
+
+ flags_modified = false;
+ enabled_geometry_types = new_enabled_geometry_types;
+ }
+
+ /* select fast code path if no filter function is present */
+ accels_select(hasFilterFunction());
+
+ /* build all hierarchies of this scene */
+ accels_build();
+
+ /* make static geometry immutable */
+ if (!isDynamicAccel()) {
+ accels_immutable();
+ flags_modified = true; // in non-dynamic mode we have to re-create accels
+ }
+
+ /* call postCommit function of each geometry */
+ parallel_for(geometries.size(), [&] ( const size_t i ) {
+ if (geometries[i] && geometries[i]->isEnabled()) {
+ geometries[i]->postCommit();
+ vertices[i] = geometries[i]->getCompactVertexArray();
+ geometryModCounters_[i] = geometries[i]->getModCounter();
+ }
+ });
+
+ updateInterface();
+
+ if (device->verbosity(2)) {
+ std::cout << "created scene intersector" << std::endl;
+ accels_print(2);
+ std::cout << "selected scene intersector" << std::endl;
+ intersectors.print(2);
+ }
+
+ setModified(false);
+ }
+
+ void Scene::setBuildQuality(RTCBuildQuality quality_flags_i)
+ {
+ if (quality_flags == quality_flags_i) return;
+ quality_flags = quality_flags_i;
+ flags_modified = true;
+ }
+
+ RTCBuildQuality Scene::getBuildQuality() const {
+ return quality_flags;
+ }
+
+ void Scene::setSceneFlags(RTCSceneFlags scene_flags_i)
+ {
+ if (scene_flags == scene_flags_i) return;
+ scene_flags = scene_flags_i;
+ flags_modified = true;
+ }
+
+ RTCSceneFlags Scene::getSceneFlags() const {
+ return scene_flags;
+ }
+
+#if defined(TASKING_INTERNAL)
+
+ void Scene::commit (bool join)
+ {
+ Lock<MutexSys> buildLock(buildMutex,false);
+
+ /* allocates own taskscheduler for each build */
+ Ref<TaskScheduler> scheduler = nullptr;
+ {
+ Lock<MutexSys> lock(schedulerMutex);
+ scheduler = this->scheduler;
+ if (scheduler == null) {
+ buildLock.lock();
+ this->scheduler = scheduler = new TaskScheduler;
+ }
+ }
+
+ /* worker threads join build */
+ if (!buildLock.isLocked())
+ {
+ if (!join)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"use rtcJoinCommitScene to join a build operation");
+
+ scheduler->join();
+ return;
+ }
+
+ /* initiate build */
+ // -- GODOT start --
+ // try {
+ scheduler->spawn_root([&]() { commit_task(); Lock<MutexSys> lock(schedulerMutex); this->scheduler = nullptr; }, 1, !join);
+ // }
+ // catch (...) {
+ // accels_clear();
+ // updateInterface();
+ // Lock<MutexSys> lock(schedulerMutex);
+ // this->scheduler = nullptr;
+ // throw;
+ // }
+ // -- GODOT end --
+ }
+
+#endif
+
+#if defined(TASKING_TBB)
+
+ void Scene::commit (bool join)
+ {
+#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)
+ if (join)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with this TBB version");
+#endif
+
+ /* try to obtain build lock */
+ Lock<MutexSys> lock(buildMutex,buildMutex.try_lock());
+
+ /* join hierarchy build */
+ if (!lock.isLocked())
+ {
+#if !TASKING_TBB_USE_TASK_ISOLATION
+ if (!join)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invoking rtcCommitScene from multiple threads is not supported with this TBB version");
+#endif
+
+ do {
+
+#if USE_TASK_ARENA
+ if (join) {
+ device->arena->execute([&]{ group.wait(); });
+ }
+ else
+#endif
+ {
+ group.wait();
+ }
+
+ pause_cpu();
+ yield();
+ } while (!buildMutex.try_lock());
+
+ buildMutex.unlock();
+ return;
+ }
+
+ /* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
+ const unsigned int mxcsr = _mm_getcsr();
+ _mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
+
+ try {
+#if TBB_INTERFACE_VERSION_MAJOR < 8
+ tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits);
+#else
+ tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits | tbb::task_group_context::fp_settings );
+#endif
+ //ctx.set_priority(tbb::priority_high);
+
+#if USE_TASK_ARENA
+ if (join)
+ {
+ device->arena->execute([&]{
+ group.run([&]{
+ tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
+ });
+ group.wait();
+ });
+ }
+ else
+#endif
+ {
+ group.run([&]{
+ tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
+ });
+ group.wait();
+ }
+
+ /* reset MXCSR register again */
+ _mm_setcsr(mxcsr);
+ }
+ catch (...)
+ {
+ /* reset MXCSR register again */
+ _mm_setcsr(mxcsr);
+
+ accels_clear();
+ updateInterface();
+ throw;
+ }
+ }
+#endif
+
+#if defined(TASKING_PPL)
+
+ void Scene::commit (bool join)
+ {
+#if defined(TASKING_PPL)
+ if (join)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with PPL");
+#endif
+
+ /* try to obtain build lock */
+ Lock<MutexSys> lock(buildMutex);
+
+ checkIfModifiedAndSet ();
+ if (!isModified()) {
+ return;
+ }
+
+ /* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
+ const unsigned int mxcsr = _mm_getcsr();
+ _mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
+
+ try {
+
+ group.run([&]{
+ concurrency::parallel_for(size_t(0), size_t(1), size_t(1), [&](size_t) { commit_task(); });
+ });
+ group.wait();
+
+ /* reset MXCSR register again */
+ _mm_setcsr(mxcsr);
+ }
+ catch (...)
+ {
+ /* reset MXCSR register again */
+ _mm_setcsr(mxcsr);
+
+ accels_clear();
+ updateInterface();
+ throw;
+ }
+ }
+#endif
+
+ void Scene::setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr)
+ {
+ progress_monitor_function = func;
+ progress_monitor_ptr = ptr;
+ }
+
+ void Scene::progressMonitor(double dn)
+ {
+ if (progress_monitor_function) {
+ size_t n = size_t(dn) + progress_monitor_counter.fetch_add(size_t(dn));
+ if (!progress_monitor_function(progress_monitor_ptr, n / (double(numPrimitives())))) {
+ throw_RTCError(RTC_ERROR_CANCELLED,"progress monitor forced termination");
+ }
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/common/scene.h b/thirdparty/embree/kernels/common/scene.h
new file mode 100644
index 0000000000..5ed80a63f6
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene.h
@@ -0,0 +1,390 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "device.h"
+#include "builder.h"
+#include "../../common/algorithms/parallel_any_of.h"
+#include "scene_triangle_mesh.h"
+#include "scene_quad_mesh.h"
+#include "scene_user_geometry.h"
+#include "scene_instance.h"
+#include "scene_curves.h"
+#include "scene_line_segments.h"
+#include "scene_subdiv_mesh.h"
+#include "scene_grid_mesh.h"
+#include "scene_points.h"
+#include "../subdiv/tessellation_cache.h"
+
+#include "acceln.h"
+#include "geometry.h"
+
+namespace embree
+{
+ /*! Base class all scenes are derived from */
+ class Scene : public AccelN
+ {
+ ALIGNED_CLASS_(std::alignment_of<Scene>::value);
+
+ public:
+ template<typename Ty, bool mblur = false>
+ class Iterator
+ {
+ public:
+ Iterator () {}
+
+ Iterator (Scene* scene, bool all = false)
+ : scene(scene), all(all) {}
+
+ __forceinline Ty* at(const size_t i)
+ {
+ Geometry* geom = scene->geometries[i].ptr;
+ if (geom == nullptr) return nullptr;
+ if (!all && !geom->isEnabled()) return nullptr;
+ const size_t mask = geom->getTypeMask() & Ty::geom_type;
+ if (!(mask)) return nullptr;
+ if ((geom->numTimeSteps != 1) != mblur) return nullptr;
+ return (Ty*) geom;
+ }
+
+ __forceinline Ty* operator[] (const size_t i) {
+ return at(i);
+ }
+
+ __forceinline size_t size() const {
+ return scene->size();
+ }
+
+ __forceinline size_t numPrimitives() const {
+ return scene->getNumPrimitives(Ty::geom_type,mblur);
+ }
+
+ __forceinline size_t maxPrimitivesPerGeometry()
+ {
+ size_t ret = 0;
+ for (size_t i=0; i<scene->size(); i++) {
+ Ty* mesh = at(i);
+ if (mesh == nullptr) continue;
+ ret = max(ret,mesh->size());
+ }
+ return ret;
+ }
+
+ __forceinline unsigned int maxGeomID()
+ {
+ unsigned int ret = 0;
+ for (size_t i=0; i<scene->size(); i++) {
+ Ty* mesh = at(i);
+ if (mesh == nullptr) continue;
+ ret = max(ret,(unsigned int)i);
+ }
+ return ret;
+ }
+
+ __forceinline unsigned maxTimeStepsPerGeometry()
+ {
+ unsigned ret = 0;
+ for (size_t i=0; i<scene->size(); i++) {
+ Ty* mesh = at(i);
+ if (mesh == nullptr) continue;
+ ret = max(ret,mesh->numTimeSteps);
+ }
+ return ret;
+ }
+
+ private:
+ Scene* scene;
+ bool all;
+ };
+
+ class Iterator2
+ {
+ public:
+ Iterator2 () {}
+
+ Iterator2 (Scene* scene, Geometry::GTypeMask typemask, bool mblur)
+ : scene(scene), typemask(typemask), mblur(mblur) {}
+
+ __forceinline Geometry* at(const size_t i)
+ {
+ Geometry* geom = scene->geometries[i].ptr;
+ if (geom == nullptr) return nullptr;
+ if (!geom->isEnabled()) return nullptr;
+ if (!(geom->getTypeMask() & typemask)) return nullptr;
+ if ((geom->numTimeSteps != 1) != mblur) return nullptr;
+ return geom;
+ }
+
+ __forceinline Geometry* operator[] (const size_t i) {
+ return at(i);
+ }
+
+ __forceinline size_t size() const {
+ return scene->size();
+ }
+
+ private:
+ Scene* scene;
+ Geometry::GTypeMask typemask;
+ bool mblur;
+ };
+
+ public:
+
+ /*! Scene construction */
+ Scene (Device* device);
+
+ /*! Scene destruction */
+ ~Scene () noexcept;
+
+ private:
+ /*! class is non-copyable */
+ Scene (const Scene& other) DELETED; // do not implement
+ Scene& operator= (const Scene& other) DELETED; // do not implement
+
+ public:
+ void createTriangleAccel();
+ void createTriangleMBAccel();
+ void createQuadAccel();
+ void createQuadMBAccel();
+ void createHairAccel();
+ void createHairMBAccel();
+ void createSubdivAccel();
+ void createSubdivMBAccel();
+ void createUserGeometryAccel();
+ void createUserGeometryMBAccel();
+ void createInstanceAccel();
+ void createInstanceMBAccel();
+ void createInstanceExpensiveAccel();
+ void createInstanceExpensiveMBAccel();
+ void createGridAccel();
+ void createGridMBAccel();
+
+ /*! prints statistics about the scene */
+ void printStatistics();
+
+ /*! clears the scene */
+ void clear();
+
+ /*! detaches some geometry */
+ void detachGeometry(size_t geomID);
+
+ void setBuildQuality(RTCBuildQuality quality_flags);
+ RTCBuildQuality getBuildQuality() const;
+
+ void setSceneFlags(RTCSceneFlags scene_flags);
+ RTCSceneFlags getSceneFlags() const;
+
+ void commit (bool join);
+ void commit_task ();
+ void build () {}
+
+ void updateInterface();
+
+ /* return number of geometries */
+ __forceinline size_t size() const { return geometries.size(); }
+
+ /* bind geometry to the scene */
+ unsigned int bind (unsigned geomID, Ref<Geometry> geometry);
+
+ /* determines if scene is modified */
+ __forceinline bool isModified() const { return modified; }
+
+ /* sets modified flag */
+ __forceinline void setModified(bool f = true) {
+ modified = f;
+ }
+
+ __forceinline bool isGeometryModified(size_t geomID)
+ {
+ Ref<Geometry>& g = geometries[geomID];
+ if (!g) return false;
+ return g->getModCounter() > geometryModCounters_[geomID];
+ }
+
+ protected:
+
+ __forceinline void checkIfModifiedAndSet ()
+ {
+ if (isModified ()) return;
+
+ auto geometryIsModified = [this](size_t geomID)->bool {
+ return isGeometryModified(geomID);
+ };
+
+ if (parallel_any_of (size_t(0), geometries.size (), geometryIsModified)) {
+ setModified ();
+ }
+ }
+
+ public:
+
+ /* get mesh by ID */
+ __forceinline Geometry* get(size_t i) { assert(i < geometries.size()); return geometries[i].ptr; }
+ __forceinline const Geometry* get(size_t i) const { assert(i < geometries.size()); return geometries[i].ptr; }
+
+ template<typename Mesh>
+ __forceinline Mesh* get(size_t i) {
+ assert(i < geometries.size());
+ assert(geometries[i]->getTypeMask() & Mesh::geom_type);
+ return (Mesh*)geometries[i].ptr;
+ }
+ template<typename Mesh>
+ __forceinline const Mesh* get(size_t i) const {
+ assert(i < geometries.size());
+ assert(geometries[i]->getTypeMask() & Mesh::geom_type);
+ return (Mesh*)geometries[i].ptr;
+ }
+
+ template<typename Mesh>
+ __forceinline Mesh* getSafe(size_t i) {
+ assert(i < geometries.size());
+ if (geometries[i] == null) return nullptr;
+ if (!(geometries[i]->getTypeMask() & Mesh::geom_type)) return nullptr;
+ else return (Mesh*) geometries[i].ptr;
+ }
+
+ __forceinline Ref<Geometry> get_locked(size_t i) {
+ Lock<SpinLock> lock(geometriesMutex);
+ assert(i < geometries.size());
+ return geometries[i];
+ }
+
+ /* flag decoding */
+ __forceinline bool isFastAccel() const { return !isCompactAccel() && !isRobustAccel(); }
+ __forceinline bool isCompactAccel() const { return scene_flags & RTC_SCENE_FLAG_COMPACT; }
+ __forceinline bool isRobustAccel() const { return scene_flags & RTC_SCENE_FLAG_ROBUST; }
+ __forceinline bool isStaticAccel() const { return !(scene_flags & RTC_SCENE_FLAG_DYNAMIC); }
+ __forceinline bool isDynamicAccel() const { return scene_flags & RTC_SCENE_FLAG_DYNAMIC; }
+
+ __forceinline bool hasContextFilterFunction() const {
+ return scene_flags & RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION;
+ }
+
+ __forceinline bool hasGeometryFilterFunction() {
+ return world.numFilterFunctions != 0;
+ }
+
+ __forceinline bool hasFilterFunction() {
+ return hasContextFilterFunction() || hasGeometryFilterFunction();
+ }
+
+ /* test if scene got already build */
+ __forceinline bool isBuild() const { return is_build; }
+
+ public:
+ IDPool<unsigned,0xFFFFFFFE> id_pool;
+ vector<Ref<Geometry>> geometries; //!< list of all user geometries
+ vector<unsigned int> geometryModCounters_;
+ vector<float*> vertices;
+
+ public:
+ Device* device;
+
+ /* these are to detect if we need to recreate the acceleration structures */
+ bool flags_modified;
+ unsigned int enabled_geometry_types;
+
+ RTCSceneFlags scene_flags;
+ RTCBuildQuality quality_flags;
+ MutexSys buildMutex;
+ SpinLock geometriesMutex;
+ bool is_build;
+ private:
+ bool modified; //!< true if scene got modified
+
+ public:
+
+ /*! global lock step task scheduler */
+#if defined(TASKING_INTERNAL)
+ MutexSys schedulerMutex;
+ Ref<TaskScheduler> scheduler;
+#elif defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION
+ tbb::isolated_task_group group;
+#elif defined(TASKING_TBB)
+ tbb::task_group group;
+#elif defined(TASKING_PPL)
+ concurrency::task_group group;
+#endif
+
+ public:
+ struct BuildProgressMonitorInterface : public BuildProgressMonitor {
+ BuildProgressMonitorInterface(Scene* scene)
+ : scene(scene) {}
+ void operator() (size_t dn) const { scene->progressMonitor(double(dn)); }
+ private:
+ Scene* scene;
+ };
+ BuildProgressMonitorInterface progressInterface;
+ RTCProgressMonitorFunction progress_monitor_function;
+ void* progress_monitor_ptr;
+ std::atomic<size_t> progress_monitor_counter;
+ void progressMonitor(double nprims);
+ void setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr);
+
+ private:
+ GeometryCounts world; //!< counts for geometry
+
+ public:
+
+ __forceinline size_t numPrimitives() const {
+ return world.size();
+ }
+
+ __forceinline size_t getNumPrimitives(Geometry::GTypeMask mask, bool mblur) const
+ {
+ size_t count = 0;
+
+ if (mask & Geometry::MTY_TRIANGLE_MESH)
+ count += mblur ? world.numMBTriangles : world.numTriangles;
+
+ if (mask & Geometry::MTY_QUAD_MESH)
+ count += mblur ? world.numMBQuads : world.numQuads;
+
+ if (mask & Geometry::MTY_CURVE2)
+ count += mblur ? world.numMBLineSegments : world.numLineSegments;
+
+ if (mask & Geometry::MTY_CURVE4)
+ count += mblur ? world.numMBBezierCurves : world.numBezierCurves;
+
+ if (mask & Geometry::MTY_POINTS)
+ count += mblur ? world.numMBPoints : world.numPoints;
+
+ if (mask & Geometry::MTY_SUBDIV_MESH)
+ count += mblur ? world.numMBSubdivPatches : world.numSubdivPatches;
+
+ if (mask & Geometry::MTY_USER_GEOMETRY)
+ count += mblur ? world.numMBUserGeometries : world.numUserGeometries;
+
+ if (mask & Geometry::MTY_INSTANCE_CHEAP)
+ count += mblur ? world.numMBInstancesCheap : world.numInstancesCheap;
+
+ if (mask & Geometry::MTY_INSTANCE_EXPENSIVE)
+ count += mblur ? world.numMBInstancesExpensive : world.numInstancesExpensive;
+
+ if (mask & Geometry::MTY_GRID_MESH)
+ count += mblur ? world.numMBGrids : world.numGrids;
+
+ return count;
+ }
+
+ template<typename Mesh, bool mblur>
+ __forceinline unsigned getNumTimeSteps()
+ {
+ if (!mblur)
+ return 1;
+
+ Scene::Iterator<Mesh,mblur> iter(this);
+ return iter.maxTimeStepsPerGeometry();
+ }
+
+ template<typename Mesh, bool mblur>
+ __forceinline unsigned int getMaxGeomID()
+ {
+ Scene::Iterator<Mesh,mblur> iter(this);
+ return iter.maxGeomID();
+ }
+ };
+}
diff --git a/thirdparty/embree/kernels/common/scene_curves.h b/thirdparty/embree/kernels/common/scene_curves.h
new file mode 100644
index 0000000000..a5a39e42d4
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_curves.h
@@ -0,0 +1,688 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "geometry.h"
+#include "buffer.h"
+
+#include "../subdiv/bezier_curve.h"
+#include "../subdiv/hermite_curve.h"
+#include "../subdiv/bspline_curve.h"
+#include "../subdiv/catmullrom_curve.h"
+#include "../subdiv/linear_bezier_patch.h"
+
+namespace embree
+{
+ /*! represents an array of bicubic bezier curves */
+ struct CurveGeometry : public Geometry
+ {
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_CURVE4;
+
+ public:
+
+ /*! bezier curve construction */
+ CurveGeometry (Device* device, Geometry::GType gtype);
+
+ public:
+ void setMask(unsigned mask);
+ void setNumTimeSteps (unsigned int numTimeSteps);
+ void setVertexAttributeCount (unsigned int N);
+ void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
+ void* getBuffer(RTCBufferType type, unsigned int slot);
+ void updateBuffer(RTCBufferType type, unsigned int slot);
+ void commit();
+ bool verify();
+ void setTessellationRate(float N);
+ void setMaxRadiusScale(float s);
+ void addElementsToCount (GeometryCounts & counts) const;
+
+ public:
+
+ /*! returns the number of vertices */
+ __forceinline size_t numVertices() const {
+ return vertices[0].size();
+ }
+
+ /*! returns the i'th curve */
+ __forceinline const unsigned int& curve(size_t i) const {
+ return curves[i];
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline Vec3ff vertex(size_t i) const {
+ return vertices0[i];
+ }
+
+ /*! returns i'th normal of the first time step */
+ __forceinline Vec3fa normal(size_t i) const {
+ return normals0[i];
+ }
+
+ /*! returns i'th tangent of the first time step */
+ __forceinline Vec3ff tangent(size_t i) const {
+ return tangents0[i];
+ }
+
+ /*! returns i'th normal derivative of the first time step */
+ __forceinline Vec3fa dnormal(size_t i) const {
+ return dnormals0[i];
+ }
+
+ /*! returns i'th radius of the first time step */
+ __forceinline float radius(size_t i) const {
+ return vertices0[i].w;
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline Vec3ff vertex(size_t i, size_t itime) const {
+ return vertices[itime][i];
+ }
+
+ /*! returns i'th normal of itime'th timestep */
+ __forceinline Vec3fa normal(size_t i, size_t itime) const {
+ return normals[itime][i];
+ }
+
+ /*! returns i'th tangent of itime'th timestep */
+ __forceinline Vec3ff tangent(size_t i, size_t itime) const {
+ return tangents[itime][i];
+ }
+
+ /*! returns i'th normal derivative of itime'th timestep */
+ __forceinline Vec3fa dnormal(size_t i, size_t itime) const {
+ return dnormals[itime][i];
+ }
+
+ /*! returns i'th radius of itime'th timestep */
+ __forceinline float radius(size_t i, size_t itime) const {
+ return vertices[itime][i].w;
+ }
+
+ /*! gathers the curve starting with i'th vertex */
+ __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i) const
+ {
+ p0 = vertex(i+0);
+ p1 = vertex(i+1);
+ p2 = vertex(i+2);
+ p3 = vertex(i+3);
+ }
+
+ /*! gathers the curve starting with i'th vertex of itime'th timestep */
+ __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, size_t itime) const
+ {
+ p0 = vertex(i+0,itime);
+ p1 = vertex(i+1,itime);
+ p2 = vertex(i+2,itime);
+ p3 = vertex(i+3,itime);
+ }
+
+ /*! gathers the curve starting with i'th vertex */
+ __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i) const
+ {
+ p0 = vertex(i+0);
+ p1 = vertex(i+1);
+ p2 = vertex(i+2);
+ p3 = vertex(i+3);
+ n0 = normal(i+0);
+ n1 = normal(i+1);
+ n2 = normal(i+2);
+ n3 = normal(i+3);
+ }
+
+ /*! gathers the curve starting with i'th vertex of itime'th timestep */
+ __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, size_t itime) const
+ {
+ p0 = vertex(i+0,itime);
+ p1 = vertex(i+1,itime);
+ p2 = vertex(i+2,itime);
+ p3 = vertex(i+3,itime);
+ n0 = normal(i+0,itime);
+ n1 = normal(i+1,itime);
+ n2 = normal(i+2,itime);
+ n3 = normal(i+3,itime);
+ }
+
+ /*! prefetches the curve starting with i'th vertex of itime'th timestep */
+ __forceinline void prefetchL1_vertices(size_t i) const
+ {
+ prefetchL1(vertices0.getPtr(i)+0);
+ prefetchL1(vertices0.getPtr(i)+64);
+ }
+
+ /*! prefetches the curve starting with i'th vertex of itime'th timestep */
+ __forceinline void prefetchL2_vertices(size_t i) const
+ {
+ prefetchL2(vertices0.getPtr(i)+0);
+ prefetchL2(vertices0.getPtr(i)+64);
+ }
+
+ /*! loads curve vertices for specified time */
+ __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, float time) const
+ {
+ float ftime;
+ const size_t itime = timeSegment(time, ftime);
+
+ const float t0 = 1.0f - ftime;
+ const float t1 = ftime;
+ Vec3ff a0,a1,a2,a3;
+ gather(a0,a1,a2,a3,i,itime);
+ Vec3ff b0,b1,b2,b3;
+ gather(b0,b1,b2,b3,i,itime+1);
+ p0 = madd(Vec3ff(t0),a0,t1*b0);
+ p1 = madd(Vec3ff(t0),a1,t1*b1);
+ p2 = madd(Vec3ff(t0),a2,t1*b2);
+ p3 = madd(Vec3ff(t0),a3,t1*b3);
+ }
+
+ /*! loads curve vertices for specified time */
+ __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, float time) const
+ {
+ float ftime;
+ const size_t itime = timeSegment(time, ftime);
+
+ const float t0 = 1.0f - ftime;
+ const float t1 = ftime;
+ Vec3ff a0,a1,a2,a3; Vec3fa an0,an1,an2,an3;
+ gather(a0,a1,a2,a3,an0,an1,an2,an3,i,itime);
+ Vec3ff b0,b1,b2,b3; Vec3fa bn0,bn1,bn2,bn3;
+ gather(b0,b1,b2,b3,bn0,bn1,bn2,bn3,i,itime+1);
+ p0 = madd(Vec3ff(t0),a0,t1*b0);
+ p1 = madd(Vec3ff(t0),a1,t1*b1);
+ p2 = madd(Vec3ff(t0),a2,t1*b2);
+ p3 = madd(Vec3ff(t0),a3,t1*b3);
+ n0 = madd(Vec3ff(t0),an0,t1*bn0);
+ n1 = madd(Vec3ff(t0),an1,t1*bn1);
+ n2 = madd(Vec3ff(t0),an2,t1*bn2);
+ n3 = madd(Vec3ff(t0),an3,t1*bn3);
+ }
+
+ template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
+ __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const
+ {
+ Vec3ff v0,v1,v2,v3; Vec3fa n0,n1,n2,n3;
+ unsigned int vertexID = curve(primID);
+ gather(v0,v1,v2,v3,n0,n1,n2,n3,vertexID,itime);
+ SourceCurve3ff ccurve(v0,v1,v2,v3);
+ SourceCurve3fa ncurve(n0,n1,n2,n3);
+ ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);
+ return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
+ }
+
+ template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
+ __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
+ {
+ float ftime;
+ const size_t itime = timeSegment(time, ftime);
+ const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+0);
+ const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+1);
+ return clerp(curve0,curve1,ftime);
+ }
+
+ /*! gathers the hermite curve starting with i'th vertex */
+ __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i) const
+ {
+ p0 = vertex (i+0);
+ p1 = vertex (i+1);
+ t0 = tangent(i+0);
+ t1 = tangent(i+1);
+ }
+
+ /*! gathers the hermite curve starting with i'th vertex of itime'th timestep */
+ __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, size_t itime) const
+ {
+ p0 = vertex (i+0,itime);
+ p1 = vertex (i+1,itime);
+ t0 = tangent(i+0,itime);
+ t1 = tangent(i+1,itime);
+ }
+
+ /*! loads curve vertices for specified time */
+ __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, float time) const
+ {
+ float ftime;
+ const size_t itime = timeSegment(time, ftime);
+ const float f0 = 1.0f - ftime, f1 = ftime;
+ Vec3ff ap0,at0,ap1,at1;
+ gather_hermite(ap0,at0,ap1,at1,i,itime);
+ Vec3ff bp0,bt0,bp1,bt1;
+ gather_hermite(bp0,bt0,bp1,bt1,i,itime+1);
+ p0 = madd(Vec3ff(f0),ap0,f1*bp0);
+ t0 = madd(Vec3ff(f0),at0,f1*bt0);
+ p1 = madd(Vec3ff(f0),ap1,f1*bp1);
+ t1 = madd(Vec3ff(f0),at1,f1*bt1);
+ }
+
+ /*! gathers the hermite curve starting with i'th vertex */
+ __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i) const
+ {
+ p0 = vertex (i+0);
+ p1 = vertex (i+1);
+ t0 = tangent(i+0);
+ t1 = tangent(i+1);
+ n0 = normal(i+0);
+ n1 = normal(i+1);
+ dn0 = dnormal(i+0);
+ dn1 = dnormal(i+1);
+ }
+
+ /*! gathers the hermite curve starting with i'th vertex of itime'th timestep */
+ __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, size_t itime) const
+ {
+ p0 = vertex (i+0,itime);
+ p1 = vertex (i+1,itime);
+ t0 = tangent(i+0,itime);
+ t1 = tangent(i+1,itime);
+ n0 = normal(i+0,itime);
+ n1 = normal(i+1,itime);
+ dn0 = dnormal(i+0,itime);
+ dn1 = dnormal(i+1,itime);
+ }
+
+ /*! loads curve vertices for specified time */
+ __forceinline void gather_hermite(Vec3ff& p0, Vec3fa& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3fa& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, float time) const
+ {
+ float ftime;
+ const size_t itime = timeSegment(time, ftime);
+ const float f0 = 1.0f - ftime, f1 = ftime;
+ Vec3ff ap0,at0,ap1,at1; Vec3fa an0,adn0,an1,adn1;
+ gather_hermite(ap0,at0,an0,adn0,ap1,at1,an1,adn1,i,itime);
+ Vec3ff bp0,bt0,bp1,bt1; Vec3fa bn0,bdn0,bn1,bdn1;
+ gather_hermite(bp0,bt0,bn0,bdn0,bp1,bt1,bn1,bdn1,i,itime+1);
+ p0 = madd(Vec3ff(f0),ap0,f1*bp0);
+ t0 = madd(Vec3ff(f0),at0,f1*bt0);
+ n0 = madd(Vec3ff(f0),an0,f1*bn0);
+ dn0= madd(Vec3ff(f0),adn0,f1*bdn0);
+ p1 = madd(Vec3ff(f0),ap1,f1*bp1);
+ t1 = madd(Vec3ff(f0),at1,f1*bt1);
+ n1 = madd(Vec3ff(f0),an1,f1*bn1);
+ dn1= madd(Vec3ff(f0),adn1,f1*bdn1);
+ }
+
+ template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
+ __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const
+ {
+ Vec3ff v0,t0,v1,t1; Vec3fa n0,dn0,n1,dn1;
+ unsigned int vertexID = curve(primID);
+ gather_hermite(v0,t0,n0,dn0,v1,t1,n1,dn1,vertexID,itime);
+
+ SourceCurve3ff ccurve(v0,t0,v1,t1);
+ SourceCurve3fa ncurve(n0,dn0,n1,dn1);
+ ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);
+ return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
+ }
+
+ template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
+ __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
+ {
+ float ftime;
+ const size_t itime = timeSegment(time, ftime);
+ const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+0);
+ const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+1);
+ return clerp(curve0,curve1,ftime);
+ }
+
+ private:
+ void resizeBuffers(unsigned int numSteps);
+
+ public:
+ BufferView<unsigned int> curves; //!< array of curve indices
+ BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
+ BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
+ BufferView<Vec3ff> tangents0; //!< fast access to first tangent buffer
+ BufferView<Vec3fa> dnormals0; //!< fast access to first normal derivative buffer
+ vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
+ vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
+ vector<BufferView<Vec3ff>> tangents; //!< tangent array for each timestep
+ vector<BufferView<Vec3fa>> dnormals; //!< normal derivative array for each timestep
+ BufferView<char> flags; //!< start, end flag per segment
+ vector<BufferView<char>> vertexAttribs; //!< user buffers
+ int tessellationRate; //!< tessellation rate for flat curve
+ float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
+ };
+
+ namespace isa
+ {
+
+ template<template<typename Ty> class Curve>
+ struct CurveGeometryInterface : public CurveGeometry
+ {
+ typedef Curve<Vec3ff> Curve3ff;
+ typedef Curve<Vec3fa> Curve3fa;
+
+ CurveGeometryInterface (Device* device, Geometry::GType gtype)
+ : CurveGeometry(device,gtype) {}
+
+ __forceinline const Curve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const
+ {
+ const unsigned int index = curve(i);
+ Vec3ff v0 = vertex(index+0,itime);
+ Vec3ff v1 = vertex(index+1,itime);
+ Vec3ff v2 = vertex(index+2,itime);
+ Vec3ff v3 = vertex(index+3,itime);
+ v0.w *= maxRadiusScale;
+ v1.w *= maxRadiusScale;
+ v2.w *= maxRadiusScale;
+ v3.w *= maxRadiusScale;
+ return Curve3ff (v0,v1,v2,v3);
+ }
+
+ __forceinline const Curve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const
+ {
+ const unsigned int index = curve(i);
+ const Vec3ff v0 = vertex(index+0,itime);
+ const Vec3ff v1 = vertex(index+1,itime);
+ const Vec3ff v2 = vertex(index+2,itime);
+ const Vec3ff v3 = vertex(index+3,itime);
+ const Vec3ff w0(xfmPoint(space,(Vec3fa)v0), maxRadiusScale*v0.w);
+ const Vec3ff w1(xfmPoint(space,(Vec3fa)v1), maxRadiusScale*v1.w);
+ const Vec3ff w2(xfmPoint(space,(Vec3fa)v2), maxRadiusScale*v2.w);
+ const Vec3ff w3(xfmPoint(space,(Vec3fa)v3), maxRadiusScale*v3.w);
+ return Curve3ff(w0,w1,w2,w3);
+ }
+
+ __forceinline const Curve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const
+ {
+ const float r_scale = r_scale0*scale;
+ const unsigned int index = curve(i);
+ const Vec3ff v0 = vertex(index+0,itime);
+ const Vec3ff v1 = vertex(index+1,itime);
+ const Vec3ff v2 = vertex(index+2,itime);
+ const Vec3ff v3 = vertex(index+3,itime);
+ const Vec3ff w0(xfmPoint(space,((Vec3fa)v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale);
+ const Vec3ff w1(xfmPoint(space,((Vec3fa)v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale);
+ const Vec3ff w2(xfmPoint(space,((Vec3fa)v2-ofs)*Vec3fa(scale)), maxRadiusScale*v2.w*r_scale);
+ const Vec3ff w3(xfmPoint(space,((Vec3fa)v3-ofs)*Vec3fa(scale)), maxRadiusScale*v3.w*r_scale);
+ return Curve3ff(w0,w1,w2,w3);
+ }
+
+ __forceinline const Curve3fa getNormalCurve(size_t i, size_t itime = 0) const
+ {
+ const unsigned int index = curve(i);
+ const Vec3fa n0 = normal(index+0,itime);
+ const Vec3fa n1 = normal(index+1,itime);
+ const Vec3fa n2 = normal(index+2,itime);
+ const Vec3fa n3 = normal(index+3,itime);
+ return Curve3fa (n0,n1,n2,n3);
+ }
+
+ __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const
+ {
+ const Curve3ff center = getCurveScaledRadius(i,itime);
+ const Curve3fa normal = getNormalCurve(i,itime);
+ const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal);
+ return ocurve;
+ }
+
+ __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
+ return getOrientedCurveScaledRadius(i,itime).xfm(space);
+ }
+
+ __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
+ return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale);
+ }
+
+ /*! check if the i'th primitive is valid at the itime'th time step */
+ __forceinline bool valid(Geometry::GType ctype, size_t i, const range<size_t>& itime_range) const
+ {
+ const unsigned int index = curve(i);
+ if (index+3 >= numVertices()) return false;
+
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
+ {
+ const float r0 = radius(index+0,itime);
+ const float r1 = radius(index+1,itime);
+ const float r2 = radius(index+2,itime);
+ const float r3 = radius(index+3,itime);
+ if (!isvalid(r0) || !isvalid(r1) || !isvalid(r2) || !isvalid(r3))
+ return false;
+
+ const Vec3fa v0 = vertex(index+0,itime);
+ const Vec3fa v1 = vertex(index+1,itime);
+ const Vec3fa v2 = vertex(index+2,itime);
+ const Vec3fa v3 = vertex(index+3,itime);
+ if (!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3))
+ return false;
+
+ if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)
+ {
+ const Vec3fa n0 = normal(index+0,itime);
+ const Vec3fa n1 = normal(index+1,itime);
+ if (!isvalid(n0) || !isvalid(n1))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ template<int N>
+ void interpolate_impl(const RTCInterpolateArguments* const args)
+ {
+ unsigned int primID = args->primID;
+ float u = args->u;
+ RTCBufferType bufferType = args->bufferType;
+ unsigned int bufferSlot = args->bufferSlot;
+ float* P = args->P;
+ float* dPdu = args->dPdu;
+ float* ddPdudu = args->ddPdudu;
+ unsigned int valueCount = args->valueCount;
+
+ /* calculate base pointer and stride */
+ assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
+ (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
+ const char* src = nullptr;
+ size_t stride = 0;
+ if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
+ src = vertexAttribs[bufferSlot].getPtr();
+ stride = vertexAttribs[bufferSlot].getStride();
+ } else {
+ src = vertices[bufferSlot].getPtr();
+ stride = vertices[bufferSlot].getStride();
+ }
+
+ for (unsigned int i=0; i<valueCount; i+=N)
+ {
+ size_t ofs = i*sizeof(float);
+ const size_t index = curves[primID];
+ const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
+ const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+0)*stride+ofs]);
+ const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+1)*stride+ofs]);
+ const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+2)*stride+ofs]);
+ const vfloat<N> p3 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+3)*stride+ofs]);
+
+ const Curve<vfloat<N>> curve(p0,p1,p2,p3);
+ if (P ) mem<vfloat<N>>::storeu(valid,P+i, curve.eval(u));
+ if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, curve.eval_du(u));
+ if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,curve.eval_dudu(u));
+ }
+ }
+
+ void interpolate(const RTCInterpolateArguments* const args) {
+ interpolate_impl<4>(args);
+ }
+ };
+
+ template<template<typename Ty> class Curve>
+ struct HermiteCurveGeometryInterface : public CurveGeometry
+ {
+ typedef Curve<Vec3ff> HermiteCurve3ff;
+ typedef Curve<Vec3fa> HermiteCurve3fa;
+
+ HermiteCurveGeometryInterface (Device* device, Geometry::GType gtype)
+ : CurveGeometry(device,gtype) {}
+
+ __forceinline const HermiteCurve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const
+ {
+ const unsigned int index = curve(i);
+ Vec3ff v0 = vertex(index+0,itime);
+ Vec3ff v1 = vertex(index+1,itime);
+ Vec3ff t0 = tangent(index+0,itime);
+ Vec3ff t1 = tangent(index+1,itime);
+ v0.w *= maxRadiusScale;
+ v1.w *= maxRadiusScale;
+ t0.w *= maxRadiusScale;
+ t1.w *= maxRadiusScale;
+ return HermiteCurve3ff (v0,t0,v1,t1);
+ }
+
+ __forceinline const HermiteCurve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const
+ {
+ const unsigned int index = curve(i);
+ const Vec3ff v0 = vertex(index+0,itime);
+ const Vec3ff v1 = vertex(index+1,itime);
+ const Vec3ff t0 = tangent(index+0,itime);
+ const Vec3ff t1 = tangent(index+1,itime);
+ const Vec3ff V0(xfmPoint(space,(Vec3fa)v0),maxRadiusScale*v0.w);
+ const Vec3ff V1(xfmPoint(space,(Vec3fa)v1),maxRadiusScale*v1.w);
+ const Vec3ff T0(xfmVector(space,(Vec3fa)t0),maxRadiusScale*t0.w);
+ const Vec3ff T1(xfmVector(space,(Vec3fa)t1),maxRadiusScale*t1.w);
+ return HermiteCurve3ff(V0,T0,V1,T1);
+ }
+
+ __forceinline const HermiteCurve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const
+ {
+ const float r_scale = r_scale0*scale;
+ const unsigned int index = curve(i);
+ const Vec3ff v0 = vertex(index+0,itime);
+ const Vec3ff v1 = vertex(index+1,itime);
+ const Vec3ff t0 = tangent(index+0,itime);
+ const Vec3ff t1 = tangent(index+1,itime);
+ const Vec3ff V0(xfmPoint(space,(v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale);
+ const Vec3ff V1(xfmPoint(space,(v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale);
+ const Vec3ff T0(xfmVector(space,t0*Vec3fa(scale)), maxRadiusScale*t0.w*r_scale);
+ const Vec3ff T1(xfmVector(space,t1*Vec3fa(scale)), maxRadiusScale*t1.w*r_scale);
+ return HermiteCurve3ff(V0,T0,V1,T1);
+ }
+
+ __forceinline const HermiteCurve3fa getNormalCurve(size_t i, size_t itime = 0) const
+ {
+ const unsigned int index = curve(i);
+ const Vec3fa n0 = normal(index+0,itime);
+ const Vec3fa n1 = normal(index+1,itime);
+ const Vec3fa dn0 = dnormal(index+0,itime);
+ const Vec3fa dn1 = dnormal(index+1,itime);
+ return HermiteCurve3fa (n0,dn0,n1,dn1);
+ }
+
+ __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const
+ {
+ const HermiteCurve3ff center = getCurveScaledRadius(i,itime);
+ const HermiteCurve3fa normal = getNormalCurve(i,itime);
+ const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal);
+ return ocurve;
+ }
+
+ __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
+ return getOrientedCurveScaledRadius(i,itime).xfm(space);
+ }
+
+ __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
+ return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale);
+ }
+
+ /*! check if the i'th primitive is valid at the itime'th time step */
+ __forceinline bool valid(Geometry::GType ctype, size_t i, const range<size_t>& itime_range) const
+ {
+ const unsigned int index = curve(i);
+ if (index+1 >= numVertices()) return false;
+
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
+ {
+ const Vec3ff v0 = vertex(index+0,itime);
+ const Vec3ff v1 = vertex(index+1,itime);
+ if (!isvalid4(v0) || !isvalid4(v1))
+ return false;
+
+ const Vec3ff t0 = tangent(index+0,itime);
+ const Vec3ff t1 = tangent(index+1,itime);
+ if (!isvalid4(t0) || !isvalid4(t1))
+ return false;
+
+ if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)
+ {
+ const Vec3fa n0 = normal(index+0,itime);
+ const Vec3fa n1 = normal(index+1,itime);
+ if (!isvalid(n0) || !isvalid(n1))
+ return false;
+
+ const Vec3fa dn0 = dnormal(index+0,itime);
+ const Vec3fa dn1 = dnormal(index+1,itime);
+ if (!isvalid(dn0) || !isvalid(dn1))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ template<int N>
+ void interpolate_impl(const RTCInterpolateArguments* const args)
+ {
+ unsigned int primID = args->primID;
+ float u = args->u;
+ RTCBufferType bufferType = args->bufferType;
+ unsigned int bufferSlot = args->bufferSlot;
+ float* P = args->P;
+ float* dPdu = args->dPdu;
+ float* ddPdudu = args->ddPdudu;
+ unsigned int valueCount = args->valueCount;
+
+ /* we interpolate vertex attributes linearly for hermite basis */
+ if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
+ {
+ assert(bufferSlot <= vertexAttribs.size());
+ const char* vsrc = vertexAttribs[bufferSlot].getPtr();
+ const size_t vstride = vertexAttribs[bufferSlot].getStride();
+
+ for (unsigned int i=0; i<valueCount; i+=N)
+ {
+ const size_t ofs = i*sizeof(float);
+ const size_t index = curves[primID];
+ const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
+ const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]);
+ const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]);
+
+ if (P ) mem<vfloat<N>>::storeu(valid,P+i, madd(1.0f-u,p0,u*p1));
+ if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, p1-p0);
+ if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,vfloat<N>(zero));
+ }
+ }
+
+ /* interpolation for vertex buffers */
+ else
+ {
+ assert(bufferSlot < numTimeSteps);
+ const char* vsrc = vertices[bufferSlot].getPtr();
+ const char* tsrc = tangents[bufferSlot].getPtr();
+ const size_t vstride = vertices[bufferSlot].getStride();
+ const size_t tstride = vertices[bufferSlot].getStride();
+
+ for (unsigned int i=0; i<valueCount; i+=N)
+ {
+ const size_t ofs = i*sizeof(float);
+ const size_t index = curves[primID];
+ const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
+ const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]);
+ const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]);
+ const vfloat<N> t0 = mem<vfloat<N>>::loadu(valid,(float*)&tsrc[(index+0)*tstride+ofs]);
+ const vfloat<N> t1 = mem<vfloat<N>>::loadu(valid,(float*)&tsrc[(index+1)*tstride+ofs]);
+
+ const HermiteCurveT<vfloat<N>> curve(p0,t0,p1,t1);
+ if (P ) mem<vfloat<N>>::storeu(valid,P+i, curve.eval(u));
+ if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, curve.eval_du(u));
+ if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,curve.eval_dudu(u));
+ }
+ }
+ }
+
+ void interpolate(const RTCInterpolateArguments* const args) {
+ interpolate_impl<4>(args);
+ }
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(CurveGeometry*, createCurves, Device* COMMA Geometry::GType);
+}
diff --git a/thirdparty/embree/kernels/common/scene_grid_mesh.h b/thirdparty/embree/kernels/common/scene_grid_mesh.h
new file mode 100644
index 0000000000..fb6fed445b
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_grid_mesh.h
@@ -0,0 +1,294 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "geometry.h"
+#include "buffer.h"
+
+namespace embree
+{
+ /*! Grid Mesh */
+ struct GridMesh : public Geometry
+ {
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_GRID_MESH;
+
+ /*! grid */
+ struct Grid
+ {
+ unsigned int startVtxID;
+ unsigned int lineVtxOffset;
+ unsigned short resX,resY;
+
+ /* border flags due to 3x3 vertex pattern */
+ __forceinline unsigned int get3x3FlagsX(const unsigned int x) const
+ {
+ return (x + 2 >= (unsigned int)resX) ? (1<<15) : 0;
+ }
+
+ /* border flags due to 3x3 vertex pattern */
+ __forceinline unsigned int get3x3FlagsY(const unsigned int y) const
+ {
+ return (y + 2 >= (unsigned int)resY) ? (1<<15) : 0;
+ }
+
+ /*! outputs grid structure */
+ __forceinline friend embree_ostream operator<<(embree_ostream cout, const Grid& t) {
+ return cout << "Grid { startVtxID " << t.startVtxID << ", lineVtxOffset " << t.lineVtxOffset << ", resX " << t.resX << ", resY " << t.resY << " }";
+ }
+ };
+
+ public:
+
+ /*! grid mesh construction */
+ GridMesh (Device* device);
+
+ /* geometry interface */
+ public:
+ void setMask(unsigned mask);
+ void setNumTimeSteps (unsigned int numTimeSteps);
+ void setVertexAttributeCount (unsigned int N);
+ void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
+ void* getBuffer(RTCBufferType type, unsigned int slot);
+ void updateBuffer(RTCBufferType type, unsigned int slot);
+ void commit();
+ bool verify();
+ void interpolate(const RTCInterpolateArguments* const args);
+
+ template<int N>
+ void interpolate_impl(const RTCInterpolateArguments* const args)
+ {
+ unsigned int primID = args->primID;
+ float U = args->u;
+ float V = args->v;
+
+ /* clamp input u,v to [0;1] range */
+ U = max(min(U,1.0f),0.0f);
+ V = max(min(V,1.0f),0.0f);
+
+ RTCBufferType bufferType = args->bufferType;
+ unsigned int bufferSlot = args->bufferSlot;
+ float* P = args->P;
+ float* dPdu = args->dPdu;
+ float* dPdv = args->dPdv;
+ float* ddPdudu = args->ddPdudu;
+ float* ddPdvdv = args->ddPdvdv;
+ float* ddPdudv = args->ddPdudv;
+ unsigned int valueCount = args->valueCount;
+
+ /* calculate base pointer and stride */
+ assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
+ (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
+ const char* src = nullptr;
+ size_t stride = 0;
+ if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
+ src = vertexAttribs[bufferSlot].getPtr();
+ stride = vertexAttribs[bufferSlot].getStride();
+ } else {
+ src = vertices[bufferSlot].getPtr();
+ stride = vertices[bufferSlot].getStride();
+ }
+
+ const Grid& grid = grids[primID];
+ const int grid_width = grid.resX-1;
+ const int grid_height = grid.resY-1;
+ const float rcp_grid_width = rcp(float(grid_width));
+ const float rcp_grid_height = rcp(float(grid_height));
+ const int iu = min((int)floor(U*grid_width ),grid_width);
+ const int iv = min((int)floor(V*grid_height),grid_height);
+ const float u = U*grid_width-float(iu);
+ const float v = V*grid_height-float(iv);
+
+ for (unsigned int i=0; i<valueCount; i+=N)
+ {
+ const size_t ofs = i*sizeof(float);
+ const unsigned int idx0 = grid.startVtxID + (iv+0)*grid.lineVtxOffset + iu;
+ const unsigned int idx1 = grid.startVtxID + (iv+1)*grid.lineVtxOffset + iu;
+
+ const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>(int(valueCount));
+ const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[(idx0+0)*stride+ofs]);
+ const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[(idx0+1)*stride+ofs]);
+ const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[(idx1+1)*stride+ofs]);
+ const vfloat<N> p3 = mem<vfloat<N>>::loadu(valid,(float*)&src[(idx1+0)*stride+ofs]);
+ const vbool<N> left = u+v <= 1.0f;
+ const vfloat<N> Q0 = select(left,p0,p2);
+ const vfloat<N> Q1 = select(left,p1,p3);
+ const vfloat<N> Q2 = select(left,p3,p1);
+ const vfloat<N> U = select(left,u,vfloat<N>(1.0f)-u);
+ const vfloat<N> V = select(left,v,vfloat<N>(1.0f)-v);
+ const vfloat<N> W = 1.0f-U-V;
+
+ if (P) {
+ mem<vfloat<N>>::storeu(valid,P+i,madd(W,Q0,madd(U,Q1,V*Q2)));
+ }
+ if (dPdu) {
+ assert(dPdu); mem<vfloat<N>>::storeu(valid,dPdu+i,select(left,Q1-Q0,Q0-Q1)*rcp_grid_width);
+ assert(dPdv); mem<vfloat<N>>::storeu(valid,dPdv+i,select(left,Q2-Q0,Q0-Q2)*rcp_grid_height);
+ }
+ if (ddPdudu) {
+ assert(ddPdudu); mem<vfloat<N>>::storeu(valid,ddPdudu+i,vfloat<N>(zero));
+ assert(ddPdvdv); mem<vfloat<N>>::storeu(valid,ddPdvdv+i,vfloat<N>(zero));
+ assert(ddPdudv); mem<vfloat<N>>::storeu(valid,ddPdudv+i,vfloat<N>(zero));
+ }
+ }
+ }
+
+ void addElementsToCount (GeometryCounts & counts) const;
+
+ __forceinline unsigned int getNumSubGrids(const size_t gridID)
+ {
+ const Grid &g = grid(gridID);
+ return max((unsigned int)1,((unsigned int)g.resX >> 1) * ((unsigned int)g.resY >> 1));
+ }
+
+ /*! get fast access to first vertex buffer */
+ __forceinline float * getCompactVertexArray () const {
+ return (float*) vertices0.getPtr();
+ }
+
+ public:
+
+ /*! returns number of vertices */
+ __forceinline size_t numVertices() const {
+ return vertices[0].size();
+ }
+
+ /*! returns i'th grid*/
+ __forceinline const Grid& grid(size_t i) const {
+ return grids[i];
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline const Vec3fa vertex(size_t i) const { // FIXME: check if this does a unaligned load
+ return vertices0[i];
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline const char* vertexPtr(size_t i) const {
+ return vertices0.getPtr(i);
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const Vec3fa vertex(size_t i, size_t itime) const {
+ return vertices[itime][i];
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const char* vertexPtr(size_t i, size_t itime) const {
+ return vertices[itime].getPtr(i);
+ }
+
+ /*! returns i'th vertex of the first timestep */
+ __forceinline size_t grid_vertex_index(const Grid& g, size_t x, size_t y) const {
+ assert(x < (size_t)g.resX);
+ assert(y < (size_t)g.resY);
+ return g.startVtxID + x + y * g.lineVtxOffset;
+ }
+
+ /*! returns i'th vertex of the first timestep */
+ __forceinline const Vec3fa grid_vertex(const Grid& g, size_t x, size_t y) const {
+ const size_t index = grid_vertex_index(g,x,y);
+ return vertex(index);
+ }
+
+ /*! returns i'th vertex of the itime'th timestep */
+ __forceinline const Vec3fa grid_vertex(const Grid& g, size_t x, size_t y, size_t itime) const {
+ const size_t index = grid_vertex_index(g,x,y);
+ return vertex(index,itime);
+ }
+
+ /*! calculates the build bounds of the i'th primitive, if it's valid */
+ __forceinline bool buildBounds(const Grid& g, size_t sx, size_t sy, BBox3fa& bbox) const
+ {
+ BBox3fa b(empty);
+ for (size_t t=0; t<numTimeSteps; t++)
+ {
+ for (size_t y=sy;y<min(sy+3,(size_t)g.resY);y++)
+ for (size_t x=sx;x<min(sx+3,(size_t)g.resX);x++)
+ {
+ const Vec3fa v = grid_vertex(g,x,y,t);
+ if (unlikely(!isvalid(v))) return false;
+ b.extend(v);
+ }
+ }
+
+ bbox = b;
+ return true;
+ }
+
+ /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
+ __forceinline bool buildBounds(const Grid& g, size_t sx, size_t sy, size_t itime, BBox3fa& bbox) const
+ {
+ assert(itime < numTimeSteps);
+ BBox3fa b0(empty);
+ for (size_t y=sy;y<min(sy+3,(size_t)g.resY);y++)
+ for (size_t x=sx;x<min(sx+3,(size_t)g.resX);x++)
+ {
+ const Vec3fa v = grid_vertex(g,x,y,itime);
+ if (unlikely(!isvalid(v))) return false;
+ b0.extend(v);
+ }
+
+ /* use bounds of first time step in builder */
+ bbox = b0;
+ return true;
+ }
+
+ __forceinline bool valid(size_t gridID, size_t itime=0) const {
+ return valid(gridID, make_range(itime, itime));
+ }
+
+ /*! check if the i'th primitive is valid between the specified time range */
+ __forceinline bool valid(size_t gridID, const range<size_t>& itime_range) const
+ {
+ if (unlikely(gridID >= grids.size())) return false;
+ const Grid &g = grid(gridID);
+ if (unlikely(g.startVtxID + 0 >= vertices0.size())) return false;
+ if (unlikely(g.startVtxID + (g.resY-1)*g.lineVtxOffset + g.resX-1 >= vertices0.size())) return false;
+
+ for (size_t y=0;y<g.resY;y++)
+ for (size_t x=0;x<g.resX;x++)
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
+ if (!isvalid(grid_vertex(g,x,y,itime))) return false;
+ return true;
+ }
+
+
+ __forceinline BBox3fa bounds(const Grid& g, size_t sx, size_t sy, size_t itime) const
+ {
+ BBox3fa box(empty);
+ buildBounds(g,sx,sy,itime,box);
+ return box;
+ }
+
+ __forceinline LBBox3fa linearBounds(const Grid& g, size_t sx, size_t sy, size_t itime) const {
+ BBox3fa bounds0, bounds1;
+ buildBounds(g,sx,sy,itime+0,bounds0);
+ buildBounds(g,sx,sy,itime+1,bounds1);
+ return LBBox3fa(bounds0,bounds1);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(const Grid& g, size_t sx, size_t sy, const BBox1f& dt) const {
+ return LBBox3fa([&] (size_t itime) { return bounds(g,sx,sy,itime); }, dt, time_range, fnumTimeSegments);
+ }
+
+ public:
+ BufferView<Grid> grids; //!< array of triangles
+ BufferView<Vec3fa> vertices0; //!< fast access to first vertex buffer
+ vector<BufferView<Vec3fa>> vertices; //!< vertex array for each timestep
+ vector<RawBufferView> vertexAttribs; //!< vertex attributes
+ };
+
+ namespace isa
+ {
+ struct GridMeshISA : public GridMesh
+ {
+ GridMeshISA (Device* device)
+ : GridMesh(device) {}
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(GridMesh*, createGridMesh, Device*);
+}
diff --git a/thirdparty/embree/kernels/common/scene_instance.h b/thirdparty/embree/kernels/common/scene_instance.h
new file mode 100644
index 0000000000..773f2b6fec
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_instance.h
@@ -0,0 +1,272 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "geometry.h"
+#include "accel.h"
+
+namespace embree
+{
+ struct MotionDerivativeCoefficients;
+
+ /*! Instanced acceleration structure */
+ struct Instance : public Geometry
+ {
+ ALIGNED_STRUCT_(16);
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_INSTANCE;
+
+ public:
+ Instance (Device* device, Accel* object = nullptr, unsigned int numTimeSteps = 1);
+ ~Instance();
+
+ private:
+ Instance (const Instance& other) DELETED; // do not implement
+ Instance& operator= (const Instance& other) DELETED; // do not implement
+
+ private:
+ LBBox3fa nonlinearBounds(const BBox1f& time_range_in,
+ const BBox1f& geom_time_range,
+ float geom_time_segments) const;
+
+ BBox3fa boundSegment(size_t itime,
+ BBox3fa const& obbox0, BBox3fa const& obbox1,
+ BBox3fa const& bbox0, BBox3fa const& bbox1,
+ float t_min, float t_max) const;
+
+ /* calculates the (correct) interpolated bounds */
+ __forceinline BBox3fa bounds(size_t itime0, size_t itime1, float f) const
+ {
+ if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
+ return xfmBounds(slerp(local2world[itime0], local2world[itime1], f),
+ lerp(getObjectBounds(itime0), getObjectBounds(itime1), f));
+ return xfmBounds(lerp(local2world[itime0], local2world[itime1], f),
+ lerp(getObjectBounds(itime0), getObjectBounds(itime1), f));
+ }
+
+ public:
+ virtual void setNumTimeSteps (unsigned int numTimeSteps) override;
+ virtual void setInstancedScene(const Ref<Scene>& scene) override;
+ virtual void setTransform(const AffineSpace3fa& local2world, unsigned int timeStep) override;
+ virtual void setQuaternionDecomposition(const AffineSpace3ff& qd, unsigned int timeStep) override;
+ virtual AffineSpace3fa getTransform(float time) override;
+ virtual void setMask (unsigned mask) override;
+ virtual void build() {}
+ virtual void addElementsToCount (GeometryCounts & counts) const override;
+ virtual void commit() override;
+
+ public:
+
+ /*! calculates the bounds of instance */
+ __forceinline BBox3fa bounds(size_t i) const {
+ assert(i == 0);
+ if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
+ return xfmBounds(quaternionDecompositionToAffineSpace(local2world[0]),object->bounds.bounds());
+ return xfmBounds(local2world[0],object->bounds.bounds());
+ }
+
+ /*! gets the bounds of the instanced scene */
+ __forceinline BBox3fa getObjectBounds(size_t itime) const {
+ return object->getBounds(timeStep(itime));
+ }
+
+ /*! calculates the bounds of instance */
+ __forceinline BBox3fa bounds(size_t i, size_t itime) const {
+ assert(i == 0);
+ if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
+ return xfmBounds(quaternionDecompositionToAffineSpace(local2world[itime]),getObjectBounds(itime));
+ return xfmBounds(local2world[itime],getObjectBounds(itime));
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(size_t i, const BBox1f& dt) const {
+ assert(i == 0);
+ LBBox3fa lbbox = nonlinearBounds(dt, time_range, fnumTimeSegments);
+ return lbbox;
+ }
+
+ /*! calculates the build bounds of the i'th item, if it's valid */
+ __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
+ {
+ assert(i==0);
+ const BBox3fa b = bounds(i);
+ if (bbox) *bbox = b;
+ return isvalid(b);
+ }
+
+ /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
+ __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
+ {
+ assert(i==0);
+ const LBBox3fa bounds = linearBounds(i,itime);
+ bbox = bounds.bounds ();
+ return isvalid(bounds);
+ }
+
+ /* gets version info of topology */
+ unsigned int getTopologyVersion() const {
+ return numPrimitives;
+ }
+
+ /* returns true if topology changed */
+ bool topologyChanged(unsigned int otherVersion) const {
+ return numPrimitives != otherVersion;
+ }
+
+ /*! check if the i'th primitive is valid between the specified time range */
+ __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
+ {
+ assert(i == 0);
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
+ if (!isvalid(bounds(i,itime))) return false;
+
+ return true;
+ }
+
+ __forceinline AffineSpace3fa getLocal2World() const
+ {
+ if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
+ return quaternionDecompositionToAffineSpace(local2world[0]);
+ return local2world[0];
+ }
+
+ __forceinline AffineSpace3fa getLocal2World(float t) const
+ {
+ float ftime; const unsigned int itime = timeSegment(t, ftime);
+ if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
+ return slerp(local2world[itime+0],local2world[itime+1],ftime);
+ return lerp(local2world[itime+0],local2world[itime+1],ftime);
+ }
+
+ __forceinline AffineSpace3fa getWorld2Local() const {
+ return world2local0;
+ }
+
+ __forceinline AffineSpace3fa getWorld2Local(float t) const {
+ return rcp(getLocal2World(t));
+ }
+
+ template<int K>
+ __forceinline AffineSpace3vf<K> getWorld2Local(const vbool<K>& valid, const vfloat<K>& t) const
+ {
+ if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
+ return getWorld2LocalSlerp<K>(valid, t);
+ return getWorld2LocalLerp<K>(valid, t);
+ }
+
+ private:
+
+ template<int K>
+ __forceinline AffineSpace3vf<K> getWorld2LocalSlerp(const vbool<K>& valid, const vfloat<K>& t) const
+ {
+ vfloat<K> ftime;
+ const vint<K> itime_k = timeSegment<K>(t, ftime);
+ assert(any(valid));
+ const size_t index = bsf(movemask(valid));
+ const int itime = itime_k[index];
+ if (likely(all(valid, itime_k == vint<K>(itime)))) {
+ return rcp(slerp(AffineSpace3vff<K>(local2world[itime+0]),
+ AffineSpace3vff<K>(local2world[itime+1]),
+ ftime));
+ }
+ else {
+ AffineSpace3vff<K> space0,space1;
+ vbool<K> valid1 = valid;
+ while (any(valid1)) {
+ vbool<K> valid2;
+ const int itime = next_unique(valid1, itime_k, valid2);
+ space0 = select(valid2, AffineSpace3vff<K>(local2world[itime+0]), space0);
+ space1 = select(valid2, AffineSpace3vff<K>(local2world[itime+1]), space1);
+ }
+ return rcp(slerp(space0, space1, ftime));
+ }
+ }
+
+ template<int K>
+ __forceinline AffineSpace3vf<K> getWorld2LocalLerp(const vbool<K>& valid, const vfloat<K>& t) const
+ {
+ vfloat<K> ftime;
+ const vint<K> itime_k = timeSegment<K>(t, ftime);
+ assert(any(valid));
+ const size_t index = bsf(movemask(valid));
+ const int itime = itime_k[index];
+ if (likely(all(valid, itime_k == vint<K>(itime)))) {
+ return rcp(lerp(AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+0]),
+ AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+1]),
+ ftime));
+ } else {
+ AffineSpace3vf<K> space0,space1;
+ vbool<K> valid1 = valid;
+ while (any(valid1)) {
+ vbool<K> valid2;
+ const int itime = next_unique(valid1, itime_k, valid2);
+ space0 = select(valid2, AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+0]), space0);
+ space1 = select(valid2, AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+1]), space1);
+ }
+ return rcp(lerp(space0, space1, ftime));
+ }
+ }
+
+ public:
+ Accel* object; //!< pointer to instanced acceleration structure
+ AffineSpace3ff* local2world; //!< transformation from local space to world space for each timestep (either normal matrix or quaternion decomposition)
+ AffineSpace3fa world2local0; //!< transformation from world space to local space for timestep 0
+ };
+
+ namespace isa
+ {
+ struct InstanceISA : public Instance
+ {
+ InstanceISA (Device* device)
+ : Instance(device) {}
+
+ PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ assert(r.begin() == 0);
+ assert(r.end() == 1);
+
+ PrimInfo pinfo(empty);
+ BBox3fa b = empty;
+ if (!buildBounds(0,&b)) return pinfo;
+ // const BBox3fa b = bounds(0);
+ // if (!isvalid(b)) return pinfo;
+
+ const PrimRef prim(b,geomID,unsigned(0));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ assert(r.begin() == 0);
+ assert(r.end() == 1);
+
+ PrimInfo pinfo(empty);
+ BBox3fa b = empty;
+ if (!buildBounds(0,&b)) return pinfo;
+ // if (!valid(0,range<size_t>(itime))) return pinfo;
+ // const PrimRef prim(linearBounds(0,itime).bounds(),geomID,unsigned(0));
+ const PrimRef prim(b,geomID,unsigned(0));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ return pinfo;
+ }
+
+ PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ assert(r.begin() == 0);
+ assert(r.end() == 1);
+
+ PrimInfoMB pinfo(empty);
+ if (!valid(0, timeSegmentRange(t0t1))) return pinfo;
+ const PrimRefMB prim(linearBounds(0,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(0));
+ pinfo.add_primref(prim);
+ prims[k++] = prim;
+ return pinfo;
+ }
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(Instance*, createInstance, Device*);
+}
diff --git a/thirdparty/embree/kernels/common/scene_line_segments.h b/thirdparty/embree/kernels/common/scene_line_segments.h
new file mode 100644
index 0000000000..3c9fdb39db
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_line_segments.h
@@ -0,0 +1,345 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+#include "geometry.h"
+#include "buffer.h"
+
+namespace embree
+{
+ /*! represents an array of line segments */
+ struct LineSegments : public Geometry
+ {
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_CURVE2;
+
+ public:
+
+ /*! line segments construction */
+ LineSegments (Device* device, Geometry::GType gtype);
+
+ public:
+ void setMask (unsigned mask);
+ void setNumTimeSteps (unsigned int numTimeSteps);
+ void setVertexAttributeCount (unsigned int N);
+ void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
+ void* getBuffer(RTCBufferType type, unsigned int slot);
+ void updateBuffer(RTCBufferType type, unsigned int slot);
+ void commit();
+ bool verify ();
+ void interpolate(const RTCInterpolateArguments* const args);
+ void setTessellationRate(float N);
+ void setMaxRadiusScale(float s);
+ void addElementsToCount (GeometryCounts & counts) const;
+
+ template<int N>
+ void interpolate_impl(const RTCInterpolateArguments* const args)
+ {
+ unsigned int primID = args->primID;
+ float u = args->u;
+ RTCBufferType bufferType = args->bufferType;
+ unsigned int bufferSlot = args->bufferSlot;
+ float* P = args->P;
+ float* dPdu = args->dPdu;
+ float* ddPdudu = args->ddPdudu;
+ unsigned int valueCount = args->valueCount;
+
+ /* calculate base pointer and stride */
+ assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
+ (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
+ const char* src = nullptr;
+ size_t stride = 0;
+ if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
+ src = vertexAttribs[bufferSlot].getPtr();
+ stride = vertexAttribs[bufferSlot].getStride();
+ } else {
+ src = vertices[bufferSlot].getPtr();
+ stride = vertices[bufferSlot].getStride();
+ }
+
+ for (unsigned int i=0; i<valueCount; i+=N)
+ {
+ const size_t ofs = i*sizeof(float);
+ const size_t segment = segments[primID];
+ const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>(int(valueCount));
+ const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[(segment+0)*stride+ofs]);
+ const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[(segment+1)*stride+ofs]);
+ if (P ) mem<vfloat<N>>::storeu(valid,P+i,lerp(p0,p1,u));
+ if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i,p1-p0);
+ if (ddPdudu) mem<vfloat<N>>::storeu(valid,dPdu+i,vfloat<N>(zero));
+ }
+ }
+
+ public:
+
+ /*! returns the number of vertices */
+ __forceinline size_t numVertices() const {
+ return vertices[0].size();
+ }
+
+ /*! returns the i'th segment */
+ __forceinline const unsigned int& segment(size_t i) const {
+ return segments[i];
+ }
+
+ /*! returns the segment to the left of the i'th segment */
+ __forceinline bool segmentLeftExists(size_t i) const {
+ assert (flags);
+ return (flags[i] & RTC_CURVE_FLAG_NEIGHBOR_LEFT) != 0;
+ }
+
+ /*! returns the segment to the right of the i'th segment */
+ __forceinline bool segmentRightExists(size_t i) const {
+ assert (flags);
+ return (flags[i] & RTC_CURVE_FLAG_NEIGHBOR_RIGHT) != 0;
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline Vec3ff vertex(size_t i) const {
+ return vertices0[i];
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline const char* vertexPtr(size_t i) const {
+ return vertices0.getPtr(i);
+ }
+
+ /*! returns i'th normal of the first time step */
+ __forceinline Vec3fa normal(size_t i) const {
+ return normals0[i];
+ }
+
+ /*! returns i'th radius of the first time step */
+ __forceinline float radius(size_t i) const {
+ return vertices0[i].w;
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline Vec3ff vertex(size_t i, size_t itime) const {
+ return vertices[itime][i];
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const char* vertexPtr(size_t i, size_t itime) const {
+ return vertices[itime].getPtr(i);
+ }
+
+ /*! returns i'th normal of itime'th timestep */
+ __forceinline Vec3fa normal(size_t i, size_t itime) const {
+ return normals[itime][i];
+ }
+
+ /*! returns i'th radius of itime'th timestep */
+ __forceinline float radius(size_t i, size_t itime) const {
+ return vertices[itime][i].w;
+ }
+
+ /*! calculates bounding box of i'th line segment */
+ __forceinline BBox3fa bounds(const Vec3ff& v0, const Vec3ff& v1) const
+ {
+ const BBox3ff b = merge(BBox3ff(v0),BBox3ff(v1));
+ return enlarge((BBox3fa)b,maxRadiusScale*Vec3fa(max(v0.w,v1.w)));
+ }
+
+ /*! calculates bounding box of i'th line segment */
+ __forceinline BBox3fa bounds(size_t i) const
+ {
+ const unsigned int index = segment(i);
+ const Vec3ff v0 = vertex(index+0);
+ const Vec3ff v1 = vertex(index+1);
+ return bounds(v0,v1);
+ }
+
+ /*! calculates bounding box of i'th line segment for the itime'th time step */
+ __forceinline BBox3fa bounds(size_t i, size_t itime) const
+ {
+ const unsigned int index = segment(i);
+ const Vec3ff v0 = vertex(index+0,itime);
+ const Vec3ff v1 = vertex(index+1,itime);
+ return bounds(v0,v1);
+ }
+
+ /*! calculates bounding box of i'th line segment */
+ __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i) const
+ {
+ const unsigned int index = segment(i);
+ const Vec3ff v0 = vertex(index+0);
+ const Vec3ff v1 = vertex(index+1);
+ const Vec3ff w0(xfmVector(space,(Vec3fa)v0),v0.w);
+ const Vec3ff w1(xfmVector(space,(Vec3fa)v1),v1.w);
+ return bounds(w0,w1);
+ }
+
+ /*! calculates bounding box of i'th line segment for the itime'th time step */
+ __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i, size_t itime) const
+ {
+ const unsigned int index = segment(i);
+ const Vec3ff v0 = vertex(index+0,itime);
+ const Vec3ff v1 = vertex(index+1,itime);
+ const Vec3ff w0(xfmVector(space,(Vec3fa)v0),v0.w);
+ const Vec3ff w1(xfmVector(space,(Vec3fa)v1),v1.w);
+ return bounds(w0,w1);
+ }
+
+ /*! check if the i'th primitive is valid at the itime'th timestep */
+ __forceinline bool valid(size_t i, size_t itime) const {
+ return valid(i, make_range(itime, itime));
+ }
+
+ /*! check if the i'th primitive is valid between the specified time range */
+ __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
+ {
+ const unsigned int index = segment(i);
+ if (index+1 >= numVertices()) return false;
+
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
+ {
+ const Vec3ff v0 = vertex(index+0,itime); if (unlikely(!isvalid4(v0))) return false;
+ const Vec3ff v1 = vertex(index+1,itime); if (unlikely(!isvalid4(v1))) return false;
+ if (min(v0.w,v1.w) < 0.0f) return false;
+ }
+ return true;
+ }
+
+ /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
+ __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
+ return LBBox3fa(bounds(i,itime+0),bounds(i,itime+1));
+ }
+
+ /*! calculates the build bounds of the i'th primitive, if it's valid */
+ __forceinline bool buildBounds(size_t i, BBox3fa* bbox) const
+ {
+ if (!valid(i,0)) return false;
+ *bbox = bounds(i);
+ return true;
+ }
+
+ /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
+ __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
+ {
+ if (!valid(i,itime+0) || !valid(i,itime+1)) return false;
+ bbox = bounds(i,itime); // use bounds of first time step in builder
+ return true;
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
+ return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
+ return LBBox3fa([&] (size_t itime) { return bounds(space, primID, itime); }, dt, time_range, fnumTimeSegments);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const
+ {
+ if (!valid(i, timeSegmentRange(time_range))) return false;
+ bbox = linearBounds(i, time_range);
+ return true;
+ }
+
+ /*! get fast access to first vertex buffer */
+ __forceinline float * getCompactVertexArray () const {
+ return (float*) vertices0.getPtr();
+ }
+
+ public:
+ BufferView<unsigned int> segments; //!< array of line segment indices
+ BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
+ BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
+ BufferView<char> flags; //!< start, end flag per segment
+ vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
+ vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
+ vector<BufferView<char>> vertexAttribs; //!< user buffers
+ int tessellationRate; //!< tessellation rate for bezier curve
+ float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
+ };
+
+ namespace isa
+ {
+ struct LineSegmentsISA : public LineSegments
+ {
+ LineSegmentsISA (Device* device, Geometry::GType gtype)
+ : LineSegments(device,gtype) {}
+
+ Vec3fa computeDirection(unsigned int primID) const
+ {
+ const unsigned vtxID = segment(primID);
+ const Vec3fa v0 = vertex(vtxID+0);
+ const Vec3fa v1 = vertex(vtxID+1);
+ return v1-v0;
+ }
+
+ Vec3fa computeDirection(unsigned int primID, size_t time) const
+ {
+ const unsigned vtxID = segment(primID);
+ const Vec3fa v0 = vertex(vtxID+0,time);
+ const Vec3fa v1 = vertex(vtxID+1,time);
+ return v1-v0;
+ }
+
+ PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j,&bounds)) continue;
+ const PrimRef prim(bounds,geomID,unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j,itime,bounds)) continue;
+ const PrimRef prim(bounds,geomID,unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfoMB pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!valid(j, timeSegmentRange(t0t1))) continue;
+ const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
+ pinfo.add_primref(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ BBox3fa vbounds(size_t i) const {
+ return bounds(i);
+ }
+
+ BBox3fa vbounds(const LinearSpace3fa& space, size_t i) const {
+ return bounds(space,i);
+ }
+
+ LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const {
+ return linearBounds(primID,time_range);
+ }
+
+ LBBox3fa vlinearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
+ return linearBounds(space,primID,time_range);
+ }
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(LineSegments*, createLineSegments, Device* COMMA Geometry::GType);
+}
diff --git a/thirdparty/embree/kernels/common/scene_points.h b/thirdparty/embree/kernels/common/scene_points.h
new file mode 100644
index 0000000000..017e098a51
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_points.h
@@ -0,0 +1,282 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "buffer.h"
+#include "default.h"
+#include "geometry.h"
+
+namespace embree
+{
+ /*! represents an array of points */
+ struct Points : public Geometry
+ {
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_POINTS;
+
+ public:
+ /*! line segments construction */
+ Points(Device* device, Geometry::GType gtype);
+
+ public:
+ void setMask(unsigned mask);
+ void setNumTimeSteps(unsigned int numTimeSteps);
+ void setVertexAttributeCount(unsigned int N);
+ void setBuffer(RTCBufferType type,
+ unsigned int slot,
+ RTCFormat format,
+ const Ref<Buffer>& buffer,
+ size_t offset,
+ size_t stride,
+ unsigned int num);
+ void* getBuffer(RTCBufferType type, unsigned int slot);
+ void updateBuffer(RTCBufferType type, unsigned int slot);
+ void commit();
+ bool verify();
+ void setMaxRadiusScale(float s);
+ void addElementsToCount (GeometryCounts & counts) const;
+
+ public:
+ /*! returns the number of vertices */
+ __forceinline size_t numVertices() const {
+ return vertices[0].size();
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline Vec3ff vertex(size_t i) const {
+ return vertices0[i];
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline const char* vertexPtr(size_t i) const {
+ return vertices0.getPtr(i);
+ }
+
+ /*! returns i'th normal of the first time step */
+ __forceinline Vec3fa normal(size_t i) const {
+ return normals0[i];
+ }
+
+ /*! returns i'th radius of the first time step */
+ __forceinline float radius(size_t i) const {
+ return vertices0[i].w;
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline Vec3ff vertex(size_t i, size_t itime) const {
+ return vertices[itime][i];
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const char* vertexPtr(size_t i, size_t itime) const {
+ return vertices[itime].getPtr(i);
+ }
+
+ /*! returns i'th normal of itime'th timestep */
+ __forceinline Vec3fa normal(size_t i, size_t itime) const {
+ return normals[itime][i];
+ }
+
+ /*! returns i'th radius of itime'th timestep */
+ __forceinline float radius(size_t i, size_t itime) const {
+ return vertices[itime][i].w;
+ }
+
+ /*! calculates bounding box of i'th line segment */
+ __forceinline BBox3fa bounds(const Vec3ff& v0) const {
+ return enlarge(BBox3fa(v0), maxRadiusScale*Vec3fa(v0.w));
+ }
+
+ /*! calculates bounding box of i'th line segment */
+ __forceinline BBox3fa bounds(size_t i) const
+ {
+ const Vec3ff v0 = vertex(i);
+ return bounds(v0);
+ }
+
+ /*! calculates bounding box of i'th line segment for the itime'th time step */
+ __forceinline BBox3fa bounds(size_t i, size_t itime) const
+ {
+ const Vec3ff v0 = vertex(i, itime);
+ return bounds(v0);
+ }
+
+ /*! calculates bounding box of i'th line segment */
+ __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i) const
+ {
+ const Vec3ff v0 = vertex(i);
+ const Vec3ff w0(xfmVector(space, (Vec3fa)v0), v0.w);
+ return bounds(w0);
+ }
+
+ /*! calculates bounding box of i'th line segment for the itime'th time step */
+ __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i, size_t itime) const
+ {
+ const Vec3ff v0 = vertex(i, itime);
+ const Vec3ff w0(xfmVector(space, (Vec3fa)v0), v0.w);
+ return bounds(w0);
+ }
+
+ /*! check if the i'th primitive is valid at the itime'th timestep */
+ __forceinline bool valid(size_t i, size_t itime) const {
+ return valid(i, make_range(itime, itime));
+ }
+
+ /*! check if the i'th primitive is valid between the specified time range */
+ __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
+ {
+ const unsigned int index = (unsigned int)i;
+ if (index >= numVertices())
+ return false;
+
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) {
+ const Vec3ff v0 = vertex(index + 0, itime);
+ if (unlikely(!isvalid4(v0)))
+ return false;
+ if (v0.w < 0.0f)
+ return false;
+ }
+ return true;
+ }
+
+ /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
+ __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
+ return LBBox3fa(bounds(i, itime + 0), bounds(i, itime + 1));
+ }
+
+ /*! calculates the build bounds of the i'th primitive, if it's valid */
+ __forceinline bool buildBounds(size_t i, BBox3fa* bbox) const
+ {
+ if (!valid(i, 0))
+ return false;
+ *bbox = bounds(i);
+ return true;
+ }
+
+ /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
+ __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
+ {
+ if (!valid(i, itime + 0) || !valid(i, itime + 1))
+ return false;
+ bbox = bounds(i, itime); // use bounds of first time step in builder
+ return true;
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
+ return LBBox3fa([&](size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
+ return LBBox3fa([&](size_t itime) { return bounds(space, primID, itime); }, dt, time_range, fnumTimeSegments);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const
+ {
+ if (!valid(i, timeSegmentRange(time_range))) return false;
+ bbox = linearBounds(i, time_range);
+ return true;
+ }
+
+ /*! get fast access to first vertex buffer */
+ __forceinline float * getCompactVertexArray () const {
+ return (float*) vertices0.getPtr();
+ }
+
+ public:
+ BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
+ BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
+ vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
+ vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
+ vector<BufferView<char>> vertexAttribs; //!< user buffers
+ float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
+ };
+
+ namespace isa
+ {
+ struct PointsISA : public Points
+ {
+ PointsISA(Device* device, Geometry::GType gtype) : Points(device, gtype) {}
+
+ Vec3fa computeDirection(unsigned int primID) const
+ {
+ return Vec3fa(1, 0, 0);
+ }
+
+ Vec3fa computeDirection(unsigned int primID, size_t time) const
+ {
+ return Vec3fa(1, 0, 0);
+ }
+
+ PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j = r.begin(); j < r.end(); j++) {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j, &bounds))
+ continue;
+ const PrimRef prim(bounds, geomID, unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j = r.begin(); j < r.end(); j++) {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j, itime, bounds))
+ continue;
+ const PrimRef prim(bounds, geomID, unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims,
+ const BBox1f& t0t1,
+ const range<size_t>& r,
+ size_t k,
+ unsigned int geomID) const
+ {
+ PrimInfoMB pinfo(empty);
+ for (size_t j = r.begin(); j < r.end(); j++) {
+ if (!valid(j, timeSegmentRange(t0t1)))
+ continue;
+ const PrimRefMB prim(linearBounds(j, t0t1), this->numTimeSegments(), this->time_range, this->numTimeSegments(), geomID, unsigned(j));
+ pinfo.add_primref(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ BBox3fa vbounds(size_t i) const
+ {
+ return bounds(i);
+ }
+
+ BBox3fa vbounds(const LinearSpace3fa& space, size_t i) const
+ {
+ return bounds(space, i);
+ }
+
+ LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const
+ {
+ return linearBounds(primID, time_range);
+ }
+
+ LBBox3fa vlinearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const
+ {
+ return linearBounds(space, primID, time_range);
+ }
+ };
+ } // namespace isa
+
+ DECLARE_ISA_FUNCTION(Points*, createPoints, Device* COMMA Geometry::GType);
+} // namespace embree
diff --git a/thirdparty/embree/kernels/common/scene_quad_mesh.h b/thirdparty/embree/kernels/common/scene_quad_mesh.h
new file mode 100644
index 0000000000..bd8eeaaeb7
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_quad_mesh.h
@@ -0,0 +1,337 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "geometry.h"
+#include "buffer.h"
+
+namespace embree
+{
+ /*! Quad Mesh */
+ struct QuadMesh : public Geometry
+ {
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_QUAD_MESH;
+
+ /*! triangle indices */
+ struct Quad
+ {
+ uint32_t v[4];
+
+ /*! outputs triangle indices */
+ __forceinline friend embree_ostream operator<<(embree_ostream cout, const Quad& q) {
+ return cout << "Quad {" << q.v[0] << ", " << q.v[1] << ", " << q.v[2] << ", " << q.v[3] << " }";
+ }
+ };
+
+ public:
+
+ /*! quad mesh construction */
+ QuadMesh (Device* device);
+
+ /* geometry interface */
+ public:
+ void setMask(unsigned mask);
+ void setNumTimeSteps (unsigned int numTimeSteps);
+ void setVertexAttributeCount (unsigned int N);
+ void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
+ void* getBuffer(RTCBufferType type, unsigned int slot);
+ void updateBuffer(RTCBufferType type, unsigned int slot);
+ void commit();
+ bool verify();
+ void interpolate(const RTCInterpolateArguments* const args);
+ void addElementsToCount (GeometryCounts & counts) const;
+
+ template<int N>
+ void interpolate_impl(const RTCInterpolateArguments* const args)
+ {
+ unsigned int primID = args->primID;
+ float u = args->u;
+ float v = args->v;
+ RTCBufferType bufferType = args->bufferType;
+ unsigned int bufferSlot = args->bufferSlot;
+ float* P = args->P;
+ float* dPdu = args->dPdu;
+ float* dPdv = args->dPdv;
+ float* ddPdudu = args->ddPdudu;
+ float* ddPdvdv = args->ddPdvdv;
+ float* ddPdudv = args->ddPdudv;
+ unsigned int valueCount = args->valueCount;
+
+ /* calculate base pointer and stride */
+ assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
+ (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
+ const char* src = nullptr;
+ size_t stride = 0;
+ if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
+ src = vertexAttribs[bufferSlot].getPtr();
+ stride = vertexAttribs[bufferSlot].getStride();
+ } else {
+ src = vertices[bufferSlot].getPtr();
+ stride = vertices[bufferSlot].getStride();
+ }
+
+ for (unsigned int i=0; i<valueCount; i+=N)
+ {
+ const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>(int(valueCount));
+ const size_t ofs = i*sizeof(float);
+ const Quad& tri = quad(primID);
+ const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[0]*stride+ofs]);
+ const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[1]*stride+ofs]);
+ const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[2]*stride+ofs]);
+ const vfloat<N> p3 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[3]*stride+ofs]);
+ const vbool<N> left = u+v <= 1.0f;
+ const vfloat<N> Q0 = select(left,p0,p2);
+ const vfloat<N> Q1 = select(left,p1,p3);
+ const vfloat<N> Q2 = select(left,p3,p1);
+ const vfloat<N> U = select(left,u,vfloat<N>(1.0f)-u);
+ const vfloat<N> V = select(left,v,vfloat<N>(1.0f)-v);
+ const vfloat<N> W = 1.0f-U-V;
+ if (P) {
+ mem<vfloat<N>>::storeu(valid,P+i,madd(W,Q0,madd(U,Q1,V*Q2)));
+ }
+ if (dPdu) {
+ assert(dPdu); mem<vfloat<N>>::storeu(valid,dPdu+i,select(left,Q1-Q0,Q0-Q1));
+ assert(dPdv); mem<vfloat<N>>::storeu(valid,dPdv+i,select(left,Q2-Q0,Q0-Q2));
+ }
+ if (ddPdudu) {
+ assert(ddPdudu); mem<vfloat<N>>::storeu(valid,ddPdudu+i,vfloat<N>(zero));
+ assert(ddPdvdv); mem<vfloat<N>>::storeu(valid,ddPdvdv+i,vfloat<N>(zero));
+ assert(ddPdudv); mem<vfloat<N>>::storeu(valid,ddPdudv+i,vfloat<N>(zero));
+ }
+ }
+ }
+
+ public:
+
+ /*! returns number of vertices */
+ __forceinline size_t numVertices() const {
+ return vertices[0].size();
+ }
+
+ /*! returns i'th quad */
+ __forceinline const Quad& quad(size_t i) const {
+ return quads[i];
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const Vec3fa vertex(size_t i) const {
+ return vertices0[i];
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const char* vertexPtr(size_t i) const {
+ return vertices0.getPtr(i);
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const Vec3fa vertex(size_t i, size_t itime) const {
+ return vertices[itime][i];
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const char* vertexPtr(size_t i, size_t itime) const {
+ return vertices[itime].getPtr(i);
+ }
+
+ /*! calculates the bounds of the i'th quad */
+ __forceinline BBox3fa bounds(size_t i) const
+ {
+ const Quad& q = quad(i);
+ const Vec3fa v0 = vertex(q.v[0]);
+ const Vec3fa v1 = vertex(q.v[1]);
+ const Vec3fa v2 = vertex(q.v[2]);
+ const Vec3fa v3 = vertex(q.v[3]);
+ return BBox3fa(min(v0,v1,v2,v3),max(v0,v1,v2,v3));
+ }
+
+ /*! calculates the bounds of the i'th quad at the itime'th timestep */
+ __forceinline BBox3fa bounds(size_t i, size_t itime) const
+ {
+ const Quad& q = quad(i);
+ const Vec3fa v0 = vertex(q.v[0],itime);
+ const Vec3fa v1 = vertex(q.v[1],itime);
+ const Vec3fa v2 = vertex(q.v[2],itime);
+ const Vec3fa v3 = vertex(q.v[3],itime);
+ return BBox3fa(min(v0,v1,v2,v3),max(v0,v1,v2,v3));
+ }
+
+ /*! check if the i'th primitive is valid at the itime'th timestep */
+ __forceinline bool valid(size_t i, size_t itime) const {
+ return valid(i, make_range(itime, itime));
+ }
+
+ /*! check if the i'th primitive is valid between the specified time range */
+ __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
+ {
+ const Quad& q = quad(i);
+ if (unlikely(q.v[0] >= numVertices())) return false;
+ if (unlikely(q.v[1] >= numVertices())) return false;
+ if (unlikely(q.v[2] >= numVertices())) return false;
+ if (unlikely(q.v[3] >= numVertices())) return false;
+
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
+ {
+ if (!isvalid(vertex(q.v[0],itime))) return false;
+ if (!isvalid(vertex(q.v[1],itime))) return false;
+ if (!isvalid(vertex(q.v[2],itime))) return false;
+ if (!isvalid(vertex(q.v[3],itime))) return false;
+ }
+
+ return true;
+ }
+
+ /*! calculates the linear bounds of the i'th quad at the itimeGlobal'th time segment */
+ __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
+ return LBBox3fa(bounds(i,itime+0),bounds(i,itime+1));
+ }
+
+ /*! calculates the build bounds of the i'th primitive, if it's valid */
+ __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
+ {
+ const Quad& q = quad(i);
+ if (q.v[0] >= numVertices()) return false;
+ if (q.v[1] >= numVertices()) return false;
+ if (q.v[2] >= numVertices()) return false;
+ if (q.v[3] >= numVertices()) return false;
+
+ for (unsigned int t=0; t<numTimeSteps; t++)
+ {
+ const Vec3fa v0 = vertex(q.v[0],t);
+ const Vec3fa v1 = vertex(q.v[1],t);
+ const Vec3fa v2 = vertex(q.v[2],t);
+ const Vec3fa v3 = vertex(q.v[3],t);
+
+ if (unlikely(!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3)))
+ return false;
+ }
+
+ if (bbox)
+ *bbox = bounds(i);
+
+ return true;
+ }
+
+ /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
+ __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
+ {
+ const Quad& q = quad(i);
+ if (unlikely(q.v[0] >= numVertices())) return false;
+ if (unlikely(q.v[1] >= numVertices())) return false;
+ if (unlikely(q.v[2] >= numVertices())) return false;
+ if (unlikely(q.v[3] >= numVertices())) return false;
+
+ assert(itime+1 < numTimeSteps);
+ const Vec3fa a0 = vertex(q.v[0],itime+0); if (unlikely(!isvalid(a0))) return false;
+ const Vec3fa a1 = vertex(q.v[1],itime+0); if (unlikely(!isvalid(a1))) return false;
+ const Vec3fa a2 = vertex(q.v[2],itime+0); if (unlikely(!isvalid(a2))) return false;
+ const Vec3fa a3 = vertex(q.v[3],itime+0); if (unlikely(!isvalid(a3))) return false;
+ const Vec3fa b0 = vertex(q.v[0],itime+1); if (unlikely(!isvalid(b0))) return false;
+ const Vec3fa b1 = vertex(q.v[1],itime+1); if (unlikely(!isvalid(b1))) return false;
+ const Vec3fa b2 = vertex(q.v[2],itime+1); if (unlikely(!isvalid(b2))) return false;
+ const Vec3fa b3 = vertex(q.v[3],itime+1); if (unlikely(!isvalid(b3))) return false;
+
+ /* use bounds of first time step in builder */
+ bbox = BBox3fa(min(a0,a1,a2,a3),max(a0,a1,a2,a3));
+ return true;
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
+ return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline bool linearBounds(size_t i, const BBox1f& dt, LBBox3fa& bbox) const
+ {
+ if (!valid(i, timeSegmentRange(dt))) return false;
+ bbox = linearBounds(i, dt);
+ return true;
+ }
+
+ /*! get fast access to first vertex buffer */
+ __forceinline float * getCompactVertexArray () const {
+ return (float*) vertices0.getPtr();
+ }
+
+ /* gets version info of topology */
+ unsigned int getTopologyVersion() const {
+ return quads.modCounter;
+ }
+
+ /* returns true if topology changed */
+ bool topologyChanged(unsigned int otherVersion) const {
+ return quads.isModified(otherVersion); // || numPrimitivesChanged;
+ }
+
+ /* returns the projected area */
+ __forceinline float projectedPrimitiveArea(const size_t i) const {
+ const Quad& q = quad(i);
+ const Vec3fa v0 = vertex(q.v[0]);
+ const Vec3fa v1 = vertex(q.v[1]);
+ const Vec3fa v2 = vertex(q.v[2]);
+ const Vec3fa v3 = vertex(q.v[3]);
+ return areaProjectedTriangle(v0,v1,v3) +
+ areaProjectedTriangle(v1,v2,v3);
+ }
+
+ public:
+ BufferView<Quad> quads; //!< array of quads
+ BufferView<Vec3fa> vertices0; //!< fast access to first vertex buffer
+ vector<BufferView<Vec3fa>> vertices; //!< vertex array for each timestep
+ vector<BufferView<char>> vertexAttribs; //!< vertex attribute buffers
+ };
+
+ namespace isa
+ {
+ struct QuadMeshISA : public QuadMesh
+ {
+ QuadMeshISA (Device* device)
+ : QuadMesh(device) {}
+
+ PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j,&bounds)) continue;
+ const PrimRef prim(bounds,geomID,unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j,itime,bounds)) continue;
+ const PrimRef prim(bounds,geomID,unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfoMB pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!valid(j, timeSegmentRange(t0t1))) continue;
+ const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
+ pinfo.add_primref(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(QuadMesh*, createQuadMesh, Device*);
+}
diff --git a/thirdparty/embree/kernels/common/scene_subdiv_mesh.h b/thirdparty/embree/kernels/common/scene_subdiv_mesh.h
new file mode 100644
index 0000000000..1db170196d
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_subdiv_mesh.h
@@ -0,0 +1,326 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "geometry.h"
+#include "buffer.h"
+#include "../subdiv/half_edge.h"
+#include "../subdiv/tessellation_cache.h"
+#include "../subdiv/catmullclark_coefficients.h"
+#include "../subdiv/patch.h"
+#include "../../common/algorithms/parallel_map.h"
+#include "../../common/algorithms/parallel_set.h"
+
+namespace embree
+{
+ class SubdivMesh : public Geometry
+ {
+ ALIGNED_CLASS_(16);
+ public:
+
+ typedef HalfEdge::Edge Edge;
+
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_SUBDIV_MESH;
+
+ /*! structure used to sort half edges using radix sort by their key */
+ struct KeyHalfEdge
+ {
+ KeyHalfEdge() {}
+
+ KeyHalfEdge (uint64_t key, HalfEdge* edge)
+ : key(key), edge(edge) {}
+
+ __forceinline operator uint64_t() const {
+ return key;
+ }
+
+ friend __forceinline bool operator<(const KeyHalfEdge& e0, const KeyHalfEdge& e1) {
+ return e0.key < e1.key;
+ }
+
+ public:
+ uint64_t key;
+ HalfEdge* edge;
+ };
+
+ public:
+
+ /*! subdiv mesh construction */
+ SubdivMesh(Device* device);
+
+ public:
+ void setMask (unsigned mask);
+ void setSubdivisionMode (unsigned int topologyID, RTCSubdivisionMode mode);
+ void setVertexAttributeTopology(unsigned int vertexAttribID, unsigned int topologyID);
+ void setNumTimeSteps (unsigned int numTimeSteps);
+ void setVertexAttributeCount (unsigned int N);
+ void setTopologyCount (unsigned int N);
+ void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
+ void* getBuffer(RTCBufferType type, unsigned int slot);
+ void updateBuffer(RTCBufferType type, unsigned int slot);
+ void setTessellationRate(float N);
+ bool verify();
+ void commit();
+ void addElementsToCount (GeometryCounts & counts) const;
+ void setDisplacementFunction (RTCDisplacementFunctionN func);
+ unsigned int getFirstHalfEdge(unsigned int faceID);
+ unsigned int getFace(unsigned int edgeID);
+ unsigned int getNextHalfEdge(unsigned int edgeID);
+ unsigned int getPreviousHalfEdge(unsigned int edgeID);
+ unsigned int getOppositeHalfEdge(unsigned int topologyID, unsigned int edgeID);
+
+ public:
+
+ /*! return the number of faces */
+ size_t numFaces() const {
+ return faceVertices.size();
+ }
+
+ /*! return the number of edges */
+ size_t numEdges() const {
+ return topology[0].vertexIndices.size();
+ }
+
+ /*! return the number of vertices */
+ size_t numVertices() const {
+ return vertices[0].size();
+ }
+
+ /*! calculates the bounds of the i'th subdivision patch at the j'th timestep */
+ __forceinline BBox3fa bounds(size_t i, size_t j = 0) const {
+ return topology[0].getHalfEdge(i)->bounds(vertices[j]);
+ }
+
+ /*! check if the i'th primitive is valid */
+ __forceinline bool valid(size_t i) const {
+ return topology[0].valid(i) && !invalidFace(i);
+ }
+
+ /*! check if the i'th primitive is valid for the j'th time range */
+ __forceinline bool valid(size_t i, size_t j) const {
+ return topology[0].valid(i) && !invalidFace(i,j);
+ }
+
+ /*! prints some statistics */
+ void printStatistics();
+
+ /*! initializes the half edge data structure */
+ void initializeHalfEdgeStructures ();
+
+ public:
+
+ /*! returns the vertex buffer for some time step */
+ __forceinline const BufferView<Vec3fa>& getVertexBuffer( const size_t t = 0 ) const {
+ return vertices[t];
+ }
+
+ /* returns tessellation level of edge */
+ __forceinline float getEdgeLevel(const size_t i) const
+ {
+ if (levels) return clamp(levels[i],1.0f,4096.0f); // FIXME: do we want to limit edge level?
+ else return clamp(tessellationRate,1.0f,4096.0f); // FIXME: do we want to limit edge level?
+ }
+
+ public:
+ RTCDisplacementFunctionN displFunc; //!< displacement function
+
+ /*! all buffers in this section are provided by the application */
+ public:
+
+ /*! the topology contains all data that may differ when
+ * interpolating different user data buffers */
+ struct Topology
+ {
+ public:
+
+ /*! Default topology construction */
+ Topology () : halfEdges(nullptr,0) {}
+
+ /*! Topology initialization */
+ Topology (SubdivMesh* mesh);
+
+ /*! make the class movable */
+ public:
+ Topology (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
+ : mesh(std::move(other.mesh)),
+ vertexIndices(std::move(other.vertexIndices)),
+ subdiv_mode(std::move(other.subdiv_mode)),
+ halfEdges(std::move(other.halfEdges)),
+ halfEdges0(std::move(other.halfEdges0)),
+ halfEdges1(std::move(other.halfEdges1)) {}
+
+ Topology& operator= (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
+ {
+ mesh = std::move(other.mesh);
+ vertexIndices = std::move(other.vertexIndices);
+ subdiv_mode = std::move(other.subdiv_mode);
+ halfEdges = std::move(other.halfEdges);
+ halfEdges0 = std::move(other.halfEdges0);
+ halfEdges1 = std::move(other.halfEdges1);
+ return *this;
+ }
+
+ public:
+ /*! check if the i'th primitive is valid in this topology */
+ __forceinline bool valid(size_t i) const
+ {
+ if (unlikely(subdiv_mode == RTC_SUBDIVISION_MODE_NO_BOUNDARY)) {
+ if (getHalfEdge(i)->faceHasBorder()) return false;
+ }
+ return true;
+ }
+
+ /*! updates the interpolation mode for the topology */
+ void setSubdivisionMode (RTCSubdivisionMode mode);
+
+ /*! marks all buffers as modified */
+ void update ();
+
+ /*! verifies index array */
+ bool verify (size_t numVertices);
+
+ /*! initializes the half edge data structure */
+ void initializeHalfEdgeStructures ();
+
+ private:
+
+ /*! recalculates the half edges */
+ void calculateHalfEdges();
+
+ /*! updates half edges when recalculation is not necessary */
+ void updateHalfEdges();
+
+ /*! user input data */
+ public:
+
+ SubdivMesh* mesh;
+
+ /*! indices of the vertices composing each face */
+ BufferView<unsigned int> vertexIndices;
+
+ /*! subdiv interpolation mode */
+ RTCSubdivisionMode subdiv_mode;
+
+ /*! generated data */
+ public:
+
+ /*! returns the start half edge for face f */
+ __forceinline const HalfEdge* getHalfEdge ( const size_t f ) const {
+ return &halfEdges[mesh->faceStartEdge[f]];
+ }
+
+ /*! Half edge structure, generated by initHalfEdgeStructures */
+ mvector<HalfEdge> halfEdges;
+
+ /*! the following data is only required during construction of the
+ * half edge structure and can be cleared for static scenes */
+ private:
+
+ /*! two arrays used to sort the half edges */
+ std::vector<KeyHalfEdge> halfEdges0;
+ std::vector<KeyHalfEdge> halfEdges1;
+ };
+
+ /*! returns the start half edge for topology t and face f */
+ __forceinline const HalfEdge* getHalfEdge ( const size_t t , const size_t f ) const {
+ return topology[t].getHalfEdge(f);
+ }
+
+ /*! buffer containing the number of vertices for each face */
+ BufferView<unsigned int> faceVertices;
+
+ /*! array of topologies */
+ vector<Topology> topology;
+
+ /*! vertex buffer (one buffer for each time step) */
+ vector<BufferView<Vec3fa>> vertices;
+
+ /*! user data buffers */
+ vector<RawBufferView> vertexAttribs;
+
+ /*! edge crease buffer containing edges (pairs of vertices) that carry edge crease weights */
+ BufferView<Edge> edge_creases;
+
+ /*! edge crease weights for each edge of the edge_creases buffer */
+ BufferView<float> edge_crease_weights;
+
+ /*! vertex crease buffer containing all vertices that carry vertex crease weights */
+ BufferView<unsigned int> vertex_creases;
+
+ /*! vertex crease weights for each vertex of the vertex_creases buffer */
+ BufferView<float> vertex_crease_weights;
+
+ /*! subdivision level for each half edge of the vertexIndices buffer */
+ BufferView<float> levels;
+ float tessellationRate; // constant rate that is used when levels is not set
+
+ /*! buffer that marks specific faces as holes */
+ BufferView<unsigned> holes;
+
+ /*! all data in this section is generated by initializeHalfEdgeStructures function */
+ private:
+
+ /*! number of half edges used by faces */
+ size_t numHalfEdges;
+
+ /*! fast lookup table to find the first half edge for some face */
+ mvector<uint32_t> faceStartEdge;
+
+ /*! fast lookup table to find the face for some half edge */
+ mvector<uint32_t> halfEdgeFace;
+
+ /*! set with all holes */
+ parallel_set<uint32_t> holeSet;
+
+ /*! fast lookup table to detect invalid faces */
+ mvector<char> invalid_face;
+
+ /*! test if face i is invalid in timestep j */
+ __forceinline char& invalidFace(size_t i, size_t j = 0) { return invalid_face[i*numTimeSteps+j]; }
+ __forceinline const char& invalidFace(size_t i, size_t j = 0) const { return invalid_face[i*numTimeSteps+j]; }
+
+ /*! interpolation cache */
+ public:
+ static __forceinline size_t numInterpolationSlots4(size_t stride) { return (stride+15)/16; }
+ static __forceinline size_t numInterpolationSlots8(size_t stride) { return (stride+31)/32; }
+ static __forceinline size_t interpolationSlot(size_t prim, size_t slot, size_t stride) {
+ const size_t slots = numInterpolationSlots4(stride);
+ assert(slot < slots);
+ return slots*prim+slot;
+ }
+ std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_buffer_tags;
+ std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_attrib_buffer_tags;
+ std::vector<Patch3fa::Ref> patch_eval_trees;
+
+ /*! the following data is only required during construction of the
+ * half edge structure and can be cleared for static scenes */
+ private:
+
+ /*! map with all vertex creases */
+ parallel_map<uint32_t,float> vertexCreaseMap;
+
+ /*! map with all edge creases */
+ parallel_map<uint64_t,float> edgeCreaseMap;
+
+ protected:
+
+ /*! counts number of geometry commits */
+ size_t commitCounter;
+ };
+
+ namespace isa
+ {
+ struct SubdivMeshISA : public SubdivMesh
+ {
+ SubdivMeshISA (Device* device)
+ : SubdivMesh(device) {}
+
+ void interpolate(const RTCInterpolateArguments* const args);
+ void interpolateN(const RTCInterpolateNArguments* const args);
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(SubdivMesh*, createSubdivMesh, Device*);
+};
diff --git a/thirdparty/embree/kernels/common/scene_triangle_mesh.cpp b/thirdparty/embree/kernels/common/scene_triangle_mesh.cpp
new file mode 100644
index 0000000000..3bbd7e51ae
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_triangle_mesh.cpp
@@ -0,0 +1,194 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "scene_triangle_mesh.h"
+#include "scene.h"
+
+namespace embree
+{
+#if defined(EMBREE_LOWEST_ISA)
+
+ TriangleMesh::TriangleMesh (Device* device)
+ : Geometry(device,GTY_TRIANGLE_MESH,0,1)
+ {
+ vertices.resize(numTimeSteps);
+ }
+
+ void TriangleMesh::setMask (unsigned mask)
+ {
+ this->mask = mask;
+ Geometry::update();
+ }
+
+ void TriangleMesh::setNumTimeSteps (unsigned int numTimeSteps)
+ {
+ vertices.resize(numTimeSteps);
+ Geometry::setNumTimeSteps(numTimeSteps);
+ }
+
+ void TriangleMesh::setVertexAttributeCount (unsigned int N)
+ {
+ vertexAttribs.resize(N);
+ Geometry::update();
+ }
+
+ void TriangleMesh::setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num)
+ {
+ /* verify that all accesses are 4 bytes aligned */
+ if (((size_t(buffer->getPtr()) + offset) & 0x3) || (stride & 0x3))
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION, "data must be 4 bytes aligned");
+
+ if (type == RTC_BUFFER_TYPE_VERTEX)
+ {
+ if (format != RTC_FORMAT_FLOAT3)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex buffer format");
+
+ /* if buffer is larger than 16GB the premultiplied index optimization does not work */
+ if (stride*num > 16ll*1024ll*1024ll*1024ll)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION, "vertex buffer can be at most 16GB large");
+
+ if (slot >= vertices.size())
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid vertex buffer slot");
+
+ vertices[slot].set(buffer, offset, stride, num, format);
+ vertices[slot].checkPadding16();
+ vertices0 = vertices[0];
+ }
+ else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
+ {
+ if (format < RTC_FORMAT_FLOAT || format > RTC_FORMAT_FLOAT16)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex attribute buffer format");
+
+ if (slot >= vertexAttribs.size())
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex attribute buffer slot");
+
+ vertexAttribs[slot].set(buffer, offset, stride, num, format);
+ vertexAttribs[slot].checkPadding16();
+ }
+ else if (type == RTC_BUFFER_TYPE_INDEX)
+ {
+ if (slot != 0)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
+ if (format != RTC_FORMAT_UINT3)
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid index buffer format");
+
+ triangles.set(buffer, offset, stride, num, format);
+ setNumPrimitives(num);
+ }
+ else
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
+ }
+
+ void* TriangleMesh::getBuffer(RTCBufferType type, unsigned int slot)
+ {
+ if (type == RTC_BUFFER_TYPE_INDEX)
+ {
+ if (slot != 0)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
+ return triangles.getPtr();
+ }
+ else if (type == RTC_BUFFER_TYPE_VERTEX)
+ {
+ if (slot >= vertices.size())
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
+ return vertices[slot].getPtr();
+ }
+ else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
+ {
+ if (slot >= vertexAttribs.size())
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
+ return vertexAttribs[slot].getPtr();
+ }
+ else
+ {
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
+ return nullptr;
+ }
+ }
+
+ void TriangleMesh::updateBuffer(RTCBufferType type, unsigned int slot)
+ {
+ if (type == RTC_BUFFER_TYPE_INDEX)
+ {
+ if (slot != 0)
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
+ triangles.setModified();
+ }
+ else if (type == RTC_BUFFER_TYPE_VERTEX)
+ {
+ if (slot >= vertices.size())
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
+ vertices[slot].setModified();
+ }
+ else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
+ {
+ if (slot >= vertexAttribs.size())
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
+ vertexAttribs[slot].setModified();
+ }
+ else
+ {
+ throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
+ }
+
+ Geometry::update();
+ }
+
+ void TriangleMesh::commit()
+ {
+ /* verify that stride of all time steps are identical */
+ for (unsigned int t=0; t<numTimeSteps; t++)
+ if (vertices[t].getStride() != vertices[0].getStride())
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"stride of vertex buffers have to be identical for each time step");
+
+ Geometry::commit();
+ }
+
+ void TriangleMesh::addElementsToCount (GeometryCounts & counts) const
+ {
+ if (numTimeSteps == 1) counts.numTriangles += numPrimitives;
+ else counts.numMBTriangles += numPrimitives;
+ }
+
+ bool TriangleMesh::verify()
+ {
+ /*! verify size of vertex arrays */
+ if (vertices.size() == 0) return false;
+ for (const auto& buffer : vertices)
+ if (buffer.size() != numVertices())
+ return false;
+
+ /*! verify size of user vertex arrays */
+ for (const auto& buffer : vertexAttribs)
+ if (buffer.size() != numVertices())
+ return false;
+
+ /*! verify triangle indices */
+ for (size_t i=0; i<size(); i++) {
+ if (triangles[i].v[0] >= numVertices()) return false;
+ if (triangles[i].v[1] >= numVertices()) return false;
+ if (triangles[i].v[2] >= numVertices()) return false;
+ }
+
+ /*! verify vertices */
+ for (const auto& buffer : vertices)
+ for (size_t i=0; i<buffer.size(); i++)
+ if (!isvalid(buffer[i]))
+ return false;
+
+ return true;
+ }
+
+ void TriangleMesh::interpolate(const RTCInterpolateArguments* const args) {
+ interpolate_impl<4>(args);
+ }
+
+#endif
+
+ namespace isa
+ {
+ TriangleMesh* createTriangleMesh(Device* device) {
+ return new TriangleMeshISA(device);
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/common/scene_triangle_mesh.h b/thirdparty/embree/kernels/common/scene_triangle_mesh.h
new file mode 100644
index 0000000000..ad3f602fde
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_triangle_mesh.h
@@ -0,0 +1,318 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "geometry.h"
+#include "buffer.h"
+
+namespace embree
+{
+ /*! Triangle Mesh */
+ struct TriangleMesh : public Geometry
+ {
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_TRIANGLE_MESH;
+
+ /*! triangle indices */
+ struct Triangle
+ {
+ uint32_t v[3];
+
+ /*! outputs triangle indices */
+ __forceinline friend embree_ostream operator<<(embree_ostream cout, const Triangle& t) {
+ return cout << "Triangle { " << t.v[0] << ", " << t.v[1] << ", " << t.v[2] << " }";
+ }
+ };
+
+ public:
+
+ /*! triangle mesh construction */
+ TriangleMesh (Device* device);
+
+ /* geometry interface */
+ public:
+ void setMask(unsigned mask);
+ void setNumTimeSteps (unsigned int numTimeSteps);
+ void setVertexAttributeCount (unsigned int N);
+ void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
+ void* getBuffer(RTCBufferType type, unsigned int slot);
+ void updateBuffer(RTCBufferType type, unsigned int slot);
+ void commit();
+ bool verify();
+ void interpolate(const RTCInterpolateArguments* const args);
+ void addElementsToCount (GeometryCounts & counts) const;
+
+ template<int N>
+ void interpolate_impl(const RTCInterpolateArguments* const args)
+ {
+ unsigned int primID = args->primID;
+ float u = args->u;
+ float v = args->v;
+ RTCBufferType bufferType = args->bufferType;
+ unsigned int bufferSlot = args->bufferSlot;
+ float* P = args->P;
+ float* dPdu = args->dPdu;
+ float* dPdv = args->dPdv;
+ float* ddPdudu = args->ddPdudu;
+ float* ddPdvdv = args->ddPdvdv;
+ float* ddPdudv = args->ddPdudv;
+ unsigned int valueCount = args->valueCount;
+
+ /* calculate base pointer and stride */
+ assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
+ (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
+ const char* src = nullptr;
+ size_t stride = 0;
+ if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
+ src = vertexAttribs[bufferSlot].getPtr();
+ stride = vertexAttribs[bufferSlot].getStride();
+ } else {
+ src = vertices[bufferSlot].getPtr();
+ stride = vertices[bufferSlot].getStride();
+ }
+
+ for (unsigned int i=0; i<valueCount; i+=N)
+ {
+ size_t ofs = i*sizeof(float);
+ const float w = 1.0f-u-v;
+ const Triangle& tri = triangle(primID);
+ const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>(int(valueCount));
+ const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[0]*stride+ofs]);
+ const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[1]*stride+ofs]);
+ const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[2]*stride+ofs]);
+
+ if (P) {
+ mem<vfloat<N>>::storeu(valid,P+i,madd(w,p0,madd(u,p1,v*p2)));
+ }
+ if (dPdu) {
+ assert(dPdu); mem<vfloat<N>>::storeu(valid,dPdu+i,p1-p0);
+ assert(dPdv); mem<vfloat<N>>::storeu(valid,dPdv+i,p2-p0);
+ }
+ if (ddPdudu) {
+ assert(ddPdudu); mem<vfloat<N>>::storeu(valid,ddPdudu+i,vfloat<N>(zero));
+ assert(ddPdvdv); mem<vfloat<N>>::storeu(valid,ddPdvdv+i,vfloat<N>(zero));
+ assert(ddPdudv); mem<vfloat<N>>::storeu(valid,ddPdudv+i,vfloat<N>(zero));
+ }
+ }
+ }
+
+ public:
+
+ /*! returns number of vertices */
+ __forceinline size_t numVertices() const {
+ return vertices[0].size();
+ }
+
+ /*! returns i'th triangle*/
+ __forceinline const Triangle& triangle(size_t i) const {
+ return triangles[i];
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline const Vec3fa vertex(size_t i) const {
+ return vertices0[i];
+ }
+
+ /*! returns i'th vertex of the first time step */
+ __forceinline const char* vertexPtr(size_t i) const {
+ return vertices0.getPtr(i);
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const Vec3fa vertex(size_t i, size_t itime) const {
+ return vertices[itime][i];
+ }
+
+ /*! returns i'th vertex of itime'th timestep */
+ __forceinline const char* vertexPtr(size_t i, size_t itime) const {
+ return vertices[itime].getPtr(i);
+ }
+
+ /*! calculates the bounds of the i'th triangle */
+ __forceinline BBox3fa bounds(size_t i) const
+ {
+ const Triangle& tri = triangle(i);
+ const Vec3fa v0 = vertex(tri.v[0]);
+ const Vec3fa v1 = vertex(tri.v[1]);
+ const Vec3fa v2 = vertex(tri.v[2]);
+ return BBox3fa(min(v0,v1,v2),max(v0,v1,v2));
+ }
+
+ /*! calculates the bounds of the i'th triangle at the itime'th timestep */
+ __forceinline BBox3fa bounds(size_t i, size_t itime) const
+ {
+ const Triangle& tri = triangle(i);
+ const Vec3fa v0 = vertex(tri.v[0],itime);
+ const Vec3fa v1 = vertex(tri.v[1],itime);
+ const Vec3fa v2 = vertex(tri.v[2],itime);
+ return BBox3fa(min(v0,v1,v2),max(v0,v1,v2));
+ }
+
+ /*! check if the i'th primitive is valid at the itime'th timestep */
+ __forceinline bool valid(size_t i, size_t itime) const {
+ return valid(i, make_range(itime, itime));
+ }
+
+ /*! check if the i'th primitive is valid between the specified time range */
+ __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
+ {
+ const Triangle& tri = triangle(i);
+ if (unlikely(tri.v[0] >= numVertices())) return false;
+ if (unlikely(tri.v[1] >= numVertices())) return false;
+ if (unlikely(tri.v[2] >= numVertices())) return false;
+
+ for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
+ {
+ if (!isvalid(vertex(tri.v[0],itime))) return false;
+ if (!isvalid(vertex(tri.v[1],itime))) return false;
+ if (!isvalid(vertex(tri.v[2],itime))) return false;
+ }
+
+ return true;
+ }
+
+ /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
+ __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
+ return LBBox3fa(bounds(i,itime+0),bounds(i,itime+1));
+ }
+
+ /*! calculates the build bounds of the i'th primitive, if it's valid */
+ __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
+ {
+ const Triangle& tri = triangle(i);
+ if (unlikely(tri.v[0] >= numVertices())) return false;
+ if (unlikely(tri.v[1] >= numVertices())) return false;
+ if (unlikely(tri.v[2] >= numVertices())) return false;
+
+ for (size_t t=0; t<numTimeSteps; t++)
+ {
+ const Vec3fa v0 = vertex(tri.v[0],t);
+ const Vec3fa v1 = vertex(tri.v[1],t);
+ const Vec3fa v2 = vertex(tri.v[2],t);
+ if (unlikely(!isvalid(v0) || !isvalid(v1) || !isvalid(v2)))
+ return false;
+ }
+
+ if (likely(bbox))
+ *bbox = bounds(i);
+
+ return true;
+ }
+
+ /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
+ __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
+ {
+ const Triangle& tri = triangle(i);
+ if (unlikely(tri.v[0] >= numVertices())) return false;
+ if (unlikely(tri.v[1] >= numVertices())) return false;
+ if (unlikely(tri.v[2] >= numVertices())) return false;
+
+ assert(itime+1 < numTimeSteps);
+ const Vec3fa a0 = vertex(tri.v[0],itime+0); if (unlikely(!isvalid(a0))) return false;
+ const Vec3fa a1 = vertex(tri.v[1],itime+0); if (unlikely(!isvalid(a1))) return false;
+ const Vec3fa a2 = vertex(tri.v[2],itime+0); if (unlikely(!isvalid(a2))) return false;
+ const Vec3fa b0 = vertex(tri.v[0],itime+1); if (unlikely(!isvalid(b0))) return false;
+ const Vec3fa b1 = vertex(tri.v[1],itime+1); if (unlikely(!isvalid(b1))) return false;
+ const Vec3fa b2 = vertex(tri.v[2],itime+1); if (unlikely(!isvalid(b2))) return false;
+
+ /* use bounds of first time step in builder */
+ bbox = BBox3fa(min(a0,a1,a2),max(a0,a1,a2));
+ return true;
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
+ return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
+ }
+
+ /*! calculates the linear bounds of the i'th primitive for the specified time range */
+ __forceinline bool linearBounds(size_t i, const BBox1f& dt, LBBox3fa& bbox) const {
+ if (!valid(i, timeSegmentRange(dt))) return false;
+ bbox = linearBounds(i, dt);
+ return true;
+ }
+
+ /*! get fast access to first vertex buffer */
+ __forceinline float * getCompactVertexArray () const {
+ return (float*) vertices0.getPtr();
+ }
+
+ /* gets version info of topology */
+ unsigned int getTopologyVersion() const {
+ return triangles.modCounter;
+ }
+
+ /* returns true if topology changed */
+ bool topologyChanged(unsigned int otherVersion) const {
+ return triangles.isModified(otherVersion); // || numPrimitivesChanged;
+ }
+
+ /* returns the projected area */
+ __forceinline float projectedPrimitiveArea(const size_t i) const {
+ const Triangle& tri = triangle(i);
+ const Vec3fa v0 = vertex(tri.v[0]);
+ const Vec3fa v1 = vertex(tri.v[1]);
+ const Vec3fa v2 = vertex(tri.v[2]);
+ return areaProjectedTriangle(v0,v1,v2);
+ }
+
+ public:
+ BufferView<Triangle> triangles; //!< array of triangles
+ BufferView<Vec3fa> vertices0; //!< fast access to first vertex buffer
+ vector<BufferView<Vec3fa>> vertices; //!< vertex array for each timestep
+ vector<RawBufferView> vertexAttribs; //!< vertex attributes
+ };
+
+ namespace isa
+ {
+ struct TriangleMeshISA : public TriangleMesh
+ {
+ TriangleMeshISA (Device* device)
+ : TriangleMesh(device) {}
+
+ PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j,&bounds)) continue;
+ const PrimRef prim(bounds,geomID,unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j,itime,bounds)) continue;
+ const PrimRef prim(bounds,geomID,unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfoMB pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!valid(j, timeSegmentRange(t0t1))) continue;
+ const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
+ pinfo.add_primref(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(TriangleMesh*, createTriangleMesh, Device*);
+}
diff --git a/thirdparty/embree/kernels/common/scene_user_geometry.h b/thirdparty/embree/kernels/common/scene_user_geometry.h
new file mode 100644
index 0000000000..2867b18b79
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_user_geometry.h
@@ -0,0 +1,77 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "accelset.h"
+
+namespace embree
+{
+ /*! User geometry with user defined intersection functions */
+ struct UserGeometry : public AccelSet
+ {
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_USER_GEOMETRY;
+
+ public:
+ UserGeometry (Device* device, unsigned int items = 0, unsigned int numTimeSteps = 1);
+ virtual void setMask (unsigned mask);
+ virtual void setBoundsFunction (RTCBoundsFunction bounds, void* userPtr);
+ virtual void setIntersectFunctionN (RTCIntersectFunctionN intersect);
+ virtual void setOccludedFunctionN (RTCOccludedFunctionN occluded);
+ virtual void build() {}
+ virtual void addElementsToCount (GeometryCounts & counts) const;
+ };
+
+ namespace isa
+ {
+ struct UserGeometryISA : public UserGeometry
+ {
+ UserGeometryISA (Device* device)
+ : UserGeometry(device) {}
+
+ PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j,&bounds)) continue;
+ const PrimRef prim(bounds,geomID,unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfo pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ BBox3fa bounds = empty;
+ if (!buildBounds(j,itime,bounds)) continue;
+ const PrimRef prim(bounds,geomID,unsigned(j));
+ pinfo.add_center2(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+
+ PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
+ {
+ PrimInfoMB pinfo(empty);
+ for (size_t j=r.begin(); j<r.end(); j++)
+ {
+ if (!valid(j, timeSegmentRange(t0t1))) continue;
+ const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
+ pinfo.add_primref(prim);
+ prims[k++] = prim;
+ }
+ return pinfo;
+ }
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(UserGeometry*, createUserGeometry, Device*);
+}
diff --git a/thirdparty/embree/kernels/common/stack_item.h b/thirdparty/embree/kernels/common/stack_item.h
new file mode 100644
index 0000000000..c31c64e862
--- /dev/null
+++ b/thirdparty/embree/kernels/common/stack_item.h
@@ -0,0 +1,125 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+
+namespace embree
+{
+ /*! An item on the stack holds the node ID and distance of that node. */
+ template<typename T>
+ struct __aligned(16) StackItemT
+ {
+ /*! assert that the xchg function works */
+ static_assert(sizeof(T) <= 12, "sizeof(T) <= 12 failed");
+
+ __forceinline StackItemT() {}
+
+ __forceinline StackItemT(T &ptr, unsigned &dist) : ptr(ptr), dist(dist) {}
+
+ /*! use SSE instructions to swap stack items */
+ __forceinline static void xchg(StackItemT& a, StackItemT& b)
+ {
+ const vfloat4 sse_a = vfloat4::load((float*)&a);
+ const vfloat4 sse_b = vfloat4::load((float*)&b);
+ vfloat4::store(&a,sse_b);
+ vfloat4::store(&b,sse_a);
+ }
+
+ /*! Sort 2 stack items. */
+ __forceinline friend void sort(StackItemT& s1, StackItemT& s2) {
+ if (s2.dist < s1.dist) xchg(s2,s1);
+ }
+
+ /*! Sort 3 stack items. */
+ __forceinline friend void sort(StackItemT& s1, StackItemT& s2, StackItemT& s3)
+ {
+ if (s2.dist < s1.dist) xchg(s2,s1);
+ if (s3.dist < s2.dist) xchg(s3,s2);
+ if (s2.dist < s1.dist) xchg(s2,s1);
+ }
+
+ /*! Sort 4 stack items. */
+ __forceinline friend void sort(StackItemT& s1, StackItemT& s2, StackItemT& s3, StackItemT& s4)
+ {
+ if (s2.dist < s1.dist) xchg(s2,s1);
+ if (s4.dist < s3.dist) xchg(s4,s3);
+ if (s3.dist < s1.dist) xchg(s3,s1);
+ if (s4.dist < s2.dist) xchg(s4,s2);
+ if (s3.dist < s2.dist) xchg(s3,s2);
+ }
+
+ /*! use SSE instructions to swap stack items */
+ __forceinline static void cmp_xchg(vint4& a, vint4& b)
+ {
+#if defined(__AVX512VL__)
+ const vboolf4 mask(shuffle<2,2,2,2>(b) < shuffle<2,2,2,2>(a));
+#else
+ const vboolf4 mask0(b < a);
+ const vboolf4 mask(shuffle<2,2,2,2>(mask0));
+#endif
+ const vint4 c = select(mask,b,a);
+ const vint4 d = select(mask,a,b);
+ a = c;
+ b = d;
+ }
+
+ /*! Sort 3 stack items. */
+ __forceinline static void sort3(vint4& s1, vint4& s2, vint4& s3)
+ {
+ cmp_xchg(s2,s1);
+ cmp_xchg(s3,s2);
+ cmp_xchg(s2,s1);
+ }
+
+ /*! Sort 4 stack items. */
+ __forceinline static void sort4(vint4& s1, vint4& s2, vint4& s3, vint4& s4)
+ {
+ cmp_xchg(s2,s1);
+ cmp_xchg(s4,s3);
+ cmp_xchg(s3,s1);
+ cmp_xchg(s4,s2);
+ cmp_xchg(s3,s2);
+ }
+
+
+ /*! Sort N stack items. */
+ __forceinline friend void sort(StackItemT* begin, StackItemT* end)
+ {
+ for (StackItemT* i = begin+1; i != end; ++i)
+ {
+ const vfloat4 item = vfloat4::load((float*)i);
+ const unsigned dist = i->dist;
+ StackItemT* j = i;
+
+ while ((j != begin) && ((j-1)->dist < dist))
+ {
+ vfloat4::store(j, vfloat4::load((float*)(j-1)));
+ --j;
+ }
+
+ vfloat4::store(j, item);
+ }
+ }
+
+ public:
+ T ptr;
+ unsigned dist;
+ };
+
+ /*! An item on the stack holds the node ID and active ray mask. */
+ template<typename T>
+ struct __aligned(8) StackItemMaskT
+ {
+ T ptr;
+ size_t mask;
+ };
+
+ struct __aligned(8) StackItemMaskCoherent
+ {
+ size_t mask;
+ size_t parent;
+ size_t child;
+ };
+}
diff --git a/thirdparty/embree/kernels/common/stat.cpp b/thirdparty/embree/kernels/common/stat.cpp
new file mode 100644
index 0000000000..ebb77cd534
--- /dev/null
+++ b/thirdparty/embree/kernels/common/stat.cpp
@@ -0,0 +1,128 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "stat.h"
+
+namespace embree
+{
+ Stat Stat::instance;
+
+ Stat::Stat () {
+ }
+
+ Stat::~Stat ()
+ {
+#ifdef EMBREE_STAT_COUNTERS
+ Stat::print(std::cout);
+#endif
+ }
+
+ void Stat::print(std::ostream& cout)
+ {
+ Counters& cntrs = instance.cntrs;
+ Counters::Data& data = instance.cntrs.code;
+ //Counters::Data& data = instance.cntrs.active;
+
+ /* print absolute numbers */
+ cout << "--------- ABSOLUTE ---------" << std::endl;
+ cout << " #normal_travs = " << float(data.normal.travs )*1E-6 << "M" << std::endl;
+ cout << " #nodes = " << float(data.normal.trav_nodes )*1E-6 << "M" << std::endl;
+ cout << " #nodes_xfm = " << float(data.normal.trav_xfm_nodes )*1E-6 << "M" << std::endl;
+ cout << " #leaves = " << float(data.normal.trav_leaves )*1E-6 << "M" << std::endl;
+ cout << " #prims = " << float(data.normal.trav_prims )*1E-6 << "M" << std::endl;
+ cout << " #prim_hits = " << float(data.normal.trav_prim_hits )*1E-6 << "M" << std::endl;
+
+ cout << " #stack nodes = " << float(data.normal.trav_stack_nodes )*1E-6 << "M" << std::endl;
+ cout << " #stack pop = " << float(data.normal.trav_stack_pop )*1E-6 << "M" << std::endl;
+
+ size_t normal_box_hits = 0;
+ size_t weighted_box_hits = 0;
+ for (size_t i=0;i<SIZE_HISTOGRAM;i++) {
+ normal_box_hits += data.normal.trav_hit_boxes[i];
+ weighted_box_hits += data.normal.trav_hit_boxes[i]*i;
+ }
+ cout << " #hit_boxes = " << normal_box_hits << " (total) distribution: ";
+ float average = 0.0f;
+ for (size_t i=0;i<SIZE_HISTOGRAM;i++)
+ {
+ float value = 100.0f * data.normal.trav_hit_boxes[i] / normal_box_hits;
+ cout << "[" << i << "] " << value << " ";
+ average += (float)i*data.normal.trav_hit_boxes[i] / normal_box_hits;
+ }
+ cout << " average = " << average << std::endl;
+ for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.normal.trav_hit_boxes[i]*i / weighted_box_hits << " ";
+ cout << std::endl;
+
+ if (data.shadow.travs) {
+ cout << " #shadow_travs = " << float(data.shadow.travs )*1E-6 << "M" << std::endl;
+ cout << " #nodes = " << float(data.shadow.trav_nodes )*1E-6 << "M" << std::endl;
+ cout << " #nodes_xfm = " << float(data.shadow.trav_xfm_nodes)*1E-6 << "M" << std::endl;
+ cout << " #leaves = " << float(data.shadow.trav_leaves )*1E-6 << "M" << std::endl;
+ cout << " #prims = " << float(data.shadow.trav_prims )*1E-6 << "M" << std::endl;
+ cout << " #prim_hits = " << float(data.shadow.trav_prim_hits)*1E-6 << "M" << std::endl;
+
+ cout << " #stack nodes = " << float(data.shadow.trav_stack_nodes )*1E-6 << "M" << std::endl;
+ cout << " #stack pop = " << float(data.shadow.trav_stack_pop )*1E-6 << "M" << std::endl;
+
+ size_t shadow_box_hits = 0;
+ size_t weighted_shadow_box_hits = 0;
+
+ for (size_t i=0;i<SIZE_HISTOGRAM;i++) {
+ shadow_box_hits += data.shadow.trav_hit_boxes[i];
+ weighted_shadow_box_hits += data.shadow.trav_hit_boxes[i]*i;
+ }
+ cout << " #hit_boxes = ";
+ for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.shadow.trav_hit_boxes[i] / shadow_box_hits << " ";
+ cout << std::endl;
+ for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.shadow.trav_hit_boxes[i]*i / weighted_shadow_box_hits << " ";
+ cout << std::endl;
+ }
+ cout << std::endl;
+
+ /* print per traversal numbers */
+ cout << "--------- PER TRAVERSAL ---------" << std::endl;
+ float active_normal_travs = float(cntrs.active.normal.travs )/float(cntrs.all.normal.travs );
+ float active_normal_trav_nodes = float(cntrs.active.normal.trav_nodes )/float(cntrs.all.normal.trav_nodes );
+ float active_normal_trav_xfm_nodes = float(cntrs.active.normal.trav_xfm_nodes )/float(cntrs.all.normal.trav_xfm_nodes );
+ float active_normal_trav_leaves = float(cntrs.active.normal.trav_leaves)/float(cntrs.all.normal.trav_leaves);
+ float active_normal_trav_prims = float(cntrs.active.normal.trav_prims )/float(cntrs.all.normal.trav_prims );
+ float active_normal_trav_prim_hits = float(cntrs.active.normal.trav_prim_hits )/float(cntrs.all.normal.trav_prim_hits );
+ float active_normal_trav_stack_pop = float(cntrs.active.normal.trav_stack_pop )/float(cntrs.all.normal.trav_stack_pop );
+
+ cout << " #normal_travs = " << float(cntrs.code.normal.travs )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_travs << "% active" << std::endl;
+ cout << " #nodes = " << float(cntrs.code.normal.trav_nodes )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_nodes << "% active" << std::endl;
+ cout << " #node_xfm = " << float(cntrs.code.normal.trav_xfm_nodes )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_xfm_nodes << "% active" << std::endl;
+ cout << " #leaves = " << float(cntrs.code.normal.trav_leaves)/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_leaves << "% active" << std::endl;
+ cout << " #prims = " << float(cntrs.code.normal.trav_prims )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_prims << "% active" << std::endl;
+ cout << " #prim_hits = " << float(cntrs.code.normal.trav_prim_hits )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_prim_hits << "% active" << std::endl;
+ cout << " #stack_pop = " << float(cntrs.code.normal.trav_stack_pop )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_stack_pop << "% active" << std::endl;
+
+ if (cntrs.all.shadow.travs) {
+ float active_shadow_travs = float(cntrs.active.shadow.travs )/float(cntrs.all.shadow.travs );
+ float active_shadow_trav_nodes = float(cntrs.active.shadow.trav_nodes )/float(cntrs.all.shadow.trav_nodes );
+ float active_shadow_trav_xfm_nodes = float(cntrs.active.shadow.trav_xfm_nodes )/float(cntrs.all.shadow.trav_xfm_nodes );
+ float active_shadow_trav_leaves = float(cntrs.active.shadow.trav_leaves)/float(cntrs.all.shadow.trav_leaves);
+ float active_shadow_trav_prims = float(cntrs.active.shadow.trav_prims )/float(cntrs.all.shadow.trav_prims );
+ float active_shadow_trav_prim_hits = float(cntrs.active.shadow.trav_prim_hits )/float(cntrs.all.shadow.trav_prim_hits );
+
+ cout << " #shadow_travs = " << float(cntrs.code.shadow.travs )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_travs << "% active" << std::endl;
+ cout << " #nodes = " << float(cntrs.code.shadow.trav_nodes )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_nodes << "% active" << std::endl;
+ cout << " #nodes_xfm = " << float(cntrs.code.shadow.trav_xfm_nodes )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_xfm_nodes << "% active" << std::endl;
+ cout << " #leaves = " << float(cntrs.code.shadow.trav_leaves)/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_leaves << "% active" << std::endl;
+ cout << " #prims = " << float(cntrs.code.shadow.trav_prims )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_prims << "% active" << std::endl;
+ cout << " #prim_hits = " << float(cntrs.code.shadow.trav_prim_hits )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_prim_hits << "% active" << std::endl;
+
+ }
+ cout << std::endl;
+
+ /* print user counters for performance tuning */
+ cout << "--------- USER ---------" << std::endl;
+ for (size_t i=0; i<10; i++)
+ cout << "#user" << i << " = " << float(cntrs.user[i])/float(cntrs.all.normal.travs+cntrs.all.shadow.travs) << " per traversal" << std::endl;
+
+ cout << "#user5/user3 " << 100.0f*float(cntrs.user[5])/float(cntrs.user[3]) << "%" << std::endl;
+ cout << "#user6/user3 " << 100.0f*float(cntrs.user[6])/float(cntrs.user[3]) << "%" << std::endl;
+ cout << "#user7/user3 " << 100.0f*float(cntrs.user[7])/float(cntrs.user[3]) << "%" << std::endl;
+ cout << std::endl;
+ }
+}
diff --git a/thirdparty/embree/kernels/common/stat.h b/thirdparty/embree/kernels/common/stat.h
new file mode 100644
index 0000000000..02fc07e67f
--- /dev/null
+++ b/thirdparty/embree/kernels/common/stat.h
@@ -0,0 +1,116 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+
+/* Macros to gather statistics */
+#ifdef EMBREE_STAT_COUNTERS
+# define STAT(x) x
+# define STAT3(s,x,y,z) \
+ STAT(Stat::get().code .s+=x); \
+ STAT(Stat::get().active.s+=y); \
+ STAT(Stat::get().all .s+=z);
+# define STAT_USER(i,x) Stat::get().user[i]+=x;
+#else
+# define STAT(x)
+# define STAT3(s,x,y,z)
+# define STAT_USER(i,x)
+#endif
+
+namespace embree
+{
+ /*! Gathers ray tracing statistics. We count 1) how often a code
+ * location is reached, 2) how many SIMD lanes are active, 3) how
+ * many SIMD lanes reach the code location */
+ class Stat
+ {
+ public:
+
+ static const size_t SIZE_HISTOGRAM = 64+1;
+
+ /*! constructs stat counter class */
+ Stat ();
+
+ /*! destructs stat counter class */
+ ~Stat ();
+
+ class Counters
+ {
+ public:
+ Counters () {
+ clear();
+ }
+
+ void clear()
+ {
+ all.clear();
+ active.clear();
+ code.clear();
+ for (auto& u : user) u.store(0);
+ }
+
+ public:
+
+ /* per packet and per ray stastics */
+ struct Data
+ {
+ void clear () {
+ normal.clear();
+ shadow.clear();
+ point_query.clear();
+ }
+
+ /* normal and shadow ray statistics */
+ struct
+ {
+ void clear()
+ {
+ travs.store(0);
+ trav_nodes.store(0);
+ trav_leaves.store(0);
+ trav_prims.store(0);
+ trav_prim_hits.store(0);
+ for (auto& v : trav_hit_boxes) v.store(0);
+ trav_stack_pop.store(0);
+ trav_stack_nodes.store(0);
+ trav_xfm_nodes.store(0);
+ }
+
+ public:
+ std::atomic<size_t> travs;
+ std::atomic<size_t> trav_nodes;
+ std::atomic<size_t> trav_leaves;
+ std::atomic<size_t> trav_prims;
+ std::atomic<size_t> trav_prim_hits;
+ std::atomic<size_t> trav_hit_boxes[SIZE_HISTOGRAM+1];
+ std::atomic<size_t> trav_stack_pop;
+ std::atomic<size_t> trav_stack_nodes;
+ std::atomic<size_t> trav_xfm_nodes;
+
+ } normal, shadow, point_query;
+ } all, active, code;
+
+ std::atomic<size_t> user[10];
+ };
+
+ public:
+
+ static __forceinline Counters& get() {
+ return instance.cntrs;
+ }
+
+ static void clear() {
+ instance.cntrs.clear();
+ }
+
+ static void print(embree_ostream cout);
+
+ private:
+ Counters cntrs;
+
+ private:
+ static Stat instance;
+ };
+}
diff --git a/thirdparty/embree/kernels/common/state.cpp b/thirdparty/embree/kernels/common/state.cpp
new file mode 100644
index 0000000000..01c862da0c
--- /dev/null
+++ b/thirdparty/embree/kernels/common/state.cpp
@@ -0,0 +1,519 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "state.h"
+#include "../../common/lexers/streamfilters.h"
+
+namespace embree
+{
+ MutexSys g_printMutex;
+
+ State::ErrorHandler State::g_errorHandler;
+
+ State::ErrorHandler::ErrorHandler()
+ : thread_error(createTls()) {}
+
+ State::ErrorHandler::~ErrorHandler()
+ {
+ Lock<MutexSys> lock(errors_mutex);
+ for (size_t i=0; i<thread_errors.size(); i++)
+ delete thread_errors[i];
+ destroyTls(thread_error);
+ thread_errors.clear();
+ }
+
+ RTCError* State::ErrorHandler::error()
+ {
+ RTCError* stored_error = (RTCError*) getTls(thread_error);
+ if (stored_error) return stored_error;
+
+ Lock<MutexSys> lock(errors_mutex);
+ stored_error = new RTCError(RTC_ERROR_NONE);
+ thread_errors.push_back(stored_error);
+ setTls(thread_error,stored_error);
+ return stored_error;
+ }
+
+ State::State ()
+ : enabled_cpu_features(getCPUFeatures()),
+ enabled_builder_cpu_features(enabled_cpu_features),
+ frequency_level(FREQUENCY_SIMD256)
+ {
+ tri_accel = "default";
+ tri_builder = "default";
+ tri_traverser = "default";
+
+ tri_accel_mb = "default";
+ tri_builder_mb = "default";
+ tri_traverser_mb = "default";
+
+ quad_accel = "default";
+ quad_builder = "default";
+ quad_traverser = "default";
+
+ quad_accel_mb = "default";
+ quad_builder_mb = "default";
+ quad_traverser_mb = "default";
+
+ line_accel = "default";
+ line_builder = "default";
+ line_traverser = "default";
+
+ line_accel_mb = "default";
+ line_builder_mb = "default";
+ line_traverser_mb = "default";
+
+ hair_accel = "default";
+ hair_builder = "default";
+ hair_traverser = "default";
+
+ hair_accel_mb = "default";
+ hair_builder_mb = "default";
+ hair_traverser_mb = "default";
+
+ object_accel = "default";
+ object_builder = "default";
+ object_accel_min_leaf_size = 1;
+ object_accel_max_leaf_size = 1;
+
+ object_accel_mb = "default";
+ object_builder_mb = "default";
+ object_accel_mb_min_leaf_size = 1;
+ object_accel_mb_max_leaf_size = 1;
+
+ max_spatial_split_replications = 1.2f;
+ useSpatialPreSplits = false;
+
+ tessellation_cache_size = 128*1024*1024;
+
+ subdiv_accel = "default";
+ subdiv_accel_mb = "default";
+
+ grid_accel = "default";
+ grid_builder = "default";
+ grid_accel_mb = "default";
+ grid_builder_mb = "default";
+
+ instancing_open_min = 0;
+ instancing_block_size = 0;
+ instancing_open_factor = 8.0f;
+ instancing_open_max_depth = 32;
+ instancing_open_max = 50000000;
+
+ float_exceptions = false;
+ quality_flags = -1;
+ scene_flags = -1;
+ verbose = 0;
+ benchmark = 0;
+
+ numThreads = 0;
+ numUserThreads = 0;
+
+#if TASKING_INTERNAL
+ set_affinity = true;
+#else
+ set_affinity = false;
+#endif
+
+ start_threads = false;
+ enable_selockmemoryprivilege = false;
+#if defined(__LINUX__)
+ hugepages = true;
+#else
+ hugepages = false;
+#endif
+ hugepages_success = true;
+
+ alloc_main_block_size = 0;
+ alloc_num_main_slots = 0;
+ alloc_thread_block_size = 0;
+ alloc_single_thread_alloc = -1;
+
+ error_function = nullptr;
+ error_function_userptr = nullptr;
+
+ memory_monitor_function = nullptr;
+ memory_monitor_userptr = nullptr;
+ }
+
+ State::~State() {
+ }
+
+ bool State::hasISA(const int isa) {
+ return (enabled_cpu_features & isa) == isa;
+ }
+
+ bool State::checkISASupport() {
+ return (getCPUFeatures() & enabled_cpu_features) == enabled_cpu_features;
+ }
+
+ void State::verify()
+ {
+ /* verify that calculations stay in range */
+ assert(rcp(min_rcp_input)*FLT_LARGE+FLT_LARGE < 0.01f*FLT_MAX);
+
+ /* here we verify that CPP files compiled for a specific ISA only
+ * call that same or lower ISA version of non-inlined class member
+ * functions */
+#if defined(DEBUG)
+#if defined(EMBREE_TARGET_SSE2)
+ assert(sse2::getISA() <= SSE2);
+#endif
+#if defined(EMBREE_TARGET_SSE42)
+ assert(sse42::getISA() <= SSE42);
+#endif
+#if defined(EMBREE_TARGET_AVX)
+ assert(avx::getISA() <= AVX);
+#endif
+#if defined(EMBREE_TARGET_AVX2)
+ assert(avx2::getISA() <= AVX2);
+#endif
+#if defined (EMBREE_TARGET_AVX512)
+ assert(avx512::getISA() <= AVX512);
+#endif
+#endif
+ }
+
+ const char* symbols[3] = { "=", ",", "|" };
+
+ bool State::parseFile(const FileName& fileName)
+ {
+ FILE* f = fopen(fileName.c_str(),"r");
+ if (!f) return false;
+ Ref<Stream<int> > file = new FileStream(f,fileName);
+
+ std::vector<std::string> syms;
+ for (size_t i=0; i<sizeof(symbols)/sizeof(void*); i++)
+ syms.push_back(symbols[i]);
+
+ Ref<TokenStream> cin = new TokenStream(new LineCommentFilter(file,"#"),
+ TokenStream::alpha+TokenStream::ALPHA+TokenStream::numbers+"_.",
+ TokenStream::separators,syms);
+ parse(cin);
+ return true;
+ }
+
+ void State::parseString(const char* cfg)
+ {
+ if (cfg == nullptr) return;
+
+ std::vector<std::string> syms;
+ for (size_t i=0; i<sizeof(symbols)/sizeof(void*); i++)
+ syms.push_back(symbols[i]);
+
+ Ref<TokenStream> cin = new TokenStream(new StrStream(cfg),
+ TokenStream::alpha+TokenStream::ALPHA+TokenStream::numbers+"_.",
+ TokenStream::separators,syms);
+ parse(cin);
+ }
+
+ int string_to_cpufeatures(const std::string& isa)
+ {
+ if (isa == "sse" ) return SSE;
+ else if (isa == "sse2") return SSE2;
+ else if (isa == "sse3") return SSE3;
+ else if (isa == "ssse3") return SSSE3;
+ else if (isa == "sse41") return SSE41;
+ else if (isa == "sse4.1") return SSE41;
+ else if (isa == "sse42") return SSE42;
+ else if (isa == "sse4.2") return SSE42;
+ else if (isa == "avx") return AVX;
+ else if (isa == "avxi") return AVXI;
+ else if (isa == "avx2") return AVX2;
+ else if (isa == "avx512") return AVX512;
+ else return SSE2;
+ }
+
+ void State::parse(Ref<TokenStream> cin)
+ {
+ /* parse until end of stream */
+ while (cin->peek() != Token::Eof())
+ {
+ const Token tok = cin->get();
+
+ if (tok == Token::Id("threads") && cin->trySymbol("="))
+ numThreads = cin->get().Int();
+
+ else if (tok == Token::Id("user_threads")&& cin->trySymbol("="))
+ numUserThreads = cin->get().Int();
+
+ else if (tok == Token::Id("set_affinity")&& cin->trySymbol("="))
+ set_affinity = cin->get().Int();
+
+ else if (tok == Token::Id("affinity")&& cin->trySymbol("="))
+ set_affinity = cin->get().Int();
+
+ else if (tok == Token::Id("start_threads")&& cin->trySymbol("="))
+ start_threads = cin->get().Int();
+
+ else if (tok == Token::Id("isa") && cin->trySymbol("=")) {
+ std::string isa_str = toLowerCase(cin->get().Identifier());
+ enabled_cpu_features = string_to_cpufeatures(isa_str);
+ enabled_builder_cpu_features = enabled_cpu_features;
+ }
+
+ else if (tok == Token::Id("max_isa") && cin->trySymbol("=")) {
+ std::string isa_str = toLowerCase(cin->get().Identifier());
+ enabled_cpu_features &= string_to_cpufeatures(isa_str);
+ enabled_builder_cpu_features &= enabled_cpu_features;
+ }
+
+ else if (tok == Token::Id("max_builder_isa") && cin->trySymbol("=")) {
+ std::string isa_str = toLowerCase(cin->get().Identifier());
+ enabled_builder_cpu_features &= string_to_cpufeatures(isa_str);
+ }
+
+ else if (tok == Token::Id("frequency_level") && cin->trySymbol("=")) {
+ std::string freq = cin->get().Identifier();
+ if (freq == "simd128") frequency_level = FREQUENCY_SIMD128;
+ else if (freq == "simd256") frequency_level = FREQUENCY_SIMD256;
+ else if (freq == "simd512") frequency_level = FREQUENCY_SIMD512;
+ }
+
+ else if (tok == Token::Id("enable_selockmemoryprivilege") && cin->trySymbol("=")) {
+ enable_selockmemoryprivilege = cin->get().Int();
+ }
+ else if (tok == Token::Id("hugepages") && cin->trySymbol("=")) {
+ hugepages = cin->get().Int();
+ }
+
+ else if (tok == Token::Id("float_exceptions") && cin->trySymbol("="))
+ float_exceptions = cin->get().Int();
+
+ else if ((tok == Token::Id("tri_accel") || tok == Token::Id("accel")) && cin->trySymbol("="))
+ tri_accel = cin->get().Identifier();
+ else if ((tok == Token::Id("tri_builder") || tok == Token::Id("builder")) && cin->trySymbol("="))
+ tri_builder = cin->get().Identifier();
+ else if ((tok == Token::Id("tri_traverser") || tok == Token::Id("traverser")) && cin->trySymbol("="))
+ tri_traverser = cin->get().Identifier();
+
+ else if ((tok == Token::Id("tri_accel_mb") || tok == Token::Id("accel_mb")) && cin->trySymbol("="))
+ tri_accel_mb = cin->get().Identifier();
+ else if ((tok == Token::Id("tri_builder_mb") || tok == Token::Id("builder_mb")) && cin->trySymbol("="))
+ tri_builder_mb = cin->get().Identifier();
+ else if ((tok == Token::Id("tri_traverser_mb") || tok == Token::Id("traverser_mb")) && cin->trySymbol("="))
+ tri_traverser_mb = cin->get().Identifier();
+
+ else if ((tok == Token::Id("quad_accel")) && cin->trySymbol("="))
+ quad_accel = cin->get().Identifier();
+ else if ((tok == Token::Id("quad_builder")) && cin->trySymbol("="))
+ quad_builder = cin->get().Identifier();
+ else if ((tok == Token::Id("quad_traverser")) && cin->trySymbol("="))
+ quad_traverser = cin->get().Identifier();
+
+ else if ((tok == Token::Id("quad_accel_mb")) && cin->trySymbol("="))
+ quad_accel_mb = cin->get().Identifier();
+ else if ((tok == Token::Id("quad_builder_mb")) && cin->trySymbol("="))
+ quad_builder_mb = cin->get().Identifier();
+ else if ((tok == Token::Id("quad_traverser_mb")) && cin->trySymbol("="))
+ quad_traverser_mb = cin->get().Identifier();
+
+ else if ((tok == Token::Id("line_accel")) && cin->trySymbol("="))
+ line_accel = cin->get().Identifier();
+ else if ((tok == Token::Id("line_builder")) && cin->trySymbol("="))
+ line_builder = cin->get().Identifier();
+ else if ((tok == Token::Id("line_traverser")) && cin->trySymbol("="))
+ line_traverser = cin->get().Identifier();
+
+ else if ((tok == Token::Id("line_accel_mb")) && cin->trySymbol("="))
+ line_accel_mb = cin->get().Identifier();
+ else if ((tok == Token::Id("line_builder_mb")) && cin->trySymbol("="))
+ line_builder_mb = cin->get().Identifier();
+ else if ((tok == Token::Id("line_traverser_mb")) && cin->trySymbol("="))
+ line_traverser_mb = cin->get().Identifier();
+
+ else if (tok == Token::Id("hair_accel") && cin->trySymbol("="))
+ hair_accel = cin->get().Identifier();
+ else if (tok == Token::Id("hair_builder") && cin->trySymbol("="))
+ hair_builder = cin->get().Identifier();
+ else if (tok == Token::Id("hair_traverser") && cin->trySymbol("="))
+ hair_traverser = cin->get().Identifier();
+
+ else if (tok == Token::Id("hair_accel_mb") && cin->trySymbol("="))
+ hair_accel_mb = cin->get().Identifier();
+ else if (tok == Token::Id("hair_builder_mb") && cin->trySymbol("="))
+ hair_builder_mb = cin->get().Identifier();
+ else if (tok == Token::Id("hair_traverser_mb") && cin->trySymbol("="))
+ hair_traverser_mb = cin->get().Identifier();
+
+ else if (tok == Token::Id("object_accel") && cin->trySymbol("="))
+ object_accel = cin->get().Identifier();
+ else if (tok == Token::Id("object_builder") && cin->trySymbol("="))
+ object_builder = cin->get().Identifier();
+ else if (tok == Token::Id("object_accel_min_leaf_size") && cin->trySymbol("="))
+ object_accel_min_leaf_size = cin->get().Int();
+ else if (tok == Token::Id("object_accel_max_leaf_size") && cin->trySymbol("="))
+ object_accel_max_leaf_size = cin->get().Int();
+
+ else if (tok == Token::Id("object_accel_mb") && cin->trySymbol("="))
+ object_accel_mb = cin->get().Identifier();
+ else if (tok == Token::Id("object_builder_mb") && cin->trySymbol("="))
+ object_builder_mb = cin->get().Identifier();
+ else if (tok == Token::Id("object_accel_mb_min_leaf_size") && cin->trySymbol("="))
+ object_accel_mb_min_leaf_size = cin->get().Int();
+ else if (tok == Token::Id("object_accel_mb_max_leaf_size") && cin->trySymbol("="))
+ object_accel_mb_max_leaf_size = cin->get().Int();
+
+ else if (tok == Token::Id("instancing_open_min") && cin->trySymbol("="))
+ instancing_open_min = cin->get().Int();
+ else if (tok == Token::Id("instancing_block_size") && cin->trySymbol("=")) {
+ instancing_block_size = cin->get().Int();
+ instancing_open_factor = 0.0f;
+ }
+ else if (tok == Token::Id("instancing_open_max_depth") && cin->trySymbol("="))
+ instancing_open_max_depth = cin->get().Int();
+ else if (tok == Token::Id("instancing_open_factor") && cin->trySymbol("=")) {
+ instancing_block_size = 0;
+ instancing_open_factor = cin->get().Float();
+ }
+ else if (tok == Token::Id("instancing_open_max") && cin->trySymbol("="))
+ instancing_open_max = cin->get().Int();
+
+ else if (tok == Token::Id("subdiv_accel") && cin->trySymbol("="))
+ subdiv_accel = cin->get().Identifier();
+ else if (tok == Token::Id("subdiv_accel_mb") && cin->trySymbol("="))
+ subdiv_accel_mb = cin->get().Identifier();
+
+ else if (tok == Token::Id("grid_accel") && cin->trySymbol("="))
+ grid_accel = cin->get().Identifier();
+ else if (tok == Token::Id("grid_accel_mb") && cin->trySymbol("="))
+ grid_accel_mb = cin->get().Identifier();
+
+ else if (tok == Token::Id("verbose") && cin->trySymbol("="))
+ verbose = cin->get().Int();
+ else if (tok == Token::Id("benchmark") && cin->trySymbol("="))
+ benchmark = cin->get().Int();
+
+ else if (tok == Token::Id("quality")) {
+ if (cin->trySymbol("=")) {
+ Token flag = cin->get();
+ if (flag == Token::Id("low")) quality_flags = RTC_BUILD_QUALITY_LOW;
+ else if (flag == Token::Id("medium")) quality_flags = RTC_BUILD_QUALITY_MEDIUM;
+ else if (flag == Token::Id("high")) quality_flags = RTC_BUILD_QUALITY_HIGH;
+ }
+ }
+
+ else if (tok == Token::Id("scene_flags")) {
+ scene_flags = 0;
+ if (cin->trySymbol("=")) {
+ do {
+ Token flag = cin->get();
+ if (flag == Token::Id("dynamic") ) scene_flags |= RTC_SCENE_FLAG_DYNAMIC;
+ else if (flag == Token::Id("compact")) scene_flags |= RTC_SCENE_FLAG_COMPACT;
+ else if (flag == Token::Id("robust")) scene_flags |= RTC_SCENE_FLAG_ROBUST;
+ } while (cin->trySymbol("|"));
+ }
+ }
+
+ else if (tok == Token::Id("max_spatial_split_replications") && cin->trySymbol("="))
+ max_spatial_split_replications = cin->get().Float();
+
+ else if (tok == Token::Id("presplits") && cin->trySymbol("="))
+ useSpatialPreSplits = cin->get().Int() != 0 ? true : false;
+
+ else if (tok == Token::Id("tessellation_cache_size") && cin->trySymbol("="))
+ tessellation_cache_size = size_t(cin->get().Float()*1024.0f*1024.0f);
+ else if (tok == Token::Id("cache_size") && cin->trySymbol("="))
+ tessellation_cache_size = size_t(cin->get().Float()*1024.0f*1024.0f);
+
+ else if (tok == Token::Id("alloc_main_block_size") && cin->trySymbol("="))
+ alloc_main_block_size = cin->get().Int();
+ else if (tok == Token::Id("alloc_num_main_slots") && cin->trySymbol("="))
+ alloc_num_main_slots = cin->get().Int();
+ else if (tok == Token::Id("alloc_thread_block_size") && cin->trySymbol("="))
+ alloc_thread_block_size = cin->get().Int();
+ else if (tok == Token::Id("alloc_single_thread_alloc") && cin->trySymbol("="))
+ alloc_single_thread_alloc = cin->get().Int();
+
+ cin->trySymbol(","); // optional , separator
+ }
+ }
+
+ bool State::verbosity(size_t N) {
+ return N <= verbose;
+ }
+
+ void State::print()
+ {
+ std::cout << "general:" << std::endl;
+ std::cout << " build threads = " << numThreads << std::endl;
+ std::cout << " build user threads = " << numUserThreads << std::endl;
+ std::cout << " start_threads = " << start_threads << std::endl;
+ std::cout << " affinity = " << set_affinity << std::endl;
+ std::cout << " frequency_level = ";
+ switch (frequency_level) {
+ case FREQUENCY_SIMD128: std::cout << "simd128" << std::endl; break;
+ case FREQUENCY_SIMD256: std::cout << "simd256" << std::endl; break;
+ case FREQUENCY_SIMD512: std::cout << "simd512" << std::endl; break;
+ default: std::cout << "error" << std::endl; break;
+ }
+
+ std::cout << " hugepages = ";
+ if (!hugepages) std::cout << "disabled" << std::endl;
+ else if (hugepages_success) std::cout << "enabled" << std::endl;
+ else std::cout << "failed" << std::endl;
+
+ std::cout << " verbosity = " << verbose << std::endl;
+ std::cout << " cache_size = " << float(tessellation_cache_size)*1E-6 << " MB" << std::endl;
+ std::cout << " max_spatial_split_replications = " << max_spatial_split_replications << std::endl;
+
+ std::cout << "triangles:" << std::endl;
+ std::cout << " accel = " << tri_accel << std::endl;
+ std::cout << " builder = " << tri_builder << std::endl;
+ std::cout << " traverser = " << tri_traverser << std::endl;
+
+ std::cout << "motion blur triangles:" << std::endl;
+ std::cout << " accel = " << tri_accel_mb << std::endl;
+ std::cout << " builder = " << tri_builder_mb << std::endl;
+ std::cout << " traverser = " << tri_traverser_mb << std::endl;
+
+ std::cout << "quads:" << std::endl;
+ std::cout << " accel = " << quad_accel << std::endl;
+ std::cout << " builder = " << quad_builder << std::endl;
+ std::cout << " traverser = " << quad_traverser << std::endl;
+
+ std::cout << "motion blur quads:" << std::endl;
+ std::cout << " accel = " << quad_accel_mb << std::endl;
+ std::cout << " builder = " << quad_builder_mb << std::endl;
+ std::cout << " traverser = " << quad_traverser_mb << std::endl;
+
+ std::cout << "line segments:" << std::endl;
+ std::cout << " accel = " << line_accel << std::endl;
+ std::cout << " builder = " << line_builder << std::endl;
+ std::cout << " traverser = " << line_traverser << std::endl;
+
+ std::cout << "motion blur line segments:" << std::endl;
+ std::cout << " accel = " << line_accel_mb << std::endl;
+ std::cout << " builder = " << line_builder_mb << std::endl;
+ std::cout << " traverser = " << line_traverser_mb << std::endl;
+
+ std::cout << "hair:" << std::endl;
+ std::cout << " accel = " << hair_accel << std::endl;
+ std::cout << " builder = " << hair_builder << std::endl;
+ std::cout << " traverser = " << hair_traverser << std::endl;
+
+ std::cout << "motion blur hair:" << std::endl;
+ std::cout << " accel = " << hair_accel_mb << std::endl;
+ std::cout << " builder = " << hair_builder_mb << std::endl;
+ std::cout << " traverser = " << hair_traverser_mb << std::endl;
+
+ std::cout << "subdivision surfaces:" << std::endl;
+ std::cout << " accel = " << subdiv_accel << std::endl;
+
+ std::cout << "grids:" << std::endl;
+ std::cout << " accel = " << grid_accel << std::endl;
+ std::cout << " builder = " << grid_builder << std::endl;
+
+ std::cout << "motion blur grids:" << std::endl;
+ std::cout << " accel = " << grid_accel_mb << std::endl;
+ std::cout << " builder = " << grid_builder_mb << std::endl;
+
+ std::cout << "object_accel:" << std::endl;
+ std::cout << " min_leaf_size = " << object_accel_min_leaf_size << std::endl;
+ std::cout << " max_leaf_size = " << object_accel_max_leaf_size << std::endl;
+
+ std::cout << "object_accel_mb:" << std::endl;
+ std::cout << " min_leaf_size = " << object_accel_mb_min_leaf_size << std::endl;
+ std::cout << " max_leaf_size = " << object_accel_mb_max_leaf_size << std::endl;
+ }
+}
diff --git a/thirdparty/embree/kernels/common/state.h b/thirdparty/embree/kernels/common/state.h
new file mode 100644
index 0000000000..33bcc843b2
--- /dev/null
+++ b/thirdparty/embree/kernels/common/state.h
@@ -0,0 +1,196 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "default.h"
+
+namespace embree
+{
+ /* mutex to make printing to cout thread safe */
+ extern MutexSys g_printMutex;
+
+ struct State : public RefCount
+ {
+ public:
+ /*! state construction */
+ State ();
+
+ /*! state destruction */
+ ~State();
+
+ /*! verifies that state is correct */
+ void verify();
+
+ /*! parses state from a configuration file */
+ bool parseFile(const FileName& fileName);
+
+ /*! parses the state from a string */
+ void parseString(const char* cfg);
+
+ /*! parses the state from a stream */
+ void parse(Ref<TokenStream> cin);
+
+ /*! prints the state */
+ void print();
+
+ /*! checks if verbosity level is at least N */
+ bool verbosity(size_t N);
+
+ /*! checks if some particular ISA is enabled */
+ bool hasISA(const int isa);
+
+ /*! check whether selected ISA is supported by the HW */
+ bool checkISASupport();
+
+ public:
+ std::string tri_accel; //!< acceleration structure to use for triangles
+ std::string tri_builder; //!< builder to use for triangles
+ std::string tri_traverser; //!< traverser to use for triangles
+
+ public:
+ std::string tri_accel_mb; //!< acceleration structure to use for motion blur triangles
+ std::string tri_builder_mb; //!< builder to use for motion blur triangles
+ std::string tri_traverser_mb; //!< traverser to use for triangles
+
+ public:
+ std::string quad_accel; //!< acceleration structure to use for quads
+ std::string quad_builder; //!< builder to use for quads
+ std::string quad_traverser; //!< traverser to use for quads
+
+ public:
+ std::string quad_accel_mb; //!< acceleration structure to use for motion blur quads
+ std::string quad_builder_mb; //!< builder to use for motion blur quads
+ std::string quad_traverser_mb; //!< traverser to use for motion blur quads
+
+ public:
+ std::string line_accel; //!< acceleration structure to use for line segments
+ std::string line_builder; //!< builder to use for line segments
+ std::string line_traverser; //!< traverser to use for line segments
+
+ public:
+ std::string line_accel_mb; //!< acceleration structure to use for motion blur line segments
+ std::string line_builder_mb; //!< builder to use for motion blur line segments
+ std::string line_traverser_mb; //!< traverser to use for motion blur line segments
+
+ public:
+ std::string hair_accel; //!< hair acceleration structure to use
+ std::string hair_builder; //!< builder to use for hair
+ std::string hair_traverser; //!< traverser to use for hair
+
+ public:
+ std::string hair_accel_mb; //!< acceleration structure to use for motion blur hair
+ std::string hair_builder_mb; //!< builder to use for motion blur hair
+ std::string hair_traverser_mb; //!< traverser to use for motion blur hair
+
+ public:
+ std::string object_accel; //!< acceleration structure for user geometries
+ std::string object_builder; //!< builder for user geometries
+ int object_accel_min_leaf_size; //!< minimum leaf size for object acceleration structure
+ int object_accel_max_leaf_size; //!< maximum leaf size for object acceleration structure
+
+ public:
+ std::string object_accel_mb; //!< acceleration structure for user geometries
+ std::string object_builder_mb; //!< builder for user geometries
+ int object_accel_mb_min_leaf_size; //!< minimum leaf size for mblur object acceleration structure
+ int object_accel_mb_max_leaf_size; //!< maximum leaf size for mblur object acceleration structure
+
+ public:
+ std::string subdiv_accel; //!< acceleration structure to use for subdivision surfaces
+ std::string subdiv_accel_mb; //!< acceleration structure to use for subdivision surfaces
+
+ public:
+ std::string grid_accel; //!< acceleration structure to use for grids
+ std::string grid_builder; //!< builder for grids
+ std::string grid_accel_mb; //!< acceleration structure to use for motion blur grids
+ std::string grid_builder_mb; //!< builder for motion blur grids
+
+ public:
+ float max_spatial_split_replications; //!< maximally replications*N many primitives in accel for spatial splits
+ bool useSpatialPreSplits; //!< use spatial pre-splits instead of the full spatial split builder
+ size_t tessellation_cache_size; //!< size of the shared tessellation cache
+
+ public:
+ size_t instancing_open_min; //!< instancing opens tree to minimally that number of subtrees
+ size_t instancing_block_size; //!< instancing opens tree up to average block size of primitives
+ float instancing_open_factor; //!< instancing opens tree up to x times the number of instances
+ size_t instancing_open_max_depth; //!< maximum open depth for geometries
+ size_t instancing_open_max; //!< instancing opens tree to maximally that number of subtrees
+
+ public:
+ bool float_exceptions; //!< enable floating point exceptions
+ int quality_flags;
+ int scene_flags;
+ size_t verbose; //!< verbosity of output
+ size_t benchmark; //!< true
+
+ public:
+ size_t numThreads; //!< number of threads to use in builders
+ size_t numUserThreads; //!< number of user provided threads to use in builders
+ bool set_affinity; //!< sets affinity for worker threads
+ bool start_threads; //!< true when threads should be started at device creation time
+ int enabled_cpu_features; //!< CPU ISA features to use
+ int enabled_builder_cpu_features; //!< CPU ISA features to use for builders only
+ enum FREQUENCY_LEVEL {
+ FREQUENCY_SIMD128,
+ FREQUENCY_SIMD256,
+ FREQUENCY_SIMD512
+ } frequency_level; //!< frequency level the app wants to run on (default is SIMD256)
+ bool enable_selockmemoryprivilege; //!< configures the SeLockMemoryPrivilege under Windows to enable huge pages
+ bool hugepages; //!< true if huge pages should get used
+ bool hugepages_success; //!< status for enabling huge pages
+
+ public:
+ size_t alloc_main_block_size; //!< main allocation block size (shared between threads)
+ int alloc_num_main_slots; //!< number of such shared blocks to be used to allocate
+ size_t alloc_thread_block_size; //!< size of thread local allocator block size
+ int alloc_single_thread_alloc; //!< in single mode nodes and leaves use same thread local allocator
+
+ public:
+
+ /*! checks if we can use AVX */
+ bool canUseAVX() {
+ return hasISA(AVX) && frequency_level != FREQUENCY_SIMD128;
+ }
+
+ /*! checks if we can use AVX2 */
+ bool canUseAVX2() {
+ return hasISA(AVX2) && frequency_level != FREQUENCY_SIMD128;
+ }
+
+ struct ErrorHandler
+ {
+ public:
+ ErrorHandler();
+ ~ErrorHandler();
+ RTCError* error();
+
+ public:
+ tls_t thread_error;
+ std::vector<RTCError*> thread_errors;
+ MutexSys errors_mutex;
+ };
+ ErrorHandler errorHandler;
+ static ErrorHandler g_errorHandler;
+
+ public:
+ void setErrorFunction(RTCErrorFunction fptr, void* uptr)
+ {
+ error_function = fptr;
+ error_function_userptr = uptr;
+ }
+
+ RTCErrorFunction error_function;
+ void* error_function_userptr;
+
+ public:
+ void setMemoryMonitorFunction(RTCMemoryMonitorFunction fptr, void* uptr)
+ {
+ memory_monitor_function = fptr;
+ memory_monitor_userptr = uptr;
+ }
+
+ RTCMemoryMonitorFunction memory_monitor_function;
+ void* memory_monitor_userptr;
+ };
+}
diff --git a/thirdparty/embree/kernels/common/vector.h b/thirdparty/embree/kernels/common/vector.h
new file mode 100644
index 0000000000..4b08275f3b
--- /dev/null
+++ b/thirdparty/embree/kernels/common/vector.h
@@ -0,0 +1,76 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "default.h"
+
+namespace embree
+{
+ /*! invokes the memory monitor callback */
+ struct MemoryMonitorInterface {
+ virtual void memoryMonitor(ssize_t bytes, bool post) = 0;
+ };
+
+ /*! allocator that performs aligned monitored allocations */
+ template<typename T, size_t alignment = 64>
+ struct aligned_monitored_allocator
+ {
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ __forceinline aligned_monitored_allocator(MemoryMonitorInterface* device)
+ : device(device), hugepages(false) {}
+
+ __forceinline pointer allocate( size_type n )
+ {
+ if (n) {
+ assert(device);
+ device->memoryMonitor(n*sizeof(T),false);
+ }
+ if (n*sizeof(value_type) >= 14 * PAGE_SIZE_2M)
+ {
+ pointer p = (pointer) os_malloc(n*sizeof(value_type),hugepages);
+ assert(p);
+ return p;
+ }
+ return (pointer) alignedMalloc(n*sizeof(value_type),alignment);
+ }
+
+ __forceinline void deallocate( pointer p, size_type n )
+ {
+ if (p)
+ {
+ if (n*sizeof(value_type) >= 14 * PAGE_SIZE_2M)
+ os_free(p,n*sizeof(value_type),hugepages);
+ else
+ alignedFree(p);
+ }
+ else assert(n == 0);
+
+ if (n) {
+ assert(device);
+ device->memoryMonitor(-ssize_t(n)*sizeof(T),true);
+ }
+ }
+
+ __forceinline void construct( pointer p, const_reference val ) {
+ new (p) T(val);
+ }
+
+ __forceinline void destroy( pointer p ) {
+ p->~T();
+ }
+
+ private:
+ MemoryMonitorInterface* device;
+ bool hugepages;
+ };
+
+ /*! monitored vector */
+ template<typename T>
+ using mvector = vector_t<T,aligned_monitored_allocator<T,std::alignment_of<T>::value> >;
+}
diff --git a/thirdparty/embree-aarch64/kernels/config.h b/thirdparty/embree/kernels/config.h
index 80a8ab2a56..80a8ab2a56 100644
--- a/thirdparty/embree-aarch64/kernels/config.h
+++ b/thirdparty/embree/kernels/config.h
diff --git a/thirdparty/embree/kernels/geometry/cone.h b/thirdparty/embree/kernels/geometry/cone.h
new file mode 100644
index 0000000000..17429bab32
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/cone.h
@@ -0,0 +1,321 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct Cone
+ {
+ const Vec3fa p0; //!< start position of cone
+ const Vec3fa p1; //!< end position of cone
+ const float r0; //!< start radius of cone
+ const float r1; //!< end radius of cone
+
+ __forceinline Cone(const Vec3fa& p0, const float r0, const Vec3fa& p1, const float r1)
+ : p0(p0), p1(p1), r0(r0), r1(r1) {}
+
+ __forceinline bool intersect(const Vec3fa& org, const Vec3fa& dir,
+ BBox1f& t_o,
+ float& u0_o, Vec3fa& Ng0_o,
+ float& u1_o, Vec3fa& Ng1_o) const
+ {
+ /* calculate quadratic equation to solve */
+ const Vec3fa v0 = p0-org;
+ const Vec3fa v1 = p1-org;
+
+ const float rl = rcp_length(v1-v0);
+ const Vec3fa P0 = v0, dP = (v1-v0)*rl;
+ const float dr = (r1-r0)*rl;
+ const Vec3fa O = -P0, dO = dir;
+
+ const float dOdO = dot(dO,dO);
+ const float OdO = dot(dO,O);
+ const float OO = dot(O,O);
+ const float dOz = dot(dP,dO);
+ const float Oz = dot(dP,O);
+
+ const float R = r0 + Oz*dr;
+ const float A = dOdO - sqr(dOz) * (1.0f+sqr(dr));
+ const float B = 2.0f * (OdO - dOz*(Oz + R*dr));
+ const float C = OO - (sqr(Oz) + sqr(R));
+
+ /* we miss the cone if determinant is smaller than zero */
+ const float D = B*B - 4.0f*A*C;
+ if (D < 0.0f) return false;
+
+ /* special case for rays that are "parallel" to the cone */
+ const float eps = float(1<<8)*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
+ if (unlikely(abs(A) < eps))
+ {
+ /* cylinder case */
+ if (abs(dr) < 16.0f*float(ulp)) {
+ if (C <= 0.0f) { t_o = BBox1f(neg_inf,pos_inf); return true; }
+ else { t_o = BBox1f(pos_inf,neg_inf); return false; }
+ }
+
+ /* cone case */
+ else
+ {
+ /* if we hit the negative cone there cannot be a hit */
+ const float t = -C/B;
+ const float z0 = Oz+t*dOz;
+ const float z0r = r0+z0*dr;
+ if (z0r < 0.0f) return false;
+
+ /* test if we start inside or outside the cone */
+ if (dOz*dr > 0.0f) t_o = BBox1f(t,pos_inf);
+ else t_o = BBox1f(neg_inf,t);
+ }
+ }
+
+ /* standard case for "non-parallel" rays */
+ else
+ {
+ const float Q = sqrt(D);
+ const float rcp_2A = rcp(2.0f*A);
+ t_o.lower = (-B-Q)*rcp_2A;
+ t_o.upper = (-B+Q)*rcp_2A;
+
+ /* standard case where both hits are on same cone */
+ if (likely(A > 0.0f)) {
+ const float z0 = Oz+t_o.lower*dOz;
+ const float z0r = r0+z0*dr;
+ if (z0r < 0.0f) return false;
+ }
+
+ /* special case where the hits are on the positive and negative cone */
+ else
+ {
+ /* depending on the ray direction and the open direction
+ * of the cone we have a hit from inside or outside the
+ * cone */
+ if (dOz*dr > 0) t_o.upper = pos_inf;
+ else t_o.lower = neg_inf;
+ }
+ }
+
+ /* calculates u and Ng for near hit */
+ {
+ u0_o = (Oz+t_o.lower*dOz)*rl;
+ const Vec3fa Pr = t_o.lower*dir;
+ const Vec3fa Pl = v0 + u0_o*(v1-v0);
+ const Vec3fa R = normalize(Pr-Pl);
+ const Vec3fa U = (p1-p0)+(r1-r0)*R;
+ const Vec3fa V = cross(p1-p0,R);
+ Ng0_o = cross(V,U);
+ }
+
+ /* calculates u and Ng for far hit */
+ {
+ u1_o = (Oz+t_o.upper*dOz)*rl;
+ const Vec3fa Pr = t_o.upper*dir;
+ const Vec3fa Pl = v0 + u1_o*(v1-v0);
+ const Vec3fa R = normalize(Pr-Pl);
+ const Vec3fa U = (p1-p0)+(r1-r0)*R;
+ const Vec3fa V = cross(p1-p0,R);
+ Ng1_o = cross(V,U);
+ }
+ return true;
+ }
+
+ __forceinline bool intersect(const Vec3fa& org, const Vec3fa& dir, BBox1f& t_o) const
+ {
+ float u0_o; Vec3fa Ng0_o; float u1_o; Vec3fa Ng1_o;
+ return intersect(org,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
+ }
+
+ static bool verify(const size_t id, const Cone& cone, const Ray& ray, bool shouldhit, const float t0, const float t1)
+ {
+ float eps = 0.001f;
+ BBox1f t; bool hit;
+ hit = cone.intersect(ray.org,ray.dir,t);
+
+ bool failed = hit != shouldhit;
+ if (shouldhit) failed |= std::isinf(t0) ? t0 != t.lower : (t0 == -1E6) ? t.lower > -1E6f : abs(t0-t.lower) > eps;
+ if (shouldhit) failed |= std::isinf(t1) ? t1 != t.upper : (t1 == +1E6) ? t.upper < +1E6f : abs(t1-t.upper) > eps;
+ if (!failed) return true;
+ embree_cout << "Cone test " << id << " failed: cone = " << cone << ", ray = " << ray << ", hit = " << hit << ", t = " << t << embree_endl;
+ return false;
+ }
+
+ /* verify cone class */
+ static bool verify()
+ {
+ bool passed = true;
+ const Cone cone0(Vec3fa(0.0f,0.0f,0.0f),0.0f,Vec3fa(1.0f,0.0f,0.0f),1.0f);
+ passed &= verify(0,cone0,Ray(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa(+1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,3.0f,pos_inf);
+ passed &= verify(1,cone0,Ray(Vec3fa(+2.0f,1.0f,0.0f),Vec3fa(-1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,1.0f);
+ passed &= verify(2,cone0,Ray(Vec3fa(-1.0f,0.0f,2.0f),Vec3fa(+0.0f,+0.0f,-1.0f),0.0f,float(inf)),false,0.0f,0.0f);
+ passed &= verify(3,cone0,Ray(Vec3fa(+1.0f,0.0f,2.0f),Vec3fa(+0.0f,+0.0f,-1.0f),0.0f,float(inf)),true,1.0f,3.0f);
+ passed &= verify(4,cone0,Ray(Vec3fa(-1.0f,0.0f,0.0f),Vec3fa(+1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,1.0f,pos_inf);
+ passed &= verify(5,cone0,Ray(Vec3fa(+1.0f,0.0f,0.0f),Vec3fa(-1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,1.0f);
+ passed &= verify(6,cone0,Ray(Vec3fa(+0.0f,0.0f,1.0f),Vec3fa(+0.0f,+0.0f,-1.0f),0.0f,float(inf)),true,1.0f,1.0f);
+ passed &= verify(7,cone0,Ray(Vec3fa(+0.0f,1.0f,0.0f),Vec3fa(-1.0f,-1.0f,+0.0f),0.0f,float(inf)),false,0.0f,0.0f);
+ passed &= verify(8,cone0,Ray(Vec3fa(+0.0f,1.0f,0.0f),Vec3fa(+1.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.5f,+1E6);
+ passed &= verify(9,cone0,Ray(Vec3fa(+0.0f,1.0f,0.0f),Vec3fa(-1.0f,+1.0f,+0.0f),0.0f,float(inf)),true,-1E6,-0.5f);
+ const Cone cone1(Vec3fa(0.0f,0.0f,0.0f),1.0f,Vec3fa(1.0f,0.0f,0.0f),0.0f);
+ passed &= verify(10,cone1,Ray(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa(+1.0f,+0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,2.0f);
+ passed &= verify(11,cone1,Ray(Vec3fa(-1.0f,0.0f,2.0f),Vec3fa(+0.0f,+0.0f,-1.0f),0.0f,float(inf)),true,0.0f,4.0f);
+ const Cone cylinder(Vec3fa(0.0f,0.0f,0.0f),1.0f,Vec3fa(1.0f,0.0f,0.0f),1.0f);
+ passed &= verify(12,cylinder,Ray(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
+ passed &= verify(13,cylinder,Ray(Vec3fa(+2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
+ passed &= verify(14,cylinder,Ray(Vec3fa(+2.0f,1.0f,2.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),false,0.0f,0.0f);
+ passed &= verify(15,cylinder,Ray(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
+ passed &= verify(16,cylinder,Ray(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
+ passed &= verify(17,cylinder,Ray(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
+ passed &= verify(18,cylinder,Ray(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
+ return passed;
+ }
+
+ /*! output operator */
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const Cone& c) {
+ return cout << "Cone { p0 = " << c.p0 << ", r0 = " << c.r0 << ", p1 = " << c.p1 << ", r1 = " << c.r1 << "}";
+ }
+ };
+
+ template<int N>
+ struct ConeN
+ {
+ typedef Vec3<vfloat<N>> Vec3vfN;
+
+ const Vec3vfN p0; //!< start position of cone
+ const Vec3vfN p1; //!< end position of cone
+ const vfloat<N> r0; //!< start radius of cone
+ const vfloat<N> r1; //!< end radius of cone
+
+ __forceinline ConeN(const Vec3vfN& p0, const vfloat<N>& r0, const Vec3vfN& p1, const vfloat<N>& r1)
+ : p0(p0), p1(p1), r0(r0), r1(r1) {}
+
+ __forceinline Cone operator[] (const size_t i) const
+ {
+ assert(i<N);
+ return Cone(Vec3fa(p0.x[i],p0.y[i],p0.z[i]),r0[i],Vec3fa(p1.x[i],p1.y[i],p1.z[i]),r1[i]);
+ }
+
+ __forceinline vbool<N> intersect(const Vec3fa& org, const Vec3fa& dir,
+ BBox<vfloat<N>>& t_o,
+ vfloat<N>& u0_o, Vec3vfN& Ng0_o,
+ vfloat<N>& u1_o, Vec3vfN& Ng1_o) const
+ {
+ /* calculate quadratic equation to solve */
+ const Vec3vfN v0 = p0-Vec3vfN(org);
+ const Vec3vfN v1 = p1-Vec3vfN(org);
+
+ const vfloat<N> rl = rcp_length(v1-v0);
+ const Vec3vfN P0 = v0, dP = (v1-v0)*rl;
+ const vfloat<N> dr = (r1-r0)*rl;
+ const Vec3vfN O = -P0, dO = dir;
+
+ const vfloat<N> dOdO = dot(dO,dO);
+ const vfloat<N> OdO = dot(dO,O);
+ const vfloat<N> OO = dot(O,O);
+ const vfloat<N> dOz = dot(dP,dO);
+ const vfloat<N> Oz = dot(dP,O);
+
+ const vfloat<N> R = r0 + Oz*dr;
+ const vfloat<N> A = dOdO - sqr(dOz) * (vfloat<N>(1.0f)+sqr(dr));
+ const vfloat<N> B = 2.0f * (OdO - dOz*(Oz + R*dr));
+ const vfloat<N> C = OO - (sqr(Oz) + sqr(R));
+
+ /* we miss the cone if determinant is smaller than zero */
+ const vfloat<N> D = B*B - 4.0f*A*C;
+ vbool<N> valid = D >= 0.0f;
+ if (none(valid)) return valid;
+
+ /* special case for rays that are "parallel" to the cone */
+ const vfloat<N> eps = float(1<<8)*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
+ const vbool<N> validt = valid & (abs(A) < eps);
+ const vbool<N> validf = valid & !(abs(A) < eps);
+ if (unlikely(any(validt)))
+ {
+ const vboolx validtt = validt & (abs(dr) < 16.0f*float(ulp));
+ const vboolx validtf = validt & (abs(dr) >= 16.0f*float(ulp));
+
+ /* cylinder case */
+ if (unlikely(any(validtt)))
+ {
+ t_o.lower = select(validtt, select(C <= 0.0f, vfloat<N>(neg_inf), vfloat<N>(pos_inf)), t_o.lower);
+ t_o.upper = select(validtt, select(C <= 0.0f, vfloat<N>(pos_inf), vfloat<N>(neg_inf)), t_o.upper);
+ valid &= !validtt | C <= 0.0f;
+ }
+
+ /* cone case */
+ if (any(validtf))
+ {
+ /* if we hit the negative cone there cannot be a hit */
+ const vfloat<N> t = -C/B;
+ const vfloat<N> z0 = Oz+t*dOz;
+ const vfloat<N> z0r = r0+z0*dr;
+ valid &= !validtf | z0r >= 0.0f;
+
+ /* test if we start inside or outside the cone */
+ t_o.lower = select(validtf, select(dOz*dr > 0.0f, t, vfloat<N>(neg_inf)), t_o.lower);
+ t_o.upper = select(validtf, select(dOz*dr > 0.0f, vfloat<N>(pos_inf), t), t_o.upper);
+ }
+ }
+
+ /* standard case for "non-parallel" rays */
+ if (likely(any(validf)))
+ {
+ const vfloat<N> Q = sqrt(D);
+ const vfloat<N> rcp_2A = 0.5f*rcp(A);
+ t_o.lower = select(validf, (-B-Q)*rcp_2A, t_o.lower);
+ t_o.upper = select(validf, (-B+Q)*rcp_2A, t_o.upper);
+
+ /* standard case where both hits are on same cone */
+ const vbool<N> validft = validf & A>0.0f;
+ const vbool<N> validff = validf & !(A>0.0f);
+ if (any(validft)) {
+ const vfloat<N> z0 = Oz+t_o.lower*dOz;
+ const vfloat<N> z0r = r0+z0*dr;
+ valid &= !validft | z0r >= 0.0f;
+ }
+
+ /* special case where the hits are on the positive and negative cone */
+ if (any(validff)) {
+ /* depending on the ray direction and the open direction
+ * of the cone we have a hit from inside or outside the
+ * cone */
+ t_o.lower = select(validff, select(dOz*dr > 0.0f, t_o.lower, float(neg_inf)), t_o.lower);
+ t_o.upper = select(validff, select(dOz*dr > 0.0f, float(pos_inf), t_o.upper), t_o.upper);
+ }
+ }
+
+ /* calculates u and Ng for near hit */
+ {
+ u0_o = (Oz+t_o.lower*dOz)*rl;
+ const Vec3vfN Pr = t_o.lower*Vec3vfN(dir);
+ const Vec3vfN Pl = v0 + u0_o*(v1-v0);
+ const Vec3vfN R = normalize(Pr-Pl);
+ const Vec3vfN U = (p1-p0)+(r1-r0)*R;
+ const Vec3vfN V = cross(p1-p0,R);
+ Ng0_o = cross(V,U);
+ }
+
+ /* calculates u and Ng for far hit */
+ {
+ u1_o = (Oz+t_o.upper*dOz)*rl;
+ const Vec3vfN Pr = t_o.lower*Vec3vfN(dir);
+ const Vec3vfN Pl = v0 + u1_o*(v1-v0);
+ const Vec3vfN R = normalize(Pr-Pl);
+ const Vec3vfN U = (p1-p0)+(r1-r0)*R;
+ const Vec3vfN V = cross(p1-p0,R);
+ Ng1_o = cross(V,U);
+ }
+ return valid;
+ }
+
+ __forceinline vbool<N> intersect(const Vec3fa& org, const Vec3fa& dir, BBox<vfloat<N>>& t_o) const
+ {
+ vfloat<N> u0_o; Vec3vfN Ng0_o; vfloat<N> u1_o; Vec3vfN Ng1_o;
+ return intersect(org,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
+ }
+ };
+ }
+}
+
diff --git a/thirdparty/embree/kernels/geometry/coneline_intersector.h b/thirdparty/embree/kernels/geometry/coneline_intersector.h
new file mode 100644
index 0000000000..90f3792eff
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/coneline_intersector.h
@@ -0,0 +1,209 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "curve_intersector_precalculations.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ namespace __coneline_internal
+ {
+ template<int M, typename Epilog, typename ray_tfar_func>
+ static __forceinline bool intersectCone(const vbool<M>& valid_i,
+ const Vec3vf<M>& ray_org_in, const Vec3vf<M>& ray_dir,
+ const vfloat<M>& ray_tnear, const ray_tfar_func& ray_tfar,
+ const Vec4vf<M>& v0, const Vec4vf<M>& v1,
+ const vbool<M>& cL, const vbool<M>& cR,
+ const Epilog& epilog)
+ {
+ vbool<M> valid = valid_i;
+
+ /* move ray origin closer to make calculations numerically stable */
+ const vfloat<M> dOdO = sqr(ray_dir);
+ const vfloat<M> rcp_dOdO = rcp(dOdO);
+ const Vec3vf<M> center = vfloat<M>(0.5f)*(v0.xyz()+v1.xyz());
+ const vfloat<M> dt = dot(center-ray_org_in,ray_dir)*rcp_dOdO;
+ const Vec3vf<M> ray_org = ray_org_in + dt*ray_dir;
+
+ const Vec3vf<M> dP = v1.xyz() - v0.xyz();
+ const Vec3vf<M> p0 = ray_org - v0.xyz();
+ const Vec3vf<M> p1 = ray_org - v1.xyz();
+
+ const vfloat<M> dPdP = sqr(dP);
+ const vfloat<M> dP0 = dot(p0,dP);
+ const vfloat<M> dP1 = dot(p1,dP);
+ const vfloat<M> dOdP = dot(ray_dir,dP);
+
+ // intersect cone body
+ const vfloat<M> dr = v0.w - v1.w;
+ const vfloat<M> hy = dPdP + sqr(dr);
+ const vfloat<M> dO0 = dot(ray_dir,p0);
+ const vfloat<M> OO = sqr(p0);
+ const vfloat<M> dPdP2 = sqr(dPdP);
+ const vfloat<M> dPdPr0 = dPdP*v0.w;
+
+ const vfloat<M> A = dPdP2 - sqr(dOdP)*hy;
+ const vfloat<M> B = dPdP2*dO0 - dP0*dOdP*hy + dPdPr0*(dr*dOdP);
+ const vfloat<M> C = dPdP2*OO - sqr(dP0)*hy + dPdPr0*(2.0f*dr*dP0 - dPdPr0);
+
+ const vfloat<M> D = B*B - A*C;
+ valid &= D >= 0.0f;
+ if (unlikely(none(valid))) {
+ return false;
+ }
+
+ /* standard case for "non-parallel" rays */
+ const vfloat<M> Q = sqrt(D);
+ const vfloat<M> rcp_A = rcp(A);
+ /* special case for rays that are "parallel" to the cone - assume miss */
+ const vbool<M> isParallel = abs(A) <= min_rcp_input;
+
+ vfloat<M> t_cone_lower = select (isParallel, neg_inf, (-B-Q)*rcp_A);
+ vfloat<M> t_cone_upper = select (isParallel, pos_inf, (-B+Q)*rcp_A);
+ const vfloat<M> y_lower = dP0 + t_cone_lower*dOdP;
+ const vfloat<M> y_upper = dP0 + t_cone_upper*dOdP;
+ t_cone_lower = select(valid & y_lower > 0.0f & y_lower < dPdP, t_cone_lower, pos_inf);
+ t_cone_upper = select(valid & y_upper > 0.0f & y_upper < dPdP, t_cone_upper, neg_inf);
+
+ const vbool<M> hitDisk0 = valid & cL;
+ const vbool<M> hitDisk1 = valid & cR;
+ const vfloat<M> rcp_dOdP = rcp(dOdP);
+ const vfloat<M> t_disk0 = select (hitDisk0, select (sqr(p0*dOdP-ray_dir*dP0)<(sqr(v0.w)*sqr(dOdP)), -dP0*rcp_dOdP, pos_inf), pos_inf);
+ const vfloat<M> t_disk1 = select (hitDisk1, select (sqr(p1*dOdP-ray_dir*dP1)<(sqr(v1.w)*sqr(dOdP)), -dP1*rcp_dOdP, pos_inf), pos_inf);
+ const vfloat<M> t_disk_lower = min(t_disk0, t_disk1);
+ const vfloat<M> t_disk_upper = max(t_disk0, t_disk1);
+
+ const vfloat<M> t_lower = min(t_cone_lower, t_disk_lower);
+ const vfloat<M> t_upper = max(t_cone_upper, select(t_lower==t_disk_lower,
+ select(t_disk_upper==vfloat<M>(pos_inf),neg_inf,t_disk_upper),
+ select(t_disk_lower==vfloat<M>(pos_inf),neg_inf,t_disk_lower)));
+
+ const vbool<M> valid_lower = valid & ray_tnear <= dt+t_lower & dt+t_lower <= ray_tfar() & t_lower != vfloat<M>(pos_inf);
+ const vbool<M> valid_upper = valid & ray_tnear <= dt+t_upper & dt+t_upper <= ray_tfar() & t_upper != vfloat<M>(neg_inf);
+
+ const vbool<M> valid_first = valid_lower | valid_upper;
+ if (unlikely(none(valid_first)))
+ return false;
+
+ const vfloat<M> t_first = select(valid_lower, t_lower, t_upper);
+ const vfloat<M> y_first = select(valid_lower, y_lower, y_upper);
+
+ const vfloat<M> rcp_dPdP = rcp(dPdP);
+ const Vec3vf<M> dP2drr0dP = dPdP*dr*v0.w*dP;
+ const Vec3vf<M> dPhy = dP*hy;
+ const vbool<M> cone_hit_first = valid & (t_first == t_cone_lower | t_first == t_cone_upper);
+ const vbool<M> disk0_hit_first = valid & (t_first == t_disk0);
+ const Vec3vf<M> Ng_first = select(cone_hit_first, dPdP2*(p0+t_first*ray_dir)+dP2drr0dP-dPhy*y_first, select(disk0_hit_first, -dP, dP));
+ const vfloat<M> u_first = select(cone_hit_first, y_first*rcp_dPdP, select(disk0_hit_first, vfloat<M>(zero), vfloat<M>(one)));
+
+ /* invoke intersection filter for first hit */
+ RoundLineIntersectorHitM<M> hit(u_first,zero,dt+t_first,Ng_first);
+ const bool is_hit_first = epilog(valid_first, hit);
+
+ /* check for possible second hits before potentially accepted hit */
+ const vfloat<M> t_second = t_upper;
+ const vfloat<M> y_second = y_upper;
+ const vbool<M> valid_second = valid_lower & valid_upper & (dt+t_upper <= ray_tfar());
+ if (unlikely(none(valid_second)))
+ return is_hit_first;
+
+ /* invoke intersection filter for second hit */
+ const vbool<M> cone_hit_second = t_second == t_cone_lower | t_second == t_cone_upper;
+ const vbool<M> disk0_hit_second = t_second == t_disk0;
+ const Vec3vf<M> Ng_second = select(cone_hit_second, dPdP2*(p0+t_second*ray_dir)+dP2drr0dP-dPhy*y_second, select(disk0_hit_second, -dP, dP));
+ const vfloat<M> u_second = select(cone_hit_second, y_second*rcp_dPdP, select(disk0_hit_first, vfloat<M>(zero), vfloat<M>(one)));
+
+ hit = RoundLineIntersectorHitM<M>(u_second,zero,dt+t_second,Ng_second);
+ const bool is_hit_second = epilog(valid_second, hit);
+
+ return is_hit_first | is_hit_second;
+ }
+ }
+
+ template<int M>
+ struct ConeLineIntersectorHitM
+ {
+ __forceinline ConeLineIntersectorHitM() {}
+
+ __forceinline ConeLineIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
+ : vu(u), vv(v), vt(t), vNg(Ng) {}
+
+ __forceinline void finalize() {}
+
+ __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
+ __forceinline float t (const size_t i) const { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
+
+ public:
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+ };
+
+ template<int M>
+ struct ConeCurveIntersector1
+ {
+ typedef CurvePrecalculations1 Precalculations;
+
+ struct ray_tfar {
+ Ray& ray;
+ __forceinline ray_tfar(Ray& ray) : ray(ray) {}
+ __forceinline vfloat<M> operator() () const { return ray.tfar; };
+ };
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ Ray& ray,
+ IntersectContext* context,
+ const LineSegments* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
+ const vbool<M>& cL, const vbool<M>& cR,
+ const Epilog& epilog)
+ {
+ const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
+ const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
+ const vfloat<M> ray_tnear(ray.tnear());
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec4vf<M> v1 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v1i);
+ return __coneline_internal::intersectCone<M>(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray),v0,v1,cL,cR,epilog);
+ }
+ };
+
+ template<int M, int K>
+ struct ConeCurveIntersectorK
+ {
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ struct ray_tfar {
+ RayK<K>& ray;
+ size_t k;
+ __forceinline ray_tfar(RayK<K>& ray, size_t k) : ray(ray), k(k) {}
+ __forceinline vfloat<M> operator() () const { return ray.tfar[k]; };
+ };
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const LineSegments* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
+ const vbool<M>& cL, const vbool<M>& cR,
+ const Epilog& epilog)
+ {
+ const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
+ const vfloat<M> ray_tnear = ray.tnear()[k];
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec4vf<M> v1 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v1i);
+ return __coneline_internal::intersectCone<M>(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray,k),v0,v1,cL,cR,epilog);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/conelinei_intersector.h b/thirdparty/embree/kernels/geometry/conelinei_intersector.h
new file mode 100644
index 0000000000..6a985ebcad
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/conelinei_intersector.h
@@ -0,0 +1,141 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "coneline_intersector.h"
+#include "intersector_epilog.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M, bool filter>
+ struct ConeCurveMiIntersector1
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1;
+ vbool<M> cL,cR;
+ line.gather(v0,v1,cL,cR,geom);
+ const vbool<M> valid = line.valid();
+ ConeCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Intersect1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1;
+ vbool<M> cL,cR;
+ line.gather(v0,v1,cL,cR,geom);
+ const vbool<M> valid = line.valid();
+ return ConeCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Occluded1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ return false;
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
+ }
+ };
+
+ template<int M, bool filter>
+ struct ConeCurveMiMBIntersector1
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1;
+ vbool<M> cL,cR;
+ line.gather(v0,v1,cL,cR,geom,ray.time());
+ const vbool<M> valid = line.valid();
+ ConeCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Intersect1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1;
+ vbool<M> cL,cR;
+ line.gather(v0,v1,cL,cR,geom,ray.time());
+ const vbool<M> valid = line.valid();
+ return ConeCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Occluded1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ return false;
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct ConeCurveMiIntersectorK
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1;
+ vbool<M> cL,cR;
+ line.gather(v0,v1,cL,cR,geom);
+ const vbool<M> valid = line.valid();
+ ConeCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Intersect1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1;
+ vbool<M> cL,cR;
+ line.gather(v0,v1,cL,cR,geom);
+ const vbool<M> valid = line.valid();
+ return ConeCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Occluded1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct ConeCurveMiMBIntersectorK
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1;
+ vbool<M> cL,cR;
+ line.gather(v0,v1,cL,cR,geom,ray.time()[k]);
+ const vbool<M> valid = line.valid();
+ ConeCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Intersect1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1;
+ vbool<M> cL,cR;
+ line.gather(v0,v1,cL,cR,geom,ray.time()[k]);
+ const vbool<M> valid = line.valid();
+ return ConeCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Occluded1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curveNi.h b/thirdparty/embree/kernels/geometry/curveNi.h
new file mode 100644
index 0000000000..6366a6fb9c
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curveNi.h
@@ -0,0 +1,222 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+#include "curve_intersector_precalculations.h"
+
+namespace embree
+{
+ template<int M>
+ struct CurveNi
+ {
+ struct Type : public PrimitiveType {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* Returns maximum number of stored primitives */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+M-1)/M; }
+
+ static __forceinline size_t bytes(size_t N)
+ {
+ const size_t f = N/M, r = N%M;
+ static_assert(sizeof(CurveNi) == 22+25*M, "internal data layout issue");
+ return f*sizeof(CurveNi) + (r!=0)*(22 + 25*r);
+ }
+
+ public:
+
+ /*! Default constructor. */
+ __forceinline CurveNi () {}
+
+ /*! fill curve from curve list */
+ __forceinline void fill(const PrimRef* prims, size_t& begin, size_t _end, Scene* scene)
+ {
+ size_t end = min(begin+M,_end);
+ N = (unsigned char)(end-begin);
+ const unsigned int geomID0 = prims[begin].geomID();
+ this->geomID(N) = geomID0;
+ ty = (unsigned char) scene->get(geomID0)->getType();
+
+ /* encode all primitives */
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<N; i++)
+ {
+ const PrimRef& prim = prims[begin+i];
+ const unsigned int geomID = prim.geomID(); assert(geomID == geomID0);
+ const unsigned int primID = prim.primID();
+ bounds.extend(scene->get(geomID)->vbounds(primID));
+ }
+
+ /* calculate offset and scale */
+ Vec3fa loffset = bounds.lower;
+ float lscale = reduce_min(256.0f/(bounds.size()*sqrt(3.0f)));
+ if (bounds.size() == Vec3fa(zero)) lscale = 0.0f;
+ *this->offset(N) = loffset;
+ *this->scale(N) = lscale;
+
+ /* encode all primitives */
+ for (size_t i=0; i<M && begin<end; i++, begin++)
+ {
+ const PrimRef& prim = prims[begin];
+ const unsigned int geomID = prim.geomID();
+ const unsigned int primID = prim.primID();
+ const LinearSpace3fa space2 = scene->get(geomID)->computeAlignedSpace(primID);
+
+ const LinearSpace3fa space3(trunc(126.0f*space2.vx),trunc(126.0f*space2.vy),trunc(126.0f*space2.vz));
+ const BBox3fa bounds = scene->get(geomID)->vbounds(loffset,lscale,max(length(space3.vx),length(space3.vy),length(space3.vz)),space3.transposed(),primID);
+
+ bounds_vx_x(N)[i] = (char) space3.vx.x;
+ bounds_vx_y(N)[i] = (char) space3.vx.y;
+ bounds_vx_z(N)[i] = (char) space3.vx.z;
+ bounds_vx_lower(N)[i] = (short) clamp(floor(bounds.lower.x),-32767.0f,32767.0f);
+ bounds_vx_upper(N)[i] = (short) clamp(ceil (bounds.upper.x),-32767.0f,32767.0f);
+ assert(-32767.0f <= floor(bounds.lower.x) && floor(bounds.lower.x) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.upper.x) && ceil (bounds.upper.x) <= 32767.0f);
+
+ bounds_vy_x(N)[i] = (char) space3.vy.x;
+ bounds_vy_y(N)[i] = (char) space3.vy.y;
+ bounds_vy_z(N)[i] = (char) space3.vy.z;
+ bounds_vy_lower(N)[i] = (short) clamp(floor(bounds.lower.y),-32767.0f,32767.0f);
+ bounds_vy_upper(N)[i] = (short) clamp(ceil (bounds.upper.y),-32767.0f,32767.0f);
+ assert(-32767.0f <= floor(bounds.lower.y) && floor(bounds.lower.y) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.upper.y) && ceil (bounds.upper.y) <= 32767.0f);
+
+ bounds_vz_x(N)[i] = (char) space3.vz.x;
+ bounds_vz_y(N)[i] = (char) space3.vz.y;
+ bounds_vz_z(N)[i] = (char) space3.vz.z;
+ bounds_vz_lower(N)[i] = (short) clamp(floor(bounds.lower.z),-32767.0f,32767.0f);
+ bounds_vz_upper(N)[i] = (short) clamp(ceil (bounds.upper.z),-32767.0f,32767.0f);
+ assert(-32767.0f <= floor(bounds.lower.z) && floor(bounds.lower.z) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.upper.z) && ceil (bounds.upper.z) <= 32767.0f);
+
+ this->primID(N)[i] = primID;
+ }
+ }
+
+ template<typename BVH, typename Allocator>
+ __forceinline static typename BVH::NodeRef createLeaf (BVH* bvh, const PrimRef* prims, const range<size_t>& set, const Allocator& alloc)
+ {
+ size_t start = set.begin();
+ size_t items = CurveNi::blocks(set.size());
+ size_t numbytes = CurveNi::bytes(set.size());
+ CurveNi* accel = (CurveNi*) alloc.malloc1(numbytes,BVH::byteAlignment);
+ for (size_t i=0; i<items; i++) {
+ accel[i].fill(prims,start,set.end(),bvh->scene);
+ }
+ return bvh->encodeLeaf((char*)accel,items);
+ };
+
+ public:
+
+ // 27.6 - 46 bytes per primitive
+ unsigned char ty;
+ unsigned char N;
+ unsigned char data[4+25*M+16];
+
+ /*
+ struct Layout
+ {
+ unsigned int geomID;
+ unsigned int primID[N];
+
+ char bounds_vx_x[N];
+ char bounds_vx_y[N];
+ char bounds_vx_z[N];
+ short bounds_vx_lower[N];
+ short bounds_vx_upper[N];
+
+ char bounds_vy_x[N];
+ char bounds_vy_y[N];
+ char bounds_vy_z[N];
+ short bounds_vy_lower[N];
+ short bounds_vy_upper[N];
+
+ char bounds_vz_x[N];
+ char bounds_vz_y[N];
+ char bounds_vz_z[N];
+ short bounds_vz_lower[N];
+ short bounds_vz_upper[N];
+
+ Vec3f offset;
+ float scale;
+ };
+ */
+
+ __forceinline unsigned int& geomID(size_t N) { return *(unsigned int*)((char*)this+2); }
+ __forceinline const unsigned int& geomID(size_t N) const { return *(unsigned int*)((char*)this+2); }
+
+ __forceinline unsigned int* primID(size_t N) { return (unsigned int*)((char*)this+6); }
+ __forceinline const unsigned int* primID(size_t N) const { return (unsigned int*)((char*)this+6); }
+
+ __forceinline char* bounds_vx_x(size_t N) { return (char*)((char*)this+6+4*N); }
+ __forceinline const char* bounds_vx_x(size_t N) const { return (char*)((char*)this+6+4*N); }
+
+ __forceinline char* bounds_vx_y(size_t N) { return (char*)((char*)this+6+5*N); }
+ __forceinline const char* bounds_vx_y(size_t N) const { return (char*)((char*)this+6+5*N); }
+
+ __forceinline char* bounds_vx_z(size_t N) { return (char*)((char*)this+6+6*N); }
+ __forceinline const char* bounds_vx_z(size_t N) const { return (char*)((char*)this+6+6*N); }
+
+ __forceinline short* bounds_vx_lower(size_t N) { return (short*)((char*)this+6+7*N); }
+ __forceinline const short* bounds_vx_lower(size_t N) const { return (short*)((char*)this+6+7*N); }
+
+ __forceinline short* bounds_vx_upper(size_t N) { return (short*)((char*)this+6+9*N); }
+ __forceinline const short* bounds_vx_upper(size_t N) const { return (short*)((char*)this+6+9*N); }
+
+ __forceinline char* bounds_vy_x(size_t N) { return (char*)((char*)this+6+11*N); }
+ __forceinline const char* bounds_vy_x(size_t N) const { return (char*)((char*)this+6+11*N); }
+
+ __forceinline char* bounds_vy_y(size_t N) { return (char*)((char*)this+6+12*N); }
+ __forceinline const char* bounds_vy_y(size_t N) const { return (char*)((char*)this+6+12*N); }
+
+ __forceinline char* bounds_vy_z(size_t N) { return (char*)((char*)this+6+13*N); }
+ __forceinline const char* bounds_vy_z(size_t N) const { return (char*)((char*)this+6+13*N); }
+
+ __forceinline short* bounds_vy_lower(size_t N) { return (short*)((char*)this+6+14*N); }
+ __forceinline const short* bounds_vy_lower(size_t N) const { return (short*)((char*)this+6+14*N); }
+
+ __forceinline short* bounds_vy_upper(size_t N) { return (short*)((char*)this+6+16*N); }
+ __forceinline const short* bounds_vy_upper(size_t N) const { return (short*)((char*)this+6+16*N); }
+
+ __forceinline char* bounds_vz_x(size_t N) { return (char*)((char*)this+6+18*N); }
+ __forceinline const char* bounds_vz_x(size_t N) const { return (char*)((char*)this+6+18*N); }
+
+ __forceinline char* bounds_vz_y(size_t N) { return (char*)((char*)this+6+19*N); }
+ __forceinline const char* bounds_vz_y(size_t N) const { return (char*)((char*)this+6+19*N); }
+
+ __forceinline char* bounds_vz_z(size_t N) { return (char*)((char*)this+6+20*N); }
+ __forceinline const char* bounds_vz_z(size_t N) const { return (char*)((char*)this+6+20*N); }
+
+ __forceinline short* bounds_vz_lower(size_t N) { return (short*)((char*)this+6+21*N); }
+ __forceinline const short* bounds_vz_lower(size_t N) const { return (short*)((char*)this+6+21*N); }
+
+ __forceinline short* bounds_vz_upper(size_t N) { return (short*)((char*)this+6+23*N); }
+ __forceinline const short* bounds_vz_upper(size_t N) const { return (short*)((char*)this+6+23*N); }
+
+ __forceinline Vec3f* offset(size_t N) { return (Vec3f*)((char*)this+6+25*N); }
+ __forceinline const Vec3f* offset(size_t N) const { return (Vec3f*)((char*)this+6+25*N); }
+
+ __forceinline float* scale(size_t N) { return (float*)((char*)this+6+25*N+12); }
+ __forceinline const float* scale(size_t N) const { return (float*)((char*)this+6+25*N+12); }
+
+ __forceinline char* end(size_t N) { return (char*)this+6+25*N+16; }
+ __forceinline const char* end(size_t N) const { return (char*)this+6+25*N+16; }
+ };
+
+ template<int M>
+ typename CurveNi<M>::Type CurveNi<M>::type;
+
+ typedef CurveNi<4> Curve4i;
+ typedef CurveNi<8> Curve8i;
+}
diff --git a/thirdparty/embree/kernels/geometry/curveNi_intersector.h b/thirdparty/embree/kernels/geometry/curveNi_intersector.h
new file mode 100644
index 0000000000..c0b66515c1
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curveNi_intersector.h
@@ -0,0 +1,569 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "curveNi.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct CurveNiIntersector1
+ {
+ typedef CurveNi<M> Primitive;
+ typedef Vec3vf<M> Vec3vfM;
+ typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline vbool<M> intersect(Ray& ray, const Primitive& prim, vfloat<M>& tNear_o)
+ {
+ const size_t N = prim.N;
+ const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));
+ const Vec3fa offset = Vec3fa(offset_scale);
+ const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));
+ const Vec3fa org1 = (ray.org-offset)*scale;
+ const Vec3fa dir1 = ray.dir*scale;
+
+ const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),
+ vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),
+ vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));
+
+ const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));
+ const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));
+ const Vec3vfM rcp_dir2 = rcp_safe(dir2);
+
+ const vfloat<M> t_lower_x = (vfloat<M>::load(prim.bounds_vx_lower(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
+ const vfloat<M> t_upper_x = (vfloat<M>::load(prim.bounds_vx_upper(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
+ const vfloat<M> t_lower_y = (vfloat<M>::load(prim.bounds_vy_lower(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
+ const vfloat<M> t_upper_y = (vfloat<M>::load(prim.bounds_vy_upper(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
+ const vfloat<M> t_lower_z = (vfloat<M>::load(prim.bounds_vz_lower(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
+ const vfloat<M> t_upper_z = (vfloat<M>::load(prim.bounds_vz_upper(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
+
+ const vfloat<M> round_up (1.0f+3.0f*float(ulp));
+ const vfloat<M> round_down(1.0f-3.0f*float(ulp));
+ const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()));
+ const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar));
+ tNear_o = tNear;
+ return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ const unsigned int primID1 = prim.primID(N)[i1];
+ geom->prefetchL1_vertices(geom->curve(primID1));
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ const unsigned int primID2 = prim.primID(N)[i2];
+ geom->prefetchL2_vertices(geom->curve(primID2));
+ }
+ }
+
+ Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ const unsigned int primID1 = prim.primID(N)[i1];
+ geom->prefetchL1_vertices(geom->curve(primID1));
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ const unsigned int primID2 = prim.primID(N)[i2];
+ geom->prefetchL2_vertices(geom->curve(primID2));
+ }
+ }
+
+ if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_n(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+
+ unsigned int vertexID = geom->curve(primID);
+ Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ const unsigned int primID1 = prim.primID(N)[i1];
+ geom->prefetchL1_vertices(geom->curve(primID1));
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ const unsigned int primID2 = prim.primID(N)[i2];
+ geom->prefetchL2_vertices(geom->curve(primID2));
+ }
+ }
+
+ Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_n(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+
+ unsigned int vertexID = geom->curve(primID);
+ Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ const unsigned int primID1 = prim.primID(N)[i1];
+ geom->prefetchL1_vertices(geom->curve(primID1));
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ const unsigned int primID2 = prim.primID(N)[i2];
+ geom->prefetchL2_vertices(geom->curve(primID2));
+ }
+ }
+
+ if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_h(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));
+ Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_h(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));
+ if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_hn(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));
+ Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_hn(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));
+ if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+ };
+
+ template<int M, int K>
+ struct CurveNiIntersectorK
+ {
+ typedef CurveNi<M> Primitive;
+ typedef Vec3vf<M> Vec3vfM;
+ typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline vbool<M> intersect(RayK<K>& ray, const size_t k, const Primitive& prim, vfloat<M>& tNear_o)
+ {
+ const size_t N = prim.N;
+ const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));
+ const Vec3fa offset = Vec3fa(offset_scale);
+ const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));
+
+ const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
+ const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
+ const Vec3fa org1 = (ray_org-offset)*scale;
+ const Vec3fa dir1 = ray_dir*scale;
+
+ const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),
+ vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),
+ vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));
+
+ const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));
+ const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));
+ const Vec3vfM rcp_dir2 = rcp_safe(dir2);
+
+ const vfloat<M> t_lower_x = (vfloat<M>::load(prim.bounds_vx_lower(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
+ const vfloat<M> t_upper_x = (vfloat<M>::load(prim.bounds_vx_upper(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
+ const vfloat<M> t_lower_y = (vfloat<M>::load(prim.bounds_vy_lower(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
+ const vfloat<M> t_upper_y = (vfloat<M>::load(prim.bounds_vy_upper(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
+ const vfloat<M> t_lower_z = (vfloat<M>::load(prim.bounds_vz_lower(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
+ const vfloat<M> t_upper_z = (vfloat<M>::load(prim.bounds_vz_upper(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
+
+ const vfloat<M> round_up (1.0f+3.0f*float(ulp));
+ const vfloat<M> round_down(1.0f-3.0f*float(ulp));
+ const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()[k]));
+ const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar[k]));
+ tNear_o = tNear;
+ return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ const unsigned int primID1 = prim.primID(N)[i1];
+ geom->prefetchL1_vertices(geom->curve(primID1));
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ const unsigned int primID2 = prim.primID(N)[i2];
+ geom->prefetchL2_vertices(geom->curve(primID2));
+ }
+ }
+
+ Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ const unsigned int primID1 = prim.primID(N)[i1];
+ geom->prefetchL1_vertices(geom->curve(primID1));
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ const unsigned int primID2 = prim.primID(N)[i2];
+ geom->prefetchL2_vertices(geom->curve(primID2));
+ }
+ }
+
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_n(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+
+ unsigned int vertexID = geom->curve(primID);
+ Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ const unsigned int primID1 = prim.primID(N)[i1];
+ geom->prefetchL1_vertices(geom->curve(primID1));
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ const unsigned int primID2 = prim.primID(N)[i2];
+ geom->prefetchL2_vertices(geom->curve(primID2));
+ }
+ }
+
+ Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_n(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+
+ unsigned int vertexID = geom->curve(primID);
+ Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ const unsigned int primID1 = prim.primID(N)[i1];
+ geom->prefetchL1_vertices(geom->curve(primID1));
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ const unsigned int primID2 = prim.primID(N)[i2];
+ geom->prefetchL2_vertices(geom->curve(primID2));
+ }
+ }
+
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_h(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));
+ Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_h(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_hn(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));
+ Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_hn(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curveNi_mb.h b/thirdparty/embree/kernels/geometry/curveNi_mb.h
new file mode 100644
index 0000000000..5d972b43a0
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curveNi_mb.h
@@ -0,0 +1,278 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+#include "curve_intersector_precalculations.h"
+
+namespace embree
+{
+ template<int M>
+ struct CurveNiMB
+ {
+ struct Type : public PrimitiveType {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* Returns maximum number of stored primitives */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+M-1)/M; }
+
+ static __forceinline size_t bytes(size_t N)
+ {
+ const size_t f = N/M, r = N%M;
+ static_assert(sizeof(CurveNiMB) == 6+37*M+24, "internal data layout issue");
+ return f*sizeof(CurveNiMB) + (r!=0)*(6+37*r+24);
+ }
+
+ public:
+
+ /*! Default constructor. */
+ __forceinline CurveNiMB () {}
+
+ /*! fill curve from curve list */
+ __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t _end, Scene* scene, const BBox1f time_range)
+ {
+ size_t end = min(begin+M,_end);
+ N = (unsigned char)(end-begin);
+ const unsigned int geomID0 = prims[begin].geomID();
+ this->geomID(N) = geomID0;
+ ty = (unsigned char) scene->get(geomID0)->getType();
+
+ /* encode all primitives */
+ LBBox3fa lbounds = empty;
+ for (size_t i=0; i<N; i++)
+ {
+ const PrimRefMB& prim = prims[begin+i];
+ const unsigned int geomID = prim.geomID(); assert(geomID == geomID0);
+ const unsigned int primID = prim.primID();
+ lbounds.extend(scene->get(geomID)->vlinearBounds(primID,time_range));
+ }
+ BBox3fa bounds = lbounds.bounds();
+
+ /* calculate offset and scale */
+ Vec3fa loffset = bounds.lower;
+ float lscale = reduce_min(256.0f/(bounds.size()*sqrt(3.0f)));
+ if (bounds.size() == Vec3fa(zero)) lscale = 0.0f;
+ *this->offset(N) = loffset;
+ *this->scale(N) = lscale;
+ this->time_offset(N) = time_range.lower;
+ this->time_scale(N) = 1.0f/time_range.size();
+
+ /* encode all primitives */
+ for (size_t i=0; i<M && begin<end; i++, begin++)
+ {
+ const PrimRefMB& prim = prims[begin];
+ const unsigned int geomID = prim.geomID();
+ const unsigned int primID = prim.primID();
+ const LinearSpace3fa space2 = scene->get(geomID)->computeAlignedSpaceMB(primID,time_range);
+
+ const LinearSpace3fa space3(trunc(126.0f*space2.vx),trunc(126.0f*space2.vy),trunc(126.0f*space2.vz));
+ const LBBox3fa bounds = scene->get(geomID)->vlinearBounds(loffset,lscale,max(length(space3.vx),length(space3.vy),length(space3.vz)),space3.transposed(),primID,time_range);
+
+ // NOTE: this weird (char) (short) cast works around VS2015 Win32 compiler bug
+ bounds_vx_x(N)[i] = (char) (short) space3.vx.x;
+ bounds_vx_y(N)[i] = (char) (short) space3.vx.y;
+ bounds_vx_z(N)[i] = (char) (short) space3.vx.z;
+ bounds_vx_lower0(N)[i] = (short) clamp(floor(bounds.bounds0.lower.x),-32767.0f,32767.0f);
+ bounds_vx_upper0(N)[i] = (short) clamp(ceil (bounds.bounds0.upper.x),-32767.0f,32767.0f);
+ bounds_vx_lower1(N)[i] = (short) clamp(floor(bounds.bounds1.lower.x),-32767.0f,32767.0f);
+ bounds_vx_upper1(N)[i] = (short) clamp(ceil (bounds.bounds1.upper.x),-32767.0f,32767.0f);
+ assert(-32767.0f <= floor(bounds.bounds0.lower.x) && floor(bounds.bounds0.lower.x) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.bounds0.upper.x) && ceil (bounds.bounds0.upper.x) <= 32767.0f);
+ assert(-32767.0f <= floor(bounds.bounds1.lower.x) && floor(bounds.bounds1.lower.x) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.bounds1.upper.x) && ceil (bounds.bounds1.upper.x) <= 32767.0f);
+
+ bounds_vy_x(N)[i] = (char) (short) space3.vy.x;
+ bounds_vy_y(N)[i] = (char) (short) space3.vy.y;
+ bounds_vy_z(N)[i] = (char) (short) space3.vy.z;
+ bounds_vy_lower0(N)[i] = (short) clamp(floor(bounds.bounds0.lower.y),-32767.0f,32767.0f);
+ bounds_vy_upper0(N)[i] = (short) clamp(ceil (bounds.bounds0.upper.y),-32767.0f,32767.0f);
+ bounds_vy_lower1(N)[i] = (short) clamp(floor(bounds.bounds1.lower.y),-32767.0f,32767.0f);
+ bounds_vy_upper1(N)[i] = (short) clamp(ceil (bounds.bounds1.upper.y),-32767.0f,32767.0f);
+ assert(-32767.0f <= floor(bounds.bounds0.lower.y) && floor(bounds.bounds0.lower.y) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.bounds0.upper.y) && ceil (bounds.bounds0.upper.y) <= 32767.0f);
+ assert(-32767.0f <= floor(bounds.bounds1.lower.y) && floor(bounds.bounds1.lower.y) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.bounds1.upper.y) && ceil (bounds.bounds1.upper.y) <= 32767.0f);
+
+ bounds_vz_x(N)[i] = (char) (short) space3.vz.x;
+ bounds_vz_y(N)[i] = (char) (short) space3.vz.y;
+ bounds_vz_z(N)[i] = (char) (short) space3.vz.z;
+ bounds_vz_lower0(N)[i] = (short) clamp(floor(bounds.bounds0.lower.z),-32767.0f,32767.0f);
+ bounds_vz_upper0(N)[i] = (short) clamp(ceil (bounds.bounds0.upper.z),-32767.0f,32767.0f);
+ bounds_vz_lower1(N)[i] = (short) clamp(floor(bounds.bounds1.lower.z),-32767.0f,32767.0f);
+ bounds_vz_upper1(N)[i] = (short) clamp(ceil (bounds.bounds1.upper.z),-32767.0f,32767.0f);
+ assert(-32767.0f <= floor(bounds.bounds0.lower.z) && floor(bounds.bounds0.lower.z) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.bounds0.upper.z) && ceil (bounds.bounds0.upper.z) <= 32767.0f);
+ assert(-32767.0f <= floor(bounds.bounds1.lower.z) && floor(bounds.bounds1.lower.z) <= 32767.0f);
+ assert(-32767.0f <= ceil (bounds.bounds1.upper.z) && ceil (bounds.bounds1.upper.z) <= 32767.0f);
+
+ this->primID(N)[i] = primID;
+ }
+
+ return lbounds;
+ }
+
+ template<typename BVH, typename SetMB, typename Allocator>
+ __forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc)
+ {
+ size_t start = prims.begin();
+ size_t end = prims.end();
+ size_t items = CurveNiMB::blocks(prims.size());
+ size_t numbytes = CurveNiMB::bytes(prims.size());
+ CurveNiMB* accel = (CurveNiMB*) alloc.malloc1(numbytes,BVH::byteAlignment);
+ const typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,items);
+
+ LBBox3fa bounds = empty;
+ for (size_t i=0; i<items; i++)
+ bounds.extend(accel[i].fillMB(prims.prims->data(),start,end,bvh->scene,prims.time_range));
+
+ return typename BVH::NodeRecordMB4D(node,bounds,prims.time_range);
+ };
+
+
+ public:
+
+ // 27.6 - 46 bytes per primitive
+ unsigned char ty;
+ unsigned char N;
+ unsigned char data[4+37*M+24];
+
+ /*
+ struct Layout
+ {
+ unsigned int geomID;
+ unsigned int primID[N];
+
+ char bounds_vx_x[N];
+ char bounds_vx_y[N];
+ char bounds_vx_z[N];
+ short bounds_vx_lower0[N];
+ short bounds_vx_upper0[N];
+ short bounds_vx_lower1[N];
+ short bounds_vx_upper1[N];
+
+ char bounds_vy_x[N];
+ char bounds_vy_y[N];
+ char bounds_vy_z[N];
+ short bounds_vy_lower0[N];
+ short bounds_vy_upper0[N];
+ short bounds_vy_lower1[N];
+ short bounds_vy_upper1[N];
+
+ char bounds_vz_x[N];
+ char bounds_vz_y[N];
+ char bounds_vz_z[N];
+ short bounds_vz_lower0[N];
+ short bounds_vz_upper0[N];
+ short bounds_vz_lower1[N];
+ short bounds_vz_upper1[N];
+
+ Vec3f offset;
+ float scale;
+
+ float time_offset;
+ float time_scale;
+ };
+ */
+
+ __forceinline unsigned int& geomID(size_t N) { return *(unsigned int*)((char*)this+2); }
+ __forceinline const unsigned int& geomID(size_t N) const { return *(unsigned int*)((char*)this+2); }
+
+ __forceinline unsigned int* primID(size_t N) { return (unsigned int*)((char*)this+6); }
+ __forceinline const unsigned int* primID(size_t N) const { return (unsigned int*)((char*)this+6); }
+
+ __forceinline char* bounds_vx_x(size_t N) { return (char*)((char*)this+6+4*N); }
+ __forceinline const char* bounds_vx_x(size_t N) const { return (char*)((char*)this+6+4*N); }
+
+ __forceinline char* bounds_vx_y(size_t N) { return (char*)((char*)this+6+5*N); }
+ __forceinline const char* bounds_vx_y(size_t N) const { return (char*)((char*)this+6+5*N); }
+
+ __forceinline char* bounds_vx_z(size_t N) { return (char*)((char*)this+6+6*N); }
+ __forceinline const char* bounds_vx_z(size_t N) const { return (char*)((char*)this+6+6*N); }
+
+ __forceinline short* bounds_vx_lower0(size_t N) { return (short*)((char*)this+6+7*N); }
+ __forceinline const short* bounds_vx_lower0(size_t N) const { return (short*)((char*)this+6+7*N); }
+
+ __forceinline short* bounds_vx_upper0(size_t N) { return (short*)((char*)this+6+9*N); }
+ __forceinline const short* bounds_vx_upper0(size_t N) const { return (short*)((char*)this+6+9*N); }
+
+ __forceinline short* bounds_vx_lower1(size_t N) { return (short*)((char*)this+6+11*N); }
+ __forceinline const short* bounds_vx_lower1(size_t N) const { return (short*)((char*)this+6+11*N); }
+
+ __forceinline short* bounds_vx_upper1(size_t N) { return (short*)((char*)this+6+13*N); }
+ __forceinline const short* bounds_vx_upper1(size_t N) const { return (short*)((char*)this+6+13*N); }
+
+ __forceinline char* bounds_vy_x(size_t N) { return (char*)((char*)this+6+15*N); }
+ __forceinline const char* bounds_vy_x(size_t N) const { return (char*)((char*)this+6+15*N); }
+
+ __forceinline char* bounds_vy_y(size_t N) { return (char*)((char*)this+6+16*N); }
+ __forceinline const char* bounds_vy_y(size_t N) const { return (char*)((char*)this+6+16*N); }
+
+ __forceinline char* bounds_vy_z(size_t N) { return (char*)((char*)this+6+17*N); }
+ __forceinline const char* bounds_vy_z(size_t N) const { return (char*)((char*)this+6+17*N); }
+
+ __forceinline short* bounds_vy_lower0(size_t N) { return (short*)((char*)this+6+18*N); }
+ __forceinline const short* bounds_vy_lower0(size_t N) const { return (short*)((char*)this+6+18*N); }
+
+ __forceinline short* bounds_vy_upper0(size_t N) { return (short*)((char*)this+6+20*N); }
+ __forceinline const short* bounds_vy_upper0(size_t N) const { return (short*)((char*)this+6+20*N); }
+
+ __forceinline short* bounds_vy_lower1(size_t N) { return (short*)((char*)this+6+22*N); }
+ __forceinline const short* bounds_vy_lower1(size_t N) const { return (short*)((char*)this+6+22*N); }
+
+ __forceinline short* bounds_vy_upper1(size_t N) { return (short*)((char*)this+6+24*N); }
+ __forceinline const short* bounds_vy_upper1(size_t N) const { return (short*)((char*)this+6+24*N); }
+
+ __forceinline char* bounds_vz_x(size_t N) { return (char*)((char*)this+6+26*N); }
+ __forceinline const char* bounds_vz_x(size_t N) const { return (char*)((char*)this+6+26*N); }
+
+ __forceinline char* bounds_vz_y(size_t N) { return (char*)((char*)this+6+27*N); }
+ __forceinline const char* bounds_vz_y(size_t N) const { return (char*)((char*)this+6+27*N); }
+
+ __forceinline char* bounds_vz_z(size_t N) { return (char*)((char*)this+6+28*N); }
+ __forceinline const char* bounds_vz_z(size_t N) const { return (char*)((char*)this+6+28*N); }
+
+ __forceinline short* bounds_vz_lower0(size_t N) { return (short*)((char*)this+6+29*N); }
+ __forceinline const short* bounds_vz_lower0(size_t N) const { return (short*)((char*)this+6+29*N); }
+
+ __forceinline short* bounds_vz_upper0(size_t N) { return (short*)((char*)this+6+31*N); }
+ __forceinline const short* bounds_vz_upper0(size_t N) const { return (short*)((char*)this+6+31*N); }
+
+ __forceinline short* bounds_vz_lower1(size_t N) { return (short*)((char*)this+6+33*N); }
+ __forceinline const short* bounds_vz_lower1(size_t N) const { return (short*)((char*)this+6+33*N); }
+
+ __forceinline short* bounds_vz_upper1(size_t N) { return (short*)((char*)this+6+35*N); }
+ __forceinline const short* bounds_vz_upper1(size_t N) const { return (short*)((char*)this+6+35*N); }
+
+ __forceinline Vec3f* offset(size_t N) { return (Vec3f*)((char*)this+6+37*N); }
+ __forceinline const Vec3f* offset(size_t N) const { return (Vec3f*)((char*)this+6+37*N); }
+
+ __forceinline float* scale(size_t N) { return (float*)((char*)this+6+37*N+12); }
+ __forceinline const float* scale(size_t N) const { return (float*)((char*)this+6+37*N+12); }
+
+ __forceinline float& time_offset(size_t N) { return *(float*)((char*)this+6+37*N+16); }
+ __forceinline const float& time_offset(size_t N) const { return *(float*)((char*)this+6+37*N+16); }
+
+ __forceinline float& time_scale(size_t N) { return *(float*)((char*)this+6+37*N+20); }
+ __forceinline const float& time_scale(size_t N) const { return *(float*)((char*)this+6+37*N+20); }
+
+ __forceinline char* end(size_t N) { return (char*)this+6+37*N+24; }
+ __forceinline const char* end(size_t N) const { return (char*)this+6+37*N+24; }
+ };
+
+ template<int M>
+ typename CurveNiMB<M>::Type CurveNiMB<M>::type;
+
+ typedef CurveNiMB<4> Curve4iMB;
+ typedef CurveNiMB<8> Curve8iMB;
+}
diff --git a/thirdparty/embree/kernels/geometry/curveNi_mb_intersector.h b/thirdparty/embree/kernels/geometry/curveNi_mb_intersector.h
new file mode 100644
index 0000000000..bab796b33b
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curveNi_mb_intersector.h
@@ -0,0 +1,516 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "curveNi_mb.h"
+#include "../subdiv/linear_bezier_patch.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct CurveNiMBIntersector1
+ {
+ typedef CurveNiMB<M> Primitive;
+ typedef Vec3vf<M> Vec3vfM;
+ typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline vbool<M> intersect(Ray& ray, const Primitive& prim, vfloat<M>& tNear_o)
+ {
+ const size_t N = prim.N;
+ const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));
+ const Vec3fa offset = Vec3fa(offset_scale);
+ const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));
+ const Vec3fa org1 = (ray.org-offset)*scale;
+ const Vec3fa dir1 = ray.dir*scale;
+
+ const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),
+ vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),
+ vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));
+
+ const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));
+ const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));
+ const Vec3vfM rcp_dir2 = rcp_safe(dir2);
+
+ const vfloat<M> ltime = (ray.time()-prim.time_offset(N))*prim.time_scale(N);
+ const vfloat<M> vx_lower0 = vfloat<M>::load(prim.bounds_vx_lower0(N));
+ const vfloat<M> vx_lower1 = vfloat<M>::load(prim.bounds_vx_lower1(N));
+ const vfloat<M> vx_lower = madd(ltime,vx_lower1-vx_lower0,vx_lower0);
+ const vfloat<M> vx_upper0 = vfloat<M>::load(prim.bounds_vx_upper0(N));
+ const vfloat<M> vx_upper1 = vfloat<M>::load(prim.bounds_vx_upper1(N));
+ const vfloat<M> vx_upper = madd(ltime,vx_upper1-vx_upper0,vx_upper0);
+
+ const vfloat<M> vy_lower0 = vfloat<M>::load(prim.bounds_vy_lower0(N));
+ const vfloat<M> vy_lower1 = vfloat<M>::load(prim.bounds_vy_lower1(N));
+ const vfloat<M> vy_lower = madd(ltime,vy_lower1-vy_lower0,vy_lower0);
+ const vfloat<M> vy_upper0 = vfloat<M>::load(prim.bounds_vy_upper0(N));
+ const vfloat<M> vy_upper1 = vfloat<M>::load(prim.bounds_vy_upper1(N));
+ const vfloat<M> vy_upper = madd(ltime,vy_upper1-vy_upper0,vy_upper0);
+
+ const vfloat<M> vz_lower0 = vfloat<M>::load(prim.bounds_vz_lower0(N));
+ const vfloat<M> vz_lower1 = vfloat<M>::load(prim.bounds_vz_lower1(N));
+ const vfloat<M> vz_lower = madd(ltime,vz_lower1-vz_lower0,vz_lower0);
+ const vfloat<M> vz_upper0 = vfloat<M>::load(prim.bounds_vz_upper0(N));
+ const vfloat<M> vz_upper1 = vfloat<M>::load(prim.bounds_vz_upper1(N));
+ const vfloat<M> vz_upper = madd(ltime,vz_upper1-vz_upper0,vz_upper0);
+
+ const vfloat<M> t_lower_x = (vx_lower-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
+ const vfloat<M> t_upper_x = (vx_upper-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
+ const vfloat<M> t_lower_y = (vy_lower-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
+ const vfloat<M> t_upper_y = (vy_upper-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
+ const vfloat<M> t_lower_z = (vz_lower-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
+ const vfloat<M> t_upper_z = (vz_upper-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
+
+ const vfloat<M> round_up (1.0f+3.0f*float(ulp));
+ const vfloat<M> round_down(1.0f-3.0f*float(ulp));
+ const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()));
+ const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar));
+ tNear_o = tNear;
+ return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID),ray.time());
+
+ Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID),ray.time());
+
+ if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_n(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time());
+ Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_n(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time());
+
+ if (Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_h(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID),ray.time());
+ Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_h(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID),ray.time());
+ if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_hn(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time());
+ Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_hn(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time());
+ if (Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+ };
+
+ template<int M, int K>
+ struct CurveNiMBIntersectorK
+ {
+ typedef CurveNiMB<M> Primitive;
+ typedef Vec3vf<M> Vec3vfM;
+ typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline vbool<M> intersect(RayK<K>& ray, const size_t k, const Primitive& prim, vfloat<M>& tNear_o)
+ {
+ const size_t N = prim.N;
+ const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));
+ const Vec3fa offset = Vec3fa(offset_scale);
+ const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));
+
+ const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
+ const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
+ const Vec3fa org1 = (ray_org-offset)*scale;
+ const Vec3fa dir1 = ray_dir*scale;
+
+ const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),
+ vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),
+ vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));
+
+ const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));
+ const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));
+ const Vec3vfM rcp_dir2 = rcp_safe(dir2);
+
+ const vfloat<M> ltime = (ray.time()[k]-prim.time_offset(N))*prim.time_scale(N);
+ const vfloat<M> vx_lower0 = vfloat<M>::load(prim.bounds_vx_lower0(N));
+ const vfloat<M> vx_lower1 = vfloat<M>::load(prim.bounds_vx_lower1(N));
+ const vfloat<M> vx_lower = madd(ltime,vx_lower1-vx_lower0,vx_lower0);
+ const vfloat<M> vx_upper0 = vfloat<M>::load(prim.bounds_vx_upper0(N));
+ const vfloat<M> vx_upper1 = vfloat<M>::load(prim.bounds_vx_upper1(N));
+ const vfloat<M> vx_upper = madd(ltime,vx_upper1-vx_upper0,vx_upper0);
+
+ const vfloat<M> vy_lower0 = vfloat<M>::load(prim.bounds_vy_lower0(N));
+ const vfloat<M> vy_lower1 = vfloat<M>::load(prim.bounds_vy_lower1(N));
+ const vfloat<M> vy_lower = madd(ltime,vy_lower1-vy_lower0,vy_lower0);
+ const vfloat<M> vy_upper0 = vfloat<M>::load(prim.bounds_vy_upper0(N));
+ const vfloat<M> vy_upper1 = vfloat<M>::load(prim.bounds_vy_upper1(N));
+ const vfloat<M> vy_upper = madd(ltime,vy_upper1-vy_upper0,vy_upper0);
+
+ const vfloat<M> vz_lower0 = vfloat<M>::load(prim.bounds_vz_lower0(N));
+ const vfloat<M> vz_lower1 = vfloat<M>::load(prim.bounds_vz_lower1(N));
+ const vfloat<M> vz_lower = madd(ltime,vz_lower1-vz_lower0,vz_lower0);
+ const vfloat<M> vz_upper0 = vfloat<M>::load(prim.bounds_vz_upper0(N));
+ const vfloat<M> vz_upper1 = vfloat<M>::load(prim.bounds_vz_upper1(N));
+ const vfloat<M> vz_upper = madd(ltime,vz_upper1-vz_upper0,vz_upper0);
+
+ const vfloat<M> t_lower_x = (vx_lower-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
+ const vfloat<M> t_upper_x = (vx_upper-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);
+ const vfloat<M> t_lower_y = (vy_lower-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
+ const vfloat<M> t_upper_y = (vy_upper-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);
+ const vfloat<M> t_lower_z = (vz_lower-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
+ const vfloat<M> t_upper_z = (vz_upper-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);
+
+ const vfloat<M> round_up (1.0f+3.0f*float(ulp));
+ const vfloat<M> round_down(1.0f-3.0f*float(ulp));
+ const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()[k]));
+ const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar[k]));
+ tNear_o = tNear;
+ return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID),ray.time()[k]);
+
+ Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID),ray.time()[k]);
+
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_n(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]);
+ Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_n(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]);
+
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_h(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID),ray.time()[k]);
+ Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_h(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID),ray.time()[k]);
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_hn(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]);
+ Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_hn(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);
+ const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]);
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curveNv.h b/thirdparty/embree/kernels/geometry/curveNv.h
new file mode 100644
index 0000000000..e41a381706
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curveNv.h
@@ -0,0 +1,101 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "curveNi.h"
+
+namespace embree
+{
+ template<int M>
+ struct CurveNv : public CurveNi<M>
+ {
+ using CurveNi<M>::N;
+
+ struct Type : public PrimitiveType {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* Returns maximum number of stored primitives */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+M-1)/M; }
+
+ static __forceinline size_t bytes(size_t N)
+ {
+ const size_t f = N/M, r = N%M;
+ static_assert(sizeof(CurveNv) == 22+25*M+4*16*M, "internal data layout issue");
+ return f*sizeof(CurveNv) + (r!=0)*(22 + 25*r + 4*16*r);
+ }
+
+ public:
+
+ /*! Default constructor. */
+ __forceinline CurveNv () {}
+
+ /*! fill curve from curve list */
+ __forceinline void fill(const PrimRef* prims, size_t& begin, size_t _end, Scene* scene)
+ {
+ size_t end = min(begin+M,_end);
+ size_t N = end-begin;
+
+ /* encode all primitives */
+ for (size_t i=0; i<N; i++)
+ {
+ const PrimRef& prim = prims[begin+i];
+ const unsigned int geomID = prim.geomID();
+ const unsigned int primID = prim.primID();
+ CurveGeometry* mesh = (CurveGeometry*) scene->get(geomID);
+ const unsigned vtxID = mesh->curve(primID);
+ Vec3fa::storeu(&this->vertices(i,N)[0],mesh->vertex(vtxID+0));
+ Vec3fa::storeu(&this->vertices(i,N)[1],mesh->vertex(vtxID+1));
+ Vec3fa::storeu(&this->vertices(i,N)[2],mesh->vertex(vtxID+2));
+ Vec3fa::storeu(&this->vertices(i,N)[3],mesh->vertex(vtxID+3));
+ }
+ }
+
+ template<typename BVH, typename Allocator>
+ __forceinline static typename BVH::NodeRef createLeaf (BVH* bvh, const PrimRef* prims, const range<size_t>& set, const Allocator& alloc)
+ {
+ if (set.size() == 0)
+ return BVH::emptyNode;
+
+ /* fall back to CurveNi for oriented curves */
+ unsigned int geomID = prims[set.begin()].geomID();
+ if (bvh->scene->get(geomID)->getCurveType() == Geometry::GTY_SUBTYPE_ORIENTED_CURVE) {
+ return CurveNi<M>::createLeaf(bvh,prims,set,alloc);
+ }
+ if (bvh->scene->get(geomID)->getCurveBasis() == Geometry::GTY_BASIS_HERMITE) {
+ return CurveNi<M>::createLeaf(bvh,prims,set,alloc);
+ }
+
+ size_t start = set.begin();
+ size_t items = CurveNv::blocks(set.size());
+ size_t numbytes = CurveNv::bytes(set.size());
+ CurveNv* accel = (CurveNv*) alloc.malloc1(numbytes,BVH::byteAlignment);
+ for (size_t i=0; i<items; i++) {
+ accel[i].CurveNv<M>::fill(prims,start,set.end(),bvh->scene);
+ accel[i].CurveNi<M>::fill(prims,start,set.end(),bvh->scene);
+ }
+ return bvh->encodeLeaf((char*)accel,items);
+ };
+
+ public:
+ unsigned char data[4*16*M];
+ __forceinline Vec3fa* vertices(size_t i, size_t N) { return (Vec3fa*)CurveNi<M>::end(N)+4*i; }
+ __forceinline const Vec3fa* vertices(size_t i, size_t N) const { return (Vec3fa*)CurveNi<M>::end(N)+4*i; }
+ };
+
+ template<int M>
+ typename CurveNv<M>::Type CurveNv<M>::type;
+
+ typedef CurveNv<4> Curve4v;
+ typedef CurveNv<8> Curve8v;
+}
diff --git a/thirdparty/embree/kernels/geometry/curveNv_intersector.h b/thirdparty/embree/kernels/geometry/curveNv_intersector.h
new file mode 100644
index 0000000000..2742725aec
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curveNv_intersector.h
@@ -0,0 +1,181 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "curveNv.h"
+#include "curveNi_intersector.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct CurveNvIntersector1 : public CurveNiIntersector1<M>
+ {
+ typedef CurveNv<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = CurveNiIntersector1<M>::intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = (CurveGeometry*) context->scene->get(geomID);
+ const Vec3ff a0 = Vec3ff::loadu(&prim.vertices(i,N)[0]);
+ const Vec3ff a1 = Vec3ff::loadu(&prim.vertices(i,N)[1]);
+ const Vec3ff a2 = Vec3ff::loadu(&prim.vertices(i,N)[2]);
+ const Vec3ff a3 = Vec3ff::loadu(&prim.vertices(i,N)[3]);
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ prefetchL1(&prim.vertices(i1,N)[0]);
+ prefetchL1(&prim.vertices(i1,N)[4]);
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ prefetchL2(&prim.vertices(i2,N)[0]);
+ prefetchL2(&prim.vertices(i2,N)[4]);
+ }
+ }
+
+ Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = CurveNiIntersector1<M>::intersect(ray,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = (CurveGeometry*) context->scene->get(geomID);
+ const Vec3ff a0 = Vec3ff::loadu(&prim.vertices(i,N)[0]);
+ const Vec3ff a1 = Vec3ff::loadu(&prim.vertices(i,N)[1]);
+ const Vec3ff a2 = Vec3ff::loadu(&prim.vertices(i,N)[2]);
+ const Vec3ff a3 = Vec3ff::loadu(&prim.vertices(i,N)[3]);
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ prefetchL1(&prim.vertices(i1,N)[0]);
+ prefetchL1(&prim.vertices(i1,N)[4]);
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ prefetchL2(&prim.vertices(i2,N)[0]);
+ prefetchL2(&prim.vertices(i2,N)[4]);
+ }
+ }
+
+ if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar));
+ }
+ return false;
+ }
+ };
+
+ template<int M, int K>
+ struct CurveNvIntersectorK : public CurveNiIntersectorK<M,K>
+ {
+ typedef CurveNv<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = CurveNiIntersectorK<M,K>::intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(normal.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = (CurveGeometry*) context->scene->get(geomID);
+ const Vec3ff a0 = Vec3ff::loadu(&prim.vertices(i,N)[0]);
+ const Vec3ff a1 = Vec3ff::loadu(&prim.vertices(i,N)[1]);
+ const Vec3ff a2 = Vec3ff::loadu(&prim.vertices(i,N)[2]);
+ const Vec3ff a3 = Vec3ff::loadu(&prim.vertices(i,N)[3]);
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ prefetchL1(&prim.vertices(i1,N)[0]);
+ prefetchL1(&prim.vertices(i1,N)[4]);
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ prefetchL2(&prim.vertices(i2,N)[0]);
+ prefetchL2(&prim.vertices(i2,N)[4]);
+ }
+ }
+
+ Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID));
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ }
+
+ template<typename Intersector, typename Epilog>
+ static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim)
+ {
+ vfloat<M> tNear;
+ vbool<M> valid = CurveNiIntersectorK<M,K>::intersect(ray,k,prim,tNear);
+
+ const size_t N = prim.N;
+ size_t mask = movemask(valid);
+ while (mask)
+ {
+ const size_t i = bscf(mask);
+ STAT3(shadow.trav_prims,1,1,1);
+ const unsigned int geomID = prim.geomID(N);
+ const unsigned int primID = prim.primID(N)[i];
+ const CurveGeometry* geom = (CurveGeometry*) context->scene->get(geomID);
+ const Vec3ff a0 = Vec3ff::loadu(&prim.vertices(i,N)[0]);
+ const Vec3ff a1 = Vec3ff::loadu(&prim.vertices(i,N)[1]);
+ const Vec3ff a2 = Vec3ff::loadu(&prim.vertices(i,N)[2]);
+ const Vec3ff a3 = Vec3ff::loadu(&prim.vertices(i,N)[3]);
+
+ size_t mask1 = mask;
+ const size_t i1 = bscf(mask1);
+ if (mask) {
+ prefetchL1(&prim.vertices(i1,N)[0]);
+ prefetchL1(&prim.vertices(i1,N)[4]);
+ if (mask1) {
+ const size_t i2 = bsf(mask1);
+ prefetchL2(&prim.vertices(i2,N)[0]);
+ prefetchL2(&prim.vertices(i2,N)[4]);
+ }
+ }
+
+ if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)))
+ return true;
+
+ mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));
+ }
+ return false;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector.h b/thirdparty/embree/kernels/geometry/curve_intersector.h
new file mode 100644
index 0000000000..1e8ac26125
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curve_intersector.h
@@ -0,0 +1,98 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+#include "../subdiv/bezier_curve.h"
+#include "../common/primref.h"
+#include "bezier_hair_intersector.h"
+#include "bezier_ribbon_intersector.h"
+#include "bezier_curve_intersector.h"
+#include "oriented_curve_intersector.h"
+#include "../bvh/node_intersector1.h"
+
+// FIXME: this file seems replicate of curve_intersector_virtual.h
+
+namespace embree
+{
+ namespace isa
+ {
+ struct VirtualCurveIntersector1
+ {
+ typedef unsigned char Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
+ leafIntersector.intersect<1>(&pre,&ray,context,prim);
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
+ return leafIntersector.occluded<1>(&pre,&ray,context,prim);
+ }
+ };
+
+ template<int K>
+ struct VirtualCurveIntersectorK
+ {
+ typedef unsigned char Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(const vbool<K>& valid_i, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
+ size_t mask = movemask(valid_i);
+ while (mask) leafIntersector.intersect<K>(&pre,&ray,bscf(mask),context,prim);
+ }
+
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
+ vbool<K> valid_o = false;
+ size_t mask = movemask(valid_i);
+ while (mask) {
+ size_t k = bscf(mask);
+ if (leafIntersector.occluded<K>(&pre,&ray,k,context,prim))
+ set(valid_o, k);
+ }
+ return valid_o;
+ }
+
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
+ leafIntersector.intersect<K>(&pre,&ray,k,context,prim);
+ }
+
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurvePrimitive::Intersectors& leafIntersector = ((VirtualCurvePrimitive*) This->leafIntersector)->vtbl[ty];
+ return leafIntersector.occluded<K>(&pre,&ray,k,context,prim);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector_distance.h b/thirdparty/embree/kernels/geometry/curve_intersector_distance.h
new file mode 100644
index 0000000000..748a9511a5
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curve_intersector_distance.h
@@ -0,0 +1,129 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "curve_intersector_precalculations.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename NativeCurve3fa, int M>
+ struct DistanceCurveHit
+ {
+ __forceinline DistanceCurveHit() {}
+
+ __forceinline DistanceCurveHit(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const int i, const int N,
+ const NativeCurve3fa& curve3D)
+ : U(U), V(V), T(T), i(i), N(N), curve3D(curve3D), valid(valid) {}
+
+ __forceinline void finalize()
+ {
+ vu = (vfloat<M>(step)+U+vfloat<M>(float(i)))*(1.0f/float(N));
+ vv = V;
+ vt = T;
+ }
+
+ __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
+ __forceinline float t (const size_t i) const { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) const {
+ return curve3D.eval_du(vu[i]);
+ }
+
+ public:
+ vfloat<M> U;
+ vfloat<M> V;
+ vfloat<M> T;
+ int i, N;
+ NativeCurve3fa curve3D;
+
+ public:
+ vbool<M> valid;
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ };
+
+ template<typename NativeCurve3fa>
+ struct DistanceCurve1Intersector1
+ {
+ template<typename Epilog>
+ __forceinline bool intersect(const CurvePrecalculations1& pre,Ray& ray,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2, const Vec3fa& v3,
+ const Epilog& epilog)
+ {
+ const int N = geom->tessellationRate;
+
+ /* transform control points into ray space */
+ const NativeCurve3fa curve3Di(v0,v1,v2,v3);
+ const NativeCurve3fa curve3D = enlargeRadiusToMinWidth(context,geom,ray.org,curve3Di);
+ const NativeCurve3fa curve2D = curve3D.xfm_pr(pre.ray_space,ray.org);
+
+ /* evaluate the bezier curve */
+ vboolx valid = vfloatx(step) < vfloatx(float(N));
+ const Vec4vfx p0 = curve2D.template eval0<VSIZEX>(0,N);
+ const Vec4vfx p1 = curve2D.template eval1<VSIZEX>(0,N);
+
+ /* approximative intersection with cone */
+ const Vec4vfx v = p1-p0;
+ const Vec4vfx w = -p0;
+ const vfloatx d0 = madd(w.x,v.x,w.y*v.y);
+ const vfloatx d1 = madd(v.x,v.x,v.y*v.y);
+ const vfloatx u = clamp(d0*rcp(d1),vfloatx(zero),vfloatx(one));
+ const Vec4vfx p = madd(u,v,p0);
+ const vfloatx t = p.z*pre.depth_scale;
+ const vfloatx d2 = madd(p.x,p.x,p.y*p.y);
+ const vfloatx r = p.w;
+ const vfloatx r2 = r*r;
+ valid &= (d2 <= r2) & (vfloatx(ray.tnear()) <= t) & (t <= vfloatx(ray.tfar));
+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
+ valid &= t > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*pre.depth_scale; // ignore self intersections
+
+ /* update hit information */
+ bool ishit = false;
+ if (unlikely(any(valid))) {
+ DistanceCurveHit<NativeCurve3fa,VSIZEX> hit(valid,u,0.0f,t,0,N,curve3D);
+ ishit = ishit | epilog(valid,hit);
+ }
+
+ if (unlikely(VSIZEX < N))
+ {
+ /* process SIMD-size many segments per iteration */
+ for (int i=VSIZEX; i<N; i+=VSIZEX)
+ {
+ /* evaluate the bezier curve */
+ vboolx valid = vintx(i)+vintx(step) < vintx(N);
+ const Vec4vfx p0 = curve2D.template eval0<VSIZEX>(i,N);
+ const Vec4vfx p1 = curve2D.template eval1<VSIZEX>(i,N);
+
+ /* approximative intersection with cone */
+ const Vec4vfx v = p1-p0;
+ const Vec4vfx w = -p0;
+ const vfloatx d0 = madd(w.x,v.x,w.y*v.y);
+ const vfloatx d1 = madd(v.x,v.x,v.y*v.y);
+ const vfloatx u = clamp(d0*rcp(d1),vfloatx(zero),vfloatx(one));
+ const Vec4vfx p = madd(u,v,p0);
+ const vfloatx t = p.z*pre.depth_scale;
+ const vfloatx d2 = madd(p.x,p.x,p.y*p.y);
+ const vfloatx r = p.w;
+ const vfloatx r2 = r*r;
+ valid &= (d2 <= r2) & (vfloatx(ray.tnear()) <= t) & (t <= vfloatx(ray.tfar));
+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
+ valid &= t > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*pre.depth_scale; // ignore self intersections
+
+ /* update hit information */
+ if (unlikely(any(valid))) {
+ DistanceCurveHit<NativeCurve3fa,VSIZEX> hit(valid,u,0.0f,t,i,N,curve3D);
+ ishit = ishit | epilog(valid,hit);
+ }
+ }
+ }
+ return ishit;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector_oriented.h b/thirdparty/embree/kernels/geometry/curve_intersector_oriented.h
new file mode 100644
index 0000000000..3d8900c2aa
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curve_intersector_oriented.h
@@ -0,0 +1,417 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "curve_intersector_precalculations.h"
+#include "curve_intersector_sweep.h"
+#include "../subdiv/linear_bezier_patch.h"
+
+#define DBG(x)
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename Ray, typename Epilog>
+ struct TensorLinearCubicBezierSurfaceIntersector
+ {
+ const LinearSpace3fa& ray_space;
+ Ray& ray;
+ TensorLinearCubicBezierSurface3fa curve3d;
+ TensorLinearCubicBezierSurface2fa curve2d;
+ float eps;
+ const Epilog& epilog;
+ bool isHit;
+
+ __forceinline TensorLinearCubicBezierSurfaceIntersector (const LinearSpace3fa& ray_space, Ray& ray, const TensorLinearCubicBezierSurface3fa& curve3d, const Epilog& epilog)
+ : ray_space(ray_space), ray(ray), curve3d(curve3d), epilog(epilog), isHit(false)
+ {
+ const TensorLinearCubicBezierSurface3fa curve3dray = curve3d.xfm(ray_space,ray.org);
+ curve2d = TensorLinearCubicBezierSurface2fa(CubicBezierCurve2fa(curve3dray.L),CubicBezierCurve2fa(curve3dray.R));
+ const BBox2fa b2 = curve2d.bounds();
+ eps = 8.0f*float(ulp)*reduce_max(max(abs(b2.lower),abs(b2.upper)));
+ }
+
+ __forceinline Interval1f solve_linear(const float u0, const float u1, const float& p0, const float& p1)
+ {
+ if (p1 == p0) {
+ if (p0 == 0.0f) return Interval1f(u0,u1);
+ else return Interval1f(empty);
+ }
+ const float t = -p0/(p1-p0);
+ const float tt = lerp(u0,u1,t);
+ return Interval1f(tt);
+ }
+
+ __forceinline void solve_linear(const float u0, const float u1, const Interval1f& p0, const Interval1f& p1, Interval1f& u)
+ {
+ if (sign(p0.lower) != sign(p0.upper)) u.extend(u0);
+ if (sign(p0.lower) != sign(p1.lower)) u.extend(solve_linear(u0,u1,p0.lower,p1.lower));
+ if (sign(p0.upper) != sign(p1.upper)) u.extend(solve_linear(u0,u1,p0.upper,p1.upper));
+ if (sign(p1.lower) != sign(p1.upper)) u.extend(u1);
+ }
+
+ __forceinline Interval1f bezier_clipping(const CubicBezierCurve<Interval1f>& curve)
+ {
+ Interval1f u = empty;
+ solve_linear(0.0f/3.0f,1.0f/3.0f,curve.v0,curve.v1,u);
+ solve_linear(0.0f/3.0f,2.0f/3.0f,curve.v0,curve.v2,u);
+ solve_linear(0.0f/3.0f,3.0f/3.0f,curve.v0,curve.v3,u);
+ solve_linear(1.0f/3.0f,2.0f/3.0f,curve.v1,curve.v2,u);
+ solve_linear(1.0f/3.0f,3.0f/3.0f,curve.v1,curve.v3,u);
+ solve_linear(2.0f/3.0f,3.0f/3.0f,curve.v2,curve.v3,u);
+ return intersect(u,Interval1f(0.0f,1.0f));
+ }
+
+ __forceinline Interval1f bezier_clipping(const LinearBezierCurve<Interval1f>& curve)
+ {
+ Interval1f v = empty;
+ solve_linear(0.0f,1.0f,curve.v0,curve.v1,v);
+ return intersect(v,Interval1f(0.0f,1.0f));
+ }
+
+ __forceinline void solve_bezier_clipping(BBox1f cu, BBox1f cv, const TensorLinearCubicBezierSurface2fa& curve2)
+ {
+ BBox2fa bounds = curve2.bounds();
+ if (bounds.upper.x < 0.0f) return;
+ if (bounds.upper.y < 0.0f) return;
+ if (bounds.lower.x > 0.0f) return;
+ if (bounds.lower.y > 0.0f) return;
+
+ if (max(cu.size(),cv.size()) < 1E-4f)
+ {
+ const float u = cu.center();
+ const float v = cv.center();
+ TensorLinearCubicBezierSurface1f curve_z = curve3d.xfm(ray_space.row2(),ray.org);
+ const float t = curve_z.eval(u,v);
+ if (ray.tnear() <= t && t <= ray.tfar) {
+ const Vec3fa Ng = cross(curve3d.eval_du(u,v),curve3d.eval_dv(u,v));
+ BezierCurveHit hit(t,u,v,Ng);
+ isHit |= epilog(hit);
+ }
+ return;
+ }
+
+ const Vec2fa dv = curve2.axis_v();
+ const TensorLinearCubicBezierSurface1f curve1v = curve2.xfm(dv);
+ LinearBezierCurve<Interval1f> curve0v = curve1v.reduce_u();
+ if (!curve0v.hasRoot()) return;
+
+ const Interval1f v = bezier_clipping(curve0v);
+ if (isEmpty(v)) return;
+ TensorLinearCubicBezierSurface2fa curve2a = curve2.clip_v(v);
+ cv = BBox1f(lerp(cv.lower,cv.upper,v.lower),lerp(cv.lower,cv.upper,v.upper));
+
+ const Vec2fa du = curve2.axis_u();
+ const TensorLinearCubicBezierSurface1f curve1u = curve2a.xfm(du);
+ CubicBezierCurve<Interval1f> curve0u = curve1u.reduce_v();
+ int roots = curve0u.maxRoots();
+ if (roots == 0) return;
+
+ if (roots == 1)
+ {
+ const Interval1f u = bezier_clipping(curve0u);
+ if (isEmpty(u)) return;
+ TensorLinearCubicBezierSurface2fa curve2b = curve2a.clip_u(u);
+ cu = BBox1f(lerp(cu.lower,cu.upper,u.lower),lerp(cu.lower,cu.upper,u.upper));
+ solve_bezier_clipping(cu,cv,curve2b);
+ return;
+ }
+
+ TensorLinearCubicBezierSurface2fa curve2l, curve2r;
+ curve2a.split_u(curve2l,curve2r);
+ solve_bezier_clipping(BBox1f(cu.lower,cu.center()),cv,curve2l);
+ solve_bezier_clipping(BBox1f(cu.center(),cu.upper),cv,curve2r);
+ }
+
+ __forceinline bool solve_bezier_clipping()
+ {
+ solve_bezier_clipping(BBox1f(0.0f,1.0f),BBox1f(0.0f,1.0f),curve2d);
+ return isHit;
+ }
+
+ __forceinline void solve_newton_raphson(BBox1f cu, BBox1f cv)
+ {
+ Vec2fa uv(cu.center(),cv.center());
+ const Vec2fa dfdu = curve2d.eval_du(uv.x,uv.y);
+ const Vec2fa dfdv = curve2d.eval_dv(uv.x,uv.y);
+ const LinearSpace2fa rcp_J = rcp(LinearSpace2fa(dfdu,dfdv));
+ solve_newton_raphson_loop(cu,cv,uv,dfdu,dfdv,rcp_J);
+ }
+
+ __forceinline void solve_newton_raphson_loop(BBox1f cu, BBox1f cv, const Vec2fa& uv_in, const Vec2fa& dfdu, const Vec2fa& dfdv, const LinearSpace2fa& rcp_J)
+ {
+ Vec2fa uv = uv_in;
+
+ for (size_t i=0; i<200; i++)
+ {
+ const Vec2fa f = curve2d.eval(uv.x,uv.y);
+ const Vec2fa duv = rcp_J*f;
+ uv -= duv;
+
+ if (max(abs(f.x),abs(f.y)) < eps)
+ {
+ const float u = uv.x;
+ const float v = uv.y;
+ if (!(u >= 0.0f && u <= 1.0f)) return; // rejects NaNs
+ if (!(v >= 0.0f && v <= 1.0f)) return; // rejects NaNs
+ const TensorLinearCubicBezierSurface1f curve_z = curve3d.xfm(ray_space.row2(),ray.org);
+ const float t = curve_z.eval(u,v);
+ if (!(ray.tnear() <= t && t <= ray.tfar)) return; // rejects NaNs
+ const Vec3fa Ng = cross(curve3d.eval_du(u,v),curve3d.eval_dv(u,v));
+ BezierCurveHit hit(t,u,v,Ng);
+ isHit |= epilog(hit);
+ return;
+ }
+ }
+ }
+
+ __forceinline bool clip_v(BBox1f& cu, BBox1f& cv)
+ {
+ const Vec2fa dv = curve2d.eval_dv(cu.lower,cv.lower);
+ const TensorLinearCubicBezierSurface1f curve1v = curve2d.xfm(dv).clip(cu,cv);
+ LinearBezierCurve<Interval1f> curve0v = curve1v.reduce_u();
+ if (!curve0v.hasRoot()) return false;
+ Interval1f v = bezier_clipping(curve0v);
+ if (isEmpty(v)) return false;
+ v = intersect(v + Interval1f(-0.1f,+0.1f),Interval1f(0.0f,1.0f));
+ cv = BBox1f(lerp(cv.lower,cv.upper,v.lower),lerp(cv.lower,cv.upper,v.upper));
+ return true;
+ }
+
+ __forceinline bool solve_krawczyk(bool very_small, BBox1f& cu, BBox1f& cv)
+ {
+ /* perform bezier clipping in v-direction to get tight v-bounds */
+ TensorLinearCubicBezierSurface2fa curve2 = curve2d.clip(cu,cv);
+ const Vec2fa dv = curve2.axis_v();
+ const TensorLinearCubicBezierSurface1f curve1v = curve2.xfm(dv);
+ LinearBezierCurve<Interval1f> curve0v = curve1v.reduce_u();
+ if (unlikely(!curve0v.hasRoot())) return true;
+ Interval1f v = bezier_clipping(curve0v);
+ if (unlikely(isEmpty(v))) return true;
+ v = intersect(v + Interval1f(-0.1f,+0.1f),Interval1f(0.0f,1.0f));
+ curve2 = curve2.clip_v(v);
+ cv = BBox1f(lerp(cv.lower,cv.upper,v.lower),lerp(cv.lower,cv.upper,v.upper));
+
+ /* perform one newton raphson iteration */
+ Vec2fa c(cu.center(),cv.center());
+ Vec2fa f,dfdu,dfdv; curve2d.eval(c.x,c.y,f,dfdu,dfdv);
+ const LinearSpace2fa rcp_J = rcp(LinearSpace2fa(dfdu,dfdv));
+ const Vec2fa c1 = c - rcp_J*f;
+
+ /* calculate bounds of derivatives */
+ const BBox2fa bounds_du = (1.0f/cu.size())*curve2.derivative_u().bounds();
+ const BBox2fa bounds_dv = (1.0f/cv.size())*curve2.derivative_v().bounds();
+
+ /* calculate krawczyk test */
+ LinearSpace2<Vec2<Interval1f>> I(Interval1f(1.0f), Interval1f(0.0f),
+ Interval1f(0.0f), Interval1f(1.0f));
+
+ LinearSpace2<Vec2<Interval1f>> G(Interval1f(bounds_du.lower.x,bounds_du.upper.x), Interval1f(bounds_dv.lower.x,bounds_dv.upper.x),
+ Interval1f(bounds_du.lower.y,bounds_du.upper.y), Interval1f(bounds_dv.lower.y,bounds_dv.upper.y));
+
+ const LinearSpace2<Vec2f> rcp_J2(rcp_J);
+ const LinearSpace2<Vec2<Interval1f>> rcp_Ji(rcp_J2);
+
+ const Vec2<Interval1f> x(cu,cv);
+ const Vec2<Interval1f> K = Vec2<Interval1f>(Vec2f(c1)) + (I - rcp_Ji*G)*(x-Vec2<Interval1f>(Vec2f(c)));
+
+ /* test if there is no solution */
+ const Vec2<Interval1f> KK = intersect(K,x);
+ if (unlikely(isEmpty(KK.x) || isEmpty(KK.y))) return true;
+
+ /* exit if convergence cannot get proven, but terminate if we are very small */
+ if (unlikely(!subset(K,x) && !very_small)) return false;
+
+ /* solve using newton raphson iteration of convergence is guarenteed */
+ solve_newton_raphson_loop(cu,cv,c1,dfdu,dfdv,rcp_J);
+ return true;
+ }
+
+ __forceinline void solve_newton_raphson_no_recursion(BBox1f cu, BBox1f cv)
+ {
+ if (!clip_v(cu,cv)) return;
+ return solve_newton_raphson(cu,cv);
+ }
+
+ __forceinline void solve_newton_raphson_recursion(BBox1f cu, BBox1f cv)
+ {
+ unsigned int sptr = 0;
+ const unsigned int stack_size = 4;
+ unsigned int mask_stack[stack_size];
+ BBox1f cu_stack[stack_size];
+ BBox1f cv_stack[stack_size];
+ goto entry;
+
+ /* terminate if stack is empty */
+ while (sptr)
+ {
+ /* pop from stack */
+ {
+ sptr--;
+ size_t mask = mask_stack[sptr];
+ cu = cu_stack[sptr];
+ cv = cv_stack[sptr];
+ const size_t i = bscf(mask);
+ mask_stack[sptr] = mask;
+ if (mask) sptr++; // there are still items on the stack
+
+ /* process next element recurse into each hit curve segment */
+ const float u0 = float(i+0)*(1.0f/(VSIZEX-1));
+ const float u1 = float(i+1)*(1.0f/(VSIZEX-1));
+ const BBox1f cui(lerp(cu.lower,cu.upper,u0),lerp(cu.lower,cu.upper,u1));
+ cu = cui;
+ }
+
+#if 0
+ solve_newton_raphson_no_recursion(cu,cv);
+ continue;
+
+#else
+ /* we assume convergence for small u ranges and verify using krawczyk */
+ if (cu.size() < 1.0f/6.0f) {
+ const bool very_small = cu.size() < 0.001f || sptr >= stack_size;
+ if (solve_krawczyk(very_small,cu,cv)) {
+ continue;
+ }
+ }
+#endif
+
+ entry:
+
+ /* split the curve into VSIZEX-1 segments in u-direction */
+ vboolx valid = true;
+ TensorLinearCubicBezierSurface<Vec2vfx> subcurves = curve2d.clip_v(cv).vsplit_u(valid,cu);
+
+ /* slabs test in u-direction */
+ Vec2vfx ndv = cross(subcurves.axis_v());
+ BBox<vfloatx> boundsv = subcurves.vxfm(ndv).bounds();
+ valid &= boundsv.lower <= eps;
+ valid &= boundsv.upper >= -eps;
+ if (none(valid)) continue;
+
+ /* slabs test in v-direction */
+ Vec2vfx ndu = cross(subcurves.axis_u());
+ BBox<vfloatx> boundsu = subcurves.vxfm(ndu).bounds();
+ valid &= boundsu.lower <= eps;
+ valid &= boundsu.upper >= -eps;
+ if (none(valid)) continue;
+
+ /* push valid segments to stack */
+ assert(sptr < stack_size);
+ mask_stack [sptr] = movemask(valid);
+ cu_stack [sptr] = cu;
+ cv_stack [sptr] = cv;
+ sptr++;
+ }
+ }
+
+ __forceinline bool solve_newton_raphson_main()
+ {
+ BBox1f vu(0.0f,1.0f);
+ BBox1f vv(0.0f,1.0f);
+ solve_newton_raphson_recursion(vu,vv);
+ return isHit;
+ }
+ };
+
+
+ template<template<typename Ty> class SourceCurve>
+ struct OrientedCurve1Intersector1
+ {
+ //template<typename Ty> using Curve = SourceCurve<Ty>;
+ typedef SourceCurve<Vec3ff> SourceCurve3ff;
+ typedef SourceCurve<Vec3fa> SourceCurve3fa;
+
+ __forceinline OrientedCurve1Intersector1() {}
+
+ __forceinline OrientedCurve1Intersector1(const Ray& ray, const void* ptr) {}
+
+ template<typename Epilog>
+ __noinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const Vec3ff& v0i, const Vec3ff& v1i, const Vec3ff& v2i, const Vec3ff& v3i,
+ const Vec3fa& n0i, const Vec3fa& n1i, const Vec3fa& n2i, const Vec3fa& n3i,
+ const Epilog& epilog) const
+ {
+ STAT3(normal.trav_prims,1,1,1);
+
+ SourceCurve3ff ccurve(v0i,v1i,v2i,v3i);
+ SourceCurve3fa ncurve(n0i,n1i,n2i,n3i);
+ ccurve = enlargeRadiusToMinWidth(context,geom,ray.org,ccurve);
+ TensorLinearCubicBezierSurface3fa curve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
+ //return TensorLinearCubicBezierSurfaceIntersector<Ray,Epilog>(pre.ray_space,ray,curve,epilog).solve_bezier_clipping();
+ return TensorLinearCubicBezierSurfaceIntersector<Ray,Epilog>(pre.ray_space,ray,curve,epilog).solve_newton_raphson_main();
+ }
+
+ template<typename Epilog>
+ __noinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const TensorLinearCubicBezierSurface3fa& curve, const Epilog& epilog) const
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ //return TensorLinearCubicBezierSurfaceIntersector<Ray,Epilog>(pre.ray_space,ray,curve,epilog).solve_bezier_clipping();
+ return TensorLinearCubicBezierSurfaceIntersector<Ray,Epilog>(pre.ray_space,ray,curve,epilog).solve_newton_raphson_main();
+ }
+ };
+
+ template<template<typename Ty> class SourceCurve, int K>
+ struct OrientedCurve1IntersectorK
+ {
+ //template<typename Ty> using Curve = SourceCurve<Ty>;
+ typedef SourceCurve<Vec3ff> SourceCurve3ff;
+ typedef SourceCurve<Vec3fa> SourceCurve3fa;
+
+ struct Ray1
+ {
+ __forceinline Ray1(RayK<K>& ray, size_t k)
+ : org(ray.org.x[k],ray.org.y[k],ray.org.z[k]), dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]), _tnear(ray.tnear()[k]), tfar(ray.tfar[k]) {}
+
+ Vec3fa org;
+ Vec3fa dir;
+ float _tnear;
+ float& tfar;
+
+ __forceinline float& tnear() { return _tnear; }
+ //__forceinline float& tfar() { return _tfar; }
+ __forceinline const float& tnear() const { return _tnear; }
+ //__forceinline const float& tfar() const { return _tfar; }
+ };
+
+ template<typename Epilog>
+ __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& vray, size_t k,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const Vec3ff& v0i, const Vec3ff& v1i, const Vec3ff& v2i, const Vec3ff& v3i,
+ const Vec3fa& n0i, const Vec3fa& n1i, const Vec3fa& n2i, const Vec3fa& n3i,
+ const Epilog& epilog)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Ray1 ray(vray,k);
+ SourceCurve3ff ccurve(v0i,v1i,v2i,v3i);
+ SourceCurve3fa ncurve(n0i,n1i,n2i,n3i);
+ ccurve = enlargeRadiusToMinWidth(context,geom,ray.org,ccurve);
+ TensorLinearCubicBezierSurface3fa curve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
+ //return TensorLinearCubicBezierSurfaceIntersector<Ray1,Epilog>(pre.ray_space[k],ray,curve,epilog).solve_bezier_clipping();
+ return TensorLinearCubicBezierSurfaceIntersector<Ray1,Epilog>(pre.ray_space[k],ray,curve,epilog).solve_newton_raphson_main();
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& vray, size_t k,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const TensorLinearCubicBezierSurface3fa& curve,
+ const Epilog& epilog)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Ray1 ray(vray,k);
+ //return TensorLinearCubicBezierSurfaceIntersector<Ray1,Epilog>(pre.ray_space[k],ray,curve,epilog).solve_bezier_clipping();
+ return TensorLinearCubicBezierSurfaceIntersector<Ray1,Epilog>(pre.ray_space[k],ray,curve,epilog).solve_newton_raphson_main();
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector_precalculations.h b/thirdparty/embree/kernels/geometry/curve_intersector_precalculations.h
new file mode 100644
index 0000000000..de6b70be1b
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curve_intersector_precalculations.h
@@ -0,0 +1,49 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "../common/geometry.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct CurvePrecalculations1
+ {
+ float depth_scale;
+ LinearSpace3fa ray_space;
+
+ __forceinline CurvePrecalculations1() {}
+
+ __forceinline CurvePrecalculations1(const Ray& ray, const void* ptr)
+ {
+ depth_scale = rsqrt(dot(ray.dir,ray.dir));
+ LinearSpace3fa space = frame(depth_scale*ray.dir);
+ space.vz *= depth_scale;
+ ray_space = space.transposed();
+ }
+ };
+
+ template<int K>
+ struct CurvePrecalculationsK
+ {
+ vfloat<K> depth_scale;
+ LinearSpace3fa ray_space[K];
+
+ __forceinline CurvePrecalculationsK(const vbool<K>& valid, const RayK<K>& ray)
+ {
+ size_t mask = movemask(valid);
+ depth_scale = rsqrt(dot(ray.dir,ray.dir));
+ while (mask) {
+ size_t k = bscf(mask);
+ Vec3fa ray_dir_k = Vec3fa(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
+ LinearSpace3fa ray_space_k = frame(depth_scale[k]*ray_dir_k);
+ ray_space_k.vz *= depth_scale[k];
+ ray_space[k] = ray_space_k.transposed();
+ }
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector_ribbon.h b/thirdparty/embree/kernels/geometry/curve_intersector_ribbon.h
new file mode 100644
index 0000000000..c3272e99fd
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curve_intersector_ribbon.h
@@ -0,0 +1,216 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "quad_intersector.h"
+#include "curve_intersector_precalculations.h"
+
+#define Bezier1Intersector1 RibbonCurve1Intersector1
+#define Bezier1IntersectorK RibbonCurve1IntersectorK
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename NativeCurve3ff, int M>
+ struct RibbonHit
+ {
+ __forceinline RibbonHit() {}
+
+ __forceinline RibbonHit(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const int i, const int N,
+ const NativeCurve3ff& curve3D)
+ : U(U), V(V), T(T), i(i), N(N), curve3D(curve3D), valid(valid) {}
+
+ __forceinline void finalize()
+ {
+ vu = (vfloat<M>(step)+U+vfloat<M>(float(i)))*(1.0f/float(N));
+ vv = V;
+ vt = T;
+ }
+
+ __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
+ __forceinline float t (const size_t i) const { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) const { return curve3D.eval_du(vu[i]); }
+
+ __forceinline Vec2vf<M> uv() const { return Vec2vf<M>(vu,vv); }
+ __forceinline vfloat<M> t () const { return vt; }
+ __forceinline Vec3vf<M> Ng() const { return (Vec3vf<M>) curve3D.template veval_du<M>(vu); }
+
+ public:
+ vfloat<M> U;
+ vfloat<M> V;
+ vfloat<M> T;
+ int i, N;
+ NativeCurve3ff curve3D;
+
+ public:
+ vbool<M> valid;
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ };
+
+ /* calculate squared distance of point p0 to line p1->p2 */
+ __forceinline std::pair<vfloatx,vfloatx> sqr_point_line_distance(const Vec2vfx& p0, const Vec2vfx& p1, const Vec2vfx& p2)
+ {
+ const vfloatx num = det(p2-p1,p1-p0);
+ const vfloatx den2 = dot(p2-p1,p2-p1);
+ return std::make_pair(num*num,den2);
+ }
+
+ /* performs culling against a cylinder */
+ __forceinline vboolx cylinder_culling_test(const Vec2vfx& p0, const Vec2vfx& p1, const Vec2vfx& p2, const vfloatx& r)
+ {
+ const std::pair<vfloatx,vfloatx> d = sqr_point_line_distance(p0,p1,p2);
+ return d.first <= r*r*d.second;
+ }
+
+ template<typename NativeCurve3ff, typename Epilog>
+ __forceinline bool intersect_ribbon(const Vec3fa& ray_org, const Vec3fa& ray_dir, const float ray_tnear, const float& ray_tfar,
+ const LinearSpace3fa& ray_space, const float& depth_scale,
+ const NativeCurve3ff& curve3D, const int N,
+ const Epilog& epilog)
+ {
+ /* transform control points into ray space */
+ const NativeCurve3ff curve2D = curve3D.xfm_pr(ray_space,ray_org);
+ float eps = 4.0f*float(ulp)*reduce_max(max(abs(curve2D.v0),abs(curve2D.v1),abs(curve2D.v2),abs(curve2D.v3)));
+
+ /* evaluate the bezier curve */
+ bool ishit = false;
+ vboolx valid = vfloatx(step) < vfloatx(float(N));
+ const Vec4vfx p0 = curve2D.template eval0<VSIZEX>(0,N);
+ const Vec4vfx p1 = curve2D.template eval1<VSIZEX>(0,N);
+ valid &= cylinder_culling_test(zero,Vec2vfx(p0.x,p0.y),Vec2vfx(p1.x,p1.y),max(p0.w,p1.w));
+
+ if (any(valid))
+ {
+ Vec3vfx dp0dt = curve2D.template derivative0<VSIZEX>(0,N);
+ Vec3vfx dp1dt = curve2D.template derivative1<VSIZEX>(0,N);
+ dp0dt = select(reduce_max(abs(dp0dt)) < vfloatx(eps),Vec3vfx(p1-p0),dp0dt);
+ dp1dt = select(reduce_max(abs(dp1dt)) < vfloatx(eps),Vec3vfx(p1-p0),dp1dt);
+ const Vec3vfx n0(dp0dt.y,-dp0dt.x,0.0f);
+ const Vec3vfx n1(dp1dt.y,-dp1dt.x,0.0f);
+ const Vec3vfx nn0 = normalize(n0);
+ const Vec3vfx nn1 = normalize(n1);
+ const Vec3vfx lp0 = madd(p0.w,nn0,Vec3vfx(p0));
+ const Vec3vfx lp1 = madd(p1.w,nn1,Vec3vfx(p1));
+ const Vec3vfx up0 = nmadd(p0.w,nn0,Vec3vfx(p0));
+ const Vec3vfx up1 = nmadd(p1.w,nn1,Vec3vfx(p1));
+
+ vfloatx vu,vv,vt;
+ vboolx valid0 = intersect_quad_backface_culling<VSIZEX>(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt);
+
+ if (any(valid0))
+ {
+ /* ignore self intersections */
+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f) {
+ vfloatx r = lerp(p0.w, p1.w, vu);
+ valid0 &= vt > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale;
+ }
+
+ if (any(valid0))
+ {
+ vv = madd(2.0f,vv,vfloatx(-1.0f));
+ RibbonHit<NativeCurve3ff,VSIZEX> bhit(valid0,vu,vv,vt,0,N,curve3D);
+ ishit |= epilog(bhit.valid,bhit);
+ }
+ }
+ }
+
+ if (unlikely(VSIZEX < N))
+ {
+ /* process SIMD-size many segments per iteration */
+ for (int i=VSIZEX; i<N; i+=VSIZEX)
+ {
+ /* evaluate the bezier curve */
+ vboolx valid = vintx(i)+vintx(step) < vintx(N);
+ const Vec4vfx p0 = curve2D.template eval0<VSIZEX>(i,N);
+ const Vec4vfx p1 = curve2D.template eval1<VSIZEX>(i,N);
+ valid &= cylinder_culling_test(zero,Vec2vfx(p0.x,p0.y),Vec2vfx(p1.x,p1.y),max(p0.w,p1.w));
+ if (none(valid)) continue;
+
+ Vec3vfx dp0dt = curve2D.template derivative0<VSIZEX>(i,N);
+ Vec3vfx dp1dt = curve2D.template derivative1<VSIZEX>(i,N);
+ dp0dt = select(reduce_max(abs(dp0dt)) < vfloatx(eps),Vec3vfx(p1-p0),dp0dt);
+ dp1dt = select(reduce_max(abs(dp1dt)) < vfloatx(eps),Vec3vfx(p1-p0),dp1dt);
+ const Vec3vfx n0(dp0dt.y,-dp0dt.x,0.0f);
+ const Vec3vfx n1(dp1dt.y,-dp1dt.x,0.0f);
+ const Vec3vfx nn0 = normalize(n0);
+ const Vec3vfx nn1 = normalize(n1);
+ const Vec3vfx lp0 = madd(p0.w,nn0,Vec3vfx(p0));
+ const Vec3vfx lp1 = madd(p1.w,nn1,Vec3vfx(p1));
+ const Vec3vfx up0 = nmadd(p0.w,nn0,Vec3vfx(p0));
+ const Vec3vfx up1 = nmadd(p1.w,nn1,Vec3vfx(p1));
+
+ vfloatx vu,vv,vt;
+ vboolx valid0 = intersect_quad_backface_culling<VSIZEX>(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt);
+
+ if (any(valid0))
+ {
+ /* ignore self intersections */
+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f) {
+ vfloatx r = lerp(p0.w, p1.w, vu);
+ valid0 &= vt > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale;
+ }
+
+ if (any(valid0))
+ {
+ vv = madd(2.0f,vv,vfloatx(-1.0f));
+ RibbonHit<NativeCurve3ff,VSIZEX> bhit(valid0,vu,vv,vt,i,N,curve3D);
+ ishit |= epilog(bhit.valid,bhit);
+ }
+ }
+ }
+ }
+ return ishit;
+ }
+
+ template<template<typename Ty> class NativeCurve>
+ struct RibbonCurve1Intersector1
+ {
+ typedef NativeCurve<Vec3ff> NativeCurve3ff;
+
+ template<typename Epilog>
+ __forceinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
+ const Epilog& epilog)
+ {
+ const int N = geom->tessellationRate;
+ NativeCurve3ff curve(v0,v1,v2,v3);
+ curve = enlargeRadiusToMinWidth(context,geom,ray.org,curve);
+ return intersect_ribbon<NativeCurve3ff>(ray.org,ray.dir,ray.tnear(),ray.tfar,
+ pre.ray_space,pre.depth_scale,
+ curve,N,
+ epilog);
+ }
+ };
+
+ template<template<typename Ty> class NativeCurve, int K>
+ struct RibbonCurve1IntersectorK
+ {
+ typedef NativeCurve<Vec3ff> NativeCurve3ff;
+
+ template<typename Epilog>
+ __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
+ const Epilog& epilog)
+ {
+ const int N = geom->tessellationRate;
+ const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
+ const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
+ NativeCurve3ff curve(v0,v1,v2,v3);
+ curve = enlargeRadiusToMinWidth(context,geom,ray_org,curve);
+ return intersect_ribbon<NativeCurve3ff>(ray_org,ray_dir,ray.tnear()[k],ray.tfar[k],
+ pre.ray_space[k],pre.depth_scale[k],
+ curve,N,
+ epilog);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector_sweep.h b/thirdparty/embree/kernels/geometry/curve_intersector_sweep.h
new file mode 100644
index 0000000000..2d4abd73ac
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curve_intersector_sweep.h
@@ -0,0 +1,364 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "cylinder.h"
+#include "plane.h"
+#include "line_intersector.h"
+#include "curve_intersector_precalculations.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ static const size_t numJacobianIterations = 5;
+#if defined(__AVX__)
+ static const size_t numBezierSubdivisions = 2;
+#else
+ static const size_t numBezierSubdivisions = 3;
+#endif
+
+ struct BezierCurveHit
+ {
+ __forceinline BezierCurveHit() {}
+
+ __forceinline BezierCurveHit(const float t, const float u, const Vec3fa& Ng)
+ : t(t), u(u), v(0.0f), Ng(Ng) {}
+
+ __forceinline BezierCurveHit(const float t, const float u, const float v, const Vec3fa& Ng)
+ : t(t), u(u), v(v), Ng(Ng) {}
+
+ __forceinline void finalize() {}
+
+ public:
+ float t;
+ float u;
+ float v;
+ Vec3fa Ng;
+ };
+
+ template<typename NativeCurve3ff, typename Ray, typename Epilog>
+ __forceinline bool intersect_bezier_iterative_debug(const Ray& ray, const float dt, const NativeCurve3ff& curve, size_t i,
+ const vfloatx& u, const BBox<vfloatx>& tp, const BBox<vfloatx>& h0, const BBox<vfloatx>& h1,
+ const Vec3vfx& Ng, const Vec4vfx& dP0du, const Vec4vfx& dP3du,
+ const Epilog& epilog)
+ {
+ if (tp.lower[i]+dt > ray.tfar) return false;
+ Vec3fa Ng_o = Vec3fa(Ng.x[i],Ng.y[i],Ng.z[i]);
+ if (h0.lower[i] == tp.lower[i]) Ng_o = -Vec3fa(dP0du.x[i],dP0du.y[i],dP0du.z[i]);
+ if (h1.lower[i] == tp.lower[i]) Ng_o = +Vec3fa(dP3du.x[i],dP3du.y[i],dP3du.z[i]);
+ BezierCurveHit hit(tp.lower[i]+dt,u[i],Ng_o);
+ return epilog(hit);
+ }
+
+ template<typename NativeCurve3ff, typename Ray, typename Epilog>
+ __forceinline bool intersect_bezier_iterative_jacobian(const Ray& ray, const float dt, const NativeCurve3ff& curve, float u, float t, const Epilog& epilog)
+ {
+ const Vec3fa org = zero;
+ const Vec3fa dir = ray.dir;
+ const float length_ray_dir = length(dir);
+
+ /* error of curve evaluations is propertional to largest coordinate */
+ const BBox3ff box = curve.bounds();
+ const float P_err = 16.0f*float(ulp)*reduce_max(max(abs(box.lower),abs(box.upper)));
+
+ for (size_t i=0; i<numJacobianIterations; i++)
+ {
+ const Vec3fa Q = madd(Vec3fa(t),dir,org);
+ //const Vec3fa dQdu = zero;
+ const Vec3fa dQdt = dir;
+ const float Q_err = 16.0f*float(ulp)*length_ray_dir*t; // works as org=zero here
+
+ Vec3ff P,dPdu,ddPdu; curve.eval(u,P,dPdu,ddPdu);
+ //const Vec3fa dPdt = zero;
+
+ const Vec3fa R = Q-P;
+ const float len_R = length(R); //reduce_max(abs(R));
+ const float R_err = max(Q_err,P_err);
+ const Vec3fa dRdu = /*dQdu*/-dPdu;
+ const Vec3fa dRdt = dQdt;//-dPdt;
+
+ const Vec3fa T = normalize(dPdu);
+ const Vec3fa dTdu = dnormalize(dPdu,ddPdu);
+ //const Vec3fa dTdt = zero;
+ const float cos_err = P_err/length(dPdu);
+
+ /* Error estimate for dot(R,T):
+
+ dot(R,T) = cos(R,T) |R| |T|
+ = (cos(R,T) +- cos_error) * (|R| +- |R|_err) * (|T| +- |T|_err)
+ = cos(R,T)*|R|*|T|
+ +- cos(R,T)*(|R|*|T|_err + |T|*|R|_err)
+ +- cos_error*(|R| + |T|)
+ +- lower order terms
+ with cos(R,T) being in [0,1] and |T| = 1 we get:
+ dot(R,T)_err = |R|*|T|_err + |R|_err = cos_error*(|R|+1)
+ */
+
+ const float f = dot(R,T);
+ const float f_err = len_R*P_err + R_err + cos_err*(1.0f+len_R);
+ const float dfdu = dot(dRdu,T) + dot(R,dTdu);
+ const float dfdt = dot(dRdt,T);// + dot(R,dTdt);
+
+ const float K = dot(R,R)-sqr(f);
+ const float dKdu = /*2.0f*/(dot(R,dRdu)-f*dfdu);
+ const float dKdt = /*2.0f*/(dot(R,dRdt)-f*dfdt);
+ const float rsqrt_K = rsqrt(K);
+
+ const float g = sqrt(K)-P.w;
+ const float g_err = R_err + f_err + 16.0f*float(ulp)*box.upper.w;
+ const float dgdu = /*0.5f*/dKdu*rsqrt_K-dPdu.w;
+ const float dgdt = /*0.5f*/dKdt*rsqrt_K;//-dPdt.w;
+
+ const LinearSpace2f J = LinearSpace2f(dfdu,dfdt,dgdu,dgdt);
+ const Vec2f dut = rcp(J)*Vec2f(f,g);
+ const Vec2f ut = Vec2f(u,t) - dut;
+ u = ut.x; t = ut.y;
+
+ if (abs(f) < f_err && abs(g) < g_err)
+ {
+ t+=dt;
+ if (!(ray.tnear() <= t && t <= ray.tfar)) return false; // rejects NaNs
+ if (!(u >= 0.0f && u <= 1.0f)) return false; // rejects NaNs
+ const Vec3fa R = normalize(Q-P);
+ const Vec3fa U = madd(Vec3fa(dPdu.w),R,dPdu);
+ const Vec3fa V = cross(dPdu,R);
+ BezierCurveHit hit(t,u,cross(V,U));
+ return epilog(hit);
+ }
+ }
+ return false;
+ }
+
+ template<typename NativeCurve3ff, typename Ray, typename Epilog>
+ bool intersect_bezier_recursive_jacobian(const Ray& ray, const float dt, const NativeCurve3ff& curve,
+ float u0, float u1, unsigned int depth, const Epilog& epilog)
+ {
+#if defined(__AVX__)
+ enum { VSIZEX_ = 8 };
+ typedef vbool8 vboolx; // maximally 8-wide to work around KNL issues
+ typedef vint8 vintx;
+ typedef vfloat8 vfloatx;
+#else
+ enum { VSIZEX_ = 4 };
+ typedef vbool4 vboolx;
+ typedef vint4 vintx;
+ typedef vfloat4 vfloatx;
+#endif
+ typedef Vec3<vfloatx> Vec3vfx;
+ typedef Vec4<vfloatx> Vec4vfx;
+
+ unsigned int maxDepth = numBezierSubdivisions;
+ bool found = false;
+ const Vec3fa org = zero;
+ const Vec3fa dir = ray.dir;
+
+ unsigned int sptr = 0;
+ const unsigned int stack_size = numBezierSubdivisions+1; // +1 because of unstable workaround below
+ struct StackEntry {
+ vboolx valid;
+ vfloatx tlower;
+ float u0;
+ float u1;
+ unsigned int depth;
+ };
+ StackEntry stack[stack_size];
+ goto entry;
+
+ /* terminate if stack is empty */
+ while (sptr)
+ {
+ /* pop from stack */
+ {
+ sptr--;
+ vboolx valid = stack[sptr].valid;
+ const vfloatx tlower = stack[sptr].tlower;
+ valid &= tlower+dt <= ray.tfar;
+ if (none(valid)) continue;
+ u0 = stack[sptr].u0;
+ u1 = stack[sptr].u1;
+ depth = stack[sptr].depth;
+ const size_t i = select_min(valid,tlower); clear(valid,i);
+ stack[sptr].valid = valid;
+ if (any(valid)) sptr++; // there are still items on the stack
+
+ /* process next segment */
+ const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(vfloatx::size-1)));
+ u0 = vu0[i+0];
+ u1 = vu0[i+1];
+ }
+ entry:
+
+ /* subdivide curve */
+ const float dscale = (u1-u0)*(1.0f/(3.0f*(vfloatx::size-1)));
+ const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(vfloatx::size-1)));
+ Vec4vfx P0, dP0du; curve.template veval<VSIZEX_>(vu0,P0,dP0du); dP0du = dP0du * Vec4vfx(dscale);
+ const Vec4vfx P3 = shift_right_1(P0);
+ const Vec4vfx dP3du = shift_right_1(dP0du);
+ const Vec4vfx P1 = P0 + dP0du;
+ const Vec4vfx P2 = P3 - dP3du;
+
+ /* calculate bounding cylinders */
+ const vfloatx rr1 = sqr_point_to_line_distance(Vec3vfx(dP0du),Vec3vfx(P3-P0));
+ const vfloatx rr2 = sqr_point_to_line_distance(Vec3vfx(dP3du),Vec3vfx(P3-P0));
+ const vfloatx maxr12 = sqrt(max(rr1,rr2));
+ const vfloatx one_plus_ulp = 1.0f+2.0f*float(ulp);
+ const vfloatx one_minus_ulp = 1.0f-2.0f*float(ulp);
+ vfloatx r_outer = max(P0.w,P1.w,P2.w,P3.w)+maxr12;
+ vfloatx r_inner = min(P0.w,P1.w,P2.w,P3.w)-maxr12;
+ r_outer = one_plus_ulp*r_outer;
+ r_inner = max(0.0f,one_minus_ulp*r_inner);
+ const CylinderN<vfloatx::size> cylinder_outer(Vec3vfx(P0),Vec3vfx(P3),r_outer);
+ const CylinderN<vfloatx::size> cylinder_inner(Vec3vfx(P0),Vec3vfx(P3),r_inner);
+ vboolx valid = true; clear(valid,vfloatx::size-1);
+
+ /* intersect with outer cylinder */
+ BBox<vfloatx> tc_outer; vfloatx u_outer0; Vec3vfx Ng_outer0; vfloatx u_outer1; Vec3vfx Ng_outer1;
+ valid &= cylinder_outer.intersect(org,dir,tc_outer,u_outer0,Ng_outer0,u_outer1,Ng_outer1);
+ if (none(valid)) continue;
+
+ /* intersect with cap-planes */
+ BBox<vfloatx> tp(ray.tnear()-dt,ray.tfar-dt);
+ tp = embree::intersect(tp,tc_outer);
+ BBox<vfloatx> h0 = HalfPlaneN<vfloatx::size>(Vec3vfx(P0),+Vec3vfx(dP0du)).intersect(org,dir);
+ tp = embree::intersect(tp,h0);
+ BBox<vfloatx> h1 = HalfPlaneN<vfloatx::size>(Vec3vfx(P3),-Vec3vfx(dP3du)).intersect(org,dir);
+ tp = embree::intersect(tp,h1);
+ valid &= tp.lower <= tp.upper;
+ if (none(valid)) continue;
+
+ /* clamp and correct u parameter */
+ u_outer0 = clamp(u_outer0,vfloatx(0.0f),vfloatx(1.0f));
+ u_outer1 = clamp(u_outer1,vfloatx(0.0f),vfloatx(1.0f));
+ u_outer0 = lerp(u0,u1,(vfloatx(step)+u_outer0)*(1.0f/float(vfloatx::size)));
+ u_outer1 = lerp(u0,u1,(vfloatx(step)+u_outer1)*(1.0f/float(vfloatx::size)));
+
+ /* intersect with inner cylinder */
+ BBox<vfloatx> tc_inner;
+ vfloatx u_inner0 = zero; Vec3vfx Ng_inner0 = zero; vfloatx u_inner1 = zero; Vec3vfx Ng_inner1 = zero;
+ const vboolx valid_inner = cylinder_inner.intersect(org,dir,tc_inner,u_inner0,Ng_inner0,u_inner1,Ng_inner1);
+
+ /* at the unstable area we subdivide deeper */
+ const vboolx unstable0 = (!valid_inner) | (abs(dot(Vec3vfx(Vec3fa(ray.dir)),Ng_inner0)) < 0.3f);
+ const vboolx unstable1 = (!valid_inner) | (abs(dot(Vec3vfx(Vec3fa(ray.dir)),Ng_inner1)) < 0.3f);
+
+ /* subtract the inner interval from the current hit interval */
+ BBox<vfloatx> tp0, tp1;
+ subtract(tp,tc_inner,tp0,tp1);
+ vboolx valid0 = valid & (tp0.lower <= tp0.upper);
+ vboolx valid1 = valid & (tp1.lower <= tp1.upper);
+ if (none(valid0 | valid1)) continue;
+
+ /* iterate over all first hits front to back */
+ const vintx termDepth0 = select(unstable0,vintx(maxDepth+1),vintx(maxDepth));
+ vboolx recursion_valid0 = valid0 & (depth < termDepth0);
+ valid0 &= depth >= termDepth0;
+
+ while (any(valid0))
+ {
+ const size_t i = select_min(valid0,tp0.lower); clear(valid0,i);
+ found = found | intersect_bezier_iterative_jacobian(ray,dt,curve,u_outer0[i],tp0.lower[i],epilog);
+ //found = found | intersect_bezier_iterative_debug (ray,dt,curve,i,u_outer0,tp0,h0,h1,Ng_outer0,dP0du,dP3du,epilog);
+ valid0 &= tp0.lower+dt <= ray.tfar;
+ }
+ valid1 &= tp1.lower+dt <= ray.tfar;
+
+ /* iterate over all second hits front to back */
+ const vintx termDepth1 = select(unstable1,vintx(maxDepth+1),vintx(maxDepth));
+ vboolx recursion_valid1 = valid1 & (depth < termDepth1);
+ valid1 &= depth >= termDepth1;
+ while (any(valid1))
+ {
+ const size_t i = select_min(valid1,tp1.lower); clear(valid1,i);
+ found = found | intersect_bezier_iterative_jacobian(ray,dt,curve,u_outer1[i],tp1.upper[i],epilog);
+ //found = found | intersect_bezier_iterative_debug (ray,dt,curve,i,u_outer1,tp1,h0,h1,Ng_outer1,dP0du,dP3du,epilog);
+ valid1 &= tp1.lower+dt <= ray.tfar;
+ }
+
+ /* push valid segments to stack */
+ recursion_valid0 &= tp0.lower+dt <= ray.tfar;
+ recursion_valid1 &= tp1.lower+dt <= ray.tfar;
+ const vboolx recursion_valid = recursion_valid0 | recursion_valid1;
+ if (any(recursion_valid))
+ {
+ assert(sptr < stack_size);
+ stack[sptr].valid = recursion_valid;
+ stack[sptr].tlower = select(recursion_valid0,tp0.lower,tp1.lower);
+ stack[sptr].u0 = u0;
+ stack[sptr].u1 = u1;
+ stack[sptr].depth = depth+1;
+ sptr++;
+ }
+ }
+ return found;
+ }
+
+ template<template<typename Ty> class NativeCurve>
+ struct SweepCurve1Intersector1
+ {
+ typedef NativeCurve<Vec3ff> NativeCurve3ff;
+
+ template<typename Epilog>
+ __noinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
+ const Epilog& epilog)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+
+ /* move ray closer to make intersection stable */
+ NativeCurve3ff curve0(v0,v1,v2,v3);
+ curve0 = enlargeRadiusToMinWidth(context,geom,ray.org,curve0);
+ const float dt = dot(curve0.center()-ray.org,ray.dir)*rcp(dot(ray.dir,ray.dir));
+ const Vec3ff ref(madd(Vec3fa(dt),ray.dir,ray.org),0.0f);
+ const NativeCurve3ff curve1 = curve0-ref;
+ return intersect_bezier_recursive_jacobian(ray,dt,curve1,0.0f,1.0f,1,epilog);
+ }
+ };
+
+ template<template<typename Ty> class NativeCurve, int K>
+ struct SweepCurve1IntersectorK
+ {
+ typedef NativeCurve<Vec3ff> NativeCurve3ff;
+
+ struct Ray1
+ {
+ __forceinline Ray1(RayK<K>& ray, size_t k)
+ : org(ray.org.x[k],ray.org.y[k],ray.org.z[k]), dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]), _tnear(ray.tnear()[k]), tfar(ray.tfar[k]) {}
+
+ Vec3fa org;
+ Vec3fa dir;
+ float _tnear;
+ float& tfar;
+
+ __forceinline float& tnear() { return _tnear; }
+ //__forceinline float& tfar() { return _tfar; }
+ __forceinline const float& tnear() const { return _tnear; }
+ //__forceinline const float& tfar() const { return _tfar; }
+
+ };
+
+ template<typename Epilog>
+ __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& vray, size_t k,
+ IntersectContext* context,
+ const CurveGeometry* geom, const unsigned int primID,
+ const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
+ const Epilog& epilog)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Ray1 ray(vray,k);
+
+ /* move ray closer to make intersection stable */
+ NativeCurve3ff curve0(v0,v1,v2,v3);
+ curve0 = enlargeRadiusToMinWidth(context,geom,ray.org,curve0);
+ const float dt = dot(curve0.center()-ray.org,ray.dir)*rcp(dot(ray.dir,ray.dir));
+ const Vec3ff ref(madd(Vec3fa(dt),ray.dir,ray.org),0.0f);
+ const NativeCurve3ff curve1 = curve0-ref;
+ return intersect_bezier_recursive_jacobian(ray,dt,curve1,0.0f,1.0f,1,epilog);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/curve_intersector_virtual.h b/thirdparty/embree/kernels/geometry/curve_intersector_virtual.h
new file mode 100644
index 0000000000..cffa8e46ad
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/curve_intersector_virtual.h
@@ -0,0 +1,671 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+#include "../subdiv/bezier_curve.h"
+#include "../common/primref.h"
+#include "curve_intersector_precalculations.h"
+#include "../bvh/node_intersector1.h"
+#include "../bvh/node_intersector_packet.h"
+
+#include "intersector_epilog.h"
+
+#include "../subdiv/bezier_curve.h"
+#include "../subdiv/bspline_curve.h"
+#include "../subdiv/hermite_curve.h"
+#include "../subdiv/catmullrom_curve.h"
+
+#include "spherei_intersector.h"
+#include "disci_intersector.h"
+
+#include "linei_intersector.h"
+#include "roundlinei_intersector.h"
+#include "conelinei_intersector.h"
+
+#include "curveNi_intersector.h"
+#include "curveNv_intersector.h"
+#include "curveNi_mb_intersector.h"
+
+#include "curve_intersector_distance.h"
+#include "curve_intersector_ribbon.h"
+#include "curve_intersector_oriented.h"
+#include "curve_intersector_sweep.h"
+
+namespace embree
+{
+ struct VirtualCurveIntersector
+ {
+ typedef void (*Intersect1Ty)(void* pre, void* ray, IntersectContext* context, const void* primitive);
+ typedef bool (*Occluded1Ty )(void* pre, void* ray, IntersectContext* context, const void* primitive);
+
+ typedef void (*Intersect4Ty)(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
+ typedef bool (*Occluded4Ty) (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
+
+ typedef void (*Intersect8Ty)(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
+ typedef bool (*Occluded8Ty) (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
+
+ typedef void (*Intersect16Ty)(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
+ typedef bool (*Occluded16Ty) (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
+
+ public:
+ struct Intersectors
+ {
+ Intersectors() {} // WARNING: Do not zero initialize this, as we otherwise get problems with thread unsafe local static variable initialization (e.g. on VS2013) in curve_intersector_virtual.cpp.
+
+ template<int K> void intersect(void* pre, void* ray, IntersectContext* context, const void* primitive);
+ template<int K> bool occluded (void* pre, void* ray, IntersectContext* context, const void* primitive);
+
+ template<int K> void intersect(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
+ template<int K> bool occluded (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive);
+
+ public:
+ Intersect1Ty intersect1;
+ Occluded1Ty occluded1;
+ Intersect4Ty intersect4;
+ Occluded4Ty occluded4;
+ Intersect8Ty intersect8;
+ Occluded8Ty occluded8;
+ Intersect16Ty intersect16;
+ Occluded16Ty occluded16;
+ };
+
+ Intersectors vtbl[Geometry::GTY_END];
+ };
+
+ template<> __forceinline void VirtualCurveIntersector::Intersectors::intersect<1> (void* pre, void* ray, IntersectContext* context, const void* primitive) { assert(intersect1); intersect1(pre,ray,context,primitive); }
+ template<> __forceinline bool VirtualCurveIntersector::Intersectors::occluded<1> (void* pre, void* ray, IntersectContext* context, const void* primitive) { assert(occluded1); return occluded1(pre,ray,context,primitive); }
+
+ template<> __forceinline void VirtualCurveIntersector::Intersectors::intersect<4>(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(intersect4); intersect4(pre,ray,k,context,primitive); }
+ template<> __forceinline bool VirtualCurveIntersector::Intersectors::occluded<4> (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(occluded4); return occluded4(pre,ray,k,context,primitive); }
+
+#if defined(__AVX__)
+ template<> __forceinline void VirtualCurveIntersector::Intersectors::intersect<8>(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(intersect8); intersect8(pre,ray,k,context,primitive); }
+ template<> __forceinline bool VirtualCurveIntersector::Intersectors::occluded<8> (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(occluded8); return occluded8(pre,ray,k,context,primitive); }
+#endif
+
+#if defined(__AVX512F__)
+ template<> __forceinline void VirtualCurveIntersector::Intersectors::intersect<16>(void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(intersect16); intersect16(pre,ray,k,context,primitive); }
+ template<> __forceinline bool VirtualCurveIntersector::Intersectors::occluded<16> (void* pre, void* ray, size_t k, IntersectContext* context, const void* primitive) { assert(occluded16); return occluded16(pre,ray,k,context,primitive); }
+#endif
+
+ namespace isa
+ {
+ struct VirtualCurveIntersector1
+ {
+ typedef unsigned char Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
+ leafIntersector.intersect<1>(&pre,&ray,context,prim);
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
+ return leafIntersector.occluded<1>(&pre,&ray,context,prim);
+ }
+ };
+
+ template<int K>
+ struct VirtualCurveIntersectorK
+ {
+ typedef unsigned char Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ template<bool robust>
+ static __forceinline void intersect(const vbool<K>& valid_i, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
+ size_t mask = movemask(valid_i);
+ while (mask) leafIntersector.intersect<K>(&pre,&ray,bscf(mask),context,prim);
+ }
+
+ template<bool robust>
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
+ vbool<K> valid_o = false;
+ size_t mask = movemask(valid_i);
+ while (mask) {
+ size_t k = bscf(mask);
+ if (leafIntersector.occluded<K>(&pre,&ray,k,context,prim))
+ set(valid_o, k);
+ }
+ return valid_o;
+ }
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
+ leafIntersector.intersect<K>(&pre,&ray,k,context,prim);
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ assert(num == 1);
+ RTCGeometryType ty = (RTCGeometryType)(*prim);
+ assert(This->leafIntersector);
+ VirtualCurveIntersector::Intersectors& leafIntersector = ((VirtualCurveIntersector*) This->leafIntersector)->vtbl[ty];
+ return leafIntersector.occluded<K>(&pre,&ray,k,context,prim);
+ }
+ };
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors LinearRoundConeNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &RoundLinearCurveMiIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &RoundLinearCurveMiIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &RoundLinearCurveMiIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &RoundLinearCurveMiIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&RoundLinearCurveMiIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &RoundLinearCurveMiIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&RoundLinearCurveMiIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &RoundLinearCurveMiIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors LinearConeNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &ConeCurveMiIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &ConeCurveMiIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &ConeCurveMiIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &ConeCurveMiIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&ConeCurveMiIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &ConeCurveMiIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&ConeCurveMiIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &ConeCurveMiIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors LinearRoundConeNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &RoundLinearCurveMiMBIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &RoundLinearCurveMiMBIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &RoundLinearCurveMiMBIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &RoundLinearCurveMiMBIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&RoundLinearCurveMiMBIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &RoundLinearCurveMiMBIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&RoundLinearCurveMiMBIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &RoundLinearCurveMiMBIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors LinearConeNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &ConeCurveMiMBIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &ConeCurveMiMBIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &ConeCurveMiMBIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &ConeCurveMiMBIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&ConeCurveMiMBIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &ConeCurveMiMBIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&ConeCurveMiMBIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &ConeCurveMiMBIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors LinearRibbonNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &FlatLinearCurveMiIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &FlatLinearCurveMiIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &FlatLinearCurveMiIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &FlatLinearCurveMiIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&FlatLinearCurveMiIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &FlatLinearCurveMiIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&FlatLinearCurveMiIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &FlatLinearCurveMiIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors LinearRibbonNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &FlatLinearCurveMiMBIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &FlatLinearCurveMiMBIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &FlatLinearCurveMiMBIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &FlatLinearCurveMiMBIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&FlatLinearCurveMiMBIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &FlatLinearCurveMiMBIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&FlatLinearCurveMiMBIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &FlatLinearCurveMiMBIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors SphereNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &SphereMiIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &SphereMiIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &SphereMiIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &SphereMiIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&SphereMiIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &SphereMiIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&SphereMiIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &SphereMiIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors SphereNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &SphereMiMBIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &SphereMiMBIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &SphereMiMBIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &SphereMiMBIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&SphereMiMBIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &SphereMiMBIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&SphereMiMBIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &SphereMiMBIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors DiscNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &DiscMiIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &DiscMiIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &DiscMiIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &DiscMiIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&DiscMiIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &DiscMiIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&DiscMiIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &DiscMiIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors DiscNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &DiscMiMBIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &DiscMiMBIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &DiscMiMBIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &DiscMiMBIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&DiscMiMBIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &DiscMiMBIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&DiscMiMBIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &DiscMiMBIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors OrientedDiscNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &OrientedDiscMiIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &OrientedDiscMiIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &OrientedDiscMiIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &OrientedDiscMiIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&OrientedDiscMiIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &OrientedDiscMiIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&OrientedDiscMiIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &OrientedDiscMiIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<int N>
+ static VirtualCurveIntersector::Intersectors OrientedDiscNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &OrientedDiscMiMBIntersector1<N,true>::intersect;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &OrientedDiscMiMBIntersector1<N,true>::occluded;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &OrientedDiscMiMBIntersectorK<N,4,true>::intersect;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &OrientedDiscMiMBIntersectorK<N,4,true>::occluded;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&OrientedDiscMiMBIntersectorK<N,8,true>::intersect;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &OrientedDiscMiMBIntersectorK<N,8,true>::occluded;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&OrientedDiscMiMBIntersectorK<N,16,true>::intersect;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &OrientedDiscMiMBIntersectorK<N,16,true>::occluded;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors RibbonNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_t<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_t <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &CurveNiIntersectorK<N,4>::template intersect_t<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_t <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_t<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_t <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_t<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_t <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors RibbonNvIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNvIntersector1<N>::template intersect_t<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNvIntersector1<N>::template occluded_t <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &CurveNvIntersectorK<N,4>::template intersect_t<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNvIntersectorK<N,4>::template occluded_t <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNvIntersectorK<N,8>::template intersect_t<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNvIntersectorK<N,8>::template occluded_t <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNvIntersectorK<N,16>::template intersect_t<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNvIntersectorK<N,16>::template occluded_t <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors RibbonNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_t<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_t <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &CurveNiMBIntersectorK<N,4>::template intersect_t<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_t <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_t<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_t <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_t<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_t <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors CurveNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_t<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_t <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_t<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_t <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_t<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_t <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_t<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_t <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors CurveNvIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNvIntersector1<N>::template intersect_t<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNvIntersector1<N>::template occluded_t <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNvIntersectorK<N,4>::template intersect_t<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNvIntersectorK<N,4>::template occluded_t <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNvIntersectorK<N,8>::template intersect_t<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNvIntersectorK<N,8>::template occluded_t <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNvIntersectorK<N,16>::template intersect_t<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNvIntersectorK<N,16>::template occluded_t <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors CurveNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_t<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_t <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_t<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_t <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_t<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_t <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_t<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_t <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors OrientedCurveNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_n<OrientedCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_n <OrientedCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_n<OrientedCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_n <OrientedCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_n<OrientedCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_n <OrientedCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_n<OrientedCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_n <OrientedCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors OrientedCurveNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_n<OrientedCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_n <OrientedCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_n<OrientedCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_n <OrientedCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_n<OrientedCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_n <OrientedCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_n<OrientedCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_n <OrientedCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors HermiteRibbonNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_h<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_h <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_h<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_h <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_h<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_h <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_h<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_h <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors HermiteRibbonNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_h<RibbonCurve1Intersector1<Curve>, Intersect1EpilogMU<VSIZEX,true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_h <RibbonCurve1Intersector1<Curve>, Occluded1EpilogMU<VSIZEX,true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_h<RibbonCurve1IntersectorK<Curve,4>, Intersect1KEpilogMU<VSIZEX,4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_h <RibbonCurve1IntersectorK<Curve,4>, Occluded1KEpilogMU<VSIZEX,4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_h<RibbonCurve1IntersectorK<Curve,8>, Intersect1KEpilogMU<VSIZEX,8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_h <RibbonCurve1IntersectorK<Curve,8>, Occluded1KEpilogMU<VSIZEX,8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_h<RibbonCurve1IntersectorK<Curve,16>, Intersect1KEpilogMU<VSIZEX,16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_h <RibbonCurve1IntersectorK<Curve,16>, Occluded1KEpilogMU<VSIZEX,16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors HermiteCurveNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_h<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_h <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_h<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_h <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_h<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_h <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_h<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_h <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors HermiteCurveNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_h<SweepCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_h <SweepCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_h<SweepCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_h <SweepCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_h<SweepCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_h <SweepCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_h<SweepCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_h <SweepCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors HermiteOrientedCurveNiIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiIntersector1<N>::template intersect_hn<OrientedCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiIntersector1<N>::template occluded_hn <OrientedCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiIntersectorK<N,4>::template intersect_hn<OrientedCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiIntersectorK<N,4>::template occluded_hn <OrientedCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiIntersectorK<N,8>::template intersect_hn<OrientedCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiIntersectorK<N,8>::template occluded_hn <OrientedCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiIntersectorK<N,16>::template intersect_hn<OrientedCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiIntersectorK<N,16>::template occluded_hn <OrientedCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+
+ template<template<typename Ty> class Curve, int N>
+ static VirtualCurveIntersector::Intersectors HermiteOrientedCurveNiMBIntersectors()
+ {
+ VirtualCurveIntersector::Intersectors intersectors;
+ intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &CurveNiMBIntersector1<N>::template intersect_hn<OrientedCurve1Intersector1<Curve>, Intersect1Epilog1<true> >;
+ intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &CurveNiMBIntersector1<N>::template occluded_hn <OrientedCurve1Intersector1<Curve>, Occluded1Epilog1<true> >;
+ intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty)&CurveNiMBIntersectorK<N,4>::template intersect_hn<OrientedCurve1IntersectorK<Curve,4>, Intersect1KEpilog1<4,true> >;
+ intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &CurveNiMBIntersectorK<N,4>::template occluded_hn <OrientedCurve1IntersectorK<Curve,4>, Occluded1KEpilog1<4,true> >;
+#if defined(__AVX__)
+ intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&CurveNiMBIntersectorK<N,8>::template intersect_hn<OrientedCurve1IntersectorK<Curve,8>, Intersect1KEpilog1<8,true> >;
+ intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &CurveNiMBIntersectorK<N,8>::template occluded_hn <OrientedCurve1IntersectorK<Curve,8>, Occluded1KEpilog1<8,true> >;
+#endif
+#if defined(__AVX512F__)
+ intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&CurveNiMBIntersectorK<N,16>::template intersect_hn<OrientedCurve1IntersectorK<Curve,16>, Intersect1KEpilog1<16,true> >;
+ intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &CurveNiMBIntersectorK<N,16>::template occluded_hn <OrientedCurve1IntersectorK<Curve,16>, Occluded1KEpilog1<16,true> >;
+#endif
+ return intersectors;
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/cylinder.h b/thirdparty/embree/kernels/geometry/cylinder.h
new file mode 100644
index 0000000000..dab02989ce
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/cylinder.h
@@ -0,0 +1,223 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct Cylinder
+ {
+ const Vec3fa p0; //!< start location
+ const Vec3fa p1; //!< end position
+ const float rr; //!< squared radius of cylinder
+
+ __forceinline Cylinder(const Vec3fa& p0, const Vec3fa& p1, const float r)
+ : p0(p0), p1(p1), rr(sqr(r)) {}
+
+ __forceinline Cylinder(const Vec3fa& p0, const Vec3fa& p1, const float rr, bool)
+ : p0(p0), p1(p1), rr(rr) {}
+
+ __forceinline bool intersect(const Vec3fa& org,
+ const Vec3fa& dir,
+ BBox1f& t_o,
+ float& u0_o, Vec3fa& Ng0_o,
+ float& u1_o, Vec3fa& Ng1_o) const
+ {
+ /* calculate quadratic equation to solve */
+ const float rl = rcp_length(p1-p0);
+ const Vec3fa P0 = p0, dP = (p1-p0)*rl;
+ const Vec3fa O = org-P0, dO = dir;
+
+ const float dOdO = dot(dO,dO);
+ const float OdO = dot(dO,O);
+ const float OO = dot(O,O);
+ const float dOz = dot(dP,dO);
+ const float Oz = dot(dP,O);
+
+ const float A = dOdO - sqr(dOz);
+ const float B = 2.0f * (OdO - dOz*Oz);
+ const float C = OO - sqr(Oz) - rr;
+
+ /* we miss the cylinder if determinant is smaller than zero */
+ const float D = B*B - 4.0f*A*C;
+ if (D < 0.0f) {
+ t_o = BBox1f(pos_inf,neg_inf);
+ return false;
+ }
+
+ /* special case for rays that are parallel to the cylinder */
+ const float eps = 16.0f*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
+ if (abs(A) < eps)
+ {
+ if (C <= 0.0f) {
+ t_o = BBox1f(neg_inf,pos_inf);
+ return true;
+ } else {
+ t_o = BBox1f(pos_inf,neg_inf);
+ return false;
+ }
+ }
+
+ /* standard case for rays that are not parallel to the cylinder */
+ const float Q = sqrt(D);
+ const float rcp_2A = rcp(2.0f*A);
+ const float t0 = (-B-Q)*rcp_2A;
+ const float t1 = (-B+Q)*rcp_2A;
+
+ /* calculates u and Ng for near hit */
+ {
+ u0_o = madd(t0,dOz,Oz)*rl;
+ const Vec3fa Pr = t0*dir;
+ const Vec3fa Pl = madd(u0_o,p1-p0,p0);
+ Ng0_o = Pr-Pl;
+ }
+
+ /* calculates u and Ng for far hit */
+ {
+ u1_o = madd(t1,dOz,Oz)*rl;
+ const Vec3fa Pr = t1*dir;
+ const Vec3fa Pl = madd(u1_o,p1-p0,p0);
+ Ng1_o = Pr-Pl;
+ }
+
+ t_o.lower = t0;
+ t_o.upper = t1;
+ return true;
+ }
+
+ __forceinline bool intersect(const Vec3fa& org_i, const Vec3fa& dir, BBox1f& t_o) const
+ {
+ float u0_o; Vec3fa Ng0_o;
+ float u1_o; Vec3fa Ng1_o;
+ return intersect(org_i,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
+ }
+
+ static bool verify(const size_t id, const Cylinder& cylinder, const RayHit& ray, bool shouldhit, const float t0, const float t1)
+ {
+ float eps = 0.001f;
+ BBox1f t; bool hit;
+ hit = cylinder.intersect(ray.org,ray.dir,t);
+
+ bool failed = hit != shouldhit;
+ if (shouldhit) failed |= std::isinf(t0) ? t0 != t.lower : abs(t0-t.lower) > eps;
+ if (shouldhit) failed |= std::isinf(t1) ? t1 != t.upper : abs(t1-t.upper) > eps;
+ if (!failed) return true;
+ embree_cout << "Cylinder test " << id << " failed: cylinder = " << cylinder << ", ray = " << ray << ", hit = " << hit << ", t = " << t << embree_endl;
+ return false;
+ }
+
+ /* verify cylinder class */
+ static bool verify()
+ {
+ bool passed = true;
+ const Cylinder cylinder(Vec3fa(0.0f,0.0f,0.0f),Vec3fa(1.0f,0.0f,0.0f),1.0f);
+ passed &= verify(0,cylinder,RayHit(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
+ passed &= verify(1,cylinder,RayHit(Vec3fa(+2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
+ passed &= verify(2,cylinder,RayHit(Vec3fa(+2.0f,1.0f,2.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),false,0.0f,0.0f);
+ passed &= verify(3,cylinder,RayHit(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
+ passed &= verify(4,cylinder,RayHit(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
+ passed &= verify(5,cylinder,RayHit(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
+ passed &= verify(6,cylinder,RayHit(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
+ return passed;
+ }
+
+ /*! output operator */
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const Cylinder& c) {
+ return cout << "Cylinder { p0 = " << c.p0 << ", p1 = " << c.p1 << ", r = " << sqrtf(c.rr) << "}";
+ }
+ };
+
+ template<int N>
+ struct CylinderN
+ {
+ const Vec3vf<N> p0; //!< start location
+ const Vec3vf<N> p1; //!< end position
+ const vfloat<N> rr; //!< squared radius of cylinder
+
+ __forceinline CylinderN(const Vec3vf<N>& p0, const Vec3vf<N>& p1, const vfloat<N>& r)
+ : p0(p0), p1(p1), rr(sqr(r)) {}
+
+ __forceinline CylinderN(const Vec3vf<N>& p0, const Vec3vf<N>& p1, const vfloat<N>& rr, bool)
+ : p0(p0), p1(p1), rr(rr) {}
+
+
+ __forceinline vbool<N> intersect(const Vec3fa& org, const Vec3fa& dir,
+ BBox<vfloat<N>>& t_o,
+ vfloat<N>& u0_o, Vec3vf<N>& Ng0_o,
+ vfloat<N>& u1_o, Vec3vf<N>& Ng1_o) const
+ {
+ /* calculate quadratic equation to solve */
+ const vfloat<N> rl = rcp_length(p1-p0);
+ const Vec3vf<N> P0 = p0, dP = (p1-p0)*rl;
+ const Vec3vf<N> O = Vec3vf<N>(org)-P0, dO = dir;
+
+ const vfloat<N> dOdO = dot(dO,dO);
+ const vfloat<N> OdO = dot(dO,O);
+ const vfloat<N> OO = dot(O,O);
+ const vfloat<N> dOz = dot(dP,dO);
+ const vfloat<N> Oz = dot(dP,O);
+
+ const vfloat<N> A = dOdO - sqr(dOz);
+ const vfloat<N> B = 2.0f * (OdO - dOz*Oz);
+ const vfloat<N> C = OO - sqr(Oz) - rr;
+
+ /* we miss the cylinder if determinant is smaller than zero */
+ const vfloat<N> D = B*B - 4.0f*A*C;
+ vbool<N> valid = D >= 0.0f;
+ if (none(valid)) {
+ t_o = BBox<vfloat<N>>(empty);
+ return valid;
+ }
+
+ /* standard case for rays that are not parallel to the cylinder */
+ const vfloat<N> Q = sqrt(D);
+ const vfloat<N> rcp_2A = rcp(2.0f*A);
+ const vfloat<N> t0 = (-B-Q)*rcp_2A;
+ const vfloat<N> t1 = (-B+Q)*rcp_2A;
+
+ /* calculates u and Ng for near hit */
+ {
+ u0_o = madd(t0,dOz,Oz)*rl;
+ const Vec3vf<N> Pr = t0*Vec3vf<N>(dir);
+ const Vec3vf<N> Pl = madd(u0_o,p1-p0,p0);
+ Ng0_o = Pr-Pl;
+ }
+
+ /* calculates u and Ng for far hit */
+ {
+ u1_o = madd(t1,dOz,Oz)*rl;
+ const Vec3vf<N> Pr = t1*Vec3vf<N>(dir);
+ const Vec3vf<N> Pl = madd(u1_o,p1-p0,p0);
+ Ng1_o = Pr-Pl;
+ }
+
+ t_o.lower = select(valid, t0, vfloat<N>(pos_inf));
+ t_o.upper = select(valid, t1, vfloat<N>(neg_inf));
+
+ /* special case for rays that are parallel to the cylinder */
+ const vfloat<N> eps = 16.0f*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
+ vbool<N> validt = valid & (abs(A) < eps);
+ if (unlikely(any(validt)))
+ {
+ vbool<N> inside = C <= 0.0f;
+ t_o.lower = select(validt,select(inside,vfloat<N>(neg_inf),vfloat<N>(pos_inf)),t_o.lower);
+ t_o.upper = select(validt,select(inside,vfloat<N>(pos_inf),vfloat<N>(neg_inf)),t_o.upper);
+ valid &= !validt | inside;
+ }
+ return valid;
+ }
+
+ __forceinline vbool<N> intersect(const Vec3fa& org_i, const Vec3fa& dir, BBox<vfloat<N>>& t_o) const
+ {
+ vfloat<N> u0_o; Vec3vf<N> Ng0_o;
+ vfloat<N> u1_o; Vec3vf<N> Ng1_o;
+ return intersect(org_i,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
+ }
+ };
+ }
+}
+
diff --git a/thirdparty/embree/kernels/geometry/disc_intersector.h b/thirdparty/embree/kernels/geometry/disc_intersector.h
new file mode 100644
index 0000000000..816c066899
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/disc_intersector.h
@@ -0,0 +1,216 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "../common/scene_points.h"
+#include "curve_intersector_precalculations.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct DiscIntersectorHitM
+ {
+ __forceinline DiscIntersectorHitM() {}
+
+ __forceinline DiscIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
+ : vu(u), vv(v), vt(t), vNg(Ng)
+ {
+ }
+
+ __forceinline void finalize() {}
+
+ __forceinline Vec2f uv(const size_t i) const
+ {
+ return Vec2f(vu[i], vv[i]);
+ }
+ __forceinline float t(const size_t i) const
+ {
+ return vt[i];
+ }
+ __forceinline Vec3fa Ng(const size_t i) const
+ {
+ return Vec3fa(vNg.x[i], vNg.y[i], vNg.z[i]);
+ }
+
+ public:
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+ };
+
+ template<int M>
+ struct DiscIntersector1
+ {
+ typedef CurvePrecalculations1 Precalculations;
+
+ template<typename Epilog>
+ static __forceinline bool intersect(
+ const vbool<M>& valid_i,
+ Ray& ray,
+ IntersectContext* context,
+ const Points* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i,
+ const Epilog& epilog)
+ {
+ vbool<M> valid = valid_i;
+
+ const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
+ const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
+ const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
+
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec3vf<M> center = v0.xyz();
+ const vfloat<M> radius = v0.w;
+
+ const Vec3vf<M> c0 = center - ray_org;
+ const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
+
+ valid &= (vfloat<M>(ray.tnear()) <= projC0) & (projC0 <= vfloat<M>(ray.tfar));
+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
+ valid &= projC0 > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR) * radius * pre.depth_scale; // ignore self intersections
+ if (unlikely(none(valid)))
+ return false;
+
+ const Vec3vf<M> perp = c0 - projC0 * ray_dir;
+ const vfloat<M> l2 = dot(perp, perp);
+ const vfloat<M> r2 = radius * radius;
+ valid &= (l2 <= r2);
+ if (unlikely(none(valid)))
+ return false;
+
+ DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
+ return epilog(valid, hit);
+ }
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ Ray& ray,
+ IntersectContext* context,
+ const Points* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i,
+ const Vec3vf<M>& normal,
+ const Epilog& epilog)
+ {
+ vbool<M> valid = valid_i;
+ const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
+
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec3vf<M> center = v0.xyz();
+ const vfloat<M> radius = v0.w;
+
+ vfloat<M> divisor = dot(Vec3vf<M>((Vec3fa)ray.dir), normal);
+ const vbool<M> parallel = divisor == vfloat<M>(0.f);
+ valid &= !parallel;
+ divisor = select(parallel, 1.f, divisor); // prevent divide by zero
+
+ vfloat<M> t = dot(center - Vec3vf<M>((Vec3fa)ray.org), Vec3vf<M>(normal)) / divisor;
+
+ valid &= (vfloat<M>(ray.tnear()) <= t) & (t <= vfloat<M>(ray.tfar));
+ if (unlikely(none(valid)))
+ return false;
+
+ Vec3vf<M> intersection = Vec3vf<M>((Vec3fa)ray.org) + Vec3vf<M>((Vec3fa)ray.dir) * t;
+ vfloat<M> dist2 = dot(intersection - center, intersection - center);
+ valid &= dist2 < radius * radius;
+ if (unlikely(none(valid)))
+ return false;
+
+ DiscIntersectorHitM<M> hit(zero, zero, t, normal);
+ return epilog(valid, hit);
+ }
+ };
+
+ template<int M, int K>
+ struct DiscIntersectorK
+ {
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ RayK<K>& ray,
+ size_t k,
+ IntersectContext* context,
+ const Points* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i,
+ const Epilog& epilog)
+ {
+ vbool<M> valid = valid_i;
+
+ const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
+ const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
+
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec3vf<M> center = v0.xyz();
+ const vfloat<M> radius = v0.w;
+
+ const Vec3vf<M> c0 = center - ray_org;
+ const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
+
+ valid &= (vfloat<M>(ray.tnear()[k]) <= projC0) & (projC0 <= vfloat<M>(ray.tfar[k]));
+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
+ valid &= projC0 > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR) * radius * pre.depth_scale[k]; // ignore self intersections
+ if (unlikely(none(valid)))
+ return false;
+
+ const Vec3vf<M> perp = c0 - projC0 * ray_dir;
+ const vfloat<M> l2 = dot(perp, perp);
+ const vfloat<M> r2 = radius * radius;
+ valid &= (l2 <= r2);
+ if (unlikely(none(valid)))
+ return false;
+
+ DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
+ return epilog(valid, hit);
+ }
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ RayK<K>& ray,
+ size_t k,
+ IntersectContext* context,
+ const Points* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i,
+ const Vec3vf<M>& normal,
+ const Epilog& epilog)
+ {
+ vbool<M> valid = valid_i;
+ const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
+
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec3vf<M> center = v0.xyz();
+ const vfloat<M> radius = v0.w;
+
+ vfloat<M> divisor = dot(Vec3vf<M>(ray_dir), normal);
+ const vbool<M> parallel = divisor == vfloat<M>(0.f);
+ valid &= !parallel;
+ divisor = select(parallel, 1.f, divisor); // prevent divide by zero
+
+ vfloat<M> t = dot(center - Vec3vf<M>(ray_org), Vec3vf<M>(normal)) / divisor;
+
+ valid &= (vfloat<M>(ray.tnear()[k]) <= t) & (t <= vfloat<M>(ray.tfar[k]));
+ if (unlikely(none(valid)))
+ return false;
+
+ Vec3vf<M> intersection = Vec3vf<M>(ray_org) + Vec3vf<M>(ray_dir) * t;
+ vfloat<M> dist2 = dot(intersection - center, intersection - center);
+ valid &= dist2 < radius * radius;
+ if (unlikely(none(valid)))
+ return false;
+
+ DiscIntersectorHitM<M> hit(zero, zero, t, normal);
+ return epilog(valid, hit);
+ }
+ };
+ } // namespace isa
+} // namespace embree
diff --git a/thirdparty/embree/kernels/geometry/disci_intersector.h b/thirdparty/embree/kernels/geometry/disci_intersector.h
new file mode 100644
index 0000000000..bb9d396f6e
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/disci_intersector.h
@@ -0,0 +1,277 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "disc_intersector.h"
+#include "intersector_epilog.h"
+#include "pointi.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M, bool filter>
+ struct DiscMiIntersector1
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre,
+ RayHit& ray,
+ IntersectContext* context,
+ const Primitive& Disc)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Disc.gather(v0, geom);
+ const vbool<M> valid = Disc.valid();
+ DiscIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, Intersect1EpilogM<M, filter>(ray, context, Disc.geomID(), Disc.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre,
+ Ray& ray,
+ IntersectContext* context,
+ const Primitive& Disc)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Disc.gather(v0, geom);
+ const vbool<M> valid = Disc.valid();
+ return DiscIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, Occluded1EpilogM<M, filter>(ray, context, Disc.geomID(), Disc.primID()));
+ }
+ };
+
+ template<int M, bool filter>
+ struct DiscMiMBIntersector1
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre,
+ RayHit& ray,
+ IntersectContext* context,
+ const Primitive& Disc)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Disc.gather(v0, geom, ray.time());
+ const vbool<M> valid = Disc.valid();
+ DiscIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, Intersect1EpilogM<M, filter>(ray, context, Disc.geomID(), Disc.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre,
+ Ray& ray,
+ IntersectContext* context,
+ const Primitive& Disc)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Disc.gather(v0, geom, ray.time());
+ const vbool<M> valid = Disc.valid();
+ return DiscIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, Occluded1EpilogM<M, filter>(ray, context, Disc.geomID(), Disc.primID()));
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct DiscMiIntersectorK
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(
+ const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Disc.gather(v0, geom);
+ const vbool<M> valid = Disc.valid();
+ DiscIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0,
+ Intersect1KEpilogM<M, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
+ }
+
+ static __forceinline bool occluded(
+ const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Disc.gather(v0, geom);
+ const vbool<M> valid = Disc.valid();
+ return DiscIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0,
+ Occluded1KEpilogM<M, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct DiscMiMBIntersectorK
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(
+ const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Disc.gather(v0, geom, ray.time()[k]);
+ const vbool<M> valid = Disc.valid();
+ DiscIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0,
+ Intersect1KEpilogM<M, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
+ }
+
+ static __forceinline bool occluded(
+ const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Disc.gather(v0, geom, ray.time()[k]);
+ const vbool<M> valid = Disc.valid();
+ return DiscIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0, Occluded1KEpilogM<M, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
+ }
+ };
+
+ template<int M, bool filter>
+ struct OrientedDiscMiIntersector1
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre,
+ RayHit& ray,
+ IntersectContext* context,
+ const Primitive& Disc)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Vec3vf<M> n0;
+ Disc.gather(v0, n0, geom);
+ const vbool<M> valid = Disc.valid();
+ DiscIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, n0, Intersect1EpilogM<M, filter>(ray, context, Disc.geomID(), Disc.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre,
+ Ray& ray,
+ IntersectContext* context,
+ const Primitive& Disc)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Vec3vf<M> n0;
+ Disc.gather(v0, n0, geom);
+ const vbool<M> valid = Disc.valid();
+ return DiscIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, n0, Occluded1EpilogM<M, filter>(ray, context, Disc.geomID(), Disc.primID()));
+ }
+ };
+
+ template<int M, bool filter>
+ struct OrientedDiscMiMBIntersector1
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre,
+ RayHit& ray,
+ IntersectContext* context,
+ const Primitive& Disc)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Vec3vf<M> n0;
+ Disc.gather(v0, n0, geom, ray.time());
+ const vbool<M> valid = Disc.valid();
+ DiscIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, n0, Intersect1EpilogM<M, filter>(ray, context, Disc.geomID(), Disc.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre,
+ Ray& ray,
+ IntersectContext* context,
+ const Primitive& Disc)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Vec3vf<M> n0;
+ Disc.gather(v0, n0, geom, ray.time());
+ const vbool<M> valid = Disc.valid();
+ return DiscIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, n0, Occluded1EpilogM<M, filter>(ray, context, Disc.geomID(), Disc.primID()));
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct OrientedDiscMiIntersectorK
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(
+ const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Vec3vf<M> n0;
+ Disc.gather(v0, n0, geom);
+ const vbool<M> valid = Disc.valid();
+ DiscIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0, n0,
+ Intersect1KEpilogM<M, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
+ }
+
+ static __forceinline bool occluded(
+ const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Vec3vf<M> n0;
+ Disc.gather(v0, n0, geom);
+ const vbool<M> valid = Disc.valid();
+ return DiscIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0, n0,
+ Occluded1KEpilogM<M, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct OrientedDiscMiMBIntersectorK
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(
+ const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Vec3vf<M> n0;
+ Disc.gather(v0, n0, geom, ray.time()[k]);
+ const vbool<M> valid = Disc.valid();
+ DiscIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0, n0,
+ Intersect1KEpilogM<M, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
+ }
+
+ static __forceinline bool occluded(
+ const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& Disc)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(Disc.geomID());
+ Vec4vf<M> v0; Vec3vf<M> n0;
+ Disc.gather(v0, n0, geom, ray.time()[k]);
+ const vbool<M> valid = Disc.valid();
+ return DiscIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0, n0,
+ Occluded1KEpilogM<M, K, filter>(ray, k, context, Disc.geomID(), Disc.primID()));
+ }
+ };
+ } // namespace isa
+} // namespace embree
diff --git a/thirdparty/embree/kernels/geometry/filter.h b/thirdparty/embree/kernels/geometry/filter.h
new file mode 100644
index 0000000000..3b4d924ea7
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/filter.h
@@ -0,0 +1,204 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/geometry.h"
+#include "../common/ray.h"
+#include "../common/hit.h"
+#include "../common/context.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ __forceinline bool runIntersectionFilter1Helper(RTCFilterFunctionNArguments* args, const Geometry* const geometry, IntersectContext* context)
+ {
+ if (geometry->intersectionFilterN)
+ {
+ assert(context->scene->hasGeometryFilterFunction());
+ geometry->intersectionFilterN(args);
+
+ if (args->valid[0] == 0)
+ return false;
+ }
+
+ if (context->user->filter) {
+ assert(context->scene->hasContextFilterFunction());
+ context->user->filter(args);
+
+ if (args->valid[0] == 0)
+ return false;
+ }
+
+ copyHitToRay(*(RayHit*)args->ray,*(Hit*)args->hit);
+ return true;
+ }
+
+ __forceinline bool runIntersectionFilter1(const Geometry* const geometry, RayHit& ray, IntersectContext* context, Hit& hit)
+ {
+ RTCFilterFunctionNArguments args;
+ int mask = -1;
+ args.valid = &mask;
+ args.geometryUserPtr = geometry->userPtr;
+ args.context = context->user;
+ args.ray = (RTCRayN*)&ray;
+ args.hit = (RTCHitN*)&hit;
+ args.N = 1;
+ return runIntersectionFilter1Helper(&args,geometry,context);
+ }
+
+ __forceinline void reportIntersection1(IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args)
+ {
+#if defined(EMBREE_FILTER_FUNCTION)
+ IntersectContext* MAYBE_UNUSED context = args->internal_context;
+ const Geometry* const geometry = args->geometry;
+ if (geometry->intersectionFilterN) {
+ assert(context->scene->hasGeometryFilterFunction());
+ geometry->intersectionFilterN(filter_args);
+ }
+
+ //if (args->valid[0] == 0)
+ // return;
+
+ if (context->user->filter) {
+ assert(context->scene->hasContextFilterFunction());
+ context->user->filter(filter_args);
+ }
+#endif
+ }
+
+ __forceinline bool runOcclusionFilter1Helper(RTCFilterFunctionNArguments* args, const Geometry* const geometry, IntersectContext* context)
+ {
+ if (geometry->occlusionFilterN)
+ {
+ assert(context->scene->hasGeometryFilterFunction());
+ geometry->occlusionFilterN(args);
+
+ if (args->valid[0] == 0)
+ return false;
+ }
+
+ if (context->user->filter) {
+ assert(context->scene->hasContextFilterFunction());
+ context->user->filter(args);
+
+ if (args->valid[0] == 0)
+ return false;
+ }
+ return true;
+ }
+
+ __forceinline bool runOcclusionFilter1(const Geometry* const geometry, Ray& ray, IntersectContext* context, Hit& hit)
+ {
+ RTCFilterFunctionNArguments args;
+ int mask = -1;
+ args.valid = &mask;
+ args.geometryUserPtr = geometry->userPtr;
+ args.context = context->user;
+ args.ray = (RTCRayN*)&ray;
+ args.hit = (RTCHitN*)&hit;
+ args.N = 1;
+ return runOcclusionFilter1Helper(&args,geometry,context);
+ }
+
+ __forceinline void reportOcclusion1(OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args)
+ {
+#if defined(EMBREE_FILTER_FUNCTION)
+ IntersectContext* MAYBE_UNUSED context = args->internal_context;
+ const Geometry* const geometry = args->geometry;
+ if (geometry->occlusionFilterN) {
+ assert(context->scene->hasGeometryFilterFunction());
+ geometry->occlusionFilterN(filter_args);
+ }
+
+ //if (args->valid[0] == 0)
+ // return false;
+
+ if (context->user->filter) {
+ assert(context->scene->hasContextFilterFunction());
+ context->user->filter(filter_args);
+ }
+#endif
+ }
+
+ template<int K>
+ __forceinline vbool<K> runIntersectionFilterHelper(RTCFilterFunctionNArguments* args, const Geometry* const geometry, IntersectContext* context)
+ {
+ vint<K>* mask = (vint<K>*) args->valid;
+ if (geometry->intersectionFilterN)
+ {
+ assert(context->scene->hasGeometryFilterFunction());
+ geometry->intersectionFilterN(args);
+ }
+
+ vbool<K> valid_o = *mask != vint<K>(zero);
+ if (none(valid_o)) return valid_o;
+
+ if (context->user->filter) {
+ assert(context->scene->hasContextFilterFunction());
+ context->user->filter(args);
+ }
+
+ valid_o = *mask != vint<K>(zero);
+ if (none(valid_o)) return valid_o;
+
+ copyHitToRay(valid_o,*(RayHitK<K>*)args->ray,*(HitK<K>*)args->hit);
+ return valid_o;
+ }
+
+ template<int K>
+ __forceinline vbool<K> runIntersectionFilter(const vbool<K>& valid, const Geometry* const geometry, RayHitK<K>& ray, IntersectContext* context, HitK<K>& hit)
+ {
+ RTCFilterFunctionNArguments args;
+ vint<K> mask = valid.mask32();
+ args.valid = (int*)&mask;
+ args.geometryUserPtr = geometry->userPtr;
+ args.context = context->user;
+ args.ray = (RTCRayN*)&ray;
+ args.hit = (RTCHitN*)&hit;
+ args.N = K;
+ return runIntersectionFilterHelper<K>(&args,geometry,context);
+ }
+
+ template<int K>
+ __forceinline vbool<K> runOcclusionFilterHelper(RTCFilterFunctionNArguments* args, const Geometry* const geometry, IntersectContext* context)
+ {
+ vint<K>* mask = (vint<K>*) args->valid;
+ if (geometry->occlusionFilterN)
+ {
+ assert(context->scene->hasGeometryFilterFunction());
+ geometry->occlusionFilterN(args);
+ }
+
+ vbool<K> valid_o = *mask != vint<K>(zero);
+
+ if (none(valid_o)) return valid_o;
+
+ if (context->user->filter) {
+ assert(context->scene->hasContextFilterFunction());
+ context->user->filter(args);
+ }
+
+ valid_o = *mask != vint<K>(zero);
+
+ RayK<K>* ray = (RayK<K>*) args->ray;
+ ray->tfar = select(valid_o, vfloat<K>(neg_inf), ray->tfar);
+ return valid_o;
+ }
+
+ template<int K>
+ __forceinline vbool<K> runOcclusionFilter(const vbool<K>& valid, const Geometry* const geometry, RayK<K>& ray, IntersectContext* context, HitK<K>& hit)
+ {
+ RTCFilterFunctionNArguments args;
+ vint<K> mask = valid.mask32();
+ args.valid = (int*)&mask;
+ args.geometryUserPtr = geometry->userPtr;
+ args.context = context->user;
+ args.ray = (RTCRayN*)&ray;
+ args.hit = (RTCHitN*)&hit;
+ args.N = K;
+ return runOcclusionFilterHelper<K>(&args,geometry,context);
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/grid_intersector.h b/thirdparty/embree/kernels/geometry/grid_intersector.h
new file mode 100644
index 0000000000..9c59cef119
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/grid_intersector.h
@@ -0,0 +1,99 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "grid_soa.h"
+#include "grid_soa_intersector1.h"
+#include "grid_soa_intersector_packet.h"
+#include "../common/ray.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename T>
+ class SubdivPatch1Precalculations : public T
+ {
+ public:
+ __forceinline SubdivPatch1Precalculations (const Ray& ray, const void* ptr)
+ : T(ray,ptr) {}
+ };
+
+ template<int K, typename T>
+ class SubdivPatch1PrecalculationsK : public T
+ {
+ public:
+ __forceinline SubdivPatch1PrecalculationsK (const vbool<K>& valid, RayK<K>& ray)
+ : T(valid,ray) {}
+ };
+
+ class Grid1Intersector1
+ {
+ public:
+ typedef GridSOA Primitive;
+ typedef Grid1Precalculations<GridSOAIntersector1::Precalculations> Precalculations;
+
+ /*! Intersect a ray with the primitive. */
+ static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
+ {
+ GridSOAIntersector1::intersect(pre,ray,context,prim,lazy_node);
+ }
+ static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, size_t& lazy_node) {
+ intersect(pre,ray,context,prim,ty,lazy_node);
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ static __forceinline bool occluded(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
+ {
+ GridSOAIntersector1::occluded(pre,ray,context,prim,lazy_node);
+ }
+ static __forceinline bool occluded(Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, size_t& lazy_node) {
+ return occluded(pre,ray,context,prim,ty,lazy_node);
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t ty, size_t& lazy_node) {
+ assert(false && "not implemented");
+ return false;
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, size_t ty0, const Primitive* prim, size_t ty, size_t& lazy_node) {
+ assert(false && "not implemented");
+ return false;
+ }
+ };
+
+ template <int K>
+ struct GridIntersectorK
+ {
+ typedef GridSOA Primitive;
+ typedef SubdivPatch1PrecalculationsK<K,typename GridSOAIntersectorK<K>::Precalculations> Precalculations;
+
+
+ static __forceinline void intersect(const vbool<K>& valid, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
+ {
+ GridSOAIntersectorK<K>::intersect(valid,pre,ray,context,prim,lazy_node);
+ }
+
+ static __forceinline vbool<K> occluded(const vbool<K>& valid, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
+ {
+ GridSOAIntersectorK<K>::occluded(valid,pre,ray,context,prim,lazy_node);
+ }
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
+ {
+ GridSOAIntersectorK<K>::intersect(pre,ray,k,context,prim,lazy_node);
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, size_t& lazy_node)
+ {
+ GridSOAIntersectorK<K>::occluded(pre,ray,k,context,prim,lazy_node);
+ }
+ };
+
+ typedef Grid1IntersectorK<4> SubdivPatch1Intersector4;
+ typedef Grid1IntersectorK<8> SubdivPatch1Intersector8;
+ typedef Grid1IntersectorK<16> SubdivPatch1Intersector16;
+
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/grid_soa.h b/thirdparty/embree/kernels/geometry/grid_soa.h
new file mode 100644
index 0000000000..cea90aedf6
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/grid_soa.h
@@ -0,0 +1,275 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "../common/scene_subdiv_mesh.h"
+#include "../bvh/bvh.h"
+#include "../subdiv/tessellation.h"
+#include "../subdiv/tessellation_cache.h"
+#include "subdivpatch1.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ class GridSOA
+ {
+ public:
+
+ /*! GridSOA constructor */
+ GridSOA(const SubdivPatch1Base* patches, const unsigned time_steps,
+ const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
+ const SubdivMesh* const geom, const size_t totalBvhBytes, const size_t gridBytes, BBox3fa* bounds_o = nullptr);
+
+ /*! Subgrid creation */
+ template<typename Allocator>
+ static GridSOA* create(const SubdivPatch1Base* patches, const unsigned time_steps,
+ unsigned x0, unsigned x1, unsigned y0, unsigned y1,
+ const Scene* scene, Allocator& alloc, BBox3fa* bounds_o = nullptr)
+ {
+ const unsigned width = x1-x0+1;
+ const unsigned height = y1-y0+1;
+ const GridRange range(0,width-1,0,height-1);
+ size_t bvhBytes = 0;
+ if (time_steps == 1)
+ bvhBytes = getBVHBytes(range,sizeof(BVH4::AABBNode),0);
+ else {
+ bvhBytes = (time_steps-1)*getBVHBytes(range,sizeof(BVH4::AABBNodeMB),0);
+ bvhBytes += getTemporalBVHBytes(make_range(0,int(time_steps-1)),sizeof(BVH4::AABBNodeMB4D));
+ }
+ const size_t gridBytes = 4*size_t(width)*size_t(height)*sizeof(float);
+ size_t rootBytes = time_steps*sizeof(BVH4::NodeRef);
+#if !defined(__64BIT__)
+ rootBytes += 4; // We read 2 elements behind the grid. As we store at least 8 root bytes after the grid we are fine in 64 bit mode. But in 32 bit mode we have to do additional padding.
+#endif
+ void* data = alloc(offsetof(GridSOA,data)+bvhBytes+time_steps*gridBytes+rootBytes);
+ assert(data);
+ return new (data) GridSOA(patches,time_steps,x0,x1,y0,y1,patches->grid_u_res,patches->grid_v_res,scene->get<SubdivMesh>(patches->geomID()),bvhBytes,gridBytes,bounds_o);
+ }
+
+ /*! Grid creation */
+ template<typename Allocator>
+ static GridSOA* create(const SubdivPatch1Base* const patches, const unsigned time_steps,
+ const Scene* scene, const Allocator& alloc, BBox3fa* bounds_o = nullptr)
+ {
+ return create(patches,time_steps,0,patches->grid_u_res-1,0,patches->grid_v_res-1,scene,alloc,bounds_o);
+ }
+
+ /*! returns reference to root */
+ __forceinline BVH4::NodeRef& root(size_t t = 0) { return (BVH4::NodeRef&)data[rootOffset + t*sizeof(BVH4::NodeRef)]; }
+ __forceinline const BVH4::NodeRef& root(size_t t = 0) const { return (BVH4::NodeRef&)data[rootOffset + t*sizeof(BVH4::NodeRef)]; }
+
+ /*! returns pointer to BVH array */
+ __forceinline char* bvhData() { return &data[0]; }
+ __forceinline const char* bvhData() const { return &data[0]; }
+
+ /*! returns pointer to Grid array */
+ __forceinline float* gridData(size_t t = 0) { return (float*) &data[gridOffset + t*gridBytes]; }
+ __forceinline const float* gridData(size_t t = 0) const { return (float*) &data[gridOffset + t*gridBytes]; }
+
+ __forceinline void* encodeLeaf(size_t u, size_t v) {
+ return (void*) (16*(v * width + u + 1)); // +1 to not create empty leaf
+ }
+ __forceinline float* decodeLeaf(size_t t, const void* ptr) {
+ return gridData(t) + (((size_t) (ptr) >> 4) - 1);
+ }
+
+ /*! returns the size of the BVH over the grid in bytes */
+ static size_t getBVHBytes(const GridRange& range, const size_t nodeBytes, const size_t leafBytes);
+
+ /*! returns the size of the temporal BVH over the time range BVHs */
+ static size_t getTemporalBVHBytes(const range<int> time_range, const size_t nodeBytes);
+
+ /*! calculates bounding box of grid range */
+ __forceinline BBox3fa calculateBounds(size_t time, const GridRange& range) const
+ {
+ const float* const grid_array = gridData(time);
+ const float* const grid_x_array = grid_array + 0 * dim_offset;
+ const float* const grid_y_array = grid_array + 1 * dim_offset;
+ const float* const grid_z_array = grid_array + 2 * dim_offset;
+
+ /* compute the bounds just for the range! */
+ BBox3fa bounds( empty );
+ for (unsigned v = range.v_start; v<=range.v_end; v++)
+ {
+ for (unsigned u = range.u_start; u<=range.u_end; u++)
+ {
+ const float x = grid_x_array[ v * width + u];
+ const float y = grid_y_array[ v * width + u];
+ const float z = grid_z_array[ v * width + u];
+ bounds.extend( Vec3fa(x,y,z) );
+ }
+ }
+ assert(is_finite(bounds));
+ return bounds;
+ }
+
+ /*! Evaluates grid over patch and builds BVH4 tree over the grid. */
+ std::pair<BVH4::NodeRef,BBox3fa> buildBVH(BBox3fa* bounds_o);
+
+ /*! Create BVH4 tree over grid. */
+ std::pair<BVH4::NodeRef,BBox3fa> buildBVH(const GridRange& range, size_t& allocator);
+
+ /*! Evaluates grid over patch and builds MSMBlur BVH4 tree over the grid. */
+ std::pair<BVH4::NodeRef,LBBox3fa> buildMSMBlurBVH(const range<int> time_range, BBox3fa* bounds_o);
+
+ /*! Create MBlur BVH4 tree over grid. */
+ std::pair<BVH4::NodeRef,LBBox3fa> buildMBlurBVH(size_t time, const GridRange& range, size_t& allocator);
+
+ /*! Create MSMBlur BVH4 tree over grid. */
+ std::pair<BVH4::NodeRef,LBBox3fa> buildMSMBlurBVH(const range<int> time_range, size_t& allocator, BBox3fa* bounds_o);
+
+ template<typename Loader>
+ struct MapUV
+ {
+ typedef typename Loader::vfloat vfloat;
+ const float* const grid_uv;
+ size_t line_offset;
+ size_t lines;
+
+ __forceinline MapUV(const float* const grid_uv, size_t line_offset, const size_t lines)
+ : grid_uv(grid_uv), line_offset(line_offset), lines(lines) {}
+
+ __forceinline void operator() (vfloat& u, vfloat& v, Vec3<vfloat>& Ng) const {
+ const Vec3<vfloat> tri_v012_uv = Loader::gather(grid_uv,line_offset,lines);
+ const Vec2<vfloat> uv0 = GridSOA::decodeUV(tri_v012_uv[0]);
+ const Vec2<vfloat> uv1 = GridSOA::decodeUV(tri_v012_uv[1]);
+ const Vec2<vfloat> uv2 = GridSOA::decodeUV(tri_v012_uv[2]);
+ const Vec2<vfloat> uv = u * uv1 + v * uv2 + (1.0f-u-v) * uv0;
+ u = uv[0];v = uv[1];
+ }
+ };
+
+ struct Gather2x3
+ {
+ enum { M = 4 };
+ typedef vbool4 vbool;
+ typedef vint4 vint;
+ typedef vfloat4 vfloat;
+
+ static __forceinline const Vec3vf4 gather(const float* const grid, const size_t line_offset, const size_t lines)
+ {
+ vfloat4 r0 = vfloat4::loadu(grid + 0*line_offset);
+ vfloat4 r1 = vfloat4::loadu(grid + 1*line_offset); // this accesses 2 elements too much in case of 2x2 grid, but this is ok as we ensure enough padding after the grid
+ if (unlikely(line_offset == 2))
+ {
+ r0 = shuffle<0,1,1,1>(r0);
+ r1 = shuffle<0,1,1,1>(r1);
+ }
+ return Vec3vf4(unpacklo(r0,r1), // r00, r10, r01, r11
+ shuffle<1,1,2,2>(r0), // r01, r01, r02, r02
+ shuffle<0,1,1,2>(r1)); // r10, r11, r11, r12
+ }
+
+ static __forceinline void gather(const float* const grid_x,
+ const float* const grid_y,
+ const float* const grid_z,
+ const size_t line_offset,
+ const size_t lines,
+ Vec3vf4& v0_o,
+ Vec3vf4& v1_o,
+ Vec3vf4& v2_o)
+ {
+ const Vec3vf4 tri_v012_x = gather(grid_x,line_offset,lines);
+ const Vec3vf4 tri_v012_y = gather(grid_y,line_offset,lines);
+ const Vec3vf4 tri_v012_z = gather(grid_z,line_offset,lines);
+ v0_o = Vec3vf4(tri_v012_x[0],tri_v012_y[0],tri_v012_z[0]);
+ v1_o = Vec3vf4(tri_v012_x[1],tri_v012_y[1],tri_v012_z[1]);
+ v2_o = Vec3vf4(tri_v012_x[2],tri_v012_y[2],tri_v012_z[2]);
+ }
+ };
+
+#if defined (__AVX__)
+ struct Gather3x3
+ {
+ enum { M = 8 };
+ typedef vbool8 vbool;
+ typedef vint8 vint;
+ typedef vfloat8 vfloat;
+
+ static __forceinline const Vec3vf8 gather(const float* const grid, const size_t line_offset, const size_t lines)
+ {
+ vfloat4 ra = vfloat4::loadu(grid + 0*line_offset);
+ vfloat4 rb = vfloat4::loadu(grid + 1*line_offset); // this accesses 2 elements too much in case of 2x2 grid, but this is ok as we ensure enough padding after the grid
+ vfloat4 rc;
+ if (likely(lines > 2))
+ rc = vfloat4::loadu(grid + 2*line_offset);
+ else
+ rc = rb;
+
+ if (unlikely(line_offset == 2))
+ {
+ ra = shuffle<0,1,1,1>(ra);
+ rb = shuffle<0,1,1,1>(rb);
+ rc = shuffle<0,1,1,1>(rc);
+ }
+
+ const vfloat8 r0 = vfloat8(ra,rb);
+ const vfloat8 r1 = vfloat8(rb,rc);
+ return Vec3vf8(unpacklo(r0,r1), // r00, r10, r01, r11, r10, r20, r11, r21
+ shuffle<1,1,2,2>(r0), // r01, r01, r02, r02, r11, r11, r12, r12
+ shuffle<0,1,1,2>(r1)); // r10, r11, r11, r12, r20, r21, r21, r22
+ }
+
+ static __forceinline void gather(const float* const grid_x,
+ const float* const grid_y,
+ const float* const grid_z,
+ const size_t line_offset,
+ const size_t lines,
+ Vec3vf8& v0_o,
+ Vec3vf8& v1_o,
+ Vec3vf8& v2_o)
+ {
+ const Vec3vf8 tri_v012_x = gather(grid_x,line_offset,lines);
+ const Vec3vf8 tri_v012_y = gather(grid_y,line_offset,lines);
+ const Vec3vf8 tri_v012_z = gather(grid_z,line_offset,lines);
+ v0_o = Vec3vf8(tri_v012_x[0],tri_v012_y[0],tri_v012_z[0]);
+ v1_o = Vec3vf8(tri_v012_x[1],tri_v012_y[1],tri_v012_z[1]);
+ v2_o = Vec3vf8(tri_v012_x[2],tri_v012_y[2],tri_v012_z[2]);
+ }
+ };
+#endif
+
+ template<typename vfloat>
+ static __forceinline Vec2<vfloat> decodeUV(const vfloat& uv)
+ {
+ typedef typename vfloat::Int vint;
+ const vint iu = asInt(uv) & 0xffff;
+ const vint iv = srl(asInt(uv),16);
+ const vfloat u = (vfloat)iu * vfloat(8.0f/0x10000);
+ const vfloat v = (vfloat)iv * vfloat(8.0f/0x10000);
+ return Vec2<vfloat>(u,v);
+ }
+
+ __forceinline unsigned int geomID() const {
+ return _geomID;
+ }
+
+ __forceinline unsigned int primID() const {
+ return _primID;
+ }
+
+ public:
+ BVH4::NodeRef troot;
+#if !defined(__64BIT__)
+ unsigned align1;
+#endif
+ unsigned time_steps;
+ unsigned width;
+
+ unsigned height;
+ unsigned dim_offset;
+ unsigned _geomID;
+ unsigned _primID;
+
+ unsigned align2;
+ unsigned gridOffset;
+ unsigned gridBytes;
+ unsigned rootOffset;
+
+ char data[1]; //!< after the struct we first store the BVH, then the grid, and finally the roots
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/grid_soa_intersector1.h b/thirdparty/embree/kernels/geometry/grid_soa_intersector1.h
new file mode 100644
index 0000000000..8fbf0d4bdf
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/grid_soa_intersector1.h
@@ -0,0 +1,207 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "grid_soa.h"
+#include "../common/ray.h"
+#include "triangle_intersector_pluecker.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ class GridSOAIntersector1
+ {
+ public:
+ typedef void Primitive;
+
+ class Precalculations
+ {
+ public:
+ __forceinline Precalculations (const Ray& ray, const void* ptr)
+ : grid(nullptr) {}
+
+ public:
+ GridSOA* grid;
+ int itime;
+ float ftime;
+ };
+
+ template<typename Loader>
+ static __forceinline void intersect(RayHit& ray,
+ IntersectContext* context,
+ const float* const grid_x,
+ const size_t line_offset,
+ const size_t lines,
+ Precalculations& pre)
+ {
+ typedef typename Loader::vfloat vfloat;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+ Vec3<vfloat> v0, v1, v2;
+ Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,v0,v1,v2);
+ GridSOA::MapUV<Loader> mapUV(grid_uv,line_offset,lines);
+ PlueckerIntersector1<Loader::M> intersector(ray,nullptr);
+ intersector.intersect(ray,v0,v1,v2,mapUV,Intersect1EpilogMU<Loader::M,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
+ };
+
+ template<typename Loader>
+ static __forceinline bool occluded(Ray& ray,
+ IntersectContext* context,
+ const float* const grid_x,
+ const size_t line_offset,
+ const size_t lines,
+ Precalculations& pre)
+ {
+ typedef typename Loader::vfloat vfloat;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ Vec3<vfloat> v0, v1, v2;
+ Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,v0,v1,v2);
+
+ GridSOA::MapUV<Loader> mapUV(grid_uv,line_offset,lines);
+ PlueckerIntersector1<Loader::M> intersector(ray,nullptr);
+ return intersector.intersect(ray,v0,v1,v2,mapUV,Occluded1EpilogMU<Loader::M,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
+ }
+
+ /*! Intersect a ray with the primitive. */
+ static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t line_offset = pre.grid->width;
+ const size_t lines = pre.grid->height;
+ const float* const grid_x = pre.grid->decodeLeaf(0,prim);
+
+#if defined(__AVX__)
+ intersect<GridSOA::Gather3x3>( ray, context, grid_x, line_offset, lines, pre);
+#else
+ intersect<GridSOA::Gather2x3>(ray, context, grid_x , line_offset, lines, pre);
+ if (likely(lines > 2))
+ intersect<GridSOA::Gather2x3>(ray, context, grid_x+line_offset, line_offset, lines, pre);
+#endif
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ static __forceinline bool occluded(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t line_offset = pre.grid->width;
+ const size_t lines = pre.grid->height;
+ const float* const grid_x = pre.grid->decodeLeaf(0,prim);
+
+#if defined(__AVX__)
+ return occluded<GridSOA::Gather3x3>( ray, context, grid_x, line_offset, lines, pre);
+#else
+ if (occluded<GridSOA::Gather2x3>(ray, context, grid_x , line_offset, lines, pre)) return true;
+ if (likely(lines > 2))
+ if (occluded<GridSOA::Gather2x3>(ray, context, grid_x+line_offset, line_offset, lines, pre)) return true;
+#endif
+ return false;
+ }
+ };
+
+ class GridSOAMBIntersector1
+ {
+ public:
+ typedef void Primitive;
+ typedef GridSOAIntersector1::Precalculations Precalculations;
+
+ template<typename Loader>
+ static __forceinline void intersect(RayHit& ray, const float ftime,
+ IntersectContext* context,
+ const float* const grid_x,
+ const size_t line_offset,
+ const size_t lines,
+ Precalculations& pre)
+ {
+ typedef typename Loader::vfloat vfloat;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const size_t grid_offset = pre.grid->gridBytes >> 2;
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ Vec3<vfloat> a0, a1, a2;
+ Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,a0,a1,a2);
+
+ Vec3<vfloat> b0, b1, b2;
+ Loader::gather(grid_x+grid_offset,grid_y+grid_offset,grid_z+grid_offset,line_offset,lines,b0,b1,b2);
+
+ Vec3<vfloat> v0 = lerp(a0,b0,vfloat(ftime));
+ Vec3<vfloat> v1 = lerp(a1,b1,vfloat(ftime));
+ Vec3<vfloat> v2 = lerp(a2,b2,vfloat(ftime));
+
+ GridSOA::MapUV<Loader> mapUV(grid_uv,line_offset,lines);
+ PlueckerIntersector1<Loader::M> intersector(ray,nullptr);
+ intersector.intersect(ray,v0,v1,v2,mapUV,Intersect1EpilogMU<Loader::M,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
+ };
+
+ template<typename Loader>
+ static __forceinline bool occluded(Ray& ray, const float ftime,
+ IntersectContext* context,
+ const float* const grid_x,
+ const size_t line_offset,
+ const size_t lines,
+ Precalculations& pre)
+ {
+ typedef typename Loader::vfloat vfloat;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const size_t grid_offset = pre.grid->gridBytes >> 2;
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ Vec3<vfloat> a0, a1, a2;
+ Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,a0,a1,a2);
+
+ Vec3<vfloat> b0, b1, b2;
+ Loader::gather(grid_x+grid_offset,grid_y+grid_offset,grid_z+grid_offset,line_offset,lines,b0,b1,b2);
+
+ Vec3<vfloat> v0 = lerp(a0,b0,vfloat(ftime));
+ Vec3<vfloat> v1 = lerp(a1,b1,vfloat(ftime));
+ Vec3<vfloat> v2 = lerp(a2,b2,vfloat(ftime));
+
+ GridSOA::MapUV<Loader> mapUV(grid_uv,line_offset,lines);
+ PlueckerIntersector1<Loader::M> intersector(ray,nullptr);
+ return intersector.intersect(ray,v0,v1,v2,mapUV,Occluded1EpilogMU<Loader::M,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
+ }
+
+ /*! Intersect a ray with the primitive. */
+ static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t line_offset = pre.grid->width;
+ const size_t lines = pre.grid->height;
+ const float* const grid_x = pre.grid->decodeLeaf(pre.itime,prim);
+
+#if defined(__AVX__)
+ intersect<GridSOA::Gather3x3>( ray, pre.ftime, context, grid_x, line_offset, lines, pre);
+#else
+ intersect<GridSOA::Gather2x3>(ray, pre.ftime, context, grid_x, line_offset, lines, pre);
+ if (likely(lines > 2))
+ intersect<GridSOA::Gather2x3>(ray, pre.ftime, context, grid_x+line_offset, line_offset, lines, pre);
+#endif
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ static __forceinline bool occluded(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t line_offset = pre.grid->width;
+ const size_t lines = pre.grid->height;
+ const float* const grid_x = pre.grid->decodeLeaf(pre.itime,prim);
+
+#if defined(__AVX__)
+ return occluded<GridSOA::Gather3x3>( ray, pre.ftime, context, grid_x, line_offset, lines, pre);
+#else
+ if (occluded<GridSOA::Gather2x3>(ray, pre.ftime, context, grid_x , line_offset, lines, pre)) return true;
+ if (likely(lines > 2))
+ if (occluded<GridSOA::Gather2x3>(ray, pre.ftime, context, grid_x+line_offset, line_offset, lines, pre)) return true;
+#endif
+ return false;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/grid_soa_intersector_packet.h b/thirdparty/embree/kernels/geometry/grid_soa_intersector_packet.h
new file mode 100644
index 0000000000..14cacab5fe
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/grid_soa_intersector_packet.h
@@ -0,0 +1,445 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "grid_soa.h"
+#include "../common/ray.h"
+#include "triangle_intersector_pluecker.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int K>
+ struct MapUV0
+ {
+ const float* const grid_uv;
+ size_t ofs00, ofs01, ofs10, ofs11;
+
+ __forceinline MapUV0(const float* const grid_uv, size_t ofs00, size_t ofs01, size_t ofs10, size_t ofs11)
+ : grid_uv(grid_uv), ofs00(ofs00), ofs01(ofs01), ofs10(ofs10), ofs11(ofs11) {}
+
+ __forceinline void operator() (vfloat<K>& u, vfloat<K>& v, Vec3vf<K>& Ng) const {
+ const vfloat<K> uv00(grid_uv[ofs00]);
+ const vfloat<K> uv01(grid_uv[ofs01]);
+ const vfloat<K> uv10(grid_uv[ofs10]);
+ const vfloat<K> uv11(grid_uv[ofs11]);
+ const Vec2vf<K> uv0 = GridSOA::decodeUV(uv00);
+ const Vec2vf<K> uv1 = GridSOA::decodeUV(uv01);
+ const Vec2vf<K> uv2 = GridSOA::decodeUV(uv10);
+ const Vec2vf<K> uv = madd(u,uv1,madd(v,uv2,(1.0f-u-v)*uv0));
+ u = uv[0]; v = uv[1];
+ }
+ };
+
+ template<int K>
+ struct MapUV1
+ {
+ const float* const grid_uv;
+ size_t ofs00, ofs01, ofs10, ofs11;
+
+ __forceinline MapUV1(const float* const grid_uv, size_t ofs00, size_t ofs01, size_t ofs10, size_t ofs11)
+ : grid_uv(grid_uv), ofs00(ofs00), ofs01(ofs01), ofs10(ofs10), ofs11(ofs11) {}
+
+ __forceinline void operator() (vfloat<K>& u, vfloat<K>& v, Vec3vf<K>& Ng) const {
+ const vfloat<K> uv00(grid_uv[ofs00]);
+ const vfloat<K> uv01(grid_uv[ofs01]);
+ const vfloat<K> uv10(grid_uv[ofs10]);
+ const vfloat<K> uv11(grid_uv[ofs11]);
+ const Vec2vf<K> uv0 = GridSOA::decodeUV(uv10);
+ const Vec2vf<K> uv1 = GridSOA::decodeUV(uv01);
+ const Vec2vf<K> uv2 = GridSOA::decodeUV(uv11);
+ const Vec2vf<K> uv = madd(u,uv1,madd(v,uv2,(1.0f-u-v)*uv0));
+ u = uv[0]; v = uv[1];
+ }
+ };
+
+ template<int K>
+ class GridSOAIntersectorK
+ {
+ public:
+ typedef void Primitive;
+
+ class Precalculations
+ {
+#if defined(__AVX__)
+ static const int M = 8;
+#else
+ static const int M = 4;
+#endif
+
+ public:
+ __forceinline Precalculations (const vbool<K>& valid, const RayK<K>& ray)
+ : grid(nullptr), intersector(valid,ray) {}
+
+ public:
+ GridSOA* grid;
+ PlueckerIntersectorK<M,K> intersector; // FIXME: use quad intersector
+ };
+
+ /*! Intersect a ray with the primitive. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t dim_offset = pre.grid->dim_offset;
+ const size_t line_offset = pre.grid->width;
+ const float* const grid_x = pre.grid->decodeLeaf(0,prim);
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ const size_t max_x = pre.grid->width == 2 ? 1 : 2;
+ const size_t max_y = pre.grid->height == 2 ? 1 : 2;
+ for (size_t y=0; y<max_y; y++)
+ {
+ for (size_t x=0; x<max_x; x++)
+ {
+ const size_t ofs00 = (y+0)*line_offset+(x+0);
+ const size_t ofs01 = (y+0)*line_offset+(x+1);
+ const size_t ofs10 = (y+1)*line_offset+(x+0);
+ const size_t ofs11 = (y+1)*line_offset+(x+1);
+ const Vec3vf<K> p00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
+ const Vec3vf<K> p01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
+ const Vec3vf<K> p10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
+ const Vec3vf<K> p11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
+
+ pre.intersector.intersectK(valid_i,ray,p00,p01,p10,MapUV0<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),IntersectKEpilogMU<1,K,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
+ pre.intersector.intersectK(valid_i,ray,p10,p01,p11,MapUV1<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),IntersectKEpilogMU<1,K,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
+ }
+ }
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t dim_offset = pre.grid->dim_offset;
+ const size_t line_offset = pre.grid->width;
+ const float* const grid_x = pre.grid->decodeLeaf(0,prim);
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ vbool<K> valid = valid_i;
+ const size_t max_x = pre.grid->width == 2 ? 1 : 2;
+ const size_t max_y = pre.grid->height == 2 ? 1 : 2;
+ for (size_t y=0; y<max_y; y++)
+ {
+ for (size_t x=0; x<max_x; x++)
+ {
+ const size_t ofs00 = (y+0)*line_offset+(x+0);
+ const size_t ofs01 = (y+0)*line_offset+(x+1);
+ const size_t ofs10 = (y+1)*line_offset+(x+0);
+ const size_t ofs11 = (y+1)*line_offset+(x+1);
+ const Vec3vf<K> p00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
+ const Vec3vf<K> p01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
+ const Vec3vf<K> p10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
+ const Vec3vf<K> p11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
+
+ pre.intersector.intersectK(valid,ray,p00,p01,p10,MapUV0<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),OccludedKEpilogMU<1,K,true>(valid,ray,context,pre.grid->geomID(),pre.grid->primID()));
+ if (none(valid)) break;
+ pre.intersector.intersectK(valid,ray,p10,p01,p11,MapUV1<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),OccludedKEpilogMU<1,K,true>(valid,ray,context,pre.grid->geomID(),pre.grid->primID()));
+ if (none(valid)) break;
+ }
+ }
+ return !valid;
+ }
+
+ template<typename Loader>
+ static __forceinline void intersect(RayHitK<K>& ray, size_t k,
+ IntersectContext* context,
+ const float* const grid_x,
+ const size_t line_offset,
+ const size_t lines,
+ Precalculations& pre)
+ {
+ typedef typename Loader::vfloat vfloat;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+ Vec3<vfloat> v0, v1, v2; Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,v0,v1,v2);
+ pre.intersector.intersect(ray,k,v0,v1,v2,GridSOA::MapUV<Loader>(grid_uv,line_offset,lines),Intersect1KEpilogMU<Loader::M,K,true>(ray,k,context,pre.grid->geomID(),pre.grid->primID()));
+ };
+
+ template<typename Loader>
+ static __forceinline bool occluded(RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const float* const grid_x,
+ const size_t line_offset,
+ const size_t lines,
+ Precalculations& pre)
+ {
+ typedef typename Loader::vfloat vfloat;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+ Vec3<vfloat> v0, v1, v2; Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,v0,v1,v2);
+ return pre.intersector.intersect(ray,k,v0,v1,v2,GridSOA::MapUV<Loader>(grid_uv,line_offset,lines),Occluded1KEpilogMU<Loader::M,K,true>(ray,k,context,pre.grid->geomID(),pre.grid->primID()));
+ }
+
+ /*! Intersect a ray with the primitive. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t line_offset = pre.grid->width;
+ const size_t lines = pre.grid->height;
+ const float* const grid_x = pre.grid->decodeLeaf(0,prim);
+#if defined(__AVX__)
+ intersect<GridSOA::Gather3x3>( ray, k, context, grid_x, line_offset, lines, pre);
+#else
+ intersect<GridSOA::Gather2x3>(ray, k, context, grid_x , line_offset, lines, pre);
+ if (likely(lines > 2))
+ intersect<GridSOA::Gather2x3>(ray, k, context, grid_x+line_offset, line_offset, lines, pre);
+#endif
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t line_offset = pre.grid->width;
+ const size_t lines = pre.grid->height;
+ const float* const grid_x = pre.grid->decodeLeaf(0,prim);
+
+#if defined(__AVX__)
+ return occluded<GridSOA::Gather3x3>( ray, k, context, grid_x, line_offset, lines, pre);
+#else
+ if (occluded<GridSOA::Gather2x3>(ray, k, context, grid_x , line_offset, lines, pre)) return true;
+ if (likely(lines > 2))
+ if (occluded<GridSOA::Gather2x3>(ray, k, context, grid_x+line_offset, line_offset, lines, pre)) return true;
+#endif
+ return false;
+ }
+ };
+
+ template<int K>
+ class GridSOAMBIntersectorK
+ {
+ public:
+ typedef void Primitive;
+ typedef typename GridSOAIntersectorK<K>::Precalculations Precalculations;
+
+ /*! Intersect a ray with the primitive. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ vfloat<K> vftime;
+ vint<K> vitime = getTimeSegment<K>(ray.time(), vfloat<K>((float)(pre.grid->time_steps-1)), vftime);
+
+ vbool<K> valid1 = valid_i;
+ while (any(valid1)) {
+ const size_t j = bsf(movemask(valid1));
+ const int itime = vitime[j];
+ const vbool<K> valid2 = valid1 & (itime == vitime);
+ valid1 = valid1 & !valid2;
+ intersect(valid2,pre,ray,vftime,itime,context,prim,lazy_node);
+ }
+ }
+
+ /*! Intersect a ray with the primitive. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, const vfloat<K>& ftime, int itime, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t grid_offset = pre.grid->gridBytes >> 2;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const size_t line_offset = pre.grid->width;
+ const float* const grid_x = pre.grid->decodeLeaf(itime,prim);
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ const size_t max_x = pre.grid->width == 2 ? 1 : 2;
+ const size_t max_y = pre.grid->height == 2 ? 1 : 2;
+ for (size_t y=0; y<max_y; y++)
+ {
+ for (size_t x=0; x<max_x; x++)
+ {
+ size_t ofs00 = (y+0)*line_offset+(x+0);
+ size_t ofs01 = (y+0)*line_offset+(x+1);
+ size_t ofs10 = (y+1)*line_offset+(x+0);
+ size_t ofs11 = (y+1)*line_offset+(x+1);
+ const Vec3vf<K> a00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
+ const Vec3vf<K> a01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
+ const Vec3vf<K> a10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
+ const Vec3vf<K> a11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
+ ofs00 += grid_offset;
+ ofs01 += grid_offset;
+ ofs10 += grid_offset;
+ ofs11 += grid_offset;
+ const Vec3vf<K> b00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
+ const Vec3vf<K> b01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
+ const Vec3vf<K> b10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
+ const Vec3vf<K> b11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
+ const Vec3vf<K> p00 = lerp(a00,b00,ftime);
+ const Vec3vf<K> p01 = lerp(a01,b01,ftime);
+ const Vec3vf<K> p10 = lerp(a10,b10,ftime);
+ const Vec3vf<K> p11 = lerp(a11,b11,ftime);
+
+ pre.intersector.intersectK(valid_i,ray,p00,p01,p10,MapUV0<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),IntersectKEpilogMU<1,K,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
+ pre.intersector.intersectK(valid_i,ray,p10,p01,p11,MapUV1<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),IntersectKEpilogMU<1,K,true>(ray,context,pre.grid->geomID(),pre.grid->primID()));
+ }
+ }
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ vfloat<K> vftime;
+ vint<K> vitime = getTimeSegment<K>(ray.time(), vfloat<K>((float)(pre.grid->time_steps-1)), vftime);
+
+ vbool<K> valid_o = valid_i;
+ vbool<K> valid1 = valid_i;
+ while (any(valid1)) {
+ const int j = int(bsf(movemask(valid1)));
+ const int itime = vitime[j];
+ const vbool<K> valid2 = valid1 & (itime == vitime);
+ valid1 = valid1 & !valid2;
+ valid_o &= !valid2 | occluded(valid2,pre,ray,vftime,itime,context,prim,lazy_node);
+ }
+ return !valid_o;
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, const vfloat<K>& ftime, int itime, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ const size_t grid_offset = pre.grid->gridBytes >> 2;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const size_t line_offset = pre.grid->width;
+ const float* const grid_x = pre.grid->decodeLeaf(itime,prim);
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ vbool<K> valid = valid_i;
+ const size_t max_x = pre.grid->width == 2 ? 1 : 2;
+ const size_t max_y = pre.grid->height == 2 ? 1 : 2;
+ for (size_t y=0; y<max_y; y++)
+ {
+ for (size_t x=0; x<max_x; x++)
+ {
+ size_t ofs00 = (y+0)*line_offset+(x+0);
+ size_t ofs01 = (y+0)*line_offset+(x+1);
+ size_t ofs10 = (y+1)*line_offset+(x+0);
+ size_t ofs11 = (y+1)*line_offset+(x+1);
+ const Vec3vf<K> a00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
+ const Vec3vf<K> a01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
+ const Vec3vf<K> a10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
+ const Vec3vf<K> a11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
+ ofs00 += grid_offset;
+ ofs01 += grid_offset;
+ ofs10 += grid_offset;
+ ofs11 += grid_offset;
+ const Vec3vf<K> b00(grid_x[ofs00],grid_y[ofs00],grid_z[ofs00]);
+ const Vec3vf<K> b01(grid_x[ofs01],grid_y[ofs01],grid_z[ofs01]);
+ const Vec3vf<K> b10(grid_x[ofs10],grid_y[ofs10],grid_z[ofs10]);
+ const Vec3vf<K> b11(grid_x[ofs11],grid_y[ofs11],grid_z[ofs11]);
+ const Vec3vf<K> p00 = lerp(a00,b00,ftime);
+ const Vec3vf<K> p01 = lerp(a01,b01,ftime);
+ const Vec3vf<K> p10 = lerp(a10,b10,ftime);
+ const Vec3vf<K> p11 = lerp(a11,b11,ftime);
+
+ pre.intersector.intersectK(valid,ray,p00,p01,p10,MapUV0<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),OccludedKEpilogMU<1,K,true>(valid,ray,context,pre.grid->geomID(),pre.grid->primID()));
+ if (none(valid)) break;
+ pre.intersector.intersectK(valid,ray,p10,p01,p11,MapUV1<K>(grid_uv,ofs00,ofs01,ofs10,ofs11),OccludedKEpilogMU<1,K,true>(valid,ray,context,pre.grid->geomID(),pre.grid->primID()));
+ if (none(valid)) break;
+ }
+ }
+ return valid;
+ }
+
+ template<typename Loader>
+ static __forceinline void intersect(RayHitK<K>& ray, size_t k,
+ const float ftime,
+ IntersectContext* context,
+ const float* const grid_x,
+ const size_t line_offset,
+ const size_t lines,
+ Precalculations& pre)
+ {
+ typedef typename Loader::vfloat vfloat;
+ const size_t grid_offset = pre.grid->gridBytes >> 2;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ Vec3<vfloat> a0, a1, a2;
+ Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,a0,a1,a2);
+
+ Vec3<vfloat> b0, b1, b2;
+ Loader::gather(grid_x+grid_offset,grid_y+grid_offset,grid_z+grid_offset,line_offset,lines,b0,b1,b2);
+
+ Vec3<vfloat> v0 = lerp(a0,b0,vfloat(ftime));
+ Vec3<vfloat> v1 = lerp(a1,b1,vfloat(ftime));
+ Vec3<vfloat> v2 = lerp(a2,b2,vfloat(ftime));
+
+ pre.intersector.intersect(ray,k,v0,v1,v2,GridSOA::MapUV<Loader>(grid_uv,line_offset,lines),Intersect1KEpilogMU<Loader::M,K,true>(ray,k,context,pre.grid->geomID(),pre.grid->primID()));
+ };
+
+ template<typename Loader>
+ static __forceinline bool occluded(RayK<K>& ray, size_t k,
+ const float ftime,
+ IntersectContext* context,
+ const float* const grid_x,
+ const size_t line_offset,
+ const size_t lines,
+ Precalculations& pre)
+ {
+ typedef typename Loader::vfloat vfloat;
+ const size_t grid_offset = pre.grid->gridBytes >> 2;
+ const size_t dim_offset = pre.grid->dim_offset;
+ const float* const grid_y = grid_x + 1 * dim_offset;
+ const float* const grid_z = grid_x + 2 * dim_offset;
+ const float* const grid_uv = grid_x + 3 * dim_offset;
+
+ Vec3<vfloat> a0, a1, a2;
+ Loader::gather(grid_x,grid_y,grid_z,line_offset,lines,a0,a1,a2);
+
+ Vec3<vfloat> b0, b1, b2;
+ Loader::gather(grid_x+grid_offset,grid_y+grid_offset,grid_z+grid_offset,line_offset,lines,b0,b1,b2);
+
+ Vec3<vfloat> v0 = lerp(a0,b0,vfloat(ftime));
+ Vec3<vfloat> v1 = lerp(a1,b1,vfloat(ftime));
+ Vec3<vfloat> v2 = lerp(a2,b2,vfloat(ftime));
+
+ return pre.intersector.intersect(ray,k,v0,v1,v2,GridSOA::MapUV<Loader>(grid_uv,line_offset,lines),Occluded1KEpilogMU<Loader::M,K,true>(ray,k,context,pre.grid->geomID(),pre.grid->primID()));
+ }
+
+ /*! Intersect a ray with the primitive. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ float ftime;
+ int itime = getTimeSegment(ray.time()[k], float(pre.grid->time_steps-1), ftime);
+
+ const size_t line_offset = pre.grid->width;
+ const size_t lines = pre.grid->height;
+ const float* const grid_x = pre.grid->decodeLeaf(itime,prim);
+
+#if defined(__AVX__)
+ intersect<GridSOA::Gather3x3>( ray, k, ftime, context, grid_x, line_offset, lines, pre);
+#else
+ intersect<GridSOA::Gather2x3>(ray, k, ftime, context, grid_x, line_offset, lines, pre);
+ if (likely(lines > 2))
+ intersect<GridSOA::Gather2x3>(ray, k, ftime, context, grid_x+line_offset, line_offset, lines, pre);
+#endif
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ float ftime;
+ int itime = getTimeSegment(ray.time()[k], float(pre.grid->time_steps-1), ftime);
+
+ const size_t line_offset = pre.grid->width;
+ const size_t lines = pre.grid->height;
+ const float* const grid_x = pre.grid->decodeLeaf(itime,prim);
+
+#if defined(__AVX__)
+ return occluded<GridSOA::Gather3x3>( ray, k, ftime, context, grid_x, line_offset, lines, pre);
+#else
+ if (occluded<GridSOA::Gather2x3>(ray, k, ftime, context, grid_x, line_offset, lines, pre)) return true;
+ if (likely(lines > 2))
+ if (occluded<GridSOA::Gather2x3>(ray, k, ftime, context, grid_x+line_offset, line_offset, lines, pre)) return true;
+#endif
+ return false;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/instance.h b/thirdparty/embree/kernels/geometry/instance.h
new file mode 100644
index 0000000000..7c0e7e0f49
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/instance.h
@@ -0,0 +1,78 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+#include "../common/scene_instance.h"
+
+namespace embree
+{
+ struct InstancePrimitive
+ {
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* primitive supports multiple time segments */
+ static const bool singleTimeSegment = false;
+
+ /* Returns maximum number of stored primitives */
+ static __forceinline size_t max_size() { return 1; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return N; }
+
+ public:
+
+ InstancePrimitive (const Instance* instance, unsigned int instID)
+ : instance(instance)
+ , instID_(instID)
+ {}
+
+ __forceinline void fill(const PrimRef* prims, size_t& i, size_t end, Scene* scene)
+ {
+ assert(end-i == 1);
+ const PrimRef& prim = prims[i]; i++;
+ const unsigned int geomID = prim.geomID();
+ const Instance* instance = scene->get<Instance>(geomID);
+ new (this) InstancePrimitive(instance, geomID);
+ }
+
+ __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& i, size_t end, Scene* scene, size_t itime)
+ {
+ assert(end-i == 1);
+ const PrimRef& prim = prims[i]; i++;
+ const unsigned int geomID = prim.geomID();
+ const Instance* instance = scene->get<Instance>(geomID);
+ new (this) InstancePrimitive(instance,geomID);
+ return instance->linearBounds(0,itime);
+ }
+
+ __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& i, size_t end, Scene* scene, const BBox1f time_range)
+ {
+ assert(end-i == 1);
+ const PrimRefMB& prim = prims[i]; i++;
+ const unsigned int geomID = prim.geomID();
+ const Instance* instance = scene->get<Instance>(geomID);
+ new (this) InstancePrimitive(instance,geomID);
+ return instance->linearBounds(0,time_range);
+ }
+
+ /* Updates the primitive */
+ __forceinline BBox3fa update(Instance* instance) {
+ return instance->bounds(0);
+ }
+
+ public:
+ const Instance* instance;
+ const unsigned int instID_ = std::numeric_limits<unsigned int>::max ();
+ };
+}
diff --git a/thirdparty/embree/kernels/geometry/instance_intersector.h b/thirdparty/embree/kernels/geometry/instance_intersector.h
new file mode 100644
index 0000000000..28a7b728e5
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/instance_intersector.h
@@ -0,0 +1,84 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "instance.h"
+#include "../common/ray.h"
+#include "../common/point_query.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct InstanceIntersector1
+ {
+ typedef InstancePrimitive Primitive;
+
+ struct Precalculations {
+ __forceinline Precalculations (const Ray& ray, const void *ptr) {}
+ };
+
+ static void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim);
+ static bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim);
+ static bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& prim);
+ };
+
+ struct InstanceIntersector1MB
+ {
+ typedef InstancePrimitive Primitive;
+
+ struct Precalculations {
+ __forceinline Precalculations (const Ray& ray, const void *ptr) {}
+ };
+
+ static void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim);
+ static bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim);
+ static bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& prim);
+ };
+
+ template<int K>
+ struct InstanceIntersectorK
+ {
+ typedef InstancePrimitive Primitive;
+
+ struct Precalculations {
+ __forceinline Precalculations (const vbool<K>& valid, const RayK<K>& ray) {}
+ };
+
+ static void intersect(const vbool<K>& valid_i, const Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& prim);
+ static vbool<K> occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& prim);
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
+ intersect(vbool<K>(1<<int(k)),pre,ray,context,prim);
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
+ occluded(vbool<K>(1<<int(k)),pre,ray,context,prim);
+ return ray.tfar[k] < 0.0f;
+ }
+ };
+
+ template<int K>
+ struct InstanceIntersectorKMB
+ {
+ typedef InstancePrimitive Primitive;
+
+ struct Precalculations {
+ __forceinline Precalculations (const vbool<K>& valid, const RayK<K>& ray) {}
+ };
+
+ static void intersect(const vbool<K>& valid_i, const Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& prim);
+ static vbool<K> occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& prim);
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
+ intersect(vbool<K>(1<<int(k)),pre,ray,context,prim);
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
+ occluded(vbool<K>(1<<int(k)),pre,ray,context,prim);
+ return ray.tfar[k] < 0.0f;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/intersector_epilog.h b/thirdparty/embree/kernels/geometry/intersector_epilog.h
new file mode 100644
index 0000000000..7bf134cc54
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/intersector_epilog.h
@@ -0,0 +1,979 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "../common/context.h"
+#include "filter.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct UVIdentity {
+ __forceinline void operator() (vfloat<M>& u, vfloat<M>& v, Vec3vf<M>& Ng) const {}
+ };
+
+
+ template<bool filter>
+ struct Intersect1Epilog1
+ {
+ RayHit& ray;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline Intersect1Epilog1(RayHit& ray,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (Hit& hit) const
+ {
+ /* ray mask test */
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+#if defined(EMBREE_RAY_MASK)
+ if ((geometry->mask & ray.mask) == 0) return false;
+#endif
+ hit.finalize();
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
+ HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
+ const float old_t = ray.tfar;
+ ray.tfar = hit.t;
+ bool found = runIntersectionFilter1(geometry,ray,context,h);
+ if (!found) ray.tfar = old_t;
+ return found;
+ }
+ }
+#endif
+
+ /* update hit information */
+ ray.tfar = hit.t;
+ ray.Ng = hit.Ng;
+ ray.u = hit.u;
+ ray.v = hit.v;
+ ray.primID = primID;
+ ray.geomID = geomID;
+ instance_id_stack::copy_UU(context->user->instID, ray.instID);
+ return true;
+ }
+ };
+
+ template<bool filter>
+ struct Occluded1Epilog1
+ {
+ Ray& ray;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline Occluded1Epilog1(Ray& ray,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (Hit& hit) const
+ {
+ /* ray mask test */
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+
+
+#if defined(EMBREE_RAY_MASK)
+ if ((geometry->mask & ray.mask) == 0) return false;
+#endif
+ hit.finalize();
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
+ HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
+ const float old_t = ray.tfar;
+ ray.tfar = hit.t;
+ const bool found = runOcclusionFilter1(geometry,ray,context,h);
+ if (!found) ray.tfar = old_t;
+ return found;
+ }
+ }
+#endif
+ return true;
+ }
+ };
+
+ template<int K, bool filter>
+ struct Intersect1KEpilog1
+ {
+ RayHitK<K>& ray;
+ size_t k;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline Intersect1KEpilog1(RayHitK<K>& ray, size_t k,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (Hit& hit) const
+ {
+ /* ray mask test */
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+#if defined(EMBREE_RAY_MASK)
+ if ((geometry->mask & ray.mask[k]) == 0)
+ return false;
+#endif
+ hit.finalize();
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
+ HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
+ const float old_t = ray.tfar[k];
+ ray.tfar[k] = hit.t;
+ const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
+ if (!found) ray.tfar[k] = old_t;
+ return found;
+ }
+ }
+#endif
+
+ /* update hit information */
+ ray.tfar[k] = hit.t;
+ ray.Ng.x[k] = hit.Ng.x;
+ ray.Ng.y[k] = hit.Ng.y;
+ ray.Ng.z[k] = hit.Ng.z;
+ ray.u[k] = hit.u;
+ ray.v[k] = hit.v;
+ ray.primID[k] = primID;
+ ray.geomID[k] = geomID;
+ instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
+ return true;
+ }
+ };
+
+ template<int K, bool filter>
+ struct Occluded1KEpilog1
+ {
+ RayK<K>& ray;
+ size_t k;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline Occluded1KEpilog1(RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (Hit& hit) const
+ {
+ /* ray mask test */
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+#if defined(EMBREE_RAY_MASK)
+ if ((geometry->mask & ray.mask[k]) == 0)
+ return false;
+#endif
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
+ hit.finalize();
+ HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
+ const float old_t = ray.tfar[k];
+ ray.tfar[k] = hit.t;
+ const bool found = any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h));
+ if (!found) ray.tfar[k] = old_t;
+ return found;
+ }
+ }
+#endif
+ return true;
+ }
+ };
+
+ template<int M, bool filter>
+ struct Intersect1EpilogM
+ {
+ RayHit& ray;
+ IntersectContext* context;
+ const vuint<M>& geomIDs;
+ const vuint<M>& primIDs;
+
+ __forceinline Intersect1EpilogM(RayHit& ray,
+ IntersectContext* context,
+ const vuint<M>& geomIDs,
+ const vuint<M>& primIDs)
+ : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
+ {
+ Scene* scene MAYBE_UNUSED = context->scene;
+ vbool<M> valid = valid_i;
+ hit.finalize();
+ size_t i = select_min(valid,hit.vt);
+ unsigned int geomID = geomIDs[i];
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
+ bool foundhit = false;
+ goto entry;
+ while (true)
+ {
+ if (unlikely(none(valid))) return foundhit;
+ i = select_min(valid,hit.vt);
+
+ geomID = geomIDs[i];
+ entry:
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+
+#if defined(EMBREE_RAY_MASK)
+ /* goto next hit if mask test fails */
+ if ((geometry->mask & ray.mask) == 0) {
+ clear(valid,i);
+ continue;
+ }
+#endif
+
+#if defined(EMBREE_FILTER_FUNCTION)
+ /* call intersection filter function */
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
+ const Vec2f uv = hit.uv(i);
+ HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
+ const float old_t = ray.tfar;
+ ray.tfar = hit.t(i);
+ const bool found = runIntersectionFilter1(geometry,ray,context,h);
+ if (!found) ray.tfar = old_t;
+ foundhit |= found;
+ clear(valid,i);
+ valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
+ continue;
+ }
+ }
+#endif
+ break;
+ }
+#endif
+
+ /* update hit information */
+ const Vec2f uv = hit.uv(i);
+ ray.tfar = hit.vt[i];
+ ray.Ng.x = hit.vNg.x[i];
+ ray.Ng.y = hit.vNg.y[i];
+ ray.Ng.z = hit.vNg.z[i];
+ ray.u = uv.x;
+ ray.v = uv.y;
+ ray.primID = primIDs[i];
+ ray.geomID = geomID;
+ instance_id_stack::copy_UU(context->user->instID, ray.instID);
+ return true;
+
+ }
+ };
+
+ template<int M, bool filter>
+ struct Occluded1EpilogM
+ {
+ Ray& ray;
+ IntersectContext* context;
+ const vuint<M>& geomIDs;
+ const vuint<M>& primIDs;
+
+ __forceinline Occluded1EpilogM(Ray& ray,
+ IntersectContext* context,
+ const vuint<M>& geomIDs,
+ const vuint<M>& primIDs)
+ : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
+ {
+ Scene* scene MAYBE_UNUSED = context->scene;
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
+ if (unlikely(filter))
+ hit.finalize(); /* called only once */
+
+ vbool<M> valid = valid_i;
+ size_t m=movemask(valid);
+ goto entry;
+ while (true)
+ {
+ if (unlikely(m == 0)) return false;
+ entry:
+ size_t i=bsf(m);
+
+ const unsigned int geomID = geomIDs[i];
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+
+#if defined(EMBREE_RAY_MASK)
+ /* goto next hit if mask test fails */
+ if ((geometry->mask & ray.mask) == 0) {
+ m=btc(m,i);
+ continue;
+ }
+#endif
+
+#if defined(EMBREE_FILTER_FUNCTION)
+ /* if we have no filter then the test passed */
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
+ {
+ const Vec2f uv = hit.uv(i);
+ HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
+ const float old_t = ray.tfar;
+ ray.tfar = hit.t(i);
+ if (runOcclusionFilter1(geometry,ray,context,h)) return true;
+ ray.tfar = old_t;
+ m=btc(m,i);
+ continue;
+ }
+ }
+#endif
+ break;
+ }
+#endif
+
+ return true;
+ }
+ };
+
+ template<int M, bool filter>
+ struct Intersect1EpilogMU
+ {
+ RayHit& ray;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline Intersect1EpilogMU(RayHit& ray,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
+ {
+ /* ray mask test */
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+#if defined(EMBREE_RAY_MASK)
+ if ((geometry->mask & ray.mask) == 0) return false;
+#endif
+
+ vbool<M> valid = valid_i;
+ hit.finalize();
+
+ size_t i = select_min(valid,hit.vt);
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
+ {
+ bool foundhit = false;
+ while (true)
+ {
+ /* call intersection filter function */
+ Vec2f uv = hit.uv(i);
+ const float old_t = ray.tfar;
+ ray.tfar = hit.t(i);
+ HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
+ const bool found = runIntersectionFilter1(geometry,ray,context,h);
+ if (!found) ray.tfar = old_t;
+ foundhit |= found;
+ clear(valid,i);
+ valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
+ if (unlikely(none(valid))) break;
+ i = select_min(valid,hit.vt);
+ }
+ return foundhit;
+ }
+#endif
+
+ /* update hit information */
+ const Vec2f uv = hit.uv(i);
+ const Vec3fa Ng = hit.Ng(i);
+ ray.tfar = hit.t(i);
+ ray.Ng.x = Ng.x;
+ ray.Ng.y = Ng.y;
+ ray.Ng.z = Ng.z;
+ ray.u = uv.x;
+ ray.v = uv.y;
+ ray.primID = primID;
+ ray.geomID = geomID;
+ instance_id_stack::copy_UU(context->user->instID, ray.instID);
+ return true;
+ }
+ };
+
+ template<int M, bool filter>
+ struct Occluded1EpilogMU
+ {
+ Ray& ray;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline Occluded1EpilogMU(Ray& ray,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (const vbool<M>& valid, Hit& hit) const
+ {
+ /* ray mask test */
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+#if defined(EMBREE_RAY_MASK)
+ if ((geometry->mask & ray.mask) == 0) return false;
+#endif
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
+ {
+ hit.finalize();
+ for (size_t m=movemask(valid), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
+ {
+ const Vec2f uv = hit.uv(i);
+ const float old_t = ray.tfar;
+ ray.tfar = hit.t(i);
+ HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
+ if (runOcclusionFilter1(geometry,ray,context,h)) return true;
+ ray.tfar = old_t;
+ }
+ return false;
+ }
+#endif
+ return true;
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct IntersectKEpilogM
+ {
+ RayHitK<K>& ray;
+ IntersectContext* context;
+ const vuint<M>& geomIDs;
+ const vuint<M>& primIDs;
+ const size_t i;
+
+ __forceinline IntersectKEpilogM(RayHitK<K>& ray,
+ IntersectContext* context,
+ const vuint<M>& geomIDs,
+ const vuint<M>& primIDs,
+ size_t i)
+ : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
+
+ template<typename Hit>
+ __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
+ {
+ Scene* scene MAYBE_UNUSED = context->scene;
+
+ vfloat<K> u, v, t;
+ Vec3vf<K> Ng;
+ vbool<K> valid = valid_i;
+
+ std::tie(u,v,t,Ng) = hit();
+
+ const unsigned int geomID = geomIDs[i];
+ const unsigned int primID = primIDs[i];
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+
+ /* ray masking test */
+#if defined(EMBREE_RAY_MASK)
+ valid &= (geometry->mask & ray.mask) != 0;
+ if (unlikely(none(valid))) return false;
+#endif
+
+ /* occlusion filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
+ HitK<K> h(context->user,geomID,primID,u,v,Ng);
+ const vfloat<K> old_t = ray.tfar;
+ ray.tfar = select(valid,t,ray.tfar);
+ const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
+ ray.tfar = select(m_accept,ray.tfar,old_t);
+ return m_accept;
+ }
+ }
+#endif
+
+ /* update hit information */
+ vfloat<K>::store(valid,&ray.tfar,t);
+ vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
+ vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
+ vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
+ vfloat<K>::store(valid,&ray.u,u);
+ vfloat<K>::store(valid,&ray.v,v);
+ vuint<K>::store(valid,&ray.primID,primID);
+ vuint<K>::store(valid,&ray.geomID,geomID);
+ instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);
+ return valid;
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct OccludedKEpilogM
+ {
+ vbool<K>& valid0;
+ RayK<K>& ray;
+ IntersectContext* context;
+ const vuint<M>& geomIDs;
+ const vuint<M>& primIDs;
+ const size_t i;
+
+ __forceinline OccludedKEpilogM(vbool<K>& valid0,
+ RayK<K>& ray,
+ IntersectContext* context,
+ const vuint<M>& geomIDs,
+ const vuint<M>& primIDs,
+ size_t i)
+ : valid0(valid0), ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
+
+ template<typename Hit>
+ __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
+ {
+ vbool<K> valid = valid_i;
+
+ /* ray masking test */
+ Scene* scene MAYBE_UNUSED = context->scene;
+ const unsigned int geomID MAYBE_UNUSED = geomIDs[i];
+ const unsigned int primID MAYBE_UNUSED = primIDs[i];
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+#if defined(EMBREE_RAY_MASK)
+ valid &= (geometry->mask & ray.mask) != 0;
+ if (unlikely(none(valid))) return valid;
+#endif
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
+ {
+ vfloat<K> u, v, t;
+ Vec3vf<K> Ng;
+ std::tie(u,v,t,Ng) = hit();
+ HitK<K> h(context->user,geomID,primID,u,v,Ng);
+ const vfloat<K> old_t = ray.tfar;
+ ray.tfar = select(valid,t,ray.tfar);
+ valid = runOcclusionFilter(valid,geometry,ray,context,h);
+ ray.tfar = select(valid,ray.tfar,old_t);
+ }
+ }
+#endif
+
+ /* update occlusion */
+ valid0 = valid0 & !valid;
+ return valid;
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct IntersectKEpilogMU
+ {
+ RayHitK<K>& ray;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline IntersectKEpilogMU(RayHitK<K>& ray,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline vbool<K> operator() (const vbool<K>& valid_org, const Hit& hit) const
+ {
+ vbool<K> valid = valid_org;
+ vfloat<K> u, v, t;
+ Vec3vf<K> Ng;
+ std::tie(u,v,t,Ng) = hit();
+
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+
+ /* ray masking test */
+#if defined(EMBREE_RAY_MASK)
+ valid &= (geometry->mask & ray.mask) != 0;
+ if (unlikely(none(valid))) return false;
+#endif
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
+ HitK<K> h(context->user,geomID,primID,u,v,Ng);
+ const vfloat<K> old_t = ray.tfar;
+ ray.tfar = select(valid,t,ray.tfar);
+ const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
+ ray.tfar = select(m_accept,ray.tfar,old_t);
+ return m_accept;
+ }
+ }
+#endif
+
+ /* update hit information */
+ vfloat<K>::store(valid,&ray.tfar,t);
+ vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
+ vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
+ vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
+ vfloat<K>::store(valid,&ray.u,u);
+ vfloat<K>::store(valid,&ray.v,v);
+ vuint<K>::store(valid,&ray.primID,primID);
+ vuint<K>::store(valid,&ray.geomID,geomID);
+ instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);
+ return valid;
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct OccludedKEpilogMU
+ {
+ vbool<K>& valid0;
+ RayK<K>& ray;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline OccludedKEpilogMU(vbool<K>& valid0,
+ RayK<K>& ray,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : valid0(valid0), ray(ray), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
+ {
+ vbool<K> valid = valid_i;
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+
+#if defined(EMBREE_RAY_MASK)
+ valid &= (geometry->mask & ray.mask) != 0;
+ if (unlikely(none(valid))) return false;
+#endif
+
+ /* occlusion filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
+ {
+ vfloat<K> u, v, t;
+ Vec3vf<K> Ng;
+ std::tie(u,v,t,Ng) = hit();
+ HitK<K> h(context->user,geomID,primID,u,v,Ng);
+ const vfloat<K> old_t = ray.tfar;
+ ray.tfar = select(valid,t,ray.tfar);
+ valid = runOcclusionFilter(valid,geometry,ray,context,h);
+ ray.tfar = select(valid,ray.tfar,old_t);
+ }
+ }
+#endif
+
+ /* update occlusion */
+ valid0 = valid0 & !valid;
+ return valid;
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct Intersect1KEpilogM
+ {
+ RayHitK<K>& ray;
+ size_t k;
+ IntersectContext* context;
+ const vuint<M>& geomIDs;
+ const vuint<M>& primIDs;
+
+ __forceinline Intersect1KEpilogM(RayHitK<K>& ray, size_t k,
+ IntersectContext* context,
+ const vuint<M>& geomIDs,
+ const vuint<M>& primIDs)
+ : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
+ {
+ Scene* scene MAYBE_UNUSED = context->scene;
+ vbool<M> valid = valid_i;
+ hit.finalize();
+ size_t i = select_min(valid,hit.vt);
+ assert(i<M);
+ unsigned int geomID = geomIDs[i];
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
+ bool foundhit = false;
+ goto entry;
+ while (true)
+ {
+ if (unlikely(none(valid))) return foundhit;
+ i = select_min(valid,hit.vt);
+ assert(i<M);
+ geomID = geomIDs[i];
+ entry:
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+
+#if defined(EMBREE_RAY_MASK)
+ /* goto next hit if mask test fails */
+ if ((geometry->mask & ray.mask[k]) == 0) {
+ clear(valid,i);
+ continue;
+ }
+#endif
+
+#if defined(EMBREE_FILTER_FUNCTION)
+ /* call intersection filter function */
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
+ assert(i<M);
+ const Vec2f uv = hit.uv(i);
+ HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
+ const float old_t = ray.tfar[k];
+ ray.tfar[k] = hit.t(i);
+ const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
+ if (!found) ray.tfar[k] = old_t;
+ foundhit = foundhit | found;
+ clear(valid,i);
+ valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
+ continue;
+ }
+ }
+#endif
+ break;
+ }
+#endif
+ assert(i<M);
+ /* update hit information */
+ const Vec2f uv = hit.uv(i);
+ ray.tfar[k] = hit.t(i);
+ ray.Ng.x[k] = hit.vNg.x[i];
+ ray.Ng.y[k] = hit.vNg.y[i];
+ ray.Ng.z[k] = hit.vNg.z[i];
+ ray.u[k] = uv.x;
+ ray.v[k] = uv.y;
+ ray.primID[k] = primIDs[i];
+ ray.geomID[k] = geomID;
+ instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
+ return true;
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct Occluded1KEpilogM
+ {
+ RayK<K>& ray;
+ size_t k;
+ IntersectContext* context;
+ const vuint<M>& geomIDs;
+ const vuint<M>& primIDs;
+
+ __forceinline Occluded1KEpilogM(RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const vuint<M>& geomIDs,
+ const vuint<M>& primIDs)
+ : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
+ {
+ Scene* scene MAYBE_UNUSED = context->scene;
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
+ if (unlikely(filter))
+ hit.finalize(); /* called only once */
+
+ vbool<M> valid = valid_i;
+ size_t m=movemask(valid);
+ goto entry;
+ while (true)
+ {
+ if (unlikely(m == 0)) return false;
+ entry:
+ size_t i=bsf(m);
+
+ const unsigned int geomID = geomIDs[i];
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+
+#if defined(EMBREE_RAY_MASK)
+ /* goto next hit if mask test fails */
+ if ((geometry->mask & ray.mask[k]) == 0) {
+ m=btc(m,i);
+ continue;
+ }
+#endif
+
+#if defined(EMBREE_FILTER_FUNCTION)
+ /* execute occlusion filer */
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
+ {
+ const Vec2f uv = hit.uv(i);
+ const float old_t = ray.tfar[k];
+ ray.tfar[k] = hit.t(i);
+ HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
+ if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
+ ray.tfar[k] = old_t;
+ m=btc(m,i);
+ continue;
+ }
+ }
+#endif
+ break;
+ }
+#endif
+ return true;
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct Intersect1KEpilogMU
+ {
+ RayHitK<K>& ray;
+ size_t k;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline Intersect1KEpilogMU(RayHitK<K>& ray, size_t k,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
+ {
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+#if defined(EMBREE_RAY_MASK)
+ /* ray mask test */
+ if ((geometry->mask & ray.mask[k]) == 0)
+ return false;
+#endif
+
+ /* finalize hit calculation */
+ vbool<M> valid = valid_i;
+ hit.finalize();
+ size_t i = select_min(valid,hit.vt);
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
+ {
+ bool foundhit = false;
+ while (true)
+ {
+ const Vec2f uv = hit.uv(i);
+ const float old_t = ray.tfar[k];
+ ray.tfar[k] = hit.t(i);
+ HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
+ const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
+ if (!found) ray.tfar[k] = old_t;
+ foundhit = foundhit | found;
+ clear(valid,i);
+ valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
+ if (unlikely(none(valid))) break;
+ i = select_min(valid,hit.vt);
+ }
+ return foundhit;
+ }
+ }
+#endif
+
+ /* update hit information */
+ const Vec2f uv = hit.uv(i);
+ const Vec3fa Ng = hit.Ng(i);
+ ray.tfar[k] = hit.t(i);
+ ray.Ng.x[k] = Ng.x;
+ ray.Ng.y[k] = Ng.y;
+ ray.Ng.z[k] = Ng.z;
+ ray.u[k] = uv.x;
+ ray.v[k] = uv.y;
+ ray.primID[k] = primID;
+ ray.geomID[k] = geomID;
+ instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
+ return true;
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct Occluded1KEpilogMU
+ {
+ RayK<K>& ray;
+ size_t k;
+ IntersectContext* context;
+ const unsigned int geomID;
+ const unsigned int primID;
+
+ __forceinline Occluded1KEpilogMU(RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
+
+ template<typename Hit>
+ __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
+ {
+ Scene* scene MAYBE_UNUSED = context->scene;
+ Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
+#if defined(EMBREE_RAY_MASK)
+ /* ray mask test */
+ if ((geometry->mask & ray.mask[k]) == 0)
+ return false;
+#endif
+
+ /* intersection filter test */
+#if defined(EMBREE_FILTER_FUNCTION)
+ if (filter) {
+ if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
+ {
+ hit.finalize();
+ for (size_t m=movemask(valid_i), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
+ {
+ const Vec2f uv = hit.uv(i);
+ const float old_t = ray.tfar[k];
+ ray.tfar[k] = hit.t(i);
+ HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
+ if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
+ ray.tfar[k] = old_t;
+ }
+ return false;
+ }
+ }
+#endif
+ return true;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/intersector_iterators.h b/thirdparty/embree/kernels/geometry/intersector_iterators.h
new file mode 100644
index 0000000000..9cac1cd25c
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/intersector_iterators.h
@@ -0,0 +1,172 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/scene.h"
+#include "../common/ray.h"
+#include "../common/point_query.h"
+#include "../bvh/node_intersector1.h"
+#include "../bvh/node_intersector_packet.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename Intersector>
+ struct ArrayIntersector1
+ {
+ typedef typename Intersector::Primitive Primitive;
+ typedef typename Intersector::Precalculations Precalculations;
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ for (size_t i=0; i<num; i++)
+ Intersector::intersect(pre,ray,context,prim[i]);
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ for (size_t i=0; i<num; i++) {
+ if (Intersector::occluded(pre,ray,context,prim[i]))
+ return true;
+ }
+ return false;
+ }
+
+ template<int N>
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t num, const TravPointQuery<N> &tquery, size_t& lazy_node)
+ {
+ bool changed = false;
+ for (size_t i=0; i<num; i++)
+ changed |= Intersector::pointQuery(query, context, prim[i]);
+ return changed;
+ }
+
+ template<int K>
+ static __forceinline void intersectK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
+ {
+ }
+
+ template<int K>
+ static __forceinline vbool<K> occludedK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
+ {
+ return valid;
+ }
+ };
+
+ template<int K, typename Intersector>
+ struct ArrayIntersectorK_1
+ {
+ typedef typename Intersector::Primitive Primitive;
+ typedef typename Intersector::Precalculations Precalculations;
+
+ template<bool robust>
+ static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ for (size_t i=0; i<num; i++) {
+ Intersector::intersect(valid,pre,ray,context,prim[i]);
+ }
+ }
+
+ template<bool robust>
+ static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ vbool<K> valid0 = valid;
+ for (size_t i=0; i<num; i++) {
+ valid0 &= !Intersector::occluded(valid0,pre,ray,context,prim[i]);
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ for (size_t i=0; i<num; i++) {
+ Intersector::intersect(pre,ray,k,context,prim[i]);
+ }
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ for (size_t i=0; i<num; i++) {
+ if (Intersector::occluded(pre,ray,k,context,prim[i]))
+ return true;
+ }
+ return false;
+ }
+ };
+
+ // =============================================================================================
+
+ template<int K, typename IntersectorK>
+ struct ArrayIntersectorKStream
+ {
+ typedef typename IntersectorK::Primitive PrimitiveK;
+ typedef typename IntersectorK::Precalculations PrecalculationsK;
+
+ static __forceinline void intersectK(const vbool<K>& valid, const Accel::Intersectors* This, /* PrecalculationsK& pre, */ RayHitK<K>& ray, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
+ {
+ PrecalculationsK pre(valid,ray); // FIXME: might cause trouble
+
+ for (size_t i=0; i<num; i++) {
+ IntersectorK::intersect(valid,pre,ray,context,prim[i]);
+ }
+ }
+
+ static __forceinline vbool<K> occludedK(const vbool<K>& valid, const Accel::Intersectors* This, /* PrecalculationsK& pre, */ RayK<K>& ray, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
+ {
+ PrecalculationsK pre(valid,ray); // FIXME: might cause trouble
+ vbool<K> valid0 = valid;
+ for (size_t i=0; i<num; i++) {
+ valid0 &= !IntersectorK::occluded(valid0,pre,ray,context,prim[i]);
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ static __forceinline void intersect(const Accel::Intersectors* This, RayHitK<K>& ray, size_t k, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
+ {
+ PrecalculationsK pre(ray.tnear() <= ray.tfar,ray); // FIXME: might cause trouble
+ for (size_t i=0; i<num; i++) {
+ IntersectorK::intersect(pre,ray,k,context,prim[i]);
+ }
+ }
+
+ static __forceinline bool occluded(const Accel::Intersectors* This, RayK<K>& ray, size_t k, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
+ {
+ PrecalculationsK pre(ray.tnear() <= ray.tfar,ray); // FIXME: might cause trouble
+ for (size_t i=0; i<num; i++) {
+ if (IntersectorK::occluded(pre,ray,k,context,prim[i]))
+ return true;
+ }
+ return false;
+ }
+
+ static __forceinline size_t occluded(const Accel::Intersectors* This, size_t cur_mask, RayK<K>** __restrict__ inputPackets, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
+ {
+ size_t m_occluded = 0;
+ for (size_t i=0; i<num; i++) {
+ size_t bits = cur_mask & (~m_occluded);
+ for (; bits!=0; )
+ {
+ const size_t rayID = bscf(bits);
+ RayHitK<K> &ray = *inputPackets[rayID / K];
+ const size_t k = rayID % K;
+ PrecalculationsK pre(ray.tnear() <= ray.tfar,ray); // FIXME: might cause trouble
+ if (IntersectorK::occluded(pre,ray,k,context,prim[i]))
+ {
+ m_occluded |= (size_t)1 << rayID;
+ ray.tfar[k] = neg_inf;
+ }
+ }
+ }
+ return m_occluded;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/line_intersector.h b/thirdparty/embree/kernels/geometry/line_intersector.h
new file mode 100644
index 0000000000..41096d8794
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/line_intersector.h
@@ -0,0 +1,145 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "curve_intersector_precalculations.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct LineIntersectorHitM
+ {
+ __forceinline LineIntersectorHitM() {}
+
+ __forceinline LineIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
+ : vu(u), vv(v), vt(t), vNg(Ng) {}
+
+ __forceinline void finalize() {}
+
+ __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
+ __forceinline float t (const size_t i) const { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
+
+ __forceinline Vec2vf<M> uv() const { return Vec2vf<M>(vu,vv); }
+ __forceinline vfloat<M> t () const { return vt; }
+ __forceinline Vec3vf<M> Ng() const { return vNg; }
+
+ public:
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+ };
+
+ template<int M>
+ struct FlatLinearCurveIntersector1
+ {
+ typedef CurvePrecalculations1 Precalculations;
+
+ template<typename Ray, typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ Ray& ray,
+ IntersectContext* context,
+ const LineSegments* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
+ const Epilog& epilog)
+ {
+ /* transform end points into ray space */
+ vbool<M> valid = valid_i;
+ vfloat<M> depth_scale = pre.depth_scale;
+ LinearSpace3<Vec3vf<M>> ray_space = pre.ray_space;
+
+ const Vec3vf<M> ray_org ((Vec3fa)ray.org);
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec4vf<M> v1 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v1i);
+
+ Vec4vf<M> p0(xfmVector(ray_space,v0.xyz()-ray_org), v0.w);
+ Vec4vf<M> p1(xfmVector(ray_space,v1.xyz()-ray_org), v1.w);
+
+ /* approximative intersection with cone */
+ const Vec4vf<M> v = p1-p0;
+ const Vec4vf<M> w = -p0;
+ const vfloat<M> d0 = madd(w.x,v.x,w.y*v.y);
+ const vfloat<M> d1 = madd(v.x,v.x,v.y*v.y);
+ const vfloat<M> u = clamp(d0*rcp(d1),vfloat<M>(zero),vfloat<M>(one));
+ const Vec4vf<M> p = madd(u,v,p0);
+ const vfloat<M> t = p.z;
+ const vfloat<M> d2 = madd(p.x,p.x,p.y*p.y);
+ const vfloat<M> r = p.w;
+ const vfloat<M> r2 = r*r;
+ valid &= (d2 <= r2) & (vfloat<M>(ray.tnear()) <= t) & (t <= vfloat<M>(ray.tfar));
+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
+ valid &= t > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale; // ignore self intersections
+ if (unlikely(none(valid))) return false;
+
+ /* ignore denormalized segments */
+ const Vec3vf<M> T = v1.xyz()-v0.xyz();
+ valid &= (T.x != vfloat<M>(zero)) | (T.y != vfloat<M>(zero)) | (T.z != vfloat<M>(zero));
+ if (unlikely(none(valid))) return false;
+
+ /* update hit information */
+ LineIntersectorHitM<M> hit(u,zero,t,T);
+ return epilog(valid,hit);
+ }
+ };
+
+ template<int M, int K>
+ struct FlatLinearCurveIntersectorK
+ {
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const LineSegments* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
+ const Epilog& epilog)
+ {
+ /* transform end points into ray space */
+ vbool<M> valid = valid_i;
+ vfloat<M> depth_scale = pre.depth_scale[k];
+ LinearSpace3<Vec3vf<M>> ray_space = pre.ray_space[k];
+ const Vec3vf<M> ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
+ const Vec3vf<M> ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
+
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec4vf<M> v1 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v1i);
+
+ Vec4vf<M> p0(xfmVector(ray_space,v0.xyz()-ray_org), v0.w);
+ Vec4vf<M> p1(xfmVector(ray_space,v1.xyz()-ray_org), v1.w);
+
+ /* approximative intersection with cone */
+ const Vec4vf<M> v = p1-p0;
+ const Vec4vf<M> w = -p0;
+ const vfloat<M> d0 = madd(w.x,v.x,w.y*v.y);
+ const vfloat<M> d1 = madd(v.x,v.x,v.y*v.y);
+ const vfloat<M> u = clamp(d0*rcp(d1),vfloat<M>(zero),vfloat<M>(one));
+ const Vec4vf<M> p = madd(u,v,p0);
+ const vfloat<M> t = p.z;
+ const vfloat<M> d2 = madd(p.x,p.x,p.y*p.y);
+ const vfloat<M> r = p.w;
+ const vfloat<M> r2 = r*r;
+ valid &= (d2 <= r2) & (vfloat<M>(ray.tnear()[k]) <= t) & (t <= vfloat<M>(ray.tfar[k]));
+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
+ valid &= t > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale; // ignore self intersections
+ if (unlikely(none(valid))) return false;
+
+ /* ignore denormalized segments */
+ const Vec3vf<M> T = v1.xyz()-v0.xyz();
+ valid &= (T.x != vfloat<M>(zero)) | (T.y != vfloat<M>(zero)) | (T.z != vfloat<M>(zero));
+ if (unlikely(none(valid))) return false;
+
+ /* update hit information */
+ LineIntersectorHitM<M> hit(u,zero,t,T);
+ return epilog(valid,hit);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/linei.h b/thirdparty/embree/kernels/geometry/linei.h
new file mode 100644
index 0000000000..3ee70ac012
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/linei.h
@@ -0,0 +1,705 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+
+namespace embree
+{
+ template<int M>
+ struct LineMi
+ {
+ /* Virtual interface to query information about the line segment type */
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* primitive supports multiple time segments */
+ static const bool singleTimeSegment = false;
+
+ /* Returns maximum number of stored line segments */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N line segments */
+ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
+
+ /* Returns required number of bytes for N line segments */
+ static __forceinline size_t bytes(size_t N) { return blocks(N)*sizeof(LineMi); }
+
+ public:
+
+ /* Default constructor */
+ __forceinline LineMi() { }
+
+ /* Construction from vertices and IDs */
+ __forceinline LineMi(const vuint<M>& v0, unsigned short leftExists, unsigned short rightExists, const vuint<M>& geomIDs, const vuint<M>& primIDs, Geometry::GType gtype)
+ : gtype((unsigned char)gtype), m((unsigned char)popcnt(vuint<M>(primIDs) != vuint<M>(-1))), sharedGeomID(geomIDs[0]), leftExists (leftExists), rightExists(rightExists), v0(v0), primIDs(primIDs)
+ {
+ assert(all(vuint<M>(geomID()) == geomIDs));
+ }
+
+ /* Returns a mask that tells which line segments are valid */
+ __forceinline vbool<M> valid() const { return primIDs != vuint<M>(-1); }
+
+ /* Returns if the specified line segment is valid */
+ __forceinline bool valid(const size_t i) const { assert(i<M); return primIDs[i] != -1; }
+
+ /* Returns the number of stored line segments */
+ __forceinline size_t size() const { return bsf(~movemask(valid())); }
+
+ /* Returns the geometry IDs */
+ //template<class T>
+ //static __forceinline T unmask(T &index) { return index & 0x3fffffff; }
+
+ __forceinline unsigned int geomID(unsigned int i = 0) const { return sharedGeomID; }
+ //__forceinline vuint<M> geomID() { return unmask(geomIDs); }
+ //__forceinline const vuint<M> geomID() const { return unmask(geomIDs); }
+ //__forceinline unsigned int geomID(const size_t i) const { assert(i<M); return unmask(geomIDs[i]); }
+
+ /* Returns the primitive IDs */
+ __forceinline vuint<M>& primID() { return primIDs; }
+ __forceinline const vuint<M>& primID() const { return primIDs; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
+
+ /* gather the line segments */
+ __forceinline void gather(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ const LineSegments* geom) const;
+
+ __forceinline void gatheri(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ const LineSegments* geom,
+ const int itime) const;
+
+ __forceinline void gather(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ const LineSegments* geom,
+ float time) const;
+
+ /* gather the line segments with lateral info */
+ __forceinline void gather(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ Vec4vf<M>& pL,
+ Vec4vf<M>& pR,
+ const LineSegments* geom) const;
+
+ __forceinline void gatheri(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ Vec4vf<M>& pL,
+ Vec4vf<M>& pR,
+ const LineSegments* geom,
+ const int itime) const;
+
+ __forceinline void gather(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ Vec4vf<M>& pL,
+ Vec4vf<M>& pR,
+ const LineSegments* geom,
+ float time) const;
+
+ __forceinline void gather(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ vbool<M>& cL,
+ vbool<M>& cR,
+ const LineSegments* geom) const;
+
+ __forceinline void gatheri(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ vbool<M>& cL,
+ vbool<M>& cR,
+ const LineSegments* geom,
+ const int itime) const;
+
+ __forceinline void gather(Vec4vf<M>& p0,
+ Vec4vf<M>& p1,
+ vbool<M>& cL,
+ vbool<M>& cR,
+ const LineSegments* geom,
+ float time) const;
+
+ /* Calculate the bounds of the line segments */
+ __forceinline const BBox3fa bounds(const Scene* scene, size_t itime = 0) const
+ {
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<M && valid(i); i++)
+ {
+ const LineSegments* geom = scene->get<LineSegments>(geomID(i));
+ const Vec3ff& p0 = geom->vertex(v0[i]+0,itime);
+ const Vec3ff& p1 = geom->vertex(v0[i]+1,itime);
+ BBox3fa b = merge(BBox3fa(p0),BBox3fa(p1));
+ b = enlarge(b,Vec3fa(max(p0.w,p1.w)));
+ bounds.extend(b);
+ }
+ return bounds;
+ }
+
+ /* Calculate the linear bounds of the primitive */
+ __forceinline LBBox3fa linearBounds(const Scene* scene, size_t itime) {
+ return LBBox3fa(bounds(scene,itime+0), bounds(scene,itime+1));
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps) {
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<M && valid(i); i++)
+ {
+ const LineSegments* geom = scene->get<LineSegments>(geomID(i));
+ allBounds.extend(geom->linearBounds(primID(i), itime, numTimeSteps));
+ }
+ return allBounds;
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range)
+ {
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<M && valid(i); i++)
+ {
+ const LineSegments* geom = scene->get<LineSegments>(geomID((unsigned int)i));
+ allBounds.extend(geom->linearBounds(primID(i), time_range));
+ }
+ return allBounds;
+ }
+
+ /* Fill line segment from line segment list */
+ template<typename PrimRefT>
+ __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene)
+ {
+ Geometry::GType gty = scene->get(prims[begin].geomID())->getType();
+ vuint<M> geomID, primID;
+ vuint<M> v0;
+ unsigned short leftExists = 0;
+ unsigned short rightExists = 0;
+ const PrimRefT* prim = &prims[begin];
+
+ for (size_t i=0; i<M; i++)
+ {
+ const LineSegments* geom = scene->get<LineSegments>(prim->geomID());
+ if (begin<end) {
+ geomID[i] = prim->geomID();
+ primID[i] = prim->primID();
+ v0[i] = geom->segment(prim->primID());
+ leftExists |= geom->segmentLeftExists(primID[i]) << i;
+ rightExists |= geom->segmentRightExists(primID[i]) << i;
+ begin++;
+ } else {
+ assert(i);
+ if (i>0) {
+ geomID[i] = geomID[i-1];
+ primID[i] = -1;
+ v0[i] = v0[i-1];
+ }
+ }
+ if (begin<end) prim = &prims[begin]; // FIXME: remove this line
+ }
+ new (this) LineMi(v0,leftExists,rightExists,geomID,primID,gty); // FIXME: use non temporal store
+ }
+
+ template<typename BVH, typename Allocator>
+ __forceinline static typename BVH::NodeRef createLeaf (BVH* bvh, const PrimRef* prims, const range<size_t>& set, const Allocator& alloc)
+ {
+ size_t start = set.begin();
+ size_t items = LineMi::blocks(set.size());
+ size_t numbytes = LineMi::bytes(set.size());
+ LineMi* accel = (LineMi*) alloc.malloc1(numbytes,M*sizeof(float));
+ for (size_t i=0; i<items; i++) {
+ accel[i].fill(prims,start,set.end(),bvh->scene);
+ }
+ return bvh->encodeLeaf((char*)accel,items);
+ };
+
+ __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
+ {
+ fill(prims,begin,end,scene);
+ return linearBounds(scene,itime);
+ }
+
+ __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
+ {
+ fill(prims,begin,end,scene);
+ return linearBounds(scene,time_range);
+ }
+
+ template<typename BVH, typename SetMB, typename Allocator>
+ __forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc)
+ {
+ size_t start = prims.begin();
+ size_t end = prims.end();
+ size_t items = LineMi::blocks(prims.size());
+ size_t numbytes = LineMi::bytes(prims.size());
+ LineMi* accel = (LineMi*) alloc.malloc1(numbytes,M*sizeof(float));
+ const typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,items);
+
+ LBBox3fa bounds = empty;
+ for (size_t i=0; i<items; i++)
+ bounds.extend(accel[i].fillMB(prims.prims->data(),start,end,bvh->scene,prims.time_range));
+
+ return typename BVH::NodeRecordMB4D(node,bounds,prims.time_range);
+ };
+
+ /* Updates the primitive */
+ __forceinline BBox3fa update(LineSegments* geom)
+ {
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<M && valid(i); i++)
+ {
+ const Vec3ff& p0 = geom->vertex(v0[i]+0);
+ const Vec3ff& p1 = geom->vertex(v0[i]+1);
+ BBox3fa b = merge(BBox3fa(p0),BBox3fa(p1));
+ b = enlarge(b,Vec3fa(max(p0.w,p1.w)));
+ bounds.extend(b);
+ }
+ return bounds;
+ }
+
+ /*! output operator */
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const LineMi& line) {
+ return cout << "Line" << M << "i {" << line.v0 << ", " << line.geomID() << ", " << line.primID() << "}";
+ }
+
+ public:
+ unsigned char gtype;
+ unsigned char m;
+ unsigned int sharedGeomID;
+ unsigned short leftExists, rightExists;
+ vuint<M> v0; // index of start vertex
+ private:
+ vuint<M> primIDs; // primitive ID
+ };
+
+ template<>
+ __forceinline void LineMi<4>::gather(Vec4vf4& p0,
+ Vec4vf4& p1,
+ const LineSegments* geom) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0]));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1]));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2]));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3]));
+ transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
+
+ const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1));
+ const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1));
+ const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1));
+ const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1));
+ transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
+ }
+
+ template<>
+ __forceinline void LineMi<4>::gatheri(Vec4vf4& p0,
+ Vec4vf4& p1,
+ const LineSegments* geom,
+ const int itime) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
+ transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
+
+ const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
+ const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
+ const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
+ const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
+ transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
+ }
+
+ template<>
+ __forceinline void LineMi<4>::gather(Vec4vf4& p0,
+ Vec4vf4& p1,
+ const LineSegments* geom,
+ float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf4 a0,a1;
+ gatheri(a0,a1,geom,itime);
+ Vec4vf4 b0,b1;
+ gatheri(b0,b1,geom,itime+1);
+ p0 = lerp(a0,b0,vfloat4(ftime));
+ p1 = lerp(a1,b1,vfloat4(ftime));
+ }
+
+ template<>
+ __forceinline void LineMi<4>::gather(Vec4vf4& p0,
+ Vec4vf4& p1,
+ vbool4& cL,
+ vbool4& cR,
+ const LineSegments* geom) const
+ {
+ gather(p0,p1,geom);
+ cL = !vbool4(leftExists);
+ cR = !vbool4(rightExists);
+ }
+
+ template<>
+ __forceinline void LineMi<4>::gatheri(Vec4vf4& p0,
+ Vec4vf4& p1,
+ vbool4& cL,
+ vbool4& cR,
+ const LineSegments* geom,
+ const int itime) const
+ {
+ gatheri(p0,p1,geom,itime);
+ cL = !vbool4(leftExists);
+ cR = !vbool4(rightExists);
+ }
+
+ template<>
+ __forceinline void LineMi<4>::gather(Vec4vf4& p0,
+ Vec4vf4& p1,
+ vbool4& cL,
+ vbool4& cR,
+ const LineSegments* geom,
+ float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf4 a0,a1;
+ gatheri(a0,a1,geom,itime);
+ Vec4vf4 b0,b1;
+ gatheri(b0,b1,geom,itime+1);
+ p0 = lerp(a0,b0,vfloat4(ftime));
+ p1 = lerp(a1,b1,vfloat4(ftime));
+ cL = !vbool4(leftExists);
+ cR = !vbool4(rightExists);
+ }
+
+ template<>
+ __forceinline void LineMi<4>::gather(Vec4vf4& p0,
+ Vec4vf4& p1,
+ Vec4vf4& pL,
+ Vec4vf4& pR,
+ const LineSegments* geom) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0]));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1]));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2]));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3]));
+ transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
+
+ const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1));
+ const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1));
+ const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1));
+ const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1));
+ transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
+
+ const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1)) : vfloat4(inf);
+ const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1)) : vfloat4(inf);
+ const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1)) : vfloat4(inf);
+ const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1)) : vfloat4(inf);
+ transpose(l0,l1,l2,l3,pL.x,pL.y,pL.z,pL.w);
+
+ const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2)) : vfloat4(inf);
+ const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2)) : vfloat4(inf);
+ const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2)) : vfloat4(inf);
+ const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2)) : vfloat4(inf);
+ transpose(r0,r1,r2,r3,pR.x,pR.y,pR.z,pR.w);
+ }
+
+ template<>
+ __forceinline void LineMi<4>::gatheri(Vec4vf4& p0,
+ Vec4vf4& p1,
+ Vec4vf4& pL,
+ Vec4vf4& pR,
+ const LineSegments* geom,
+ const int itime) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
+ transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z,p0.w);
+
+ const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
+ const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
+ const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
+ const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
+ transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w);
+
+ const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1,itime)) : vfloat4(inf);
+ const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1,itime)) : vfloat4(inf);
+ const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1,itime)) : vfloat4(inf);
+ const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1,itime)) : vfloat4(inf);
+ transpose(l0,l1,l2,l3,pL.x,pL.y,pL.z,pL.w);
+
+ const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2,itime)) : vfloat4(inf);
+ const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2,itime)) : vfloat4(inf);
+ const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2,itime)) : vfloat4(inf);
+ const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2,itime)) : vfloat4(inf);
+ transpose(r0,r1,r2,r3,pR.x,pR.y,pR.z,pR.w);
+ }
+
+ template<>
+ __forceinline void LineMi<4>::gather(Vec4vf4& p0,
+ Vec4vf4& p1,
+ Vec4vf4& pL,
+ Vec4vf4& pR,
+ const LineSegments* geom,
+ float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf4 a0,a1,aL,aR;
+ gatheri(a0,a1,aL,aR,geom,itime);
+ Vec4vf4 b0,b1,bL,bR;
+ gatheri(b0,b1,bL,bR,geom,itime+1);
+ p0 = lerp(a0,b0,vfloat4(ftime));
+ p1 = lerp(a1,b1,vfloat4(ftime));
+ pL = lerp(aL,bL,vfloat4(ftime));
+ pR = lerp(aR,bR,vfloat4(ftime));
+ }
+
+#if defined(__AVX__)
+
+ template<>
+ __forceinline void LineMi<8>::gather(Vec4vf8& p0,
+ Vec4vf8& p1,
+ const LineSegments* geom) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0]));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1]));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2]));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3]));
+ const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4]));
+ const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5]));
+ const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6]));
+ const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7]));
+ transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
+
+ const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1));
+ const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1));
+ const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1));
+ const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1));
+ const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1));
+ const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1));
+ const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1));
+ const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1));
+ transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
+ }
+
+ template<>
+ __forceinline void LineMi<8>::gatheri(Vec4vf8& p0,
+ Vec4vf8& p1,
+ const LineSegments* geom,
+ const int itime) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
+ const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4],itime));
+ const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5],itime));
+ const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6],itime));
+ const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7],itime));
+ transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
+
+ const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
+ const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
+ const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
+ const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
+ const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1,itime));
+ const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1,itime));
+ const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1,itime));
+ const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1,itime));
+ transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
+ }
+
+ template<>
+ __forceinline void LineMi<8>::gather(Vec4vf8& p0,
+ Vec4vf8& p1,
+ const LineSegments* geom,
+ float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf8 a0,a1;
+ gatheri(a0,a1,geom,itime);
+ Vec4vf8 b0,b1;
+ gatheri(b0,b1,geom,itime+1);
+ p0 = lerp(a0,b0,vfloat8(ftime));
+ p1 = lerp(a1,b1,vfloat8(ftime));
+ }
+
+ template<>
+ __forceinline void LineMi<8>::gather(Vec4vf8& p0,
+ Vec4vf8& p1,
+ Vec4vf8& pL,
+ Vec4vf8& pR,
+ const LineSegments* geom) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0]));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1]));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2]));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3]));
+ const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4]));
+ const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5]));
+ const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6]));
+ const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7]));
+ transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
+
+ const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1));
+ const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1));
+ const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1));
+ const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1));
+ const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1));
+ const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1));
+ const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1));
+ const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1));
+ transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
+
+ const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1)) : vfloat4(inf);
+ const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1)) : vfloat4(inf);
+ const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1)) : vfloat4(inf);
+ const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1)) : vfloat4(inf);
+ const vfloat4 l4 = (leftExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]-1)) : vfloat4(inf);
+ const vfloat4 l5 = (leftExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]-1)) : vfloat4(inf);
+ const vfloat4 l6 = (leftExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]-1)) : vfloat4(inf);
+ const vfloat4 l7 = (leftExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]-1)) : vfloat4(inf);
+ transpose(l0,l1,l2,l3,l4,l5,l6,l7,pL.x,pL.y,pL.z,pL.w);
+
+ const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2)) : vfloat4(inf);
+ const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2)) : vfloat4(inf);
+ const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2)) : vfloat4(inf);
+ const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2)) : vfloat4(inf);
+ const vfloat4 r4 = (rightExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]+2)) : vfloat4(inf);
+ const vfloat4 r5 = (rightExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]+2)) : vfloat4(inf);
+ const vfloat4 r6 = (rightExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]+2)) : vfloat4(inf);
+ const vfloat4 r7 = (rightExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]+2)) : vfloat4(inf);
+ transpose(r0,r1,r2,r3,r4,r5,r6,r7,pR.x,pR.y,pR.z,pR.w);
+ }
+
+ template<>
+ __forceinline void LineMi<8>::gatheri(Vec4vf8& p0,
+ Vec4vf8& p1,
+ Vec4vf8& pL,
+ Vec4vf8& pR,
+ const LineSegments* geom,
+ const int itime) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(v0[0],itime));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(v0[1],itime));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(v0[2],itime));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(v0[3],itime));
+ const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(v0[4],itime));
+ const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(v0[5],itime));
+ const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(v0[6],itime));
+ const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(v0[7],itime));
+ transpose(a0,a1,a2,a3,a4,a5,a6,a7,p0.x,p0.y,p0.z,p0.w);
+
+ const vfloat4 b0 = vfloat4::loadu(geom->vertexPtr(v0[0]+1,itime));
+ const vfloat4 b1 = vfloat4::loadu(geom->vertexPtr(v0[1]+1,itime));
+ const vfloat4 b2 = vfloat4::loadu(geom->vertexPtr(v0[2]+1,itime));
+ const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime));
+ const vfloat4 b4 = vfloat4::loadu(geom->vertexPtr(v0[4]+1,itime));
+ const vfloat4 b5 = vfloat4::loadu(geom->vertexPtr(v0[5]+1,itime));
+ const vfloat4 b6 = vfloat4::loadu(geom->vertexPtr(v0[6]+1,itime));
+ const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1,itime));
+ transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w);
+
+ const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1,itime)) : vfloat4(inf);
+ const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1,itime)) : vfloat4(inf);
+ const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1,itime)) : vfloat4(inf);
+ const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1,itime)) : vfloat4(inf);
+ const vfloat4 l4 = (leftExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]-1,itime)) : vfloat4(inf);
+ const vfloat4 l5 = (leftExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]-1,itime)) : vfloat4(inf);
+ const vfloat4 l6 = (leftExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]-1,itime)) : vfloat4(inf);
+ const vfloat4 l7 = (leftExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]-1,itime)) : vfloat4(inf);
+ transpose(l0,l1,l2,l3,l4,l5,l6,l7,pL.x,pL.y,pL.z,pL.w);
+
+ const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2,itime)) : vfloat4(inf);
+ const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2,itime)) : vfloat4(inf);
+ const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2,itime)) : vfloat4(inf);
+ const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2,itime)) : vfloat4(inf);
+ const vfloat4 r4 = (rightExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]+2,itime)) : vfloat4(inf);
+ const vfloat4 r5 = (rightExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]+2,itime)) : vfloat4(inf);
+ const vfloat4 r6 = (rightExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]+2,itime)) : vfloat4(inf);
+ const vfloat4 r7 = (rightExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]+2,itime)) : vfloat4(inf);
+ transpose(r0,r1,r2,r3,r4,r5,r6,r7,pR.x,pR.y,pR.z,pR.w);
+ }
+
+ template<>
+ __forceinline void LineMi<8>::gather(Vec4vf8& p0,
+ Vec4vf8& p1,
+ Vec4vf8& pL,
+ Vec4vf8& pR,
+ const LineSegments* geom,
+ float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf8 a0,a1,aL,aR;
+ gatheri(a0,a1,aL,aR,geom,itime);
+ Vec4vf8 b0,b1,bL,bR;
+ gatheri(b0,b1,bL,bR,geom,itime+1);
+ p0 = lerp(a0,b0,vfloat8(ftime));
+ p1 = lerp(a1,b1,vfloat8(ftime));
+ pL = lerp(aL,bL,vfloat8(ftime));
+ pR = lerp(aR,bR,vfloat8(ftime));
+ }
+
+ template<>
+ __forceinline void LineMi<8>::gather(Vec4vf8& p0,
+ Vec4vf8& p1,
+ vbool8& cL,
+ vbool8& cR,
+ const LineSegments* geom) const
+ {
+ gather(p0,p1,geom);
+ cL = !vbool8(leftExists);
+ cR = !vbool8(rightExists);
+ }
+
+ template<>
+ __forceinline void LineMi<8>::gatheri(Vec4vf8& p0,
+ Vec4vf8& p1,
+ vbool8& cL,
+ vbool8& cR,
+ const LineSegments* geom,
+ const int itime) const
+ {
+ gatheri(p0,p1,geom,itime);
+ cL = !vbool8(leftExists);
+ cR = !vbool8(rightExists);
+ }
+
+ template<>
+ __forceinline void LineMi<8>::gather(Vec4vf8& p0,
+ Vec4vf8& p1,
+ vbool8& cL,
+ vbool8& cR,
+ const LineSegments* geom,
+ float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf8 a0,a1;
+ gatheri(a0,a1,geom,itime);
+ Vec4vf8 b0,b1;
+ gatheri(b0,b1,geom,itime+1);
+ p0 = lerp(a0,b0,vfloat8(ftime));
+ p1 = lerp(a1,b1,vfloat8(ftime));
+ cL = !vbool8(leftExists);
+ cR = !vbool8(rightExists);
+ }
+
+#endif
+
+ template<int M>
+ typename LineMi<M>::Type LineMi<M>::type;
+
+ typedef LineMi<4> Line4i;
+ typedef LineMi<8> Line8i;
+}
diff --git a/thirdparty/embree/kernels/geometry/linei_intersector.h b/thirdparty/embree/kernels/geometry/linei_intersector.h
new file mode 100644
index 0000000000..5992827f5b
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/linei_intersector.h
@@ -0,0 +1,124 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "linei.h"
+#include "line_intersector.h"
+#include "intersector_epilog.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M, bool filter>
+ struct FlatLinearCurveMiIntersector1
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1; line.gather(v0,v1,geom);
+ const vbool<M> valid = line.valid();
+ FlatLinearCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,Intersect1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1; line.gather(v0,v1,geom);
+ const vbool<M> valid = line.valid();
+ return FlatLinearCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,Occluded1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
+ }
+ };
+
+ template<int M, bool filter>
+ struct FlatLinearCurveMiMBIntersector1
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1; line.gather(v0,v1,geom,ray.time());
+ const vbool<M> valid = line.valid();
+ FlatLinearCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,Intersect1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1; line.gather(v0,v1,geom,ray.time());
+ const vbool<M> valid = line.valid();
+ return FlatLinearCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,Occluded1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct FlatLinearCurveMiIntersectorK
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1; line.gather(v0,v1,geom);
+ const vbool<M> valid = line.valid();
+ FlatLinearCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,Intersect1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1; line.gather(v0,v1,geom);
+ const vbool<M> valid = line.valid();
+ return FlatLinearCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,Occluded1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct FlatLinearCurveMiMBIntersectorK
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1; line.gather(v0,v1,geom,ray.time()[k]);
+ const vbool<M> valid = line.valid();
+ FlatLinearCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,Intersect1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1; line.gather(v0,v1,geom,ray.time()[k]);
+ const vbool<M> valid = line.valid();
+ return FlatLinearCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,Occluded1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/object.h b/thirdparty/embree/kernels/geometry/object.h
new file mode 100644
index 0000000000..2a61829ffd
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/object.h
@@ -0,0 +1,84 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+
+namespace embree
+{
+ struct Object
+ {
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* primitive supports multiple time segments */
+ static const bool singleTimeSegment = false;
+
+ /* Returns maximum number of stored primitives */
+ static __forceinline size_t max_size() { return 1; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return N; }
+
+ public:
+
+ /*! constructs a virtual object */
+ Object (unsigned geomID, unsigned primID)
+ : _geomID(geomID), _primID(primID) {}
+
+ __forceinline unsigned geomID() const {
+ return _geomID;
+ }
+
+ __forceinline unsigned primID() const {
+ return _primID;
+ }
+
+ /*! fill triangle from triangle list */
+ __forceinline void fill(const PrimRef* prims, size_t& i, size_t end, Scene* scene)
+ {
+ const PrimRef& prim = prims[i]; i++;
+ new (this) Object(prim.geomID(), prim.primID());
+ }
+
+ /*! fill triangle from triangle list */
+ __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& i, size_t end, Scene* scene, size_t itime)
+ {
+ const PrimRef& prim = prims[i]; i++;
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ new (this) Object(geomID, primID);
+ AccelSet* accel = (AccelSet*) scene->get(geomID);
+ return accel->linearBounds(primID,itime);
+ }
+
+ /*! fill triangle from triangle list */
+ __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& i, size_t end, Scene* scene, const BBox1f time_range)
+ {
+ const PrimRefMB& prim = prims[i]; i++;
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ new (this) Object(geomID, primID);
+ AccelSet* accel = (AccelSet*) scene->get(geomID);
+ return accel->linearBounds(primID,time_range);
+ }
+
+ /* Updates the primitive */
+ __forceinline BBox3fa update(AccelSet* mesh) {
+ return mesh->bounds(primID());
+ }
+
+ private:
+ unsigned int _geomID; //!< geometry ID
+ unsigned int _primID; //!< primitive ID
+ };
+}
diff --git a/thirdparty/embree/kernels/geometry/object_intersector.h b/thirdparty/embree/kernels/geometry/object_intersector.h
new file mode 100644
index 0000000000..11ceb2f7fe
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/object_intersector.h
@@ -0,0 +1,127 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "object.h"
+#include "../common/ray.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<bool mblur>
+ struct ObjectIntersector1
+ {
+ typedef Object Primitive;
+
+ static const bool validIntersectorK = false;
+
+ struct Precalculations {
+ __forceinline Precalculations() {}
+ __forceinline Precalculations (const Ray& ray, const void *ptr) {}
+ };
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim)
+ {
+ AccelSet* accel = (AccelSet*) context->scene->get(prim.geomID());
+
+ /* perform ray mask test */
+#if defined(EMBREE_RAY_MASK)
+ if ((ray.mask & accel->mask) == 0)
+ return;
+#endif
+
+ accel->intersect(ray,prim.geomID(),prim.primID(),context,reportIntersection1);
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim)
+ {
+ AccelSet* accel = (AccelSet*) context->scene->get(prim.geomID());
+ /* perform ray mask test */
+#if defined(EMBREE_RAY_MASK)
+ if ((ray.mask & accel->mask) == 0)
+ return false;
+#endif
+
+ accel->occluded(ray,prim.geomID(),prim.primID(),context,&reportOcclusion1);
+ return ray.tfar < 0.0f;
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& prim)
+ {
+ AccelSet* accel = (AccelSet*)context->scene->get(prim.geomID());
+ context->geomID = prim.geomID();
+ context->primID = prim.primID();
+ return accel->pointQuery(query, context);
+ }
+
+ template<int K>
+ static __forceinline void intersectK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
+ {
+ assert(false);
+ }
+
+ template<int K>
+ static __forceinline vbool<K> occludedK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
+ {
+ assert(false);
+ return valid;
+ }
+ };
+
+ template<int K, bool mblur>
+ struct ObjectIntersectorK
+ {
+ typedef Object Primitive;
+
+ struct Precalculations {
+ __forceinline Precalculations (const vbool<K>& valid, const RayK<K>& ray) {}
+ };
+
+ static __forceinline void intersect(const vbool<K>& valid_i, const Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vbool<K> valid = valid_i;
+ AccelSet* accel = (AccelSet*) context->scene->get(prim.geomID());
+
+ /* perform ray mask test */
+#if defined(EMBREE_RAY_MASK)
+ valid &= (ray.mask & accel->mask) != 0;
+ if (none(valid)) return;
+#endif
+ accel->intersect(valid,ray,prim.geomID(),prim.primID(),context,&reportIntersection1);
+ }
+
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& prim)
+ {
+ vbool<K> valid = valid_i;
+ AccelSet* accel = (AccelSet*) context->scene->get(prim.geomID());
+
+ /* perform ray mask test */
+#if defined(EMBREE_RAY_MASK)
+ valid &= (ray.mask & accel->mask) != 0;
+ if (none(valid)) return false;
+#endif
+ accel->occluded(valid,ray,prim.geomID(),prim.primID(),context,&reportOcclusion1);
+ return ray.tfar < 0.0f;
+ }
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
+ intersect(vbool<K>(1<<int(k)),pre,ray,context,prim);
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& prim) {
+ occluded(vbool<K>(1<<int(k)),pre,ray,context,prim);
+ return ray.tfar[k] < 0.0f;
+ }
+ };
+
+ typedef ObjectIntersectorK<4,false> ObjectIntersector4;
+ typedef ObjectIntersectorK<8,false> ObjectIntersector8;
+ typedef ObjectIntersectorK<16,false> ObjectIntersector16;
+
+ typedef ObjectIntersectorK<4,true> ObjectIntersector4MB;
+ typedef ObjectIntersectorK<8,true> ObjectIntersector8MB;
+ typedef ObjectIntersectorK<16,true> ObjectIntersector16MB;
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/plane.h b/thirdparty/embree/kernels/geometry/plane.h
new file mode 100644
index 0000000000..e447122eab
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/plane.h
@@ -0,0 +1,57 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct HalfPlane
+ {
+ const Vec3fa P; //!< plane origin
+ const Vec3fa N; //!< plane normal
+
+ __forceinline HalfPlane(const Vec3fa& P, const Vec3fa& N)
+ : P(P), N(N) {}
+
+ __forceinline BBox1f intersect(const Vec3fa& ray_org, const Vec3fa& ray_dir) const
+ {
+ Vec3fa O = Vec3fa(ray_org) - P;
+ Vec3fa D = Vec3fa(ray_dir);
+ float ON = dot(O,N);
+ float DN = dot(D,N);
+ bool eps = abs(DN) < min_rcp_input;
+ float t = -ON*rcp(DN);
+ float lower = select(eps || DN < 0.0f, float(neg_inf), t);
+ float upper = select(eps || DN > 0.0f, float(pos_inf), t);
+ return BBox1f(lower,upper);
+ }
+ };
+
+ template<int M>
+ struct HalfPlaneN
+ {
+ const Vec3vf<M> P; //!< plane origin
+ const Vec3vf<M> N; //!< plane normal
+
+ __forceinline HalfPlaneN(const Vec3vf<M>& P, const Vec3vf<M>& N)
+ : P(P), N(N) {}
+
+ __forceinline BBox<vfloat<M>> intersect(const Vec3fa& ray_org, const Vec3fa& ray_dir) const
+ {
+ Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray_org) - P;
+ Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray_dir);
+ vfloat<M> ON = dot(O,N);
+ vfloat<M> DN = dot(D,N);
+ vbool<M> eps = abs(DN) < min_rcp_input;
+ vfloat<M> t = -ON*rcp(DN);
+ vfloat<M> lower = select(eps | DN < 0.0f, vfloat<M>(neg_inf), t);
+ vfloat<M> upper = select(eps | DN > 0.0f, vfloat<M>(pos_inf), t);
+ return BBox<vfloat<M>>(lower,upper);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/pointi.h b/thirdparty/embree/kernels/geometry/pointi.h
new file mode 100644
index 0000000000..bed04116b0
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/pointi.h
@@ -0,0 +1,412 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+
+namespace embree
+{
+ template<int M>
+ struct PointMi
+ {
+ /* Virtual interface to query information about the line segment type */
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+ /* primitive supports multiple time segments */
+ static const bool singleTimeSegment = false;
+
+ /* Returns maximum number of stored line segments */
+ static __forceinline size_t max_size()
+ {
+ return M;
+ }
+
+ /* Returns required number of primitive blocks for N line segments */
+ static __forceinline size_t blocks(size_t N)
+ {
+ return (N + max_size() - 1) / max_size();
+ }
+
+ /* Returns required number of bytes for N line segments */
+ static __forceinline size_t bytes(size_t N)
+ {
+ return blocks(N) * sizeof(PointMi);
+ }
+
+ public:
+ /* Default constructor */
+ __forceinline PointMi() {}
+
+ /* Construction from vertices and IDs */
+ __forceinline PointMi(const vuint<M>& geomIDs, const vuint<M>& primIDs, Geometry::GType gtype, uint32_t numPrimitives)
+ : gtype((unsigned char)gtype),
+ numPrimitives(numPrimitives),
+ sharedGeomID(geomIDs[0]),
+ primIDs(primIDs)
+ {
+ assert(all(vuint<M>(geomID()) == geomIDs));
+ }
+
+ /* Returns a mask that tells which line segments are valid */
+ __forceinline vbool<M> valid() const {
+ return vint<M>(step) < vint<M>(numPrimitives);
+ }
+
+ /* Returns if the specified line segment is valid */
+ __forceinline bool valid(const size_t i) const
+ {
+ assert(i < M);
+ return i < numPrimitives;
+ }
+
+ /* Returns the number of stored line segments */
+ __forceinline size_t size() const {
+ return numPrimitives;
+ }
+
+ __forceinline unsigned int geomID(unsigned int i = 0) const {
+ return sharedGeomID;
+ }
+
+ __forceinline vuint<M>& primID() {
+ return primIDs;
+ }
+ __forceinline const vuint<M>& primID() const {
+ return primIDs;
+ }
+ __forceinline unsigned int primID(const size_t i) const {
+ assert(i < M);
+ return primIDs[i];
+ }
+
+ /* gather the line segments */
+ __forceinline void gather(Vec4vf<M>& p0, const Points* geom) const;
+ __forceinline void gather(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom) const;
+
+ __forceinline void gatheri(Vec4vf<M>& p0, const Points* geom, const int itime) const;
+ __forceinline void gatheri(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom, const int itime) const;
+
+ __forceinline void gather(Vec4vf<M>& p0, const Points* geom, float time) const;
+ __forceinline void gather(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom, float time) const;
+
+ /* Calculate the bounds of the line segments */
+ __forceinline const BBox3fa bounds(const Scene* scene, size_t itime = 0) const
+ {
+ BBox3fa bounds = empty;
+ for (size_t i = 0; i < M && valid(i); i++) {
+ const Points* geom = scene->get<Points>(geomID(i));
+ bounds.extend(geom->bounds(primID(i),itime));
+ }
+ return bounds;
+ }
+
+ /* Calculate the linear bounds of the primitive */
+ __forceinline LBBox3fa linearBounds(const Scene* scene, size_t itime) {
+ return LBBox3fa(bounds(scene, itime + 0), bounds(scene, itime + 1));
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene* const scene, size_t itime, size_t numTimeSteps)
+ {
+ LBBox3fa allBounds = empty;
+ for (size_t i = 0; i < M && valid(i); i++) {
+ const Points* geom = scene->get<Points>(geomID(i));
+ allBounds.extend(geom->linearBounds(primID(i), itime, numTimeSteps));
+ }
+ return allBounds;
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene* const scene, const BBox1f time_range)
+ {
+ LBBox3fa allBounds = empty;
+ for (size_t i = 0; i < M && valid(i); i++) {
+ const Points* geom = scene->get<Points>(geomID((unsigned int)i));
+ allBounds.extend(geom->linearBounds(primID(i), time_range));
+ }
+ return allBounds;
+ }
+
+ /* Fill line segment from line segment list */
+ template<typename PrimRefT>
+ __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene)
+ {
+ Geometry::GType gty = scene->get(prims[begin].geomID())->getType();
+ vuint<M> geomID, primID;
+ vuint<M> v0;
+ const PrimRefT* prim = &prims[begin];
+
+ int numPrimitives = 0;
+ for (size_t i = 0; i < M; i++) {
+ if (begin < end) {
+ geomID[i] = prim->geomID();
+ primID[i] = prim->primID();
+ begin++;
+ numPrimitives++;
+ } else {
+ assert(i);
+ if (i > 0) {
+ geomID[i] = geomID[i - 1];
+ primID[i] = primID[i - 1];
+ }
+ }
+ if (begin < end)
+ prim = &prims[begin]; // FIXME: remove this line
+ }
+ new (this) PointMi(geomID, primID, gty, numPrimitives); // FIXME: use non temporal store
+ }
+
+ template<typename BVH, typename Allocator>
+ __forceinline static typename BVH::NodeRef createLeaf(BVH* bvh,
+ const PrimRef* prims,
+ const range<size_t>& set,
+ const Allocator& alloc)
+ {
+ size_t start = set.begin();
+ size_t items = PointMi::blocks(set.size());
+ size_t numbytes = PointMi::bytes(set.size());
+ PointMi* accel = (PointMi*)alloc.malloc1(numbytes, M * sizeof(float));
+ for (size_t i = 0; i < items; i++) {
+ accel[i].fill(prims, start, set.end(), bvh->scene);
+ }
+ return bvh->encodeLeaf((char*)accel, items);
+ };
+
+ __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
+ {
+ fill(prims, begin, end, scene);
+ return linearBounds(scene, itime);
+ }
+
+ __forceinline LBBox3fa fillMB(
+ const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
+ {
+ fill(prims, begin, end, scene);
+ return linearBounds(scene, time_range);
+ }
+
+ template<typename BVH, typename SetMB, typename Allocator>
+ __forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc)
+ {
+ size_t start = prims.object_range.begin();
+ size_t end = prims.object_range.end();
+ size_t items = PointMi::blocks(prims.object_range.size());
+ size_t numbytes = PointMi::bytes(prims.object_range.size());
+ PointMi* accel = (PointMi*)alloc.malloc1(numbytes, M * sizeof(float));
+ const typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel, items);
+
+ LBBox3fa bounds = empty;
+ for (size_t i = 0; i < items; i++)
+ bounds.extend(accel[i].fillMB(prims.prims->data(), start, end, bvh->scene, prims.time_range));
+
+ return typename BVH::NodeRecordMB4D(node, bounds, prims.time_range);
+ };
+
+ /*! output operator */
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const PointMi& line)
+ {
+ return cout << "Line" << M << "i {" << line.v0 << ", " << line.geomID() << ", " << line.primID() << "}";
+ }
+
+ public:
+ unsigned char gtype;
+ unsigned char numPrimitives;
+ unsigned int sharedGeomID;
+
+ private:
+ vuint<M> primIDs; // primitive ID
+ };
+
+ template<>
+ __forceinline void PointMi<4>::gather(Vec4vf4& p0, const Points* geom) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0)));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1)));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2)));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3)));
+ transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w);
+ }
+
+ template<>
+ __forceinline void PointMi<4>::gather(Vec4vf4& p0, Vec3vf4& n0, const Points* geom) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0)));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1)));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2)));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3)));
+ transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w);
+ const vfloat4 b0 = vfloat4(geom->normal(primID(0)));
+ const vfloat4 b1 = vfloat4(geom->normal(primID(1)));
+ const vfloat4 b2 = vfloat4(geom->normal(primID(2)));
+ const vfloat4 b3 = vfloat4(geom->normal(primID(3)));
+ transpose(b0, b1, b2, b3, n0.x, n0.y, n0.z);
+ }
+
+ template<>
+ __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, const Points* geom, const int itime) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime));
+ transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w);
+ }
+
+ template<>
+ __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, const int itime) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime));
+ transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w);
+ const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime));
+ const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime));
+ const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime));
+ const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime));
+ transpose(b0, b1, b2, b3, n0.x, n0.y, n0.z);
+ }
+
+ template<>
+ __forceinline void PointMi<4>::gather(Vec4vf4& p0, const Points* geom, float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf4 a0; gatheri(a0, geom, itime);
+ Vec4vf4 b0; gatheri(b0, geom, itime + 1);
+ p0 = lerp(a0, b0, vfloat4(ftime));
+ }
+
+ template<>
+ __forceinline void PointMi<4>::gather(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf4 a0, b0;
+ Vec3vf4 norm0, norm1;
+ gatheri(a0, norm0, geom, itime);
+ gatheri(b0, norm1, geom, itime + 1);
+ p0 = lerp(a0, b0, vfloat4(ftime));
+ n0 = lerp(norm0, norm1, vfloat4(ftime));
+ }
+
+#if defined(__AVX__)
+
+ template<>
+ __forceinline void PointMi<8>::gather(Vec4vf8& p0, const Points* geom) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0)));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1)));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2)));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3)));
+ const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4)));
+ const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5)));
+ const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6)));
+ const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7)));
+ transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w);
+ }
+
+ template<>
+ __forceinline void PointMi<8>::gather(Vec4vf8& p0, Vec3vf8& n0, const Points* geom) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0)));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1)));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2)));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3)));
+ const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4)));
+ const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5)));
+ const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6)));
+ const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7)));
+ transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w);
+ const vfloat4 b0 = vfloat4(geom->normal(primID(0)));
+ const vfloat4 b1 = vfloat4(geom->normal(primID(1)));
+ const vfloat4 b2 = vfloat4(geom->normal(primID(2)));
+ const vfloat4 b3 = vfloat4(geom->normal(primID(3)));
+ const vfloat4 b4 = vfloat4(geom->normal(primID(4)));
+ const vfloat4 b5 = vfloat4(geom->normal(primID(5)));
+ const vfloat4 b6 = vfloat4(geom->normal(primID(6)));
+ const vfloat4 b7 = vfloat4(geom->normal(primID(7)));
+ transpose(b0, b1, b2, b3, b4, b5, b6, b7, n0.x, n0.y, n0.z);
+ }
+
+ template<>
+ __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, const Points* geom, const int itime) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime));
+ const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime));
+ const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime));
+ const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime));
+ const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime));
+ transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w);
+ }
+
+ template<>
+ __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, const int itime) const
+ {
+ const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime));
+ const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime));
+ const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime));
+ const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime));
+ const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime));
+ const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime));
+ const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime));
+ const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime));
+ transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w);
+ const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime));
+ const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime));
+ const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime));
+ const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime));
+ const vfloat4 b4 = vfloat4(geom->normal(primID(4), itime));
+ const vfloat4 b5 = vfloat4(geom->normal(primID(5), itime));
+ const vfloat4 b6 = vfloat4(geom->normal(primID(6), itime));
+ const vfloat4 b7 = vfloat4(geom->normal(primID(7), itime));
+ transpose(b0, b1, b2, b3, b4, b5, b6, b7, n0.x, n0.y, n0.z);
+ }
+
+ template<>
+ __forceinline void PointMi<8>::gather(Vec4vf8& p0, const Points* geom, float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf8 a0;
+ gatheri(a0, geom, itime);
+ Vec4vf8 b0;
+ gatheri(b0, geom, itime + 1);
+ p0 = lerp(a0, b0, vfloat8(ftime));
+ }
+
+ template<>
+ __forceinline void PointMi<8>::gather(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, float time) const
+ {
+ float ftime;
+ const int itime = geom->timeSegment(time, ftime);
+
+ Vec4vf8 a0, b0;
+ Vec3vf8 norm0, norm1;
+ gatheri(a0, norm0, geom, itime);
+ gatheri(b0, norm1, geom, itime + 1);
+ p0 = lerp(a0, b0, vfloat8(ftime));
+ n0 = lerp(norm0, norm1, vfloat8(ftime));
+ }
+#endif
+
+ template<int M>
+ typename PointMi<M>::Type PointMi<M>::type;
+
+ typedef PointMi<4> Point4i;
+ typedef PointMi<8> Point8i;
+
+} // namespace embree
diff --git a/thirdparty/embree/kernels/geometry/primitive.h b/thirdparty/embree/kernels/geometry/primitive.h
new file mode 100644
index 0000000000..608d981dd7
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/primitive.h
@@ -0,0 +1,49 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+#include "../common/scene.h"
+#include "../../common/simd/simd.h"
+#include "../common/primref.h"
+#include "../common/primref_mb.h"
+
+namespace embree
+{
+ struct PrimitiveType
+ {
+ /*! returns name of this primitive type */
+ virtual const char* name() const = 0;
+
+ /*! Returns the number of stored active primitives in a block. */
+ virtual size_t sizeActive(const char* This) const = 0;
+
+ /*! Returns the number of stored active and inactive primitives in a block. */
+ virtual size_t sizeTotal(const char* This) const = 0;
+
+ /*! Returns the number of bytes of block. */
+ virtual size_t getBytes(const char* This) const = 0;
+ };
+
+ template<typename Primitive>
+ struct PrimitivePointQuery1
+ {
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& prim)
+ {
+ bool changed = false;
+ for (size_t i = 0; i < Primitive::max_size(); i++)
+ {
+ if (!prim.valid(i)) break;
+ STAT3(point_query.trav_prims,1,1,1);
+ AccelSet* accel = (AccelSet*)context->scene->get(prim.geomID(i));
+ context->geomID = prim.geomID(i);
+ context->primID = prim.primID(i);
+ changed |= accel->pointQuery(query, context);
+ }
+ return changed;
+ }
+
+ static __forceinline void pointQueryNoop(PointQuery* query, PointQueryContext* context, const Primitive& prim) { }
+ };
+}
diff --git a/thirdparty/embree/kernels/geometry/primitive4.cpp b/thirdparty/embree/kernels/geometry/primitive4.cpp
new file mode 100644
index 0000000000..9c953c5d35
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/primitive4.cpp
@@ -0,0 +1,379 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "primitive.h"
+#include "curveNv.h"
+#include "curveNi.h"
+#include "curveNi_mb.h"
+#include "linei.h"
+#include "triangle.h"
+#include "trianglev.h"
+#include "trianglev_mb.h"
+#include "trianglei.h"
+#include "quadv.h"
+#include "quadi.h"
+#include "subdivpatch1.h"
+#include "object.h"
+#include "instance.h"
+#include "subgrid.h"
+
+namespace embree
+{
+ /********************** Curve4v **************************/
+
+ template<>
+ const char* Curve4v::Type::name () const {
+ return "curve4v";
+ }
+
+ template<>
+ size_t Curve4v::Type::sizeActive(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return ((Line4i*)This)->size();
+ else
+ return ((Curve4v*)This)->N;
+ }
+
+ template<>
+ size_t Curve4v::Type::sizeTotal(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return 4;
+ else
+ return ((Curve4v*)This)->N;
+ }
+
+ template<>
+ size_t Curve4v::Type::getBytes(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return Line4i::bytes(sizeActive(This));
+ else
+ return Curve4v::bytes(sizeActive(This));
+ }
+
+ /********************** Curve4i **************************/
+
+ template<>
+ const char* Curve4i::Type::name () const {
+ return "curve4i";
+ }
+
+ template<>
+ size_t Curve4i::Type::sizeActive(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return ((Line4i*)This)->size();
+ else
+ return ((Curve4i*)This)->N;
+ }
+
+ template<>
+ size_t Curve4i::Type::sizeTotal(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return 4;
+ else
+ return ((Curve4i*)This)->N;
+ }
+
+ template<>
+ size_t Curve4i::Type::getBytes(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return Line4i::bytes(sizeActive(This));
+ else
+ return Curve4i::bytes(sizeActive(This));
+ }
+
+ /********************** Curve4iMB **************************/
+
+ template<>
+ const char* Curve4iMB::Type::name () const {
+ return "curve4imb";
+ }
+
+ template<>
+ size_t Curve4iMB::Type::sizeActive(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return ((Line4i*)This)->size();
+ else
+ return ((Curve4iMB*)This)->N;
+ }
+
+ template<>
+ size_t Curve4iMB::Type::sizeTotal(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return 4;
+ else
+ return ((Curve4iMB*)This)->N;
+ }
+
+ template<>
+ size_t Curve4iMB::Type::getBytes(const char* This) const
+ {
+ if ((*This & Geometry::GType::GTY_BASIS_MASK) == Geometry::GType::GTY_BASIS_LINEAR)
+ return Line4i::bytes(sizeActive(This));
+ else
+ return Curve4iMB::bytes(sizeActive(This));
+ }
+
+ /********************** Line4i **************************/
+
+ template<>
+ const char* Line4i::Type::name () const {
+ return "line4i";
+ }
+
+ template<>
+ size_t Line4i::Type::sizeActive(const char* This) const {
+ return ((Line4i*)This)->size();
+ }
+
+ template<>
+ size_t Line4i::Type::sizeTotal(const char* This) const {
+ return 4;
+ }
+
+ template<>
+ size_t Line4i::Type::getBytes(const char* This) const {
+ return sizeof(Line4i);
+ }
+
+ /********************** Triangle4 **************************/
+
+ template<>
+ const char* Triangle4::Type::name () const {
+ return "triangle4";
+ }
+
+ template<>
+ size_t Triangle4::Type::sizeActive(const char* This) const {
+ return ((Triangle4*)This)->size();
+ }
+
+ template<>
+ size_t Triangle4::Type::sizeTotal(const char* This) const {
+ return 4;
+ }
+
+ template<>
+ size_t Triangle4::Type::getBytes(const char* This) const {
+ return sizeof(Triangle4);
+ }
+
+ /********************** Triangle4v **************************/
+
+ template<>
+ const char* Triangle4v::Type::name () const {
+ return "triangle4v";
+ }
+
+ template<>
+ size_t Triangle4v::Type::sizeActive(const char* This) const {
+ return ((Triangle4v*)This)->size();
+ }
+
+ template<>
+ size_t Triangle4v::Type::sizeTotal(const char* This) const {
+ return 4;
+ }
+
+ template<>
+ size_t Triangle4v::Type::getBytes(const char* This) const {
+ return sizeof(Triangle4v);
+ }
+
+ /********************** Triangle4i **************************/
+
+ template<>
+ const char* Triangle4i::Type::name () const {
+ return "triangle4i";
+ }
+
+ template<>
+ size_t Triangle4i::Type::sizeActive(const char* This) const {
+ return ((Triangle4i*)This)->size();
+ }
+
+ template<>
+ size_t Triangle4i::Type::sizeTotal(const char* This) const {
+ return 4;
+ }
+
+ template<>
+ size_t Triangle4i::Type::getBytes(const char* This) const {
+ return sizeof(Triangle4i);
+ }
+
+ /********************** Triangle4vMB **************************/
+
+ template<>
+ const char* Triangle4vMB::Type::name () const {
+ return "triangle4vmb";
+ }
+
+ template<>
+ size_t Triangle4vMB::Type::sizeActive(const char* This) const {
+ return ((Triangle4vMB*)This)->size();
+ }
+
+ template<>
+ size_t Triangle4vMB::Type::sizeTotal(const char* This) const {
+ return 4;
+ }
+
+ template<>
+ size_t Triangle4vMB::Type::getBytes(const char* This) const {
+ return sizeof(Triangle4vMB);
+ }
+
+ /********************** Quad4v **************************/
+
+ template<>
+ const char* Quad4v::Type::name () const {
+ return "quad4v";
+ }
+
+ template<>
+ size_t Quad4v::Type::sizeActive(const char* This) const {
+ return ((Quad4v*)This)->size();
+ }
+
+ template<>
+ size_t Quad4v::Type::sizeTotal(const char* This) const {
+ return 4;
+ }
+
+ template<>
+ size_t Quad4v::Type::getBytes(const char* This) const {
+ return sizeof(Quad4v);
+ }
+
+ /********************** Quad4i **************************/
+
+ template<>
+ const char* Quad4i::Type::name () const {
+ return "quad4i";
+ }
+
+ template<>
+ size_t Quad4i::Type::sizeActive(const char* This) const {
+ return ((Quad4i*)This)->size();
+ }
+
+ template<>
+ size_t Quad4i::Type::sizeTotal(const char* This) const {
+ return 4;
+ }
+
+ template<>
+ size_t Quad4i::Type::getBytes(const char* This) const {
+ return sizeof(Quad4i);
+ }
+
+ /********************** SubdivPatch1 **************************/
+
+ const char* SubdivPatch1::Type::name () const {
+ return "subdivpatch1";
+ }
+
+ size_t SubdivPatch1::Type::sizeActive(const char* This) const {
+ return 1;
+ }
+
+ size_t SubdivPatch1::Type::sizeTotal(const char* This) const {
+ return 1;
+ }
+
+ size_t SubdivPatch1::Type::getBytes(const char* This) const {
+ return sizeof(SubdivPatch1);
+ }
+
+ SubdivPatch1::Type SubdivPatch1::type;
+
+ /********************** Virtual Object **************************/
+
+ const char* Object::Type::name () const {
+ return "object";
+ }
+
+ size_t Object::Type::sizeActive(const char* This) const {
+ return 1;
+ }
+
+ size_t Object::Type::sizeTotal(const char* This) const {
+ return 1;
+ }
+
+ size_t Object::Type::getBytes(const char* This) const {
+ return sizeof(Object);
+ }
+
+ Object::Type Object::type;
+
+ /********************** Instance **************************/
+
+ const char* InstancePrimitive::Type::name () const {
+ return "instance";
+ }
+
+ size_t InstancePrimitive::Type::sizeActive(const char* This) const {
+ return 1;
+ }
+
+ size_t InstancePrimitive::Type::sizeTotal(const char* This) const {
+ return 1;
+ }
+
+ size_t InstancePrimitive::Type::getBytes(const char* This) const {
+ return sizeof(InstancePrimitive);
+ }
+
+ InstancePrimitive::Type InstancePrimitive::type;
+
+ /********************** SubGrid **************************/
+
+ const char* SubGrid::Type::name () const {
+ return "subgrid";
+ }
+
+ size_t SubGrid::Type::sizeActive(const char* This) const {
+ return 1;
+ }
+
+ size_t SubGrid::Type::sizeTotal(const char* This) const {
+ return 1;
+ }
+
+ size_t SubGrid::Type::getBytes(const char* This) const {
+ return sizeof(SubGrid);
+ }
+
+ SubGrid::Type SubGrid::type;
+
+ /********************** SubGridQBVH4 **************************/
+
+ template<>
+ const char* SubGridQBVH4::Type::name () const {
+ return "SubGridQBVH4";
+ }
+
+ template<>
+ size_t SubGridQBVH4::Type::sizeActive(const char* This) const {
+ return 1;
+ }
+
+ template<>
+ size_t SubGridQBVH4::Type::sizeTotal(const char* This) const {
+ return 1;
+ }
+
+ template<>
+ size_t SubGridQBVH4::Type::getBytes(const char* This) const {
+ return sizeof(SubGridQBVH4);
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/quad_intersector.h b/thirdparty/embree/kernels/geometry/quad_intersector.h
new file mode 100644
index 0000000000..93c9526912
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/quad_intersector.h
@@ -0,0 +1,76 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Intersects a ray with a quad with backface culling
+ * enabled. The quad v0,v1,v2,v3 is split into two triangles
+ * v0,v1,v3 and v2,v3,v1. The edge v1,v2 decides which of the two
+ * triangles gets intersected. */
+ template<int N>
+ __forceinline vbool<N> intersect_quad_backface_culling(const vbool<N>& valid0,
+ const Vec3fa& ray_org,
+ const Vec3fa& ray_dir,
+ const float ray_tnear,
+ const float ray_tfar,
+ const Vec3vf<N>& quad_v0,
+ const Vec3vf<N>& quad_v1,
+ const Vec3vf<N>& quad_v2,
+ const Vec3vf<N>& quad_v3,
+ vfloat<N>& u_o,
+ vfloat<N>& v_o,
+ vfloat<N>& t_o)
+ {
+ /* calculate vertices relative to ray origin */
+ vbool<N> valid = valid0;
+ const Vec3vf<N> O = Vec3vf<N>(ray_org);
+ const Vec3vf<N> D = Vec3vf<N>(ray_dir);
+ const Vec3vf<N> va = quad_v0-O;
+ const Vec3vf<N> vb = quad_v1-O;
+ const Vec3vf<N> vc = quad_v2-O;
+ const Vec3vf<N> vd = quad_v3-O;
+
+ const Vec3vf<N> edb = vb-vd;
+ const vfloat<N> WW = dot(cross(vd,edb),D);
+ const Vec3vf<N> v0 = select(WW <= 0.0f,va,vc);
+ const Vec3vf<N> v1 = select(WW <= 0.0f,vb,vd);
+ const Vec3vf<N> v2 = select(WW <= 0.0f,vd,vb);
+
+ /* calculate edges */
+ const Vec3vf<N> e0 = v2-v0;
+ const Vec3vf<N> e1 = v0-v1;
+
+ /* perform edge tests */
+ const vfloat<N> U = dot(cross(v0,e0),D);
+ const vfloat<N> V = dot(cross(v1,e1),D);
+ valid &= max(U,V) <= 0.0f;
+ if (unlikely(none(valid))) return false;
+
+ /* calculate geometry normal and denominator */
+ const Vec3vf<N> Ng = cross(e1,e0);
+ const vfloat<N> den = dot(Ng,D);
+ const vfloat<N> rcpDen = rcp(den);
+
+ /* perform depth test */
+ const vfloat<N> t = rcpDen*dot(v0,Ng);
+ valid &= vfloat<N>(ray_tnear) <= t & t <= vfloat<N>(ray_tfar);
+ if (unlikely(none(valid))) return false;
+
+ /* avoid division by 0 */
+ valid &= den != vfloat<N>(zero);
+ if (unlikely(none(valid))) return false;
+
+ /* update hit information */
+ t_o = t;
+ u_o = U * rcpDen;
+ v_o = V * rcpDen;
+ u_o = select(WW <= 0.0f,u_o,1.0f-u_o);
+ v_o = select(WW <= 0.0f,v_o,1.0f-v_o);
+ return valid;
+ }
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/quad_intersector_moeller.h b/thirdparty/embree/kernels/geometry/quad_intersector_moeller.h
new file mode 100644
index 0000000000..3abc9d6f70
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/quad_intersector_moeller.h
@@ -0,0 +1,460 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "quadv.h"
+#include "triangle_intersector_moeller.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct QuadHitM
+ {
+ __forceinline QuadHitM() {}
+
+ __forceinline QuadHitM(const vbool<M>& valid,
+ const vfloat<M>& U,
+ const vfloat<M>& V,
+ const vfloat<M>& T,
+ const vfloat<M>& absDen,
+ const Vec3vf<M>& Ng,
+ const vbool<M>& flags)
+ : U(U), V(V), T(T), absDen(absDen), tri_Ng(Ng), valid(valid), flags(flags) {}
+
+ __forceinline void finalize()
+ {
+ const vfloat<M> rcpAbsDen = rcp(absDen);
+ vt = T * rcpAbsDen;
+ const vfloat<M> u = min(U * rcpAbsDen,1.0f);
+ const vfloat<M> v = min(V * rcpAbsDen,1.0f);
+ const vfloat<M> u1 = vfloat<M>(1.0f) - u;
+ const vfloat<M> v1 = vfloat<M>(1.0f) - v;
+#if !defined(__AVX__) || defined(EMBREE_BACKFACE_CULLING)
+ vu = select(flags,u1,u);
+ vv = select(flags,v1,v);
+ vNg = Vec3vf<M>(tri_Ng.x,tri_Ng.y,tri_Ng.z);
+#else
+ const vfloat<M> flip = select(flags,vfloat<M>(-1.0f),vfloat<M>(1.0f));
+ vv = select(flags,u1,v);
+ vu = select(flags,v1,u);
+ vNg = Vec3vf<M>(flip*tri_Ng.x,flip*tri_Ng.y,flip*tri_Ng.z);
+#endif
+ }
+
+ __forceinline Vec2f uv(const size_t i)
+ {
+ const float u = vu[i];
+ const float v = vv[i];
+ return Vec2f(u,v);
+ }
+
+ __forceinline float t(const size_t i) { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
+
+ private:
+ vfloat<M> U;
+ vfloat<M> V;
+ vfloat<M> T;
+ vfloat<M> absDen;
+ Vec3vf<M> tri_Ng;
+
+ public:
+ vbool<M> valid;
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+
+ public:
+ const vbool<M> flags;
+ };
+
+ template<int K>
+ struct QuadHitK
+ {
+ __forceinline QuadHitK(const vfloat<K>& U,
+ const vfloat<K>& V,
+ const vfloat<K>& T,
+ const vfloat<K>& absDen,
+ const Vec3vf<K>& Ng,
+ const vbool<K>& flags)
+ : U(U), V(V), T(T), absDen(absDen), flags(flags), tri_Ng(Ng) {}
+
+ __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
+ {
+ const vfloat<K> rcpAbsDen = rcp(absDen);
+ const vfloat<K> t = T * rcpAbsDen;
+ const vfloat<K> u0 = min(U * rcpAbsDen,1.0f);
+ const vfloat<K> v0 = min(V * rcpAbsDen,1.0f);
+ const vfloat<K> u1 = vfloat<K>(1.0f) - u0;
+ const vfloat<K> v1 = vfloat<K>(1.0f) - v0;
+ const vfloat<K> u = select(flags,u1,u0);
+ const vfloat<K> v = select(flags,v1,v0);
+ const Vec3vf<K> Ng(tri_Ng.x,tri_Ng.y,tri_Ng.z);
+ return std::make_tuple(u,v,t,Ng);
+ }
+
+ private:
+ const vfloat<K> U;
+ const vfloat<K> V;
+ const vfloat<K> T;
+ const vfloat<K> absDen;
+ const vbool<K> flags;
+ const Vec3vf<K> tri_Ng;
+ };
+
+ /* ----------------------------- */
+ /* -- single ray intersectors -- */
+ /* ----------------------------- */
+
+
+ template<int M, bool filter>
+ struct QuadMIntersector1MoellerTrumbore;
+
+ /*! Intersects M quads with 1 ray */
+ template<int M, bool filter>
+ struct QuadMIntersector1MoellerTrumbore
+ {
+ __forceinline QuadMIntersector1MoellerTrumbore() {}
+
+ __forceinline QuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
+
+ __forceinline void intersect(RayHit& ray, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const vuint<M>& geomID, const vuint<M>& primID) const
+ {
+ UVIdentity<M> mapUV;
+ MoellerTrumboreHitM<M,UVIdentity<M>> hit(mapUV);
+ MoellerTrumboreIntersector1<M> intersector(ray,nullptr);
+ Intersect1EpilogM<M,filter> epilog(ray,context,geomID,primID);
+
+ /* intersect first triangle */
+ if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))
+ epilog(hit.valid,hit);
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.absDen - hit.U;
+ hit.V = hit.absDen - hit.V;
+ epilog(hit.valid,hit);
+ }
+ }
+
+ __forceinline bool occluded(Ray& ray, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const vuint<M>& geomID, const vuint<M>& primID) const
+ {
+ UVIdentity<M> mapUV;
+ MoellerTrumboreHitM<M,UVIdentity<M>> hit(mapUV);
+ MoellerTrumboreIntersector1<M> intersector(ray,nullptr);
+ Occluded1EpilogM<M,filter> epilog(ray,context,geomID,primID);
+
+ /* intersect first triangle */
+ if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))
+ {
+ if (epilog(hit.valid,hit))
+ return true;
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.absDen - hit.U;
+ hit.V = hit.absDen - hit.V;
+ if (epilog(hit.valid,hit))
+ return true;
+ }
+ return false;
+ }
+ };
+
+#if defined(__AVX__)
+
+ /*! Intersects 4 quads with 1 ray using AVX */
+ template<bool filter>
+ struct QuadMIntersector1MoellerTrumbore<4,filter>
+ {
+ __forceinline QuadMIntersector1MoellerTrumbore() {}
+
+ __forceinline QuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
+
+ template<typename Epilog>
+ __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
+ {
+ const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
+#if !defined(EMBREE_BACKFACE_CULLING)
+ const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
+#else
+ const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
+#endif
+ UVIdentity<8> mapUV;
+ MoellerTrumboreHitM<8,UVIdentity<8>> hit(mapUV);
+ MoellerTrumboreIntersector1<8> intersector(ray,nullptr);
+ const vbool8 flags(0,0,0,0,1,1,1,1);
+ if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,mapUV,hit)))
+ {
+ vfloat8 U = hit.U, V = hit.V, absDen = hit.absDen;
+
+#if !defined(EMBREE_BACKFACE_CULLING)
+ hit.U = select(flags,absDen-V,U);
+ hit.V = select(flags,absDen-U,V);
+ hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f)); // FIXME: use XOR
+#else
+ hit.U = select(flags,absDen-U,U);
+ hit.V = select(flags,absDen-V,V);
+#endif
+ if (unlikely(epilog(hit.valid,hit)))
+ return true;
+ }
+ return false;
+ }
+
+ __forceinline bool intersect(RayHit& ray, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const vuint4& geomID, const vuint4& primID) const
+ {
+ return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,filter>(ray,context,vuint8(geomID),vuint8(primID)));
+ }
+
+ __forceinline bool occluded(Ray& ray, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const vuint4& geomID, const vuint4& primID) const
+ {
+ return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,filter>(ray,context,vuint8(geomID),vuint8(primID)));
+ }
+ };
+
+#endif
+
+ /* ----------------------------- */
+ /* -- ray packet intersectors -- */
+ /* ----------------------------- */
+
+
+ struct MoellerTrumboreIntersector1KTriangleM
+ {
+ /*! Intersect k'th ray from ray packet of size K with M triangles. */
+ template<int M, int K, typename Epilog>
+ static __forceinline bool intersect(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const Vec3vf<M>& tri_Ng,
+ const vbool<M>& flags,
+ const Epilog& epilog)
+ {
+ /* calculate denominator */
+ const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
+ const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
+ const Vec3vf<M> C = Vec3vf<M>(tri_v0) - O;
+ const Vec3vf<M> R = cross(C,D);
+ const vfloat<M> den = dot(Vec3vf<M>(tri_Ng),D);
+ const vfloat<M> absDen = abs(den);
+ const vfloat<M> sgnDen = signmsk(den);
+
+ /* perform edge tests */
+ const vfloat<M> U = dot(R,Vec3vf<M>(tri_e2)) ^ sgnDen;
+ const vfloat<M> V = dot(R,Vec3vf<M>(tri_e1)) ^ sgnDen;
+
+ /* perform backface culling */
+#if defined(EMBREE_BACKFACE_CULLING)
+ vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
+#else
+ vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
+#endif
+ if (likely(none(valid))) return false;
+
+ /* perform depth test */
+ const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
+ valid &= (absDen*vfloat<M>(ray.tnear()[k]) < T) & (T <= absDen*vfloat<M>(ray.tfar[k]));
+ if (likely(none(valid))) return false;
+
+ /* calculate hit information */
+ QuadHitM<M> hit(valid,U,V,T,absDen,tri_Ng,flags);
+ return epilog(valid,hit);
+ }
+
+ template<int M, int K, typename Epilog>
+ static __forceinline bool intersect1(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const vbool<M>& flags,
+ const Epilog& epilog)
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ const Vec3vf<M> Ng = cross(e2,e1);
+ return intersect<M,K>(ray,k,v0,e1,e2,Ng,flags,epilog);
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct QuadMIntersectorKMoellerTrumboreBase
+ {
+ __forceinline QuadMIntersectorKMoellerTrumboreBase(const vbool<K>& valid, const RayK<K>& ray) {}
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_e1,
+ const Vec3vf<K>& tri_e2,
+ const Vec3vf<K>& tri_Ng,
+ const vbool<K>& flags,
+ const Epilog& epilog) const
+ {
+ /* calculate denominator */
+ vbool<K> valid = valid0;
+ const Vec3vf<K> C = tri_v0 - ray.org;
+ const Vec3vf<K> R = cross(C,ray.dir);
+ const vfloat<K> den = dot(tri_Ng,ray.dir);
+ const vfloat<K> absDen = abs(den);
+ const vfloat<K> sgnDen = signmsk(den);
+
+ /* test against edge p2 p0 */
+ const vfloat<K> U = dot(R,tri_e2) ^ sgnDen;
+ valid &= U >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* test against edge p0 p1 */
+ const vfloat<K> V = dot(R,tri_e1) ^ sgnDen;
+ valid &= V >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* test against edge p1 p2 */
+ const vfloat<K> W = absDen-U-V;
+ valid &= W >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* perform depth test */
+ const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen;
+ valid &= (absDen*ray.tnear() < T) & (T <= absDen*ray.tfar);
+ if (unlikely(none(valid))) return false;
+
+ /* perform backface culling */
+#if defined(EMBREE_BACKFACE_CULLING)
+ valid &= den < vfloat<K>(zero);
+ if (unlikely(none(valid))) return false;
+#else
+ valid &= den != vfloat<K>(zero);
+ if (unlikely(none(valid))) return false;
+#endif
+
+ /* calculate hit information */
+ QuadHitK<K> hit(U,V,T,absDen,tri_Ng,flags);
+ return epilog(valid,hit);
+ }
+
+ /*! Intersects K rays with one of M quads. */
+ template<typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const vbool<K>& flags,
+ const Epilog& epilog) const
+ {
+ const Vec3vf<K> e1 = tri_v0-tri_v1;
+ const Vec3vf<K> e2 = tri_v2-tri_v0;
+ const Vec3vf<K> Ng = cross(e2,e1);
+ return intersectK(valid0,ray,tri_v0,e1,e2,Ng,flags,epilog);
+ }
+
+ /*! Intersects K rays with one of M quads. */
+ template<typename Epilog>
+ __forceinline bool intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& v0,
+ const Vec3vf<K>& v1,
+ const Vec3vf<K>& v2,
+ const Vec3vf<K>& v3,
+ const Epilog& epilog) const
+ {
+ intersectK(valid0,ray,v0,v1,v3,vbool<K>(false),epilog);
+ if (none(valid0)) return true;
+ intersectK(valid0,ray,v2,v3,v1,vbool<K>(true ),epilog);
+ return none(valid0);
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct QuadMIntersectorKMoellerTrumbore : public QuadMIntersectorKMoellerTrumboreBase<M,K,filter>
+ {
+ __forceinline QuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
+ : QuadMIntersectorKMoellerTrumboreBase<M,K,filter>(valid,ray) {}
+
+ __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const vuint<M>& geomID, const vuint<M>& primID) const
+ {
+ Intersect1KEpilogM<M,K,filter> epilog(ray,k,context,geomID,primID);
+ MoellerTrumboreIntersector1KTriangleM::intersect1<M,K>(ray,k,v0,v1,v3,vbool<M>(false),epilog);
+ MoellerTrumboreIntersector1KTriangleM::intersect1<M,K>(ray,k,v2,v3,v1,vbool<M>(true ),epilog);
+ }
+
+ __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const vuint<M>& geomID, const vuint<M>& primID) const
+ {
+ Occluded1KEpilogM<M,K,filter> epilog(ray,k,context,geomID,primID);
+ if (MoellerTrumboreIntersector1KTriangleM::intersect1<M,K>(ray,k,v0,v1,v3,vbool<M>(false),epilog)) return true;
+ if (MoellerTrumboreIntersector1KTriangleM::intersect1<M,K>(ray,k,v2,v3,v1,vbool<M>(true ),epilog)) return true;
+ return false;
+ }
+ };
+
+
+#if defined(__AVX__)
+
+ /*! Intersects 4 quads with 1 ray using AVX */
+ template<int K, bool filter>
+ struct QuadMIntersectorKMoellerTrumbore<4,K,filter> : public QuadMIntersectorKMoellerTrumboreBase<4,K,filter>
+ {
+ __forceinline QuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
+ : QuadMIntersectorKMoellerTrumboreBase<4,K,filter>(valid,ray) {}
+
+ template<typename Epilog>
+ __forceinline bool intersect1(RayK<K>& ray, size_t k,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
+ {
+ const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
+#if !defined(EMBREE_BACKFACE_CULLING)
+ const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
+#else
+ const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
+#endif
+ const vbool8 flags(0,0,0,0,1,1,1,1);
+ return MoellerTrumboreIntersector1KTriangleM::intersect1<8,K>(ray,k,vtx0,vtx1,vtx2,flags,epilog);
+ }
+
+ __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const vuint4& geomID, const vuint4& primID) const
+ {
+ return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
+ }
+
+ __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const vuint4& geomID, const vuint4& primID) const
+ {
+ return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
+ }
+ };
+
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/quad_intersector_pluecker.h b/thirdparty/embree/kernels/geometry/quad_intersector_pluecker.h
new file mode 100644
index 0000000000..9873ff76ac
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/quad_intersector_pluecker.h
@@ -0,0 +1,438 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "quad_intersector_moeller.h"
+
+/*! Modified Pluecker ray/triangle intersector. The test first shifts
+ * the ray origin into the origin of the coordinate system and then
+ * uses Pluecker coordinates for the intersection. Due to the shift,
+ * the Pluecker coordinate calculation simplifies and the tests get
+ * numerically stable. The edge equations are watertight along the
+ * edge for neighboring triangles. */
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct QuadHitPlueckerM
+ {
+ __forceinline QuadHitPlueckerM() {}
+
+ __forceinline QuadHitPlueckerM(const vbool<M>& valid,
+ const vfloat<M>& U,
+ const vfloat<M>& V,
+ const vfloat<M>& UVW,
+ const vfloat<M>& t,
+ const Vec3vf<M>& Ng,
+ const vbool<M>& flags)
+ : U(U), V(V), UVW(UVW), tri_Ng(Ng), valid(valid), vt(t), flags(flags) {}
+
+ __forceinline void finalize()
+ {
+ const vbool<M> invalid = abs(UVW) < min_rcp_input;
+ const vfloat<M> rcpUVW = select(invalid,vfloat<M>(0.0f),rcp(UVW));
+ const vfloat<M> u = min(U * rcpUVW,1.0f);
+ const vfloat<M> v = min(V * rcpUVW,1.0f);
+ const vfloat<M> u1 = vfloat<M>(1.0f) - u;
+ const vfloat<M> v1 = vfloat<M>(1.0f) - v;
+#if !defined(__AVX__) || defined(EMBREE_BACKFACE_CULLING)
+ vu = select(flags,u1,u);
+ vv = select(flags,v1,v);
+ vNg = Vec3vf<M>(tri_Ng.x,tri_Ng.y,tri_Ng.z);
+#else
+ const vfloat<M> flip = select(flags,vfloat<M>(-1.0f),vfloat<M>(1.0f));
+ vv = select(flags,u1,v);
+ vu = select(flags,v1,u);
+ vNg = Vec3vf<M>(flip*tri_Ng.x,flip*tri_Ng.y,flip*tri_Ng.z);
+#endif
+ }
+
+ __forceinline Vec2f uv(const size_t i)
+ {
+ const float u = vu[i];
+ const float v = vv[i];
+ return Vec2f(u,v);
+ }
+
+ __forceinline float t(const size_t i) { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
+
+ private:
+ vfloat<M> U;
+ vfloat<M> V;
+ vfloat<M> UVW;
+ Vec3vf<M> tri_Ng;
+
+ public:
+ vbool<M> valid;
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+
+ public:
+ const vbool<M> flags;
+ };
+
+ template<int K>
+ struct QuadHitPlueckerK
+ {
+ __forceinline QuadHitPlueckerK(const vfloat<K>& U,
+ const vfloat<K>& V,
+ const vfloat<K>& UVW,
+ const vfloat<K>& t,
+ const Vec3vf<K>& Ng,
+ const vbool<K>& flags)
+ : U(U), V(V), UVW(UVW), t(t), flags(flags), tri_Ng(Ng) {}
+
+ __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
+ {
+ const vbool<K> invalid = abs(UVW) < min_rcp_input;
+ const vfloat<K> rcpUVW = select(invalid,vfloat<K>(0.0f),rcp(UVW));
+ const vfloat<K> u0 = min(U * rcpUVW,1.0f);
+ const vfloat<K> v0 = min(V * rcpUVW,1.0f);
+ const vfloat<K> u1 = vfloat<K>(1.0f) - u0;
+ const vfloat<K> v1 = vfloat<K>(1.0f) - v0;
+ const vfloat<K> u = select(flags,u1,u0);
+ const vfloat<K> v = select(flags,v1,v0);
+ const Vec3vf<K> Ng(tri_Ng.x,tri_Ng.y,tri_Ng.z);
+ return std::make_tuple(u,v,t,Ng);
+ }
+
+ private:
+ const vfloat<K> U;
+ const vfloat<K> V;
+ const vfloat<K> UVW;
+ const vfloat<K> t;
+ const vbool<K> flags;
+ const Vec3vf<K> tri_Ng;
+ };
+
+ struct PlueckerIntersectorTriangle1
+ {
+ template<int M, typename Epilog>
+ static __forceinline bool intersect(Ray& ray,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const vbool<M>& flags,
+ const Epilog& epilog)
+ {
+ /* calculate vertices relative to ray origin */
+ const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org);
+ const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir);
+ const Vec3vf<M> v0 = tri_v0-O;
+ const Vec3vf<M> v1 = tri_v1-O;
+ const Vec3vf<M> v2 = tri_v2-O;
+
+ /* calculate triangle edges */
+ const Vec3vf<M> e0 = v2-v0;
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v1-v2;
+
+ /* perform edge tests */
+ const vfloat<M> U = dot(cross(e0,v2+v0),D);
+ const vfloat<M> V = dot(cross(e1,v0+v1),D);
+ const vfloat<M> W = dot(cross(e2,v1+v2),D);
+ const vfloat<M> UVW = U+V+W;
+ const vfloat<M> eps = float(ulp)*abs(UVW);
+#if defined(EMBREE_BACKFACE_CULLING)
+ vbool<M> valid = max(U,V,W) <= eps;
+#else
+ vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
+#endif
+ if (unlikely(none(valid))) return false;
+
+ /* calculate geometry normal and denominator */
+ const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
+ const vfloat<M> den = twice(dot(Ng,D));
+
+ /* perform depth test */
+ const vfloat<M> T = twice(dot(v0,Ng));
+ const vfloat<M> t = rcp(den)*T;
+ valid &= vfloat<M>(ray.tnear()) <= t & t <= vfloat<M>(ray.tfar);
+ valid &= den != vfloat<M>(zero);
+ if (unlikely(none(valid))) return false;
+
+ /* update hit information */
+ QuadHitPlueckerM<M> hit(valid,U,V,UVW,t,Ng,flags);
+ return epilog(valid,hit);
+ }
+ };
+
+ /*! Intersects M quads with 1 ray */
+ template<int M, bool filter>
+ struct QuadMIntersector1Pluecker
+ {
+ __forceinline QuadMIntersector1Pluecker() {}
+
+ __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
+
+ __forceinline void intersect(RayHit& ray, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const vuint<M>& geomID, const vuint<M>& primID) const
+ {
+ Intersect1EpilogM<M,filter> epilog(ray,context,geomID,primID);
+ PlueckerIntersectorTriangle1::intersect<M>(ray,v0,v1,v3,vbool<M>(false),epilog);
+ PlueckerIntersectorTriangle1::intersect<M>(ray,v2,v3,v1,vbool<M>(true),epilog);
+ }
+
+ __forceinline bool occluded(Ray& ray, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const vuint<M>& geomID, const vuint<M>& primID) const
+ {
+ Occluded1EpilogM<M,filter> epilog(ray,context,geomID,primID);
+ if (PlueckerIntersectorTriangle1::intersect<M>(ray,v0,v1,v3,vbool<M>(false),epilog)) return true;
+ if (PlueckerIntersectorTriangle1::intersect<M>(ray,v2,v3,v1,vbool<M>(true ),epilog)) return true;
+ return false;
+ }
+ };
+
+#if defined(__AVX__)
+
+ /*! Intersects 4 quads with 1 ray using AVX */
+ template<bool filter>
+ struct QuadMIntersector1Pluecker<4,filter>
+ {
+ __forceinline QuadMIntersector1Pluecker() {}
+
+ __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
+
+ template<typename Epilog>
+ __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
+ {
+ const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
+#if !defined(EMBREE_BACKFACE_CULLING)
+ const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
+#else
+ const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
+#endif
+ const vbool8 flags(0,0,0,0,1,1,1,1);
+ return PlueckerIntersectorTriangle1::intersect<8>(ray,vtx0,vtx1,vtx2,flags,epilog);
+ }
+
+ __forceinline bool intersect(RayHit& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const vuint4& geomID, const vuint4& primID) const
+ {
+ return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,filter>(ray,context,vuint8(geomID),vuint8(primID)));
+ }
+
+ __forceinline bool occluded(Ray& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const vuint4& geomID, const vuint4& primID) const
+ {
+ return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,filter>(ray,context,vuint8(geomID),vuint8(primID)));
+ }
+ };
+
+#endif
+
+
+ /* ----------------------------- */
+ /* -- ray packet intersectors -- */
+ /* ----------------------------- */
+
+ struct PlueckerIntersector1KTriangleM
+ {
+ /*! Intersect k'th ray from ray packet of size K with M triangles. */
+ template<int M, int K, typename Epilog>
+ static __forceinline bool intersect1(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const vbool<M>& flags,
+ const Epilog& epilog)
+ {
+ /* calculate vertices relative to ray origin */
+ const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
+ const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
+ const Vec3vf<M> v0 = tri_v0-O;
+ const Vec3vf<M> v1 = tri_v1-O;
+ const Vec3vf<M> v2 = tri_v2-O;
+
+ /* calculate triangle edges */
+ const Vec3vf<M> e0 = v2-v0;
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v1-v2;
+
+ /* perform edge tests */
+ const vfloat<M> U = dot(cross(e0,v2+v0),D);
+ const vfloat<M> V = dot(cross(e1,v0+v1),D);
+ const vfloat<M> W = dot(cross(e2,v1+v2),D);
+
+ const vfloat<M> UVW = U+V+W;
+ const vfloat<M> eps = float(ulp)*abs(UVW);
+#if defined(EMBREE_BACKFACE_CULLING)
+ vbool<M> valid = max(U,V,W) <= eps;
+#else
+ vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
+#endif
+ if (unlikely(none(valid))) return false;
+
+ /* calculate geometry normal and denominator */
+ const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
+ const vfloat<M> den = twice(dot(Ng,D));
+
+ /* perform depth test */
+ const vfloat<M> T = twice(dot(v0,Ng));
+ const vfloat<M> t = rcp(den)*T;
+ valid &= vfloat<M>(ray.tnear()[k]) <= t & t <= vfloat<M>(ray.tfar[k]);
+ if (unlikely(none(valid))) return false;
+
+ /* avoid division by 0 */
+ valid &= den != vfloat<M>(zero);
+ if (unlikely(none(valid))) return false;
+
+ /* update hit information */
+ QuadHitPlueckerM<M> hit(valid,U,V,UVW,t,Ng,flags);
+ return epilog(valid,hit);
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct QuadMIntersectorKPlueckerBase
+ {
+ __forceinline QuadMIntersectorKPlueckerBase(const vbool<K>& valid, const RayK<K>& ray) {}
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const vbool<K>& flags,
+ const Epilog& epilog) const
+ {
+ /* calculate vertices relative to ray origin */
+ vbool<K> valid = valid0;
+ const Vec3vf<K> O = ray.org;
+ const Vec3vf<K> D = ray.dir;
+ const Vec3vf<K> v0 = tri_v0-O;
+ const Vec3vf<K> v1 = tri_v1-O;
+ const Vec3vf<K> v2 = tri_v2-O;
+
+ /* calculate triangle edges */
+ const Vec3vf<K> e0 = v2-v0;
+ const Vec3vf<K> e1 = v0-v1;
+ const Vec3vf<K> e2 = v1-v2;
+
+ /* perform edge tests */
+ const vfloat<K> U = dot(Vec3vf<K>(cross(e0,v2+v0)),D);
+ const vfloat<K> V = dot(Vec3vf<K>(cross(e1,v0+v1)),D);
+ const vfloat<K> W = dot(Vec3vf<K>(cross(e2,v1+v2)),D);
+ const vfloat<K> UVW = U+V+W;
+ const vfloat<K> eps = float(ulp)*abs(UVW);
+#if defined(EMBREE_BACKFACE_CULLING)
+ valid &= max(U,V,W) <= eps;
+#else
+ valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
+#endif
+ if (unlikely(none(valid))) return false;
+
+ /* calculate geometry normal and denominator */
+ const Vec3vf<K> Ng = stable_triangle_normal(e0,e1,e2);
+ const vfloat<K> den = twice(dot(Vec3vf<K>(Ng),D));
+
+ /* perform depth test */
+ const vfloat<K> T = twice(dot(v0,Vec3vf<K>(Ng)));
+ const vfloat<K> t = rcp(den)*T;
+ valid &= ray.tnear() <= t & t <= ray.tfar;
+ valid &= den != vfloat<K>(zero);
+ if (unlikely(none(valid))) return false;
+
+ /* calculate hit information */
+ QuadHitPlueckerK<K> hit(U,V,UVW,t,Ng,flags);
+ return epilog(valid,hit);
+ }
+
+ /*! Intersects K rays with one of M quads. */
+ template<typename Epilog>
+ __forceinline bool intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& v0,
+ const Vec3vf<K>& v1,
+ const Vec3vf<K>& v2,
+ const Vec3vf<K>& v3,
+ const Epilog& epilog) const
+ {
+ intersectK(valid0,ray,v0,v1,v3,vbool<K>(false),epilog);
+ if (none(valid0)) return true;
+ intersectK(valid0,ray,v2,v3,v1,vbool<K>(true ),epilog);
+ return none(valid0);
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct QuadMIntersectorKPluecker : public QuadMIntersectorKPlueckerBase<M,K,filter>
+ {
+ __forceinline QuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
+ : QuadMIntersectorKPlueckerBase<M,K,filter>(valid,ray) {}
+
+ __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const vuint<M>& geomID, const vuint<M>& primID) const
+ {
+ Intersect1KEpilogM<M,K,filter> epilog(ray,k,context,geomID,primID);
+ PlueckerIntersector1KTriangleM::intersect1<M,K>(ray,k,v0,v1,v3,vbool<M>(false),epilog);
+ PlueckerIntersector1KTriangleM::intersect1<M,K>(ray,k,v2,v3,v1,vbool<M>(true ),epilog);
+ }
+
+ __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const vuint<M>& geomID, const vuint<M>& primID) const
+ {
+ Occluded1KEpilogM<M,K,filter> epilog(ray,k,context,geomID,primID);
+ if (PlueckerIntersector1KTriangleM::intersect1<M,K>(ray,k,v0,v1,v3,vbool<M>(false),epilog)) return true;
+ if (PlueckerIntersector1KTriangleM::intersect1<M,K>(ray,k,v2,v3,v1,vbool<M>(true ),epilog)) return true;
+ return false;
+ }
+ };
+
+#if defined(__AVX__)
+
+ /*! Intersects 4 quads with 1 ray using AVX */
+ template<int K, bool filter>
+ struct QuadMIntersectorKPluecker<4,K,filter> : public QuadMIntersectorKPlueckerBase<4,K,filter>
+ {
+ __forceinline QuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
+ : QuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {}
+
+ template<typename Epilog>
+ __forceinline bool intersect1(RayK<K>& ray, size_t k, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
+ {
+ const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
+ const vbool8 flags(0,0,0,0,1,1,1,1);
+#if !defined(EMBREE_BACKFACE_CULLING)
+ const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
+#else
+ const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
+#endif
+ return PlueckerIntersector1KTriangleM::intersect1<8,K>(ray,k,vtx0,vtx1,vtx2,flags,epilog);
+ }
+
+ __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const vuint4& geomID, const vuint4& primID) const
+ {
+ return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
+ }
+
+ __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const vuint4& geomID, const vuint4& primID) const
+ {
+ return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID)));
+ }
+ };
+
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/quadi.h b/thirdparty/embree/kernels/geometry/quadi.h
new file mode 100644
index 0000000000..70a7bdf158
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/quadi.h
@@ -0,0 +1,483 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+#include "../common/scene.h"
+
+namespace embree
+{
+ /* Stores M quads from an indexed face set */
+ template <int M>
+ struct QuadMi
+ {
+ /* Virtual interface to query information about the quad type */
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* primitive supports multiple time segments */
+ static const bool singleTimeSegment = false;
+
+ /* Returns maximum number of stored quads */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
+
+ public:
+
+ /* Default constructor */
+ __forceinline QuadMi() { }
+
+ /* Construction from vertices and IDs */
+ __forceinline QuadMi(const vuint<M>& v0,
+ const vuint<M>& v1,
+ const vuint<M>& v2,
+ const vuint<M>& v3,
+ const vuint<M>& geomIDs,
+ const vuint<M>& primIDs)
+#if defined(EMBREE_COMPACT_POLYS)
+ : geomIDs(geomIDs), primIDs(primIDs) {}
+#else
+ : v0_(v0),v1_(v1), v2_(v2), v3_(v3), geomIDs(geomIDs), primIDs(primIDs) {}
+#endif
+
+ /* Returns a mask that tells which quads are valid */
+ __forceinline vbool<M> valid() const { return primIDs != vuint<M>(-1); }
+
+ /* Returns if the specified quad is valid */
+ __forceinline bool valid(const size_t i) const { assert(i<M); return primIDs[i] != -1; }
+
+ /* Returns the number of stored quads */
+ __forceinline size_t size() const { return bsf(~movemask(valid())); }
+
+ /* Returns the geometry IDs */
+ __forceinline vuint<M>& geomID() { return geomIDs; }
+ __forceinline const vuint<M>& geomID() const { return geomIDs; }
+ __forceinline unsigned int geomID(const size_t i) const { assert(i<M); assert(geomIDs[i] != -1); return geomIDs[i]; }
+
+ /* Returns the primitive IDs */
+ __forceinline vuint<M>& primID() { return primIDs; }
+ __forceinline const vuint<M>& primID() const { return primIDs; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
+
+ /* Calculate the bounds of the quads */
+ __forceinline const BBox3fa bounds(const Scene *const scene, const size_t itime=0) const
+ {
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<M && valid(i); i++) {
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(i));
+ bounds.extend(mesh->bounds(primID(i),itime));
+ }
+ return bounds;
+ }
+
+ /* Calculate the linear bounds of the primitive */
+ __forceinline LBBox3fa linearBounds(const Scene* const scene, const size_t itime) {
+ return LBBox3fa(bounds(scene,itime+0),bounds(scene,itime+1));
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps)
+ {
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<M && valid(i); i++)
+ {
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(i));
+ allBounds.extend(mesh->linearBounds(primID(i), itime, numTimeSteps));
+ }
+ return allBounds;
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range)
+ {
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<M && valid(i); i++)
+ {
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(i));
+ allBounds.extend(mesh->linearBounds(primID(i), time_range));
+ }
+ return allBounds;
+ }
+
+ /* Fill quad from quad list */
+ template<typename PrimRefT>
+ __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene)
+ {
+ vuint<M> geomID = -1, primID = -1;
+ const PrimRefT* prim = &prims[begin];
+ vuint<M> v0 = zero, v1 = zero, v2 = zero, v3 = zero;
+
+ for (size_t i=0; i<M; i++)
+ {
+ if (begin<end) {
+ geomID[i] = prim->geomID();
+ primID[i] = prim->primID();
+#if !defined(EMBREE_COMPACT_POLYS)
+ const QuadMesh* mesh = scene->get<QuadMesh>(prim->geomID());
+ const QuadMesh::Quad& q = mesh->quad(prim->primID());
+ unsigned int_stride = mesh->vertices0.getStride()/4;
+ v0[i] = q.v[0] * int_stride;
+ v1[i] = q.v[1] * int_stride;
+ v2[i] = q.v[2] * int_stride;
+ v3[i] = q.v[3] * int_stride;
+#endif
+ begin++;
+ } else {
+ assert(i);
+ if (likely(i > 0)) {
+ geomID[i] = geomID[0]; // always valid geomIDs
+ primID[i] = -1; // indicates invalid data
+ v0[i] = v0[0];
+ v1[i] = v0[0];
+ v2[i] = v0[0];
+ v3[i] = v0[0];
+ }
+ }
+ if (begin<end) prim = &prims[begin];
+ }
+ new (this) QuadMi(v0,v1,v2,v3,geomID,primID); // FIXME: use non temporal store
+ }
+
+ __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
+ {
+ fill(prims, begin, end, scene);
+ return linearBounds(scene, itime);
+ }
+
+ __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
+ {
+ fill(prims, begin, end, scene);
+ return linearBounds(scene, time_range);
+ }
+
+ friend embree_ostream operator<<(embree_ostream cout, const QuadMi& quad) {
+ return cout << "QuadMi<" << M << ">( "
+#if !defined(EMBREE_COMPACT_POLYS)
+ << "v0 = " << quad.v0_ << ", v1 = " << quad.v1_ << ", v2 = " << quad.v2_ << ", v3 = " << quad.v3_ << ", "
+#endif
+ << "geomID = " << quad.geomIDs << ", primID = " << quad.primIDs << " )";
+ }
+
+ protected:
+#if !defined(EMBREE_COMPACT_POLYS)
+ vuint<M> v0_; // 4 byte offset of 1st vertex
+ vuint<M> v1_; // 4 byte offset of 2nd vertex
+ vuint<M> v2_; // 4 byte offset of 3rd vertex
+ vuint<M> v3_; // 4 byte offset of 4th vertex
+#endif
+ vuint<M> geomIDs; // geometry ID of mesh
+ vuint<M> primIDs; // primitive ID of primitive inside mesh
+ };
+
+ namespace isa
+ {
+
+ template<int M>
+ struct QuadMi : public embree::QuadMi<M>
+ {
+#if !defined(EMBREE_COMPACT_POLYS)
+ using embree::QuadMi<M>::v0_;
+ using embree::QuadMi<M>::v1_;
+ using embree::QuadMi<M>::v2_;
+ using embree::QuadMi<M>::v3_;
+#endif
+ using embree::QuadMi<M>::geomIDs;
+ using embree::QuadMi<M>::primIDs;
+ using embree::QuadMi<M>::geomID;
+ using embree::QuadMi<M>::primID;
+ using embree::QuadMi<M>::valid;
+
+ template<int vid>
+ __forceinline Vec3f getVertex(const size_t index, const Scene *const scene) const
+ {
+#if defined(EMBREE_COMPACT_POLYS)
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
+ const QuadMesh::Quad& quad = mesh->quad(primID(index));
+ return (Vec3f) mesh->vertices[0][quad.v[vid]];
+#else
+ const vuint<M>& v = getVertexOffset<vid>();
+ const float* vertices = scene->vertices[geomID(index)];
+ return (Vec3f&) vertices[v[index]];
+#endif
+ }
+
+ template<int vid, typename T>
+ __forceinline Vec3<T> getVertex(const size_t index, const Scene *const scene, const size_t itime, const T& ftime) const
+ {
+#if defined(EMBREE_COMPACT_POLYS)
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
+ const QuadMesh::Quad& quad = mesh->quad(primID(index));
+ const Vec3fa v0 = mesh->vertices[itime+0][quad.v[vid]];
+ const Vec3fa v1 = mesh->vertices[itime+1][quad.v[vid]];
+#else
+ const vuint<M>& v = getVertexOffset<vid>();
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
+ const float* vertices0 = (const float*) mesh->vertexPtr(0,itime+0);
+ const float* vertices1 = (const float*) mesh->vertexPtr(0,itime+1);
+ const Vec3fa v0 = Vec3fa::loadu(vertices0+v[index]);
+ const Vec3fa v1 = Vec3fa::loadu(vertices1+v[index]);
+#endif
+ const Vec3<T> p0(v0.x,v0.y,v0.z);
+ const Vec3<T> p1(v1.x,v1.y,v1.z);
+ return lerp(p0,p1,ftime);
+ }
+
+ template<int vid, int K, typename T>
+ __forceinline Vec3<T> getVertex(const vbool<K>& valid, const size_t index, const Scene *const scene, const vint<K>& itime, const T& ftime) const
+ {
+ Vec3<T> p0, p1;
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
+
+ for (size_t mask=movemask(valid), i=bsf(mask); mask; mask=btc(mask,i), i=bsf(mask))
+ {
+#if defined(EMBREE_COMPACT_POLYS)
+ const QuadMesh::Quad& quad = mesh->quad(primID(index));
+ const Vec3fa v0 = mesh->vertices[itime[i]+0][quad.v[vid]];
+ const Vec3fa v1 = mesh->vertices[itime[i]+1][quad.v[vid]];
+#else
+ const vuint<M>& v = getVertexOffset<vid>();
+ const float* vertices0 = (const float*) mesh->vertexPtr(0,itime[i]+0);
+ const float* vertices1 = (const float*) mesh->vertexPtr(0,itime[i]+1);
+ const Vec3fa v0 = Vec3fa::loadu(vertices0+v[index]);
+ const Vec3fa v1 = Vec3fa::loadu(vertices1+v[index]);
+#endif
+ p0.x[i] = v0.x; p0.y[i] = v0.y; p0.z[i] = v0.z;
+ p1.x[i] = v1.x; p1.y[i] = v1.y; p1.z[i] = v1.z;
+ }
+ return (T(one)-ftime)*p0 + ftime*p1;
+ }
+
+ struct Quad {
+ vfloat4 v0,v1,v2,v3;
+ };
+
+#if defined(EMBREE_COMPACT_POLYS)
+
+ __forceinline Quad loadQuad(const int i, const Scene* const scene) const
+ {
+ const unsigned int geomID = geomIDs[i];
+ const unsigned int primID = primIDs[i];
+ if (unlikely(primID == -1)) return { zero, zero, zero, zero };
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID);
+ const QuadMesh::Quad& quad = mesh->quad(primID);
+ const vfloat4 v0 = (vfloat4) mesh->vertices0[quad.v[0]];
+ const vfloat4 v1 = (vfloat4) mesh->vertices0[quad.v[1]];
+ const vfloat4 v2 = (vfloat4) mesh->vertices0[quad.v[2]];
+ const vfloat4 v3 = (vfloat4) mesh->vertices0[quad.v[3]];
+ return { v0, v1, v2, v3 };
+ }
+
+ __forceinline Quad loadQuad(const int i, const int itime, const Scene* const scene) const
+ {
+ const unsigned int geomID = geomIDs[i];
+ const unsigned int primID = primIDs[i];
+ if (unlikely(primID == -1)) return { zero, zero, zero, zero };
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID);
+ const QuadMesh::Quad& quad = mesh->quad(primID);
+ const vfloat4 v0 = (vfloat4) mesh->vertices[itime][quad.v[0]];
+ const vfloat4 v1 = (vfloat4) mesh->vertices[itime][quad.v[1]];
+ const vfloat4 v2 = (vfloat4) mesh->vertices[itime][quad.v[2]];
+ const vfloat4 v3 = (vfloat4) mesh->vertices[itime][quad.v[3]];
+ return { v0, v1, v2, v3 };
+ }
+
+#else
+
+ __forceinline Quad loadQuad(const int i, const Scene* const scene) const
+ {
+ const float* vertices = scene->vertices[geomID(i)];
+ const vfloat4 v0 = vfloat4::loadu(vertices + v0_[i]);
+ const vfloat4 v1 = vfloat4::loadu(vertices + v1_[i]);
+ const vfloat4 v2 = vfloat4::loadu(vertices + v2_[i]);
+ const vfloat4 v3 = vfloat4::loadu(vertices + v3_[i]);
+ return { v0, v1, v2, v3 };
+ }
+
+ __forceinline Quad loadQuad(const int i, const int itime, const Scene* const scene) const
+ {
+ const unsigned int geomID = geomIDs[i];
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID);
+ const float* vertices = (const float*) mesh->vertexPtr(0,itime);
+ const vfloat4 v0 = vfloat4::loadu(vertices + v0_[i]);
+ const vfloat4 v1 = vfloat4::loadu(vertices + v1_[i]);
+ const vfloat4 v2 = vfloat4::loadu(vertices + v2_[i]);
+ const vfloat4 v3 = vfloat4::loadu(vertices + v3_[i]);
+ return { v0, v1, v2, v3 };
+ }
+
+#endif
+
+ /* Gather the quads */
+ __forceinline void gather(Vec3vf<M>& p0,
+ Vec3vf<M>& p1,
+ Vec3vf<M>& p2,
+ Vec3vf<M>& p3,
+ const Scene *const scene) const;
+
+#if defined(__AVX512F__)
+ __forceinline void gather(Vec3vf16& p0,
+ Vec3vf16& p1,
+ Vec3vf16& p2,
+ Vec3vf16& p3,
+ const Scene *const scene) const;
+#endif
+
+ template<int K>
+#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 2000) // workaround for compiler bug in ICC 2019
+ __noinline
+#else
+ __forceinline
+#endif
+ void gather(const vbool<K>& valid,
+ Vec3vf<K>& p0,
+ Vec3vf<K>& p1,
+ Vec3vf<K>& p2,
+ Vec3vf<K>& p3,
+ const size_t index,
+ const Scene* const scene,
+ const vfloat<K>& time) const
+ {
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(index));
+
+ vfloat<K> ftime;
+ const vint<K> itime = mesh->timeSegment<K>(time, ftime);
+
+ const size_t first = bsf(movemask(valid));
+ if (likely(all(valid,itime[first] == itime)))
+ {
+ p0 = getVertex<0>(index, scene, itime[first], ftime);
+ p1 = getVertex<1>(index, scene, itime[first], ftime);
+ p2 = getVertex<2>(index, scene, itime[first], ftime);
+ p3 = getVertex<3>(index, scene, itime[first], ftime);
+ }
+ else
+ {
+ p0 = getVertex<0,K>(valid, index, scene, itime, ftime);
+ p1 = getVertex<1,K>(valid, index, scene, itime, ftime);
+ p2 = getVertex<2,K>(valid, index, scene, itime, ftime);
+ p3 = getVertex<3,K>(valid, index, scene, itime, ftime);
+ }
+ }
+
+ __forceinline void gather(Vec3vf<M>& p0,
+ Vec3vf<M>& p1,
+ Vec3vf<M>& p2,
+ Vec3vf<M>& p3,
+ const QuadMesh* mesh,
+ const Scene *const scene,
+ const int itime) const;
+
+ __forceinline void gather(Vec3vf<M>& p0,
+ Vec3vf<M>& p1,
+ Vec3vf<M>& p2,
+ Vec3vf<M>& p3,
+ const Scene *const scene,
+ const float time) const;
+
+ /* Updates the primitive */
+ __forceinline BBox3fa update(QuadMesh* mesh)
+ {
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<M; i++)
+ {
+ if (!valid(i)) break;
+ const unsigned primId = primID(i);
+ const QuadMesh::Quad& q = mesh->quad(primId);
+ const Vec3fa p0 = mesh->vertex(q.v[0]);
+ const Vec3fa p1 = mesh->vertex(q.v[1]);
+ const Vec3fa p2 = mesh->vertex(q.v[2]);
+ const Vec3fa p3 = mesh->vertex(q.v[3]);
+ bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2),BBox3fa(p3)));
+ }
+ return bounds;
+ }
+
+ private:
+#if !defined(EMBREE_COMPACT_POLYS)
+ template<int N> const vuint<M>& getVertexOffset() const;
+#endif
+ };
+
+#if !defined(EMBREE_COMPACT_POLYS)
+ template<> template<> __forceinline const vuint<4>& QuadMi<4>::getVertexOffset<0>() const { return v0_; }
+ template<> template<> __forceinline const vuint<4>& QuadMi<4>::getVertexOffset<1>() const { return v1_; }
+ template<> template<> __forceinline const vuint<4>& QuadMi<4>::getVertexOffset<2>() const { return v2_; }
+ template<> template<> __forceinline const vuint<4>& QuadMi<4>::getVertexOffset<3>() const { return v3_; }
+#endif
+
+ template<>
+ __forceinline void QuadMi<4>::gather(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ Vec3vf4& p3,
+ const Scene *const scene) const
+ {
+ prefetchL1(((char*)this)+0*64);
+ prefetchL1(((char*)this)+1*64);
+ const Quad tri0 = loadQuad(0,scene);
+ const Quad tri1 = loadQuad(1,scene);
+ const Quad tri2 = loadQuad(2,scene);
+ const Quad tri3 = loadQuad(3,scene);
+ transpose(tri0.v0,tri1.v0,tri2.v0,tri3.v0,p0.x,p0.y,p0.z);
+ transpose(tri0.v1,tri1.v1,tri2.v1,tri3.v1,p1.x,p1.y,p1.z);
+ transpose(tri0.v2,tri1.v2,tri2.v2,tri3.v2,p2.x,p2.y,p2.z);
+ transpose(tri0.v3,tri1.v3,tri2.v3,tri3.v3,p3.x,p3.y,p3.z);
+ }
+
+ template<>
+ __forceinline void QuadMi<4>::gather(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ Vec3vf4& p3,
+ const QuadMesh* mesh,
+ const Scene *const scene,
+ const int itime) const
+ {
+ // FIXME: for trianglei there all geometries are identical, is this the case here too?
+
+ const Quad tri0 = loadQuad(0,itime,scene);
+ const Quad tri1 = loadQuad(1,itime,scene);
+ const Quad tri2 = loadQuad(2,itime,scene);
+ const Quad tri3 = loadQuad(3,itime,scene);
+ transpose(tri0.v0,tri1.v0,tri2.v0,tri3.v0,p0.x,p0.y,p0.z);
+ transpose(tri0.v1,tri1.v1,tri2.v1,tri3.v1,p1.x,p1.y,p1.z);
+ transpose(tri0.v2,tri1.v2,tri2.v2,tri3.v2,p2.x,p2.y,p2.z);
+ transpose(tri0.v3,tri1.v3,tri2.v3,tri3.v3,p3.x,p3.y,p3.z);
+ }
+
+ template<>
+ __forceinline void QuadMi<4>::gather(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ Vec3vf4& p3,
+ const Scene *const scene,
+ const float time) const
+ {
+ const QuadMesh* mesh = scene->get<QuadMesh>(geomID(0)); // in mblur mode all geometries are identical
+
+ float ftime;
+ const int itime = mesh->timeSegment(time, ftime);
+
+ Vec3vf4 a0,a1,a2,a3; gather(a0,a1,a2,a3,mesh,scene,itime);
+ Vec3vf4 b0,b1,b2,b3; gather(b0,b1,b2,b3,mesh,scene,itime+1);
+ p0 = lerp(a0,b0,vfloat4(ftime));
+ p1 = lerp(a1,b1,vfloat4(ftime));
+ p2 = lerp(a2,b2,vfloat4(ftime));
+ p3 = lerp(a3,b3,vfloat4(ftime));
+ }
+ }
+
+ template<int M>
+ typename QuadMi<M>::Type QuadMi<M>::type;
+
+ typedef QuadMi<4> Quad4i;
+}
diff --git a/thirdparty/embree/kernels/geometry/quadi_intersector.h b/thirdparty/embree/kernels/geometry/quadi_intersector.h
new file mode 100644
index 0000000000..20a98c3406
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/quadi_intersector.h
@@ -0,0 +1,350 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "quadi.h"
+#include "quad_intersector_moeller.h"
+#include "quad_intersector_pluecker.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Intersects M quads with 1 ray */
+ template<int M, bool filter>
+ struct QuadMiIntersector1Moeller
+ {
+ typedef QuadMi<M> Primitive;
+ typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations;
+
+ /*! Intersect a ray with the M quads and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
+ pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of M quads. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
+ return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
+ }
+ };
+
+ /*! Intersects M triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct QuadMiIntersectorKMoeller
+ {
+ typedef QuadMi<M> Primitive;
+ typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ Scene* scene = context->scene;
+ for (size_t i=0; i<QuadMi<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene);
+ const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene);
+ const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene);
+ const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene);
+ pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ Scene* scene = context->scene;
+ vbool<K> valid0 = valid_i;
+ for (size_t i=0; i<QuadMi<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene);
+ const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene);
+ const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene);
+ const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene);
+ if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
+ break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
+ pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
+ return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+ };
+
+ /*! Intersects M quads with 1 ray */
+ template<int M, bool filter>
+ struct QuadMiIntersector1Pluecker
+ {
+ typedef QuadMi<M> Primitive;
+ typedef QuadMIntersector1Pluecker<M,filter> Precalculations;
+
+ /*! Intersect a ray with the M quads and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
+ pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of M quads. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
+ return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
+ }
+ };
+
+ /*! Intersects M triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct QuadMiIntersectorKPluecker
+ {
+ typedef QuadMi<M> Primitive;
+ typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ Scene* scene = context->scene;
+ for (size_t i=0; i<QuadMi<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene);
+ const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene);
+ const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene);
+ const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene);
+ pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ Scene* scene = context->scene;
+ vbool<K> valid0 = valid_i;
+ for (size_t i=0; i<QuadMi<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene);
+ const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene);
+ const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene);
+ const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene);
+ if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
+ break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
+ pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene);
+ return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+ };
+
+ /*! Intersects M motion blur quads with 1 ray */
+ template<int M, bool filter>
+ struct QuadMiMBIntersector1Moeller
+ {
+ typedef QuadMi<M> Primitive;
+ typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations;
+
+ /*! Intersect a ray with the M quads and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time());
+ pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of M quads. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time());
+ return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
+ }
+ };
+
+ /*! Intersects M motion blur quads with K rays. */
+ template<int M, int K, bool filter>
+ struct QuadMiMBIntersectorKMoeller
+ {
+ typedef QuadMi<M> Primitive;
+ typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations;
+
+ /*! Intersects K rays with M quads. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ for (size_t i=0; i<QuadMi<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ Vec3vf<K> v0,v1,v2,v3; quad.template gather<K>(valid_i,v0,v1,v2,v3,i,context->scene,ray.time());
+ pre.intersectK(valid_i,ray,v0,v1,v2,v3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M quads. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ vbool<K> valid0 = valid_i;
+ for (size_t i=0; i<QuadMi<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ Vec3vf<K> v0,v1,v2,v3; quad.template gather<K>(valid_i,v0,v1,v2,v3,i,context->scene,ray.time());
+ if (pre.intersectK(valid0,ray,v0,v1,v2,v3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
+ break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M quads and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]);
+ pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of the M quads. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]);
+ return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+ };
+
+ /*! Intersects M motion blur quads with 1 ray */
+ template<int M, bool filter>
+ struct QuadMiMBIntersector1Pluecker
+ {
+ typedef QuadMi<M> Primitive;
+ typedef QuadMIntersector1Pluecker<M,filter> Precalculations;
+
+ /*! Intersect a ray with the M quads and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time());
+ pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of M quads. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time());
+ return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
+ }
+ };
+
+ /*! Intersects M motion blur quads with K rays. */
+ template<int M, int K, bool filter>
+ struct QuadMiMBIntersectorKPluecker
+ {
+ typedef QuadMi<M> Primitive;
+ typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations;
+
+ /*! Intersects K rays with M quads. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ for (size_t i=0; i<QuadMi<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ Vec3vf<K> v0,v1,v2,v3; quad.template gather<K>(valid_i,v0,v1,v2,v3,i,context->scene,ray.time());
+ pre.intersectK(valid_i,ray,v0,v1,v2,v3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M quads. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ vbool<K> valid0 = valid_i;
+ for (size_t i=0; i<QuadMi<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ Vec3vf<K> v0,v1,v2,v3; quad.template gather<K>(valid_i,v0,v1,v2,v3,i,context->scene,ray.time());
+ if (pre.intersectK(valid0,ray,v0,v1,v2,v3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
+ break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M quads and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]);
+ pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of the M quads. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]);
+ return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID());
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/quadv.h b/thirdparty/embree/kernels/geometry/quadv.h
new file mode 100644
index 0000000000..2137356ff2
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/quadv.h
@@ -0,0 +1,165 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+
+namespace embree
+{
+ /* Stores the vertices of M quads in struct of array layout */
+ template <int M>
+ struct QuadMv
+ {
+ public:
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* Returns maximum number of stored quads */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
+
+ public:
+
+ /* Default constructor */
+ __forceinline QuadMv() {}
+
+ /* Construction from vertices and IDs */
+ __forceinline QuadMv(const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const vuint<M>& geomIDs, const vuint<M>& primIDs)
+ : v0(v0), v1(v1), v2(v2), v3(v3), geomIDs(geomIDs), primIDs(primIDs) {}
+
+ /* Returns a mask that tells which quads are valid */
+ __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); }
+
+ /* Returns true if the specified quad is valid */
+ __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; }
+
+ /* Returns the number of stored quads */
+ __forceinline size_t size() const { return bsf(~movemask(valid())); }
+
+ /* Returns the geometry IDs */
+ __forceinline vuint<M>& geomID() { return geomIDs; }
+ __forceinline const vuint<M>& geomID() const { return geomIDs; }
+ __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
+
+ /* Returns the primitive IDs */
+ __forceinline vuint<M> primID() { return primIDs; }
+ __forceinline const vuint<M> primID() const { return primIDs; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
+
+ /* Calculate the bounds of the quads */
+ __forceinline BBox3fa bounds() const
+ {
+ Vec3vf<M> lower = min(v0,v1,v2,v3);
+ Vec3vf<M> upper = max(v0,v1,v2,v3);
+ vbool<M> mask = valid();
+ lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
+ lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
+ lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
+ upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
+ upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
+ upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
+ return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
+ Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
+ }
+
+ /* Non temporal store */
+ __forceinline static void store_nt(QuadMv* dst, const QuadMv& src)
+ {
+ vfloat<M>::store_nt(&dst->v0.x,src.v0.x);
+ vfloat<M>::store_nt(&dst->v0.y,src.v0.y);
+ vfloat<M>::store_nt(&dst->v0.z,src.v0.z);
+ vfloat<M>::store_nt(&dst->v1.x,src.v1.x);
+ vfloat<M>::store_nt(&dst->v1.y,src.v1.y);
+ vfloat<M>::store_nt(&dst->v1.z,src.v1.z);
+ vfloat<M>::store_nt(&dst->v2.x,src.v2.x);
+ vfloat<M>::store_nt(&dst->v2.y,src.v2.y);
+ vfloat<M>::store_nt(&dst->v2.z,src.v2.z);
+ vfloat<M>::store_nt(&dst->v3.x,src.v3.x);
+ vfloat<M>::store_nt(&dst->v3.y,src.v3.y);
+ vfloat<M>::store_nt(&dst->v3.z,src.v3.z);
+ vuint<M>::store_nt(&dst->geomIDs,src.geomIDs);
+ vuint<M>::store_nt(&dst->primIDs,src.primIDs);
+ }
+
+ /* Fill quad from quad list */
+ __forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
+ {
+ vuint<M> vgeomID = -1, vprimID = -1;
+ Vec3vf<M> v0 = zero, v1 = zero, v2 = zero, v3 = zero;
+
+ for (size_t i=0; i<M && begin<end; i++, begin++)
+ {
+ const PrimRef& prim = prims[begin];
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const QuadMesh* __restrict__ const mesh = scene->get<QuadMesh>(geomID);
+ const QuadMesh::Quad& quad = mesh->quad(primID);
+ const Vec3fa& p0 = mesh->vertex(quad.v[0]);
+ const Vec3fa& p1 = mesh->vertex(quad.v[1]);
+ const Vec3fa& p2 = mesh->vertex(quad.v[2]);
+ const Vec3fa& p3 = mesh->vertex(quad.v[3]);
+ vgeomID [i] = geomID;
+ vprimID [i] = primID;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ v3.x[i] = p3.x; v3.y[i] = p3.y; v3.z[i] = p3.z;
+ }
+ QuadMv::store_nt(this,QuadMv(v0,v1,v2,v3,vgeomID,vprimID));
+ }
+
+ /* Updates the primitive */
+ __forceinline BBox3fa update(QuadMesh* mesh)
+ {
+ BBox3fa bounds = empty;
+ vuint<M> vgeomID = -1, vprimID = -1;
+ Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
+
+ for (size_t i=0; i<M; i++)
+ {
+ if (primID(i) == -1) break;
+ const unsigned geomId = geomID(i);
+ const unsigned primId = primID(i);
+ const QuadMesh::Quad& quad = mesh->quad(primId);
+ const Vec3fa p0 = mesh->vertex(quad.v[0]);
+ const Vec3fa p1 = mesh->vertex(quad.v[1]);
+ const Vec3fa p2 = mesh->vertex(quad.v[2]);
+ const Vec3fa p3 = mesh->vertex(quad.v[3]);
+ bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2),BBox3fa(p3)));
+ vgeomID [i] = geomId;
+ vprimID [i] = primId;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ v3.x[i] = p3.x; v3.y[i] = p3.y; v3.z[i] = p3.z;
+ }
+ new (this) QuadMv(v0,v1,v2,v3,vgeomID,vprimID);
+ return bounds;
+ }
+
+ public:
+ Vec3vf<M> v0; // 1st vertex of the quads
+ Vec3vf<M> v1; // 2nd vertex of the quads
+ Vec3vf<M> v2; // 3rd vertex of the quads
+ Vec3vf<M> v3; // 4rd vertex of the quads
+ private:
+ vuint<M> geomIDs; // geometry ID
+ vuint<M> primIDs; // primitive ID
+ };
+
+ template<int M>
+ typename QuadMv<M>::Type QuadMv<M>::type;
+
+ typedef QuadMv<4> Quad4v;
+}
diff --git a/thirdparty/embree/kernels/geometry/quadv_intersector.h b/thirdparty/embree/kernels/geometry/quadv_intersector.h
new file mode 100644
index 0000000000..9b28e05614
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/quadv_intersector.h
@@ -0,0 +1,181 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "quadv.h"
+#include "quad_intersector_moeller.h"
+#include "quad_intersector_pluecker.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Intersects M quads with 1 ray */
+ template<int M, bool filter>
+ struct QuadMvIntersector1Moeller
+ {
+ typedef QuadMv<M> Primitive;
+ typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations;
+
+ /*! Intersect a ray with the M quads and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersect(ray,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of M quads. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.occluded(ray,context, quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
+ }
+ };
+
+ /*! Intersects M triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct QuadMvIntersectorKMoeller
+ {
+ typedef QuadMv<M> Primitive;
+ typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMv<M>& quad)
+ {
+ for (size_t i=0; i<QuadMv<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i);
+ const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i);
+ const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i);
+ const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i);
+ pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMv<M>& quad)
+ {
+ vbool<K> valid0 = valid_i;
+
+ for (size_t i=0; i<QuadMv<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i);
+ const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i);
+ const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i);
+ const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i);
+ if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
+ break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersect1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.occluded1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
+ }
+ };
+
+ /*! Intersects M quads with 1 ray */
+ template<int M, bool filter>
+ struct QuadMvIntersector1Pluecker
+ {
+ typedef QuadMv<M> Primitive;
+ typedef QuadMIntersector1Pluecker<M,filter> Precalculations;
+
+ /*! Intersect a ray with the M quads and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersect(ray,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of M quads. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.occluded(ray,context, quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad);
+ }
+ };
+
+ /*! Intersects M triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct QuadMvIntersectorKPluecker
+ {
+ typedef QuadMv<M> Primitive;
+ typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMv<M>& quad)
+ {
+ for (size_t i=0; i<QuadMv<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i);
+ const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i);
+ const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i);
+ const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i);
+ pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMv<M>& quad)
+ {
+ vbool<K> valid0 = valid_i;
+
+ for (size_t i=0; i<QuadMv<M>::max_size(); i++)
+ {
+ if (!quad.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i);
+ const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i);
+ const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i);
+ const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i);
+ if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i)))
+ break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersect1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.occluded1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID());
+ }
+ };
+ }
+}
+
diff --git a/thirdparty/embree/kernels/geometry/roundline_intersector.h b/thirdparty/embree/kernels/geometry/roundline_intersector.h
new file mode 100644
index 0000000000..0e9393442b
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/roundline_intersector.h
@@ -0,0 +1,715 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "curve_intersector_precalculations.h"
+
+
+/*
+
+ This file implements the intersection of a ray with a round linear
+ curve segment. We define the geometry of such a round linear curve
+ segment from point p0 with radius r0 to point p1 with radius r1
+ using the cone that touches spheres p0/r0 and p1/r1 tangentially
+ plus the sphere p1/r1. We denote the tangentially touching cone from
+ p0/r0 to p1/r1 with cone(p0,r0,p1,r1) and the cone plus the ending
+ sphere with cone_sphere(p0,r0,p1,r1).
+
+ For multiple connected round linear curve segments this construction
+ yield a proper shape when viewed from the outside. Using the
+ following CSG we can also handle the interiour in most common cases:
+
+ round_linear_curve(pl,rl,p0,r0,p1,r1,pr,rr) =
+ cone_sphere(p0,r0,p1,r1) - cone(pl,rl,p0,r0) - cone(p1,r1,pr,rr)
+
+ Thus by subtracting the neighboring cone geometries, we cut away
+ parts of the center cone_sphere surface which lie inside the
+ combined curve. This approach works as long as geometry of the
+ current cone_sphere penetrates into direct neighbor segments only,
+ and not into segments further away.
+
+ To construct a cone that touches two spheres at p0 and p1 with r0
+ and r1, one has to increase the cone radius at r0 and r1 to obtain
+ larger radii w0 and w1, such that the infinite cone properly touches
+ the spheres. From the paper "Ray Tracing Generalized Tube
+ Primitives: Method and Applications"
+ (https://www.researchgate.net/publication/334378683_Ray_Tracing_Generalized_Tube_Primitives_Method_and_Applications)
+ one can derive the following equations for these increased
+ radii:
+
+ sr = 1.0f / sqrt(1-sqr(dr)/sqr(p1-p0))
+ w0 = sr*r0
+ w1 = sr*r1
+
+ Further, we want the cone to start where it touches the sphere at p0
+ and to end where it touches sphere at p1. Therefore, we need to
+ construct clipping locations y0 and y1 for the start and end of the
+ cone. These start and end clipping location of the cone can get
+ calculated as:
+
+ Y0 = - r0 * (r1-r0) / length(p1-p0)
+ Y1 = length(p1-p0) - r1 * (r1-r0) / length(p1-p0)
+
+ Where the cone starts a distance Y0 and ends a distance Y1 away of
+ point p0 along the cone center. The distance between Y1-Y0 can get
+ calculated as:
+
+ dY = length(p1-p0) - (r1-r0)^2 / length(p1-p0)
+
+ In the code below, Y will always be scaled by length(p1-p0) to
+ obtain y and you will find the terms r0*(r1-r0) and
+ (p1-p0)^2-(r1-r0)^2.
+
+ */
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct RoundLineIntersectorHitM
+ {
+ __forceinline RoundLineIntersectorHitM() {}
+
+ __forceinline RoundLineIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
+ : vu(u), vv(v), vt(t), vNg(Ng) {}
+
+ __forceinline void finalize() {}
+
+ __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
+ __forceinline float t (const size_t i) const { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
+
+ __forceinline Vec2vf<M> uv() const { return Vec2vf<M>(vu,vv); }
+ __forceinline vfloat<M> t () const { return vt; }
+ __forceinline Vec3vf<M> Ng() const { return vNg; }
+
+ public:
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+ };
+
+ namespace __roundline_internal
+ {
+ template<int M>
+ struct ConeGeometry
+ {
+ ConeGeometry (const Vec4vf<M>& a, const Vec4vf<M>& b)
+ : p0(a.xyz()), p1(b.xyz()), dP(p1-p0), dPdP(dot(dP,dP)), r0(a.w), sqr_r0(sqr(r0)), r1(b.w), dr(r1-r0), drdr(dr*dr), r0dr (r0*dr), g(dPdP - drdr) {}
+
+ /*
+
+ This function tests if a point is accepted by first cone
+ clipping plane.
+
+ First, we need to project the point onto the line p0->p1:
+
+ Y = (p-p0)*(p1-p0)/length(p1-p0)
+
+ This value y is the distance to the projection point from
+ p0. The clip distances are calculated as:
+
+ Y0 = - r0 * (r1-r0) / length(p1-p0)
+ Y1 = length(p1-p0) - r1 * (r1-r0) / length(p1-p0)
+
+ Thus to test if the point p is accepted by the first
+ clipping plane we need to test Y > Y0 and to test if it
+ is accepted by the second clipping plane we need to test
+ Y < Y1.
+
+ By multiplying the calculations with length(p1-p0) these
+ calculation can get simplied to:
+
+ y = (p-p0)*(p1-p0)
+ y0 = - r0 * (r1-r0)
+ y1 = (p1-p0)^2 - r1 * (r1-r0)
+
+ and the test y > y0 and y < y1.
+
+ */
+
+ __forceinline vbool<M> isClippedByPlane (const vbool<M>& valid_i, const Vec3vf<M>& p) const
+ {
+ const Vec3vf<M> p0p = p - p0;
+ const vfloat<M> y = dot(p0p,dP);
+ const vfloat<M> cap0 = -r0dr;
+ const vbool<M> inside_cone = y > cap0;
+ return valid_i & (p0.x != vfloat<M>(inf)) & (p1.x != vfloat<M>(inf)) & inside_cone;
+ }
+
+ /*
+
+ This function tests whether a point lies inside the capped cone
+ tangential to its ending spheres.
+
+ Therefore one has to check if the point is inside the
+ region defined by the cone clipping planes, which is
+ performed similar as in the previous function.
+
+ To perform the inside cone test we need to project the
+ point onto the line p0->p1:
+
+ dP = p1-p0
+ Y = (p-p0)*dP/length(dP)
+
+ This value Y is the distance to the projection point from
+ p0. To obtain a parameter value u going from 0 to 1 along
+ the line p0->p1 we calculate:
+
+ U = Y/length(dP)
+
+ The radii to use at points p0 and p1 are:
+
+ w0 = sr * r0
+ w1 = sr * r1
+ dw = w1-w0
+
+ Using these radii and u one can directly test if the point
+ lies inside the cone using the formula dP*dP < wy*wy with:
+
+ wy = w0 + u*dw
+ py = p0 + u*dP - p
+
+ By multiplying the calculations with length(p1-p0) and
+ inserting the definition of w can obtain simpler equations:
+
+ y = (p-p0)*dP
+ ry = r0 + y/dP^2 * dr
+ wy = sr*ry
+ py = p0 + y/dP^2*dP - p
+ y0 = - r0 * dr
+ y1 = dP^2 - r1 * dr
+
+ Thus for the in-cone test we get:
+
+ py^2 < wy^2
+ <=> py^2 < sr^2 * ry^2
+ <=> py^2 * ( dP^2 - dr^2 ) < dP^2 * ry^2
+
+ This can further get simplified to:
+
+ (p0-p)^2 * (dP^2 - dr^2) - y^2 < dP^2 * r0^2 + 2.0f*r0*dr*y;
+
+ */
+
+ __forceinline vbool<M> isInsideCappedCone (const vbool<M>& valid_i, const Vec3vf<M>& p) const
+ {
+ const Vec3vf<M> p0p = p - p0;
+ const vfloat<M> y = dot(p0p,dP);
+ const vfloat<M> cap0 = -r0dr+vfloat<M>(ulp);
+ const vfloat<M> cap1 = -r1*dr + dPdP;
+
+ vbool<M> inside_cone = valid_i & (p0.x != vfloat<M>(inf)) & (p1.x != vfloat<M>(inf));
+ inside_cone &= y > cap0; // start clipping plane
+ inside_cone &= y < cap1; // end clipping plane
+ inside_cone &= sqr(p0p)*g - sqr(y) < dPdP * sqr_r0 + 2.0f*r0dr*y; // in cone test
+ return inside_cone;
+ }
+
+ protected:
+ Vec3vf<M> p0;
+ Vec3vf<M> p1;
+ Vec3vf<M> dP;
+ vfloat<M> dPdP;
+ vfloat<M> r0;
+ vfloat<M> sqr_r0;
+ vfloat<M> r1;
+ vfloat<M> dr;
+ vfloat<M> drdr;
+ vfloat<M> r0dr;
+ vfloat<M> g;
+ };
+
+ template<int M>
+ struct ConeGeometryIntersector : public ConeGeometry<M>
+ {
+ using ConeGeometry<M>::p0;
+ using ConeGeometry<M>::p1;
+ using ConeGeometry<M>::dP;
+ using ConeGeometry<M>::dPdP;
+ using ConeGeometry<M>::r0;
+ using ConeGeometry<M>::sqr_r0;
+ using ConeGeometry<M>::r1;
+ using ConeGeometry<M>::dr;
+ using ConeGeometry<M>::r0dr;
+ using ConeGeometry<M>::g;
+
+ ConeGeometryIntersector (const Vec3vf<M>& ray_org, const Vec3vf<M>& ray_dir, const vfloat<M>& dOdO, const vfloat<M>& rcp_dOdO, const Vec4vf<M>& a, const Vec4vf<M>& b)
+ : ConeGeometry<M>(a,b), org(ray_org), O(ray_org-p0), dO(ray_dir), dOdO(dOdO), rcp_dOdO(rcp_dOdO), OdP(dot(dP,O)), dOdP(dot(dP,dO)), yp(OdP + r0dr) {}
+
+ /*
+
+ This function intersects a ray with a cone that touches a
+ start sphere p0/r0 and end sphere p1/r1.
+
+ To find this ray/cone intersections one could just
+ calculate radii w0 and w1 as described above and use a
+ standard ray/cone intersection routine with these
+ radii. However, it turns out that calculations can get
+ simplified when deriving a specialized ray/cone
+ intersection for this special case. We perform
+ calculations relative to the cone origin p0 and define:
+
+ O = ray_org - p0
+ dO = ray_dir
+ dP = p1-p0
+ dr = r1-r0
+ dw = w1-w0
+
+ For some t we can compute the potential hit point h = O + t*dO and
+ project it onto the cone vector dP to obtain u = (h*dP)/(dP*dP). In
+ case of an intersection, the squared distance from the hit point
+ projected onto the cone center line to the hit point should be equal
+ to the squared cone radius at u:
+
+ (u*dP - h)^2 = (w0 + u*dw)^2
+
+ Inserting the definition of h, u, w0, and dw into this formula, then
+ factoring out all terms, and sorting by t^2, t^1, and t^0 terms
+ yields a quadratic equation to solve.
+
+ Inserting u:
+ ( (h*dP)*dP/dP^2 - h )^2 = ( w0 + (h*dP)*dw/dP^2 )^2
+
+ Multiplying by dP^4:
+ ( (h*dP)*dP - h*dP^2 )^2 = ( w0*dP^2 + (h*dP)*dw )^2
+
+ Inserting w0 and dw:
+ ( (h*dP)*dP - h*dP^2 )^2 = ( r0*dP^2 + (h*dP)*dr )^2 / (1-dr^2/dP^2)
+ ( (h*dP)*dP - h*dP^2 )^2 *(dP^2 - dr^2) = dP^2 * ( r0*dP^2 + (h*dP)*dr )^2
+
+ Now one can insert the definition of h, factor out, and presort by t:
+ ( ((O + t*dO)*dP)*dP - (O + t*dO)*dP^2 )^2 *(dP^2 - dr^2) = dP^2 * ( r0*dP^2 + ((O + t*dO)*dP)*dr )^2
+ ( (O*dP)*dP-O*dP^2 + t*( (dO*dP)*dP - dO*dP^2 ) )^2 *(dP^2 - dr^2) = dP^2 * ( r0*dP^2 + (O*dP)*dr + t*(dO*dP)*dr )^2
+
+ Factoring out further and sorting by t^2, t^1 and t^0 yields:
+
+ 0 = t^2 * [ ((dO*dP)*dP - dO-dP^2)^2 * (dP^2 - dr^2) - dP^2*(dO*dP)^2*dr^2 ]
+ + 2*t^1 * [ ((O*dP)*dP - O*dP^2) * ((dO*dP)*dP - dO*dP^2) * (dP^2 - dr^2) - dP^2*(r0*dP^2 + (O*dP)*dr)*(dO*dP)*dr ]
+ + t^0 * [ ( (O*dP)*dP - O*dP^2)^2 * (dP^2-dr^2) - dP^2*(r0*dP^2 + (O*dP)*dr)^2 ]
+
+ This can be simplified to:
+
+ 0 = t^2 * [ (dP^2 - dr^2)*dO^2 - (dO*dP)^2 ]
+ + 2*t^1 * [ (dP^2 - dr^2)*(O*dO) - (dO*dP)*(O*dP + r0*dr) ]
+ + t^0 * [ (dP^2 - dr^2)*O^2 - (O*dP)^2 - r0^2*dP^2 - 2.0f*r0*dr*(O*dP) ]
+
+ Solving this quadratic equation yields the values for t at which the
+ ray intersects the cone.
+
+ */
+
+ __forceinline bool intersectCone(vbool<M>& valid, vfloat<M>& lower, vfloat<M>& upper)
+ {
+ /* return no hit by default */
+ lower = pos_inf;
+ upper = neg_inf;
+
+ /* compute quadratic equation A*t^2 + B*t + C = 0 */
+ const vfloat<M> OO = dot(O,O);
+ const vfloat<M> OdO = dot(dO,O);
+ const vfloat<M> A = g * dOdO - sqr(dOdP);
+ const vfloat<M> B = 2.0f * (g*OdO - dOdP*yp);
+ const vfloat<M> C = g*OO - sqr(OdP) - sqr_r0*dPdP - 2.0f*r0dr*OdP;
+
+ /* we miss the cone if determinant is smaller than zero */
+ const vfloat<M> D = B*B - 4.0f*A*C;
+ valid &= (D >= 0.0f & g > 0.0f); // if g <= 0 then the cone is inside a sphere end
+
+ /* When rays are parallel to the cone surface, then the
+ * ray may be inside or outside the cone. We just assume a
+ * miss in that case, which is fine as rays inside the
+ * cone would anyway hit the ending spheres in that
+ * case. */
+ valid &= abs(A) > min_rcp_input;
+ if (unlikely(none(valid))) {
+ return false;
+ }
+
+ /* compute distance to front and back hit */
+ const vfloat<M> Q = sqrt(D);
+ const vfloat<M> rcp_2A = rcp(2.0f*A);
+ t_cone_front = (-B-Q)*rcp_2A;
+ y_cone_front = yp + t_cone_front*dOdP;
+ lower = select( (y_cone_front > -(float)ulp) & (y_cone_front <= g) & (g > 0.0f), t_cone_front, vfloat<M>(pos_inf));
+#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
+ t_cone_back = (-B+Q)*rcp_2A;
+ y_cone_back = yp + t_cone_back *dOdP;
+ upper = select( (y_cone_back > -(float)ulp) & (y_cone_back <= g) & (g > 0.0f), t_cone_back , vfloat<M>(neg_inf));
+#endif
+ return true;
+ }
+
+ /*
+ This function intersects the ray with the end sphere at
+ p1. We already clip away hits that are inside the
+ neighboring cone segment.
+
+ */
+
+ __forceinline void intersectEndSphere(vbool<M>& valid,
+ const ConeGeometry<M>& coneR,
+ vfloat<M>& lower, vfloat<M>& upper)
+ {
+ /* calculate front and back hit with end sphere */
+ const Vec3vf<M> O1 = org - p1;
+ const vfloat<M> O1dO = dot(O1,dO);
+ const vfloat<M> h2 = sqr(O1dO) - dOdO*(sqr(O1) - sqr(r1));
+ const vfloat<M> rhs1 = select( h2 >= 0.0f, sqrt(h2), vfloat<M>(neg_inf) );
+
+ /* clip away front hit if it is inside next cone segment */
+ t_sph1_front = (-O1dO - rhs1)*rcp_dOdO;
+ const Vec3vf<M> hit_front = org + t_sph1_front*dO;
+ vbool<M> valid_sph1_front = h2 >= 0.0f & yp + t_sph1_front*dOdP > g & !coneR.isClippedByPlane (valid, hit_front);
+ lower = select(valid_sph1_front, t_sph1_front, vfloat<M>(pos_inf));
+
+#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
+ /* clip away back hit if it is inside next cone segment */
+ t_sph1_back = (-O1dO + rhs1)*rcp_dOdO;
+ const Vec3vf<M> hit_back = org + t_sph1_back*dO;
+ vbool<M> valid_sph1_back = h2 >= 0.0f & yp + t_sph1_back*dOdP > g & !coneR.isClippedByPlane (valid, hit_back);
+ upper = select(valid_sph1_back, t_sph1_back, vfloat<M>(neg_inf));
+#else
+ upper = vfloat<M>(neg_inf);
+#endif
+ }
+
+ __forceinline void intersectBeginSphere(const vbool<M>& valid,
+ vfloat<M>& lower, vfloat<M>& upper)
+ {
+ /* calculate front and back hit with end sphere */
+ const Vec3vf<M> O1 = org - p0;
+ const vfloat<M> O1dO = dot(O1,dO);
+ const vfloat<M> h2 = sqr(O1dO) - dOdO*(sqr(O1) - sqr(r0));
+ const vfloat<M> rhs1 = select( h2 >= 0.0f, sqrt(h2), vfloat<M>(neg_inf) );
+
+ /* clip away front hit if it is inside next cone segment */
+ t_sph0_front = (-O1dO - rhs1)*rcp_dOdO;
+ vbool<M> valid_sph1_front = valid & h2 >= 0.0f & yp + t_sph0_front*dOdP < 0;
+ lower = select(valid_sph1_front, t_sph0_front, vfloat<M>(pos_inf));
+
+#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
+ /* clip away back hit if it is inside next cone segment */
+ t_sph0_back = (-O1dO + rhs1)*rcp_dOdO;
+ vbool<M> valid_sph1_back = valid & h2 >= 0.0f & yp + t_sph0_back*dOdP < 0;
+ upper = select(valid_sph1_back, t_sph0_back, vfloat<M>(neg_inf));
+#else
+ upper = vfloat<M>(neg_inf);
+#endif
+ }
+
+ /*
+
+ This function calculates the geometry normal of some cone hit.
+
+ For a given hit point h (relative to p0) with a cone
+ starting at p0 with radius w0 and ending at p1 with
+ radius w1 one normally calculates the geometry normal by
+ first calculating the parmetric u hit location along the
+ cone:
+
+ u = dot(h,dP)/dP^2
+
+ Using this value one can now directly calculate the
+ geometry normal by bending the connection vector (h-u*dP)
+ from hit to projected hit with some cone dependent value
+ dw/sqrt(dP^2) * normalize(dP):
+
+ Ng = normalize(h-u*dP) - dw/length(dP) * normalize(dP)
+
+ The length of the vector (h-u*dP) can also get calculated
+ by interpolating the radii as w0+u*dw which yields:
+
+ Ng = (h-u*dP)/(w0+u*dw) - dw/dP^2 * dP
+
+ Multiplying with (w0+u*dw) yield a scaled Ng':
+
+ Ng' = (h-u*dP) - (w0+u*dw)*dw/dP^2*dP
+
+ Inserting the definition of w0 and dw and refactoring
+ yield a furhter scaled Ng'':
+
+ Ng'' = (dP^2 - dr^2) (h-q) - (r0+u*dr)*dr*dP
+
+ Now inserting the definition of u gives and multiplying
+ with the denominator yields:
+
+ Ng''' = (dP^2-dr^2)*(dP^2*h-dot(h,dP)*dP) - (dP^2*r0+dot(h,dP)*dr)*dr*dP
+
+ Factoring out, cancelling terms, dividing by dP^2, and
+ factoring again yields finally:
+
+ Ng'''' = (dP^2-dr^2)*h - dP*(dot(h,dP) + r0*dr)
+
+ */
+
+ __forceinline Vec3vf<M> Ng_cone(const vbool<M>& front_hit) const
+ {
+#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
+ const vfloat<M> y = select(front_hit, y_cone_front, y_cone_back);
+ const vfloat<M> t = select(front_hit, t_cone_front, t_cone_back);
+ const Vec3vf<M> h = O + t*dO;
+ return g*h-dP*y;
+#else
+ const Vec3vf<M> h = O + t_cone_front*dO;
+ return g*h-dP*y_cone_front;
+#endif
+ }
+
+ /* compute geometry normal of sphere hit as the difference
+ * vector from hit point to sphere center */
+
+ __forceinline Vec3vf<M> Ng_sphere1(const vbool<M>& front_hit) const
+ {
+#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
+ const vfloat<M> t_sph1 = select(front_hit, t_sph1_front, t_sph1_back);
+ return org+t_sph1*dO-p1;
+#else
+ return org+t_sph1_front*dO-p1;
+#endif
+ }
+
+ __forceinline Vec3vf<M> Ng_sphere0(const vbool<M>& front_hit) const
+ {
+#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
+ const vfloat<M> t_sph0 = select(front_hit, t_sph0_front, t_sph0_back);
+ return org+t_sph0*dO-p0;
+#else
+ return org+t_sph0_front*dO-p0;
+#endif
+ }
+
+ /*
+ This function calculates the u coordinate of a
+ hit. Therefore we use the hit distance y (which is zero
+ at the first cone clipping plane) and divide by distance
+ g between the clipping planes.
+
+ */
+
+ __forceinline vfloat<M> u_cone(const vbool<M>& front_hit) const
+ {
+#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
+ const vfloat<M> y = select(front_hit, y_cone_front, y_cone_back);
+ return clamp(y*rcp(g));
+#else
+ return clamp(y_cone_front*rcp(g));
+#endif
+ }
+
+ private:
+ Vec3vf<M> org;
+ Vec3vf<M> O;
+ Vec3vf<M> dO;
+ vfloat<M> dOdO;
+ vfloat<M> rcp_dOdO;
+ vfloat<M> OdP;
+ vfloat<M> dOdP;
+
+ /* for ray/cone intersection */
+ private:
+ vfloat<M> yp;
+ vfloat<M> y_cone_front;
+ vfloat<M> t_cone_front;
+#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
+ vfloat<M> y_cone_back;
+ vfloat<M> t_cone_back;
+#endif
+
+ /* for ray/sphere intersection */
+ private:
+ vfloat<M> t_sph1_front;
+ vfloat<M> t_sph0_front;
+#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
+ vfloat<M> t_sph1_back;
+ vfloat<M> t_sph0_back;
+#endif
+ };
+
+
+ template<int M, typename Epilog, typename ray_tfar_func>
+ static __forceinline bool intersectConeSphere(const vbool<M>& valid_i,
+ const Vec3vf<M>& ray_org_in, const Vec3vf<M>& ray_dir,
+ const vfloat<M>& ray_tnear, const ray_tfar_func& ray_tfar,
+ const Vec4vf<M>& v0, const Vec4vf<M>& v1,
+ const Vec4vf<M>& vL, const Vec4vf<M>& vR,
+ const Epilog& epilog)
+ {
+ vbool<M> valid = valid_i;
+
+ /* move ray origin closer to make calculations numerically stable */
+ const vfloat<M> dOdO = sqr(ray_dir);
+ const vfloat<M> rcp_dOdO = rcp(dOdO);
+ const Vec3vf<M> center = vfloat<M>(0.5f)*(v0.xyz()+v1.xyz());
+ const vfloat<M> dt = dot(center-ray_org_in,ray_dir)*rcp_dOdO;
+ const Vec3vf<M> ray_org = ray_org_in + dt*ray_dir;
+
+ /* intersect with cone from v0 to v1 */
+ vfloat<M> t_cone_lower, t_cone_upper;
+ ConeGeometryIntersector<M> cone (ray_org, ray_dir, dOdO, rcp_dOdO, v0, v1);
+ vbool<M> validCone = valid;
+ cone.intersectCone(validCone, t_cone_lower, t_cone_upper);
+
+ valid &= (validCone | (cone.g <= 0.0f)); // if cone is entirely in sphere end - check sphere
+ if (unlikely(none(valid)))
+ return false;
+
+ /* cone hits inside the neighboring capped cones are inside the geometry and thus ignored */
+ const ConeGeometry<M> coneL (v0, vL);
+ const ConeGeometry<M> coneR (v1, vR);
+#if !defined(EMBREE_BACKFACE_CULLING_CURVES)
+ const Vec3vf<M> hit_lower = ray_org + t_cone_lower*ray_dir;
+ const Vec3vf<M> hit_upper = ray_org + t_cone_upper*ray_dir;
+ t_cone_lower = select (!coneL.isInsideCappedCone (validCone, hit_lower) & !coneR.isInsideCappedCone (validCone, hit_lower), t_cone_lower, vfloat<M>(pos_inf));
+ t_cone_upper = select (!coneL.isInsideCappedCone (validCone, hit_upper) & !coneR.isInsideCappedCone (validCone, hit_upper), t_cone_upper, vfloat<M>(neg_inf));
+#endif
+
+ /* intersect ending sphere */
+ vfloat<M> t_sph1_lower, t_sph1_upper;
+ vfloat<M> t_sph0_lower = vfloat<M>(pos_inf);
+ vfloat<M> t_sph0_upper = vfloat<M>(neg_inf);
+ cone.intersectEndSphere(valid, coneR, t_sph1_lower, t_sph1_upper);
+
+ const vbool<M> isBeginPoint = valid & (vL[0] == vfloat<M>(pos_inf));
+ if (unlikely(any(isBeginPoint))) {
+ cone.intersectBeginSphere (isBeginPoint, t_sph0_lower, t_sph0_upper);
+ }
+
+ /* CSG union of cone and end sphere */
+ vfloat<M> t_sph_lower = min(t_sph0_lower, t_sph1_lower);
+ vfloat<M> t_cone_sphere_lower = min(t_cone_lower, t_sph_lower);
+#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
+ vfloat<M> t_sph_upper = max(t_sph0_upper, t_sph1_upper);
+ vfloat<M> t_cone_sphere_upper = max(t_cone_upper, t_sph_upper);
+
+ /* filter out hits that are not in tnear/tfar range */
+ const vbool<M> valid_lower = valid & ray_tnear <= dt+t_cone_sphere_lower & dt+t_cone_sphere_lower <= ray_tfar() & t_cone_sphere_lower != vfloat<M>(pos_inf);
+ const vbool<M> valid_upper = valid & ray_tnear <= dt+t_cone_sphere_upper & dt+t_cone_sphere_upper <= ray_tfar() & t_cone_sphere_upper != vfloat<M>(neg_inf);
+
+ /* check if there is a first hit */
+ const vbool<M> valid_first = valid_lower | valid_upper;
+ if (unlikely(none(valid_first)))
+ return false;
+
+ /* construct first hit */
+ const vfloat<M> t_first = select(valid_lower, t_cone_sphere_lower, t_cone_sphere_upper);
+ const vbool<M> cone_hit_first = t_first == t_cone_lower | t_first == t_cone_upper;
+ const vbool<M> sph0_hit_first = t_first == t_sph0_lower | t_first == t_sph0_upper;
+ const Vec3vf<M> Ng_first = select(cone_hit_first, cone.Ng_cone(valid_lower), select (sph0_hit_first, cone.Ng_sphere0(valid_lower), cone.Ng_sphere1(valid_lower)));
+ const vfloat<M> u_first = select(cone_hit_first, cone.u_cone(valid_lower), select (sph0_hit_first, vfloat<M>(zero), vfloat<M>(one)));
+
+ /* invoke intersection filter for first hit */
+ RoundLineIntersectorHitM<M> hit(u_first,zero,dt+t_first,Ng_first);
+ const bool is_hit_first = epilog(valid_first, hit);
+
+ /* check for possible second hits before potentially accepted hit */
+ const vfloat<M> t_second = t_cone_sphere_upper;
+ const vbool<M> valid_second = valid_lower & valid_upper & (dt+t_cone_sphere_upper <= ray_tfar());
+ if (unlikely(none(valid_second)))
+ return is_hit_first;
+
+ /* invoke intersection filter for second hit */
+ const vbool<M> cone_hit_second = t_second == t_cone_lower | t_second == t_cone_upper;
+ const vbool<M> sph0_hit_second = t_second == t_sph0_lower | t_second == t_sph0_upper;
+ const Vec3vf<M> Ng_second = select(cone_hit_second, cone.Ng_cone(false), select (sph0_hit_second, cone.Ng_sphere0(false), cone.Ng_sphere1(false)));
+ const vfloat<M> u_second = select(cone_hit_second, cone.u_cone(false), select (sph0_hit_second, vfloat<M>(zero), vfloat<M>(one)));
+
+ hit = RoundLineIntersectorHitM<M>(u_second,zero,dt+t_second,Ng_second);
+ const bool is_hit_second = epilog(valid_second, hit);
+
+ return is_hit_first | is_hit_second;
+#else
+ /* filter out hits that are not in tnear/tfar range */
+ const vbool<M> valid_lower = valid & ray_tnear <= dt+t_cone_sphere_lower & dt+t_cone_sphere_lower <= ray_tfar() & t_cone_sphere_lower != vfloat<M>(pos_inf);
+
+ /* check if there is a valid hit */
+ if (unlikely(none(valid_lower)))
+ return false;
+
+ /* construct first hit */
+ const vbool<M> cone_hit_first = t_cone_sphere_lower == t_cone_lower | t_cone_sphere_lower == t_cone_upper;
+ const vbool<M> sph0_hit_first = t_cone_sphere_lower == t_sph0_lower | t_cone_sphere_lower == t_sph0_upper;
+ const Vec3vf<M> Ng_first = select(cone_hit_first, cone.Ng_cone(valid_lower), select (sph0_hit_first, cone.Ng_sphere0(valid_lower), cone.Ng_sphere1(valid_lower)));
+ const vfloat<M> u_first = select(cone_hit_first, cone.u_cone(valid_lower), select (sph0_hit_first, vfloat<M>(zero), vfloat<M>(one)));
+
+ /* invoke intersection filter for first hit */
+ RoundLineIntersectorHitM<M> hit(u_first,zero,dt+t_cone_sphere_lower,Ng_first);
+ const bool is_hit_first = epilog(valid_lower, hit);
+
+ return is_hit_first;
+#endif
+ }
+
+ } // end namespace __roundline_internal
+
+ template<int M>
+ struct RoundLinearCurveIntersector1
+ {
+ typedef CurvePrecalculations1 Precalculations;
+
+ template<typename Ray>
+ struct ray_tfar {
+ Ray& ray;
+ __forceinline ray_tfar(Ray& ray) : ray(ray) {}
+ __forceinline vfloat<M> operator() () const { return ray.tfar; };
+ };
+
+ template<typename Ray, typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ Ray& ray,
+ IntersectContext* context,
+ const LineSegments* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
+ const Vec4vf<M>& vLi, const Vec4vf<M>& vRi,
+ const Epilog& epilog)
+ {
+ const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
+ const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
+ const vfloat<M> ray_tnear(ray.tnear());
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec4vf<M> v1 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v1i);
+ const Vec4vf<M> vL = enlargeRadiusToMinWidth<M>(context,geom,ray_org,vLi);
+ const Vec4vf<M> vR = enlargeRadiusToMinWidth<M>(context,geom,ray_org,vRi);
+ return __roundline_internal::intersectConeSphere<M>(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar<Ray>(ray),v0,v1,vL,vR,epilog);
+ }
+ };
+
+ template<int M, int K>
+ struct RoundLinearCurveIntersectorK
+ {
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ struct ray_tfar {
+ RayK<K>& ray;
+ size_t k;
+ __forceinline ray_tfar(RayK<K>& ray, size_t k) : ray(ray), k(k) {}
+ __forceinline vfloat<M> operator() () const { return ray.tfar[k]; };
+ };
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const LineSegments* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i, const Vec4vf<M>& v1i,
+ const Vec4vf<M>& vLi, const Vec4vf<M>& vRi,
+ const Epilog& epilog)
+ {
+ const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
+ const vfloat<M> ray_tnear = ray.tnear()[k];
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec4vf<M> v1 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v1i);
+ const Vec4vf<M> vL = enlargeRadiusToMinWidth<M>(context,geom,ray_org,vLi);
+ const Vec4vf<M> vR = enlargeRadiusToMinWidth<M>(context,geom,ray_org,vRi);
+ return __roundline_internal::intersectConeSphere<M>(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray,k),v0,v1,vL,vR,epilog);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/roundlinei_intersector.h b/thirdparty/embree/kernels/geometry/roundlinei_intersector.h
new file mode 100644
index 0000000000..29061d6475
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/roundlinei_intersector.h
@@ -0,0 +1,123 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "roundline_intersector.h"
+#include "intersector_epilog.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M, bool filter>
+ struct RoundLinearCurveMiIntersector1
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom);
+ const vbool<M> valid = line.valid();
+ RoundLinearCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Intersect1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom);
+ const vbool<M> valid = line.valid();
+ return RoundLinearCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Occluded1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
+ }
+ };
+
+ template<int M, bool filter>
+ struct RoundLinearCurveMiMBIntersector1
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time());
+ const vbool<M> valid = line.valid();
+ RoundLinearCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Intersect1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time());
+ const vbool<M> valid = line.valid();
+ return RoundLinearCurveIntersector1<M>::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Occluded1EpilogM<M,filter>(ray,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, line);
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct RoundLinearCurveMiIntersectorK
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom);
+ const vbool<M> valid = line.valid();
+ RoundLinearCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Intersect1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom);
+ const vbool<M> valid = line.valid();
+ return RoundLinearCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Occluded1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct RoundLinearCurveMiMBIntersectorK
+ {
+ typedef LineMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time()[k]);
+ const vbool<M> valid = line.valid();
+ RoundLinearCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Intersect1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& line)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const LineSegments* geom = context->scene->get<LineSegments>(line.geomID());
+ Vec4vf<M> v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time()[k]);
+ const vbool<M> valid = line.valid();
+ return RoundLinearCurveIntersectorK<M,K>::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Occluded1KEpilogM<M,K,filter>(ray,k,context,line.geomID(),line.primID()));
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/sphere_intersector.h b/thirdparty/embree/kernels/geometry/sphere_intersector.h
new file mode 100644
index 0000000000..2670f9762d
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/sphere_intersector.h
@@ -0,0 +1,183 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "../common/scene_points.h"
+#include "curve_intersector_precalculations.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct SphereIntersectorHitM
+ {
+ __forceinline SphereIntersectorHitM() {}
+
+ __forceinline SphereIntersectorHitM(const vfloat<M>& t, const Vec3vf<M>& Ng)
+ : vt(t), vNg(Ng) {}
+
+ __forceinline void finalize() {}
+
+ __forceinline Vec2f uv(const size_t i) const {
+ return Vec2f(0.0f, 0.0f);
+ }
+ __forceinline float t(const size_t i) const {
+ return vt[i];
+ }
+ __forceinline Vec3fa Ng(const size_t i) const {
+ return Vec3fa(vNg.x[i], vNg.y[i], vNg.z[i]);
+ }
+
+ public:
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+ };
+
+ template<int M>
+ struct SphereIntersector1
+ {
+ typedef CurvePrecalculations1 Precalculations;
+
+ template<typename Epilog>
+ static __forceinline bool intersect(
+ const vbool<M>& valid_i, Ray& ray,
+ const Precalculations& pre, const Vec4vf<M>& v0, const Epilog& epilog)
+ {
+ vbool<M> valid = valid_i;
+
+ const vfloat<M> rd2 = rcp(dot(ray.dir, ray.dir));
+ const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
+ const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
+ const Vec3vf<M> center = v0.xyz();
+ const vfloat<M> radius = v0.w;
+
+ const Vec3vf<M> c0 = center - ray_org;
+ const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
+ const Vec3vf<M> perp = c0 - projC0 * ray_dir;
+ const vfloat<M> l2 = dot(perp, perp);
+ const vfloat<M> r2 = radius * radius;
+ valid &= (l2 <= r2);
+ if (unlikely(none(valid)))
+ return false;
+
+ const vfloat<M> td = sqrt((r2 - l2) * rd2);
+ const vfloat<M> t_front = projC0 - td;
+ const vfloat<M> t_back = projC0 + td;
+
+ const vbool<M> valid_front = valid & (ray.tnear() <= t_front) & (t_front <= ray.tfar);
+ const vbool<M> valid_back = valid & (ray.tnear() <= t_back ) & (t_back <= ray.tfar);
+
+ /* check if there is a first hit */
+ const vbool<M> valid_first = valid_front | valid_back;
+ if (unlikely(none(valid_first)))
+ return false;
+
+ /* construct first hit */
+ const vfloat<M> td_front = -td;
+ const vfloat<M> td_back = +td;
+ const vfloat<M> t_first = select(valid_front, t_front, t_back);
+ const Vec3vf<M> Ng_first = select(valid_front, td_front, td_back) * ray_dir - perp;
+ SphereIntersectorHitM<M> hit(t_first, Ng_first);
+
+ /* invoke intersection filter for first hit */
+ const bool is_hit_first = epilog(valid_first, hit);
+
+ /* check for possible second hits before potentially accepted hit */
+ const vfloat<M> t_second = t_back;
+ const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar);
+ if (unlikely(none(valid_second)))
+ return is_hit_first;
+
+ /* invoke intersection filter for second hit */
+ const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
+ hit = SphereIntersectorHitM<M> (t_second, Ng_second);
+ const bool is_hit_second = epilog(valid_second, hit);
+
+ return is_hit_first | is_hit_second;
+ }
+
+ template<typename Epilog>
+ static __forceinline bool intersect(
+ const vbool<M>& valid_i, Ray& ray, IntersectContext* context, const Points* geom,
+ const Precalculations& pre, const Vec4vf<M>& v0i, const Epilog& epilog)
+ {
+ const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ return intersect(valid_i,ray,pre,v0,epilog);
+ }
+ };
+
+ template<int M, int K>
+ struct SphereIntersectorK
+ {
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid_i,
+ RayK<K>& ray, size_t k,
+ IntersectContext* context,
+ const Points* geom,
+ const Precalculations& pre,
+ const Vec4vf<M>& v0i,
+ const Epilog& epilog)
+ {
+ vbool<M> valid = valid_i;
+
+ const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
+ const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
+ const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
+
+ const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
+ const Vec3vf<M> center = v0.xyz();
+ const vfloat<M> radius = v0.w;
+
+ const Vec3vf<M> c0 = center - ray_org;
+ const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
+ const Vec3vf<M> perp = c0 - projC0 * ray_dir;
+ const vfloat<M> l2 = dot(perp, perp);
+ const vfloat<M> r2 = radius * radius;
+ valid &= (l2 <= r2);
+ if (unlikely(none(valid)))
+ return false;
+
+ const vfloat<M> td = sqrt((r2 - l2) * rd2);
+ const vfloat<M> t_front = projC0 - td;
+ const vfloat<M> t_back = projC0 + td;
+
+ const vbool<M> valid_front = valid & (ray.tnear()[k] <= t_front) & (t_front <= ray.tfar[k]);
+ const vbool<M> valid_back = valid & (ray.tnear()[k] <= t_back ) & (t_back <= ray.tfar[k]);
+
+ /* check if there is a first hit */
+ const vbool<M> valid_first = valid_front | valid_back;
+ if (unlikely(none(valid_first)))
+ return false;
+
+ /* construct first hit */
+ const vfloat<M> td_front = -td;
+ const vfloat<M> td_back = +td;
+ const vfloat<M> t_first = select(valid_front, t_front, t_back);
+ const Vec3vf<M> Ng_first = select(valid_front, td_front, td_back) * ray_dir - perp;
+ SphereIntersectorHitM<M> hit(t_first, Ng_first);
+
+ /* invoke intersection filter for first hit */
+ const bool is_hit_first = epilog(valid_first, hit);
+
+ /* check for possible second hits before potentially accepted hit */
+ const vfloat<M> t_second = t_back;
+ const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar[k]);
+ if (unlikely(none(valid_second)))
+ return is_hit_first;
+
+ /* invoke intersection filter for second hit */
+ const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
+ hit = SphereIntersectorHitM<M> (t_second, Ng_second);
+ const bool is_hit_second = epilog(valid_second, hit);
+
+ return is_hit_first | is_hit_second;
+ }
+ };
+ } // namespace isa
+} // namespace embree
diff --git a/thirdparty/embree/kernels/geometry/spherei_intersector.h b/thirdparty/embree/kernels/geometry/spherei_intersector.h
new file mode 100644
index 0000000000..7a0b428117
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/spherei_intersector.h
@@ -0,0 +1,156 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "intersector_epilog.h"
+#include "pointi.h"
+#include "sphere_intersector.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M, bool filter>
+ struct SphereMiIntersector1
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre,
+ RayHit& ray,
+ IntersectContext* context,
+ const Primitive& sphere)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(sphere.geomID());
+ Vec4vf<M> v0; sphere.gather(v0, geom);
+ const vbool<M> valid = sphere.valid();
+ SphereIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, Intersect1EpilogM<M, filter>(ray, context, sphere.geomID(), sphere.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre,
+ Ray& ray,
+ IntersectContext* context,
+ const Primitive& sphere)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(sphere.geomID());
+ Vec4vf<M> v0; sphere.gather(v0, geom);
+ const vbool<M> valid = sphere.valid();
+ return SphereIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, Occluded1EpilogM<M, filter>(ray, context, sphere.geomID(), sphere.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query,
+ PointQueryContext* context,
+ const Primitive& sphere)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, sphere);
+ }
+ };
+
+ template<int M, bool filter>
+ struct SphereMiMBIntersector1
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculations1 Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre,
+ RayHit& ray,
+ IntersectContext* context,
+ const Primitive& sphere)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(sphere.geomID());
+ Vec4vf<M> v0; sphere.gather(v0, geom, ray.time());
+ const vbool<M> valid = sphere.valid();
+ SphereIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, Intersect1EpilogM<M, filter>(ray, context, sphere.geomID(), sphere.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre,
+ Ray& ray,
+ IntersectContext* context,
+ const Primitive& sphere)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(sphere.geomID());
+ Vec4vf<M> v0; sphere.gather(v0, geom, ray.time());
+ const vbool<M> valid = sphere.valid();
+ return SphereIntersector1<M>::intersect(
+ valid, ray, context, geom, pre, v0, Occluded1EpilogM<M, filter>(ray, context, sphere.geomID(), sphere.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query,
+ PointQueryContext* context,
+ const Primitive& sphere)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, sphere);
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct SphereMiIntersectorK
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(
+ const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& sphere)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(sphere.geomID());
+ Vec4vf<M> v0; sphere.gather(v0, geom);
+ const vbool<M> valid = sphere.valid();
+ SphereIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0,
+ Intersect1KEpilogM<M, K, filter>(ray, k, context, sphere.geomID(), sphere.primID()));
+ }
+
+ static __forceinline bool occluded(
+ const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& sphere)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(sphere.geomID());
+ Vec4vf<M> v0; sphere.gather(v0, geom);
+ const vbool<M> valid = sphere.valid();
+ return SphereIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0,
+ Occluded1KEpilogM<M, K, filter>(ray, k, context, sphere.geomID(), sphere.primID()));
+ }
+ };
+
+ template<int M, int K, bool filter>
+ struct SphereMiMBIntersectorK
+ {
+ typedef PointMi<M> Primitive;
+ typedef CurvePrecalculationsK<K> Precalculations;
+
+ static __forceinline void intersect(
+ const Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& sphere)
+ {
+ STAT3(normal.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(sphere.geomID());
+ Vec4vf<M> v0; sphere.gather(v0, geom, ray.time()[k]);
+ const vbool<M> valid = sphere.valid();
+ SphereIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0,
+ Intersect1KEpilogM<M, K, filter>(ray, k, context, sphere.geomID(), sphere.primID()));
+ }
+
+ static __forceinline bool occluded(
+ const Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& sphere)
+ {
+ STAT3(shadow.trav_prims, 1, 1, 1);
+ const Points* geom = context->scene->get<Points>(sphere.geomID());
+ Vec4vf<M> v0; sphere.gather(v0, geom, ray.time()[k]);
+ const vbool<M> valid = sphere.valid();
+ return SphereIntersectorK<M, K>::intersect(
+ valid, ray, k, context, geom, pre, v0,
+ Occluded1KEpilogM<M, K, filter>(ray, k, context, sphere.geomID(), sphere.primID()));
+ }
+ };
+ } // namespace isa
+} // namespace embree
diff --git a/thirdparty/embree/kernels/geometry/subdivpatch1.h b/thirdparty/embree/kernels/geometry/subdivpatch1.h
new file mode 100644
index 0000000000..ae0d4e2616
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/subdivpatch1.h
@@ -0,0 +1,38 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../geometry/primitive.h"
+#include "../subdiv/subdivpatch1base.h"
+
+namespace embree
+{
+
+ struct __aligned(64) SubdivPatch1 : public SubdivPatch1Base
+ {
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+
+ static Type type;
+
+ public:
+
+ /*! constructor for cached subdiv patch */
+ SubdivPatch1 (const unsigned int gID,
+ const unsigned int pID,
+ const unsigned int subPatch,
+ const SubdivMesh *const mesh,
+ const size_t time,
+ const Vec2f uv[4],
+ const float edge_level[4],
+ const int subdiv[4],
+ const int simd_width)
+ : SubdivPatch1Base(gID,pID,subPatch,mesh,time,uv,edge_level,subdiv,simd_width) {}
+ };
+}
diff --git a/thirdparty/embree/kernels/geometry/subdivpatch1_intersector.h b/thirdparty/embree/kernels/geometry/subdivpatch1_intersector.h
new file mode 100644
index 0000000000..b4b15a1210
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/subdivpatch1_intersector.h
@@ -0,0 +1,237 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "subdivpatch1.h"
+#include "grid_soa.h"
+#include "grid_soa_intersector1.h"
+#include "grid_soa_intersector_packet.h"
+#include "../common/ray.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename T>
+ class SubdivPatch1Precalculations : public T
+ {
+ public:
+ __forceinline SubdivPatch1Precalculations (const Ray& ray, const void* ptr)
+ : T(ray,ptr) {}
+ };
+
+ template<int K, typename T>
+ class SubdivPatch1PrecalculationsK : public T
+ {
+ public:
+ __forceinline SubdivPatch1PrecalculationsK (const vbool<K>& valid, RayK<K>& ray)
+ : T(valid,ray) {}
+ };
+
+ class SubdivPatch1Intersector1
+ {
+ public:
+ typedef GridSOA Primitive;
+ typedef SubdivPatch1Precalculations<GridSOAIntersector1::Precalculations> Precalculations;
+
+ static __forceinline bool processLazyNode(Precalculations& pre, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ lazy_node = prim->root(0);
+ pre.grid = (Primitive*)prim;
+ return false;
+ }
+
+ /*! Intersect a ray with the primitive. */
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) GridSOAIntersector1::intersect(pre,ray,context,prim,lazy_node);
+ else processLazyNode(pre,context,prim,lazy_node);
+ }
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node) {
+ intersect(This,pre,ray,context,prim,ty,tray,lazy_node);
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) return GridSOAIntersector1::occluded(pre,ray,context,prim,lazy_node);
+ else return processLazyNode(pre,context,prim,lazy_node);
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node) {
+ return occluded(This,pre,ray,context,prim,ty,tray,lazy_node);
+ }
+
+ template<int N>
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t ty, const TravPointQuery<N> &tquery, size_t& lazy_node)
+ {
+ // TODO: PointQuery implement
+ assert(false && "not implemented");
+ return false;
+ }
+
+ template<int N>
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravPointQuery<N> &tquery, size_t& lazy_node) {
+ return pointQuery(This,query,context,prim,ty,tquery,lazy_node);
+ }
+ };
+
+ class SubdivPatch1MBIntersector1
+ {
+ public:
+ typedef SubdivPatch1 Primitive;
+ typedef GridSOAMBIntersector1::Precalculations Precalculations;
+
+ static __forceinline bool processLazyNode(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim_i, size_t& lazy_node)
+ {
+ Primitive* prim = (Primitive*) prim_i;
+ GridSOA* grid = nullptr;
+ grid = (GridSOA*) prim->root_ref.get();
+ pre.itime = getTimeSegment(ray.time(), float(grid->time_steps-1), pre.ftime);
+ lazy_node = grid->root(pre.itime);
+ pre.grid = grid;
+ return false;
+ }
+
+ /*! Intersect a ray with the primitive. */
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) GridSOAMBIntersector1::intersect(pre,ray,context,prim,lazy_node);
+ else processLazyNode(pre,ray,context,prim,lazy_node);
+ }
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node) {
+ intersect(This,pre,ray,context,prim,ty,tray,lazy_node);
+ }
+
+ /*! Test if the ray is occluded by the primitive */
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) return GridSOAMBIntersector1::occluded(pre,ray,context,prim,lazy_node);
+ else return processLazyNode(pre,ray,context,prim,lazy_node);
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node) {
+ return occluded(This,pre,ray,context,prim,ty,tray,lazy_node);
+ }
+
+ template<int N>
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t ty, const TravPointQuery<N> &tquery, size_t& lazy_node)
+ {
+ // TODO: PointQuery implement
+ assert(false && "not implemented");
+ return false;
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravPointQuery<N> &tquery, size_t& lazy_node) {
+ return pointQuery(This,query,context,prim,ty,tquery,lazy_node);
+ }
+ };
+
+ template <int K>
+ struct SubdivPatch1IntersectorK
+ {
+ typedef GridSOA Primitive;
+ typedef SubdivPatch1PrecalculationsK<K,typename GridSOAIntersectorK<K>::Precalculations> Precalculations;
+
+ static __forceinline bool processLazyNode(Precalculations& pre, IntersectContext* context, const Primitive* prim, size_t& lazy_node)
+ {
+ lazy_node = prim->root(0);
+ pre.grid = (Primitive*)prim;
+ return false;
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) GridSOAIntersectorK<K>::intersect(valid,pre,ray,context,prim,lazy_node);
+ else processLazyNode(pre,context,prim,lazy_node);
+ }
+
+ template<bool robust>
+ static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) return GridSOAIntersectorK<K>::occluded(valid,pre,ray,context,prim,lazy_node);
+ else return processLazyNode(pre,context,prim,lazy_node);
+ }
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) GridSOAIntersectorK<K>::intersect(pre,ray,k,context,prim,lazy_node);
+ else processLazyNode(pre,context,prim,lazy_node);
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) return GridSOAIntersectorK<K>::occluded(pre,ray,k,context,prim,lazy_node);
+ else return processLazyNode(pre,context,prim,lazy_node);
+ }
+ };
+
+ typedef SubdivPatch1IntersectorK<4> SubdivPatch1Intersector4;
+ typedef SubdivPatch1IntersectorK<8> SubdivPatch1Intersector8;
+ typedef SubdivPatch1IntersectorK<16> SubdivPatch1Intersector16;
+
+ template <int K>
+ struct SubdivPatch1MBIntersectorK
+ {
+ typedef SubdivPatch1 Primitive;
+ //typedef GridSOAMBIntersectorK<K>::Precalculations Precalculations;
+ typedef SubdivPatch1PrecalculationsK<K,typename GridSOAMBIntersectorK<K>::Precalculations> Precalculations;
+
+ static __forceinline bool processLazyNode(Precalculations& pre, IntersectContext* context, const Primitive* prim_i, size_t& lazy_node)
+ {
+ Primitive* prim = (Primitive*) prim_i;
+ GridSOA* grid = (GridSOA*) prim->root_ref.get();
+ lazy_node = grid->troot;
+ pre.grid = grid;
+ return false;
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) GridSOAMBIntersectorK<K>::intersect(valid,pre,ray,context,prim,lazy_node);
+ else processLazyNode(pre,context,prim,lazy_node);
+ }
+
+ template<bool robust>
+ static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) return GridSOAMBIntersectorK<K>::occluded(valid,pre,ray,context,prim,lazy_node);
+ else return processLazyNode(pre,context,prim,lazy_node);
+ }
+
+ template<int N, bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) GridSOAMBIntersectorK<K>::intersect(pre,ray,k,context,prim,lazy_node);
+ else processLazyNode(pre,context,prim,lazy_node);
+ }
+
+ template<int N, bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ if (likely(ty == 0)) return GridSOAMBIntersectorK<K>::occluded(pre,ray,k,context,prim,lazy_node);
+ else return processLazyNode(pre,context,prim,lazy_node);
+ }
+ };
+
+ typedef SubdivPatch1MBIntersectorK<4> SubdivPatch1MBIntersector4;
+ typedef SubdivPatch1MBIntersectorK<8> SubdivPatch1MBIntersector8;
+ typedef SubdivPatch1MBIntersectorK<16> SubdivPatch1MBIntersector16;
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/subgrid.h b/thirdparty/embree/kernels/geometry/subgrid.h
new file mode 100644
index 0000000000..ce54421cab
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/subgrid.h
@@ -0,0 +1,517 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/ray.h"
+#include "../common/scene_grid_mesh.h"
+#include "../bvh/bvh.h"
+
+namespace embree
+{
+ /* Stores M quads from an indexed face set */
+ struct SubGrid
+ {
+ /* Virtual interface to query information about the quad type */
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* primitive supports multiple time segments */
+ static const bool singleTimeSegment = false;
+
+ /* Returns maximum number of stored quads */
+ static __forceinline size_t max_size() { return 1; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
+
+ public:
+
+ /* Default constructor */
+ __forceinline SubGrid() { }
+
+ /* Construction from vertices and IDs */
+ __forceinline SubGrid(const unsigned int x,
+ const unsigned int y,
+ const unsigned int geomID,
+ const unsigned int primID)
+ : _x(x), _y(y), _geomID(geomID), _primID(primID)
+ {
+ }
+
+ __forceinline bool invalid3x3X() const { return (unsigned int)_x & (1<<15); }
+ __forceinline bool invalid3x3Y() const { return (unsigned int)_y & (1<<15); }
+
+ /* Gather the quads */
+ __forceinline void gather(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ Vec3vf4& p3,
+ const GridMesh* const mesh,
+ const GridMesh::Grid &g) const
+ {
+ /* first quad always valid */
+ const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset;
+ const size_t vtxID01 = vtxID00 + 1;
+ const vfloat4 vtx00 = vfloat4::loadu(mesh->vertexPtr(vtxID00));
+ const vfloat4 vtx01 = vfloat4::loadu(mesh->vertexPtr(vtxID01));
+ const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
+ const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
+ const vfloat4 vtx10 = vfloat4::loadu(mesh->vertexPtr(vtxID10));
+ const vfloat4 vtx11 = vfloat4::loadu(mesh->vertexPtr(vtxID11));
+
+ /* deltaX => vtx02, vtx12 */
+ const size_t deltaX = invalid3x3X() ? 0 : 1;
+ const size_t vtxID02 = vtxID01 + deltaX;
+ const vfloat4 vtx02 = vfloat4::loadu(mesh->vertexPtr(vtxID02));
+ const size_t vtxID12 = vtxID11 + deltaX;
+ const vfloat4 vtx12 = vfloat4::loadu(mesh->vertexPtr(vtxID12));
+
+ /* deltaY => vtx20, vtx21 */
+ const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset;
+ const size_t vtxID20 = vtxID10 + deltaY;
+ const size_t vtxID21 = vtxID11 + deltaY;
+ const vfloat4 vtx20 = vfloat4::loadu(mesh->vertexPtr(vtxID20));
+ const vfloat4 vtx21 = vfloat4::loadu(mesh->vertexPtr(vtxID21));
+
+ /* deltaX/deltaY => vtx22 */
+ const size_t vtxID22 = vtxID11 + deltaX + deltaY;
+ const vfloat4 vtx22 = vfloat4::loadu(mesh->vertexPtr(vtxID22));
+
+ transpose(vtx00,vtx01,vtx11,vtx10,p0.x,p0.y,p0.z);
+ transpose(vtx01,vtx02,vtx12,vtx11,p1.x,p1.y,p1.z);
+ transpose(vtx11,vtx12,vtx22,vtx21,p2.x,p2.y,p2.z);
+ transpose(vtx10,vtx11,vtx21,vtx20,p3.x,p3.y,p3.z);
+ }
+
+ template<typename T>
+ __forceinline vfloat4 getVertexMB(const GridMesh* const mesh, const size_t offset, const size_t itime, const float ftime) const
+ {
+ const T v0 = T::loadu(mesh->vertexPtr(offset,itime+0));
+ const T v1 = T::loadu(mesh->vertexPtr(offset,itime+1));
+ return lerp(v0,v1,ftime);
+ }
+
+ /* Gather the quads */
+ __forceinline void gatherMB(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ Vec3vf4& p3,
+ const GridMesh* const mesh,
+ const GridMesh::Grid &g,
+ const size_t itime,
+ const float ftime) const
+ {
+ /* first quad always valid */
+ const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset;
+ const size_t vtxID01 = vtxID00 + 1;
+ const vfloat4 vtx00 = getVertexMB<vfloat4>(mesh,vtxID00,itime,ftime);
+ const vfloat4 vtx01 = getVertexMB<vfloat4>(mesh,vtxID01,itime,ftime);
+ const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
+ const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
+ const vfloat4 vtx10 = getVertexMB<vfloat4>(mesh,vtxID10,itime,ftime);
+ const vfloat4 vtx11 = getVertexMB<vfloat4>(mesh,vtxID11,itime,ftime);
+
+ /* deltaX => vtx02, vtx12 */
+ const size_t deltaX = invalid3x3X() ? 0 : 1;
+ const size_t vtxID02 = vtxID01 + deltaX;
+ const vfloat4 vtx02 = getVertexMB<vfloat4>(mesh,vtxID02,itime,ftime);
+ const size_t vtxID12 = vtxID11 + deltaX;
+ const vfloat4 vtx12 = getVertexMB<vfloat4>(mesh,vtxID12,itime,ftime);
+
+ /* deltaY => vtx20, vtx21 */
+ const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset;
+ const size_t vtxID20 = vtxID10 + deltaY;
+ const size_t vtxID21 = vtxID11 + deltaY;
+ const vfloat4 vtx20 = getVertexMB<vfloat4>(mesh,vtxID20,itime,ftime);
+ const vfloat4 vtx21 = getVertexMB<vfloat4>(mesh,vtxID21,itime,ftime);
+
+ /* deltaX/deltaY => vtx22 */
+ const size_t vtxID22 = vtxID11 + deltaX + deltaY;
+ const vfloat4 vtx22 = getVertexMB<vfloat4>(mesh,vtxID22,itime,ftime);
+
+ transpose(vtx00,vtx01,vtx11,vtx10,p0.x,p0.y,p0.z);
+ transpose(vtx01,vtx02,vtx12,vtx11,p1.x,p1.y,p1.z);
+ transpose(vtx11,vtx12,vtx22,vtx21,p2.x,p2.y,p2.z);
+ transpose(vtx10,vtx11,vtx21,vtx20,p3.x,p3.y,p3.z);
+ }
+
+
+
+ /* Gather the quads */
+ __forceinline void gather(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ Vec3vf4& p3,
+ const Scene *const scene) const
+ {
+ const GridMesh* const mesh = scene->get<GridMesh>(geomID());
+ const GridMesh::Grid &g = mesh->grid(primID());
+ gather(p0,p1,p2,p3,mesh,g);
+ }
+
+ /* Gather the quads in the motion blur case */
+ __forceinline void gatherMB(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ Vec3vf4& p3,
+ const Scene *const scene,
+ const size_t itime,
+ const float ftime) const
+ {
+ const GridMesh* const mesh = scene->get<GridMesh>(geomID());
+ const GridMesh::Grid &g = mesh->grid(primID());
+ gatherMB(p0,p1,p2,p3,mesh,g,itime,ftime);
+ }
+
+ /* Gather the quads */
+ __forceinline void gather(Vec3fa vtx[16], const Scene *const scene) const
+ {
+ const GridMesh* mesh = scene->get<GridMesh>(geomID());
+ const GridMesh::Grid &g = mesh->grid(primID());
+
+ /* first quad always valid */
+ const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset;
+ const size_t vtxID01 = vtxID00 + 1;
+ const Vec3fa vtx00 = Vec3fa::loadu(mesh->vertexPtr(vtxID00));
+ const Vec3fa vtx01 = Vec3fa::loadu(mesh->vertexPtr(vtxID01));
+ const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
+ const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
+ const Vec3fa vtx10 = Vec3fa::loadu(mesh->vertexPtr(vtxID10));
+ const Vec3fa vtx11 = Vec3fa::loadu(mesh->vertexPtr(vtxID11));
+
+ /* deltaX => vtx02, vtx12 */
+ const size_t deltaX = invalid3x3X() ? 0 : 1;
+ const size_t vtxID02 = vtxID01 + deltaX;
+ const Vec3fa vtx02 = Vec3fa::loadu(mesh->vertexPtr(vtxID02));
+ const size_t vtxID12 = vtxID11 + deltaX;
+ const Vec3fa vtx12 = Vec3fa::loadu(mesh->vertexPtr(vtxID12));
+
+ /* deltaY => vtx20, vtx21 */
+ const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset;
+ const size_t vtxID20 = vtxID10 + deltaY;
+ const size_t vtxID21 = vtxID11 + deltaY;
+ const Vec3fa vtx20 = Vec3fa::loadu(mesh->vertexPtr(vtxID20));
+ const Vec3fa vtx21 = Vec3fa::loadu(mesh->vertexPtr(vtxID21));
+
+ /* deltaX/deltaY => vtx22 */
+ const size_t vtxID22 = vtxID11 + deltaX + deltaY;
+ const Vec3fa vtx22 = Vec3fa::loadu(mesh->vertexPtr(vtxID22));
+
+ vtx[ 0] = vtx00; vtx[ 1] = vtx01; vtx[ 2] = vtx11; vtx[ 3] = vtx10;
+ vtx[ 4] = vtx01; vtx[ 5] = vtx02; vtx[ 6] = vtx12; vtx[ 7] = vtx11;
+ vtx[ 8] = vtx10; vtx[ 9] = vtx11; vtx[10] = vtx21; vtx[11] = vtx20;
+ vtx[12] = vtx11; vtx[13] = vtx12; vtx[14] = vtx22; vtx[15] = vtx21;
+ }
+
+ /* Gather the quads */
+ __forceinline void gatherMB(vfloat4 vtx[16], const Scene *const scene, const size_t itime, const float ftime) const
+ {
+ const GridMesh* mesh = scene->get<GridMesh>(geomID());
+ const GridMesh::Grid &g = mesh->grid(primID());
+
+ /* first quad always valid */
+ const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset;
+ const size_t vtxID01 = vtxID00 + 1;
+ const vfloat4 vtx00 = getVertexMB<vfloat4>(mesh,vtxID00,itime,ftime);
+ const vfloat4 vtx01 = getVertexMB<vfloat4>(mesh,vtxID01,itime,ftime);
+ const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
+ const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
+ const vfloat4 vtx10 = getVertexMB<vfloat4>(mesh,vtxID10,itime,ftime);
+ const vfloat4 vtx11 = getVertexMB<vfloat4>(mesh,vtxID11,itime,ftime);
+
+ /* deltaX => vtx02, vtx12 */
+ const size_t deltaX = invalid3x3X() ? 0 : 1;
+ const size_t vtxID02 = vtxID01 + deltaX;
+ const vfloat4 vtx02 = getVertexMB<vfloat4>(mesh,vtxID02,itime,ftime);
+ const size_t vtxID12 = vtxID11 + deltaX;
+ const vfloat4 vtx12 = getVertexMB<vfloat4>(mesh,vtxID12,itime,ftime);
+
+ /* deltaY => vtx20, vtx21 */
+ const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset;
+ const size_t vtxID20 = vtxID10 + deltaY;
+ const size_t vtxID21 = vtxID11 + deltaY;
+ const vfloat4 vtx20 = getVertexMB<vfloat4>(mesh,vtxID20,itime,ftime);
+ const vfloat4 vtx21 = getVertexMB<vfloat4>(mesh,vtxID21,itime,ftime);
+
+ /* deltaX/deltaY => vtx22 */
+ const size_t vtxID22 = vtxID11 + deltaX + deltaY;
+ const vfloat4 vtx22 = getVertexMB<vfloat4>(mesh,vtxID22,itime,ftime);
+
+ vtx[ 0] = vtx00; vtx[ 1] = vtx01; vtx[ 2] = vtx11; vtx[ 3] = vtx10;
+ vtx[ 4] = vtx01; vtx[ 5] = vtx02; vtx[ 6] = vtx12; vtx[ 7] = vtx11;
+ vtx[ 8] = vtx10; vtx[ 9] = vtx11; vtx[10] = vtx21; vtx[11] = vtx20;
+ vtx[12] = vtx11; vtx[13] = vtx12; vtx[14] = vtx22; vtx[15] = vtx21;
+ }
+
+
+ /* Calculate the bounds of the subgrid */
+ __forceinline const BBox3fa bounds(const Scene *const scene, const size_t itime=0) const
+ {
+ BBox3fa bounds = empty;
+ FATAL("not implemented yet");
+ return bounds;
+ }
+
+ /* Calculate the linear bounds of the primitive */
+ __forceinline LBBox3fa linearBounds(const Scene* const scene, const size_t itime)
+ {
+ return LBBox3fa(bounds(scene,itime+0),bounds(scene,itime+1));
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps)
+ {
+ LBBox3fa allBounds = empty;
+ FATAL("not implemented yet");
+ return allBounds;
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range)
+ {
+ LBBox3fa allBounds = empty;
+ FATAL("not implemented yet");
+ return allBounds;
+ }
+
+
+ friend embree_ostream operator<<(embree_ostream cout, const SubGrid& sg) {
+ return cout << "SubGrid " << " ( x " << sg.x() << ", y = " << sg.y() << ", geomID = " << sg.geomID() << ", primID = " << sg.primID() << " )";
+ }
+
+ __forceinline unsigned int geomID() const { return _geomID; }
+ __forceinline unsigned int primID() const { return _primID; }
+ __forceinline unsigned int x() const { return (unsigned int)_x & 0x7fff; }
+ __forceinline unsigned int y() const { return (unsigned int)_y & 0x7fff; }
+
+ private:
+ unsigned short _x;
+ unsigned short _y;
+ unsigned int _geomID; // geometry ID of mesh
+ unsigned int _primID; // primitive ID of primitive inside mesh
+ };
+
+ struct SubGridID {
+ unsigned short x;
+ unsigned short y;
+ unsigned int primID;
+
+ __forceinline SubGridID() {}
+ __forceinline SubGridID(const unsigned int x, const unsigned int y, const unsigned int primID) :
+ x(x), y(y), primID(primID) {}
+ };
+
+ /* QuantizedBaseNode as large subgrid leaf */
+ template<int N>
+ struct SubGridQBVHN
+ {
+ /* Virtual interface to query information about the quad type */
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ __forceinline size_t size() const
+ {
+ for (size_t i=0;i<N;i++)
+ if (primID(i) == -1) return i;
+ return N;
+ }
+
+ __forceinline void clear() {
+ for (size_t i=0;i<N;i++)
+ subgridIDs[i] = SubGridID(0,0,(unsigned int)-1);
+ qnode.clear();
+ }
+
+ /* Default constructor */
+ __forceinline SubGridQBVHN() { }
+
+ /* Construction from vertices and IDs */
+ __forceinline SubGridQBVHN(const unsigned int x[N],
+ const unsigned int y[N],
+ const unsigned int primID[N],
+ const BBox3fa * const subGridBounds,
+ const unsigned int geomID,
+ const unsigned int items)
+ {
+ clear();
+ _geomID = geomID;
+
+ __aligned(64) typename BVHN<N>::AABBNode node;
+ node.clear();
+ for (size_t i=0;i<items;i++)
+ {
+ subgridIDs[i] = SubGridID(x[i],y[i],primID[i]);
+ node.setBounds(i,subGridBounds[i]);
+ }
+ qnode.init_dim(node);
+ }
+
+ __forceinline unsigned int geomID() const { return _geomID; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i < N); return subgridIDs[i].primID; }
+ __forceinline unsigned int x(const size_t i) const { assert(i < N); return subgridIDs[i].x; }
+ __forceinline unsigned int y(const size_t i) const { assert(i < N); return subgridIDs[i].y; }
+
+ __forceinline SubGrid subgrid(const size_t i) const {
+ assert(i < N);
+ assert(primID(i) != -1);
+ return SubGrid(x(i),y(i),geomID(),primID(i));
+ }
+
+ public:
+ SubGridID subgridIDs[N];
+
+ typename BVHN<N>::QuantizedBaseNode qnode;
+
+ unsigned int _geomID; // geometry ID of mesh
+
+
+ friend embree_ostream operator<<(embree_ostream cout, const SubGridQBVHN& sg) {
+ cout << "SubGridQBVHN " << embree_endl;
+ for (size_t i=0;i<N;i++)
+ cout << i << " ( x = " << sg.subgridIDs[i].x << ", y = " << sg.subgridIDs[i].y << ", primID = " << sg.subgridIDs[i].primID << " )" << embree_endl;
+ cout << "geomID " << sg._geomID << embree_endl;
+ cout << "lowerX " << sg.qnode.dequantizeLowerX() << embree_endl;
+ cout << "upperX " << sg.qnode.dequantizeUpperX() << embree_endl;
+ cout << "lowerY " << sg.qnode.dequantizeLowerY() << embree_endl;
+ cout << "upperY " << sg.qnode.dequantizeUpperY() << embree_endl;
+ cout << "lowerZ " << sg.qnode.dequantizeLowerZ() << embree_endl;
+ cout << "upperZ " << sg.qnode.dequantizeUpperZ() << embree_endl;
+ return cout;
+ }
+
+ };
+
+ template<int N>
+ typename SubGridQBVHN<N>::Type SubGridQBVHN<N>::type;
+
+ typedef SubGridQBVHN<4> SubGridQBVH4;
+ typedef SubGridQBVHN<8> SubGridQBVH8;
+
+
+ /* QuantizedBaseNode as large subgrid leaf */
+ template<int N>
+ struct SubGridMBQBVHN
+ {
+ /* Virtual interface to query information about the quad type */
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ __forceinline size_t size() const
+ {
+ for (size_t i=0;i<N;i++)
+ if (primID(i) == -1) return i;
+ return N;
+ }
+
+ __forceinline void clear() {
+ for (size_t i=0;i<N;i++)
+ subgridIDs[i] = SubGridID(0,0,(unsigned int)-1);
+ qnode.clear();
+ }
+
+ /* Default constructor */
+ __forceinline SubGridMBQBVHN() { }
+
+ /* Construction from vertices and IDs */
+ __forceinline SubGridMBQBVHN(const unsigned int x[N],
+ const unsigned int y[N],
+ const unsigned int primID[N],
+ const BBox3fa * const subGridBounds0,
+ const BBox3fa * const subGridBounds1,
+ const unsigned int geomID,
+ const float toffset,
+ const float tscale,
+ const unsigned int items)
+ {
+ clear();
+ _geomID = geomID;
+ time_offset = toffset;
+ time_scale = tscale;
+
+ __aligned(64) typename BVHN<N>::AABBNode node0,node1;
+ node0.clear();
+ node1.clear();
+ for (size_t i=0;i<items;i++)
+ {
+ subgridIDs[i] = SubGridID(x[i],y[i],primID[i]);
+ node0.setBounds(i,subGridBounds0[i]);
+ node1.setBounds(i,subGridBounds1[i]);
+ }
+ qnode.node0.init_dim(node0);
+ qnode.node1.init_dim(node1);
+ }
+
+ __forceinline unsigned int geomID() const { return _geomID; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i < N); return subgridIDs[i].primID; }
+ __forceinline unsigned int x(const size_t i) const { assert(i < N); return subgridIDs[i].x; }
+ __forceinline unsigned int y(const size_t i) const { assert(i < N); return subgridIDs[i].y; }
+
+ __forceinline SubGrid subgrid(const size_t i) const {
+ assert(i < N);
+ assert(primID(i) != -1);
+ return SubGrid(x(i),y(i),geomID(),primID(i));
+ }
+
+ __forceinline float adjustTime(const float t) const { return time_scale * (t-time_offset); }
+
+ template<int K>
+ __forceinline vfloat<K> adjustTime(const vfloat<K> &t) const { return time_scale * (t-time_offset); }
+
+ public:
+ SubGridID subgridIDs[N];
+
+ typename BVHN<N>::QuantizedBaseNodeMB qnode;
+
+ float time_offset;
+ float time_scale;
+ unsigned int _geomID; // geometry ID of mesh
+
+
+ friend embree_ostream operator<<(embree_ostream cout, const SubGridMBQBVHN& sg) {
+ cout << "SubGridMBQBVHN " << embree_endl;
+ for (size_t i=0;i<N;i++)
+ cout << i << " ( x = " << sg.subgridIDs[i].x << ", y = " << sg.subgridIDs[i].y << ", primID = " << sg.subgridIDs[i].primID << " )" << embree_endl;
+ cout << "geomID " << sg._geomID << embree_endl;
+ cout << "time_offset " << sg.time_offset << embree_endl;
+ cout << "time_scale " << sg.time_scale << embree_endl;
+ cout << "lowerX " << sg.qnode.node0.dequantizeLowerX() << embree_endl;
+ cout << "upperX " << sg.qnode.node0.dequantizeUpperX() << embree_endl;
+ cout << "lowerY " << sg.qnode.node0.dequantizeLowerY() << embree_endl;
+ cout << "upperY " << sg.qnode.node0.dequantizeUpperY() << embree_endl;
+ cout << "lowerZ " << sg.qnode.node0.dequantizeLowerZ() << embree_endl;
+ cout << "upperZ " << sg.qnode.node0.dequantizeUpperZ() << embree_endl;
+ cout << "lowerX " << sg.qnode.node1.dequantizeLowerX() << embree_endl;
+ cout << "upperX " << sg.qnode.node1.dequantizeUpperX() << embree_endl;
+ cout << "lowerY " << sg.qnode.node1.dequantizeLowerY() << embree_endl;
+ cout << "upperY " << sg.qnode.node1.dequantizeUpperY() << embree_endl;
+ cout << "lowerZ " << sg.qnode.node1.dequantizeLowerZ() << embree_endl;
+ cout << "upperZ " << sg.qnode.node1.dequantizeUpperZ() << embree_endl;
+ return cout;
+ }
+
+ };
+
+}
diff --git a/thirdparty/embree/kernels/geometry/subgrid_intersector.h b/thirdparty/embree/kernels/geometry/subgrid_intersector.h
new file mode 100644
index 0000000000..ad5fee2e4e
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/subgrid_intersector.h
@@ -0,0 +1,517 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "subgrid.h"
+#include "subgrid_intersector_moeller.h"
+#include "subgrid_intersector_pluecker.h"
+
+namespace embree
+{
+ namespace isa
+ {
+
+ // =======================================================================================
+ // =================================== SubGridIntersectors ===============================
+ // =======================================================================================
+
+
+ template<int N, bool filter>
+ struct SubGridIntersector1Moeller
+ {
+ typedef SubGridQBVHN<N> Primitive;
+ typedef SubGridQuadMIntersector1MoellerTrumbore<4,filter> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
+ pre.intersect(ray,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
+ return pre.occluded(ray,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const SubGrid& subgrid)
+ {
+ STAT3(point_query.trav_prims,1,1,1);
+ AccelSet* accel = (AccelSet*)context->scene->get(subgrid.geomID());
+ assert(accel);
+ context->geomID = subgrid.geomID();
+ context->primID = subgrid.primID();
+ return accel->pointQuery(query, context);
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
+#if defined(__AVX__)
+ STAT3(normal.trav_hit_boxes[popcnt(mask)],1,1,1);
+#endif
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+
+ if (unlikely(dist[ID] > ray.tfar)) continue;
+ intersect(pre,ray,context,prim[i].subgrid(ID));
+ }
+ }
+ }
+ template<bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+
+ if (occluded(pre,ray,context,prim[i].subgrid(ID)))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t num, const TravPointQuery<N> &tquery, size_t& lazy_node)
+ {
+ bool changed = false;
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask;
+ if (likely(context->query_type == POINT_QUERY_TYPE_SPHERE)) {
+ mask = BVHNQuantizedBaseNodePointQuerySphere1<N>::pointQuery(&prim[i].qnode,tquery,dist);
+ } else {
+ mask = BVHNQuantizedBaseNodePointQueryAABB1<N>::pointQuery(&prim[i].qnode,tquery,dist);
+ }
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+ changed |= pointQuery(query, context, prim[i].subgrid(ID));
+ }
+ }
+ return changed;
+ }
+ };
+
+ template<int N, bool filter>
+ struct SubGridIntersector1Pluecker
+ {
+ typedef SubGridQBVHN<N> Primitive;
+ typedef SubGridQuadMIntersector1Pluecker<4,filter> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
+ pre.intersect(ray,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
+ return pre.occluded(ray,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const SubGrid& subgrid)
+ {
+ STAT3(point_query.trav_prims,1,1,1);
+ AccelSet* accel = (AccelSet*)context->scene->get(subgrid.geomID());
+ context->geomID = subgrid.geomID();
+ context->primID = subgrid.primID();
+ return accel->pointQuery(query, context);
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
+#if defined(__AVX__)
+ STAT3(normal.trav_hit_boxes[popcnt(mask)],1,1,1);
+#endif
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+
+ if (unlikely(dist[ID] > ray.tfar)) continue;
+ intersect(pre,ray,context,prim[i].subgrid(ID));
+ }
+ }
+ }
+
+ template<bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+
+ if (occluded(pre,ray,context,prim[i].subgrid(ID)))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t num, const TravPointQuery<N> &tquery, size_t& lazy_node)
+ {
+ bool changed = false;
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask;
+ if (likely(context->query_type == POINT_QUERY_TYPE_SPHERE)) {
+ mask = BVHNQuantizedBaseNodePointQuerySphere1<N>::pointQuery(&prim[i].qnode,tquery,dist);
+ } else {
+ mask = BVHNQuantizedBaseNodePointQueryAABB1<N>::pointQuery(&prim[i].qnode,tquery,dist);
+ }
+#if defined(__AVX__)
+ STAT3(point_query.trav_hit_boxes[popcnt(mask)],1,1,1);
+#endif
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+ changed |= pointQuery(query, context, prim[i].subgrid(ID));
+ }
+ }
+ return changed;
+ }
+ };
+
+ template<int N, int K, bool filter>
+ struct SubGridIntersectorKMoeller
+ {
+ typedef SubGridQBVHN<N> Primitive;
+ typedef SubGridQuadMIntersectorKMoellerTrumbore<4,K,filter> Precalculations;
+
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ Vec3fa vtx[16];
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ subgrid.gather(vtx,context->scene);
+ for (unsigned int i=0; i<4; i++)
+ {
+ const Vec3vf<K> p0 = vtx[i*4+0];
+ const Vec3vf<K> p1 = vtx[i*4+1];
+ const Vec3vf<K> p2 = vtx[i*4+2];
+ const Vec3vf<K> p3 = vtx[i*4+3];
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ pre.intersectK(valid_i,ray,p0,p1,p2,p3,g,subgrid,i,IntersectKEpilogM<4,K,filter>(ray,context,subgrid.geomID(),subgrid.primID(),i));
+ }
+ }
+
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ vbool<K> valid0 = valid_i;
+ Vec3fa vtx[16];
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ subgrid.gather(vtx,context->scene);
+ for (unsigned int i=0; i<4; i++)
+ {
+ const Vec3vf<K> p0 = vtx[i*4+0];
+ const Vec3vf<K> p1 = vtx[i*4+1];
+ const Vec3vf<K> p2 = vtx[i*4+2];
+ const Vec3vf<K> p3 = vtx[i*4+3];
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ if (pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)))
+ break;
+ }
+ return !valid0;
+ }
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
+ pre.intersect1(ray,k,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+ Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
+ return pre.occluded1(ray,k,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
+ for (size_t j=0;j<num;j++)
+ {
+ size_t m_valid = movemask(prim[j].qnode.validMask());
+ vfloat<K> dist;
+ while(m_valid)
+ {
+ const size_t i = bscf(m_valid);
+ if (none(valid & isecK.intersectK(&prim[j].qnode,i,tray,dist))) continue;
+ intersect(valid,pre,ray,context,prim[j].subgrid(i));
+ }
+ }
+ }
+
+ template<bool robust>
+ static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
+ vbool<K> valid0 = valid;
+ for (size_t j=0;j<num;j++)
+ {
+ size_t m_valid = movemask(prim[j].qnode.validMask());
+ vfloat<K> dist;
+ while(m_valid)
+ {
+ const size_t i = bscf(m_valid);
+ if (none(valid0 & isecK.intersectK(&prim[j].qnode,i,tray,dist))) continue;
+ valid0 &= !occluded(valid0,pre,ray,context,prim[j].subgrid(i));
+ if (none(valid0)) break;
+ }
+ }
+ return !valid0;
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+
+ if (unlikely(dist[ID] > ray.tfar[k])) continue;
+ intersect(pre,ray,k,context,prim[i].subgrid(ID));
+ }
+ }
+ }
+
+ template<bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+
+ if (occluded(pre,ray,k,context,prim[i].subgrid(ID)))
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
+
+ template<int N, int K, bool filter>
+ struct SubGridIntersectorKPluecker
+ {
+ typedef SubGridQBVHN<N> Primitive;
+ typedef SubGridQuadMIntersectorKPluecker<4,K,filter> Precalculations;
+
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ Vec3fa vtx[16];
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ subgrid.gather(vtx,context->scene);
+ for (unsigned int i=0; i<4; i++)
+ {
+ const Vec3vf<K> p0 = vtx[i*4+0];
+ const Vec3vf<K> p1 = vtx[i*4+1];
+ const Vec3vf<K> p2 = vtx[i*4+2];
+ const Vec3vf<K> p3 = vtx[i*4+3];
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ pre.intersectK(valid_i,ray,p0,p1,p2,p3,g,subgrid,i,IntersectKEpilogM<4,K,filter>(ray,context,subgrid.geomID(),subgrid.primID(),i));
+ }
+ }
+
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ vbool<K> valid0 = valid_i;
+ Vec3fa vtx[16];
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ subgrid.gather(vtx,context->scene);
+ for (unsigned int i=0; i<4; i++)
+ {
+ const Vec3vf<K> p0 = vtx[i*4+0];
+ const Vec3vf<K> p1 = vtx[i*4+1];
+ const Vec3vf<K> p2 = vtx[i*4+2];
+ const Vec3vf<K> p3 = vtx[i*4+3];
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ //if (pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)))
+ if (pre.occludedK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)))
+
+ break;
+ }
+ return !valid0;
+ }
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
+ pre.intersect1(ray,k,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+ Vec3vf4 v0,v1,v2,v3; subgrid.gather(v0,v1,v2,v3,context->scene);
+ return pre.occluded1(ray,k,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
+ for (size_t j=0;j<num;j++)
+ {
+ size_t m_valid = movemask(prim[j].qnode.validMask());
+ vfloat<K> dist;
+ while(m_valid)
+ {
+ const size_t i = bscf(m_valid);
+ if (none(valid & isecK.intersectK(&prim[j].qnode,i,tray,dist))) continue;
+ intersect(valid,pre,ray,context,prim[j].subgrid(i));
+ }
+ }
+ }
+
+ template<bool robust>
+ static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
+ vbool<K> valid0 = valid;
+ for (size_t j=0;j<num;j++)
+ {
+ size_t m_valid = movemask(prim[j].qnode.validMask());
+ vfloat<K> dist;
+ while(m_valid)
+ {
+ const size_t i = bscf(m_valid);
+ if (none(valid0 & isecK.intersectK(&prim[j].qnode,i,tray,dist))) continue;
+ valid0 &= !occluded(valid0,pre,ray,context,prim[j].subgrid(i));
+ if (none(valid0)) break;
+ }
+ }
+ return !valid0;
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+
+ if (unlikely(dist[ID] > ray.tfar[k])) continue;
+ intersect(pre,ray,k,context,prim[i].subgrid(ID));
+ }
+ }
+ }
+
+ template<bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ assert(((size_t)1 << ID) & movemask(prim[i].qnode.validMask()));
+
+ if (occluded(pre,ray,k,context,prim[i].subgrid(ID)))
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/subgrid_intersector_moeller.h b/thirdparty/embree/kernels/geometry/subgrid_intersector_moeller.h
new file mode 100644
index 0000000000..64937d34fe
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/subgrid_intersector_moeller.h
@@ -0,0 +1,382 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "subgrid.h"
+#include "quad_intersector_moeller.h"
+
+namespace embree
+{
+ namespace isa
+ {
+
+ /* ----------------------------- */
+ /* -- single ray intersectors -- */
+ /* ----------------------------- */
+
+ template<int M>
+ __forceinline void interpolateUV(MoellerTrumboreHitM<M,UVIdentity<M>> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const vint<M> &stepX, const vint<M> &stepY)
+ {
+ /* correct U,V interpolation across the entire grid */
+ const vint<M> sx((int)subgrid.x());
+ const vint<M> sy((int)subgrid.y());
+ const vint<M> sxM(sx + stepX);
+ const vint<M> syM(sy + stepY);
+ const float inv_resX = rcp((float)((int)g.resX-1));
+ const float inv_resY = rcp((float)((int)g.resY-1));
+ hit.U = (hit.U + (vfloat<M>)sxM * hit.absDen) * inv_resX;
+ hit.V = (hit.V + (vfloat<M>)syM * hit.absDen) * inv_resY;
+ }
+
+ template<int M, bool filter>
+ struct SubGridQuadMIntersector1MoellerTrumbore;
+
+ template<int M, bool filter>
+ struct SubGridQuadMIntersector1MoellerTrumbore
+ {
+ __forceinline SubGridQuadMIntersector1MoellerTrumbore() {}
+
+ __forceinline SubGridQuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
+
+ __forceinline void intersect(RayHit& ray, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const GridMesh::Grid &g, const SubGrid& subgrid) const
+ {
+ UVIdentity<M> mapUV;
+ MoellerTrumboreHitM<M,UVIdentity<M>> hit(mapUV);
+ MoellerTrumboreIntersector1<M> intersector(ray,nullptr);
+ Intersect1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
+
+ /* intersect first triangle */
+ if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))
+ {
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ epilog(hit.valid,hit);
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.absDen - hit.U;
+ hit.V = hit.absDen - hit.V;
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ epilog(hit.valid,hit);
+ }
+ }
+
+ __forceinline bool occluded(Ray& ray, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const GridMesh::Grid &g, const SubGrid& subgrid) const
+ {
+ UVIdentity<M> mapUV;
+ MoellerTrumboreHitM<M,UVIdentity<M>> hit(mapUV);
+ MoellerTrumboreIntersector1<M> intersector(ray,nullptr);
+ Occluded1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
+
+ /* intersect first triangle */
+ if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))
+ {
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ if (epilog(hit.valid,hit))
+ return true;
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.absDen - hit.U;
+ hit.V = hit.absDen - hit.V;
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ if (epilog(hit.valid,hit))
+ return true;
+ }
+ return false;
+ }
+ };
+
+#if defined (__AVX__)
+
+ /*! Intersects 4 quads with 1 ray using AVX */
+ template<bool filter>
+ struct SubGridQuadMIntersector1MoellerTrumbore<4,filter>
+ {
+ __forceinline SubGridQuadMIntersector1MoellerTrumbore() {}
+
+ __forceinline SubGridQuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {}
+
+ template<typename Epilog>
+ __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid& subgrid, const Epilog& epilog) const
+ {
+ const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
+#if !defined(EMBREE_BACKFACE_CULLING)
+ const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
+#else
+ const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
+#endif
+ UVIdentity<8> mapUV;
+ MoellerTrumboreHitM<8,UVIdentity<8>> hit(mapUV);
+ MoellerTrumboreIntersector1<8> intersector(ray,nullptr);
+ const vbool8 flags(0,0,0,0,1,1,1,1);
+ if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,mapUV,hit)))
+ {
+ /* correct U,V interpolation across the entire grid */
+ const vfloat8 U = select(flags,hit.absDen - hit.V,hit.U);
+ const vfloat8 V = select(flags,hit.absDen - hit.U,hit.V);
+ hit.U = U;
+ hit.V = V;
+ hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));
+ interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1));
+ if (unlikely(epilog(hit.valid,hit)))
+ return true;
+ }
+ return false;
+ }
+
+ __forceinline bool intersect(RayHit& ray, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const GridMesh::Grid &g, const SubGrid& subgrid) const
+ {
+ return intersect(ray,v0,v1,v2,v3,g,subgrid,Intersect1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
+ }
+
+ __forceinline bool occluded(Ray& ray, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const GridMesh::Grid &g, const SubGrid& subgrid) const
+ {
+ return intersect(ray,v0,v1,v2,v3,g,subgrid,Occluded1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
+ }
+ };
+
+#endif
+
+ // ============================================================================================================================
+ // ============================================================================================================================
+ // ============================================================================================================================
+
+
+ /* ----------------------------- */
+ /* -- ray packet intersectors -- */
+ /* ----------------------------- */
+
+ template<int K>
+ __forceinline void interpolateUV(const vbool<K>& valid, MoellerTrumboreHitK<K,UVIdentity<K>> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const unsigned int i)
+ {
+ /* correct U,V interpolation across the entire grid */
+ const unsigned int sx = subgrid.x() + (unsigned int)(i % 2);
+ const unsigned int sy = subgrid.y() + (unsigned int)(i >>1);
+ const float inv_resX = rcp((float)(int)(g.resX-1));
+ const float inv_resY = rcp((float)(int)(g.resY-1));
+ hit.U = select(valid,(hit.U + vfloat<K>((float)sx) * hit.absDen) * inv_resX,hit.U);
+ hit.V = select(valid,(hit.V + vfloat<K>((float)sy) * hit.absDen) * inv_resY,hit.V);
+ }
+
+ template<int M, int K, bool filter>
+ struct SubGridQuadMIntersectorKMoellerTrumboreBase
+ {
+ __forceinline SubGridQuadMIntersectorKMoellerTrumboreBase(const vbool<K>& valid, const RayK<K>& ray) {}
+
+ template<typename Epilog>
+ __forceinline bool intersectK(const vbool<K>& valid,
+ RayK<K>& ray,
+ const Vec3vf<K>& v0,
+ const Vec3vf<K>& v1,
+ const Vec3vf<K>& v2,
+ const Vec3vf<K>& v3,
+ const GridMesh::Grid &g,
+ const SubGrid &subgrid,
+ const unsigned int i,
+ const Epilog& epilog) const
+ {
+ UVIdentity<K> mapUV;
+ MoellerTrumboreHitK<K,UVIdentity<K>> hit(mapUV);
+ MoellerTrumboreIntersectorK<M,K> intersector;
+
+ const vbool<K> valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit);
+ if (any(valid0))
+ {
+ interpolateUV(valid0,hit,g,subgrid,i);
+ epilog(valid0,hit);
+ }
+ const vbool<K> valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit);
+ if (any(valid1))
+ {
+ hit.U = hit.absDen - hit.U;
+ hit.V = hit.absDen - hit.V;
+ interpolateUV(valid1,hit,g,subgrid,i);
+ epilog(valid1,hit);
+ }
+ return any(valid0|valid1);
+ }
+
+ template<typename Epilog>
+ __forceinline bool occludedK(const vbool<K>& valid,
+ RayK<K>& ray,
+ const Vec3vf<K>& v0,
+ const Vec3vf<K>& v1,
+ const Vec3vf<K>& v2,
+ const Vec3vf<K>& v3,
+ const GridMesh::Grid &g,
+ const SubGrid &subgrid,
+ const unsigned int i,
+ const Epilog& epilog) const
+ {
+ UVIdentity<K> mapUV;
+ MoellerTrumboreHitK<K,UVIdentity<K>> hit(mapUV);
+ MoellerTrumboreIntersectorK<M,K> intersector;
+
+ vbool<K> valid_final = valid;
+ const vbool<K> valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit);
+ if (any(valid0))
+ {
+ interpolateUV(valid0,hit,g,subgrid,i);
+ epilog(valid0,hit);
+ valid_final &= !valid0;
+ }
+ if (none(valid_final)) return true;
+ const vbool<K> valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit);
+ if (any(valid1))
+ {
+ hit.U = hit.absDen - hit.U;
+ hit.V = hit.absDen - hit.V;
+ interpolateUV(valid1,hit,g,subgrid,i);
+ epilog(valid1,hit);
+ valid_final &= !valid1;
+ }
+ return none(valid_final);
+ }
+
+ static __forceinline bool intersect1(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ MoellerTrumboreHitM<M,UVIdentity<M>> &hit)
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ MoellerTrumboreIntersectorK<8,K> intersector;
+ UVIdentity<M> mapUV;
+ return intersector.intersectEdge(ray,k,v0,e1,e2,mapUV,hit);
+ }
+
+ };
+
+ template<int M, int K, bool filter>
+ struct SubGridQuadMIntersectorKMoellerTrumbore : public SubGridQuadMIntersectorKMoellerTrumboreBase<M,K,filter>
+ {
+ __forceinline SubGridQuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
+ : SubGridQuadMIntersectorKMoellerTrumboreBase<M,K,filter>(valid,ray) {}
+
+ __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
+ {
+ UVIdentity<M> mapUV;
+ MoellerTrumboreHitM<M,UVIdentity<M>> hit(mapUV);
+ Intersect1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
+ MoellerTrumboreIntersectorK<M,K> intersector;
+ /* intersect first triangle */
+ if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit))
+ {
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ epilog(hit.valid,hit);
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.absDen - hit.U;
+ hit.V = hit.absDen - hit.V;
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ epilog(hit.valid,hit);
+ }
+ }
+
+ __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
+ {
+ UVIdentity<M> mapUV;
+ MoellerTrumboreHitM<M,UVIdentity<M>> hit(mapUV);
+ Occluded1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
+ MoellerTrumboreIntersectorK<M,K> intersector;
+ /* intersect first triangle */
+ if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit))
+ {
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ if (epilog(hit.valid,hit)) return true;
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.absDen - hit.U;
+ hit.V = hit.absDen - hit.V;
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ if (epilog(hit.valid,hit)) return true;
+ }
+ return false;
+ }
+ };
+
+
+#if defined (__AVX__)
+
+ /*! Intersects 4 quads with 1 ray using AVX */
+ template<int K, bool filter>
+ struct SubGridQuadMIntersectorKMoellerTrumbore<4,K,filter> : public SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>
+ {
+ __forceinline SubGridQuadMIntersectorKMoellerTrumbore(const vbool<K>& valid, const RayK<K>& ray)
+ : SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>(valid,ray) {}
+
+ template<typename Epilog>
+ __forceinline bool intersect1(RayK<K>& ray, size_t k,const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const GridMesh::Grid &g, const SubGrid &subgrid, const Epilog& epilog) const
+ {
+ const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
+#if !defined(EMBREE_BACKFACE_CULLING)
+ const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
+#else
+ const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
+#endif
+ const vbool8 flags(0,0,0,0,1,1,1,1);
+
+ UVIdentity<8> mapUV;
+ MoellerTrumboreHitM<8,UVIdentity<8>> hit(mapUV);
+ if (SubGridQuadMIntersectorKMoellerTrumboreBase<8,K,filter>::intersect1(ray,k,vtx0,vtx1,vtx2,hit))
+ {
+ const vfloat8 U = select(flags,hit.absDen - hit.V,hit.U);
+ const vfloat8 V = select(flags,hit.absDen - hit.U,hit.V);
+ hit.U = U;
+ hit.V = V;
+ hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));
+ interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1));
+ if (unlikely(epilog(hit.valid,hit)))
+ return true;
+
+ }
+ return false;
+ }
+
+ __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
+ {
+ return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Intersect1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID()));
+ }
+
+ __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
+ {
+ return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Occluded1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID()));
+ }
+ };
+
+#endif
+
+
+
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/subgrid_intersector_pluecker.h b/thirdparty/embree/kernels/geometry/subgrid_intersector_pluecker.h
new file mode 100644
index 0000000000..5ded56e1f7
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/subgrid_intersector_pluecker.h
@@ -0,0 +1,367 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "subgrid.h"
+#include "quad_intersector_moeller.h"
+#include "quad_intersector_pluecker.h"
+
+namespace embree
+{
+ namespace isa
+ {
+
+ template<int M>
+ __forceinline void interpolateUV(PlueckerHitM<M,UVIdentity<M>> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const vint<M> &stepX, const vint<M> &stepY)
+ {
+ /* correct U,V interpolation across the entire grid */
+ const vint<M> sx((int)subgrid.x());
+ const vint<M> sy((int)subgrid.y());
+ const vint<M> sxM(sx + stepX);
+ const vint<M> syM(sy + stepY);
+ const float inv_resX = rcp((float)((int)g.resX-1));
+ const float inv_resY = rcp((float)((int)g.resY-1));
+ hit.U = (hit.U + vfloat<M>(sxM) * hit.UVW) * inv_resX;
+ hit.V = (hit.V + vfloat<M>(syM) * hit.UVW) * inv_resY;
+ }
+
+ template<int M, bool filter>
+ struct SubGridQuadMIntersector1Pluecker;
+
+ template<int M, bool filter>
+ struct SubGridQuadMIntersector1Pluecker
+ {
+ __forceinline SubGridQuadMIntersector1Pluecker() {}
+
+ __forceinline SubGridQuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
+
+ __forceinline void intersect(RayHit& ray, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const GridMesh::Grid &g, const SubGrid& subgrid) const
+ {
+ UVIdentity<M> mapUV;
+ PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
+ PlueckerIntersector1<M> intersector(ray,nullptr);
+
+ Intersect1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
+
+ /* intersect first triangle */
+ if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))
+ {
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ epilog(hit.valid,hit);
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.UVW - hit.U;
+ hit.V = hit.UVW - hit.V;
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ epilog(hit.valid,hit);
+ }
+ }
+
+ __forceinline bool occluded(Ray& ray, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
+ const GridMesh::Grid &g, const SubGrid& subgrid) const
+ {
+ UVIdentity<M> mapUV;
+ PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
+ PlueckerIntersector1<M> intersector(ray,nullptr);
+ Occluded1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
+
+ /* intersect first triangle */
+ if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))
+ {
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ if (epilog(hit.valid,hit))
+ return true;
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.UVW - hit.U;
+ hit.V = hit.UVW - hit.V;
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ if (epilog(hit.valid,hit))
+ return true;
+ }
+ return false;
+ }
+ };
+
+#if defined (__AVX__)
+
+ /*! Intersects 4 quads with 1 ray using AVX */
+ template<bool filter>
+ struct SubGridQuadMIntersector1Pluecker<4,filter>
+ {
+ __forceinline SubGridQuadMIntersector1Pluecker() {}
+
+ __forceinline SubGridQuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
+
+ template<typename Epilog>
+ __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid& subgrid, const Epilog& epilog) const
+ {
+ const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
+#if !defined(EMBREE_BACKFACE_CULLING)
+ const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
+#else
+ const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
+#endif
+
+ UVIdentity<8> mapUV;
+ PlueckerHitM<8,UVIdentity<8>> hit(mapUV);
+ PlueckerIntersector1<8> intersector(ray,nullptr);
+ const vbool8 flags(0,0,0,0,1,1,1,1);
+ if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,mapUV,hit)))
+ {
+ /* correct U,V interpolation across the entire grid */
+ const vfloat8 U = select(flags,hit.UVW - hit.V,hit.U);
+ const vfloat8 V = select(flags,hit.UVW - hit.U,hit.V);
+ hit.U = U;
+ hit.V = V;
+ hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));
+ interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1));
+ if (unlikely(epilog(hit.valid,hit)))
+ return true;
+ }
+ return false;
+ }
+
+ __forceinline bool intersect(RayHit& ray, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const GridMesh::Grid &g, const SubGrid& subgrid) const
+ {
+ return intersect(ray,v0,v1,v2,v3,g,subgrid,Intersect1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
+ }
+
+ __forceinline bool occluded(Ray& ray, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const GridMesh::Grid &g, const SubGrid& subgrid) const
+ {
+ return intersect(ray,v0,v1,v2,v3,g,subgrid,Occluded1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
+ }
+ };
+
+#endif
+
+
+ /* ----------------------------- */
+ /* -- ray packet intersectors -- */
+ /* ----------------------------- */
+
+ template<int K>
+ __forceinline void interpolateUV(const vbool<K>& valid, PlueckerHitK<K,UVIdentity<K>> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const unsigned int i)
+ {
+ /* correct U,V interpolation across the entire grid */
+ const unsigned int sx = subgrid.x() + (unsigned int)(i % 2);
+ const unsigned int sy = subgrid.y() + (unsigned int)(i >>1);
+ const float inv_resX = rcp((float)(int)(g.resX-1));
+ const float inv_resY = rcp((float)(int)(g.resY-1));
+ hit.U = select(valid,(hit.U + vfloat<K>((float)sx) * hit.UVW) * inv_resX,hit.U);
+ hit.V = select(valid,(hit.V + vfloat<K>((float)sy) * hit.UVW) * inv_resY,hit.V);
+ }
+
+ template<int M, int K, bool filter>
+ struct SubGridQuadMIntersectorKPlueckerBase
+ {
+ __forceinline SubGridQuadMIntersectorKPlueckerBase(const vbool<K>& valid, const RayK<K>& ray) {}
+
+ template<typename Epilog>
+ __forceinline bool intersectK(const vbool<K>& valid,
+ RayK<K>& ray,
+ const Vec3vf<K>& v0,
+ const Vec3vf<K>& v1,
+ const Vec3vf<K>& v2,
+ const Vec3vf<K>& v3,
+ const GridMesh::Grid &g,
+ const SubGrid &subgrid,
+ const unsigned int i,
+ const Epilog& epilog) const
+ {
+ UVIdentity<K> mapUV;
+ PlueckerHitK<K,UVIdentity<K>> hit(mapUV);
+ PlueckerIntersectorK<M,K> intersector;
+
+ const vbool<K> valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit);
+ if (any(valid0))
+ {
+ interpolateUV(valid0,hit,g,subgrid,i);
+ epilog(valid0,hit);
+ }
+ const vbool<K> valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit);
+ if (any(valid1))
+ {
+ hit.U = hit.UVW - hit.U;
+ hit.V = hit.UVW - hit.V;
+ interpolateUV(valid1,hit,g,subgrid,i);
+ epilog(valid1,hit);
+ }
+ return any(valid0|valid1);
+ }
+
+ template<typename Epilog>
+ __forceinline bool occludedK(const vbool<K>& valid,
+ RayK<K>& ray,
+ const Vec3vf<K>& v0,
+ const Vec3vf<K>& v1,
+ const Vec3vf<K>& v2,
+ const Vec3vf<K>& v3,
+ const GridMesh::Grid &g,
+ const SubGrid &subgrid,
+ const unsigned int i,
+ const Epilog& epilog) const
+ {
+ UVIdentity<K> mapUV;
+ PlueckerHitK<K,UVIdentity<K>> hit(mapUV);
+ PlueckerIntersectorK<M,K> intersector;
+
+ vbool<K> valid_final = valid;
+ const vbool<K> valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit);
+ if (any(valid0))
+ {
+ interpolateUV(valid0,hit,g,subgrid,i);
+ epilog(valid0,hit);
+ valid_final &= !valid0;
+ }
+ if (none(valid_final)) return true;
+ const vbool<K> valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit);
+ if (any(valid1))
+ {
+ hit.U = hit.UVW - hit.U;
+ hit.V = hit.UVW - hit.V;
+ interpolateUV(valid1,hit,g,subgrid,i);
+ epilog(valid1,hit);
+ valid_final &= !valid1;
+ }
+ return none(valid_final);
+ }
+
+
+ };
+
+
+
+
+ template<int M, int K, bool filter>
+ struct SubGridQuadMIntersectorKPluecker : public SubGridQuadMIntersectorKPlueckerBase<M,K,filter>
+ {
+ __forceinline SubGridQuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
+ : SubGridQuadMIntersectorKPlueckerBase<M,K,filter>(valid,ray) {}
+
+ __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
+ {
+ UVIdentity<M> mapUV;
+ PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
+ Intersect1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
+ PlueckerIntersectorK<M,K> intersector;
+
+ /* intersect first triangle */
+ if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit))
+ {
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ epilog(hit.valid,hit);
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.UVW - hit.U;
+ hit.V = hit.UVW - hit.V;
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ epilog(hit.valid,hit);
+ }
+ }
+
+ __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
+ {
+ UVIdentity<M> mapUV;
+ PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
+ Occluded1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
+ PlueckerIntersectorK<M,K> intersector;
+
+ /* intersect first triangle */
+ if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit))
+ {
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ if (epilog(hit.valid,hit)) return true;
+ }
+
+ /* intersect second triangle */
+ if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit))
+ {
+ hit.U = hit.UVW - hit.U;
+ hit.V = hit.UVW - hit.V;
+ interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
+ if (epilog(hit.valid,hit)) return true;
+ }
+ return false;
+ }
+ };
+
+
+#if defined (__AVX__)
+
+ /*! Intersects 4 quads with 1 ray using AVX */
+ template<int K, bool filter>
+ struct SubGridQuadMIntersectorKPluecker<4,K,filter> : public SubGridQuadMIntersectorKPlueckerBase<4,K,filter>
+ {
+ __forceinline SubGridQuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
+ : SubGridQuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {}
+
+ template<typename Epilog>
+ __forceinline bool intersect1(RayK<K>& ray, size_t k,const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
+ const GridMesh::Grid &g, const SubGrid &subgrid, const Epilog& epilog) const
+ {
+ const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
+#if !defined(EMBREE_BACKFACE_CULLING)
+ const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
+#else
+ const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
+ const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
+#endif
+ UVIdentity<8> mapUV;
+ PlueckerHitM<8,UVIdentity<8>> hit(mapUV);
+ PlueckerIntersectorK<8,K> intersector;
+ const vbool8 flags(0,0,0,0,1,1,1,1);
+ if (unlikely(intersector.intersect(ray,k,vtx0,vtx1,vtx2,mapUV,hit)))
+ {
+ /* correct U,V interpolation across the entire grid */
+ const vfloat8 U = select(flags,hit.UVW - hit.V,hit.U);
+ const vfloat8 V = select(flags,hit.UVW - hit.U,hit.V);
+ hit.U = U;
+ hit.V = V;
+ hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));
+ interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1));
+ if (unlikely(epilog(hit.valid,hit)))
+ return true;
+ }
+ return false;
+ }
+
+ __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
+ {
+ return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Intersect1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID()));
+ }
+
+ __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
+ const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
+ {
+ return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Occluded1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID()));
+ }
+ };
+#endif
+
+
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/subgrid_mb_intersector.h b/thirdparty/embree/kernels/geometry/subgrid_mb_intersector.h
new file mode 100644
index 0000000000..473d656e24
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/subgrid_mb_intersector.h
@@ -0,0 +1,236 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "subgrid_intersector.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int N, bool filter>
+ struct SubGridMBIntersector1Pluecker
+ {
+ typedef SubGridMBQBVHN<N> Primitive;
+ typedef SubGridQuadMIntersector1Pluecker<4,filter> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ float ftime;
+ const int itime = mesh->timeSegment(ray.time(), ftime);
+ Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime,ftime);
+ pre.intersect(ray,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ float ftime;
+ const int itime = mesh->timeSegment(ray.time(), ftime);
+
+ Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime,ftime);
+ return pre.occluded(ray,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const SubGrid& subgrid)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, subgrid);
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ const float time = prim[i].adjustTime(ray.time());
+
+ assert(time <= 1.0f);
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist);
+#if defined(__AVX__)
+ STAT3(normal.trav_hit_boxes[popcnt(mask)],1,1,1);
+#endif
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ if (unlikely(dist[ID] > ray.tfar)) continue;
+ intersect(pre,ray,context,prim[i].subgrid(ID));
+ }
+ }
+ }
+
+ template<bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+ for (size_t i=0;i<num;i++)
+ {
+ const float time = prim[i].adjustTime(ray.time());
+ assert(time <= 1.0f);
+ vfloat<N> dist;
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ if (occluded(pre,ray,context,prim[i].subgrid(ID)))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, const Primitive* prim, size_t num, const TravPointQuery<N> &tquery, size_t& lazy_node)
+ {
+ assert(false && "not implemented");
+ return false;
+ }
+ };
+
+
+ template<int N, int K, bool filter>
+ struct SubGridMBIntersectorKPluecker
+ {
+ typedef SubGridMBQBVHN<N> Primitive;
+ typedef SubGridQuadMIntersectorKPluecker<4,K,filter> Precalculations;
+
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ size_t m_valid = movemask(valid_i);
+ while(m_valid)
+ {
+ size_t ID = bscf(m_valid);
+ intersect(pre,ray,ID,context,subgrid);
+ }
+ }
+
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const SubGrid& subgrid)
+ {
+ vbool<K> valid0 = valid_i;
+ size_t m_valid = movemask(valid_i);
+ while(m_valid)
+ {
+ size_t ID = bscf(m_valid);
+ if (occluded(pre,ray,ID,context,subgrid))
+ clear(valid0,ID);
+ }
+ return !valid0;
+ }
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ vfloat<K> ftime;
+ const vint<K> itime = mesh->timeSegment<K>(ray.time(), ftime);
+ Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime[k],ftime[k]);
+ pre.intersect1(ray,k,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const SubGrid& subgrid)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const GridMesh* mesh = context->scene->get<GridMesh>(subgrid.geomID());
+ const GridMesh::Grid &g = mesh->grid(subgrid.primID());
+
+ vfloat<K> ftime;
+ const vint<K> itime = mesh->timeSegment<K>(ray.time(), ftime);
+ Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime[k],ftime[k]);
+ return pre.occluded1(ray,k,context,v0,v1,v2,v3,g,subgrid);
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
+ for (size_t j=0;j<num;j++)
+ {
+ size_t m_valid = movemask(prim[j].qnode.validMask());
+ const vfloat<K> time = prim[j].template adjustTime<K>(ray.time());
+
+ vfloat<K> dist;
+ while(m_valid)
+ {
+ const size_t i = bscf(m_valid);
+ if (none(valid & isecK.intersectK(&prim[j].qnode,i,tray,time,dist))) continue;
+ intersect(valid,pre,ray,context,prim[j].subgrid(i));
+ }
+ }
+ }
+
+ template<bool robust>
+ static __forceinline vbool<K> occluded(const vbool<K>& valid, const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRayK<K, robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersectorK<N,K,robust> isecK;
+
+ vbool<K> valid0 = valid;
+ for (size_t j=0;j<num;j++)
+ {
+ size_t m_valid = movemask(prim[j].qnode.validMask());
+ const vfloat<K> time = prim[j].template adjustTime<K>(ray.time());
+ vfloat<K> dist;
+ while(m_valid)
+ {
+ const size_t i = bscf(m_valid);
+ if (none(valid0 & isecK.intersectK(&prim[j].qnode,i,tray,time,dist))) continue;
+ valid0 &= !occluded(valid0,pre,ray,context,prim[j].subgrid(i));
+ if (none(valid0)) break;
+ }
+ }
+ return !valid0;
+ }
+
+ template<bool robust>
+ static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ const float time = prim[i].adjustTime(ray.time()[k]);
+ assert(time <= 1.0f);
+
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ if (unlikely(dist[ID] > ray.tfar[k])) continue;
+ intersect(pre,ray,k,context,prim[i].subgrid(ID));
+ }
+ }
+ }
+
+ template<bool robust>
+ static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay<N,robust> &tray, size_t& lazy_node)
+ {
+ BVHNQuantizedBaseNodeIntersector1<N,robust> isec1;
+
+ for (size_t i=0;i<num;i++)
+ {
+ vfloat<N> dist;
+ const float time = prim[i].adjustTime(ray.time()[k]);
+ assert(time <= 1.0f);
+
+ size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist);
+ while(mask != 0)
+ {
+ const size_t ID = bscf(mask);
+ if (occluded(pre,ray,k,context,prim[i].subgrid(ID)))
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/triangle.h b/thirdparty/embree/kernels/geometry/triangle.h
new file mode 100644
index 0000000000..24b758ae48
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/triangle.h
@@ -0,0 +1,162 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+
+namespace embree
+{
+ /* Precalculated representation for M triangles. Stores for each
+ triangle a base vertex, two edges, and the geometry normal to
+ speed up intersection calculations */
+ template<int M>
+ struct TriangleM
+ {
+ public:
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* Returns maximum number of stored triangles */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
+
+ public:
+
+ /* Default constructor */
+ __forceinline TriangleM() {}
+
+ /* Construction from vertices and IDs */
+ __forceinline TriangleM(const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const vuint<M>& geomIDs, const vuint<M>& primIDs)
+ : v0(v0), e1(v0-v1), e2(v2-v0), geomIDs(geomIDs), primIDs(primIDs) {}
+
+ /* Returns a mask that tells which triangles are valid */
+ __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); }
+
+ /* Returns true if the specified triangle is valid */
+ __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; }
+
+ /* Returns the number of stored triangles */
+ __forceinline size_t size() const { return bsf(~movemask(valid())); }
+
+ /* Returns the geometry IDs */
+ __forceinline vuint<M>& geomID() { return geomIDs; }
+ __forceinline const vuint<M>& geomID() const { return geomIDs; }
+ __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
+
+ /* Returns the primitive IDs */
+ __forceinline vuint<M>& primID() { return primIDs; }
+ __forceinline const vuint<M>& primID() const { return primIDs; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
+
+ /* Calculate the bounds of the triangle */
+ __forceinline BBox3fa bounds() const
+ {
+ Vec3vf<M> p0 = v0;
+ Vec3vf<M> p1 = v0-e1;
+ Vec3vf<M> p2 = v0+e2;
+ Vec3vf<M> lower = min(p0,p1,p2);
+ Vec3vf<M> upper = max(p0,p1,p2);
+ vbool<M> mask = valid();
+ lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
+ lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
+ lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
+ upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
+ upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
+ upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
+ return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
+ Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
+ }
+
+ /* Non temporal store */
+ __forceinline static void store_nt(TriangleM* dst, const TriangleM& src)
+ {
+ vfloat<M>::store_nt(&dst->v0.x,src.v0.x);
+ vfloat<M>::store_nt(&dst->v0.y,src.v0.y);
+ vfloat<M>::store_nt(&dst->v0.z,src.v0.z);
+ vfloat<M>::store_nt(&dst->e1.x,src.e1.x);
+ vfloat<M>::store_nt(&dst->e1.y,src.e1.y);
+ vfloat<M>::store_nt(&dst->e1.z,src.e1.z);
+ vfloat<M>::store_nt(&dst->e2.x,src.e2.x);
+ vfloat<M>::store_nt(&dst->e2.y,src.e2.y);
+ vfloat<M>::store_nt(&dst->e2.z,src.e2.z);
+ vuint<M>::store_nt(&dst->geomIDs,src.geomIDs);
+ vuint<M>::store_nt(&dst->primIDs,src.primIDs);
+ }
+
+ /* Fill triangle from triangle list */
+ __forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
+ {
+ vuint<M> vgeomID = -1, vprimID = -1;
+ Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
+
+ for (size_t i=0; i<M && begin<end; i++, begin++)
+ {
+ const PrimRef& prim = prims[begin];
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(geomID);
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ const Vec3fa& p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa& p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa& p2 = mesh->vertex(tri.v[2]);
+ vgeomID [i] = geomID;
+ vprimID [i] = primID;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ }
+ TriangleM::store_nt(this,TriangleM(v0,v1,v2,vgeomID,vprimID));
+ }
+
+ /* Updates the primitive */
+ __forceinline BBox3fa update(TriangleMesh* mesh)
+ {
+ BBox3fa bounds = empty;
+ vuint<M> vgeomID = -1, vprimID = -1;
+ Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
+
+ for (size_t i=0; i<M; i++)
+ {
+ if (unlikely(geomID(i) == -1)) break;
+ const unsigned geomId = geomID(i);
+ const unsigned primId = primID(i);
+ const TriangleMesh::Triangle& tri = mesh->triangle(primId);
+ const Vec3fa p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa p2 = mesh->vertex(tri.v[2]);
+ bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2)));
+ vgeomID [i] = geomId;
+ vprimID [i] = primId;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ }
+ TriangleM::store_nt(this,TriangleM(v0,v1,v2,vgeomID,vprimID));
+ return bounds;
+ }
+
+ public:
+ Vec3vf<M> v0; // base vertex of the triangles
+ Vec3vf<M> e1; // 1st edge of the triangles (v0-v1)
+ Vec3vf<M> e2; // 2nd edge of the triangles (v2-v0)
+ private:
+ vuint<M> geomIDs; // geometry IDs
+ vuint<M> primIDs; // primitive IDs
+ };
+
+ template<int M>
+ typename TriangleM<M>::Type TriangleM<M>::type;
+
+ typedef TriangleM<4> Triangle4;
+}
diff --git a/thirdparty/embree/kernels/geometry/triangle_intersector.h b/thirdparty/embree/kernels/geometry/triangle_intersector.h
new file mode 100644
index 0000000000..2cdff78ec8
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/triangle_intersector.h
@@ -0,0 +1,96 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "triangle.h"
+#include "triangle_intersector_moeller.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Intersects M triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMIntersector1Moeller
+ {
+ typedef TriangleM<M> Primitive;
+ typedef MoellerTrumboreIntersector1<M> Precalculations;
+
+ /*! Intersect a ray with the M triangles and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleM<M>& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,UVIdentity<M>(),Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of M triangles. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleM<M>& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,UVIdentity<M>(),Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+
+ };
+
+ /*! Intersects M triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct TriangleMIntersectorKMoeller
+ {
+ typedef TriangleM<M> Primitive;
+ typedef MoellerTrumboreIntersectorK<M,K> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleM<M>& tri)
+ {
+ STAT_USER(0,TriangleM<M>::max_size());
+ for (size_t i=0; i<TriangleM<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> p0 = broadcast<vfloat<K>>(tri.v0,i);
+ const Vec3vf<K> e1 = broadcast<vfloat<K>>(tri.e1,i);
+ const Vec3vf<K> e2 = broadcast<vfloat<K>>(tri.e2,i);
+ pre.intersectEdgeK(valid_i,ray,p0,e1,e2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleM<M>& tri)
+ {
+ vbool<K> valid0 = valid_i;
+
+ for (size_t i=0; i<TriangleM<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ const Vec3vf<K> p0 = broadcast<vfloat<K>>(tri.v0,i);
+ const Vec3vf<K> e1 = broadcast<vfloat<K>>(tri.e1,i);
+ const Vec3vf<K> e2 = broadcast<vfloat<K>>(tri.e2,i);
+ pre.intersectEdgeK(valid0,ray,p0,e1,e2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleM<M>& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,UVIdentity<M>(),Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleM<M>& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,UVIdentity<M>(),Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/triangle_intersector_moeller.h b/thirdparty/embree/kernels/geometry/triangle_intersector_moeller.h
new file mode 100644
index 0000000000..0a42d8f08b
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/triangle_intersector_moeller.h
@@ -0,0 +1,525 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "triangle.h"
+#include "intersector_epilog.h"
+
+/*! This intersector implements a modified version of the Moeller
+ * Trumbore intersector from the paper "Fast, Minimum Storage
+ * Ray-Triangle Intersection". In contrast to the paper we
+ * precalculate some factors and factor the calculations differently
+ * to allow precalculating the cross product e1 x e2. The resulting
+ * algorithm is similar to the fastest one of the paper "Optimizing
+ * Ray-Triangle Intersection via Automated Search". */
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M, typename UVMapper>
+ struct MoellerTrumboreHitM
+ {
+ __forceinline MoellerTrumboreHitM(const UVMapper& mapUV) : mapUV(mapUV) {}
+
+ __forceinline MoellerTrumboreHitM(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const vfloat<M>& absDen, const Vec3vf<M>& Ng, const UVMapper& mapUV)
+ : U(U), V(V), T(T), absDen(absDen), mapUV(mapUV), valid(valid), vNg(Ng) {}
+
+ __forceinline void finalize()
+ {
+ const vfloat<M> rcpAbsDen = rcp(absDen);
+ vt = T * rcpAbsDen;
+ vu = U * rcpAbsDen;
+ vv = V * rcpAbsDen;
+ mapUV(vu,vv,vNg);
+ }
+
+ __forceinline Vec2vf<M> uv() const { return Vec2vf<M>(vu,vv); }
+ __forceinline vfloat<M> t () const { return vt; }
+ __forceinline Vec3vf<M> Ng() const { return vNg; }
+
+ __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
+ __forceinline float t (const size_t i) const { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
+
+ public:
+ vfloat<M> U;
+ vfloat<M> V;
+ vfloat<M> T;
+ vfloat<M> absDen;
+ UVMapper mapUV;
+
+ public:
+ vbool<M> valid;
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+ };
+
+ template<int M, bool early_out = true>
+ struct MoellerTrumboreIntersector1
+ {
+ __forceinline MoellerTrumboreIntersector1() {}
+
+ __forceinline MoellerTrumboreIntersector1(const Ray& ray, const void* ptr) {}
+
+ template<typename UVMapper>
+ __forceinline bool intersect(const vbool<M>& valid0,
+ Ray& ray,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const Vec3vf<M>& tri_Ng,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitM<M,UVMapper>& hit) const
+ {
+ /* calculate denominator */
+ vbool<M> valid = valid0;
+ const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org);
+ const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir);
+ const Vec3vf<M> C = Vec3vf<M>(tri_v0) - O;
+ const Vec3vf<M> R = cross(C,D);
+ const vfloat<M> den = dot(Vec3vf<M>(tri_Ng),D);
+
+ const vfloat<M> absDen = abs(den);
+ const vfloat<M> sgnDen = signmsk(den);
+
+ /* perform edge tests */
+ const vfloat<M> U = dot(R,Vec3vf<M>(tri_e2)) ^ sgnDen;
+ const vfloat<M> V = dot(R,Vec3vf<M>(tri_e1)) ^ sgnDen;
+
+ /* perform backface culling */
+#if defined(EMBREE_BACKFACE_CULLING)
+ valid &= (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
+#else
+ valid &= (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
+#endif
+ if (likely(early_out && none(valid))) return false;
+
+ /* perform depth test */
+ const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
+ valid &= (absDen*vfloat<M>(ray.tnear()) < T) & (T <= absDen*vfloat<M>(ray.tfar));
+ if (likely(early_out && none(valid))) return false;
+
+ /* update hit information */
+ new (&hit) MoellerTrumboreHitM<M,UVMapper>(valid,U,V,T,absDen,tri_Ng,mapUV);
+
+ return true;
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersectEdge(const vbool<M>& valid,
+ Ray& ray,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitM<M,UVMapper>& hit) const
+ {
+ const Vec3<vfloat<M>> tri_Ng = cross(tri_e2,tri_e1);
+ return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit);
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersectEdge(Ray& ray,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitM<M,UVMapper>& hit) const
+ {
+ vbool<M> valid = true;
+ const Vec3<vfloat<M>> tri_Ng = cross(tri_e2,tri_e1);
+ return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit);
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersect(Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitM<M,UVMapper>& hit) const
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ return intersectEdge(ray,v0,e1,e2,mapUV,hit);
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersect(const vbool<M>& valid,
+ Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitM<M,UVMapper>& hit) const
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ return intersectEdge(valid,ray,v0,e1,e2,mapUV,hit);
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersectEdge(Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& e1,
+ const Vec3vf<M>& e2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ MoellerTrumboreHitM<M,UVMapper> hit(mapUV);
+ if (likely(intersectEdge(ray,v0,e1,e2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersect(Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ MoellerTrumboreHitM<M,UVMapper> hit(mapUV);
+ if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersect(Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const Epilog& epilog) const
+ {
+ auto mapUV = UVIdentity<M>();
+ MoellerTrumboreHitM<M,UVIdentity<M>> hit(mapUV);
+ if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersect(const vbool<M>& valid,
+ Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ MoellerTrumboreHitM<M,UVMapper> hit(mapUV);
+ if (likely(intersect(valid,ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+ };
+
+ template<int K, typename UVMapper>
+ struct MoellerTrumboreHitK
+ {
+ __forceinline MoellerTrumboreHitK(const UVMapper& mapUV) : mapUV(mapUV) {}
+ __forceinline MoellerTrumboreHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& T, const vfloat<K>& absDen, const Vec3vf<K>& Ng, const UVMapper& mapUV)
+ : U(U), V(V), T(T), absDen(absDen), Ng(Ng), mapUV(mapUV) {}
+
+ __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
+ {
+ const vfloat<K> rcpAbsDen = rcp(absDen);
+ const vfloat<K> t = T * rcpAbsDen;
+ vfloat<K> u = U * rcpAbsDen;
+ vfloat<K> v = V * rcpAbsDen;
+ Vec3vf<K> vNg = Ng;
+ mapUV(u,v,vNg);
+ return std::make_tuple(u,v,t,vNg);
+ }
+
+ vfloat<K> U;
+ vfloat<K> V;
+ const vfloat<K> T;
+ const vfloat<K> absDen;
+ const Vec3vf<K> Ng;
+ const UVMapper& mapUV;
+ };
+
+ template<int M, int K>
+ struct MoellerTrumboreIntersectorK
+ {
+ __forceinline MoellerTrumboreIntersectorK() {}
+ __forceinline MoellerTrumboreIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {}
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename UVMapper>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ //RayK<K>& ray,
+ const Vec3vf<K>& ray_org,
+ const Vec3vf<K>& ray_dir,
+ const vfloat<K>& ray_tnear,
+ const vfloat<K>& ray_tfar,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_e1,
+ const Vec3vf<K>& tri_e2,
+ const Vec3vf<K>& tri_Ng,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitK<K,UVMapper> &hit) const
+ {
+ /* calculate denominator */
+ vbool<K> valid = valid0;
+ const Vec3vf<K> C = tri_v0 - ray_org;
+ const Vec3vf<K> R = cross(C,ray_dir);
+ const vfloat<K> den = dot(tri_Ng,ray_dir);
+ const vfloat<K> absDen = abs(den);
+ const vfloat<K> sgnDen = signmsk(den);
+
+ /* test against edge p2 p0 */
+ const vfloat<K> U = dot(tri_e2,R) ^ sgnDen;
+ valid &= U >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* test against edge p0 p1 */
+ const vfloat<K> V = dot(tri_e1,R) ^ sgnDen;
+ valid &= V >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* test against edge p1 p2 */
+ const vfloat<K> W = absDen-U-V;
+ valid &= W >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* perform depth test */
+ const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen;
+ valid &= (absDen*ray_tnear < T) & (T <= absDen*ray_tfar);
+ if (unlikely(none(valid))) return false;
+
+ /* perform backface culling */
+#if defined(EMBREE_BACKFACE_CULLING)
+ valid &= den < vfloat<K>(zero);
+ if (unlikely(none(valid))) return false;
+#else
+ valid &= den != vfloat<K>(zero);
+ if (unlikely(none(valid))) return false;
+#endif
+
+ /* calculate hit information */
+ new (&hit) MoellerTrumboreHitK<K,UVMapper>(U,V,T,absDen,tri_Ng,mapUV);
+ return valid;
+ }
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename UVMapper>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitK<K,UVMapper> &hit) const
+ {
+ const Vec3vf<K> e1 = tri_v0-tri_v1;
+ const Vec3vf<K> e2 = tri_v2-tri_v0;
+ const Vec3vf<K> Ng = cross(e2,e1);
+ return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit);
+ }
+
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename UVMapper, typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ MoellerTrumboreHitK<K,UVIdentity<K>> hit(mapUV);
+ const Vec3vf<K> e1 = tri_v0-tri_v1;
+ const Vec3vf<K> e2 = tri_v2-tri_v0;
+ const Vec3vf<K> Ng = cross(e2,e1);
+ const vbool<K> valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit);
+ return epilog(valid,hit);
+ }
+
+
+
+ template<typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const Epilog& epilog) const
+ {
+ UVIdentity<K> mapUV;
+ MoellerTrumboreHitK<K,UVIdentity<K>> hit(mapUV);
+ const Vec3vf<K> e1 = tri_v0-tri_v1;
+ const Vec3vf<K> e2 = tri_v2-tri_v0;
+ const Vec3vf<K> Ng = cross(e2,e1);
+ const vbool<K> valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit);
+ return epilog(valid,hit);
+ }
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename UVMapper, typename Epilog>
+ __forceinline vbool<K> intersectEdgeK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_e1,
+ const Vec3vf<K>& tri_e2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ MoellerTrumboreHitK<K,UVIdentity<K>> hit(mapUV);
+ const Vec3vf<K> tri_Ng = cross(tri_e2,tri_e1);
+ const vbool<K> valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit);
+ return epilog(valid,hit);
+ }
+
+ /*! Intersect k'th ray from ray packet of size K with M triangles. */
+ template<typename UVMapper>
+ __forceinline bool intersectEdge(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitM<M,UVMapper>& hit) const
+ {
+ /* calculate denominator */
+ typedef Vec3vf<M> Vec3vfM;
+ const Vec3vf<M> tri_Ng = cross(tri_e2,tri_e1);
+
+ const Vec3vfM O = broadcast<vfloat<M>>(ray.org,k);
+ const Vec3vfM D = broadcast<vfloat<M>>(ray.dir,k);
+ const Vec3vfM C = Vec3vfM(tri_v0) - O;
+ const Vec3vfM R = cross(C,D);
+ const vfloat<M> den = dot(Vec3vfM(tri_Ng),D);
+ const vfloat<M> absDen = abs(den);
+ const vfloat<M> sgnDen = signmsk(den);
+
+ /* perform edge tests */
+ const vfloat<M> U = dot(Vec3vf<M>(tri_e2),R) ^ sgnDen;
+ const vfloat<M> V = dot(Vec3vf<M>(tri_e1),R) ^ sgnDen;
+
+ /* perform backface culling */
+#if defined(EMBREE_BACKFACE_CULLING)
+ vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
+#else
+ vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
+#endif
+ if (likely(none(valid))) return false;
+
+ /* perform depth test */
+ const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
+ valid &= (absDen*vfloat<M>(ray.tnear()[k]) < T) & (T <= absDen*vfloat<M>(ray.tfar[k]));
+ if (likely(none(valid))) return false;
+
+ /* calculate hit information */
+ new (&hit) MoellerTrumboreHitM<M,UVMapper>(valid,U,V,T,absDen,tri_Ng,mapUV);
+ return true;
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersectEdge(RayK<K>& ray,
+ size_t k,
+ const BBox<vfloat<M>>& time_range,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitM<M,UVMapper>& hit) const
+ {
+ if (likely(intersect(ray,k,tri_v0,tri_e1,tri_e2,mapUV,hit)))
+ {
+ hit.valid &= time_range.lower <= vfloat<M>(ray.time[k]);
+ hit.valid &= vfloat<M>(ray.time[k]) < time_range.upper;
+ return any(hit.valid);
+ }
+ return false;
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersect(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ MoellerTrumboreHitM<M,UVMapper>& hit) const
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ return intersectEdge(ray,k,v0,e1,e2,mapUV,hit);
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersectEdge(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ MoellerTrumboreHitM<M,UVMapper> hit(mapUV);
+ if (likely(intersectEdge(ray,k,tri_v0,tri_e1,tri_e2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersectEdge(RayK<K>& ray,
+ size_t k,
+ const BBox<vfloat<M>>& time_range,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ MoellerTrumboreHitM<M,UVMapper> hit(mapUV);
+ if (likely(intersectEdge(ray,k,time_range,tri_v0,tri_e1,tri_e2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersect(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ return intersectEdge(ray,k,v0,e1,e2,mapUV,epilog);
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersect(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const Epilog& epilog) const
+ {
+ return intersect(ray,k,v0,v1,v2,UVIdentity<M>(),epilog);
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersect(RayK<K>& ray,
+ size_t k,
+ const BBox<vfloat<M>>& time_range,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ return intersectEdge(ray,k,time_range,v0,e1,e2,mapUV,epilog);
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h b/thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h
new file mode 100644
index 0000000000..8fbefcea88
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h
@@ -0,0 +1,407 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "triangle.h"
+#include "trianglev.h"
+#include "trianglev_mb.h"
+#include "intersector_epilog.h"
+
+/*! Modified Pluecker ray/triangle intersector. The test first shifts
+ * the ray origin into the origin of the coordinate system and then
+ * uses Pluecker coordinates for the intersection. Due to the shift,
+ * the Pluecker coordinate calculation simplifies and the tests get
+ * numerically stable. The edge equations are watertight along the
+ * edge for neighboring triangles. */
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M, typename UVMapper>
+ struct PlueckerHitM
+ {
+ __forceinline PlueckerHitM(const UVMapper& mapUV) : mapUV(mapUV) {}
+
+ __forceinline PlueckerHitM(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& UVW, const vfloat<M>& t, const Vec3vf<M>& Ng, const UVMapper& mapUV)
+ : U(U), V(V), UVW(UVW), mapUV(mapUV), valid(valid), vt(t), vNg(Ng) {}
+
+ __forceinline void finalize()
+ {
+ const vbool<M> invalid = abs(UVW) < min_rcp_input;
+ const vfloat<M> rcpUVW = select(invalid,vfloat<M>(0.0f),rcp(UVW));
+ vu = min(U * rcpUVW,1.0f);
+ vv = min(V * rcpUVW,1.0f);
+ mapUV(vu,vv,vNg);
+ }
+
+ __forceinline Vec2vf<M> uv() const { return Vec2vf<M>(vu,vv); }
+ __forceinline vfloat<M> t () const { return vt; }
+ __forceinline Vec3vf<M> Ng() const { return vNg; }
+
+ __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
+ __forceinline float t (const size_t i) const { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
+
+ public:
+ vfloat<M> U;
+ vfloat<M> V;
+ vfloat<M> UVW;
+ const UVMapper& mapUV;
+
+ public:
+ vbool<M> valid;
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+ };
+
+ template<int M, bool early_out = true>
+ struct PlueckerIntersector1
+ {
+ __forceinline PlueckerIntersector1() {}
+
+ __forceinline PlueckerIntersector1(const Ray& ray, const void* ptr) {}
+
+ template<typename UVMapper>
+ __forceinline bool intersect(const vbool<M>& valid0,
+ Ray& ray,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const UVMapper& mapUV,
+ PlueckerHitM<M,UVMapper>& hit) const
+ {
+ vbool<M> valid = valid0;
+
+ /* calculate vertices relative to ray origin */
+ const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org);
+ const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir);
+ const Vec3vf<M> v0 = tri_v0-O;
+ const Vec3vf<M> v1 = tri_v1-O;
+ const Vec3vf<M> v2 = tri_v2-O;
+
+ /* calculate triangle edges */
+ const Vec3vf<M> e0 = v2-v0;
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v1-v2;
+
+ /* perform edge tests */
+ const vfloat<M> U = dot(cross(e0,v2+v0),D);
+ const vfloat<M> V = dot(cross(e1,v0+v1),D);
+ const vfloat<M> W = dot(cross(e2,v1+v2),D);
+ const vfloat<M> UVW = U+V+W;
+ const vfloat<M> eps = float(ulp)*abs(UVW);
+#if defined(EMBREE_BACKFACE_CULLING)
+ valid &= max(U,V,W) <= eps;
+#else
+ valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
+#endif
+ if (unlikely(early_out && none(valid))) return false;
+
+ /* calculate geometry normal and denominator */
+ const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
+ const vfloat<M> den = twice(dot(Ng,D));
+
+ /* perform depth test */
+ const vfloat<M> T = twice(dot(v0,Ng));
+ const vfloat<M> t = rcp(den)*T;
+ valid &= vfloat<M>(ray.tnear()) <= t & t <= vfloat<M>(ray.tfar);
+ valid &= den != vfloat<M>(zero);
+ if (unlikely(early_out && none(valid))) return false;
+
+ /* update hit information */
+ new (&hit) PlueckerHitM<M,UVMapper>(valid,U,V,UVW,t,Ng,mapUV);
+ return true;
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersectEdge(const vbool<M>& valid,
+ Ray& ray,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const UVMapper& mapUV,
+ PlueckerHitM<M,UVMapper>& hit) const
+ {
+ return intersect(valid,ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersectEdge(Ray& ray,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const UVMapper& mapUV,
+ PlueckerHitM<M,UVMapper>& hit) const
+ {
+ vbool<M> valid = true;
+ return intersect(valid,ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
+ }
+
+ template<typename UVMapper>
+ __forceinline bool intersect(Ray& ray,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const UVMapper& mapUV,
+ PlueckerHitM<M,UVMapper>& hit) const
+ {
+ return intersectEdge(ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersectEdge(Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& e1,
+ const Vec3vf<M>& e2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ PlueckerHitM<M,UVMapper> hit(mapUV);
+ if (likely(intersectEdge(ray,v0,e1,e2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersect(Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ PlueckerHitM<M,UVMapper> hit(mapUV);
+ if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersect(Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const Epilog& epilog) const
+ {
+ auto mapUV = UVIdentity<M>();
+ PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
+ if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersect(const vbool<M>& valid,
+ Ray& ray,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ PlueckerHitM<M,UVMapper> hit(mapUV);
+ if (likely(intersect(valid,ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ };
+
+ template<int K, typename UVMapper>
+ struct PlueckerHitK
+ {
+ __forceinline PlueckerHitK(const UVMapper& mapUV) : mapUV(mapUV) {}
+
+ __forceinline PlueckerHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& UVW, const vfloat<K>& t, const Vec3vf<K>& Ng, const UVMapper& mapUV)
+ : U(U), V(V), UVW(UVW), t(t), Ng(Ng), mapUV(mapUV) {}
+
+ __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
+ {
+ const vbool<K> invalid = abs(UVW) < min_rcp_input;
+ const vfloat<K> rcpUVW = select(invalid,vfloat<K>(0.0f),rcp(UVW));
+ vfloat<K> u = min(U * rcpUVW,1.0f);
+ vfloat<K> v = min(V * rcpUVW,1.0f);
+ Vec3vf<K> vNg = Ng;
+ mapUV(u,v,vNg);
+ return std::make_tuple(u,v,t,vNg);
+ }
+ vfloat<K> U;
+ vfloat<K> V;
+ const vfloat<K> UVW;
+ const vfloat<K> t;
+ const Vec3vf<K> Ng;
+ const UVMapper& mapUV;
+ };
+
+ template<int M, int K>
+ struct PlueckerIntersectorK
+ {
+ __forceinline PlueckerIntersectorK() {}
+ __forceinline PlueckerIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {}
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename UVMapper>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const UVMapper& mapUV,
+ PlueckerHitK<K,UVMapper> &hit) const
+ {
+ /* calculate vertices relative to ray origin */
+ vbool<K> valid = valid0;
+ const Vec3vf<K> O = ray.org;
+ const Vec3vf<K> D = ray.dir;
+ const Vec3vf<K> v0 = tri_v0-O;
+ const Vec3vf<K> v1 = tri_v1-O;
+ const Vec3vf<K> v2 = tri_v2-O;
+
+ /* calculate triangle edges */
+ const Vec3vf<K> e0 = v2-v0;
+ const Vec3vf<K> e1 = v0-v1;
+ const Vec3vf<K> e2 = v1-v2;
+
+ /* perform edge tests */
+ const vfloat<K> U = dot(Vec3vf<K>(cross(e0,v2+v0)),D);
+ const vfloat<K> V = dot(Vec3vf<K>(cross(e1,v0+v1)),D);
+ const vfloat<K> W = dot(Vec3vf<K>(cross(e2,v1+v2)),D);
+ const vfloat<K> UVW = U+V+W;
+ const vfloat<K> eps = float(ulp)*abs(UVW);
+#if defined(EMBREE_BACKFACE_CULLING)
+ valid &= max(U,V,W) <= eps;
+#else
+ valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
+#endif
+ if (unlikely(none(valid))) return valid;
+
+ /* calculate geometry normal and denominator */
+ const Vec3vf<K> Ng = stable_triangle_normal(e0,e1,e2);
+ const vfloat<K> den = twice(dot(Vec3vf<K>(Ng),D));
+
+ /* perform depth test */
+ const vfloat<K> T = twice(dot(v0,Vec3vf<K>(Ng)));
+ const vfloat<K> t = rcp(den)*T;
+ valid &= ray.tnear() <= t & t <= ray.tfar;
+ valid &= den != vfloat<K>(zero);
+ if (unlikely(none(valid))) return valid;
+
+ /* calculate hit information */
+ new (&hit) PlueckerHitK<K,UVMapper>(U,V,UVW,t,Ng,mapUV);
+ return valid;
+ }
+
+ template<typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const Epilog& epilog) const
+ {
+ UVIdentity<K> mapUV;
+ PlueckerHitK<K,UVIdentity<K>> hit(mapUV);
+ const vbool<K> valid = intersectK(valid0,ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
+ return epilog(valid,hit);
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ PlueckerHitK<K,UVMapper> hit(mapUV);
+ const vbool<K> valid = intersectK(valid0,ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
+ return epilog(valid,hit);
+ }
+
+ /*! Intersect k'th ray from ray packet of size K with M triangles. */
+ template<typename UVMapper>
+ __forceinline bool intersect(RayK<K>& ray, size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const UVMapper& mapUV,
+ PlueckerHitM<M,UVMapper> &hit) const
+ {
+ /* calculate vertices relative to ray origin */
+ const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
+ const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
+ const Vec3vf<M> v0 = tri_v0-O;
+ const Vec3vf<M> v1 = tri_v1-O;
+ const Vec3vf<M> v2 = tri_v2-O;
+
+ /* calculate triangle edges */
+ const Vec3vf<M> e0 = v2-v0;
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v1-v2;
+
+
+ /* perform edge tests */
+ const vfloat<M> U = dot(cross(e0,v2+v0),D);
+ const vfloat<M> V = dot(cross(e1,v0+v1),D);
+ const vfloat<M> W = dot(cross(e2,v1+v2),D);
+
+ const vfloat<M> UVW = U+V+W;
+ const vfloat<M> eps = float(ulp)*abs(UVW);
+#if defined(EMBREE_BACKFACE_CULLING)
+ vbool<M> valid = max(U,V,W) <= eps;
+#else
+ vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
+#endif
+ if (unlikely(none(valid))) return false;
+
+ /* calculate geometry normal and denominator */
+ const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
+ const vfloat<M> den = twice(dot(Ng,D));
+
+ /* perform depth test */
+ const vfloat<M> T = twice(dot(v0,Ng));
+ const vfloat<M> t = rcp(den)*T;
+ valid &= vfloat<M>(ray.tnear()[k]) <= t & t <= vfloat<M>(ray.tfar[k]);
+ if (unlikely(none(valid))) return false;
+
+ /* avoid division by 0 */
+ valid &= den != vfloat<M>(zero);
+ if (unlikely(none(valid))) return false;
+
+ /* update hit information */
+ new (&hit) PlueckerHitM<M,UVMapper>(valid,U,V,UVW,t,Ng,mapUV);
+ return true;
+ }
+
+ template<typename UVMapper, typename Epilog>
+ __forceinline bool intersect(RayK<K>& ray, size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const UVMapper& mapUV,
+ const Epilog& epilog) const
+ {
+ PlueckerHitM<M,UVMapper> hit(mapUV);
+ if (intersect(ray,k,tri_v0,tri_v1,tri_v2,mapUV,hit))
+ return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersect(RayK<K>& ray, size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ const Epilog& epilog) const
+ {
+ UVIdentity<M> mapUV;
+ PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
+ if (intersect(ray,k,tri_v0,tri_v1,tri_v2,mapUV,hit))
+ return epilog(hit.valid,hit);
+ return false;
+ }
+
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/triangle_intersector_woop.h b/thirdparty/embree/kernels/geometry/triangle_intersector_woop.h
new file mode 100644
index 0000000000..f05dcc4537
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/triangle_intersector_woop.h
@@ -0,0 +1,418 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "triangle.h"
+#include "intersector_epilog.h"
+
+/*! This intersector implements a modified version of the Woop's ray-triangle intersection test */
+
+namespace embree
+{
+ namespace isa
+ {
+ template<int M>
+ struct WoopHitM
+ {
+ __forceinline WoopHitM() {}
+
+ __forceinline WoopHitM(const vbool<M>& valid,
+ const vfloat<M>& U,
+ const vfloat<M>& V,
+ const vfloat<M>& T,
+ const vfloat<M>& inv_det,
+ const Vec3vf<M>& Ng)
+ : U(U), V(V), T(T), inv_det(inv_det), valid(valid), vNg(Ng) {}
+
+ __forceinline void finalize()
+ {
+ vt = T;
+ vu = U*inv_det;
+ vv = V*inv_det;
+ }
+
+ __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
+ __forceinline float t (const size_t i) const { return vt[i]; }
+ __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
+
+ private:
+ const vfloat<M> U;
+ const vfloat<M> V;
+ const vfloat<M> T;
+ const vfloat<M> inv_det;
+
+ public:
+ const vbool<M> valid;
+ vfloat<M> vu;
+ vfloat<M> vv;
+ vfloat<M> vt;
+ Vec3vf<M> vNg;
+ };
+
+ template<int M>
+ struct WoopPrecalculations1
+ {
+ unsigned int kx,ky,kz;
+ Vec3vf<M> org;
+ Vec3fa S;
+ __forceinline WoopPrecalculations1() {}
+
+ __forceinline WoopPrecalculations1(const Ray& ray, const void* ptr)
+ {
+ kz = maxDim(abs(ray.dir));
+ kx = (kz+1) % 3;
+ ky = (kx+1) % 3;
+ const float inv_dir_kz = rcp(ray.dir[kz]);
+ if (ray.dir[kz]) std::swap(kx,ky);
+ S.x = ray.dir[kx] * inv_dir_kz;
+ S.y = ray.dir[ky] * inv_dir_kz;
+ S.z = inv_dir_kz;
+ org = Vec3vf<M>(ray.org[kx],ray.org[ky],ray.org[kz]);
+ }
+ };
+
+
+ template<int M>
+ struct WoopIntersector1
+ {
+
+ typedef WoopPrecalculations1<M> Precalculations;
+
+ __forceinline WoopIntersector1() {}
+
+ __forceinline WoopIntersector1(const Ray& ray, const void* ptr) {}
+
+ static __forceinline bool intersect(const vbool<M>& valid0,
+ Ray& ray,
+ const Precalculations& pre,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_v1,
+ const Vec3vf<M>& tri_v2,
+ WoopHitM<M>& hit)
+ {
+ vbool<M> valid = valid0;
+
+ /* vertices relative to ray origin */
+ const Vec3vf<M> org = Vec3vf<M>(pre.org.x,pre.org.y,pre.org.z);
+ const Vec3vf<M> A = Vec3vf<M>(tri_v0[pre.kx],tri_v0[pre.ky],tri_v0[pre.kz]) - org;
+ const Vec3vf<M> B = Vec3vf<M>(tri_v1[pre.kx],tri_v1[pre.ky],tri_v1[pre.kz]) - org;
+ const Vec3vf<M> C = Vec3vf<M>(tri_v2[pre.kx],tri_v2[pre.ky],tri_v2[pre.kz]) - org;
+
+ /* shear and scale vertices */
+ const vfloat<M> Ax = nmadd(A.z,pre.S.x,A.x);
+ const vfloat<M> Ay = nmadd(A.z,pre.S.y,A.y);
+ const vfloat<M> Bx = nmadd(B.z,pre.S.x,B.x);
+ const vfloat<M> By = nmadd(B.z,pre.S.y,B.y);
+ const vfloat<M> Cx = nmadd(C.z,pre.S.x,C.x);
+ const vfloat<M> Cy = nmadd(C.z,pre.S.y,C.y);
+
+ /* scaled barycentric */
+ const vfloat<M> U0 = Cx*By;
+ const vfloat<M> U1 = Cy*Bx;
+ const vfloat<M> V0 = Ax*Cy;
+ const vfloat<M> V1 = Ay*Cx;
+ const vfloat<M> W0 = Bx*Ay;
+ const vfloat<M> W1 = By*Ax;
+#if !defined(__AVX512F__)
+ valid &= (U0 >= U1) & (V0 >= V1) & (W0 >= W1) |
+ (U0 <= U1) & (V0 <= V1) & (W0 <= W1);
+#else
+ valid &= ge(ge(U0 >= U1,V0,V1),W0,W1) | le(le(U0 <= U1,V0,V1),W0,W1);
+#endif
+
+ if (likely(none(valid))) return false;
+ const vfloat<M> U = U0-U1;
+ const vfloat<M> V = V0-V1;
+ const vfloat<M> W = W0-W1;
+
+ const vfloat<M> det = U+V+W;
+
+ valid &= det != 0.0f;
+ const vfloat<M> inv_det = rcp(det);
+
+ const vfloat<M> Az = pre.S.z * A.z;
+ const vfloat<M> Bz = pre.S.z * B.z;
+ const vfloat<M> Cz = pre.S.z * C.z;
+ const vfloat<M> T = madd(U,Az,madd(V,Bz,W*Cz));
+ const vfloat<M> t = T * inv_det;
+ /* perform depth test */
+ valid &= (vfloat<M>(ray.tnear()) < t) & (t <= vfloat<M>(ray.tfar));
+ if (likely(none(valid))) return false;
+
+ const Vec3vf<M> tri_Ng = cross(tri_v2-tri_v0,tri_v0-tri_v1);
+
+ /* update hit information */
+ new (&hit) WoopHitM<M>(valid,U,V,t,inv_det,tri_Ng);
+ return true;
+ }
+
+ static __forceinline bool intersect(Ray& ray,
+ const Precalculations& pre,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ WoopHitM<M>& hit)
+ {
+ vbool<M> valid = true;
+ return intersect(valid,ray,pre,v0,v1,v2,hit);
+ }
+
+
+ template<typename Epilog>
+ static __forceinline bool intersect(Ray& ray,
+ const Precalculations& pre,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const Epilog& epilog)
+ {
+ WoopHitM<M> hit;
+ if (likely(intersect(ray,pre,v0,v1,v2,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename Epilog>
+ static __forceinline bool intersect(const vbool<M>& valid,
+ Ray& ray,
+ const Precalculations& pre,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const Epilog& epilog)
+ {
+ WoopHitM<M> hit;
+ if (likely(intersect(valid,ray,pre,v0,v1,v2,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+ };
+
+#if 0
+ template<int K>
+ struct WoopHitK
+ {
+ __forceinline WoopHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& T, const vfloat<K>& absDen, const Vec3vf<K>& Ng)
+ : U(U), V(V), T(T), absDen(absDen), Ng(Ng) {}
+
+ __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
+ {
+ const vfloat<K> rcpAbsDen = rcp(absDen);
+ const vfloat<K> t = T * rcpAbsDen;
+ const vfloat<K> u = U * rcpAbsDen;
+ const vfloat<K> v = V * rcpAbsDen;
+ return std::make_tuple(u,v,t,Ng);
+ }
+
+ private:
+ const vfloat<K> U;
+ const vfloat<K> V;
+ const vfloat<K> T;
+ const vfloat<K> absDen;
+ const Vec3vf<K> Ng;
+ };
+
+ template<int M, int K>
+ struct WoopIntersectorK
+ {
+ __forceinline WoopIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {}
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ //RayK<K>& ray,
+ const Vec3vf<K>& ray_org,
+ const Vec3vf<K>& ray_dir,
+ const vfloat<K>& ray_tnear,
+ const vfloat<K>& ray_tfar,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_e1,
+ const Vec3vf<K>& tri_e2,
+ const Vec3vf<K>& tri_Ng,
+ const Epilog& epilog) const
+ {
+ /* calculate denominator */
+ vbool<K> valid = valid0;
+ const Vec3vf<K> C = tri_v0 - ray_org;
+ const Vec3vf<K> R = cross(C,ray_dir);
+ const vfloat<K> den = dot(tri_Ng,ray_dir);
+ const vfloat<K> absDen = abs(den);
+ const vfloat<K> sgnDen = signmsk(den);
+
+ /* test against edge p2 p0 */
+ const vfloat<K> U = dot(tri_e2,R) ^ sgnDen;
+ valid &= U >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* test against edge p0 p1 */
+ const vfloat<K> V = dot(tri_e1,R) ^ sgnDen;
+ valid &= V >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* test against edge p1 p2 */
+ const vfloat<K> W = absDen-U-V;
+ valid &= W >= 0.0f;
+ if (likely(none(valid))) return false;
+
+ /* perform depth test */
+ const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen;
+ valid &= (absDen*ray_tnear < T) & (T <= absDen*ray_tfar);
+ if (unlikely(none(valid))) return false;
+
+ /* perform backface culling */
+#if defined(EMBREE_BACKFACE_CULLING)
+ valid &= den < vfloat<K>(zero);
+ if (unlikely(none(valid))) return false;
+#else
+ valid &= den != vfloat<K>(zero);
+ if (unlikely(none(valid))) return false;
+#endif
+
+ /* calculate hit information */
+ WoopHitK<K> hit(U,V,T,absDen,tri_Ng);
+ return epilog(valid,hit);
+ }
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename Epilog>
+ __forceinline vbool<K> intersectK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_v1,
+ const Vec3vf<K>& tri_v2,
+ const Epilog& epilog) const
+ {
+ const Vec3vf<K> e1 = tri_v0-tri_v1;
+ const Vec3vf<K> e2 = tri_v2-tri_v0;
+ const Vec3vf<K> Ng = cross(e2,e1);
+ return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,epilog);
+ }
+
+ /*! Intersects K rays with one of M triangles. */
+ template<typename Epilog>
+ __forceinline vbool<K> intersectEdgeK(const vbool<K>& valid0,
+ RayK<K>& ray,
+ const Vec3vf<K>& tri_v0,
+ const Vec3vf<K>& tri_e1,
+ const Vec3vf<K>& tri_e2,
+ const Epilog& epilog) const
+ {
+ const Vec3vf<K> tri_Ng = cross(tri_e2,tri_e1);
+ return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,tri_e1,tri_e2,tri_Ng,epilog);
+ }
+
+ /*! Intersect k'th ray from ray packet of size K with M triangles. */
+ __forceinline bool intersectEdge(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ WoopHitM<M>& hit) const
+ {
+ /* calculate denominator */
+ typedef Vec3vf<M> Vec3vfM;
+ const Vec3vf<M> tri_Ng = cross(tri_e2,tri_e1);
+
+ const Vec3vfM O = broadcast<vfloat<M>>(ray.org,k);
+ const Vec3vfM D = broadcast<vfloat<M>>(ray.dir,k);
+ const Vec3vfM C = Vec3vfM(tri_v0) - O;
+ const Vec3vfM R = cross(C,D);
+ const vfloat<M> den = dot(Vec3vfM(tri_Ng),D);
+ const vfloat<M> absDen = abs(den);
+ const vfloat<M> sgnDen = signmsk(den);
+
+ /* perform edge tests */
+ const vfloat<M> U = dot(Vec3vf<M>(tri_e2),R) ^ sgnDen;
+ const vfloat<M> V = dot(Vec3vf<M>(tri_e1),R) ^ sgnDen;
+
+ /* perform backface culling */
+#if defined(EMBREE_BACKFACE_CULLING)
+ vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
+#else
+ vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
+#endif
+ if (likely(none(valid))) return false;
+
+ /* perform depth test */
+ const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen;
+ valid &= (absDen*vfloat<M>(ray.tnear()[k]) < T) & (T <= absDen*vfloat<M>(ray.tfar[k]));
+ if (likely(none(valid))) return false;
+
+ /* calculate hit information */
+ new (&hit) WoopHitM<M>(valid,U,V,T,absDen,tri_Ng);
+ return true;
+ }
+
+ __forceinline bool intersectEdge(RayK<K>& ray,
+ size_t k,
+ const BBox<vfloat<M>>& time_range,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ WoopHitM<M>& hit) const
+ {
+ if (likely(intersect(ray,k,tri_v0,tri_e1,tri_e2,hit)))
+ {
+ hit.valid &= time_range.lower <= vfloat<M>(ray.time[k]);
+ hit.valid &= vfloat<M>(ray.time[k]) < time_range.upper;
+ return any(hit.valid);
+ }
+ return false;
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersectEdge(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const Epilog& epilog) const
+ {
+ WoopHitM<M> hit;
+ if (likely(intersectEdge(ray,k,tri_v0,tri_e1,tri_e2,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersectEdge(RayK<K>& ray,
+ size_t k,
+ const BBox<vfloat<M>>& time_range,
+ const Vec3vf<M>& tri_v0,
+ const Vec3vf<M>& tri_e1,
+ const Vec3vf<M>& tri_e2,
+ const Epilog& epilog) const
+ {
+ WoopHitM<M> hit;
+ if (likely(intersectEdge(ray,k,time_range,tri_v0,tri_e1,tri_e2,hit))) return epilog(hit.valid,hit);
+ return false;
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersect(RayK<K>& ray,
+ size_t k,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const Epilog& epilog) const
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ return intersectEdge(ray,k,v0,e1,e2,epilog);
+ }
+
+ template<typename Epilog>
+ __forceinline bool intersect(RayK<K>& ray,
+ size_t k,
+ const BBox<vfloat<M>>& time_range,
+ const Vec3vf<M>& v0,
+ const Vec3vf<M>& v1,
+ const Vec3vf<M>& v2,
+ const Epilog& epilog) const
+ {
+ const Vec3vf<M> e1 = v0-v1;
+ const Vec3vf<M> e2 = v2-v0;
+ return intersectEdge(ray,k,time_range,v0,e1,e2,epilog);
+ }
+ };
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/triangle_triangle_intersector.h b/thirdparty/embree/kernels/geometry/triangle_triangle_intersector.h
new file mode 100644
index 0000000000..50106bcc16
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/triangle_triangle_intersector.h
@@ -0,0 +1,132 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#include "primitive.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct TriangleTriangleIntersector
+ {
+ __forceinline static float T(float pa0, float pa1, float da0, float da1) {
+ return pa0 + (pa1-pa0)*da0/(da0-da1);
+ }
+
+ __forceinline static bool point_line_side(const Vec2f& p, const Vec2f& a0, const Vec2f& a1) {
+ return det(p-a0,a0-a1) >= 0.0f;
+ }
+
+ __forceinline static bool point_inside_triangle(const Vec2f& p, const Vec2f& a, const Vec2f& b, const Vec2f& c)
+ {
+ const bool pab = point_line_side(p,a,b);
+ const bool pbc = point_line_side(p,b,c);
+ const bool pca = point_line_side(p,c,a);
+ return pab == pbc && pab == pca;
+ }
+
+ __forceinline static bool intersect_line_line(const Vec2f& a0, const Vec2f& a1, const Vec2f& b0, const Vec2f& b1)
+ {
+ const bool different_sides0 = point_line_side(b0,a0,a1) != point_line_side(b1,a0,a1);
+ const bool different_sides1 = point_line_side(a0,b0,b1) != point_line_side(a1,b0,b1);
+ return different_sides0 && different_sides1;
+ }
+
+ __forceinline static bool intersect_triangle_triangle (const Vec2f& a0, const Vec2f& a1, const Vec2f& a2,
+ const Vec2f& b0, const Vec2f& b1, const Vec2f& b2)
+ {
+ const bool a01_b01 = intersect_line_line(a0,a1,b0,b1);
+ if (a01_b01) return true;
+ const bool a01_b12 = intersect_line_line(a0,a1,b1,b2);
+ if (a01_b12) return true;
+ const bool a01_b20 = intersect_line_line(a0,a1,b2,b0);
+ if (a01_b20) return true;
+ const bool a12_b01 = intersect_line_line(a1,a2,b0,b1);
+ if (a12_b01) return true;
+ const bool a12_b12 = intersect_line_line(a1,a2,b1,b2);
+ if (a12_b12) return true;
+ const bool a12_b20 = intersect_line_line(a1,a2,b2,b0);
+ if (a12_b20) return true;
+ const bool a20_b01 = intersect_line_line(a2,a0,b0,b1);
+ if (a20_b01) return true;
+ const bool a20_b12 = intersect_line_line(a2,a0,b1,b2);
+ if (a20_b12) return true;
+ const bool a20_b20 = intersect_line_line(a2,a0,b2,b0);
+ if (a20_b20) return true;
+
+ bool a_in_b = point_inside_triangle(a0,b0,b1,b2) && point_inside_triangle(a1,b0,b1,b2) && point_inside_triangle(a2,b0,b1,b2);
+ if (a_in_b) return true;
+
+ bool b_in_a = point_inside_triangle(b0,a0,a1,a2) && point_inside_triangle(b1,a0,a1,a2) && point_inside_triangle(b2,a0,a1,a2);
+ if (b_in_a) return true;
+
+ return false;
+ }
+
+ static bool intersect_triangle_triangle (const Vec3fa& a0, const Vec3fa& a1, const Vec3fa& a2,
+ const Vec3fa& b0, const Vec3fa& b1, const Vec3fa& b2)
+ {
+ const float eps = 1E-5f;
+
+ /* calculate triangle planes */
+ const Vec3fa Na = cross(a1-a0,a2-a0);
+ const float Ca = dot(Na,a0);
+ const Vec3fa Nb = cross(b1-b0,b2-b0);
+ const float Cb = dot(Nb,b0);
+
+ /* project triangle A onto plane B */
+ const float da0 = dot(Nb,a0)-Cb;
+ const float da1 = dot(Nb,a1)-Cb;
+ const float da2 = dot(Nb,a2)-Cb;
+ if (max(da0,da1,da2) < -eps) return false;
+ if (min(da0,da1,da2) > +eps) return false;
+ //CSTAT(bvh_collide_prim_intersections4++);
+
+ /* project triangle B onto plane A */
+ const float db0 = dot(Na,b0)-Ca;
+ const float db1 = dot(Na,b1)-Ca;
+ const float db2 = dot(Na,b2)-Ca;
+ if (max(db0,db1,db2) < -eps) return false;
+ if (min(db0,db1,db2) > +eps) return false;
+ //CSTAT(bvh_collide_prim_intersections5++);
+
+ if (unlikely((std::fabs(da0) < eps && std::fabs(da1) < eps && std::fabs(da2) < eps) ||
+ (std::fabs(db0) < eps && std::fabs(db1) < eps && std::fabs(db2) < eps)))
+ {
+ const size_t dz = maxDim(Na);
+ const size_t dx = (dz+1)%3;
+ const size_t dy = (dx+1)%3;
+ const Vec2f A0(a0[dx],a0[dy]);
+ const Vec2f A1(a1[dx],a1[dy]);
+ const Vec2f A2(a2[dx],a2[dy]);
+ const Vec2f B0(b0[dx],b0[dy]);
+ const Vec2f B1(b1[dx],b1[dy]);
+ const Vec2f B2(b2[dx],b2[dy]);
+ return intersect_triangle_triangle(A0,A1,A2,B0,B1,B2);
+ }
+
+ const Vec3fa D = cross(Na,Nb);
+ const float pa0 = dot(D,a0);
+ const float pa1 = dot(D,a1);
+ const float pa2 = dot(D,a2);
+ const float pb0 = dot(D,b0);
+ const float pb1 = dot(D,b1);
+ const float pb2 = dot(D,b2);
+
+ BBox1f ba = empty;
+ if (min(da0,da1) <= 0.0f && max(da0,da1) >= 0.0f && abs(da0-da1) > 0.0f) ba.extend(T(pa0,pa1,da0,da1));
+ if (min(da1,da2) <= 0.0f && max(da1,da2) >= 0.0f && abs(da1-da2) > 0.0f) ba.extend(T(pa1,pa2,da1,da2));
+ if (min(da2,da0) <= 0.0f && max(da2,da0) >= 0.0f && abs(da2-da0) > 0.0f) ba.extend(T(pa2,pa0,da2,da0));
+
+ BBox1f bb = empty;
+ if (min(db0,db1) <= 0.0f && max(db0,db1) >= 0.0f && abs(db0-db1) > 0.0f) bb.extend(T(pb0,pb1,db0,db1));
+ if (min(db1,db2) <= 0.0f && max(db1,db2) >= 0.0f && abs(db1-db2) > 0.0f) bb.extend(T(pb1,pb2,db1,db2));
+ if (min(db2,db0) <= 0.0f && max(db2,db0) >= 0.0f && abs(db2-db0) > 0.0f) bb.extend(T(pb2,pb0,db2,db0));
+
+ return conjoint(ba,bb);
+ }
+ };
+ }
+}
+
+
diff --git a/thirdparty/embree/kernels/geometry/trianglei.h b/thirdparty/embree/kernels/geometry/trianglei.h
new file mode 100644
index 0000000000..6aad48a5ef
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/trianglei.h
@@ -0,0 +1,442 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+#include "../common/scene.h"
+
+namespace embree
+{
+ /* Stores M triangles from an indexed face set */
+ template <int M>
+ struct TriangleMi
+ {
+ /* Virtual interface to query information about the triangle type */
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* primitive supports multiple time segments */
+ static const bool singleTimeSegment = false;
+
+ /* Returns maximum number of stored triangles */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
+
+ public:
+
+ /* Default constructor */
+ __forceinline TriangleMi() { }
+
+ /* Construction from vertices and IDs */
+ __forceinline TriangleMi(const vuint<M>& v0,
+ const vuint<M>& v1,
+ const vuint<M>& v2,
+ const vuint<M>& geomIDs,
+ const vuint<M>& primIDs)
+#if defined(EMBREE_COMPACT_POLYS)
+ : geomIDs(geomIDs), primIDs(primIDs) {}
+#else
+ : v0_(v0), v1_(v1), v2_(v2), geomIDs(geomIDs), primIDs(primIDs) {}
+#endif
+
+ /* Returns a mask that tells which triangles are valid */
+ __forceinline vbool<M> valid() const { return primIDs != vuint<M>(-1); }
+
+ /* Returns if the specified triangle is valid */
+ __forceinline bool valid(const size_t i) const { assert(i<M); return primIDs[i] != -1; }
+
+ /* Returns the number of stored triangles */
+ __forceinline size_t size() const { return bsf(~movemask(valid())); }
+
+ /* Returns the geometry IDs */
+ __forceinline vuint<M> geomID() const { return geomIDs; }
+ __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
+
+ /* Returns the primitive IDs */
+ __forceinline vuint<M> primID() const { return primIDs; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
+
+ /* Calculate the bounds of the triangles */
+ __forceinline const BBox3fa bounds(const Scene *const scene, const size_t itime=0) const
+ {
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<M && valid(i); i++) {
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(i));
+ bounds.extend(mesh->bounds(primID(i),itime));
+ }
+ return bounds;
+ }
+
+ /* Calculate the linear bounds of the primitive */
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime) {
+ return LBBox3fa(bounds(scene,itime+0),bounds(scene,itime+1));
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps)
+ {
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<M && valid(i); i++)
+ {
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(i));
+ allBounds.extend(mesh->linearBounds(primID(i), itime, numTimeSteps));
+ }
+ return allBounds;
+ }
+
+ __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range)
+ {
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<M && valid(i); i++)
+ {
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(i));
+ allBounds.extend(mesh->linearBounds(primID(i), time_range));
+ }
+ return allBounds;
+ }
+
+ /* Non-temporal store */
+ __forceinline static void store_nt(TriangleMi* dst, const TriangleMi& src)
+ {
+#if !defined(EMBREE_COMPACT_POLYS)
+ vuint<M>::store_nt(&dst->v0_,src.v0_);
+ vuint<M>::store_nt(&dst->v1_,src.v1_);
+ vuint<M>::store_nt(&dst->v2_,src.v2_);
+#endif
+ vuint<M>::store_nt(&dst->geomIDs,src.geomIDs);
+ vuint<M>::store_nt(&dst->primIDs,src.primIDs);
+ }
+
+ /* Fill triangle from triangle list */
+ template<typename PrimRefT>
+ __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene)
+ {
+ vuint<M> v0 = zero, v1 = zero, v2 = zero;
+ vuint<M> geomID = -1, primID = -1;
+ const PrimRefT* prim = &prims[begin];
+
+ for (size_t i=0; i<M; i++)
+ {
+ if (begin<end) {
+ geomID[i] = prim->geomID();
+ primID[i] = prim->primID();
+#if !defined(EMBREE_COMPACT_POLYS)
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(prim->geomID());
+ const TriangleMesh::Triangle& tri = mesh->triangle(prim->primID());
+ unsigned int int_stride = mesh->vertices0.getStride()/4;
+ v0[i] = tri.v[0] * int_stride;
+ v1[i] = tri.v[1] * int_stride;
+ v2[i] = tri.v[2] * int_stride;
+#endif
+ begin++;
+ } else {
+ assert(i);
+ if (likely(i > 0)) {
+ geomID[i] = geomID[0];
+ primID[i] = -1;
+ v0[i] = v0[0];
+ v1[i] = v0[0];
+ v2[i] = v0[0];
+ }
+ }
+ if (begin<end) prim = &prims[begin];
+ }
+ new (this) TriangleMi(v0,v1,v2,geomID,primID); // FIXME: use non temporal store
+ }
+
+ __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
+ {
+ fill(prims, begin, end, scene);
+ return linearBounds(scene, itime);
+ }
+
+ __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
+ {
+ fill(prims, begin, end, scene);
+ return linearBounds(scene, time_range);
+ }
+
+ /* Updates the primitive */
+ __forceinline BBox3fa update(TriangleMesh* mesh)
+ {
+ BBox3fa bounds = empty;
+ for (size_t i=0; i<M; i++)
+ {
+ if (primID(i) == -1) break;
+ const unsigned int primId = primID(i);
+ const TriangleMesh::Triangle& tri = mesh->triangle(primId);
+ const Vec3fa p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa p2 = mesh->vertex(tri.v[2]);
+ bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2)));
+ }
+ return bounds;
+ }
+
+ protected:
+#if !defined(EMBREE_COMPACT_POLYS)
+ vuint<M> v0_; // 4 byte offset of 1st vertex
+ vuint<M> v1_; // 4 byte offset of 2nd vertex
+ vuint<M> v2_; // 4 byte offset of 3rd vertex
+#endif
+ vuint<M> geomIDs; // geometry ID of mesh
+ vuint<M> primIDs; // primitive ID of primitive inside mesh
+ };
+
+ namespace isa
+ {
+
+ template<int M>
+ struct TriangleMi : public embree::TriangleMi<M>
+ {
+#if !defined(EMBREE_COMPACT_POLYS)
+ using embree::TriangleMi<M>::v0_;
+ using embree::TriangleMi<M>::v1_;
+ using embree::TriangleMi<M>::v2_;
+#endif
+ using embree::TriangleMi<M>::geomIDs;
+ using embree::TriangleMi<M>::primIDs;
+ using embree::TriangleMi<M>::geomID;
+ using embree::TriangleMi<M>::primID;
+ using embree::TriangleMi<M>::valid;
+
+ /* loads a single vertex */
+ template<int vid>
+ __forceinline Vec3f getVertex(const size_t index, const Scene *const scene) const
+ {
+#if defined(EMBREE_COMPACT_POLYS)
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID(index));
+ return (Vec3f) mesh->vertices[0][tri.v[vid]];
+#else
+ const vuint<M>& v = getVertexOffset<vid>();
+ const float* vertices = scene->vertices[geomID(index)];
+ return (Vec3f&) vertices[v[index]];
+#endif
+ }
+
+ template<int vid, typename T>
+ __forceinline Vec3<T> getVertex(const size_t index, const Scene *const scene, const size_t itime, const T& ftime) const
+ {
+#if defined(EMBREE_COMPACT_POLYS)
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID(index));
+ const Vec3fa v0 = mesh->vertices[itime+0][tri.v[vid]];
+ const Vec3fa v1 = mesh->vertices[itime+1][tri.v[vid]];
+#else
+ const vuint<M>& v = getVertexOffset<vid>();
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
+ const float* vertices0 = (const float*) mesh->vertexPtr(0,itime+0);
+ const float* vertices1 = (const float*) mesh->vertexPtr(0,itime+1);
+ const Vec3fa v0 = Vec3fa::loadu(vertices0+v[index]);
+ const Vec3fa v1 = Vec3fa::loadu(vertices1+v[index]);
+#endif
+ const Vec3<T> p0(v0.x,v0.y,v0.z);
+ const Vec3<T> p1(v1.x,v1.y,v1.z);
+ return lerp(p0,p1,ftime);
+ }
+
+ template<int vid, int K, typename T>
+ __forceinline Vec3<T> getVertex(const vbool<K>& valid, const size_t index, const Scene *const scene, const vint<K>& itime, const T& ftime) const
+ {
+ Vec3<T> p0, p1;
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
+
+ for (size_t mask=movemask(valid), i=bsf(mask); mask; mask=btc(mask,i), i=bsf(mask))
+ {
+#if defined(EMBREE_COMPACT_POLYS)
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID(index));
+ const Vec3fa v0 = mesh->vertices[itime[i]+0][tri.v[vid]];
+ const Vec3fa v1 = mesh->vertices[itime[i]+1][tri.v[vid]];
+#else
+ const vuint<M>& v = getVertexOffset<vid>();
+ const float* vertices0 = (const float*) mesh->vertexPtr(0,itime[i]+0);
+ const float* vertices1 = (const float*) mesh->vertexPtr(0,itime[i]+1);
+ const Vec3fa v0 = Vec3fa::loadu(vertices0+v[index]);
+ const Vec3fa v1 = Vec3fa::loadu(vertices1+v[index]);
+#endif
+ p0.x[i] = v0.x; p0.y[i] = v0.y; p0.z[i] = v0.z;
+ p1.x[i] = v1.x; p1.y[i] = v1.y; p1.z[i] = v1.z;
+ }
+ return (T(one)-ftime)*p0 + ftime*p1;
+ }
+
+ struct Triangle {
+ vfloat4 v0,v1,v2;
+ };
+
+#if defined(EMBREE_COMPACT_POLYS)
+
+ __forceinline Triangle loadTriangle(const int i, const Scene* const scene) const
+ {
+ const unsigned int geomID = geomIDs[i];
+ const unsigned int primID = primIDs[i];
+ if (unlikely(primID == -1)) return { zero, zero, zero };
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID);
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ const vfloat4 v0 = (vfloat4) mesh->vertices0[tri.v[0]];
+ const vfloat4 v1 = (vfloat4) mesh->vertices0[tri.v[1]];
+ const vfloat4 v2 = (vfloat4) mesh->vertices0[tri.v[2]];
+ return { v0, v1, v2 };
+ }
+
+ __forceinline Triangle loadTriangle(const int i, const int itime, const TriangleMesh* const mesh) const
+ {
+ const unsigned int primID = primIDs[i];
+ if (unlikely(primID == -1)) return { zero, zero, zero };
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ const vfloat4 v0 = (vfloat4) mesh->vertices[itime][tri.v[0]];
+ const vfloat4 v1 = (vfloat4) mesh->vertices[itime][tri.v[1]];
+ const vfloat4 v2 = (vfloat4) mesh->vertices[itime][tri.v[2]];
+ return { v0, v1, v2 };
+ }
+
+#else
+
+ __forceinline Triangle loadTriangle(const int i, const Scene* const scene) const
+ {
+ const float* vertices = scene->vertices[geomID(i)];
+ const vfloat4 v0 = vfloat4::loadu(vertices + v0_[i]);
+ const vfloat4 v1 = vfloat4::loadu(vertices + v1_[i]);
+ const vfloat4 v2 = vfloat4::loadu(vertices + v2_[i]);
+ return { v0, v1, v2 };
+ }
+
+ __forceinline Triangle loadTriangle(const int i, const int itime, const TriangleMesh* const mesh) const
+ {
+ const float* vertices = (const float*) mesh->vertexPtr(0,itime);
+ const vfloat4 v0 = vfloat4::loadu(vertices + v0_[i]);
+ const vfloat4 v1 = vfloat4::loadu(vertices + v1_[i]);
+ const vfloat4 v2 = vfloat4::loadu(vertices + v2_[i]);
+ return { v0, v1, v2 };
+ }
+
+#endif
+
+ /* Gather the triangles */
+ __forceinline void gather(Vec3vf<M>& p0, Vec3vf<M>& p1, Vec3vf<M>& p2, const Scene* const scene) const;
+
+ template<int K>
+#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 2000) // workaround for compiler bug in ICC 2019
+ __noinline
+#else
+ __forceinline
+#endif
+ void gather(const vbool<K>& valid,
+ Vec3vf<K>& p0,
+ Vec3vf<K>& p1,
+ Vec3vf<K>& p2,
+ const size_t index,
+ const Scene* const scene,
+ const vfloat<K>& time) const
+ {
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(index));
+
+ vfloat<K> ftime;
+ const vint<K> itime = mesh->timeSegment<K>(time, ftime);
+
+ const size_t first = bsf(movemask(valid));
+ if (likely(all(valid,itime[first] == itime)))
+ {
+ p0 = getVertex<0>(index, scene, itime[first], ftime);
+ p1 = getVertex<1>(index, scene, itime[first], ftime);
+ p2 = getVertex<2>(index, scene, itime[first], ftime);
+ } else {
+ p0 = getVertex<0,K>(valid, index, scene, itime, ftime);
+ p1 = getVertex<1,K>(valid, index, scene, itime, ftime);
+ p2 = getVertex<2,K>(valid, index, scene, itime, ftime);
+ }
+ }
+
+ __forceinline void gather(Vec3vf<M>& p0,
+ Vec3vf<M>& p1,
+ Vec3vf<M>& p2,
+ const TriangleMesh* mesh,
+ const Scene *const scene,
+ const int itime) const;
+
+ __forceinline void gather(Vec3vf<M>& p0,
+ Vec3vf<M>& p1,
+ Vec3vf<M>& p2,
+ const Scene *const scene,
+ const float time) const;
+
+
+#if !defined(EMBREE_COMPACT_POLYS)
+ template<int N> const vuint<M>& getVertexOffset() const;
+#endif
+ };
+
+#if !defined(EMBREE_COMPACT_POLYS)
+ template<> template<> __forceinline const vuint<4>& TriangleMi<4>::getVertexOffset<0>() const { return v0_; }
+ template<> template<> __forceinline const vuint<4>& TriangleMi<4>::getVertexOffset<1>() const { return v1_; }
+ template<> template<> __forceinline const vuint<4>& TriangleMi<4>::getVertexOffset<2>() const { return v2_; }
+#endif
+
+ template<>
+ __forceinline void TriangleMi<4>::gather(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ const Scene* const scene) const
+ {
+ const Triangle tri0 = loadTriangle(0,scene);
+ const Triangle tri1 = loadTriangle(1,scene);
+ const Triangle tri2 = loadTriangle(2,scene);
+ const Triangle tri3 = loadTriangle(3,scene);
+ transpose(tri0.v0,tri1.v0,tri2.v0,tri3.v0,p0.x,p0.y,p0.z);
+ transpose(tri0.v1,tri1.v1,tri2.v1,tri3.v1,p1.x,p1.y,p1.z);
+ transpose(tri0.v2,tri1.v2,tri2.v2,tri3.v2,p2.x,p2.y,p2.z);
+ }
+
+ template<>
+ __forceinline void TriangleMi<4>::gather(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ const TriangleMesh* mesh,
+ const Scene *const scene,
+ const int itime) const
+ {
+ const Triangle tri0 = loadTriangle(0,itime,mesh);
+ const Triangle tri1 = loadTriangle(1,itime,mesh);
+ const Triangle tri2 = loadTriangle(2,itime,mesh);
+ const Triangle tri3 = loadTriangle(3,itime,mesh);
+ transpose(tri0.v0,tri1.v0,tri2.v0,tri3.v0,p0.x,p0.y,p0.z);
+ transpose(tri0.v1,tri1.v1,tri2.v1,tri3.v1,p1.x,p1.y,p1.z);
+ transpose(tri0.v2,tri1.v2,tri2.v2,tri3.v2,p2.x,p2.y,p2.z);
+ }
+
+ template<>
+ __forceinline void TriangleMi<4>::gather(Vec3vf4& p0,
+ Vec3vf4& p1,
+ Vec3vf4& p2,
+ const Scene *const scene,
+ const float time) const
+ {
+ const TriangleMesh* mesh = scene->get<TriangleMesh>(geomID(0)); // in mblur mode all geometries are identical
+
+ float ftime;
+ const int itime = mesh->timeSegment(time, ftime);
+
+ Vec3vf4 a0,a1,a2; gather(a0,a1,a2,mesh,scene,itime);
+ Vec3vf4 b0,b1,b2; gather(b0,b1,b2,mesh,scene,itime+1);
+ p0 = lerp(a0,b0,vfloat4(ftime));
+ p1 = lerp(a1,b1,vfloat4(ftime));
+ p2 = lerp(a2,b2,vfloat4(ftime));
+ }
+ }
+
+ template<int M>
+ typename TriangleMi<M>::Type TriangleMi<M>::type;
+
+ typedef TriangleMi<4> Triangle4i;
+}
diff --git a/thirdparty/embree/kernels/geometry/trianglei_intersector.h b/thirdparty/embree/kernels/geometry/trianglei_intersector.h
new file mode 100644
index 0000000000..f7deb9e72d
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/trianglei_intersector.h
@@ -0,0 +1,336 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "trianglei.h"
+#include "triangle_intersector_moeller.h"
+#include "triangle_intersector_pluecker.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Intersects M triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMiIntersector1Moeller
+ {
+ typedef TriangleMi<M> Primitive;
+ typedef MoellerTrumboreIntersector1<M> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
+ pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
+ return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+ /*! Intersects M triangles with K rays */
+ template<int M, int K, bool filter>
+ struct TriangleMiIntersectorKMoeller
+ {
+ typedef TriangleMi<M> Primitive;
+ typedef MoellerTrumboreIntersectorK<M,K> Precalculations;
+
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri)
+ {
+ const Scene* scene = context->scene;
+ for (size_t i=0; i<Primitive::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),RayHitK<K>::size());
+ const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene);
+ const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene);
+ const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene);
+ pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri)
+ {
+ vbool<K> valid0 = valid_i;
+ const Scene* scene = context->scene;
+
+ for (size_t i=0; i<Primitive::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid_i),RayHitK<K>::size());
+ const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene);
+ const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene);
+ const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene);
+ pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
+ pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
+ return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+ };
+
+ /*! Intersects M triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMiIntersector1Pluecker
+ {
+ typedef TriangleMi<M> Primitive;
+ typedef PlueckerIntersector1<M> Precalculations;
+
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
+ pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
+ return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+ /*! Intersects M triangles with K rays */
+ template<int M, int K, bool filter>
+ struct TriangleMiIntersectorKPluecker
+ {
+ typedef TriangleMi<M> Primitive;
+ typedef PlueckerIntersectorK<M,K> Precalculations;
+
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri)
+ {
+ const Scene* scene = context->scene;
+ for (size_t i=0; i<Primitive::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),RayHitK<K>::size());
+ const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene);
+ const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene);
+ const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene);
+ pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri)
+ {
+ vbool<K> valid0 = valid_i;
+ const Scene* scene = context->scene;
+
+ for (size_t i=0; i<Primitive::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid_i),RayHitK<K>::size());
+ const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene);
+ const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene);
+ const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene);
+ pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
+ pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene);
+ return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+ };
+
+ /*! Intersects M motion blur triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMiMBIntersector1Moeller
+ {
+ typedef TriangleMi<M> Primitive;
+ typedef MoellerTrumboreIntersector1<M> Precalculations;
+
+ /*! Intersect a ray with the M triangles and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time());
+ pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of M triangles. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time());
+ return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+ /*! Intersects M motion blur triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct TriangleMiMBIntersectorKMoeller
+ {
+ typedef TriangleMi<M> Primitive;
+ typedef MoellerTrumboreIntersectorK<M,K> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri)
+ {
+ for (size_t i=0; i<TriangleMi<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ Vec3vf<K> v0,v1,v2; tri.template gather<K>(valid_i,v0,v1,v2,i,context->scene,ray.time());
+ pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri)
+ {
+ vbool<K> valid0 = valid_i;
+ for (size_t i=0; i<TriangleMi<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ Vec3vf<K> v0,v1,v2; tri.template gather<K>(valid_i,v0,v1,v2,i,context->scene,ray.time());
+ pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]);
+ pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]);
+ return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+ };
+
+ /*! Intersects M motion blur triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMiMBIntersector1Pluecker
+ {
+ typedef TriangleMi<M> Primitive;
+ typedef PlueckerIntersector1<M> Precalculations;
+
+ /*! Intersect a ray with the M triangles and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time());
+ pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of M triangles. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time());
+ return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+ /*! Intersects M motion blur triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct TriangleMiMBIntersectorKPluecker
+ {
+ typedef TriangleMi<M> Primitive;
+ typedef PlueckerIntersectorK<M,K> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri)
+ {
+ for (size_t i=0; i<TriangleMi<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ Vec3vf<K> v0,v1,v2; tri.template gather<K>(valid_i,v0,v1,v2,i,context->scene,ray.time());
+ pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri)
+ {
+ vbool<K> valid0 = valid_i;
+ for (size_t i=0; i<TriangleMi<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ Vec3vf<K> v0,v1,v2; tri.template gather<K>(valid_i,v0,v1,v2,i,context->scene,ray.time());
+ pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]);
+ pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]);
+ return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/trianglev.h b/thirdparty/embree/kernels/geometry/trianglev.h
new file mode 100644
index 0000000000..cd94756b9e
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/trianglev.h
@@ -0,0 +1,157 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+
+namespace embree
+{
+ /* Stores the vertices of M triangles in struct of array layout */
+ template <int M>
+ struct TriangleMv
+ {
+ public:
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+ static Type type;
+
+ public:
+
+ /* Returns maximum number of stored triangles */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
+
+ public:
+
+ /* Default constructor */
+ __forceinline TriangleMv() {}
+
+ /* Construction from vertices and IDs */
+ __forceinline TriangleMv(const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const vuint<M>& geomIDs, const vuint<M>& primIDs)
+ : v0(v0), v1(v1), v2(v2), geomIDs(geomIDs), primIDs(primIDs) {}
+
+ /* Returns a mask that tells which triangles are valid */
+ __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); }
+
+ /* Returns true if the specified triangle is valid */
+ __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; }
+
+ /* Returns the number of stored triangles */
+ __forceinline size_t size() const { return bsf(~movemask(valid())); }
+
+ /* Returns the geometry IDs */
+ __forceinline vuint<M>& geomID() { return geomIDs; }
+ __forceinline const vuint<M>& geomID() const { return geomIDs; }
+ __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
+
+ /* Returns the primitive IDs */
+ __forceinline vuint<M>& primID() { return primIDs; }
+ __forceinline const vuint<M>& primID() const { return primIDs; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
+
+ /* Calculate the bounds of the triangles */
+ __forceinline BBox3fa bounds() const
+ {
+ Vec3vf<M> lower = min(v0,v1,v2);
+ Vec3vf<M> upper = max(v0,v1,v2);
+ vbool<M> mask = valid();
+ lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
+ lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
+ lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
+ upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
+ upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
+ upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
+ return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
+ Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
+ }
+
+ /* Non temporal store */
+ __forceinline static void store_nt(TriangleMv* dst, const TriangleMv& src)
+ {
+ vfloat<M>::store_nt(&dst->v0.x,src.v0.x);
+ vfloat<M>::store_nt(&dst->v0.y,src.v0.y);
+ vfloat<M>::store_nt(&dst->v0.z,src.v0.z);
+ vfloat<M>::store_nt(&dst->v1.x,src.v1.x);
+ vfloat<M>::store_nt(&dst->v1.y,src.v1.y);
+ vfloat<M>::store_nt(&dst->v1.z,src.v1.z);
+ vfloat<M>::store_nt(&dst->v2.x,src.v2.x);
+ vfloat<M>::store_nt(&dst->v2.y,src.v2.y);
+ vfloat<M>::store_nt(&dst->v2.z,src.v2.z);
+ vuint<M>::store_nt(&dst->geomIDs,src.geomIDs);
+ vuint<M>::store_nt(&dst->primIDs,src.primIDs);
+ }
+
+ /* Fill triangle from triangle list */
+ __forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
+ {
+ vuint<M> vgeomID = -1, vprimID = -1;
+ Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
+
+ for (size_t i=0; i<M && begin<end; i++, begin++)
+ {
+ const PrimRef& prim = prims[begin];
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(geomID);
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ const Vec3fa& p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa& p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa& p2 = mesh->vertex(tri.v[2]);
+ vgeomID [i] = geomID;
+ vprimID [i] = primID;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ }
+ TriangleMv::store_nt(this,TriangleMv(v0,v1,v2,vgeomID,vprimID));
+ }
+
+ /* Updates the primitive */
+ __forceinline BBox3fa update(TriangleMesh* mesh)
+ {
+ BBox3fa bounds = empty;
+ vuint<M> vgeomID = -1, vprimID = -1;
+ Vec3vf<M> v0 = zero, v1 = zero, v2 = zero;
+
+ for (size_t i=0; i<M; i++)
+ {
+ if (primID(i) == -1) break;
+ const unsigned geomId = geomID(i);
+ const unsigned primId = primID(i);
+ const TriangleMesh::Triangle& tri = mesh->triangle(primId);
+ const Vec3fa p0 = mesh->vertex(tri.v[0]);
+ const Vec3fa p1 = mesh->vertex(tri.v[1]);
+ const Vec3fa p2 = mesh->vertex(tri.v[2]);
+ bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2)));
+ vgeomID [i] = geomId;
+ vprimID [i] = primId;
+ v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
+ v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
+ v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
+ }
+ new (this) TriangleMv(v0,v1,v2,vgeomID,vprimID);
+ return bounds;
+ }
+
+ public:
+ Vec3vf<M> v0; // 1st vertex of the triangles
+ Vec3vf<M> v1; // 2nd vertex of the triangles
+ Vec3vf<M> v2; // 3rd vertex of the triangles
+ private:
+ vuint<M> geomIDs; // geometry ID
+ vuint<M> primIDs; // primitive ID
+ };
+
+ template<int M>
+ typename TriangleMv<M>::Type TriangleMv<M>::type;
+
+ typedef TriangleMv<4> Triangle4v;
+}
diff --git a/thirdparty/embree/kernels/geometry/trianglev_intersector.h b/thirdparty/embree/kernels/geometry/trianglev_intersector.h
new file mode 100644
index 0000000000..3abb7f8e32
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/trianglev_intersector.h
@@ -0,0 +1,206 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "triangle.h"
+#include "triangle_intersector_pluecker.h"
+#include "triangle_intersector_moeller.h"
+#include "triangle_intersector_woop.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Intersects M triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMvIntersector1Moeller
+ {
+ typedef TriangleMv<M> Primitive;
+ typedef MoellerTrumboreIntersector1<M> Precalculations;
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity<M>(),*/Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity<M>(),*/Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+
+ template<int M, bool filter>
+ struct TriangleMvIntersector1Woop
+ {
+ typedef TriangleMv<M> Primitive;
+ typedef WoopIntersector1<M> intersec;
+ typedef WoopPrecalculations1<M> Precalculations;
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+
+ /*! Intersects M triangles with K rays */
+ template<int M, int K, bool filter>
+ struct TriangleMvIntersectorKMoeller
+ {
+ typedef TriangleMv<M> Primitive;
+ typedef MoellerTrumboreIntersectorK<M,K> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri)
+ {
+ for (size_t i=0; i<M; i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i);
+ const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i);
+ const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i);
+ pre.intersectK(valid_i,ray,v0,v1,v2,/*UVIdentity<K>(),*/IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri)
+ {
+ vbool<K> valid0 = valid_i;
+
+ for (size_t i=0; i<M; i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i);
+ const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i);
+ const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i);
+ pre.intersectK(valid0,ray,v0,v1,v2,/*UVIdentity<K>(),*/OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity<M>(),*/Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity<M>(),*/Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M
+ }
+ };
+
+ /*! Intersects M triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMvIntersector1Pluecker
+ {
+ typedef TriangleMv<M> Primitive;
+ typedef PlueckerIntersector1<M> Precalculations;
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity<M>(),Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity<M>(),Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+ /*! Intersects M triangles with K rays */
+ template<int M, int K, bool filter>
+ struct TriangleMvIntersectorKPluecker
+ {
+ typedef TriangleMv<M> Primitive;
+ typedef PlueckerIntersectorK<M,K> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri)
+ {
+ for (size_t i=0; i<M; i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i);
+ const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i);
+ const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i);
+ pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri)
+ {
+ vbool<K> valid0 = valid_i;
+
+ for (size_t i=0; i<M; i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i);
+ const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i);
+ const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i);
+ pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity<M>(),Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity<M>(),Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/geometry/trianglev_mb.h b/thirdparty/embree/kernels/geometry/trianglev_mb.h
new file mode 100644
index 0000000000..b550a29fd5
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/trianglev_mb.h
@@ -0,0 +1,201 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "primitive.h"
+
+namespace embree
+{
+ /* Stores the vertices of M triangles in struct of array layout */
+ template<int M>
+ struct TriangleMvMB
+ {
+ public:
+ struct Type : public PrimitiveType
+ {
+ const char* name() const;
+ size_t sizeActive(const char* This) const;
+ size_t sizeTotal(const char* This) const;
+ size_t getBytes(const char* This) const;
+ };
+
+ static Type type;
+
+ public:
+
+ /* primitive supports single time segments */
+ static const bool singleTimeSegment = true;
+
+ /* Returns maximum number of stored triangles */
+ static __forceinline size_t max_size() { return M; }
+
+ /* Returns required number of primitive blocks for N primitives */
+ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
+
+ public:
+
+ /* Default constructor */
+ __forceinline TriangleMvMB() {}
+
+ /* Construction from vertices and IDs */
+ __forceinline TriangleMvMB(const Vec3vf<M>& a0, const Vec3vf<M>& a1,
+ const Vec3vf<M>& b0, const Vec3vf<M>& b1,
+ const Vec3vf<M>& c0, const Vec3vf<M>& c1,
+ const vuint<M>& geomIDs, const vuint<M>& primIDs)
+ : v0(a0), v1(b0), v2(c0), dv0(a1-a0), dv1(b1-b0), dv2(c1-c0), geomIDs(geomIDs), primIDs(primIDs) {}
+
+ /* Returns a mask that tells which triangles are valid */
+ __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); }
+
+ /* Returns if the specified triangle is valid */
+ __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; }
+
+ /* Returns the number of stored triangles */
+ __forceinline size_t size() const { return bsf(~movemask(valid())); }
+
+ /* Returns the geometry IDs */
+ __forceinline vuint<M>& geomID() { return geomIDs; }
+ __forceinline const vuint<M>& geomID() const { return geomIDs; }
+ __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; }
+
+ /* Returns the primitive IDs */
+ __forceinline vuint<M>& primID() { return primIDs; }
+ __forceinline const vuint<M>& primID() const { return primIDs; }
+ __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; }
+
+ /* Calculate the bounds of the triangles at t0 */
+ __forceinline BBox3fa bounds0() const
+ {
+ Vec3vf<M> lower = min(v0,v1,v2);
+ Vec3vf<M> upper = max(v0,v1,v2);
+ const vbool<M> mask = valid();
+ lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
+ lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
+ lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
+ upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
+ upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
+ upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
+ return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
+ Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
+ }
+
+ /* Calculate the bounds of the triangles at t1 */
+ __forceinline BBox3fa bounds1() const
+ {
+ const Vec3vf<M> p0 = v0+dv0;
+ const Vec3vf<M> p1 = v1+dv1;
+ const Vec3vf<M> p2 = v2+dv2;
+ Vec3vf<M> lower = min(p0,p1,p2);
+ Vec3vf<M> upper = max(p0,p1,p2);
+ const vbool<M> mask = valid();
+ lower.x = select(mask,lower.x,vfloat<M>(pos_inf));
+ lower.y = select(mask,lower.y,vfloat<M>(pos_inf));
+ lower.z = select(mask,lower.z,vfloat<M>(pos_inf));
+ upper.x = select(mask,upper.x,vfloat<M>(neg_inf));
+ upper.y = select(mask,upper.y,vfloat<M>(neg_inf));
+ upper.z = select(mask,upper.z,vfloat<M>(neg_inf));
+ return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)),
+ Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z)));
+ }
+
+ /* Calculate the linear bounds of the primitive */
+ __forceinline LBBox3fa linearBounds() const {
+ return LBBox3fa(bounds0(),bounds1());
+ }
+
+ /* Fill triangle from triangle list */
+ __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime)
+ {
+ vuint<M> vgeomID = -1, vprimID = -1;
+ Vec3vf<M> va0 = zero, vb0 = zero, vc0 = zero;
+ Vec3vf<M> va1 = zero, vb1 = zero, vc1 = zero;
+
+ BBox3fa bounds0 = empty;
+ BBox3fa bounds1 = empty;
+
+ for (size_t i=0; i<M && begin<end; i++, begin++)
+ {
+ const PrimRef& prim = prims[begin];
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(geomID);
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ const Vec3fa& a0 = mesh->vertex(tri.v[0],itime+0); bounds0.extend(a0);
+ const Vec3fa& a1 = mesh->vertex(tri.v[0],itime+1); bounds1.extend(a1);
+ const Vec3fa& b0 = mesh->vertex(tri.v[1],itime+0); bounds0.extend(b0);
+ const Vec3fa& b1 = mesh->vertex(tri.v[1],itime+1); bounds1.extend(b1);
+ const Vec3fa& c0 = mesh->vertex(tri.v[2],itime+0); bounds0.extend(c0);
+ const Vec3fa& c1 = mesh->vertex(tri.v[2],itime+1); bounds1.extend(c1);
+ vgeomID [i] = geomID;
+ vprimID [i] = primID;
+ va0.x[i] = a0.x; va0.y[i] = a0.y; va0.z[i] = a0.z;
+ va1.x[i] = a1.x; va1.y[i] = a1.y; va1.z[i] = a1.z;
+ vb0.x[i] = b0.x; vb0.y[i] = b0.y; vb0.z[i] = b0.z;
+ vb1.x[i] = b1.x; vb1.y[i] = b1.y; vb1.z[i] = b1.z;
+ vc0.x[i] = c0.x; vc0.y[i] = c0.y; vc0.z[i] = c0.z;
+ vc1.x[i] = c1.x; vc1.y[i] = c1.y; vc1.z[i] = c1.z;
+ }
+ new (this) TriangleMvMB(va0,va1,vb0,vb1,vc0,vc1,vgeomID,vprimID);
+ return LBBox3fa(bounds0,bounds1);
+ }
+
+ /* Fill triangle from triangle list */
+ __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range)
+ {
+ vuint<M> vgeomID = -1, vprimID = -1;
+ Vec3vf<M> va0 = zero, vb0 = zero, vc0 = zero;
+ Vec3vf<M> va1 = zero, vb1 = zero, vc1 = zero;
+
+ LBBox3fa allBounds = empty;
+ for (size_t i=0; i<M && begin<end; i++, begin++)
+ {
+ const PrimRefMB& prim = prims[begin];
+ const unsigned geomID = prim.geomID();
+ const unsigned primID = prim.primID();
+ const TriangleMesh* const mesh = scene->get<TriangleMesh>(geomID);
+ const range<int> itime_range = mesh->timeSegmentRange(time_range);
+ assert(itime_range.size() == 1);
+ const int ilower = itime_range.begin();
+ const TriangleMesh::Triangle& tri = mesh->triangle(primID);
+ allBounds.extend(mesh->linearBounds(primID, time_range));
+ const Vec3fa& a0 = mesh->vertex(tri.v[0],ilower+0);
+ const Vec3fa& a1 = mesh->vertex(tri.v[0],ilower+1);
+ const Vec3fa& b0 = mesh->vertex(tri.v[1],ilower+0);
+ const Vec3fa& b1 = mesh->vertex(tri.v[1],ilower+1);
+ const Vec3fa& c0 = mesh->vertex(tri.v[2],ilower+0);
+ const Vec3fa& c1 = mesh->vertex(tri.v[2],ilower+1);
+ const BBox1f time_range_v(mesh->timeStep(ilower+0),mesh->timeStep(ilower+1));
+ auto a01 = globalLinear(std::make_pair(a0,a1),time_range_v);
+ auto b01 = globalLinear(std::make_pair(b0,b1),time_range_v);
+ auto c01 = globalLinear(std::make_pair(c0,c1),time_range_v);
+ vgeomID [i] = geomID;
+ vprimID [i] = primID;
+ va0.x[i] = a01.first .x; va0.y[i] = a01.first .y; va0.z[i] = a01.first .z;
+ va1.x[i] = a01.second.x; va1.y[i] = a01.second.y; va1.z[i] = a01.second.z;
+ vb0.x[i] = b01.first .x; vb0.y[i] = b01.first .y; vb0.z[i] = b01.first .z;
+ vb1.x[i] = b01.second.x; vb1.y[i] = b01.second.y; vb1.z[i] = b01.second.z;
+ vc0.x[i] = c01.first .x; vc0.y[i] = c01.first .y; vc0.z[i] = c01.first .z;
+ vc1.x[i] = c01.second.x; vc1.y[i] = c01.second.y; vc1.z[i] = c01.second.z;
+ }
+ new (this) TriangleMvMB(va0,va1,vb0,vb1,vc0,vc1,vgeomID,vprimID);
+ return allBounds;
+ }
+
+ public:
+ Vec3vf<M> v0; // 1st vertex of the triangles
+ Vec3vf<M> v1; // 2nd vertex of the triangles
+ Vec3vf<M> v2; // 3rd vertex of the triangles
+ Vec3vf<M> dv0; // difference vector between time steps t0 and t1 for first vertex
+ Vec3vf<M> dv1; // difference vector between time steps t0 and t1 for second vertex
+ Vec3vf<M> dv2; // difference vector between time steps t0 and t1 for third vertex
+ private:
+ vuint<M> geomIDs; // geometry ID
+ vuint<M> primIDs; // primitive ID
+ };
+
+ template<int M>
+ typename TriangleMvMB<M>::Type TriangleMvMB<M>::type;
+
+ typedef TriangleMvMB<4> Triangle4vMB;
+}
diff --git a/thirdparty/embree/kernels/geometry/trianglev_mb_intersector.h b/thirdparty/embree/kernels/geometry/trianglev_mb_intersector.h
new file mode 100644
index 0000000000..38cd52e85d
--- /dev/null
+++ b/thirdparty/embree/kernels/geometry/trianglev_mb_intersector.h
@@ -0,0 +1,211 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "triangle.h"
+#include "intersector_epilog.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ /*! Intersects M motion blur triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMvMBIntersector1Moeller
+ {
+ typedef TriangleMvMB<M> Primitive;
+ typedef MoellerTrumboreIntersector1<M> Precalculations;
+
+ /*! Intersect a ray with the M triangles and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const Vec3vf<M> time(ray.time());
+ const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
+ const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
+ const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
+ pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of M triangles. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const Vec3vf<M> time(ray.time());
+ const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
+ const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
+ const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
+ return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+ /*! Intersects M motion blur triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct TriangleMvMBIntersectorKMoeller
+ {
+ typedef TriangleMvMB<M> Primitive;
+ typedef MoellerTrumboreIntersectorK<M,K> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> time(ray.time());
+ const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
+ const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
+ const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
+ pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ vbool<K> valid0 = valid_i;
+
+ for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ const Vec3vf<K> time(ray.time());
+ const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
+ const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
+ const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
+ pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const Vec3vf<M> time(ray.time()[k]);
+ const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
+ const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
+ const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
+ pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const Vec3vf<M> time(ray.time()[k]);
+ const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
+ const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
+ const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
+ return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+ };
+
+ /*! Intersects M motion blur triangles with 1 ray */
+ template<int M, bool filter>
+ struct TriangleMvMBIntersector1Pluecker
+ {
+ typedef TriangleMvMB<M> Primitive;
+ typedef PlueckerIntersector1<M> Precalculations;
+
+ /*! Intersect a ray with the M triangles and updates the hit. */
+ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const Vec3vf<M> time(ray.time());
+ const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
+ const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
+ const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
+ pre.intersect(ray,v0,v1,v2,UVIdentity<M>(),Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of M triangles. */
+ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const Vec3vf<M> time(ray.time());
+ const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
+ const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
+ const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
+ return pre.intersect(ray,v0,v1,v2,UVIdentity<M>(),Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
+ }
+
+ static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
+ {
+ return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
+ }
+ };
+
+ /*! Intersects M motion blur triangles with K rays. */
+ template<int M, int K, bool filter>
+ struct TriangleMvMBIntersectorKPluecker
+ {
+ typedef TriangleMvMB<M> Primitive;
+ typedef PlueckerIntersectorK<M,K> Precalculations;
+
+ /*! Intersects K rays with M triangles. */
+ static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(normal.trav_prims,1,popcnt(valid_i),K);
+ const Vec3vf<K> time(ray.time());
+ const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
+ const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
+ const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
+ pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
+ }
+ }
+
+ /*! Test for K rays if they are occluded by any of the M triangles. */
+ static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ vbool<K> valid0 = valid_i;
+
+ for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
+ {
+ if (!tri.valid(i)) break;
+ STAT3(shadow.trav_prims,1,popcnt(valid0),K);
+ const Vec3vf<K> time(ray.time());
+ const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
+ const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
+ const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
+ pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
+ if (none(valid0)) break;
+ }
+ return !valid0;
+ }
+
+ /*! Intersect a ray with M triangles and updates the hit. */
+ static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ STAT3(normal.trav_prims,1,1,1);
+ const Vec3vf<M> time(ray.time()[k]);
+ const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
+ const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
+ const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
+ pre.intersect(ray,k,v0,v1,v2,UVIdentity<M>(),Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+
+ /*! Test if the ray is occluded by one of the M triangles. */
+ static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
+ {
+ STAT3(shadow.trav_prims,1,1,1);
+ const Vec3vf<M> time(ray.time()[k]);
+ const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
+ const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
+ const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
+ return pre.intersect(ray,k,v0,v1,v2,UVIdentity<M>(),Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
+ }
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/hash.h b/thirdparty/embree/kernels/hash.h
new file mode 100644
index 0000000000..10f315cee7
--- /dev/null
+++ b/thirdparty/embree/kernels/hash.h
@@ -0,0 +1,5 @@
+
+// Copyright 2009-2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#define RTC_HASH "7c53133eb21424f7f0ae1e25bf357e358feaf6ab"
diff --git a/thirdparty/embree/kernels/subdiv/bezier_curve.h b/thirdparty/embree/kernels/subdiv/bezier_curve.h
new file mode 100644
index 0000000000..a5adad5cc9
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/bezier_curve.h
@@ -0,0 +1,671 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+//#include "../common/scene_curves.h"
+#include "../common/context.h"
+
+namespace embree
+{
+ class BezierBasis
+ {
+ public:
+
+ template<typename T>
+ static __forceinline Vec4<T> eval(const T& u)
+ {
+ const T t1 = u;
+ const T t0 = 1.0f-t1;
+ const T B0 = t0 * t0 * t0;
+ const T B1 = 3.0f * t1 * (t0 * t0);
+ const T B2 = 3.0f * (t1 * t1) * t0;
+ const T B3 = t1 * t1 * t1;
+ return Vec4<T>(B0,B1,B2,B3);
+ }
+
+ template<typename T>
+ static __forceinline Vec4<T> derivative(const T& u)
+ {
+ const T t1 = u;
+ const T t0 = 1.0f-t1;
+ const T B0 = -(t0*t0);
+ const T B1 = madd(-2.0f,t0*t1,t0*t0);
+ const T B2 = msub(+2.0f,t0*t1,t1*t1);
+ const T B3 = +(t1*t1);
+ return T(3.0f)*Vec4<T>(B0,B1,B2,B3);
+ }
+
+ template<typename T>
+ static __forceinline Vec4<T> derivative2(const T& u)
+ {
+ const T t1 = u;
+ const T t0 = 1.0f-t1;
+ const T B0 = t0;
+ const T B1 = madd(-2.0f,t0,t1);
+ const T B2 = madd(-2.0f,t1,t0);
+ const T B3 = t1;
+ return T(6.0f)*Vec4<T>(B0,B1,B2,B3);
+ }
+ };
+
+ struct PrecomputedBezierBasis
+ {
+ enum { N = 16 };
+ public:
+ PrecomputedBezierBasis() {}
+ PrecomputedBezierBasis(int shift);
+
+ /* basis for bezier evaluation */
+ public:
+ float c0[N+1][N+1];
+ float c1[N+1][N+1];
+ float c2[N+1][N+1];
+ float c3[N+1][N+1];
+
+ /* basis for bezier derivative evaluation */
+ public:
+ float d0[N+1][N+1];
+ float d1[N+1][N+1];
+ float d2[N+1][N+1];
+ float d3[N+1][N+1];
+ };
+ extern PrecomputedBezierBasis bezier_basis0;
+ extern PrecomputedBezierBasis bezier_basis1;
+
+
+ template<typename V>
+ struct LinearBezierCurve
+ {
+ V v0,v1;
+
+ __forceinline LinearBezierCurve () {}
+
+ __forceinline LinearBezierCurve (const LinearBezierCurve& other)
+ : v0(other.v0), v1(other.v1) {}
+
+ __forceinline LinearBezierCurve& operator= (const LinearBezierCurve& other) {
+ v0 = other.v0; v1 = other.v1; return *this;
+ }
+
+ __forceinline LinearBezierCurve (const V& v0, const V& v1)
+ : v0(v0), v1(v1) {}
+
+ __forceinline V begin() const { return v0; }
+ __forceinline V end () const { return v1; }
+
+ bool hasRoot() const;
+
+ friend embree_ostream operator<<(embree_ostream cout, const LinearBezierCurve& a) {
+ return cout << "LinearBezierCurve (" << a.v0 << ", " << a.v1 << ")";
+ }
+ };
+
+ template<> __forceinline bool LinearBezierCurve<Interval1f>::hasRoot() const {
+ return numRoots(v0,v1);
+ }
+
+ template<typename V>
+ struct QuadraticBezierCurve
+ {
+ V v0,v1,v2;
+
+ __forceinline QuadraticBezierCurve () {}
+
+ __forceinline QuadraticBezierCurve (const QuadraticBezierCurve& other)
+ : v0(other.v0), v1(other.v1), v2(other.v2) {}
+
+ __forceinline QuadraticBezierCurve& operator= (const QuadraticBezierCurve& other) {
+ v0 = other.v0; v1 = other.v1; v2 = other.v2; return *this;
+ }
+
+ __forceinline QuadraticBezierCurve (const V& v0, const V& v1, const V& v2)
+ : v0(v0), v1(v1), v2(v2) {}
+
+ __forceinline V begin() const { return v0; }
+ __forceinline V end () const { return v2; }
+
+ __forceinline V interval() const {
+ return merge(v0,v1,v2);
+ }
+
+ __forceinline BBox<V> bounds() const {
+ return merge(BBox<V>(v0),BBox<V>(v1),BBox<V>(v2));
+ }
+
+ friend embree_ostream operator<<(embree_ostream cout, const QuadraticBezierCurve& a) {
+ return cout << "QuadraticBezierCurve ( (" << a.u.lower << ", " << a.u.upper << "), " << a.v0 << ", " << a.v1 << ", " << a.v2 << ")";
+ }
+ };
+
+
+ typedef QuadraticBezierCurve<float> QuadraticBezierCurve1f;
+ typedef QuadraticBezierCurve<Vec2fa> QuadraticBezierCurve2fa;
+ typedef QuadraticBezierCurve<Vec3fa> QuadraticBezierCurve3fa;
+
+ template<typename Vertex>
+ struct CubicBezierCurve
+ {
+ Vertex v0,v1,v2,v3;
+
+ __forceinline CubicBezierCurve() {}
+
+ template<typename T1>
+ __forceinline CubicBezierCurve (const CubicBezierCurve<T1>& other)
+ : v0(other.v0), v1(other.v1), v2(other.v2), v3(other.v3) {}
+
+ __forceinline CubicBezierCurve& operator= (const CubicBezierCurve& other) {
+ v0 = other.v0; v1 = other.v1; v2 = other.v2; v3 = other.v3; return *this;
+ }
+
+ __forceinline CubicBezierCurve(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3)
+ : v0(v0), v1(v1), v2(v2), v3(v3) {}
+
+ __forceinline Vertex begin() const {
+ return v0;
+ }
+
+ __forceinline Vertex end() const {
+ return v3;
+ }
+
+ __forceinline Vertex center() const {
+ return 0.25f*(v0+v1+v2+v3);
+ }
+
+ __forceinline Vertex begin_direction() const {
+ return v1-v0;
+ }
+
+ __forceinline Vertex end_direction() const {
+ return v3-v2;
+ }
+
+ __forceinline CubicBezierCurve<float> xfm(const Vertex& dx) const {
+ return CubicBezierCurve<float>(dot(v0,dx),dot(v1,dx),dot(v2,dx),dot(v3,dx));
+ }
+
+ __forceinline CubicBezierCurve<vfloatx> vxfm(const Vertex& dx) const {
+ return CubicBezierCurve<vfloatx>(dot(v0,dx),dot(v1,dx),dot(v2,dx),dot(v3,dx));
+ }
+
+ __forceinline CubicBezierCurve<float> xfm(const Vertex& dx, const Vertex& p) const {
+ return CubicBezierCurve<float>(dot(v0-p,dx),dot(v1-p,dx),dot(v2-p,dx),dot(v3-p,dx));
+ }
+
+ __forceinline CubicBezierCurve<Vec3fa> xfm(const LinearSpace3fa& space) const
+ {
+ const Vec3fa q0 = xfmVector(space,v0);
+ const Vec3fa q1 = xfmVector(space,v1);
+ const Vec3fa q2 = xfmVector(space,v2);
+ const Vec3fa q3 = xfmVector(space,v3);
+ return CubicBezierCurve<Vec3fa>(q0,q1,q2,q3);
+ }
+
+ __forceinline CubicBezierCurve<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p) const
+ {
+ const Vec3fa q0 = xfmVector(space,v0-p);
+ const Vec3fa q1 = xfmVector(space,v1-p);
+ const Vec3fa q2 = xfmVector(space,v2-p);
+ const Vec3fa q3 = xfmVector(space,v3-p);
+ return CubicBezierCurve<Vec3fa>(q0,q1,q2,q3);
+ }
+
+ __forceinline CubicBezierCurve<Vec3ff> xfm_pr(const LinearSpace3fa& space, const Vec3fa& p) const
+ {
+ const Vec3ff q0(xfmVector(space,(Vec3fa)v0-p), v0.w);
+ const Vec3ff q1(xfmVector(space,(Vec3fa)v1-p), v1.w);
+ const Vec3ff q2(xfmVector(space,(Vec3fa)v2-p), v2.w);
+ const Vec3ff q3(xfmVector(space,(Vec3fa)v3-p), v3.w);
+ return CubicBezierCurve<Vec3ff>(q0,q1,q2,q3);
+ }
+
+ __forceinline CubicBezierCurve<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p, const float s) const
+ {
+ const Vec3fa q0 = xfmVector(space,s*(v0-p));
+ const Vec3fa q1 = xfmVector(space,s*(v1-p));
+ const Vec3fa q2 = xfmVector(space,s*(v2-p));
+ const Vec3fa q3 = xfmVector(space,s*(v3-p));
+ return CubicBezierCurve<Vec3fa>(q0,q1,q2,q3);
+ }
+
+ __forceinline int maxRoots() const;
+
+ __forceinline BBox<Vertex> bounds() const {
+ return merge(BBox<Vertex>(v0),BBox<Vertex>(v1),BBox<Vertex>(v2),BBox<Vertex>(v3));
+ }
+
+ __forceinline friend CubicBezierCurve operator +( const CubicBezierCurve& a, const CubicBezierCurve& b ) {
+ return CubicBezierCurve(a.v0+b.v0,a.v1+b.v1,a.v2+b.v2,a.v3+b.v3);
+ }
+
+ __forceinline friend CubicBezierCurve operator -( const CubicBezierCurve& a, const CubicBezierCurve& b ) {
+ return CubicBezierCurve(a.v0-b.v0,a.v1-b.v1,a.v2-b.v2,a.v3-b.v3);
+ }
+
+ __forceinline friend CubicBezierCurve operator -( const CubicBezierCurve& a, const Vertex& b ) {
+ return CubicBezierCurve(a.v0-b,a.v1-b,a.v2-b,a.v3-b);
+ }
+
+ __forceinline friend CubicBezierCurve operator *( const Vertex& a, const CubicBezierCurve& b ) {
+ return CubicBezierCurve(a*b.v0,a*b.v1,a*b.v2,a*b.v3);
+ }
+
+ __forceinline friend CubicBezierCurve cmadd( const Vertex& a, const CubicBezierCurve& b, const CubicBezierCurve& c) {
+ return CubicBezierCurve(madd(a,b.v0,c.v0),madd(a,b.v1,c.v1),madd(a,b.v2,c.v2),madd(a,b.v3,c.v3));
+ }
+
+ __forceinline friend CubicBezierCurve clerp ( const CubicBezierCurve& a, const CubicBezierCurve& b, const Vertex& t ) {
+ return cmadd((Vertex(1.0f)-t),a,t*b);
+ }
+
+ __forceinline friend CubicBezierCurve merge ( const CubicBezierCurve& a, const CubicBezierCurve& b ) {
+ return CubicBezierCurve(merge(a.v0,b.v0),merge(a.v1,b.v1),merge(a.v2,b.v2),merge(a.v3,b.v3));
+ }
+
+ __forceinline void split(CubicBezierCurve& left, CubicBezierCurve& right, const float t = 0.5f) const
+ {
+ const Vertex p00 = v0;
+ const Vertex p01 = v1;
+ const Vertex p02 = v2;
+ const Vertex p03 = v3;
+
+ const Vertex p10 = lerp(p00,p01,t);
+ const Vertex p11 = lerp(p01,p02,t);
+ const Vertex p12 = lerp(p02,p03,t);
+ const Vertex p20 = lerp(p10,p11,t);
+ const Vertex p21 = lerp(p11,p12,t);
+ const Vertex p30 = lerp(p20,p21,t);
+
+ new (&left ) CubicBezierCurve(p00,p10,p20,p30);
+ new (&right) CubicBezierCurve(p30,p21,p12,p03);
+ }
+
+ __forceinline CubicBezierCurve<Vec2vfx> split() const
+ {
+ const float u0 = 0.0f, u1 = 1.0f;
+ const float dscale = (u1-u0)*(1.0f/(3.0f*(VSIZEX-1)));
+ const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(VSIZEX-1)));
+ Vec2vfx P0, dP0du; evalN(vu0,P0,dP0du); dP0du = dP0du * Vec2vfx(dscale);
+ const Vec2vfx P3 = shift_right_1(P0);
+ const Vec2vfx dP3du = shift_right_1(dP0du);
+ const Vec2vfx P1 = P0 + dP0du;
+ const Vec2vfx P2 = P3 - dP3du;
+ return CubicBezierCurve<Vec2vfx>(P0,P1,P2,P3);
+ }
+
+ __forceinline CubicBezierCurve<Vec2vfx> split(const BBox1f& u) const
+ {
+ const float u0 = u.lower, u1 = u.upper;
+ const float dscale = (u1-u0)*(1.0f/(3.0f*(VSIZEX-1)));
+ const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(VSIZEX-1)));
+ Vec2vfx P0, dP0du; evalN(vu0,P0,dP0du); dP0du = dP0du * Vec2vfx(dscale);
+ const Vec2vfx P3 = shift_right_1(P0);
+ const Vec2vfx dP3du = shift_right_1(dP0du);
+ const Vec2vfx P1 = P0 + dP0du;
+ const Vec2vfx P2 = P3 - dP3du;
+ return CubicBezierCurve<Vec2vfx>(P0,P1,P2,P3);
+ }
+
+ __forceinline void eval(float t, Vertex& p, Vertex& dp) const
+ {
+ const Vertex p00 = v0;
+ const Vertex p01 = v1;
+ const Vertex p02 = v2;
+ const Vertex p03 = v3;
+
+ const Vertex p10 = lerp(p00,p01,t);
+ const Vertex p11 = lerp(p01,p02,t);
+ const Vertex p12 = lerp(p02,p03,t);
+ const Vertex p20 = lerp(p10,p11,t);
+ const Vertex p21 = lerp(p11,p12,t);
+ const Vertex p30 = lerp(p20,p21,t);
+
+ p = p30;
+ dp = Vertex(3.0f)*(p21-p20);
+ }
+
+#if 0
+ __forceinline Vertex eval(float t) const
+ {
+ const Vertex p00 = v0;
+ const Vertex p01 = v1;
+ const Vertex p02 = v2;
+ const Vertex p03 = v3;
+
+ const Vertex p10 = lerp(p00,p01,t);
+ const Vertex p11 = lerp(p01,p02,t);
+ const Vertex p12 = lerp(p02,p03,t);
+ const Vertex p20 = lerp(p10,p11,t);
+ const Vertex p21 = lerp(p11,p12,t);
+ const Vertex p30 = lerp(p20,p21,t);
+
+ return p30;
+ }
+#else
+ __forceinline Vertex eval(const float t) const
+ {
+ const Vec4<float> b = BezierBasis::eval(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+#endif
+
+ __forceinline Vertex eval_dt(float t) const
+ {
+ const Vertex p00 = v1-v0;
+ const Vertex p01 = v2-v1;
+ const Vertex p02 = v3-v2;
+ const Vertex p10 = lerp(p00,p01,t);
+ const Vertex p11 = lerp(p01,p02,t);
+ const Vertex p20 = lerp(p10,p11,t);
+ return Vertex(3.0f)*p20;
+ }
+
+ __forceinline Vertex eval_du(const float t) const
+ {
+ const Vec4<float> b = BezierBasis::derivative(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+
+ __forceinline Vertex eval_dudu(const float t) const
+ {
+ const Vec4<float> b = BezierBasis::derivative2(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+
+ __forceinline void evalN(const vfloatx& t, Vec2vfx& p, Vec2vfx& dp) const
+ {
+ const Vec2vfx p00 = v0;
+ const Vec2vfx p01 = v1;
+ const Vec2vfx p02 = v2;
+ const Vec2vfx p03 = v3;
+
+ const Vec2vfx p10 = lerp(p00,p01,t);
+ const Vec2vfx p11 = lerp(p01,p02,t);
+ const Vec2vfx p12 = lerp(p02,p03,t);
+
+ const Vec2vfx p20 = lerp(p10,p11,t);
+ const Vec2vfx p21 = lerp(p11,p12,t);
+
+ const Vec2vfx p30 = lerp(p20,p21,t);
+
+ p = p30;
+ dp = vfloatx(3.0f)*(p21-p20);
+ }
+
+ __forceinline void eval(const float t, Vertex& p, Vertex& dp, Vertex& ddp) const
+ {
+ const Vertex p00 = v0;
+ const Vertex p01 = v1;
+ const Vertex p02 = v2;
+ const Vertex p03 = v3;
+ const Vertex p10 = lerp(p00,p01,t);
+ const Vertex p11 = lerp(p01,p02,t);
+ const Vertex p12 = lerp(p02,p03,t);
+ const Vertex p20 = lerp(p10,p11,t);
+ const Vertex p21 = lerp(p11,p12,t);
+ const Vertex p30 = lerp(p20,p21,t);
+ p = p30;
+ dp = 3.0f*(p21-p20);
+ ddp = eval_dudu(t);
+ }
+
+ __forceinline CubicBezierCurve clip(const Interval1f& u1) const
+ {
+ Vertex f0,df0; eval(u1.lower,f0,df0);
+ Vertex f1,df1; eval(u1.upper,f1,df1);
+ float s = u1.upper-u1.lower;
+ return CubicBezierCurve(f0,f0+s*(1.0f/3.0f)*df0,f1-s*(1.0f/3.0f)*df1,f1);
+ }
+
+ __forceinline QuadraticBezierCurve<Vertex> derivative() const
+ {
+ const Vertex q0 = 3.0f*(v1-v0);
+ const Vertex q1 = 3.0f*(v2-v1);
+ const Vertex q2 = 3.0f*(v3-v2);
+ return QuadraticBezierCurve<Vertex>(q0,q1,q2);
+ }
+
+ __forceinline BBox<Vertex> derivative_bounds(const Interval1f& u1) const
+ {
+ Vertex f0,df0; eval(u1.lower,f0,df0);
+ Vertex f3,df3; eval(u1.upper,f3,df3);
+ const float s = u1.upper-u1.lower;
+ const Vertex f1 = f0+s*(1.0f/3.0f)*df0;
+ const Vertex f2 = f3-s*(1.0f/3.0f)*df3;
+ const Vertex q0 = s*df0;
+ const Vertex q1 = 3.0f*(f2-f1);
+ const Vertex q2 = s*df3;
+ return merge(BBox<Vertex>(q0),BBox<Vertex>(q1),BBox<Vertex>(q2));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = BezierBasis::eval(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval_du(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = BezierBasis::derivative(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval_dudu(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = BezierBasis::derivative2(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline void veval(const vfloat<M>& t, Vec4vf<M>& p, Vec4vf<M>& dp) const
+ {
+ const Vec4vf<M> p00 = v0;
+ const Vec4vf<M> p01 = v1;
+ const Vec4vf<M> p02 = v2;
+ const Vec4vf<M> p03 = v3;
+
+ const Vec4vf<M> p10 = lerp(p00,p01,t);
+ const Vec4vf<M> p11 = lerp(p01,p02,t);
+ const Vec4vf<M> p12 = lerp(p02,p03,t);
+ const Vec4vf<M> p20 = lerp(p10,p11,t);
+ const Vec4vf<M> p21 = lerp(p11,p12,t);
+ const Vec4vf<M> p30 = lerp(p20,p21,t);
+
+ p = p30;
+ dp = vfloat<M>(3.0f)*(p21-p20);
+ }
+
+ template<int M, typename Vec = Vec4vf<M>>
+ __forceinline Vec eval0(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedBezierBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&bezier_basis0.c0[size][ofs]), Vec(v0),
+ madd(vfloat<M>::loadu(&bezier_basis0.c1[size][ofs]), Vec(v1),
+ madd(vfloat<M>::loadu(&bezier_basis0.c2[size][ofs]), Vec(v2),
+ vfloat<M>::loadu(&bezier_basis0.c3[size][ofs]) * Vec(v3))));
+ }
+
+ template<int M, typename Vec = Vec4vf<M>>
+ __forceinline Vec eval1(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedBezierBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&bezier_basis1.c0[size][ofs]), Vec(v0),
+ madd(vfloat<M>::loadu(&bezier_basis1.c1[size][ofs]), Vec(v1),
+ madd(vfloat<M>::loadu(&bezier_basis1.c2[size][ofs]), Vec(v2),
+ vfloat<M>::loadu(&bezier_basis1.c3[size][ofs]) * Vec(v3))));
+ }
+
+ template<int M, typename Vec = Vec4vf<M>>
+ __forceinline Vec derivative0(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedBezierBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&bezier_basis0.d0[size][ofs]), Vec(v0),
+ madd(vfloat<M>::loadu(&bezier_basis0.d1[size][ofs]), Vec(v1),
+ madd(vfloat<M>::loadu(&bezier_basis0.d2[size][ofs]), Vec(v2),
+ vfloat<M>::loadu(&bezier_basis0.d3[size][ofs]) * Vec(v3))));
+ }
+
+ template<int M, typename Vec = Vec4vf<M>>
+ __forceinline Vec derivative1(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedBezierBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&bezier_basis1.d0[size][ofs]), Vec(v0),
+ madd(vfloat<M>::loadu(&bezier_basis1.d1[size][ofs]), Vec(v1),
+ madd(vfloat<M>::loadu(&bezier_basis1.d2[size][ofs]), Vec(v2),
+ vfloat<M>::loadu(&bezier_basis1.d3[size][ofs]) * Vec(v3))));
+ }
+
+ /* calculates bounds of bezier curve geometry */
+ __forceinline BBox3fa accurateBounds() const
+ {
+ const int N = 7;
+ const float scale = 1.0f/(3.0f*(N-1));
+ Vec3vfx pl(pos_inf), pu(neg_inf);
+ for (int i=0; i<=N; i+=VSIZEX)
+ {
+ vintx vi = vintx(i)+vintx(step);
+ vboolx valid = vi <= vintx(N);
+ const Vec3vfx p = eval0<VSIZEX,Vec3vf<VSIZEX>>(i,N);
+ const Vec3vfx dp = derivative0<VSIZEX,Vec3vf<VSIZEX>>(i,N);
+ const Vec3vfx pm = p-Vec3vfx(scale)*select(vi!=vintx(0),dp,Vec3vfx(zero));
+ const Vec3vfx pp = p+Vec3vfx(scale)*select(vi!=vintx(N),dp,Vec3vfx(zero));
+ pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
+ pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
+ }
+ const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
+ const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
+ return BBox3fa(lower,upper);
+ }
+
+ /* calculates bounds of bezier curve geometry */
+ __forceinline BBox3fa accurateRoundBounds() const
+ {
+ const int N = 7;
+ const float scale = 1.0f/(3.0f*(N-1));
+ Vec4vfx pl(pos_inf), pu(neg_inf);
+ for (int i=0; i<=N; i+=VSIZEX)
+ {
+ vintx vi = vintx(i)+vintx(step);
+ vboolx valid = vi <= vintx(N);
+ const Vec4vfx p = eval0<VSIZEX>(i,N);
+ const Vec4vfx dp = derivative0<VSIZEX>(i,N);
+ const Vec4vfx pm = p-Vec4vfx(scale)*select(vi!=vintx(0),dp,Vec4vfx(zero));
+ const Vec4vfx pp = p+Vec4vfx(scale)*select(vi!=vintx(N),dp,Vec4vfx(zero));
+ pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
+ pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
+ }
+ const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
+ const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
+ const float r_min = reduce_min(pl.w);
+ const float r_max = reduce_max(pu.w);
+ const Vec3fa upper_r = Vec3fa(max(abs(r_min),abs(r_max)));
+ return enlarge(BBox3fa(lower,upper),upper_r);
+ }
+
+ /* calculates bounds when tessellated into N line segments */
+ __forceinline BBox3fa accurateFlatBounds(int N) const
+ {
+ if (likely(N == 4))
+ {
+ const Vec4vf4 pi = eval0<4>(0,4);
+ const Vec3fa lower(reduce_min(pi.x),reduce_min(pi.y),reduce_min(pi.z));
+ const Vec3fa upper(reduce_max(pi.x),reduce_max(pi.y),reduce_max(pi.z));
+ const Vec3fa upper_r = Vec3fa(reduce_max(abs(pi.w)));
+ return enlarge(BBox3fa(min(lower,v3),max(upper,v3)),max(upper_r,Vec3fa(abs(v3.w))));
+ }
+ else
+ {
+ Vec3vfx pl(pos_inf), pu(neg_inf); vfloatx ru(0.0f);
+ for (int i=0; i<N; i+=VSIZEX)
+ {
+ vboolx valid = vintx(i)+vintx(step) < vintx(N);
+ const Vec4vfx pi = eval0<VSIZEX>(i,N);
+
+ pl.x = select(valid,min(pl.x,pi.x),pl.x); // FIXME: use masked min
+ pl.y = select(valid,min(pl.y,pi.y),pl.y);
+ pl.z = select(valid,min(pl.z,pi.z),pl.z);
+
+ pu.x = select(valid,max(pu.x,pi.x),pu.x); // FIXME: use masked min
+ pu.y = select(valid,max(pu.y,pi.y),pu.y);
+ pu.z = select(valid,max(pu.z,pi.z),pu.z);
+
+ ru = select(valid,max(ru,abs(pi.w)),ru);
+ }
+ const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
+ const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
+ const Vec3fa upper_r(reduce_max(ru));
+ return enlarge(BBox3fa(min(lower,v3),max(upper,v3)),max(upper_r,Vec3fa(abs(v3.w))));
+ }
+ }
+
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const CubicBezierCurve& curve) {
+ return cout << "CubicBezierCurve { v0 = " << curve.v0 << ", v1 = " << curve.v1 << ", v2 = " << curve.v2 << ", v3 = " << curve.v3 << " }";
+ }
+ };
+
+#if defined(__AVX__)
+ template<>
+ __forceinline CubicBezierCurve<vfloat4> CubicBezierCurve<vfloat4>::clip(const Interval1f& u1) const
+ {
+ const vfloat8 p00 = vfloat8(v0);
+ const vfloat8 p01 = vfloat8(v1);
+ const vfloat8 p02 = vfloat8(v2);
+ const vfloat8 p03 = vfloat8(v3);
+
+ const vfloat8 t(vfloat4(u1.lower),vfloat4(u1.upper));
+ const vfloat8 p10 = lerp(p00,p01,t);
+ const vfloat8 p11 = lerp(p01,p02,t);
+ const vfloat8 p12 = lerp(p02,p03,t);
+ const vfloat8 p20 = lerp(p10,p11,t);
+ const vfloat8 p21 = lerp(p11,p12,t);
+ const vfloat8 p30 = lerp(p20,p21,t);
+
+ const vfloat8 f01 = p30;
+ const vfloat8 df01 = vfloat8(3.0f)*(p21-p20);
+
+ const vfloat4 f0 = extract4<0>(f01), f1 = extract4<1>(f01);
+ const vfloat4 df0 = extract4<0>(df01), df1 = extract4<1>(df01);
+ const float s = u1.upper-u1.lower;
+ return CubicBezierCurve(f0,f0+s*(1.0f/3.0f)*df0,f1-s*(1.0f/3.0f)*df1,f1);
+ }
+#endif
+
+ template<typename Vertex> using BezierCurveT = CubicBezierCurve<Vertex>;
+
+ typedef CubicBezierCurve<float> CubicBezierCurve1f;
+ typedef CubicBezierCurve<Vec2fa> CubicBezierCurve2fa;
+ typedef CubicBezierCurve<Vec3fa> CubicBezierCurve3fa;
+ typedef CubicBezierCurve<Vec3fa> BezierCurve3fa;
+
+ template<> __forceinline int CubicBezierCurve<float>::maxRoots() const
+ {
+ float eps = 1E-4f;
+ bool neg0 = v0 <= 0.0f; bool zero0 = fabs(v0) < eps;
+ bool neg1 = v1 <= 0.0f; bool zero1 = fabs(v1) < eps;
+ bool neg2 = v2 <= 0.0f; bool zero2 = fabs(v2) < eps;
+ bool neg3 = v3 <= 0.0f; bool zero3 = fabs(v3) < eps;
+ return (neg0 != neg1 || zero0) + (neg1 != neg2 || zero1) + (neg2 != neg3 || zero2 || zero3);
+ }
+
+ template<> __forceinline int CubicBezierCurve<Interval1f>::maxRoots() const {
+ return numRoots(v0,v1) + numRoots(v1,v2) + numRoots(v2,v3);
+ }
+
+ template<typename CurveGeometry>
+ __forceinline CubicBezierCurve<Vec3ff> enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const CubicBezierCurve<Vec3ff>& curve)
+ {
+ return CubicBezierCurve<Vec3ff>(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v1),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v2),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v3));
+ }
+}
diff --git a/thirdparty/embree/kernels/subdiv/bezier_patch.h b/thirdparty/embree/kernels/subdiv/bezier_patch.h
new file mode 100644
index 0000000000..2ff03902a7
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/bezier_patch.h
@@ -0,0 +1,372 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "catmullclark_patch.h"
+#include "bezier_curve.h"
+
+namespace embree
+{
+ template<class T, class S>
+ static __forceinline T deCasteljau(const S& uu, const T& v0, const T& v1, const T& v2, const T& v3)
+ {
+ const T v0_1 = lerp(v0,v1,uu);
+ const T v1_1 = lerp(v1,v2,uu);
+ const T v2_1 = lerp(v2,v3,uu);
+ const T v0_2 = lerp(v0_1,v1_1,uu);
+ const T v1_2 = lerp(v1_1,v2_1,uu);
+ const T v0_3 = lerp(v0_2,v1_2,uu);
+ return v0_3;
+ }
+
+ template<class T, class S>
+ static __forceinline T deCasteljau_tangent(const S& uu, const T& v0, const T& v1, const T& v2, const T& v3)
+ {
+ const T v0_1 = lerp(v0,v1,uu);
+ const T v1_1 = lerp(v1,v2,uu);
+ const T v2_1 = lerp(v2,v3,uu);
+ const T v0_2 = lerp(v0_1,v1_1,uu);
+ const T v1_2 = lerp(v1_1,v2_1,uu);
+ return S(3.0f)*(v1_2-v0_2);
+ }
+
+ template<typename Vertex>
+ __forceinline Vertex computeInnerBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
+ return 1.0f / 36.0f * (16.0f * v[y][x] + 4.0f * (v[y-1][x] + v[y+1][x] + v[y][x-1] + v[y][x+1]) + (v[y-1][x-1] + v[y+1][x+1] + v[y-1][x+1] + v[y+1][x-1]));
+ }
+
+ template<typename Vertex>
+ __forceinline Vertex computeTopEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
+ return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y-1][x] + 2.0f * (v[y][x-1] + v[y][x+1]) + (v[y-1][x-1] + v[y-1][x+1]));
+ }
+
+ template<typename Vertex>
+ __forceinline Vertex computeBottomEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
+ return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y+1][x] + 2.0f * (v[y][x-1] + v[y][x+1]) + v[y+1][x-1] + v[y+1][x+1]);
+ }
+
+ template<typename Vertex>
+ __forceinline Vertex computeLeftEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
+ return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y][x-1] + 2.0f * (v[y-1][x] + v[y+1][x]) + v[y-1][x-1] + v[y+1][x-1]);
+ }
+
+ template<typename Vertex>
+ __forceinline Vertex computeRightEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
+ return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y][x+1] + 2.0f * (v[y-1][x] + v[y+1][x]) + v[y-1][x+1] + v[y+1][x+1]);
+ }
+
+ template<typename Vertex>
+ __forceinline Vertex computeCornerBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x, const ssize_t delta_y, const ssize_t delta_x)
+ {
+ return 1.0f / 9.0f * (4.0f * v[y][x] + 2.0f * (v[y+delta_y][x] + v[y][x+delta_x]) + v[y+delta_y][x+delta_x]);
+ }
+
+ template<typename Vertex, typename Vertex_t>
+ class __aligned(64) BezierPatchT
+ {
+ public:
+ Vertex matrix[4][4];
+
+ public:
+
+ __forceinline BezierPatchT() {}
+
+ __forceinline BezierPatchT (const HalfEdge* edge, const char* vertices, size_t stride);
+
+ __forceinline BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch);
+
+ __forceinline BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch,
+ const BezierCurveT<Vertex>* border0,
+ const BezierCurveT<Vertex>* border1,
+ const BezierCurveT<Vertex>* border2,
+ const BezierCurveT<Vertex>* border3);
+
+ __forceinline BezierPatchT(const BSplinePatchT<Vertex,Vertex_t>& source)
+ {
+ /* compute inner bezier control points */
+ matrix[0][0] = computeInnerBezierControlPoint(source.v,1,1);
+ matrix[0][3] = computeInnerBezierControlPoint(source.v,1,2);
+ matrix[3][3] = computeInnerBezierControlPoint(source.v,2,2);
+ matrix[3][0] = computeInnerBezierControlPoint(source.v,2,1);
+
+ /* compute top edge control points */
+ matrix[0][1] = computeRightEdgeBezierControlPoint(source.v,1,1);
+ matrix[0][2] = computeLeftEdgeBezierControlPoint(source.v,1,2);
+
+ /* compute buttom edge control points */
+ matrix[3][1] = computeRightEdgeBezierControlPoint(source.v,2,1);
+ matrix[3][2] = computeLeftEdgeBezierControlPoint(source.v,2,2);
+
+ /* compute left edge control points */
+ matrix[1][0] = computeBottomEdgeBezierControlPoint(source.v,1,1);
+ matrix[2][0] = computeTopEdgeBezierControlPoint(source.v,2,1);
+
+ /* compute right edge control points */
+ matrix[1][3] = computeBottomEdgeBezierControlPoint(source.v,1,2);
+ matrix[2][3] = computeTopEdgeBezierControlPoint(source.v,2,2);
+
+ /* compute corner control points */
+ matrix[1][1] = computeCornerBezierControlPoint(source.v,1,1, 1, 1);
+ matrix[1][2] = computeCornerBezierControlPoint(source.v,1,2, 1,-1);
+ matrix[2][2] = computeCornerBezierControlPoint(source.v,2,2,-1,-1);
+ matrix[2][1] = computeCornerBezierControlPoint(source.v,2,1,-1, 1);
+ }
+
+ static __forceinline Vertex_t bilinear(const Vec4f Bu, const Vertex matrix[4][4], const Vec4f Bv)
+ {
+ const Vertex_t M0 = madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3])));
+ const Vertex_t M1 = madd(Bu.x,matrix[1][0],madd(Bu.y,matrix[1][1],madd(Bu.z,matrix[1][2],Bu.w * matrix[1][3])));
+ const Vertex_t M2 = madd(Bu.x,matrix[2][0],madd(Bu.y,matrix[2][1],madd(Bu.z,matrix[2][2],Bu.w * matrix[2][3])));
+ const Vertex_t M3 = madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3])));
+ return madd(Bv.x,M0,madd(Bv.y,M1,madd(Bv.z,M2,Bv.w*M3)));
+ }
+
+ static __forceinline Vertex_t eval(const Vertex matrix[4][4], const float uu, const float vv)
+ {
+ const Vec4f Bu = BezierBasis::eval(uu);
+ const Vec4f Bv = BezierBasis::eval(vv);
+ return bilinear(Bu,matrix,Bv);
+ }
+
+ static __forceinline Vertex_t eval_du(const Vertex matrix[4][4], const float uu, const float vv)
+ {
+ const Vec4f Bu = BezierBasis::derivative(uu);
+ const Vec4f Bv = BezierBasis::eval(vv);
+ return bilinear(Bu,matrix,Bv);
+ }
+
+ static __forceinline Vertex_t eval_dv(const Vertex matrix[4][4], const float uu, const float vv)
+ {
+ const Vec4f Bu = BezierBasis::eval(uu);
+ const Vec4f Bv = BezierBasis::derivative(vv);
+ return bilinear(Bu,matrix,Bv);
+ }
+
+ static __forceinline Vertex_t eval_dudu(const Vertex matrix[4][4], const float uu, const float vv)
+ {
+ const Vec4f Bu = BezierBasis::derivative2(uu);
+ const Vec4f Bv = BezierBasis::eval(vv);
+ return bilinear(Bu,matrix,Bv);
+ }
+
+ static __forceinline Vertex_t eval_dvdv(const Vertex matrix[4][4], const float uu, const float vv)
+ {
+ const Vec4f Bu = BezierBasis::eval(uu);
+ const Vec4f Bv = BezierBasis::derivative2(vv);
+ return bilinear(Bu,matrix,Bv);
+ }
+
+ static __forceinline Vertex_t eval_dudv(const Vertex matrix[4][4], const float uu, const float vv)
+ {
+ const Vec4f Bu = BezierBasis::derivative(uu);
+ const Vec4f Bv = BezierBasis::derivative(vv);
+ return bilinear(Bu,matrix,Bv);
+ }
+
+ static __forceinline Vertex_t normal(const Vertex matrix[4][4], const float uu, const float vv)
+ {
+ const Vertex_t dPdu = eval_du(matrix,uu,vv);
+ const Vertex_t dPdv = eval_dv(matrix,uu,vv);
+ return cross(dPdu,dPdv);
+ }
+
+ __forceinline Vertex_t normal(const float uu, const float vv)
+ {
+ const Vertex_t dPdu = eval_du(matrix,uu,vv);
+ const Vertex_t dPdv = eval_dv(matrix,uu,vv);
+ return cross(dPdu,dPdv);
+ }
+
+ __forceinline Vertex_t eval(const float uu, const float vv) const {
+ return eval(matrix,uu,vv);
+ }
+
+ __forceinline Vertex_t eval_du(const float uu, const float vv) const {
+ return eval_du(matrix,uu,vv);
+ }
+
+ __forceinline Vertex_t eval_dv(const float uu, const float vv) const {
+ return eval_dv(matrix,uu,vv);
+ }
+
+ __forceinline Vertex_t eval_dudu(const float uu, const float vv) const {
+ return eval_dudu(matrix,uu,vv);
+ }
+
+ __forceinline Vertex_t eval_dvdv(const float uu, const float vv) const {
+ return eval_dvdv(matrix,uu,vv);
+ }
+
+ __forceinline Vertex_t eval_dudv(const float uu, const float vv) const {
+ return eval_dudv(matrix,uu,vv);
+ }
+
+ __forceinline void eval(const float u, const float v, Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv, const float dscale = 1.0f) const
+ {
+ if (P) {
+ *P = eval(u,v);
+ }
+ if (dPdu) {
+ assert(dPdu); *dPdu = eval_du(u,v)*dscale;
+ assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
+ }
+ if (ddPdudu) {
+ assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
+ assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
+ assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
+ }
+ }
+
+ template<class vfloat>
+ __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n) const
+ {
+ const vfloat curve0_x = v_n[0] * vfloat(matrix[0][0][i]) + v_n[1] * vfloat(matrix[1][0][i]) + v_n[2] * vfloat(matrix[2][0][i]) + v_n[3] * vfloat(matrix[3][0][i]);
+ const vfloat curve1_x = v_n[0] * vfloat(matrix[0][1][i]) + v_n[1] * vfloat(matrix[1][1][i]) + v_n[2] * vfloat(matrix[2][1][i]) + v_n[3] * vfloat(matrix[3][1][i]);
+ const vfloat curve2_x = v_n[0] * vfloat(matrix[0][2][i]) + v_n[1] * vfloat(matrix[1][2][i]) + v_n[2] * vfloat(matrix[2][2][i]) + v_n[3] * vfloat(matrix[3][2][i]);
+ const vfloat curve3_x = v_n[0] * vfloat(matrix[0][3][i]) + v_n[1] * vfloat(matrix[1][3][i]) + v_n[2] * vfloat(matrix[2][3][i]) + v_n[3] * vfloat(matrix[3][3][i]);
+ return u_n[0] * curve0_x + u_n[1] * curve1_x + u_n[2] * curve2_x + u_n[3] * curve3_x;
+ }
+
+ template<typename vbool, typename vfloat>
+ __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
+ const float dscale, const size_t dstride, const size_t N) const
+ {
+ if (P) {
+ const Vec4<vfloat> u_n = BezierBasis::eval(uu);
+ const Vec4<vfloat> v_n = BezierBasis::eval(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv,u_n,v_n));
+ }
+ if (dPdu)
+ {
+ {
+ assert(dPdu);
+ const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
+ const Vec4<vfloat> v_n = BezierBasis::eval(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,dPdu+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
+ }
+ {
+ assert(dPdv);
+ const Vec4<vfloat> u_n = BezierBasis::eval(uu);
+ const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,dPdv+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
+ }
+ }
+ if (ddPdudu)
+ {
+ {
+ assert(ddPdudu);
+ const Vec4<vfloat> u_n = BezierBasis::derivative2(uu);
+ const Vec4<vfloat> v_n = BezierBasis::eval(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudu+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
+ }
+ {
+ assert(ddPdvdv);
+ const Vec4<vfloat> u_n = BezierBasis::eval(uu);
+ const Vec4<vfloat> v_n = BezierBasis::derivative2(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdvdv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
+ }
+ {
+ assert(ddPdudv);
+ const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
+ const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
+ }
+ }
+ }
+
+ template<typename T>
+ static __forceinline Vec3<T> eval(const Vertex matrix[4][4], const T& uu, const T& vv)
+ {
+ const T one_minus_uu = 1.0f - uu;
+ const T one_minus_vv = 1.0f - vv;
+
+ const T B0_u = one_minus_uu * one_minus_uu * one_minus_uu;
+ const T B0_v = one_minus_vv * one_minus_vv * one_minus_vv;
+ const T B1_u = 3.0f * (one_minus_uu * uu * one_minus_uu);
+ const T B1_v = 3.0f * (one_minus_vv * vv * one_minus_vv);
+ const T B2_u = 3.0f * (uu * one_minus_uu * uu);
+ const T B2_v = 3.0f * (vv * one_minus_vv * vv);
+ const T B3_u = uu * uu * uu;
+ const T B3_v = vv * vv * vv;
+
+ const T x =
+ madd(B0_v,madd(B0_u,matrix[0][0].x,madd(B1_u,matrix[0][1].x,madd(B2_u,matrix[0][2].x,B3_u*matrix[0][3].x))),
+ madd(B1_v,madd(B0_u,matrix[1][0].x,madd(B1_u,matrix[1][1].x,madd(B2_u,matrix[1][2].x,B3_u*matrix[1][3].x))),
+ madd(B2_v,madd(B0_u,matrix[2][0].x,madd(B1_u,matrix[2][1].x,madd(B2_u,matrix[2][2].x,B3_u*matrix[2][3].x))),
+ B3_v*madd(B0_u,matrix[3][0].x,madd(B1_u,matrix[3][1].x,madd(B2_u,matrix[3][2].x,B3_u*matrix[3][3].x))))));
+
+ const T y =
+ madd(B0_v,madd(B0_u,matrix[0][0].y,madd(B1_u,matrix[0][1].y,madd(B2_u,matrix[0][2].y,B3_u*matrix[0][3].y))),
+ madd(B1_v,madd(B0_u,matrix[1][0].y,madd(B1_u,matrix[1][1].y,madd(B2_u,matrix[1][2].y,B3_u*matrix[1][3].y))),
+ madd(B2_v,madd(B0_u,matrix[2][0].y,madd(B1_u,matrix[2][1].y,madd(B2_u,matrix[2][2].y,B3_u*matrix[2][3].y))),
+ B3_v*madd(B0_u,matrix[3][0].y,madd(B1_u,matrix[3][1].y,madd(B2_u,matrix[3][2].y,B3_u*matrix[3][3].y))))));
+
+ const T z =
+ madd(B0_v,madd(B0_u,matrix[0][0].z,madd(B1_u,matrix[0][1].z,madd(B2_u,matrix[0][2].z,B3_u*matrix[0][3].z))),
+ madd(B1_v,madd(B0_u,matrix[1][0].z,madd(B1_u,matrix[1][1].z,madd(B2_u,matrix[1][2].z,B3_u*matrix[1][3].z))),
+ madd(B2_v,madd(B0_u,matrix[2][0].z,madd(B1_u,matrix[2][1].z,madd(B2_u,matrix[2][2].z,B3_u*matrix[2][3].z))),
+ B3_v*madd(B0_u,matrix[3][0].z,madd(B1_u,matrix[3][1].z,madd(B2_u,matrix[3][2].z,B3_u*matrix[3][3].z))))));
+
+ return Vec3<T>(x,y,z);
+ }
+
+ template<typename vfloat>
+ __forceinline Vec3<vfloat> eval(const vfloat& uu, const vfloat& vv) const {
+ return eval(matrix,uu,vv);
+ }
+
+ template<class T>
+ static __forceinline Vec3<T> normal(const Vertex matrix[4][4], const T& uu, const T& vv)
+ {
+
+ const Vec3<T> matrix_00 = Vec3<T>(matrix[0][0].x,matrix[0][0].y,matrix[0][0].z);
+ const Vec3<T> matrix_01 = Vec3<T>(matrix[0][1].x,matrix[0][1].y,matrix[0][1].z);
+ const Vec3<T> matrix_02 = Vec3<T>(matrix[0][2].x,matrix[0][2].y,matrix[0][2].z);
+ const Vec3<T> matrix_03 = Vec3<T>(matrix[0][3].x,matrix[0][3].y,matrix[0][3].z);
+
+ const Vec3<T> matrix_10 = Vec3<T>(matrix[1][0].x,matrix[1][0].y,matrix[1][0].z);
+ const Vec3<T> matrix_11 = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);
+ const Vec3<T> matrix_12 = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);
+ const Vec3<T> matrix_13 = Vec3<T>(matrix[1][3].x,matrix[1][3].y,matrix[1][3].z);
+
+ const Vec3<T> matrix_20 = Vec3<T>(matrix[2][0].x,matrix[2][0].y,matrix[2][0].z);
+ const Vec3<T> matrix_21 = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);
+ const Vec3<T> matrix_22 = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);
+ const Vec3<T> matrix_23 = Vec3<T>(matrix[2][3].x,matrix[2][3].y,matrix[2][3].z);
+
+ const Vec3<T> matrix_30 = Vec3<T>(matrix[3][0].x,matrix[3][0].y,matrix[3][0].z);
+ const Vec3<T> matrix_31 = Vec3<T>(matrix[3][1].x,matrix[3][1].y,matrix[3][1].z);
+ const Vec3<T> matrix_32 = Vec3<T>(matrix[3][2].x,matrix[3][2].y,matrix[3][2].z);
+ const Vec3<T> matrix_33 = Vec3<T>(matrix[3][3].x,matrix[3][3].y,matrix[3][3].z);
+
+ /* tangentU */
+ const Vec3<T> col0 = deCasteljau(vv, matrix_00, matrix_10, matrix_20, matrix_30);
+ const Vec3<T> col1 = deCasteljau(vv, matrix_01, matrix_11, matrix_21, matrix_31);
+ const Vec3<T> col2 = deCasteljau(vv, matrix_02, matrix_12, matrix_22, matrix_32);
+ const Vec3<T> col3 = deCasteljau(vv, matrix_03, matrix_13, matrix_23, matrix_33);
+
+ const Vec3<T> tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);
+
+ /* tangentV */
+ const Vec3<T> row0 = deCasteljau(uu, matrix_00, matrix_01, matrix_02, matrix_03);
+ const Vec3<T> row1 = deCasteljau(uu, matrix_10, matrix_11, matrix_12, matrix_13);
+ const Vec3<T> row2 = deCasteljau(uu, matrix_20, matrix_21, matrix_22, matrix_23);
+ const Vec3<T> row3 = deCasteljau(uu, matrix_30, matrix_31, matrix_32, matrix_33);
+
+ const Vec3<T> tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);
+
+ /* normal = tangentU x tangentV */
+ const Vec3<T> n = cross(tangentU,tangentV);
+ return n;
+ }
+
+ template<typename vfloat>
+ __forceinline Vec3<vfloat> normal(const vfloat& uu, const vfloat& vv) const {
+ return normal(matrix,uu,vv);
+ }
+ };
+
+ typedef BezierPatchT<Vec3fa,Vec3fa_t> BezierPatch3fa;
+}
diff --git a/thirdparty/embree/kernels/subdiv/bilinear_patch.h b/thirdparty/embree/kernels/subdiv/bilinear_patch.h
new file mode 100644
index 0000000000..cade104a6c
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/bilinear_patch.h
@@ -0,0 +1,191 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "catmullclark_patch.h"
+#include "bezier_curve.h"
+
+namespace embree
+{
+ template<typename Vertex, typename Vertex_t = Vertex>
+ class __aligned(64) BilinearPatchT
+ {
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+
+ public:
+ Vertex v[4];
+
+ public:
+
+ __forceinline BilinearPatchT () {}
+
+ __forceinline BilinearPatchT (const HalfEdge* edge, const BufferView<Vertex>& vertices) {
+ init(edge,vertices.getPtr(),vertices.getStride());
+ }
+
+ __forceinline BilinearPatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
+ init(edge,vertices,stride);
+ }
+
+ __forceinline void init (const HalfEdge* edge, const char* vertices, size_t stride)
+ {
+ v[0] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
+ v[1] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
+ v[2] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
+ v[3] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
+ }
+
+ __forceinline BilinearPatchT (const CatmullClarkPatch& patch)
+ {
+ v[0] = patch.ring[0].getLimitVertex();
+ v[1] = patch.ring[1].getLimitVertex();
+ v[2] = patch.ring[2].getLimitVertex();
+ v[3] = patch.ring[3].getLimitVertex();
+ }
+
+ __forceinline BBox<Vertex> bounds() const
+ {
+
+ BBox<Vertex> bounds (v[0]);
+ bounds.extend(v[1]);
+ bounds.extend(v[2]);
+ bounds.extend(v[3]);
+ return bounds;
+ }
+
+ __forceinline Vertex eval(const float uu, const float vv) const {
+ return lerp(lerp(v[0],v[1],uu),lerp(v[3],v[2],uu),vv);
+ }
+
+ __forceinline Vertex eval_du(const float uu, const float vv) const {
+ return lerp(v[1]-v[0],v[2]-v[3],vv);
+ }
+
+ __forceinline Vertex eval_dv(const float uu, const float vv) const {
+ return lerp(v[3]-v[0],v[2]-v[1],uu);
+ }
+
+ __forceinline Vertex eval_dudu(const float uu, const float vv) const {
+ return Vertex(zero);
+ }
+
+ __forceinline Vertex eval_dvdv(const float uu, const float vv) const {
+ return Vertex(zero);
+ }
+
+ __forceinline Vertex eval_dudv(const float uu, const float vv) const {
+ return (v[2]-v[3]) - (v[1]-v[0]);
+ }
+
+ __forceinline Vertex normal(const float uu, const float vv) const {
+ return cross(eval_du(uu,vv),eval_dv(uu,vv));
+ }
+
+ __forceinline void eval(const float u, const float v,
+ Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
+ const float dscale = 1.0f) const
+ {
+ if (P) {
+ *P = eval(u,v);
+ }
+ if (dPdu) {
+ assert(dPdu); *dPdu = eval_du(u,v)*dscale;
+ assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
+ }
+ if (ddPdudu) {
+ assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
+ assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
+ assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
+ }
+ }
+
+ template<class vfloat>
+ __forceinline Vec3<vfloat> eval(const vfloat& uu, const vfloat& vv) const
+ {
+ const vfloat x = lerp(lerp(v[0].x,v[1].x,uu),lerp(v[3].x,v[2].x,uu),vv);
+ const vfloat y = lerp(lerp(v[0].y,v[1].y,uu),lerp(v[3].y,v[2].y,uu),vv);
+ const vfloat z = lerp(lerp(v[0].z,v[1].z,uu),lerp(v[3].z,v[2].z,uu),vv);
+ return Vec3<vfloat>(x,y,z);
+ }
+
+ template<class vfloat>
+ __forceinline Vec3<vfloat> eval_du(const vfloat& uu, const vfloat& vv) const
+ {
+ const vfloat x = lerp(v[1].x-v[0].x,v[2].x-v[3].x,vv);
+ const vfloat y = lerp(v[1].y-v[0].y,v[2].y-v[3].y,vv);
+ const vfloat z = lerp(v[1].z-v[0].z,v[2].z-v[3].z,vv);
+ return Vec3<vfloat>(x,y,z);
+ }
+
+ template<class vfloat>
+ __forceinline Vec3<vfloat> eval_dv(const vfloat& uu, const vfloat& vv) const
+ {
+ const vfloat x = lerp(v[3].x-v[0].x,v[2].x-v[1].x,uu);
+ const vfloat y = lerp(v[3].y-v[0].y,v[2].y-v[1].y,uu);
+ const vfloat z = lerp(v[3].z-v[0].z,v[2].z-v[1].z,uu);
+ return Vec3<vfloat>(x,y,z);
+ }
+
+ template<typename vfloat>
+ __forceinline Vec3<vfloat> normal(const vfloat& uu, const vfloat& vv) const {
+ return cross(eval_du(uu,vv),eval_dv(uu,vv));
+ }
+
+ template<class vfloat>
+ __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv) const {
+ return lerp(lerp(v[0][i],v[1][i],uu),lerp(v[3][i],v[2][i],uu),vv);
+ }
+
+ template<class vfloat>
+ __forceinline vfloat eval_du(const size_t i, const vfloat& uu, const vfloat& vv) const {
+ return lerp(v[1][i]-v[0][i],v[2][i]-v[3][i],vv);
+ }
+
+ template<class vfloat>
+ __forceinline vfloat eval_dv(const size_t i, const vfloat& uu, const vfloat& vv) const {
+ return lerp(v[3][i]-v[0][i],v[2][i]-v[1][i],uu);
+ }
+
+ template<class vfloat>
+ __forceinline vfloat eval_dudu(const size_t i, const vfloat& uu, const vfloat& vv) const {
+ return vfloat(zero);
+ }
+
+ template<class vfloat>
+ __forceinline vfloat eval_dvdv(const size_t i, const vfloat& uu, const vfloat& vv) const {
+ return vfloat(zero);
+ }
+
+ template<class vfloat>
+ __forceinline vfloat eval_dudv(const size_t i, const vfloat& uu, const vfloat& vv) const {
+ return (v[2][i]-v[3][i]) - (v[1][i]-v[0][i]);
+ }
+
+ template<typename vbool, typename vfloat>
+ __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
+ const float dscale, const size_t dstride, const size_t N) const
+ {
+ if (P) {
+ for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv));
+ }
+ if (dPdu) {
+ for (size_t i=0; i<N; i++) {
+ assert(dPdu); vfloat::store(valid,dPdu+i*dstride,eval_du(i,uu,vv)*dscale);
+ assert(dPdv); vfloat::store(valid,dPdv+i*dstride,eval_dv(i,uu,vv)*dscale);
+ }
+ }
+ if (ddPdudu) {
+ for (size_t i=0; i<N; i++) {
+ assert(ddPdudu); vfloat::store(valid,ddPdudu+i*dstride,eval_dudu(i,uu,vv)*sqr(dscale));
+ assert(ddPdvdv); vfloat::store(valid,ddPdvdv+i*dstride,eval_dvdv(i,uu,vv)*sqr(dscale));
+ assert(ddPdudv); vfloat::store(valid,ddPdudv+i*dstride,eval_dudv(i,uu,vv)*sqr(dscale));
+ }
+ }
+ }
+ };
+
+ typedef BilinearPatchT<Vec3fa,Vec3fa_t> BilinearPatch3fa;
+}
diff --git a/thirdparty/embree/kernels/subdiv/bspline_curve.h b/thirdparty/embree/kernels/subdiv/bspline_curve.h
new file mode 100644
index 0000000000..51489ef37c
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/bspline_curve.h
@@ -0,0 +1,320 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+#include "bezier_curve.h"
+
+namespace embree
+{
+ class BSplineBasis
+ {
+ public:
+
+ template<typename T>
+ static __forceinline Vec4<T> eval(const T& u)
+ {
+ const T t = u;
+ const T s = T(1.0f) - u;
+ const T n0 = s*s*s;
+ const T n1 = (4.0f*(s*s*s)+(t*t*t)) + (12.0f*((s*t)*s) + 6.0f*((t*s)*t));
+ const T n2 = (4.0f*(t*t*t)+(s*s*s)) + (12.0f*((t*s)*t) + 6.0f*((s*t)*s));
+ const T n3 = t*t*t;
+ return T(1.0f/6.0f)*Vec4<T>(n0,n1,n2,n3);
+ }
+
+ template<typename T>
+ static __forceinline Vec4<T> derivative(const T& u)
+ {
+ const T t = u;
+ const T s = 1.0f - u;
+ const T n0 = -s*s;
+ const T n1 = -t*t - 4.0f*(t*s);
+ const T n2 = s*s + 4.0f*(s*t);
+ const T n3 = t*t;
+ return T(0.5f)*Vec4<T>(n0,n1,n2,n3);
+ }
+
+ template<typename T>
+ static __forceinline Vec4<T> derivative2(const T& u)
+ {
+ const T t = u;
+ const T s = 1.0f - u;
+ const T n0 = s;
+ const T n1 = t - 2.0f*s;
+ const T n2 = s - 2.0f*t;
+ const T n3 = t;
+ return Vec4<T>(n0,n1,n2,n3);
+ }
+ };
+
+ struct PrecomputedBSplineBasis
+ {
+ enum { N = 16 };
+ public:
+ PrecomputedBSplineBasis() {}
+ PrecomputedBSplineBasis(int shift);
+
+ /* basis for bspline evaluation */
+ public:
+ float c0[N+1][N+1];
+ float c1[N+1][N+1];
+ float c2[N+1][N+1];
+ float c3[N+1][N+1];
+
+ /* basis for bspline derivative evaluation */
+ public:
+ float d0[N+1][N+1];
+ float d1[N+1][N+1];
+ float d2[N+1][N+1];
+ float d3[N+1][N+1];
+ };
+ extern PrecomputedBSplineBasis bspline_basis0;
+ extern PrecomputedBSplineBasis bspline_basis1;
+
+ template<typename Vertex>
+ struct BSplineCurveT
+ {
+ Vertex v0,v1,v2,v3;
+
+ __forceinline BSplineCurveT() {}
+
+ __forceinline BSplineCurveT(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3)
+ : v0(v0), v1(v1), v2(v2), v3(v3) {}
+
+ __forceinline Vertex begin() const {
+ return madd(1.0f/6.0f,v0,madd(2.0f/3.0f,v1,1.0f/6.0f*v2));
+ }
+
+ __forceinline Vertex end() const {
+ return madd(1.0f/6.0f,v1,madd(2.0f/3.0f,v2,1.0f/6.0f*v3));
+ }
+
+ __forceinline Vertex center() const {
+ return 0.25f*(v0+v1+v2+v3);
+ }
+
+ __forceinline BBox<Vertex> bounds() const {
+ return merge(BBox<Vertex>(v0),BBox<Vertex>(v1),BBox<Vertex>(v2),BBox<Vertex>(v3));
+ }
+
+ __forceinline friend BSplineCurveT operator -( const BSplineCurveT& a, const Vertex& b ) {
+ return BSplineCurveT(a.v0-b,a.v1-b,a.v2-b,a.v3-b);
+ }
+
+ __forceinline BSplineCurveT<Vec3ff> xfm_pr(const LinearSpace3fa& space, const Vec3fa& p) const
+ {
+ const Vec3ff q0(xfmVector(space,(Vec3fa)v0-p), v0.w);
+ const Vec3ff q1(xfmVector(space,(Vec3fa)v1-p), v1.w);
+ const Vec3ff q2(xfmVector(space,(Vec3fa)v2-p), v2.w);
+ const Vec3ff q3(xfmVector(space,(Vec3fa)v3-p), v3.w);
+ return BSplineCurveT<Vec3ff>(q0,q1,q2,q3);
+ }
+
+ __forceinline Vertex eval(const float t) const
+ {
+ const Vec4<float> b = BSplineBasis::eval(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+
+ __forceinline Vertex eval_du(const float t) const
+ {
+ const Vec4<float> b = BSplineBasis::derivative(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+
+ __forceinline Vertex eval_dudu(const float t) const
+ {
+ const Vec4<float> b = BSplineBasis::derivative2(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+
+ __forceinline void eval(const float t, Vertex& p, Vertex& dp, Vertex& ddp) const
+ {
+ p = eval(t);
+ dp = eval_du(t);
+ ddp = eval_dudu(t);
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = BSplineBasis::eval(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval_du(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = BSplineBasis::derivative(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval_dudu(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = BSplineBasis::derivative2(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline void veval(const vfloat<M>& t, Vec4vf<M>& p, Vec4vf<M>& dp) const
+ {
+ p = veval<M>(t);
+ dp = veval_du<M>(t);
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> eval0(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedBSplineBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&bspline_basis0.c0[size][ofs]), Vec4vf<M>(v0),
+ madd(vfloat<M>::loadu(&bspline_basis0.c1[size][ofs]), Vec4vf<M>(v1),
+ madd(vfloat<M>::loadu(&bspline_basis0.c2[size][ofs]), Vec4vf<M>(v2),
+ vfloat<M>::loadu(&bspline_basis0.c3[size][ofs]) * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> eval1(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedBSplineBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&bspline_basis1.c0[size][ofs]), Vec4vf<M>(v0),
+ madd(vfloat<M>::loadu(&bspline_basis1.c1[size][ofs]), Vec4vf<M>(v1),
+ madd(vfloat<M>::loadu(&bspline_basis1.c2[size][ofs]), Vec4vf<M>(v2),
+ vfloat<M>::loadu(&bspline_basis1.c3[size][ofs]) * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> derivative0(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedBSplineBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&bspline_basis0.d0[size][ofs]), Vec4vf<M>(v0),
+ madd(vfloat<M>::loadu(&bspline_basis0.d1[size][ofs]), Vec4vf<M>(v1),
+ madd(vfloat<M>::loadu(&bspline_basis0.d2[size][ofs]), Vec4vf<M>(v2),
+ vfloat<M>::loadu(&bspline_basis0.d3[size][ofs]) * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> derivative1(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedBSplineBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&bspline_basis1.d0[size][ofs]), Vec4vf<M>(v0),
+ madd(vfloat<M>::loadu(&bspline_basis1.d1[size][ofs]), Vec4vf<M>(v1),
+ madd(vfloat<M>::loadu(&bspline_basis1.d2[size][ofs]), Vec4vf<M>(v2),
+ vfloat<M>::loadu(&bspline_basis1.d3[size][ofs]) * Vec4vf<M>(v3))));
+ }
+
+ /* calculates bounds of bspline curve geometry */
+ __forceinline BBox3fa accurateRoundBounds() const
+ {
+ const int N = 7;
+ const float scale = 1.0f/(3.0f*(N-1));
+ Vec4vfx pl(pos_inf), pu(neg_inf);
+ for (int i=0; i<=N; i+=VSIZEX)
+ {
+ vintx vi = vintx(i)+vintx(step);
+ vboolx valid = vi <= vintx(N);
+ const Vec4vfx p = eval0<VSIZEX>(i,N);
+ const Vec4vfx dp = derivative0<VSIZEX>(i,N);
+ const Vec4vfx pm = p-Vec4vfx(scale)*select(vi!=vintx(0),dp,Vec4vfx(zero));
+ const Vec4vfx pp = p+Vec4vfx(scale)*select(vi!=vintx(N),dp,Vec4vfx(zero));
+ pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
+ pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
+ }
+ const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
+ const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
+ const float r_min = reduce_min(pl.w);
+ const float r_max = reduce_max(pu.w);
+ const Vec3fa upper_r = Vec3fa(max(abs(r_min),abs(r_max)));
+ return enlarge(BBox3fa(lower,upper),upper_r);
+ }
+
+ /* calculates bounds when tessellated into N line segments */
+ __forceinline BBox3fa accurateFlatBounds(int N) const
+ {
+ if (likely(N == 4))
+ {
+ const Vec4vf4 pi = eval0<4>(0,4);
+ const Vec3fa lower(reduce_min(pi.x),reduce_min(pi.y),reduce_min(pi.z));
+ const Vec3fa upper(reduce_max(pi.x),reduce_max(pi.y),reduce_max(pi.z));
+ const Vec3fa upper_r = Vec3fa(reduce_max(abs(pi.w)));
+ const Vec3ff pe = end();
+ return enlarge(BBox3fa(min(lower,pe),max(upper,pe)),max(upper_r,Vec3fa(abs(pe.w))));
+ }
+ else
+ {
+ Vec3vfx pl(pos_inf), pu(neg_inf); vfloatx ru(0.0f);
+ for (int i=0; i<=N; i+=VSIZEX)
+ {
+ vboolx valid = vintx(i)+vintx(step) <= vintx(N);
+ const Vec4vfx pi = eval0<VSIZEX>(i,N);
+
+ pl.x = select(valid,min(pl.x,pi.x),pl.x); // FIXME: use masked min
+ pl.y = select(valid,min(pl.y,pi.y),pl.y);
+ pl.z = select(valid,min(pl.z,pi.z),pl.z);
+
+ pu.x = select(valid,max(pu.x,pi.x),pu.x); // FIXME: use masked min
+ pu.y = select(valid,max(pu.y,pi.y),pu.y);
+ pu.z = select(valid,max(pu.z,pi.z),pu.z);
+
+ ru = select(valid,max(ru,abs(pi.w)),ru);
+ }
+ const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
+ const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
+ const Vec3fa upper_r(reduce_max(ru));
+ return enlarge(BBox3fa(lower,upper),upper_r);
+ }
+ }
+
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const BSplineCurveT& curve) {
+ return cout << "BSplineCurve { v0 = " << curve.v0 << ", v1 = " << curve.v1 << ", v2 = " << curve.v2 << ", v3 = " << curve.v3 << " }";
+ }
+ };
+
+ template<typename Vertex>
+ __forceinline void convert(const BezierCurveT<Vertex>& icurve, BezierCurveT<Vertex>& ocurve) {
+ ocurve = icurve;
+ }
+
+ template<typename Vertex>
+ __forceinline void convert(const BSplineCurveT<Vertex>& icurve, BSplineCurveT<Vertex>& ocurve) {
+ ocurve = icurve;
+ }
+
+ template<typename Vertex>
+ __forceinline void convert(const BezierCurveT<Vertex>& icurve, BSplineCurveT<Vertex>& ocurve)
+ {
+ const Vertex v0 = madd(6.0f,icurve.v0,madd(-7.0f,icurve.v1,2.0f*icurve.v2));
+ const Vertex v1 = msub(2.0f,icurve.v1,icurve.v2);
+ const Vertex v2 = msub(2.0f,icurve.v2,icurve.v1);
+ const Vertex v3 = madd(2.0f,icurve.v1,madd(-7.0f,icurve.v2,6.0f*icurve.v3));
+ ocurve = BSplineCurveT<Vertex>(v0,v1,v2,v3);
+ }
+
+ template<typename Vertex>
+ __forceinline void convert(const BSplineCurveT<Vertex>& icurve, BezierCurveT<Vertex>& ocurve)
+ {
+ const Vertex v0 = madd(1.0f/6.0f,icurve.v0,madd(2.0f/3.0f,icurve.v1,1.0f/6.0f*icurve.v2));
+ const Vertex v1 = madd(2.0f/3.0f,icurve.v1,1.0f/3.0f*icurve.v2);
+ const Vertex v2 = madd(1.0f/3.0f,icurve.v1,2.0f/3.0f*icurve.v2);
+ const Vertex v3 = madd(1.0f/6.0f,icurve.v1,madd(2.0f/3.0f,icurve.v2,1.0f/6.0f*icurve.v3));
+ ocurve = BezierCurveT<Vertex>(v0,v1,v2,v3);
+ }
+
+ template<typename CurveGeometry>
+ __forceinline BSplineCurveT<Vec3ff> enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const BSplineCurveT<Vec3ff>& curve)
+ {
+ return BSplineCurveT<Vec3ff>(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v1),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v2),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v3));
+ }
+
+ typedef BSplineCurveT<Vec3fa> BSplineCurve3fa;
+}
+
diff --git a/thirdparty/embree/kernels/subdiv/bspline_patch.h b/thirdparty/embree/kernels/subdiv/bspline_patch.h
new file mode 100644
index 0000000000..ff47f01c7a
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/bspline_patch.h
@@ -0,0 +1,449 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "catmullclark_patch.h"
+#include "bspline_curve.h"
+
+namespace embree
+{
+ template<typename Vertex, typename Vertex_t = Vertex>
+ class __aligned(64) BSplinePatchT
+ {
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+
+ public:
+
+ __forceinline BSplinePatchT () {}
+
+ __forceinline BSplinePatchT (const CatmullClarkPatch& patch) {
+ init(patch);
+ }
+
+ __forceinline BSplinePatchT(const CatmullClarkPatch& patch,
+ const BezierCurveT<Vertex>* border0,
+ const BezierCurveT<Vertex>* border1,
+ const BezierCurveT<Vertex>* border2,
+ const BezierCurveT<Vertex>* border3)
+ {
+ init(patch);
+ }
+
+ __forceinline BSplinePatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
+ init(edge,vertices,stride);
+ }
+
+ __forceinline Vertex hard_corner(const Vertex& v01, const Vertex& v02,
+ const Vertex& v10, const Vertex& v11, const Vertex& v12,
+ const Vertex& v20, const Vertex& v21, const Vertex& v22)
+ {
+ return 4.0f*v11 - 2.0f*(v12+v21) + v22;
+ }
+
+ __forceinline Vertex soft_convex_corner( const Vertex& v01, const Vertex& v02,
+ const Vertex& v10, const Vertex& v11, const Vertex& v12,
+ const Vertex& v20, const Vertex& v21, const Vertex& v22)
+ {
+ return -8.0f*v11 + 4.0f*(v12+v21) + v22;
+ }
+
+ __forceinline Vertex convex_corner(const float vertex_crease_weight,
+ const Vertex& v01, const Vertex& v02,
+ const Vertex& v10, const Vertex& v11, const Vertex& v12,
+ const Vertex& v20, const Vertex& v21, const Vertex& v22)
+ {
+ if (std::isinf(vertex_crease_weight)) return hard_corner(v01,v02,v10,v11,v12,v20,v21,v22);
+ else return soft_convex_corner(v01,v02,v10,v11,v12,v20,v21,v22);
+ }
+
+ __forceinline Vertex load(const HalfEdge* edge, const char* vertices, size_t stride) {
+ return Vertex_t::loadu(vertices+edge->getStartVertexIndex()*stride);
+ }
+
+ __forceinline void init_border(const CatmullClarkRing& edge0,
+ Vertex& v01, Vertex& v02,
+ const Vertex& v11, const Vertex& v12,
+ const Vertex& v21, const Vertex& v22)
+ {
+ if (likely(edge0.has_opposite_back(0)))
+ {
+ v01 = edge0.back(2);
+ v02 = edge0.back(1);
+ } else {
+ v01 = 2.0f*v11-v21;
+ v02 = 2.0f*v12-v22;
+ }
+ }
+
+ __forceinline void init_corner(const CatmullClarkRing& edge0,
+ Vertex& v00, const Vertex& v01, const Vertex& v02,
+ const Vertex& v10, const Vertex& v11, const Vertex& v12,
+ const Vertex& v20, const Vertex& v21, const Vertex& v22)
+ {
+ const bool MAYBE_UNUSED has_back1 = edge0.has_opposite_back(1);
+ const bool has_back0 = edge0.has_opposite_back(0);
+ const bool has_front1 = edge0.has_opposite_front(1);
+ const bool MAYBE_UNUSED has_front2 = edge0.has_opposite_front(2);
+
+ if (likely(has_back0)) {
+ if (likely(has_front1)) { assert(has_back1 && has_front2); v00 = edge0.back(3); }
+ else { assert(!has_back1); v00 = 2.0f*v01-v02; }
+ }
+ else {
+ if (likely(has_front1)) { assert(!has_front2); v00 = 2.0f*v10-v20; }
+ else v00 = convex_corner(edge0.vertex_crease_weight,v01,v02,v10,v11,v12,v20,v21,v22);
+ }
+ }
+
+ void init(const CatmullClarkPatch& patch)
+ {
+ /* fill inner vertices */
+ const Vertex v11 = v[1][1] = patch.ring[0].vtx;
+ const Vertex v12 = v[1][2] = patch.ring[1].vtx;
+ const Vertex v22 = v[2][2] = patch.ring[2].vtx;
+ const Vertex v21 = v[2][1] = patch.ring[3].vtx;
+
+ /* fill border vertices */
+ init_border(patch.ring[0],v[0][1],v[0][2],v11,v12,v21,v22);
+ init_border(patch.ring[1],v[1][3],v[2][3],v12,v22,v11,v21);
+ init_border(patch.ring[2],v[3][2],v[3][1],v22,v21,v12,v11);
+ init_border(patch.ring[3],v[2][0],v[1][0],v21,v11,v22,v12);
+
+ /* fill corner vertices */
+ init_corner(patch.ring[0],v[0][0],v[0][1],v[0][2],v[1][0],v11,v12,v[2][0],v21,v22);
+ init_corner(patch.ring[1],v[0][3],v[1][3],v[2][3],v[0][2],v12,v22,v[0][1],v11,v21);
+ init_corner(patch.ring[2],v[3][3],v[3][2],v[3][1],v[2][3],v22,v21,v[1][3],v12,v11);
+ init_corner(patch.ring[3],v[3][0],v[2][0],v[1][0],v[3][1],v21,v11,v[3][2],v22,v12);
+ }
+
+ void init_border(const HalfEdge* edge0, const char* vertices, size_t stride,
+ Vertex& v01, Vertex& v02,
+ const Vertex& v11, const Vertex& v12,
+ const Vertex& v21, const Vertex& v22)
+ {
+ if (likely(edge0->hasOpposite()))
+ {
+ const HalfEdge* e = edge0->opposite()->next()->next();
+ v01 = load(e,vertices,stride);
+ v02 = load(e->next(),vertices,stride);
+ } else {
+ v01 = 2.0f*v11-v21;
+ v02 = 2.0f*v12-v22;
+ }
+ }
+
+ void init_corner(const HalfEdge* edge0, const char* vertices, size_t stride,
+ Vertex& v00, const Vertex& v01, const Vertex& v02,
+ const Vertex& v10, const Vertex& v11, const Vertex& v12,
+ const Vertex& v20, const Vertex& v21, const Vertex& v22)
+ {
+ const bool has_back0 = edge0->hasOpposite();
+ const bool has_front1 = edge0->prev()->hasOpposite();
+
+ if (likely(has_back0))
+ {
+ const HalfEdge* e = edge0->opposite()->next();
+ if (likely(has_front1))
+ {
+ assert(e->hasOpposite());
+ assert(edge0->prev()->opposite()->prev()->hasOpposite());
+ v00 = load(e->opposite()->prev(),vertices,stride);
+ }
+ else {
+ assert(!e->hasOpposite());
+ v00 = 2.0f*v01-v02;
+ }
+ }
+ else
+ {
+ if (likely(has_front1)) {
+ assert(!edge0->prev()->opposite()->prev()->hasOpposite());
+ v00 = 2.0f*v10-v20;
+ }
+ else {
+ assert(edge0->vertex_crease_weight == 0.0f || std::isinf(edge0->vertex_crease_weight));
+ v00 = convex_corner(edge0->vertex_crease_weight,v01,v02,v10,v11,v12,v20,v21,v22);
+ }
+ }
+ }
+
+ void init(const HalfEdge* edge0, const char* vertices, size_t stride)
+ {
+ assert( edge0->isRegularFace() );
+
+ /* fill inner vertices */
+ const Vertex v11 = v[1][1] = load(edge0,vertices,stride); const HalfEdge* edge1 = edge0->next();
+ const Vertex v12 = v[1][2] = load(edge1,vertices,stride); const HalfEdge* edge2 = edge1->next();
+ const Vertex v22 = v[2][2] = load(edge2,vertices,stride); const HalfEdge* edge3 = edge2->next();
+ const Vertex v21 = v[2][1] = load(edge3,vertices,stride); assert(edge0 == edge3->next());
+
+ /* fill border vertices */
+ init_border(edge0,vertices,stride,v[0][1],v[0][2],v11,v12,v21,v22);
+ init_border(edge1,vertices,stride,v[1][3],v[2][3],v12,v22,v11,v21);
+ init_border(edge2,vertices,stride,v[3][2],v[3][1],v22,v21,v12,v11);
+ init_border(edge3,vertices,stride,v[2][0],v[1][0],v21,v11,v22,v12);
+
+ /* fill corner vertices */
+ init_corner(edge0,vertices,stride,v[0][0],v[0][1],v[0][2],v[1][0],v11,v12,v[2][0],v21,v22);
+ init_corner(edge1,vertices,stride,v[0][3],v[1][3],v[2][3],v[0][2],v12,v22,v[0][1],v11,v21);
+ init_corner(edge2,vertices,stride,v[3][3],v[3][2],v[3][1],v[2][3],v22,v21,v[1][3],v12,v11);
+ init_corner(edge3,vertices,stride,v[3][0],v[2][0],v[1][0],v[3][1],v21,v11,v[3][2],v22,v12);
+ }
+
+ __forceinline BBox<Vertex> bounds() const
+ {
+ const Vertex* const cv = &v[0][0];
+ BBox<Vertex> bounds (cv[0]);
+ for (size_t i=1; i<16 ; i++)
+ bounds.extend( cv[i] );
+ return bounds;
+ }
+
+ __forceinline Vertex eval(const float uu, const float vv) const
+ {
+ const Vec4f v_n = BSplineBasis::eval(vv);
+ const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
+ const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
+ const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
+ const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
+
+ const Vec4f u_n = BSplineBasis::eval(uu);
+ return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
+ }
+
+ __forceinline Vertex eval_du(const float uu, const float vv) const
+ {
+ const Vec4f v_n = BSplineBasis::eval(vv);
+ const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
+ const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
+ const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
+ const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
+
+ const Vec4f u_n = BSplineBasis::derivative(uu);
+ return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
+ }
+
+ __forceinline Vertex eval_dv(const float uu, const float vv) const
+ {
+ const Vec4f v_n = BSplineBasis::derivative(vv);
+ const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
+ const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
+ const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
+ const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
+
+ const Vec4f u_n = BSplineBasis::eval(uu);
+ return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
+ }
+
+ __forceinline Vertex eval_dudu(const float uu, const float vv) const
+ {
+ const Vec4f v_n = BSplineBasis::eval(vv);
+ const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
+ const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
+ const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
+ const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
+
+ const Vec4f u_n = BSplineBasis::derivative2(uu);
+ return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
+ }
+
+ __forceinline Vertex eval_dvdv(const float uu, const float vv) const
+ {
+ const Vec4f v_n = BSplineBasis::derivative2(vv);
+ const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
+ const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
+ const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
+ const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
+
+ const Vec4f u_n = BSplineBasis::eval(uu);
+ return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
+ }
+
+ __forceinline Vertex eval_dudv(const float uu, const float vv) const
+ {
+ const Vec4f v_n = BSplineBasis::derivative(vv);
+ const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
+ const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
+ const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
+ const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
+
+ const Vec4f u_n = BSplineBasis::derivative(uu);
+ return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
+ }
+
+ __forceinline Vertex normal(const float uu, const float vv) const
+ {
+ const Vertex tu = eval_du(uu,vv);
+ const Vertex tv = eval_dv(uu,vv);
+ return cross(tu,tv);
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> eval(const T& uu, const T& vv, const Vec4<T>& u_n, const Vec4<T>& v_n) const
+ {
+ const T curve0_x = madd(v_n[0],T(v[0][0].x),madd(v_n[1],T(v[1][0].x),madd(v_n[2],T(v[2][0].x),v_n[3] * T(v[3][0].x))));
+ const T curve1_x = madd(v_n[0],T(v[0][1].x),madd(v_n[1],T(v[1][1].x),madd(v_n[2],T(v[2][1].x),v_n[3] * T(v[3][1].x))));
+ const T curve2_x = madd(v_n[0],T(v[0][2].x),madd(v_n[1],T(v[1][2].x),madd(v_n[2],T(v[2][2].x),v_n[3] * T(v[3][2].x))));
+ const T curve3_x = madd(v_n[0],T(v[0][3].x),madd(v_n[1],T(v[1][3].x),madd(v_n[2],T(v[2][3].x),v_n[3] * T(v[3][3].x))));
+ const T x = madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));
+
+ const T curve0_y = madd(v_n[0],T(v[0][0].y),madd(v_n[1],T(v[1][0].y),madd(v_n[2],T(v[2][0].y),v_n[3] * T(v[3][0].y))));
+ const T curve1_y = madd(v_n[0],T(v[0][1].y),madd(v_n[1],T(v[1][1].y),madd(v_n[2],T(v[2][1].y),v_n[3] * T(v[3][1].y))));
+ const T curve2_y = madd(v_n[0],T(v[0][2].y),madd(v_n[1],T(v[1][2].y),madd(v_n[2],T(v[2][2].y),v_n[3] * T(v[3][2].y))));
+ const T curve3_y = madd(v_n[0],T(v[0][3].y),madd(v_n[1],T(v[1][3].y),madd(v_n[2],T(v[2][3].y),v_n[3] * T(v[3][3].y))));
+ const T y = madd(u_n[0],curve0_y,madd(u_n[1],curve1_y,madd(u_n[2],curve2_y,u_n[3] * curve3_y)));
+
+ const T curve0_z = madd(v_n[0],T(v[0][0].z),madd(v_n[1],T(v[1][0].z),madd(v_n[2],T(v[2][0].z),v_n[3] * T(v[3][0].z))));
+ const T curve1_z = madd(v_n[0],T(v[0][1].z),madd(v_n[1],T(v[1][1].z),madd(v_n[2],T(v[2][1].z),v_n[3] * T(v[3][1].z))));
+ const T curve2_z = madd(v_n[0],T(v[0][2].z),madd(v_n[1],T(v[1][2].z),madd(v_n[2],T(v[2][2].z),v_n[3] * T(v[3][2].z))));
+ const T curve3_z = madd(v_n[0],T(v[0][3].z),madd(v_n[1],T(v[1][3].z),madd(v_n[2],T(v[2][3].z),v_n[3] * T(v[3][3].z))));
+ const T z = madd(u_n[0],curve0_z,madd(u_n[1],curve1_z,madd(u_n[2],curve2_z,u_n[3] * curve3_z)));
+
+ return Vec3<T>(x,y,z);
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> eval(const T& uu, const T& vv) const
+ {
+ const Vec4<T> u_n = BSplineBasis::eval(uu);
+ const Vec4<T> v_n = BSplineBasis::eval(vv);
+ return eval(uu,vv,u_n,v_n);
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> eval_du(const T& uu, const T& vv) const
+ {
+ const Vec4<T> u_n = BSplineBasis::derivative(uu);
+ const Vec4<T> v_n = BSplineBasis::eval(vv);
+ return eval(uu,vv,u_n,v_n);
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> eval_dv(const T& uu, const T& vv) const
+ {
+ const Vec4<T> u_n = BSplineBasis::eval(uu);
+ const Vec4<T> v_n = BSplineBasis::derivative(vv);
+ return eval(uu,vv,u_n,v_n);
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> eval_dudu(const T& uu, const T& vv) const
+ {
+ const Vec4<T> u_n = BSplineBasis::derivative2(uu);
+ const Vec4<T> v_n = BSplineBasis::eval(vv);
+ return eval(uu,vv,u_n,v_n);
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> eval_dvdv(const T& uu, const T& vv) const
+ {
+ const Vec4<T> u_n = BSplineBasis::eval(uu);
+ const Vec4<T> v_n = BSplineBasis::derivative2(vv);
+ return eval(uu,vv,u_n,v_n);
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> eval_dudv(const T& uu, const T& vv) const
+ {
+ const Vec4<T> u_n = BSplineBasis::derivative(uu);
+ const Vec4<T> v_n = BSplineBasis::derivative(vv);
+ return eval(uu,vv,u_n,v_n);
+ }
+
+ template<typename T>
+ __forceinline Vec3<T> normal(const T& uu, const T& vv) const {
+ return cross(eval_du(uu,vv),eval_dv(uu,vv));
+ }
+
+ void eval(const float u, const float v,
+ Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
+ const float dscale = 1.0f) const
+ {
+ if (P) {
+ *P = eval(u,v);
+ }
+ if (dPdu) {
+ assert(dPdu); *dPdu = eval_du(u,v)*dscale;
+ assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
+ }
+ if (ddPdudu) {
+ assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
+ assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
+ assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
+ }
+ }
+
+ template<class vfloat>
+ __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n) const
+ {
+ const vfloat curve0_x = madd(v_n[0],vfloat(v[0][0][i]),madd(v_n[1],vfloat(v[1][0][i]),madd(v_n[2],vfloat(v[2][0][i]),v_n[3] * vfloat(v[3][0][i]))));
+ const vfloat curve1_x = madd(v_n[0],vfloat(v[0][1][i]),madd(v_n[1],vfloat(v[1][1][i]),madd(v_n[2],vfloat(v[2][1][i]),v_n[3] * vfloat(v[3][1][i]))));
+ const vfloat curve2_x = madd(v_n[0],vfloat(v[0][2][i]),madd(v_n[1],vfloat(v[1][2][i]),madd(v_n[2],vfloat(v[2][2][i]),v_n[3] * vfloat(v[3][2][i]))));
+ const vfloat curve3_x = madd(v_n[0],vfloat(v[0][3][i]),madd(v_n[1],vfloat(v[1][3][i]),madd(v_n[2],vfloat(v[2][3][i]),v_n[3] * vfloat(v[3][3][i]))));
+ return madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));
+ }
+
+ template<typename vbool, typename vfloat>
+ void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
+ const float dscale, const size_t dstride, const size_t N) const
+ {
+ if (P) {
+ const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
+ const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv,u_n,v_n));
+ }
+ if (dPdu)
+ {
+ {
+ assert(dPdu);
+ const Vec4<vfloat> u_n = BSplineBasis::derivative(uu);
+ const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,dPdu+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
+ }
+ {
+ assert(dPdv);
+ const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
+ const Vec4<vfloat> v_n = BSplineBasis::derivative(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,dPdv+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
+ }
+ }
+ if (ddPdudu)
+ {
+ {
+ assert(ddPdudu);
+ const Vec4<vfloat> u_n = BSplineBasis::derivative2(uu);
+ const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudu+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
+ }
+ {
+ assert(ddPdvdv);
+ const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
+ const Vec4<vfloat> v_n = BSplineBasis::derivative2(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdvdv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
+ }
+ {
+ assert(ddPdudv);
+ const Vec4<vfloat> u_n = BSplineBasis::derivative(uu);
+ const Vec4<vfloat> v_n = BSplineBasis::derivative(vv);
+ for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
+ }
+ }
+ }
+
+ friend __forceinline embree_ostream operator<<(embree_ostream o, const BSplinePatchT& p)
+ {
+ for (size_t y=0; y<4; y++)
+ for (size_t x=0; x<4; x++)
+ o << "[" << y << "][" << x << "] " << p.v[y][x] << embree_endl;
+ return o;
+ }
+
+ public:
+ Vertex v[4][4];
+ };
+
+ typedef BSplinePatchT<Vec3fa,Vec3fa_t> BSplinePatch3fa;
+}
diff --git a/thirdparty/embree/kernels/subdiv/catmullclark_coefficients.h b/thirdparty/embree/kernels/subdiv/catmullclark_coefficients.h
new file mode 100644
index 0000000000..46959797bf
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/catmullclark_coefficients.h
@@ -0,0 +1,85 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/geometry.h"
+
+namespace embree
+{
+ static const size_t MAX_PATCH_VALENCE = 16; //!< maximum number of vertices of a patch
+ static const size_t MAX_RING_FACE_VALENCE = 64; //!< maximum number of faces per ring
+ static const size_t MAX_RING_EDGE_VALENCE = 2*64; //!< maximum number of edges per ring
+
+ class CatmullClarkPrecomputedCoefficients
+ {
+ private:
+
+ float table_cos_2PI_div_n[MAX_RING_FACE_VALENCE+1];
+
+ float* table_limittangent_a[MAX_RING_FACE_VALENCE+1];
+ float* table_limittangent_b[MAX_RING_FACE_VALENCE+1];
+ float table_limittangent_c[MAX_RING_FACE_VALENCE+1];
+
+ __forceinline float set_cos_2PI_div_n(const size_t n) {
+ if (unlikely(n == 0)) return 1.0f;
+ return cosf(2.0f*float(pi)/(float)n);
+ }
+
+ __forceinline float set_limittangent_a(const size_t i, const size_t n)
+ {
+ if (unlikely(n == 0)) return 1.0f;
+ const float c0 = 1.0f/(float)n * 1.0f / sqrtf(4.0f + cosf(float(pi)/(float)n)*cosf(float(pi)/(float)n));
+ const float c1 = (1.0f/(float)n + cosf(float(pi)/(float)n) * c0);
+ return cosf(2.0f*float(pi)*(float)i/(float)n) * c1;
+ }
+
+ __forceinline float set_limittangent_b(const size_t i, const size_t n)
+ {
+ if (unlikely(n == 0)) return 1.0f;
+ const float c0 = 1.0f/(float)n * 1.0f / sqrtf(4.0f + cosf(float(pi)/(float)n)*cosf(float(pi)/(float)n));
+ return cosf((2.0f*float(pi)*i+float(pi))/(float)n) * c0;
+ }
+
+ __forceinline float set_limittangent_c(const size_t n)
+ {
+ if (unlikely(n == 0)) return 1.0f;
+ return 2.0f/16.0f * (5.0f + cosf(2.0f*float(pi)/(float)n) + cosf(float(pi)/(float)n) * sqrtf(18.0f+2.0f*cosf(2.0f*float(pi)/(float)n)));
+ }
+
+ public:
+
+ __forceinline float cos_2PI_div_n(const size_t n)
+ {
+ if (likely(n <= MAX_RING_FACE_VALENCE))
+ return table_cos_2PI_div_n[n];
+ else
+ return set_cos_2PI_div_n(n);
+ }
+
+ __forceinline float limittangent_a(const size_t i, const size_t n)
+ {
+ assert(n <= MAX_RING_FACE_VALENCE);
+ assert(i < n);
+ return table_limittangent_a[n][i];
+ }
+
+ __forceinline float limittangent_b(const size_t i, const size_t n)
+ {
+ assert(n <= MAX_RING_FACE_VALENCE);
+ assert(i < n);
+ return table_limittangent_b[n][i];
+ }
+
+ __forceinline float limittangent_c(const size_t n)
+ {
+ assert(n <= MAX_RING_FACE_VALENCE);
+ return table_limittangent_c[n];
+ }
+
+ static CatmullClarkPrecomputedCoefficients table;
+
+ CatmullClarkPrecomputedCoefficients();
+ ~CatmullClarkPrecomputedCoefficients();
+ };
+}
diff --git a/thirdparty/embree/kernels/subdiv/catmullclark_patch.h b/thirdparty/embree/kernels/subdiv/catmullclark_patch.h
new file mode 100644
index 0000000000..91772d94ed
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/catmullclark_patch.h
@@ -0,0 +1,562 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "catmullclark_ring.h"
+#include "bezier_curve.h"
+
+namespace embree
+{
+ template<typename Vertex, typename Vertex_t = Vertex>
+ class __aligned(64) CatmullClarkPatchT
+ {
+ public:
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
+ typedef typename CatmullClark1Ring::Type Type;
+
+ array_t<CatmullClark1RingT<Vertex,Vertex_t>,4> ring;
+
+ public:
+ __forceinline CatmullClarkPatchT () {}
+
+ __forceinline CatmullClarkPatchT (const HalfEdge* first_half_edge, const char* vertices, size_t stride) {
+ init(first_half_edge,vertices,stride);
+ }
+
+ __forceinline CatmullClarkPatchT (const HalfEdge* first_half_edge, const BufferView<Vec3fa>& vertices) {
+ init(first_half_edge,vertices.getPtr(),vertices.getStride());
+ }
+
+ __forceinline void init (const HalfEdge* first_half_edge, const char* vertices, size_t stride)
+ {
+ for (unsigned i=0; i<4; i++)
+ ring[i].init(first_half_edge+i,vertices,stride);
+
+ assert(verify());
+ }
+
+ __forceinline size_t bytes() const {
+ return ring[0].bytes()+ring[1].bytes()+ring[2].bytes()+ring[3].bytes();
+ }
+
+ __forceinline void serialize(void* ptr, size_t& ofs) const
+ {
+ for (size_t i=0; i<4; i++)
+ ring[i].serialize((char*)ptr,ofs);
+ }
+
+ __forceinline void deserialize(void* ptr)
+ {
+ size_t ofs = 0;
+ for (size_t i=0; i<4; i++)
+ ring[i].deserialize((char*)ptr,ofs);
+ }
+
+ __forceinline BBox3fa bounds() const
+ {
+ BBox3fa bounds (ring[0].bounds());
+ for (size_t i=1; i<4; i++)
+ bounds.extend(ring[i].bounds());
+ return bounds;
+ }
+
+ __forceinline Type type() const
+ {
+ const int ty0 = ring[0].type() ^ CatmullClark1Ring::TYPE_CREASES;
+ const int ty1 = ring[1].type() ^ CatmullClark1Ring::TYPE_CREASES;
+ const int ty2 = ring[2].type() ^ CatmullClark1Ring::TYPE_CREASES;
+ const int ty3 = ring[3].type() ^ CatmullClark1Ring::TYPE_CREASES;
+ return (Type) ((ty0 & ty1 & ty2 & ty3) ^ CatmullClark1Ring::TYPE_CREASES);
+ }
+
+ __forceinline bool isFinalResolution(float res) const {
+ return ring[0].isFinalResolution(res) && ring[1].isFinalResolution(res) && ring[2].isFinalResolution(res) && ring[3].isFinalResolution(res);
+ }
+
+ static __forceinline void init_regular(const CatmullClark1RingT<Vertex,Vertex_t>& p0,
+ const CatmullClark1RingT<Vertex,Vertex_t>& p1,
+ CatmullClark1RingT<Vertex,Vertex_t>& dest0,
+ CatmullClark1RingT<Vertex,Vertex_t>& dest1)
+ {
+ assert(p1.face_valence > 2);
+ dest1.vertex_level = dest0.vertex_level = p0.edge_level;
+ dest1.face_valence = dest0.face_valence = 4;
+ dest1.edge_valence = dest0.edge_valence = 8;
+ dest1.border_index = dest0.border_index = -1;
+ dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
+ dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
+
+ dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
+ dest1.ring[1] = dest0.ring[7] = (Vertex_t)p1.ring[0];
+ dest1.ring[0] = dest0.ring[6] = (Vertex_t)p1.vtx;
+ dest1.ring[7] = dest0.ring[5] = (Vertex_t)p1.ring[4];
+ dest1.ring[6] = dest0.ring[4] = (Vertex_t)p0.ring[p0.edge_valence-1];
+ dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.edge_valence-2];
+ dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
+ dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
+
+ dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
+ dest1.crease_weight[0] = dest0.crease_weight[3] = p1.crease_weight[1];
+ dest1.crease_weight[3] = dest0.crease_weight[2] = 0.0f;
+ dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
+
+ if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
+ {
+ dest0.eval_start_index = 3;
+ dest1.eval_start_index = 0;
+ dest0.eval_unique_identifier = p0.eval_unique_identifier;
+ dest1.eval_unique_identifier = p0.eval_unique_identifier;
+ }
+ else
+ {
+ dest0.eval_start_index = 1;
+ dest1.eval_start_index = 2;
+ dest0.eval_unique_identifier = p1.eval_unique_identifier;
+ dest1.eval_unique_identifier = p1.eval_unique_identifier;
+ }
+ }
+
+ static __forceinline void init_border(const CatmullClark1RingT<Vertex,Vertex_t> &p0,
+ const CatmullClark1RingT<Vertex,Vertex_t> &p1,
+ CatmullClark1RingT<Vertex,Vertex_t> &dest0,
+ CatmullClark1RingT<Vertex,Vertex_t> &dest1)
+ {
+ dest1.vertex_level = dest0.vertex_level = p0.edge_level;
+ dest1.face_valence = dest0.face_valence = 3;
+ dest1.edge_valence = dest0.edge_valence = 6;
+ dest0.border_index = 2;
+ dest1.border_index = 4;
+ dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
+ dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
+
+ dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
+ dest1.ring[1] = dest0.ring[5] = (Vertex_t)p1.ring[0];
+ dest1.ring[0] = dest0.ring[4] = (Vertex_t)p1.vtx;
+ dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.border_index+1]; // dummy
+ dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
+ dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
+
+ dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
+ dest1.crease_weight[0] = dest0.crease_weight[2] = p1.crease_weight[1];
+ dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
+
+ if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
+ {
+ dest0.eval_start_index = 1;
+ dest1.eval_start_index = 2;
+ dest0.eval_unique_identifier = p0.eval_unique_identifier;
+ dest1.eval_unique_identifier = p0.eval_unique_identifier;
+ }
+ else
+ {
+ dest0.eval_start_index = 2;
+ dest1.eval_start_index = 0;
+ dest0.eval_unique_identifier = p1.eval_unique_identifier;
+ dest1.eval_unique_identifier = p1.eval_unique_identifier;
+ }
+ }
+
+ static __forceinline void init_regular(const Vertex_t &center, const Vertex_t center_ring[8], const unsigned int offset, CatmullClark1RingT<Vertex,Vertex_t> &dest)
+ {
+ dest.vertex_level = 0.0f;
+ dest.face_valence = 4;
+ dest.edge_valence = 8;
+ dest.border_index = -1;
+ dest.vtx = (Vertex_t)center;
+ dest.vertex_crease_weight = 0.0f;
+ for (size_t i=0; i<8; i++)
+ dest.ring[i] = (Vertex_t)center_ring[(offset+i)%8];
+ for (size_t i=0; i<4; i++)
+ dest.crease_weight[i] = 0.0f;
+
+ dest.eval_start_index = (8-offset)>>1;
+ if (dest.eval_start_index >= dest.face_valence) dest.eval_start_index -= dest.face_valence;
+ assert( dest.eval_start_index < dest.face_valence );
+ dest.eval_unique_identifier = 0;
+ }
+
+ __noinline void subdivide(array_t<CatmullClarkPatchT,4>& patch) const
+ {
+ ring[0].subdivide(patch[0].ring[0]);
+ ring[1].subdivide(patch[1].ring[1]);
+ ring[2].subdivide(patch[2].ring[2]);
+ ring[3].subdivide(patch[3].ring[3]);
+
+ patch[0].ring[0].edge_level = 0.5f*ring[0].edge_level;
+ patch[0].ring[1].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
+ patch[0].ring[2].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
+ patch[0].ring[3].edge_level = 0.5f*ring[3].edge_level;
+
+ patch[1].ring[0].edge_level = 0.5f*ring[0].edge_level;
+ patch[1].ring[1].edge_level = 0.5f*ring[1].edge_level;
+ patch[1].ring[2].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
+ patch[1].ring[3].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
+
+ patch[2].ring[0].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
+ patch[2].ring[1].edge_level = 0.5f*ring[1].edge_level;
+ patch[2].ring[2].edge_level = 0.5f*ring[2].edge_level;
+ patch[2].ring[3].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
+
+ patch[3].ring[0].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
+ patch[3].ring[1].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
+ patch[3].ring[2].edge_level = 0.5f*ring[2].edge_level;
+ patch[3].ring[3].edge_level = 0.5f*ring[3].edge_level;
+
+ const bool regular0 = ring[0].has_last_face() && ring[1].face_valence > 2;
+ if (likely(regular0))
+ init_regular(patch[0].ring[0],patch[1].ring[1],patch[0].ring[1],patch[1].ring[0]);
+ else
+ init_border(patch[0].ring[0],patch[1].ring[1],patch[0].ring[1],patch[1].ring[0]);
+
+ const bool regular1 = ring[1].has_last_face() && ring[2].face_valence > 2;
+ if (likely(regular1))
+ init_regular(patch[1].ring[1],patch[2].ring[2],patch[1].ring[2],patch[2].ring[1]);
+ else
+ init_border(patch[1].ring[1],patch[2].ring[2],patch[1].ring[2],patch[2].ring[1]);
+
+ const bool regular2 = ring[2].has_last_face() && ring[3].face_valence > 2;
+ if (likely(regular2))
+ init_regular(patch[2].ring[2],patch[3].ring[3],patch[2].ring[3],patch[3].ring[2]);
+ else
+ init_border(patch[2].ring[2],patch[3].ring[3],patch[2].ring[3],patch[3].ring[2]);
+
+ const bool regular3 = ring[3].has_last_face() && ring[0].face_valence > 2;
+ if (likely(regular3))
+ init_regular(patch[3].ring[3],patch[0].ring[0],patch[3].ring[0],patch[0].ring[3]);
+ else
+ init_border(patch[3].ring[3],patch[0].ring[0],patch[3].ring[0],patch[0].ring[3]);
+
+ Vertex_t center = (ring[0].vtx + ring[1].vtx + ring[2].vtx + ring[3].vtx) * 0.25f;
+
+ Vertex_t center_ring[8];
+ center_ring[0] = (Vertex_t)patch[3].ring[3].ring[0];
+ center_ring[7] = (Vertex_t)patch[3].ring[3].vtx;
+ center_ring[6] = (Vertex_t)patch[2].ring[2].ring[0];
+ center_ring[5] = (Vertex_t)patch[2].ring[2].vtx;
+ center_ring[4] = (Vertex_t)patch[1].ring[1].ring[0];
+ center_ring[3] = (Vertex_t)patch[1].ring[1].vtx;
+ center_ring[2] = (Vertex_t)patch[0].ring[0].ring[0];
+ center_ring[1] = (Vertex_t)patch[0].ring[0].vtx;
+
+ init_regular(center,center_ring,0,patch[0].ring[2]);
+ init_regular(center,center_ring,2,patch[1].ring[3]);
+ init_regular(center,center_ring,4,patch[2].ring[0]);
+ init_regular(center,center_ring,6,patch[3].ring[1]);
+
+ assert(patch[0].verify());
+ assert(patch[1].verify());
+ assert(patch[2].verify());
+ assert(patch[3].verify());
+ }
+
+ bool verify() const {
+ return ring[0].hasValidPositions() && ring[1].hasValidPositions() && ring[2].hasValidPositions() && ring[3].hasValidPositions();
+ }
+
+ __forceinline void init( FinalQuad& quad ) const
+ {
+ quad.vtx[0] = (Vertex_t)ring[0].vtx;
+ quad.vtx[1] = (Vertex_t)ring[1].vtx;
+ quad.vtx[2] = (Vertex_t)ring[2].vtx;
+ quad.vtx[3] = (Vertex_t)ring[3].vtx;
+ };
+
+ friend __forceinline embree_ostream operator<<(embree_ostream o, const CatmullClarkPatchT &p)
+ {
+ o << "CatmullClarkPatch { " << embree_endl;
+ for (size_t i=0; i<4; i++)
+ o << "ring" << i << ": " << p.ring[i] << embree_endl;
+ o << "}" << embree_endl;
+ return o;
+ }
+ };
+
+ typedef CatmullClarkPatchT<Vec3fa,Vec3fa_t> CatmullClarkPatch3fa;
+
+ template<typename Vertex, typename Vertex_t = Vertex>
+ class __aligned(64) GeneralCatmullClarkPatchT
+ {
+ public:
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
+ typedef BezierCurveT<Vertex> BezierCurve;
+
+ static const unsigned SIZE = MAX_PATCH_VALENCE;
+ DynamicStackArray<GeneralCatmullClark1RingT<Vertex,Vertex_t>,8,SIZE> ring;
+ unsigned N;
+
+ __forceinline GeneralCatmullClarkPatchT ()
+ : N(0) {}
+
+ GeneralCatmullClarkPatchT (const HalfEdge* h, const char* vertices, size_t stride) {
+ init(h,vertices,stride);
+ }
+
+ __forceinline GeneralCatmullClarkPatchT (const HalfEdge* first_half_edge, const BufferView<Vec3fa>& vertices) {
+ init(first_half_edge,vertices.getPtr(),vertices.getStride());
+ }
+
+ __forceinline void init (const HalfEdge* h, const char* vertices, size_t stride)
+ {
+ unsigned int i = 0;
+ const HalfEdge* edge = h;
+ do {
+ ring[i].init(edge,vertices,stride);
+ edge = edge->next();
+ i++;
+ } while ((edge != h) && (i < SIZE));
+ N = i;
+ }
+
+ __forceinline unsigned size() const {
+ return N;
+ }
+
+ __forceinline bool isQuadPatch() const {
+ return (N == 4) && ring[0].only_quads && ring[1].only_quads && ring[2].only_quads && ring[3].only_quads;
+ }
+
+ static __forceinline void init_regular(const CatmullClark1RingT<Vertex,Vertex_t>& p0,
+ const CatmullClark1RingT<Vertex,Vertex_t>& p1,
+ CatmullClark1RingT<Vertex,Vertex_t>& dest0,
+ CatmullClark1RingT<Vertex,Vertex_t>& dest1)
+ {
+ assert(p1.face_valence > 2);
+ dest1.vertex_level = dest0.vertex_level = p0.edge_level;
+ dest1.face_valence = dest0.face_valence = 4;
+ dest1.edge_valence = dest0.edge_valence = 8;
+ dest1.border_index = dest0.border_index = -1;
+ dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
+ dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
+
+ dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
+ dest1.ring[1] = dest0.ring[7] = (Vertex_t)p1.ring[0];
+ dest1.ring[0] = dest0.ring[6] = (Vertex_t)p1.vtx;
+ dest1.ring[7] = dest0.ring[5] = (Vertex_t)p1.ring[4];
+ dest1.ring[6] = dest0.ring[4] = (Vertex_t)p0.ring[p0.edge_valence-1];
+ dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.edge_valence-2];
+ dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
+ dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
+
+ dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
+ dest1.crease_weight[0] = dest0.crease_weight[3] = p1.crease_weight[1];
+ dest1.crease_weight[3] = dest0.crease_weight[2] = 0.0f;
+ dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
+
+ if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
+ {
+ dest0.eval_start_index = 3;
+ dest1.eval_start_index = 0;
+ dest0.eval_unique_identifier = p0.eval_unique_identifier;
+ dest1.eval_unique_identifier = p0.eval_unique_identifier;
+ }
+ else
+ {
+ dest0.eval_start_index = 1;
+ dest1.eval_start_index = 2;
+ dest0.eval_unique_identifier = p1.eval_unique_identifier;
+ dest1.eval_unique_identifier = p1.eval_unique_identifier;
+ }
+ }
+
+
+ static __forceinline void init_border(const CatmullClark1RingT<Vertex,Vertex_t> &p0,
+ const CatmullClark1RingT<Vertex,Vertex_t> &p1,
+ CatmullClark1RingT<Vertex,Vertex_t> &dest0,
+ CatmullClark1RingT<Vertex,Vertex_t> &dest1)
+ {
+ dest1.vertex_level = dest0.vertex_level = p0.edge_level;
+ dest1.face_valence = dest0.face_valence = 3;
+ dest1.edge_valence = dest0.edge_valence = 6;
+ dest0.border_index = 2;
+ dest1.border_index = 4;
+ dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
+ dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
+
+ dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
+ dest1.ring[1] = dest0.ring[5] = (Vertex_t)p1.ring[0];
+ dest1.ring[0] = dest0.ring[4] = (Vertex_t)p1.vtx;
+ dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.border_index+1]; // dummy
+ dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
+ dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
+
+ dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
+ dest1.crease_weight[0] = dest0.crease_weight[2] = p1.crease_weight[1];
+ dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
+
+ if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
+ {
+ dest0.eval_start_index = 1;
+ dest1.eval_start_index = 2;
+ dest0.eval_unique_identifier = p0.eval_unique_identifier;
+ dest1.eval_unique_identifier = p0.eval_unique_identifier;
+ }
+ else
+ {
+ dest0.eval_start_index = 2;
+ dest1.eval_start_index = 0;
+ dest0.eval_unique_identifier = p1.eval_unique_identifier;
+ dest1.eval_unique_identifier = p1.eval_unique_identifier;
+ }
+ }
+
+ static __forceinline void init_regular(const Vertex_t &center, const array_t<Vertex_t,2*SIZE>& center_ring, const float vertex_level, const unsigned int N, const unsigned int offset, CatmullClark1RingT<Vertex,Vertex_t> &dest)
+ {
+ assert(N<(MAX_RING_FACE_VALENCE));
+ assert(2*N<(MAX_RING_EDGE_VALENCE));
+ dest.vertex_level = vertex_level;
+ dest.face_valence = N;
+ dest.edge_valence = 2*N;
+ dest.border_index = -1;
+ dest.vtx = (Vertex_t)center;
+ dest.vertex_crease_weight = 0.0f;
+ for (unsigned i=0; i<2*N; i++) {
+ dest.ring[i] = (Vertex_t)center_ring[(2*N+offset+i-1)%(2*N)];
+ assert(isvalid(dest.ring[i]));
+ }
+ for (unsigned i=0; i<N; i++)
+ dest.crease_weight[i] = 0.0f;
+
+ assert(offset <= 2*N);
+ dest.eval_start_index = (2*N-offset)>>1;
+ if (dest.eval_start_index >= dest.face_valence) dest.eval_start_index -= dest.face_valence;
+
+ assert( dest.eval_start_index < dest.face_valence );
+ dest.eval_unique_identifier = 0;
+ }
+
+ __noinline void subdivide(array_t<CatmullClarkPatch,SIZE>& patch, unsigned& N_o) const
+ {
+ N_o = N;
+ assert( N );
+ for (unsigned i=0; i<N; i++) {
+ unsigned ip1 = (i+1)%N; // FIXME: %
+ ring[i].subdivide(patch[i].ring[0]);
+ patch[i] .ring[0].edge_level = 0.5f*ring[i].edge_level;
+ patch[ip1].ring[3].edge_level = 0.5f*ring[i].edge_level;
+
+ assert( patch[i].ring[0].hasValidPositions() );
+
+ }
+ assert(N < 2*SIZE);
+ Vertex_t center = Vertex_t(0.0f);
+ array_t<Vertex_t,2*SIZE> center_ring;
+ float center_vertex_level = 2.0f; // guarantees that irregular vertices get always isolated also for non-quads
+
+ for (unsigned i=0; i<N; i++)
+ {
+ unsigned ip1 = (i+1)%N; // FIXME: %
+ unsigned im1 = (i+N-1)%N; // FIXME: %
+ bool regular = ring[i].has_last_face() && ring[ip1].face_valence > 2;
+ if (likely(regular)) init_regular(patch[i].ring[0],patch[ip1].ring[0],patch[i].ring[1],patch[ip1].ring[3]);
+ else init_border (patch[i].ring[0],patch[ip1].ring[0],patch[i].ring[1],patch[ip1].ring[3]);
+
+ assert( patch[i].ring[1].hasValidPositions() );
+ assert( patch[ip1].ring[3].hasValidPositions() );
+
+ float level = 0.25f*(ring[im1].edge_level+ring[ip1].edge_level);
+ patch[i].ring[1].edge_level = patch[ip1].ring[2].edge_level = level;
+ center_vertex_level = max(center_vertex_level,level);
+
+ center += ring[i].vtx;
+ center_ring[2*i+0] = (Vertex_t)patch[i].ring[0].vtx;
+ center_ring[2*i+1] = (Vertex_t)patch[i].ring[0].ring[0];
+ }
+ center /= float(N);
+
+ for (unsigned int i=0; i<N; i++) {
+ init_regular(center,center_ring,center_vertex_level,N,2*i,patch[i].ring[2]);
+
+ assert( patch[i].ring[2].hasValidPositions() );
+ }
+ }
+
+ void init(CatmullClarkPatch& patch) const
+ {
+ assert(size() == 4);
+ ring[0].convert(patch.ring[0]);
+ ring[1].convert(patch.ring[1]);
+ ring[2].convert(patch.ring[2]);
+ ring[3].convert(patch.ring[3]);
+ }
+
+ static void fix_quad_ring_order (array_t<CatmullClarkPatch,GeneralCatmullClarkPatchT::SIZE>& patches)
+ {
+ CatmullClark1Ring patches1ring1 = patches[1].ring[1];
+ patches[1].ring[1] = patches[1].ring[0]; // FIXME: optimize these assignments
+ patches[1].ring[0] = patches[1].ring[3];
+ patches[1].ring[3] = patches[1].ring[2];
+ patches[1].ring[2] = patches1ring1;
+
+ CatmullClark1Ring patches2ring2 = patches[2].ring[2];
+ patches[2].ring[2] = patches[2].ring[0];
+ patches[2].ring[0] = patches2ring2;
+ CatmullClark1Ring patches2ring3 = patches[2].ring[3];
+ patches[2].ring[3] = patches[2].ring[1];
+ patches[2].ring[1] = patches2ring3;
+
+ CatmullClark1Ring patches3ring3 = patches[3].ring[3];
+ patches[3].ring[3] = patches[3].ring[0];
+ patches[3].ring[0] = patches[3].ring[1];
+ patches[3].ring[1] = patches[3].ring[2];
+ patches[3].ring[2] = patches3ring3;
+ }
+
+ __forceinline void getLimitBorder(BezierCurve curves[GeneralCatmullClarkPatchT::SIZE]) const
+ {
+ Vertex P0 = ring[0].getLimitVertex();
+ for (unsigned i=0; i<N; i++)
+ {
+ const unsigned i0 = i, i1 = i+1==N ? 0 : i+1;
+ const Vertex P1 = madd(1.0f/3.0f,ring[i0].getLimitTangent(),P0);
+ const Vertex P3 = ring[i1].getLimitVertex();
+ const Vertex P2 = madd(1.0f/3.0f,ring[i1].getSecondLimitTangent(),P3);
+ new (&curves[i]) BezierCurve(P0,P1,P2,P3);
+ P0 = P3;
+ }
+ }
+
+ __forceinline void getLimitBorder(BezierCurve curves[2], const unsigned subPatch) const
+ {
+ const unsigned i0 = subPatch;
+ const Vertex t0_p = ring[i0].getLimitTangent();
+ const Vertex t0_m = ring[i0].getSecondLimitTangent();
+
+ const unsigned i1 = subPatch+1 == N ? 0 : subPatch+1;
+ const Vertex t1_p = ring[i1].getLimitTangent();
+ const Vertex t1_m = ring[i1].getSecondLimitTangent();
+
+ const unsigned i2 = subPatch == 0 ? N-1 : subPatch-1;
+ const Vertex t2_p = ring[i2].getLimitTangent();
+ const Vertex t2_m = ring[i2].getSecondLimitTangent();
+
+ const Vertex b00 = ring[i0].getLimitVertex();
+ const Vertex b03 = ring[i1].getLimitVertex();
+ const Vertex b33 = ring[i2].getLimitVertex();
+
+ const Vertex b01 = madd(1.0/3.0f,t0_p,b00);
+ const Vertex b11 = madd(1.0/3.0f,t0_m,b00);
+
+ //const Vertex b13 = madd(1.0/3.0f,t1_p,b03);
+ const Vertex b02 = madd(1.0/3.0f,t1_m,b03);
+
+ const Vertex b22 = madd(1.0/3.0f,t2_p,b33);
+ const Vertex b23 = madd(1.0/3.0f,t2_m,b33);
+
+ new (&curves[0]) BezierCurve(b00,b01,b02,b03);
+ new (&curves[1]) BezierCurve(b33,b22,b11,b00);
+ }
+
+ friend __forceinline embree_ostream operator<<(embree_ostream o, const GeneralCatmullClarkPatchT &p)
+ {
+ o << "GeneralCatmullClarkPatch { " << embree_endl;
+ for (unsigned i=0; i<p.N; i++)
+ o << "ring" << i << ": " << p.ring[i] << embree_endl;
+ o << "}" << embree_endl;
+ return o;
+ }
+ };
+
+ typedef GeneralCatmullClarkPatchT<Vec3fa,Vec3fa_t> GeneralCatmullClarkPatch3fa;
+}
diff --git a/thirdparty/embree/kernels/subdiv/catmullclark_ring.h b/thirdparty/embree/kernels/subdiv/catmullclark_ring.h
new file mode 100644
index 0000000000..e5ad5dadfe
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/catmullclark_ring.h
@@ -0,0 +1,826 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/geometry.h"
+#include "../common/buffer.h"
+#include "half_edge.h"
+#include "catmullclark_coefficients.h"
+
+namespace embree
+{
+ struct __aligned(64) FinalQuad {
+ Vec3fa vtx[4];
+ };
+
+ template<typename Vertex, typename Vertex_t = Vertex>
+ struct __aligned(64) CatmullClark1RingT
+ {
+ ALIGNED_STRUCT_(64);
+
+ int border_index; //!< edge index where border starts
+ unsigned int face_valence; //!< number of adjacent quad faces
+ unsigned int edge_valence; //!< number of adjacent edges (2*face_valence)
+ float vertex_crease_weight; //!< weight of vertex crease (0 if no vertex crease)
+ DynamicStackArray<float,16,MAX_RING_FACE_VALENCE> crease_weight; //!< edge crease weights for each adjacent edge
+ float vertex_level; //!< maximum level of all adjacent edges
+ float edge_level; //!< level of first edge
+ unsigned int eval_start_index; //!< topology dependent index to start evaluation
+ unsigned int eval_unique_identifier; //!< topology dependent unique identifier for this ring
+ Vertex vtx; //!< center vertex
+ DynamicStackArray<Vertex,32,MAX_RING_EDGE_VALENCE> ring; //!< ring of neighboring vertices
+
+ public:
+ CatmullClark1RingT ()
+ : eval_start_index(0), eval_unique_identifier(0) {} // FIXME: default constructor should be empty
+
+ /*! calculates number of bytes required to serialize this structure */
+ __forceinline size_t bytes() const
+ {
+ size_t ofs = 0;
+ ofs += sizeof(border_index);
+ ofs += sizeof(face_valence);
+ assert(2*face_valence == edge_valence);
+ ofs += sizeof(vertex_crease_weight);
+ ofs += face_valence*sizeof(float);
+ ofs += sizeof(vertex_level);
+ ofs += sizeof(edge_level);
+ ofs += sizeof(eval_start_index);
+ ofs += sizeof(eval_unique_identifier);
+ ofs += sizeof(vtx);
+ ofs += edge_valence*sizeof(Vertex);
+ return ofs;
+ }
+
+ template<typename Ty>
+ static __forceinline void store(char* ptr, size_t& ofs, const Ty& v) {
+ *(Ty*)&ptr[ofs] = v; ofs += sizeof(Ty);
+ }
+
+ template<typename Ty>
+ static __forceinline void load(char* ptr, size_t& ofs, Ty& v) {
+ v = *(Ty*)&ptr[ofs]; ofs += sizeof(Ty);
+ }
+
+ /*! serializes the ring to some memory location */
+ __forceinline void serialize(char* ptr, size_t& ofs) const
+ {
+ store(ptr,ofs,border_index);
+ store(ptr,ofs,face_valence);
+ store(ptr,ofs,vertex_crease_weight);
+ for (size_t i=0; i<face_valence; i++)
+ store(ptr,ofs,crease_weight[i]);
+ store(ptr,ofs,vertex_level);
+ store(ptr,ofs,edge_level);
+ store(ptr,ofs,eval_start_index);
+ store(ptr,ofs,eval_unique_identifier);
+ Vertex_t::storeu(&ptr[ofs],vtx); ofs += sizeof(Vertex);
+ for (size_t i=0; i<edge_valence; i++) {
+ Vertex_t::storeu(&ptr[ofs],ring[i]); ofs += sizeof(Vertex);
+ }
+ }
+
+ /*! deserializes the ring from some memory location */
+ __forceinline void deserialize(char* ptr, size_t& ofs)
+ {
+ load(ptr,ofs,border_index);
+ load(ptr,ofs,face_valence);
+ edge_valence = 2*face_valence;
+ load(ptr,ofs,vertex_crease_weight);
+ for (size_t i=0; i<face_valence; i++)
+ load(ptr,ofs,crease_weight[i]);
+ load(ptr,ofs,vertex_level);
+ load(ptr,ofs,edge_level);
+ load(ptr,ofs,eval_start_index);
+ load(ptr,ofs,eval_unique_identifier);
+ vtx = Vertex_t::loadu(&ptr[ofs]); ofs += sizeof(Vertex);
+ for (size_t i=0; i<edge_valence; i++) {
+ ring[i] = Vertex_t::loadu(&ptr[ofs]); ofs += sizeof(Vertex);
+ }
+ }
+
+ __forceinline bool hasBorder() const {
+ return border_index != -1;
+ }
+
+ __forceinline const Vertex& front(size_t i) const {
+ assert(edge_valence>i);
+ return ring[i];
+ }
+
+ __forceinline const Vertex& back(size_t i) const {
+ assert(edge_valence>=i);
+ return ring[edge_valence-i];
+ }
+
+ __forceinline bool has_last_face() const {
+ return (size_t)border_index != (size_t)edge_valence-2;
+ }
+
+ __forceinline bool has_opposite_front(size_t i) const {
+ return (size_t)border_index != 2*i;
+ }
+
+ __forceinline bool has_opposite_back(size_t i) const {
+ return (size_t)border_index != ((size_t)edge_valence-2-2*i);
+ }
+
+ __forceinline BBox3fa bounds() const
+ {
+ BBox3fa bounds ( vtx );
+ for (size_t i = 0; i<edge_valence ; i++)
+ bounds.extend( ring[i] );
+ return bounds;
+ }
+
+ /*! initializes the ring from the half edge structure */
+ __forceinline void init(const HalfEdge* const h, const char* vertices, size_t stride)
+ {
+ border_index = -1;
+ vtx = Vertex_t::loadu(vertices+h->getStartVertexIndex()*stride);
+ vertex_crease_weight = h->vertex_crease_weight;
+
+ HalfEdge* p = (HalfEdge*) h;
+
+ unsigned i=0;
+ unsigned min_vertex_index = (unsigned)-1;
+ unsigned min_vertex_index_face = (unsigned)-1;
+ edge_level = p->edge_level;
+ vertex_level = 0.0f;
+
+ do
+ {
+ vertex_level = max(vertex_level,p->edge_level);
+ crease_weight[i/2] = p->edge_crease_weight;
+ assert(p->hasOpposite() || p->edge_crease_weight == float(inf));
+
+ /* store first two vertices of face */
+ p = p->next();
+ const unsigned index0 = p->getStartVertexIndex();
+ ring[i++] = Vertex_t::loadu(vertices+index0*stride);
+ if (index0 < min_vertex_index) { min_vertex_index = index0; min_vertex_index_face = i>>1; }
+ p = p->next();
+
+ const unsigned index1 = p->getStartVertexIndex();
+ ring[i++] = Vertex_t::loadu(vertices+index1*stride);
+ p = p->next();
+
+ /* continue with next face */
+ if (likely(p->hasOpposite()))
+ p = p->opposite();
+
+ /* if there is no opposite go the long way to the other side of the border */
+ else
+ {
+ /* find minimum start vertex */
+ const unsigned index0 = p->getStartVertexIndex();
+ if (index0 < min_vertex_index) { min_vertex_index = index0; min_vertex_index_face = i>>1; }
+
+ /*! mark first border edge and store dummy vertex for face between the two border edges */
+ border_index = i;
+ crease_weight[i/2] = inf;
+ ring[i++] = Vertex_t::loadu(vertices+index0*stride);
+ ring[i++] = vtx; // dummy vertex
+
+ /*! goto other side of border */
+ p = (HalfEdge*) h;
+ while (p->hasOpposite())
+ p = p->opposite()->next();
+ }
+
+ } while (p != h);
+
+ edge_valence = i;
+ face_valence = i >> 1;
+ eval_unique_identifier = min_vertex_index;
+ eval_start_index = min_vertex_index_face;
+
+ assert( hasValidPositions() );
+ }
+
+ __forceinline void subdivide(CatmullClark1RingT& dest) const
+ {
+ dest.edge_level = 0.5f*edge_level;
+ dest.vertex_level = 0.5f*vertex_level;
+ dest.face_valence = face_valence;
+ dest.edge_valence = edge_valence;
+ dest.border_index = border_index;
+ dest.vertex_crease_weight = max(0.0f,vertex_crease_weight-1.0f);
+ dest.eval_start_index = eval_start_index;
+ dest.eval_unique_identifier = eval_unique_identifier;
+
+ /* calculate face points */
+ Vertex_t S = Vertex_t(0.0f);
+ for (size_t i=0; i<face_valence; i++)
+ {
+ size_t face_index = i + eval_start_index; if (face_index >= face_valence) face_index -= face_valence; assert(face_index < face_valence);
+ size_t index0 = 2*face_index+0; if (index0 >= edge_valence) index0 -= edge_valence; assert(index0 < edge_valence);
+ size_t index1 = 2*face_index+1; if (index1 >= edge_valence) index1 -= edge_valence; assert(index1 < edge_valence);
+ size_t index2 = 2*face_index+2; if (index2 >= edge_valence) index2 -= edge_valence; assert(index2 < edge_valence);
+ S += dest.ring[index1] = ((vtx + ring[index1]) + (ring[index0] + ring[index2])) * 0.25f;
+ }
+
+ /* calculate new edge points */
+ size_t num_creases = 0;
+ array_t<size_t,MAX_RING_FACE_VALENCE> crease_id;
+
+ for (size_t i=0; i<face_valence; i++)
+ {
+ size_t face_index = i + eval_start_index;
+ if (face_index >= face_valence) face_index -= face_valence;
+ const float edge_crease = crease_weight[face_index];
+ dest.crease_weight[face_index] = max(edge_crease-1.0f,0.0f);
+
+ size_t index = 2*face_index;
+ size_t prev_index = face_index == 0 ? edge_valence-1 : 2*face_index-1;
+ size_t next_index = 2*face_index+1;
+
+ const Vertex_t v = vtx + ring[index];
+ const Vertex_t f = dest.ring[prev_index] + dest.ring[next_index];
+ S += ring[index];
+
+ /* fast path for regular edge points */
+ if (likely(edge_crease <= 0.0f)) {
+ dest.ring[index] = (v+f) * 0.25f;
+ }
+
+ /* slower path for hard edge rule */
+ else {
+ crease_id[num_creases++] = face_index;
+ dest.ring[index] = v*0.5f;
+
+ /* even slower path for blended edge rule */
+ if (unlikely(edge_crease < 1.0f)) {
+ dest.ring[index] = lerp((v+f)*0.25f,v*0.5f,edge_crease);
+ }
+ }
+ }
+
+ /* compute new vertex using smooth rule */
+ const float inv_face_valence = 1.0f / (float)face_valence;
+ const Vertex_t v_smooth = (Vertex_t) madd(inv_face_valence,S,(float(face_valence)-2.0f)*vtx)*inv_face_valence;
+ dest.vtx = v_smooth;
+
+ /* compute new vertex using vertex_crease_weight rule */
+ if (unlikely(vertex_crease_weight > 0.0f))
+ {
+ if (vertex_crease_weight >= 1.0f) {
+ dest.vtx = vtx;
+ } else {
+ dest.vtx = lerp(v_smooth,vtx,vertex_crease_weight);
+ }
+ return;
+ }
+
+ /* no edge crease rule and dart rule */
+ if (likely(num_creases <= 1))
+ return;
+
+ /* compute new vertex using crease rule */
+ if (likely(num_creases == 2))
+ {
+ /* update vertex using crease rule */
+ const size_t crease0 = crease_id[0], crease1 = crease_id[1];
+ const Vertex_t v_sharp = (Vertex_t)(ring[2*crease0] + 6.0f*vtx + ring[2*crease1]) * (1.0f / 8.0f);
+ dest.vtx = v_sharp;
+
+ /* update crease_weights using chaikin rule */
+ const float crease_weight0 = crease_weight[crease0], crease_weight1 = crease_weight[crease1];
+ dest.crease_weight[crease0] = max(0.25f*(3.0f*crease_weight0 + crease_weight1)-1.0f,0.0f);
+ dest.crease_weight[crease1] = max(0.25f*(3.0f*crease_weight1 + crease_weight0)-1.0f,0.0f);
+
+ /* interpolate between sharp and smooth rule */
+ const float v_blend = 0.5f*(crease_weight0+crease_weight1);
+ if (unlikely(v_blend < 1.0f)) {
+ dest.vtx = lerp(v_smooth,v_sharp,v_blend);
+ }
+ }
+
+ /* compute new vertex using corner rule */
+ else {
+ dest.vtx = vtx;
+ }
+ }
+
+ __forceinline bool isRegular1() const
+ {
+ if (border_index == -1) {
+ if (face_valence == 4) return true;
+ } else {
+ if (face_valence < 4) return true;
+ }
+ return false;
+ }
+
+ __forceinline size_t numEdgeCreases() const
+ {
+ ssize_t numCreases = 0;
+ for (size_t i=0; i<face_valence; i++) {
+ numCreases += crease_weight[i] > 0.0f;
+ }
+ return numCreases;
+ }
+
+ enum Type {
+ TYPE_NONE = 0, //!< invalid type
+ TYPE_REGULAR = 1, //!< regular patch when ignoring creases
+ TYPE_REGULAR_CREASES = 2, //!< regular patch when considering creases
+ TYPE_GREGORY = 4, //!< gregory patch when ignoring creases
+ TYPE_GREGORY_CREASES = 8, //!< gregory patch when considering creases
+ TYPE_CREASES = 16 //!< patch has crease features
+ };
+
+ __forceinline Type type() const
+ {
+ /* check if there is an edge crease anywhere */
+ const size_t numCreases = numEdgeCreases();
+ const bool noInnerCreases = hasBorder() ? numCreases == 2 : numCreases == 0;
+
+ Type crease_mask = (Type) (TYPE_REGULAR | TYPE_GREGORY);
+ if (noInnerCreases ) crease_mask = (Type) (crease_mask | TYPE_REGULAR_CREASES | TYPE_GREGORY_CREASES);
+ if (numCreases != 0) crease_mask = (Type) (crease_mask | TYPE_CREASES);
+
+ /* calculate if this vertex is regular */
+ bool hasBorder = border_index != -1;
+ if (face_valence == 2 && hasBorder) {
+ if (vertex_crease_weight == 0.0f ) return (Type) (crease_mask & (TYPE_REGULAR | TYPE_REGULAR_CREASES | TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
+ else if (vertex_crease_weight == float(inf)) return (Type) (crease_mask & (TYPE_REGULAR | TYPE_REGULAR_CREASES | TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
+ else return TYPE_CREASES;
+ }
+ else if (vertex_crease_weight != 0.0f) return TYPE_CREASES;
+ else if (face_valence == 3 && hasBorder) return (Type) (crease_mask & (TYPE_REGULAR | TYPE_REGULAR_CREASES | TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
+ else if (face_valence == 4 && !hasBorder) return (Type) (crease_mask & (TYPE_REGULAR | TYPE_REGULAR_CREASES | TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
+ else return (Type) (crease_mask & (TYPE_GREGORY | TYPE_GREGORY_CREASES | TYPE_CREASES));
+ }
+
+ __forceinline bool isFinalResolution(float res) const {
+ return vertex_level <= res;
+ }
+
+ /* computes the limit vertex */
+ __forceinline Vertex getLimitVertex() const
+ {
+ /* return hard corner */
+ if (unlikely(std::isinf(vertex_crease_weight)))
+ return vtx;
+
+ /* border vertex rule */
+ if (unlikely(border_index != -1))
+ {
+ const unsigned int second_border_index = border_index+2 >= int(edge_valence) ? 0 : border_index+2;
+ return (4.0f * vtx + (ring[border_index] + ring[second_border_index])) * 1.0f/6.0f;
+ }
+
+ Vertex_t F( 0.0f );
+ Vertex_t E( 0.0f );
+
+ assert(eval_start_index < face_valence);
+
+ for (size_t i=0; i<face_valence; i++) {
+ size_t index = i+eval_start_index;
+ if (index >= face_valence) index -= face_valence;
+ F += ring[2*index+1];
+ E += ring[2*index];
+ }
+
+ const float n = (float)face_valence;
+ return (Vertex_t)(n*n*vtx+4.0f*E+F) / ((n+5.0f)*n);
+ }
+
+ /* gets limit tangent in the direction of egde vtx -> ring[0] */
+ __forceinline Vertex getLimitTangent() const
+ {
+ if (unlikely(std::isinf(vertex_crease_weight)))
+ return ring[0] - vtx;
+
+ /* border vertex rule */
+ if (unlikely(border_index != -1))
+ {
+ if (border_index != (int)edge_valence-2 ) {
+ return ring[0] - vtx;
+ }
+ else
+ {
+ const unsigned int second_border_index = border_index+2 >= int(edge_valence) ? 0 : border_index+2;
+ return (ring[second_border_index] - ring[border_index]) * 0.5f;
+ }
+ }
+
+ Vertex_t alpha( 0.0f );
+ Vertex_t beta ( 0.0f );
+
+ const size_t n = face_valence;
+
+ assert(eval_start_index < face_valence);
+
+ Vertex_t q( 0.0f );
+ for (size_t i=0; i<face_valence; i++)
+ {
+ size_t index = i+eval_start_index;
+ if (index >= face_valence) index -= face_valence;
+ const float a = CatmullClarkPrecomputedCoefficients::table.limittangent_a(index,n);
+ const float b = CatmullClarkPrecomputedCoefficients::table.limittangent_b(index,n);
+ alpha += a * ring[2*index];
+ beta += b * ring[2*index+1];
+ }
+
+ const float sigma = CatmullClarkPrecomputedCoefficients::table.limittangent_c(n);
+ return sigma * (alpha + beta);
+ }
+
+ /* gets limit tangent in the direction of egde vtx -> ring[edge_valence-2] */
+ __forceinline Vertex getSecondLimitTangent() const
+ {
+ if (unlikely(std::isinf(vertex_crease_weight)))
+ return ring[2] - vtx;
+
+ /* border vertex rule */
+ if (unlikely(border_index != -1))
+ {
+ if (border_index != 2) {
+ return ring[2] - vtx;
+ }
+ else {
+ const unsigned int second_border_index = border_index+2 >= int(edge_valence) ? 0 : border_index+2;
+ return (ring[border_index] - ring[second_border_index]) * 0.5f;
+ }
+ }
+
+ Vertex_t alpha( 0.0f );
+ Vertex_t beta ( 0.0f );
+
+ const size_t n = face_valence;
+
+ assert(eval_start_index < face_valence);
+
+ for (size_t i=0; i<face_valence; i++)
+ {
+ size_t index = i+eval_start_index;
+ if (index >= face_valence) index -= face_valence;
+
+ size_t prev_index = index == 0 ? face_valence-1 : index-1; // need to be bit-wise exact in cosf eval
+ const float a = CatmullClarkPrecomputedCoefficients::table.limittangent_a(prev_index,n);
+ const float b = CatmullClarkPrecomputedCoefficients::table.limittangent_b(prev_index,n);
+ alpha += a * ring[2*index];
+ beta += b * ring[2*index+1];
+ }
+
+ const float sigma = CatmullClarkPrecomputedCoefficients::table.limittangent_c(n);
+ return sigma* (alpha + beta);
+ }
+
+ /* gets surface normal */
+ const Vertex getNormal() const {
+ return cross(getLimitTangent(),getSecondLimitTangent());
+ }
+
+ /* returns center of the n-th quad in the 1-ring */
+ __forceinline Vertex getQuadCenter(const size_t index) const
+ {
+ const Vertex_t &p0 = vtx;
+ const Vertex_t &p1 = ring[2*index+0];
+ const Vertex_t &p2 = ring[2*index+1];
+ const Vertex_t &p3 = index == face_valence-1 ? ring[0] : ring[2*index+2];
+ const Vertex p = (p0+p1+p2+p3) * 0.25f;
+ return p;
+ }
+
+ /* returns center of the n-th edge in the 1-ring */
+ __forceinline Vertex getEdgeCenter(const size_t index) const {
+ return (vtx + ring[index*2]) * 0.5f;
+ }
+
+ bool hasValidPositions() const
+ {
+ for (size_t i=0; i<edge_valence; i++) {
+ if (!isvalid(ring[i]))
+ return false;
+ }
+ return true;
+ }
+
+ friend __forceinline embree_ostream operator<<(embree_ostream o, const CatmullClark1RingT &c)
+ {
+ o << "vtx " << c.vtx << " size = " << c.edge_valence << ", " <<
+ "hard_edge = " << c.border_index << ", face_valence " << c.face_valence <<
+ ", edge_level = " << c.edge_level << ", vertex_level = " << c.vertex_level << ", eval_start_index: " << c.eval_start_index << ", ring: " << embree_endl;
+
+ for (unsigned int i=0; i<min(c.edge_valence,(unsigned int)MAX_RING_FACE_VALENCE); i++) {
+ o << i << " -> " << c.ring[i];
+ if (i % 2 == 0) o << " crease = " << c.crease_weight[i/2];
+ o << embree_endl;
+ }
+ return o;
+ }
+ };
+
+ typedef CatmullClark1RingT<Vec3fa,Vec3fa_t> CatmullClark1Ring3fa;
+
+ template<typename Vertex, typename Vertex_t = Vertex>
+ struct __aligned(64) GeneralCatmullClark1RingT
+ {
+ ALIGNED_STRUCT_(64);
+
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
+
+ struct Face
+ {
+ __forceinline Face() {}
+ __forceinline Face (int size, float crease_weight)
+ : size(size), crease_weight(crease_weight) {}
+
+ // FIXME: add member that returns total number of vertices
+
+ int size; // number of vertices-2 of nth face in ring
+ float crease_weight;
+ };
+
+ Vertex vtx;
+ DynamicStackArray<Vertex,32,MAX_RING_EDGE_VALENCE> ring;
+ DynamicStackArray<Face,16,MAX_RING_FACE_VALENCE> faces;
+ unsigned int face_valence;
+ unsigned int edge_valence;
+ int border_face;
+ float vertex_crease_weight;
+ float vertex_level; //!< maximum level of adjacent edges
+ float edge_level; // level of first edge
+ bool only_quads; // true if all faces are quads
+ unsigned int eval_start_face_index;
+ unsigned int eval_start_vertex_index;
+ unsigned int eval_unique_identifier;
+
+ public:
+ GeneralCatmullClark1RingT()
+ : eval_start_face_index(0), eval_start_vertex_index(0), eval_unique_identifier(0) {}
+
+ __forceinline bool isRegular() const
+ {
+ if (border_face == -1 && face_valence == 4) return true;
+ return false;
+ }
+
+ __forceinline bool has_last_face() const {
+ return border_face != (int)face_valence-1;
+ }
+
+ __forceinline bool has_second_face() const {
+ return (border_face == -1) || (border_face >= 2);
+ }
+
+ bool hasValidPositions() const
+ {
+ for (size_t i=0; i<edge_valence; i++) {
+ if (!isvalid(ring[i]))
+ return false;
+ }
+ return true;
+ }
+
+ __forceinline void init(const HalfEdge* const h, const char* vertices, size_t stride)
+ {
+ only_quads = true;
+ border_face = -1;
+ vtx = Vertex_t::loadu(vertices+h->getStartVertexIndex()*stride);
+ vertex_crease_weight = h->vertex_crease_weight;
+ HalfEdge* p = (HalfEdge*) h;
+
+ unsigned int e=0, f=0;
+ unsigned min_vertex_index = (unsigned)-1;
+ unsigned min_vertex_index_face = (unsigned)-1;
+ unsigned min_vertex_index_vertex = (unsigned)-1;
+ edge_level = p->edge_level;
+ vertex_level = 0.0f;
+ do
+ {
+ HalfEdge* p_prev = p->prev();
+ HalfEdge* p_next = p->next();
+ const float crease_weight = p->edge_crease_weight;
+ assert(p->hasOpposite() || p->edge_crease_weight == float(inf));
+ vertex_level = max(vertex_level,p->edge_level);
+
+ /* find minimum start vertex */
+ unsigned vertex_index = p_next->getStartVertexIndex();
+ if (vertex_index < min_vertex_index) { min_vertex_index = vertex_index; min_vertex_index_face = f; min_vertex_index_vertex = e; }
+
+ /* store first N-2 vertices of face */
+ unsigned int vn = 0;
+ for (p = p_next; p!=p_prev; p=p->next()) {
+ ring[e++] = Vertex_t::loadu(vertices+p->getStartVertexIndex()*stride);
+ vn++;
+ }
+ faces[f++] = Face(vn,crease_weight);
+ only_quads &= (vn == 2);
+
+ /* continue with next face */
+ if (likely(p->hasOpposite()))
+ p = p->opposite();
+
+ /* if there is no opposite go the long way to the other side of the border */
+ else
+ {
+ /* find minimum start vertex */
+ unsigned vertex_index = p->getStartVertexIndex();
+ if (vertex_index < min_vertex_index) { min_vertex_index = vertex_index; min_vertex_index_face = f; min_vertex_index_vertex = e; }
+
+ /*! mark first border edge and store dummy vertex for face between the two border edges */
+ border_face = f;
+ faces[f++] = Face(2,inf);
+ ring[e++] = Vertex_t::loadu(vertices+p->getStartVertexIndex()*stride);
+ ring[e++] = vtx; // dummy vertex
+
+ /*! goto other side of border */
+ p = (HalfEdge*) h;
+ while (p->hasOpposite())
+ p = p->opposite()->next();
+ }
+
+ } while (p != h);
+
+ edge_valence = e;
+ face_valence = f;
+ eval_unique_identifier = min_vertex_index;
+ eval_start_face_index = min_vertex_index_face;
+ eval_start_vertex_index = min_vertex_index_vertex;
+
+ assert( hasValidPositions() );
+ }
+
+ __forceinline void subdivide(CatmullClark1Ring& dest) const
+ {
+ dest.edge_level = 0.5f*edge_level;
+ dest.vertex_level = 0.5f*vertex_level;
+ dest.face_valence = face_valence;
+ dest.edge_valence = 2*face_valence;
+ dest.border_index = border_face == -1 ? -1 : 2*border_face; // FIXME:
+ dest.vertex_crease_weight = max(0.0f,vertex_crease_weight-1.0f);
+ dest.eval_start_index = eval_start_face_index;
+ dest.eval_unique_identifier = eval_unique_identifier;
+ assert(dest.face_valence <= MAX_RING_FACE_VALENCE);
+
+ /* calculate face points */
+ Vertex_t S = Vertex_t(0.0f);
+ for (size_t face=0, v=eval_start_vertex_index; face<face_valence; face++) {
+ size_t f = (face + eval_start_face_index)%face_valence;
+
+ Vertex_t F = vtx;
+ for (size_t k=v; k<=v+faces[f].size; k++) F += ring[k%edge_valence]; // FIXME: optimize
+ S += dest.ring[2*f+1] = F/float(faces[f].size+2);
+ v+=faces[f].size;
+ v%=edge_valence;
+ }
+
+ /* calculate new edge points */
+ size_t num_creases = 0;
+ array_t<size_t,MAX_RING_FACE_VALENCE> crease_id;
+ Vertex_t C = Vertex_t(0.0f);
+ for (size_t face=0, j=eval_start_vertex_index; face<face_valence; face++)
+ {
+ size_t i = (face + eval_start_face_index)%face_valence;
+
+ const Vertex_t v = vtx + ring[j];
+ Vertex_t f = dest.ring[2*i+1];
+ if (i == 0) f += dest.ring[dest.edge_valence-1];
+ else f += dest.ring[2*i-1];
+ S += ring[j];
+ dest.crease_weight[i] = max(faces[i].crease_weight-1.0f,0.0f);
+
+ /* fast path for regular edge points */
+ if (likely(faces[i].crease_weight <= 0.0f)) {
+ dest.ring[2*i] = (v+f) * 0.25f;
+ }
+
+ /* slower path for hard edge rule */
+ else {
+ C += ring[j]; crease_id[num_creases++] = i;
+ dest.ring[2*i] = v*0.5f;
+
+ /* even slower path for blended edge rule */
+ if (unlikely(faces[i].crease_weight < 1.0f)) {
+ dest.ring[2*i] = lerp((v+f)*0.25f,v*0.5f,faces[i].crease_weight);
+ }
+ }
+ j+=faces[i].size;
+ j%=edge_valence;
+ }
+
+ /* compute new vertex using smooth rule */
+ const float inv_face_valence = 1.0f / (float)face_valence;
+ const Vertex_t v_smooth = (Vertex_t) madd(inv_face_valence,S,(float(face_valence)-2.0f)*vtx)*inv_face_valence;
+ dest.vtx = v_smooth;
+
+ /* compute new vertex using vertex_crease_weight rule */
+ if (unlikely(vertex_crease_weight > 0.0f))
+ {
+ if (vertex_crease_weight >= 1.0f) {
+ dest.vtx = vtx;
+ } else {
+ dest.vtx = lerp(vtx,v_smooth,vertex_crease_weight);
+ }
+ return;
+ }
+
+ if (likely(num_creases <= 1))
+ return;
+
+ /* compute new vertex using crease rule */
+ if (likely(num_creases == 2)) {
+ const Vertex_t v_sharp = (Vertex_t)(C + 6.0f * vtx) * (1.0f / 8.0f);
+ const float crease_weight0 = faces[crease_id[0]].crease_weight;
+ const float crease_weight1 = faces[crease_id[1]].crease_weight;
+ dest.vtx = v_sharp;
+ dest.crease_weight[crease_id[0]] = max(0.25f*(3.0f*crease_weight0 + crease_weight1)-1.0f,0.0f);
+ dest.crease_weight[crease_id[1]] = max(0.25f*(3.0f*crease_weight1 + crease_weight0)-1.0f,0.0f);
+ const float v_blend = 0.5f*(crease_weight0+crease_weight1);
+ if (unlikely(v_blend < 1.0f)) {
+ dest.vtx = lerp(v_sharp,v_smooth,v_blend);
+ }
+ }
+
+ /* compute new vertex using corner rule */
+ else {
+ dest.vtx = vtx;
+ }
+ }
+
+ void convert(CatmullClark1Ring& dst) const
+ {
+ dst.edge_level = edge_level;
+ dst.vertex_level = vertex_level;
+ dst.vtx = vtx;
+ dst.face_valence = face_valence;
+ dst.edge_valence = 2*face_valence;
+ dst.border_index = border_face == -1 ? -1 : 2*border_face;
+ for (size_t i=0; i<face_valence; i++)
+ dst.crease_weight[i] = faces[i].crease_weight;
+ dst.vertex_crease_weight = vertex_crease_weight;
+ for (size_t i=0; i<edge_valence; i++) dst.ring[i] = ring[i];
+
+ dst.eval_start_index = eval_start_face_index;
+ dst.eval_unique_identifier = eval_unique_identifier;
+
+ assert( dst.hasValidPositions() );
+ }
+
+
+ /* gets limit tangent in the direction of egde vtx -> ring[0] */
+ __forceinline Vertex getLimitTangent() const
+ {
+ CatmullClark1Ring cc_vtx;
+
+ /* fast path for quad only rings */
+ if (only_quads)
+ {
+ convert(cc_vtx);
+ return cc_vtx.getLimitTangent();
+ }
+
+ subdivide(cc_vtx);
+ return 2.0f * cc_vtx.getLimitTangent();
+ }
+
+ /* gets limit tangent in the direction of egde vtx -> ring[edge_valence-2] */
+ __forceinline Vertex getSecondLimitTangent() const
+ {
+ CatmullClark1Ring cc_vtx;
+
+ /* fast path for quad only rings */
+ if (only_quads)
+ {
+ convert(cc_vtx);
+ return cc_vtx.getSecondLimitTangent();
+ }
+
+ subdivide(cc_vtx);
+ return 2.0f * cc_vtx.getSecondLimitTangent();
+ }
+
+
+ /* gets limit vertex */
+ __forceinline Vertex getLimitVertex() const
+ {
+ CatmullClark1Ring cc_vtx;
+
+ /* fast path for quad only rings */
+ if (only_quads)
+ convert(cc_vtx);
+ else
+ subdivide(cc_vtx);
+ return cc_vtx.getLimitVertex();
+ }
+
+ friend __forceinline embree_ostream operator<<(embree_ostream o, const GeneralCatmullClark1RingT &c)
+ {
+ o << "vtx " << c.vtx << " size = " << c.edge_valence << ", border_face = " << c.border_face << ", " << " face_valence = " << c.face_valence <<
+ ", edge_level = " << c.edge_level << ", vertex_level = " << c.vertex_level << ", ring: " << embree_endl;
+ for (size_t v=0, f=0; f<c.face_valence; v+=c.faces[f++].size) {
+ for (size_t i=v; i<v+c.faces[f].size; i++) {
+ o << i << " -> " << c.ring[i];
+ if (i == v) o << " crease = " << c.faces[f].crease_weight;
+ o << embree_endl;
+ }
+ }
+ return o;
+ }
+ };
+}
diff --git a/thirdparty/embree/kernels/subdiv/catmullrom_curve.h b/thirdparty/embree/kernels/subdiv/catmullrom_curve.h
new file mode 100644
index 0000000000..74fc4c1230
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/catmullrom_curve.h
@@ -0,0 +1,297 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+#include "../common/scene_curves.h"
+
+/*
+
+ Implements Catmul Rom curves with control points p0, p1, p2, p3. At
+ t=0 the curve goes through p1, with tangent (p2-p0)/3, and for t=1
+ the curve goes through p2 with tangent (p3-p2)/2.
+
+ */
+
+namespace embree
+{
+ class CatmullRomBasis
+ {
+ public:
+
+ template<typename T>
+ static __forceinline Vec4<T> eval(const T& u)
+ {
+ const T t = u;
+ const T s = T(1.0f) - u;
+ const T n0 = - t * s * s;
+ const T n1 = 2.0f + t * t * (3.0f * t - 5.0f);
+ const T n2 = 2.0f + s * s * (3.0f * s - 5.0f);
+ const T n3 = - s * t * t;
+ return T(0.5f) * Vec4<T>(n0, n1, n2, n3);
+ }
+
+ template<typename T>
+ static __forceinline Vec4<T> derivative(const T& u)
+ {
+ const T t = u;
+ const T s = 1.0f - u;
+ const T n0 = - s * s + 2.0f * s * t;
+ const T n1 = 2.0f * t * (3.0f * t - 5.0f) + 3.0f * t * t;
+ const T n2 = 2.0f * s * (3.0f * t + 2.0f) - 3.0f * s * s;
+ const T n3 = -2.0f * s * t + t * t;
+ return T(0.5f) * Vec4<T>(n0, n1, n2, n3);
+ }
+
+ template<typename T>
+ static __forceinline Vec4<T> derivative2(const T& u)
+ {
+ const T t = u;
+ const T n0 = -3.0f * t + 2.0f;
+ const T n1 = 9.0f * t - 5.0f;
+ const T n2 = -9.0f * t + 4.0f;
+ const T n3 = 3.0f * t - 1.0f;
+ return Vec4<T>(n0, n1, n2, n3);
+ }
+ };
+
+ struct PrecomputedCatmullRomBasis
+ {
+ enum { N = 16 };
+ public:
+ PrecomputedCatmullRomBasis() {}
+ PrecomputedCatmullRomBasis(int shift);
+
+ /* basis for bspline evaluation */
+ public:
+ float c0[N+1][N+1];
+ float c1[N+1][N+1];
+ float c2[N+1][N+1];
+ float c3[N+1][N+1];
+
+ /* basis for bspline derivative evaluation */
+ public:
+ float d0[N+1][N+1];
+ float d1[N+1][N+1];
+ float d2[N+1][N+1];
+ float d3[N+1][N+1];
+ };
+ extern PrecomputedCatmullRomBasis catmullrom_basis0;
+ extern PrecomputedCatmullRomBasis catmullrom_basis1;
+
+ template<typename Vertex>
+ struct CatmullRomCurveT
+ {
+ Vertex v0,v1,v2,v3;
+
+ __forceinline CatmullRomCurveT() {}
+
+ __forceinline CatmullRomCurveT(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3)
+ : v0(v0), v1(v1), v2(v2), v3(v3) {}
+
+ __forceinline Vertex begin() const {
+ return madd(1.0f/6.0f,v0,madd(2.0f/3.0f,v1,1.0f/6.0f*v2));
+ }
+
+ __forceinline Vertex end() const {
+ return madd(1.0f/6.0f,v1,madd(2.0f/3.0f,v2,1.0f/6.0f*v3));
+ }
+
+ __forceinline Vertex center() const {
+ return 0.25f*(v0+v1+v2+v3);
+ }
+
+ __forceinline BBox<Vertex> bounds() const {
+ return merge(BBox<Vertex>(v0),BBox<Vertex>(v1),BBox<Vertex>(v2),BBox<Vertex>(v3));
+ }
+
+ __forceinline friend CatmullRomCurveT operator -( const CatmullRomCurveT& a, const Vertex& b ) {
+ return CatmullRomCurveT(a.v0-b,a.v1-b,a.v2-b,a.v3-b);
+ }
+
+ __forceinline CatmullRomCurveT<Vec3ff> xfm_pr(const LinearSpace3fa& space, const Vec3fa& p) const
+ {
+ const Vec3ff q0(xfmVector(space,v0-p), v0.w);
+ const Vec3ff q1(xfmVector(space,v1-p), v1.w);
+ const Vec3ff q2(xfmVector(space,v2-p), v2.w);
+ const Vec3ff q3(xfmVector(space,v3-p), v3.w);
+ return CatmullRomCurveT<Vec3ff>(q0,q1,q2,q3);
+ }
+
+ __forceinline Vertex eval(const float t) const
+ {
+ const Vec4<float> b = CatmullRomBasis::eval(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+
+ __forceinline Vertex eval_du(const float t) const
+ {
+ const Vec4<float> b = CatmullRomBasis::derivative(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+
+ __forceinline Vertex eval_dudu(const float t) const
+ {
+ const Vec4<float> b = CatmullRomBasis::derivative2(t);
+ return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
+ }
+
+ __forceinline void eval(const float t, Vertex& p, Vertex& dp, Vertex& ddp) const
+ {
+ p = eval(t);
+ dp = eval_du(t);
+ ddp = eval_dudu(t);
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = CatmullRomBasis::eval(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval_du(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = CatmullRomBasis::derivative(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> veval_dudu(const vfloat<M>& t) const
+ {
+ const Vec4vf<M> b = CatmullRomBasis::derivative2(t);
+ return madd(b.x, Vec4vf<M>(v0), madd(b.y, Vec4vf<M>(v1), madd(b.z, Vec4vf<M>(v2), b.w * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline void veval(const vfloat<M>& t, Vec4vf<M>& p, Vec4vf<M>& dp) const
+ {
+ p = veval<M>(t);
+ dp = veval_du<M>(t);
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> eval0(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedCatmullRomBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&catmullrom_basis0.c0[size][ofs]), Vec4vf<M>(v0),
+ madd(vfloat<M>::loadu(&catmullrom_basis0.c1[size][ofs]), Vec4vf<M>(v1),
+ madd(vfloat<M>::loadu(&catmullrom_basis0.c2[size][ofs]), Vec4vf<M>(v2),
+ vfloat<M>::loadu(&catmullrom_basis0.c3[size][ofs]) * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> eval1(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedCatmullRomBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&catmullrom_basis1.c0[size][ofs]), Vec4vf<M>(v0),
+ madd(vfloat<M>::loadu(&catmullrom_basis1.c1[size][ofs]), Vec4vf<M>(v1),
+ madd(vfloat<M>::loadu(&catmullrom_basis1.c2[size][ofs]), Vec4vf<M>(v2),
+ vfloat<M>::loadu(&catmullrom_basis1.c3[size][ofs]) * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> derivative0(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedCatmullRomBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&catmullrom_basis0.d0[size][ofs]), Vec4vf<M>(v0),
+ madd(vfloat<M>::loadu(&catmullrom_basis0.d1[size][ofs]), Vec4vf<M>(v1),
+ madd(vfloat<M>::loadu(&catmullrom_basis0.d2[size][ofs]), Vec4vf<M>(v2),
+ vfloat<M>::loadu(&catmullrom_basis0.d3[size][ofs]) * Vec4vf<M>(v3))));
+ }
+
+ template<int M>
+ __forceinline Vec4vf<M> derivative1(const int ofs, const int size) const
+ {
+ assert(size <= PrecomputedCatmullRomBasis::N);
+ assert(ofs <= size);
+ return madd(vfloat<M>::loadu(&catmullrom_basis1.d0[size][ofs]), Vec4vf<M>(v0),
+ madd(vfloat<M>::loadu(&catmullrom_basis1.d1[size][ofs]), Vec4vf<M>(v1),
+ madd(vfloat<M>::loadu(&catmullrom_basis1.d2[size][ofs]), Vec4vf<M>(v2),
+ vfloat<M>::loadu(&catmullrom_basis1.d3[size][ofs]) * Vec4vf<M>(v3))));
+ }
+
+ /* calculates bounds of catmull-rom curve geometry */
+ __forceinline BBox3fa accurateRoundBounds() const
+ {
+ const int N = 7;
+ const float scale = 1.0f/(3.0f*(N-1));
+ Vec4vfx pl(pos_inf), pu(neg_inf);
+ for (int i=0; i<=N; i+=VSIZEX)
+ {
+ vintx vi = vintx(i)+vintx(step);
+ vboolx valid = vi <= vintx(N);
+ const Vec4vfx p = eval0<VSIZEX>(i,N);
+ const Vec4vfx dp = derivative0<VSIZEX>(i,N);
+ const Vec4vfx pm = p-Vec4vfx(scale)*select(vi!=vintx(0),dp,Vec4vfx(zero));
+ const Vec4vfx pp = p+Vec4vfx(scale)*select(vi!=vintx(N),dp,Vec4vfx(zero));
+ pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
+ pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
+ }
+ const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
+ const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
+ const float r_min = reduce_min(pl.w);
+ const float r_max = reduce_max(pu.w);
+ const Vec3fa upper_r = Vec3fa(max(abs(r_min),abs(r_max)));
+ return enlarge(BBox3fa(lower,upper),upper_r);
+ }
+
+ /* calculates bounds when tessellated into N line segments */
+ __forceinline BBox3fa accurateFlatBounds(int N) const
+ {
+ if (likely(N == 4))
+ {
+ const Vec4vf4 pi = eval0<4>(0,4);
+ const Vec3fa lower(reduce_min(pi.x),reduce_min(pi.y),reduce_min(pi.z));
+ const Vec3fa upper(reduce_max(pi.x),reduce_max(pi.y),reduce_max(pi.z));
+ const Vec3fa upper_r = Vec3fa(reduce_max(abs(pi.w)));
+ const Vec3ff pe = end();
+ return enlarge(BBox3fa(min(lower,pe),max(upper,pe)),max(upper_r,Vec3fa(abs(pe.w))));
+ }
+ else
+ {
+ Vec3vfx pl(pos_inf), pu(neg_inf); vfloatx ru(0.0f);
+ for (int i=0; i<=N; i+=VSIZEX)
+ {
+ vboolx valid = vintx(i)+vintx(step) <= vintx(N);
+ const Vec4vfx pi = eval0<VSIZEX>(i,N);
+
+ pl.x = select(valid,min(pl.x,pi.x),pl.x); // FIXME: use masked min
+ pl.y = select(valid,min(pl.y,pi.y),pl.y);
+ pl.z = select(valid,min(pl.z,pi.z),pl.z);
+
+ pu.x = select(valid,max(pu.x,pi.x),pu.x); // FIXME: use masked min
+ pu.y = select(valid,max(pu.y,pi.y),pu.y);
+ pu.z = select(valid,max(pu.z,pi.z),pu.z);
+
+ ru = select(valid,max(ru,abs(pi.w)),ru);
+ }
+ const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
+ const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
+ const Vec3fa upper_r(reduce_max(ru));
+ return enlarge(BBox3fa(lower,upper),upper_r);
+ }
+ }
+
+ friend __forceinline embree_ostream operator<<(embree_ostream cout, const CatmullRomCurveT& curve) {
+ return cout << "CatmullRomCurve { v0 = " << curve.v0 << ", v1 = " << curve.v1 << ", v2 = " << curve.v2 << ", v3 = " << curve.v3 << " }";
+ }
+ };
+
+ template<typename CurveGeometry>
+ __forceinline CatmullRomCurveT<Vec3ff> enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const CatmullRomCurveT<Vec3ff>& curve)
+ {
+ return CatmullRomCurveT<Vec3ff>(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v1),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v2),
+ enlargeRadiusToMinWidth(context,geom,ray_org,curve.v3));
+ }
+
+ typedef CatmullRomCurveT<Vec3fa> CatmullRomCurve3fa;
+}
+
diff --git a/thirdparty/embree/kernels/subdiv/feature_adaptive_eval.h b/thirdparty/embree/kernels/subdiv/feature_adaptive_eval.h
new file mode 100644
index 0000000000..58c0b63e62
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/feature_adaptive_eval.h
@@ -0,0 +1,226 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "patch.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename Vertex, typename Vertex_t = Vertex>
+ struct FeatureAdaptiveEval
+ {
+ public:
+
+ typedef PatchT<Vertex,Vertex_t> Patch;
+ typedef typename Patch::Ref Ref;
+ typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+ typedef BSplinePatchT<Vertex,Vertex_t> BSplinePatch;
+ typedef BezierPatchT<Vertex,Vertex_t> BezierPatch;
+ typedef GregoryPatchT<Vertex,Vertex_t> GregoryPatch;
+ typedef BilinearPatchT<Vertex,Vertex_t> BilinearPatch;
+ typedef BezierCurveT<Vertex> BezierCurve;
+
+ public:
+
+ FeatureAdaptiveEval (const HalfEdge* edge, const char* vertices, size_t stride, const float u, const float v,
+ Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv)
+ : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv)
+ {
+ switch (edge->patch_type) {
+ case HalfEdge::BILINEAR_PATCH: BilinearPatch(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;
+ case HalfEdge::REGULAR_QUAD_PATCH: RegularPatchT(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;
+#if PATCH_USE_GREGORY == 2
+ case HalfEdge::IRREGULAR_QUAD_PATCH: GregoryPatch(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;
+#endif
+ default: {
+ GeneralCatmullClarkPatch patch(edge,vertices,stride);
+ eval(patch,Vec2f(u,v),0);
+ break;
+ }
+ }
+ }
+
+ FeatureAdaptiveEval (CatmullClarkPatch& patch, const float u, const float v, float dscale, size_t depth,
+ Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv)
+ : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv)
+ {
+ eval(patch,Vec2f(u,v),dscale,depth);
+ }
+
+ void eval_general_quad(const GeneralCatmullClarkPatch& patch, array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE>& patches, const Vec2f& uv, size_t depth)
+ {
+ float u = uv.x, v = uv.y;
+ if (v < 0.5f) {
+ if (u < 0.5f) {
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[2]; patch.getLimitBorder(borders,0);
+ BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
+ eval(patches[0],Vec2f(2.0f*u,2.0f*v),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
+#else
+ eval(patches[0],Vec2f(2.0f*u,2.0f*v),2.0f,depth+1);
+#endif
+ if (dPdu && dPdv) {
+ const Vertex dpdx = *dPdu, dpdy = *dPdv;
+ *dPdu = dpdx; *dPdv = dpdy;
+ }
+ }
+ else {
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[2]; patch.getLimitBorder(borders,1);
+ BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
+ eval(patches[1],Vec2f(2.0f*v,2.0f-2.0f*u),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
+#else
+ eval(patches[1],Vec2f(2.0f*v,2.0f-2.0f*u),2.0f,depth+1);
+#endif
+ if (dPdu && dPdv) {
+ const Vertex dpdx = *dPdu, dpdy = *dPdv;
+ *dPdu = -dpdy; *dPdv = dpdx;
+ }
+ }
+ } else {
+ if (u > 0.5f) {
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[2]; patch.getLimitBorder(borders,2);
+ BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
+ eval(patches[2],Vec2f(2.0f-2.0f*u,2.0f-2.0f*v),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
+#else
+ eval(patches[2],Vec2f(2.0f-2.0f*u,2.0f-2.0f*v),2.0f,depth+1);
+#endif
+ if (dPdu && dPdv) {
+ const Vertex dpdx = *dPdu, dpdy = *dPdv;
+ *dPdu = -dpdx; *dPdv = -dpdy;
+ }
+ }
+ else {
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[2]; patch.getLimitBorder(borders,3);
+ BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
+ eval(patches[3],Vec2f(2.0f-2.0f*v,2.0f*u),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
+#else
+ eval(patches[3],Vec2f(2.0f-2.0f*v,2.0f*u),2.0f,depth+1);
+#endif
+ if (dPdu && dPdv) {
+ const Vertex dpdx = *dPdu, dpdy = *dPdv;
+ *dPdu = dpdy; *dPdv = -dpdx;
+ }
+ }
+ }
+ }
+
+ __forceinline bool final(const CatmullClarkPatch& patch, const typename CatmullClarkRing::Type type, size_t depth)
+ {
+ const int max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
+//#if PATCH_MIN_RESOLUTION
+// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=(size_t)max_eval_depth;
+//#else
+ return depth>=(size_t)max_eval_depth;
+//#endif
+ }
+
+ void eval(CatmullClarkPatch& patch, Vec2f uv, float dscale, size_t depth,
+ BezierCurve* border0 = nullptr, BezierCurve* border1 = nullptr, BezierCurve* border2 = nullptr, BezierCurve* border3 = nullptr)
+ {
+ while (true)
+ {
+ typename CatmullClarkPatch::Type ty = patch.type();
+
+ if (unlikely(final(patch,ty,depth)))
+ {
+ if (ty & CatmullClarkRing::TYPE_REGULAR) {
+ RegularPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
+ PATCH_DEBUG_SUBDIVISION(234423,c,c,-1);
+ return;
+ } else {
+ IrregularFillPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
+ PATCH_DEBUG_SUBDIVISION(34534,c,-1,c);
+ return;
+ }
+ }
+ else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
+ assert(depth > 0);
+ RegularPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
+ PATCH_DEBUG_SUBDIVISION(43524,c,c,-1);
+ return;
+ }
+#if PATCH_USE_GREGORY == 2
+ else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
+ assert(depth > 0);
+ GregoryPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
+ PATCH_DEBUG_SUBDIVISION(23498,c,-1,c);
+ return;
+ }
+#endif
+ else
+ {
+ array_t<CatmullClarkPatch,4> patches;
+ patch.subdivide(patches); // FIXME: only have to generate one of the patches
+
+ const float u = uv.x, v = uv.y;
+ if (v < 0.5f) {
+ if (u < 0.5f) { patch = patches[0]; uv = Vec2f(2.0f*u,2.0f*v); dscale *= 2.0f; }
+ else { patch = patches[1]; uv = Vec2f(2.0f*u-1.0f,2.0f*v); dscale *= 2.0f; }
+ } else {
+ if (u > 0.5f) { patch = patches[2]; uv = Vec2f(2.0f*u-1.0f,2.0f*v-1.0f); dscale *= 2.0f; }
+ else { patch = patches[3]; uv = Vec2f(2.0f*u,2.0f*v-1.0f); dscale *= 2.0f; }
+ }
+ depth++;
+ }
+ }
+ }
+
+ void eval(const GeneralCatmullClarkPatch& patch, const Vec2f& uv, const size_t depth)
+ {
+ /* convert into standard quad patch if possible */
+ if (likely(patch.isQuadPatch()))
+ {
+ CatmullClarkPatch qpatch; patch.init(qpatch);
+ return eval(qpatch,uv,1.0f,depth);
+ }
+
+ /* subdivide patch */
+ unsigned N;
+ array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches;
+ patch.subdivide(patches,N); // FIXME: only have to generate one of the patches
+
+ /* parametrization for quads */
+ if (N == 4)
+ eval_general_quad(patch,patches,uv,depth);
+
+ /* parametrization for arbitrary polygons */
+ else
+ {
+ const unsigned l = (unsigned) floor(0.5f*uv.x); const float u = 2.0f*frac(0.5f*uv.x)-0.5f;
+ const unsigned h = (unsigned) floor(0.5f*uv.y); const float v = 2.0f*frac(0.5f*uv.y)-0.5f;
+ const unsigned i = 4*h+l; assert(i<N);
+ if (i >= N) return;
+
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[2]; patch.getLimitBorder(borders,i);
+ BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
+ eval(patches[i],Vec2f(u,v),1.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
+#else
+ eval(patches[i],Vec2f(u,v),1.0f,depth+1);
+#endif
+ }
+ }
+
+ private:
+ Vertex* const P;
+ Vertex* const dPdu;
+ Vertex* const dPdv;
+ Vertex* const ddPdudu;
+ Vertex* const ddPdvdv;
+ Vertex* const ddPdudv;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/subdiv/feature_adaptive_eval_grid.h b/thirdparty/embree/kernels/subdiv/feature_adaptive_eval_grid.h
new file mode 100644
index 0000000000..4755aba28d
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/feature_adaptive_eval_grid.h
@@ -0,0 +1,359 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "patch.h"
+#include "catmullclark_patch.h"
+#include "bspline_patch.h"
+#include "gregory_patch.h"
+#include "tessellation.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct FeatureAdaptiveEvalGrid
+ {
+ typedef CatmullClark1Ring3fa CatmullClarkRing;
+ typedef CatmullClarkPatch3fa CatmullClarkPatch;
+ typedef BilinearPatch3fa BilinearPatch;
+ typedef BSplinePatch3fa BSplinePatch;
+ typedef BezierPatch3fa BezierPatch;
+ typedef GregoryPatch3fa GregoryPatch;
+
+ private:
+ const unsigned x0,x1;
+ const unsigned y0,y1;
+ const unsigned swidth,sheight;
+ const float rcp_swidth, rcp_sheight;
+ float* const Px;
+ float* const Py;
+ float* const Pz;
+ float* const U;
+ float* const V;
+ float* const Nx;
+ float* const Ny;
+ float* const Nz;
+ const unsigned dwidth;
+ //const unsigned dheight;
+ unsigned count;
+
+
+ public:
+ FeatureAdaptiveEvalGrid (const GeneralCatmullClarkPatch3fa& patch, unsigned subPatch,
+ const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
+ float* Px, float* Py, float* Pz, float* U, float* V,
+ float* Nx, float* Ny, float* Nz,
+ const unsigned dwidth, const unsigned dheight)
+ : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
+ Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), /*dheight(dheight),*/ count(0)
+ {
+ assert(swidth < (2<<20) && sheight < (2<<20));
+ const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(float(swidth-1),float(sheight-1)));
+ const BBox2f erange(Vec2f((float)x0,(float)y0),Vec2f((float)x1,(float)y1));
+
+ /* convert into standard quad patch if possible */
+ if (likely(patch.isQuadPatch()))
+ {
+ CatmullClarkPatch3fa qpatch; patch.init(qpatch);
+ eval(qpatch, srange, erange, 0);
+ assert(count == (x1-x0+1)*(y1-y0+1));
+ return;
+ }
+
+ /* subdivide patch */
+ unsigned N;
+ array_t<CatmullClarkPatch3fa,GeneralCatmullClarkPatch3fa::SIZE> patches;
+ patch.subdivide(patches,N);
+
+ if (N == 4)
+ {
+ const Vec2f c = srange.center();
+ const BBox2f srange0(srange.lower,c);
+ const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
+ const BBox2f srange2(c,srange.upper);
+ const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
+
+#if PATCH_USE_GREGORY == 2
+ BezierCurve3fa borders[GeneralCatmullClarkPatch3fa::SIZE]; patch.getLimitBorder(borders);
+ BezierCurve3fa border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve3fa border1l,border1r; borders[1].subdivide(border1l,border1r);
+ BezierCurve3fa border2l,border2r; borders[2].subdivide(border2l,border2r);
+ BezierCurve3fa border3l,border3r; borders[3].subdivide(border3l,border3r);
+ GeneralCatmullClarkPatch3fa::fix_quad_ring_order(patches);
+ eval(patches[0],srange0,intersect(srange0,erange),1,&border0l,nullptr,nullptr,&border3r);
+ eval(patches[1],srange1,intersect(srange1,erange),1,&border0r,&border1l,nullptr,nullptr);
+ eval(patches[2],srange2,intersect(srange2,erange),1,nullptr,&border1r,&border2l,nullptr);
+ eval(patches[3],srange3,intersect(srange3,erange),1,nullptr,nullptr,&border2r,&border3l);
+#else
+ GeneralCatmullClarkPatch3fa::fix_quad_ring_order(patches);
+ eval(patches[0],srange0,intersect(srange0,erange),1);
+ eval(patches[1],srange1,intersect(srange1,erange),1);
+ eval(patches[2],srange2,intersect(srange2,erange),1);
+ eval(patches[3],srange3,intersect(srange3,erange),1);
+#endif
+ }
+ else
+ {
+ assert(subPatch < N);
+
+#if PATCH_USE_GREGORY == 2
+ BezierCurve3fa borders[2]; patch.getLimitBorder(borders,subPatch);
+ BezierCurve3fa border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve3fa border2l,border2r; borders[1].subdivide(border2l,border2r);
+ eval(patches[subPatch], srange, erange, 1, &border0l, nullptr, nullptr, &border2r);
+#else
+ eval(patches[subPatch], srange, erange, 1);
+#endif
+
+ }
+ assert(count == (x1-x0+1)*(y1-y0+1));
+ }
+
+ FeatureAdaptiveEvalGrid (const CatmullClarkPatch3fa& patch,
+ const BBox2f& srange, const BBox2f& erange, const unsigned depth,
+ const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
+ float* Px, float* Py, float* Pz, float* U, float* V,
+ float* Nx, float* Ny, float* Nz,
+ const unsigned dwidth, const unsigned dheight)
+ : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
+ Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), /*dheight(dheight),*/ count(0)
+ {
+ eval(patch,srange,erange,depth);
+ }
+
+ template<typename Patch>
+ void evalLocalGrid(const Patch& patch, const BBox2f& srange, const int lx0, const int lx1, const int ly0, const int ly1)
+ {
+ const float scale_x = rcp(srange.upper.x-srange.lower.x);
+ const float scale_y = rcp(srange.upper.y-srange.lower.y);
+ count += (lx1-lx0)*(ly1-ly0);
+
+#if 0
+ for (unsigned iy=ly0; iy<ly1; iy++) {
+ for (unsigned ix=lx0; ix<lx1; ix++) {
+ const float lu = select(ix == swidth -1, float(1.0f), (float(ix)-srange.lower.x)*scale_x);
+ const float lv = select(iy == sheight-1, float(1.0f), (float(iy)-srange.lower.y)*scale_y);
+ const Vec3fa p = patch.eval(lu,lv);
+ const float u = float(ix)*rcp_swidth;
+ const float v = float(iy)*rcp_sheight;
+ const int ofs = (iy-y0)*dwidth+(ix-x0);
+ Px[ofs] = p.x;
+ Py[ofs] = p.y;
+ Pz[ofs] = p.z;
+ U[ofs] = u;
+ V[ofs] = v;
+ }
+ }
+#else
+ foreach2(lx0,lx1,ly0,ly1,[&](const vboolx& valid, const vintx& ix, const vintx& iy) {
+ const vfloatx lu = select(ix == swidth -1, vfloatx(1.0f), (vfloatx(ix)-srange.lower.x)*scale_x);
+ const vfloatx lv = select(iy == sheight-1, vfloatx(1.0f), (vfloatx(iy)-srange.lower.y)*scale_y);
+ const Vec3vfx p = patch.eval(lu,lv);
+ Vec3vfx n = zero;
+ if (unlikely(Nx != nullptr)) n = normalize_safe(patch.normal(lu,lv));
+ const vfloatx u = vfloatx(ix)*rcp_swidth;
+ const vfloatx v = vfloatx(iy)*rcp_sheight;
+ const vintx ofs = (iy-y0)*dwidth+(ix-x0);
+ if (likely(all(valid)) && all(iy==iy[0])) {
+ const unsigned ofs2 = ofs[0];
+ vfloatx::storeu(Px+ofs2,p.x);
+ vfloatx::storeu(Py+ofs2,p.y);
+ vfloatx::storeu(Pz+ofs2,p.z);
+ vfloatx::storeu(U+ofs2,u);
+ vfloatx::storeu(V+ofs2,v);
+ if (unlikely(Nx != nullptr)) {
+ vfloatx::storeu(Nx+ofs2,n.x);
+ vfloatx::storeu(Ny+ofs2,n.y);
+ vfloatx::storeu(Nz+ofs2,n.z);
+ }
+ } else {
+ foreach_unique_index(valid,iy,[&](const vboolx& valid, const int iy0, const int j) {
+ const unsigned ofs2 = ofs[j]-j;
+ vfloatx::storeu(valid,Px+ofs2,p.x);
+ vfloatx::storeu(valid,Py+ofs2,p.y);
+ vfloatx::storeu(valid,Pz+ofs2,p.z);
+ vfloatx::storeu(valid,U+ofs2,u);
+ vfloatx::storeu(valid,V+ofs2,v);
+ if (unlikely(Nx != nullptr)) {
+ vfloatx::storeu(valid,Nx+ofs2,n.x);
+ vfloatx::storeu(valid,Ny+ofs2,n.y);
+ vfloatx::storeu(valid,Nz+ofs2,n.z);
+ }
+ });
+ }
+ });
+#endif
+ }
+
+ __forceinline bool final(const CatmullClarkPatch3fa& patch, const CatmullClarkRing::Type type, unsigned depth)
+ {
+ const unsigned max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
+//#if PATCH_MIN_RESOLUTION
+// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=max_eval_depth;
+//#else
+ return depth>=max_eval_depth;
+//#endif
+ }
+
+ void eval(const CatmullClarkPatch3fa& patch, const BBox2f& srange, const BBox2f& erange, const unsigned depth,
+ const BezierCurve3fa* border0 = nullptr, const BezierCurve3fa* border1 = nullptr, const BezierCurve3fa* border2 = nullptr, const BezierCurve3fa* border3 = nullptr)
+ {
+ if (erange.empty())
+ return;
+
+ int lx0 = (int) ceilf(erange.lower.x);
+ int lx1 = (int) ceilf(erange.upper.x) + (erange.upper.x == x1 && (srange.lower.x < erange.upper.x || erange.upper.x == 0));
+ int ly0 = (int) ceilf(erange.lower.y);
+ int ly1 = (int) ceilf(erange.upper.y) + (erange.upper.y == y1 && (srange.lower.y < erange.upper.y || erange.upper.y == 0));
+ if (lx0 >= lx1 || ly0 >= ly1) return;
+
+ CatmullClarkPatch::Type ty = patch.type();
+
+ if (unlikely(final(patch,ty,depth)))
+ {
+ if (ty & CatmullClarkRing::TYPE_REGULAR) {
+ RegularPatch rpatch(patch,border0,border1,border2,border3);
+ evalLocalGrid(rpatch,srange,lx0,lx1,ly0,ly1);
+ return;
+ } else {
+ IrregularFillPatch ipatch(patch,border0,border1,border2,border3);
+ evalLocalGrid(ipatch,srange,lx0,lx1,ly0,ly1);
+ return;
+ }
+ }
+ else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
+ assert(depth > 0);
+ RegularPatch rpatch(patch,border0,border1,border2,border3);
+ evalLocalGrid(rpatch,srange,lx0,lx1,ly0,ly1);
+ return;
+ }
+#if PATCH_USE_GREGORY == 2
+ else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
+ assert(depth > 0);
+ GregoryPatch gpatch(patch,border0,border1,border2,border3);
+ evalLocalGrid(gpatch,srange,lx0,lx1,ly0,ly1);
+ }
+#endif
+ else
+ {
+ array_t<CatmullClarkPatch3fa,4> patches;
+ patch.subdivide(patches);
+
+ const Vec2f c = srange.center();
+ const BBox2f srange0(srange.lower,c);
+ const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
+ const BBox2f srange2(c,srange.upper);
+ const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
+
+ eval(patches[0],srange0,intersect(srange0,erange),depth+1);
+ eval(patches[1],srange1,intersect(srange1,erange),depth+1);
+ eval(patches[2],srange2,intersect(srange2,erange),depth+1);
+ eval(patches[3],srange3,intersect(srange3,erange),depth+1);
+ }
+ }
+ };
+
+ template<typename Eval, typename Patch>
+ bool stitch_col(const Patch& patch, int subPatch,
+ const bool right, const unsigned y0, const unsigned y1, const int fine_y, const int coarse_y,
+ float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dx0, const unsigned dwidth, const unsigned dheight)
+ {
+ assert(coarse_y <= fine_y);
+ if (likely(fine_y == coarse_y))
+ return false;
+
+ const unsigned y0s = stitch(y0,fine_y,coarse_y);
+ const unsigned y1s = stitch(y1,fine_y,coarse_y);
+ const unsigned M = y1s-y0s+1 + VSIZEX;
+
+ dynamic_large_stack_array(float,px,M,64*sizeof(float));
+ dynamic_large_stack_array(float,py,M,64*sizeof(float));
+ dynamic_large_stack_array(float,pz,M,64*sizeof(float));
+ dynamic_large_stack_array(float,u,M,64*sizeof(float));
+ dynamic_large_stack_array(float,v,M,64*sizeof(float));
+ dynamic_large_stack_array(float,nx,M,64*sizeof(float));
+ dynamic_large_stack_array(float,ny,M,64*sizeof(float));
+ dynamic_large_stack_array(float,nz,M,64*sizeof(float));
+ const bool has_Nxyz = Nx; assert(!Nx || (Ny && Nz));
+ Eval(patch,subPatch, right,right, y0s,y1s, 2,coarse_y+1, px,py,pz,u,v,
+ has_Nxyz ? (float*)nx : nullptr,has_Nxyz ? (float*)ny : nullptr ,has_Nxyz ? (float*)nz : nullptr, 1,4097);
+
+ for (unsigned y=y0; y<=y1; y++)
+ {
+ const unsigned ys = stitch(y,fine_y,coarse_y)-y0s;
+ Px[(y-y0)*dwidth+dx0] = px[ys];
+ Py[(y-y0)*dwidth+dx0] = py[ys];
+ Pz[(y-y0)*dwidth+dx0] = pz[ys];
+ U [(y-y0)*dwidth+dx0] = u[ys];
+ V [(y-y0)*dwidth+dx0] = v[ys];
+ if (unlikely(has_Nxyz)) {
+ Nx[(y-y0)*dwidth+dx0] = nx[ys];
+ Ny[(y-y0)*dwidth+dx0] = ny[ys];
+ Nz[(y-y0)*dwidth+dx0] = nz[ys];
+ }
+ }
+ return true;
+ }
+
+ template<typename Eval, typename Patch>
+ bool stitch_row(const Patch& patch, int subPatch,
+ const bool bottom, const unsigned x0, const unsigned x1, const int fine_x, const int coarse_x,
+ float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dy0, const unsigned dwidth, const unsigned dheight)
+ {
+ assert(coarse_x <= fine_x);
+ if (likely(fine_x == coarse_x))
+ return false;
+
+ const unsigned x0s = stitch(x0,fine_x,coarse_x);
+ const unsigned x1s = stitch(x1,fine_x,coarse_x);
+ const unsigned M = x1s-x0s+1 + VSIZEX;
+
+ dynamic_large_stack_array(float,px,M,32*sizeof(float));
+ dynamic_large_stack_array(float,py,M,32*sizeof(float));
+ dynamic_large_stack_array(float,pz,M,32*sizeof(float));
+ dynamic_large_stack_array(float,u,M,32*sizeof(float));
+ dynamic_large_stack_array(float,v,M,32*sizeof(float));
+ dynamic_large_stack_array(float,nx,M,32*sizeof(float));
+ dynamic_large_stack_array(float,ny,M,32*sizeof(float));
+ dynamic_large_stack_array(float,nz,M,32*sizeof(float));
+ const bool has_Nxyz = Nx; assert(!Nx || (Ny && Nz));
+ Eval(patch,subPatch, x0s,x1s, bottom,bottom, coarse_x+1,2, px,py,pz,u,v,
+ has_Nxyz ? (float*)nx :nullptr, has_Nxyz ? (float*)ny : nullptr , has_Nxyz ? (float*)nz : nullptr, 4097,1);
+
+ for (unsigned x=x0; x<=x1; x++)
+ {
+ const unsigned xs = stitch(x,fine_x,coarse_x)-x0s;
+ Px[dy0*dwidth+x-x0] = px[xs];
+ Py[dy0*dwidth+x-x0] = py[xs];
+ Pz[dy0*dwidth+x-x0] = pz[xs];
+ U [dy0*dwidth+x-x0] = u[xs];
+ V [dy0*dwidth+x-x0] = v[xs];
+ if (unlikely(has_Nxyz)) {
+ Nx[dy0*dwidth+x-x0] = nx[xs];
+ Ny[dy0*dwidth+x-x0] = ny[xs];
+ Nz[dy0*dwidth+x-x0] = nz[xs];
+ }
+ }
+ return true;
+ }
+
+ template<typename Eval, typename Patch>
+ void feature_adaptive_eval_grid (const Patch& patch, unsigned subPatch, const float levels[4],
+ const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
+ float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dwidth, const unsigned dheight)
+ {
+ bool sl = false, sr = false, st = false, sb = false;
+ if (levels) {
+ sl = x0 == 0 && stitch_col<Eval,Patch>(patch,subPatch,0,y0,y1,sheight-1,int(levels[3]), Px,Py,Pz,U,V,Nx,Ny,Nz, 0 ,dwidth,dheight);
+ sr = x1 == swidth-1 && stitch_col<Eval,Patch>(patch,subPatch,1,y0,y1,sheight-1,int(levels[1]), Px,Py,Pz,U,V,Nx,Ny,Nz, x1-x0,dwidth,dheight);
+ st = y0 == 0 && stitch_row<Eval,Patch>(patch,subPatch,0,x0,x1,swidth-1,int(levels[0]), Px,Py,Pz,U,V,Nx,Ny,Nz, 0 ,dwidth,dheight);
+ sb = y1 == sheight-1 && stitch_row<Eval,Patch>(patch,subPatch,1,x0,x1,swidth-1,int(levels[2]), Px,Py,Pz,U,V,Nx,Ny,Nz, y1-y0,dwidth,dheight);
+ }
+ const unsigned ofs = st*dwidth+sl;
+ Eval(patch,subPatch,x0+sl,x1-sr,y0+st,y1-sb, swidth,sheight, Px+ofs,Py+ofs,Pz+ofs,U+ofs,V+ofs,Nx?Nx+ofs:nullptr,Ny?Ny+ofs:nullptr,Nz?Nz+ofs:nullptr, dwidth,dheight);
+ }
+ }
+}
+
diff --git a/thirdparty/embree/kernels/subdiv/feature_adaptive_eval_simd.h b/thirdparty/embree/kernels/subdiv/feature_adaptive_eval_simd.h
new file mode 100644
index 0000000000..edab0db12f
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/feature_adaptive_eval_simd.h
@@ -0,0 +1,186 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "patch.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename vbool, typename vint, typename vfloat, typename Vertex, typename Vertex_t = Vertex>
+ struct FeatureAdaptiveEvalSimd
+ {
+ public:
+
+ typedef PatchT<Vertex,Vertex_t> Patch;
+ typedef typename Patch::Ref Ref;
+ typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+ typedef BSplinePatchT<Vertex,Vertex_t> BSplinePatch;
+ typedef BezierPatchT<Vertex,Vertex_t> BezierPatch;
+ typedef GregoryPatchT<Vertex,Vertex_t> GregoryPatch;
+ typedef BilinearPatchT<Vertex,Vertex_t> BilinearPatch;
+ typedef BezierCurveT<Vertex> BezierCurve;
+
+ FeatureAdaptiveEvalSimd (const HalfEdge* edge, const char* vertices, size_t stride, const vbool& valid, const vfloat& u, const vfloat& v,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, const size_t dstride, const size_t N)
+ : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv), dstride(dstride), N(N)
+ {
+ switch (edge->patch_type) {
+ case HalfEdge::BILINEAR_PATCH: BilinearPatch(edge,vertices,stride).eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f,dstride,N); break;
+ case HalfEdge::REGULAR_QUAD_PATCH: RegularPatchT(edge,vertices,stride).eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f,dstride,N); break;
+#if PATCH_USE_GREGORY == 2
+ case HalfEdge::IRREGULAR_QUAD_PATCH: GregoryPatchT<Vertex,Vertex_t>(edge,vertices,stride).eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f,dstride,N); break;
+#endif
+ default: {
+ GeneralCatmullClarkPatch patch(edge,vertices,stride);
+ eval_direct(valid,patch,Vec2<vfloat>(u,v),0);
+ break;
+ }
+ }
+ }
+
+ FeatureAdaptiveEvalSimd (const CatmullClarkPatch& patch, const vbool& valid, const vfloat& u, const vfloat& v, float dscale, size_t depth,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, const size_t dstride, const size_t N)
+ : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv), dstride(dstride), N(N)
+ {
+ eval_direct(valid,patch,Vec2<vfloat>(u,v),dscale,depth);
+ }
+
+ template<size_t N>
+ __forceinline void eval_quad_direct(const vbool& valid, array_t<CatmullClarkPatch,N>& patches, const Vec2<vfloat>& uv, float dscale, size_t depth)
+ {
+ const vfloat u = uv.x, v = uv.y;
+ const vbool u0_mask = u < 0.5f, u1_mask = u >= 0.5f;
+ const vbool v0_mask = v < 0.5f, v1_mask = v >= 0.5f;
+ const vbool u0v0_mask = valid & u0_mask & v0_mask;
+ const vbool u0v1_mask = valid & u0_mask & v1_mask;
+ const vbool u1v0_mask = valid & u1_mask & v0_mask;
+ const vbool u1v1_mask = valid & u1_mask & v1_mask;
+ if (any(u0v0_mask)) eval_direct(u0v0_mask,patches[0],Vec2<vfloat>(2.0f*u,2.0f*v),2.0f*dscale,depth+1);
+ if (any(u1v0_mask)) eval_direct(u1v0_mask,patches[1],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v),2.0f*dscale,depth+1);
+ if (any(u1v1_mask)) eval_direct(u1v1_mask,patches[2],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v-1.0f),2.0f*dscale,depth+1);
+ if (any(u0v1_mask)) eval_direct(u0v1_mask,patches[3],Vec2<vfloat>(2.0f*u,2.0f*v-1.0f),2.0f*dscale,depth+1);
+ }
+
+ template<size_t N>
+ __forceinline void eval_general_quad_direct(const vbool& valid, const GeneralCatmullClarkPatch& patch, array_t<CatmullClarkPatch,N>& patches, const Vec2<vfloat>& uv, float dscale, size_t depth)
+ {
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[GeneralCatmullClarkPatch::SIZE]; patch.getLimitBorder(borders);
+ BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve border1l,border1r; borders[1].subdivide(border1l,border1r);
+ BezierCurve border2l,border2r; borders[2].subdivide(border2l,border2r);
+ BezierCurve border3l,border3r; borders[3].subdivide(border3l,border3r);
+#endif
+ GeneralCatmullClarkPatch::fix_quad_ring_order(patches);
+ const vfloat u = uv.x, v = uv.y;
+ const vbool u0_mask = u < 0.5f, u1_mask = u >= 0.5f;
+ const vbool v0_mask = v < 0.5f, v1_mask = v >= 0.5f;
+ const vbool u0v0_mask = valid & u0_mask & v0_mask;
+ const vbool u0v1_mask = valid & u0_mask & v1_mask;
+ const vbool u1v0_mask = valid & u1_mask & v0_mask;
+ const vbool u1v1_mask = valid & u1_mask & v1_mask;
+#if PATCH_USE_GREGORY == 2
+ if (any(u0v0_mask)) eval_direct(u0v0_mask,patches[0],Vec2<vfloat>(2.0f*u,2.0f*v),2.0f*dscale,depth+1,&border0l,nullptr,nullptr,&border3r);
+ if (any(u1v0_mask)) eval_direct(u1v0_mask,patches[1],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v),2.0f*dscale,depth+1,&border0r,&border1l,nullptr,nullptr);
+ if (any(u1v1_mask)) eval_direct(u1v1_mask,patches[2],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v-1.0f),2.0f*dscale,depth+1,nullptr,&border1r,&border2l,nullptr);
+ if (any(u0v1_mask)) eval_direct(u0v1_mask,patches[3],Vec2<vfloat>(2.0f*u,2.0f*v-1.0f),2.0f*dscale,depth+1,nullptr,nullptr,&border2r,&border3l);
+#else
+ if (any(u0v0_mask)) eval_direct(u0v0_mask,patches[0],Vec2<vfloat>(2.0f*u,2.0f*v),2.0f*dscale,depth+1);
+ if (any(u1v0_mask)) eval_direct(u1v0_mask,patches[1],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v),2.0f*dscale,depth+1);
+ if (any(u1v1_mask)) eval_direct(u1v1_mask,patches[2],Vec2<vfloat>(2.0f*u-1.0f,2.0f*v-1.0f),2.0f*dscale,depth+1);
+ if (any(u0v1_mask)) eval_direct(u0v1_mask,patches[3],Vec2<vfloat>(2.0f*u,2.0f*v-1.0f),2.0f*dscale,depth+1);
+#endif
+ }
+
+ __forceinline bool final(const CatmullClarkPatch& patch, const typename CatmullClarkRing::Type type, size_t depth)
+ {
+ const size_t max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
+//#if PATCH_MIN_RESOLUTION
+// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=max_eval_depth;
+//#else
+ return depth>=max_eval_depth;
+//#endif
+ }
+
+ void eval_direct(const vbool& valid, const CatmullClarkPatch& patch, const Vec2<vfloat>& uv, float dscale, size_t depth,
+ BezierCurve* border0 = nullptr, BezierCurve* border1 = nullptr, BezierCurve* border2 = nullptr, BezierCurve* border3 = nullptr)
+ {
+ typename CatmullClarkPatch::Type ty = patch.type();
+
+ if (unlikely(final(patch,ty,depth)))
+ {
+ if (ty & CatmullClarkRing::TYPE_REGULAR) {
+ RegularPatch(patch,border0,border1,border2,border3).eval(valid,uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ } else {
+ IrregularFillPatch(patch,border0,border1,border2,border3).eval(valid,uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ }
+ }
+ else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
+ assert(depth > 0); RegularPatch(patch,border0,border1,border2,border3).eval(valid,uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ }
+#if PATCH_USE_GREGORY == 2
+ else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
+ assert(depth > 0); GregoryPatch(patch,border0,border1,border2,border3).eval(valid,uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ }
+#endif
+ else
+ {
+ array_t<CatmullClarkPatch,4> patches;
+ patch.subdivide(patches); // FIXME: only have to generate one of the patches
+ eval_quad_direct(valid,patches,uv,dscale,depth);
+ }
+ }
+
+ void eval_direct(const vbool& valid, const GeneralCatmullClarkPatch& patch, const Vec2<vfloat>& uv, const size_t depth)
+ {
+ /* convert into standard quad patch if possible */
+ if (likely(patch.isQuadPatch())) {
+ CatmullClarkPatch qpatch; patch.init(qpatch);
+ return eval_direct(valid,qpatch,uv,1.0f,depth);
+ }
+
+ /* subdivide patch */
+ unsigned Nc;
+ array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches;
+ patch.subdivide(patches,Nc); // FIXME: only have to generate one of the patches
+
+ /* parametrization for quads */
+ if (Nc == 4)
+ eval_general_quad_direct(valid,patch,patches,uv,1.0f,depth);
+
+ /* parametrization for arbitrary polygons */
+ else
+ {
+ const vint l = (vint)floor(0.5f*uv.x); const vfloat u = 2.0f*frac(0.5f*uv.x)-0.5f;
+ const vint h = (vint)floor(0.5f*uv.y); const vfloat v = 2.0f*frac(0.5f*uv.y)-0.5f;
+ const vint i = (h<<2)+l; assert(all(valid,i<Nc));
+ foreach_unique(valid,i,[&](const vbool& valid, const int i) {
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[2]; patch.getLimitBorder(borders,i);
+ BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);
+ eval_direct(valid,patches[i],Vec2<vfloat>(u,v),1.0f,depth+1, &border0l, nullptr, nullptr, &border2r);
+#else
+ eval_direct(valid,patches[i],Vec2<vfloat>(u,v),1.0f,depth+1);
+#endif
+ });
+ }
+ }
+
+ private:
+ float* const P;
+ float* const dPdu;
+ float* const dPdv;
+ float* const ddPdudu;
+ float* const ddPdvdv;
+ float* const ddPdudv;
+ const size_t dstride;
+ const size_t N;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/subdiv/gregory_patch.h b/thirdparty/embree/kernels/subdiv/gregory_patch.h
new file mode 100644
index 0000000000..9026d5c407
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/gregory_patch.h
@@ -0,0 +1,893 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "catmullclark_patch.h"
+#include "bezier_patch.h"
+#include "bezier_curve.h"
+#include "catmullclark_coefficients.h"
+
+namespace embree
+{
+ template<typename Vertex, typename Vertex_t = Vertex>
+ class __aligned(64) GregoryPatchT
+ {
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+ typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
+ typedef BezierCurveT<Vertex> BezierCurve;
+
+ public:
+ Vertex v[4][4];
+ Vertex f[2][2];
+
+ __forceinline GregoryPatchT() {}
+
+ __forceinline GregoryPatchT(const CatmullClarkPatch& patch) {
+ init(patch);
+ }
+
+ __forceinline GregoryPatchT(const CatmullClarkPatch& patch,
+ const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)
+ {
+ init_crackfix(patch,border0,border1,border2,border3);
+ }
+
+ __forceinline GregoryPatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
+ init(CatmullClarkPatch(edge,vertices,stride));
+ }
+
+ __forceinline Vertex& p0() { return v[0][0]; }
+ __forceinline Vertex& p1() { return v[0][3]; }
+ __forceinline Vertex& p2() { return v[3][3]; }
+ __forceinline Vertex& p3() { return v[3][0]; }
+
+ __forceinline Vertex& e0_p() { return v[0][1]; }
+ __forceinline Vertex& e0_m() { return v[1][0]; }
+ __forceinline Vertex& e1_p() { return v[1][3]; }
+ __forceinline Vertex& e1_m() { return v[0][2]; }
+ __forceinline Vertex& e2_p() { return v[3][2]; }
+ __forceinline Vertex& e2_m() { return v[2][3]; }
+ __forceinline Vertex& e3_p() { return v[2][0]; }
+ __forceinline Vertex& e3_m() { return v[3][1]; }
+
+ __forceinline Vertex& f0_p() { return v[1][1]; }
+ __forceinline Vertex& f1_p() { return v[1][2]; }
+ __forceinline Vertex& f2_p() { return v[2][2]; }
+ __forceinline Vertex& f3_p() { return v[2][1]; }
+ __forceinline Vertex& f0_m() { return f[0][0]; }
+ __forceinline Vertex& f1_m() { return f[0][1]; }
+ __forceinline Vertex& f2_m() { return f[1][1]; }
+ __forceinline Vertex& f3_m() { return f[1][0]; }
+
+ __forceinline const Vertex& p0() const { return v[0][0]; }
+ __forceinline const Vertex& p1() const { return v[0][3]; }
+ __forceinline const Vertex& p2() const { return v[3][3]; }
+ __forceinline const Vertex& p3() const { return v[3][0]; }
+
+ __forceinline const Vertex& e0_p() const { return v[0][1]; }
+ __forceinline const Vertex& e0_m() const { return v[1][0]; }
+ __forceinline const Vertex& e1_p() const { return v[1][3]; }
+ __forceinline const Vertex& e1_m() const { return v[0][2]; }
+ __forceinline const Vertex& e2_p() const { return v[3][2]; }
+ __forceinline const Vertex& e2_m() const { return v[2][3]; }
+ __forceinline const Vertex& e3_p() const { return v[2][0]; }
+ __forceinline const Vertex& e3_m() const { return v[3][1]; }
+
+ __forceinline const Vertex& f0_p() const { return v[1][1]; }
+ __forceinline const Vertex& f1_p() const { return v[1][2]; }
+ __forceinline const Vertex& f2_p() const { return v[2][2]; }
+ __forceinline const Vertex& f3_p() const { return v[2][1]; }
+ __forceinline const Vertex& f0_m() const { return f[0][0]; }
+ __forceinline const Vertex& f1_m() const { return f[0][1]; }
+ __forceinline const Vertex& f2_m() const { return f[1][1]; }
+ __forceinline const Vertex& f3_m() const { return f[1][0]; }
+
+ __forceinline Vertex initCornerVertex(const CatmullClarkPatch& irreg_patch, const size_t index) {
+ return irreg_patch.ring[index].getLimitVertex();
+ }
+
+ __forceinline Vertex initPositiveEdgeVertex(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx) {
+ return madd(1.0f/3.0f,irreg_patch.ring[index].getLimitTangent(),p_vtx);
+ }
+
+ __forceinline Vertex initNegativeEdgeVertex(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx) {
+ return madd(1.0f/3.0f,irreg_patch.ring[index].getSecondLimitTangent(),p_vtx);
+ }
+
+ __forceinline Vertex initPositiveEdgeVertex2(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx)
+ {
+ CatmullClark1Ring3fa r0,r1,r2;
+ irreg_patch.ring[index].subdivide(r0);
+ r0.subdivide(r1);
+ r1.subdivide(r2);
+ return madd(8.0f/3.0f,r2.getLimitTangent(),p_vtx);
+ }
+
+ __forceinline Vertex initNegativeEdgeVertex2(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx)
+ {
+ CatmullClark1Ring3fa r0,r1,r2;
+ irreg_patch.ring[index].subdivide(r0);
+ r0.subdivide(r1);
+ r1.subdivide(r2);
+ return madd(8.0f/3.0f,r2.getSecondLimitTangent(),p_vtx);
+ }
+
+ void initFaceVertex(const CatmullClarkPatch& irreg_patch,
+ const size_t index,
+ const Vertex& p_vtx,
+ const Vertex& e0_p_vtx,
+ const Vertex& e1_m_vtx,
+ const unsigned int face_valence_p1,
+ const Vertex& e0_m_vtx,
+ const Vertex& e3_p_vtx,
+ const unsigned int face_valence_p3,
+ Vertex& f_p_vtx,
+ Vertex& f_m_vtx)
+ {
+ const unsigned int face_valence = irreg_patch.ring[index].face_valence;
+ const unsigned int edge_valence = irreg_patch.ring[index].edge_valence;
+ const unsigned int border_index = irreg_patch.ring[index].border_index;
+
+ const Vertex& vtx = irreg_patch.ring[index].vtx;
+ const Vertex e_i = irreg_patch.ring[index].getEdgeCenter(0);
+ const Vertex c_i_m_1 = irreg_patch.ring[index].getQuadCenter(0);
+ const Vertex e_i_m_1 = irreg_patch.ring[index].getEdgeCenter(1);
+
+ Vertex c_i, e_i_p_1;
+ const bool hasHardEdge0 =
+ std::isinf(irreg_patch.ring[index].vertex_crease_weight) &&
+ std::isinf(irreg_patch.ring[index].crease_weight[0]);
+
+ if (unlikely((border_index == edge_valence-2) || hasHardEdge0))
+ {
+ /* mirror quad center and edge mid-point */
+ c_i = madd(2.0f, e_i - c_i_m_1, c_i_m_1);
+ e_i_p_1 = madd(2.0f, vtx - e_i_m_1, e_i_m_1);
+ }
+ else
+ {
+ c_i = irreg_patch.ring[index].getQuadCenter( face_valence-1 );
+ e_i_p_1 = irreg_patch.ring[index].getEdgeCenter( face_valence-1 );
+ }
+
+ Vertex c_i_m_2, e_i_m_2;
+ const bool hasHardEdge1 =
+ std::isinf(irreg_patch.ring[index].vertex_crease_weight) &&
+ std::isinf(irreg_patch.ring[index].crease_weight[1]);
+
+ if (unlikely(border_index == 2 || hasHardEdge1))
+ {
+ /* mirror quad center and edge mid-point */
+ c_i_m_2 = madd(2.0f, e_i_m_1 - c_i_m_1, c_i_m_1);
+ e_i_m_2 = madd(2.0f, vtx - e_i, + e_i);
+ }
+ else
+ {
+ c_i_m_2 = irreg_patch.ring[index].getQuadCenter( 1 );
+ e_i_m_2 = irreg_patch.ring[index].getEdgeCenter( 2 );
+ }
+
+ const float d = 3.0f;
+ //const float c = cosf(2.0f*M_PI/(float)face_valence);
+ //const float c_e_p = cosf(2.0f*M_PI/(float)face_valence_p1);
+ //const float c_e_m = cosf(2.0f*M_PI/(float)face_valence_p3);
+
+ const float c = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence);
+ const float c_e_p = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p1);
+ const float c_e_m = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p3);
+
+ const Vertex r_e_p = 1.0f/3.0f * (e_i_m_1 - e_i_p_1) + 2.0f/3.0f * (c_i_m_1 - c_i);
+ const Vertex r_e_m = 1.0f/3.0f * (e_i - e_i_m_2) + 2.0f/3.0f * (c_i_m_1 - c_i_m_2);
+
+ f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);
+ f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);
+ }
+
+ __noinline void init(const CatmullClarkPatch& patch)
+ {
+ assert( patch.ring[0].hasValidPositions() );
+ assert( patch.ring[1].hasValidPositions() );
+ assert( patch.ring[2].hasValidPositions() );
+ assert( patch.ring[3].hasValidPositions() );
+
+ p0() = initCornerVertex(patch,0);
+ p1() = initCornerVertex(patch,1);
+ p2() = initCornerVertex(patch,2);
+ p3() = initCornerVertex(patch,3);
+
+ e0_p() = initPositiveEdgeVertex(patch,0, p0());
+ e1_p() = initPositiveEdgeVertex(patch,1, p1());
+ e2_p() = initPositiveEdgeVertex(patch,2, p2());
+ e3_p() = initPositiveEdgeVertex(patch,3, p3());
+
+ e0_m() = initNegativeEdgeVertex(patch,0, p0());
+ e1_m() = initNegativeEdgeVertex(patch,1, p1());
+ e2_m() = initNegativeEdgeVertex(patch,2, p2());
+ e3_m() = initNegativeEdgeVertex(patch,3, p3());
+
+ const unsigned int face_valence_p0 = patch.ring[0].face_valence;
+ const unsigned int face_valence_p1 = patch.ring[1].face_valence;
+ const unsigned int face_valence_p2 = patch.ring[2].face_valence;
+ const unsigned int face_valence_p3 = patch.ring[3].face_valence;
+
+ initFaceVertex(patch,0,p0(),e0_p(),e1_m(),face_valence_p1,e0_m(),e3_p(),face_valence_p3,f0_p(),f0_m() );
+ initFaceVertex(patch,1,p1(),e1_p(),e2_m(),face_valence_p2,e1_m(),e0_p(),face_valence_p0,f1_p(),f1_m() );
+ initFaceVertex(patch,2,p2(),e2_p(),e3_m(),face_valence_p3,e2_m(),e1_p(),face_valence_p1,f2_p(),f2_m() );
+ initFaceVertex(patch,3,p3(),e3_p(),e0_m(),face_valence_p0,e3_m(),e2_p(),face_valence_p3,f3_p(),f3_m() );
+
+ }
+
+ __noinline void init_crackfix(const CatmullClarkPatch& patch,
+ const BezierCurve* border0,
+ const BezierCurve* border1,
+ const BezierCurve* border2,
+ const BezierCurve* border3)
+ {
+ assert( patch.ring[0].hasValidPositions() );
+ assert( patch.ring[1].hasValidPositions() );
+ assert( patch.ring[2].hasValidPositions() );
+ assert( patch.ring[3].hasValidPositions() );
+
+ p0() = initCornerVertex(patch,0);
+ p1() = initCornerVertex(patch,1);
+ p2() = initCornerVertex(patch,2);
+ p3() = initCornerVertex(patch,3);
+
+ e0_p() = initPositiveEdgeVertex(patch,0, p0());
+ e1_p() = initPositiveEdgeVertex(patch,1, p1());
+ e2_p() = initPositiveEdgeVertex(patch,2, p2());
+ e3_p() = initPositiveEdgeVertex(patch,3, p3());
+
+ e0_m() = initNegativeEdgeVertex(patch,0, p0());
+ e1_m() = initNegativeEdgeVertex(patch,1, p1());
+ e2_m() = initNegativeEdgeVertex(patch,2, p2());
+ e3_m() = initNegativeEdgeVertex(patch,3, p3());
+
+ if (unlikely(border0 != nullptr))
+ {
+ p0() = border0->v0;
+ e0_p() = border0->v1;
+ e1_m() = border0->v2;
+ p1() = border0->v3;
+ }
+
+ if (unlikely(border1 != nullptr))
+ {
+ p1() = border1->v0;
+ e1_p() = border1->v1;
+ e2_m() = border1->v2;
+ p2() = border1->v3;
+ }
+
+ if (unlikely(border2 != nullptr))
+ {
+ p2() = border2->v0;
+ e2_p() = border2->v1;
+ e3_m() = border2->v2;
+ p3() = border2->v3;
+ }
+
+ if (unlikely(border3 != nullptr))
+ {
+ p3() = border3->v0;
+ e3_p() = border3->v1;
+ e0_m() = border3->v2;
+ p0() = border3->v3;
+ }
+
+ const unsigned int face_valence_p0 = patch.ring[0].face_valence;
+ const unsigned int face_valence_p1 = patch.ring[1].face_valence;
+ const unsigned int face_valence_p2 = patch.ring[2].face_valence;
+ const unsigned int face_valence_p3 = patch.ring[3].face_valence;
+
+ initFaceVertex(patch,0,p0(),e0_p(),e1_m(),face_valence_p1,e0_m(),e3_p(),face_valence_p3,f0_p(),f0_m() );
+ initFaceVertex(patch,1,p1(),e1_p(),e2_m(),face_valence_p2,e1_m(),e0_p(),face_valence_p0,f1_p(),f1_m() );
+ initFaceVertex(patch,2,p2(),e2_p(),e3_m(),face_valence_p3,e2_m(),e1_p(),face_valence_p1,f2_p(),f2_m() );
+ initFaceVertex(patch,3,p3(),e3_p(),e0_m(),face_valence_p0,e3_m(),e2_p(),face_valence_p3,f3_p(),f3_m() );
+ }
+
+
+ void computeGregoryPatchFacePoints(const unsigned int face_valence,
+ const Vertex& r_e_p,
+ const Vertex& r_e_m,
+ const Vertex& p_vtx,
+ const Vertex& e0_p_vtx,
+ const Vertex& e1_m_vtx,
+ const unsigned int face_valence_p1,
+ const Vertex& e0_m_vtx,
+ const Vertex& e3_p_vtx,
+ const unsigned int face_valence_p3,
+ Vertex& f_p_vtx,
+ Vertex& f_m_vtx,
+ const float d = 3.0f)
+ {
+ //const float c = cosf(2.0*M_PI/(float)face_valence);
+ //const float c_e_p = cosf(2.0*M_PI/(float)face_valence_p1);
+ //const float c_e_m = cosf(2.0*M_PI/(float)face_valence_p3);
+
+ const float c = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence);
+ const float c_e_p = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p1);
+ const float c_e_m = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p3);
+
+
+ f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);
+ f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);
+ f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);
+ f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);
+ }
+
+ __noinline void init(const GeneralCatmullClarkPatch& patch)
+ {
+ assert(patch.size() == 4);
+#if 0
+ CatmullClarkPatch qpatch; patch.init(qpatch);
+ init(qpatch);
+#else
+ const float face_valence_p0 = patch.ring[0].face_valence;
+ const float face_valence_p1 = patch.ring[1].face_valence;
+ const float face_valence_p2 = patch.ring[2].face_valence;
+ const float face_valence_p3 = patch.ring[3].face_valence;
+
+ Vertex p0_r_p, p0_r_m;
+ patch.ring[0].computeGregoryPatchEdgePoints( p0(), e0_p(), e0_m(), p0_r_p, p0_r_m );
+
+ Vertex p1_r_p, p1_r_m;
+ patch.ring[1].computeGregoryPatchEdgePoints( p1(), e1_p(), e1_m(), p1_r_p, p1_r_m );
+
+ Vertex p2_r_p, p2_r_m;
+ patch.ring[2].computeGregoryPatchEdgePoints( p2(), e2_p(), e2_m(), p2_r_p, p2_r_m );
+
+ Vertex p3_r_p, p3_r_m;
+ patch.ring[3].computeGregoryPatchEdgePoints( p3(), e3_p(), e3_m(), p3_r_p, p3_r_m );
+
+ computeGregoryPatchFacePoints(face_valence_p0, p0_r_p, p0_r_m, p0(), e0_p(), e1_m(), face_valence_p1, e0_m(), e3_p(), face_valence_p3, f0_p(), f0_m() );
+ computeGregoryPatchFacePoints(face_valence_p1, p1_r_p, p1_r_m, p1(), e1_p(), e2_m(), face_valence_p2, e1_m(), e0_p(), face_valence_p0, f1_p(), f1_m() );
+ computeGregoryPatchFacePoints(face_valence_p2, p2_r_p, p2_r_m, p2(), e2_p(), e3_m(), face_valence_p3, e2_m(), e1_p(), face_valence_p1, f2_p(), f2_m() );
+ computeGregoryPatchFacePoints(face_valence_p3, p3_r_p, p3_r_m, p3(), e3_p(), e0_m(), face_valence_p0, e3_m(), e2_p(), face_valence_p3, f3_p(), f3_m() );
+
+#endif
+ }
+
+
+ __forceinline void convert_to_bezier()
+ {
+ f0_p() = (f0_p() + f0_m()) * 0.5f;
+ f1_p() = (f1_p() + f1_m()) * 0.5f;
+ f2_p() = (f2_p() + f2_m()) * 0.5f;
+ f3_p() = (f3_p() + f3_m()) * 0.5f;
+ f0_m() = Vertex( zero );
+ f1_m() = Vertex( zero );
+ f2_m() = Vertex( zero );
+ f3_m() = Vertex( zero );
+ }
+
+ static __forceinline void computeInnerVertices(const Vertex matrix[4][4], const Vertex f_m[2][2], const float uu, const float vv,
+ Vertex_t& matrix_11, Vertex_t& matrix_12, Vertex_t& matrix_22, Vertex_t& matrix_21)
+ {
+ if (unlikely(uu == 0.0f || uu == 1.0f || vv == 0.0f || vv == 1.0f))
+ {
+ matrix_11 = matrix[1][1];
+ matrix_12 = matrix[1][2];
+ matrix_22 = matrix[2][2];
+ matrix_21 = matrix[2][1];
+ }
+ else
+ {
+ const Vertex_t f0_p = matrix[1][1];
+ const Vertex_t f1_p = matrix[1][2];
+ const Vertex_t f2_p = matrix[2][2];
+ const Vertex_t f3_p = matrix[2][1];
+
+ const Vertex_t f0_m = f_m[0][0];
+ const Vertex_t f1_m = f_m[0][1];
+ const Vertex_t f2_m = f_m[1][1];
+ const Vertex_t f3_m = f_m[1][0];
+
+ matrix_11 = ( uu * f0_p + vv * f0_m)*rcp(uu+vv);
+ matrix_12 = ((1.0f-uu) * f1_m + vv * f1_p)*rcp(1.0f-uu+vv);
+ matrix_22 = ((1.0f-uu) * f2_p + (1.0f-vv) * f2_m)*rcp(2.0f-uu-vv);
+ matrix_21 = ( uu * f3_m + (1.0f-vv) * f3_p)*rcp(1.0f+uu-vv);
+ }
+ }
+
+ template<typename vfloat>
+ static __forceinline void computeInnerVertices(const Vertex v[4][4], const Vertex f[2][2],
+ size_t i, const vfloat& uu, const vfloat& vv, vfloat& matrix_11, vfloat& matrix_12, vfloat& matrix_22, vfloat& matrix_21)
+ {
+ const auto m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);
+
+ const vfloat f0_p = v[1][1][i];
+ const vfloat f1_p = v[1][2][i];
+ const vfloat f2_p = v[2][2][i];
+ const vfloat f3_p = v[2][1][i];
+
+ const vfloat f0_m = f[0][0][i];
+ const vfloat f1_m = f[0][1][i];
+ const vfloat f2_m = f[1][1][i];
+ const vfloat f3_m = f[1][0][i];
+
+ const vfloat one_minus_uu = vfloat(1.0f) - uu;
+ const vfloat one_minus_vv = vfloat(1.0f) - vv;
+
+ const vfloat f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);
+ const vfloat f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);
+ const vfloat f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);
+ const vfloat f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);
+
+ matrix_11 = select(m_border,f0_p,f0_i);
+ matrix_12 = select(m_border,f1_p,f1_i);
+ matrix_22 = select(m_border,f2_p,f2_i);
+ matrix_21 = select(m_border,f3_p,f3_i);
+ }
+
+ static __forceinline Vertex eval(const Vertex matrix[4][4], const Vertex f[2][2], const float& uu, const float& vv)
+ {
+ Vertex_t v_11, v_12, v_22, v_21;
+ computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
+
+ const Vec4<float> Bu = BezierBasis::eval(uu);
+ const Vec4<float> Bv = BezierBasis::eval(vv);
+
+ return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
+ madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
+ madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
+ Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
+ }
+
+ static __forceinline Vertex eval_du(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
+ {
+ Vertex_t v_11, v_12, v_22, v_21;
+ computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
+
+ const Vec4<float> Bu = BezierBasis::derivative(uu);
+ const Vec4<float> Bv = BezierBasis::eval(vv);
+
+ return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
+ madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
+ madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
+ Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
+ }
+
+ static __forceinline Vertex eval_dv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
+ {
+ Vertex_t v_11, v_12, v_22, v_21;
+ computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
+
+ const Vec4<float> Bu = BezierBasis::eval(uu);
+ const Vec4<float> Bv = BezierBasis::derivative(vv);
+
+ return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
+ madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
+ madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
+ Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
+ }
+
+ static __forceinline Vertex eval_dudu(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
+ {
+ Vertex_t v_11, v_12, v_22, v_21;
+ computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
+
+ const Vec4<float> Bu = BezierBasis::derivative2(uu);
+ const Vec4<float> Bv = BezierBasis::eval(vv);
+
+ return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
+ madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
+ madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
+ Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
+ }
+
+ static __forceinline Vertex eval_dvdv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
+ {
+ Vertex_t v_11, v_12, v_22, v_21;
+ computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
+
+ const Vec4<float> Bu = BezierBasis::eval(uu);
+ const Vec4<float> Bv = BezierBasis::derivative2(vv);
+
+ return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
+ madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
+ madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
+ Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
+ }
+
+ static __forceinline Vertex eval_dudv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative
+ {
+ Vertex_t v_11, v_12, v_22, v_21;
+ computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);
+
+ const Vec4<float> Bu = BezierBasis::derivative(uu);
+ const Vec4<float> Bv = BezierBasis::derivative(vv);
+
+ return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),
+ madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),
+ madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),
+ Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));
+ }
+
+ __forceinline Vertex eval(const float uu, const float vv) const {
+ return eval(v,f,uu,vv);
+ }
+
+ __forceinline Vertex eval_du( const float uu, const float vv) const {
+ return eval_du(v,f,uu,vv);
+ }
+
+ __forceinline Vertex eval_dv( const float uu, const float vv) const {
+ return eval_dv(v,f,uu,vv);
+ }
+
+ __forceinline Vertex eval_dudu( const float uu, const float vv) const {
+ return eval_dudu(v,f,uu,vv);
+ }
+
+ __forceinline Vertex eval_dvdv( const float uu, const float vv) const {
+ return eval_dvdv(v,f,uu,vv);
+ }
+
+ __forceinline Vertex eval_dudv( const float uu, const float vv) const {
+ return eval_dudv(v,f,uu,vv);
+ }
+
+ static __forceinline Vertex normal(const Vertex matrix[4][4], const Vertex f_m[2][2], const float uu, const float vv) // FIXME: why not using basis functions
+ {
+ /* interpolate inner vertices */
+ Vertex_t matrix_11, matrix_12, matrix_22, matrix_21;
+ computeInnerVertices(matrix,f_m,uu,vv,matrix_11, matrix_12, matrix_22, matrix_21);
+
+ /* tangentU */
+ const Vertex_t col0 = deCasteljau(vv, (Vertex_t)matrix[0][0], (Vertex_t)matrix[1][0], (Vertex_t)matrix[2][0], (Vertex_t)matrix[3][0]);
+ const Vertex_t col1 = deCasteljau(vv, (Vertex_t)matrix[0][1], (Vertex_t)matrix_11 , (Vertex_t)matrix_21 , (Vertex_t)matrix[3][1]);
+ const Vertex_t col2 = deCasteljau(vv, (Vertex_t)matrix[0][2], (Vertex_t)matrix_12 , (Vertex_t)matrix_22 , (Vertex_t)matrix[3][2]);
+ const Vertex_t col3 = deCasteljau(vv, (Vertex_t)matrix[0][3], (Vertex_t)matrix[1][3], (Vertex_t)matrix[2][3], (Vertex_t)matrix[3][3]);
+
+ const Vertex_t tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);
+
+ /* tangentV */
+ const Vertex_t row0 = deCasteljau(uu, (Vertex_t)matrix[0][0], (Vertex_t)matrix[0][1], (Vertex_t)matrix[0][2], (Vertex_t)matrix[0][3]);
+ const Vertex_t row1 = deCasteljau(uu, (Vertex_t)matrix[1][0], (Vertex_t)matrix_11 , (Vertex_t)matrix_12 , (Vertex_t)matrix[1][3]);
+ const Vertex_t row2 = deCasteljau(uu, (Vertex_t)matrix[2][0], (Vertex_t)matrix_21 , (Vertex_t)matrix_22 , (Vertex_t)matrix[2][3]);
+ const Vertex_t row3 = deCasteljau(uu, (Vertex_t)matrix[3][0], (Vertex_t)matrix[3][1], (Vertex_t)matrix[3][2], (Vertex_t)matrix[3][3]);
+
+ const Vertex_t tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);
+
+ /* normal = tangentU x tangentV */
+ const Vertex_t n = cross(tangentU,tangentV);
+
+ return n;
+ }
+
+ __forceinline Vertex normal( const float uu, const float vv) const {
+ return normal(v,f,uu,vv);
+ }
+
+ __forceinline void eval(const float u, const float v,
+ Vertex* P, Vertex* dPdu, Vertex* dPdv,
+ Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
+ const float dscale = 1.0f) const
+ {
+ if (P) {
+ *P = eval(u,v);
+ }
+ if (dPdu) {
+ assert(dPdu); *dPdu = eval_du(u,v)*dscale;
+ assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
+ }
+ if (ddPdudu) {
+ assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
+ assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
+ assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
+ }
+ }
+
+ template<class vfloat>
+ static __forceinline vfloat eval(const Vertex v[4][4], const Vertex f[2][2],
+ const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n,
+ vfloat& matrix_11, vfloat& matrix_12, vfloat& matrix_22, vfloat& matrix_21)
+ {
+ const vfloat curve0_x = madd(v_n[0],vfloat(v[0][0][i]),madd(v_n[1],vfloat(v[1][0][i]),madd(v_n[2],vfloat(v[2][0][i]),v_n[3] * vfloat(v[3][0][i]))));
+ const vfloat curve1_x = madd(v_n[0],vfloat(v[0][1][i]),madd(v_n[1],vfloat(matrix_11 ),madd(v_n[2],vfloat(matrix_21 ),v_n[3] * vfloat(v[3][1][i]))));
+ const vfloat curve2_x = madd(v_n[0],vfloat(v[0][2][i]),madd(v_n[1],vfloat(matrix_12 ),madd(v_n[2],vfloat(matrix_22 ),v_n[3] * vfloat(v[3][2][i]))));
+ const vfloat curve3_x = madd(v_n[0],vfloat(v[0][3][i]),madd(v_n[1],vfloat(v[1][3][i]),madd(v_n[2],vfloat(v[2][3][i]),v_n[3] * vfloat(v[3][3][i]))));
+ return madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));
+ }
+
+ template<typename vbool, typename vfloat>
+ static __forceinline void eval(const Vertex v[4][4], const Vertex f[2][2],
+ const vbool& valid, const vfloat& uu, const vfloat& vv,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
+ const float dscale, const size_t dstride, const size_t N)
+ {
+ if (P) {
+ const Vec4<vfloat> u_n = BezierBasis::eval(uu);
+ const Vec4<vfloat> v_n = BezierBasis::eval(vv);
+ for (size_t i=0; i<N; i++) {
+ vfloat matrix_11, matrix_12, matrix_22, matrix_21;
+ computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
+ vfloat::store(valid,P+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21));
+ }
+ }
+ if (dPdu)
+ {
+ {
+ assert(dPdu);
+ const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
+ const Vec4<vfloat> v_n = BezierBasis::eval(vv);
+ for (size_t i=0; i<N; i++) {
+ vfloat matrix_11, matrix_12, matrix_22, matrix_21;
+ computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
+ vfloat::store(valid,dPdu+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*dscale);
+ }
+ }
+ {
+ assert(dPdv);
+ const Vec4<vfloat> u_n = BezierBasis::eval(uu);
+ const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
+ for (size_t i=0; i<N; i++) {
+ vfloat matrix_11, matrix_12, matrix_22, matrix_21;
+ computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
+ vfloat::store(valid,dPdv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*dscale);
+ }
+ }
+ }
+ if (ddPdudu)
+ {
+ {
+ assert(ddPdudu);
+ const Vec4<vfloat> u_n = BezierBasis::derivative2(uu);
+ const Vec4<vfloat> v_n = BezierBasis::eval(vv);
+ for (size_t i=0; i<N; i++) {
+ vfloat matrix_11, matrix_12, matrix_22, matrix_21;
+ computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
+ vfloat::store(valid,ddPdudu+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));
+ }
+ }
+ {
+ assert(ddPdvdv);
+ const Vec4<vfloat> u_n = BezierBasis::eval(uu);
+ const Vec4<vfloat> v_n = BezierBasis::derivative2(vv);
+ for (size_t i=0; i<N; i++) {
+ vfloat matrix_11, matrix_12, matrix_22, matrix_21;
+ computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
+ vfloat::store(valid,ddPdvdv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));
+ }
+ }
+ {
+ assert(ddPdudv);
+ const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
+ const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
+ for (size_t i=0; i<N; i++) {
+ vfloat matrix_11, matrix_12, matrix_22, matrix_21;
+ computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times
+ vfloat::store(valid,ddPdudv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));
+ }
+ }
+ }
+ }
+
+ template<typename vbool, typename vfloat>
+ __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
+ const float dscale, const size_t dstride, const size_t N) const {
+ eval(v,f,valid,uu,vv,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ }
+
+ template<class T>
+ static __forceinline Vec3<T> eval_t(const Vertex matrix[4][4], const Vec3<T> f[2][2], const T& uu, const T& vv)
+ {
+ typedef typename T::Bool M;
+ const M m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);
+
+ const Vec3<T> f0_p = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);
+ const Vec3<T> f1_p = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);
+ const Vec3<T> f2_p = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);
+ const Vec3<T> f3_p = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);
+
+ const Vec3<T> f0_m = f[0][0];
+ const Vec3<T> f1_m = f[0][1];
+ const Vec3<T> f2_m = f[1][1];
+ const Vec3<T> f3_m = f[1][0];
+
+ const T one_minus_uu = T(1.0f) - uu;
+ const T one_minus_vv = T(1.0f) - vv;
+
+ const Vec3<T> f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);
+ const Vec3<T> f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);
+ const Vec3<T> f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);
+ const Vec3<T> f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);
+
+ const Vec3<T> F0( select(m_border,f0_p.x,f0_i.x), select(m_border,f0_p.y,f0_i.y), select(m_border,f0_p.z,f0_i.z) );
+ const Vec3<T> F1( select(m_border,f1_p.x,f1_i.x), select(m_border,f1_p.y,f1_i.y), select(m_border,f1_p.z,f1_i.z) );
+ const Vec3<T> F2( select(m_border,f2_p.x,f2_i.x), select(m_border,f2_p.y,f2_i.y), select(m_border,f2_p.z,f2_i.z) );
+ const Vec3<T> F3( select(m_border,f3_p.x,f3_i.x), select(m_border,f3_p.y,f3_i.y), select(m_border,f3_p.z,f3_i.z) );
+
+ const T B0_u = one_minus_uu * one_minus_uu * one_minus_uu;
+ const T B0_v = one_minus_vv * one_minus_vv * one_minus_vv;
+ const T B1_u = 3.0f * (one_minus_uu * uu * one_minus_uu);
+ const T B1_v = 3.0f * (one_minus_vv * vv * one_minus_vv);
+ const T B2_u = 3.0f * (uu * one_minus_uu * uu);
+ const T B2_v = 3.0f * (vv * one_minus_vv * vv);
+ const T B3_u = uu * uu * uu;
+ const T B3_v = vv * vv * vv;
+
+ const T x = madd(B0_v,madd(B0_u,matrix[0][0].x,madd(B1_u,matrix[0][1].x,madd(B2_u,matrix[0][2].x,B3_u * matrix[0][3].x))),
+ madd(B1_v,madd(B0_u,matrix[1][0].x,madd(B1_u,F0.x ,madd(B2_u,F1.x ,B3_u * matrix[1][3].x))),
+ madd(B2_v,madd(B0_u,matrix[2][0].x,madd(B1_u,F3.x ,madd(B2_u,F2.x ,B3_u * matrix[2][3].x))),
+ B3_v*madd(B0_u,matrix[3][0].x,madd(B1_u,matrix[3][1].x,madd(B2_u,matrix[3][2].x,B3_u * matrix[3][3].x))))));
+
+ const T y = madd(B0_v,madd(B0_u,matrix[0][0].y,madd(B1_u,matrix[0][1].y,madd(B2_u,matrix[0][2].y,B3_u * matrix[0][3].y))),
+ madd(B1_v,madd(B0_u,matrix[1][0].y,madd(B1_u,F0.y ,madd(B2_u,F1.y ,B3_u * matrix[1][3].y))),
+ madd(B2_v,madd(B0_u,matrix[2][0].y,madd(B1_u,F3.y ,madd(B2_u,F2.y ,B3_u * matrix[2][3].y))),
+ B3_v*madd(B0_u,matrix[3][0].y,madd(B1_u,matrix[3][1].y,madd(B2_u,matrix[3][2].y,B3_u * matrix[3][3].y))))));
+
+ const T z = madd(B0_v,madd(B0_u,matrix[0][0].z,madd(B1_u,matrix[0][1].z,madd(B2_u,matrix[0][2].z,B3_u * matrix[0][3].z))),
+ madd(B1_v,madd(B0_u,matrix[1][0].z,madd(B1_u,F0.z ,madd(B2_u,F1.z ,B3_u * matrix[1][3].z))),
+ madd(B2_v,madd(B0_u,matrix[2][0].z,madd(B1_u,F3.z ,madd(B2_u,F2.z ,B3_u * matrix[2][3].z))),
+ B3_v*madd(B0_u,matrix[3][0].z,madd(B1_u,matrix[3][1].z,madd(B2_u,matrix[3][2].z,B3_u * matrix[3][3].z))))));
+
+ return Vec3<T>(x,y,z);
+ }
+
+ template<class T>
+ __forceinline Vec3<T> eval(const T& uu, const T& vv) const
+ {
+ Vec3<T> ff[2][2];
+ ff[0][0] = Vec3<T>(f[0][0]);
+ ff[0][1] = Vec3<T>(f[0][1]);
+ ff[1][1] = Vec3<T>(f[1][1]);
+ ff[1][0] = Vec3<T>(f[1][0]);
+ return eval_t(v,ff,uu,vv);
+ }
+
+ template<class T>
+ static __forceinline Vec3<T> normal_t(const Vertex matrix[4][4], const Vec3<T> f[2][2], const T& uu, const T& vv)
+ {
+ typedef typename T::Bool M;
+
+ const Vec3<T> f0_p = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);
+ const Vec3<T> f1_p = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);
+ const Vec3<T> f2_p = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);
+ const Vec3<T> f3_p = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);
+
+ const Vec3<T> f0_m = f[0][0];
+ const Vec3<T> f1_m = f[0][1];
+ const Vec3<T> f2_m = f[1][1];
+ const Vec3<T> f3_m = f[1][0];
+
+ const T one_minus_uu = T(1.0f) - uu;
+ const T one_minus_vv = T(1.0f) - vv;
+
+ const Vec3<T> f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);
+ const Vec3<T> f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);
+ const Vec3<T> f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);
+ const Vec3<T> f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);
+
+#if 1
+ const M m_corner0 = (uu == 0.0f) & (vv == 0.0f);
+ const M m_corner1 = (uu == 1.0f) & (vv == 0.0f);
+ const M m_corner2 = (uu == 1.0f) & (vv == 1.0f);
+ const M m_corner3 = (uu == 0.0f) & (vv == 1.0f);
+ const Vec3<T> matrix_11( select(m_corner0,f0_p.x,f0_i.x), select(m_corner0,f0_p.y,f0_i.y), select(m_corner0,f0_p.z,f0_i.z) );
+ const Vec3<T> matrix_12( select(m_corner1,f1_p.x,f1_i.x), select(m_corner1,f1_p.y,f1_i.y), select(m_corner1,f1_p.z,f1_i.z) );
+ const Vec3<T> matrix_22( select(m_corner2,f2_p.x,f2_i.x), select(m_corner2,f2_p.y,f2_i.y), select(m_corner2,f2_p.z,f2_i.z) );
+ const Vec3<T> matrix_21( select(m_corner3,f3_p.x,f3_i.x), select(m_corner3,f3_p.y,f3_i.y), select(m_corner3,f3_p.z,f3_i.z) );
+#else
+ const M m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);
+ const Vec3<T> matrix_11( select(m_border,f0_p.x,f0_i.x), select(m_border,f0_p.y,f0_i.y), select(m_border,f0_p.z,f0_i.z) );
+ const Vec3<T> matrix_12( select(m_border,f1_p.x,f1_i.x), select(m_border,f1_p.y,f1_i.y), select(m_border,f1_p.z,f1_i.z) );
+ const Vec3<T> matrix_22( select(m_border,f2_p.x,f2_i.x), select(m_border,f2_p.y,f2_i.y), select(m_border,f2_p.z,f2_i.z) );
+ const Vec3<T> matrix_21( select(m_border,f3_p.x,f3_i.x), select(m_border,f3_p.y,f3_i.y), select(m_border,f3_p.z,f3_i.z) );
+#endif
+
+ const Vec3<T> matrix_00 = Vec3<T>(matrix[0][0].x,matrix[0][0].y,matrix[0][0].z);
+ const Vec3<T> matrix_10 = Vec3<T>(matrix[1][0].x,matrix[1][0].y,matrix[1][0].z);
+ const Vec3<T> matrix_20 = Vec3<T>(matrix[2][0].x,matrix[2][0].y,matrix[2][0].z);
+ const Vec3<T> matrix_30 = Vec3<T>(matrix[3][0].x,matrix[3][0].y,matrix[3][0].z);
+
+ const Vec3<T> matrix_01 = Vec3<T>(matrix[0][1].x,matrix[0][1].y,matrix[0][1].z);
+ const Vec3<T> matrix_02 = Vec3<T>(matrix[0][2].x,matrix[0][2].y,matrix[0][2].z);
+ const Vec3<T> matrix_03 = Vec3<T>(matrix[0][3].x,matrix[0][3].y,matrix[0][3].z);
+
+ const Vec3<T> matrix_31 = Vec3<T>(matrix[3][1].x,matrix[3][1].y,matrix[3][1].z);
+ const Vec3<T> matrix_32 = Vec3<T>(matrix[3][2].x,matrix[3][2].y,matrix[3][2].z);
+ const Vec3<T> matrix_33 = Vec3<T>(matrix[3][3].x,matrix[3][3].y,matrix[3][3].z);
+
+ const Vec3<T> matrix_13 = Vec3<T>(matrix[1][3].x,matrix[1][3].y,matrix[1][3].z);
+ const Vec3<T> matrix_23 = Vec3<T>(matrix[2][3].x,matrix[2][3].y,matrix[2][3].z);
+
+ /* tangentU */
+ const Vec3<T> col0 = deCasteljau(vv, matrix_00, matrix_10, matrix_20, matrix_30);
+ const Vec3<T> col1 = deCasteljau(vv, matrix_01, matrix_11, matrix_21, matrix_31);
+ const Vec3<T> col2 = deCasteljau(vv, matrix_02, matrix_12, matrix_22, matrix_32);
+ const Vec3<T> col3 = deCasteljau(vv, matrix_03, matrix_13, matrix_23, matrix_33);
+
+ const Vec3<T> tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);
+
+ /* tangentV */
+ const Vec3<T> row0 = deCasteljau(uu, matrix_00, matrix_01, matrix_02, matrix_03);
+ const Vec3<T> row1 = deCasteljau(uu, matrix_10, matrix_11, matrix_12, matrix_13);
+ const Vec3<T> row2 = deCasteljau(uu, matrix_20, matrix_21, matrix_22, matrix_23);
+ const Vec3<T> row3 = deCasteljau(uu, matrix_30, matrix_31, matrix_32, matrix_33);
+
+ const Vec3<T> tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);
+
+ /* normal = tangentU x tangentV */
+ const Vec3<T> n = cross(tangentU,tangentV);
+ return n;
+ }
+
+ template<class T>
+ __forceinline Vec3<T> normal(const T& uu, const T& vv) const
+ {
+ Vec3<T> ff[2][2];
+ ff[0][0] = Vec3<T>(f[0][0]);
+ ff[0][1] = Vec3<T>(f[0][1]);
+ ff[1][1] = Vec3<T>(f[1][1]);
+ ff[1][0] = Vec3<T>(f[1][0]);
+ return normal_t(v,ff,uu,vv);
+ }
+
+ __forceinline BBox<Vertex> bounds() const
+ {
+ const Vertex *const cv = &v[0][0];
+ BBox<Vertex> bounds (cv[0]);
+ for (size_t i=1; i<16; i++)
+ bounds.extend( cv[i] );
+ bounds.extend(f[0][0]);
+ bounds.extend(f[1][0]);
+ bounds.extend(f[1][1]);
+ bounds.extend(f[1][1]);
+ return bounds;
+ }
+
+ friend embree_ostream operator<<(embree_ostream o, const GregoryPatchT& p)
+ {
+ for (size_t y=0; y<4; y++)
+ for (size_t x=0; x<4; x++)
+ o << "v[" << y << "][" << x << "] " << p.v[y][x] << embree_endl;
+
+ for (size_t y=0; y<2; y++)
+ for (size_t x=0; x<2; x++)
+ o << "f[" << y << "][" << x << "] " << p.f[y][x] << embree_endl;
+ return o;
+ }
+ };
+
+ typedef GregoryPatchT<Vec3fa,Vec3fa_t> GregoryPatch3fa;
+
+ template<typename Vertex, typename Vertex_t>
+ __forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT (const HalfEdge* edge, const char* vertices, size_t stride)
+ {
+ CatmullClarkPatchT<Vertex,Vertex_t> patch(edge,vertices,stride);
+ GregoryPatchT<Vertex,Vertex_t> gpatch(patch);
+ gpatch.convert_to_bezier();
+ for (size_t y=0; y<4; y++)
+ for (size_t x=0; x<4; x++)
+ matrix[y][x] = (Vertex_t)gpatch.v[y][x];
+ }
+
+ template<typename Vertex, typename Vertex_t>
+ __forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch)
+ {
+ GregoryPatchT<Vertex,Vertex_t> gpatch(patch);
+ gpatch.convert_to_bezier();
+ for (size_t y=0; y<4; y++)
+ for (size_t x=0; x<4; x++)
+ matrix[y][x] = (Vertex_t)gpatch.v[y][x];
+ }
+
+ template<typename Vertex, typename Vertex_t>
+ __forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch,
+ const BezierCurveT<Vertex>* border0,
+ const BezierCurveT<Vertex>* border1,
+ const BezierCurveT<Vertex>* border2,
+ const BezierCurveT<Vertex>* border3)
+ {
+ GregoryPatchT<Vertex,Vertex_t> gpatch(patch,border0,border1,border2,border3);
+ gpatch.convert_to_bezier();
+ for (size_t y=0; y<4; y++)
+ for (size_t x=0; x<4; x++)
+ matrix[y][x] = (Vertex_t)gpatch.v[y][x];
+ }
+}
diff --git a/thirdparty/embree/kernels/subdiv/gregory_patch_dense.h b/thirdparty/embree/kernels/subdiv/gregory_patch_dense.h
new file mode 100644
index 0000000000..4cf9a7e98f
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/gregory_patch_dense.h
@@ -0,0 +1,113 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "gregory_patch.h"
+
+namespace embree
+{
+ class __aligned(64) DenseGregoryPatch3fa
+ {
+ typedef Vec3fa Vec3fa_4x4[4][4];
+ public:
+
+ __forceinline DenseGregoryPatch3fa (const GregoryPatch3fa& patch)
+ {
+ for (size_t y=0; y<4; y++)
+ for (size_t x=0; x<4; x++)
+ matrix[y][x] = Vec3ff(patch.v[y][x], 0.0f);
+
+ matrix[0][0].w = patch.f[0][0].x;
+ matrix[0][1].w = patch.f[0][0].y;
+ matrix[0][2].w = patch.f[0][0].z;
+ matrix[0][3].w = 0.0f;
+
+ matrix[1][0].w = patch.f[0][1].x;
+ matrix[1][1].w = patch.f[0][1].y;
+ matrix[1][2].w = patch.f[0][1].z;
+ matrix[1][3].w = 0.0f;
+
+ matrix[2][0].w = patch.f[1][1].x;
+ matrix[2][1].w = patch.f[1][1].y;
+ matrix[2][2].w = patch.f[1][1].z;
+ matrix[2][3].w = 0.0f;
+
+ matrix[3][0].w = patch.f[1][0].x;
+ matrix[3][1].w = patch.f[1][0].y;
+ matrix[3][2].w = patch.f[1][0].z;
+ matrix[3][3].w = 0.0f;
+ }
+
+ __forceinline void extract_f_m(Vec3fa f_m[2][2]) const
+ {
+ f_m[0][0] = Vec3fa( matrix[0][0].w, matrix[0][1].w, matrix[0][2].w );
+ f_m[0][1] = Vec3fa( matrix[1][0].w, matrix[1][1].w, matrix[1][2].w );
+ f_m[1][1] = Vec3fa( matrix[2][0].w, matrix[2][1].w, matrix[2][2].w );
+ f_m[1][0] = Vec3fa( matrix[3][0].w, matrix[3][1].w, matrix[3][2].w );
+ }
+
+ __forceinline Vec3fa eval(const float uu, const float vv) const
+ {
+ __aligned(64) Vec3fa f_m[2][2]; extract_f_m(f_m);
+ return GregoryPatch3fa::eval(*(Vec3fa_4x4*)&matrix,f_m,uu,vv);
+ }
+
+ __forceinline Vec3fa normal(const float uu, const float vv) const
+ {
+ __aligned(64) Vec3fa f_m[2][2]; extract_f_m(f_m);
+ return GregoryPatch3fa::normal(*(Vec3fa_4x4*)&matrix,f_m,uu,vv);
+ }
+
+ template<class T>
+ __forceinline Vec3<T> eval(const T &uu, const T &vv) const
+ {
+ Vec3<T> f_m[2][2];
+ f_m[0][0] = Vec3<T>( matrix[0][0].w, matrix[0][1].w, matrix[0][2].w );
+ f_m[0][1] = Vec3<T>( matrix[1][0].w, matrix[1][1].w, matrix[1][2].w );
+ f_m[1][1] = Vec3<T>( matrix[2][0].w, matrix[2][1].w, matrix[2][2].w );
+ f_m[1][0] = Vec3<T>( matrix[3][0].w, matrix[3][1].w, matrix[3][2].w );
+ return GregoryPatch3fa::eval_t(*(Vec3fa_4x4*)&matrix,f_m,uu,vv);
+ }
+
+ template<class T>
+ __forceinline Vec3<T> normal(const T &uu, const T &vv) const
+ {
+ Vec3<T> f_m[2][2];
+ f_m[0][0] = Vec3<T>( matrix[0][0].w, matrix[0][1].w, matrix[0][2].w );
+ f_m[0][1] = Vec3<T>( matrix[1][0].w, matrix[1][1].w, matrix[1][2].w );
+ f_m[1][1] = Vec3<T>( matrix[2][0].w, matrix[2][1].w, matrix[2][2].w );
+ f_m[1][0] = Vec3<T>( matrix[3][0].w, matrix[3][1].w, matrix[3][2].w );
+ return GregoryPatch3fa::normal_t(*(Vec3fa_4x4*)&matrix,f_m,uu,vv);
+ }
+
+ __forceinline void eval(const float u, const float v,
+ Vec3fa* P, Vec3fa* dPdu, Vec3fa* dPdv, Vec3fa* ddPdudu, Vec3fa* ddPdvdv, Vec3fa* ddPdudv,
+ const float dscale = 1.0f) const
+ {
+ __aligned(64) Vec3fa f_m[2][2]; extract_f_m(f_m);
+ if (P) {
+ *P = GregoryPatch3fa::eval(*(Vec3fa_4x4*)&matrix,f_m,u,v);
+ }
+ if (dPdu) {
+ assert(dPdu); *dPdu = GregoryPatch3fa::eval_du(*(Vec3fa_4x4*)&matrix,f_m,u,v)*dscale;
+ assert(dPdv); *dPdv = GregoryPatch3fa::eval_dv(*(Vec3fa_4x4*)&matrix,f_m,u,v)*dscale;
+ }
+ if (ddPdudu) {
+ assert(ddPdudu); *ddPdudu = GregoryPatch3fa::eval_dudu(*(Vec3fa_4x4*)&matrix,f_m,u,v)*sqr(dscale);
+ assert(ddPdvdv); *ddPdvdv = GregoryPatch3fa::eval_dvdv(*(Vec3fa_4x4*)&matrix,f_m,u,v)*sqr(dscale);
+ assert(ddPdudv); *ddPdudv = GregoryPatch3fa::eval_dudv(*(Vec3fa_4x4*)&matrix,f_m,u,v)*sqr(dscale);
+ }
+ }
+
+ template<typename vbool, typename vfloat>
+ __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv, float* P, float* dPdu, float* dPdv, const float dscale, const size_t dstride, const size_t N) const
+ {
+ __aligned(64) Vec3fa f_m[2][2]; extract_f_m(f_m);
+ GregoryPatch3fa::eval(matrix,f_m,valid,uu,vv,P,dPdu,dPdv,dscale,dstride,N);
+ }
+
+ private:
+ Vec3ff matrix[4][4]; // f_p/m points are stored in 4th component
+ };
+}
diff --git a/thirdparty/embree/kernels/subdiv/gridrange.h b/thirdparty/embree/kernels/subdiv/gridrange.h
new file mode 100644
index 0000000000..4f2b90d7bd
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/gridrange.h
@@ -0,0 +1,96 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+
+namespace embree
+{
+ struct __aligned(16) GridRange
+ {
+ unsigned int u_start;
+ unsigned int u_end;
+ unsigned int v_start;
+ unsigned int v_end;
+
+ __forceinline GridRange() {}
+
+ __forceinline GridRange(unsigned int u_start, unsigned int u_end, unsigned int v_start, unsigned int v_end)
+ : u_start(u_start), u_end(u_end), v_start(v_start), v_end(v_end) {}
+
+ __forceinline unsigned int width() const {
+ return u_end-u_start+1;
+ }
+
+ __forceinline unsigned int height() const {
+ return v_end-v_start+1;
+ }
+
+ __forceinline bool hasLeafSize() const
+ {
+ const unsigned int u_size = u_end-u_start+1;
+ const unsigned int v_size = v_end-v_start+1;
+ assert(u_size >= 1);
+ assert(v_size >= 1);
+ return u_size <= 3 && v_size <= 3;
+ }
+
+ static __forceinline unsigned int split(unsigned int start,unsigned int end)
+ {
+ const unsigned int center = (start+end)/2;
+ assert (center > start);
+ assert (center < end);
+ return center;
+ }
+
+ __forceinline void split(GridRange& r0, GridRange& r1) const
+ {
+ assert( hasLeafSize() == false );
+ const unsigned int u_size = u_end-u_start+1;
+ const unsigned int v_size = v_end-v_start+1;
+ r0 = *this;
+ r1 = *this;
+
+ if (u_size >= v_size)
+ {
+ const unsigned int u_mid = split(u_start,u_end);
+ r0.u_end = u_mid;
+ r1.u_start = u_mid;
+ }
+ else
+ {
+ const unsigned int v_mid = split(v_start,v_end);
+ r0.v_end = v_mid;
+ r1.v_start = v_mid;
+ }
+ }
+
+ __forceinline unsigned int splitIntoSubRanges(GridRange r[4]) const
+ {
+ assert( !hasLeafSize() );
+ unsigned int children = 0;
+ GridRange first,second;
+ split(first,second);
+
+ if (first.hasLeafSize()) {
+ r[0] = first;
+ children++;
+ }
+ else {
+ first.split(r[0],r[1]);
+ children += 2;
+ }
+
+ if (second.hasLeafSize()) {
+ r[children] = second;
+ children++;
+ }
+ else {
+ second.split(r[children+0],r[children+1]);
+ children += 2;
+ }
+ return children;
+ }
+ };
+}
diff --git a/thirdparty/embree/kernels/subdiv/half_edge.h b/thirdparty/embree/kernels/subdiv/half_edge.h
new file mode 100644
index 0000000000..baf019cd79
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/half_edge.h
@@ -0,0 +1,371 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "catmullclark_coefficients.h"
+
+namespace embree
+{
+ class __aligned(32) HalfEdge
+ {
+ friend class SubdivMesh;
+ public:
+
+ enum PatchType : char {
+ BILINEAR_PATCH = 0, //!< a bilinear patch
+ REGULAR_QUAD_PATCH = 1, //!< a regular quad patch can be represented as a B-Spline
+ IRREGULAR_QUAD_PATCH = 2, //!< an irregular quad patch can be represented as a Gregory patch
+ COMPLEX_PATCH = 3 //!< these patches need subdivision and cannot be processed by the above fast code paths
+ };
+
+ enum VertexType : char {
+ REGULAR_VERTEX = 0, //!< regular vertex
+ NON_MANIFOLD_EDGE_VERTEX = 1, //!< vertex of a non-manifold edge
+ };
+
+ __forceinline friend PatchType max( const PatchType& ty0, const PatchType& ty1) {
+ return (PatchType) max((int)ty0,(int)ty1);
+ }
+
+ struct Edge
+ {
+ /*! edge constructor */
+ __forceinline Edge(const uint32_t v0, const uint32_t v1)
+ : v0(v0), v1(v1) {}
+
+ /*! create an 64 bit identifier that is unique for the not oriented edge */
+ __forceinline operator uint64_t() const
+ {
+ uint32_t p0 = v0, p1 = v1;
+ if (p0<p1) std::swap(p0,p1);
+ return (((uint64_t)p0) << 32) | (uint64_t)p1;
+ }
+
+ public:
+ uint32_t v0,v1; //!< start and end vertex of the edge
+ };
+
+ HalfEdge ()
+ : vtx_index(-1), next_half_edge_ofs(0), prev_half_edge_ofs(0), opposite_half_edge_ofs(0), edge_crease_weight(0),
+ vertex_crease_weight(0), edge_level(0), patch_type(COMPLEX_PATCH), vertex_type(REGULAR_VERTEX)
+ {
+ static_assert(sizeof(HalfEdge) == 32, "invalid half edge size");
+ }
+
+ __forceinline bool hasOpposite() const { return opposite_half_edge_ofs != 0; }
+ __forceinline void setOpposite(HalfEdge* opposite) { opposite_half_edge_ofs = int(opposite-this); }
+
+ __forceinline HalfEdge* next() { assert( next_half_edge_ofs != 0 ); return &this[next_half_edge_ofs]; }
+ __forceinline const HalfEdge* next() const { assert( next_half_edge_ofs != 0 ); return &this[next_half_edge_ofs]; }
+
+ __forceinline HalfEdge* prev() { assert( prev_half_edge_ofs != 0 ); return &this[prev_half_edge_ofs]; }
+ __forceinline const HalfEdge* prev() const { assert( prev_half_edge_ofs != 0 ); return &this[prev_half_edge_ofs]; }
+
+ __forceinline HalfEdge* opposite() { assert( opposite_half_edge_ofs != 0 ); return &this[opposite_half_edge_ofs]; }
+ __forceinline const HalfEdge* opposite() const { assert( opposite_half_edge_ofs != 0 ); return &this[opposite_half_edge_ofs]; }
+
+ __forceinline HalfEdge* rotate() { return opposite()->next(); }
+ __forceinline const HalfEdge* rotate() const { return opposite()->next(); }
+
+ __forceinline unsigned int getStartVertexIndex() const { return vtx_index; }
+ __forceinline unsigned int getEndVertexIndex () const { return next()->vtx_index; }
+ __forceinline Edge getEdge () const { return Edge(getStartVertexIndex(),getEndVertexIndex()); }
+
+
+ /*! tests if the start vertex of the edge is regular */
+ __forceinline PatchType vertexType() const
+ {
+ const HalfEdge* p = this;
+ size_t face_valence = 0;
+ bool hasBorder = false;
+
+ do
+ {
+ /* we need subdivision to handle edge creases */
+ if (p->hasOpposite() && p->edge_crease_weight > 0.0f)
+ return COMPLEX_PATCH;
+
+ face_valence++;
+
+ /* test for quad */
+ const HalfEdge* pp = p;
+ pp = pp->next(); if (pp == p) return COMPLEX_PATCH;
+ pp = pp->next(); if (pp == p) return COMPLEX_PATCH;
+ pp = pp->next(); if (pp == p) return COMPLEX_PATCH;
+ pp = pp->next(); if (pp != p) return COMPLEX_PATCH;
+
+ /* continue with next face */
+ p = p->prev();
+ if (likely(p->hasOpposite()))
+ p = p->opposite();
+
+ /* if there is no opposite go the long way to the other side of the border */
+ else
+ {
+ face_valence++;
+ hasBorder = true;
+ p = this;
+ while (p->hasOpposite())
+ p = p->rotate();
+ }
+ } while (p != this);
+
+ /* calculate vertex type */
+ if (face_valence == 2 && hasBorder) {
+ if (vertex_crease_weight == 0.0f ) return REGULAR_QUAD_PATCH;
+ else if (vertex_crease_weight == float(inf)) return REGULAR_QUAD_PATCH;
+ else return COMPLEX_PATCH;
+ }
+ else if (vertex_crease_weight != 0.0f) return COMPLEX_PATCH;
+ else if (face_valence == 3 && hasBorder) return REGULAR_QUAD_PATCH;
+ else if (face_valence == 4 && !hasBorder) return REGULAR_QUAD_PATCH;
+ else return IRREGULAR_QUAD_PATCH;
+ }
+
+ /*! tests if this edge is part of a bilinear patch */
+ __forceinline bool bilinearVertex() const {
+ return vertex_crease_weight == float(inf) && edge_crease_weight == float(inf);
+ }
+
+ /*! calculates the type of the patch */
+ __forceinline PatchType patchType() const
+ {
+ const HalfEdge* p = this;
+ PatchType ret = REGULAR_QUAD_PATCH;
+ bool bilinear = true;
+
+ ret = max(ret,p->vertexType());
+ bilinear &= p->bilinearVertex();
+ if ((p = p->next()) == this) return COMPLEX_PATCH;
+
+ ret = max(ret,p->vertexType());
+ bilinear &= p->bilinearVertex();
+ if ((p = p->next()) == this) return COMPLEX_PATCH;
+
+ ret = max(ret,p->vertexType());
+ bilinear &= p->bilinearVertex();
+ if ((p = p->next()) == this) return COMPLEX_PATCH;
+
+ ret = max(ret,p->vertexType());
+ bilinear &= p->bilinearVertex();
+ if ((p = p->next()) != this) return COMPLEX_PATCH;
+
+ if (bilinear) return BILINEAR_PATCH;
+ return ret;
+ }
+
+ /*! tests if the face is a regular b-spline face */
+ __forceinline bool isRegularFace() const {
+ return patch_type == REGULAR_QUAD_PATCH;
+ }
+
+ /*! tests if the face can be diced (using bspline or gregory patch) */
+ __forceinline bool isGregoryFace() const {
+ return patch_type == IRREGULAR_QUAD_PATCH || patch_type == REGULAR_QUAD_PATCH;
+ }
+
+ /*! tests if the base vertex of this half edge is a corner vertex */
+ __forceinline bool isCorner() const {
+ return !hasOpposite() && !prev()->hasOpposite();
+ }
+
+ /*! tests if the vertex is attached to any border */
+ __forceinline bool vertexHasBorder() const
+ {
+ const HalfEdge* p = this;
+ do {
+ if (!p->hasOpposite()) return true;
+ p = p->rotate();
+ } while (p != this);
+ return false;
+ }
+
+ /*! tests if the face this half edge belongs to has some border */
+ __forceinline bool faceHasBorder() const
+ {
+ const HalfEdge* p = this;
+ do {
+ if (p->vertexHasBorder() && (p->vertex_type != HalfEdge::NON_MANIFOLD_EDGE_VERTEX)) return true;
+ p = p->next();
+ } while (p != this);
+ return false;
+ }
+
+ /*! calculates conservative bounds of a catmull clark subdivision face */
+ __forceinline BBox3fa bounds(const BufferView<Vec3fa>& vertices) const
+ {
+ BBox3fa bounds = this->get1RingBounds(vertices);
+ for (const HalfEdge* p=this->next(); p!=this; p=p->next())
+ bounds.extend(p->get1RingBounds(vertices));
+ return bounds;
+ }
+
+ /*! tests if this is a valid patch */
+ __forceinline bool valid(const BufferView<Vec3fa>& vertices) const
+ {
+ size_t N = 1;
+ if (!this->validRing(vertices)) return false;
+ for (const HalfEdge* p=this->next(); p!=this; p=p->next(), N++) {
+ if (!p->validRing(vertices)) return false;
+ }
+ return N >= 3 && N <= MAX_PATCH_VALENCE;
+ }
+
+ /*! counts number of polygon edges */
+ __forceinline unsigned int numEdges() const
+ {
+ unsigned int N = 1;
+ for (const HalfEdge* p=this->next(); p!=this; p=p->next(), N++);
+ return N;
+ }
+
+ /*! calculates face and edge valence */
+ __forceinline void calculateFaceValenceAndEdgeValence(size_t& faceValence, size_t& edgeValence) const
+ {
+ faceValence = 0;
+ edgeValence = 0;
+
+ const HalfEdge* p = this;
+ do
+ {
+ /* calculate bounds of current face */
+ unsigned int numEdges = p->numEdges();
+ assert(numEdges >= 3);
+ edgeValence += numEdges-2;
+
+ faceValence++;
+ p = p->prev();
+
+ /* continue with next face */
+ if (likely(p->hasOpposite()))
+ p = p->opposite();
+
+ /* if there is no opposite go the long way to the other side of the border */
+ else {
+ faceValence++;
+ edgeValence++;
+ p = this;
+ while (p->hasOpposite())
+ p = p->opposite()->next();
+ }
+
+ } while (p != this);
+ }
+
+ /*! stream output */
+ friend __forceinline std::ostream &operator<<(std::ostream &o, const HalfEdge &h)
+ {
+ return o << "{ " <<
+ "vertex = " << h.vtx_index << ", " << //" -> " << h.next()->vtx_index << ", " <<
+ "prev = " << h.prev_half_edge_ofs << ", " <<
+ "next = " << h.next_half_edge_ofs << ", " <<
+ "opposite = " << h.opposite_half_edge_ofs << ", " <<
+ "edge_crease = " << h.edge_crease_weight << ", " <<
+ "vertex_crease = " << h.vertex_crease_weight << ", " <<
+ //"edge_level = " << h.edge_level <<
+ " }";
+ }
+
+ private:
+
+ /*! calculates the bounds of the face associated with the half-edge */
+ __forceinline BBox3fa getFaceBounds(const BufferView<Vec3fa>& vertices) const
+ {
+ BBox3fa b = vertices[getStartVertexIndex()];
+ for (const HalfEdge* p = next(); p!=this; p=p->next()) {
+ b.extend(vertices[p->getStartVertexIndex()]);
+ }
+ return b;
+ }
+
+ /*! calculates the bounds of the 1-ring associated with the vertex of the half-edge */
+ __forceinline BBox3fa get1RingBounds(const BufferView<Vec3fa>& vertices) const
+ {
+ BBox3fa bounds = empty;
+ const HalfEdge* p = this;
+ do
+ {
+ /* calculate bounds of current face */
+ bounds.extend(p->getFaceBounds(vertices));
+ p = p->prev();
+
+ /* continue with next face */
+ if (likely(p->hasOpposite()))
+ p = p->opposite();
+
+ /* if there is no opposite go the long way to the other side of the border */
+ else {
+ p = this;
+ while (p->hasOpposite())
+ p = p->opposite()->next();
+ }
+
+ } while (p != this);
+
+ return bounds;
+ }
+
+ /*! tests if this is a valid face */
+ __forceinline bool validFace(const BufferView<Vec3fa>& vertices, size_t& N) const
+ {
+ const Vec3fa v = vertices[getStartVertexIndex()];
+ if (!isvalid(v)) return false;
+ size_t n = 1;
+ for (const HalfEdge* p = next(); p!=this; p=p->next(), n++) {
+ const Vec3fa v = vertices[p->getStartVertexIndex()];
+ if (!isvalid(v)) return false;
+ }
+ N += n-2;
+ return n >= 3 && n <= MAX_PATCH_VALENCE;
+ }
+
+ /*! tests if this is a valid ring */
+ __forceinline bool validRing(const BufferView<Vec3fa>& vertices) const
+ {
+ size_t faceValence = 0;
+ size_t edgeValence = 0;
+
+ const HalfEdge* p = this;
+ do
+ {
+ /* calculate bounds of current face */
+ if (!p->validFace(vertices,edgeValence))
+ return false;
+
+ faceValence++;
+ p = p->prev();
+
+ /* continue with next face */
+ if (likely(p->hasOpposite()))
+ p = p->opposite();
+
+ /* if there is no opposite go the long way to the other side of the border */
+ else {
+ faceValence++;
+ edgeValence++;
+ p = this;
+ while (p->hasOpposite())
+ p = p->opposite()->next();
+ }
+
+ } while (p != this);
+
+ return faceValence <= MAX_RING_FACE_VALENCE && edgeValence <= MAX_RING_EDGE_VALENCE;
+ }
+
+ private:
+ unsigned int vtx_index; //!< index of edge start vertex
+ int next_half_edge_ofs; //!< relative offset to next half edge of face
+ int prev_half_edge_ofs; //!< relative offset to previous half edge of face
+ int opposite_half_edge_ofs; //!< relative offset to opposite half edge
+
+ public:
+ float edge_crease_weight; //!< crease weight attached to edge
+ float vertex_crease_weight; //!< crease weight attached to start vertex
+ float edge_level; //!< subdivision factor for edge
+ PatchType patch_type; //!< stores type of subdiv patch
+ VertexType vertex_type; //!< stores type of the start vertex
+ char align[2];
+ };
+}
diff --git a/thirdparty/embree/kernels/subdiv/hermite_curve.h b/thirdparty/embree/kernels/subdiv/hermite_curve.h
new file mode 100644
index 0000000000..ffef5a4315
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/hermite_curve.h
@@ -0,0 +1,39 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+#include "bezier_curve.h"
+
+namespace embree
+{
+ template<typename Vertex>
+ struct HermiteCurveT : BezierCurveT<Vertex>
+ {
+ __forceinline HermiteCurveT() {}
+
+ __forceinline HermiteCurveT(const BezierCurveT<Vertex>& curve)
+ : BezierCurveT<Vertex>(curve) {}
+
+ __forceinline HermiteCurveT(const Vertex& v0, const Vertex& t0, const Vertex& v1, const Vertex& t1)
+ : BezierCurveT<Vertex>(v0,madd(1.0f/3.0f,t0,v0),nmadd(1.0f/3.0f,t1,v1),v1) {}
+
+ __forceinline HermiteCurveT<Vec3ff> xfm_pr(const LinearSpace3fa& space, const Vec3fa& p) const
+ {
+ const Vec3ff q0(xfmVector(space,this->v0-p), this->v0.w);
+ const Vec3ff q1(xfmVector(space,this->v1-p), this->v1.w);
+ const Vec3ff q2(xfmVector(space,this->v2-p), this->v2.w);
+ const Vec3ff q3(xfmVector(space,this->v3-p), this->v3.w);
+ return BezierCurveT<Vec3ff>(q0,q1,q2,q3);
+ }
+ };
+
+ template<typename CurveGeometry>
+ __forceinline HermiteCurveT<Vec3ff> enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const HermiteCurveT<Vec3ff>& curve) {
+ return HermiteCurveT<Vec3ff>(enlargeRadiusToMinWidth(context,geom,ray_org,BezierCurveT<Vec3ff>(curve)));
+ }
+
+ typedef HermiteCurveT<Vec3fa> HermiteCurve3fa;
+}
+
diff --git a/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h b/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h
new file mode 100644
index 0000000000..f8e8a25f35
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h
@@ -0,0 +1,403 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "bezier_curve.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename V>
+ struct TensorLinearQuadraticBezierSurface
+ {
+ QuadraticBezierCurve<V> L;
+ QuadraticBezierCurve<V> R;
+
+ __forceinline TensorLinearQuadraticBezierSurface() {}
+
+ __forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<V>& curve)
+ : L(curve.L), R(curve.R) {}
+
+ __forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {
+ L = other.L; R = other.R; return *this;
+ }
+
+ __forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<V>& L, const QuadraticBezierCurve<V>& R)
+ : L(L), R(R) {}
+
+ __forceinline BBox<V> bounds() const {
+ return merge(L.bounds(),R.bounds());
+ }
+ };
+
+ template<>
+ struct TensorLinearQuadraticBezierSurface<Vec2fa>
+ {
+ QuadraticBezierCurve<vfloat4> LR;
+
+ __forceinline TensorLinearQuadraticBezierSurface() {}
+
+ __forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<Vec2fa>& curve)
+ : LR(curve.LR) {}
+
+ __forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {
+ LR = other.LR; return *this;
+ }
+
+ __forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<vfloat4>& LR)
+ : LR(LR) {}
+
+ __forceinline BBox<Vec2fa> bounds() const
+ {
+ const BBox<vfloat4> b = LR.bounds();
+ const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));
+ const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));
+ return merge(bl,br);
+ }
+ };
+
+ template<typename V>
+ struct TensorLinearCubicBezierSurface
+ {
+ CubicBezierCurve<V> L;
+ CubicBezierCurve<V> R;
+
+ __forceinline TensorLinearCubicBezierSurface() {}
+
+ __forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)
+ : L(curve.L), R(curve.R) {}
+
+ __forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {
+ L = other.L; R = other.R; return *this;
+ }
+
+ __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<V>& L, const CubicBezierCurve<V>& R)
+ : L(L), R(R) {}
+
+ template<template<typename T> class SourceCurve>
+ __forceinline static TensorLinearCubicBezierSurface fromCenterAndNormalCurve(const SourceCurve<Vec3ff>& center, const SourceCurve<Vec3fa>& normal)
+ {
+ SourceCurve<Vec3ff> vcurve = center;
+ SourceCurve<Vec3fa> ncurve = normal;
+
+ /* here we construct a patch which follows the curve l(t) =
+ * p(t) +/- r(t)*normalize(cross(n(t),dp(t))) */
+
+ const Vec3ff p0 = vcurve.eval(0.0f);
+ const Vec3ff dp0 = vcurve.eval_du(0.0f);
+ const Vec3ff ddp0 = vcurve.eval_dudu(0.0f);
+
+ const Vec3fa n0 = ncurve.eval(0.0f);
+ const Vec3fa dn0 = ncurve.eval_du(0.0f);
+
+ const Vec3ff p1 = vcurve.eval(1.0f);
+ const Vec3ff dp1 = vcurve.eval_du(1.0f);
+ const Vec3ff ddp1 = vcurve.eval_dudu(1.0f);
+
+ const Vec3fa n1 = ncurve.eval(1.0f);
+ const Vec3fa dn1 = ncurve.eval_du(1.0f);
+
+ const Vec3fa bt0 = cross(n0,dp0);
+ const Vec3fa dbt0 = cross(dn0,dp0) + cross(n0,ddp0);
+
+ const Vec3fa bt1 = cross(n1,dp1);
+ const Vec3fa dbt1 = cross(dn1,dp1) + cross(n1,ddp1);
+
+ const Vec3fa k0 = normalize(bt0);
+ const Vec3fa dk0 = dnormalize(bt0,dbt0);
+
+ const Vec3fa k1 = normalize(bt1);
+ const Vec3fa dk1 = dnormalize(bt1,dbt1);
+
+ const Vec3fa l0 = p0 - p0.w*k0;
+ const Vec3fa dl0 = dp0 - (dp0.w*k0 + p0.w*dk0);
+
+ const Vec3fa r0 = p0 + p0.w*k0;
+ const Vec3fa dr0 = dp0 + (dp0.w*k0 + p0.w*dk0);
+
+ const Vec3fa l1 = p1 - p1.w*k1;
+ const Vec3fa dl1 = dp1 - (dp1.w*k1 + p1.w*dk1);
+
+ const Vec3fa r1 = p1 + p1.w*k1;
+ const Vec3fa dr1 = dp1 + (dp1.w*k1 + p1.w*dk1);
+
+ const float scale = 1.0f/3.0f;
+ CubicBezierCurve<V> L(l0,l0+scale*dl0,l1-scale*dl1,l1);
+ CubicBezierCurve<V> R(r0,r0+scale*dr0,r1-scale*dr1,r1);
+ return TensorLinearCubicBezierSurface(L,R);
+ }
+
+ __forceinline BBox<V> bounds() const {
+ return merge(L.bounds(),R.bounds());
+ }
+
+ __forceinline BBox3fa accurateBounds() const {
+ return merge(L.accurateBounds(),R.accurateBounds());
+ }
+
+ __forceinline CubicBezierCurve<Interval1f> reduce_v() const {
+ return merge(CubicBezierCurve<Interval<V>>(L),CubicBezierCurve<Interval<V>>(R));
+ }
+
+ __forceinline LinearBezierCurve<Interval1f> reduce_u() const {
+ return LinearBezierCurve<Interval1f>(L.bounds(),R.bounds());
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx) const {
+ return TensorLinearCubicBezierSurface<float>(L.xfm(dx),R.xfm(dx));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<vfloatx> vxfm(const V& dx) const {
+ return TensorLinearCubicBezierSurface<vfloatx>(L.vxfm(dx),R.vxfm(dx));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx, const V& p) const {
+ return TensorLinearCubicBezierSurface<float>(L.xfm(dx,p),R.xfm(dx,p));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space) const {
+ return TensorLinearCubicBezierSurface(L.xfm(space),R.xfm(space));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p) const {
+ return TensorLinearCubicBezierSurface(L.xfm(space,p),R.xfm(space,p));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p, const float s) const {
+ return TensorLinearCubicBezierSurface(L.xfm(space,p,s),R.xfm(space,p,s));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {
+ return TensorLinearCubicBezierSurface(L.clip(u),R.clip(u));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const {
+ return TensorLinearCubicBezierSurface(clerp(L,R,V(v.lower)),clerp(L,R,V(v.upper)));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {
+ return clip_v(v).clip_u(u);
+ }
+
+ __forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const
+ {
+ CubicBezierCurve<V> L0,L1; L.split(L0,L1,u);
+ CubicBezierCurve<V> R0,R1; R.split(R0,R1,u);
+ new (&left ) TensorLinearCubicBezierSurface(L0,R0);
+ new (&right) TensorLinearCubicBezierSurface(L1,R1);
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {
+ valid = true; clear(valid,VSIZEX-1);
+ return TensorLinearCubicBezierSurface<Vec2vfx>(L.split(u),R.split(u));
+ }
+
+ __forceinline V eval(const float u, const float v) const {
+ return clerp(L,R,V(v)).eval(u);
+ }
+
+ __forceinline V eval_du(const float u, const float v) const {
+ return clerp(L,R,V(v)).eval_dt(u);
+ }
+
+ __forceinline V eval_dv(const float u, const float v) const {
+ return (R-L).eval(u);
+ }
+
+ __forceinline void eval(const float u, const float v, V& p, V& dpdu, V& dpdv) const
+ {
+ V p0, dp0du; L.eval(u,p0,dp0du);
+ V p1, dp1du; R.eval(u,p1,dp1du);
+ p = lerp(p0,p1,v);
+ dpdu = lerp(dp0du,dp1du,v);
+ dpdv = p1-p0;
+ }
+
+ __forceinline TensorLinearQuadraticBezierSurface<V> derivative_u() const {
+ return TensorLinearQuadraticBezierSurface<V>(L.derivative(),R.derivative());
+ }
+
+ __forceinline CubicBezierCurve<V> derivative_v() const {
+ return R-L;
+ }
+
+ __forceinline V axis_u() const {
+ return (L.end()-L.begin())+(R.end()-R.begin());
+ }
+
+ __forceinline V axis_v() const {
+ return (R.begin()-L.begin())+(R.end()-L.end());
+ }
+
+ friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)
+ {
+ return cout << "TensorLinearCubicBezierSurface" << embree_endl
+ << "{" << embree_endl
+ << " L = " << a.L << ", " << embree_endl
+ << " R = " << a.R << embree_endl
+ << "}";
+ }
+
+ friend __forceinline TensorLinearCubicBezierSurface clerp(const TensorLinearCubicBezierSurface& a, const TensorLinearCubicBezierSurface& b, const float t) {
+ return TensorLinearCubicBezierSurface(clerp(a.L,b.L,V(t)), clerp(a.R,b.R,V(t)));
+ }
+ };
+
+ template<>
+ struct TensorLinearCubicBezierSurface<Vec2fa>
+ {
+ CubicBezierCurve<vfloat4> LR;
+
+ __forceinline TensorLinearCubicBezierSurface() {}
+
+ __forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)
+ : LR(curve.LR) {}
+
+ __forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {
+ LR = other.LR; return *this;
+ }
+
+ __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<vfloat4>& LR)
+ : LR(LR) {}
+
+ __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<Vec2fa>& L, const CubicBezierCurve<Vec2fa>& R)
+ : LR(shuffle<0,1,0,1>(vfloat4(L.v0),vfloat4(R.v0)),shuffle<0,1,0,1>(vfloat4(L.v1),vfloat4(R.v1)),shuffle<0,1,0,1>(vfloat4(L.v2),vfloat4(R.v2)),shuffle<0,1,0,1>(vfloat4(L.v3),vfloat4(R.v3))) {}
+
+ __forceinline CubicBezierCurve<Vec2fa> getL() const {
+ return CubicBezierCurve<Vec2fa>(Vec2fa(LR.v0),Vec2fa(LR.v1),Vec2fa(LR.v2),Vec2fa(LR.v3));
+ }
+
+ __forceinline CubicBezierCurve<Vec2fa> getR() const {
+ return CubicBezierCurve<Vec2fa>(Vec2fa(shuffle<2,3,2,3>(LR.v0)),Vec2fa(shuffle<2,3,2,3>(LR.v1)),Vec2fa(shuffle<2,3,2,3>(LR.v2)),Vec2fa(shuffle<2,3,2,3>(LR.v3)));
+ }
+
+ __forceinline BBox<Vec2fa> bounds() const
+ {
+ const BBox<vfloat4> b = LR.bounds();
+ const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));
+ const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));
+ return merge(bl,br);
+ }
+
+ __forceinline BBox1f bounds(const Vec2fa& axis) const
+ {
+ const CubicBezierCurve<vfloat4> LRx = LR;
+ const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
+ const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(axis)),LRx,shuffle<1>(vfloat4(axis))*LRy);
+ const BBox<vfloat4> Lb = LRa.bounds();
+ const BBox<vfloat4> Rb(shuffle<3>(Lb.lower),shuffle<3>(Lb.upper));
+ const BBox<vfloat4> b = merge(Lb,Rb);
+ return BBox1f(b.lower[0],b.upper[0]);
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx) const
+ {
+ const CubicBezierCurve<vfloat4> LRx = LR;
+ const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
+ const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);
+ return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),
+ CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx, const Vec2fa& p) const
+ {
+ const vfloat4 pxyxy = shuffle<0,1,0,1>(vfloat4(p));
+ const CubicBezierCurve<vfloat4> LRx = LR-pxyxy;
+ const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
+ const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);
+ return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),
+ CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {
+ return TensorLinearCubicBezierSurface(LR.clip(u));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const
+ {
+ const CubicBezierCurve<vfloat4> LL(shuffle<0,1,0,1>(LR.v0),shuffle<0,1,0,1>(LR.v1),shuffle<0,1,0,1>(LR.v2),shuffle<0,1,0,1>(LR.v3));
+ const CubicBezierCurve<vfloat4> RR(shuffle<2,3,2,3>(LR.v0),shuffle<2,3,2,3>(LR.v1),shuffle<2,3,2,3>(LR.v2),shuffle<2,3,2,3>(LR.v3));
+ return TensorLinearCubicBezierSurface(clerp(LL,RR,vfloat4(v.lower,v.lower,v.upper,v.upper)));
+ }
+
+ __forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {
+ return clip_v(v).clip_u(u);
+ }
+
+ __forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const
+ {
+ CubicBezierCurve<vfloat4> LR0,LR1; LR.split(LR0,LR1,u);
+ new (&left ) TensorLinearCubicBezierSurface(LR0);
+ new (&right) TensorLinearCubicBezierSurface(LR1);
+ }
+
+ __forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {
+ valid = true; clear(valid,VSIZEX-1);
+ return TensorLinearCubicBezierSurface<Vec2vfx>(getL().split(u),getR().split(u));
+ }
+
+ __forceinline Vec2fa eval(const float u, const float v) const
+ {
+ const vfloat4 p = LR.eval(u);
+ return Vec2fa(lerp(shuffle<0,1,0,1>(p),shuffle<2,3,2,3>(p),v));
+ }
+
+ __forceinline Vec2fa eval_du(const float u, const float v) const
+ {
+ const vfloat4 dpdu = LR.eval_dt(u);
+ return Vec2fa(lerp(shuffle<0,1,0,1>(dpdu),shuffle<2,3,2,3>(dpdu),v));
+ }
+
+ __forceinline Vec2fa eval_dv(const float u, const float v) const
+ {
+ const vfloat4 p = LR.eval(u);
+ return Vec2fa(shuffle<2,3,2,3>(p)-shuffle<0,1,0,1>(p));
+ }
+
+ __forceinline void eval(const float u, const float v, Vec2fa& p, Vec2fa& dpdu, Vec2fa& dpdv) const
+ {
+ vfloat4 p0, dp0du; LR.eval(u,p0,dp0du);
+ p = Vec2fa(lerp(shuffle<0,1,0,1>(p0),shuffle<2,3,2,3>(p0),v));
+ dpdu = Vec2fa(lerp(shuffle<0,1,0,1>(dp0du),shuffle<2,3,2,3>(dp0du),v));
+ dpdv = Vec2fa(shuffle<2,3,2,3>(p0)-shuffle<0,1,0,1>(p0));
+ }
+
+ __forceinline TensorLinearQuadraticBezierSurface<Vec2fa> derivative_u() const {
+ return TensorLinearQuadraticBezierSurface<Vec2fa>(LR.derivative());
+ }
+
+ __forceinline CubicBezierCurve<Vec2fa> derivative_v() const {
+ return getR()-getL();
+ }
+
+ __forceinline Vec2fa axis_u() const
+ {
+ const CubicBezierCurve<Vec2fa> L = getL();
+ const CubicBezierCurve<Vec2fa> R = getR();
+ return (L.end()-L.begin())+(R.end()-R.begin());
+ }
+
+ __forceinline Vec2fa axis_v() const
+ {
+ const CubicBezierCurve<Vec2fa> L = getL();
+ const CubicBezierCurve<Vec2fa> R = getR();
+ return (R.begin()-L.begin())+(R.end()-L.end());
+ }
+
+ friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)
+ {
+ return cout << "TensorLinearCubicBezierSurface" << embree_endl
+ << "{" << embree_endl
+ << " L = " << a.getL() << ", " << embree_endl
+ << " R = " << a.getR() << embree_endl
+ << "}";
+ }
+ };
+
+ typedef TensorLinearCubicBezierSurface<float> TensorLinearCubicBezierSurface1f;
+ typedef TensorLinearCubicBezierSurface<Vec2fa> TensorLinearCubicBezierSurface2fa;
+ typedef TensorLinearCubicBezierSurface<Vec3fa> TensorLinearCubicBezierSurface3fa;
+ }
+}
diff --git a/thirdparty/embree/kernels/subdiv/patch.h b/thirdparty/embree/kernels/subdiv/patch.h
new file mode 100644
index 0000000000..c4340ea9b6
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/patch.h
@@ -0,0 +1,371 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "catmullclark_patch.h"
+#include "bilinear_patch.h"
+#include "bspline_patch.h"
+#include "bezier_patch.h"
+#include "gregory_patch.h"
+#include "tessellation_cache.h"
+
+#if 1
+#define PATCH_DEBUG_SUBDIVISION(ptr,x,y,z)
+#else
+#define PATCH_DEBUG_SUBDIVISION(ptr,x,y,z) \
+ { \
+ size_t hex = (size_t)ptr; \
+ for (size_t i=0; i<4; i++) hex = hex ^ (hex >> 8); \
+ const float c = (float)(((hex >> 0) ^ (hex >> 4) ^ (hex >> 8) ^ (hex >> 12) ^ (hex >> 16))&0xf)/15.0f; \
+ if (P) *P = Vertex(0.5f+0.5f*x,0.5f+0.5f*y,0.5f+0.5f*z,0.0f); \
+ }
+#endif
+
+#define PATCH_MAX_CACHE_DEPTH 2
+//#define PATCH_MIN_RESOLUTION 1 // FIXME: not yet completely implemented
+#define PATCH_MAX_EVAL_DEPTH_IRREGULAR 10 // maximum evaluation depth at irregular vertices (has to be larger or equal than PATCH_MAX_CACHE_DEPTH)
+#define PATCH_MAX_EVAL_DEPTH_CREASE 10 // maximum evaluation depth at crease features (has to be larger or equal than PATCH_MAX_CACHE_DEPTH)
+#define PATCH_USE_GREGORY 1 // 0 = no gregory, 1 = fill, 2 = as early as possible
+
+#if PATCH_USE_GREGORY==2
+#define PATCH_USE_BEZIER_PATCH 1 // enable use of bezier instead of b-spline patches
+#else
+#define PATCH_USE_BEZIER_PATCH 0 // enable use of bezier instead of b-spline patches
+#endif
+
+#if PATCH_USE_BEZIER_PATCH
+# define RegularPatch BezierPatch
+# define RegularPatchT BezierPatchT<Vertex,Vertex_t>
+#else
+# define RegularPatch BSplinePatch
+# define RegularPatchT BSplinePatchT<Vertex,Vertex_t>
+#endif
+
+#if PATCH_USE_GREGORY
+#define IrregularFillPatch GregoryPatch
+#define IrregularFillPatchT GregoryPatchT<Vertex,Vertex_t>
+#else
+#define IrregularFillPatch BilinearPatch
+#define IrregularFillPatchT BilinearPatchT<Vertex,Vertex_t>
+#endif
+
+namespace embree
+{
+ template<typename Vertex, typename Vertex_t = Vertex>
+ struct __aligned(64) PatchT
+ {
+ public:
+
+ typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+ typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
+ typedef BezierCurveT<Vertex> BezierCurve;
+
+ enum Type {
+ INVALID_PATCH = 0,
+ BILINEAR_PATCH = 1,
+ BSPLINE_PATCH = 2,
+ BEZIER_PATCH = 3,
+ GREGORY_PATCH = 4,
+ SUBDIVIDED_GENERAL_PATCH = 7,
+ SUBDIVIDED_QUAD_PATCH = 8,
+ EVAL_PATCH = 9,
+ };
+
+ struct Ref
+ {
+ __forceinline Ref(void* p = nullptr)
+ : ptr((size_t)p) {}
+
+ __forceinline operator bool() const { return ptr != 0; }
+ __forceinline operator size_t() const { return ptr; }
+
+ __forceinline Ref (Type ty, void* in)
+ : ptr(((size_t)in)+ty) { assert((((size_t)in) & 0xF) == 0); }
+
+ __forceinline Type type () const { return (Type)(ptr & 0xF); }
+ __forceinline void* object() const { return (void*) (ptr & ~0xF); }
+
+ size_t ptr;
+ };
+
+ struct EvalPatch
+ {
+ /* creates EvalPatch from a CatmullClarkPatch */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch)
+ {
+ size_t ofs = 0, bytes = patch.bytes();
+ void* ptr = alloc(bytes);
+ patch.serialize(ptr,ofs);
+ assert(ofs == bytes);
+ return Ref(EVAL_PATCH, ptr);
+ }
+ };
+
+ struct BilinearPatch
+ {
+ /* creates BilinearPatch from a CatmullClarkPatch */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch,
+ const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3) {
+ return Ref(BILINEAR_PATCH, new (alloc(sizeof(BilinearPatch))) BilinearPatch(patch));
+ }
+
+ __forceinline BilinearPatch (const CatmullClarkPatch& patch)
+ : patch(patch) {}
+
+ /* creates BilinearPatch from 4 vertices */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride) {
+ return Ref(BILINEAR_PATCH, new (alloc(sizeof(BilinearPatch))) BilinearPatch(edge,vertices,stride));
+ }
+
+ __forceinline BilinearPatch (const HalfEdge* edge, const char* vertices, size_t stride)
+ : patch(edge,vertices,stride) {}
+
+ public:
+ BilinearPatchT<Vertex,Vertex_t> patch;
+ };
+
+ struct BSplinePatch
+ {
+ /* creates BSplinePatch from a half edge */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride) {
+ return Ref(BSPLINE_PATCH, new (alloc(sizeof(BSplinePatch))) BSplinePatch(edge,vertices,stride));
+ }
+
+ __forceinline BSplinePatch (const HalfEdge* edge, const char* vertices, size_t stride)
+ : patch(edge,vertices,stride) {}
+
+ /* creates BSplinePatch from a CatmullClarkPatch */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch,
+ const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3) {
+ return Ref(BSPLINE_PATCH, new (alloc(sizeof(BSplinePatch))) BSplinePatch(patch,border0,border1,border2,border3));
+ }
+
+ __forceinline BSplinePatch (const CatmullClarkPatch& patch, const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)
+ : patch(patch,border0,border1,border2,border3) {}
+
+ public:
+ BSplinePatchT<Vertex,Vertex_t> patch;
+ };
+
+ struct BezierPatch
+ {
+ /* creates BezierPatch from a half edge */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride) {
+ return Ref(BEZIER_PATCH, new (alloc(sizeof(BezierPatch))) BezierPatch(edge,vertices,stride));
+ }
+
+ __forceinline BezierPatch (const HalfEdge* edge, const char* vertices, size_t stride)
+ : patch(edge,vertices,stride) {}
+
+ /* creates Bezier from a CatmullClarkPatch */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch,
+ const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3) {
+ return Ref(BEZIER_PATCH, new (alloc(sizeof(BezierPatch))) BezierPatch(patch,border0,border1,border2,border3));
+ }
+
+ __forceinline BezierPatch (const CatmullClarkPatch& patch, const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)
+ : patch(patch,border0,border1,border2,border3) {}
+
+ public:
+ BezierPatchT<Vertex,Vertex_t> patch;
+ };
+
+ struct GregoryPatch
+ {
+ /* creates GregoryPatch from half edge */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride) {
+ return Ref(GREGORY_PATCH, new (alloc(sizeof(GregoryPatch))) GregoryPatch(edge,vertices,stride));
+ }
+
+ __forceinline GregoryPatch (const HalfEdge* edge, const char* vertices, size_t stride)
+ : patch(CatmullClarkPatch(edge,vertices,stride)) {}
+
+ /* creates GregoryPatch from CatmullClarkPatch */
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const CatmullClarkPatch& patch,
+ const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3) {
+ return Ref(GREGORY_PATCH, new (alloc(sizeof(GregoryPatch))) GregoryPatch(patch,border0,border1,border2,border3));
+ }
+
+ __forceinline GregoryPatch (const CatmullClarkPatch& patch, const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)
+ : patch(patch,border0,border1,border2,border3) {}
+
+ public:
+ GregoryPatchT<Vertex,Vertex_t> patch;
+ };
+
+ struct SubdividedQuadPatch
+ {
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, Ref children[4]) {
+ return Ref(SUBDIVIDED_QUAD_PATCH, new (alloc(sizeof(SubdividedQuadPatch))) SubdividedQuadPatch(children));
+ }
+
+ __forceinline SubdividedQuadPatch(Ref children[4]) {
+ for (size_t i=0; i<4; i++) child[i] = children[i];
+ }
+
+ public:
+ Ref child[4];
+ };
+
+ struct SubdividedGeneralPatch
+ {
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, Ref* children, const unsigned N) {
+ return Ref(SUBDIVIDED_GENERAL_PATCH, new (alloc(sizeof(SubdividedGeneralPatch))) SubdividedGeneralPatch(children,N));
+ }
+
+ __forceinline SubdividedGeneralPatch(Ref* children, const unsigned N) : N(N) {
+ for (unsigned i=0; i<N; i++) child[i] = children[i];
+ }
+
+ unsigned N;
+ Ref child[MAX_PATCH_VALENCE];
+ };
+
+ /*! Default constructor. */
+ __forceinline PatchT () {}
+
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, const HalfEdge* edge, const char* vertices, size_t stride)
+ {
+ if (PATCH_MAX_CACHE_DEPTH == 0)
+ return nullptr;
+
+ Ref child(0);
+ switch (edge->patch_type) {
+ case HalfEdge::BILINEAR_PATCH: child = BilinearPatch::create(alloc,edge,vertices,stride); break;
+ case HalfEdge::REGULAR_QUAD_PATCH: child = RegularPatch::create(alloc,edge,vertices,stride); break;
+#if PATCH_USE_GREGORY == 2
+ case HalfEdge::IRREGULAR_QUAD_PATCH: child = GregoryPatch::create(alloc,edge,vertices,stride); break;
+#endif
+ default: {
+ GeneralCatmullClarkPatch patch(edge,vertices,stride);
+ child = PatchT::create(alloc,patch,edge,vertices,stride,0);
+ }
+ }
+ return child;
+ }
+
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, GeneralCatmullClarkPatch& patch, const HalfEdge* edge, const char* vertices, size_t stride, size_t depth)
+ {
+ /* convert into standard quad patch if possible */
+ if (likely(patch.isQuadPatch()))
+ {
+ CatmullClarkPatch qpatch; patch.init(qpatch);
+ return PatchT::create(alloc,qpatch,edge,vertices,stride,depth);
+ }
+
+ /* do only cache up to some depth */
+ if (depth >= PATCH_MAX_CACHE_DEPTH)
+ return nullptr;
+
+ /* subdivide patch */
+ unsigned N;
+ array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches;
+ patch.subdivide(patches,N);
+
+ if (N == 4)
+ {
+ Ref child[4];
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[GeneralCatmullClarkPatch::SIZE]; patch.getLimitBorder(borders);
+ BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);
+ BezierCurve border1l,border1r; borders[1].subdivide(border1l,border1r);
+ BezierCurve border2l,border2r; borders[2].subdivide(border2l,border2r);
+ BezierCurve border3l,border3r; borders[3].subdivide(border3l,border3r);
+ GeneralCatmullClarkPatch::fix_quad_ring_order(patches);
+ child[0] = PatchT::create(alloc,patches[0],edge,vertices,stride,depth+1,&border0l,nullptr,nullptr,&border3r);
+ child[1] = PatchT::create(alloc,patches[1],edge,vertices,stride,depth+1,&border0r,&border1l,nullptr,nullptr);
+ child[2] = PatchT::create(alloc,patches[2],edge,vertices,stride,depth+1,nullptr,&border1r,&border2l,nullptr);
+ child[3] = PatchT::create(alloc,patches[3],edge,vertices,stride,depth+1,nullptr,nullptr,&border2r,&border3l);
+#else
+ GeneralCatmullClarkPatch::fix_quad_ring_order(patches);
+ for (size_t i=0; i<4; i++)
+ child[i] = PatchT::create(alloc,patches[i],edge,vertices,stride,depth+1);
+#endif
+ return SubdividedQuadPatch::create(alloc,child);
+ }
+ else
+ {
+ assert(N<MAX_PATCH_VALENCE);
+ Ref child[MAX_PATCH_VALENCE];
+
+#if PATCH_USE_GREGORY == 2
+ BezierCurve borders[GeneralCatmullClarkPatch::SIZE];
+ patch.getLimitBorder(borders);
+
+ for (size_t i0=0; i0<N; i0++) {
+ const size_t i2 = i0==0 ? N-1 : i0-1;
+ BezierCurve border0l,border0r; borders[i0].subdivide(border0l,border0r);
+ BezierCurve border2l,border2r; borders[i2].subdivide(border2l,border2r);
+ child[i0] = PatchT::create(alloc,patches[i0],edge,vertices,stride,depth+1, &border0l, nullptr, nullptr, &border2r);
+ }
+#else
+ for (size_t i=0; i<N; i++)
+ child[i] = PatchT::create(alloc,patches[i],edge,vertices,stride,depth+1);
+#endif
+ return SubdividedGeneralPatch::create(alloc,child,N);
+ }
+
+ return nullptr;
+ }
+
+ static __forceinline bool final(const CatmullClarkPatch& patch, const typename CatmullClarkRing::Type type, size_t depth)
+ {
+ const size_t max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
+//#if PATCH_MIN_RESOLUTION
+// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=max_eval_depth;
+//#else
+ return depth>=max_eval_depth;
+//#endif
+ }
+
+ template<typename Allocator>
+ __noinline static Ref create(const Allocator& alloc, CatmullClarkPatch& patch, const HalfEdge* edge, const char* vertices, size_t stride, size_t depth,
+ const BezierCurve* border0 = nullptr, const BezierCurve* border1 = nullptr, const BezierCurve* border2 = nullptr, const BezierCurve* border3 = nullptr)
+ {
+ const typename CatmullClarkPatch::Type ty = patch.type();
+ if (unlikely(final(patch,ty,depth))) {
+ if (ty & CatmullClarkRing::TYPE_REGULAR) return RegularPatch::create(alloc,patch,border0,border1,border2,border3);
+ else return IrregularFillPatch::create(alloc,patch,border0,border1,border2,border3);
+ }
+ else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
+ assert(depth > 0); return RegularPatch::create(alloc,patch,border0,border1,border2,border3);
+ }
+#if PATCH_USE_GREGORY == 2
+ else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
+ assert(depth > 0); return GregoryPatch::create(alloc,patch,border0,border1,border2,border3);
+ }
+#endif
+ else if (depth >= PATCH_MAX_CACHE_DEPTH) {
+ return EvalPatch::create(alloc,patch);
+ }
+
+ else
+ {
+ Ref child[4];
+ array_t<CatmullClarkPatch,4> patches;
+ patch.subdivide(patches);
+
+ for (size_t i=0; i<4; i++)
+ child[i] = PatchT::create(alloc,patches[i],edge,vertices,stride,depth+1);
+ return SubdividedQuadPatch::create(alloc,child);
+ }
+ }
+ };
+
+ typedef PatchT<Vec3fa,Vec3fa_t> Patch3fa;
+}
diff --git a/thirdparty/embree/kernels/subdiv/patch_eval.h b/thirdparty/embree/kernels/subdiv/patch_eval.h
new file mode 100644
index 0000000000..a3fafa72f4
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/patch_eval.h
@@ -0,0 +1,129 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "patch.h"
+#include "feature_adaptive_eval.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename Vertex, typename Vertex_t = Vertex>
+ struct PatchEval
+ {
+ public:
+
+ typedef PatchT<Vertex,Vertex_t> Patch;
+ typedef typename Patch::Ref Ref;
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+
+ PatchEval (SharedLazyTessellationCache::CacheEntry& entry, size_t commitCounter,
+ const HalfEdge* edge, const char* vertices, size_t stride, const float u, const float v,
+ Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv)
+ : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv)
+ {
+ /* conservative time for the very first allocation */
+ auto time = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
+
+ Ref patch = SharedLazyTessellationCache::lookup(entry,commitCounter,[&] () {
+ auto alloc = [&](size_t bytes) { return SharedLazyTessellationCache::malloc(bytes); };
+ return Patch::create(alloc,edge,vertices,stride);
+ },true);
+
+ auto curTime = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
+ const bool allAllocationsValid = SharedLazyTessellationCache::validTime(time,curTime);
+
+ if (patch && allAllocationsValid && eval(patch,u,v,1.0f,0)) {
+ SharedLazyTessellationCache::unlock();
+ return;
+ }
+ SharedLazyTessellationCache::unlock();
+ FeatureAdaptiveEval<Vertex,Vertex_t>(edge,vertices,stride,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv);
+ PATCH_DEBUG_SUBDIVISION(edge,c,-1,-1);
+ }
+
+ __forceinline bool eval_quad(const typename Patch::SubdividedQuadPatch* This, const float u, const float v, const float dscale, const size_t depth)
+ {
+ if (v < 0.5f) {
+ if (u < 0.5f) return eval(This->child[0],2.0f*u,2.0f*v,2.0f*dscale,depth+1);
+ else return eval(This->child[1],2.0f*u-1.0f,2.0f*v,2.0f*dscale,depth+1);
+ } else {
+ if (u > 0.5f) return eval(This->child[2],2.0f*u-1.0f,2.0f*v-1.0f,2.0f*dscale,depth+1);
+ else return eval(This->child[3],2.0f*u,2.0f*v-1.0f,2.0f*dscale,depth+1);
+ }
+ }
+
+ bool eval_general(const typename Patch::SubdividedGeneralPatch* This, const float U, const float V, const size_t depth)
+ {
+ const unsigned l = (unsigned) floor(0.5f*U); const float u = 2.0f*frac(0.5f*U)-0.5f;
+ const unsigned h = (unsigned) floor(0.5f*V); const float v = 2.0f*frac(0.5f*V)-0.5f;
+ const unsigned i = 4*h+l; assert(i<This->N);
+ return eval(This->child[i],u,v,1.0f,depth+1);
+ }
+
+ bool eval(Ref This, const float& u, const float& v, const float dscale, const size_t depth)
+ {
+ if (!This) return false;
+ //PRINT(depth);
+ //PRINT2(u,v);
+
+ switch (This.type())
+ {
+ case Patch::BILINEAR_PATCH: {
+ //PRINT("bilinear");
+ ((typename Patch::BilinearPatch*)This.object())->patch.eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
+ PATCH_DEBUG_SUBDIVISION(This,-1,c,c);
+ return true;
+ }
+ case Patch::BSPLINE_PATCH: {
+ //PRINT("bspline");
+ ((typename Patch::BSplinePatch*)This.object())->patch.eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
+ PATCH_DEBUG_SUBDIVISION(This,-1,c,-1);
+ return true;
+ }
+ case Patch::BEZIER_PATCH: {
+ //PRINT("bezier");
+ ((typename Patch::BezierPatch*)This.object())->patch.eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
+ PATCH_DEBUG_SUBDIVISION(This,-1,c,-1);
+ return true;
+ }
+ case Patch::GREGORY_PATCH: {
+ //PRINT("gregory");
+ ((typename Patch::GregoryPatch*)This.object())->patch.eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);
+ PATCH_DEBUG_SUBDIVISION(This,-1,-1,c);
+ return true;
+ }
+ case Patch::SUBDIVIDED_QUAD_PATCH: {
+ //PRINT("subdivided quad");
+ return eval_quad(((typename Patch::SubdividedQuadPatch*)This.object()),u,v,dscale,depth);
+ }
+ case Patch::SUBDIVIDED_GENERAL_PATCH: {
+ //PRINT("general_patch");
+ assert(dscale == 1.0f);
+ return eval_general(((typename Patch::SubdividedGeneralPatch*)This.object()),u,v,depth);
+ }
+ case Patch::EVAL_PATCH: {
+ //PRINT("eval_patch");
+ CatmullClarkPatch patch; patch.deserialize(This.object());
+ FeatureAdaptiveEval<Vertex,Vertex_t>(patch,u,v,dscale,depth,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv);
+ return true;
+ }
+ default:
+ assert(false);
+ return false;
+ }
+ }
+
+ private:
+ Vertex* const P;
+ Vertex* const dPdu;
+ Vertex* const dPdv;
+ Vertex* const ddPdudu;
+ Vertex* const ddPdvdv;
+ Vertex* const ddPdudv;
+ };
+ }
+}
+
diff --git a/thirdparty/embree/kernels/subdiv/patch_eval_grid.h b/thirdparty/embree/kernels/subdiv/patch_eval_grid.h
new file mode 100644
index 0000000000..167e1ebe1c
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/patch_eval_grid.h
@@ -0,0 +1,245 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "patch.h"
+#include "feature_adaptive_eval_grid.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ struct PatchEvalGrid
+ {
+ typedef Patch3fa Patch;
+ typedef Patch::Ref Ref;
+ typedef GeneralCatmullClarkPatch3fa GeneralCatmullClarkPatch;
+ typedef CatmullClarkPatch3fa CatmullClarkPatch;
+ typedef BSplinePatch3fa BSplinePatch;
+ typedef BezierPatch3fa BezierPatch;
+ typedef GregoryPatch3fa GregoryPatch;
+ typedef BilinearPatch3fa BilinearPatch;
+
+ private:
+ const unsigned x0,x1;
+ const unsigned y0,y1;
+ const unsigned swidth,sheight;
+ const float rcp_swidth, rcp_sheight;
+ float* const Px;
+ float* const Py;
+ float* const Pz;
+ float* const U;
+ float* const V;
+ float* const Nx;
+ float* const Ny;
+ float* const Nz;
+ const unsigned dwidth,dheight;
+ unsigned count;
+
+ public:
+
+ PatchEvalGrid (Ref patch, unsigned subPatch,
+ const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
+ float* Px, float* Py, float* Pz, float* U, float* V,
+ float* Nx, float* Ny, float* Nz,
+ const unsigned dwidth, const unsigned dheight)
+ : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
+ Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), dheight(dheight), count(0)
+ {
+ assert(swidth < (2<<20) && sheight < (2<<20));
+ const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(float(swidth-1),float(sheight-1)));
+ const BBox2f erange(Vec2f(float(x0),float(y0)),Vec2f((float)x1,(float)y1));
+ bool done MAYBE_UNUSED = eval(patch,subPatch,srange,erange);
+ assert(done);
+ assert(count == (x1-x0+1)*(y1-y0+1));
+ }
+
+ template<typename Patch>
+ __forceinline void evalLocalGrid(const Patch* patch, const BBox2f& srange, const int lx0, const int lx1, const int ly0, const int ly1)
+ {
+ const float scale_x = rcp(srange.upper.x-srange.lower.x);
+ const float scale_y = rcp(srange.upper.y-srange.lower.y);
+ count += (lx1-lx0)*(ly1-ly0);
+
+#if 0
+ for (unsigned iy=ly0; iy<ly1; iy++) {
+ for (unsigned ix=lx0; ix<lx1; ix++) {
+ const float lu = select(ix == swidth -1, float(1.0f), (float(ix)-srange.lower.x)*scale_x);
+ const float lv = select(iy == sheight-1, float(1.0f), (float(iy)-srange.lower.y)*scale_y);
+ const Vec3fa p = patch->patch.eval(lu,lv);
+ const float u = float(ix)*rcp_swidth;
+ const float v = float(iy)*rcp_sheight;
+ const int ofs = (iy-y0)*dwidth+(ix-x0);
+ Px[ofs] = p.x;
+ Py[ofs] = p.y;
+ Pz[ofs] = p.z;
+ U[ofs] = u;
+ V[ofs] = v;
+ }
+ }
+#else
+ foreach2(lx0,lx1,ly0,ly1,[&](const vboolx& valid, const vintx& ix, const vintx& iy) {
+ const vfloatx lu = select(ix == swidth -1, vfloatx(1.0f), (vfloatx(ix)-srange.lower.x)*scale_x);
+ const vfloatx lv = select(iy == sheight-1, vfloatx(1.0f), (vfloatx(iy)-srange.lower.y)*scale_y);
+ const Vec3vfx p = patch->patch.eval(lu,lv);
+ Vec3vfx n = zero;
+ if (unlikely(Nx != nullptr)) n = normalize_safe(patch->patch.normal(lu,lv));
+ const vfloatx u = vfloatx(ix)*rcp_swidth;
+ const vfloatx v = vfloatx(iy)*rcp_sheight;
+ const vintx ofs = (iy-y0)*dwidth+(ix-x0);
+ if (likely(all(valid)) && all(iy==iy[0])) {
+ const unsigned ofs2 = ofs[0];
+ vfloatx::storeu(Px+ofs2,p.x);
+ vfloatx::storeu(Py+ofs2,p.y);
+ vfloatx::storeu(Pz+ofs2,p.z);
+ vfloatx::storeu(U+ofs2,u);
+ vfloatx::storeu(V+ofs2,v);
+ if (unlikely(Nx != nullptr)) {
+ vfloatx::storeu(Nx+ofs2,n.x);
+ vfloatx::storeu(Ny+ofs2,n.y);
+ vfloatx::storeu(Nz+ofs2,n.z);
+ }
+ } else {
+ foreach_unique_index(valid,iy,[&](const vboolx& valid, const int iy0, const int j) {
+ const unsigned ofs2 = ofs[j]-j;
+ vfloatx::storeu(valid,Px+ofs2,p.x);
+ vfloatx::storeu(valid,Py+ofs2,p.y);
+ vfloatx::storeu(valid,Pz+ofs2,p.z);
+ vfloatx::storeu(valid,U+ofs2,u);
+ vfloatx::storeu(valid,V+ofs2,v);
+ if (unlikely(Nx != nullptr)) {
+ vfloatx::storeu(valid,Nx+ofs2,n.x);
+ vfloatx::storeu(valid,Ny+ofs2,n.y);
+ vfloatx::storeu(valid,Nz+ofs2,n.z);
+ }
+ });
+ }
+ });
+#endif
+ }
+
+ bool eval(Ref This, const BBox2f& srange, const BBox2f& erange, const unsigned depth)
+ {
+ if (erange.empty())
+ return true;
+
+ const int lx0 = (int) ceilf(erange.lower.x);
+ const int lx1 = (int) ceilf(erange.upper.x) + (erange.upper.x == x1 && (srange.lower.x < erange.upper.x || erange.upper.x == 0));
+ const int ly0 = (int) ceilf(erange.lower.y);
+ const int ly1 = (int) ceilf(erange.upper.y) + (erange.upper.y == y1 && (srange.lower.y < erange.upper.y || erange.upper.y == 0));
+ if (lx0 >= lx1 || ly0 >= ly1)
+ return true;
+
+ if (!This)
+ return false;
+
+ switch (This.type())
+ {
+ case Patch::BILINEAR_PATCH: {
+ evalLocalGrid((Patch::BilinearPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
+ return true;
+ }
+ case Patch::BSPLINE_PATCH: {
+ evalLocalGrid((Patch::BSplinePatch*)This.object(),srange,lx0,lx1,ly0,ly1);
+ return true;
+ }
+ case Patch::BEZIER_PATCH: {
+ evalLocalGrid((Patch::BezierPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
+ return true;
+ }
+ case Patch::GREGORY_PATCH: {
+ evalLocalGrid((Patch::GregoryPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
+ return true;
+ }
+ case Patch::SUBDIVIDED_QUAD_PATCH:
+ {
+ const Vec2f c = srange.center();
+ const BBox2f srange0(srange.lower,c);
+ const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
+ const BBox2f srange2(c,srange.upper);
+ const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
+
+ Patch::SubdividedQuadPatch* patch = (Patch::SubdividedQuadPatch*)This.object();
+ eval(patch->child[0],srange0,intersect(srange0,erange),depth+1);
+ eval(patch->child[1],srange1,intersect(srange1,erange),depth+1);
+ eval(patch->child[2],srange2,intersect(srange2,erange),depth+1);
+ eval(patch->child[3],srange3,intersect(srange3,erange),depth+1);
+ return true;
+ }
+ case Patch::EVAL_PATCH: {
+ CatmullClarkPatch patch; patch.deserialize(This.object());
+ FeatureAdaptiveEvalGrid(patch,srange,erange,depth,x0,x1,y0,y1,swidth,sheight,Px,Py,Pz,U,V,Nx,Ny,Nz,dwidth,dheight);
+ count += (lx1-lx0)*(ly1-ly0);
+ return true;
+ }
+ default:
+ assert(false);
+ return false;
+ }
+ }
+
+ bool eval(Ref This, unsigned subPatch, const BBox2f& srange, const BBox2f& erange)
+ {
+ if (!This)
+ return false;
+
+ switch (This.type())
+ {
+ case Patch::SUBDIVIDED_GENERAL_PATCH: {
+ Patch::SubdividedGeneralPatch* patch = (Patch::SubdividedGeneralPatch*)This.object();
+ assert(subPatch < patch->N);
+ return eval(patch->child[subPatch],srange,erange,1);
+ }
+ default:
+ assert(subPatch == 0);
+ return eval(This,srange,erange,0);
+ }
+ }
+ };
+
+ __forceinline unsigned patch_eval_subdivision_count (const HalfEdge* h)
+ {
+ const unsigned N = h->numEdges();
+ if (N == 4) return 1;
+ else return N;
+ }
+
+ template<typename Tessellator>
+ inline void patch_eval_subdivision (const HalfEdge* h, Tessellator tessellator)
+ {
+ const unsigned N = h->numEdges();
+ int neighborSubdiv[GeneralCatmullClarkPatch3fa::SIZE]; // FIXME: use array_t
+ float levels[GeneralCatmullClarkPatch3fa::SIZE];
+ for (unsigned i=0; i<N; i++) {
+ assert(i<GeneralCatmullClarkPatch3fa::SIZE);
+ neighborSubdiv[i] = h->hasOpposite() ? h->opposite()->numEdges() != 4 : 0;
+ levels[i] = h->edge_level;
+ h = h->next();
+ }
+ if (N == 4)
+ {
+ const Vec2f uv[4] = { Vec2f(0.0f,0.0f), Vec2f(1.0f,0.0f), Vec2f(1.0f,1.0f), Vec2f(0.0f,1.0f) };
+ tessellator(uv,neighborSubdiv,levels,0);
+ }
+ else
+ {
+ for (unsigned i=0; i<N; i++)
+ {
+ assert(i<MAX_PATCH_VALENCE);
+ static_assert(MAX_PATCH_VALENCE <= 16, "MAX_PATCH_VALENCE > 16");
+ const int h = (i >> 2) & 3, l = i & 3;
+ const Vec2f subPatchID((float)l,(float)h);
+ const Vec2f uv[4] = { 2.0f*subPatchID + (0.5f+Vec2f(0.0f,0.0f)),
+ 2.0f*subPatchID + (0.5f+Vec2f(1.0f,0.0f)),
+ 2.0f*subPatchID + (0.5f+Vec2f(1.0f,1.0f)),
+ 2.0f*subPatchID + (0.5f+Vec2f(0.0f,1.0f)) };
+ const int neighborSubdiv1[4] = { 0,0,0,0 };
+ const float levels1[4] = { 0.5f*levels[(i+0)%N], 0.5f*levels[(i+0)%N], 0.5f*levels[(i+N-1)%N], 0.5f*levels[(i+N-1)%N] };
+ tessellator(uv,neighborSubdiv1,levels1,i);
+ }
+ }
+ }
+ }
+}
+
diff --git a/thirdparty/embree/kernels/subdiv/patch_eval_simd.h b/thirdparty/embree/kernels/subdiv/patch_eval_simd.h
new file mode 100644
index 0000000000..fef88a4492
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/patch_eval_simd.h
@@ -0,0 +1,127 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "patch.h"
+#include "feature_adaptive_eval_simd.h"
+
+namespace embree
+{
+ namespace isa
+ {
+ template<typename vbool, typename vint, typename vfloat, typename Vertex, typename Vertex_t = Vertex>
+ struct PatchEvalSimd
+ {
+ public:
+
+ typedef PatchT<Vertex,Vertex_t> Patch;
+ typedef typename Patch::Ref Ref;
+ typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
+
+ PatchEvalSimd (SharedLazyTessellationCache::CacheEntry& entry, size_t commitCounter,
+ const HalfEdge* edge, const char* vertices, size_t stride, const vbool& valid0, const vfloat& u, const vfloat& v,
+ float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, const size_t dstride, const size_t N)
+ : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv), dstride(dstride), N(N)
+ {
+ /* conservative time for the very first allocation */
+ auto time = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
+
+ Ref patch = SharedLazyTessellationCache::lookup(entry,commitCounter,[&] () {
+ auto alloc = [](size_t bytes) { return SharedLazyTessellationCache::malloc(bytes); };
+ return Patch::create(alloc,edge,vertices,stride);
+ }, true);
+
+ auto curTime = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
+ const bool allAllocationsValid = SharedLazyTessellationCache::validTime(time,curTime);
+
+ patch = allAllocationsValid ? patch : nullptr;
+
+ /* use cached data structure for calculations */
+ const vbool valid1 = patch ? eval(valid0,patch,u,v,1.0f,0) : vbool(false);
+ SharedLazyTessellationCache::unlock();
+ const vbool valid2 = valid0 & !valid1;
+ if (any(valid2)) {
+ FeatureAdaptiveEvalSimd<vbool,vint,vfloat,Vertex,Vertex_t>(edge,vertices,stride,valid2,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dstride,N);
+ }
+ }
+
+ vbool eval_quad(const vbool& valid, const typename Patch::SubdividedQuadPatch* This, const vfloat& u, const vfloat& v, const float dscale, const size_t depth)
+ {
+ vbool ret = false;
+ const vbool u0_mask = u < 0.5f, u1_mask = u >= 0.5f;
+ const vbool v0_mask = v < 0.5f, v1_mask = v >= 0.5f;
+ const vbool u0v0_mask = valid & u0_mask & v0_mask;
+ const vbool u0v1_mask = valid & u0_mask & v1_mask;
+ const vbool u1v0_mask = valid & u1_mask & v0_mask;
+ const vbool u1v1_mask = valid & u1_mask & v1_mask;
+ if (any(u0v0_mask)) ret |= eval(u0v0_mask,This->child[0],2.0f*u,2.0f*v,2.0f*dscale,depth+1);
+ if (any(u1v0_mask)) ret |= eval(u1v0_mask,This->child[1],2.0f*u-1.0f,2.0f*v,2.0f*dscale,depth+1);
+ if (any(u1v1_mask)) ret |= eval(u1v1_mask,This->child[2],2.0f*u-1.0f,2.0f*v-1.0f,2.0f*dscale,depth+1);
+ if (any(u0v1_mask)) ret |= eval(u0v1_mask,This->child[3],2.0f*u,2.0f*v-1.0f,2.0f*dscale,depth+1);
+ return ret;
+ }
+
+ vbool eval_general(const vbool& valid, const typename Patch::SubdividedGeneralPatch* patch, const vfloat& U, const vfloat& V, const size_t depth)
+ {
+ vbool ret = false;
+ const vint l = (vint)floor(0.5f*U); const vfloat u = 2.0f*frac(0.5f*U)-0.5f;
+ const vint h = (vint)floor(0.5f*V); const vfloat v = 2.0f*frac(0.5f*V)-0.5f;
+ const vint i = (h<<2)+l; assert(all(valid,i<patch->N));
+ foreach_unique(valid,i,[&](const vbool& valid, const int i) {
+ ret |= eval(valid,patch->child[i],u,v,1.0f,depth+1);
+ });
+ return ret;
+ }
+
+ vbool eval(const vbool& valid, Ref This, const vfloat& u, const vfloat& v, const float dscale, const size_t depth)
+ {
+ if (!This) return false;
+ switch (This.type())
+ {
+ case Patch::BILINEAR_PATCH: {
+ ((typename Patch::BilinearPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ return valid;
+ }
+ case Patch::BSPLINE_PATCH: {
+ ((typename Patch::BSplinePatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ return valid;
+ }
+ case Patch::BEZIER_PATCH: {
+ ((typename Patch::BezierPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ return valid;
+ }
+ case Patch::GREGORY_PATCH: {
+ ((typename Patch::GregoryPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
+ return valid;
+ }
+ case Patch::SUBDIVIDED_QUAD_PATCH: {
+ return eval_quad(valid,((typename Patch::SubdividedQuadPatch*)This.object()),u,v,dscale,depth);
+ }
+ case Patch::SUBDIVIDED_GENERAL_PATCH: {
+ assert(dscale == 1.0f);
+ return eval_general(valid,((typename Patch::SubdividedGeneralPatch*)This.object()),u,v,depth);
+ }
+ case Patch::EVAL_PATCH: {
+ CatmullClarkPatch patch; patch.deserialize(This.object());
+ FeatureAdaptiveEvalSimd<vbool,vint,vfloat,Vertex,Vertex_t>(patch,valid,u,v,dscale,depth,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dstride,N);
+ return valid;
+ }
+ default:
+ assert(false);
+ return false;
+ }
+ }
+
+ private:
+ float* const P;
+ float* const dPdu;
+ float* const dPdv;
+ float* const ddPdudu;
+ float* const ddPdvdv;
+ float* const ddPdudv;
+ const size_t dstride;
+ const size_t N;
+ };
+ }
+}
diff --git a/thirdparty/embree/kernels/subdiv/subdivpatch1base.h b/thirdparty/embree/kernels/subdiv/subdivpatch1base.h
new file mode 100644
index 0000000000..c3069dadee
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/subdivpatch1base.h
@@ -0,0 +1,156 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../geometry/primitive.h"
+#include "bspline_patch.h"
+#include "bezier_patch.h"
+#include "gregory_patch.h"
+#include "gregory_patch_dense.h"
+#include "tessellation.h"
+#include "tessellation_cache.h"
+#include "gridrange.h"
+#include "patch_eval_grid.h"
+#include "feature_adaptive_eval_grid.h"
+#include "../common/scene_subdiv_mesh.h"
+
+namespace embree
+{
+ struct __aligned(64) SubdivPatch1Base
+ {
+ public:
+
+ enum Type {
+ INVALID_PATCH = 0,
+ BSPLINE_PATCH = 1,
+ BEZIER_PATCH = 2,
+ GREGORY_PATCH = 3,
+ EVAL_PATCH = 5,
+ BILINEAR_PATCH = 6,
+ };
+
+ enum Flags {
+ TRANSITION_PATCH = 16,
+ };
+
+ /*! Default constructor. */
+ __forceinline SubdivPatch1Base () {}
+
+ SubdivPatch1Base (const unsigned int gID,
+ const unsigned int pID,
+ const unsigned int subPatch,
+ const SubdivMesh *const mesh,
+ const size_t time,
+ const Vec2f uv[4],
+ const float edge_level[4],
+ const int subdiv[4],
+ const int simd_width);
+
+ __forceinline bool needsStitching() const {
+ return flags & TRANSITION_PATCH;
+ }
+
+ __forceinline Vec2f getUV(const size_t i) const {
+ return Vec2f((float)u[i],(float)v[i]) * (8.0f/0x10000);
+ }
+
+ static void computeEdgeLevels(const float edge_level[4], const int subdiv[4], float level[4]);
+ static Vec2i computeGridSize(const float level[4]);
+ bool updateEdgeLevels(const float edge_level[4], const int subdiv[4], const SubdivMesh *const mesh, const int simd_width);
+
+ public:
+
+ __forceinline size_t getGridBytes() const {
+ const size_t grid_size_xyzuv = (grid_size_simd_blocks * VSIZEX) * 4;
+ return 64*((grid_size_xyzuv+15) / 16);
+ }
+
+ __forceinline void write_lock() { mtx.lock(); }
+ __forceinline void write_unlock() { mtx.unlock(); }
+ __forceinline bool try_write_lock() { return mtx.try_lock(); }
+ //__forceinline bool try_read_lock() { return mtx.try_read_lock(); }
+
+ __forceinline void resetRootRef() {
+ //assert( mtx.hasInitialState() );
+ root_ref = SharedLazyTessellationCache::Tag();
+ }
+
+ __forceinline SharedLazyTessellationCache::CacheEntry& entry() {
+ return (SharedLazyTessellationCache::CacheEntry&) root_ref;
+ }
+
+ public:
+ __forceinline unsigned int geomID() const {
+ return geom;
+ }
+
+ __forceinline unsigned int primID() const {
+ return prim;
+ }
+
+ public:
+ SharedLazyTessellationCache::Tag root_ref;
+ SpinLock mtx;
+
+ unsigned short u[4]; //!< 16bit discretized u,v coordinates
+ unsigned short v[4];
+ float level[4];
+
+ unsigned char flags;
+ unsigned char type;
+ unsigned short grid_u_res;
+ unsigned int geom; //!< geometry ID of the subdivision mesh this patch belongs to
+ unsigned int prim; //!< primitive ID of this subdivision patch
+ unsigned short grid_v_res;
+
+ unsigned short grid_size_simd_blocks;
+ unsigned int time_;
+
+ struct PatchHalfEdge {
+ const HalfEdge* edge;
+ unsigned subPatch;
+ };
+
+ Vec3fa patch_v[4][4];
+
+ const HalfEdge *edge() const { return ((PatchHalfEdge*)patch_v)->edge; }
+ unsigned time() const { return time_; }
+ unsigned subPatch() const { return ((PatchHalfEdge*)patch_v)->subPatch; }
+
+ void set_edge(const HalfEdge *h) const { ((PatchHalfEdge*)patch_v)->edge = h; }
+ void set_subPatch(const unsigned s) const { ((PatchHalfEdge*)patch_v)->subPatch = s; }
+ };
+
+ namespace isa
+ {
+ Vec3fa patchEval(const SubdivPatch1Base& patch, const float uu, const float vv);
+ Vec3fa patchNormal(const SubdivPatch1Base& patch, const float uu, const float vv);
+
+ template<typename simdf>
+ Vec3<simdf> patchEval(const SubdivPatch1Base& patch, const simdf& uu, const simdf& vv);
+
+ template<typename simdf>
+ Vec3<simdf> patchNormal(const SubdivPatch1Base& patch, const simdf& uu, const simdf& vv);
+
+
+ /* eval grid over patch and stich edges when required */
+ void evalGrid(const SubdivPatch1Base& patch,
+ const unsigned x0, const unsigned x1,
+ const unsigned y0, const unsigned y1,
+ const unsigned swidth, const unsigned sheight,
+ float *__restrict__ const grid_x,
+ float *__restrict__ const grid_y,
+ float *__restrict__ const grid_z,
+ float *__restrict__ const grid_u,
+ float *__restrict__ const grid_v,
+ const SubdivMesh* const geom);
+
+ /* eval grid over patch and stich edges when required */
+ BBox3fa evalGridBounds(const SubdivPatch1Base& patch,
+ const unsigned x0, const unsigned x1,
+ const unsigned y0, const unsigned y1,
+ const unsigned swidth, const unsigned sheight,
+ const SubdivMesh* const geom);
+ }
+}
diff --git a/thirdparty/embree/kernels/subdiv/tessellation.h b/thirdparty/embree/kernels/subdiv/tessellation.h
new file mode 100644
index 0000000000..abde4f2bde
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/tessellation.h
@@ -0,0 +1,161 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+namespace embree
+{
+ /* adjust discret tessellation level for feature-adaptive pre-subdivision */
+ __forceinline float adjustTessellationLevel(float l, const size_t sublevel)
+ {
+ for (size_t i=0; i<sublevel; i++) l *= 0.5f;
+ float r = ceilf(l);
+ for (size_t i=0; i<sublevel; i++) r *= 2.0f;
+ return r;
+ }
+
+ __forceinline int stitch(const int x, const int fine, const int coarse) {
+ return (2*x+1)*coarse/(2*fine);
+ }
+
+ __forceinline void stitchGridEdges(const unsigned int low_rate,
+ const unsigned int high_rate,
+ const unsigned int x0,
+ const unsigned int x1,
+ float * __restrict__ const uv_array,
+ const unsigned int uv_array_step)
+ {
+#if 1
+ const float inv_low_rate = rcp((float)(low_rate-1));
+ for (unsigned x=x0; x<=x1; x++) {
+ uv_array[(x-x0)*uv_array_step] = float(stitch(x,high_rate-1,low_rate-1))*inv_low_rate;
+ }
+ if (unlikely(x1 == high_rate-1))
+ uv_array[(x1-x0)*uv_array_step] = 1.0f;
+#else
+ assert(low_rate < high_rate);
+ assert(high_rate >= 2);
+
+ const float inv_low_rate = rcp((float)(low_rate-1));
+ const unsigned int dy = low_rate - 1;
+ const unsigned int dx = high_rate - 1;
+
+ int p = 2*dy-dx;
+
+ unsigned int offset = 0;
+ unsigned int y = 0;
+ float value = 0.0f;
+ for(unsigned int x=0;x<high_rate-1; x++) // '<=' would be correct but we will leave the 1.0f at the end
+ {
+ uv_array[offset] = value;
+
+ offset += uv_array_step;
+ if (unlikely(p > 0))
+ {
+ y++;
+ value = (float)y * inv_low_rate;
+ p -= 2*dx;
+ }
+ p += 2*dy;
+ }
+#endif
+ }
+
+ __forceinline void stitchUVGrid(const float edge_levels[4],
+ const unsigned int swidth,
+ const unsigned int sheight,
+ const unsigned int x0,
+ const unsigned int y0,
+ const unsigned int grid_u_res,
+ const unsigned int grid_v_res,
+ float * __restrict__ const u_array,
+ float * __restrict__ const v_array)
+ {
+ const unsigned int x1 = x0+grid_u_res-1;
+ const unsigned int y1 = y0+grid_v_res-1;
+ const unsigned int int_edge_points0 = (unsigned int)edge_levels[0] + 1;
+ const unsigned int int_edge_points1 = (unsigned int)edge_levels[1] + 1;
+ const unsigned int int_edge_points2 = (unsigned int)edge_levels[2] + 1;
+ const unsigned int int_edge_points3 = (unsigned int)edge_levels[3] + 1;
+
+ if (unlikely(y0 == 0 && int_edge_points0 < swidth))
+ stitchGridEdges(int_edge_points0,swidth,x0,x1,u_array,1);
+
+ if (unlikely(y1 == sheight-1 && int_edge_points2 < swidth))
+ stitchGridEdges(int_edge_points2,swidth,x0,x1,&u_array[(grid_v_res-1)*grid_u_res],1);
+
+ if (unlikely(x0 == 0 && int_edge_points1 < sheight))
+ stitchGridEdges(int_edge_points1,sheight,y0,y1,&v_array[grid_u_res-1],grid_u_res);
+
+ if (unlikely(x1 == swidth-1 && int_edge_points3 < sheight))
+ stitchGridEdges(int_edge_points3,sheight,y0,y1,v_array,grid_u_res);
+ }
+
+ __forceinline void gridUVTessellator(const float edge_levels[4],
+ const unsigned int swidth,
+ const unsigned int sheight,
+ const unsigned int x0,
+ const unsigned int y0,
+ const unsigned int grid_u_res,
+ const unsigned int grid_v_res,
+ float * __restrict__ const u_array,
+ float * __restrict__ const v_array)
+ {
+ assert( grid_u_res >= 1);
+ assert( grid_v_res >= 1);
+ assert( edge_levels[0] >= 1.0f );
+ assert( edge_levels[1] >= 1.0f );
+ assert( edge_levels[2] >= 1.0f );
+ assert( edge_levels[3] >= 1.0f );
+
+#if defined(__AVX__)
+ const vint8 grid_u_segments = vint8(swidth)-1;
+ const vint8 grid_v_segments = vint8(sheight)-1;
+
+ const vfloat8 inv_grid_u_segments = rcp(vfloat8(grid_u_segments));
+ const vfloat8 inv_grid_v_segments = rcp(vfloat8(grid_v_segments));
+
+ unsigned int index = 0;
+ vint8 v_i( zero );
+ for (unsigned int y=0;y<grid_v_res;y++,index+=grid_u_res,v_i += 1)
+ {
+ vint8 u_i ( step );
+
+ const vbool8 m_v = v_i < grid_v_segments;
+
+ for (unsigned int x=0;x<grid_u_res;x+=8, u_i += 8)
+ {
+ const vbool8 m_u = u_i < grid_u_segments;
+ const vfloat8 u = select(m_u, vfloat8(x0+u_i) * inv_grid_u_segments, 1.0f);
+ const vfloat8 v = select(m_v, vfloat8(y0+v_i) * inv_grid_v_segments, 1.0f);
+ vfloat8::storeu(&u_array[index + x],u);
+ vfloat8::storeu(&v_array[index + x],v);
+ }
+ }
+ #else
+ const vint4 grid_u_segments = vint4(swidth)-1;
+ const vint4 grid_v_segments = vint4(sheight)-1;
+
+ const vfloat4 inv_grid_u_segments = rcp(vfloat4(grid_u_segments));
+ const vfloat4 inv_grid_v_segments = rcp(vfloat4(grid_v_segments));
+
+ unsigned int index = 0;
+ vint4 v_i( zero );
+ for (unsigned int y=0;y<grid_v_res;y++,index+=grid_u_res,v_i += 1)
+ {
+ vint4 u_i ( step );
+
+ const vbool4 m_v = v_i < grid_v_segments;
+
+ for (unsigned int x=0;x<grid_u_res;x+=4, u_i += 4)
+ {
+ const vbool4 m_u = u_i < grid_u_segments;
+ const vfloat4 u = select(m_u, vfloat4(x0+u_i) * inv_grid_u_segments, 1.0f);
+ const vfloat4 v = select(m_v, vfloat4(y0+v_i) * inv_grid_v_segments, 1.0f);
+ vfloat4::storeu(&u_array[index + x],u);
+ vfloat4::storeu(&v_array[index + x],v);
+ }
+ }
+#endif
+ }
+}
diff --git a/thirdparty/embree/kernels/subdiv/tessellation_cache.h b/thirdparty/embree/kernels/subdiv/tessellation_cache.h
new file mode 100644
index 0000000000..99edf49be4
--- /dev/null
+++ b/thirdparty/embree/kernels/subdiv/tessellation_cache.h
@@ -0,0 +1,325 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "../common/default.h"
+
+/* force a complete cache invalidation when running out of allocation space */
+#define FORCE_SIMPLE_FLUSH 0
+
+#define THREAD_BLOCK_ATOMIC_ADD 4
+
+#if defined(DEBUG)
+#define CACHE_STATS(x)
+#else
+#define CACHE_STATS(x)
+#endif
+
+namespace embree
+{
+ class SharedTessellationCacheStats
+ {
+ public:
+ /* stats */
+ static std::atomic<size_t> cache_accesses;
+ static std::atomic<size_t> cache_hits;
+ static std::atomic<size_t> cache_misses;
+ static std::atomic<size_t> cache_flushes;
+ static size_t cache_num_patches;
+ __aligned(64) static SpinLock mtx;
+
+ /* print stats for debugging */
+ static void printStats();
+ static void clearStats();
+ };
+
+ void resizeTessellationCache(size_t new_size);
+ void resetTessellationCache();
+
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct __aligned(64) ThreadWorkState
+ {
+ ALIGNED_STRUCT_(64);
+
+ std::atomic<size_t> counter;
+ ThreadWorkState* next;
+ bool allocated;
+
+ __forceinline ThreadWorkState(bool allocated = false)
+ : counter(0), next(nullptr), allocated(allocated)
+ {
+ assert( ((size_t)this % 64) == 0 );
+ }
+ };
+
+ class __aligned(64) SharedLazyTessellationCache
+ {
+ public:
+
+ static const size_t NUM_CACHE_SEGMENTS = 8;
+ static const size_t NUM_PREALLOC_THREAD_WORK_STATES = 512;
+ static const size_t COMMIT_INDEX_SHIFT = 32+8;
+#if defined(__64BIT__)
+ static const size_t REF_TAG_MASK = 0xffffffffff;
+#else
+ static const size_t REF_TAG_MASK = 0x7FFFFFFF;
+#endif
+ static const size_t MAX_TESSELLATION_CACHE_SIZE = REF_TAG_MASK+1;
+ static const size_t BLOCK_SIZE = 64;
+
+
+ /*! Per thread tessellation ref cache */
+ static __thread ThreadWorkState* init_t_state;
+ static ThreadWorkState* current_t_state;
+
+ static __forceinline ThreadWorkState *threadState()
+ {
+ if (unlikely(!init_t_state))
+ /* sets init_t_state, can't return pointer due to macosx icc bug*/
+ SharedLazyTessellationCache::sharedLazyTessellationCache.getNextRenderThreadWorkState();
+ return init_t_state;
+ }
+
+ struct Tag
+ {
+ __forceinline Tag() : data(0) {}
+
+ __forceinline Tag(void* ptr, size_t combinedTime) {
+ init(ptr,combinedTime);
+ }
+
+ __forceinline Tag(size_t ptr, size_t combinedTime) {
+ init((void*)ptr,combinedTime);
+ }
+
+ __forceinline void init(void* ptr, size_t combinedTime)
+ {
+ if (ptr == nullptr) {
+ data = 0;
+ return;
+ }
+ int64_t new_root_ref = (int64_t) ptr;
+ new_root_ref -= (int64_t)SharedLazyTessellationCache::sharedLazyTessellationCache.getDataPtr();
+ assert( new_root_ref <= (int64_t)REF_TAG_MASK );
+ new_root_ref |= (int64_t)combinedTime << COMMIT_INDEX_SHIFT;
+ data = new_root_ref;
+ }
+
+ __forceinline int64_t get() const { return data.load(); }
+ __forceinline void set( int64_t v ) { data.store(v); }
+ __forceinline void reset() { data.store(0); }
+
+ private:
+ atomic<int64_t> data;
+ };
+
+ static __forceinline size_t extractCommitIndex(const int64_t v) { return v >> SharedLazyTessellationCache::COMMIT_INDEX_SHIFT; }
+
+ struct CacheEntry
+ {
+ Tag tag;
+ SpinLock mutex;
+ };
+
+ private:
+
+ float *data;
+ bool hugepages;
+ size_t size;
+ size_t maxBlocks;
+ ThreadWorkState *threadWorkState;
+
+ __aligned(64) std::atomic<size_t> localTime;
+ __aligned(64) std::atomic<size_t> next_block;
+ __aligned(64) SpinLock reset_state;
+ __aligned(64) SpinLock linkedlist_mtx;
+ __aligned(64) std::atomic<size_t> switch_block_threshold;
+ __aligned(64) std::atomic<size_t> numRenderThreads;
+
+
+ public:
+
+
+ SharedLazyTessellationCache();
+ ~SharedLazyTessellationCache();
+
+ void getNextRenderThreadWorkState();
+
+ __forceinline size_t maxAllocSize() const {
+ return switch_block_threshold;
+ }
+
+ __forceinline size_t getCurrentIndex() { return localTime.load(); }
+ __forceinline void addCurrentIndex(const size_t i=1) { localTime.fetch_add(i); }
+
+ __forceinline size_t getTime(const size_t globalTime) {
+ return localTime.load()+NUM_CACHE_SEGMENTS*globalTime;
+ }
+
+
+ __forceinline size_t lockThread (ThreadWorkState *const t_state, const ssize_t plus=1) { return t_state->counter.fetch_add(plus); }
+ __forceinline size_t unlockThread(ThreadWorkState *const t_state, const ssize_t plus=-1) { assert(isLocked(t_state)); return t_state->counter.fetch_add(plus); }
+
+ __forceinline bool isLocked(ThreadWorkState *const t_state) { return t_state->counter.load() != 0; }
+
+ static __forceinline void lock () { sharedLazyTessellationCache.lockThread(threadState()); }
+ static __forceinline void unlock() { sharedLazyTessellationCache.unlockThread(threadState()); }
+ static __forceinline bool isLocked() { return sharedLazyTessellationCache.isLocked(threadState()); }
+ static __forceinline size_t getState() { return threadState()->counter.load(); }
+ static __forceinline void lockThreadLoop() { sharedLazyTessellationCache.lockThreadLoop(threadState()); }
+
+ static __forceinline size_t getTCacheTime(const size_t globalTime) {
+ return sharedLazyTessellationCache.getTime(globalTime);
+ }
+
+ /* per thread lock */
+ __forceinline void lockThreadLoop (ThreadWorkState *const t_state)
+ {
+ while(1)
+ {
+ size_t lock = SharedLazyTessellationCache::sharedLazyTessellationCache.lockThread(t_state,1);
+ if (unlikely(lock >= THREAD_BLOCK_ATOMIC_ADD))
+ {
+ /* lock failed wait until sync phase is over */
+ sharedLazyTessellationCache.unlockThread(t_state,-1);
+ sharedLazyTessellationCache.waitForUsersLessEqual(t_state,0);
+ }
+ else
+ break;
+ }
+ }
+
+ static __forceinline void* lookup(CacheEntry& entry, size_t globalTime)
+ {
+ const int64_t subdiv_patch_root_ref = entry.tag.get();
+ CACHE_STATS(SharedTessellationCacheStats::cache_accesses++);
+
+ if (likely(subdiv_patch_root_ref != 0))
+ {
+ const size_t subdiv_patch_root = (subdiv_patch_root_ref & REF_TAG_MASK) + (size_t)sharedLazyTessellationCache.getDataPtr();
+ const size_t subdiv_patch_cache_index = extractCommitIndex(subdiv_patch_root_ref);
+
+ if (likely( sharedLazyTessellationCache.validCacheIndex(subdiv_patch_cache_index,globalTime) ))
+ {
+ CACHE_STATS(SharedTessellationCacheStats::cache_hits++);
+ return (void*) subdiv_patch_root;
+ }
+ }
+ CACHE_STATS(SharedTessellationCacheStats::cache_misses++);
+ return nullptr;
+ }
+
+ template<typename Constructor>
+ static __forceinline auto lookup (CacheEntry& entry, size_t globalTime, const Constructor constructor, const bool before=false) -> decltype(constructor())
+ {
+ ThreadWorkState *t_state = SharedLazyTessellationCache::threadState();
+
+ while (true)
+ {
+ sharedLazyTessellationCache.lockThreadLoop(t_state);
+ void* patch = SharedLazyTessellationCache::lookup(entry,globalTime);
+ if (patch) return (decltype(constructor())) patch;
+
+ if (entry.mutex.try_lock())
+ {
+ if (!validTag(entry.tag,globalTime))
+ {
+ auto timeBefore = sharedLazyTessellationCache.getTime(globalTime);
+ auto ret = constructor(); // thread is locked here!
+ assert(ret);
+ /* this should never return nullptr */
+ auto timeAfter = sharedLazyTessellationCache.getTime(globalTime);
+ auto time = before ? timeBefore : timeAfter;
+ __memory_barrier();
+ entry.tag = SharedLazyTessellationCache::Tag(ret,time);
+ __memory_barrier();
+ entry.mutex.unlock();
+ return ret;
+ }
+ entry.mutex.unlock();
+ }
+ SharedLazyTessellationCache::sharedLazyTessellationCache.unlockThread(t_state);
+ }
+ }
+
+ __forceinline bool validCacheIndex(const size_t i, const size_t globalTime)
+ {
+#if FORCE_SIMPLE_FLUSH == 1
+ return i == getTime(globalTime);
+#else
+ return i+(NUM_CACHE_SEGMENTS-1) >= getTime(globalTime);
+#endif
+ }
+
+ static __forceinline bool validTime(const size_t oldtime, const size_t newTime)
+ {
+ return oldtime+(NUM_CACHE_SEGMENTS-1) >= newTime;
+ }
+
+
+ static __forceinline bool validTag(const Tag& tag, size_t globalTime)
+ {
+ const int64_t subdiv_patch_root_ref = tag.get();
+ if (subdiv_patch_root_ref == 0) return false;
+ const size_t subdiv_patch_cache_index = extractCommitIndex(subdiv_patch_root_ref);
+ return sharedLazyTessellationCache.validCacheIndex(subdiv_patch_cache_index,globalTime);
+ }
+
+ void waitForUsersLessEqual(ThreadWorkState *const t_state,
+ const unsigned int users);
+
+ __forceinline size_t alloc(const size_t blocks)
+ {
+ if (unlikely(blocks >= switch_block_threshold))
+ throw_RTCError(RTC_ERROR_INVALID_OPERATION,"allocation exceeds size of tessellation cache segment");
+
+ assert(blocks < switch_block_threshold);
+ size_t index = next_block.fetch_add(blocks);
+ if (unlikely(index + blocks >= switch_block_threshold)) return (size_t)-1;
+ return index;
+ }
+
+ static __forceinline void* malloc(const size_t bytes)
+ {
+ size_t block_index = -1;
+ ThreadWorkState *const t_state = threadState();
+ while (true)
+ {
+ block_index = sharedLazyTessellationCache.alloc((bytes+BLOCK_SIZE-1)/BLOCK_SIZE);
+ if (block_index == (size_t)-1)
+ {
+ sharedLazyTessellationCache.unlockThread(t_state);
+ sharedLazyTessellationCache.allocNextSegment();
+ sharedLazyTessellationCache.lockThread(t_state);
+ continue;
+ }
+ break;
+ }
+ return sharedLazyTessellationCache.getBlockPtr(block_index);
+ }
+
+ __forceinline void *getBlockPtr(const size_t block_index)
+ {
+ assert(block_index < maxBlocks);
+ assert(data);
+ assert(block_index*16 <= size);
+ return (void*)&data[block_index*16];
+ }
+
+ __forceinline void* getDataPtr() { return data; }
+ __forceinline size_t getNumUsedBytes() { return next_block * BLOCK_SIZE; }
+ __forceinline size_t getMaxBlocks() { return maxBlocks; }
+ __forceinline size_t getSize() { return size; }
+
+ void allocNextSegment();
+ void realloc(const size_t newSize);
+
+ void reset();
+
+ static SharedLazyTessellationCache sharedLazyTessellationCache;
+ };
+}
diff --git a/thirdparty/embree/patches/godot-changes-android.patch b/thirdparty/embree/patches/godot-changes-android.patch
new file mode 100644
index 0000000000..a27f924bde
--- /dev/null
+++ b/thirdparty/embree/patches/godot-changes-android.patch
@@ -0,0 +1,103 @@
+diff --git a/thirdparty/embree/common/sys/sysinfo.cpp b/thirdparty/embree/common/sys/sysinfo.cpp
+index ba97dc227b..1679599608 100644
+--- a/thirdparty/embree/common/sys/sysinfo.cpp
++++ b/thirdparty/embree/common/sys/sysinfo.cpp
+@@ -618,7 +618,10 @@ namespace embree
+ static int nThreads = -1;
+ if (nThreads != -1) return nThreads;
+
+-#if defined(__MACOSX__)
++// -- GODOT start --
++// #if defined(__MACOSX__)
++#if defined(__MACOSX__) || defined(__ANDROID__)
++// -- GODOT end --
+ nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container
+ assert(nThreads);
+ #else
+diff --git a/thirdparty/embree/common/sys/thread.cpp b/thirdparty/embree/common/sys/thread.cpp
+index a7827e18f7..f4014be89b 100644
+--- a/thirdparty/embree/common/sys/thread.cpp
++++ b/thirdparty/embree/common/sys/thread.cpp
+@@ -158,7 +158,9 @@ namespace embree
+ /// Linux Platform
+ ////////////////////////////////////////////////////////////////////////////////
+
+-#if defined(__LINUX__)
++// -- GODOT start --
++#if defined(__LINUX__) && !defined(__ANDROID__)
++// -- GODOT end --
+
+ #include <fstream>
+ #include <sstream>
+@@ -247,6 +249,28 @@ namespace embree
+ }
+ #endif
+
++// -- GODOT start --
++////////////////////////////////////////////////////////////////////////////////
++/// Android Platform
++////////////////////////////////////////////////////////////////////////////////
++
++#if defined(__ANDROID__)
++
++namespace embree
++{
++ /*! set affinity of the calling thread */
++ void setAffinity(ssize_t affinity)
++ {
++ cpu_set_t cset;
++ CPU_ZERO(&cset);
++ CPU_SET(affinity, &cset);
++
++ sched_setaffinity(0, sizeof(cset), &cset);
++ }
++}
++#endif
++// -- GODOT end --
++
+ ////////////////////////////////////////////////////////////////////////////////
+ /// FreeBSD Platform
+ ////////////////////////////////////////////////////////////////////////////////
+@@ -355,7 +379,9 @@ namespace embree
+ pthread_attr_destroy(&attr);
+
+ /* set affinity */
+-#if defined(__LINUX__)
++// -- GODOT start --
++#if defined(__LINUX__) && !defined(__ANDROID__)
++// -- GODOT end --
+ if (threadID >= 0) {
+ cpu_set_t cset;
+ CPU_ZERO(&cset);
+@@ -370,7 +396,16 @@ namespace embree
+ CPU_SET(threadID, &cset);
+ pthread_setaffinity_np(*tid, sizeof(cset), &cset);
+ }
++// -- GODOT start --
++#elif defined(__ANDROID__)
++ if (threadID >= 0) {
++ cpu_set_t cset;
++ CPU_ZERO(&cset);
++ CPU_SET(threadID, &cset);
++ sched_setaffinity(pthread_gettid_np(*tid), sizeof(cset), &cset);
++ }
+ #endif
++// -- GODOT end --
+
+ return thread_t(tid);
+ }
+@@ -389,8 +424,14 @@ namespace embree
+
+ /*! destroy a hardware thread by its handle */
+ void destroyThread(thread_t tid) {
++// -- GODOT start --
++#if defined(__ANDROID__)
++ FATAL("Can't destroy threads on Android.");
++#else
+ pthread_cancel(*(pthread_t*)tid);
+ delete (pthread_t*)tid;
++#endif
++// -- GODOT end --
+ }
+
+ /*! creates thread local storage */
diff --git a/thirdparty/embree/patches/godot-changes-misc.patch b/thirdparty/embree/patches/godot-changes-misc.patch
new file mode 100644
index 0000000000..8bf0d9fa97
--- /dev/null
+++ b/thirdparty/embree/patches/godot-changes-misc.patch
@@ -0,0 +1,105 @@
+diff --git a/thirdparty/embree/common/sys/intrinsics.h b/thirdparty/embree/common/sys/intrinsics.h
+index 79729c87ab..ed8dd7d40a 100644
+--- a/thirdparty/embree/common/sys/intrinsics.h
++++ b/thirdparty/embree/common/sys/intrinsics.h
+@@ -34,8 +34,14 @@
+ #endif
+
+ #if defined(__WIN32__)
+-# define NOMINMAX
+-# include <windows.h>
++// -- GODOT start --
++#if !defined(NOMINMAX)
++// -- GODOT end --
++#define NOMINMAX
++// -- GODOT start --
++#endif
++#include "windows.h"
++// -- GODOT end --
+ #endif
+
+ /* normally defined in pmmintrin.h, but we always need this */
+diff --git a/thirdparty/embree/common/sys/platform.h b/thirdparty/embree/common/sys/platform.h
+index 3fc5e99b8d..697e07bb86 100644
+--- a/thirdparty/embree/common/sys/platform.h
++++ b/thirdparty/embree/common/sys/platform.h
+@@ -99,7 +99,9 @@
+ #define dll_import
+ #endif
+
+-#ifdef __WIN32__
++// -- GODOT start --
++#if defined(__WIN32__) && !defined(__MINGW32__)
++// -- GODOT end --
+ #if !defined(__noinline)
+ #define __noinline __declspec(noinline)
+ #endif
+@@ -149,6 +151,9 @@
+ #define DELETED = delete
+ #endif
+
++// -- GODOT start --
++#if !defined(likely)
++// -- GODOT end --
+ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+ #define likely(expr) (expr)
+ #define unlikely(expr) (expr)
+@@ -156,6 +161,9 @@
+ #define likely(expr) __builtin_expect((bool)(expr),true )
+ #define unlikely(expr) __builtin_expect((bool)(expr),false)
+ #endif
++// -- GODOT start --
++#endif
++// -- GODOT end --
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Error handling and debugging
+diff --git a/thirdparty/embree/common/sys/sysinfo.cpp b/thirdparty/embree/common/sys/sysinfo.cpp
+index ba97dc227b..f1a59e511e 100644
+--- a/thirdparty/embree/common/sys/sysinfo.cpp
++++ b/thirdparty/embree/common/sys/sysinfo.cpp
+@@ -248,7 +248,9 @@ namespace embree
+ #if defined(__X86_ASM__)
+ __noinline int64_t get_xcr0()
+ {
+-#if defined (__WIN32__)
++// -- GODOT start --
++#if defined (__WIN32__) && !defined (__MINGW32__)
++// -- GODOT end --
+ int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32
+ xcr0 = _xgetbv(0);
+ return xcr0;
+diff --git a/thirdparty/embree/include/embree3/rtcore_common.h b/thirdparty/embree/include/embree3/rtcore_common.h
+index 9c14b28745..4857e1e05e 100644
+--- a/thirdparty/embree/include/embree3/rtcore_common.h
++++ b/thirdparty/embree/include/embree3/rtcore_common.h
+@@ -19,7 +19,9 @@ typedef int ssize_t;
+ #endif
+ #endif
+
+-#ifdef _WIN32
++// -- GODOT start --
++#if defined(_WIN32) && defined(_MSC_VER)
++// -- GODOT end --
+ # define RTC_ALIGN(...) __declspec(align(__VA_ARGS__))
+ #else
+ # define RTC_ALIGN(...) __attribute__((aligned(__VA_ARGS__)))
+diff --git a/thirdparty/embree/common/tasking/taskschedulertbb.h b/thirdparty/embree/common/tasking/taskschedulertbb.h
+index 3fd15816e9..35bd49849f 100644
+--- a/thirdparty/embree/common/tasking/taskschedulertbb.h
++++ b/thirdparty/embree/common/tasking/taskschedulertbb.h
+@@ -12,7 +12,13 @@
+ #include "../sys/ref.h"
+
+ #if defined(__WIN32__)
++// -- GODOT start --
++#if !defined(NOMINMAX)
++// -- GODOT end --
+ # define NOMINMAX
++// -- GODOT start --
++#endif
++// -- GODOT end --
+ #endif
+
+ // We need to define these to avoid implicit linkage against
+ \ No newline at end of file
diff --git a/thirdparty/embree/patches/godot-changes-noexcept.patch b/thirdparty/embree/patches/godot-changes-noexcept.patch
new file mode 100644
index 0000000000..c587a0e2be
--- /dev/null
+++ b/thirdparty/embree/patches/godot-changes-noexcept.patch
@@ -0,0 +1,630 @@
+diff --git a/thirdparty/embree/common/algorithms/parallel_for.h b/thirdparty/embree/common/algorithms/parallel_for.h
+index f052d8b468..645681ac63 100644
+--- a/thirdparty/embree/common/algorithms/parallel_for.h
++++ b/thirdparty/embree/common/algorithms/parallel_for.h
+@@ -21,7 +21,10 @@ namespace embree
+ func(r.begin());
+ });
+ if (!TaskScheduler::wait())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ }
+
+ #elif defined(TASKING_TBB)
+@@ -31,13 +34,19 @@ namespace embree
+ func(i);
+ },context);
+ if (context.is_group_execution_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ #else
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ });
+ if (tbb::task::self().is_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ #endif
+
+ #elif defined(TASKING_PPL)
+@@ -57,7 +66,10 @@ namespace embree
+ #if defined(TASKING_INTERNAL)
+ TaskScheduler::spawn(first,last,minStepSize,func);
+ if (!TaskScheduler::wait())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+
+ #elif defined(TASKING_TBB)
+ #if TBB_INTERFACE_VERSION >= 12002
+@@ -66,13 +78,19 @@ namespace embree
+ func(range<Index>(r.begin(),r.end()));
+ },context);
+ if (context.is_group_execution_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ #else
+ tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
+ func(range<Index>(r.begin(),r.end()));
+ });
+ if (tbb::task::self().is_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ #endif
+
+ #elif defined(TASKING_PPL)
+@@ -104,13 +122,19 @@ namespace embree
+ func(i);
+ },tbb::simple_partitioner(),context);
+ if (context.is_group_execution_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ #else
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ },tbb::simple_partitioner());
+ if (tbb::task::self().is_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ #endif
+ }
+
+@@ -125,13 +149,19 @@ namespace embree
+ func(i);
+ },ap,context);
+ if (context.is_group_execution_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ #else
+ tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
+ func(i);
+ },ap);
+ if (tbb::task::self().is_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // throw std::runtime_error("task cancelled");
++ abort();
++ // -- GODOT end --
+ #endif
+ }
+
+diff --git a/thirdparty/embree/common/algorithms/parallel_reduce.h b/thirdparty/embree/common/algorithms/parallel_reduce.h
+index f42ae2ec50..8271372ea4 100644
+--- a/thirdparty/embree/common/algorithms/parallel_reduce.h
++++ b/thirdparty/embree/common/algorithms/parallel_reduce.h
+@@ -58,15 +58,19 @@ namespace embree
+ const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
+ [&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
+ reduction,context);
+- if (context.is_group_execution_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // if (context.is_group_execution_cancelled())
++ // throw std::runtime_error("task cancelled");
++ // -- GODOT end --
+ return v;
+ #else
+ const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
+ [&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
+ reduction);
+- if (tbb::task::self().is_cancelled())
+- throw std::runtime_error("task cancelled");
++ // -- GODOT start --
++ // if (tbb::task::self().is_cancelled())
++ // throw std::runtime_error("task cancelled");
++ // -- GODOT end --
+ return v;
+ #endif
+ #else // TASKING_PPL
+diff --git a/thirdparty/embree/common/lexers/stringstream.cpp b/thirdparty/embree/common/lexers/stringstream.cpp
+index 42ffb10176..a037869506 100644
+--- a/thirdparty/embree/common/lexers/stringstream.cpp
++++ b/thirdparty/embree/common/lexers/stringstream.cpp
+@@ -39,7 +39,10 @@ namespace embree
+ std::vector<char> str; str.reserve(64);
+ while (cin->peek() != EOF && !isSeparator(cin->peek())) {
+ int c = cin->get();
+- if (!isValidChar(c)) throw std::runtime_error("invalid character "+std::string(1,c)+" in input");
++ // -- GODOT start --
++ // if (!isValidChar(c)) throw std::runtime_error("invalid character "+std::string(1,c)+" in input");
++ if (!isValidChar(c)) abort();
++ // -- GODOT end --
+ str.push_back((char)c);
+ }
+ str.push_back(0);
+diff --git a/thirdparty/embree/common/sys/alloc.cpp b/thirdparty/embree/common/sys/alloc.cpp
+index 1bc30fe9a5..abdd269069 100644
+--- a/thirdparty/embree/common/sys/alloc.cpp
++++ b/thirdparty/embree/common/sys/alloc.cpp
+@@ -21,7 +21,10 @@ namespace embree
+ void* ptr = _mm_malloc(size,align);
+
+ if (size != 0 && ptr == nullptr)
+- throw std::bad_alloc();
++ // -- GODOT start --
++ // throw std::bad_alloc();
++ abort();
++ // -- GODOT end --
+
+ return ptr;
+ }
+@@ -128,7 +131,10 @@ namespace embree
+ /* fall back to 4k pages */
+ int flags = MEM_COMMIT | MEM_RESERVE;
+ char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
+- if (ptr == nullptr) throw std::bad_alloc();
++ // -- GODOT start --
++ // if (ptr == nullptr) throw std::bad_alloc();
++ if (ptr == nullptr) abort();
++ // -- GODOT end --
+ hugepages = false;
+ return ptr;
+ }
+@@ -145,7 +151,10 @@ namespace embree
+ return bytesOld;
+
+ if (!VirtualFree((char*)ptr+bytesNew,bytesOld-bytesNew,MEM_DECOMMIT))
+- throw std::bad_alloc();
++ // -- GODOT start --
++ // throw std::bad_alloc();
++ abort();
++ // -- GODOT end --
+
+ return bytesNew;
+ }
+@@ -156,7 +165,10 @@ namespace embree
+ return;
+
+ if (!VirtualFree(ptr,0,MEM_RELEASE))
+- throw std::bad_alloc();
++ // -- GODOT start --
++ // throw std::bad_alloc();
++ abort();
++ // -- GODOT end --
+ }
+
+ void os_advise(void *ptr, size_t bytes)
+@@ -260,7 +272,10 @@ namespace embree
+
+ /* fallback to 4k pages */
+ void* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+- if (ptr == MAP_FAILED) throw std::bad_alloc();
++ // -- GODOT start --
++ // if (ptr == MAP_FAILED) throw std::bad_alloc();
++ if (ptr == MAP_FAILED) abort();
++ // -- GODOT end --
+ hugepages = false;
+
+ /* advise huge page hint for THP */
+@@ -277,7 +292,10 @@ namespace embree
+ return bytesOld;
+
+ if (munmap((char*)ptr+bytesNew,bytesOld-bytesNew) == -1)
+- throw std::bad_alloc();
++ // -- GODOT start --
++ // throw std::bad_alloc();
++ abort();
++ // -- GODOT end --
+
+ return bytesNew;
+ }
+@@ -291,7 +309,10 @@ namespace embree
+ const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
+ bytes = (bytes+pageSize-1) & ~(pageSize-1);
+ if (munmap(ptr,bytes) == -1)
+- throw std::bad_alloc();
++ // -- GODOT start --
++ // throw std::bad_alloc();
++ abort();
++ // -- GODOT end --
+ }
+
+ /* hint for transparent huge pages (THP) */
+diff --git a/thirdparty/embree/common/sys/platform.h b/thirdparty/embree/common/sys/platform.h
+index 8a6d9fa0a9..697e07bb86 100644
+--- a/thirdparty/embree/common/sys/platform.h
++++ b/thirdparty/embree/common/sys/platform.h
+@@ -179,11 +179,19 @@
+ #define PRINT4(x,y,z,w) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << embree_endl
+
+ #if defined(DEBUG) // only report file and line in debug mode
++ // -- GODOT start --
++ // #define THROW_RUNTIME_ERROR(str)
++ // throw std::runtime_error(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
+ #define THROW_RUNTIME_ERROR(str) \
+- throw std::runtime_error(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
++ printf(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)), abort();
++ // -- GODOT end --
+ #else
++ // -- GODOT start --
++ // #define THROW_RUNTIME_ERROR(str)
++ // throw std::runtime_error(str);
+ #define THROW_RUNTIME_ERROR(str) \
+- throw std::runtime_error(str);
++ abort();
++ // -- GODOT end --
+ #endif
+
+ #define FATAL(x) THROW_RUNTIME_ERROR(x)
+diff --git a/thirdparty/embree/common/tasking/taskschedulerinternal.cpp b/thirdparty/embree/common/tasking/taskschedulerinternal.cpp
+index dca835a716..ad438588a3 100644
+--- a/thirdparty/embree/common/tasking/taskschedulerinternal.cpp
++++ b/thirdparty/embree/common/tasking/taskschedulerinternal.cpp
+@@ -48,13 +48,15 @@ namespace embree
+ {
+ Task* prevTask = thread.task;
+ thread.task = this;
+- try {
+- if (thread.scheduler->cancellingException == nullptr)
++ // -- GODOT start --
++ // try {
++ // if (thread.scheduler->cancellingException == nullptr)
+ closure->execute();
+- } catch (...) {
+- if (thread.scheduler->cancellingException == nullptr)
+- thread.scheduler->cancellingException = std::current_exception();
+- }
++ // } catch (...) {
++ // if (thread.scheduler->cancellingException == nullptr)
++ // thread.scheduler->cancellingException = std::current_exception();
++ // }
++ // -- GODOT end --
+ thread.task = prevTask;
+ add_dependencies(-1);
+ }
+@@ -291,8 +293,11 @@ namespace embree
+ size_t threadIndex = allocThreadIndex();
+ condition.wait(mutex, [&] () { return hasRootTask.load(); });
+ mutex.unlock();
+- std::exception_ptr except = thread_loop(threadIndex);
+- if (except != nullptr) std::rethrow_exception(except);
++ // -- GODOT start --
++ // std::exception_ptr except = thread_loop(threadIndex);
++ // if (except != nullptr) std::rethrow_exception(except);
++ thread_loop(threadIndex);
++ // -- GODOT end --
+ }
+
+ void TaskScheduler::reset() {
+@@ -324,7 +329,10 @@ namespace embree
+ return thread->scheduler->cancellingException == nullptr;
+ }
+
+- std::exception_ptr TaskScheduler::thread_loop(size_t threadIndex)
++// -- GODOT start --
++// std::exception_ptr TaskScheduler::thread_loop(size_t threadIndex)
++ void TaskScheduler::thread_loop(size_t threadIndex)
++// -- GODOT end --
+ {
+ /* allocate thread structure */
+ std::unique_ptr<Thread> mthread(new Thread(threadIndex,this)); // too large for stack allocation
+@@ -347,9 +355,10 @@ namespace embree
+ swapThread(oldThread);
+
+ /* remember exception to throw */
+- std::exception_ptr except = nullptr;
+- if (cancellingException != nullptr) except = cancellingException;
+-
++ // -- GODOT start --
++ // std::exception_ptr except = nullptr;
++ // if (cancellingException != nullptr) except = cancellingException;
++ // -- GODOT end --
+ /* wait for all threads to terminate */
+ threadCounter--;
+ #if defined(__WIN32__)
+@@ -367,7 +376,10 @@ namespace embree
+ yield();
+ #endif
+ }
+- return except;
++ // -- GODOT start --
++ // return except;
++ return;
++ // -- GODOT end --
+ }
+
+ bool TaskScheduler::steal_from_other_threads(Thread& thread)
+diff --git a/thirdparty/embree/common/tasking/taskschedulerinternal.h b/thirdparty/embree/common/tasking/taskschedulerinternal.h
+index c766a0bb6a..8fa6bb12fa 100644
+--- a/thirdparty/embree/common/tasking/taskschedulerinternal.h
++++ b/thirdparty/embree/common/tasking/taskschedulerinternal.h
+@@ -123,7 +123,10 @@ namespace embree
+ {
+ size_t ofs = bytes + ((align - stackPtr) & (align-1));
+ if (stackPtr + ofs > CLOSURE_STACK_SIZE)
+- throw std::runtime_error("closure stack overflow");
++ // -- GODOT start --
++ // throw std::runtime_error("closure stack overflow");
++ abort();
++ // -- GODOT end --
+ stackPtr += ofs;
+ return &stack[stackPtr-bytes];
+ }
+@@ -132,7 +135,10 @@ namespace embree
+ __forceinline void push_right(Thread& thread, const size_t size, const Closure& closure)
+ {
+ if (right >= TASK_STACK_SIZE)
+- throw std::runtime_error("task stack overflow");
++ // -- GODOT start --
++ // throw std::runtime_error("task stack overflow");
++ abort();
++ // -- GODOT end --
+
+ /* allocate new task on right side of stack */
+ size_t oldStackPtr = stackPtr;
+@@ -238,7 +244,10 @@ namespace embree
+ void wait_for_threads(size_t threadCount);
+
+ /*! thread loop for all worker threads */
+- std::exception_ptr thread_loop(size_t threadIndex);
++ // -- GODOT start --
++ // std::exception_ptr thread_loop(size_t threadIndex);
++ void thread_loop(size_t threadIndex);
++ // -- GODOT end --
+
+ /*! steals a task from a different thread */
+ bool steal_from_other_threads(Thread& thread);
+diff --git a/thirdparty/embree/kernels/bvh/bvh_statistics.cpp b/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
+index d8da78eed7..d857ff7d95 100644
+--- a/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
++++ b/thirdparty/embree/kernels/bvh/bvh_statistics.cpp
+@@ -150,7 +150,10 @@ namespace embree
+ }
+ }
+ else {
+- throw std::runtime_error("not supported node type in bvh_statistics");
++ // -- GODOT start --
++ // throw std::runtime_error("not supported node type in bvh_statistics");
++ abort();
++ // -- GODOT end --
+ }
+ return s;
+ }
+diff --git a/thirdparty/embree/kernels/common/rtcore.cpp b/thirdparty/embree/kernels/common/rtcore.cpp
+index 74e9fb335c..94b3819e42 100644
+--- a/thirdparty/embree/kernels/common/rtcore.cpp
++++ b/thirdparty/embree/kernels/common/rtcore.cpp
+@@ -197,7 +197,10 @@ RTC_NAMESPACE_BEGIN;
+ if (quality != RTC_BUILD_QUALITY_LOW &&
+ quality != RTC_BUILD_QUALITY_MEDIUM &&
+ quality != RTC_BUILD_QUALITY_HIGH)
+- throw std::runtime_error("invalid build quality");
++ // -- GODOT start --
++ // throw std::runtime_error("invalid build quality");
++ abort();
++ // -- GODOT end --
+ scene->setBuildQuality(quality);
+ RTC_CATCH_END2(scene);
+ }
+@@ -1350,7 +1353,10 @@ RTC_NAMESPACE_BEGIN;
+ quality != RTC_BUILD_QUALITY_MEDIUM &&
+ quality != RTC_BUILD_QUALITY_HIGH &&
+ quality != RTC_BUILD_QUALITY_REFIT)
+- throw std::runtime_error("invalid build quality");
++ // -- GODOT start --
++ // throw std::runtime_error("invalid build quality");
++ abort();
++ // -- GODOT end --
+ geometry->setBuildQuality(quality);
+ RTC_CATCH_END2(geometry);
+ }
+diff --git a/thirdparty/embree/kernels/common/rtcore.h b/thirdparty/embree/kernels/common/rtcore.h
+index 4e4b24e9c2..373e49a689 100644
+--- a/thirdparty/embree/kernels/common/rtcore.h
++++ b/thirdparty/embree/kernels/common/rtcore.h
+@@ -25,52 +25,58 @@ namespace embree
+ #endif
+
+ /*! Macros used in the rtcore API implementation */
+-#define RTC_CATCH_BEGIN try {
++// -- GODOT start --
++// #define RTC_CATCH_BEGIN try {
++#define RTC_CATCH_BEGIN
+
+-#define RTC_CATCH_END(device) \
+- } catch (std::bad_alloc&) { \
+- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+- } catch (rtcore_error& e) { \
+- Device::process_error(device,e.error,e.what()); \
+- } catch (std::exception& e) { \
+- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+- } catch (...) { \
+- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+- }
++// #define RTC_CATCH_END(device) \
++// } catch (std::bad_alloc&) { \
++// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
++// } catch (rtcore_error& e) { \
++// Device::process_error(device,e.error,e.what()); \
++// } catch (std::exception& e) { \
++// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
++// } catch (...) { \
++// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
++// }
++#define RTC_CATCH_END(device)
+
+-#define RTC_CATCH_END2(scene) \
+- } catch (std::bad_alloc&) { \
+- Device* device = scene ? scene->device : nullptr; \
+- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+- } catch (rtcore_error& e) { \
+- Device* device = scene ? scene->device : nullptr; \
+- Device::process_error(device,e.error,e.what()); \
+- } catch (std::exception& e) { \
+- Device* device = scene ? scene->device : nullptr; \
+- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+- } catch (...) { \
+- Device* device = scene ? scene->device : nullptr; \
+- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+- }
++// #define RTC_CATCH_END2(scene) \
++// } catch (std::bad_alloc&) { \
++// Device* device = scene ? scene->device : nullptr; \
++// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
++// } catch (rtcore_error& e) { \
++// Device* device = scene ? scene->device : nullptr; \
++// Device::process_error(device,e.error,e.what()); \
++// } catch (std::exception& e) { \
++// Device* device = scene ? scene->device : nullptr; \
++// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
++// } catch (...) { \
++// Device* device = scene ? scene->device : nullptr; \
++// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
++// }
++#define RTC_CATCH_END2(scene)
+
+-#define RTC_CATCH_END2_FALSE(scene) \
+- } catch (std::bad_alloc&) { \
+- Device* device = scene ? scene->device : nullptr; \
+- Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
+- return false; \
+- } catch (rtcore_error& e) { \
+- Device* device = scene ? scene->device : nullptr; \
+- Device::process_error(device,e.error,e.what()); \
+- return false; \
+- } catch (std::exception& e) { \
+- Device* device = scene ? scene->device : nullptr; \
+- Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
+- return false; \
+- } catch (...) { \
+- Device* device = scene ? scene->device : nullptr; \
+- Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
+- return false; \
+- }
++// #define RTC_CATCH_END2_FALSE(scene) \
++// } catch (std::bad_alloc&) { \
++// Device* device = scene ? scene->device : nullptr; \
++// Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
++// return false; \
++// } catch (rtcore_error& e) { \
++// Device* device = scene ? scene->device : nullptr; \
++// Device::process_error(device,e.error,e.what()); \
++// return false; \
++// } catch (std::exception& e) { \
++// Device* device = scene ? scene->device : nullptr; \
++// Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
++// return false; \
++// } catch (...) { \
++// Device* device = scene ? scene->device : nullptr; \
++// Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
++// return false; \
++// }
++#define RTC_CATCH_END2_FALSE(scene) return false;
++// -- GODOT end --
+
+ #define RTC_VERIFY_HANDLE(handle) \
+ if (handle == nullptr) { \
+@@ -97,28 +103,38 @@ namespace embree
+ #define RTC_TRACE(x)
+ #endif
+
+- /*! used to throw embree API errors */
+- struct rtcore_error : public std::exception
+- {
+- __forceinline rtcore_error(RTCError error, const std::string& str)
+- : error(error), str(str) {}
+-
+- ~rtcore_error() throw() {}
+-
+- const char* what () const throw () {
+- return str.c_str();
+- }
+-
+- RTCError error;
+- std::string str;
+- };
++// -- GODOT begin --
++// /*! used to throw embree API errors */
++// struct rtcore_error : public std::exception
++// {
++// __forceinline rtcore_error(RTCError error, const std::string& str)
++// : error(error), str(str) {}
++//
++// ~rtcore_error() throw() {}
++//
++// const char* what () const throw () {
++// return str.c_str();
++// }
++//
++// RTCError error;
++// std::string str;
++// };
++// -- GODOT end --
+
+ #if defined(DEBUG) // only report file and line in debug mode
++ // -- GODOT begin --
++ // #define throw_RTCError(error,str) \
++ // throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
+ #define throw_RTCError(error,str) \
+- throw rtcore_error(error,std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str));
++ printf(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)), abort();
++ // -- GODOT end --
+ #else
++ // -- GODOT begin --
++ // #define throw_RTCError(error,str) \
++ // throw rtcore_error(error,str);
+ #define throw_RTCError(error,str) \
+- throw rtcore_error(error,str);
++ abort();
++ // -- GODOT end --
+ #endif
+
+ #define RTC_BUILD_ARGUMENTS_HAS(settings,member) \
+diff --git a/thirdparty/embree/kernels/common/scene.cpp b/thirdparty/embree/kernels/common/scene.cpp
+index 0149055f2c..408d7eae6f 100644
+--- a/thirdparty/embree/kernels/common/scene.cpp
++++ b/thirdparty/embree/kernels/common/scene.cpp
+@@ -792,16 +792,18 @@ namespace embree
+ }
+
+ /* initiate build */
+- try {
++ // -- GODOT start --
++ // try {
+ scheduler->spawn_root([&]() { commit_task(); Lock<MutexSys> lock(schedulerMutex); this->scheduler = nullptr; }, 1, !join);
+- }
+- catch (...) {
+- accels_clear();
+- updateInterface();
+- Lock<MutexSys> lock(schedulerMutex);
+- this->scheduler = nullptr;
+- throw;
+- }
++ // }
++ // catch (...) {
++ // accels_clear();
++ // updateInterface();
++ // Lock<MutexSys> lock(schedulerMutex);
++ // this->scheduler = nullptr;
++ // throw;
++ // }
++ // -- GODOT end --
+ }
+
+ #endif
diff --git a/thirdparty/embree/patches/godot-changes-ubsan.patch b/thirdparty/embree/patches/godot-changes-ubsan.patch
new file mode 100644
index 0000000000..1336246f0d
--- /dev/null
+++ b/thirdparty/embree/patches/godot-changes-ubsan.patch
@@ -0,0 +1,24 @@
+diff --git a/thirdparty/embree/kernels/builders/primrefgen.cpp b/thirdparty/embree/kernels/builders/primrefgen.cpp
+index bb4fc81dfe..d279dc4993 100644
+--- a/thirdparty/embree/kernels/builders/primrefgen.cpp
++++ b/thirdparty/embree/kernels/builders/primrefgen.cpp
+@@ -184,6 +184,9 @@ namespace embree
+
+ // special variants for grid meshes
+
++// -- GODOT start --
++#if defined(EMBREE_GEOMETRY_GRID)
++// -- GODOT end --
+ PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
+ {
+ PrimInfo pinfo(empty);
+@@ -293,6 +296,9 @@ namespace embree
+
+ return pinfo;
+ }
++// -- GODOT start --
++#endif
++// -- GODOT end --
+
+ // ====================================================================================================
+ // ====================================================================================================
diff --git a/thirdparty/fonts/OpenSans_SemiBold.ttf b/thirdparty/fonts/OpenSans_SemiBold.ttf
new file mode 100644
index 0000000000..54e7059cf3
--- /dev/null
+++ b/thirdparty/fonts/OpenSans_SemiBold.ttf
Binary files differ
diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h
index fe8d349731..e44b99ce52 100644
--- a/thirdparty/meshoptimizer/meshoptimizer.h
+++ b/thirdparty/meshoptimizer/meshoptimizer.h
@@ -299,6 +299,11 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t ver
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error);
/**
+ * Experimental: Mesh simplifier with attribute metric; attributes follow xyz position data atm (vertex data must contain 3 + attribute_count floats per vertex)
+ */
+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count);
+
+/**
* Experimental: Mesh simplifier (sloppy)
* Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance
* The algorithm doesn't preserve mesh topology but can stop short of the target goal based on target error.
diff --git a/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch
new file mode 100644
index 0000000000..cf648b0da3
--- /dev/null
+++ b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch
@@ -0,0 +1,262 @@
+diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h
+index fe8d349731..e44b99ce52 100644
+--- a/thirdparty/meshoptimizer/meshoptimizer.h
++++ b/thirdparty/meshoptimizer/meshoptimizer.h
+@@ -298,6 +298,11 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t ver
+ */
+ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error);
+
++/**
++ * Experimental: Mesh simplifier with attribute metric; attributes follow xyz position data atm (vertex data must contain 3 + attribute_count floats per vertex)
++ */
++MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count);
++
+ /**
+ * Experimental: Mesh simplifier (sloppy)
+ * Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance
+diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
+index b2cb589462..059cabb055 100644
+--- a/thirdparty/meshoptimizer/simplifier.cpp
++++ b/thirdparty/meshoptimizer/simplifier.cpp
+@@ -20,6 +20,8 @@
+ #define TRACESTATS(i) (void)0
+ #endif
+
++#define ATTRIBUTES 8
++
+ // This work is based on:
+ // Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
+ // Michael Garland. Quadric-based polygonal surface simplification. 1999
+@@ -358,6 +360,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
+ struct Vector3
+ {
+ float x, y, z;
++
++#if ATTRIBUTES
++ float a[ATTRIBUTES];
++#endif
+ };
+
+ static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride)
+@@ -414,6 +420,13 @@ struct Quadric
+ float a10, a20, a21;
+ float b0, b1, b2, c;
+ float w;
++
++#if ATTRIBUTES
++ float gx[ATTRIBUTES];
++ float gy[ATTRIBUTES];
++ float gz[ATTRIBUTES];
++ float gw[ATTRIBUTES];
++#endif
+ };
+
+ struct Collapse
+@@ -456,6 +469,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R)
+ Q.b2 += R.b2;
+ Q.c += R.c;
+ Q.w += R.w;
++
++#if ATTRIBUTES
++ for (int k = 0; k < ATTRIBUTES; ++k)
++ {
++ Q.gx[k] += R.gx[k];
++ Q.gy[k] += R.gy[k];
++ Q.gz[k] += R.gz[k];
++ Q.gw[k] += R.gw[k];
++ }
++#endif
+ }
+
+ static float quadricError(const Quadric& Q, const Vector3& v)
+@@ -481,6 +504,17 @@ static float quadricError(const Quadric& Q, const Vector3& v)
+ r += ry * v.y;
+ r += rz * v.z;
+
++#if ATTRIBUTES
++ // see quadricUpdateAttributes for general derivation; here we need to add the parts of (eval(pos) - attr)^2 that depend on attr
++ for (int k = 0; k < ATTRIBUTES; ++k)
++ {
++ float a = v.a[k];
++
++ r += a * a * Q.w;
++ r -= 2 * a * (v.x * Q.gx[k] + v.y * Q.gy[k] + v.z * Q.gz[k] + Q.gw[k]);
++ }
++#endif
++
+ float s = Q.w == 0.f ? 0.f : 1.f / Q.w;
+
+ return fabsf(r) * s;
+@@ -504,6 +538,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo
+ Q.b2 = c * dw;
+ Q.c = d * dw;
+ Q.w = w;
++
++#if ATTRIBUTES
++ memset(Q.gx, 0, sizeof(Q.gx));
++ memset(Q.gy, 0, sizeof(Q.gy));
++ memset(Q.gz, 0, sizeof(Q.gz));
++ memset(Q.gw, 0, sizeof(Q.gw));
++#endif
+ }
+
+ static void quadricFromPoint(Quadric& Q, float x, float y, float z, float w)
+@@ -556,6 +597,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3
+ quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight);
+ }
+
++#if ATTRIBUTES
++static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float w)
++{
++ // for each attribute we want to encode the following function into the quadric:
++ // (eval(pos) - attr)^2
++ // where eval(pos) interpolates attribute across the triangle like so:
++ // eval(pos) = pos.x * gx + pos.y * gy + pos.z * gz + gw
++ // where gx/gy/gz/gw are gradients
++ Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z};
++ Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z};
++
++ // we compute gradients using barycentric coordinates; barycentric coordinates can be computed as follows:
++ // v = (d11 * d20 - d01 * d21) / denom
++ // w = (d00 * d21 - d01 * d20) / denom
++ // u = 1 - v - w
++ // here v0, v1 are triangle edge vectors, v2 is a vector from point to triangle corner, and dij = dot(vi, vj)
++ const Vector3& v0 = p10;
++ const Vector3& v1 = p20;
++ float d00 = v0.x * v0.x + v0.y * v0.y + v0.z * v0.z;
++ float d01 = v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
++ float d11 = v1.x * v1.x + v1.y * v1.y + v1.z * v1.z;
++ float denom = d00 * d11 - d01 * d01;
++ float denomr = denom == 0 ? 0.f : 1.f / denom;
++
++ // precompute gradient factors
++ // these are derived by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w and factoring out common factors that are shared between attributes
++ float gx1 = (d11 * v0.x - d01 * v1.x) * denomr;
++ float gx2 = (d00 * v1.x - d01 * v0.x) * denomr;
++ float gy1 = (d11 * v0.y - d01 * v1.y) * denomr;
++ float gy2 = (d00 * v1.y - d01 * v0.y) * denomr;
++ float gz1 = (d11 * v0.z - d01 * v1.z) * denomr;
++ float gz2 = (d00 * v1.z - d01 * v0.z) * denomr;
++
++ for (int k = 0; k < ATTRIBUTES; ++k)
++ {
++ float a0 = p0.a[k], a1 = p1.a[k], a2 = p2.a[k];
++
++ // compute gradient of eval(pos) for x/y/z/w
++ // the formulas below are obtained by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w
++ float gx = gx1 * (a1 - a0) + gx2 * (a2 - a0);
++ float gy = gy1 * (a1 - a0) + gy2 * (a2 - a0);
++ float gz = gz1 * (a1 - a0) + gz2 * (a2 - a0);
++ float gw = a0 - p0.x * gx - p0.y * gy - p0.z * gz;
++
++ // quadric encodes (eval(pos)-attr)^2; this means that the resulting expansion needs to compute, for example, pos.x * pos.y * K
++ // since quadrics already encode factors for pos.x * pos.y, we can accumulate almost everything in basic quadric fields
++ Q.a00 += w * (gx * gx);
++ Q.a11 += w * (gy * gy);
++ Q.a22 += w * (gz * gz);
++
++ Q.a10 += w * (gy * gx);
++ Q.a20 += w * (gz * gx);
++ Q.a21 += w * (gz * gy);
++
++ Q.b0 += w * (gx * gw);
++ Q.b1 += w * (gy * gw);
++ Q.b2 += w * (gz * gw);
++
++ Q.c += w * (gw * gw);
++
++ // the only remaining sum components are ones that depend on attr; these will be addded during error evaluation, see quadricError
++ Q.gx[k] = w * gx;
++ Q.gy[k] = w * gy;
++ Q.gz[k] = w * gz;
++ Q.gw[k] = w * gw;
++
++#if TRACE > 2
++ printf("attr%d: %e %e %e\n",
++ k,
++ (gx * p0.x + gy * p0.y + gz * p0.z + gw - a0),
++ (gx * p1.x + gy * p1.y + gz * p1.z + gw - a1),
++ (gx * p2.x + gy * p2.y + gz * p2.z + gw - a2)
++ );
++#endif
++ }
++}
++#endif
++
+ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap)
+ {
+ for (size_t i = 0; i < index_count; i += 3)
+@@ -567,6 +686,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
+ Quadric Q;
+ quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f);
+
++#if ATTRIBUTES
++ quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w);
++#endif
+ quadricAdd(vertex_quadrics[remap[i0]], Q);
+ quadricAdd(vertex_quadrics[remap[i1]], Q);
+ quadricAdd(vertex_quadrics[remap[i2]], Q);
+@@ -1259,13 +1381,19 @@ unsigned int* meshopt_simplifyDebugLoopBack = 0;
+ #endif
+
+ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error)
++{
++ return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, out_result_error, 0, 0, 0);
++}
++
++size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count)
+ {
+ using namespace meshopt;
+
+ assert(index_count % 3 == 0);
+- assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
+- assert(vertex_positions_stride % sizeof(float) == 0);
++ assert(vertex_stride > 0 && vertex_stride <= 256);
++ assert(vertex_stride % sizeof(float) == 0);
+ assert(target_index_count <= index_count);
++ assert(attribute_count <= ATTRIBUTES);
+
+ meshopt_Allocator allocator;
+
+@@ -1279,7 +1407,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+ // build position remap that maps each vertex to the one with identical position
+ unsigned int* remap = allocator.allocate<unsigned int>(vertex_count);
+ unsigned int* wedge = allocator.allocate<unsigned int>(vertex_count);
+- buildPositionRemap(remap, wedge, vertex_positions_data, vertex_count, vertex_positions_stride, allocator);
++ buildPositionRemap(remap, wedge, vertex_data, vertex_count, vertex_stride, allocator);
+
+ // classify vertices; vertex kind determines collapse rules, see kCanCollapse
+ unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count);
+@@ -1303,7 +1431,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+ #endif
+
+ Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count);
+- rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride);
++ rescalePositions(vertex_positions, vertex_data, vertex_count, vertex_stride);
++
++#if ATTRIBUTES
++ for (size_t i = 0; i < vertex_count; ++i)
++ {
++ memset(vertex_positions[i].a, 0, sizeof(vertex_positions[i].a));
++
++ for (size_t k = 0; k < attribute_count; ++k)
++ {
++ float a = attributes[i * attribute_count + k];
++
++ vertex_positions[i].a[k] = a * attribute_weights[k];
++ }
++ }
++#endif
+
+ Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count);
+ memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
+@@ -1395,7 +1537,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+
+ // result_error is quadratic; we need to remap it back to linear
+ if (out_result_error)
++ {
+ *out_result_error = sqrtf(result_error);
++ }
+
+ return result_count;
+ }
diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
index b2cb589462..0f10ebef4b 100644
--- a/thirdparty/meshoptimizer/simplifier.cpp
+++ b/thirdparty/meshoptimizer/simplifier.cpp
@@ -20,6 +20,8 @@
#define TRACESTATS(i) (void)0
#endif
+#define ATTRIBUTES 8
+
// This work is based on:
// Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
// Michael Garland. Quadric-based polygonal surface simplification. 1999
@@ -118,8 +120,13 @@ struct PositionHasher
{
const unsigned int* key = reinterpret_cast<const unsigned int*>(vertex_positions + index * vertex_stride_float);
+ // scramble bits to make sure that integer coordinates have entropy in lower bits
+ unsigned int x = key[0] ^ (key[0] >> 17);
+ unsigned int y = key[1] ^ (key[1] >> 17);
+ unsigned int z = key[2] ^ (key[2] >> 17);
+
// Optimized Spatial Hashing for Collision Detection of Deformable Objects
- return (key[0] * 73856093) ^ (key[1] * 19349663) ^ (key[2] * 83492791);
+ return (x * 73856093) ^ (y * 19349663) ^ (z * 83492791);
}
bool equal(unsigned int lhs, unsigned int rhs) const
@@ -358,6 +365,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
struct Vector3
{
float x, y, z;
+
+#if ATTRIBUTES
+ float a[ATTRIBUTES];
+#endif
};
static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride)
@@ -414,6 +425,13 @@ struct Quadric
float a10, a20, a21;
float b0, b1, b2, c;
float w;
+
+#if ATTRIBUTES
+ float gx[ATTRIBUTES];
+ float gy[ATTRIBUTES];
+ float gz[ATTRIBUTES];
+ float gw[ATTRIBUTES];
+#endif
};
struct Collapse
@@ -456,6 +474,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R)
Q.b2 += R.b2;
Q.c += R.c;
Q.w += R.w;
+
+#if ATTRIBUTES
+ for (int k = 0; k < ATTRIBUTES; ++k)
+ {
+ Q.gx[k] += R.gx[k];
+ Q.gy[k] += R.gy[k];
+ Q.gz[k] += R.gz[k];
+ Q.gw[k] += R.gw[k];
+ }
+#endif
}
static float quadricError(const Quadric& Q, const Vector3& v)
@@ -481,6 +509,17 @@ static float quadricError(const Quadric& Q, const Vector3& v)
r += ry * v.y;
r += rz * v.z;
+#if ATTRIBUTES
+ // see quadricUpdateAttributes for general derivation; here we need to add the parts of (eval(pos) - attr)^2 that depend on attr
+ for (int k = 0; k < ATTRIBUTES; ++k)
+ {
+ float a = v.a[k];
+
+ r += a * a * Q.w;
+ r -= 2 * a * (v.x * Q.gx[k] + v.y * Q.gy[k] + v.z * Q.gz[k] + Q.gw[k]);
+ }
+#endif
+
float s = Q.w == 0.f ? 0.f : 1.f / Q.w;
return fabsf(r) * s;
@@ -504,6 +543,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo
Q.b2 = c * dw;
Q.c = d * dw;
Q.w = w;
+
+#if ATTRIBUTES
+ memset(Q.gx, 0, sizeof(Q.gx));
+ memset(Q.gy, 0, sizeof(Q.gy));
+ memset(Q.gz, 0, sizeof(Q.gz));
+ memset(Q.gw, 0, sizeof(Q.gw));
+#endif
}
static void quadricFromPoint(Quadric& Q, float x, float y, float z, float w)
@@ -556,6 +602,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3
quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight);
}
+#if ATTRIBUTES
+static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float w)
+{
+ // for each attribute we want to encode the following function into the quadric:
+ // (eval(pos) - attr)^2
+ // where eval(pos) interpolates attribute across the triangle like so:
+ // eval(pos) = pos.x * gx + pos.y * gy + pos.z * gz + gw
+ // where gx/gy/gz/gw are gradients
+ Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z};
+ Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z};
+
+ // we compute gradients using barycentric coordinates; barycentric coordinates can be computed as follows:
+ // v = (d11 * d20 - d01 * d21) / denom
+ // w = (d00 * d21 - d01 * d20) / denom
+ // u = 1 - v - w
+ // here v0, v1 are triangle edge vectors, v2 is a vector from point to triangle corner, and dij = dot(vi, vj)
+ const Vector3& v0 = p10;
+ const Vector3& v1 = p20;
+ float d00 = v0.x * v0.x + v0.y * v0.y + v0.z * v0.z;
+ float d01 = v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
+ float d11 = v1.x * v1.x + v1.y * v1.y + v1.z * v1.z;
+ float denom = d00 * d11 - d01 * d01;
+ float denomr = denom == 0 ? 0.f : 1.f / denom;
+
+ // precompute gradient factors
+ // these are derived by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w and factoring out common factors that are shared between attributes
+ float gx1 = (d11 * v0.x - d01 * v1.x) * denomr;
+ float gx2 = (d00 * v1.x - d01 * v0.x) * denomr;
+ float gy1 = (d11 * v0.y - d01 * v1.y) * denomr;
+ float gy2 = (d00 * v1.y - d01 * v0.y) * denomr;
+ float gz1 = (d11 * v0.z - d01 * v1.z) * denomr;
+ float gz2 = (d00 * v1.z - d01 * v0.z) * denomr;
+
+ for (int k = 0; k < ATTRIBUTES; ++k)
+ {
+ float a0 = p0.a[k], a1 = p1.a[k], a2 = p2.a[k];
+
+ // compute gradient of eval(pos) for x/y/z/w
+ // the formulas below are obtained by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w
+ float gx = gx1 * (a1 - a0) + gx2 * (a2 - a0);
+ float gy = gy1 * (a1 - a0) + gy2 * (a2 - a0);
+ float gz = gz1 * (a1 - a0) + gz2 * (a2 - a0);
+ float gw = a0 - p0.x * gx - p0.y * gy - p0.z * gz;
+
+ // quadric encodes (eval(pos)-attr)^2; this means that the resulting expansion needs to compute, for example, pos.x * pos.y * K
+ // since quadrics already encode factors for pos.x * pos.y, we can accumulate almost everything in basic quadric fields
+ Q.a00 += w * (gx * gx);
+ Q.a11 += w * (gy * gy);
+ Q.a22 += w * (gz * gz);
+
+ Q.a10 += w * (gy * gx);
+ Q.a20 += w * (gz * gx);
+ Q.a21 += w * (gz * gy);
+
+ Q.b0 += w * (gx * gw);
+ Q.b1 += w * (gy * gw);
+ Q.b2 += w * (gz * gw);
+
+ Q.c += w * (gw * gw);
+
+ // the only remaining sum components are ones that depend on attr; these will be addded during error evaluation, see quadricError
+ Q.gx[k] = w * gx;
+ Q.gy[k] = w * gy;
+ Q.gz[k] = w * gz;
+ Q.gw[k] = w * gw;
+
+#if TRACE > 2
+ printf("attr%d: %e %e %e\n",
+ k,
+ (gx * p0.x + gy * p0.y + gz * p0.z + gw - a0),
+ (gx * p1.x + gy * p1.y + gz * p1.z + gw - a1),
+ (gx * p2.x + gy * p2.y + gz * p2.z + gw - a2)
+ );
+#endif
+ }
+}
+#endif
+
static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap)
{
for (size_t i = 0; i < index_count; i += 3)
@@ -567,6 +691,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
Quadric Q;
quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f);
+#if ATTRIBUTES
+ quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w);
+#endif
quadricAdd(vertex_quadrics[remap[i0]], Q);
quadricAdd(vertex_quadrics[remap[i1]], Q);
quadricAdd(vertex_quadrics[remap[i2]], Q);
@@ -1038,7 +1165,7 @@ struct IdHasher
struct TriangleHasher
{
- unsigned int* indices;
+ const unsigned int* indices;
size_t hash(unsigned int i) const
{
@@ -1253,19 +1380,26 @@ static float interpolate(float y, float x0, float y0, float x1, float y1, float
} // namespace meshopt
#ifndef NDEBUG
-unsigned char* meshopt_simplifyDebugKind = 0;
-unsigned int* meshopt_simplifyDebugLoop = 0;
-unsigned int* meshopt_simplifyDebugLoopBack = 0;
+// Note: this is only exposed for debug visualization purposes; do *not* use these in debug builds
+MESHOPTIMIZER_API unsigned char* meshopt_simplifyDebugKind = 0;
+MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoop = 0;
+MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = 0;
#endif
size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error)
{
+ return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, out_result_error, 0, 0, 0);
+}
+
+size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count)
+{
using namespace meshopt;
assert(index_count % 3 == 0);
- assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
- assert(vertex_positions_stride % sizeof(float) == 0);
+ assert(vertex_stride > 0 && vertex_stride <= 256);
+ assert(vertex_stride % sizeof(float) == 0);
assert(target_index_count <= index_count);
+ assert(attribute_count <= ATTRIBUTES);
meshopt_Allocator allocator;
@@ -1279,7 +1413,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
// build position remap that maps each vertex to the one with identical position
unsigned int* remap = allocator.allocate<unsigned int>(vertex_count);
unsigned int* wedge = allocator.allocate<unsigned int>(vertex_count);
- buildPositionRemap(remap, wedge, vertex_positions_data, vertex_count, vertex_positions_stride, allocator);
+ buildPositionRemap(remap, wedge, vertex_data, vertex_count, vertex_stride, allocator);
// classify vertices; vertex kind determines collapse rules, see kCanCollapse
unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count);
@@ -1303,7 +1437,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
#endif
Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count);
- rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride);
+ rescalePositions(vertex_positions, vertex_data, vertex_count, vertex_stride);
+
+#if ATTRIBUTES
+ for (size_t i = 0; i < vertex_count; ++i)
+ {
+ memset(vertex_positions[i].a, 0, sizeof(vertex_positions[i].a));
+
+ for (size_t k = 0; k < attribute_count; ++k)
+ {
+ float a = attributes[i * attribute_count + k];
+
+ vertex_positions[i].a[k] = a * attribute_weights[k];
+ }
+ }
+#endif
Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count);
memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
@@ -1395,7 +1543,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
// result_error is quadratic; we need to remap it back to linear
if (out_result_error)
+ {
*out_result_error = sqrtf(result_error);
+ }
return result_count;
}
diff --git a/thirdparty/misc/patches/polypartition-godot-types.patch b/thirdparty/misc/patches/polypartition-godot-types.patch
index 59fdb2707c..782f02e8dc 100644
--- a/thirdparty/misc/patches/polypartition-godot-types.patch
+++ b/thirdparty/misc/patches/polypartition-godot-types.patch
@@ -1,5 +1,5 @@
diff --git a/thirdparty/misc/polypartition.cpp b/thirdparty/misc/polypartition.cpp
-index 3a8a6efa8319..4f1b6dcb21d8 100644
+index 3a8a6efa83..5e94793b79 100644
--- a/thirdparty/misc/polypartition.cpp
+++ b/thirdparty/misc/polypartition.cpp
@@ -23,10 +23,7 @@
@@ -510,7 +510,7 @@ index 3a8a6efa8319..4f1b6dcb21d8 100644
- return 0;
- }
- numvertices += iter->GetNumPoints();
-+ for (iter = inpolys->front(); iter; iter++) {
++ for (iter = inpolys->front(); iter; iter = iter->next()) {
+ numvertices += iter->get().GetNumPoints();
}
@@ -521,7 +521,7 @@ index 3a8a6efa8319..4f1b6dcb21d8 100644
polystartindex = 0;
- for (iter = inpolys->begin(); iter != inpolys->end(); iter++) {
- poly = &(*iter);
-+ for (iter = inpolys->front(); iter; iter++) {
++ for (iter = inpolys->front(); iter; iter = iter->next()) {
+ poly = &(iter->get());
polyendindex = polystartindex + poly->GetNumPoints() - 1;
for (i = 0; i < poly->GetNumPoints(); i++) {
@@ -569,7 +569,7 @@ index 3a8a6efa8319..4f1b6dcb21d8 100644
newedge.p2 = v->p;
edgeIter = edgeTree.lower_bound(newedge);
- if (edgeIter == edgeTree.begin()) {
-+ if (edgeIter == edgeTree.front()) {
++ if (edgeIter == nullptr || edgeIter == edgeTree.front()) {
error = true;
break;
}
@@ -606,7 +606,7 @@ index 3a8a6efa8319..4f1b6dcb21d8 100644
newedge.p2 = v->p;
edgeIter = edgeTree.lower_bound(newedge);
- if (edgeIter == edgeTree.begin()) {
-+ if (edgeIter == edgeTree.front()) {
++ if (edgeIter == nullptr || edgeIter == edgeTree.front()) {
error = true;
break;
}
@@ -648,7 +648,7 @@ index 3a8a6efa8319..4f1b6dcb21d8 100644
newedge.p2 = v->p;
edgeIter = edgeTree.lower_bound(newedge);
- if (edgeIter == edgeTree.begin()) {
-+ if (edgeIter == edgeTree.front()) {
++ if (edgeIter == nullptr || edgeIter == edgeTree.front()) {
error = true;
break;
}
@@ -716,7 +716,7 @@ index 3a8a6efa8319..4f1b6dcb21d8 100644
}
}
diff --git a/thirdparty/misc/polypartition.h b/thirdparty/misc/polypartition.h
-index f163f5d2173f..b2d905a3ef76 100644
+index f163f5d217..b2d905a3ef 100644
--- a/thirdparty/misc/polypartition.h
+++ b/thirdparty/misc/polypartition.h
@@ -24,8 +24,9 @@
diff --git a/thirdparty/misc/polypartition.cpp b/thirdparty/misc/polypartition.cpp
index 4f1b6dcb21..5e94793b79 100644
--- a/thirdparty/misc/polypartition.cpp
+++ b/thirdparty/misc/polypartition.cpp
@@ -1289,7 +1289,7 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto
bool error = false;
numvertices = 0;
- for (iter = inpolys->front(); iter; iter++) {
+ for (iter = inpolys->front(); iter; iter = iter->next()) {
numvertices += iter->get().GetNumPoints();
}
@@ -1298,7 +1298,7 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto
newnumvertices = numvertices;
polystartindex = 0;
- for (iter = inpolys->front(); iter; iter++) {
+ for (iter = inpolys->front(); iter; iter = iter->next()) {
poly = &(iter->get());
polyendindex = polystartindex + poly->GetNumPoints() - 1;
for (i = 0; i < poly->GetNumPoints(); i++) {
@@ -1408,7 +1408,7 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto
newedge.p1 = v->p;
newedge.p2 = v->p;
edgeIter = edgeTree.lower_bound(newedge);
- if (edgeIter == edgeTree.front()) {
+ if (edgeIter == nullptr || edgeIter == edgeTree.front()) {
error = true;
break;
}
@@ -1449,7 +1449,7 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto
newedge.p1 = v->p;
newedge.p2 = v->p;
edgeIter = edgeTree.lower_bound(newedge);
- if (edgeIter == edgeTree.front()) {
+ if (edgeIter == nullptr || edgeIter == edgeTree.front()) {
error = true;
break;
}
@@ -1494,7 +1494,7 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto
newedge.p1 = v->p;
newedge.p2 = v->p;
edgeIter = edgeTree.lower_bound(newedge);
- if (edgeIter == edgeTree.front()) {
+ if (edgeIter == nullptr || edgeIter == edgeTree.front()) {
error = true;
break;
}
diff --git a/thirdparty/misc/smolv.cpp b/thirdparty/misc/smolv.cpp
new file mode 100644
index 0000000000..26ed7294f9
--- /dev/null
+++ b/thirdparty/misc/smolv.cpp
@@ -0,0 +1,2108 @@
+// smol-v - public domain - https://github.com/aras-p/smol-v
+// authored 2016-2020 by Aras Pranckevicius
+// no warranty implied; use at your own risk
+// See end of file for license information.
+
+#include "smolv.h"
+#include <stdint.h>
+#include <vector>
+#include <algorithm>
+#include <cstdio>
+#include <cstring>
+
+#if !defined(_MSC_VER) && __cplusplus < 201103L
+#define static_assert(x,y)
+#endif
+
+#define _SMOLV_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+// --------------------------------------------------------------------------------------------
+// Metadata about known SPIR-V operations
+
+enum SpvOp
+{
+ SpvOpNop = 0,
+ SpvOpUndef = 1,
+ SpvOpSourceContinued = 2,
+ SpvOpSource = 3,
+ SpvOpSourceExtension = 4,
+ SpvOpName = 5,
+ SpvOpMemberName = 6,
+ SpvOpString = 7,
+ SpvOpLine = 8,
+ SpvOpExtension = 10,
+ SpvOpExtInstImport = 11,
+ SpvOpExtInst = 12,
+ SpvOpVectorShuffleCompact = 13, // not in SPIR-V, added for SMOL-V!
+ SpvOpMemoryModel = 14,
+ SpvOpEntryPoint = 15,
+ SpvOpExecutionMode = 16,
+ SpvOpCapability = 17,
+ SpvOpTypeVoid = 19,
+ SpvOpTypeBool = 20,
+ SpvOpTypeInt = 21,
+ SpvOpTypeFloat = 22,
+ SpvOpTypeVector = 23,
+ SpvOpTypeMatrix = 24,
+ SpvOpTypeImage = 25,
+ SpvOpTypeSampler = 26,
+ SpvOpTypeSampledImage = 27,
+ SpvOpTypeArray = 28,
+ SpvOpTypeRuntimeArray = 29,
+ SpvOpTypeStruct = 30,
+ SpvOpTypeOpaque = 31,
+ SpvOpTypePointer = 32,
+ SpvOpTypeFunction = 33,
+ SpvOpTypeEvent = 34,
+ SpvOpTypeDeviceEvent = 35,
+ SpvOpTypeReserveId = 36,
+ SpvOpTypeQueue = 37,
+ SpvOpTypePipe = 38,
+ SpvOpTypeForwardPointer = 39,
+ SpvOpConstantTrue = 41,
+ SpvOpConstantFalse = 42,
+ SpvOpConstant = 43,
+ SpvOpConstantComposite = 44,
+ SpvOpConstantSampler = 45,
+ SpvOpConstantNull = 46,
+ SpvOpSpecConstantTrue = 48,
+ SpvOpSpecConstantFalse = 49,
+ SpvOpSpecConstant = 50,
+ SpvOpSpecConstantComposite = 51,
+ SpvOpSpecConstantOp = 52,
+ SpvOpFunction = 54,
+ SpvOpFunctionParameter = 55,
+ SpvOpFunctionEnd = 56,
+ SpvOpFunctionCall = 57,
+ SpvOpVariable = 59,
+ SpvOpImageTexelPointer = 60,
+ SpvOpLoad = 61,
+ SpvOpStore = 62,
+ SpvOpCopyMemory = 63,
+ SpvOpCopyMemorySized = 64,
+ SpvOpAccessChain = 65,
+ SpvOpInBoundsAccessChain = 66,
+ SpvOpPtrAccessChain = 67,
+ SpvOpArrayLength = 68,
+ SpvOpGenericPtrMemSemantics = 69,
+ SpvOpInBoundsPtrAccessChain = 70,
+ SpvOpDecorate = 71,
+ SpvOpMemberDecorate = 72,
+ SpvOpDecorationGroup = 73,
+ SpvOpGroupDecorate = 74,
+ SpvOpGroupMemberDecorate = 75,
+ SpvOpVectorExtractDynamic = 77,
+ SpvOpVectorInsertDynamic = 78,
+ SpvOpVectorShuffle = 79,
+ SpvOpCompositeConstruct = 80,
+ SpvOpCompositeExtract = 81,
+ SpvOpCompositeInsert = 82,
+ SpvOpCopyObject = 83,
+ SpvOpTranspose = 84,
+ SpvOpSampledImage = 86,
+ SpvOpImageSampleImplicitLod = 87,
+ SpvOpImageSampleExplicitLod = 88,
+ SpvOpImageSampleDrefImplicitLod = 89,
+ SpvOpImageSampleDrefExplicitLod = 90,
+ SpvOpImageSampleProjImplicitLod = 91,
+ SpvOpImageSampleProjExplicitLod = 92,
+ SpvOpImageSampleProjDrefImplicitLod = 93,
+ SpvOpImageSampleProjDrefExplicitLod = 94,
+ SpvOpImageFetch = 95,
+ SpvOpImageGather = 96,
+ SpvOpImageDrefGather = 97,
+ SpvOpImageRead = 98,
+ SpvOpImageWrite = 99,
+ SpvOpImage = 100,
+ SpvOpImageQueryFormat = 101,
+ SpvOpImageQueryOrder = 102,
+ SpvOpImageQuerySizeLod = 103,
+ SpvOpImageQuerySize = 104,
+ SpvOpImageQueryLod = 105,
+ SpvOpImageQueryLevels = 106,
+ SpvOpImageQuerySamples = 107,
+ SpvOpConvertFToU = 109,
+ SpvOpConvertFToS = 110,
+ SpvOpConvertSToF = 111,
+ SpvOpConvertUToF = 112,
+ SpvOpUConvert = 113,
+ SpvOpSConvert = 114,
+ SpvOpFConvert = 115,
+ SpvOpQuantizeToF16 = 116,
+ SpvOpConvertPtrToU = 117,
+ SpvOpSatConvertSToU = 118,
+ SpvOpSatConvertUToS = 119,
+ SpvOpConvertUToPtr = 120,
+ SpvOpPtrCastToGeneric = 121,
+ SpvOpGenericCastToPtr = 122,
+ SpvOpGenericCastToPtrExplicit = 123,
+ SpvOpBitcast = 124,
+ SpvOpSNegate = 126,
+ SpvOpFNegate = 127,
+ SpvOpIAdd = 128,
+ SpvOpFAdd = 129,
+ SpvOpISub = 130,
+ SpvOpFSub = 131,
+ SpvOpIMul = 132,
+ SpvOpFMul = 133,
+ SpvOpUDiv = 134,
+ SpvOpSDiv = 135,
+ SpvOpFDiv = 136,
+ SpvOpUMod = 137,
+ SpvOpSRem = 138,
+ SpvOpSMod = 139,
+ SpvOpFRem = 140,
+ SpvOpFMod = 141,
+ SpvOpVectorTimesScalar = 142,
+ SpvOpMatrixTimesScalar = 143,
+ SpvOpVectorTimesMatrix = 144,
+ SpvOpMatrixTimesVector = 145,
+ SpvOpMatrixTimesMatrix = 146,
+ SpvOpOuterProduct = 147,
+ SpvOpDot = 148,
+ SpvOpIAddCarry = 149,
+ SpvOpISubBorrow = 150,
+ SpvOpUMulExtended = 151,
+ SpvOpSMulExtended = 152,
+ SpvOpAny = 154,
+ SpvOpAll = 155,
+ SpvOpIsNan = 156,
+ SpvOpIsInf = 157,
+ SpvOpIsFinite = 158,
+ SpvOpIsNormal = 159,
+ SpvOpSignBitSet = 160,
+ SpvOpLessOrGreater = 161,
+ SpvOpOrdered = 162,
+ SpvOpUnordered = 163,
+ SpvOpLogicalEqual = 164,
+ SpvOpLogicalNotEqual = 165,
+ SpvOpLogicalOr = 166,
+ SpvOpLogicalAnd = 167,
+ SpvOpLogicalNot = 168,
+ SpvOpSelect = 169,
+ SpvOpIEqual = 170,
+ SpvOpINotEqual = 171,
+ SpvOpUGreaterThan = 172,
+ SpvOpSGreaterThan = 173,
+ SpvOpUGreaterThanEqual = 174,
+ SpvOpSGreaterThanEqual = 175,
+ SpvOpULessThan = 176,
+ SpvOpSLessThan = 177,
+ SpvOpULessThanEqual = 178,
+ SpvOpSLessThanEqual = 179,
+ SpvOpFOrdEqual = 180,
+ SpvOpFUnordEqual = 181,
+ SpvOpFOrdNotEqual = 182,
+ SpvOpFUnordNotEqual = 183,
+ SpvOpFOrdLessThan = 184,
+ SpvOpFUnordLessThan = 185,
+ SpvOpFOrdGreaterThan = 186,
+ SpvOpFUnordGreaterThan = 187,
+ SpvOpFOrdLessThanEqual = 188,
+ SpvOpFUnordLessThanEqual = 189,
+ SpvOpFOrdGreaterThanEqual = 190,
+ SpvOpFUnordGreaterThanEqual = 191,
+ SpvOpShiftRightLogical = 194,
+ SpvOpShiftRightArithmetic = 195,
+ SpvOpShiftLeftLogical = 196,
+ SpvOpBitwiseOr = 197,
+ SpvOpBitwiseXor = 198,
+ SpvOpBitwiseAnd = 199,
+ SpvOpNot = 200,
+ SpvOpBitFieldInsert = 201,
+ SpvOpBitFieldSExtract = 202,
+ SpvOpBitFieldUExtract = 203,
+ SpvOpBitReverse = 204,
+ SpvOpBitCount = 205,
+ SpvOpDPdx = 207,
+ SpvOpDPdy = 208,
+ SpvOpFwidth = 209,
+ SpvOpDPdxFine = 210,
+ SpvOpDPdyFine = 211,
+ SpvOpFwidthFine = 212,
+ SpvOpDPdxCoarse = 213,
+ SpvOpDPdyCoarse = 214,
+ SpvOpFwidthCoarse = 215,
+ SpvOpEmitVertex = 218,
+ SpvOpEndPrimitive = 219,
+ SpvOpEmitStreamVertex = 220,
+ SpvOpEndStreamPrimitive = 221,
+ SpvOpControlBarrier = 224,
+ SpvOpMemoryBarrier = 225,
+ SpvOpAtomicLoad = 227,
+ SpvOpAtomicStore = 228,
+ SpvOpAtomicExchange = 229,
+ SpvOpAtomicCompareExchange = 230,
+ SpvOpAtomicCompareExchangeWeak = 231,
+ SpvOpAtomicIIncrement = 232,
+ SpvOpAtomicIDecrement = 233,
+ SpvOpAtomicIAdd = 234,
+ SpvOpAtomicISub = 235,
+ SpvOpAtomicSMin = 236,
+ SpvOpAtomicUMin = 237,
+ SpvOpAtomicSMax = 238,
+ SpvOpAtomicUMax = 239,
+ SpvOpAtomicAnd = 240,
+ SpvOpAtomicOr = 241,
+ SpvOpAtomicXor = 242,
+ SpvOpPhi = 245,
+ SpvOpLoopMerge = 246,
+ SpvOpSelectionMerge = 247,
+ SpvOpLabel = 248,
+ SpvOpBranch = 249,
+ SpvOpBranchConditional = 250,
+ SpvOpSwitch = 251,
+ SpvOpKill = 252,
+ SpvOpReturn = 253,
+ SpvOpReturnValue = 254,
+ SpvOpUnreachable = 255,
+ SpvOpLifetimeStart = 256,
+ SpvOpLifetimeStop = 257,
+ SpvOpGroupAsyncCopy = 259,
+ SpvOpGroupWaitEvents = 260,
+ SpvOpGroupAll = 261,
+ SpvOpGroupAny = 262,
+ SpvOpGroupBroadcast = 263,
+ SpvOpGroupIAdd = 264,
+ SpvOpGroupFAdd = 265,
+ SpvOpGroupFMin = 266,
+ SpvOpGroupUMin = 267,
+ SpvOpGroupSMin = 268,
+ SpvOpGroupFMax = 269,
+ SpvOpGroupUMax = 270,
+ SpvOpGroupSMax = 271,
+ SpvOpReadPipe = 274,
+ SpvOpWritePipe = 275,
+ SpvOpReservedReadPipe = 276,
+ SpvOpReservedWritePipe = 277,
+ SpvOpReserveReadPipePackets = 278,
+ SpvOpReserveWritePipePackets = 279,
+ SpvOpCommitReadPipe = 280,
+ SpvOpCommitWritePipe = 281,
+ SpvOpIsValidReserveId = 282,
+ SpvOpGetNumPipePackets = 283,
+ SpvOpGetMaxPipePackets = 284,
+ SpvOpGroupReserveReadPipePackets = 285,
+ SpvOpGroupReserveWritePipePackets = 286,
+ SpvOpGroupCommitReadPipe = 287,
+ SpvOpGroupCommitWritePipe = 288,
+ SpvOpEnqueueMarker = 291,
+ SpvOpEnqueueKernel = 292,
+ SpvOpGetKernelNDrangeSubGroupCount = 293,
+ SpvOpGetKernelNDrangeMaxSubGroupSize = 294,
+ SpvOpGetKernelWorkGroupSize = 295,
+ SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,
+ SpvOpRetainEvent = 297,
+ SpvOpReleaseEvent = 298,
+ SpvOpCreateUserEvent = 299,
+ SpvOpIsValidEvent = 300,
+ SpvOpSetUserEventStatus = 301,
+ SpvOpCaptureEventProfilingInfo = 302,
+ SpvOpGetDefaultQueue = 303,
+ SpvOpBuildNDRange = 304,
+ SpvOpImageSparseSampleImplicitLod = 305,
+ SpvOpImageSparseSampleExplicitLod = 306,
+ SpvOpImageSparseSampleDrefImplicitLod = 307,
+ SpvOpImageSparseSampleDrefExplicitLod = 308,
+ SpvOpImageSparseSampleProjImplicitLod = 309,
+ SpvOpImageSparseSampleProjExplicitLod = 310,
+ SpvOpImageSparseSampleProjDrefImplicitLod = 311,
+ SpvOpImageSparseSampleProjDrefExplicitLod = 312,
+ SpvOpImageSparseFetch = 313,
+ SpvOpImageSparseGather = 314,
+ SpvOpImageSparseDrefGather = 315,
+ SpvOpImageSparseTexelsResident = 316,
+ SpvOpNoLine = 317,
+ SpvOpAtomicFlagTestAndSet = 318,
+ SpvOpAtomicFlagClear = 319,
+ SpvOpImageSparseRead = 320,
+ SpvOpSizeOf = 321,
+ SpvOpTypePipeStorage = 322,
+ SpvOpConstantPipeStorage = 323,
+ SpvOpCreatePipeFromPipeStorage = 324,
+ SpvOpGetKernelLocalSizeForSubgroupCount = 325,
+ SpvOpGetKernelMaxNumSubgroups = 326,
+ SpvOpTypeNamedBarrier = 327,
+ SpvOpNamedBarrierInitialize = 328,
+ SpvOpMemoryNamedBarrier = 329,
+ SpvOpModuleProcessed = 330,
+ SpvOpExecutionModeId = 331,
+ SpvOpDecorateId = 332,
+ SpvOpGroupNonUniformElect = 333,
+ SpvOpGroupNonUniformAll = 334,
+ SpvOpGroupNonUniformAny = 335,
+ SpvOpGroupNonUniformAllEqual = 336,
+ SpvOpGroupNonUniformBroadcast = 337,
+ SpvOpGroupNonUniformBroadcastFirst = 338,
+ SpvOpGroupNonUniformBallot = 339,
+ SpvOpGroupNonUniformInverseBallot = 340,
+ SpvOpGroupNonUniformBallotBitExtract = 341,
+ SpvOpGroupNonUniformBallotBitCount = 342,
+ SpvOpGroupNonUniformBallotFindLSB = 343,
+ SpvOpGroupNonUniformBallotFindMSB = 344,
+ SpvOpGroupNonUniformShuffle = 345,
+ SpvOpGroupNonUniformShuffleXor = 346,
+ SpvOpGroupNonUniformShuffleUp = 347,
+ SpvOpGroupNonUniformShuffleDown = 348,
+ SpvOpGroupNonUniformIAdd = 349,
+ SpvOpGroupNonUniformFAdd = 350,
+ SpvOpGroupNonUniformIMul = 351,
+ SpvOpGroupNonUniformFMul = 352,
+ SpvOpGroupNonUniformSMin = 353,
+ SpvOpGroupNonUniformUMin = 354,
+ SpvOpGroupNonUniformFMin = 355,
+ SpvOpGroupNonUniformSMax = 356,
+ SpvOpGroupNonUniformUMax = 357,
+ SpvOpGroupNonUniformFMax = 358,
+ SpvOpGroupNonUniformBitwiseAnd = 359,
+ SpvOpGroupNonUniformBitwiseOr = 360,
+ SpvOpGroupNonUniformBitwiseXor = 361,
+ SpvOpGroupNonUniformLogicalAnd = 362,
+ SpvOpGroupNonUniformLogicalOr = 363,
+ SpvOpGroupNonUniformLogicalXor = 364,
+ SpvOpGroupNonUniformQuadBroadcast = 365,
+ SpvOpGroupNonUniformQuadSwap = 366,
+};
+static const int kKnownOpsCount = SpvOpGroupNonUniformQuadSwap+1;
+
+
+static const char* kSpirvOpNames[] =
+{
+ "Nop",
+ "Undef",
+ "SourceContinued",
+ "Source",
+ "SourceExtension",
+ "Name",
+ "MemberName",
+ "String",
+ "Line",
+ "#9",
+ "Extension",
+ "ExtInstImport",
+ "ExtInst",
+ "VectorShuffleCompact",
+ "MemoryModel",
+ "EntryPoint",
+ "ExecutionMode",
+ "Capability",
+ "#18",
+ "TypeVoid",
+ "TypeBool",
+ "TypeInt",
+ "TypeFloat",
+ "TypeVector",
+ "TypeMatrix",
+ "TypeImage",
+ "TypeSampler",
+ "TypeSampledImage",
+ "TypeArray",
+ "TypeRuntimeArray",
+ "TypeStruct",
+ "TypeOpaque",
+ "TypePointer",
+ "TypeFunction",
+ "TypeEvent",
+ "TypeDeviceEvent",
+ "TypeReserveId",
+ "TypeQueue",
+ "TypePipe",
+ "TypeForwardPointer",
+ "#40",
+ "ConstantTrue",
+ "ConstantFalse",
+ "Constant",
+ "ConstantComposite",
+ "ConstantSampler",
+ "ConstantNull",
+ "#47",
+ "SpecConstantTrue",
+ "SpecConstantFalse",
+ "SpecConstant",
+ "SpecConstantComposite",
+ "SpecConstantOp",
+ "#53",
+ "Function",
+ "FunctionParameter",
+ "FunctionEnd",
+ "FunctionCall",
+ "#58",
+ "Variable",
+ "ImageTexelPointer",
+ "Load",
+ "Store",
+ "CopyMemory",
+ "CopyMemorySized",
+ "AccessChain",
+ "InBoundsAccessChain",
+ "PtrAccessChain",
+ "ArrayLength",
+ "GenericPtrMemSemantics",
+ "InBoundsPtrAccessChain",
+ "Decorate",
+ "MemberDecorate",
+ "DecorationGroup",
+ "GroupDecorate",
+ "GroupMemberDecorate",
+ "#76",
+ "VectorExtractDynamic",
+ "VectorInsertDynamic",
+ "VectorShuffle",
+ "CompositeConstruct",
+ "CompositeExtract",
+ "CompositeInsert",
+ "CopyObject",
+ "Transpose",
+ "#85",
+ "SampledImage",
+ "ImageSampleImplicitLod",
+ "ImageSampleExplicitLod",
+ "ImageSampleDrefImplicitLod",
+ "ImageSampleDrefExplicitLod",
+ "ImageSampleProjImplicitLod",
+ "ImageSampleProjExplicitLod",
+ "ImageSampleProjDrefImplicitLod",
+ "ImageSampleProjDrefExplicitLod",
+ "ImageFetch",
+ "ImageGather",
+ "ImageDrefGather",
+ "ImageRead",
+ "ImageWrite",
+ "Image",
+ "ImageQueryFormat",
+ "ImageQueryOrder",
+ "ImageQuerySizeLod",
+ "ImageQuerySize",
+ "ImageQueryLod",
+ "ImageQueryLevels",
+ "ImageQuerySamples",
+ "#108",
+ "ConvertFToU",
+ "ConvertFToS",
+ "ConvertSToF",
+ "ConvertUToF",
+ "UConvert",
+ "SConvert",
+ "FConvert",
+ "QuantizeToF16",
+ "ConvertPtrToU",
+ "SatConvertSToU",
+ "SatConvertUToS",
+ "ConvertUToPtr",
+ "PtrCastToGeneric",
+ "GenericCastToPtr",
+ "GenericCastToPtrExplicit",
+ "Bitcast",
+ "#125",
+ "SNegate",
+ "FNegate",
+ "IAdd",
+ "FAdd",
+ "ISub",
+ "FSub",
+ "IMul",
+ "FMul",
+ "UDiv",
+ "SDiv",
+ "FDiv",
+ "UMod",
+ "SRem",
+ "SMod",
+ "FRem",
+ "FMod",
+ "VectorTimesScalar",
+ "MatrixTimesScalar",
+ "VectorTimesMatrix",
+ "MatrixTimesVector",
+ "MatrixTimesMatrix",
+ "OuterProduct",
+ "Dot",
+ "IAddCarry",
+ "ISubBorrow",
+ "UMulExtended",
+ "SMulExtended",
+ "#153",
+ "Any",
+ "All",
+ "IsNan",
+ "IsInf",
+ "IsFinite",
+ "IsNormal",
+ "SignBitSet",
+ "LessOrGreater",
+ "Ordered",
+ "Unordered",
+ "LogicalEqual",
+ "LogicalNotEqual",
+ "LogicalOr",
+ "LogicalAnd",
+ "LogicalNot",
+ "Select",
+ "IEqual",
+ "INotEqual",
+ "UGreaterThan",
+ "SGreaterThan",
+ "UGreaterThanEqual",
+ "SGreaterThanEqual",
+ "ULessThan",
+ "SLessThan",
+ "ULessThanEqual",
+ "SLessThanEqual",
+ "FOrdEqual",
+ "FUnordEqual",
+ "FOrdNotEqual",
+ "FUnordNotEqual",
+ "FOrdLessThan",
+ "FUnordLessThan",
+ "FOrdGreaterThan",
+ "FUnordGreaterThan",
+ "FOrdLessThanEqual",
+ "FUnordLessThanEqual",
+ "FOrdGreaterThanEqual",
+ "FUnordGreaterThanEqual",
+ "#192",
+ "#193",
+ "ShiftRightLogical",
+ "ShiftRightArithmetic",
+ "ShiftLeftLogical",
+ "BitwiseOr",
+ "BitwiseXor",
+ "BitwiseAnd",
+ "Not",
+ "BitFieldInsert",
+ "BitFieldSExtract",
+ "BitFieldUExtract",
+ "BitReverse",
+ "BitCount",
+ "#206",
+ "DPdx",
+ "DPdy",
+ "Fwidth",
+ "DPdxFine",
+ "DPdyFine",
+ "FwidthFine",
+ "DPdxCoarse",
+ "DPdyCoarse",
+ "FwidthCoarse",
+ "#216",
+ "#217",
+ "EmitVertex",
+ "EndPrimitive",
+ "EmitStreamVertex",
+ "EndStreamPrimitive",
+ "#222",
+ "#223",
+ "ControlBarrier",
+ "MemoryBarrier",
+ "#226",
+ "AtomicLoad",
+ "AtomicStore",
+ "AtomicExchange",
+ "AtomicCompareExchange",
+ "AtomicCompareExchangeWeak",
+ "AtomicIIncrement",
+ "AtomicIDecrement",
+ "AtomicIAdd",
+ "AtomicISub",
+ "AtomicSMin",
+ "AtomicUMin",
+ "AtomicSMax",
+ "AtomicUMax",
+ "AtomicAnd",
+ "AtomicOr",
+ "AtomicXor",
+ "#243",
+ "#244",
+ "Phi",
+ "LoopMerge",
+ "SelectionMerge",
+ "Label",
+ "Branch",
+ "BranchConditional",
+ "Switch",
+ "Kill",
+ "Return",
+ "ReturnValue",
+ "Unreachable",
+ "LifetimeStart",
+ "LifetimeStop",
+ "#258",
+ "GroupAsyncCopy",
+ "GroupWaitEvents",
+ "GroupAll",
+ "GroupAny",
+ "GroupBroadcast",
+ "GroupIAdd",
+ "GroupFAdd",
+ "GroupFMin",
+ "GroupUMin",
+ "GroupSMin",
+ "GroupFMax",
+ "GroupUMax",
+ "GroupSMax",
+ "#272",
+ "#273",
+ "ReadPipe",
+ "WritePipe",
+ "ReservedReadPipe",
+ "ReservedWritePipe",
+ "ReserveReadPipePackets",
+ "ReserveWritePipePackets",
+ "CommitReadPipe",
+ "CommitWritePipe",
+ "IsValidReserveId",
+ "GetNumPipePackets",
+ "GetMaxPipePackets",
+ "GroupReserveReadPipePackets",
+ "GroupReserveWritePipePackets",
+ "GroupCommitReadPipe",
+ "GroupCommitWritePipe",
+ "#289",
+ "#290",
+ "EnqueueMarker",
+ "EnqueueKernel",
+ "GetKernelNDrangeSubGroupCount",
+ "GetKernelNDrangeMaxSubGroupSize",
+ "GetKernelWorkGroupSize",
+ "GetKernelPreferredWorkGroupSizeMultiple",
+ "RetainEvent",
+ "ReleaseEvent",
+ "CreateUserEvent",
+ "IsValidEvent",
+ "SetUserEventStatus",
+ "CaptureEventProfilingInfo",
+ "GetDefaultQueue",
+ "BuildNDRange",
+ "ImageSparseSampleImplicitLod",
+ "ImageSparseSampleExplicitLod",
+ "ImageSparseSampleDrefImplicitLod",
+ "ImageSparseSampleDrefExplicitLod",
+ "ImageSparseSampleProjImplicitLod",
+ "ImageSparseSampleProjExplicitLod",
+ "ImageSparseSampleProjDrefImplicitLod",
+ "ImageSparseSampleProjDrefExplicitLod",
+ "ImageSparseFetch",
+ "ImageSparseGather",
+ "ImageSparseDrefGather",
+ "ImageSparseTexelsResident",
+ "NoLine",
+ "AtomicFlagTestAndSet",
+ "AtomicFlagClear",
+ "ImageSparseRead",
+ "SizeOf",
+ "TypePipeStorage",
+ "ConstantPipeStorage",
+ "CreatePipeFromPipeStorage",
+ "GetKernelLocalSizeForSubgroupCount",
+ "GetKernelMaxNumSubgroups",
+ "TypeNamedBarrier",
+ "NamedBarrierInitialize",
+ "MemoryNamedBarrier",
+ "ModuleProcessed",
+ "ExecutionModeId",
+ "DecorateId",
+ "GroupNonUniformElect",
+ "GroupNonUniformAll",
+ "GroupNonUniformAny",
+ "GroupNonUniformAllEqual",
+ "GroupNonUniformBroadcast",
+ "GroupNonUniformBroadcastFirst",
+ "GroupNonUniformBallot",
+ "GroupNonUniformInverseBallot",
+ "GroupNonUniformBallotBitExtract",
+ "GroupNonUniformBallotBitCount",
+ "GroupNonUniformBallotFindLSB",
+ "GroupNonUniformBallotFindMSB",
+ "GroupNonUniformShuffle",
+ "GroupNonUniformShuffleXor",
+ "GroupNonUniformShuffleUp",
+ "GroupNonUniformShuffleDown",
+ "GroupNonUniformIAdd",
+ "GroupNonUniformFAdd",
+ "GroupNonUniformIMul",
+ "GroupNonUniformFMul",
+ "GroupNonUniformSMin",
+ "GroupNonUniformUMin",
+ "GroupNonUniformFMin",
+ "GroupNonUniformSMax",
+ "GroupNonUniformUMax",
+ "GroupNonUniformFMax",
+ "GroupNonUniformBitwiseAnd",
+ "GroupNonUniformBitwiseOr",
+ "GroupNonUniformBitwiseXor",
+ "GroupNonUniformLogicalAnd",
+ "GroupNonUniformLogicalOr",
+ "GroupNonUniformLogicalXor",
+ "GroupNonUniformQuadBroadcast",
+ "GroupNonUniformQuadSwap",
+};
+static_assert(_SMOLV_ARRAY_SIZE(kSpirvOpNames) == kKnownOpsCount, "kSpirvOpNames table mismatch with known SpvOps");
+
+
+struct OpData
+{
+ uint8_t hasResult; // does it have result ID?
+ uint8_t hasType; // does it have type ID?
+ uint8_t deltaFromResult; // How many words after (optional) type+result to write out as deltas from result?
+ uint8_t varrest; // should the rest of words be written in varint encoding?
+};
+static const OpData kSpirvOpData[] =
+{
+ {0, 0, 0, 0}, // Nop
+ {1, 1, 0, 0}, // Undef
+ {0, 0, 0, 0}, // SourceContinued
+ {0, 0, 0, 1}, // Source
+ {0, 0, 0, 0}, // SourceExtension
+ {0, 0, 0, 0}, // Name
+ {0, 0, 0, 0}, // MemberName
+ {0, 0, 0, 0}, // String
+ {0, 0, 0, 1}, // Line
+ {1, 1, 0, 0}, // #9
+ {0, 0, 0, 0}, // Extension
+ {1, 0, 0, 0}, // ExtInstImport
+ {1, 1, 0, 1}, // ExtInst
+ {1, 1, 2, 1}, // VectorShuffleCompact - new in SMOLV
+ {0, 0, 0, 1}, // MemoryModel
+ {0, 0, 0, 1}, // EntryPoint
+ {0, 0, 0, 1}, // ExecutionMode
+ {0, 0, 0, 1}, // Capability
+ {1, 1, 0, 0}, // #18
+ {1, 0, 0, 1}, // TypeVoid
+ {1, 0, 0, 1}, // TypeBool
+ {1, 0, 0, 1}, // TypeInt
+ {1, 0, 0, 1}, // TypeFloat
+ {1, 0, 0, 1}, // TypeVector
+ {1, 0, 0, 1}, // TypeMatrix
+ {1, 0, 0, 1}, // TypeImage
+ {1, 0, 0, 1}, // TypeSampler
+ {1, 0, 0, 1}, // TypeSampledImage
+ {1, 0, 0, 1}, // TypeArray
+ {1, 0, 0, 1}, // TypeRuntimeArray
+ {1, 0, 0, 1}, // TypeStruct
+ {1, 0, 0, 1}, // TypeOpaque
+ {1, 0, 0, 1}, // TypePointer
+ {1, 0, 0, 1}, // TypeFunction
+ {1, 0, 0, 1}, // TypeEvent
+ {1, 0, 0, 1}, // TypeDeviceEvent
+ {1, 0, 0, 1}, // TypeReserveId
+ {1, 0, 0, 1}, // TypeQueue
+ {1, 0, 0, 1}, // TypePipe
+ {0, 0, 0, 1}, // TypeForwardPointer
+ {1, 1, 0, 0}, // #40
+ {1, 1, 0, 0}, // ConstantTrue
+ {1, 1, 0, 0}, // ConstantFalse
+ {1, 1, 0, 0}, // Constant
+ {1, 1, 9, 0}, // ConstantComposite
+ {1, 1, 0, 1}, // ConstantSampler
+ {1, 1, 0, 0}, // ConstantNull
+ {1, 1, 0, 0}, // #47
+ {1, 1, 0, 0}, // SpecConstantTrue
+ {1, 1, 0, 0}, // SpecConstantFalse
+ {1, 1, 0, 0}, // SpecConstant
+ {1, 1, 9, 0}, // SpecConstantComposite
+ {1, 1, 0, 0}, // SpecConstantOp
+ {1, 1, 0, 0}, // #53
+ {1, 1, 0, 1}, // Function
+ {1, 1, 0, 0}, // FunctionParameter
+ {0, 0, 0, 0}, // FunctionEnd
+ {1, 1, 9, 0}, // FunctionCall
+ {1, 1, 0, 0}, // #58
+ {1, 1, 0, 1}, // Variable
+ {1, 1, 0, 0}, // ImageTexelPointer
+ {1, 1, 1, 1}, // Load
+ {0, 0, 2, 1}, // Store
+ {0, 0, 0, 0}, // CopyMemory
+ {0, 0, 0, 0}, // CopyMemorySized
+ {1, 1, 0, 1}, // AccessChain
+ {1, 1, 0, 0}, // InBoundsAccessChain
+ {1, 1, 0, 0}, // PtrAccessChain
+ {1, 1, 0, 0}, // ArrayLength
+ {1, 1, 0, 0}, // GenericPtrMemSemantics
+ {1, 1, 0, 0}, // InBoundsPtrAccessChain
+ {0, 0, 0, 1}, // Decorate
+ {0, 0, 0, 1}, // MemberDecorate
+ {1, 0, 0, 0}, // DecorationGroup
+ {0, 0, 0, 0}, // GroupDecorate
+ {0, 0, 0, 0}, // GroupMemberDecorate
+ {1, 1, 0, 0}, // #76
+ {1, 1, 1, 1}, // VectorExtractDynamic
+ {1, 1, 2, 1}, // VectorInsertDynamic
+ {1, 1, 2, 1}, // VectorShuffle
+ {1, 1, 9, 0}, // CompositeConstruct
+ {1, 1, 1, 1}, // CompositeExtract
+ {1, 1, 2, 1}, // CompositeInsert
+ {1, 1, 1, 0}, // CopyObject
+ {1, 1, 0, 0}, // Transpose
+ {1, 1, 0, 0}, // #85
+ {1, 1, 0, 0}, // SampledImage
+ {1, 1, 2, 1}, // ImageSampleImplicitLod
+ {1, 1, 2, 1}, // ImageSampleExplicitLod
+ {1, 1, 3, 1}, // ImageSampleDrefImplicitLod
+ {1, 1, 3, 1}, // ImageSampleDrefExplicitLod
+ {1, 1, 2, 1}, // ImageSampleProjImplicitLod
+ {1, 1, 2, 1}, // ImageSampleProjExplicitLod
+ {1, 1, 3, 1}, // ImageSampleProjDrefImplicitLod
+ {1, 1, 3, 1}, // ImageSampleProjDrefExplicitLod
+ {1, 1, 2, 1}, // ImageFetch
+ {1, 1, 3, 1}, // ImageGather
+ {1, 1, 3, 1}, // ImageDrefGather
+ {1, 1, 2, 1}, // ImageRead
+ {0, 0, 3, 1}, // ImageWrite
+ {1, 1, 1, 0}, // Image
+ {1, 1, 1, 0}, // ImageQueryFormat
+ {1, 1, 1, 0}, // ImageQueryOrder
+ {1, 1, 2, 0}, // ImageQuerySizeLod
+ {1, 1, 1, 0}, // ImageQuerySize
+ {1, 1, 2, 0}, // ImageQueryLod
+ {1, 1, 1, 0}, // ImageQueryLevels
+ {1, 1, 1, 0}, // ImageQuerySamples
+ {1, 1, 0, 0}, // #108
+ {1, 1, 1, 0}, // ConvertFToU
+ {1, 1, 1, 0}, // ConvertFToS
+ {1, 1, 1, 0}, // ConvertSToF
+ {1, 1, 1, 0}, // ConvertUToF
+ {1, 1, 1, 0}, // UConvert
+ {1, 1, 1, 0}, // SConvert
+ {1, 1, 1, 0}, // FConvert
+ {1, 1, 1, 0}, // QuantizeToF16
+ {1, 1, 1, 0}, // ConvertPtrToU
+ {1, 1, 1, 0}, // SatConvertSToU
+ {1, 1, 1, 0}, // SatConvertUToS
+ {1, 1, 1, 0}, // ConvertUToPtr
+ {1, 1, 1, 0}, // PtrCastToGeneric
+ {1, 1, 1, 0}, // GenericCastToPtr
+ {1, 1, 1, 1}, // GenericCastToPtrExplicit
+ {1, 1, 1, 0}, // Bitcast
+ {1, 1, 0, 0}, // #125
+ {1, 1, 1, 0}, // SNegate
+ {1, 1, 1, 0}, // FNegate
+ {1, 1, 2, 0}, // IAdd
+ {1, 1, 2, 0}, // FAdd
+ {1, 1, 2, 0}, // ISub
+ {1, 1, 2, 0}, // FSub
+ {1, 1, 2, 0}, // IMul
+ {1, 1, 2, 0}, // FMul
+ {1, 1, 2, 0}, // UDiv
+ {1, 1, 2, 0}, // SDiv
+ {1, 1, 2, 0}, // FDiv
+ {1, 1, 2, 0}, // UMod
+ {1, 1, 2, 0}, // SRem
+ {1, 1, 2, 0}, // SMod
+ {1, 1, 2, 0}, // FRem
+ {1, 1, 2, 0}, // FMod
+ {1, 1, 2, 0}, // VectorTimesScalar
+ {1, 1, 2, 0}, // MatrixTimesScalar
+ {1, 1, 2, 0}, // VectorTimesMatrix
+ {1, 1, 2, 0}, // MatrixTimesVector
+ {1, 1, 2, 0}, // MatrixTimesMatrix
+ {1, 1, 2, 0}, // OuterProduct
+ {1, 1, 2, 0}, // Dot
+ {1, 1, 2, 0}, // IAddCarry
+ {1, 1, 2, 0}, // ISubBorrow
+ {1, 1, 2, 0}, // UMulExtended
+ {1, 1, 2, 0}, // SMulExtended
+ {1, 1, 0, 0}, // #153
+ {1, 1, 1, 0}, // Any
+ {1, 1, 1, 0}, // All
+ {1, 1, 1, 0}, // IsNan
+ {1, 1, 1, 0}, // IsInf
+ {1, 1, 1, 0}, // IsFinite
+ {1, 1, 1, 0}, // IsNormal
+ {1, 1, 1, 0}, // SignBitSet
+ {1, 1, 2, 0}, // LessOrGreater
+ {1, 1, 2, 0}, // Ordered
+ {1, 1, 2, 0}, // Unordered
+ {1, 1, 2, 0}, // LogicalEqual
+ {1, 1, 2, 0}, // LogicalNotEqual
+ {1, 1, 2, 0}, // LogicalOr
+ {1, 1, 2, 0}, // LogicalAnd
+ {1, 1, 1, 0}, // LogicalNot
+ {1, 1, 3, 0}, // Select
+ {1, 1, 2, 0}, // IEqual
+ {1, 1, 2, 0}, // INotEqual
+ {1, 1, 2, 0}, // UGreaterThan
+ {1, 1, 2, 0}, // SGreaterThan
+ {1, 1, 2, 0}, // UGreaterThanEqual
+ {1, 1, 2, 0}, // SGreaterThanEqual
+ {1, 1, 2, 0}, // ULessThan
+ {1, 1, 2, 0}, // SLessThan
+ {1, 1, 2, 0}, // ULessThanEqual
+ {1, 1, 2, 0}, // SLessThanEqual
+ {1, 1, 2, 0}, // FOrdEqual
+ {1, 1, 2, 0}, // FUnordEqual
+ {1, 1, 2, 0}, // FOrdNotEqual
+ {1, 1, 2, 0}, // FUnordNotEqual
+ {1, 1, 2, 0}, // FOrdLessThan
+ {1, 1, 2, 0}, // FUnordLessThan
+ {1, 1, 2, 0}, // FOrdGreaterThan
+ {1, 1, 2, 0}, // FUnordGreaterThan
+ {1, 1, 2, 0}, // FOrdLessThanEqual
+ {1, 1, 2, 0}, // FUnordLessThanEqual
+ {1, 1, 2, 0}, // FOrdGreaterThanEqual
+ {1, 1, 2, 0}, // FUnordGreaterThanEqual
+ {1, 1, 0, 0}, // #192
+ {1, 1, 0, 0}, // #193
+ {1, 1, 2, 0}, // ShiftRightLogical
+ {1, 1, 2, 0}, // ShiftRightArithmetic
+ {1, 1, 2, 0}, // ShiftLeftLogical
+ {1, 1, 2, 0}, // BitwiseOr
+ {1, 1, 2, 0}, // BitwiseXor
+ {1, 1, 2, 0}, // BitwiseAnd
+ {1, 1, 1, 0}, // Not
+ {1, 1, 4, 0}, // BitFieldInsert
+ {1, 1, 3, 0}, // BitFieldSExtract
+ {1, 1, 3, 0}, // BitFieldUExtract
+ {1, 1, 1, 0}, // BitReverse
+ {1, 1, 1, 0}, // BitCount
+ {1, 1, 0, 0}, // #206
+ {1, 1, 0, 0}, // DPdx
+ {1, 1, 0, 0}, // DPdy
+ {1, 1, 0, 0}, // Fwidth
+ {1, 1, 0, 0}, // DPdxFine
+ {1, 1, 0, 0}, // DPdyFine
+ {1, 1, 0, 0}, // FwidthFine
+ {1, 1, 0, 0}, // DPdxCoarse
+ {1, 1, 0, 0}, // DPdyCoarse
+ {1, 1, 0, 0}, // FwidthCoarse
+ {1, 1, 0, 0}, // #216
+ {1, 1, 0, 0}, // #217
+ {0, 0, 0, 0}, // EmitVertex
+ {0, 0, 0, 0}, // EndPrimitive
+ {0, 0, 0, 0}, // EmitStreamVertex
+ {0, 0, 0, 0}, // EndStreamPrimitive
+ {1, 1, 0, 0}, // #222
+ {1, 1, 0, 0}, // #223
+ {0, 0, 3, 0}, // ControlBarrier
+ {0, 0, 2, 0}, // MemoryBarrier
+ {1, 1, 0, 0}, // #226
+ {1, 1, 0, 0}, // AtomicLoad
+ {0, 0, 0, 0}, // AtomicStore
+ {1, 1, 0, 0}, // AtomicExchange
+ {1, 1, 0, 0}, // AtomicCompareExchange
+ {1, 1, 0, 0}, // AtomicCompareExchangeWeak
+ {1, 1, 0, 0}, // AtomicIIncrement
+ {1, 1, 0, 0}, // AtomicIDecrement
+ {1, 1, 0, 0}, // AtomicIAdd
+ {1, 1, 0, 0}, // AtomicISub
+ {1, 1, 0, 0}, // AtomicSMin
+ {1, 1, 0, 0}, // AtomicUMin
+ {1, 1, 0, 0}, // AtomicSMax
+ {1, 1, 0, 0}, // AtomicUMax
+ {1, 1, 0, 0}, // AtomicAnd
+ {1, 1, 0, 0}, // AtomicOr
+ {1, 1, 0, 0}, // AtomicXor
+ {1, 1, 0, 0}, // #243
+ {1, 1, 0, 0}, // #244
+ {1, 1, 0, 0}, // Phi
+ {0, 0, 2, 1}, // LoopMerge
+ {0, 0, 1, 1}, // SelectionMerge
+ {1, 0, 0, 0}, // Label
+ {0, 0, 1, 0}, // Branch
+ {0, 0, 3, 1}, // BranchConditional
+ {0, 0, 0, 0}, // Switch
+ {0, 0, 0, 0}, // Kill
+ {0, 0, 0, 0}, // Return
+ {0, 0, 0, 0}, // ReturnValue
+ {0, 0, 0, 0}, // Unreachable
+ {0, 0, 0, 0}, // LifetimeStart
+ {0, 0, 0, 0}, // LifetimeStop
+ {1, 1, 0, 0}, // #258
+ {1, 1, 0, 0}, // GroupAsyncCopy
+ {0, 0, 0, 0}, // GroupWaitEvents
+ {1, 1, 0, 0}, // GroupAll
+ {1, 1, 0, 0}, // GroupAny
+ {1, 1, 0, 0}, // GroupBroadcast
+ {1, 1, 0, 0}, // GroupIAdd
+ {1, 1, 0, 0}, // GroupFAdd
+ {1, 1, 0, 0}, // GroupFMin
+ {1, 1, 0, 0}, // GroupUMin
+ {1, 1, 0, 0}, // GroupSMin
+ {1, 1, 0, 0}, // GroupFMax
+ {1, 1, 0, 0}, // GroupUMax
+ {1, 1, 0, 0}, // GroupSMax
+ {1, 1, 0, 0}, // #272
+ {1, 1, 0, 0}, // #273
+ {1, 1, 0, 0}, // ReadPipe
+ {1, 1, 0, 0}, // WritePipe
+ {1, 1, 0, 0}, // ReservedReadPipe
+ {1, 1, 0, 0}, // ReservedWritePipe
+ {1, 1, 0, 0}, // ReserveReadPipePackets
+ {1, 1, 0, 0}, // ReserveWritePipePackets
+ {0, 0, 0, 0}, // CommitReadPipe
+ {0, 0, 0, 0}, // CommitWritePipe
+ {1, 1, 0, 0}, // IsValidReserveId
+ {1, 1, 0, 0}, // GetNumPipePackets
+ {1, 1, 0, 0}, // GetMaxPipePackets
+ {1, 1, 0, 0}, // GroupReserveReadPipePackets
+ {1, 1, 0, 0}, // GroupReserveWritePipePackets
+ {0, 0, 0, 0}, // GroupCommitReadPipe
+ {0, 0, 0, 0}, // GroupCommitWritePipe
+ {1, 1, 0, 0}, // #289
+ {1, 1, 0, 0}, // #290
+ {1, 1, 0, 0}, // EnqueueMarker
+ {1, 1, 0, 0}, // EnqueueKernel
+ {1, 1, 0, 0}, // GetKernelNDrangeSubGroupCount
+ {1, 1, 0, 0}, // GetKernelNDrangeMaxSubGroupSize
+ {1, 1, 0, 0}, // GetKernelWorkGroupSize
+ {1, 1, 0, 0}, // GetKernelPreferredWorkGroupSizeMultiple
+ {0, 0, 0, 0}, // RetainEvent
+ {0, 0, 0, 0}, // ReleaseEvent
+ {1, 1, 0, 0}, // CreateUserEvent
+ {1, 1, 0, 0}, // IsValidEvent
+ {0, 0, 0, 0}, // SetUserEventStatus
+ {0, 0, 0, 0}, // CaptureEventProfilingInfo
+ {1, 1, 0, 0}, // GetDefaultQueue
+ {1, 1, 0, 0}, // BuildNDRange
+ {1, 1, 2, 1}, // ImageSparseSampleImplicitLod
+ {1, 1, 2, 1}, // ImageSparseSampleExplicitLod
+ {1, 1, 3, 1}, // ImageSparseSampleDrefImplicitLod
+ {1, 1, 3, 1}, // ImageSparseSampleDrefExplicitLod
+ {1, 1, 2, 1}, // ImageSparseSampleProjImplicitLod
+ {1, 1, 2, 1}, // ImageSparseSampleProjExplicitLod
+ {1, 1, 3, 1}, // ImageSparseSampleProjDrefImplicitLod
+ {1, 1, 3, 1}, // ImageSparseSampleProjDrefExplicitLod
+ {1, 1, 2, 1}, // ImageSparseFetch
+ {1, 1, 3, 1}, // ImageSparseGather
+ {1, 1, 3, 1}, // ImageSparseDrefGather
+ {1, 1, 1, 0}, // ImageSparseTexelsResident
+ {0, 0, 0, 0}, // NoLine
+ {1, 1, 0, 0}, // AtomicFlagTestAndSet
+ {0, 0, 0, 0}, // AtomicFlagClear
+ {1, 1, 0, 0}, // ImageSparseRead
+ {1, 1, 0, 0}, // SizeOf
+ {1, 1, 0, 0}, // TypePipeStorage
+ {1, 1, 0, 0}, // ConstantPipeStorage
+ {1, 1, 0, 0}, // CreatePipeFromPipeStorage
+ {1, 1, 0, 0}, // GetKernelLocalSizeForSubgroupCount
+ {1, 1, 0, 0}, // GetKernelMaxNumSubgroups
+ {1, 1, 0, 0}, // TypeNamedBarrier
+ {1, 1, 0, 1}, // NamedBarrierInitialize
+ {0, 0, 2, 1}, // MemoryNamedBarrier
+ {1, 1, 0, 0}, // ModuleProcessed
+ {0, 0, 0, 1}, // ExecutionModeId
+ {0, 0, 0, 1}, // DecorateId
+ {1, 1, 1, 1}, // GroupNonUniformElect
+ {1, 1, 1, 1}, // GroupNonUniformAll
+ {1, 1, 1, 1}, // GroupNonUniformAny
+ {1, 1, 1, 1}, // GroupNonUniformAllEqual
+ {1, 1, 1, 1}, // GroupNonUniformBroadcast
+ {1, 1, 1, 1}, // GroupNonUniformBroadcastFirst
+ {1, 1, 1, 1}, // GroupNonUniformBallot
+ {1, 1, 1, 1}, // GroupNonUniformInverseBallot
+ {1, 1, 1, 1}, // GroupNonUniformBallotBitExtract
+ {1, 1, 1, 1}, // GroupNonUniformBallotBitCount
+ {1, 1, 1, 1}, // GroupNonUniformBallotFindLSB
+ {1, 1, 1, 1}, // GroupNonUniformBallotFindMSB
+ {1, 1, 1, 1}, // GroupNonUniformShuffle
+ {1, 1, 1, 1}, // GroupNonUniformShuffleXor
+ {1, 1, 1, 1}, // GroupNonUniformShuffleUp
+ {1, 1, 1, 1}, // GroupNonUniformShuffleDown
+ {1, 1, 1, 1}, // GroupNonUniformIAdd
+ {1, 1, 1, 1}, // GroupNonUniformFAdd
+ {1, 1, 1, 1}, // GroupNonUniformIMul
+ {1, 1, 1, 1}, // GroupNonUniformFMul
+ {1, 1, 1, 1}, // GroupNonUniformSMin
+ {1, 1, 1, 1}, // GroupNonUniformUMin
+ {1, 1, 1, 1}, // GroupNonUniformFMin
+ {1, 1, 1, 1}, // GroupNonUniformSMax
+ {1, 1, 1, 1}, // GroupNonUniformUMax
+ {1, 1, 1, 1}, // GroupNonUniformFMax
+ {1, 1, 1, 1}, // GroupNonUniformBitwiseAnd
+ {1, 1, 1, 1}, // GroupNonUniformBitwiseOr
+ {1, 1, 1, 1}, // GroupNonUniformBitwiseXor
+ {1, 1, 1, 1}, // GroupNonUniformLogicalAnd
+ {1, 1, 1, 1}, // GroupNonUniformLogicalOr
+ {1, 1, 1, 1}, // GroupNonUniformLogicalXor
+ {1, 1, 1, 1}, // GroupNonUniformQuadBroadcast
+ {1, 1, 1, 1}, // GroupNonUniformQuadSwap
+};
+static_assert(_SMOLV_ARRAY_SIZE(kSpirvOpData) == kKnownOpsCount, "kSpirvOpData table mismatch with known SpvOps");
+
+// Instruction encoding depends on the table that describes the various SPIR-V opcodes.
+// Whenever we change or expand the table, we need to bump up the SMOL-V version, and make
+// sure that we can still decode files encoded by an older version.
+static int smolv_GetKnownOpsCount(int version)
+{
+ if (version == 0)
+ return SpvOpModuleProcessed+1;
+ if (version == 1) // 2020 February, version 1 added ExecutionModeId..GroupNonUniformQuadSwap
+ return SpvOpGroupNonUniformQuadSwap+1;
+ return 0;
+}
+
+static bool smolv_OpHasResult(SpvOp op, int opsCount)
+{
+ if (op < 0 || op >= opsCount)
+ return false;
+ return kSpirvOpData[op].hasResult != 0;
+}
+
+static bool smolv_OpHasType(SpvOp op, int opsCount)
+{
+ if (op < 0 || op >= opsCount)
+ return false;
+ return kSpirvOpData[op].hasType != 0;
+}
+
+static int smolv_OpDeltaFromResult(SpvOp op, int opsCount)
+{
+ if (op < 0 || op >= opsCount)
+ return 0;
+ return kSpirvOpData[op].deltaFromResult;
+}
+
+static bool smolv_OpVarRest(SpvOp op, int opsCount)
+{
+ if (op < 0 || op >= opsCount)
+ return false;
+ return kSpirvOpData[op].varrest != 0;
+}
+
+static bool smolv_OpDebugInfo(SpvOp op, int opsCount)
+{
+ return
+ op == SpvOpSourceContinued ||
+ op == SpvOpSource ||
+ op == SpvOpSourceExtension ||
+ op == SpvOpName ||
+ op == SpvOpMemberName ||
+ op == SpvOpString ||
+ op == SpvOpLine ||
+ op == SpvOpNoLine ||
+ op == SpvOpModuleProcessed;
+}
+
+
+static int smolv_DecorationExtraOps(int dec)
+{
+ if (dec == 0 || (dec >= 2 && dec <= 5)) // RelaxedPrecision, Block..ColMajor
+ return 0;
+ if (dec >= 29 && dec <= 37) // Stream..XfbStride
+ return 1;
+ return -1; // unknown, encode length
+}
+
+
+// --------------------------------------------------------------------------------------------
+
+
+static bool smolv_CheckGenericHeader(const uint32_t* words, size_t wordCount, uint32_t expectedMagic, uint32_t versionMask)
+{
+ if (!words)
+ return false;
+ if (wordCount < 5)
+ return false;
+
+ uint32_t headerMagic = words[0];
+ if (headerMagic != expectedMagic)
+ return false;
+ uint32_t headerVersion = words[1] & versionMask;
+ if (headerVersion < 0x00010000 || headerVersion > 0x00010500)
+ return false; // only support 1.0 through 1.5
+
+ return true;
+}
+
+static const int kSpirVHeaderMagic = 0x07230203;
+static const int kSmolHeaderMagic = 0x534D4F4C; // "SMOL"
+
+static const int kSmolCurrEncodingVersion = 1;
+
+static bool smolv_CheckSpirVHeader(const uint32_t* words, size_t wordCount)
+{
+ //@TODO: if SPIR-V header magic was reversed, that means the file got written
+ // in a "big endian" order. Need to byteswap all words then.
+ return smolv_CheckGenericHeader(words, wordCount, kSpirVHeaderMagic, 0xFFFFFFFF);
+}
+static bool smolv_CheckSmolHeader(const uint8_t* bytes, size_t byteCount)
+{
+ if (!smolv_CheckGenericHeader((const uint32_t*)bytes, byteCount/4, kSmolHeaderMagic, 0x00FFFFFF))
+ return false;
+ if (byteCount < 24) // one more word past header to store decoded length
+ return false;
+ // SMOL-V version
+ int smolVersion = ((const uint32_t*)bytes)[1] >> 24;
+ if (smolVersion < 0 || smolVersion > kSmolCurrEncodingVersion)
+ return false;
+ return true;
+}
+
+
+static void smolv_Write4(smolv::ByteArray& arr, uint32_t v)
+{
+ arr.push_back(v & 0xFF);
+ arr.push_back((v >> 8) & 0xFF);
+ arr.push_back((v >> 16) & 0xFF);
+ arr.push_back(v >> 24);
+}
+
+static void smolv_Write4(uint8_t*& buf, uint32_t v)
+{
+ memcpy(buf, &v, 4);
+ buf += 4;
+}
+
+
+static bool smolv_Read4(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outv)
+{
+ if (data + 4 > dataEnd)
+ return false;
+ outv = (data[0]) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+ data += 4;
+ return true;
+}
+
+
+// --------------------------------------------------------------------------------------------
+
+// Variable-length integer encoding for unsigned integers. In each byte:
+// - highest bit set if more bytes follow, cleared if this is last byte.
+// - other 7 bits are the actual value payload.
+// Takes 1-5 bytes to encode an integer (values between 0 and 127 take one byte, etc.).
+
+static void smolv_WriteVarint(smolv::ByteArray& arr, uint32_t v)
+{
+ while (v > 127)
+ {
+ arr.push_back((v & 127) | 128);
+ v >>= 7;
+ }
+ arr.push_back(v & 127);
+}
+
+static bool smolv_ReadVarint(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outVal)
+{
+ uint32_t v = 0;
+ uint32_t shift = 0;
+ while (data < dataEnd)
+ {
+ uint8_t b = *data;
+ v |= (b & 127) << shift;
+ shift += 7;
+ data++;
+ if (!(b & 128))
+ break;
+ }
+ outVal = v;
+ return true; //@TODO: report failures
+}
+
+static uint32_t smolv_ZigEncode(int32_t i)
+{
+ return (uint32_t(i) << 1) ^ (i >> 31);
+}
+
+static int32_t smolv_ZigDecode(uint32_t u)
+{
+ return (u & 1) ? ((u >> 1) ^ ~0) : (u >> 1);
+}
+
+
+// Remap most common Op codes (Load, Store, Decorate, VectorShuffle etc.) to be in < 16 range, for
+// more compact varint encoding. This basically swaps rarely used op values that are < 16 with the
+// ones that are common.
+
+static SpvOp smolv_RemapOp(SpvOp op)
+{
+# define _SMOLV_SWAP_OP(op1,op2) if (op==op1) return op2; if (op==op2) return op1
+ _SMOLV_SWAP_OP(SpvOpDecorate,SpvOpNop); // 0: 24%
+ _SMOLV_SWAP_OP(SpvOpLoad,SpvOpUndef); // 1: 17%
+ _SMOLV_SWAP_OP(SpvOpStore,SpvOpSourceContinued); // 2: 9%
+ _SMOLV_SWAP_OP(SpvOpAccessChain,SpvOpSource); // 3: 7.2%
+ _SMOLV_SWAP_OP(SpvOpVectorShuffle,SpvOpSourceExtension); // 4: 5.0%
+ // Name - already small enum value - 5: 4.4%
+ // MemberName - already small enum value - 6: 2.9%
+ _SMOLV_SWAP_OP(SpvOpMemberDecorate,SpvOpString); // 7: 4.0%
+ _SMOLV_SWAP_OP(SpvOpLabel,SpvOpLine); // 8: 0.9%
+ _SMOLV_SWAP_OP(SpvOpVariable,(SpvOp)9); // 9: 3.9%
+ _SMOLV_SWAP_OP(SpvOpFMul,SpvOpExtension); // 10: 3.9%
+ _SMOLV_SWAP_OP(SpvOpFAdd,SpvOpExtInstImport); // 11: 2.5%
+ // ExtInst - already small enum value - 12: 1.2%
+ // VectorShuffleCompact - already small enum value - used for compact shuffle encoding
+ _SMOLV_SWAP_OP(SpvOpTypePointer,SpvOpMemoryModel); // 14: 2.2%
+ _SMOLV_SWAP_OP(SpvOpFNegate,SpvOpEntryPoint); // 15: 1.1%
+# undef _SMOLV_SWAP_OP
+ return op;
+}
+
+
+// For most compact varint encoding of common instructions, the instruction length should come out
+// into 3 bits (be <8). SPIR-V instruction lengths are always at least 1, and for some other
+// instructions they are guaranteed to be some other minimum length. Adjust the length before encoding,
+// and after decoding accordingly.
+
+static uint32_t smolv_EncodeLen(SpvOp op, uint32_t len)
+{
+ len--;
+ if (op == SpvOpVectorShuffle) len -= 4;
+ if (op == SpvOpVectorShuffleCompact) len -= 4;
+ if (op == SpvOpDecorate) len -= 2;
+ if (op == SpvOpLoad) len -= 3;
+ if (op == SpvOpAccessChain) len -= 3;
+ return len;
+}
+
+static uint32_t smolv_DecodeLen(SpvOp op, uint32_t len)
+{
+ len++;
+ if (op == SpvOpVectorShuffle) len += 4;
+ if (op == SpvOpVectorShuffleCompact) len += 4;
+ if (op == SpvOpDecorate) len += 2;
+ if (op == SpvOpLoad) len += 3;
+ if (op == SpvOpAccessChain) len += 3;
+ return len;
+}
+
+
+// Shuffling bits of length + opcode to be more compact in varint encoding in typical cases:
+// 0x LLLL OOOO is how SPIR-V encodes it (L=length, O=op), we shuffle into:
+// 0x LLLO OOLO, so that common case (op<16, len<8) is encoded into one byte.
+
+static bool smolv_WriteLengthOp(smolv::ByteArray& arr, uint32_t len, SpvOp op)
+{
+ len = smolv_EncodeLen(op, len);
+ // SPIR-V length field is 16 bits; if we get a larger value that means something
+ // was wrong, e.g. a vector shuffle instruction with less than 4 words (and our
+ // adjustment to common lengths in smolv_EncodeLen wrapped around)
+ if (len > 0xFFFF)
+ return false;
+ op = smolv_RemapOp(op);
+ uint32_t oplen = ((len >> 4) << 20) | ((op >> 4) << 8) | ((len & 0xF) << 4) | (op & 0xF);
+ smolv_WriteVarint(arr, oplen);
+ return true;
+}
+
+static bool smolv_ReadLengthOp(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outLen, SpvOp& outOp)
+{
+ uint32_t val;
+ if (!smolv_ReadVarint(data, dataEnd, val))
+ return false;
+ outLen = ((val >> 20) << 4) | ((val >> 4) & 0xF);
+ outOp = (SpvOp)(((val >> 4) & 0xFFF0) | (val & 0xF));
+
+ outOp = smolv_RemapOp(outOp);
+ outLen = smolv_DecodeLen(outOp, outLen);
+ return true;
+}
+
+
+
+#define _SMOLV_READ_OP(len, words, op) \
+ uint32_t len = words[0] >> 16; \
+ if (len < 1) return false; /* malformed instruction, length needs to be at least 1 */ \
+ if (words + len > wordsEnd) return false; /* malformed instruction, goes past end of data */ \
+ SpvOp op = (SpvOp)(words[0] & 0xFFFF)
+
+
+bool smolv::Encode(const void* spirvData, size_t spirvSize, ByteArray& outSmolv, uint32_t flags, StripOpNameFilterFunc stripFilter)
+{
+ const size_t wordCount = spirvSize / 4;
+ if (wordCount * 4 != spirvSize)
+ return false;
+ const uint32_t* words = (const uint32_t*)spirvData;
+ const uint32_t* wordsEnd = words + wordCount;
+ if (!smolv_CheckSpirVHeader(words, wordCount))
+ return false;
+
+ // reserve space in output (typical compression is to about 30%; reserve half of input space)
+ outSmolv.reserve(outSmolv.size() + spirvSize/2);
+
+ // header (matches SPIR-V one, except different magic)
+ smolv_Write4(outSmolv, kSmolHeaderMagic);
+ smolv_Write4(outSmolv, (words[1] & 0x00FFFFFF) + (kSmolCurrEncodingVersion<<24)); // SPIR-V version (_XXX) + SMOL-V version (X___)
+ smolv_Write4(outSmolv, words[2]); // generator
+ smolv_Write4(outSmolv, words[3]); // bound
+ smolv_Write4(outSmolv, words[4]); // schema
+
+ const size_t headerSpirvSizeOffset = outSmolv.size(); // size field may get updated later if stripping is enabled
+ smolv_Write4(outSmolv, (uint32_t)spirvSize); // space needed to decode (i.e. original SPIR-V size)
+
+ size_t strippedSpirvWordCount = wordCount;
+ uint32_t prevResult = 0;
+ uint32_t prevDecorate = 0;
+
+ const int knownOpsCount = smolv_GetKnownOpsCount(kSmolCurrEncodingVersion);
+
+ words += 5;
+ while (words < wordsEnd)
+ {
+ _SMOLV_READ_OP(instrLen, words, op);
+
+ if ((flags & kEncodeFlagStripDebugInfo) && smolv_OpDebugInfo(op, knownOpsCount))
+ {
+ if (!stripFilter || op != SpvOpName || !stripFilter(reinterpret_cast<const char*>(&words[2])))
+ {
+ strippedSpirvWordCount -= instrLen;
+ words += instrLen;
+ continue;
+ }
+ }
+
+ // A usual case of vector shuffle, with less than 4 components, each with a value
+ // in [0..3] range: encode it in a more compact form, with the swizzle pattern in one byte.
+ // Turn this into a VectorShuffleCompact instruction, that takes up unused slot in Ops.
+ uint32_t swizzle = 0;
+ if (op == SpvOpVectorShuffle && instrLen <= 9)
+ {
+ uint32_t swz0 = instrLen > 5 ? words[5] : 0;
+ uint32_t swz1 = instrLen > 6 ? words[6] : 0;
+ uint32_t swz2 = instrLen > 7 ? words[7] : 0;
+ uint32_t swz3 = instrLen > 8 ? words[8] : 0;
+ if (swz0 < 4 && swz1 < 4 && swz2 < 4 && swz3 < 4)
+ {
+ op = SpvOpVectorShuffleCompact;
+ swizzle = (swz0 << 6) | (swz1 << 4) | (swz2 << 2) | (swz3);
+ }
+ }
+
+ // length + opcode
+ if (!smolv_WriteLengthOp(outSmolv, instrLen, op))
+ return false;
+
+ size_t ioffs = 1;
+ // write type as varint, if we have it
+ if (smolv_OpHasType(op, knownOpsCount))
+ {
+ if (ioffs >= instrLen)
+ return false;
+ smolv_WriteVarint(outSmolv, words[ioffs]);
+ ioffs++;
+ }
+ // write result as delta+zig+varint, if we have it
+ if (smolv_OpHasResult(op, knownOpsCount))
+ {
+ if (ioffs >= instrLen)
+ return false;
+ uint32_t v = words[ioffs];
+ smolv_WriteVarint(outSmolv, smolv_ZigEncode(v - prevResult)); // some deltas are negative, use zig
+ prevResult = v;
+ ioffs++;
+ }
+
+ // Decorate & MemberDecorate: IDs relative to previous decorate
+ if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
+ {
+ if (ioffs >= instrLen)
+ return false;
+ uint32_t v = words[ioffs];
+ smolv_WriteVarint(outSmolv, smolv_ZigEncode(v - prevDecorate)); // spirv-remapped deltas often negative, use zig
+ prevDecorate = v;
+ ioffs++;
+ }
+
+ // MemberDecorate special encoding: whole row of MemberDecorate instructions is often referring
+ // to the same type and linearly increasing member indices. Scan ahead to see how many we have,
+ // and encode whole bunch as one.
+ if (op == SpvOpMemberDecorate)
+ {
+ // scan ahead until we reach end, non-member-decoration or different type
+ const uint32_t decorationType = words[ioffs-1];
+ const uint32_t* memberWords = words;
+ uint32_t prevIndex = 0;
+ uint32_t prevOffset = 0;
+ // write a byte on how many we have encoded as a bunch
+ size_t countLocation = outSmolv.size();
+ outSmolv.push_back(0);
+ int count = 0;
+ while (memberWords < wordsEnd && count < 255)
+ {
+ _SMOLV_READ_OP(memberLen, memberWords, memberOp);
+ if (memberOp != SpvOpMemberDecorate)
+ break;
+ if (memberLen < 4)
+ return false; // invalid input
+ if (memberWords[1] != decorationType)
+ break;
+
+ // write member index as delta from previous
+ uint32_t memberIndex = memberWords[2];
+ smolv_WriteVarint(outSmolv, memberIndex - prevIndex);
+ prevIndex = memberIndex;
+
+ // decoration (and length if not common/known)
+ uint32_t memberDec = memberWords[3];
+ smolv_WriteVarint(outSmolv, memberDec);
+ const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
+ if (knownExtraOps == -1)
+ smolv_WriteVarint(outSmolv, memberLen-4);
+ else if (unsigned(knownExtraOps) + 4 != memberLen)
+ return false; // invalid input
+
+ // Offset decorations are most often linearly increasing, so encode as deltas
+ if (memberDec == 35) // Offset
+ {
+ if (memberLen != 5)
+ return false;
+ smolv_WriteVarint(outSmolv, memberWords[4]-prevOffset);
+ prevOffset = memberWords[4];
+ }
+ else
+ {
+ // write rest of decorations as varint
+ for (uint32_t i = 4; i < memberLen; ++i)
+ smolv_WriteVarint(outSmolv, memberWords[i]);
+ }
+
+ memberWords += memberLen;
+ ++count;
+ }
+ outSmolv[countLocation] = uint8_t(count);
+ words = memberWords;
+ continue;
+ }
+
+ // Write out this many IDs, encoding them relative+zigzag to result ID
+ int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
+ for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
+ {
+ if (ioffs >= instrLen)
+ return false;
+ uint32_t delta = prevResult - words[ioffs];
+ // some deltas are negative (often on branches, or if program was processed by spirv-remap),
+ // so use zig encoding
+ smolv_WriteVarint(outSmolv, smolv_ZigEncode(delta));
+ }
+
+ if (op == SpvOpVectorShuffleCompact)
+ {
+ // compact vector shuffle, just write out single swizzle byte
+ outSmolv.push_back(uint8_t(swizzle));
+ ioffs = instrLen;
+ }
+ else if (smolv_OpVarRest(op, knownOpsCount))
+ {
+ // write out rest of words with variable encoding (expected to be small integers)
+ for (; ioffs < instrLen; ++ioffs)
+ smolv_WriteVarint(outSmolv, words[ioffs]);
+ }
+ else
+ {
+ // write out rest of words without any encoding
+ for (; ioffs < instrLen; ++ioffs)
+ smolv_Write4(outSmolv, words[ioffs]);
+ }
+
+ words += instrLen;
+ }
+
+ if (strippedSpirvWordCount != wordCount)
+ {
+ uint8_t* headerSpirvSize = &outSmolv[headerSpirvSizeOffset];
+ smolv_Write4(headerSpirvSize, (uint32_t)strippedSpirvWordCount * 4);
+ }
+
+ return true;
+}
+
+
+size_t smolv::GetDecodedBufferSize(const void* smolvData, size_t smolvSize)
+{
+ if (!smolv_CheckSmolHeader((const uint8_t*)smolvData, smolvSize))
+ return 0;
+ const uint32_t* words = (const uint32_t*)smolvData;
+ return words[5];
+}
+
+
+bool smolv::Decode(const void* smolvData, size_t smolvSize, void* spirvOutputBuffer, size_t spirvOutputBufferSize, uint32_t flags)
+{
+ // check header, and whether we have enough output buffer space
+ const size_t neededBufferSize = GetDecodedBufferSize(smolvData, smolvSize);
+ if (neededBufferSize == 0)
+ return false; // invalid SMOL-V
+ if (spirvOutputBufferSize < neededBufferSize)
+ return false; // not enough space in output buffer
+ if (spirvOutputBuffer == NULL)
+ return false; // output buffer is null
+
+ const uint8_t* bytes = (const uint8_t*)smolvData;
+ const uint8_t* bytesEnd = bytes + smolvSize;
+
+ uint8_t* outSpirv = (uint8_t*)spirvOutputBuffer;
+
+ uint32_t val;
+ int smolVersion = 0;
+
+ // header
+ smolv_Write4(outSpirv, kSpirVHeaderMagic); bytes += 4;
+ smolv_Read4(bytes, bytesEnd, val); smolVersion = val >> 24; val &= 0x00FFFFFF; smolv_Write4(outSpirv, val); // version
+ smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // generator
+ smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // bound
+ smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // schema
+ bytes += 4; // decode buffer size
+
+ // there are two SMOL-V encoding versions, both not indicating anything in their header version field:
+ // one that is called "before zero" here (2016-08-31 code). Support decoding that one only by presence
+ // of this special flag.
+ const bool beforeZeroVersion = smolVersion == 0 && (flags & kDecodeFlagUse20160831AsZeroVersion) != 0;
+
+ const int knownOpsCount = smolv_GetKnownOpsCount(smolVersion);
+
+ uint32_t prevResult = 0;
+ uint32_t prevDecorate = 0;
+
+ while (bytes < bytesEnd)
+ {
+ // read length + opcode
+ uint32_t instrLen;
+ SpvOp op;
+ if (!smolv_ReadLengthOp(bytes, bytesEnd, instrLen, op))
+ return false;
+ const bool wasSwizzle = (op == SpvOpVectorShuffleCompact);
+ if (wasSwizzle)
+ op = SpvOpVectorShuffle;
+ smolv_Write4(outSpirv, (instrLen << 16) | op);
+
+ size_t ioffs = 1;
+
+ // read type as varint, if we have it
+ if (smolv_OpHasType(op, knownOpsCount))
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ smolv_Write4(outSpirv, val);
+ ioffs++;
+ }
+ // read result as delta+varint, if we have it
+ if (smolv_OpHasResult(op, knownOpsCount))
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ val = prevResult + smolv_ZigDecode(val);
+ smolv_Write4(outSpirv, val);
+ prevResult = val;
+ ioffs++;
+ }
+
+ // Decorate: IDs relative to previous decorate
+ if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ // "before zero" version did not use zig encoding for the value
+ val = prevDecorate + (beforeZeroVersion ? val : smolv_ZigDecode(val));
+ smolv_Write4(outSpirv, val);
+ prevDecorate = val;
+ ioffs++;
+ }
+
+ // MemberDecorate special decoding
+ if (op == SpvOpMemberDecorate && !beforeZeroVersion)
+ {
+ if (bytes >= bytesEnd)
+ return false; // broken input
+ int count = *bytes++;
+ int prevIndex = 0;
+ int prevOffset = 0;
+ for (int m = 0; m < count; ++m)
+ {
+ // read member index
+ uint32_t memberIndex;
+ if (!smolv_ReadVarint(bytes, bytesEnd, memberIndex)) return false;
+ memberIndex += prevIndex;
+ prevIndex = memberIndex;
+
+ // decoration (and length if not common/known)
+ uint32_t memberDec;
+ if (!smolv_ReadVarint(bytes, bytesEnd, memberDec)) return false;
+ const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
+ uint32_t memberLen;
+ if (knownExtraOps == -1)
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, memberLen)) return false;
+ memberLen += 4;
+ }
+ else
+ memberLen = 4 + knownExtraOps;
+
+ // write SPIR-V op+length (unless it's first member decoration, in which case it was written before)
+ if (m != 0)
+ {
+ smolv_Write4(outSpirv, (memberLen << 16) | op);
+ smolv_Write4(outSpirv, prevDecorate);
+ }
+ smolv_Write4(outSpirv, memberIndex);
+ smolv_Write4(outSpirv, memberDec);
+ // Special case for Offset decorations
+ if (memberDec == 35) // Offset
+ {
+ if (memberLen != 5)
+ return false;
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ val += prevOffset;
+ smolv_Write4(outSpirv, val);
+ prevOffset = val;
+ }
+ else
+ {
+ for (uint32_t i = 4; i < memberLen; ++i)
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ smolv_Write4(outSpirv, val);
+ }
+ }
+ }
+ continue;
+ }
+
+ // Read this many IDs, that are relative to result ID
+ int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
+ // "before zero" version only used zig encoding for IDs of several ops; after
+ // that ops got zig encoding for their IDs
+ bool zigDecodeVals = true;
+ if (beforeZeroVersion)
+ {
+ if (op != SpvOpControlBarrier && op != SpvOpMemoryBarrier && op != SpvOpLoopMerge && op != SpvOpSelectionMerge && op != SpvOpBranch && op != SpvOpBranchConditional && op != SpvOpMemoryNamedBarrier)
+ zigDecodeVals = false;
+ }
+ for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ if (zigDecodeVals)
+ val = smolv_ZigDecode(val);
+ smolv_Write4(outSpirv, prevResult - val);
+ }
+
+ if (wasSwizzle && instrLen <= 9)
+ {
+ uint32_t swizzle = *bytes++;
+ if (instrLen > 5) smolv_Write4(outSpirv, (swizzle >> 6) & 3);
+ if (instrLen > 6) smolv_Write4(outSpirv, (swizzle >> 4) & 3);
+ if (instrLen > 7) smolv_Write4(outSpirv, (swizzle >> 2) & 3);
+ if (instrLen > 8) smolv_Write4(outSpirv, swizzle & 3);
+ }
+ else if (smolv_OpVarRest(op, knownOpsCount))
+ {
+ // read rest of words with variable encoding
+ for (; ioffs < instrLen; ++ioffs)
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ smolv_Write4(outSpirv, val);
+ }
+ }
+ else
+ {
+ // read rest of words without any encoding
+ for (; ioffs < instrLen; ++ioffs)
+ {
+ if (!smolv_Read4(bytes, bytesEnd, val)) return false;
+ smolv_Write4(outSpirv, val);
+ }
+ }
+ }
+
+ if ((uint8_t*)spirvOutputBuffer + neededBufferSize != outSpirv)
+ return false; // something went wrong during decoding? we should have decoded to exact output size
+
+ return true;
+}
+
+
+
+// --------------------------------------------------------------------------------------------
+// Calculating instruction count / space stats on SPIR-V and SMOL-V
+
+
+struct smolv::Stats
+{
+ Stats() { memset(this, 0, sizeof(*this)); }
+ size_t opCounts[kKnownOpsCount];
+ size_t opSizes[kKnownOpsCount];
+ size_t smolOpSizes[kKnownOpsCount];
+ size_t varintCountsOp[6];
+ size_t varintCountsType[6];
+ size_t varintCountsRes[6];
+ size_t varintCountsOther[6];
+ size_t totalOps;
+ size_t totalSize;
+ size_t totalSizeSmol;
+ size_t inputCount;
+};
+
+
+smolv::Stats* smolv::StatsCreate()
+{
+ return new Stats();
+}
+
+void smolv::StatsDelete(smolv::Stats *s)
+{
+ delete s;
+}
+
+
+bool smolv::StatsCalculate(smolv::Stats* stats, const void* spirvData, size_t spirvSize)
+{
+ if (!stats)
+ return false;
+
+ const size_t wordCount = spirvSize / 4;
+ if (wordCount * 4 != spirvSize)
+ return false;
+ const uint32_t* words = (const uint32_t*)spirvData;
+ const uint32_t* wordsEnd = words + wordCount;
+ if (!smolv_CheckSpirVHeader(words, wordCount))
+ return false;
+ words += 5;
+
+ stats->inputCount++;
+ stats->totalSize += wordCount;
+
+ while (words < wordsEnd)
+ {
+ _SMOLV_READ_OP(instrLen, words, op);
+
+ if (op < kKnownOpsCount)
+ {
+ stats->opCounts[op]++;
+ stats->opSizes[op] += instrLen;
+ }
+ words += instrLen;
+ stats->totalOps++;
+ }
+
+ return true;
+}
+
+
+bool smolv::StatsCalculateSmol(smolv::Stats* stats, const void* smolvData, size_t smolvSize)
+{
+ if (!stats)
+ return false;
+
+ // debugging helper to dump all encoded bytes to stdout, keep at "if 0"
+# if 0
+# define _SMOLV_DEBUG_PRINT_ENCODED_BYTES() { \
+ printf("Op %-22s ", op < kKnownOpsCount ? kSpirvOpNames[op] : "???"); \
+ for (const uint8_t* b = instrBegin; b < bytes; ++b) \
+ printf("%02x ", *b); \
+ printf("\n"); \
+ }
+# else
+# define _SMOLV_DEBUG_PRINT_ENCODED_BYTES() {}
+# endif
+
+ const uint8_t* bytes = (const uint8_t*)smolvData;
+ const uint8_t* bytesEnd = bytes + smolvSize;
+ if (!smolv_CheckSmolHeader(bytes, smolvSize))
+ return false;
+
+ uint32_t val;
+ int smolVersion;
+ bytes += 4;
+ smolv_Read4(bytes, bytesEnd, val); smolVersion = val >> 24;
+ const int knownOpsCount = smolv_GetKnownOpsCount(smolVersion);
+ bytes += 16;
+
+ stats->totalSizeSmol += smolvSize;
+
+ while (bytes < bytesEnd)
+ {
+ const uint8_t* instrBegin = bytes;
+ const uint8_t* varBegin;
+
+ // read length + opcode
+ uint32_t instrLen;
+ SpvOp op;
+ varBegin = bytes;
+ if (!smolv_ReadLengthOp(bytes, bytesEnd, instrLen, op))
+ return false;
+ const bool wasSwizzle = (op == SpvOpVectorShuffleCompact);
+ if (wasSwizzle)
+ op = SpvOpVectorShuffle;
+ stats->varintCountsOp[bytes-varBegin]++;
+
+ size_t ioffs = 1;
+ if (smolv_OpHasType(op, knownOpsCount))
+ {
+ varBegin = bytes;
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ stats->varintCountsType[bytes-varBegin]++;
+ ioffs++;
+ }
+ if (smolv_OpHasResult(op, knownOpsCount))
+ {
+ varBegin = bytes;
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ stats->varintCountsRes[bytes-varBegin]++;
+ ioffs++;
+ }
+
+ if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ ioffs++;
+ }
+ // MemberDecorate special decoding
+ if (op == SpvOpMemberDecorate)
+ {
+ if (bytes >= bytesEnd)
+ return false; // broken input
+ int count = *bytes++;
+ for (int m = 0; m < count; ++m)
+ {
+ uint32_t memberIndex;
+ if (!smolv_ReadVarint(bytes, bytesEnd, memberIndex)) return false;
+ uint32_t memberDec;
+ if (!smolv_ReadVarint(bytes, bytesEnd, memberDec)) return false;
+ const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
+ uint32_t memberLen;
+ if (knownExtraOps == -1)
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, memberLen)) return false;
+ memberLen += 4;
+ }
+ else
+ memberLen = 4 + knownExtraOps;
+ for (uint32_t i = 4; i < memberLen; ++i)
+ {
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ }
+ }
+ stats->smolOpSizes[op] += bytes - instrBegin;
+ _SMOLV_DEBUG_PRINT_ENCODED_BYTES();
+ continue;
+ }
+
+ int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
+ for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
+ {
+ varBegin = bytes;
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ stats->varintCountsRes[bytes-varBegin]++;
+ }
+
+ if (wasSwizzle && instrLen <= 9)
+ {
+ bytes++;
+ }
+ else if (smolv_OpVarRest(op, knownOpsCount))
+ {
+ for (; ioffs < instrLen; ++ioffs)
+ {
+ varBegin = bytes;
+ if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
+ stats->varintCountsOther[bytes-varBegin]++;
+ }
+ }
+ else
+ {
+ for (; ioffs < instrLen; ++ioffs)
+ {
+ if (!smolv_Read4(bytes, bytesEnd, val)) return false;
+ }
+ }
+
+ if (op < kKnownOpsCount)
+ {
+ stats->smolOpSizes[op] += bytes - instrBegin;
+ }
+ _SMOLV_DEBUG_PRINT_ENCODED_BYTES();
+ }
+
+ return true;
+}
+
+static bool CompareOpCounters (std::pair<SpvOp,size_t> a, std::pair<SpvOp,size_t> b)
+{
+ return a.second > b.second;
+}
+
+void smolv::StatsPrint(const Stats* stats)
+{
+ if (!stats)
+ return;
+
+ typedef std::pair<SpvOp,size_t> OpCounter;
+ OpCounter counts[kKnownOpsCount];
+ OpCounter sizes[kKnownOpsCount];
+ OpCounter sizesSmol[kKnownOpsCount];
+ for (int i = 0; i < kKnownOpsCount; ++i)
+ {
+ counts[i].first = (SpvOp)i;
+ counts[i].second = stats->opCounts[i];
+ sizes[i].first = (SpvOp)i;
+ sizes[i].second = stats->opSizes[i];
+ sizesSmol[i].first = (SpvOp)i;
+ sizesSmol[i].second = stats->smolOpSizes[i];
+ }
+ std::sort(counts, counts + kKnownOpsCount, CompareOpCounters);
+ std::sort(sizes, sizes + kKnownOpsCount, CompareOpCounters);
+ std::sort(sizesSmol, sizesSmol + kKnownOpsCount, CompareOpCounters);
+
+ printf("Stats for %i SPIR-V inputs, total size %i words (%.1fKB):\n", (int)stats->inputCount, (int)stats->totalSize, stats->totalSize * 4.0f / 1024.0f);
+ printf("Most occuring ops:\n");
+ for (int i = 0; i < 30; ++i)
+ {
+ SpvOp op = counts[i].first;
+ printf(" #%2i: %4i %-20s %4i (%4.1f%%)\n", i, op, kSpirvOpNames[op], (int)counts[i].second, (float)counts[i].second / (float)stats->totalOps * 100.0f);
+ }
+ printf("Largest total size of ops:\n");
+ for (int i = 0; i < 30; ++i)
+ {
+ SpvOp op = sizes[i].first;
+ printf(" #%2i: %-22s %6i (%4.1f%%) avg len %.1f\n",
+ i,
+ kSpirvOpNames[op],
+ (int)sizes[i].second*4,
+ (float)sizes[i].second / (float)stats->totalSize * 100.0f,
+ (float)sizes[i].second*4 / (float)stats->opCounts[op]
+ );
+ }
+ printf("SMOL varint encoding counts per byte length:\n");
+ printf(" B: %6s %6s %6s %6s\n", "Op", "Type", "Result", "Other");
+ for (int i = 1; i < 6; ++i)
+ {
+ printf(" %i: %6i %6i %6i %6i\n", i, (int)stats->varintCountsOp[i], (int)stats->varintCountsType[i], (int)stats->varintCountsRes[i], (int)stats->varintCountsOther[i]);
+ }
+ printf("Largest total size of ops in SMOL:\n");
+ for (int i = 0; i < 30; ++i)
+ {
+ SpvOp op = sizesSmol[i].first;
+ printf(" #%2i: %-22s %6i (%4.1f%%) avg len %.1f\n",
+ i,
+ kSpirvOpNames[op],
+ (int)sizesSmol[i].second,
+ (float)sizesSmol[i].second / (float)stats->totalSizeSmol * 100.0f,
+ (float)sizesSmol[i].second / (float)stats->opCounts[op]
+ );
+ }
+}
+
+
+// ------------------------------------------------------------------------------
+// This software is available under 2 licenses -- choose whichever you prefer.
+// ------------------------------------------------------------------------------
+// ALTERNATIVE A - MIT License
+// Copyright (c) 2016-2020 Aras Pranckevicius
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+// ------------------------------------------------------------------------------
+// ALTERNATIVE B - Public Domain (www.unlicense.org)
+// This is free and unencumbered software released into the public domain.
+// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+// software, either in source code form or as a compiled binary, for any purpose,
+// commercial or non-commercial, and by any means.
+// In jurisdictions that recognize copyright laws, the author or authors of this
+// software dedicate any and all copyright interest in the software to the public
+// domain. We make this dedication for the benefit of the public at large and to
+// the detriment of our heirs and successors. We intend this dedication to be an
+// overt act of relinquishment in perpetuity of all present and future rights to
+// this software under copyright law.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// ------------------------------------------------------------------------------
diff --git a/thirdparty/misc/smolv.h b/thirdparty/misc/smolv.h
new file mode 100644
index 0000000000..798ee4126f
--- /dev/null
+++ b/thirdparty/misc/smolv.h
@@ -0,0 +1,169 @@
+// smol-v - public domain - https://github.com/aras-p/smol-v
+// authored 2016-2020 by Aras Pranckevicius
+// no warranty implied; use at your own risk
+// See end of file for license information.
+//
+//
+// ### OVERVIEW:
+//
+// SMOL-V encodes Vulkan/Khronos SPIR-V format programs into a form that is smaller, and is more
+// compressible. Normally no changes to the programs are done; they decode
+// into exactly same program as what was encoded. Optionally, debug information
+// can be removed too.
+//
+// SPIR-V is a very verbose format, several times larger than same programs expressed in other
+// shader formats (e.g. DX11 bytecode, GLSL, DX9 bytecode etc.). The SSA-form with ever increasing
+// IDs is not very appreciated by regular data compressors either. SMOL-V does several things
+// to improve this:
+// - Many words, especially ones that most often have small values, are encoded using
+// "varint" scheme (1-5 bytes per word, with just one byte for values in 0..127 range).
+// See https://developers.google.com/protocol-buffers/docs/encoding
+// - Some IDs used in the program are delta-encoded, relative to previously seen IDs (e.g. Result
+// IDs). Often instructions reference things that were computed just before, so this results in
+// small deltas. These values are also encoded using "varint" scheme.
+// - Reordering instruction opcodes so that the most common ones are the smallest values, for smaller
+// varint encoding.
+// - Encoding several instructions in a more compact form, e.g. the "typical <=4 component swizzle"
+// shape of a VectorShuffle instruction, or sequences of MemberDecorate instructions.
+//
+// A somewhat similar utility is spirv-remap from glslang, see
+// https://github.com/KhronosGroup/glslang/blob/master/README-spirv-remap.txt
+//
+//
+// ### USAGE:
+//
+// Add source/smolv.h and source/smolv.cpp to your C++ project build.
+// Currently it might require C++11 or somesuch; I only tested with Visual Studio 2017/2019, Mac Xcode 11 and Gcc 5.4.
+//
+// smolv::Encode and smolv::Decode is the basic functionality.
+//
+// Other functions are for development/statistics purposes, to figure out frequencies and
+// distributions of the instructions.
+//
+// There's a test + compression benchmarking suite in testing/testmain.cpp; using that needs adding
+// other files under testing/external to the build too (3rd party code: glslang remapper, Zstd, LZ4).
+//
+//
+// ### LIMITATIONS / TODO:
+//
+// - SPIR-V where the words got stored in big-endian layout is not supported yet.
+// - The whole thing might not work on Big-Endian CPUs. It might, but I'm not 100% sure.
+// - Not much prevention is done against malformed/corrupted inputs, TODO.
+// - Out of memory cases are not handled. The code will either throw exception
+// or crash, depending on your compilation flags.
+
+#pragma once
+
+#include <stdint.h>
+#include <vector>
+#include <cstddef>
+
+namespace smolv
+{
+ typedef std::vector<uint8_t> ByteArray;
+
+ enum EncodeFlags
+ {
+ kEncodeFlagNone = 0,
+ kEncodeFlagStripDebugInfo = (1<<0), // Strip all optional SPIR-V instructions (debug names etc.)
+ };
+ enum DecodeFlags
+ {
+ kDecodeFlagNone = 0,
+ kDecodeFlagUse20160831AsZeroVersion = (1 << 0), // For "version zero" of SMOL-V encoding, use 2016 08 31 code path (this is what happens to be used by Unity 2017-2020)
+ };
+
+ // Preserve *some* OpName debug names.
+ // Return true to preserve, false to strip.
+ // This is really only used to implement a workaround for problems with some Vulkan drivers.
+ typedef bool(*StripOpNameFilterFunc)(const char* name);
+
+ // -------------------------------------------------------------------
+ // Encoding / Decoding
+
+ // Encode SPIR-V into SMOL-V.
+ //
+ // Resulting data is appended to outSmolv array (the array is not cleared).
+ //
+ // flags is bitset of EncodeFlags values.
+ //
+ // Returns false on malformed SPIR-V input; if that happens the output array might get
+ // partial/broken SMOL-V program.
+ bool Encode(const void* spirvData, size_t spirvSize, ByteArray& outSmolv, uint32_t flags = kEncodeFlagNone, StripOpNameFilterFunc stripFilter = 0);
+
+
+ // Decode SMOL-V into SPIR-V.
+ //
+ // Resulting data is written into the passed buffer. Get required buffer space with
+ // GetDecodeBufferSize; this is the size of decoded SPIR-V program.
+ //
+ // flags is bitset of DecodeFlags values.
+
+ // Decoding does no memory allocations.
+ //
+ // Returns false on malformed input; if that happens the output buffer might be only partially
+ // written to.
+ bool Decode(const void* smolvData, size_t smolvSize, void* spirvOutputBuffer, size_t spirvOutputBufferSize, uint32_t flags = kDecodeFlagNone);
+
+
+ // Given a SMOL-V program, get size of the decoded SPIR-V program.
+ // This is the buffer size that Decode expects.
+ //
+ // Returns zero on malformed input (just checks the header, not the full input).
+ size_t GetDecodedBufferSize(const void* smolvData, size_t smolvSize);
+
+
+ // -------------------------------------------------------------------
+ // Computing instruction statistics on SPIR-V/SMOL-V programs
+
+ struct Stats;
+
+ Stats* StatsCreate();
+ void StatsDelete(Stats* s);
+
+ bool StatsCalculate(Stats* stats, const void* spirvData, size_t spirvSize);
+ bool StatsCalculateSmol(Stats* stats, const void* smolvData, size_t smolvSize);
+ void StatsPrint(const Stats* stats);
+
+} // namespace smolv
+
+
+// ------------------------------------------------------------------------------
+// This software is available under 2 licenses -- choose whichever you prefer.
+// ------------------------------------------------------------------------------
+// ALTERNATIVE A - MIT License
+// Copyright (c) 2016-2020 Aras Pranckevicius
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+// ------------------------------------------------------------------------------
+// ALTERNATIVE B - Public Domain (www.unlicense.org)
+// This is free and unencumbered software released into the public domain.
+// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+// software, either in source code form or as a compiled binary, for any purpose,
+// commercial or non-commercial, and by any means.
+// In jurisdictions that recognize copyright laws, the author or authors of this
+// software dedicate any and all copyright interest in the software to the public
+// domain. We make this dedication for the benefit of the public at large and to
+// the detriment of our heirs and successors. We intend this dedication to be an
+// overt act of relinquishment in perpetuity of all present and future rights to
+// this software under copyright law.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// ------------------------------------------------------------------------------